summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Langley <agl@google.com>2015-01-22 14:27:53 -0800
committerAdam Langley <agl@google.com>2015-01-30 16:52:14 -0800
commitd9e397b599b13d642138480a28c14db7a136bf05 (patch)
tree34bab61dc4ce323b123ad4614dbc07e86ea2f9ef
downloadexternal_boringssl-d9e397b599b13d642138480a28c14db7a136bf05.zip
external_boringssl-d9e397b599b13d642138480a28c14db7a136bf05.tar.gz
external_boringssl-d9e397b599b13d642138480a28c14db7a136bf05.tar.bz2
Initial commit of BoringSSL for Android.
-rw-r--r--Android.mk102
-rw-r--r--BORINGSSL_REVISION1
-rw-r--r--MODULE_LICENSE_BSD_LIKE0
-rw-r--r--NOTICE127
-rw-r--r--android_compat_hacks.c75
l---------arm_arch.h1
-rw-r--r--crypto-sources.mk9
-rw-r--r--flavor.mk4
l---------include1
-rw-r--r--linux-aarch64/crypto/aes/aesv8-armx.S725
-rw-r--r--linux-aarch64/crypto/modes/ghashv8-armx.S115
-rw-r--r--linux-aarch64/crypto/sha/sha1-armv8.S1211
-rw-r--r--linux-aarch64/crypto/sha/sha256-armv8.S1141
-rw-r--r--linux-aarch64/crypto/sha/sha512-armv8.S1021
-rw-r--r--linux-arm/crypto/aes/aes-armv4.S1185
-rw-r--r--linux-arm/crypto/aes/aesv8-armx.S732
-rw-r--r--linux-arm/crypto/aes/bsaes-armv7.S2550
-rw-r--r--linux-arm/crypto/bn/armv4-mont.S575
-rw-r--r--linux-arm/crypto/modes/ghash-armv4.S532
-rw-r--r--linux-arm/crypto/modes/ghashv8-armx.S116
-rw-r--r--linux-arm/crypto/sha/sha1-armv4-large.S1455
-rw-r--r--linux-arm/crypto/sha/sha256-armv4.S2695
-rw-r--r--linux-arm/crypto/sha/sha512-armv4.S1775
-rw-r--r--linux-x86/crypto/aes/aes-586.S3257
-rw-r--r--linux-x86/crypto/aes/aesni-x86.S2218
-rw-r--r--linux-x86/crypto/aes/vpaes-x86.S676
-rw-r--r--linux-x86/crypto/bn/bn-586.S1393
-rw-r--r--linux-x86/crypto/bn/co-586.S1260
-rw-r--r--linux-x86/crypto/bn/x86-mont.S340
-rw-r--r--linux-x86/crypto/cpu-x86-asm.S314
-rw-r--r--linux-x86/crypto/md5/md5-586.S682
-rw-r--r--linux-x86/crypto/modes/ghash-x86.S1274
-rw-r--r--linux-x86/crypto/rc4/rc4-586.S385
-rw-r--r--linux-x86/crypto/sha/sha1-586.S1383
-rw-r--r--linux-x86/crypto/sha/sha256-586.S3350
-rw-r--r--linux-x86/crypto/sha/sha512-586.S568
-rw-r--r--linux-x86_64/crypto/aes/aes-x86_64.S2535
-rw-r--r--linux-x86_64/crypto/aes/aesni-x86_64.S3178
-rw-r--r--linux-x86_64/crypto/aes/bsaes-x86_64.S2504
-rw-r--r--linux-x86_64/crypto/aes/vpaes-x86_64.S834
-rw-r--r--linux-x86_64/crypto/bn/modexp512-x86_64.S1776
-rw-r--r--linux-x86_64/crypto/bn/rsaz-avx2.S34
-rw-r--r--linux-x86_64/crypto/bn/rsaz-x86_64.S1126
-rw-r--r--linux-x86_64/crypto/bn/x86_64-mont.S726
-rw-r--r--linux-x86_64/crypto/bn/x86_64-mont5.S1822
-rw-r--r--linux-x86_64/crypto/cpu-x86_64-asm.S147
-rw-r--r--linux-x86_64/crypto/md5/md5-x86_64.S671
-rw-r--r--linux-x86_64/crypto/modes/aesni-gcm-x86_64.S19
-rw-r--r--linux-x86_64/crypto/modes/ghash-x86_64.S1328
-rw-r--r--linux-x86_64/crypto/rc4/rc4-md5-x86_64.S1262
-rw-r--r--linux-x86_64/crypto/rc4/rc4-x86_64.S622
-rw-r--r--linux-x86_64/crypto/sha/sha1-x86_64.S2425
-rw-r--r--linux-x86_64/crypto/sha/sha256-x86_64.S2843
-rw-r--r--linux-x86_64/crypto/sha/sha512-x86_64.S1786
-rw-r--r--mac-x86/crypto/aes/aes-586.S3221
-rw-r--r--mac-x86/crypto/aes/aesni-x86.S2178
-rw-r--r--mac-x86/crypto/aes/vpaes-x86.S650
-rw-r--r--mac-x86/crypto/bn/bn-586.S1379
-rw-r--r--mac-x86/crypto/bn/co-586.S1252
-rw-r--r--mac-x86/crypto/bn/x86-mont.S338
-rw-r--r--mac-x86/crypto/cpu-x86-asm.S301
-rw-r--r--mac-x86/crypto/md5/md5-586.S680
-rw-r--r--mac-x86/crypto/modes/ghash-x86.S1260
-rw-r--r--mac-x86/crypto/rc4/rc4-586.S383
-rw-r--r--mac-x86/crypto/sha/sha1-586.S1381
-rw-r--r--mac-x86/crypto/sha/sha256-586.S3348
-rw-r--r--mac-x86/crypto/sha/sha512-586.S566
-rw-r--r--mac-x86_64/crypto/aes/aes-x86_64.S2535
-rw-r--r--mac-x86_64/crypto/aes/aesni-x86_64.S3178
-rw-r--r--mac-x86_64/crypto/aes/bsaes-x86_64.S2504
-rw-r--r--mac-x86_64/crypto/aes/vpaes-x86_64.S834
-rw-r--r--mac-x86_64/crypto/bn/modexp512-x86_64.S1776
-rw-r--r--mac-x86_64/crypto/bn/rsaz-avx2.S34
-rw-r--r--mac-x86_64/crypto/bn/rsaz-x86_64.S1126
-rw-r--r--mac-x86_64/crypto/bn/x86_64-mont.S726
-rw-r--r--mac-x86_64/crypto/bn/x86_64-mont5.S1822
-rw-r--r--mac-x86_64/crypto/cpu-x86_64-asm.S147
-rw-r--r--mac-x86_64/crypto/md5/md5-x86_64.S671
-rw-r--r--mac-x86_64/crypto/modes/aesni-gcm-x86_64.S19
-rw-r--r--mac-x86_64/crypto/modes/ghash-x86_64.S1328
-rw-r--r--mac-x86_64/crypto/rc4/rc4-md5-x86_64.S1262
-rw-r--r--mac-x86_64/crypto/rc4/rc4-x86_64.S622
-rw-r--r--mac-x86_64/crypto/sha/sha1-x86_64.S2425
-rw-r--r--mac-x86_64/crypto/sha/sha256-x86_64.S2843
-rw-r--r--mac-x86_64/crypto/sha/sha512-x86_64.S1786
-rw-r--r--sources.mk430
-rw-r--r--src/.clang-format4
-rw-r--r--src/.gitignore5
-rw-r--r--src/BUILDING81
-rw-r--r--src/CMakeLists.txt100
-rw-r--r--src/codereview.settings4
-rw-r--r--src/crypto/CMakeLists.txt198
-rw-r--r--src/crypto/aes/CMakeLists.txt62
-rw-r--r--src/crypto/aes/aes.c1077
-rwxr-xr-xsrc/crypto/aes/asm/aes-586.pl2987
-rw-r--r--src/crypto/aes/asm/aes-armv4.pl1224
-rw-r--r--src/crypto/aes/asm/aes-x86_64.pl2805
-rw-r--r--src/crypto/aes/asm/aesni-x86.pl2232
-rw-r--r--src/crypto/aes/asm/aesni-x86_64.pl3555
-rw-r--r--src/crypto/aes/asm/aesv8-armx.pl962
-rw-r--r--src/crypto/aes/asm/bsaes-armv7.pl2477
-rw-r--r--src/crypto/aes/asm/bsaes-x86_64.pl3102
-rw-r--r--src/crypto/aes/asm/vpaes-x86.pl903
-rw-r--r--src/crypto/aes/asm/vpaes-x86_64.pl1207
-rw-r--r--src/crypto/aes/internal.h87
-rw-r--r--src/crypto/aes/mode_wrappers.c108
-rw-r--r--src/crypto/arm_arch.h136
-rw-r--r--src/crypto/asn1/CMakeLists.txt46
-rw-r--r--src/crypto/asn1/a_bitstr.c258
-rw-r--r--src/crypto/asn1/a_bool.c112
-rw-r--r--src/crypto/asn1/a_bytes.c317
-rw-r--r--src/crypto/asn1/a_d2i_fp.c286
-rw-r--r--src/crypto/asn1/a_dup.c103
-rw-r--r--src/crypto/asn1/a_enum.c183
-rw-r--r--src/crypto/asn1/a_gentm.c254
-rw-r--r--src/crypto/asn1/a_i2d_fp.c154
-rw-r--r--src/crypto/asn1/a_int.c456
-rw-r--r--src/crypto/asn1/a_mbstr.c390
-rw-r--r--src/crypto/asn1/a_object.c412
-rw-r--r--src/crypto/asn1/a_octet.c70
-rw-r--r--src/crypto/asn1/a_print.c119
-rw-r--r--src/crypto/asn1/a_strnid.c286
-rw-r--r--src/crypto/asn1/a_time.c220
-rw-r--r--src/crypto/asn1/a_type.c157
-rw-r--r--src/crypto/asn1/a_utctm.c341
-rw-r--r--src/crypto/asn1/a_utf8.c210
-rw-r--r--src/crypto/asn1/asn1_error.c203
-rw-r--r--src/crypto/asn1/asn1_lib.c488
-rw-r--r--src/crypto/asn1/asn1_locl.h73
-rw-r--r--src/crypto/asn1/asn1_par.c435
-rw-r--r--src/crypto/asn1/asn_pack.c104
-rw-r--r--src/crypto/asn1/bio_asn1.c496
-rw-r--r--src/crypto/asn1/bio_ndef.c248
-rw-r--r--src/crypto/asn1/charmap.pl135
-rw-r--r--src/crypto/asn1/f_enum.c206
-rw-r--r--src/crypto/asn1/f_int.c210
-rw-r--r--src/crypto/asn1/f_string.c204
-rw-r--r--src/crypto/asn1/t_bitst.c102
-rw-r--r--src/crypto/asn1/t_pkey.c112
-rw-r--r--src/crypto/asn1/tasn_dec.c1314
-rw-r--r--src/crypto/asn1/tasn_enc.c695
-rw-r--r--src/crypto/asn1/tasn_fre.c264
-rw-r--r--src/crypto/asn1/tasn_new.c396
-rw-r--r--src/crypto/asn1/tasn_prn.c639
-rw-r--r--src/crypto/asn1/tasn_typ.c152
-rw-r--r--src/crypto/asn1/tasn_utl.c260
-rw-r--r--src/crypto/asn1/x_bignum.c142
-rw-r--r--src/crypto/asn1/x_long.c182
-rw-r--r--src/crypto/base64/CMakeLists.txt17
-rw-r--r--src/crypto/base64/base64.c474
-rw-r--r--src/crypto/base64/base64_test.c133
-rw-r--r--src/crypto/bio/CMakeLists.txt31
-rw-r--r--src/crypto/bio/bio.c477
-rw-r--r--src/crypto/bio/bio_error.c59
-rw-r--r--src/crypto/bio/bio_mem.c327
-rw-r--r--src/crypto/bio/bio_test.c362
-rw-r--r--src/crypto/bio/buffer.c499
-rw-r--r--src/crypto/bio/connect.c541
-rw-r--r--src/crypto/bio/fd.c270
-rw-r--r--src/crypto/bio/file.c350
-rw-r--r--src/crypto/bio/hexdump.c192
-rw-r--r--src/crypto/bio/internal.h108
-rw-r--r--src/crypto/bio/pair.c821
-rw-r--r--src/crypto/bio/printf.c115
-rw-r--r--src/crypto/bio/socket.c191
-rw-r--r--src/crypto/bio/socket_helper.c112
-rw-r--r--src/crypto/bn/CMakeLists.txt76
-rw-r--r--src/crypto/bn/add.c394
-rw-r--r--src/crypto/bn/asm/armv4-mont.pl670
-rw-r--r--src/crypto/bn/asm/bn-586.pl774
-rw-r--r--src/crypto/bn/asm/co-586.pl287
-rw-r--r--src/crypto/bn/asm/rsaz-avx2.pl1898
-rw-r--r--src/crypto/bn/asm/rsaz-x86_64.pl2144
-rw-r--r--src/crypto/bn/asm/x86-mont.pl592
-rw-r--r--src/crypto/bn/asm/x86_64-gcc.c579
-rw-r--r--src/crypto/bn/asm/x86_64-mont.pl1401
-rw-r--r--src/crypto/bn/asm/x86_64-mont5.pl3499
-rw-r--r--src/crypto/bn/bn.c338
-rw-r--r--src/crypto/bn/bn_error.c63
-rw-r--r--src/crypto/bn/bn_test.c1471
-rw-r--r--src/crypto/bn/cmp.c200
-rw-r--r--src/crypto/bn/convert.c504
-rw-r--r--src/crypto/bn/ctx.c315
-rw-r--r--src/crypto/bn/div.c620
-rw-r--r--src/crypto/bn/exponentiation.c1535
-rw-r--r--src/crypto/bn/gcd.c704
-rw-r--r--src/crypto/bn/generic.c1120
-rw-r--r--src/crypto/bn/internal.h297
-rw-r--r--src/crypto/bn/kronecker.c175
-rw-r--r--src/crypto/bn/montgomery.c571
-rw-r--r--src/crypto/bn/mul.c886
-rw-r--r--src/crypto/bn/prime.c838
-rw-r--r--src/crypto/bn/random.c328
-rw-r--r--src/crypto/bn/rsaz_exp.c326
-rw-r--r--src/crypto/bn/rsaz_exp.h44
-rw-r--r--src/crypto/bn/shift.c287
-rw-r--r--src/crypto/bn/sqrt.c505
-rw-r--r--src/crypto/buf/CMakeLists.txt10
-rw-r--r--src/crypto/buf/buf.c235
-rw-r--r--src/crypto/buf/buf_error.c25
-rw-r--r--src/crypto/bytestring/CMakeLists.txt19
-rw-r--r--src/crypto/bytestring/ber.c219
-rw-r--r--src/crypto/bytestring/bytestring_test.c655
-rw-r--r--src/crypto/bytestring/cbb.c375
-rw-r--r--src/crypto/bytestring/cbs.c388
-rw-r--r--src/crypto/bytestring/internal.h46
-rw-r--r--src/crypto/chacha/CMakeLists.txt20
-rw-r--r--src/crypto/chacha/chacha_generic.c143
-rw-r--r--src/crypto/chacha/chacha_vec.c340
-rw-r--r--src/crypto/chacha/chacha_vec_arm.S1426
-rw-r--r--src/crypto/cipher/CMakeLists.txt38
-rw-r--r--src/crypto/cipher/aead.c119
-rw-r--r--src/crypto/cipher/aead_test.c387
-rw-r--r--src/crypto/cipher/cipher.c654
-rw-r--r--src/crypto/cipher/cipher_error.c78
-rw-r--r--src/crypto/cipher/cipher_test.c413
-rw-r--r--src/crypto/cipher/derive_key.c154
-rw-r--r--src/crypto/cipher/e_aes.c1364
-rw-r--r--src/crypto/cipher/e_chacha20poly1305.c218
-rw-r--r--src/crypto/cipher/e_des.c157
-rw-r--r--src/crypto/cipher/e_null.c85
-rw-r--r--src/crypto/cipher/e_rc2.c420
-rw-r--r--src/crypto/cipher/e_rc4.c384
-rw-r--r--src/crypto/cipher/e_ssl3.c437
-rw-r--r--src/crypto/cipher/e_tls.c611
-rw-r--r--src/crypto/cipher/internal.h193
-rw-r--r--src/crypto/cipher/test/aes_128_cbc_sha1_ssl3_tests.txt840
-rw-r--r--src/crypto/cipher/test/aes_128_cbc_sha1_tls_implicit_iv_tests.txt840
-rw-r--r--src/crypto/cipher/test/aes_128_cbc_sha1_tls_tests.txt840
-rw-r--r--src/crypto/cipher/test/aes_128_cbc_sha256_tls_tests.txt840
-rw-r--r--src/crypto/cipher/test/aes_128_gcm_tests.txt420
-rw-r--r--src/crypto/cipher/test/aes_128_key_wrap_tests.txt9
-rw-r--r--src/crypto/cipher/test/aes_256_cbc_sha1_ssl3_tests.txt840
-rw-r--r--src/crypto/cipher/test/aes_256_cbc_sha1_tls_implicit_iv_tests.txt840
-rw-r--r--src/crypto/cipher/test/aes_256_cbc_sha1_tls_tests.txt840
-rw-r--r--src/crypto/cipher/test/aes_256_cbc_sha256_tls_tests.txt840
-rw-r--r--src/crypto/cipher/test/aes_256_cbc_sha384_tls_tests.txt840
-rw-r--r--src/crypto/cipher/test/aes_256_gcm_tests.txt420
-rw-r--r--src/crypto/cipher/test/aes_256_key_wrap_tests.txt23
-rw-r--r--src/crypto/cipher/test/chacha20_poly1305_tests.txt524
-rw-r--r--src/crypto/cipher/test/cipher_test.txt81
-rw-r--r--src/crypto/cipher/test/des_ede3_cbc_sha1_ssl3_tests.txt840
-rw-r--r--src/crypto/cipher/test/des_ede3_cbc_sha1_tls_implicit_iv_tests.txt840
-rw-r--r--src/crypto/cipher/test/des_ede3_cbc_sha1_tls_tests.txt840
-rwxr-xr-xsrc/crypto/cipher/test/make_all_legacy_aead_tests.sh24
-rw-r--r--src/crypto/cipher/test/make_legacy_aead_tests.go357
-rw-r--r--src/crypto/cipher/test/rc4_md5_ssl3_tests.txt808
-rw-r--r--src/crypto/cipher/test/rc4_md5_tls_tests.txt808
-rw-r--r--src/crypto/cipher/test/rc4_sha1_ssl3_tests.txt808
-rw-r--r--src/crypto/cipher/test/rc4_sha1_tls_tests.txt808
-rw-r--r--src/crypto/cipher/tls_cbc.c495
-rw-r--r--src/crypto/conf/CMakeLists.txt10
-rw-r--r--src/crypto/conf/conf.c746
-rw-r--r--src/crypto/conf/conf_def.h127
-rw-r--r--src/crypto/conf/conf_error.c31
-rw-r--r--src/crypto/constant_time_test.c307
-rw-r--r--src/crypto/cpu-arm.c112
-rw-r--r--src/crypto/cpu-intel.c127
-rw-r--r--src/crypto/cpu-x86-asm.pl338
-rw-r--r--src/crypto/cpu-x86_64-asm.pl167
-rw-r--r--src/crypto/crypto.c104
-rw-r--r--src/crypto/crypto_error.c25
-rw-r--r--src/crypto/crypto_error.h18
-rw-r--r--src/crypto/des/CMakeLists.txt9
-rw-r--r--src/crypto/des/des.c710
-rw-r--r--src/crypto/des/internal.h229
-rw-r--r--src/crypto/dh/CMakeLists.txt22
-rw-r--r--src/crypto/dh/check.c180
-rw-r--r--src/crypto/dh/dh.c243
-rw-r--r--src/crypto/dh/dh_asn1.c84
-rw-r--r--src/crypto/dh/dh_error.c29
-rw-r--r--src/crypto/dh/dh_impl.c324
-rw-r--r--src/crypto/dh/dh_test.c502
-rw-r--r--src/crypto/dh/internal.h80
-rw-r--r--src/crypto/dh/params.c316
-rw-r--r--src/crypto/digest/CMakeLists.txt19
-rw-r--r--src/crypto/digest/digest.c273
-rw-r--r--src/crypto/digest/digest_error.c24
-rw-r--r--src/crypto/digest/digest_test.c244
-rw-r--r--src/crypto/digest/digests.c274
-rw-r--r--src/crypto/digest/internal.h117
-rw-r--r--src/crypto/digest/md32_common.h370
-rw-r--r--src/crypto/directory.h66
-rw-r--r--src/crypto/directory_posix.c107
-rw-r--r--src/crypto/directory_win.c141
-rw-r--r--src/crypto/dsa/CMakeLists.txt20
-rw-r--r--src/crypto/dsa/dsa.c354
-rw-r--r--src/crypto/dsa/dsa_asn1.c150
-rw-r--r--src/crypto/dsa/dsa_error.c30
-rw-r--r--src/crypto/dsa/dsa_impl.c762
-rw-r--r--src/crypto/dsa/dsa_test.c338
-rw-r--r--src/crypto/dsa/internal.h78
-rw-r--r--src/crypto/ec/CMakeLists.txt31
-rw-r--r--src/crypto/ec/ec.c856
-rw-r--r--src/crypto/ec/ec_asn1.c599
-rw-r--r--src/crypto/ec/ec_error.c107
-rw-r--r--src/crypto/ec/ec_key.c516
-rw-r--r--src/crypto/ec/ec_montgomery.c296
-rw-r--r--src/crypto/ec/ec_test.c124
-rw-r--r--src/crypto/ec/example_mul.c133
-rw-r--r--src/crypto/ec/internal.h380
-rw-r--r--src/crypto/ec/oct.c476
-rw-r--r--src/crypto/ec/simple.c1362
-rw-r--r--src/crypto/ec/wnaf.c844
-rw-r--r--src/crypto/ecdh/CMakeLists.txt10
-rw-r--r--src/crypto/ecdh/ecdh.c157
-rw-r--r--src/crypto/ecdh/ecdh_error.c25
-rw-r--r--src/crypto/ecdsa/CMakeLists.txt20
-rw-r--r--src/crypto/ecdsa/ecdsa.c496
-rw-r--r--src/crypto/ecdsa/ecdsa_asn1.c116
-rw-r--r--src/crypto/ecdsa/ecdsa_error.c32
-rw-r--r--src/crypto/ecdsa/ecdsa_test.c328
-rw-r--r--src/crypto/engine/CMakeLists.txt10
-rw-r--r--src/crypto/engine/engine.c138
-rw-r--r--src/crypto/engine/engine_error.c22
-rw-r--r--src/crypto/err/CMakeLists.txt18
-rw-r--r--src/crypto/err/err.c809
-rw-r--r--src/crypto/err/err_impl.c323
-rw-r--r--src/crypto/err/err_test.c140
-rw-r--r--src/crypto/evp/CMakeLists.txt38
-rw-r--r--src/crypto/evp/algorithm.c159
-rw-r--r--src/crypto/evp/asn1.c167
-rw-r--r--src/crypto/evp/digestsign.c205
-rw-r--r--src/crypto/evp/evp.c440
-rw-r--r--src/crypto/evp/evp_ctx.c512
-rw-r--r--src/crypto/evp/evp_error.c131
-rw-r--r--src/crypto/evp/evp_test.c639
-rw-r--r--src/crypto/evp/internal.h255
-rw-r--r--src/crypto/evp/p_ec.c303
-rw-r--r--src/crypto/evp/p_ec_asn1.c574
-rw-r--r--src/crypto/evp/p_hmac.c222
-rw-r--r--src/crypto/evp/p_hmac_asn1.c89
-rw-r--r--src/crypto/evp/p_rsa.c598
-rw-r--r--src/crypto/evp/p_rsa_asn1.c705
-rw-r--r--src/crypto/evp/pbkdf.c135
-rw-r--r--src/crypto/evp/sign.c151
-rw-r--r--src/crypto/ex_data.c227
-rw-r--r--src/crypto/ex_data_impl.c401
-rw-r--r--src/crypto/header_removed.h17
-rw-r--r--src/crypto/hkdf/CMakeLists.txt18
-rw-r--r--src/crypto/hkdf/hkdf.c89
-rw-r--r--src/crypto/hkdf/hkdf_error.c23
-rw-r--r--src/crypto/hkdf/hkdf_test.c240
-rw-r--r--src/crypto/hmac/CMakeLists.txt18
-rw-r--r--src/crypto/hmac/hmac.c225
-rw-r--r--src/crypto/hmac/hmac_test.c223
-rw-r--r--src/crypto/internal.h302
-rw-r--r--src/crypto/lhash/CMakeLists.txt17
-rw-r--r--src/crypto/lhash/lhash.c345
-rw-r--r--src/crypto/lhash/lhash_test.c196
-rw-r--r--src/crypto/lhash/make_macros.sh64
-rw-r--r--src/crypto/md4/CMakeLists.txt9
-rw-r--r--src/crypto/md4/md4.c224
-rw-r--r--src/crypto/md5/CMakeLists.txt30
-rw-r--r--src/crypto/md5/asm/md5-586.pl307
-rw-r--r--src/crypto/md5/asm/md5-x86_64.pl370
-rw-r--r--src/crypto/md5/md5.c274
-rw-r--r--src/crypto/mem.c199
-rw-r--r--src/crypto/modes/CMakeLists.txt63
-rw-r--r--src/crypto/modes/asm/aesni-gcm-x86_64.pl1057
-rw-r--r--src/crypto/modes/asm/ghash-armv4.pl501
-rw-r--r--src/crypto/modes/asm/ghash-x86.pl1393
-rw-r--r--src/crypto/modes/asm/ghash-x86_64.pl1753
-rw-r--r--src/crypto/modes/asm/ghashv8-armx.pl241
-rw-r--r--src/crypto/modes/cbc.c203
-rw-r--r--src/crypto/modes/cfb.c230
-rw-r--r--src/crypto/modes/ctr.c219
-rw-r--r--src/crypto/modes/gcm.c1245
-rw-r--r--src/crypto/modes/gcm_test.c435
-rw-r--r--src/crypto/modes/internal.h199
-rw-r--r--src/crypto/modes/ofb.c107
-rw-r--r--src/crypto/obj/CMakeLists.txt11
-rw-r--r--src/crypto/obj/README37
-rw-r--r--src/crypto/obj/obj.c673
-rw-r--r--src/crypto/obj/obj_dat.h5261
-rw-r--r--src/crypto/obj/obj_dat.pl309
-rw-r--r--src/crypto/obj/obj_error.c26
-rw-r--r--src/crypto/obj/obj_mac.num947
-rw-r--r--src/crypto/obj/obj_xref.c124
-rw-r--r--src/crypto/obj/obj_xref.h96
-rw-r--r--src/crypto/obj/obj_xref.pl118
-rw-r--r--src/crypto/obj/obj_xref.txt58
-rw-r--r--src/crypto/obj/objects.pl235
-rw-r--r--src/crypto/obj/objects.txt1334
-rw-r--r--src/crypto/pem/CMakeLists.txt17
-rw-r--r--src/crypto/pem/pem_all.c281
-rw-r--r--src/crypto/pem/pem_error.c73
-rw-r--r--src/crypto/pem/pem_info.c404
-rw-r--r--src/crypto/pem/pem_lib.c812
-rw-r--r--src/crypto/pem/pem_oth.c89
-rw-r--r--src/crypto/pem/pem_pk8.c243
-rw-r--r--src/crypto/pem/pem_pkey.c312
-rw-r--r--src/crypto/pem/pem_x509.c65
-rw-r--r--src/crypto/pem/pem_xaux.c66
-rw-r--r--src/crypto/perlasm/cbc.pl349
-rwxr-xr-xsrc/crypto/perlasm/ppc-xlate.pl167
-rw-r--r--src/crypto/perlasm/readme124
-rw-r--r--src/crypto/perlasm/sparcv9_modes.pl1680
-rwxr-xr-xsrc/crypto/perlasm/x86_64-xlate.pl1165
-rw-r--r--src/crypto/perlasm/x86asm.pl292
-rw-r--r--src/crypto/perlasm/x86gas.pl263
-rw-r--r--src/crypto/perlasm/x86masm.pl203
-rw-r--r--src/crypto/perlasm/x86nasm.pl187
-rw-r--r--src/crypto/pkcs8/CMakeLists.txt21
-rw-r--r--src/crypto/pkcs8/internal.h74
-rw-r--r--src/crypto/pkcs8/p5_pbe.c150
-rw-r--r--src/crypto/pkcs8/p5_pbev2.c303
-rw-r--r--src/crypto/pkcs8/p8_pkey.c85
-rw-r--r--src/crypto/pkcs8/pkcs12_test.c763
-rw-r--r--src/crypto/pkcs8/pkcs8.c1155
-rw-r--r--src/crypto/pkcs8/pkcs8_error.c68
-rw-r--r--src/crypto/poly1305/CMakeLists.txt21
-rw-r--r--src/crypto/poly1305/poly1305.c323
-rw-r--r--src/crypto/poly1305/poly1305_arm.c290
-rw-r--r--src/crypto/poly1305/poly1305_arm_asm.S2015
-rw-r--r--src/crypto/poly1305/poly1305_vec.c887
-rw-r--r--src/crypto/rand/CMakeLists.txt11
-rw-r--r--src/crypto/rand/rand.c28
-rw-r--r--src/crypto/rand/urandom.c241
-rw-r--r--src/crypto/rand/windows.c54
-rw-r--r--src/crypto/rc4/CMakeLists.txt31
-rw-r--r--src/crypto/rc4/asm/rc4-586.pl414
-rw-r--r--src/crypto/rc4/asm/rc4-md5-x86_64.pl632
-rw-r--r--src/crypto/rc4/asm/rc4-x86_64.pl679
-rw-r--r--src/crypto/rc4/rc4.c371
-rw-r--r--src/crypto/rsa/CMakeLists.txt22
-rw-r--r--src/crypto/rsa/blinding.c471
-rw-r--r--src/crypto/rsa/internal.h150
-rw-r--r--src/crypto/rsa/padding.c779
-rw-r--r--src/crypto/rsa/rsa.c761
-rw-r--r--src/crypto/rsa/rsa_asn1.c125
-rw-r--r--src/crypto/rsa/rsa_error.c95
-rw-r--r--src/crypto/rsa/rsa_impl.c960
-rw-r--r--src/crypto/rsa/rsa_test.c508
-rw-r--r--src/crypto/sha/CMakeLists.txt66
-rw-r--r--src/crypto/sha/asm/sha1-586.pl1476
-rw-r--r--src/crypto/sha/asm/sha1-armv4-large.pl683
-rw-r--r--src/crypto/sha/asm/sha1-armv8.pl334
-rw-r--r--src/crypto/sha/asm/sha1-x86_64.pl2067
-rw-r--r--src/crypto/sha/asm/sha256-586.pl1281
-rw-r--r--src/crypto/sha/asm/sha256-armv4.pl661
-rw-r--r--src/crypto/sha/asm/sha512-586.pl911
-rw-r--r--src/crypto/sha/asm/sha512-armv4.pl609
-rw-r--r--src/crypto/sha/asm/sha512-armv8.pl419
-rw-r--r--src/crypto/sha/asm/sha512-x86_64.pl2396
-rw-r--r--src/crypto/sha/sha1.c380
-rw-r--r--src/crypto/sha/sha256.c366
-rw-r--r--src/crypto/sha/sha512.c593
-rw-r--r--src/crypto/stack/CMakeLists.txt9
-rw-r--r--src/crypto/stack/make_macros.sh112
-rw-r--r--src/crypto/stack/stack.c362
-rw-r--r--src/crypto/thread.c203
-rw-r--r--src/crypto/time_support.c200
-rw-r--r--src/crypto/x509/CMakeLists.txt65
-rw-r--r--src/crypto/x509/a_digest.c97
-rw-r--r--src/crypto/x509/a_sign.c136
-rw-r--r--src/crypto/x509/a_strex.c564
-rw-r--r--src/crypto/x509/a_verify.c133
-rw-r--r--src/crypto/x509/asn1_gen.c862
-rw-r--r--src/crypto/x509/by_dir.c479
-rw-r--r--src/crypto/x509/by_file.c292
-rw-r--r--src/crypto/x509/charmap.h15
-rw-r--r--src/crypto/x509/i2d_pr.c83
-rw-r--r--src/crypto/x509/pkcs7.c154
-rw-r--r--src/crypto/x509/pkcs7_test.c409
-rw-r--r--src/crypto/x509/t_crl.c129
-rw-r--r--src/crypto/x509/t_x509.c500
-rw-r--r--src/crypto/x509/t_x509a.c109
-rw-r--r--src/crypto/x509/vpm_int.h70
-rw-r--r--src/crypto/x509/x509.c152
-rw-r--r--src/crypto/x509/x509_att.c353
-rw-r--r--src/crypto/x509/x509_cmp.c490
-rw-r--r--src/crypto/x509/x509_d2.c105
-rw-r--r--src/crypto/x509/x509_def.c88
-rw-r--r--src/crypto/x509/x509_error.c125
-rw-r--r--src/crypto/x509/x509_ext.c206
-rw-r--r--src/crypto/x509/x509_lu.c740
-rw-r--r--src/crypto/x509/x509_obj.c191
-rw-r--r--src/crypto/x509/x509_r2x.c113
-rw-r--r--src/crypto/x509/x509_req.c313
-rw-r--r--src/crypto/x509/x509_set.c154
-rw-r--r--src/crypto/x509/x509_trs.c304
-rw-r--r--src/crypto/x509/x509_txt.c209
-rw-r--r--src/crypto/x509/x509_v3.c271
-rw-r--r--src/crypto/x509/x509_vfy.c2447
-rw-r--r--src/crypto/x509/x509_vpm.c588
-rw-r--r--src/crypto/x509/x509cset.c165
-rw-r--r--src/crypto/x509/x509name.c381
-rw-r--r--src/crypto/x509/x509rset.c80
-rw-r--r--src/crypto/x509/x509spki.c135
-rw-r--r--src/crypto/x509/x509type.c128
-rw-r--r--src/crypto/x509/x_algor.c154
-rw-r--r--src/crypto/x509/x_all.c544
-rw-r--r--src/crypto/x509/x_attrib.c117
-rw-r--r--src/crypto/x509/x_crl.c545
-rw-r--r--src/crypto/x509/x_exten.c75
-rw-r--r--src/crypto/x509/x_info.c110
-rw-r--r--src/crypto/x509/x_name.c533
-rw-r--r--src/crypto/x509/x_pkey.c105
-rw-r--r--src/crypto/x509/x_pubkey.c373
-rw-r--r--src/crypto/x509/x_req.c112
-rw-r--r--src/crypto/x509/x_sig.c69
-rw-r--r--src/crypto/x509/x_spki.c78
-rw-r--r--src/crypto/x509/x_val.c69
-rw-r--r--src/crypto/x509/x_x509.c209
-rw-r--r--src/crypto/x509/x_x509a.c177
-rw-r--r--src/crypto/x509v3/CMakeLists.txt60
-rw-r--r--src/crypto/x509v3/ext_dat.h129
-rw-r--r--src/crypto/x509v3/pcy_cache.c286
-rw-r--r--src/crypto/x509v3/pcy_data.c137
-rw-r--r--src/crypto/x509v3/pcy_int.h212
-rw-r--r--src/crypto/x509v3/pcy_lib.c165
-rw-r--r--src/crypto/x509v3/pcy_map.c133
-rw-r--r--src/crypto/x509v3/pcy_node.c197
-rw-r--r--src/crypto/x509v3/pcy_tree.c876
-rw-r--r--src/crypto/x509v3/tabtest.c94
-rw-r--r--src/crypto/x509v3/v3_akey.c212
-rw-r--r--src/crypto/x509v3/v3_akeya.c71
-rw-r--r--src/crypto/x509v3/v3_alt.c618
-rw-r--r--src/crypto/x509v3/v3_bcons.c126
-rw-r--r--src/crypto/x509v3/v3_bitst.c141
-rw-r--r--src/crypto/x509v3/v3_conf.c529
-rw-r--r--src/crypto/x509v3/v3_cpols.c461
-rw-r--r--src/crypto/x509v3/v3_crld.c616
-rw-r--r--src/crypto/x509v3/v3_enum.c98
-rw-r--r--src/crypto/x509v3/v3_extku.c145
-rw-r--r--src/crypto/x509v3/v3_genn.c252
-rw-r--r--src/crypto/x509v3/v3_ia5.c117
-rw-r--r--src/crypto/x509v3/v3_info.c200
-rw-r--r--src/crypto/x509v3/v3_int.c87
-rw-r--r--src/crypto/x509v3/v3_lib.c335
-rw-r--r--src/crypto/x509v3/v3_ncons.c510
-rw-r--r--src/crypto/x509v3/v3_pci.c334
-rw-r--r--src/crypto/x509v3/v3_pcia.c56
-rw-r--r--src/crypto/x509v3/v3_pcons.c142
-rw-r--r--src/crypto/x509v3/v3_pku.c109
-rw-r--r--src/crypto/x509v3/v3_pmaps.c156
-rw-r--r--src/crypto/x509v3/v3_prn.c207
-rw-r--r--src/crypto/x509v3/v3_purp.c786
-rw-r--r--src/crypto/x509v3/v3_skey.c148
-rw-r--r--src/crypto/x509v3/v3_sxnet.c266
-rw-r--r--src/crypto/x509v3/v3_utl.c1295
-rw-r--r--src/crypto/x509v3/v3nametest.c423
-rw-r--r--src/crypto/x509v3/x509v3_error.c147
l---------src/doc/doc.css1
-rw-r--r--src/include/openssl/aead.h277
-rw-r--r--src/include/openssl/aes.h146
-rw-r--r--src/include/openssl/asn1.h1264
-rw-r--r--src/include/openssl/asn1_mac.h578
-rw-r--r--src/include/openssl/asn1t.h907
-rw-r--r--src/include/openssl/base.h219
-rw-r--r--src/include/openssl/base64.h179
-rw-r--r--src/include/openssl/bio.h896
-rw-r--r--src/include/openssl/bn.h861
-rw-r--r--src/include/openssl/buf.h123
-rw-r--r--src/include/openssl/bytestring.h325
-rw-r--r--src/include/openssl/chacha.h37
-rw-r--r--src/include/openssl/cipher.h560
-rw-r--r--src/include/openssl/conf.h144
-rw-r--r--src/include/openssl/cpu.h122
-rw-r--r--src/include/openssl/crypto.h45
-rw-r--r--src/include/openssl/des.h126
-rw-r--r--src/include/openssl/dh.h263
-rw-r--r--src/include/openssl/digest.h282
-rw-r--r--src/include/openssl/dsa.h377
-rw-r--r--src/include/openssl/dtls1.h255
-rw-r--r--src/include/openssl/ec.h387
-rw-r--r--src/include/openssl/ec_key.h280
-rw-r--r--src/include/openssl/ecdh.h103
-rw-r--r--src/include/openssl/ecdsa.h187
-rw-r--r--src/include/openssl/engine.h105
-rw-r--r--src/include/openssl/err.h544
-rw-r--r--src/include/openssl/evp.h876
-rw-r--r--src/include/openssl/ex_data.h300
-rw-r--r--src/include/openssl/hkdf.h45
-rw-r--r--src/include/openssl/hmac.h164
-rw-r--r--src/include/openssl/lhash.h194
-rw-r--r--src/include/openssl/lhash_macros.h248
-rw-r--r--src/include/openssl/md4.h101
-rw-r--r--src/include/openssl/md5.h106
-rw-r--r--src/include/openssl/mem.h138
-rw-r--r--src/include/openssl/modes.h223
-rw-r--r--src/include/openssl/obj.h202
-rw-r--r--src/include/openssl/obj_mac.h4145
-rw-r--r--src/include/openssl/objects.h18
-rw-r--r--src/include/openssl/opensslfeatures.h55
-rw-r--r--src/include/openssl/opensslv.h18
-rw-r--r--src/include/openssl/ossl_typ.h18
-rw-r--r--src/include/openssl/pem.h558
-rw-r--r--src/include/openssl/pkcs12.h18
-rw-r--r--src/include/openssl/pkcs7.h16
-rw-r--r--src/include/openssl/pkcs8.h223
-rw-r--r--src/include/openssl/poly1305.h47
-rw-r--r--src/include/openssl/pqueue.h146
-rw-r--r--src/include/openssl/rand.h53
-rw-r--r--src/include/openssl/rc4.h93
-rw-r--r--src/include/openssl/rsa.h541
-rw-r--r--src/include/openssl/safe_stack.h16
-rw-r--r--src/include/openssl/sha.h237
-rw-r--r--src/include/openssl/srtp.h178
-rw-r--r--src/include/openssl/ssl.h2751
-rw-r--r--src/include/openssl/ssl2.h272
-rw-r--r--src/include/openssl/ssl23.h85
-rw-r--r--src/include/openssl/ssl3.h662
-rw-r--r--src/include/openssl/stack.h294
-rw-r--r--src/include/openssl/stack_macros.h3704
-rw-r--r--src/include/openssl/thread.h273
-rw-r--r--src/include/openssl/time_support.h91
-rw-r--r--src/include/openssl/tls1.h716
-rw-r--r--src/include/openssl/type_check.h87
-rw-r--r--src/include/openssl/x509.h1309
-rw-r--r--src/include/openssl/x509_vfy.h607
-rw-r--r--src/include/openssl/x509v3.h870
-rw-r--r--src/ssl/CMakeLists.txt45
-rw-r--r--src/ssl/d1_both.c1173
-rw-r--r--src/ssl/d1_clnt.c577
-rw-r--r--src/ssl/d1_lib.c439
-rw-r--r--src/ssl/d1_meth.c136
-rw-r--r--src/ssl/d1_pkt.c1321
-rw-r--r--src/ssl/d1_srtp.c431
-rw-r--r--src/ssl/d1_srvr.c605
-rw-r--r--src/ssl/pqueue/CMakeLists.txt17
-rw-r--r--src/ssl/pqueue/pqueue.c194
-rw-r--r--src/ssl/pqueue/pqueue_test.c117
-rw-r--r--src/ssl/s3_both.c699
-rw-r--r--src/ssl/s3_clnt.c2417
-rw-r--r--src/ssl/s3_enc.c527
-rw-r--r--src/ssl/s3_lib.c1548
-rw-r--r--src/ssl/s3_meth.c171
-rw-r--r--src/ssl/s3_pkt.c1216
-rw-r--r--src/ssl/s3_srvr.c2807
-rw-r--r--src/ssl/ssl_algs.c71
-rw-r--r--src/ssl/ssl_asn1.c591
-rw-r--r--src/ssl/ssl_cert.c1081
-rw-r--r--src/ssl/ssl_ciph.c1421
-rw-r--r--src/ssl/ssl_error.c566
-rw-r--r--src/ssl/ssl_lib.c3174
-rw-r--r--src/ssl/ssl_locl.h1035
-rw-r--r--src/ssl/ssl_rsa.c707
-rw-r--r--src/ssl/ssl_sess.c920
-rw-r--r--src/ssl/ssl_stat.c1018
-rw-r--r--src/ssl/ssl_test.c456
-rw-r--r--src/ssl/ssl_txt.c211
-rw-r--r--src/ssl/t1_enc.c1042
-rw-r--r--src/ssl/t1_lib.c2671
-rw-r--r--src/ssl/t1_reneg.c247
-rw-r--r--src/ssl/test/CMakeLists.txt16
-rw-r--r--src/ssl/test/async_bio.cc180
-rw-r--r--src/ssl/test/async_bio.h40
-rw-r--r--src/ssl/test/bssl_shim.cc758
-rw-r--r--src/ssl/test/malloc.cc130
-rw-r--r--src/ssl/test/packeted_bio.cc135
-rw-r--r--src/ssl/test/packeted_bio.h32
-rw-r--r--src/ssl/test/runner/alert.go77
-rw-r--r--src/ssl/test/runner/cert.pem15
-rw-r--r--src/ssl/test/runner/channel_id_key.pem5
-rw-r--r--src/ssl/test/runner/cipher_suites.go395
-rw-r--r--src/ssl/test/runner/common.go953
-rw-r--r--src/ssl/test/runner/conn.go1229
-rw-r--r--src/ssl/test/runner/dtls.go342
-rw-r--r--src/ssl/test/runner/ecdsa_cert.pem12
-rw-r--r--src/ssl/test/runner/ecdsa_key.pem8
-rw-r--r--src/ssl/test/runner/handshake_client.go910
-rw-r--r--src/ssl/test/runner/handshake_messages.go1875
-rw-r--r--src/ssl/test/runner/handshake_server.go964
-rw-r--r--src/ssl/test/runner/key.pem15
-rw-r--r--src/ssl/test/runner/key_agreement.go776
-rw-r--r--src/ssl/test/runner/packet_adapter.go101
-rw-r--r--src/ssl/test/runner/prf.go388
-rw-r--r--src/ssl/test/runner/recordingconn.go130
-rw-r--r--src/ssl/test/runner/runner.go2649
-rw-r--r--src/ssl/test/runner/ticket.go221
-rw-r--r--src/ssl/test/runner/tls.go279
-rw-r--r--src/ssl/test/test_config.cc198
-rw-r--r--src/ssl/test/test_config.h75
-rw-r--r--src/tool/CMakeLists.txt21
-rw-r--r--src/tool/args.cc73
-rw-r--r--src/tool/client.cc100
-rw-r--r--src/tool/const.cc326
-rw-r--r--src/tool/digest.cc482
-rw-r--r--src/tool/internal.h47
-rw-r--r--src/tool/pkcs12.cc138
-rw-r--r--src/tool/server.cc109
-rw-r--r--src/tool/speed.cc329
-rw-r--r--src/tool/tool.cc132
-rw-r--r--src/tool/transport_common.cc298
-rw-r--r--src/tool/transport_common.h43
-rw-r--r--src/util/32-bit-toolchain.cmake7
-rw-r--r--src/util/aarch64-toolchain.cmake6
-rw-r--r--src/util/all_tests.sh85
-rw-r--r--src/util/arm-toolchain.cmake6
-rw-r--r--src/util/clang-toolchain.cmake2
-rw-r--r--src/util/doc.config49
-rw-r--r--src/util/doc.css67
-rw-r--r--src/util/doc.go623
-rw-r--r--src/util/make_errors.go462
-rw-r--r--ssl-sources.mk5
-rw-r--r--update_gypi_and_asm.py214
-rw-r--r--win-x86_64/crypto/aes/aes-x86_64.asm2864
-rw-r--r--win-x86_64/crypto/aes/aesni-x86_64.asm3631
-rw-r--r--win-x86_64/crypto/aes/bsaes-x86_64.asm2734
-rw-r--r--win-x86_64/crypto/aes/vpaes-x86_64.asm1143
-rw-r--r--win-x86_64/crypto/bn/modexp512-x86_64.asm1887
-rw-r--r--win-x86_64/crypto/bn/rsaz-avx2.asm29
-rw-r--r--win-x86_64/crypto/bn/rsaz-x86_64.asm1326
-rw-r--r--win-x86_64/crypto/bn/x86_64-mont.asm945
-rw-r--r--win-x86_64/crypto/bn/x86_64-mont5.asm2061
-rw-r--r--win-x86_64/crypto/cpu-x86_64-asm.asm158
-rw-r--r--win-x86_64/crypto/md5/md5-x86_64.asm778
-rw-r--r--win-x86_64/crypto/modes/aesni-gcm-x86_64.asm19
-rw-r--r--win-x86_64/crypto/modes/ghash-x86_64.asm1510
-rw-r--r--win-x86_64/crypto/rc4/rc4-md5-x86_64.asm1374
-rw-r--r--win-x86_64/crypto/rc4/rc4-x86_64.asm773
-rw-r--r--win-x86_64/crypto/sha/sha1-x86_64.asm2619
-rw-r--r--win-x86_64/crypto/sha/sha256-x86_64.asm2997
-rw-r--r--win-x86_64/crypto/sha/sha512-x86_64.asm1913
716 files changed, 396653 insertions, 0 deletions
diff --git a/Android.mk b/Android.mk
new file mode 100644
index 0000000..81b6ce1
--- /dev/null
+++ b/Android.mk
@@ -0,0 +1,102 @@
+# Note that some host libraries have the same module name as the target
+# libraries. This is currently needed to build, for example, adb. But it's
+# probably something that should be changed.
+
+LOCAL_PATH := $(call my-dir)
+
+## libcrypto
+
+# Target static library
+include $(CLEAR_VARS)
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE := libcrypto_static
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/src/include
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk $(LOCAL_PATH)/crypto-sources.mk
+include $(LOCAL_PATH)/crypto-sources.mk
+include $(BUILD_STATIC_LIBRARY)
+
+# Target shared library
+include $(CLEAR_VARS)
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE := libcrypto
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/src/include
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk $(LOCAL_PATH)/crypto-sources.mk
+LOCAL_CFLAGS += -fvisibility=hidden -DBORINGSSL_SHARED_LIBRARY -DBORINGSSL_IMPLEMENTATION
+include $(LOCAL_PATH)/crypto-sources.mk
+include $(BUILD_SHARED_LIBRARY)
+
+# Target static tool
+include $(CLEAR_VARS)
+LOCAL_CFLAGS += -Wall -Werror -std=c++0x
+LOCAL_CPP_EXTENSION := cc
+LOCAL_MODULE := bssl
+LOCAL_MODULE_TAGS := optional
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk $(LOCAL_PATH)/sources.mk
+LOCAL_SHARED_LIBRARIES=libcrypto libssl
+include $(LOCAL_PATH)/sources.mk
+LOCAL_SRC_FILES = $(tool_sources)
+include $(BUILD_EXECUTABLE)
+
+# Host static library
+include $(CLEAR_VARS)
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE := libcrypto_static
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/src/include
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk $(LOCAL_PATH)/crypto-sources.mk
+include $(LOCAL_PATH)/crypto-sources.mk
+include $(BUILD_HOST_STATIC_LIBRARY)
+
+# Host shared library
+include $(CLEAR_VARS)
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE := libcrypto-host
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+LOCAL_MULTILIB := both
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk $(LOCAL_PATH)/crypto-sources.mk
+LOCAL_CFLAGS += -fvisibility=hidden -DBORINGSSL_SHARED_LIBRARY -DBORINGSSL_IMPLEMENTATION
+include $(LOCAL_PATH)/crypto-sources.mk
+include $(BUILD_HOST_SHARED_LIBRARY)
+
+
+## libssl
+
+# Target static library
+include $(CLEAR_VARS)
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE := libssl_static
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/src/include
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk $(LOCAL_PATH)/ssl-sources.mk
+include $(LOCAL_PATH)/ssl-sources.mk
+include $(BUILD_STATIC_LIBRARY)
+
+# Target shared library
+include $(CLEAR_VARS)
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE := libssl
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/src/include
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk $(LOCAL_PATH)/ssl-sources.mk
+LOCAL_CFLAGS += -fvisibility=hidden -DBORINGSSL_SHARED_LIBRARY -DBORINGSSL_IMPLEMENTATION
+LOCAL_SHARED_LIBRARIES=libcrypto
+include $(LOCAL_PATH)/ssl-sources.mk
+include $(BUILD_SHARED_LIBRARY)
+
+# Host static library
+include $(CLEAR_VARS)
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE := libssl_static-host
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/src/include
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk $(LOCAL_PATH)/ssl-sources.mk
+include $(LOCAL_PATH)/ssl-sources.mk
+include $(BUILD_HOST_STATIC_LIBRARY)
+
+# Host shared library
+include $(CLEAR_VARS)
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE := libssl-host
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/src/include
+LOCAL_MULTILIB := both
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk $(LOCAL_PATH)/ssl-sources.mk
+LOCAL_CFLAGS += -fvisibility=hidden -DBORINGSSL_SHARED_LIBRARY -DBORINGSSL_IMPLEMENTATION
+LOCAL_SHARED_LIBRARIES += libcrypto-host
+include $(LOCAL_PATH)/ssl-sources.mk
+include $(BUILD_HOST_SHARED_LIBRARY)
diff --git a/BORINGSSL_REVISION b/BORINGSSL_REVISION
new file mode 100644
index 0000000..d740488
--- /dev/null
+++ b/BORINGSSL_REVISION
@@ -0,0 +1 @@
+4cc1e838aef70be6194c2c77e1de9015b9b7410a
diff --git a/MODULE_LICENSE_BSD_LIKE b/MODULE_LICENSE_BSD_LIKE
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/MODULE_LICENSE_BSD_LIKE
diff --git a/NOTICE b/NOTICE
new file mode 100644
index 0000000..e47d101
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,127 @@
+
+ LICENSE ISSUES
+ ==============
+
+ The OpenSSL toolkit stays under a dual license, i.e. both the conditions of
+ the OpenSSL License and the original SSLeay license apply to the toolkit.
+ See below for the actual license texts. Actually both licenses are BSD-style
+ Open Source licenses. In case of any license issues related to OpenSSL
+ please contact openssl-core@openssl.org.
+
+ OpenSSL License
+ ---------------
+
+/* ====================================================================
+ * 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).
+ *
+ */
+
+ Original SSLeay License
+ -----------------------
+
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
diff --git a/android_compat_hacks.c b/android_compat_hacks.c
new file mode 100644
index 0000000..ac6a344
--- /dev/null
+++ b/android_compat_hacks.c
@@ -0,0 +1,75 @@
+/* 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. */
+
+/* This file contains odd functions that are needed, temporarily, on Android
+ * because wpa_supplicant will take a little while to sync with upstream.
+ *
+ * The declarations for these functions are in the main BoringSSL headers but
+ * the only definitions are here, in Android land. */
+
+#include <openssl/base.h>
+
+#include <assert.h>
+
+#include <openssl/bn.h>
+#include <openssl/cipher.h>
+#include <openssl/err.h>
+#include <openssl/ssl.h>
+
+
+const EVP_CIPHER *EVP_aes_192_ecb(void) { return NULL; }
+
+const EVP_CIPHER *EVP_aes_192_cbc(void) { return NULL; }
+
+BIGNUM *get_rfc3526_prime_1536(BIGNUM *bn) {
+ assert(bn == NULL);
+
+ static const uint8_t data[] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
+ 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+ 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
+ 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+ 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
+ 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+ 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
+ 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
+ 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
+ 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
+ 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
+ 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
+ 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
+ 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
+ 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
+ 0xCA, 0x23, 0x73, 0x27, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ };
+
+ return BN_bin2bn(data, sizeof(data), NULL);
+}
+
+void ERR_remove_state(unsigned long pid) {
+ assert(pid == 0);
+ ERR_remove_thread_state(NULL);
+}
+
+int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len) {
+ return 0;
+}
+
+int SSL_set_session_ticket_ext_cb(SSL *s, void *cb, void *arg) {
+ return 0;
+}
+
+int SSL_set_session_secret_cb(SSL *s, void *cb, void *arg) {
+ return 0;
+}
diff --git a/arm_arch.h b/arm_arch.h
new file mode 120000
index 0000000..3958887
--- /dev/null
+++ b/arm_arch.h
@@ -0,0 +1 @@
+src/crypto/arm_arch.h \ No newline at end of file
diff --git a/crypto-sources.mk b/crypto-sources.mk
new file mode 100644
index 0000000..a575406
--- /dev/null
+++ b/crypto-sources.mk
@@ -0,0 +1,9 @@
+LOCAL_ADDITIONAL_DEPENDENCIES += $(LOCAL_PATH)/sources.mk
+include $(LOCAL_PATH)/sources.mk
+
+LOCAL_CFLAGS += -I$(LOCAL_PATH)/src/include -I$(LOCAL_PATH)/src/crypto -Wno-unused-parameter
+LOCAL_SRC_FILES_x86 = $(linux_x86_sources)
+LOCAL_SRC_FILES_x86_64 = $(linux_x86_64_sources)
+LOCAL_SRC_FILES_arm = $(linux_arm_sources)
+LOCAL_SRC_FILES_arm64 = $(linux_aarch64_sources)
+LOCAL_SRC_FILES += $(crypto_sources)
diff --git a/flavor.mk b/flavor.mk
new file mode 100644
index 0000000..32c4fc5
--- /dev/null
+++ b/flavor.mk
@@ -0,0 +1,4 @@
+# This makefile exists to be included by makefiles in other directories so that
+# they can detect whether BoringSSL or OpenSSL is being used.
+
+OPENSSL_FLAVOR=BoringSSL
diff --git a/include b/include
new file mode 120000
index 0000000..6004eb4
--- /dev/null
+++ b/include
@@ -0,0 +1 @@
+src/include \ No newline at end of file
diff --git a/linux-aarch64/crypto/aes/aesv8-armx.S b/linux-aarch64/crypto/aes/aesv8-armx.S
new file mode 100644
index 0000000..0a4b1ac
--- /dev/null
+++ b/linux-aarch64/crypto/aes/aesv8-armx.S
@@ -0,0 +1,725 @@
+#include "arm_arch.h"
+
+#if __ARM_MAX_ARCH__>=7
+.text
+.arch armv8-a+crypto
+.align 5
+rcon:
+.long 0x01,0x01,0x01,0x01
+.long 0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d // rotate-n-splat
+.long 0x1b,0x1b,0x1b,0x1b
+
+.globl aes_v8_set_encrypt_key
+.type aes_v8_set_encrypt_key,%function
+.align 5
+aes_v8_set_encrypt_key:
+.Lenc_key:
+ stp x29,x30,[sp,#-16]!
+ add x29,sp,#0
+ mov x3,#-1
+ cmp x0,#0
+ b.eq .Lenc_key_abort
+ cmp x2,#0
+ b.eq .Lenc_key_abort
+ mov x3,#-2
+ cmp w1,#128
+ b.lt .Lenc_key_abort
+ cmp w1,#256
+ b.gt .Lenc_key_abort
+ tst w1,#0x3f
+ b.ne .Lenc_key_abort
+
+ adr x3,rcon
+ cmp w1,#192
+
+ eor v0.16b,v0.16b,v0.16b
+ ld1 {v3.16b},[x0],#16
+ mov w1,#8 // reuse w1
+ ld1 {v1.4s,v2.4s},[x3],#32
+
+ b.lt .Loop128
+ b.eq .L192
+ b .L256
+
+.align 4
+.Loop128:
+ tbl v6.16b,{v3.16b},v2.16b
+ ext v5.16b,v0.16b,v3.16b,#12
+ st1 {v3.4s},[x2],#16
+ aese v6.16b,v0.16b
+ subs w1,w1,#1
+
+ eor v3.16b,v3.16b,v5.16b
+ ext v5.16b,v0.16b,v5.16b,#12
+ eor v3.16b,v3.16b,v5.16b
+ ext v5.16b,v0.16b,v5.16b,#12
+ eor v6.16b,v6.16b,v1.16b
+ eor v3.16b,v3.16b,v5.16b
+ shl v1.16b,v1.16b,#1
+ eor v3.16b,v3.16b,v6.16b
+ b.ne .Loop128
+
+ ld1 {v1.4s},[x3]
+
+ tbl v6.16b,{v3.16b},v2.16b
+ ext v5.16b,v0.16b,v3.16b,#12
+ st1 {v3.4s},[x2],#16
+ aese v6.16b,v0.16b
+
+ eor v3.16b,v3.16b,v5.16b
+ ext v5.16b,v0.16b,v5.16b,#12
+ eor v3.16b,v3.16b,v5.16b
+ ext v5.16b,v0.16b,v5.16b,#12
+ eor v6.16b,v6.16b,v1.16b
+ eor v3.16b,v3.16b,v5.16b
+ shl v1.16b,v1.16b,#1
+ eor v3.16b,v3.16b,v6.16b
+
+ tbl v6.16b,{v3.16b},v2.16b
+ ext v5.16b,v0.16b,v3.16b,#12
+ st1 {v3.4s},[x2],#16
+ aese v6.16b,v0.16b
+
+ eor v3.16b,v3.16b,v5.16b
+ ext v5.16b,v0.16b,v5.16b,#12
+ eor v3.16b,v3.16b,v5.16b
+ ext v5.16b,v0.16b,v5.16b,#12
+ eor v6.16b,v6.16b,v1.16b
+ eor v3.16b,v3.16b,v5.16b
+ eor v3.16b,v3.16b,v6.16b
+ st1 {v3.4s},[x2]
+ add x2,x2,#0x50
+
+ mov w12,#10
+ b .Ldone
+
+.align 4
+.L192:
+ ld1 {v4.8b},[x0],#8
+ movi v6.16b,#8 // borrow v6.16b
+ st1 {v3.4s},[x2],#16
+ sub v2.16b,v2.16b,v6.16b // adjust the mask
+
+.Loop192:
+ tbl v6.16b,{v4.16b},v2.16b
+ ext v5.16b,v0.16b,v3.16b,#12
+ st1 {v4.8b},[x2],#8
+ aese v6.16b,v0.16b
+ subs w1,w1,#1
+
+ eor v3.16b,v3.16b,v5.16b
+ ext v5.16b,v0.16b,v5.16b,#12
+ eor v3.16b,v3.16b,v5.16b
+ ext v5.16b,v0.16b,v5.16b,#12
+ eor v3.16b,v3.16b,v5.16b
+
+ dup v5.4s,v3.s[3]
+ eor v5.16b,v5.16b,v4.16b
+ eor v6.16b,v6.16b,v1.16b
+ ext v4.16b,v0.16b,v4.16b,#12
+ shl v1.16b,v1.16b,#1
+ eor v4.16b,v4.16b,v5.16b
+ eor v3.16b,v3.16b,v6.16b
+ eor v4.16b,v4.16b,v6.16b
+ st1 {v3.4s},[x2],#16
+ b.ne .Loop192
+
+ mov w12,#12
+ add x2,x2,#0x20
+ b .Ldone
+
+.align 4
+.L256:
+ ld1 {v4.16b},[x0]
+ mov w1,#7
+ mov w12,#14
+ st1 {v3.4s},[x2],#16
+
+.Loop256:
+ tbl v6.16b,{v4.16b},v2.16b
+ ext v5.16b,v0.16b,v3.16b,#12
+ st1 {v4.4s},[x2],#16
+ aese v6.16b,v0.16b
+ subs w1,w1,#1
+
+ eor v3.16b,v3.16b,v5.16b
+ ext v5.16b,v0.16b,v5.16b,#12
+ eor v3.16b,v3.16b,v5.16b
+ ext v5.16b,v0.16b,v5.16b,#12
+ eor v6.16b,v6.16b,v1.16b
+ eor v3.16b,v3.16b,v5.16b
+ shl v1.16b,v1.16b,#1
+ eor v3.16b,v3.16b,v6.16b
+ st1 {v3.4s},[x2],#16
+ b.eq .Ldone
+
+ dup v6.4s,v3.s[3] // just splat
+ ext v5.16b,v0.16b,v4.16b,#12
+ aese v6.16b,v0.16b
+
+ eor v4.16b,v4.16b,v5.16b
+ ext v5.16b,v0.16b,v5.16b,#12
+ eor v4.16b,v4.16b,v5.16b
+ ext v5.16b,v0.16b,v5.16b,#12
+ eor v4.16b,v4.16b,v5.16b
+
+ eor v4.16b,v4.16b,v6.16b
+ b .Loop256
+
+.Ldone:
+ str w12,[x2]
+ mov x3,#0
+
+.Lenc_key_abort:
+ mov x0,x3 // return value
+ ldr x29,[sp],#16
+ ret
+.size aes_v8_set_encrypt_key,.-aes_v8_set_encrypt_key
+
+.globl aes_v8_set_decrypt_key
+.type aes_v8_set_decrypt_key,%function
+.align 5
+aes_v8_set_decrypt_key:
+ stp x29,x30,[sp,#-16]!
+ add x29,sp,#0
+ bl .Lenc_key
+
+ cmp x0,#0
+ b.ne .Ldec_key_abort
+
+ sub x2,x2,#240 // restore original x2
+ mov x4,#-16
+ add x0,x2,x12,lsl#4 // end of key schedule
+
+ ld1 {v0.4s},[x2]
+ ld1 {v1.4s},[x0]
+ st1 {v0.4s},[x0],x4
+ st1 {v1.4s},[x2],#16
+
+.Loop_imc:
+ ld1 {v0.4s},[x2]
+ ld1 {v1.4s},[x0]
+ aesimc v0.16b,v0.16b
+ aesimc v1.16b,v1.16b
+ st1 {v0.4s},[x0],x4
+ st1 {v1.4s},[x2],#16
+ cmp x0,x2
+ b.hi .Loop_imc
+
+ ld1 {v0.4s},[x2]
+ aesimc v0.16b,v0.16b
+ st1 {v0.4s},[x0]
+
+ eor x0,x0,x0 // return value
+.Ldec_key_abort:
+ ldp x29,x30,[sp],#16
+ ret
+.size aes_v8_set_decrypt_key,.-aes_v8_set_decrypt_key
+.globl aes_v8_encrypt
+.type aes_v8_encrypt,%function
+.align 5
+aes_v8_encrypt:
+ ldr w3,[x2,#240]
+ ld1 {v0.4s},[x2],#16
+ ld1 {v2.16b},[x0]
+ sub w3,w3,#2
+ ld1 {v1.4s},[x2],#16
+
+.Loop_enc:
+ aese v2.16b,v0.16b
+ ld1 {v0.4s},[x2],#16
+ aesmc v2.16b,v2.16b
+ subs w3,w3,#2
+ aese v2.16b,v1.16b
+ ld1 {v1.4s},[x2],#16
+ aesmc v2.16b,v2.16b
+ b.gt .Loop_enc
+
+ aese v2.16b,v0.16b
+ ld1 {v0.4s},[x2]
+ aesmc v2.16b,v2.16b
+ aese v2.16b,v1.16b
+ eor v2.16b,v2.16b,v0.16b
+
+ st1 {v2.16b},[x1]
+ ret
+.size aes_v8_encrypt,.-aes_v8_encrypt
+.globl aes_v8_decrypt
+.type aes_v8_decrypt,%function
+.align 5
+aes_v8_decrypt:
+ ldr w3,[x2,#240]
+ ld1 {v0.4s},[x2],#16
+ ld1 {v2.16b},[x0]
+ sub w3,w3,#2
+ ld1 {v1.4s},[x2],#16
+
+.Loop_dec:
+ aesd v2.16b,v0.16b
+ ld1 {v0.4s},[x2],#16
+ aesimc v2.16b,v2.16b
+ subs w3,w3,#2
+ aesd v2.16b,v1.16b
+ ld1 {v1.4s},[x2],#16
+ aesimc v2.16b,v2.16b
+ b.gt .Loop_dec
+
+ aesd v2.16b,v0.16b
+ ld1 {v0.4s},[x2]
+ aesimc v2.16b,v2.16b
+ aesd v2.16b,v1.16b
+ eor v2.16b,v2.16b,v0.16b
+
+ st1 {v2.16b},[x1]
+ ret
+.size aes_v8_decrypt,.-aes_v8_decrypt
+.globl aes_v8_cbc_encrypt
+.type aes_v8_cbc_encrypt,%function
+.align 5
+aes_v8_cbc_encrypt:
+ stp x29,x30,[sp,#-16]!
+ add x29,sp,#0
+ subs x2,x2,#16
+ mov x8,#16
+ b.lo .Lcbc_abort
+ csel x8,xzr,x8,eq
+
+ cmp w5,#0 // en- or decrypting?
+ ldr w5,[x3,#240]
+ and x2,x2,#-16
+ ld1 {v6.16b},[x4]
+ ld1 {v0.16b},[x0],x8
+
+ ld1 {v16.4s-v17.4s},[x3] // load key schedule...
+ sub w5,w5,#6
+ add x7,x3,x5,lsl#4 // pointer to last 7 round keys
+ sub w5,w5,#2
+ ld1 {v18.4s-v19.4s},[x7],#32
+ ld1 {v20.4s-v21.4s},[x7],#32
+ ld1 {v22.4s-v23.4s},[x7],#32
+ ld1 {v7.4s},[x7]
+
+ add x7,x3,#32
+ mov w6,w5
+ b.eq .Lcbc_dec
+
+ cmp w5,#2
+ eor v0.16b,v0.16b,v6.16b
+ eor v5.16b,v16.16b,v7.16b
+ b.eq .Lcbc_enc128
+
+.Loop_cbc_enc:
+ aese v0.16b,v16.16b
+ ld1 {v16.4s},[x7],#16
+ aesmc v0.16b,v0.16b
+ subs w6,w6,#2
+ aese v0.16b,v17.16b
+ ld1 {v17.4s},[x7],#16
+ aesmc v0.16b,v0.16b
+ b.gt .Loop_cbc_enc
+
+ aese v0.16b,v16.16b
+ aesmc v0.16b,v0.16b
+ subs x2,x2,#16
+ aese v0.16b,v17.16b
+ aesmc v0.16b,v0.16b
+ csel x8,xzr,x8,eq
+ aese v0.16b,v18.16b
+ aesmc v0.16b,v0.16b
+ add x7,x3,#16
+ aese v0.16b,v19.16b
+ aesmc v0.16b,v0.16b
+ ld1 {v16.16b},[x0],x8
+ aese v0.16b,v20.16b
+ aesmc v0.16b,v0.16b
+ eor v16.16b,v16.16b,v5.16b
+ aese v0.16b,v21.16b
+ aesmc v0.16b,v0.16b
+ ld1 {v17.4s},[x7],#16 // re-pre-load rndkey[1]
+ aese v0.16b,v22.16b
+ aesmc v0.16b,v0.16b
+ aese v0.16b,v23.16b
+
+ mov w6,w5
+ eor v6.16b,v0.16b,v7.16b
+ st1 {v6.16b},[x1],#16
+ b.hs .Loop_cbc_enc
+
+ b .Lcbc_done
+
+.align 5
+.Lcbc_enc128:
+ ld1 {v2.4s-v3.4s},[x7]
+ aese v0.16b,v16.16b
+ aesmc v0.16b,v0.16b
+ b .Lenter_cbc_enc128
+.Loop_cbc_enc128:
+ aese v0.16b,v16.16b
+ aesmc v0.16b,v0.16b
+ st1 {v6.16b},[x1],#16
+.Lenter_cbc_enc128:
+ aese v0.16b,v17.16b
+ aesmc v0.16b,v0.16b
+ subs x2,x2,#16
+ aese v0.16b,v2.16b
+ aesmc v0.16b,v0.16b
+ csel x8,xzr,x8,eq
+ aese v0.16b,v3.16b
+ aesmc v0.16b,v0.16b
+ aese v0.16b,v18.16b
+ aesmc v0.16b,v0.16b
+ aese v0.16b,v19.16b
+ aesmc v0.16b,v0.16b
+ ld1 {v16.16b},[x0],x8
+ aese v0.16b,v20.16b
+ aesmc v0.16b,v0.16b
+ aese v0.16b,v21.16b
+ aesmc v0.16b,v0.16b
+ aese v0.16b,v22.16b
+ aesmc v0.16b,v0.16b
+ eor v16.16b,v16.16b,v5.16b
+ aese v0.16b,v23.16b
+ eor v6.16b,v0.16b,v7.16b
+ b.hs .Loop_cbc_enc128
+
+ st1 {v6.16b},[x1],#16
+ b .Lcbc_done
+.align 5
+.Lcbc_dec:
+ ld1 {v18.16b},[x0],#16
+ subs x2,x2,#32 // bias
+ add w6,w5,#2
+ orr v3.16b,v0.16b,v0.16b
+ orr v1.16b,v0.16b,v0.16b
+ orr v19.16b,v18.16b,v18.16b
+ b.lo .Lcbc_dec_tail
+
+ orr v1.16b,v18.16b,v18.16b
+ ld1 {v18.16b},[x0],#16
+ orr v2.16b,v0.16b,v0.16b
+ orr v3.16b,v1.16b,v1.16b
+ orr v19.16b,v18.16b,v18.16b
+
+.Loop3x_cbc_dec:
+ aesd v0.16b,v16.16b
+ aesd v1.16b,v16.16b
+ aesd v18.16b,v16.16b
+ ld1 {v16.4s},[x7],#16
+ aesimc v0.16b,v0.16b
+ aesimc v1.16b,v1.16b
+ aesimc v18.16b,v18.16b
+ subs w6,w6,#2
+ aesd v0.16b,v17.16b
+ aesd v1.16b,v17.16b
+ aesd v18.16b,v17.16b
+ ld1 {v17.4s},[x7],#16
+ aesimc v0.16b,v0.16b
+ aesimc v1.16b,v1.16b
+ aesimc v18.16b,v18.16b
+ b.gt .Loop3x_cbc_dec
+
+ aesd v0.16b,v16.16b
+ aesd v1.16b,v16.16b
+ aesd v18.16b,v16.16b
+ eor v4.16b,v6.16b,v7.16b
+ aesimc v0.16b,v0.16b
+ aesimc v1.16b,v1.16b
+ aesimc v18.16b,v18.16b
+ eor v5.16b,v2.16b,v7.16b
+ aesd v0.16b,v17.16b
+ aesd v1.16b,v17.16b
+ aesd v18.16b,v17.16b
+ eor v17.16b,v3.16b,v7.16b
+ subs x2,x2,#0x30
+ aesimc v0.16b,v0.16b
+ aesimc v1.16b,v1.16b
+ aesimc v18.16b,v18.16b
+ orr v6.16b,v19.16b,v19.16b
+ csel x6,x2,x6,lo // x6, w6, is zero at this point
+ aesd v0.16b,v20.16b
+ aesd v1.16b,v20.16b
+ aesd v18.16b,v20.16b
+ add x0,x0,x6 // x0 is adjusted in such way that
+ // at exit from the loop v1.16b-v18.16b
+ // are loaded with last "words"
+ aesimc v0.16b,v0.16b
+ aesimc v1.16b,v1.16b
+ aesimc v18.16b,v18.16b
+ mov x7,x3
+ aesd v0.16b,v21.16b
+ aesd v1.16b,v21.16b
+ aesd v18.16b,v21.16b
+ ld1 {v2.16b},[x0],#16
+ aesimc v0.16b,v0.16b
+ aesimc v1.16b,v1.16b
+ aesimc v18.16b,v18.16b
+ ld1 {v3.16b},[x0],#16
+ aesd v0.16b,v22.16b
+ aesd v1.16b,v22.16b
+ aesd v18.16b,v22.16b
+ ld1 {v19.16b},[x0],#16
+ aesimc v0.16b,v0.16b
+ aesimc v1.16b,v1.16b
+ aesimc v18.16b,v18.16b
+ ld1 {v16.4s},[x7],#16 // re-pre-load rndkey[0]
+ aesd v0.16b,v23.16b
+ aesd v1.16b,v23.16b
+ aesd v18.16b,v23.16b
+
+ add w6,w5,#2
+ eor v4.16b,v4.16b,v0.16b
+ eor v5.16b,v5.16b,v1.16b
+ eor v18.16b,v18.16b,v17.16b
+ ld1 {v17.4s},[x7],#16 // re-pre-load rndkey[1]
+ orr v0.16b,v2.16b,v2.16b
+ st1 {v4.16b},[x1],#16
+ orr v1.16b,v3.16b,v3.16b
+ st1 {v5.16b},[x1],#16
+ st1 {v18.16b},[x1],#16
+ orr v18.16b,v19.16b,v19.16b
+ b.hs .Loop3x_cbc_dec
+
+ cmn x2,#0x30
+ b.eq .Lcbc_done
+ nop
+
+.Lcbc_dec_tail:
+ aesd v1.16b,v16.16b
+ aesd v18.16b,v16.16b
+ ld1 {v16.4s},[x7],#16
+ aesimc v1.16b,v1.16b
+ aesimc v18.16b,v18.16b
+ subs w6,w6,#2
+ aesd v1.16b,v17.16b
+ aesd v18.16b,v17.16b
+ ld1 {v17.4s},[x7],#16
+ aesimc v1.16b,v1.16b
+ aesimc v18.16b,v18.16b
+ b.gt .Lcbc_dec_tail
+
+ aesd v1.16b,v16.16b
+ aesd v18.16b,v16.16b
+ aesimc v1.16b,v1.16b
+ aesimc v18.16b,v18.16b
+ aesd v1.16b,v17.16b
+ aesd v18.16b,v17.16b
+ aesimc v1.16b,v1.16b
+ aesimc v18.16b,v18.16b
+ aesd v1.16b,v20.16b
+ aesd v18.16b,v20.16b
+ aesimc v1.16b,v1.16b
+ aesimc v18.16b,v18.16b
+ cmn x2,#0x20
+ aesd v1.16b,v21.16b
+ aesd v18.16b,v21.16b
+ aesimc v1.16b,v1.16b
+ aesimc v18.16b,v18.16b
+ eor v5.16b,v6.16b,v7.16b
+ aesd v1.16b,v22.16b
+ aesd v18.16b,v22.16b
+ aesimc v1.16b,v1.16b
+ aesimc v18.16b,v18.16b
+ eor v17.16b,v3.16b,v7.16b
+ aesd v1.16b,v23.16b
+ aesd v18.16b,v23.16b
+ b.eq .Lcbc_dec_one
+ eor v5.16b,v5.16b,v1.16b
+ eor v17.16b,v17.16b,v18.16b
+ orr v6.16b,v19.16b,v19.16b
+ st1 {v5.16b},[x1],#16
+ st1 {v17.16b},[x1],#16
+ b .Lcbc_done
+
+.Lcbc_dec_one:
+ eor v5.16b,v5.16b,v18.16b
+ orr v6.16b,v19.16b,v19.16b
+ st1 {v5.16b},[x1],#16
+
+.Lcbc_done:
+ st1 {v6.16b},[x4]
+.Lcbc_abort:
+ ldr x29,[sp],#16
+ ret
+.size aes_v8_cbc_encrypt,.-aes_v8_cbc_encrypt
+.globl aes_v8_ctr32_encrypt_blocks
+.type aes_v8_ctr32_encrypt_blocks,%function
+.align 5
+aes_v8_ctr32_encrypt_blocks:
+ stp x29,x30,[sp,#-16]!
+ add x29,sp,#0
+ ldr w5,[x3,#240]
+
+ ldr w8, [x4, #12]
+ ld1 {v0.4s},[x4]
+
+ ld1 {v16.4s-v17.4s},[x3] // load key schedule...
+ sub w5,w5,#4
+ mov x12,#16
+ cmp x2,#2
+ add x7,x3,x5,lsl#4 // pointer to last 5 round keys
+ sub w5,w5,#2
+ ld1 {v20.4s-v21.4s},[x7],#32
+ ld1 {v22.4s-v23.4s},[x7],#32
+ ld1 {v7.4s},[x7]
+ add x7,x3,#32
+ mov w6,w5
+ csel x12,xzr,x12,lo
+#ifndef __ARMEB__
+ rev w8, w8
+#endif
+ orr v1.16b,v0.16b,v0.16b
+ add w10, w8, #1
+ orr v18.16b,v0.16b,v0.16b
+ add w8, w8, #2
+ orr v6.16b,v0.16b,v0.16b
+ rev w10, w10
+ mov v1.s[3],w10
+ b.ls .Lctr32_tail
+ rev w12, w8
+ sub x2,x2,#3 // bias
+ mov v18.s[3],w12
+ b .Loop3x_ctr32
+
+.align 4
+.Loop3x_ctr32:
+ aese v0.16b,v16.16b
+ aese v1.16b,v16.16b
+ aese v18.16b,v16.16b
+ ld1 {v16.4s},[x7],#16
+ aesmc v0.16b,v0.16b
+ aesmc v1.16b,v1.16b
+ aesmc v18.16b,v18.16b
+ subs w6,w6,#2
+ aese v0.16b,v17.16b
+ aese v1.16b,v17.16b
+ aese v18.16b,v17.16b
+ ld1 {v17.4s},[x7],#16
+ aesmc v0.16b,v0.16b
+ aesmc v1.16b,v1.16b
+ aesmc v18.16b,v18.16b
+ b.gt .Loop3x_ctr32
+
+ aese v0.16b,v16.16b
+ aese v1.16b,v16.16b
+ aese v18.16b,v16.16b
+ mov x7,x3
+ aesmc v4.16b,v0.16b
+ ld1 {v2.16b},[x0],#16
+ aesmc v5.16b,v1.16b
+ aesmc v18.16b,v18.16b
+ orr v0.16b,v6.16b,v6.16b
+ aese v4.16b,v17.16b
+ ld1 {v3.16b},[x0],#16
+ aese v5.16b,v17.16b
+ aese v18.16b,v17.16b
+ orr v1.16b,v6.16b,v6.16b
+ aesmc v4.16b,v4.16b
+ ld1 {v19.16b},[x0],#16
+ aesmc v5.16b,v5.16b
+ aesmc v17.16b,v18.16b
+ orr v18.16b,v6.16b,v6.16b
+ add w9,w8,#1
+ aese v4.16b,v20.16b
+ aese v5.16b,v20.16b
+ aese v17.16b,v20.16b
+ eor v2.16b,v2.16b,v7.16b
+ add w10,w8,#2
+ aesmc v4.16b,v4.16b
+ aesmc v5.16b,v5.16b
+ aesmc v17.16b,v17.16b
+ eor v3.16b,v3.16b,v7.16b
+ add w8,w8,#3
+ aese v4.16b,v21.16b
+ aese v5.16b,v21.16b
+ aese v17.16b,v21.16b
+ eor v19.16b,v19.16b,v7.16b
+ rev w9,w9
+ aesmc v4.16b,v4.16b
+ ld1 {v16.4s},[x7],#16 // re-pre-load rndkey[0]
+ aesmc v5.16b,v5.16b
+ aesmc v17.16b,v17.16b
+ mov v0.s[3], w9
+ rev w10,w10
+ aese v4.16b,v22.16b
+ aese v5.16b,v22.16b
+ aese v17.16b,v22.16b
+ mov v1.s[3], w10
+ rev w12,w8
+ aesmc v4.16b,v4.16b
+ aesmc v5.16b,v5.16b
+ aesmc v17.16b,v17.16b
+ mov v18.s[3], w12
+ subs x2,x2,#3
+ aese v4.16b,v23.16b
+ aese v5.16b,v23.16b
+ aese v17.16b,v23.16b
+
+ mov w6,w5
+ eor v2.16b,v2.16b,v4.16b
+ eor v3.16b,v3.16b,v5.16b
+ eor v19.16b,v19.16b,v17.16b
+ ld1 {v17.4s},[x7],#16 // re-pre-load rndkey[1]
+ st1 {v2.16b},[x1],#16
+ st1 {v3.16b},[x1],#16
+ st1 {v19.16b},[x1],#16
+ b.hs .Loop3x_ctr32
+
+ adds x2,x2,#3
+ b.eq .Lctr32_done
+ cmp x2,#1
+ mov x12,#16
+ csel x12,xzr,x12,eq
+
+.Lctr32_tail:
+ aese v0.16b,v16.16b
+ aese v1.16b,v16.16b
+ ld1 {v16.4s},[x7],#16
+ aesmc v0.16b,v0.16b
+ aesmc v1.16b,v1.16b
+ subs w6,w6,#2
+ aese v0.16b,v17.16b
+ aese v1.16b,v17.16b
+ ld1 {v17.4s},[x7],#16
+ aesmc v0.16b,v0.16b
+ aesmc v1.16b,v1.16b
+ b.gt .Lctr32_tail
+
+ aese v0.16b,v16.16b
+ aese v1.16b,v16.16b
+ aesmc v0.16b,v0.16b
+ aesmc v1.16b,v1.16b
+ aese v0.16b,v17.16b
+ aese v1.16b,v17.16b
+ aesmc v0.16b,v0.16b
+ aesmc v1.16b,v1.16b
+ ld1 {v2.16b},[x0],x12
+ aese v0.16b,v20.16b
+ aese v1.16b,v20.16b
+ ld1 {v3.16b},[x0]
+ aesmc v0.16b,v0.16b
+ aesmc v1.16b,v1.16b
+ aese v0.16b,v21.16b
+ aese v1.16b,v21.16b
+ aesmc v0.16b,v0.16b
+ aesmc v1.16b,v1.16b
+ aese v0.16b,v22.16b
+ aese v1.16b,v22.16b
+ eor v2.16b,v2.16b,v7.16b
+ aesmc v0.16b,v0.16b
+ aesmc v1.16b,v1.16b
+ eor v3.16b,v3.16b,v7.16b
+ aese v0.16b,v23.16b
+ aese v1.16b,v23.16b
+
+ cmp x2,#1
+ eor v2.16b,v2.16b,v0.16b
+ eor v3.16b,v3.16b,v1.16b
+ st1 {v2.16b},[x1],#16
+ b.eq .Lctr32_done
+ st1 {v3.16b},[x1]
+
+.Lctr32_done:
+ ldr x29,[sp],#16
+ ret
+.size aes_v8_ctr32_encrypt_blocks,.-aes_v8_ctr32_encrypt_blocks
+#endif
diff --git a/linux-aarch64/crypto/modes/ghashv8-armx.S b/linux-aarch64/crypto/modes/ghashv8-armx.S
new file mode 100644
index 0000000..1bfb263
--- /dev/null
+++ b/linux-aarch64/crypto/modes/ghashv8-armx.S
@@ -0,0 +1,115 @@
+#include "arm_arch.h"
+
+.text
+.arch armv8-a+crypto
+.global gcm_init_v8
+.type gcm_init_v8,%function
+.align 4
+gcm_init_v8:
+ ld1 {v17.2d},[x1] //load H
+ movi v16.16b,#0xe1
+ ext v3.16b,v17.16b,v17.16b,#8
+ shl v16.2d,v16.2d,#57
+ ushr v18.2d,v16.2d,#63
+ ext v16.16b,v18.16b,v16.16b,#8 //t0=0xc2....01
+ dup v17.4s,v17.s[1]
+ ushr v19.2d,v3.2d,#63
+ sshr v17.4s,v17.4s,#31 //broadcast carry bit
+ and v19.16b,v19.16b,v16.16b
+ shl v3.2d,v3.2d,#1
+ ext v19.16b,v19.16b,v19.16b,#8
+ and v16.16b,v16.16b,v17.16b
+ orr v3.16b,v3.16b,v19.16b //H<<<=1
+ eor v3.16b,v3.16b,v16.16b //twisted H
+ st1 {v3.2d},[x0]
+
+ ret
+.size gcm_init_v8,.-gcm_init_v8
+
+.global gcm_gmult_v8
+.type gcm_gmult_v8,%function
+.align 4
+gcm_gmult_v8:
+ ld1 {v17.2d},[x0] //load Xi
+ movi v19.16b,#0xe1
+ ld1 {v20.2d},[x1] //load twisted H
+ shl v19.2d,v19.2d,#57
+#ifndef __ARMEB__
+ rev64 v17.16b,v17.16b
+#endif
+ ext v21.16b,v20.16b,v20.16b,#8
+ mov x3,#0
+ ext v3.16b,v17.16b,v17.16b,#8
+ mov x12,#0
+ eor v21.16b,v21.16b,v20.16b //Karatsuba pre-processing
+ mov x2,x0
+ b .Lgmult_v8
+.size gcm_gmult_v8,.-gcm_gmult_v8
+
+.global gcm_ghash_v8
+.type gcm_ghash_v8,%function
+.align 4
+gcm_ghash_v8:
+ ld1 {v0.2d},[x0] //load [rotated] Xi
+ subs x3,x3,#16
+ movi v19.16b,#0xe1
+ mov x12,#16
+ ld1 {v20.2d},[x1] //load twisted H
+ csel x12,xzr,x12,eq
+ ext v0.16b,v0.16b,v0.16b,#8
+ shl v19.2d,v19.2d,#57
+ ld1 {v17.2d},[x2],x12 //load [rotated] inp
+ ext v21.16b,v20.16b,v20.16b,#8
+#ifndef __ARMEB__
+ rev64 v0.16b,v0.16b
+ rev64 v17.16b,v17.16b
+#endif
+ eor v21.16b,v21.16b,v20.16b //Karatsuba pre-processing
+ ext v3.16b,v17.16b,v17.16b,#8
+ b .Loop_v8
+
+.align 4
+.Loop_v8:
+ ext v18.16b,v0.16b,v0.16b,#8
+ eor v3.16b,v3.16b,v0.16b //inp^=Xi
+ eor v17.16b,v17.16b,v18.16b //v17.16b is rotated inp^Xi
+
+.Lgmult_v8:
+ pmull v0.1q,v20.1d,v3.1d //H.lo·Xi.lo
+ eor v17.16b,v17.16b,v3.16b //Karatsuba pre-processing
+ pmull2 v2.1q,v20.2d,v3.2d //H.hi·Xi.hi
+ subs x3,x3,#16
+ pmull v1.1q,v21.1d,v17.1d //(H.lo+H.hi)·(Xi.lo+Xi.hi)
+ csel x12,xzr,x12,eq
+
+ ext v17.16b,v0.16b,v2.16b,#8 //Karatsuba post-processing
+ eor v18.16b,v0.16b,v2.16b
+ eor v1.16b,v1.16b,v17.16b
+ ld1 {v17.2d},[x2],x12 //load [rotated] inp
+ eor v1.16b,v1.16b,v18.16b
+ pmull v18.1q,v0.1d,v19.1d //1st phase
+
+ ins v2.d[0],v1.d[1]
+ ins v1.d[1],v0.d[0]
+#ifndef __ARMEB__
+ rev64 v17.16b,v17.16b
+#endif
+ eor v0.16b,v1.16b,v18.16b
+ ext v3.16b,v17.16b,v17.16b,#8
+
+ ext v18.16b,v0.16b,v0.16b,#8 //2nd phase
+ pmull v0.1q,v0.1d,v19.1d
+ eor v18.16b,v18.16b,v2.16b
+ eor v0.16b,v0.16b,v18.16b
+ b.hs .Loop_v8
+
+#ifndef __ARMEB__
+ rev64 v0.16b,v0.16b
+#endif
+ ext v0.16b,v0.16b,v0.16b,#8
+ st1 {v0.2d},[x0] //write out Xi
+
+ ret
+.size gcm_ghash_v8,.-gcm_ghash_v8
+.asciz "GHASH for ARMv8, CRYPTOGAMS by <appro@openssl.org>"
+.align 2
diff --git a/linux-aarch64/crypto/sha/sha1-armv8.S b/linux-aarch64/crypto/sha/sha1-armv8.S
new file mode 100644
index 0000000..f9d1262
--- /dev/null
+++ b/linux-aarch64/crypto/sha/sha1-armv8.S
@@ -0,0 +1,1211 @@
+#include "arm_arch.h"
+
+.text
+
+.globl sha1_block_data_order
+.type sha1_block_data_order,%function
+.align 6
+sha1_block_data_order:
+ ldr x16,.LOPENSSL_armcap_P
+ adr x17,.LOPENSSL_armcap_P
+ add x16,x16,x17
+ ldr w16,[x16]
+ tst w16,#ARMV8_SHA1
+ b.ne .Lv8_entry
+
+ stp x29,x30,[sp,#-96]!
+ add x29,sp,#0
+ stp x19,x20,[sp,#16]
+ stp x21,x22,[sp,#32]
+ stp x23,x24,[sp,#48]
+ stp x25,x26,[sp,#64]
+ stp x27,x28,[sp,#80]
+
+ ldp w20,w21,[x0]
+ ldp w22,w23,[x0,#8]
+ ldr w24,[x0,#16]
+
+.Loop:
+ ldr x3,[x1],#64
+ movz w28,#0x7999
+ sub x2,x2,#1
+ movk w28,#0x5a82,lsl#16
+#ifdef __ARMEB__
+ ror x3,x3,#32
+#else
+ rev32 x3,x3
+#endif
+ add w24,w24,w28 // warm it up
+ add w24,w24,w3
+ lsr x4,x3,#32
+ ldr x5,[x1,#-56]
+ bic w25,w23,w21
+ and w26,w22,w21
+ ror w27,w20,#27
+ add w23,w23,w28 // future e+=K
+ orr w25,w25,w26
+ add w24,w24,w27 // e+=rot(a,5)
+ ror w21,w21,#2
+ add w23,w23,w4 // future e+=X[i]
+ add w24,w24,w25 // e+=F(b,c,d)
+#ifdef __ARMEB__
+ ror x5,x5,#32
+#else
+ rev32 x5,x5
+#endif
+ bic w25,w22,w20
+ and w26,w21,w20
+ ror w27,w24,#27
+ add w22,w22,w28 // future e+=K
+ orr w25,w25,w26
+ add w23,w23,w27 // e+=rot(a,5)
+ ror w20,w20,#2
+ add w22,w22,w5 // future e+=X[i]
+ add w23,w23,w25 // e+=F(b,c,d)
+ lsr x6,x5,#32
+ ldr x7,[x1,#-48]
+ bic w25,w21,w24
+ and w26,w20,w24
+ ror w27,w23,#27
+ add w21,w21,w28 // future e+=K
+ orr w25,w25,w26
+ add w22,w22,w27 // e+=rot(a,5)
+ ror w24,w24,#2
+ add w21,w21,w6 // future e+=X[i]
+ add w22,w22,w25 // e+=F(b,c,d)
+#ifdef __ARMEB__
+ ror x7,x7,#32
+#else
+ rev32 x7,x7
+#endif
+ bic w25,w20,w23
+ and w26,w24,w23
+ ror w27,w22,#27
+ add w20,w20,w28 // future e+=K
+ orr w25,w25,w26
+ add w21,w21,w27 // e+=rot(a,5)
+ ror w23,w23,#2
+ add w20,w20,w7 // future e+=X[i]
+ add w21,w21,w25 // e+=F(b,c,d)
+ lsr x8,x7,#32
+ ldr x9,[x1,#-40]
+ bic w25,w24,w22
+ and w26,w23,w22
+ ror w27,w21,#27
+ add w24,w24,w28 // future e+=K
+ orr w25,w25,w26
+ add w20,w20,w27 // e+=rot(a,5)
+ ror w22,w22,#2
+ add w24,w24,w8 // future e+=X[i]
+ add w20,w20,w25 // e+=F(b,c,d)
+#ifdef __ARMEB__
+ ror x9,x9,#32
+#else
+ rev32 x9,x9
+#endif
+ bic w25,w23,w21
+ and w26,w22,w21
+ ror w27,w20,#27
+ add w23,w23,w28 // future e+=K
+ orr w25,w25,w26
+ add w24,w24,w27 // e+=rot(a,5)
+ ror w21,w21,#2
+ add w23,w23,w9 // future e+=X[i]
+ add w24,w24,w25 // e+=F(b,c,d)
+ lsr x10,x9,#32
+ ldr x11,[x1,#-32]
+ bic w25,w22,w20
+ and w26,w21,w20
+ ror w27,w24,#27
+ add w22,w22,w28 // future e+=K
+ orr w25,w25,w26
+ add w23,w23,w27 // e+=rot(a,5)
+ ror w20,w20,#2
+ add w22,w22,w10 // future e+=X[i]
+ add w23,w23,w25 // e+=F(b,c,d)
+#ifdef __ARMEB__
+ ror x11,x11,#32
+#else
+ rev32 x11,x11
+#endif
+ bic w25,w21,w24
+ and w26,w20,w24
+ ror w27,w23,#27
+ add w21,w21,w28 // future e+=K
+ orr w25,w25,w26
+ add w22,w22,w27 // e+=rot(a,5)
+ ror w24,w24,#2
+ add w21,w21,w11 // future e+=X[i]
+ add w22,w22,w25 // e+=F(b,c,d)
+ lsr x12,x11,#32
+ ldr x13,[x1,#-24]
+ bic w25,w20,w23
+ and w26,w24,w23
+ ror w27,w22,#27
+ add w20,w20,w28 // future e+=K
+ orr w25,w25,w26
+ add w21,w21,w27 // e+=rot(a,5)
+ ror w23,w23,#2
+ add w20,w20,w12 // future e+=X[i]
+ add w21,w21,w25 // e+=F(b,c,d)
+#ifdef __ARMEB__
+ ror x13,x13,#32
+#else
+ rev32 x13,x13
+#endif
+ bic w25,w24,w22
+ and w26,w23,w22
+ ror w27,w21,#27
+ add w24,w24,w28 // future e+=K
+ orr w25,w25,w26
+ add w20,w20,w27 // e+=rot(a,5)
+ ror w22,w22,#2
+ add w24,w24,w13 // future e+=X[i]
+ add w20,w20,w25 // e+=F(b,c,d)
+ lsr x14,x13,#32
+ ldr x15,[x1,#-16]
+ bic w25,w23,w21
+ and w26,w22,w21
+ ror w27,w20,#27
+ add w23,w23,w28 // future e+=K
+ orr w25,w25,w26
+ add w24,w24,w27 // e+=rot(a,5)
+ ror w21,w21,#2
+ add w23,w23,w14 // future e+=X[i]
+ add w24,w24,w25 // e+=F(b,c,d)
+#ifdef __ARMEB__
+ ror x15,x15,#32
+#else
+ rev32 x15,x15
+#endif
+ bic w25,w22,w20
+ and w26,w21,w20
+ ror w27,w24,#27
+ add w22,w22,w28 // future e+=K
+ orr w25,w25,w26
+ add w23,w23,w27 // e+=rot(a,5)
+ ror w20,w20,#2
+ add w22,w22,w15 // future e+=X[i]
+ add w23,w23,w25 // e+=F(b,c,d)
+ lsr x16,x15,#32
+ ldr x17,[x1,#-8]
+ bic w25,w21,w24
+ and w26,w20,w24
+ ror w27,w23,#27
+ add w21,w21,w28 // future e+=K
+ orr w25,w25,w26
+ add w22,w22,w27 // e+=rot(a,5)
+ ror w24,w24,#2
+ add w21,w21,w16 // future e+=X[i]
+ add w22,w22,w25 // e+=F(b,c,d)
+#ifdef __ARMEB__
+ ror x17,x17,#32
+#else
+ rev32 x17,x17
+#endif
+ bic w25,w20,w23
+ and w26,w24,w23
+ ror w27,w22,#27
+ add w20,w20,w28 // future e+=K
+ orr w25,w25,w26
+ add w21,w21,w27 // e+=rot(a,5)
+ ror w23,w23,#2
+ add w20,w20,w17 // future e+=X[i]
+ add w21,w21,w25 // e+=F(b,c,d)
+ lsr x19,x17,#32
+ eor w3,w3,w5
+ bic w25,w24,w22
+ and w26,w23,w22
+ ror w27,w21,#27
+ eor w3,w3,w11
+ add w24,w24,w28 // future e+=K
+ orr w25,w25,w26
+ add w20,w20,w27 // e+=rot(a,5)
+ eor w3,w3,w16
+ ror w22,w22,#2
+ add w24,w24,w19 // future e+=X[i]
+ add w20,w20,w25 // e+=F(b,c,d)
+ ror w3,w3,#31
+ eor w4,w4,w6
+ bic w25,w23,w21
+ and w26,w22,w21
+ ror w27,w20,#27
+ eor w4,w4,w12
+ add w23,w23,w28 // future e+=K
+ orr w25,w25,w26
+ add w24,w24,w27 // e+=rot(a,5)
+ eor w4,w4,w17
+ ror w21,w21,#2
+ add w23,w23,w3 // future e+=X[i]
+ add w24,w24,w25 // e+=F(b,c,d)
+ ror w4,w4,#31
+ eor w5,w5,w7
+ bic w25,w22,w20
+ and w26,w21,w20
+ ror w27,w24,#27
+ eor w5,w5,w13
+ add w22,w22,w28 // future e+=K
+ orr w25,w25,w26
+ add w23,w23,w27 // e+=rot(a,5)
+ eor w5,w5,w19
+ ror w20,w20,#2
+ add w22,w22,w4 // future e+=X[i]
+ add w23,w23,w25 // e+=F(b,c,d)
+ ror w5,w5,#31
+ eor w6,w6,w8
+ bic w25,w21,w24
+ and w26,w20,w24
+ ror w27,w23,#27
+ eor w6,w6,w14
+ add w21,w21,w28 // future e+=K
+ orr w25,w25,w26
+ add w22,w22,w27 // e+=rot(a,5)
+ eor w6,w6,w3
+ ror w24,w24,#2
+ add w21,w21,w5 // future e+=X[i]
+ add w22,w22,w25 // e+=F(b,c,d)
+ ror w6,w6,#31
+ eor w7,w7,w9
+ bic w25,w20,w23
+ and w26,w24,w23
+ ror w27,w22,#27
+ eor w7,w7,w15
+ add w20,w20,w28 // future e+=K
+ orr w25,w25,w26
+ add w21,w21,w27 // e+=rot(a,5)
+ eor w7,w7,w4
+ ror w23,w23,#2
+ add w20,w20,w6 // future e+=X[i]
+ add w21,w21,w25 // e+=F(b,c,d)
+ ror w7,w7,#31
+ movz w28,#0xeba1
+ movk w28,#0x6ed9,lsl#16
+ eor w8,w8,w10
+ bic w25,w24,w22
+ and w26,w23,w22
+ ror w27,w21,#27
+ eor w8,w8,w16
+ add w24,w24,w28 // future e+=K
+ orr w25,w25,w26
+ add w20,w20,w27 // e+=rot(a,5)
+ eor w8,w8,w5
+ ror w22,w22,#2
+ add w24,w24,w7 // future e+=X[i]
+ add w20,w20,w25 // e+=F(b,c,d)
+ ror w8,w8,#31
+ eor w9,w9,w11
+ eor w25,w23,w21
+ ror w27,w20,#27
+ add w23,w23,w28 // future e+=K
+ eor w9,w9,w17
+ eor w25,w25,w22
+ add w24,w24,w27 // e+=rot(a,5)
+ ror w21,w21,#2
+ eor w9,w9,w6
+ add w23,w23,w8 // future e+=X[i]
+ add w24,w24,w25 // e+=F(b,c,d)
+ ror w9,w9,#31
+ eor w10,w10,w12
+ eor w25,w22,w20
+ ror w27,w24,#27
+ add w22,w22,w28 // future e+=K
+ eor w10,w10,w19
+ eor w25,w25,w21
+ add w23,w23,w27 // e+=rot(a,5)
+ ror w20,w20,#2
+ eor w10,w10,w7
+ add w22,w22,w9 // future e+=X[i]
+ add w23,w23,w25 // e+=F(b,c,d)
+ ror w10,w10,#31
+ eor w11,w11,w13
+ eor w25,w21,w24
+ ror w27,w23,#27
+ add w21,w21,w28 // future e+=K
+ eor w11,w11,w3
+ eor w25,w25,w20
+ add w22,w22,w27 // e+=rot(a,5)
+ ror w24,w24,#2
+ eor w11,w11,w8
+ add w21,w21,w10 // future e+=X[i]
+ add w22,w22,w25 // e+=F(b,c,d)
+ ror w11,w11,#31
+ eor w12,w12,w14
+ eor w25,w20,w23
+ ror w27,w22,#27
+ add w20,w20,w28 // future e+=K
+ eor w12,w12,w4
+ eor w25,w25,w24
+ add w21,w21,w27 // e+=rot(a,5)
+ ror w23,w23,#2
+ eor w12,w12,w9
+ add w20,w20,w11 // future e+=X[i]
+ add w21,w21,w25 // e+=F(b,c,d)
+ ror w12,w12,#31
+ eor w13,w13,w15
+ eor w25,w24,w22
+ ror w27,w21,#27
+ add w24,w24,w28 // future e+=K
+ eor w13,w13,w5
+ eor w25,w25,w23
+ add w20,w20,w27 // e+=rot(a,5)
+ ror w22,w22,#2
+ eor w13,w13,w10
+ add w24,w24,w12 // future e+=X[i]
+ add w20,w20,w25 // e+=F(b,c,d)
+ ror w13,w13,#31
+ eor w14,w14,w16
+ eor w25,w23,w21
+ ror w27,w20,#27
+ add w23,w23,w28 // future e+=K
+ eor w14,w14,w6
+ eor w25,w25,w22
+ add w24,w24,w27 // e+=rot(a,5)
+ ror w21,w21,#2
+ eor w14,w14,w11
+ add w23,w23,w13 // future e+=X[i]
+ add w24,w24,w25 // e+=F(b,c,d)
+ ror w14,w14,#31
+ eor w15,w15,w17
+ eor w25,w22,w20
+ ror w27,w24,#27
+ add w22,w22,w28 // future e+=K
+ eor w15,w15,w7
+ eor w25,w25,w21
+ add w23,w23,w27 // e+=rot(a,5)
+ ror w20,w20,#2
+ eor w15,w15,w12
+ add w22,w22,w14 // future e+=X[i]
+ add w23,w23,w25 // e+=F(b,c,d)
+ ror w15,w15,#31
+ eor w16,w16,w19
+ eor w25,w21,w24
+ ror w27,w23,#27
+ add w21,w21,w28 // future e+=K
+ eor w16,w16,w8
+ eor w25,w25,w20
+ add w22,w22,w27 // e+=rot(a,5)
+ ror w24,w24,#2
+ eor w16,w16,w13
+ add w21,w21,w15 // future e+=X[i]
+ add w22,w22,w25 // e+=F(b,c,d)
+ ror w16,w16,#31
+ eor w17,w17,w3
+ eor w25,w20,w23
+ ror w27,w22,#27
+ add w20,w20,w28 // future e+=K
+ eor w17,w17,w9
+ eor w25,w25,w24
+ add w21,w21,w27 // e+=rot(a,5)
+ ror w23,w23,#2
+ eor w17,w17,w14
+ add w20,w20,w16 // future e+=X[i]
+ add w21,w21,w25 // e+=F(b,c,d)
+ ror w17,w17,#31
+ eor w19,w19,w4
+ eor w25,w24,w22
+ ror w27,w21,#27
+ add w24,w24,w28 // future e+=K
+ eor w19,w19,w10
+ eor w25,w25,w23
+ add w20,w20,w27 // e+=rot(a,5)
+ ror w22,w22,#2
+ eor w19,w19,w15
+ add w24,w24,w17 // future e+=X[i]
+ add w20,w20,w25 // e+=F(b,c,d)
+ ror w19,w19,#31
+ eor w3,w3,w5
+ eor w25,w23,w21
+ ror w27,w20,#27
+ add w23,w23,w28 // future e+=K
+ eor w3,w3,w11
+ eor w25,w25,w22
+ add w24,w24,w27 // e+=rot(a,5)
+ ror w21,w21,#2
+ eor w3,w3,w16
+ add w23,w23,w19 // future e+=X[i]
+ add w24,w24,w25 // e+=F(b,c,d)
+ ror w3,w3,#31
+ eor w4,w4,w6
+ eor w25,w22,w20
+ ror w27,w24,#27
+ add w22,w22,w28 // future e+=K
+ eor w4,w4,w12
+ eor w25,w25,w21
+ add w23,w23,w27 // e+=rot(a,5)
+ ror w20,w20,#2
+ eor w4,w4,w17
+ add w22,w22,w3 // future e+=X[i]
+ add w23,w23,w25 // e+=F(b,c,d)
+ ror w4,w4,#31
+ eor w5,w5,w7
+ eor w25,w21,w24
+ ror w27,w23,#27
+ add w21,w21,w28 // future e+=K
+ eor w5,w5,w13
+ eor w25,w25,w20
+ add w22,w22,w27 // e+=rot(a,5)
+ ror w24,w24,#2
+ eor w5,w5,w19
+ add w21,w21,w4 // future e+=X[i]
+ add w22,w22,w25 // e+=F(b,c,d)
+ ror w5,w5,#31
+ eor w6,w6,w8
+ eor w25,w20,w23
+ ror w27,w22,#27
+ add w20,w20,w28 // future e+=K
+ eor w6,w6,w14
+ eor w25,w25,w24
+ add w21,w21,w27 // e+=rot(a,5)
+ ror w23,w23,#2
+ eor w6,w6,w3
+ add w20,w20,w5 // future e+=X[i]
+ add w21,w21,w25 // e+=F(b,c,d)
+ ror w6,w6,#31
+ eor w7,w7,w9
+ eor w25,w24,w22
+ ror w27,w21,#27
+ add w24,w24,w28 // future e+=K
+ eor w7,w7,w15
+ eor w25,w25,w23
+ add w20,w20,w27 // e+=rot(a,5)
+ ror w22,w22,#2
+ eor w7,w7,w4
+ add w24,w24,w6 // future e+=X[i]
+ add w20,w20,w25 // e+=F(b,c,d)
+ ror w7,w7,#31
+ eor w8,w8,w10
+ eor w25,w23,w21
+ ror w27,w20,#27
+ add w23,w23,w28 // future e+=K
+ eor w8,w8,w16
+ eor w25,w25,w22
+ add w24,w24,w27 // e+=rot(a,5)
+ ror w21,w21,#2
+ eor w8,w8,w5
+ add w23,w23,w7 // future e+=X[i]
+ add w24,w24,w25 // e+=F(b,c,d)
+ ror w8,w8,#31
+ eor w9,w9,w11
+ eor w25,w22,w20
+ ror w27,w24,#27
+ add w22,w22,w28 // future e+=K
+ eor w9,w9,w17
+ eor w25,w25,w21
+ add w23,w23,w27 // e+=rot(a,5)
+ ror w20,w20,#2
+ eor w9,w9,w6
+ add w22,w22,w8 // future e+=X[i]
+ add w23,w23,w25 // e+=F(b,c,d)
+ ror w9,w9,#31
+ eor w10,w10,w12
+ eor w25,w21,w24
+ ror w27,w23,#27
+ add w21,w21,w28 // future e+=K
+ eor w10,w10,w19
+ eor w25,w25,w20
+ add w22,w22,w27 // e+=rot(a,5)
+ ror w24,w24,#2
+ eor w10,w10,w7
+ add w21,w21,w9 // future e+=X[i]
+ add w22,w22,w25 // e+=F(b,c,d)
+ ror w10,w10,#31
+ eor w11,w11,w13
+ eor w25,w20,w23
+ ror w27,w22,#27
+ add w20,w20,w28 // future e+=K
+ eor w11,w11,w3
+ eor w25,w25,w24
+ add w21,w21,w27 // e+=rot(a,5)
+ ror w23,w23,#2
+ eor w11,w11,w8
+ add w20,w20,w10 // future e+=X[i]
+ add w21,w21,w25 // e+=F(b,c,d)
+ ror w11,w11,#31
+ movz w28,#0xbcdc
+ movk w28,#0x8f1b,lsl#16
+ eor w12,w12,w14
+ eor w25,w24,w22
+ ror w27,w21,#27
+ add w24,w24,w28 // future e+=K
+ eor w12,w12,w4
+ eor w25,w25,w23
+ add w20,w20,w27 // e+=rot(a,5)
+ ror w22,w22,#2
+ eor w12,w12,w9
+ add w24,w24,w11 // future e+=X[i]
+ add w20,w20,w25 // e+=F(b,c,d)
+ ror w12,w12,#31
+ orr w25,w21,w22
+ and w26,w21,w22
+ eor w13,w13,w15
+ ror w27,w20,#27
+ and w25,w25,w23
+ add w23,w23,w28 // future e+=K
+ eor w13,w13,w5
+ add w24,w24,w27 // e+=rot(a,5)
+ orr w25,w25,w26
+ ror w21,w21,#2
+ eor w13,w13,w10
+ add w23,w23,w12 // future e+=X[i]
+ add w24,w24,w25 // e+=F(b,c,d)
+ ror w13,w13,#31
+ orr w25,w20,w21
+ and w26,w20,w21
+ eor w14,w14,w16
+ ror w27,w24,#27
+ and w25,w25,w22
+ add w22,w22,w28 // future e+=K
+ eor w14,w14,w6
+ add w23,w23,w27 // e+=rot(a,5)
+ orr w25,w25,w26
+ ror w20,w20,#2
+ eor w14,w14,w11
+ add w22,w22,w13 // future e+=X[i]
+ add w23,w23,w25 // e+=F(b,c,d)
+ ror w14,w14,#31
+ orr w25,w24,w20
+ and w26,w24,w20
+ eor w15,w15,w17
+ ror w27,w23,#27
+ and w25,w25,w21
+ add w21,w21,w28 // future e+=K
+ eor w15,w15,w7
+ add w22,w22,w27 // e+=rot(a,5)
+ orr w25,w25,w26
+ ror w24,w24,#2
+ eor w15,w15,w12
+ add w21,w21,w14 // future e+=X[i]
+ add w22,w22,w25 // e+=F(b,c,d)
+ ror w15,w15,#31
+ orr w25,w23,w24
+ and w26,w23,w24
+ eor w16,w16,w19
+ ror w27,w22,#27
+ and w25,w25,w20
+ add w20,w20,w28 // future e+=K
+ eor w16,w16,w8
+ add w21,w21,w27 // e+=rot(a,5)
+ orr w25,w25,w26
+ ror w23,w23,#2
+ eor w16,w16,w13
+ add w20,w20,w15 // future e+=X[i]
+ add w21,w21,w25 // e+=F(b,c,d)
+ ror w16,w16,#31
+ orr w25,w22,w23
+ and w26,w22,w23
+ eor w17,w17,w3
+ ror w27,w21,#27
+ and w25,w25,w24
+ add w24,w24,w28 // future e+=K
+ eor w17,w17,w9
+ add w20,w20,w27 // e+=rot(a,5)
+ orr w25,w25,w26
+ ror w22,w22,#2
+ eor w17,w17,w14
+ add w24,w24,w16 // future e+=X[i]
+ add w20,w20,w25 // e+=F(b,c,d)
+ ror w17,w17,#31
+ orr w25,w21,w22
+ and w26,w21,w22
+ eor w19,w19,w4
+ ror w27,w20,#27
+ and w25,w25,w23
+ add w23,w23,w28 // future e+=K
+ eor w19,w19,w10
+ add w24,w24,w27 // e+=rot(a,5)
+ orr w25,w25,w26
+ ror w21,w21,#2
+ eor w19,w19,w15
+ add w23,w23,w17 // future e+=X[i]
+ add w24,w24,w25 // e+=F(b,c,d)
+ ror w19,w19,#31
+ orr w25,w20,w21
+ and w26,w20,w21
+ eor w3,w3,w5
+ ror w27,w24,#27
+ and w25,w25,w22
+ add w22,w22,w28 // future e+=K
+ eor w3,w3,w11
+ add w23,w23,w27 // e+=rot(a,5)
+ orr w25,w25,w26
+ ror w20,w20,#2
+ eor w3,w3,w16
+ add w22,w22,w19 // future e+=X[i]
+ add w23,w23,w25 // e+=F(b,c,d)
+ ror w3,w3,#31
+ orr w25,w24,w20
+ and w26,w24,w20
+ eor w4,w4,w6
+ ror w27,w23,#27
+ and w25,w25,w21
+ add w21,w21,w28 // future e+=K
+ eor w4,w4,w12
+ add w22,w22,w27 // e+=rot(a,5)
+ orr w25,w25,w26
+ ror w24,w24,#2
+ eor w4,w4,w17
+ add w21,w21,w3 // future e+=X[i]
+ add w22,w22,w25 // e+=F(b,c,d)
+ ror w4,w4,#31
+ orr w25,w23,w24
+ and w26,w23,w24
+ eor w5,w5,w7
+ ror w27,w22,#27
+ and w25,w25,w20
+ add w20,w20,w28 // future e+=K
+ eor w5,w5,w13
+ add w21,w21,w27 // e+=rot(a,5)
+ orr w25,w25,w26
+ ror w23,w23,#2
+ eor w5,w5,w19
+ add w20,w20,w4 // future e+=X[i]
+ add w21,w21,w25 // e+=F(b,c,d)
+ ror w5,w5,#31
+ orr w25,w22,w23
+ and w26,w22,w23
+ eor w6,w6,w8
+ ror w27,w21,#27
+ and w25,w25,w24
+ add w24,w24,w28 // future e+=K
+ eor w6,w6,w14
+ add w20,w20,w27 // e+=rot(a,5)
+ orr w25,w25,w26
+ ror w22,w22,#2
+ eor w6,w6,w3
+ add w24,w24,w5 // future e+=X[i]
+ add w20,w20,w25 // e+=F(b,c,d)
+ ror w6,w6,#31
+ orr w25,w21,w22
+ and w26,w21,w22
+ eor w7,w7,w9
+ ror w27,w20,#27
+ and w25,w25,w23
+ add w23,w23,w28 // future e+=K
+ eor w7,w7,w15
+ add w24,w24,w27 // e+=rot(a,5)
+ orr w25,w25,w26
+ ror w21,w21,#2
+ eor w7,w7,w4
+ add w23,w23,w6 // future e+=X[i]
+ add w24,w24,w25 // e+=F(b,c,d)
+ ror w7,w7,#31
+ orr w25,w20,w21
+ and w26,w20,w21
+ eor w8,w8,w10
+ ror w27,w24,#27
+ and w25,w25,w22
+ add w22,w22,w28 // future e+=K
+ eor w8,w8,w16
+ add w23,w23,w27 // e+=rot(a,5)
+ orr w25,w25,w26
+ ror w20,w20,#2
+ eor w8,w8,w5
+ add w22,w22,w7 // future e+=X[i]
+ add w23,w23,w25 // e+=F(b,c,d)
+ ror w8,w8,#31
+ orr w25,w24,w20
+ and w26,w24,w20
+ eor w9,w9,w11
+ ror w27,w23,#27
+ and w25,w25,w21
+ add w21,w21,w28 // future e+=K
+ eor w9,w9,w17
+ add w22,w22,w27 // e+=rot(a,5)
+ orr w25,w25,w26
+ ror w24,w24,#2
+ eor w9,w9,w6
+ add w21,w21,w8 // future e+=X[i]
+ add w22,w22,w25 // e+=F(b,c,d)
+ ror w9,w9,#31
+ orr w25,w23,w24
+ and w26,w23,w24
+ eor w10,w10,w12
+ ror w27,w22,#27
+ and w25,w25,w20
+ add w20,w20,w28 // future e+=K
+ eor w10,w10,w19
+ add w21,w21,w27 // e+=rot(a,5)
+ orr w25,w25,w26
+ ror w23,w23,#2
+ eor w10,w10,w7
+ add w20,w20,w9 // future e+=X[i]
+ add w21,w21,w25 // e+=F(b,c,d)
+ ror w10,w10,#31
+ orr w25,w22,w23
+ and w26,w22,w23
+ eor w11,w11,w13
+ ror w27,w21,#27
+ and w25,w25,w24
+ add w24,w24,w28 // future e+=K
+ eor w11,w11,w3
+ add w20,w20,w27 // e+=rot(a,5)
+ orr w25,w25,w26
+ ror w22,w22,#2
+ eor w11,w11,w8
+ add w24,w24,w10 // future e+=X[i]
+ add w20,w20,w25 // e+=F(b,c,d)
+ ror w11,w11,#31
+ orr w25,w21,w22
+ and w26,w21,w22
+ eor w12,w12,w14
+ ror w27,w20,#27
+ and w25,w25,w23
+ add w23,w23,w28 // future e+=K
+ eor w12,w12,w4
+ add w24,w24,w27 // e+=rot(a,5)
+ orr w25,w25,w26
+ ror w21,w21,#2
+ eor w12,w12,w9
+ add w23,w23,w11 // future e+=X[i]
+ add w24,w24,w25 // e+=F(b,c,d)
+ ror w12,w12,#31
+ orr w25,w20,w21
+ and w26,w20,w21
+ eor w13,w13,w15
+ ror w27,w24,#27
+ and w25,w25,w22
+ add w22,w22,w28 // future e+=K
+ eor w13,w13,w5
+ add w23,w23,w27 // e+=rot(a,5)
+ orr w25,w25,w26
+ ror w20,w20,#2
+ eor w13,w13,w10
+ add w22,w22,w12 // future e+=X[i]
+ add w23,w23,w25 // e+=F(b,c,d)
+ ror w13,w13,#31
+ orr w25,w24,w20
+ and w26,w24,w20
+ eor w14,w14,w16
+ ror w27,w23,#27
+ and w25,w25,w21
+ add w21,w21,w28 // future e+=K
+ eor w14,w14,w6
+ add w22,w22,w27 // e+=rot(a,5)
+ orr w25,w25,w26
+ ror w24,w24,#2
+ eor w14,w14,w11
+ add w21,w21,w13 // future e+=X[i]
+ add w22,w22,w25 // e+=F(b,c,d)
+ ror w14,w14,#31
+ orr w25,w23,w24
+ and w26,w23,w24
+ eor w15,w15,w17
+ ror w27,w22,#27
+ and w25,w25,w20
+ add w20,w20,w28 // future e+=K
+ eor w15,w15,w7
+ add w21,w21,w27 // e+=rot(a,5)
+ orr w25,w25,w26
+ ror w23,w23,#2
+ eor w15,w15,w12
+ add w20,w20,w14 // future e+=X[i]
+ add w21,w21,w25 // e+=F(b,c,d)
+ ror w15,w15,#31
+ movz w28,#0xc1d6
+ movk w28,#0xca62,lsl#16
+ orr w25,w22,w23
+ and w26,w22,w23
+ eor w16,w16,w19
+ ror w27,w21,#27
+ and w25,w25,w24
+ add w24,w24,w28 // future e+=K
+ eor w16,w16,w8
+ add w20,w20,w27 // e+=rot(a,5)
+ orr w25,w25,w26
+ ror w22,w22,#2
+ eor w16,w16,w13
+ add w24,w24,w15 // future e+=X[i]
+ add w20,w20,w25 // e+=F(b,c,d)
+ ror w16,w16,#31
+ eor w17,w17,w3
+ eor w25,w23,w21
+ ror w27,w20,#27
+ add w23,w23,w28 // future e+=K
+ eor w17,w17,w9
+ eor w25,w25,w22
+ add w24,w24,w27 // e+=rot(a,5)
+ ror w21,w21,#2
+ eor w17,w17,w14
+ add w23,w23,w16 // future e+=X[i]
+ add w24,w24,w25 // e+=F(b,c,d)
+ ror w17,w17,#31
+ eor w19,w19,w4
+ eor w25,w22,w20
+ ror w27,w24,#27
+ add w22,w22,w28 // future e+=K
+ eor w19,w19,w10
+ eor w25,w25,w21
+ add w23,w23,w27 // e+=rot(a,5)
+ ror w20,w20,#2
+ eor w19,w19,w15
+ add w22,w22,w17 // future e+=X[i]
+ add w23,w23,w25 // e+=F(b,c,d)
+ ror w19,w19,#31
+ eor w3,w3,w5
+ eor w25,w21,w24
+ ror w27,w23,#27
+ add w21,w21,w28 // future e+=K
+ eor w3,w3,w11
+ eor w25,w25,w20
+ add w22,w22,w27 // e+=rot(a,5)
+ ror w24,w24,#2
+ eor w3,w3,w16
+ add w21,w21,w19 // future e+=X[i]
+ add w22,w22,w25 // e+=F(b,c,d)
+ ror w3,w3,#31
+ eor w4,w4,w6
+ eor w25,w20,w23
+ ror w27,w22,#27
+ add w20,w20,w28 // future e+=K
+ eor w4,w4,w12
+ eor w25,w25,w24
+ add w21,w21,w27 // e+=rot(a,5)
+ ror w23,w23,#2
+ eor w4,w4,w17
+ add w20,w20,w3 // future e+=X[i]
+ add w21,w21,w25 // e+=F(b,c,d)
+ ror w4,w4,#31
+ eor w5,w5,w7
+ eor w25,w24,w22
+ ror w27,w21,#27
+ add w24,w24,w28 // future e+=K
+ eor w5,w5,w13
+ eor w25,w25,w23
+ add w20,w20,w27 // e+=rot(a,5)
+ ror w22,w22,#2
+ eor w5,w5,w19
+ add w24,w24,w4 // future e+=X[i]
+ add w20,w20,w25 // e+=F(b,c,d)
+ ror w5,w5,#31
+ eor w6,w6,w8
+ eor w25,w23,w21
+ ror w27,w20,#27
+ add w23,w23,w28 // future e+=K
+ eor w6,w6,w14
+ eor w25,w25,w22
+ add w24,w24,w27 // e+=rot(a,5)
+ ror w21,w21,#2
+ eor w6,w6,w3
+ add w23,w23,w5 // future e+=X[i]
+ add w24,w24,w25 // e+=F(b,c,d)
+ ror w6,w6,#31
+ eor w7,w7,w9
+ eor w25,w22,w20
+ ror w27,w24,#27
+ add w22,w22,w28 // future e+=K
+ eor w7,w7,w15
+ eor w25,w25,w21
+ add w23,w23,w27 // e+=rot(a,5)
+ ror w20,w20,#2
+ eor w7,w7,w4
+ add w22,w22,w6 // future e+=X[i]
+ add w23,w23,w25 // e+=F(b,c,d)
+ ror w7,w7,#31
+ eor w8,w8,w10
+ eor w25,w21,w24
+ ror w27,w23,#27
+ add w21,w21,w28 // future e+=K
+ eor w8,w8,w16
+ eor w25,w25,w20
+ add w22,w22,w27 // e+=rot(a,5)
+ ror w24,w24,#2
+ eor w8,w8,w5
+ add w21,w21,w7 // future e+=X[i]
+ add w22,w22,w25 // e+=F(b,c,d)
+ ror w8,w8,#31
+ eor w9,w9,w11
+ eor w25,w20,w23
+ ror w27,w22,#27
+ add w20,w20,w28 // future e+=K
+ eor w9,w9,w17
+ eor w25,w25,w24
+ add w21,w21,w27 // e+=rot(a,5)
+ ror w23,w23,#2
+ eor w9,w9,w6
+ add w20,w20,w8 // future e+=X[i]
+ add w21,w21,w25 // e+=F(b,c,d)
+ ror w9,w9,#31
+ eor w10,w10,w12
+ eor w25,w24,w22
+ ror w27,w21,#27
+ add w24,w24,w28 // future e+=K
+ eor w10,w10,w19
+ eor w25,w25,w23
+ add w20,w20,w27 // e+=rot(a,5)
+ ror w22,w22,#2
+ eor w10,w10,w7
+ add w24,w24,w9 // future e+=X[i]
+ add w20,w20,w25 // e+=F(b,c,d)
+ ror w10,w10,#31
+ eor w11,w11,w13
+ eor w25,w23,w21
+ ror w27,w20,#27
+ add w23,w23,w28 // future e+=K
+ eor w11,w11,w3
+ eor w25,w25,w22
+ add w24,w24,w27 // e+=rot(a,5)
+ ror w21,w21,#2
+ eor w11,w11,w8
+ add w23,w23,w10 // future e+=X[i]
+ add w24,w24,w25 // e+=F(b,c,d)
+ ror w11,w11,#31
+ eor w12,w12,w14
+ eor w25,w22,w20
+ ror w27,w24,#27
+ add w22,w22,w28 // future e+=K
+ eor w12,w12,w4
+ eor w25,w25,w21
+ add w23,w23,w27 // e+=rot(a,5)
+ ror w20,w20,#2
+ eor w12,w12,w9
+ add w22,w22,w11 // future e+=X[i]
+ add w23,w23,w25 // e+=F(b,c,d)
+ ror w12,w12,#31
+ eor w13,w13,w15
+ eor w25,w21,w24
+ ror w27,w23,#27
+ add w21,w21,w28 // future e+=K
+ eor w13,w13,w5
+ eor w25,w25,w20
+ add w22,w22,w27 // e+=rot(a,5)
+ ror w24,w24,#2
+ eor w13,w13,w10
+ add w21,w21,w12 // future e+=X[i]
+ add w22,w22,w25 // e+=F(b,c,d)
+ ror w13,w13,#31
+ eor w14,w14,w16
+ eor w25,w20,w23
+ ror w27,w22,#27
+ add w20,w20,w28 // future e+=K
+ eor w14,w14,w6
+ eor w25,w25,w24
+ add w21,w21,w27 // e+=rot(a,5)
+ ror w23,w23,#2
+ eor w14,w14,w11
+ add w20,w20,w13 // future e+=X[i]
+ add w21,w21,w25 // e+=F(b,c,d)
+ ror w14,w14,#31
+ eor w15,w15,w17
+ eor w25,w24,w22
+ ror w27,w21,#27
+ add w24,w24,w28 // future e+=K
+ eor w15,w15,w7
+ eor w25,w25,w23
+ add w20,w20,w27 // e+=rot(a,5)
+ ror w22,w22,#2
+ eor w15,w15,w12
+ add w24,w24,w14 // future e+=X[i]
+ add w20,w20,w25 // e+=F(b,c,d)
+ ror w15,w15,#31
+ eor w16,w16,w19
+ eor w25,w23,w21
+ ror w27,w20,#27
+ add w23,w23,w28 // future e+=K
+ eor w16,w16,w8
+ eor w25,w25,w22
+ add w24,w24,w27 // e+=rot(a,5)
+ ror w21,w21,#2
+ eor w16,w16,w13
+ add w23,w23,w15 // future e+=X[i]
+ add w24,w24,w25 // e+=F(b,c,d)
+ ror w16,w16,#31
+ eor w17,w17,w3
+ eor w25,w22,w20
+ ror w27,w24,#27
+ add w22,w22,w28 // future e+=K
+ eor w17,w17,w9
+ eor w25,w25,w21
+ add w23,w23,w27 // e+=rot(a,5)
+ ror w20,w20,#2
+ eor w17,w17,w14
+ add w22,w22,w16 // future e+=X[i]
+ add w23,w23,w25 // e+=F(b,c,d)
+ ror w17,w17,#31
+ eor w19,w19,w4
+ eor w25,w21,w24
+ ror w27,w23,#27
+ add w21,w21,w28 // future e+=K
+ eor w19,w19,w10
+ eor w25,w25,w20
+ add w22,w22,w27 // e+=rot(a,5)
+ ror w24,w24,#2
+ eor w19,w19,w15
+ add w21,w21,w17 // future e+=X[i]
+ add w22,w22,w25 // e+=F(b,c,d)
+ ror w19,w19,#31
+ ldp w4,w5,[x0]
+ eor w25,w20,w23
+ ror w27,w22,#27
+ add w20,w20,w28 // future e+=K
+ eor w25,w25,w24
+ add w21,w21,w27 // e+=rot(a,5)
+ ror w23,w23,#2
+ add w20,w20,w19 // future e+=X[i]
+ add w21,w21,w25 // e+=F(b,c,d)
+ ldp w6,w7,[x0,#8]
+ eor w25,w24,w22
+ ror w27,w21,#27
+ eor w25,w25,w23
+ add w20,w20,w27 // e+=rot(a,5)
+ ror w22,w22,#2
+ ldr w8,[x0,#16]
+ add w20,w20,w25 // e+=F(b,c,d)
+ add w21,w21,w5
+ add w22,w22,w6
+ add w20,w20,w4
+ add w23,w23,w7
+ add w24,w24,w8
+ stp w20,w21,[x0]
+ stp w22,w23,[x0,#8]
+ str w24,[x0,#16]
+ cbnz x2,.Loop
+
+ ldp x19,x20,[sp,#16]
+ ldp x21,x22,[sp,#32]
+ ldp x23,x24,[sp,#48]
+ ldp x25,x26,[sp,#64]
+ ldp x27,x28,[sp,#80]
+ ldr x29,[sp],#96
+ ret
+.size sha1_block_data_order,.-sha1_block_data_order
+.type sha1_block_armv8,%function
+.align 6
+sha1_block_armv8:
+.Lv8_entry:
+ stp x29,x30,[sp,#-16]!
+ add x29,sp,#0
+
+ adr x4,.Lconst
+ eor v1.16b,v1.16b,v1.16b
+ ld1 {v0.4s},[x0],#16
+ ld1 {v1.s}[0],[x0]
+ sub x0,x0,#16
+ ld1 {v16.4s-v19.4s},[x4]
+
+.Loop_hw:
+ ld1 {v4.16b-v7.16b},[x1],#64
+ sub x2,x2,#1
+ rev32 v4.16b,v4.16b
+ rev32 v5.16b,v5.16b
+
+ add v20.4s,v16.4s,v4.4s
+ rev32 v6.16b,v6.16b
+ orr v22.16b,v0.16b,v0.16b // offload
+
+ add v21.4s,v16.4s,v5.4s
+ rev32 v7.16b,v7.16b
+ .inst 0x5e280803 //sha1h v3.16b,v0.16b
+ .inst 0x5e140020 //sha1c v0.16b,v1.16b,v20.4s // 0
+ add v20.4s,v16.4s,v6.4s
+ .inst 0x5e0630a4 //sha1su0 v4.16b,v5.16b,v6.16b
+ .inst 0x5e280802 //sha1h v2.16b,v0.16b // 1
+ .inst 0x5e150060 //sha1c v0.16b,v3.16b,v21.4s
+ add v21.4s,v16.4s,v7.4s
+ .inst 0x5e2818e4 //sha1su1 v4.16b,v7.16b
+ .inst 0x5e0730c5 //sha1su0 v5.16b,v6.16b,v7.16b
+ .inst 0x5e280803 //sha1h v3.16b,v0.16b // 2
+ .inst 0x5e140040 //sha1c v0.16b,v2.16b,v20.4s
+ add v20.4s,v16.4s,v4.4s
+ .inst 0x5e281885 //sha1su1 v5.16b,v4.16b
+ .inst 0x5e0430e6 //sha1su0 v6.16b,v7.16b,v4.16b
+ .inst 0x5e280802 //sha1h v2.16b,v0.16b // 3
+ .inst 0x5e150060 //sha1c v0.16b,v3.16b,v21.4s
+ add v21.4s,v17.4s,v5.4s
+ .inst 0x5e2818a6 //sha1su1 v6.16b,v5.16b
+ .inst 0x5e053087 //sha1su0 v7.16b,v4.16b,v5.16b
+ .inst 0x5e280803 //sha1h v3.16b,v0.16b // 4
+ .inst 0x5e140040 //sha1c v0.16b,v2.16b,v20.4s
+ add v20.4s,v17.4s,v6.4s
+ .inst 0x5e2818c7 //sha1su1 v7.16b,v6.16b
+ .inst 0x5e0630a4 //sha1su0 v4.16b,v5.16b,v6.16b
+ .inst 0x5e280802 //sha1h v2.16b,v0.16b // 5
+ .inst 0x5e151060 //sha1p v0.16b,v3.16b,v21.4s
+ add v21.4s,v17.4s,v7.4s
+ .inst 0x5e2818e4 //sha1su1 v4.16b,v7.16b
+ .inst 0x5e0730c5 //sha1su0 v5.16b,v6.16b,v7.16b
+ .inst 0x5e280803 //sha1h v3.16b,v0.16b // 6
+ .inst 0x5e141040 //sha1p v0.16b,v2.16b,v20.4s
+ add v20.4s,v17.4s,v4.4s
+ .inst 0x5e281885 //sha1su1 v5.16b,v4.16b
+ .inst 0x5e0430e6 //sha1su0 v6.16b,v7.16b,v4.16b
+ .inst 0x5e280802 //sha1h v2.16b,v0.16b // 7
+ .inst 0x5e151060 //sha1p v0.16b,v3.16b,v21.4s
+ add v21.4s,v17.4s,v5.4s
+ .inst 0x5e2818a6 //sha1su1 v6.16b,v5.16b
+ .inst 0x5e053087 //sha1su0 v7.16b,v4.16b,v5.16b
+ .inst 0x5e280803 //sha1h v3.16b,v0.16b // 8
+ .inst 0x5e141040 //sha1p v0.16b,v2.16b,v20.4s
+ add v20.4s,v18.4s,v6.4s
+ .inst 0x5e2818c7 //sha1su1 v7.16b,v6.16b
+ .inst 0x5e0630a4 //sha1su0 v4.16b,v5.16b,v6.16b
+ .inst 0x5e280802 //sha1h v2.16b,v0.16b // 9
+ .inst 0x5e151060 //sha1p v0.16b,v3.16b,v21.4s
+ add v21.4s,v18.4s,v7.4s
+ .inst 0x5e2818e4 //sha1su1 v4.16b,v7.16b
+ .inst 0x5e0730c5 //sha1su0 v5.16b,v6.16b,v7.16b
+ .inst 0x5e280803 //sha1h v3.16b,v0.16b // 10
+ .inst 0x5e142040 //sha1m v0.16b,v2.16b,v20.4s
+ add v20.4s,v18.4s,v4.4s
+ .inst 0x5e281885 //sha1su1 v5.16b,v4.16b
+ .inst 0x5e0430e6 //sha1su0 v6.16b,v7.16b,v4.16b
+ .inst 0x5e280802 //sha1h v2.16b,v0.16b // 11
+ .inst 0x5e152060 //sha1m v0.16b,v3.16b,v21.4s
+ add v21.4s,v18.4s,v5.4s
+ .inst 0x5e2818a6 //sha1su1 v6.16b,v5.16b
+ .inst 0x5e053087 //sha1su0 v7.16b,v4.16b,v5.16b
+ .inst 0x5e280803 //sha1h v3.16b,v0.16b // 12
+ .inst 0x5e142040 //sha1m v0.16b,v2.16b,v20.4s
+ add v20.4s,v18.4s,v6.4s
+ .inst 0x5e2818c7 //sha1su1 v7.16b,v6.16b
+ .inst 0x5e0630a4 //sha1su0 v4.16b,v5.16b,v6.16b
+ .inst 0x5e280802 //sha1h v2.16b,v0.16b // 13
+ .inst 0x5e152060 //sha1m v0.16b,v3.16b,v21.4s
+ add v21.4s,v19.4s,v7.4s
+ .inst 0x5e2818e4 //sha1su1 v4.16b,v7.16b
+ .inst 0x5e0730c5 //sha1su0 v5.16b,v6.16b,v7.16b
+ .inst 0x5e280803 //sha1h v3.16b,v0.16b // 14
+ .inst 0x5e142040 //sha1m v0.16b,v2.16b,v20.4s
+ add v20.4s,v19.4s,v4.4s
+ .inst 0x5e281885 //sha1su1 v5.16b,v4.16b
+ .inst 0x5e0430e6 //sha1su0 v6.16b,v7.16b,v4.16b
+ .inst 0x5e280802 //sha1h v2.16b,v0.16b // 15
+ .inst 0x5e151060 //sha1p v0.16b,v3.16b,v21.4s
+ add v21.4s,v19.4s,v5.4s
+ .inst 0x5e2818a6 //sha1su1 v6.16b,v5.16b
+ .inst 0x5e053087 //sha1su0 v7.16b,v4.16b,v5.16b
+ .inst 0x5e280803 //sha1h v3.16b,v0.16b // 16
+ .inst 0x5e141040 //sha1p v0.16b,v2.16b,v20.4s
+ add v20.4s,v19.4s,v6.4s
+ .inst 0x5e2818c7 //sha1su1 v7.16b,v6.16b
+ .inst 0x5e280802 //sha1h v2.16b,v0.16b // 17
+ .inst 0x5e151060 //sha1p v0.16b,v3.16b,v21.4s
+ add v21.4s,v19.4s,v7.4s
+
+ .inst 0x5e280803 //sha1h v3.16b,v0.16b // 18
+ .inst 0x5e141040 //sha1p v0.16b,v2.16b,v20.4s
+
+ .inst 0x5e280802 //sha1h v2.16b,v0.16b // 19
+ .inst 0x5e151060 //sha1p v0.16b,v3.16b,v21.4s
+
+ add v1.4s,v1.4s,v2.4s
+ add v0.4s,v0.4s,v22.4s
+
+ cbnz x2,.Loop_hw
+
+ st1 {v0.4s},[x0],#16
+ st1 {v1.s}[0],[x0]
+
+ ldr x29,[sp],#16
+ ret
+.size sha1_block_armv8,.-sha1_block_armv8
+.align 6
+.Lconst:
+.long 0x5a827999,0x5a827999,0x5a827999,0x5a827999 //K_00_19
+.long 0x6ed9eba1,0x6ed9eba1,0x6ed9eba1,0x6ed9eba1 //K_20_39
+.long 0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc //K_40_59
+.long 0xca62c1d6,0xca62c1d6,0xca62c1d6,0xca62c1d6 //K_60_79
+.LOPENSSL_armcap_P:
+.quad OPENSSL_armcap_P-.
+.asciz "SHA1 block transform for ARMv8, CRYPTOGAMS by <appro@openssl.org>"
+.align 2
+.comm OPENSSL_armcap_P,4,4
diff --git a/linux-aarch64/crypto/sha/sha256-armv8.S b/linux-aarch64/crypto/sha/sha256-armv8.S
new file mode 100644
index 0000000..bd43b1f
--- /dev/null
+++ b/linux-aarch64/crypto/sha/sha256-armv8.S
@@ -0,0 +1,1141 @@
+#include "arm_arch.h"
+
+.text
+
+.globl sha256_block_data_order
+.type sha256_block_data_order,%function
+.align 6
+sha256_block_data_order:
+ ldr x16,.LOPENSSL_armcap_P
+ adr x17,.LOPENSSL_armcap_P
+ add x16,x16,x17
+ ldr w16,[x16]
+ tst w16,#ARMV8_SHA256
+ b.ne .Lv8_entry
+ stp x29,x30,[sp,#-128]!
+ add x29,sp,#0
+
+ stp x19,x20,[sp,#16]
+ stp x21,x22,[sp,#32]
+ stp x23,x24,[sp,#48]
+ stp x25,x26,[sp,#64]
+ stp x27,x28,[sp,#80]
+ sub sp,sp,#4*4
+
+ ldp w20,w21,[x0] // load context
+ ldp w22,w23,[x0,#2*4]
+ ldp w24,w25,[x0,#4*4]
+ add x2,x1,x2,lsl#6 // end of input
+ ldp w26,w27,[x0,#6*4]
+ adr x30,K256
+ stp x0,x2,[x29,#96]
+
+.Loop:
+ ldp w3,w4,[x1],#2*4
+ ldr w19,[x30],#4 // *K++
+ eor w28,w21,w22 // magic seed
+ str x1,[x29,#112]
+#ifndef __ARMEB__
+ rev w3,w3 // 0
+#endif
+ ror w16,w24,#6
+ add w27,w27,w19 // h+=K[i]
+ eor w6,w24,w24,ror#14
+ and w17,w25,w24
+ bic w19,w26,w24
+ add w27,w27,w3 // h+=X[i]
+ orr w17,w17,w19 // Ch(e,f,g)
+ eor w19,w20,w21 // a^b, b^c in next round
+ eor w16,w16,w6,ror#11 // Sigma1(e)
+ ror w6,w20,#2
+ add w27,w27,w17 // h+=Ch(e,f,g)
+ eor w17,w20,w20,ror#9
+ add w27,w27,w16 // h+=Sigma1(e)
+ and w28,w28,w19 // (b^c)&=(a^b)
+ add w23,w23,w27 // d+=h
+ eor w28,w28,w21 // Maj(a,b,c)
+ eor w17,w6,w17,ror#13 // Sigma0(a)
+ add w27,w27,w28 // h+=Maj(a,b,c)
+ ldr w28,[x30],#4 // *K++, w19 in next round
+ //add w27,w27,w17 // h+=Sigma0(a)
+#ifndef __ARMEB__
+ rev w4,w4 // 1
+#endif
+ ldp w5,w6,[x1],#2*4
+ add w27,w27,w17 // h+=Sigma0(a)
+ ror w16,w23,#6
+ add w26,w26,w28 // h+=K[i]
+ eor w7,w23,w23,ror#14
+ and w17,w24,w23
+ bic w28,w25,w23
+ add w26,w26,w4 // h+=X[i]
+ orr w17,w17,w28 // Ch(e,f,g)
+ eor w28,w27,w20 // a^b, b^c in next round
+ eor w16,w16,w7,ror#11 // Sigma1(e)
+ ror w7,w27,#2
+ add w26,w26,w17 // h+=Ch(e,f,g)
+ eor w17,w27,w27,ror#9
+ add w26,w26,w16 // h+=Sigma1(e)
+ and w19,w19,w28 // (b^c)&=(a^b)
+ add w22,w22,w26 // d+=h
+ eor w19,w19,w20 // Maj(a,b,c)
+ eor w17,w7,w17,ror#13 // Sigma0(a)
+ add w26,w26,w19 // h+=Maj(a,b,c)
+ ldr w19,[x30],#4 // *K++, w28 in next round
+ //add w26,w26,w17 // h+=Sigma0(a)
+#ifndef __ARMEB__
+ rev w5,w5 // 2
+#endif
+ add w26,w26,w17 // h+=Sigma0(a)
+ ror w16,w22,#6
+ add w25,w25,w19 // h+=K[i]
+ eor w8,w22,w22,ror#14
+ and w17,w23,w22
+ bic w19,w24,w22
+ add w25,w25,w5 // h+=X[i]
+ orr w17,w17,w19 // Ch(e,f,g)
+ eor w19,w26,w27 // a^b, b^c in next round
+ eor w16,w16,w8,ror#11 // Sigma1(e)
+ ror w8,w26,#2
+ add w25,w25,w17 // h+=Ch(e,f,g)
+ eor w17,w26,w26,ror#9
+ add w25,w25,w16 // h+=Sigma1(e)
+ and w28,w28,w19 // (b^c)&=(a^b)
+ add w21,w21,w25 // d+=h
+ eor w28,w28,w27 // Maj(a,b,c)
+ eor w17,w8,w17,ror#13 // Sigma0(a)
+ add w25,w25,w28 // h+=Maj(a,b,c)
+ ldr w28,[x30],#4 // *K++, w19 in next round
+ //add w25,w25,w17 // h+=Sigma0(a)
+#ifndef __ARMEB__
+ rev w6,w6 // 3
+#endif
+ ldp w7,w8,[x1],#2*4
+ add w25,w25,w17 // h+=Sigma0(a)
+ ror w16,w21,#6
+ add w24,w24,w28 // h+=K[i]
+ eor w9,w21,w21,ror#14
+ and w17,w22,w21
+ bic w28,w23,w21
+ add w24,w24,w6 // h+=X[i]
+ orr w17,w17,w28 // Ch(e,f,g)
+ eor w28,w25,w26 // a^b, b^c in next round
+ eor w16,w16,w9,ror#11 // Sigma1(e)
+ ror w9,w25,#2
+ add w24,w24,w17 // h+=Ch(e,f,g)
+ eor w17,w25,w25,ror#9
+ add w24,w24,w16 // h+=Sigma1(e)
+ and w19,w19,w28 // (b^c)&=(a^b)
+ add w20,w20,w24 // d+=h
+ eor w19,w19,w26 // Maj(a,b,c)
+ eor w17,w9,w17,ror#13 // Sigma0(a)
+ add w24,w24,w19 // h+=Maj(a,b,c)
+ ldr w19,[x30],#4 // *K++, w28 in next round
+ //add w24,w24,w17 // h+=Sigma0(a)
+#ifndef __ARMEB__
+ rev w7,w7 // 4
+#endif
+ add w24,w24,w17 // h+=Sigma0(a)
+ ror w16,w20,#6
+ add w23,w23,w19 // h+=K[i]
+ eor w10,w20,w20,ror#14
+ and w17,w21,w20
+ bic w19,w22,w20
+ add w23,w23,w7 // h+=X[i]
+ orr w17,w17,w19 // Ch(e,f,g)
+ eor w19,w24,w25 // a^b, b^c in next round
+ eor w16,w16,w10,ror#11 // Sigma1(e)
+ ror w10,w24,#2
+ add w23,w23,w17 // h+=Ch(e,f,g)
+ eor w17,w24,w24,ror#9
+ add w23,w23,w16 // h+=Sigma1(e)
+ and w28,w28,w19 // (b^c)&=(a^b)
+ add w27,w27,w23 // d+=h
+ eor w28,w28,w25 // Maj(a,b,c)
+ eor w17,w10,w17,ror#13 // Sigma0(a)
+ add w23,w23,w28 // h+=Maj(a,b,c)
+ ldr w28,[x30],#4 // *K++, w19 in next round
+ //add w23,w23,w17 // h+=Sigma0(a)
+#ifndef __ARMEB__
+ rev w8,w8 // 5
+#endif
+ ldp w9,w10,[x1],#2*4
+ add w23,w23,w17 // h+=Sigma0(a)
+ ror w16,w27,#6
+ add w22,w22,w28 // h+=K[i]
+ eor w11,w27,w27,ror#14
+ and w17,w20,w27
+ bic w28,w21,w27
+ add w22,w22,w8 // h+=X[i]
+ orr w17,w17,w28 // Ch(e,f,g)
+ eor w28,w23,w24 // a^b, b^c in next round
+ eor w16,w16,w11,ror#11 // Sigma1(e)
+ ror w11,w23,#2
+ add w22,w22,w17 // h+=Ch(e,f,g)
+ eor w17,w23,w23,ror#9
+ add w22,w22,w16 // h+=Sigma1(e)
+ and w19,w19,w28 // (b^c)&=(a^b)
+ add w26,w26,w22 // d+=h
+ eor w19,w19,w24 // Maj(a,b,c)
+ eor w17,w11,w17,ror#13 // Sigma0(a)
+ add w22,w22,w19 // h+=Maj(a,b,c)
+ ldr w19,[x30],#4 // *K++, w28 in next round
+ //add w22,w22,w17 // h+=Sigma0(a)
+#ifndef __ARMEB__
+ rev w9,w9 // 6
+#endif
+ add w22,w22,w17 // h+=Sigma0(a)
+ ror w16,w26,#6
+ add w21,w21,w19 // h+=K[i]
+ eor w12,w26,w26,ror#14
+ and w17,w27,w26
+ bic w19,w20,w26
+ add w21,w21,w9 // h+=X[i]
+ orr w17,w17,w19 // Ch(e,f,g)
+ eor w19,w22,w23 // a^b, b^c in next round
+ eor w16,w16,w12,ror#11 // Sigma1(e)
+ ror w12,w22,#2
+ add w21,w21,w17 // h+=Ch(e,f,g)
+ eor w17,w22,w22,ror#9
+ add w21,w21,w16 // h+=Sigma1(e)
+ and w28,w28,w19 // (b^c)&=(a^b)
+ add w25,w25,w21 // d+=h
+ eor w28,w28,w23 // Maj(a,b,c)
+ eor w17,w12,w17,ror#13 // Sigma0(a)
+ add w21,w21,w28 // h+=Maj(a,b,c)
+ ldr w28,[x30],#4 // *K++, w19 in next round
+ //add w21,w21,w17 // h+=Sigma0(a)
+#ifndef __ARMEB__
+ rev w10,w10 // 7
+#endif
+ ldp w11,w12,[x1],#2*4
+ add w21,w21,w17 // h+=Sigma0(a)
+ ror w16,w25,#6
+ add w20,w20,w28 // h+=K[i]
+ eor w13,w25,w25,ror#14
+ and w17,w26,w25
+ bic w28,w27,w25
+ add w20,w20,w10 // h+=X[i]
+ orr w17,w17,w28 // Ch(e,f,g)
+ eor w28,w21,w22 // a^b, b^c in next round
+ eor w16,w16,w13,ror#11 // Sigma1(e)
+ ror w13,w21,#2
+ add w20,w20,w17 // h+=Ch(e,f,g)
+ eor w17,w21,w21,ror#9
+ add w20,w20,w16 // h+=Sigma1(e)
+ and w19,w19,w28 // (b^c)&=(a^b)
+ add w24,w24,w20 // d+=h
+ eor w19,w19,w22 // Maj(a,b,c)
+ eor w17,w13,w17,ror#13 // Sigma0(a)
+ add w20,w20,w19 // h+=Maj(a,b,c)
+ ldr w19,[x30],#4 // *K++, w28 in next round
+ //add w20,w20,w17 // h+=Sigma0(a)
+#ifndef __ARMEB__
+ rev w11,w11 // 8
+#endif
+ add w20,w20,w17 // h+=Sigma0(a)
+ ror w16,w24,#6
+ add w27,w27,w19 // h+=K[i]
+ eor w14,w24,w24,ror#14
+ and w17,w25,w24
+ bic w19,w26,w24
+ add w27,w27,w11 // h+=X[i]
+ orr w17,w17,w19 // Ch(e,f,g)
+ eor w19,w20,w21 // a^b, b^c in next round
+ eor w16,w16,w14,ror#11 // Sigma1(e)
+ ror w14,w20,#2
+ add w27,w27,w17 // h+=Ch(e,f,g)
+ eor w17,w20,w20,ror#9
+ add w27,w27,w16 // h+=Sigma1(e)
+ and w28,w28,w19 // (b^c)&=(a^b)
+ add w23,w23,w27 // d+=h
+ eor w28,w28,w21 // Maj(a,b,c)
+ eor w17,w14,w17,ror#13 // Sigma0(a)
+ add w27,w27,w28 // h+=Maj(a,b,c)
+ ldr w28,[x30],#4 // *K++, w19 in next round
+ //add w27,w27,w17 // h+=Sigma0(a)
+#ifndef __ARMEB__
+ rev w12,w12 // 9
+#endif
+ ldp w13,w14,[x1],#2*4
+ add w27,w27,w17 // h+=Sigma0(a)
+ ror w16,w23,#6
+ add w26,w26,w28 // h+=K[i]
+ eor w15,w23,w23,ror#14
+ and w17,w24,w23
+ bic w28,w25,w23
+ add w26,w26,w12 // h+=X[i]
+ orr w17,w17,w28 // Ch(e,f,g)
+ eor w28,w27,w20 // a^b, b^c in next round
+ eor w16,w16,w15,ror#11 // Sigma1(e)
+ ror w15,w27,#2
+ add w26,w26,w17 // h+=Ch(e,f,g)
+ eor w17,w27,w27,ror#9
+ add w26,w26,w16 // h+=Sigma1(e)
+ and w19,w19,w28 // (b^c)&=(a^b)
+ add w22,w22,w26 // d+=h
+ eor w19,w19,w20 // Maj(a,b,c)
+ eor w17,w15,w17,ror#13 // Sigma0(a)
+ add w26,w26,w19 // h+=Maj(a,b,c)
+ ldr w19,[x30],#4 // *K++, w28 in next round
+ //add w26,w26,w17 // h+=Sigma0(a)
+#ifndef __ARMEB__
+ rev w13,w13 // 10
+#endif
+ add w26,w26,w17 // h+=Sigma0(a)
+ ror w16,w22,#6
+ add w25,w25,w19 // h+=K[i]
+ eor w0,w22,w22,ror#14
+ and w17,w23,w22
+ bic w19,w24,w22
+ add w25,w25,w13 // h+=X[i]
+ orr w17,w17,w19 // Ch(e,f,g)
+ eor w19,w26,w27 // a^b, b^c in next round
+ eor w16,w16,w0,ror#11 // Sigma1(e)
+ ror w0,w26,#2
+ add w25,w25,w17 // h+=Ch(e,f,g)
+ eor w17,w26,w26,ror#9
+ add w25,w25,w16 // h+=Sigma1(e)
+ and w28,w28,w19 // (b^c)&=(a^b)
+ add w21,w21,w25 // d+=h
+ eor w28,w28,w27 // Maj(a,b,c)
+ eor w17,w0,w17,ror#13 // Sigma0(a)
+ add w25,w25,w28 // h+=Maj(a,b,c)
+ ldr w28,[x30],#4 // *K++, w19 in next round
+ //add w25,w25,w17 // h+=Sigma0(a)
+#ifndef __ARMEB__
+ rev w14,w14 // 11
+#endif
+ ldp w15,w0,[x1],#2*4
+ add w25,w25,w17 // h+=Sigma0(a)
+ str w6,[sp,#12]
+ ror w16,w21,#6
+ add w24,w24,w28 // h+=K[i]
+ eor w6,w21,w21,ror#14
+ and w17,w22,w21
+ bic w28,w23,w21
+ add w24,w24,w14 // h+=X[i]
+ orr w17,w17,w28 // Ch(e,f,g)
+ eor w28,w25,w26 // a^b, b^c in next round
+ eor w16,w16,w6,ror#11 // Sigma1(e)
+ ror w6,w25,#2
+ add w24,w24,w17 // h+=Ch(e,f,g)
+ eor w17,w25,w25,ror#9
+ add w24,w24,w16 // h+=Sigma1(e)
+ and w19,w19,w28 // (b^c)&=(a^b)
+ add w20,w20,w24 // d+=h
+ eor w19,w19,w26 // Maj(a,b,c)
+ eor w17,w6,w17,ror#13 // Sigma0(a)
+ add w24,w24,w19 // h+=Maj(a,b,c)
+ ldr w19,[x30],#4 // *K++, w28 in next round
+ //add w24,w24,w17 // h+=Sigma0(a)
+#ifndef __ARMEB__
+ rev w15,w15 // 12
+#endif
+ add w24,w24,w17 // h+=Sigma0(a)
+ str w7,[sp,#0]
+ ror w16,w20,#6
+ add w23,w23,w19 // h+=K[i]
+ eor w7,w20,w20,ror#14
+ and w17,w21,w20
+ bic w19,w22,w20
+ add w23,w23,w15 // h+=X[i]
+ orr w17,w17,w19 // Ch(e,f,g)
+ eor w19,w24,w25 // a^b, b^c in next round
+ eor w16,w16,w7,ror#11 // Sigma1(e)
+ ror w7,w24,#2
+ add w23,w23,w17 // h+=Ch(e,f,g)
+ eor w17,w24,w24,ror#9
+ add w23,w23,w16 // h+=Sigma1(e)
+ and w28,w28,w19 // (b^c)&=(a^b)
+ add w27,w27,w23 // d+=h
+ eor w28,w28,w25 // Maj(a,b,c)
+ eor w17,w7,w17,ror#13 // Sigma0(a)
+ add w23,w23,w28 // h+=Maj(a,b,c)
+ ldr w28,[x30],#4 // *K++, w19 in next round
+ //add w23,w23,w17 // h+=Sigma0(a)
+#ifndef __ARMEB__
+ rev w0,w0 // 13
+#endif
+ ldp w1,w2,[x1]
+ add w23,w23,w17 // h+=Sigma0(a)
+ str w8,[sp,#4]
+ ror w16,w27,#6
+ add w22,w22,w28 // h+=K[i]
+ eor w8,w27,w27,ror#14
+ and w17,w20,w27
+ bic w28,w21,w27
+ add w22,w22,w0 // h+=X[i]
+ orr w17,w17,w28 // Ch(e,f,g)
+ eor w28,w23,w24 // a^b, b^c in next round
+ eor w16,w16,w8,ror#11 // Sigma1(e)
+ ror w8,w23,#2
+ add w22,w22,w17 // h+=Ch(e,f,g)
+ eor w17,w23,w23,ror#9
+ add w22,w22,w16 // h+=Sigma1(e)
+ and w19,w19,w28 // (b^c)&=(a^b)
+ add w26,w26,w22 // d+=h
+ eor w19,w19,w24 // Maj(a,b,c)
+ eor w17,w8,w17,ror#13 // Sigma0(a)
+ add w22,w22,w19 // h+=Maj(a,b,c)
+ ldr w19,[x30],#4 // *K++, w28 in next round
+ //add w22,w22,w17 // h+=Sigma0(a)
+#ifndef __ARMEB__
+ rev w1,w1 // 14
+#endif
+ ldr w6,[sp,#12]
+ add w22,w22,w17 // h+=Sigma0(a)
+ str w9,[sp,#8]
+ ror w16,w26,#6
+ add w21,w21,w19 // h+=K[i]
+ eor w9,w26,w26,ror#14
+ and w17,w27,w26
+ bic w19,w20,w26
+ add w21,w21,w1 // h+=X[i]
+ orr w17,w17,w19 // Ch(e,f,g)
+ eor w19,w22,w23 // a^b, b^c in next round
+ eor w16,w16,w9,ror#11 // Sigma1(e)
+ ror w9,w22,#2
+ add w21,w21,w17 // h+=Ch(e,f,g)
+ eor w17,w22,w22,ror#9
+ add w21,w21,w16 // h+=Sigma1(e)
+ and w28,w28,w19 // (b^c)&=(a^b)
+ add w25,w25,w21 // d+=h
+ eor w28,w28,w23 // Maj(a,b,c)
+ eor w17,w9,w17,ror#13 // Sigma0(a)
+ add w21,w21,w28 // h+=Maj(a,b,c)
+ ldr w28,[x30],#4 // *K++, w19 in next round
+ //add w21,w21,w17 // h+=Sigma0(a)
+#ifndef __ARMEB__
+ rev w2,w2 // 15
+#endif
+ ldr w7,[sp,#0]
+ add w21,w21,w17 // h+=Sigma0(a)
+ str w10,[sp,#12]
+ ror w16,w25,#6
+ add w20,w20,w28 // h+=K[i]
+ ror w9,w4,#7
+ and w17,w26,w25
+ ror w8,w1,#17
+ bic w28,w27,w25
+ ror w10,w21,#2
+ add w20,w20,w2 // h+=X[i]
+ eor w16,w16,w25,ror#11
+ eor w9,w9,w4,ror#18
+ orr w17,w17,w28 // Ch(e,f,g)
+ eor w28,w21,w22 // a^b, b^c in next round
+ eor w16,w16,w25,ror#25 // Sigma1(e)
+ eor w10,w10,w21,ror#13
+ add w20,w20,w17 // h+=Ch(e,f,g)
+ and w19,w19,w28 // (b^c)&=(a^b)
+ eor w8,w8,w1,ror#19
+ eor w9,w9,w4,lsr#3 // sigma0(X[i+1])
+ add w20,w20,w16 // h+=Sigma1(e)
+ eor w19,w19,w22 // Maj(a,b,c)
+ eor w17,w10,w21,ror#22 // Sigma0(a)
+ eor w8,w8,w1,lsr#10 // sigma1(X[i+14])
+ add w3,w3,w12
+ add w24,w24,w20 // d+=h
+ add w20,w20,w19 // h+=Maj(a,b,c)
+ ldr w19,[x30],#4 // *K++, w28 in next round
+ add w3,w3,w9
+ add w20,w20,w17 // h+=Sigma0(a)
+ add w3,w3,w8
+.Loop_16_xx:
+ ldr w8,[sp,#4]
+ str w11,[sp,#0]
+ ror w16,w24,#6
+ add w27,w27,w19 // h+=K[i]
+ ror w10,w5,#7
+ and w17,w25,w24
+ ror w9,w2,#17
+ bic w19,w26,w24
+ ror w11,w20,#2
+ add w27,w27,w3 // h+=X[i]
+ eor w16,w16,w24,ror#11
+ eor w10,w10,w5,ror#18
+ orr w17,w17,w19 // Ch(e,f,g)
+ eor w19,w20,w21 // a^b, b^c in next round
+ eor w16,w16,w24,ror#25 // Sigma1(e)
+ eor w11,w11,w20,ror#13
+ add w27,w27,w17 // h+=Ch(e,f,g)
+ and w28,w28,w19 // (b^c)&=(a^b)
+ eor w9,w9,w2,ror#19
+ eor w10,w10,w5,lsr#3 // sigma0(X[i+1])
+ add w27,w27,w16 // h+=Sigma1(e)
+ eor w28,w28,w21 // Maj(a,b,c)
+ eor w17,w11,w20,ror#22 // Sigma0(a)
+ eor w9,w9,w2,lsr#10 // sigma1(X[i+14])
+ add w4,w4,w13
+ add w23,w23,w27 // d+=h
+ add w27,w27,w28 // h+=Maj(a,b,c)
+ ldr w28,[x30],#4 // *K++, w19 in next round
+ add w4,w4,w10
+ add w27,w27,w17 // h+=Sigma0(a)
+ add w4,w4,w9
+ ldr w9,[sp,#8]
+ str w12,[sp,#4]
+ ror w16,w23,#6
+ add w26,w26,w28 // h+=K[i]
+ ror w11,w6,#7
+ and w17,w24,w23
+ ror w10,w3,#17
+ bic w28,w25,w23
+ ror w12,w27,#2
+ add w26,w26,w4 // h+=X[i]
+ eor w16,w16,w23,ror#11
+ eor w11,w11,w6,ror#18
+ orr w17,w17,w28 // Ch(e,f,g)
+ eor w28,w27,w20 // a^b, b^c in next round
+ eor w16,w16,w23,ror#25 // Sigma1(e)
+ eor w12,w12,w27,ror#13
+ add w26,w26,w17 // h+=Ch(e,f,g)
+ and w19,w19,w28 // (b^c)&=(a^b)
+ eor w10,w10,w3,ror#19
+ eor w11,w11,w6,lsr#3 // sigma0(X[i+1])
+ add w26,w26,w16 // h+=Sigma1(e)
+ eor w19,w19,w20 // Maj(a,b,c)
+ eor w17,w12,w27,ror#22 // Sigma0(a)
+ eor w10,w10,w3,lsr#10 // sigma1(X[i+14])
+ add w5,w5,w14
+ add w22,w22,w26 // d+=h
+ add w26,w26,w19 // h+=Maj(a,b,c)
+ ldr w19,[x30],#4 // *K++, w28 in next round
+ add w5,w5,w11
+ add w26,w26,w17 // h+=Sigma0(a)
+ add w5,w5,w10
+ ldr w10,[sp,#12]
+ str w13,[sp,#8]
+ ror w16,w22,#6
+ add w25,w25,w19 // h+=K[i]
+ ror w12,w7,#7
+ and w17,w23,w22
+ ror w11,w4,#17
+ bic w19,w24,w22
+ ror w13,w26,#2
+ add w25,w25,w5 // h+=X[i]
+ eor w16,w16,w22,ror#11
+ eor w12,w12,w7,ror#18
+ orr w17,w17,w19 // Ch(e,f,g)
+ eor w19,w26,w27 // a^b, b^c in next round
+ eor w16,w16,w22,ror#25 // Sigma1(e)
+ eor w13,w13,w26,ror#13
+ add w25,w25,w17 // h+=Ch(e,f,g)
+ and w28,w28,w19 // (b^c)&=(a^b)
+ eor w11,w11,w4,ror#19
+ eor w12,w12,w7,lsr#3 // sigma0(X[i+1])
+ add w25,w25,w16 // h+=Sigma1(e)
+ eor w28,w28,w27 // Maj(a,b,c)
+ eor w17,w13,w26,ror#22 // Sigma0(a)
+ eor w11,w11,w4,lsr#10 // sigma1(X[i+14])
+ add w6,w6,w15
+ add w21,w21,w25 // d+=h
+ add w25,w25,w28 // h+=Maj(a,b,c)
+ ldr w28,[x30],#4 // *K++, w19 in next round
+ add w6,w6,w12
+ add w25,w25,w17 // h+=Sigma0(a)
+ add w6,w6,w11
+ ldr w11,[sp,#0]
+ str w14,[sp,#12]
+ ror w16,w21,#6
+ add w24,w24,w28 // h+=K[i]
+ ror w13,w8,#7
+ and w17,w22,w21
+ ror w12,w5,#17
+ bic w28,w23,w21
+ ror w14,w25,#2
+ add w24,w24,w6 // h+=X[i]
+ eor w16,w16,w21,ror#11
+ eor w13,w13,w8,ror#18
+ orr w17,w17,w28 // Ch(e,f,g)
+ eor w28,w25,w26 // a^b, b^c in next round
+ eor w16,w16,w21,ror#25 // Sigma1(e)
+ eor w14,w14,w25,ror#13
+ add w24,w24,w17 // h+=Ch(e,f,g)
+ and w19,w19,w28 // (b^c)&=(a^b)
+ eor w12,w12,w5,ror#19
+ eor w13,w13,w8,lsr#3 // sigma0(X[i+1])
+ add w24,w24,w16 // h+=Sigma1(e)
+ eor w19,w19,w26 // Maj(a,b,c)
+ eor w17,w14,w25,ror#22 // Sigma0(a)
+ eor w12,w12,w5,lsr#10 // sigma1(X[i+14])
+ add w7,w7,w0
+ add w20,w20,w24 // d+=h
+ add w24,w24,w19 // h+=Maj(a,b,c)
+ ldr w19,[x30],#4 // *K++, w28 in next round
+ add w7,w7,w13
+ add w24,w24,w17 // h+=Sigma0(a)
+ add w7,w7,w12
+ ldr w12,[sp,#4]
+ str w15,[sp,#0]
+ ror w16,w20,#6
+ add w23,w23,w19 // h+=K[i]
+ ror w14,w9,#7
+ and w17,w21,w20
+ ror w13,w6,#17
+ bic w19,w22,w20
+ ror w15,w24,#2
+ add w23,w23,w7 // h+=X[i]
+ eor w16,w16,w20,ror#11
+ eor w14,w14,w9,ror#18
+ orr w17,w17,w19 // Ch(e,f,g)
+ eor w19,w24,w25 // a^b, b^c in next round
+ eor w16,w16,w20,ror#25 // Sigma1(e)
+ eor w15,w15,w24,ror#13
+ add w23,w23,w17 // h+=Ch(e,f,g)
+ and w28,w28,w19 // (b^c)&=(a^b)
+ eor w13,w13,w6,ror#19
+ eor w14,w14,w9,lsr#3 // sigma0(X[i+1])
+ add w23,w23,w16 // h+=Sigma1(e)
+ eor w28,w28,w25 // Maj(a,b,c)
+ eor w17,w15,w24,ror#22 // Sigma0(a)
+ eor w13,w13,w6,lsr#10 // sigma1(X[i+14])
+ add w8,w8,w1
+ add w27,w27,w23 // d+=h
+ add w23,w23,w28 // h+=Maj(a,b,c)
+ ldr w28,[x30],#4 // *K++, w19 in next round
+ add w8,w8,w14
+ add w23,w23,w17 // h+=Sigma0(a)
+ add w8,w8,w13
+ ldr w13,[sp,#8]
+ str w0,[sp,#4]
+ ror w16,w27,#6
+ add w22,w22,w28 // h+=K[i]
+ ror w15,w10,#7
+ and w17,w20,w27
+ ror w14,w7,#17
+ bic w28,w21,w27
+ ror w0,w23,#2
+ add w22,w22,w8 // h+=X[i]
+ eor w16,w16,w27,ror#11
+ eor w15,w15,w10,ror#18
+ orr w17,w17,w28 // Ch(e,f,g)
+ eor w28,w23,w24 // a^b, b^c in next round
+ eor w16,w16,w27,ror#25 // Sigma1(e)
+ eor w0,w0,w23,ror#13
+ add w22,w22,w17 // h+=Ch(e,f,g)
+ and w19,w19,w28 // (b^c)&=(a^b)
+ eor w14,w14,w7,ror#19
+ eor w15,w15,w10,lsr#3 // sigma0(X[i+1])
+ add w22,w22,w16 // h+=Sigma1(e)
+ eor w19,w19,w24 // Maj(a,b,c)
+ eor w17,w0,w23,ror#22 // Sigma0(a)
+ eor w14,w14,w7,lsr#10 // sigma1(X[i+14])
+ add w9,w9,w2
+ add w26,w26,w22 // d+=h
+ add w22,w22,w19 // h+=Maj(a,b,c)
+ ldr w19,[x30],#4 // *K++, w28 in next round
+ add w9,w9,w15
+ add w22,w22,w17 // h+=Sigma0(a)
+ add w9,w9,w14
+ ldr w14,[sp,#12]
+ str w1,[sp,#8]
+ ror w16,w26,#6
+ add w21,w21,w19 // h+=K[i]
+ ror w0,w11,#7
+ and w17,w27,w26
+ ror w15,w8,#17
+ bic w19,w20,w26
+ ror w1,w22,#2
+ add w21,w21,w9 // h+=X[i]
+ eor w16,w16,w26,ror#11
+ eor w0,w0,w11,ror#18
+ orr w17,w17,w19 // Ch(e,f,g)
+ eor w19,w22,w23 // a^b, b^c in next round
+ eor w16,w16,w26,ror#25 // Sigma1(e)
+ eor w1,w1,w22,ror#13
+ add w21,w21,w17 // h+=Ch(e,f,g)
+ and w28,w28,w19 // (b^c)&=(a^b)
+ eor w15,w15,w8,ror#19
+ eor w0,w0,w11,lsr#3 // sigma0(X[i+1])
+ add w21,w21,w16 // h+=Sigma1(e)
+ eor w28,w28,w23 // Maj(a,b,c)
+ eor w17,w1,w22,ror#22 // Sigma0(a)
+ eor w15,w15,w8,lsr#10 // sigma1(X[i+14])
+ add w10,w10,w3
+ add w25,w25,w21 // d+=h
+ add w21,w21,w28 // h+=Maj(a,b,c)
+ ldr w28,[x30],#4 // *K++, w19 in next round
+ add w10,w10,w0
+ add w21,w21,w17 // h+=Sigma0(a)
+ add w10,w10,w15
+ ldr w15,[sp,#0]
+ str w2,[sp,#12]
+ ror w16,w25,#6
+ add w20,w20,w28 // h+=K[i]
+ ror w1,w12,#7
+ and w17,w26,w25
+ ror w0,w9,#17
+ bic w28,w27,w25
+ ror w2,w21,#2
+ add w20,w20,w10 // h+=X[i]
+ eor w16,w16,w25,ror#11
+ eor w1,w1,w12,ror#18
+ orr w17,w17,w28 // Ch(e,f,g)
+ eor w28,w21,w22 // a^b, b^c in next round
+ eor w16,w16,w25,ror#25 // Sigma1(e)
+ eor w2,w2,w21,ror#13
+ add w20,w20,w17 // h+=Ch(e,f,g)
+ and w19,w19,w28 // (b^c)&=(a^b)
+ eor w0,w0,w9,ror#19
+ eor w1,w1,w12,lsr#3 // sigma0(X[i+1])
+ add w20,w20,w16 // h+=Sigma1(e)
+ eor w19,w19,w22 // Maj(a,b,c)
+ eor w17,w2,w21,ror#22 // Sigma0(a)
+ eor w0,w0,w9,lsr#10 // sigma1(X[i+14])
+ add w11,w11,w4
+ add w24,w24,w20 // d+=h
+ add w20,w20,w19 // h+=Maj(a,b,c)
+ ldr w19,[x30],#4 // *K++, w28 in next round
+ add w11,w11,w1
+ add w20,w20,w17 // h+=Sigma0(a)
+ add w11,w11,w0
+ ldr w0,[sp,#4]
+ str w3,[sp,#0]
+ ror w16,w24,#6
+ add w27,w27,w19 // h+=K[i]
+ ror w2,w13,#7
+ and w17,w25,w24
+ ror w1,w10,#17
+ bic w19,w26,w24
+ ror w3,w20,#2
+ add w27,w27,w11 // h+=X[i]
+ eor w16,w16,w24,ror#11
+ eor w2,w2,w13,ror#18
+ orr w17,w17,w19 // Ch(e,f,g)
+ eor w19,w20,w21 // a^b, b^c in next round
+ eor w16,w16,w24,ror#25 // Sigma1(e)
+ eor w3,w3,w20,ror#13
+ add w27,w27,w17 // h+=Ch(e,f,g)
+ and w28,w28,w19 // (b^c)&=(a^b)
+ eor w1,w1,w10,ror#19
+ eor w2,w2,w13,lsr#3 // sigma0(X[i+1])
+ add w27,w27,w16 // h+=Sigma1(e)
+ eor w28,w28,w21 // Maj(a,b,c)
+ eor w17,w3,w20,ror#22 // Sigma0(a)
+ eor w1,w1,w10,lsr#10 // sigma1(X[i+14])
+ add w12,w12,w5
+ add w23,w23,w27 // d+=h
+ add w27,w27,w28 // h+=Maj(a,b,c)
+ ldr w28,[x30],#4 // *K++, w19 in next round
+ add w12,w12,w2
+ add w27,w27,w17 // h+=Sigma0(a)
+ add w12,w12,w1
+ ldr w1,[sp,#8]
+ str w4,[sp,#4]
+ ror w16,w23,#6
+ add w26,w26,w28 // h+=K[i]
+ ror w3,w14,#7
+ and w17,w24,w23
+ ror w2,w11,#17
+ bic w28,w25,w23
+ ror w4,w27,#2
+ add w26,w26,w12 // h+=X[i]
+ eor w16,w16,w23,ror#11
+ eor w3,w3,w14,ror#18
+ orr w17,w17,w28 // Ch(e,f,g)
+ eor w28,w27,w20 // a^b, b^c in next round
+ eor w16,w16,w23,ror#25 // Sigma1(e)
+ eor w4,w4,w27,ror#13
+ add w26,w26,w17 // h+=Ch(e,f,g)
+ and w19,w19,w28 // (b^c)&=(a^b)
+ eor w2,w2,w11,ror#19
+ eor w3,w3,w14,lsr#3 // sigma0(X[i+1])
+ add w26,w26,w16 // h+=Sigma1(e)
+ eor w19,w19,w20 // Maj(a,b,c)
+ eor w17,w4,w27,ror#22 // Sigma0(a)
+ eor w2,w2,w11,lsr#10 // sigma1(X[i+14])
+ add w13,w13,w6
+ add w22,w22,w26 // d+=h
+ add w26,w26,w19 // h+=Maj(a,b,c)
+ ldr w19,[x30],#4 // *K++, w28 in next round
+ add w13,w13,w3
+ add w26,w26,w17 // h+=Sigma0(a)
+ add w13,w13,w2
+ ldr w2,[sp,#12]
+ str w5,[sp,#8]
+ ror w16,w22,#6
+ add w25,w25,w19 // h+=K[i]
+ ror w4,w15,#7
+ and w17,w23,w22
+ ror w3,w12,#17
+ bic w19,w24,w22
+ ror w5,w26,#2
+ add w25,w25,w13 // h+=X[i]
+ eor w16,w16,w22,ror#11
+ eor w4,w4,w15,ror#18
+ orr w17,w17,w19 // Ch(e,f,g)
+ eor w19,w26,w27 // a^b, b^c in next round
+ eor w16,w16,w22,ror#25 // Sigma1(e)
+ eor w5,w5,w26,ror#13
+ add w25,w25,w17 // h+=Ch(e,f,g)
+ and w28,w28,w19 // (b^c)&=(a^b)
+ eor w3,w3,w12,ror#19
+ eor w4,w4,w15,lsr#3 // sigma0(X[i+1])
+ add w25,w25,w16 // h+=Sigma1(e)
+ eor w28,w28,w27 // Maj(a,b,c)
+ eor w17,w5,w26,ror#22 // Sigma0(a)
+ eor w3,w3,w12,lsr#10 // sigma1(X[i+14])
+ add w14,w14,w7
+ add w21,w21,w25 // d+=h
+ add w25,w25,w28 // h+=Maj(a,b,c)
+ ldr w28,[x30],#4 // *K++, w19 in next round
+ add w14,w14,w4
+ add w25,w25,w17 // h+=Sigma0(a)
+ add w14,w14,w3
+ ldr w3,[sp,#0]
+ str w6,[sp,#12]
+ ror w16,w21,#6
+ add w24,w24,w28 // h+=K[i]
+ ror w5,w0,#7
+ and w17,w22,w21
+ ror w4,w13,#17
+ bic w28,w23,w21
+ ror w6,w25,#2
+ add w24,w24,w14 // h+=X[i]
+ eor w16,w16,w21,ror#11
+ eor w5,w5,w0,ror#18
+ orr w17,w17,w28 // Ch(e,f,g)
+ eor w28,w25,w26 // a^b, b^c in next round
+ eor w16,w16,w21,ror#25 // Sigma1(e)
+ eor w6,w6,w25,ror#13
+ add w24,w24,w17 // h+=Ch(e,f,g)
+ and w19,w19,w28 // (b^c)&=(a^b)
+ eor w4,w4,w13,ror#19
+ eor w5,w5,w0,lsr#3 // sigma0(X[i+1])
+ add w24,w24,w16 // h+=Sigma1(e)
+ eor w19,w19,w26 // Maj(a,b,c)
+ eor w17,w6,w25,ror#22 // Sigma0(a)
+ eor w4,w4,w13,lsr#10 // sigma1(X[i+14])
+ add w15,w15,w8
+ add w20,w20,w24 // d+=h
+ add w24,w24,w19 // h+=Maj(a,b,c)
+ ldr w19,[x30],#4 // *K++, w28 in next round
+ add w15,w15,w5
+ add w24,w24,w17 // h+=Sigma0(a)
+ add w15,w15,w4
+ ldr w4,[sp,#4]
+ str w7,[sp,#0]
+ ror w16,w20,#6
+ add w23,w23,w19 // h+=K[i]
+ ror w6,w1,#7
+ and w17,w21,w20
+ ror w5,w14,#17
+ bic w19,w22,w20
+ ror w7,w24,#2
+ add w23,w23,w15 // h+=X[i]
+ eor w16,w16,w20,ror#11
+ eor w6,w6,w1,ror#18
+ orr w17,w17,w19 // Ch(e,f,g)
+ eor w19,w24,w25 // a^b, b^c in next round
+ eor w16,w16,w20,ror#25 // Sigma1(e)
+ eor w7,w7,w24,ror#13
+ add w23,w23,w17 // h+=Ch(e,f,g)
+ and w28,w28,w19 // (b^c)&=(a^b)
+ eor w5,w5,w14,ror#19
+ eor w6,w6,w1,lsr#3 // sigma0(X[i+1])
+ add w23,w23,w16 // h+=Sigma1(e)
+ eor w28,w28,w25 // Maj(a,b,c)
+ eor w17,w7,w24,ror#22 // Sigma0(a)
+ eor w5,w5,w14,lsr#10 // sigma1(X[i+14])
+ add w0,w0,w9
+ add w27,w27,w23 // d+=h
+ add w23,w23,w28 // h+=Maj(a,b,c)
+ ldr w28,[x30],#4 // *K++, w19 in next round
+ add w0,w0,w6
+ add w23,w23,w17 // h+=Sigma0(a)
+ add w0,w0,w5
+ ldr w5,[sp,#8]
+ str w8,[sp,#4]
+ ror w16,w27,#6
+ add w22,w22,w28 // h+=K[i]
+ ror w7,w2,#7
+ and w17,w20,w27
+ ror w6,w15,#17
+ bic w28,w21,w27
+ ror w8,w23,#2
+ add w22,w22,w0 // h+=X[i]
+ eor w16,w16,w27,ror#11
+ eor w7,w7,w2,ror#18
+ orr w17,w17,w28 // Ch(e,f,g)
+ eor w28,w23,w24 // a^b, b^c in next round
+ eor w16,w16,w27,ror#25 // Sigma1(e)
+ eor w8,w8,w23,ror#13
+ add w22,w22,w17 // h+=Ch(e,f,g)
+ and w19,w19,w28 // (b^c)&=(a^b)
+ eor w6,w6,w15,ror#19
+ eor w7,w7,w2,lsr#3 // sigma0(X[i+1])
+ add w22,w22,w16 // h+=Sigma1(e)
+ eor w19,w19,w24 // Maj(a,b,c)
+ eor w17,w8,w23,ror#22 // Sigma0(a)
+ eor w6,w6,w15,lsr#10 // sigma1(X[i+14])
+ add w1,w1,w10
+ add w26,w26,w22 // d+=h
+ add w22,w22,w19 // h+=Maj(a,b,c)
+ ldr w19,[x30],#4 // *K++, w28 in next round
+ add w1,w1,w7
+ add w22,w22,w17 // h+=Sigma0(a)
+ add w1,w1,w6
+ ldr w6,[sp,#12]
+ str w9,[sp,#8]
+ ror w16,w26,#6
+ add w21,w21,w19 // h+=K[i]
+ ror w8,w3,#7
+ and w17,w27,w26
+ ror w7,w0,#17
+ bic w19,w20,w26
+ ror w9,w22,#2
+ add w21,w21,w1 // h+=X[i]
+ eor w16,w16,w26,ror#11
+ eor w8,w8,w3,ror#18
+ orr w17,w17,w19 // Ch(e,f,g)
+ eor w19,w22,w23 // a^b, b^c in next round
+ eor w16,w16,w26,ror#25 // Sigma1(e)
+ eor w9,w9,w22,ror#13
+ add w21,w21,w17 // h+=Ch(e,f,g)
+ and w28,w28,w19 // (b^c)&=(a^b)
+ eor w7,w7,w0,ror#19
+ eor w8,w8,w3,lsr#3 // sigma0(X[i+1])
+ add w21,w21,w16 // h+=Sigma1(e)
+ eor w28,w28,w23 // Maj(a,b,c)
+ eor w17,w9,w22,ror#22 // Sigma0(a)
+ eor w7,w7,w0,lsr#10 // sigma1(X[i+14])
+ add w2,w2,w11
+ add w25,w25,w21 // d+=h
+ add w21,w21,w28 // h+=Maj(a,b,c)
+ ldr w28,[x30],#4 // *K++, w19 in next round
+ add w2,w2,w8
+ add w21,w21,w17 // h+=Sigma0(a)
+ add w2,w2,w7
+ ldr w7,[sp,#0]
+ str w10,[sp,#12]
+ ror w16,w25,#6
+ add w20,w20,w28 // h+=K[i]
+ ror w9,w4,#7
+ and w17,w26,w25
+ ror w8,w1,#17
+ bic w28,w27,w25
+ ror w10,w21,#2
+ add w20,w20,w2 // h+=X[i]
+ eor w16,w16,w25,ror#11
+ eor w9,w9,w4,ror#18
+ orr w17,w17,w28 // Ch(e,f,g)
+ eor w28,w21,w22 // a^b, b^c in next round
+ eor w16,w16,w25,ror#25 // Sigma1(e)
+ eor w10,w10,w21,ror#13
+ add w20,w20,w17 // h+=Ch(e,f,g)
+ and w19,w19,w28 // (b^c)&=(a^b)
+ eor w8,w8,w1,ror#19
+ eor w9,w9,w4,lsr#3 // sigma0(X[i+1])
+ add w20,w20,w16 // h+=Sigma1(e)
+ eor w19,w19,w22 // Maj(a,b,c)
+ eor w17,w10,w21,ror#22 // Sigma0(a)
+ eor w8,w8,w1,lsr#10 // sigma1(X[i+14])
+ add w3,w3,w12
+ add w24,w24,w20 // d+=h
+ add w20,w20,w19 // h+=Maj(a,b,c)
+ ldr w19,[x30],#4 // *K++, w28 in next round
+ add w3,w3,w9
+ add w20,w20,w17 // h+=Sigma0(a)
+ add w3,w3,w8
+ cbnz w19,.Loop_16_xx
+
+ ldp x0,x2,[x29,#96]
+ ldr x1,[x29,#112]
+ sub x30,x30,#260 // rewind
+
+ ldp w3,w4,[x0]
+ ldp w5,w6,[x0,#2*4]
+ add x1,x1,#14*4 // advance input pointer
+ ldp w7,w8,[x0,#4*4]
+ add w20,w20,w3
+ ldp w9,w10,[x0,#6*4]
+ add w21,w21,w4
+ add w22,w22,w5
+ add w23,w23,w6
+ stp w20,w21,[x0]
+ add w24,w24,w7
+ add w25,w25,w8
+ stp w22,w23,[x0,#2*4]
+ add w26,w26,w9
+ add w27,w27,w10
+ cmp x1,x2
+ stp w24,w25,[x0,#4*4]
+ stp w26,w27,[x0,#6*4]
+ b.ne .Loop
+
+ ldp x19,x20,[x29,#16]
+ add sp,sp,#4*4
+ ldp x21,x22,[x29,#32]
+ ldp x23,x24,[x29,#48]
+ ldp x25,x26,[x29,#64]
+ ldp x27,x28,[x29,#80]
+ ldp x29,x30,[sp],#128
+ ret
+.size sha256_block_data_order,.-sha256_block_data_order
+
+.align 6
+.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
+ .long 0 //terminator
+.size K256,.-K256
+.align 3
+.LOPENSSL_armcap_P:
+ .quad OPENSSL_armcap_P-.
+.asciz "SHA256 block transform for ARMv8, CRYPTOGAMS by <appro@openssl.org>"
+.align 2
+.type sha256_block_armv8,%function
+.align 6
+sha256_block_armv8:
+.Lv8_entry:
+ stp x29,x30,[sp,#-16]!
+ add x29,sp,#0
+
+ ld1 {v0.4s,v1.4s},[x0]
+ adr x3,K256
+
+.Loop_hw:
+ ld1 {v4.16b-v7.16b},[x1],#64
+ sub x2,x2,#1
+ ld1 {v16.4s},[x3],#16
+ rev32 v4.16b,v4.16b
+ rev32 v5.16b,v5.16b
+ rev32 v6.16b,v6.16b
+ rev32 v7.16b,v7.16b
+ orr v18.16b,v0.16b,v0.16b // offload
+ orr v19.16b,v1.16b,v1.16b
+ ld1 {v17.4s},[x3],#16
+ add v16.4s,v16.4s,v4.4s
+ .inst 0x5e2828a4 //sha256su0 v4.16b,v5.16b
+ orr v2.16b,v0.16b,v0.16b
+ .inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s
+ .inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s
+ .inst 0x5e0760c4 //sha256su1 v4.16b,v6.16b,v7.16b
+ ld1 {v16.4s},[x3],#16
+ add v17.4s,v17.4s,v5.4s
+ .inst 0x5e2828c5 //sha256su0 v5.16b,v6.16b
+ orr v2.16b,v0.16b,v0.16b
+ .inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s
+ .inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s
+ .inst 0x5e0460e5 //sha256su1 v5.16b,v7.16b,v4.16b
+ ld1 {v17.4s},[x3],#16
+ add v16.4s,v16.4s,v6.4s
+ .inst 0x5e2828e6 //sha256su0 v6.16b,v7.16b
+ orr v2.16b,v0.16b,v0.16b
+ .inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s
+ .inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s
+ .inst 0x5e056086 //sha256su1 v6.16b,v4.16b,v5.16b
+ ld1 {v16.4s},[x3],#16
+ add v17.4s,v17.4s,v7.4s
+ .inst 0x5e282887 //sha256su0 v7.16b,v4.16b
+ orr v2.16b,v0.16b,v0.16b
+ .inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s
+ .inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s
+ .inst 0x5e0660a7 //sha256su1 v7.16b,v5.16b,v6.16b
+ ld1 {v17.4s},[x3],#16
+ add v16.4s,v16.4s,v4.4s
+ .inst 0x5e2828a4 //sha256su0 v4.16b,v5.16b
+ orr v2.16b,v0.16b,v0.16b
+ .inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s
+ .inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s
+ .inst 0x5e0760c4 //sha256su1 v4.16b,v6.16b,v7.16b
+ ld1 {v16.4s},[x3],#16
+ add v17.4s,v17.4s,v5.4s
+ .inst 0x5e2828c5 //sha256su0 v5.16b,v6.16b
+ orr v2.16b,v0.16b,v0.16b
+ .inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s
+ .inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s
+ .inst 0x5e0460e5 //sha256su1 v5.16b,v7.16b,v4.16b
+ ld1 {v17.4s},[x3],#16
+ add v16.4s,v16.4s,v6.4s
+ .inst 0x5e2828e6 //sha256su0 v6.16b,v7.16b
+ orr v2.16b,v0.16b,v0.16b
+ .inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s
+ .inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s
+ .inst 0x5e056086 //sha256su1 v6.16b,v4.16b,v5.16b
+ ld1 {v16.4s},[x3],#16
+ add v17.4s,v17.4s,v7.4s
+ .inst 0x5e282887 //sha256su0 v7.16b,v4.16b
+ orr v2.16b,v0.16b,v0.16b
+ .inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s
+ .inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s
+ .inst 0x5e0660a7 //sha256su1 v7.16b,v5.16b,v6.16b
+ ld1 {v17.4s},[x3],#16
+ add v16.4s,v16.4s,v4.4s
+ .inst 0x5e2828a4 //sha256su0 v4.16b,v5.16b
+ orr v2.16b,v0.16b,v0.16b
+ .inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s
+ .inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s
+ .inst 0x5e0760c4 //sha256su1 v4.16b,v6.16b,v7.16b
+ ld1 {v16.4s},[x3],#16
+ add v17.4s,v17.4s,v5.4s
+ .inst 0x5e2828c5 //sha256su0 v5.16b,v6.16b
+ orr v2.16b,v0.16b,v0.16b
+ .inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s
+ .inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s
+ .inst 0x5e0460e5 //sha256su1 v5.16b,v7.16b,v4.16b
+ ld1 {v17.4s},[x3],#16
+ add v16.4s,v16.4s,v6.4s
+ .inst 0x5e2828e6 //sha256su0 v6.16b,v7.16b
+ orr v2.16b,v0.16b,v0.16b
+ .inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s
+ .inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s
+ .inst 0x5e056086 //sha256su1 v6.16b,v4.16b,v5.16b
+ ld1 {v16.4s},[x3],#16
+ add v17.4s,v17.4s,v7.4s
+ .inst 0x5e282887 //sha256su0 v7.16b,v4.16b
+ orr v2.16b,v0.16b,v0.16b
+ .inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s
+ .inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s
+ .inst 0x5e0660a7 //sha256su1 v7.16b,v5.16b,v6.16b
+ ld1 {v17.4s},[x3],#16
+ add v16.4s,v16.4s,v4.4s
+ orr v2.16b,v0.16b,v0.16b
+ .inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s
+ .inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s
+
+ ld1 {v16.4s},[x3],#16
+ add v17.4s,v17.4s,v5.4s
+ orr v2.16b,v0.16b,v0.16b
+ .inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s
+ .inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s
+
+ ld1 {v17.4s},[x3]
+ add v16.4s,v16.4s,v6.4s
+ sub x3,x3,#64*4-16 // rewind
+ orr v2.16b,v0.16b,v0.16b
+ .inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s
+ .inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s
+
+ add v17.4s,v17.4s,v7.4s
+ orr v2.16b,v0.16b,v0.16b
+ .inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s
+ .inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s
+
+ add v0.4s,v0.4s,v18.4s
+ add v1.4s,v1.4s,v19.4s
+
+ cbnz x2,.Loop_hw
+
+ st1 {v0.4s,v1.4s},[x0]
+
+ ldr x29,[sp],#16
+ ret
+.size sha256_block_armv8,.-sha256_block_armv8
+.comm OPENSSL_armcap_P,4,4
diff --git a/linux-aarch64/crypto/sha/sha512-armv8.S b/linux-aarch64/crypto/sha/sha512-armv8.S
new file mode 100644
index 0000000..6b0d194
--- /dev/null
+++ b/linux-aarch64/crypto/sha/sha512-armv8.S
@@ -0,0 +1,1021 @@
+#include "arm_arch.h"
+
+.text
+
+.globl sha512_block_data_order
+.type sha512_block_data_order,%function
+.align 6
+sha512_block_data_order:
+ stp x29,x30,[sp,#-128]!
+ add x29,sp,#0
+
+ stp x19,x20,[sp,#16]
+ stp x21,x22,[sp,#32]
+ stp x23,x24,[sp,#48]
+ stp x25,x26,[sp,#64]
+ stp x27,x28,[sp,#80]
+ sub sp,sp,#4*8
+
+ ldp x20,x21,[x0] // load context
+ ldp x22,x23,[x0,#2*8]
+ ldp x24,x25,[x0,#4*8]
+ add x2,x1,x2,lsl#7 // end of input
+ ldp x26,x27,[x0,#6*8]
+ adr x30,K512
+ stp x0,x2,[x29,#96]
+
+.Loop:
+ ldp x3,x4,[x1],#2*8
+ ldr x19,[x30],#8 // *K++
+ eor x28,x21,x22 // magic seed
+ str x1,[x29,#112]
+#ifndef __ARMEB__
+ rev x3,x3 // 0
+#endif
+ ror x16,x24,#14
+ add x27,x27,x19 // h+=K[i]
+ eor x6,x24,x24,ror#23
+ and x17,x25,x24
+ bic x19,x26,x24
+ add x27,x27,x3 // h+=X[i]
+ orr x17,x17,x19 // Ch(e,f,g)
+ eor x19,x20,x21 // a^b, b^c in next round
+ eor x16,x16,x6,ror#18 // Sigma1(e)
+ ror x6,x20,#28
+ add x27,x27,x17 // h+=Ch(e,f,g)
+ eor x17,x20,x20,ror#5
+ add x27,x27,x16 // h+=Sigma1(e)
+ and x28,x28,x19 // (b^c)&=(a^b)
+ add x23,x23,x27 // d+=h
+ eor x28,x28,x21 // Maj(a,b,c)
+ eor x17,x6,x17,ror#34 // Sigma0(a)
+ add x27,x27,x28 // h+=Maj(a,b,c)
+ ldr x28,[x30],#8 // *K++, x19 in next round
+ //add x27,x27,x17 // h+=Sigma0(a)
+#ifndef __ARMEB__
+ rev x4,x4 // 1
+#endif
+ ldp x5,x6,[x1],#2*8
+ add x27,x27,x17 // h+=Sigma0(a)
+ ror x16,x23,#14
+ add x26,x26,x28 // h+=K[i]
+ eor x7,x23,x23,ror#23
+ and x17,x24,x23
+ bic x28,x25,x23
+ add x26,x26,x4 // h+=X[i]
+ orr x17,x17,x28 // Ch(e,f,g)
+ eor x28,x27,x20 // a^b, b^c in next round
+ eor x16,x16,x7,ror#18 // Sigma1(e)
+ ror x7,x27,#28
+ add x26,x26,x17 // h+=Ch(e,f,g)
+ eor x17,x27,x27,ror#5
+ add x26,x26,x16 // h+=Sigma1(e)
+ and x19,x19,x28 // (b^c)&=(a^b)
+ add x22,x22,x26 // d+=h
+ eor x19,x19,x20 // Maj(a,b,c)
+ eor x17,x7,x17,ror#34 // Sigma0(a)
+ add x26,x26,x19 // h+=Maj(a,b,c)
+ ldr x19,[x30],#8 // *K++, x28 in next round
+ //add x26,x26,x17 // h+=Sigma0(a)
+#ifndef __ARMEB__
+ rev x5,x5 // 2
+#endif
+ add x26,x26,x17 // h+=Sigma0(a)
+ ror x16,x22,#14
+ add x25,x25,x19 // h+=K[i]
+ eor x8,x22,x22,ror#23
+ and x17,x23,x22
+ bic x19,x24,x22
+ add x25,x25,x5 // h+=X[i]
+ orr x17,x17,x19 // Ch(e,f,g)
+ eor x19,x26,x27 // a^b, b^c in next round
+ eor x16,x16,x8,ror#18 // Sigma1(e)
+ ror x8,x26,#28
+ add x25,x25,x17 // h+=Ch(e,f,g)
+ eor x17,x26,x26,ror#5
+ add x25,x25,x16 // h+=Sigma1(e)
+ and x28,x28,x19 // (b^c)&=(a^b)
+ add x21,x21,x25 // d+=h
+ eor x28,x28,x27 // Maj(a,b,c)
+ eor x17,x8,x17,ror#34 // Sigma0(a)
+ add x25,x25,x28 // h+=Maj(a,b,c)
+ ldr x28,[x30],#8 // *K++, x19 in next round
+ //add x25,x25,x17 // h+=Sigma0(a)
+#ifndef __ARMEB__
+ rev x6,x6 // 3
+#endif
+ ldp x7,x8,[x1],#2*8
+ add x25,x25,x17 // h+=Sigma0(a)
+ ror x16,x21,#14
+ add x24,x24,x28 // h+=K[i]
+ eor x9,x21,x21,ror#23
+ and x17,x22,x21
+ bic x28,x23,x21
+ add x24,x24,x6 // h+=X[i]
+ orr x17,x17,x28 // Ch(e,f,g)
+ eor x28,x25,x26 // a^b, b^c in next round
+ eor x16,x16,x9,ror#18 // Sigma1(e)
+ ror x9,x25,#28
+ add x24,x24,x17 // h+=Ch(e,f,g)
+ eor x17,x25,x25,ror#5
+ add x24,x24,x16 // h+=Sigma1(e)
+ and x19,x19,x28 // (b^c)&=(a^b)
+ add x20,x20,x24 // d+=h
+ eor x19,x19,x26 // Maj(a,b,c)
+ eor x17,x9,x17,ror#34 // Sigma0(a)
+ add x24,x24,x19 // h+=Maj(a,b,c)
+ ldr x19,[x30],#8 // *K++, x28 in next round
+ //add x24,x24,x17 // h+=Sigma0(a)
+#ifndef __ARMEB__
+ rev x7,x7 // 4
+#endif
+ add x24,x24,x17 // h+=Sigma0(a)
+ ror x16,x20,#14
+ add x23,x23,x19 // h+=K[i]
+ eor x10,x20,x20,ror#23
+ and x17,x21,x20
+ bic x19,x22,x20
+ add x23,x23,x7 // h+=X[i]
+ orr x17,x17,x19 // Ch(e,f,g)
+ eor x19,x24,x25 // a^b, b^c in next round
+ eor x16,x16,x10,ror#18 // Sigma1(e)
+ ror x10,x24,#28
+ add x23,x23,x17 // h+=Ch(e,f,g)
+ eor x17,x24,x24,ror#5
+ add x23,x23,x16 // h+=Sigma1(e)
+ and x28,x28,x19 // (b^c)&=(a^b)
+ add x27,x27,x23 // d+=h
+ eor x28,x28,x25 // Maj(a,b,c)
+ eor x17,x10,x17,ror#34 // Sigma0(a)
+ add x23,x23,x28 // h+=Maj(a,b,c)
+ ldr x28,[x30],#8 // *K++, x19 in next round
+ //add x23,x23,x17 // h+=Sigma0(a)
+#ifndef __ARMEB__
+ rev x8,x8 // 5
+#endif
+ ldp x9,x10,[x1],#2*8
+ add x23,x23,x17 // h+=Sigma0(a)
+ ror x16,x27,#14
+ add x22,x22,x28 // h+=K[i]
+ eor x11,x27,x27,ror#23
+ and x17,x20,x27
+ bic x28,x21,x27
+ add x22,x22,x8 // h+=X[i]
+ orr x17,x17,x28 // Ch(e,f,g)
+ eor x28,x23,x24 // a^b, b^c in next round
+ eor x16,x16,x11,ror#18 // Sigma1(e)
+ ror x11,x23,#28
+ add x22,x22,x17 // h+=Ch(e,f,g)
+ eor x17,x23,x23,ror#5
+ add x22,x22,x16 // h+=Sigma1(e)
+ and x19,x19,x28 // (b^c)&=(a^b)
+ add x26,x26,x22 // d+=h
+ eor x19,x19,x24 // Maj(a,b,c)
+ eor x17,x11,x17,ror#34 // Sigma0(a)
+ add x22,x22,x19 // h+=Maj(a,b,c)
+ ldr x19,[x30],#8 // *K++, x28 in next round
+ //add x22,x22,x17 // h+=Sigma0(a)
+#ifndef __ARMEB__
+ rev x9,x9 // 6
+#endif
+ add x22,x22,x17 // h+=Sigma0(a)
+ ror x16,x26,#14
+ add x21,x21,x19 // h+=K[i]
+ eor x12,x26,x26,ror#23
+ and x17,x27,x26
+ bic x19,x20,x26
+ add x21,x21,x9 // h+=X[i]
+ orr x17,x17,x19 // Ch(e,f,g)
+ eor x19,x22,x23 // a^b, b^c in next round
+ eor x16,x16,x12,ror#18 // Sigma1(e)
+ ror x12,x22,#28
+ add x21,x21,x17 // h+=Ch(e,f,g)
+ eor x17,x22,x22,ror#5
+ add x21,x21,x16 // h+=Sigma1(e)
+ and x28,x28,x19 // (b^c)&=(a^b)
+ add x25,x25,x21 // d+=h
+ eor x28,x28,x23 // Maj(a,b,c)
+ eor x17,x12,x17,ror#34 // Sigma0(a)
+ add x21,x21,x28 // h+=Maj(a,b,c)
+ ldr x28,[x30],#8 // *K++, x19 in next round
+ //add x21,x21,x17 // h+=Sigma0(a)
+#ifndef __ARMEB__
+ rev x10,x10 // 7
+#endif
+ ldp x11,x12,[x1],#2*8
+ add x21,x21,x17 // h+=Sigma0(a)
+ ror x16,x25,#14
+ add x20,x20,x28 // h+=K[i]
+ eor x13,x25,x25,ror#23
+ and x17,x26,x25
+ bic x28,x27,x25
+ add x20,x20,x10 // h+=X[i]
+ orr x17,x17,x28 // Ch(e,f,g)
+ eor x28,x21,x22 // a^b, b^c in next round
+ eor x16,x16,x13,ror#18 // Sigma1(e)
+ ror x13,x21,#28
+ add x20,x20,x17 // h+=Ch(e,f,g)
+ eor x17,x21,x21,ror#5
+ add x20,x20,x16 // h+=Sigma1(e)
+ and x19,x19,x28 // (b^c)&=(a^b)
+ add x24,x24,x20 // d+=h
+ eor x19,x19,x22 // Maj(a,b,c)
+ eor x17,x13,x17,ror#34 // Sigma0(a)
+ add x20,x20,x19 // h+=Maj(a,b,c)
+ ldr x19,[x30],#8 // *K++, x28 in next round
+ //add x20,x20,x17 // h+=Sigma0(a)
+#ifndef __ARMEB__
+ rev x11,x11 // 8
+#endif
+ add x20,x20,x17 // h+=Sigma0(a)
+ ror x16,x24,#14
+ add x27,x27,x19 // h+=K[i]
+ eor x14,x24,x24,ror#23
+ and x17,x25,x24
+ bic x19,x26,x24
+ add x27,x27,x11 // h+=X[i]
+ orr x17,x17,x19 // Ch(e,f,g)
+ eor x19,x20,x21 // a^b, b^c in next round
+ eor x16,x16,x14,ror#18 // Sigma1(e)
+ ror x14,x20,#28
+ add x27,x27,x17 // h+=Ch(e,f,g)
+ eor x17,x20,x20,ror#5
+ add x27,x27,x16 // h+=Sigma1(e)
+ and x28,x28,x19 // (b^c)&=(a^b)
+ add x23,x23,x27 // d+=h
+ eor x28,x28,x21 // Maj(a,b,c)
+ eor x17,x14,x17,ror#34 // Sigma0(a)
+ add x27,x27,x28 // h+=Maj(a,b,c)
+ ldr x28,[x30],#8 // *K++, x19 in next round
+ //add x27,x27,x17 // h+=Sigma0(a)
+#ifndef __ARMEB__
+ rev x12,x12 // 9
+#endif
+ ldp x13,x14,[x1],#2*8
+ add x27,x27,x17 // h+=Sigma0(a)
+ ror x16,x23,#14
+ add x26,x26,x28 // h+=K[i]
+ eor x15,x23,x23,ror#23
+ and x17,x24,x23
+ bic x28,x25,x23
+ add x26,x26,x12 // h+=X[i]
+ orr x17,x17,x28 // Ch(e,f,g)
+ eor x28,x27,x20 // a^b, b^c in next round
+ eor x16,x16,x15,ror#18 // Sigma1(e)
+ ror x15,x27,#28
+ add x26,x26,x17 // h+=Ch(e,f,g)
+ eor x17,x27,x27,ror#5
+ add x26,x26,x16 // h+=Sigma1(e)
+ and x19,x19,x28 // (b^c)&=(a^b)
+ add x22,x22,x26 // d+=h
+ eor x19,x19,x20 // Maj(a,b,c)
+ eor x17,x15,x17,ror#34 // Sigma0(a)
+ add x26,x26,x19 // h+=Maj(a,b,c)
+ ldr x19,[x30],#8 // *K++, x28 in next round
+ //add x26,x26,x17 // h+=Sigma0(a)
+#ifndef __ARMEB__
+ rev x13,x13 // 10
+#endif
+ add x26,x26,x17 // h+=Sigma0(a)
+ ror x16,x22,#14
+ add x25,x25,x19 // h+=K[i]
+ eor x0,x22,x22,ror#23
+ and x17,x23,x22
+ bic x19,x24,x22
+ add x25,x25,x13 // h+=X[i]
+ orr x17,x17,x19 // Ch(e,f,g)
+ eor x19,x26,x27 // a^b, b^c in next round
+ eor x16,x16,x0,ror#18 // Sigma1(e)
+ ror x0,x26,#28
+ add x25,x25,x17 // h+=Ch(e,f,g)
+ eor x17,x26,x26,ror#5
+ add x25,x25,x16 // h+=Sigma1(e)
+ and x28,x28,x19 // (b^c)&=(a^b)
+ add x21,x21,x25 // d+=h
+ eor x28,x28,x27 // Maj(a,b,c)
+ eor x17,x0,x17,ror#34 // Sigma0(a)
+ add x25,x25,x28 // h+=Maj(a,b,c)
+ ldr x28,[x30],#8 // *K++, x19 in next round
+ //add x25,x25,x17 // h+=Sigma0(a)
+#ifndef __ARMEB__
+ rev x14,x14 // 11
+#endif
+ ldp x15,x0,[x1],#2*8
+ add x25,x25,x17 // h+=Sigma0(a)
+ str x6,[sp,#24]
+ ror x16,x21,#14
+ add x24,x24,x28 // h+=K[i]
+ eor x6,x21,x21,ror#23
+ and x17,x22,x21
+ bic x28,x23,x21
+ add x24,x24,x14 // h+=X[i]
+ orr x17,x17,x28 // Ch(e,f,g)
+ eor x28,x25,x26 // a^b, b^c in next round
+ eor x16,x16,x6,ror#18 // Sigma1(e)
+ ror x6,x25,#28
+ add x24,x24,x17 // h+=Ch(e,f,g)
+ eor x17,x25,x25,ror#5
+ add x24,x24,x16 // h+=Sigma1(e)
+ and x19,x19,x28 // (b^c)&=(a^b)
+ add x20,x20,x24 // d+=h
+ eor x19,x19,x26 // Maj(a,b,c)
+ eor x17,x6,x17,ror#34 // Sigma0(a)
+ add x24,x24,x19 // h+=Maj(a,b,c)
+ ldr x19,[x30],#8 // *K++, x28 in next round
+ //add x24,x24,x17 // h+=Sigma0(a)
+#ifndef __ARMEB__
+ rev x15,x15 // 12
+#endif
+ add x24,x24,x17 // h+=Sigma0(a)
+ str x7,[sp,#0]
+ ror x16,x20,#14
+ add x23,x23,x19 // h+=K[i]
+ eor x7,x20,x20,ror#23
+ and x17,x21,x20
+ bic x19,x22,x20
+ add x23,x23,x15 // h+=X[i]
+ orr x17,x17,x19 // Ch(e,f,g)
+ eor x19,x24,x25 // a^b, b^c in next round
+ eor x16,x16,x7,ror#18 // Sigma1(e)
+ ror x7,x24,#28
+ add x23,x23,x17 // h+=Ch(e,f,g)
+ eor x17,x24,x24,ror#5
+ add x23,x23,x16 // h+=Sigma1(e)
+ and x28,x28,x19 // (b^c)&=(a^b)
+ add x27,x27,x23 // d+=h
+ eor x28,x28,x25 // Maj(a,b,c)
+ eor x17,x7,x17,ror#34 // Sigma0(a)
+ add x23,x23,x28 // h+=Maj(a,b,c)
+ ldr x28,[x30],#8 // *K++, x19 in next round
+ //add x23,x23,x17 // h+=Sigma0(a)
+#ifndef __ARMEB__
+ rev x0,x0 // 13
+#endif
+ ldp x1,x2,[x1]
+ add x23,x23,x17 // h+=Sigma0(a)
+ str x8,[sp,#8]
+ ror x16,x27,#14
+ add x22,x22,x28 // h+=K[i]
+ eor x8,x27,x27,ror#23
+ and x17,x20,x27
+ bic x28,x21,x27
+ add x22,x22,x0 // h+=X[i]
+ orr x17,x17,x28 // Ch(e,f,g)
+ eor x28,x23,x24 // a^b, b^c in next round
+ eor x16,x16,x8,ror#18 // Sigma1(e)
+ ror x8,x23,#28
+ add x22,x22,x17 // h+=Ch(e,f,g)
+ eor x17,x23,x23,ror#5
+ add x22,x22,x16 // h+=Sigma1(e)
+ and x19,x19,x28 // (b^c)&=(a^b)
+ add x26,x26,x22 // d+=h
+ eor x19,x19,x24 // Maj(a,b,c)
+ eor x17,x8,x17,ror#34 // Sigma0(a)
+ add x22,x22,x19 // h+=Maj(a,b,c)
+ ldr x19,[x30],#8 // *K++, x28 in next round
+ //add x22,x22,x17 // h+=Sigma0(a)
+#ifndef __ARMEB__
+ rev x1,x1 // 14
+#endif
+ ldr x6,[sp,#24]
+ add x22,x22,x17 // h+=Sigma0(a)
+ str x9,[sp,#16]
+ ror x16,x26,#14
+ add x21,x21,x19 // h+=K[i]
+ eor x9,x26,x26,ror#23
+ and x17,x27,x26
+ bic x19,x20,x26
+ add x21,x21,x1 // h+=X[i]
+ orr x17,x17,x19 // Ch(e,f,g)
+ eor x19,x22,x23 // a^b, b^c in next round
+ eor x16,x16,x9,ror#18 // Sigma1(e)
+ ror x9,x22,#28
+ add x21,x21,x17 // h+=Ch(e,f,g)
+ eor x17,x22,x22,ror#5
+ add x21,x21,x16 // h+=Sigma1(e)
+ and x28,x28,x19 // (b^c)&=(a^b)
+ add x25,x25,x21 // d+=h
+ eor x28,x28,x23 // Maj(a,b,c)
+ eor x17,x9,x17,ror#34 // Sigma0(a)
+ add x21,x21,x28 // h+=Maj(a,b,c)
+ ldr x28,[x30],#8 // *K++, x19 in next round
+ //add x21,x21,x17 // h+=Sigma0(a)
+#ifndef __ARMEB__
+ rev x2,x2 // 15
+#endif
+ ldr x7,[sp,#0]
+ add x21,x21,x17 // h+=Sigma0(a)
+ str x10,[sp,#24]
+ ror x16,x25,#14
+ add x20,x20,x28 // h+=K[i]
+ ror x9,x4,#1
+ and x17,x26,x25
+ ror x8,x1,#19
+ bic x28,x27,x25
+ ror x10,x21,#28
+ add x20,x20,x2 // h+=X[i]
+ eor x16,x16,x25,ror#18
+ eor x9,x9,x4,ror#8
+ orr x17,x17,x28 // Ch(e,f,g)
+ eor x28,x21,x22 // a^b, b^c in next round
+ eor x16,x16,x25,ror#41 // Sigma1(e)
+ eor x10,x10,x21,ror#34
+ add x20,x20,x17 // h+=Ch(e,f,g)
+ and x19,x19,x28 // (b^c)&=(a^b)
+ eor x8,x8,x1,ror#61
+ eor x9,x9,x4,lsr#7 // sigma0(X[i+1])
+ add x20,x20,x16 // h+=Sigma1(e)
+ eor x19,x19,x22 // Maj(a,b,c)
+ eor x17,x10,x21,ror#39 // Sigma0(a)
+ eor x8,x8,x1,lsr#6 // sigma1(X[i+14])
+ add x3,x3,x12
+ add x24,x24,x20 // d+=h
+ add x20,x20,x19 // h+=Maj(a,b,c)
+ ldr x19,[x30],#8 // *K++, x28 in next round
+ add x3,x3,x9
+ add x20,x20,x17 // h+=Sigma0(a)
+ add x3,x3,x8
+.Loop_16_xx:
+ ldr x8,[sp,#8]
+ str x11,[sp,#0]
+ ror x16,x24,#14
+ add x27,x27,x19 // h+=K[i]
+ ror x10,x5,#1
+ and x17,x25,x24
+ ror x9,x2,#19
+ bic x19,x26,x24
+ ror x11,x20,#28
+ add x27,x27,x3 // h+=X[i]
+ eor x16,x16,x24,ror#18
+ eor x10,x10,x5,ror#8
+ orr x17,x17,x19 // Ch(e,f,g)
+ eor x19,x20,x21 // a^b, b^c in next round
+ eor x16,x16,x24,ror#41 // Sigma1(e)
+ eor x11,x11,x20,ror#34
+ add x27,x27,x17 // h+=Ch(e,f,g)
+ and x28,x28,x19 // (b^c)&=(a^b)
+ eor x9,x9,x2,ror#61
+ eor x10,x10,x5,lsr#7 // sigma0(X[i+1])
+ add x27,x27,x16 // h+=Sigma1(e)
+ eor x28,x28,x21 // Maj(a,b,c)
+ eor x17,x11,x20,ror#39 // Sigma0(a)
+ eor x9,x9,x2,lsr#6 // sigma1(X[i+14])
+ add x4,x4,x13
+ add x23,x23,x27 // d+=h
+ add x27,x27,x28 // h+=Maj(a,b,c)
+ ldr x28,[x30],#8 // *K++, x19 in next round
+ add x4,x4,x10
+ add x27,x27,x17 // h+=Sigma0(a)
+ add x4,x4,x9
+ ldr x9,[sp,#16]
+ str x12,[sp,#8]
+ ror x16,x23,#14
+ add x26,x26,x28 // h+=K[i]
+ ror x11,x6,#1
+ and x17,x24,x23
+ ror x10,x3,#19
+ bic x28,x25,x23
+ ror x12,x27,#28
+ add x26,x26,x4 // h+=X[i]
+ eor x16,x16,x23,ror#18
+ eor x11,x11,x6,ror#8
+ orr x17,x17,x28 // Ch(e,f,g)
+ eor x28,x27,x20 // a^b, b^c in next round
+ eor x16,x16,x23,ror#41 // Sigma1(e)
+ eor x12,x12,x27,ror#34
+ add x26,x26,x17 // h+=Ch(e,f,g)
+ and x19,x19,x28 // (b^c)&=(a^b)
+ eor x10,x10,x3,ror#61
+ eor x11,x11,x6,lsr#7 // sigma0(X[i+1])
+ add x26,x26,x16 // h+=Sigma1(e)
+ eor x19,x19,x20 // Maj(a,b,c)
+ eor x17,x12,x27,ror#39 // Sigma0(a)
+ eor x10,x10,x3,lsr#6 // sigma1(X[i+14])
+ add x5,x5,x14
+ add x22,x22,x26 // d+=h
+ add x26,x26,x19 // h+=Maj(a,b,c)
+ ldr x19,[x30],#8 // *K++, x28 in next round
+ add x5,x5,x11
+ add x26,x26,x17 // h+=Sigma0(a)
+ add x5,x5,x10
+ ldr x10,[sp,#24]
+ str x13,[sp,#16]
+ ror x16,x22,#14
+ add x25,x25,x19 // h+=K[i]
+ ror x12,x7,#1
+ and x17,x23,x22
+ ror x11,x4,#19
+ bic x19,x24,x22
+ ror x13,x26,#28
+ add x25,x25,x5 // h+=X[i]
+ eor x16,x16,x22,ror#18
+ eor x12,x12,x7,ror#8
+ orr x17,x17,x19 // Ch(e,f,g)
+ eor x19,x26,x27 // a^b, b^c in next round
+ eor x16,x16,x22,ror#41 // Sigma1(e)
+ eor x13,x13,x26,ror#34
+ add x25,x25,x17 // h+=Ch(e,f,g)
+ and x28,x28,x19 // (b^c)&=(a^b)
+ eor x11,x11,x4,ror#61
+ eor x12,x12,x7,lsr#7 // sigma0(X[i+1])
+ add x25,x25,x16 // h+=Sigma1(e)
+ eor x28,x28,x27 // Maj(a,b,c)
+ eor x17,x13,x26,ror#39 // Sigma0(a)
+ eor x11,x11,x4,lsr#6 // sigma1(X[i+14])
+ add x6,x6,x15
+ add x21,x21,x25 // d+=h
+ add x25,x25,x28 // h+=Maj(a,b,c)
+ ldr x28,[x30],#8 // *K++, x19 in next round
+ add x6,x6,x12
+ add x25,x25,x17 // h+=Sigma0(a)
+ add x6,x6,x11
+ ldr x11,[sp,#0]
+ str x14,[sp,#24]
+ ror x16,x21,#14
+ add x24,x24,x28 // h+=K[i]
+ ror x13,x8,#1
+ and x17,x22,x21
+ ror x12,x5,#19
+ bic x28,x23,x21
+ ror x14,x25,#28
+ add x24,x24,x6 // h+=X[i]
+ eor x16,x16,x21,ror#18
+ eor x13,x13,x8,ror#8
+ orr x17,x17,x28 // Ch(e,f,g)
+ eor x28,x25,x26 // a^b, b^c in next round
+ eor x16,x16,x21,ror#41 // Sigma1(e)
+ eor x14,x14,x25,ror#34
+ add x24,x24,x17 // h+=Ch(e,f,g)
+ and x19,x19,x28 // (b^c)&=(a^b)
+ eor x12,x12,x5,ror#61
+ eor x13,x13,x8,lsr#7 // sigma0(X[i+1])
+ add x24,x24,x16 // h+=Sigma1(e)
+ eor x19,x19,x26 // Maj(a,b,c)
+ eor x17,x14,x25,ror#39 // Sigma0(a)
+ eor x12,x12,x5,lsr#6 // sigma1(X[i+14])
+ add x7,x7,x0
+ add x20,x20,x24 // d+=h
+ add x24,x24,x19 // h+=Maj(a,b,c)
+ ldr x19,[x30],#8 // *K++, x28 in next round
+ add x7,x7,x13
+ add x24,x24,x17 // h+=Sigma0(a)
+ add x7,x7,x12
+ ldr x12,[sp,#8]
+ str x15,[sp,#0]
+ ror x16,x20,#14
+ add x23,x23,x19 // h+=K[i]
+ ror x14,x9,#1
+ and x17,x21,x20
+ ror x13,x6,#19
+ bic x19,x22,x20
+ ror x15,x24,#28
+ add x23,x23,x7 // h+=X[i]
+ eor x16,x16,x20,ror#18
+ eor x14,x14,x9,ror#8
+ orr x17,x17,x19 // Ch(e,f,g)
+ eor x19,x24,x25 // a^b, b^c in next round
+ eor x16,x16,x20,ror#41 // Sigma1(e)
+ eor x15,x15,x24,ror#34
+ add x23,x23,x17 // h+=Ch(e,f,g)
+ and x28,x28,x19 // (b^c)&=(a^b)
+ eor x13,x13,x6,ror#61
+ eor x14,x14,x9,lsr#7 // sigma0(X[i+1])
+ add x23,x23,x16 // h+=Sigma1(e)
+ eor x28,x28,x25 // Maj(a,b,c)
+ eor x17,x15,x24,ror#39 // Sigma0(a)
+ eor x13,x13,x6,lsr#6 // sigma1(X[i+14])
+ add x8,x8,x1
+ add x27,x27,x23 // d+=h
+ add x23,x23,x28 // h+=Maj(a,b,c)
+ ldr x28,[x30],#8 // *K++, x19 in next round
+ add x8,x8,x14
+ add x23,x23,x17 // h+=Sigma0(a)
+ add x8,x8,x13
+ ldr x13,[sp,#16]
+ str x0,[sp,#8]
+ ror x16,x27,#14
+ add x22,x22,x28 // h+=K[i]
+ ror x15,x10,#1
+ and x17,x20,x27
+ ror x14,x7,#19
+ bic x28,x21,x27
+ ror x0,x23,#28
+ add x22,x22,x8 // h+=X[i]
+ eor x16,x16,x27,ror#18
+ eor x15,x15,x10,ror#8
+ orr x17,x17,x28 // Ch(e,f,g)
+ eor x28,x23,x24 // a^b, b^c in next round
+ eor x16,x16,x27,ror#41 // Sigma1(e)
+ eor x0,x0,x23,ror#34
+ add x22,x22,x17 // h+=Ch(e,f,g)
+ and x19,x19,x28 // (b^c)&=(a^b)
+ eor x14,x14,x7,ror#61
+ eor x15,x15,x10,lsr#7 // sigma0(X[i+1])
+ add x22,x22,x16 // h+=Sigma1(e)
+ eor x19,x19,x24 // Maj(a,b,c)
+ eor x17,x0,x23,ror#39 // Sigma0(a)
+ eor x14,x14,x7,lsr#6 // sigma1(X[i+14])
+ add x9,x9,x2
+ add x26,x26,x22 // d+=h
+ add x22,x22,x19 // h+=Maj(a,b,c)
+ ldr x19,[x30],#8 // *K++, x28 in next round
+ add x9,x9,x15
+ add x22,x22,x17 // h+=Sigma0(a)
+ add x9,x9,x14
+ ldr x14,[sp,#24]
+ str x1,[sp,#16]
+ ror x16,x26,#14
+ add x21,x21,x19 // h+=K[i]
+ ror x0,x11,#1
+ and x17,x27,x26
+ ror x15,x8,#19
+ bic x19,x20,x26
+ ror x1,x22,#28
+ add x21,x21,x9 // h+=X[i]
+ eor x16,x16,x26,ror#18
+ eor x0,x0,x11,ror#8
+ orr x17,x17,x19 // Ch(e,f,g)
+ eor x19,x22,x23 // a^b, b^c in next round
+ eor x16,x16,x26,ror#41 // Sigma1(e)
+ eor x1,x1,x22,ror#34
+ add x21,x21,x17 // h+=Ch(e,f,g)
+ and x28,x28,x19 // (b^c)&=(a^b)
+ eor x15,x15,x8,ror#61
+ eor x0,x0,x11,lsr#7 // sigma0(X[i+1])
+ add x21,x21,x16 // h+=Sigma1(e)
+ eor x28,x28,x23 // Maj(a,b,c)
+ eor x17,x1,x22,ror#39 // Sigma0(a)
+ eor x15,x15,x8,lsr#6 // sigma1(X[i+14])
+ add x10,x10,x3
+ add x25,x25,x21 // d+=h
+ add x21,x21,x28 // h+=Maj(a,b,c)
+ ldr x28,[x30],#8 // *K++, x19 in next round
+ add x10,x10,x0
+ add x21,x21,x17 // h+=Sigma0(a)
+ add x10,x10,x15
+ ldr x15,[sp,#0]
+ str x2,[sp,#24]
+ ror x16,x25,#14
+ add x20,x20,x28 // h+=K[i]
+ ror x1,x12,#1
+ and x17,x26,x25
+ ror x0,x9,#19
+ bic x28,x27,x25
+ ror x2,x21,#28
+ add x20,x20,x10 // h+=X[i]
+ eor x16,x16,x25,ror#18
+ eor x1,x1,x12,ror#8
+ orr x17,x17,x28 // Ch(e,f,g)
+ eor x28,x21,x22 // a^b, b^c in next round
+ eor x16,x16,x25,ror#41 // Sigma1(e)
+ eor x2,x2,x21,ror#34
+ add x20,x20,x17 // h+=Ch(e,f,g)
+ and x19,x19,x28 // (b^c)&=(a^b)
+ eor x0,x0,x9,ror#61
+ eor x1,x1,x12,lsr#7 // sigma0(X[i+1])
+ add x20,x20,x16 // h+=Sigma1(e)
+ eor x19,x19,x22 // Maj(a,b,c)
+ eor x17,x2,x21,ror#39 // Sigma0(a)
+ eor x0,x0,x9,lsr#6 // sigma1(X[i+14])
+ add x11,x11,x4
+ add x24,x24,x20 // d+=h
+ add x20,x20,x19 // h+=Maj(a,b,c)
+ ldr x19,[x30],#8 // *K++, x28 in next round
+ add x11,x11,x1
+ add x20,x20,x17 // h+=Sigma0(a)
+ add x11,x11,x0
+ ldr x0,[sp,#8]
+ str x3,[sp,#0]
+ ror x16,x24,#14
+ add x27,x27,x19 // h+=K[i]
+ ror x2,x13,#1
+ and x17,x25,x24
+ ror x1,x10,#19
+ bic x19,x26,x24
+ ror x3,x20,#28
+ add x27,x27,x11 // h+=X[i]
+ eor x16,x16,x24,ror#18
+ eor x2,x2,x13,ror#8
+ orr x17,x17,x19 // Ch(e,f,g)
+ eor x19,x20,x21 // a^b, b^c in next round
+ eor x16,x16,x24,ror#41 // Sigma1(e)
+ eor x3,x3,x20,ror#34
+ add x27,x27,x17 // h+=Ch(e,f,g)
+ and x28,x28,x19 // (b^c)&=(a^b)
+ eor x1,x1,x10,ror#61
+ eor x2,x2,x13,lsr#7 // sigma0(X[i+1])
+ add x27,x27,x16 // h+=Sigma1(e)
+ eor x28,x28,x21 // Maj(a,b,c)
+ eor x17,x3,x20,ror#39 // Sigma0(a)
+ eor x1,x1,x10,lsr#6 // sigma1(X[i+14])
+ add x12,x12,x5
+ add x23,x23,x27 // d+=h
+ add x27,x27,x28 // h+=Maj(a,b,c)
+ ldr x28,[x30],#8 // *K++, x19 in next round
+ add x12,x12,x2
+ add x27,x27,x17 // h+=Sigma0(a)
+ add x12,x12,x1
+ ldr x1,[sp,#16]
+ str x4,[sp,#8]
+ ror x16,x23,#14
+ add x26,x26,x28 // h+=K[i]
+ ror x3,x14,#1
+ and x17,x24,x23
+ ror x2,x11,#19
+ bic x28,x25,x23
+ ror x4,x27,#28
+ add x26,x26,x12 // h+=X[i]
+ eor x16,x16,x23,ror#18
+ eor x3,x3,x14,ror#8
+ orr x17,x17,x28 // Ch(e,f,g)
+ eor x28,x27,x20 // a^b, b^c in next round
+ eor x16,x16,x23,ror#41 // Sigma1(e)
+ eor x4,x4,x27,ror#34
+ add x26,x26,x17 // h+=Ch(e,f,g)
+ and x19,x19,x28 // (b^c)&=(a^b)
+ eor x2,x2,x11,ror#61
+ eor x3,x3,x14,lsr#7 // sigma0(X[i+1])
+ add x26,x26,x16 // h+=Sigma1(e)
+ eor x19,x19,x20 // Maj(a,b,c)
+ eor x17,x4,x27,ror#39 // Sigma0(a)
+ eor x2,x2,x11,lsr#6 // sigma1(X[i+14])
+ add x13,x13,x6
+ add x22,x22,x26 // d+=h
+ add x26,x26,x19 // h+=Maj(a,b,c)
+ ldr x19,[x30],#8 // *K++, x28 in next round
+ add x13,x13,x3
+ add x26,x26,x17 // h+=Sigma0(a)
+ add x13,x13,x2
+ ldr x2,[sp,#24]
+ str x5,[sp,#16]
+ ror x16,x22,#14
+ add x25,x25,x19 // h+=K[i]
+ ror x4,x15,#1
+ and x17,x23,x22
+ ror x3,x12,#19
+ bic x19,x24,x22
+ ror x5,x26,#28
+ add x25,x25,x13 // h+=X[i]
+ eor x16,x16,x22,ror#18
+ eor x4,x4,x15,ror#8
+ orr x17,x17,x19 // Ch(e,f,g)
+ eor x19,x26,x27 // a^b, b^c in next round
+ eor x16,x16,x22,ror#41 // Sigma1(e)
+ eor x5,x5,x26,ror#34
+ add x25,x25,x17 // h+=Ch(e,f,g)
+ and x28,x28,x19 // (b^c)&=(a^b)
+ eor x3,x3,x12,ror#61
+ eor x4,x4,x15,lsr#7 // sigma0(X[i+1])
+ add x25,x25,x16 // h+=Sigma1(e)
+ eor x28,x28,x27 // Maj(a,b,c)
+ eor x17,x5,x26,ror#39 // Sigma0(a)
+ eor x3,x3,x12,lsr#6 // sigma1(X[i+14])
+ add x14,x14,x7
+ add x21,x21,x25 // d+=h
+ add x25,x25,x28 // h+=Maj(a,b,c)
+ ldr x28,[x30],#8 // *K++, x19 in next round
+ add x14,x14,x4
+ add x25,x25,x17 // h+=Sigma0(a)
+ add x14,x14,x3
+ ldr x3,[sp,#0]
+ str x6,[sp,#24]
+ ror x16,x21,#14
+ add x24,x24,x28 // h+=K[i]
+ ror x5,x0,#1
+ and x17,x22,x21
+ ror x4,x13,#19
+ bic x28,x23,x21
+ ror x6,x25,#28
+ add x24,x24,x14 // h+=X[i]
+ eor x16,x16,x21,ror#18
+ eor x5,x5,x0,ror#8
+ orr x17,x17,x28 // Ch(e,f,g)
+ eor x28,x25,x26 // a^b, b^c in next round
+ eor x16,x16,x21,ror#41 // Sigma1(e)
+ eor x6,x6,x25,ror#34
+ add x24,x24,x17 // h+=Ch(e,f,g)
+ and x19,x19,x28 // (b^c)&=(a^b)
+ eor x4,x4,x13,ror#61
+ eor x5,x5,x0,lsr#7 // sigma0(X[i+1])
+ add x24,x24,x16 // h+=Sigma1(e)
+ eor x19,x19,x26 // Maj(a,b,c)
+ eor x17,x6,x25,ror#39 // Sigma0(a)
+ eor x4,x4,x13,lsr#6 // sigma1(X[i+14])
+ add x15,x15,x8
+ add x20,x20,x24 // d+=h
+ add x24,x24,x19 // h+=Maj(a,b,c)
+ ldr x19,[x30],#8 // *K++, x28 in next round
+ add x15,x15,x5
+ add x24,x24,x17 // h+=Sigma0(a)
+ add x15,x15,x4
+ ldr x4,[sp,#8]
+ str x7,[sp,#0]
+ ror x16,x20,#14
+ add x23,x23,x19 // h+=K[i]
+ ror x6,x1,#1
+ and x17,x21,x20
+ ror x5,x14,#19
+ bic x19,x22,x20
+ ror x7,x24,#28
+ add x23,x23,x15 // h+=X[i]
+ eor x16,x16,x20,ror#18
+ eor x6,x6,x1,ror#8
+ orr x17,x17,x19 // Ch(e,f,g)
+ eor x19,x24,x25 // a^b, b^c in next round
+ eor x16,x16,x20,ror#41 // Sigma1(e)
+ eor x7,x7,x24,ror#34
+ add x23,x23,x17 // h+=Ch(e,f,g)
+ and x28,x28,x19 // (b^c)&=(a^b)
+ eor x5,x5,x14,ror#61
+ eor x6,x6,x1,lsr#7 // sigma0(X[i+1])
+ add x23,x23,x16 // h+=Sigma1(e)
+ eor x28,x28,x25 // Maj(a,b,c)
+ eor x17,x7,x24,ror#39 // Sigma0(a)
+ eor x5,x5,x14,lsr#6 // sigma1(X[i+14])
+ add x0,x0,x9
+ add x27,x27,x23 // d+=h
+ add x23,x23,x28 // h+=Maj(a,b,c)
+ ldr x28,[x30],#8 // *K++, x19 in next round
+ add x0,x0,x6
+ add x23,x23,x17 // h+=Sigma0(a)
+ add x0,x0,x5
+ ldr x5,[sp,#16]
+ str x8,[sp,#8]
+ ror x16,x27,#14
+ add x22,x22,x28 // h+=K[i]
+ ror x7,x2,#1
+ and x17,x20,x27
+ ror x6,x15,#19
+ bic x28,x21,x27
+ ror x8,x23,#28
+ add x22,x22,x0 // h+=X[i]
+ eor x16,x16,x27,ror#18
+ eor x7,x7,x2,ror#8
+ orr x17,x17,x28 // Ch(e,f,g)
+ eor x28,x23,x24 // a^b, b^c in next round
+ eor x16,x16,x27,ror#41 // Sigma1(e)
+ eor x8,x8,x23,ror#34
+ add x22,x22,x17 // h+=Ch(e,f,g)
+ and x19,x19,x28 // (b^c)&=(a^b)
+ eor x6,x6,x15,ror#61
+ eor x7,x7,x2,lsr#7 // sigma0(X[i+1])
+ add x22,x22,x16 // h+=Sigma1(e)
+ eor x19,x19,x24 // Maj(a,b,c)
+ eor x17,x8,x23,ror#39 // Sigma0(a)
+ eor x6,x6,x15,lsr#6 // sigma1(X[i+14])
+ add x1,x1,x10
+ add x26,x26,x22 // d+=h
+ add x22,x22,x19 // h+=Maj(a,b,c)
+ ldr x19,[x30],#8 // *K++, x28 in next round
+ add x1,x1,x7
+ add x22,x22,x17 // h+=Sigma0(a)
+ add x1,x1,x6
+ ldr x6,[sp,#24]
+ str x9,[sp,#16]
+ ror x16,x26,#14
+ add x21,x21,x19 // h+=K[i]
+ ror x8,x3,#1
+ and x17,x27,x26
+ ror x7,x0,#19
+ bic x19,x20,x26
+ ror x9,x22,#28
+ add x21,x21,x1 // h+=X[i]
+ eor x16,x16,x26,ror#18
+ eor x8,x8,x3,ror#8
+ orr x17,x17,x19 // Ch(e,f,g)
+ eor x19,x22,x23 // a^b, b^c in next round
+ eor x16,x16,x26,ror#41 // Sigma1(e)
+ eor x9,x9,x22,ror#34
+ add x21,x21,x17 // h+=Ch(e,f,g)
+ and x28,x28,x19 // (b^c)&=(a^b)
+ eor x7,x7,x0,ror#61
+ eor x8,x8,x3,lsr#7 // sigma0(X[i+1])
+ add x21,x21,x16 // h+=Sigma1(e)
+ eor x28,x28,x23 // Maj(a,b,c)
+ eor x17,x9,x22,ror#39 // Sigma0(a)
+ eor x7,x7,x0,lsr#6 // sigma1(X[i+14])
+ add x2,x2,x11
+ add x25,x25,x21 // d+=h
+ add x21,x21,x28 // h+=Maj(a,b,c)
+ ldr x28,[x30],#8 // *K++, x19 in next round
+ add x2,x2,x8
+ add x21,x21,x17 // h+=Sigma0(a)
+ add x2,x2,x7
+ ldr x7,[sp,#0]
+ str x10,[sp,#24]
+ ror x16,x25,#14
+ add x20,x20,x28 // h+=K[i]
+ ror x9,x4,#1
+ and x17,x26,x25
+ ror x8,x1,#19
+ bic x28,x27,x25
+ ror x10,x21,#28
+ add x20,x20,x2 // h+=X[i]
+ eor x16,x16,x25,ror#18
+ eor x9,x9,x4,ror#8
+ orr x17,x17,x28 // Ch(e,f,g)
+ eor x28,x21,x22 // a^b, b^c in next round
+ eor x16,x16,x25,ror#41 // Sigma1(e)
+ eor x10,x10,x21,ror#34
+ add x20,x20,x17 // h+=Ch(e,f,g)
+ and x19,x19,x28 // (b^c)&=(a^b)
+ eor x8,x8,x1,ror#61
+ eor x9,x9,x4,lsr#7 // sigma0(X[i+1])
+ add x20,x20,x16 // h+=Sigma1(e)
+ eor x19,x19,x22 // Maj(a,b,c)
+ eor x17,x10,x21,ror#39 // Sigma0(a)
+ eor x8,x8,x1,lsr#6 // sigma1(X[i+14])
+ add x3,x3,x12
+ add x24,x24,x20 // d+=h
+ add x20,x20,x19 // h+=Maj(a,b,c)
+ ldr x19,[x30],#8 // *K++, x28 in next round
+ add x3,x3,x9
+ add x20,x20,x17 // h+=Sigma0(a)
+ add x3,x3,x8
+ cbnz x19,.Loop_16_xx
+
+ ldp x0,x2,[x29,#96]
+ ldr x1,[x29,#112]
+ sub x30,x30,#648 // rewind
+
+ ldp x3,x4,[x0]
+ ldp x5,x6,[x0,#2*8]
+ add x1,x1,#14*8 // advance input pointer
+ ldp x7,x8,[x0,#4*8]
+ add x20,x20,x3
+ ldp x9,x10,[x0,#6*8]
+ add x21,x21,x4
+ add x22,x22,x5
+ add x23,x23,x6
+ stp x20,x21,[x0]
+ add x24,x24,x7
+ add x25,x25,x8
+ stp x22,x23,[x0,#2*8]
+ add x26,x26,x9
+ add x27,x27,x10
+ cmp x1,x2
+ stp x24,x25,[x0,#4*8]
+ stp x26,x27,[x0,#6*8]
+ b.ne .Loop
+
+ ldp x19,x20,[x29,#16]
+ add sp,sp,#4*8
+ ldp x21,x22,[x29,#32]
+ ldp x23,x24,[x29,#48]
+ ldp x25,x26,[x29,#64]
+ ldp x27,x28,[x29,#80]
+ ldp x29,x30,[sp],#128
+ ret
+.size sha512_block_data_order,.-sha512_block_data_order
+
+.align 6
+.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
+ .quad 0 // terminator
+.size K512,.-K512
+.align 3
+.LOPENSSL_armcap_P:
+ .quad OPENSSL_armcap_P-.
+.asciz "SHA512 block transform for ARMv8, CRYPTOGAMS by <appro@openssl.org>"
+.align 2
+.comm OPENSSL_armcap_P,4,4
diff --git a/linux-arm/crypto/aes/aes-armv4.S b/linux-arm/crypto/aes/aes-armv4.S
new file mode 100644
index 0000000..0b7d193
--- /dev/null
+++ b/linux-arm/crypto/aes/aes-armv4.S
@@ -0,0 +1,1185 @@
+
+@ ====================================================================
+@ Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+@ project. The module is, however, dual licensed under OpenSSL and
+@ CRYPTOGAMS licenses depending on where you obtain it. For further
+@ details see http://www.openssl.org/~appro/cryptogams/.
+@ ====================================================================
+
+@ AES for ARMv4
+
+@ January 2007.
+@
+@ Code uses single 1K S-box and is >2 times faster than code generated
+@ by gcc-3.4.1. This is thanks to unique feature of ARMv4 ISA, which
+@ allows to merge logical or arithmetic operation with shift or rotate
+@ in one instruction and emit combined result every cycle. The module
+@ is endian-neutral. The performance is ~42 cycles/byte for 128-bit
+@ key [on single-issue Xscale PXA250 core].
+
+@ May 2007.
+@
+@ AES_set_[en|de]crypt_key is added.
+
+@ July 2010.
+@
+@ Rescheduling for dual-issue pipeline resulted in 12% improvement on
+@ Cortex A8 core and ~25 cycles per byte processed with 128-bit key.
+
+@ February 2011.
+@
+@ Profiler-assisted and platform-specific optimization resulted in 16%
+@ improvement on Cortex A8 core and ~21.5 cycles per byte.
+
+#if defined(__arm__)
+#ifndef __KERNEL__
+# include "arm_arch.h"
+#else
+# define __ARM_ARCH__ __LINUX_ARM_ARCH__
+#endif
+
+.text
+#if __ARM_ARCH__<7
+.code 32
+#else
+.syntax unified
+# ifdef __thumb2__
+.thumb
+# else
+.code 32
+# endif
+#endif
+
+.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 asm_AES_encrypt(const unsigned char *in, unsigned char *out,
+@ const AES_KEY *key) {
+.global asm_AES_encrypt
+.hidden asm_AES_encrypt
+.type asm_AES_encrypt,%function
+.align 5
+asm_AES_encrypt:
+#if __ARM_ARCH__<7
+ sub r3,pc,#8 @ asm_AES_encrypt
+#else
+ adr r3,asm_AES_encrypt
+#endif
+ stmdb sp!,{r1,r4-r12,lr}
+ mov r12,r0 @ inp
+ mov r11,r2
+ sub r10,r3,#asm_AES_encrypt-AES_Te @ Te
+#if __ARM_ARCH__<7
+ 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
+#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 asm_AES_encrypt,.-asm_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 asm_AES_set_encrypt_key
+.hidden asm_AES_set_encrypt_key
+.type asm_AES_set_encrypt_key,%function
+.align 5
+asm_AES_set_encrypt_key:
+_armv4_AES_set_encrypt_key:
+#if __ARM_ARCH__<7
+ sub r3,pc,#8 @ asm_AES_set_encrypt_key
+#else
+ adr r3,asm_AES_set_encrypt_key
+#endif
+ teq r0,#0
+#if __ARM_ARCH__>=7
+ itt eq @ Thumb2 thing, sanity check in ARM
+#endif
+ moveq r0,#-1
+ beq .Labrt
+ teq r2,#0
+#if __ARM_ARCH__>=7
+ itt eq @ Thumb2 thing, sanity check in ARM
+#endif
+ moveq r0,#-1
+ beq .Labrt
+
+ teq r1,#128
+ beq .Lok
+ teq r1,#192
+ beq .Lok
+ teq r1,#256
+#if __ARM_ARCH__>=7
+ itt ne @ Thumb2 thing, sanity check in ARM
+#endif
+ 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
+ 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
+ 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]
+#if __ARM_ARCH__>=7
+ itt eq @ Thumb2 thing, sanity check in ARM
+#endif
+ 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
+ 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]
+#if __ARM_ARCH__>=7
+ itt eq @ Thumb2 thing, sanity check in ARM
+#endif
+ 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
+
+.align 2
+.Ldone: mov r0,#0
+ ldmia sp!,{r4-r12,lr}
+.Labrt:
+#if defined(__thumb2__) && __ARM_ARCH__>=7
+ .short 0x4770 @ .word 0xe12fff1e in Thumb2 encoding
+#else
+ tst lr,#1
+ moveq pc,lr @ be binary compatible with V4, yet
+ .word 0xe12fff1e @ interoperable with Thumb ISA:-)
+#endif
+.size asm_AES_set_encrypt_key,.-asm_AES_set_encrypt_key
+
+.global asm_AES_set_decrypt_key
+.hidden asm_AES_set_decrypt_key
+.type asm_AES_set_decrypt_key,%function
+.align 5
+asm_AES_set_decrypt_key:
+ str lr,[sp,#-4]! @ push lr
+ bl _armv4_AES_set_encrypt_key
+ teq r0,#0
+ ldr lr,[sp],#4 @ pop lr
+ bne .Labrt
+
+ mov r0,r2 @ asm_AES_set_encrypt_key preserves r2,
+ mov r1,r2 @ which is AES_KEY *key
+ b _armv4_AES_set_enc2dec_key
+.size asm_AES_set_decrypt_key,.-asm_AES_set_decrypt_key
+
+@ void AES_set_enc2dec_key(const AES_KEY *inp,AES_KEY *out)
+.global AES_set_enc2dec_key
+.hidden AES_set_enc2dec_key
+.type AES_set_enc2dec_key,%function
+.align 5
+AES_set_enc2dec_key:
+_armv4_AES_set_enc2dec_key:
+ stmdb sp!,{r4-r12,lr}
+
+ ldr r12,[r0,#240]
+ mov r7,r0 @ input
+ add r8,r0,r12,lsl#4
+ mov r11,r1 @ ouput
+ add r10,r1,r12,lsl#4
+ str r12,[r1,#240]
+
+.Linv: ldr r0,[r7],#16
+ ldr r1,[r7,#-12]
+ ldr r2,[r7,#-8]
+ ldr r3,[r7,#-4]
+ ldr r4,[r8],#-16
+ ldr r5,[r8,#16+4]
+ ldr r6,[r8,#16+8]
+ ldr r9,[r8,#16+12]
+ str r0,[r10],#-16
+ str r1,[r10,#16+4]
+ str r2,[r10,#16+8]
+ str r3,[r10,#16+12]
+ str r4,[r11],#16
+ str r5,[r11,#-12]
+ str r6,[r11,#-8]
+ str r9,[r11,#-4]
+ teq r7,r8
+ bne .Linv
+
+ ldr r0,[r7]
+ ldr r1,[r7,#4]
+ ldr r2,[r7,#8]
+ ldr r3,[r7,#12]
+ str r0,[r11]
+ str r1,[r11,#4]
+ str r2,[r11,#8]
+ str r3,[r11,#12]
+ sub r11,r11,r12,lsl#3
+ 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_enc2dec_key,.-AES_set_enc2dec_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 asm_AES_decrypt(const unsigned char *in, unsigned char *out,
+@ const AES_KEY *key) {
+.global asm_AES_decrypt
+.hidden asm_AES_decrypt
+.type asm_AES_decrypt,%function
+.align 5
+asm_AES_decrypt:
+#if __ARM_ARCH__<7
+ sub r3,pc,#8 @ asm_AES_decrypt
+#else
+ adr r3,asm_AES_decrypt
+#endif
+ stmdb sp!,{r1,r4-r12,lr}
+ mov r12,r0 @ inp
+ mov r11,r2
+ sub r10,r3,#asm_AES_decrypt-AES_Td @ Td
+#if __ARM_ARCH__<7
+ 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
+#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 asm_AES_decrypt,.-asm_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
+
+ add r1,r10,r1,lsr#24
+ ldrb r7,[r10,r7] @ Td4[s1>>0]
+ ldrb r1,[r1] @ 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
+
+ add r2,r10,r2,lsr#24
+ ldrb r2,[r2] @ 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
+
+ add r3,r10,r3,lsr#24
+ ldrb r9,[r10,r9] @ Td4[s3>>0]
+ ldrb r3,[r3] @ 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 <appro@openssl.org>"
+.align 2
+
+#endif
diff --git a/linux-arm/crypto/aes/aesv8-armx.S b/linux-arm/crypto/aes/aesv8-armx.S
new file mode 100644
index 0000000..fede6ed
--- /dev/null
+++ b/linux-arm/crypto/aes/aesv8-armx.S
@@ -0,0 +1,732 @@
+#include "arm_arch.h"
+
+#if __ARM_MAX_ARCH__>=7
+.text
+.arch armv7-a
+.fpu neon
+.code 32
+.align 5
+rcon:
+.long 0x01,0x01,0x01,0x01
+.long 0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d @ rotate-n-splat
+.long 0x1b,0x1b,0x1b,0x1b
+
+.globl aes_v8_set_encrypt_key
+.type aes_v8_set_encrypt_key,%function
+.align 5
+aes_v8_set_encrypt_key:
+.Lenc_key:
+ mov r3,#-1
+ cmp r0,#0
+ beq .Lenc_key_abort
+ cmp r2,#0
+ beq .Lenc_key_abort
+ mov r3,#-2
+ cmp r1,#128
+ blt .Lenc_key_abort
+ cmp r1,#256
+ bgt .Lenc_key_abort
+ tst r1,#0x3f
+ bne .Lenc_key_abort
+
+ adr r3,rcon
+ cmp r1,#192
+
+ veor q0,q0,q0
+ vld1.8 {q3},[r0]!
+ mov r1,#8 @ reuse r1
+ vld1.32 {q1,q2},[r3]!
+
+ blt .Loop128
+ beq .L192
+ b .L256
+
+.align 4
+.Loop128:
+ vtbl.8 d20,{q3},d4
+ vtbl.8 d21,{q3},d5
+ vext.8 q9,q0,q3,#12
+ vst1.32 {q3},[r2]!
+ .byte 0x00,0x43,0xf0,0xf3 @ aese q10,q0
+ subs r1,r1,#1
+
+ veor q3,q3,q9
+ vext.8 q9,q0,q9,#12
+ veor q3,q3,q9
+ vext.8 q9,q0,q9,#12
+ veor q10,q10,q1
+ veor q3,q3,q9
+ vshl.u8 q1,q1,#1
+ veor q3,q3,q10
+ bne .Loop128
+
+ vld1.32 {q1},[r3]
+
+ vtbl.8 d20,{q3},d4
+ vtbl.8 d21,{q3},d5
+ vext.8 q9,q0,q3,#12
+ vst1.32 {q3},[r2]!
+ .byte 0x00,0x43,0xf0,0xf3 @ aese q10,q0
+
+ veor q3,q3,q9
+ vext.8 q9,q0,q9,#12
+ veor q3,q3,q9
+ vext.8 q9,q0,q9,#12
+ veor q10,q10,q1
+ veor q3,q3,q9
+ vshl.u8 q1,q1,#1
+ veor q3,q3,q10
+
+ vtbl.8 d20,{q3},d4
+ vtbl.8 d21,{q3},d5
+ vext.8 q9,q0,q3,#12
+ vst1.32 {q3},[r2]!
+ .byte 0x00,0x43,0xf0,0xf3 @ aese q10,q0
+
+ veor q3,q3,q9
+ vext.8 q9,q0,q9,#12
+ veor q3,q3,q9
+ vext.8 q9,q0,q9,#12
+ veor q10,q10,q1
+ veor q3,q3,q9
+ veor q3,q3,q10
+ vst1.32 {q3},[r2]
+ add r2,r2,#0x50
+
+ mov r12,#10
+ b .Ldone
+
+.align 4
+.L192:
+ vld1.8 {d16},[r0]!
+ vmov.i8 q10,#8 @ borrow q10
+ vst1.32 {q3},[r2]!
+ vsub.i8 q2,q2,q10 @ adjust the mask
+
+.Loop192:
+ vtbl.8 d20,{q8},d4
+ vtbl.8 d21,{q8},d5
+ vext.8 q9,q0,q3,#12
+ vst1.32 {d16},[r2]!
+ .byte 0x00,0x43,0xf0,0xf3 @ aese q10,q0
+ subs r1,r1,#1
+
+ veor q3,q3,q9
+ vext.8 q9,q0,q9,#12
+ veor q3,q3,q9
+ vext.8 q9,q0,q9,#12
+ veor q3,q3,q9
+
+ vdup.32 q9,d7[1]
+ veor q9,q9,q8
+ veor q10,q10,q1
+ vext.8 q8,q0,q8,#12
+ vshl.u8 q1,q1,#1
+ veor q8,q8,q9
+ veor q3,q3,q10
+ veor q8,q8,q10
+ vst1.32 {q3},[r2]!
+ bne .Loop192
+
+ mov r12,#12
+ add r2,r2,#0x20
+ b .Ldone
+
+.align 4
+.L256:
+ vld1.8 {q8},[r0]
+ mov r1,#7
+ mov r12,#14
+ vst1.32 {q3},[r2]!
+
+.Loop256:
+ vtbl.8 d20,{q8},d4
+ vtbl.8 d21,{q8},d5
+ vext.8 q9,q0,q3,#12
+ vst1.32 {q8},[r2]!
+ .byte 0x00,0x43,0xf0,0xf3 @ aese q10,q0
+ subs r1,r1,#1
+
+ veor q3,q3,q9
+ vext.8 q9,q0,q9,#12
+ veor q3,q3,q9
+ vext.8 q9,q0,q9,#12
+ veor q10,q10,q1
+ veor q3,q3,q9
+ vshl.u8 q1,q1,#1
+ veor q3,q3,q10
+ vst1.32 {q3},[r2]!
+ beq .Ldone
+
+ vdup.32 q10,d7[1]
+ vext.8 q9,q0,q8,#12
+ .byte 0x00,0x43,0xf0,0xf3 @ aese q10,q0
+
+ veor q8,q8,q9
+ vext.8 q9,q0,q9,#12
+ veor q8,q8,q9
+ vext.8 q9,q0,q9,#12
+ veor q8,q8,q9
+
+ veor q8,q8,q10
+ b .Loop256
+
+.Ldone:
+ str r12,[r2]
+ mov r3,#0
+
+.Lenc_key_abort:
+ mov r0,r3 @ return value
+
+ bx lr
+.size aes_v8_set_encrypt_key,.-aes_v8_set_encrypt_key
+
+.globl aes_v8_set_decrypt_key
+.type aes_v8_set_decrypt_key,%function
+.align 5
+aes_v8_set_decrypt_key:
+ stmdb sp!,{r4,lr}
+ bl .Lenc_key
+
+ cmp r0,#0
+ bne .Ldec_key_abort
+
+ sub r2,r2,#240 @ restore original r2
+ mov r4,#-16
+ add r0,r2,r12,lsl#4 @ end of key schedule
+
+ vld1.32 {q0},[r2]
+ vld1.32 {q1},[r0]
+ vst1.32 {q0},[r0],r4
+ vst1.32 {q1},[r2]!
+
+.Loop_imc:
+ vld1.32 {q0},[r2]
+ vld1.32 {q1},[r0]
+ .byte 0xc0,0x03,0xb0,0xf3 @ aesimc q0,q0
+ .byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1
+ vst1.32 {q0},[r0],r4
+ vst1.32 {q1},[r2]!
+ cmp r0,r2
+ bhi .Loop_imc
+
+ vld1.32 {q0},[r2]
+ .byte 0xc0,0x03,0xb0,0xf3 @ aesimc q0,q0
+ vst1.32 {q0},[r0]
+
+ eor r0,r0,r0 @ return value
+.Ldec_key_abort:
+ ldmia sp!,{r4,pc}
+.size aes_v8_set_decrypt_key,.-aes_v8_set_decrypt_key
+.globl aes_v8_encrypt
+.type aes_v8_encrypt,%function
+.align 5
+aes_v8_encrypt:
+ ldr r3,[r2,#240]
+ vld1.32 {q0},[r2]!
+ vld1.8 {q2},[r0]
+ sub r3,r3,#2
+ vld1.32 {q1},[r2]!
+
+.Loop_enc:
+ .byte 0x00,0x43,0xb0,0xf3 @ aese q2,q0
+ vld1.32 {q0},[r2]!
+ .byte 0x84,0x43,0xb0,0xf3 @ aesmc q2,q2
+ subs r3,r3,#2
+ .byte 0x02,0x43,0xb0,0xf3 @ aese q2,q1
+ vld1.32 {q1},[r2]!
+ .byte 0x84,0x43,0xb0,0xf3 @ aesmc q2,q2
+ bgt .Loop_enc
+
+ .byte 0x00,0x43,0xb0,0xf3 @ aese q2,q0
+ vld1.32 {q0},[r2]
+ .byte 0x84,0x43,0xb0,0xf3 @ aesmc q2,q2
+ .byte 0x02,0x43,0xb0,0xf3 @ aese q2,q1
+ veor q2,q2,q0
+
+ vst1.8 {q2},[r1]
+ bx lr
+.size aes_v8_encrypt,.-aes_v8_encrypt
+.globl aes_v8_decrypt
+.type aes_v8_decrypt,%function
+.align 5
+aes_v8_decrypt:
+ ldr r3,[r2,#240]
+ vld1.32 {q0},[r2]!
+ vld1.8 {q2},[r0]
+ sub r3,r3,#2
+ vld1.32 {q1},[r2]!
+
+.Loop_dec:
+ .byte 0x40,0x43,0xb0,0xf3 @ aesd q2,q0
+ vld1.32 {q0},[r2]!
+ .byte 0xc4,0x43,0xb0,0xf3 @ aesimc q2,q2
+ subs r3,r3,#2
+ .byte 0x42,0x43,0xb0,0xf3 @ aesd q2,q1
+ vld1.32 {q1},[r2]!
+ .byte 0xc4,0x43,0xb0,0xf3 @ aesimc q2,q2
+ bgt .Loop_dec
+
+ .byte 0x40,0x43,0xb0,0xf3 @ aesd q2,q0
+ vld1.32 {q0},[r2]
+ .byte 0xc4,0x43,0xb0,0xf3 @ aesimc q2,q2
+ .byte 0x42,0x43,0xb0,0xf3 @ aesd q2,q1
+ veor q2,q2,q0
+
+ vst1.8 {q2},[r1]
+ bx lr
+.size aes_v8_decrypt,.-aes_v8_decrypt
+.globl aes_v8_cbc_encrypt
+.type aes_v8_cbc_encrypt,%function
+.align 5
+aes_v8_cbc_encrypt:
+ mov ip,sp
+ stmdb sp!,{r4-r8,lr}
+ vstmdb sp!,{d8-d15} @ ABI specification says so
+ ldmia ip,{r4-r5} @ load remaining args
+ subs r2,r2,#16
+ mov r8,#16
+ blo .Lcbc_abort
+ moveq r8,#0
+
+ cmp r5,#0 @ en- or decrypting?
+ ldr r5,[r3,#240]
+ and r2,r2,#-16
+ vld1.8 {q6},[r4]
+ vld1.8 {q0},[r0],r8
+
+ vld1.32 {q8-q9},[r3] @ load key schedule...
+ sub r5,r5,#6
+ add r7,r3,r5,lsl#4 @ pointer to last 7 round keys
+ sub r5,r5,#2
+ vld1.32 {q10-q11},[r7]!
+ vld1.32 {q12-q13},[r7]!
+ vld1.32 {q14-q15},[r7]!
+ vld1.32 {q7},[r7]
+
+ add r7,r3,#32
+ mov r6,r5
+ beq .Lcbc_dec
+
+ cmp r5,#2
+ veor q0,q0,q6
+ veor q5,q8,q7
+ beq .Lcbc_enc128
+
+.Loop_cbc_enc:
+ .byte 0x20,0x03,0xb0,0xf3 @ aese q0,q8
+ vld1.32 {q8},[r7]!
+ .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
+ subs r6,r6,#2
+ .byte 0x22,0x03,0xb0,0xf3 @ aese q0,q9
+ vld1.32 {q9},[r7]!
+ .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
+ bgt .Loop_cbc_enc
+
+ .byte 0x20,0x03,0xb0,0xf3 @ aese q0,q8
+ .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
+ subs r2,r2,#16
+ .byte 0x22,0x03,0xb0,0xf3 @ aese q0,q9
+ .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
+ moveq r8,#0
+ .byte 0x24,0x03,0xb0,0xf3 @ aese q0,q10
+ .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
+ add r7,r3,#16
+ .byte 0x26,0x03,0xb0,0xf3 @ aese q0,q11
+ .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
+ vld1.8 {q8},[r0],r8
+ .byte 0x28,0x03,0xb0,0xf3 @ aese q0,q12
+ .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
+ veor q8,q8,q5
+ .byte 0x2a,0x03,0xb0,0xf3 @ aese q0,q13
+ .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
+ vld1.32 {q9},[r7]! @ re-pre-load rndkey[1]
+ .byte 0x2c,0x03,0xb0,0xf3 @ aese q0,q14
+ .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
+ .byte 0x2e,0x03,0xb0,0xf3 @ aese q0,q15
+
+ mov r6,r5
+ veor q6,q0,q7
+ vst1.8 {q6},[r1]!
+ bhs .Loop_cbc_enc
+
+ b .Lcbc_done
+
+.align 5
+.Lcbc_enc128:
+ vld1.32 {q2-q3},[r7]
+ .byte 0x20,0x03,0xb0,0xf3 @ aese q0,q8
+ .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
+ b .Lenter_cbc_enc128
+.Loop_cbc_enc128:
+ .byte 0x20,0x03,0xb0,0xf3 @ aese q0,q8
+ .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
+ vst1.8 {q6},[r1]!
+.Lenter_cbc_enc128:
+ .byte 0x22,0x03,0xb0,0xf3 @ aese q0,q9
+ .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
+ subs r2,r2,#16
+ .byte 0x04,0x03,0xb0,0xf3 @ aese q0,q2
+ .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
+ moveq r8,#0
+ .byte 0x06,0x03,0xb0,0xf3 @ aese q0,q3
+ .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
+ .byte 0x24,0x03,0xb0,0xf3 @ aese q0,q10
+ .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
+ .byte 0x26,0x03,0xb0,0xf3 @ aese q0,q11
+ .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
+ vld1.8 {q8},[r0],r8
+ .byte 0x28,0x03,0xb0,0xf3 @ aese q0,q12
+ .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
+ .byte 0x2a,0x03,0xb0,0xf3 @ aese q0,q13
+ .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
+ .byte 0x2c,0x03,0xb0,0xf3 @ aese q0,q14
+ .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
+ veor q8,q8,q5
+ .byte 0x2e,0x03,0xb0,0xf3 @ aese q0,q15
+ veor q6,q0,q7
+ bhs .Loop_cbc_enc128
+
+ vst1.8 {q6},[r1]!
+ b .Lcbc_done
+.align 5
+.Lcbc_dec:
+ vld1.8 {q10},[r0]!
+ subs r2,r2,#32 @ bias
+ add r6,r5,#2
+ vorr q3,q0,q0
+ vorr q1,q0,q0
+ vorr q11,q10,q10
+ blo .Lcbc_dec_tail
+
+ vorr q1,q10,q10
+ vld1.8 {q10},[r0]!
+ vorr q2,q0,q0
+ vorr q3,q1,q1
+ vorr q11,q10,q10
+
+.Loop3x_cbc_dec:
+ .byte 0x60,0x03,0xb0,0xf3 @ aesd q0,q8
+ .byte 0x60,0x23,0xb0,0xf3 @ aesd q1,q8
+ .byte 0x60,0x43,0xf0,0xf3 @ aesd q10,q8
+ vld1.32 {q8},[r7]!
+ .byte 0xc0,0x03,0xb0,0xf3 @ aesimc q0,q0
+ .byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1
+ .byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10
+ subs r6,r6,#2
+ .byte 0x62,0x03,0xb0,0xf3 @ aesd q0,q9
+ .byte 0x62,0x23,0xb0,0xf3 @ aesd q1,q9
+ .byte 0x62,0x43,0xf0,0xf3 @ aesd q10,q9
+ vld1.32 {q9},[r7]!
+ .byte 0xc0,0x03,0xb0,0xf3 @ aesimc q0,q0
+ .byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1
+ .byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10
+ bgt .Loop3x_cbc_dec
+
+ .byte 0x60,0x03,0xb0,0xf3 @ aesd q0,q8
+ .byte 0x60,0x23,0xb0,0xf3 @ aesd q1,q8
+ .byte 0x60,0x43,0xf0,0xf3 @ aesd q10,q8
+ veor q4,q6,q7
+ .byte 0xc0,0x03,0xb0,0xf3 @ aesimc q0,q0
+ .byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1
+ .byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10
+ veor q5,q2,q7
+ .byte 0x62,0x03,0xb0,0xf3 @ aesd q0,q9
+ .byte 0x62,0x23,0xb0,0xf3 @ aesd q1,q9
+ .byte 0x62,0x43,0xf0,0xf3 @ aesd q10,q9
+ veor q9,q3,q7
+ subs r2,r2,#0x30
+ .byte 0xc0,0x03,0xb0,0xf3 @ aesimc q0,q0
+ .byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1
+ .byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10
+ vorr q6,q11,q11
+ movlo r6,r2 @ r6, r6, is zero at this point
+ .byte 0x68,0x03,0xb0,0xf3 @ aesd q0,q12
+ .byte 0x68,0x23,0xb0,0xf3 @ aesd q1,q12
+ .byte 0x68,0x43,0xf0,0xf3 @ aesd q10,q12
+ add r0,r0,r6 @ r0 is adjusted in such way that
+ @ at exit from the loop q1-q10
+ @ are loaded with last "words"
+ .byte 0xc0,0x03,0xb0,0xf3 @ aesimc q0,q0
+ .byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1
+ .byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10
+ mov r7,r3
+ .byte 0x6a,0x03,0xb0,0xf3 @ aesd q0,q13
+ .byte 0x6a,0x23,0xb0,0xf3 @ aesd q1,q13
+ .byte 0x6a,0x43,0xf0,0xf3 @ aesd q10,q13
+ vld1.8 {q2},[r0]!
+ .byte 0xc0,0x03,0xb0,0xf3 @ aesimc q0,q0
+ .byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1
+ .byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10
+ vld1.8 {q3},[r0]!
+ .byte 0x6c,0x03,0xb0,0xf3 @ aesd q0,q14
+ .byte 0x6c,0x23,0xb0,0xf3 @ aesd q1,q14
+ .byte 0x6c,0x43,0xf0,0xf3 @ aesd q10,q14
+ vld1.8 {q11},[r0]!
+ .byte 0xc0,0x03,0xb0,0xf3 @ aesimc q0,q0
+ .byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1
+ .byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10
+ vld1.32 {q8},[r7]! @ re-pre-load rndkey[0]
+ .byte 0x6e,0x03,0xb0,0xf3 @ aesd q0,q15
+ .byte 0x6e,0x23,0xb0,0xf3 @ aesd q1,q15
+ .byte 0x6e,0x43,0xf0,0xf3 @ aesd q10,q15
+
+ add r6,r5,#2
+ veor q4,q4,q0
+ veor q5,q5,q1
+ veor q10,q10,q9
+ vld1.32 {q9},[r7]! @ re-pre-load rndkey[1]
+ vorr q0,q2,q2
+ vst1.8 {q4},[r1]!
+ vorr q1,q3,q3
+ vst1.8 {q5},[r1]!
+ vst1.8 {q10},[r1]!
+ vorr q10,q11,q11
+ bhs .Loop3x_cbc_dec
+
+ cmn r2,#0x30
+ beq .Lcbc_done
+ nop
+
+.Lcbc_dec_tail:
+ .byte 0x60,0x23,0xb0,0xf3 @ aesd q1,q8
+ .byte 0x60,0x43,0xf0,0xf3 @ aesd q10,q8
+ vld1.32 {q8},[r7]!
+ .byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1
+ .byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10
+ subs r6,r6,#2
+ .byte 0x62,0x23,0xb0,0xf3 @ aesd q1,q9
+ .byte 0x62,0x43,0xf0,0xf3 @ aesd q10,q9
+ vld1.32 {q9},[r7]!
+ .byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1
+ .byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10
+ bgt .Lcbc_dec_tail
+
+ .byte 0x60,0x23,0xb0,0xf3 @ aesd q1,q8
+ .byte 0x60,0x43,0xf0,0xf3 @ aesd q10,q8
+ .byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1
+ .byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10
+ .byte 0x62,0x23,0xb0,0xf3 @ aesd q1,q9
+ .byte 0x62,0x43,0xf0,0xf3 @ aesd q10,q9
+ .byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1
+ .byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10
+ .byte 0x68,0x23,0xb0,0xf3 @ aesd q1,q12
+ .byte 0x68,0x43,0xf0,0xf3 @ aesd q10,q12
+ .byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1
+ .byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10
+ cmn r2,#0x20
+ .byte 0x6a,0x23,0xb0,0xf3 @ aesd q1,q13
+ .byte 0x6a,0x43,0xf0,0xf3 @ aesd q10,q13
+ .byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1
+ .byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10
+ veor q5,q6,q7
+ .byte 0x6c,0x23,0xb0,0xf3 @ aesd q1,q14
+ .byte 0x6c,0x43,0xf0,0xf3 @ aesd q10,q14
+ .byte 0xc2,0x23,0xb0,0xf3 @ aesimc q1,q1
+ .byte 0xe4,0x43,0xf0,0xf3 @ aesimc q10,q10
+ veor q9,q3,q7
+ .byte 0x6e,0x23,0xb0,0xf3 @ aesd q1,q15
+ .byte 0x6e,0x43,0xf0,0xf3 @ aesd q10,q15
+ beq .Lcbc_dec_one
+ veor q5,q5,q1
+ veor q9,q9,q10
+ vorr q6,q11,q11
+ vst1.8 {q5},[r1]!
+ vst1.8 {q9},[r1]!
+ b .Lcbc_done
+
+.Lcbc_dec_one:
+ veor q5,q5,q10
+ vorr q6,q11,q11
+ vst1.8 {q5},[r1]!
+
+.Lcbc_done:
+ vst1.8 {q6},[r4]
+.Lcbc_abort:
+ vldmia sp!,{d8-d15}
+ ldmia sp!,{r4-r8,pc}
+.size aes_v8_cbc_encrypt,.-aes_v8_cbc_encrypt
+.globl aes_v8_ctr32_encrypt_blocks
+.type aes_v8_ctr32_encrypt_blocks,%function
+.align 5
+aes_v8_ctr32_encrypt_blocks:
+ mov ip,sp
+ stmdb sp!,{r4-r10,lr}
+ vstmdb sp!,{d8-d15} @ ABI specification says so
+ ldr r4, [ip] @ load remaining arg
+ ldr r5,[r3,#240]
+
+ ldr r8, [r4, #12]
+ vld1.32 {q0},[r4]
+
+ vld1.32 {q8-q9},[r3] @ load key schedule...
+ sub r5,r5,#4
+ mov r12,#16
+ cmp r2,#2
+ add r7,r3,r5,lsl#4 @ pointer to last 5 round keys
+ sub r5,r5,#2
+ vld1.32 {q12-q13},[r7]!
+ vld1.32 {q14-q15},[r7]!
+ vld1.32 {q7},[r7]
+ add r7,r3,#32
+ mov r6,r5
+ movlo r12,#0
+#ifndef __ARMEB__
+ rev r8, r8
+#endif
+ vorr q1,q0,q0
+ add r10, r8, #1
+ vorr q10,q0,q0
+ add r8, r8, #2
+ vorr q6,q0,q0
+ rev r10, r10
+ vmov.32 d3[1],r10
+ bls .Lctr32_tail
+ rev r12, r8
+ sub r2,r2,#3 @ bias
+ vmov.32 d21[1],r12
+ b .Loop3x_ctr32
+
+.align 4
+.Loop3x_ctr32:
+ .byte 0x20,0x03,0xb0,0xf3 @ aese q0,q8
+ .byte 0x20,0x23,0xb0,0xf3 @ aese q1,q8
+ .byte 0x20,0x43,0xf0,0xf3 @ aese q10,q8
+ vld1.32 {q8},[r7]!
+ .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
+ .byte 0x82,0x23,0xb0,0xf3 @ aesmc q1,q1
+ .byte 0xa4,0x43,0xf0,0xf3 @ aesmc q10,q10
+ subs r6,r6,#2
+ .byte 0x22,0x03,0xb0,0xf3 @ aese q0,q9
+ .byte 0x22,0x23,0xb0,0xf3 @ aese q1,q9
+ .byte 0x22,0x43,0xf0,0xf3 @ aese q10,q9
+ vld1.32 {q9},[r7]!
+ .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
+ .byte 0x82,0x23,0xb0,0xf3 @ aesmc q1,q1
+ .byte 0xa4,0x43,0xf0,0xf3 @ aesmc q10,q10
+ bgt .Loop3x_ctr32
+
+ .byte 0x20,0x03,0xb0,0xf3 @ aese q0,q8
+ .byte 0x20,0x23,0xb0,0xf3 @ aese q1,q8
+ .byte 0x20,0x43,0xf0,0xf3 @ aese q10,q8
+ mov r7,r3
+ .byte 0x80,0x83,0xb0,0xf3 @ aesmc q4,q0
+ vld1.8 {q2},[r0]!
+ .byte 0x82,0xa3,0xb0,0xf3 @ aesmc q5,q1
+ .byte 0xa4,0x43,0xf0,0xf3 @ aesmc q10,q10
+ vorr q0,q6,q6
+ .byte 0x22,0x83,0xb0,0xf3 @ aese q4,q9
+ vld1.8 {q3},[r0]!
+ .byte 0x22,0xa3,0xb0,0xf3 @ aese q5,q9
+ .byte 0x22,0x43,0xf0,0xf3 @ aese q10,q9
+ vorr q1,q6,q6
+ .byte 0x88,0x83,0xb0,0xf3 @ aesmc q4,q4
+ vld1.8 {q11},[r0]!
+ .byte 0x8a,0xa3,0xb0,0xf3 @ aesmc q5,q5
+ .byte 0xa4,0x23,0xf0,0xf3 @ aesmc q9,q10
+ vorr q10,q6,q6
+ add r9,r8,#1
+ .byte 0x28,0x83,0xb0,0xf3 @ aese q4,q12
+ .byte 0x28,0xa3,0xb0,0xf3 @ aese q5,q12
+ .byte 0x28,0x23,0xf0,0xf3 @ aese q9,q12
+ veor q2,q2,q7
+ add r10,r8,#2
+ .byte 0x88,0x83,0xb0,0xf3 @ aesmc q4,q4
+ .byte 0x8a,0xa3,0xb0,0xf3 @ aesmc q5,q5
+ .byte 0xa2,0x23,0xf0,0xf3 @ aesmc q9,q9
+ veor q3,q3,q7
+ add r8,r8,#3
+ .byte 0x2a,0x83,0xb0,0xf3 @ aese q4,q13
+ .byte 0x2a,0xa3,0xb0,0xf3 @ aese q5,q13
+ .byte 0x2a,0x23,0xf0,0xf3 @ aese q9,q13
+ veor q11,q11,q7
+ rev r9,r9
+ .byte 0x88,0x83,0xb0,0xf3 @ aesmc q4,q4
+ vld1.32 {q8},[r7]! @ re-pre-load rndkey[0]
+ .byte 0x8a,0xa3,0xb0,0xf3 @ aesmc q5,q5
+ .byte 0xa2,0x23,0xf0,0xf3 @ aesmc q9,q9
+ vmov.32 d1[1], r9
+ rev r10,r10
+ .byte 0x2c,0x83,0xb0,0xf3 @ aese q4,q14
+ .byte 0x2c,0xa3,0xb0,0xf3 @ aese q5,q14
+ .byte 0x2c,0x23,0xf0,0xf3 @ aese q9,q14
+ vmov.32 d3[1], r10
+ rev r12,r8
+ .byte 0x88,0x83,0xb0,0xf3 @ aesmc q4,q4
+ .byte 0x8a,0xa3,0xb0,0xf3 @ aesmc q5,q5
+ .byte 0xa2,0x23,0xf0,0xf3 @ aesmc q9,q9
+ vmov.32 d21[1], r12
+ subs r2,r2,#3
+ .byte 0x2e,0x83,0xb0,0xf3 @ aese q4,q15
+ .byte 0x2e,0xa3,0xb0,0xf3 @ aese q5,q15
+ .byte 0x2e,0x23,0xf0,0xf3 @ aese q9,q15
+
+ mov r6,r5
+ veor q2,q2,q4
+ veor q3,q3,q5
+ veor q11,q11,q9
+ vld1.32 {q9},[r7]! @ re-pre-load rndkey[1]
+ vst1.8 {q2},[r1]!
+ vst1.8 {q3},[r1]!
+ vst1.8 {q11},[r1]!
+ bhs .Loop3x_ctr32
+
+ adds r2,r2,#3
+ beq .Lctr32_done
+ cmp r2,#1
+ mov r12,#16
+ moveq r12,#0
+
+.Lctr32_tail:
+ .byte 0x20,0x03,0xb0,0xf3 @ aese q0,q8
+ .byte 0x20,0x23,0xb0,0xf3 @ aese q1,q8
+ vld1.32 {q8},[r7]!
+ .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
+ .byte 0x82,0x23,0xb0,0xf3 @ aesmc q1,q1
+ subs r6,r6,#2
+ .byte 0x22,0x03,0xb0,0xf3 @ aese q0,q9
+ .byte 0x22,0x23,0xb0,0xf3 @ aese q1,q9
+ vld1.32 {q9},[r7]!
+ .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
+ .byte 0x82,0x23,0xb0,0xf3 @ aesmc q1,q1
+ bgt .Lctr32_tail
+
+ .byte 0x20,0x03,0xb0,0xf3 @ aese q0,q8
+ .byte 0x20,0x23,0xb0,0xf3 @ aese q1,q8
+ .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
+ .byte 0x82,0x23,0xb0,0xf3 @ aesmc q1,q1
+ .byte 0x22,0x03,0xb0,0xf3 @ aese q0,q9
+ .byte 0x22,0x23,0xb0,0xf3 @ aese q1,q9
+ .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
+ .byte 0x82,0x23,0xb0,0xf3 @ aesmc q1,q1
+ vld1.8 {q2},[r0],r12
+ .byte 0x28,0x03,0xb0,0xf3 @ aese q0,q12
+ .byte 0x28,0x23,0xb0,0xf3 @ aese q1,q12
+ vld1.8 {q3},[r0]
+ .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
+ .byte 0x82,0x23,0xb0,0xf3 @ aesmc q1,q1
+ .byte 0x2a,0x03,0xb0,0xf3 @ aese q0,q13
+ .byte 0x2a,0x23,0xb0,0xf3 @ aese q1,q13
+ .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
+ .byte 0x82,0x23,0xb0,0xf3 @ aesmc q1,q1
+ .byte 0x2c,0x03,0xb0,0xf3 @ aese q0,q14
+ .byte 0x2c,0x23,0xb0,0xf3 @ aese q1,q14
+ veor q2,q2,q7
+ .byte 0x80,0x03,0xb0,0xf3 @ aesmc q0,q0
+ .byte 0x82,0x23,0xb0,0xf3 @ aesmc q1,q1
+ veor q3,q3,q7
+ .byte 0x2e,0x03,0xb0,0xf3 @ aese q0,q15
+ .byte 0x2e,0x23,0xb0,0xf3 @ aese q1,q15
+
+ cmp r2,#1
+ veor q2,q2,q0
+ veor q3,q3,q1
+ vst1.8 {q2},[r1]!
+ beq .Lctr32_done
+ vst1.8 {q3},[r1]
+
+.Lctr32_done:
+ vldmia sp!,{d8-d15}
+ ldmia sp!,{r4-r10,pc}
+.size aes_v8_ctr32_encrypt_blocks,.-aes_v8_ctr32_encrypt_blocks
+#endif
diff --git a/linux-arm/crypto/aes/bsaes-armv7.S b/linux-arm/crypto/aes/bsaes-armv7.S
new file mode 100644
index 0000000..cbc32fb
--- /dev/null
+++ b/linux-arm/crypto/aes/bsaes-armv7.S
@@ -0,0 +1,2550 @@
+
+@ ====================================================================
+@ Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+@ project. The module is, however, dual licensed under OpenSSL and
+@ CRYPTOGAMS licenses depending on where you obtain it. For further
+@ details see http://www.openssl.org/~appro/cryptogams/.
+@
+@ Specific modes and adaptation for Linux kernel by Ard Biesheuvel
+@ <ard.biesheuvel@linaro.org>. Permission to use under GPL terms is
+@ granted.
+@ ====================================================================
+
+@ Bit-sliced AES for ARM NEON
+@
+@ February 2012.
+@
+@ This implementation is direct adaptation of bsaes-x86_64 module for
+@ ARM NEON. Except that this module is endian-neutral [in sense that
+@ it can be compiled for either endianness] by courtesy of vld1.8's
+@ neutrality. Initial version doesn't implement interface to OpenSSL,
+@ only low-level primitives and unsupported entry points, just enough
+@ to collect performance results, which for Cortex-A8 core are:
+@
+@ encrypt 19.5 cycles per byte processed with 128-bit key
+@ decrypt 22.1 cycles per byte processed with 128-bit key
+@ key conv. 440 cycles per 128-bit key/0.18 of 8x block
+@
+@ Snapdragon S4 encrypts byte in 17.6 cycles and decrypts in 19.7,
+@ which is [much] worse than anticipated (for further details see
+@ http://www.openssl.org/~appro/Snapdragon-S4.html).
+@
+@ Cortex-A15 manages in 14.2/16.1 cycles [when integer-only code
+@ manages in 20.0 cycles].
+@
+@ When comparing to x86_64 results keep in mind that NEON unit is
+@ [mostly] single-issue and thus can't [fully] benefit from
+@ instruction-level parallelism. And when comparing to aes-armv4
+@ results keep in mind key schedule conversion overhead (see
+@ bsaes-x86_64.pl for further details)...
+@
+@ <appro@openssl.org>
+
+@ April-August 2013
+@
+@ Add CBC, CTR and XTS subroutines, adapt for kernel use.
+@
+@ <ard.biesheuvel@linaro.org>
+
+#if defined(__arm__)
+#ifndef __KERNEL__
+# include "arm_arch.h"
+
+# define VFP_ABI_PUSH vstmdb sp!,{d8-d15}
+# define VFP_ABI_POP vldmia sp!,{d8-d15}
+# define VFP_ABI_FRAME 0x40
+#else
+# define VFP_ABI_PUSH
+# define VFP_ABI_POP
+# define VFP_ABI_FRAME 0
+# define BSAES_ASM_EXTENDED_KEY
+# define XTS_CHAIN_TWEAK
+# define __ARM_ARCH__ __LINUX_ARM_ARCH__
+#endif
+
+#ifdef __thumb__
+# define adrl adr
+#endif
+
+#if __ARM_ARCH__>=7
+.text
+.syntax unified @ ARMv7-capable assembler is expected to handle this
+#ifdef __thumb2__
+.thumb
+#else
+.code 32
+#endif
+
+.fpu neon
+
+.type _bsaes_decrypt8,%function
+.align 4
+_bsaes_decrypt8:
+ adr r6,_bsaes_decrypt8
+ vldmia r4!, {q9} @ round 0 key
+ add r6,r6,#.LM0ISR-_bsaes_decrypt8
+
+ vldmia r6!, {q8} @ .LM0ISR
+ veor q10, q0, q9 @ xor with round0 key
+ veor q11, q1, q9
+ vtbl.8 d0, {q10}, d16
+ vtbl.8 d1, {q10}, d17
+ veor q12, q2, q9
+ vtbl.8 d2, {q11}, d16
+ vtbl.8 d3, {q11}, d17
+ veor q13, q3, q9
+ vtbl.8 d4, {q12}, d16
+ vtbl.8 d5, {q12}, d17
+ veor q14, q4, q9
+ vtbl.8 d6, {q13}, d16
+ vtbl.8 d7, {q13}, d17
+ veor q15, q5, q9
+ vtbl.8 d8, {q14}, d16
+ vtbl.8 d9, {q14}, d17
+ veor q10, q6, q9
+ vtbl.8 d10, {q15}, d16
+ vtbl.8 d11, {q15}, d17
+ veor q11, q7, q9
+ vtbl.8 d12, {q10}, d16
+ vtbl.8 d13, {q10}, d17
+ vtbl.8 d14, {q11}, d16
+ vtbl.8 d15, {q11}, d17
+ vmov.i8 q8,#0x55 @ compose .LBS0
+ vmov.i8 q9,#0x33 @ compose .LBS1
+ vshr.u64 q10, q6, #1
+ vshr.u64 q11, q4, #1
+ veor q10, q10, q7
+ veor q11, q11, q5
+ vand q10, q10, q8
+ vand q11, q11, q8
+ veor q7, q7, q10
+ vshl.u64 q10, q10, #1
+ veor q5, q5, q11
+ vshl.u64 q11, q11, #1
+ veor q6, q6, q10
+ veor q4, q4, q11
+ vshr.u64 q10, q2, #1
+ vshr.u64 q11, q0, #1
+ veor q10, q10, q3
+ veor q11, q11, q1
+ vand q10, q10, q8
+ vand q11, q11, q8
+ veor q3, q3, q10
+ vshl.u64 q10, q10, #1
+ veor q1, q1, q11
+ vshl.u64 q11, q11, #1
+ veor q2, q2, q10
+ veor q0, q0, q11
+ vmov.i8 q8,#0x0f @ compose .LBS2
+ vshr.u64 q10, q5, #2
+ vshr.u64 q11, q4, #2
+ veor q10, q10, q7
+ veor q11, q11, q6
+ vand q10, q10, q9
+ vand q11, q11, q9
+ veor q7, q7, q10
+ vshl.u64 q10, q10, #2
+ veor q6, q6, q11
+ vshl.u64 q11, q11, #2
+ veor q5, q5, q10
+ veor q4, q4, q11
+ vshr.u64 q10, q1, #2
+ vshr.u64 q11, q0, #2
+ veor q10, q10, q3
+ veor q11, q11, q2
+ vand q10, q10, q9
+ vand q11, q11, q9
+ veor q3, q3, q10
+ vshl.u64 q10, q10, #2
+ veor q2, q2, q11
+ vshl.u64 q11, q11, #2
+ veor q1, q1, q10
+ veor q0, q0, q11
+ vshr.u64 q10, q3, #4
+ vshr.u64 q11, q2, #4
+ veor q10, q10, q7
+ veor q11, q11, q6
+ vand q10, q10, q8
+ vand q11, q11, q8
+ veor q7, q7, q10
+ vshl.u64 q10, q10, #4
+ veor q6, q6, q11
+ vshl.u64 q11, q11, #4
+ veor q3, q3, q10
+ veor q2, q2, q11
+ vshr.u64 q10, q1, #4
+ vshr.u64 q11, q0, #4
+ veor q10, q10, q5
+ veor q11, q11, q4
+ vand q10, q10, q8
+ vand q11, q11, q8
+ veor q5, q5, q10
+ vshl.u64 q10, q10, #4
+ veor q4, q4, q11
+ vshl.u64 q11, q11, #4
+ veor q1, q1, q10
+ veor q0, q0, q11
+ sub r5,r5,#1
+ b .Ldec_sbox
+.align 4
+.Ldec_loop:
+ vldmia r4!, {q8-q11}
+ veor q8, q8, q0
+ veor q9, q9, q1
+ vtbl.8 d0, {q8}, d24
+ vtbl.8 d1, {q8}, d25
+ vldmia r4!, {q8}
+ veor q10, q10, q2
+ vtbl.8 d2, {q9}, d24
+ vtbl.8 d3, {q9}, d25
+ vldmia r4!, {q9}
+ veor q11, q11, q3
+ vtbl.8 d4, {q10}, d24
+ vtbl.8 d5, {q10}, d25
+ vldmia r4!, {q10}
+ vtbl.8 d6, {q11}, d24
+ vtbl.8 d7, {q11}, d25
+ vldmia r4!, {q11}
+ veor q8, q8, q4
+ veor q9, q9, q5
+ vtbl.8 d8, {q8}, d24
+ vtbl.8 d9, {q8}, d25
+ veor q10, q10, q6
+ vtbl.8 d10, {q9}, d24
+ vtbl.8 d11, {q9}, d25
+ veor q11, q11, q7
+ vtbl.8 d12, {q10}, d24
+ vtbl.8 d13, {q10}, d25
+ vtbl.8 d14, {q11}, d24
+ vtbl.8 d15, {q11}, d25
+.Ldec_sbox:
+ veor q1, q1, q4
+ veor q3, q3, q4
+
+ veor q4, q4, q7
+ veor q1, q1, q6
+ veor q2, q2, q7
+ veor q6, q6, q4
+
+ veor q0, q0, q1
+ veor q2, q2, q5
+ veor q7, q7, q6
+ veor q3, q3, q0
+ veor q5, q5, q0
+ veor q1, q1, q3
+ veor q11, q3, q0
+ veor q10, q7, q4
+ veor q9, q1, q6
+ veor q13, q4, q0
+ vmov q8, q10
+ veor q12, q5, q2
+
+ vorr q10, q10, q9
+ veor q15, q11, q8
+ vand q14, q11, q12
+ vorr q11, q11, q12
+ veor q12, q12, q9
+ vand q8, q8, q9
+ veor q9, q6, q2
+ vand q15, q15, q12
+ vand q13, q13, q9
+ veor q9, q3, q7
+ veor q12, q1, q5
+ veor q11, q11, q13
+ veor q10, q10, q13
+ vand q13, q9, q12
+ vorr q9, q9, q12
+ veor q11, q11, q15
+ veor q8, q8, q13
+ veor q10, q10, q14
+ veor q9, q9, q15
+ veor q8, q8, q14
+ vand q12, q4, q6
+ veor q9, q9, q14
+ vand q13, q0, q2
+ vand q14, q7, q1
+ vorr q15, q3, q5
+ veor q11, q11, q12
+ veor q9, q9, q14
+ veor q8, q8, q15
+ veor q10, q10, q13
+
+ @ Inv_GF16 0, 1, 2, 3, s0, s1, s2, s3
+
+ @ new smaller inversion
+
+ vand q14, q11, q9
+ vmov q12, q8
+
+ veor q13, q10, q14
+ veor q15, q8, q14
+ veor q14, q8, q14 @ q14=q15
+
+ vbsl q13, q9, q8
+ vbsl q15, q11, q10
+ veor q11, q11, q10
+
+ vbsl q12, q13, q14
+ vbsl q8, q14, q13
+
+ vand q14, q12, q15
+ veor q9, q9, q8
+
+ veor q14, q14, q11
+ veor q12, q5, q2
+ veor q8, q1, q6
+ veor q10, q15, q14
+ vand q10, q10, q5
+ veor q5, q5, q1
+ vand q11, q1, q15
+ vand q5, q5, q14
+ veor q1, q11, q10
+ veor q5, q5, q11
+ veor q15, q15, q13
+ veor q14, q14, q9
+ veor q11, q15, q14
+ veor q10, q13, q9
+ vand q11, q11, q12
+ vand q10, q10, q2
+ veor q12, q12, q8
+ veor q2, q2, q6
+ vand q8, q8, q15
+ vand q6, q6, q13
+ vand q12, q12, q14
+ vand q2, q2, q9
+ veor q8, q8, q12
+ veor q2, q2, q6
+ veor q12, q12, q11
+ veor q6, q6, q10
+ veor q5, q5, q12
+ veor q2, q2, q12
+ veor q1, q1, q8
+ veor q6, q6, q8
+
+ veor q12, q3, q0
+ veor q8, q7, q4
+ veor q11, q15, q14
+ veor q10, q13, q9
+ vand q11, q11, q12
+ vand q10, q10, q0
+ veor q12, q12, q8
+ veor q0, q0, q4
+ vand q8, q8, q15
+ vand q4, q4, q13
+ vand q12, q12, q14
+ vand q0, q0, q9
+ veor q8, q8, q12
+ veor q0, q0, q4
+ veor q12, q12, q11
+ veor q4, q4, q10
+ veor q15, q15, q13
+ veor q14, q14, q9
+ veor q10, q15, q14
+ vand q10, q10, q3
+ veor q3, q3, q7
+ vand q11, q7, q15
+ vand q3, q3, q14
+ veor q7, q11, q10
+ veor q3, q3, q11
+ veor q3, q3, q12
+ veor q0, q0, q12
+ veor q7, q7, q8
+ veor q4, q4, q8
+ veor q1, q1, q7
+ veor q6, q6, q5
+
+ veor q4, q4, q1
+ veor q2, q2, q7
+ veor q5, q5, q7
+ veor q4, q4, q2
+ veor q7, q7, q0
+ veor q4, q4, q5
+ veor q3, q3, q6
+ veor q6, q6, q1
+ veor q3, q3, q4
+
+ veor q4, q4, q0
+ veor q7, q7, q3
+ subs r5,r5,#1
+ bcc .Ldec_done
+ @ multiplication by 0x05-0x00-0x04-0x00
+ vext.8 q8, q0, q0, #8
+ vext.8 q14, q3, q3, #8
+ vext.8 q15, q5, q5, #8
+ veor q8, q8, q0
+ vext.8 q9, q1, q1, #8
+ veor q14, q14, q3
+ vext.8 q10, q6, q6, #8
+ veor q15, q15, q5
+ vext.8 q11, q4, q4, #8
+ veor q9, q9, q1
+ vext.8 q12, q2, q2, #8
+ veor q10, q10, q6
+ vext.8 q13, q7, q7, #8
+ veor q11, q11, q4
+ veor q12, q12, q2
+ veor q13, q13, q7
+
+ veor q0, q0, q14
+ veor q1, q1, q14
+ veor q6, q6, q8
+ veor q2, q2, q10
+ veor q4, q4, q9
+ veor q1, q1, q15
+ veor q6, q6, q15
+ veor q2, q2, q14
+ veor q7, q7, q11
+ veor q4, q4, q14
+ veor q3, q3, q12
+ veor q2, q2, q15
+ veor q7, q7, q15
+ veor q5, q5, q13
+ vext.8 q8, q0, q0, #12 @ x0 <<< 32
+ vext.8 q9, q1, q1, #12
+ veor q0, q0, q8 @ x0 ^ (x0 <<< 32)
+ vext.8 q10, q6, q6, #12
+ veor q1, q1, q9
+ vext.8 q11, q4, q4, #12
+ veor q6, q6, q10
+ vext.8 q12, q2, q2, #12
+ veor q4, q4, q11
+ vext.8 q13, q7, q7, #12
+ veor q2, q2, q12
+ vext.8 q14, q3, q3, #12
+ veor q7, q7, q13
+ vext.8 q15, q5, q5, #12
+ veor q3, q3, q14
+
+ veor q9, q9, q0
+ veor q5, q5, q15
+ vext.8 q0, q0, q0, #8 @ (x0 ^ (x0 <<< 32)) <<< 64)
+ veor q10, q10, q1
+ veor q8, q8, q5
+ veor q9, q9, q5
+ vext.8 q1, q1, q1, #8
+ veor q13, q13, q2
+ veor q0, q0, q8
+ veor q14, q14, q7
+ veor q1, q1, q9
+ vext.8 q8, q2, q2, #8
+ veor q12, q12, q4
+ vext.8 q9, q7, q7, #8
+ veor q15, q15, q3
+ vext.8 q2, q4, q4, #8
+ veor q11, q11, q6
+ vext.8 q7, q5, q5, #8
+ veor q12, q12, q5
+ vext.8 q4, q3, q3, #8
+ veor q11, q11, q5
+ vext.8 q3, q6, q6, #8
+ veor q5, q9, q13
+ veor q11, q11, q2
+ veor q7, q7, q15
+ veor q6, q4, q14
+ veor q4, q8, q12
+ veor q2, q3, q10
+ vmov q3, q11
+ @ vmov q5, q9
+ vldmia r6, {q12} @ .LISR
+ ite eq @ Thumb2 thing, sanity check in ARM
+ addeq r6,r6,#0x10
+ bne .Ldec_loop
+ vldmia r6, {q12} @ .LISRM0
+ b .Ldec_loop
+.align 4
+.Ldec_done:
+ vmov.i8 q8,#0x55 @ compose .LBS0
+ vmov.i8 q9,#0x33 @ compose .LBS1
+ vshr.u64 q10, q3, #1
+ vshr.u64 q11, q2, #1
+ veor q10, q10, q5
+ veor q11, q11, q7
+ vand q10, q10, q8
+ vand q11, q11, q8
+ veor q5, q5, q10
+ vshl.u64 q10, q10, #1
+ veor q7, q7, q11
+ vshl.u64 q11, q11, #1
+ veor q3, q3, q10
+ veor q2, q2, q11
+ vshr.u64 q10, q6, #1
+ vshr.u64 q11, q0, #1
+ veor q10, q10, q4
+ veor q11, q11, q1
+ vand q10, q10, q8
+ vand q11, q11, q8
+ veor q4, q4, q10
+ vshl.u64 q10, q10, #1
+ veor q1, q1, q11
+ vshl.u64 q11, q11, #1
+ veor q6, q6, q10
+ veor q0, q0, q11
+ vmov.i8 q8,#0x0f @ compose .LBS2
+ vshr.u64 q10, q7, #2
+ vshr.u64 q11, q2, #2
+ veor q10, q10, q5
+ veor q11, q11, q3
+ vand q10, q10, q9
+ vand q11, q11, q9
+ veor q5, q5, q10
+ vshl.u64 q10, q10, #2
+ veor q3, q3, q11
+ vshl.u64 q11, q11, #2
+ veor q7, q7, q10
+ veor q2, q2, q11
+ vshr.u64 q10, q1, #2
+ vshr.u64 q11, q0, #2
+ veor q10, q10, q4
+ veor q11, q11, q6
+ vand q10, q10, q9
+ vand q11, q11, q9
+ veor q4, q4, q10
+ vshl.u64 q10, q10, #2
+ veor q6, q6, q11
+ vshl.u64 q11, q11, #2
+ veor q1, q1, q10
+ veor q0, q0, q11
+ vshr.u64 q10, q4, #4
+ vshr.u64 q11, q6, #4
+ veor q10, q10, q5
+ veor q11, q11, q3
+ vand q10, q10, q8
+ vand q11, q11, q8
+ veor q5, q5, q10
+ vshl.u64 q10, q10, #4
+ veor q3, q3, q11
+ vshl.u64 q11, q11, #4
+ veor q4, q4, q10
+ veor q6, q6, q11
+ vshr.u64 q10, q1, #4
+ vshr.u64 q11, q0, #4
+ veor q10, q10, q7
+ veor q11, q11, q2
+ vand q10, q10, q8
+ vand q11, q11, q8
+ veor q7, q7, q10
+ vshl.u64 q10, q10, #4
+ veor q2, q2, q11
+ vshl.u64 q11, q11, #4
+ veor q1, q1, q10
+ veor q0, q0, q11
+ vldmia r4, {q8} @ last round key
+ veor q6, q6, q8
+ veor q4, q4, q8
+ veor q2, q2, q8
+ veor q7, q7, q8
+ veor q3, q3, q8
+ veor q5, q5, q8
+ veor q0, q0, q8
+ veor q1, q1, q8
+ bx lr
+.size _bsaes_decrypt8,.-_bsaes_decrypt8
+
+.type _bsaes_const,%object
+.align 6
+_bsaes_const:
+.LM0ISR: @ InvShiftRows constants
+ .quad 0x0a0e0206070b0f03, 0x0004080c0d010509
+.LISR:
+ .quad 0x0504070602010003, 0x0f0e0d0c080b0a09
+.LISRM0:
+ .quad 0x01040b0e0205080f, 0x0306090c00070a0d
+.LM0SR: @ ShiftRows constants
+ .quad 0x0a0e02060f03070b, 0x0004080c05090d01
+.LSR:
+ .quad 0x0504070600030201, 0x0f0e0d0c0a09080b
+.LSRM0:
+ .quad 0x0304090e00050a0f, 0x01060b0c0207080d
+.LM0:
+ .quad 0x02060a0e03070b0f, 0x0004080c0105090d
+.LREVM0SR:
+ .quad 0x090d01050c000408, 0x03070b0f060a0e02
+.asciz "Bit-sliced AES for NEON, CRYPTOGAMS by <appro@openssl.org>"
+.align 6
+.size _bsaes_const,.-_bsaes_const
+
+.type _bsaes_encrypt8,%function
+.align 4
+_bsaes_encrypt8:
+ adr r6,_bsaes_encrypt8
+ vldmia r4!, {q9} @ round 0 key
+ sub r6,r6,#_bsaes_encrypt8-.LM0SR
+
+ vldmia r6!, {q8} @ .LM0SR
+_bsaes_encrypt8_alt:
+ veor q10, q0, q9 @ xor with round0 key
+ veor q11, q1, q9
+ vtbl.8 d0, {q10}, d16
+ vtbl.8 d1, {q10}, d17
+ veor q12, q2, q9
+ vtbl.8 d2, {q11}, d16
+ vtbl.8 d3, {q11}, d17
+ veor q13, q3, q9
+ vtbl.8 d4, {q12}, d16
+ vtbl.8 d5, {q12}, d17
+ veor q14, q4, q9
+ vtbl.8 d6, {q13}, d16
+ vtbl.8 d7, {q13}, d17
+ veor q15, q5, q9
+ vtbl.8 d8, {q14}, d16
+ vtbl.8 d9, {q14}, d17
+ veor q10, q6, q9
+ vtbl.8 d10, {q15}, d16
+ vtbl.8 d11, {q15}, d17
+ veor q11, q7, q9
+ vtbl.8 d12, {q10}, d16
+ vtbl.8 d13, {q10}, d17
+ vtbl.8 d14, {q11}, d16
+ vtbl.8 d15, {q11}, d17
+_bsaes_encrypt8_bitslice:
+ vmov.i8 q8,#0x55 @ compose .LBS0
+ vmov.i8 q9,#0x33 @ compose .LBS1
+ vshr.u64 q10, q6, #1
+ vshr.u64 q11, q4, #1
+ veor q10, q10, q7
+ veor q11, q11, q5
+ vand q10, q10, q8
+ vand q11, q11, q8
+ veor q7, q7, q10
+ vshl.u64 q10, q10, #1
+ veor q5, q5, q11
+ vshl.u64 q11, q11, #1
+ veor q6, q6, q10
+ veor q4, q4, q11
+ vshr.u64 q10, q2, #1
+ vshr.u64 q11, q0, #1
+ veor q10, q10, q3
+ veor q11, q11, q1
+ vand q10, q10, q8
+ vand q11, q11, q8
+ veor q3, q3, q10
+ vshl.u64 q10, q10, #1
+ veor q1, q1, q11
+ vshl.u64 q11, q11, #1
+ veor q2, q2, q10
+ veor q0, q0, q11
+ vmov.i8 q8,#0x0f @ compose .LBS2
+ vshr.u64 q10, q5, #2
+ vshr.u64 q11, q4, #2
+ veor q10, q10, q7
+ veor q11, q11, q6
+ vand q10, q10, q9
+ vand q11, q11, q9
+ veor q7, q7, q10
+ vshl.u64 q10, q10, #2
+ veor q6, q6, q11
+ vshl.u64 q11, q11, #2
+ veor q5, q5, q10
+ veor q4, q4, q11
+ vshr.u64 q10, q1, #2
+ vshr.u64 q11, q0, #2
+ veor q10, q10, q3
+ veor q11, q11, q2
+ vand q10, q10, q9
+ vand q11, q11, q9
+ veor q3, q3, q10
+ vshl.u64 q10, q10, #2
+ veor q2, q2, q11
+ vshl.u64 q11, q11, #2
+ veor q1, q1, q10
+ veor q0, q0, q11
+ vshr.u64 q10, q3, #4
+ vshr.u64 q11, q2, #4
+ veor q10, q10, q7
+ veor q11, q11, q6
+ vand q10, q10, q8
+ vand q11, q11, q8
+ veor q7, q7, q10
+ vshl.u64 q10, q10, #4
+ veor q6, q6, q11
+ vshl.u64 q11, q11, #4
+ veor q3, q3, q10
+ veor q2, q2, q11
+ vshr.u64 q10, q1, #4
+ vshr.u64 q11, q0, #4
+ veor q10, q10, q5
+ veor q11, q11, q4
+ vand q10, q10, q8
+ vand q11, q11, q8
+ veor q5, q5, q10
+ vshl.u64 q10, q10, #4
+ veor q4, q4, q11
+ vshl.u64 q11, q11, #4
+ veor q1, q1, q10
+ veor q0, q0, q11
+ sub r5,r5,#1
+ b .Lenc_sbox
+.align 4
+.Lenc_loop:
+ vldmia r4!, {q8-q11}
+ veor q8, q8, q0
+ veor q9, q9, q1
+ vtbl.8 d0, {q8}, d24
+ vtbl.8 d1, {q8}, d25
+ vldmia r4!, {q8}
+ veor q10, q10, q2
+ vtbl.8 d2, {q9}, d24
+ vtbl.8 d3, {q9}, d25
+ vldmia r4!, {q9}
+ veor q11, q11, q3
+ vtbl.8 d4, {q10}, d24
+ vtbl.8 d5, {q10}, d25
+ vldmia r4!, {q10}
+ vtbl.8 d6, {q11}, d24
+ vtbl.8 d7, {q11}, d25
+ vldmia r4!, {q11}
+ veor q8, q8, q4
+ veor q9, q9, q5
+ vtbl.8 d8, {q8}, d24
+ vtbl.8 d9, {q8}, d25
+ veor q10, q10, q6
+ vtbl.8 d10, {q9}, d24
+ vtbl.8 d11, {q9}, d25
+ veor q11, q11, q7
+ vtbl.8 d12, {q10}, d24
+ vtbl.8 d13, {q10}, d25
+ vtbl.8 d14, {q11}, d24
+ vtbl.8 d15, {q11}, d25
+.Lenc_sbox:
+ veor q2, q2, q1
+ veor q5, q5, q6
+ veor q3, q3, q0
+ veor q6, q6, q2
+ veor q5, q5, q0
+
+ veor q6, q6, q3
+ veor q3, q3, q7
+ veor q7, q7, q5
+ veor q3, q3, q4
+ veor q4, q4, q5
+
+ veor q2, q2, q7
+ veor q3, q3, q1
+ veor q1, q1, q5
+ veor q11, q7, q4
+ veor q10, q1, q2
+ veor q9, q5, q3
+ veor q13, q2, q4
+ vmov q8, q10
+ veor q12, q6, q0
+
+ vorr q10, q10, q9
+ veor q15, q11, q8
+ vand q14, q11, q12
+ vorr q11, q11, q12
+ veor q12, q12, q9
+ vand q8, q8, q9
+ veor q9, q3, q0
+ vand q15, q15, q12
+ vand q13, q13, q9
+ veor q9, q7, q1
+ veor q12, q5, q6
+ veor q11, q11, q13
+ veor q10, q10, q13
+ vand q13, q9, q12
+ vorr q9, q9, q12
+ veor q11, q11, q15
+ veor q8, q8, q13
+ veor q10, q10, q14
+ veor q9, q9, q15
+ veor q8, q8, q14
+ vand q12, q2, q3
+ veor q9, q9, q14
+ vand q13, q4, q0
+ vand q14, q1, q5
+ vorr q15, q7, q6
+ veor q11, q11, q12
+ veor q9, q9, q14
+ veor q8, q8, q15
+ veor q10, q10, q13
+
+ @ Inv_GF16 0, 1, 2, 3, s0, s1, s2, s3
+
+ @ new smaller inversion
+
+ vand q14, q11, q9
+ vmov q12, q8
+
+ veor q13, q10, q14
+ veor q15, q8, q14
+ veor q14, q8, q14 @ q14=q15
+
+ vbsl q13, q9, q8
+ vbsl q15, q11, q10
+ veor q11, q11, q10
+
+ vbsl q12, q13, q14
+ vbsl q8, q14, q13
+
+ vand q14, q12, q15
+ veor q9, q9, q8
+
+ veor q14, q14, q11
+ veor q12, q6, q0
+ veor q8, q5, q3
+ veor q10, q15, q14
+ vand q10, q10, q6
+ veor q6, q6, q5
+ vand q11, q5, q15
+ vand q6, q6, q14
+ veor q5, q11, q10
+ veor q6, q6, q11
+ veor q15, q15, q13
+ veor q14, q14, q9
+ veor q11, q15, q14
+ veor q10, q13, q9
+ vand q11, q11, q12
+ vand q10, q10, q0
+ veor q12, q12, q8
+ veor q0, q0, q3
+ vand q8, q8, q15
+ vand q3, q3, q13
+ vand q12, q12, q14
+ vand q0, q0, q9
+ veor q8, q8, q12
+ veor q0, q0, q3
+ veor q12, q12, q11
+ veor q3, q3, q10
+ veor q6, q6, q12
+ veor q0, q0, q12
+ veor q5, q5, q8
+ veor q3, q3, q8
+
+ veor q12, q7, q4
+ veor q8, q1, q2
+ veor q11, q15, q14
+ veor q10, q13, q9
+ vand q11, q11, q12
+ vand q10, q10, q4
+ veor q12, q12, q8
+ veor q4, q4, q2
+ vand q8, q8, q15
+ vand q2, q2, q13
+ vand q12, q12, q14
+ vand q4, q4, q9
+ veor q8, q8, q12
+ veor q4, q4, q2
+ veor q12, q12, q11
+ veor q2, q2, q10
+ veor q15, q15, q13
+ veor q14, q14, q9
+ veor q10, q15, q14
+ vand q10, q10, q7
+ veor q7, q7, q1
+ vand q11, q1, q15
+ vand q7, q7, q14
+ veor q1, q11, q10
+ veor q7, q7, q11
+ veor q7, q7, q12
+ veor q4, q4, q12
+ veor q1, q1, q8
+ veor q2, q2, q8
+ veor q7, q7, q0
+ veor q1, q1, q6
+ veor q6, q6, q0
+ veor q4, q4, q7
+ veor q0, q0, q1
+
+ veor q1, q1, q5
+ veor q5, q5, q2
+ veor q2, q2, q3
+ veor q3, q3, q5
+ veor q4, q4, q5
+
+ veor q6, q6, q3
+ subs r5,r5,#1
+ bcc .Lenc_done
+ vext.8 q8, q0, q0, #12 @ x0 <<< 32
+ vext.8 q9, q1, q1, #12
+ veor q0, q0, q8 @ x0 ^ (x0 <<< 32)
+ vext.8 q10, q4, q4, #12
+ veor q1, q1, q9
+ vext.8 q11, q6, q6, #12
+ veor q4, q4, q10
+ vext.8 q12, q3, q3, #12
+ veor q6, q6, q11
+ vext.8 q13, q7, q7, #12
+ veor q3, q3, q12
+ vext.8 q14, q2, q2, #12
+ veor q7, q7, q13
+ vext.8 q15, q5, q5, #12
+ veor q2, q2, q14
+
+ veor q9, q9, q0
+ veor q5, q5, q15
+ vext.8 q0, q0, q0, #8 @ (x0 ^ (x0 <<< 32)) <<< 64)
+ veor q10, q10, q1
+ veor q8, q8, q5
+ veor q9, q9, q5
+ vext.8 q1, q1, q1, #8
+ veor q13, q13, q3
+ veor q0, q0, q8
+ veor q14, q14, q7
+ veor q1, q1, q9
+ vext.8 q8, q3, q3, #8
+ veor q12, q12, q6
+ vext.8 q9, q7, q7, #8
+ veor q15, q15, q2
+ vext.8 q3, q6, q6, #8
+ veor q11, q11, q4
+ vext.8 q7, q5, q5, #8
+ veor q12, q12, q5
+ vext.8 q6, q2, q2, #8
+ veor q11, q11, q5
+ vext.8 q2, q4, q4, #8
+ veor q5, q9, q13
+ veor q4, q8, q12
+ veor q3, q3, q11
+ veor q7, q7, q15
+ veor q6, q6, q14
+ @ vmov q4, q8
+ veor q2, q2, q10
+ @ vmov q5, q9
+ vldmia r6, {q12} @ .LSR
+ ite eq @ Thumb2 thing, samity check in ARM
+ addeq r6,r6,#0x10
+ bne .Lenc_loop
+ vldmia r6, {q12} @ .LSRM0
+ b .Lenc_loop
+.align 4
+.Lenc_done:
+ vmov.i8 q8,#0x55 @ compose .LBS0
+ vmov.i8 q9,#0x33 @ compose .LBS1
+ vshr.u64 q10, q2, #1
+ vshr.u64 q11, q3, #1
+ veor q10, q10, q5
+ veor q11, q11, q7
+ vand q10, q10, q8
+ vand q11, q11, q8
+ veor q5, q5, q10
+ vshl.u64 q10, q10, #1
+ veor q7, q7, q11
+ vshl.u64 q11, q11, #1
+ veor q2, q2, q10
+ veor q3, q3, q11
+ vshr.u64 q10, q4, #1
+ vshr.u64 q11, q0, #1
+ veor q10, q10, q6
+ veor q11, q11, q1
+ vand q10, q10, q8
+ vand q11, q11, q8
+ veor q6, q6, q10
+ vshl.u64 q10, q10, #1
+ veor q1, q1, q11
+ vshl.u64 q11, q11, #1
+ veor q4, q4, q10
+ veor q0, q0, q11
+ vmov.i8 q8,#0x0f @ compose .LBS2
+ vshr.u64 q10, q7, #2
+ vshr.u64 q11, q3, #2
+ veor q10, q10, q5
+ veor q11, q11, q2
+ vand q10, q10, q9
+ vand q11, q11, q9
+ veor q5, q5, q10
+ vshl.u64 q10, q10, #2
+ veor q2, q2, q11
+ vshl.u64 q11, q11, #2
+ veor q7, q7, q10
+ veor q3, q3, q11
+ vshr.u64 q10, q1, #2
+ vshr.u64 q11, q0, #2
+ veor q10, q10, q6
+ veor q11, q11, q4
+ vand q10, q10, q9
+ vand q11, q11, q9
+ veor q6, q6, q10
+ vshl.u64 q10, q10, #2
+ veor q4, q4, q11
+ vshl.u64 q11, q11, #2
+ veor q1, q1, q10
+ veor q0, q0, q11
+ vshr.u64 q10, q6, #4
+ vshr.u64 q11, q4, #4
+ veor q10, q10, q5
+ veor q11, q11, q2
+ vand q10, q10, q8
+ vand q11, q11, q8
+ veor q5, q5, q10
+ vshl.u64 q10, q10, #4
+ veor q2, q2, q11
+ vshl.u64 q11, q11, #4
+ veor q6, q6, q10
+ veor q4, q4, q11
+ vshr.u64 q10, q1, #4
+ vshr.u64 q11, q0, #4
+ veor q10, q10, q7
+ veor q11, q11, q3
+ vand q10, q10, q8
+ vand q11, q11, q8
+ veor q7, q7, q10
+ vshl.u64 q10, q10, #4
+ veor q3, q3, q11
+ vshl.u64 q11, q11, #4
+ veor q1, q1, q10
+ veor q0, q0, q11
+ vldmia r4, {q8} @ last round key
+ veor q4, q4, q8
+ veor q6, q6, q8
+ veor q3, q3, q8
+ veor q7, q7, q8
+ veor q2, q2, q8
+ veor q5, q5, q8
+ veor q0, q0, q8
+ veor q1, q1, q8
+ bx lr
+.size _bsaes_encrypt8,.-_bsaes_encrypt8
+.type _bsaes_key_convert,%function
+.align 4
+_bsaes_key_convert:
+ adr r6,_bsaes_key_convert
+ vld1.8 {q7}, [r4]! @ load round 0 key
+ sub r6,r6,#_bsaes_key_convert-.LM0
+ vld1.8 {q15}, [r4]! @ load round 1 key
+
+ vmov.i8 q8, #0x01 @ bit masks
+ vmov.i8 q9, #0x02
+ vmov.i8 q10, #0x04
+ vmov.i8 q11, #0x08
+ vmov.i8 q12, #0x10
+ vmov.i8 q13, #0x20
+ vldmia r6, {q14} @ .LM0
+
+#ifdef __ARMEL__
+ vrev32.8 q7, q7
+ vrev32.8 q15, q15
+#endif
+ sub r5,r5,#1
+ vstmia r12!, {q7} @ save round 0 key
+ b .Lkey_loop
+
+.align 4
+.Lkey_loop:
+ vtbl.8 d14,{q15},d28
+ vtbl.8 d15,{q15},d29
+ vmov.i8 q6, #0x40
+ vmov.i8 q15, #0x80
+
+ vtst.8 q0, q7, q8
+ vtst.8 q1, q7, q9
+ vtst.8 q2, q7, q10
+ vtst.8 q3, q7, q11
+ vtst.8 q4, q7, q12
+ vtst.8 q5, q7, q13
+ vtst.8 q6, q7, q6
+ vtst.8 q7, q7, q15
+ vld1.8 {q15}, [r4]! @ load next round key
+ vmvn q0, q0 @ "pnot"
+ vmvn q1, q1
+ vmvn q5, q5
+ vmvn q6, q6
+#ifdef __ARMEL__
+ vrev32.8 q15, q15
+#endif
+ subs r5,r5,#1
+ vstmia r12!,{q0-q7} @ write bit-sliced round key
+ bne .Lkey_loop
+
+ vmov.i8 q7,#0x63 @ compose .L63
+ @ don't save last round key
+ bx lr
+.size _bsaes_key_convert,.-_bsaes_key_convert
+.extern AES_cbc_encrypt
+.extern AES_decrypt
+
+.global bsaes_cbc_encrypt
+.hidden bsaes_cbc_encrypt
+.type bsaes_cbc_encrypt,%function
+.align 5
+bsaes_cbc_encrypt:
+#ifndef __KERNEL__
+ cmp r2, #128
+#ifndef __thumb__
+ blo AES_cbc_encrypt
+#else
+ bhs 1f
+ b AES_cbc_encrypt
+1:
+#endif
+#endif
+
+ @ it is up to the caller to make sure we are called with enc == 0
+
+ mov ip, sp
+ stmdb sp!, {r4-r10, lr}
+ VFP_ABI_PUSH
+ ldr r8, [ip] @ IV is 1st arg on the stack
+ mov r2, r2, lsr#4 @ len in 16 byte blocks
+ sub sp, #0x10 @ scratch space to carry over the IV
+ mov r9, sp @ save sp
+
+ ldr r10, [r3, #240] @ get # of rounds
+#ifndef BSAES_ASM_EXTENDED_KEY
+ @ allocate the key schedule on the stack
+ sub r12, sp, r10, lsl#7 @ 128 bytes per inner round key
+ add r12, #96 @ sifze of bit-slices key schedule
+
+ @ populate the key schedule
+ mov r4, r3 @ pass key
+ mov r5, r10 @ pass # of rounds
+ mov sp, r12 @ sp is sp
+ bl _bsaes_key_convert
+ vldmia sp, {q6}
+ vstmia r12, {q15} @ save last round key
+ veor q7, q7, q6 @ fix up round 0 key
+ vstmia sp, {q7}
+#else
+ ldr r12, [r3, #244]
+ eors r12, #1
+ beq 0f
+
+ @ populate the key schedule
+ str r12, [r3, #244]
+ mov r4, r3 @ pass key
+ mov r5, r10 @ pass # of rounds
+ add r12, r3, #248 @ pass key schedule
+ bl _bsaes_key_convert
+ add r4, r3, #248
+ vldmia r4, {q6}
+ vstmia r12, {q15} @ save last round key
+ veor q7, q7, q6 @ fix up round 0 key
+ vstmia r4, {q7}
+
+.align 2
+0:
+#endif
+
+ vld1.8 {q15}, [r8] @ load IV
+ b .Lcbc_dec_loop
+
+.align 4
+.Lcbc_dec_loop:
+ subs r2, r2, #0x8
+ bmi .Lcbc_dec_loop_finish
+
+ vld1.8 {q0-q1}, [r0]! @ load input
+ vld1.8 {q2-q3}, [r0]!
+#ifndef BSAES_ASM_EXTENDED_KEY
+ mov r4, sp @ pass the key
+#else
+ add r4, r3, #248
+#endif
+ vld1.8 {q4-q5}, [r0]!
+ mov r5, r10
+ vld1.8 {q6-q7}, [r0]
+ sub r0, r0, #0x60
+ vstmia r9, {q15} @ put aside IV
+
+ bl _bsaes_decrypt8
+
+ vldmia r9, {q14} @ reload IV
+ vld1.8 {q8-q9}, [r0]! @ reload input
+ veor q0, q0, q14 @ ^= IV
+ vld1.8 {q10-q11}, [r0]!
+ veor q1, q1, q8
+ veor q6, q6, q9
+ vld1.8 {q12-q13}, [r0]!
+ veor q4, q4, q10
+ veor q2, q2, q11
+ vld1.8 {q14-q15}, [r0]!
+ veor q7, q7, q12
+ vst1.8 {q0-q1}, [r1]! @ write output
+ veor q3, q3, q13
+ vst1.8 {q6}, [r1]!
+ veor q5, q5, q14
+ vst1.8 {q4}, [r1]!
+ vst1.8 {q2}, [r1]!
+ vst1.8 {q7}, [r1]!
+ vst1.8 {q3}, [r1]!
+ vst1.8 {q5}, [r1]!
+
+ b .Lcbc_dec_loop
+
+.Lcbc_dec_loop_finish:
+ adds r2, r2, #8
+ beq .Lcbc_dec_done
+
+ vld1.8 {q0}, [r0]! @ load input
+ cmp r2, #2
+ blo .Lcbc_dec_one
+ vld1.8 {q1}, [r0]!
+#ifndef BSAES_ASM_EXTENDED_KEY
+ mov r4, sp @ pass the key
+#else
+ add r4, r3, #248
+#endif
+ mov r5, r10
+ vstmia r9, {q15} @ put aside IV
+ beq .Lcbc_dec_two
+ vld1.8 {q2}, [r0]!
+ cmp r2, #4
+ blo .Lcbc_dec_three
+ vld1.8 {q3}, [r0]!
+ beq .Lcbc_dec_four
+ vld1.8 {q4}, [r0]!
+ cmp r2, #6
+ blo .Lcbc_dec_five
+ vld1.8 {q5}, [r0]!
+ beq .Lcbc_dec_six
+ vld1.8 {q6}, [r0]!
+ sub r0, r0, #0x70
+
+ bl _bsaes_decrypt8
+
+ vldmia r9, {q14} @ reload IV
+ vld1.8 {q8-q9}, [r0]! @ reload input
+ veor q0, q0, q14 @ ^= IV
+ vld1.8 {q10-q11}, [r0]!
+ veor q1, q1, q8
+ veor q6, q6, q9
+ vld1.8 {q12-q13}, [r0]!
+ veor q4, q4, q10
+ veor q2, q2, q11
+ vld1.8 {q15}, [r0]!
+ veor q7, q7, q12
+ vst1.8 {q0-q1}, [r1]! @ write output
+ veor q3, q3, q13
+ vst1.8 {q6}, [r1]!
+ vst1.8 {q4}, [r1]!
+ vst1.8 {q2}, [r1]!
+ vst1.8 {q7}, [r1]!
+ vst1.8 {q3}, [r1]!
+ b .Lcbc_dec_done
+.align 4
+.Lcbc_dec_six:
+ sub r0, r0, #0x60
+ bl _bsaes_decrypt8
+ vldmia r9,{q14} @ reload IV
+ vld1.8 {q8-q9}, [r0]! @ reload input
+ veor q0, q0, q14 @ ^= IV
+ vld1.8 {q10-q11}, [r0]!
+ veor q1, q1, q8
+ veor q6, q6, q9
+ vld1.8 {q12}, [r0]!
+ veor q4, q4, q10
+ veor q2, q2, q11
+ vld1.8 {q15}, [r0]!
+ veor q7, q7, q12
+ vst1.8 {q0-q1}, [r1]! @ write output
+ vst1.8 {q6}, [r1]!
+ vst1.8 {q4}, [r1]!
+ vst1.8 {q2}, [r1]!
+ vst1.8 {q7}, [r1]!
+ b .Lcbc_dec_done
+.align 4
+.Lcbc_dec_five:
+ sub r0, r0, #0x50
+ bl _bsaes_decrypt8
+ vldmia r9, {q14} @ reload IV
+ vld1.8 {q8-q9}, [r0]! @ reload input
+ veor q0, q0, q14 @ ^= IV
+ vld1.8 {q10-q11}, [r0]!
+ veor q1, q1, q8
+ veor q6, q6, q9
+ vld1.8 {q15}, [r0]!
+ veor q4, q4, q10
+ vst1.8 {q0-q1}, [r1]! @ write output
+ veor q2, q2, q11
+ vst1.8 {q6}, [r1]!
+ vst1.8 {q4}, [r1]!
+ vst1.8 {q2}, [r1]!
+ b .Lcbc_dec_done
+.align 4
+.Lcbc_dec_four:
+ sub r0, r0, #0x40
+ bl _bsaes_decrypt8
+ vldmia r9, {q14} @ reload IV
+ vld1.8 {q8-q9}, [r0]! @ reload input
+ veor q0, q0, q14 @ ^= IV
+ vld1.8 {q10}, [r0]!
+ veor q1, q1, q8
+ veor q6, q6, q9
+ vld1.8 {q15}, [r0]!
+ veor q4, q4, q10
+ vst1.8 {q0-q1}, [r1]! @ write output
+ vst1.8 {q6}, [r1]!
+ vst1.8 {q4}, [r1]!
+ b .Lcbc_dec_done
+.align 4
+.Lcbc_dec_three:
+ sub r0, r0, #0x30
+ bl _bsaes_decrypt8
+ vldmia r9, {q14} @ reload IV
+ vld1.8 {q8-q9}, [r0]! @ reload input
+ veor q0, q0, q14 @ ^= IV
+ vld1.8 {q15}, [r0]!
+ veor q1, q1, q8
+ veor q6, q6, q9
+ vst1.8 {q0-q1}, [r1]! @ write output
+ vst1.8 {q6}, [r1]!
+ b .Lcbc_dec_done
+.align 4
+.Lcbc_dec_two:
+ sub r0, r0, #0x20
+ bl _bsaes_decrypt8
+ vldmia r9, {q14} @ reload IV
+ vld1.8 {q8}, [r0]! @ reload input
+ veor q0, q0, q14 @ ^= IV
+ vld1.8 {q15}, [r0]! @ reload input
+ veor q1, q1, q8
+ vst1.8 {q0-q1}, [r1]! @ write output
+ b .Lcbc_dec_done
+.align 4
+.Lcbc_dec_one:
+ sub r0, r0, #0x10
+ mov r10, r1 @ save original out pointer
+ mov r1, r9 @ use the iv scratch space as out buffer
+ mov r2, r3
+ vmov q4,q15 @ just in case ensure that IV
+ vmov q5,q0 @ and input are preserved
+ bl AES_decrypt
+ vld1.8 {q0}, [r9,:64] @ load result
+ veor q0, q0, q4 @ ^= IV
+ vmov q15, q5 @ q5 holds input
+ vst1.8 {q0}, [r10] @ write output
+
+.Lcbc_dec_done:
+#ifndef BSAES_ASM_EXTENDED_KEY
+ vmov.i32 q0, #0
+ vmov.i32 q1, #0
+.Lcbc_dec_bzero: @ wipe key schedule [if any]
+ vstmia sp!, {q0-q1}
+ cmp sp, r9
+ bne .Lcbc_dec_bzero
+#endif
+
+ mov sp, r9
+ add sp, #0x10 @ add sp,r9,#0x10 is no good for thumb
+ vst1.8 {q15}, [r8] @ return IV
+ VFP_ABI_POP
+ ldmia sp!, {r4-r10, pc}
+.size bsaes_cbc_encrypt,.-bsaes_cbc_encrypt
+.extern AES_encrypt
+.global bsaes_ctr32_encrypt_blocks
+.hidden bsaes_ctr32_encrypt_blocks
+.type bsaes_ctr32_encrypt_blocks,%function
+.align 5
+bsaes_ctr32_encrypt_blocks:
+ cmp r2, #8 @ use plain AES for
+ blo .Lctr_enc_short @ small sizes
+
+ mov ip, sp
+ stmdb sp!, {r4-r10, lr}
+ VFP_ABI_PUSH
+ ldr r8, [ip] @ ctr is 1st arg on the stack
+ sub sp, sp, #0x10 @ scratch space to carry over the ctr
+ mov r9, sp @ save sp
+
+ ldr r10, [r3, #240] @ get # of rounds
+#ifndef BSAES_ASM_EXTENDED_KEY
+ @ allocate the key schedule on the stack
+ sub r12, sp, r10, lsl#7 @ 128 bytes per inner round key
+ add r12, #96 @ size of bit-sliced key schedule
+
+ @ populate the key schedule
+ mov r4, r3 @ pass key
+ mov r5, r10 @ pass # of rounds
+ mov sp, r12 @ sp is sp
+ bl _bsaes_key_convert
+ veor q7,q7,q15 @ fix up last round key
+ vstmia r12, {q7} @ save last round key
+
+ vld1.8 {q0}, [r8] @ load counter
+ add r8, r6, #.LREVM0SR-.LM0 @ borrow r8
+ vldmia sp, {q4} @ load round0 key
+#else
+ ldr r12, [r3, #244]
+ eors r12, #1
+ beq 0f
+
+ @ populate the key schedule
+ str r12, [r3, #244]
+ mov r4, r3 @ pass key
+ mov r5, r10 @ pass # of rounds
+ add r12, r3, #248 @ pass key schedule
+ bl _bsaes_key_convert
+ veor q7,q7,q15 @ fix up last round key
+ vstmia r12, {q7} @ save last round key
+
+.align 2
+0: add r12, r3, #248
+ vld1.8 {q0}, [r8] @ load counter
+ adrl r8, .LREVM0SR @ borrow r8
+ vldmia r12, {q4} @ load round0 key
+ sub sp, #0x10 @ place for adjusted round0 key
+#endif
+
+ vmov.i32 q8,#1 @ compose 1<<96
+ veor q9,q9,q9
+ vrev32.8 q0,q0
+ vext.8 q8,q9,q8,#4
+ vrev32.8 q4,q4
+ vadd.u32 q9,q8,q8 @ compose 2<<96
+ vstmia sp, {q4} @ save adjusted round0 key
+ b .Lctr_enc_loop
+
+.align 4
+.Lctr_enc_loop:
+ vadd.u32 q10, q8, q9 @ compose 3<<96
+ vadd.u32 q1, q0, q8 @ +1
+ vadd.u32 q2, q0, q9 @ +2
+ vadd.u32 q3, q0, q10 @ +3
+ vadd.u32 q4, q1, q10
+ vadd.u32 q5, q2, q10
+ vadd.u32 q6, q3, q10
+ vadd.u32 q7, q4, q10
+ vadd.u32 q10, q5, q10 @ next counter
+
+ @ Borrow prologue from _bsaes_encrypt8 to use the opportunity
+ @ to flip byte order in 32-bit counter
+
+ vldmia sp, {q9} @ load round0 key
+#ifndef BSAES_ASM_EXTENDED_KEY
+ add r4, sp, #0x10 @ pass next round key
+#else
+ add r4, r3, #264
+#endif
+ vldmia r8, {q8} @ .LREVM0SR
+ mov r5, r10 @ pass rounds
+ vstmia r9, {q10} @ save next counter
+ sub r6, r8, #.LREVM0SR-.LSR @ pass constants
+
+ bl _bsaes_encrypt8_alt
+
+ subs r2, r2, #8
+ blo .Lctr_enc_loop_done
+
+ vld1.8 {q8-q9}, [r0]! @ load input
+ vld1.8 {q10-q11}, [r0]!
+ veor q0, q8
+ veor q1, q9
+ vld1.8 {q12-q13}, [r0]!
+ veor q4, q10
+ veor q6, q11
+ vld1.8 {q14-q15}, [r0]!
+ veor q3, q12
+ vst1.8 {q0-q1}, [r1]! @ write output
+ veor q7, q13
+ veor q2, q14
+ vst1.8 {q4}, [r1]!
+ veor q5, q15
+ vst1.8 {q6}, [r1]!
+ vmov.i32 q8, #1 @ compose 1<<96
+ vst1.8 {q3}, [r1]!
+ veor q9, q9, q9
+ vst1.8 {q7}, [r1]!
+ vext.8 q8, q9, q8, #4
+ vst1.8 {q2}, [r1]!
+ vadd.u32 q9,q8,q8 @ compose 2<<96
+ vst1.8 {q5}, [r1]!
+ vldmia r9, {q0} @ load counter
+
+ bne .Lctr_enc_loop
+ b .Lctr_enc_done
+
+.align 4
+.Lctr_enc_loop_done:
+ add r2, r2, #8
+ vld1.8 {q8}, [r0]! @ load input
+ veor q0, q8
+ vst1.8 {q0}, [r1]! @ write output
+ cmp r2, #2
+ blo .Lctr_enc_done
+ vld1.8 {q9}, [r0]!
+ veor q1, q9
+ vst1.8 {q1}, [r1]!
+ beq .Lctr_enc_done
+ vld1.8 {q10}, [r0]!
+ veor q4, q10
+ vst1.8 {q4}, [r1]!
+ cmp r2, #4
+ blo .Lctr_enc_done
+ vld1.8 {q11}, [r0]!
+ veor q6, q11
+ vst1.8 {q6}, [r1]!
+ beq .Lctr_enc_done
+ vld1.8 {q12}, [r0]!
+ veor q3, q12
+ vst1.8 {q3}, [r1]!
+ cmp r2, #6
+ blo .Lctr_enc_done
+ vld1.8 {q13}, [r0]!
+ veor q7, q13
+ vst1.8 {q7}, [r1]!
+ beq .Lctr_enc_done
+ vld1.8 {q14}, [r0]
+ veor q2, q14
+ vst1.8 {q2}, [r1]!
+
+.Lctr_enc_done:
+ vmov.i32 q0, #0
+ vmov.i32 q1, #0
+#ifndef BSAES_ASM_EXTENDED_KEY
+.Lctr_enc_bzero: @ wipe key schedule [if any]
+ vstmia sp!, {q0-q1}
+ cmp sp, r9
+ bne .Lctr_enc_bzero
+#else
+ vstmia sp, {q0-q1}
+#endif
+
+ mov sp, r9
+ add sp, #0x10 @ add sp,r9,#0x10 is no good for thumb
+ VFP_ABI_POP
+ ldmia sp!, {r4-r10, pc} @ return
+
+.align 4
+.Lctr_enc_short:
+ ldr ip, [sp] @ ctr pointer is passed on stack
+ stmdb sp!, {r4-r8, lr}
+
+ mov r4, r0 @ copy arguments
+ mov r5, r1
+ mov r6, r2
+ mov r7, r3
+ ldr r8, [ip, #12] @ load counter LSW
+ vld1.8 {q1}, [ip] @ load whole counter value
+#ifdef __ARMEL__
+ rev r8, r8
+#endif
+ sub sp, sp, #0x10
+ vst1.8 {q1}, [sp,:64] @ copy counter value
+ sub sp, sp, #0x10
+
+.Lctr_enc_short_loop:
+ add r0, sp, #0x10 @ input counter value
+ mov r1, sp @ output on the stack
+ mov r2, r7 @ key
+
+ bl AES_encrypt
+
+ vld1.8 {q0}, [r4]! @ load input
+ vld1.8 {q1}, [sp,:64] @ load encrypted counter
+ add r8, r8, #1
+#ifdef __ARMEL__
+ rev r0, r8
+ str r0, [sp, #0x1c] @ next counter value
+#else
+ str r8, [sp, #0x1c] @ next counter value
+#endif
+ veor q0,q0,q1
+ vst1.8 {q0}, [r5]! @ store output
+ subs r6, r6, #1
+ bne .Lctr_enc_short_loop
+
+ vmov.i32 q0, #0
+ vmov.i32 q1, #0
+ vstmia sp!, {q0-q1}
+
+ ldmia sp!, {r4-r8, pc}
+.size bsaes_ctr32_encrypt_blocks,.-bsaes_ctr32_encrypt_blocks
+.globl bsaes_xts_encrypt
+.hidden bsaes_xts_encrypt
+.type bsaes_xts_encrypt,%function
+.align 4
+bsaes_xts_encrypt:
+ mov ip, sp
+ stmdb sp!, {r4-r10, lr} @ 0x20
+ VFP_ABI_PUSH
+ mov r6, sp @ future r3
+
+ mov r7, r0
+ mov r8, r1
+ mov r9, r2
+ mov r10, r3
+
+ sub r0, sp, #0x10 @ 0x10
+ bic r0, #0xf @ align at 16 bytes
+ mov sp, r0
+
+#ifdef XTS_CHAIN_TWEAK
+ ldr r0, [ip] @ pointer to input tweak
+#else
+ @ generate initial tweak
+ ldr r0, [ip, #4] @ iv[]
+ mov r1, sp
+ ldr r2, [ip, #0] @ key2
+ bl AES_encrypt
+ mov r0,sp @ pointer to initial tweak
+#endif
+
+ ldr r1, [r10, #240] @ get # of rounds
+ mov r3, r6
+#ifndef BSAES_ASM_EXTENDED_KEY
+ @ allocate the key schedule on the stack
+ sub r12, sp, r1, lsl#7 @ 128 bytes per inner round key
+ @ add r12, #96 @ size of bit-sliced key schedule
+ sub r12, #48 @ place for tweak[9]
+
+ @ populate the key schedule
+ mov r4, r10 @ pass key
+ mov r5, r1 @ pass # of rounds
+ mov sp, r12
+ add r12, #0x90 @ pass key schedule
+ bl _bsaes_key_convert
+ veor q7, q7, q15 @ fix up last round key
+ vstmia r12, {q7} @ save last round key
+#else
+ ldr r12, [r10, #244]
+ eors r12, #1
+ beq 0f
+
+ str r12, [r10, #244]
+ mov r4, r10 @ pass key
+ mov r5, r1 @ pass # of rounds
+ add r12, r10, #248 @ pass key schedule
+ bl _bsaes_key_convert
+ veor q7, q7, q15 @ fix up last round key
+ vstmia r12, {q7}
+
+.align 2
+0: sub sp, #0x90 @ place for tweak[9]
+#endif
+
+ vld1.8 {q8}, [r0] @ initial tweak
+ adr r2, .Lxts_magic
+
+ subs r9, #0x80
+ blo .Lxts_enc_short
+ b .Lxts_enc_loop
+
+.align 4
+.Lxts_enc_loop:
+ vldmia r2, {q5} @ load XTS magic
+ vshr.s64 q6, q8, #63
+ mov r0, sp
+ vand q6, q6, q5
+ vadd.u64 q9, q8, q8
+ vst1.64 {q8}, [r0,:128]!
+ vswp d13,d12
+ vshr.s64 q7, q9, #63
+ veor q9, q9, q6
+ vand q7, q7, q5
+ vadd.u64 q10, q9, q9
+ vst1.64 {q9}, [r0,:128]!
+ vswp d15,d14
+ vshr.s64 q6, q10, #63
+ veor q10, q10, q7
+ vand q6, q6, q5
+ vld1.8 {q0}, [r7]!
+ vadd.u64 q11, q10, q10
+ vst1.64 {q10}, [r0,:128]!
+ vswp d13,d12
+ vshr.s64 q7, q11, #63
+ veor q11, q11, q6
+ vand q7, q7, q5
+ vld1.8 {q1}, [r7]!
+ veor q0, q0, q8
+ vadd.u64 q12, q11, q11
+ vst1.64 {q11}, [r0,:128]!
+ vswp d15,d14
+ vshr.s64 q6, q12, #63
+ veor q12, q12, q7
+ vand q6, q6, q5
+ vld1.8 {q2}, [r7]!
+ veor q1, q1, q9
+ vadd.u64 q13, q12, q12
+ vst1.64 {q12}, [r0,:128]!
+ vswp d13,d12
+ vshr.s64 q7, q13, #63
+ veor q13, q13, q6
+ vand q7, q7, q5
+ vld1.8 {q3}, [r7]!
+ veor q2, q2, q10
+ vadd.u64 q14, q13, q13
+ vst1.64 {q13}, [r0,:128]!
+ vswp d15,d14
+ vshr.s64 q6, q14, #63
+ veor q14, q14, q7
+ vand q6, q6, q5
+ vld1.8 {q4}, [r7]!
+ veor q3, q3, q11
+ vadd.u64 q15, q14, q14
+ vst1.64 {q14}, [r0,:128]!
+ vswp d13,d12
+ vshr.s64 q7, q15, #63
+ veor q15, q15, q6
+ vand q7, q7, q5
+ vld1.8 {q5}, [r7]!
+ veor q4, q4, q12
+ vadd.u64 q8, q15, q15
+ vst1.64 {q15}, [r0,:128]!
+ vswp d15,d14
+ veor q8, q8, q7
+ vst1.64 {q8}, [r0,:128] @ next round tweak
+
+ vld1.8 {q6-q7}, [r7]!
+ veor q5, q5, q13
+#ifndef BSAES_ASM_EXTENDED_KEY
+ add r4, sp, #0x90 @ pass key schedule
+#else
+ add r4, r10, #248 @ pass key schedule
+#endif
+ veor q6, q6, q14
+ mov r5, r1 @ pass rounds
+ veor q7, q7, q15
+ mov r0, sp
+
+ bl _bsaes_encrypt8
+
+ vld1.64 {q8-q9}, [r0,:128]!
+ vld1.64 {q10-q11}, [r0,:128]!
+ veor q0, q0, q8
+ vld1.64 {q12-q13}, [r0,:128]!
+ veor q1, q1, q9
+ veor q8, q4, q10
+ vst1.8 {q0-q1}, [r8]!
+ veor q9, q6, q11
+ vld1.64 {q14-q15}, [r0,:128]!
+ veor q10, q3, q12
+ vst1.8 {q8-q9}, [r8]!
+ veor q11, q7, q13
+ veor q12, q2, q14
+ vst1.8 {q10-q11}, [r8]!
+ veor q13, q5, q15
+ vst1.8 {q12-q13}, [r8]!
+
+ vld1.64 {q8}, [r0,:128] @ next round tweak
+
+ subs r9, #0x80
+ bpl .Lxts_enc_loop
+
+.Lxts_enc_short:
+ adds r9, #0x70
+ bmi .Lxts_enc_done
+
+ vldmia r2, {q5} @ load XTS magic
+ vshr.s64 q7, q8, #63
+ mov r0, sp
+ vand q7, q7, q5
+ vadd.u64 q9, q8, q8
+ vst1.64 {q8}, [r0,:128]!
+ vswp d15,d14
+ vshr.s64 q6, q9, #63
+ veor q9, q9, q7
+ vand q6, q6, q5
+ vadd.u64 q10, q9, q9
+ vst1.64 {q9}, [r0,:128]!
+ vswp d13,d12
+ vshr.s64 q7, q10, #63
+ veor q10, q10, q6
+ vand q7, q7, q5
+ vld1.8 {q0}, [r7]!
+ subs r9, #0x10
+ bmi .Lxts_enc_1
+ vadd.u64 q11, q10, q10
+ vst1.64 {q10}, [r0,:128]!
+ vswp d15,d14
+ vshr.s64 q6, q11, #63
+ veor q11, q11, q7
+ vand q6, q6, q5
+ vld1.8 {q1}, [r7]!
+ subs r9, #0x10
+ bmi .Lxts_enc_2
+ veor q0, q0, q8
+ vadd.u64 q12, q11, q11
+ vst1.64 {q11}, [r0,:128]!
+ vswp d13,d12
+ vshr.s64 q7, q12, #63
+ veor q12, q12, q6
+ vand q7, q7, q5
+ vld1.8 {q2}, [r7]!
+ subs r9, #0x10
+ bmi .Lxts_enc_3
+ veor q1, q1, q9
+ vadd.u64 q13, q12, q12
+ vst1.64 {q12}, [r0,:128]!
+ vswp d15,d14
+ vshr.s64 q6, q13, #63
+ veor q13, q13, q7
+ vand q6, q6, q5
+ vld1.8 {q3}, [r7]!
+ subs r9, #0x10
+ bmi .Lxts_enc_4
+ veor q2, q2, q10
+ vadd.u64 q14, q13, q13
+ vst1.64 {q13}, [r0,:128]!
+ vswp d13,d12
+ vshr.s64 q7, q14, #63
+ veor q14, q14, q6
+ vand q7, q7, q5
+ vld1.8 {q4}, [r7]!
+ subs r9, #0x10
+ bmi .Lxts_enc_5
+ veor q3, q3, q11
+ vadd.u64 q15, q14, q14
+ vst1.64 {q14}, [r0,:128]!
+ vswp d15,d14
+ vshr.s64 q6, q15, #63
+ veor q15, q15, q7
+ vand q6, q6, q5
+ vld1.8 {q5}, [r7]!
+ subs r9, #0x10
+ bmi .Lxts_enc_6
+ veor q4, q4, q12
+ sub r9, #0x10
+ vst1.64 {q15}, [r0,:128] @ next round tweak
+
+ vld1.8 {q6}, [r7]!
+ veor q5, q5, q13
+#ifndef BSAES_ASM_EXTENDED_KEY
+ add r4, sp, #0x90 @ pass key schedule
+#else
+ add r4, r10, #248 @ pass key schedule
+#endif
+ veor q6, q6, q14
+ mov r5, r1 @ pass rounds
+ mov r0, sp
+
+ bl _bsaes_encrypt8
+
+ vld1.64 {q8-q9}, [r0,:128]!
+ vld1.64 {q10-q11}, [r0,:128]!
+ veor q0, q0, q8
+ vld1.64 {q12-q13}, [r0,:128]!
+ veor q1, q1, q9
+ veor q8, q4, q10
+ vst1.8 {q0-q1}, [r8]!
+ veor q9, q6, q11
+ vld1.64 {q14}, [r0,:128]!
+ veor q10, q3, q12
+ vst1.8 {q8-q9}, [r8]!
+ veor q11, q7, q13
+ veor q12, q2, q14
+ vst1.8 {q10-q11}, [r8]!
+ vst1.8 {q12}, [r8]!
+
+ vld1.64 {q8}, [r0,:128] @ next round tweak
+ b .Lxts_enc_done
+.align 4
+.Lxts_enc_6:
+ vst1.64 {q14}, [r0,:128] @ next round tweak
+
+ veor q4, q4, q12
+#ifndef BSAES_ASM_EXTENDED_KEY
+ add r4, sp, #0x90 @ pass key schedule
+#else
+ add r4, r10, #248 @ pass key schedule
+#endif
+ veor q5, q5, q13
+ mov r5, r1 @ pass rounds
+ mov r0, sp
+
+ bl _bsaes_encrypt8
+
+ vld1.64 {q8-q9}, [r0,:128]!
+ vld1.64 {q10-q11}, [r0,:128]!
+ veor q0, q0, q8
+ vld1.64 {q12-q13}, [r0,:128]!
+ veor q1, q1, q9
+ veor q8, q4, q10
+ vst1.8 {q0-q1}, [r8]!
+ veor q9, q6, q11
+ veor q10, q3, q12
+ vst1.8 {q8-q9}, [r8]!
+ veor q11, q7, q13
+ vst1.8 {q10-q11}, [r8]!
+
+ vld1.64 {q8}, [r0,:128] @ next round tweak
+ b .Lxts_enc_done
+
+@ put this in range for both ARM and Thumb mode adr instructions
+.align 5
+.Lxts_magic:
+ .quad 1, 0x87
+
+.align 5
+.Lxts_enc_5:
+ vst1.64 {q13}, [r0,:128] @ next round tweak
+
+ veor q3, q3, q11
+#ifndef BSAES_ASM_EXTENDED_KEY
+ add r4, sp, #0x90 @ pass key schedule
+#else
+ add r4, r10, #248 @ pass key schedule
+#endif
+ veor q4, q4, q12
+ mov r5, r1 @ pass rounds
+ mov r0, sp
+
+ bl _bsaes_encrypt8
+
+ vld1.64 {q8-q9}, [r0,:128]!
+ vld1.64 {q10-q11}, [r0,:128]!
+ veor q0, q0, q8
+ vld1.64 {q12}, [r0,:128]!
+ veor q1, q1, q9
+ veor q8, q4, q10
+ vst1.8 {q0-q1}, [r8]!
+ veor q9, q6, q11
+ veor q10, q3, q12
+ vst1.8 {q8-q9}, [r8]!
+ vst1.8 {q10}, [r8]!
+
+ vld1.64 {q8}, [r0,:128] @ next round tweak
+ b .Lxts_enc_done
+.align 4
+.Lxts_enc_4:
+ vst1.64 {q12}, [r0,:128] @ next round tweak
+
+ veor q2, q2, q10
+#ifndef BSAES_ASM_EXTENDED_KEY
+ add r4, sp, #0x90 @ pass key schedule
+#else
+ add r4, r10, #248 @ pass key schedule
+#endif
+ veor q3, q3, q11
+ mov r5, r1 @ pass rounds
+ mov r0, sp
+
+ bl _bsaes_encrypt8
+
+ vld1.64 {q8-q9}, [r0,:128]!
+ vld1.64 {q10-q11}, [r0,:128]!
+ veor q0, q0, q8
+ veor q1, q1, q9
+ veor q8, q4, q10
+ vst1.8 {q0-q1}, [r8]!
+ veor q9, q6, q11
+ vst1.8 {q8-q9}, [r8]!
+
+ vld1.64 {q8}, [r0,:128] @ next round tweak
+ b .Lxts_enc_done
+.align 4
+.Lxts_enc_3:
+ vst1.64 {q11}, [r0,:128] @ next round tweak
+
+ veor q1, q1, q9
+#ifndef BSAES_ASM_EXTENDED_KEY
+ add r4, sp, #0x90 @ pass key schedule
+#else
+ add r4, r10, #248 @ pass key schedule
+#endif
+ veor q2, q2, q10
+ mov r5, r1 @ pass rounds
+ mov r0, sp
+
+ bl _bsaes_encrypt8
+
+ vld1.64 {q8-q9}, [r0,:128]!
+ vld1.64 {q10}, [r0,:128]!
+ veor q0, q0, q8
+ veor q1, q1, q9
+ veor q8, q4, q10
+ vst1.8 {q0-q1}, [r8]!
+ vst1.8 {q8}, [r8]!
+
+ vld1.64 {q8}, [r0,:128] @ next round tweak
+ b .Lxts_enc_done
+.align 4
+.Lxts_enc_2:
+ vst1.64 {q10}, [r0,:128] @ next round tweak
+
+ veor q0, q0, q8
+#ifndef BSAES_ASM_EXTENDED_KEY
+ add r4, sp, #0x90 @ pass key schedule
+#else
+ add r4, r10, #248 @ pass key schedule
+#endif
+ veor q1, q1, q9
+ mov r5, r1 @ pass rounds
+ mov r0, sp
+
+ bl _bsaes_encrypt8
+
+ vld1.64 {q8-q9}, [r0,:128]!
+ veor q0, q0, q8
+ veor q1, q1, q9
+ vst1.8 {q0-q1}, [r8]!
+
+ vld1.64 {q8}, [r0,:128] @ next round tweak
+ b .Lxts_enc_done
+.align 4
+.Lxts_enc_1:
+ mov r0, sp
+ veor q0, q8
+ mov r1, sp
+ vst1.8 {q0}, [sp,:128]
+ mov r2, r10
+ mov r4, r3 @ preserve fp
+
+ bl AES_encrypt
+
+ vld1.8 {q0}, [sp,:128]
+ veor q0, q0, q8
+ vst1.8 {q0}, [r8]!
+ mov r3, r4
+
+ vmov q8, q9 @ next round tweak
+
+.Lxts_enc_done:
+#ifndef XTS_CHAIN_TWEAK
+ adds r9, #0x10
+ beq .Lxts_enc_ret
+ sub r6, r8, #0x10
+
+.Lxts_enc_steal:
+ ldrb r0, [r7], #1
+ ldrb r1, [r8, #-0x10]
+ strb r0, [r8, #-0x10]
+ strb r1, [r8], #1
+
+ subs r9, #1
+ bhi .Lxts_enc_steal
+
+ vld1.8 {q0}, [r6]
+ mov r0, sp
+ veor q0, q0, q8
+ mov r1, sp
+ vst1.8 {q0}, [sp,:128]
+ mov r2, r10
+ mov r4, r3 @ preserve fp
+
+ bl AES_encrypt
+
+ vld1.8 {q0}, [sp,:128]
+ veor q0, q0, q8
+ vst1.8 {q0}, [r6]
+ mov r3, r4
+#endif
+
+.Lxts_enc_ret:
+ bic r0, r3, #0xf
+ vmov.i32 q0, #0
+ vmov.i32 q1, #0
+#ifdef XTS_CHAIN_TWEAK
+ ldr r1, [r3, #0x20+VFP_ABI_FRAME] @ chain tweak
+#endif
+.Lxts_enc_bzero: @ wipe key schedule [if any]
+ vstmia sp!, {q0-q1}
+ cmp sp, r0
+ bne .Lxts_enc_bzero
+
+ mov sp, r3
+#ifdef XTS_CHAIN_TWEAK
+ vst1.8 {q8}, [r1]
+#endif
+ VFP_ABI_POP
+ ldmia sp!, {r4-r10, pc} @ return
+
+.size bsaes_xts_encrypt,.-bsaes_xts_encrypt
+
+.globl bsaes_xts_decrypt
+.hidden bsaes_xts_decrypt
+.type bsaes_xts_decrypt,%function
+.align 4
+bsaes_xts_decrypt:
+ mov ip, sp
+ stmdb sp!, {r4-r10, lr} @ 0x20
+ VFP_ABI_PUSH
+ mov r6, sp @ future r3
+
+ mov r7, r0
+ mov r8, r1
+ mov r9, r2
+ mov r10, r3
+
+ sub r0, sp, #0x10 @ 0x10
+ bic r0, #0xf @ align at 16 bytes
+ mov sp, r0
+
+#ifdef XTS_CHAIN_TWEAK
+ ldr r0, [ip] @ pointer to input tweak
+#else
+ @ generate initial tweak
+ ldr r0, [ip, #4] @ iv[]
+ mov r1, sp
+ ldr r2, [ip, #0] @ key2
+ bl AES_encrypt
+ mov r0, sp @ pointer to initial tweak
+#endif
+
+ ldr r1, [r10, #240] @ get # of rounds
+ mov r3, r6
+#ifndef BSAES_ASM_EXTENDED_KEY
+ @ allocate the key schedule on the stack
+ sub r12, sp, r1, lsl#7 @ 128 bytes per inner round key
+ @ add r12, #96 @ size of bit-sliced key schedule
+ sub r12, #48 @ place for tweak[9]
+
+ @ populate the key schedule
+ mov r4, r10 @ pass key
+ mov r5, r1 @ pass # of rounds
+ mov sp, r12
+ add r12, #0x90 @ pass key schedule
+ bl _bsaes_key_convert
+ add r4, sp, #0x90
+ vldmia r4, {q6}
+ vstmia r12, {q15} @ save last round key
+ veor q7, q7, q6 @ fix up round 0 key
+ vstmia r4, {q7}
+#else
+ ldr r12, [r10, #244]
+ eors r12, #1
+ beq 0f
+
+ str r12, [r10, #244]
+ mov r4, r10 @ pass key
+ mov r5, r1 @ pass # of rounds
+ add r12, r10, #248 @ pass key schedule
+ bl _bsaes_key_convert
+ add r4, r10, #248
+ vldmia r4, {q6}
+ vstmia r12, {q15} @ save last round key
+ veor q7, q7, q6 @ fix up round 0 key
+ vstmia r4, {q7}
+
+.align 2
+0: sub sp, #0x90 @ place for tweak[9]
+#endif
+ vld1.8 {q8}, [r0] @ initial tweak
+ adr r2, .Lxts_magic
+
+ tst r9, #0xf @ if not multiple of 16
+ it ne @ Thumb2 thing, sanity check in ARM
+ subne r9, #0x10 @ subtract another 16 bytes
+ subs r9, #0x80
+
+ blo .Lxts_dec_short
+ b .Lxts_dec_loop
+
+.align 4
+.Lxts_dec_loop:
+ vldmia r2, {q5} @ load XTS magic
+ vshr.s64 q6, q8, #63
+ mov r0, sp
+ vand q6, q6, q5
+ vadd.u64 q9, q8, q8
+ vst1.64 {q8}, [r0,:128]!
+ vswp d13,d12
+ vshr.s64 q7, q9, #63
+ veor q9, q9, q6
+ vand q7, q7, q5
+ vadd.u64 q10, q9, q9
+ vst1.64 {q9}, [r0,:128]!
+ vswp d15,d14
+ vshr.s64 q6, q10, #63
+ veor q10, q10, q7
+ vand q6, q6, q5
+ vld1.8 {q0}, [r7]!
+ vadd.u64 q11, q10, q10
+ vst1.64 {q10}, [r0,:128]!
+ vswp d13,d12
+ vshr.s64 q7, q11, #63
+ veor q11, q11, q6
+ vand q7, q7, q5
+ vld1.8 {q1}, [r7]!
+ veor q0, q0, q8
+ vadd.u64 q12, q11, q11
+ vst1.64 {q11}, [r0,:128]!
+ vswp d15,d14
+ vshr.s64 q6, q12, #63
+ veor q12, q12, q7
+ vand q6, q6, q5
+ vld1.8 {q2}, [r7]!
+ veor q1, q1, q9
+ vadd.u64 q13, q12, q12
+ vst1.64 {q12}, [r0,:128]!
+ vswp d13,d12
+ vshr.s64 q7, q13, #63
+ veor q13, q13, q6
+ vand q7, q7, q5
+ vld1.8 {q3}, [r7]!
+ veor q2, q2, q10
+ vadd.u64 q14, q13, q13
+ vst1.64 {q13}, [r0,:128]!
+ vswp d15,d14
+ vshr.s64 q6, q14, #63
+ veor q14, q14, q7
+ vand q6, q6, q5
+ vld1.8 {q4}, [r7]!
+ veor q3, q3, q11
+ vadd.u64 q15, q14, q14
+ vst1.64 {q14}, [r0,:128]!
+ vswp d13,d12
+ vshr.s64 q7, q15, #63
+ veor q15, q15, q6
+ vand q7, q7, q5
+ vld1.8 {q5}, [r7]!
+ veor q4, q4, q12
+ vadd.u64 q8, q15, q15
+ vst1.64 {q15}, [r0,:128]!
+ vswp d15,d14
+ veor q8, q8, q7
+ vst1.64 {q8}, [r0,:128] @ next round tweak
+
+ vld1.8 {q6-q7}, [r7]!
+ veor q5, q5, q13
+#ifndef BSAES_ASM_EXTENDED_KEY
+ add r4, sp, #0x90 @ pass key schedule
+#else
+ add r4, r10, #248 @ pass key schedule
+#endif
+ veor q6, q6, q14
+ mov r5, r1 @ pass rounds
+ veor q7, q7, q15
+ mov r0, sp
+
+ bl _bsaes_decrypt8
+
+ vld1.64 {q8-q9}, [r0,:128]!
+ vld1.64 {q10-q11}, [r0,:128]!
+ veor q0, q0, q8
+ vld1.64 {q12-q13}, [r0,:128]!
+ veor q1, q1, q9
+ veor q8, q6, q10
+ vst1.8 {q0-q1}, [r8]!
+ veor q9, q4, q11
+ vld1.64 {q14-q15}, [r0,:128]!
+ veor q10, q2, q12
+ vst1.8 {q8-q9}, [r8]!
+ veor q11, q7, q13
+ veor q12, q3, q14
+ vst1.8 {q10-q11}, [r8]!
+ veor q13, q5, q15
+ vst1.8 {q12-q13}, [r8]!
+
+ vld1.64 {q8}, [r0,:128] @ next round tweak
+
+ subs r9, #0x80
+ bpl .Lxts_dec_loop
+
+.Lxts_dec_short:
+ adds r9, #0x70
+ bmi .Lxts_dec_done
+
+ vldmia r2, {q5} @ load XTS magic
+ vshr.s64 q7, q8, #63
+ mov r0, sp
+ vand q7, q7, q5
+ vadd.u64 q9, q8, q8
+ vst1.64 {q8}, [r0,:128]!
+ vswp d15,d14
+ vshr.s64 q6, q9, #63
+ veor q9, q9, q7
+ vand q6, q6, q5
+ vadd.u64 q10, q9, q9
+ vst1.64 {q9}, [r0,:128]!
+ vswp d13,d12
+ vshr.s64 q7, q10, #63
+ veor q10, q10, q6
+ vand q7, q7, q5
+ vld1.8 {q0}, [r7]!
+ subs r9, #0x10
+ bmi .Lxts_dec_1
+ vadd.u64 q11, q10, q10
+ vst1.64 {q10}, [r0,:128]!
+ vswp d15,d14
+ vshr.s64 q6, q11, #63
+ veor q11, q11, q7
+ vand q6, q6, q5
+ vld1.8 {q1}, [r7]!
+ subs r9, #0x10
+ bmi .Lxts_dec_2
+ veor q0, q0, q8
+ vadd.u64 q12, q11, q11
+ vst1.64 {q11}, [r0,:128]!
+ vswp d13,d12
+ vshr.s64 q7, q12, #63
+ veor q12, q12, q6
+ vand q7, q7, q5
+ vld1.8 {q2}, [r7]!
+ subs r9, #0x10
+ bmi .Lxts_dec_3
+ veor q1, q1, q9
+ vadd.u64 q13, q12, q12
+ vst1.64 {q12}, [r0,:128]!
+ vswp d15,d14
+ vshr.s64 q6, q13, #63
+ veor q13, q13, q7
+ vand q6, q6, q5
+ vld1.8 {q3}, [r7]!
+ subs r9, #0x10
+ bmi .Lxts_dec_4
+ veor q2, q2, q10
+ vadd.u64 q14, q13, q13
+ vst1.64 {q13}, [r0,:128]!
+ vswp d13,d12
+ vshr.s64 q7, q14, #63
+ veor q14, q14, q6
+ vand q7, q7, q5
+ vld1.8 {q4}, [r7]!
+ subs r9, #0x10
+ bmi .Lxts_dec_5
+ veor q3, q3, q11
+ vadd.u64 q15, q14, q14
+ vst1.64 {q14}, [r0,:128]!
+ vswp d15,d14
+ vshr.s64 q6, q15, #63
+ veor q15, q15, q7
+ vand q6, q6, q5
+ vld1.8 {q5}, [r7]!
+ subs r9, #0x10
+ bmi .Lxts_dec_6
+ veor q4, q4, q12
+ sub r9, #0x10
+ vst1.64 {q15}, [r0,:128] @ next round tweak
+
+ vld1.8 {q6}, [r7]!
+ veor q5, q5, q13
+#ifndef BSAES_ASM_EXTENDED_KEY
+ add r4, sp, #0x90 @ pass key schedule
+#else
+ add r4, r10, #248 @ pass key schedule
+#endif
+ veor q6, q6, q14
+ mov r5, r1 @ pass rounds
+ mov r0, sp
+
+ bl _bsaes_decrypt8
+
+ vld1.64 {q8-q9}, [r0,:128]!
+ vld1.64 {q10-q11}, [r0,:128]!
+ veor q0, q0, q8
+ vld1.64 {q12-q13}, [r0,:128]!
+ veor q1, q1, q9
+ veor q8, q6, q10
+ vst1.8 {q0-q1}, [r8]!
+ veor q9, q4, q11
+ vld1.64 {q14}, [r0,:128]!
+ veor q10, q2, q12
+ vst1.8 {q8-q9}, [r8]!
+ veor q11, q7, q13
+ veor q12, q3, q14
+ vst1.8 {q10-q11}, [r8]!
+ vst1.8 {q12}, [r8]!
+
+ vld1.64 {q8}, [r0,:128] @ next round tweak
+ b .Lxts_dec_done
+.align 4
+.Lxts_dec_6:
+ vst1.64 {q14}, [r0,:128] @ next round tweak
+
+ veor q4, q4, q12
+#ifndef BSAES_ASM_EXTENDED_KEY
+ add r4, sp, #0x90 @ pass key schedule
+#else
+ add r4, r10, #248 @ pass key schedule
+#endif
+ veor q5, q5, q13
+ mov r5, r1 @ pass rounds
+ mov r0, sp
+
+ bl _bsaes_decrypt8
+
+ vld1.64 {q8-q9}, [r0,:128]!
+ vld1.64 {q10-q11}, [r0,:128]!
+ veor q0, q0, q8
+ vld1.64 {q12-q13}, [r0,:128]!
+ veor q1, q1, q9
+ veor q8, q6, q10
+ vst1.8 {q0-q1}, [r8]!
+ veor q9, q4, q11
+ veor q10, q2, q12
+ vst1.8 {q8-q9}, [r8]!
+ veor q11, q7, q13
+ vst1.8 {q10-q11}, [r8]!
+
+ vld1.64 {q8}, [r0,:128] @ next round tweak
+ b .Lxts_dec_done
+.align 4
+.Lxts_dec_5:
+ vst1.64 {q13}, [r0,:128] @ next round tweak
+
+ veor q3, q3, q11
+#ifndef BSAES_ASM_EXTENDED_KEY
+ add r4, sp, #0x90 @ pass key schedule
+#else
+ add r4, r10, #248 @ pass key schedule
+#endif
+ veor q4, q4, q12
+ mov r5, r1 @ pass rounds
+ mov r0, sp
+
+ bl _bsaes_decrypt8
+
+ vld1.64 {q8-q9}, [r0,:128]!
+ vld1.64 {q10-q11}, [r0,:128]!
+ veor q0, q0, q8
+ vld1.64 {q12}, [r0,:128]!
+ veor q1, q1, q9
+ veor q8, q6, q10
+ vst1.8 {q0-q1}, [r8]!
+ veor q9, q4, q11
+ veor q10, q2, q12
+ vst1.8 {q8-q9}, [r8]!
+ vst1.8 {q10}, [r8]!
+
+ vld1.64 {q8}, [r0,:128] @ next round tweak
+ b .Lxts_dec_done
+.align 4
+.Lxts_dec_4:
+ vst1.64 {q12}, [r0,:128] @ next round tweak
+
+ veor q2, q2, q10
+#ifndef BSAES_ASM_EXTENDED_KEY
+ add r4, sp, #0x90 @ pass key schedule
+#else
+ add r4, r10, #248 @ pass key schedule
+#endif
+ veor q3, q3, q11
+ mov r5, r1 @ pass rounds
+ mov r0, sp
+
+ bl _bsaes_decrypt8
+
+ vld1.64 {q8-q9}, [r0,:128]!
+ vld1.64 {q10-q11}, [r0,:128]!
+ veor q0, q0, q8
+ veor q1, q1, q9
+ veor q8, q6, q10
+ vst1.8 {q0-q1}, [r8]!
+ veor q9, q4, q11
+ vst1.8 {q8-q9}, [r8]!
+
+ vld1.64 {q8}, [r0,:128] @ next round tweak
+ b .Lxts_dec_done
+.align 4
+.Lxts_dec_3:
+ vst1.64 {q11}, [r0,:128] @ next round tweak
+
+ veor q1, q1, q9
+#ifndef BSAES_ASM_EXTENDED_KEY
+ add r4, sp, #0x90 @ pass key schedule
+#else
+ add r4, r10, #248 @ pass key schedule
+#endif
+ veor q2, q2, q10
+ mov r5, r1 @ pass rounds
+ mov r0, sp
+
+ bl _bsaes_decrypt8
+
+ vld1.64 {q8-q9}, [r0,:128]!
+ vld1.64 {q10}, [r0,:128]!
+ veor q0, q0, q8
+ veor q1, q1, q9
+ veor q8, q6, q10
+ vst1.8 {q0-q1}, [r8]!
+ vst1.8 {q8}, [r8]!
+
+ vld1.64 {q8}, [r0,:128] @ next round tweak
+ b .Lxts_dec_done
+.align 4
+.Lxts_dec_2:
+ vst1.64 {q10}, [r0,:128] @ next round tweak
+
+ veor q0, q0, q8
+#ifndef BSAES_ASM_EXTENDED_KEY
+ add r4, sp, #0x90 @ pass key schedule
+#else
+ add r4, r10, #248 @ pass key schedule
+#endif
+ veor q1, q1, q9
+ mov r5, r1 @ pass rounds
+ mov r0, sp
+
+ bl _bsaes_decrypt8
+
+ vld1.64 {q8-q9}, [r0,:128]!
+ veor q0, q0, q8
+ veor q1, q1, q9
+ vst1.8 {q0-q1}, [r8]!
+
+ vld1.64 {q8}, [r0,:128] @ next round tweak
+ b .Lxts_dec_done
+.align 4
+.Lxts_dec_1:
+ mov r0, sp
+ veor q0, q8
+ mov r1, sp
+ vst1.8 {q0}, [sp,:128]
+ mov r2, r10
+ mov r4, r3 @ preserve fp
+ mov r5, r2 @ preserve magic
+
+ bl AES_decrypt
+
+ vld1.8 {q0}, [sp,:128]
+ veor q0, q0, q8
+ vst1.8 {q0}, [r8]!
+ mov r3, r4
+ mov r2, r5
+
+ vmov q8, q9 @ next round tweak
+
+.Lxts_dec_done:
+#ifndef XTS_CHAIN_TWEAK
+ adds r9, #0x10
+ beq .Lxts_dec_ret
+
+ @ calculate one round of extra tweak for the stolen ciphertext
+ vldmia r2, {q5}
+ vshr.s64 q6, q8, #63
+ vand q6, q6, q5
+ vadd.u64 q9, q8, q8
+ vswp d13,d12
+ veor q9, q9, q6
+
+ @ perform the final decryption with the last tweak value
+ vld1.8 {q0}, [r7]!
+ mov r0, sp
+ veor q0, q0, q9
+ mov r1, sp
+ vst1.8 {q0}, [sp,:128]
+ mov r2, r10
+ mov r4, r3 @ preserve fp
+
+ bl AES_decrypt
+
+ vld1.8 {q0}, [sp,:128]
+ veor q0, q0, q9
+ vst1.8 {q0}, [r8]
+
+ mov r6, r8
+.Lxts_dec_steal:
+ ldrb r1, [r8]
+ ldrb r0, [r7], #1
+ strb r1, [r8, #0x10]
+ strb r0, [r8], #1
+
+ subs r9, #1
+ bhi .Lxts_dec_steal
+
+ vld1.8 {q0}, [r6]
+ mov r0, sp
+ veor q0, q8
+ mov r1, sp
+ vst1.8 {q0}, [sp,:128]
+ mov r2, r10
+
+ bl AES_decrypt
+
+ vld1.8 {q0}, [sp,:128]
+ veor q0, q0, q8
+ vst1.8 {q0}, [r6]
+ mov r3, r4
+#endif
+
+.Lxts_dec_ret:
+ bic r0, r3, #0xf
+ vmov.i32 q0, #0
+ vmov.i32 q1, #0
+#ifdef XTS_CHAIN_TWEAK
+ ldr r1, [r3, #0x20+VFP_ABI_FRAME] @ chain tweak
+#endif
+.Lxts_dec_bzero: @ wipe key schedule [if any]
+ vstmia sp!, {q0-q1}
+ cmp sp, r0
+ bne .Lxts_dec_bzero
+
+ mov sp, r3
+#ifdef XTS_CHAIN_TWEAK
+ vst1.8 {q8}, [r1]
+#endif
+ VFP_ABI_POP
+ ldmia sp!, {r4-r10, pc} @ return
+
+.size bsaes_xts_decrypt,.-bsaes_xts_decrypt
+#endif
+#endif
diff --git a/linux-arm/crypto/bn/armv4-mont.S b/linux-arm/crypto/bn/armv4-mont.S
new file mode 100644
index 0000000..fa30dab
--- /dev/null
+++ b/linux-arm/crypto/bn/armv4-mont.S
@@ -0,0 +1,575 @@
+#include "arm_arch.h"
+
+.text
+.code 32
+
+#if __ARM_ARCH__>=7
+.align 5
+.LOPENSSL_armcap:
+.word OPENSSL_armcap_P-bn_mul_mont
+#endif
+
+.global bn_mul_mont
+.hidden bn_mul_mont
+.type bn_mul_mont,%function
+
+.align 5
+bn_mul_mont:
+ ldr ip,[sp,#4] @ load num
+ stmdb sp!,{r0,r2} @ sp points at argument block
+#if __ARM_ARCH__>=7
+ tst ip,#7
+ bne .Lialu
+ adr r0,bn_mul_mont
+ ldr r2,.LOPENSSL_armcap
+ ldr r0,[r0,r2]
+ tst r0,#1 @ NEON available?
+ ldmia sp, {r0,r2}
+ beq .Lialu
+ add sp,sp,#8
+ b bn_mul8x_mont_neon
+.align 4
+.Lialu:
+#endif
+ cmp ip,#2
+ mov r0,ip @ load num
+ 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
+#if __ARM_ARCH__>=7
+.fpu neon
+
+.type bn_mul8x_mont_neon,%function
+.align 5
+bn_mul8x_mont_neon:
+ mov ip,sp
+ stmdb sp!,{r4-r11}
+ vstmdb sp!,{d8-d15} @ ABI specification says so
+ ldmia ip,{r4-r5} @ load rest of parameter block
+
+ sub r7,sp,#16
+ vld1.32 {d28[0]}, [r2,:32]!
+ sub r7,r7,r5,lsl#4
+ vld1.32 {d0-d3}, [r1]! @ can't specify :32 :-(
+ and r7,r7,#-64
+ vld1.32 {d30[0]}, [r4,:32]
+ mov sp,r7 @ alloca
+ veor d8,d8,d8
+ subs r8,r5,#8
+ vzip.16 d28,d8
+
+ vmull.u32 q6,d28,d0[0]
+ vmull.u32 q7,d28,d0[1]
+ vmull.u32 q8,d28,d1[0]
+ vshl.i64 d10,d13,#16
+ vmull.u32 q9,d28,d1[1]
+
+ vadd.u64 d10,d10,d12
+ veor d8,d8,d8
+ vmul.u32 d29,d10,d30
+
+ vmull.u32 q10,d28,d2[0]
+ vld1.32 {d4-d7}, [r3]!
+ vmull.u32 q11,d28,d2[1]
+ vmull.u32 q12,d28,d3[0]
+ vzip.16 d29,d8
+ vmull.u32 q13,d28,d3[1]
+
+ bne .LNEON_1st
+
+ @ special case for num=8, everything is in register bank...
+
+ vmlal.u32 q6,d29,d4[0]
+ sub r9,r5,#1
+ vmlal.u32 q7,d29,d4[1]
+ vmlal.u32 q8,d29,d5[0]
+ vmlal.u32 q9,d29,d5[1]
+
+ vmlal.u32 q10,d29,d6[0]
+ vmov q5,q6
+ vmlal.u32 q11,d29,d6[1]
+ vmov q6,q7
+ vmlal.u32 q12,d29,d7[0]
+ vmov q7,q8
+ vmlal.u32 q13,d29,d7[1]
+ vmov q8,q9
+ vmov q9,q10
+ vshr.u64 d10,d10,#16
+ vmov q10,q11
+ vmov q11,q12
+ vadd.u64 d10,d10,d11
+ vmov q12,q13
+ veor q13,q13
+ vshr.u64 d10,d10,#16
+
+ b .LNEON_outer8
+
+.align 4
+.LNEON_outer8:
+ vld1.32 {d28[0]}, [r2,:32]!
+ veor d8,d8,d8
+ vzip.16 d28,d8
+ vadd.u64 d12,d12,d10
+
+ vmlal.u32 q6,d28,d0[0]
+ vmlal.u32 q7,d28,d0[1]
+ vmlal.u32 q8,d28,d1[0]
+ vshl.i64 d10,d13,#16
+ vmlal.u32 q9,d28,d1[1]
+
+ vadd.u64 d10,d10,d12
+ veor d8,d8,d8
+ subs r9,r9,#1
+ vmul.u32 d29,d10,d30
+
+ vmlal.u32 q10,d28,d2[0]
+ vmlal.u32 q11,d28,d2[1]
+ vmlal.u32 q12,d28,d3[0]
+ vzip.16 d29,d8
+ vmlal.u32 q13,d28,d3[1]
+
+ vmlal.u32 q6,d29,d4[0]
+ vmlal.u32 q7,d29,d4[1]
+ vmlal.u32 q8,d29,d5[0]
+ vmlal.u32 q9,d29,d5[1]
+
+ vmlal.u32 q10,d29,d6[0]
+ vmov q5,q6
+ vmlal.u32 q11,d29,d6[1]
+ vmov q6,q7
+ vmlal.u32 q12,d29,d7[0]
+ vmov q7,q8
+ vmlal.u32 q13,d29,d7[1]
+ vmov q8,q9
+ vmov q9,q10
+ vshr.u64 d10,d10,#16
+ vmov q10,q11
+ vmov q11,q12
+ vadd.u64 d10,d10,d11
+ vmov q12,q13
+ veor q13,q13
+ vshr.u64 d10,d10,#16
+
+ bne .LNEON_outer8
+
+ vadd.u64 d12,d12,d10
+ mov r7,sp
+ vshr.u64 d10,d12,#16
+ mov r8,r5
+ vadd.u64 d13,d13,d10
+ add r6,sp,#16
+ vshr.u64 d10,d13,#16
+ vzip.16 d12,d13
+
+ b .LNEON_tail2
+
+.align 4
+.LNEON_1st:
+ vmlal.u32 q6,d29,d4[0]
+ vld1.32 {d0-d3}, [r1]!
+ vmlal.u32 q7,d29,d4[1]
+ subs r8,r8,#8
+ vmlal.u32 q8,d29,d5[0]
+ vmlal.u32 q9,d29,d5[1]
+
+ vmlal.u32 q10,d29,d6[0]
+ vld1.32 {d4-d5}, [r3]!
+ vmlal.u32 q11,d29,d6[1]
+ vst1.64 {q6-q7}, [r7,:256]!
+ vmlal.u32 q12,d29,d7[0]
+ vmlal.u32 q13,d29,d7[1]
+ vst1.64 {q8-q9}, [r7,:256]!
+
+ vmull.u32 q6,d28,d0[0]
+ vld1.32 {d6-d7}, [r3]!
+ vmull.u32 q7,d28,d0[1]
+ vst1.64 {q10-q11}, [r7,:256]!
+ vmull.u32 q8,d28,d1[0]
+ vmull.u32 q9,d28,d1[1]
+ vst1.64 {q12-q13}, [r7,:256]!
+
+ vmull.u32 q10,d28,d2[0]
+ vmull.u32 q11,d28,d2[1]
+ vmull.u32 q12,d28,d3[0]
+ vmull.u32 q13,d28,d3[1]
+
+ bne .LNEON_1st
+
+ vmlal.u32 q6,d29,d4[0]
+ add r6,sp,#16
+ vmlal.u32 q7,d29,d4[1]
+ sub r1,r1,r5,lsl#2 @ rewind r1
+ vmlal.u32 q8,d29,d5[0]
+ vld1.64 {q5}, [sp,:128]
+ vmlal.u32 q9,d29,d5[1]
+ sub r9,r5,#1
+
+ vmlal.u32 q10,d29,d6[0]
+ vst1.64 {q6-q7}, [r7,:256]!
+ vmlal.u32 q11,d29,d6[1]
+ vshr.u64 d10,d10,#16
+ vld1.64 {q6}, [r6, :128]!
+ vmlal.u32 q12,d29,d7[0]
+ vst1.64 {q8-q9}, [r7,:256]!
+ vmlal.u32 q13,d29,d7[1]
+
+ vst1.64 {q10-q11}, [r7,:256]!
+ vadd.u64 d10,d10,d11
+ veor q4,q4,q4
+ vst1.64 {q12-q13}, [r7,:256]!
+ vld1.64 {q7-q8}, [r6, :256]!
+ vst1.64 {q4}, [r7,:128]
+ vshr.u64 d10,d10,#16
+
+ b .LNEON_outer
+
+.align 4
+.LNEON_outer:
+ vld1.32 {d28[0]}, [r2,:32]!
+ sub r3,r3,r5,lsl#2 @ rewind r3
+ vld1.32 {d0-d3}, [r1]!
+ veor d8,d8,d8
+ mov r7,sp
+ vzip.16 d28,d8
+ sub r8,r5,#8
+ vadd.u64 d12,d12,d10
+
+ vmlal.u32 q6,d28,d0[0]
+ vld1.64 {q9-q10},[r6,:256]!
+ vmlal.u32 q7,d28,d0[1]
+ vmlal.u32 q8,d28,d1[0]
+ vld1.64 {q11-q12},[r6,:256]!
+ vmlal.u32 q9,d28,d1[1]
+
+ vshl.i64 d10,d13,#16
+ veor d8,d8,d8
+ vadd.u64 d10,d10,d12
+ vld1.64 {q13},[r6,:128]!
+ vmul.u32 d29,d10,d30
+
+ vmlal.u32 q10,d28,d2[0]
+ vld1.32 {d4-d7}, [r3]!
+ vmlal.u32 q11,d28,d2[1]
+ vmlal.u32 q12,d28,d3[0]
+ vzip.16 d29,d8
+ vmlal.u32 q13,d28,d3[1]
+
+.LNEON_inner:
+ vmlal.u32 q6,d29,d4[0]
+ vld1.32 {d0-d3}, [r1]!
+ vmlal.u32 q7,d29,d4[1]
+ subs r8,r8,#8
+ vmlal.u32 q8,d29,d5[0]
+ vmlal.u32 q9,d29,d5[1]
+ vst1.64 {q6-q7}, [r7,:256]!
+
+ vmlal.u32 q10,d29,d6[0]
+ vld1.64 {q6}, [r6, :128]!
+ vmlal.u32 q11,d29,d6[1]
+ vst1.64 {q8-q9}, [r7,:256]!
+ vmlal.u32 q12,d29,d7[0]
+ vld1.64 {q7-q8}, [r6, :256]!
+ vmlal.u32 q13,d29,d7[1]
+ vst1.64 {q10-q11}, [r7,:256]!
+
+ vmlal.u32 q6,d28,d0[0]
+ vld1.64 {q9-q10}, [r6, :256]!
+ vmlal.u32 q7,d28,d0[1]
+ vst1.64 {q12-q13}, [r7,:256]!
+ vmlal.u32 q8,d28,d1[0]
+ vld1.64 {q11-q12}, [r6, :256]!
+ vmlal.u32 q9,d28,d1[1]
+ vld1.32 {d4-d7}, [r3]!
+
+ vmlal.u32 q10,d28,d2[0]
+ vld1.64 {q13}, [r6, :128]!
+ vmlal.u32 q11,d28,d2[1]
+ vmlal.u32 q12,d28,d3[0]
+ vmlal.u32 q13,d28,d3[1]
+
+ bne .LNEON_inner
+
+ vmlal.u32 q6,d29,d4[0]
+ add r6,sp,#16
+ vmlal.u32 q7,d29,d4[1]
+ sub r1,r1,r5,lsl#2 @ rewind r1
+ vmlal.u32 q8,d29,d5[0]
+ vld1.64 {q5}, [sp,:128]
+ vmlal.u32 q9,d29,d5[1]
+ subs r9,r9,#1
+
+ vmlal.u32 q10,d29,d6[0]
+ vst1.64 {q6-q7}, [r7,:256]!
+ vmlal.u32 q11,d29,d6[1]
+ vld1.64 {q6}, [r6, :128]!
+ vshr.u64 d10,d10,#16
+ vst1.64 {q8-q9}, [r7,:256]!
+ vmlal.u32 q12,d29,d7[0]
+ vld1.64 {q7-q8}, [r6, :256]!
+ vmlal.u32 q13,d29,d7[1]
+
+ vst1.64 {q10-q11}, [r7,:256]!
+ vadd.u64 d10,d10,d11
+ vst1.64 {q12-q13}, [r7,:256]!
+ vshr.u64 d10,d10,#16
+
+ bne .LNEON_outer
+
+ mov r7,sp
+ mov r8,r5
+
+.LNEON_tail:
+ vadd.u64 d12,d12,d10
+ vld1.64 {q9-q10}, [r6, :256]!
+ vshr.u64 d10,d12,#16
+ vadd.u64 d13,d13,d10
+ vld1.64 {q11-q12}, [r6, :256]!
+ vshr.u64 d10,d13,#16
+ vld1.64 {q13}, [r6, :128]!
+ vzip.16 d12,d13
+
+.LNEON_tail2:
+ vadd.u64 d14,d14,d10
+ vst1.32 {d12[0]}, [r7, :32]!
+ vshr.u64 d10,d14,#16
+ vadd.u64 d15,d15,d10
+ vshr.u64 d10,d15,#16
+ vzip.16 d14,d15
+
+ vadd.u64 d16,d16,d10
+ vst1.32 {d14[0]}, [r7, :32]!
+ vshr.u64 d10,d16,#16
+ vadd.u64 d17,d17,d10
+ vshr.u64 d10,d17,#16
+ vzip.16 d16,d17
+
+ vadd.u64 d18,d18,d10
+ vst1.32 {d16[0]}, [r7, :32]!
+ vshr.u64 d10,d18,#16
+ vadd.u64 d19,d19,d10
+ vshr.u64 d10,d19,#16
+ vzip.16 d18,d19
+
+ vadd.u64 d20,d20,d10
+ vst1.32 {d18[0]}, [r7, :32]!
+ vshr.u64 d10,d20,#16
+ vadd.u64 d21,d21,d10
+ vshr.u64 d10,d21,#16
+ vzip.16 d20,d21
+
+ vadd.u64 d22,d22,d10
+ vst1.32 {d20[0]}, [r7, :32]!
+ vshr.u64 d10,d22,#16
+ vadd.u64 d23,d23,d10
+ vshr.u64 d10,d23,#16
+ vzip.16 d22,d23
+
+ vadd.u64 d24,d24,d10
+ vst1.32 {d22[0]}, [r7, :32]!
+ vshr.u64 d10,d24,#16
+ vadd.u64 d25,d25,d10
+ vld1.64 {q6}, [r6, :128]!
+ vshr.u64 d10,d25,#16
+ vzip.16 d24,d25
+
+ vadd.u64 d26,d26,d10
+ vst1.32 {d24[0]}, [r7, :32]!
+ vshr.u64 d10,d26,#16
+ vadd.u64 d27,d27,d10
+ vld1.64 {q7-q8}, [r6, :256]!
+ vshr.u64 d10,d27,#16
+ vzip.16 d26,d27
+ subs r8,r8,#8
+ vst1.32 {d26[0]}, [r7, :32]!
+
+ bne .LNEON_tail
+
+ vst1.32 {d10[0]}, [r7, :32] @ top-most bit
+ sub r3,r3,r5,lsl#2 @ rewind r3
+ subs r1,sp,#0 @ clear carry flag
+ add r2,sp,r5,lsl#2
+
+.LNEON_sub:
+ ldmia r1!, {r4-r7}
+ ldmia r3!, {r8-r11}
+ sbcs r8, r4,r8
+ sbcs r9, r5,r9
+ sbcs r10,r6,r10
+ sbcs r11,r7,r11
+ teq r1,r2 @ preserves carry
+ stmia r0!, {r8-r11}
+ bne .LNEON_sub
+
+ ldr r10, [r1] @ load top-most bit
+ veor q0,q0,q0
+ sub r11,r2,sp @ this is num*4
+ veor q1,q1,q1
+ mov r1,sp
+ sub r0,r0,r11 @ rewind r0
+ mov r3,r2 @ second 3/4th of frame
+ sbcs r10,r10,#0 @ result is carry flag
+
+.LNEON_copy_n_zap:
+ ldmia r1!, {r4-r7}
+ ldmia r0, {r8-r11}
+ movcc r8, r4
+ vst1.64 {q0-q1}, [r3,:256]! @ wipe
+ movcc r9, r5
+ movcc r10,r6
+ vst1.64 {q0-q1}, [r3,:256]! @ wipe
+ movcc r11,r7
+ ldmia r1, {r4-r7}
+ stmia r0!, {r8-r11}
+ sub r1,r1,#16
+ ldmia r0, {r8-r11}
+ movcc r8, r4
+ vst1.64 {q0-q1}, [r1,:256]! @ wipe
+ movcc r9, r5
+ movcc r10,r6
+ vst1.64 {q0-q1}, [r3,:256]! @ wipe
+ movcc r11,r7
+ teq r1,r2 @ preserves carry
+ stmia r0!, {r8-r11}
+ bne .LNEON_copy_n_zap
+
+ sub sp,ip,#96
+ vldmia sp!,{d8-d15}
+ ldmia sp!,{r4-r11}
+ .word 0xe12fff1e
+.size bn_mul8x_mont_neon,.-bn_mul8x_mont_neon
+#endif
+.asciz "Montgomery multiplication for ARMv4/NEON, CRYPTOGAMS by <appro@openssl.org>"
+.align 2
+#if __ARM_ARCH__>=7
+.comm OPENSSL_armcap_P,4,4
+#endif
diff --git a/linux-arm/crypto/modes/ghash-armv4.S b/linux-arm/crypto/modes/ghash-armv4.S
new file mode 100644
index 0000000..8c81975
--- /dev/null
+++ b/linux-arm/crypto/modes/ghash-armv4.S
@@ -0,0 +1,532 @@
+#if defined(__arm__)
+#include "arm_arch.h"
+
+.syntax unified
+
+.text
+.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
+.hidden 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
+.hidden 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
+.fpu neon
+
+.global gcm_init_neon
+.hidden gcm_init_neon
+.type gcm_init_neon,%function
+.align 4
+gcm_init_neon:
+ vld1.64 d7,[r1,:64]! @ load H
+ vmov.i8 q8,#0xe1
+ vld1.64 d6,[r1,:64]
+ vshl.i64 d17,#57
+ vshr.u64 d16,#63 @ t0=0xc2....01
+ vdup.8 q9,d7[7]
+ vshr.u64 d26,d6,#63
+ vshr.s8 q9,#7 @ broadcast carry bit
+ vshl.i64 q3,q3,#1
+ vand q8,q8,q9
+ vorr d7,d26 @ H<<<=1
+ veor q3,q3,q8 @ twisted H
+ vstmia r0,{q3}
+
+ .word 0xe12fff1e
+.size gcm_init_neon,.-gcm_init_neon
+
+.global gcm_gmult_neon
+.hidden gcm_gmult_neon
+.type gcm_gmult_neon,%function
+.align 4
+gcm_gmult_neon:
+ vld1.64 d7,[r0,:64]! @ load Xi
+ vld1.64 d6,[r0,:64]!
+ vmov.i64 d29,#0x0000ffffffffffff
+ vldmia r1,{d26-d27} @ load twisted H
+ vmov.i64 d30,#0x00000000ffffffff
+#ifdef __ARMEL__
+ vrev64.8 q3,q3
+#endif
+ vmov.i64 d31,#0x000000000000ffff
+ veor d28,d26,d27 @ Karatsuba pre-processing
+ mov r3,#16
+ b .Lgmult_neon
+.size gcm_gmult_neon,.-gcm_gmult_neon
+
+.global gcm_ghash_neon
+.hidden gcm_ghash_neon
+.type gcm_ghash_neon,%function
+.align 4
+gcm_ghash_neon:
+ vld1.64 d1,[r0,:64]! @ load Xi
+ vld1.64 d0,[r0,:64]!
+ vmov.i64 d29,#0x0000ffffffffffff
+ vldmia r1,{d26-d27} @ load twisted H
+ vmov.i64 d30,#0x00000000ffffffff
+#ifdef __ARMEL__
+ vrev64.8 q0,q0
+#endif
+ vmov.i64 d31,#0x000000000000ffff
+ veor d28,d26,d27 @ Karatsuba pre-processing
+
+.Loop_neon:
+ vld1.64 d7,[r2]! @ load inp
+ vld1.64 d6,[r2]!
+#ifdef __ARMEL__
+ vrev64.8 q3,q3
+#endif
+ veor q3,q0 @ inp^=Xi
+.Lgmult_neon:
+ vext.8 d16, d26, d26, #1 @ A1
+ vmull.p8 q8, d16, d6 @ F = A1*B
+ vext.8 d0, d6, d6, #1 @ B1
+ vmull.p8 q0, d26, d0 @ E = A*B1
+ vext.8 d18, d26, d26, #2 @ A2
+ vmull.p8 q9, d18, d6 @ H = A2*B
+ vext.8 d22, d6, d6, #2 @ B2
+ vmull.p8 q11, d26, d22 @ G = A*B2
+ vext.8 d20, d26, d26, #3 @ A3
+ veor q8, q8, q0 @ L = E + F
+ vmull.p8 q10, d20, d6 @ J = A3*B
+ vext.8 d0, d6, d6, #3 @ B3
+ veor q9, q9, q11 @ M = G + H
+ vmull.p8 q0, d26, d0 @ I = A*B3
+ veor d16, d16, d17 @ t0 = (L) (P0 + P1) << 8
+ vand d17, d17, d29
+ vext.8 d22, d6, d6, #4 @ B4
+ veor d18, d18, d19 @ t1 = (M) (P2 + P3) << 16
+ vand d19, d19, d30
+ vmull.p8 q11, d26, d22 @ K = A*B4
+ veor q10, q10, q0 @ N = I + J
+ veor d16, d16, d17
+ veor d18, d18, d19
+ veor d20, d20, d21 @ t2 = (N) (P4 + P5) << 24
+ vand d21, d21, d31
+ vext.8 q8, q8, q8, #15
+ veor d22, d22, d23 @ t3 = (K) (P6 + P7) << 32
+ vmov.i64 d23, #0
+ vext.8 q9, q9, q9, #14
+ veor d20, d20, d21
+ vmull.p8 q0, d26, d6 @ D = A*B
+ vext.8 q11, q11, q11, #12
+ vext.8 q10, q10, q10, #13
+ veor q8, q8, q9
+ veor q10, q10, q11
+ veor q0, q0, q8
+ veor q0, q0, q10
+ veor d6,d6,d7 @ Karatsuba pre-processing
+ vext.8 d16, d28, d28, #1 @ A1
+ vmull.p8 q8, d16, d6 @ F = A1*B
+ vext.8 d2, d6, d6, #1 @ B1
+ vmull.p8 q1, d28, d2 @ E = A*B1
+ vext.8 d18, d28, d28, #2 @ A2
+ vmull.p8 q9, d18, d6 @ H = A2*B
+ vext.8 d22, d6, d6, #2 @ B2
+ vmull.p8 q11, d28, d22 @ G = A*B2
+ vext.8 d20, d28, d28, #3 @ A3
+ veor q8, q8, q1 @ L = E + F
+ vmull.p8 q10, d20, d6 @ J = A3*B
+ vext.8 d2, d6, d6, #3 @ B3
+ veor q9, q9, q11 @ M = G + H
+ vmull.p8 q1, d28, d2 @ I = A*B3
+ veor d16, d16, d17 @ t0 = (L) (P0 + P1) << 8
+ vand d17, d17, d29
+ vext.8 d22, d6, d6, #4 @ B4
+ veor d18, d18, d19 @ t1 = (M) (P2 + P3) << 16
+ vand d19, d19, d30
+ vmull.p8 q11, d28, d22 @ K = A*B4
+ veor q10, q10, q1 @ N = I + J
+ veor d16, d16, d17
+ veor d18, d18, d19
+ veor d20, d20, d21 @ t2 = (N) (P4 + P5) << 24
+ vand d21, d21, d31
+ vext.8 q8, q8, q8, #15
+ veor d22, d22, d23 @ t3 = (K) (P6 + P7) << 32
+ vmov.i64 d23, #0
+ vext.8 q9, q9, q9, #14
+ veor d20, d20, d21
+ vmull.p8 q1, d28, d6 @ D = A*B
+ vext.8 q11, q11, q11, #12
+ vext.8 q10, q10, q10, #13
+ veor q8, q8, q9
+ veor q10, q10, q11
+ veor q1, q1, q8
+ veor q1, q1, q10
+ vext.8 d16, d27, d27, #1 @ A1
+ vmull.p8 q8, d16, d7 @ F = A1*B
+ vext.8 d4, d7, d7, #1 @ B1
+ vmull.p8 q2, d27, d4 @ E = A*B1
+ vext.8 d18, d27, d27, #2 @ A2
+ vmull.p8 q9, d18, d7 @ H = A2*B
+ vext.8 d22, d7, d7, #2 @ B2
+ vmull.p8 q11, d27, d22 @ G = A*B2
+ vext.8 d20, d27, d27, #3 @ A3
+ veor q8, q8, q2 @ L = E + F
+ vmull.p8 q10, d20, d7 @ J = A3*B
+ vext.8 d4, d7, d7, #3 @ B3
+ veor q9, q9, q11 @ M = G + H
+ vmull.p8 q2, d27, d4 @ I = A*B3
+ veor d16, d16, d17 @ t0 = (L) (P0 + P1) << 8
+ vand d17, d17, d29
+ vext.8 d22, d7, d7, #4 @ B4
+ veor d18, d18, d19 @ t1 = (M) (P2 + P3) << 16
+ vand d19, d19, d30
+ vmull.p8 q11, d27, d22 @ K = A*B4
+ veor q10, q10, q2 @ N = I + J
+ veor d16, d16, d17
+ veor d18, d18, d19
+ veor d20, d20, d21 @ t2 = (N) (P4 + P5) << 24
+ vand d21, d21, d31
+ vext.8 q8, q8, q8, #15
+ veor d22, d22, d23 @ t3 = (K) (P6 + P7) << 32
+ vmov.i64 d23, #0
+ vext.8 q9, q9, q9, #14
+ veor d20, d20, d21
+ vmull.p8 q2, d27, d7 @ D = A*B
+ vext.8 q11, q11, q11, #12
+ vext.8 q10, q10, q10, #13
+ veor q8, q8, q9
+ veor q10, q10, q11
+ veor q2, q2, q8
+ veor q2, q2, q10
+ veor q1,q1,q0 @ Karatsuba post-processing
+ veor q1,q1,q2
+ veor d1,d1,d2
+ veor d4,d4,d3 @ Xh|Xl - 256-bit result
+
+ @ equivalent of reduction_avx from ghash-x86_64.pl
+ vshl.i64 q9,q0,#57 @ 1st phase
+ vshl.i64 q10,q0,#62
+ veor q10,q10,q9 @
+ vshl.i64 q9,q0,#63
+ veor q10, q10, q9 @
+ veor d1,d1,d20 @
+ veor d4,d4,d21
+
+ vshr.u64 q10,q0,#1 @ 2nd phase
+ veor q2,q2,q0
+ veor q0,q0,q10 @
+ vshr.u64 q10,q10,#6
+ vshr.u64 q0,q0,#1 @
+ veor q0,q0,q2 @
+ veor q0,q0,q10 @
+
+ subs r3,#16
+ bne .Loop_neon
+
+#ifdef __ARMEL__
+ vrev64.8 q0,q0
+#endif
+ sub r0,#16
+ vst1.64 d1,[r0,:64]! @ write out Xi
+ vst1.64 d0,[r0,:64]
+
+ .word 0xe12fff1e
+.size gcm_ghash_neon,.-gcm_ghash_neon
+#endif
+.asciz "GHASH for ARMv4/NEON, CRYPTOGAMS by <appro@openssl.org>"
+.align 2
+
+#endif
diff --git a/linux-arm/crypto/modes/ghashv8-armx.S b/linux-arm/crypto/modes/ghashv8-armx.S
new file mode 100644
index 0000000..570d917
--- /dev/null
+++ b/linux-arm/crypto/modes/ghashv8-armx.S
@@ -0,0 +1,116 @@
+#include "arm_arch.h"
+
+.text
+.fpu neon
+.code 32
+.global gcm_init_v8
+.type gcm_init_v8,%function
+.align 4
+gcm_init_v8:
+ vld1.64 {q9},[r1] @ load H
+ vmov.i8 q8,#0xe1
+ vext.8 q3,q9,q9,#8
+ vshl.i64 q8,q8,#57
+ vshr.u64 q10,q8,#63
+ vext.8 q8,q10,q8,#8 @ t0=0xc2....01
+ vdup.32 q9,d18[1]
+ vshr.u64 q11,q3,#63
+ vshr.s32 q9,q9,#31 @ broadcast carry bit
+ vand q11,q11,q8
+ vshl.i64 q3,q3,#1
+ vext.8 q11,q11,q11,#8
+ vand q8,q8,q9
+ vorr q3,q3,q11 @ H<<<=1
+ veor q3,q3,q8 @ twisted H
+ vst1.64 {q3},[r0]
+
+ bx lr
+.size gcm_init_v8,.-gcm_init_v8
+
+.global gcm_gmult_v8
+.type gcm_gmult_v8,%function
+.align 4
+gcm_gmult_v8:
+ vld1.64 {q9},[r0] @ load Xi
+ vmov.i8 q11,#0xe1
+ vld1.64 {q12},[r1] @ load twisted H
+ vshl.u64 q11,q11,#57
+#ifndef __ARMEB__
+ vrev64.8 q9,q9
+#endif
+ vext.8 q13,q12,q12,#8
+ mov r3,#0
+ vext.8 q3,q9,q9,#8
+ mov r12,#0
+ veor q13,q13,q12 @ Karatsuba pre-processing
+ mov r2,r0
+ b .Lgmult_v8
+.size gcm_gmult_v8,.-gcm_gmult_v8
+
+.global gcm_ghash_v8
+.type gcm_ghash_v8,%function
+.align 4
+gcm_ghash_v8:
+ vld1.64 {q0},[r0] @ load [rotated] Xi
+ subs r3,r3,#16
+ vmov.i8 q11,#0xe1
+ mov r12,#16
+ vld1.64 {q12},[r1] @ load twisted H
+ moveq r12,#0
+ vext.8 q0,q0,q0,#8
+ vshl.u64 q11,q11,#57
+ vld1.64 {q9},[r2],r12 @ load [rotated] inp
+ vext.8 q13,q12,q12,#8
+#ifndef __ARMEB__
+ vrev64.8 q0,q0
+ vrev64.8 q9,q9
+#endif
+ veor q13,q13,q12 @ Karatsuba pre-processing
+ vext.8 q3,q9,q9,#8
+ b .Loop_v8
+
+.align 4
+.Loop_v8:
+ vext.8 q10,q0,q0,#8
+ veor q3,q3,q0 @ inp^=Xi
+ veor q9,q9,q10 @ q9 is rotated inp^Xi
+
+.Lgmult_v8:
+ .byte 0x86,0x0e,0xa8,0xf2 @ pmull q0,q12,q3 @ H.lo·Xi.lo
+ veor q9,q9,q3 @ Karatsuba pre-processing
+ .byte 0x87,0x4e,0xa9,0xf2 @ pmull2 q2,q12,q3 @ H.hi·Xi.hi
+ subs r3,r3,#16
+ .byte 0xa2,0x2e,0xaa,0xf2 @ pmull q1,q13,q9 @ (H.lo+H.hi)·(Xi.lo+Xi.hi)
+ moveq r12,#0
+
+ vext.8 q9,q0,q2,#8 @ Karatsuba post-processing
+ veor q10,q0,q2
+ veor q1,q1,q9
+ vld1.64 {q9},[r2],r12 @ load [rotated] inp
+ veor q1,q1,q10
+ .byte 0x26,0x4e,0xe0,0xf2 @ pmull q10,q0,q11 @ 1st phase
+
+ vmov d4,d3 @ Xh|Xm - 256-bit result
+ vmov d3,d0 @ Xm is rotated Xl
+#ifndef __ARMEB__
+ vrev64.8 q9,q9
+#endif
+ veor q0,q1,q10
+ vext.8 q3,q9,q9,#8
+
+ vext.8 q10,q0,q0,#8 @ 2nd phase
+ .byte 0x26,0x0e,0xa0,0xf2 @ pmull q0,q0,q11
+ veor q10,q10,q2
+ veor q0,q0,q10
+ bhs .Loop_v8
+
+#ifndef __ARMEB__
+ vrev64.8 q0,q0
+#endif
+ vext.8 q0,q0,q0,#8
+ vst1.64 {q0},[r0] @ write out Xi
+
+ bx lr
+.size gcm_ghash_v8,.-gcm_ghash_v8
+.asciz "GHASH for ARMv8, CRYPTOGAMS by <appro@openssl.org>"
+.align 2
diff --git a/linux-arm/crypto/sha/sha1-armv4-large.S b/linux-arm/crypto/sha/sha1-armv4-large.S
new file mode 100644
index 0000000..b089335
--- /dev/null
+++ b/linux-arm/crypto/sha/sha1-armv4-large.S
@@ -0,0 +1,1455 @@
+#include "arm_arch.h"
+
+.text
+.code 32
+
+.global sha1_block_data_order
+.type sha1_block_data_order,%function
+
+.align 5
+sha1_block_data_order:
+#if __ARM_MAX_ARCH__>=7
+ sub r3,pc,#8 @ sha1_block_data_order
+ ldr r12,.LOPENSSL_armcap
+ ldr r12,[r3,r12] @ OPENSSL_armcap_P
+ tst r12,#ARMV8_SHA1
+ bne .LARMv8
+ tst r12,#ARMV7_NEON
+ bne .LNEON
+#endif
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+.size sha1_block_data_order,.-sha1_block_data_order
+
+.align 5
+.LK_00_19: .word 0x5a827999
+.LK_20_39: .word 0x6ed9eba1
+.LK_40_59: .word 0x8f1bbcdc
+.LK_60_79: .word 0xca62c1d6
+#if __ARM_MAX_ARCH__>=7
+.LOPENSSL_armcap:
+.word OPENSSL_armcap_P-sha1_block_data_order
+#endif
+.asciz "SHA1 block transform for ARMv4/NEON/ARMv8, CRYPTOGAMS by <appro@openssl.org>"
+.align 5
+#if __ARM_MAX_ARCH__>=7
+.arch armv7-a
+.fpu neon
+
+.type sha1_block_data_order_neon,%function
+.align 4
+sha1_block_data_order_neon:
+.LNEON:
+ stmdb sp!,{r4-r12,lr}
+ add r2,r1,r2,lsl#6 @ r2 to point at the end of r1
+ @ dmb @ errata #451034 on early Cortex A8
+ @ vstmdb sp!,{d8-d15} @ ABI specification says so
+ mov r14,sp
+ sub sp,sp,#64 @ alloca
+ adr r8,.LK_00_19
+ bic sp,sp,#15 @ align for 128-bit stores
+
+ ldmia r0,{r3,r4,r5,r6,r7} @ load context
+ mov r12,sp
+
+ vld1.8 {q0-q1},[r1]! @ handles unaligned
+ veor q15,q15,q15
+ vld1.8 {q2-q3},[r1]!
+ vld1.32 {d28[],d29[]},[r8,:32]! @ load K_00_19
+ vrev32.8 q0,q0 @ yes, even on
+ vrev32.8 q1,q1 @ big-endian...
+ vrev32.8 q2,q2
+ vadd.i32 q8,q0,q14
+ vrev32.8 q3,q3
+ vadd.i32 q9,q1,q14
+ vst1.32 {q8},[r12,:128]!
+ vadd.i32 q10,q2,q14
+ vst1.32 {q9},[r12,:128]!
+ vst1.32 {q10},[r12,:128]!
+ ldr r9,[sp] @ big RAW stall
+
+.Loop_neon:
+ vext.8 q8,q0,q1,#8
+ bic r10,r6,r4
+ add r7,r7,r9
+ and r11,r5,r4
+ vadd.i32 q13,q3,q14
+ ldr r9,[sp,#4]
+ add r7,r7,r3,ror#27
+ vext.8 q12,q3,q15,#4
+ eor r11,r11,r10
+ mov r4,r4,ror#2
+ add r7,r7,r11
+ veor q8,q8,q0
+ bic r10,r5,r3
+ add r6,r6,r9
+ veor q12,q12,q2
+ and r11,r4,r3
+ ldr r9,[sp,#8]
+ veor q12,q12,q8
+ add r6,r6,r7,ror#27
+ eor r11,r11,r10
+ vst1.32 {q13},[r12,:128]!
+ sub r12,r12,#64
+ mov r3,r3,ror#2
+ add r6,r6,r11
+ vext.8 q13,q15,q12,#4
+ bic r10,r4,r7
+ add r5,r5,r9
+ vadd.i32 q8,q12,q12
+ and r11,r3,r7
+ ldr r9,[sp,#12]
+ vsri.32 q8,q12,#31
+ add r5,r5,r6,ror#27
+ eor r11,r11,r10
+ mov r7,r7,ror#2
+ vshr.u32 q12,q13,#30
+ add r5,r5,r11
+ bic r10,r3,r6
+ vshl.u32 q13,q13,#2
+ add r4,r4,r9
+ and r11,r7,r6
+ veor q8,q8,q12
+ ldr r9,[sp,#16]
+ add r4,r4,r5,ror#27
+ veor q8,q8,q13
+ eor r11,r11,r10
+ mov r6,r6,ror#2
+ add r4,r4,r11
+ vext.8 q9,q1,q2,#8
+ bic r10,r7,r5
+ add r3,r3,r9
+ and r11,r6,r5
+ vadd.i32 q13,q8,q14
+ ldr r9,[sp,#20]
+ vld1.32 {d28[],d29[]},[r8,:32]!
+ add r3,r3,r4,ror#27
+ vext.8 q12,q8,q15,#4
+ eor r11,r11,r10
+ mov r5,r5,ror#2
+ add r3,r3,r11
+ veor q9,q9,q1
+ bic r10,r6,r4
+ add r7,r7,r9
+ veor q12,q12,q3
+ and r11,r5,r4
+ ldr r9,[sp,#24]
+ veor q12,q12,q9
+ add r7,r7,r3,ror#27
+ eor r11,r11,r10
+ vst1.32 {q13},[r12,:128]!
+ mov r4,r4,ror#2
+ add r7,r7,r11
+ vext.8 q13,q15,q12,#4
+ bic r10,r5,r3
+ add r6,r6,r9
+ vadd.i32 q9,q12,q12
+ and r11,r4,r3
+ ldr r9,[sp,#28]
+ vsri.32 q9,q12,#31
+ add r6,r6,r7,ror#27
+ eor r11,r11,r10
+ mov r3,r3,ror#2
+ vshr.u32 q12,q13,#30
+ add r6,r6,r11
+ bic r10,r4,r7
+ vshl.u32 q13,q13,#2
+ add r5,r5,r9
+ and r11,r3,r7
+ veor q9,q9,q12
+ ldr r9,[sp,#32]
+ add r5,r5,r6,ror#27
+ veor q9,q9,q13
+ eor r11,r11,r10
+ mov r7,r7,ror#2
+ add r5,r5,r11
+ vext.8 q10,q2,q3,#8
+ bic r10,r3,r6
+ add r4,r4,r9
+ and r11,r7,r6
+ vadd.i32 q13,q9,q14
+ ldr r9,[sp,#36]
+ add r4,r4,r5,ror#27
+ vext.8 q12,q9,q15,#4
+ eor r11,r11,r10
+ mov r6,r6,ror#2
+ add r4,r4,r11
+ veor q10,q10,q2
+ bic r10,r7,r5
+ add r3,r3,r9
+ veor q12,q12,q8
+ and r11,r6,r5
+ ldr r9,[sp,#40]
+ veor q12,q12,q10
+ add r3,r3,r4,ror#27
+ eor r11,r11,r10
+ vst1.32 {q13},[r12,:128]!
+ mov r5,r5,ror#2
+ add r3,r3,r11
+ vext.8 q13,q15,q12,#4
+ bic r10,r6,r4
+ add r7,r7,r9
+ vadd.i32 q10,q12,q12
+ and r11,r5,r4
+ ldr r9,[sp,#44]
+ vsri.32 q10,q12,#31
+ add r7,r7,r3,ror#27
+ eor r11,r11,r10
+ mov r4,r4,ror#2
+ vshr.u32 q12,q13,#30
+ add r7,r7,r11
+ bic r10,r5,r3
+ vshl.u32 q13,q13,#2
+ add r6,r6,r9
+ and r11,r4,r3
+ veor q10,q10,q12
+ ldr r9,[sp,#48]
+ add r6,r6,r7,ror#27
+ veor q10,q10,q13
+ eor r11,r11,r10
+ mov r3,r3,ror#2
+ add r6,r6,r11
+ vext.8 q11,q3,q8,#8
+ bic r10,r4,r7
+ add r5,r5,r9
+ and r11,r3,r7
+ vadd.i32 q13,q10,q14
+ ldr r9,[sp,#52]
+ add r5,r5,r6,ror#27
+ vext.8 q12,q10,q15,#4
+ eor r11,r11,r10
+ mov r7,r7,ror#2
+ add r5,r5,r11
+ veor q11,q11,q3
+ bic r10,r3,r6
+ add r4,r4,r9
+ veor q12,q12,q9
+ and r11,r7,r6
+ ldr r9,[sp,#56]
+ veor q12,q12,q11
+ add r4,r4,r5,ror#27
+ eor r11,r11,r10
+ vst1.32 {q13},[r12,:128]!
+ mov r6,r6,ror#2
+ add r4,r4,r11
+ vext.8 q13,q15,q12,#4
+ bic r10,r7,r5
+ add r3,r3,r9
+ vadd.i32 q11,q12,q12
+ and r11,r6,r5
+ ldr r9,[sp,#60]
+ vsri.32 q11,q12,#31
+ add r3,r3,r4,ror#27
+ eor r11,r11,r10
+ mov r5,r5,ror#2
+ vshr.u32 q12,q13,#30
+ add r3,r3,r11
+ bic r10,r6,r4
+ vshl.u32 q13,q13,#2
+ add r7,r7,r9
+ and r11,r5,r4
+ veor q11,q11,q12
+ ldr r9,[sp,#0]
+ add r7,r7,r3,ror#27
+ veor q11,q11,q13
+ eor r11,r11,r10
+ mov r4,r4,ror#2
+ add r7,r7,r11
+ vext.8 q12,q10,q11,#8
+ bic r10,r5,r3
+ add r6,r6,r9
+ and r11,r4,r3
+ veor q0,q0,q8
+ ldr r9,[sp,#4]
+ add r6,r6,r7,ror#27
+ veor q0,q0,q1
+ eor r11,r11,r10
+ mov r3,r3,ror#2
+ vadd.i32 q13,q11,q14
+ add r6,r6,r11
+ bic r10,r4,r7
+ veor q12,q12,q0
+ add r5,r5,r9
+ and r11,r3,r7
+ vshr.u32 q0,q12,#30
+ ldr r9,[sp,#8]
+ add r5,r5,r6,ror#27
+ vst1.32 {q13},[r12,:128]!
+ sub r12,r12,#64
+ eor r11,r11,r10
+ mov r7,r7,ror#2
+ vsli.32 q0,q12,#2
+ add r5,r5,r11
+ bic r10,r3,r6
+ add r4,r4,r9
+ and r11,r7,r6
+ ldr r9,[sp,#12]
+ add r4,r4,r5,ror#27
+ eor r11,r11,r10
+ mov r6,r6,ror#2
+ add r4,r4,r11
+ bic r10,r7,r5
+ add r3,r3,r9
+ and r11,r6,r5
+ ldr r9,[sp,#16]
+ add r3,r3,r4,ror#27
+ eor r11,r11,r10
+ mov r5,r5,ror#2
+ add r3,r3,r11
+ vext.8 q12,q11,q0,#8
+ eor r10,r4,r6
+ add r7,r7,r9
+ ldr r9,[sp,#20]
+ veor q1,q1,q9
+ eor r11,r10,r5
+ add r7,r7,r3,ror#27
+ veor q1,q1,q2
+ mov r4,r4,ror#2
+ add r7,r7,r11
+ vadd.i32 q13,q0,q14
+ eor r10,r3,r5
+ add r6,r6,r9
+ veor q12,q12,q1
+ ldr r9,[sp,#24]
+ eor r11,r10,r4
+ vshr.u32 q1,q12,#30
+ add r6,r6,r7,ror#27
+ mov r3,r3,ror#2
+ vst1.32 {q13},[r12,:128]!
+ add r6,r6,r11
+ eor r10,r7,r4
+ vsli.32 q1,q12,#2
+ add r5,r5,r9
+ ldr r9,[sp,#28]
+ eor r11,r10,r3
+ add r5,r5,r6,ror#27
+ mov r7,r7,ror#2
+ add r5,r5,r11
+ eor r10,r6,r3
+ add r4,r4,r9
+ ldr r9,[sp,#32]
+ eor r11,r10,r7
+ add r4,r4,r5,ror#27
+ mov r6,r6,ror#2
+ add r4,r4,r11
+ vext.8 q12,q0,q1,#8
+ eor r10,r5,r7
+ add r3,r3,r9
+ ldr r9,[sp,#36]
+ veor q2,q2,q10
+ eor r11,r10,r6
+ add r3,r3,r4,ror#27
+ veor q2,q2,q3
+ mov r5,r5,ror#2
+ add r3,r3,r11
+ vadd.i32 q13,q1,q14
+ eor r10,r4,r6
+ vld1.32 {d28[],d29[]},[r8,:32]!
+ add r7,r7,r9
+ veor q12,q12,q2
+ ldr r9,[sp,#40]
+ eor r11,r10,r5
+ vshr.u32 q2,q12,#30
+ add r7,r7,r3,ror#27
+ mov r4,r4,ror#2
+ vst1.32 {q13},[r12,:128]!
+ add r7,r7,r11
+ eor r10,r3,r5
+ vsli.32 q2,q12,#2
+ add r6,r6,r9
+ ldr r9,[sp,#44]
+ eor r11,r10,r4
+ add r6,r6,r7,ror#27
+ mov r3,r3,ror#2
+ add r6,r6,r11
+ eor r10,r7,r4
+ add r5,r5,r9
+ ldr r9,[sp,#48]
+ eor r11,r10,r3
+ add r5,r5,r6,ror#27
+ mov r7,r7,ror#2
+ add r5,r5,r11
+ vext.8 q12,q1,q2,#8
+ eor r10,r6,r3
+ add r4,r4,r9
+ ldr r9,[sp,#52]
+ veor q3,q3,q11
+ eor r11,r10,r7
+ add r4,r4,r5,ror#27
+ veor q3,q3,q8
+ mov r6,r6,ror#2
+ add r4,r4,r11
+ vadd.i32 q13,q2,q14
+ eor r10,r5,r7
+ add r3,r3,r9
+ veor q12,q12,q3
+ ldr r9,[sp,#56]
+ eor r11,r10,r6
+ vshr.u32 q3,q12,#30
+ add r3,r3,r4,ror#27
+ mov r5,r5,ror#2
+ vst1.32 {q13},[r12,:128]!
+ add r3,r3,r11
+ eor r10,r4,r6
+ vsli.32 q3,q12,#2
+ add r7,r7,r9
+ ldr r9,[sp,#60]
+ eor r11,r10,r5
+ add r7,r7,r3,ror#27
+ mov r4,r4,ror#2
+ add r7,r7,r11
+ eor r10,r3,r5
+ add r6,r6,r9
+ ldr r9,[sp,#0]
+ eor r11,r10,r4
+ add r6,r6,r7,ror#27
+ mov r3,r3,ror#2
+ add r6,r6,r11
+ vext.8 q12,q2,q3,#8
+ eor r10,r7,r4
+ add r5,r5,r9
+ ldr r9,[sp,#4]
+ veor q8,q8,q0
+ eor r11,r10,r3
+ add r5,r5,r6,ror#27
+ veor q8,q8,q9
+ mov r7,r7,ror#2
+ add r5,r5,r11
+ vadd.i32 q13,q3,q14
+ eor r10,r6,r3
+ add r4,r4,r9
+ veor q12,q12,q8
+ ldr r9,[sp,#8]
+ eor r11,r10,r7
+ vshr.u32 q8,q12,#30
+ add r4,r4,r5,ror#27
+ mov r6,r6,ror#2
+ vst1.32 {q13},[r12,:128]!
+ sub r12,r12,#64
+ add r4,r4,r11
+ eor r10,r5,r7
+ vsli.32 q8,q12,#2
+ add r3,r3,r9
+ ldr r9,[sp,#12]
+ eor r11,r10,r6
+ add r3,r3,r4,ror#27
+ mov r5,r5,ror#2
+ add r3,r3,r11
+ eor r10,r4,r6
+ add r7,r7,r9
+ ldr r9,[sp,#16]
+ eor r11,r10,r5
+ add r7,r7,r3,ror#27
+ mov r4,r4,ror#2
+ add r7,r7,r11
+ vext.8 q12,q3,q8,#8
+ eor r10,r3,r5
+ add r6,r6,r9
+ ldr r9,[sp,#20]
+ veor q9,q9,q1
+ eor r11,r10,r4
+ add r6,r6,r7,ror#27
+ veor q9,q9,q10
+ mov r3,r3,ror#2
+ add r6,r6,r11
+ vadd.i32 q13,q8,q14
+ eor r10,r7,r4
+ add r5,r5,r9
+ veor q12,q12,q9
+ ldr r9,[sp,#24]
+ eor r11,r10,r3
+ vshr.u32 q9,q12,#30
+ add r5,r5,r6,ror#27
+ mov r7,r7,ror#2
+ vst1.32 {q13},[r12,:128]!
+ add r5,r5,r11
+ eor r10,r6,r3
+ vsli.32 q9,q12,#2
+ add r4,r4,r9
+ ldr r9,[sp,#28]
+ eor r11,r10,r7
+ add r4,r4,r5,ror#27
+ mov r6,r6,ror#2
+ add r4,r4,r11
+ eor r10,r5,r7
+ add r3,r3,r9
+ ldr r9,[sp,#32]
+ eor r11,r10,r6
+ add r3,r3,r4,ror#27
+ mov r5,r5,ror#2
+ add r3,r3,r11
+ vext.8 q12,q8,q9,#8
+ add r7,r7,r9
+ and r10,r5,r6
+ ldr r9,[sp,#36]
+ veor q10,q10,q2
+ add r7,r7,r3,ror#27
+ eor r11,r5,r6
+ veor q10,q10,q11
+ add r7,r7,r10
+ and r11,r11,r4
+ vadd.i32 q13,q9,q14
+ mov r4,r4,ror#2
+ add r7,r7,r11
+ veor q12,q12,q10
+ add r6,r6,r9
+ and r10,r4,r5
+ vshr.u32 q10,q12,#30
+ ldr r9,[sp,#40]
+ add r6,r6,r7,ror#27
+ vst1.32 {q13},[r12,:128]!
+ eor r11,r4,r5
+ add r6,r6,r10
+ vsli.32 q10,q12,#2
+ and r11,r11,r3
+ mov r3,r3,ror#2
+ add r6,r6,r11
+ add r5,r5,r9
+ and r10,r3,r4
+ ldr r9,[sp,#44]
+ add r5,r5,r6,ror#27
+ eor r11,r3,r4
+ add r5,r5,r10
+ and r11,r11,r7
+ mov r7,r7,ror#2
+ add r5,r5,r11
+ add r4,r4,r9
+ and r10,r7,r3
+ ldr r9,[sp,#48]
+ add r4,r4,r5,ror#27
+ eor r11,r7,r3
+ add r4,r4,r10
+ and r11,r11,r6
+ mov r6,r6,ror#2
+ add r4,r4,r11
+ vext.8 q12,q9,q10,#8
+ add r3,r3,r9
+ and r10,r6,r7
+ ldr r9,[sp,#52]
+ veor q11,q11,q3
+ add r3,r3,r4,ror#27
+ eor r11,r6,r7
+ veor q11,q11,q0
+ add r3,r3,r10
+ and r11,r11,r5
+ vadd.i32 q13,q10,q14
+ mov r5,r5,ror#2
+ vld1.32 {d28[],d29[]},[r8,:32]!
+ add r3,r3,r11
+ veor q12,q12,q11
+ add r7,r7,r9
+ and r10,r5,r6
+ vshr.u32 q11,q12,#30
+ ldr r9,[sp,#56]
+ add r7,r7,r3,ror#27
+ vst1.32 {q13},[r12,:128]!
+ eor r11,r5,r6
+ add r7,r7,r10
+ vsli.32 q11,q12,#2
+ and r11,r11,r4
+ mov r4,r4,ror#2
+ add r7,r7,r11
+ add r6,r6,r9
+ and r10,r4,r5
+ ldr r9,[sp,#60]
+ add r6,r6,r7,ror#27
+ eor r11,r4,r5
+ add r6,r6,r10
+ and r11,r11,r3
+ mov r3,r3,ror#2
+ add r6,r6,r11
+ add r5,r5,r9
+ and r10,r3,r4
+ ldr r9,[sp,#0]
+ add r5,r5,r6,ror#27
+ eor r11,r3,r4
+ add r5,r5,r10
+ and r11,r11,r7
+ mov r7,r7,ror#2
+ add r5,r5,r11
+ vext.8 q12,q10,q11,#8
+ add r4,r4,r9
+ and r10,r7,r3
+ ldr r9,[sp,#4]
+ veor q0,q0,q8
+ add r4,r4,r5,ror#27
+ eor r11,r7,r3
+ veor q0,q0,q1
+ add r4,r4,r10
+ and r11,r11,r6
+ vadd.i32 q13,q11,q14
+ mov r6,r6,ror#2
+ add r4,r4,r11
+ veor q12,q12,q0
+ add r3,r3,r9
+ and r10,r6,r7
+ vshr.u32 q0,q12,#30
+ ldr r9,[sp,#8]
+ add r3,r3,r4,ror#27
+ vst1.32 {q13},[r12,:128]!
+ sub r12,r12,#64
+ eor r11,r6,r7
+ add r3,r3,r10
+ vsli.32 q0,q12,#2
+ and r11,r11,r5
+ mov r5,r5,ror#2
+ add r3,r3,r11
+ add r7,r7,r9
+ and r10,r5,r6
+ ldr r9,[sp,#12]
+ add r7,r7,r3,ror#27
+ eor r11,r5,r6
+ add r7,r7,r10
+ and r11,r11,r4
+ mov r4,r4,ror#2
+ add r7,r7,r11
+ add r6,r6,r9
+ and r10,r4,r5
+ ldr r9,[sp,#16]
+ add r6,r6,r7,ror#27
+ eor r11,r4,r5
+ add r6,r6,r10
+ and r11,r11,r3
+ mov r3,r3,ror#2
+ add r6,r6,r11
+ vext.8 q12,q11,q0,#8
+ add r5,r5,r9
+ and r10,r3,r4
+ ldr r9,[sp,#20]
+ veor q1,q1,q9
+ add r5,r5,r6,ror#27
+ eor r11,r3,r4
+ veor q1,q1,q2
+ add r5,r5,r10
+ and r11,r11,r7
+ vadd.i32 q13,q0,q14
+ mov r7,r7,ror#2
+ add r5,r5,r11
+ veor q12,q12,q1
+ add r4,r4,r9
+ and r10,r7,r3
+ vshr.u32 q1,q12,#30
+ ldr r9,[sp,#24]
+ add r4,r4,r5,ror#27
+ vst1.32 {q13},[r12,:128]!
+ eor r11,r7,r3
+ add r4,r4,r10
+ vsli.32 q1,q12,#2
+ and r11,r11,r6
+ mov r6,r6,ror#2
+ add r4,r4,r11
+ add r3,r3,r9
+ and r10,r6,r7
+ ldr r9,[sp,#28]
+ add r3,r3,r4,ror#27
+ eor r11,r6,r7
+ add r3,r3,r10
+ and r11,r11,r5
+ mov r5,r5,ror#2
+ add r3,r3,r11
+ add r7,r7,r9
+ and r10,r5,r6
+ ldr r9,[sp,#32]
+ add r7,r7,r3,ror#27
+ eor r11,r5,r6
+ add r7,r7,r10
+ and r11,r11,r4
+ mov r4,r4,ror#2
+ add r7,r7,r11
+ vext.8 q12,q0,q1,#8
+ add r6,r6,r9
+ and r10,r4,r5
+ ldr r9,[sp,#36]
+ veor q2,q2,q10
+ add r6,r6,r7,ror#27
+ eor r11,r4,r5
+ veor q2,q2,q3
+ add r6,r6,r10
+ and r11,r11,r3
+ vadd.i32 q13,q1,q14
+ mov r3,r3,ror#2
+ add r6,r6,r11
+ veor q12,q12,q2
+ add r5,r5,r9
+ and r10,r3,r4
+ vshr.u32 q2,q12,#30
+ ldr r9,[sp,#40]
+ add r5,r5,r6,ror#27
+ vst1.32 {q13},[r12,:128]!
+ eor r11,r3,r4
+ add r5,r5,r10
+ vsli.32 q2,q12,#2
+ and r11,r11,r7
+ mov r7,r7,ror#2
+ add r5,r5,r11
+ add r4,r4,r9
+ and r10,r7,r3
+ ldr r9,[sp,#44]
+ add r4,r4,r5,ror#27
+ eor r11,r7,r3
+ add r4,r4,r10
+ and r11,r11,r6
+ mov r6,r6,ror#2
+ add r4,r4,r11
+ add r3,r3,r9
+ and r10,r6,r7
+ ldr r9,[sp,#48]
+ add r3,r3,r4,ror#27
+ eor r11,r6,r7
+ add r3,r3,r10
+ and r11,r11,r5
+ mov r5,r5,ror#2
+ add r3,r3,r11
+ vext.8 q12,q1,q2,#8
+ eor r10,r4,r6
+ add r7,r7,r9
+ ldr r9,[sp,#52]
+ veor q3,q3,q11
+ eor r11,r10,r5
+ add r7,r7,r3,ror#27
+ veor q3,q3,q8
+ mov r4,r4,ror#2
+ add r7,r7,r11
+ vadd.i32 q13,q2,q14
+ eor r10,r3,r5
+ add r6,r6,r9
+ veor q12,q12,q3
+ ldr r9,[sp,#56]
+ eor r11,r10,r4
+ vshr.u32 q3,q12,#30
+ add r6,r6,r7,ror#27
+ mov r3,r3,ror#2
+ vst1.32 {q13},[r12,:128]!
+ add r6,r6,r11
+ eor r10,r7,r4
+ vsli.32 q3,q12,#2
+ add r5,r5,r9
+ ldr r9,[sp,#60]
+ eor r11,r10,r3
+ add r5,r5,r6,ror#27
+ mov r7,r7,ror#2
+ add r5,r5,r11
+ eor r10,r6,r3
+ add r4,r4,r9
+ ldr r9,[sp,#0]
+ eor r11,r10,r7
+ add r4,r4,r5,ror#27
+ mov r6,r6,ror#2
+ add r4,r4,r11
+ vadd.i32 q13,q3,q14
+ eor r10,r5,r7
+ add r3,r3,r9
+ vst1.32 {q13},[r12,:128]!
+ sub r12,r12,#64
+ teq r1,r2
+ sub r8,r8,#16
+ subeq r1,r1,#64
+ vld1.8 {q0-q1},[r1]!
+ ldr r9,[sp,#4]
+ eor r11,r10,r6
+ vld1.8 {q2-q3},[r1]!
+ add r3,r3,r4,ror#27
+ mov r5,r5,ror#2
+ vld1.32 {d28[],d29[]},[r8,:32]!
+ add r3,r3,r11
+ eor r10,r4,r6
+ vrev32.8 q0,q0
+ add r7,r7,r9
+ ldr r9,[sp,#8]
+ eor r11,r10,r5
+ add r7,r7,r3,ror#27
+ mov r4,r4,ror#2
+ add r7,r7,r11
+ eor r10,r3,r5
+ add r6,r6,r9
+ ldr r9,[sp,#12]
+ eor r11,r10,r4
+ add r6,r6,r7,ror#27
+ mov r3,r3,ror#2
+ add r6,r6,r11
+ eor r10,r7,r4
+ add r5,r5,r9
+ ldr r9,[sp,#16]
+ eor r11,r10,r3
+ add r5,r5,r6,ror#27
+ mov r7,r7,ror#2
+ add r5,r5,r11
+ vrev32.8 q1,q1
+ eor r10,r6,r3
+ add r4,r4,r9
+ vadd.i32 q8,q0,q14
+ ldr r9,[sp,#20]
+ eor r11,r10,r7
+ vst1.32 {q8},[r12,:128]!
+ add r4,r4,r5,ror#27
+ mov r6,r6,ror#2
+ add r4,r4,r11
+ eor r10,r5,r7
+ add r3,r3,r9
+ ldr r9,[sp,#24]
+ eor r11,r10,r6
+ add r3,r3,r4,ror#27
+ mov r5,r5,ror#2
+ add r3,r3,r11
+ eor r10,r4,r6
+ add r7,r7,r9
+ ldr r9,[sp,#28]
+ eor r11,r10,r5
+ add r7,r7,r3,ror#27
+ mov r4,r4,ror#2
+ add r7,r7,r11
+ eor r10,r3,r5
+ add r6,r6,r9
+ ldr r9,[sp,#32]
+ eor r11,r10,r4
+ add r6,r6,r7,ror#27
+ mov r3,r3,ror#2
+ add r6,r6,r11
+ vrev32.8 q2,q2
+ eor r10,r7,r4
+ add r5,r5,r9
+ vadd.i32 q9,q1,q14
+ ldr r9,[sp,#36]
+ eor r11,r10,r3
+ vst1.32 {q9},[r12,:128]!
+ add r5,r5,r6,ror#27
+ mov r7,r7,ror#2
+ add r5,r5,r11
+ eor r10,r6,r3
+ add r4,r4,r9
+ ldr r9,[sp,#40]
+ eor r11,r10,r7
+ add r4,r4,r5,ror#27
+ mov r6,r6,ror#2
+ add r4,r4,r11
+ eor r10,r5,r7
+ add r3,r3,r9
+ ldr r9,[sp,#44]
+ eor r11,r10,r6
+ add r3,r3,r4,ror#27
+ mov r5,r5,ror#2
+ add r3,r3,r11
+ eor r10,r4,r6
+ add r7,r7,r9
+ ldr r9,[sp,#48]
+ eor r11,r10,r5
+ add r7,r7,r3,ror#27
+ mov r4,r4,ror#2
+ add r7,r7,r11
+ vrev32.8 q3,q3
+ eor r10,r3,r5
+ add r6,r6,r9
+ vadd.i32 q10,q2,q14
+ ldr r9,[sp,#52]
+ eor r11,r10,r4
+ vst1.32 {q10},[r12,:128]!
+ add r6,r6,r7,ror#27
+ mov r3,r3,ror#2
+ add r6,r6,r11
+ eor r10,r7,r4
+ add r5,r5,r9
+ ldr r9,[sp,#56]
+ eor r11,r10,r3
+ add r5,r5,r6,ror#27
+ mov r7,r7,ror#2
+ add r5,r5,r11
+ eor r10,r6,r3
+ add r4,r4,r9
+ ldr r9,[sp,#60]
+ eor r11,r10,r7
+ add r4,r4,r5,ror#27
+ mov r6,r6,ror#2
+ add r4,r4,r11
+ eor r10,r5,r7
+ add r3,r3,r9
+ eor r11,r10,r6
+ add r3,r3,r4,ror#27
+ mov r5,r5,ror#2
+ add r3,r3,r11
+ ldmia r0,{r9,r10,r11,r12} @ accumulate context
+ add r3,r3,r9
+ ldr r9,[r0,#16]
+ add r4,r4,r10
+ add r5,r5,r11
+ add r6,r6,r12
+ moveq sp,r14
+ add r7,r7,r9
+ ldrne r9,[sp]
+ stmia r0,{r3,r4,r5,r6,r7}
+ addne r12,sp,#3*16
+ bne .Loop_neon
+
+ @ vldmia sp!,{d8-d15}
+ ldmia sp!,{r4-r12,pc}
+.size sha1_block_data_order_neon,.-sha1_block_data_order_neon
+#endif
+#if __ARM_MAX_ARCH__>=7
+.type sha1_block_data_order_armv8,%function
+.align 5
+sha1_block_data_order_armv8:
+.LARMv8:
+ vstmdb sp!,{d8-d15} @ ABI specification says so
+
+ veor q1,q1,q1
+ adr r3,.LK_00_19
+ vld1.32 {q0},[r0]!
+ vld1.32 {d2[0]},[r0]
+ sub r0,r0,#16
+ vld1.32 {d16[],d17[]},[r3,:32]!
+ vld1.32 {d18[],d19[]},[r3,:32]!
+ vld1.32 {d20[],d21[]},[r3,:32]!
+ vld1.32 {d22[],d23[]},[r3,:32]
+
+.Loop_v8:
+ vld1.8 {q4-q5},[r1]!
+ vld1.8 {q6-q7},[r1]!
+ vrev32.8 q4,q4
+ vrev32.8 q5,q5
+
+ vadd.i32 q12,q8,q4
+ vrev32.8 q6,q6
+ vmov q14,q0 @ offload
+ subs r2,r2,#1
+
+ vadd.i32 q13,q8,q5
+ vrev32.8 q7,q7
+ .byte 0xc0,0x62,0xb9,0xf3 @ sha1h q3,q0 @ 0
+ .byte 0x68,0x0c,0x02,0xf2 @ sha1c q0,q1,q12
+ vadd.i32 q12,q8,q6
+ .byte 0x4c,0x8c,0x3a,0xf2 @ sha1su0 q4,q5,q6
+ .byte 0xc0,0x42,0xb9,0xf3 @ sha1h q2,q0 @ 1
+ .byte 0x6a,0x0c,0x06,0xf2 @ sha1c q0,q3,q13
+ vadd.i32 q13,q8,q7
+ .byte 0x8e,0x83,0xba,0xf3 @ sha1su1 q4,q7
+ .byte 0x4e,0xac,0x3c,0xf2 @ sha1su0 q5,q6,q7
+ .byte 0xc0,0x62,0xb9,0xf3 @ sha1h q3,q0 @ 2
+ .byte 0x68,0x0c,0x04,0xf2 @ sha1c q0,q2,q12
+ vadd.i32 q12,q8,q4
+ .byte 0x88,0xa3,0xba,0xf3 @ sha1su1 q5,q4
+ .byte 0x48,0xcc,0x3e,0xf2 @ sha1su0 q6,q7,q4
+ .byte 0xc0,0x42,0xb9,0xf3 @ sha1h q2,q0 @ 3
+ .byte 0x6a,0x0c,0x06,0xf2 @ sha1c q0,q3,q13
+ vadd.i32 q13,q9,q5
+ .byte 0x8a,0xc3,0xba,0xf3 @ sha1su1 q6,q5
+ .byte 0x4a,0xec,0x38,0xf2 @ sha1su0 q7,q4,q5
+ .byte 0xc0,0x62,0xb9,0xf3 @ sha1h q3,q0 @ 4
+ .byte 0x68,0x0c,0x04,0xf2 @ sha1c q0,q2,q12
+ vadd.i32 q12,q9,q6
+ .byte 0x8c,0xe3,0xba,0xf3 @ sha1su1 q7,q6
+ .byte 0x4c,0x8c,0x3a,0xf2 @ sha1su0 q4,q5,q6
+ .byte 0xc0,0x42,0xb9,0xf3 @ sha1h q2,q0 @ 5
+ .byte 0x6a,0x0c,0x16,0xf2 @ sha1p q0,q3,q13
+ vadd.i32 q13,q9,q7
+ .byte 0x8e,0x83,0xba,0xf3 @ sha1su1 q4,q7
+ .byte 0x4e,0xac,0x3c,0xf2 @ sha1su0 q5,q6,q7
+ .byte 0xc0,0x62,0xb9,0xf3 @ sha1h q3,q0 @ 6
+ .byte 0x68,0x0c,0x14,0xf2 @ sha1p q0,q2,q12
+ vadd.i32 q12,q9,q4
+ .byte 0x88,0xa3,0xba,0xf3 @ sha1su1 q5,q4
+ .byte 0x48,0xcc,0x3e,0xf2 @ sha1su0 q6,q7,q4
+ .byte 0xc0,0x42,0xb9,0xf3 @ sha1h q2,q0 @ 7
+ .byte 0x6a,0x0c,0x16,0xf2 @ sha1p q0,q3,q13
+ vadd.i32 q13,q9,q5
+ .byte 0x8a,0xc3,0xba,0xf3 @ sha1su1 q6,q5
+ .byte 0x4a,0xec,0x38,0xf2 @ sha1su0 q7,q4,q5
+ .byte 0xc0,0x62,0xb9,0xf3 @ sha1h q3,q0 @ 8
+ .byte 0x68,0x0c,0x14,0xf2 @ sha1p q0,q2,q12
+ vadd.i32 q12,q10,q6
+ .byte 0x8c,0xe3,0xba,0xf3 @ sha1su1 q7,q6
+ .byte 0x4c,0x8c,0x3a,0xf2 @ sha1su0 q4,q5,q6
+ .byte 0xc0,0x42,0xb9,0xf3 @ sha1h q2,q0 @ 9
+ .byte 0x6a,0x0c,0x16,0xf2 @ sha1p q0,q3,q13
+ vadd.i32 q13,q10,q7
+ .byte 0x8e,0x83,0xba,0xf3 @ sha1su1 q4,q7
+ .byte 0x4e,0xac,0x3c,0xf2 @ sha1su0 q5,q6,q7
+ .byte 0xc0,0x62,0xb9,0xf3 @ sha1h q3,q0 @ 10
+ .byte 0x68,0x0c,0x24,0xf2 @ sha1m q0,q2,q12
+ vadd.i32 q12,q10,q4
+ .byte 0x88,0xa3,0xba,0xf3 @ sha1su1 q5,q4
+ .byte 0x48,0xcc,0x3e,0xf2 @ sha1su0 q6,q7,q4
+ .byte 0xc0,0x42,0xb9,0xf3 @ sha1h q2,q0 @ 11
+ .byte 0x6a,0x0c,0x26,0xf2 @ sha1m q0,q3,q13
+ vadd.i32 q13,q10,q5
+ .byte 0x8a,0xc3,0xba,0xf3 @ sha1su1 q6,q5
+ .byte 0x4a,0xec,0x38,0xf2 @ sha1su0 q7,q4,q5
+ .byte 0xc0,0x62,0xb9,0xf3 @ sha1h q3,q0 @ 12
+ .byte 0x68,0x0c,0x24,0xf2 @ sha1m q0,q2,q12
+ vadd.i32 q12,q10,q6
+ .byte 0x8c,0xe3,0xba,0xf3 @ sha1su1 q7,q6
+ .byte 0x4c,0x8c,0x3a,0xf2 @ sha1su0 q4,q5,q6
+ .byte 0xc0,0x42,0xb9,0xf3 @ sha1h q2,q0 @ 13
+ .byte 0x6a,0x0c,0x26,0xf2 @ sha1m q0,q3,q13
+ vadd.i32 q13,q11,q7
+ .byte 0x8e,0x83,0xba,0xf3 @ sha1su1 q4,q7
+ .byte 0x4e,0xac,0x3c,0xf2 @ sha1su0 q5,q6,q7
+ .byte 0xc0,0x62,0xb9,0xf3 @ sha1h q3,q0 @ 14
+ .byte 0x68,0x0c,0x24,0xf2 @ sha1m q0,q2,q12
+ vadd.i32 q12,q11,q4
+ .byte 0x88,0xa3,0xba,0xf3 @ sha1su1 q5,q4
+ .byte 0x48,0xcc,0x3e,0xf2 @ sha1su0 q6,q7,q4
+ .byte 0xc0,0x42,0xb9,0xf3 @ sha1h q2,q0 @ 15
+ .byte 0x6a,0x0c,0x16,0xf2 @ sha1p q0,q3,q13
+ vadd.i32 q13,q11,q5
+ .byte 0x8a,0xc3,0xba,0xf3 @ sha1su1 q6,q5
+ .byte 0x4a,0xec,0x38,0xf2 @ sha1su0 q7,q4,q5
+ .byte 0xc0,0x62,0xb9,0xf3 @ sha1h q3,q0 @ 16
+ .byte 0x68,0x0c,0x14,0xf2 @ sha1p q0,q2,q12
+ vadd.i32 q12,q11,q6
+ .byte 0x8c,0xe3,0xba,0xf3 @ sha1su1 q7,q6
+ .byte 0xc0,0x42,0xb9,0xf3 @ sha1h q2,q0 @ 17
+ .byte 0x6a,0x0c,0x16,0xf2 @ sha1p q0,q3,q13
+ vadd.i32 q13,q11,q7
+
+ .byte 0xc0,0x62,0xb9,0xf3 @ sha1h q3,q0 @ 18
+ .byte 0x68,0x0c,0x14,0xf2 @ sha1p q0,q2,q12
+
+ .byte 0xc0,0x42,0xb9,0xf3 @ sha1h q2,q0 @ 19
+ .byte 0x6a,0x0c,0x16,0xf2 @ sha1p q0,q3,q13
+
+ vadd.i32 q1,q1,q2
+ vadd.i32 q0,q0,q14
+ bne .Loop_v8
+
+ vst1.32 {q0},[r0]!
+ vst1.32 {d2[0]},[r0]
+
+ vldmia sp!,{d8-d15}
+ bx lr @ bx lr
+.size sha1_block_data_order_armv8,.-sha1_block_data_order_armv8
+#endif
+#if __ARM_MAX_ARCH__>=7
+.comm OPENSSL_armcap_P,4,4
+#endif
diff --git a/linux-arm/crypto/sha/sha256-armv4.S b/linux-arm/crypto/sha/sha256-armv4.S
new file mode 100644
index 0000000..bf1ce4f
--- /dev/null
+++ b/linux-arm/crypto/sha/sha256-armv4.S
@@ -0,0 +1,2695 @@
+#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
+.word 0 @ terminator
+#if __ARM_MAX_ARCH__>=7
+.LOPENSSL_armcap:
+.word OPENSSL_armcap_P-sha256_block_data_order
+#endif
+.align 5
+
+.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
+#if __ARM_MAX_ARCH__>=7
+ ldr r12,.LOPENSSL_armcap
+ ldr r12,[r3,r12] @ OPENSSL_armcap_P
+ tst r12,#ARMV8_SHA256
+ bne .LARMv8
+ tst r12,#ARMV7_NEON
+ bne .LNEON
+#endif
+ stmdb sp!,{r0,r1,r2,r4-r11,lr}
+ ldmia r0,{r4,r5,r6,r7,r8,r9,r10,r11}
+ sub r14,r3,#256+32 @ K256
+ sub sp,sp,#16*4 @ alloca(X[16])
+.Loop:
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r3,r5,r6 @ magic
+ eor r12,r12,r12
+#if __ARM_ARCH__>=7
+ @ ldr r2,[r1],#4 @ 0
+# if 0==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r8,r8,ror#5
+ add r4,r4,r12 @ h+=Maj(a,b,c) from the past
+ eor r0,r0,r8,ror#19 @ Sigma1(e)
+ rev r2,r2
+#else
+ @ ldrb r2,[r1,#3] @ 0
+ add r4,r4,r12 @ h+=Maj(a,b,c) from the past
+ ldrb r12,[r1,#2]
+ ldrb r0,[r1,#1]
+ orr r2,r2,r12,lsl#8
+ ldrb r12,[r1],#4
+ orr r2,r2,r0,lsl#16
+# if 0==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r8,r8,ror#5
+ orr r2,r2,r12,lsl#24
+ eor r0,r0,r8,ror#19 @ Sigma1(e)
+#endif
+ ldr r12,[r14],#4 @ *K256++
+ add r11,r11,r2 @ h+=X[i]
+ str r2,[sp,#0*4]
+ eor r2,r9,r10
+ add r11,r11,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r8
+ add r11,r11,r12 @ h+=K256[i]
+ eor r2,r2,r10 @ Ch(e,f,g)
+ eor r0,r4,r4,ror#11
+ add r11,r11,r2 @ h+=Ch(e,f,g)
+#if 0==31
+ and r12,r12,#0xff
+ cmp r12,#0xf2 @ done?
+#endif
+#if 0<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r12,r4,r5 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#2*4] @ from future BODY_16_xx
+ eor r12,r4,r5 @ a^b, b^c in next round
+ ldr r1,[sp,#15*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r4,ror#20 @ Sigma0(a)
+ and r3,r3,r12 @ (b^c)&=(a^b)
+ add r7,r7,r11 @ d+=h
+ eor r3,r3,r5 @ Maj(a,b,c)
+ add r11,r11,r0,ror#2 @ h+=Sigma0(a)
+ @ add r11,r11,r3 @ h+=Maj(a,b,c)
+#if __ARM_ARCH__>=7
+ @ ldr r2,[r1],#4 @ 1
+# if 1==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r7,r7,ror#5
+ add r11,r11,r3 @ h+=Maj(a,b,c) from the past
+ eor r0,r0,r7,ror#19 @ Sigma1(e)
+ rev r2,r2
+#else
+ @ ldrb r2,[r1,#3] @ 1
+ add r11,r11,r3 @ h+=Maj(a,b,c) from the past
+ ldrb r3,[r1,#2]
+ ldrb r0,[r1,#1]
+ orr r2,r2,r3,lsl#8
+ ldrb r3,[r1],#4
+ orr r2,r2,r0,lsl#16
+# if 1==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r7,r7,ror#5
+ orr r2,r2,r3,lsl#24
+ eor r0,r0,r7,ror#19 @ Sigma1(e)
+#endif
+ ldr r3,[r14],#4 @ *K256++
+ add r10,r10,r2 @ h+=X[i]
+ str r2,[sp,#1*4]
+ eor r2,r8,r9
+ add r10,r10,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r7
+ add r10,r10,r3 @ h+=K256[i]
+ eor r2,r2,r9 @ Ch(e,f,g)
+ eor r0,r11,r11,ror#11
+ add r10,r10,r2 @ h+=Ch(e,f,g)
+#if 1==31
+ and r3,r3,#0xff
+ cmp r3,#0xf2 @ done?
+#endif
+#if 1<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r3,r11,r4 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#3*4] @ from future BODY_16_xx
+ eor r3,r11,r4 @ a^b, b^c in next round
+ ldr r1,[sp,#0*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r11,ror#20 @ Sigma0(a)
+ and r12,r12,r3 @ (b^c)&=(a^b)
+ add r6,r6,r10 @ d+=h
+ eor r12,r12,r4 @ Maj(a,b,c)
+ add r10,r10,r0,ror#2 @ h+=Sigma0(a)
+ @ add r10,r10,r12 @ h+=Maj(a,b,c)
+#if __ARM_ARCH__>=7
+ @ ldr r2,[r1],#4 @ 2
+# if 2==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r6,r6,ror#5
+ add r10,r10,r12 @ h+=Maj(a,b,c) from the past
+ eor r0,r0,r6,ror#19 @ Sigma1(e)
+ rev r2,r2
+#else
+ @ ldrb r2,[r1,#3] @ 2
+ add r10,r10,r12 @ h+=Maj(a,b,c) from the past
+ ldrb r12,[r1,#2]
+ ldrb r0,[r1,#1]
+ orr r2,r2,r12,lsl#8
+ ldrb r12,[r1],#4
+ orr r2,r2,r0,lsl#16
+# if 2==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r6,r6,ror#5
+ orr r2,r2,r12,lsl#24
+ eor r0,r0,r6,ror#19 @ Sigma1(e)
+#endif
+ ldr r12,[r14],#4 @ *K256++
+ add r9,r9,r2 @ h+=X[i]
+ str r2,[sp,#2*4]
+ eor r2,r7,r8
+ add r9,r9,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r6
+ add r9,r9,r12 @ h+=K256[i]
+ eor r2,r2,r8 @ Ch(e,f,g)
+ eor r0,r10,r10,ror#11
+ add r9,r9,r2 @ h+=Ch(e,f,g)
+#if 2==31
+ and r12,r12,#0xff
+ cmp r12,#0xf2 @ done?
+#endif
+#if 2<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r12,r10,r11 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#4*4] @ from future BODY_16_xx
+ eor r12,r10,r11 @ a^b, b^c in next round
+ ldr r1,[sp,#1*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r10,ror#20 @ Sigma0(a)
+ and r3,r3,r12 @ (b^c)&=(a^b)
+ add r5,r5,r9 @ d+=h
+ eor r3,r3,r11 @ Maj(a,b,c)
+ add r9,r9,r0,ror#2 @ h+=Sigma0(a)
+ @ add r9,r9,r3 @ h+=Maj(a,b,c)
+#if __ARM_ARCH__>=7
+ @ ldr r2,[r1],#4 @ 3
+# if 3==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r5,r5,ror#5
+ add r9,r9,r3 @ h+=Maj(a,b,c) from the past
+ eor r0,r0,r5,ror#19 @ Sigma1(e)
+ rev r2,r2
+#else
+ @ ldrb r2,[r1,#3] @ 3
+ add r9,r9,r3 @ h+=Maj(a,b,c) from the past
+ ldrb r3,[r1,#2]
+ ldrb r0,[r1,#1]
+ orr r2,r2,r3,lsl#8
+ ldrb r3,[r1],#4
+ orr r2,r2,r0,lsl#16
+# if 3==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r5,r5,ror#5
+ orr r2,r2,r3,lsl#24
+ eor r0,r0,r5,ror#19 @ Sigma1(e)
+#endif
+ ldr r3,[r14],#4 @ *K256++
+ add r8,r8,r2 @ h+=X[i]
+ str r2,[sp,#3*4]
+ eor r2,r6,r7
+ add r8,r8,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r5
+ add r8,r8,r3 @ h+=K256[i]
+ eor r2,r2,r7 @ Ch(e,f,g)
+ eor r0,r9,r9,ror#11
+ add r8,r8,r2 @ h+=Ch(e,f,g)
+#if 3==31
+ and r3,r3,#0xff
+ cmp r3,#0xf2 @ done?
+#endif
+#if 3<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r3,r9,r10 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#5*4] @ from future BODY_16_xx
+ eor r3,r9,r10 @ a^b, b^c in next round
+ ldr r1,[sp,#2*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r9,ror#20 @ Sigma0(a)
+ and r12,r12,r3 @ (b^c)&=(a^b)
+ add r4,r4,r8 @ d+=h
+ eor r12,r12,r10 @ Maj(a,b,c)
+ add r8,r8,r0,ror#2 @ h+=Sigma0(a)
+ @ add r8,r8,r12 @ h+=Maj(a,b,c)
+#if __ARM_ARCH__>=7
+ @ ldr r2,[r1],#4 @ 4
+# if 4==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r4,r4,ror#5
+ add r8,r8,r12 @ h+=Maj(a,b,c) from the past
+ eor r0,r0,r4,ror#19 @ Sigma1(e)
+ rev r2,r2
+#else
+ @ ldrb r2,[r1,#3] @ 4
+ add r8,r8,r12 @ h+=Maj(a,b,c) from the past
+ ldrb r12,[r1,#2]
+ ldrb r0,[r1,#1]
+ orr r2,r2,r12,lsl#8
+ ldrb r12,[r1],#4
+ orr r2,r2,r0,lsl#16
+# if 4==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r4,r4,ror#5
+ orr r2,r2,r12,lsl#24
+ eor r0,r0,r4,ror#19 @ Sigma1(e)
+#endif
+ ldr r12,[r14],#4 @ *K256++
+ add r7,r7,r2 @ h+=X[i]
+ str r2,[sp,#4*4]
+ eor r2,r5,r6
+ add r7,r7,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r4
+ add r7,r7,r12 @ h+=K256[i]
+ eor r2,r2,r6 @ Ch(e,f,g)
+ eor r0,r8,r8,ror#11
+ add r7,r7,r2 @ h+=Ch(e,f,g)
+#if 4==31
+ and r12,r12,#0xff
+ cmp r12,#0xf2 @ done?
+#endif
+#if 4<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r12,r8,r9 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#6*4] @ from future BODY_16_xx
+ eor r12,r8,r9 @ a^b, b^c in next round
+ ldr r1,[sp,#3*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r8,ror#20 @ Sigma0(a)
+ and r3,r3,r12 @ (b^c)&=(a^b)
+ add r11,r11,r7 @ d+=h
+ eor r3,r3,r9 @ Maj(a,b,c)
+ add r7,r7,r0,ror#2 @ h+=Sigma0(a)
+ @ add r7,r7,r3 @ h+=Maj(a,b,c)
+#if __ARM_ARCH__>=7
+ @ ldr r2,[r1],#4 @ 5
+# if 5==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r11,r11,ror#5
+ add r7,r7,r3 @ h+=Maj(a,b,c) from the past
+ eor r0,r0,r11,ror#19 @ Sigma1(e)
+ rev r2,r2
+#else
+ @ ldrb r2,[r1,#3] @ 5
+ add r7,r7,r3 @ h+=Maj(a,b,c) from the past
+ ldrb r3,[r1,#2]
+ ldrb r0,[r1,#1]
+ orr r2,r2,r3,lsl#8
+ ldrb r3,[r1],#4
+ orr r2,r2,r0,lsl#16
+# if 5==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r11,r11,ror#5
+ orr r2,r2,r3,lsl#24
+ eor r0,r0,r11,ror#19 @ Sigma1(e)
+#endif
+ ldr r3,[r14],#4 @ *K256++
+ add r6,r6,r2 @ h+=X[i]
+ str r2,[sp,#5*4]
+ eor r2,r4,r5
+ add r6,r6,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r11
+ add r6,r6,r3 @ h+=K256[i]
+ eor r2,r2,r5 @ Ch(e,f,g)
+ eor r0,r7,r7,ror#11
+ add r6,r6,r2 @ h+=Ch(e,f,g)
+#if 5==31
+ and r3,r3,#0xff
+ cmp r3,#0xf2 @ done?
+#endif
+#if 5<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r3,r7,r8 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#7*4] @ from future BODY_16_xx
+ eor r3,r7,r8 @ a^b, b^c in next round
+ ldr r1,[sp,#4*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r7,ror#20 @ Sigma0(a)
+ and r12,r12,r3 @ (b^c)&=(a^b)
+ add r10,r10,r6 @ d+=h
+ eor r12,r12,r8 @ Maj(a,b,c)
+ add r6,r6,r0,ror#2 @ h+=Sigma0(a)
+ @ add r6,r6,r12 @ h+=Maj(a,b,c)
+#if __ARM_ARCH__>=7
+ @ ldr r2,[r1],#4 @ 6
+# if 6==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r10,r10,ror#5
+ add r6,r6,r12 @ h+=Maj(a,b,c) from the past
+ eor r0,r0,r10,ror#19 @ Sigma1(e)
+ rev r2,r2
+#else
+ @ ldrb r2,[r1,#3] @ 6
+ add r6,r6,r12 @ h+=Maj(a,b,c) from the past
+ ldrb r12,[r1,#2]
+ ldrb r0,[r1,#1]
+ orr r2,r2,r12,lsl#8
+ ldrb r12,[r1],#4
+ orr r2,r2,r0,lsl#16
+# if 6==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r10,r10,ror#5
+ orr r2,r2,r12,lsl#24
+ eor r0,r0,r10,ror#19 @ Sigma1(e)
+#endif
+ ldr r12,[r14],#4 @ *K256++
+ add r5,r5,r2 @ h+=X[i]
+ str r2,[sp,#6*4]
+ eor r2,r11,r4
+ add r5,r5,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r10
+ add r5,r5,r12 @ h+=K256[i]
+ eor r2,r2,r4 @ Ch(e,f,g)
+ eor r0,r6,r6,ror#11
+ add r5,r5,r2 @ h+=Ch(e,f,g)
+#if 6==31
+ and r12,r12,#0xff
+ cmp r12,#0xf2 @ done?
+#endif
+#if 6<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r12,r6,r7 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#8*4] @ from future BODY_16_xx
+ eor r12,r6,r7 @ a^b, b^c in next round
+ ldr r1,[sp,#5*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r6,ror#20 @ Sigma0(a)
+ and r3,r3,r12 @ (b^c)&=(a^b)
+ add r9,r9,r5 @ d+=h
+ eor r3,r3,r7 @ Maj(a,b,c)
+ add r5,r5,r0,ror#2 @ h+=Sigma0(a)
+ @ add r5,r5,r3 @ h+=Maj(a,b,c)
+#if __ARM_ARCH__>=7
+ @ ldr r2,[r1],#4 @ 7
+# if 7==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r9,r9,ror#5
+ add r5,r5,r3 @ h+=Maj(a,b,c) from the past
+ eor r0,r0,r9,ror#19 @ Sigma1(e)
+ rev r2,r2
+#else
+ @ ldrb r2,[r1,#3] @ 7
+ add r5,r5,r3 @ h+=Maj(a,b,c) from the past
+ ldrb r3,[r1,#2]
+ ldrb r0,[r1,#1]
+ orr r2,r2,r3,lsl#8
+ ldrb r3,[r1],#4
+ orr r2,r2,r0,lsl#16
+# if 7==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r9,r9,ror#5
+ orr r2,r2,r3,lsl#24
+ eor r0,r0,r9,ror#19 @ Sigma1(e)
+#endif
+ ldr r3,[r14],#4 @ *K256++
+ add r4,r4,r2 @ h+=X[i]
+ str r2,[sp,#7*4]
+ eor r2,r10,r11
+ add r4,r4,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r9
+ add r4,r4,r3 @ h+=K256[i]
+ eor r2,r2,r11 @ Ch(e,f,g)
+ eor r0,r5,r5,ror#11
+ add r4,r4,r2 @ h+=Ch(e,f,g)
+#if 7==31
+ and r3,r3,#0xff
+ cmp r3,#0xf2 @ done?
+#endif
+#if 7<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r3,r5,r6 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#9*4] @ from future BODY_16_xx
+ eor r3,r5,r6 @ a^b, b^c in next round
+ ldr r1,[sp,#6*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r5,ror#20 @ Sigma0(a)
+ and r12,r12,r3 @ (b^c)&=(a^b)
+ add r8,r8,r4 @ d+=h
+ eor r12,r12,r6 @ Maj(a,b,c)
+ add r4,r4,r0,ror#2 @ h+=Sigma0(a)
+ @ add r4,r4,r12 @ h+=Maj(a,b,c)
+#if __ARM_ARCH__>=7
+ @ ldr r2,[r1],#4 @ 8
+# if 8==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r8,r8,ror#5
+ add r4,r4,r12 @ h+=Maj(a,b,c) from the past
+ eor r0,r0,r8,ror#19 @ Sigma1(e)
+ rev r2,r2
+#else
+ @ ldrb r2,[r1,#3] @ 8
+ add r4,r4,r12 @ h+=Maj(a,b,c) from the past
+ ldrb r12,[r1,#2]
+ ldrb r0,[r1,#1]
+ orr r2,r2,r12,lsl#8
+ ldrb r12,[r1],#4
+ orr r2,r2,r0,lsl#16
+# if 8==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r8,r8,ror#5
+ orr r2,r2,r12,lsl#24
+ eor r0,r0,r8,ror#19 @ Sigma1(e)
+#endif
+ ldr r12,[r14],#4 @ *K256++
+ add r11,r11,r2 @ h+=X[i]
+ str r2,[sp,#8*4]
+ eor r2,r9,r10
+ add r11,r11,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r8
+ add r11,r11,r12 @ h+=K256[i]
+ eor r2,r2,r10 @ Ch(e,f,g)
+ eor r0,r4,r4,ror#11
+ add r11,r11,r2 @ h+=Ch(e,f,g)
+#if 8==31
+ and r12,r12,#0xff
+ cmp r12,#0xf2 @ done?
+#endif
+#if 8<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r12,r4,r5 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#10*4] @ from future BODY_16_xx
+ eor r12,r4,r5 @ a^b, b^c in next round
+ ldr r1,[sp,#7*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r4,ror#20 @ Sigma0(a)
+ and r3,r3,r12 @ (b^c)&=(a^b)
+ add r7,r7,r11 @ d+=h
+ eor r3,r3,r5 @ Maj(a,b,c)
+ add r11,r11,r0,ror#2 @ h+=Sigma0(a)
+ @ add r11,r11,r3 @ h+=Maj(a,b,c)
+#if __ARM_ARCH__>=7
+ @ ldr r2,[r1],#4 @ 9
+# if 9==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r7,r7,ror#5
+ add r11,r11,r3 @ h+=Maj(a,b,c) from the past
+ eor r0,r0,r7,ror#19 @ Sigma1(e)
+ rev r2,r2
+#else
+ @ ldrb r2,[r1,#3] @ 9
+ add r11,r11,r3 @ h+=Maj(a,b,c) from the past
+ ldrb r3,[r1,#2]
+ ldrb r0,[r1,#1]
+ orr r2,r2,r3,lsl#8
+ ldrb r3,[r1],#4
+ orr r2,r2,r0,lsl#16
+# if 9==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r7,r7,ror#5
+ orr r2,r2,r3,lsl#24
+ eor r0,r0,r7,ror#19 @ Sigma1(e)
+#endif
+ ldr r3,[r14],#4 @ *K256++
+ add r10,r10,r2 @ h+=X[i]
+ str r2,[sp,#9*4]
+ eor r2,r8,r9
+ add r10,r10,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r7
+ add r10,r10,r3 @ h+=K256[i]
+ eor r2,r2,r9 @ Ch(e,f,g)
+ eor r0,r11,r11,ror#11
+ add r10,r10,r2 @ h+=Ch(e,f,g)
+#if 9==31
+ and r3,r3,#0xff
+ cmp r3,#0xf2 @ done?
+#endif
+#if 9<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r3,r11,r4 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#11*4] @ from future BODY_16_xx
+ eor r3,r11,r4 @ a^b, b^c in next round
+ ldr r1,[sp,#8*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r11,ror#20 @ Sigma0(a)
+ and r12,r12,r3 @ (b^c)&=(a^b)
+ add r6,r6,r10 @ d+=h
+ eor r12,r12,r4 @ Maj(a,b,c)
+ add r10,r10,r0,ror#2 @ h+=Sigma0(a)
+ @ add r10,r10,r12 @ h+=Maj(a,b,c)
+#if __ARM_ARCH__>=7
+ @ ldr r2,[r1],#4 @ 10
+# if 10==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r6,r6,ror#5
+ add r10,r10,r12 @ h+=Maj(a,b,c) from the past
+ eor r0,r0,r6,ror#19 @ Sigma1(e)
+ rev r2,r2
+#else
+ @ ldrb r2,[r1,#3] @ 10
+ add r10,r10,r12 @ h+=Maj(a,b,c) from the past
+ ldrb r12,[r1,#2]
+ ldrb r0,[r1,#1]
+ orr r2,r2,r12,lsl#8
+ ldrb r12,[r1],#4
+ orr r2,r2,r0,lsl#16
+# if 10==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r6,r6,ror#5
+ orr r2,r2,r12,lsl#24
+ eor r0,r0,r6,ror#19 @ Sigma1(e)
+#endif
+ ldr r12,[r14],#4 @ *K256++
+ add r9,r9,r2 @ h+=X[i]
+ str r2,[sp,#10*4]
+ eor r2,r7,r8
+ add r9,r9,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r6
+ add r9,r9,r12 @ h+=K256[i]
+ eor r2,r2,r8 @ Ch(e,f,g)
+ eor r0,r10,r10,ror#11
+ add r9,r9,r2 @ h+=Ch(e,f,g)
+#if 10==31
+ and r12,r12,#0xff
+ cmp r12,#0xf2 @ done?
+#endif
+#if 10<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r12,r10,r11 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#12*4] @ from future BODY_16_xx
+ eor r12,r10,r11 @ a^b, b^c in next round
+ ldr r1,[sp,#9*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r10,ror#20 @ Sigma0(a)
+ and r3,r3,r12 @ (b^c)&=(a^b)
+ add r5,r5,r9 @ d+=h
+ eor r3,r3,r11 @ Maj(a,b,c)
+ add r9,r9,r0,ror#2 @ h+=Sigma0(a)
+ @ add r9,r9,r3 @ h+=Maj(a,b,c)
+#if __ARM_ARCH__>=7
+ @ ldr r2,[r1],#4 @ 11
+# if 11==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r5,r5,ror#5
+ add r9,r9,r3 @ h+=Maj(a,b,c) from the past
+ eor r0,r0,r5,ror#19 @ Sigma1(e)
+ rev r2,r2
+#else
+ @ ldrb r2,[r1,#3] @ 11
+ add r9,r9,r3 @ h+=Maj(a,b,c) from the past
+ ldrb r3,[r1,#2]
+ ldrb r0,[r1,#1]
+ orr r2,r2,r3,lsl#8
+ ldrb r3,[r1],#4
+ orr r2,r2,r0,lsl#16
+# if 11==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r5,r5,ror#5
+ orr r2,r2,r3,lsl#24
+ eor r0,r0,r5,ror#19 @ Sigma1(e)
+#endif
+ ldr r3,[r14],#4 @ *K256++
+ add r8,r8,r2 @ h+=X[i]
+ str r2,[sp,#11*4]
+ eor r2,r6,r7
+ add r8,r8,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r5
+ add r8,r8,r3 @ h+=K256[i]
+ eor r2,r2,r7 @ Ch(e,f,g)
+ eor r0,r9,r9,ror#11
+ add r8,r8,r2 @ h+=Ch(e,f,g)
+#if 11==31
+ and r3,r3,#0xff
+ cmp r3,#0xf2 @ done?
+#endif
+#if 11<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r3,r9,r10 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#13*4] @ from future BODY_16_xx
+ eor r3,r9,r10 @ a^b, b^c in next round
+ ldr r1,[sp,#10*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r9,ror#20 @ Sigma0(a)
+ and r12,r12,r3 @ (b^c)&=(a^b)
+ add r4,r4,r8 @ d+=h
+ eor r12,r12,r10 @ Maj(a,b,c)
+ add r8,r8,r0,ror#2 @ h+=Sigma0(a)
+ @ add r8,r8,r12 @ h+=Maj(a,b,c)
+#if __ARM_ARCH__>=7
+ @ ldr r2,[r1],#4 @ 12
+# if 12==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r4,r4,ror#5
+ add r8,r8,r12 @ h+=Maj(a,b,c) from the past
+ eor r0,r0,r4,ror#19 @ Sigma1(e)
+ rev r2,r2
+#else
+ @ ldrb r2,[r1,#3] @ 12
+ add r8,r8,r12 @ h+=Maj(a,b,c) from the past
+ ldrb r12,[r1,#2]
+ ldrb r0,[r1,#1]
+ orr r2,r2,r12,lsl#8
+ ldrb r12,[r1],#4
+ orr r2,r2,r0,lsl#16
+# if 12==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r4,r4,ror#5
+ orr r2,r2,r12,lsl#24
+ eor r0,r0,r4,ror#19 @ Sigma1(e)
+#endif
+ ldr r12,[r14],#4 @ *K256++
+ add r7,r7,r2 @ h+=X[i]
+ str r2,[sp,#12*4]
+ eor r2,r5,r6
+ add r7,r7,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r4
+ add r7,r7,r12 @ h+=K256[i]
+ eor r2,r2,r6 @ Ch(e,f,g)
+ eor r0,r8,r8,ror#11
+ add r7,r7,r2 @ h+=Ch(e,f,g)
+#if 12==31
+ and r12,r12,#0xff
+ cmp r12,#0xf2 @ done?
+#endif
+#if 12<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r12,r8,r9 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#14*4] @ from future BODY_16_xx
+ eor r12,r8,r9 @ a^b, b^c in next round
+ ldr r1,[sp,#11*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r8,ror#20 @ Sigma0(a)
+ and r3,r3,r12 @ (b^c)&=(a^b)
+ add r11,r11,r7 @ d+=h
+ eor r3,r3,r9 @ Maj(a,b,c)
+ add r7,r7,r0,ror#2 @ h+=Sigma0(a)
+ @ add r7,r7,r3 @ h+=Maj(a,b,c)
+#if __ARM_ARCH__>=7
+ @ ldr r2,[r1],#4 @ 13
+# if 13==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r11,r11,ror#5
+ add r7,r7,r3 @ h+=Maj(a,b,c) from the past
+ eor r0,r0,r11,ror#19 @ Sigma1(e)
+ rev r2,r2
+#else
+ @ ldrb r2,[r1,#3] @ 13
+ add r7,r7,r3 @ h+=Maj(a,b,c) from the past
+ ldrb r3,[r1,#2]
+ ldrb r0,[r1,#1]
+ orr r2,r2,r3,lsl#8
+ ldrb r3,[r1],#4
+ orr r2,r2,r0,lsl#16
+# if 13==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r11,r11,ror#5
+ orr r2,r2,r3,lsl#24
+ eor r0,r0,r11,ror#19 @ Sigma1(e)
+#endif
+ ldr r3,[r14],#4 @ *K256++
+ add r6,r6,r2 @ h+=X[i]
+ str r2,[sp,#13*4]
+ eor r2,r4,r5
+ add r6,r6,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r11
+ add r6,r6,r3 @ h+=K256[i]
+ eor r2,r2,r5 @ Ch(e,f,g)
+ eor r0,r7,r7,ror#11
+ add r6,r6,r2 @ h+=Ch(e,f,g)
+#if 13==31
+ and r3,r3,#0xff
+ cmp r3,#0xf2 @ done?
+#endif
+#if 13<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r3,r7,r8 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#15*4] @ from future BODY_16_xx
+ eor r3,r7,r8 @ a^b, b^c in next round
+ ldr r1,[sp,#12*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r7,ror#20 @ Sigma0(a)
+ and r12,r12,r3 @ (b^c)&=(a^b)
+ add r10,r10,r6 @ d+=h
+ eor r12,r12,r8 @ Maj(a,b,c)
+ add r6,r6,r0,ror#2 @ h+=Sigma0(a)
+ @ add r6,r6,r12 @ h+=Maj(a,b,c)
+#if __ARM_ARCH__>=7
+ @ ldr r2,[r1],#4 @ 14
+# if 14==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r10,r10,ror#5
+ add r6,r6,r12 @ h+=Maj(a,b,c) from the past
+ eor r0,r0,r10,ror#19 @ Sigma1(e)
+ rev r2,r2
+#else
+ @ ldrb r2,[r1,#3] @ 14
+ add r6,r6,r12 @ h+=Maj(a,b,c) from the past
+ ldrb r12,[r1,#2]
+ ldrb r0,[r1,#1]
+ orr r2,r2,r12,lsl#8
+ ldrb r12,[r1],#4
+ orr r2,r2,r0,lsl#16
+# if 14==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r10,r10,ror#5
+ orr r2,r2,r12,lsl#24
+ eor r0,r0,r10,ror#19 @ Sigma1(e)
+#endif
+ ldr r12,[r14],#4 @ *K256++
+ add r5,r5,r2 @ h+=X[i]
+ str r2,[sp,#14*4]
+ eor r2,r11,r4
+ add r5,r5,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r10
+ add r5,r5,r12 @ h+=K256[i]
+ eor r2,r2,r4 @ Ch(e,f,g)
+ eor r0,r6,r6,ror#11
+ add r5,r5,r2 @ h+=Ch(e,f,g)
+#if 14==31
+ and r12,r12,#0xff
+ cmp r12,#0xf2 @ done?
+#endif
+#if 14<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r12,r6,r7 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#0*4] @ from future BODY_16_xx
+ eor r12,r6,r7 @ a^b, b^c in next round
+ ldr r1,[sp,#13*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r6,ror#20 @ Sigma0(a)
+ and r3,r3,r12 @ (b^c)&=(a^b)
+ add r9,r9,r5 @ d+=h
+ eor r3,r3,r7 @ Maj(a,b,c)
+ add r5,r5,r0,ror#2 @ h+=Sigma0(a)
+ @ add r5,r5,r3 @ h+=Maj(a,b,c)
+#if __ARM_ARCH__>=7
+ @ ldr r2,[r1],#4 @ 15
+# if 15==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r9,r9,ror#5
+ add r5,r5,r3 @ h+=Maj(a,b,c) from the past
+ eor r0,r0,r9,ror#19 @ Sigma1(e)
+ rev r2,r2
+#else
+ @ ldrb r2,[r1,#3] @ 15
+ add r5,r5,r3 @ h+=Maj(a,b,c) from the past
+ ldrb r3,[r1,#2]
+ ldrb r0,[r1,#1]
+ orr r2,r2,r3,lsl#8
+ ldrb r3,[r1],#4
+ orr r2,r2,r0,lsl#16
+# if 15==15
+ str r1,[sp,#17*4] @ make room for r1
+# endif
+ eor r0,r9,r9,ror#5
+ orr r2,r2,r3,lsl#24
+ eor r0,r0,r9,ror#19 @ Sigma1(e)
+#endif
+ ldr r3,[r14],#4 @ *K256++
+ add r4,r4,r2 @ h+=X[i]
+ str r2,[sp,#15*4]
+ eor r2,r10,r11
+ add r4,r4,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r9
+ add r4,r4,r3 @ h+=K256[i]
+ eor r2,r2,r11 @ Ch(e,f,g)
+ eor r0,r5,r5,ror#11
+ add r4,r4,r2 @ h+=Ch(e,f,g)
+#if 15==31
+ and r3,r3,#0xff
+ cmp r3,#0xf2 @ done?
+#endif
+#if 15<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r3,r5,r6 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#1*4] @ from future BODY_16_xx
+ eor r3,r5,r6 @ a^b, b^c in next round
+ ldr r1,[sp,#14*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r5,ror#20 @ Sigma0(a)
+ and r12,r12,r3 @ (b^c)&=(a^b)
+ add r8,r8,r4 @ d+=h
+ eor r12,r12,r6 @ Maj(a,b,c)
+ add r4,r4,r0,ror#2 @ h+=Sigma0(a)
+ @ add r4,r4,r12 @ h+=Maj(a,b,c)
+.Lrounds_16_xx:
+ @ ldr r2,[sp,#1*4] @ 16
+ @ ldr r1,[sp,#14*4]
+ mov r0,r2,ror#7
+ add r4,r4,r12 @ h+=Maj(a,b,c) from the past
+ mov r12,r1,ror#17
+ eor r0,r0,r2,ror#18
+ eor r12,r12,r1,ror#19
+ eor r0,r0,r2,lsr#3 @ sigma0(X[i+1])
+ ldr r2,[sp,#0*4]
+ eor r12,r12,r1,lsr#10 @ sigma1(X[i+14])
+ ldr r1,[sp,#9*4]
+
+ add r12,r12,r0
+ eor r0,r8,r8,ror#5 @ from BODY_00_15
+ add r2,r2,r12
+ eor r0,r0,r8,ror#19 @ Sigma1(e)
+ add r2,r2,r1 @ X[i]
+ ldr r12,[r14],#4 @ *K256++
+ add r11,r11,r2 @ h+=X[i]
+ str r2,[sp,#0*4]
+ eor r2,r9,r10
+ add r11,r11,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r8
+ add r11,r11,r12 @ h+=K256[i]
+ eor r2,r2,r10 @ Ch(e,f,g)
+ eor r0,r4,r4,ror#11
+ add r11,r11,r2 @ h+=Ch(e,f,g)
+#if 16==31
+ and r12,r12,#0xff
+ cmp r12,#0xf2 @ done?
+#endif
+#if 16<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r12,r4,r5 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#2*4] @ from future BODY_16_xx
+ eor r12,r4,r5 @ a^b, b^c in next round
+ ldr r1,[sp,#15*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r4,ror#20 @ Sigma0(a)
+ and r3,r3,r12 @ (b^c)&=(a^b)
+ add r7,r7,r11 @ d+=h
+ eor r3,r3,r5 @ Maj(a,b,c)
+ add r11,r11,r0,ror#2 @ h+=Sigma0(a)
+ @ add r11,r11,r3 @ h+=Maj(a,b,c)
+ @ ldr r2,[sp,#2*4] @ 17
+ @ ldr r1,[sp,#15*4]
+ mov r0,r2,ror#7
+ add r11,r11,r3 @ h+=Maj(a,b,c) from the past
+ mov r3,r1,ror#17
+ eor r0,r0,r2,ror#18
+ eor r3,r3,r1,ror#19
+ eor r0,r0,r2,lsr#3 @ sigma0(X[i+1])
+ ldr r2,[sp,#1*4]
+ eor r3,r3,r1,lsr#10 @ sigma1(X[i+14])
+ ldr r1,[sp,#10*4]
+
+ add r3,r3,r0
+ eor r0,r7,r7,ror#5 @ from BODY_00_15
+ add r2,r2,r3
+ eor r0,r0,r7,ror#19 @ Sigma1(e)
+ add r2,r2,r1 @ X[i]
+ ldr r3,[r14],#4 @ *K256++
+ add r10,r10,r2 @ h+=X[i]
+ str r2,[sp,#1*4]
+ eor r2,r8,r9
+ add r10,r10,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r7
+ add r10,r10,r3 @ h+=K256[i]
+ eor r2,r2,r9 @ Ch(e,f,g)
+ eor r0,r11,r11,ror#11
+ add r10,r10,r2 @ h+=Ch(e,f,g)
+#if 17==31
+ and r3,r3,#0xff
+ cmp r3,#0xf2 @ done?
+#endif
+#if 17<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r3,r11,r4 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#3*4] @ from future BODY_16_xx
+ eor r3,r11,r4 @ a^b, b^c in next round
+ ldr r1,[sp,#0*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r11,ror#20 @ Sigma0(a)
+ and r12,r12,r3 @ (b^c)&=(a^b)
+ add r6,r6,r10 @ d+=h
+ eor r12,r12,r4 @ Maj(a,b,c)
+ add r10,r10,r0,ror#2 @ h+=Sigma0(a)
+ @ add r10,r10,r12 @ h+=Maj(a,b,c)
+ @ ldr r2,[sp,#3*4] @ 18
+ @ ldr r1,[sp,#0*4]
+ mov r0,r2,ror#7
+ add r10,r10,r12 @ h+=Maj(a,b,c) from the past
+ mov r12,r1,ror#17
+ eor r0,r0,r2,ror#18
+ eor r12,r12,r1,ror#19
+ eor r0,r0,r2,lsr#3 @ sigma0(X[i+1])
+ ldr r2,[sp,#2*4]
+ eor r12,r12,r1,lsr#10 @ sigma1(X[i+14])
+ ldr r1,[sp,#11*4]
+
+ add r12,r12,r0
+ eor r0,r6,r6,ror#5 @ from BODY_00_15
+ add r2,r2,r12
+ eor r0,r0,r6,ror#19 @ Sigma1(e)
+ add r2,r2,r1 @ X[i]
+ ldr r12,[r14],#4 @ *K256++
+ add r9,r9,r2 @ h+=X[i]
+ str r2,[sp,#2*4]
+ eor r2,r7,r8
+ add r9,r9,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r6
+ add r9,r9,r12 @ h+=K256[i]
+ eor r2,r2,r8 @ Ch(e,f,g)
+ eor r0,r10,r10,ror#11
+ add r9,r9,r2 @ h+=Ch(e,f,g)
+#if 18==31
+ and r12,r12,#0xff
+ cmp r12,#0xf2 @ done?
+#endif
+#if 18<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r12,r10,r11 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#4*4] @ from future BODY_16_xx
+ eor r12,r10,r11 @ a^b, b^c in next round
+ ldr r1,[sp,#1*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r10,ror#20 @ Sigma0(a)
+ and r3,r3,r12 @ (b^c)&=(a^b)
+ add r5,r5,r9 @ d+=h
+ eor r3,r3,r11 @ Maj(a,b,c)
+ add r9,r9,r0,ror#2 @ h+=Sigma0(a)
+ @ add r9,r9,r3 @ h+=Maj(a,b,c)
+ @ ldr r2,[sp,#4*4] @ 19
+ @ ldr r1,[sp,#1*4]
+ mov r0,r2,ror#7
+ add r9,r9,r3 @ h+=Maj(a,b,c) from the past
+ mov r3,r1,ror#17
+ eor r0,r0,r2,ror#18
+ eor r3,r3,r1,ror#19
+ eor r0,r0,r2,lsr#3 @ sigma0(X[i+1])
+ ldr r2,[sp,#3*4]
+ eor r3,r3,r1,lsr#10 @ sigma1(X[i+14])
+ ldr r1,[sp,#12*4]
+
+ add r3,r3,r0
+ eor r0,r5,r5,ror#5 @ from BODY_00_15
+ add r2,r2,r3
+ eor r0,r0,r5,ror#19 @ Sigma1(e)
+ add r2,r2,r1 @ X[i]
+ ldr r3,[r14],#4 @ *K256++
+ add r8,r8,r2 @ h+=X[i]
+ str r2,[sp,#3*4]
+ eor r2,r6,r7
+ add r8,r8,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r5
+ add r8,r8,r3 @ h+=K256[i]
+ eor r2,r2,r7 @ Ch(e,f,g)
+ eor r0,r9,r9,ror#11
+ add r8,r8,r2 @ h+=Ch(e,f,g)
+#if 19==31
+ and r3,r3,#0xff
+ cmp r3,#0xf2 @ done?
+#endif
+#if 19<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r3,r9,r10 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#5*4] @ from future BODY_16_xx
+ eor r3,r9,r10 @ a^b, b^c in next round
+ ldr r1,[sp,#2*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r9,ror#20 @ Sigma0(a)
+ and r12,r12,r3 @ (b^c)&=(a^b)
+ add r4,r4,r8 @ d+=h
+ eor r12,r12,r10 @ Maj(a,b,c)
+ add r8,r8,r0,ror#2 @ h+=Sigma0(a)
+ @ add r8,r8,r12 @ h+=Maj(a,b,c)
+ @ ldr r2,[sp,#5*4] @ 20
+ @ ldr r1,[sp,#2*4]
+ mov r0,r2,ror#7
+ add r8,r8,r12 @ h+=Maj(a,b,c) from the past
+ mov r12,r1,ror#17
+ eor r0,r0,r2,ror#18
+ eor r12,r12,r1,ror#19
+ eor r0,r0,r2,lsr#3 @ sigma0(X[i+1])
+ ldr r2,[sp,#4*4]
+ eor r12,r12,r1,lsr#10 @ sigma1(X[i+14])
+ ldr r1,[sp,#13*4]
+
+ add r12,r12,r0
+ eor r0,r4,r4,ror#5 @ from BODY_00_15
+ add r2,r2,r12
+ eor r0,r0,r4,ror#19 @ Sigma1(e)
+ add r2,r2,r1 @ X[i]
+ ldr r12,[r14],#4 @ *K256++
+ add r7,r7,r2 @ h+=X[i]
+ str r2,[sp,#4*4]
+ eor r2,r5,r6
+ add r7,r7,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r4
+ add r7,r7,r12 @ h+=K256[i]
+ eor r2,r2,r6 @ Ch(e,f,g)
+ eor r0,r8,r8,ror#11
+ add r7,r7,r2 @ h+=Ch(e,f,g)
+#if 20==31
+ and r12,r12,#0xff
+ cmp r12,#0xf2 @ done?
+#endif
+#if 20<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r12,r8,r9 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#6*4] @ from future BODY_16_xx
+ eor r12,r8,r9 @ a^b, b^c in next round
+ ldr r1,[sp,#3*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r8,ror#20 @ Sigma0(a)
+ and r3,r3,r12 @ (b^c)&=(a^b)
+ add r11,r11,r7 @ d+=h
+ eor r3,r3,r9 @ Maj(a,b,c)
+ add r7,r7,r0,ror#2 @ h+=Sigma0(a)
+ @ add r7,r7,r3 @ h+=Maj(a,b,c)
+ @ ldr r2,[sp,#6*4] @ 21
+ @ ldr r1,[sp,#3*4]
+ mov r0,r2,ror#7
+ add r7,r7,r3 @ h+=Maj(a,b,c) from the past
+ mov r3,r1,ror#17
+ eor r0,r0,r2,ror#18
+ eor r3,r3,r1,ror#19
+ eor r0,r0,r2,lsr#3 @ sigma0(X[i+1])
+ ldr r2,[sp,#5*4]
+ eor r3,r3,r1,lsr#10 @ sigma1(X[i+14])
+ ldr r1,[sp,#14*4]
+
+ add r3,r3,r0
+ eor r0,r11,r11,ror#5 @ from BODY_00_15
+ add r2,r2,r3
+ eor r0,r0,r11,ror#19 @ Sigma1(e)
+ add r2,r2,r1 @ X[i]
+ ldr r3,[r14],#4 @ *K256++
+ add r6,r6,r2 @ h+=X[i]
+ str r2,[sp,#5*4]
+ eor r2,r4,r5
+ add r6,r6,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r11
+ add r6,r6,r3 @ h+=K256[i]
+ eor r2,r2,r5 @ Ch(e,f,g)
+ eor r0,r7,r7,ror#11
+ add r6,r6,r2 @ h+=Ch(e,f,g)
+#if 21==31
+ and r3,r3,#0xff
+ cmp r3,#0xf2 @ done?
+#endif
+#if 21<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r3,r7,r8 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#7*4] @ from future BODY_16_xx
+ eor r3,r7,r8 @ a^b, b^c in next round
+ ldr r1,[sp,#4*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r7,ror#20 @ Sigma0(a)
+ and r12,r12,r3 @ (b^c)&=(a^b)
+ add r10,r10,r6 @ d+=h
+ eor r12,r12,r8 @ Maj(a,b,c)
+ add r6,r6,r0,ror#2 @ h+=Sigma0(a)
+ @ add r6,r6,r12 @ h+=Maj(a,b,c)
+ @ ldr r2,[sp,#7*4] @ 22
+ @ ldr r1,[sp,#4*4]
+ mov r0,r2,ror#7
+ add r6,r6,r12 @ h+=Maj(a,b,c) from the past
+ mov r12,r1,ror#17
+ eor r0,r0,r2,ror#18
+ eor r12,r12,r1,ror#19
+ eor r0,r0,r2,lsr#3 @ sigma0(X[i+1])
+ ldr r2,[sp,#6*4]
+ eor r12,r12,r1,lsr#10 @ sigma1(X[i+14])
+ ldr r1,[sp,#15*4]
+
+ add r12,r12,r0
+ eor r0,r10,r10,ror#5 @ from BODY_00_15
+ add r2,r2,r12
+ eor r0,r0,r10,ror#19 @ Sigma1(e)
+ add r2,r2,r1 @ X[i]
+ ldr r12,[r14],#4 @ *K256++
+ add r5,r5,r2 @ h+=X[i]
+ str r2,[sp,#6*4]
+ eor r2,r11,r4
+ add r5,r5,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r10
+ add r5,r5,r12 @ h+=K256[i]
+ eor r2,r2,r4 @ Ch(e,f,g)
+ eor r0,r6,r6,ror#11
+ add r5,r5,r2 @ h+=Ch(e,f,g)
+#if 22==31
+ and r12,r12,#0xff
+ cmp r12,#0xf2 @ done?
+#endif
+#if 22<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r12,r6,r7 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#8*4] @ from future BODY_16_xx
+ eor r12,r6,r7 @ a^b, b^c in next round
+ ldr r1,[sp,#5*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r6,ror#20 @ Sigma0(a)
+ and r3,r3,r12 @ (b^c)&=(a^b)
+ add r9,r9,r5 @ d+=h
+ eor r3,r3,r7 @ Maj(a,b,c)
+ add r5,r5,r0,ror#2 @ h+=Sigma0(a)
+ @ add r5,r5,r3 @ h+=Maj(a,b,c)
+ @ ldr r2,[sp,#8*4] @ 23
+ @ ldr r1,[sp,#5*4]
+ mov r0,r2,ror#7
+ add r5,r5,r3 @ h+=Maj(a,b,c) from the past
+ mov r3,r1,ror#17
+ eor r0,r0,r2,ror#18
+ eor r3,r3,r1,ror#19
+ eor r0,r0,r2,lsr#3 @ sigma0(X[i+1])
+ ldr r2,[sp,#7*4]
+ eor r3,r3,r1,lsr#10 @ sigma1(X[i+14])
+ ldr r1,[sp,#0*4]
+
+ add r3,r3,r0
+ eor r0,r9,r9,ror#5 @ from BODY_00_15
+ add r2,r2,r3
+ eor r0,r0,r9,ror#19 @ Sigma1(e)
+ add r2,r2,r1 @ X[i]
+ ldr r3,[r14],#4 @ *K256++
+ add r4,r4,r2 @ h+=X[i]
+ str r2,[sp,#7*4]
+ eor r2,r10,r11
+ add r4,r4,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r9
+ add r4,r4,r3 @ h+=K256[i]
+ eor r2,r2,r11 @ Ch(e,f,g)
+ eor r0,r5,r5,ror#11
+ add r4,r4,r2 @ h+=Ch(e,f,g)
+#if 23==31
+ and r3,r3,#0xff
+ cmp r3,#0xf2 @ done?
+#endif
+#if 23<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r3,r5,r6 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#9*4] @ from future BODY_16_xx
+ eor r3,r5,r6 @ a^b, b^c in next round
+ ldr r1,[sp,#6*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r5,ror#20 @ Sigma0(a)
+ and r12,r12,r3 @ (b^c)&=(a^b)
+ add r8,r8,r4 @ d+=h
+ eor r12,r12,r6 @ Maj(a,b,c)
+ add r4,r4,r0,ror#2 @ h+=Sigma0(a)
+ @ add r4,r4,r12 @ h+=Maj(a,b,c)
+ @ ldr r2,[sp,#9*4] @ 24
+ @ ldr r1,[sp,#6*4]
+ mov r0,r2,ror#7
+ add r4,r4,r12 @ h+=Maj(a,b,c) from the past
+ mov r12,r1,ror#17
+ eor r0,r0,r2,ror#18
+ eor r12,r12,r1,ror#19
+ eor r0,r0,r2,lsr#3 @ sigma0(X[i+1])
+ ldr r2,[sp,#8*4]
+ eor r12,r12,r1,lsr#10 @ sigma1(X[i+14])
+ ldr r1,[sp,#1*4]
+
+ add r12,r12,r0
+ eor r0,r8,r8,ror#5 @ from BODY_00_15
+ add r2,r2,r12
+ eor r0,r0,r8,ror#19 @ Sigma1(e)
+ add r2,r2,r1 @ X[i]
+ ldr r12,[r14],#4 @ *K256++
+ add r11,r11,r2 @ h+=X[i]
+ str r2,[sp,#8*4]
+ eor r2,r9,r10
+ add r11,r11,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r8
+ add r11,r11,r12 @ h+=K256[i]
+ eor r2,r2,r10 @ Ch(e,f,g)
+ eor r0,r4,r4,ror#11
+ add r11,r11,r2 @ h+=Ch(e,f,g)
+#if 24==31
+ and r12,r12,#0xff
+ cmp r12,#0xf2 @ done?
+#endif
+#if 24<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r12,r4,r5 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#10*4] @ from future BODY_16_xx
+ eor r12,r4,r5 @ a^b, b^c in next round
+ ldr r1,[sp,#7*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r4,ror#20 @ Sigma0(a)
+ and r3,r3,r12 @ (b^c)&=(a^b)
+ add r7,r7,r11 @ d+=h
+ eor r3,r3,r5 @ Maj(a,b,c)
+ add r11,r11,r0,ror#2 @ h+=Sigma0(a)
+ @ add r11,r11,r3 @ h+=Maj(a,b,c)
+ @ ldr r2,[sp,#10*4] @ 25
+ @ ldr r1,[sp,#7*4]
+ mov r0,r2,ror#7
+ add r11,r11,r3 @ h+=Maj(a,b,c) from the past
+ mov r3,r1,ror#17
+ eor r0,r0,r2,ror#18
+ eor r3,r3,r1,ror#19
+ eor r0,r0,r2,lsr#3 @ sigma0(X[i+1])
+ ldr r2,[sp,#9*4]
+ eor r3,r3,r1,lsr#10 @ sigma1(X[i+14])
+ ldr r1,[sp,#2*4]
+
+ add r3,r3,r0
+ eor r0,r7,r7,ror#5 @ from BODY_00_15
+ add r2,r2,r3
+ eor r0,r0,r7,ror#19 @ Sigma1(e)
+ add r2,r2,r1 @ X[i]
+ ldr r3,[r14],#4 @ *K256++
+ add r10,r10,r2 @ h+=X[i]
+ str r2,[sp,#9*4]
+ eor r2,r8,r9
+ add r10,r10,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r7
+ add r10,r10,r3 @ h+=K256[i]
+ eor r2,r2,r9 @ Ch(e,f,g)
+ eor r0,r11,r11,ror#11
+ add r10,r10,r2 @ h+=Ch(e,f,g)
+#if 25==31
+ and r3,r3,#0xff
+ cmp r3,#0xf2 @ done?
+#endif
+#if 25<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r3,r11,r4 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#11*4] @ from future BODY_16_xx
+ eor r3,r11,r4 @ a^b, b^c in next round
+ ldr r1,[sp,#8*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r11,ror#20 @ Sigma0(a)
+ and r12,r12,r3 @ (b^c)&=(a^b)
+ add r6,r6,r10 @ d+=h
+ eor r12,r12,r4 @ Maj(a,b,c)
+ add r10,r10,r0,ror#2 @ h+=Sigma0(a)
+ @ add r10,r10,r12 @ h+=Maj(a,b,c)
+ @ ldr r2,[sp,#11*4] @ 26
+ @ ldr r1,[sp,#8*4]
+ mov r0,r2,ror#7
+ add r10,r10,r12 @ h+=Maj(a,b,c) from the past
+ mov r12,r1,ror#17
+ eor r0,r0,r2,ror#18
+ eor r12,r12,r1,ror#19
+ eor r0,r0,r2,lsr#3 @ sigma0(X[i+1])
+ ldr r2,[sp,#10*4]
+ eor r12,r12,r1,lsr#10 @ sigma1(X[i+14])
+ ldr r1,[sp,#3*4]
+
+ add r12,r12,r0
+ eor r0,r6,r6,ror#5 @ from BODY_00_15
+ add r2,r2,r12
+ eor r0,r0,r6,ror#19 @ Sigma1(e)
+ add r2,r2,r1 @ X[i]
+ ldr r12,[r14],#4 @ *K256++
+ add r9,r9,r2 @ h+=X[i]
+ str r2,[sp,#10*4]
+ eor r2,r7,r8
+ add r9,r9,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r6
+ add r9,r9,r12 @ h+=K256[i]
+ eor r2,r2,r8 @ Ch(e,f,g)
+ eor r0,r10,r10,ror#11
+ add r9,r9,r2 @ h+=Ch(e,f,g)
+#if 26==31
+ and r12,r12,#0xff
+ cmp r12,#0xf2 @ done?
+#endif
+#if 26<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r12,r10,r11 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#12*4] @ from future BODY_16_xx
+ eor r12,r10,r11 @ a^b, b^c in next round
+ ldr r1,[sp,#9*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r10,ror#20 @ Sigma0(a)
+ and r3,r3,r12 @ (b^c)&=(a^b)
+ add r5,r5,r9 @ d+=h
+ eor r3,r3,r11 @ Maj(a,b,c)
+ add r9,r9,r0,ror#2 @ h+=Sigma0(a)
+ @ add r9,r9,r3 @ h+=Maj(a,b,c)
+ @ ldr r2,[sp,#12*4] @ 27
+ @ ldr r1,[sp,#9*4]
+ mov r0,r2,ror#7
+ add r9,r9,r3 @ h+=Maj(a,b,c) from the past
+ mov r3,r1,ror#17
+ eor r0,r0,r2,ror#18
+ eor r3,r3,r1,ror#19
+ eor r0,r0,r2,lsr#3 @ sigma0(X[i+1])
+ ldr r2,[sp,#11*4]
+ eor r3,r3,r1,lsr#10 @ sigma1(X[i+14])
+ ldr r1,[sp,#4*4]
+
+ add r3,r3,r0
+ eor r0,r5,r5,ror#5 @ from BODY_00_15
+ add r2,r2,r3
+ eor r0,r0,r5,ror#19 @ Sigma1(e)
+ add r2,r2,r1 @ X[i]
+ ldr r3,[r14],#4 @ *K256++
+ add r8,r8,r2 @ h+=X[i]
+ str r2,[sp,#11*4]
+ eor r2,r6,r7
+ add r8,r8,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r5
+ add r8,r8,r3 @ h+=K256[i]
+ eor r2,r2,r7 @ Ch(e,f,g)
+ eor r0,r9,r9,ror#11
+ add r8,r8,r2 @ h+=Ch(e,f,g)
+#if 27==31
+ and r3,r3,#0xff
+ cmp r3,#0xf2 @ done?
+#endif
+#if 27<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r3,r9,r10 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#13*4] @ from future BODY_16_xx
+ eor r3,r9,r10 @ a^b, b^c in next round
+ ldr r1,[sp,#10*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r9,ror#20 @ Sigma0(a)
+ and r12,r12,r3 @ (b^c)&=(a^b)
+ add r4,r4,r8 @ d+=h
+ eor r12,r12,r10 @ Maj(a,b,c)
+ add r8,r8,r0,ror#2 @ h+=Sigma0(a)
+ @ add r8,r8,r12 @ h+=Maj(a,b,c)
+ @ ldr r2,[sp,#13*4] @ 28
+ @ ldr r1,[sp,#10*4]
+ mov r0,r2,ror#7
+ add r8,r8,r12 @ h+=Maj(a,b,c) from the past
+ mov r12,r1,ror#17
+ eor r0,r0,r2,ror#18
+ eor r12,r12,r1,ror#19
+ eor r0,r0,r2,lsr#3 @ sigma0(X[i+1])
+ ldr r2,[sp,#12*4]
+ eor r12,r12,r1,lsr#10 @ sigma1(X[i+14])
+ ldr r1,[sp,#5*4]
+
+ add r12,r12,r0
+ eor r0,r4,r4,ror#5 @ from BODY_00_15
+ add r2,r2,r12
+ eor r0,r0,r4,ror#19 @ Sigma1(e)
+ add r2,r2,r1 @ X[i]
+ ldr r12,[r14],#4 @ *K256++
+ add r7,r7,r2 @ h+=X[i]
+ str r2,[sp,#12*4]
+ eor r2,r5,r6
+ add r7,r7,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r4
+ add r7,r7,r12 @ h+=K256[i]
+ eor r2,r2,r6 @ Ch(e,f,g)
+ eor r0,r8,r8,ror#11
+ add r7,r7,r2 @ h+=Ch(e,f,g)
+#if 28==31
+ and r12,r12,#0xff
+ cmp r12,#0xf2 @ done?
+#endif
+#if 28<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r12,r8,r9 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#14*4] @ from future BODY_16_xx
+ eor r12,r8,r9 @ a^b, b^c in next round
+ ldr r1,[sp,#11*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r8,ror#20 @ Sigma0(a)
+ and r3,r3,r12 @ (b^c)&=(a^b)
+ add r11,r11,r7 @ d+=h
+ eor r3,r3,r9 @ Maj(a,b,c)
+ add r7,r7,r0,ror#2 @ h+=Sigma0(a)
+ @ add r7,r7,r3 @ h+=Maj(a,b,c)
+ @ ldr r2,[sp,#14*4] @ 29
+ @ ldr r1,[sp,#11*4]
+ mov r0,r2,ror#7
+ add r7,r7,r3 @ h+=Maj(a,b,c) from the past
+ mov r3,r1,ror#17
+ eor r0,r0,r2,ror#18
+ eor r3,r3,r1,ror#19
+ eor r0,r0,r2,lsr#3 @ sigma0(X[i+1])
+ ldr r2,[sp,#13*4]
+ eor r3,r3,r1,lsr#10 @ sigma1(X[i+14])
+ ldr r1,[sp,#6*4]
+
+ add r3,r3,r0
+ eor r0,r11,r11,ror#5 @ from BODY_00_15
+ add r2,r2,r3
+ eor r0,r0,r11,ror#19 @ Sigma1(e)
+ add r2,r2,r1 @ X[i]
+ ldr r3,[r14],#4 @ *K256++
+ add r6,r6,r2 @ h+=X[i]
+ str r2,[sp,#13*4]
+ eor r2,r4,r5
+ add r6,r6,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r11
+ add r6,r6,r3 @ h+=K256[i]
+ eor r2,r2,r5 @ Ch(e,f,g)
+ eor r0,r7,r7,ror#11
+ add r6,r6,r2 @ h+=Ch(e,f,g)
+#if 29==31
+ and r3,r3,#0xff
+ cmp r3,#0xf2 @ done?
+#endif
+#if 29<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r3,r7,r8 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#15*4] @ from future BODY_16_xx
+ eor r3,r7,r8 @ a^b, b^c in next round
+ ldr r1,[sp,#12*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r7,ror#20 @ Sigma0(a)
+ and r12,r12,r3 @ (b^c)&=(a^b)
+ add r10,r10,r6 @ d+=h
+ eor r12,r12,r8 @ Maj(a,b,c)
+ add r6,r6,r0,ror#2 @ h+=Sigma0(a)
+ @ add r6,r6,r12 @ h+=Maj(a,b,c)
+ @ ldr r2,[sp,#15*4] @ 30
+ @ ldr r1,[sp,#12*4]
+ mov r0,r2,ror#7
+ add r6,r6,r12 @ h+=Maj(a,b,c) from the past
+ mov r12,r1,ror#17
+ eor r0,r0,r2,ror#18
+ eor r12,r12,r1,ror#19
+ eor r0,r0,r2,lsr#3 @ sigma0(X[i+1])
+ ldr r2,[sp,#14*4]
+ eor r12,r12,r1,lsr#10 @ sigma1(X[i+14])
+ ldr r1,[sp,#7*4]
+
+ add r12,r12,r0
+ eor r0,r10,r10,ror#5 @ from BODY_00_15
+ add r2,r2,r12
+ eor r0,r0,r10,ror#19 @ Sigma1(e)
+ add r2,r2,r1 @ X[i]
+ ldr r12,[r14],#4 @ *K256++
+ add r5,r5,r2 @ h+=X[i]
+ str r2,[sp,#14*4]
+ eor r2,r11,r4
+ add r5,r5,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r10
+ add r5,r5,r12 @ h+=K256[i]
+ eor r2,r2,r4 @ Ch(e,f,g)
+ eor r0,r6,r6,ror#11
+ add r5,r5,r2 @ h+=Ch(e,f,g)
+#if 30==31
+ and r12,r12,#0xff
+ cmp r12,#0xf2 @ done?
+#endif
+#if 30<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r12,r6,r7 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#0*4] @ from future BODY_16_xx
+ eor r12,r6,r7 @ a^b, b^c in next round
+ ldr r1,[sp,#13*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r6,ror#20 @ Sigma0(a)
+ and r3,r3,r12 @ (b^c)&=(a^b)
+ add r9,r9,r5 @ d+=h
+ eor r3,r3,r7 @ Maj(a,b,c)
+ add r5,r5,r0,ror#2 @ h+=Sigma0(a)
+ @ add r5,r5,r3 @ h+=Maj(a,b,c)
+ @ ldr r2,[sp,#0*4] @ 31
+ @ ldr r1,[sp,#13*4]
+ mov r0,r2,ror#7
+ add r5,r5,r3 @ h+=Maj(a,b,c) from the past
+ mov r3,r1,ror#17
+ eor r0,r0,r2,ror#18
+ eor r3,r3,r1,ror#19
+ eor r0,r0,r2,lsr#3 @ sigma0(X[i+1])
+ ldr r2,[sp,#15*4]
+ eor r3,r3,r1,lsr#10 @ sigma1(X[i+14])
+ ldr r1,[sp,#8*4]
+
+ add r3,r3,r0
+ eor r0,r9,r9,ror#5 @ from BODY_00_15
+ add r2,r2,r3
+ eor r0,r0,r9,ror#19 @ Sigma1(e)
+ add r2,r2,r1 @ X[i]
+ ldr r3,[r14],#4 @ *K256++
+ add r4,r4,r2 @ h+=X[i]
+ str r2,[sp,#15*4]
+ eor r2,r10,r11
+ add r4,r4,r0,ror#6 @ h+=Sigma1(e)
+ and r2,r2,r9
+ add r4,r4,r3 @ h+=K256[i]
+ eor r2,r2,r11 @ Ch(e,f,g)
+ eor r0,r5,r5,ror#11
+ add r4,r4,r2 @ h+=Ch(e,f,g)
+#if 31==31
+ and r3,r3,#0xff
+ cmp r3,#0xf2 @ done?
+#endif
+#if 31<15
+# if __ARM_ARCH__>=7
+ ldr r2,[r1],#4 @ prefetch
+# else
+ ldrb r2,[r1,#3]
+# endif
+ eor r3,r5,r6 @ a^b, b^c in next round
+#else
+ ldr r2,[sp,#1*4] @ from future BODY_16_xx
+ eor r3,r5,r6 @ a^b, b^c in next round
+ ldr r1,[sp,#14*4] @ from future BODY_16_xx
+#endif
+ eor r0,r0,r5,ror#20 @ Sigma0(a)
+ and r12,r12,r3 @ (b^c)&=(a^b)
+ add r8,r8,r4 @ d+=h
+ eor r12,r12,r6 @ Maj(a,b,c)
+ add r4,r4,r0,ror#2 @ h+=Sigma0(a)
+ @ add r4,r4,r12 @ h+=Maj(a,b,c)
+ ldreq r3,[sp,#16*4] @ pull ctx
+ bne .Lrounds_16_xx
+
+ add r4,r4,r12 @ h+=Maj(a,b,c) from the past
+ 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
+#if __ARM_MAX_ARCH__>=7
+.arch armv7-a
+.fpu neon
+
+.type sha256_block_data_order_neon,%function
+.align 4
+sha256_block_data_order_neon:
+.LNEON:
+ stmdb sp!,{r4-r12,lr}
+
+ mov r12,sp
+ sub sp,sp,#16*4+16 @ alloca
+ sub r14,r3,#256+32 @ K256
+ bic sp,sp,#15 @ align for 128-bit stores
+
+ vld1.8 {q0},[r1]!
+ vld1.8 {q1},[r1]!
+ vld1.8 {q2},[r1]!
+ vld1.8 {q3},[r1]!
+ vld1.32 {q8},[r14,:128]!
+ vld1.32 {q9},[r14,:128]!
+ vld1.32 {q10},[r14,:128]!
+ vld1.32 {q11},[r14,:128]!
+ vrev32.8 q0,q0 @ yes, even on
+ str r0,[sp,#64]
+ vrev32.8 q1,q1 @ big-endian
+ str r1,[sp,#68]
+ mov r1,sp
+ vrev32.8 q2,q2
+ str r2,[sp,#72]
+ vrev32.8 q3,q3
+ str r12,[sp,#76] @ save original sp
+ vadd.i32 q8,q8,q0
+ vadd.i32 q9,q9,q1
+ vst1.32 {q8},[r1,:128]!
+ vadd.i32 q10,q10,q2
+ vst1.32 {q9},[r1,:128]!
+ vadd.i32 q11,q11,q3
+ vst1.32 {q10},[r1,:128]!
+ vst1.32 {q11},[r1,:128]!
+
+ ldmia r0,{r4-r11}
+ sub r1,r1,#64
+ ldr r2,[sp,#0]
+ eor r12,r12,r12
+ eor r3,r5,r6
+ b .L_00_48
+
+.align 4
+.L_00_48:
+ vext.8 q8,q0,q1,#4
+ add r11,r11,r2
+ eor r2,r9,r10
+ eor r0,r8,r8,ror#5
+ vext.8 q9,q2,q3,#4
+ add r4,r4,r12
+ and r2,r2,r8
+ eor r12,r0,r8,ror#19
+ vshr.u32 q10,q8,#7
+ eor r0,r4,r4,ror#11
+ eor r2,r2,r10
+ vadd.i32 q0,q0,q9
+ add r11,r11,r12,ror#6
+ eor r12,r4,r5
+ vshr.u32 q9,q8,#3
+ eor r0,r0,r4,ror#20
+ add r11,r11,r2
+ vsli.32 q10,q8,#25
+ ldr r2,[sp,#4]
+ and r3,r3,r12
+ vshr.u32 q11,q8,#18
+ add r7,r7,r11
+ add r11,r11,r0,ror#2
+ eor r3,r3,r5
+ veor q9,q9,q10
+ add r10,r10,r2
+ vsli.32 q11,q8,#14
+ eor r2,r8,r9
+ eor r0,r7,r7,ror#5
+ vshr.u32 d24,d7,#17
+ add r11,r11,r3
+ and r2,r2,r7
+ veor q9,q9,q11
+ eor r3,r0,r7,ror#19
+ eor r0,r11,r11,ror#11
+ vsli.32 d24,d7,#15
+ eor r2,r2,r9
+ add r10,r10,r3,ror#6
+ vshr.u32 d25,d7,#10
+ eor r3,r11,r4
+ eor r0,r0,r11,ror#20
+ vadd.i32 q0,q0,q9
+ add r10,r10,r2
+ ldr r2,[sp,#8]
+ veor d25,d25,d24
+ and r12,r12,r3
+ add r6,r6,r10
+ vshr.u32 d24,d7,#19
+ add r10,r10,r0,ror#2
+ eor r12,r12,r4
+ vsli.32 d24,d7,#13
+ add r9,r9,r2
+ eor r2,r7,r8
+ veor d25,d25,d24
+ eor r0,r6,r6,ror#5
+ add r10,r10,r12
+ vadd.i32 d0,d0,d25
+ and r2,r2,r6
+ eor r12,r0,r6,ror#19
+ vshr.u32 d24,d0,#17
+ eor r0,r10,r10,ror#11
+ eor r2,r2,r8
+ vsli.32 d24,d0,#15
+ add r9,r9,r12,ror#6
+ eor r12,r10,r11
+ vshr.u32 d25,d0,#10
+ eor r0,r0,r10,ror#20
+ add r9,r9,r2
+ veor d25,d25,d24
+ ldr r2,[sp,#12]
+ and r3,r3,r12
+ vshr.u32 d24,d0,#19
+ add r5,r5,r9
+ add r9,r9,r0,ror#2
+ eor r3,r3,r11
+ vld1.32 {q8},[r14,:128]!
+ add r8,r8,r2
+ vsli.32 d24,d0,#13
+ eor r2,r6,r7
+ eor r0,r5,r5,ror#5
+ veor d25,d25,d24
+ add r9,r9,r3
+ and r2,r2,r5
+ vadd.i32 d1,d1,d25
+ eor r3,r0,r5,ror#19
+ eor r0,r9,r9,ror#11
+ vadd.i32 q8,q8,q0
+ eor r2,r2,r7
+ add r8,r8,r3,ror#6
+ eor r3,r9,r10
+ eor r0,r0,r9,ror#20
+ add r8,r8,r2
+ ldr r2,[sp,#16]
+ and r12,r12,r3
+ add r4,r4,r8
+ vst1.32 {q8},[r1,:128]!
+ add r8,r8,r0,ror#2
+ eor r12,r12,r10
+ vext.8 q8,q1,q2,#4
+ add r7,r7,r2
+ eor r2,r5,r6
+ eor r0,r4,r4,ror#5
+ vext.8 q9,q3,q0,#4
+ add r8,r8,r12
+ and r2,r2,r4
+ eor r12,r0,r4,ror#19
+ vshr.u32 q10,q8,#7
+ eor r0,r8,r8,ror#11
+ eor r2,r2,r6
+ vadd.i32 q1,q1,q9
+ add r7,r7,r12,ror#6
+ eor r12,r8,r9
+ vshr.u32 q9,q8,#3
+ eor r0,r0,r8,ror#20
+ add r7,r7,r2
+ vsli.32 q10,q8,#25
+ ldr r2,[sp,#20]
+ and r3,r3,r12
+ vshr.u32 q11,q8,#18
+ add r11,r11,r7
+ add r7,r7,r0,ror#2
+ eor r3,r3,r9
+ veor q9,q9,q10
+ add r6,r6,r2
+ vsli.32 q11,q8,#14
+ eor r2,r4,r5
+ eor r0,r11,r11,ror#5
+ vshr.u32 d24,d1,#17
+ add r7,r7,r3
+ and r2,r2,r11
+ veor q9,q9,q11
+ eor r3,r0,r11,ror#19
+ eor r0,r7,r7,ror#11
+ vsli.32 d24,d1,#15
+ eor r2,r2,r5
+ add r6,r6,r3,ror#6
+ vshr.u32 d25,d1,#10
+ eor r3,r7,r8
+ eor r0,r0,r7,ror#20
+ vadd.i32 q1,q1,q9
+ add r6,r6,r2
+ ldr r2,[sp,#24]
+ veor d25,d25,d24
+ and r12,r12,r3
+ add r10,r10,r6
+ vshr.u32 d24,d1,#19
+ add r6,r6,r0,ror#2
+ eor r12,r12,r8
+ vsli.32 d24,d1,#13
+ add r5,r5,r2
+ eor r2,r11,r4
+ veor d25,d25,d24
+ eor r0,r10,r10,ror#5
+ add r6,r6,r12
+ vadd.i32 d2,d2,d25
+ and r2,r2,r10
+ eor r12,r0,r10,ror#19
+ vshr.u32 d24,d2,#17
+ eor r0,r6,r6,ror#11
+ eor r2,r2,r4
+ vsli.32 d24,d2,#15
+ add r5,r5,r12,ror#6
+ eor r12,r6,r7
+ vshr.u32 d25,d2,#10
+ eor r0,r0,r6,ror#20
+ add r5,r5,r2
+ veor d25,d25,d24
+ ldr r2,[sp,#28]
+ and r3,r3,r12
+ vshr.u32 d24,d2,#19
+ add r9,r9,r5
+ add r5,r5,r0,ror#2
+ eor r3,r3,r7
+ vld1.32 {q8},[r14,:128]!
+ add r4,r4,r2
+ vsli.32 d24,d2,#13
+ eor r2,r10,r11
+ eor r0,r9,r9,ror#5
+ veor d25,d25,d24
+ add r5,r5,r3
+ and r2,r2,r9
+ vadd.i32 d3,d3,d25
+ eor r3,r0,r9,ror#19
+ eor r0,r5,r5,ror#11
+ vadd.i32 q8,q8,q1
+ eor r2,r2,r11
+ add r4,r4,r3,ror#6
+ eor r3,r5,r6
+ eor r0,r0,r5,ror#20
+ add r4,r4,r2
+ ldr r2,[sp,#32]
+ and r12,r12,r3
+ add r8,r8,r4
+ vst1.32 {q8},[r1,:128]!
+ add r4,r4,r0,ror#2
+ eor r12,r12,r6
+ vext.8 q8,q2,q3,#4
+ add r11,r11,r2
+ eor r2,r9,r10
+ eor r0,r8,r8,ror#5
+ vext.8 q9,q0,q1,#4
+ add r4,r4,r12
+ and r2,r2,r8
+ eor r12,r0,r8,ror#19
+ vshr.u32 q10,q8,#7
+ eor r0,r4,r4,ror#11
+ eor r2,r2,r10
+ vadd.i32 q2,q2,q9
+ add r11,r11,r12,ror#6
+ eor r12,r4,r5
+ vshr.u32 q9,q8,#3
+ eor r0,r0,r4,ror#20
+ add r11,r11,r2
+ vsli.32 q10,q8,#25
+ ldr r2,[sp,#36]
+ and r3,r3,r12
+ vshr.u32 q11,q8,#18
+ add r7,r7,r11
+ add r11,r11,r0,ror#2
+ eor r3,r3,r5
+ veor q9,q9,q10
+ add r10,r10,r2
+ vsli.32 q11,q8,#14
+ eor r2,r8,r9
+ eor r0,r7,r7,ror#5
+ vshr.u32 d24,d3,#17
+ add r11,r11,r3
+ and r2,r2,r7
+ veor q9,q9,q11
+ eor r3,r0,r7,ror#19
+ eor r0,r11,r11,ror#11
+ vsli.32 d24,d3,#15
+ eor r2,r2,r9
+ add r10,r10,r3,ror#6
+ vshr.u32 d25,d3,#10
+ eor r3,r11,r4
+ eor r0,r0,r11,ror#20
+ vadd.i32 q2,q2,q9
+ add r10,r10,r2
+ ldr r2,[sp,#40]
+ veor d25,d25,d24
+ and r12,r12,r3
+ add r6,r6,r10
+ vshr.u32 d24,d3,#19
+ add r10,r10,r0,ror#2
+ eor r12,r12,r4
+ vsli.32 d24,d3,#13
+ add r9,r9,r2
+ eor r2,r7,r8
+ veor d25,d25,d24
+ eor r0,r6,r6,ror#5
+ add r10,r10,r12
+ vadd.i32 d4,d4,d25
+ and r2,r2,r6
+ eor r12,r0,r6,ror#19
+ vshr.u32 d24,d4,#17
+ eor r0,r10,r10,ror#11
+ eor r2,r2,r8
+ vsli.32 d24,d4,#15
+ add r9,r9,r12,ror#6
+ eor r12,r10,r11
+ vshr.u32 d25,d4,#10
+ eor r0,r0,r10,ror#20
+ add r9,r9,r2
+ veor d25,d25,d24
+ ldr r2,[sp,#44]
+ and r3,r3,r12
+ vshr.u32 d24,d4,#19
+ add r5,r5,r9
+ add r9,r9,r0,ror#2
+ eor r3,r3,r11
+ vld1.32 {q8},[r14,:128]!
+ add r8,r8,r2
+ vsli.32 d24,d4,#13
+ eor r2,r6,r7
+ eor r0,r5,r5,ror#5
+ veor d25,d25,d24
+ add r9,r9,r3
+ and r2,r2,r5
+ vadd.i32 d5,d5,d25
+ eor r3,r0,r5,ror#19
+ eor r0,r9,r9,ror#11
+ vadd.i32 q8,q8,q2
+ eor r2,r2,r7
+ add r8,r8,r3,ror#6
+ eor r3,r9,r10
+ eor r0,r0,r9,ror#20
+ add r8,r8,r2
+ ldr r2,[sp,#48]
+ and r12,r12,r3
+ add r4,r4,r8
+ vst1.32 {q8},[r1,:128]!
+ add r8,r8,r0,ror#2
+ eor r12,r12,r10
+ vext.8 q8,q3,q0,#4
+ add r7,r7,r2
+ eor r2,r5,r6
+ eor r0,r4,r4,ror#5
+ vext.8 q9,q1,q2,#4
+ add r8,r8,r12
+ and r2,r2,r4
+ eor r12,r0,r4,ror#19
+ vshr.u32 q10,q8,#7
+ eor r0,r8,r8,ror#11
+ eor r2,r2,r6
+ vadd.i32 q3,q3,q9
+ add r7,r7,r12,ror#6
+ eor r12,r8,r9
+ vshr.u32 q9,q8,#3
+ eor r0,r0,r8,ror#20
+ add r7,r7,r2
+ vsli.32 q10,q8,#25
+ ldr r2,[sp,#52]
+ and r3,r3,r12
+ vshr.u32 q11,q8,#18
+ add r11,r11,r7
+ add r7,r7,r0,ror#2
+ eor r3,r3,r9
+ veor q9,q9,q10
+ add r6,r6,r2
+ vsli.32 q11,q8,#14
+ eor r2,r4,r5
+ eor r0,r11,r11,ror#5
+ vshr.u32 d24,d5,#17
+ add r7,r7,r3
+ and r2,r2,r11
+ veor q9,q9,q11
+ eor r3,r0,r11,ror#19
+ eor r0,r7,r7,ror#11
+ vsli.32 d24,d5,#15
+ eor r2,r2,r5
+ add r6,r6,r3,ror#6
+ vshr.u32 d25,d5,#10
+ eor r3,r7,r8
+ eor r0,r0,r7,ror#20
+ vadd.i32 q3,q3,q9
+ add r6,r6,r2
+ ldr r2,[sp,#56]
+ veor d25,d25,d24
+ and r12,r12,r3
+ add r10,r10,r6
+ vshr.u32 d24,d5,#19
+ add r6,r6,r0,ror#2
+ eor r12,r12,r8
+ vsli.32 d24,d5,#13
+ add r5,r5,r2
+ eor r2,r11,r4
+ veor d25,d25,d24
+ eor r0,r10,r10,ror#5
+ add r6,r6,r12
+ vadd.i32 d6,d6,d25
+ and r2,r2,r10
+ eor r12,r0,r10,ror#19
+ vshr.u32 d24,d6,#17
+ eor r0,r6,r6,ror#11
+ eor r2,r2,r4
+ vsli.32 d24,d6,#15
+ add r5,r5,r12,ror#6
+ eor r12,r6,r7
+ vshr.u32 d25,d6,#10
+ eor r0,r0,r6,ror#20
+ add r5,r5,r2
+ veor d25,d25,d24
+ ldr r2,[sp,#60]
+ and r3,r3,r12
+ vshr.u32 d24,d6,#19
+ add r9,r9,r5
+ add r5,r5,r0,ror#2
+ eor r3,r3,r7
+ vld1.32 {q8},[r14,:128]!
+ add r4,r4,r2
+ vsli.32 d24,d6,#13
+ eor r2,r10,r11
+ eor r0,r9,r9,ror#5
+ veor d25,d25,d24
+ add r5,r5,r3
+ and r2,r2,r9
+ vadd.i32 d7,d7,d25
+ eor r3,r0,r9,ror#19
+ eor r0,r5,r5,ror#11
+ vadd.i32 q8,q8,q3
+ eor r2,r2,r11
+ add r4,r4,r3,ror#6
+ eor r3,r5,r6
+ eor r0,r0,r5,ror#20
+ add r4,r4,r2
+ ldr r2,[r14]
+ and r12,r12,r3
+ add r8,r8,r4
+ vst1.32 {q8},[r1,:128]!
+ add r4,r4,r0,ror#2
+ eor r12,r12,r6
+ teq r2,#0 @ check for K256 terminator
+ ldr r2,[sp,#0]
+ sub r1,r1,#64
+ bne .L_00_48
+
+ ldr r1,[sp,#68]
+ ldr r0,[sp,#72]
+ sub r14,r14,#256 @ rewind r14
+ teq r1,r0
+ subeq r1,r1,#64 @ avoid SEGV
+ vld1.8 {q0},[r1]! @ load next input block
+ vld1.8 {q1},[r1]!
+ vld1.8 {q2},[r1]!
+ vld1.8 {q3},[r1]!
+ strne r1,[sp,#68]
+ mov r1,sp
+ add r11,r11,r2
+ eor r2,r9,r10
+ eor r0,r8,r8,ror#5
+ add r4,r4,r12
+ vld1.32 {q8},[r14,:128]!
+ and r2,r2,r8
+ eor r12,r0,r8,ror#19
+ eor r0,r4,r4,ror#11
+ eor r2,r2,r10
+ vrev32.8 q0,q0
+ add r11,r11,r12,ror#6
+ eor r12,r4,r5
+ eor r0,r0,r4,ror#20
+ add r11,r11,r2
+ vadd.i32 q8,q8,q0
+ ldr r2,[sp,#4]
+ and r3,r3,r12
+ add r7,r7,r11
+ add r11,r11,r0,ror#2
+ eor r3,r3,r5
+ add r10,r10,r2
+ eor r2,r8,r9
+ eor r0,r7,r7,ror#5
+ add r11,r11,r3
+ and r2,r2,r7
+ eor r3,r0,r7,ror#19
+ eor r0,r11,r11,ror#11
+ eor r2,r2,r9
+ add r10,r10,r3,ror#6
+ eor r3,r11,r4
+ eor r0,r0,r11,ror#20
+ add r10,r10,r2
+ ldr r2,[sp,#8]
+ and r12,r12,r3
+ add r6,r6,r10
+ add r10,r10,r0,ror#2
+ eor r12,r12,r4
+ add r9,r9,r2
+ eor r2,r7,r8
+ eor r0,r6,r6,ror#5
+ add r10,r10,r12
+ and r2,r2,r6
+ eor r12,r0,r6,ror#19
+ eor r0,r10,r10,ror#11
+ eor r2,r2,r8
+ add r9,r9,r12,ror#6
+ eor r12,r10,r11
+ eor r0,r0,r10,ror#20
+ add r9,r9,r2
+ ldr r2,[sp,#12]
+ and r3,r3,r12
+ add r5,r5,r9
+ add r9,r9,r0,ror#2
+ eor r3,r3,r11
+ add r8,r8,r2
+ eor r2,r6,r7
+ eor r0,r5,r5,ror#5
+ add r9,r9,r3
+ and r2,r2,r5
+ eor r3,r0,r5,ror#19
+ eor r0,r9,r9,ror#11
+ eor r2,r2,r7
+ add r8,r8,r3,ror#6
+ eor r3,r9,r10
+ eor r0,r0,r9,ror#20
+ add r8,r8,r2
+ ldr r2,[sp,#16]
+ and r12,r12,r3
+ add r4,r4,r8
+ add r8,r8,r0,ror#2
+ eor r12,r12,r10
+ vst1.32 {q8},[r1,:128]!
+ add r7,r7,r2
+ eor r2,r5,r6
+ eor r0,r4,r4,ror#5
+ add r8,r8,r12
+ vld1.32 {q8},[r14,:128]!
+ and r2,r2,r4
+ eor r12,r0,r4,ror#19
+ eor r0,r8,r8,ror#11
+ eor r2,r2,r6
+ vrev32.8 q1,q1
+ add r7,r7,r12,ror#6
+ eor r12,r8,r9
+ eor r0,r0,r8,ror#20
+ add r7,r7,r2
+ vadd.i32 q8,q8,q1
+ ldr r2,[sp,#20]
+ and r3,r3,r12
+ add r11,r11,r7
+ add r7,r7,r0,ror#2
+ eor r3,r3,r9
+ add r6,r6,r2
+ eor r2,r4,r5
+ eor r0,r11,r11,ror#5
+ add r7,r7,r3
+ and r2,r2,r11
+ eor r3,r0,r11,ror#19
+ eor r0,r7,r7,ror#11
+ eor r2,r2,r5
+ add r6,r6,r3,ror#6
+ eor r3,r7,r8
+ eor r0,r0,r7,ror#20
+ add r6,r6,r2
+ ldr r2,[sp,#24]
+ and r12,r12,r3
+ add r10,r10,r6
+ add r6,r6,r0,ror#2
+ eor r12,r12,r8
+ add r5,r5,r2
+ eor r2,r11,r4
+ eor r0,r10,r10,ror#5
+ add r6,r6,r12
+ and r2,r2,r10
+ eor r12,r0,r10,ror#19
+ eor r0,r6,r6,ror#11
+ eor r2,r2,r4
+ add r5,r5,r12,ror#6
+ eor r12,r6,r7
+ eor r0,r0,r6,ror#20
+ add r5,r5,r2
+ ldr r2,[sp,#28]
+ and r3,r3,r12
+ add r9,r9,r5
+ add r5,r5,r0,ror#2
+ eor r3,r3,r7
+ add r4,r4,r2
+ eor r2,r10,r11
+ eor r0,r9,r9,ror#5
+ add r5,r5,r3
+ and r2,r2,r9
+ eor r3,r0,r9,ror#19
+ eor r0,r5,r5,ror#11
+ eor r2,r2,r11
+ add r4,r4,r3,ror#6
+ eor r3,r5,r6
+ eor r0,r0,r5,ror#20
+ add r4,r4,r2
+ ldr r2,[sp,#32]
+ and r12,r12,r3
+ add r8,r8,r4
+ add r4,r4,r0,ror#2
+ eor r12,r12,r6
+ vst1.32 {q8},[r1,:128]!
+ add r11,r11,r2
+ eor r2,r9,r10
+ eor r0,r8,r8,ror#5
+ add r4,r4,r12
+ vld1.32 {q8},[r14,:128]!
+ and r2,r2,r8
+ eor r12,r0,r8,ror#19
+ eor r0,r4,r4,ror#11
+ eor r2,r2,r10
+ vrev32.8 q2,q2
+ add r11,r11,r12,ror#6
+ eor r12,r4,r5
+ eor r0,r0,r4,ror#20
+ add r11,r11,r2
+ vadd.i32 q8,q8,q2
+ ldr r2,[sp,#36]
+ and r3,r3,r12
+ add r7,r7,r11
+ add r11,r11,r0,ror#2
+ eor r3,r3,r5
+ add r10,r10,r2
+ eor r2,r8,r9
+ eor r0,r7,r7,ror#5
+ add r11,r11,r3
+ and r2,r2,r7
+ eor r3,r0,r7,ror#19
+ eor r0,r11,r11,ror#11
+ eor r2,r2,r9
+ add r10,r10,r3,ror#6
+ eor r3,r11,r4
+ eor r0,r0,r11,ror#20
+ add r10,r10,r2
+ ldr r2,[sp,#40]
+ and r12,r12,r3
+ add r6,r6,r10
+ add r10,r10,r0,ror#2
+ eor r12,r12,r4
+ add r9,r9,r2
+ eor r2,r7,r8
+ eor r0,r6,r6,ror#5
+ add r10,r10,r12
+ and r2,r2,r6
+ eor r12,r0,r6,ror#19
+ eor r0,r10,r10,ror#11
+ eor r2,r2,r8
+ add r9,r9,r12,ror#6
+ eor r12,r10,r11
+ eor r0,r0,r10,ror#20
+ add r9,r9,r2
+ ldr r2,[sp,#44]
+ and r3,r3,r12
+ add r5,r5,r9
+ add r9,r9,r0,ror#2
+ eor r3,r3,r11
+ add r8,r8,r2
+ eor r2,r6,r7
+ eor r0,r5,r5,ror#5
+ add r9,r9,r3
+ and r2,r2,r5
+ eor r3,r0,r5,ror#19
+ eor r0,r9,r9,ror#11
+ eor r2,r2,r7
+ add r8,r8,r3,ror#6
+ eor r3,r9,r10
+ eor r0,r0,r9,ror#20
+ add r8,r8,r2
+ ldr r2,[sp,#48]
+ and r12,r12,r3
+ add r4,r4,r8
+ add r8,r8,r0,ror#2
+ eor r12,r12,r10
+ vst1.32 {q8},[r1,:128]!
+ add r7,r7,r2
+ eor r2,r5,r6
+ eor r0,r4,r4,ror#5
+ add r8,r8,r12
+ vld1.32 {q8},[r14,:128]!
+ and r2,r2,r4
+ eor r12,r0,r4,ror#19
+ eor r0,r8,r8,ror#11
+ eor r2,r2,r6
+ vrev32.8 q3,q3
+ add r7,r7,r12,ror#6
+ eor r12,r8,r9
+ eor r0,r0,r8,ror#20
+ add r7,r7,r2
+ vadd.i32 q8,q8,q3
+ ldr r2,[sp,#52]
+ and r3,r3,r12
+ add r11,r11,r7
+ add r7,r7,r0,ror#2
+ eor r3,r3,r9
+ add r6,r6,r2
+ eor r2,r4,r5
+ eor r0,r11,r11,ror#5
+ add r7,r7,r3
+ and r2,r2,r11
+ eor r3,r0,r11,ror#19
+ eor r0,r7,r7,ror#11
+ eor r2,r2,r5
+ add r6,r6,r3,ror#6
+ eor r3,r7,r8
+ eor r0,r0,r7,ror#20
+ add r6,r6,r2
+ ldr r2,[sp,#56]
+ and r12,r12,r3
+ add r10,r10,r6
+ add r6,r6,r0,ror#2
+ eor r12,r12,r8
+ add r5,r5,r2
+ eor r2,r11,r4
+ eor r0,r10,r10,ror#5
+ add r6,r6,r12
+ and r2,r2,r10
+ eor r12,r0,r10,ror#19
+ eor r0,r6,r6,ror#11
+ eor r2,r2,r4
+ add r5,r5,r12,ror#6
+ eor r12,r6,r7
+ eor r0,r0,r6,ror#20
+ add r5,r5,r2
+ ldr r2,[sp,#60]
+ and r3,r3,r12
+ add r9,r9,r5
+ add r5,r5,r0,ror#2
+ eor r3,r3,r7
+ add r4,r4,r2
+ eor r2,r10,r11
+ eor r0,r9,r9,ror#5
+ add r5,r5,r3
+ and r2,r2,r9
+ eor r3,r0,r9,ror#19
+ eor r0,r5,r5,ror#11
+ eor r2,r2,r11
+ add r4,r4,r3,ror#6
+ eor r3,r5,r6
+ eor r0,r0,r5,ror#20
+ add r4,r4,r2
+ ldr r2,[sp,#64]
+ and r12,r12,r3
+ add r8,r8,r4
+ add r4,r4,r0,ror#2
+ eor r12,r12,r6
+ vst1.32 {q8},[r1,:128]!
+ ldr r0,[r2,#0]
+ add r4,r4,r12 @ h+=Maj(a,b,c) from the past
+ ldr r12,[r2,#4]
+ ldr r3,[r2,#8]
+ ldr r1,[r2,#12]
+ add r4,r4,r0 @ accumulate
+ ldr r0,[r2,#16]
+ add r5,r5,r12
+ ldr r12,[r2,#20]
+ add r6,r6,r3
+ ldr r3,[r2,#24]
+ add r7,r7,r1
+ ldr r1,[r2,#28]
+ add r8,r8,r0
+ str r4,[r2],#4
+ add r9,r9,r12
+ str r5,[r2],#4
+ add r10,r10,r3
+ str r6,[r2],#4
+ add r11,r11,r1
+ str r7,[r2],#4
+ stmia r2,{r8-r11}
+
+ movne r1,sp
+ ldrne r2,[sp,#0]
+ eorne r12,r12,r12
+ ldreq sp,[sp,#76] @ restore original sp
+ eorne r3,r5,r6
+ bne .L_00_48
+
+ ldmia sp!,{r4-r12,pc}
+.size sha256_block_data_order_neon,.-sha256_block_data_order_neon
+#endif
+#if __ARM_MAX_ARCH__>=7
+.type sha256_block_data_order_armv8,%function
+.align 5
+sha256_block_data_order_armv8:
+.LARMv8:
+ vld1.32 {q0,q1},[r0]
+ sub r3,r3,#sha256_block_data_order-K256
+
+.Loop_v8:
+ vld1.8 {q8-q9},[r1]!
+ vld1.8 {q10-q11},[r1]!
+ vld1.32 {q12},[r3]!
+ vrev32.8 q8,q8
+ vrev32.8 q9,q9
+ vrev32.8 q10,q10
+ vrev32.8 q11,q11
+ vmov q14,q0 @ offload
+ vmov q15,q1
+ teq r1,r2
+ vld1.32 {q13},[r3]!
+ vadd.i32 q12,q12,q8
+ .byte 0xe2,0x03,0xfa,0xf3 @ sha256su0 q8,q9
+ vmov q2,q0
+ .byte 0x68,0x0c,0x02,0xf3 @ sha256h q0,q1,q12
+ .byte 0x68,0x2c,0x14,0xf3 @ sha256h2 q1,q2,q12
+ .byte 0xe6,0x0c,0x64,0xf3 @ sha256su1 q8,q10,q11
+ vld1.32 {q12},[r3]!
+ vadd.i32 q13,q13,q9
+ .byte 0xe4,0x23,0xfa,0xf3 @ sha256su0 q9,q10
+ vmov q2,q0
+ .byte 0x6a,0x0c,0x02,0xf3 @ sha256h q0,q1,q13
+ .byte 0x6a,0x2c,0x14,0xf3 @ sha256h2 q1,q2,q13
+ .byte 0xe0,0x2c,0x66,0xf3 @ sha256su1 q9,q11,q8
+ vld1.32 {q13},[r3]!
+ vadd.i32 q12,q12,q10
+ .byte 0xe6,0x43,0xfa,0xf3 @ sha256su0 q10,q11
+ vmov q2,q0
+ .byte 0x68,0x0c,0x02,0xf3 @ sha256h q0,q1,q12
+ .byte 0x68,0x2c,0x14,0xf3 @ sha256h2 q1,q2,q12
+ .byte 0xe2,0x4c,0x60,0xf3 @ sha256su1 q10,q8,q9
+ vld1.32 {q12},[r3]!
+ vadd.i32 q13,q13,q11
+ .byte 0xe0,0x63,0xfa,0xf3 @ sha256su0 q11,q8
+ vmov q2,q0
+ .byte 0x6a,0x0c,0x02,0xf3 @ sha256h q0,q1,q13
+ .byte 0x6a,0x2c,0x14,0xf3 @ sha256h2 q1,q2,q13
+ .byte 0xe4,0x6c,0x62,0xf3 @ sha256su1 q11,q9,q10
+ vld1.32 {q13},[r3]!
+ vadd.i32 q12,q12,q8
+ .byte 0xe2,0x03,0xfa,0xf3 @ sha256su0 q8,q9
+ vmov q2,q0
+ .byte 0x68,0x0c,0x02,0xf3 @ sha256h q0,q1,q12
+ .byte 0x68,0x2c,0x14,0xf3 @ sha256h2 q1,q2,q12
+ .byte 0xe6,0x0c,0x64,0xf3 @ sha256su1 q8,q10,q11
+ vld1.32 {q12},[r3]!
+ vadd.i32 q13,q13,q9
+ .byte 0xe4,0x23,0xfa,0xf3 @ sha256su0 q9,q10
+ vmov q2,q0
+ .byte 0x6a,0x0c,0x02,0xf3 @ sha256h q0,q1,q13
+ .byte 0x6a,0x2c,0x14,0xf3 @ sha256h2 q1,q2,q13
+ .byte 0xe0,0x2c,0x66,0xf3 @ sha256su1 q9,q11,q8
+ vld1.32 {q13},[r3]!
+ vadd.i32 q12,q12,q10
+ .byte 0xe6,0x43,0xfa,0xf3 @ sha256su0 q10,q11
+ vmov q2,q0
+ .byte 0x68,0x0c,0x02,0xf3 @ sha256h q0,q1,q12
+ .byte 0x68,0x2c,0x14,0xf3 @ sha256h2 q1,q2,q12
+ .byte 0xe2,0x4c,0x60,0xf3 @ sha256su1 q10,q8,q9
+ vld1.32 {q12},[r3]!
+ vadd.i32 q13,q13,q11
+ .byte 0xe0,0x63,0xfa,0xf3 @ sha256su0 q11,q8
+ vmov q2,q0
+ .byte 0x6a,0x0c,0x02,0xf3 @ sha256h q0,q1,q13
+ .byte 0x6a,0x2c,0x14,0xf3 @ sha256h2 q1,q2,q13
+ .byte 0xe4,0x6c,0x62,0xf3 @ sha256su1 q11,q9,q10
+ vld1.32 {q13},[r3]!
+ vadd.i32 q12,q12,q8
+ .byte 0xe2,0x03,0xfa,0xf3 @ sha256su0 q8,q9
+ vmov q2,q0
+ .byte 0x68,0x0c,0x02,0xf3 @ sha256h q0,q1,q12
+ .byte 0x68,0x2c,0x14,0xf3 @ sha256h2 q1,q2,q12
+ .byte 0xe6,0x0c,0x64,0xf3 @ sha256su1 q8,q10,q11
+ vld1.32 {q12},[r3]!
+ vadd.i32 q13,q13,q9
+ .byte 0xe4,0x23,0xfa,0xf3 @ sha256su0 q9,q10
+ vmov q2,q0
+ .byte 0x6a,0x0c,0x02,0xf3 @ sha256h q0,q1,q13
+ .byte 0x6a,0x2c,0x14,0xf3 @ sha256h2 q1,q2,q13
+ .byte 0xe0,0x2c,0x66,0xf3 @ sha256su1 q9,q11,q8
+ vld1.32 {q13},[r3]!
+ vadd.i32 q12,q12,q10
+ .byte 0xe6,0x43,0xfa,0xf3 @ sha256su0 q10,q11
+ vmov q2,q0
+ .byte 0x68,0x0c,0x02,0xf3 @ sha256h q0,q1,q12
+ .byte 0x68,0x2c,0x14,0xf3 @ sha256h2 q1,q2,q12
+ .byte 0xe2,0x4c,0x60,0xf3 @ sha256su1 q10,q8,q9
+ vld1.32 {q12},[r3]!
+ vadd.i32 q13,q13,q11
+ .byte 0xe0,0x63,0xfa,0xf3 @ sha256su0 q11,q8
+ vmov q2,q0
+ .byte 0x6a,0x0c,0x02,0xf3 @ sha256h q0,q1,q13
+ .byte 0x6a,0x2c,0x14,0xf3 @ sha256h2 q1,q2,q13
+ .byte 0xe4,0x6c,0x62,0xf3 @ sha256su1 q11,q9,q10
+ vld1.32 {q13},[r3]!
+ vadd.i32 q12,q12,q8
+ vmov q2,q0
+ .byte 0x68,0x0c,0x02,0xf3 @ sha256h q0,q1,q12
+ .byte 0x68,0x2c,0x14,0xf3 @ sha256h2 q1,q2,q12
+
+ vld1.32 {q12},[r3]!
+ vadd.i32 q13,q13,q9
+ vmov q2,q0
+ .byte 0x6a,0x0c,0x02,0xf3 @ sha256h q0,q1,q13
+ .byte 0x6a,0x2c,0x14,0xf3 @ sha256h2 q1,q2,q13
+
+ vld1.32 {q13},[r3]
+ vadd.i32 q12,q12,q10
+ sub r3,r3,#256-16 @ rewind
+ vmov q2,q0
+ .byte 0x68,0x0c,0x02,0xf3 @ sha256h q0,q1,q12
+ .byte 0x68,0x2c,0x14,0xf3 @ sha256h2 q1,q2,q12
+
+ vadd.i32 q13,q13,q11
+ vmov q2,q0
+ .byte 0x6a,0x0c,0x02,0xf3 @ sha256h q0,q1,q13
+ .byte 0x6a,0x2c,0x14,0xf3 @ sha256h2 q1,q2,q13
+
+ vadd.i32 q0,q0,q14
+ vadd.i32 q1,q1,q15
+ bne .Loop_v8
+
+ vst1.32 {q0,q1},[r0]
+
+ bx lr @ bx lr
+.size sha256_block_data_order_armv8,.-sha256_block_data_order_armv8
+#endif
+.asciz "SHA256 block transform for ARMv4/NEON/ARMv8, CRYPTOGAMS by <appro@openssl.org>"
+.align 2
+#if __ARM_MAX_ARCH__>=7
+.comm OPENSSL_armcap_P,4,4
+#endif
diff --git a/linux-arm/crypto/sha/sha512-armv4.S b/linux-arm/crypto/sha/sha512-armv4.S
new file mode 100644
index 0000000..1889fc7
--- /dev/null
+++ b/linux-arm/crypto/sha/sha512-armv4.S
@@ -0,0 +1,1775 @@
+#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
+#if __ARM_MAX_ARCH__>=7
+.LOPENSSL_armcap:
+.word OPENSSL_armcap_P-sha512_block_data_order
+.skip 32-4
+#else
+.skip 32
+#endif
+
+.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_MAX_ARCH__>=7
+ 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
+ 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_MAX_ARCH__>=7
+.arch armv7-a
+.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
+#if 0>0
+ vadd.i64 d16,d30 @ h+=Maj from the past
+#endif
+ vshr.u64 d26,d20,#41
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d20,#50
+ vsli.64 d25,d20,#46
+ vmov d29,d20
+ vsli.64 d26,d20,#23
+#if 0<16 && defined(__ARMEL__)
+ vrev64.8 d0,d0
+#endif
+ veor d25,d24
+ vbsl d29,d21,d22 @ Ch(e,f,g)
+ vshr.u64 d24,d16,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d23
+ vshr.u64 d25,d16,#34
+ vsli.64 d24,d16,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d16,#39
+ vadd.i64 d28,d0
+ vsli.64 d25,d16,#30
+ veor d30,d16,d17
+ vsli.64 d26,d16,#25
+ veor d23,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d18,d17 @ Maj(a,b,c)
+ veor d23,d26 @ Sigma0(a)
+ vadd.i64 d19,d27
+ vadd.i64 d30,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
+#if 1>0
+ vadd.i64 d23,d30 @ h+=Maj from the past
+#endif
+ vshr.u64 d26,d19,#41
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d19,#50
+ vsli.64 d25,d19,#46
+ vmov d29,d19
+ vsli.64 d26,d19,#23
+#if 1<16 && defined(__ARMEL__)
+ vrev64.8 d1,d1
+#endif
+ veor d25,d24
+ vbsl d29,d20,d21 @ Ch(e,f,g)
+ vshr.u64 d24,d23,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d22
+ vshr.u64 d25,d23,#34
+ vsli.64 d24,d23,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d23,#39
+ vadd.i64 d28,d1
+ vsli.64 d25,d23,#30
+ veor d30,d23,d16
+ vsli.64 d26,d23,#25
+ veor d22,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d17,d16 @ Maj(a,b,c)
+ veor d22,d26 @ Sigma0(a)
+ vadd.i64 d18,d27
+ vadd.i64 d30,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
+#if 2>0
+ vadd.i64 d22,d30 @ h+=Maj from the past
+#endif
+ vshr.u64 d26,d18,#41
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d18,#50
+ vsli.64 d25,d18,#46
+ vmov d29,d18
+ vsli.64 d26,d18,#23
+#if 2<16 && defined(__ARMEL__)
+ vrev64.8 d2,d2
+#endif
+ veor d25,d24
+ vbsl d29,d19,d20 @ Ch(e,f,g)
+ vshr.u64 d24,d22,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d21
+ vshr.u64 d25,d22,#34
+ vsli.64 d24,d22,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d22,#39
+ vadd.i64 d28,d2
+ vsli.64 d25,d22,#30
+ veor d30,d22,d23
+ vsli.64 d26,d22,#25
+ veor d21,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d16,d23 @ Maj(a,b,c)
+ veor d21,d26 @ Sigma0(a)
+ vadd.i64 d17,d27
+ vadd.i64 d30,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
+#if 3>0
+ vadd.i64 d21,d30 @ h+=Maj from the past
+#endif
+ vshr.u64 d26,d17,#41
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d17,#50
+ vsli.64 d25,d17,#46
+ vmov d29,d17
+ vsli.64 d26,d17,#23
+#if 3<16 && defined(__ARMEL__)
+ vrev64.8 d3,d3
+#endif
+ veor d25,d24
+ vbsl d29,d18,d19 @ Ch(e,f,g)
+ vshr.u64 d24,d21,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d20
+ vshr.u64 d25,d21,#34
+ vsli.64 d24,d21,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d21,#39
+ vadd.i64 d28,d3
+ vsli.64 d25,d21,#30
+ veor d30,d21,d22
+ vsli.64 d26,d21,#25
+ veor d20,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d23,d22 @ Maj(a,b,c)
+ veor d20,d26 @ Sigma0(a)
+ vadd.i64 d16,d27
+ vadd.i64 d30,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
+#if 4>0
+ vadd.i64 d20,d30 @ h+=Maj from the past
+#endif
+ vshr.u64 d26,d16,#41
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d16,#50
+ vsli.64 d25,d16,#46
+ vmov d29,d16
+ vsli.64 d26,d16,#23
+#if 4<16 && defined(__ARMEL__)
+ vrev64.8 d4,d4
+#endif
+ veor d25,d24
+ vbsl d29,d17,d18 @ Ch(e,f,g)
+ vshr.u64 d24,d20,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d19
+ vshr.u64 d25,d20,#34
+ vsli.64 d24,d20,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d20,#39
+ vadd.i64 d28,d4
+ vsli.64 d25,d20,#30
+ veor d30,d20,d21
+ vsli.64 d26,d20,#25
+ veor d19,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d22,d21 @ Maj(a,b,c)
+ veor d19,d26 @ Sigma0(a)
+ vadd.i64 d23,d27
+ vadd.i64 d30,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
+#if 5>0
+ vadd.i64 d19,d30 @ h+=Maj from the past
+#endif
+ vshr.u64 d26,d23,#41
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d23,#50
+ vsli.64 d25,d23,#46
+ vmov d29,d23
+ vsli.64 d26,d23,#23
+#if 5<16 && defined(__ARMEL__)
+ vrev64.8 d5,d5
+#endif
+ veor d25,d24
+ vbsl d29,d16,d17 @ Ch(e,f,g)
+ vshr.u64 d24,d19,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d18
+ vshr.u64 d25,d19,#34
+ vsli.64 d24,d19,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d19,#39
+ vadd.i64 d28,d5
+ vsli.64 d25,d19,#30
+ veor d30,d19,d20
+ vsli.64 d26,d19,#25
+ veor d18,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d21,d20 @ Maj(a,b,c)
+ veor d18,d26 @ Sigma0(a)
+ vadd.i64 d22,d27
+ vadd.i64 d30,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
+#if 6>0
+ vadd.i64 d18,d30 @ h+=Maj from the past
+#endif
+ vshr.u64 d26,d22,#41
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d22,#50
+ vsli.64 d25,d22,#46
+ vmov d29,d22
+ vsli.64 d26,d22,#23
+#if 6<16 && defined(__ARMEL__)
+ vrev64.8 d6,d6
+#endif
+ veor d25,d24
+ vbsl d29,d23,d16 @ Ch(e,f,g)
+ vshr.u64 d24,d18,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d17
+ vshr.u64 d25,d18,#34
+ vsli.64 d24,d18,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d18,#39
+ vadd.i64 d28,d6
+ vsli.64 d25,d18,#30
+ veor d30,d18,d19
+ vsli.64 d26,d18,#25
+ veor d17,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d20,d19 @ Maj(a,b,c)
+ veor d17,d26 @ Sigma0(a)
+ vadd.i64 d21,d27
+ vadd.i64 d30,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
+#if 7>0
+ vadd.i64 d17,d30 @ h+=Maj from the past
+#endif
+ vshr.u64 d26,d21,#41
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d21,#50
+ vsli.64 d25,d21,#46
+ vmov d29,d21
+ vsli.64 d26,d21,#23
+#if 7<16 && defined(__ARMEL__)
+ vrev64.8 d7,d7
+#endif
+ veor d25,d24
+ vbsl d29,d22,d23 @ Ch(e,f,g)
+ vshr.u64 d24,d17,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d16
+ vshr.u64 d25,d17,#34
+ vsli.64 d24,d17,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d17,#39
+ vadd.i64 d28,d7
+ vsli.64 d25,d17,#30
+ veor d30,d17,d18
+ vsli.64 d26,d17,#25
+ veor d16,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d19,d18 @ Maj(a,b,c)
+ veor d16,d26 @ Sigma0(a)
+ vadd.i64 d20,d27
+ vadd.i64 d30,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
+#if 8>0
+ vadd.i64 d16,d30 @ h+=Maj from the past
+#endif
+ vshr.u64 d26,d20,#41
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d20,#50
+ vsli.64 d25,d20,#46
+ vmov d29,d20
+ vsli.64 d26,d20,#23
+#if 8<16 && defined(__ARMEL__)
+ vrev64.8 d8,d8
+#endif
+ veor d25,d24
+ vbsl d29,d21,d22 @ Ch(e,f,g)
+ vshr.u64 d24,d16,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d23
+ vshr.u64 d25,d16,#34
+ vsli.64 d24,d16,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d16,#39
+ vadd.i64 d28,d8
+ vsli.64 d25,d16,#30
+ veor d30,d16,d17
+ vsli.64 d26,d16,#25
+ veor d23,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d18,d17 @ Maj(a,b,c)
+ veor d23,d26 @ Sigma0(a)
+ vadd.i64 d19,d27
+ vadd.i64 d30,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
+#if 9>0
+ vadd.i64 d23,d30 @ h+=Maj from the past
+#endif
+ vshr.u64 d26,d19,#41
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d19,#50
+ vsli.64 d25,d19,#46
+ vmov d29,d19
+ vsli.64 d26,d19,#23
+#if 9<16 && defined(__ARMEL__)
+ vrev64.8 d9,d9
+#endif
+ veor d25,d24
+ vbsl d29,d20,d21 @ Ch(e,f,g)
+ vshr.u64 d24,d23,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d22
+ vshr.u64 d25,d23,#34
+ vsli.64 d24,d23,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d23,#39
+ vadd.i64 d28,d9
+ vsli.64 d25,d23,#30
+ veor d30,d23,d16
+ vsli.64 d26,d23,#25
+ veor d22,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d17,d16 @ Maj(a,b,c)
+ veor d22,d26 @ Sigma0(a)
+ vadd.i64 d18,d27
+ vadd.i64 d30,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
+#if 10>0
+ vadd.i64 d22,d30 @ h+=Maj from the past
+#endif
+ vshr.u64 d26,d18,#41
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d18,#50
+ vsli.64 d25,d18,#46
+ vmov d29,d18
+ vsli.64 d26,d18,#23
+#if 10<16 && defined(__ARMEL__)
+ vrev64.8 d10,d10
+#endif
+ veor d25,d24
+ vbsl d29,d19,d20 @ Ch(e,f,g)
+ vshr.u64 d24,d22,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d21
+ vshr.u64 d25,d22,#34
+ vsli.64 d24,d22,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d22,#39
+ vadd.i64 d28,d10
+ vsli.64 d25,d22,#30
+ veor d30,d22,d23
+ vsli.64 d26,d22,#25
+ veor d21,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d16,d23 @ Maj(a,b,c)
+ veor d21,d26 @ Sigma0(a)
+ vadd.i64 d17,d27
+ vadd.i64 d30,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
+#if 11>0
+ vadd.i64 d21,d30 @ h+=Maj from the past
+#endif
+ vshr.u64 d26,d17,#41
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d17,#50
+ vsli.64 d25,d17,#46
+ vmov d29,d17
+ vsli.64 d26,d17,#23
+#if 11<16 && defined(__ARMEL__)
+ vrev64.8 d11,d11
+#endif
+ veor d25,d24
+ vbsl d29,d18,d19 @ Ch(e,f,g)
+ vshr.u64 d24,d21,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d20
+ vshr.u64 d25,d21,#34
+ vsli.64 d24,d21,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d21,#39
+ vadd.i64 d28,d11
+ vsli.64 d25,d21,#30
+ veor d30,d21,d22
+ vsli.64 d26,d21,#25
+ veor d20,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d23,d22 @ Maj(a,b,c)
+ veor d20,d26 @ Sigma0(a)
+ vadd.i64 d16,d27
+ vadd.i64 d30,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
+#if 12>0
+ vadd.i64 d20,d30 @ h+=Maj from the past
+#endif
+ vshr.u64 d26,d16,#41
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d16,#50
+ vsli.64 d25,d16,#46
+ vmov d29,d16
+ vsli.64 d26,d16,#23
+#if 12<16 && defined(__ARMEL__)
+ vrev64.8 d12,d12
+#endif
+ veor d25,d24
+ vbsl d29,d17,d18 @ Ch(e,f,g)
+ vshr.u64 d24,d20,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d19
+ vshr.u64 d25,d20,#34
+ vsli.64 d24,d20,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d20,#39
+ vadd.i64 d28,d12
+ vsli.64 d25,d20,#30
+ veor d30,d20,d21
+ vsli.64 d26,d20,#25
+ veor d19,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d22,d21 @ Maj(a,b,c)
+ veor d19,d26 @ Sigma0(a)
+ vadd.i64 d23,d27
+ vadd.i64 d30,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
+#if 13>0
+ vadd.i64 d19,d30 @ h+=Maj from the past
+#endif
+ vshr.u64 d26,d23,#41
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d23,#50
+ vsli.64 d25,d23,#46
+ vmov d29,d23
+ vsli.64 d26,d23,#23
+#if 13<16 && defined(__ARMEL__)
+ vrev64.8 d13,d13
+#endif
+ veor d25,d24
+ vbsl d29,d16,d17 @ Ch(e,f,g)
+ vshr.u64 d24,d19,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d18
+ vshr.u64 d25,d19,#34
+ vsli.64 d24,d19,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d19,#39
+ vadd.i64 d28,d13
+ vsli.64 d25,d19,#30
+ veor d30,d19,d20
+ vsli.64 d26,d19,#25
+ veor d18,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d21,d20 @ Maj(a,b,c)
+ veor d18,d26 @ Sigma0(a)
+ vadd.i64 d22,d27
+ vadd.i64 d30,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
+#if 14>0
+ vadd.i64 d18,d30 @ h+=Maj from the past
+#endif
+ vshr.u64 d26,d22,#41
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d22,#50
+ vsli.64 d25,d22,#46
+ vmov d29,d22
+ vsli.64 d26,d22,#23
+#if 14<16 && defined(__ARMEL__)
+ vrev64.8 d14,d14
+#endif
+ veor d25,d24
+ vbsl d29,d23,d16 @ Ch(e,f,g)
+ vshr.u64 d24,d18,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d17
+ vshr.u64 d25,d18,#34
+ vsli.64 d24,d18,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d18,#39
+ vadd.i64 d28,d14
+ vsli.64 d25,d18,#30
+ veor d30,d18,d19
+ vsli.64 d26,d18,#25
+ veor d17,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d20,d19 @ Maj(a,b,c)
+ veor d17,d26 @ Sigma0(a)
+ vadd.i64 d21,d27
+ vadd.i64 d30,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
+#if 15>0
+ vadd.i64 d17,d30 @ h+=Maj from the past
+#endif
+ vshr.u64 d26,d21,#41
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d21,#50
+ vsli.64 d25,d21,#46
+ vmov d29,d21
+ vsli.64 d26,d21,#23
+#if 15<16 && defined(__ARMEL__)
+ vrev64.8 d15,d15
+#endif
+ veor d25,d24
+ vbsl d29,d22,d23 @ Ch(e,f,g)
+ vshr.u64 d24,d17,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d16
+ vshr.u64 d25,d17,#34
+ vsli.64 d24,d17,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d17,#39
+ vadd.i64 d28,d15
+ vsli.64 d25,d17,#30
+ veor d30,d17,d18
+ vsli.64 d26,d17,#25
+ veor d16,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d19,d18 @ Maj(a,b,c)
+ veor d16,d26 @ Sigma0(a)
+ vadd.i64 d20,d27
+ vadd.i64 d30,d27
+ @ vadd.i64 d16,d30
+ mov r12,#4
+.L16_79_neon:
+ subs r12,#1
+ vshr.u64 q12,q7,#19
+ vshr.u64 q13,q7,#61
+ vadd.i64 d16,d30 @ h+=Maj from the past
+ 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
+ vmov d29,d20
+ vsli.64 d26,d20,#23
+#if 16<16 && defined(__ARMEL__)
+ vrev64.8 ,
+#endif
+ veor d25,d24
+ vbsl d29,d21,d22 @ Ch(e,f,g)
+ vshr.u64 d24,d16,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d23
+ vshr.u64 d25,d16,#34
+ vsli.64 d24,d16,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d16,#39
+ vadd.i64 d28,d0
+ vsli.64 d25,d16,#30
+ veor d30,d16,d17
+ vsli.64 d26,d16,#25
+ veor d23,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d18,d17 @ Maj(a,b,c)
+ veor d23,d26 @ Sigma0(a)
+ vadd.i64 d19,d27
+ vadd.i64 d30,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
+#if 17>0
+ vadd.i64 d23,d30 @ h+=Maj from the past
+#endif
+ vshr.u64 d26,d19,#41
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d19,#50
+ vsli.64 d25,d19,#46
+ vmov d29,d19
+ vsli.64 d26,d19,#23
+#if 17<16 && defined(__ARMEL__)
+ vrev64.8 ,
+#endif
+ veor d25,d24
+ vbsl d29,d20,d21 @ Ch(e,f,g)
+ vshr.u64 d24,d23,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d22
+ vshr.u64 d25,d23,#34
+ vsli.64 d24,d23,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d23,#39
+ vadd.i64 d28,d1
+ vsli.64 d25,d23,#30
+ veor d30,d23,d16
+ vsli.64 d26,d23,#25
+ veor d22,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d17,d16 @ Maj(a,b,c)
+ veor d22,d26 @ Sigma0(a)
+ vadd.i64 d18,d27
+ vadd.i64 d30,d27
+ @ vadd.i64 d22,d30
+ vshr.u64 q12,q0,#19
+ vshr.u64 q13,q0,#61
+ vadd.i64 d22,d30 @ h+=Maj from the past
+ 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
+ vmov d29,d18
+ vsli.64 d26,d18,#23
+#if 18<16 && defined(__ARMEL__)
+ vrev64.8 ,
+#endif
+ veor d25,d24
+ vbsl d29,d19,d20 @ Ch(e,f,g)
+ vshr.u64 d24,d22,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d21
+ vshr.u64 d25,d22,#34
+ vsli.64 d24,d22,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d22,#39
+ vadd.i64 d28,d2
+ vsli.64 d25,d22,#30
+ veor d30,d22,d23
+ vsli.64 d26,d22,#25
+ veor d21,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d16,d23 @ Maj(a,b,c)
+ veor d21,d26 @ Sigma0(a)
+ vadd.i64 d17,d27
+ vadd.i64 d30,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
+#if 19>0
+ vadd.i64 d21,d30 @ h+=Maj from the past
+#endif
+ vshr.u64 d26,d17,#41
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d17,#50
+ vsli.64 d25,d17,#46
+ vmov d29,d17
+ vsli.64 d26,d17,#23
+#if 19<16 && defined(__ARMEL__)
+ vrev64.8 ,
+#endif
+ veor d25,d24
+ vbsl d29,d18,d19 @ Ch(e,f,g)
+ vshr.u64 d24,d21,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d20
+ vshr.u64 d25,d21,#34
+ vsli.64 d24,d21,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d21,#39
+ vadd.i64 d28,d3
+ vsli.64 d25,d21,#30
+ veor d30,d21,d22
+ vsli.64 d26,d21,#25
+ veor d20,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d23,d22 @ Maj(a,b,c)
+ veor d20,d26 @ Sigma0(a)
+ vadd.i64 d16,d27
+ vadd.i64 d30,d27
+ @ vadd.i64 d20,d30
+ vshr.u64 q12,q1,#19
+ vshr.u64 q13,q1,#61
+ vadd.i64 d20,d30 @ h+=Maj from the past
+ 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
+ vmov d29,d16
+ vsli.64 d26,d16,#23
+#if 20<16 && defined(__ARMEL__)
+ vrev64.8 ,
+#endif
+ veor d25,d24
+ vbsl d29,d17,d18 @ Ch(e,f,g)
+ vshr.u64 d24,d20,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d19
+ vshr.u64 d25,d20,#34
+ vsli.64 d24,d20,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d20,#39
+ vadd.i64 d28,d4
+ vsli.64 d25,d20,#30
+ veor d30,d20,d21
+ vsli.64 d26,d20,#25
+ veor d19,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d22,d21 @ Maj(a,b,c)
+ veor d19,d26 @ Sigma0(a)
+ vadd.i64 d23,d27
+ vadd.i64 d30,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
+#if 21>0
+ vadd.i64 d19,d30 @ h+=Maj from the past
+#endif
+ vshr.u64 d26,d23,#41
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d23,#50
+ vsli.64 d25,d23,#46
+ vmov d29,d23
+ vsli.64 d26,d23,#23
+#if 21<16 && defined(__ARMEL__)
+ vrev64.8 ,
+#endif
+ veor d25,d24
+ vbsl d29,d16,d17 @ Ch(e,f,g)
+ vshr.u64 d24,d19,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d18
+ vshr.u64 d25,d19,#34
+ vsli.64 d24,d19,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d19,#39
+ vadd.i64 d28,d5
+ vsli.64 d25,d19,#30
+ veor d30,d19,d20
+ vsli.64 d26,d19,#25
+ veor d18,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d21,d20 @ Maj(a,b,c)
+ veor d18,d26 @ Sigma0(a)
+ vadd.i64 d22,d27
+ vadd.i64 d30,d27
+ @ vadd.i64 d18,d30
+ vshr.u64 q12,q2,#19
+ vshr.u64 q13,q2,#61
+ vadd.i64 d18,d30 @ h+=Maj from the past
+ 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
+ vmov d29,d22
+ vsli.64 d26,d22,#23
+#if 22<16 && defined(__ARMEL__)
+ vrev64.8 ,
+#endif
+ veor d25,d24
+ vbsl d29,d23,d16 @ Ch(e,f,g)
+ vshr.u64 d24,d18,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d17
+ vshr.u64 d25,d18,#34
+ vsli.64 d24,d18,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d18,#39
+ vadd.i64 d28,d6
+ vsli.64 d25,d18,#30
+ veor d30,d18,d19
+ vsli.64 d26,d18,#25
+ veor d17,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d20,d19 @ Maj(a,b,c)
+ veor d17,d26 @ Sigma0(a)
+ vadd.i64 d21,d27
+ vadd.i64 d30,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
+#if 23>0
+ vadd.i64 d17,d30 @ h+=Maj from the past
+#endif
+ vshr.u64 d26,d21,#41
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d21,#50
+ vsli.64 d25,d21,#46
+ vmov d29,d21
+ vsli.64 d26,d21,#23
+#if 23<16 && defined(__ARMEL__)
+ vrev64.8 ,
+#endif
+ veor d25,d24
+ vbsl d29,d22,d23 @ Ch(e,f,g)
+ vshr.u64 d24,d17,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d16
+ vshr.u64 d25,d17,#34
+ vsli.64 d24,d17,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d17,#39
+ vadd.i64 d28,d7
+ vsli.64 d25,d17,#30
+ veor d30,d17,d18
+ vsli.64 d26,d17,#25
+ veor d16,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d19,d18 @ Maj(a,b,c)
+ veor d16,d26 @ Sigma0(a)
+ vadd.i64 d20,d27
+ vadd.i64 d30,d27
+ @ vadd.i64 d16,d30
+ vshr.u64 q12,q3,#19
+ vshr.u64 q13,q3,#61
+ vadd.i64 d16,d30 @ h+=Maj from the past
+ 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
+ vmov d29,d20
+ vsli.64 d26,d20,#23
+#if 24<16 && defined(__ARMEL__)
+ vrev64.8 ,
+#endif
+ veor d25,d24
+ vbsl d29,d21,d22 @ Ch(e,f,g)
+ vshr.u64 d24,d16,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d23
+ vshr.u64 d25,d16,#34
+ vsli.64 d24,d16,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d16,#39
+ vadd.i64 d28,d8
+ vsli.64 d25,d16,#30
+ veor d30,d16,d17
+ vsli.64 d26,d16,#25
+ veor d23,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d18,d17 @ Maj(a,b,c)
+ veor d23,d26 @ Sigma0(a)
+ vadd.i64 d19,d27
+ vadd.i64 d30,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
+#if 25>0
+ vadd.i64 d23,d30 @ h+=Maj from the past
+#endif
+ vshr.u64 d26,d19,#41
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d19,#50
+ vsli.64 d25,d19,#46
+ vmov d29,d19
+ vsli.64 d26,d19,#23
+#if 25<16 && defined(__ARMEL__)
+ vrev64.8 ,
+#endif
+ veor d25,d24
+ vbsl d29,d20,d21 @ Ch(e,f,g)
+ vshr.u64 d24,d23,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d22
+ vshr.u64 d25,d23,#34
+ vsli.64 d24,d23,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d23,#39
+ vadd.i64 d28,d9
+ vsli.64 d25,d23,#30
+ veor d30,d23,d16
+ vsli.64 d26,d23,#25
+ veor d22,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d17,d16 @ Maj(a,b,c)
+ veor d22,d26 @ Sigma0(a)
+ vadd.i64 d18,d27
+ vadd.i64 d30,d27
+ @ vadd.i64 d22,d30
+ vshr.u64 q12,q4,#19
+ vshr.u64 q13,q4,#61
+ vadd.i64 d22,d30 @ h+=Maj from the past
+ 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
+ vmov d29,d18
+ vsli.64 d26,d18,#23
+#if 26<16 && defined(__ARMEL__)
+ vrev64.8 ,
+#endif
+ veor d25,d24
+ vbsl d29,d19,d20 @ Ch(e,f,g)
+ vshr.u64 d24,d22,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d21
+ vshr.u64 d25,d22,#34
+ vsli.64 d24,d22,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d22,#39
+ vadd.i64 d28,d10
+ vsli.64 d25,d22,#30
+ veor d30,d22,d23
+ vsli.64 d26,d22,#25
+ veor d21,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d16,d23 @ Maj(a,b,c)
+ veor d21,d26 @ Sigma0(a)
+ vadd.i64 d17,d27
+ vadd.i64 d30,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
+#if 27>0
+ vadd.i64 d21,d30 @ h+=Maj from the past
+#endif
+ vshr.u64 d26,d17,#41
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d17,#50
+ vsli.64 d25,d17,#46
+ vmov d29,d17
+ vsli.64 d26,d17,#23
+#if 27<16 && defined(__ARMEL__)
+ vrev64.8 ,
+#endif
+ veor d25,d24
+ vbsl d29,d18,d19 @ Ch(e,f,g)
+ vshr.u64 d24,d21,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d20
+ vshr.u64 d25,d21,#34
+ vsli.64 d24,d21,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d21,#39
+ vadd.i64 d28,d11
+ vsli.64 d25,d21,#30
+ veor d30,d21,d22
+ vsli.64 d26,d21,#25
+ veor d20,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d23,d22 @ Maj(a,b,c)
+ veor d20,d26 @ Sigma0(a)
+ vadd.i64 d16,d27
+ vadd.i64 d30,d27
+ @ vadd.i64 d20,d30
+ vshr.u64 q12,q5,#19
+ vshr.u64 q13,q5,#61
+ vadd.i64 d20,d30 @ h+=Maj from the past
+ 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
+ vmov d29,d16
+ vsli.64 d26,d16,#23
+#if 28<16 && defined(__ARMEL__)
+ vrev64.8 ,
+#endif
+ veor d25,d24
+ vbsl d29,d17,d18 @ Ch(e,f,g)
+ vshr.u64 d24,d20,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d19
+ vshr.u64 d25,d20,#34
+ vsli.64 d24,d20,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d20,#39
+ vadd.i64 d28,d12
+ vsli.64 d25,d20,#30
+ veor d30,d20,d21
+ vsli.64 d26,d20,#25
+ veor d19,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d22,d21 @ Maj(a,b,c)
+ veor d19,d26 @ Sigma0(a)
+ vadd.i64 d23,d27
+ vadd.i64 d30,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
+#if 29>0
+ vadd.i64 d19,d30 @ h+=Maj from the past
+#endif
+ vshr.u64 d26,d23,#41
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d23,#50
+ vsli.64 d25,d23,#46
+ vmov d29,d23
+ vsli.64 d26,d23,#23
+#if 29<16 && defined(__ARMEL__)
+ vrev64.8 ,
+#endif
+ veor d25,d24
+ vbsl d29,d16,d17 @ Ch(e,f,g)
+ vshr.u64 d24,d19,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d18
+ vshr.u64 d25,d19,#34
+ vsli.64 d24,d19,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d19,#39
+ vadd.i64 d28,d13
+ vsli.64 d25,d19,#30
+ veor d30,d19,d20
+ vsli.64 d26,d19,#25
+ veor d18,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d21,d20 @ Maj(a,b,c)
+ veor d18,d26 @ Sigma0(a)
+ vadd.i64 d22,d27
+ vadd.i64 d30,d27
+ @ vadd.i64 d18,d30
+ vshr.u64 q12,q6,#19
+ vshr.u64 q13,q6,#61
+ vadd.i64 d18,d30 @ h+=Maj from the past
+ 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
+ vmov d29,d22
+ vsli.64 d26,d22,#23
+#if 30<16 && defined(__ARMEL__)
+ vrev64.8 ,
+#endif
+ veor d25,d24
+ vbsl d29,d23,d16 @ Ch(e,f,g)
+ vshr.u64 d24,d18,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d17
+ vshr.u64 d25,d18,#34
+ vsli.64 d24,d18,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d18,#39
+ vadd.i64 d28,d14
+ vsli.64 d25,d18,#30
+ veor d30,d18,d19
+ vsli.64 d26,d18,#25
+ veor d17,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d20,d19 @ Maj(a,b,c)
+ veor d17,d26 @ Sigma0(a)
+ vadd.i64 d21,d27
+ vadd.i64 d30,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
+#if 31>0
+ vadd.i64 d17,d30 @ h+=Maj from the past
+#endif
+ vshr.u64 d26,d21,#41
+ vld1.64 {d28},[r3,:64]! @ K[i++]
+ vsli.64 d24,d21,#50
+ vsli.64 d25,d21,#46
+ vmov d29,d21
+ vsli.64 d26,d21,#23
+#if 31<16 && defined(__ARMEL__)
+ vrev64.8 ,
+#endif
+ veor d25,d24
+ vbsl d29,d22,d23 @ Ch(e,f,g)
+ vshr.u64 d24,d17,#28
+ veor d26,d25 @ Sigma1(e)
+ vadd.i64 d27,d29,d16
+ vshr.u64 d25,d17,#34
+ vsli.64 d24,d17,#36
+ vadd.i64 d27,d26
+ vshr.u64 d26,d17,#39
+ vadd.i64 d28,d15
+ vsli.64 d25,d17,#30
+ veor d30,d17,d18
+ vsli.64 d26,d17,#25
+ veor d16,d24,d25
+ vadd.i64 d27,d28
+ vbsl d30,d19,d18 @ Maj(a,b,c)
+ veor d16,d26 @ Sigma0(a)
+ vadd.i64 d20,d27
+ vadd.i64 d30,d27
+ @ vadd.i64 d16,d30
+ bne .L16_79_neon
+
+ vadd.i64 d16,d30 @ h+=Maj from the past
+ 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
+ bx lr @ .word 0xe12fff1e
+#endif
+.size sha512_block_data_order,.-sha512_block_data_order
+.asciz "SHA512 block transform for ARMv4/NEON, CRYPTOGAMS by <appro@openssl.org>"
+.align 2
+#if __ARM_MAX_ARCH__>=7
+.comm OPENSSL_armcap_P,4,4
+#endif
diff --git a/linux-x86/crypto/aes/aes-586.S b/linux-x86/crypto/aes/aes-586.S
new file mode 100644
index 0000000..7428274
--- /dev/null
+++ b/linux-x86/crypto/aes/aes-586.S
@@ -0,0 +1,3257 @@
+#if defined(__i386__)
+.file "aes-586.S"
+.text
+.hidden _x86_AES_encrypt_compact
+.type _x86_AES_encrypt_compact,@function
+.align 16
+_x86_AES_encrypt_compact:
+ movl %edi,20(%esp)
+ xorl (%edi),%eax
+ xorl 4(%edi),%ebx
+ xorl 8(%edi),%ecx
+ xorl 12(%edi),%edx
+ movl 240(%edi),%esi
+ leal -2(%esi,%esi,1),%esi
+ leal (%edi,%esi,8),%esi
+ movl %esi,24(%esp)
+ movl -128(%ebp),%edi
+ movl -96(%ebp),%esi
+ movl -64(%ebp),%edi
+ movl -32(%ebp),%esi
+ movl (%ebp),%edi
+ movl 32(%ebp),%esi
+ movl 64(%ebp),%edi
+ movl 96(%ebp),%esi
+.align 16
+.L000loop:
+ movl %eax,%esi
+ andl $255,%esi
+ movzbl -128(%ebp,%esi,1),%esi
+ movzbl %bh,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $8,%edi
+ xorl %edi,%esi
+ movl %ecx,%edi
+ shrl $16,%edi
+ andl $255,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $16,%edi
+ xorl %edi,%esi
+ movl %edx,%edi
+ shrl $24,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $24,%edi
+ xorl %edi,%esi
+ movl %esi,4(%esp)
+
+ movl %ebx,%esi
+ andl $255,%esi
+ shrl $16,%ebx
+ movzbl -128(%ebp,%esi,1),%esi
+ movzbl %ch,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $8,%edi
+ xorl %edi,%esi
+ movl %edx,%edi
+ shrl $16,%edi
+ andl $255,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $16,%edi
+ xorl %edi,%esi
+ movl %eax,%edi
+ shrl $24,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $24,%edi
+ xorl %edi,%esi
+ movl %esi,8(%esp)
+
+ movl %ecx,%esi
+ andl $255,%esi
+ shrl $24,%ecx
+ movzbl -128(%ebp,%esi,1),%esi
+ movzbl %dh,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $8,%edi
+ xorl %edi,%esi
+ movl %eax,%edi
+ shrl $16,%edi
+ andl $255,%edx
+ andl $255,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $16,%edi
+ xorl %edi,%esi
+ movzbl %bh,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $24,%edi
+ xorl %edi,%esi
+
+ andl $255,%edx
+ movzbl -128(%ebp,%edx,1),%edx
+ movzbl %ah,%eax
+ movzbl -128(%ebp,%eax,1),%eax
+ shll $8,%eax
+ xorl %eax,%edx
+ movl 4(%esp),%eax
+ andl $255,%ebx
+ movzbl -128(%ebp,%ebx,1),%ebx
+ shll $16,%ebx
+ xorl %ebx,%edx
+ movl 8(%esp),%ebx
+ movzbl -128(%ebp,%ecx,1),%ecx
+ shll $24,%ecx
+ xorl %ecx,%edx
+ movl %esi,%ecx
+
+ movl $2155905152,%ebp
+ andl %ecx,%ebp
+ leal (%ecx,%ecx,1),%edi
+ movl %ebp,%esi
+ shrl $7,%ebp
+ andl $4278124286,%edi
+ subl %ebp,%esi
+ movl %ecx,%ebp
+ andl $454761243,%esi
+ rorl $16,%ebp
+ xorl %edi,%esi
+ movl %ecx,%edi
+ xorl %esi,%ecx
+ rorl $24,%edi
+ xorl %ebp,%esi
+ roll $24,%ecx
+ xorl %edi,%esi
+ movl $2155905152,%ebp
+ xorl %esi,%ecx
+ andl %edx,%ebp
+ leal (%edx,%edx,1),%edi
+ movl %ebp,%esi
+ shrl $7,%ebp
+ andl $4278124286,%edi
+ subl %ebp,%esi
+ movl %edx,%ebp
+ andl $454761243,%esi
+ rorl $16,%ebp
+ xorl %edi,%esi
+ movl %edx,%edi
+ xorl %esi,%edx
+ rorl $24,%edi
+ xorl %ebp,%esi
+ roll $24,%edx
+ xorl %edi,%esi
+ movl $2155905152,%ebp
+ xorl %esi,%edx
+ andl %eax,%ebp
+ leal (%eax,%eax,1),%edi
+ movl %ebp,%esi
+ shrl $7,%ebp
+ andl $4278124286,%edi
+ subl %ebp,%esi
+ movl %eax,%ebp
+ andl $454761243,%esi
+ rorl $16,%ebp
+ xorl %edi,%esi
+ movl %eax,%edi
+ xorl %esi,%eax
+ rorl $24,%edi
+ xorl %ebp,%esi
+ roll $24,%eax
+ xorl %edi,%esi
+ movl $2155905152,%ebp
+ xorl %esi,%eax
+ andl %ebx,%ebp
+ leal (%ebx,%ebx,1),%edi
+ movl %ebp,%esi
+ shrl $7,%ebp
+ andl $4278124286,%edi
+ subl %ebp,%esi
+ movl %ebx,%ebp
+ andl $454761243,%esi
+ rorl $16,%ebp
+ xorl %edi,%esi
+ movl %ebx,%edi
+ xorl %esi,%ebx
+ rorl $24,%edi
+ xorl %ebp,%esi
+ roll $24,%ebx
+ xorl %edi,%esi
+ xorl %esi,%ebx
+ movl 20(%esp),%edi
+ movl 28(%esp),%ebp
+ addl $16,%edi
+ xorl (%edi),%eax
+ xorl 4(%edi),%ebx
+ xorl 8(%edi),%ecx
+ xorl 12(%edi),%edx
+ cmpl 24(%esp),%edi
+ movl %edi,20(%esp)
+ jb .L000loop
+ movl %eax,%esi
+ andl $255,%esi
+ movzbl -128(%ebp,%esi,1),%esi
+ movzbl %bh,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $8,%edi
+ xorl %edi,%esi
+ movl %ecx,%edi
+ shrl $16,%edi
+ andl $255,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $16,%edi
+ xorl %edi,%esi
+ movl %edx,%edi
+ shrl $24,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $24,%edi
+ xorl %edi,%esi
+ movl %esi,4(%esp)
+
+ movl %ebx,%esi
+ andl $255,%esi
+ shrl $16,%ebx
+ movzbl -128(%ebp,%esi,1),%esi
+ movzbl %ch,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $8,%edi
+ xorl %edi,%esi
+ movl %edx,%edi
+ shrl $16,%edi
+ andl $255,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $16,%edi
+ xorl %edi,%esi
+ movl %eax,%edi
+ shrl $24,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $24,%edi
+ xorl %edi,%esi
+ movl %esi,8(%esp)
+
+ movl %ecx,%esi
+ andl $255,%esi
+ shrl $24,%ecx
+ movzbl -128(%ebp,%esi,1),%esi
+ movzbl %dh,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $8,%edi
+ xorl %edi,%esi
+ movl %eax,%edi
+ shrl $16,%edi
+ andl $255,%edx
+ andl $255,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $16,%edi
+ xorl %edi,%esi
+ movzbl %bh,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $24,%edi
+ xorl %edi,%esi
+
+ movl 20(%esp),%edi
+ andl $255,%edx
+ movzbl -128(%ebp,%edx,1),%edx
+ movzbl %ah,%eax
+ movzbl -128(%ebp,%eax,1),%eax
+ shll $8,%eax
+ xorl %eax,%edx
+ movl 4(%esp),%eax
+ andl $255,%ebx
+ movzbl -128(%ebp,%ebx,1),%ebx
+ shll $16,%ebx
+ xorl %ebx,%edx
+ movl 8(%esp),%ebx
+ movzbl -128(%ebp,%ecx,1),%ecx
+ shll $24,%ecx
+ xorl %ecx,%edx
+ movl %esi,%ecx
+
+ xorl 16(%edi),%eax
+ xorl 20(%edi),%ebx
+ xorl 24(%edi),%ecx
+ xorl 28(%edi),%edx
+ ret
+.size _x86_AES_encrypt_compact,.-_x86_AES_encrypt_compact
+.hidden _sse_AES_encrypt_compact
+.type _sse_AES_encrypt_compact,@function
+.align 16
+_sse_AES_encrypt_compact:
+ pxor (%edi),%mm0
+ pxor 8(%edi),%mm4
+ movl 240(%edi),%esi
+ leal -2(%esi,%esi,1),%esi
+ leal (%edi,%esi,8),%esi
+ movl %esi,24(%esp)
+ movl $454761243,%eax
+ movl %eax,8(%esp)
+ movl %eax,12(%esp)
+ movl -128(%ebp),%eax
+ movl -96(%ebp),%ebx
+ movl -64(%ebp),%ecx
+ movl -32(%ebp),%edx
+ movl (%ebp),%eax
+ movl 32(%ebp),%ebx
+ movl 64(%ebp),%ecx
+ movl 96(%ebp),%edx
+.align 16
+.L001loop:
+ pshufw $8,%mm0,%mm1
+ pshufw $13,%mm4,%mm5
+ movd %mm1,%eax
+ movd %mm5,%ebx
+ movl %edi,20(%esp)
+ movzbl %al,%esi
+ movzbl %ah,%edx
+ pshufw $13,%mm0,%mm2
+ movzbl -128(%ebp,%esi,1),%ecx
+ movzbl %bl,%edi
+ movzbl -128(%ebp,%edx,1),%edx
+ shrl $16,%eax
+ shll $8,%edx
+ movzbl -128(%ebp,%edi,1),%esi
+ movzbl %bh,%edi
+ shll $16,%esi
+ pshufw $8,%mm4,%mm6
+ orl %esi,%ecx
+ movzbl -128(%ebp,%edi,1),%esi
+ movzbl %ah,%edi
+ shll $24,%esi
+ shrl $16,%ebx
+ orl %esi,%edx
+ movzbl -128(%ebp,%edi,1),%esi
+ movzbl %bh,%edi
+ shll $8,%esi
+ orl %esi,%ecx
+ movzbl -128(%ebp,%edi,1),%esi
+ movzbl %al,%edi
+ shll $24,%esi
+ orl %esi,%ecx
+ movzbl -128(%ebp,%edi,1),%esi
+ movzbl %bl,%edi
+ movd %mm2,%eax
+ movd %ecx,%mm0
+ movzbl -128(%ebp,%edi,1),%ecx
+ movzbl %ah,%edi
+ shll $16,%ecx
+ movd %mm6,%ebx
+ orl %esi,%ecx
+ movzbl -128(%ebp,%edi,1),%esi
+ movzbl %bh,%edi
+ shll $24,%esi
+ orl %esi,%ecx
+ movzbl -128(%ebp,%edi,1),%esi
+ movzbl %bl,%edi
+ shll $8,%esi
+ shrl $16,%ebx
+ orl %esi,%ecx
+ movzbl -128(%ebp,%edi,1),%esi
+ movzbl %al,%edi
+ shrl $16,%eax
+ movd %ecx,%mm1
+ movzbl -128(%ebp,%edi,1),%ecx
+ movzbl %ah,%edi
+ shll $16,%ecx
+ andl $255,%eax
+ orl %esi,%ecx
+ punpckldq %mm1,%mm0
+ movzbl -128(%ebp,%edi,1),%esi
+ movzbl %bh,%edi
+ shll $24,%esi
+ andl $255,%ebx
+ movzbl -128(%ebp,%eax,1),%eax
+ orl %esi,%ecx
+ shll $16,%eax
+ movzbl -128(%ebp,%edi,1),%esi
+ orl %eax,%edx
+ shll $8,%esi
+ movzbl -128(%ebp,%ebx,1),%ebx
+ orl %esi,%ecx
+ orl %ebx,%edx
+ movl 20(%esp),%edi
+ movd %ecx,%mm4
+ movd %edx,%mm5
+ punpckldq %mm5,%mm4
+ addl $16,%edi
+ cmpl 24(%esp),%edi
+ ja .L002out
+ movq 8(%esp),%mm2
+ pxor %mm3,%mm3
+ pxor %mm7,%mm7
+ movq %mm0,%mm1
+ movq %mm4,%mm5
+ pcmpgtb %mm0,%mm3
+ pcmpgtb %mm4,%mm7
+ pand %mm2,%mm3
+ pand %mm2,%mm7
+ pshufw $177,%mm0,%mm2
+ pshufw $177,%mm4,%mm6
+ paddb %mm0,%mm0
+ paddb %mm4,%mm4
+ pxor %mm3,%mm0
+ pxor %mm7,%mm4
+ pshufw $177,%mm2,%mm3
+ pshufw $177,%mm6,%mm7
+ pxor %mm0,%mm1
+ pxor %mm4,%mm5
+ pxor %mm2,%mm0
+ pxor %mm6,%mm4
+ movq %mm3,%mm2
+ movq %mm7,%mm6
+ pslld $8,%mm3
+ pslld $8,%mm7
+ psrld $24,%mm2
+ psrld $24,%mm6
+ pxor %mm3,%mm0
+ pxor %mm7,%mm4
+ pxor %mm2,%mm0
+ pxor %mm6,%mm4
+ movq %mm1,%mm3
+ movq %mm5,%mm7
+ movq (%edi),%mm2
+ movq 8(%edi),%mm6
+ psrld $8,%mm1
+ psrld $8,%mm5
+ movl -128(%ebp),%eax
+ pslld $24,%mm3
+ pslld $24,%mm7
+ movl -64(%ebp),%ebx
+ pxor %mm1,%mm0
+ pxor %mm5,%mm4
+ movl (%ebp),%ecx
+ pxor %mm3,%mm0
+ pxor %mm7,%mm4
+ movl 64(%ebp),%edx
+ pxor %mm2,%mm0
+ pxor %mm6,%mm4
+ jmp .L001loop
+.align 16
+.L002out:
+ pxor (%edi),%mm0
+ pxor 8(%edi),%mm4
+ ret
+.size _sse_AES_encrypt_compact,.-_sse_AES_encrypt_compact
+.hidden _x86_AES_encrypt
+.type _x86_AES_encrypt,@function
+.align 16
+_x86_AES_encrypt:
+ movl %edi,20(%esp)
+ xorl (%edi),%eax
+ xorl 4(%edi),%ebx
+ xorl 8(%edi),%ecx
+ xorl 12(%edi),%edx
+ movl 240(%edi),%esi
+ leal -2(%esi,%esi,1),%esi
+ leal (%edi,%esi,8),%esi
+ movl %esi,24(%esp)
+.align 16
+.L003loop:
+ movl %eax,%esi
+ andl $255,%esi
+ movl (%ebp,%esi,8),%esi
+ movzbl %bh,%edi
+ xorl 3(%ebp,%edi,8),%esi
+ movl %ecx,%edi
+ shrl $16,%edi
+ andl $255,%edi
+ xorl 2(%ebp,%edi,8),%esi
+ movl %edx,%edi
+ shrl $24,%edi
+ xorl 1(%ebp,%edi,8),%esi
+ movl %esi,4(%esp)
+
+ movl %ebx,%esi
+ andl $255,%esi
+ shrl $16,%ebx
+ movl (%ebp,%esi,8),%esi
+ movzbl %ch,%edi
+ xorl 3(%ebp,%edi,8),%esi
+ movl %edx,%edi
+ shrl $16,%edi
+ andl $255,%edi
+ xorl 2(%ebp,%edi,8),%esi
+ movl %eax,%edi
+ shrl $24,%edi
+ xorl 1(%ebp,%edi,8),%esi
+ movl %esi,8(%esp)
+
+ movl %ecx,%esi
+ andl $255,%esi
+ shrl $24,%ecx
+ movl (%ebp,%esi,8),%esi
+ movzbl %dh,%edi
+ xorl 3(%ebp,%edi,8),%esi
+ movl %eax,%edi
+ shrl $16,%edi
+ andl $255,%edx
+ andl $255,%edi
+ xorl 2(%ebp,%edi,8),%esi
+ movzbl %bh,%edi
+ xorl 1(%ebp,%edi,8),%esi
+
+ movl 20(%esp),%edi
+ movl (%ebp,%edx,8),%edx
+ movzbl %ah,%eax
+ xorl 3(%ebp,%eax,8),%edx
+ movl 4(%esp),%eax
+ andl $255,%ebx
+ xorl 2(%ebp,%ebx,8),%edx
+ movl 8(%esp),%ebx
+ xorl 1(%ebp,%ecx,8),%edx
+ movl %esi,%ecx
+
+ addl $16,%edi
+ xorl (%edi),%eax
+ xorl 4(%edi),%ebx
+ xorl 8(%edi),%ecx
+ xorl 12(%edi),%edx
+ cmpl 24(%esp),%edi
+ movl %edi,20(%esp)
+ jb .L003loop
+ movl %eax,%esi
+ andl $255,%esi
+ movl 2(%ebp,%esi,8),%esi
+ andl $255,%esi
+ movzbl %bh,%edi
+ movl (%ebp,%edi,8),%edi
+ andl $65280,%edi
+ xorl %edi,%esi
+ movl %ecx,%edi
+ shrl $16,%edi
+ andl $255,%edi
+ movl (%ebp,%edi,8),%edi
+ andl $16711680,%edi
+ xorl %edi,%esi
+ movl %edx,%edi
+ shrl $24,%edi
+ movl 2(%ebp,%edi,8),%edi
+ andl $4278190080,%edi
+ xorl %edi,%esi
+ movl %esi,4(%esp)
+ movl %ebx,%esi
+ andl $255,%esi
+ shrl $16,%ebx
+ movl 2(%ebp,%esi,8),%esi
+ andl $255,%esi
+ movzbl %ch,%edi
+ movl (%ebp,%edi,8),%edi
+ andl $65280,%edi
+ xorl %edi,%esi
+ movl %edx,%edi
+ shrl $16,%edi
+ andl $255,%edi
+ movl (%ebp,%edi,8),%edi
+ andl $16711680,%edi
+ xorl %edi,%esi
+ movl %eax,%edi
+ shrl $24,%edi
+ movl 2(%ebp,%edi,8),%edi
+ andl $4278190080,%edi
+ xorl %edi,%esi
+ movl %esi,8(%esp)
+ movl %ecx,%esi
+ andl $255,%esi
+ shrl $24,%ecx
+ movl 2(%ebp,%esi,8),%esi
+ andl $255,%esi
+ movzbl %dh,%edi
+ movl (%ebp,%edi,8),%edi
+ andl $65280,%edi
+ xorl %edi,%esi
+ movl %eax,%edi
+ shrl $16,%edi
+ andl $255,%edx
+ andl $255,%edi
+ movl (%ebp,%edi,8),%edi
+ andl $16711680,%edi
+ xorl %edi,%esi
+ movzbl %bh,%edi
+ movl 2(%ebp,%edi,8),%edi
+ andl $4278190080,%edi
+ xorl %edi,%esi
+ movl 20(%esp),%edi
+ andl $255,%edx
+ movl 2(%ebp,%edx,8),%edx
+ andl $255,%edx
+ movzbl %ah,%eax
+ movl (%ebp,%eax,8),%eax
+ andl $65280,%eax
+ xorl %eax,%edx
+ movl 4(%esp),%eax
+ andl $255,%ebx
+ movl (%ebp,%ebx,8),%ebx
+ andl $16711680,%ebx
+ xorl %ebx,%edx
+ movl 8(%esp),%ebx
+ movl 2(%ebp,%ecx,8),%ecx
+ andl $4278190080,%ecx
+ xorl %ecx,%edx
+ movl %esi,%ecx
+ addl $16,%edi
+ xorl (%edi),%eax
+ xorl 4(%edi),%ebx
+ xorl 8(%edi),%ecx
+ xorl 12(%edi),%edx
+ ret
+.align 64
+.LAES_Te:
+.long 2774754246,2774754246
+.long 2222750968,2222750968
+.long 2574743534,2574743534
+.long 2373680118,2373680118
+.long 234025727,234025727
+.long 3177933782,3177933782
+.long 2976870366,2976870366
+.long 1422247313,1422247313
+.long 1345335392,1345335392
+.long 50397442,50397442
+.long 2842126286,2842126286
+.long 2099981142,2099981142
+.long 436141799,436141799
+.long 1658312629,1658312629
+.long 3870010189,3870010189
+.long 2591454956,2591454956
+.long 1170918031,1170918031
+.long 2642575903,2642575903
+.long 1086966153,1086966153
+.long 2273148410,2273148410
+.long 368769775,368769775
+.long 3948501426,3948501426
+.long 3376891790,3376891790
+.long 200339707,200339707
+.long 3970805057,3970805057
+.long 1742001331,1742001331
+.long 4255294047,4255294047
+.long 3937382213,3937382213
+.long 3214711843,3214711843
+.long 4154762323,4154762323
+.long 2524082916,2524082916
+.long 1539358875,1539358875
+.long 3266819957,3266819957
+.long 486407649,486407649
+.long 2928907069,2928907069
+.long 1780885068,1780885068
+.long 1513502316,1513502316
+.long 1094664062,1094664062
+.long 49805301,49805301
+.long 1338821763,1338821763
+.long 1546925160,1546925160
+.long 4104496465,4104496465
+.long 887481809,887481809
+.long 150073849,150073849
+.long 2473685474,2473685474
+.long 1943591083,1943591083
+.long 1395732834,1395732834
+.long 1058346282,1058346282
+.long 201589768,201589768
+.long 1388824469,1388824469
+.long 1696801606,1696801606
+.long 1589887901,1589887901
+.long 672667696,672667696
+.long 2711000631,2711000631
+.long 251987210,251987210
+.long 3046808111,3046808111
+.long 151455502,151455502
+.long 907153956,907153956
+.long 2608889883,2608889883
+.long 1038279391,1038279391
+.long 652995533,652995533
+.long 1764173646,1764173646
+.long 3451040383,3451040383
+.long 2675275242,2675275242
+.long 453576978,453576978
+.long 2659418909,2659418909
+.long 1949051992,1949051992
+.long 773462580,773462580
+.long 756751158,756751158
+.long 2993581788,2993581788
+.long 3998898868,3998898868
+.long 4221608027,4221608027
+.long 4132590244,4132590244
+.long 1295727478,1295727478
+.long 1641469623,1641469623
+.long 3467883389,3467883389
+.long 2066295122,2066295122
+.long 1055122397,1055122397
+.long 1898917726,1898917726
+.long 2542044179,2542044179
+.long 4115878822,4115878822
+.long 1758581177,1758581177
+.long 0,0
+.long 753790401,753790401
+.long 1612718144,1612718144
+.long 536673507,536673507
+.long 3367088505,3367088505
+.long 3982187446,3982187446
+.long 3194645204,3194645204
+.long 1187761037,1187761037
+.long 3653156455,3653156455
+.long 1262041458,1262041458
+.long 3729410708,3729410708
+.long 3561770136,3561770136
+.long 3898103984,3898103984
+.long 1255133061,1255133061
+.long 1808847035,1808847035
+.long 720367557,720367557
+.long 3853167183,3853167183
+.long 385612781,385612781
+.long 3309519750,3309519750
+.long 3612167578,3612167578
+.long 1429418854,1429418854
+.long 2491778321,2491778321
+.long 3477423498,3477423498
+.long 284817897,284817897
+.long 100794884,100794884
+.long 2172616702,2172616702
+.long 4031795360,4031795360
+.long 1144798328,1144798328
+.long 3131023141,3131023141
+.long 3819481163,3819481163
+.long 4082192802,4082192802
+.long 4272137053,4272137053
+.long 3225436288,3225436288
+.long 2324664069,2324664069
+.long 2912064063,2912064063
+.long 3164445985,3164445985
+.long 1211644016,1211644016
+.long 83228145,83228145
+.long 3753688163,3753688163
+.long 3249976951,3249976951
+.long 1977277103,1977277103
+.long 1663115586,1663115586
+.long 806359072,806359072
+.long 452984805,452984805
+.long 250868733,250868733
+.long 1842533055,1842533055
+.long 1288555905,1288555905
+.long 336333848,336333848
+.long 890442534,890442534
+.long 804056259,804056259
+.long 3781124030,3781124030
+.long 2727843637,2727843637
+.long 3427026056,3427026056
+.long 957814574,957814574
+.long 1472513171,1472513171
+.long 4071073621,4071073621
+.long 2189328124,2189328124
+.long 1195195770,1195195770
+.long 2892260552,2892260552
+.long 3881655738,3881655738
+.long 723065138,723065138
+.long 2507371494,2507371494
+.long 2690670784,2690670784
+.long 2558624025,2558624025
+.long 3511635870,3511635870
+.long 2145180835,2145180835
+.long 1713513028,1713513028
+.long 2116692564,2116692564
+.long 2878378043,2878378043
+.long 2206763019,2206763019
+.long 3393603212,3393603212
+.long 703524551,703524551
+.long 3552098411,3552098411
+.long 1007948840,1007948840
+.long 2044649127,2044649127
+.long 3797835452,3797835452
+.long 487262998,487262998
+.long 1994120109,1994120109
+.long 1004593371,1004593371
+.long 1446130276,1446130276
+.long 1312438900,1312438900
+.long 503974420,503974420
+.long 3679013266,3679013266
+.long 168166924,168166924
+.long 1814307912,1814307912
+.long 3831258296,3831258296
+.long 1573044895,1573044895
+.long 1859376061,1859376061
+.long 4021070915,4021070915
+.long 2791465668,2791465668
+.long 2828112185,2828112185
+.long 2761266481,2761266481
+.long 937747667,937747667
+.long 2339994098,2339994098
+.long 854058965,854058965
+.long 1137232011,1137232011
+.long 1496790894,1496790894
+.long 3077402074,3077402074
+.long 2358086913,2358086913
+.long 1691735473,1691735473
+.long 3528347292,3528347292
+.long 3769215305,3769215305
+.long 3027004632,3027004632
+.long 4199962284,4199962284
+.long 133494003,133494003
+.long 636152527,636152527
+.long 2942657994,2942657994
+.long 2390391540,2390391540
+.long 3920539207,3920539207
+.long 403179536,403179536
+.long 3585784431,3585784431
+.long 2289596656,2289596656
+.long 1864705354,1864705354
+.long 1915629148,1915629148
+.long 605822008,605822008
+.long 4054230615,4054230615
+.long 3350508659,3350508659
+.long 1371981463,1371981463
+.long 602466507,602466507
+.long 2094914977,2094914977
+.long 2624877800,2624877800
+.long 555687742,555687742
+.long 3712699286,3712699286
+.long 3703422305,3703422305
+.long 2257292045,2257292045
+.long 2240449039,2240449039
+.long 2423288032,2423288032
+.long 1111375484,1111375484
+.long 3300242801,3300242801
+.long 2858837708,2858837708
+.long 3628615824,3628615824
+.long 84083462,84083462
+.long 32962295,32962295
+.long 302911004,302911004
+.long 2741068226,2741068226
+.long 1597322602,1597322602
+.long 4183250862,4183250862
+.long 3501832553,3501832553
+.long 2441512471,2441512471
+.long 1489093017,1489093017
+.long 656219450,656219450
+.long 3114180135,3114180135
+.long 954327513,954327513
+.long 335083755,335083755
+.long 3013122091,3013122091
+.long 856756514,856756514
+.long 3144247762,3144247762
+.long 1893325225,1893325225
+.long 2307821063,2307821063
+.long 2811532339,2811532339
+.long 3063651117,3063651117
+.long 572399164,572399164
+.long 2458355477,2458355477
+.long 552200649,552200649
+.long 1238290055,1238290055
+.long 4283782570,4283782570
+.long 2015897680,2015897680
+.long 2061492133,2061492133
+.long 2408352771,2408352771
+.long 4171342169,4171342169
+.long 2156497161,2156497161
+.long 386731290,386731290
+.long 3669999461,3669999461
+.long 837215959,837215959
+.long 3326231172,3326231172
+.long 3093850320,3093850320
+.long 3275833730,3275833730
+.long 2962856233,2962856233
+.long 1999449434,1999449434
+.long 286199582,286199582
+.long 3417354363,3417354363
+.long 4233385128,4233385128
+.long 3602627437,3602627437
+.long 974525996,974525996
+.byte 99,124,119,123,242,107,111,197
+.byte 48,1,103,43,254,215,171,118
+.byte 202,130,201,125,250,89,71,240
+.byte 173,212,162,175,156,164,114,192
+.byte 183,253,147,38,54,63,247,204
+.byte 52,165,229,241,113,216,49,21
+.byte 4,199,35,195,24,150,5,154
+.byte 7,18,128,226,235,39,178,117
+.byte 9,131,44,26,27,110,90,160
+.byte 82,59,214,179,41,227,47,132
+.byte 83,209,0,237,32,252,177,91
+.byte 106,203,190,57,74,76,88,207
+.byte 208,239,170,251,67,77,51,133
+.byte 69,249,2,127,80,60,159,168
+.byte 81,163,64,143,146,157,56,245
+.byte 188,182,218,33,16,255,243,210
+.byte 205,12,19,236,95,151,68,23
+.byte 196,167,126,61,100,93,25,115
+.byte 96,129,79,220,34,42,144,136
+.byte 70,238,184,20,222,94,11,219
+.byte 224,50,58,10,73,6,36,92
+.byte 194,211,172,98,145,149,228,121
+.byte 231,200,55,109,141,213,78,169
+.byte 108,86,244,234,101,122,174,8
+.byte 186,120,37,46,28,166,180,198
+.byte 232,221,116,31,75,189,139,138
+.byte 112,62,181,102,72,3,246,14
+.byte 97,53,87,185,134,193,29,158
+.byte 225,248,152,17,105,217,142,148
+.byte 155,30,135,233,206,85,40,223
+.byte 140,161,137,13,191,230,66,104
+.byte 65,153,45,15,176,84,187,22
+.byte 99,124,119,123,242,107,111,197
+.byte 48,1,103,43,254,215,171,118
+.byte 202,130,201,125,250,89,71,240
+.byte 173,212,162,175,156,164,114,192
+.byte 183,253,147,38,54,63,247,204
+.byte 52,165,229,241,113,216,49,21
+.byte 4,199,35,195,24,150,5,154
+.byte 7,18,128,226,235,39,178,117
+.byte 9,131,44,26,27,110,90,160
+.byte 82,59,214,179,41,227,47,132
+.byte 83,209,0,237,32,252,177,91
+.byte 106,203,190,57,74,76,88,207
+.byte 208,239,170,251,67,77,51,133
+.byte 69,249,2,127,80,60,159,168
+.byte 81,163,64,143,146,157,56,245
+.byte 188,182,218,33,16,255,243,210
+.byte 205,12,19,236,95,151,68,23
+.byte 196,167,126,61,100,93,25,115
+.byte 96,129,79,220,34,42,144,136
+.byte 70,238,184,20,222,94,11,219
+.byte 224,50,58,10,73,6,36,92
+.byte 194,211,172,98,145,149,228,121
+.byte 231,200,55,109,141,213,78,169
+.byte 108,86,244,234,101,122,174,8
+.byte 186,120,37,46,28,166,180,198
+.byte 232,221,116,31,75,189,139,138
+.byte 112,62,181,102,72,3,246,14
+.byte 97,53,87,185,134,193,29,158
+.byte 225,248,152,17,105,217,142,148
+.byte 155,30,135,233,206,85,40,223
+.byte 140,161,137,13,191,230,66,104
+.byte 65,153,45,15,176,84,187,22
+.byte 99,124,119,123,242,107,111,197
+.byte 48,1,103,43,254,215,171,118
+.byte 202,130,201,125,250,89,71,240
+.byte 173,212,162,175,156,164,114,192
+.byte 183,253,147,38,54,63,247,204
+.byte 52,165,229,241,113,216,49,21
+.byte 4,199,35,195,24,150,5,154
+.byte 7,18,128,226,235,39,178,117
+.byte 9,131,44,26,27,110,90,160
+.byte 82,59,214,179,41,227,47,132
+.byte 83,209,0,237,32,252,177,91
+.byte 106,203,190,57,74,76,88,207
+.byte 208,239,170,251,67,77,51,133
+.byte 69,249,2,127,80,60,159,168
+.byte 81,163,64,143,146,157,56,245
+.byte 188,182,218,33,16,255,243,210
+.byte 205,12,19,236,95,151,68,23
+.byte 196,167,126,61,100,93,25,115
+.byte 96,129,79,220,34,42,144,136
+.byte 70,238,184,20,222,94,11,219
+.byte 224,50,58,10,73,6,36,92
+.byte 194,211,172,98,145,149,228,121
+.byte 231,200,55,109,141,213,78,169
+.byte 108,86,244,234,101,122,174,8
+.byte 186,120,37,46,28,166,180,198
+.byte 232,221,116,31,75,189,139,138
+.byte 112,62,181,102,72,3,246,14
+.byte 97,53,87,185,134,193,29,158
+.byte 225,248,152,17,105,217,142,148
+.byte 155,30,135,233,206,85,40,223
+.byte 140,161,137,13,191,230,66,104
+.byte 65,153,45,15,176,84,187,22
+.byte 99,124,119,123,242,107,111,197
+.byte 48,1,103,43,254,215,171,118
+.byte 202,130,201,125,250,89,71,240
+.byte 173,212,162,175,156,164,114,192
+.byte 183,253,147,38,54,63,247,204
+.byte 52,165,229,241,113,216,49,21
+.byte 4,199,35,195,24,150,5,154
+.byte 7,18,128,226,235,39,178,117
+.byte 9,131,44,26,27,110,90,160
+.byte 82,59,214,179,41,227,47,132
+.byte 83,209,0,237,32,252,177,91
+.byte 106,203,190,57,74,76,88,207
+.byte 208,239,170,251,67,77,51,133
+.byte 69,249,2,127,80,60,159,168
+.byte 81,163,64,143,146,157,56,245
+.byte 188,182,218,33,16,255,243,210
+.byte 205,12,19,236,95,151,68,23
+.byte 196,167,126,61,100,93,25,115
+.byte 96,129,79,220,34,42,144,136
+.byte 70,238,184,20,222,94,11,219
+.byte 224,50,58,10,73,6,36,92
+.byte 194,211,172,98,145,149,228,121
+.byte 231,200,55,109,141,213,78,169
+.byte 108,86,244,234,101,122,174,8
+.byte 186,120,37,46,28,166,180,198
+.byte 232,221,116,31,75,189,139,138
+.byte 112,62,181,102,72,3,246,14
+.byte 97,53,87,185,134,193,29,158
+.byte 225,248,152,17,105,217,142,148
+.byte 155,30,135,233,206,85,40,223
+.byte 140,161,137,13,191,230,66,104
+.byte 65,153,45,15,176,84,187,22
+.long 1,2,4,8
+.long 16,32,64,128
+.long 27,54,0,0
+.long 0,0,0,0
+.size _x86_AES_encrypt,.-_x86_AES_encrypt
+.globl asm_AES_encrypt
+.hidden asm_AES_encrypt
+.type asm_AES_encrypt,@function
+.align 16
+asm_AES_encrypt:
+.L_asm_AES_encrypt_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ movl 20(%esp),%esi
+ movl 28(%esp),%edi
+ movl %esp,%eax
+ subl $36,%esp
+ andl $-64,%esp
+ leal -127(%edi),%ebx
+ subl %esp,%ebx
+ negl %ebx
+ andl $960,%ebx
+ subl %ebx,%esp
+ addl $4,%esp
+ movl %eax,28(%esp)
+ call .L004pic_point
+.L004pic_point:
+ popl %ebp
+ leal OPENSSL_ia32cap_P-.L004pic_point(%ebp),%eax
+ leal .LAES_Te-.L004pic_point(%ebp),%ebp
+ leal 764(%esp),%ebx
+ subl %ebp,%ebx
+ andl $768,%ebx
+ leal 2176(%ebp,%ebx,1),%ebp
+ btl $25,(%eax)
+ jnc .L005x86
+ movq (%esi),%mm0
+ movq 8(%esi),%mm4
+ call _sse_AES_encrypt_compact
+ movl 28(%esp),%esp
+ movl 24(%esp),%esi
+ movq %mm0,(%esi)
+ movq %mm4,8(%esi)
+ emms
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.align 16
+.L005x86:
+ movl %ebp,24(%esp)
+ movl (%esi),%eax
+ movl 4(%esi),%ebx
+ movl 8(%esi),%ecx
+ movl 12(%esi),%edx
+ call _x86_AES_encrypt_compact
+ movl 28(%esp),%esp
+ movl 24(%esp),%esi
+ movl %eax,(%esi)
+ movl %ebx,4(%esi)
+ movl %ecx,8(%esi)
+ movl %edx,12(%esi)
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.size asm_AES_encrypt,.-.L_asm_AES_encrypt_begin
+.hidden _x86_AES_decrypt_compact
+.type _x86_AES_decrypt_compact,@function
+.align 16
+_x86_AES_decrypt_compact:
+ movl %edi,20(%esp)
+ xorl (%edi),%eax
+ xorl 4(%edi),%ebx
+ xorl 8(%edi),%ecx
+ xorl 12(%edi),%edx
+ movl 240(%edi),%esi
+ leal -2(%esi,%esi,1),%esi
+ leal (%edi,%esi,8),%esi
+ movl %esi,24(%esp)
+ movl -128(%ebp),%edi
+ movl -96(%ebp),%esi
+ movl -64(%ebp),%edi
+ movl -32(%ebp),%esi
+ movl (%ebp),%edi
+ movl 32(%ebp),%esi
+ movl 64(%ebp),%edi
+ movl 96(%ebp),%esi
+.align 16
+.L006loop:
+ movl %eax,%esi
+ andl $255,%esi
+ movzbl -128(%ebp,%esi,1),%esi
+ movzbl %dh,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $8,%edi
+ xorl %edi,%esi
+ movl %ecx,%edi
+ shrl $16,%edi
+ andl $255,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $16,%edi
+ xorl %edi,%esi
+ movl %ebx,%edi
+ shrl $24,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $24,%edi
+ xorl %edi,%esi
+ movl %esi,4(%esp)
+ movl %ebx,%esi
+ andl $255,%esi
+ movzbl -128(%ebp,%esi,1),%esi
+ movzbl %ah,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $8,%edi
+ xorl %edi,%esi
+ movl %edx,%edi
+ shrl $16,%edi
+ andl $255,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $16,%edi
+ xorl %edi,%esi
+ movl %ecx,%edi
+ shrl $24,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $24,%edi
+ xorl %edi,%esi
+ movl %esi,8(%esp)
+ movl %ecx,%esi
+ andl $255,%esi
+ movzbl -128(%ebp,%esi,1),%esi
+ movzbl %bh,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $8,%edi
+ xorl %edi,%esi
+ movl %eax,%edi
+ shrl $16,%edi
+ andl $255,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $16,%edi
+ xorl %edi,%esi
+ movl %edx,%edi
+ shrl $24,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $24,%edi
+ xorl %edi,%esi
+ andl $255,%edx
+ movzbl -128(%ebp,%edx,1),%edx
+ movzbl %ch,%ecx
+ movzbl -128(%ebp,%ecx,1),%ecx
+ shll $8,%ecx
+ xorl %ecx,%edx
+ movl %esi,%ecx
+ shrl $16,%ebx
+ andl $255,%ebx
+ movzbl -128(%ebp,%ebx,1),%ebx
+ shll $16,%ebx
+ xorl %ebx,%edx
+ shrl $24,%eax
+ movzbl -128(%ebp,%eax,1),%eax
+ shll $24,%eax
+ xorl %eax,%edx
+ movl $2155905152,%edi
+ andl %ecx,%edi
+ movl %edi,%esi
+ shrl $7,%edi
+ leal (%ecx,%ecx,1),%eax
+ subl %edi,%esi
+ andl $4278124286,%eax
+ andl $454761243,%esi
+ xorl %esi,%eax
+ movl $2155905152,%edi
+ andl %eax,%edi
+ movl %edi,%esi
+ shrl $7,%edi
+ leal (%eax,%eax,1),%ebx
+ subl %edi,%esi
+ andl $4278124286,%ebx
+ andl $454761243,%esi
+ xorl %ecx,%eax
+ xorl %esi,%ebx
+ movl $2155905152,%edi
+ andl %ebx,%edi
+ movl %edi,%esi
+ shrl $7,%edi
+ leal (%ebx,%ebx,1),%ebp
+ subl %edi,%esi
+ andl $4278124286,%ebp
+ andl $454761243,%esi
+ xorl %ecx,%ebx
+ roll $8,%ecx
+ xorl %esi,%ebp
+ xorl %eax,%ecx
+ xorl %ebp,%eax
+ xorl %ebx,%ecx
+ xorl %ebp,%ebx
+ roll $24,%eax
+ xorl %ebp,%ecx
+ roll $16,%ebx
+ xorl %eax,%ecx
+ roll $8,%ebp
+ xorl %ebx,%ecx
+ movl 4(%esp),%eax
+ xorl %ebp,%ecx
+ movl %ecx,12(%esp)
+ movl $2155905152,%edi
+ andl %edx,%edi
+ movl %edi,%esi
+ shrl $7,%edi
+ leal (%edx,%edx,1),%ebx
+ subl %edi,%esi
+ andl $4278124286,%ebx
+ andl $454761243,%esi
+ xorl %esi,%ebx
+ movl $2155905152,%edi
+ andl %ebx,%edi
+ movl %edi,%esi
+ shrl $7,%edi
+ leal (%ebx,%ebx,1),%ecx
+ subl %edi,%esi
+ andl $4278124286,%ecx
+ andl $454761243,%esi
+ xorl %edx,%ebx
+ xorl %esi,%ecx
+ movl $2155905152,%edi
+ andl %ecx,%edi
+ movl %edi,%esi
+ shrl $7,%edi
+ leal (%ecx,%ecx,1),%ebp
+ subl %edi,%esi
+ andl $4278124286,%ebp
+ andl $454761243,%esi
+ xorl %edx,%ecx
+ roll $8,%edx
+ xorl %esi,%ebp
+ xorl %ebx,%edx
+ xorl %ebp,%ebx
+ xorl %ecx,%edx
+ xorl %ebp,%ecx
+ roll $24,%ebx
+ xorl %ebp,%edx
+ roll $16,%ecx
+ xorl %ebx,%edx
+ roll $8,%ebp
+ xorl %ecx,%edx
+ movl 8(%esp),%ebx
+ xorl %ebp,%edx
+ movl %edx,16(%esp)
+ movl $2155905152,%edi
+ andl %eax,%edi
+ movl %edi,%esi
+ shrl $7,%edi
+ leal (%eax,%eax,1),%ecx
+ subl %edi,%esi
+ andl $4278124286,%ecx
+ andl $454761243,%esi
+ xorl %esi,%ecx
+ movl $2155905152,%edi
+ andl %ecx,%edi
+ movl %edi,%esi
+ shrl $7,%edi
+ leal (%ecx,%ecx,1),%edx
+ subl %edi,%esi
+ andl $4278124286,%edx
+ andl $454761243,%esi
+ xorl %eax,%ecx
+ xorl %esi,%edx
+ movl $2155905152,%edi
+ andl %edx,%edi
+ movl %edi,%esi
+ shrl $7,%edi
+ leal (%edx,%edx,1),%ebp
+ subl %edi,%esi
+ andl $4278124286,%ebp
+ andl $454761243,%esi
+ xorl %eax,%edx
+ roll $8,%eax
+ xorl %esi,%ebp
+ xorl %ecx,%eax
+ xorl %ebp,%ecx
+ xorl %edx,%eax
+ xorl %ebp,%edx
+ roll $24,%ecx
+ xorl %ebp,%eax
+ roll $16,%edx
+ xorl %ecx,%eax
+ roll $8,%ebp
+ xorl %edx,%eax
+ xorl %ebp,%eax
+ movl $2155905152,%edi
+ andl %ebx,%edi
+ movl %edi,%esi
+ shrl $7,%edi
+ leal (%ebx,%ebx,1),%ecx
+ subl %edi,%esi
+ andl $4278124286,%ecx
+ andl $454761243,%esi
+ xorl %esi,%ecx
+ movl $2155905152,%edi
+ andl %ecx,%edi
+ movl %edi,%esi
+ shrl $7,%edi
+ leal (%ecx,%ecx,1),%edx
+ subl %edi,%esi
+ andl $4278124286,%edx
+ andl $454761243,%esi
+ xorl %ebx,%ecx
+ xorl %esi,%edx
+ movl $2155905152,%edi
+ andl %edx,%edi
+ movl %edi,%esi
+ shrl $7,%edi
+ leal (%edx,%edx,1),%ebp
+ subl %edi,%esi
+ andl $4278124286,%ebp
+ andl $454761243,%esi
+ xorl %ebx,%edx
+ roll $8,%ebx
+ xorl %esi,%ebp
+ xorl %ecx,%ebx
+ xorl %ebp,%ecx
+ xorl %edx,%ebx
+ xorl %ebp,%edx
+ roll $24,%ecx
+ xorl %ebp,%ebx
+ roll $16,%edx
+ xorl %ecx,%ebx
+ roll $8,%ebp
+ xorl %edx,%ebx
+ movl 12(%esp),%ecx
+ xorl %ebp,%ebx
+ movl 16(%esp),%edx
+ movl 20(%esp),%edi
+ movl 28(%esp),%ebp
+ addl $16,%edi
+ xorl (%edi),%eax
+ xorl 4(%edi),%ebx
+ xorl 8(%edi),%ecx
+ xorl 12(%edi),%edx
+ cmpl 24(%esp),%edi
+ movl %edi,20(%esp)
+ jb .L006loop
+ movl %eax,%esi
+ andl $255,%esi
+ movzbl -128(%ebp,%esi,1),%esi
+ movzbl %dh,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $8,%edi
+ xorl %edi,%esi
+ movl %ecx,%edi
+ shrl $16,%edi
+ andl $255,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $16,%edi
+ xorl %edi,%esi
+ movl %ebx,%edi
+ shrl $24,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $24,%edi
+ xorl %edi,%esi
+ movl %esi,4(%esp)
+ movl %ebx,%esi
+ andl $255,%esi
+ movzbl -128(%ebp,%esi,1),%esi
+ movzbl %ah,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $8,%edi
+ xorl %edi,%esi
+ movl %edx,%edi
+ shrl $16,%edi
+ andl $255,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $16,%edi
+ xorl %edi,%esi
+ movl %ecx,%edi
+ shrl $24,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $24,%edi
+ xorl %edi,%esi
+ movl %esi,8(%esp)
+ movl %ecx,%esi
+ andl $255,%esi
+ movzbl -128(%ebp,%esi,1),%esi
+ movzbl %bh,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $8,%edi
+ xorl %edi,%esi
+ movl %eax,%edi
+ shrl $16,%edi
+ andl $255,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $16,%edi
+ xorl %edi,%esi
+ movl %edx,%edi
+ shrl $24,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $24,%edi
+ xorl %edi,%esi
+ movl 20(%esp),%edi
+ andl $255,%edx
+ movzbl -128(%ebp,%edx,1),%edx
+ movzbl %ch,%ecx
+ movzbl -128(%ebp,%ecx,1),%ecx
+ shll $8,%ecx
+ xorl %ecx,%edx
+ movl %esi,%ecx
+ shrl $16,%ebx
+ andl $255,%ebx
+ movzbl -128(%ebp,%ebx,1),%ebx
+ shll $16,%ebx
+ xorl %ebx,%edx
+ movl 8(%esp),%ebx
+ shrl $24,%eax
+ movzbl -128(%ebp,%eax,1),%eax
+ shll $24,%eax
+ xorl %eax,%edx
+ movl 4(%esp),%eax
+ xorl 16(%edi),%eax
+ xorl 20(%edi),%ebx
+ xorl 24(%edi),%ecx
+ xorl 28(%edi),%edx
+ ret
+.size _x86_AES_decrypt_compact,.-_x86_AES_decrypt_compact
+.hidden _sse_AES_decrypt_compact
+.type _sse_AES_decrypt_compact,@function
+.align 16
+_sse_AES_decrypt_compact:
+ pxor (%edi),%mm0
+ pxor 8(%edi),%mm4
+ movl 240(%edi),%esi
+ leal -2(%esi,%esi,1),%esi
+ leal (%edi,%esi,8),%esi
+ movl %esi,24(%esp)
+ movl $454761243,%eax
+ movl %eax,8(%esp)
+ movl %eax,12(%esp)
+ movl -128(%ebp),%eax
+ movl -96(%ebp),%ebx
+ movl -64(%ebp),%ecx
+ movl -32(%ebp),%edx
+ movl (%ebp),%eax
+ movl 32(%ebp),%ebx
+ movl 64(%ebp),%ecx
+ movl 96(%ebp),%edx
+.align 16
+.L007loop:
+ pshufw $12,%mm0,%mm1
+ pshufw $9,%mm4,%mm5
+ movd %mm1,%eax
+ movd %mm5,%ebx
+ movl %edi,20(%esp)
+ movzbl %al,%esi
+ movzbl %ah,%edx
+ pshufw $6,%mm0,%mm2
+ movzbl -128(%ebp,%esi,1),%ecx
+ movzbl %bl,%edi
+ movzbl -128(%ebp,%edx,1),%edx
+ shrl $16,%eax
+ shll $8,%edx
+ movzbl -128(%ebp,%edi,1),%esi
+ movzbl %bh,%edi
+ shll $16,%esi
+ pshufw $3,%mm4,%mm6
+ orl %esi,%ecx
+ movzbl -128(%ebp,%edi,1),%esi
+ movzbl %ah,%edi
+ shll $24,%esi
+ shrl $16,%ebx
+ orl %esi,%edx
+ movzbl -128(%ebp,%edi,1),%esi
+ movzbl %bh,%edi
+ shll $24,%esi
+ orl %esi,%ecx
+ movzbl -128(%ebp,%edi,1),%esi
+ movzbl %al,%edi
+ shll $8,%esi
+ movd %mm2,%eax
+ orl %esi,%ecx
+ movzbl -128(%ebp,%edi,1),%esi
+ movzbl %bl,%edi
+ shll $16,%esi
+ movd %mm6,%ebx
+ movd %ecx,%mm0
+ movzbl -128(%ebp,%edi,1),%ecx
+ movzbl %al,%edi
+ orl %esi,%ecx
+ movzbl -128(%ebp,%edi,1),%esi
+ movzbl %bl,%edi
+ orl %esi,%edx
+ movzbl -128(%ebp,%edi,1),%esi
+ movzbl %ah,%edi
+ shll $16,%esi
+ shrl $16,%eax
+ orl %esi,%edx
+ movzbl -128(%ebp,%edi,1),%esi
+ movzbl %bh,%edi
+ shrl $16,%ebx
+ shll $8,%esi
+ movd %edx,%mm1
+ movzbl -128(%ebp,%edi,1),%edx
+ movzbl %bh,%edi
+ shll $24,%edx
+ andl $255,%ebx
+ orl %esi,%edx
+ punpckldq %mm1,%mm0
+ movzbl -128(%ebp,%edi,1),%esi
+ movzbl %al,%edi
+ shll $8,%esi
+ movzbl %ah,%eax
+ movzbl -128(%ebp,%ebx,1),%ebx
+ orl %esi,%ecx
+ movzbl -128(%ebp,%edi,1),%esi
+ orl %ebx,%edx
+ shll $16,%esi
+ movzbl -128(%ebp,%eax,1),%eax
+ orl %esi,%edx
+ shll $24,%eax
+ orl %eax,%ecx
+ movl 20(%esp),%edi
+ movd %edx,%mm4
+ movd %ecx,%mm5
+ punpckldq %mm5,%mm4
+ addl $16,%edi
+ cmpl 24(%esp),%edi
+ ja .L008out
+ movq %mm0,%mm3
+ movq %mm4,%mm7
+ pshufw $228,%mm0,%mm2
+ pshufw $228,%mm4,%mm6
+ movq %mm0,%mm1
+ movq %mm4,%mm5
+ pshufw $177,%mm0,%mm0
+ pshufw $177,%mm4,%mm4
+ pslld $8,%mm2
+ pslld $8,%mm6
+ psrld $8,%mm3
+ psrld $8,%mm7
+ pxor %mm2,%mm0
+ pxor %mm6,%mm4
+ pxor %mm3,%mm0
+ pxor %mm7,%mm4
+ pslld $16,%mm2
+ pslld $16,%mm6
+ psrld $16,%mm3
+ psrld $16,%mm7
+ pxor %mm2,%mm0
+ pxor %mm6,%mm4
+ pxor %mm3,%mm0
+ pxor %mm7,%mm4
+ movq 8(%esp),%mm3
+ pxor %mm2,%mm2
+ pxor %mm6,%mm6
+ pcmpgtb %mm1,%mm2
+ pcmpgtb %mm5,%mm6
+ pand %mm3,%mm2
+ pand %mm3,%mm6
+ paddb %mm1,%mm1
+ paddb %mm5,%mm5
+ pxor %mm2,%mm1
+ pxor %mm6,%mm5
+ movq %mm1,%mm3
+ movq %mm5,%mm7
+ movq %mm1,%mm2
+ movq %mm5,%mm6
+ pxor %mm1,%mm0
+ pxor %mm5,%mm4
+ pslld $24,%mm3
+ pslld $24,%mm7
+ psrld $8,%mm2
+ psrld $8,%mm6
+ pxor %mm3,%mm0
+ pxor %mm7,%mm4
+ pxor %mm2,%mm0
+ pxor %mm6,%mm4
+ movq 8(%esp),%mm2
+ pxor %mm3,%mm3
+ pxor %mm7,%mm7
+ pcmpgtb %mm1,%mm3
+ pcmpgtb %mm5,%mm7
+ pand %mm2,%mm3
+ pand %mm2,%mm7
+ paddb %mm1,%mm1
+ paddb %mm5,%mm5
+ pxor %mm3,%mm1
+ pxor %mm7,%mm5
+ pshufw $177,%mm1,%mm3
+ pshufw $177,%mm5,%mm7
+ pxor %mm1,%mm0
+ pxor %mm5,%mm4
+ pxor %mm3,%mm0
+ pxor %mm7,%mm4
+ pxor %mm3,%mm3
+ pxor %mm7,%mm7
+ pcmpgtb %mm1,%mm3
+ pcmpgtb %mm5,%mm7
+ pand %mm2,%mm3
+ pand %mm2,%mm7
+ paddb %mm1,%mm1
+ paddb %mm5,%mm5
+ pxor %mm3,%mm1
+ pxor %mm7,%mm5
+ pxor %mm1,%mm0
+ pxor %mm5,%mm4
+ movq %mm1,%mm3
+ movq %mm5,%mm7
+ pshufw $177,%mm1,%mm2
+ pshufw $177,%mm5,%mm6
+ pxor %mm2,%mm0
+ pxor %mm6,%mm4
+ pslld $8,%mm1
+ pslld $8,%mm5
+ psrld $8,%mm3
+ psrld $8,%mm7
+ movq (%edi),%mm2
+ movq 8(%edi),%mm6
+ pxor %mm1,%mm0
+ pxor %mm5,%mm4
+ pxor %mm3,%mm0
+ pxor %mm7,%mm4
+ movl -128(%ebp),%eax
+ pslld $16,%mm1
+ pslld $16,%mm5
+ movl -64(%ebp),%ebx
+ psrld $16,%mm3
+ psrld $16,%mm7
+ movl (%ebp),%ecx
+ pxor %mm1,%mm0
+ pxor %mm5,%mm4
+ movl 64(%ebp),%edx
+ pxor %mm3,%mm0
+ pxor %mm7,%mm4
+ pxor %mm2,%mm0
+ pxor %mm6,%mm4
+ jmp .L007loop
+.align 16
+.L008out:
+ pxor (%edi),%mm0
+ pxor 8(%edi),%mm4
+ ret
+.size _sse_AES_decrypt_compact,.-_sse_AES_decrypt_compact
+.hidden _x86_AES_decrypt
+.type _x86_AES_decrypt,@function
+.align 16
+_x86_AES_decrypt:
+ movl %edi,20(%esp)
+ xorl (%edi),%eax
+ xorl 4(%edi),%ebx
+ xorl 8(%edi),%ecx
+ xorl 12(%edi),%edx
+ movl 240(%edi),%esi
+ leal -2(%esi,%esi,1),%esi
+ leal (%edi,%esi,8),%esi
+ movl %esi,24(%esp)
+.align 16
+.L009loop:
+ movl %eax,%esi
+ andl $255,%esi
+ movl (%ebp,%esi,8),%esi
+ movzbl %dh,%edi
+ xorl 3(%ebp,%edi,8),%esi
+ movl %ecx,%edi
+ shrl $16,%edi
+ andl $255,%edi
+ xorl 2(%ebp,%edi,8),%esi
+ movl %ebx,%edi
+ shrl $24,%edi
+ xorl 1(%ebp,%edi,8),%esi
+ movl %esi,4(%esp)
+
+ movl %ebx,%esi
+ andl $255,%esi
+ movl (%ebp,%esi,8),%esi
+ movzbl %ah,%edi
+ xorl 3(%ebp,%edi,8),%esi
+ movl %edx,%edi
+ shrl $16,%edi
+ andl $255,%edi
+ xorl 2(%ebp,%edi,8),%esi
+ movl %ecx,%edi
+ shrl $24,%edi
+ xorl 1(%ebp,%edi,8),%esi
+ movl %esi,8(%esp)
+
+ movl %ecx,%esi
+ andl $255,%esi
+ movl (%ebp,%esi,8),%esi
+ movzbl %bh,%edi
+ xorl 3(%ebp,%edi,8),%esi
+ movl %eax,%edi
+ shrl $16,%edi
+ andl $255,%edi
+ xorl 2(%ebp,%edi,8),%esi
+ movl %edx,%edi
+ shrl $24,%edi
+ xorl 1(%ebp,%edi,8),%esi
+
+ movl 20(%esp),%edi
+ andl $255,%edx
+ movl (%ebp,%edx,8),%edx
+ movzbl %ch,%ecx
+ xorl 3(%ebp,%ecx,8),%edx
+ movl %esi,%ecx
+ shrl $16,%ebx
+ andl $255,%ebx
+ xorl 2(%ebp,%ebx,8),%edx
+ movl 8(%esp),%ebx
+ shrl $24,%eax
+ xorl 1(%ebp,%eax,8),%edx
+ movl 4(%esp),%eax
+
+ addl $16,%edi
+ xorl (%edi),%eax
+ xorl 4(%edi),%ebx
+ xorl 8(%edi),%ecx
+ xorl 12(%edi),%edx
+ cmpl 24(%esp),%edi
+ movl %edi,20(%esp)
+ jb .L009loop
+ leal 2176(%ebp),%ebp
+ movl -128(%ebp),%edi
+ movl -96(%ebp),%esi
+ movl -64(%ebp),%edi
+ movl -32(%ebp),%esi
+ movl (%ebp),%edi
+ movl 32(%ebp),%esi
+ movl 64(%ebp),%edi
+ movl 96(%ebp),%esi
+ leal -128(%ebp),%ebp
+ movl %eax,%esi
+ andl $255,%esi
+ movzbl (%ebp,%esi,1),%esi
+ movzbl %dh,%edi
+ movzbl (%ebp,%edi,1),%edi
+ shll $8,%edi
+ xorl %edi,%esi
+ movl %ecx,%edi
+ shrl $16,%edi
+ andl $255,%edi
+ movzbl (%ebp,%edi,1),%edi
+ shll $16,%edi
+ xorl %edi,%esi
+ movl %ebx,%edi
+ shrl $24,%edi
+ movzbl (%ebp,%edi,1),%edi
+ shll $24,%edi
+ xorl %edi,%esi
+ movl %esi,4(%esp)
+ movl %ebx,%esi
+ andl $255,%esi
+ movzbl (%ebp,%esi,1),%esi
+ movzbl %ah,%edi
+ movzbl (%ebp,%edi,1),%edi
+ shll $8,%edi
+ xorl %edi,%esi
+ movl %edx,%edi
+ shrl $16,%edi
+ andl $255,%edi
+ movzbl (%ebp,%edi,1),%edi
+ shll $16,%edi
+ xorl %edi,%esi
+ movl %ecx,%edi
+ shrl $24,%edi
+ movzbl (%ebp,%edi,1),%edi
+ shll $24,%edi
+ xorl %edi,%esi
+ movl %esi,8(%esp)
+ movl %ecx,%esi
+ andl $255,%esi
+ movzbl (%ebp,%esi,1),%esi
+ movzbl %bh,%edi
+ movzbl (%ebp,%edi,1),%edi
+ shll $8,%edi
+ xorl %edi,%esi
+ movl %eax,%edi
+ shrl $16,%edi
+ andl $255,%edi
+ movzbl (%ebp,%edi,1),%edi
+ shll $16,%edi
+ xorl %edi,%esi
+ movl %edx,%edi
+ shrl $24,%edi
+ movzbl (%ebp,%edi,1),%edi
+ shll $24,%edi
+ xorl %edi,%esi
+ movl 20(%esp),%edi
+ andl $255,%edx
+ movzbl (%ebp,%edx,1),%edx
+ movzbl %ch,%ecx
+ movzbl (%ebp,%ecx,1),%ecx
+ shll $8,%ecx
+ xorl %ecx,%edx
+ movl %esi,%ecx
+ shrl $16,%ebx
+ andl $255,%ebx
+ movzbl (%ebp,%ebx,1),%ebx
+ shll $16,%ebx
+ xorl %ebx,%edx
+ movl 8(%esp),%ebx
+ shrl $24,%eax
+ movzbl (%ebp,%eax,1),%eax
+ shll $24,%eax
+ xorl %eax,%edx
+ movl 4(%esp),%eax
+ leal -2048(%ebp),%ebp
+ addl $16,%edi
+ xorl (%edi),%eax
+ xorl 4(%edi),%ebx
+ xorl 8(%edi),%ecx
+ xorl 12(%edi),%edx
+ ret
+.align 64
+.LAES_Td:
+.long 1353184337,1353184337
+.long 1399144830,1399144830
+.long 3282310938,3282310938
+.long 2522752826,2522752826
+.long 3412831035,3412831035
+.long 4047871263,4047871263
+.long 2874735276,2874735276
+.long 2466505547,2466505547
+.long 1442459680,1442459680
+.long 4134368941,4134368941
+.long 2440481928,2440481928
+.long 625738485,625738485
+.long 4242007375,4242007375
+.long 3620416197,3620416197
+.long 2151953702,2151953702
+.long 2409849525,2409849525
+.long 1230680542,1230680542
+.long 1729870373,1729870373
+.long 2551114309,2551114309
+.long 3787521629,3787521629
+.long 41234371,41234371
+.long 317738113,317738113
+.long 2744600205,2744600205
+.long 3338261355,3338261355
+.long 3881799427,3881799427
+.long 2510066197,2510066197
+.long 3950669247,3950669247
+.long 3663286933,3663286933
+.long 763608788,763608788
+.long 3542185048,3542185048
+.long 694804553,694804553
+.long 1154009486,1154009486
+.long 1787413109,1787413109
+.long 2021232372,2021232372
+.long 1799248025,1799248025
+.long 3715217703,3715217703
+.long 3058688446,3058688446
+.long 397248752,397248752
+.long 1722556617,1722556617
+.long 3023752829,3023752829
+.long 407560035,407560035
+.long 2184256229,2184256229
+.long 1613975959,1613975959
+.long 1165972322,1165972322
+.long 3765920945,3765920945
+.long 2226023355,2226023355
+.long 480281086,480281086
+.long 2485848313,2485848313
+.long 1483229296,1483229296
+.long 436028815,436028815
+.long 2272059028,2272059028
+.long 3086515026,3086515026
+.long 601060267,601060267
+.long 3791801202,3791801202
+.long 1468997603,1468997603
+.long 715871590,715871590
+.long 120122290,120122290
+.long 63092015,63092015
+.long 2591802758,2591802758
+.long 2768779219,2768779219
+.long 4068943920,4068943920
+.long 2997206819,2997206819
+.long 3127509762,3127509762
+.long 1552029421,1552029421
+.long 723308426,723308426
+.long 2461301159,2461301159
+.long 4042393587,4042393587
+.long 2715969870,2715969870
+.long 3455375973,3455375973
+.long 3586000134,3586000134
+.long 526529745,526529745
+.long 2331944644,2331944644
+.long 2639474228,2639474228
+.long 2689987490,2689987490
+.long 853641733,853641733
+.long 1978398372,1978398372
+.long 971801355,971801355
+.long 2867814464,2867814464
+.long 111112542,111112542
+.long 1360031421,1360031421
+.long 4186579262,4186579262
+.long 1023860118,1023860118
+.long 2919579357,2919579357
+.long 1186850381,1186850381
+.long 3045938321,3045938321
+.long 90031217,90031217
+.long 1876166148,1876166148
+.long 4279586912,4279586912
+.long 620468249,620468249
+.long 2548678102,2548678102
+.long 3426959497,3426959497
+.long 2006899047,2006899047
+.long 3175278768,3175278768
+.long 2290845959,2290845959
+.long 945494503,945494503
+.long 3689859193,3689859193
+.long 1191869601,1191869601
+.long 3910091388,3910091388
+.long 3374220536,3374220536
+.long 0,0
+.long 2206629897,2206629897
+.long 1223502642,1223502642
+.long 2893025566,2893025566
+.long 1316117100,1316117100
+.long 4227796733,4227796733
+.long 1446544655,1446544655
+.long 517320253,517320253
+.long 658058550,658058550
+.long 1691946762,1691946762
+.long 564550760,564550760
+.long 3511966619,3511966619
+.long 976107044,976107044
+.long 2976320012,2976320012
+.long 266819475,266819475
+.long 3533106868,3533106868
+.long 2660342555,2660342555
+.long 1338359936,1338359936
+.long 2720062561,2720062561
+.long 1766553434,1766553434
+.long 370807324,370807324
+.long 179999714,179999714
+.long 3844776128,3844776128
+.long 1138762300,1138762300
+.long 488053522,488053522
+.long 185403662,185403662
+.long 2915535858,2915535858
+.long 3114841645,3114841645
+.long 3366526484,3366526484
+.long 2233069911,2233069911
+.long 1275557295,1275557295
+.long 3151862254,3151862254
+.long 4250959779,4250959779
+.long 2670068215,2670068215
+.long 3170202204,3170202204
+.long 3309004356,3309004356
+.long 880737115,880737115
+.long 1982415755,1982415755
+.long 3703972811,3703972811
+.long 1761406390,1761406390
+.long 1676797112,1676797112
+.long 3403428311,3403428311
+.long 277177154,277177154
+.long 1076008723,1076008723
+.long 538035844,538035844
+.long 2099530373,2099530373
+.long 4164795346,4164795346
+.long 288553390,288553390
+.long 1839278535,1839278535
+.long 1261411869,1261411869
+.long 4080055004,4080055004
+.long 3964831245,3964831245
+.long 3504587127,3504587127
+.long 1813426987,1813426987
+.long 2579067049,2579067049
+.long 4199060497,4199060497
+.long 577038663,577038663
+.long 3297574056,3297574056
+.long 440397984,440397984
+.long 3626794326,3626794326
+.long 4019204898,4019204898
+.long 3343796615,3343796615
+.long 3251714265,3251714265
+.long 4272081548,4272081548
+.long 906744984,906744984
+.long 3481400742,3481400742
+.long 685669029,685669029
+.long 646887386,646887386
+.long 2764025151,2764025151
+.long 3835509292,3835509292
+.long 227702864,227702864
+.long 2613862250,2613862250
+.long 1648787028,1648787028
+.long 3256061430,3256061430
+.long 3904428176,3904428176
+.long 1593260334,1593260334
+.long 4121936770,4121936770
+.long 3196083615,3196083615
+.long 2090061929,2090061929
+.long 2838353263,2838353263
+.long 3004310991,3004310991
+.long 999926984,999926984
+.long 2809993232,2809993232
+.long 1852021992,1852021992
+.long 2075868123,2075868123
+.long 158869197,158869197
+.long 4095236462,4095236462
+.long 28809964,28809964
+.long 2828685187,2828685187
+.long 1701746150,1701746150
+.long 2129067946,2129067946
+.long 147831841,147831841
+.long 3873969647,3873969647
+.long 3650873274,3650873274
+.long 3459673930,3459673930
+.long 3557400554,3557400554
+.long 3598495785,3598495785
+.long 2947720241,2947720241
+.long 824393514,824393514
+.long 815048134,815048134
+.long 3227951669,3227951669
+.long 935087732,935087732
+.long 2798289660,2798289660
+.long 2966458592,2966458592
+.long 366520115,366520115
+.long 1251476721,1251476721
+.long 4158319681,4158319681
+.long 240176511,240176511
+.long 804688151,804688151
+.long 2379631990,2379631990
+.long 1303441219,1303441219
+.long 1414376140,1414376140
+.long 3741619940,3741619940
+.long 3820343710,3820343710
+.long 461924940,461924940
+.long 3089050817,3089050817
+.long 2136040774,2136040774
+.long 82468509,82468509
+.long 1563790337,1563790337
+.long 1937016826,1937016826
+.long 776014843,776014843
+.long 1511876531,1511876531
+.long 1389550482,1389550482
+.long 861278441,861278441
+.long 323475053,323475053
+.long 2355222426,2355222426
+.long 2047648055,2047648055
+.long 2383738969,2383738969
+.long 2302415851,2302415851
+.long 3995576782,3995576782
+.long 902390199,902390199
+.long 3991215329,3991215329
+.long 1018251130,1018251130
+.long 1507840668,1507840668
+.long 1064563285,1064563285
+.long 2043548696,2043548696
+.long 3208103795,3208103795
+.long 3939366739,3939366739
+.long 1537932639,1537932639
+.long 342834655,342834655
+.long 2262516856,2262516856
+.long 2180231114,2180231114
+.long 1053059257,1053059257
+.long 741614648,741614648
+.long 1598071746,1598071746
+.long 1925389590,1925389590
+.long 203809468,203809468
+.long 2336832552,2336832552
+.long 1100287487,1100287487
+.long 1895934009,1895934009
+.long 3736275976,3736275976
+.long 2632234200,2632234200
+.long 2428589668,2428589668
+.long 1636092795,1636092795
+.long 1890988757,1890988757
+.long 1952214088,1952214088
+.long 1113045200,1113045200
+.byte 82,9,106,213,48,54,165,56
+.byte 191,64,163,158,129,243,215,251
+.byte 124,227,57,130,155,47,255,135
+.byte 52,142,67,68,196,222,233,203
+.byte 84,123,148,50,166,194,35,61
+.byte 238,76,149,11,66,250,195,78
+.byte 8,46,161,102,40,217,36,178
+.byte 118,91,162,73,109,139,209,37
+.byte 114,248,246,100,134,104,152,22
+.byte 212,164,92,204,93,101,182,146
+.byte 108,112,72,80,253,237,185,218
+.byte 94,21,70,87,167,141,157,132
+.byte 144,216,171,0,140,188,211,10
+.byte 247,228,88,5,184,179,69,6
+.byte 208,44,30,143,202,63,15,2
+.byte 193,175,189,3,1,19,138,107
+.byte 58,145,17,65,79,103,220,234
+.byte 151,242,207,206,240,180,230,115
+.byte 150,172,116,34,231,173,53,133
+.byte 226,249,55,232,28,117,223,110
+.byte 71,241,26,113,29,41,197,137
+.byte 111,183,98,14,170,24,190,27
+.byte 252,86,62,75,198,210,121,32
+.byte 154,219,192,254,120,205,90,244
+.byte 31,221,168,51,136,7,199,49
+.byte 177,18,16,89,39,128,236,95
+.byte 96,81,127,169,25,181,74,13
+.byte 45,229,122,159,147,201,156,239
+.byte 160,224,59,77,174,42,245,176
+.byte 200,235,187,60,131,83,153,97
+.byte 23,43,4,126,186,119,214,38
+.byte 225,105,20,99,85,33,12,125
+.byte 82,9,106,213,48,54,165,56
+.byte 191,64,163,158,129,243,215,251
+.byte 124,227,57,130,155,47,255,135
+.byte 52,142,67,68,196,222,233,203
+.byte 84,123,148,50,166,194,35,61
+.byte 238,76,149,11,66,250,195,78
+.byte 8,46,161,102,40,217,36,178
+.byte 118,91,162,73,109,139,209,37
+.byte 114,248,246,100,134,104,152,22
+.byte 212,164,92,204,93,101,182,146
+.byte 108,112,72,80,253,237,185,218
+.byte 94,21,70,87,167,141,157,132
+.byte 144,216,171,0,140,188,211,10
+.byte 247,228,88,5,184,179,69,6
+.byte 208,44,30,143,202,63,15,2
+.byte 193,175,189,3,1,19,138,107
+.byte 58,145,17,65,79,103,220,234
+.byte 151,242,207,206,240,180,230,115
+.byte 150,172,116,34,231,173,53,133
+.byte 226,249,55,232,28,117,223,110
+.byte 71,241,26,113,29,41,197,137
+.byte 111,183,98,14,170,24,190,27
+.byte 252,86,62,75,198,210,121,32
+.byte 154,219,192,254,120,205,90,244
+.byte 31,221,168,51,136,7,199,49
+.byte 177,18,16,89,39,128,236,95
+.byte 96,81,127,169,25,181,74,13
+.byte 45,229,122,159,147,201,156,239
+.byte 160,224,59,77,174,42,245,176
+.byte 200,235,187,60,131,83,153,97
+.byte 23,43,4,126,186,119,214,38
+.byte 225,105,20,99,85,33,12,125
+.byte 82,9,106,213,48,54,165,56
+.byte 191,64,163,158,129,243,215,251
+.byte 124,227,57,130,155,47,255,135
+.byte 52,142,67,68,196,222,233,203
+.byte 84,123,148,50,166,194,35,61
+.byte 238,76,149,11,66,250,195,78
+.byte 8,46,161,102,40,217,36,178
+.byte 118,91,162,73,109,139,209,37
+.byte 114,248,246,100,134,104,152,22
+.byte 212,164,92,204,93,101,182,146
+.byte 108,112,72,80,253,237,185,218
+.byte 94,21,70,87,167,141,157,132
+.byte 144,216,171,0,140,188,211,10
+.byte 247,228,88,5,184,179,69,6
+.byte 208,44,30,143,202,63,15,2
+.byte 193,175,189,3,1,19,138,107
+.byte 58,145,17,65,79,103,220,234
+.byte 151,242,207,206,240,180,230,115
+.byte 150,172,116,34,231,173,53,133
+.byte 226,249,55,232,28,117,223,110
+.byte 71,241,26,113,29,41,197,137
+.byte 111,183,98,14,170,24,190,27
+.byte 252,86,62,75,198,210,121,32
+.byte 154,219,192,254,120,205,90,244
+.byte 31,221,168,51,136,7,199,49
+.byte 177,18,16,89,39,128,236,95
+.byte 96,81,127,169,25,181,74,13
+.byte 45,229,122,159,147,201,156,239
+.byte 160,224,59,77,174,42,245,176
+.byte 200,235,187,60,131,83,153,97
+.byte 23,43,4,126,186,119,214,38
+.byte 225,105,20,99,85,33,12,125
+.byte 82,9,106,213,48,54,165,56
+.byte 191,64,163,158,129,243,215,251
+.byte 124,227,57,130,155,47,255,135
+.byte 52,142,67,68,196,222,233,203
+.byte 84,123,148,50,166,194,35,61
+.byte 238,76,149,11,66,250,195,78
+.byte 8,46,161,102,40,217,36,178
+.byte 118,91,162,73,109,139,209,37
+.byte 114,248,246,100,134,104,152,22
+.byte 212,164,92,204,93,101,182,146
+.byte 108,112,72,80,253,237,185,218
+.byte 94,21,70,87,167,141,157,132
+.byte 144,216,171,0,140,188,211,10
+.byte 247,228,88,5,184,179,69,6
+.byte 208,44,30,143,202,63,15,2
+.byte 193,175,189,3,1,19,138,107
+.byte 58,145,17,65,79,103,220,234
+.byte 151,242,207,206,240,180,230,115
+.byte 150,172,116,34,231,173,53,133
+.byte 226,249,55,232,28,117,223,110
+.byte 71,241,26,113,29,41,197,137
+.byte 111,183,98,14,170,24,190,27
+.byte 252,86,62,75,198,210,121,32
+.byte 154,219,192,254,120,205,90,244
+.byte 31,221,168,51,136,7,199,49
+.byte 177,18,16,89,39,128,236,95
+.byte 96,81,127,169,25,181,74,13
+.byte 45,229,122,159,147,201,156,239
+.byte 160,224,59,77,174,42,245,176
+.byte 200,235,187,60,131,83,153,97
+.byte 23,43,4,126,186,119,214,38
+.byte 225,105,20,99,85,33,12,125
+.size _x86_AES_decrypt,.-_x86_AES_decrypt
+.globl asm_AES_decrypt
+.hidden asm_AES_decrypt
+.type asm_AES_decrypt,@function
+.align 16
+asm_AES_decrypt:
+.L_asm_AES_decrypt_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ movl 20(%esp),%esi
+ movl 28(%esp),%edi
+ movl %esp,%eax
+ subl $36,%esp
+ andl $-64,%esp
+ leal -127(%edi),%ebx
+ subl %esp,%ebx
+ negl %ebx
+ andl $960,%ebx
+ subl %ebx,%esp
+ addl $4,%esp
+ movl %eax,28(%esp)
+ call .L010pic_point
+.L010pic_point:
+ popl %ebp
+ leal OPENSSL_ia32cap_P-.L010pic_point(%ebp),%eax
+ leal .LAES_Td-.L010pic_point(%ebp),%ebp
+ leal 764(%esp),%ebx
+ subl %ebp,%ebx
+ andl $768,%ebx
+ leal 2176(%ebp,%ebx,1),%ebp
+ btl $25,(%eax)
+ jnc .L011x86
+ movq (%esi),%mm0
+ movq 8(%esi),%mm4
+ call _sse_AES_decrypt_compact
+ movl 28(%esp),%esp
+ movl 24(%esp),%esi
+ movq %mm0,(%esi)
+ movq %mm4,8(%esi)
+ emms
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.align 16
+.L011x86:
+ movl %ebp,24(%esp)
+ movl (%esi),%eax
+ movl 4(%esi),%ebx
+ movl 8(%esi),%ecx
+ movl 12(%esi),%edx
+ call _x86_AES_decrypt_compact
+ movl 28(%esp),%esp
+ movl 24(%esp),%esi
+ movl %eax,(%esi)
+ movl %ebx,4(%esi)
+ movl %ecx,8(%esi)
+ movl %edx,12(%esi)
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.size asm_AES_decrypt,.-.L_asm_AES_decrypt_begin
+.globl asm_AES_cbc_encrypt
+.hidden asm_AES_cbc_encrypt
+.type asm_AES_cbc_encrypt,@function
+.align 16
+asm_AES_cbc_encrypt:
+.L_asm_AES_cbc_encrypt_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ movl 28(%esp),%ecx
+ cmpl $0,%ecx
+ je .L012drop_out
+ call .L013pic_point
+.L013pic_point:
+ popl %ebp
+ leal OPENSSL_ia32cap_P-.L013pic_point(%ebp),%eax
+ cmpl $0,40(%esp)
+ leal .LAES_Te-.L013pic_point(%ebp),%ebp
+ jne .L014picked_te
+ leal .LAES_Td-.LAES_Te(%ebp),%ebp
+.L014picked_te:
+ pushfl
+ cld
+ cmpl $512,%ecx
+ jb .L015slow_way
+ testl $15,%ecx
+ jnz .L015slow_way
+ btl $28,(%eax)
+ jc .L015slow_way
+ leal -324(%esp),%esi
+ andl $-64,%esi
+ movl %ebp,%eax
+ leal 2304(%ebp),%ebx
+ movl %esi,%edx
+ andl $4095,%eax
+ andl $4095,%ebx
+ andl $4095,%edx
+ cmpl %ebx,%edx
+ jb .L016tbl_break_out
+ subl %ebx,%edx
+ subl %edx,%esi
+ jmp .L017tbl_ok
+.align 4
+.L016tbl_break_out:
+ subl %eax,%edx
+ andl $4095,%edx
+ addl $384,%edx
+ subl %edx,%esi
+.align 4
+.L017tbl_ok:
+ leal 24(%esp),%edx
+ xchgl %esi,%esp
+ addl $4,%esp
+ movl %ebp,24(%esp)
+ movl %esi,28(%esp)
+ movl (%edx),%eax
+ movl 4(%edx),%ebx
+ movl 12(%edx),%edi
+ movl 16(%edx),%esi
+ movl 20(%edx),%edx
+ movl %eax,32(%esp)
+ movl %ebx,36(%esp)
+ movl %ecx,40(%esp)
+ movl %edi,44(%esp)
+ movl %esi,48(%esp)
+ movl $0,316(%esp)
+ movl %edi,%ebx
+ movl $61,%ecx
+ subl %ebp,%ebx
+ movl %edi,%esi
+ andl $4095,%ebx
+ leal 76(%esp),%edi
+ cmpl $2304,%ebx
+ jb .L018do_copy
+ cmpl $3852,%ebx
+ jb .L019skip_copy
+.align 4
+.L018do_copy:
+ movl %edi,44(%esp)
+.long 2784229001
+.L019skip_copy:
+ movl $16,%edi
+.align 4
+.L020prefetch_tbl:
+ movl (%ebp),%eax
+ movl 32(%ebp),%ebx
+ movl 64(%ebp),%ecx
+ movl 96(%ebp),%esi
+ leal 128(%ebp),%ebp
+ subl $1,%edi
+ jnz .L020prefetch_tbl
+ subl $2048,%ebp
+ movl 32(%esp),%esi
+ movl 48(%esp),%edi
+ cmpl $0,%edx
+ je .L021fast_decrypt
+ movl (%edi),%eax
+ movl 4(%edi),%ebx
+.align 16
+.L022fast_enc_loop:
+ movl 8(%edi),%ecx
+ movl 12(%edi),%edx
+ xorl (%esi),%eax
+ xorl 4(%esi),%ebx
+ xorl 8(%esi),%ecx
+ xorl 12(%esi),%edx
+ movl 44(%esp),%edi
+ call _x86_AES_encrypt
+ movl 32(%esp),%esi
+ movl 36(%esp),%edi
+ movl %eax,(%edi)
+ movl %ebx,4(%edi)
+ movl %ecx,8(%edi)
+ movl %edx,12(%edi)
+ leal 16(%esi),%esi
+ movl 40(%esp),%ecx
+ movl %esi,32(%esp)
+ leal 16(%edi),%edx
+ movl %edx,36(%esp)
+ subl $16,%ecx
+ movl %ecx,40(%esp)
+ jnz .L022fast_enc_loop
+ movl 48(%esp),%esi
+ movl 8(%edi),%ecx
+ movl 12(%edi),%edx
+ movl %eax,(%esi)
+ movl %ebx,4(%esi)
+ movl %ecx,8(%esi)
+ movl %edx,12(%esi)
+ cmpl $0,316(%esp)
+ movl 44(%esp),%edi
+ je .L023skip_ezero
+ movl $60,%ecx
+ xorl %eax,%eax
+.align 4
+.long 2884892297
+.L023skip_ezero:
+ movl 28(%esp),%esp
+ popfl
+.L012drop_out:
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+ pushfl
+.align 16
+.L021fast_decrypt:
+ cmpl 36(%esp),%esi
+ je .L024fast_dec_in_place
+ movl %edi,52(%esp)
+.align 4
+.align 16
+.L025fast_dec_loop:
+ movl (%esi),%eax
+ movl 4(%esi),%ebx
+ movl 8(%esi),%ecx
+ movl 12(%esi),%edx
+ movl 44(%esp),%edi
+ call _x86_AES_decrypt
+ movl 52(%esp),%edi
+ movl 40(%esp),%esi
+ xorl (%edi),%eax
+ xorl 4(%edi),%ebx
+ xorl 8(%edi),%ecx
+ xorl 12(%edi),%edx
+ movl 36(%esp),%edi
+ movl 32(%esp),%esi
+ movl %eax,(%edi)
+ movl %ebx,4(%edi)
+ movl %ecx,8(%edi)
+ movl %edx,12(%edi)
+ movl 40(%esp),%ecx
+ movl %esi,52(%esp)
+ leal 16(%esi),%esi
+ movl %esi,32(%esp)
+ leal 16(%edi),%edi
+ movl %edi,36(%esp)
+ subl $16,%ecx
+ movl %ecx,40(%esp)
+ jnz .L025fast_dec_loop
+ movl 52(%esp),%edi
+ movl 48(%esp),%esi
+ movl (%edi),%eax
+ movl 4(%edi),%ebx
+ movl 8(%edi),%ecx
+ movl 12(%edi),%edx
+ movl %eax,(%esi)
+ movl %ebx,4(%esi)
+ movl %ecx,8(%esi)
+ movl %edx,12(%esi)
+ jmp .L026fast_dec_out
+.align 16
+.L024fast_dec_in_place:
+.L027fast_dec_in_place_loop:
+ movl (%esi),%eax
+ movl 4(%esi),%ebx
+ movl 8(%esi),%ecx
+ movl 12(%esi),%edx
+ leal 60(%esp),%edi
+ movl %eax,(%edi)
+ movl %ebx,4(%edi)
+ movl %ecx,8(%edi)
+ movl %edx,12(%edi)
+ movl 44(%esp),%edi
+ call _x86_AES_decrypt
+ movl 48(%esp),%edi
+ movl 36(%esp),%esi
+ xorl (%edi),%eax
+ xorl 4(%edi),%ebx
+ xorl 8(%edi),%ecx
+ xorl 12(%edi),%edx
+ movl %eax,(%esi)
+ movl %ebx,4(%esi)
+ movl %ecx,8(%esi)
+ movl %edx,12(%esi)
+ leal 16(%esi),%esi
+ movl %esi,36(%esp)
+ leal 60(%esp),%esi
+ movl (%esi),%eax
+ movl 4(%esi),%ebx
+ movl 8(%esi),%ecx
+ movl 12(%esi),%edx
+ movl %eax,(%edi)
+ movl %ebx,4(%edi)
+ movl %ecx,8(%edi)
+ movl %edx,12(%edi)
+ movl 32(%esp),%esi
+ movl 40(%esp),%ecx
+ leal 16(%esi),%esi
+ movl %esi,32(%esp)
+ subl $16,%ecx
+ movl %ecx,40(%esp)
+ jnz .L027fast_dec_in_place_loop
+.align 4
+.L026fast_dec_out:
+ cmpl $0,316(%esp)
+ movl 44(%esp),%edi
+ je .L028skip_dzero
+ movl $60,%ecx
+ xorl %eax,%eax
+.align 4
+.long 2884892297
+.L028skip_dzero:
+ movl 28(%esp),%esp
+ popfl
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+ pushfl
+.align 16
+.L015slow_way:
+ movl (%eax),%eax
+ movl 36(%esp),%edi
+ leal -80(%esp),%esi
+ andl $-64,%esi
+ leal -143(%edi),%ebx
+ subl %esi,%ebx
+ negl %ebx
+ andl $960,%ebx
+ subl %ebx,%esi
+ leal 768(%esi),%ebx
+ subl %ebp,%ebx
+ andl $768,%ebx
+ leal 2176(%ebp,%ebx,1),%ebp
+ leal 24(%esp),%edx
+ xchgl %esi,%esp
+ addl $4,%esp
+ movl %ebp,24(%esp)
+ movl %esi,28(%esp)
+ movl %eax,52(%esp)
+ movl (%edx),%eax
+ movl 4(%edx),%ebx
+ movl 16(%edx),%esi
+ movl 20(%edx),%edx
+ movl %eax,32(%esp)
+ movl %ebx,36(%esp)
+ movl %ecx,40(%esp)
+ movl %edi,44(%esp)
+ movl %esi,48(%esp)
+ movl %esi,%edi
+ movl %eax,%esi
+ cmpl $0,%edx
+ je .L029slow_decrypt
+ cmpl $16,%ecx
+ movl %ebx,%edx
+ jb .L030slow_enc_tail
+ btl $25,52(%esp)
+ jnc .L031slow_enc_x86
+ movq (%edi),%mm0
+ movq 8(%edi),%mm4
+.align 16
+.L032slow_enc_loop_sse:
+ pxor (%esi),%mm0
+ pxor 8(%esi),%mm4
+ movl 44(%esp),%edi
+ call _sse_AES_encrypt_compact
+ movl 32(%esp),%esi
+ movl 36(%esp),%edi
+ movl 40(%esp),%ecx
+ movq %mm0,(%edi)
+ movq %mm4,8(%edi)
+ leal 16(%esi),%esi
+ movl %esi,32(%esp)
+ leal 16(%edi),%edx
+ movl %edx,36(%esp)
+ subl $16,%ecx
+ cmpl $16,%ecx
+ movl %ecx,40(%esp)
+ jae .L032slow_enc_loop_sse
+ testl $15,%ecx
+ jnz .L030slow_enc_tail
+ movl 48(%esp),%esi
+ movq %mm0,(%esi)
+ movq %mm4,8(%esi)
+ emms
+ movl 28(%esp),%esp
+ popfl
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+ pushfl
+.align 16
+.L031slow_enc_x86:
+ movl (%edi),%eax
+ movl 4(%edi),%ebx
+.align 4
+.L033slow_enc_loop_x86:
+ movl 8(%edi),%ecx
+ movl 12(%edi),%edx
+ xorl (%esi),%eax
+ xorl 4(%esi),%ebx
+ xorl 8(%esi),%ecx
+ xorl 12(%esi),%edx
+ movl 44(%esp),%edi
+ call _x86_AES_encrypt_compact
+ movl 32(%esp),%esi
+ movl 36(%esp),%edi
+ movl %eax,(%edi)
+ movl %ebx,4(%edi)
+ movl %ecx,8(%edi)
+ movl %edx,12(%edi)
+ movl 40(%esp),%ecx
+ leal 16(%esi),%esi
+ movl %esi,32(%esp)
+ leal 16(%edi),%edx
+ movl %edx,36(%esp)
+ subl $16,%ecx
+ cmpl $16,%ecx
+ movl %ecx,40(%esp)
+ jae .L033slow_enc_loop_x86
+ testl $15,%ecx
+ jnz .L030slow_enc_tail
+ movl 48(%esp),%esi
+ movl 8(%edi),%ecx
+ movl 12(%edi),%edx
+ movl %eax,(%esi)
+ movl %ebx,4(%esi)
+ movl %ecx,8(%esi)
+ movl %edx,12(%esi)
+ movl 28(%esp),%esp
+ popfl
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+ pushfl
+.align 16
+.L030slow_enc_tail:
+ emms
+ movl %edx,%edi
+ movl $16,%ebx
+ subl %ecx,%ebx
+ cmpl %esi,%edi
+ je .L034enc_in_place
+.align 4
+.long 2767451785
+ jmp .L035enc_skip_in_place
+.L034enc_in_place:
+ leal (%edi,%ecx,1),%edi
+.L035enc_skip_in_place:
+ movl %ebx,%ecx
+ xorl %eax,%eax
+.align 4
+.long 2868115081
+ movl 48(%esp),%edi
+ movl %edx,%esi
+ movl (%edi),%eax
+ movl 4(%edi),%ebx
+ movl $16,40(%esp)
+ jmp .L033slow_enc_loop_x86
+.align 16
+.L029slow_decrypt:
+ btl $25,52(%esp)
+ jnc .L036slow_dec_loop_x86
+.align 4
+.L037slow_dec_loop_sse:
+ movq (%esi),%mm0
+ movq 8(%esi),%mm4
+ movl 44(%esp),%edi
+ call _sse_AES_decrypt_compact
+ movl 32(%esp),%esi
+ leal 60(%esp),%eax
+ movl 36(%esp),%ebx
+ movl 40(%esp),%ecx
+ movl 48(%esp),%edi
+ movq (%esi),%mm1
+ movq 8(%esi),%mm5
+ pxor (%edi),%mm0
+ pxor 8(%edi),%mm4
+ movq %mm1,(%edi)
+ movq %mm5,8(%edi)
+ subl $16,%ecx
+ jc .L038slow_dec_partial_sse
+ movq %mm0,(%ebx)
+ movq %mm4,8(%ebx)
+ leal 16(%ebx),%ebx
+ movl %ebx,36(%esp)
+ leal 16(%esi),%esi
+ movl %esi,32(%esp)
+ movl %ecx,40(%esp)
+ jnz .L037slow_dec_loop_sse
+ emms
+ movl 28(%esp),%esp
+ popfl
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+ pushfl
+.align 16
+.L038slow_dec_partial_sse:
+ movq %mm0,(%eax)
+ movq %mm4,8(%eax)
+ emms
+ addl $16,%ecx
+ movl %ebx,%edi
+ movl %eax,%esi
+.align 4
+.long 2767451785
+ movl 28(%esp),%esp
+ popfl
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+ pushfl
+.align 16
+.L036slow_dec_loop_x86:
+ movl (%esi),%eax
+ movl 4(%esi),%ebx
+ movl 8(%esi),%ecx
+ movl 12(%esi),%edx
+ leal 60(%esp),%edi
+ movl %eax,(%edi)
+ movl %ebx,4(%edi)
+ movl %ecx,8(%edi)
+ movl %edx,12(%edi)
+ movl 44(%esp),%edi
+ call _x86_AES_decrypt_compact
+ movl 48(%esp),%edi
+ movl 40(%esp),%esi
+ xorl (%edi),%eax
+ xorl 4(%edi),%ebx
+ xorl 8(%edi),%ecx
+ xorl 12(%edi),%edx
+ subl $16,%esi
+ jc .L039slow_dec_partial_x86
+ movl %esi,40(%esp)
+ movl 36(%esp),%esi
+ movl %eax,(%esi)
+ movl %ebx,4(%esi)
+ movl %ecx,8(%esi)
+ movl %edx,12(%esi)
+ leal 16(%esi),%esi
+ movl %esi,36(%esp)
+ leal 60(%esp),%esi
+ movl (%esi),%eax
+ movl 4(%esi),%ebx
+ movl 8(%esi),%ecx
+ movl 12(%esi),%edx
+ movl %eax,(%edi)
+ movl %ebx,4(%edi)
+ movl %ecx,8(%edi)
+ movl %edx,12(%edi)
+ movl 32(%esp),%esi
+ leal 16(%esi),%esi
+ movl %esi,32(%esp)
+ jnz .L036slow_dec_loop_x86
+ movl 28(%esp),%esp
+ popfl
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+ pushfl
+.align 16
+.L039slow_dec_partial_x86:
+ leal 60(%esp),%esi
+ movl %eax,(%esi)
+ movl %ebx,4(%esi)
+ movl %ecx,8(%esi)
+ movl %edx,12(%esi)
+ movl 32(%esp),%esi
+ movl (%esi),%eax
+ movl 4(%esi),%ebx
+ movl 8(%esi),%ecx
+ movl 12(%esi),%edx
+ movl %eax,(%edi)
+ movl %ebx,4(%edi)
+ movl %ecx,8(%edi)
+ movl %edx,12(%edi)
+ movl 40(%esp),%ecx
+ movl 36(%esp),%edi
+ leal 60(%esp),%esi
+.align 4
+.long 2767451785
+ movl 28(%esp),%esp
+ popfl
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.size asm_AES_cbc_encrypt,.-.L_asm_AES_cbc_encrypt_begin
+.hidden _x86_AES_set_encrypt_key
+.type _x86_AES_set_encrypt_key,@function
+.align 16
+_x86_AES_set_encrypt_key:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ movl 24(%esp),%esi
+ movl 32(%esp),%edi
+ testl $-1,%esi
+ jz .L040badpointer
+ testl $-1,%edi
+ jz .L040badpointer
+ call .L041pic_point
+.L041pic_point:
+ popl %ebp
+ leal .LAES_Te-.L041pic_point(%ebp),%ebp
+ leal 2176(%ebp),%ebp
+ movl -128(%ebp),%eax
+ movl -96(%ebp),%ebx
+ movl -64(%ebp),%ecx
+ movl -32(%ebp),%edx
+ movl (%ebp),%eax
+ movl 32(%ebp),%ebx
+ movl 64(%ebp),%ecx
+ movl 96(%ebp),%edx
+ movl 28(%esp),%ecx
+ cmpl $128,%ecx
+ je .L04210rounds
+ cmpl $192,%ecx
+ je .L04312rounds
+ cmpl $256,%ecx
+ je .L04414rounds
+ movl $-2,%eax
+ jmp .L045exit
+.L04210rounds:
+ movl (%esi),%eax
+ movl 4(%esi),%ebx
+ movl 8(%esi),%ecx
+ movl 12(%esi),%edx
+ movl %eax,(%edi)
+ movl %ebx,4(%edi)
+ movl %ecx,8(%edi)
+ movl %edx,12(%edi)
+ xorl %ecx,%ecx
+ jmp .L04610shortcut
+.align 4
+.L04710loop:
+ movl (%edi),%eax
+ movl 12(%edi),%edx
+.L04610shortcut:
+ movzbl %dl,%esi
+ movzbl -128(%ebp,%esi,1),%ebx
+ movzbl %dh,%esi
+ shll $24,%ebx
+ xorl %ebx,%eax
+ movzbl -128(%ebp,%esi,1),%ebx
+ shrl $16,%edx
+ movzbl %dl,%esi
+ xorl %ebx,%eax
+ movzbl -128(%ebp,%esi,1),%ebx
+ movzbl %dh,%esi
+ shll $8,%ebx
+ xorl %ebx,%eax
+ movzbl -128(%ebp,%esi,1),%ebx
+ shll $16,%ebx
+ xorl %ebx,%eax
+ xorl 896(%ebp,%ecx,4),%eax
+ movl %eax,16(%edi)
+ xorl 4(%edi),%eax
+ movl %eax,20(%edi)
+ xorl 8(%edi),%eax
+ movl %eax,24(%edi)
+ xorl 12(%edi),%eax
+ movl %eax,28(%edi)
+ incl %ecx
+ addl $16,%edi
+ cmpl $10,%ecx
+ jl .L04710loop
+ movl $10,80(%edi)
+ xorl %eax,%eax
+ jmp .L045exit
+.L04312rounds:
+ movl (%esi),%eax
+ movl 4(%esi),%ebx
+ movl 8(%esi),%ecx
+ movl 12(%esi),%edx
+ movl %eax,(%edi)
+ movl %ebx,4(%edi)
+ movl %ecx,8(%edi)
+ movl %edx,12(%edi)
+ movl 16(%esi),%ecx
+ movl 20(%esi),%edx
+ movl %ecx,16(%edi)
+ movl %edx,20(%edi)
+ xorl %ecx,%ecx
+ jmp .L04812shortcut
+.align 4
+.L04912loop:
+ movl (%edi),%eax
+ movl 20(%edi),%edx
+.L04812shortcut:
+ movzbl %dl,%esi
+ movzbl -128(%ebp,%esi,1),%ebx
+ movzbl %dh,%esi
+ shll $24,%ebx
+ xorl %ebx,%eax
+ movzbl -128(%ebp,%esi,1),%ebx
+ shrl $16,%edx
+ movzbl %dl,%esi
+ xorl %ebx,%eax
+ movzbl -128(%ebp,%esi,1),%ebx
+ movzbl %dh,%esi
+ shll $8,%ebx
+ xorl %ebx,%eax
+ movzbl -128(%ebp,%esi,1),%ebx
+ shll $16,%ebx
+ xorl %ebx,%eax
+ xorl 896(%ebp,%ecx,4),%eax
+ movl %eax,24(%edi)
+ xorl 4(%edi),%eax
+ movl %eax,28(%edi)
+ xorl 8(%edi),%eax
+ movl %eax,32(%edi)
+ xorl 12(%edi),%eax
+ movl %eax,36(%edi)
+ cmpl $7,%ecx
+ je .L05012break
+ incl %ecx
+ xorl 16(%edi),%eax
+ movl %eax,40(%edi)
+ xorl 20(%edi),%eax
+ movl %eax,44(%edi)
+ addl $24,%edi
+ jmp .L04912loop
+.L05012break:
+ movl $12,72(%edi)
+ xorl %eax,%eax
+ jmp .L045exit
+.L04414rounds:
+ movl (%esi),%eax
+ movl 4(%esi),%ebx
+ movl 8(%esi),%ecx
+ movl 12(%esi),%edx
+ movl %eax,(%edi)
+ movl %ebx,4(%edi)
+ movl %ecx,8(%edi)
+ movl %edx,12(%edi)
+ movl 16(%esi),%eax
+ movl 20(%esi),%ebx
+ movl 24(%esi),%ecx
+ movl 28(%esi),%edx
+ movl %eax,16(%edi)
+ movl %ebx,20(%edi)
+ movl %ecx,24(%edi)
+ movl %edx,28(%edi)
+ xorl %ecx,%ecx
+ jmp .L05114shortcut
+.align 4
+.L05214loop:
+ movl 28(%edi),%edx
+.L05114shortcut:
+ movl (%edi),%eax
+ movzbl %dl,%esi
+ movzbl -128(%ebp,%esi,1),%ebx
+ movzbl %dh,%esi
+ shll $24,%ebx
+ xorl %ebx,%eax
+ movzbl -128(%ebp,%esi,1),%ebx
+ shrl $16,%edx
+ movzbl %dl,%esi
+ xorl %ebx,%eax
+ movzbl -128(%ebp,%esi,1),%ebx
+ movzbl %dh,%esi
+ shll $8,%ebx
+ xorl %ebx,%eax
+ movzbl -128(%ebp,%esi,1),%ebx
+ shll $16,%ebx
+ xorl %ebx,%eax
+ xorl 896(%ebp,%ecx,4),%eax
+ movl %eax,32(%edi)
+ xorl 4(%edi),%eax
+ movl %eax,36(%edi)
+ xorl 8(%edi),%eax
+ movl %eax,40(%edi)
+ xorl 12(%edi),%eax
+ movl %eax,44(%edi)
+ cmpl $6,%ecx
+ je .L05314break
+ incl %ecx
+ movl %eax,%edx
+ movl 16(%edi),%eax
+ movzbl %dl,%esi
+ movzbl -128(%ebp,%esi,1),%ebx
+ movzbl %dh,%esi
+ xorl %ebx,%eax
+ movzbl -128(%ebp,%esi,1),%ebx
+ shrl $16,%edx
+ shll $8,%ebx
+ movzbl %dl,%esi
+ xorl %ebx,%eax
+ movzbl -128(%ebp,%esi,1),%ebx
+ movzbl %dh,%esi
+ shll $16,%ebx
+ xorl %ebx,%eax
+ movzbl -128(%ebp,%esi,1),%ebx
+ shll $24,%ebx
+ xorl %ebx,%eax
+ movl %eax,48(%edi)
+ xorl 20(%edi),%eax
+ movl %eax,52(%edi)
+ xorl 24(%edi),%eax
+ movl %eax,56(%edi)
+ xorl 28(%edi),%eax
+ movl %eax,60(%edi)
+ addl $32,%edi
+ jmp .L05214loop
+.L05314break:
+ movl $14,48(%edi)
+ xorl %eax,%eax
+ jmp .L045exit
+.L040badpointer:
+ movl $-1,%eax
+.L045exit:
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.size _x86_AES_set_encrypt_key,.-_x86_AES_set_encrypt_key
+.globl asm_AES_set_encrypt_key
+.hidden asm_AES_set_encrypt_key
+.type asm_AES_set_encrypt_key,@function
+.align 16
+asm_AES_set_encrypt_key:
+.L_asm_AES_set_encrypt_key_begin:
+ call _x86_AES_set_encrypt_key
+ ret
+.size asm_AES_set_encrypt_key,.-.L_asm_AES_set_encrypt_key_begin
+.globl asm_AES_set_decrypt_key
+.hidden asm_AES_set_decrypt_key
+.type asm_AES_set_decrypt_key,@function
+.align 16
+asm_AES_set_decrypt_key:
+.L_asm_AES_set_decrypt_key_begin:
+ call _x86_AES_set_encrypt_key
+ cmpl $0,%eax
+ je .L054proceed
+ ret
+.L054proceed:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ movl 28(%esp),%esi
+ movl 240(%esi),%ecx
+ leal (,%ecx,4),%ecx
+ leal (%esi,%ecx,4),%edi
+.align 4
+.L055invert:
+ movl (%esi),%eax
+ movl 4(%esi),%ebx
+ movl (%edi),%ecx
+ movl 4(%edi),%edx
+ movl %eax,(%edi)
+ movl %ebx,4(%edi)
+ movl %ecx,(%esi)
+ movl %edx,4(%esi)
+ movl 8(%esi),%eax
+ movl 12(%esi),%ebx
+ movl 8(%edi),%ecx
+ movl 12(%edi),%edx
+ movl %eax,8(%edi)
+ movl %ebx,12(%edi)
+ movl %ecx,8(%esi)
+ movl %edx,12(%esi)
+ addl $16,%esi
+ subl $16,%edi
+ cmpl %edi,%esi
+ jne .L055invert
+ movl 28(%esp),%edi
+ movl 240(%edi),%esi
+ leal -2(%esi,%esi,1),%esi
+ leal (%edi,%esi,8),%esi
+ movl %esi,28(%esp)
+ movl 16(%edi),%eax
+.align 4
+.L056permute:
+ addl $16,%edi
+ movl $2155905152,%ebp
+ andl %eax,%ebp
+ leal (%eax,%eax,1),%ebx
+ movl %ebp,%esi
+ shrl $7,%ebp
+ subl %ebp,%esi
+ andl $4278124286,%ebx
+ andl $454761243,%esi
+ xorl %esi,%ebx
+ movl $2155905152,%ebp
+ andl %ebx,%ebp
+ leal (%ebx,%ebx,1),%ecx
+ movl %ebp,%esi
+ shrl $7,%ebp
+ subl %ebp,%esi
+ andl $4278124286,%ecx
+ andl $454761243,%esi
+ xorl %eax,%ebx
+ xorl %esi,%ecx
+ movl $2155905152,%ebp
+ andl %ecx,%ebp
+ leal (%ecx,%ecx,1),%edx
+ movl %ebp,%esi
+ shrl $7,%ebp
+ xorl %eax,%ecx
+ subl %ebp,%esi
+ andl $4278124286,%edx
+ andl $454761243,%esi
+ roll $8,%eax
+ xorl %esi,%edx
+ movl 4(%edi),%ebp
+ xorl %ebx,%eax
+ xorl %edx,%ebx
+ xorl %ecx,%eax
+ roll $24,%ebx
+ xorl %edx,%ecx
+ xorl %edx,%eax
+ roll $16,%ecx
+ xorl %ebx,%eax
+ roll $8,%edx
+ xorl %ecx,%eax
+ movl %ebp,%ebx
+ xorl %edx,%eax
+ movl %eax,(%edi)
+ movl $2155905152,%ebp
+ andl %ebx,%ebp
+ leal (%ebx,%ebx,1),%ecx
+ movl %ebp,%esi
+ shrl $7,%ebp
+ subl %ebp,%esi
+ andl $4278124286,%ecx
+ andl $454761243,%esi
+ xorl %esi,%ecx
+ movl $2155905152,%ebp
+ andl %ecx,%ebp
+ leal (%ecx,%ecx,1),%edx
+ movl %ebp,%esi
+ shrl $7,%ebp
+ subl %ebp,%esi
+ andl $4278124286,%edx
+ andl $454761243,%esi
+ xorl %ebx,%ecx
+ xorl %esi,%edx
+ movl $2155905152,%ebp
+ andl %edx,%ebp
+ leal (%edx,%edx,1),%eax
+ movl %ebp,%esi
+ shrl $7,%ebp
+ xorl %ebx,%edx
+ subl %ebp,%esi
+ andl $4278124286,%eax
+ andl $454761243,%esi
+ roll $8,%ebx
+ xorl %esi,%eax
+ movl 8(%edi),%ebp
+ xorl %ecx,%ebx
+ xorl %eax,%ecx
+ xorl %edx,%ebx
+ roll $24,%ecx
+ xorl %eax,%edx
+ xorl %eax,%ebx
+ roll $16,%edx
+ xorl %ecx,%ebx
+ roll $8,%eax
+ xorl %edx,%ebx
+ movl %ebp,%ecx
+ xorl %eax,%ebx
+ movl %ebx,4(%edi)
+ movl $2155905152,%ebp
+ andl %ecx,%ebp
+ leal (%ecx,%ecx,1),%edx
+ movl %ebp,%esi
+ shrl $7,%ebp
+ subl %ebp,%esi
+ andl $4278124286,%edx
+ andl $454761243,%esi
+ xorl %esi,%edx
+ movl $2155905152,%ebp
+ andl %edx,%ebp
+ leal (%edx,%edx,1),%eax
+ movl %ebp,%esi
+ shrl $7,%ebp
+ subl %ebp,%esi
+ andl $4278124286,%eax
+ andl $454761243,%esi
+ xorl %ecx,%edx
+ xorl %esi,%eax
+ movl $2155905152,%ebp
+ andl %eax,%ebp
+ leal (%eax,%eax,1),%ebx
+ movl %ebp,%esi
+ shrl $7,%ebp
+ xorl %ecx,%eax
+ subl %ebp,%esi
+ andl $4278124286,%ebx
+ andl $454761243,%esi
+ roll $8,%ecx
+ xorl %esi,%ebx
+ movl 12(%edi),%ebp
+ xorl %edx,%ecx
+ xorl %ebx,%edx
+ xorl %eax,%ecx
+ roll $24,%edx
+ xorl %ebx,%eax
+ xorl %ebx,%ecx
+ roll $16,%eax
+ xorl %edx,%ecx
+ roll $8,%ebx
+ xorl %eax,%ecx
+ movl %ebp,%edx
+ xorl %ebx,%ecx
+ movl %ecx,8(%edi)
+ movl $2155905152,%ebp
+ andl %edx,%ebp
+ leal (%edx,%edx,1),%eax
+ movl %ebp,%esi
+ shrl $7,%ebp
+ subl %ebp,%esi
+ andl $4278124286,%eax
+ andl $454761243,%esi
+ xorl %esi,%eax
+ movl $2155905152,%ebp
+ andl %eax,%ebp
+ leal (%eax,%eax,1),%ebx
+ movl %ebp,%esi
+ shrl $7,%ebp
+ subl %ebp,%esi
+ andl $4278124286,%ebx
+ andl $454761243,%esi
+ xorl %edx,%eax
+ xorl %esi,%ebx
+ movl $2155905152,%ebp
+ andl %ebx,%ebp
+ leal (%ebx,%ebx,1),%ecx
+ movl %ebp,%esi
+ shrl $7,%ebp
+ xorl %edx,%ebx
+ subl %ebp,%esi
+ andl $4278124286,%ecx
+ andl $454761243,%esi
+ roll $8,%edx
+ xorl %esi,%ecx
+ movl 16(%edi),%ebp
+ xorl %eax,%edx
+ xorl %ecx,%eax
+ xorl %ebx,%edx
+ roll $24,%eax
+ xorl %ecx,%ebx
+ xorl %ecx,%edx
+ roll $16,%ebx
+ xorl %eax,%edx
+ roll $8,%ecx
+ xorl %ebx,%edx
+ movl %ebp,%eax
+ xorl %ecx,%edx
+ movl %edx,12(%edi)
+ cmpl 28(%esp),%edi
+ jb .L056permute
+ xorl %eax,%eax
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.size asm_AES_set_decrypt_key,.-.L_asm_AES_set_decrypt_key_begin
+.byte 65,69,83,32,102,111,114,32,120,56,54,44,32,67,82,89
+.byte 80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114
+.byte 111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
+#endif
diff --git a/linux-x86/crypto/aes/aesni-x86.S b/linux-x86/crypto/aes/aesni-x86.S
new file mode 100644
index 0000000..5aee116
--- /dev/null
+++ b/linux-x86/crypto/aes/aesni-x86.S
@@ -0,0 +1,2218 @@
+#if defined(__i386__)
+.file "src/crypto/aes/asm/aesni-x86.S"
+.text
+.globl aesni_encrypt
+.hidden aesni_encrypt
+.type aesni_encrypt,@function
+.align 16
+aesni_encrypt:
+.L_aesni_encrypt_begin:
+ movl 4(%esp),%eax
+ movl 12(%esp),%edx
+ movups (%eax),%xmm2
+ movl 240(%edx),%ecx
+ movl 8(%esp),%eax
+ movups (%edx),%xmm0
+ movups 16(%edx),%xmm1
+ leal 32(%edx),%edx
+ xorps %xmm0,%xmm2
+.L000enc1_loop_1:
+.byte 102,15,56,220,209
+ decl %ecx
+ movups (%edx),%xmm1
+ leal 16(%edx),%edx
+ jnz .L000enc1_loop_1
+.byte 102,15,56,221,209
+ movups %xmm2,(%eax)
+ ret
+.size aesni_encrypt,.-.L_aesni_encrypt_begin
+.globl aesni_decrypt
+.hidden aesni_decrypt
+.type aesni_decrypt,@function
+.align 16
+aesni_decrypt:
+.L_aesni_decrypt_begin:
+ movl 4(%esp),%eax
+ movl 12(%esp),%edx
+ movups (%eax),%xmm2
+ movl 240(%edx),%ecx
+ movl 8(%esp),%eax
+ movups (%edx),%xmm0
+ movups 16(%edx),%xmm1
+ leal 32(%edx),%edx
+ xorps %xmm0,%xmm2
+.L001dec1_loop_2:
+.byte 102,15,56,222,209
+ decl %ecx
+ movups (%edx),%xmm1
+ leal 16(%edx),%edx
+ jnz .L001dec1_loop_2
+.byte 102,15,56,223,209
+ movups %xmm2,(%eax)
+ ret
+.size aesni_decrypt,.-.L_aesni_decrypt_begin
+.hidden _aesni_encrypt2
+.type _aesni_encrypt2,@function
+.align 16
+_aesni_encrypt2:
+ movups (%edx),%xmm0
+ shll $4,%ecx
+ movups 16(%edx),%xmm1
+ xorps %xmm0,%xmm2
+ pxor %xmm0,%xmm3
+ movups 32(%edx),%xmm0
+ leal 32(%edx,%ecx,1),%edx
+ negl %ecx
+ addl $16,%ecx
+.L002enc2_loop:
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+ movups (%edx,%ecx,1),%xmm1
+ addl $32,%ecx
+.byte 102,15,56,220,208
+.byte 102,15,56,220,216
+ movups -16(%edx,%ecx,1),%xmm0
+ jnz .L002enc2_loop
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+.byte 102,15,56,221,208
+.byte 102,15,56,221,216
+ ret
+.size _aesni_encrypt2,.-_aesni_encrypt2
+.hidden _aesni_decrypt2
+.type _aesni_decrypt2,@function
+.align 16
+_aesni_decrypt2:
+ movups (%edx),%xmm0
+ shll $4,%ecx
+ movups 16(%edx),%xmm1
+ xorps %xmm0,%xmm2
+ pxor %xmm0,%xmm3
+ movups 32(%edx),%xmm0
+ leal 32(%edx,%ecx,1),%edx
+ negl %ecx
+ addl $16,%ecx
+.L003dec2_loop:
+.byte 102,15,56,222,209
+.byte 102,15,56,222,217
+ movups (%edx,%ecx,1),%xmm1
+ addl $32,%ecx
+.byte 102,15,56,222,208
+.byte 102,15,56,222,216
+ movups -16(%edx,%ecx,1),%xmm0
+ jnz .L003dec2_loop
+.byte 102,15,56,222,209
+.byte 102,15,56,222,217
+.byte 102,15,56,223,208
+.byte 102,15,56,223,216
+ ret
+.size _aesni_decrypt2,.-_aesni_decrypt2
+.hidden _aesni_encrypt3
+.type _aesni_encrypt3,@function
+.align 16
+_aesni_encrypt3:
+ movups (%edx),%xmm0
+ shll $4,%ecx
+ movups 16(%edx),%xmm1
+ xorps %xmm0,%xmm2
+ pxor %xmm0,%xmm3
+ pxor %xmm0,%xmm4
+ movups 32(%edx),%xmm0
+ leal 32(%edx,%ecx,1),%edx
+ negl %ecx
+ addl $16,%ecx
+.L004enc3_loop:
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+.byte 102,15,56,220,225
+ movups (%edx,%ecx,1),%xmm1
+ addl $32,%ecx
+.byte 102,15,56,220,208
+.byte 102,15,56,220,216
+.byte 102,15,56,220,224
+ movups -16(%edx,%ecx,1),%xmm0
+ jnz .L004enc3_loop
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+.byte 102,15,56,220,225
+.byte 102,15,56,221,208
+.byte 102,15,56,221,216
+.byte 102,15,56,221,224
+ ret
+.size _aesni_encrypt3,.-_aesni_encrypt3
+.hidden _aesni_decrypt3
+.type _aesni_decrypt3,@function
+.align 16
+_aesni_decrypt3:
+ movups (%edx),%xmm0
+ shll $4,%ecx
+ movups 16(%edx),%xmm1
+ xorps %xmm0,%xmm2
+ pxor %xmm0,%xmm3
+ pxor %xmm0,%xmm4
+ movups 32(%edx),%xmm0
+ leal 32(%edx,%ecx,1),%edx
+ negl %ecx
+ addl $16,%ecx
+.L005dec3_loop:
+.byte 102,15,56,222,209
+.byte 102,15,56,222,217
+.byte 102,15,56,222,225
+ movups (%edx,%ecx,1),%xmm1
+ addl $32,%ecx
+.byte 102,15,56,222,208
+.byte 102,15,56,222,216
+.byte 102,15,56,222,224
+ movups -16(%edx,%ecx,1),%xmm0
+ jnz .L005dec3_loop
+.byte 102,15,56,222,209
+.byte 102,15,56,222,217
+.byte 102,15,56,222,225
+.byte 102,15,56,223,208
+.byte 102,15,56,223,216
+.byte 102,15,56,223,224
+ ret
+.size _aesni_decrypt3,.-_aesni_decrypt3
+.hidden _aesni_encrypt4
+.type _aesni_encrypt4,@function
+.align 16
+_aesni_encrypt4:
+ movups (%edx),%xmm0
+ movups 16(%edx),%xmm1
+ shll $4,%ecx
+ xorps %xmm0,%xmm2
+ pxor %xmm0,%xmm3
+ pxor %xmm0,%xmm4
+ pxor %xmm0,%xmm5
+ movups 32(%edx),%xmm0
+ leal 32(%edx,%ecx,1),%edx
+ negl %ecx
+.byte 15,31,64,0
+ addl $16,%ecx
+.L006enc4_loop:
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+.byte 102,15,56,220,225
+.byte 102,15,56,220,233
+ movups (%edx,%ecx,1),%xmm1
+ addl $32,%ecx
+.byte 102,15,56,220,208
+.byte 102,15,56,220,216
+.byte 102,15,56,220,224
+.byte 102,15,56,220,232
+ movups -16(%edx,%ecx,1),%xmm0
+ jnz .L006enc4_loop
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+.byte 102,15,56,220,225
+.byte 102,15,56,220,233
+.byte 102,15,56,221,208
+.byte 102,15,56,221,216
+.byte 102,15,56,221,224
+.byte 102,15,56,221,232
+ ret
+.size _aesni_encrypt4,.-_aesni_encrypt4
+.hidden _aesni_decrypt4
+.type _aesni_decrypt4,@function
+.align 16
+_aesni_decrypt4:
+ movups (%edx),%xmm0
+ movups 16(%edx),%xmm1
+ shll $4,%ecx
+ xorps %xmm0,%xmm2
+ pxor %xmm0,%xmm3
+ pxor %xmm0,%xmm4
+ pxor %xmm0,%xmm5
+ movups 32(%edx),%xmm0
+ leal 32(%edx,%ecx,1),%edx
+ negl %ecx
+.byte 15,31,64,0
+ addl $16,%ecx
+.L007dec4_loop:
+.byte 102,15,56,222,209
+.byte 102,15,56,222,217
+.byte 102,15,56,222,225
+.byte 102,15,56,222,233
+ movups (%edx,%ecx,1),%xmm1
+ addl $32,%ecx
+.byte 102,15,56,222,208
+.byte 102,15,56,222,216
+.byte 102,15,56,222,224
+.byte 102,15,56,222,232
+ movups -16(%edx,%ecx,1),%xmm0
+ jnz .L007dec4_loop
+.byte 102,15,56,222,209
+.byte 102,15,56,222,217
+.byte 102,15,56,222,225
+.byte 102,15,56,222,233
+.byte 102,15,56,223,208
+.byte 102,15,56,223,216
+.byte 102,15,56,223,224
+.byte 102,15,56,223,232
+ ret
+.size _aesni_decrypt4,.-_aesni_decrypt4
+.hidden _aesni_encrypt6
+.type _aesni_encrypt6,@function
+.align 16
+_aesni_encrypt6:
+ movups (%edx),%xmm0
+ shll $4,%ecx
+ movups 16(%edx),%xmm1
+ xorps %xmm0,%xmm2
+ pxor %xmm0,%xmm3
+ pxor %xmm0,%xmm4
+.byte 102,15,56,220,209
+ pxor %xmm0,%xmm5
+ pxor %xmm0,%xmm6
+.byte 102,15,56,220,217
+ leal 32(%edx,%ecx,1),%edx
+ negl %ecx
+.byte 102,15,56,220,225
+ pxor %xmm0,%xmm7
+ addl $16,%ecx
+.byte 102,15,56,220,233
+.byte 102,15,56,220,241
+.byte 102,15,56,220,249
+ movups -16(%edx,%ecx,1),%xmm0
+ jmp .L_aesni_encrypt6_enter
+.align 16
+.L008enc6_loop:
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+.byte 102,15,56,220,225
+.byte 102,15,56,220,233
+.byte 102,15,56,220,241
+.byte 102,15,56,220,249
+.L_aesni_encrypt6_enter:
+ movups (%edx,%ecx,1),%xmm1
+ addl $32,%ecx
+.byte 102,15,56,220,208
+.byte 102,15,56,220,216
+.byte 102,15,56,220,224
+.byte 102,15,56,220,232
+.byte 102,15,56,220,240
+.byte 102,15,56,220,248
+ movups -16(%edx,%ecx,1),%xmm0
+ jnz .L008enc6_loop
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+.byte 102,15,56,220,225
+.byte 102,15,56,220,233
+.byte 102,15,56,220,241
+.byte 102,15,56,220,249
+.byte 102,15,56,221,208
+.byte 102,15,56,221,216
+.byte 102,15,56,221,224
+.byte 102,15,56,221,232
+.byte 102,15,56,221,240
+.byte 102,15,56,221,248
+ ret
+.size _aesni_encrypt6,.-_aesni_encrypt6
+.hidden _aesni_decrypt6
+.type _aesni_decrypt6,@function
+.align 16
+_aesni_decrypt6:
+ movups (%edx),%xmm0
+ shll $4,%ecx
+ movups 16(%edx),%xmm1
+ xorps %xmm0,%xmm2
+ pxor %xmm0,%xmm3
+ pxor %xmm0,%xmm4
+.byte 102,15,56,222,209
+ pxor %xmm0,%xmm5
+ pxor %xmm0,%xmm6
+.byte 102,15,56,222,217
+ leal 32(%edx,%ecx,1),%edx
+ negl %ecx
+.byte 102,15,56,222,225
+ pxor %xmm0,%xmm7
+ addl $16,%ecx
+.byte 102,15,56,222,233
+.byte 102,15,56,222,241
+.byte 102,15,56,222,249
+ movups -16(%edx,%ecx,1),%xmm0
+ jmp .L_aesni_decrypt6_enter
+.align 16
+.L009dec6_loop:
+.byte 102,15,56,222,209
+.byte 102,15,56,222,217
+.byte 102,15,56,222,225
+.byte 102,15,56,222,233
+.byte 102,15,56,222,241
+.byte 102,15,56,222,249
+.L_aesni_decrypt6_enter:
+ movups (%edx,%ecx,1),%xmm1
+ addl $32,%ecx
+.byte 102,15,56,222,208
+.byte 102,15,56,222,216
+.byte 102,15,56,222,224
+.byte 102,15,56,222,232
+.byte 102,15,56,222,240
+.byte 102,15,56,222,248
+ movups -16(%edx,%ecx,1),%xmm0
+ jnz .L009dec6_loop
+.byte 102,15,56,222,209
+.byte 102,15,56,222,217
+.byte 102,15,56,222,225
+.byte 102,15,56,222,233
+.byte 102,15,56,222,241
+.byte 102,15,56,222,249
+.byte 102,15,56,223,208
+.byte 102,15,56,223,216
+.byte 102,15,56,223,224
+.byte 102,15,56,223,232
+.byte 102,15,56,223,240
+.byte 102,15,56,223,248
+ ret
+.size _aesni_decrypt6,.-_aesni_decrypt6
+.globl aesni_ecb_encrypt
+.hidden aesni_ecb_encrypt
+.type aesni_ecb_encrypt,@function
+.align 16
+aesni_ecb_encrypt:
+.L_aesni_ecb_encrypt_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ movl 20(%esp),%esi
+ movl 24(%esp),%edi
+ movl 28(%esp),%eax
+ movl 32(%esp),%edx
+ movl 36(%esp),%ebx
+ andl $-16,%eax
+ jz .L010ecb_ret
+ movl 240(%edx),%ecx
+ testl %ebx,%ebx
+ jz .L011ecb_decrypt
+ movl %edx,%ebp
+ movl %ecx,%ebx
+ cmpl $96,%eax
+ jb .L012ecb_enc_tail
+ movdqu (%esi),%xmm2
+ movdqu 16(%esi),%xmm3
+ movdqu 32(%esi),%xmm4
+ movdqu 48(%esi),%xmm5
+ movdqu 64(%esi),%xmm6
+ movdqu 80(%esi),%xmm7
+ leal 96(%esi),%esi
+ subl $96,%eax
+ jmp .L013ecb_enc_loop6_enter
+.align 16
+.L014ecb_enc_loop6:
+ movups %xmm2,(%edi)
+ movdqu (%esi),%xmm2
+ movups %xmm3,16(%edi)
+ movdqu 16(%esi),%xmm3
+ movups %xmm4,32(%edi)
+ movdqu 32(%esi),%xmm4
+ movups %xmm5,48(%edi)
+ movdqu 48(%esi),%xmm5
+ movups %xmm6,64(%edi)
+ movdqu 64(%esi),%xmm6
+ movups %xmm7,80(%edi)
+ leal 96(%edi),%edi
+ movdqu 80(%esi),%xmm7
+ leal 96(%esi),%esi
+.L013ecb_enc_loop6_enter:
+ call _aesni_encrypt6
+ movl %ebp,%edx
+ movl %ebx,%ecx
+ subl $96,%eax
+ jnc .L014ecb_enc_loop6
+ movups %xmm2,(%edi)
+ movups %xmm3,16(%edi)
+ movups %xmm4,32(%edi)
+ movups %xmm5,48(%edi)
+ movups %xmm6,64(%edi)
+ movups %xmm7,80(%edi)
+ leal 96(%edi),%edi
+ addl $96,%eax
+ jz .L010ecb_ret
+.L012ecb_enc_tail:
+ movups (%esi),%xmm2
+ cmpl $32,%eax
+ jb .L015ecb_enc_one
+ movups 16(%esi),%xmm3
+ je .L016ecb_enc_two
+ movups 32(%esi),%xmm4
+ cmpl $64,%eax
+ jb .L017ecb_enc_three
+ movups 48(%esi),%xmm5
+ je .L018ecb_enc_four
+ movups 64(%esi),%xmm6
+ xorps %xmm7,%xmm7
+ call _aesni_encrypt6
+ movups %xmm2,(%edi)
+ movups %xmm3,16(%edi)
+ movups %xmm4,32(%edi)
+ movups %xmm5,48(%edi)
+ movups %xmm6,64(%edi)
+ jmp .L010ecb_ret
+.align 16
+.L015ecb_enc_one:
+ movups (%edx),%xmm0
+ movups 16(%edx),%xmm1
+ leal 32(%edx),%edx
+ xorps %xmm0,%xmm2
+.L019enc1_loop_3:
+.byte 102,15,56,220,209
+ decl %ecx
+ movups (%edx),%xmm1
+ leal 16(%edx),%edx
+ jnz .L019enc1_loop_3
+.byte 102,15,56,221,209
+ movups %xmm2,(%edi)
+ jmp .L010ecb_ret
+.align 16
+.L016ecb_enc_two:
+ call _aesni_encrypt2
+ movups %xmm2,(%edi)
+ movups %xmm3,16(%edi)
+ jmp .L010ecb_ret
+.align 16
+.L017ecb_enc_three:
+ call _aesni_encrypt3
+ movups %xmm2,(%edi)
+ movups %xmm3,16(%edi)
+ movups %xmm4,32(%edi)
+ jmp .L010ecb_ret
+.align 16
+.L018ecb_enc_four:
+ call _aesni_encrypt4
+ movups %xmm2,(%edi)
+ movups %xmm3,16(%edi)
+ movups %xmm4,32(%edi)
+ movups %xmm5,48(%edi)
+ jmp .L010ecb_ret
+.align 16
+.L011ecb_decrypt:
+ movl %edx,%ebp
+ movl %ecx,%ebx
+ cmpl $96,%eax
+ jb .L020ecb_dec_tail
+ movdqu (%esi),%xmm2
+ movdqu 16(%esi),%xmm3
+ movdqu 32(%esi),%xmm4
+ movdqu 48(%esi),%xmm5
+ movdqu 64(%esi),%xmm6
+ movdqu 80(%esi),%xmm7
+ leal 96(%esi),%esi
+ subl $96,%eax
+ jmp .L021ecb_dec_loop6_enter
+.align 16
+.L022ecb_dec_loop6:
+ movups %xmm2,(%edi)
+ movdqu (%esi),%xmm2
+ movups %xmm3,16(%edi)
+ movdqu 16(%esi),%xmm3
+ movups %xmm4,32(%edi)
+ movdqu 32(%esi),%xmm4
+ movups %xmm5,48(%edi)
+ movdqu 48(%esi),%xmm5
+ movups %xmm6,64(%edi)
+ movdqu 64(%esi),%xmm6
+ movups %xmm7,80(%edi)
+ leal 96(%edi),%edi
+ movdqu 80(%esi),%xmm7
+ leal 96(%esi),%esi
+.L021ecb_dec_loop6_enter:
+ call _aesni_decrypt6
+ movl %ebp,%edx
+ movl %ebx,%ecx
+ subl $96,%eax
+ jnc .L022ecb_dec_loop6
+ movups %xmm2,(%edi)
+ movups %xmm3,16(%edi)
+ movups %xmm4,32(%edi)
+ movups %xmm5,48(%edi)
+ movups %xmm6,64(%edi)
+ movups %xmm7,80(%edi)
+ leal 96(%edi),%edi
+ addl $96,%eax
+ jz .L010ecb_ret
+.L020ecb_dec_tail:
+ movups (%esi),%xmm2
+ cmpl $32,%eax
+ jb .L023ecb_dec_one
+ movups 16(%esi),%xmm3
+ je .L024ecb_dec_two
+ movups 32(%esi),%xmm4
+ cmpl $64,%eax
+ jb .L025ecb_dec_three
+ movups 48(%esi),%xmm5
+ je .L026ecb_dec_four
+ movups 64(%esi),%xmm6
+ xorps %xmm7,%xmm7
+ call _aesni_decrypt6
+ movups %xmm2,(%edi)
+ movups %xmm3,16(%edi)
+ movups %xmm4,32(%edi)
+ movups %xmm5,48(%edi)
+ movups %xmm6,64(%edi)
+ jmp .L010ecb_ret
+.align 16
+.L023ecb_dec_one:
+ movups (%edx),%xmm0
+ movups 16(%edx),%xmm1
+ leal 32(%edx),%edx
+ xorps %xmm0,%xmm2
+.L027dec1_loop_4:
+.byte 102,15,56,222,209
+ decl %ecx
+ movups (%edx),%xmm1
+ leal 16(%edx),%edx
+ jnz .L027dec1_loop_4
+.byte 102,15,56,223,209
+ movups %xmm2,(%edi)
+ jmp .L010ecb_ret
+.align 16
+.L024ecb_dec_two:
+ call _aesni_decrypt2
+ movups %xmm2,(%edi)
+ movups %xmm3,16(%edi)
+ jmp .L010ecb_ret
+.align 16
+.L025ecb_dec_three:
+ call _aesni_decrypt3
+ movups %xmm2,(%edi)
+ movups %xmm3,16(%edi)
+ movups %xmm4,32(%edi)
+ jmp .L010ecb_ret
+.align 16
+.L026ecb_dec_four:
+ call _aesni_decrypt4
+ movups %xmm2,(%edi)
+ movups %xmm3,16(%edi)
+ movups %xmm4,32(%edi)
+ movups %xmm5,48(%edi)
+.L010ecb_ret:
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.size aesni_ecb_encrypt,.-.L_aesni_ecb_encrypt_begin
+.globl aesni_ccm64_encrypt_blocks
+.hidden aesni_ccm64_encrypt_blocks
+.type aesni_ccm64_encrypt_blocks,@function
+.align 16
+aesni_ccm64_encrypt_blocks:
+.L_aesni_ccm64_encrypt_blocks_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ movl 20(%esp),%esi
+ movl 24(%esp),%edi
+ movl 28(%esp),%eax
+ movl 32(%esp),%edx
+ movl 36(%esp),%ebx
+ movl 40(%esp),%ecx
+ movl %esp,%ebp
+ subl $60,%esp
+ andl $-16,%esp
+ movl %ebp,48(%esp)
+ movdqu (%ebx),%xmm7
+ movdqu (%ecx),%xmm3
+ movl 240(%edx),%ecx
+ movl $202182159,(%esp)
+ movl $134810123,4(%esp)
+ movl $67438087,8(%esp)
+ movl $66051,12(%esp)
+ movl $1,%ebx
+ xorl %ebp,%ebp
+ movl %ebx,16(%esp)
+ movl %ebp,20(%esp)
+ movl %ebp,24(%esp)
+ movl %ebp,28(%esp)
+ shll $4,%ecx
+ movl $16,%ebx
+ leal (%edx),%ebp
+ movdqa (%esp),%xmm5
+ movdqa %xmm7,%xmm2
+ leal 32(%edx,%ecx,1),%edx
+ subl %ecx,%ebx
+.byte 102,15,56,0,253
+.L028ccm64_enc_outer:
+ movups (%ebp),%xmm0
+ movl %ebx,%ecx
+ movups (%esi),%xmm6
+ xorps %xmm0,%xmm2
+ movups 16(%ebp),%xmm1
+ xorps %xmm6,%xmm0
+ xorps %xmm0,%xmm3
+ movups 32(%ebp),%xmm0
+.L029ccm64_enc2_loop:
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+ movups (%edx,%ecx,1),%xmm1
+ addl $32,%ecx
+.byte 102,15,56,220,208
+.byte 102,15,56,220,216
+ movups -16(%edx,%ecx,1),%xmm0
+ jnz .L029ccm64_enc2_loop
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+ paddq 16(%esp),%xmm7
+ decl %eax
+.byte 102,15,56,221,208
+.byte 102,15,56,221,216
+ leal 16(%esi),%esi
+ xorps %xmm2,%xmm6
+ movdqa %xmm7,%xmm2
+ movups %xmm6,(%edi)
+.byte 102,15,56,0,213
+ leal 16(%edi),%edi
+ jnz .L028ccm64_enc_outer
+ movl 48(%esp),%esp
+ movl 40(%esp),%edi
+ movups %xmm3,(%edi)
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.size aesni_ccm64_encrypt_blocks,.-.L_aesni_ccm64_encrypt_blocks_begin
+.globl aesni_ccm64_decrypt_blocks
+.hidden aesni_ccm64_decrypt_blocks
+.type aesni_ccm64_decrypt_blocks,@function
+.align 16
+aesni_ccm64_decrypt_blocks:
+.L_aesni_ccm64_decrypt_blocks_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ movl 20(%esp),%esi
+ movl 24(%esp),%edi
+ movl 28(%esp),%eax
+ movl 32(%esp),%edx
+ movl 36(%esp),%ebx
+ movl 40(%esp),%ecx
+ movl %esp,%ebp
+ subl $60,%esp
+ andl $-16,%esp
+ movl %ebp,48(%esp)
+ movdqu (%ebx),%xmm7
+ movdqu (%ecx),%xmm3
+ movl 240(%edx),%ecx
+ movl $202182159,(%esp)
+ movl $134810123,4(%esp)
+ movl $67438087,8(%esp)
+ movl $66051,12(%esp)
+ movl $1,%ebx
+ xorl %ebp,%ebp
+ movl %ebx,16(%esp)
+ movl %ebp,20(%esp)
+ movl %ebp,24(%esp)
+ movl %ebp,28(%esp)
+ movdqa (%esp),%xmm5
+ movdqa %xmm7,%xmm2
+ movl %edx,%ebp
+ movl %ecx,%ebx
+.byte 102,15,56,0,253
+ movups (%edx),%xmm0
+ movups 16(%edx),%xmm1
+ leal 32(%edx),%edx
+ xorps %xmm0,%xmm2
+.L030enc1_loop_5:
+.byte 102,15,56,220,209
+ decl %ecx
+ movups (%edx),%xmm1
+ leal 16(%edx),%edx
+ jnz .L030enc1_loop_5
+.byte 102,15,56,221,209
+ shll $4,%ebx
+ movl $16,%ecx
+ movups (%esi),%xmm6
+ paddq 16(%esp),%xmm7
+ leal 16(%esi),%esi
+ subl %ebx,%ecx
+ leal 32(%ebp,%ebx,1),%edx
+ movl %ecx,%ebx
+ jmp .L031ccm64_dec_outer
+.align 16
+.L031ccm64_dec_outer:
+ xorps %xmm2,%xmm6
+ movdqa %xmm7,%xmm2
+ movups %xmm6,(%edi)
+ leal 16(%edi),%edi
+.byte 102,15,56,0,213
+ subl $1,%eax
+ jz .L032ccm64_dec_break
+ movups (%ebp),%xmm0
+ movl %ebx,%ecx
+ movups 16(%ebp),%xmm1
+ xorps %xmm0,%xmm6
+ xorps %xmm0,%xmm2
+ xorps %xmm6,%xmm3
+ movups 32(%ebp),%xmm0
+.L033ccm64_dec2_loop:
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+ movups (%edx,%ecx,1),%xmm1
+ addl $32,%ecx
+.byte 102,15,56,220,208
+.byte 102,15,56,220,216
+ movups -16(%edx,%ecx,1),%xmm0
+ jnz .L033ccm64_dec2_loop
+ movups (%esi),%xmm6
+ paddq 16(%esp),%xmm7
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+.byte 102,15,56,221,208
+.byte 102,15,56,221,216
+ leal 16(%esi),%esi
+ jmp .L031ccm64_dec_outer
+.align 16
+.L032ccm64_dec_break:
+ movl 240(%ebp),%ecx
+ movl %ebp,%edx
+ movups (%edx),%xmm0
+ movups 16(%edx),%xmm1
+ xorps %xmm0,%xmm6
+ leal 32(%edx),%edx
+ xorps %xmm6,%xmm3
+.L034enc1_loop_6:
+.byte 102,15,56,220,217
+ decl %ecx
+ movups (%edx),%xmm1
+ leal 16(%edx),%edx
+ jnz .L034enc1_loop_6
+.byte 102,15,56,221,217
+ movl 48(%esp),%esp
+ movl 40(%esp),%edi
+ movups %xmm3,(%edi)
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.size aesni_ccm64_decrypt_blocks,.-.L_aesni_ccm64_decrypt_blocks_begin
+.globl aesni_ctr32_encrypt_blocks
+.hidden aesni_ctr32_encrypt_blocks
+.type aesni_ctr32_encrypt_blocks,@function
+.align 16
+aesni_ctr32_encrypt_blocks:
+.L_aesni_ctr32_encrypt_blocks_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ movl 20(%esp),%esi
+ movl 24(%esp),%edi
+ movl 28(%esp),%eax
+ movl 32(%esp),%edx
+ movl 36(%esp),%ebx
+ movl %esp,%ebp
+ subl $88,%esp
+ andl $-16,%esp
+ movl %ebp,80(%esp)
+ cmpl $1,%eax
+ je .L035ctr32_one_shortcut
+ movdqu (%ebx),%xmm7
+ movl $202182159,(%esp)
+ movl $134810123,4(%esp)
+ movl $67438087,8(%esp)
+ movl $66051,12(%esp)
+ movl $6,%ecx
+ xorl %ebp,%ebp
+ movl %ecx,16(%esp)
+ movl %ecx,20(%esp)
+ movl %ecx,24(%esp)
+ movl %ebp,28(%esp)
+.byte 102,15,58,22,251,3
+.byte 102,15,58,34,253,3
+ movl 240(%edx),%ecx
+ bswap %ebx
+ pxor %xmm0,%xmm0
+ pxor %xmm1,%xmm1
+ movdqa (%esp),%xmm2
+.byte 102,15,58,34,195,0
+ leal 3(%ebx),%ebp
+.byte 102,15,58,34,205,0
+ incl %ebx
+.byte 102,15,58,34,195,1
+ incl %ebp
+.byte 102,15,58,34,205,1
+ incl %ebx
+.byte 102,15,58,34,195,2
+ incl %ebp
+.byte 102,15,58,34,205,2
+ movdqa %xmm0,48(%esp)
+.byte 102,15,56,0,194
+ movdqu (%edx),%xmm6
+ movdqa %xmm1,64(%esp)
+.byte 102,15,56,0,202
+ pshufd $192,%xmm0,%xmm2
+ pshufd $128,%xmm0,%xmm3
+ cmpl $6,%eax
+ jb .L036ctr32_tail
+ pxor %xmm6,%xmm7
+ shll $4,%ecx
+ movl $16,%ebx
+ movdqa %xmm7,32(%esp)
+ movl %edx,%ebp
+ subl %ecx,%ebx
+ leal 32(%edx,%ecx,1),%edx
+ subl $6,%eax
+ jmp .L037ctr32_loop6
+.align 16
+.L037ctr32_loop6:
+ pshufd $64,%xmm0,%xmm4
+ movdqa 32(%esp),%xmm0
+ pshufd $192,%xmm1,%xmm5
+ pxor %xmm0,%xmm2
+ pshufd $128,%xmm1,%xmm6
+ pxor %xmm0,%xmm3
+ pshufd $64,%xmm1,%xmm7
+ movups 16(%ebp),%xmm1
+ pxor %xmm0,%xmm4
+ pxor %xmm0,%xmm5
+.byte 102,15,56,220,209
+ pxor %xmm0,%xmm6
+ pxor %xmm0,%xmm7
+.byte 102,15,56,220,217
+ movups 32(%ebp),%xmm0
+ movl %ebx,%ecx
+.byte 102,15,56,220,225
+.byte 102,15,56,220,233
+.byte 102,15,56,220,241
+.byte 102,15,56,220,249
+ call .L_aesni_encrypt6_enter
+ movups (%esi),%xmm1
+ movups 16(%esi),%xmm0
+ xorps %xmm1,%xmm2
+ movups 32(%esi),%xmm1
+ xorps %xmm0,%xmm3
+ movups %xmm2,(%edi)
+ movdqa 16(%esp),%xmm0
+ xorps %xmm1,%xmm4
+ movdqa 64(%esp),%xmm1
+ movups %xmm3,16(%edi)
+ movups %xmm4,32(%edi)
+ paddd %xmm0,%xmm1
+ paddd 48(%esp),%xmm0
+ movdqa (%esp),%xmm2
+ movups 48(%esi),%xmm3
+ movups 64(%esi),%xmm4
+ xorps %xmm3,%xmm5
+ movups 80(%esi),%xmm3
+ leal 96(%esi),%esi
+ movdqa %xmm0,48(%esp)
+.byte 102,15,56,0,194
+ xorps %xmm4,%xmm6
+ movups %xmm5,48(%edi)
+ xorps %xmm3,%xmm7
+ movdqa %xmm1,64(%esp)
+.byte 102,15,56,0,202
+ movups %xmm6,64(%edi)
+ pshufd $192,%xmm0,%xmm2
+ movups %xmm7,80(%edi)
+ leal 96(%edi),%edi
+ pshufd $128,%xmm0,%xmm3
+ subl $6,%eax
+ jnc .L037ctr32_loop6
+ addl $6,%eax
+ jz .L038ctr32_ret
+ movdqu (%ebp),%xmm7
+ movl %ebp,%edx
+ pxor 32(%esp),%xmm7
+ movl 240(%ebp),%ecx
+.L036ctr32_tail:
+ por %xmm7,%xmm2
+ cmpl $2,%eax
+ jb .L039ctr32_one
+ pshufd $64,%xmm0,%xmm4
+ por %xmm7,%xmm3
+ je .L040ctr32_two
+ pshufd $192,%xmm1,%xmm5
+ por %xmm7,%xmm4
+ cmpl $4,%eax
+ jb .L041ctr32_three
+ pshufd $128,%xmm1,%xmm6
+ por %xmm7,%xmm5
+ je .L042ctr32_four
+ por %xmm7,%xmm6
+ call _aesni_encrypt6
+ movups (%esi),%xmm1
+ movups 16(%esi),%xmm0
+ xorps %xmm1,%xmm2
+ movups 32(%esi),%xmm1
+ xorps %xmm0,%xmm3
+ movups 48(%esi),%xmm0
+ xorps %xmm1,%xmm4
+ movups 64(%esi),%xmm1
+ xorps %xmm0,%xmm5
+ movups %xmm2,(%edi)
+ xorps %xmm1,%xmm6
+ movups %xmm3,16(%edi)
+ movups %xmm4,32(%edi)
+ movups %xmm5,48(%edi)
+ movups %xmm6,64(%edi)
+ jmp .L038ctr32_ret
+.align 16
+.L035ctr32_one_shortcut:
+ movups (%ebx),%xmm2
+ movl 240(%edx),%ecx
+.L039ctr32_one:
+ movups (%edx),%xmm0
+ movups 16(%edx),%xmm1
+ leal 32(%edx),%edx
+ xorps %xmm0,%xmm2
+.L043enc1_loop_7:
+.byte 102,15,56,220,209
+ decl %ecx
+ movups (%edx),%xmm1
+ leal 16(%edx),%edx
+ jnz .L043enc1_loop_7
+.byte 102,15,56,221,209
+ movups (%esi),%xmm6
+ xorps %xmm2,%xmm6
+ movups %xmm6,(%edi)
+ jmp .L038ctr32_ret
+.align 16
+.L040ctr32_two:
+ call _aesni_encrypt2
+ movups (%esi),%xmm5
+ movups 16(%esi),%xmm6
+ xorps %xmm5,%xmm2
+ xorps %xmm6,%xmm3
+ movups %xmm2,(%edi)
+ movups %xmm3,16(%edi)
+ jmp .L038ctr32_ret
+.align 16
+.L041ctr32_three:
+ call _aesni_encrypt3
+ movups (%esi),%xmm5
+ movups 16(%esi),%xmm6
+ xorps %xmm5,%xmm2
+ movups 32(%esi),%xmm7
+ xorps %xmm6,%xmm3
+ movups %xmm2,(%edi)
+ xorps %xmm7,%xmm4
+ movups %xmm3,16(%edi)
+ movups %xmm4,32(%edi)
+ jmp .L038ctr32_ret
+.align 16
+.L042ctr32_four:
+ call _aesni_encrypt4
+ movups (%esi),%xmm6
+ movups 16(%esi),%xmm7
+ movups 32(%esi),%xmm1
+ xorps %xmm6,%xmm2
+ movups 48(%esi),%xmm0
+ xorps %xmm7,%xmm3
+ movups %xmm2,(%edi)
+ xorps %xmm1,%xmm4
+ movups %xmm3,16(%edi)
+ xorps %xmm0,%xmm5
+ movups %xmm4,32(%edi)
+ movups %xmm5,48(%edi)
+.L038ctr32_ret:
+ movl 80(%esp),%esp
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.size aesni_ctr32_encrypt_blocks,.-.L_aesni_ctr32_encrypt_blocks_begin
+.globl aesni_xts_encrypt
+.hidden aesni_xts_encrypt
+.type aesni_xts_encrypt,@function
+.align 16
+aesni_xts_encrypt:
+.L_aesni_xts_encrypt_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ movl 36(%esp),%edx
+ movl 40(%esp),%esi
+ movl 240(%edx),%ecx
+ movups (%esi),%xmm2
+ movups (%edx),%xmm0
+ movups 16(%edx),%xmm1
+ leal 32(%edx),%edx
+ xorps %xmm0,%xmm2
+.L044enc1_loop_8:
+.byte 102,15,56,220,209
+ decl %ecx
+ movups (%edx),%xmm1
+ leal 16(%edx),%edx
+ jnz .L044enc1_loop_8
+.byte 102,15,56,221,209
+ movl 20(%esp),%esi
+ movl 24(%esp),%edi
+ movl 28(%esp),%eax
+ movl 32(%esp),%edx
+ movl %esp,%ebp
+ subl $120,%esp
+ movl 240(%edx),%ecx
+ andl $-16,%esp
+ movl $135,96(%esp)
+ movl $0,100(%esp)
+ movl $1,104(%esp)
+ movl $0,108(%esp)
+ movl %eax,112(%esp)
+ movl %ebp,116(%esp)
+ movdqa %xmm2,%xmm1
+ pxor %xmm0,%xmm0
+ movdqa 96(%esp),%xmm3
+ pcmpgtd %xmm1,%xmm0
+ andl $-16,%eax
+ movl %edx,%ebp
+ movl %ecx,%ebx
+ subl $96,%eax
+ jc .L045xts_enc_short
+ shll $4,%ecx
+ movl $16,%ebx
+ subl %ecx,%ebx
+ leal 32(%edx,%ecx,1),%edx
+ jmp .L046xts_enc_loop6
+.align 16
+.L046xts_enc_loop6:
+ pshufd $19,%xmm0,%xmm2
+ pxor %xmm0,%xmm0
+ movdqa %xmm1,(%esp)
+ paddq %xmm1,%xmm1
+ pand %xmm3,%xmm2
+ pcmpgtd %xmm1,%xmm0
+ pxor %xmm2,%xmm1
+ pshufd $19,%xmm0,%xmm2
+ pxor %xmm0,%xmm0
+ movdqa %xmm1,16(%esp)
+ paddq %xmm1,%xmm1
+ pand %xmm3,%xmm2
+ pcmpgtd %xmm1,%xmm0
+ pxor %xmm2,%xmm1
+ pshufd $19,%xmm0,%xmm2
+ pxor %xmm0,%xmm0
+ movdqa %xmm1,32(%esp)
+ paddq %xmm1,%xmm1
+ pand %xmm3,%xmm2
+ pcmpgtd %xmm1,%xmm0
+ pxor %xmm2,%xmm1
+ pshufd $19,%xmm0,%xmm2
+ pxor %xmm0,%xmm0
+ movdqa %xmm1,48(%esp)
+ paddq %xmm1,%xmm1
+ pand %xmm3,%xmm2
+ pcmpgtd %xmm1,%xmm0
+ pxor %xmm2,%xmm1
+ pshufd $19,%xmm0,%xmm7
+ movdqa %xmm1,64(%esp)
+ paddq %xmm1,%xmm1
+ movups (%ebp),%xmm0
+ pand %xmm3,%xmm7
+ movups (%esi),%xmm2
+ pxor %xmm1,%xmm7
+ movl %ebx,%ecx
+ movdqu 16(%esi),%xmm3
+ xorps %xmm0,%xmm2
+ movdqu 32(%esi),%xmm4
+ pxor %xmm0,%xmm3
+ movdqu 48(%esi),%xmm5
+ pxor %xmm0,%xmm4
+ movdqu 64(%esi),%xmm6
+ pxor %xmm0,%xmm5
+ movdqu 80(%esi),%xmm1
+ pxor %xmm0,%xmm6
+ leal 96(%esi),%esi
+ pxor (%esp),%xmm2
+ movdqa %xmm7,80(%esp)
+ pxor %xmm1,%xmm7
+ movups 16(%ebp),%xmm1
+ pxor 16(%esp),%xmm3
+ pxor 32(%esp),%xmm4
+.byte 102,15,56,220,209
+ pxor 48(%esp),%xmm5
+ pxor 64(%esp),%xmm6
+.byte 102,15,56,220,217
+ pxor %xmm0,%xmm7
+ movups 32(%ebp),%xmm0
+.byte 102,15,56,220,225
+.byte 102,15,56,220,233
+.byte 102,15,56,220,241
+.byte 102,15,56,220,249
+ call .L_aesni_encrypt6_enter
+ movdqa 80(%esp),%xmm1
+ pxor %xmm0,%xmm0
+ xorps (%esp),%xmm2
+ pcmpgtd %xmm1,%xmm0
+ xorps 16(%esp),%xmm3
+ movups %xmm2,(%edi)
+ xorps 32(%esp),%xmm4
+ movups %xmm3,16(%edi)
+ xorps 48(%esp),%xmm5
+ movups %xmm4,32(%edi)
+ xorps 64(%esp),%xmm6
+ movups %xmm5,48(%edi)
+ xorps %xmm1,%xmm7
+ movups %xmm6,64(%edi)
+ pshufd $19,%xmm0,%xmm2
+ movups %xmm7,80(%edi)
+ leal 96(%edi),%edi
+ movdqa 96(%esp),%xmm3
+ pxor %xmm0,%xmm0
+ paddq %xmm1,%xmm1
+ pand %xmm3,%xmm2
+ pcmpgtd %xmm1,%xmm0
+ pxor %xmm2,%xmm1
+ subl $96,%eax
+ jnc .L046xts_enc_loop6
+ movl 240(%ebp),%ecx
+ movl %ebp,%edx
+ movl %ecx,%ebx
+.L045xts_enc_short:
+ addl $96,%eax
+ jz .L047xts_enc_done6x
+ movdqa %xmm1,%xmm5
+ cmpl $32,%eax
+ jb .L048xts_enc_one
+ pshufd $19,%xmm0,%xmm2
+ pxor %xmm0,%xmm0
+ paddq %xmm1,%xmm1
+ pand %xmm3,%xmm2
+ pcmpgtd %xmm1,%xmm0
+ pxor %xmm2,%xmm1
+ je .L049xts_enc_two
+ pshufd $19,%xmm0,%xmm2
+ pxor %xmm0,%xmm0
+ movdqa %xmm1,%xmm6
+ paddq %xmm1,%xmm1
+ pand %xmm3,%xmm2
+ pcmpgtd %xmm1,%xmm0
+ pxor %xmm2,%xmm1
+ cmpl $64,%eax
+ jb .L050xts_enc_three
+ pshufd $19,%xmm0,%xmm2
+ pxor %xmm0,%xmm0
+ movdqa %xmm1,%xmm7
+ paddq %xmm1,%xmm1
+ pand %xmm3,%xmm2
+ pcmpgtd %xmm1,%xmm0
+ pxor %xmm2,%xmm1
+ movdqa %xmm5,(%esp)
+ movdqa %xmm6,16(%esp)
+ je .L051xts_enc_four
+ movdqa %xmm7,32(%esp)
+ pshufd $19,%xmm0,%xmm7
+ movdqa %xmm1,48(%esp)
+ paddq %xmm1,%xmm1
+ pand %xmm3,%xmm7
+ pxor %xmm1,%xmm7
+ movdqu (%esi),%xmm2
+ movdqu 16(%esi),%xmm3
+ movdqu 32(%esi),%xmm4
+ pxor (%esp),%xmm2
+ movdqu 48(%esi),%xmm5
+ pxor 16(%esp),%xmm3
+ movdqu 64(%esi),%xmm6
+ pxor 32(%esp),%xmm4
+ leal 80(%esi),%esi
+ pxor 48(%esp),%xmm5
+ movdqa %xmm7,64(%esp)
+ pxor %xmm7,%xmm6
+ call _aesni_encrypt6
+ movaps 64(%esp),%xmm1
+ xorps (%esp),%xmm2
+ xorps 16(%esp),%xmm3
+ xorps 32(%esp),%xmm4
+ movups %xmm2,(%edi)
+ xorps 48(%esp),%xmm5
+ movups %xmm3,16(%edi)
+ xorps %xmm1,%xmm6
+ movups %xmm4,32(%edi)
+ movups %xmm5,48(%edi)
+ movups %xmm6,64(%edi)
+ leal 80(%edi),%edi
+ jmp .L052xts_enc_done
+.align 16
+.L048xts_enc_one:
+ movups (%esi),%xmm2
+ leal 16(%esi),%esi
+ xorps %xmm5,%xmm2
+ movups (%edx),%xmm0
+ movups 16(%edx),%xmm1
+ leal 32(%edx),%edx
+ xorps %xmm0,%xmm2
+.L053enc1_loop_9:
+.byte 102,15,56,220,209
+ decl %ecx
+ movups (%edx),%xmm1
+ leal 16(%edx),%edx
+ jnz .L053enc1_loop_9
+.byte 102,15,56,221,209
+ xorps %xmm5,%xmm2
+ movups %xmm2,(%edi)
+ leal 16(%edi),%edi
+ movdqa %xmm5,%xmm1
+ jmp .L052xts_enc_done
+.align 16
+.L049xts_enc_two:
+ movaps %xmm1,%xmm6
+ movups (%esi),%xmm2
+ movups 16(%esi),%xmm3
+ leal 32(%esi),%esi
+ xorps %xmm5,%xmm2
+ xorps %xmm6,%xmm3
+ call _aesni_encrypt2
+ xorps %xmm5,%xmm2
+ xorps %xmm6,%xmm3
+ movups %xmm2,(%edi)
+ movups %xmm3,16(%edi)
+ leal 32(%edi),%edi
+ movdqa %xmm6,%xmm1
+ jmp .L052xts_enc_done
+.align 16
+.L050xts_enc_three:
+ movaps %xmm1,%xmm7
+ movups (%esi),%xmm2
+ movups 16(%esi),%xmm3
+ movups 32(%esi),%xmm4
+ leal 48(%esi),%esi
+ xorps %xmm5,%xmm2
+ xorps %xmm6,%xmm3
+ xorps %xmm7,%xmm4
+ call _aesni_encrypt3
+ xorps %xmm5,%xmm2
+ xorps %xmm6,%xmm3
+ xorps %xmm7,%xmm4
+ movups %xmm2,(%edi)
+ movups %xmm3,16(%edi)
+ movups %xmm4,32(%edi)
+ leal 48(%edi),%edi
+ movdqa %xmm7,%xmm1
+ jmp .L052xts_enc_done
+.align 16
+.L051xts_enc_four:
+ movaps %xmm1,%xmm6
+ movups (%esi),%xmm2
+ movups 16(%esi),%xmm3
+ movups 32(%esi),%xmm4
+ xorps (%esp),%xmm2
+ movups 48(%esi),%xmm5
+ leal 64(%esi),%esi
+ xorps 16(%esp),%xmm3
+ xorps %xmm7,%xmm4
+ xorps %xmm6,%xmm5
+ call _aesni_encrypt4
+ xorps (%esp),%xmm2
+ xorps 16(%esp),%xmm3
+ xorps %xmm7,%xmm4
+ movups %xmm2,(%edi)
+ xorps %xmm6,%xmm5
+ movups %xmm3,16(%edi)
+ movups %xmm4,32(%edi)
+ movups %xmm5,48(%edi)
+ leal 64(%edi),%edi
+ movdqa %xmm6,%xmm1
+ jmp .L052xts_enc_done
+.align 16
+.L047xts_enc_done6x:
+ movl 112(%esp),%eax
+ andl $15,%eax
+ jz .L054xts_enc_ret
+ movdqa %xmm1,%xmm5
+ movl %eax,112(%esp)
+ jmp .L055xts_enc_steal
+.align 16
+.L052xts_enc_done:
+ movl 112(%esp),%eax
+ pxor %xmm0,%xmm0
+ andl $15,%eax
+ jz .L054xts_enc_ret
+ pcmpgtd %xmm1,%xmm0
+ movl %eax,112(%esp)
+ pshufd $19,%xmm0,%xmm5
+ paddq %xmm1,%xmm1
+ pand 96(%esp),%xmm5
+ pxor %xmm1,%xmm5
+.L055xts_enc_steal:
+ movzbl (%esi),%ecx
+ movzbl -16(%edi),%edx
+ leal 1(%esi),%esi
+ movb %cl,-16(%edi)
+ movb %dl,(%edi)
+ leal 1(%edi),%edi
+ subl $1,%eax
+ jnz .L055xts_enc_steal
+ subl 112(%esp),%edi
+ movl %ebp,%edx
+ movl %ebx,%ecx
+ movups -16(%edi),%xmm2
+ xorps %xmm5,%xmm2
+ movups (%edx),%xmm0
+ movups 16(%edx),%xmm1
+ leal 32(%edx),%edx
+ xorps %xmm0,%xmm2
+.L056enc1_loop_10:
+.byte 102,15,56,220,209
+ decl %ecx
+ movups (%edx),%xmm1
+ leal 16(%edx),%edx
+ jnz .L056enc1_loop_10
+.byte 102,15,56,221,209
+ xorps %xmm5,%xmm2
+ movups %xmm2,-16(%edi)
+.L054xts_enc_ret:
+ movl 116(%esp),%esp
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.size aesni_xts_encrypt,.-.L_aesni_xts_encrypt_begin
+.globl aesni_xts_decrypt
+.hidden aesni_xts_decrypt
+.type aesni_xts_decrypt,@function
+.align 16
+aesni_xts_decrypt:
+.L_aesni_xts_decrypt_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ movl 36(%esp),%edx
+ movl 40(%esp),%esi
+ movl 240(%edx),%ecx
+ movups (%esi),%xmm2
+ movups (%edx),%xmm0
+ movups 16(%edx),%xmm1
+ leal 32(%edx),%edx
+ xorps %xmm0,%xmm2
+.L057enc1_loop_11:
+.byte 102,15,56,220,209
+ decl %ecx
+ movups (%edx),%xmm1
+ leal 16(%edx),%edx
+ jnz .L057enc1_loop_11
+.byte 102,15,56,221,209
+ movl 20(%esp),%esi
+ movl 24(%esp),%edi
+ movl 28(%esp),%eax
+ movl 32(%esp),%edx
+ movl %esp,%ebp
+ subl $120,%esp
+ andl $-16,%esp
+ xorl %ebx,%ebx
+ testl $15,%eax
+ setnz %bl
+ shll $4,%ebx
+ subl %ebx,%eax
+ movl $135,96(%esp)
+ movl $0,100(%esp)
+ movl $1,104(%esp)
+ movl $0,108(%esp)
+ movl %eax,112(%esp)
+ movl %ebp,116(%esp)
+ movl 240(%edx),%ecx
+ movl %edx,%ebp
+ movl %ecx,%ebx
+ movdqa %xmm2,%xmm1
+ pxor %xmm0,%xmm0
+ movdqa 96(%esp),%xmm3
+ pcmpgtd %xmm1,%xmm0
+ andl $-16,%eax
+ subl $96,%eax
+ jc .L058xts_dec_short
+ shll $4,%ecx
+ movl $16,%ebx
+ subl %ecx,%ebx
+ leal 32(%edx,%ecx,1),%edx
+ jmp .L059xts_dec_loop6
+.align 16
+.L059xts_dec_loop6:
+ pshufd $19,%xmm0,%xmm2
+ pxor %xmm0,%xmm0
+ movdqa %xmm1,(%esp)
+ paddq %xmm1,%xmm1
+ pand %xmm3,%xmm2
+ pcmpgtd %xmm1,%xmm0
+ pxor %xmm2,%xmm1
+ pshufd $19,%xmm0,%xmm2
+ pxor %xmm0,%xmm0
+ movdqa %xmm1,16(%esp)
+ paddq %xmm1,%xmm1
+ pand %xmm3,%xmm2
+ pcmpgtd %xmm1,%xmm0
+ pxor %xmm2,%xmm1
+ pshufd $19,%xmm0,%xmm2
+ pxor %xmm0,%xmm0
+ movdqa %xmm1,32(%esp)
+ paddq %xmm1,%xmm1
+ pand %xmm3,%xmm2
+ pcmpgtd %xmm1,%xmm0
+ pxor %xmm2,%xmm1
+ pshufd $19,%xmm0,%xmm2
+ pxor %xmm0,%xmm0
+ movdqa %xmm1,48(%esp)
+ paddq %xmm1,%xmm1
+ pand %xmm3,%xmm2
+ pcmpgtd %xmm1,%xmm0
+ pxor %xmm2,%xmm1
+ pshufd $19,%xmm0,%xmm7
+ movdqa %xmm1,64(%esp)
+ paddq %xmm1,%xmm1
+ movups (%ebp),%xmm0
+ pand %xmm3,%xmm7
+ movups (%esi),%xmm2
+ pxor %xmm1,%xmm7
+ movl %ebx,%ecx
+ movdqu 16(%esi),%xmm3
+ xorps %xmm0,%xmm2
+ movdqu 32(%esi),%xmm4
+ pxor %xmm0,%xmm3
+ movdqu 48(%esi),%xmm5
+ pxor %xmm0,%xmm4
+ movdqu 64(%esi),%xmm6
+ pxor %xmm0,%xmm5
+ movdqu 80(%esi),%xmm1
+ pxor %xmm0,%xmm6
+ leal 96(%esi),%esi
+ pxor (%esp),%xmm2
+ movdqa %xmm7,80(%esp)
+ pxor %xmm1,%xmm7
+ movups 16(%ebp),%xmm1
+ pxor 16(%esp),%xmm3
+ pxor 32(%esp),%xmm4
+.byte 102,15,56,222,209
+ pxor 48(%esp),%xmm5
+ pxor 64(%esp),%xmm6
+.byte 102,15,56,222,217
+ pxor %xmm0,%xmm7
+ movups 32(%ebp),%xmm0
+.byte 102,15,56,222,225
+.byte 102,15,56,222,233
+.byte 102,15,56,222,241
+.byte 102,15,56,222,249
+ call .L_aesni_decrypt6_enter
+ movdqa 80(%esp),%xmm1
+ pxor %xmm0,%xmm0
+ xorps (%esp),%xmm2
+ pcmpgtd %xmm1,%xmm0
+ xorps 16(%esp),%xmm3
+ movups %xmm2,(%edi)
+ xorps 32(%esp),%xmm4
+ movups %xmm3,16(%edi)
+ xorps 48(%esp),%xmm5
+ movups %xmm4,32(%edi)
+ xorps 64(%esp),%xmm6
+ movups %xmm5,48(%edi)
+ xorps %xmm1,%xmm7
+ movups %xmm6,64(%edi)
+ pshufd $19,%xmm0,%xmm2
+ movups %xmm7,80(%edi)
+ leal 96(%edi),%edi
+ movdqa 96(%esp),%xmm3
+ pxor %xmm0,%xmm0
+ paddq %xmm1,%xmm1
+ pand %xmm3,%xmm2
+ pcmpgtd %xmm1,%xmm0
+ pxor %xmm2,%xmm1
+ subl $96,%eax
+ jnc .L059xts_dec_loop6
+ movl 240(%ebp),%ecx
+ movl %ebp,%edx
+ movl %ecx,%ebx
+.L058xts_dec_short:
+ addl $96,%eax
+ jz .L060xts_dec_done6x
+ movdqa %xmm1,%xmm5
+ cmpl $32,%eax
+ jb .L061xts_dec_one
+ pshufd $19,%xmm0,%xmm2
+ pxor %xmm0,%xmm0
+ paddq %xmm1,%xmm1
+ pand %xmm3,%xmm2
+ pcmpgtd %xmm1,%xmm0
+ pxor %xmm2,%xmm1
+ je .L062xts_dec_two
+ pshufd $19,%xmm0,%xmm2
+ pxor %xmm0,%xmm0
+ movdqa %xmm1,%xmm6
+ paddq %xmm1,%xmm1
+ pand %xmm3,%xmm2
+ pcmpgtd %xmm1,%xmm0
+ pxor %xmm2,%xmm1
+ cmpl $64,%eax
+ jb .L063xts_dec_three
+ pshufd $19,%xmm0,%xmm2
+ pxor %xmm0,%xmm0
+ movdqa %xmm1,%xmm7
+ paddq %xmm1,%xmm1
+ pand %xmm3,%xmm2
+ pcmpgtd %xmm1,%xmm0
+ pxor %xmm2,%xmm1
+ movdqa %xmm5,(%esp)
+ movdqa %xmm6,16(%esp)
+ je .L064xts_dec_four
+ movdqa %xmm7,32(%esp)
+ pshufd $19,%xmm0,%xmm7
+ movdqa %xmm1,48(%esp)
+ paddq %xmm1,%xmm1
+ pand %xmm3,%xmm7
+ pxor %xmm1,%xmm7
+ movdqu (%esi),%xmm2
+ movdqu 16(%esi),%xmm3
+ movdqu 32(%esi),%xmm4
+ pxor (%esp),%xmm2
+ movdqu 48(%esi),%xmm5
+ pxor 16(%esp),%xmm3
+ movdqu 64(%esi),%xmm6
+ pxor 32(%esp),%xmm4
+ leal 80(%esi),%esi
+ pxor 48(%esp),%xmm5
+ movdqa %xmm7,64(%esp)
+ pxor %xmm7,%xmm6
+ call _aesni_decrypt6
+ movaps 64(%esp),%xmm1
+ xorps (%esp),%xmm2
+ xorps 16(%esp),%xmm3
+ xorps 32(%esp),%xmm4
+ movups %xmm2,(%edi)
+ xorps 48(%esp),%xmm5
+ movups %xmm3,16(%edi)
+ xorps %xmm1,%xmm6
+ movups %xmm4,32(%edi)
+ movups %xmm5,48(%edi)
+ movups %xmm6,64(%edi)
+ leal 80(%edi),%edi
+ jmp .L065xts_dec_done
+.align 16
+.L061xts_dec_one:
+ movups (%esi),%xmm2
+ leal 16(%esi),%esi
+ xorps %xmm5,%xmm2
+ movups (%edx),%xmm0
+ movups 16(%edx),%xmm1
+ leal 32(%edx),%edx
+ xorps %xmm0,%xmm2
+.L066dec1_loop_12:
+.byte 102,15,56,222,209
+ decl %ecx
+ movups (%edx),%xmm1
+ leal 16(%edx),%edx
+ jnz .L066dec1_loop_12
+.byte 102,15,56,223,209
+ xorps %xmm5,%xmm2
+ movups %xmm2,(%edi)
+ leal 16(%edi),%edi
+ movdqa %xmm5,%xmm1
+ jmp .L065xts_dec_done
+.align 16
+.L062xts_dec_two:
+ movaps %xmm1,%xmm6
+ movups (%esi),%xmm2
+ movups 16(%esi),%xmm3
+ leal 32(%esi),%esi
+ xorps %xmm5,%xmm2
+ xorps %xmm6,%xmm3
+ call _aesni_decrypt2
+ xorps %xmm5,%xmm2
+ xorps %xmm6,%xmm3
+ movups %xmm2,(%edi)
+ movups %xmm3,16(%edi)
+ leal 32(%edi),%edi
+ movdqa %xmm6,%xmm1
+ jmp .L065xts_dec_done
+.align 16
+.L063xts_dec_three:
+ movaps %xmm1,%xmm7
+ movups (%esi),%xmm2
+ movups 16(%esi),%xmm3
+ movups 32(%esi),%xmm4
+ leal 48(%esi),%esi
+ xorps %xmm5,%xmm2
+ xorps %xmm6,%xmm3
+ xorps %xmm7,%xmm4
+ call _aesni_decrypt3
+ xorps %xmm5,%xmm2
+ xorps %xmm6,%xmm3
+ xorps %xmm7,%xmm4
+ movups %xmm2,(%edi)
+ movups %xmm3,16(%edi)
+ movups %xmm4,32(%edi)
+ leal 48(%edi),%edi
+ movdqa %xmm7,%xmm1
+ jmp .L065xts_dec_done
+.align 16
+.L064xts_dec_four:
+ movaps %xmm1,%xmm6
+ movups (%esi),%xmm2
+ movups 16(%esi),%xmm3
+ movups 32(%esi),%xmm4
+ xorps (%esp),%xmm2
+ movups 48(%esi),%xmm5
+ leal 64(%esi),%esi
+ xorps 16(%esp),%xmm3
+ xorps %xmm7,%xmm4
+ xorps %xmm6,%xmm5
+ call _aesni_decrypt4
+ xorps (%esp),%xmm2
+ xorps 16(%esp),%xmm3
+ xorps %xmm7,%xmm4
+ movups %xmm2,(%edi)
+ xorps %xmm6,%xmm5
+ movups %xmm3,16(%edi)
+ movups %xmm4,32(%edi)
+ movups %xmm5,48(%edi)
+ leal 64(%edi),%edi
+ movdqa %xmm6,%xmm1
+ jmp .L065xts_dec_done
+.align 16
+.L060xts_dec_done6x:
+ movl 112(%esp),%eax
+ andl $15,%eax
+ jz .L067xts_dec_ret
+ movl %eax,112(%esp)
+ jmp .L068xts_dec_only_one_more
+.align 16
+.L065xts_dec_done:
+ movl 112(%esp),%eax
+ pxor %xmm0,%xmm0
+ andl $15,%eax
+ jz .L067xts_dec_ret
+ pcmpgtd %xmm1,%xmm0
+ movl %eax,112(%esp)
+ pshufd $19,%xmm0,%xmm2
+ pxor %xmm0,%xmm0
+ movdqa 96(%esp),%xmm3
+ paddq %xmm1,%xmm1
+ pand %xmm3,%xmm2
+ pcmpgtd %xmm1,%xmm0
+ pxor %xmm2,%xmm1
+.L068xts_dec_only_one_more:
+ pshufd $19,%xmm0,%xmm5
+ movdqa %xmm1,%xmm6
+ paddq %xmm1,%xmm1
+ pand %xmm3,%xmm5
+ pxor %xmm1,%xmm5
+ movl %ebp,%edx
+ movl %ebx,%ecx
+ movups (%esi),%xmm2
+ xorps %xmm5,%xmm2
+ movups (%edx),%xmm0
+ movups 16(%edx),%xmm1
+ leal 32(%edx),%edx
+ xorps %xmm0,%xmm2
+.L069dec1_loop_13:
+.byte 102,15,56,222,209
+ decl %ecx
+ movups (%edx),%xmm1
+ leal 16(%edx),%edx
+ jnz .L069dec1_loop_13
+.byte 102,15,56,223,209
+ xorps %xmm5,%xmm2
+ movups %xmm2,(%edi)
+.L070xts_dec_steal:
+ movzbl 16(%esi),%ecx
+ movzbl (%edi),%edx
+ leal 1(%esi),%esi
+ movb %cl,(%edi)
+ movb %dl,16(%edi)
+ leal 1(%edi),%edi
+ subl $1,%eax
+ jnz .L070xts_dec_steal
+ subl 112(%esp),%edi
+ movl %ebp,%edx
+ movl %ebx,%ecx
+ movups (%edi),%xmm2
+ xorps %xmm6,%xmm2
+ movups (%edx),%xmm0
+ movups 16(%edx),%xmm1
+ leal 32(%edx),%edx
+ xorps %xmm0,%xmm2
+.L071dec1_loop_14:
+.byte 102,15,56,222,209
+ decl %ecx
+ movups (%edx),%xmm1
+ leal 16(%edx),%edx
+ jnz .L071dec1_loop_14
+.byte 102,15,56,223,209
+ xorps %xmm6,%xmm2
+ movups %xmm2,(%edi)
+.L067xts_dec_ret:
+ movl 116(%esp),%esp
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.size aesni_xts_decrypt,.-.L_aesni_xts_decrypt_begin
+.globl aesni_cbc_encrypt
+.hidden aesni_cbc_encrypt
+.type aesni_cbc_encrypt,@function
+.align 16
+aesni_cbc_encrypt:
+.L_aesni_cbc_encrypt_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ movl 20(%esp),%esi
+ movl %esp,%ebx
+ movl 24(%esp),%edi
+ subl $24,%ebx
+ movl 28(%esp),%eax
+ andl $-16,%ebx
+ movl 32(%esp),%edx
+ movl 36(%esp),%ebp
+ testl %eax,%eax
+ jz .L072cbc_abort
+ cmpl $0,40(%esp)
+ xchgl %esp,%ebx
+ movups (%ebp),%xmm7
+ movl 240(%edx),%ecx
+ movl %edx,%ebp
+ movl %ebx,16(%esp)
+ movl %ecx,%ebx
+ je .L073cbc_decrypt
+ movaps %xmm7,%xmm2
+ cmpl $16,%eax
+ jb .L074cbc_enc_tail
+ subl $16,%eax
+ jmp .L075cbc_enc_loop
+.align 16
+.L075cbc_enc_loop:
+ movups (%esi),%xmm7
+ leal 16(%esi),%esi
+ movups (%edx),%xmm0
+ movups 16(%edx),%xmm1
+ xorps %xmm0,%xmm7
+ leal 32(%edx),%edx
+ xorps %xmm7,%xmm2
+.L076enc1_loop_15:
+.byte 102,15,56,220,209
+ decl %ecx
+ movups (%edx),%xmm1
+ leal 16(%edx),%edx
+ jnz .L076enc1_loop_15
+.byte 102,15,56,221,209
+ movl %ebx,%ecx
+ movl %ebp,%edx
+ movups %xmm2,(%edi)
+ leal 16(%edi),%edi
+ subl $16,%eax
+ jnc .L075cbc_enc_loop
+ addl $16,%eax
+ jnz .L074cbc_enc_tail
+ movaps %xmm2,%xmm7
+ jmp .L077cbc_ret
+.L074cbc_enc_tail:
+ movl %eax,%ecx
+.long 2767451785
+ movl $16,%ecx
+ subl %eax,%ecx
+ xorl %eax,%eax
+.long 2868115081
+ leal -16(%edi),%edi
+ movl %ebx,%ecx
+ movl %edi,%esi
+ movl %ebp,%edx
+ jmp .L075cbc_enc_loop
+.align 16
+.L073cbc_decrypt:
+ cmpl $80,%eax
+ jbe .L078cbc_dec_tail
+ movaps %xmm7,(%esp)
+ subl $80,%eax
+ jmp .L079cbc_dec_loop6_enter
+.align 16
+.L080cbc_dec_loop6:
+ movaps %xmm0,(%esp)
+ movups %xmm7,(%edi)
+ leal 16(%edi),%edi
+.L079cbc_dec_loop6_enter:
+ movdqu (%esi),%xmm2
+ movdqu 16(%esi),%xmm3
+ movdqu 32(%esi),%xmm4
+ movdqu 48(%esi),%xmm5
+ movdqu 64(%esi),%xmm6
+ movdqu 80(%esi),%xmm7
+ call _aesni_decrypt6
+ movups (%esi),%xmm1
+ movups 16(%esi),%xmm0
+ xorps (%esp),%xmm2
+ xorps %xmm1,%xmm3
+ movups 32(%esi),%xmm1
+ xorps %xmm0,%xmm4
+ movups 48(%esi),%xmm0
+ xorps %xmm1,%xmm5
+ movups 64(%esi),%xmm1
+ xorps %xmm0,%xmm6
+ movups 80(%esi),%xmm0
+ xorps %xmm1,%xmm7
+ movups %xmm2,(%edi)
+ movups %xmm3,16(%edi)
+ leal 96(%esi),%esi
+ movups %xmm4,32(%edi)
+ movl %ebx,%ecx
+ movups %xmm5,48(%edi)
+ movl %ebp,%edx
+ movups %xmm6,64(%edi)
+ leal 80(%edi),%edi
+ subl $96,%eax
+ ja .L080cbc_dec_loop6
+ movaps %xmm7,%xmm2
+ movaps %xmm0,%xmm7
+ addl $80,%eax
+ jle .L081cbc_dec_tail_collected
+ movups %xmm2,(%edi)
+ leal 16(%edi),%edi
+.L078cbc_dec_tail:
+ movups (%esi),%xmm2
+ movaps %xmm2,%xmm6
+ cmpl $16,%eax
+ jbe .L082cbc_dec_one
+ movups 16(%esi),%xmm3
+ movaps %xmm3,%xmm5
+ cmpl $32,%eax
+ jbe .L083cbc_dec_two
+ movups 32(%esi),%xmm4
+ cmpl $48,%eax
+ jbe .L084cbc_dec_three
+ movups 48(%esi),%xmm5
+ cmpl $64,%eax
+ jbe .L085cbc_dec_four
+ movups 64(%esi),%xmm6
+ movaps %xmm7,(%esp)
+ movups (%esi),%xmm2
+ xorps %xmm7,%xmm7
+ call _aesni_decrypt6
+ movups (%esi),%xmm1
+ movups 16(%esi),%xmm0
+ xorps (%esp),%xmm2
+ xorps %xmm1,%xmm3
+ movups 32(%esi),%xmm1
+ xorps %xmm0,%xmm4
+ movups 48(%esi),%xmm0
+ xorps %xmm1,%xmm5
+ movups 64(%esi),%xmm7
+ xorps %xmm0,%xmm6
+ movups %xmm2,(%edi)
+ movups %xmm3,16(%edi)
+ movups %xmm4,32(%edi)
+ movups %xmm5,48(%edi)
+ leal 64(%edi),%edi
+ movaps %xmm6,%xmm2
+ subl $80,%eax
+ jmp .L081cbc_dec_tail_collected
+.align 16
+.L082cbc_dec_one:
+ movups (%edx),%xmm0
+ movups 16(%edx),%xmm1
+ leal 32(%edx),%edx
+ xorps %xmm0,%xmm2
+.L086dec1_loop_16:
+.byte 102,15,56,222,209
+ decl %ecx
+ movups (%edx),%xmm1
+ leal 16(%edx),%edx
+ jnz .L086dec1_loop_16
+.byte 102,15,56,223,209
+ xorps %xmm7,%xmm2
+ movaps %xmm6,%xmm7
+ subl $16,%eax
+ jmp .L081cbc_dec_tail_collected
+.align 16
+.L083cbc_dec_two:
+ call _aesni_decrypt2
+ xorps %xmm7,%xmm2
+ xorps %xmm6,%xmm3
+ movups %xmm2,(%edi)
+ movaps %xmm3,%xmm2
+ leal 16(%edi),%edi
+ movaps %xmm5,%xmm7
+ subl $32,%eax
+ jmp .L081cbc_dec_tail_collected
+.align 16
+.L084cbc_dec_three:
+ call _aesni_decrypt3
+ xorps %xmm7,%xmm2
+ xorps %xmm6,%xmm3
+ xorps %xmm5,%xmm4
+ movups %xmm2,(%edi)
+ movaps %xmm4,%xmm2
+ movups %xmm3,16(%edi)
+ leal 32(%edi),%edi
+ movups 32(%esi),%xmm7
+ subl $48,%eax
+ jmp .L081cbc_dec_tail_collected
+.align 16
+.L085cbc_dec_four:
+ call _aesni_decrypt4
+ movups 16(%esi),%xmm1
+ movups 32(%esi),%xmm0
+ xorps %xmm7,%xmm2
+ movups 48(%esi),%xmm7
+ xorps %xmm6,%xmm3
+ movups %xmm2,(%edi)
+ xorps %xmm1,%xmm4
+ movups %xmm3,16(%edi)
+ xorps %xmm0,%xmm5
+ movups %xmm4,32(%edi)
+ leal 48(%edi),%edi
+ movaps %xmm5,%xmm2
+ subl $64,%eax
+.L081cbc_dec_tail_collected:
+ andl $15,%eax
+ jnz .L087cbc_dec_tail_partial
+ movups %xmm2,(%edi)
+ jmp .L077cbc_ret
+.align 16
+.L087cbc_dec_tail_partial:
+ movaps %xmm2,(%esp)
+ movl $16,%ecx
+ movl %esp,%esi
+ subl %eax,%ecx
+.long 2767451785
+.L077cbc_ret:
+ movl 16(%esp),%esp
+ movl 36(%esp),%ebp
+ movups %xmm7,(%ebp)
+.L072cbc_abort:
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.size aesni_cbc_encrypt,.-.L_aesni_cbc_encrypt_begin
+.hidden _aesni_set_encrypt_key
+.type _aesni_set_encrypt_key,@function
+.align 16
+_aesni_set_encrypt_key:
+ testl %eax,%eax
+ jz .L088bad_pointer
+ testl %edx,%edx
+ jz .L088bad_pointer
+ movups (%eax),%xmm0
+ xorps %xmm4,%xmm4
+ leal 16(%edx),%edx
+ cmpl $256,%ecx
+ je .L08914rounds
+ cmpl $192,%ecx
+ je .L09012rounds
+ cmpl $128,%ecx
+ jne .L091bad_keybits
+.align 16
+.L09210rounds:
+ movl $9,%ecx
+ movups %xmm0,-16(%edx)
+.byte 102,15,58,223,200,1
+ call .L093key_128_cold
+.byte 102,15,58,223,200,2
+ call .L094key_128
+.byte 102,15,58,223,200,4
+ call .L094key_128
+.byte 102,15,58,223,200,8
+ call .L094key_128
+.byte 102,15,58,223,200,16
+ call .L094key_128
+.byte 102,15,58,223,200,32
+ call .L094key_128
+.byte 102,15,58,223,200,64
+ call .L094key_128
+.byte 102,15,58,223,200,128
+ call .L094key_128
+.byte 102,15,58,223,200,27
+ call .L094key_128
+.byte 102,15,58,223,200,54
+ call .L094key_128
+ movups %xmm0,(%edx)
+ movl %ecx,80(%edx)
+ xorl %eax,%eax
+ ret
+.align 16
+.L094key_128:
+ movups %xmm0,(%edx)
+ leal 16(%edx),%edx
+.L093key_128_cold:
+ shufps $16,%xmm0,%xmm4
+ xorps %xmm4,%xmm0
+ shufps $140,%xmm0,%xmm4
+ xorps %xmm4,%xmm0
+ shufps $255,%xmm1,%xmm1
+ xorps %xmm1,%xmm0
+ ret
+.align 16
+.L09012rounds:
+ movq 16(%eax),%xmm2
+ movl $11,%ecx
+ movups %xmm0,-16(%edx)
+.byte 102,15,58,223,202,1
+ call .L095key_192a_cold
+.byte 102,15,58,223,202,2
+ call .L096key_192b
+.byte 102,15,58,223,202,4
+ call .L097key_192a
+.byte 102,15,58,223,202,8
+ call .L096key_192b
+.byte 102,15,58,223,202,16
+ call .L097key_192a
+.byte 102,15,58,223,202,32
+ call .L096key_192b
+.byte 102,15,58,223,202,64
+ call .L097key_192a
+.byte 102,15,58,223,202,128
+ call .L096key_192b
+ movups %xmm0,(%edx)
+ movl %ecx,48(%edx)
+ xorl %eax,%eax
+ ret
+.align 16
+.L097key_192a:
+ movups %xmm0,(%edx)
+ leal 16(%edx),%edx
+.align 16
+.L095key_192a_cold:
+ movaps %xmm2,%xmm5
+.L098key_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
+ ret
+.align 16
+.L096key_192b:
+ movaps %xmm0,%xmm3
+ shufps $68,%xmm0,%xmm5
+ movups %xmm5,(%edx)
+ shufps $78,%xmm2,%xmm3
+ movups %xmm3,16(%edx)
+ leal 32(%edx),%edx
+ jmp .L098key_192b_warm
+.align 16
+.L08914rounds:
+ movups 16(%eax),%xmm2
+ movl $13,%ecx
+ leal 16(%edx),%edx
+ movups %xmm0,-32(%edx)
+ movups %xmm2,-16(%edx)
+.byte 102,15,58,223,202,1
+ call .L099key_256a_cold
+.byte 102,15,58,223,200,1
+ call .L100key_256b
+.byte 102,15,58,223,202,2
+ call .L101key_256a
+.byte 102,15,58,223,200,2
+ call .L100key_256b
+.byte 102,15,58,223,202,4
+ call .L101key_256a
+.byte 102,15,58,223,200,4
+ call .L100key_256b
+.byte 102,15,58,223,202,8
+ call .L101key_256a
+.byte 102,15,58,223,200,8
+ call .L100key_256b
+.byte 102,15,58,223,202,16
+ call .L101key_256a
+.byte 102,15,58,223,200,16
+ call .L100key_256b
+.byte 102,15,58,223,202,32
+ call .L101key_256a
+.byte 102,15,58,223,200,32
+ call .L100key_256b
+.byte 102,15,58,223,202,64
+ call .L101key_256a
+ movups %xmm0,(%edx)
+ movl %ecx,16(%edx)
+ xorl %eax,%eax
+ ret
+.align 16
+.L101key_256a:
+ movups %xmm2,(%edx)
+ leal 16(%edx),%edx
+.L099key_256a_cold:
+ shufps $16,%xmm0,%xmm4
+ xorps %xmm4,%xmm0
+ shufps $140,%xmm0,%xmm4
+ xorps %xmm4,%xmm0
+ shufps $255,%xmm1,%xmm1
+ xorps %xmm1,%xmm0
+ ret
+.align 16
+.L100key_256b:
+ movups %xmm0,(%edx)
+ leal 16(%edx),%edx
+ shufps $16,%xmm2,%xmm4
+ xorps %xmm4,%xmm2
+ shufps $140,%xmm2,%xmm4
+ xorps %xmm4,%xmm2
+ shufps $170,%xmm1,%xmm1
+ xorps %xmm1,%xmm2
+ ret
+.align 4
+.L088bad_pointer:
+ movl $-1,%eax
+ ret
+.align 4
+.L091bad_keybits:
+ movl $-2,%eax
+ ret
+.size _aesni_set_encrypt_key,.-_aesni_set_encrypt_key
+.globl aesni_set_encrypt_key
+.hidden aesni_set_encrypt_key
+.type aesni_set_encrypt_key,@function
+.align 16
+aesni_set_encrypt_key:
+.L_aesni_set_encrypt_key_begin:
+ movl 4(%esp),%eax
+ movl 8(%esp),%ecx
+ movl 12(%esp),%edx
+ call _aesni_set_encrypt_key
+ ret
+.size aesni_set_encrypt_key,.-.L_aesni_set_encrypt_key_begin
+.globl aesni_set_decrypt_key
+.hidden aesni_set_decrypt_key
+.type aesni_set_decrypt_key,@function
+.align 16
+aesni_set_decrypt_key:
+.L_aesni_set_decrypt_key_begin:
+ movl 4(%esp),%eax
+ movl 8(%esp),%ecx
+ movl 12(%esp),%edx
+ call _aesni_set_encrypt_key
+ movl 12(%esp),%edx
+ shll $4,%ecx
+ testl %eax,%eax
+ jnz .L102dec_key_ret
+ leal 16(%edx,%ecx,1),%eax
+ movups (%edx),%xmm0
+ movups (%eax),%xmm1
+ movups %xmm0,(%eax)
+ movups %xmm1,(%edx)
+ leal 16(%edx),%edx
+ leal -16(%eax),%eax
+.L103dec_key_inverse:
+ movups (%edx),%xmm0
+ movups (%eax),%xmm1
+.byte 102,15,56,219,192
+.byte 102,15,56,219,201
+ leal 16(%edx),%edx
+ leal -16(%eax),%eax
+ movups %xmm0,16(%eax)
+ movups %xmm1,-16(%edx)
+ cmpl %edx,%eax
+ ja .L103dec_key_inverse
+ movups (%edx),%xmm0
+.byte 102,15,56,219,192
+ movups %xmm0,(%edx)
+ xorl %eax,%eax
+.L102dec_key_ret:
+ ret
+.size aesni_set_decrypt_key,.-.L_aesni_set_decrypt_key_begin
+.byte 65,69,83,32,102,111,114,32,73,110,116,101,108,32,65,69
+.byte 83,45,78,73,44,32,67,82,89,80,84,79,71,65,77,83
+.byte 32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115
+.byte 115,108,46,111,114,103,62,0
+#endif
diff --git a/linux-x86/crypto/aes/vpaes-x86.S b/linux-x86/crypto/aes/vpaes-x86.S
new file mode 100644
index 0000000..9aede39
--- /dev/null
+++ b/linux-x86/crypto/aes/vpaes-x86.S
@@ -0,0 +1,676 @@
+#if defined(__i386__)
+.file "vpaes-x86.S"
+.text
+.align 64
+.L_vpaes_consts:
+.long 218628480,235210255,168496130,67568393
+.long 252381056,17041926,33884169,51187212
+.long 252645135,252645135,252645135,252645135
+.long 1512730624,3266504856,1377990664,3401244816
+.long 830229760,1275146365,2969422977,3447763452
+.long 3411033600,2979783055,338359620,2782886510
+.long 4209124096,907596821,221174255,1006095553
+.long 191964160,3799684038,3164090317,1589111125
+.long 182528256,1777043520,2877432650,3265356744
+.long 1874708224,3503451415,3305285752,363511674
+.long 1606117888,3487855781,1093350906,2384367825
+.long 197121,67569157,134941193,202313229
+.long 67569157,134941193,202313229,197121
+.long 134941193,202313229,197121,67569157
+.long 202313229,197121,67569157,134941193
+.long 33619971,100992007,168364043,235736079
+.long 235736079,33619971,100992007,168364043
+.long 168364043,235736079,33619971,100992007
+.long 100992007,168364043,235736079,33619971
+.long 50462976,117835012,185207048,252579084
+.long 252314880,51251460,117574920,184942860
+.long 184682752,252054788,50987272,118359308
+.long 118099200,185467140,251790600,50727180
+.long 2946363062,528716217,1300004225,1881839624
+.long 1532713819,1532713819,1532713819,1532713819
+.long 3602276352,4288629033,3737020424,4153884961
+.long 1354558464,32357713,2958822624,3775749553
+.long 1201988352,132424512,1572796698,503232858
+.long 2213177600,1597421020,4103937655,675398315
+.long 2749646592,4273543773,1511898873,121693092
+.long 3040248576,1103263732,2871565598,1608280554
+.long 2236667136,2588920351,482954393,64377734
+.long 3069987328,291237287,2117370568,3650299247
+.long 533321216,3573750986,2572112006,1401264716
+.long 1339849704,2721158661,548607111,3445553514
+.long 2128193280,3054596040,2183486460,1257083700
+.long 655635200,1165381986,3923443150,2344132524
+.long 190078720,256924420,290342170,357187870
+.long 1610966272,2263057382,4103205268,309794674
+.long 2592527872,2233205587,1335446729,3402964816
+.long 3973531904,3225098121,3002836325,1918774430
+.long 3870401024,2102906079,2284471353,4117666579
+.long 617007872,1021508343,366931923,691083277
+.long 2528395776,3491914898,2968704004,1613121270
+.long 3445188352,3247741094,844474987,4093578302
+.long 651481088,1190302358,1689581232,574775300
+.long 4289380608,206939853,2555985458,2489840491
+.long 2130264064,327674451,3566485037,3349835193
+.long 2470714624,316102159,3636825756,3393945945
+.byte 86,101,99,116,111,114,32,80,101,114,109,117,116,97,116,105
+.byte 111,110,32,65,69,83,32,102,111,114,32,120,56,54,47,83
+.byte 83,83,69,51,44,32,77,105,107,101,32,72,97,109,98,117
+.byte 114,103,32,40,83,116,97,110,102,111,114,100,32,85,110,105
+.byte 118,101,114,115,105,116,121,41,0
+.align 64
+.hidden _vpaes_preheat
+.type _vpaes_preheat,@function
+.align 16
+_vpaes_preheat:
+ addl (%esp),%ebp
+ movdqa -48(%ebp),%xmm7
+ movdqa -16(%ebp),%xmm6
+ ret
+.size _vpaes_preheat,.-_vpaes_preheat
+.hidden _vpaes_encrypt_core
+.type _vpaes_encrypt_core,@function
+.align 16
+_vpaes_encrypt_core:
+ movl $16,%ecx
+ movl 240(%edx),%eax
+ movdqa %xmm6,%xmm1
+ movdqa (%ebp),%xmm2
+ pandn %xmm0,%xmm1
+ pand %xmm6,%xmm0
+ movdqu (%edx),%xmm5
+.byte 102,15,56,0,208
+ movdqa 16(%ebp),%xmm0
+ pxor %xmm5,%xmm2
+ psrld $4,%xmm1
+ addl $16,%edx
+.byte 102,15,56,0,193
+ leal 192(%ebp),%ebx
+ pxor %xmm2,%xmm0
+ jmp .L000enc_entry
+.align 16
+.L001enc_loop:
+ movdqa 32(%ebp),%xmm4
+ movdqa 48(%ebp),%xmm0
+.byte 102,15,56,0,226
+.byte 102,15,56,0,195
+ pxor %xmm5,%xmm4
+ movdqa 64(%ebp),%xmm5
+ pxor %xmm4,%xmm0
+ movdqa -64(%ebx,%ecx,1),%xmm1
+.byte 102,15,56,0,234
+ movdqa 80(%ebp),%xmm2
+ movdqa (%ebx,%ecx,1),%xmm4
+.byte 102,15,56,0,211
+ movdqa %xmm0,%xmm3
+ pxor %xmm5,%xmm2
+.byte 102,15,56,0,193
+ addl $16,%edx
+ pxor %xmm2,%xmm0
+.byte 102,15,56,0,220
+ addl $16,%ecx
+ pxor %xmm0,%xmm3
+.byte 102,15,56,0,193
+ andl $48,%ecx
+ subl $1,%eax
+ pxor %xmm3,%xmm0
+.L000enc_entry:
+ movdqa %xmm6,%xmm1
+ movdqa -32(%ebp),%xmm5
+ pandn %xmm0,%xmm1
+ psrld $4,%xmm1
+ pand %xmm6,%xmm0
+.byte 102,15,56,0,232
+ movdqa %xmm7,%xmm3
+ pxor %xmm1,%xmm0
+.byte 102,15,56,0,217
+ movdqa %xmm7,%xmm4
+ pxor %xmm5,%xmm3
+.byte 102,15,56,0,224
+ movdqa %xmm7,%xmm2
+ pxor %xmm5,%xmm4
+.byte 102,15,56,0,211
+ movdqa %xmm7,%xmm3
+ pxor %xmm0,%xmm2
+.byte 102,15,56,0,220
+ movdqu (%edx),%xmm5
+ pxor %xmm1,%xmm3
+ jnz .L001enc_loop
+ movdqa 96(%ebp),%xmm4
+ movdqa 112(%ebp),%xmm0
+.byte 102,15,56,0,226
+ pxor %xmm5,%xmm4
+.byte 102,15,56,0,195
+ movdqa 64(%ebx,%ecx,1),%xmm1
+ pxor %xmm4,%xmm0
+.byte 102,15,56,0,193
+ ret
+.size _vpaes_encrypt_core,.-_vpaes_encrypt_core
+.hidden _vpaes_decrypt_core
+.type _vpaes_decrypt_core,@function
+.align 16
+_vpaes_decrypt_core:
+ leal 608(%ebp),%ebx
+ movl 240(%edx),%eax
+ movdqa %xmm6,%xmm1
+ movdqa -64(%ebx),%xmm2
+ pandn %xmm0,%xmm1
+ movl %eax,%ecx
+ psrld $4,%xmm1
+ movdqu (%edx),%xmm5
+ shll $4,%ecx
+ pand %xmm6,%xmm0
+.byte 102,15,56,0,208
+ movdqa -48(%ebx),%xmm0
+ xorl $48,%ecx
+.byte 102,15,56,0,193
+ andl $48,%ecx
+ pxor %xmm5,%xmm2
+ movdqa 176(%ebp),%xmm5
+ pxor %xmm2,%xmm0
+ addl $16,%edx
+ leal -352(%ebx,%ecx,1),%ecx
+ jmp .L002dec_entry
+.align 16
+.L003dec_loop:
+ movdqa -32(%ebx),%xmm4
+ movdqa -16(%ebx),%xmm1
+.byte 102,15,56,0,226
+.byte 102,15,56,0,203
+ pxor %xmm4,%xmm0
+ movdqa (%ebx),%xmm4
+ pxor %xmm1,%xmm0
+ movdqa 16(%ebx),%xmm1
+.byte 102,15,56,0,226
+.byte 102,15,56,0,197
+.byte 102,15,56,0,203
+ pxor %xmm4,%xmm0
+ movdqa 32(%ebx),%xmm4
+ pxor %xmm1,%xmm0
+ movdqa 48(%ebx),%xmm1
+.byte 102,15,56,0,226
+.byte 102,15,56,0,197
+.byte 102,15,56,0,203
+ pxor %xmm4,%xmm0
+ movdqa 64(%ebx),%xmm4
+ pxor %xmm1,%xmm0
+ movdqa 80(%ebx),%xmm1
+.byte 102,15,56,0,226
+.byte 102,15,56,0,197
+.byte 102,15,56,0,203
+ pxor %xmm4,%xmm0
+ addl $16,%edx
+.byte 102,15,58,15,237,12
+ pxor %xmm1,%xmm0
+ subl $1,%eax
+.L002dec_entry:
+ movdqa %xmm6,%xmm1
+ movdqa -32(%ebp),%xmm2
+ pandn %xmm0,%xmm1
+ pand %xmm6,%xmm0
+ psrld $4,%xmm1
+.byte 102,15,56,0,208
+ movdqa %xmm7,%xmm3
+ pxor %xmm1,%xmm0
+.byte 102,15,56,0,217
+ movdqa %xmm7,%xmm4
+ pxor %xmm2,%xmm3
+.byte 102,15,56,0,224
+ pxor %xmm2,%xmm4
+ movdqa %xmm7,%xmm2
+.byte 102,15,56,0,211
+ movdqa %xmm7,%xmm3
+ pxor %xmm0,%xmm2
+.byte 102,15,56,0,220
+ movdqu (%edx),%xmm0
+ pxor %xmm1,%xmm3
+ jnz .L003dec_loop
+ movdqa 96(%ebx),%xmm4
+.byte 102,15,56,0,226
+ pxor %xmm0,%xmm4
+ movdqa 112(%ebx),%xmm0
+ movdqa (%ecx),%xmm2
+.byte 102,15,56,0,195
+ pxor %xmm4,%xmm0
+.byte 102,15,56,0,194
+ ret
+.size _vpaes_decrypt_core,.-_vpaes_decrypt_core
+.hidden _vpaes_schedule_core
+.type _vpaes_schedule_core,@function
+.align 16
+_vpaes_schedule_core:
+ addl (%esp),%ebp
+ movdqu (%esi),%xmm0
+ movdqa 320(%ebp),%xmm2
+ movdqa %xmm0,%xmm3
+ leal (%ebp),%ebx
+ movdqa %xmm2,4(%esp)
+ call _vpaes_schedule_transform
+ movdqa %xmm0,%xmm7
+ testl %edi,%edi
+ jnz .L004schedule_am_decrypting
+ movdqu %xmm0,(%edx)
+ jmp .L005schedule_go
+.L004schedule_am_decrypting:
+ movdqa 256(%ebp,%ecx,1),%xmm1
+.byte 102,15,56,0,217
+ movdqu %xmm3,(%edx)
+ xorl $48,%ecx
+.L005schedule_go:
+ cmpl $192,%eax
+ ja .L006schedule_256
+ je .L007schedule_192
+.L008schedule_128:
+ movl $10,%eax
+.L009loop_schedule_128:
+ call _vpaes_schedule_round
+ decl %eax
+ jz .L010schedule_mangle_last
+ call _vpaes_schedule_mangle
+ jmp .L009loop_schedule_128
+.align 16
+.L007schedule_192:
+ movdqu 8(%esi),%xmm0
+ call _vpaes_schedule_transform
+ movdqa %xmm0,%xmm6
+ pxor %xmm4,%xmm4
+ movhlps %xmm4,%xmm6
+ movl $4,%eax
+.L011loop_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
+ decl %eax
+ jz .L010schedule_mangle_last
+ call _vpaes_schedule_mangle
+ call _vpaes_schedule_192_smear
+ jmp .L011loop_schedule_192
+.align 16
+.L006schedule_256:
+ movdqu 16(%esi),%xmm0
+ call _vpaes_schedule_transform
+ movl $7,%eax
+.L012loop_schedule_256:
+ call _vpaes_schedule_mangle
+ movdqa %xmm0,%xmm6
+ call _vpaes_schedule_round
+ decl %eax
+ jz .L010schedule_mangle_last
+ call _vpaes_schedule_mangle
+ pshufd $255,%xmm0,%xmm0
+ movdqa %xmm7,20(%esp)
+ movdqa %xmm6,%xmm7
+ call .L_vpaes_schedule_low_round
+ movdqa 20(%esp),%xmm7
+ jmp .L012loop_schedule_256
+.align 16
+.L010schedule_mangle_last:
+ leal 384(%ebp),%ebx
+ testl %edi,%edi
+ jnz .L013schedule_mangle_last_dec
+ movdqa 256(%ebp,%ecx,1),%xmm1
+.byte 102,15,56,0,193
+ leal 352(%ebp),%ebx
+ addl $32,%edx
+.L013schedule_mangle_last_dec:
+ addl $-16,%edx
+ pxor 336(%ebp),%xmm0
+ call _vpaes_schedule_transform
+ movdqu %xmm0,(%edx)
+ pxor %xmm0,%xmm0
+ pxor %xmm1,%xmm1
+ pxor %xmm2,%xmm2
+ pxor %xmm3,%xmm3
+ pxor %xmm4,%xmm4
+ pxor %xmm5,%xmm5
+ pxor %xmm6,%xmm6
+ pxor %xmm7,%xmm7
+ ret
+.size _vpaes_schedule_core,.-_vpaes_schedule_core
+.hidden _vpaes_schedule_192_smear
+.type _vpaes_schedule_192_smear,@function
+.align 16
+_vpaes_schedule_192_smear:
+ pshufd $128,%xmm6,%xmm1
+ pshufd $254,%xmm7,%xmm0
+ pxor %xmm1,%xmm6
+ pxor %xmm1,%xmm1
+ pxor %xmm0,%xmm6
+ movdqa %xmm6,%xmm0
+ movhlps %xmm1,%xmm6
+ ret
+.size _vpaes_schedule_192_smear,.-_vpaes_schedule_192_smear
+.hidden _vpaes_schedule_round
+.type _vpaes_schedule_round,@function
+.align 16
+_vpaes_schedule_round:
+ movdqa 8(%esp),%xmm2
+ pxor %xmm1,%xmm1
+.byte 102,15,58,15,202,15
+.byte 102,15,58,15,210,15
+ pxor %xmm1,%xmm7
+ pshufd $255,%xmm0,%xmm0
+.byte 102,15,58,15,192,1
+ movdqa %xmm2,8(%esp)
+.L_vpaes_schedule_low_round:
+ movdqa %xmm7,%xmm1
+ pslldq $4,%xmm7
+ pxor %xmm1,%xmm7
+ movdqa %xmm7,%xmm1
+ pslldq $8,%xmm7
+ pxor %xmm1,%xmm7
+ pxor 336(%ebp),%xmm7
+ movdqa -16(%ebp),%xmm4
+ movdqa -48(%ebp),%xmm5
+ movdqa %xmm4,%xmm1
+ pandn %xmm0,%xmm1
+ psrld $4,%xmm1
+ pand %xmm4,%xmm0
+ movdqa -32(%ebp),%xmm2
+.byte 102,15,56,0,208
+ pxor %xmm1,%xmm0
+ movdqa %xmm5,%xmm3
+.byte 102,15,56,0,217
+ pxor %xmm2,%xmm3
+ movdqa %xmm5,%xmm4
+.byte 102,15,56,0,224
+ pxor %xmm2,%xmm4
+ movdqa %xmm5,%xmm2
+.byte 102,15,56,0,211
+ pxor %xmm0,%xmm2
+ movdqa %xmm5,%xmm3
+.byte 102,15,56,0,220
+ pxor %xmm1,%xmm3
+ movdqa 32(%ebp),%xmm4
+.byte 102,15,56,0,226
+ movdqa 48(%ebp),%xmm0
+.byte 102,15,56,0,195
+ pxor %xmm4,%xmm0
+ pxor %xmm7,%xmm0
+ movdqa %xmm0,%xmm7
+ ret
+.size _vpaes_schedule_round,.-_vpaes_schedule_round
+.hidden _vpaes_schedule_transform
+.type _vpaes_schedule_transform,@function
+.align 16
+_vpaes_schedule_transform:
+ movdqa -16(%ebp),%xmm2
+ movdqa %xmm2,%xmm1
+ pandn %xmm0,%xmm1
+ psrld $4,%xmm1
+ pand %xmm2,%xmm0
+ movdqa (%ebx),%xmm2
+.byte 102,15,56,0,208
+ movdqa 16(%ebx),%xmm0
+.byte 102,15,56,0,193
+ pxor %xmm2,%xmm0
+ ret
+.size _vpaes_schedule_transform,.-_vpaes_schedule_transform
+.hidden _vpaes_schedule_mangle
+.type _vpaes_schedule_mangle,@function
+.align 16
+_vpaes_schedule_mangle:
+ movdqa %xmm0,%xmm4
+ movdqa 128(%ebp),%xmm5
+ testl %edi,%edi
+ jnz .L014schedule_mangle_dec
+ addl $16,%edx
+ pxor 336(%ebp),%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 .L015schedule_mangle_both
+.align 16
+.L014schedule_mangle_dec:
+ movdqa -16(%ebp),%xmm2
+ leal 416(%ebp),%esi
+ movdqa %xmm2,%xmm1
+ pandn %xmm4,%xmm1
+ psrld $4,%xmm1
+ pand %xmm2,%xmm4
+ movdqa (%esi),%xmm2
+.byte 102,15,56,0,212
+ movdqa 16(%esi),%xmm3
+.byte 102,15,56,0,217
+ pxor %xmm2,%xmm3
+.byte 102,15,56,0,221
+ movdqa 32(%esi),%xmm2
+.byte 102,15,56,0,212
+ pxor %xmm3,%xmm2
+ movdqa 48(%esi),%xmm3
+.byte 102,15,56,0,217
+ pxor %xmm2,%xmm3
+.byte 102,15,56,0,221
+ movdqa 64(%esi),%xmm2
+.byte 102,15,56,0,212
+ pxor %xmm3,%xmm2
+ movdqa 80(%esi),%xmm3
+.byte 102,15,56,0,217
+ pxor %xmm2,%xmm3
+.byte 102,15,56,0,221
+ movdqa 96(%esi),%xmm2
+.byte 102,15,56,0,212
+ pxor %xmm3,%xmm2
+ movdqa 112(%esi),%xmm3
+.byte 102,15,56,0,217
+ pxor %xmm2,%xmm3
+ addl $-16,%edx
+.L015schedule_mangle_both:
+ movdqa 256(%ebp,%ecx,1),%xmm1
+.byte 102,15,56,0,217
+ addl $-16,%ecx
+ andl $48,%ecx
+ movdqu %xmm3,(%edx)
+ ret
+.size _vpaes_schedule_mangle,.-_vpaes_schedule_mangle
+.globl vpaes_set_encrypt_key
+.hidden vpaes_set_encrypt_key
+.type vpaes_set_encrypt_key,@function
+.align 16
+vpaes_set_encrypt_key:
+.L_vpaes_set_encrypt_key_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ movl 20(%esp),%esi
+ leal -56(%esp),%ebx
+ movl 24(%esp),%eax
+ andl $-16,%ebx
+ movl 28(%esp),%edx
+ xchgl %esp,%ebx
+ movl %ebx,48(%esp)
+ movl %eax,%ebx
+ shrl $5,%ebx
+ addl $5,%ebx
+ movl %ebx,240(%edx)
+ movl $48,%ecx
+ movl $0,%edi
+ leal .L_vpaes_consts+0x30-.L016pic_point,%ebp
+ call _vpaes_schedule_core
+.L016pic_point:
+ movl 48(%esp),%esp
+ xorl %eax,%eax
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.size vpaes_set_encrypt_key,.-.L_vpaes_set_encrypt_key_begin
+.globl vpaes_set_decrypt_key
+.hidden vpaes_set_decrypt_key
+.type vpaes_set_decrypt_key,@function
+.align 16
+vpaes_set_decrypt_key:
+.L_vpaes_set_decrypt_key_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ movl 20(%esp),%esi
+ leal -56(%esp),%ebx
+ movl 24(%esp),%eax
+ andl $-16,%ebx
+ movl 28(%esp),%edx
+ xchgl %esp,%ebx
+ movl %ebx,48(%esp)
+ movl %eax,%ebx
+ shrl $5,%ebx
+ addl $5,%ebx
+ movl %ebx,240(%edx)
+ shll $4,%ebx
+ leal 16(%edx,%ebx,1),%edx
+ movl $1,%edi
+ movl %eax,%ecx
+ shrl $1,%ecx
+ andl $32,%ecx
+ xorl $32,%ecx
+ leal .L_vpaes_consts+0x30-.L017pic_point,%ebp
+ call _vpaes_schedule_core
+.L017pic_point:
+ movl 48(%esp),%esp
+ xorl %eax,%eax
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.size vpaes_set_decrypt_key,.-.L_vpaes_set_decrypt_key_begin
+.globl vpaes_encrypt
+.hidden vpaes_encrypt
+.type vpaes_encrypt,@function
+.align 16
+vpaes_encrypt:
+.L_vpaes_encrypt_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ leal .L_vpaes_consts+0x30-.L018pic_point,%ebp
+ call _vpaes_preheat
+.L018pic_point:
+ movl 20(%esp),%esi
+ leal -56(%esp),%ebx
+ movl 24(%esp),%edi
+ andl $-16,%ebx
+ movl 28(%esp),%edx
+ xchgl %esp,%ebx
+ movl %ebx,48(%esp)
+ movdqu (%esi),%xmm0
+ call _vpaes_encrypt_core
+ movdqu %xmm0,(%edi)
+ movl 48(%esp),%esp
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.size vpaes_encrypt,.-.L_vpaes_encrypt_begin
+.globl vpaes_decrypt
+.hidden vpaes_decrypt
+.type vpaes_decrypt,@function
+.align 16
+vpaes_decrypt:
+.L_vpaes_decrypt_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ leal .L_vpaes_consts+0x30-.L019pic_point,%ebp
+ call _vpaes_preheat
+.L019pic_point:
+ movl 20(%esp),%esi
+ leal -56(%esp),%ebx
+ movl 24(%esp),%edi
+ andl $-16,%ebx
+ movl 28(%esp),%edx
+ xchgl %esp,%ebx
+ movl %ebx,48(%esp)
+ movdqu (%esi),%xmm0
+ call _vpaes_decrypt_core
+ movdqu %xmm0,(%edi)
+ movl 48(%esp),%esp
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.size vpaes_decrypt,.-.L_vpaes_decrypt_begin
+.globl vpaes_cbc_encrypt
+.hidden vpaes_cbc_encrypt
+.type vpaes_cbc_encrypt,@function
+.align 16
+vpaes_cbc_encrypt:
+.L_vpaes_cbc_encrypt_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ movl 20(%esp),%esi
+ movl 24(%esp),%edi
+ movl 28(%esp),%eax
+ movl 32(%esp),%edx
+ subl $16,%eax
+ jc .L020cbc_abort
+ leal -56(%esp),%ebx
+ movl 36(%esp),%ebp
+ andl $-16,%ebx
+ movl 40(%esp),%ecx
+ xchgl %esp,%ebx
+ movdqu (%ebp),%xmm1
+ subl %esi,%edi
+ movl %ebx,48(%esp)
+ movl %edi,(%esp)
+ movl %edx,4(%esp)
+ movl %ebp,8(%esp)
+ movl %eax,%edi
+ leal .L_vpaes_consts+0x30-.L021pic_point,%ebp
+ call _vpaes_preheat
+.L021pic_point:
+ cmpl $0,%ecx
+ je .L022cbc_dec_loop
+ jmp .L023cbc_enc_loop
+.align 16
+.L023cbc_enc_loop:
+ movdqu (%esi),%xmm0
+ pxor %xmm1,%xmm0
+ call _vpaes_encrypt_core
+ movl (%esp),%ebx
+ movl 4(%esp),%edx
+ movdqa %xmm0,%xmm1
+ movdqu %xmm0,(%ebx,%esi,1)
+ leal 16(%esi),%esi
+ subl $16,%edi
+ jnc .L023cbc_enc_loop
+ jmp .L024cbc_done
+.align 16
+.L022cbc_dec_loop:
+ movdqu (%esi),%xmm0
+ movdqa %xmm1,16(%esp)
+ movdqa %xmm0,32(%esp)
+ call _vpaes_decrypt_core
+ movl (%esp),%ebx
+ movl 4(%esp),%edx
+ pxor 16(%esp),%xmm0
+ movdqa 32(%esp),%xmm1
+ movdqu %xmm0,(%ebx,%esi,1)
+ leal 16(%esi),%esi
+ subl $16,%edi
+ jnc .L022cbc_dec_loop
+.L024cbc_done:
+ movl 8(%esp),%ebx
+ movl 48(%esp),%esp
+ movdqu %xmm1,(%ebx)
+.L020cbc_abort:
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.size vpaes_cbc_encrypt,.-.L_vpaes_cbc_encrypt_begin
+#endif
diff --git a/linux-x86/crypto/bn/bn-586.S b/linux-x86/crypto/bn/bn-586.S
new file mode 100644
index 0000000..b953393
--- /dev/null
+++ b/linux-x86/crypto/bn/bn-586.S
@@ -0,0 +1,1393 @@
+#if defined(__i386__)
+.file "src/crypto/bn/asm/bn-586.S"
+.text
+.globl bn_mul_add_words
+.hidden bn_mul_add_words
+.type bn_mul_add_words,@function
+.align 16
+bn_mul_add_words:
+.L_bn_mul_add_words_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+
+ xorl %esi,%esi
+ movl 20(%esp),%edi
+ movl 28(%esp),%ecx
+ movl 24(%esp),%ebx
+ andl $4294967288,%ecx
+ movl 32(%esp),%ebp
+ pushl %ecx
+ jz .L000maw_finish
+.align 16
+.L001maw_loop:
+
+ movl (%ebx),%eax
+ mull %ebp
+ addl %esi,%eax
+ adcl $0,%edx
+ addl (%edi),%eax
+ adcl $0,%edx
+ movl %eax,(%edi)
+ movl %edx,%esi
+
+ movl 4(%ebx),%eax
+ mull %ebp
+ addl %esi,%eax
+ adcl $0,%edx
+ addl 4(%edi),%eax
+ adcl $0,%edx
+ movl %eax,4(%edi)
+ movl %edx,%esi
+
+ movl 8(%ebx),%eax
+ mull %ebp
+ addl %esi,%eax
+ adcl $0,%edx
+ addl 8(%edi),%eax
+ adcl $0,%edx
+ movl %eax,8(%edi)
+ movl %edx,%esi
+
+ movl 12(%ebx),%eax
+ mull %ebp
+ addl %esi,%eax
+ adcl $0,%edx
+ addl 12(%edi),%eax
+ adcl $0,%edx
+ movl %eax,12(%edi)
+ movl %edx,%esi
+
+ movl 16(%ebx),%eax
+ mull %ebp
+ addl %esi,%eax
+ adcl $0,%edx
+ addl 16(%edi),%eax
+ adcl $0,%edx
+ movl %eax,16(%edi)
+ movl %edx,%esi
+
+ movl 20(%ebx),%eax
+ mull %ebp
+ addl %esi,%eax
+ adcl $0,%edx
+ addl 20(%edi),%eax
+ adcl $0,%edx
+ movl %eax,20(%edi)
+ movl %edx,%esi
+
+ movl 24(%ebx),%eax
+ mull %ebp
+ addl %esi,%eax
+ adcl $0,%edx
+ addl 24(%edi),%eax
+ adcl $0,%edx
+ movl %eax,24(%edi)
+ movl %edx,%esi
+
+ movl 28(%ebx),%eax
+ mull %ebp
+ addl %esi,%eax
+ adcl $0,%edx
+ addl 28(%edi),%eax
+ adcl $0,%edx
+ movl %eax,28(%edi)
+ movl %edx,%esi
+
+ subl $8,%ecx
+ leal 32(%ebx),%ebx
+ leal 32(%edi),%edi
+ jnz .L001maw_loop
+.L000maw_finish:
+ movl 32(%esp),%ecx
+ andl $7,%ecx
+ jnz .L002maw_finish2
+ jmp .L003maw_end
+.L002maw_finish2:
+
+ movl (%ebx),%eax
+ mull %ebp
+ addl %esi,%eax
+ adcl $0,%edx
+ addl (%edi),%eax
+ adcl $0,%edx
+ decl %ecx
+ movl %eax,(%edi)
+ movl %edx,%esi
+ jz .L003maw_end
+
+ movl 4(%ebx),%eax
+ mull %ebp
+ addl %esi,%eax
+ adcl $0,%edx
+ addl 4(%edi),%eax
+ adcl $0,%edx
+ decl %ecx
+ movl %eax,4(%edi)
+ movl %edx,%esi
+ jz .L003maw_end
+
+ movl 8(%ebx),%eax
+ mull %ebp
+ addl %esi,%eax
+ adcl $0,%edx
+ addl 8(%edi),%eax
+ adcl $0,%edx
+ decl %ecx
+ movl %eax,8(%edi)
+ movl %edx,%esi
+ jz .L003maw_end
+
+ movl 12(%ebx),%eax
+ mull %ebp
+ addl %esi,%eax
+ adcl $0,%edx
+ addl 12(%edi),%eax
+ adcl $0,%edx
+ decl %ecx
+ movl %eax,12(%edi)
+ movl %edx,%esi
+ jz .L003maw_end
+
+ movl 16(%ebx),%eax
+ mull %ebp
+ addl %esi,%eax
+ adcl $0,%edx
+ addl 16(%edi),%eax
+ adcl $0,%edx
+ decl %ecx
+ movl %eax,16(%edi)
+ movl %edx,%esi
+ jz .L003maw_end
+
+ movl 20(%ebx),%eax
+ mull %ebp
+ addl %esi,%eax
+ adcl $0,%edx
+ addl 20(%edi),%eax
+ adcl $0,%edx
+ decl %ecx
+ movl %eax,20(%edi)
+ movl %edx,%esi
+ jz .L003maw_end
+
+ movl 24(%ebx),%eax
+ mull %ebp
+ addl %esi,%eax
+ adcl $0,%edx
+ addl 24(%edi),%eax
+ adcl $0,%edx
+ movl %eax,24(%edi)
+ movl %edx,%esi
+.L003maw_end:
+ movl %esi,%eax
+ popl %ecx
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.size bn_mul_add_words,.-.L_bn_mul_add_words_begin
+.globl bn_mul_words
+.hidden bn_mul_words
+.type bn_mul_words,@function
+.align 16
+bn_mul_words:
+.L_bn_mul_words_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+
+ xorl %esi,%esi
+ movl 20(%esp),%edi
+ movl 24(%esp),%ebx
+ movl 28(%esp),%ebp
+ movl 32(%esp),%ecx
+ andl $4294967288,%ebp
+ jz .L004mw_finish
+.L005mw_loop:
+
+ movl (%ebx),%eax
+ mull %ecx
+ addl %esi,%eax
+ adcl $0,%edx
+ movl %eax,(%edi)
+ movl %edx,%esi
+
+ movl 4(%ebx),%eax
+ mull %ecx
+ addl %esi,%eax
+ adcl $0,%edx
+ movl %eax,4(%edi)
+ movl %edx,%esi
+
+ movl 8(%ebx),%eax
+ mull %ecx
+ addl %esi,%eax
+ adcl $0,%edx
+ movl %eax,8(%edi)
+ movl %edx,%esi
+
+ movl 12(%ebx),%eax
+ mull %ecx
+ addl %esi,%eax
+ adcl $0,%edx
+ movl %eax,12(%edi)
+ movl %edx,%esi
+
+ movl 16(%ebx),%eax
+ mull %ecx
+ addl %esi,%eax
+ adcl $0,%edx
+ movl %eax,16(%edi)
+ movl %edx,%esi
+
+ movl 20(%ebx),%eax
+ mull %ecx
+ addl %esi,%eax
+ adcl $0,%edx
+ movl %eax,20(%edi)
+ movl %edx,%esi
+
+ movl 24(%ebx),%eax
+ mull %ecx
+ addl %esi,%eax
+ adcl $0,%edx
+ movl %eax,24(%edi)
+ movl %edx,%esi
+
+ movl 28(%ebx),%eax
+ mull %ecx
+ addl %esi,%eax
+ adcl $0,%edx
+ movl %eax,28(%edi)
+ movl %edx,%esi
+
+ addl $32,%ebx
+ addl $32,%edi
+ subl $8,%ebp
+ jz .L004mw_finish
+ jmp .L005mw_loop
+.L004mw_finish:
+ movl 28(%esp),%ebp
+ andl $7,%ebp
+ jnz .L006mw_finish2
+ jmp .L007mw_end
+.L006mw_finish2:
+
+ movl (%ebx),%eax
+ mull %ecx
+ addl %esi,%eax
+ adcl $0,%edx
+ movl %eax,(%edi)
+ movl %edx,%esi
+ decl %ebp
+ jz .L007mw_end
+
+ movl 4(%ebx),%eax
+ mull %ecx
+ addl %esi,%eax
+ adcl $0,%edx
+ movl %eax,4(%edi)
+ movl %edx,%esi
+ decl %ebp
+ jz .L007mw_end
+
+ movl 8(%ebx),%eax
+ mull %ecx
+ addl %esi,%eax
+ adcl $0,%edx
+ movl %eax,8(%edi)
+ movl %edx,%esi
+ decl %ebp
+ jz .L007mw_end
+
+ movl 12(%ebx),%eax
+ mull %ecx
+ addl %esi,%eax
+ adcl $0,%edx
+ movl %eax,12(%edi)
+ movl %edx,%esi
+ decl %ebp
+ jz .L007mw_end
+
+ movl 16(%ebx),%eax
+ mull %ecx
+ addl %esi,%eax
+ adcl $0,%edx
+ movl %eax,16(%edi)
+ movl %edx,%esi
+ decl %ebp
+ jz .L007mw_end
+
+ movl 20(%ebx),%eax
+ mull %ecx
+ addl %esi,%eax
+ adcl $0,%edx
+ movl %eax,20(%edi)
+ movl %edx,%esi
+ decl %ebp
+ jz .L007mw_end
+
+ movl 24(%ebx),%eax
+ mull %ecx
+ addl %esi,%eax
+ adcl $0,%edx
+ movl %eax,24(%edi)
+ movl %edx,%esi
+.L007mw_end:
+ movl %esi,%eax
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.size bn_mul_words,.-.L_bn_mul_words_begin
+.globl bn_sqr_words
+.hidden bn_sqr_words
+.type bn_sqr_words,@function
+.align 16
+bn_sqr_words:
+.L_bn_sqr_words_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+
+ movl 20(%esp),%esi
+ movl 24(%esp),%edi
+ movl 28(%esp),%ebx
+ andl $4294967288,%ebx
+ jz .L008sw_finish
+.L009sw_loop:
+
+ movl (%edi),%eax
+ mull %eax
+ movl %eax,(%esi)
+ movl %edx,4(%esi)
+
+ movl 4(%edi),%eax
+ mull %eax
+ movl %eax,8(%esi)
+ movl %edx,12(%esi)
+
+ movl 8(%edi),%eax
+ mull %eax
+ movl %eax,16(%esi)
+ movl %edx,20(%esi)
+
+ movl 12(%edi),%eax
+ mull %eax
+ movl %eax,24(%esi)
+ movl %edx,28(%esi)
+
+ movl 16(%edi),%eax
+ mull %eax
+ movl %eax,32(%esi)
+ movl %edx,36(%esi)
+
+ movl 20(%edi),%eax
+ mull %eax
+ movl %eax,40(%esi)
+ movl %edx,44(%esi)
+
+ movl 24(%edi),%eax
+ mull %eax
+ movl %eax,48(%esi)
+ movl %edx,52(%esi)
+
+ movl 28(%edi),%eax
+ mull %eax
+ movl %eax,56(%esi)
+ movl %edx,60(%esi)
+
+ addl $32,%edi
+ addl $64,%esi
+ subl $8,%ebx
+ jnz .L009sw_loop
+.L008sw_finish:
+ movl 28(%esp),%ebx
+ andl $7,%ebx
+ jz .L010sw_end
+
+ movl (%edi),%eax
+ mull %eax
+ movl %eax,(%esi)
+ decl %ebx
+ movl %edx,4(%esi)
+ jz .L010sw_end
+
+ movl 4(%edi),%eax
+ mull %eax
+ movl %eax,8(%esi)
+ decl %ebx
+ movl %edx,12(%esi)
+ jz .L010sw_end
+
+ movl 8(%edi),%eax
+ mull %eax
+ movl %eax,16(%esi)
+ decl %ebx
+ movl %edx,20(%esi)
+ jz .L010sw_end
+
+ movl 12(%edi),%eax
+ mull %eax
+ movl %eax,24(%esi)
+ decl %ebx
+ movl %edx,28(%esi)
+ jz .L010sw_end
+
+ movl 16(%edi),%eax
+ mull %eax
+ movl %eax,32(%esi)
+ decl %ebx
+ movl %edx,36(%esi)
+ jz .L010sw_end
+
+ movl 20(%edi),%eax
+ mull %eax
+ movl %eax,40(%esi)
+ decl %ebx
+ movl %edx,44(%esi)
+ jz .L010sw_end
+
+ movl 24(%edi),%eax
+ mull %eax
+ movl %eax,48(%esi)
+ movl %edx,52(%esi)
+.L010sw_end:
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.size bn_sqr_words,.-.L_bn_sqr_words_begin
+.globl bn_div_words
+.hidden bn_div_words
+.type bn_div_words,@function
+.align 16
+bn_div_words:
+.L_bn_div_words_begin:
+ movl 4(%esp),%edx
+ movl 8(%esp),%eax
+ movl 12(%esp),%ecx
+ divl %ecx
+ ret
+.size bn_div_words,.-.L_bn_div_words_begin
+.globl bn_add_words
+.hidden bn_add_words
+.type bn_add_words,@function
+.align 16
+bn_add_words:
+.L_bn_add_words_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+
+ movl 20(%esp),%ebx
+ movl 24(%esp),%esi
+ movl 28(%esp),%edi
+ movl 32(%esp),%ebp
+ xorl %eax,%eax
+ andl $4294967288,%ebp
+ jz .L011aw_finish
+.L012aw_loop:
+
+ movl (%esi),%ecx
+ movl (%edi),%edx
+ addl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ addl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,(%ebx)
+
+ movl 4(%esi),%ecx
+ movl 4(%edi),%edx
+ addl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ addl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,4(%ebx)
+
+ movl 8(%esi),%ecx
+ movl 8(%edi),%edx
+ addl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ addl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,8(%ebx)
+
+ movl 12(%esi),%ecx
+ movl 12(%edi),%edx
+ addl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ addl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,12(%ebx)
+
+ movl 16(%esi),%ecx
+ movl 16(%edi),%edx
+ addl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ addl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,16(%ebx)
+
+ movl 20(%esi),%ecx
+ movl 20(%edi),%edx
+ addl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ addl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,20(%ebx)
+
+ movl 24(%esi),%ecx
+ movl 24(%edi),%edx
+ addl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ addl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,24(%ebx)
+
+ movl 28(%esi),%ecx
+ movl 28(%edi),%edx
+ addl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ addl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,28(%ebx)
+
+ addl $32,%esi
+ addl $32,%edi
+ addl $32,%ebx
+ subl $8,%ebp
+ jnz .L012aw_loop
+.L011aw_finish:
+ movl 32(%esp),%ebp
+ andl $7,%ebp
+ jz .L013aw_end
+
+ movl (%esi),%ecx
+ movl (%edi),%edx
+ addl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ addl %edx,%ecx
+ adcl $0,%eax
+ decl %ebp
+ movl %ecx,(%ebx)
+ jz .L013aw_end
+
+ movl 4(%esi),%ecx
+ movl 4(%edi),%edx
+ addl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ addl %edx,%ecx
+ adcl $0,%eax
+ decl %ebp
+ movl %ecx,4(%ebx)
+ jz .L013aw_end
+
+ movl 8(%esi),%ecx
+ movl 8(%edi),%edx
+ addl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ addl %edx,%ecx
+ adcl $0,%eax
+ decl %ebp
+ movl %ecx,8(%ebx)
+ jz .L013aw_end
+
+ movl 12(%esi),%ecx
+ movl 12(%edi),%edx
+ addl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ addl %edx,%ecx
+ adcl $0,%eax
+ decl %ebp
+ movl %ecx,12(%ebx)
+ jz .L013aw_end
+
+ movl 16(%esi),%ecx
+ movl 16(%edi),%edx
+ addl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ addl %edx,%ecx
+ adcl $0,%eax
+ decl %ebp
+ movl %ecx,16(%ebx)
+ jz .L013aw_end
+
+ movl 20(%esi),%ecx
+ movl 20(%edi),%edx
+ addl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ addl %edx,%ecx
+ adcl $0,%eax
+ decl %ebp
+ movl %ecx,20(%ebx)
+ jz .L013aw_end
+
+ movl 24(%esi),%ecx
+ movl 24(%edi),%edx
+ addl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ addl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,24(%ebx)
+.L013aw_end:
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.size bn_add_words,.-.L_bn_add_words_begin
+.globl bn_sub_words
+.hidden bn_sub_words
+.type bn_sub_words,@function
+.align 16
+bn_sub_words:
+.L_bn_sub_words_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+
+ movl 20(%esp),%ebx
+ movl 24(%esp),%esi
+ movl 28(%esp),%edi
+ movl 32(%esp),%ebp
+ xorl %eax,%eax
+ andl $4294967288,%ebp
+ jz .L014aw_finish
+.L015aw_loop:
+
+ movl (%esi),%ecx
+ movl (%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,(%ebx)
+
+ movl 4(%esi),%ecx
+ movl 4(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,4(%ebx)
+
+ movl 8(%esi),%ecx
+ movl 8(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,8(%ebx)
+
+ movl 12(%esi),%ecx
+ movl 12(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,12(%ebx)
+
+ movl 16(%esi),%ecx
+ movl 16(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,16(%ebx)
+
+ movl 20(%esi),%ecx
+ movl 20(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,20(%ebx)
+
+ movl 24(%esi),%ecx
+ movl 24(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,24(%ebx)
+
+ movl 28(%esi),%ecx
+ movl 28(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,28(%ebx)
+
+ addl $32,%esi
+ addl $32,%edi
+ addl $32,%ebx
+ subl $8,%ebp
+ jnz .L015aw_loop
+.L014aw_finish:
+ movl 32(%esp),%ebp
+ andl $7,%ebp
+ jz .L016aw_end
+
+ movl (%esi),%ecx
+ movl (%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ decl %ebp
+ movl %ecx,(%ebx)
+ jz .L016aw_end
+
+ movl 4(%esi),%ecx
+ movl 4(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ decl %ebp
+ movl %ecx,4(%ebx)
+ jz .L016aw_end
+
+ movl 8(%esi),%ecx
+ movl 8(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ decl %ebp
+ movl %ecx,8(%ebx)
+ jz .L016aw_end
+
+ movl 12(%esi),%ecx
+ movl 12(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ decl %ebp
+ movl %ecx,12(%ebx)
+ jz .L016aw_end
+
+ movl 16(%esi),%ecx
+ movl 16(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ decl %ebp
+ movl %ecx,16(%ebx)
+ jz .L016aw_end
+
+ movl 20(%esi),%ecx
+ movl 20(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ decl %ebp
+ movl %ecx,20(%ebx)
+ jz .L016aw_end
+
+ movl 24(%esi),%ecx
+ movl 24(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,24(%ebx)
+.L016aw_end:
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.size bn_sub_words,.-.L_bn_sub_words_begin
+.globl bn_sub_part_words
+.hidden bn_sub_part_words
+.type bn_sub_part_words,@function
+.align 16
+bn_sub_part_words:
+.L_bn_sub_part_words_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+
+ movl 20(%esp),%ebx
+ movl 24(%esp),%esi
+ movl 28(%esp),%edi
+ movl 32(%esp),%ebp
+ xorl %eax,%eax
+ andl $4294967288,%ebp
+ jz .L017aw_finish
+.L018aw_loop:
+
+ movl (%esi),%ecx
+ movl (%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,(%ebx)
+
+ movl 4(%esi),%ecx
+ movl 4(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,4(%ebx)
+
+ movl 8(%esi),%ecx
+ movl 8(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,8(%ebx)
+
+ movl 12(%esi),%ecx
+ movl 12(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,12(%ebx)
+
+ movl 16(%esi),%ecx
+ movl 16(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,16(%ebx)
+
+ movl 20(%esi),%ecx
+ movl 20(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,20(%ebx)
+
+ movl 24(%esi),%ecx
+ movl 24(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,24(%ebx)
+
+ movl 28(%esi),%ecx
+ movl 28(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,28(%ebx)
+
+ addl $32,%esi
+ addl $32,%edi
+ addl $32,%ebx
+ subl $8,%ebp
+ jnz .L018aw_loop
+.L017aw_finish:
+ movl 32(%esp),%ebp
+ andl $7,%ebp
+ jz .L019aw_end
+
+ movl (%esi),%ecx
+ movl (%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,(%ebx)
+ addl $4,%esi
+ addl $4,%edi
+ addl $4,%ebx
+ decl %ebp
+ jz .L019aw_end
+
+ movl (%esi),%ecx
+ movl (%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,(%ebx)
+ addl $4,%esi
+ addl $4,%edi
+ addl $4,%ebx
+ decl %ebp
+ jz .L019aw_end
+
+ movl (%esi),%ecx
+ movl (%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,(%ebx)
+ addl $4,%esi
+ addl $4,%edi
+ addl $4,%ebx
+ decl %ebp
+ jz .L019aw_end
+
+ movl (%esi),%ecx
+ movl (%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,(%ebx)
+ addl $4,%esi
+ addl $4,%edi
+ addl $4,%ebx
+ decl %ebp
+ jz .L019aw_end
+
+ movl (%esi),%ecx
+ movl (%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,(%ebx)
+ addl $4,%esi
+ addl $4,%edi
+ addl $4,%ebx
+ decl %ebp
+ jz .L019aw_end
+
+ movl (%esi),%ecx
+ movl (%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,(%ebx)
+ addl $4,%esi
+ addl $4,%edi
+ addl $4,%ebx
+ decl %ebp
+ jz .L019aw_end
+
+ movl (%esi),%ecx
+ movl (%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,(%ebx)
+ addl $4,%esi
+ addl $4,%edi
+ addl $4,%ebx
+.L019aw_end:
+ cmpl $0,36(%esp)
+ je .L020pw_end
+ movl 36(%esp),%ebp
+ cmpl $0,%ebp
+ je .L020pw_end
+ jge .L021pw_pos
+
+ movl $0,%edx
+ subl %ebp,%edx
+ movl %edx,%ebp
+ andl $4294967288,%ebp
+ jz .L022pw_neg_finish
+.L023pw_neg_loop:
+
+ movl $0,%ecx
+ movl (%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,(%ebx)
+
+ movl $0,%ecx
+ movl 4(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,4(%ebx)
+
+ movl $0,%ecx
+ movl 8(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,8(%ebx)
+
+ movl $0,%ecx
+ movl 12(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,12(%ebx)
+
+ movl $0,%ecx
+ movl 16(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,16(%ebx)
+
+ movl $0,%ecx
+ movl 20(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,20(%ebx)
+
+ movl $0,%ecx
+ movl 24(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,24(%ebx)
+
+ movl $0,%ecx
+ movl 28(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,28(%ebx)
+
+ addl $32,%edi
+ addl $32,%ebx
+ subl $8,%ebp
+ jnz .L023pw_neg_loop
+.L022pw_neg_finish:
+ movl 36(%esp),%edx
+ movl $0,%ebp
+ subl %edx,%ebp
+ andl $7,%ebp
+ jz .L020pw_end
+
+ movl $0,%ecx
+ movl (%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ decl %ebp
+ movl %ecx,(%ebx)
+ jz .L020pw_end
+
+ movl $0,%ecx
+ movl 4(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ decl %ebp
+ movl %ecx,4(%ebx)
+ jz .L020pw_end
+
+ movl $0,%ecx
+ movl 8(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ decl %ebp
+ movl %ecx,8(%ebx)
+ jz .L020pw_end
+
+ movl $0,%ecx
+ movl 12(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ decl %ebp
+ movl %ecx,12(%ebx)
+ jz .L020pw_end
+
+ movl $0,%ecx
+ movl 16(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ decl %ebp
+ movl %ecx,16(%ebx)
+ jz .L020pw_end
+
+ movl $0,%ecx
+ movl 20(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ decl %ebp
+ movl %ecx,20(%ebx)
+ jz .L020pw_end
+
+ movl $0,%ecx
+ movl 24(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,24(%ebx)
+ jmp .L020pw_end
+.L021pw_pos:
+ andl $4294967288,%ebp
+ jz .L024pw_pos_finish
+.L025pw_pos_loop:
+
+ movl (%esi),%ecx
+ subl %eax,%ecx
+ movl %ecx,(%ebx)
+ jnc .L026pw_nc0
+
+ movl 4(%esi),%ecx
+ subl %eax,%ecx
+ movl %ecx,4(%ebx)
+ jnc .L027pw_nc1
+
+ movl 8(%esi),%ecx
+ subl %eax,%ecx
+ movl %ecx,8(%ebx)
+ jnc .L028pw_nc2
+
+ movl 12(%esi),%ecx
+ subl %eax,%ecx
+ movl %ecx,12(%ebx)
+ jnc .L029pw_nc3
+
+ movl 16(%esi),%ecx
+ subl %eax,%ecx
+ movl %ecx,16(%ebx)
+ jnc .L030pw_nc4
+
+ movl 20(%esi),%ecx
+ subl %eax,%ecx
+ movl %ecx,20(%ebx)
+ jnc .L031pw_nc5
+
+ movl 24(%esi),%ecx
+ subl %eax,%ecx
+ movl %ecx,24(%ebx)
+ jnc .L032pw_nc6
+
+ movl 28(%esi),%ecx
+ subl %eax,%ecx
+ movl %ecx,28(%ebx)
+ jnc .L033pw_nc7
+
+ addl $32,%esi
+ addl $32,%ebx
+ subl $8,%ebp
+ jnz .L025pw_pos_loop
+.L024pw_pos_finish:
+ movl 36(%esp),%ebp
+ andl $7,%ebp
+ jz .L020pw_end
+
+ movl (%esi),%ecx
+ subl %eax,%ecx
+ movl %ecx,(%ebx)
+ jnc .L034pw_tail_nc0
+ decl %ebp
+ jz .L020pw_end
+
+ movl 4(%esi),%ecx
+ subl %eax,%ecx
+ movl %ecx,4(%ebx)
+ jnc .L035pw_tail_nc1
+ decl %ebp
+ jz .L020pw_end
+
+ movl 8(%esi),%ecx
+ subl %eax,%ecx
+ movl %ecx,8(%ebx)
+ jnc .L036pw_tail_nc2
+ decl %ebp
+ jz .L020pw_end
+
+ movl 12(%esi),%ecx
+ subl %eax,%ecx
+ movl %ecx,12(%ebx)
+ jnc .L037pw_tail_nc3
+ decl %ebp
+ jz .L020pw_end
+
+ movl 16(%esi),%ecx
+ subl %eax,%ecx
+ movl %ecx,16(%ebx)
+ jnc .L038pw_tail_nc4
+ decl %ebp
+ jz .L020pw_end
+
+ movl 20(%esi),%ecx
+ subl %eax,%ecx
+ movl %ecx,20(%ebx)
+ jnc .L039pw_tail_nc5
+ decl %ebp
+ jz .L020pw_end
+
+ movl 24(%esi),%ecx
+ subl %eax,%ecx
+ movl %ecx,24(%ebx)
+ jnc .L040pw_tail_nc6
+ movl $1,%eax
+ jmp .L020pw_end
+.L041pw_nc_loop:
+ movl (%esi),%ecx
+ movl %ecx,(%ebx)
+.L026pw_nc0:
+ movl 4(%esi),%ecx
+ movl %ecx,4(%ebx)
+.L027pw_nc1:
+ movl 8(%esi),%ecx
+ movl %ecx,8(%ebx)
+.L028pw_nc2:
+ movl 12(%esi),%ecx
+ movl %ecx,12(%ebx)
+.L029pw_nc3:
+ movl 16(%esi),%ecx
+ movl %ecx,16(%ebx)
+.L030pw_nc4:
+ movl 20(%esi),%ecx
+ movl %ecx,20(%ebx)
+.L031pw_nc5:
+ movl 24(%esi),%ecx
+ movl %ecx,24(%ebx)
+.L032pw_nc6:
+ movl 28(%esi),%ecx
+ movl %ecx,28(%ebx)
+.L033pw_nc7:
+
+ addl $32,%esi
+ addl $32,%ebx
+ subl $8,%ebp
+ jnz .L041pw_nc_loop
+ movl 36(%esp),%ebp
+ andl $7,%ebp
+ jz .L042pw_nc_end
+ movl (%esi),%ecx
+ movl %ecx,(%ebx)
+.L034pw_tail_nc0:
+ decl %ebp
+ jz .L042pw_nc_end
+ movl 4(%esi),%ecx
+ movl %ecx,4(%ebx)
+.L035pw_tail_nc1:
+ decl %ebp
+ jz .L042pw_nc_end
+ movl 8(%esi),%ecx
+ movl %ecx,8(%ebx)
+.L036pw_tail_nc2:
+ decl %ebp
+ jz .L042pw_nc_end
+ movl 12(%esi),%ecx
+ movl %ecx,12(%ebx)
+.L037pw_tail_nc3:
+ decl %ebp
+ jz .L042pw_nc_end
+ movl 16(%esi),%ecx
+ movl %ecx,16(%ebx)
+.L038pw_tail_nc4:
+ decl %ebp
+ jz .L042pw_nc_end
+ movl 20(%esi),%ecx
+ movl %ecx,20(%ebx)
+.L039pw_tail_nc5:
+ decl %ebp
+ jz .L042pw_nc_end
+ movl 24(%esi),%ecx
+ movl %ecx,24(%ebx)
+.L040pw_tail_nc6:
+.L042pw_nc_end:
+ movl $0,%eax
+.L020pw_end:
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.size bn_sub_part_words,.-.L_bn_sub_part_words_begin
+#endif
diff --git a/linux-x86/crypto/bn/co-586.S b/linux-x86/crypto/bn/co-586.S
new file mode 100644
index 0000000..e41c3a1
--- /dev/null
+++ b/linux-x86/crypto/bn/co-586.S
@@ -0,0 +1,1260 @@
+#if defined(__i386__)
+.file "src/crypto/bn/asm/co-586.S"
+.text
+.globl bn_mul_comba8
+.hidden bn_mul_comba8
+.type bn_mul_comba8,@function
+.align 16
+bn_mul_comba8:
+.L_bn_mul_comba8_begin:
+ pushl %esi
+ movl 12(%esp),%esi
+ pushl %edi
+ movl 20(%esp),%edi
+ pushl %ebp
+ pushl %ebx
+ xorl %ebx,%ebx
+ movl (%esi),%eax
+ xorl %ecx,%ecx
+ movl (%edi),%edx
+
+ xorl %ebp,%ebp
+
+ mull %edx
+ addl %eax,%ebx
+ movl 20(%esp),%eax
+ adcl %edx,%ecx
+ movl (%edi),%edx
+ adcl $0,%ebp
+ movl %ebx,(%eax)
+ movl 4(%esi),%eax
+
+
+ xorl %ebx,%ebx
+
+ mull %edx
+ addl %eax,%ecx
+ movl (%esi),%eax
+ adcl %edx,%ebp
+ movl 4(%edi),%edx
+ adcl $0,%ebx
+
+ mull %edx
+ addl %eax,%ecx
+ movl 20(%esp),%eax
+ adcl %edx,%ebp
+ movl (%edi),%edx
+ adcl $0,%ebx
+ movl %ecx,4(%eax)
+ movl 8(%esi),%eax
+
+
+ xorl %ecx,%ecx
+
+ mull %edx
+ addl %eax,%ebp
+ movl 4(%esi),%eax
+ adcl %edx,%ebx
+ movl 4(%edi),%edx
+ adcl $0,%ecx
+
+ mull %edx
+ addl %eax,%ebp
+ movl (%esi),%eax
+ adcl %edx,%ebx
+ movl 8(%edi),%edx
+ adcl $0,%ecx
+
+ mull %edx
+ addl %eax,%ebp
+ movl 20(%esp),%eax
+ adcl %edx,%ebx
+ movl (%edi),%edx
+ adcl $0,%ecx
+ movl %ebp,8(%eax)
+ movl 12(%esi),%eax
+
+
+ xorl %ebp,%ebp
+
+ mull %edx
+ addl %eax,%ebx
+ movl 8(%esi),%eax
+ adcl %edx,%ecx
+ movl 4(%edi),%edx
+ adcl $0,%ebp
+
+ mull %edx
+ addl %eax,%ebx
+ movl 4(%esi),%eax
+ adcl %edx,%ecx
+ movl 8(%edi),%edx
+ adcl $0,%ebp
+
+ mull %edx
+ addl %eax,%ebx
+ movl (%esi),%eax
+ adcl %edx,%ecx
+ movl 12(%edi),%edx
+ adcl $0,%ebp
+
+ mull %edx
+ addl %eax,%ebx
+ movl 20(%esp),%eax
+ adcl %edx,%ecx
+ movl (%edi),%edx
+ adcl $0,%ebp
+ movl %ebx,12(%eax)
+ movl 16(%esi),%eax
+
+
+ xorl %ebx,%ebx
+
+ mull %edx
+ addl %eax,%ecx
+ movl 12(%esi),%eax
+ adcl %edx,%ebp
+ movl 4(%edi),%edx
+ adcl $0,%ebx
+
+ mull %edx
+ addl %eax,%ecx
+ movl 8(%esi),%eax
+ adcl %edx,%ebp
+ movl 8(%edi),%edx
+ adcl $0,%ebx
+
+ mull %edx
+ addl %eax,%ecx
+ movl 4(%esi),%eax
+ adcl %edx,%ebp
+ movl 12(%edi),%edx
+ adcl $0,%ebx
+
+ mull %edx
+ addl %eax,%ecx
+ movl (%esi),%eax
+ adcl %edx,%ebp
+ movl 16(%edi),%edx
+ adcl $0,%ebx
+
+ mull %edx
+ addl %eax,%ecx
+ movl 20(%esp),%eax
+ adcl %edx,%ebp
+ movl (%edi),%edx
+ adcl $0,%ebx
+ movl %ecx,16(%eax)
+ movl 20(%esi),%eax
+
+
+ xorl %ecx,%ecx
+
+ mull %edx
+ addl %eax,%ebp
+ movl 16(%esi),%eax
+ adcl %edx,%ebx
+ movl 4(%edi),%edx
+ adcl $0,%ecx
+
+ mull %edx
+ addl %eax,%ebp
+ movl 12(%esi),%eax
+ adcl %edx,%ebx
+ movl 8(%edi),%edx
+ adcl $0,%ecx
+
+ mull %edx
+ addl %eax,%ebp
+ movl 8(%esi),%eax
+ adcl %edx,%ebx
+ movl 12(%edi),%edx
+ adcl $0,%ecx
+
+ mull %edx
+ addl %eax,%ebp
+ movl 4(%esi),%eax
+ adcl %edx,%ebx
+ movl 16(%edi),%edx
+ adcl $0,%ecx
+
+ mull %edx
+ addl %eax,%ebp
+ movl (%esi),%eax
+ adcl %edx,%ebx
+ movl 20(%edi),%edx
+ adcl $0,%ecx
+
+ mull %edx
+ addl %eax,%ebp
+ movl 20(%esp),%eax
+ adcl %edx,%ebx
+ movl (%edi),%edx
+ adcl $0,%ecx
+ movl %ebp,20(%eax)
+ movl 24(%esi),%eax
+
+
+ xorl %ebp,%ebp
+
+ mull %edx
+ addl %eax,%ebx
+ movl 20(%esi),%eax
+ adcl %edx,%ecx
+ movl 4(%edi),%edx
+ adcl $0,%ebp
+
+ mull %edx
+ addl %eax,%ebx
+ movl 16(%esi),%eax
+ adcl %edx,%ecx
+ movl 8(%edi),%edx
+ adcl $0,%ebp
+
+ mull %edx
+ addl %eax,%ebx
+ movl 12(%esi),%eax
+ adcl %edx,%ecx
+ movl 12(%edi),%edx
+ adcl $0,%ebp
+
+ mull %edx
+ addl %eax,%ebx
+ movl 8(%esi),%eax
+ adcl %edx,%ecx
+ movl 16(%edi),%edx
+ adcl $0,%ebp
+
+ mull %edx
+ addl %eax,%ebx
+ movl 4(%esi),%eax
+ adcl %edx,%ecx
+ movl 20(%edi),%edx
+ adcl $0,%ebp
+
+ mull %edx
+ addl %eax,%ebx
+ movl (%esi),%eax
+ adcl %edx,%ecx
+ movl 24(%edi),%edx
+ adcl $0,%ebp
+
+ mull %edx
+ addl %eax,%ebx
+ movl 20(%esp),%eax
+ adcl %edx,%ecx
+ movl (%edi),%edx
+ adcl $0,%ebp
+ movl %ebx,24(%eax)
+ movl 28(%esi),%eax
+
+
+ xorl %ebx,%ebx
+
+ mull %edx
+ addl %eax,%ecx
+ movl 24(%esi),%eax
+ adcl %edx,%ebp
+ movl 4(%edi),%edx
+ adcl $0,%ebx
+
+ mull %edx
+ addl %eax,%ecx
+ movl 20(%esi),%eax
+ adcl %edx,%ebp
+ movl 8(%edi),%edx
+ adcl $0,%ebx
+
+ mull %edx
+ addl %eax,%ecx
+ movl 16(%esi),%eax
+ adcl %edx,%ebp
+ movl 12(%edi),%edx
+ adcl $0,%ebx
+
+ mull %edx
+ addl %eax,%ecx
+ movl 12(%esi),%eax
+ adcl %edx,%ebp
+ movl 16(%edi),%edx
+ adcl $0,%ebx
+
+ mull %edx
+ addl %eax,%ecx
+ movl 8(%esi),%eax
+ adcl %edx,%ebp
+ movl 20(%edi),%edx
+ adcl $0,%ebx
+
+ mull %edx
+ addl %eax,%ecx
+ movl 4(%esi),%eax
+ adcl %edx,%ebp
+ movl 24(%edi),%edx
+ adcl $0,%ebx
+
+ mull %edx
+ addl %eax,%ecx
+ movl (%esi),%eax
+ adcl %edx,%ebp
+ movl 28(%edi),%edx
+ adcl $0,%ebx
+
+ mull %edx
+ addl %eax,%ecx
+ movl 20(%esp),%eax
+ adcl %edx,%ebp
+ movl 4(%edi),%edx
+ adcl $0,%ebx
+ movl %ecx,28(%eax)
+ movl 28(%esi),%eax
+
+
+ xorl %ecx,%ecx
+
+ mull %edx
+ addl %eax,%ebp
+ movl 24(%esi),%eax
+ adcl %edx,%ebx
+ movl 8(%edi),%edx
+ adcl $0,%ecx
+
+ mull %edx
+ addl %eax,%ebp
+ movl 20(%esi),%eax
+ adcl %edx,%ebx
+ movl 12(%edi),%edx
+ adcl $0,%ecx
+
+ mull %edx
+ addl %eax,%ebp
+ movl 16(%esi),%eax
+ adcl %edx,%ebx
+ movl 16(%edi),%edx
+ adcl $0,%ecx
+
+ mull %edx
+ addl %eax,%ebp
+ movl 12(%esi),%eax
+ adcl %edx,%ebx
+ movl 20(%edi),%edx
+ adcl $0,%ecx
+
+ mull %edx
+ addl %eax,%ebp
+ movl 8(%esi),%eax
+ adcl %edx,%ebx
+ movl 24(%edi),%edx
+ adcl $0,%ecx
+
+ mull %edx
+ addl %eax,%ebp
+ movl 4(%esi),%eax
+ adcl %edx,%ebx
+ movl 28(%edi),%edx
+ adcl $0,%ecx
+
+ mull %edx
+ addl %eax,%ebp
+ movl 20(%esp),%eax
+ adcl %edx,%ebx
+ movl 8(%edi),%edx
+ adcl $0,%ecx
+ movl %ebp,32(%eax)
+ movl 28(%esi),%eax
+
+
+ xorl %ebp,%ebp
+
+ mull %edx
+ addl %eax,%ebx
+ movl 24(%esi),%eax
+ adcl %edx,%ecx
+ movl 12(%edi),%edx
+ adcl $0,%ebp
+
+ mull %edx
+ addl %eax,%ebx
+ movl 20(%esi),%eax
+ adcl %edx,%ecx
+ movl 16(%edi),%edx
+ adcl $0,%ebp
+
+ mull %edx
+ addl %eax,%ebx
+ movl 16(%esi),%eax
+ adcl %edx,%ecx
+ movl 20(%edi),%edx
+ adcl $0,%ebp
+
+ mull %edx
+ addl %eax,%ebx
+ movl 12(%esi),%eax
+ adcl %edx,%ecx
+ movl 24(%edi),%edx
+ adcl $0,%ebp
+
+ mull %edx
+ addl %eax,%ebx
+ movl 8(%esi),%eax
+ adcl %edx,%ecx
+ movl 28(%edi),%edx
+ adcl $0,%ebp
+
+ mull %edx
+ addl %eax,%ebx
+ movl 20(%esp),%eax
+ adcl %edx,%ecx
+ movl 12(%edi),%edx
+ adcl $0,%ebp
+ movl %ebx,36(%eax)
+ movl 28(%esi),%eax
+
+
+ xorl %ebx,%ebx
+
+ mull %edx
+ addl %eax,%ecx
+ movl 24(%esi),%eax
+ adcl %edx,%ebp
+ movl 16(%edi),%edx
+ adcl $0,%ebx
+
+ mull %edx
+ addl %eax,%ecx
+ movl 20(%esi),%eax
+ adcl %edx,%ebp
+ movl 20(%edi),%edx
+ adcl $0,%ebx
+
+ mull %edx
+ addl %eax,%ecx
+ movl 16(%esi),%eax
+ adcl %edx,%ebp
+ movl 24(%edi),%edx
+ adcl $0,%ebx
+
+ mull %edx
+ addl %eax,%ecx
+ movl 12(%esi),%eax
+ adcl %edx,%ebp
+ movl 28(%edi),%edx
+ adcl $0,%ebx
+
+ mull %edx
+ addl %eax,%ecx
+ movl 20(%esp),%eax
+ adcl %edx,%ebp
+ movl 16(%edi),%edx
+ adcl $0,%ebx
+ movl %ecx,40(%eax)
+ movl 28(%esi),%eax
+
+
+ xorl %ecx,%ecx
+
+ mull %edx
+ addl %eax,%ebp
+ movl 24(%esi),%eax
+ adcl %edx,%ebx
+ movl 20(%edi),%edx
+ adcl $0,%ecx
+
+ mull %edx
+ addl %eax,%ebp
+ movl 20(%esi),%eax
+ adcl %edx,%ebx
+ movl 24(%edi),%edx
+ adcl $0,%ecx
+
+ mull %edx
+ addl %eax,%ebp
+ movl 16(%esi),%eax
+ adcl %edx,%ebx
+ movl 28(%edi),%edx
+ adcl $0,%ecx
+
+ mull %edx
+ addl %eax,%ebp
+ movl 20(%esp),%eax
+ adcl %edx,%ebx
+ movl 20(%edi),%edx
+ adcl $0,%ecx
+ movl %ebp,44(%eax)
+ movl 28(%esi),%eax
+
+
+ xorl %ebp,%ebp
+
+ mull %edx
+ addl %eax,%ebx
+ movl 24(%esi),%eax
+ adcl %edx,%ecx
+ movl 24(%edi),%edx
+ adcl $0,%ebp
+
+ mull %edx
+ addl %eax,%ebx
+ movl 20(%esi),%eax
+ adcl %edx,%ecx
+ movl 28(%edi),%edx
+ adcl $0,%ebp
+
+ mull %edx
+ addl %eax,%ebx
+ movl 20(%esp),%eax
+ adcl %edx,%ecx
+ movl 24(%edi),%edx
+ adcl $0,%ebp
+ movl %ebx,48(%eax)
+ movl 28(%esi),%eax
+
+
+ xorl %ebx,%ebx
+
+ mull %edx
+ addl %eax,%ecx
+ movl 24(%esi),%eax
+ adcl %edx,%ebp
+ movl 28(%edi),%edx
+ adcl $0,%ebx
+
+ mull %edx
+ addl %eax,%ecx
+ movl 20(%esp),%eax
+ adcl %edx,%ebp
+ movl 28(%edi),%edx
+ adcl $0,%ebx
+ movl %ecx,52(%eax)
+ movl 28(%esi),%eax
+
+
+ xorl %ecx,%ecx
+
+ mull %edx
+ addl %eax,%ebp
+ movl 20(%esp),%eax
+ adcl %edx,%ebx
+ adcl $0,%ecx
+ movl %ebp,56(%eax)
+
+
+ movl %ebx,60(%eax)
+ popl %ebx
+ popl %ebp
+ popl %edi
+ popl %esi
+ ret
+.size bn_mul_comba8,.-.L_bn_mul_comba8_begin
+.globl bn_mul_comba4
+.hidden bn_mul_comba4
+.type bn_mul_comba4,@function
+.align 16
+bn_mul_comba4:
+.L_bn_mul_comba4_begin:
+ pushl %esi
+ movl 12(%esp),%esi
+ pushl %edi
+ movl 20(%esp),%edi
+ pushl %ebp
+ pushl %ebx
+ xorl %ebx,%ebx
+ movl (%esi),%eax
+ xorl %ecx,%ecx
+ movl (%edi),%edx
+
+ xorl %ebp,%ebp
+
+ mull %edx
+ addl %eax,%ebx
+ movl 20(%esp),%eax
+ adcl %edx,%ecx
+ movl (%edi),%edx
+ adcl $0,%ebp
+ movl %ebx,(%eax)
+ movl 4(%esi),%eax
+
+
+ xorl %ebx,%ebx
+
+ mull %edx
+ addl %eax,%ecx
+ movl (%esi),%eax
+ adcl %edx,%ebp
+ movl 4(%edi),%edx
+ adcl $0,%ebx
+
+ mull %edx
+ addl %eax,%ecx
+ movl 20(%esp),%eax
+ adcl %edx,%ebp
+ movl (%edi),%edx
+ adcl $0,%ebx
+ movl %ecx,4(%eax)
+ movl 8(%esi),%eax
+
+
+ xorl %ecx,%ecx
+
+ mull %edx
+ addl %eax,%ebp
+ movl 4(%esi),%eax
+ adcl %edx,%ebx
+ movl 4(%edi),%edx
+ adcl $0,%ecx
+
+ mull %edx
+ addl %eax,%ebp
+ movl (%esi),%eax
+ adcl %edx,%ebx
+ movl 8(%edi),%edx
+ adcl $0,%ecx
+
+ mull %edx
+ addl %eax,%ebp
+ movl 20(%esp),%eax
+ adcl %edx,%ebx
+ movl (%edi),%edx
+ adcl $0,%ecx
+ movl %ebp,8(%eax)
+ movl 12(%esi),%eax
+
+
+ xorl %ebp,%ebp
+
+ mull %edx
+ addl %eax,%ebx
+ movl 8(%esi),%eax
+ adcl %edx,%ecx
+ movl 4(%edi),%edx
+ adcl $0,%ebp
+
+ mull %edx
+ addl %eax,%ebx
+ movl 4(%esi),%eax
+ adcl %edx,%ecx
+ movl 8(%edi),%edx
+ adcl $0,%ebp
+
+ mull %edx
+ addl %eax,%ebx
+ movl (%esi),%eax
+ adcl %edx,%ecx
+ movl 12(%edi),%edx
+ adcl $0,%ebp
+
+ mull %edx
+ addl %eax,%ebx
+ movl 20(%esp),%eax
+ adcl %edx,%ecx
+ movl 4(%edi),%edx
+ adcl $0,%ebp
+ movl %ebx,12(%eax)
+ movl 12(%esi),%eax
+
+
+ xorl %ebx,%ebx
+
+ mull %edx
+ addl %eax,%ecx
+ movl 8(%esi),%eax
+ adcl %edx,%ebp
+ movl 8(%edi),%edx
+ adcl $0,%ebx
+
+ mull %edx
+ addl %eax,%ecx
+ movl 4(%esi),%eax
+ adcl %edx,%ebp
+ movl 12(%edi),%edx
+ adcl $0,%ebx
+
+ mull %edx
+ addl %eax,%ecx
+ movl 20(%esp),%eax
+ adcl %edx,%ebp
+ movl 8(%edi),%edx
+ adcl $0,%ebx
+ movl %ecx,16(%eax)
+ movl 12(%esi),%eax
+
+
+ xorl %ecx,%ecx
+
+ mull %edx
+ addl %eax,%ebp
+ movl 8(%esi),%eax
+ adcl %edx,%ebx
+ movl 12(%edi),%edx
+ adcl $0,%ecx
+
+ mull %edx
+ addl %eax,%ebp
+ movl 20(%esp),%eax
+ adcl %edx,%ebx
+ movl 12(%edi),%edx
+ adcl $0,%ecx
+ movl %ebp,20(%eax)
+ movl 12(%esi),%eax
+
+
+ xorl %ebp,%ebp
+
+ mull %edx
+ addl %eax,%ebx
+ movl 20(%esp),%eax
+ adcl %edx,%ecx
+ adcl $0,%ebp
+ movl %ebx,24(%eax)
+
+
+ movl %ecx,28(%eax)
+ popl %ebx
+ popl %ebp
+ popl %edi
+ popl %esi
+ ret
+.size bn_mul_comba4,.-.L_bn_mul_comba4_begin
+.globl bn_sqr_comba8
+.hidden bn_sqr_comba8
+.type bn_sqr_comba8,@function
+.align 16
+bn_sqr_comba8:
+.L_bn_sqr_comba8_begin:
+ pushl %esi
+ pushl %edi
+ pushl %ebp
+ pushl %ebx
+ movl 20(%esp),%edi
+ movl 24(%esp),%esi
+ xorl %ebx,%ebx
+ xorl %ecx,%ecx
+ movl (%esi),%eax
+
+ xorl %ebp,%ebp
+
+ mull %eax
+ addl %eax,%ebx
+ adcl %edx,%ecx
+ movl (%esi),%edx
+ adcl $0,%ebp
+ movl %ebx,(%edi)
+ movl 4(%esi),%eax
+
+
+ xorl %ebx,%ebx
+
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ebx
+ addl %eax,%ecx
+ adcl %edx,%ebp
+ movl 8(%esi),%eax
+ adcl $0,%ebx
+ movl %ecx,4(%edi)
+ movl (%esi),%edx
+
+
+ xorl %ecx,%ecx
+
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ecx
+ addl %eax,%ebp
+ adcl %edx,%ebx
+ movl 4(%esi),%eax
+ adcl $0,%ecx
+
+ mull %eax
+ addl %eax,%ebp
+ adcl %edx,%ebx
+ movl (%esi),%edx
+ adcl $0,%ecx
+ movl %ebp,8(%edi)
+ movl 12(%esi),%eax
+
+
+ xorl %ebp,%ebp
+
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ebp
+ addl %eax,%ebx
+ adcl %edx,%ecx
+ movl 8(%esi),%eax
+ adcl $0,%ebp
+ movl 4(%esi),%edx
+
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ebp
+ addl %eax,%ebx
+ adcl %edx,%ecx
+ movl 16(%esi),%eax
+ adcl $0,%ebp
+ movl %ebx,12(%edi)
+ movl (%esi),%edx
+
+
+ xorl %ebx,%ebx
+
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ebx
+ addl %eax,%ecx
+ adcl %edx,%ebp
+ movl 12(%esi),%eax
+ adcl $0,%ebx
+ movl 4(%esi),%edx
+
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ebx
+ addl %eax,%ecx
+ adcl %edx,%ebp
+ movl 8(%esi),%eax
+ adcl $0,%ebx
+
+ mull %eax
+ addl %eax,%ecx
+ adcl %edx,%ebp
+ movl (%esi),%edx
+ adcl $0,%ebx
+ movl %ecx,16(%edi)
+ movl 20(%esi),%eax
+
+
+ xorl %ecx,%ecx
+
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ecx
+ addl %eax,%ebp
+ adcl %edx,%ebx
+ movl 16(%esi),%eax
+ adcl $0,%ecx
+ movl 4(%esi),%edx
+
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ecx
+ addl %eax,%ebp
+ adcl %edx,%ebx
+ movl 12(%esi),%eax
+ adcl $0,%ecx
+ movl 8(%esi),%edx
+
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ecx
+ addl %eax,%ebp
+ adcl %edx,%ebx
+ movl 24(%esi),%eax
+ adcl $0,%ecx
+ movl %ebp,20(%edi)
+ movl (%esi),%edx
+
+
+ xorl %ebp,%ebp
+
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ebp
+ addl %eax,%ebx
+ adcl %edx,%ecx
+ movl 20(%esi),%eax
+ adcl $0,%ebp
+ movl 4(%esi),%edx
+
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ebp
+ addl %eax,%ebx
+ adcl %edx,%ecx
+ movl 16(%esi),%eax
+ adcl $0,%ebp
+ movl 8(%esi),%edx
+
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ebp
+ addl %eax,%ebx
+ adcl %edx,%ecx
+ movl 12(%esi),%eax
+ adcl $0,%ebp
+
+ mull %eax
+ addl %eax,%ebx
+ adcl %edx,%ecx
+ movl (%esi),%edx
+ adcl $0,%ebp
+ movl %ebx,24(%edi)
+ movl 28(%esi),%eax
+
+
+ xorl %ebx,%ebx
+
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ebx
+ addl %eax,%ecx
+ adcl %edx,%ebp
+ movl 24(%esi),%eax
+ adcl $0,%ebx
+ movl 4(%esi),%edx
+
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ebx
+ addl %eax,%ecx
+ adcl %edx,%ebp
+ movl 20(%esi),%eax
+ adcl $0,%ebx
+ movl 8(%esi),%edx
+
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ebx
+ addl %eax,%ecx
+ adcl %edx,%ebp
+ movl 16(%esi),%eax
+ adcl $0,%ebx
+ movl 12(%esi),%edx
+
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ebx
+ addl %eax,%ecx
+ adcl %edx,%ebp
+ movl 28(%esi),%eax
+ adcl $0,%ebx
+ movl %ecx,28(%edi)
+ movl 4(%esi),%edx
+
+
+ xorl %ecx,%ecx
+
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ecx
+ addl %eax,%ebp
+ adcl %edx,%ebx
+ movl 24(%esi),%eax
+ adcl $0,%ecx
+ movl 8(%esi),%edx
+
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ecx
+ addl %eax,%ebp
+ adcl %edx,%ebx
+ movl 20(%esi),%eax
+ adcl $0,%ecx
+ movl 12(%esi),%edx
+
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ecx
+ addl %eax,%ebp
+ adcl %edx,%ebx
+ movl 16(%esi),%eax
+ adcl $0,%ecx
+
+ mull %eax
+ addl %eax,%ebp
+ adcl %edx,%ebx
+ movl 8(%esi),%edx
+ adcl $0,%ecx
+ movl %ebp,32(%edi)
+ movl 28(%esi),%eax
+
+
+ xorl %ebp,%ebp
+
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ebp
+ addl %eax,%ebx
+ adcl %edx,%ecx
+ movl 24(%esi),%eax
+ adcl $0,%ebp
+ movl 12(%esi),%edx
+
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ebp
+ addl %eax,%ebx
+ adcl %edx,%ecx
+ movl 20(%esi),%eax
+ adcl $0,%ebp
+ movl 16(%esi),%edx
+
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ebp
+ addl %eax,%ebx
+ adcl %edx,%ecx
+ movl 28(%esi),%eax
+ adcl $0,%ebp
+ movl %ebx,36(%edi)
+ movl 12(%esi),%edx
+
+
+ xorl %ebx,%ebx
+
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ebx
+ addl %eax,%ecx
+ adcl %edx,%ebp
+ movl 24(%esi),%eax
+ adcl $0,%ebx
+ movl 16(%esi),%edx
+
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ebx
+ addl %eax,%ecx
+ adcl %edx,%ebp
+ movl 20(%esi),%eax
+ adcl $0,%ebx
+
+ mull %eax
+ addl %eax,%ecx
+ adcl %edx,%ebp
+ movl 16(%esi),%edx
+ adcl $0,%ebx
+ movl %ecx,40(%edi)
+ movl 28(%esi),%eax
+
+
+ xorl %ecx,%ecx
+
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ecx
+ addl %eax,%ebp
+ adcl %edx,%ebx
+ movl 24(%esi),%eax
+ adcl $0,%ecx
+ movl 20(%esi),%edx
+
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ecx
+ addl %eax,%ebp
+ adcl %edx,%ebx
+ movl 28(%esi),%eax
+ adcl $0,%ecx
+ movl %ebp,44(%edi)
+ movl 20(%esi),%edx
+
+
+ xorl %ebp,%ebp
+
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ebp
+ addl %eax,%ebx
+ adcl %edx,%ecx
+ movl 24(%esi),%eax
+ adcl $0,%ebp
+
+ mull %eax
+ addl %eax,%ebx
+ adcl %edx,%ecx
+ movl 24(%esi),%edx
+ adcl $0,%ebp
+ movl %ebx,48(%edi)
+ movl 28(%esi),%eax
+
+
+ xorl %ebx,%ebx
+
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ebx
+ addl %eax,%ecx
+ adcl %edx,%ebp
+ movl 28(%esi),%eax
+ adcl $0,%ebx
+ movl %ecx,52(%edi)
+
+
+ xorl %ecx,%ecx
+
+ mull %eax
+ addl %eax,%ebp
+ adcl %edx,%ebx
+ adcl $0,%ecx
+ movl %ebp,56(%edi)
+
+ movl %ebx,60(%edi)
+ popl %ebx
+ popl %ebp
+ popl %edi
+ popl %esi
+ ret
+.size bn_sqr_comba8,.-.L_bn_sqr_comba8_begin
+.globl bn_sqr_comba4
+.hidden bn_sqr_comba4
+.type bn_sqr_comba4,@function
+.align 16
+bn_sqr_comba4:
+.L_bn_sqr_comba4_begin:
+ pushl %esi
+ pushl %edi
+ pushl %ebp
+ pushl %ebx
+ movl 20(%esp),%edi
+ movl 24(%esp),%esi
+ xorl %ebx,%ebx
+ xorl %ecx,%ecx
+ movl (%esi),%eax
+
+ xorl %ebp,%ebp
+
+ mull %eax
+ addl %eax,%ebx
+ adcl %edx,%ecx
+ movl (%esi),%edx
+ adcl $0,%ebp
+ movl %ebx,(%edi)
+ movl 4(%esi),%eax
+
+
+ xorl %ebx,%ebx
+
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ebx
+ addl %eax,%ecx
+ adcl %edx,%ebp
+ movl 8(%esi),%eax
+ adcl $0,%ebx
+ movl %ecx,4(%edi)
+ movl (%esi),%edx
+
+
+ xorl %ecx,%ecx
+
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ecx
+ addl %eax,%ebp
+ adcl %edx,%ebx
+ movl 4(%esi),%eax
+ adcl $0,%ecx
+
+ mull %eax
+ addl %eax,%ebp
+ adcl %edx,%ebx
+ movl (%esi),%edx
+ adcl $0,%ecx
+ movl %ebp,8(%edi)
+ movl 12(%esi),%eax
+
+
+ xorl %ebp,%ebp
+
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ebp
+ addl %eax,%ebx
+ adcl %edx,%ecx
+ movl 8(%esi),%eax
+ adcl $0,%ebp
+ movl 4(%esi),%edx
+
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ebp
+ addl %eax,%ebx
+ adcl %edx,%ecx
+ movl 12(%esi),%eax
+ adcl $0,%ebp
+ movl %ebx,12(%edi)
+ movl 4(%esi),%edx
+
+
+ xorl %ebx,%ebx
+
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ebx
+ addl %eax,%ecx
+ adcl %edx,%ebp
+ movl 8(%esi),%eax
+ adcl $0,%ebx
+
+ mull %eax
+ addl %eax,%ecx
+ adcl %edx,%ebp
+ movl 8(%esi),%edx
+ adcl $0,%ebx
+ movl %ecx,16(%edi)
+ movl 12(%esi),%eax
+
+
+ xorl %ecx,%ecx
+
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ecx
+ addl %eax,%ebp
+ adcl %edx,%ebx
+ movl 12(%esi),%eax
+ adcl $0,%ecx
+ movl %ebp,20(%edi)
+
+
+ xorl %ebp,%ebp
+
+ mull %eax
+ addl %eax,%ebx
+ adcl %edx,%ecx
+ adcl $0,%ebp
+ movl %ebx,24(%edi)
+
+ movl %ecx,28(%edi)
+ popl %ebx
+ popl %ebp
+ popl %edi
+ popl %esi
+ ret
+.size bn_sqr_comba4,.-.L_bn_sqr_comba4_begin
+#endif
diff --git a/linux-x86/crypto/bn/x86-mont.S b/linux-x86/crypto/bn/x86-mont.S
new file mode 100644
index 0000000..e2d23b3
--- /dev/null
+++ b/linux-x86/crypto/bn/x86-mont.S
@@ -0,0 +1,340 @@
+#if defined(__i386__)
+.file "src/crypto/bn/asm/x86-mont.S"
+.text
+.globl bn_mul_mont
+.hidden bn_mul_mont
+.type bn_mul_mont,@function
+.align 16
+bn_mul_mont:
+.L_bn_mul_mont_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ xorl %eax,%eax
+ movl 40(%esp),%edi
+ cmpl $4,%edi
+ jl .L000just_leave
+ leal 20(%esp),%esi
+ leal 24(%esp),%edx
+ movl %esp,%ebp
+ addl $2,%edi
+ negl %edi
+ leal -32(%esp,%edi,4),%esp
+ negl %edi
+ movl %esp,%eax
+ subl %edx,%eax
+ andl $2047,%eax
+ subl %eax,%esp
+ xorl %esp,%edx
+ andl $2048,%edx
+ xorl $2048,%edx
+ subl %edx,%esp
+ andl $-64,%esp
+ movl (%esi),%eax
+ movl 4(%esi),%ebx
+ movl 8(%esi),%ecx
+ movl 12(%esi),%edx
+ movl 16(%esi),%esi
+ movl (%esi),%esi
+ movl %eax,4(%esp)
+ movl %ebx,8(%esp)
+ movl %ecx,12(%esp)
+ movl %edx,16(%esp)
+ movl %esi,20(%esp)
+ leal -3(%edi),%ebx
+ movl %ebp,24(%esp)
+ movl 8(%esp),%esi
+ leal 1(%ebx),%ebp
+ movl 12(%esp),%edi
+ xorl %ecx,%ecx
+ movl %esi,%edx
+ andl $1,%ebp
+ subl %edi,%edx
+ leal 4(%edi,%ebx,4),%eax
+ orl %edx,%ebp
+ movl (%edi),%edi
+ jz .L001bn_sqr_mont
+ movl %eax,28(%esp)
+ movl (%esi),%eax
+ xorl %edx,%edx
+.align 16
+.L002mull:
+ movl %edx,%ebp
+ mull %edi
+ addl %eax,%ebp
+ leal 1(%ecx),%ecx
+ adcl $0,%edx
+ movl (%esi,%ecx,4),%eax
+ cmpl %ebx,%ecx
+ movl %ebp,28(%esp,%ecx,4)
+ jl .L002mull
+ movl %edx,%ebp
+ mull %edi
+ movl 20(%esp),%edi
+ addl %ebp,%eax
+ movl 16(%esp),%esi
+ adcl $0,%edx
+ imull 32(%esp),%edi
+ movl %eax,32(%esp,%ebx,4)
+ xorl %ecx,%ecx
+ movl %edx,36(%esp,%ebx,4)
+ movl %ecx,40(%esp,%ebx,4)
+ movl (%esi),%eax
+ mull %edi
+ addl 32(%esp),%eax
+ movl 4(%esi),%eax
+ adcl $0,%edx
+ incl %ecx
+ jmp .L0032ndmadd
+.align 16
+.L0041stmadd:
+ movl %edx,%ebp
+ mull %edi
+ addl 32(%esp,%ecx,4),%ebp
+ leal 1(%ecx),%ecx
+ adcl $0,%edx
+ addl %eax,%ebp
+ movl (%esi,%ecx,4),%eax
+ adcl $0,%edx
+ cmpl %ebx,%ecx
+ movl %ebp,28(%esp,%ecx,4)
+ jl .L0041stmadd
+ movl %edx,%ebp
+ mull %edi
+ addl 32(%esp,%ebx,4),%eax
+ movl 20(%esp),%edi
+ adcl $0,%edx
+ movl 16(%esp),%esi
+ addl %eax,%ebp
+ adcl $0,%edx
+ imull 32(%esp),%edi
+ xorl %ecx,%ecx
+ addl 36(%esp,%ebx,4),%edx
+ movl %ebp,32(%esp,%ebx,4)
+ adcl $0,%ecx
+ movl (%esi),%eax
+ movl %edx,36(%esp,%ebx,4)
+ movl %ecx,40(%esp,%ebx,4)
+ mull %edi
+ addl 32(%esp),%eax
+ movl 4(%esi),%eax
+ adcl $0,%edx
+ movl $1,%ecx
+.align 16
+.L0032ndmadd:
+ movl %edx,%ebp
+ mull %edi
+ addl 32(%esp,%ecx,4),%ebp
+ leal 1(%ecx),%ecx
+ adcl $0,%edx
+ addl %eax,%ebp
+ movl (%esi,%ecx,4),%eax
+ adcl $0,%edx
+ cmpl %ebx,%ecx
+ movl %ebp,24(%esp,%ecx,4)
+ jl .L0032ndmadd
+ movl %edx,%ebp
+ mull %edi
+ addl 32(%esp,%ebx,4),%ebp
+ adcl $0,%edx
+ addl %eax,%ebp
+ adcl $0,%edx
+ movl %ebp,28(%esp,%ebx,4)
+ xorl %eax,%eax
+ movl 12(%esp),%ecx
+ addl 36(%esp,%ebx,4),%edx
+ adcl 40(%esp,%ebx,4),%eax
+ leal 4(%ecx),%ecx
+ movl %edx,32(%esp,%ebx,4)
+ cmpl 28(%esp),%ecx
+ movl %eax,36(%esp,%ebx,4)
+ je .L005common_tail
+ movl (%ecx),%edi
+ movl 8(%esp),%esi
+ movl %ecx,12(%esp)
+ xorl %ecx,%ecx
+ xorl %edx,%edx
+ movl (%esi),%eax
+ jmp .L0041stmadd
+.align 16
+.L001bn_sqr_mont:
+ movl %ebx,(%esp)
+ movl %ecx,12(%esp)
+ movl %edi,%eax
+ mull %edi
+ movl %eax,32(%esp)
+ movl %edx,%ebx
+ shrl $1,%edx
+ andl $1,%ebx
+ incl %ecx
+.align 16
+.L006sqr:
+ movl (%esi,%ecx,4),%eax
+ movl %edx,%ebp
+ mull %edi
+ addl %ebp,%eax
+ leal 1(%ecx),%ecx
+ adcl $0,%edx
+ leal (%ebx,%eax,2),%ebp
+ shrl $31,%eax
+ cmpl (%esp),%ecx
+ movl %eax,%ebx
+ movl %ebp,28(%esp,%ecx,4)
+ jl .L006sqr
+ movl (%esi,%ecx,4),%eax
+ movl %edx,%ebp
+ mull %edi
+ addl %ebp,%eax
+ movl 20(%esp),%edi
+ adcl $0,%edx
+ movl 16(%esp),%esi
+ leal (%ebx,%eax,2),%ebp
+ imull 32(%esp),%edi
+ shrl $31,%eax
+ movl %ebp,32(%esp,%ecx,4)
+ leal (%eax,%edx,2),%ebp
+ movl (%esi),%eax
+ shrl $31,%edx
+ movl %ebp,36(%esp,%ecx,4)
+ movl %edx,40(%esp,%ecx,4)
+ mull %edi
+ addl 32(%esp),%eax
+ movl %ecx,%ebx
+ adcl $0,%edx
+ movl 4(%esi),%eax
+ movl $1,%ecx
+.align 16
+.L0073rdmadd:
+ movl %edx,%ebp
+ mull %edi
+ addl 32(%esp,%ecx,4),%ebp
+ adcl $0,%edx
+ addl %eax,%ebp
+ movl 4(%esi,%ecx,4),%eax
+ adcl $0,%edx
+ movl %ebp,28(%esp,%ecx,4)
+ movl %edx,%ebp
+ mull %edi
+ addl 36(%esp,%ecx,4),%ebp
+ leal 2(%ecx),%ecx
+ adcl $0,%edx
+ addl %eax,%ebp
+ movl (%esi,%ecx,4),%eax
+ adcl $0,%edx
+ cmpl %ebx,%ecx
+ movl %ebp,24(%esp,%ecx,4)
+ jl .L0073rdmadd
+ movl %edx,%ebp
+ mull %edi
+ addl 32(%esp,%ebx,4),%ebp
+ adcl $0,%edx
+ addl %eax,%ebp
+ adcl $0,%edx
+ movl %ebp,28(%esp,%ebx,4)
+ movl 12(%esp),%ecx
+ xorl %eax,%eax
+ movl 8(%esp),%esi
+ addl 36(%esp,%ebx,4),%edx
+ adcl 40(%esp,%ebx,4),%eax
+ movl %edx,32(%esp,%ebx,4)
+ cmpl %ebx,%ecx
+ movl %eax,36(%esp,%ebx,4)
+ je .L005common_tail
+ movl 4(%esi,%ecx,4),%edi
+ leal 1(%ecx),%ecx
+ movl %edi,%eax
+ movl %ecx,12(%esp)
+ mull %edi
+ addl 32(%esp,%ecx,4),%eax
+ adcl $0,%edx
+ movl %eax,32(%esp,%ecx,4)
+ xorl %ebp,%ebp
+ cmpl %ebx,%ecx
+ leal 1(%ecx),%ecx
+ je .L008sqrlast
+ movl %edx,%ebx
+ shrl $1,%edx
+ andl $1,%ebx
+.align 16
+.L009sqradd:
+ movl (%esi,%ecx,4),%eax
+ movl %edx,%ebp
+ mull %edi
+ addl %ebp,%eax
+ leal (%eax,%eax,1),%ebp
+ adcl $0,%edx
+ shrl $31,%eax
+ addl 32(%esp,%ecx,4),%ebp
+ leal 1(%ecx),%ecx
+ adcl $0,%eax
+ addl %ebx,%ebp
+ adcl $0,%eax
+ cmpl (%esp),%ecx
+ movl %ebp,28(%esp,%ecx,4)
+ movl %eax,%ebx
+ jle .L009sqradd
+ movl %edx,%ebp
+ addl %edx,%edx
+ shrl $31,%ebp
+ addl %ebx,%edx
+ adcl $0,%ebp
+.L008sqrlast:
+ movl 20(%esp),%edi
+ movl 16(%esp),%esi
+ imull 32(%esp),%edi
+ addl 32(%esp,%ecx,4),%edx
+ movl (%esi),%eax
+ adcl $0,%ebp
+ movl %edx,32(%esp,%ecx,4)
+ movl %ebp,36(%esp,%ecx,4)
+ mull %edi
+ addl 32(%esp),%eax
+ leal -1(%ecx),%ebx
+ adcl $0,%edx
+ movl $1,%ecx
+ movl 4(%esi),%eax
+ jmp .L0073rdmadd
+.align 16
+.L005common_tail:
+ movl 16(%esp),%ebp
+ movl 4(%esp),%edi
+ leal 32(%esp),%esi
+ movl (%esi),%eax
+ movl %ebx,%ecx
+ xorl %edx,%edx
+.align 16
+.L010sub:
+ sbbl (%ebp,%edx,4),%eax
+ movl %eax,(%edi,%edx,4)
+ decl %ecx
+ movl 4(%esi,%edx,4),%eax
+ leal 1(%edx),%edx
+ jge .L010sub
+ sbbl $0,%eax
+.align 16
+.L011copy:
+ movl (%esi,%ebx,4),%edx
+ movl (%edi,%ebx,4),%ebp
+ xorl %ebp,%edx
+ andl %eax,%edx
+ xorl %ebp,%edx
+ movl %ecx,(%esi,%ebx,4)
+ movl %edx,(%edi,%ebx,4)
+ decl %ebx
+ jge .L011copy
+ movl 24(%esp),%esp
+ movl $1,%eax
+.L000just_leave:
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.size bn_mul_mont,.-.L_bn_mul_mont_begin
+.byte 77,111,110,116,103,111,109,101,114,121,32,77,117,108,116,105
+.byte 112,108,105,99,97,116,105,111,110,32,102,111,114,32,120,56
+.byte 54,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121
+.byte 32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46
+.byte 111,114,103,62,0
+#endif
diff --git a/linux-x86/crypto/cpu-x86-asm.S b/linux-x86/crypto/cpu-x86-asm.S
new file mode 100644
index 0000000..b6f767b
--- /dev/null
+++ b/linux-x86/crypto/cpu-x86-asm.S
@@ -0,0 +1,314 @@
+#if defined(__i386__)
+.file "crypto/cpu-x86-asm.S"
+.text
+.globl OPENSSL_ia32_cpuid
+.hidden OPENSSL_ia32_cpuid
+.type OPENSSL_ia32_cpuid,@function
+.align 16
+OPENSSL_ia32_cpuid:
+.L_OPENSSL_ia32_cpuid_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ xorl %edx,%edx
+ pushfl
+ popl %eax
+ movl %eax,%ecx
+ xorl $2097152,%eax
+ pushl %eax
+ popfl
+ pushfl
+ popl %eax
+ xorl %eax,%ecx
+ xorl %eax,%eax
+ btl $21,%ecx
+ jnc .L000nocpuid
+ movl 20(%esp),%esi
+ movl %eax,8(%esi)
+ .byte 0x0f,0xa2
+ movl %eax,%edi
+ xorl %eax,%eax
+ cmpl $1970169159,%ebx
+ setne %al
+ movl %eax,%ebp
+ cmpl $1231384169,%edx
+ setne %al
+ orl %eax,%ebp
+ cmpl $1818588270,%ecx
+ setne %al
+ orl %eax,%ebp
+ jz .L001intel
+ cmpl $1752462657,%ebx
+ setne %al
+ movl %eax,%esi
+ cmpl $1769238117,%edx
+ setne %al
+ orl %eax,%esi
+ cmpl $1145913699,%ecx
+ setne %al
+ orl %eax,%esi
+ jnz .L001intel
+ movl $2147483648,%eax
+ .byte 0x0f,0xa2
+ cmpl $2147483649,%eax
+ jb .L001intel
+ movl %eax,%esi
+ movl $2147483649,%eax
+ .byte 0x0f,0xa2
+ orl %ecx,%ebp
+ andl $2049,%ebp
+ cmpl $2147483656,%esi
+ jb .L001intel
+ movl $2147483656,%eax
+ .byte 0x0f,0xa2
+ movzbl %cl,%esi
+ incl %esi
+ movl $1,%eax
+ xorl %ecx,%ecx
+ .byte 0x0f,0xa2
+ btl $28,%edx
+ jnc .L002generic
+ shrl $16,%ebx
+ andl $255,%ebx
+ cmpl %esi,%ebx
+ ja .L002generic
+ andl $4026531839,%edx
+ jmp .L002generic
+.L001intel:
+ cmpl $7,%edi
+ jb .L003cacheinfo
+ movl 20(%esp),%esi
+ movl $7,%eax
+ xorl %ecx,%ecx
+ .byte 0x0f,0xa2
+ movl %ebx,8(%esi)
+.L003cacheinfo:
+ cmpl $4,%edi
+ movl $-1,%edi
+ jb .L004nocacheinfo
+ movl $4,%eax
+ movl $0,%ecx
+ .byte 0x0f,0xa2
+ movl %eax,%edi
+ shrl $14,%edi
+ andl $4095,%edi
+.L004nocacheinfo:
+ movl $1,%eax
+ xorl %ecx,%ecx
+ .byte 0x0f,0xa2
+ andl $3220176895,%edx
+ cmpl $0,%ebp
+ jne .L005notintel
+ orl $1073741824,%edx
+ andb $15,%ah
+ cmpb $15,%ah
+ jne .L005notintel
+ orl $1048576,%edx
+.L005notintel:
+ btl $28,%edx
+ jnc .L002generic
+ andl $4026531839,%edx
+ cmpl $0,%edi
+ je .L002generic
+ orl $268435456,%edx
+ shrl $16,%ebx
+ cmpb $1,%bl
+ ja .L002generic
+ andl $4026531839,%edx
+.L002generic:
+ andl $2048,%ebp
+ andl $4294965247,%ecx
+ movl %edx,%esi
+ orl %ecx,%ebp
+ btl $27,%ecx
+ jnc .L006clear_avx
+ xorl %ecx,%ecx
+.byte 15,1,208
+ andl $6,%eax
+ cmpl $6,%eax
+ je .L007done
+ cmpl $2,%eax
+ je .L006clear_avx
+.L008clear_xmm:
+ andl $4261412861,%ebp
+ andl $4278190079,%esi
+.L006clear_avx:
+ andl $4026525695,%ebp
+ movl 20(%esp),%edi
+ andl $4294967263,8(%edi)
+.L007done:
+ movl %esi,%eax
+ movl %ebp,%edx
+.L000nocpuid:
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.size OPENSSL_ia32_cpuid,.-.L_OPENSSL_ia32_cpuid_begin
+.globl OPENSSL_rdtsc
+.hidden OPENSSL_rdtsc
+.type OPENSSL_rdtsc,@function
+.align 16
+OPENSSL_rdtsc:
+.L_OPENSSL_rdtsc_begin:
+ xorl %eax,%eax
+ xorl %edx,%edx
+ call .L009PIC_me_up
+.L009PIC_me_up:
+ popl %ecx
+ leal OPENSSL_ia32cap_P-.L009PIC_me_up(%ecx),%ecx
+ btl $4,(%ecx)
+ jnc .L010notsc
+ .byte 0x0f,0x31
+.L010notsc:
+ ret
+.size OPENSSL_rdtsc,.-.L_OPENSSL_rdtsc_begin
+.globl OPENSSL_instrument_halt
+.hidden OPENSSL_instrument_halt
+.type OPENSSL_instrument_halt,@function
+.align 16
+OPENSSL_instrument_halt:
+.L_OPENSSL_instrument_halt_begin:
+ call .L011PIC_me_up
+.L011PIC_me_up:
+ popl %ecx
+ leal OPENSSL_ia32cap_P-.L011PIC_me_up(%ecx),%ecx
+ btl $4,(%ecx)
+ jnc .L012nohalt
+.long 2421723150
+ andl $3,%eax
+ jnz .L012nohalt
+ pushfl
+ popl %eax
+ btl $9,%eax
+ jnc .L012nohalt
+ .byte 0x0f,0x31
+ pushl %edx
+ pushl %eax
+ hlt
+ .byte 0x0f,0x31
+ subl (%esp),%eax
+ sbbl 4(%esp),%edx
+ addl $8,%esp
+ ret
+.L012nohalt:
+ xorl %eax,%eax
+ xorl %edx,%edx
+ ret
+.size OPENSSL_instrument_halt,.-.L_OPENSSL_instrument_halt_begin
+.globl OPENSSL_far_spin
+.hidden OPENSSL_far_spin
+.type OPENSSL_far_spin,@function
+.align 16
+OPENSSL_far_spin:
+.L_OPENSSL_far_spin_begin:
+ pushfl
+ popl %eax
+ btl $9,%eax
+ jnc .L013nospin
+ movl 4(%esp),%eax
+ movl 8(%esp),%ecx
+.long 2430111262
+ xorl %eax,%eax
+ movl (%ecx),%edx
+ jmp .L014spin
+.align 16
+.L014spin:
+ incl %eax
+ cmpl (%ecx),%edx
+ je .L014spin
+.long 529567888
+ ret
+.L013nospin:
+ xorl %eax,%eax
+ xorl %edx,%edx
+ ret
+.size OPENSSL_far_spin,.-.L_OPENSSL_far_spin_begin
+.globl OPENSSL_wipe_cpu
+.hidden OPENSSL_wipe_cpu
+.type OPENSSL_wipe_cpu,@function
+.align 16
+OPENSSL_wipe_cpu:
+.L_OPENSSL_wipe_cpu_begin:
+ xorl %eax,%eax
+ xorl %edx,%edx
+ call .L015PIC_me_up
+.L015PIC_me_up:
+ popl %ecx
+ leal OPENSSL_ia32cap_P-.L015PIC_me_up(%ecx),%ecx
+ movl (%ecx),%ecx
+ btl $1,(%ecx)
+ jnc .L016no_x87
+.long 4007259865,4007259865,4007259865,4007259865,2430851995
+.L016no_x87:
+ leal 4(%esp),%eax
+ ret
+.size OPENSSL_wipe_cpu,.-.L_OPENSSL_wipe_cpu_begin
+.globl OPENSSL_atomic_add
+.hidden OPENSSL_atomic_add
+.type OPENSSL_atomic_add,@function
+.align 16
+OPENSSL_atomic_add:
+.L_OPENSSL_atomic_add_begin:
+ movl 4(%esp),%edx
+ movl 8(%esp),%ecx
+ pushl %ebx
+ nop
+ movl (%edx),%eax
+.L017spin:
+ leal (%eax,%ecx,1),%ebx
+ nop
+.long 447811568
+ jne .L017spin
+ movl %ebx,%eax
+ popl %ebx
+ ret
+.size OPENSSL_atomic_add,.-.L_OPENSSL_atomic_add_begin
+.globl OPENSSL_indirect_call
+.hidden OPENSSL_indirect_call
+.type OPENSSL_indirect_call,@function
+.align 16
+OPENSSL_indirect_call:
+.L_OPENSSL_indirect_call_begin:
+ pushl %ebp
+ movl %esp,%ebp
+ subl $28,%esp
+ movl 12(%ebp),%ecx
+ movl %ecx,(%esp)
+ movl 16(%ebp),%edx
+ movl %edx,4(%esp)
+ movl 20(%ebp),%eax
+ movl %eax,8(%esp)
+ movl 24(%ebp),%eax
+ movl %eax,12(%esp)
+ movl 28(%ebp),%eax
+ movl %eax,16(%esp)
+ movl 32(%ebp),%eax
+ movl %eax,20(%esp)
+ movl 36(%ebp),%eax
+ movl %eax,24(%esp)
+ call *8(%ebp)
+ movl %ebp,%esp
+ popl %ebp
+ ret
+.size OPENSSL_indirect_call,.-.L_OPENSSL_indirect_call_begin
+.globl OPENSSL_ia32_rdrand
+.hidden OPENSSL_ia32_rdrand
+.type OPENSSL_ia32_rdrand,@function
+.align 16
+OPENSSL_ia32_rdrand:
+.L_OPENSSL_ia32_rdrand_begin:
+ movl $8,%ecx
+.L018loop:
+.byte 15,199,240
+ jc .L019break
+ loop .L018loop
+.L019break:
+ cmpl $0,%eax
+ cmovel %ecx,%eax
+ ret
+.size OPENSSL_ia32_rdrand,.-.L_OPENSSL_ia32_rdrand_begin
+.hidden OPENSSL_ia32cap_P
+#endif
diff --git a/linux-x86/crypto/md5/md5-586.S b/linux-x86/crypto/md5/md5-586.S
new file mode 100644
index 0000000..734b941
--- /dev/null
+++ b/linux-x86/crypto/md5/md5-586.S
@@ -0,0 +1,682 @@
+#if defined(__i386__)
+.file "src/crypto/md5/asm/md5-586.S"
+.text
+.globl md5_block_asm_data_order
+.hidden md5_block_asm_data_order
+.type md5_block_asm_data_order,@function
+.align 16
+md5_block_asm_data_order:
+.L_md5_block_asm_data_order_begin:
+ pushl %esi
+ pushl %edi
+ movl 12(%esp),%edi
+ movl 16(%esp),%esi
+ movl 20(%esp),%ecx
+ pushl %ebp
+ shll $6,%ecx
+ pushl %ebx
+ addl %esi,%ecx
+ subl $64,%ecx
+ movl (%edi),%eax
+ pushl %ecx
+ movl 4(%edi),%ebx
+ movl 8(%edi),%ecx
+ movl 12(%edi),%edx
+.L000start:
+
+
+ movl %ecx,%edi
+ movl (%esi),%ebp
+
+ xorl %edx,%edi
+ andl %ebx,%edi
+ leal 3614090360(%eax,%ebp,1),%eax
+ xorl %edx,%edi
+ addl %edi,%eax
+ movl %ebx,%edi
+ roll $7,%eax
+ movl 4(%esi),%ebp
+ addl %ebx,%eax
+
+ xorl %ecx,%edi
+ andl %eax,%edi
+ leal 3905402710(%edx,%ebp,1),%edx
+ xorl %ecx,%edi
+ addl %edi,%edx
+ movl %eax,%edi
+ roll $12,%edx
+ movl 8(%esi),%ebp
+ addl %eax,%edx
+
+ xorl %ebx,%edi
+ andl %edx,%edi
+ leal 606105819(%ecx,%ebp,1),%ecx
+ xorl %ebx,%edi
+ addl %edi,%ecx
+ movl %edx,%edi
+ roll $17,%ecx
+ movl 12(%esi),%ebp
+ addl %edx,%ecx
+
+ xorl %eax,%edi
+ andl %ecx,%edi
+ leal 3250441966(%ebx,%ebp,1),%ebx
+ xorl %eax,%edi
+ addl %edi,%ebx
+ movl %ecx,%edi
+ roll $22,%ebx
+ movl 16(%esi),%ebp
+ addl %ecx,%ebx
+
+ xorl %edx,%edi
+ andl %ebx,%edi
+ leal 4118548399(%eax,%ebp,1),%eax
+ xorl %edx,%edi
+ addl %edi,%eax
+ movl %ebx,%edi
+ roll $7,%eax
+ movl 20(%esi),%ebp
+ addl %ebx,%eax
+
+ xorl %ecx,%edi
+ andl %eax,%edi
+ leal 1200080426(%edx,%ebp,1),%edx
+ xorl %ecx,%edi
+ addl %edi,%edx
+ movl %eax,%edi
+ roll $12,%edx
+ movl 24(%esi),%ebp
+ addl %eax,%edx
+
+ xorl %ebx,%edi
+ andl %edx,%edi
+ leal 2821735955(%ecx,%ebp,1),%ecx
+ xorl %ebx,%edi
+ addl %edi,%ecx
+ movl %edx,%edi
+ roll $17,%ecx
+ movl 28(%esi),%ebp
+ addl %edx,%ecx
+
+ xorl %eax,%edi
+ andl %ecx,%edi
+ leal 4249261313(%ebx,%ebp,1),%ebx
+ xorl %eax,%edi
+ addl %edi,%ebx
+ movl %ecx,%edi
+ roll $22,%ebx
+ movl 32(%esi),%ebp
+ addl %ecx,%ebx
+
+ xorl %edx,%edi
+ andl %ebx,%edi
+ leal 1770035416(%eax,%ebp,1),%eax
+ xorl %edx,%edi
+ addl %edi,%eax
+ movl %ebx,%edi
+ roll $7,%eax
+ movl 36(%esi),%ebp
+ addl %ebx,%eax
+
+ xorl %ecx,%edi
+ andl %eax,%edi
+ leal 2336552879(%edx,%ebp,1),%edx
+ xorl %ecx,%edi
+ addl %edi,%edx
+ movl %eax,%edi
+ roll $12,%edx
+ movl 40(%esi),%ebp
+ addl %eax,%edx
+
+ xorl %ebx,%edi
+ andl %edx,%edi
+ leal 4294925233(%ecx,%ebp,1),%ecx
+ xorl %ebx,%edi
+ addl %edi,%ecx
+ movl %edx,%edi
+ roll $17,%ecx
+ movl 44(%esi),%ebp
+ addl %edx,%ecx
+
+ xorl %eax,%edi
+ andl %ecx,%edi
+ leal 2304563134(%ebx,%ebp,1),%ebx
+ xorl %eax,%edi
+ addl %edi,%ebx
+ movl %ecx,%edi
+ roll $22,%ebx
+ movl 48(%esi),%ebp
+ addl %ecx,%ebx
+
+ xorl %edx,%edi
+ andl %ebx,%edi
+ leal 1804603682(%eax,%ebp,1),%eax
+ xorl %edx,%edi
+ addl %edi,%eax
+ movl %ebx,%edi
+ roll $7,%eax
+ movl 52(%esi),%ebp
+ addl %ebx,%eax
+
+ xorl %ecx,%edi
+ andl %eax,%edi
+ leal 4254626195(%edx,%ebp,1),%edx
+ xorl %ecx,%edi
+ addl %edi,%edx
+ movl %eax,%edi
+ roll $12,%edx
+ movl 56(%esi),%ebp
+ addl %eax,%edx
+
+ xorl %ebx,%edi
+ andl %edx,%edi
+ leal 2792965006(%ecx,%ebp,1),%ecx
+ xorl %ebx,%edi
+ addl %edi,%ecx
+ movl %edx,%edi
+ roll $17,%ecx
+ movl 60(%esi),%ebp
+ addl %edx,%ecx
+
+ xorl %eax,%edi
+ andl %ecx,%edi
+ leal 1236535329(%ebx,%ebp,1),%ebx
+ xorl %eax,%edi
+ addl %edi,%ebx
+ movl %ecx,%edi
+ roll $22,%ebx
+ movl 4(%esi),%ebp
+ addl %ecx,%ebx
+
+
+
+ leal 4129170786(%eax,%ebp,1),%eax
+ xorl %ebx,%edi
+ andl %edx,%edi
+ movl 24(%esi),%ebp
+ xorl %ecx,%edi
+ addl %edi,%eax
+ movl %ebx,%edi
+ roll $5,%eax
+ addl %ebx,%eax
+
+ leal 3225465664(%edx,%ebp,1),%edx
+ xorl %eax,%edi
+ andl %ecx,%edi
+ movl 44(%esi),%ebp
+ xorl %ebx,%edi
+ addl %edi,%edx
+ movl %eax,%edi
+ roll $9,%edx
+ addl %eax,%edx
+
+ leal 643717713(%ecx,%ebp,1),%ecx
+ xorl %edx,%edi
+ andl %ebx,%edi
+ movl (%esi),%ebp
+ xorl %eax,%edi
+ addl %edi,%ecx
+ movl %edx,%edi
+ roll $14,%ecx
+ addl %edx,%ecx
+
+ leal 3921069994(%ebx,%ebp,1),%ebx
+ xorl %ecx,%edi
+ andl %eax,%edi
+ movl 20(%esi),%ebp
+ xorl %edx,%edi
+ addl %edi,%ebx
+ movl %ecx,%edi
+ roll $20,%ebx
+ addl %ecx,%ebx
+
+ leal 3593408605(%eax,%ebp,1),%eax
+ xorl %ebx,%edi
+ andl %edx,%edi
+ movl 40(%esi),%ebp
+ xorl %ecx,%edi
+ addl %edi,%eax
+ movl %ebx,%edi
+ roll $5,%eax
+ addl %ebx,%eax
+
+ leal 38016083(%edx,%ebp,1),%edx
+ xorl %eax,%edi
+ andl %ecx,%edi
+ movl 60(%esi),%ebp
+ xorl %ebx,%edi
+ addl %edi,%edx
+ movl %eax,%edi
+ roll $9,%edx
+ addl %eax,%edx
+
+ leal 3634488961(%ecx,%ebp,1),%ecx
+ xorl %edx,%edi
+ andl %ebx,%edi
+ movl 16(%esi),%ebp
+ xorl %eax,%edi
+ addl %edi,%ecx
+ movl %edx,%edi
+ roll $14,%ecx
+ addl %edx,%ecx
+
+ leal 3889429448(%ebx,%ebp,1),%ebx
+ xorl %ecx,%edi
+ andl %eax,%edi
+ movl 36(%esi),%ebp
+ xorl %edx,%edi
+ addl %edi,%ebx
+ movl %ecx,%edi
+ roll $20,%ebx
+ addl %ecx,%ebx
+
+ leal 568446438(%eax,%ebp,1),%eax
+ xorl %ebx,%edi
+ andl %edx,%edi
+ movl 56(%esi),%ebp
+ xorl %ecx,%edi
+ addl %edi,%eax
+ movl %ebx,%edi
+ roll $5,%eax
+ addl %ebx,%eax
+
+ leal 3275163606(%edx,%ebp,1),%edx
+ xorl %eax,%edi
+ andl %ecx,%edi
+ movl 12(%esi),%ebp
+ xorl %ebx,%edi
+ addl %edi,%edx
+ movl %eax,%edi
+ roll $9,%edx
+ addl %eax,%edx
+
+ leal 4107603335(%ecx,%ebp,1),%ecx
+ xorl %edx,%edi
+ andl %ebx,%edi
+ movl 32(%esi),%ebp
+ xorl %eax,%edi
+ addl %edi,%ecx
+ movl %edx,%edi
+ roll $14,%ecx
+ addl %edx,%ecx
+
+ leal 1163531501(%ebx,%ebp,1),%ebx
+ xorl %ecx,%edi
+ andl %eax,%edi
+ movl 52(%esi),%ebp
+ xorl %edx,%edi
+ addl %edi,%ebx
+ movl %ecx,%edi
+ roll $20,%ebx
+ addl %ecx,%ebx
+
+ leal 2850285829(%eax,%ebp,1),%eax
+ xorl %ebx,%edi
+ andl %edx,%edi
+ movl 8(%esi),%ebp
+ xorl %ecx,%edi
+ addl %edi,%eax
+ movl %ebx,%edi
+ roll $5,%eax
+ addl %ebx,%eax
+
+ leal 4243563512(%edx,%ebp,1),%edx
+ xorl %eax,%edi
+ andl %ecx,%edi
+ movl 28(%esi),%ebp
+ xorl %ebx,%edi
+ addl %edi,%edx
+ movl %eax,%edi
+ roll $9,%edx
+ addl %eax,%edx
+
+ leal 1735328473(%ecx,%ebp,1),%ecx
+ xorl %edx,%edi
+ andl %ebx,%edi
+ movl 48(%esi),%ebp
+ xorl %eax,%edi
+ addl %edi,%ecx
+ movl %edx,%edi
+ roll $14,%ecx
+ addl %edx,%ecx
+
+ leal 2368359562(%ebx,%ebp,1),%ebx
+ xorl %ecx,%edi
+ andl %eax,%edi
+ movl 20(%esi),%ebp
+ xorl %edx,%edi
+ addl %edi,%ebx
+ movl %ecx,%edi
+ roll $20,%ebx
+ addl %ecx,%ebx
+
+
+
+ xorl %edx,%edi
+ xorl %ebx,%edi
+ leal 4294588738(%eax,%ebp,1),%eax
+ addl %edi,%eax
+ roll $4,%eax
+ movl 32(%esi),%ebp
+ movl %ebx,%edi
+
+ leal 2272392833(%edx,%ebp,1),%edx
+ addl %ebx,%eax
+ xorl %ecx,%edi
+ xorl %eax,%edi
+ movl 44(%esi),%ebp
+ addl %edi,%edx
+ movl %eax,%edi
+ roll $11,%edx
+ addl %eax,%edx
+
+ xorl %ebx,%edi
+ xorl %edx,%edi
+ leal 1839030562(%ecx,%ebp,1),%ecx
+ addl %edi,%ecx
+ roll $16,%ecx
+ movl 56(%esi),%ebp
+ movl %edx,%edi
+
+ leal 4259657740(%ebx,%ebp,1),%ebx
+ addl %edx,%ecx
+ xorl %eax,%edi
+ xorl %ecx,%edi
+ movl 4(%esi),%ebp
+ addl %edi,%ebx
+ movl %ecx,%edi
+ roll $23,%ebx
+ addl %ecx,%ebx
+
+ xorl %edx,%edi
+ xorl %ebx,%edi
+ leal 2763975236(%eax,%ebp,1),%eax
+ addl %edi,%eax
+ roll $4,%eax
+ movl 16(%esi),%ebp
+ movl %ebx,%edi
+
+ leal 1272893353(%edx,%ebp,1),%edx
+ addl %ebx,%eax
+ xorl %ecx,%edi
+ xorl %eax,%edi
+ movl 28(%esi),%ebp
+ addl %edi,%edx
+ movl %eax,%edi
+ roll $11,%edx
+ addl %eax,%edx
+
+ xorl %ebx,%edi
+ xorl %edx,%edi
+ leal 4139469664(%ecx,%ebp,1),%ecx
+ addl %edi,%ecx
+ roll $16,%ecx
+ movl 40(%esi),%ebp
+ movl %edx,%edi
+
+ leal 3200236656(%ebx,%ebp,1),%ebx
+ addl %edx,%ecx
+ xorl %eax,%edi
+ xorl %ecx,%edi
+ movl 52(%esi),%ebp
+ addl %edi,%ebx
+ movl %ecx,%edi
+ roll $23,%ebx
+ addl %ecx,%ebx
+
+ xorl %edx,%edi
+ xorl %ebx,%edi
+ leal 681279174(%eax,%ebp,1),%eax
+ addl %edi,%eax
+ roll $4,%eax
+ movl (%esi),%ebp
+ movl %ebx,%edi
+
+ leal 3936430074(%edx,%ebp,1),%edx
+ addl %ebx,%eax
+ xorl %ecx,%edi
+ xorl %eax,%edi
+ movl 12(%esi),%ebp
+ addl %edi,%edx
+ movl %eax,%edi
+ roll $11,%edx
+ addl %eax,%edx
+
+ xorl %ebx,%edi
+ xorl %edx,%edi
+ leal 3572445317(%ecx,%ebp,1),%ecx
+ addl %edi,%ecx
+ roll $16,%ecx
+ movl 24(%esi),%ebp
+ movl %edx,%edi
+
+ leal 76029189(%ebx,%ebp,1),%ebx
+ addl %edx,%ecx
+ xorl %eax,%edi
+ xorl %ecx,%edi
+ movl 36(%esi),%ebp
+ addl %edi,%ebx
+ movl %ecx,%edi
+ roll $23,%ebx
+ addl %ecx,%ebx
+
+ xorl %edx,%edi
+ xorl %ebx,%edi
+ leal 3654602809(%eax,%ebp,1),%eax
+ addl %edi,%eax
+ roll $4,%eax
+ movl 48(%esi),%ebp
+ movl %ebx,%edi
+
+ leal 3873151461(%edx,%ebp,1),%edx
+ addl %ebx,%eax
+ xorl %ecx,%edi
+ xorl %eax,%edi
+ movl 60(%esi),%ebp
+ addl %edi,%edx
+ movl %eax,%edi
+ roll $11,%edx
+ addl %eax,%edx
+
+ xorl %ebx,%edi
+ xorl %edx,%edi
+ leal 530742520(%ecx,%ebp,1),%ecx
+ addl %edi,%ecx
+ roll $16,%ecx
+ movl 8(%esi),%ebp
+ movl %edx,%edi
+
+ leal 3299628645(%ebx,%ebp,1),%ebx
+ addl %edx,%ecx
+ xorl %eax,%edi
+ xorl %ecx,%edi
+ movl (%esi),%ebp
+ addl %edi,%ebx
+ movl $-1,%edi
+ roll $23,%ebx
+ addl %ecx,%ebx
+
+
+
+ xorl %edx,%edi
+ orl %ebx,%edi
+ leal 4096336452(%eax,%ebp,1),%eax
+ xorl %ecx,%edi
+ movl 28(%esi),%ebp
+ addl %edi,%eax
+ movl $-1,%edi
+ roll $6,%eax
+ xorl %ecx,%edi
+ addl %ebx,%eax
+
+ orl %eax,%edi
+ leal 1126891415(%edx,%ebp,1),%edx
+ xorl %ebx,%edi
+ movl 56(%esi),%ebp
+ addl %edi,%edx
+ movl $-1,%edi
+ roll $10,%edx
+ xorl %ebx,%edi
+ addl %eax,%edx
+
+ orl %edx,%edi
+ leal 2878612391(%ecx,%ebp,1),%ecx
+ xorl %eax,%edi
+ movl 20(%esi),%ebp
+ addl %edi,%ecx
+ movl $-1,%edi
+ roll $15,%ecx
+ xorl %eax,%edi
+ addl %edx,%ecx
+
+ orl %ecx,%edi
+ leal 4237533241(%ebx,%ebp,1),%ebx
+ xorl %edx,%edi
+ movl 48(%esi),%ebp
+ addl %edi,%ebx
+ movl $-1,%edi
+ roll $21,%ebx
+ xorl %edx,%edi
+ addl %ecx,%ebx
+
+ orl %ebx,%edi
+ leal 1700485571(%eax,%ebp,1),%eax
+ xorl %ecx,%edi
+ movl 12(%esi),%ebp
+ addl %edi,%eax
+ movl $-1,%edi
+ roll $6,%eax
+ xorl %ecx,%edi
+ addl %ebx,%eax
+
+ orl %eax,%edi
+ leal 2399980690(%edx,%ebp,1),%edx
+ xorl %ebx,%edi
+ movl 40(%esi),%ebp
+ addl %edi,%edx
+ movl $-1,%edi
+ roll $10,%edx
+ xorl %ebx,%edi
+ addl %eax,%edx
+
+ orl %edx,%edi
+ leal 4293915773(%ecx,%ebp,1),%ecx
+ xorl %eax,%edi
+ movl 4(%esi),%ebp
+ addl %edi,%ecx
+ movl $-1,%edi
+ roll $15,%ecx
+ xorl %eax,%edi
+ addl %edx,%ecx
+
+ orl %ecx,%edi
+ leal 2240044497(%ebx,%ebp,1),%ebx
+ xorl %edx,%edi
+ movl 32(%esi),%ebp
+ addl %edi,%ebx
+ movl $-1,%edi
+ roll $21,%ebx
+ xorl %edx,%edi
+ addl %ecx,%ebx
+
+ orl %ebx,%edi
+ leal 1873313359(%eax,%ebp,1),%eax
+ xorl %ecx,%edi
+ movl 60(%esi),%ebp
+ addl %edi,%eax
+ movl $-1,%edi
+ roll $6,%eax
+ xorl %ecx,%edi
+ addl %ebx,%eax
+
+ orl %eax,%edi
+ leal 4264355552(%edx,%ebp,1),%edx
+ xorl %ebx,%edi
+ movl 24(%esi),%ebp
+ addl %edi,%edx
+ movl $-1,%edi
+ roll $10,%edx
+ xorl %ebx,%edi
+ addl %eax,%edx
+
+ orl %edx,%edi
+ leal 2734768916(%ecx,%ebp,1),%ecx
+ xorl %eax,%edi
+ movl 52(%esi),%ebp
+ addl %edi,%ecx
+ movl $-1,%edi
+ roll $15,%ecx
+ xorl %eax,%edi
+ addl %edx,%ecx
+
+ orl %ecx,%edi
+ leal 1309151649(%ebx,%ebp,1),%ebx
+ xorl %edx,%edi
+ movl 16(%esi),%ebp
+ addl %edi,%ebx
+ movl $-1,%edi
+ roll $21,%ebx
+ xorl %edx,%edi
+ addl %ecx,%ebx
+
+ orl %ebx,%edi
+ leal 4149444226(%eax,%ebp,1),%eax
+ xorl %ecx,%edi
+ movl 44(%esi),%ebp
+ addl %edi,%eax
+ movl $-1,%edi
+ roll $6,%eax
+ xorl %ecx,%edi
+ addl %ebx,%eax
+
+ orl %eax,%edi
+ leal 3174756917(%edx,%ebp,1),%edx
+ xorl %ebx,%edi
+ movl 8(%esi),%ebp
+ addl %edi,%edx
+ movl $-1,%edi
+ roll $10,%edx
+ xorl %ebx,%edi
+ addl %eax,%edx
+
+ orl %edx,%edi
+ leal 718787259(%ecx,%ebp,1),%ecx
+ xorl %eax,%edi
+ movl 36(%esi),%ebp
+ addl %edi,%ecx
+ movl $-1,%edi
+ roll $15,%ecx
+ xorl %eax,%edi
+ addl %edx,%ecx
+
+ orl %ecx,%edi
+ leal 3951481745(%ebx,%ebp,1),%ebx
+ xorl %edx,%edi
+ movl 24(%esp),%ebp
+ addl %edi,%ebx
+ addl $64,%esi
+ roll $21,%ebx
+ movl (%ebp),%edi
+ addl %ecx,%ebx
+ addl %edi,%eax
+ movl 4(%ebp),%edi
+ addl %edi,%ebx
+ movl 8(%ebp),%edi
+ addl %edi,%ecx
+ movl 12(%ebp),%edi
+ addl %edi,%edx
+ movl %eax,(%ebp)
+ movl %ebx,4(%ebp)
+ movl (%esp),%edi
+ movl %ecx,8(%ebp)
+ movl %edx,12(%ebp)
+ cmpl %esi,%edi
+ jae .L000start
+ popl %eax
+ popl %ebx
+ popl %ebp
+ popl %edi
+ popl %esi
+ ret
+.size md5_block_asm_data_order,.-.L_md5_block_asm_data_order_begin
+#endif
diff --git a/linux-x86/crypto/modes/ghash-x86.S b/linux-x86/crypto/modes/ghash-x86.S
new file mode 100644
index 0000000..2872088
--- /dev/null
+++ b/linux-x86/crypto/modes/ghash-x86.S
@@ -0,0 +1,1274 @@
+#if defined(__i386__)
+.file "ghash-x86.S"
+.text
+.globl gcm_gmult_4bit_x86
+.hidden gcm_gmult_4bit_x86
+.type gcm_gmult_4bit_x86,@function
+.align 16
+gcm_gmult_4bit_x86:
+.L_gcm_gmult_4bit_x86_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ subl $84,%esp
+ movl 104(%esp),%edi
+ movl 108(%esp),%esi
+ movl (%edi),%ebp
+ movl 4(%edi),%edx
+ movl 8(%edi),%ecx
+ movl 12(%edi),%ebx
+ movl $0,16(%esp)
+ movl $471859200,20(%esp)
+ movl $943718400,24(%esp)
+ movl $610271232,28(%esp)
+ movl $1887436800,32(%esp)
+ movl $1822425088,36(%esp)
+ movl $1220542464,40(%esp)
+ movl $1423966208,44(%esp)
+ movl $3774873600,48(%esp)
+ movl $4246732800,52(%esp)
+ movl $3644850176,56(%esp)
+ movl $3311403008,60(%esp)
+ movl $2441084928,64(%esp)
+ movl $2376073216,68(%esp)
+ movl $2847932416,72(%esp)
+ movl $3051356160,76(%esp)
+ movl %ebp,(%esp)
+ movl %edx,4(%esp)
+ movl %ecx,8(%esp)
+ movl %ebx,12(%esp)
+ shrl $20,%ebx
+ andl $240,%ebx
+ movl 4(%esi,%ebx,1),%ebp
+ movl (%esi,%ebx,1),%edx
+ movl 12(%esi,%ebx,1),%ecx
+ movl 8(%esi,%ebx,1),%ebx
+ xorl %eax,%eax
+ movl $15,%edi
+ jmp .L000x86_loop
+.align 16
+.L000x86_loop:
+ movb %bl,%al
+ shrdl $4,%ecx,%ebx
+ andb $15,%al
+ shrdl $4,%edx,%ecx
+ shrdl $4,%ebp,%edx
+ shrl $4,%ebp
+ xorl 16(%esp,%eax,4),%ebp
+ movb (%esp,%edi,1),%al
+ andb $240,%al
+ xorl 8(%esi,%eax,1),%ebx
+ xorl 12(%esi,%eax,1),%ecx
+ xorl (%esi,%eax,1),%edx
+ xorl 4(%esi,%eax,1),%ebp
+ decl %edi
+ js .L001x86_break
+ movb %bl,%al
+ shrdl $4,%ecx,%ebx
+ andb $15,%al
+ shrdl $4,%edx,%ecx
+ shrdl $4,%ebp,%edx
+ shrl $4,%ebp
+ xorl 16(%esp,%eax,4),%ebp
+ movb (%esp,%edi,1),%al
+ shlb $4,%al
+ xorl 8(%esi,%eax,1),%ebx
+ xorl 12(%esi,%eax,1),%ecx
+ xorl (%esi,%eax,1),%edx
+ xorl 4(%esi,%eax,1),%ebp
+ jmp .L000x86_loop
+.align 16
+.L001x86_break:
+ bswap %ebx
+ bswap %ecx
+ bswap %edx
+ bswap %ebp
+ movl 104(%esp),%edi
+ movl %ebx,12(%edi)
+ movl %ecx,8(%edi)
+ movl %edx,4(%edi)
+ movl %ebp,(%edi)
+ addl $84,%esp
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.size gcm_gmult_4bit_x86,.-.L_gcm_gmult_4bit_x86_begin
+.globl gcm_ghash_4bit_x86
+.hidden gcm_ghash_4bit_x86
+.type gcm_ghash_4bit_x86,@function
+.align 16
+gcm_ghash_4bit_x86:
+.L_gcm_ghash_4bit_x86_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ subl $84,%esp
+ movl 104(%esp),%ebx
+ movl 108(%esp),%esi
+ movl 112(%esp),%edi
+ movl 116(%esp),%ecx
+ addl %edi,%ecx
+ movl %ecx,116(%esp)
+ movl (%ebx),%ebp
+ movl 4(%ebx),%edx
+ movl 8(%ebx),%ecx
+ movl 12(%ebx),%ebx
+ movl $0,16(%esp)
+ movl $471859200,20(%esp)
+ movl $943718400,24(%esp)
+ movl $610271232,28(%esp)
+ movl $1887436800,32(%esp)
+ movl $1822425088,36(%esp)
+ movl $1220542464,40(%esp)
+ movl $1423966208,44(%esp)
+ movl $3774873600,48(%esp)
+ movl $4246732800,52(%esp)
+ movl $3644850176,56(%esp)
+ movl $3311403008,60(%esp)
+ movl $2441084928,64(%esp)
+ movl $2376073216,68(%esp)
+ movl $2847932416,72(%esp)
+ movl $3051356160,76(%esp)
+.align 16
+.L002x86_outer_loop:
+ xorl 12(%edi),%ebx
+ xorl 8(%edi),%ecx
+ xorl 4(%edi),%edx
+ xorl (%edi),%ebp
+ movl %ebx,12(%esp)
+ movl %ecx,8(%esp)
+ movl %edx,4(%esp)
+ movl %ebp,(%esp)
+ shrl $20,%ebx
+ andl $240,%ebx
+ movl 4(%esi,%ebx,1),%ebp
+ movl (%esi,%ebx,1),%edx
+ movl 12(%esi,%ebx,1),%ecx
+ movl 8(%esi,%ebx,1),%ebx
+ xorl %eax,%eax
+ movl $15,%edi
+ jmp .L003x86_loop
+.align 16
+.L003x86_loop:
+ movb %bl,%al
+ shrdl $4,%ecx,%ebx
+ andb $15,%al
+ shrdl $4,%edx,%ecx
+ shrdl $4,%ebp,%edx
+ shrl $4,%ebp
+ xorl 16(%esp,%eax,4),%ebp
+ movb (%esp,%edi,1),%al
+ andb $240,%al
+ xorl 8(%esi,%eax,1),%ebx
+ xorl 12(%esi,%eax,1),%ecx
+ xorl (%esi,%eax,1),%edx
+ xorl 4(%esi,%eax,1),%ebp
+ decl %edi
+ js .L004x86_break
+ movb %bl,%al
+ shrdl $4,%ecx,%ebx
+ andb $15,%al
+ shrdl $4,%edx,%ecx
+ shrdl $4,%ebp,%edx
+ shrl $4,%ebp
+ xorl 16(%esp,%eax,4),%ebp
+ movb (%esp,%edi,1),%al
+ shlb $4,%al
+ xorl 8(%esi,%eax,1),%ebx
+ xorl 12(%esi,%eax,1),%ecx
+ xorl (%esi,%eax,1),%edx
+ xorl 4(%esi,%eax,1),%ebp
+ jmp .L003x86_loop
+.align 16
+.L004x86_break:
+ bswap %ebx
+ bswap %ecx
+ bswap %edx
+ bswap %ebp
+ movl 112(%esp),%edi
+ leal 16(%edi),%edi
+ cmpl 116(%esp),%edi
+ movl %edi,112(%esp)
+ jb .L002x86_outer_loop
+ movl 104(%esp),%edi
+ movl %ebx,12(%edi)
+ movl %ecx,8(%edi)
+ movl %edx,4(%edi)
+ movl %ebp,(%edi)
+ addl $84,%esp
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.size gcm_ghash_4bit_x86,.-.L_gcm_ghash_4bit_x86_begin
+.globl gcm_gmult_4bit_mmx
+.hidden gcm_gmult_4bit_mmx
+.type gcm_gmult_4bit_mmx,@function
+.align 16
+gcm_gmult_4bit_mmx:
+.L_gcm_gmult_4bit_mmx_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ movl 20(%esp),%edi
+ movl 24(%esp),%esi
+ call .L005pic_point
+.L005pic_point:
+ popl %eax
+ leal .Lrem_4bit-.L005pic_point(%eax),%eax
+ movzbl 15(%edi),%ebx
+ xorl %ecx,%ecx
+ movl %ebx,%edx
+ movb %dl,%cl
+ movl $14,%ebp
+ shlb $4,%cl
+ andl $240,%edx
+ movq 8(%esi,%ecx,1),%mm0
+ movq (%esi,%ecx,1),%mm1
+ movd %mm0,%ebx
+ jmp .L006mmx_loop
+.align 16
+.L006mmx_loop:
+ psrlq $4,%mm0
+ andl $15,%ebx
+ movq %mm1,%mm2
+ psrlq $4,%mm1
+ pxor 8(%esi,%edx,1),%mm0
+ movb (%edi,%ebp,1),%cl
+ psllq $60,%mm2
+ pxor (%eax,%ebx,8),%mm1
+ decl %ebp
+ movd %mm0,%ebx
+ pxor (%esi,%edx,1),%mm1
+ movl %ecx,%edx
+ pxor %mm2,%mm0
+ js .L007mmx_break
+ shlb $4,%cl
+ andl $15,%ebx
+ psrlq $4,%mm0
+ andl $240,%edx
+ movq %mm1,%mm2
+ psrlq $4,%mm1
+ pxor 8(%esi,%ecx,1),%mm0
+ psllq $60,%mm2
+ pxor (%eax,%ebx,8),%mm1
+ movd %mm0,%ebx
+ pxor (%esi,%ecx,1),%mm1
+ pxor %mm2,%mm0
+ jmp .L006mmx_loop
+.align 16
+.L007mmx_break:
+ shlb $4,%cl
+ andl $15,%ebx
+ psrlq $4,%mm0
+ andl $240,%edx
+ movq %mm1,%mm2
+ psrlq $4,%mm1
+ pxor 8(%esi,%ecx,1),%mm0
+ psllq $60,%mm2
+ pxor (%eax,%ebx,8),%mm1
+ movd %mm0,%ebx
+ pxor (%esi,%ecx,1),%mm1
+ pxor %mm2,%mm0
+ psrlq $4,%mm0
+ andl $15,%ebx
+ movq %mm1,%mm2
+ psrlq $4,%mm1
+ pxor 8(%esi,%edx,1),%mm0
+ psllq $60,%mm2
+ pxor (%eax,%ebx,8),%mm1
+ movd %mm0,%ebx
+ pxor (%esi,%edx,1),%mm1
+ pxor %mm2,%mm0
+ psrlq $32,%mm0
+ movd %mm1,%edx
+ psrlq $32,%mm1
+ movd %mm0,%ecx
+ movd %mm1,%ebp
+ bswap %ebx
+ bswap %edx
+ bswap %ecx
+ bswap %ebp
+ emms
+ movl %ebx,12(%edi)
+ movl %edx,4(%edi)
+ movl %ecx,8(%edi)
+ movl %ebp,(%edi)
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.size gcm_gmult_4bit_mmx,.-.L_gcm_gmult_4bit_mmx_begin
+.globl gcm_ghash_4bit_mmx
+.hidden gcm_ghash_4bit_mmx
+.type gcm_ghash_4bit_mmx,@function
+.align 16
+gcm_ghash_4bit_mmx:
+.L_gcm_ghash_4bit_mmx_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ movl 20(%esp),%eax
+ movl 24(%esp),%ebx
+ movl 28(%esp),%ecx
+ movl 32(%esp),%edx
+ movl %esp,%ebp
+ call .L008pic_point
+.L008pic_point:
+ popl %esi
+ leal .Lrem_8bit-.L008pic_point(%esi),%esi
+ subl $544,%esp
+ andl $-64,%esp
+ subl $16,%esp
+ addl %ecx,%edx
+ movl %eax,544(%esp)
+ movl %edx,552(%esp)
+ movl %ebp,556(%esp)
+ addl $128,%ebx
+ leal 144(%esp),%edi
+ leal 400(%esp),%ebp
+ movl -120(%ebx),%edx
+ movq -120(%ebx),%mm0
+ movq -128(%ebx),%mm3
+ shll $4,%edx
+ movb %dl,(%esp)
+ movl -104(%ebx),%edx
+ movq -104(%ebx),%mm2
+ movq -112(%ebx),%mm5
+ movq %mm0,-128(%edi)
+ psrlq $4,%mm0
+ movq %mm3,(%edi)
+ movq %mm3,%mm7
+ psrlq $4,%mm3
+ shll $4,%edx
+ movb %dl,1(%esp)
+ movl -88(%ebx),%edx
+ movq -88(%ebx),%mm1
+ psllq $60,%mm7
+ movq -96(%ebx),%mm4
+ por %mm7,%mm0
+ movq %mm2,-120(%edi)
+ psrlq $4,%mm2
+ movq %mm5,8(%edi)
+ movq %mm5,%mm6
+ movq %mm0,-128(%ebp)
+ psrlq $4,%mm5
+ movq %mm3,(%ebp)
+ shll $4,%edx
+ movb %dl,2(%esp)
+ movl -72(%ebx),%edx
+ movq -72(%ebx),%mm0
+ psllq $60,%mm6
+ movq -80(%ebx),%mm3
+ por %mm6,%mm2
+ movq %mm1,-112(%edi)
+ psrlq $4,%mm1
+ movq %mm4,16(%edi)
+ movq %mm4,%mm7
+ movq %mm2,-120(%ebp)
+ psrlq $4,%mm4
+ movq %mm5,8(%ebp)
+ shll $4,%edx
+ movb %dl,3(%esp)
+ movl -56(%ebx),%edx
+ movq -56(%ebx),%mm2
+ psllq $60,%mm7
+ movq -64(%ebx),%mm5
+ por %mm7,%mm1
+ movq %mm0,-104(%edi)
+ psrlq $4,%mm0
+ movq %mm3,24(%edi)
+ movq %mm3,%mm6
+ movq %mm1,-112(%ebp)
+ psrlq $4,%mm3
+ movq %mm4,16(%ebp)
+ shll $4,%edx
+ movb %dl,4(%esp)
+ movl -40(%ebx),%edx
+ movq -40(%ebx),%mm1
+ psllq $60,%mm6
+ movq -48(%ebx),%mm4
+ por %mm6,%mm0
+ movq %mm2,-96(%edi)
+ psrlq $4,%mm2
+ movq %mm5,32(%edi)
+ movq %mm5,%mm7
+ movq %mm0,-104(%ebp)
+ psrlq $4,%mm5
+ movq %mm3,24(%ebp)
+ shll $4,%edx
+ movb %dl,5(%esp)
+ movl -24(%ebx),%edx
+ movq -24(%ebx),%mm0
+ psllq $60,%mm7
+ movq -32(%ebx),%mm3
+ por %mm7,%mm2
+ movq %mm1,-88(%edi)
+ psrlq $4,%mm1
+ movq %mm4,40(%edi)
+ movq %mm4,%mm6
+ movq %mm2,-96(%ebp)
+ psrlq $4,%mm4
+ movq %mm5,32(%ebp)
+ shll $4,%edx
+ movb %dl,6(%esp)
+ movl -8(%ebx),%edx
+ movq -8(%ebx),%mm2
+ psllq $60,%mm6
+ movq -16(%ebx),%mm5
+ por %mm6,%mm1
+ movq %mm0,-80(%edi)
+ psrlq $4,%mm0
+ movq %mm3,48(%edi)
+ movq %mm3,%mm7
+ movq %mm1,-88(%ebp)
+ psrlq $4,%mm3
+ movq %mm4,40(%ebp)
+ shll $4,%edx
+ movb %dl,7(%esp)
+ movl 8(%ebx),%edx
+ movq 8(%ebx),%mm1
+ psllq $60,%mm7
+ movq (%ebx),%mm4
+ por %mm7,%mm0
+ movq %mm2,-72(%edi)
+ psrlq $4,%mm2
+ movq %mm5,56(%edi)
+ movq %mm5,%mm6
+ movq %mm0,-80(%ebp)
+ psrlq $4,%mm5
+ movq %mm3,48(%ebp)
+ shll $4,%edx
+ movb %dl,8(%esp)
+ movl 24(%ebx),%edx
+ movq 24(%ebx),%mm0
+ psllq $60,%mm6
+ movq 16(%ebx),%mm3
+ por %mm6,%mm2
+ movq %mm1,-64(%edi)
+ psrlq $4,%mm1
+ movq %mm4,64(%edi)
+ movq %mm4,%mm7
+ movq %mm2,-72(%ebp)
+ psrlq $4,%mm4
+ movq %mm5,56(%ebp)
+ shll $4,%edx
+ movb %dl,9(%esp)
+ movl 40(%ebx),%edx
+ movq 40(%ebx),%mm2
+ psllq $60,%mm7
+ movq 32(%ebx),%mm5
+ por %mm7,%mm1
+ movq %mm0,-56(%edi)
+ psrlq $4,%mm0
+ movq %mm3,72(%edi)
+ movq %mm3,%mm6
+ movq %mm1,-64(%ebp)
+ psrlq $4,%mm3
+ movq %mm4,64(%ebp)
+ shll $4,%edx
+ movb %dl,10(%esp)
+ movl 56(%ebx),%edx
+ movq 56(%ebx),%mm1
+ psllq $60,%mm6
+ movq 48(%ebx),%mm4
+ por %mm6,%mm0
+ movq %mm2,-48(%edi)
+ psrlq $4,%mm2
+ movq %mm5,80(%edi)
+ movq %mm5,%mm7
+ movq %mm0,-56(%ebp)
+ psrlq $4,%mm5
+ movq %mm3,72(%ebp)
+ shll $4,%edx
+ movb %dl,11(%esp)
+ movl 72(%ebx),%edx
+ movq 72(%ebx),%mm0
+ psllq $60,%mm7
+ movq 64(%ebx),%mm3
+ por %mm7,%mm2
+ movq %mm1,-40(%edi)
+ psrlq $4,%mm1
+ movq %mm4,88(%edi)
+ movq %mm4,%mm6
+ movq %mm2,-48(%ebp)
+ psrlq $4,%mm4
+ movq %mm5,80(%ebp)
+ shll $4,%edx
+ movb %dl,12(%esp)
+ movl 88(%ebx),%edx
+ movq 88(%ebx),%mm2
+ psllq $60,%mm6
+ movq 80(%ebx),%mm5
+ por %mm6,%mm1
+ movq %mm0,-32(%edi)
+ psrlq $4,%mm0
+ movq %mm3,96(%edi)
+ movq %mm3,%mm7
+ movq %mm1,-40(%ebp)
+ psrlq $4,%mm3
+ movq %mm4,88(%ebp)
+ shll $4,%edx
+ movb %dl,13(%esp)
+ movl 104(%ebx),%edx
+ movq 104(%ebx),%mm1
+ psllq $60,%mm7
+ movq 96(%ebx),%mm4
+ por %mm7,%mm0
+ movq %mm2,-24(%edi)
+ psrlq $4,%mm2
+ movq %mm5,104(%edi)
+ movq %mm5,%mm6
+ movq %mm0,-32(%ebp)
+ psrlq $4,%mm5
+ movq %mm3,96(%ebp)
+ shll $4,%edx
+ movb %dl,14(%esp)
+ movl 120(%ebx),%edx
+ movq 120(%ebx),%mm0
+ psllq $60,%mm6
+ movq 112(%ebx),%mm3
+ por %mm6,%mm2
+ movq %mm1,-16(%edi)
+ psrlq $4,%mm1
+ movq %mm4,112(%edi)
+ movq %mm4,%mm7
+ movq %mm2,-24(%ebp)
+ psrlq $4,%mm4
+ movq %mm5,104(%ebp)
+ shll $4,%edx
+ movb %dl,15(%esp)
+ psllq $60,%mm7
+ por %mm7,%mm1
+ movq %mm0,-8(%edi)
+ psrlq $4,%mm0
+ movq %mm3,120(%edi)
+ movq %mm3,%mm6
+ movq %mm1,-16(%ebp)
+ psrlq $4,%mm3
+ movq %mm4,112(%ebp)
+ psllq $60,%mm6
+ por %mm6,%mm0
+ movq %mm0,-8(%ebp)
+ movq %mm3,120(%ebp)
+ movq (%eax),%mm6
+ movl 8(%eax),%ebx
+ movl 12(%eax),%edx
+.align 16
+.L009outer:
+ xorl 12(%ecx),%edx
+ xorl 8(%ecx),%ebx
+ pxor (%ecx),%mm6
+ leal 16(%ecx),%ecx
+ movl %ebx,536(%esp)
+ movq %mm6,528(%esp)
+ movl %ecx,548(%esp)
+ xorl %eax,%eax
+ roll $8,%edx
+ movb %dl,%al
+ movl %eax,%ebp
+ andb $15,%al
+ shrl $4,%ebp
+ pxor %mm0,%mm0
+ roll $8,%edx
+ pxor %mm1,%mm1
+ pxor %mm2,%mm2
+ movq 16(%esp,%eax,8),%mm7
+ movq 144(%esp,%eax,8),%mm6
+ movb %dl,%al
+ movd %mm7,%ebx
+ psrlq $8,%mm7
+ movq %mm6,%mm3
+ movl %eax,%edi
+ psrlq $8,%mm6
+ pxor 272(%esp,%ebp,8),%mm7
+ andb $15,%al
+ psllq $56,%mm3
+ shrl $4,%edi
+ pxor 16(%esp,%eax,8),%mm7
+ roll $8,%edx
+ pxor 144(%esp,%eax,8),%mm6
+ pxor %mm3,%mm7
+ pxor 400(%esp,%ebp,8),%mm6
+ xorb (%esp,%ebp,1),%bl
+ movb %dl,%al
+ movd %mm7,%ecx
+ movzbl %bl,%ebx
+ psrlq $8,%mm7
+ movq %mm6,%mm3
+ movl %eax,%ebp
+ psrlq $8,%mm6
+ pxor 272(%esp,%edi,8),%mm7
+ andb $15,%al
+ psllq $56,%mm3
+ shrl $4,%ebp
+ pinsrw $2,(%esi,%ebx,2),%mm2
+ pxor 16(%esp,%eax,8),%mm7
+ roll $8,%edx
+ pxor 144(%esp,%eax,8),%mm6
+ pxor %mm3,%mm7
+ pxor 400(%esp,%edi,8),%mm6
+ xorb (%esp,%edi,1),%cl
+ movb %dl,%al
+ movl 536(%esp),%edx
+ movd %mm7,%ebx
+ movzbl %cl,%ecx
+ psrlq $8,%mm7
+ movq %mm6,%mm3
+ movl %eax,%edi
+ psrlq $8,%mm6
+ pxor 272(%esp,%ebp,8),%mm7
+ andb $15,%al
+ psllq $56,%mm3
+ pxor %mm2,%mm6
+ shrl $4,%edi
+ pinsrw $2,(%esi,%ecx,2),%mm1
+ pxor 16(%esp,%eax,8),%mm7
+ roll $8,%edx
+ pxor 144(%esp,%eax,8),%mm6
+ pxor %mm3,%mm7
+ pxor 400(%esp,%ebp,8),%mm6
+ xorb (%esp,%ebp,1),%bl
+ movb %dl,%al
+ movd %mm7,%ecx
+ movzbl %bl,%ebx
+ psrlq $8,%mm7
+ movq %mm6,%mm3
+ movl %eax,%ebp
+ psrlq $8,%mm6
+ pxor 272(%esp,%edi,8),%mm7
+ andb $15,%al
+ psllq $56,%mm3
+ pxor %mm1,%mm6
+ shrl $4,%ebp
+ pinsrw $2,(%esi,%ebx,2),%mm0
+ pxor 16(%esp,%eax,8),%mm7
+ roll $8,%edx
+ pxor 144(%esp,%eax,8),%mm6
+ pxor %mm3,%mm7
+ pxor 400(%esp,%edi,8),%mm6
+ xorb (%esp,%edi,1),%cl
+ movb %dl,%al
+ movd %mm7,%ebx
+ movzbl %cl,%ecx
+ psrlq $8,%mm7
+ movq %mm6,%mm3
+ movl %eax,%edi
+ psrlq $8,%mm6
+ pxor 272(%esp,%ebp,8),%mm7
+ andb $15,%al
+ psllq $56,%mm3
+ pxor %mm0,%mm6
+ shrl $4,%edi
+ pinsrw $2,(%esi,%ecx,2),%mm2
+ pxor 16(%esp,%eax,8),%mm7
+ roll $8,%edx
+ pxor 144(%esp,%eax,8),%mm6
+ pxor %mm3,%mm7
+ pxor 400(%esp,%ebp,8),%mm6
+ xorb (%esp,%ebp,1),%bl
+ movb %dl,%al
+ movd %mm7,%ecx
+ movzbl %bl,%ebx
+ psrlq $8,%mm7
+ movq %mm6,%mm3
+ movl %eax,%ebp
+ psrlq $8,%mm6
+ pxor 272(%esp,%edi,8),%mm7
+ andb $15,%al
+ psllq $56,%mm3
+ pxor %mm2,%mm6
+ shrl $4,%ebp
+ pinsrw $2,(%esi,%ebx,2),%mm1
+ pxor 16(%esp,%eax,8),%mm7
+ roll $8,%edx
+ pxor 144(%esp,%eax,8),%mm6
+ pxor %mm3,%mm7
+ pxor 400(%esp,%edi,8),%mm6
+ xorb (%esp,%edi,1),%cl
+ movb %dl,%al
+ movl 532(%esp),%edx
+ movd %mm7,%ebx
+ movzbl %cl,%ecx
+ psrlq $8,%mm7
+ movq %mm6,%mm3
+ movl %eax,%edi
+ psrlq $8,%mm6
+ pxor 272(%esp,%ebp,8),%mm7
+ andb $15,%al
+ psllq $56,%mm3
+ pxor %mm1,%mm6
+ shrl $4,%edi
+ pinsrw $2,(%esi,%ecx,2),%mm0
+ pxor 16(%esp,%eax,8),%mm7
+ roll $8,%edx
+ pxor 144(%esp,%eax,8),%mm6
+ pxor %mm3,%mm7
+ pxor 400(%esp,%ebp,8),%mm6
+ xorb (%esp,%ebp,1),%bl
+ movb %dl,%al
+ movd %mm7,%ecx
+ movzbl %bl,%ebx
+ psrlq $8,%mm7
+ movq %mm6,%mm3
+ movl %eax,%ebp
+ psrlq $8,%mm6
+ pxor 272(%esp,%edi,8),%mm7
+ andb $15,%al
+ psllq $56,%mm3
+ pxor %mm0,%mm6
+ shrl $4,%ebp
+ pinsrw $2,(%esi,%ebx,2),%mm2
+ pxor 16(%esp,%eax,8),%mm7
+ roll $8,%edx
+ pxor 144(%esp,%eax,8),%mm6
+ pxor %mm3,%mm7
+ pxor 400(%esp,%edi,8),%mm6
+ xorb (%esp,%edi,1),%cl
+ movb %dl,%al
+ movd %mm7,%ebx
+ movzbl %cl,%ecx
+ psrlq $8,%mm7
+ movq %mm6,%mm3
+ movl %eax,%edi
+ psrlq $8,%mm6
+ pxor 272(%esp,%ebp,8),%mm7
+ andb $15,%al
+ psllq $56,%mm3
+ pxor %mm2,%mm6
+ shrl $4,%edi
+ pinsrw $2,(%esi,%ecx,2),%mm1
+ pxor 16(%esp,%eax,8),%mm7
+ roll $8,%edx
+ pxor 144(%esp,%eax,8),%mm6
+ pxor %mm3,%mm7
+ pxor 400(%esp,%ebp,8),%mm6
+ xorb (%esp,%ebp,1),%bl
+ movb %dl,%al
+ movd %mm7,%ecx
+ movzbl %bl,%ebx
+ psrlq $8,%mm7
+ movq %mm6,%mm3
+ movl %eax,%ebp
+ psrlq $8,%mm6
+ pxor 272(%esp,%edi,8),%mm7
+ andb $15,%al
+ psllq $56,%mm3
+ pxor %mm1,%mm6
+ shrl $4,%ebp
+ pinsrw $2,(%esi,%ebx,2),%mm0
+ pxor 16(%esp,%eax,8),%mm7
+ roll $8,%edx
+ pxor 144(%esp,%eax,8),%mm6
+ pxor %mm3,%mm7
+ pxor 400(%esp,%edi,8),%mm6
+ xorb (%esp,%edi,1),%cl
+ movb %dl,%al
+ movl 528(%esp),%edx
+ movd %mm7,%ebx
+ movzbl %cl,%ecx
+ psrlq $8,%mm7
+ movq %mm6,%mm3
+ movl %eax,%edi
+ psrlq $8,%mm6
+ pxor 272(%esp,%ebp,8),%mm7
+ andb $15,%al
+ psllq $56,%mm3
+ pxor %mm0,%mm6
+ shrl $4,%edi
+ pinsrw $2,(%esi,%ecx,2),%mm2
+ pxor 16(%esp,%eax,8),%mm7
+ roll $8,%edx
+ pxor 144(%esp,%eax,8),%mm6
+ pxor %mm3,%mm7
+ pxor 400(%esp,%ebp,8),%mm6
+ xorb (%esp,%ebp,1),%bl
+ movb %dl,%al
+ movd %mm7,%ecx
+ movzbl %bl,%ebx
+ psrlq $8,%mm7
+ movq %mm6,%mm3
+ movl %eax,%ebp
+ psrlq $8,%mm6
+ pxor 272(%esp,%edi,8),%mm7
+ andb $15,%al
+ psllq $56,%mm3
+ pxor %mm2,%mm6
+ shrl $4,%ebp
+ pinsrw $2,(%esi,%ebx,2),%mm1
+ pxor 16(%esp,%eax,8),%mm7
+ roll $8,%edx
+ pxor 144(%esp,%eax,8),%mm6
+ pxor %mm3,%mm7
+ pxor 400(%esp,%edi,8),%mm6
+ xorb (%esp,%edi,1),%cl
+ movb %dl,%al
+ movd %mm7,%ebx
+ movzbl %cl,%ecx
+ psrlq $8,%mm7
+ movq %mm6,%mm3
+ movl %eax,%edi
+ psrlq $8,%mm6
+ pxor 272(%esp,%ebp,8),%mm7
+ andb $15,%al
+ psllq $56,%mm3
+ pxor %mm1,%mm6
+ shrl $4,%edi
+ pinsrw $2,(%esi,%ecx,2),%mm0
+ pxor 16(%esp,%eax,8),%mm7
+ roll $8,%edx
+ pxor 144(%esp,%eax,8),%mm6
+ pxor %mm3,%mm7
+ pxor 400(%esp,%ebp,8),%mm6
+ xorb (%esp,%ebp,1),%bl
+ movb %dl,%al
+ movd %mm7,%ecx
+ movzbl %bl,%ebx
+ psrlq $8,%mm7
+ movq %mm6,%mm3
+ movl %eax,%ebp
+ psrlq $8,%mm6
+ pxor 272(%esp,%edi,8),%mm7
+ andb $15,%al
+ psllq $56,%mm3
+ pxor %mm0,%mm6
+ shrl $4,%ebp
+ pinsrw $2,(%esi,%ebx,2),%mm2
+ pxor 16(%esp,%eax,8),%mm7
+ roll $8,%edx
+ pxor 144(%esp,%eax,8),%mm6
+ pxor %mm3,%mm7
+ pxor 400(%esp,%edi,8),%mm6
+ xorb (%esp,%edi,1),%cl
+ movb %dl,%al
+ movl 524(%esp),%edx
+ movd %mm7,%ebx
+ movzbl %cl,%ecx
+ psrlq $8,%mm7
+ movq %mm6,%mm3
+ movl %eax,%edi
+ psrlq $8,%mm6
+ pxor 272(%esp,%ebp,8),%mm7
+ andb $15,%al
+ psllq $56,%mm3
+ pxor %mm2,%mm6
+ shrl $4,%edi
+ pinsrw $2,(%esi,%ecx,2),%mm1
+ pxor 16(%esp,%eax,8),%mm7
+ pxor 144(%esp,%eax,8),%mm6
+ xorb (%esp,%ebp,1),%bl
+ pxor %mm3,%mm7
+ pxor 400(%esp,%ebp,8),%mm6
+ movzbl %bl,%ebx
+ pxor %mm2,%mm2
+ psllq $4,%mm1
+ movd %mm7,%ecx
+ psrlq $4,%mm7
+ movq %mm6,%mm3
+ psrlq $4,%mm6
+ shll $4,%ecx
+ pxor 16(%esp,%edi,8),%mm7
+ psllq $60,%mm3
+ movzbl %cl,%ecx
+ pxor %mm3,%mm7
+ pxor 144(%esp,%edi,8),%mm6
+ pinsrw $2,(%esi,%ebx,2),%mm0
+ pxor %mm1,%mm6
+ movd %mm7,%edx
+ pinsrw $3,(%esi,%ecx,2),%mm2
+ psllq $12,%mm0
+ pxor %mm0,%mm6
+ psrlq $32,%mm7
+ pxor %mm2,%mm6
+ movl 548(%esp),%ecx
+ movd %mm7,%ebx
+ movq %mm6,%mm3
+ psllw $8,%mm6
+ psrlw $8,%mm3
+ por %mm3,%mm6
+ bswap %edx
+ pshufw $27,%mm6,%mm6
+ bswap %ebx
+ cmpl 552(%esp),%ecx
+ jne .L009outer
+ movl 544(%esp),%eax
+ movl %edx,12(%eax)
+ movl %ebx,8(%eax)
+ movq %mm6,(%eax)
+ movl 556(%esp),%esp
+ emms
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.size gcm_ghash_4bit_mmx,.-.L_gcm_ghash_4bit_mmx_begin
+.globl gcm_init_clmul
+.hidden gcm_init_clmul
+.type gcm_init_clmul,@function
+.align 16
+gcm_init_clmul:
+.L_gcm_init_clmul_begin:
+ movl 4(%esp),%edx
+ movl 8(%esp),%eax
+ call .L010pic
+.L010pic:
+ popl %ecx
+ leal .Lbswap-.L010pic(%ecx),%ecx
+ movdqu (%eax),%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 16(%ecx),%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
+ xorps %xmm0,%xmm3
+ xorps %xmm1,%xmm3
+ movdqa %xmm3,%xmm4
+ psrldq $8,%xmm3
+ pslldq $8,%xmm4
+ pxor %xmm3,%xmm1
+ pxor %xmm4,%xmm0
+ movdqa %xmm0,%xmm4
+ movdqa %xmm0,%xmm3
+ psllq $5,%xmm0
+ pxor %xmm0,%xmm3
+ psllq $1,%xmm0
+ pxor %xmm3,%xmm0
+ psllq $57,%xmm0
+ movdqa %xmm0,%xmm3
+ pslldq $8,%xmm0
+ psrldq $8,%xmm3
+ pxor %xmm4,%xmm0
+ pxor %xmm3,%xmm1
+ movdqa %xmm0,%xmm4
+ psrlq $1,%xmm0
+ pxor %xmm4,%xmm1
+ pxor %xmm0,%xmm4
+ psrlq $5,%xmm0
+ pxor %xmm4,%xmm0
+ psrlq $1,%xmm0
+ pxor %xmm1,%xmm0
+ pshufd $78,%xmm2,%xmm3
+ pshufd $78,%xmm0,%xmm4
+ pxor %xmm2,%xmm3
+ movdqu %xmm2,(%edx)
+ pxor %xmm0,%xmm4
+ movdqu %xmm0,16(%edx)
+.byte 102,15,58,15,227,8
+ movdqu %xmm4,32(%edx)
+ ret
+.size gcm_init_clmul,.-.L_gcm_init_clmul_begin
+.globl gcm_gmult_clmul
+.hidden gcm_gmult_clmul
+.type gcm_gmult_clmul,@function
+.align 16
+gcm_gmult_clmul:
+.L_gcm_gmult_clmul_begin:
+ movl 4(%esp),%eax
+ movl 8(%esp),%edx
+ call .L011pic
+.L011pic:
+ popl %ecx
+ leal .Lbswap-.L011pic(%ecx),%ecx
+ movdqu (%eax),%xmm0
+ movdqa (%ecx),%xmm5
+ movups (%edx),%xmm2
+.byte 102,15,56,0,197
+ movups 32(%edx),%xmm4
+ movdqa %xmm0,%xmm1
+ pshufd $78,%xmm0,%xmm3
+ pxor %xmm0,%xmm3
+.byte 102,15,58,68,194,0
+.byte 102,15,58,68,202,17
+.byte 102,15,58,68,220,0
+ xorps %xmm0,%xmm3
+ xorps %xmm1,%xmm3
+ movdqa %xmm3,%xmm4
+ psrldq $8,%xmm3
+ pslldq $8,%xmm4
+ pxor %xmm3,%xmm1
+ pxor %xmm4,%xmm0
+ movdqa %xmm0,%xmm4
+ movdqa %xmm0,%xmm3
+ psllq $5,%xmm0
+ pxor %xmm0,%xmm3
+ psllq $1,%xmm0
+ pxor %xmm3,%xmm0
+ psllq $57,%xmm0
+ movdqa %xmm0,%xmm3
+ pslldq $8,%xmm0
+ psrldq $8,%xmm3
+ pxor %xmm4,%xmm0
+ pxor %xmm3,%xmm1
+ movdqa %xmm0,%xmm4
+ psrlq $1,%xmm0
+ pxor %xmm4,%xmm1
+ pxor %xmm0,%xmm4
+ psrlq $5,%xmm0
+ pxor %xmm4,%xmm0
+ psrlq $1,%xmm0
+ pxor %xmm1,%xmm0
+.byte 102,15,56,0,197
+ movdqu %xmm0,(%eax)
+ ret
+.size gcm_gmult_clmul,.-.L_gcm_gmult_clmul_begin
+.globl gcm_ghash_clmul
+.hidden gcm_ghash_clmul
+.type gcm_ghash_clmul,@function
+.align 16
+gcm_ghash_clmul:
+.L_gcm_ghash_clmul_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ movl 20(%esp),%eax
+ movl 24(%esp),%edx
+ movl 28(%esp),%esi
+ movl 32(%esp),%ebx
+ call .L012pic
+.L012pic:
+ popl %ecx
+ leal .Lbswap-.L012pic(%ecx),%ecx
+ movdqu (%eax),%xmm0
+ movdqa (%ecx),%xmm5
+ movdqu (%edx),%xmm2
+.byte 102,15,56,0,197
+ subl $16,%ebx
+ jz .L013odd_tail
+ movdqu (%esi),%xmm3
+ movdqu 16(%esi),%xmm6
+.byte 102,15,56,0,221
+.byte 102,15,56,0,245
+ movdqu 32(%edx),%xmm5
+ pxor %xmm3,%xmm0
+ pshufd $78,%xmm6,%xmm3
+ movdqa %xmm6,%xmm7
+ pxor %xmm6,%xmm3
+ leal 32(%esi),%esi
+.byte 102,15,58,68,242,0
+.byte 102,15,58,68,250,17
+.byte 102,15,58,68,221,0
+ movups 16(%edx),%xmm2
+ nop
+ subl $32,%ebx
+ jbe .L014even_tail
+ jmp .L015mod_loop
+.align 32
+.L015mod_loop:
+ pshufd $78,%xmm0,%xmm4
+ movdqa %xmm0,%xmm1
+ pxor %xmm0,%xmm4
+ nop
+.byte 102,15,58,68,194,0
+.byte 102,15,58,68,202,17
+.byte 102,15,58,68,229,16
+ movups (%edx),%xmm2
+ xorps %xmm6,%xmm0
+ movdqa (%ecx),%xmm5
+ xorps %xmm7,%xmm1
+ movdqu (%esi),%xmm7
+ pxor %xmm0,%xmm3
+ movdqu 16(%esi),%xmm6
+ pxor %xmm1,%xmm3
+.byte 102,15,56,0,253
+ pxor %xmm3,%xmm4
+ movdqa %xmm4,%xmm3
+ psrldq $8,%xmm4
+ pslldq $8,%xmm3
+ pxor %xmm4,%xmm1
+ pxor %xmm3,%xmm0
+.byte 102,15,56,0,245
+ pxor %xmm7,%xmm1
+ movdqa %xmm6,%xmm7
+ movdqa %xmm0,%xmm4
+ movdqa %xmm0,%xmm3
+ psllq $5,%xmm0
+ pxor %xmm0,%xmm3
+ psllq $1,%xmm0
+ pxor %xmm3,%xmm0
+.byte 102,15,58,68,242,0
+ movups 32(%edx),%xmm5
+ psllq $57,%xmm0
+ movdqa %xmm0,%xmm3
+ pslldq $8,%xmm0
+ psrldq $8,%xmm3
+ pxor %xmm4,%xmm0
+ pxor %xmm3,%xmm1
+ pshufd $78,%xmm7,%xmm3
+ movdqa %xmm0,%xmm4
+ psrlq $1,%xmm0
+ pxor %xmm7,%xmm3
+ pxor %xmm4,%xmm1
+.byte 102,15,58,68,250,17
+ movups 16(%edx),%xmm2
+ pxor %xmm0,%xmm4
+ psrlq $5,%xmm0
+ pxor %xmm4,%xmm0
+ psrlq $1,%xmm0
+ pxor %xmm1,%xmm0
+.byte 102,15,58,68,221,0
+ leal 32(%esi),%esi
+ subl $32,%ebx
+ ja .L015mod_loop
+.L014even_tail:
+ pshufd $78,%xmm0,%xmm4
+ movdqa %xmm0,%xmm1
+ pxor %xmm0,%xmm4
+.byte 102,15,58,68,194,0
+.byte 102,15,58,68,202,17
+.byte 102,15,58,68,229,16
+ movdqa (%ecx),%xmm5
+ xorps %xmm6,%xmm0
+ xorps %xmm7,%xmm1
+ pxor %xmm0,%xmm3
+ pxor %xmm1,%xmm3
+ pxor %xmm3,%xmm4
+ movdqa %xmm4,%xmm3
+ psrldq $8,%xmm4
+ pslldq $8,%xmm3
+ pxor %xmm4,%xmm1
+ pxor %xmm3,%xmm0
+ movdqa %xmm0,%xmm4
+ movdqa %xmm0,%xmm3
+ psllq $5,%xmm0
+ pxor %xmm0,%xmm3
+ psllq $1,%xmm0
+ pxor %xmm3,%xmm0
+ psllq $57,%xmm0
+ movdqa %xmm0,%xmm3
+ pslldq $8,%xmm0
+ psrldq $8,%xmm3
+ pxor %xmm4,%xmm0
+ pxor %xmm3,%xmm1
+ movdqa %xmm0,%xmm4
+ psrlq $1,%xmm0
+ pxor %xmm4,%xmm1
+ pxor %xmm0,%xmm4
+ psrlq $5,%xmm0
+ pxor %xmm4,%xmm0
+ psrlq $1,%xmm0
+ pxor %xmm1,%xmm0
+ testl %ebx,%ebx
+ jnz .L016done
+ movups (%edx),%xmm2
+.L013odd_tail:
+ movdqu (%esi),%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
+ xorps %xmm0,%xmm3
+ xorps %xmm1,%xmm3
+ movdqa %xmm3,%xmm4
+ psrldq $8,%xmm3
+ pslldq $8,%xmm4
+ pxor %xmm3,%xmm1
+ pxor %xmm4,%xmm0
+ movdqa %xmm0,%xmm4
+ movdqa %xmm0,%xmm3
+ psllq $5,%xmm0
+ pxor %xmm0,%xmm3
+ psllq $1,%xmm0
+ pxor %xmm3,%xmm0
+ psllq $57,%xmm0
+ movdqa %xmm0,%xmm3
+ pslldq $8,%xmm0
+ psrldq $8,%xmm3
+ pxor %xmm4,%xmm0
+ pxor %xmm3,%xmm1
+ movdqa %xmm0,%xmm4
+ psrlq $1,%xmm0
+ pxor %xmm4,%xmm1
+ pxor %xmm0,%xmm4
+ psrlq $5,%xmm0
+ pxor %xmm4,%xmm0
+ psrlq $1,%xmm0
+ pxor %xmm1,%xmm0
+.L016done:
+.byte 102,15,56,0,197
+ movdqu %xmm0,(%eax)
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.size gcm_ghash_clmul,.-.L_gcm_ghash_clmul_begin
+.align 64
+.Lbswap:
+.byte 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0
+.byte 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,194
+.align 64
+.Lrem_8bit:
+.value 0,450,900,582,1800,1738,1164,1358
+.value 3600,4050,3476,3158,2328,2266,2716,2910
+.value 7200,7650,8100,7782,6952,6890,6316,6510
+.value 4656,5106,4532,4214,5432,5370,5820,6014
+.value 14400,14722,15300,14854,16200,16010,15564,15630
+.value 13904,14226,13780,13334,12632,12442,13020,13086
+.value 9312,9634,10212,9766,9064,8874,8428,8494
+.value 10864,11186,10740,10294,11640,11450,12028,12094
+.value 28800,28994,29444,29382,30600,30282,29708,30158
+.value 32400,32594,32020,31958,31128,30810,31260,31710
+.value 27808,28002,28452,28390,27560,27242,26668,27118
+.value 25264,25458,24884,24822,26040,25722,26172,26622
+.value 18624,18690,19268,19078,20424,19978,19532,19854
+.value 18128,18194,17748,17558,16856,16410,16988,17310
+.value 21728,21794,22372,22182,21480,21034,20588,20910
+.value 23280,23346,22900,22710,24056,23610,24188,24510
+.value 57600,57538,57988,58182,58888,59338,58764,58446
+.value 61200,61138,60564,60758,59416,59866,60316,59998
+.value 64800,64738,65188,65382,64040,64490,63916,63598
+.value 62256,62194,61620,61814,62520,62970,63420,63102
+.value 55616,55426,56004,56070,56904,57226,56780,56334
+.value 55120,54930,54484,54550,53336,53658,54236,53790
+.value 50528,50338,50916,50982,49768,50090,49644,49198
+.value 52080,51890,51444,51510,52344,52666,53244,52798
+.value 37248,36930,37380,37830,38536,38730,38156,38094
+.value 40848,40530,39956,40406,39064,39258,39708,39646
+.value 36256,35938,36388,36838,35496,35690,35116,35054
+.value 33712,33394,32820,33270,33976,34170,34620,34558
+.value 43456,43010,43588,43910,44744,44810,44364,44174
+.value 42960,42514,42068,42390,41176,41242,41820,41630
+.value 46560,46114,46692,47014,45800,45866,45420,45230
+.value 48112,47666,47220,47542,48376,48442,49020,48830
+.align 64
+.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
+.byte 71,72,65,83,72,32,102,111,114,32,120,56,54,44,32,67
+.byte 82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112
+.byte 112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62
+.byte 0
+#endif
diff --git a/linux-x86/crypto/rc4/rc4-586.S b/linux-x86/crypto/rc4/rc4-586.S
new file mode 100644
index 0000000..a5cce47
--- /dev/null
+++ b/linux-x86/crypto/rc4/rc4-586.S
@@ -0,0 +1,385 @@
+#if defined(__i386__)
+.file "rc4-586.S"
+.text
+.globl asm_RC4
+.hidden asm_RC4
+.type asm_RC4,@function
+.align 16
+asm_RC4:
+.L_asm_RC4_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ movl 20(%esp),%edi
+ movl 24(%esp),%edx
+ movl 28(%esp),%esi
+ movl 32(%esp),%ebp
+ xorl %eax,%eax
+ xorl %ebx,%ebx
+ cmpl $0,%edx
+ je .L000abort
+ movb (%edi),%al
+ movb 4(%edi),%bl
+ addl $8,%edi
+ leal (%esi,%edx,1),%ecx
+ subl %esi,%ebp
+ movl %ecx,24(%esp)
+ incb %al
+ cmpl $-1,256(%edi)
+ je .L001RC4_CHAR
+ movl (%edi,%eax,4),%ecx
+ andl $-4,%edx
+ jz .L002loop1
+ movl %ebp,32(%esp)
+ testl $-8,%edx
+ jz .L003go4loop4
+ call .L004PIC_me_up
+.L004PIC_me_up:
+ popl %ebp
+ leal OPENSSL_ia32cap_P-.L004PIC_me_up(%ebp),%ebp
+ btl $26,(%ebp)
+ jnc .L003go4loop4
+ movl 32(%esp),%ebp
+ andl $-8,%edx
+ leal -8(%esi,%edx,1),%edx
+ movl %edx,-4(%edi)
+ addb %cl,%bl
+ movl (%edi,%ebx,4),%edx
+ movl %ecx,(%edi,%ebx,4)
+ movl %edx,(%edi,%eax,4)
+ incl %eax
+ addl %ecx,%edx
+ movzbl %al,%eax
+ movzbl %dl,%edx
+ movq (%esi),%mm0
+ movl (%edi,%eax,4),%ecx
+ movd (%edi,%edx,4),%mm2
+ jmp .L005loop_mmx_enter
+.align 16
+.L006loop_mmx:
+ addb %cl,%bl
+ psllq $56,%mm1
+ movl (%edi,%ebx,4),%edx
+ movl %ecx,(%edi,%ebx,4)
+ movl %edx,(%edi,%eax,4)
+ incl %eax
+ addl %ecx,%edx
+ movzbl %al,%eax
+ movzbl %dl,%edx
+ pxor %mm1,%mm2
+ movq (%esi),%mm0
+ movq %mm2,-8(%ebp,%esi,1)
+ movl (%edi,%eax,4),%ecx
+ movd (%edi,%edx,4),%mm2
+.L005loop_mmx_enter:
+ addb %cl,%bl
+ movl (%edi,%ebx,4),%edx
+ movl %ecx,(%edi,%ebx,4)
+ movl %edx,(%edi,%eax,4)
+ incl %eax
+ addl %ecx,%edx
+ movzbl %al,%eax
+ movzbl %dl,%edx
+ pxor %mm0,%mm2
+ movl (%edi,%eax,4),%ecx
+ movd (%edi,%edx,4),%mm1
+ addb %cl,%bl
+ psllq $8,%mm1
+ movl (%edi,%ebx,4),%edx
+ movl %ecx,(%edi,%ebx,4)
+ movl %edx,(%edi,%eax,4)
+ incl %eax
+ addl %ecx,%edx
+ movzbl %al,%eax
+ movzbl %dl,%edx
+ pxor %mm1,%mm2
+ movl (%edi,%eax,4),%ecx
+ movd (%edi,%edx,4),%mm1
+ addb %cl,%bl
+ psllq $16,%mm1
+ movl (%edi,%ebx,4),%edx
+ movl %ecx,(%edi,%ebx,4)
+ movl %edx,(%edi,%eax,4)
+ incl %eax
+ addl %ecx,%edx
+ movzbl %al,%eax
+ movzbl %dl,%edx
+ pxor %mm1,%mm2
+ movl (%edi,%eax,4),%ecx
+ movd (%edi,%edx,4),%mm1
+ addb %cl,%bl
+ psllq $24,%mm1
+ movl (%edi,%ebx,4),%edx
+ movl %ecx,(%edi,%ebx,4)
+ movl %edx,(%edi,%eax,4)
+ incl %eax
+ addl %ecx,%edx
+ movzbl %al,%eax
+ movzbl %dl,%edx
+ pxor %mm1,%mm2
+ movl (%edi,%eax,4),%ecx
+ movd (%edi,%edx,4),%mm1
+ addb %cl,%bl
+ psllq $32,%mm1
+ movl (%edi,%ebx,4),%edx
+ movl %ecx,(%edi,%ebx,4)
+ movl %edx,(%edi,%eax,4)
+ incl %eax
+ addl %ecx,%edx
+ movzbl %al,%eax
+ movzbl %dl,%edx
+ pxor %mm1,%mm2
+ movl (%edi,%eax,4),%ecx
+ movd (%edi,%edx,4),%mm1
+ addb %cl,%bl
+ psllq $40,%mm1
+ movl (%edi,%ebx,4),%edx
+ movl %ecx,(%edi,%ebx,4)
+ movl %edx,(%edi,%eax,4)
+ incl %eax
+ addl %ecx,%edx
+ movzbl %al,%eax
+ movzbl %dl,%edx
+ pxor %mm1,%mm2
+ movl (%edi,%eax,4),%ecx
+ movd (%edi,%edx,4),%mm1
+ addb %cl,%bl
+ psllq $48,%mm1
+ movl (%edi,%ebx,4),%edx
+ movl %ecx,(%edi,%ebx,4)
+ movl %edx,(%edi,%eax,4)
+ incl %eax
+ addl %ecx,%edx
+ movzbl %al,%eax
+ movzbl %dl,%edx
+ pxor %mm1,%mm2
+ movl (%edi,%eax,4),%ecx
+ movd (%edi,%edx,4),%mm1
+ movl %ebx,%edx
+ xorl %ebx,%ebx
+ movb %dl,%bl
+ cmpl -4(%edi),%esi
+ leal 8(%esi),%esi
+ jb .L006loop_mmx
+ psllq $56,%mm1
+ pxor %mm1,%mm2
+ movq %mm2,-8(%ebp,%esi,1)
+ emms
+ cmpl 24(%esp),%esi
+ je .L007done
+ jmp .L002loop1
+.align 16
+.L003go4loop4:
+ leal -4(%esi,%edx,1),%edx
+ movl %edx,28(%esp)
+.L008loop4:
+ addb %cl,%bl
+ movl (%edi,%ebx,4),%edx
+ movl %ecx,(%edi,%ebx,4)
+ movl %edx,(%edi,%eax,4)
+ addl %ecx,%edx
+ incb %al
+ andl $255,%edx
+ movl (%edi,%eax,4),%ecx
+ movl (%edi,%edx,4),%ebp
+ addb %cl,%bl
+ movl (%edi,%ebx,4),%edx
+ movl %ecx,(%edi,%ebx,4)
+ movl %edx,(%edi,%eax,4)
+ addl %ecx,%edx
+ incb %al
+ andl $255,%edx
+ rorl $8,%ebp
+ movl (%edi,%eax,4),%ecx
+ orl (%edi,%edx,4),%ebp
+ addb %cl,%bl
+ movl (%edi,%ebx,4),%edx
+ movl %ecx,(%edi,%ebx,4)
+ movl %edx,(%edi,%eax,4)
+ addl %ecx,%edx
+ incb %al
+ andl $255,%edx
+ rorl $8,%ebp
+ movl (%edi,%eax,4),%ecx
+ orl (%edi,%edx,4),%ebp
+ addb %cl,%bl
+ movl (%edi,%ebx,4),%edx
+ movl %ecx,(%edi,%ebx,4)
+ movl %edx,(%edi,%eax,4)
+ addl %ecx,%edx
+ incb %al
+ andl $255,%edx
+ rorl $8,%ebp
+ movl 32(%esp),%ecx
+ orl (%edi,%edx,4),%ebp
+ rorl $8,%ebp
+ xorl (%esi),%ebp
+ cmpl 28(%esp),%esi
+ movl %ebp,(%ecx,%esi,1)
+ leal 4(%esi),%esi
+ movl (%edi,%eax,4),%ecx
+ jb .L008loop4
+ cmpl 24(%esp),%esi
+ je .L007done
+ movl 32(%esp),%ebp
+.align 16
+.L002loop1:
+ addb %cl,%bl
+ movl (%edi,%ebx,4),%edx
+ movl %ecx,(%edi,%ebx,4)
+ movl %edx,(%edi,%eax,4)
+ addl %ecx,%edx
+ incb %al
+ andl $255,%edx
+ movl (%edi,%edx,4),%edx
+ xorb (%esi),%dl
+ leal 1(%esi),%esi
+ movl (%edi,%eax,4),%ecx
+ cmpl 24(%esp),%esi
+ movb %dl,-1(%ebp,%esi,1)
+ jb .L002loop1
+ jmp .L007done
+.align 16
+.L001RC4_CHAR:
+ movzbl (%edi,%eax,1),%ecx
+.L009cloop1:
+ addb %cl,%bl
+ movzbl (%edi,%ebx,1),%edx
+ movb %cl,(%edi,%ebx,1)
+ movb %dl,(%edi,%eax,1)
+ addb %cl,%dl
+ movzbl (%edi,%edx,1),%edx
+ addb $1,%al
+ xorb (%esi),%dl
+ leal 1(%esi),%esi
+ movzbl (%edi,%eax,1),%ecx
+ cmpl 24(%esp),%esi
+ movb %dl,-1(%ebp,%esi,1)
+ jb .L009cloop1
+.L007done:
+ decb %al
+ movl %ebx,-4(%edi)
+ movb %al,-8(%edi)
+.L000abort:
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.size asm_RC4,.-.L_asm_RC4_begin
+.globl asm_RC4_set_key
+.hidden asm_RC4_set_key
+.type asm_RC4_set_key,@function
+.align 16
+asm_RC4_set_key:
+.L_asm_RC4_set_key_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ movl 20(%esp),%edi
+ movl 24(%esp),%ebp
+ movl 28(%esp),%esi
+ call .L010PIC_me_up
+.L010PIC_me_up:
+ popl %edx
+ leal OPENSSL_ia32cap_P-.L010PIC_me_up(%edx),%edx
+ leal 8(%edi),%edi
+ leal (%esi,%ebp,1),%esi
+ negl %ebp
+ xorl %eax,%eax
+ movl %ebp,-4(%edi)
+ btl $20,(%edx)
+ jc .L011c1stloop
+.align 16
+.L012w1stloop:
+ movl %eax,(%edi,%eax,4)
+ addb $1,%al
+ jnc .L012w1stloop
+ xorl %ecx,%ecx
+ xorl %edx,%edx
+.align 16
+.L013w2ndloop:
+ movl (%edi,%ecx,4),%eax
+ addb (%esi,%ebp,1),%dl
+ addb %al,%dl
+ addl $1,%ebp
+ movl (%edi,%edx,4),%ebx
+ jnz .L014wnowrap
+ movl -4(%edi),%ebp
+.L014wnowrap:
+ movl %eax,(%edi,%edx,4)
+ movl %ebx,(%edi,%ecx,4)
+ addb $1,%cl
+ jnc .L013w2ndloop
+ jmp .L015exit
+.align 16
+.L011c1stloop:
+ movb %al,(%edi,%eax,1)
+ addb $1,%al
+ jnc .L011c1stloop
+ xorl %ecx,%ecx
+ xorl %edx,%edx
+ xorl %ebx,%ebx
+.align 16
+.L016c2ndloop:
+ movb (%edi,%ecx,1),%al
+ addb (%esi,%ebp,1),%dl
+ addb %al,%dl
+ addl $1,%ebp
+ movb (%edi,%edx,1),%bl
+ jnz .L017cnowrap
+ movl -4(%edi),%ebp
+.L017cnowrap:
+ movb %al,(%edi,%edx,1)
+ movb %bl,(%edi,%ecx,1)
+ addb $1,%cl
+ jnc .L016c2ndloop
+ movl $-1,256(%edi)
+.L015exit:
+ xorl %eax,%eax
+ movl %eax,-8(%edi)
+ movl %eax,-4(%edi)
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.size asm_RC4_set_key,.-.L_asm_RC4_set_key_begin
+.globl RC4_options
+.hidden RC4_options
+.type RC4_options,@function
+.align 16
+RC4_options:
+.L_RC4_options_begin:
+ call .L018pic_point
+.L018pic_point:
+ popl %eax
+ leal .L019opts-.L018pic_point(%eax),%eax
+ call .L020PIC_me_up
+.L020PIC_me_up:
+ popl %edx
+ leal OPENSSL_ia32cap_P-.L020PIC_me_up(%edx),%edx
+ movl (%edx),%edx
+ btl $20,%edx
+ jc .L0211xchar
+ btl $26,%edx
+ jnc .L022ret
+ addl $25,%eax
+ ret
+.L0211xchar:
+ addl $12,%eax
+.L022ret:
+ ret
+.align 64
+.L019opts:
+.byte 114,99,52,40,52,120,44,105,110,116,41,0
+.byte 114,99,52,40,49,120,44,99,104,97,114,41,0
+.byte 114,99,52,40,56,120,44,109,109,120,41,0
+.byte 82,67,52,32,102,111,114,32,120,56,54,44,32,67,82,89
+.byte 80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114
+.byte 111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
+.align 64
+.size RC4_options,.-.L_RC4_options_begin
+#endif
diff --git a/linux-x86/crypto/sha/sha1-586.S b/linux-x86/crypto/sha/sha1-586.S
new file mode 100644
index 0000000..71ae5b3
--- /dev/null
+++ b/linux-x86/crypto/sha/sha1-586.S
@@ -0,0 +1,1383 @@
+#if defined(__i386__)
+.file "sha1-586.S"
+.text
+.globl sha1_block_data_order
+.hidden sha1_block_data_order
+.type sha1_block_data_order,@function
+.align 16
+sha1_block_data_order:
+.L_sha1_block_data_order_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ movl 20(%esp),%ebp
+ movl 24(%esp),%esi
+ movl 28(%esp),%eax
+ subl $76,%esp
+ shll $6,%eax
+ addl %esi,%eax
+ movl %eax,104(%esp)
+ movl 16(%ebp),%edi
+ jmp .L000loop
+.align 16
+.L000loop:
+ movl (%esi),%eax
+ movl 4(%esi),%ebx
+ movl 8(%esi),%ecx
+ movl 12(%esi),%edx
+ bswap %eax
+ bswap %ebx
+ bswap %ecx
+ bswap %edx
+ movl %eax,(%esp)
+ movl %ebx,4(%esp)
+ movl %ecx,8(%esp)
+ movl %edx,12(%esp)
+ movl 16(%esi),%eax
+ movl 20(%esi),%ebx
+ movl 24(%esi),%ecx
+ movl 28(%esi),%edx
+ bswap %eax
+ bswap %ebx
+ bswap %ecx
+ bswap %edx
+ movl %eax,16(%esp)
+ movl %ebx,20(%esp)
+ movl %ecx,24(%esp)
+ movl %edx,28(%esp)
+ movl 32(%esi),%eax
+ movl 36(%esi),%ebx
+ movl 40(%esi),%ecx
+ movl 44(%esi),%edx
+ bswap %eax
+ bswap %ebx
+ bswap %ecx
+ bswap %edx
+ movl %eax,32(%esp)
+ movl %ebx,36(%esp)
+ movl %ecx,40(%esp)
+ movl %edx,44(%esp)
+ movl 48(%esi),%eax
+ movl 52(%esi),%ebx
+ movl 56(%esi),%ecx
+ movl 60(%esi),%edx
+ bswap %eax
+ bswap %ebx
+ bswap %ecx
+ bswap %edx
+ movl %eax,48(%esp)
+ movl %ebx,52(%esp)
+ movl %ecx,56(%esp)
+ movl %edx,60(%esp)
+ movl %esi,100(%esp)
+ movl (%ebp),%eax
+ movl 4(%ebp),%ebx
+ movl 8(%ebp),%ecx
+ movl 12(%ebp),%edx
+
+ movl %ecx,%esi
+ movl %eax,%ebp
+ roll $5,%ebp
+ xorl %edx,%esi
+ addl %edi,%ebp
+ movl (%esp),%edi
+ andl %ebx,%esi
+ rorl $2,%ebx
+ xorl %edx,%esi
+ leal 1518500249(%ebp,%edi,1),%ebp
+ addl %esi,%ebp
+
+ movl %ebx,%edi
+ movl %ebp,%esi
+ roll $5,%ebp
+ xorl %ecx,%edi
+ addl %edx,%ebp
+ movl 4(%esp),%edx
+ andl %eax,%edi
+ rorl $2,%eax
+ xorl %ecx,%edi
+ leal 1518500249(%ebp,%edx,1),%ebp
+ addl %edi,%ebp
+
+ movl %eax,%edx
+ movl %ebp,%edi
+ roll $5,%ebp
+ xorl %ebx,%edx
+ addl %ecx,%ebp
+ movl 8(%esp),%ecx
+ andl %esi,%edx
+ rorl $2,%esi
+ xorl %ebx,%edx
+ leal 1518500249(%ebp,%ecx,1),%ebp
+ addl %edx,%ebp
+
+ movl %esi,%ecx
+ movl %ebp,%edx
+ roll $5,%ebp
+ xorl %eax,%ecx
+ addl %ebx,%ebp
+ movl 12(%esp),%ebx
+ andl %edi,%ecx
+ rorl $2,%edi
+ xorl %eax,%ecx
+ leal 1518500249(%ebp,%ebx,1),%ebp
+ addl %ecx,%ebp
+
+ movl %edi,%ebx
+ movl %ebp,%ecx
+ roll $5,%ebp
+ xorl %esi,%ebx
+ addl %eax,%ebp
+ movl 16(%esp),%eax
+ andl %edx,%ebx
+ rorl $2,%edx
+ xorl %esi,%ebx
+ leal 1518500249(%ebp,%eax,1),%ebp
+ addl %ebx,%ebp
+
+ movl %edx,%eax
+ movl %ebp,%ebx
+ roll $5,%ebp
+ xorl %edi,%eax
+ addl %esi,%ebp
+ movl 20(%esp),%esi
+ andl %ecx,%eax
+ rorl $2,%ecx
+ xorl %edi,%eax
+ leal 1518500249(%ebp,%esi,1),%ebp
+ addl %eax,%ebp
+
+ movl %ecx,%esi
+ movl %ebp,%eax
+ roll $5,%ebp
+ xorl %edx,%esi
+ addl %edi,%ebp
+ movl 24(%esp),%edi
+ andl %ebx,%esi
+ rorl $2,%ebx
+ xorl %edx,%esi
+ leal 1518500249(%ebp,%edi,1),%ebp
+ addl %esi,%ebp
+
+ movl %ebx,%edi
+ movl %ebp,%esi
+ roll $5,%ebp
+ xorl %ecx,%edi
+ addl %edx,%ebp
+ movl 28(%esp),%edx
+ andl %eax,%edi
+ rorl $2,%eax
+ xorl %ecx,%edi
+ leal 1518500249(%ebp,%edx,1),%ebp
+ addl %edi,%ebp
+
+ movl %eax,%edx
+ movl %ebp,%edi
+ roll $5,%ebp
+ xorl %ebx,%edx
+ addl %ecx,%ebp
+ movl 32(%esp),%ecx
+ andl %esi,%edx
+ rorl $2,%esi
+ xorl %ebx,%edx
+ leal 1518500249(%ebp,%ecx,1),%ebp
+ addl %edx,%ebp
+
+ movl %esi,%ecx
+ movl %ebp,%edx
+ roll $5,%ebp
+ xorl %eax,%ecx
+ addl %ebx,%ebp
+ movl 36(%esp),%ebx
+ andl %edi,%ecx
+ rorl $2,%edi
+ xorl %eax,%ecx
+ leal 1518500249(%ebp,%ebx,1),%ebp
+ addl %ecx,%ebp
+
+ movl %edi,%ebx
+ movl %ebp,%ecx
+ roll $5,%ebp
+ xorl %esi,%ebx
+ addl %eax,%ebp
+ movl 40(%esp),%eax
+ andl %edx,%ebx
+ rorl $2,%edx
+ xorl %esi,%ebx
+ leal 1518500249(%ebp,%eax,1),%ebp
+ addl %ebx,%ebp
+
+ movl %edx,%eax
+ movl %ebp,%ebx
+ roll $5,%ebp
+ xorl %edi,%eax
+ addl %esi,%ebp
+ movl 44(%esp),%esi
+ andl %ecx,%eax
+ rorl $2,%ecx
+ xorl %edi,%eax
+ leal 1518500249(%ebp,%esi,1),%ebp
+ addl %eax,%ebp
+
+ movl %ecx,%esi
+ movl %ebp,%eax
+ roll $5,%ebp
+ xorl %edx,%esi
+ addl %edi,%ebp
+ movl 48(%esp),%edi
+ andl %ebx,%esi
+ rorl $2,%ebx
+ xorl %edx,%esi
+ leal 1518500249(%ebp,%edi,1),%ebp
+ addl %esi,%ebp
+
+ movl %ebx,%edi
+ movl %ebp,%esi
+ roll $5,%ebp
+ xorl %ecx,%edi
+ addl %edx,%ebp
+ movl 52(%esp),%edx
+ andl %eax,%edi
+ rorl $2,%eax
+ xorl %ecx,%edi
+ leal 1518500249(%ebp,%edx,1),%ebp
+ addl %edi,%ebp
+
+ movl %eax,%edx
+ movl %ebp,%edi
+ roll $5,%ebp
+ xorl %ebx,%edx
+ addl %ecx,%ebp
+ movl 56(%esp),%ecx
+ andl %esi,%edx
+ rorl $2,%esi
+ xorl %ebx,%edx
+ leal 1518500249(%ebp,%ecx,1),%ebp
+ addl %edx,%ebp
+
+ movl %esi,%ecx
+ movl %ebp,%edx
+ roll $5,%ebp
+ xorl %eax,%ecx
+ addl %ebx,%ebp
+ movl 60(%esp),%ebx
+ andl %edi,%ecx
+ rorl $2,%edi
+ xorl %eax,%ecx
+ leal 1518500249(%ebp,%ebx,1),%ebp
+ movl (%esp),%ebx
+ addl %ebp,%ecx
+
+ movl %edi,%ebp
+ xorl 8(%esp),%ebx
+ xorl %esi,%ebp
+ xorl 32(%esp),%ebx
+ andl %edx,%ebp
+ xorl 52(%esp),%ebx
+ roll $1,%ebx
+ xorl %esi,%ebp
+ addl %ebp,%eax
+ movl %ecx,%ebp
+ rorl $2,%edx
+ movl %ebx,(%esp)
+ roll $5,%ebp
+ leal 1518500249(%ebx,%eax,1),%ebx
+ movl 4(%esp),%eax
+ addl %ebp,%ebx
+
+ movl %edx,%ebp
+ xorl 12(%esp),%eax
+ xorl %edi,%ebp
+ xorl 36(%esp),%eax
+ andl %ecx,%ebp
+ xorl 56(%esp),%eax
+ roll $1,%eax
+ xorl %edi,%ebp
+ addl %ebp,%esi
+ movl %ebx,%ebp
+ rorl $2,%ecx
+ movl %eax,4(%esp)
+ roll $5,%ebp
+ leal 1518500249(%eax,%esi,1),%eax
+ movl 8(%esp),%esi
+ addl %ebp,%eax
+
+ movl %ecx,%ebp
+ xorl 16(%esp),%esi
+ xorl %edx,%ebp
+ xorl 40(%esp),%esi
+ andl %ebx,%ebp
+ xorl 60(%esp),%esi
+ roll $1,%esi
+ xorl %edx,%ebp
+ addl %ebp,%edi
+ movl %eax,%ebp
+ rorl $2,%ebx
+ movl %esi,8(%esp)
+ roll $5,%ebp
+ leal 1518500249(%esi,%edi,1),%esi
+ movl 12(%esp),%edi
+ addl %ebp,%esi
+
+ movl %ebx,%ebp
+ xorl 20(%esp),%edi
+ xorl %ecx,%ebp
+ xorl 44(%esp),%edi
+ andl %eax,%ebp
+ xorl (%esp),%edi
+ roll $1,%edi
+ xorl %ecx,%ebp
+ addl %ebp,%edx
+ movl %esi,%ebp
+ rorl $2,%eax
+ movl %edi,12(%esp)
+ roll $5,%ebp
+ leal 1518500249(%edi,%edx,1),%edi
+ movl 16(%esp),%edx
+ addl %ebp,%edi
+
+ movl %esi,%ebp
+ xorl 24(%esp),%edx
+ xorl %eax,%ebp
+ xorl 48(%esp),%edx
+ xorl %ebx,%ebp
+ xorl 4(%esp),%edx
+ roll $1,%edx
+ addl %ebp,%ecx
+ rorl $2,%esi
+ movl %edi,%ebp
+ roll $5,%ebp
+ movl %edx,16(%esp)
+ leal 1859775393(%edx,%ecx,1),%edx
+ movl 20(%esp),%ecx
+ addl %ebp,%edx
+
+ movl %edi,%ebp
+ xorl 28(%esp),%ecx
+ xorl %esi,%ebp
+ xorl 52(%esp),%ecx
+ xorl %eax,%ebp
+ xorl 8(%esp),%ecx
+ roll $1,%ecx
+ addl %ebp,%ebx
+ rorl $2,%edi
+ movl %edx,%ebp
+ roll $5,%ebp
+ movl %ecx,20(%esp)
+ leal 1859775393(%ecx,%ebx,1),%ecx
+ movl 24(%esp),%ebx
+ addl %ebp,%ecx
+
+ movl %edx,%ebp
+ xorl 32(%esp),%ebx
+ xorl %edi,%ebp
+ xorl 56(%esp),%ebx
+ xorl %esi,%ebp
+ xorl 12(%esp),%ebx
+ roll $1,%ebx
+ addl %ebp,%eax
+ rorl $2,%edx
+ movl %ecx,%ebp
+ roll $5,%ebp
+ movl %ebx,24(%esp)
+ leal 1859775393(%ebx,%eax,1),%ebx
+ movl 28(%esp),%eax
+ addl %ebp,%ebx
+
+ movl %ecx,%ebp
+ xorl 36(%esp),%eax
+ xorl %edx,%ebp
+ xorl 60(%esp),%eax
+ xorl %edi,%ebp
+ xorl 16(%esp),%eax
+ roll $1,%eax
+ addl %ebp,%esi
+ rorl $2,%ecx
+ movl %ebx,%ebp
+ roll $5,%ebp
+ movl %eax,28(%esp)
+ leal 1859775393(%eax,%esi,1),%eax
+ movl 32(%esp),%esi
+ addl %ebp,%eax
+
+ movl %ebx,%ebp
+ xorl 40(%esp),%esi
+ xorl %ecx,%ebp
+ xorl (%esp),%esi
+ xorl %edx,%ebp
+ xorl 20(%esp),%esi
+ roll $1,%esi
+ addl %ebp,%edi
+ rorl $2,%ebx
+ movl %eax,%ebp
+ roll $5,%ebp
+ movl %esi,32(%esp)
+ leal 1859775393(%esi,%edi,1),%esi
+ movl 36(%esp),%edi
+ addl %ebp,%esi
+
+ movl %eax,%ebp
+ xorl 44(%esp),%edi
+ xorl %ebx,%ebp
+ xorl 4(%esp),%edi
+ xorl %ecx,%ebp
+ xorl 24(%esp),%edi
+ roll $1,%edi
+ addl %ebp,%edx
+ rorl $2,%eax
+ movl %esi,%ebp
+ roll $5,%ebp
+ movl %edi,36(%esp)
+ leal 1859775393(%edi,%edx,1),%edi
+ movl 40(%esp),%edx
+ addl %ebp,%edi
+
+ movl %esi,%ebp
+ xorl 48(%esp),%edx
+ xorl %eax,%ebp
+ xorl 8(%esp),%edx
+ xorl %ebx,%ebp
+ xorl 28(%esp),%edx
+ roll $1,%edx
+ addl %ebp,%ecx
+ rorl $2,%esi
+ movl %edi,%ebp
+ roll $5,%ebp
+ movl %edx,40(%esp)
+ leal 1859775393(%edx,%ecx,1),%edx
+ movl 44(%esp),%ecx
+ addl %ebp,%edx
+
+ movl %edi,%ebp
+ xorl 52(%esp),%ecx
+ xorl %esi,%ebp
+ xorl 12(%esp),%ecx
+ xorl %eax,%ebp
+ xorl 32(%esp),%ecx
+ roll $1,%ecx
+ addl %ebp,%ebx
+ rorl $2,%edi
+ movl %edx,%ebp
+ roll $5,%ebp
+ movl %ecx,44(%esp)
+ leal 1859775393(%ecx,%ebx,1),%ecx
+ movl 48(%esp),%ebx
+ addl %ebp,%ecx
+
+ movl %edx,%ebp
+ xorl 56(%esp),%ebx
+ xorl %edi,%ebp
+ xorl 16(%esp),%ebx
+ xorl %esi,%ebp
+ xorl 36(%esp),%ebx
+ roll $1,%ebx
+ addl %ebp,%eax
+ rorl $2,%edx
+ movl %ecx,%ebp
+ roll $5,%ebp
+ movl %ebx,48(%esp)
+ leal 1859775393(%ebx,%eax,1),%ebx
+ movl 52(%esp),%eax
+ addl %ebp,%ebx
+
+ movl %ecx,%ebp
+ xorl 60(%esp),%eax
+ xorl %edx,%ebp
+ xorl 20(%esp),%eax
+ xorl %edi,%ebp
+ xorl 40(%esp),%eax
+ roll $1,%eax
+ addl %ebp,%esi
+ rorl $2,%ecx
+ movl %ebx,%ebp
+ roll $5,%ebp
+ movl %eax,52(%esp)
+ leal 1859775393(%eax,%esi,1),%eax
+ movl 56(%esp),%esi
+ addl %ebp,%eax
+
+ movl %ebx,%ebp
+ xorl (%esp),%esi
+ xorl %ecx,%ebp
+ xorl 24(%esp),%esi
+ xorl %edx,%ebp
+ xorl 44(%esp),%esi
+ roll $1,%esi
+ addl %ebp,%edi
+ rorl $2,%ebx
+ movl %eax,%ebp
+ roll $5,%ebp
+ movl %esi,56(%esp)
+ leal 1859775393(%esi,%edi,1),%esi
+ movl 60(%esp),%edi
+ addl %ebp,%esi
+
+ movl %eax,%ebp
+ xorl 4(%esp),%edi
+ xorl %ebx,%ebp
+ xorl 28(%esp),%edi
+ xorl %ecx,%ebp
+ xorl 48(%esp),%edi
+ roll $1,%edi
+ addl %ebp,%edx
+ rorl $2,%eax
+ movl %esi,%ebp
+ roll $5,%ebp
+ movl %edi,60(%esp)
+ leal 1859775393(%edi,%edx,1),%edi
+ movl (%esp),%edx
+ addl %ebp,%edi
+
+ movl %esi,%ebp
+ xorl 8(%esp),%edx
+ xorl %eax,%ebp
+ xorl 32(%esp),%edx
+ xorl %ebx,%ebp
+ xorl 52(%esp),%edx
+ roll $1,%edx
+ addl %ebp,%ecx
+ rorl $2,%esi
+ movl %edi,%ebp
+ roll $5,%ebp
+ movl %edx,(%esp)
+ leal 1859775393(%edx,%ecx,1),%edx
+ movl 4(%esp),%ecx
+ addl %ebp,%edx
+
+ movl %edi,%ebp
+ xorl 12(%esp),%ecx
+ xorl %esi,%ebp
+ xorl 36(%esp),%ecx
+ xorl %eax,%ebp
+ xorl 56(%esp),%ecx
+ roll $1,%ecx
+ addl %ebp,%ebx
+ rorl $2,%edi
+ movl %edx,%ebp
+ roll $5,%ebp
+ movl %ecx,4(%esp)
+ leal 1859775393(%ecx,%ebx,1),%ecx
+ movl 8(%esp),%ebx
+ addl %ebp,%ecx
+
+ movl %edx,%ebp
+ xorl 16(%esp),%ebx
+ xorl %edi,%ebp
+ xorl 40(%esp),%ebx
+ xorl %esi,%ebp
+ xorl 60(%esp),%ebx
+ roll $1,%ebx
+ addl %ebp,%eax
+ rorl $2,%edx
+ movl %ecx,%ebp
+ roll $5,%ebp
+ movl %ebx,8(%esp)
+ leal 1859775393(%ebx,%eax,1),%ebx
+ movl 12(%esp),%eax
+ addl %ebp,%ebx
+
+ movl %ecx,%ebp
+ xorl 20(%esp),%eax
+ xorl %edx,%ebp
+ xorl 44(%esp),%eax
+ xorl %edi,%ebp
+ xorl (%esp),%eax
+ roll $1,%eax
+ addl %ebp,%esi
+ rorl $2,%ecx
+ movl %ebx,%ebp
+ roll $5,%ebp
+ movl %eax,12(%esp)
+ leal 1859775393(%eax,%esi,1),%eax
+ movl 16(%esp),%esi
+ addl %ebp,%eax
+
+ movl %ebx,%ebp
+ xorl 24(%esp),%esi
+ xorl %ecx,%ebp
+ xorl 48(%esp),%esi
+ xorl %edx,%ebp
+ xorl 4(%esp),%esi
+ roll $1,%esi
+ addl %ebp,%edi
+ rorl $2,%ebx
+ movl %eax,%ebp
+ roll $5,%ebp
+ movl %esi,16(%esp)
+ leal 1859775393(%esi,%edi,1),%esi
+ movl 20(%esp),%edi
+ addl %ebp,%esi
+
+ movl %eax,%ebp
+ xorl 28(%esp),%edi
+ xorl %ebx,%ebp
+ xorl 52(%esp),%edi
+ xorl %ecx,%ebp
+ xorl 8(%esp),%edi
+ roll $1,%edi
+ addl %ebp,%edx
+ rorl $2,%eax
+ movl %esi,%ebp
+ roll $5,%ebp
+ movl %edi,20(%esp)
+ leal 1859775393(%edi,%edx,1),%edi
+ movl 24(%esp),%edx
+ addl %ebp,%edi
+
+ movl %esi,%ebp
+ xorl 32(%esp),%edx
+ xorl %eax,%ebp
+ xorl 56(%esp),%edx
+ xorl %ebx,%ebp
+ xorl 12(%esp),%edx
+ roll $1,%edx
+ addl %ebp,%ecx
+ rorl $2,%esi
+ movl %edi,%ebp
+ roll $5,%ebp
+ movl %edx,24(%esp)
+ leal 1859775393(%edx,%ecx,1),%edx
+ movl 28(%esp),%ecx
+ addl %ebp,%edx
+
+ movl %edi,%ebp
+ xorl 36(%esp),%ecx
+ xorl %esi,%ebp
+ xorl 60(%esp),%ecx
+ xorl %eax,%ebp
+ xorl 16(%esp),%ecx
+ roll $1,%ecx
+ addl %ebp,%ebx
+ rorl $2,%edi
+ movl %edx,%ebp
+ roll $5,%ebp
+ movl %ecx,28(%esp)
+ leal 1859775393(%ecx,%ebx,1),%ecx
+ movl 32(%esp),%ebx
+ addl %ebp,%ecx
+
+ movl %edi,%ebp
+ xorl 40(%esp),%ebx
+ xorl %esi,%ebp
+ xorl (%esp),%ebx
+ andl %edx,%ebp
+ xorl 20(%esp),%ebx
+ roll $1,%ebx
+ addl %eax,%ebp
+ rorl $2,%edx
+ movl %ecx,%eax
+ roll $5,%eax
+ movl %ebx,32(%esp)
+ leal 2400959708(%ebx,%ebp,1),%ebx
+ movl %edi,%ebp
+ addl %eax,%ebx
+ andl %esi,%ebp
+ movl 36(%esp),%eax
+ addl %ebp,%ebx
+
+ movl %edx,%ebp
+ xorl 44(%esp),%eax
+ xorl %edi,%ebp
+ xorl 4(%esp),%eax
+ andl %ecx,%ebp
+ xorl 24(%esp),%eax
+ roll $1,%eax
+ addl %esi,%ebp
+ rorl $2,%ecx
+ movl %ebx,%esi
+ roll $5,%esi
+ movl %eax,36(%esp)
+ leal 2400959708(%eax,%ebp,1),%eax
+ movl %edx,%ebp
+ addl %esi,%eax
+ andl %edi,%ebp
+ movl 40(%esp),%esi
+ addl %ebp,%eax
+
+ movl %ecx,%ebp
+ xorl 48(%esp),%esi
+ xorl %edx,%ebp
+ xorl 8(%esp),%esi
+ andl %ebx,%ebp
+ xorl 28(%esp),%esi
+ roll $1,%esi
+ addl %edi,%ebp
+ rorl $2,%ebx
+ movl %eax,%edi
+ roll $5,%edi
+ movl %esi,40(%esp)
+ leal 2400959708(%esi,%ebp,1),%esi
+ movl %ecx,%ebp
+ addl %edi,%esi
+ andl %edx,%ebp
+ movl 44(%esp),%edi
+ addl %ebp,%esi
+
+ movl %ebx,%ebp
+ xorl 52(%esp),%edi
+ xorl %ecx,%ebp
+ xorl 12(%esp),%edi
+ andl %eax,%ebp
+ xorl 32(%esp),%edi
+ roll $1,%edi
+ addl %edx,%ebp
+ rorl $2,%eax
+ movl %esi,%edx
+ roll $5,%edx
+ movl %edi,44(%esp)
+ leal 2400959708(%edi,%ebp,1),%edi
+ movl %ebx,%ebp
+ addl %edx,%edi
+ andl %ecx,%ebp
+ movl 48(%esp),%edx
+ addl %ebp,%edi
+
+ movl %eax,%ebp
+ xorl 56(%esp),%edx
+ xorl %ebx,%ebp
+ xorl 16(%esp),%edx
+ andl %esi,%ebp
+ xorl 36(%esp),%edx
+ roll $1,%edx
+ addl %ecx,%ebp
+ rorl $2,%esi
+ movl %edi,%ecx
+ roll $5,%ecx
+ movl %edx,48(%esp)
+ leal 2400959708(%edx,%ebp,1),%edx
+ movl %eax,%ebp
+ addl %ecx,%edx
+ andl %ebx,%ebp
+ movl 52(%esp),%ecx
+ addl %ebp,%edx
+
+ movl %esi,%ebp
+ xorl 60(%esp),%ecx
+ xorl %eax,%ebp
+ xorl 20(%esp),%ecx
+ andl %edi,%ebp
+ xorl 40(%esp),%ecx
+ roll $1,%ecx
+ addl %ebx,%ebp
+ rorl $2,%edi
+ movl %edx,%ebx
+ roll $5,%ebx
+ movl %ecx,52(%esp)
+ leal 2400959708(%ecx,%ebp,1),%ecx
+ movl %esi,%ebp
+ addl %ebx,%ecx
+ andl %eax,%ebp
+ movl 56(%esp),%ebx
+ addl %ebp,%ecx
+
+ movl %edi,%ebp
+ xorl (%esp),%ebx
+ xorl %esi,%ebp
+ xorl 24(%esp),%ebx
+ andl %edx,%ebp
+ xorl 44(%esp),%ebx
+ roll $1,%ebx
+ addl %eax,%ebp
+ rorl $2,%edx
+ movl %ecx,%eax
+ roll $5,%eax
+ movl %ebx,56(%esp)
+ leal 2400959708(%ebx,%ebp,1),%ebx
+ movl %edi,%ebp
+ addl %eax,%ebx
+ andl %esi,%ebp
+ movl 60(%esp),%eax
+ addl %ebp,%ebx
+
+ movl %edx,%ebp
+ xorl 4(%esp),%eax
+ xorl %edi,%ebp
+ xorl 28(%esp),%eax
+ andl %ecx,%ebp
+ xorl 48(%esp),%eax
+ roll $1,%eax
+ addl %esi,%ebp
+ rorl $2,%ecx
+ movl %ebx,%esi
+ roll $5,%esi
+ movl %eax,60(%esp)
+ leal 2400959708(%eax,%ebp,1),%eax
+ movl %edx,%ebp
+ addl %esi,%eax
+ andl %edi,%ebp
+ movl (%esp),%esi
+ addl %ebp,%eax
+
+ movl %ecx,%ebp
+ xorl 8(%esp),%esi
+ xorl %edx,%ebp
+ xorl 32(%esp),%esi
+ andl %ebx,%ebp
+ xorl 52(%esp),%esi
+ roll $1,%esi
+ addl %edi,%ebp
+ rorl $2,%ebx
+ movl %eax,%edi
+ roll $5,%edi
+ movl %esi,(%esp)
+ leal 2400959708(%esi,%ebp,1),%esi
+ movl %ecx,%ebp
+ addl %edi,%esi
+ andl %edx,%ebp
+ movl 4(%esp),%edi
+ addl %ebp,%esi
+
+ movl %ebx,%ebp
+ xorl 12(%esp),%edi
+ xorl %ecx,%ebp
+ xorl 36(%esp),%edi
+ andl %eax,%ebp
+ xorl 56(%esp),%edi
+ roll $1,%edi
+ addl %edx,%ebp
+ rorl $2,%eax
+ movl %esi,%edx
+ roll $5,%edx
+ movl %edi,4(%esp)
+ leal 2400959708(%edi,%ebp,1),%edi
+ movl %ebx,%ebp
+ addl %edx,%edi
+ andl %ecx,%ebp
+ movl 8(%esp),%edx
+ addl %ebp,%edi
+
+ movl %eax,%ebp
+ xorl 16(%esp),%edx
+ xorl %ebx,%ebp
+ xorl 40(%esp),%edx
+ andl %esi,%ebp
+ xorl 60(%esp),%edx
+ roll $1,%edx
+ addl %ecx,%ebp
+ rorl $2,%esi
+ movl %edi,%ecx
+ roll $5,%ecx
+ movl %edx,8(%esp)
+ leal 2400959708(%edx,%ebp,1),%edx
+ movl %eax,%ebp
+ addl %ecx,%edx
+ andl %ebx,%ebp
+ movl 12(%esp),%ecx
+ addl %ebp,%edx
+
+ movl %esi,%ebp
+ xorl 20(%esp),%ecx
+ xorl %eax,%ebp
+ xorl 44(%esp),%ecx
+ andl %edi,%ebp
+ xorl (%esp),%ecx
+ roll $1,%ecx
+ addl %ebx,%ebp
+ rorl $2,%edi
+ movl %edx,%ebx
+ roll $5,%ebx
+ movl %ecx,12(%esp)
+ leal 2400959708(%ecx,%ebp,1),%ecx
+ movl %esi,%ebp
+ addl %ebx,%ecx
+ andl %eax,%ebp
+ movl 16(%esp),%ebx
+ addl %ebp,%ecx
+
+ movl %edi,%ebp
+ xorl 24(%esp),%ebx
+ xorl %esi,%ebp
+ xorl 48(%esp),%ebx
+ andl %edx,%ebp
+ xorl 4(%esp),%ebx
+ roll $1,%ebx
+ addl %eax,%ebp
+ rorl $2,%edx
+ movl %ecx,%eax
+ roll $5,%eax
+ movl %ebx,16(%esp)
+ leal 2400959708(%ebx,%ebp,1),%ebx
+ movl %edi,%ebp
+ addl %eax,%ebx
+ andl %esi,%ebp
+ movl 20(%esp),%eax
+ addl %ebp,%ebx
+
+ movl %edx,%ebp
+ xorl 28(%esp),%eax
+ xorl %edi,%ebp
+ xorl 52(%esp),%eax
+ andl %ecx,%ebp
+ xorl 8(%esp),%eax
+ roll $1,%eax
+ addl %esi,%ebp
+ rorl $2,%ecx
+ movl %ebx,%esi
+ roll $5,%esi
+ movl %eax,20(%esp)
+ leal 2400959708(%eax,%ebp,1),%eax
+ movl %edx,%ebp
+ addl %esi,%eax
+ andl %edi,%ebp
+ movl 24(%esp),%esi
+ addl %ebp,%eax
+
+ movl %ecx,%ebp
+ xorl 32(%esp),%esi
+ xorl %edx,%ebp
+ xorl 56(%esp),%esi
+ andl %ebx,%ebp
+ xorl 12(%esp),%esi
+ roll $1,%esi
+ addl %edi,%ebp
+ rorl $2,%ebx
+ movl %eax,%edi
+ roll $5,%edi
+ movl %esi,24(%esp)
+ leal 2400959708(%esi,%ebp,1),%esi
+ movl %ecx,%ebp
+ addl %edi,%esi
+ andl %edx,%ebp
+ movl 28(%esp),%edi
+ addl %ebp,%esi
+
+ movl %ebx,%ebp
+ xorl 36(%esp),%edi
+ xorl %ecx,%ebp
+ xorl 60(%esp),%edi
+ andl %eax,%ebp
+ xorl 16(%esp),%edi
+ roll $1,%edi
+ addl %edx,%ebp
+ rorl $2,%eax
+ movl %esi,%edx
+ roll $5,%edx
+ movl %edi,28(%esp)
+ leal 2400959708(%edi,%ebp,1),%edi
+ movl %ebx,%ebp
+ addl %edx,%edi
+ andl %ecx,%ebp
+ movl 32(%esp),%edx
+ addl %ebp,%edi
+
+ movl %eax,%ebp
+ xorl 40(%esp),%edx
+ xorl %ebx,%ebp
+ xorl (%esp),%edx
+ andl %esi,%ebp
+ xorl 20(%esp),%edx
+ roll $1,%edx
+ addl %ecx,%ebp
+ rorl $2,%esi
+ movl %edi,%ecx
+ roll $5,%ecx
+ movl %edx,32(%esp)
+ leal 2400959708(%edx,%ebp,1),%edx
+ movl %eax,%ebp
+ addl %ecx,%edx
+ andl %ebx,%ebp
+ movl 36(%esp),%ecx
+ addl %ebp,%edx
+
+ movl %esi,%ebp
+ xorl 44(%esp),%ecx
+ xorl %eax,%ebp
+ xorl 4(%esp),%ecx
+ andl %edi,%ebp
+ xorl 24(%esp),%ecx
+ roll $1,%ecx
+ addl %ebx,%ebp
+ rorl $2,%edi
+ movl %edx,%ebx
+ roll $5,%ebx
+ movl %ecx,36(%esp)
+ leal 2400959708(%ecx,%ebp,1),%ecx
+ movl %esi,%ebp
+ addl %ebx,%ecx
+ andl %eax,%ebp
+ movl 40(%esp),%ebx
+ addl %ebp,%ecx
+
+ movl %edi,%ebp
+ xorl 48(%esp),%ebx
+ xorl %esi,%ebp
+ xorl 8(%esp),%ebx
+ andl %edx,%ebp
+ xorl 28(%esp),%ebx
+ roll $1,%ebx
+ addl %eax,%ebp
+ rorl $2,%edx
+ movl %ecx,%eax
+ roll $5,%eax
+ movl %ebx,40(%esp)
+ leal 2400959708(%ebx,%ebp,1),%ebx
+ movl %edi,%ebp
+ addl %eax,%ebx
+ andl %esi,%ebp
+ movl 44(%esp),%eax
+ addl %ebp,%ebx
+
+ movl %edx,%ebp
+ xorl 52(%esp),%eax
+ xorl %edi,%ebp
+ xorl 12(%esp),%eax
+ andl %ecx,%ebp
+ xorl 32(%esp),%eax
+ roll $1,%eax
+ addl %esi,%ebp
+ rorl $2,%ecx
+ movl %ebx,%esi
+ roll $5,%esi
+ movl %eax,44(%esp)
+ leal 2400959708(%eax,%ebp,1),%eax
+ movl %edx,%ebp
+ addl %esi,%eax
+ andl %edi,%ebp
+ movl 48(%esp),%esi
+ addl %ebp,%eax
+
+ movl %ebx,%ebp
+ xorl 56(%esp),%esi
+ xorl %ecx,%ebp
+ xorl 16(%esp),%esi
+ xorl %edx,%ebp
+ xorl 36(%esp),%esi
+ roll $1,%esi
+ addl %ebp,%edi
+ rorl $2,%ebx
+ movl %eax,%ebp
+ roll $5,%ebp
+ movl %esi,48(%esp)
+ leal 3395469782(%esi,%edi,1),%esi
+ movl 52(%esp),%edi
+ addl %ebp,%esi
+
+ movl %eax,%ebp
+ xorl 60(%esp),%edi
+ xorl %ebx,%ebp
+ xorl 20(%esp),%edi
+ xorl %ecx,%ebp
+ xorl 40(%esp),%edi
+ roll $1,%edi
+ addl %ebp,%edx
+ rorl $2,%eax
+ movl %esi,%ebp
+ roll $5,%ebp
+ movl %edi,52(%esp)
+ leal 3395469782(%edi,%edx,1),%edi
+ movl 56(%esp),%edx
+ addl %ebp,%edi
+
+ movl %esi,%ebp
+ xorl (%esp),%edx
+ xorl %eax,%ebp
+ xorl 24(%esp),%edx
+ xorl %ebx,%ebp
+ xorl 44(%esp),%edx
+ roll $1,%edx
+ addl %ebp,%ecx
+ rorl $2,%esi
+ movl %edi,%ebp
+ roll $5,%ebp
+ movl %edx,56(%esp)
+ leal 3395469782(%edx,%ecx,1),%edx
+ movl 60(%esp),%ecx
+ addl %ebp,%edx
+
+ movl %edi,%ebp
+ xorl 4(%esp),%ecx
+ xorl %esi,%ebp
+ xorl 28(%esp),%ecx
+ xorl %eax,%ebp
+ xorl 48(%esp),%ecx
+ roll $1,%ecx
+ addl %ebp,%ebx
+ rorl $2,%edi
+ movl %edx,%ebp
+ roll $5,%ebp
+ movl %ecx,60(%esp)
+ leal 3395469782(%ecx,%ebx,1),%ecx
+ movl (%esp),%ebx
+ addl %ebp,%ecx
+
+ movl %edx,%ebp
+ xorl 8(%esp),%ebx
+ xorl %edi,%ebp
+ xorl 32(%esp),%ebx
+ xorl %esi,%ebp
+ xorl 52(%esp),%ebx
+ roll $1,%ebx
+ addl %ebp,%eax
+ rorl $2,%edx
+ movl %ecx,%ebp
+ roll $5,%ebp
+ movl %ebx,(%esp)
+ leal 3395469782(%ebx,%eax,1),%ebx
+ movl 4(%esp),%eax
+ addl %ebp,%ebx
+
+ movl %ecx,%ebp
+ xorl 12(%esp),%eax
+ xorl %edx,%ebp
+ xorl 36(%esp),%eax
+ xorl %edi,%ebp
+ xorl 56(%esp),%eax
+ roll $1,%eax
+ addl %ebp,%esi
+ rorl $2,%ecx
+ movl %ebx,%ebp
+ roll $5,%ebp
+ movl %eax,4(%esp)
+ leal 3395469782(%eax,%esi,1),%eax
+ movl 8(%esp),%esi
+ addl %ebp,%eax
+
+ movl %ebx,%ebp
+ xorl 16(%esp),%esi
+ xorl %ecx,%ebp
+ xorl 40(%esp),%esi
+ xorl %edx,%ebp
+ xorl 60(%esp),%esi
+ roll $1,%esi
+ addl %ebp,%edi
+ rorl $2,%ebx
+ movl %eax,%ebp
+ roll $5,%ebp
+ movl %esi,8(%esp)
+ leal 3395469782(%esi,%edi,1),%esi
+ movl 12(%esp),%edi
+ addl %ebp,%esi
+
+ movl %eax,%ebp
+ xorl 20(%esp),%edi
+ xorl %ebx,%ebp
+ xorl 44(%esp),%edi
+ xorl %ecx,%ebp
+ xorl (%esp),%edi
+ roll $1,%edi
+ addl %ebp,%edx
+ rorl $2,%eax
+ movl %esi,%ebp
+ roll $5,%ebp
+ movl %edi,12(%esp)
+ leal 3395469782(%edi,%edx,1),%edi
+ movl 16(%esp),%edx
+ addl %ebp,%edi
+
+ movl %esi,%ebp
+ xorl 24(%esp),%edx
+ xorl %eax,%ebp
+ xorl 48(%esp),%edx
+ xorl %ebx,%ebp
+ xorl 4(%esp),%edx
+ roll $1,%edx
+ addl %ebp,%ecx
+ rorl $2,%esi
+ movl %edi,%ebp
+ roll $5,%ebp
+ movl %edx,16(%esp)
+ leal 3395469782(%edx,%ecx,1),%edx
+ movl 20(%esp),%ecx
+ addl %ebp,%edx
+
+ movl %edi,%ebp
+ xorl 28(%esp),%ecx
+ xorl %esi,%ebp
+ xorl 52(%esp),%ecx
+ xorl %eax,%ebp
+ xorl 8(%esp),%ecx
+ roll $1,%ecx
+ addl %ebp,%ebx
+ rorl $2,%edi
+ movl %edx,%ebp
+ roll $5,%ebp
+ movl %ecx,20(%esp)
+ leal 3395469782(%ecx,%ebx,1),%ecx
+ movl 24(%esp),%ebx
+ addl %ebp,%ecx
+
+ movl %edx,%ebp
+ xorl 32(%esp),%ebx
+ xorl %edi,%ebp
+ xorl 56(%esp),%ebx
+ xorl %esi,%ebp
+ xorl 12(%esp),%ebx
+ roll $1,%ebx
+ addl %ebp,%eax
+ rorl $2,%edx
+ movl %ecx,%ebp
+ roll $5,%ebp
+ movl %ebx,24(%esp)
+ leal 3395469782(%ebx,%eax,1),%ebx
+ movl 28(%esp),%eax
+ addl %ebp,%ebx
+
+ movl %ecx,%ebp
+ xorl 36(%esp),%eax
+ xorl %edx,%ebp
+ xorl 60(%esp),%eax
+ xorl %edi,%ebp
+ xorl 16(%esp),%eax
+ roll $1,%eax
+ addl %ebp,%esi
+ rorl $2,%ecx
+ movl %ebx,%ebp
+ roll $5,%ebp
+ movl %eax,28(%esp)
+ leal 3395469782(%eax,%esi,1),%eax
+ movl 32(%esp),%esi
+ addl %ebp,%eax
+
+ movl %ebx,%ebp
+ xorl 40(%esp),%esi
+ xorl %ecx,%ebp
+ xorl (%esp),%esi
+ xorl %edx,%ebp
+ xorl 20(%esp),%esi
+ roll $1,%esi
+ addl %ebp,%edi
+ rorl $2,%ebx
+ movl %eax,%ebp
+ roll $5,%ebp
+ movl %esi,32(%esp)
+ leal 3395469782(%esi,%edi,1),%esi
+ movl 36(%esp),%edi
+ addl %ebp,%esi
+
+ movl %eax,%ebp
+ xorl 44(%esp),%edi
+ xorl %ebx,%ebp
+ xorl 4(%esp),%edi
+ xorl %ecx,%ebp
+ xorl 24(%esp),%edi
+ roll $1,%edi
+ addl %ebp,%edx
+ rorl $2,%eax
+ movl %esi,%ebp
+ roll $5,%ebp
+ movl %edi,36(%esp)
+ leal 3395469782(%edi,%edx,1),%edi
+ movl 40(%esp),%edx
+ addl %ebp,%edi
+
+ movl %esi,%ebp
+ xorl 48(%esp),%edx
+ xorl %eax,%ebp
+ xorl 8(%esp),%edx
+ xorl %ebx,%ebp
+ xorl 28(%esp),%edx
+ roll $1,%edx
+ addl %ebp,%ecx
+ rorl $2,%esi
+ movl %edi,%ebp
+ roll $5,%ebp
+ movl %edx,40(%esp)
+ leal 3395469782(%edx,%ecx,1),%edx
+ movl 44(%esp),%ecx
+ addl %ebp,%edx
+
+ movl %edi,%ebp
+ xorl 52(%esp),%ecx
+ xorl %esi,%ebp
+ xorl 12(%esp),%ecx
+ xorl %eax,%ebp
+ xorl 32(%esp),%ecx
+ roll $1,%ecx
+ addl %ebp,%ebx
+ rorl $2,%edi
+ movl %edx,%ebp
+ roll $5,%ebp
+ movl %ecx,44(%esp)
+ leal 3395469782(%ecx,%ebx,1),%ecx
+ movl 48(%esp),%ebx
+ addl %ebp,%ecx
+
+ movl %edx,%ebp
+ xorl 56(%esp),%ebx
+ xorl %edi,%ebp
+ xorl 16(%esp),%ebx
+ xorl %esi,%ebp
+ xorl 36(%esp),%ebx
+ roll $1,%ebx
+ addl %ebp,%eax
+ rorl $2,%edx
+ movl %ecx,%ebp
+ roll $5,%ebp
+ movl %ebx,48(%esp)
+ leal 3395469782(%ebx,%eax,1),%ebx
+ movl 52(%esp),%eax
+ addl %ebp,%ebx
+
+ movl %ecx,%ebp
+ xorl 60(%esp),%eax
+ xorl %edx,%ebp
+ xorl 20(%esp),%eax
+ xorl %edi,%ebp
+ xorl 40(%esp),%eax
+ roll $1,%eax
+ addl %ebp,%esi
+ rorl $2,%ecx
+ movl %ebx,%ebp
+ roll $5,%ebp
+ leal 3395469782(%eax,%esi,1),%eax
+ movl 56(%esp),%esi
+ addl %ebp,%eax
+
+ movl %ebx,%ebp
+ xorl (%esp),%esi
+ xorl %ecx,%ebp
+ xorl 24(%esp),%esi
+ xorl %edx,%ebp
+ xorl 44(%esp),%esi
+ roll $1,%esi
+ addl %ebp,%edi
+ rorl $2,%ebx
+ movl %eax,%ebp
+ roll $5,%ebp
+ leal 3395469782(%esi,%edi,1),%esi
+ movl 60(%esp),%edi
+ addl %ebp,%esi
+
+ movl %eax,%ebp
+ xorl 4(%esp),%edi
+ xorl %ebx,%ebp
+ xorl 28(%esp),%edi
+ xorl %ecx,%ebp
+ xorl 48(%esp),%edi
+ roll $1,%edi
+ addl %ebp,%edx
+ rorl $2,%eax
+ movl %esi,%ebp
+ roll $5,%ebp
+ leal 3395469782(%edi,%edx,1),%edi
+ addl %ebp,%edi
+ movl 96(%esp),%ebp
+ movl 100(%esp),%edx
+ addl (%ebp),%edi
+ addl 4(%ebp),%esi
+ addl 8(%ebp),%eax
+ addl 12(%ebp),%ebx
+ addl 16(%ebp),%ecx
+ movl %edi,(%ebp)
+ addl $64,%edx
+ movl %esi,4(%ebp)
+ cmpl 104(%esp),%edx
+ movl %eax,8(%ebp)
+ movl %ecx,%edi
+ movl %ebx,12(%ebp)
+ movl %edx,%esi
+ movl %ecx,16(%ebp)
+ jb .L000loop
+ addl $76,%esp
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.size sha1_block_data_order,.-.L_sha1_block_data_order_begin
+.byte 83,72,65,49,32,98,108,111,99,107,32,116,114,97,110,115
+.byte 102,111,114,109,32,102,111,114,32,120,56,54,44,32,67,82
+.byte 89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112
+.byte 114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
+#endif
diff --git a/linux-x86/crypto/sha/sha256-586.S b/linux-x86/crypto/sha/sha256-586.S
new file mode 100644
index 0000000..fe41afc
--- /dev/null
+++ b/linux-x86/crypto/sha/sha256-586.S
@@ -0,0 +1,3350 @@
+#if defined(__i386__)
+.file "sha512-586.S"
+.text
+.globl sha256_block_data_order
+.hidden sha256_block_data_order
+.type sha256_block_data_order,@function
+.align 16
+sha256_block_data_order:
+.L_sha256_block_data_order_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ movl 20(%esp),%esi
+ movl 24(%esp),%edi
+ movl 28(%esp),%eax
+ movl %esp,%ebx
+ call .L000pic_point
+.L000pic_point:
+ popl %ebp
+ leal .L001K256-.L000pic_point(%ebp),%ebp
+ subl $16,%esp
+ andl $-64,%esp
+ shll $6,%eax
+ addl %edi,%eax
+ movl %esi,(%esp)
+ movl %edi,4(%esp)
+ movl %eax,8(%esp)
+ movl %ebx,12(%esp)
+ jmp .L002loop
+.align 16
+.L002loop:
+ movl (%edi),%eax
+ movl 4(%edi),%ebx
+ movl 8(%edi),%ecx
+ bswap %eax
+ movl 12(%edi),%edx
+ bswap %ebx
+ pushl %eax
+ bswap %ecx
+ pushl %ebx
+ bswap %edx
+ pushl %ecx
+ pushl %edx
+ movl 16(%edi),%eax
+ movl 20(%edi),%ebx
+ movl 24(%edi),%ecx
+ bswap %eax
+ movl 28(%edi),%edx
+ bswap %ebx
+ pushl %eax
+ bswap %ecx
+ pushl %ebx
+ bswap %edx
+ pushl %ecx
+ pushl %edx
+ movl 32(%edi),%eax
+ movl 36(%edi),%ebx
+ movl 40(%edi),%ecx
+ bswap %eax
+ movl 44(%edi),%edx
+ bswap %ebx
+ pushl %eax
+ bswap %ecx
+ pushl %ebx
+ bswap %edx
+ pushl %ecx
+ pushl %edx
+ movl 48(%edi),%eax
+ movl 52(%edi),%ebx
+ movl 56(%edi),%ecx
+ bswap %eax
+ movl 60(%edi),%edx
+ bswap %ebx
+ pushl %eax
+ bswap %ecx
+ pushl %ebx
+ bswap %edx
+ pushl %ecx
+ pushl %edx
+ addl $64,%edi
+ leal -36(%esp),%esp
+ movl %edi,104(%esp)
+ movl (%esi),%eax
+ movl 4(%esi),%ebx
+ movl 8(%esi),%ecx
+ movl 12(%esi),%edi
+ movl %ebx,8(%esp)
+ xorl %ecx,%ebx
+ movl %ecx,12(%esp)
+ movl %edi,16(%esp)
+ movl %ebx,(%esp)
+ movl 16(%esi),%edx
+ movl 20(%esi),%ebx
+ movl 24(%esi),%ecx
+ movl 28(%esi),%edi
+ movl %ebx,24(%esp)
+ movl %ecx,28(%esp)
+ movl %edi,32(%esp)
+.align 16
+.L00300_15:
+ movl %edx,%ecx
+ movl 24(%esp),%esi
+ rorl $14,%ecx
+ movl 28(%esp),%edi
+ xorl %edx,%ecx
+ xorl %edi,%esi
+ movl 96(%esp),%ebx
+ rorl $5,%ecx
+ andl %edx,%esi
+ movl %edx,20(%esp)
+ xorl %ecx,%edx
+ addl 32(%esp),%ebx
+ xorl %edi,%esi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %esi,%ebx
+ rorl $9,%ecx
+ addl %edx,%ebx
+ movl 8(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,4(%esp)
+ leal -4(%esp),%esp
+ rorl $11,%ecx
+ movl (%ebp),%esi
+ xorl %eax,%ecx
+ movl 20(%esp),%edx
+ xorl %edi,%eax
+ rorl $2,%ecx
+ addl %esi,%ebx
+ movl %eax,(%esp)
+ addl %ebx,%edx
+ andl 4(%esp),%eax
+ addl %ecx,%ebx
+ xorl %edi,%eax
+ addl $4,%ebp
+ addl %ebx,%eax
+ cmpl $3248222580,%esi
+ jne .L00300_15
+ movl 156(%esp),%ecx
+ jmp .L00416_63
+.align 16
+.L00416_63:
+ movl %ecx,%ebx
+ movl 104(%esp),%esi
+ rorl $11,%ecx
+ movl %esi,%edi
+ rorl $2,%esi
+ xorl %ebx,%ecx
+ shrl $3,%ebx
+ rorl $7,%ecx
+ xorl %edi,%esi
+ xorl %ecx,%ebx
+ rorl $17,%esi
+ addl 160(%esp),%ebx
+ shrl $10,%edi
+ addl 124(%esp),%ebx
+ movl %edx,%ecx
+ xorl %esi,%edi
+ movl 24(%esp),%esi
+ rorl $14,%ecx
+ addl %edi,%ebx
+ movl 28(%esp),%edi
+ xorl %edx,%ecx
+ xorl %edi,%esi
+ movl %ebx,96(%esp)
+ rorl $5,%ecx
+ andl %edx,%esi
+ movl %edx,20(%esp)
+ xorl %ecx,%edx
+ addl 32(%esp),%ebx
+ xorl %edi,%esi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %esi,%ebx
+ rorl $9,%ecx
+ addl %edx,%ebx
+ movl 8(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,4(%esp)
+ leal -4(%esp),%esp
+ rorl $11,%ecx
+ movl (%ebp),%esi
+ xorl %eax,%ecx
+ movl 20(%esp),%edx
+ xorl %edi,%eax
+ rorl $2,%ecx
+ addl %esi,%ebx
+ movl %eax,(%esp)
+ addl %ebx,%edx
+ andl 4(%esp),%eax
+ addl %ecx,%ebx
+ xorl %edi,%eax
+ movl 156(%esp),%ecx
+ addl $4,%ebp
+ addl %ebx,%eax
+ cmpl $3329325298,%esi
+ jne .L00416_63
+ movl 356(%esp),%esi
+ movl 8(%esp),%ebx
+ movl 16(%esp),%ecx
+ addl (%esi),%eax
+ addl 4(%esi),%ebx
+ addl 8(%esi),%edi
+ addl 12(%esi),%ecx
+ movl %eax,(%esi)
+ movl %ebx,4(%esi)
+ movl %edi,8(%esi)
+ movl %ecx,12(%esi)
+ movl 24(%esp),%eax
+ movl 28(%esp),%ebx
+ movl 32(%esp),%ecx
+ movl 360(%esp),%edi
+ addl 16(%esi),%edx
+ addl 20(%esi),%eax
+ addl 24(%esi),%ebx
+ addl 28(%esi),%ecx
+ movl %edx,16(%esi)
+ movl %eax,20(%esi)
+ movl %ebx,24(%esi)
+ movl %ecx,28(%esi)
+ leal 356(%esp),%esp
+ subl $256,%ebp
+ cmpl 8(%esp),%edi
+ jb .L002loop
+ movl 12(%esp),%esp
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.align 32
+.L005loop_shrd:
+ movl (%edi),%eax
+ movl 4(%edi),%ebx
+ movl 8(%edi),%ecx
+ bswap %eax
+ movl 12(%edi),%edx
+ bswap %ebx
+ pushl %eax
+ bswap %ecx
+ pushl %ebx
+ bswap %edx
+ pushl %ecx
+ pushl %edx
+ movl 16(%edi),%eax
+ movl 20(%edi),%ebx
+ movl 24(%edi),%ecx
+ bswap %eax
+ movl 28(%edi),%edx
+ bswap %ebx
+ pushl %eax
+ bswap %ecx
+ pushl %ebx
+ bswap %edx
+ pushl %ecx
+ pushl %edx
+ movl 32(%edi),%eax
+ movl 36(%edi),%ebx
+ movl 40(%edi),%ecx
+ bswap %eax
+ movl 44(%edi),%edx
+ bswap %ebx
+ pushl %eax
+ bswap %ecx
+ pushl %ebx
+ bswap %edx
+ pushl %ecx
+ pushl %edx
+ movl 48(%edi),%eax
+ movl 52(%edi),%ebx
+ movl 56(%edi),%ecx
+ bswap %eax
+ movl 60(%edi),%edx
+ bswap %ebx
+ pushl %eax
+ bswap %ecx
+ pushl %ebx
+ bswap %edx
+ pushl %ecx
+ pushl %edx
+ addl $64,%edi
+ leal -36(%esp),%esp
+ movl %edi,104(%esp)
+ movl (%esi),%eax
+ movl 4(%esi),%ebx
+ movl 8(%esi),%ecx
+ movl 12(%esi),%edi
+ movl %ebx,8(%esp)
+ xorl %ecx,%ebx
+ movl %ecx,12(%esp)
+ movl %edi,16(%esp)
+ movl %ebx,(%esp)
+ movl 16(%esi),%edx
+ movl 20(%esi),%ebx
+ movl 24(%esi),%ecx
+ movl 28(%esi),%edi
+ movl %ebx,24(%esp)
+ movl %ecx,28(%esp)
+ movl %edi,32(%esp)
+.align 16
+.L00600_15_shrd:
+ movl %edx,%ecx
+ movl 24(%esp),%esi
+ shrdl $14,%ecx,%ecx
+ movl 28(%esp),%edi
+ xorl %edx,%ecx
+ xorl %edi,%esi
+ movl 96(%esp),%ebx
+ shrdl $5,%ecx,%ecx
+ andl %edx,%esi
+ movl %edx,20(%esp)
+ xorl %ecx,%edx
+ addl 32(%esp),%ebx
+ xorl %edi,%esi
+ shrdl $6,%edx,%edx
+ movl %eax,%ecx
+ addl %esi,%ebx
+ shrdl $9,%ecx,%ecx
+ addl %edx,%ebx
+ movl 8(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,4(%esp)
+ leal -4(%esp),%esp
+ shrdl $11,%ecx,%ecx
+ movl (%ebp),%esi
+ xorl %eax,%ecx
+ movl 20(%esp),%edx
+ xorl %edi,%eax
+ shrdl $2,%ecx,%ecx
+ addl %esi,%ebx
+ movl %eax,(%esp)
+ addl %ebx,%edx
+ andl 4(%esp),%eax
+ addl %ecx,%ebx
+ xorl %edi,%eax
+ addl $4,%ebp
+ addl %ebx,%eax
+ cmpl $3248222580,%esi
+ jne .L00600_15_shrd
+ movl 156(%esp),%ecx
+ jmp .L00716_63_shrd
+.align 16
+.L00716_63_shrd:
+ movl %ecx,%ebx
+ movl 104(%esp),%esi
+ shrdl $11,%ecx,%ecx
+ movl %esi,%edi
+ shrdl $2,%esi,%esi
+ xorl %ebx,%ecx
+ shrl $3,%ebx
+ shrdl $7,%ecx,%ecx
+ xorl %edi,%esi
+ xorl %ecx,%ebx
+ shrdl $17,%esi,%esi
+ addl 160(%esp),%ebx
+ shrl $10,%edi
+ addl 124(%esp),%ebx
+ movl %edx,%ecx
+ xorl %esi,%edi
+ movl 24(%esp),%esi
+ shrdl $14,%ecx,%ecx
+ addl %edi,%ebx
+ movl 28(%esp),%edi
+ xorl %edx,%ecx
+ xorl %edi,%esi
+ movl %ebx,96(%esp)
+ shrdl $5,%ecx,%ecx
+ andl %edx,%esi
+ movl %edx,20(%esp)
+ xorl %ecx,%edx
+ addl 32(%esp),%ebx
+ xorl %edi,%esi
+ shrdl $6,%edx,%edx
+ movl %eax,%ecx
+ addl %esi,%ebx
+ shrdl $9,%ecx,%ecx
+ addl %edx,%ebx
+ movl 8(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,4(%esp)
+ leal -4(%esp),%esp
+ shrdl $11,%ecx,%ecx
+ movl (%ebp),%esi
+ xorl %eax,%ecx
+ movl 20(%esp),%edx
+ xorl %edi,%eax
+ shrdl $2,%ecx,%ecx
+ addl %esi,%ebx
+ movl %eax,(%esp)
+ addl %ebx,%edx
+ andl 4(%esp),%eax
+ addl %ecx,%ebx
+ xorl %edi,%eax
+ movl 156(%esp),%ecx
+ addl $4,%ebp
+ addl %ebx,%eax
+ cmpl $3329325298,%esi
+ jne .L00716_63_shrd
+ movl 356(%esp),%esi
+ movl 8(%esp),%ebx
+ movl 16(%esp),%ecx
+ addl (%esi),%eax
+ addl 4(%esi),%ebx
+ addl 8(%esi),%edi
+ addl 12(%esi),%ecx
+ movl %eax,(%esi)
+ movl %ebx,4(%esi)
+ movl %edi,8(%esi)
+ movl %ecx,12(%esi)
+ movl 24(%esp),%eax
+ movl 28(%esp),%ebx
+ movl 32(%esp),%ecx
+ movl 360(%esp),%edi
+ addl 16(%esi),%edx
+ addl 20(%esi),%eax
+ addl 24(%esi),%ebx
+ addl 28(%esi),%ecx
+ movl %edx,16(%esi)
+ movl %eax,20(%esi)
+ movl %ebx,24(%esi)
+ movl %ecx,28(%esi)
+ leal 356(%esp),%esp
+ subl $256,%ebp
+ cmpl 8(%esp),%edi
+ jb .L005loop_shrd
+ movl 12(%esp),%esp
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.align 64
+.L001K256:
+.long 1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298
+.long 66051,67438087,134810123,202182159
+.byte 83,72,65,50,53,54,32,98,108,111,99,107,32,116,114,97
+.byte 110,115,102,111,114,109,32,102,111,114,32,120,56,54,44,32
+.byte 67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97
+.byte 112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103
+.byte 62,0
+.align 16
+.L008unrolled:
+ leal -96(%esp),%esp
+ movl (%esi),%eax
+ movl 4(%esi),%ebp
+ movl 8(%esi),%ecx
+ movl 12(%esi),%ebx
+ movl %ebp,4(%esp)
+ xorl %ecx,%ebp
+ movl %ecx,8(%esp)
+ movl %ebx,12(%esp)
+ movl 16(%esi),%edx
+ movl 20(%esi),%ebx
+ movl 24(%esi),%ecx
+ movl 28(%esi),%esi
+ movl %ebx,20(%esp)
+ movl %ecx,24(%esp)
+ movl %esi,28(%esp)
+ jmp .L009grand_loop
+.align 16
+.L009grand_loop:
+ movl (%edi),%ebx
+ movl 4(%edi),%ecx
+ bswap %ebx
+ movl 8(%edi),%esi
+ bswap %ecx
+ movl %ebx,32(%esp)
+ bswap %esi
+ movl %ecx,36(%esp)
+ movl %esi,40(%esp)
+ movl 12(%edi),%ebx
+ movl 16(%edi),%ecx
+ bswap %ebx
+ movl 20(%edi),%esi
+ bswap %ecx
+ movl %ebx,44(%esp)
+ bswap %esi
+ movl %ecx,48(%esp)
+ movl %esi,52(%esp)
+ movl 24(%edi),%ebx
+ movl 28(%edi),%ecx
+ bswap %ebx
+ movl 32(%edi),%esi
+ bswap %ecx
+ movl %ebx,56(%esp)
+ bswap %esi
+ movl %ecx,60(%esp)
+ movl %esi,64(%esp)
+ movl 36(%edi),%ebx
+ movl 40(%edi),%ecx
+ bswap %ebx
+ movl 44(%edi),%esi
+ bswap %ecx
+ movl %ebx,68(%esp)
+ bswap %esi
+ movl %ecx,72(%esp)
+ movl %esi,76(%esp)
+ movl 48(%edi),%ebx
+ movl 52(%edi),%ecx
+ bswap %ebx
+ movl 56(%edi),%esi
+ bswap %ecx
+ movl %ebx,80(%esp)
+ bswap %esi
+ movl %ecx,84(%esp)
+ movl %esi,88(%esp)
+ movl 60(%edi),%ebx
+ addl $64,%edi
+ bswap %ebx
+ movl %edi,100(%esp)
+ movl %ebx,92(%esp)
+ movl %edx,%ecx
+ movl 20(%esp),%esi
+ rorl $14,%edx
+ movl 24(%esp),%edi
+ xorl %ecx,%edx
+ movl 32(%esp),%ebx
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,16(%esp)
+ xorl %ecx,%edx
+ addl 28(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 4(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 1116352408(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 12(%esp),%edx
+ addl %ecx,%ebp
+ movl %edx,%esi
+ movl 16(%esp),%ecx
+ rorl $14,%edx
+ movl 20(%esp),%edi
+ xorl %esi,%edx
+ movl 36(%esp),%ebx
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,12(%esp)
+ xorl %esi,%edx
+ addl 24(%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl (%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,28(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 1899447441(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ rorl $2,%esi
+ addl %edx,%eax
+ addl 8(%esp),%edx
+ addl %esi,%eax
+ movl %edx,%ecx
+ movl 12(%esp),%esi
+ rorl $14,%edx
+ movl 16(%esp),%edi
+ xorl %ecx,%edx
+ movl 40(%esp),%ebx
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,8(%esp)
+ xorl %ecx,%edx
+ addl 20(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 28(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,24(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 3049323471(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 4(%esp),%edx
+ addl %ecx,%ebp
+ movl %edx,%esi
+ movl 8(%esp),%ecx
+ rorl $14,%edx
+ movl 12(%esp),%edi
+ xorl %esi,%edx
+ movl 44(%esp),%ebx
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,4(%esp)
+ xorl %esi,%edx
+ addl 16(%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl 24(%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,20(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 3921009573(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ rorl $2,%esi
+ addl %edx,%eax
+ addl (%esp),%edx
+ addl %esi,%eax
+ movl %edx,%ecx
+ movl 4(%esp),%esi
+ rorl $14,%edx
+ movl 8(%esp),%edi
+ xorl %ecx,%edx
+ movl 48(%esp),%ebx
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,(%esp)
+ xorl %ecx,%edx
+ addl 12(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 20(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,16(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 961987163(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 28(%esp),%edx
+ addl %ecx,%ebp
+ movl %edx,%esi
+ movl (%esp),%ecx
+ rorl $14,%edx
+ movl 4(%esp),%edi
+ xorl %esi,%edx
+ movl 52(%esp),%ebx
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,28(%esp)
+ xorl %esi,%edx
+ addl 8(%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl 16(%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,12(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 1508970993(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ rorl $2,%esi
+ addl %edx,%eax
+ addl 24(%esp),%edx
+ addl %esi,%eax
+ movl %edx,%ecx
+ movl 28(%esp),%esi
+ rorl $14,%edx
+ movl (%esp),%edi
+ xorl %ecx,%edx
+ movl 56(%esp),%ebx
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,24(%esp)
+ xorl %ecx,%edx
+ addl 4(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 12(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,8(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 2453635748(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 20(%esp),%edx
+ addl %ecx,%ebp
+ movl %edx,%esi
+ movl 24(%esp),%ecx
+ rorl $14,%edx
+ movl 28(%esp),%edi
+ xorl %esi,%edx
+ movl 60(%esp),%ebx
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,20(%esp)
+ xorl %esi,%edx
+ addl (%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl 8(%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,4(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 2870763221(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ rorl $2,%esi
+ addl %edx,%eax
+ addl 16(%esp),%edx
+ addl %esi,%eax
+ movl %edx,%ecx
+ movl 20(%esp),%esi
+ rorl $14,%edx
+ movl 24(%esp),%edi
+ xorl %ecx,%edx
+ movl 64(%esp),%ebx
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,16(%esp)
+ xorl %ecx,%edx
+ addl 28(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 4(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 3624381080(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 12(%esp),%edx
+ addl %ecx,%ebp
+ movl %edx,%esi
+ movl 16(%esp),%ecx
+ rorl $14,%edx
+ movl 20(%esp),%edi
+ xorl %esi,%edx
+ movl 68(%esp),%ebx
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,12(%esp)
+ xorl %esi,%edx
+ addl 24(%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl (%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,28(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 310598401(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ rorl $2,%esi
+ addl %edx,%eax
+ addl 8(%esp),%edx
+ addl %esi,%eax
+ movl %edx,%ecx
+ movl 12(%esp),%esi
+ rorl $14,%edx
+ movl 16(%esp),%edi
+ xorl %ecx,%edx
+ movl 72(%esp),%ebx
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,8(%esp)
+ xorl %ecx,%edx
+ addl 20(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 28(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,24(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 607225278(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 4(%esp),%edx
+ addl %ecx,%ebp
+ movl %edx,%esi
+ movl 8(%esp),%ecx
+ rorl $14,%edx
+ movl 12(%esp),%edi
+ xorl %esi,%edx
+ movl 76(%esp),%ebx
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,4(%esp)
+ xorl %esi,%edx
+ addl 16(%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl 24(%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,20(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 1426881987(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ rorl $2,%esi
+ addl %edx,%eax
+ addl (%esp),%edx
+ addl %esi,%eax
+ movl %edx,%ecx
+ movl 4(%esp),%esi
+ rorl $14,%edx
+ movl 8(%esp),%edi
+ xorl %ecx,%edx
+ movl 80(%esp),%ebx
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,(%esp)
+ xorl %ecx,%edx
+ addl 12(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 20(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,16(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 1925078388(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 28(%esp),%edx
+ addl %ecx,%ebp
+ movl %edx,%esi
+ movl (%esp),%ecx
+ rorl $14,%edx
+ movl 4(%esp),%edi
+ xorl %esi,%edx
+ movl 84(%esp),%ebx
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,28(%esp)
+ xorl %esi,%edx
+ addl 8(%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl 16(%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,12(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 2162078206(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ rorl $2,%esi
+ addl %edx,%eax
+ addl 24(%esp),%edx
+ addl %esi,%eax
+ movl %edx,%ecx
+ movl 28(%esp),%esi
+ rorl $14,%edx
+ movl (%esp),%edi
+ xorl %ecx,%edx
+ movl 88(%esp),%ebx
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,24(%esp)
+ xorl %ecx,%edx
+ addl 4(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 12(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,8(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 2614888103(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 20(%esp),%edx
+ addl %ecx,%ebp
+ movl %edx,%esi
+ movl 24(%esp),%ecx
+ rorl $14,%edx
+ movl 28(%esp),%edi
+ xorl %esi,%edx
+ movl 92(%esp),%ebx
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,20(%esp)
+ xorl %esi,%edx
+ addl (%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl 8(%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,4(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 3248222580(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ movl 36(%esp),%ecx
+ rorl $2,%esi
+ addl %edx,%eax
+ addl 16(%esp),%edx
+ addl %esi,%eax
+ movl 88(%esp),%esi
+ movl %ecx,%ebx
+ rorl $11,%ecx
+ movl %esi,%edi
+ rorl $2,%esi
+ xorl %ebx,%ecx
+ shrl $3,%ebx
+ rorl $7,%ecx
+ xorl %edi,%esi
+ xorl %ecx,%ebx
+ rorl $17,%esi
+ addl 32(%esp),%ebx
+ shrl $10,%edi
+ addl 68(%esp),%ebx
+ movl %edx,%ecx
+ xorl %esi,%edi
+ movl 20(%esp),%esi
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 24(%esp),%edi
+ xorl %ecx,%edx
+ movl %ebx,32(%esp)
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,16(%esp)
+ xorl %ecx,%edx
+ addl 28(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 4(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 3835390401(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ movl 40(%esp),%esi
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 12(%esp),%edx
+ addl %ecx,%ebp
+ movl 92(%esp),%ecx
+ movl %esi,%ebx
+ rorl $11,%esi
+ movl %ecx,%edi
+ rorl $2,%ecx
+ xorl %ebx,%esi
+ shrl $3,%ebx
+ rorl $7,%esi
+ xorl %edi,%ecx
+ xorl %esi,%ebx
+ rorl $17,%ecx
+ addl 36(%esp),%ebx
+ shrl $10,%edi
+ addl 72(%esp),%ebx
+ movl %edx,%esi
+ xorl %ecx,%edi
+ movl 16(%esp),%ecx
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 20(%esp),%edi
+ xorl %esi,%edx
+ movl %ebx,36(%esp)
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,12(%esp)
+ xorl %esi,%edx
+ addl 24(%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl (%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,28(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 4022224774(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ movl 44(%esp),%ecx
+ rorl $2,%esi
+ addl %edx,%eax
+ addl 8(%esp),%edx
+ addl %esi,%eax
+ movl 32(%esp),%esi
+ movl %ecx,%ebx
+ rorl $11,%ecx
+ movl %esi,%edi
+ rorl $2,%esi
+ xorl %ebx,%ecx
+ shrl $3,%ebx
+ rorl $7,%ecx
+ xorl %edi,%esi
+ xorl %ecx,%ebx
+ rorl $17,%esi
+ addl 40(%esp),%ebx
+ shrl $10,%edi
+ addl 76(%esp),%ebx
+ movl %edx,%ecx
+ xorl %esi,%edi
+ movl 12(%esp),%esi
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 16(%esp),%edi
+ xorl %ecx,%edx
+ movl %ebx,40(%esp)
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,8(%esp)
+ xorl %ecx,%edx
+ addl 20(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 28(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,24(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 264347078(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ movl 48(%esp),%esi
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 4(%esp),%edx
+ addl %ecx,%ebp
+ movl 36(%esp),%ecx
+ movl %esi,%ebx
+ rorl $11,%esi
+ movl %ecx,%edi
+ rorl $2,%ecx
+ xorl %ebx,%esi
+ shrl $3,%ebx
+ rorl $7,%esi
+ xorl %edi,%ecx
+ xorl %esi,%ebx
+ rorl $17,%ecx
+ addl 44(%esp),%ebx
+ shrl $10,%edi
+ addl 80(%esp),%ebx
+ movl %edx,%esi
+ xorl %ecx,%edi
+ movl 8(%esp),%ecx
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 12(%esp),%edi
+ xorl %esi,%edx
+ movl %ebx,44(%esp)
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,4(%esp)
+ xorl %esi,%edx
+ addl 16(%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl 24(%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,20(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 604807628(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ movl 52(%esp),%ecx
+ rorl $2,%esi
+ addl %edx,%eax
+ addl (%esp),%edx
+ addl %esi,%eax
+ movl 40(%esp),%esi
+ movl %ecx,%ebx
+ rorl $11,%ecx
+ movl %esi,%edi
+ rorl $2,%esi
+ xorl %ebx,%ecx
+ shrl $3,%ebx
+ rorl $7,%ecx
+ xorl %edi,%esi
+ xorl %ecx,%ebx
+ rorl $17,%esi
+ addl 48(%esp),%ebx
+ shrl $10,%edi
+ addl 84(%esp),%ebx
+ movl %edx,%ecx
+ xorl %esi,%edi
+ movl 4(%esp),%esi
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 8(%esp),%edi
+ xorl %ecx,%edx
+ movl %ebx,48(%esp)
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,(%esp)
+ xorl %ecx,%edx
+ addl 12(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 20(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,16(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 770255983(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ movl 56(%esp),%esi
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 28(%esp),%edx
+ addl %ecx,%ebp
+ movl 44(%esp),%ecx
+ movl %esi,%ebx
+ rorl $11,%esi
+ movl %ecx,%edi
+ rorl $2,%ecx
+ xorl %ebx,%esi
+ shrl $3,%ebx
+ rorl $7,%esi
+ xorl %edi,%ecx
+ xorl %esi,%ebx
+ rorl $17,%ecx
+ addl 52(%esp),%ebx
+ shrl $10,%edi
+ addl 88(%esp),%ebx
+ movl %edx,%esi
+ xorl %ecx,%edi
+ movl (%esp),%ecx
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 4(%esp),%edi
+ xorl %esi,%edx
+ movl %ebx,52(%esp)
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,28(%esp)
+ xorl %esi,%edx
+ addl 8(%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl 16(%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,12(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 1249150122(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ movl 60(%esp),%ecx
+ rorl $2,%esi
+ addl %edx,%eax
+ addl 24(%esp),%edx
+ addl %esi,%eax
+ movl 48(%esp),%esi
+ movl %ecx,%ebx
+ rorl $11,%ecx
+ movl %esi,%edi
+ rorl $2,%esi
+ xorl %ebx,%ecx
+ shrl $3,%ebx
+ rorl $7,%ecx
+ xorl %edi,%esi
+ xorl %ecx,%ebx
+ rorl $17,%esi
+ addl 56(%esp),%ebx
+ shrl $10,%edi
+ addl 92(%esp),%ebx
+ movl %edx,%ecx
+ xorl %esi,%edi
+ movl 28(%esp),%esi
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl (%esp),%edi
+ xorl %ecx,%edx
+ movl %ebx,56(%esp)
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,24(%esp)
+ xorl %ecx,%edx
+ addl 4(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 12(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,8(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 1555081692(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ movl 64(%esp),%esi
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 20(%esp),%edx
+ addl %ecx,%ebp
+ movl 52(%esp),%ecx
+ movl %esi,%ebx
+ rorl $11,%esi
+ movl %ecx,%edi
+ rorl $2,%ecx
+ xorl %ebx,%esi
+ shrl $3,%ebx
+ rorl $7,%esi
+ xorl %edi,%ecx
+ xorl %esi,%ebx
+ rorl $17,%ecx
+ addl 60(%esp),%ebx
+ shrl $10,%edi
+ addl 32(%esp),%ebx
+ movl %edx,%esi
+ xorl %ecx,%edi
+ movl 24(%esp),%ecx
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 28(%esp),%edi
+ xorl %esi,%edx
+ movl %ebx,60(%esp)
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,20(%esp)
+ xorl %esi,%edx
+ addl (%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl 8(%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,4(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 1996064986(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ movl 68(%esp),%ecx
+ rorl $2,%esi
+ addl %edx,%eax
+ addl 16(%esp),%edx
+ addl %esi,%eax
+ movl 56(%esp),%esi
+ movl %ecx,%ebx
+ rorl $11,%ecx
+ movl %esi,%edi
+ rorl $2,%esi
+ xorl %ebx,%ecx
+ shrl $3,%ebx
+ rorl $7,%ecx
+ xorl %edi,%esi
+ xorl %ecx,%ebx
+ rorl $17,%esi
+ addl 64(%esp),%ebx
+ shrl $10,%edi
+ addl 36(%esp),%ebx
+ movl %edx,%ecx
+ xorl %esi,%edi
+ movl 20(%esp),%esi
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 24(%esp),%edi
+ xorl %ecx,%edx
+ movl %ebx,64(%esp)
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,16(%esp)
+ xorl %ecx,%edx
+ addl 28(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 4(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 2554220882(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ movl 72(%esp),%esi
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 12(%esp),%edx
+ addl %ecx,%ebp
+ movl 60(%esp),%ecx
+ movl %esi,%ebx
+ rorl $11,%esi
+ movl %ecx,%edi
+ rorl $2,%ecx
+ xorl %ebx,%esi
+ shrl $3,%ebx
+ rorl $7,%esi
+ xorl %edi,%ecx
+ xorl %esi,%ebx
+ rorl $17,%ecx
+ addl 68(%esp),%ebx
+ shrl $10,%edi
+ addl 40(%esp),%ebx
+ movl %edx,%esi
+ xorl %ecx,%edi
+ movl 16(%esp),%ecx
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 20(%esp),%edi
+ xorl %esi,%edx
+ movl %ebx,68(%esp)
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,12(%esp)
+ xorl %esi,%edx
+ addl 24(%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl (%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,28(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 2821834349(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ movl 76(%esp),%ecx
+ rorl $2,%esi
+ addl %edx,%eax
+ addl 8(%esp),%edx
+ addl %esi,%eax
+ movl 64(%esp),%esi
+ movl %ecx,%ebx
+ rorl $11,%ecx
+ movl %esi,%edi
+ rorl $2,%esi
+ xorl %ebx,%ecx
+ shrl $3,%ebx
+ rorl $7,%ecx
+ xorl %edi,%esi
+ xorl %ecx,%ebx
+ rorl $17,%esi
+ addl 72(%esp),%ebx
+ shrl $10,%edi
+ addl 44(%esp),%ebx
+ movl %edx,%ecx
+ xorl %esi,%edi
+ movl 12(%esp),%esi
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 16(%esp),%edi
+ xorl %ecx,%edx
+ movl %ebx,72(%esp)
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,8(%esp)
+ xorl %ecx,%edx
+ addl 20(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 28(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,24(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 2952996808(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ movl 80(%esp),%esi
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 4(%esp),%edx
+ addl %ecx,%ebp
+ movl 68(%esp),%ecx
+ movl %esi,%ebx
+ rorl $11,%esi
+ movl %ecx,%edi
+ rorl $2,%ecx
+ xorl %ebx,%esi
+ shrl $3,%ebx
+ rorl $7,%esi
+ xorl %edi,%ecx
+ xorl %esi,%ebx
+ rorl $17,%ecx
+ addl 76(%esp),%ebx
+ shrl $10,%edi
+ addl 48(%esp),%ebx
+ movl %edx,%esi
+ xorl %ecx,%edi
+ movl 8(%esp),%ecx
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 12(%esp),%edi
+ xorl %esi,%edx
+ movl %ebx,76(%esp)
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,4(%esp)
+ xorl %esi,%edx
+ addl 16(%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl 24(%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,20(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 3210313671(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ movl 84(%esp),%ecx
+ rorl $2,%esi
+ addl %edx,%eax
+ addl (%esp),%edx
+ addl %esi,%eax
+ movl 72(%esp),%esi
+ movl %ecx,%ebx
+ rorl $11,%ecx
+ movl %esi,%edi
+ rorl $2,%esi
+ xorl %ebx,%ecx
+ shrl $3,%ebx
+ rorl $7,%ecx
+ xorl %edi,%esi
+ xorl %ecx,%ebx
+ rorl $17,%esi
+ addl 80(%esp),%ebx
+ shrl $10,%edi
+ addl 52(%esp),%ebx
+ movl %edx,%ecx
+ xorl %esi,%edi
+ movl 4(%esp),%esi
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 8(%esp),%edi
+ xorl %ecx,%edx
+ movl %ebx,80(%esp)
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,(%esp)
+ xorl %ecx,%edx
+ addl 12(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 20(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,16(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 3336571891(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ movl 88(%esp),%esi
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 28(%esp),%edx
+ addl %ecx,%ebp
+ movl 76(%esp),%ecx
+ movl %esi,%ebx
+ rorl $11,%esi
+ movl %ecx,%edi
+ rorl $2,%ecx
+ xorl %ebx,%esi
+ shrl $3,%ebx
+ rorl $7,%esi
+ xorl %edi,%ecx
+ xorl %esi,%ebx
+ rorl $17,%ecx
+ addl 84(%esp),%ebx
+ shrl $10,%edi
+ addl 56(%esp),%ebx
+ movl %edx,%esi
+ xorl %ecx,%edi
+ movl (%esp),%ecx
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 4(%esp),%edi
+ xorl %esi,%edx
+ movl %ebx,84(%esp)
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,28(%esp)
+ xorl %esi,%edx
+ addl 8(%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl 16(%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,12(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 3584528711(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ movl 92(%esp),%ecx
+ rorl $2,%esi
+ addl %edx,%eax
+ addl 24(%esp),%edx
+ addl %esi,%eax
+ movl 80(%esp),%esi
+ movl %ecx,%ebx
+ rorl $11,%ecx
+ movl %esi,%edi
+ rorl $2,%esi
+ xorl %ebx,%ecx
+ shrl $3,%ebx
+ rorl $7,%ecx
+ xorl %edi,%esi
+ xorl %ecx,%ebx
+ rorl $17,%esi
+ addl 88(%esp),%ebx
+ shrl $10,%edi
+ addl 60(%esp),%ebx
+ movl %edx,%ecx
+ xorl %esi,%edi
+ movl 28(%esp),%esi
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl (%esp),%edi
+ xorl %ecx,%edx
+ movl %ebx,88(%esp)
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,24(%esp)
+ xorl %ecx,%edx
+ addl 4(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 12(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,8(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 113926993(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ movl 32(%esp),%esi
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 20(%esp),%edx
+ addl %ecx,%ebp
+ movl 84(%esp),%ecx
+ movl %esi,%ebx
+ rorl $11,%esi
+ movl %ecx,%edi
+ rorl $2,%ecx
+ xorl %ebx,%esi
+ shrl $3,%ebx
+ rorl $7,%esi
+ xorl %edi,%ecx
+ xorl %esi,%ebx
+ rorl $17,%ecx
+ addl 92(%esp),%ebx
+ shrl $10,%edi
+ addl 64(%esp),%ebx
+ movl %edx,%esi
+ xorl %ecx,%edi
+ movl 24(%esp),%ecx
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 28(%esp),%edi
+ xorl %esi,%edx
+ movl %ebx,92(%esp)
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,20(%esp)
+ xorl %esi,%edx
+ addl (%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl 8(%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,4(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 338241895(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ movl 36(%esp),%ecx
+ rorl $2,%esi
+ addl %edx,%eax
+ addl 16(%esp),%edx
+ addl %esi,%eax
+ movl 88(%esp),%esi
+ movl %ecx,%ebx
+ rorl $11,%ecx
+ movl %esi,%edi
+ rorl $2,%esi
+ xorl %ebx,%ecx
+ shrl $3,%ebx
+ rorl $7,%ecx
+ xorl %edi,%esi
+ xorl %ecx,%ebx
+ rorl $17,%esi
+ addl 32(%esp),%ebx
+ shrl $10,%edi
+ addl 68(%esp),%ebx
+ movl %edx,%ecx
+ xorl %esi,%edi
+ movl 20(%esp),%esi
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 24(%esp),%edi
+ xorl %ecx,%edx
+ movl %ebx,32(%esp)
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,16(%esp)
+ xorl %ecx,%edx
+ addl 28(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 4(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 666307205(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ movl 40(%esp),%esi
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 12(%esp),%edx
+ addl %ecx,%ebp
+ movl 92(%esp),%ecx
+ movl %esi,%ebx
+ rorl $11,%esi
+ movl %ecx,%edi
+ rorl $2,%ecx
+ xorl %ebx,%esi
+ shrl $3,%ebx
+ rorl $7,%esi
+ xorl %edi,%ecx
+ xorl %esi,%ebx
+ rorl $17,%ecx
+ addl 36(%esp),%ebx
+ shrl $10,%edi
+ addl 72(%esp),%ebx
+ movl %edx,%esi
+ xorl %ecx,%edi
+ movl 16(%esp),%ecx
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 20(%esp),%edi
+ xorl %esi,%edx
+ movl %ebx,36(%esp)
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,12(%esp)
+ xorl %esi,%edx
+ addl 24(%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl (%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,28(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 773529912(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ movl 44(%esp),%ecx
+ rorl $2,%esi
+ addl %edx,%eax
+ addl 8(%esp),%edx
+ addl %esi,%eax
+ movl 32(%esp),%esi
+ movl %ecx,%ebx
+ rorl $11,%ecx
+ movl %esi,%edi
+ rorl $2,%esi
+ xorl %ebx,%ecx
+ shrl $3,%ebx
+ rorl $7,%ecx
+ xorl %edi,%esi
+ xorl %ecx,%ebx
+ rorl $17,%esi
+ addl 40(%esp),%ebx
+ shrl $10,%edi
+ addl 76(%esp),%ebx
+ movl %edx,%ecx
+ xorl %esi,%edi
+ movl 12(%esp),%esi
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 16(%esp),%edi
+ xorl %ecx,%edx
+ movl %ebx,40(%esp)
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,8(%esp)
+ xorl %ecx,%edx
+ addl 20(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 28(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,24(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 1294757372(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ movl 48(%esp),%esi
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 4(%esp),%edx
+ addl %ecx,%ebp
+ movl 36(%esp),%ecx
+ movl %esi,%ebx
+ rorl $11,%esi
+ movl %ecx,%edi
+ rorl $2,%ecx
+ xorl %ebx,%esi
+ shrl $3,%ebx
+ rorl $7,%esi
+ xorl %edi,%ecx
+ xorl %esi,%ebx
+ rorl $17,%ecx
+ addl 44(%esp),%ebx
+ shrl $10,%edi
+ addl 80(%esp),%ebx
+ movl %edx,%esi
+ xorl %ecx,%edi
+ movl 8(%esp),%ecx
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 12(%esp),%edi
+ xorl %esi,%edx
+ movl %ebx,44(%esp)
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,4(%esp)
+ xorl %esi,%edx
+ addl 16(%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl 24(%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,20(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 1396182291(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ movl 52(%esp),%ecx
+ rorl $2,%esi
+ addl %edx,%eax
+ addl (%esp),%edx
+ addl %esi,%eax
+ movl 40(%esp),%esi
+ movl %ecx,%ebx
+ rorl $11,%ecx
+ movl %esi,%edi
+ rorl $2,%esi
+ xorl %ebx,%ecx
+ shrl $3,%ebx
+ rorl $7,%ecx
+ xorl %edi,%esi
+ xorl %ecx,%ebx
+ rorl $17,%esi
+ addl 48(%esp),%ebx
+ shrl $10,%edi
+ addl 84(%esp),%ebx
+ movl %edx,%ecx
+ xorl %esi,%edi
+ movl 4(%esp),%esi
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 8(%esp),%edi
+ xorl %ecx,%edx
+ movl %ebx,48(%esp)
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,(%esp)
+ xorl %ecx,%edx
+ addl 12(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 20(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,16(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 1695183700(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ movl 56(%esp),%esi
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 28(%esp),%edx
+ addl %ecx,%ebp
+ movl 44(%esp),%ecx
+ movl %esi,%ebx
+ rorl $11,%esi
+ movl %ecx,%edi
+ rorl $2,%ecx
+ xorl %ebx,%esi
+ shrl $3,%ebx
+ rorl $7,%esi
+ xorl %edi,%ecx
+ xorl %esi,%ebx
+ rorl $17,%ecx
+ addl 52(%esp),%ebx
+ shrl $10,%edi
+ addl 88(%esp),%ebx
+ movl %edx,%esi
+ xorl %ecx,%edi
+ movl (%esp),%ecx
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 4(%esp),%edi
+ xorl %esi,%edx
+ movl %ebx,52(%esp)
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,28(%esp)
+ xorl %esi,%edx
+ addl 8(%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl 16(%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,12(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 1986661051(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ movl 60(%esp),%ecx
+ rorl $2,%esi
+ addl %edx,%eax
+ addl 24(%esp),%edx
+ addl %esi,%eax
+ movl 48(%esp),%esi
+ movl %ecx,%ebx
+ rorl $11,%ecx
+ movl %esi,%edi
+ rorl $2,%esi
+ xorl %ebx,%ecx
+ shrl $3,%ebx
+ rorl $7,%ecx
+ xorl %edi,%esi
+ xorl %ecx,%ebx
+ rorl $17,%esi
+ addl 56(%esp),%ebx
+ shrl $10,%edi
+ addl 92(%esp),%ebx
+ movl %edx,%ecx
+ xorl %esi,%edi
+ movl 28(%esp),%esi
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl (%esp),%edi
+ xorl %ecx,%edx
+ movl %ebx,56(%esp)
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,24(%esp)
+ xorl %ecx,%edx
+ addl 4(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 12(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,8(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 2177026350(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ movl 64(%esp),%esi
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 20(%esp),%edx
+ addl %ecx,%ebp
+ movl 52(%esp),%ecx
+ movl %esi,%ebx
+ rorl $11,%esi
+ movl %ecx,%edi
+ rorl $2,%ecx
+ xorl %ebx,%esi
+ shrl $3,%ebx
+ rorl $7,%esi
+ xorl %edi,%ecx
+ xorl %esi,%ebx
+ rorl $17,%ecx
+ addl 60(%esp),%ebx
+ shrl $10,%edi
+ addl 32(%esp),%ebx
+ movl %edx,%esi
+ xorl %ecx,%edi
+ movl 24(%esp),%ecx
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 28(%esp),%edi
+ xorl %esi,%edx
+ movl %ebx,60(%esp)
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,20(%esp)
+ xorl %esi,%edx
+ addl (%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl 8(%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,4(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 2456956037(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ movl 68(%esp),%ecx
+ rorl $2,%esi
+ addl %edx,%eax
+ addl 16(%esp),%edx
+ addl %esi,%eax
+ movl 56(%esp),%esi
+ movl %ecx,%ebx
+ rorl $11,%ecx
+ movl %esi,%edi
+ rorl $2,%esi
+ xorl %ebx,%ecx
+ shrl $3,%ebx
+ rorl $7,%ecx
+ xorl %edi,%esi
+ xorl %ecx,%ebx
+ rorl $17,%esi
+ addl 64(%esp),%ebx
+ shrl $10,%edi
+ addl 36(%esp),%ebx
+ movl %edx,%ecx
+ xorl %esi,%edi
+ movl 20(%esp),%esi
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 24(%esp),%edi
+ xorl %ecx,%edx
+ movl %ebx,64(%esp)
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,16(%esp)
+ xorl %ecx,%edx
+ addl 28(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 4(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 2730485921(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ movl 72(%esp),%esi
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 12(%esp),%edx
+ addl %ecx,%ebp
+ movl 60(%esp),%ecx
+ movl %esi,%ebx
+ rorl $11,%esi
+ movl %ecx,%edi
+ rorl $2,%ecx
+ xorl %ebx,%esi
+ shrl $3,%ebx
+ rorl $7,%esi
+ xorl %edi,%ecx
+ xorl %esi,%ebx
+ rorl $17,%ecx
+ addl 68(%esp),%ebx
+ shrl $10,%edi
+ addl 40(%esp),%ebx
+ movl %edx,%esi
+ xorl %ecx,%edi
+ movl 16(%esp),%ecx
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 20(%esp),%edi
+ xorl %esi,%edx
+ movl %ebx,68(%esp)
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,12(%esp)
+ xorl %esi,%edx
+ addl 24(%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl (%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,28(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 2820302411(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ movl 76(%esp),%ecx
+ rorl $2,%esi
+ addl %edx,%eax
+ addl 8(%esp),%edx
+ addl %esi,%eax
+ movl 64(%esp),%esi
+ movl %ecx,%ebx
+ rorl $11,%ecx
+ movl %esi,%edi
+ rorl $2,%esi
+ xorl %ebx,%ecx
+ shrl $3,%ebx
+ rorl $7,%ecx
+ xorl %edi,%esi
+ xorl %ecx,%ebx
+ rorl $17,%esi
+ addl 72(%esp),%ebx
+ shrl $10,%edi
+ addl 44(%esp),%ebx
+ movl %edx,%ecx
+ xorl %esi,%edi
+ movl 12(%esp),%esi
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 16(%esp),%edi
+ xorl %ecx,%edx
+ movl %ebx,72(%esp)
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,8(%esp)
+ xorl %ecx,%edx
+ addl 20(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 28(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,24(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 3259730800(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ movl 80(%esp),%esi
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 4(%esp),%edx
+ addl %ecx,%ebp
+ movl 68(%esp),%ecx
+ movl %esi,%ebx
+ rorl $11,%esi
+ movl %ecx,%edi
+ rorl $2,%ecx
+ xorl %ebx,%esi
+ shrl $3,%ebx
+ rorl $7,%esi
+ xorl %edi,%ecx
+ xorl %esi,%ebx
+ rorl $17,%ecx
+ addl 76(%esp),%ebx
+ shrl $10,%edi
+ addl 48(%esp),%ebx
+ movl %edx,%esi
+ xorl %ecx,%edi
+ movl 8(%esp),%ecx
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 12(%esp),%edi
+ xorl %esi,%edx
+ movl %ebx,76(%esp)
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,4(%esp)
+ xorl %esi,%edx
+ addl 16(%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl 24(%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,20(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 3345764771(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ movl 84(%esp),%ecx
+ rorl $2,%esi
+ addl %edx,%eax
+ addl (%esp),%edx
+ addl %esi,%eax
+ movl 72(%esp),%esi
+ movl %ecx,%ebx
+ rorl $11,%ecx
+ movl %esi,%edi
+ rorl $2,%esi
+ xorl %ebx,%ecx
+ shrl $3,%ebx
+ rorl $7,%ecx
+ xorl %edi,%esi
+ xorl %ecx,%ebx
+ rorl $17,%esi
+ addl 80(%esp),%ebx
+ shrl $10,%edi
+ addl 52(%esp),%ebx
+ movl %edx,%ecx
+ xorl %esi,%edi
+ movl 4(%esp),%esi
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 8(%esp),%edi
+ xorl %ecx,%edx
+ movl %ebx,80(%esp)
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,(%esp)
+ xorl %ecx,%edx
+ addl 12(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 20(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,16(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 3516065817(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ movl 88(%esp),%esi
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 28(%esp),%edx
+ addl %ecx,%ebp
+ movl 76(%esp),%ecx
+ movl %esi,%ebx
+ rorl $11,%esi
+ movl %ecx,%edi
+ rorl $2,%ecx
+ xorl %ebx,%esi
+ shrl $3,%ebx
+ rorl $7,%esi
+ xorl %edi,%ecx
+ xorl %esi,%ebx
+ rorl $17,%ecx
+ addl 84(%esp),%ebx
+ shrl $10,%edi
+ addl 56(%esp),%ebx
+ movl %edx,%esi
+ xorl %ecx,%edi
+ movl (%esp),%ecx
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 4(%esp),%edi
+ xorl %esi,%edx
+ movl %ebx,84(%esp)
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,28(%esp)
+ xorl %esi,%edx
+ addl 8(%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl 16(%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,12(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 3600352804(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ movl 92(%esp),%ecx
+ rorl $2,%esi
+ addl %edx,%eax
+ addl 24(%esp),%edx
+ addl %esi,%eax
+ movl 80(%esp),%esi
+ movl %ecx,%ebx
+ rorl $11,%ecx
+ movl %esi,%edi
+ rorl $2,%esi
+ xorl %ebx,%ecx
+ shrl $3,%ebx
+ rorl $7,%ecx
+ xorl %edi,%esi
+ xorl %ecx,%ebx
+ rorl $17,%esi
+ addl 88(%esp),%ebx
+ shrl $10,%edi
+ addl 60(%esp),%ebx
+ movl %edx,%ecx
+ xorl %esi,%edi
+ movl 28(%esp),%esi
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl (%esp),%edi
+ xorl %ecx,%edx
+ movl %ebx,88(%esp)
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,24(%esp)
+ xorl %ecx,%edx
+ addl 4(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 12(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,8(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 4094571909(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ movl 32(%esp),%esi
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 20(%esp),%edx
+ addl %ecx,%ebp
+ movl 84(%esp),%ecx
+ movl %esi,%ebx
+ rorl $11,%esi
+ movl %ecx,%edi
+ rorl $2,%ecx
+ xorl %ebx,%esi
+ shrl $3,%ebx
+ rorl $7,%esi
+ xorl %edi,%ecx
+ xorl %esi,%ebx
+ rorl $17,%ecx
+ addl 92(%esp),%ebx
+ shrl $10,%edi
+ addl 64(%esp),%ebx
+ movl %edx,%esi
+ xorl %ecx,%edi
+ movl 24(%esp),%ecx
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 28(%esp),%edi
+ xorl %esi,%edx
+ movl %ebx,92(%esp)
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,20(%esp)
+ xorl %esi,%edx
+ addl (%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl 8(%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,4(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 275423344(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ movl 36(%esp),%ecx
+ rorl $2,%esi
+ addl %edx,%eax
+ addl 16(%esp),%edx
+ addl %esi,%eax
+ movl 88(%esp),%esi
+ movl %ecx,%ebx
+ rorl $11,%ecx
+ movl %esi,%edi
+ rorl $2,%esi
+ xorl %ebx,%ecx
+ shrl $3,%ebx
+ rorl $7,%ecx
+ xorl %edi,%esi
+ xorl %ecx,%ebx
+ rorl $17,%esi
+ addl 32(%esp),%ebx
+ shrl $10,%edi
+ addl 68(%esp),%ebx
+ movl %edx,%ecx
+ xorl %esi,%edi
+ movl 20(%esp),%esi
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 24(%esp),%edi
+ xorl %ecx,%edx
+ movl %ebx,32(%esp)
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,16(%esp)
+ xorl %ecx,%edx
+ addl 28(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 4(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 430227734(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ movl 40(%esp),%esi
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 12(%esp),%edx
+ addl %ecx,%ebp
+ movl 92(%esp),%ecx
+ movl %esi,%ebx
+ rorl $11,%esi
+ movl %ecx,%edi
+ rorl $2,%ecx
+ xorl %ebx,%esi
+ shrl $3,%ebx
+ rorl $7,%esi
+ xorl %edi,%ecx
+ xorl %esi,%ebx
+ rorl $17,%ecx
+ addl 36(%esp),%ebx
+ shrl $10,%edi
+ addl 72(%esp),%ebx
+ movl %edx,%esi
+ xorl %ecx,%edi
+ movl 16(%esp),%ecx
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 20(%esp),%edi
+ xorl %esi,%edx
+ movl %ebx,36(%esp)
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,12(%esp)
+ xorl %esi,%edx
+ addl 24(%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl (%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,28(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 506948616(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ movl 44(%esp),%ecx
+ rorl $2,%esi
+ addl %edx,%eax
+ addl 8(%esp),%edx
+ addl %esi,%eax
+ movl 32(%esp),%esi
+ movl %ecx,%ebx
+ rorl $11,%ecx
+ movl %esi,%edi
+ rorl $2,%esi
+ xorl %ebx,%ecx
+ shrl $3,%ebx
+ rorl $7,%ecx
+ xorl %edi,%esi
+ xorl %ecx,%ebx
+ rorl $17,%esi
+ addl 40(%esp),%ebx
+ shrl $10,%edi
+ addl 76(%esp),%ebx
+ movl %edx,%ecx
+ xorl %esi,%edi
+ movl 12(%esp),%esi
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 16(%esp),%edi
+ xorl %ecx,%edx
+ movl %ebx,40(%esp)
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,8(%esp)
+ xorl %ecx,%edx
+ addl 20(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 28(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,24(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 659060556(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ movl 48(%esp),%esi
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 4(%esp),%edx
+ addl %ecx,%ebp
+ movl 36(%esp),%ecx
+ movl %esi,%ebx
+ rorl $11,%esi
+ movl %ecx,%edi
+ rorl $2,%ecx
+ xorl %ebx,%esi
+ shrl $3,%ebx
+ rorl $7,%esi
+ xorl %edi,%ecx
+ xorl %esi,%ebx
+ rorl $17,%ecx
+ addl 44(%esp),%ebx
+ shrl $10,%edi
+ addl 80(%esp),%ebx
+ movl %edx,%esi
+ xorl %ecx,%edi
+ movl 8(%esp),%ecx
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 12(%esp),%edi
+ xorl %esi,%edx
+ movl %ebx,44(%esp)
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,4(%esp)
+ xorl %esi,%edx
+ addl 16(%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl 24(%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,20(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 883997877(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ movl 52(%esp),%ecx
+ rorl $2,%esi
+ addl %edx,%eax
+ addl (%esp),%edx
+ addl %esi,%eax
+ movl 40(%esp),%esi
+ movl %ecx,%ebx
+ rorl $11,%ecx
+ movl %esi,%edi
+ rorl $2,%esi
+ xorl %ebx,%ecx
+ shrl $3,%ebx
+ rorl $7,%ecx
+ xorl %edi,%esi
+ xorl %ecx,%ebx
+ rorl $17,%esi
+ addl 48(%esp),%ebx
+ shrl $10,%edi
+ addl 84(%esp),%ebx
+ movl %edx,%ecx
+ xorl %esi,%edi
+ movl 4(%esp),%esi
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 8(%esp),%edi
+ xorl %ecx,%edx
+ movl %ebx,48(%esp)
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,(%esp)
+ xorl %ecx,%edx
+ addl 12(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 20(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,16(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 958139571(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ movl 56(%esp),%esi
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 28(%esp),%edx
+ addl %ecx,%ebp
+ movl 44(%esp),%ecx
+ movl %esi,%ebx
+ rorl $11,%esi
+ movl %ecx,%edi
+ rorl $2,%ecx
+ xorl %ebx,%esi
+ shrl $3,%ebx
+ rorl $7,%esi
+ xorl %edi,%ecx
+ xorl %esi,%ebx
+ rorl $17,%ecx
+ addl 52(%esp),%ebx
+ shrl $10,%edi
+ addl 88(%esp),%ebx
+ movl %edx,%esi
+ xorl %ecx,%edi
+ movl (%esp),%ecx
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 4(%esp),%edi
+ xorl %esi,%edx
+ movl %ebx,52(%esp)
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,28(%esp)
+ xorl %esi,%edx
+ addl 8(%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl 16(%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,12(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 1322822218(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ movl 60(%esp),%ecx
+ rorl $2,%esi
+ addl %edx,%eax
+ addl 24(%esp),%edx
+ addl %esi,%eax
+ movl 48(%esp),%esi
+ movl %ecx,%ebx
+ rorl $11,%ecx
+ movl %esi,%edi
+ rorl $2,%esi
+ xorl %ebx,%ecx
+ shrl $3,%ebx
+ rorl $7,%ecx
+ xorl %edi,%esi
+ xorl %ecx,%ebx
+ rorl $17,%esi
+ addl 56(%esp),%ebx
+ shrl $10,%edi
+ addl 92(%esp),%ebx
+ movl %edx,%ecx
+ xorl %esi,%edi
+ movl 28(%esp),%esi
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl (%esp),%edi
+ xorl %ecx,%edx
+ movl %ebx,56(%esp)
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,24(%esp)
+ xorl %ecx,%edx
+ addl 4(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 12(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,8(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 1537002063(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ movl 64(%esp),%esi
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 20(%esp),%edx
+ addl %ecx,%ebp
+ movl 52(%esp),%ecx
+ movl %esi,%ebx
+ rorl $11,%esi
+ movl %ecx,%edi
+ rorl $2,%ecx
+ xorl %ebx,%esi
+ shrl $3,%ebx
+ rorl $7,%esi
+ xorl %edi,%ecx
+ xorl %esi,%ebx
+ rorl $17,%ecx
+ addl 60(%esp),%ebx
+ shrl $10,%edi
+ addl 32(%esp),%ebx
+ movl %edx,%esi
+ xorl %ecx,%edi
+ movl 24(%esp),%ecx
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 28(%esp),%edi
+ xorl %esi,%edx
+ movl %ebx,60(%esp)
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,20(%esp)
+ xorl %esi,%edx
+ addl (%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl 8(%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,4(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 1747873779(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ movl 68(%esp),%ecx
+ rorl $2,%esi
+ addl %edx,%eax
+ addl 16(%esp),%edx
+ addl %esi,%eax
+ movl 56(%esp),%esi
+ movl %ecx,%ebx
+ rorl $11,%ecx
+ movl %esi,%edi
+ rorl $2,%esi
+ xorl %ebx,%ecx
+ shrl $3,%ebx
+ rorl $7,%ecx
+ xorl %edi,%esi
+ xorl %ecx,%ebx
+ rorl $17,%esi
+ addl 64(%esp),%ebx
+ shrl $10,%edi
+ addl 36(%esp),%ebx
+ movl %edx,%ecx
+ xorl %esi,%edi
+ movl 20(%esp),%esi
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 24(%esp),%edi
+ xorl %ecx,%edx
+ movl %ebx,64(%esp)
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,16(%esp)
+ xorl %ecx,%edx
+ addl 28(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 4(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 1955562222(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ movl 72(%esp),%esi
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 12(%esp),%edx
+ addl %ecx,%ebp
+ movl 60(%esp),%ecx
+ movl %esi,%ebx
+ rorl $11,%esi
+ movl %ecx,%edi
+ rorl $2,%ecx
+ xorl %ebx,%esi
+ shrl $3,%ebx
+ rorl $7,%esi
+ xorl %edi,%ecx
+ xorl %esi,%ebx
+ rorl $17,%ecx
+ addl 68(%esp),%ebx
+ shrl $10,%edi
+ addl 40(%esp),%ebx
+ movl %edx,%esi
+ xorl %ecx,%edi
+ movl 16(%esp),%ecx
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 20(%esp),%edi
+ xorl %esi,%edx
+ movl %ebx,68(%esp)
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,12(%esp)
+ xorl %esi,%edx
+ addl 24(%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl (%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,28(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 2024104815(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ movl 76(%esp),%ecx
+ rorl $2,%esi
+ addl %edx,%eax
+ addl 8(%esp),%edx
+ addl %esi,%eax
+ movl 64(%esp),%esi
+ movl %ecx,%ebx
+ rorl $11,%ecx
+ movl %esi,%edi
+ rorl $2,%esi
+ xorl %ebx,%ecx
+ shrl $3,%ebx
+ rorl $7,%ecx
+ xorl %edi,%esi
+ xorl %ecx,%ebx
+ rorl $17,%esi
+ addl 72(%esp),%ebx
+ shrl $10,%edi
+ addl 44(%esp),%ebx
+ movl %edx,%ecx
+ xorl %esi,%edi
+ movl 12(%esp),%esi
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 16(%esp),%edi
+ xorl %ecx,%edx
+ movl %ebx,72(%esp)
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,8(%esp)
+ xorl %ecx,%edx
+ addl 20(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 28(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,24(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 2227730452(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ movl 80(%esp),%esi
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 4(%esp),%edx
+ addl %ecx,%ebp
+ movl 68(%esp),%ecx
+ movl %esi,%ebx
+ rorl $11,%esi
+ movl %ecx,%edi
+ rorl $2,%ecx
+ xorl %ebx,%esi
+ shrl $3,%ebx
+ rorl $7,%esi
+ xorl %edi,%ecx
+ xorl %esi,%ebx
+ rorl $17,%ecx
+ addl 76(%esp),%ebx
+ shrl $10,%edi
+ addl 48(%esp),%ebx
+ movl %edx,%esi
+ xorl %ecx,%edi
+ movl 8(%esp),%ecx
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 12(%esp),%edi
+ xorl %esi,%edx
+ movl %ebx,76(%esp)
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,4(%esp)
+ xorl %esi,%edx
+ addl 16(%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl 24(%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,20(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 2361852424(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ movl 84(%esp),%ecx
+ rorl $2,%esi
+ addl %edx,%eax
+ addl (%esp),%edx
+ addl %esi,%eax
+ movl 72(%esp),%esi
+ movl %ecx,%ebx
+ rorl $11,%ecx
+ movl %esi,%edi
+ rorl $2,%esi
+ xorl %ebx,%ecx
+ shrl $3,%ebx
+ rorl $7,%ecx
+ xorl %edi,%esi
+ xorl %ecx,%ebx
+ rorl $17,%esi
+ addl 80(%esp),%ebx
+ shrl $10,%edi
+ addl 52(%esp),%ebx
+ movl %edx,%ecx
+ xorl %esi,%edi
+ movl 4(%esp),%esi
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 8(%esp),%edi
+ xorl %ecx,%edx
+ movl %ebx,80(%esp)
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,(%esp)
+ xorl %ecx,%edx
+ addl 12(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 20(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,16(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 2428436474(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ movl 88(%esp),%esi
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 28(%esp),%edx
+ addl %ecx,%ebp
+ movl 76(%esp),%ecx
+ movl %esi,%ebx
+ rorl $11,%esi
+ movl %ecx,%edi
+ rorl $2,%ecx
+ xorl %ebx,%esi
+ shrl $3,%ebx
+ rorl $7,%esi
+ xorl %edi,%ecx
+ xorl %esi,%ebx
+ rorl $17,%ecx
+ addl 84(%esp),%ebx
+ shrl $10,%edi
+ addl 56(%esp),%ebx
+ movl %edx,%esi
+ xorl %ecx,%edi
+ movl (%esp),%ecx
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 4(%esp),%edi
+ xorl %esi,%edx
+ movl %ebx,84(%esp)
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,28(%esp)
+ xorl %esi,%edx
+ addl 8(%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl 16(%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,12(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 2756734187(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ movl 92(%esp),%ecx
+ rorl $2,%esi
+ addl %edx,%eax
+ addl 24(%esp),%edx
+ addl %esi,%eax
+ movl 80(%esp),%esi
+ movl %ecx,%ebx
+ rorl $11,%ecx
+ movl %esi,%edi
+ rorl $2,%esi
+ xorl %ebx,%ecx
+ shrl $3,%ebx
+ rorl $7,%ecx
+ xorl %edi,%esi
+ xorl %ecx,%ebx
+ rorl $17,%esi
+ addl 88(%esp),%ebx
+ shrl $10,%edi
+ addl 60(%esp),%ebx
+ movl %edx,%ecx
+ xorl %esi,%edi
+ movl 28(%esp),%esi
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl (%esp),%edi
+ xorl %ecx,%edx
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,24(%esp)
+ xorl %ecx,%edx
+ addl 4(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 12(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,8(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 3204031479(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ movl 32(%esp),%esi
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 20(%esp),%edx
+ addl %ecx,%ebp
+ movl 84(%esp),%ecx
+ movl %esi,%ebx
+ rorl $11,%esi
+ movl %ecx,%edi
+ rorl $2,%ecx
+ xorl %ebx,%esi
+ shrl $3,%ebx
+ rorl $7,%esi
+ xorl %edi,%ecx
+ xorl %esi,%ebx
+ rorl $17,%ecx
+ addl 92(%esp),%ebx
+ shrl $10,%edi
+ addl 64(%esp),%ebx
+ movl %edx,%esi
+ xorl %ecx,%edi
+ movl 24(%esp),%ecx
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 28(%esp),%edi
+ xorl %esi,%edx
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,20(%esp)
+ xorl %esi,%edx
+ addl (%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl 8(%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,4(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 3329325298(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ rorl $2,%esi
+ addl %edx,%eax
+ addl 16(%esp),%edx
+ addl %esi,%eax
+ movl 96(%esp),%esi
+ xorl %edi,%ebp
+ movl 12(%esp),%ecx
+ addl (%esi),%eax
+ addl 4(%esi),%ebp
+ addl 8(%esi),%edi
+ addl 12(%esi),%ecx
+ movl %eax,(%esi)
+ movl %ebp,4(%esi)
+ movl %edi,8(%esi)
+ movl %ecx,12(%esi)
+ movl %ebp,4(%esp)
+ xorl %edi,%ebp
+ movl %edi,8(%esp)
+ movl %ecx,12(%esp)
+ movl 20(%esp),%edi
+ movl 24(%esp),%ebx
+ movl 28(%esp),%ecx
+ addl 16(%esi),%edx
+ addl 20(%esi),%edi
+ addl 24(%esi),%ebx
+ addl 28(%esi),%ecx
+ movl %edx,16(%esi)
+ movl %edi,20(%esi)
+ movl %ebx,24(%esi)
+ movl %ecx,28(%esi)
+ movl %edi,20(%esp)
+ movl 100(%esp),%edi
+ movl %ebx,24(%esp)
+ movl %ecx,28(%esp)
+ cmpl 104(%esp),%edi
+ jb .L009grand_loop
+ movl 108(%esp),%esp
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.size sha256_block_data_order,.-.L_sha256_block_data_order_begin
+#endif
diff --git a/linux-x86/crypto/sha/sha512-586.S b/linux-x86/crypto/sha/sha512-586.S
new file mode 100644
index 0000000..17f7945
--- /dev/null
+++ b/linux-x86/crypto/sha/sha512-586.S
@@ -0,0 +1,568 @@
+#if defined(__i386__)
+.file "sha512-586.S"
+.text
+.globl sha512_block_data_order
+.hidden sha512_block_data_order
+.type sha512_block_data_order,@function
+.align 16
+sha512_block_data_order:
+.L_sha512_block_data_order_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ movl 20(%esp),%esi
+ movl 24(%esp),%edi
+ movl 28(%esp),%eax
+ movl %esp,%ebx
+ call .L000pic_point
+.L000pic_point:
+ popl %ebp
+ leal .L001K512-.L000pic_point(%ebp),%ebp
+ subl $16,%esp
+ andl $-64,%esp
+ shll $7,%eax
+ addl %edi,%eax
+ movl %esi,(%esp)
+ movl %edi,4(%esp)
+ movl %eax,8(%esp)
+ movl %ebx,12(%esp)
+.align 16
+.L002loop_x86:
+ movl (%edi),%eax
+ movl 4(%edi),%ebx
+ movl 8(%edi),%ecx
+ movl 12(%edi),%edx
+ bswap %eax
+ bswap %ebx
+ bswap %ecx
+ bswap %edx
+ pushl %eax
+ pushl %ebx
+ pushl %ecx
+ pushl %edx
+ movl 16(%edi),%eax
+ movl 20(%edi),%ebx
+ movl 24(%edi),%ecx
+ movl 28(%edi),%edx
+ bswap %eax
+ bswap %ebx
+ bswap %ecx
+ bswap %edx
+ pushl %eax
+ pushl %ebx
+ pushl %ecx
+ pushl %edx
+ movl 32(%edi),%eax
+ movl 36(%edi),%ebx
+ movl 40(%edi),%ecx
+ movl 44(%edi),%edx
+ bswap %eax
+ bswap %ebx
+ bswap %ecx
+ bswap %edx
+ pushl %eax
+ pushl %ebx
+ pushl %ecx
+ pushl %edx
+ movl 48(%edi),%eax
+ movl 52(%edi),%ebx
+ movl 56(%edi),%ecx
+ movl 60(%edi),%edx
+ bswap %eax
+ bswap %ebx
+ bswap %ecx
+ bswap %edx
+ pushl %eax
+ pushl %ebx
+ pushl %ecx
+ pushl %edx
+ movl 64(%edi),%eax
+ movl 68(%edi),%ebx
+ movl 72(%edi),%ecx
+ movl 76(%edi),%edx
+ bswap %eax
+ bswap %ebx
+ bswap %ecx
+ bswap %edx
+ pushl %eax
+ pushl %ebx
+ pushl %ecx
+ pushl %edx
+ movl 80(%edi),%eax
+ movl 84(%edi),%ebx
+ movl 88(%edi),%ecx
+ movl 92(%edi),%edx
+ bswap %eax
+ bswap %ebx
+ bswap %ecx
+ bswap %edx
+ pushl %eax
+ pushl %ebx
+ pushl %ecx
+ pushl %edx
+ movl 96(%edi),%eax
+ movl 100(%edi),%ebx
+ movl 104(%edi),%ecx
+ movl 108(%edi),%edx
+ bswap %eax
+ bswap %ebx
+ bswap %ecx
+ bswap %edx
+ pushl %eax
+ pushl %ebx
+ pushl %ecx
+ pushl %edx
+ movl 112(%edi),%eax
+ movl 116(%edi),%ebx
+ movl 120(%edi),%ecx
+ movl 124(%edi),%edx
+ bswap %eax
+ bswap %ebx
+ bswap %ecx
+ bswap %edx
+ pushl %eax
+ pushl %ebx
+ pushl %ecx
+ pushl %edx
+ addl $128,%edi
+ subl $72,%esp
+ movl %edi,204(%esp)
+ leal 8(%esp),%edi
+ movl $16,%ecx
+.long 2784229001
+.align 16
+.L00300_15_x86:
+ movl 40(%esp),%ecx
+ movl 44(%esp),%edx
+ movl %ecx,%esi
+ shrl $9,%ecx
+ movl %edx,%edi
+ shrl $9,%edx
+ movl %ecx,%ebx
+ shll $14,%esi
+ movl %edx,%eax
+ shll $14,%edi
+ xorl %esi,%ebx
+ shrl $5,%ecx
+ xorl %edi,%eax
+ shrl $5,%edx
+ xorl %ecx,%eax
+ shll $4,%esi
+ xorl %edx,%ebx
+ shll $4,%edi
+ xorl %esi,%ebx
+ shrl $4,%ecx
+ xorl %edi,%eax
+ shrl $4,%edx
+ xorl %ecx,%eax
+ shll $5,%esi
+ xorl %edx,%ebx
+ shll $5,%edi
+ xorl %esi,%eax
+ xorl %edi,%ebx
+ movl 48(%esp),%ecx
+ movl 52(%esp),%edx
+ movl 56(%esp),%esi
+ movl 60(%esp),%edi
+ addl 64(%esp),%eax
+ adcl 68(%esp),%ebx
+ xorl %esi,%ecx
+ xorl %edi,%edx
+ andl 40(%esp),%ecx
+ andl 44(%esp),%edx
+ addl 192(%esp),%eax
+ adcl 196(%esp),%ebx
+ xorl %esi,%ecx
+ xorl %edi,%edx
+ movl (%ebp),%esi
+ movl 4(%ebp),%edi
+ addl %ecx,%eax
+ adcl %edx,%ebx
+ movl 32(%esp),%ecx
+ movl 36(%esp),%edx
+ addl %esi,%eax
+ adcl %edi,%ebx
+ movl %eax,(%esp)
+ movl %ebx,4(%esp)
+ addl %ecx,%eax
+ adcl %edx,%ebx
+ movl 8(%esp),%ecx
+ movl 12(%esp),%edx
+ movl %eax,32(%esp)
+ movl %ebx,36(%esp)
+ movl %ecx,%esi
+ shrl $2,%ecx
+ movl %edx,%edi
+ shrl $2,%edx
+ movl %ecx,%ebx
+ shll $4,%esi
+ movl %edx,%eax
+ shll $4,%edi
+ xorl %esi,%ebx
+ shrl $5,%ecx
+ xorl %edi,%eax
+ shrl $5,%edx
+ xorl %ecx,%ebx
+ shll $21,%esi
+ xorl %edx,%eax
+ shll $21,%edi
+ xorl %esi,%eax
+ shrl $21,%ecx
+ xorl %edi,%ebx
+ shrl $21,%edx
+ xorl %ecx,%eax
+ shll $5,%esi
+ xorl %edx,%ebx
+ shll $5,%edi
+ xorl %esi,%eax
+ xorl %edi,%ebx
+ movl 8(%esp),%ecx
+ movl 12(%esp),%edx
+ movl 16(%esp),%esi
+ movl 20(%esp),%edi
+ addl (%esp),%eax
+ adcl 4(%esp),%ebx
+ orl %esi,%ecx
+ orl %edi,%edx
+ andl 24(%esp),%ecx
+ andl 28(%esp),%edx
+ andl 8(%esp),%esi
+ andl 12(%esp),%edi
+ orl %esi,%ecx
+ orl %edi,%edx
+ addl %ecx,%eax
+ adcl %edx,%ebx
+ movl %eax,(%esp)
+ movl %ebx,4(%esp)
+ movb (%ebp),%dl
+ subl $8,%esp
+ leal 8(%ebp),%ebp
+ cmpb $148,%dl
+ jne .L00300_15_x86
+.align 16
+.L00416_79_x86:
+ movl 312(%esp),%ecx
+ movl 316(%esp),%edx
+ movl %ecx,%esi
+ shrl $1,%ecx
+ movl %edx,%edi
+ shrl $1,%edx
+ movl %ecx,%eax
+ shll $24,%esi
+ movl %edx,%ebx
+ shll $24,%edi
+ xorl %esi,%ebx
+ shrl $6,%ecx
+ xorl %edi,%eax
+ shrl $6,%edx
+ xorl %ecx,%eax
+ shll $7,%esi
+ xorl %edx,%ebx
+ shll $1,%edi
+ xorl %esi,%ebx
+ shrl $1,%ecx
+ xorl %edi,%eax
+ shrl $1,%edx
+ xorl %ecx,%eax
+ shll $6,%edi
+ xorl %edx,%ebx
+ xorl %edi,%eax
+ movl %eax,(%esp)
+ movl %ebx,4(%esp)
+ movl 208(%esp),%ecx
+ movl 212(%esp),%edx
+ movl %ecx,%esi
+ shrl $6,%ecx
+ movl %edx,%edi
+ shrl $6,%edx
+ movl %ecx,%eax
+ shll $3,%esi
+ movl %edx,%ebx
+ shll $3,%edi
+ xorl %esi,%eax
+ shrl $13,%ecx
+ xorl %edi,%ebx
+ shrl $13,%edx
+ xorl %ecx,%eax
+ shll $10,%esi
+ xorl %edx,%ebx
+ shll $10,%edi
+ xorl %esi,%ebx
+ shrl $10,%ecx
+ xorl %edi,%eax
+ shrl $10,%edx
+ xorl %ecx,%ebx
+ shll $13,%edi
+ xorl %edx,%eax
+ xorl %edi,%eax
+ movl 320(%esp),%ecx
+ movl 324(%esp),%edx
+ addl (%esp),%eax
+ adcl 4(%esp),%ebx
+ movl 248(%esp),%esi
+ movl 252(%esp),%edi
+ addl %ecx,%eax
+ adcl %edx,%ebx
+ addl %esi,%eax
+ adcl %edi,%ebx
+ movl %eax,192(%esp)
+ movl %ebx,196(%esp)
+ movl 40(%esp),%ecx
+ movl 44(%esp),%edx
+ movl %ecx,%esi
+ shrl $9,%ecx
+ movl %edx,%edi
+ shrl $9,%edx
+ movl %ecx,%ebx
+ shll $14,%esi
+ movl %edx,%eax
+ shll $14,%edi
+ xorl %esi,%ebx
+ shrl $5,%ecx
+ xorl %edi,%eax
+ shrl $5,%edx
+ xorl %ecx,%eax
+ shll $4,%esi
+ xorl %edx,%ebx
+ shll $4,%edi
+ xorl %esi,%ebx
+ shrl $4,%ecx
+ xorl %edi,%eax
+ shrl $4,%edx
+ xorl %ecx,%eax
+ shll $5,%esi
+ xorl %edx,%ebx
+ shll $5,%edi
+ xorl %esi,%eax
+ xorl %edi,%ebx
+ movl 48(%esp),%ecx
+ movl 52(%esp),%edx
+ movl 56(%esp),%esi
+ movl 60(%esp),%edi
+ addl 64(%esp),%eax
+ adcl 68(%esp),%ebx
+ xorl %esi,%ecx
+ xorl %edi,%edx
+ andl 40(%esp),%ecx
+ andl 44(%esp),%edx
+ addl 192(%esp),%eax
+ adcl 196(%esp),%ebx
+ xorl %esi,%ecx
+ xorl %edi,%edx
+ movl (%ebp),%esi
+ movl 4(%ebp),%edi
+ addl %ecx,%eax
+ adcl %edx,%ebx
+ movl 32(%esp),%ecx
+ movl 36(%esp),%edx
+ addl %esi,%eax
+ adcl %edi,%ebx
+ movl %eax,(%esp)
+ movl %ebx,4(%esp)
+ addl %ecx,%eax
+ adcl %edx,%ebx
+ movl 8(%esp),%ecx
+ movl 12(%esp),%edx
+ movl %eax,32(%esp)
+ movl %ebx,36(%esp)
+ movl %ecx,%esi
+ shrl $2,%ecx
+ movl %edx,%edi
+ shrl $2,%edx
+ movl %ecx,%ebx
+ shll $4,%esi
+ movl %edx,%eax
+ shll $4,%edi
+ xorl %esi,%ebx
+ shrl $5,%ecx
+ xorl %edi,%eax
+ shrl $5,%edx
+ xorl %ecx,%ebx
+ shll $21,%esi
+ xorl %edx,%eax
+ shll $21,%edi
+ xorl %esi,%eax
+ shrl $21,%ecx
+ xorl %edi,%ebx
+ shrl $21,%edx
+ xorl %ecx,%eax
+ shll $5,%esi
+ xorl %edx,%ebx
+ shll $5,%edi
+ xorl %esi,%eax
+ xorl %edi,%ebx
+ movl 8(%esp),%ecx
+ movl 12(%esp),%edx
+ movl 16(%esp),%esi
+ movl 20(%esp),%edi
+ addl (%esp),%eax
+ adcl 4(%esp),%ebx
+ orl %esi,%ecx
+ orl %edi,%edx
+ andl 24(%esp),%ecx
+ andl 28(%esp),%edx
+ andl 8(%esp),%esi
+ andl 12(%esp),%edi
+ orl %esi,%ecx
+ orl %edi,%edx
+ addl %ecx,%eax
+ adcl %edx,%ebx
+ movl %eax,(%esp)
+ movl %ebx,4(%esp)
+ movb (%ebp),%dl
+ subl $8,%esp
+ leal 8(%ebp),%ebp
+ cmpb $23,%dl
+ jne .L00416_79_x86
+ movl 840(%esp),%esi
+ movl 844(%esp),%edi
+ movl (%esi),%eax
+ movl 4(%esi),%ebx
+ movl 8(%esi),%ecx
+ movl 12(%esi),%edx
+ addl 8(%esp),%eax
+ adcl 12(%esp),%ebx
+ movl %eax,(%esi)
+ movl %ebx,4(%esi)
+ addl 16(%esp),%ecx
+ adcl 20(%esp),%edx
+ movl %ecx,8(%esi)
+ movl %edx,12(%esi)
+ movl 16(%esi),%eax
+ movl 20(%esi),%ebx
+ movl 24(%esi),%ecx
+ movl 28(%esi),%edx
+ addl 24(%esp),%eax
+ adcl 28(%esp),%ebx
+ movl %eax,16(%esi)
+ movl %ebx,20(%esi)
+ addl 32(%esp),%ecx
+ adcl 36(%esp),%edx
+ movl %ecx,24(%esi)
+ movl %edx,28(%esi)
+ movl 32(%esi),%eax
+ movl 36(%esi),%ebx
+ movl 40(%esi),%ecx
+ movl 44(%esi),%edx
+ addl 40(%esp),%eax
+ adcl 44(%esp),%ebx
+ movl %eax,32(%esi)
+ movl %ebx,36(%esi)
+ addl 48(%esp),%ecx
+ adcl 52(%esp),%edx
+ movl %ecx,40(%esi)
+ movl %edx,44(%esi)
+ movl 48(%esi),%eax
+ movl 52(%esi),%ebx
+ movl 56(%esi),%ecx
+ movl 60(%esi),%edx
+ addl 56(%esp),%eax
+ adcl 60(%esp),%ebx
+ movl %eax,48(%esi)
+ movl %ebx,52(%esi)
+ addl 64(%esp),%ecx
+ adcl 68(%esp),%edx
+ movl %ecx,56(%esi)
+ movl %edx,60(%esi)
+ addl $840,%esp
+ subl $640,%ebp
+ cmpl 8(%esp),%edi
+ jb .L002loop_x86
+ movl 12(%esp),%esp
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.align 64
+.L001K512:
+.long 3609767458,1116352408
+.long 602891725,1899447441
+.long 3964484399,3049323471
+.long 2173295548,3921009573
+.long 4081628472,961987163
+.long 3053834265,1508970993
+.long 2937671579,2453635748
+.long 3664609560,2870763221
+.long 2734883394,3624381080
+.long 1164996542,310598401
+.long 1323610764,607225278
+.long 3590304994,1426881987
+.long 4068182383,1925078388
+.long 991336113,2162078206
+.long 633803317,2614888103
+.long 3479774868,3248222580
+.long 2666613458,3835390401
+.long 944711139,4022224774
+.long 2341262773,264347078
+.long 2007800933,604807628
+.long 1495990901,770255983
+.long 1856431235,1249150122
+.long 3175218132,1555081692
+.long 2198950837,1996064986
+.long 3999719339,2554220882
+.long 766784016,2821834349
+.long 2566594879,2952996808
+.long 3203337956,3210313671
+.long 1034457026,3336571891
+.long 2466948901,3584528711
+.long 3758326383,113926993
+.long 168717936,338241895
+.long 1188179964,666307205
+.long 1546045734,773529912
+.long 1522805485,1294757372
+.long 2643833823,1396182291
+.long 2343527390,1695183700
+.long 1014477480,1986661051
+.long 1206759142,2177026350
+.long 344077627,2456956037
+.long 1290863460,2730485921
+.long 3158454273,2820302411
+.long 3505952657,3259730800
+.long 106217008,3345764771
+.long 3606008344,3516065817
+.long 1432725776,3600352804
+.long 1467031594,4094571909
+.long 851169720,275423344
+.long 3100823752,430227734
+.long 1363258195,506948616
+.long 3750685593,659060556
+.long 3785050280,883997877
+.long 3318307427,958139571
+.long 3812723403,1322822218
+.long 2003034995,1537002063
+.long 3602036899,1747873779
+.long 1575990012,1955562222
+.long 1125592928,2024104815
+.long 2716904306,2227730452
+.long 442776044,2361852424
+.long 593698344,2428436474
+.long 3733110249,2756734187
+.long 2999351573,3204031479
+.long 3815920427,3329325298
+.long 3928383900,3391569614
+.long 566280711,3515267271
+.long 3454069534,3940187606
+.long 4000239992,4118630271
+.long 1914138554,116418474
+.long 2731055270,174292421
+.long 3203993006,289380356
+.long 320620315,460393269
+.long 587496836,685471733
+.long 1086792851,852142971
+.long 365543100,1017036298
+.long 2618297676,1126000580
+.long 3409855158,1288033470
+.long 4234509866,1501505948
+.long 987167468,1607167915
+.long 1246189591,1816402316
+.long 67438087,66051
+.long 202182159,134810123
+.size sha512_block_data_order,.-.L_sha512_block_data_order_begin
+.byte 83,72,65,53,49,50,32,98,108,111,99,107,32,116,114,97
+.byte 110,115,102,111,114,109,32,102,111,114,32,120,56,54,44,32
+.byte 67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97
+.byte 112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103
+.byte 62,0
+#endif
diff --git a/linux-x86_64/crypto/aes/aes-x86_64.S b/linux-x86_64/crypto/aes/aes-x86_64.S
new file mode 100644
index 0000000..b01ad7f
--- /dev/null
+++ b/linux-x86_64/crypto/aes/aes-x86_64.S
@@ -0,0 +1,2535 @@
+#if defined(__x86_64__)
+.text
+.type _x86_64_AES_encrypt,@function
+.align 16
+_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
+.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
+.byte 0xf3,0xc3
+.size _x86_64_AES_encrypt,.-_x86_64_AES_encrypt
+.type _x86_64_AES_encrypt_compact,@function
+.align 16
+_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
+.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 %dl,%r8d
+ movzbl %bh,%esi
+ movzbl %ch,%edi
+ shrl $16,%ecx
+ movzbl %dh,%ebp
+ movzbl (%r14,%r10,1),%r10d
+ movzbl (%r14,%r11,1),%r11d
+ movzbl (%r14,%r12,1),%r12d
+ movzbl (%r14,%r8,1),%r8d
+
+ movzbl (%r14,%rsi,1),%r9d
+ movzbl %ah,%esi
+ movzbl (%r14,%rdi,1),%r13d
+ movzbl %cl,%edi
+ movzbl (%r14,%rbp,1),%ebp
+ movzbl (%r14,%rsi,1),%esi
+
+ shll $8,%r9d
+ shrl $16,%edx
+ shll $8,%r13d
+ xorl %r9d,%r10d
+ shrl $16,%eax
+ movzbl %dl,%r9d
+ shrl $16,%ebx
+ xorl %r13d,%r11d
+ shll $8,%ebp
+ movzbl %al,%r13d
+ movzbl (%r14,%rdi,1),%edi
+ xorl %ebp,%r12d
+
+ shll $8,%esi
+ movzbl %bl,%ebp
+ shll $16,%edi
+ xorl %esi,%r8d
+ movzbl (%r14,%r9,1),%r9d
+ movzbl %dh,%esi
+ movzbl (%r14,%r13,1),%r13d
+ xorl %edi,%r10d
+
+ shrl $8,%ecx
+ movzbl %ah,%edi
+ shll $16,%r9d
+ shrl $8,%ebx
+ shll $16,%r13d
+ xorl %r9d,%r11d
+ movzbl (%r14,%rbp,1),%ebp
+ movzbl (%r14,%rsi,1),%esi
+ movzbl (%r14,%rdi,1),%edi
+ movzbl (%r14,%rcx,1),%edx
+ movzbl (%r14,%rbx,1),%ecx
+
+ shll $16,%ebp
+ xorl %r13d,%r12d
+ shll $24,%esi
+ xorl %ebp,%r8d
+ shll $24,%edi
+ xorl %esi,%r10d
+ shll $24,%edx
+ xorl %edi,%r11d
+ shll $24,%ecx
+ movl %r10d,%eax
+ movl %r11d,%ebx
+ xorl %r12d,%ecx
+ xorl %r8d,%edx
+ cmpq 16(%rsp),%r15
+ je .Lenc_compact_done
+ movl $2155905152,%r10d
+ movl $2155905152,%r11d
+ andl %eax,%r10d
+ andl %ebx,%r11d
+ movl %r10d,%esi
+ movl %r11d,%edi
+ 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 $2155905152,%r12d
+ roll $24,%eax
+ movl $2155905152,%ebp
+ roll $24,%ebx
+ andl %ecx,%r12d
+ andl %edx,%ebp
+ xorl %r8d,%eax
+ xorl %r9d,%ebx
+ movl %r12d,%esi
+ rorl $16,%r10d
+ movl %ebp,%edi
+ rorl $16,%r11d
+ leal (%rcx,%rcx,1),%r8d
+ shrl $7,%r12d
+ xorl %r10d,%eax
+ shrl $7,%ebp
+ xorl %r11d,%ebx
+ rorl $8,%r10d
+ leal (%rdx,%rdx,1),%r9d
+ 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
+
+ rorl $16,%r12d
+ xorl %r8d,%ecx
+ rorl $16,%ebp
+ xorl %r9d,%edx
+ roll $24,%ecx
+ movl 0(%r14),%esi
+ roll $24,%edx
+ xorl %r8d,%ecx
+ movl 64(%r14),%edi
+ xorl %r9d,%edx
+ movl 128(%r14),%r8d
+ xorl %r12d,%ecx
+ rorl $8,%r12d
+ xorl %ebp,%edx
+ rorl $8,%ebp
+ xorl %r12d,%ecx
+ movl 192(%r14),%r9d
+ 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
+.byte 0xf3,0xc3
+.size _x86_64_AES_encrypt_compact,.-_x86_64_AES_encrypt_compact
+.align 16
+.globl asm_AES_encrypt
+.hidden asm_AES_encrypt
+.type asm_AES_encrypt,@function
+.hidden asm_AES_encrypt
+asm_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)
+.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:
+ .byte 0xf3,0xc3
+.size asm_AES_encrypt,.-asm_AES_encrypt
+.type _x86_64_AES_decrypt,@function
+.align 16
+_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
+.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
+.byte 0xf3,0xc3
+.size _x86_64_AES_decrypt,.-_x86_64_AES_decrypt
+.type _x86_64_AES_decrypt_compact,@function
+.align 16
+_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
+
+.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 %dl,%r8d
+ movzbl %dh,%esi
+ movzbl %ah,%edi
+ shrl $16,%edx
+ movzbl %bh,%ebp
+ movzbl (%r14,%r10,1),%r10d
+ movzbl (%r14,%r11,1),%r11d
+ movzbl (%r14,%r12,1),%r12d
+ movzbl (%r14,%r8,1),%r8d
+
+ movzbl (%r14,%rsi,1),%r9d
+ movzbl %ch,%esi
+ movzbl (%r14,%rdi,1),%r13d
+ movzbl (%r14,%rbp,1),%ebp
+ movzbl (%r14,%rsi,1),%esi
+
+ shrl $16,%ecx
+ shll $8,%r13d
+ shll $8,%r9d
+ movzbl %cl,%edi
+ shrl $16,%eax
+ xorl %r9d,%r10d
+ shrl $16,%ebx
+ movzbl %dl,%r9d
+
+ shll $8,%ebp
+ xorl %r13d,%r11d
+ shll $8,%esi
+ movzbl %al,%r13d
+ movzbl (%r14,%rdi,1),%edi
+ xorl %ebp,%r12d
+ movzbl %bl,%ebp
+
+ shll $16,%edi
+ xorl %esi,%r8d
+ movzbl (%r14,%r9,1),%r9d
+ movzbl %bh,%esi
+ movzbl (%r14,%rbp,1),%ebp
+ xorl %edi,%r10d
+ movzbl (%r14,%r13,1),%r13d
+ movzbl %ch,%edi
+
+ shll $16,%ebp
+ shll $16,%r9d
+ shll $16,%r13d
+ xorl %ebp,%r8d
+ movzbl %dh,%ebp
+ xorl %r9d,%r11d
+ shrl $8,%eax
+ xorl %r13d,%r12d
+
+ movzbl (%r14,%rsi,1),%esi
+ movzbl (%r14,%rdi,1),%ebx
+ movzbl (%r14,%rbp,1),%ecx
+ movzbl (%r14,%rax,1),%edx
+
+ movl %r10d,%eax
+ shll $24,%esi
+ shll $24,%ebx
+ shll $24,%ecx
+ xorl %esi,%eax
+ shll $24,%edx
+ xorl %r11d,%ebx
+ 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 %rsi,%r9
+ movq %rsi,%r12
+ andq %rax,%r9
+ andq %rcx,%r12
+ movq %r9,%rbx
+ movq %r12,%rdx
+ 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 %rbx,%r8
+ xorq %rdx,%r11
+ movq %rsi,%r10
+ movq %rsi,%r13
+
+ andq %r8,%r10
+ andq %r11,%r13
+ movq %r10,%rbx
+ movq %r13,%rdx
+ 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 %rbx,%r9
+ xorq %rdx,%r12
+ movq %rsi,%r10
+ movq %rsi,%r13
+
+ andq %r9,%r10
+ andq %r12,%r13
+ movq %r10,%rbx
+ movq %r13,%rdx
+ 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
+ shrq $32,%rbx
+ xorq %r13,%r12
+ shrq $32,%rdx
+ xorq %r8,%r10
+ roll $8,%eax
+ xorq %r11,%r13
+ roll $8,%ecx
+ xorq %r9,%r10
+ roll $8,%ebx
+ xorq %r12,%r13
+
+ roll $8,%edx
+ xorl %r10d,%eax
+ shrq $32,%r10
+ xorl %r13d,%ecx
+ shrq $32,%r13
+ xorl %r10d,%ebx
+ xorl %r13d,%edx
+
+ movq %r8,%r10
+ roll $24,%r8d
+ movq %r11,%r13
+ roll $24,%r11d
+ shrq $32,%r10
+ xorl %r8d,%eax
+ shrq $32,%r13
+ xorl %r11d,%ecx
+ roll $24,%r10d
+ movq %r9,%r8
+ roll $24,%r13d
+ movq %r12,%r11
+ shrq $32,%r8
+ xorl %r10d,%ebx
+ shrq $32,%r11
+ xorl %r13d,%edx
+
+ movq 0(%r14),%rsi
+ roll $16,%r9d
+ movq 64(%r14),%rdi
+ roll $16,%r12d
+ movq 128(%r14),%rbp
+ roll $16,%r8d
+ movq 192(%r14),%r10
+ xorl %r9d,%eax
+ roll $16,%r11d
+ 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
+.byte 0xf3,0xc3
+.size _x86_64_AES_decrypt_compact,.-_x86_64_AES_decrypt_compact
+.align 16
+.globl asm_AES_decrypt
+.hidden asm_AES_decrypt
+.type asm_AES_decrypt,@function
+.hidden asm_AES_decrypt
+asm_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)
+.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:
+ .byte 0xf3,0xc3
+.size asm_AES_decrypt,.-asm_AES_decrypt
+.align 16
+.globl asm_AES_set_encrypt_key
+.hidden asm_AES_set_encrypt_key
+.type asm_AES_set_encrypt_key,@function
+asm_AES_set_encrypt_key:
+ 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 40(%rsp),%rbp
+ movq 48(%rsp),%rbx
+ addq $56,%rsp
+.Lenc_key_epilogue:
+ .byte 0xf3,0xc3
+.size asm_AES_set_encrypt_key,.-asm_AES_set_encrypt_key
+
+.type _x86_64_AES_set_encrypt_key,@function
+.align 16
+_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
+.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:
+.byte 0xf3,0xc3
+.size _x86_64_AES_set_encrypt_key,.-_x86_64_AES_set_encrypt_key
+.align 16
+.globl asm_AES_set_decrypt_key
+.hidden asm_AES_set_decrypt_key
+.type asm_AES_set_decrypt_key,@function
+asm_AES_set_decrypt_key:
+ 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 %rsi,%r9
+ movq %rsi,%r12
+ andq %rax,%r9
+ andq %rcx,%r12
+ movq %r9,%rbx
+ movq %r12,%rdx
+ 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 %rbx,%r8
+ xorq %rdx,%r11
+ movq %rsi,%r10
+ movq %rsi,%r13
+
+ andq %r8,%r10
+ andq %r11,%r13
+ movq %r10,%rbx
+ movq %r13,%rdx
+ 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 %rbx,%r9
+ xorq %rdx,%r12
+ movq %rsi,%r10
+ movq %rsi,%r13
+
+ andq %r9,%r10
+ andq %r12,%r13
+ movq %r10,%rbx
+ movq %r13,%rdx
+ 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
+ shrq $32,%rbx
+ xorq %r13,%r12
+ shrq $32,%rdx
+ xorq %r8,%r10
+ roll $8,%eax
+ xorq %r11,%r13
+ roll $8,%ecx
+ xorq %r9,%r10
+ roll $8,%ebx
+ xorq %r12,%r13
+
+ roll $8,%edx
+ xorl %r10d,%eax
+ shrq $32,%r10
+ xorl %r13d,%ecx
+ shrq $32,%r13
+ xorl %r10d,%ebx
+ xorl %r13d,%edx
+
+ movq %r8,%r10
+ roll $24,%r8d
+ movq %r11,%r13
+ roll $24,%r11d
+ shrq $32,%r10
+ xorl %r8d,%eax
+ shrq $32,%r13
+ xorl %r11d,%ecx
+ roll $24,%r10d
+ movq %r9,%r8
+ roll $24,%r13d
+ movq %r12,%r11
+ shrq $32,%r8
+ xorl %r10d,%ebx
+ shrq $32,%r11
+ xorl %r13d,%edx
+
+
+ roll $16,%r9d
+
+ roll $16,%r12d
+
+ roll $16,%r8d
+
+ xorl %r9d,%eax
+ roll $16,%r11d
+ 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:
+ .byte 0xf3,0xc3
+.size asm_AES_set_decrypt_key,.-asm_AES_set_decrypt_key
+.align 16
+.globl asm_AES_cbc_encrypt
+.hidden asm_AES_cbc_encrypt
+.type asm_AES_cbc_encrypt,@function
+
+.hidden asm_AES_cbc_encrypt
+asm_AES_cbc_encrypt:
+ 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 $28,%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:
+ .byte 0xf3,0xc3
+.size asm_AES_cbc_encrypt,.-asm_AES_cbc_encrypt
+.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
+.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
+.align 64
+#endif
diff --git a/linux-x86_64/crypto/aes/aesni-x86_64.S b/linux-x86_64/crypto/aes/aesni-x86_64.S
new file mode 100644
index 0000000..9ab973d
--- /dev/null
+++ b/linux-x86_64/crypto/aes/aesni-x86_64.S
@@ -0,0 +1,3178 @@
+#if defined(__x86_64__)
+.text
+
+.globl aesni_encrypt
+.hidden aesni_encrypt
+.type aesni_encrypt,@function
+.align 16
+aesni_encrypt:
+ movups (%rdi),%xmm2
+ movl 240(%rdx),%eax
+ movups (%rdx),%xmm0
+ movups 16(%rdx),%xmm1
+ leaq 32(%rdx),%rdx
+ xorps %xmm0,%xmm2
+.Loop_enc1_1:
+.byte 102,15,56,220,209
+ decl %eax
+ movups (%rdx),%xmm1
+ leaq 16(%rdx),%rdx
+ jnz .Loop_enc1_1
+.byte 102,15,56,221,209
+ movups %xmm2,(%rsi)
+ .byte 0xf3,0xc3
+.size aesni_encrypt,.-aesni_encrypt
+
+.globl aesni_decrypt
+.hidden aesni_decrypt
+.type aesni_decrypt,@function
+.align 16
+aesni_decrypt:
+ movups (%rdi),%xmm2
+ movl 240(%rdx),%eax
+ movups (%rdx),%xmm0
+ movups 16(%rdx),%xmm1
+ leaq 32(%rdx),%rdx
+ xorps %xmm0,%xmm2
+.Loop_dec1_2:
+.byte 102,15,56,222,209
+ decl %eax
+ movups (%rdx),%xmm1
+ leaq 16(%rdx),%rdx
+ jnz .Loop_dec1_2
+.byte 102,15,56,223,209
+ movups %xmm2,(%rsi)
+ .byte 0xf3,0xc3
+.size aesni_decrypt, .-aesni_decrypt
+.type _aesni_encrypt2,@function
+.align 16
+_aesni_encrypt2:
+ movups (%rcx),%xmm0
+ shll $4,%eax
+ movups 16(%rcx),%xmm1
+ xorps %xmm0,%xmm2
+ xorps %xmm0,%xmm3
+ movups 32(%rcx),%xmm0
+ leaq 32(%rcx,%rax,1),%rcx
+ negq %rax
+ addq $16,%rax
+
+.Lenc_loop2:
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+ movups (%rcx,%rax,1),%xmm1
+ addq $32,%rax
+.byte 102,15,56,220,208
+.byte 102,15,56,220,216
+ movups -16(%rcx,%rax,1),%xmm0
+ jnz .Lenc_loop2
+
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+.byte 102,15,56,221,208
+.byte 102,15,56,221,216
+ .byte 0xf3,0xc3
+.size _aesni_encrypt2,.-_aesni_encrypt2
+.type _aesni_decrypt2,@function
+.align 16
+_aesni_decrypt2:
+ movups (%rcx),%xmm0
+ shll $4,%eax
+ movups 16(%rcx),%xmm1
+ xorps %xmm0,%xmm2
+ xorps %xmm0,%xmm3
+ movups 32(%rcx),%xmm0
+ leaq 32(%rcx,%rax,1),%rcx
+ negq %rax
+ addq $16,%rax
+
+.Ldec_loop2:
+.byte 102,15,56,222,209
+.byte 102,15,56,222,217
+ movups (%rcx,%rax,1),%xmm1
+ addq $32,%rax
+.byte 102,15,56,222,208
+.byte 102,15,56,222,216
+ movups -16(%rcx,%rax,1),%xmm0
+ jnz .Ldec_loop2
+
+.byte 102,15,56,222,209
+.byte 102,15,56,222,217
+.byte 102,15,56,223,208
+.byte 102,15,56,223,216
+ .byte 0xf3,0xc3
+.size _aesni_decrypt2,.-_aesni_decrypt2
+.type _aesni_encrypt3,@function
+.align 16
+_aesni_encrypt3:
+ movups (%rcx),%xmm0
+ shll $4,%eax
+ movups 16(%rcx),%xmm1
+ xorps %xmm0,%xmm2
+ xorps %xmm0,%xmm3
+ xorps %xmm0,%xmm4
+ movups 32(%rcx),%xmm0
+ leaq 32(%rcx,%rax,1),%rcx
+ negq %rax
+ addq $16,%rax
+
+.Lenc_loop3:
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+.byte 102,15,56,220,225
+ movups (%rcx,%rax,1),%xmm1
+ addq $32,%rax
+.byte 102,15,56,220,208
+.byte 102,15,56,220,216
+.byte 102,15,56,220,224
+ movups -16(%rcx,%rax,1),%xmm0
+ jnz .Lenc_loop3
+
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+.byte 102,15,56,220,225
+.byte 102,15,56,221,208
+.byte 102,15,56,221,216
+.byte 102,15,56,221,224
+ .byte 0xf3,0xc3
+.size _aesni_encrypt3,.-_aesni_encrypt3
+.type _aesni_decrypt3,@function
+.align 16
+_aesni_decrypt3:
+ movups (%rcx),%xmm0
+ shll $4,%eax
+ movups 16(%rcx),%xmm1
+ xorps %xmm0,%xmm2
+ xorps %xmm0,%xmm3
+ xorps %xmm0,%xmm4
+ movups 32(%rcx),%xmm0
+ leaq 32(%rcx,%rax,1),%rcx
+ negq %rax
+ addq $16,%rax
+
+.Ldec_loop3:
+.byte 102,15,56,222,209
+.byte 102,15,56,222,217
+.byte 102,15,56,222,225
+ movups (%rcx,%rax,1),%xmm1
+ addq $32,%rax
+.byte 102,15,56,222,208
+.byte 102,15,56,222,216
+.byte 102,15,56,222,224
+ movups -16(%rcx,%rax,1),%xmm0
+ jnz .Ldec_loop3
+
+.byte 102,15,56,222,209
+.byte 102,15,56,222,217
+.byte 102,15,56,222,225
+.byte 102,15,56,223,208
+.byte 102,15,56,223,216
+.byte 102,15,56,223,224
+ .byte 0xf3,0xc3
+.size _aesni_decrypt3,.-_aesni_decrypt3
+.type _aesni_encrypt4,@function
+.align 16
+_aesni_encrypt4:
+ movups (%rcx),%xmm0
+ shll $4,%eax
+ movups 16(%rcx),%xmm1
+ xorps %xmm0,%xmm2
+ xorps %xmm0,%xmm3
+ xorps %xmm0,%xmm4
+ xorps %xmm0,%xmm5
+ movups 32(%rcx),%xmm0
+ leaq 32(%rcx,%rax,1),%rcx
+ negq %rax
+.byte 0x0f,0x1f,0x00
+ addq $16,%rax
+
+.Lenc_loop4:
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+.byte 102,15,56,220,225
+.byte 102,15,56,220,233
+ movups (%rcx,%rax,1),%xmm1
+ addq $32,%rax
+.byte 102,15,56,220,208
+.byte 102,15,56,220,216
+.byte 102,15,56,220,224
+.byte 102,15,56,220,232
+ movups -16(%rcx,%rax,1),%xmm0
+ jnz .Lenc_loop4
+
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+.byte 102,15,56,220,225
+.byte 102,15,56,220,233
+.byte 102,15,56,221,208
+.byte 102,15,56,221,216
+.byte 102,15,56,221,224
+.byte 102,15,56,221,232
+ .byte 0xf3,0xc3
+.size _aesni_encrypt4,.-_aesni_encrypt4
+.type _aesni_decrypt4,@function
+.align 16
+_aesni_decrypt4:
+ movups (%rcx),%xmm0
+ shll $4,%eax
+ movups 16(%rcx),%xmm1
+ xorps %xmm0,%xmm2
+ xorps %xmm0,%xmm3
+ xorps %xmm0,%xmm4
+ xorps %xmm0,%xmm5
+ movups 32(%rcx),%xmm0
+ leaq 32(%rcx,%rax,1),%rcx
+ negq %rax
+.byte 0x0f,0x1f,0x00
+ addq $16,%rax
+
+.Ldec_loop4:
+.byte 102,15,56,222,209
+.byte 102,15,56,222,217
+.byte 102,15,56,222,225
+.byte 102,15,56,222,233
+ movups (%rcx,%rax,1),%xmm1
+ addq $32,%rax
+.byte 102,15,56,222,208
+.byte 102,15,56,222,216
+.byte 102,15,56,222,224
+.byte 102,15,56,222,232
+ movups -16(%rcx,%rax,1),%xmm0
+ jnz .Ldec_loop4
+
+.byte 102,15,56,222,209
+.byte 102,15,56,222,217
+.byte 102,15,56,222,225
+.byte 102,15,56,222,233
+.byte 102,15,56,223,208
+.byte 102,15,56,223,216
+.byte 102,15,56,223,224
+.byte 102,15,56,223,232
+ .byte 0xf3,0xc3
+.size _aesni_decrypt4,.-_aesni_decrypt4
+.type _aesni_encrypt6,@function
+.align 16
+_aesni_encrypt6:
+ movups (%rcx),%xmm0
+ shll $4,%eax
+ movups 16(%rcx),%xmm1
+ xorps %xmm0,%xmm2
+ pxor %xmm0,%xmm3
+ pxor %xmm0,%xmm4
+.byte 102,15,56,220,209
+ leaq 32(%rcx,%rax,1),%rcx
+ negq %rax
+.byte 102,15,56,220,217
+ pxor %xmm0,%xmm5
+ pxor %xmm0,%xmm6
+.byte 102,15,56,220,225
+ pxor %xmm0,%xmm7
+ addq $16,%rax
+.byte 102,15,56,220,233
+.byte 102,15,56,220,241
+.byte 102,15,56,220,249
+ movups -16(%rcx,%rax,1),%xmm0
+ jmp .Lenc_loop6_enter
+.align 16
+.Lenc_loop6:
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+.byte 102,15,56,220,225
+.byte 102,15,56,220,233
+.byte 102,15,56,220,241
+.byte 102,15,56,220,249
+.Lenc_loop6_enter:
+ movups (%rcx,%rax,1),%xmm1
+ addq $32,%rax
+.byte 102,15,56,220,208
+.byte 102,15,56,220,216
+.byte 102,15,56,220,224
+.byte 102,15,56,220,232
+.byte 102,15,56,220,240
+.byte 102,15,56,220,248
+ movups -16(%rcx,%rax,1),%xmm0
+ jnz .Lenc_loop6
+
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+.byte 102,15,56,220,225
+.byte 102,15,56,220,233
+.byte 102,15,56,220,241
+.byte 102,15,56,220,249
+.byte 102,15,56,221,208
+.byte 102,15,56,221,216
+.byte 102,15,56,221,224
+.byte 102,15,56,221,232
+.byte 102,15,56,221,240
+.byte 102,15,56,221,248
+ .byte 0xf3,0xc3
+.size _aesni_encrypt6,.-_aesni_encrypt6
+.type _aesni_decrypt6,@function
+.align 16
+_aesni_decrypt6:
+ movups (%rcx),%xmm0
+ shll $4,%eax
+ movups 16(%rcx),%xmm1
+ xorps %xmm0,%xmm2
+ pxor %xmm0,%xmm3
+ pxor %xmm0,%xmm4
+.byte 102,15,56,222,209
+ leaq 32(%rcx,%rax,1),%rcx
+ negq %rax
+.byte 102,15,56,222,217
+ pxor %xmm0,%xmm5
+ pxor %xmm0,%xmm6
+.byte 102,15,56,222,225
+ pxor %xmm0,%xmm7
+ addq $16,%rax
+.byte 102,15,56,222,233
+.byte 102,15,56,222,241
+.byte 102,15,56,222,249
+ movups -16(%rcx,%rax,1),%xmm0
+ jmp .Ldec_loop6_enter
+.align 16
+.Ldec_loop6:
+.byte 102,15,56,222,209
+.byte 102,15,56,222,217
+.byte 102,15,56,222,225
+.byte 102,15,56,222,233
+.byte 102,15,56,222,241
+.byte 102,15,56,222,249
+.Ldec_loop6_enter:
+ movups (%rcx,%rax,1),%xmm1
+ addq $32,%rax
+.byte 102,15,56,222,208
+.byte 102,15,56,222,216
+.byte 102,15,56,222,224
+.byte 102,15,56,222,232
+.byte 102,15,56,222,240
+.byte 102,15,56,222,248
+ movups -16(%rcx,%rax,1),%xmm0
+ jnz .Ldec_loop6
+
+.byte 102,15,56,222,209
+.byte 102,15,56,222,217
+.byte 102,15,56,222,225
+.byte 102,15,56,222,233
+.byte 102,15,56,222,241
+.byte 102,15,56,222,249
+.byte 102,15,56,223,208
+.byte 102,15,56,223,216
+.byte 102,15,56,223,224
+.byte 102,15,56,223,232
+.byte 102,15,56,223,240
+.byte 102,15,56,223,248
+ .byte 0xf3,0xc3
+.size _aesni_decrypt6,.-_aesni_decrypt6
+.type _aesni_encrypt8,@function
+.align 16
+_aesni_encrypt8:
+ movups (%rcx),%xmm0
+ shll $4,%eax
+ movups 16(%rcx),%xmm1
+ xorps %xmm0,%xmm2
+ xorps %xmm0,%xmm3
+ pxor %xmm0,%xmm4
+ pxor %xmm0,%xmm5
+ pxor %xmm0,%xmm6
+ leaq 32(%rcx,%rax,1),%rcx
+ negq %rax
+.byte 102,15,56,220,209
+ addq $16,%rax
+ pxor %xmm0,%xmm7
+.byte 102,15,56,220,217
+ pxor %xmm0,%xmm8
+ pxor %xmm0,%xmm9
+.byte 102,15,56,220,225
+.byte 102,15,56,220,233
+.byte 102,15,56,220,241
+.byte 102,15,56,220,249
+.byte 102,68,15,56,220,193
+.byte 102,68,15,56,220,201
+ movups -16(%rcx,%rax,1),%xmm0
+ jmp .Lenc_loop8_enter
+.align 16
+.Lenc_loop8:
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+.byte 102,15,56,220,225
+.byte 102,15,56,220,233
+.byte 102,15,56,220,241
+.byte 102,15,56,220,249
+.byte 102,68,15,56,220,193
+.byte 102,68,15,56,220,201
+.Lenc_loop8_enter:
+ movups (%rcx,%rax,1),%xmm1
+ addq $32,%rax
+.byte 102,15,56,220,208
+.byte 102,15,56,220,216
+.byte 102,15,56,220,224
+.byte 102,15,56,220,232
+.byte 102,15,56,220,240
+.byte 102,15,56,220,248
+.byte 102,68,15,56,220,192
+.byte 102,68,15,56,220,200
+ movups -16(%rcx,%rax,1),%xmm0
+ jnz .Lenc_loop8
+
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+.byte 102,15,56,220,225
+.byte 102,15,56,220,233
+.byte 102,15,56,220,241
+.byte 102,15,56,220,249
+.byte 102,68,15,56,220,193
+.byte 102,68,15,56,220,201
+.byte 102,15,56,221,208
+.byte 102,15,56,221,216
+.byte 102,15,56,221,224
+.byte 102,15,56,221,232
+.byte 102,15,56,221,240
+.byte 102,15,56,221,248
+.byte 102,68,15,56,221,192
+.byte 102,68,15,56,221,200
+ .byte 0xf3,0xc3
+.size _aesni_encrypt8,.-_aesni_encrypt8
+.type _aesni_decrypt8,@function
+.align 16
+_aesni_decrypt8:
+ movups (%rcx),%xmm0
+ shll $4,%eax
+ movups 16(%rcx),%xmm1
+ xorps %xmm0,%xmm2
+ xorps %xmm0,%xmm3
+ pxor %xmm0,%xmm4
+ pxor %xmm0,%xmm5
+ pxor %xmm0,%xmm6
+ leaq 32(%rcx,%rax,1),%rcx
+ negq %rax
+.byte 102,15,56,222,209
+ addq $16,%rax
+ pxor %xmm0,%xmm7
+.byte 102,15,56,222,217
+ pxor %xmm0,%xmm8
+ pxor %xmm0,%xmm9
+.byte 102,15,56,222,225
+.byte 102,15,56,222,233
+.byte 102,15,56,222,241
+.byte 102,15,56,222,249
+.byte 102,68,15,56,222,193
+.byte 102,68,15,56,222,201
+ movups -16(%rcx,%rax,1),%xmm0
+ jmp .Ldec_loop8_enter
+.align 16
+.Ldec_loop8:
+.byte 102,15,56,222,209
+.byte 102,15,56,222,217
+.byte 102,15,56,222,225
+.byte 102,15,56,222,233
+.byte 102,15,56,222,241
+.byte 102,15,56,222,249
+.byte 102,68,15,56,222,193
+.byte 102,68,15,56,222,201
+.Ldec_loop8_enter:
+ movups (%rcx,%rax,1),%xmm1
+ addq $32,%rax
+.byte 102,15,56,222,208
+.byte 102,15,56,222,216
+.byte 102,15,56,222,224
+.byte 102,15,56,222,232
+.byte 102,15,56,222,240
+.byte 102,15,56,222,248
+.byte 102,68,15,56,222,192
+.byte 102,68,15,56,222,200
+ movups -16(%rcx,%rax,1),%xmm0
+ jnz .Ldec_loop8
+
+.byte 102,15,56,222,209
+.byte 102,15,56,222,217
+.byte 102,15,56,222,225
+.byte 102,15,56,222,233
+.byte 102,15,56,222,241
+.byte 102,15,56,222,249
+.byte 102,68,15,56,222,193
+.byte 102,68,15,56,222,201
+.byte 102,15,56,223,208
+.byte 102,15,56,223,216
+.byte 102,15,56,223,224
+.byte 102,15,56,223,232
+.byte 102,15,56,223,240
+.byte 102,15,56,223,248
+.byte 102,68,15,56,223,192
+.byte 102,68,15,56,223,200
+ .byte 0xf3,0xc3
+.size _aesni_decrypt8,.-_aesni_decrypt8
+.globl aesni_ecb_encrypt
+.hidden aesni_ecb_encrypt
+.type aesni_ecb_encrypt,@function
+.align 16
+aesni_ecb_encrypt:
+ 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:
+.byte 102,15,56,220,209
+ decl %eax
+ movups (%rcx),%xmm1
+ leaq 16(%rcx),%rcx
+ jnz .Loop_enc1_3
+.byte 102,15,56,221,209
+ movups %xmm2,(%rsi)
+ jmp .Lecb_ret
+.align 16
+.Lecb_enc_two:
+ call _aesni_encrypt2
+ 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:
+.byte 102,15,56,222,209
+ decl %eax
+ movups (%rcx),%xmm1
+ leaq 16(%rcx),%rcx
+ jnz .Loop_dec1_4
+.byte 102,15,56,223,209
+ movups %xmm2,(%rsi)
+ jmp .Lecb_ret
+.align 16
+.Lecb_dec_two:
+ call _aesni_decrypt2
+ 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:
+ .byte 0xf3,0xc3
+.size aesni_ecb_encrypt,.-aesni_ecb_encrypt
+.globl aesni_ccm64_encrypt_blocks
+.hidden aesni_ccm64_encrypt_blocks
+.type aesni_ccm64_encrypt_blocks,@function
+.align 16
+aesni_ccm64_encrypt_blocks:
+ movl 240(%rcx),%eax
+ movdqu (%r8),%xmm6
+ movdqa .Lincrement64(%rip),%xmm9
+ movdqa .Lbswap_mask(%rip),%xmm7
+
+ shll $4,%eax
+ movl $16,%r10d
+ leaq 0(%rcx),%r11
+ movdqu (%r9),%xmm3
+ movdqa %xmm6,%xmm2
+ leaq 32(%rcx,%rax,1),%rcx
+.byte 102,15,56,0,247
+ subq %rax,%r10
+ jmp .Lccm64_enc_outer
+.align 16
+.Lccm64_enc_outer:
+ movups (%r11),%xmm0
+ movq %r10,%rax
+ movups (%rdi),%xmm8
+
+ xorps %xmm0,%xmm2
+ movups 16(%r11),%xmm1
+ xorps %xmm8,%xmm0
+ xorps %xmm0,%xmm3
+ movups 32(%r11),%xmm0
+
+.Lccm64_enc2_loop:
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+ movups (%rcx,%rax,1),%xmm1
+ addq $32,%rax
+.byte 102,15,56,220,208
+.byte 102,15,56,220,216
+ movups -16(%rcx,%rax,1),%xmm0
+ jnz .Lccm64_enc2_loop
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+ paddq %xmm9,%xmm6
+ decq %rdx
+.byte 102,15,56,221,208
+.byte 102,15,56,221,216
+
+ leaq 16(%rdi),%rdi
+ xorps %xmm2,%xmm8
+ movdqa %xmm6,%xmm2
+ movups %xmm8,(%rsi)
+.byte 102,15,56,0,215
+ leaq 16(%rsi),%rsi
+ jnz .Lccm64_enc_outer
+
+ movups %xmm3,(%r9)
+ .byte 0xf3,0xc3
+.size aesni_ccm64_encrypt_blocks,.-aesni_ccm64_encrypt_blocks
+.globl aesni_ccm64_decrypt_blocks
+.hidden aesni_ccm64_decrypt_blocks
+.type aesni_ccm64_decrypt_blocks,@function
+.align 16
+aesni_ccm64_decrypt_blocks:
+ movl 240(%rcx),%eax
+ movups (%r8),%xmm6
+ movdqu (%r9),%xmm3
+ movdqa .Lincrement64(%rip),%xmm9
+ movdqa .Lbswap_mask(%rip),%xmm7
+
+ movaps %xmm6,%xmm2
+ movl %eax,%r10d
+ movq %rcx,%r11
+.byte 102,15,56,0,247
+ movups (%rcx),%xmm0
+ movups 16(%rcx),%xmm1
+ leaq 32(%rcx),%rcx
+ xorps %xmm0,%xmm2
+.Loop_enc1_5:
+.byte 102,15,56,220,209
+ decl %eax
+ movups (%rcx),%xmm1
+ leaq 16(%rcx),%rcx
+ jnz .Loop_enc1_5
+.byte 102,15,56,221,209
+ shll $4,%r10d
+ movl $16,%eax
+ movups (%rdi),%xmm8
+ paddq %xmm9,%xmm6
+ leaq 16(%rdi),%rdi
+ subq %r10,%rax
+ leaq 32(%r11,%r10,1),%rcx
+ movq %rax,%r10
+ jmp .Lccm64_dec_outer
+.align 16
+.Lccm64_dec_outer:
+ xorps %xmm2,%xmm8
+ movdqa %xmm6,%xmm2
+ movups %xmm8,(%rsi)
+ leaq 16(%rsi),%rsi
+.byte 102,15,56,0,215
+
+ subq $1,%rdx
+ jz .Lccm64_dec_break
+
+ movups (%r11),%xmm0
+ movq %r10,%rax
+ movups 16(%r11),%xmm1
+ xorps %xmm0,%xmm8
+ xorps %xmm0,%xmm2
+ xorps %xmm8,%xmm3
+ movups 32(%r11),%xmm0
+ jmp .Lccm64_dec2_loop
+.align 16
+.Lccm64_dec2_loop:
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+ movups (%rcx,%rax,1),%xmm1
+ addq $32,%rax
+.byte 102,15,56,220,208
+.byte 102,15,56,220,216
+ movups -16(%rcx,%rax,1),%xmm0
+ jnz .Lccm64_dec2_loop
+ movups (%rdi),%xmm8
+ paddq %xmm9,%xmm6
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+.byte 102,15,56,221,208
+.byte 102,15,56,221,216
+ leaq 16(%rdi),%rdi
+ jmp .Lccm64_dec_outer
+
+.align 16
+.Lccm64_dec_break:
+
+ movl 240(%r11),%eax
+ movups (%r11),%xmm0
+ movups 16(%r11),%xmm1
+ xorps %xmm0,%xmm8
+ leaq 32(%r11),%r11
+ xorps %xmm8,%xmm3
+.Loop_enc1_6:
+.byte 102,15,56,220,217
+ decl %eax
+ movups (%r11),%xmm1
+ leaq 16(%r11),%r11
+ jnz .Loop_enc1_6
+.byte 102,15,56,221,217
+ movups %xmm3,(%r9)
+ .byte 0xf3,0xc3
+.size aesni_ccm64_decrypt_blocks,.-aesni_ccm64_decrypt_blocks
+.globl aesni_ctr32_encrypt_blocks
+.hidden aesni_ctr32_encrypt_blocks
+.type aesni_ctr32_encrypt_blocks,@function
+.align 16
+aesni_ctr32_encrypt_blocks:
+ leaq (%rsp),%rax
+ pushq %rbp
+ subq $128,%rsp
+ andq $-16,%rsp
+ leaq -8(%rax),%rbp
+
+ cmpq $1,%rdx
+ je .Lctr32_one_shortcut
+
+ movdqu (%r8),%xmm2
+ movdqu (%rcx),%xmm0
+ movl 12(%r8),%r8d
+ pxor %xmm0,%xmm2
+ movl 12(%rcx),%r11d
+ movdqa %xmm2,0(%rsp)
+ bswapl %r8d
+ movdqa %xmm2,%xmm3
+ movdqa %xmm2,%xmm4
+ movdqa %xmm2,%xmm5
+ movdqa %xmm2,64(%rsp)
+ movdqa %xmm2,80(%rsp)
+ movdqa %xmm2,96(%rsp)
+ movq %rdx,%r10
+ movdqa %xmm2,112(%rsp)
+
+ leaq 1(%r8),%rax
+ leaq 2(%r8),%rdx
+ bswapl %eax
+ bswapl %edx
+ xorl %r11d,%eax
+ xorl %r11d,%edx
+.byte 102,15,58,34,216,3
+ leaq 3(%r8),%rax
+ movdqa %xmm3,16(%rsp)
+.byte 102,15,58,34,226,3
+ bswapl %eax
+ movq %r10,%rdx
+ leaq 4(%r8),%r10
+ movdqa %xmm4,32(%rsp)
+ xorl %r11d,%eax
+ bswapl %r10d
+.byte 102,15,58,34,232,3
+ xorl %r11d,%r10d
+ movdqa %xmm5,48(%rsp)
+ leaq 5(%r8),%r9
+ movl %r10d,64+12(%rsp)
+ bswapl %r9d
+ leaq 6(%r8),%r10
+ movl 240(%rcx),%eax
+ xorl %r11d,%r9d
+ bswapl %r10d
+ movl %r9d,80+12(%rsp)
+ xorl %r11d,%r10d
+ leaq 7(%r8),%r9
+ movl %r10d,96+12(%rsp)
+ bswapl %r9d
+ movl OPENSSL_ia32cap_P+4(%rip),%r10d
+ xorl %r11d,%r9d
+ andl $71303168,%r10d
+ movl %r9d,112+12(%rsp)
+
+ movups 16(%rcx),%xmm1
+
+ movdqa 64(%rsp),%xmm6
+ movdqa 80(%rsp),%xmm7
+
+ cmpq $8,%rdx
+ jb .Lctr32_tail
+
+ subq $6,%rdx
+ cmpl $4194304,%r10d
+ je .Lctr32_6x
+
+ leaq 128(%rcx),%rcx
+ subq $2,%rdx
+ jmp .Lctr32_loop8
+
+.align 16
+.Lctr32_6x:
+ shll $4,%eax
+ movl $48,%r10d
+ bswapl %r11d
+ leaq 32(%rcx,%rax,1),%rcx
+ subq %rax,%r10
+ jmp .Lctr32_loop6
+
+.align 16
+.Lctr32_loop6:
+ addl $6,%r8d
+ movups -48(%rcx,%r10,1),%xmm0
+.byte 102,15,56,220,209
+ movl %r8d,%eax
+ xorl %r11d,%eax
+.byte 102,15,56,220,217
+.byte 0x0f,0x38,0xf1,0x44,0x24,12
+ leal 1(%r8),%eax
+.byte 102,15,56,220,225
+ xorl %r11d,%eax
+.byte 0x0f,0x38,0xf1,0x44,0x24,28
+.byte 102,15,56,220,233
+ leal 2(%r8),%eax
+ xorl %r11d,%eax
+.byte 102,15,56,220,241
+.byte 0x0f,0x38,0xf1,0x44,0x24,44
+ leal 3(%r8),%eax
+.byte 102,15,56,220,249
+ movups -32(%rcx,%r10,1),%xmm1
+ xorl %r11d,%eax
+
+.byte 102,15,56,220,208
+.byte 0x0f,0x38,0xf1,0x44,0x24,60
+ leal 4(%r8),%eax
+.byte 102,15,56,220,216
+ xorl %r11d,%eax
+.byte 0x0f,0x38,0xf1,0x44,0x24,76
+.byte 102,15,56,220,224
+ leal 5(%r8),%eax
+ xorl %r11d,%eax
+.byte 102,15,56,220,232
+.byte 0x0f,0x38,0xf1,0x44,0x24,92
+ movq %r10,%rax
+.byte 102,15,56,220,240
+.byte 102,15,56,220,248
+ movups -16(%rcx,%r10,1),%xmm0
+
+ call .Lenc_loop6
+
+ movdqu (%rdi),%xmm8
+ movdqu 16(%rdi),%xmm9
+ movdqu 32(%rdi),%xmm10
+ movdqu 48(%rdi),%xmm11
+ movdqu 64(%rdi),%xmm12
+ movdqu 80(%rdi),%xmm13
+ leaq 96(%rdi),%rdi
+ movups -64(%rcx,%r10,1),%xmm1
+ pxor %xmm2,%xmm8
+ movaps 0(%rsp),%xmm2
+ pxor %xmm3,%xmm9
+ movaps 16(%rsp),%xmm3
+ pxor %xmm4,%xmm10
+ movaps 32(%rsp),%xmm4
+ pxor %xmm5,%xmm11
+ movaps 48(%rsp),%xmm5
+ pxor %xmm6,%xmm12
+ movaps 64(%rsp),%xmm6
+ pxor %xmm7,%xmm13
+ movaps 80(%rsp),%xmm7
+ movdqu %xmm8,(%rsi)
+ movdqu %xmm9,16(%rsi)
+ movdqu %xmm10,32(%rsi)
+ movdqu %xmm11,48(%rsi)
+ movdqu %xmm12,64(%rsi)
+ movdqu %xmm13,80(%rsi)
+ leaq 96(%rsi),%rsi
+
+ subq $6,%rdx
+ jnc .Lctr32_loop6
+
+ addq $6,%rdx
+ jz .Lctr32_done
+
+ leal -48(%r10),%eax
+ leaq -80(%rcx,%r10,1),%rcx
+ negl %eax
+ shrl $4,%eax
+ jmp .Lctr32_tail
+
+.align 32
+.Lctr32_loop8:
+ addl $8,%r8d
+ movdqa 96(%rsp),%xmm8
+.byte 102,15,56,220,209
+ movl %r8d,%r9d
+ movdqa 112(%rsp),%xmm9
+.byte 102,15,56,220,217
+ bswapl %r9d
+ movups 32-128(%rcx),%xmm0
+.byte 102,15,56,220,225
+ xorl %r11d,%r9d
+ nop
+.byte 102,15,56,220,233
+ movl %r9d,0+12(%rsp)
+ leaq 1(%r8),%r9
+.byte 102,15,56,220,241
+.byte 102,15,56,220,249
+.byte 102,68,15,56,220,193
+.byte 102,68,15,56,220,201
+ movups 48-128(%rcx),%xmm1
+ bswapl %r9d
+.byte 102,15,56,220,208
+.byte 102,15,56,220,216
+ xorl %r11d,%r9d
+.byte 0x66,0x90
+.byte 102,15,56,220,224
+.byte 102,15,56,220,232
+ movl %r9d,16+12(%rsp)
+ leaq 2(%r8),%r9
+.byte 102,15,56,220,240
+.byte 102,15,56,220,248
+.byte 102,68,15,56,220,192
+.byte 102,68,15,56,220,200
+ movups 64-128(%rcx),%xmm0
+ bswapl %r9d
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+ xorl %r11d,%r9d
+.byte 0x66,0x90
+.byte 102,15,56,220,225
+.byte 102,15,56,220,233
+ movl %r9d,32+12(%rsp)
+ leaq 3(%r8),%r9
+.byte 102,15,56,220,241
+.byte 102,15,56,220,249
+.byte 102,68,15,56,220,193
+.byte 102,68,15,56,220,201
+ movups 80-128(%rcx),%xmm1
+ bswapl %r9d
+.byte 102,15,56,220,208
+.byte 102,15,56,220,216
+ xorl %r11d,%r9d
+.byte 0x66,0x90
+.byte 102,15,56,220,224
+.byte 102,15,56,220,232
+ movl %r9d,48+12(%rsp)
+ leaq 4(%r8),%r9
+.byte 102,15,56,220,240
+.byte 102,15,56,220,248
+.byte 102,68,15,56,220,192
+.byte 102,68,15,56,220,200
+ movups 96-128(%rcx),%xmm0
+ bswapl %r9d
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+ xorl %r11d,%r9d
+.byte 0x66,0x90
+.byte 102,15,56,220,225
+.byte 102,15,56,220,233
+ movl %r9d,64+12(%rsp)
+ leaq 5(%r8),%r9
+.byte 102,15,56,220,241
+.byte 102,15,56,220,249
+.byte 102,68,15,56,220,193
+.byte 102,68,15,56,220,201
+ movups 112-128(%rcx),%xmm1
+ bswapl %r9d
+.byte 102,15,56,220,208
+.byte 102,15,56,220,216
+ xorl %r11d,%r9d
+.byte 0x66,0x90
+.byte 102,15,56,220,224
+.byte 102,15,56,220,232
+ movl %r9d,80+12(%rsp)
+ leaq 6(%r8),%r9
+.byte 102,15,56,220,240
+.byte 102,15,56,220,248
+.byte 102,68,15,56,220,192
+.byte 102,68,15,56,220,200
+ movups 128-128(%rcx),%xmm0
+ bswapl %r9d
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+ xorl %r11d,%r9d
+.byte 0x66,0x90
+.byte 102,15,56,220,225
+.byte 102,15,56,220,233
+ movl %r9d,96+12(%rsp)
+ leaq 7(%r8),%r9
+.byte 102,15,56,220,241
+.byte 102,15,56,220,249
+.byte 102,68,15,56,220,193
+.byte 102,68,15,56,220,201
+ movups 144-128(%rcx),%xmm1
+ bswapl %r9d
+.byte 102,15,56,220,208
+.byte 102,15,56,220,216
+.byte 102,15,56,220,224
+ xorl %r11d,%r9d
+ movdqu 0(%rdi),%xmm10
+.byte 102,15,56,220,232
+ movl %r9d,112+12(%rsp)
+ cmpl $11,%eax
+.byte 102,15,56,220,240
+.byte 102,15,56,220,248
+.byte 102,68,15,56,220,192
+.byte 102,68,15,56,220,200
+ movups 160-128(%rcx),%xmm0
+
+ jb .Lctr32_enc_done
+
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+.byte 102,15,56,220,225
+.byte 102,15,56,220,233
+.byte 102,15,56,220,241
+.byte 102,15,56,220,249
+.byte 102,68,15,56,220,193
+.byte 102,68,15,56,220,201
+ movups 176-128(%rcx),%xmm1
+
+.byte 102,15,56,220,208
+.byte 102,15,56,220,216
+.byte 102,15,56,220,224
+.byte 102,15,56,220,232
+.byte 102,15,56,220,240
+.byte 102,15,56,220,248
+.byte 102,68,15,56,220,192
+.byte 102,68,15,56,220,200
+ movups 192-128(%rcx),%xmm0
+ je .Lctr32_enc_done
+
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+.byte 102,15,56,220,225
+.byte 102,15,56,220,233
+.byte 102,15,56,220,241
+.byte 102,15,56,220,249
+.byte 102,68,15,56,220,193
+.byte 102,68,15,56,220,201
+ movups 208-128(%rcx),%xmm1
+
+.byte 102,15,56,220,208
+.byte 102,15,56,220,216
+.byte 102,15,56,220,224
+.byte 102,15,56,220,232
+.byte 102,15,56,220,240
+.byte 102,15,56,220,248
+.byte 102,68,15,56,220,192
+.byte 102,68,15,56,220,200
+ movups 224-128(%rcx),%xmm0
+ jmp .Lctr32_enc_done
+
+.align 16
+.Lctr32_enc_done:
+ movdqu 16(%rdi),%xmm11
+ pxor %xmm0,%xmm10
+ movdqu 32(%rdi),%xmm12
+ pxor %xmm0,%xmm11
+ movdqu 48(%rdi),%xmm13
+ pxor %xmm0,%xmm12
+ movdqu 64(%rdi),%xmm14
+ pxor %xmm0,%xmm13
+ movdqu 80(%rdi),%xmm15
+ pxor %xmm0,%xmm14
+ pxor %xmm0,%xmm15
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+.byte 102,15,56,220,225
+.byte 102,15,56,220,233
+.byte 102,15,56,220,241
+.byte 102,15,56,220,249
+.byte 102,68,15,56,220,193
+.byte 102,68,15,56,220,201
+ movdqu 96(%rdi),%xmm1
+ leaq 128(%rdi),%rdi
+
+.byte 102,65,15,56,221,210
+ pxor %xmm0,%xmm1
+ movdqu 112-128(%rdi),%xmm10
+.byte 102,65,15,56,221,219
+ pxor %xmm0,%xmm10
+ movdqa 0(%rsp),%xmm11
+.byte 102,65,15,56,221,228
+.byte 102,65,15,56,221,237
+ movdqa 16(%rsp),%xmm12
+ movdqa 32(%rsp),%xmm13
+.byte 102,65,15,56,221,246
+.byte 102,65,15,56,221,255
+ movdqa 48(%rsp),%xmm14
+ movdqa 64(%rsp),%xmm15
+.byte 102,68,15,56,221,193
+ movdqa 80(%rsp),%xmm0
+ movups 16-128(%rcx),%xmm1
+.byte 102,69,15,56,221,202
+
+ movups %xmm2,(%rsi)
+ movdqa %xmm11,%xmm2
+ movups %xmm3,16(%rsi)
+ movdqa %xmm12,%xmm3
+ movups %xmm4,32(%rsi)
+ movdqa %xmm13,%xmm4
+ movups %xmm5,48(%rsi)
+ movdqa %xmm14,%xmm5
+ movups %xmm6,64(%rsi)
+ movdqa %xmm15,%xmm6
+ movups %xmm7,80(%rsi)
+ movdqa %xmm0,%xmm7
+ movups %xmm8,96(%rsi)
+ movups %xmm9,112(%rsi)
+ leaq 128(%rsi),%rsi
+
+ subq $8,%rdx
+ jnc .Lctr32_loop8
+
+ addq $8,%rdx
+ jz .Lctr32_done
+ leaq -128(%rcx),%rcx
+
+.Lctr32_tail:
+ leaq 16(%rcx),%rcx
+ cmpq $4,%rdx
+ jb .Lctr32_loop3
+ je .Lctr32_loop4
+
+ shll $4,%eax
+ movdqa 96(%rsp),%xmm8
+ pxor %xmm9,%xmm9
+
+ movups 16(%rcx),%xmm0
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+ leaq 32-16(%rcx,%rax,1),%rcx
+ negq %rax
+.byte 102,15,56,220,225
+ addq $16,%rax
+ movups (%rdi),%xmm10
+.byte 102,15,56,220,233
+.byte 102,15,56,220,241
+ movups 16(%rdi),%xmm11
+ movups 32(%rdi),%xmm12
+.byte 102,15,56,220,249
+.byte 102,68,15,56,220,193
+
+ call .Lenc_loop8_enter
+
+ movdqu 48(%rdi),%xmm13
+ pxor %xmm10,%xmm2
+ movdqu 64(%rdi),%xmm10
+ pxor %xmm11,%xmm3
+ movdqu %xmm2,(%rsi)
+ pxor %xmm12,%xmm4
+ movdqu %xmm3,16(%rsi)
+ pxor %xmm13,%xmm5
+ movdqu %xmm4,32(%rsi)
+ pxor %xmm10,%xmm6
+ movdqu %xmm5,48(%rsi)
+ movdqu %xmm6,64(%rsi)
+ cmpq $6,%rdx
+ jb .Lctr32_done
+
+ movups 80(%rdi),%xmm11
+ xorps %xmm11,%xmm7
+ movups %xmm7,80(%rsi)
+ je .Lctr32_done
+
+ movups 96(%rdi),%xmm12
+ xorps %xmm12,%xmm8
+ movups %xmm8,96(%rsi)
+ jmp .Lctr32_done
+
+.align 32
+.Lctr32_loop4:
+.byte 102,15,56,220,209
+ leaq 16(%rcx),%rcx
+ decl %eax
+.byte 102,15,56,220,217
+.byte 102,15,56,220,225
+.byte 102,15,56,220,233
+ movups (%rcx),%xmm1
+ jnz .Lctr32_loop4
+.byte 102,15,56,221,209
+.byte 102,15,56,221,217
+ movups (%rdi),%xmm10
+ movups 16(%rdi),%xmm11
+.byte 102,15,56,221,225
+.byte 102,15,56,221,233
+ movups 32(%rdi),%xmm12
+ movups 48(%rdi),%xmm13
+
+ xorps %xmm10,%xmm2
+ movups %xmm2,(%rsi)
+ xorps %xmm11,%xmm3
+ movups %xmm3,16(%rsi)
+ pxor %xmm12,%xmm4
+ movdqu %xmm4,32(%rsi)
+ pxor %xmm13,%xmm5
+ movdqu %xmm5,48(%rsi)
+ jmp .Lctr32_done
+
+.align 32
+.Lctr32_loop3:
+.byte 102,15,56,220,209
+ leaq 16(%rcx),%rcx
+ decl %eax
+.byte 102,15,56,220,217
+.byte 102,15,56,220,225
+ movups (%rcx),%xmm1
+ jnz .Lctr32_loop3
+.byte 102,15,56,221,209
+.byte 102,15,56,221,217
+.byte 102,15,56,221,225
+
+ movups (%rdi),%xmm10
+ xorps %xmm10,%xmm2
+ movups %xmm2,(%rsi)
+ cmpq $2,%rdx
+ jb .Lctr32_done
+
+ movups 16(%rdi),%xmm11
+ xorps %xmm11,%xmm3
+ movups %xmm3,16(%rsi)
+ je .Lctr32_done
+
+ movups 32(%rdi),%xmm12
+ xorps %xmm12,%xmm4
+ movups %xmm4,32(%rsi)
+ jmp .Lctr32_done
+
+.align 16
+.Lctr32_one_shortcut:
+ movups (%r8),%xmm2
+ movups (%rdi),%xmm10
+ movl 240(%rcx),%eax
+ movups (%rcx),%xmm0
+ movups 16(%rcx),%xmm1
+ leaq 32(%rcx),%rcx
+ xorps %xmm0,%xmm2
+.Loop_enc1_7:
+.byte 102,15,56,220,209
+ decl %eax
+ movups (%rcx),%xmm1
+ leaq 16(%rcx),%rcx
+ jnz .Loop_enc1_7
+.byte 102,15,56,221,209
+ xorps %xmm10,%xmm2
+ movups %xmm2,(%rsi)
+ jmp .Lctr32_done
+
+.align 16
+.Lctr32_done:
+ leaq (%rbp),%rsp
+ popq %rbp
+.Lctr32_epilogue:
+ .byte 0xf3,0xc3
+.size aesni_ctr32_encrypt_blocks,.-aesni_ctr32_encrypt_blocks
+.globl aesni_xts_encrypt
+.hidden aesni_xts_encrypt
+.type aesni_xts_encrypt,@function
+.align 16
+aesni_xts_encrypt:
+ leaq (%rsp),%rax
+ pushq %rbp
+ subq $112,%rsp
+ andq $-16,%rsp
+ leaq -8(%rax),%rbp
+ movups (%r9),%xmm2
+ movl 240(%r8),%eax
+ movl 240(%rcx),%r10d
+ movups (%r8),%xmm0
+ movups 16(%r8),%xmm1
+ leaq 32(%r8),%r8
+ xorps %xmm0,%xmm2
+.Loop_enc1_8:
+.byte 102,15,56,220,209
+ decl %eax
+ movups (%r8),%xmm1
+ leaq 16(%r8),%r8
+ jnz .Loop_enc1_8
+.byte 102,15,56,221,209
+ movups (%rcx),%xmm0
+ movq %rcx,%r11
+ movl %r10d,%eax
+ shll $4,%r10d
+ movq %rdx,%r9
+ andq $-16,%rdx
+
+ movups 16(%rcx,%r10,1),%xmm1
+
+ movdqa .Lxts_magic(%rip),%xmm8
+ movdqa %xmm2,%xmm15
+ pshufd $95,%xmm2,%xmm9
+ pxor %xmm0,%xmm1
+ movdqa %xmm9,%xmm14
+ paddd %xmm9,%xmm9
+ movdqa %xmm15,%xmm10
+ psrad $31,%xmm14
+ paddq %xmm15,%xmm15
+ pand %xmm8,%xmm14
+ pxor %xmm0,%xmm10
+ pxor %xmm14,%xmm15
+ movdqa %xmm9,%xmm14
+ paddd %xmm9,%xmm9
+ movdqa %xmm15,%xmm11
+ psrad $31,%xmm14
+ paddq %xmm15,%xmm15
+ pand %xmm8,%xmm14
+ pxor %xmm0,%xmm11
+ pxor %xmm14,%xmm15
+ movdqa %xmm9,%xmm14
+ paddd %xmm9,%xmm9
+ movdqa %xmm15,%xmm12
+ psrad $31,%xmm14
+ paddq %xmm15,%xmm15
+ pand %xmm8,%xmm14
+ pxor %xmm0,%xmm12
+ pxor %xmm14,%xmm15
+ movdqa %xmm9,%xmm14
+ paddd %xmm9,%xmm9
+ movdqa %xmm15,%xmm13
+ psrad $31,%xmm14
+ paddq %xmm15,%xmm15
+ pand %xmm8,%xmm14
+ pxor %xmm0,%xmm13
+ pxor %xmm14,%xmm15
+ movdqa %xmm15,%xmm14
+ psrad $31,%xmm9
+ paddq %xmm15,%xmm15
+ pand %xmm8,%xmm9
+ pxor %xmm0,%xmm14
+ pxor %xmm9,%xmm15
+ movaps %xmm1,96(%rsp)
+
+ subq $96,%rdx
+ jc .Lxts_enc_short
+
+ movl $16+96,%eax
+ leaq 32(%r11,%r10,1),%rcx
+ subq %r10,%rax
+ movups 16(%r11),%xmm1
+ movq %rax,%r10
+ leaq .Lxts_magic(%rip),%r8
+ jmp .Lxts_enc_grandloop
+
+.align 32
+.Lxts_enc_grandloop:
+ movdqu 0(%rdi),%xmm2
+ movdqa %xmm0,%xmm8
+ movdqu 16(%rdi),%xmm3
+ pxor %xmm10,%xmm2
+ movdqu 32(%rdi),%xmm4
+ pxor %xmm11,%xmm3
+.byte 102,15,56,220,209
+ movdqu 48(%rdi),%xmm5
+ pxor %xmm12,%xmm4
+.byte 102,15,56,220,217
+ movdqu 64(%rdi),%xmm6
+ pxor %xmm13,%xmm5
+.byte 102,15,56,220,225
+ movdqu 80(%rdi),%xmm7
+ pxor %xmm15,%xmm8
+ movdqa 96(%rsp),%xmm9
+ pxor %xmm14,%xmm6
+.byte 102,15,56,220,233
+ movups 32(%r11),%xmm0
+ leaq 96(%rdi),%rdi
+ pxor %xmm8,%xmm7
+
+ pxor %xmm9,%xmm10
+.byte 102,15,56,220,241
+ pxor %xmm9,%xmm11
+ movdqa %xmm10,0(%rsp)
+.byte 102,15,56,220,249
+ movups 48(%r11),%xmm1
+ pxor %xmm9,%xmm12
+
+.byte 102,15,56,220,208
+ pxor %xmm9,%xmm13
+ movdqa %xmm11,16(%rsp)
+.byte 102,15,56,220,216
+ pxor %xmm9,%xmm14
+ movdqa %xmm12,32(%rsp)
+.byte 102,15,56,220,224
+.byte 102,15,56,220,232
+ pxor %xmm9,%xmm8
+ movdqa %xmm14,64(%rsp)
+.byte 102,15,56,220,240
+.byte 102,15,56,220,248
+ movups 64(%r11),%xmm0
+ movdqa %xmm8,80(%rsp)
+ pshufd $95,%xmm15,%xmm9
+ jmp .Lxts_enc_loop6
+.align 32
+.Lxts_enc_loop6:
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+.byte 102,15,56,220,225
+.byte 102,15,56,220,233
+.byte 102,15,56,220,241
+.byte 102,15,56,220,249
+ movups -64(%rcx,%rax,1),%xmm1
+ addq $32,%rax
+
+.byte 102,15,56,220,208
+.byte 102,15,56,220,216
+.byte 102,15,56,220,224
+.byte 102,15,56,220,232
+.byte 102,15,56,220,240
+.byte 102,15,56,220,248
+ movups -80(%rcx,%rax,1),%xmm0
+ jnz .Lxts_enc_loop6
+
+ movdqa (%r8),%xmm8
+ movdqa %xmm9,%xmm14
+ paddd %xmm9,%xmm9
+.byte 102,15,56,220,209
+ paddq %xmm15,%xmm15
+ psrad $31,%xmm14
+.byte 102,15,56,220,217
+ pand %xmm8,%xmm14
+ movups (%r11),%xmm10
+.byte 102,15,56,220,225
+.byte 102,15,56,220,233
+.byte 102,15,56,220,241
+ pxor %xmm14,%xmm15
+ movaps %xmm10,%xmm11
+.byte 102,15,56,220,249
+ movups -64(%rcx),%xmm1
+
+ movdqa %xmm9,%xmm14
+.byte 102,15,56,220,208
+ paddd %xmm9,%xmm9
+ pxor %xmm15,%xmm10
+.byte 102,15,56,220,216
+ psrad $31,%xmm14
+ paddq %xmm15,%xmm15
+.byte 102,15,56,220,224
+.byte 102,15,56,220,232
+ pand %xmm8,%xmm14
+ movaps %xmm11,%xmm12
+.byte 102,15,56,220,240
+ pxor %xmm14,%xmm15
+ movdqa %xmm9,%xmm14
+.byte 102,15,56,220,248
+ movups -48(%rcx),%xmm0
+
+ paddd %xmm9,%xmm9
+.byte 102,15,56,220,209
+ pxor %xmm15,%xmm11
+ psrad $31,%xmm14
+.byte 102,15,56,220,217
+ paddq %xmm15,%xmm15
+ pand %xmm8,%xmm14
+.byte 102,15,56,220,225
+.byte 102,15,56,220,233
+ movdqa %xmm13,48(%rsp)
+ pxor %xmm14,%xmm15
+.byte 102,15,56,220,241
+ movaps %xmm12,%xmm13
+ movdqa %xmm9,%xmm14
+.byte 102,15,56,220,249
+ movups -32(%rcx),%xmm1
+
+ paddd %xmm9,%xmm9
+.byte 102,15,56,220,208
+ pxor %xmm15,%xmm12
+ psrad $31,%xmm14
+.byte 102,15,56,220,216
+ paddq %xmm15,%xmm15
+ pand %xmm8,%xmm14
+.byte 102,15,56,220,224
+.byte 102,15,56,220,232
+.byte 102,15,56,220,240
+ pxor %xmm14,%xmm15
+ movaps %xmm13,%xmm14
+.byte 102,15,56,220,248
+
+ movdqa %xmm9,%xmm0
+ paddd %xmm9,%xmm9
+.byte 102,15,56,220,209
+ pxor %xmm15,%xmm13
+ psrad $31,%xmm0
+.byte 102,15,56,220,217
+ paddq %xmm15,%xmm15
+ pand %xmm8,%xmm0
+.byte 102,15,56,220,225
+.byte 102,15,56,220,233
+ pxor %xmm0,%xmm15
+ movups (%r11),%xmm0
+.byte 102,15,56,220,241
+.byte 102,15,56,220,249
+ movups 16(%r11),%xmm1
+
+ pxor %xmm15,%xmm14
+.byte 102,15,56,221,84,36,0
+ psrad $31,%xmm9
+ paddq %xmm15,%xmm15
+.byte 102,15,56,221,92,36,16
+.byte 102,15,56,221,100,36,32
+ pand %xmm8,%xmm9
+ movq %r10,%rax
+.byte 102,15,56,221,108,36,48
+.byte 102,15,56,221,116,36,64
+.byte 102,15,56,221,124,36,80
+ pxor %xmm9,%xmm15
+
+ leaq 96(%rsi),%rsi
+ movups %xmm2,-96(%rsi)
+ movups %xmm3,-80(%rsi)
+ movups %xmm4,-64(%rsi)
+ movups %xmm5,-48(%rsi)
+ movups %xmm6,-32(%rsi)
+ movups %xmm7,-16(%rsi)
+ subq $96,%rdx
+ jnc .Lxts_enc_grandloop
+
+ movl $16+96,%eax
+ subl %r10d,%eax
+ movq %r11,%rcx
+ shrl $4,%eax
+
+.Lxts_enc_short:
+ movl %eax,%r10d
+ pxor %xmm0,%xmm10
+ addq $96,%rdx
+ jz .Lxts_enc_done
+
+ pxor %xmm0,%xmm11
+ cmpq $32,%rdx
+ jb .Lxts_enc_one
+ pxor %xmm0,%xmm12
+ je .Lxts_enc_two
+
+ pxor %xmm0,%xmm13
+ cmpq $64,%rdx
+ jb .Lxts_enc_three
+ pxor %xmm0,%xmm14
+ je .Lxts_enc_four
+
+ movdqu (%rdi),%xmm2
+ movdqu 16(%rdi),%xmm3
+ 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:
+.byte 102,15,56,220,209
+ decl %eax
+ movups (%rcx),%xmm1
+ leaq 16(%rcx),%rcx
+ jnz .Loop_enc1_9
+.byte 102,15,56,221,209
+ 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_encrypt2
+
+ 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
+
+ pxor %xmm10,%xmm2
+ movdqa %xmm14,%xmm10
+ pxor %xmm11,%xmm3
+ pxor %xmm12,%xmm4
+ movdqu %xmm2,(%rsi)
+ pxor %xmm13,%xmm5
+ movdqu %xmm3,16(%rsi)
+ movdqu %xmm4,32(%rsi)
+ movdqu %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:
+.byte 102,15,56,220,209
+ decl %eax
+ movups (%rcx),%xmm1
+ leaq 16(%rcx),%rcx
+ jnz .Loop_enc1_10
+.byte 102,15,56,221,209
+ xorps %xmm10,%xmm2
+ movups %xmm2,-16(%rsi)
+
+.Lxts_enc_ret:
+ leaq (%rbp),%rsp
+ popq %rbp
+.Lxts_enc_epilogue:
+ .byte 0xf3,0xc3
+.size aesni_xts_encrypt,.-aesni_xts_encrypt
+.globl aesni_xts_decrypt
+.hidden aesni_xts_decrypt
+.type aesni_xts_decrypt,@function
+.align 16
+aesni_xts_decrypt:
+ leaq (%rsp),%rax
+ pushq %rbp
+ subq $112,%rsp
+ andq $-16,%rsp
+ leaq -8(%rax),%rbp
+ movups (%r9),%xmm2
+ movl 240(%r8),%eax
+ movl 240(%rcx),%r10d
+ movups (%r8),%xmm0
+ movups 16(%r8),%xmm1
+ leaq 32(%r8),%r8
+ xorps %xmm0,%xmm2
+.Loop_enc1_11:
+.byte 102,15,56,220,209
+ decl %eax
+ movups (%r8),%xmm1
+ leaq 16(%r8),%r8
+ jnz .Loop_enc1_11
+.byte 102,15,56,221,209
+ xorl %eax,%eax
+ testq $15,%rdx
+ setnz %al
+ shlq $4,%rax
+ subq %rax,%rdx
+
+ movups (%rcx),%xmm0
+ movq %rcx,%r11
+ movl %r10d,%eax
+ shll $4,%r10d
+ movq %rdx,%r9
+ andq $-16,%rdx
+
+ movups 16(%rcx,%r10,1),%xmm1
+
+ movdqa .Lxts_magic(%rip),%xmm8
+ movdqa %xmm2,%xmm15
+ pshufd $95,%xmm2,%xmm9
+ pxor %xmm0,%xmm1
+ movdqa %xmm9,%xmm14
+ paddd %xmm9,%xmm9
+ movdqa %xmm15,%xmm10
+ psrad $31,%xmm14
+ paddq %xmm15,%xmm15
+ pand %xmm8,%xmm14
+ pxor %xmm0,%xmm10
+ pxor %xmm14,%xmm15
+ movdqa %xmm9,%xmm14
+ paddd %xmm9,%xmm9
+ movdqa %xmm15,%xmm11
+ psrad $31,%xmm14
+ paddq %xmm15,%xmm15
+ pand %xmm8,%xmm14
+ pxor %xmm0,%xmm11
+ pxor %xmm14,%xmm15
+ movdqa %xmm9,%xmm14
+ paddd %xmm9,%xmm9
+ movdqa %xmm15,%xmm12
+ psrad $31,%xmm14
+ paddq %xmm15,%xmm15
+ pand %xmm8,%xmm14
+ pxor %xmm0,%xmm12
+ pxor %xmm14,%xmm15
+ movdqa %xmm9,%xmm14
+ paddd %xmm9,%xmm9
+ movdqa %xmm15,%xmm13
+ psrad $31,%xmm14
+ paddq %xmm15,%xmm15
+ pand %xmm8,%xmm14
+ pxor %xmm0,%xmm13
+ pxor %xmm14,%xmm15
+ movdqa %xmm15,%xmm14
+ psrad $31,%xmm9
+ paddq %xmm15,%xmm15
+ pand %xmm8,%xmm9
+ pxor %xmm0,%xmm14
+ pxor %xmm9,%xmm15
+ movaps %xmm1,96(%rsp)
+
+ subq $96,%rdx
+ jc .Lxts_dec_short
+
+ movl $16+96,%eax
+ leaq 32(%r11,%r10,1),%rcx
+ subq %r10,%rax
+ movups 16(%r11),%xmm1
+ movq %rax,%r10
+ leaq .Lxts_magic(%rip),%r8
+ jmp .Lxts_dec_grandloop
+
+.align 32
+.Lxts_dec_grandloop:
+ movdqu 0(%rdi),%xmm2
+ movdqa %xmm0,%xmm8
+ movdqu 16(%rdi),%xmm3
+ pxor %xmm10,%xmm2
+ movdqu 32(%rdi),%xmm4
+ pxor %xmm11,%xmm3
+.byte 102,15,56,222,209
+ movdqu 48(%rdi),%xmm5
+ pxor %xmm12,%xmm4
+.byte 102,15,56,222,217
+ movdqu 64(%rdi),%xmm6
+ pxor %xmm13,%xmm5
+.byte 102,15,56,222,225
+ movdqu 80(%rdi),%xmm7
+ pxor %xmm15,%xmm8
+ movdqa 96(%rsp),%xmm9
+ pxor %xmm14,%xmm6
+.byte 102,15,56,222,233
+ movups 32(%r11),%xmm0
+ leaq 96(%rdi),%rdi
+ pxor %xmm8,%xmm7
+
+ pxor %xmm9,%xmm10
+.byte 102,15,56,222,241
+ pxor %xmm9,%xmm11
+ movdqa %xmm10,0(%rsp)
+.byte 102,15,56,222,249
+ movups 48(%r11),%xmm1
+ pxor %xmm9,%xmm12
+
+.byte 102,15,56,222,208
+ pxor %xmm9,%xmm13
+ movdqa %xmm11,16(%rsp)
+.byte 102,15,56,222,216
+ pxor %xmm9,%xmm14
+ movdqa %xmm12,32(%rsp)
+.byte 102,15,56,222,224
+.byte 102,15,56,222,232
+ pxor %xmm9,%xmm8
+ movdqa %xmm14,64(%rsp)
+.byte 102,15,56,222,240
+.byte 102,15,56,222,248
+ movups 64(%r11),%xmm0
+ movdqa %xmm8,80(%rsp)
+ pshufd $95,%xmm15,%xmm9
+ jmp .Lxts_dec_loop6
+.align 32
+.Lxts_dec_loop6:
+.byte 102,15,56,222,209
+.byte 102,15,56,222,217
+.byte 102,15,56,222,225
+.byte 102,15,56,222,233
+.byte 102,15,56,222,241
+.byte 102,15,56,222,249
+ movups -64(%rcx,%rax,1),%xmm1
+ addq $32,%rax
+
+.byte 102,15,56,222,208
+.byte 102,15,56,222,216
+.byte 102,15,56,222,224
+.byte 102,15,56,222,232
+.byte 102,15,56,222,240
+.byte 102,15,56,222,248
+ movups -80(%rcx,%rax,1),%xmm0
+ jnz .Lxts_dec_loop6
+
+ movdqa (%r8),%xmm8
+ movdqa %xmm9,%xmm14
+ paddd %xmm9,%xmm9
+.byte 102,15,56,222,209
+ paddq %xmm15,%xmm15
+ psrad $31,%xmm14
+.byte 102,15,56,222,217
+ pand %xmm8,%xmm14
+ movups (%r11),%xmm10
+.byte 102,15,56,222,225
+.byte 102,15,56,222,233
+.byte 102,15,56,222,241
+ pxor %xmm14,%xmm15
+ movaps %xmm10,%xmm11
+.byte 102,15,56,222,249
+ movups -64(%rcx),%xmm1
+
+ movdqa %xmm9,%xmm14
+.byte 102,15,56,222,208
+ paddd %xmm9,%xmm9
+ pxor %xmm15,%xmm10
+.byte 102,15,56,222,216
+ psrad $31,%xmm14
+ paddq %xmm15,%xmm15
+.byte 102,15,56,222,224
+.byte 102,15,56,222,232
+ pand %xmm8,%xmm14
+ movaps %xmm11,%xmm12
+.byte 102,15,56,222,240
+ pxor %xmm14,%xmm15
+ movdqa %xmm9,%xmm14
+.byte 102,15,56,222,248
+ movups -48(%rcx),%xmm0
+
+ paddd %xmm9,%xmm9
+.byte 102,15,56,222,209
+ pxor %xmm15,%xmm11
+ psrad $31,%xmm14
+.byte 102,15,56,222,217
+ paddq %xmm15,%xmm15
+ pand %xmm8,%xmm14
+.byte 102,15,56,222,225
+.byte 102,15,56,222,233
+ movdqa %xmm13,48(%rsp)
+ pxor %xmm14,%xmm15
+.byte 102,15,56,222,241
+ movaps %xmm12,%xmm13
+ movdqa %xmm9,%xmm14
+.byte 102,15,56,222,249
+ movups -32(%rcx),%xmm1
+
+ paddd %xmm9,%xmm9
+.byte 102,15,56,222,208
+ pxor %xmm15,%xmm12
+ psrad $31,%xmm14
+.byte 102,15,56,222,216
+ paddq %xmm15,%xmm15
+ pand %xmm8,%xmm14
+.byte 102,15,56,222,224
+.byte 102,15,56,222,232
+.byte 102,15,56,222,240
+ pxor %xmm14,%xmm15
+ movaps %xmm13,%xmm14
+.byte 102,15,56,222,248
+
+ movdqa %xmm9,%xmm0
+ paddd %xmm9,%xmm9
+.byte 102,15,56,222,209
+ pxor %xmm15,%xmm13
+ psrad $31,%xmm0
+.byte 102,15,56,222,217
+ paddq %xmm15,%xmm15
+ pand %xmm8,%xmm0
+.byte 102,15,56,222,225
+.byte 102,15,56,222,233
+ pxor %xmm0,%xmm15
+ movups (%r11),%xmm0
+.byte 102,15,56,222,241
+.byte 102,15,56,222,249
+ movups 16(%r11),%xmm1
+
+ pxor %xmm15,%xmm14
+.byte 102,15,56,223,84,36,0
+ psrad $31,%xmm9
+ paddq %xmm15,%xmm15
+.byte 102,15,56,223,92,36,16
+.byte 102,15,56,223,100,36,32
+ pand %xmm8,%xmm9
+ movq %r10,%rax
+.byte 102,15,56,223,108,36,48
+.byte 102,15,56,223,116,36,64
+.byte 102,15,56,223,124,36,80
+ pxor %xmm9,%xmm15
+
+ leaq 96(%rsi),%rsi
+ movups %xmm2,-96(%rsi)
+ movups %xmm3,-80(%rsi)
+ movups %xmm4,-64(%rsi)
+ movups %xmm5,-48(%rsi)
+ movups %xmm6,-32(%rsi)
+ movups %xmm7,-16(%rsi)
+ subq $96,%rdx
+ jnc .Lxts_dec_grandloop
+
+ movl $16+96,%eax
+ subl %r10d,%eax
+ movq %r11,%rcx
+ shrl $4,%eax
+
+.Lxts_dec_short:
+ movl %eax,%r10d
+ pxor %xmm0,%xmm10
+ pxor %xmm0,%xmm11
+ addq $96,%rdx
+ jz .Lxts_dec_done
+
+ pxor %xmm0,%xmm12
+ cmpq $32,%rdx
+ jb .Lxts_dec_one
+ pxor %xmm0,%xmm13
+ je .Lxts_dec_two
+
+ pxor %xmm0,%xmm14
+ cmpq $64,%rdx
+ jb .Lxts_dec_three
+ je .Lxts_dec_four
+
+ movdqu (%rdi),%xmm2
+ movdqu 16(%rdi),%xmm3
+ 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:
+.byte 102,15,56,222,209
+ decl %eax
+ movups (%rcx),%xmm1
+ leaq 16(%rcx),%rcx
+ jnz .Loop_dec1_12
+.byte 102,15,56,223,209
+ 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_decrypt2
+
+ 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 %xmm14,%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:
+ 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_decrypt4
+
+ pxor %xmm10,%xmm2
+ movdqa %xmm14,%xmm10
+ pxor %xmm11,%xmm3
+ movdqa %xmm15,%xmm11
+ pxor %xmm12,%xmm4
+ movdqu %xmm2,(%rsi)
+ pxor %xmm13,%xmm5
+ movdqu %xmm3,16(%rsi)
+ movdqu %xmm4,32(%rsi)
+ movdqu %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:
+.byte 102,15,56,222,209
+ decl %eax
+ movups (%rcx),%xmm1
+ leaq 16(%rcx),%rcx
+ jnz .Loop_dec1_13
+.byte 102,15,56,223,209
+ 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:
+.byte 102,15,56,222,209
+ decl %eax
+ movups (%rcx),%xmm1
+ leaq 16(%rcx),%rcx
+ jnz .Loop_dec1_14
+.byte 102,15,56,223,209
+ xorps %xmm10,%xmm2
+ movups %xmm2,(%rsi)
+
+.Lxts_dec_ret:
+ leaq (%rbp),%rsp
+ popq %rbp
+.Lxts_dec_epilogue:
+ .byte 0xf3,0xc3
+.size aesni_xts_decrypt,.-aesni_xts_decrypt
+.globl aesni_cbc_encrypt
+.hidden 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:
+.byte 102,15,56,220,209
+ decl %eax
+ movups (%rcx),%xmm1
+ leaq 16(%rcx),%rcx
+ jnz .Loop_enc1_15
+.byte 102,15,56,221,209
+ 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
+ andq $-16,%rsp
+ leaq -8(%rax),%rbp
+ movups (%r8),%xmm10
+ movl %r10d,%eax
+ cmpq $80,%rdx
+ jbe .Lcbc_dec_tail
+
+ movups (%rcx),%xmm0
+ movdqu 0(%rdi),%xmm2
+ movdqu 16(%rdi),%xmm3
+ movdqa %xmm2,%xmm11
+ movdqu 32(%rdi),%xmm4
+ movdqa %xmm3,%xmm12
+ movdqu 48(%rdi),%xmm5
+ movdqa %xmm4,%xmm13
+ movdqu 64(%rdi),%xmm6
+ movdqa %xmm5,%xmm14
+ movdqu 80(%rdi),%xmm7
+ movdqa %xmm6,%xmm15
+ movl OPENSSL_ia32cap_P+4(%rip),%r9d
+ cmpq $112,%rdx
+ jbe .Lcbc_dec_six_or_seven
+
+ andl $71303168,%r9d
+ subq $80,%rdx
+ cmpl $4194304,%r9d
+ je .Lcbc_dec_loop6_enter
+ subq $32,%rdx
+ leaq 112(%rcx),%rcx
+ jmp .Lcbc_dec_loop8_enter
+.align 16
+.Lcbc_dec_loop8:
+ movups %xmm9,(%rsi)
+ leaq 16(%rsi),%rsi
+.Lcbc_dec_loop8_enter:
+ movdqu 96(%rdi),%xmm8
+ pxor %xmm0,%xmm2
+ movdqu 112(%rdi),%xmm9
+ pxor %xmm0,%xmm3
+ movups 16-112(%rcx),%xmm1
+ pxor %xmm0,%xmm4
+ xorq %r11,%r11
+ cmpq $112,%rdx
+ pxor %xmm0,%xmm5
+ pxor %xmm0,%xmm6
+ pxor %xmm0,%xmm7
+ pxor %xmm0,%xmm8
+
+.byte 102,15,56,222,209
+ pxor %xmm0,%xmm9
+ movups 32-112(%rcx),%xmm0
+.byte 102,15,56,222,217
+.byte 102,15,56,222,225
+.byte 102,15,56,222,233
+.byte 102,15,56,222,241
+.byte 102,15,56,222,249
+.byte 102,68,15,56,222,193
+ setnc %r11b
+ shlq $7,%r11
+.byte 102,68,15,56,222,201
+ addq %rdi,%r11
+ movups 48-112(%rcx),%xmm1
+.byte 102,15,56,222,208
+.byte 102,15,56,222,216
+.byte 102,15,56,222,224
+.byte 102,15,56,222,232
+.byte 102,15,56,222,240
+.byte 102,15,56,222,248
+.byte 102,68,15,56,222,192
+.byte 102,68,15,56,222,200
+ movups 64-112(%rcx),%xmm0
+ nop
+.byte 102,15,56,222,209
+.byte 102,15,56,222,217
+.byte 102,15,56,222,225
+.byte 102,15,56,222,233
+.byte 102,15,56,222,241
+.byte 102,15,56,222,249
+.byte 102,68,15,56,222,193
+.byte 102,68,15,56,222,201
+ movups 80-112(%rcx),%xmm1
+ nop
+.byte 102,15,56,222,208
+.byte 102,15,56,222,216
+.byte 102,15,56,222,224
+.byte 102,15,56,222,232
+.byte 102,15,56,222,240
+.byte 102,15,56,222,248
+.byte 102,68,15,56,222,192
+.byte 102,68,15,56,222,200
+ movups 96-112(%rcx),%xmm0
+ nop
+.byte 102,15,56,222,209
+.byte 102,15,56,222,217
+.byte 102,15,56,222,225
+.byte 102,15,56,222,233
+.byte 102,15,56,222,241
+.byte 102,15,56,222,249
+.byte 102,68,15,56,222,193
+.byte 102,68,15,56,222,201
+ movups 112-112(%rcx),%xmm1
+ nop
+.byte 102,15,56,222,208
+.byte 102,15,56,222,216
+.byte 102,15,56,222,224
+.byte 102,15,56,222,232
+.byte 102,15,56,222,240
+.byte 102,15,56,222,248
+.byte 102,68,15,56,222,192
+.byte 102,68,15,56,222,200
+ movups 128-112(%rcx),%xmm0
+ nop
+.byte 102,15,56,222,209
+.byte 102,15,56,222,217
+.byte 102,15,56,222,225
+.byte 102,15,56,222,233
+.byte 102,15,56,222,241
+.byte 102,15,56,222,249
+.byte 102,68,15,56,222,193
+.byte 102,68,15,56,222,201
+ movups 144-112(%rcx),%xmm1
+ cmpl $11,%eax
+.byte 102,15,56,222,208
+.byte 102,15,56,222,216
+.byte 102,15,56,222,224
+.byte 102,15,56,222,232
+.byte 102,15,56,222,240
+.byte 102,15,56,222,248
+.byte 102,68,15,56,222,192
+.byte 102,68,15,56,222,200
+ movups 160-112(%rcx),%xmm0
+ jb .Lcbc_dec_done
+.byte 102,15,56,222,209
+.byte 102,15,56,222,217
+.byte 102,15,56,222,225
+.byte 102,15,56,222,233
+.byte 102,15,56,222,241
+.byte 102,15,56,222,249
+.byte 102,68,15,56,222,193
+.byte 102,68,15,56,222,201
+ movups 176-112(%rcx),%xmm1
+ nop
+.byte 102,15,56,222,208
+.byte 102,15,56,222,216
+.byte 102,15,56,222,224
+.byte 102,15,56,222,232
+.byte 102,15,56,222,240
+.byte 102,15,56,222,248
+.byte 102,68,15,56,222,192
+.byte 102,68,15,56,222,200
+ movups 192-112(%rcx),%xmm0
+ je .Lcbc_dec_done
+.byte 102,15,56,222,209
+.byte 102,15,56,222,217
+.byte 102,15,56,222,225
+.byte 102,15,56,222,233
+.byte 102,15,56,222,241
+.byte 102,15,56,222,249
+.byte 102,68,15,56,222,193
+.byte 102,68,15,56,222,201
+ movups 208-112(%rcx),%xmm1
+ nop
+.byte 102,15,56,222,208
+.byte 102,15,56,222,216
+.byte 102,15,56,222,224
+.byte 102,15,56,222,232
+.byte 102,15,56,222,240
+.byte 102,15,56,222,248
+.byte 102,68,15,56,222,192
+.byte 102,68,15,56,222,200
+ movups 224-112(%rcx),%xmm0
+ jmp .Lcbc_dec_done
+.align 16
+.Lcbc_dec_done:
+.byte 102,15,56,222,209
+.byte 102,15,56,222,217
+ pxor %xmm0,%xmm10
+ pxor %xmm0,%xmm11
+.byte 102,15,56,222,225
+.byte 102,15,56,222,233
+ pxor %xmm0,%xmm12
+ pxor %xmm0,%xmm13
+.byte 102,15,56,222,241
+.byte 102,15,56,222,249
+ pxor %xmm0,%xmm14
+ pxor %xmm0,%xmm15
+.byte 102,68,15,56,222,193
+.byte 102,68,15,56,222,201
+ movdqu 80(%rdi),%xmm1
+
+.byte 102,65,15,56,223,210
+ movdqu 96(%rdi),%xmm10
+ pxor %xmm0,%xmm1
+.byte 102,65,15,56,223,219
+ pxor %xmm0,%xmm10
+ movdqu 112(%rdi),%xmm0
+.byte 102,65,15,56,223,228
+ leaq 128(%rdi),%rdi
+ movdqu 0(%r11),%xmm11
+.byte 102,65,15,56,223,237
+.byte 102,65,15,56,223,246
+ movdqu 16(%r11),%xmm12
+ movdqu 32(%r11),%xmm13
+.byte 102,65,15,56,223,255
+.byte 102,68,15,56,223,193
+ movdqu 48(%r11),%xmm14
+ movdqu 64(%r11),%xmm15
+.byte 102,69,15,56,223,202
+ movdqa %xmm0,%xmm10
+ movdqu 80(%r11),%xmm1
+ movups -112(%rcx),%xmm0
+
+ movups %xmm2,(%rsi)
+ movdqa %xmm11,%xmm2
+ movups %xmm3,16(%rsi)
+ movdqa %xmm12,%xmm3
+ movups %xmm4,32(%rsi)
+ movdqa %xmm13,%xmm4
+ movups %xmm5,48(%rsi)
+ movdqa %xmm14,%xmm5
+ movups %xmm6,64(%rsi)
+ movdqa %xmm15,%xmm6
+ movups %xmm7,80(%rsi)
+ movdqa %xmm1,%xmm7
+ movups %xmm8,96(%rsi)
+ leaq 112(%rsi),%rsi
+
+ subq $128,%rdx
+ ja .Lcbc_dec_loop8
+
+ movaps %xmm9,%xmm2
+ leaq -112(%rcx),%rcx
+ addq $112,%rdx
+ jle .Lcbc_dec_tail_collected
+ movups %xmm9,(%rsi)
+ leaq 16(%rsi),%rsi
+ cmpq $80,%rdx
+ jbe .Lcbc_dec_tail
+
+ movaps %xmm11,%xmm2
+.Lcbc_dec_six_or_seven:
+ cmpq $96,%rdx
+ ja .Lcbc_dec_seven
+
+ movaps %xmm7,%xmm8
+ call _aesni_decrypt6
+ pxor %xmm10,%xmm2
+ movaps %xmm8,%xmm10
+ pxor %xmm11,%xmm3
+ movdqu %xmm2,(%rsi)
+ pxor %xmm12,%xmm4
+ movdqu %xmm3,16(%rsi)
+ pxor %xmm13,%xmm5
+ movdqu %xmm4,32(%rsi)
+ pxor %xmm14,%xmm6
+ movdqu %xmm5,48(%rsi)
+ pxor %xmm15,%xmm7
+ movdqu %xmm6,64(%rsi)
+ leaq 80(%rsi),%rsi
+ movdqa %xmm7,%xmm2
+ jmp .Lcbc_dec_tail_collected
+
+.align 16
+.Lcbc_dec_seven:
+ movups 96(%rdi),%xmm8
+ xorps %xmm9,%xmm9
+ call _aesni_decrypt8
+ movups 80(%rdi),%xmm9
+ pxor %xmm10,%xmm2
+ movups 96(%rdi),%xmm10
+ pxor %xmm11,%xmm3
+ movdqu %xmm2,(%rsi)
+ pxor %xmm12,%xmm4
+ movdqu %xmm3,16(%rsi)
+ pxor %xmm13,%xmm5
+ movdqu %xmm4,32(%rsi)
+ pxor %xmm14,%xmm6
+ movdqu %xmm5,48(%rsi)
+ pxor %xmm15,%xmm7
+ movdqu %xmm6,64(%rsi)
+ pxor %xmm9,%xmm8
+ movdqu %xmm7,80(%rsi)
+ leaq 96(%rsi),%rsi
+ movdqa %xmm8,%xmm2
+ jmp .Lcbc_dec_tail_collected
+
+.align 16
+.Lcbc_dec_loop6:
+ movups %xmm7,(%rsi)
+ leaq 16(%rsi),%rsi
+ movdqu 0(%rdi),%xmm2
+ movdqu 16(%rdi),%xmm3
+ movdqa %xmm2,%xmm11
+ movdqu 32(%rdi),%xmm4
+ movdqa %xmm3,%xmm12
+ movdqu 48(%rdi),%xmm5
+ movdqa %xmm4,%xmm13
+ movdqu 64(%rdi),%xmm6
+ movdqa %xmm5,%xmm14
+ movdqu 80(%rdi),%xmm7
+ movdqa %xmm6,%xmm15
+.Lcbc_dec_loop6_enter:
+ leaq 96(%rdi),%rdi
+ movdqa %xmm7,%xmm8
+
+ call _aesni_decrypt6
+
+ pxor %xmm10,%xmm2
+ movdqa %xmm8,%xmm10
+ pxor %xmm11,%xmm3
+ movdqu %xmm2,(%rsi)
+ pxor %xmm12,%xmm4
+ movdqu %xmm3,16(%rsi)
+ pxor %xmm13,%xmm5
+ movdqu %xmm4,32(%rsi)
+ pxor %xmm14,%xmm6
+ movq %r11,%rcx
+ movdqu %xmm5,48(%rsi)
+ pxor %xmm15,%xmm7
+ movl %r10d,%eax
+ movdqu %xmm6,64(%rsi)
+ leaq 80(%rsi),%rsi
+ subq $96,%rdx
+ ja .Lcbc_dec_loop6
+
+ movdqa %xmm7,%xmm2
+ addq $80,%rdx
+ jle .Lcbc_dec_tail_collected
+ movups %xmm7,(%rsi)
+ leaq 16(%rsi),%rsi
+
+.Lcbc_dec_tail:
+ movups (%rdi),%xmm2
+ subq $16,%rdx
+ jbe .Lcbc_dec_one
+
+ movups 16(%rdi),%xmm3
+ movaps %xmm2,%xmm11
+ subq $16,%rdx
+ jbe .Lcbc_dec_two
+
+ movups 32(%rdi),%xmm4
+ movaps %xmm3,%xmm12
+ subq $16,%rdx
+ jbe .Lcbc_dec_three
+
+ movups 48(%rdi),%xmm5
+ movaps %xmm4,%xmm13
+ subq $16,%rdx
+ jbe .Lcbc_dec_four
+
+ movups 64(%rdi),%xmm6
+ movaps %xmm5,%xmm14
+ movaps %xmm6,%xmm15
+ xorps %xmm7,%xmm7
+ call _aesni_decrypt6
+ pxor %xmm10,%xmm2
+ movaps %xmm15,%xmm10
+ pxor %xmm11,%xmm3
+ movdqu %xmm2,(%rsi)
+ pxor %xmm12,%xmm4
+ movdqu %xmm3,16(%rsi)
+ pxor %xmm13,%xmm5
+ movdqu %xmm4,32(%rsi)
+ pxor %xmm14,%xmm6
+ movdqu %xmm5,48(%rsi)
+ leaq 64(%rsi),%rsi
+ movdqa %xmm6,%xmm2
+ subq $16,%rdx
+ jmp .Lcbc_dec_tail_collected
+
+.align 16
+.Lcbc_dec_one:
+ movaps %xmm2,%xmm11
+ movups (%rcx),%xmm0
+ movups 16(%rcx),%xmm1
+ leaq 32(%rcx),%rcx
+ xorps %xmm0,%xmm2
+.Loop_dec1_16:
+.byte 102,15,56,222,209
+ decl %eax
+ movups (%rcx),%xmm1
+ leaq 16(%rcx),%rcx
+ jnz .Loop_dec1_16
+.byte 102,15,56,223,209
+ xorps %xmm10,%xmm2
+ movaps %xmm11,%xmm10
+ jmp .Lcbc_dec_tail_collected
+.align 16
+.Lcbc_dec_two:
+ movaps %xmm3,%xmm12
+ call _aesni_decrypt2
+ pxor %xmm10,%xmm2
+ movaps %xmm12,%xmm10
+ pxor %xmm11,%xmm3
+ movdqu %xmm2,(%rsi)
+ movdqa %xmm3,%xmm2
+ leaq 16(%rsi),%rsi
+ jmp .Lcbc_dec_tail_collected
+.align 16
+.Lcbc_dec_three:
+ movaps %xmm4,%xmm13
+ call _aesni_decrypt3
+ pxor %xmm10,%xmm2
+ movaps %xmm13,%xmm10
+ pxor %xmm11,%xmm3
+ movdqu %xmm2,(%rsi)
+ pxor %xmm12,%xmm4
+ movdqu %xmm3,16(%rsi)
+ movdqa %xmm4,%xmm2
+ leaq 32(%rsi),%rsi
+ jmp .Lcbc_dec_tail_collected
+.align 16
+.Lcbc_dec_four:
+ movaps %xmm5,%xmm14
+ call _aesni_decrypt4
+ pxor %xmm10,%xmm2
+ movaps %xmm14,%xmm10
+ pxor %xmm11,%xmm3
+ movdqu %xmm2,(%rsi)
+ pxor %xmm12,%xmm4
+ movdqu %xmm3,16(%rsi)
+ pxor %xmm13,%xmm5
+ movdqu %xmm4,32(%rsi)
+ movdqa %xmm5,%xmm2
+ leaq 48(%rsi),%rsi
+ jmp .Lcbc_dec_tail_collected
+
+.align 16
+.Lcbc_dec_tail_collected:
+ movups %xmm10,(%r8)
+ andq $15,%rdx
+ 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:
+ .byte 0xf3,0xc3
+.size aesni_cbc_encrypt,.-aesni_cbc_encrypt
+.globl aesni_set_decrypt_key
+.hidden aesni_set_decrypt_key
+.type aesni_set_decrypt_key,@function
+.align 16
+aesni_set_decrypt_key:
+.byte 0x48,0x83,0xEC,0x08
+ 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
+.byte 102,15,56,219,192
+.byte 102,15,56,219,201
+ 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
+.byte 102,15,56,219,192
+ movups %xmm0,(%rdi)
+.Ldec_key_ret:
+ addq $8,%rsp
+ .byte 0xf3,0xc3
+.LSEH_end_set_decrypt_key:
+.size aesni_set_decrypt_key,.-aesni_set_decrypt_key
+.globl aesni_set_encrypt_key
+.hidden aesni_set_encrypt_key
+.type aesni_set_encrypt_key,@function
+.align 16
+aesni_set_encrypt_key:
+__aesni_set_encrypt_key:
+.byte 0x48,0x83,0xEC,0x08
+ 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)
+.byte 102,15,58,223,200,1
+ call .Lkey_expansion_128_cold
+.byte 102,15,58,223,200,2
+ call .Lkey_expansion_128
+.byte 102,15,58,223,200,4
+ call .Lkey_expansion_128
+.byte 102,15,58,223,200,8
+ call .Lkey_expansion_128
+.byte 102,15,58,223,200,16
+ call .Lkey_expansion_128
+.byte 102,15,58,223,200,32
+ call .Lkey_expansion_128
+.byte 102,15,58,223,200,64
+ call .Lkey_expansion_128
+.byte 102,15,58,223,200,128
+ call .Lkey_expansion_128
+.byte 102,15,58,223,200,27
+ call .Lkey_expansion_128
+.byte 102,15,58,223,200,54
+ 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)
+.byte 102,15,58,223,202,1
+ call .Lkey_expansion_192a_cold
+.byte 102,15,58,223,202,2
+ call .Lkey_expansion_192b
+.byte 102,15,58,223,202,4
+ call .Lkey_expansion_192a
+.byte 102,15,58,223,202,8
+ call .Lkey_expansion_192b
+.byte 102,15,58,223,202,16
+ call .Lkey_expansion_192a
+.byte 102,15,58,223,202,32
+ call .Lkey_expansion_192b
+.byte 102,15,58,223,202,64
+ call .Lkey_expansion_192a
+.byte 102,15,58,223,202,128
+ 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)
+.byte 102,15,58,223,202,1
+ call .Lkey_expansion_256a_cold
+.byte 102,15,58,223,200,1
+ call .Lkey_expansion_256b
+.byte 102,15,58,223,202,2
+ call .Lkey_expansion_256a
+.byte 102,15,58,223,200,2
+ call .Lkey_expansion_256b
+.byte 102,15,58,223,202,4
+ call .Lkey_expansion_256a
+.byte 102,15,58,223,200,4
+ call .Lkey_expansion_256b
+.byte 102,15,58,223,202,8
+ call .Lkey_expansion_256a
+.byte 102,15,58,223,200,8
+ call .Lkey_expansion_256b
+.byte 102,15,58,223,202,16
+ call .Lkey_expansion_256a
+.byte 102,15,58,223,200,16
+ call .Lkey_expansion_256b
+.byte 102,15,58,223,202,32
+ call .Lkey_expansion_256a
+.byte 102,15,58,223,200,32
+ call .Lkey_expansion_256b
+.byte 102,15,58,223,202,64
+ 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
+ .byte 0xf3,0xc3
+.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
+ .byte 0xf3,0xc3
+
+.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
+ .byte 0xf3,0xc3
+
+.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
+ .byte 0xf3,0xc3
+
+.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
+ .byte 0xf3,0xc3
+.size aesni_set_encrypt_key,.-aesni_set_encrypt_key
+.size __aesni_set_encrypt_key,.-__aesni_set_encrypt_key
+.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
+.Lincrement1:
+.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
+
+.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
+.align 64
+#endif
diff --git a/linux-x86_64/crypto/aes/bsaes-x86_64.S b/linux-x86_64/crypto/aes/bsaes-x86_64.S
new file mode 100644
index 0000000..2960e95
--- /dev/null
+++ b/linux-x86_64/crypto/aes/bsaes-x86_64.S
@@ -0,0 +1,2504 @@
+#if defined(__x86_64__)
+.text
+
+
+
+
+.type _bsaes_encrypt8,@function
+.align 64
+_bsaes_encrypt8:
+ leaq .LBS0(%rip),%r11
+
+ movdqa (%rax),%xmm8
+ leaq 16(%rax),%rax
+ movdqa 80(%r11),%xmm7
+ pxor %xmm8,%xmm15
+ pxor %xmm8,%xmm0
+ pxor %xmm8,%xmm1
+ pxor %xmm8,%xmm2
+.byte 102,68,15,56,0,255
+.byte 102,15,56,0,199
+ pxor %xmm8,%xmm3
+ pxor %xmm8,%xmm4
+.byte 102,15,56,0,207
+.byte 102,15,56,0,215
+ pxor %xmm8,%xmm5
+ pxor %xmm8,%xmm6
+.byte 102,15,56,0,223
+.byte 102,15,56,0,231
+.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
+ pxor 32(%rax),%xmm1
+ pxor 48(%rax),%xmm2
+.byte 102,68,15,56,0,255
+.byte 102,15,56,0,199
+ pxor 64(%rax),%xmm3
+ pxor 80(%rax),%xmm4
+.byte 102,15,56,0,207
+.byte 102,15,56,0,215
+ pxor 96(%rax),%xmm5
+ pxor 112(%rax),%xmm6
+.byte 102,15,56,0,223
+.byte 102,15,56,0,231
+.byte 102,15,56,0,239
+.byte 102,15,56,0,247
+ leaq 128(%rax),%rax
+.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
+ .byte 0xf3,0xc3
+.size _bsaes_encrypt8,.-_bsaes_encrypt8
+
+.type _bsaes_decrypt8,@function
+.align 64
+_bsaes_decrypt8:
+ leaq .LBS0(%rip),%r11
+
+ movdqa (%rax),%xmm8
+ leaq 16(%rax),%rax
+ movdqa -48(%r11),%xmm7
+ pxor %xmm8,%xmm15
+ pxor %xmm8,%xmm0
+ pxor %xmm8,%xmm1
+ pxor %xmm8,%xmm2
+.byte 102,68,15,56,0,255
+.byte 102,15,56,0,199
+ pxor %xmm8,%xmm3
+ pxor %xmm8,%xmm4
+.byte 102,15,56,0,207
+.byte 102,15,56,0,215
+ pxor %xmm8,%xmm5
+ pxor %xmm8,%xmm6
+.byte 102,15,56,0,223
+.byte 102,15,56,0,231
+.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
+ pxor 32(%rax),%xmm1
+ pxor 48(%rax),%xmm2
+.byte 102,68,15,56,0,255
+.byte 102,15,56,0,199
+ pxor 64(%rax),%xmm3
+ pxor 80(%rax),%xmm4
+.byte 102,15,56,0,207
+.byte 102,15,56,0,215
+ pxor 96(%rax),%xmm5
+ pxor 112(%rax),%xmm6
+.byte 102,15,56,0,223
+.byte 102,15,56,0,231
+.byte 102,15,56,0,239
+.byte 102,15,56,0,247
+ leaq 128(%rax),%rax
+.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
+ .byte 0xf3,0xc3
+.size _bsaes_decrypt8,.-_bsaes_decrypt8
+.type _bsaes_key_convert,@function
+.align 16
+_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
+.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
+
+ .byte 0xf3,0xc3
+.size _bsaes_key_convert,.-_bsaes_key_convert
+
+.globl bsaes_cbc_encrypt
+.hidden bsaes_cbc_encrypt
+.type bsaes_cbc_encrypt,@function
+.align 16
+bsaes_cbc_encrypt:
+ 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:
+ .byte 0xf3,0xc3
+.size bsaes_cbc_encrypt,.-bsaes_cbc_encrypt
+
+.globl bsaes_ctr32_encrypt_blocks
+.hidden bsaes_ctr32_encrypt_blocks
+.type bsaes_ctr32_encrypt_blocks,@function
+.align 16
+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 %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
+ pxor %xmm8,%xmm1
+ pxor %xmm8,%xmm2
+.byte 102,68,15,56,0,255
+.byte 102,15,56,0,199
+ pxor %xmm8,%xmm3
+ pxor %xmm8,%xmm4
+.byte 102,15,56,0,207
+.byte 102,15,56,0,215
+ pxor %xmm8,%xmm5
+ pxor %xmm8,%xmm6
+.byte 102,15,56,0,223
+.byte 102,15,56,0,231
+.byte 102,15,56,0,239
+.byte 102,15,56,0,247
+ leaq .LBS0(%rip),%r11
+ 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:
+ .byte 0xf3,0xc3
+.size bsaes_ctr32_encrypt_blocks,.-bsaes_ctr32_encrypt_blocks
+.globl bsaes_xts_encrypt
+.hidden bsaes_xts_encrypt
+.type bsaes_xts_encrypt,@function
+.align 16
+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 %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:
+ .byte 0xf3,0xc3
+.size bsaes_xts_encrypt,.-bsaes_xts_encrypt
+
+.globl bsaes_xts_decrypt
+.hidden bsaes_xts_decrypt
+.type bsaes_xts_decrypt,@function
+.align 16
+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 %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:
+ .byte 0xf3,0xc3
+.size bsaes_xts_decrypt,.-bsaes_xts_decrypt
+.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
+.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
+.align 64
+.size _bsaes_const,.-_bsaes_const
+#endif
diff --git a/linux-x86_64/crypto/aes/vpaes-x86_64.S b/linux-x86_64/crypto/aes/vpaes-x86_64.S
new file mode 100644
index 0000000..1d12424
--- /dev/null
+++ b/linux-x86_64/crypto/aes/vpaes-x86_64.S
@@ -0,0 +1,834 @@
+#if defined(__x86_64__)
+.text
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+.type _vpaes_encrypt_core,@function
+.align 16
+_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
+ addq $16,%r9
+ pxor %xmm2,%xmm0
+ leaq .Lk_mc_backward(%rip),%r10
+ jmp .Lenc_entry
+
+.align 16
+.Lenc_loop:
+
+ movdqa %xmm13,%xmm4
+ movdqa %xmm12,%xmm0
+.byte 102,15,56,0,226
+.byte 102,15,56,0,195
+ pxor %xmm5,%xmm4
+ movdqa %xmm15,%xmm5
+ pxor %xmm4,%xmm0
+ movdqa -64(%r11,%r10,1),%xmm1
+.byte 102,15,56,0,234
+ movdqa (%r11,%r10,1),%xmm4
+ movdqa %xmm14,%xmm2
+.byte 102,15,56,0,211
+ movdqa %xmm0,%xmm3
+ pxor %xmm5,%xmm2
+.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
+ subq $1,%rax
+ pxor %xmm3,%xmm0
+
+.Lenc_entry:
+
+ movdqa %xmm9,%xmm1
+ movdqa %xmm11,%xmm5
+ pandn %xmm0,%xmm1
+ psrld $4,%xmm1
+ pand %xmm9,%xmm0
+.byte 102,15,56,0,232
+ movdqa %xmm10,%xmm3
+ pxor %xmm1,%xmm0
+.byte 102,15,56,0,217
+ movdqa %xmm10,%xmm4
+ pxor %xmm5,%xmm3
+.byte 102,15,56,0,224
+ movdqa %xmm10,%xmm2
+ pxor %xmm5,%xmm4
+.byte 102,15,56,0,211
+ movdqa %xmm10,%xmm3
+ pxor %xmm0,%xmm2
+.byte 102,15,56,0,220
+ movdqu (%r9),%xmm5
+ 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
+ .byte 0xf3,0xc3
+.size _vpaes_encrypt_core,.-_vpaes_encrypt_core
+
+
+
+
+
+
+.type _vpaes_decrypt_core,@function
+.align 16
+_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
+
+.align 16
+.Ldec_loop:
+
+
+
+ movdqa -32(%r10),%xmm4
+ movdqa -16(%r10),%xmm1
+.byte 102,15,56,0,226
+.byte 102,15,56,0,203
+ pxor %xmm4,%xmm0
+ movdqa 0(%r10),%xmm4
+ pxor %xmm1,%xmm0
+ movdqa 16(%r10),%xmm1
+
+.byte 102,15,56,0,226
+.byte 102,15,56,0,197
+.byte 102,15,56,0,203
+ pxor %xmm4,%xmm0
+ movdqa 32(%r10),%xmm4
+ pxor %xmm1,%xmm0
+ movdqa 48(%r10),%xmm1
+
+.byte 102,15,56,0,226
+.byte 102,15,56,0,197
+.byte 102,15,56,0,203
+ pxor %xmm4,%xmm0
+ movdqa 64(%r10),%xmm4
+ pxor %xmm1,%xmm0
+ movdqa 80(%r10),%xmm1
+
+.byte 102,15,56,0,226
+.byte 102,15,56,0,197
+.byte 102,15,56,0,203
+ pxor %xmm4,%xmm0
+ addq $16,%r9
+.byte 102,15,58,15,237,12
+ pxor %xmm1,%xmm0
+ subq $1,%rax
+
+.Ldec_entry:
+
+ movdqa %xmm9,%xmm1
+ pandn %xmm0,%xmm1
+ movdqa %xmm11,%xmm2
+ psrld $4,%xmm1
+ pand %xmm9,%xmm0
+.byte 102,15,56,0,208
+ movdqa %xmm10,%xmm3
+ pxor %xmm1,%xmm0
+.byte 102,15,56,0,217
+ movdqa %xmm10,%xmm4
+ pxor %xmm2,%xmm3
+.byte 102,15,56,0,224
+ pxor %xmm2,%xmm4
+ movdqa %xmm10,%xmm2
+.byte 102,15,56,0,211
+ movdqa %xmm10,%xmm3
+ pxor %xmm0,%xmm2
+.byte 102,15,56,0,220
+ movdqu (%r9),%xmm0
+ pxor %xmm1,%xmm3
+ 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
+ .byte 0xf3,0xc3
+.size _vpaes_decrypt_core,.-_vpaes_decrypt_core
+
+
+
+
+
+
+.type _vpaes_schedule_core,@function
+.align 16
+_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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+.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
+ .byte 0xf3,0xc3
+.size _vpaes_schedule_core,.-_vpaes_schedule_core
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+.type _vpaes_schedule_192_smear,@function
+.align 16
+_vpaes_schedule_192_smear:
+ pshufd $128,%xmm6,%xmm1
+ pshufd $254,%xmm7,%xmm0
+ pxor %xmm1,%xmm6
+ pxor %xmm1,%xmm1
+ pxor %xmm0,%xmm6
+ movdqa %xmm6,%xmm0
+ movhlps %xmm1,%xmm6
+ .byte 0xf3,0xc3
+.size _vpaes_schedule_192_smear,.-_vpaes_schedule_192_smear
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+.type _vpaes_schedule_round,@function
+.align 16
+_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
+ .byte 0xf3,0xc3
+.size _vpaes_schedule_round,.-_vpaes_schedule_round
+
+
+
+
+
+
+
+
+
+
+.type _vpaes_schedule_transform,@function
+.align 16
+_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
+ .byte 0xf3,0xc3
+.size _vpaes_schedule_transform,.-_vpaes_schedule_transform
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+.type _vpaes_schedule_mangle,@function
+.align 16
+_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
+.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)
+ .byte 0xf3,0xc3
+.size _vpaes_schedule_mangle,.-_vpaes_schedule_mangle
+
+
+
+
+.globl vpaes_set_encrypt_key
+.hidden vpaes_set_encrypt_key
+.type vpaes_set_encrypt_key,@function
+.align 16
+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
+ .byte 0xf3,0xc3
+.size vpaes_set_encrypt_key,.-vpaes_set_encrypt_key
+
+.globl vpaes_set_decrypt_key
+.hidden vpaes_set_decrypt_key
+.type vpaes_set_decrypt_key,@function
+.align 16
+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
+ .byte 0xf3,0xc3
+.size vpaes_set_decrypt_key,.-vpaes_set_decrypt_key
+
+.globl vpaes_encrypt
+.hidden vpaes_encrypt
+.type vpaes_encrypt,@function
+.align 16
+vpaes_encrypt:
+ movdqu (%rdi),%xmm0
+ call _vpaes_preheat
+ call _vpaes_encrypt_core
+ movdqu %xmm0,(%rsi)
+ .byte 0xf3,0xc3
+.size vpaes_encrypt,.-vpaes_encrypt
+
+.globl vpaes_decrypt
+.hidden vpaes_decrypt
+.type vpaes_decrypt,@function
+.align 16
+vpaes_decrypt:
+ movdqu (%rdi),%xmm0
+ call _vpaes_preheat
+ call _vpaes_decrypt_core
+ movdqu %xmm0,(%rsi)
+ .byte 0xf3,0xc3
+.size vpaes_decrypt,.-vpaes_decrypt
+.globl vpaes_cbc_encrypt
+.hidden vpaes_cbc_encrypt
+.type vpaes_cbc_encrypt,@function
+.align 16
+vpaes_cbc_encrypt:
+ 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:
+ .byte 0xf3,0xc3
+.size vpaes_cbc_encrypt,.-vpaes_cbc_encrypt
+
+
+
+
+
+
+.type _vpaes_preheat,@function
+.align 16
+_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
+ .byte 0xf3,0xc3
+.size _vpaes_preheat,.-_vpaes_preheat
+
+
+
+
+
+.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
+.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
+.align 64
+.size _vpaes_consts,.-_vpaes_consts
+#endif
diff --git a/linux-x86_64/crypto/bn/modexp512-x86_64.S b/linux-x86_64/crypto/bn/modexp512-x86_64.S
new file mode 100644
index 0000000..e49a2cb
--- /dev/null
+++ b/linux-x86_64/crypto/bn/modexp512-x86_64.S
@@ -0,0 +1,1776 @@
+#if defined(__x86_64__)
+.text
+
+.type MULADD_128x512,@function
+.align 16
+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
+ .byte 0xf3,0xc3
+.size MULADD_128x512,.-MULADD_128x512
+.type mont_reduce,@function
+.align 16
+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)
+
+ .byte 0xf3,0xc3
+.size mont_reduce,.-mont_reduce
+.type mont_mul_a3b,@function
+.align 16
+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
+
+
+.size mont_mul_a3b,.-mont_mul_a3b
+.type sqr_reduce,@function
+.align 16
+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
+
+
+.size sqr_reduce,.-sqr_reduce
+.globl mod_exp_512
+.hidden mod_exp_512
+.type mod_exp_512,@function
+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)
+.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:
+ .byte 0xf3,0xc3
+.size mod_exp_512, . - mod_exp_512
+#endif
diff --git a/linux-x86_64/crypto/bn/rsaz-avx2.S b/linux-x86_64/crypto/bn/rsaz-avx2.S
new file mode 100644
index 0000000..cd334d9
--- /dev/null
+++ b/linux-x86_64/crypto/bn/rsaz-avx2.S
@@ -0,0 +1,34 @@
+#if defined(__x86_64__)
+.text
+
+.globl rsaz_avx2_eligible
+.hidden rsaz_avx2_eligible
+.type rsaz_avx2_eligible,@function
+rsaz_avx2_eligible:
+ xorl %eax,%eax
+ .byte 0xf3,0xc3
+.size rsaz_avx2_eligible,.-rsaz_avx2_eligible
+
+.globl rsaz_1024_sqr_avx2
+.hidden rsaz_1024_sqr_avx2
+.globl rsaz_1024_mul_avx2
+.hidden rsaz_1024_mul_avx2
+.globl rsaz_1024_norm2red_avx2
+.hidden rsaz_1024_norm2red_avx2
+.globl rsaz_1024_red2norm_avx2
+.hidden rsaz_1024_red2norm_avx2
+.globl rsaz_1024_scatter5_avx2
+.hidden rsaz_1024_scatter5_avx2
+.globl rsaz_1024_gather5_avx2
+.hidden rsaz_1024_gather5_avx2
+.type rsaz_1024_sqr_avx2,@function
+rsaz_1024_sqr_avx2:
+rsaz_1024_mul_avx2:
+rsaz_1024_norm2red_avx2:
+rsaz_1024_red2norm_avx2:
+rsaz_1024_scatter5_avx2:
+rsaz_1024_gather5_avx2:
+.byte 0x0f,0x0b
+ .byte 0xf3,0xc3
+.size rsaz_1024_sqr_avx2,.-rsaz_1024_sqr_avx2
+#endif
diff --git a/linux-x86_64/crypto/bn/rsaz-x86_64.S b/linux-x86_64/crypto/bn/rsaz-x86_64.S
new file mode 100644
index 0000000..fe0eed5
--- /dev/null
+++ b/linux-x86_64/crypto/bn/rsaz-x86_64.S
@@ -0,0 +1,1126 @@
+#if defined(__x86_64__)
+.text
+
+
+
+.globl rsaz_512_sqr
+.hidden rsaz_512_sqr
+.type rsaz_512_sqr,@function
+.align 32
+rsaz_512_sqr:
+ pushq %rbx
+ pushq %rbp
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ pushq %r15
+
+ subq $128+24,%rsp
+.Lsqr_body:
+ movq %rdx,%rbp
+ movq (%rsi),%rdx
+ movq 8(%rsi),%rax
+ movq %rcx,128(%rsp)
+ jmp .Loop_sqr
+
+.align 32
+.Loop_sqr:
+ movl %r8d,128+8(%rsp)
+
+ movq %rdx,%rbx
+ mulq %rdx
+ movq %rax,%r8
+ movq 16(%rsi),%rax
+ movq %rdx,%r9
+
+ mulq %rbx
+ addq %rax,%r9
+ movq 24(%rsi),%rax
+ movq %rdx,%r10
+ adcq $0,%r10
+
+ mulq %rbx
+ addq %rax,%r10
+ movq 32(%rsi),%rax
+ movq %rdx,%r11
+ adcq $0,%r11
+
+ mulq %rbx
+ addq %rax,%r11
+ movq 40(%rsi),%rax
+ movq %rdx,%r12
+ adcq $0,%r12
+
+ mulq %rbx
+ addq %rax,%r12
+ movq 48(%rsi),%rax
+ movq %rdx,%r13
+ adcq $0,%r13
+
+ mulq %rbx
+ addq %rax,%r13
+ movq 56(%rsi),%rax
+ movq %rdx,%r14
+ adcq $0,%r14
+
+ mulq %rbx
+ addq %rax,%r14
+ movq %rbx,%rax
+ movq %rdx,%r15
+ adcq $0,%r15
+
+ addq %r8,%r8
+ movq %r9,%rcx
+ adcq %r9,%r9
+
+ mulq %rax
+ movq %rax,(%rsp)
+ addq %rdx,%r8
+ adcq $0,%r9
+
+ movq %r8,8(%rsp)
+ shrq $63,%rcx
+
+
+ movq 8(%rsi),%r8
+ movq 16(%rsi),%rax
+ mulq %r8
+ addq %rax,%r10
+ movq 24(%rsi),%rax
+ movq %rdx,%rbx
+ adcq $0,%rbx
+
+ mulq %r8
+ addq %rax,%r11
+ movq 32(%rsi),%rax
+ adcq $0,%rdx
+ addq %rbx,%r11
+ movq %rdx,%rbx
+ adcq $0,%rbx
+
+ mulq %r8
+ addq %rax,%r12
+ movq 40(%rsi),%rax
+ adcq $0,%rdx
+ addq %rbx,%r12
+ movq %rdx,%rbx
+ adcq $0,%rbx
+
+ mulq %r8
+ addq %rax,%r13
+ movq 48(%rsi),%rax
+ adcq $0,%rdx
+ addq %rbx,%r13
+ movq %rdx,%rbx
+ adcq $0,%rbx
+
+ mulq %r8
+ addq %rax,%r14
+ movq 56(%rsi),%rax
+ adcq $0,%rdx
+ addq %rbx,%r14
+ movq %rdx,%rbx
+ adcq $0,%rbx
+
+ mulq %r8
+ addq %rax,%r15
+ movq %r8,%rax
+ adcq $0,%rdx
+ addq %rbx,%r15
+ movq %rdx,%r8
+ movq %r10,%rdx
+ adcq $0,%r8
+
+ addq %rdx,%rdx
+ leaq (%rcx,%r10,2),%r10
+ movq %r11,%rbx
+ adcq %r11,%r11
+
+ mulq %rax
+ addq %rax,%r9
+ adcq %rdx,%r10
+ adcq $0,%r11
+
+ movq %r9,16(%rsp)
+ movq %r10,24(%rsp)
+ shrq $63,%rbx
+
+
+ movq 16(%rsi),%r9
+ movq 24(%rsi),%rax
+ mulq %r9
+ addq %rax,%r12
+ movq 32(%rsi),%rax
+ movq %rdx,%rcx
+ adcq $0,%rcx
+
+ mulq %r9
+ addq %rax,%r13
+ movq 40(%rsi),%rax
+ adcq $0,%rdx
+ addq %rcx,%r13
+ movq %rdx,%rcx
+ adcq $0,%rcx
+
+ mulq %r9
+ addq %rax,%r14
+ movq 48(%rsi),%rax
+ adcq $0,%rdx
+ addq %rcx,%r14
+ movq %rdx,%rcx
+ adcq $0,%rcx
+
+ mulq %r9
+ movq %r12,%r10
+ leaq (%rbx,%r12,2),%r12
+ addq %rax,%r15
+ movq 56(%rsi),%rax
+ adcq $0,%rdx
+ addq %rcx,%r15
+ movq %rdx,%rcx
+ adcq $0,%rcx
+
+ mulq %r9
+ shrq $63,%r10
+ addq %rax,%r8
+ movq %r9,%rax
+ adcq $0,%rdx
+ addq %rcx,%r8
+ movq %rdx,%r9
+ adcq $0,%r9
+
+ movq %r13,%rcx
+ leaq (%r10,%r13,2),%r13
+
+ mulq %rax
+ addq %rax,%r11
+ adcq %rdx,%r12
+ adcq $0,%r13
+
+ movq %r11,32(%rsp)
+ movq %r12,40(%rsp)
+ shrq $63,%rcx
+
+
+ movq 24(%rsi),%r10
+ movq 32(%rsi),%rax
+ mulq %r10
+ addq %rax,%r14
+ movq 40(%rsi),%rax
+ movq %rdx,%rbx
+ adcq $0,%rbx
+
+ mulq %r10
+ addq %rax,%r15
+ movq 48(%rsi),%rax
+ adcq $0,%rdx
+ addq %rbx,%r15
+ movq %rdx,%rbx
+ adcq $0,%rbx
+
+ mulq %r10
+ movq %r14,%r12
+ leaq (%rcx,%r14,2),%r14
+ addq %rax,%r8
+ movq 56(%rsi),%rax
+ adcq $0,%rdx
+ addq %rbx,%r8
+ movq %rdx,%rbx
+ adcq $0,%rbx
+
+ mulq %r10
+ shrq $63,%r12
+ addq %rax,%r9
+ movq %r10,%rax
+ adcq $0,%rdx
+ addq %rbx,%r9
+ movq %rdx,%r10
+ adcq $0,%r10
+
+ movq %r15,%rbx
+ leaq (%r12,%r15,2),%r15
+
+ mulq %rax
+ addq %rax,%r13
+ adcq %rdx,%r14
+ adcq $0,%r15
+
+ movq %r13,48(%rsp)
+ movq %r14,56(%rsp)
+ shrq $63,%rbx
+
+
+ movq 32(%rsi),%r11
+ movq 40(%rsi),%rax
+ mulq %r11
+ addq %rax,%r8
+ movq 48(%rsi),%rax
+ movq %rdx,%rcx
+ adcq $0,%rcx
+
+ mulq %r11
+ addq %rax,%r9
+ movq 56(%rsi),%rax
+ adcq $0,%rdx
+ movq %r8,%r12
+ leaq (%rbx,%r8,2),%r8
+ addq %rcx,%r9
+ movq %rdx,%rcx
+ adcq $0,%rcx
+
+ mulq %r11
+ shrq $63,%r12
+ addq %rax,%r10
+ movq %r11,%rax
+ adcq $0,%rdx
+ addq %rcx,%r10
+ movq %rdx,%r11
+ adcq $0,%r11
+
+ movq %r9,%rcx
+ leaq (%r12,%r9,2),%r9
+
+ mulq %rax
+ addq %rax,%r15
+ adcq %rdx,%r8
+ adcq $0,%r9
+
+ movq %r15,64(%rsp)
+ movq %r8,72(%rsp)
+ shrq $63,%rcx
+
+
+ movq 40(%rsi),%r12
+ movq 48(%rsi),%rax
+ mulq %r12
+ addq %rax,%r10
+ movq 56(%rsi),%rax
+ movq %rdx,%rbx
+ adcq $0,%rbx
+
+ mulq %r12
+ addq %rax,%r11
+ movq %r12,%rax
+ movq %r10,%r15
+ leaq (%rcx,%r10,2),%r10
+ adcq $0,%rdx
+ shrq $63,%r15
+ addq %rbx,%r11
+ movq %rdx,%r12
+ adcq $0,%r12
+
+ movq %r11,%rbx
+ leaq (%r15,%r11,2),%r11
+
+ mulq %rax
+ addq %rax,%r9
+ adcq %rdx,%r10
+ adcq $0,%r11
+
+ movq %r9,80(%rsp)
+ movq %r10,88(%rsp)
+
+
+ movq 48(%rsi),%r13
+ movq 56(%rsi),%rax
+ mulq %r13
+ addq %rax,%r12
+ movq %r13,%rax
+ movq %rdx,%r13
+ adcq $0,%r13
+
+ xorq %r14,%r14
+ shlq $1,%rbx
+ adcq %r12,%r12
+ adcq %r13,%r13
+ adcq %r14,%r14
+
+ mulq %rax
+ addq %rax,%r11
+ adcq %rdx,%r12
+ adcq $0,%r13
+
+ movq %r11,96(%rsp)
+ movq %r12,104(%rsp)
+
+
+ movq 56(%rsi),%rax
+ mulq %rax
+ addq %rax,%r13
+ adcq $0,%rdx
+
+ addq %rdx,%r14
+
+ movq %r13,112(%rsp)
+ movq %r14,120(%rsp)
+
+ movq (%rsp),%r8
+ movq 8(%rsp),%r9
+ movq 16(%rsp),%r10
+ movq 24(%rsp),%r11
+ movq 32(%rsp),%r12
+ movq 40(%rsp),%r13
+ movq 48(%rsp),%r14
+ movq 56(%rsp),%r15
+
+ call __rsaz_512_reduce
+
+ addq 64(%rsp),%r8
+ adcq 72(%rsp),%r9
+ adcq 80(%rsp),%r10
+ adcq 88(%rsp),%r11
+ adcq 96(%rsp),%r12
+ adcq 104(%rsp),%r13
+ adcq 112(%rsp),%r14
+ adcq 120(%rsp),%r15
+ sbbq %rcx,%rcx
+
+ call __rsaz_512_subtract
+
+ movq %r8,%rdx
+ movq %r9,%rax
+ movl 128+8(%rsp),%r8d
+ movq %rdi,%rsi
+
+ decl %r8d
+ jnz .Loop_sqr
+
+ leaq 128+24+48(%rsp),%rax
+ movq -48(%rax),%r15
+ movq -40(%rax),%r14
+ movq -32(%rax),%r13
+ movq -24(%rax),%r12
+ movq -16(%rax),%rbp
+ movq -8(%rax),%rbx
+ leaq (%rax),%rsp
+.Lsqr_epilogue:
+ .byte 0xf3,0xc3
+.size rsaz_512_sqr,.-rsaz_512_sqr
+.globl rsaz_512_mul
+.hidden rsaz_512_mul
+.type rsaz_512_mul,@function
+.align 32
+rsaz_512_mul:
+ pushq %rbx
+ pushq %rbp
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ pushq %r15
+
+ subq $128+24,%rsp
+.Lmul_body:
+.byte 102,72,15,110,199
+.byte 102,72,15,110,201
+ movq %r8,128(%rsp)
+ movq (%rdx),%rbx
+ movq %rdx,%rbp
+ call __rsaz_512_mul
+
+.byte 102,72,15,126,199
+.byte 102,72,15,126,205
+
+ movq (%rsp),%r8
+ movq 8(%rsp),%r9
+ movq 16(%rsp),%r10
+ movq 24(%rsp),%r11
+ movq 32(%rsp),%r12
+ movq 40(%rsp),%r13
+ movq 48(%rsp),%r14
+ movq 56(%rsp),%r15
+
+ call __rsaz_512_reduce
+ addq 64(%rsp),%r8
+ adcq 72(%rsp),%r9
+ adcq 80(%rsp),%r10
+ adcq 88(%rsp),%r11
+ adcq 96(%rsp),%r12
+ adcq 104(%rsp),%r13
+ adcq 112(%rsp),%r14
+ adcq 120(%rsp),%r15
+ sbbq %rcx,%rcx
+
+ call __rsaz_512_subtract
+
+ leaq 128+24+48(%rsp),%rax
+ movq -48(%rax),%r15
+ movq -40(%rax),%r14
+ movq -32(%rax),%r13
+ movq -24(%rax),%r12
+ movq -16(%rax),%rbp
+ movq -8(%rax),%rbx
+ leaq (%rax),%rsp
+.Lmul_epilogue:
+ .byte 0xf3,0xc3
+.size rsaz_512_mul,.-rsaz_512_mul
+.globl rsaz_512_mul_gather4
+.hidden rsaz_512_mul_gather4
+.type rsaz_512_mul_gather4,@function
+.align 32
+rsaz_512_mul_gather4:
+ pushq %rbx
+ pushq %rbp
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ pushq %r15
+
+ movl %r9d,%r9d
+ subq $128+24,%rsp
+.Lmul_gather4_body:
+ movl 64(%rdx,%r9,4),%eax
+.byte 102,72,15,110,199
+ movl (%rdx,%r9,4),%ebx
+.byte 102,72,15,110,201
+ movq %r8,128(%rsp)
+
+ shlq $32,%rax
+ orq %rax,%rbx
+ movq (%rsi),%rax
+ movq 8(%rsi),%rcx
+ leaq 128(%rdx,%r9,4),%rbp
+ mulq %rbx
+ movq %rax,(%rsp)
+ movq %rcx,%rax
+ movq %rdx,%r8
+
+ mulq %rbx
+ movd (%rbp),%xmm4
+ addq %rax,%r8
+ movq 16(%rsi),%rax
+ movq %rdx,%r9
+ adcq $0,%r9
+
+ mulq %rbx
+ movd 64(%rbp),%xmm5
+ addq %rax,%r9
+ movq 24(%rsi),%rax
+ movq %rdx,%r10
+ adcq $0,%r10
+
+ mulq %rbx
+ pslldq $4,%xmm5
+ addq %rax,%r10
+ movq 32(%rsi),%rax
+ movq %rdx,%r11
+ adcq $0,%r11
+
+ mulq %rbx
+ por %xmm5,%xmm4
+ addq %rax,%r11
+ movq 40(%rsi),%rax
+ movq %rdx,%r12
+ adcq $0,%r12
+
+ mulq %rbx
+ addq %rax,%r12
+ movq 48(%rsi),%rax
+ movq %rdx,%r13
+ adcq $0,%r13
+
+ mulq %rbx
+ leaq 128(%rbp),%rbp
+ addq %rax,%r13
+ movq 56(%rsi),%rax
+ movq %rdx,%r14
+ adcq $0,%r14
+
+ mulq %rbx
+.byte 102,72,15,126,227
+ addq %rax,%r14
+ movq (%rsi),%rax
+ movq %rdx,%r15
+ adcq $0,%r15
+
+ leaq 8(%rsp),%rdi
+ movl $7,%ecx
+ jmp .Loop_mul_gather
+
+.align 32
+.Loop_mul_gather:
+ mulq %rbx
+ addq %rax,%r8
+ movq 8(%rsi),%rax
+ movq %r8,(%rdi)
+ movq %rdx,%r8
+ adcq $0,%r8
+
+ mulq %rbx
+ movd (%rbp),%xmm4
+ addq %rax,%r9
+ movq 16(%rsi),%rax
+ adcq $0,%rdx
+ addq %r9,%r8
+ movq %rdx,%r9
+ adcq $0,%r9
+
+ mulq %rbx
+ movd 64(%rbp),%xmm5
+ addq %rax,%r10
+ movq 24(%rsi),%rax
+ adcq $0,%rdx
+ addq %r10,%r9
+ movq %rdx,%r10
+ adcq $0,%r10
+
+ mulq %rbx
+ pslldq $4,%xmm5
+ addq %rax,%r11
+ movq 32(%rsi),%rax
+ adcq $0,%rdx
+ addq %r11,%r10
+ movq %rdx,%r11
+ adcq $0,%r11
+
+ mulq %rbx
+ por %xmm5,%xmm4
+ addq %rax,%r12
+ movq 40(%rsi),%rax
+ adcq $0,%rdx
+ addq %r12,%r11
+ movq %rdx,%r12
+ adcq $0,%r12
+
+ mulq %rbx
+ addq %rax,%r13
+ movq 48(%rsi),%rax
+ adcq $0,%rdx
+ addq %r13,%r12
+ movq %rdx,%r13
+ adcq $0,%r13
+
+ mulq %rbx
+ addq %rax,%r14
+ movq 56(%rsi),%rax
+ adcq $0,%rdx
+ addq %r14,%r13
+ movq %rdx,%r14
+ adcq $0,%r14
+
+ mulq %rbx
+.byte 102,72,15,126,227
+ addq %rax,%r15
+ movq (%rsi),%rax
+ adcq $0,%rdx
+ addq %r15,%r14
+ movq %rdx,%r15
+ adcq $0,%r15
+
+ leaq 128(%rbp),%rbp
+ leaq 8(%rdi),%rdi
+
+ decl %ecx
+ jnz .Loop_mul_gather
+
+ movq %r8,(%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)
+
+.byte 102,72,15,126,199
+.byte 102,72,15,126,205
+
+ movq (%rsp),%r8
+ movq 8(%rsp),%r9
+ movq 16(%rsp),%r10
+ movq 24(%rsp),%r11
+ movq 32(%rsp),%r12
+ movq 40(%rsp),%r13
+ movq 48(%rsp),%r14
+ movq 56(%rsp),%r15
+
+ call __rsaz_512_reduce
+ addq 64(%rsp),%r8
+ adcq 72(%rsp),%r9
+ adcq 80(%rsp),%r10
+ adcq 88(%rsp),%r11
+ adcq 96(%rsp),%r12
+ adcq 104(%rsp),%r13
+ adcq 112(%rsp),%r14
+ adcq 120(%rsp),%r15
+ sbbq %rcx,%rcx
+
+ call __rsaz_512_subtract
+
+ leaq 128+24+48(%rsp),%rax
+ movq -48(%rax),%r15
+ movq -40(%rax),%r14
+ movq -32(%rax),%r13
+ movq -24(%rax),%r12
+ movq -16(%rax),%rbp
+ movq -8(%rax),%rbx
+ leaq (%rax),%rsp
+.Lmul_gather4_epilogue:
+ .byte 0xf3,0xc3
+.size rsaz_512_mul_gather4,.-rsaz_512_mul_gather4
+.globl rsaz_512_mul_scatter4
+.hidden rsaz_512_mul_scatter4
+.type rsaz_512_mul_scatter4,@function
+.align 32
+rsaz_512_mul_scatter4:
+ pushq %rbx
+ pushq %rbp
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ pushq %r15
+
+ movl %r9d,%r9d
+ subq $128+24,%rsp
+.Lmul_scatter4_body:
+ leaq (%r8,%r9,4),%r8
+.byte 102,72,15,110,199
+.byte 102,72,15,110,202
+.byte 102,73,15,110,208
+ movq %rcx,128(%rsp)
+
+ movq %rdi,%rbp
+ movq (%rdi),%rbx
+ call __rsaz_512_mul
+
+.byte 102,72,15,126,199
+.byte 102,72,15,126,205
+
+ movq (%rsp),%r8
+ movq 8(%rsp),%r9
+ movq 16(%rsp),%r10
+ movq 24(%rsp),%r11
+ movq 32(%rsp),%r12
+ movq 40(%rsp),%r13
+ movq 48(%rsp),%r14
+ movq 56(%rsp),%r15
+
+ call __rsaz_512_reduce
+ addq 64(%rsp),%r8
+ adcq 72(%rsp),%r9
+ adcq 80(%rsp),%r10
+ adcq 88(%rsp),%r11
+ adcq 96(%rsp),%r12
+ adcq 104(%rsp),%r13
+ adcq 112(%rsp),%r14
+ adcq 120(%rsp),%r15
+.byte 102,72,15,126,214
+ sbbq %rcx,%rcx
+
+ call __rsaz_512_subtract
+
+ movl %r8d,0(%rsi)
+ shrq $32,%r8
+ movl %r9d,128(%rsi)
+ shrq $32,%r9
+ movl %r10d,256(%rsi)
+ shrq $32,%r10
+ movl %r11d,384(%rsi)
+ shrq $32,%r11
+ movl %r12d,512(%rsi)
+ shrq $32,%r12
+ movl %r13d,640(%rsi)
+ shrq $32,%r13
+ movl %r14d,768(%rsi)
+ shrq $32,%r14
+ movl %r15d,896(%rsi)
+ shrq $32,%r15
+ movl %r8d,64(%rsi)
+ movl %r9d,192(%rsi)
+ movl %r10d,320(%rsi)
+ movl %r11d,448(%rsi)
+ movl %r12d,576(%rsi)
+ movl %r13d,704(%rsi)
+ movl %r14d,832(%rsi)
+ movl %r15d,960(%rsi)
+
+ leaq 128+24+48(%rsp),%rax
+ movq -48(%rax),%r15
+ movq -40(%rax),%r14
+ movq -32(%rax),%r13
+ movq -24(%rax),%r12
+ movq -16(%rax),%rbp
+ movq -8(%rax),%rbx
+ leaq (%rax),%rsp
+.Lmul_scatter4_epilogue:
+ .byte 0xf3,0xc3
+.size rsaz_512_mul_scatter4,.-rsaz_512_mul_scatter4
+.globl rsaz_512_mul_by_one
+.hidden rsaz_512_mul_by_one
+.type rsaz_512_mul_by_one,@function
+.align 32
+rsaz_512_mul_by_one:
+ pushq %rbx
+ pushq %rbp
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ pushq %r15
+
+ subq $128+24,%rsp
+.Lmul_by_one_body:
+ movq %rdx,%rbp
+ movq %rcx,128(%rsp)
+
+ movq (%rsi),%r8
+ pxor %xmm0,%xmm0
+ movq 8(%rsi),%r9
+ movq 16(%rsi),%r10
+ movq 24(%rsi),%r11
+ movq 32(%rsi),%r12
+ movq 40(%rsi),%r13
+ movq 48(%rsi),%r14
+ movq 56(%rsi),%r15
+
+ movdqa %xmm0,(%rsp)
+ movdqa %xmm0,16(%rsp)
+ movdqa %xmm0,32(%rsp)
+ movdqa %xmm0,48(%rsp)
+ movdqa %xmm0,64(%rsp)
+ movdqa %xmm0,80(%rsp)
+ movdqa %xmm0,96(%rsp)
+ call __rsaz_512_reduce
+ movq %r8,(%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 128+24+48(%rsp),%rax
+ movq -48(%rax),%r15
+ movq -40(%rax),%r14
+ movq -32(%rax),%r13
+ movq -24(%rax),%r12
+ movq -16(%rax),%rbp
+ movq -8(%rax),%rbx
+ leaq (%rax),%rsp
+.Lmul_by_one_epilogue:
+ .byte 0xf3,0xc3
+.size rsaz_512_mul_by_one,.-rsaz_512_mul_by_one
+.type __rsaz_512_reduce,@function
+.align 32
+__rsaz_512_reduce:
+ movq %r8,%rbx
+ imulq 128+8(%rsp),%rbx
+ movq 0(%rbp),%rax
+ movl $8,%ecx
+ jmp .Lreduction_loop
+
+.align 32
+.Lreduction_loop:
+ mulq %rbx
+ movq 8(%rbp),%rax
+ negq %r8
+ movq %rdx,%r8
+ adcq $0,%r8
+
+ mulq %rbx
+ addq %rax,%r9
+ movq 16(%rbp),%rax
+ adcq $0,%rdx
+ addq %r9,%r8
+ movq %rdx,%r9
+ adcq $0,%r9
+
+ mulq %rbx
+ addq %rax,%r10
+ movq 24(%rbp),%rax
+ adcq $0,%rdx
+ addq %r10,%r9
+ movq %rdx,%r10
+ adcq $0,%r10
+
+ mulq %rbx
+ addq %rax,%r11
+ movq 32(%rbp),%rax
+ adcq $0,%rdx
+ addq %r11,%r10
+ movq 128+8(%rsp),%rsi
+
+
+ adcq $0,%rdx
+ movq %rdx,%r11
+
+ mulq %rbx
+ addq %rax,%r12
+ movq 40(%rbp),%rax
+ adcq $0,%rdx
+ imulq %r8,%rsi
+ addq %r12,%r11
+ movq %rdx,%r12
+ adcq $0,%r12
+
+ mulq %rbx
+ addq %rax,%r13
+ movq 48(%rbp),%rax
+ adcq $0,%rdx
+ addq %r13,%r12
+ movq %rdx,%r13
+ adcq $0,%r13
+
+ mulq %rbx
+ addq %rax,%r14
+ movq 56(%rbp),%rax
+ adcq $0,%rdx
+ addq %r14,%r13
+ movq %rdx,%r14
+ adcq $0,%r14
+
+ mulq %rbx
+ movq %rsi,%rbx
+ addq %rax,%r15
+ movq 0(%rbp),%rax
+ adcq $0,%rdx
+ addq %r15,%r14
+ movq %rdx,%r15
+ adcq $0,%r15
+
+ decl %ecx
+ jne .Lreduction_loop
+
+ .byte 0xf3,0xc3
+.size __rsaz_512_reduce,.-__rsaz_512_reduce
+.type __rsaz_512_subtract,@function
+.align 32
+__rsaz_512_subtract:
+ movq %r8,(%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)
+
+ movq 0(%rbp),%r8
+ movq 8(%rbp),%r9
+ negq %r8
+ notq %r9
+ andq %rcx,%r8
+ movq 16(%rbp),%r10
+ andq %rcx,%r9
+ notq %r10
+ movq 24(%rbp),%r11
+ andq %rcx,%r10
+ notq %r11
+ movq 32(%rbp),%r12
+ andq %rcx,%r11
+ notq %r12
+ movq 40(%rbp),%r13
+ andq %rcx,%r12
+ notq %r13
+ movq 48(%rbp),%r14
+ andq %rcx,%r13
+ notq %r14
+ movq 56(%rbp),%r15
+ andq %rcx,%r14
+ notq %r15
+ andq %rcx,%r15
+
+ addq (%rdi),%r8
+ adcq 8(%rdi),%r9
+ adcq 16(%rdi),%r10
+ adcq 24(%rdi),%r11
+ adcq 32(%rdi),%r12
+ adcq 40(%rdi),%r13
+ adcq 48(%rdi),%r14
+ adcq 56(%rdi),%r15
+
+ movq %r8,(%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)
+
+ .byte 0xf3,0xc3
+.size __rsaz_512_subtract,.-__rsaz_512_subtract
+.type __rsaz_512_mul,@function
+.align 32
+__rsaz_512_mul:
+ leaq 8(%rsp),%rdi
+
+ movq (%rsi),%rax
+ mulq %rbx
+ movq %rax,(%rdi)
+ movq 8(%rsi),%rax
+ movq %rdx,%r8
+
+ mulq %rbx
+ addq %rax,%r8
+ movq 16(%rsi),%rax
+ movq %rdx,%r9
+ adcq $0,%r9
+
+ mulq %rbx
+ addq %rax,%r9
+ movq 24(%rsi),%rax
+ movq %rdx,%r10
+ adcq $0,%r10
+
+ mulq %rbx
+ addq %rax,%r10
+ movq 32(%rsi),%rax
+ movq %rdx,%r11
+ adcq $0,%r11
+
+ mulq %rbx
+ addq %rax,%r11
+ movq 40(%rsi),%rax
+ movq %rdx,%r12
+ adcq $0,%r12
+
+ mulq %rbx
+ addq %rax,%r12
+ movq 48(%rsi),%rax
+ movq %rdx,%r13
+ adcq $0,%r13
+
+ mulq %rbx
+ addq %rax,%r13
+ movq 56(%rsi),%rax
+ movq %rdx,%r14
+ adcq $0,%r14
+
+ mulq %rbx
+ addq %rax,%r14
+ movq (%rsi),%rax
+ movq %rdx,%r15
+ adcq $0,%r15
+
+ leaq 8(%rbp),%rbp
+ leaq 8(%rdi),%rdi
+
+ movl $7,%ecx
+ jmp .Loop_mul
+
+.align 32
+.Loop_mul:
+ movq (%rbp),%rbx
+ mulq %rbx
+ addq %rax,%r8
+ movq 8(%rsi),%rax
+ movq %r8,(%rdi)
+ movq %rdx,%r8
+ adcq $0,%r8
+
+ mulq %rbx
+ addq %rax,%r9
+ movq 16(%rsi),%rax
+ adcq $0,%rdx
+ addq %r9,%r8
+ movq %rdx,%r9
+ adcq $0,%r9
+
+ mulq %rbx
+ addq %rax,%r10
+ movq 24(%rsi),%rax
+ adcq $0,%rdx
+ addq %r10,%r9
+ movq %rdx,%r10
+ adcq $0,%r10
+
+ mulq %rbx
+ addq %rax,%r11
+ movq 32(%rsi),%rax
+ adcq $0,%rdx
+ addq %r11,%r10
+ movq %rdx,%r11
+ adcq $0,%r11
+
+ mulq %rbx
+ addq %rax,%r12
+ movq 40(%rsi),%rax
+ adcq $0,%rdx
+ addq %r12,%r11
+ movq %rdx,%r12
+ adcq $0,%r12
+
+ mulq %rbx
+ addq %rax,%r13
+ movq 48(%rsi),%rax
+ adcq $0,%rdx
+ addq %r13,%r12
+ movq %rdx,%r13
+ adcq $0,%r13
+
+ mulq %rbx
+ addq %rax,%r14
+ movq 56(%rsi),%rax
+ adcq $0,%rdx
+ addq %r14,%r13
+ movq %rdx,%r14
+ leaq 8(%rbp),%rbp
+ adcq $0,%r14
+
+ mulq %rbx
+ addq %rax,%r15
+ movq (%rsi),%rax
+ adcq $0,%rdx
+ addq %r15,%r14
+ movq %rdx,%r15
+ adcq $0,%r15
+
+ leaq 8(%rdi),%rdi
+
+ decl %ecx
+ jnz .Loop_mul
+
+ movq %r8,(%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)
+
+ .byte 0xf3,0xc3
+.size __rsaz_512_mul,.-__rsaz_512_mul
+.globl rsaz_512_scatter4
+.hidden rsaz_512_scatter4
+.type rsaz_512_scatter4,@function
+.align 16
+rsaz_512_scatter4:
+ leaq (%rdi,%rdx,4),%rdi
+ movl $8,%r9d
+ jmp .Loop_scatter
+.align 16
+.Loop_scatter:
+ movq (%rsi),%rax
+ leaq 8(%rsi),%rsi
+ movl %eax,(%rdi)
+ shrq $32,%rax
+ movl %eax,64(%rdi)
+ leaq 128(%rdi),%rdi
+ decl %r9d
+ jnz .Loop_scatter
+ .byte 0xf3,0xc3
+.size rsaz_512_scatter4,.-rsaz_512_scatter4
+
+.globl rsaz_512_gather4
+.hidden rsaz_512_gather4
+.type rsaz_512_gather4,@function
+.align 16
+rsaz_512_gather4:
+ leaq (%rsi,%rdx,4),%rsi
+ movl $8,%r9d
+ jmp .Loop_gather
+.align 16
+.Loop_gather:
+ movl (%rsi),%eax
+ movl 64(%rsi),%r8d
+ leaq 128(%rsi),%rsi
+ shlq $32,%r8
+ orq %r8,%rax
+ movq %rax,(%rdi)
+ leaq 8(%rdi),%rdi
+ decl %r9d
+ jnz .Loop_gather
+ .byte 0xf3,0xc3
+.size rsaz_512_gather4,.-rsaz_512_gather4
+#endif
diff --git a/linux-x86_64/crypto/bn/x86_64-mont.S b/linux-x86_64/crypto/bn/x86_64-mont.S
new file mode 100644
index 0000000..ebe7678
--- /dev/null
+++ b/linux-x86_64/crypto/bn/x86_64-mont.S
@@ -0,0 +1,726 @@
+#if defined(__x86_64__)
+.text
+
+
+
+.globl bn_mul_mont
+.hidden bn_mul_mont
+.type bn_mul_mont,@function
+.align 16
+bn_mul_mont:
+ testl $3,%r9d
+ jnz .Lmul_enter
+ cmpl $8,%r9d
+ jb .Lmul_enter
+ cmpq %rsi,%rdx
+ jne .Lmul4x_enter
+ testl $7,%r9d
+ jz .Lsqr8x_enter
+ jmp .Lmul4x_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
+ jne .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
+ jne .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
+ jb .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
+ movq %r9,%r15
+.align 16
+.Lcopy:
+ movq (%rsp,%r14,8),%rsi
+ movq (%rdi,%r14,8),%rcx
+ xorq %rcx,%rsi
+ andq %rax,%rsi
+ xorq %rcx,%rsi
+ movq %r14,(%rsp,%r14,8)
+ movq %rsi,(%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:
+ .byte 0xf3,0xc3
+.size bn_mul_mont,.-bn_mul_mont
+.type bn_mul4x_mont,@function
+.align 16
+bn_mul4x_mont:
+.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
+.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
+ jb .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
+ jb .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
+ jb .Louter4x
+ movq 16(%rsp,%r9,8),%rdi
+ movq 0(%rsp),%rax
+ 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 %rax,%xmm0
+ punpcklqdq %xmm0,%xmm0
+ movq %rbp,24(%rdi,%r14,8)
+ xorq %r14,%r14
+
+ movq %r9,%r15
+ pxor %xmm5,%xmm5
+ jmp .Lcopy4x
+.align 16
+.Lcopy4x:
+ movdqu (%rsp,%r14,1),%xmm2
+ movdqu 16(%rsp,%r14,1),%xmm4
+ movdqu (%rdi,%r14,1),%xmm1
+ movdqu 16(%rdi,%r14,1),%xmm3
+ pxor %xmm1,%xmm2
+ pxor %xmm3,%xmm4
+ pand %xmm0,%xmm2
+ pand %xmm0,%xmm4
+ pxor %xmm1,%xmm2
+ pxor %xmm3,%xmm4
+ movdqu %xmm2,(%rdi,%r14,1)
+ movdqu %xmm4,16(%rdi,%r14,1)
+ movdqa %xmm5,(%rsp,%r14,1)
+ movdqa %xmm5,16(%rsp,%r14,1)
+
+ leaq 32(%r14),%r14
+ decq %r15
+ jnz .Lcopy4x
+
+ shlq $2,%r9
+ 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:
+ .byte 0xf3,0xc3
+.size bn_mul4x_mont,.-bn_mul4x_mont
+
+
+.type bn_sqr8x_mont,@function
+.align 32
+bn_sqr8x_mont:
+.Lsqr8x_enter:
+ movq %rsp,%rax
+ pushq %rbx
+ pushq %rbp
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ pushq %r15
+
+ movl %r9d,%r10d
+ shll $3,%r9d
+ shlq $3+2,%r10
+ negq %r9
+
+
+
+
+
+
+ leaq -64(%rsp,%r9,4),%r11
+ movq (%r8),%r8
+ subq %rsi,%r11
+ andq $4095,%r11
+ cmpq %r11,%r10
+ jb .Lsqr8x_sp_alt
+ subq %r11,%rsp
+ leaq -64(%rsp,%r9,4),%rsp
+ jmp .Lsqr8x_sp_done
+
+.align 32
+.Lsqr8x_sp_alt:
+ leaq 4096-64(,%r9,4),%r10
+ leaq -64(%rsp,%r9,4),%rsp
+ subq %r10,%r11
+ movq $0,%r10
+ cmovcq %r10,%r11
+ subq %r11,%rsp
+.Lsqr8x_sp_done:
+ andq $-64,%rsp
+ movq %r9,%r10
+ negq %r9
+
+ leaq 64(%rsp,%r9,2),%r11
+ movq %r8,32(%rsp)
+ movq %rax,40(%rsp)
+.Lsqr8x_body:
+
+ movq %r9,%rbp
+.byte 102,73,15,110,211
+ shrq $3+2,%rbp
+ movl OPENSSL_ia32cap_P+8(%rip),%eax
+ jmp .Lsqr8x_copy_n
+
+.align 32
+.Lsqr8x_copy_n:
+ movq 0(%rcx),%xmm0
+ movq 8(%rcx),%xmm1
+ movq 16(%rcx),%xmm3
+ movq 24(%rcx),%xmm4
+ leaq 32(%rcx),%rcx
+ movdqa %xmm0,0(%r11)
+ movdqa %xmm1,16(%r11)
+ movdqa %xmm3,32(%r11)
+ movdqa %xmm4,48(%r11)
+ leaq 64(%r11),%r11
+ decq %rbp
+ jnz .Lsqr8x_copy_n
+
+ pxor %xmm0,%xmm0
+.byte 102,72,15,110,207
+.byte 102,73,15,110,218
+ call bn_sqr8x_internal
+
+ pxor %xmm0,%xmm0
+ leaq 48(%rsp),%rax
+ leaq 64(%rsp,%r9,2),%rdx
+ shrq $3+2,%r9
+ movq 40(%rsp),%rsi
+ jmp .Lsqr8x_zero
+
+.align 32
+.Lsqr8x_zero:
+ movdqa %xmm0,0(%rax)
+ movdqa %xmm0,16(%rax)
+ movdqa %xmm0,32(%rax)
+ movdqa %xmm0,48(%rax)
+ leaq 64(%rax),%rax
+ movdqa %xmm0,0(%rdx)
+ movdqa %xmm0,16(%rdx)
+ movdqa %xmm0,32(%rdx)
+ movdqa %xmm0,48(%rdx)
+ leaq 64(%rdx),%rdx
+ decq %r9
+ jnz .Lsqr8x_zero
+
+ movq $1,%rax
+ movq -48(%rsi),%r15
+ movq -40(%rsi),%r14
+ movq -32(%rsi),%r13
+ movq -24(%rsi),%r12
+ movq -16(%rsi),%rbp
+ movq -8(%rsi),%rbx
+ leaq (%rsi),%rsp
+.Lsqr8x_epilogue:
+ .byte 0xf3,0xc3
+.size bn_sqr8x_mont,.-bn_sqr8x_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
+.align 16
+#endif
diff --git a/linux-x86_64/crypto/bn/x86_64-mont5.S b/linux-x86_64/crypto/bn/x86_64-mont5.S
new file mode 100644
index 0000000..357bc11
--- /dev/null
+++ b/linux-x86_64/crypto/bn/x86_64-mont5.S
@@ -0,0 +1,1822 @@
+#if defined(__x86_64__)
+.text
+
+
+
+.globl bn_mul_mont_gather5
+.hidden bn_mul_mont_gather5
+.type bn_mul_mont_gather5,@function
+.align 64
+bn_mul_mont_gather5:
+ testl $7,%r9d
+ jnz .Lmul_enter
+ jmp .Lmul4x_enter
+
+.align 16
+.Lmul_enter:
+ movl %r9d,%r9d
+ movq %rsp,%rax
+ movl 8(%rsp),%r10d
+ pushq %rbx
+ pushq %rbp
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ pushq %r15
+ leaq 2(%r9),%r11
+ negq %r11
+ leaq (%rsp,%r11,8),%rsp
+ andq $-1024,%rsp
+
+ movq %rax,8(%rsp,%r9,8)
+.Lmul_body:
+ movq %rdx,%r12
+ movq %r10,%r11
+ shrq $3,%r10
+ andq $7,%r11
+ notq %r10
+ leaq .Lmagic_masks(%rip),%rax
+ andq $3,%r10
+ leaq 96(%r12,%r11,8),%r12
+ movq 0(%rax,%r10,8),%xmm4
+ movq 8(%rax,%r10,8),%xmm5
+ movq 16(%rax,%r10,8),%xmm6
+ movq 24(%rax,%r10,8),%xmm7
+
+ movq -96(%r12),%xmm0
+ movq -32(%r12),%xmm1
+ pand %xmm4,%xmm0
+ movq 32(%r12),%xmm2
+ pand %xmm5,%xmm1
+ movq 96(%r12),%xmm3
+ pand %xmm6,%xmm2
+ por %xmm1,%xmm0
+ pand %xmm7,%xmm3
+ por %xmm2,%xmm0
+ leaq 256(%r12),%r12
+ por %xmm3,%xmm0
+
+.byte 102,72,15,126,195
+
+ movq (%r8),%r8
+ movq (%rsi),%rax
+
+ xorq %r14,%r14
+ xorq %r15,%r15
+
+ movq -96(%r12),%xmm0
+ movq -32(%r12),%xmm1
+ pand %xmm4,%xmm0
+ movq 32(%r12),%xmm2
+ pand %xmm5,%xmm1
+
+ movq %r8,%rbp
+ mulq %rbx
+ movq %rax,%r10
+ movq (%rcx),%rax
+
+ movq 96(%r12),%xmm3
+ pand %xmm6,%xmm2
+ por %xmm1,%xmm0
+ pand %xmm7,%xmm3
+
+ imulq %r10,%rbp
+ movq %rdx,%r11
+
+ por %xmm2,%xmm0
+ leaq 256(%r12),%r12
+ por %xmm3,%xmm0
+
+ 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
+ jne .L1st
+
+.byte 102,72,15,126,195
+
+ 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:
+ xorq %r15,%r15
+ movq %r8,%rbp
+ movq (%rsp),%r10
+
+ movq -96(%r12),%xmm0
+ movq -32(%r12),%xmm1
+ pand %xmm4,%xmm0
+ movq 32(%r12),%xmm2
+ pand %xmm5,%xmm1
+
+ mulq %rbx
+ addq %rax,%r10
+ movq (%rcx),%rax
+ adcq $0,%rdx
+
+ movq 96(%r12),%xmm3
+ pand %xmm6,%xmm2
+ por %xmm1,%xmm0
+ pand %xmm7,%xmm3
+
+ imulq %r10,%rbp
+ movq %rdx,%r11
+
+ por %xmm2,%xmm0
+ leaq 256(%r12),%r12
+ por %xmm3,%xmm0
+
+ 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
+ jne .Linner
+
+.byte 102,72,15,126,195
+
+ 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
+ jb .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
+ movq %r9,%r15
+.align 16
+.Lcopy:
+ movq (%rsp,%r14,8),%rsi
+ movq (%rdi,%r14,8),%rcx
+ xorq %rcx,%rsi
+ andq %rax,%rsi
+ xorq %rcx,%rsi
+ movq %r14,(%rsp,%r14,8)
+ movq %rsi,(%rdi,%r14,8)
+ leaq 1(%r14),%r14
+ subq $1,%r15
+ jnz .Lcopy
+
+ movq 8(%rsp,%r9,8),%rsi
+ movq $1,%rax
+ movq -48(%rsi),%r15
+ movq -40(%rsi),%r14
+ movq -32(%rsi),%r13
+ movq -24(%rsi),%r12
+ movq -16(%rsi),%rbp
+ movq -8(%rsi),%rbx
+ leaq (%rsi),%rsp
+.Lmul_epilogue:
+ .byte 0xf3,0xc3
+.size bn_mul_mont_gather5,.-bn_mul_mont_gather5
+.type bn_mul4x_mont_gather5,@function
+.align 32
+bn_mul4x_mont_gather5:
+.Lmul4x_enter:
+.byte 0x67
+ movq %rsp,%rax
+ pushq %rbx
+ pushq %rbp
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ pushq %r15
+.byte 0x67
+ movl %r9d,%r10d
+ shll $3,%r9d
+ shll $3+2,%r10d
+ negq %r9
+
+
+
+
+
+
+
+
+ leaq -64(%rsp,%r9,2),%r11
+ subq %rsi,%r11
+ andq $4095,%r11
+ cmpq %r11,%r10
+ jb .Lmul4xsp_alt
+ subq %r11,%rsp
+ leaq -64(%rsp,%r9,2),%rsp
+ jmp .Lmul4xsp_done
+
+.align 32
+.Lmul4xsp_alt:
+ leaq 4096-64(,%r9,2),%r10
+ leaq -64(%rsp,%r9,2),%rsp
+ subq %r10,%r11
+ movq $0,%r10
+ cmovcq %r10,%r11
+ subq %r11,%rsp
+.Lmul4xsp_done:
+ andq $-64,%rsp
+ negq %r9
+
+ movq %rax,40(%rsp)
+.Lmul4x_body:
+
+ call mul4x_internal
+
+ movq 40(%rsp),%rsi
+ movq $1,%rax
+ movq -48(%rsi),%r15
+ movq -40(%rsi),%r14
+ movq -32(%rsi),%r13
+ movq -24(%rsi),%r12
+ movq -16(%rsi),%rbp
+ movq -8(%rsi),%rbx
+ leaq (%rsi),%rsp
+.Lmul4x_epilogue:
+ .byte 0xf3,0xc3
+.size bn_mul4x_mont_gather5,.-bn_mul4x_mont_gather5
+
+.type mul4x_internal,@function
+.align 32
+mul4x_internal:
+ shlq $5,%r9
+ movl 8(%rax),%r10d
+ leaq 256(%rdx,%r9,1),%r13
+ shrq $5,%r9
+ movq %r10,%r11
+ shrq $3,%r10
+ andq $7,%r11
+ notq %r10
+ leaq .Lmagic_masks(%rip),%rax
+ andq $3,%r10
+ leaq 96(%rdx,%r11,8),%r12
+ movq 0(%rax,%r10,8),%xmm4
+ movq 8(%rax,%r10,8),%xmm5
+ addq $7,%r11
+ movq 16(%rax,%r10,8),%xmm6
+ movq 24(%rax,%r10,8),%xmm7
+ andq $7,%r11
+
+ movq -96(%r12),%xmm0
+ leaq 256(%r12),%r14
+ movq -32(%r12),%xmm1
+ pand %xmm4,%xmm0
+ movq 32(%r12),%xmm2
+ pand %xmm5,%xmm1
+ movq 96(%r12),%xmm3
+ pand %xmm6,%xmm2
+.byte 0x67
+ por %xmm1,%xmm0
+ movq -96(%r14),%xmm1
+.byte 0x67
+ pand %xmm7,%xmm3
+.byte 0x67
+ por %xmm2,%xmm0
+ movq -32(%r14),%xmm2
+.byte 0x67
+ pand %xmm4,%xmm1
+.byte 0x67
+ por %xmm3,%xmm0
+ movq 32(%r14),%xmm3
+
+.byte 102,72,15,126,195
+ movq 96(%r14),%xmm0
+ movq %r13,16+8(%rsp)
+ movq %rdi,56+8(%rsp)
+
+ movq (%r8),%r8
+ movq (%rsi),%rax
+ leaq (%rsi,%r9,1),%rsi
+ negq %r9
+
+ movq %r8,%rbp
+ mulq %rbx
+ movq %rax,%r10
+ movq (%rcx),%rax
+
+ pand %xmm5,%xmm2
+ pand %xmm6,%xmm3
+ por %xmm2,%xmm1
+
+ imulq %r10,%rbp
+
+
+
+
+
+
+
+ leaq 64+8(%rsp,%r11,8),%r14
+ movq %rdx,%r11
+
+ pand %xmm7,%xmm0
+ por %xmm3,%xmm1
+ leaq 512(%r12),%r12
+ por %xmm1,%xmm0
+
+ mulq %rbp
+ addq %rax,%r10
+ movq 8(%rsi,%r9,1),%rax
+ adcq $0,%rdx
+ movq %rdx,%rdi
+
+ mulq %rbx
+ addq %rax,%r11
+ movq 16(%rcx),%rax
+ adcq $0,%rdx
+ movq %rdx,%r10
+
+ mulq %rbp
+ addq %rax,%rdi
+ movq 16(%rsi,%r9,1),%rax
+ adcq $0,%rdx
+ addq %r11,%rdi
+ leaq 32(%r9),%r15
+ leaq 64(%rcx),%rcx
+ adcq $0,%rdx
+ movq %rdi,(%r14)
+ movq %rdx,%r13
+ jmp .L1st4x
+
+.align 32
+.L1st4x:
+ mulq %rbx
+ addq %rax,%r10
+ movq -32(%rcx),%rax
+ leaq 32(%r14),%r14
+ adcq $0,%rdx
+ movq %rdx,%r11
+
+ mulq %rbp
+ addq %rax,%r13
+ movq -8(%rsi,%r15,1),%rax
+ adcq $0,%rdx
+ addq %r10,%r13
+ adcq $0,%rdx
+ movq %r13,-24(%r14)
+ movq %rdx,%rdi
+
+ mulq %rbx
+ addq %rax,%r11
+ movq -16(%rcx),%rax
+ adcq $0,%rdx
+ movq %rdx,%r10
+
+ mulq %rbp
+ addq %rax,%rdi
+ movq (%rsi,%r15,1),%rax
+ adcq $0,%rdx
+ addq %r11,%rdi
+ adcq $0,%rdx
+ movq %rdi,-16(%r14)
+ movq %rdx,%r13
+
+ mulq %rbx
+ addq %rax,%r10
+ movq 0(%rcx),%rax
+ adcq $0,%rdx
+ movq %rdx,%r11
+
+ mulq %rbp
+ addq %rax,%r13
+ movq 8(%rsi,%r15,1),%rax
+ adcq $0,%rdx
+ addq %r10,%r13
+ adcq $0,%rdx
+ movq %r13,-8(%r14)
+ movq %rdx,%rdi
+
+ mulq %rbx
+ addq %rax,%r11
+ movq 16(%rcx),%rax
+ adcq $0,%rdx
+ movq %rdx,%r10
+
+ mulq %rbp
+ addq %rax,%rdi
+ movq 16(%rsi,%r15,1),%rax
+ adcq $0,%rdx
+ addq %r11,%rdi
+ leaq 64(%rcx),%rcx
+ adcq $0,%rdx
+ movq %rdi,(%r14)
+ movq %rdx,%r13
+
+ addq $32,%r15
+ jnz .L1st4x
+
+ mulq %rbx
+ addq %rax,%r10
+ movq -32(%rcx),%rax
+ leaq 32(%r14),%r14
+ adcq $0,%rdx
+ movq %rdx,%r11
+
+ mulq %rbp
+ addq %rax,%r13
+ movq -8(%rsi),%rax
+ adcq $0,%rdx
+ addq %r10,%r13
+ adcq $0,%rdx
+ movq %r13,-24(%r14)
+ movq %rdx,%rdi
+
+ mulq %rbx
+ addq %rax,%r11
+ movq -16(%rcx),%rax
+ adcq $0,%rdx
+ movq %rdx,%r10
+
+ mulq %rbp
+ addq %rax,%rdi
+ movq (%rsi,%r9,1),%rax
+ adcq $0,%rdx
+ addq %r11,%rdi
+ adcq $0,%rdx
+ movq %rdi,-16(%r14)
+ movq %rdx,%r13
+
+.byte 102,72,15,126,195
+ leaq (%rcx,%r9,2),%rcx
+
+ xorq %rdi,%rdi
+ addq %r10,%r13
+ adcq $0,%rdi
+ movq %r13,-8(%r14)
+
+ jmp .Louter4x
+
+.align 32
+.Louter4x:
+ movq (%r14,%r9,1),%r10
+ movq %r8,%rbp
+ mulq %rbx
+ addq %rax,%r10
+ movq (%rcx),%rax
+ adcq $0,%rdx
+
+ movq -96(%r12),%xmm0
+ movq -32(%r12),%xmm1
+ pand %xmm4,%xmm0
+ movq 32(%r12),%xmm2
+ pand %xmm5,%xmm1
+ movq 96(%r12),%xmm3
+
+ imulq %r10,%rbp
+.byte 0x67
+ movq %rdx,%r11
+ movq %rdi,(%r14)
+
+ pand %xmm6,%xmm2
+ por %xmm1,%xmm0
+ pand %xmm7,%xmm3
+ por %xmm2,%xmm0
+ leaq (%r14,%r9,1),%r14
+ leaq 256(%r12),%r12
+ por %xmm3,%xmm0
+
+ mulq %rbp
+ addq %rax,%r10
+ movq 8(%rsi,%r9,1),%rax
+ adcq $0,%rdx
+ movq %rdx,%rdi
+
+ mulq %rbx
+ addq %rax,%r11
+ movq 16(%rcx),%rax
+ adcq $0,%rdx
+ addq 8(%r14),%r11
+ adcq $0,%rdx
+ movq %rdx,%r10
+
+ mulq %rbp
+ addq %rax,%rdi
+ movq 16(%rsi,%r9,1),%rax
+ adcq $0,%rdx
+ addq %r11,%rdi
+ leaq 32(%r9),%r15
+ leaq 64(%rcx),%rcx
+ adcq $0,%rdx
+ movq %rdx,%r13
+ jmp .Linner4x
+
+.align 32
+.Linner4x:
+ mulq %rbx
+ addq %rax,%r10
+ movq -32(%rcx),%rax
+ adcq $0,%rdx
+ addq 16(%r14),%r10
+ leaq 32(%r14),%r14
+ adcq $0,%rdx
+ movq %rdx,%r11
+
+ mulq %rbp
+ addq %rax,%r13
+ movq -8(%rsi,%r15,1),%rax
+ adcq $0,%rdx
+ addq %r10,%r13
+ adcq $0,%rdx
+ movq %rdi,-32(%r14)
+ movq %rdx,%rdi
+
+ mulq %rbx
+ addq %rax,%r11
+ movq -16(%rcx),%rax
+ adcq $0,%rdx
+ addq -8(%r14),%r11
+ adcq $0,%rdx
+ movq %rdx,%r10
+
+ mulq %rbp
+ addq %rax,%rdi
+ movq (%rsi,%r15,1),%rax
+ adcq $0,%rdx
+ addq %r11,%rdi
+ adcq $0,%rdx
+ movq %r13,-24(%r14)
+ movq %rdx,%r13
+
+ mulq %rbx
+ addq %rax,%r10
+ movq 0(%rcx),%rax
+ adcq $0,%rdx
+ addq (%r14),%r10
+ adcq $0,%rdx
+ movq %rdx,%r11
+
+ mulq %rbp
+ addq %rax,%r13
+ movq 8(%rsi,%r15,1),%rax
+ adcq $0,%rdx
+ addq %r10,%r13
+ adcq $0,%rdx
+ movq %rdi,-16(%r14)
+ movq %rdx,%rdi
+
+ mulq %rbx
+ addq %rax,%r11
+ movq 16(%rcx),%rax
+ adcq $0,%rdx
+ addq 8(%r14),%r11
+ adcq $0,%rdx
+ movq %rdx,%r10
+
+ mulq %rbp
+ addq %rax,%rdi
+ movq 16(%rsi,%r15,1),%rax
+ adcq $0,%rdx
+ addq %r11,%rdi
+ leaq 64(%rcx),%rcx
+ adcq $0,%rdx
+ movq %r13,-8(%r14)
+ movq %rdx,%r13
+
+ addq $32,%r15
+ jnz .Linner4x
+
+ mulq %rbx
+ addq %rax,%r10
+ movq -32(%rcx),%rax
+ adcq $0,%rdx
+ addq 16(%r14),%r10
+ leaq 32(%r14),%r14
+ adcq $0,%rdx
+ movq %rdx,%r11
+
+ mulq %rbp
+ addq %rax,%r13
+ movq -8(%rsi),%rax
+ adcq $0,%rdx
+ addq %r10,%r13
+ adcq $0,%rdx
+ movq %rdi,-32(%r14)
+ movq %rdx,%rdi
+
+ mulq %rbx
+ addq %rax,%r11
+ movq %rbp,%rax
+ movq -16(%rcx),%rbp
+ adcq $0,%rdx
+ addq -8(%r14),%r11
+ adcq $0,%rdx
+ movq %rdx,%r10
+
+ mulq %rbp
+ addq %rax,%rdi
+ movq (%rsi,%r9,1),%rax
+ adcq $0,%rdx
+ addq %r11,%rdi
+ adcq $0,%rdx
+ movq %r13,-24(%r14)
+ movq %rdx,%r13
+
+.byte 102,72,15,126,195
+ movq %rdi,-16(%r14)
+ leaq (%rcx,%r9,2),%rcx
+
+ xorq %rdi,%rdi
+ addq %r10,%r13
+ adcq $0,%rdi
+ addq (%r14),%r13
+ adcq $0,%rdi
+ movq %r13,-8(%r14)
+
+ cmpq 16+8(%rsp),%r12
+ jb .Louter4x
+ subq %r13,%rbp
+ adcq %r15,%r15
+ orq %r15,%rdi
+ xorq $1,%rdi
+ leaq (%r14,%r9,1),%rbx
+ leaq (%rcx,%rdi,8),%rbp
+ movq %r9,%rcx
+ sarq $3+2,%rcx
+ movq 56+8(%rsp),%rdi
+ jmp .Lsqr4x_sub
+.size mul4x_internal,.-mul4x_internal
+.globl bn_power5
+.hidden bn_power5
+.type bn_power5,@function
+.align 32
+bn_power5:
+ movq %rsp,%rax
+ pushq %rbx
+ pushq %rbp
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ pushq %r15
+ movl %r9d,%r10d
+ shll $3,%r9d
+ shll $3+2,%r10d
+ negq %r9
+ movq (%r8),%r8
+
+
+
+
+
+
+
+ leaq -64(%rsp,%r9,2),%r11
+ subq %rsi,%r11
+ andq $4095,%r11
+ cmpq %r11,%r10
+ jb .Lpwr_sp_alt
+ subq %r11,%rsp
+ leaq -64(%rsp,%r9,2),%rsp
+ jmp .Lpwr_sp_done
+
+.align 32
+.Lpwr_sp_alt:
+ leaq 4096-64(,%r9,2),%r10
+ leaq -64(%rsp,%r9,2),%rsp
+ subq %r10,%r11
+ movq $0,%r10
+ cmovcq %r10,%r11
+ subq %r11,%rsp
+.Lpwr_sp_done:
+ andq $-64,%rsp
+ movq %r9,%r10
+ negq %r9
+
+
+
+
+
+
+
+
+
+
+ movq %r8,32(%rsp)
+ movq %rax,40(%rsp)
+.Lpower5_body:
+.byte 102,72,15,110,207
+.byte 102,72,15,110,209
+.byte 102,73,15,110,218
+.byte 102,72,15,110,226
+
+ call __bn_sqr8x_internal
+ call __bn_sqr8x_internal
+ call __bn_sqr8x_internal
+ call __bn_sqr8x_internal
+ call __bn_sqr8x_internal
+
+.byte 102,72,15,126,209
+.byte 102,72,15,126,226
+ movq %rsi,%rdi
+ movq 40(%rsp),%rax
+ leaq 32(%rsp),%r8
+
+ call mul4x_internal
+
+ movq 40(%rsp),%rsi
+ movq $1,%rax
+ movq -48(%rsi),%r15
+ movq -40(%rsi),%r14
+ movq -32(%rsi),%r13
+ movq -24(%rsi),%r12
+ movq -16(%rsi),%rbp
+ movq -8(%rsi),%rbx
+ leaq (%rsi),%rsp
+.Lpower5_epilogue:
+ .byte 0xf3,0xc3
+.size bn_power5,.-bn_power5
+
+.globl bn_sqr8x_internal
+.hidden bn_sqr8x_internal
+.hidden bn_sqr8x_internal
+.type bn_sqr8x_internal,@function
+.align 32
+bn_sqr8x_internal:
+__bn_sqr8x_internal:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ leaq 32(%r10),%rbp
+ leaq (%rsi,%r9,1),%rsi
+
+ movq %r9,%rcx
+
+
+ movq -32(%rsi,%rbp,1),%r14
+ leaq 48+8(%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)
+
+ mulq %r14
+ addq %rax,%r11
+ movq %rbx,%rax
+ adcq $0,%rdx
+ movq %r11,-16(%rdi,%rbp,1)
+ movq %rdx,%r10
+
+
+ movq -8(%rsi,%rbp,1),%rbx
+ mulq %r15
+ movq %rax,%r12
+ movq %rbx,%rax
+ movq %rdx,%r13
+
+ leaq (%rbp),%rcx
+ mulq %r14
+ addq %rax,%r10
+ movq %rbx,%rax
+ movq %rdx,%r11
+ adcq $0,%r11
+ addq %r12,%r10
+ adcq $0,%r11
+ movq %r10,-8(%rdi,%rcx,1)
+ jmp .Lsqr4x_1st
+
+.align 32
+.Lsqr4x_1st:
+ movq (%rsi,%rcx,1),%rbx
+ mulq %r15
+ addq %rax,%r13
+ movq %rbx,%rax
+ movq %rdx,%r12
+ adcq $0,%r12
+
+ mulq %r14
+ addq %rax,%r11
+ movq %rbx,%rax
+ movq 8(%rsi,%rcx,1),%rbx
+ movq %rdx,%r10
+ adcq $0,%r10
+ addq %r13,%r11
+ adcq $0,%r10
+
+
+ mulq %r15
+ addq %rax,%r12
+ movq %rbx,%rax
+ movq %r11,(%rdi,%rcx,1)
+ movq %rdx,%r13
+ adcq $0,%r13
+
+ mulq %r14
+ addq %rax,%r10
+ movq %rbx,%rax
+ movq 16(%rsi,%rcx,1),%rbx
+ movq %rdx,%r11
+ adcq $0,%r11
+ addq %r12,%r10
+ adcq $0,%r11
+
+ mulq %r15
+ addq %rax,%r13
+ movq %rbx,%rax
+ movq %r10,8(%rdi,%rcx,1)
+ movq %rdx,%r12
+ adcq $0,%r12
+
+ mulq %r14
+ addq %rax,%r11
+ movq %rbx,%rax
+ movq 24(%rsi,%rcx,1),%rbx
+ movq %rdx,%r10
+ adcq $0,%r10
+ addq %r13,%r11
+ adcq $0,%r10
+
+
+ mulq %r15
+ addq %rax,%r12
+ movq %rbx,%rax
+ movq %r11,16(%rdi,%rcx,1)
+ movq %rdx,%r13
+ adcq $0,%r13
+ leaq 32(%rcx),%rcx
+
+ mulq %r14
+ addq %rax,%r10
+ movq %rbx,%rax
+ movq %rdx,%r11
+ adcq $0,%r11
+ addq %r12,%r10
+ adcq $0,%r11
+ movq %r10,-8(%rdi,%rcx,1)
+
+ cmpq $0,%rcx
+ jne .Lsqr4x_1st
+
+ mulq %r15
+ addq %rax,%r13
+ leaq 16(%rbp),%rbp
+ adcq $0,%rdx
+ addq %r11,%r13
+ adcq $0,%rdx
+
+ movq %r13,(%rdi)
+ movq %rdx,%r12
+ movq %rdx,8(%rdi)
+ jmp .Lsqr4x_outer
+
+.align 32
+.Lsqr4x_outer:
+ movq -32(%rsi,%rbp,1),%r14
+ leaq 48+8(%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 -24(%rdi,%rbp,1),%r10
+ addq %rax,%r10
+ movq %rbx,%rax
+ adcq $0,%rdx
+ movq %r10,-24(%rdi,%rbp,1)
+ movq %rdx,%r11
+
+ mulq %r14
+ addq %rax,%r11
+ movq %rbx,%rax
+ adcq $0,%rdx
+ addq -16(%rdi,%rbp,1),%r11
+ movq %rdx,%r10
+ adcq $0,%r10
+ movq %r11,-16(%rdi,%rbp,1)
+
+ xorq %r12,%r12
+
+ movq -8(%rsi,%rbp,1),%rbx
+ mulq %r15
+ addq %rax,%r12
+ movq %rbx,%rax
+ adcq $0,%rdx
+ addq -8(%rdi,%rbp,1),%r12
+ movq %rdx,%r13
+ adcq $0,%r13
+
+ mulq %r14
+ addq %rax,%r10
+ movq %rbx,%rax
+ adcq $0,%rdx
+ addq %r12,%r10
+ movq %rdx,%r11
+ adcq $0,%r11
+ movq %r10,-8(%rdi,%rbp,1)
+
+ leaq (%rbp),%rcx
+ jmp .Lsqr4x_inner
+
+.align 32
+.Lsqr4x_inner:
+ movq (%rsi,%rcx,1),%rbx
+ mulq %r15
+ addq %rax,%r13
+ movq %rbx,%rax
+ movq %rdx,%r12
+ adcq $0,%r12
+ addq (%rdi,%rcx,1),%r13
+ adcq $0,%r12
+
+.byte 0x67
+ mulq %r14
+ addq %rax,%r11
+ movq %rbx,%rax
+ movq 8(%rsi,%rcx,1),%rbx
+ movq %rdx,%r10
+ adcq $0,%r10
+ addq %r13,%r11
+ adcq $0,%r10
+
+ mulq %r15
+ addq %rax,%r12
+ movq %r11,(%rdi,%rcx,1)
+ movq %rbx,%rax
+ movq %rdx,%r13
+ adcq $0,%r13
+ addq 8(%rdi,%rcx,1),%r12
+ leaq 16(%rcx),%rcx
+ adcq $0,%r13
+
+ mulq %r14
+ addq %rax,%r10
+ movq %rbx,%rax
+ adcq $0,%rdx
+ addq %r12,%r10
+ movq %rdx,%r11
+ adcq $0,%r11
+ movq %r10,-8(%rdi,%rcx,1)
+
+ cmpq $0,%rcx
+ jne .Lsqr4x_inner
+
+.byte 0x67
+ mulq %r15
+ addq %rax,%r13
+ adcq $0,%rdx
+ addq %r11,%r13
+ adcq $0,%rdx
+
+ movq %r13,(%rdi)
+ movq %rdx,%r12
+ movq %rdx,8(%rdi)
+
+ addq $16,%rbp
+ jnz .Lsqr4x_outer
+
+
+ movq -32(%rsi),%r14
+ leaq 48+8(%rsp,%r9,2),%rdi
+ movq -24(%rsi),%rax
+ leaq -32(%rdi,%rbp,1),%rdi
+ movq -16(%rsi),%rbx
+ movq %rax,%r15
+
+ mulq %r14
+ addq %rax,%r10
+ movq %rbx,%rax
+ movq %rdx,%r11
+ adcq $0,%r11
+
+ mulq %r14
+ addq %rax,%r11
+ movq %rbx,%rax
+ movq %r10,-24(%rdi)
+ movq %rdx,%r10
+ adcq $0,%r10
+ addq %r13,%r11
+ movq -8(%rsi),%rbx
+ adcq $0,%r10
+
+ mulq %r15
+ addq %rax,%r12
+ movq %rbx,%rax
+ movq %r11,-16(%rdi)
+ movq %rdx,%r13
+ adcq $0,%r13
+
+ mulq %r14
+ addq %rax,%r10
+ movq %rbx,%rax
+ movq %rdx,%r11
+ adcq $0,%r11
+ addq %r12,%r10
+ adcq $0,%r11
+ movq %r10,-8(%rdi)
+
+ mulq %r15
+ addq %rax,%r13
+ movq -16(%rsi),%rax
+ adcq $0,%rdx
+ addq %r11,%r13
+ adcq $0,%rdx
+
+ movq %r13,(%rdi)
+ movq %rdx,%r12
+ movq %rdx,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 48+8(%rsp),%rdi
+ xorq %r10,%r10
+ movq 8(%rdi),%r11
+
+ 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 24(%rdi),%r11
+ adcq %rax,%r12
+ movq -8(%rsi,%rbp,1),%rax
+ movq %r12,(%rdi)
+ adcq %rdx,%r13
+
+ leaq (%r14,%r10,2),%rbx
+ movq %r13,8(%rdi)
+ sbbq %r15,%r15
+ shrq $63,%r10
+ leaq (%rcx,%r11,2),%r8
+ shrq $63,%r11
+ orq %r10,%r8
+ movq 32(%rdi),%r10
+ movq %r11,%r14
+ mulq %rax
+ negq %r15
+ movq 40(%rdi),%r11
+ adcq %rax,%rbx
+ movq 0(%rsi,%rbp,1),%rax
+ movq %rbx,16(%rdi)
+ adcq %rdx,%r8
+ leaq 16(%rbp),%rbp
+ movq %r8,24(%rdi)
+ sbbq %r15,%r15
+ leaq 64(%rdi),%rdi
+ jmp .Lsqr4x_shift_n_add
+
+.align 32
+.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,%rbp,1),%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
+ movq 0(%rdi),%r10
+ movq %r11,%r14
+ mulq %rax
+ negq %r15
+ movq 8(%rdi),%r11
+ adcq %rax,%rbx
+ movq 0(%rsi,%rbp,1),%rax
+ movq %rbx,-16(%rdi)
+ adcq %rdx,%r8
+
+ leaq (%r14,%r10,2),%r12
+ movq %r8,-8(%rdi)
+ sbbq %r15,%r15
+ 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 24(%rdi),%r11
+ adcq %rax,%r12
+ movq 8(%rsi,%rbp,1),%rax
+ movq %r12,0(%rdi)
+ adcq %rdx,%r13
+
+ leaq (%r14,%r10,2),%rbx
+ movq %r13,8(%rdi)
+ sbbq %r15,%r15
+ shrq $63,%r10
+ leaq (%rcx,%r11,2),%r8
+ shrq $63,%r11
+ orq %r10,%r8
+ movq 32(%rdi),%r10
+ movq %r11,%r14
+ mulq %rax
+ negq %r15
+ movq 40(%rdi),%r11
+ adcq %rax,%rbx
+ movq 16(%rsi,%rbp,1),%rax
+ movq %rbx,16(%rdi)
+ adcq %rdx,%r8
+ movq %r8,24(%rdi)
+ sbbq %r15,%r15
+ leaq 64(%rdi),%rdi
+ addq $32,%rbp
+ jnz .Lsqr4x_shift_n_add
+
+ leaq (%r14,%r10,2),%r12
+.byte 0x67
+ 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)
+.byte 102,72,15,126,213
+sqr8x_reduction:
+ xorq %rax,%rax
+ leaq (%rbp,%r9,2),%rcx
+ leaq 48+8(%rsp,%r9,2),%rdx
+ movq %rcx,0+8(%rsp)
+ leaq 48+8(%rsp,%r9,1),%rdi
+ movq %rdx,8+8(%rsp)
+ negq %r9
+ jmp .L8x_reduction_loop
+
+.align 32
+.L8x_reduction_loop:
+ leaq (%rdi,%r9,1),%rdi
+.byte 0x66
+ movq 0(%rdi),%rbx
+ 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
+ movq %rax,(%rdx)
+ leaq 64(%rdi),%rdi
+
+.byte 0x67
+ movq %rbx,%r8
+ imulq 32+8(%rsp),%rbx
+ movq 0(%rbp),%rax
+ movl $8,%ecx
+ jmp .L8x_reduce
+
+.align 32
+.L8x_reduce:
+ mulq %rbx
+ movq 16(%rbp),%rax
+ negq %r8
+ movq %rdx,%r8
+ adcq $0,%r8
+
+ mulq %rbx
+ addq %rax,%r9
+ movq 32(%rbp),%rax
+ adcq $0,%rdx
+ addq %r9,%r8
+ movq %rbx,48-8+8(%rsp,%rcx,8)
+ movq %rdx,%r9
+ adcq $0,%r9
+
+ mulq %rbx
+ addq %rax,%r10
+ movq 48(%rbp),%rax
+ adcq $0,%rdx
+ addq %r10,%r9
+ movq 32+8(%rsp),%rsi
+ movq %rdx,%r10
+ adcq $0,%r10
+
+ mulq %rbx
+ addq %rax,%r11
+ movq 64(%rbp),%rax
+ adcq $0,%rdx
+ imulq %r8,%rsi
+ addq %r11,%r10
+ movq %rdx,%r11
+ adcq $0,%r11
+
+ mulq %rbx
+ addq %rax,%r12
+ movq 80(%rbp),%rax
+ adcq $0,%rdx
+ addq %r12,%r11
+ movq %rdx,%r12
+ adcq $0,%r12
+
+ mulq %rbx
+ addq %rax,%r13
+ movq 96(%rbp),%rax
+ adcq $0,%rdx
+ addq %r13,%r12
+ movq %rdx,%r13
+ adcq $0,%r13
+
+ mulq %rbx
+ addq %rax,%r14
+ movq 112(%rbp),%rax
+ adcq $0,%rdx
+ addq %r14,%r13
+ movq %rdx,%r14
+ adcq $0,%r14
+
+ mulq %rbx
+ movq %rsi,%rbx
+ addq %rax,%r15
+ movq 0(%rbp),%rax
+ adcq $0,%rdx
+ addq %r15,%r14
+ movq %rdx,%r15
+ adcq $0,%r15
+
+ decl %ecx
+ jnz .L8x_reduce
+
+ leaq 128(%rbp),%rbp
+ xorq %rax,%rax
+ movq 8+8(%rsp),%rdx
+ cmpq 0+8(%rsp),%rbp
+ jae .L8x_no_tail
+
+.byte 0x66
+ addq 0(%rdi),%r8
+ adcq 8(%rdi),%r9
+ adcq 16(%rdi),%r10
+ adcq 24(%rdi),%r11
+ adcq 32(%rdi),%r12
+ adcq 40(%rdi),%r13
+ adcq 48(%rdi),%r14
+ adcq 56(%rdi),%r15
+ sbbq %rsi,%rsi
+
+ movq 48+56+8(%rsp),%rbx
+ movl $8,%ecx
+ movq 0(%rbp),%rax
+ jmp .L8x_tail
+
+.align 32
+.L8x_tail:
+ mulq %rbx
+ addq %rax,%r8
+ movq 16(%rbp),%rax
+ movq %r8,(%rdi)
+ movq %rdx,%r8
+ adcq $0,%r8
+
+ mulq %rbx
+ addq %rax,%r9
+ movq 32(%rbp),%rax
+ adcq $0,%rdx
+ addq %r9,%r8
+ leaq 8(%rdi),%rdi
+ movq %rdx,%r9
+ adcq $0,%r9
+
+ mulq %rbx
+ addq %rax,%r10
+ movq 48(%rbp),%rax
+ adcq $0,%rdx
+ addq %r10,%r9
+ movq %rdx,%r10
+ adcq $0,%r10
+
+ mulq %rbx
+ addq %rax,%r11
+ movq 64(%rbp),%rax
+ adcq $0,%rdx
+ addq %r11,%r10
+ movq %rdx,%r11
+ adcq $0,%r11
+
+ mulq %rbx
+ addq %rax,%r12
+ movq 80(%rbp),%rax
+ adcq $0,%rdx
+ addq %r12,%r11
+ movq %rdx,%r12
+ adcq $0,%r12
+
+ mulq %rbx
+ addq %rax,%r13
+ movq 96(%rbp),%rax
+ adcq $0,%rdx
+ addq %r13,%r12
+ movq %rdx,%r13
+ adcq $0,%r13
+
+ mulq %rbx
+ addq %rax,%r14
+ movq 112(%rbp),%rax
+ adcq $0,%rdx
+ addq %r14,%r13
+ movq %rdx,%r14
+ adcq $0,%r14
+
+ mulq %rbx
+ movq 48-16+8(%rsp,%rcx,8),%rbx
+ addq %rax,%r15
+ adcq $0,%rdx
+ addq %r15,%r14
+ movq 0(%rbp),%rax
+ movq %rdx,%r15
+ adcq $0,%r15
+
+ decl %ecx
+ jnz .L8x_tail
+
+ leaq 128(%rbp),%rbp
+ movq 8+8(%rsp),%rdx
+ cmpq 0+8(%rsp),%rbp
+ jae .L8x_tail_done
+
+ movq 48+56+8(%rsp),%rbx
+ negq %rsi
+ movq 0(%rbp),%rax
+ adcq 0(%rdi),%r8
+ adcq 8(%rdi),%r9
+ adcq 16(%rdi),%r10
+ adcq 24(%rdi),%r11
+ adcq 32(%rdi),%r12
+ adcq 40(%rdi),%r13
+ adcq 48(%rdi),%r14
+ adcq 56(%rdi),%r15
+ sbbq %rsi,%rsi
+
+ movl $8,%ecx
+ jmp .L8x_tail
+
+.align 32
+.L8x_tail_done:
+ addq (%rdx),%r8
+ xorq %rax,%rax
+
+ negq %rsi
+.L8x_no_tail:
+ adcq 0(%rdi),%r8
+ adcq 8(%rdi),%r9
+ adcq 16(%rdi),%r10
+ adcq 24(%rdi),%r11
+ adcq 32(%rdi),%r12
+ adcq 40(%rdi),%r13
+ adcq 48(%rdi),%r14
+ adcq 56(%rdi),%r15
+ adcq $0,%rax
+ movq -16(%rbp),%rcx
+ xorq %rsi,%rsi
+
+.byte 102,72,15,126,213
+
+ movq %r8,0(%rdi)
+ movq %r9,8(%rdi)
+.byte 102,73,15,126,217
+ 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(%rdi),%rdi
+
+ cmpq %rdx,%rdi
+ jb .L8x_reduction_loop
+
+ subq %r15,%rcx
+ leaq (%rdi,%r9,1),%rbx
+ adcq %rsi,%rsi
+ movq %r9,%rcx
+ orq %rsi,%rax
+.byte 102,72,15,126,207
+ xorq $1,%rax
+.byte 102,72,15,126,206
+ leaq (%rbp,%rax,8),%rbp
+ sarq $3+2,%rcx
+ jmp .Lsqr4x_sub
+
+.align 32
+.Lsqr4x_sub:
+.byte 0x66
+ movq 0(%rbx),%r12
+ movq 8(%rbx),%r13
+ sbbq 0(%rbp),%r12
+ movq 16(%rbx),%r14
+ sbbq 16(%rbp),%r13
+ movq 24(%rbx),%r15
+ leaq 32(%rbx),%rbx
+ sbbq 32(%rbp),%r14
+ movq %r12,0(%rdi)
+ sbbq 48(%rbp),%r15
+ leaq 64(%rbp),%rbp
+ movq %r13,8(%rdi)
+ movq %r14,16(%rdi)
+ movq %r15,24(%rdi)
+ leaq 32(%rdi),%rdi
+
+ incq %rcx
+ jnz .Lsqr4x_sub
+ movq %r9,%r10
+ negq %r9
+ .byte 0xf3,0xc3
+.size bn_sqr8x_internal,.-bn_sqr8x_internal
+.globl bn_from_montgomery
+.hidden bn_from_montgomery
+.type bn_from_montgomery,@function
+.align 32
+bn_from_montgomery:
+ testl $7,%r9d
+ jz bn_from_mont8x
+ xorl %eax,%eax
+ .byte 0xf3,0xc3
+.size bn_from_montgomery,.-bn_from_montgomery
+
+.type bn_from_mont8x,@function
+.align 32
+bn_from_mont8x:
+.byte 0x67
+ movq %rsp,%rax
+ pushq %rbx
+ pushq %rbp
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ pushq %r15
+.byte 0x67
+ movl %r9d,%r10d
+ shll $3,%r9d
+ shll $3+2,%r10d
+ negq %r9
+ movq (%r8),%r8
+
+
+
+
+
+
+
+ leaq -64(%rsp,%r9,2),%r11
+ subq %rsi,%r11
+ andq $4095,%r11
+ cmpq %r11,%r10
+ jb .Lfrom_sp_alt
+ subq %r11,%rsp
+ leaq -64(%rsp,%r9,2),%rsp
+ jmp .Lfrom_sp_done
+
+.align 32
+.Lfrom_sp_alt:
+ leaq 4096-64(,%r9,2),%r10
+ leaq -64(%rsp,%r9,2),%rsp
+ subq %r10,%r11
+ movq $0,%r10
+ cmovcq %r10,%r11
+ subq %r11,%rsp
+.Lfrom_sp_done:
+ andq $-64,%rsp
+ movq %r9,%r10
+ negq %r9
+
+
+
+
+
+
+
+
+
+
+ movq %r8,32(%rsp)
+ movq %rax,40(%rsp)
+.Lfrom_body:
+ movq %r9,%r11
+ leaq 48(%rsp),%rax
+ pxor %xmm0,%xmm0
+ jmp .Lmul_by_1
+
+.align 32
+.Lmul_by_1:
+ movdqu (%rsi),%xmm1
+ movdqu 16(%rsi),%xmm2
+ movdqu 32(%rsi),%xmm3
+ movdqa %xmm0,(%rax,%r9,1)
+ movdqu 48(%rsi),%xmm4
+ movdqa %xmm0,16(%rax,%r9,1)
+.byte 0x48,0x8d,0xb6,0x40,0x00,0x00,0x00
+ movdqa %xmm1,(%rax)
+ movdqa %xmm0,32(%rax,%r9,1)
+ movdqa %xmm2,16(%rax)
+ movdqa %xmm0,48(%rax,%r9,1)
+ movdqa %xmm3,32(%rax)
+ movdqa %xmm4,48(%rax)
+ leaq 64(%rax),%rax
+ subq $64,%r11
+ jnz .Lmul_by_1
+
+.byte 102,72,15,110,207
+.byte 102,72,15,110,209
+.byte 0x67
+ movq %rcx,%rbp
+.byte 102,73,15,110,218
+ call sqr8x_reduction
+
+ pxor %xmm0,%xmm0
+ leaq 48(%rsp),%rax
+ movq 40(%rsp),%rsi
+ jmp .Lfrom_mont_zero
+
+.align 32
+.Lfrom_mont_zero:
+ movdqa %xmm0,0(%rax)
+ movdqa %xmm0,16(%rax)
+ movdqa %xmm0,32(%rax)
+ movdqa %xmm0,48(%rax)
+ leaq 64(%rax),%rax
+ subq $32,%r9
+ jnz .Lfrom_mont_zero
+
+ movq $1,%rax
+ movq -48(%rsi),%r15
+ movq -40(%rsi),%r14
+ movq -32(%rsi),%r13
+ movq -24(%rsi),%r12
+ movq -16(%rsi),%rbp
+ movq -8(%rsi),%rbx
+ leaq (%rsi),%rsp
+.Lfrom_epilogue:
+ .byte 0xf3,0xc3
+.size bn_from_mont8x,.-bn_from_mont8x
+.globl bn_scatter5
+.hidden bn_scatter5
+.type bn_scatter5,@function
+.align 16
+bn_scatter5:
+ cmpl $0,%esi
+ jz .Lscatter_epilogue
+ leaq (%rdx,%rcx,8),%rdx
+.Lscatter:
+ movq (%rdi),%rax
+ leaq 8(%rdi),%rdi
+ movq %rax,(%rdx)
+ leaq 256(%rdx),%rdx
+ subl $1,%esi
+ jnz .Lscatter
+.Lscatter_epilogue:
+ .byte 0xf3,0xc3
+.size bn_scatter5,.-bn_scatter5
+
+.globl bn_gather5
+.hidden bn_gather5
+.type bn_gather5,@function
+.align 16
+bn_gather5:
+ movl %ecx,%r11d
+ shrl $3,%ecx
+ andq $7,%r11
+ notl %ecx
+ leaq .Lmagic_masks(%rip),%rax
+ andl $3,%ecx
+ leaq 128(%rdx,%r11,8),%rdx
+ movq 0(%rax,%rcx,8),%xmm4
+ movq 8(%rax,%rcx,8),%xmm5
+ movq 16(%rax,%rcx,8),%xmm6
+ movq 24(%rax,%rcx,8),%xmm7
+ jmp .Lgather
+.align 16
+.Lgather:
+ movq -128(%rdx),%xmm0
+ movq -64(%rdx),%xmm1
+ pand %xmm4,%xmm0
+ movq 0(%rdx),%xmm2
+ pand %xmm5,%xmm1
+ movq 64(%rdx),%xmm3
+ pand %xmm6,%xmm2
+ por %xmm1,%xmm0
+ pand %xmm7,%xmm3
+.byte 0x67,0x67
+ por %xmm2,%xmm0
+ leaq 256(%rdx),%rdx
+ por %xmm3,%xmm0
+
+ movq %xmm0,(%rdi)
+ leaq 8(%rdi),%rdi
+ subl $1,%esi
+ jnz .Lgather
+ .byte 0xf3,0xc3
+.LSEH_end_bn_gather5:
+.size bn_gather5,.-bn_gather5
+.align 64
+.Lmagic_masks:
+.long 0,0, 0,0, 0,0, -1,-1
+.long 0,0, 0,0, 0,0, 0,0
+.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
+#endif
diff --git a/linux-x86_64/crypto/cpu-x86_64-asm.S b/linux-x86_64/crypto/cpu-x86_64-asm.S
new file mode 100644
index 0000000..c664242
--- /dev/null
+++ b/linux-x86_64/crypto/cpu-x86_64-asm.S
@@ -0,0 +1,147 @@
+#if defined(__x86_64__)
+.text
+
+.globl OPENSSL_ia32_cpuid
+.hidden OPENSSL_ia32_cpuid
+.type OPENSSL_ia32_cpuid,@function
+.align 16
+OPENSSL_ia32_cpuid:
+
+
+ movq %rdi,%rdi
+ movq %rbx,%r8
+
+ xorl %eax,%eax
+ movl %eax,8(%rdi)
+ 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 $2049,%r9d
+
+ cmpl $2147483656,%r10d
+ jb .Lintel
+
+ movl $2147483656,%eax
+ cpuid
+
+ movzbq %cl,%r10
+ incq %r10
+
+ movl $1,%eax
+ cpuid
+
+ btl $28,%edx
+ jnc .Lgeneric
+ shrl $16,%ebx
+ cmpb %r10b,%bl
+ ja .Lgeneric
+ andl $4026531839,%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
+
+ cmpl $7,%r11d
+ jb .Lnocacheinfo
+
+ movl $7,%eax
+ xorl %ecx,%ecx
+ cpuid
+ movl %ebx,8(%rdi)
+
+.Lnocacheinfo:
+ movl $1,%eax
+ cpuid
+
+ andl $3220176895,%edx
+ cmpl $0,%r9d
+ jne .Lnotintel
+ orl $1073741824,%edx
+ andb $15,%ah
+ cmpb $15,%ah
+ jne .Lnotintel
+ orl $1048576,%edx
+.Lnotintel:
+ btl $28,%edx
+ jnc .Lgeneric
+ andl $4026531839,%edx
+ cmpl $0,%r10d
+ je .Lgeneric
+
+ orl $268435456,%edx
+ shrl $16,%ebx
+ cmpb $1,%bl
+ ja .Lgeneric
+ andl $4026531839,%edx
+.Lgeneric:
+ andl $2048,%r9d
+ andl $4294965247,%ecx
+ orl %ecx,%r9d
+
+ movl %edx,%r10d
+ btl $27,%r9d
+ jnc .Lclear_avx
+ xorl %ecx,%ecx
+.byte 0x0f,0x01,0xd0
+ andl $6,%eax
+ cmpl $6,%eax
+ je .Ldone
+.Lclear_avx:
+ movl $4026525695,%eax
+ andl %eax,%r9d
+ andl $4294967263,8(%rdi)
+.Ldone:
+ movl %r9d,4(%rdi)
+ movl %r10d,0(%rdi)
+ movq %r8,%rbx
+ .byte 0xf3,0xc3
+.size OPENSSL_ia32_cpuid,.-OPENSSL_ia32_cpuid
+
+#endif
diff --git a/linux-x86_64/crypto/md5/md5-x86_64.S b/linux-x86_64/crypto/md5/md5-x86_64.S
new file mode 100644
index 0000000..7644689
--- /dev/null
+++ b/linux-x86_64/crypto/md5/md5-x86_64.S
@@ -0,0 +1,671 @@
+#if defined(__x86_64__)
+.text
+.align 16
+
+.globl md5_block_asm_data_order
+.hidden md5_block_asm_data_order
+.type md5_block_asm_data_order,@function
+md5_block_asm_data_order:
+ 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:
+ .byte 0xf3,0xc3
+.size md5_block_asm_data_order,.-md5_block_asm_data_order
+#endif
diff --git a/linux-x86_64/crypto/modes/aesni-gcm-x86_64.S b/linux-x86_64/crypto/modes/aesni-gcm-x86_64.S
new file mode 100644
index 0000000..f01692e
--- /dev/null
+++ b/linux-x86_64/crypto/modes/aesni-gcm-x86_64.S
@@ -0,0 +1,19 @@
+#if defined(__x86_64__)
+.text
+
+.globl aesni_gcm_encrypt
+.hidden aesni_gcm_encrypt
+.type aesni_gcm_encrypt,@function
+aesni_gcm_encrypt:
+ xorl %eax,%eax
+ .byte 0xf3,0xc3
+.size aesni_gcm_encrypt,.-aesni_gcm_encrypt
+
+.globl aesni_gcm_decrypt
+.hidden aesni_gcm_decrypt
+.type aesni_gcm_decrypt,@function
+aesni_gcm_decrypt:
+ xorl %eax,%eax
+ .byte 0xf3,0xc3
+.size aesni_gcm_decrypt,.-aesni_gcm_decrypt
+#endif
diff --git a/linux-x86_64/crypto/modes/ghash-x86_64.S b/linux-x86_64/crypto/modes/ghash-x86_64.S
new file mode 100644
index 0000000..bd1b17f
--- /dev/null
+++ b/linux-x86_64/crypto/modes/ghash-x86_64.S
@@ -0,0 +1,1328 @@
+#if defined(__x86_64__)
+.text
+
+
+.globl gcm_gmult_4bit
+.hidden 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:
+ .byte 0xf3,0xc3
+.size gcm_gmult_4bit,.-gcm_gmult_4bit
+.globl gcm_ghash_4bit
+.hidden 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:
+ .byte 0xf3,0xc3
+.size gcm_ghash_4bit,.-gcm_ghash_4bit
+.globl gcm_init_clmul
+.hidden gcm_init_clmul
+.type gcm_init_clmul,@function
+.align 16
+gcm_init_clmul:
+.L_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 .L0x1c2_polynomial(%rip),%xmm5
+ pxor %xmm5,%xmm2
+
+
+ pshufd $78,%xmm2,%xmm6
+ movdqa %xmm2,%xmm0
+ pxor %xmm2,%xmm6
+ movdqa %xmm0,%xmm1
+ pshufd $78,%xmm0,%xmm3
+ pxor %xmm0,%xmm3
+.byte 102,15,58,68,194,0
+.byte 102,15,58,68,202,17
+.byte 102,15,58,68,222,0
+ pxor %xmm0,%xmm3
+ pxor %xmm1,%xmm3
+
+ movdqa %xmm3,%xmm4
+ psrldq $8,%xmm3
+ pslldq $8,%xmm4
+ pxor %xmm3,%xmm1
+ pxor %xmm4,%xmm0
+
+ movdqa %xmm0,%xmm4
+ movdqa %xmm0,%xmm3
+ psllq $5,%xmm0
+ pxor %xmm0,%xmm3
+ psllq $1,%xmm0
+ pxor %xmm3,%xmm0
+ psllq $57,%xmm0
+ movdqa %xmm0,%xmm3
+ pslldq $8,%xmm0
+ psrldq $8,%xmm3
+ pxor %xmm4,%xmm0
+ pxor %xmm3,%xmm1
+
+
+ movdqa %xmm0,%xmm4
+ psrlq $1,%xmm0
+ pxor %xmm4,%xmm1
+ pxor %xmm0,%xmm4
+ psrlq $5,%xmm0
+ pxor %xmm4,%xmm0
+ psrlq $1,%xmm0
+ pxor %xmm1,%xmm0
+ pshufd $78,%xmm2,%xmm3
+ pshufd $78,%xmm0,%xmm4
+ pxor %xmm2,%xmm3
+ movdqu %xmm2,0(%rdi)
+ pxor %xmm0,%xmm4
+ movdqu %xmm0,16(%rdi)
+.byte 102,15,58,15,227,8
+ movdqu %xmm4,32(%rdi)
+ movdqa %xmm0,%xmm1
+ pshufd $78,%xmm0,%xmm3
+ pxor %xmm0,%xmm3
+.byte 102,15,58,68,194,0
+.byte 102,15,58,68,202,17
+.byte 102,15,58,68,222,0
+ pxor %xmm0,%xmm3
+ pxor %xmm1,%xmm3
+
+ movdqa %xmm3,%xmm4
+ psrldq $8,%xmm3
+ pslldq $8,%xmm4
+ pxor %xmm3,%xmm1
+ pxor %xmm4,%xmm0
+
+ movdqa %xmm0,%xmm4
+ movdqa %xmm0,%xmm3
+ psllq $5,%xmm0
+ pxor %xmm0,%xmm3
+ psllq $1,%xmm0
+ pxor %xmm3,%xmm0
+ psllq $57,%xmm0
+ movdqa %xmm0,%xmm3
+ pslldq $8,%xmm0
+ psrldq $8,%xmm3
+ pxor %xmm4,%xmm0
+ pxor %xmm3,%xmm1
+
+
+ movdqa %xmm0,%xmm4
+ psrlq $1,%xmm0
+ pxor %xmm4,%xmm1
+ pxor %xmm0,%xmm4
+ psrlq $5,%xmm0
+ pxor %xmm4,%xmm0
+ psrlq $1,%xmm0
+ pxor %xmm1,%xmm0
+ movdqa %xmm0,%xmm5
+ movdqa %xmm0,%xmm1
+ pshufd $78,%xmm0,%xmm3
+ pxor %xmm0,%xmm3
+.byte 102,15,58,68,194,0
+.byte 102,15,58,68,202,17
+.byte 102,15,58,68,222,0
+ pxor %xmm0,%xmm3
+ pxor %xmm1,%xmm3
+
+ movdqa %xmm3,%xmm4
+ psrldq $8,%xmm3
+ pslldq $8,%xmm4
+ pxor %xmm3,%xmm1
+ pxor %xmm4,%xmm0
+
+ movdqa %xmm0,%xmm4
+ movdqa %xmm0,%xmm3
+ psllq $5,%xmm0
+ pxor %xmm0,%xmm3
+ psllq $1,%xmm0
+ pxor %xmm3,%xmm0
+ psllq $57,%xmm0
+ movdqa %xmm0,%xmm3
+ pslldq $8,%xmm0
+ psrldq $8,%xmm3
+ pxor %xmm4,%xmm0
+ pxor %xmm3,%xmm1
+
+
+ movdqa %xmm0,%xmm4
+ psrlq $1,%xmm0
+ pxor %xmm4,%xmm1
+ pxor %xmm0,%xmm4
+ psrlq $5,%xmm0
+ pxor %xmm4,%xmm0
+ psrlq $1,%xmm0
+ pxor %xmm1,%xmm0
+ pshufd $78,%xmm5,%xmm3
+ pshufd $78,%xmm0,%xmm4
+ pxor %xmm5,%xmm3
+ movdqu %xmm5,48(%rdi)
+ pxor %xmm0,%xmm4
+ movdqu %xmm0,64(%rdi)
+.byte 102,15,58,15,227,8
+ movdqu %xmm4,80(%rdi)
+ .byte 0xf3,0xc3
+.size gcm_init_clmul,.-gcm_init_clmul
+.globl gcm_gmult_clmul
+.hidden gcm_gmult_clmul
+.type gcm_gmult_clmul,@function
+.align 16
+gcm_gmult_clmul:
+.L_gmult_clmul:
+ movdqu (%rdi),%xmm0
+ movdqa .Lbswap_mask(%rip),%xmm5
+ movdqu (%rsi),%xmm2
+ movdqu 32(%rsi),%xmm4
+.byte 102,15,56,0,197
+ movdqa %xmm0,%xmm1
+ pshufd $78,%xmm0,%xmm3
+ pxor %xmm0,%xmm3
+.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,%xmm4
+ movdqa %xmm0,%xmm3
+ psllq $5,%xmm0
+ pxor %xmm0,%xmm3
+ psllq $1,%xmm0
+ pxor %xmm3,%xmm0
+ psllq $57,%xmm0
+ movdqa %xmm0,%xmm3
+ pslldq $8,%xmm0
+ psrldq $8,%xmm3
+ pxor %xmm4,%xmm0
+ pxor %xmm3,%xmm1
+
+
+ movdqa %xmm0,%xmm4
+ psrlq $1,%xmm0
+ pxor %xmm4,%xmm1
+ pxor %xmm0,%xmm4
+ psrlq $5,%xmm0
+ pxor %xmm4,%xmm0
+ psrlq $1,%xmm0
+ pxor %xmm1,%xmm0
+.byte 102,15,56,0,197
+ movdqu %xmm0,(%rdi)
+ .byte 0xf3,0xc3
+.size gcm_gmult_clmul,.-gcm_gmult_clmul
+.globl gcm_ghash_clmul
+.hidden gcm_ghash_clmul
+.type gcm_ghash_clmul,@function
+.align 32
+gcm_ghash_clmul:
+.L_ghash_clmul:
+ movdqa .Lbswap_mask(%rip),%xmm10
+
+ movdqu (%rdi),%xmm0
+ movdqu (%rsi),%xmm2
+ movdqu 32(%rsi),%xmm7
+.byte 102,65,15,56,0,194
+
+ subq $16,%rcx
+ jz .Lodd_tail
+
+ movdqu 16(%rsi),%xmm6
+ movl OPENSSL_ia32cap_P+4(%rip),%eax
+ cmpq $48,%rcx
+ jb .Lskip4x
+
+ andl $71303168,%eax
+ cmpl $4194304,%eax
+ je .Lskip4x
+
+ subq $48,%rcx
+ movq $11547335547999543296,%rax
+ movdqu 48(%rsi),%xmm14
+ movdqu 64(%rsi),%xmm15
+
+
+
+
+ movdqu 48(%rdx),%xmm3
+ movdqu 32(%rdx),%xmm11
+.byte 102,65,15,56,0,218
+.byte 102,69,15,56,0,218
+ movdqa %xmm3,%xmm5
+ pshufd $78,%xmm3,%xmm4
+ pxor %xmm3,%xmm4
+.byte 102,15,58,68,218,0
+.byte 102,15,58,68,234,17
+.byte 102,15,58,68,231,0
+
+ movdqa %xmm11,%xmm13
+ pshufd $78,%xmm11,%xmm12
+ pxor %xmm11,%xmm12
+.byte 102,68,15,58,68,222,0
+.byte 102,68,15,58,68,238,17
+.byte 102,68,15,58,68,231,16
+ xorps %xmm11,%xmm3
+ xorps %xmm13,%xmm5
+ movups 80(%rsi),%xmm7
+ xorps %xmm12,%xmm4
+
+ movdqu 16(%rdx),%xmm11
+ movdqu 0(%rdx),%xmm8
+.byte 102,69,15,56,0,218
+.byte 102,69,15,56,0,194
+ movdqa %xmm11,%xmm13
+ pshufd $78,%xmm11,%xmm12
+ pxor %xmm8,%xmm0
+ pxor %xmm11,%xmm12
+.byte 102,69,15,58,68,222,0
+ movdqa %xmm0,%xmm1
+ pshufd $78,%xmm0,%xmm8
+ pxor %xmm0,%xmm8
+.byte 102,69,15,58,68,238,17
+.byte 102,68,15,58,68,231,0
+ xorps %xmm11,%xmm3
+ xorps %xmm13,%xmm5
+
+ leaq 64(%rdx),%rdx
+ subq $64,%rcx
+ jc .Ltail4x
+
+ jmp .Lmod4_loop
+.align 32
+.Lmod4_loop:
+.byte 102,65,15,58,68,199,0
+ xorps %xmm12,%xmm4
+ movdqu 48(%rdx),%xmm11
+.byte 102,69,15,56,0,218
+.byte 102,65,15,58,68,207,17
+ xorps %xmm3,%xmm0
+ movdqu 32(%rdx),%xmm3
+ movdqa %xmm11,%xmm13
+.byte 102,68,15,58,68,199,16
+ pshufd $78,%xmm11,%xmm12
+ xorps %xmm5,%xmm1
+ pxor %xmm11,%xmm12
+.byte 102,65,15,56,0,218
+ movups 32(%rsi),%xmm7
+ xorps %xmm4,%xmm8
+.byte 102,68,15,58,68,218,0
+ pshufd $78,%xmm3,%xmm4
+
+ pxor %xmm0,%xmm8
+ movdqa %xmm3,%xmm5
+ pxor %xmm1,%xmm8
+ pxor %xmm3,%xmm4
+ movdqa %xmm8,%xmm9
+.byte 102,68,15,58,68,234,17
+ pslldq $8,%xmm8
+ psrldq $8,%xmm9
+ pxor %xmm8,%xmm0
+ movdqa .L7_mask(%rip),%xmm8
+ pxor %xmm9,%xmm1
+.byte 102,76,15,110,200
+
+ pand %xmm0,%xmm8
+.byte 102,69,15,56,0,200
+ pxor %xmm0,%xmm9
+.byte 102,68,15,58,68,231,0
+ psllq $57,%xmm9
+ movdqa %xmm9,%xmm8
+ pslldq $8,%xmm9
+.byte 102,15,58,68,222,0
+ psrldq $8,%xmm8
+ pxor %xmm9,%xmm0
+ pxor %xmm8,%xmm1
+ movdqu 0(%rdx),%xmm8
+
+ movdqa %xmm0,%xmm9
+ psrlq $1,%xmm0
+.byte 102,15,58,68,238,17
+ xorps %xmm11,%xmm3
+ movdqu 16(%rdx),%xmm11
+.byte 102,69,15,56,0,218
+.byte 102,15,58,68,231,16
+ xorps %xmm13,%xmm5
+ movups 80(%rsi),%xmm7
+.byte 102,69,15,56,0,194
+ pxor %xmm9,%xmm1
+ pxor %xmm0,%xmm9
+ psrlq $5,%xmm0
+
+ movdqa %xmm11,%xmm13
+ pxor %xmm12,%xmm4
+ pshufd $78,%xmm11,%xmm12
+ pxor %xmm9,%xmm0
+ pxor %xmm8,%xmm1
+ pxor %xmm11,%xmm12
+.byte 102,69,15,58,68,222,0
+ psrlq $1,%xmm0
+ pxor %xmm1,%xmm0
+ movdqa %xmm0,%xmm1
+.byte 102,69,15,58,68,238,17
+ xorps %xmm11,%xmm3
+ pshufd $78,%xmm0,%xmm8
+ pxor %xmm0,%xmm8
+
+.byte 102,68,15,58,68,231,0
+ xorps %xmm13,%xmm5
+
+ leaq 64(%rdx),%rdx
+ subq $64,%rcx
+ jnc .Lmod4_loop
+
+.Ltail4x:
+.byte 102,65,15,58,68,199,0
+.byte 102,65,15,58,68,207,17
+.byte 102,68,15,58,68,199,16
+ xorps %xmm12,%xmm4
+ xorps %xmm3,%xmm0
+ xorps %xmm5,%xmm1
+ pxor %xmm0,%xmm1
+ pxor %xmm4,%xmm8
+
+ pxor %xmm1,%xmm8
+ pxor %xmm0,%xmm1
+
+ movdqa %xmm8,%xmm9
+ psrldq $8,%xmm8
+ pslldq $8,%xmm9
+ pxor %xmm8,%xmm1
+ pxor %xmm9,%xmm0
+
+ movdqa %xmm0,%xmm4
+ movdqa %xmm0,%xmm3
+ psllq $5,%xmm0
+ pxor %xmm0,%xmm3
+ psllq $1,%xmm0
+ pxor %xmm3,%xmm0
+ psllq $57,%xmm0
+ movdqa %xmm0,%xmm3
+ pslldq $8,%xmm0
+ psrldq $8,%xmm3
+ pxor %xmm4,%xmm0
+ pxor %xmm3,%xmm1
+
+
+ movdqa %xmm0,%xmm4
+ psrlq $1,%xmm0
+ pxor %xmm4,%xmm1
+ pxor %xmm0,%xmm4
+ psrlq $5,%xmm0
+ pxor %xmm4,%xmm0
+ psrlq $1,%xmm0
+ pxor %xmm1,%xmm0
+ addq $64,%rcx
+ jz .Ldone
+ movdqu 32(%rsi),%xmm7
+ subq $16,%rcx
+ jz .Lodd_tail
+.Lskip4x:
+
+
+
+
+
+ movdqu (%rdx),%xmm8
+ movdqu 16(%rdx),%xmm3
+.byte 102,69,15,56,0,194
+.byte 102,65,15,56,0,218
+ pxor %xmm8,%xmm0
+
+ movdqa %xmm3,%xmm5
+ pshufd $78,%xmm3,%xmm4
+ pxor %xmm3,%xmm4
+.byte 102,15,58,68,218,0
+.byte 102,15,58,68,234,17
+.byte 102,15,58,68,231,0
+
+ leaq 32(%rdx),%rdx
+ nop
+ subq $32,%rcx
+ jbe .Leven_tail
+ nop
+ jmp .Lmod_loop
+
+.align 32
+.Lmod_loop:
+ movdqa %xmm0,%xmm1
+ movdqa %xmm4,%xmm8
+ pshufd $78,%xmm0,%xmm4
+ pxor %xmm0,%xmm4
+
+.byte 102,15,58,68,198,0
+.byte 102,15,58,68,206,17
+.byte 102,15,58,68,231,16
+
+ pxor %xmm3,%xmm0
+ pxor %xmm5,%xmm1
+ movdqu (%rdx),%xmm9
+ pxor %xmm0,%xmm8
+.byte 102,69,15,56,0,202
+ movdqu 16(%rdx),%xmm3
+
+ pxor %xmm1,%xmm8
+ pxor %xmm9,%xmm1
+ pxor %xmm8,%xmm4
+.byte 102,65,15,56,0,218
+ movdqa %xmm4,%xmm8
+ psrldq $8,%xmm8
+ pslldq $8,%xmm4
+ pxor %xmm8,%xmm1
+ pxor %xmm4,%xmm0
+
+ movdqa %xmm3,%xmm5
+
+ movdqa %xmm0,%xmm9
+ movdqa %xmm0,%xmm8
+ psllq $5,%xmm0
+ pxor %xmm0,%xmm8
+.byte 102,15,58,68,218,0
+ psllq $1,%xmm0
+ pxor %xmm8,%xmm0
+ psllq $57,%xmm0
+ movdqa %xmm0,%xmm8
+ pslldq $8,%xmm0
+ psrldq $8,%xmm8
+ pxor %xmm9,%xmm0
+ pshufd $78,%xmm5,%xmm4
+ pxor %xmm8,%xmm1
+ pxor %xmm5,%xmm4
+
+ movdqa %xmm0,%xmm9
+ psrlq $1,%xmm0
+.byte 102,15,58,68,234,17
+ pxor %xmm9,%xmm1
+ pxor %xmm0,%xmm9
+ psrlq $5,%xmm0
+ pxor %xmm9,%xmm0
+ leaq 32(%rdx),%rdx
+ psrlq $1,%xmm0
+.byte 102,15,58,68,231,0
+ pxor %xmm1,%xmm0
+
+ subq $32,%rcx
+ ja .Lmod_loop
+
+.Leven_tail:
+ movdqa %xmm0,%xmm1
+ movdqa %xmm4,%xmm8
+ pshufd $78,%xmm0,%xmm4
+ pxor %xmm0,%xmm4
+
+.byte 102,15,58,68,198,0
+.byte 102,15,58,68,206,17
+.byte 102,15,58,68,231,16
+
+ pxor %xmm3,%xmm0
+ pxor %xmm5,%xmm1
+ pxor %xmm0,%xmm8
+ pxor %xmm1,%xmm8
+ pxor %xmm8,%xmm4
+ movdqa %xmm4,%xmm8
+ psrldq $8,%xmm8
+ pslldq $8,%xmm4
+ pxor %xmm8,%xmm1
+ pxor %xmm4,%xmm0
+
+ movdqa %xmm0,%xmm4
+ movdqa %xmm0,%xmm3
+ psllq $5,%xmm0
+ pxor %xmm0,%xmm3
+ psllq $1,%xmm0
+ pxor %xmm3,%xmm0
+ psllq $57,%xmm0
+ movdqa %xmm0,%xmm3
+ pslldq $8,%xmm0
+ psrldq $8,%xmm3
+ pxor %xmm4,%xmm0
+ pxor %xmm3,%xmm1
+
+
+ movdqa %xmm0,%xmm4
+ psrlq $1,%xmm0
+ pxor %xmm4,%xmm1
+ pxor %xmm0,%xmm4
+ psrlq $5,%xmm0
+ pxor %xmm4,%xmm0
+ psrlq $1,%xmm0
+ pxor %xmm1,%xmm0
+ testq %rcx,%rcx
+ jnz .Ldone
+
+.Lodd_tail:
+ movdqu (%rdx),%xmm8
+.byte 102,69,15,56,0,194
+ pxor %xmm8,%xmm0
+ movdqa %xmm0,%xmm1
+ pshufd $78,%xmm0,%xmm3
+ pxor %xmm0,%xmm3
+.byte 102,15,58,68,194,0
+.byte 102,15,58,68,202,17
+.byte 102,15,58,68,223,0
+ pxor %xmm0,%xmm3
+ pxor %xmm1,%xmm3
+
+ movdqa %xmm3,%xmm4
+ psrldq $8,%xmm3
+ pslldq $8,%xmm4
+ pxor %xmm3,%xmm1
+ pxor %xmm4,%xmm0
+
+ movdqa %xmm0,%xmm4
+ movdqa %xmm0,%xmm3
+ psllq $5,%xmm0
+ pxor %xmm0,%xmm3
+ psllq $1,%xmm0
+ pxor %xmm3,%xmm0
+ psllq $57,%xmm0
+ movdqa %xmm0,%xmm3
+ pslldq $8,%xmm0
+ psrldq $8,%xmm3
+ pxor %xmm4,%xmm0
+ pxor %xmm3,%xmm1
+
+
+ movdqa %xmm0,%xmm4
+ psrlq $1,%xmm0
+ pxor %xmm4,%xmm1
+ pxor %xmm0,%xmm4
+ psrlq $5,%xmm0
+ pxor %xmm4,%xmm0
+ psrlq $1,%xmm0
+ pxor %xmm1,%xmm0
+.Ldone:
+.byte 102,65,15,56,0,194
+ movdqu %xmm0,(%rdi)
+ .byte 0xf3,0xc3
+.size gcm_ghash_clmul,.-gcm_ghash_clmul
+.globl gcm_init_avx
+.hidden gcm_init_avx
+.type gcm_init_avx,@function
+.align 32
+gcm_init_avx:
+ jmp .L_init_clmul
+.size gcm_init_avx,.-gcm_init_avx
+.globl gcm_gmult_avx
+.hidden gcm_gmult_avx
+.type gcm_gmult_avx,@function
+.align 32
+gcm_gmult_avx:
+ jmp .L_gmult_clmul
+.size gcm_gmult_avx,.-gcm_gmult_avx
+.globl gcm_ghash_avx
+.hidden gcm_ghash_avx
+.type gcm_ghash_avx,@function
+.align 32
+gcm_ghash_avx:
+ jmp .L_ghash_clmul
+.size gcm_ghash_avx,.-gcm_ghash_avx
+.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
+.L7_mask:
+.long 7,0,7,0
+.L7_mask_poly:
+.long 7,0,450,0
+.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
+
+.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
+.align 64
+#endif
diff --git a/linux-x86_64/crypto/rc4/rc4-md5-x86_64.S b/linux-x86_64/crypto/rc4/rc4-md5-x86_64.S
new file mode 100644
index 0000000..06c8d67
--- /dev/null
+++ b/linux-x86_64/crypto/rc4/rc4-md5-x86_64.S
@@ -0,0 +1,1262 @@
+#if defined(__x86_64__)
+.text
+.align 16
+
+.globl rc4_md5_enc
+.hidden rc4_md5_enc
+.type rc4_md5_enc,@function
+rc4_md5_enc:
+ 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:
+ .byte 0xf3,0xc3
+.size rc4_md5_enc,.-rc4_md5_enc
+#endif
diff --git a/linux-x86_64/crypto/rc4/rc4-x86_64.S b/linux-x86_64/crypto/rc4/rc4-x86_64.S
new file mode 100644
index 0000000..edd6565
--- /dev/null
+++ b/linux-x86_64/crypto/rc4/rc4-x86_64.S
@@ -0,0 +1,622 @@
+#if defined(__x86_64__)
+.text
+
+
+.globl asm_RC4
+.hidden asm_RC4
+.type asm_RC4,@function
+.align 16
+asm_RC4:
+ orq %rsi,%rsi
+ jne .Lentry
+ .byte 0xf3,0xc3
+.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 $30,%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,(%r12,%r13,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,(%r12,%r13,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,(%r12,%r13,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,(%r12,%r13,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,(%r12,%r13,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,(%r12,%r13,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:
+ .byte 0xf3,0xc3
+.size asm_RC4,.-asm_RC4
+.globl asm_RC4_set_key
+.hidden asm_RC4_set_key
+.type asm_RC4_set_key,@function
+.align 16
+asm_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 $20,%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)
+ .byte 0xf3,0xc3
+.size asm_RC4_set_key,.-asm_RC4_set_key
+
+.globl RC4_options
+.hidden RC4_options
+.type RC4_options,@function
+.align 16
+RC4_options:
+ leaq .Lopts(%rip),%rax
+ movq OPENSSL_ia32cap_P(%rip),%rdx
+ movl (%rdx),%edx
+ btl $20,%edx
+ jc .L8xchar
+ btl $30,%edx
+ jnc .Ldone
+ addq $25,%rax
+ .byte 0xf3,0xc3
+.L8xchar:
+ addq $12,%rax
+.Ldone:
+ .byte 0xf3,0xc3
+.align 64
+.Lopts:
+.byte 114,99,52,40,56,120,44,105,110,116,41,0
+.byte 114,99,52,40,56,120,44,99,104,97,114,41,0
+.byte 114,99,52,40,49,54,120,44,105,110,116,41,0
+.byte 82,67,52,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
+.align 64
+.size RC4_options,.-RC4_options
+#endif
diff --git a/linux-x86_64/crypto/sha/sha1-x86_64.S b/linux-x86_64/crypto/sha/sha1-x86_64.S
new file mode 100644
index 0000000..ea2f403
--- /dev/null
+++ b/linux-x86_64/crypto/sha/sha1-x86_64.S
@@ -0,0 +1,2425 @@
+#if defined(__x86_64__)
+.text
+
+
+.globl sha1_block_data_order
+.hidden sha1_block_data_order
+.type sha1_block_data_order,@function
+.align 16
+sha1_block_data_order:
+ movl OPENSSL_ia32cap_P+0(%rip),%r9d
+ movl OPENSSL_ia32cap_P+4(%rip),%r8d
+ movl OPENSSL_ia32cap_P+8(%rip),%r10d
+ testl $512,%r8d
+ jz .Lialu
+ jmp _ssse3_shortcut
+
+.align 16
+.Lialu:
+ movq %rsp,%rax
+ pushq %rbx
+ pushq %rbp
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ movq %rdi,%r8
+ subq $72,%rsp
+ movq %rsi,%r9
+ andq $-64,%rsp
+ movq %rdx,%r10
+ movq %rax,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 4(%r9),%ebp
+ movl %r12d,%eax
+ movl %edx,0(%rsp)
+ movl %esi,%ecx
+ bswapl %ebp
+ xorl %r11d,%eax
+ roll $5,%ecx
+ andl %edi,%eax
+ leal 1518500249(%rdx,%r13,1),%r13d
+ addl %ecx,%r13d
+ xorl %r12d,%eax
+ roll $30,%edi
+ addl %eax,%r13d
+ movl 8(%r9),%r14d
+ movl %r11d,%eax
+ movl %ebp,4(%rsp)
+ movl %r13d,%ecx
+ bswapl %r14d
+ xorl %edi,%eax
+ roll $5,%ecx
+ andl %esi,%eax
+ leal 1518500249(%rbp,%r12,1),%r12d
+ addl %ecx,%r12d
+ xorl %r11d,%eax
+ roll $30,%esi
+ addl %eax,%r12d
+ movl 12(%r9),%edx
+ movl %edi,%eax
+ movl %r14d,8(%rsp)
+ movl %r12d,%ecx
+ bswapl %edx
+ xorl %esi,%eax
+ roll $5,%ecx
+ andl %r13d,%eax
+ leal 1518500249(%r14,%r11,1),%r11d
+ addl %ecx,%r11d
+ xorl %edi,%eax
+ roll $30,%r13d
+ addl %eax,%r11d
+ movl 16(%r9),%ebp
+ movl %esi,%eax
+ movl %edx,12(%rsp)
+ movl %r11d,%ecx
+ bswapl %ebp
+ xorl %r13d,%eax
+ roll $5,%ecx
+ andl %r12d,%eax
+ leal 1518500249(%rdx,%rdi,1),%edi
+ addl %ecx,%edi
+ xorl %esi,%eax
+ roll $30,%r12d
+ addl %eax,%edi
+ movl 20(%r9),%r14d
+ movl %r13d,%eax
+ movl %ebp,16(%rsp)
+ movl %edi,%ecx
+ bswapl %r14d
+ xorl %r12d,%eax
+ roll $5,%ecx
+ andl %r11d,%eax
+ leal 1518500249(%rbp,%rsi,1),%esi
+ addl %ecx,%esi
+ xorl %r13d,%eax
+ roll $30,%r11d
+ addl %eax,%esi
+ movl 24(%r9),%edx
+ movl %r12d,%eax
+ movl %r14d,20(%rsp)
+ movl %esi,%ecx
+ bswapl %edx
+ xorl %r11d,%eax
+ roll $5,%ecx
+ andl %edi,%eax
+ leal 1518500249(%r14,%r13,1),%r13d
+ addl %ecx,%r13d
+ xorl %r12d,%eax
+ roll $30,%edi
+ addl %eax,%r13d
+ movl 28(%r9),%ebp
+ movl %r11d,%eax
+ movl %edx,24(%rsp)
+ movl %r13d,%ecx
+ bswapl %ebp
+ xorl %edi,%eax
+ roll $5,%ecx
+ andl %esi,%eax
+ leal 1518500249(%rdx,%r12,1),%r12d
+ addl %ecx,%r12d
+ xorl %r11d,%eax
+ roll $30,%esi
+ addl %eax,%r12d
+ movl 32(%r9),%r14d
+ movl %edi,%eax
+ movl %ebp,28(%rsp)
+ movl %r12d,%ecx
+ bswapl %r14d
+ xorl %esi,%eax
+ roll $5,%ecx
+ andl %r13d,%eax
+ leal 1518500249(%rbp,%r11,1),%r11d
+ addl %ecx,%r11d
+ xorl %edi,%eax
+ roll $30,%r13d
+ addl %eax,%r11d
+ movl 36(%r9),%edx
+ movl %esi,%eax
+ movl %r14d,32(%rsp)
+ movl %r11d,%ecx
+ bswapl %edx
+ xorl %r13d,%eax
+ roll $5,%ecx
+ andl %r12d,%eax
+ leal 1518500249(%r14,%rdi,1),%edi
+ addl %ecx,%edi
+ xorl %esi,%eax
+ roll $30,%r12d
+ addl %eax,%edi
+ movl 40(%r9),%ebp
+ movl %r13d,%eax
+ movl %edx,36(%rsp)
+ movl %edi,%ecx
+ bswapl %ebp
+ xorl %r12d,%eax
+ roll $5,%ecx
+ andl %r11d,%eax
+ leal 1518500249(%rdx,%rsi,1),%esi
+ addl %ecx,%esi
+ xorl %r13d,%eax
+ roll $30,%r11d
+ addl %eax,%esi
+ movl 44(%r9),%r14d
+ movl %r12d,%eax
+ movl %ebp,40(%rsp)
+ movl %esi,%ecx
+ bswapl %r14d
+ xorl %r11d,%eax
+ roll $5,%ecx
+ andl %edi,%eax
+ leal 1518500249(%rbp,%r13,1),%r13d
+ addl %ecx,%r13d
+ xorl %r12d,%eax
+ roll $30,%edi
+ addl %eax,%r13d
+ movl 48(%r9),%edx
+ movl %r11d,%eax
+ movl %r14d,44(%rsp)
+ movl %r13d,%ecx
+ bswapl %edx
+ xorl %edi,%eax
+ roll $5,%ecx
+ andl %esi,%eax
+ leal 1518500249(%r14,%r12,1),%r12d
+ addl %ecx,%r12d
+ xorl %r11d,%eax
+ roll $30,%esi
+ addl %eax,%r12d
+ movl 52(%r9),%ebp
+ movl %edi,%eax
+ movl %edx,48(%rsp)
+ movl %r12d,%ecx
+ bswapl %ebp
+ xorl %esi,%eax
+ roll $5,%ecx
+ andl %r13d,%eax
+ leal 1518500249(%rdx,%r11,1),%r11d
+ addl %ecx,%r11d
+ xorl %edi,%eax
+ roll $30,%r13d
+ addl %eax,%r11d
+ movl 56(%r9),%r14d
+ movl %esi,%eax
+ movl %ebp,52(%rsp)
+ movl %r11d,%ecx
+ bswapl %r14d
+ xorl %r13d,%eax
+ roll $5,%ecx
+ andl %r12d,%eax
+ leal 1518500249(%rbp,%rdi,1),%edi
+ addl %ecx,%edi
+ xorl %esi,%eax
+ roll $30,%r12d
+ addl %eax,%edi
+ movl 60(%r9),%edx
+ movl %r13d,%eax
+ movl %r14d,56(%rsp)
+ movl %edi,%ecx
+ bswapl %edx
+ xorl %r12d,%eax
+ roll $5,%ecx
+ andl %r11d,%eax
+ leal 1518500249(%r14,%rsi,1),%esi
+ addl %ecx,%esi
+ xorl %r13d,%eax
+ roll $30,%r11d
+ addl %eax,%esi
+ xorl 0(%rsp),%ebp
+ movl %r12d,%eax
+ movl %edx,60(%rsp)
+ movl %esi,%ecx
+ xorl 8(%rsp),%ebp
+ xorl %r11d,%eax
+ roll $5,%ecx
+ xorl 32(%rsp),%ebp
+ andl %edi,%eax
+ leal 1518500249(%rdx,%r13,1),%r13d
+ roll $30,%edi
+ xorl %r12d,%eax
+ addl %ecx,%r13d
+ roll $1,%ebp
+ addl %eax,%r13d
+ xorl 4(%rsp),%r14d
+ movl %r11d,%eax
+ movl %ebp,0(%rsp)
+ movl %r13d,%ecx
+ xorl 12(%rsp),%r14d
+ xorl %edi,%eax
+ roll $5,%ecx
+ xorl 36(%rsp),%r14d
+ andl %esi,%eax
+ leal 1518500249(%rbp,%r12,1),%r12d
+ roll $30,%esi
+ xorl %r11d,%eax
+ addl %ecx,%r12d
+ roll $1,%r14d
+ addl %eax,%r12d
+ xorl 8(%rsp),%edx
+ movl %edi,%eax
+ movl %r14d,4(%rsp)
+ movl %r12d,%ecx
+ xorl 16(%rsp),%edx
+ xorl %esi,%eax
+ roll $5,%ecx
+ xorl 40(%rsp),%edx
+ andl %r13d,%eax
+ leal 1518500249(%r14,%r11,1),%r11d
+ roll $30,%r13d
+ xorl %edi,%eax
+ addl %ecx,%r11d
+ roll $1,%edx
+ addl %eax,%r11d
+ xorl 12(%rsp),%ebp
+ movl %esi,%eax
+ movl %edx,8(%rsp)
+ movl %r11d,%ecx
+ xorl 20(%rsp),%ebp
+ xorl %r13d,%eax
+ roll $5,%ecx
+ xorl 44(%rsp),%ebp
+ andl %r12d,%eax
+ leal 1518500249(%rdx,%rdi,1),%edi
+ roll $30,%r12d
+ xorl %esi,%eax
+ addl %ecx,%edi
+ roll $1,%ebp
+ addl %eax,%edi
+ xorl 16(%rsp),%r14d
+ movl %r13d,%eax
+ movl %ebp,12(%rsp)
+ movl %edi,%ecx
+ xorl 24(%rsp),%r14d
+ xorl %r12d,%eax
+ roll $5,%ecx
+ xorl 48(%rsp),%r14d
+ andl %r11d,%eax
+ leal 1518500249(%rbp,%rsi,1),%esi
+ roll $30,%r11d
+ xorl %r13d,%eax
+ addl %ecx,%esi
+ roll $1,%r14d
+ addl %eax,%esi
+ xorl 20(%rsp),%edx
+ movl %edi,%eax
+ movl %r14d,16(%rsp)
+ movl %esi,%ecx
+ xorl 28(%rsp),%edx
+ xorl %r12d,%eax
+ roll $5,%ecx
+ xorl 52(%rsp),%edx
+ leal 1859775393(%r14,%r13,1),%r13d
+ xorl %r11d,%eax
+ addl %ecx,%r13d
+ roll $30,%edi
+ addl %eax,%r13d
+ roll $1,%edx
+ xorl 24(%rsp),%ebp
+ movl %esi,%eax
+ movl %edx,20(%rsp)
+ movl %r13d,%ecx
+ xorl 32(%rsp),%ebp
+ xorl %r11d,%eax
+ roll $5,%ecx
+ xorl 56(%rsp),%ebp
+ leal 1859775393(%rdx,%r12,1),%r12d
+ xorl %edi,%eax
+ addl %ecx,%r12d
+ roll $30,%esi
+ addl %eax,%r12d
+ roll $1,%ebp
+ xorl 28(%rsp),%r14d
+ movl %r13d,%eax
+ movl %ebp,24(%rsp)
+ movl %r12d,%ecx
+ xorl 36(%rsp),%r14d
+ xorl %edi,%eax
+ roll $5,%ecx
+ xorl 60(%rsp),%r14d
+ leal 1859775393(%rbp,%r11,1),%r11d
+ xorl %esi,%eax
+ addl %ecx,%r11d
+ roll $30,%r13d
+ addl %eax,%r11d
+ roll $1,%r14d
+ xorl 32(%rsp),%edx
+ movl %r12d,%eax
+ movl %r14d,28(%rsp)
+ movl %r11d,%ecx
+ xorl 40(%rsp),%edx
+ xorl %esi,%eax
+ roll $5,%ecx
+ xorl 0(%rsp),%edx
+ leal 1859775393(%r14,%rdi,1),%edi
+ xorl %r13d,%eax
+ addl %ecx,%edi
+ roll $30,%r12d
+ addl %eax,%edi
+ roll $1,%edx
+ xorl 36(%rsp),%ebp
+ movl %r11d,%eax
+ movl %edx,32(%rsp)
+ movl %edi,%ecx
+ xorl 44(%rsp),%ebp
+ xorl %r13d,%eax
+ roll $5,%ecx
+ xorl 4(%rsp),%ebp
+ leal 1859775393(%rdx,%rsi,1),%esi
+ xorl %r12d,%eax
+ addl %ecx,%esi
+ roll $30,%r11d
+ addl %eax,%esi
+ roll $1,%ebp
+ xorl 40(%rsp),%r14d
+ movl %edi,%eax
+ movl %ebp,36(%rsp)
+ movl %esi,%ecx
+ xorl 48(%rsp),%r14d
+ xorl %r12d,%eax
+ roll $5,%ecx
+ xorl 8(%rsp),%r14d
+ leal 1859775393(%rbp,%r13,1),%r13d
+ xorl %r11d,%eax
+ addl %ecx,%r13d
+ roll $30,%edi
+ addl %eax,%r13d
+ roll $1,%r14d
+ xorl 44(%rsp),%edx
+ movl %esi,%eax
+ movl %r14d,40(%rsp)
+ movl %r13d,%ecx
+ xorl 52(%rsp),%edx
+ xorl %r11d,%eax
+ roll $5,%ecx
+ xorl 12(%rsp),%edx
+ leal 1859775393(%r14,%r12,1),%r12d
+ xorl %edi,%eax
+ addl %ecx,%r12d
+ roll $30,%esi
+ addl %eax,%r12d
+ roll $1,%edx
+ xorl 48(%rsp),%ebp
+ movl %r13d,%eax
+ movl %edx,44(%rsp)
+ movl %r12d,%ecx
+ xorl 56(%rsp),%ebp
+ xorl %edi,%eax
+ roll $5,%ecx
+ xorl 16(%rsp),%ebp
+ leal 1859775393(%rdx,%r11,1),%r11d
+ xorl %esi,%eax
+ addl %ecx,%r11d
+ roll $30,%r13d
+ addl %eax,%r11d
+ roll $1,%ebp
+ xorl 52(%rsp),%r14d
+ movl %r12d,%eax
+ movl %ebp,48(%rsp)
+ movl %r11d,%ecx
+ xorl 60(%rsp),%r14d
+ xorl %esi,%eax
+ roll $5,%ecx
+ xorl 20(%rsp),%r14d
+ leal 1859775393(%rbp,%rdi,1),%edi
+ xorl %r13d,%eax
+ addl %ecx,%edi
+ roll $30,%r12d
+ addl %eax,%edi
+ roll $1,%r14d
+ xorl 56(%rsp),%edx
+ movl %r11d,%eax
+ movl %r14d,52(%rsp)
+ movl %edi,%ecx
+ xorl 0(%rsp),%edx
+ xorl %r13d,%eax
+ roll $5,%ecx
+ xorl 24(%rsp),%edx
+ leal 1859775393(%r14,%rsi,1),%esi
+ xorl %r12d,%eax
+ addl %ecx,%esi
+ roll $30,%r11d
+ addl %eax,%esi
+ roll $1,%edx
+ xorl 60(%rsp),%ebp
+ movl %edi,%eax
+ movl %edx,56(%rsp)
+ movl %esi,%ecx
+ xorl 4(%rsp),%ebp
+ xorl %r12d,%eax
+ roll $5,%ecx
+ xorl 28(%rsp),%ebp
+ leal 1859775393(%rdx,%r13,1),%r13d
+ xorl %r11d,%eax
+ addl %ecx,%r13d
+ roll $30,%edi
+ addl %eax,%r13d
+ roll $1,%ebp
+ xorl 0(%rsp),%r14d
+ movl %esi,%eax
+ movl %ebp,60(%rsp)
+ movl %r13d,%ecx
+ xorl 8(%rsp),%r14d
+ xorl %r11d,%eax
+ roll $5,%ecx
+ xorl 32(%rsp),%r14d
+ leal 1859775393(%rbp,%r12,1),%r12d
+ xorl %edi,%eax
+ addl %ecx,%r12d
+ roll $30,%esi
+ addl %eax,%r12d
+ roll $1,%r14d
+ xorl 4(%rsp),%edx
+ movl %r13d,%eax
+ movl %r14d,0(%rsp)
+ movl %r12d,%ecx
+ xorl 12(%rsp),%edx
+ xorl %edi,%eax
+ roll $5,%ecx
+ xorl 36(%rsp),%edx
+ leal 1859775393(%r14,%r11,1),%r11d
+ xorl %esi,%eax
+ addl %ecx,%r11d
+ roll $30,%r13d
+ addl %eax,%r11d
+ roll $1,%edx
+ xorl 8(%rsp),%ebp
+ movl %r12d,%eax
+ movl %edx,4(%rsp)
+ movl %r11d,%ecx
+ xorl 16(%rsp),%ebp
+ xorl %esi,%eax
+ roll $5,%ecx
+ xorl 40(%rsp),%ebp
+ leal 1859775393(%rdx,%rdi,1),%edi
+ xorl %r13d,%eax
+ addl %ecx,%edi
+ roll $30,%r12d
+ addl %eax,%edi
+ roll $1,%ebp
+ xorl 12(%rsp),%r14d
+ movl %r11d,%eax
+ movl %ebp,8(%rsp)
+ movl %edi,%ecx
+ xorl 20(%rsp),%r14d
+ xorl %r13d,%eax
+ roll $5,%ecx
+ xorl 44(%rsp),%r14d
+ leal 1859775393(%rbp,%rsi,1),%esi
+ xorl %r12d,%eax
+ addl %ecx,%esi
+ roll $30,%r11d
+ addl %eax,%esi
+ roll $1,%r14d
+ xorl 16(%rsp),%edx
+ movl %edi,%eax
+ movl %r14d,12(%rsp)
+ movl %esi,%ecx
+ xorl 24(%rsp),%edx
+ xorl %r12d,%eax
+ roll $5,%ecx
+ xorl 48(%rsp),%edx
+ leal 1859775393(%r14,%r13,1),%r13d
+ xorl %r11d,%eax
+ addl %ecx,%r13d
+ roll $30,%edi
+ addl %eax,%r13d
+ roll $1,%edx
+ xorl 20(%rsp),%ebp
+ movl %esi,%eax
+ movl %edx,16(%rsp)
+ movl %r13d,%ecx
+ xorl 28(%rsp),%ebp
+ xorl %r11d,%eax
+ roll $5,%ecx
+ xorl 52(%rsp),%ebp
+ leal 1859775393(%rdx,%r12,1),%r12d
+ xorl %edi,%eax
+ addl %ecx,%r12d
+ roll $30,%esi
+ addl %eax,%r12d
+ roll $1,%ebp
+ xorl 24(%rsp),%r14d
+ movl %r13d,%eax
+ movl %ebp,20(%rsp)
+ movl %r12d,%ecx
+ xorl 32(%rsp),%r14d
+ xorl %edi,%eax
+ roll $5,%ecx
+ xorl 56(%rsp),%r14d
+ leal 1859775393(%rbp,%r11,1),%r11d
+ xorl %esi,%eax
+ addl %ecx,%r11d
+ roll $30,%r13d
+ addl %eax,%r11d
+ roll $1,%r14d
+ xorl 28(%rsp),%edx
+ movl %r12d,%eax
+ movl %r14d,24(%rsp)
+ movl %r11d,%ecx
+ xorl 36(%rsp),%edx
+ xorl %esi,%eax
+ roll $5,%ecx
+ xorl 60(%rsp),%edx
+ leal 1859775393(%r14,%rdi,1),%edi
+ xorl %r13d,%eax
+ addl %ecx,%edi
+ roll $30,%r12d
+ addl %eax,%edi
+ roll $1,%edx
+ xorl 32(%rsp),%ebp
+ movl %r11d,%eax
+ movl %edx,28(%rsp)
+ movl %edi,%ecx
+ xorl 40(%rsp),%ebp
+ xorl %r13d,%eax
+ roll $5,%ecx
+ xorl 0(%rsp),%ebp
+ leal 1859775393(%rdx,%rsi,1),%esi
+ xorl %r12d,%eax
+ addl %ecx,%esi
+ roll $30,%r11d
+ addl %eax,%esi
+ roll $1,%ebp
+ xorl 36(%rsp),%r14d
+ movl %r12d,%eax
+ movl %ebp,32(%rsp)
+ movl %r12d,%ebx
+ xorl 44(%rsp),%r14d
+ andl %r11d,%eax
+ movl %esi,%ecx
+ xorl 4(%rsp),%r14d
+ leal -1894007588(%rbp,%r13,1),%r13d
+ xorl %r11d,%ebx
+ roll $5,%ecx
+ addl %eax,%r13d
+ roll $1,%r14d
+ andl %edi,%ebx
+ addl %ecx,%r13d
+ roll $30,%edi
+ addl %ebx,%r13d
+ xorl 40(%rsp),%edx
+ movl %r11d,%eax
+ movl %r14d,36(%rsp)
+ movl %r11d,%ebx
+ xorl 48(%rsp),%edx
+ andl %edi,%eax
+ movl %r13d,%ecx
+ xorl 8(%rsp),%edx
+ leal -1894007588(%r14,%r12,1),%r12d
+ xorl %edi,%ebx
+ roll $5,%ecx
+ addl %eax,%r12d
+ roll $1,%edx
+ andl %esi,%ebx
+ addl %ecx,%r12d
+ roll $30,%esi
+ addl %ebx,%r12d
+ xorl 44(%rsp),%ebp
+ movl %edi,%eax
+ movl %edx,40(%rsp)
+ movl %edi,%ebx
+ xorl 52(%rsp),%ebp
+ andl %esi,%eax
+ movl %r12d,%ecx
+ xorl 12(%rsp),%ebp
+ leal -1894007588(%rdx,%r11,1),%r11d
+ xorl %esi,%ebx
+ roll $5,%ecx
+ addl %eax,%r11d
+ roll $1,%ebp
+ andl %r13d,%ebx
+ addl %ecx,%r11d
+ roll $30,%r13d
+ addl %ebx,%r11d
+ xorl 48(%rsp),%r14d
+ movl %esi,%eax
+ movl %ebp,44(%rsp)
+ movl %esi,%ebx
+ xorl 56(%rsp),%r14d
+ andl %r13d,%eax
+ movl %r11d,%ecx
+ xorl 16(%rsp),%r14d
+ leal -1894007588(%rbp,%rdi,1),%edi
+ xorl %r13d,%ebx
+ roll $5,%ecx
+ addl %eax,%edi
+ roll $1,%r14d
+ andl %r12d,%ebx
+ addl %ecx,%edi
+ roll $30,%r12d
+ addl %ebx,%edi
+ xorl 52(%rsp),%edx
+ movl %r13d,%eax
+ movl %r14d,48(%rsp)
+ movl %r13d,%ebx
+ xorl 60(%rsp),%edx
+ andl %r12d,%eax
+ movl %edi,%ecx
+ xorl 20(%rsp),%edx
+ leal -1894007588(%r14,%rsi,1),%esi
+ xorl %r12d,%ebx
+ roll $5,%ecx
+ addl %eax,%esi
+ roll $1,%edx
+ andl %r11d,%ebx
+ addl %ecx,%esi
+ roll $30,%r11d
+ addl %ebx,%esi
+ xorl 56(%rsp),%ebp
+ movl %r12d,%eax
+ movl %edx,52(%rsp)
+ movl %r12d,%ebx
+ xorl 0(%rsp),%ebp
+ andl %r11d,%eax
+ movl %esi,%ecx
+ xorl 24(%rsp),%ebp
+ leal -1894007588(%rdx,%r13,1),%r13d
+ xorl %r11d,%ebx
+ roll $5,%ecx
+ addl %eax,%r13d
+ roll $1,%ebp
+ andl %edi,%ebx
+ addl %ecx,%r13d
+ roll $30,%edi
+ addl %ebx,%r13d
+ xorl 60(%rsp),%r14d
+ movl %r11d,%eax
+ movl %ebp,56(%rsp)
+ movl %r11d,%ebx
+ xorl 4(%rsp),%r14d
+ andl %edi,%eax
+ movl %r13d,%ecx
+ xorl 28(%rsp),%r14d
+ leal -1894007588(%rbp,%r12,1),%r12d
+ xorl %edi,%ebx
+ roll $5,%ecx
+ addl %eax,%r12d
+ roll $1,%r14d
+ andl %esi,%ebx
+ addl %ecx,%r12d
+ roll $30,%esi
+ addl %ebx,%r12d
+ xorl 0(%rsp),%edx
+ movl %edi,%eax
+ movl %r14d,60(%rsp)
+ movl %edi,%ebx
+ xorl 8(%rsp),%edx
+ andl %esi,%eax
+ movl %r12d,%ecx
+ xorl 32(%rsp),%edx
+ leal -1894007588(%r14,%r11,1),%r11d
+ xorl %esi,%ebx
+ roll $5,%ecx
+ addl %eax,%r11d
+ roll $1,%edx
+ andl %r13d,%ebx
+ addl %ecx,%r11d
+ roll $30,%r13d
+ addl %ebx,%r11d
+ xorl 4(%rsp),%ebp
+ movl %esi,%eax
+ movl %edx,0(%rsp)
+ movl %esi,%ebx
+ xorl 12(%rsp),%ebp
+ andl %r13d,%eax
+ movl %r11d,%ecx
+ xorl 36(%rsp),%ebp
+ leal -1894007588(%rdx,%rdi,1),%edi
+ xorl %r13d,%ebx
+ roll $5,%ecx
+ addl %eax,%edi
+ roll $1,%ebp
+ andl %r12d,%ebx
+ addl %ecx,%edi
+ roll $30,%r12d
+ addl %ebx,%edi
+ xorl 8(%rsp),%r14d
+ movl %r13d,%eax
+ movl %ebp,4(%rsp)
+ movl %r13d,%ebx
+ xorl 16(%rsp),%r14d
+ andl %r12d,%eax
+ movl %edi,%ecx
+ xorl 40(%rsp),%r14d
+ leal -1894007588(%rbp,%rsi,1),%esi
+ xorl %r12d,%ebx
+ roll $5,%ecx
+ addl %eax,%esi
+ roll $1,%r14d
+ andl %r11d,%ebx
+ addl %ecx,%esi
+ roll $30,%r11d
+ addl %ebx,%esi
+ xorl 12(%rsp),%edx
+ movl %r12d,%eax
+ movl %r14d,8(%rsp)
+ movl %r12d,%ebx
+ xorl 20(%rsp),%edx
+ andl %r11d,%eax
+ movl %esi,%ecx
+ xorl 44(%rsp),%edx
+ leal -1894007588(%r14,%r13,1),%r13d
+ xorl %r11d,%ebx
+ roll $5,%ecx
+ addl %eax,%r13d
+ roll $1,%edx
+ andl %edi,%ebx
+ addl %ecx,%r13d
+ roll $30,%edi
+ addl %ebx,%r13d
+ xorl 16(%rsp),%ebp
+ movl %r11d,%eax
+ movl %edx,12(%rsp)
+ movl %r11d,%ebx
+ xorl 24(%rsp),%ebp
+ andl %edi,%eax
+ movl %r13d,%ecx
+ xorl 48(%rsp),%ebp
+ leal -1894007588(%rdx,%r12,1),%r12d
+ xorl %edi,%ebx
+ roll $5,%ecx
+ addl %eax,%r12d
+ roll $1,%ebp
+ andl %esi,%ebx
+ addl %ecx,%r12d
+ roll $30,%esi
+ addl %ebx,%r12d
+ xorl 20(%rsp),%r14d
+ movl %edi,%eax
+ movl %ebp,16(%rsp)
+ movl %edi,%ebx
+ xorl 28(%rsp),%r14d
+ andl %esi,%eax
+ movl %r12d,%ecx
+ xorl 52(%rsp),%r14d
+ leal -1894007588(%rbp,%r11,1),%r11d
+ xorl %esi,%ebx
+ roll $5,%ecx
+ addl %eax,%r11d
+ roll $1,%r14d
+ andl %r13d,%ebx
+ addl %ecx,%r11d
+ roll $30,%r13d
+ addl %ebx,%r11d
+ xorl 24(%rsp),%edx
+ movl %esi,%eax
+ movl %r14d,20(%rsp)
+ movl %esi,%ebx
+ xorl 32(%rsp),%edx
+ andl %r13d,%eax
+ movl %r11d,%ecx
+ xorl 56(%rsp),%edx
+ leal -1894007588(%r14,%rdi,1),%edi
+ xorl %r13d,%ebx
+ roll $5,%ecx
+ addl %eax,%edi
+ roll $1,%edx
+ andl %r12d,%ebx
+ addl %ecx,%edi
+ roll $30,%r12d
+ addl %ebx,%edi
+ xorl 28(%rsp),%ebp
+ movl %r13d,%eax
+ movl %edx,24(%rsp)
+ movl %r13d,%ebx
+ xorl 36(%rsp),%ebp
+ andl %r12d,%eax
+ movl %edi,%ecx
+ xorl 60(%rsp),%ebp
+ leal -1894007588(%rdx,%rsi,1),%esi
+ xorl %r12d,%ebx
+ roll $5,%ecx
+ addl %eax,%esi
+ roll $1,%ebp
+ andl %r11d,%ebx
+ addl %ecx,%esi
+ roll $30,%r11d
+ addl %ebx,%esi
+ xorl 32(%rsp),%r14d
+ movl %r12d,%eax
+ movl %ebp,28(%rsp)
+ movl %r12d,%ebx
+ xorl 40(%rsp),%r14d
+ andl %r11d,%eax
+ movl %esi,%ecx
+ xorl 0(%rsp),%r14d
+ leal -1894007588(%rbp,%r13,1),%r13d
+ xorl %r11d,%ebx
+ roll $5,%ecx
+ addl %eax,%r13d
+ roll $1,%r14d
+ andl %edi,%ebx
+ addl %ecx,%r13d
+ roll $30,%edi
+ addl %ebx,%r13d
+ xorl 36(%rsp),%edx
+ movl %r11d,%eax
+ movl %r14d,32(%rsp)
+ movl %r11d,%ebx
+ xorl 44(%rsp),%edx
+ andl %edi,%eax
+ movl %r13d,%ecx
+ xorl 4(%rsp),%edx
+ leal -1894007588(%r14,%r12,1),%r12d
+ xorl %edi,%ebx
+ roll $5,%ecx
+ addl %eax,%r12d
+ roll $1,%edx
+ andl %esi,%ebx
+ addl %ecx,%r12d
+ roll $30,%esi
+ addl %ebx,%r12d
+ xorl 40(%rsp),%ebp
+ movl %edi,%eax
+ movl %edx,36(%rsp)
+ movl %edi,%ebx
+ xorl 48(%rsp),%ebp
+ andl %esi,%eax
+ movl %r12d,%ecx
+ xorl 8(%rsp),%ebp
+ leal -1894007588(%rdx,%r11,1),%r11d
+ xorl %esi,%ebx
+ roll $5,%ecx
+ addl %eax,%r11d
+ roll $1,%ebp
+ andl %r13d,%ebx
+ addl %ecx,%r11d
+ roll $30,%r13d
+ addl %ebx,%r11d
+ xorl 44(%rsp),%r14d
+ movl %esi,%eax
+ movl %ebp,40(%rsp)
+ movl %esi,%ebx
+ xorl 52(%rsp),%r14d
+ andl %r13d,%eax
+ movl %r11d,%ecx
+ xorl 12(%rsp),%r14d
+ leal -1894007588(%rbp,%rdi,1),%edi
+ xorl %r13d,%ebx
+ roll $5,%ecx
+ addl %eax,%edi
+ roll $1,%r14d
+ andl %r12d,%ebx
+ addl %ecx,%edi
+ roll $30,%r12d
+ addl %ebx,%edi
+ xorl 48(%rsp),%edx
+ movl %r13d,%eax
+ movl %r14d,44(%rsp)
+ movl %r13d,%ebx
+ xorl 56(%rsp),%edx
+ andl %r12d,%eax
+ movl %edi,%ecx
+ xorl 16(%rsp),%edx
+ leal -1894007588(%r14,%rsi,1),%esi
+ xorl %r12d,%ebx
+ roll $5,%ecx
+ addl %eax,%esi
+ roll $1,%edx
+ andl %r11d,%ebx
+ addl %ecx,%esi
+ roll $30,%r11d
+ addl %ebx,%esi
+ xorl 52(%rsp),%ebp
+ movl %edi,%eax
+ movl %edx,48(%rsp)
+ movl %esi,%ecx
+ xorl 60(%rsp),%ebp
+ xorl %r12d,%eax
+ roll $5,%ecx
+ xorl 20(%rsp),%ebp
+ leal -899497514(%rdx,%r13,1),%r13d
+ xorl %r11d,%eax
+ addl %ecx,%r13d
+ roll $30,%edi
+ addl %eax,%r13d
+ roll $1,%ebp
+ xorl 56(%rsp),%r14d
+ movl %esi,%eax
+ movl %ebp,52(%rsp)
+ movl %r13d,%ecx
+ xorl 0(%rsp),%r14d
+ xorl %r11d,%eax
+ roll $5,%ecx
+ xorl 24(%rsp),%r14d
+ leal -899497514(%rbp,%r12,1),%r12d
+ xorl %edi,%eax
+ addl %ecx,%r12d
+ roll $30,%esi
+ addl %eax,%r12d
+ roll $1,%r14d
+ xorl 60(%rsp),%edx
+ movl %r13d,%eax
+ movl %r14d,56(%rsp)
+ movl %r12d,%ecx
+ xorl 4(%rsp),%edx
+ xorl %edi,%eax
+ roll $5,%ecx
+ xorl 28(%rsp),%edx
+ leal -899497514(%r14,%r11,1),%r11d
+ xorl %esi,%eax
+ addl %ecx,%r11d
+ roll $30,%r13d
+ addl %eax,%r11d
+ roll $1,%edx
+ xorl 0(%rsp),%ebp
+ movl %r12d,%eax
+ movl %edx,60(%rsp)
+ movl %r11d,%ecx
+ xorl 8(%rsp),%ebp
+ xorl %esi,%eax
+ roll $5,%ecx
+ xorl 32(%rsp),%ebp
+ leal -899497514(%rdx,%rdi,1),%edi
+ xorl %r13d,%eax
+ addl %ecx,%edi
+ roll $30,%r12d
+ addl %eax,%edi
+ roll $1,%ebp
+ xorl 4(%rsp),%r14d
+ movl %r11d,%eax
+ movl %ebp,0(%rsp)
+ movl %edi,%ecx
+ xorl 12(%rsp),%r14d
+ xorl %r13d,%eax
+ roll $5,%ecx
+ xorl 36(%rsp),%r14d
+ leal -899497514(%rbp,%rsi,1),%esi
+ xorl %r12d,%eax
+ addl %ecx,%esi
+ roll $30,%r11d
+ addl %eax,%esi
+ roll $1,%r14d
+ xorl 8(%rsp),%edx
+ movl %edi,%eax
+ movl %r14d,4(%rsp)
+ movl %esi,%ecx
+ xorl 16(%rsp),%edx
+ xorl %r12d,%eax
+ roll $5,%ecx
+ xorl 40(%rsp),%edx
+ leal -899497514(%r14,%r13,1),%r13d
+ xorl %r11d,%eax
+ addl %ecx,%r13d
+ roll $30,%edi
+ addl %eax,%r13d
+ roll $1,%edx
+ xorl 12(%rsp),%ebp
+ movl %esi,%eax
+ movl %edx,8(%rsp)
+ movl %r13d,%ecx
+ xorl 20(%rsp),%ebp
+ xorl %r11d,%eax
+ roll $5,%ecx
+ xorl 44(%rsp),%ebp
+ leal -899497514(%rdx,%r12,1),%r12d
+ xorl %edi,%eax
+ addl %ecx,%r12d
+ roll $30,%esi
+ addl %eax,%r12d
+ roll $1,%ebp
+ xorl 16(%rsp),%r14d
+ movl %r13d,%eax
+ movl %ebp,12(%rsp)
+ movl %r12d,%ecx
+ xorl 24(%rsp),%r14d
+ xorl %edi,%eax
+ roll $5,%ecx
+ xorl 48(%rsp),%r14d
+ leal -899497514(%rbp,%r11,1),%r11d
+ xorl %esi,%eax
+ addl %ecx,%r11d
+ roll $30,%r13d
+ addl %eax,%r11d
+ roll $1,%r14d
+ xorl 20(%rsp),%edx
+ movl %r12d,%eax
+ movl %r14d,16(%rsp)
+ movl %r11d,%ecx
+ xorl 28(%rsp),%edx
+ xorl %esi,%eax
+ roll $5,%ecx
+ xorl 52(%rsp),%edx
+ leal -899497514(%r14,%rdi,1),%edi
+ xorl %r13d,%eax
+ addl %ecx,%edi
+ roll $30,%r12d
+ addl %eax,%edi
+ roll $1,%edx
+ xorl 24(%rsp),%ebp
+ movl %r11d,%eax
+ movl %edx,20(%rsp)
+ movl %edi,%ecx
+ xorl 32(%rsp),%ebp
+ xorl %r13d,%eax
+ roll $5,%ecx
+ xorl 56(%rsp),%ebp
+ leal -899497514(%rdx,%rsi,1),%esi
+ xorl %r12d,%eax
+ addl %ecx,%esi
+ roll $30,%r11d
+ addl %eax,%esi
+ roll $1,%ebp
+ xorl 28(%rsp),%r14d
+ movl %edi,%eax
+ movl %ebp,24(%rsp)
+ movl %esi,%ecx
+ xorl 36(%rsp),%r14d
+ xorl %r12d,%eax
+ roll $5,%ecx
+ xorl 60(%rsp),%r14d
+ leal -899497514(%rbp,%r13,1),%r13d
+ xorl %r11d,%eax
+ addl %ecx,%r13d
+ roll $30,%edi
+ addl %eax,%r13d
+ roll $1,%r14d
+ xorl 32(%rsp),%edx
+ movl %esi,%eax
+ movl %r14d,28(%rsp)
+ movl %r13d,%ecx
+ xorl 40(%rsp),%edx
+ xorl %r11d,%eax
+ roll $5,%ecx
+ xorl 0(%rsp),%edx
+ leal -899497514(%r14,%r12,1),%r12d
+ xorl %edi,%eax
+ addl %ecx,%r12d
+ roll $30,%esi
+ addl %eax,%r12d
+ roll $1,%edx
+ xorl 36(%rsp),%ebp
+ movl %r13d,%eax
+
+ movl %r12d,%ecx
+ xorl 44(%rsp),%ebp
+ xorl %edi,%eax
+ roll $5,%ecx
+ xorl 4(%rsp),%ebp
+ leal -899497514(%rdx,%r11,1),%r11d
+ xorl %esi,%eax
+ addl %ecx,%r11d
+ roll $30,%r13d
+ addl %eax,%r11d
+ roll $1,%ebp
+ xorl 40(%rsp),%r14d
+ movl %r12d,%eax
+
+ movl %r11d,%ecx
+ xorl 48(%rsp),%r14d
+ xorl %esi,%eax
+ roll $5,%ecx
+ xorl 8(%rsp),%r14d
+ leal -899497514(%rbp,%rdi,1),%edi
+ xorl %r13d,%eax
+ addl %ecx,%edi
+ roll $30,%r12d
+ addl %eax,%edi
+ roll $1,%r14d
+ xorl 44(%rsp),%edx
+ movl %r11d,%eax
+
+ movl %edi,%ecx
+ xorl 52(%rsp),%edx
+ xorl %r13d,%eax
+ roll $5,%ecx
+ xorl 12(%rsp),%edx
+ leal -899497514(%r14,%rsi,1),%esi
+ xorl %r12d,%eax
+ addl %ecx,%esi
+ roll $30,%r11d
+ addl %eax,%esi
+ roll $1,%edx
+ xorl 48(%rsp),%ebp
+ movl %edi,%eax
+
+ movl %esi,%ecx
+ xorl 56(%rsp),%ebp
+ xorl %r12d,%eax
+ roll $5,%ecx
+ xorl 16(%rsp),%ebp
+ leal -899497514(%rdx,%r13,1),%r13d
+ xorl %r11d,%eax
+ addl %ecx,%r13d
+ roll $30,%edi
+ addl %eax,%r13d
+ roll $1,%ebp
+ xorl 52(%rsp),%r14d
+ movl %esi,%eax
+
+ movl %r13d,%ecx
+ xorl 60(%rsp),%r14d
+ xorl %r11d,%eax
+ roll $5,%ecx
+ xorl 20(%rsp),%r14d
+ leal -899497514(%rbp,%r12,1),%r12d
+ xorl %edi,%eax
+ addl %ecx,%r12d
+ roll $30,%esi
+ addl %eax,%r12d
+ roll $1,%r14d
+ xorl 56(%rsp),%edx
+ movl %r13d,%eax
+
+ movl %r12d,%ecx
+ xorl 0(%rsp),%edx
+ xorl %edi,%eax
+ roll $5,%ecx
+ xorl 24(%rsp),%edx
+ leal -899497514(%r14,%r11,1),%r11d
+ xorl %esi,%eax
+ addl %ecx,%r11d
+ roll $30,%r13d
+ addl %eax,%r11d
+ roll $1,%edx
+ xorl 60(%rsp),%ebp
+ movl %r12d,%eax
+
+ movl %r11d,%ecx
+ xorl 4(%rsp),%ebp
+ xorl %esi,%eax
+ roll $5,%ecx
+ xorl 28(%rsp),%ebp
+ leal -899497514(%rdx,%rdi,1),%edi
+ xorl %r13d,%eax
+ addl %ecx,%edi
+ roll $30,%r12d
+ addl %eax,%edi
+ roll $1,%ebp
+ movl %r11d,%eax
+ movl %edi,%ecx
+ xorl %r13d,%eax
+ leal -899497514(%rbp,%rsi,1),%esi
+ roll $5,%ecx
+ xorl %r12d,%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 -40(%rsi),%r14
+ movq -32(%rsi),%r13
+ movq -24(%rsi),%r12
+ movq -16(%rsi),%rbp
+ movq -8(%rsi),%rbx
+ leaq (%rsi),%rsp
+.Lepilogue:
+ .byte 0xf3,0xc3
+.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:
+ movq %rsp,%rax
+ pushq %rbx
+ pushq %rbp
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ leaq -64(%rsp),%rsp
+ movq %rax,%r14
+ andq $-64,%rsp
+ movq %rdi,%r8
+ movq %rsi,%r9
+ movq %rdx,%r10
+
+ shlq $6,%r10
+ addq %r9,%r10
+ leaq K_XX_XX+64(%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
+ movl %ecx,%edi
+ xorl %edx,%edi
+ andl %edi,%esi
+
+ movdqa 64(%r11),%xmm6
+ movdqa -64(%r11),%xmm9
+ movdqu 0(%r9),%xmm0
+ movdqu 16(%r9),%xmm1
+ movdqu 32(%r9),%xmm2
+ movdqu 48(%r9),%xmm3
+.byte 102,15,56,0,198
+.byte 102,15,56,0,206
+.byte 102,15,56,0,214
+ addq $64,%r9
+ paddd %xmm9,%xmm0
+.byte 102,15,56,0,222
+ 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:
+ rorl $2,%ebx
+ pshufd $238,%xmm0,%xmm4
+ xorl %edx,%esi
+ movdqa %xmm3,%xmm8
+ paddd %xmm3,%xmm9
+ movl %eax,%edi
+ addl 0(%rsp),%ebp
+ punpcklqdq %xmm1,%xmm4
+ xorl %ecx,%ebx
+ roll $5,%eax
+ addl %esi,%ebp
+ psrldq $4,%xmm8
+ andl %ebx,%edi
+ xorl %ecx,%ebx
+ pxor %xmm0,%xmm4
+ addl %eax,%ebp
+ rorl $7,%eax
+ pxor %xmm2,%xmm8
+ xorl %ecx,%edi
+ movl %ebp,%esi
+ addl 4(%rsp),%edx
+ pxor %xmm8,%xmm4
+ xorl %ebx,%eax
+ roll $5,%ebp
+ movdqa %xmm9,48(%rsp)
+ addl %edi,%edx
+ andl %eax,%esi
+ movdqa %xmm4,%xmm10
+ xorl %ebx,%eax
+ addl %ebp,%edx
+ rorl $7,%ebp
+ movdqa %xmm4,%xmm8
+ xorl %ebx,%esi
+ pslldq $12,%xmm10
+ paddd %xmm4,%xmm4
+ movl %edx,%edi
+ addl 8(%rsp),%ecx
+ psrld $31,%xmm8
+ xorl %eax,%ebp
+ roll $5,%edx
+ addl %esi,%ecx
+ movdqa %xmm10,%xmm9
+ andl %ebp,%edi
+ xorl %eax,%ebp
+ psrld $30,%xmm10
+ addl %edx,%ecx
+ rorl $7,%edx
+ por %xmm8,%xmm4
+ xorl %eax,%edi
+ movl %ecx,%esi
+ addl 12(%rsp),%ebx
+ pslld $2,%xmm9
+ pxor %xmm10,%xmm4
+ xorl %ebp,%edx
+ movdqa -64(%r11),%xmm10
+ roll $5,%ecx
+ addl %edi,%ebx
+ andl %edx,%esi
+ pxor %xmm9,%xmm4
+ xorl %ebp,%edx
+ addl %ecx,%ebx
+ rorl $7,%ecx
+ pshufd $238,%xmm1,%xmm5
+ xorl %ebp,%esi
+ movdqa %xmm4,%xmm9
+ paddd %xmm4,%xmm10
+ movl %ebx,%edi
+ addl 16(%rsp),%eax
+ punpcklqdq %xmm2,%xmm5
+ xorl %edx,%ecx
+ roll $5,%ebx
+ addl %esi,%eax
+ psrldq $4,%xmm9
+ andl %ecx,%edi
+ xorl %edx,%ecx
+ pxor %xmm1,%xmm5
+ addl %ebx,%eax
+ rorl $7,%ebx
+ pxor %xmm3,%xmm9
+ xorl %edx,%edi
+ movl %eax,%esi
+ addl 20(%rsp),%ebp
+ pxor %xmm9,%xmm5
+ xorl %ecx,%ebx
+ roll $5,%eax
+ movdqa %xmm10,0(%rsp)
+ addl %edi,%ebp
+ andl %ebx,%esi
+ movdqa %xmm5,%xmm8
+ xorl %ecx,%ebx
+ addl %eax,%ebp
+ rorl $7,%eax
+ movdqa %xmm5,%xmm9
+ xorl %ecx,%esi
+ pslldq $12,%xmm8
+ paddd %xmm5,%xmm5
+ movl %ebp,%edi
+ addl 24(%rsp),%edx
+ psrld $31,%xmm9
+ xorl %ebx,%eax
+ roll $5,%ebp
+ addl %esi,%edx
+ movdqa %xmm8,%xmm10
+ andl %eax,%edi
+ xorl %ebx,%eax
+ psrld $30,%xmm8
+ addl %ebp,%edx
+ rorl $7,%ebp
+ por %xmm9,%xmm5
+ xorl %ebx,%edi
+ movl %edx,%esi
+ addl 28(%rsp),%ecx
+ pslld $2,%xmm10
+ pxor %xmm8,%xmm5
+ xorl %eax,%ebp
+ movdqa -32(%r11),%xmm8
+ roll $5,%edx
+ addl %edi,%ecx
+ andl %ebp,%esi
+ pxor %xmm10,%xmm5
+ xorl %eax,%ebp
+ addl %edx,%ecx
+ rorl $7,%edx
+ pshufd $238,%xmm2,%xmm6
+ xorl %eax,%esi
+ movdqa %xmm5,%xmm10
+ paddd %xmm5,%xmm8
+ movl %ecx,%edi
+ addl 32(%rsp),%ebx
+ punpcklqdq %xmm3,%xmm6
+ xorl %ebp,%edx
+ roll $5,%ecx
+ addl %esi,%ebx
+ psrldq $4,%xmm10
+ andl %edx,%edi
+ xorl %ebp,%edx
+ pxor %xmm2,%xmm6
+ addl %ecx,%ebx
+ rorl $7,%ecx
+ pxor %xmm4,%xmm10
+ xorl %ebp,%edi
+ movl %ebx,%esi
+ addl 36(%rsp),%eax
+ pxor %xmm10,%xmm6
+ xorl %edx,%ecx
+ roll $5,%ebx
+ movdqa %xmm8,16(%rsp)
+ addl %edi,%eax
+ andl %ecx,%esi
+ movdqa %xmm6,%xmm9
+ xorl %edx,%ecx
+ addl %ebx,%eax
+ rorl $7,%ebx
+ movdqa %xmm6,%xmm10
+ xorl %edx,%esi
+ pslldq $12,%xmm9
+ paddd %xmm6,%xmm6
+ movl %eax,%edi
+ addl 40(%rsp),%ebp
+ psrld $31,%xmm10
+ xorl %ecx,%ebx
+ roll $5,%eax
+ addl %esi,%ebp
+ movdqa %xmm9,%xmm8
+ andl %ebx,%edi
+ xorl %ecx,%ebx
+ psrld $30,%xmm9
+ addl %eax,%ebp
+ rorl $7,%eax
+ por %xmm10,%xmm6
+ xorl %ecx,%edi
+ movl %ebp,%esi
+ addl 44(%rsp),%edx
+ pslld $2,%xmm8
+ pxor %xmm9,%xmm6
+ xorl %ebx,%eax
+ movdqa -32(%r11),%xmm9
+ roll $5,%ebp
+ addl %edi,%edx
+ andl %eax,%esi
+ pxor %xmm8,%xmm6
+ xorl %ebx,%eax
+ addl %ebp,%edx
+ rorl $7,%ebp
+ pshufd $238,%xmm3,%xmm7
+ xorl %ebx,%esi
+ movdqa %xmm6,%xmm8
+ paddd %xmm6,%xmm9
+ movl %edx,%edi
+ addl 48(%rsp),%ecx
+ punpcklqdq %xmm4,%xmm7
+ xorl %eax,%ebp
+ roll $5,%edx
+ addl %esi,%ecx
+ psrldq $4,%xmm8
+ andl %ebp,%edi
+ xorl %eax,%ebp
+ pxor %xmm3,%xmm7
+ addl %edx,%ecx
+ rorl $7,%edx
+ pxor %xmm5,%xmm8
+ xorl %eax,%edi
+ movl %ecx,%esi
+ addl 52(%rsp),%ebx
+ pxor %xmm8,%xmm7
+ xorl %ebp,%edx
+ roll $5,%ecx
+ movdqa %xmm9,32(%rsp)
+ addl %edi,%ebx
+ andl %edx,%esi
+ movdqa %xmm7,%xmm10
+ xorl %ebp,%edx
+ addl %ecx,%ebx
+ rorl $7,%ecx
+ movdqa %xmm7,%xmm8
+ xorl %ebp,%esi
+ pslldq $12,%xmm10
+ paddd %xmm7,%xmm7
+ movl %ebx,%edi
+ addl 56(%rsp),%eax
+ psrld $31,%xmm8
+ xorl %edx,%ecx
+ roll $5,%ebx
+ addl %esi,%eax
+ movdqa %xmm10,%xmm9
+ andl %ecx,%edi
+ xorl %edx,%ecx
+ psrld $30,%xmm10
+ addl %ebx,%eax
+ rorl $7,%ebx
+ por %xmm8,%xmm7
+ xorl %edx,%edi
+ movl %eax,%esi
+ addl 60(%rsp),%ebp
+ pslld $2,%xmm9
+ pxor %xmm10,%xmm7
+ xorl %ecx,%ebx
+ movdqa -32(%r11),%xmm10
+ roll $5,%eax
+ addl %edi,%ebp
+ andl %ebx,%esi
+ pxor %xmm9,%xmm7
+ pshufd $238,%xmm6,%xmm9
+ xorl %ecx,%ebx
+ addl %eax,%ebp
+ rorl $7,%eax
+ pxor %xmm4,%xmm0
+ xorl %ecx,%esi
+ movl %ebp,%edi
+ addl 0(%rsp),%edx
+ punpcklqdq %xmm7,%xmm9
+ xorl %ebx,%eax
+ roll $5,%ebp
+ pxor %xmm1,%xmm0
+ addl %esi,%edx
+ andl %eax,%edi
+ movdqa %xmm10,%xmm8
+ xorl %ebx,%eax
+ paddd %xmm7,%xmm10
+ addl %ebp,%edx
+ pxor %xmm9,%xmm0
+ rorl $7,%ebp
+ xorl %ebx,%edi
+ movl %edx,%esi
+ addl 4(%rsp),%ecx
+ movdqa %xmm0,%xmm9
+ xorl %eax,%ebp
+ roll $5,%edx
+ movdqa %xmm10,48(%rsp)
+ addl %edi,%ecx
+ andl %ebp,%esi
+ xorl %eax,%ebp
+ pslld $2,%xmm0
+ addl %edx,%ecx
+ rorl $7,%edx
+ psrld $30,%xmm9
+ xorl %eax,%esi
+ movl %ecx,%edi
+ addl 8(%rsp),%ebx
+ por %xmm9,%xmm0
+ xorl %ebp,%edx
+ roll $5,%ecx
+ pshufd $238,%xmm7,%xmm10
+ addl %esi,%ebx
+ andl %edx,%edi
+ xorl %ebp,%edx
+ addl %ecx,%ebx
+ addl 12(%rsp),%eax
+ xorl %ebp,%edi
+ movl %ebx,%esi
+ roll $5,%ebx
+ addl %edi,%eax
+ xorl %edx,%esi
+ rorl $7,%ecx
+ addl %ebx,%eax
+ pxor %xmm5,%xmm1
+ addl 16(%rsp),%ebp
+ xorl %ecx,%esi
+ punpcklqdq %xmm0,%xmm10
+ movl %eax,%edi
+ roll $5,%eax
+ pxor %xmm2,%xmm1
+ addl %esi,%ebp
+ xorl %ecx,%edi
+ movdqa %xmm8,%xmm9
+ rorl $7,%ebx
+ paddd %xmm0,%xmm8
+ addl %eax,%ebp
+ pxor %xmm10,%xmm1
+ addl 20(%rsp),%edx
+ xorl %ebx,%edi
+ movl %ebp,%esi
+ roll $5,%ebp
+ movdqa %xmm1,%xmm10
+ addl %edi,%edx
+ xorl %ebx,%esi
+ movdqa %xmm8,0(%rsp)
+ rorl $7,%eax
+ addl %ebp,%edx
+ addl 24(%rsp),%ecx
+ pslld $2,%xmm1
+ xorl %eax,%esi
+ movl %edx,%edi
+ psrld $30,%xmm10
+ roll $5,%edx
+ addl %esi,%ecx
+ xorl %eax,%edi
+ rorl $7,%ebp
+ por %xmm10,%xmm1
+ addl %edx,%ecx
+ addl 28(%rsp),%ebx
+ pshufd $238,%xmm0,%xmm8
+ xorl %ebp,%edi
+ movl %ecx,%esi
+ roll $5,%ecx
+ addl %edi,%ebx
+ xorl %ebp,%esi
+ rorl $7,%edx
+ addl %ecx,%ebx
+ pxor %xmm6,%xmm2
+ addl 32(%rsp),%eax
+ xorl %edx,%esi
+ punpcklqdq %xmm1,%xmm8
+ movl %ebx,%edi
+ roll $5,%ebx
+ pxor %xmm3,%xmm2
+ addl %esi,%eax
+ xorl %edx,%edi
+ movdqa 0(%r11),%xmm10
+ rorl $7,%ecx
+ paddd %xmm1,%xmm9
+ addl %ebx,%eax
+ pxor %xmm8,%xmm2
+ addl 36(%rsp),%ebp
+ xorl %ecx,%edi
+ movl %eax,%esi
+ roll $5,%eax
+ movdqa %xmm2,%xmm8
+ addl %edi,%ebp
+ xorl %ecx,%esi
+ movdqa %xmm9,16(%rsp)
+ rorl $7,%ebx
+ addl %eax,%ebp
+ addl 40(%rsp),%edx
+ pslld $2,%xmm2
+ xorl %ebx,%esi
+ movl %ebp,%edi
+ psrld $30,%xmm8
+ roll $5,%ebp
+ addl %esi,%edx
+ xorl %ebx,%edi
+ rorl $7,%eax
+ por %xmm8,%xmm2
+ addl %ebp,%edx
+ addl 44(%rsp),%ecx
+ pshufd $238,%xmm1,%xmm9
+ xorl %eax,%edi
+ movl %edx,%esi
+ roll $5,%edx
+ addl %edi,%ecx
+ xorl %eax,%esi
+ rorl $7,%ebp
+ addl %edx,%ecx
+ pxor %xmm7,%xmm3
+ addl 48(%rsp),%ebx
+ xorl %ebp,%esi
+ punpcklqdq %xmm2,%xmm9
+ movl %ecx,%edi
+ roll $5,%ecx
+ pxor %xmm4,%xmm3
+ addl %esi,%ebx
+ xorl %ebp,%edi
+ movdqa %xmm10,%xmm8
+ rorl $7,%edx
+ paddd %xmm2,%xmm10
+ addl %ecx,%ebx
+ pxor %xmm9,%xmm3
+ addl 52(%rsp),%eax
+ xorl %edx,%edi
+ movl %ebx,%esi
+ roll $5,%ebx
+ movdqa %xmm3,%xmm9
+ addl %edi,%eax
+ xorl %edx,%esi
+ movdqa %xmm10,32(%rsp)
+ rorl $7,%ecx
+ addl %ebx,%eax
+ addl 56(%rsp),%ebp
+ pslld $2,%xmm3
+ xorl %ecx,%esi
+ movl %eax,%edi
+ psrld $30,%xmm9
+ roll $5,%eax
+ addl %esi,%ebp
+ xorl %ecx,%edi
+ rorl $7,%ebx
+ por %xmm9,%xmm3
+ addl %eax,%ebp
+ addl 60(%rsp),%edx
+ pshufd $238,%xmm2,%xmm10
+ xorl %ebx,%edi
+ movl %ebp,%esi
+ roll $5,%ebp
+ addl %edi,%edx
+ xorl %ebx,%esi
+ rorl $7,%eax
+ addl %ebp,%edx
+ pxor %xmm0,%xmm4
+ addl 0(%rsp),%ecx
+ xorl %eax,%esi
+ punpcklqdq %xmm3,%xmm10
+ movl %edx,%edi
+ roll $5,%edx
+ pxor %xmm5,%xmm4
+ addl %esi,%ecx
+ xorl %eax,%edi
+ movdqa %xmm8,%xmm9
+ rorl $7,%ebp
+ paddd %xmm3,%xmm8
+ addl %edx,%ecx
+ pxor %xmm10,%xmm4
+ addl 4(%rsp),%ebx
+ xorl %ebp,%edi
+ movl %ecx,%esi
+ roll $5,%ecx
+ movdqa %xmm4,%xmm10
+ addl %edi,%ebx
+ xorl %ebp,%esi
+ movdqa %xmm8,48(%rsp)
+ rorl $7,%edx
+ addl %ecx,%ebx
+ addl 8(%rsp),%eax
+ pslld $2,%xmm4
+ xorl %edx,%esi
+ movl %ebx,%edi
+ psrld $30,%xmm10
+ roll $5,%ebx
+ addl %esi,%eax
+ xorl %edx,%edi
+ rorl $7,%ecx
+ por %xmm10,%xmm4
+ addl %ebx,%eax
+ addl 12(%rsp),%ebp
+ pshufd $238,%xmm3,%xmm8
+ xorl %ecx,%edi
+ movl %eax,%esi
+ roll $5,%eax
+ addl %edi,%ebp
+ xorl %ecx,%esi
+ rorl $7,%ebx
+ addl %eax,%ebp
+ pxor %xmm1,%xmm5
+ addl 16(%rsp),%edx
+ xorl %ebx,%esi
+ punpcklqdq %xmm4,%xmm8
+ movl %ebp,%edi
+ roll $5,%ebp
+ pxor %xmm6,%xmm5
+ addl %esi,%edx
+ xorl %ebx,%edi
+ movdqa %xmm9,%xmm10
+ rorl $7,%eax
+ paddd %xmm4,%xmm9
+ addl %ebp,%edx
+ pxor %xmm8,%xmm5
+ addl 20(%rsp),%ecx
+ xorl %eax,%edi
+ movl %edx,%esi
+ roll $5,%edx
+ movdqa %xmm5,%xmm8
+ addl %edi,%ecx
+ xorl %eax,%esi
+ movdqa %xmm9,0(%rsp)
+ rorl $7,%ebp
+ addl %edx,%ecx
+ addl 24(%rsp),%ebx
+ pslld $2,%xmm5
+ xorl %ebp,%esi
+ movl %ecx,%edi
+ psrld $30,%xmm8
+ roll $5,%ecx
+ addl %esi,%ebx
+ xorl %ebp,%edi
+ rorl $7,%edx
+ por %xmm8,%xmm5
+ addl %ecx,%ebx
+ addl 28(%rsp),%eax
+ pshufd $238,%xmm4,%xmm9
+ rorl $7,%ecx
+ movl %ebx,%esi
+ xorl %edx,%edi
+ roll $5,%ebx
+ addl %edi,%eax
+ xorl %ecx,%esi
+ xorl %edx,%ecx
+ addl %ebx,%eax
+ pxor %xmm2,%xmm6
+ addl 32(%rsp),%ebp
+ andl %ecx,%esi
+ xorl %edx,%ecx
+ rorl $7,%ebx
+ punpcklqdq %xmm5,%xmm9
+ movl %eax,%edi
+ xorl %ecx,%esi
+ pxor %xmm7,%xmm6
+ roll $5,%eax
+ addl %esi,%ebp
+ movdqa %xmm10,%xmm8
+ xorl %ebx,%edi
+ paddd %xmm5,%xmm10
+ xorl %ecx,%ebx
+ pxor %xmm9,%xmm6
+ addl %eax,%ebp
+ addl 36(%rsp),%edx
+ andl %ebx,%edi
+ xorl %ecx,%ebx
+ rorl $7,%eax
+ movdqa %xmm6,%xmm9
+ movl %ebp,%esi
+ xorl %ebx,%edi
+ movdqa %xmm10,16(%rsp)
+ roll $5,%ebp
+ addl %edi,%edx
+ xorl %eax,%esi
+ pslld $2,%xmm6
+ xorl %ebx,%eax
+ addl %ebp,%edx
+ psrld $30,%xmm9
+ addl 40(%rsp),%ecx
+ andl %eax,%esi
+ xorl %ebx,%eax
+ por %xmm9,%xmm6
+ rorl $7,%ebp
+ movl %edx,%edi
+ xorl %eax,%esi
+ roll $5,%edx
+ pshufd $238,%xmm5,%xmm10
+ addl %esi,%ecx
+ xorl %ebp,%edi
+ xorl %eax,%ebp
+ addl %edx,%ecx
+ addl 44(%rsp),%ebx
+ andl %ebp,%edi
+ xorl %eax,%ebp
+ rorl $7,%edx
+ movl %ecx,%esi
+ xorl %ebp,%edi
+ roll $5,%ecx
+ addl %edi,%ebx
+ xorl %edx,%esi
+ xorl %ebp,%edx
+ addl %ecx,%ebx
+ pxor %xmm3,%xmm7
+ addl 48(%rsp),%eax
+ andl %edx,%esi
+ xorl %ebp,%edx
+ rorl $7,%ecx
+ punpcklqdq %xmm6,%xmm10
+ movl %ebx,%edi
+ xorl %edx,%esi
+ pxor %xmm0,%xmm7
+ roll $5,%ebx
+ addl %esi,%eax
+ movdqa 32(%r11),%xmm9
+ xorl %ecx,%edi
+ paddd %xmm6,%xmm8
+ xorl %edx,%ecx
+ pxor %xmm10,%xmm7
+ addl %ebx,%eax
+ addl 52(%rsp),%ebp
+ andl %ecx,%edi
+ xorl %edx,%ecx
+ rorl $7,%ebx
+ movdqa %xmm7,%xmm10
+ movl %eax,%esi
+ xorl %ecx,%edi
+ movdqa %xmm8,32(%rsp)
+ roll $5,%eax
+ addl %edi,%ebp
+ xorl %ebx,%esi
+ pslld $2,%xmm7
+ xorl %ecx,%ebx
+ addl %eax,%ebp
+ psrld $30,%xmm10
+ addl 56(%rsp),%edx
+ andl %ebx,%esi
+ xorl %ecx,%ebx
+ por %xmm10,%xmm7
+ rorl $7,%eax
+ movl %ebp,%edi
+ xorl %ebx,%esi
+ roll $5,%ebp
+ pshufd $238,%xmm6,%xmm8
+ addl %esi,%edx
+ xorl %eax,%edi
+ xorl %ebx,%eax
+ addl %ebp,%edx
+ addl 60(%rsp),%ecx
+ andl %eax,%edi
+ xorl %ebx,%eax
+ rorl $7,%ebp
+ movl %edx,%esi
+ xorl %eax,%edi
+ roll $5,%edx
+ addl %edi,%ecx
+ xorl %ebp,%esi
+ xorl %eax,%ebp
+ addl %edx,%ecx
+ pxor %xmm4,%xmm0
+ addl 0(%rsp),%ebx
+ andl %ebp,%esi
+ xorl %eax,%ebp
+ rorl $7,%edx
+ punpcklqdq %xmm7,%xmm8
+ movl %ecx,%edi
+ xorl %ebp,%esi
+ pxor %xmm1,%xmm0
+ roll $5,%ecx
+ addl %esi,%ebx
+ movdqa %xmm9,%xmm10
+ xorl %edx,%edi
+ paddd %xmm7,%xmm9
+ xorl %ebp,%edx
+ pxor %xmm8,%xmm0
+ addl %ecx,%ebx
+ addl 4(%rsp),%eax
+ andl %edx,%edi
+ xorl %ebp,%edx
+ rorl $7,%ecx
+ movdqa %xmm0,%xmm8
+ movl %ebx,%esi
+ xorl %edx,%edi
+ movdqa %xmm9,48(%rsp)
+ roll $5,%ebx
+ addl %edi,%eax
+ xorl %ecx,%esi
+ pslld $2,%xmm0
+ xorl %edx,%ecx
+ addl %ebx,%eax
+ psrld $30,%xmm8
+ addl 8(%rsp),%ebp
+ andl %ecx,%esi
+ xorl %edx,%ecx
+ por %xmm8,%xmm0
+ rorl $7,%ebx
+ movl %eax,%edi
+ xorl %ecx,%esi
+ roll $5,%eax
+ pshufd $238,%xmm7,%xmm9
+ addl %esi,%ebp
+ xorl %ebx,%edi
+ xorl %ecx,%ebx
+ addl %eax,%ebp
+ addl 12(%rsp),%edx
+ andl %ebx,%edi
+ xorl %ecx,%ebx
+ rorl $7,%eax
+ movl %ebp,%esi
+ xorl %ebx,%edi
+ roll $5,%ebp
+ addl %edi,%edx
+ xorl %eax,%esi
+ xorl %ebx,%eax
+ addl %ebp,%edx
+ pxor %xmm5,%xmm1
+ addl 16(%rsp),%ecx
+ andl %eax,%esi
+ xorl %ebx,%eax
+ rorl $7,%ebp
+ punpcklqdq %xmm0,%xmm9
+ movl %edx,%edi
+ xorl %eax,%esi
+ pxor %xmm2,%xmm1
+ roll $5,%edx
+ addl %esi,%ecx
+ movdqa %xmm10,%xmm8
+ xorl %ebp,%edi
+ paddd %xmm0,%xmm10
+ xorl %eax,%ebp
+ pxor %xmm9,%xmm1
+ addl %edx,%ecx
+ addl 20(%rsp),%ebx
+ andl %ebp,%edi
+ xorl %eax,%ebp
+ rorl $7,%edx
+ movdqa %xmm1,%xmm9
+ movl %ecx,%esi
+ xorl %ebp,%edi
+ movdqa %xmm10,0(%rsp)
+ roll $5,%ecx
+ addl %edi,%ebx
+ xorl %edx,%esi
+ pslld $2,%xmm1
+ xorl %ebp,%edx
+ addl %ecx,%ebx
+ psrld $30,%xmm9
+ addl 24(%rsp),%eax
+ andl %edx,%esi
+ xorl %ebp,%edx
+ por %xmm9,%xmm1
+ rorl $7,%ecx
+ movl %ebx,%edi
+ xorl %edx,%esi
+ roll $5,%ebx
+ pshufd $238,%xmm0,%xmm10
+ addl %esi,%eax
+ xorl %ecx,%edi
+ xorl %edx,%ecx
+ addl %ebx,%eax
+ addl 28(%rsp),%ebp
+ andl %ecx,%edi
+ xorl %edx,%ecx
+ rorl $7,%ebx
+ movl %eax,%esi
+ xorl %ecx,%edi
+ roll $5,%eax
+ addl %edi,%ebp
+ xorl %ebx,%esi
+ xorl %ecx,%ebx
+ addl %eax,%ebp
+ pxor %xmm6,%xmm2
+ addl 32(%rsp),%edx
+ andl %ebx,%esi
+ xorl %ecx,%ebx
+ rorl $7,%eax
+ punpcklqdq %xmm1,%xmm10
+ movl %ebp,%edi
+ xorl %ebx,%esi
+ pxor %xmm3,%xmm2
+ roll $5,%ebp
+ addl %esi,%edx
+ movdqa %xmm8,%xmm9
+ xorl %eax,%edi
+ paddd %xmm1,%xmm8
+ xorl %ebx,%eax
+ pxor %xmm10,%xmm2
+ addl %ebp,%edx
+ addl 36(%rsp),%ecx
+ andl %eax,%edi
+ xorl %ebx,%eax
+ rorl $7,%ebp
+ movdqa %xmm2,%xmm10
+ movl %edx,%esi
+ xorl %eax,%edi
+ movdqa %xmm8,16(%rsp)
+ roll $5,%edx
+ addl %edi,%ecx
+ xorl %ebp,%esi
+ pslld $2,%xmm2
+ xorl %eax,%ebp
+ addl %edx,%ecx
+ psrld $30,%xmm10
+ addl 40(%rsp),%ebx
+ andl %ebp,%esi
+ xorl %eax,%ebp
+ por %xmm10,%xmm2
+ rorl $7,%edx
+ movl %ecx,%edi
+ xorl %ebp,%esi
+ roll $5,%ecx
+ pshufd $238,%xmm1,%xmm8
+ addl %esi,%ebx
+ xorl %edx,%edi
+ xorl %ebp,%edx
+ addl %ecx,%ebx
+ addl 44(%rsp),%eax
+ andl %edx,%edi
+ xorl %ebp,%edx
+ rorl $7,%ecx
+ movl %ebx,%esi
+ xorl %edx,%edi
+ roll $5,%ebx
+ addl %edi,%eax
+ xorl %edx,%esi
+ addl %ebx,%eax
+ pxor %xmm7,%xmm3
+ addl 48(%rsp),%ebp
+ xorl %ecx,%esi
+ punpcklqdq %xmm2,%xmm8
+ movl %eax,%edi
+ roll $5,%eax
+ pxor %xmm4,%xmm3
+ addl %esi,%ebp
+ xorl %ecx,%edi
+ movdqa %xmm9,%xmm10
+ rorl $7,%ebx
+ paddd %xmm2,%xmm9
+ addl %eax,%ebp
+ pxor %xmm8,%xmm3
+ addl 52(%rsp),%edx
+ xorl %ebx,%edi
+ movl %ebp,%esi
+ roll $5,%ebp
+ movdqa %xmm3,%xmm8
+ addl %edi,%edx
+ xorl %ebx,%esi
+ movdqa %xmm9,32(%rsp)
+ rorl $7,%eax
+ addl %ebp,%edx
+ addl 56(%rsp),%ecx
+ pslld $2,%xmm3
+ xorl %eax,%esi
+ movl %edx,%edi
+ psrld $30,%xmm8
+ roll $5,%edx
+ addl %esi,%ecx
+ xorl %eax,%edi
+ rorl $7,%ebp
+ por %xmm8,%xmm3
+ addl %edx,%ecx
+ addl 60(%rsp),%ebx
+ xorl %ebp,%edi
+ movl %ecx,%esi
+ roll $5,%ecx
+ addl %edi,%ebx
+ xorl %ebp,%esi
+ rorl $7,%edx
+ addl %ecx,%ebx
+ addl 0(%rsp),%eax
+ xorl %edx,%esi
+ movl %ebx,%edi
+ roll $5,%ebx
+ paddd %xmm3,%xmm10
+ addl %esi,%eax
+ xorl %edx,%edi
+ movdqa %xmm10,48(%rsp)
+ rorl $7,%ecx
+ addl %ebx,%eax
+ addl 4(%rsp),%ebp
+ xorl %ecx,%edi
+ movl %eax,%esi
+ roll $5,%eax
+ addl %edi,%ebp
+ xorl %ecx,%esi
+ rorl $7,%ebx
+ addl %eax,%ebp
+ addl 8(%rsp),%edx
+ xorl %ebx,%esi
+ movl %ebp,%edi
+ roll $5,%ebp
+ addl %esi,%edx
+ xorl %ebx,%edi
+ rorl $7,%eax
+ addl %ebp,%edx
+ addl 12(%rsp),%ecx
+ xorl %eax,%edi
+ movl %edx,%esi
+ roll $5,%edx
+ addl %edi,%ecx
+ xorl %eax,%esi
+ rorl $7,%ebp
+ addl %edx,%ecx
+ cmpq %r10,%r9
+ je .Ldone_ssse3
+ movdqa 64(%r11),%xmm6
+ movdqa -64(%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 %ebp,%esi
+ movl %ecx,%edi
+.byte 102,15,56,0,206
+ roll $5,%ecx
+ addl %esi,%ebx
+ xorl %ebp,%edi
+ rorl $7,%edx
+ paddd %xmm9,%xmm0
+ addl %ecx,%ebx
+ addl 20(%rsp),%eax
+ xorl %edx,%edi
+ movl %ebx,%esi
+ movdqa %xmm0,0(%rsp)
+ roll $5,%ebx
+ addl %edi,%eax
+ xorl %edx,%esi
+ rorl $7,%ecx
+ psubd %xmm9,%xmm0
+ addl %ebx,%eax
+ addl 24(%rsp),%ebp
+ xorl %ecx,%esi
+ movl %eax,%edi
+ roll $5,%eax
+ addl %esi,%ebp
+ xorl %ecx,%edi
+ rorl $7,%ebx
+ addl %eax,%ebp
+ addl 28(%rsp),%edx
+ xorl %ebx,%edi
+ movl %ebp,%esi
+ roll $5,%ebp
+ addl %edi,%edx
+ xorl %ebx,%esi
+ rorl $7,%eax
+ addl %ebp,%edx
+ addl 32(%rsp),%ecx
+ xorl %eax,%esi
+ movl %edx,%edi
+.byte 102,15,56,0,214
+ roll $5,%edx
+ addl %esi,%ecx
+ xorl %eax,%edi
+ rorl $7,%ebp
+ paddd %xmm9,%xmm1
+ addl %edx,%ecx
+ addl 36(%rsp),%ebx
+ xorl %ebp,%edi
+ movl %ecx,%esi
+ movdqa %xmm1,16(%rsp)
+ roll $5,%ecx
+ addl %edi,%ebx
+ xorl %ebp,%esi
+ rorl $7,%edx
+ psubd %xmm9,%xmm1
+ addl %ecx,%ebx
+ addl 40(%rsp),%eax
+ xorl %edx,%esi
+ movl %ebx,%edi
+ roll $5,%ebx
+ addl %esi,%eax
+ xorl %edx,%edi
+ rorl $7,%ecx
+ addl %ebx,%eax
+ addl 44(%rsp),%ebp
+ xorl %ecx,%edi
+ movl %eax,%esi
+ roll $5,%eax
+ addl %edi,%ebp
+ xorl %ecx,%esi
+ rorl $7,%ebx
+ addl %eax,%ebp
+ addl 48(%rsp),%edx
+ xorl %ebx,%esi
+ movl %ebp,%edi
+.byte 102,15,56,0,222
+ roll $5,%ebp
+ addl %esi,%edx
+ xorl %ebx,%edi
+ rorl $7,%eax
+ paddd %xmm9,%xmm2
+ addl %ebp,%edx
+ addl 52(%rsp),%ecx
+ xorl %eax,%edi
+ movl %edx,%esi
+ movdqa %xmm2,32(%rsp)
+ roll $5,%edx
+ addl %edi,%ecx
+ xorl %eax,%esi
+ rorl $7,%ebp
+ psubd %xmm9,%xmm2
+ addl %edx,%ecx
+ addl 56(%rsp),%ebx
+ xorl %ebp,%esi
+ movl %ecx,%edi
+ roll $5,%ecx
+ addl %esi,%ebx
+ xorl %ebp,%edi
+ rorl $7,%edx
+ addl %ecx,%ebx
+ addl 60(%rsp),%eax
+ xorl %edx,%edi
+ movl %ebx,%esi
+ roll $5,%ebx
+ addl %edi,%eax
+ rorl $7,%ecx
+ addl %ebx,%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 %ecx,%edi
+ movl %edx,12(%r8)
+ xorl %edx,%edi
+ movl %ebp,16(%r8)
+ andl %edi,%esi
+ jmp .Loop_ssse3
+
+.align 16
+.Ldone_ssse3:
+ addl 16(%rsp),%ebx
+ xorl %ebp,%esi
+ movl %ecx,%edi
+ roll $5,%ecx
+ addl %esi,%ebx
+ xorl %ebp,%edi
+ rorl $7,%edx
+ addl %ecx,%ebx
+ addl 20(%rsp),%eax
+ xorl %edx,%edi
+ movl %ebx,%esi
+ roll $5,%ebx
+ addl %edi,%eax
+ xorl %edx,%esi
+ rorl $7,%ecx
+ addl %ebx,%eax
+ addl 24(%rsp),%ebp
+ xorl %ecx,%esi
+ movl %eax,%edi
+ roll $5,%eax
+ addl %esi,%ebp
+ xorl %ecx,%edi
+ rorl $7,%ebx
+ addl %eax,%ebp
+ addl 28(%rsp),%edx
+ xorl %ebx,%edi
+ movl %ebp,%esi
+ roll $5,%ebp
+ addl %edi,%edx
+ xorl %ebx,%esi
+ rorl $7,%eax
+ addl %ebp,%edx
+ addl 32(%rsp),%ecx
+ xorl %eax,%esi
+ movl %edx,%edi
+ roll $5,%edx
+ addl %esi,%ecx
+ xorl %eax,%edi
+ rorl $7,%ebp
+ addl %edx,%ecx
+ addl 36(%rsp),%ebx
+ xorl %ebp,%edi
+ movl %ecx,%esi
+ roll $5,%ecx
+ addl %edi,%ebx
+ xorl %ebp,%esi
+ rorl $7,%edx
+ addl %ecx,%ebx
+ addl 40(%rsp),%eax
+ xorl %edx,%esi
+ movl %ebx,%edi
+ roll $5,%ebx
+ addl %esi,%eax
+ xorl %edx,%edi
+ rorl $7,%ecx
+ addl %ebx,%eax
+ addl 44(%rsp),%ebp
+ xorl %ecx,%edi
+ movl %eax,%esi
+ roll $5,%eax
+ addl %edi,%ebp
+ xorl %ecx,%esi
+ rorl $7,%ebx
+ addl %eax,%ebp
+ addl 48(%rsp),%edx
+ xorl %ebx,%esi
+ movl %ebp,%edi
+ roll $5,%ebp
+ addl %esi,%edx
+ xorl %ebx,%edi
+ rorl $7,%eax
+ addl %ebp,%edx
+ addl 52(%rsp),%ecx
+ xorl %eax,%edi
+ movl %edx,%esi
+ roll $5,%edx
+ addl %edi,%ecx
+ xorl %eax,%esi
+ rorl $7,%ebp
+ addl %edx,%ecx
+ addl 56(%rsp),%ebx
+ xorl %ebp,%esi
+ movl %ecx,%edi
+ roll $5,%ecx
+ addl %esi,%ebx
+ xorl %ebp,%edi
+ rorl $7,%edx
+ addl %ecx,%ebx
+ addl 60(%rsp),%eax
+ xorl %edx,%edi
+ movl %ebx,%esi
+ roll $5,%ebx
+ addl %edi,%eax
+ rorl $7,%ecx
+ addl %ebx,%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 (%r14),%rsi
+ movq -40(%rsi),%r14
+ movq -32(%rsi),%r13
+ movq -24(%rsi),%r12
+ movq -16(%rsi),%rbp
+ movq -8(%rsi),%rbx
+ leaq (%rsi),%rsp
+.Lepilogue_ssse3:
+ .byte 0xf3,0xc3
+.size sha1_block_data_order_ssse3,.-sha1_block_data_order_ssse3
+.align 64
+K_XX_XX:
+.long 0x5a827999,0x5a827999,0x5a827999,0x5a827999
+.long 0x5a827999,0x5a827999,0x5a827999,0x5a827999
+.long 0x6ed9eba1,0x6ed9eba1,0x6ed9eba1,0x6ed9eba1
+.long 0x6ed9eba1,0x6ed9eba1,0x6ed9eba1,0x6ed9eba1
+.long 0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc
+.long 0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc
+.long 0xca62c1d6,0xca62c1d6,0xca62c1d6,0xca62c1d6
+.long 0xca62c1d6,0xca62c1d6,0xca62c1d6,0xca62c1d6
+.long 0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f
+.long 0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f
+.byte 0xf,0xe,0xd,0xc,0xb,0xa,0x9,0x8,0x7,0x6,0x5,0x4,0x3,0x2,0x1,0x0
+.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
+.align 64
+#endif
diff --git a/linux-x86_64/crypto/sha/sha256-x86_64.S b/linux-x86_64/crypto/sha/sha256-x86_64.S
new file mode 100644
index 0000000..4649baf
--- /dev/null
+++ b/linux-x86_64/crypto/sha/sha256-x86_64.S
@@ -0,0 +1,2843 @@
+#if defined(__x86_64__)
+.text
+
+
+.globl sha256_block_data_order
+.hidden sha256_block_data_order
+.type sha256_block_data_order,@function
+.align 16
+sha256_block_data_order:
+ leaq OPENSSL_ia32cap_P(%rip),%r11
+ movl 0(%r11),%r9d
+ movl 4(%r11),%r10d
+ movl 8(%r11),%r11d
+ testl $512,%r10d
+ jnz .Lssse3_shortcut
+ 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:
+
+ 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:
+ movl %ebx,%edi
+ leaq K256(%rip),%rbp
+ xorl %ecx,%edi
+ movl 0(%rsi),%r12d
+ movl %r8d,%r13d
+ movl %eax,%r14d
+ bswapl %r12d
+ rorl $14,%r13d
+ movl %r9d,%r15d
+
+ xorl %r8d,%r13d
+ rorl $9,%r14d
+ xorl %r10d,%r15d
+
+ movl %r12d,0(%rsp)
+ xorl %eax,%r14d
+ andl %r8d,%r15d
+
+ rorl $5,%r13d
+ addl %r11d,%r12d
+ xorl %r10d,%r15d
+
+ rorl $11,%r14d
+ xorl %r8d,%r13d
+ addl %r15d,%r12d
+
+ movl %eax,%r15d
+ addl (%rbp),%r12d
+ xorl %eax,%r14d
+
+ xorl %ebx,%r15d
+ rorl $6,%r13d
+ movl %ebx,%r11d
+
+ andl %r15d,%edi
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %edi,%r11d
+ addl %r12d,%edx
+ addl %r12d,%r11d
+
+ leaq 4(%rbp),%rbp
+ addl %r14d,%r11d
+ movl 4(%rsi),%r12d
+ movl %edx,%r13d
+ movl %r11d,%r14d
+ bswapl %r12d
+ rorl $14,%r13d
+ movl %r8d,%edi
+
+ xorl %edx,%r13d
+ rorl $9,%r14d
+ xorl %r9d,%edi
+
+ movl %r12d,4(%rsp)
+ xorl %r11d,%r14d
+ andl %edx,%edi
+
+ rorl $5,%r13d
+ addl %r10d,%r12d
+ xorl %r9d,%edi
+
+ rorl $11,%r14d
+ xorl %edx,%r13d
+ addl %edi,%r12d
+
+ movl %r11d,%edi
+ addl (%rbp),%r12d
+ xorl %r11d,%r14d
+
+ xorl %eax,%edi
+ rorl $6,%r13d
+ movl %eax,%r10d
+
+ andl %edi,%r15d
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %r15d,%r10d
+ addl %r12d,%ecx
+ addl %r12d,%r10d
+
+ leaq 4(%rbp),%rbp
+ addl %r14d,%r10d
+ movl 8(%rsi),%r12d
+ movl %ecx,%r13d
+ movl %r10d,%r14d
+ bswapl %r12d
+ rorl $14,%r13d
+ movl %edx,%r15d
+
+ xorl %ecx,%r13d
+ rorl $9,%r14d
+ xorl %r8d,%r15d
+
+ movl %r12d,8(%rsp)
+ xorl %r10d,%r14d
+ andl %ecx,%r15d
+
+ rorl $5,%r13d
+ addl %r9d,%r12d
+ xorl %r8d,%r15d
+
+ rorl $11,%r14d
+ xorl %ecx,%r13d
+ addl %r15d,%r12d
+
+ movl %r10d,%r15d
+ addl (%rbp),%r12d
+ xorl %r10d,%r14d
+
+ xorl %r11d,%r15d
+ rorl $6,%r13d
+ movl %r11d,%r9d
+
+ andl %r15d,%edi
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %edi,%r9d
+ addl %r12d,%ebx
+ addl %r12d,%r9d
+
+ leaq 4(%rbp),%rbp
+ addl %r14d,%r9d
+ movl 12(%rsi),%r12d
+ movl %ebx,%r13d
+ movl %r9d,%r14d
+ bswapl %r12d
+ rorl $14,%r13d
+ movl %ecx,%edi
+
+ xorl %ebx,%r13d
+ rorl $9,%r14d
+ xorl %edx,%edi
+
+ movl %r12d,12(%rsp)
+ xorl %r9d,%r14d
+ andl %ebx,%edi
+
+ rorl $5,%r13d
+ addl %r8d,%r12d
+ xorl %edx,%edi
+
+ rorl $11,%r14d
+ xorl %ebx,%r13d
+ addl %edi,%r12d
+
+ movl %r9d,%edi
+ addl (%rbp),%r12d
+ xorl %r9d,%r14d
+
+ xorl %r10d,%edi
+ rorl $6,%r13d
+ movl %r10d,%r8d
+
+ andl %edi,%r15d
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %r15d,%r8d
+ addl %r12d,%eax
+ addl %r12d,%r8d
+
+ leaq 20(%rbp),%rbp
+ addl %r14d,%r8d
+ movl 16(%rsi),%r12d
+ movl %eax,%r13d
+ movl %r8d,%r14d
+ bswapl %r12d
+ rorl $14,%r13d
+ movl %ebx,%r15d
+
+ xorl %eax,%r13d
+ rorl $9,%r14d
+ xorl %ecx,%r15d
+
+ movl %r12d,16(%rsp)
+ xorl %r8d,%r14d
+ andl %eax,%r15d
+
+ rorl $5,%r13d
+ addl %edx,%r12d
+ xorl %ecx,%r15d
+
+ rorl $11,%r14d
+ xorl %eax,%r13d
+ addl %r15d,%r12d
+
+ movl %r8d,%r15d
+ addl (%rbp),%r12d
+ xorl %r8d,%r14d
+
+ xorl %r9d,%r15d
+ rorl $6,%r13d
+ movl %r9d,%edx
+
+ andl %r15d,%edi
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %edi,%edx
+ addl %r12d,%r11d
+ addl %r12d,%edx
+
+ leaq 4(%rbp),%rbp
+ addl %r14d,%edx
+ movl 20(%rsi),%r12d
+ movl %r11d,%r13d
+ movl %edx,%r14d
+ bswapl %r12d
+ rorl $14,%r13d
+ movl %eax,%edi
+
+ xorl %r11d,%r13d
+ rorl $9,%r14d
+ xorl %ebx,%edi
+
+ movl %r12d,20(%rsp)
+ xorl %edx,%r14d
+ andl %r11d,%edi
+
+ rorl $5,%r13d
+ addl %ecx,%r12d
+ xorl %ebx,%edi
+
+ rorl $11,%r14d
+ xorl %r11d,%r13d
+ addl %edi,%r12d
+
+ movl %edx,%edi
+ addl (%rbp),%r12d
+ xorl %edx,%r14d
+
+ xorl %r8d,%edi
+ rorl $6,%r13d
+ movl %r8d,%ecx
+
+ andl %edi,%r15d
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %r15d,%ecx
+ addl %r12d,%r10d
+ addl %r12d,%ecx
+
+ leaq 4(%rbp),%rbp
+ addl %r14d,%ecx
+ movl 24(%rsi),%r12d
+ movl %r10d,%r13d
+ movl %ecx,%r14d
+ bswapl %r12d
+ rorl $14,%r13d
+ movl %r11d,%r15d
+
+ xorl %r10d,%r13d
+ rorl $9,%r14d
+ xorl %eax,%r15d
+
+ movl %r12d,24(%rsp)
+ xorl %ecx,%r14d
+ andl %r10d,%r15d
+
+ rorl $5,%r13d
+ addl %ebx,%r12d
+ xorl %eax,%r15d
+
+ rorl $11,%r14d
+ xorl %r10d,%r13d
+ addl %r15d,%r12d
+
+ movl %ecx,%r15d
+ addl (%rbp),%r12d
+ xorl %ecx,%r14d
+
+ xorl %edx,%r15d
+ rorl $6,%r13d
+ movl %edx,%ebx
+
+ andl %r15d,%edi
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %edi,%ebx
+ addl %r12d,%r9d
+ addl %r12d,%ebx
+
+ leaq 4(%rbp),%rbp
+ addl %r14d,%ebx
+ movl 28(%rsi),%r12d
+ movl %r9d,%r13d
+ movl %ebx,%r14d
+ bswapl %r12d
+ rorl $14,%r13d
+ movl %r10d,%edi
+
+ xorl %r9d,%r13d
+ rorl $9,%r14d
+ xorl %r11d,%edi
+
+ movl %r12d,28(%rsp)
+ xorl %ebx,%r14d
+ andl %r9d,%edi
+
+ rorl $5,%r13d
+ addl %eax,%r12d
+ xorl %r11d,%edi
+
+ rorl $11,%r14d
+ xorl %r9d,%r13d
+ addl %edi,%r12d
+
+ movl %ebx,%edi
+ addl (%rbp),%r12d
+ xorl %ebx,%r14d
+
+ xorl %ecx,%edi
+ rorl $6,%r13d
+ movl %ecx,%eax
+
+ andl %edi,%r15d
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %r15d,%eax
+ addl %r12d,%r8d
+ addl %r12d,%eax
+
+ leaq 20(%rbp),%rbp
+ addl %r14d,%eax
+ movl 32(%rsi),%r12d
+ movl %r8d,%r13d
+ movl %eax,%r14d
+ bswapl %r12d
+ rorl $14,%r13d
+ movl %r9d,%r15d
+
+ xorl %r8d,%r13d
+ rorl $9,%r14d
+ xorl %r10d,%r15d
+
+ movl %r12d,32(%rsp)
+ xorl %eax,%r14d
+ andl %r8d,%r15d
+
+ rorl $5,%r13d
+ addl %r11d,%r12d
+ xorl %r10d,%r15d
+
+ rorl $11,%r14d
+ xorl %r8d,%r13d
+ addl %r15d,%r12d
+
+ movl %eax,%r15d
+ addl (%rbp),%r12d
+ xorl %eax,%r14d
+
+ xorl %ebx,%r15d
+ rorl $6,%r13d
+ movl %ebx,%r11d
+
+ andl %r15d,%edi
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %edi,%r11d
+ addl %r12d,%edx
+ addl %r12d,%r11d
+
+ leaq 4(%rbp),%rbp
+ addl %r14d,%r11d
+ movl 36(%rsi),%r12d
+ movl %edx,%r13d
+ movl %r11d,%r14d
+ bswapl %r12d
+ rorl $14,%r13d
+ movl %r8d,%edi
+
+ xorl %edx,%r13d
+ rorl $9,%r14d
+ xorl %r9d,%edi
+
+ movl %r12d,36(%rsp)
+ xorl %r11d,%r14d
+ andl %edx,%edi
+
+ rorl $5,%r13d
+ addl %r10d,%r12d
+ xorl %r9d,%edi
+
+ rorl $11,%r14d
+ xorl %edx,%r13d
+ addl %edi,%r12d
+
+ movl %r11d,%edi
+ addl (%rbp),%r12d
+ xorl %r11d,%r14d
+
+ xorl %eax,%edi
+ rorl $6,%r13d
+ movl %eax,%r10d
+
+ andl %edi,%r15d
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %r15d,%r10d
+ addl %r12d,%ecx
+ addl %r12d,%r10d
+
+ leaq 4(%rbp),%rbp
+ addl %r14d,%r10d
+ movl 40(%rsi),%r12d
+ movl %ecx,%r13d
+ movl %r10d,%r14d
+ bswapl %r12d
+ rorl $14,%r13d
+ movl %edx,%r15d
+
+ xorl %ecx,%r13d
+ rorl $9,%r14d
+ xorl %r8d,%r15d
+
+ movl %r12d,40(%rsp)
+ xorl %r10d,%r14d
+ andl %ecx,%r15d
+
+ rorl $5,%r13d
+ addl %r9d,%r12d
+ xorl %r8d,%r15d
+
+ rorl $11,%r14d
+ xorl %ecx,%r13d
+ addl %r15d,%r12d
+
+ movl %r10d,%r15d
+ addl (%rbp),%r12d
+ xorl %r10d,%r14d
+
+ xorl %r11d,%r15d
+ rorl $6,%r13d
+ movl %r11d,%r9d
+
+ andl %r15d,%edi
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %edi,%r9d
+ addl %r12d,%ebx
+ addl %r12d,%r9d
+
+ leaq 4(%rbp),%rbp
+ addl %r14d,%r9d
+ movl 44(%rsi),%r12d
+ movl %ebx,%r13d
+ movl %r9d,%r14d
+ bswapl %r12d
+ rorl $14,%r13d
+ movl %ecx,%edi
+
+ xorl %ebx,%r13d
+ rorl $9,%r14d
+ xorl %edx,%edi
+
+ movl %r12d,44(%rsp)
+ xorl %r9d,%r14d
+ andl %ebx,%edi
+
+ rorl $5,%r13d
+ addl %r8d,%r12d
+ xorl %edx,%edi
+
+ rorl $11,%r14d
+ xorl %ebx,%r13d
+ addl %edi,%r12d
+
+ movl %r9d,%edi
+ addl (%rbp),%r12d
+ xorl %r9d,%r14d
+
+ xorl %r10d,%edi
+ rorl $6,%r13d
+ movl %r10d,%r8d
+
+ andl %edi,%r15d
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %r15d,%r8d
+ addl %r12d,%eax
+ addl %r12d,%r8d
+
+ leaq 20(%rbp),%rbp
+ addl %r14d,%r8d
+ movl 48(%rsi),%r12d
+ movl %eax,%r13d
+ movl %r8d,%r14d
+ bswapl %r12d
+ rorl $14,%r13d
+ movl %ebx,%r15d
+
+ xorl %eax,%r13d
+ rorl $9,%r14d
+ xorl %ecx,%r15d
+
+ movl %r12d,48(%rsp)
+ xorl %r8d,%r14d
+ andl %eax,%r15d
+
+ rorl $5,%r13d
+ addl %edx,%r12d
+ xorl %ecx,%r15d
+
+ rorl $11,%r14d
+ xorl %eax,%r13d
+ addl %r15d,%r12d
+
+ movl %r8d,%r15d
+ addl (%rbp),%r12d
+ xorl %r8d,%r14d
+
+ xorl %r9d,%r15d
+ rorl $6,%r13d
+ movl %r9d,%edx
+
+ andl %r15d,%edi
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %edi,%edx
+ addl %r12d,%r11d
+ addl %r12d,%edx
+
+ leaq 4(%rbp),%rbp
+ addl %r14d,%edx
+ movl 52(%rsi),%r12d
+ movl %r11d,%r13d
+ movl %edx,%r14d
+ bswapl %r12d
+ rorl $14,%r13d
+ movl %eax,%edi
+
+ xorl %r11d,%r13d
+ rorl $9,%r14d
+ xorl %ebx,%edi
+
+ movl %r12d,52(%rsp)
+ xorl %edx,%r14d
+ andl %r11d,%edi
+
+ rorl $5,%r13d
+ addl %ecx,%r12d
+ xorl %ebx,%edi
+
+ rorl $11,%r14d
+ xorl %r11d,%r13d
+ addl %edi,%r12d
+
+ movl %edx,%edi
+ addl (%rbp),%r12d
+ xorl %edx,%r14d
+
+ xorl %r8d,%edi
+ rorl $6,%r13d
+ movl %r8d,%ecx
+
+ andl %edi,%r15d
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %r15d,%ecx
+ addl %r12d,%r10d
+ addl %r12d,%ecx
+
+ leaq 4(%rbp),%rbp
+ addl %r14d,%ecx
+ movl 56(%rsi),%r12d
+ movl %r10d,%r13d
+ movl %ecx,%r14d
+ bswapl %r12d
+ rorl $14,%r13d
+ movl %r11d,%r15d
+
+ xorl %r10d,%r13d
+ rorl $9,%r14d
+ xorl %eax,%r15d
+
+ movl %r12d,56(%rsp)
+ xorl %ecx,%r14d
+ andl %r10d,%r15d
+
+ rorl $5,%r13d
+ addl %ebx,%r12d
+ xorl %eax,%r15d
+
+ rorl $11,%r14d
+ xorl %r10d,%r13d
+ addl %r15d,%r12d
+
+ movl %ecx,%r15d
+ addl (%rbp),%r12d
+ xorl %ecx,%r14d
+
+ xorl %edx,%r15d
+ rorl $6,%r13d
+ movl %edx,%ebx
+
+ andl %r15d,%edi
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %edi,%ebx
+ addl %r12d,%r9d
+ addl %r12d,%ebx
+
+ leaq 4(%rbp),%rbp
+ addl %r14d,%ebx
+ movl 60(%rsi),%r12d
+ movl %r9d,%r13d
+ movl %ebx,%r14d
+ bswapl %r12d
+ rorl $14,%r13d
+ movl %r10d,%edi
+
+ xorl %r9d,%r13d
+ rorl $9,%r14d
+ xorl %r11d,%edi
+
+ movl %r12d,60(%rsp)
+ xorl %ebx,%r14d
+ andl %r9d,%edi
+
+ rorl $5,%r13d
+ addl %eax,%r12d
+ xorl %r11d,%edi
+
+ rorl $11,%r14d
+ xorl %r9d,%r13d
+ addl %edi,%r12d
+
+ movl %ebx,%edi
+ addl (%rbp),%r12d
+ xorl %ebx,%r14d
+
+ xorl %ecx,%edi
+ rorl $6,%r13d
+ movl %ecx,%eax
+
+ andl %edi,%r15d
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %r15d,%eax
+ addl %r12d,%r8d
+ addl %r12d,%eax
+
+ leaq 20(%rbp),%rbp
+ jmp .Lrounds_16_xx
+.align 16
+.Lrounds_16_xx:
+ movl 4(%rsp),%r13d
+ movl 56(%rsp),%r15d
+
+ movl %r13d,%r12d
+ rorl $11,%r13d
+ addl %r14d,%eax
+ movl %r15d,%r14d
+ rorl $2,%r15d
+
+ xorl %r12d,%r13d
+ shrl $3,%r12d
+ rorl $7,%r13d
+ xorl %r14d,%r15d
+ shrl $10,%r14d
+
+ rorl $17,%r15d
+ xorl %r13d,%r12d
+ xorl %r14d,%r15d
+ addl 36(%rsp),%r12d
+
+ addl 0(%rsp),%r12d
+ movl %r8d,%r13d
+ addl %r15d,%r12d
+ movl %eax,%r14d
+ rorl $14,%r13d
+ movl %r9d,%r15d
+
+ xorl %r8d,%r13d
+ rorl $9,%r14d
+ xorl %r10d,%r15d
+
+ movl %r12d,0(%rsp)
+ xorl %eax,%r14d
+ andl %r8d,%r15d
+
+ rorl $5,%r13d
+ addl %r11d,%r12d
+ xorl %r10d,%r15d
+
+ rorl $11,%r14d
+ xorl %r8d,%r13d
+ addl %r15d,%r12d
+
+ movl %eax,%r15d
+ addl (%rbp),%r12d
+ xorl %eax,%r14d
+
+ xorl %ebx,%r15d
+ rorl $6,%r13d
+ movl %ebx,%r11d
+
+ andl %r15d,%edi
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %edi,%r11d
+ addl %r12d,%edx
+ addl %r12d,%r11d
+
+ leaq 4(%rbp),%rbp
+ movl 8(%rsp),%r13d
+ movl 60(%rsp),%edi
+
+ movl %r13d,%r12d
+ rorl $11,%r13d
+ addl %r14d,%r11d
+ movl %edi,%r14d
+ rorl $2,%edi
+
+ xorl %r12d,%r13d
+ shrl $3,%r12d
+ rorl $7,%r13d
+ xorl %r14d,%edi
+ shrl $10,%r14d
+
+ rorl $17,%edi
+ xorl %r13d,%r12d
+ xorl %r14d,%edi
+ addl 40(%rsp),%r12d
+
+ addl 4(%rsp),%r12d
+ movl %edx,%r13d
+ addl %edi,%r12d
+ movl %r11d,%r14d
+ rorl $14,%r13d
+ movl %r8d,%edi
+
+ xorl %edx,%r13d
+ rorl $9,%r14d
+ xorl %r9d,%edi
+
+ movl %r12d,4(%rsp)
+ xorl %r11d,%r14d
+ andl %edx,%edi
+
+ rorl $5,%r13d
+ addl %r10d,%r12d
+ xorl %r9d,%edi
+
+ rorl $11,%r14d
+ xorl %edx,%r13d
+ addl %edi,%r12d
+
+ movl %r11d,%edi
+ addl (%rbp),%r12d
+ xorl %r11d,%r14d
+
+ xorl %eax,%edi
+ rorl $6,%r13d
+ movl %eax,%r10d
+
+ andl %edi,%r15d
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %r15d,%r10d
+ addl %r12d,%ecx
+ addl %r12d,%r10d
+
+ leaq 4(%rbp),%rbp
+ movl 12(%rsp),%r13d
+ movl 0(%rsp),%r15d
+
+ movl %r13d,%r12d
+ rorl $11,%r13d
+ addl %r14d,%r10d
+ movl %r15d,%r14d
+ rorl $2,%r15d
+
+ xorl %r12d,%r13d
+ shrl $3,%r12d
+ rorl $7,%r13d
+ xorl %r14d,%r15d
+ shrl $10,%r14d
+
+ rorl $17,%r15d
+ xorl %r13d,%r12d
+ xorl %r14d,%r15d
+ addl 44(%rsp),%r12d
+
+ addl 8(%rsp),%r12d
+ movl %ecx,%r13d
+ addl %r15d,%r12d
+ movl %r10d,%r14d
+ rorl $14,%r13d
+ movl %edx,%r15d
+
+ xorl %ecx,%r13d
+ rorl $9,%r14d
+ xorl %r8d,%r15d
+
+ movl %r12d,8(%rsp)
+ xorl %r10d,%r14d
+ andl %ecx,%r15d
+
+ rorl $5,%r13d
+ addl %r9d,%r12d
+ xorl %r8d,%r15d
+
+ rorl $11,%r14d
+ xorl %ecx,%r13d
+ addl %r15d,%r12d
+
+ movl %r10d,%r15d
+ addl (%rbp),%r12d
+ xorl %r10d,%r14d
+
+ xorl %r11d,%r15d
+ rorl $6,%r13d
+ movl %r11d,%r9d
+
+ andl %r15d,%edi
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %edi,%r9d
+ addl %r12d,%ebx
+ addl %r12d,%r9d
+
+ leaq 4(%rbp),%rbp
+ movl 16(%rsp),%r13d
+ movl 4(%rsp),%edi
+
+ movl %r13d,%r12d
+ rorl $11,%r13d
+ addl %r14d,%r9d
+ movl %edi,%r14d
+ rorl $2,%edi
+
+ xorl %r12d,%r13d
+ shrl $3,%r12d
+ rorl $7,%r13d
+ xorl %r14d,%edi
+ shrl $10,%r14d
+
+ rorl $17,%edi
+ xorl %r13d,%r12d
+ xorl %r14d,%edi
+ addl 48(%rsp),%r12d
+
+ addl 12(%rsp),%r12d
+ movl %ebx,%r13d
+ addl %edi,%r12d
+ movl %r9d,%r14d
+ rorl $14,%r13d
+ movl %ecx,%edi
+
+ xorl %ebx,%r13d
+ rorl $9,%r14d
+ xorl %edx,%edi
+
+ movl %r12d,12(%rsp)
+ xorl %r9d,%r14d
+ andl %ebx,%edi
+
+ rorl $5,%r13d
+ addl %r8d,%r12d
+ xorl %edx,%edi
+
+ rorl $11,%r14d
+ xorl %ebx,%r13d
+ addl %edi,%r12d
+
+ movl %r9d,%edi
+ addl (%rbp),%r12d
+ xorl %r9d,%r14d
+
+ xorl %r10d,%edi
+ rorl $6,%r13d
+ movl %r10d,%r8d
+
+ andl %edi,%r15d
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %r15d,%r8d
+ addl %r12d,%eax
+ addl %r12d,%r8d
+
+ leaq 20(%rbp),%rbp
+ movl 20(%rsp),%r13d
+ movl 8(%rsp),%r15d
+
+ movl %r13d,%r12d
+ rorl $11,%r13d
+ addl %r14d,%r8d
+ movl %r15d,%r14d
+ rorl $2,%r15d
+
+ xorl %r12d,%r13d
+ shrl $3,%r12d
+ rorl $7,%r13d
+ xorl %r14d,%r15d
+ shrl $10,%r14d
+
+ rorl $17,%r15d
+ xorl %r13d,%r12d
+ xorl %r14d,%r15d
+ addl 52(%rsp),%r12d
+
+ addl 16(%rsp),%r12d
+ movl %eax,%r13d
+ addl %r15d,%r12d
+ movl %r8d,%r14d
+ rorl $14,%r13d
+ movl %ebx,%r15d
+
+ xorl %eax,%r13d
+ rorl $9,%r14d
+ xorl %ecx,%r15d
+
+ movl %r12d,16(%rsp)
+ xorl %r8d,%r14d
+ andl %eax,%r15d
+
+ rorl $5,%r13d
+ addl %edx,%r12d
+ xorl %ecx,%r15d
+
+ rorl $11,%r14d
+ xorl %eax,%r13d
+ addl %r15d,%r12d
+
+ movl %r8d,%r15d
+ addl (%rbp),%r12d
+ xorl %r8d,%r14d
+
+ xorl %r9d,%r15d
+ rorl $6,%r13d
+ movl %r9d,%edx
+
+ andl %r15d,%edi
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %edi,%edx
+ addl %r12d,%r11d
+ addl %r12d,%edx
+
+ leaq 4(%rbp),%rbp
+ movl 24(%rsp),%r13d
+ movl 12(%rsp),%edi
+
+ movl %r13d,%r12d
+ rorl $11,%r13d
+ addl %r14d,%edx
+ movl %edi,%r14d
+ rorl $2,%edi
+
+ xorl %r12d,%r13d
+ shrl $3,%r12d
+ rorl $7,%r13d
+ xorl %r14d,%edi
+ shrl $10,%r14d
+
+ rorl $17,%edi
+ xorl %r13d,%r12d
+ xorl %r14d,%edi
+ addl 56(%rsp),%r12d
+
+ addl 20(%rsp),%r12d
+ movl %r11d,%r13d
+ addl %edi,%r12d
+ movl %edx,%r14d
+ rorl $14,%r13d
+ movl %eax,%edi
+
+ xorl %r11d,%r13d
+ rorl $9,%r14d
+ xorl %ebx,%edi
+
+ movl %r12d,20(%rsp)
+ xorl %edx,%r14d
+ andl %r11d,%edi
+
+ rorl $5,%r13d
+ addl %ecx,%r12d
+ xorl %ebx,%edi
+
+ rorl $11,%r14d
+ xorl %r11d,%r13d
+ addl %edi,%r12d
+
+ movl %edx,%edi
+ addl (%rbp),%r12d
+ xorl %edx,%r14d
+
+ xorl %r8d,%edi
+ rorl $6,%r13d
+ movl %r8d,%ecx
+
+ andl %edi,%r15d
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %r15d,%ecx
+ addl %r12d,%r10d
+ addl %r12d,%ecx
+
+ leaq 4(%rbp),%rbp
+ movl 28(%rsp),%r13d
+ movl 16(%rsp),%r15d
+
+ movl %r13d,%r12d
+ rorl $11,%r13d
+ addl %r14d,%ecx
+ movl %r15d,%r14d
+ rorl $2,%r15d
+
+ xorl %r12d,%r13d
+ shrl $3,%r12d
+ rorl $7,%r13d
+ xorl %r14d,%r15d
+ shrl $10,%r14d
+
+ rorl $17,%r15d
+ xorl %r13d,%r12d
+ xorl %r14d,%r15d
+ addl 60(%rsp),%r12d
+
+ addl 24(%rsp),%r12d
+ movl %r10d,%r13d
+ addl %r15d,%r12d
+ movl %ecx,%r14d
+ rorl $14,%r13d
+ movl %r11d,%r15d
+
+ xorl %r10d,%r13d
+ rorl $9,%r14d
+ xorl %eax,%r15d
+
+ movl %r12d,24(%rsp)
+ xorl %ecx,%r14d
+ andl %r10d,%r15d
+
+ rorl $5,%r13d
+ addl %ebx,%r12d
+ xorl %eax,%r15d
+
+ rorl $11,%r14d
+ xorl %r10d,%r13d
+ addl %r15d,%r12d
+
+ movl %ecx,%r15d
+ addl (%rbp),%r12d
+ xorl %ecx,%r14d
+
+ xorl %edx,%r15d
+ rorl $6,%r13d
+ movl %edx,%ebx
+
+ andl %r15d,%edi
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %edi,%ebx
+ addl %r12d,%r9d
+ addl %r12d,%ebx
+
+ leaq 4(%rbp),%rbp
+ movl 32(%rsp),%r13d
+ movl 20(%rsp),%edi
+
+ movl %r13d,%r12d
+ rorl $11,%r13d
+ addl %r14d,%ebx
+ movl %edi,%r14d
+ rorl $2,%edi
+
+ xorl %r12d,%r13d
+ shrl $3,%r12d
+ rorl $7,%r13d
+ xorl %r14d,%edi
+ shrl $10,%r14d
+
+ rorl $17,%edi
+ xorl %r13d,%r12d
+ xorl %r14d,%edi
+ addl 0(%rsp),%r12d
+
+ addl 28(%rsp),%r12d
+ movl %r9d,%r13d
+ addl %edi,%r12d
+ movl %ebx,%r14d
+ rorl $14,%r13d
+ movl %r10d,%edi
+
+ xorl %r9d,%r13d
+ rorl $9,%r14d
+ xorl %r11d,%edi
+
+ movl %r12d,28(%rsp)
+ xorl %ebx,%r14d
+ andl %r9d,%edi
+
+ rorl $5,%r13d
+ addl %eax,%r12d
+ xorl %r11d,%edi
+
+ rorl $11,%r14d
+ xorl %r9d,%r13d
+ addl %edi,%r12d
+
+ movl %ebx,%edi
+ addl (%rbp),%r12d
+ xorl %ebx,%r14d
+
+ xorl %ecx,%edi
+ rorl $6,%r13d
+ movl %ecx,%eax
+
+ andl %edi,%r15d
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %r15d,%eax
+ addl %r12d,%r8d
+ addl %r12d,%eax
+
+ leaq 20(%rbp),%rbp
+ movl 36(%rsp),%r13d
+ movl 24(%rsp),%r15d
+
+ movl %r13d,%r12d
+ rorl $11,%r13d
+ addl %r14d,%eax
+ movl %r15d,%r14d
+ rorl $2,%r15d
+
+ xorl %r12d,%r13d
+ shrl $3,%r12d
+ rorl $7,%r13d
+ xorl %r14d,%r15d
+ shrl $10,%r14d
+
+ rorl $17,%r15d
+ xorl %r13d,%r12d
+ xorl %r14d,%r15d
+ addl 4(%rsp),%r12d
+
+ addl 32(%rsp),%r12d
+ movl %r8d,%r13d
+ addl %r15d,%r12d
+ movl %eax,%r14d
+ rorl $14,%r13d
+ movl %r9d,%r15d
+
+ xorl %r8d,%r13d
+ rorl $9,%r14d
+ xorl %r10d,%r15d
+
+ movl %r12d,32(%rsp)
+ xorl %eax,%r14d
+ andl %r8d,%r15d
+
+ rorl $5,%r13d
+ addl %r11d,%r12d
+ xorl %r10d,%r15d
+
+ rorl $11,%r14d
+ xorl %r8d,%r13d
+ addl %r15d,%r12d
+
+ movl %eax,%r15d
+ addl (%rbp),%r12d
+ xorl %eax,%r14d
+
+ xorl %ebx,%r15d
+ rorl $6,%r13d
+ movl %ebx,%r11d
+
+ andl %r15d,%edi
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %edi,%r11d
+ addl %r12d,%edx
+ addl %r12d,%r11d
+
+ leaq 4(%rbp),%rbp
+ movl 40(%rsp),%r13d
+ movl 28(%rsp),%edi
+
+ movl %r13d,%r12d
+ rorl $11,%r13d
+ addl %r14d,%r11d
+ movl %edi,%r14d
+ rorl $2,%edi
+
+ xorl %r12d,%r13d
+ shrl $3,%r12d
+ rorl $7,%r13d
+ xorl %r14d,%edi
+ shrl $10,%r14d
+
+ rorl $17,%edi
+ xorl %r13d,%r12d
+ xorl %r14d,%edi
+ addl 8(%rsp),%r12d
+
+ addl 36(%rsp),%r12d
+ movl %edx,%r13d
+ addl %edi,%r12d
+ movl %r11d,%r14d
+ rorl $14,%r13d
+ movl %r8d,%edi
+
+ xorl %edx,%r13d
+ rorl $9,%r14d
+ xorl %r9d,%edi
+
+ movl %r12d,36(%rsp)
+ xorl %r11d,%r14d
+ andl %edx,%edi
+
+ rorl $5,%r13d
+ addl %r10d,%r12d
+ xorl %r9d,%edi
+
+ rorl $11,%r14d
+ xorl %edx,%r13d
+ addl %edi,%r12d
+
+ movl %r11d,%edi
+ addl (%rbp),%r12d
+ xorl %r11d,%r14d
+
+ xorl %eax,%edi
+ rorl $6,%r13d
+ movl %eax,%r10d
+
+ andl %edi,%r15d
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %r15d,%r10d
+ addl %r12d,%ecx
+ addl %r12d,%r10d
+
+ leaq 4(%rbp),%rbp
+ movl 44(%rsp),%r13d
+ movl 32(%rsp),%r15d
+
+ movl %r13d,%r12d
+ rorl $11,%r13d
+ addl %r14d,%r10d
+ movl %r15d,%r14d
+ rorl $2,%r15d
+
+ xorl %r12d,%r13d
+ shrl $3,%r12d
+ rorl $7,%r13d
+ xorl %r14d,%r15d
+ shrl $10,%r14d
+
+ rorl $17,%r15d
+ xorl %r13d,%r12d
+ xorl %r14d,%r15d
+ addl 12(%rsp),%r12d
+
+ addl 40(%rsp),%r12d
+ movl %ecx,%r13d
+ addl %r15d,%r12d
+ movl %r10d,%r14d
+ rorl $14,%r13d
+ movl %edx,%r15d
+
+ xorl %ecx,%r13d
+ rorl $9,%r14d
+ xorl %r8d,%r15d
+
+ movl %r12d,40(%rsp)
+ xorl %r10d,%r14d
+ andl %ecx,%r15d
+
+ rorl $5,%r13d
+ addl %r9d,%r12d
+ xorl %r8d,%r15d
+
+ rorl $11,%r14d
+ xorl %ecx,%r13d
+ addl %r15d,%r12d
+
+ movl %r10d,%r15d
+ addl (%rbp),%r12d
+ xorl %r10d,%r14d
+
+ xorl %r11d,%r15d
+ rorl $6,%r13d
+ movl %r11d,%r9d
+
+ andl %r15d,%edi
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %edi,%r9d
+ addl %r12d,%ebx
+ addl %r12d,%r9d
+
+ leaq 4(%rbp),%rbp
+ movl 48(%rsp),%r13d
+ movl 36(%rsp),%edi
+
+ movl %r13d,%r12d
+ rorl $11,%r13d
+ addl %r14d,%r9d
+ movl %edi,%r14d
+ rorl $2,%edi
+
+ xorl %r12d,%r13d
+ shrl $3,%r12d
+ rorl $7,%r13d
+ xorl %r14d,%edi
+ shrl $10,%r14d
+
+ rorl $17,%edi
+ xorl %r13d,%r12d
+ xorl %r14d,%edi
+ addl 16(%rsp),%r12d
+
+ addl 44(%rsp),%r12d
+ movl %ebx,%r13d
+ addl %edi,%r12d
+ movl %r9d,%r14d
+ rorl $14,%r13d
+ movl %ecx,%edi
+
+ xorl %ebx,%r13d
+ rorl $9,%r14d
+ xorl %edx,%edi
+
+ movl %r12d,44(%rsp)
+ xorl %r9d,%r14d
+ andl %ebx,%edi
+
+ rorl $5,%r13d
+ addl %r8d,%r12d
+ xorl %edx,%edi
+
+ rorl $11,%r14d
+ xorl %ebx,%r13d
+ addl %edi,%r12d
+
+ movl %r9d,%edi
+ addl (%rbp),%r12d
+ xorl %r9d,%r14d
+
+ xorl %r10d,%edi
+ rorl $6,%r13d
+ movl %r10d,%r8d
+
+ andl %edi,%r15d
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %r15d,%r8d
+ addl %r12d,%eax
+ addl %r12d,%r8d
+
+ leaq 20(%rbp),%rbp
+ movl 52(%rsp),%r13d
+ movl 40(%rsp),%r15d
+
+ movl %r13d,%r12d
+ rorl $11,%r13d
+ addl %r14d,%r8d
+ movl %r15d,%r14d
+ rorl $2,%r15d
+
+ xorl %r12d,%r13d
+ shrl $3,%r12d
+ rorl $7,%r13d
+ xorl %r14d,%r15d
+ shrl $10,%r14d
+
+ rorl $17,%r15d
+ xorl %r13d,%r12d
+ xorl %r14d,%r15d
+ addl 20(%rsp),%r12d
+
+ addl 48(%rsp),%r12d
+ movl %eax,%r13d
+ addl %r15d,%r12d
+ movl %r8d,%r14d
+ rorl $14,%r13d
+ movl %ebx,%r15d
+
+ xorl %eax,%r13d
+ rorl $9,%r14d
+ xorl %ecx,%r15d
+
+ movl %r12d,48(%rsp)
+ xorl %r8d,%r14d
+ andl %eax,%r15d
+
+ rorl $5,%r13d
+ addl %edx,%r12d
+ xorl %ecx,%r15d
+
+ rorl $11,%r14d
+ xorl %eax,%r13d
+ addl %r15d,%r12d
+
+ movl %r8d,%r15d
+ addl (%rbp),%r12d
+ xorl %r8d,%r14d
+
+ xorl %r9d,%r15d
+ rorl $6,%r13d
+ movl %r9d,%edx
+
+ andl %r15d,%edi
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %edi,%edx
+ addl %r12d,%r11d
+ addl %r12d,%edx
+
+ leaq 4(%rbp),%rbp
+ movl 56(%rsp),%r13d
+ movl 44(%rsp),%edi
+
+ movl %r13d,%r12d
+ rorl $11,%r13d
+ addl %r14d,%edx
+ movl %edi,%r14d
+ rorl $2,%edi
+
+ xorl %r12d,%r13d
+ shrl $3,%r12d
+ rorl $7,%r13d
+ xorl %r14d,%edi
+ shrl $10,%r14d
+
+ rorl $17,%edi
+ xorl %r13d,%r12d
+ xorl %r14d,%edi
+ addl 24(%rsp),%r12d
+
+ addl 52(%rsp),%r12d
+ movl %r11d,%r13d
+ addl %edi,%r12d
+ movl %edx,%r14d
+ rorl $14,%r13d
+ movl %eax,%edi
+
+ xorl %r11d,%r13d
+ rorl $9,%r14d
+ xorl %ebx,%edi
+
+ movl %r12d,52(%rsp)
+ xorl %edx,%r14d
+ andl %r11d,%edi
+
+ rorl $5,%r13d
+ addl %ecx,%r12d
+ xorl %ebx,%edi
+
+ rorl $11,%r14d
+ xorl %r11d,%r13d
+ addl %edi,%r12d
+
+ movl %edx,%edi
+ addl (%rbp),%r12d
+ xorl %edx,%r14d
+
+ xorl %r8d,%edi
+ rorl $6,%r13d
+ movl %r8d,%ecx
+
+ andl %edi,%r15d
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %r15d,%ecx
+ addl %r12d,%r10d
+ addl %r12d,%ecx
+
+ leaq 4(%rbp),%rbp
+ movl 60(%rsp),%r13d
+ movl 48(%rsp),%r15d
+
+ movl %r13d,%r12d
+ rorl $11,%r13d
+ addl %r14d,%ecx
+ movl %r15d,%r14d
+ rorl $2,%r15d
+
+ xorl %r12d,%r13d
+ shrl $3,%r12d
+ rorl $7,%r13d
+ xorl %r14d,%r15d
+ shrl $10,%r14d
+
+ rorl $17,%r15d
+ xorl %r13d,%r12d
+ xorl %r14d,%r15d
+ addl 28(%rsp),%r12d
+
+ addl 56(%rsp),%r12d
+ movl %r10d,%r13d
+ addl %r15d,%r12d
+ movl %ecx,%r14d
+ rorl $14,%r13d
+ movl %r11d,%r15d
+
+ xorl %r10d,%r13d
+ rorl $9,%r14d
+ xorl %eax,%r15d
+
+ movl %r12d,56(%rsp)
+ xorl %ecx,%r14d
+ andl %r10d,%r15d
+
+ rorl $5,%r13d
+ addl %ebx,%r12d
+ xorl %eax,%r15d
+
+ rorl $11,%r14d
+ xorl %r10d,%r13d
+ addl %r15d,%r12d
+
+ movl %ecx,%r15d
+ addl (%rbp),%r12d
+ xorl %ecx,%r14d
+
+ xorl %edx,%r15d
+ rorl $6,%r13d
+ movl %edx,%ebx
+
+ andl %r15d,%edi
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %edi,%ebx
+ addl %r12d,%r9d
+ addl %r12d,%ebx
+
+ leaq 4(%rbp),%rbp
+ movl 0(%rsp),%r13d
+ movl 52(%rsp),%edi
+
+ movl %r13d,%r12d
+ rorl $11,%r13d
+ addl %r14d,%ebx
+ movl %edi,%r14d
+ rorl $2,%edi
+
+ xorl %r12d,%r13d
+ shrl $3,%r12d
+ rorl $7,%r13d
+ xorl %r14d,%edi
+ shrl $10,%r14d
+
+ rorl $17,%edi
+ xorl %r13d,%r12d
+ xorl %r14d,%edi
+ addl 32(%rsp),%r12d
+
+ addl 60(%rsp),%r12d
+ movl %r9d,%r13d
+ addl %edi,%r12d
+ movl %ebx,%r14d
+ rorl $14,%r13d
+ movl %r10d,%edi
+
+ xorl %r9d,%r13d
+ rorl $9,%r14d
+ xorl %r11d,%edi
+
+ movl %r12d,60(%rsp)
+ xorl %ebx,%r14d
+ andl %r9d,%edi
+
+ rorl $5,%r13d
+ addl %eax,%r12d
+ xorl %r11d,%edi
+
+ rorl $11,%r14d
+ xorl %r9d,%r13d
+ addl %edi,%r12d
+
+ movl %ebx,%edi
+ addl (%rbp),%r12d
+ xorl %ebx,%r14d
+
+ xorl %ecx,%edi
+ rorl $6,%r13d
+ movl %ecx,%eax
+
+ andl %edi,%r15d
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %r15d,%eax
+ addl %r12d,%r8d
+ addl %r12d,%eax
+
+ leaq 20(%rbp),%rbp
+ cmpb $0,3(%rbp)
+ jnz .Lrounds_16_xx
+
+ movq 64+0(%rsp),%rdi
+ addl %r14d,%eax
+ 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:
+ .byte 0xf3,0xc3
+.size sha256_block_data_order,.-sha256_block_data_order
+.align 64
+.type K256,@object
+K256:
+.long 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5
+.long 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5
+.long 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5
+.long 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5
+.long 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3
+.long 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3
+.long 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174
+.long 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174
+.long 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc
+.long 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc
+.long 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da
+.long 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da
+.long 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7
+.long 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7
+.long 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967
+.long 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967
+.long 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13
+.long 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13
+.long 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85
+.long 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85
+.long 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3
+.long 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3
+.long 0xd192e819,0xd6990624,0xf40e3585,0x106aa070
+.long 0xd192e819,0xd6990624,0xf40e3585,0x106aa070
+.long 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5
+.long 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5
+.long 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3
+.long 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3
+.long 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208
+.long 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208
+.long 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
+.long 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
+
+.long 0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f
+.long 0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f
+.long 0x03020100,0x0b0a0908,0xffffffff,0xffffffff
+.long 0x03020100,0x0b0a0908,0xffffffff,0xffffffff
+.long 0xffffffff,0xffffffff,0x03020100,0x0b0a0908
+.long 0xffffffff,0xffffffff,0x03020100,0x0b0a0908
+.byte 83,72,65,50,53,54,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
+.type sha256_block_data_order_ssse3,@function
+.align 64
+sha256_block_data_order_ssse3:
+.Lssse3_shortcut:
+ pushq %rbx
+ pushq %rbp
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ pushq %r15
+ movq %rsp,%r11
+ shlq $4,%rdx
+ subq $96,%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_ssse3:
+
+ 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_ssse3
+.align 16
+.Lloop_ssse3:
+ movdqa K256+512(%rip),%xmm7
+ movdqu 0(%rsi),%xmm0
+ movdqu 16(%rsi),%xmm1
+ movdqu 32(%rsi),%xmm2
+.byte 102,15,56,0,199
+ movdqu 48(%rsi),%xmm3
+ leaq K256(%rip),%rbp
+.byte 102,15,56,0,207
+ movdqa 0(%rbp),%xmm4
+ movdqa 32(%rbp),%xmm5
+.byte 102,15,56,0,215
+ paddd %xmm0,%xmm4
+ movdqa 64(%rbp),%xmm6
+.byte 102,15,56,0,223
+ movdqa 96(%rbp),%xmm7
+ paddd %xmm1,%xmm5
+ paddd %xmm2,%xmm6
+ paddd %xmm3,%xmm7
+ movdqa %xmm4,0(%rsp)
+ movl %eax,%r14d
+ movdqa %xmm5,16(%rsp)
+ movl %ebx,%edi
+ movdqa %xmm6,32(%rsp)
+ xorl %ecx,%edi
+ movdqa %xmm7,48(%rsp)
+ movl %r8d,%r13d
+ jmp .Lssse3_00_47
+
+.align 16
+.Lssse3_00_47:
+ subq $-128,%rbp
+ rorl $14,%r13d
+ movdqa %xmm1,%xmm4
+ movl %r14d,%eax
+ movl %r9d,%r12d
+ movdqa %xmm3,%xmm7
+ rorl $9,%r14d
+ xorl %r8d,%r13d
+ xorl %r10d,%r12d
+ rorl $5,%r13d
+ xorl %eax,%r14d
+.byte 102,15,58,15,224,4
+ andl %r8d,%r12d
+ xorl %r8d,%r13d
+.byte 102,15,58,15,250,4
+ addl 0(%rsp),%r11d
+ movl %eax,%r15d
+ xorl %r10d,%r12d
+ rorl $11,%r14d
+ movdqa %xmm4,%xmm5
+ xorl %ebx,%r15d
+ addl %r12d,%r11d
+ movdqa %xmm4,%xmm6
+ rorl $6,%r13d
+ andl %r15d,%edi
+ psrld $3,%xmm4
+ xorl %eax,%r14d
+ addl %r13d,%r11d
+ xorl %ebx,%edi
+ paddd %xmm7,%xmm0
+ rorl $2,%r14d
+ addl %r11d,%edx
+ psrld $7,%xmm6
+ addl %edi,%r11d
+ movl %edx,%r13d
+ pshufd $250,%xmm3,%xmm7
+ addl %r11d,%r14d
+ rorl $14,%r13d
+ pslld $14,%xmm5
+ movl %r14d,%r11d
+ movl %r8d,%r12d
+ pxor %xmm6,%xmm4
+ rorl $9,%r14d
+ xorl %edx,%r13d
+ xorl %r9d,%r12d
+ rorl $5,%r13d
+ psrld $11,%xmm6
+ xorl %r11d,%r14d
+ pxor %xmm5,%xmm4
+ andl %edx,%r12d
+ xorl %edx,%r13d
+ pslld $11,%xmm5
+ addl 4(%rsp),%r10d
+ movl %r11d,%edi
+ pxor %xmm6,%xmm4
+ xorl %r9d,%r12d
+ rorl $11,%r14d
+ movdqa %xmm7,%xmm6
+ xorl %eax,%edi
+ addl %r12d,%r10d
+ pxor %xmm5,%xmm4
+ rorl $6,%r13d
+ andl %edi,%r15d
+ xorl %r11d,%r14d
+ psrld $10,%xmm7
+ addl %r13d,%r10d
+ xorl %eax,%r15d
+ paddd %xmm4,%xmm0
+ rorl $2,%r14d
+ addl %r10d,%ecx
+ psrlq $17,%xmm6
+ addl %r15d,%r10d
+ movl %ecx,%r13d
+ addl %r10d,%r14d
+ pxor %xmm6,%xmm7
+ rorl $14,%r13d
+ movl %r14d,%r10d
+ movl %edx,%r12d
+ rorl $9,%r14d
+ psrlq $2,%xmm6
+ xorl %ecx,%r13d
+ xorl %r8d,%r12d
+ pxor %xmm6,%xmm7
+ rorl $5,%r13d
+ xorl %r10d,%r14d
+ andl %ecx,%r12d
+ pshufd $128,%xmm7,%xmm7
+ xorl %ecx,%r13d
+ addl 8(%rsp),%r9d
+ movl %r10d,%r15d
+ psrldq $8,%xmm7
+ xorl %r8d,%r12d
+ rorl $11,%r14d
+ xorl %r11d,%r15d
+ addl %r12d,%r9d
+ rorl $6,%r13d
+ paddd %xmm7,%xmm0
+ andl %r15d,%edi
+ xorl %r10d,%r14d
+ addl %r13d,%r9d
+ pshufd $80,%xmm0,%xmm7
+ xorl %r11d,%edi
+ rorl $2,%r14d
+ addl %r9d,%ebx
+ movdqa %xmm7,%xmm6
+ addl %edi,%r9d
+ movl %ebx,%r13d
+ psrld $10,%xmm7
+ addl %r9d,%r14d
+ rorl $14,%r13d
+ psrlq $17,%xmm6
+ movl %r14d,%r9d
+ movl %ecx,%r12d
+ pxor %xmm6,%xmm7
+ rorl $9,%r14d
+ xorl %ebx,%r13d
+ xorl %edx,%r12d
+ rorl $5,%r13d
+ xorl %r9d,%r14d
+ psrlq $2,%xmm6
+ andl %ebx,%r12d
+ xorl %ebx,%r13d
+ addl 12(%rsp),%r8d
+ pxor %xmm6,%xmm7
+ movl %r9d,%edi
+ xorl %edx,%r12d
+ rorl $11,%r14d
+ pshufd $8,%xmm7,%xmm7
+ xorl %r10d,%edi
+ addl %r12d,%r8d
+ movdqa 0(%rbp),%xmm6
+ rorl $6,%r13d
+ andl %edi,%r15d
+ pslldq $8,%xmm7
+ xorl %r9d,%r14d
+ addl %r13d,%r8d
+ xorl %r10d,%r15d
+ paddd %xmm7,%xmm0
+ rorl $2,%r14d
+ addl %r8d,%eax
+ addl %r15d,%r8d
+ paddd %xmm0,%xmm6
+ movl %eax,%r13d
+ addl %r8d,%r14d
+ movdqa %xmm6,0(%rsp)
+ rorl $14,%r13d
+ movdqa %xmm2,%xmm4
+ movl %r14d,%r8d
+ movl %ebx,%r12d
+ movdqa %xmm0,%xmm7
+ rorl $9,%r14d
+ xorl %eax,%r13d
+ xorl %ecx,%r12d
+ rorl $5,%r13d
+ xorl %r8d,%r14d
+.byte 102,15,58,15,225,4
+ andl %eax,%r12d
+ xorl %eax,%r13d
+.byte 102,15,58,15,251,4
+ addl 16(%rsp),%edx
+ movl %r8d,%r15d
+ xorl %ecx,%r12d
+ rorl $11,%r14d
+ movdqa %xmm4,%xmm5
+ xorl %r9d,%r15d
+ addl %r12d,%edx
+ movdqa %xmm4,%xmm6
+ rorl $6,%r13d
+ andl %r15d,%edi
+ psrld $3,%xmm4
+ xorl %r8d,%r14d
+ addl %r13d,%edx
+ xorl %r9d,%edi
+ paddd %xmm7,%xmm1
+ rorl $2,%r14d
+ addl %edx,%r11d
+ psrld $7,%xmm6
+ addl %edi,%edx
+ movl %r11d,%r13d
+ pshufd $250,%xmm0,%xmm7
+ addl %edx,%r14d
+ rorl $14,%r13d
+ pslld $14,%xmm5
+ movl %r14d,%edx
+ movl %eax,%r12d
+ pxor %xmm6,%xmm4
+ rorl $9,%r14d
+ xorl %r11d,%r13d
+ xorl %ebx,%r12d
+ rorl $5,%r13d
+ psrld $11,%xmm6
+ xorl %edx,%r14d
+ pxor %xmm5,%xmm4
+ andl %r11d,%r12d
+ xorl %r11d,%r13d
+ pslld $11,%xmm5
+ addl 20(%rsp),%ecx
+ movl %edx,%edi
+ pxor %xmm6,%xmm4
+ xorl %ebx,%r12d
+ rorl $11,%r14d
+ movdqa %xmm7,%xmm6
+ xorl %r8d,%edi
+ addl %r12d,%ecx
+ pxor %xmm5,%xmm4
+ rorl $6,%r13d
+ andl %edi,%r15d
+ xorl %edx,%r14d
+ psrld $10,%xmm7
+ addl %r13d,%ecx
+ xorl %r8d,%r15d
+ paddd %xmm4,%xmm1
+ rorl $2,%r14d
+ addl %ecx,%r10d
+ psrlq $17,%xmm6
+ addl %r15d,%ecx
+ movl %r10d,%r13d
+ addl %ecx,%r14d
+ pxor %xmm6,%xmm7
+ rorl $14,%r13d
+ movl %r14d,%ecx
+ movl %r11d,%r12d
+ rorl $9,%r14d
+ psrlq $2,%xmm6
+ xorl %r10d,%r13d
+ xorl %eax,%r12d
+ pxor %xmm6,%xmm7
+ rorl $5,%r13d
+ xorl %ecx,%r14d
+ andl %r10d,%r12d
+ pshufd $128,%xmm7,%xmm7
+ xorl %r10d,%r13d
+ addl 24(%rsp),%ebx
+ movl %ecx,%r15d
+ psrldq $8,%xmm7
+ xorl %eax,%r12d
+ rorl $11,%r14d
+ xorl %edx,%r15d
+ addl %r12d,%ebx
+ rorl $6,%r13d
+ paddd %xmm7,%xmm1
+ andl %r15d,%edi
+ xorl %ecx,%r14d
+ addl %r13d,%ebx
+ pshufd $80,%xmm1,%xmm7
+ xorl %edx,%edi
+ rorl $2,%r14d
+ addl %ebx,%r9d
+ movdqa %xmm7,%xmm6
+ addl %edi,%ebx
+ movl %r9d,%r13d
+ psrld $10,%xmm7
+ addl %ebx,%r14d
+ rorl $14,%r13d
+ psrlq $17,%xmm6
+ movl %r14d,%ebx
+ movl %r10d,%r12d
+ pxor %xmm6,%xmm7
+ rorl $9,%r14d
+ xorl %r9d,%r13d
+ xorl %r11d,%r12d
+ rorl $5,%r13d
+ xorl %ebx,%r14d
+ psrlq $2,%xmm6
+ andl %r9d,%r12d
+ xorl %r9d,%r13d
+ addl 28(%rsp),%eax
+ pxor %xmm6,%xmm7
+ movl %ebx,%edi
+ xorl %r11d,%r12d
+ rorl $11,%r14d
+ pshufd $8,%xmm7,%xmm7
+ xorl %ecx,%edi
+ addl %r12d,%eax
+ movdqa 32(%rbp),%xmm6
+ rorl $6,%r13d
+ andl %edi,%r15d
+ pslldq $8,%xmm7
+ xorl %ebx,%r14d
+ addl %r13d,%eax
+ xorl %ecx,%r15d
+ paddd %xmm7,%xmm1
+ rorl $2,%r14d
+ addl %eax,%r8d
+ addl %r15d,%eax
+ paddd %xmm1,%xmm6
+ movl %r8d,%r13d
+ addl %eax,%r14d
+ movdqa %xmm6,16(%rsp)
+ rorl $14,%r13d
+ movdqa %xmm3,%xmm4
+ movl %r14d,%eax
+ movl %r9d,%r12d
+ movdqa %xmm1,%xmm7
+ rorl $9,%r14d
+ xorl %r8d,%r13d
+ xorl %r10d,%r12d
+ rorl $5,%r13d
+ xorl %eax,%r14d
+.byte 102,15,58,15,226,4
+ andl %r8d,%r12d
+ xorl %r8d,%r13d
+.byte 102,15,58,15,248,4
+ addl 32(%rsp),%r11d
+ movl %eax,%r15d
+ xorl %r10d,%r12d
+ rorl $11,%r14d
+ movdqa %xmm4,%xmm5
+ xorl %ebx,%r15d
+ addl %r12d,%r11d
+ movdqa %xmm4,%xmm6
+ rorl $6,%r13d
+ andl %r15d,%edi
+ psrld $3,%xmm4
+ xorl %eax,%r14d
+ addl %r13d,%r11d
+ xorl %ebx,%edi
+ paddd %xmm7,%xmm2
+ rorl $2,%r14d
+ addl %r11d,%edx
+ psrld $7,%xmm6
+ addl %edi,%r11d
+ movl %edx,%r13d
+ pshufd $250,%xmm1,%xmm7
+ addl %r11d,%r14d
+ rorl $14,%r13d
+ pslld $14,%xmm5
+ movl %r14d,%r11d
+ movl %r8d,%r12d
+ pxor %xmm6,%xmm4
+ rorl $9,%r14d
+ xorl %edx,%r13d
+ xorl %r9d,%r12d
+ rorl $5,%r13d
+ psrld $11,%xmm6
+ xorl %r11d,%r14d
+ pxor %xmm5,%xmm4
+ andl %edx,%r12d
+ xorl %edx,%r13d
+ pslld $11,%xmm5
+ addl 36(%rsp),%r10d
+ movl %r11d,%edi
+ pxor %xmm6,%xmm4
+ xorl %r9d,%r12d
+ rorl $11,%r14d
+ movdqa %xmm7,%xmm6
+ xorl %eax,%edi
+ addl %r12d,%r10d
+ pxor %xmm5,%xmm4
+ rorl $6,%r13d
+ andl %edi,%r15d
+ xorl %r11d,%r14d
+ psrld $10,%xmm7
+ addl %r13d,%r10d
+ xorl %eax,%r15d
+ paddd %xmm4,%xmm2
+ rorl $2,%r14d
+ addl %r10d,%ecx
+ psrlq $17,%xmm6
+ addl %r15d,%r10d
+ movl %ecx,%r13d
+ addl %r10d,%r14d
+ pxor %xmm6,%xmm7
+ rorl $14,%r13d
+ movl %r14d,%r10d
+ movl %edx,%r12d
+ rorl $9,%r14d
+ psrlq $2,%xmm6
+ xorl %ecx,%r13d
+ xorl %r8d,%r12d
+ pxor %xmm6,%xmm7
+ rorl $5,%r13d
+ xorl %r10d,%r14d
+ andl %ecx,%r12d
+ pshufd $128,%xmm7,%xmm7
+ xorl %ecx,%r13d
+ addl 40(%rsp),%r9d
+ movl %r10d,%r15d
+ psrldq $8,%xmm7
+ xorl %r8d,%r12d
+ rorl $11,%r14d
+ xorl %r11d,%r15d
+ addl %r12d,%r9d
+ rorl $6,%r13d
+ paddd %xmm7,%xmm2
+ andl %r15d,%edi
+ xorl %r10d,%r14d
+ addl %r13d,%r9d
+ pshufd $80,%xmm2,%xmm7
+ xorl %r11d,%edi
+ rorl $2,%r14d
+ addl %r9d,%ebx
+ movdqa %xmm7,%xmm6
+ addl %edi,%r9d
+ movl %ebx,%r13d
+ psrld $10,%xmm7
+ addl %r9d,%r14d
+ rorl $14,%r13d
+ psrlq $17,%xmm6
+ movl %r14d,%r9d
+ movl %ecx,%r12d
+ pxor %xmm6,%xmm7
+ rorl $9,%r14d
+ xorl %ebx,%r13d
+ xorl %edx,%r12d
+ rorl $5,%r13d
+ xorl %r9d,%r14d
+ psrlq $2,%xmm6
+ andl %ebx,%r12d
+ xorl %ebx,%r13d
+ addl 44(%rsp),%r8d
+ pxor %xmm6,%xmm7
+ movl %r9d,%edi
+ xorl %edx,%r12d
+ rorl $11,%r14d
+ pshufd $8,%xmm7,%xmm7
+ xorl %r10d,%edi
+ addl %r12d,%r8d
+ movdqa 64(%rbp),%xmm6
+ rorl $6,%r13d
+ andl %edi,%r15d
+ pslldq $8,%xmm7
+ xorl %r9d,%r14d
+ addl %r13d,%r8d
+ xorl %r10d,%r15d
+ paddd %xmm7,%xmm2
+ rorl $2,%r14d
+ addl %r8d,%eax
+ addl %r15d,%r8d
+ paddd %xmm2,%xmm6
+ movl %eax,%r13d
+ addl %r8d,%r14d
+ movdqa %xmm6,32(%rsp)
+ rorl $14,%r13d
+ movdqa %xmm0,%xmm4
+ movl %r14d,%r8d
+ movl %ebx,%r12d
+ movdqa %xmm2,%xmm7
+ rorl $9,%r14d
+ xorl %eax,%r13d
+ xorl %ecx,%r12d
+ rorl $5,%r13d
+ xorl %r8d,%r14d
+.byte 102,15,58,15,227,4
+ andl %eax,%r12d
+ xorl %eax,%r13d
+.byte 102,15,58,15,249,4
+ addl 48(%rsp),%edx
+ movl %r8d,%r15d
+ xorl %ecx,%r12d
+ rorl $11,%r14d
+ movdqa %xmm4,%xmm5
+ xorl %r9d,%r15d
+ addl %r12d,%edx
+ movdqa %xmm4,%xmm6
+ rorl $6,%r13d
+ andl %r15d,%edi
+ psrld $3,%xmm4
+ xorl %r8d,%r14d
+ addl %r13d,%edx
+ xorl %r9d,%edi
+ paddd %xmm7,%xmm3
+ rorl $2,%r14d
+ addl %edx,%r11d
+ psrld $7,%xmm6
+ addl %edi,%edx
+ movl %r11d,%r13d
+ pshufd $250,%xmm2,%xmm7
+ addl %edx,%r14d
+ rorl $14,%r13d
+ pslld $14,%xmm5
+ movl %r14d,%edx
+ movl %eax,%r12d
+ pxor %xmm6,%xmm4
+ rorl $9,%r14d
+ xorl %r11d,%r13d
+ xorl %ebx,%r12d
+ rorl $5,%r13d
+ psrld $11,%xmm6
+ xorl %edx,%r14d
+ pxor %xmm5,%xmm4
+ andl %r11d,%r12d
+ xorl %r11d,%r13d
+ pslld $11,%xmm5
+ addl 52(%rsp),%ecx
+ movl %edx,%edi
+ pxor %xmm6,%xmm4
+ xorl %ebx,%r12d
+ rorl $11,%r14d
+ movdqa %xmm7,%xmm6
+ xorl %r8d,%edi
+ addl %r12d,%ecx
+ pxor %xmm5,%xmm4
+ rorl $6,%r13d
+ andl %edi,%r15d
+ xorl %edx,%r14d
+ psrld $10,%xmm7
+ addl %r13d,%ecx
+ xorl %r8d,%r15d
+ paddd %xmm4,%xmm3
+ rorl $2,%r14d
+ addl %ecx,%r10d
+ psrlq $17,%xmm6
+ addl %r15d,%ecx
+ movl %r10d,%r13d
+ addl %ecx,%r14d
+ pxor %xmm6,%xmm7
+ rorl $14,%r13d
+ movl %r14d,%ecx
+ movl %r11d,%r12d
+ rorl $9,%r14d
+ psrlq $2,%xmm6
+ xorl %r10d,%r13d
+ xorl %eax,%r12d
+ pxor %xmm6,%xmm7
+ rorl $5,%r13d
+ xorl %ecx,%r14d
+ andl %r10d,%r12d
+ pshufd $128,%xmm7,%xmm7
+ xorl %r10d,%r13d
+ addl 56(%rsp),%ebx
+ movl %ecx,%r15d
+ psrldq $8,%xmm7
+ xorl %eax,%r12d
+ rorl $11,%r14d
+ xorl %edx,%r15d
+ addl %r12d,%ebx
+ rorl $6,%r13d
+ paddd %xmm7,%xmm3
+ andl %r15d,%edi
+ xorl %ecx,%r14d
+ addl %r13d,%ebx
+ pshufd $80,%xmm3,%xmm7
+ xorl %edx,%edi
+ rorl $2,%r14d
+ addl %ebx,%r9d
+ movdqa %xmm7,%xmm6
+ addl %edi,%ebx
+ movl %r9d,%r13d
+ psrld $10,%xmm7
+ addl %ebx,%r14d
+ rorl $14,%r13d
+ psrlq $17,%xmm6
+ movl %r14d,%ebx
+ movl %r10d,%r12d
+ pxor %xmm6,%xmm7
+ rorl $9,%r14d
+ xorl %r9d,%r13d
+ xorl %r11d,%r12d
+ rorl $5,%r13d
+ xorl %ebx,%r14d
+ psrlq $2,%xmm6
+ andl %r9d,%r12d
+ xorl %r9d,%r13d
+ addl 60(%rsp),%eax
+ pxor %xmm6,%xmm7
+ movl %ebx,%edi
+ xorl %r11d,%r12d
+ rorl $11,%r14d
+ pshufd $8,%xmm7,%xmm7
+ xorl %ecx,%edi
+ addl %r12d,%eax
+ movdqa 96(%rbp),%xmm6
+ rorl $6,%r13d
+ andl %edi,%r15d
+ pslldq $8,%xmm7
+ xorl %ebx,%r14d
+ addl %r13d,%eax
+ xorl %ecx,%r15d
+ paddd %xmm7,%xmm3
+ rorl $2,%r14d
+ addl %eax,%r8d
+ addl %r15d,%eax
+ paddd %xmm3,%xmm6
+ movl %r8d,%r13d
+ addl %eax,%r14d
+ movdqa %xmm6,48(%rsp)
+ cmpb $0,131(%rbp)
+ jne .Lssse3_00_47
+ rorl $14,%r13d
+ movl %r14d,%eax
+ movl %r9d,%r12d
+ rorl $9,%r14d
+ xorl %r8d,%r13d
+ xorl %r10d,%r12d
+ rorl $5,%r13d
+ xorl %eax,%r14d
+ andl %r8d,%r12d
+ xorl %r8d,%r13d
+ addl 0(%rsp),%r11d
+ movl %eax,%r15d
+ xorl %r10d,%r12d
+ rorl $11,%r14d
+ xorl %ebx,%r15d
+ addl %r12d,%r11d
+ rorl $6,%r13d
+ andl %r15d,%edi
+ xorl %eax,%r14d
+ addl %r13d,%r11d
+ xorl %ebx,%edi
+ rorl $2,%r14d
+ addl %r11d,%edx
+ addl %edi,%r11d
+ movl %edx,%r13d
+ addl %r11d,%r14d
+ rorl $14,%r13d
+ movl %r14d,%r11d
+ movl %r8d,%r12d
+ rorl $9,%r14d
+ xorl %edx,%r13d
+ xorl %r9d,%r12d
+ rorl $5,%r13d
+ xorl %r11d,%r14d
+ andl %edx,%r12d
+ xorl %edx,%r13d
+ addl 4(%rsp),%r10d
+ movl %r11d,%edi
+ xorl %r9d,%r12d
+ rorl $11,%r14d
+ xorl %eax,%edi
+ addl %r12d,%r10d
+ rorl $6,%r13d
+ andl %edi,%r15d
+ xorl %r11d,%r14d
+ addl %r13d,%r10d
+ xorl %eax,%r15d
+ rorl $2,%r14d
+ addl %r10d,%ecx
+ addl %r15d,%r10d
+ movl %ecx,%r13d
+ addl %r10d,%r14d
+ rorl $14,%r13d
+ movl %r14d,%r10d
+ movl %edx,%r12d
+ rorl $9,%r14d
+ xorl %ecx,%r13d
+ xorl %r8d,%r12d
+ rorl $5,%r13d
+ xorl %r10d,%r14d
+ andl %ecx,%r12d
+ xorl %ecx,%r13d
+ addl 8(%rsp),%r9d
+ movl %r10d,%r15d
+ xorl %r8d,%r12d
+ rorl $11,%r14d
+ xorl %r11d,%r15d
+ addl %r12d,%r9d
+ rorl $6,%r13d
+ andl %r15d,%edi
+ xorl %r10d,%r14d
+ addl %r13d,%r9d
+ xorl %r11d,%edi
+ rorl $2,%r14d
+ addl %r9d,%ebx
+ addl %edi,%r9d
+ movl %ebx,%r13d
+ addl %r9d,%r14d
+ rorl $14,%r13d
+ movl %r14d,%r9d
+ movl %ecx,%r12d
+ rorl $9,%r14d
+ xorl %ebx,%r13d
+ xorl %edx,%r12d
+ rorl $5,%r13d
+ xorl %r9d,%r14d
+ andl %ebx,%r12d
+ xorl %ebx,%r13d
+ addl 12(%rsp),%r8d
+ movl %r9d,%edi
+ xorl %edx,%r12d
+ rorl $11,%r14d
+ xorl %r10d,%edi
+ addl %r12d,%r8d
+ rorl $6,%r13d
+ andl %edi,%r15d
+ xorl %r9d,%r14d
+ addl %r13d,%r8d
+ xorl %r10d,%r15d
+ rorl $2,%r14d
+ addl %r8d,%eax
+ addl %r15d,%r8d
+ movl %eax,%r13d
+ addl %r8d,%r14d
+ rorl $14,%r13d
+ movl %r14d,%r8d
+ movl %ebx,%r12d
+ rorl $9,%r14d
+ xorl %eax,%r13d
+ xorl %ecx,%r12d
+ rorl $5,%r13d
+ xorl %r8d,%r14d
+ andl %eax,%r12d
+ xorl %eax,%r13d
+ addl 16(%rsp),%edx
+ movl %r8d,%r15d
+ xorl %ecx,%r12d
+ rorl $11,%r14d
+ xorl %r9d,%r15d
+ addl %r12d,%edx
+ rorl $6,%r13d
+ andl %r15d,%edi
+ xorl %r8d,%r14d
+ addl %r13d,%edx
+ xorl %r9d,%edi
+ rorl $2,%r14d
+ addl %edx,%r11d
+ addl %edi,%edx
+ movl %r11d,%r13d
+ addl %edx,%r14d
+ rorl $14,%r13d
+ movl %r14d,%edx
+ movl %eax,%r12d
+ rorl $9,%r14d
+ xorl %r11d,%r13d
+ xorl %ebx,%r12d
+ rorl $5,%r13d
+ xorl %edx,%r14d
+ andl %r11d,%r12d
+ xorl %r11d,%r13d
+ addl 20(%rsp),%ecx
+ movl %edx,%edi
+ xorl %ebx,%r12d
+ rorl $11,%r14d
+ xorl %r8d,%edi
+ addl %r12d,%ecx
+ rorl $6,%r13d
+ andl %edi,%r15d
+ xorl %edx,%r14d
+ addl %r13d,%ecx
+ xorl %r8d,%r15d
+ rorl $2,%r14d
+ addl %ecx,%r10d
+ addl %r15d,%ecx
+ movl %r10d,%r13d
+ addl %ecx,%r14d
+ rorl $14,%r13d
+ movl %r14d,%ecx
+ movl %r11d,%r12d
+ rorl $9,%r14d
+ xorl %r10d,%r13d
+ xorl %eax,%r12d
+ rorl $5,%r13d
+ xorl %ecx,%r14d
+ andl %r10d,%r12d
+ xorl %r10d,%r13d
+ addl 24(%rsp),%ebx
+ movl %ecx,%r15d
+ xorl %eax,%r12d
+ rorl $11,%r14d
+ xorl %edx,%r15d
+ addl %r12d,%ebx
+ rorl $6,%r13d
+ andl %r15d,%edi
+ xorl %ecx,%r14d
+ addl %r13d,%ebx
+ xorl %edx,%edi
+ rorl $2,%r14d
+ addl %ebx,%r9d
+ addl %edi,%ebx
+ movl %r9d,%r13d
+ addl %ebx,%r14d
+ rorl $14,%r13d
+ movl %r14d,%ebx
+ movl %r10d,%r12d
+ rorl $9,%r14d
+ xorl %r9d,%r13d
+ xorl %r11d,%r12d
+ rorl $5,%r13d
+ xorl %ebx,%r14d
+ andl %r9d,%r12d
+ xorl %r9d,%r13d
+ addl 28(%rsp),%eax
+ movl %ebx,%edi
+ xorl %r11d,%r12d
+ rorl $11,%r14d
+ xorl %ecx,%edi
+ addl %r12d,%eax
+ rorl $6,%r13d
+ andl %edi,%r15d
+ xorl %ebx,%r14d
+ addl %r13d,%eax
+ xorl %ecx,%r15d
+ rorl $2,%r14d
+ addl %eax,%r8d
+ addl %r15d,%eax
+ movl %r8d,%r13d
+ addl %eax,%r14d
+ rorl $14,%r13d
+ movl %r14d,%eax
+ movl %r9d,%r12d
+ rorl $9,%r14d
+ xorl %r8d,%r13d
+ xorl %r10d,%r12d
+ rorl $5,%r13d
+ xorl %eax,%r14d
+ andl %r8d,%r12d
+ xorl %r8d,%r13d
+ addl 32(%rsp),%r11d
+ movl %eax,%r15d
+ xorl %r10d,%r12d
+ rorl $11,%r14d
+ xorl %ebx,%r15d
+ addl %r12d,%r11d
+ rorl $6,%r13d
+ andl %r15d,%edi
+ xorl %eax,%r14d
+ addl %r13d,%r11d
+ xorl %ebx,%edi
+ rorl $2,%r14d
+ addl %r11d,%edx
+ addl %edi,%r11d
+ movl %edx,%r13d
+ addl %r11d,%r14d
+ rorl $14,%r13d
+ movl %r14d,%r11d
+ movl %r8d,%r12d
+ rorl $9,%r14d
+ xorl %edx,%r13d
+ xorl %r9d,%r12d
+ rorl $5,%r13d
+ xorl %r11d,%r14d
+ andl %edx,%r12d
+ xorl %edx,%r13d
+ addl 36(%rsp),%r10d
+ movl %r11d,%edi
+ xorl %r9d,%r12d
+ rorl $11,%r14d
+ xorl %eax,%edi
+ addl %r12d,%r10d
+ rorl $6,%r13d
+ andl %edi,%r15d
+ xorl %r11d,%r14d
+ addl %r13d,%r10d
+ xorl %eax,%r15d
+ rorl $2,%r14d
+ addl %r10d,%ecx
+ addl %r15d,%r10d
+ movl %ecx,%r13d
+ addl %r10d,%r14d
+ rorl $14,%r13d
+ movl %r14d,%r10d
+ movl %edx,%r12d
+ rorl $9,%r14d
+ xorl %ecx,%r13d
+ xorl %r8d,%r12d
+ rorl $5,%r13d
+ xorl %r10d,%r14d
+ andl %ecx,%r12d
+ xorl %ecx,%r13d
+ addl 40(%rsp),%r9d
+ movl %r10d,%r15d
+ xorl %r8d,%r12d
+ rorl $11,%r14d
+ xorl %r11d,%r15d
+ addl %r12d,%r9d
+ rorl $6,%r13d
+ andl %r15d,%edi
+ xorl %r10d,%r14d
+ addl %r13d,%r9d
+ xorl %r11d,%edi
+ rorl $2,%r14d
+ addl %r9d,%ebx
+ addl %edi,%r9d
+ movl %ebx,%r13d
+ addl %r9d,%r14d
+ rorl $14,%r13d
+ movl %r14d,%r9d
+ movl %ecx,%r12d
+ rorl $9,%r14d
+ xorl %ebx,%r13d
+ xorl %edx,%r12d
+ rorl $5,%r13d
+ xorl %r9d,%r14d
+ andl %ebx,%r12d
+ xorl %ebx,%r13d
+ addl 44(%rsp),%r8d
+ movl %r9d,%edi
+ xorl %edx,%r12d
+ rorl $11,%r14d
+ xorl %r10d,%edi
+ addl %r12d,%r8d
+ rorl $6,%r13d
+ andl %edi,%r15d
+ xorl %r9d,%r14d
+ addl %r13d,%r8d
+ xorl %r10d,%r15d
+ rorl $2,%r14d
+ addl %r8d,%eax
+ addl %r15d,%r8d
+ movl %eax,%r13d
+ addl %r8d,%r14d
+ rorl $14,%r13d
+ movl %r14d,%r8d
+ movl %ebx,%r12d
+ rorl $9,%r14d
+ xorl %eax,%r13d
+ xorl %ecx,%r12d
+ rorl $5,%r13d
+ xorl %r8d,%r14d
+ andl %eax,%r12d
+ xorl %eax,%r13d
+ addl 48(%rsp),%edx
+ movl %r8d,%r15d
+ xorl %ecx,%r12d
+ rorl $11,%r14d
+ xorl %r9d,%r15d
+ addl %r12d,%edx
+ rorl $6,%r13d
+ andl %r15d,%edi
+ xorl %r8d,%r14d
+ addl %r13d,%edx
+ xorl %r9d,%edi
+ rorl $2,%r14d
+ addl %edx,%r11d
+ addl %edi,%edx
+ movl %r11d,%r13d
+ addl %edx,%r14d
+ rorl $14,%r13d
+ movl %r14d,%edx
+ movl %eax,%r12d
+ rorl $9,%r14d
+ xorl %r11d,%r13d
+ xorl %ebx,%r12d
+ rorl $5,%r13d
+ xorl %edx,%r14d
+ andl %r11d,%r12d
+ xorl %r11d,%r13d
+ addl 52(%rsp),%ecx
+ movl %edx,%edi
+ xorl %ebx,%r12d
+ rorl $11,%r14d
+ xorl %r8d,%edi
+ addl %r12d,%ecx
+ rorl $6,%r13d
+ andl %edi,%r15d
+ xorl %edx,%r14d
+ addl %r13d,%ecx
+ xorl %r8d,%r15d
+ rorl $2,%r14d
+ addl %ecx,%r10d
+ addl %r15d,%ecx
+ movl %r10d,%r13d
+ addl %ecx,%r14d
+ rorl $14,%r13d
+ movl %r14d,%ecx
+ movl %r11d,%r12d
+ rorl $9,%r14d
+ xorl %r10d,%r13d
+ xorl %eax,%r12d
+ rorl $5,%r13d
+ xorl %ecx,%r14d
+ andl %r10d,%r12d
+ xorl %r10d,%r13d
+ addl 56(%rsp),%ebx
+ movl %ecx,%r15d
+ xorl %eax,%r12d
+ rorl $11,%r14d
+ xorl %edx,%r15d
+ addl %r12d,%ebx
+ rorl $6,%r13d
+ andl %r15d,%edi
+ xorl %ecx,%r14d
+ addl %r13d,%ebx
+ xorl %edx,%edi
+ rorl $2,%r14d
+ addl %ebx,%r9d
+ addl %edi,%ebx
+ movl %r9d,%r13d
+ addl %ebx,%r14d
+ rorl $14,%r13d
+ movl %r14d,%ebx
+ movl %r10d,%r12d
+ rorl $9,%r14d
+ xorl %r9d,%r13d
+ xorl %r11d,%r12d
+ rorl $5,%r13d
+ xorl %ebx,%r14d
+ andl %r9d,%r12d
+ xorl %r9d,%r13d
+ addl 60(%rsp),%eax
+ movl %ebx,%edi
+ xorl %r11d,%r12d
+ rorl $11,%r14d
+ xorl %ecx,%edi
+ addl %r12d,%eax
+ rorl $6,%r13d
+ andl %edi,%r15d
+ xorl %ebx,%r14d
+ addl %r13d,%eax
+ xorl %ecx,%r15d
+ rorl $2,%r14d
+ addl %eax,%r8d
+ addl %r15d,%eax
+ movl %r8d,%r13d
+ addl %eax,%r14d
+ movq 64+0(%rsp),%rdi
+ movl %r14d,%eax
+
+ addl 0(%rdi),%eax
+ leaq 64(%rsi),%rsi
+ 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_ssse3
+
+ 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_ssse3:
+ .byte 0xf3,0xc3
+.size sha256_block_data_order_ssse3,.-sha256_block_data_order_ssse3
+#endif
diff --git a/linux-x86_64/crypto/sha/sha512-x86_64.S b/linux-x86_64/crypto/sha/sha512-x86_64.S
new file mode 100644
index 0000000..89fd5bf
--- /dev/null
+++ b/linux-x86_64/crypto/sha/sha512-x86_64.S
@@ -0,0 +1,1786 @@
+#if defined(__x86_64__)
+.text
+
+
+.globl sha512_block_data_order
+.hidden sha512_block_data_order
+.type sha512_block_data_order,@function
+.align 16
+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)
+.Lprologue:
+
+ 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:
+ movq %rbx,%rdi
+ leaq K512(%rip),%rbp
+ xorq %rcx,%rdi
+ movq 0(%rsi),%r12
+ movq %r8,%r13
+ movq %rax,%r14
+ bswapq %r12
+ rorq $23,%r13
+ movq %r9,%r15
+
+ xorq %r8,%r13
+ rorq $5,%r14
+ xorq %r10,%r15
+
+ movq %r12,0(%rsp)
+ xorq %rax,%r14
+ andq %r8,%r15
+
+ rorq $4,%r13
+ addq %r11,%r12
+ xorq %r10,%r15
+
+ rorq $6,%r14
+ xorq %r8,%r13
+ addq %r15,%r12
+
+ movq %rax,%r15
+ addq (%rbp),%r12
+ xorq %rax,%r14
+
+ xorq %rbx,%r15
+ rorq $14,%r13
+ movq %rbx,%r11
+
+ andq %r15,%rdi
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %rdi,%r11
+ addq %r12,%rdx
+ addq %r12,%r11
+
+ leaq 8(%rbp),%rbp
+ addq %r14,%r11
+ movq 8(%rsi),%r12
+ movq %rdx,%r13
+ movq %r11,%r14
+ bswapq %r12
+ rorq $23,%r13
+ movq %r8,%rdi
+
+ xorq %rdx,%r13
+ rorq $5,%r14
+ xorq %r9,%rdi
+
+ movq %r12,8(%rsp)
+ xorq %r11,%r14
+ andq %rdx,%rdi
+
+ rorq $4,%r13
+ addq %r10,%r12
+ xorq %r9,%rdi
+
+ rorq $6,%r14
+ xorq %rdx,%r13
+ addq %rdi,%r12
+
+ movq %r11,%rdi
+ addq (%rbp),%r12
+ xorq %r11,%r14
+
+ xorq %rax,%rdi
+ rorq $14,%r13
+ movq %rax,%r10
+
+ andq %rdi,%r15
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %r15,%r10
+ addq %r12,%rcx
+ addq %r12,%r10
+
+ leaq 24(%rbp),%rbp
+ addq %r14,%r10
+ movq 16(%rsi),%r12
+ movq %rcx,%r13
+ movq %r10,%r14
+ bswapq %r12
+ rorq $23,%r13
+ movq %rdx,%r15
+
+ xorq %rcx,%r13
+ rorq $5,%r14
+ xorq %r8,%r15
+
+ movq %r12,16(%rsp)
+ xorq %r10,%r14
+ andq %rcx,%r15
+
+ rorq $4,%r13
+ addq %r9,%r12
+ xorq %r8,%r15
+
+ rorq $6,%r14
+ xorq %rcx,%r13
+ addq %r15,%r12
+
+ movq %r10,%r15
+ addq (%rbp),%r12
+ xorq %r10,%r14
+
+ xorq %r11,%r15
+ rorq $14,%r13
+ movq %r11,%r9
+
+ andq %r15,%rdi
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %rdi,%r9
+ addq %r12,%rbx
+ addq %r12,%r9
+
+ leaq 8(%rbp),%rbp
+ addq %r14,%r9
+ movq 24(%rsi),%r12
+ movq %rbx,%r13
+ movq %r9,%r14
+ bswapq %r12
+ rorq $23,%r13
+ movq %rcx,%rdi
+
+ xorq %rbx,%r13
+ rorq $5,%r14
+ xorq %rdx,%rdi
+
+ movq %r12,24(%rsp)
+ xorq %r9,%r14
+ andq %rbx,%rdi
+
+ rorq $4,%r13
+ addq %r8,%r12
+ xorq %rdx,%rdi
+
+ rorq $6,%r14
+ xorq %rbx,%r13
+ addq %rdi,%r12
+
+ movq %r9,%rdi
+ addq (%rbp),%r12
+ xorq %r9,%r14
+
+ xorq %r10,%rdi
+ rorq $14,%r13
+ movq %r10,%r8
+
+ andq %rdi,%r15
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %r15,%r8
+ addq %r12,%rax
+ addq %r12,%r8
+
+ leaq 24(%rbp),%rbp
+ addq %r14,%r8
+ movq 32(%rsi),%r12
+ movq %rax,%r13
+ movq %r8,%r14
+ bswapq %r12
+ rorq $23,%r13
+ movq %rbx,%r15
+
+ xorq %rax,%r13
+ rorq $5,%r14
+ xorq %rcx,%r15
+
+ movq %r12,32(%rsp)
+ xorq %r8,%r14
+ andq %rax,%r15
+
+ rorq $4,%r13
+ addq %rdx,%r12
+ xorq %rcx,%r15
+
+ rorq $6,%r14
+ xorq %rax,%r13
+ addq %r15,%r12
+
+ movq %r8,%r15
+ addq (%rbp),%r12
+ xorq %r8,%r14
+
+ xorq %r9,%r15
+ rorq $14,%r13
+ movq %r9,%rdx
+
+ andq %r15,%rdi
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %rdi,%rdx
+ addq %r12,%r11
+ addq %r12,%rdx
+
+ leaq 8(%rbp),%rbp
+ addq %r14,%rdx
+ movq 40(%rsi),%r12
+ movq %r11,%r13
+ movq %rdx,%r14
+ bswapq %r12
+ rorq $23,%r13
+ movq %rax,%rdi
+
+ xorq %r11,%r13
+ rorq $5,%r14
+ xorq %rbx,%rdi
+
+ movq %r12,40(%rsp)
+ xorq %rdx,%r14
+ andq %r11,%rdi
+
+ rorq $4,%r13
+ addq %rcx,%r12
+ xorq %rbx,%rdi
+
+ rorq $6,%r14
+ xorq %r11,%r13
+ addq %rdi,%r12
+
+ movq %rdx,%rdi
+ addq (%rbp),%r12
+ xorq %rdx,%r14
+
+ xorq %r8,%rdi
+ rorq $14,%r13
+ movq %r8,%rcx
+
+ andq %rdi,%r15
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %r15,%rcx
+ addq %r12,%r10
+ addq %r12,%rcx
+
+ leaq 24(%rbp),%rbp
+ addq %r14,%rcx
+ movq 48(%rsi),%r12
+ movq %r10,%r13
+ movq %rcx,%r14
+ bswapq %r12
+ rorq $23,%r13
+ movq %r11,%r15
+
+ xorq %r10,%r13
+ rorq $5,%r14
+ xorq %rax,%r15
+
+ movq %r12,48(%rsp)
+ xorq %rcx,%r14
+ andq %r10,%r15
+
+ rorq $4,%r13
+ addq %rbx,%r12
+ xorq %rax,%r15
+
+ rorq $6,%r14
+ xorq %r10,%r13
+ addq %r15,%r12
+
+ movq %rcx,%r15
+ addq (%rbp),%r12
+ xorq %rcx,%r14
+
+ xorq %rdx,%r15
+ rorq $14,%r13
+ movq %rdx,%rbx
+
+ andq %r15,%rdi
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %rdi,%rbx
+ addq %r12,%r9
+ addq %r12,%rbx
+
+ leaq 8(%rbp),%rbp
+ addq %r14,%rbx
+ movq 56(%rsi),%r12
+ movq %r9,%r13
+ movq %rbx,%r14
+ bswapq %r12
+ rorq $23,%r13
+ movq %r10,%rdi
+
+ xorq %r9,%r13
+ rorq $5,%r14
+ xorq %r11,%rdi
+
+ movq %r12,56(%rsp)
+ xorq %rbx,%r14
+ andq %r9,%rdi
+
+ rorq $4,%r13
+ addq %rax,%r12
+ xorq %r11,%rdi
+
+ rorq $6,%r14
+ xorq %r9,%r13
+ addq %rdi,%r12
+
+ movq %rbx,%rdi
+ addq (%rbp),%r12
+ xorq %rbx,%r14
+
+ xorq %rcx,%rdi
+ rorq $14,%r13
+ movq %rcx,%rax
+
+ andq %rdi,%r15
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %r15,%rax
+ addq %r12,%r8
+ addq %r12,%rax
+
+ leaq 24(%rbp),%rbp
+ addq %r14,%rax
+ movq 64(%rsi),%r12
+ movq %r8,%r13
+ movq %rax,%r14
+ bswapq %r12
+ rorq $23,%r13
+ movq %r9,%r15
+
+ xorq %r8,%r13
+ rorq $5,%r14
+ xorq %r10,%r15
+
+ movq %r12,64(%rsp)
+ xorq %rax,%r14
+ andq %r8,%r15
+
+ rorq $4,%r13
+ addq %r11,%r12
+ xorq %r10,%r15
+
+ rorq $6,%r14
+ xorq %r8,%r13
+ addq %r15,%r12
+
+ movq %rax,%r15
+ addq (%rbp),%r12
+ xorq %rax,%r14
+
+ xorq %rbx,%r15
+ rorq $14,%r13
+ movq %rbx,%r11
+
+ andq %r15,%rdi
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %rdi,%r11
+ addq %r12,%rdx
+ addq %r12,%r11
+
+ leaq 8(%rbp),%rbp
+ addq %r14,%r11
+ movq 72(%rsi),%r12
+ movq %rdx,%r13
+ movq %r11,%r14
+ bswapq %r12
+ rorq $23,%r13
+ movq %r8,%rdi
+
+ xorq %rdx,%r13
+ rorq $5,%r14
+ xorq %r9,%rdi
+
+ movq %r12,72(%rsp)
+ xorq %r11,%r14
+ andq %rdx,%rdi
+
+ rorq $4,%r13
+ addq %r10,%r12
+ xorq %r9,%rdi
+
+ rorq $6,%r14
+ xorq %rdx,%r13
+ addq %rdi,%r12
+
+ movq %r11,%rdi
+ addq (%rbp),%r12
+ xorq %r11,%r14
+
+ xorq %rax,%rdi
+ rorq $14,%r13
+ movq %rax,%r10
+
+ andq %rdi,%r15
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %r15,%r10
+ addq %r12,%rcx
+ addq %r12,%r10
+
+ leaq 24(%rbp),%rbp
+ addq %r14,%r10
+ movq 80(%rsi),%r12
+ movq %rcx,%r13
+ movq %r10,%r14
+ bswapq %r12
+ rorq $23,%r13
+ movq %rdx,%r15
+
+ xorq %rcx,%r13
+ rorq $5,%r14
+ xorq %r8,%r15
+
+ movq %r12,80(%rsp)
+ xorq %r10,%r14
+ andq %rcx,%r15
+
+ rorq $4,%r13
+ addq %r9,%r12
+ xorq %r8,%r15
+
+ rorq $6,%r14
+ xorq %rcx,%r13
+ addq %r15,%r12
+
+ movq %r10,%r15
+ addq (%rbp),%r12
+ xorq %r10,%r14
+
+ xorq %r11,%r15
+ rorq $14,%r13
+ movq %r11,%r9
+
+ andq %r15,%rdi
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %rdi,%r9
+ addq %r12,%rbx
+ addq %r12,%r9
+
+ leaq 8(%rbp),%rbp
+ addq %r14,%r9
+ movq 88(%rsi),%r12
+ movq %rbx,%r13
+ movq %r9,%r14
+ bswapq %r12
+ rorq $23,%r13
+ movq %rcx,%rdi
+
+ xorq %rbx,%r13
+ rorq $5,%r14
+ xorq %rdx,%rdi
+
+ movq %r12,88(%rsp)
+ xorq %r9,%r14
+ andq %rbx,%rdi
+
+ rorq $4,%r13
+ addq %r8,%r12
+ xorq %rdx,%rdi
+
+ rorq $6,%r14
+ xorq %rbx,%r13
+ addq %rdi,%r12
+
+ movq %r9,%rdi
+ addq (%rbp),%r12
+ xorq %r9,%r14
+
+ xorq %r10,%rdi
+ rorq $14,%r13
+ movq %r10,%r8
+
+ andq %rdi,%r15
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %r15,%r8
+ addq %r12,%rax
+ addq %r12,%r8
+
+ leaq 24(%rbp),%rbp
+ addq %r14,%r8
+ movq 96(%rsi),%r12
+ movq %rax,%r13
+ movq %r8,%r14
+ bswapq %r12
+ rorq $23,%r13
+ movq %rbx,%r15
+
+ xorq %rax,%r13
+ rorq $5,%r14
+ xorq %rcx,%r15
+
+ movq %r12,96(%rsp)
+ xorq %r8,%r14
+ andq %rax,%r15
+
+ rorq $4,%r13
+ addq %rdx,%r12
+ xorq %rcx,%r15
+
+ rorq $6,%r14
+ xorq %rax,%r13
+ addq %r15,%r12
+
+ movq %r8,%r15
+ addq (%rbp),%r12
+ xorq %r8,%r14
+
+ xorq %r9,%r15
+ rorq $14,%r13
+ movq %r9,%rdx
+
+ andq %r15,%rdi
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %rdi,%rdx
+ addq %r12,%r11
+ addq %r12,%rdx
+
+ leaq 8(%rbp),%rbp
+ addq %r14,%rdx
+ movq 104(%rsi),%r12
+ movq %r11,%r13
+ movq %rdx,%r14
+ bswapq %r12
+ rorq $23,%r13
+ movq %rax,%rdi
+
+ xorq %r11,%r13
+ rorq $5,%r14
+ xorq %rbx,%rdi
+
+ movq %r12,104(%rsp)
+ xorq %rdx,%r14
+ andq %r11,%rdi
+
+ rorq $4,%r13
+ addq %rcx,%r12
+ xorq %rbx,%rdi
+
+ rorq $6,%r14
+ xorq %r11,%r13
+ addq %rdi,%r12
+
+ movq %rdx,%rdi
+ addq (%rbp),%r12
+ xorq %rdx,%r14
+
+ xorq %r8,%rdi
+ rorq $14,%r13
+ movq %r8,%rcx
+
+ andq %rdi,%r15
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %r15,%rcx
+ addq %r12,%r10
+ addq %r12,%rcx
+
+ leaq 24(%rbp),%rbp
+ addq %r14,%rcx
+ movq 112(%rsi),%r12
+ movq %r10,%r13
+ movq %rcx,%r14
+ bswapq %r12
+ rorq $23,%r13
+ movq %r11,%r15
+
+ xorq %r10,%r13
+ rorq $5,%r14
+ xorq %rax,%r15
+
+ movq %r12,112(%rsp)
+ xorq %rcx,%r14
+ andq %r10,%r15
+
+ rorq $4,%r13
+ addq %rbx,%r12
+ xorq %rax,%r15
+
+ rorq $6,%r14
+ xorq %r10,%r13
+ addq %r15,%r12
+
+ movq %rcx,%r15
+ addq (%rbp),%r12
+ xorq %rcx,%r14
+
+ xorq %rdx,%r15
+ rorq $14,%r13
+ movq %rdx,%rbx
+
+ andq %r15,%rdi
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %rdi,%rbx
+ addq %r12,%r9
+ addq %r12,%rbx
+
+ leaq 8(%rbp),%rbp
+ addq %r14,%rbx
+ movq 120(%rsi),%r12
+ movq %r9,%r13
+ movq %rbx,%r14
+ bswapq %r12
+ rorq $23,%r13
+ movq %r10,%rdi
+
+ xorq %r9,%r13
+ rorq $5,%r14
+ xorq %r11,%rdi
+
+ movq %r12,120(%rsp)
+ xorq %rbx,%r14
+ andq %r9,%rdi
+
+ rorq $4,%r13
+ addq %rax,%r12
+ xorq %r11,%rdi
+
+ rorq $6,%r14
+ xorq %r9,%r13
+ addq %rdi,%r12
+
+ movq %rbx,%rdi
+ addq (%rbp),%r12
+ xorq %rbx,%r14
+
+ xorq %rcx,%rdi
+ rorq $14,%r13
+ movq %rcx,%rax
+
+ andq %rdi,%r15
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %r15,%rax
+ addq %r12,%r8
+ addq %r12,%rax
+
+ leaq 24(%rbp),%rbp
+ jmp .Lrounds_16_xx
+.align 16
+.Lrounds_16_xx:
+ movq 8(%rsp),%r13
+ movq 112(%rsp),%r15
+
+ movq %r13,%r12
+ rorq $7,%r13
+ addq %r14,%rax
+ movq %r15,%r14
+ rorq $42,%r15
+
+ xorq %r12,%r13
+ shrq $7,%r12
+ rorq $1,%r13
+ xorq %r14,%r15
+ shrq $6,%r14
+
+ rorq $19,%r15
+ xorq %r13,%r12
+ xorq %r14,%r15
+ addq 72(%rsp),%r12
+
+ addq 0(%rsp),%r12
+ movq %r8,%r13
+ addq %r15,%r12
+ movq %rax,%r14
+ rorq $23,%r13
+ movq %r9,%r15
+
+ xorq %r8,%r13
+ rorq $5,%r14
+ xorq %r10,%r15
+
+ movq %r12,0(%rsp)
+ xorq %rax,%r14
+ andq %r8,%r15
+
+ rorq $4,%r13
+ addq %r11,%r12
+ xorq %r10,%r15
+
+ rorq $6,%r14
+ xorq %r8,%r13
+ addq %r15,%r12
+
+ movq %rax,%r15
+ addq (%rbp),%r12
+ xorq %rax,%r14
+
+ xorq %rbx,%r15
+ rorq $14,%r13
+ movq %rbx,%r11
+
+ andq %r15,%rdi
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %rdi,%r11
+ addq %r12,%rdx
+ addq %r12,%r11
+
+ leaq 8(%rbp),%rbp
+ movq 16(%rsp),%r13
+ movq 120(%rsp),%rdi
+
+ movq %r13,%r12
+ rorq $7,%r13
+ addq %r14,%r11
+ movq %rdi,%r14
+ rorq $42,%rdi
+
+ xorq %r12,%r13
+ shrq $7,%r12
+ rorq $1,%r13
+ xorq %r14,%rdi
+ shrq $6,%r14
+
+ rorq $19,%rdi
+ xorq %r13,%r12
+ xorq %r14,%rdi
+ addq 80(%rsp),%r12
+
+ addq 8(%rsp),%r12
+ movq %rdx,%r13
+ addq %rdi,%r12
+ movq %r11,%r14
+ rorq $23,%r13
+ movq %r8,%rdi
+
+ xorq %rdx,%r13
+ rorq $5,%r14
+ xorq %r9,%rdi
+
+ movq %r12,8(%rsp)
+ xorq %r11,%r14
+ andq %rdx,%rdi
+
+ rorq $4,%r13
+ addq %r10,%r12
+ xorq %r9,%rdi
+
+ rorq $6,%r14
+ xorq %rdx,%r13
+ addq %rdi,%r12
+
+ movq %r11,%rdi
+ addq (%rbp),%r12
+ xorq %r11,%r14
+
+ xorq %rax,%rdi
+ rorq $14,%r13
+ movq %rax,%r10
+
+ andq %rdi,%r15
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %r15,%r10
+ addq %r12,%rcx
+ addq %r12,%r10
+
+ leaq 24(%rbp),%rbp
+ movq 24(%rsp),%r13
+ movq 0(%rsp),%r15
+
+ movq %r13,%r12
+ rorq $7,%r13
+ addq %r14,%r10
+ movq %r15,%r14
+ rorq $42,%r15
+
+ xorq %r12,%r13
+ shrq $7,%r12
+ rorq $1,%r13
+ xorq %r14,%r15
+ shrq $6,%r14
+
+ rorq $19,%r15
+ xorq %r13,%r12
+ xorq %r14,%r15
+ addq 88(%rsp),%r12
+
+ addq 16(%rsp),%r12
+ movq %rcx,%r13
+ addq %r15,%r12
+ movq %r10,%r14
+ rorq $23,%r13
+ movq %rdx,%r15
+
+ xorq %rcx,%r13
+ rorq $5,%r14
+ xorq %r8,%r15
+
+ movq %r12,16(%rsp)
+ xorq %r10,%r14
+ andq %rcx,%r15
+
+ rorq $4,%r13
+ addq %r9,%r12
+ xorq %r8,%r15
+
+ rorq $6,%r14
+ xorq %rcx,%r13
+ addq %r15,%r12
+
+ movq %r10,%r15
+ addq (%rbp),%r12
+ xorq %r10,%r14
+
+ xorq %r11,%r15
+ rorq $14,%r13
+ movq %r11,%r9
+
+ andq %r15,%rdi
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %rdi,%r9
+ addq %r12,%rbx
+ addq %r12,%r9
+
+ leaq 8(%rbp),%rbp
+ movq 32(%rsp),%r13
+ movq 8(%rsp),%rdi
+
+ movq %r13,%r12
+ rorq $7,%r13
+ addq %r14,%r9
+ movq %rdi,%r14
+ rorq $42,%rdi
+
+ xorq %r12,%r13
+ shrq $7,%r12
+ rorq $1,%r13
+ xorq %r14,%rdi
+ shrq $6,%r14
+
+ rorq $19,%rdi
+ xorq %r13,%r12
+ xorq %r14,%rdi
+ addq 96(%rsp),%r12
+
+ addq 24(%rsp),%r12
+ movq %rbx,%r13
+ addq %rdi,%r12
+ movq %r9,%r14
+ rorq $23,%r13
+ movq %rcx,%rdi
+
+ xorq %rbx,%r13
+ rorq $5,%r14
+ xorq %rdx,%rdi
+
+ movq %r12,24(%rsp)
+ xorq %r9,%r14
+ andq %rbx,%rdi
+
+ rorq $4,%r13
+ addq %r8,%r12
+ xorq %rdx,%rdi
+
+ rorq $6,%r14
+ xorq %rbx,%r13
+ addq %rdi,%r12
+
+ movq %r9,%rdi
+ addq (%rbp),%r12
+ xorq %r9,%r14
+
+ xorq %r10,%rdi
+ rorq $14,%r13
+ movq %r10,%r8
+
+ andq %rdi,%r15
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %r15,%r8
+ addq %r12,%rax
+ addq %r12,%r8
+
+ leaq 24(%rbp),%rbp
+ movq 40(%rsp),%r13
+ movq 16(%rsp),%r15
+
+ movq %r13,%r12
+ rorq $7,%r13
+ addq %r14,%r8
+ movq %r15,%r14
+ rorq $42,%r15
+
+ xorq %r12,%r13
+ shrq $7,%r12
+ rorq $1,%r13
+ xorq %r14,%r15
+ shrq $6,%r14
+
+ rorq $19,%r15
+ xorq %r13,%r12
+ xorq %r14,%r15
+ addq 104(%rsp),%r12
+
+ addq 32(%rsp),%r12
+ movq %rax,%r13
+ addq %r15,%r12
+ movq %r8,%r14
+ rorq $23,%r13
+ movq %rbx,%r15
+
+ xorq %rax,%r13
+ rorq $5,%r14
+ xorq %rcx,%r15
+
+ movq %r12,32(%rsp)
+ xorq %r8,%r14
+ andq %rax,%r15
+
+ rorq $4,%r13
+ addq %rdx,%r12
+ xorq %rcx,%r15
+
+ rorq $6,%r14
+ xorq %rax,%r13
+ addq %r15,%r12
+
+ movq %r8,%r15
+ addq (%rbp),%r12
+ xorq %r8,%r14
+
+ xorq %r9,%r15
+ rorq $14,%r13
+ movq %r9,%rdx
+
+ andq %r15,%rdi
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %rdi,%rdx
+ addq %r12,%r11
+ addq %r12,%rdx
+
+ leaq 8(%rbp),%rbp
+ movq 48(%rsp),%r13
+ movq 24(%rsp),%rdi
+
+ movq %r13,%r12
+ rorq $7,%r13
+ addq %r14,%rdx
+ movq %rdi,%r14
+ rorq $42,%rdi
+
+ xorq %r12,%r13
+ shrq $7,%r12
+ rorq $1,%r13
+ xorq %r14,%rdi
+ shrq $6,%r14
+
+ rorq $19,%rdi
+ xorq %r13,%r12
+ xorq %r14,%rdi
+ addq 112(%rsp),%r12
+
+ addq 40(%rsp),%r12
+ movq %r11,%r13
+ addq %rdi,%r12
+ movq %rdx,%r14
+ rorq $23,%r13
+ movq %rax,%rdi
+
+ xorq %r11,%r13
+ rorq $5,%r14
+ xorq %rbx,%rdi
+
+ movq %r12,40(%rsp)
+ xorq %rdx,%r14
+ andq %r11,%rdi
+
+ rorq $4,%r13
+ addq %rcx,%r12
+ xorq %rbx,%rdi
+
+ rorq $6,%r14
+ xorq %r11,%r13
+ addq %rdi,%r12
+
+ movq %rdx,%rdi
+ addq (%rbp),%r12
+ xorq %rdx,%r14
+
+ xorq %r8,%rdi
+ rorq $14,%r13
+ movq %r8,%rcx
+
+ andq %rdi,%r15
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %r15,%rcx
+ addq %r12,%r10
+ addq %r12,%rcx
+
+ leaq 24(%rbp),%rbp
+ movq 56(%rsp),%r13
+ movq 32(%rsp),%r15
+
+ movq %r13,%r12
+ rorq $7,%r13
+ addq %r14,%rcx
+ movq %r15,%r14
+ rorq $42,%r15
+
+ xorq %r12,%r13
+ shrq $7,%r12
+ rorq $1,%r13
+ xorq %r14,%r15
+ shrq $6,%r14
+
+ rorq $19,%r15
+ xorq %r13,%r12
+ xorq %r14,%r15
+ addq 120(%rsp),%r12
+
+ addq 48(%rsp),%r12
+ movq %r10,%r13
+ addq %r15,%r12
+ movq %rcx,%r14
+ rorq $23,%r13
+ movq %r11,%r15
+
+ xorq %r10,%r13
+ rorq $5,%r14
+ xorq %rax,%r15
+
+ movq %r12,48(%rsp)
+ xorq %rcx,%r14
+ andq %r10,%r15
+
+ rorq $4,%r13
+ addq %rbx,%r12
+ xorq %rax,%r15
+
+ rorq $6,%r14
+ xorq %r10,%r13
+ addq %r15,%r12
+
+ movq %rcx,%r15
+ addq (%rbp),%r12
+ xorq %rcx,%r14
+
+ xorq %rdx,%r15
+ rorq $14,%r13
+ movq %rdx,%rbx
+
+ andq %r15,%rdi
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %rdi,%rbx
+ addq %r12,%r9
+ addq %r12,%rbx
+
+ leaq 8(%rbp),%rbp
+ movq 64(%rsp),%r13
+ movq 40(%rsp),%rdi
+
+ movq %r13,%r12
+ rorq $7,%r13
+ addq %r14,%rbx
+ movq %rdi,%r14
+ rorq $42,%rdi
+
+ xorq %r12,%r13
+ shrq $7,%r12
+ rorq $1,%r13
+ xorq %r14,%rdi
+ shrq $6,%r14
+
+ rorq $19,%rdi
+ xorq %r13,%r12
+ xorq %r14,%rdi
+ addq 0(%rsp),%r12
+
+ addq 56(%rsp),%r12
+ movq %r9,%r13
+ addq %rdi,%r12
+ movq %rbx,%r14
+ rorq $23,%r13
+ movq %r10,%rdi
+
+ xorq %r9,%r13
+ rorq $5,%r14
+ xorq %r11,%rdi
+
+ movq %r12,56(%rsp)
+ xorq %rbx,%r14
+ andq %r9,%rdi
+
+ rorq $4,%r13
+ addq %rax,%r12
+ xorq %r11,%rdi
+
+ rorq $6,%r14
+ xorq %r9,%r13
+ addq %rdi,%r12
+
+ movq %rbx,%rdi
+ addq (%rbp),%r12
+ xorq %rbx,%r14
+
+ xorq %rcx,%rdi
+ rorq $14,%r13
+ movq %rcx,%rax
+
+ andq %rdi,%r15
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %r15,%rax
+ addq %r12,%r8
+ addq %r12,%rax
+
+ leaq 24(%rbp),%rbp
+ movq 72(%rsp),%r13
+ movq 48(%rsp),%r15
+
+ movq %r13,%r12
+ rorq $7,%r13
+ addq %r14,%rax
+ movq %r15,%r14
+ rorq $42,%r15
+
+ xorq %r12,%r13
+ shrq $7,%r12
+ rorq $1,%r13
+ xorq %r14,%r15
+ shrq $6,%r14
+
+ rorq $19,%r15
+ xorq %r13,%r12
+ xorq %r14,%r15
+ addq 8(%rsp),%r12
+
+ addq 64(%rsp),%r12
+ movq %r8,%r13
+ addq %r15,%r12
+ movq %rax,%r14
+ rorq $23,%r13
+ movq %r9,%r15
+
+ xorq %r8,%r13
+ rorq $5,%r14
+ xorq %r10,%r15
+
+ movq %r12,64(%rsp)
+ xorq %rax,%r14
+ andq %r8,%r15
+
+ rorq $4,%r13
+ addq %r11,%r12
+ xorq %r10,%r15
+
+ rorq $6,%r14
+ xorq %r8,%r13
+ addq %r15,%r12
+
+ movq %rax,%r15
+ addq (%rbp),%r12
+ xorq %rax,%r14
+
+ xorq %rbx,%r15
+ rorq $14,%r13
+ movq %rbx,%r11
+
+ andq %r15,%rdi
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %rdi,%r11
+ addq %r12,%rdx
+ addq %r12,%r11
+
+ leaq 8(%rbp),%rbp
+ movq 80(%rsp),%r13
+ movq 56(%rsp),%rdi
+
+ movq %r13,%r12
+ rorq $7,%r13
+ addq %r14,%r11
+ movq %rdi,%r14
+ rorq $42,%rdi
+
+ xorq %r12,%r13
+ shrq $7,%r12
+ rorq $1,%r13
+ xorq %r14,%rdi
+ shrq $6,%r14
+
+ rorq $19,%rdi
+ xorq %r13,%r12
+ xorq %r14,%rdi
+ addq 16(%rsp),%r12
+
+ addq 72(%rsp),%r12
+ movq %rdx,%r13
+ addq %rdi,%r12
+ movq %r11,%r14
+ rorq $23,%r13
+ movq %r8,%rdi
+
+ xorq %rdx,%r13
+ rorq $5,%r14
+ xorq %r9,%rdi
+
+ movq %r12,72(%rsp)
+ xorq %r11,%r14
+ andq %rdx,%rdi
+
+ rorq $4,%r13
+ addq %r10,%r12
+ xorq %r9,%rdi
+
+ rorq $6,%r14
+ xorq %rdx,%r13
+ addq %rdi,%r12
+
+ movq %r11,%rdi
+ addq (%rbp),%r12
+ xorq %r11,%r14
+
+ xorq %rax,%rdi
+ rorq $14,%r13
+ movq %rax,%r10
+
+ andq %rdi,%r15
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %r15,%r10
+ addq %r12,%rcx
+ addq %r12,%r10
+
+ leaq 24(%rbp),%rbp
+ movq 88(%rsp),%r13
+ movq 64(%rsp),%r15
+
+ movq %r13,%r12
+ rorq $7,%r13
+ addq %r14,%r10
+ movq %r15,%r14
+ rorq $42,%r15
+
+ xorq %r12,%r13
+ shrq $7,%r12
+ rorq $1,%r13
+ xorq %r14,%r15
+ shrq $6,%r14
+
+ rorq $19,%r15
+ xorq %r13,%r12
+ xorq %r14,%r15
+ addq 24(%rsp),%r12
+
+ addq 80(%rsp),%r12
+ movq %rcx,%r13
+ addq %r15,%r12
+ movq %r10,%r14
+ rorq $23,%r13
+ movq %rdx,%r15
+
+ xorq %rcx,%r13
+ rorq $5,%r14
+ xorq %r8,%r15
+
+ movq %r12,80(%rsp)
+ xorq %r10,%r14
+ andq %rcx,%r15
+
+ rorq $4,%r13
+ addq %r9,%r12
+ xorq %r8,%r15
+
+ rorq $6,%r14
+ xorq %rcx,%r13
+ addq %r15,%r12
+
+ movq %r10,%r15
+ addq (%rbp),%r12
+ xorq %r10,%r14
+
+ xorq %r11,%r15
+ rorq $14,%r13
+ movq %r11,%r9
+
+ andq %r15,%rdi
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %rdi,%r9
+ addq %r12,%rbx
+ addq %r12,%r9
+
+ leaq 8(%rbp),%rbp
+ movq 96(%rsp),%r13
+ movq 72(%rsp),%rdi
+
+ movq %r13,%r12
+ rorq $7,%r13
+ addq %r14,%r9
+ movq %rdi,%r14
+ rorq $42,%rdi
+
+ xorq %r12,%r13
+ shrq $7,%r12
+ rorq $1,%r13
+ xorq %r14,%rdi
+ shrq $6,%r14
+
+ rorq $19,%rdi
+ xorq %r13,%r12
+ xorq %r14,%rdi
+ addq 32(%rsp),%r12
+
+ addq 88(%rsp),%r12
+ movq %rbx,%r13
+ addq %rdi,%r12
+ movq %r9,%r14
+ rorq $23,%r13
+ movq %rcx,%rdi
+
+ xorq %rbx,%r13
+ rorq $5,%r14
+ xorq %rdx,%rdi
+
+ movq %r12,88(%rsp)
+ xorq %r9,%r14
+ andq %rbx,%rdi
+
+ rorq $4,%r13
+ addq %r8,%r12
+ xorq %rdx,%rdi
+
+ rorq $6,%r14
+ xorq %rbx,%r13
+ addq %rdi,%r12
+
+ movq %r9,%rdi
+ addq (%rbp),%r12
+ xorq %r9,%r14
+
+ xorq %r10,%rdi
+ rorq $14,%r13
+ movq %r10,%r8
+
+ andq %rdi,%r15
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %r15,%r8
+ addq %r12,%rax
+ addq %r12,%r8
+
+ leaq 24(%rbp),%rbp
+ movq 104(%rsp),%r13
+ movq 80(%rsp),%r15
+
+ movq %r13,%r12
+ rorq $7,%r13
+ addq %r14,%r8
+ movq %r15,%r14
+ rorq $42,%r15
+
+ xorq %r12,%r13
+ shrq $7,%r12
+ rorq $1,%r13
+ xorq %r14,%r15
+ shrq $6,%r14
+
+ rorq $19,%r15
+ xorq %r13,%r12
+ xorq %r14,%r15
+ addq 40(%rsp),%r12
+
+ addq 96(%rsp),%r12
+ movq %rax,%r13
+ addq %r15,%r12
+ movq %r8,%r14
+ rorq $23,%r13
+ movq %rbx,%r15
+
+ xorq %rax,%r13
+ rorq $5,%r14
+ xorq %rcx,%r15
+
+ movq %r12,96(%rsp)
+ xorq %r8,%r14
+ andq %rax,%r15
+
+ rorq $4,%r13
+ addq %rdx,%r12
+ xorq %rcx,%r15
+
+ rorq $6,%r14
+ xorq %rax,%r13
+ addq %r15,%r12
+
+ movq %r8,%r15
+ addq (%rbp),%r12
+ xorq %r8,%r14
+
+ xorq %r9,%r15
+ rorq $14,%r13
+ movq %r9,%rdx
+
+ andq %r15,%rdi
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %rdi,%rdx
+ addq %r12,%r11
+ addq %r12,%rdx
+
+ leaq 8(%rbp),%rbp
+ movq 112(%rsp),%r13
+ movq 88(%rsp),%rdi
+
+ movq %r13,%r12
+ rorq $7,%r13
+ addq %r14,%rdx
+ movq %rdi,%r14
+ rorq $42,%rdi
+
+ xorq %r12,%r13
+ shrq $7,%r12
+ rorq $1,%r13
+ xorq %r14,%rdi
+ shrq $6,%r14
+
+ rorq $19,%rdi
+ xorq %r13,%r12
+ xorq %r14,%rdi
+ addq 48(%rsp),%r12
+
+ addq 104(%rsp),%r12
+ movq %r11,%r13
+ addq %rdi,%r12
+ movq %rdx,%r14
+ rorq $23,%r13
+ movq %rax,%rdi
+
+ xorq %r11,%r13
+ rorq $5,%r14
+ xorq %rbx,%rdi
+
+ movq %r12,104(%rsp)
+ xorq %rdx,%r14
+ andq %r11,%rdi
+
+ rorq $4,%r13
+ addq %rcx,%r12
+ xorq %rbx,%rdi
+
+ rorq $6,%r14
+ xorq %r11,%r13
+ addq %rdi,%r12
+
+ movq %rdx,%rdi
+ addq (%rbp),%r12
+ xorq %rdx,%r14
+
+ xorq %r8,%rdi
+ rorq $14,%r13
+ movq %r8,%rcx
+
+ andq %rdi,%r15
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %r15,%rcx
+ addq %r12,%r10
+ addq %r12,%rcx
+
+ leaq 24(%rbp),%rbp
+ movq 120(%rsp),%r13
+ movq 96(%rsp),%r15
+
+ movq %r13,%r12
+ rorq $7,%r13
+ addq %r14,%rcx
+ movq %r15,%r14
+ rorq $42,%r15
+
+ xorq %r12,%r13
+ shrq $7,%r12
+ rorq $1,%r13
+ xorq %r14,%r15
+ shrq $6,%r14
+
+ rorq $19,%r15
+ xorq %r13,%r12
+ xorq %r14,%r15
+ addq 56(%rsp),%r12
+
+ addq 112(%rsp),%r12
+ movq %r10,%r13
+ addq %r15,%r12
+ movq %rcx,%r14
+ rorq $23,%r13
+ movq %r11,%r15
+
+ xorq %r10,%r13
+ rorq $5,%r14
+ xorq %rax,%r15
+
+ movq %r12,112(%rsp)
+ xorq %rcx,%r14
+ andq %r10,%r15
+
+ rorq $4,%r13
+ addq %rbx,%r12
+ xorq %rax,%r15
+
+ rorq $6,%r14
+ xorq %r10,%r13
+ addq %r15,%r12
+
+ movq %rcx,%r15
+ addq (%rbp),%r12
+ xorq %rcx,%r14
+
+ xorq %rdx,%r15
+ rorq $14,%r13
+ movq %rdx,%rbx
+
+ andq %r15,%rdi
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %rdi,%rbx
+ addq %r12,%r9
+ addq %r12,%rbx
+
+ leaq 8(%rbp),%rbp
+ movq 0(%rsp),%r13
+ movq 104(%rsp),%rdi
+
+ movq %r13,%r12
+ rorq $7,%r13
+ addq %r14,%rbx
+ movq %rdi,%r14
+ rorq $42,%rdi
+
+ xorq %r12,%r13
+ shrq $7,%r12
+ rorq $1,%r13
+ xorq %r14,%rdi
+ shrq $6,%r14
+
+ rorq $19,%rdi
+ xorq %r13,%r12
+ xorq %r14,%rdi
+ addq 64(%rsp),%r12
+
+ addq 120(%rsp),%r12
+ movq %r9,%r13
+ addq %rdi,%r12
+ movq %rbx,%r14
+ rorq $23,%r13
+ movq %r10,%rdi
+
+ xorq %r9,%r13
+ rorq $5,%r14
+ xorq %r11,%rdi
+
+ movq %r12,120(%rsp)
+ xorq %rbx,%r14
+ andq %r9,%rdi
+
+ rorq $4,%r13
+ addq %rax,%r12
+ xorq %r11,%rdi
+
+ rorq $6,%r14
+ xorq %r9,%r13
+ addq %rdi,%r12
+
+ movq %rbx,%rdi
+ addq (%rbp),%r12
+ xorq %rbx,%r14
+
+ xorq %rcx,%rdi
+ rorq $14,%r13
+ movq %rcx,%rax
+
+ andq %rdi,%r15
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %r15,%rax
+ addq %r12,%r8
+ addq %r12,%rax
+
+ leaq 24(%rbp),%rbp
+ cmpb $0,7(%rbp)
+ jnz .Lrounds_16_xx
+
+ movq 128+0(%rsp),%rdi
+ addq %r14,%rax
+ 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:
+ .byte 0xf3,0xc3
+.size sha512_block_data_order,.-sha512_block_data_order
+.align 64
+.type K512,@object
+K512:
+.quad 0x428a2f98d728ae22,0x7137449123ef65cd
+.quad 0x428a2f98d728ae22,0x7137449123ef65cd
+.quad 0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc
+.quad 0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc
+.quad 0x3956c25bf348b538,0x59f111f1b605d019
+.quad 0x3956c25bf348b538,0x59f111f1b605d019
+.quad 0x923f82a4af194f9b,0xab1c5ed5da6d8118
+.quad 0x923f82a4af194f9b,0xab1c5ed5da6d8118
+.quad 0xd807aa98a3030242,0x12835b0145706fbe
+.quad 0xd807aa98a3030242,0x12835b0145706fbe
+.quad 0x243185be4ee4b28c,0x550c7dc3d5ffb4e2
+.quad 0x243185be4ee4b28c,0x550c7dc3d5ffb4e2
+.quad 0x72be5d74f27b896f,0x80deb1fe3b1696b1
+.quad 0x72be5d74f27b896f,0x80deb1fe3b1696b1
+.quad 0x9bdc06a725c71235,0xc19bf174cf692694
+.quad 0x9bdc06a725c71235,0xc19bf174cf692694
+.quad 0xe49b69c19ef14ad2,0xefbe4786384f25e3
+.quad 0xe49b69c19ef14ad2,0xefbe4786384f25e3
+.quad 0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65
+.quad 0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65
+.quad 0x2de92c6f592b0275,0x4a7484aa6ea6e483
+.quad 0x2de92c6f592b0275,0x4a7484aa6ea6e483
+.quad 0x5cb0a9dcbd41fbd4,0x76f988da831153b5
+.quad 0x5cb0a9dcbd41fbd4,0x76f988da831153b5
+.quad 0x983e5152ee66dfab,0xa831c66d2db43210
+.quad 0x983e5152ee66dfab,0xa831c66d2db43210
+.quad 0xb00327c898fb213f,0xbf597fc7beef0ee4
+.quad 0xb00327c898fb213f,0xbf597fc7beef0ee4
+.quad 0xc6e00bf33da88fc2,0xd5a79147930aa725
+.quad 0xc6e00bf33da88fc2,0xd5a79147930aa725
+.quad 0x06ca6351e003826f,0x142929670a0e6e70
+.quad 0x06ca6351e003826f,0x142929670a0e6e70
+.quad 0x27b70a8546d22ffc,0x2e1b21385c26c926
+.quad 0x27b70a8546d22ffc,0x2e1b21385c26c926
+.quad 0x4d2c6dfc5ac42aed,0x53380d139d95b3df
+.quad 0x4d2c6dfc5ac42aed,0x53380d139d95b3df
+.quad 0x650a73548baf63de,0x766a0abb3c77b2a8
+.quad 0x650a73548baf63de,0x766a0abb3c77b2a8
+.quad 0x81c2c92e47edaee6,0x92722c851482353b
+.quad 0x81c2c92e47edaee6,0x92722c851482353b
+.quad 0xa2bfe8a14cf10364,0xa81a664bbc423001
+.quad 0xa2bfe8a14cf10364,0xa81a664bbc423001
+.quad 0xc24b8b70d0f89791,0xc76c51a30654be30
+.quad 0xc24b8b70d0f89791,0xc76c51a30654be30
+.quad 0xd192e819d6ef5218,0xd69906245565a910
+.quad 0xd192e819d6ef5218,0xd69906245565a910
+.quad 0xf40e35855771202a,0x106aa07032bbd1b8
+.quad 0xf40e35855771202a,0x106aa07032bbd1b8
+.quad 0x19a4c116b8d2d0c8,0x1e376c085141ab53
+.quad 0x19a4c116b8d2d0c8,0x1e376c085141ab53
+.quad 0x2748774cdf8eeb99,0x34b0bcb5e19b48a8
+.quad 0x2748774cdf8eeb99,0x34b0bcb5e19b48a8
+.quad 0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb
+.quad 0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb
+.quad 0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3
+.quad 0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3
+.quad 0x748f82ee5defb2fc,0x78a5636f43172f60
+.quad 0x748f82ee5defb2fc,0x78a5636f43172f60
+.quad 0x84c87814a1f0ab72,0x8cc702081a6439ec
+.quad 0x84c87814a1f0ab72,0x8cc702081a6439ec
+.quad 0x90befffa23631e28,0xa4506cebde82bde9
+.quad 0x90befffa23631e28,0xa4506cebde82bde9
+.quad 0xbef9a3f7b2c67915,0xc67178f2e372532b
+.quad 0xbef9a3f7b2c67915,0xc67178f2e372532b
+.quad 0xca273eceea26619c,0xd186b8c721c0c207
+.quad 0xca273eceea26619c,0xd186b8c721c0c207
+.quad 0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178
+.quad 0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178
+.quad 0x06f067aa72176fba,0x0a637dc5a2c898a6
+.quad 0x06f067aa72176fba,0x0a637dc5a2c898a6
+.quad 0x113f9804bef90dae,0x1b710b35131c471b
+.quad 0x113f9804bef90dae,0x1b710b35131c471b
+.quad 0x28db77f523047d84,0x32caab7b40c72493
+.quad 0x28db77f523047d84,0x32caab7b40c72493
+.quad 0x3c9ebe0a15c9bebc,0x431d67c49c100d4c
+.quad 0x3c9ebe0a15c9bebc,0x431d67c49c100d4c
+.quad 0x4cc5d4becb3e42b6,0x597f299cfc657e2a
+.quad 0x4cc5d4becb3e42b6,0x597f299cfc657e2a
+.quad 0x5fcb6fab3ad6faec,0x6c44198c4a475817
+.quad 0x5fcb6fab3ad6faec,0x6c44198c4a475817
+
+.quad 0x0001020304050607,0x08090a0b0c0d0e0f
+.quad 0x0001020304050607,0x08090a0b0c0d0e0f
+.byte 83,72,65,53,49,50,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
+#endif
diff --git a/mac-x86/crypto/aes/aes-586.S b/mac-x86/crypto/aes/aes-586.S
new file mode 100644
index 0000000..d3dc6be
--- /dev/null
+++ b/mac-x86/crypto/aes/aes-586.S
@@ -0,0 +1,3221 @@
+#if defined(__i386__)
+.file "aes-586.S"
+.text
+.private_extern __x86_AES_encrypt_compact
+.align 4
+__x86_AES_encrypt_compact:
+ movl %edi,20(%esp)
+ xorl (%edi),%eax
+ xorl 4(%edi),%ebx
+ xorl 8(%edi),%ecx
+ xorl 12(%edi),%edx
+ movl 240(%edi),%esi
+ leal -2(%esi,%esi,1),%esi
+ leal (%edi,%esi,8),%esi
+ movl %esi,24(%esp)
+ movl -128(%ebp),%edi
+ movl -96(%ebp),%esi
+ movl -64(%ebp),%edi
+ movl -32(%ebp),%esi
+ movl (%ebp),%edi
+ movl 32(%ebp),%esi
+ movl 64(%ebp),%edi
+ movl 96(%ebp),%esi
+.align 4,0x90
+L000loop:
+ movl %eax,%esi
+ andl $255,%esi
+ movzbl -128(%ebp,%esi,1),%esi
+ movzbl %bh,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $8,%edi
+ xorl %edi,%esi
+ movl %ecx,%edi
+ shrl $16,%edi
+ andl $255,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $16,%edi
+ xorl %edi,%esi
+ movl %edx,%edi
+ shrl $24,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $24,%edi
+ xorl %edi,%esi
+ movl %esi,4(%esp)
+ movl %ebx,%esi
+ andl $255,%esi
+ shrl $16,%ebx
+ movzbl -128(%ebp,%esi,1),%esi
+ movzbl %ch,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $8,%edi
+ xorl %edi,%esi
+ movl %edx,%edi
+ shrl $16,%edi
+ andl $255,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $16,%edi
+ xorl %edi,%esi
+ movl %eax,%edi
+ shrl $24,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $24,%edi
+ xorl %edi,%esi
+ movl %esi,8(%esp)
+ movl %ecx,%esi
+ andl $255,%esi
+ shrl $24,%ecx
+ movzbl -128(%ebp,%esi,1),%esi
+ movzbl %dh,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $8,%edi
+ xorl %edi,%esi
+ movl %eax,%edi
+ shrl $16,%edi
+ andl $255,%edx
+ andl $255,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $16,%edi
+ xorl %edi,%esi
+ movzbl %bh,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $24,%edi
+ xorl %edi,%esi
+ andl $255,%edx
+ movzbl -128(%ebp,%edx,1),%edx
+ movzbl %ah,%eax
+ movzbl -128(%ebp,%eax,1),%eax
+ shll $8,%eax
+ xorl %eax,%edx
+ movl 4(%esp),%eax
+ andl $255,%ebx
+ movzbl -128(%ebp,%ebx,1),%ebx
+ shll $16,%ebx
+ xorl %ebx,%edx
+ movl 8(%esp),%ebx
+ movzbl -128(%ebp,%ecx,1),%ecx
+ shll $24,%ecx
+ xorl %ecx,%edx
+ movl %esi,%ecx
+ movl $2155905152,%ebp
+ andl %ecx,%ebp
+ leal (%ecx,%ecx,1),%edi
+ movl %ebp,%esi
+ shrl $7,%ebp
+ andl $4278124286,%edi
+ subl %ebp,%esi
+ movl %ecx,%ebp
+ andl $454761243,%esi
+ rorl $16,%ebp
+ xorl %edi,%esi
+ movl %ecx,%edi
+ xorl %esi,%ecx
+ rorl $24,%edi
+ xorl %ebp,%esi
+ roll $24,%ecx
+ xorl %edi,%esi
+ movl $2155905152,%ebp
+ xorl %esi,%ecx
+ andl %edx,%ebp
+ leal (%edx,%edx,1),%edi
+ movl %ebp,%esi
+ shrl $7,%ebp
+ andl $4278124286,%edi
+ subl %ebp,%esi
+ movl %edx,%ebp
+ andl $454761243,%esi
+ rorl $16,%ebp
+ xorl %edi,%esi
+ movl %edx,%edi
+ xorl %esi,%edx
+ rorl $24,%edi
+ xorl %ebp,%esi
+ roll $24,%edx
+ xorl %edi,%esi
+ movl $2155905152,%ebp
+ xorl %esi,%edx
+ andl %eax,%ebp
+ leal (%eax,%eax,1),%edi
+ movl %ebp,%esi
+ shrl $7,%ebp
+ andl $4278124286,%edi
+ subl %ebp,%esi
+ movl %eax,%ebp
+ andl $454761243,%esi
+ rorl $16,%ebp
+ xorl %edi,%esi
+ movl %eax,%edi
+ xorl %esi,%eax
+ rorl $24,%edi
+ xorl %ebp,%esi
+ roll $24,%eax
+ xorl %edi,%esi
+ movl $2155905152,%ebp
+ xorl %esi,%eax
+ andl %ebx,%ebp
+ leal (%ebx,%ebx,1),%edi
+ movl %ebp,%esi
+ shrl $7,%ebp
+ andl $4278124286,%edi
+ subl %ebp,%esi
+ movl %ebx,%ebp
+ andl $454761243,%esi
+ rorl $16,%ebp
+ xorl %edi,%esi
+ movl %ebx,%edi
+ xorl %esi,%ebx
+ rorl $24,%edi
+ xorl %ebp,%esi
+ roll $24,%ebx
+ xorl %edi,%esi
+ xorl %esi,%ebx
+ movl 20(%esp),%edi
+ movl 28(%esp),%ebp
+ addl $16,%edi
+ xorl (%edi),%eax
+ xorl 4(%edi),%ebx
+ xorl 8(%edi),%ecx
+ xorl 12(%edi),%edx
+ cmpl 24(%esp),%edi
+ movl %edi,20(%esp)
+ jb L000loop
+ movl %eax,%esi
+ andl $255,%esi
+ movzbl -128(%ebp,%esi,1),%esi
+ movzbl %bh,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $8,%edi
+ xorl %edi,%esi
+ movl %ecx,%edi
+ shrl $16,%edi
+ andl $255,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $16,%edi
+ xorl %edi,%esi
+ movl %edx,%edi
+ shrl $24,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $24,%edi
+ xorl %edi,%esi
+ movl %esi,4(%esp)
+ movl %ebx,%esi
+ andl $255,%esi
+ shrl $16,%ebx
+ movzbl -128(%ebp,%esi,1),%esi
+ movzbl %ch,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $8,%edi
+ xorl %edi,%esi
+ movl %edx,%edi
+ shrl $16,%edi
+ andl $255,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $16,%edi
+ xorl %edi,%esi
+ movl %eax,%edi
+ shrl $24,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $24,%edi
+ xorl %edi,%esi
+ movl %esi,8(%esp)
+ movl %ecx,%esi
+ andl $255,%esi
+ shrl $24,%ecx
+ movzbl -128(%ebp,%esi,1),%esi
+ movzbl %dh,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $8,%edi
+ xorl %edi,%esi
+ movl %eax,%edi
+ shrl $16,%edi
+ andl $255,%edx
+ andl $255,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $16,%edi
+ xorl %edi,%esi
+ movzbl %bh,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $24,%edi
+ xorl %edi,%esi
+ movl 20(%esp),%edi
+ andl $255,%edx
+ movzbl -128(%ebp,%edx,1),%edx
+ movzbl %ah,%eax
+ movzbl -128(%ebp,%eax,1),%eax
+ shll $8,%eax
+ xorl %eax,%edx
+ movl 4(%esp),%eax
+ andl $255,%ebx
+ movzbl -128(%ebp,%ebx,1),%ebx
+ shll $16,%ebx
+ xorl %ebx,%edx
+ movl 8(%esp),%ebx
+ movzbl -128(%ebp,%ecx,1),%ecx
+ shll $24,%ecx
+ xorl %ecx,%edx
+ movl %esi,%ecx
+ xorl 16(%edi),%eax
+ xorl 20(%edi),%ebx
+ xorl 24(%edi),%ecx
+ xorl 28(%edi),%edx
+ ret
+.private_extern __sse_AES_encrypt_compact
+.align 4
+__sse_AES_encrypt_compact:
+ pxor (%edi),%mm0
+ pxor 8(%edi),%mm4
+ movl 240(%edi),%esi
+ leal -2(%esi,%esi,1),%esi
+ leal (%edi,%esi,8),%esi
+ movl %esi,24(%esp)
+ movl $454761243,%eax
+ movl %eax,8(%esp)
+ movl %eax,12(%esp)
+ movl -128(%ebp),%eax
+ movl -96(%ebp),%ebx
+ movl -64(%ebp),%ecx
+ movl -32(%ebp),%edx
+ movl (%ebp),%eax
+ movl 32(%ebp),%ebx
+ movl 64(%ebp),%ecx
+ movl 96(%ebp),%edx
+.align 4,0x90
+L001loop:
+ pshufw $8,%mm0,%mm1
+ pshufw $13,%mm4,%mm5
+ movd %mm1,%eax
+ movd %mm5,%ebx
+ movl %edi,20(%esp)
+ movzbl %al,%esi
+ movzbl %ah,%edx
+ pshufw $13,%mm0,%mm2
+ movzbl -128(%ebp,%esi,1),%ecx
+ movzbl %bl,%edi
+ movzbl -128(%ebp,%edx,1),%edx
+ shrl $16,%eax
+ shll $8,%edx
+ movzbl -128(%ebp,%edi,1),%esi
+ movzbl %bh,%edi
+ shll $16,%esi
+ pshufw $8,%mm4,%mm6
+ orl %esi,%ecx
+ movzbl -128(%ebp,%edi,1),%esi
+ movzbl %ah,%edi
+ shll $24,%esi
+ shrl $16,%ebx
+ orl %esi,%edx
+ movzbl -128(%ebp,%edi,1),%esi
+ movzbl %bh,%edi
+ shll $8,%esi
+ orl %esi,%ecx
+ movzbl -128(%ebp,%edi,1),%esi
+ movzbl %al,%edi
+ shll $24,%esi
+ orl %esi,%ecx
+ movzbl -128(%ebp,%edi,1),%esi
+ movzbl %bl,%edi
+ movd %mm2,%eax
+ movd %ecx,%mm0
+ movzbl -128(%ebp,%edi,1),%ecx
+ movzbl %ah,%edi
+ shll $16,%ecx
+ movd %mm6,%ebx
+ orl %esi,%ecx
+ movzbl -128(%ebp,%edi,1),%esi
+ movzbl %bh,%edi
+ shll $24,%esi
+ orl %esi,%ecx
+ movzbl -128(%ebp,%edi,1),%esi
+ movzbl %bl,%edi
+ shll $8,%esi
+ shrl $16,%ebx
+ orl %esi,%ecx
+ movzbl -128(%ebp,%edi,1),%esi
+ movzbl %al,%edi
+ shrl $16,%eax
+ movd %ecx,%mm1
+ movzbl -128(%ebp,%edi,1),%ecx
+ movzbl %ah,%edi
+ shll $16,%ecx
+ andl $255,%eax
+ orl %esi,%ecx
+ punpckldq %mm1,%mm0
+ movzbl -128(%ebp,%edi,1),%esi
+ movzbl %bh,%edi
+ shll $24,%esi
+ andl $255,%ebx
+ movzbl -128(%ebp,%eax,1),%eax
+ orl %esi,%ecx
+ shll $16,%eax
+ movzbl -128(%ebp,%edi,1),%esi
+ orl %eax,%edx
+ shll $8,%esi
+ movzbl -128(%ebp,%ebx,1),%ebx
+ orl %esi,%ecx
+ orl %ebx,%edx
+ movl 20(%esp),%edi
+ movd %ecx,%mm4
+ movd %edx,%mm5
+ punpckldq %mm5,%mm4
+ addl $16,%edi
+ cmpl 24(%esp),%edi
+ ja L002out
+ movq 8(%esp),%mm2
+ pxor %mm3,%mm3
+ pxor %mm7,%mm7
+ movq %mm0,%mm1
+ movq %mm4,%mm5
+ pcmpgtb %mm0,%mm3
+ pcmpgtb %mm4,%mm7
+ pand %mm2,%mm3
+ pand %mm2,%mm7
+ pshufw $177,%mm0,%mm2
+ pshufw $177,%mm4,%mm6
+ paddb %mm0,%mm0
+ paddb %mm4,%mm4
+ pxor %mm3,%mm0
+ pxor %mm7,%mm4
+ pshufw $177,%mm2,%mm3
+ pshufw $177,%mm6,%mm7
+ pxor %mm0,%mm1
+ pxor %mm4,%mm5
+ pxor %mm2,%mm0
+ pxor %mm6,%mm4
+ movq %mm3,%mm2
+ movq %mm7,%mm6
+ pslld $8,%mm3
+ pslld $8,%mm7
+ psrld $24,%mm2
+ psrld $24,%mm6
+ pxor %mm3,%mm0
+ pxor %mm7,%mm4
+ pxor %mm2,%mm0
+ pxor %mm6,%mm4
+ movq %mm1,%mm3
+ movq %mm5,%mm7
+ movq (%edi),%mm2
+ movq 8(%edi),%mm6
+ psrld $8,%mm1
+ psrld $8,%mm5
+ movl -128(%ebp),%eax
+ pslld $24,%mm3
+ pslld $24,%mm7
+ movl -64(%ebp),%ebx
+ pxor %mm1,%mm0
+ pxor %mm5,%mm4
+ movl (%ebp),%ecx
+ pxor %mm3,%mm0
+ pxor %mm7,%mm4
+ movl 64(%ebp),%edx
+ pxor %mm2,%mm0
+ pxor %mm6,%mm4
+ jmp L001loop
+.align 4,0x90
+L002out:
+ pxor (%edi),%mm0
+ pxor 8(%edi),%mm4
+ ret
+.private_extern __x86_AES_encrypt
+.align 4
+__x86_AES_encrypt:
+ movl %edi,20(%esp)
+ xorl (%edi),%eax
+ xorl 4(%edi),%ebx
+ xorl 8(%edi),%ecx
+ xorl 12(%edi),%edx
+ movl 240(%edi),%esi
+ leal -2(%esi,%esi,1),%esi
+ leal (%edi,%esi,8),%esi
+ movl %esi,24(%esp)
+.align 4,0x90
+L003loop:
+ movl %eax,%esi
+ andl $255,%esi
+ movl (%ebp,%esi,8),%esi
+ movzbl %bh,%edi
+ xorl 3(%ebp,%edi,8),%esi
+ movl %ecx,%edi
+ shrl $16,%edi
+ andl $255,%edi
+ xorl 2(%ebp,%edi,8),%esi
+ movl %edx,%edi
+ shrl $24,%edi
+ xorl 1(%ebp,%edi,8),%esi
+ movl %esi,4(%esp)
+ movl %ebx,%esi
+ andl $255,%esi
+ shrl $16,%ebx
+ movl (%ebp,%esi,8),%esi
+ movzbl %ch,%edi
+ xorl 3(%ebp,%edi,8),%esi
+ movl %edx,%edi
+ shrl $16,%edi
+ andl $255,%edi
+ xorl 2(%ebp,%edi,8),%esi
+ movl %eax,%edi
+ shrl $24,%edi
+ xorl 1(%ebp,%edi,8),%esi
+ movl %esi,8(%esp)
+ movl %ecx,%esi
+ andl $255,%esi
+ shrl $24,%ecx
+ movl (%ebp,%esi,8),%esi
+ movzbl %dh,%edi
+ xorl 3(%ebp,%edi,8),%esi
+ movl %eax,%edi
+ shrl $16,%edi
+ andl $255,%edx
+ andl $255,%edi
+ xorl 2(%ebp,%edi,8),%esi
+ movzbl %bh,%edi
+ xorl 1(%ebp,%edi,8),%esi
+ movl 20(%esp),%edi
+ movl (%ebp,%edx,8),%edx
+ movzbl %ah,%eax
+ xorl 3(%ebp,%eax,8),%edx
+ movl 4(%esp),%eax
+ andl $255,%ebx
+ xorl 2(%ebp,%ebx,8),%edx
+ movl 8(%esp),%ebx
+ xorl 1(%ebp,%ecx,8),%edx
+ movl %esi,%ecx
+ addl $16,%edi
+ xorl (%edi),%eax
+ xorl 4(%edi),%ebx
+ xorl 8(%edi),%ecx
+ xorl 12(%edi),%edx
+ cmpl 24(%esp),%edi
+ movl %edi,20(%esp)
+ jb L003loop
+ movl %eax,%esi
+ andl $255,%esi
+ movl 2(%ebp,%esi,8),%esi
+ andl $255,%esi
+ movzbl %bh,%edi
+ movl (%ebp,%edi,8),%edi
+ andl $65280,%edi
+ xorl %edi,%esi
+ movl %ecx,%edi
+ shrl $16,%edi
+ andl $255,%edi
+ movl (%ebp,%edi,8),%edi
+ andl $16711680,%edi
+ xorl %edi,%esi
+ movl %edx,%edi
+ shrl $24,%edi
+ movl 2(%ebp,%edi,8),%edi
+ andl $4278190080,%edi
+ xorl %edi,%esi
+ movl %esi,4(%esp)
+ movl %ebx,%esi
+ andl $255,%esi
+ shrl $16,%ebx
+ movl 2(%ebp,%esi,8),%esi
+ andl $255,%esi
+ movzbl %ch,%edi
+ movl (%ebp,%edi,8),%edi
+ andl $65280,%edi
+ xorl %edi,%esi
+ movl %edx,%edi
+ shrl $16,%edi
+ andl $255,%edi
+ movl (%ebp,%edi,8),%edi
+ andl $16711680,%edi
+ xorl %edi,%esi
+ movl %eax,%edi
+ shrl $24,%edi
+ movl 2(%ebp,%edi,8),%edi
+ andl $4278190080,%edi
+ xorl %edi,%esi
+ movl %esi,8(%esp)
+ movl %ecx,%esi
+ andl $255,%esi
+ shrl $24,%ecx
+ movl 2(%ebp,%esi,8),%esi
+ andl $255,%esi
+ movzbl %dh,%edi
+ movl (%ebp,%edi,8),%edi
+ andl $65280,%edi
+ xorl %edi,%esi
+ movl %eax,%edi
+ shrl $16,%edi
+ andl $255,%edx
+ andl $255,%edi
+ movl (%ebp,%edi,8),%edi
+ andl $16711680,%edi
+ xorl %edi,%esi
+ movzbl %bh,%edi
+ movl 2(%ebp,%edi,8),%edi
+ andl $4278190080,%edi
+ xorl %edi,%esi
+ movl 20(%esp),%edi
+ andl $255,%edx
+ movl 2(%ebp,%edx,8),%edx
+ andl $255,%edx
+ movzbl %ah,%eax
+ movl (%ebp,%eax,8),%eax
+ andl $65280,%eax
+ xorl %eax,%edx
+ movl 4(%esp),%eax
+ andl $255,%ebx
+ movl (%ebp,%ebx,8),%ebx
+ andl $16711680,%ebx
+ xorl %ebx,%edx
+ movl 8(%esp),%ebx
+ movl 2(%ebp,%ecx,8),%ecx
+ andl $4278190080,%ecx
+ xorl %ecx,%edx
+ movl %esi,%ecx
+ addl $16,%edi
+ xorl (%edi),%eax
+ xorl 4(%edi),%ebx
+ xorl 8(%edi),%ecx
+ xorl 12(%edi),%edx
+ ret
+.align 6,0x90
+LAES_Te:
+.long 2774754246,2774754246
+.long 2222750968,2222750968
+.long 2574743534,2574743534
+.long 2373680118,2373680118
+.long 234025727,234025727
+.long 3177933782,3177933782
+.long 2976870366,2976870366
+.long 1422247313,1422247313
+.long 1345335392,1345335392
+.long 50397442,50397442
+.long 2842126286,2842126286
+.long 2099981142,2099981142
+.long 436141799,436141799
+.long 1658312629,1658312629
+.long 3870010189,3870010189
+.long 2591454956,2591454956
+.long 1170918031,1170918031
+.long 2642575903,2642575903
+.long 1086966153,1086966153
+.long 2273148410,2273148410
+.long 368769775,368769775
+.long 3948501426,3948501426
+.long 3376891790,3376891790
+.long 200339707,200339707
+.long 3970805057,3970805057
+.long 1742001331,1742001331
+.long 4255294047,4255294047
+.long 3937382213,3937382213
+.long 3214711843,3214711843
+.long 4154762323,4154762323
+.long 2524082916,2524082916
+.long 1539358875,1539358875
+.long 3266819957,3266819957
+.long 486407649,486407649
+.long 2928907069,2928907069
+.long 1780885068,1780885068
+.long 1513502316,1513502316
+.long 1094664062,1094664062
+.long 49805301,49805301
+.long 1338821763,1338821763
+.long 1546925160,1546925160
+.long 4104496465,4104496465
+.long 887481809,887481809
+.long 150073849,150073849
+.long 2473685474,2473685474
+.long 1943591083,1943591083
+.long 1395732834,1395732834
+.long 1058346282,1058346282
+.long 201589768,201589768
+.long 1388824469,1388824469
+.long 1696801606,1696801606
+.long 1589887901,1589887901
+.long 672667696,672667696
+.long 2711000631,2711000631
+.long 251987210,251987210
+.long 3046808111,3046808111
+.long 151455502,151455502
+.long 907153956,907153956
+.long 2608889883,2608889883
+.long 1038279391,1038279391
+.long 652995533,652995533
+.long 1764173646,1764173646
+.long 3451040383,3451040383
+.long 2675275242,2675275242
+.long 453576978,453576978
+.long 2659418909,2659418909
+.long 1949051992,1949051992
+.long 773462580,773462580
+.long 756751158,756751158
+.long 2993581788,2993581788
+.long 3998898868,3998898868
+.long 4221608027,4221608027
+.long 4132590244,4132590244
+.long 1295727478,1295727478
+.long 1641469623,1641469623
+.long 3467883389,3467883389
+.long 2066295122,2066295122
+.long 1055122397,1055122397
+.long 1898917726,1898917726
+.long 2542044179,2542044179
+.long 4115878822,4115878822
+.long 1758581177,1758581177
+.long 0,0
+.long 753790401,753790401
+.long 1612718144,1612718144
+.long 536673507,536673507
+.long 3367088505,3367088505
+.long 3982187446,3982187446
+.long 3194645204,3194645204
+.long 1187761037,1187761037
+.long 3653156455,3653156455
+.long 1262041458,1262041458
+.long 3729410708,3729410708
+.long 3561770136,3561770136
+.long 3898103984,3898103984
+.long 1255133061,1255133061
+.long 1808847035,1808847035
+.long 720367557,720367557
+.long 3853167183,3853167183
+.long 385612781,385612781
+.long 3309519750,3309519750
+.long 3612167578,3612167578
+.long 1429418854,1429418854
+.long 2491778321,2491778321
+.long 3477423498,3477423498
+.long 284817897,284817897
+.long 100794884,100794884
+.long 2172616702,2172616702
+.long 4031795360,4031795360
+.long 1144798328,1144798328
+.long 3131023141,3131023141
+.long 3819481163,3819481163
+.long 4082192802,4082192802
+.long 4272137053,4272137053
+.long 3225436288,3225436288
+.long 2324664069,2324664069
+.long 2912064063,2912064063
+.long 3164445985,3164445985
+.long 1211644016,1211644016
+.long 83228145,83228145
+.long 3753688163,3753688163
+.long 3249976951,3249976951
+.long 1977277103,1977277103
+.long 1663115586,1663115586
+.long 806359072,806359072
+.long 452984805,452984805
+.long 250868733,250868733
+.long 1842533055,1842533055
+.long 1288555905,1288555905
+.long 336333848,336333848
+.long 890442534,890442534
+.long 804056259,804056259
+.long 3781124030,3781124030
+.long 2727843637,2727843637
+.long 3427026056,3427026056
+.long 957814574,957814574
+.long 1472513171,1472513171
+.long 4071073621,4071073621
+.long 2189328124,2189328124
+.long 1195195770,1195195770
+.long 2892260552,2892260552
+.long 3881655738,3881655738
+.long 723065138,723065138
+.long 2507371494,2507371494
+.long 2690670784,2690670784
+.long 2558624025,2558624025
+.long 3511635870,3511635870
+.long 2145180835,2145180835
+.long 1713513028,1713513028
+.long 2116692564,2116692564
+.long 2878378043,2878378043
+.long 2206763019,2206763019
+.long 3393603212,3393603212
+.long 703524551,703524551
+.long 3552098411,3552098411
+.long 1007948840,1007948840
+.long 2044649127,2044649127
+.long 3797835452,3797835452
+.long 487262998,487262998
+.long 1994120109,1994120109
+.long 1004593371,1004593371
+.long 1446130276,1446130276
+.long 1312438900,1312438900
+.long 503974420,503974420
+.long 3679013266,3679013266
+.long 168166924,168166924
+.long 1814307912,1814307912
+.long 3831258296,3831258296
+.long 1573044895,1573044895
+.long 1859376061,1859376061
+.long 4021070915,4021070915
+.long 2791465668,2791465668
+.long 2828112185,2828112185
+.long 2761266481,2761266481
+.long 937747667,937747667
+.long 2339994098,2339994098
+.long 854058965,854058965
+.long 1137232011,1137232011
+.long 1496790894,1496790894
+.long 3077402074,3077402074
+.long 2358086913,2358086913
+.long 1691735473,1691735473
+.long 3528347292,3528347292
+.long 3769215305,3769215305
+.long 3027004632,3027004632
+.long 4199962284,4199962284
+.long 133494003,133494003
+.long 636152527,636152527
+.long 2942657994,2942657994
+.long 2390391540,2390391540
+.long 3920539207,3920539207
+.long 403179536,403179536
+.long 3585784431,3585784431
+.long 2289596656,2289596656
+.long 1864705354,1864705354
+.long 1915629148,1915629148
+.long 605822008,605822008
+.long 4054230615,4054230615
+.long 3350508659,3350508659
+.long 1371981463,1371981463
+.long 602466507,602466507
+.long 2094914977,2094914977
+.long 2624877800,2624877800
+.long 555687742,555687742
+.long 3712699286,3712699286
+.long 3703422305,3703422305
+.long 2257292045,2257292045
+.long 2240449039,2240449039
+.long 2423288032,2423288032
+.long 1111375484,1111375484
+.long 3300242801,3300242801
+.long 2858837708,2858837708
+.long 3628615824,3628615824
+.long 84083462,84083462
+.long 32962295,32962295
+.long 302911004,302911004
+.long 2741068226,2741068226
+.long 1597322602,1597322602
+.long 4183250862,4183250862
+.long 3501832553,3501832553
+.long 2441512471,2441512471
+.long 1489093017,1489093017
+.long 656219450,656219450
+.long 3114180135,3114180135
+.long 954327513,954327513
+.long 335083755,335083755
+.long 3013122091,3013122091
+.long 856756514,856756514
+.long 3144247762,3144247762
+.long 1893325225,1893325225
+.long 2307821063,2307821063
+.long 2811532339,2811532339
+.long 3063651117,3063651117
+.long 572399164,572399164
+.long 2458355477,2458355477
+.long 552200649,552200649
+.long 1238290055,1238290055
+.long 4283782570,4283782570
+.long 2015897680,2015897680
+.long 2061492133,2061492133
+.long 2408352771,2408352771
+.long 4171342169,4171342169
+.long 2156497161,2156497161
+.long 386731290,386731290
+.long 3669999461,3669999461
+.long 837215959,837215959
+.long 3326231172,3326231172
+.long 3093850320,3093850320
+.long 3275833730,3275833730
+.long 2962856233,2962856233
+.long 1999449434,1999449434
+.long 286199582,286199582
+.long 3417354363,3417354363
+.long 4233385128,4233385128
+.long 3602627437,3602627437
+.long 974525996,974525996
+.byte 99,124,119,123,242,107,111,197
+.byte 48,1,103,43,254,215,171,118
+.byte 202,130,201,125,250,89,71,240
+.byte 173,212,162,175,156,164,114,192
+.byte 183,253,147,38,54,63,247,204
+.byte 52,165,229,241,113,216,49,21
+.byte 4,199,35,195,24,150,5,154
+.byte 7,18,128,226,235,39,178,117
+.byte 9,131,44,26,27,110,90,160
+.byte 82,59,214,179,41,227,47,132
+.byte 83,209,0,237,32,252,177,91
+.byte 106,203,190,57,74,76,88,207
+.byte 208,239,170,251,67,77,51,133
+.byte 69,249,2,127,80,60,159,168
+.byte 81,163,64,143,146,157,56,245
+.byte 188,182,218,33,16,255,243,210
+.byte 205,12,19,236,95,151,68,23
+.byte 196,167,126,61,100,93,25,115
+.byte 96,129,79,220,34,42,144,136
+.byte 70,238,184,20,222,94,11,219
+.byte 224,50,58,10,73,6,36,92
+.byte 194,211,172,98,145,149,228,121
+.byte 231,200,55,109,141,213,78,169
+.byte 108,86,244,234,101,122,174,8
+.byte 186,120,37,46,28,166,180,198
+.byte 232,221,116,31,75,189,139,138
+.byte 112,62,181,102,72,3,246,14
+.byte 97,53,87,185,134,193,29,158
+.byte 225,248,152,17,105,217,142,148
+.byte 155,30,135,233,206,85,40,223
+.byte 140,161,137,13,191,230,66,104
+.byte 65,153,45,15,176,84,187,22
+.byte 99,124,119,123,242,107,111,197
+.byte 48,1,103,43,254,215,171,118
+.byte 202,130,201,125,250,89,71,240
+.byte 173,212,162,175,156,164,114,192
+.byte 183,253,147,38,54,63,247,204
+.byte 52,165,229,241,113,216,49,21
+.byte 4,199,35,195,24,150,5,154
+.byte 7,18,128,226,235,39,178,117
+.byte 9,131,44,26,27,110,90,160
+.byte 82,59,214,179,41,227,47,132
+.byte 83,209,0,237,32,252,177,91
+.byte 106,203,190,57,74,76,88,207
+.byte 208,239,170,251,67,77,51,133
+.byte 69,249,2,127,80,60,159,168
+.byte 81,163,64,143,146,157,56,245
+.byte 188,182,218,33,16,255,243,210
+.byte 205,12,19,236,95,151,68,23
+.byte 196,167,126,61,100,93,25,115
+.byte 96,129,79,220,34,42,144,136
+.byte 70,238,184,20,222,94,11,219
+.byte 224,50,58,10,73,6,36,92
+.byte 194,211,172,98,145,149,228,121
+.byte 231,200,55,109,141,213,78,169
+.byte 108,86,244,234,101,122,174,8
+.byte 186,120,37,46,28,166,180,198
+.byte 232,221,116,31,75,189,139,138
+.byte 112,62,181,102,72,3,246,14
+.byte 97,53,87,185,134,193,29,158
+.byte 225,248,152,17,105,217,142,148
+.byte 155,30,135,233,206,85,40,223
+.byte 140,161,137,13,191,230,66,104
+.byte 65,153,45,15,176,84,187,22
+.byte 99,124,119,123,242,107,111,197
+.byte 48,1,103,43,254,215,171,118
+.byte 202,130,201,125,250,89,71,240
+.byte 173,212,162,175,156,164,114,192
+.byte 183,253,147,38,54,63,247,204
+.byte 52,165,229,241,113,216,49,21
+.byte 4,199,35,195,24,150,5,154
+.byte 7,18,128,226,235,39,178,117
+.byte 9,131,44,26,27,110,90,160
+.byte 82,59,214,179,41,227,47,132
+.byte 83,209,0,237,32,252,177,91
+.byte 106,203,190,57,74,76,88,207
+.byte 208,239,170,251,67,77,51,133
+.byte 69,249,2,127,80,60,159,168
+.byte 81,163,64,143,146,157,56,245
+.byte 188,182,218,33,16,255,243,210
+.byte 205,12,19,236,95,151,68,23
+.byte 196,167,126,61,100,93,25,115
+.byte 96,129,79,220,34,42,144,136
+.byte 70,238,184,20,222,94,11,219
+.byte 224,50,58,10,73,6,36,92
+.byte 194,211,172,98,145,149,228,121
+.byte 231,200,55,109,141,213,78,169
+.byte 108,86,244,234,101,122,174,8
+.byte 186,120,37,46,28,166,180,198
+.byte 232,221,116,31,75,189,139,138
+.byte 112,62,181,102,72,3,246,14
+.byte 97,53,87,185,134,193,29,158
+.byte 225,248,152,17,105,217,142,148
+.byte 155,30,135,233,206,85,40,223
+.byte 140,161,137,13,191,230,66,104
+.byte 65,153,45,15,176,84,187,22
+.byte 99,124,119,123,242,107,111,197
+.byte 48,1,103,43,254,215,171,118
+.byte 202,130,201,125,250,89,71,240
+.byte 173,212,162,175,156,164,114,192
+.byte 183,253,147,38,54,63,247,204
+.byte 52,165,229,241,113,216,49,21
+.byte 4,199,35,195,24,150,5,154
+.byte 7,18,128,226,235,39,178,117
+.byte 9,131,44,26,27,110,90,160
+.byte 82,59,214,179,41,227,47,132
+.byte 83,209,0,237,32,252,177,91
+.byte 106,203,190,57,74,76,88,207
+.byte 208,239,170,251,67,77,51,133
+.byte 69,249,2,127,80,60,159,168
+.byte 81,163,64,143,146,157,56,245
+.byte 188,182,218,33,16,255,243,210
+.byte 205,12,19,236,95,151,68,23
+.byte 196,167,126,61,100,93,25,115
+.byte 96,129,79,220,34,42,144,136
+.byte 70,238,184,20,222,94,11,219
+.byte 224,50,58,10,73,6,36,92
+.byte 194,211,172,98,145,149,228,121
+.byte 231,200,55,109,141,213,78,169
+.byte 108,86,244,234,101,122,174,8
+.byte 186,120,37,46,28,166,180,198
+.byte 232,221,116,31,75,189,139,138
+.byte 112,62,181,102,72,3,246,14
+.byte 97,53,87,185,134,193,29,158
+.byte 225,248,152,17,105,217,142,148
+.byte 155,30,135,233,206,85,40,223
+.byte 140,161,137,13,191,230,66,104
+.byte 65,153,45,15,176,84,187,22
+.long 1,2,4,8
+.long 16,32,64,128
+.long 27,54,0,0
+.long 0,0,0,0
+.globl _asm_AES_encrypt
+.private_extern _asm_AES_encrypt
+.align 4
+_asm_AES_encrypt:
+L_asm_AES_encrypt_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ movl 20(%esp),%esi
+ movl 28(%esp),%edi
+ movl %esp,%eax
+ subl $36,%esp
+ andl $-64,%esp
+ leal -127(%edi),%ebx
+ subl %esp,%ebx
+ negl %ebx
+ andl $960,%ebx
+ subl %ebx,%esp
+ addl $4,%esp
+ movl %eax,28(%esp)
+ call L004pic_point
+L004pic_point:
+ popl %ebp
+ movl L_OPENSSL_ia32cap_P$non_lazy_ptr-L004pic_point(%ebp),%eax
+ leal LAES_Te-L004pic_point(%ebp),%ebp
+ leal 764(%esp),%ebx
+ subl %ebp,%ebx
+ andl $768,%ebx
+ leal 2176(%ebp,%ebx,1),%ebp
+ btl $25,(%eax)
+ jnc L005x86
+ movq (%esi),%mm0
+ movq 8(%esi),%mm4
+ call __sse_AES_encrypt_compact
+ movl 28(%esp),%esp
+ movl 24(%esp),%esi
+ movq %mm0,(%esi)
+ movq %mm4,8(%esi)
+ emms
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.align 4,0x90
+L005x86:
+ movl %ebp,24(%esp)
+ movl (%esi),%eax
+ movl 4(%esi),%ebx
+ movl 8(%esi),%ecx
+ movl 12(%esi),%edx
+ call __x86_AES_encrypt_compact
+ movl 28(%esp),%esp
+ movl 24(%esp),%esi
+ movl %eax,(%esi)
+ movl %ebx,4(%esi)
+ movl %ecx,8(%esi)
+ movl %edx,12(%esi)
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.private_extern __x86_AES_decrypt_compact
+.align 4
+__x86_AES_decrypt_compact:
+ movl %edi,20(%esp)
+ xorl (%edi),%eax
+ xorl 4(%edi),%ebx
+ xorl 8(%edi),%ecx
+ xorl 12(%edi),%edx
+ movl 240(%edi),%esi
+ leal -2(%esi,%esi,1),%esi
+ leal (%edi,%esi,8),%esi
+ movl %esi,24(%esp)
+ movl -128(%ebp),%edi
+ movl -96(%ebp),%esi
+ movl -64(%ebp),%edi
+ movl -32(%ebp),%esi
+ movl (%ebp),%edi
+ movl 32(%ebp),%esi
+ movl 64(%ebp),%edi
+ movl 96(%ebp),%esi
+.align 4,0x90
+L006loop:
+ movl %eax,%esi
+ andl $255,%esi
+ movzbl -128(%ebp,%esi,1),%esi
+ movzbl %dh,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $8,%edi
+ xorl %edi,%esi
+ movl %ecx,%edi
+ shrl $16,%edi
+ andl $255,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $16,%edi
+ xorl %edi,%esi
+ movl %ebx,%edi
+ shrl $24,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $24,%edi
+ xorl %edi,%esi
+ movl %esi,4(%esp)
+ movl %ebx,%esi
+ andl $255,%esi
+ movzbl -128(%ebp,%esi,1),%esi
+ movzbl %ah,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $8,%edi
+ xorl %edi,%esi
+ movl %edx,%edi
+ shrl $16,%edi
+ andl $255,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $16,%edi
+ xorl %edi,%esi
+ movl %ecx,%edi
+ shrl $24,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $24,%edi
+ xorl %edi,%esi
+ movl %esi,8(%esp)
+ movl %ecx,%esi
+ andl $255,%esi
+ movzbl -128(%ebp,%esi,1),%esi
+ movzbl %bh,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $8,%edi
+ xorl %edi,%esi
+ movl %eax,%edi
+ shrl $16,%edi
+ andl $255,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $16,%edi
+ xorl %edi,%esi
+ movl %edx,%edi
+ shrl $24,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $24,%edi
+ xorl %edi,%esi
+ andl $255,%edx
+ movzbl -128(%ebp,%edx,1),%edx
+ movzbl %ch,%ecx
+ movzbl -128(%ebp,%ecx,1),%ecx
+ shll $8,%ecx
+ xorl %ecx,%edx
+ movl %esi,%ecx
+ shrl $16,%ebx
+ andl $255,%ebx
+ movzbl -128(%ebp,%ebx,1),%ebx
+ shll $16,%ebx
+ xorl %ebx,%edx
+ shrl $24,%eax
+ movzbl -128(%ebp,%eax,1),%eax
+ shll $24,%eax
+ xorl %eax,%edx
+ movl $2155905152,%edi
+ andl %ecx,%edi
+ movl %edi,%esi
+ shrl $7,%edi
+ leal (%ecx,%ecx,1),%eax
+ subl %edi,%esi
+ andl $4278124286,%eax
+ andl $454761243,%esi
+ xorl %esi,%eax
+ movl $2155905152,%edi
+ andl %eax,%edi
+ movl %edi,%esi
+ shrl $7,%edi
+ leal (%eax,%eax,1),%ebx
+ subl %edi,%esi
+ andl $4278124286,%ebx
+ andl $454761243,%esi
+ xorl %ecx,%eax
+ xorl %esi,%ebx
+ movl $2155905152,%edi
+ andl %ebx,%edi
+ movl %edi,%esi
+ shrl $7,%edi
+ leal (%ebx,%ebx,1),%ebp
+ subl %edi,%esi
+ andl $4278124286,%ebp
+ andl $454761243,%esi
+ xorl %ecx,%ebx
+ roll $8,%ecx
+ xorl %esi,%ebp
+ xorl %eax,%ecx
+ xorl %ebp,%eax
+ xorl %ebx,%ecx
+ xorl %ebp,%ebx
+ roll $24,%eax
+ xorl %ebp,%ecx
+ roll $16,%ebx
+ xorl %eax,%ecx
+ roll $8,%ebp
+ xorl %ebx,%ecx
+ movl 4(%esp),%eax
+ xorl %ebp,%ecx
+ movl %ecx,12(%esp)
+ movl $2155905152,%edi
+ andl %edx,%edi
+ movl %edi,%esi
+ shrl $7,%edi
+ leal (%edx,%edx,1),%ebx
+ subl %edi,%esi
+ andl $4278124286,%ebx
+ andl $454761243,%esi
+ xorl %esi,%ebx
+ movl $2155905152,%edi
+ andl %ebx,%edi
+ movl %edi,%esi
+ shrl $7,%edi
+ leal (%ebx,%ebx,1),%ecx
+ subl %edi,%esi
+ andl $4278124286,%ecx
+ andl $454761243,%esi
+ xorl %edx,%ebx
+ xorl %esi,%ecx
+ movl $2155905152,%edi
+ andl %ecx,%edi
+ movl %edi,%esi
+ shrl $7,%edi
+ leal (%ecx,%ecx,1),%ebp
+ subl %edi,%esi
+ andl $4278124286,%ebp
+ andl $454761243,%esi
+ xorl %edx,%ecx
+ roll $8,%edx
+ xorl %esi,%ebp
+ xorl %ebx,%edx
+ xorl %ebp,%ebx
+ xorl %ecx,%edx
+ xorl %ebp,%ecx
+ roll $24,%ebx
+ xorl %ebp,%edx
+ roll $16,%ecx
+ xorl %ebx,%edx
+ roll $8,%ebp
+ xorl %ecx,%edx
+ movl 8(%esp),%ebx
+ xorl %ebp,%edx
+ movl %edx,16(%esp)
+ movl $2155905152,%edi
+ andl %eax,%edi
+ movl %edi,%esi
+ shrl $7,%edi
+ leal (%eax,%eax,1),%ecx
+ subl %edi,%esi
+ andl $4278124286,%ecx
+ andl $454761243,%esi
+ xorl %esi,%ecx
+ movl $2155905152,%edi
+ andl %ecx,%edi
+ movl %edi,%esi
+ shrl $7,%edi
+ leal (%ecx,%ecx,1),%edx
+ subl %edi,%esi
+ andl $4278124286,%edx
+ andl $454761243,%esi
+ xorl %eax,%ecx
+ xorl %esi,%edx
+ movl $2155905152,%edi
+ andl %edx,%edi
+ movl %edi,%esi
+ shrl $7,%edi
+ leal (%edx,%edx,1),%ebp
+ subl %edi,%esi
+ andl $4278124286,%ebp
+ andl $454761243,%esi
+ xorl %eax,%edx
+ roll $8,%eax
+ xorl %esi,%ebp
+ xorl %ecx,%eax
+ xorl %ebp,%ecx
+ xorl %edx,%eax
+ xorl %ebp,%edx
+ roll $24,%ecx
+ xorl %ebp,%eax
+ roll $16,%edx
+ xorl %ecx,%eax
+ roll $8,%ebp
+ xorl %edx,%eax
+ xorl %ebp,%eax
+ movl $2155905152,%edi
+ andl %ebx,%edi
+ movl %edi,%esi
+ shrl $7,%edi
+ leal (%ebx,%ebx,1),%ecx
+ subl %edi,%esi
+ andl $4278124286,%ecx
+ andl $454761243,%esi
+ xorl %esi,%ecx
+ movl $2155905152,%edi
+ andl %ecx,%edi
+ movl %edi,%esi
+ shrl $7,%edi
+ leal (%ecx,%ecx,1),%edx
+ subl %edi,%esi
+ andl $4278124286,%edx
+ andl $454761243,%esi
+ xorl %ebx,%ecx
+ xorl %esi,%edx
+ movl $2155905152,%edi
+ andl %edx,%edi
+ movl %edi,%esi
+ shrl $7,%edi
+ leal (%edx,%edx,1),%ebp
+ subl %edi,%esi
+ andl $4278124286,%ebp
+ andl $454761243,%esi
+ xorl %ebx,%edx
+ roll $8,%ebx
+ xorl %esi,%ebp
+ xorl %ecx,%ebx
+ xorl %ebp,%ecx
+ xorl %edx,%ebx
+ xorl %ebp,%edx
+ roll $24,%ecx
+ xorl %ebp,%ebx
+ roll $16,%edx
+ xorl %ecx,%ebx
+ roll $8,%ebp
+ xorl %edx,%ebx
+ movl 12(%esp),%ecx
+ xorl %ebp,%ebx
+ movl 16(%esp),%edx
+ movl 20(%esp),%edi
+ movl 28(%esp),%ebp
+ addl $16,%edi
+ xorl (%edi),%eax
+ xorl 4(%edi),%ebx
+ xorl 8(%edi),%ecx
+ xorl 12(%edi),%edx
+ cmpl 24(%esp),%edi
+ movl %edi,20(%esp)
+ jb L006loop
+ movl %eax,%esi
+ andl $255,%esi
+ movzbl -128(%ebp,%esi,1),%esi
+ movzbl %dh,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $8,%edi
+ xorl %edi,%esi
+ movl %ecx,%edi
+ shrl $16,%edi
+ andl $255,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $16,%edi
+ xorl %edi,%esi
+ movl %ebx,%edi
+ shrl $24,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $24,%edi
+ xorl %edi,%esi
+ movl %esi,4(%esp)
+ movl %ebx,%esi
+ andl $255,%esi
+ movzbl -128(%ebp,%esi,1),%esi
+ movzbl %ah,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $8,%edi
+ xorl %edi,%esi
+ movl %edx,%edi
+ shrl $16,%edi
+ andl $255,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $16,%edi
+ xorl %edi,%esi
+ movl %ecx,%edi
+ shrl $24,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $24,%edi
+ xorl %edi,%esi
+ movl %esi,8(%esp)
+ movl %ecx,%esi
+ andl $255,%esi
+ movzbl -128(%ebp,%esi,1),%esi
+ movzbl %bh,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $8,%edi
+ xorl %edi,%esi
+ movl %eax,%edi
+ shrl $16,%edi
+ andl $255,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $16,%edi
+ xorl %edi,%esi
+ movl %edx,%edi
+ shrl $24,%edi
+ movzbl -128(%ebp,%edi,1),%edi
+ shll $24,%edi
+ xorl %edi,%esi
+ movl 20(%esp),%edi
+ andl $255,%edx
+ movzbl -128(%ebp,%edx,1),%edx
+ movzbl %ch,%ecx
+ movzbl -128(%ebp,%ecx,1),%ecx
+ shll $8,%ecx
+ xorl %ecx,%edx
+ movl %esi,%ecx
+ shrl $16,%ebx
+ andl $255,%ebx
+ movzbl -128(%ebp,%ebx,1),%ebx
+ shll $16,%ebx
+ xorl %ebx,%edx
+ movl 8(%esp),%ebx
+ shrl $24,%eax
+ movzbl -128(%ebp,%eax,1),%eax
+ shll $24,%eax
+ xorl %eax,%edx
+ movl 4(%esp),%eax
+ xorl 16(%edi),%eax
+ xorl 20(%edi),%ebx
+ xorl 24(%edi),%ecx
+ xorl 28(%edi),%edx
+ ret
+.private_extern __sse_AES_decrypt_compact
+.align 4
+__sse_AES_decrypt_compact:
+ pxor (%edi),%mm0
+ pxor 8(%edi),%mm4
+ movl 240(%edi),%esi
+ leal -2(%esi,%esi,1),%esi
+ leal (%edi,%esi,8),%esi
+ movl %esi,24(%esp)
+ movl $454761243,%eax
+ movl %eax,8(%esp)
+ movl %eax,12(%esp)
+ movl -128(%ebp),%eax
+ movl -96(%ebp),%ebx
+ movl -64(%ebp),%ecx
+ movl -32(%ebp),%edx
+ movl (%ebp),%eax
+ movl 32(%ebp),%ebx
+ movl 64(%ebp),%ecx
+ movl 96(%ebp),%edx
+.align 4,0x90
+L007loop:
+ pshufw $12,%mm0,%mm1
+ pshufw $9,%mm4,%mm5
+ movd %mm1,%eax
+ movd %mm5,%ebx
+ movl %edi,20(%esp)
+ movzbl %al,%esi
+ movzbl %ah,%edx
+ pshufw $6,%mm0,%mm2
+ movzbl -128(%ebp,%esi,1),%ecx
+ movzbl %bl,%edi
+ movzbl -128(%ebp,%edx,1),%edx
+ shrl $16,%eax
+ shll $8,%edx
+ movzbl -128(%ebp,%edi,1),%esi
+ movzbl %bh,%edi
+ shll $16,%esi
+ pshufw $3,%mm4,%mm6
+ orl %esi,%ecx
+ movzbl -128(%ebp,%edi,1),%esi
+ movzbl %ah,%edi
+ shll $24,%esi
+ shrl $16,%ebx
+ orl %esi,%edx
+ movzbl -128(%ebp,%edi,1),%esi
+ movzbl %bh,%edi
+ shll $24,%esi
+ orl %esi,%ecx
+ movzbl -128(%ebp,%edi,1),%esi
+ movzbl %al,%edi
+ shll $8,%esi
+ movd %mm2,%eax
+ orl %esi,%ecx
+ movzbl -128(%ebp,%edi,1),%esi
+ movzbl %bl,%edi
+ shll $16,%esi
+ movd %mm6,%ebx
+ movd %ecx,%mm0
+ movzbl -128(%ebp,%edi,1),%ecx
+ movzbl %al,%edi
+ orl %esi,%ecx
+ movzbl -128(%ebp,%edi,1),%esi
+ movzbl %bl,%edi
+ orl %esi,%edx
+ movzbl -128(%ebp,%edi,1),%esi
+ movzbl %ah,%edi
+ shll $16,%esi
+ shrl $16,%eax
+ orl %esi,%edx
+ movzbl -128(%ebp,%edi,1),%esi
+ movzbl %bh,%edi
+ shrl $16,%ebx
+ shll $8,%esi
+ movd %edx,%mm1
+ movzbl -128(%ebp,%edi,1),%edx
+ movzbl %bh,%edi
+ shll $24,%edx
+ andl $255,%ebx
+ orl %esi,%edx
+ punpckldq %mm1,%mm0
+ movzbl -128(%ebp,%edi,1),%esi
+ movzbl %al,%edi
+ shll $8,%esi
+ movzbl %ah,%eax
+ movzbl -128(%ebp,%ebx,1),%ebx
+ orl %esi,%ecx
+ movzbl -128(%ebp,%edi,1),%esi
+ orl %ebx,%edx
+ shll $16,%esi
+ movzbl -128(%ebp,%eax,1),%eax
+ orl %esi,%edx
+ shll $24,%eax
+ orl %eax,%ecx
+ movl 20(%esp),%edi
+ movd %edx,%mm4
+ movd %ecx,%mm5
+ punpckldq %mm5,%mm4
+ addl $16,%edi
+ cmpl 24(%esp),%edi
+ ja L008out
+ movq %mm0,%mm3
+ movq %mm4,%mm7
+ pshufw $228,%mm0,%mm2
+ pshufw $228,%mm4,%mm6
+ movq %mm0,%mm1
+ movq %mm4,%mm5
+ pshufw $177,%mm0,%mm0
+ pshufw $177,%mm4,%mm4
+ pslld $8,%mm2
+ pslld $8,%mm6
+ psrld $8,%mm3
+ psrld $8,%mm7
+ pxor %mm2,%mm0
+ pxor %mm6,%mm4
+ pxor %mm3,%mm0
+ pxor %mm7,%mm4
+ pslld $16,%mm2
+ pslld $16,%mm6
+ psrld $16,%mm3
+ psrld $16,%mm7
+ pxor %mm2,%mm0
+ pxor %mm6,%mm4
+ pxor %mm3,%mm0
+ pxor %mm7,%mm4
+ movq 8(%esp),%mm3
+ pxor %mm2,%mm2
+ pxor %mm6,%mm6
+ pcmpgtb %mm1,%mm2
+ pcmpgtb %mm5,%mm6
+ pand %mm3,%mm2
+ pand %mm3,%mm6
+ paddb %mm1,%mm1
+ paddb %mm5,%mm5
+ pxor %mm2,%mm1
+ pxor %mm6,%mm5
+ movq %mm1,%mm3
+ movq %mm5,%mm7
+ movq %mm1,%mm2
+ movq %mm5,%mm6
+ pxor %mm1,%mm0
+ pxor %mm5,%mm4
+ pslld $24,%mm3
+ pslld $24,%mm7
+ psrld $8,%mm2
+ psrld $8,%mm6
+ pxor %mm3,%mm0
+ pxor %mm7,%mm4
+ pxor %mm2,%mm0
+ pxor %mm6,%mm4
+ movq 8(%esp),%mm2
+ pxor %mm3,%mm3
+ pxor %mm7,%mm7
+ pcmpgtb %mm1,%mm3
+ pcmpgtb %mm5,%mm7
+ pand %mm2,%mm3
+ pand %mm2,%mm7
+ paddb %mm1,%mm1
+ paddb %mm5,%mm5
+ pxor %mm3,%mm1
+ pxor %mm7,%mm5
+ pshufw $177,%mm1,%mm3
+ pshufw $177,%mm5,%mm7
+ pxor %mm1,%mm0
+ pxor %mm5,%mm4
+ pxor %mm3,%mm0
+ pxor %mm7,%mm4
+ pxor %mm3,%mm3
+ pxor %mm7,%mm7
+ pcmpgtb %mm1,%mm3
+ pcmpgtb %mm5,%mm7
+ pand %mm2,%mm3
+ pand %mm2,%mm7
+ paddb %mm1,%mm1
+ paddb %mm5,%mm5
+ pxor %mm3,%mm1
+ pxor %mm7,%mm5
+ pxor %mm1,%mm0
+ pxor %mm5,%mm4
+ movq %mm1,%mm3
+ movq %mm5,%mm7
+ pshufw $177,%mm1,%mm2
+ pshufw $177,%mm5,%mm6
+ pxor %mm2,%mm0
+ pxor %mm6,%mm4
+ pslld $8,%mm1
+ pslld $8,%mm5
+ psrld $8,%mm3
+ psrld $8,%mm7
+ movq (%edi),%mm2
+ movq 8(%edi),%mm6
+ pxor %mm1,%mm0
+ pxor %mm5,%mm4
+ pxor %mm3,%mm0
+ pxor %mm7,%mm4
+ movl -128(%ebp),%eax
+ pslld $16,%mm1
+ pslld $16,%mm5
+ movl -64(%ebp),%ebx
+ psrld $16,%mm3
+ psrld $16,%mm7
+ movl (%ebp),%ecx
+ pxor %mm1,%mm0
+ pxor %mm5,%mm4
+ movl 64(%ebp),%edx
+ pxor %mm3,%mm0
+ pxor %mm7,%mm4
+ pxor %mm2,%mm0
+ pxor %mm6,%mm4
+ jmp L007loop
+.align 4,0x90
+L008out:
+ pxor (%edi),%mm0
+ pxor 8(%edi),%mm4
+ ret
+.private_extern __x86_AES_decrypt
+.align 4
+__x86_AES_decrypt:
+ movl %edi,20(%esp)
+ xorl (%edi),%eax
+ xorl 4(%edi),%ebx
+ xorl 8(%edi),%ecx
+ xorl 12(%edi),%edx
+ movl 240(%edi),%esi
+ leal -2(%esi,%esi,1),%esi
+ leal (%edi,%esi,8),%esi
+ movl %esi,24(%esp)
+.align 4,0x90
+L009loop:
+ movl %eax,%esi
+ andl $255,%esi
+ movl (%ebp,%esi,8),%esi
+ movzbl %dh,%edi
+ xorl 3(%ebp,%edi,8),%esi
+ movl %ecx,%edi
+ shrl $16,%edi
+ andl $255,%edi
+ xorl 2(%ebp,%edi,8),%esi
+ movl %ebx,%edi
+ shrl $24,%edi
+ xorl 1(%ebp,%edi,8),%esi
+ movl %esi,4(%esp)
+ movl %ebx,%esi
+ andl $255,%esi
+ movl (%ebp,%esi,8),%esi
+ movzbl %ah,%edi
+ xorl 3(%ebp,%edi,8),%esi
+ movl %edx,%edi
+ shrl $16,%edi
+ andl $255,%edi
+ xorl 2(%ebp,%edi,8),%esi
+ movl %ecx,%edi
+ shrl $24,%edi
+ xorl 1(%ebp,%edi,8),%esi
+ movl %esi,8(%esp)
+ movl %ecx,%esi
+ andl $255,%esi
+ movl (%ebp,%esi,8),%esi
+ movzbl %bh,%edi
+ xorl 3(%ebp,%edi,8),%esi
+ movl %eax,%edi
+ shrl $16,%edi
+ andl $255,%edi
+ xorl 2(%ebp,%edi,8),%esi
+ movl %edx,%edi
+ shrl $24,%edi
+ xorl 1(%ebp,%edi,8),%esi
+ movl 20(%esp),%edi
+ andl $255,%edx
+ movl (%ebp,%edx,8),%edx
+ movzbl %ch,%ecx
+ xorl 3(%ebp,%ecx,8),%edx
+ movl %esi,%ecx
+ shrl $16,%ebx
+ andl $255,%ebx
+ xorl 2(%ebp,%ebx,8),%edx
+ movl 8(%esp),%ebx
+ shrl $24,%eax
+ xorl 1(%ebp,%eax,8),%edx
+ movl 4(%esp),%eax
+ addl $16,%edi
+ xorl (%edi),%eax
+ xorl 4(%edi),%ebx
+ xorl 8(%edi),%ecx
+ xorl 12(%edi),%edx
+ cmpl 24(%esp),%edi
+ movl %edi,20(%esp)
+ jb L009loop
+ leal 2176(%ebp),%ebp
+ movl -128(%ebp),%edi
+ movl -96(%ebp),%esi
+ movl -64(%ebp),%edi
+ movl -32(%ebp),%esi
+ movl (%ebp),%edi
+ movl 32(%ebp),%esi
+ movl 64(%ebp),%edi
+ movl 96(%ebp),%esi
+ leal -128(%ebp),%ebp
+ movl %eax,%esi
+ andl $255,%esi
+ movzbl (%ebp,%esi,1),%esi
+ movzbl %dh,%edi
+ movzbl (%ebp,%edi,1),%edi
+ shll $8,%edi
+ xorl %edi,%esi
+ movl %ecx,%edi
+ shrl $16,%edi
+ andl $255,%edi
+ movzbl (%ebp,%edi,1),%edi
+ shll $16,%edi
+ xorl %edi,%esi
+ movl %ebx,%edi
+ shrl $24,%edi
+ movzbl (%ebp,%edi,1),%edi
+ shll $24,%edi
+ xorl %edi,%esi
+ movl %esi,4(%esp)
+ movl %ebx,%esi
+ andl $255,%esi
+ movzbl (%ebp,%esi,1),%esi
+ movzbl %ah,%edi
+ movzbl (%ebp,%edi,1),%edi
+ shll $8,%edi
+ xorl %edi,%esi
+ movl %edx,%edi
+ shrl $16,%edi
+ andl $255,%edi
+ movzbl (%ebp,%edi,1),%edi
+ shll $16,%edi
+ xorl %edi,%esi
+ movl %ecx,%edi
+ shrl $24,%edi
+ movzbl (%ebp,%edi,1),%edi
+ shll $24,%edi
+ xorl %edi,%esi
+ movl %esi,8(%esp)
+ movl %ecx,%esi
+ andl $255,%esi
+ movzbl (%ebp,%esi,1),%esi
+ movzbl %bh,%edi
+ movzbl (%ebp,%edi,1),%edi
+ shll $8,%edi
+ xorl %edi,%esi
+ movl %eax,%edi
+ shrl $16,%edi
+ andl $255,%edi
+ movzbl (%ebp,%edi,1),%edi
+ shll $16,%edi
+ xorl %edi,%esi
+ movl %edx,%edi
+ shrl $24,%edi
+ movzbl (%ebp,%edi,1),%edi
+ shll $24,%edi
+ xorl %edi,%esi
+ movl 20(%esp),%edi
+ andl $255,%edx
+ movzbl (%ebp,%edx,1),%edx
+ movzbl %ch,%ecx
+ movzbl (%ebp,%ecx,1),%ecx
+ shll $8,%ecx
+ xorl %ecx,%edx
+ movl %esi,%ecx
+ shrl $16,%ebx
+ andl $255,%ebx
+ movzbl (%ebp,%ebx,1),%ebx
+ shll $16,%ebx
+ xorl %ebx,%edx
+ movl 8(%esp),%ebx
+ shrl $24,%eax
+ movzbl (%ebp,%eax,1),%eax
+ shll $24,%eax
+ xorl %eax,%edx
+ movl 4(%esp),%eax
+ leal -2048(%ebp),%ebp
+ addl $16,%edi
+ xorl (%edi),%eax
+ xorl 4(%edi),%ebx
+ xorl 8(%edi),%ecx
+ xorl 12(%edi),%edx
+ ret
+.align 6,0x90
+LAES_Td:
+.long 1353184337,1353184337
+.long 1399144830,1399144830
+.long 3282310938,3282310938
+.long 2522752826,2522752826
+.long 3412831035,3412831035
+.long 4047871263,4047871263
+.long 2874735276,2874735276
+.long 2466505547,2466505547
+.long 1442459680,1442459680
+.long 4134368941,4134368941
+.long 2440481928,2440481928
+.long 625738485,625738485
+.long 4242007375,4242007375
+.long 3620416197,3620416197
+.long 2151953702,2151953702
+.long 2409849525,2409849525
+.long 1230680542,1230680542
+.long 1729870373,1729870373
+.long 2551114309,2551114309
+.long 3787521629,3787521629
+.long 41234371,41234371
+.long 317738113,317738113
+.long 2744600205,2744600205
+.long 3338261355,3338261355
+.long 3881799427,3881799427
+.long 2510066197,2510066197
+.long 3950669247,3950669247
+.long 3663286933,3663286933
+.long 763608788,763608788
+.long 3542185048,3542185048
+.long 694804553,694804553
+.long 1154009486,1154009486
+.long 1787413109,1787413109
+.long 2021232372,2021232372
+.long 1799248025,1799248025
+.long 3715217703,3715217703
+.long 3058688446,3058688446
+.long 397248752,397248752
+.long 1722556617,1722556617
+.long 3023752829,3023752829
+.long 407560035,407560035
+.long 2184256229,2184256229
+.long 1613975959,1613975959
+.long 1165972322,1165972322
+.long 3765920945,3765920945
+.long 2226023355,2226023355
+.long 480281086,480281086
+.long 2485848313,2485848313
+.long 1483229296,1483229296
+.long 436028815,436028815
+.long 2272059028,2272059028
+.long 3086515026,3086515026
+.long 601060267,601060267
+.long 3791801202,3791801202
+.long 1468997603,1468997603
+.long 715871590,715871590
+.long 120122290,120122290
+.long 63092015,63092015
+.long 2591802758,2591802758
+.long 2768779219,2768779219
+.long 4068943920,4068943920
+.long 2997206819,2997206819
+.long 3127509762,3127509762
+.long 1552029421,1552029421
+.long 723308426,723308426
+.long 2461301159,2461301159
+.long 4042393587,4042393587
+.long 2715969870,2715969870
+.long 3455375973,3455375973
+.long 3586000134,3586000134
+.long 526529745,526529745
+.long 2331944644,2331944644
+.long 2639474228,2639474228
+.long 2689987490,2689987490
+.long 853641733,853641733
+.long 1978398372,1978398372
+.long 971801355,971801355
+.long 2867814464,2867814464
+.long 111112542,111112542
+.long 1360031421,1360031421
+.long 4186579262,4186579262
+.long 1023860118,1023860118
+.long 2919579357,2919579357
+.long 1186850381,1186850381
+.long 3045938321,3045938321
+.long 90031217,90031217
+.long 1876166148,1876166148
+.long 4279586912,4279586912
+.long 620468249,620468249
+.long 2548678102,2548678102
+.long 3426959497,3426959497
+.long 2006899047,2006899047
+.long 3175278768,3175278768
+.long 2290845959,2290845959
+.long 945494503,945494503
+.long 3689859193,3689859193
+.long 1191869601,1191869601
+.long 3910091388,3910091388
+.long 3374220536,3374220536
+.long 0,0
+.long 2206629897,2206629897
+.long 1223502642,1223502642
+.long 2893025566,2893025566
+.long 1316117100,1316117100
+.long 4227796733,4227796733
+.long 1446544655,1446544655
+.long 517320253,517320253
+.long 658058550,658058550
+.long 1691946762,1691946762
+.long 564550760,564550760
+.long 3511966619,3511966619
+.long 976107044,976107044
+.long 2976320012,2976320012
+.long 266819475,266819475
+.long 3533106868,3533106868
+.long 2660342555,2660342555
+.long 1338359936,1338359936
+.long 2720062561,2720062561
+.long 1766553434,1766553434
+.long 370807324,370807324
+.long 179999714,179999714
+.long 3844776128,3844776128
+.long 1138762300,1138762300
+.long 488053522,488053522
+.long 185403662,185403662
+.long 2915535858,2915535858
+.long 3114841645,3114841645
+.long 3366526484,3366526484
+.long 2233069911,2233069911
+.long 1275557295,1275557295
+.long 3151862254,3151862254
+.long 4250959779,4250959779
+.long 2670068215,2670068215
+.long 3170202204,3170202204
+.long 3309004356,3309004356
+.long 880737115,880737115
+.long 1982415755,1982415755
+.long 3703972811,3703972811
+.long 1761406390,1761406390
+.long 1676797112,1676797112
+.long 3403428311,3403428311
+.long 277177154,277177154
+.long 1076008723,1076008723
+.long 538035844,538035844
+.long 2099530373,2099530373
+.long 4164795346,4164795346
+.long 288553390,288553390
+.long 1839278535,1839278535
+.long 1261411869,1261411869
+.long 4080055004,4080055004
+.long 3964831245,3964831245
+.long 3504587127,3504587127
+.long 1813426987,1813426987
+.long 2579067049,2579067049
+.long 4199060497,4199060497
+.long 577038663,577038663
+.long 3297574056,3297574056
+.long 440397984,440397984
+.long 3626794326,3626794326
+.long 4019204898,4019204898
+.long 3343796615,3343796615
+.long 3251714265,3251714265
+.long 4272081548,4272081548
+.long 906744984,906744984
+.long 3481400742,3481400742
+.long 685669029,685669029
+.long 646887386,646887386
+.long 2764025151,2764025151
+.long 3835509292,3835509292
+.long 227702864,227702864
+.long 2613862250,2613862250
+.long 1648787028,1648787028
+.long 3256061430,3256061430
+.long 3904428176,3904428176
+.long 1593260334,1593260334
+.long 4121936770,4121936770
+.long 3196083615,3196083615
+.long 2090061929,2090061929
+.long 2838353263,2838353263
+.long 3004310991,3004310991
+.long 999926984,999926984
+.long 2809993232,2809993232
+.long 1852021992,1852021992
+.long 2075868123,2075868123
+.long 158869197,158869197
+.long 4095236462,4095236462
+.long 28809964,28809964
+.long 2828685187,2828685187
+.long 1701746150,1701746150
+.long 2129067946,2129067946
+.long 147831841,147831841
+.long 3873969647,3873969647
+.long 3650873274,3650873274
+.long 3459673930,3459673930
+.long 3557400554,3557400554
+.long 3598495785,3598495785
+.long 2947720241,2947720241
+.long 824393514,824393514
+.long 815048134,815048134
+.long 3227951669,3227951669
+.long 935087732,935087732
+.long 2798289660,2798289660
+.long 2966458592,2966458592
+.long 366520115,366520115
+.long 1251476721,1251476721
+.long 4158319681,4158319681
+.long 240176511,240176511
+.long 804688151,804688151
+.long 2379631990,2379631990
+.long 1303441219,1303441219
+.long 1414376140,1414376140
+.long 3741619940,3741619940
+.long 3820343710,3820343710
+.long 461924940,461924940
+.long 3089050817,3089050817
+.long 2136040774,2136040774
+.long 82468509,82468509
+.long 1563790337,1563790337
+.long 1937016826,1937016826
+.long 776014843,776014843
+.long 1511876531,1511876531
+.long 1389550482,1389550482
+.long 861278441,861278441
+.long 323475053,323475053
+.long 2355222426,2355222426
+.long 2047648055,2047648055
+.long 2383738969,2383738969
+.long 2302415851,2302415851
+.long 3995576782,3995576782
+.long 902390199,902390199
+.long 3991215329,3991215329
+.long 1018251130,1018251130
+.long 1507840668,1507840668
+.long 1064563285,1064563285
+.long 2043548696,2043548696
+.long 3208103795,3208103795
+.long 3939366739,3939366739
+.long 1537932639,1537932639
+.long 342834655,342834655
+.long 2262516856,2262516856
+.long 2180231114,2180231114
+.long 1053059257,1053059257
+.long 741614648,741614648
+.long 1598071746,1598071746
+.long 1925389590,1925389590
+.long 203809468,203809468
+.long 2336832552,2336832552
+.long 1100287487,1100287487
+.long 1895934009,1895934009
+.long 3736275976,3736275976
+.long 2632234200,2632234200
+.long 2428589668,2428589668
+.long 1636092795,1636092795
+.long 1890988757,1890988757
+.long 1952214088,1952214088
+.long 1113045200,1113045200
+.byte 82,9,106,213,48,54,165,56
+.byte 191,64,163,158,129,243,215,251
+.byte 124,227,57,130,155,47,255,135
+.byte 52,142,67,68,196,222,233,203
+.byte 84,123,148,50,166,194,35,61
+.byte 238,76,149,11,66,250,195,78
+.byte 8,46,161,102,40,217,36,178
+.byte 118,91,162,73,109,139,209,37
+.byte 114,248,246,100,134,104,152,22
+.byte 212,164,92,204,93,101,182,146
+.byte 108,112,72,80,253,237,185,218
+.byte 94,21,70,87,167,141,157,132
+.byte 144,216,171,0,140,188,211,10
+.byte 247,228,88,5,184,179,69,6
+.byte 208,44,30,143,202,63,15,2
+.byte 193,175,189,3,1,19,138,107
+.byte 58,145,17,65,79,103,220,234
+.byte 151,242,207,206,240,180,230,115
+.byte 150,172,116,34,231,173,53,133
+.byte 226,249,55,232,28,117,223,110
+.byte 71,241,26,113,29,41,197,137
+.byte 111,183,98,14,170,24,190,27
+.byte 252,86,62,75,198,210,121,32
+.byte 154,219,192,254,120,205,90,244
+.byte 31,221,168,51,136,7,199,49
+.byte 177,18,16,89,39,128,236,95
+.byte 96,81,127,169,25,181,74,13
+.byte 45,229,122,159,147,201,156,239
+.byte 160,224,59,77,174,42,245,176
+.byte 200,235,187,60,131,83,153,97
+.byte 23,43,4,126,186,119,214,38
+.byte 225,105,20,99,85,33,12,125
+.byte 82,9,106,213,48,54,165,56
+.byte 191,64,163,158,129,243,215,251
+.byte 124,227,57,130,155,47,255,135
+.byte 52,142,67,68,196,222,233,203
+.byte 84,123,148,50,166,194,35,61
+.byte 238,76,149,11,66,250,195,78
+.byte 8,46,161,102,40,217,36,178
+.byte 118,91,162,73,109,139,209,37
+.byte 114,248,246,100,134,104,152,22
+.byte 212,164,92,204,93,101,182,146
+.byte 108,112,72,80,253,237,185,218
+.byte 94,21,70,87,167,141,157,132
+.byte 144,216,171,0,140,188,211,10
+.byte 247,228,88,5,184,179,69,6
+.byte 208,44,30,143,202,63,15,2
+.byte 193,175,189,3,1,19,138,107
+.byte 58,145,17,65,79,103,220,234
+.byte 151,242,207,206,240,180,230,115
+.byte 150,172,116,34,231,173,53,133
+.byte 226,249,55,232,28,117,223,110
+.byte 71,241,26,113,29,41,197,137
+.byte 111,183,98,14,170,24,190,27
+.byte 252,86,62,75,198,210,121,32
+.byte 154,219,192,254,120,205,90,244
+.byte 31,221,168,51,136,7,199,49
+.byte 177,18,16,89,39,128,236,95
+.byte 96,81,127,169,25,181,74,13
+.byte 45,229,122,159,147,201,156,239
+.byte 160,224,59,77,174,42,245,176
+.byte 200,235,187,60,131,83,153,97
+.byte 23,43,4,126,186,119,214,38
+.byte 225,105,20,99,85,33,12,125
+.byte 82,9,106,213,48,54,165,56
+.byte 191,64,163,158,129,243,215,251
+.byte 124,227,57,130,155,47,255,135
+.byte 52,142,67,68,196,222,233,203
+.byte 84,123,148,50,166,194,35,61
+.byte 238,76,149,11,66,250,195,78
+.byte 8,46,161,102,40,217,36,178
+.byte 118,91,162,73,109,139,209,37
+.byte 114,248,246,100,134,104,152,22
+.byte 212,164,92,204,93,101,182,146
+.byte 108,112,72,80,253,237,185,218
+.byte 94,21,70,87,167,141,157,132
+.byte 144,216,171,0,140,188,211,10
+.byte 247,228,88,5,184,179,69,6
+.byte 208,44,30,143,202,63,15,2
+.byte 193,175,189,3,1,19,138,107
+.byte 58,145,17,65,79,103,220,234
+.byte 151,242,207,206,240,180,230,115
+.byte 150,172,116,34,231,173,53,133
+.byte 226,249,55,232,28,117,223,110
+.byte 71,241,26,113,29,41,197,137
+.byte 111,183,98,14,170,24,190,27
+.byte 252,86,62,75,198,210,121,32
+.byte 154,219,192,254,120,205,90,244
+.byte 31,221,168,51,136,7,199,49
+.byte 177,18,16,89,39,128,236,95
+.byte 96,81,127,169,25,181,74,13
+.byte 45,229,122,159,147,201,156,239
+.byte 160,224,59,77,174,42,245,176
+.byte 200,235,187,60,131,83,153,97
+.byte 23,43,4,126,186,119,214,38
+.byte 225,105,20,99,85,33,12,125
+.byte 82,9,106,213,48,54,165,56
+.byte 191,64,163,158,129,243,215,251
+.byte 124,227,57,130,155,47,255,135
+.byte 52,142,67,68,196,222,233,203
+.byte 84,123,148,50,166,194,35,61
+.byte 238,76,149,11,66,250,195,78
+.byte 8,46,161,102,40,217,36,178
+.byte 118,91,162,73,109,139,209,37
+.byte 114,248,246,100,134,104,152,22
+.byte 212,164,92,204,93,101,182,146
+.byte 108,112,72,80,253,237,185,218
+.byte 94,21,70,87,167,141,157,132
+.byte 144,216,171,0,140,188,211,10
+.byte 247,228,88,5,184,179,69,6
+.byte 208,44,30,143,202,63,15,2
+.byte 193,175,189,3,1,19,138,107
+.byte 58,145,17,65,79,103,220,234
+.byte 151,242,207,206,240,180,230,115
+.byte 150,172,116,34,231,173,53,133
+.byte 226,249,55,232,28,117,223,110
+.byte 71,241,26,113,29,41,197,137
+.byte 111,183,98,14,170,24,190,27
+.byte 252,86,62,75,198,210,121,32
+.byte 154,219,192,254,120,205,90,244
+.byte 31,221,168,51,136,7,199,49
+.byte 177,18,16,89,39,128,236,95
+.byte 96,81,127,169,25,181,74,13
+.byte 45,229,122,159,147,201,156,239
+.byte 160,224,59,77,174,42,245,176
+.byte 200,235,187,60,131,83,153,97
+.byte 23,43,4,126,186,119,214,38
+.byte 225,105,20,99,85,33,12,125
+.globl _asm_AES_decrypt
+.private_extern _asm_AES_decrypt
+.align 4
+_asm_AES_decrypt:
+L_asm_AES_decrypt_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ movl 20(%esp),%esi
+ movl 28(%esp),%edi
+ movl %esp,%eax
+ subl $36,%esp
+ andl $-64,%esp
+ leal -127(%edi),%ebx
+ subl %esp,%ebx
+ negl %ebx
+ andl $960,%ebx
+ subl %ebx,%esp
+ addl $4,%esp
+ movl %eax,28(%esp)
+ call L010pic_point
+L010pic_point:
+ popl %ebp
+ movl L_OPENSSL_ia32cap_P$non_lazy_ptr-L010pic_point(%ebp),%eax
+ leal LAES_Td-L010pic_point(%ebp),%ebp
+ leal 764(%esp),%ebx
+ subl %ebp,%ebx
+ andl $768,%ebx
+ leal 2176(%ebp,%ebx,1),%ebp
+ btl $25,(%eax)
+ jnc L011x86
+ movq (%esi),%mm0
+ movq 8(%esi),%mm4
+ call __sse_AES_decrypt_compact
+ movl 28(%esp),%esp
+ movl 24(%esp),%esi
+ movq %mm0,(%esi)
+ movq %mm4,8(%esi)
+ emms
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.align 4,0x90
+L011x86:
+ movl %ebp,24(%esp)
+ movl (%esi),%eax
+ movl 4(%esi),%ebx
+ movl 8(%esi),%ecx
+ movl 12(%esi),%edx
+ call __x86_AES_decrypt_compact
+ movl 28(%esp),%esp
+ movl 24(%esp),%esi
+ movl %eax,(%esi)
+ movl %ebx,4(%esi)
+ movl %ecx,8(%esi)
+ movl %edx,12(%esi)
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.globl _asm_AES_cbc_encrypt
+.private_extern _asm_AES_cbc_encrypt
+.align 4
+_asm_AES_cbc_encrypt:
+L_asm_AES_cbc_encrypt_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ movl 28(%esp),%ecx
+ cmpl $0,%ecx
+ je L012drop_out
+ call L013pic_point
+L013pic_point:
+ popl %ebp
+ movl L_OPENSSL_ia32cap_P$non_lazy_ptr-L013pic_point(%ebp),%eax
+ cmpl $0,40(%esp)
+ leal LAES_Te-L013pic_point(%ebp),%ebp
+ jne L014picked_te
+ leal LAES_Td-LAES_Te(%ebp),%ebp
+L014picked_te:
+ pushfl
+ cld
+ cmpl $512,%ecx
+ jb L015slow_way
+ testl $15,%ecx
+ jnz L015slow_way
+ btl $28,(%eax)
+ jc L015slow_way
+ leal -324(%esp),%esi
+ andl $-64,%esi
+ movl %ebp,%eax
+ leal 2304(%ebp),%ebx
+ movl %esi,%edx
+ andl $4095,%eax
+ andl $4095,%ebx
+ andl $4095,%edx
+ cmpl %ebx,%edx
+ jb L016tbl_break_out
+ subl %ebx,%edx
+ subl %edx,%esi
+ jmp L017tbl_ok
+.align 2,0x90
+L016tbl_break_out:
+ subl %eax,%edx
+ andl $4095,%edx
+ addl $384,%edx
+ subl %edx,%esi
+.align 2,0x90
+L017tbl_ok:
+ leal 24(%esp),%edx
+ xchgl %esi,%esp
+ addl $4,%esp
+ movl %ebp,24(%esp)
+ movl %esi,28(%esp)
+ movl (%edx),%eax
+ movl 4(%edx),%ebx
+ movl 12(%edx),%edi
+ movl 16(%edx),%esi
+ movl 20(%edx),%edx
+ movl %eax,32(%esp)
+ movl %ebx,36(%esp)
+ movl %ecx,40(%esp)
+ movl %edi,44(%esp)
+ movl %esi,48(%esp)
+ movl $0,316(%esp)
+ movl %edi,%ebx
+ movl $61,%ecx
+ subl %ebp,%ebx
+ movl %edi,%esi
+ andl $4095,%ebx
+ leal 76(%esp),%edi
+ cmpl $2304,%ebx
+ jb L018do_copy
+ cmpl $3852,%ebx
+ jb L019skip_copy
+.align 2,0x90
+L018do_copy:
+ movl %edi,44(%esp)
+.long 2784229001
+L019skip_copy:
+ movl $16,%edi
+.align 2,0x90
+L020prefetch_tbl:
+ movl (%ebp),%eax
+ movl 32(%ebp),%ebx
+ movl 64(%ebp),%ecx
+ movl 96(%ebp),%esi
+ leal 128(%ebp),%ebp
+ subl $1,%edi
+ jnz L020prefetch_tbl
+ subl $2048,%ebp
+ movl 32(%esp),%esi
+ movl 48(%esp),%edi
+ cmpl $0,%edx
+ je L021fast_decrypt
+ movl (%edi),%eax
+ movl 4(%edi),%ebx
+.align 4,0x90
+L022fast_enc_loop:
+ movl 8(%edi),%ecx
+ movl 12(%edi),%edx
+ xorl (%esi),%eax
+ xorl 4(%esi),%ebx
+ xorl 8(%esi),%ecx
+ xorl 12(%esi),%edx
+ movl 44(%esp),%edi
+ call __x86_AES_encrypt
+ movl 32(%esp),%esi
+ movl 36(%esp),%edi
+ movl %eax,(%edi)
+ movl %ebx,4(%edi)
+ movl %ecx,8(%edi)
+ movl %edx,12(%edi)
+ leal 16(%esi),%esi
+ movl 40(%esp),%ecx
+ movl %esi,32(%esp)
+ leal 16(%edi),%edx
+ movl %edx,36(%esp)
+ subl $16,%ecx
+ movl %ecx,40(%esp)
+ jnz L022fast_enc_loop
+ movl 48(%esp),%esi
+ movl 8(%edi),%ecx
+ movl 12(%edi),%edx
+ movl %eax,(%esi)
+ movl %ebx,4(%esi)
+ movl %ecx,8(%esi)
+ movl %edx,12(%esi)
+ cmpl $0,316(%esp)
+ movl 44(%esp),%edi
+ je L023skip_ezero
+ movl $60,%ecx
+ xorl %eax,%eax
+.align 2,0x90
+.long 2884892297
+L023skip_ezero:
+ movl 28(%esp),%esp
+ popfl
+L012drop_out:
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+ pushfl
+.align 4,0x90
+L021fast_decrypt:
+ cmpl 36(%esp),%esi
+ je L024fast_dec_in_place
+ movl %edi,52(%esp)
+.align 2,0x90
+.align 4,0x90
+L025fast_dec_loop:
+ movl (%esi),%eax
+ movl 4(%esi),%ebx
+ movl 8(%esi),%ecx
+ movl 12(%esi),%edx
+ movl 44(%esp),%edi
+ call __x86_AES_decrypt
+ movl 52(%esp),%edi
+ movl 40(%esp),%esi
+ xorl (%edi),%eax
+ xorl 4(%edi),%ebx
+ xorl 8(%edi),%ecx
+ xorl 12(%edi),%edx
+ movl 36(%esp),%edi
+ movl 32(%esp),%esi
+ movl %eax,(%edi)
+ movl %ebx,4(%edi)
+ movl %ecx,8(%edi)
+ movl %edx,12(%edi)
+ movl 40(%esp),%ecx
+ movl %esi,52(%esp)
+ leal 16(%esi),%esi
+ movl %esi,32(%esp)
+ leal 16(%edi),%edi
+ movl %edi,36(%esp)
+ subl $16,%ecx
+ movl %ecx,40(%esp)
+ jnz L025fast_dec_loop
+ movl 52(%esp),%edi
+ movl 48(%esp),%esi
+ movl (%edi),%eax
+ movl 4(%edi),%ebx
+ movl 8(%edi),%ecx
+ movl 12(%edi),%edx
+ movl %eax,(%esi)
+ movl %ebx,4(%esi)
+ movl %ecx,8(%esi)
+ movl %edx,12(%esi)
+ jmp L026fast_dec_out
+.align 4,0x90
+L024fast_dec_in_place:
+L027fast_dec_in_place_loop:
+ movl (%esi),%eax
+ movl 4(%esi),%ebx
+ movl 8(%esi),%ecx
+ movl 12(%esi),%edx
+ leal 60(%esp),%edi
+ movl %eax,(%edi)
+ movl %ebx,4(%edi)
+ movl %ecx,8(%edi)
+ movl %edx,12(%edi)
+ movl 44(%esp),%edi
+ call __x86_AES_decrypt
+ movl 48(%esp),%edi
+ movl 36(%esp),%esi
+ xorl (%edi),%eax
+ xorl 4(%edi),%ebx
+ xorl 8(%edi),%ecx
+ xorl 12(%edi),%edx
+ movl %eax,(%esi)
+ movl %ebx,4(%esi)
+ movl %ecx,8(%esi)
+ movl %edx,12(%esi)
+ leal 16(%esi),%esi
+ movl %esi,36(%esp)
+ leal 60(%esp),%esi
+ movl (%esi),%eax
+ movl 4(%esi),%ebx
+ movl 8(%esi),%ecx
+ movl 12(%esi),%edx
+ movl %eax,(%edi)
+ movl %ebx,4(%edi)
+ movl %ecx,8(%edi)
+ movl %edx,12(%edi)
+ movl 32(%esp),%esi
+ movl 40(%esp),%ecx
+ leal 16(%esi),%esi
+ movl %esi,32(%esp)
+ subl $16,%ecx
+ movl %ecx,40(%esp)
+ jnz L027fast_dec_in_place_loop
+.align 2,0x90
+L026fast_dec_out:
+ cmpl $0,316(%esp)
+ movl 44(%esp),%edi
+ je L028skip_dzero
+ movl $60,%ecx
+ xorl %eax,%eax
+.align 2,0x90
+.long 2884892297
+L028skip_dzero:
+ movl 28(%esp),%esp
+ popfl
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+ pushfl
+.align 4,0x90
+L015slow_way:
+ movl (%eax),%eax
+ movl 36(%esp),%edi
+ leal -80(%esp),%esi
+ andl $-64,%esi
+ leal -143(%edi),%ebx
+ subl %esi,%ebx
+ negl %ebx
+ andl $960,%ebx
+ subl %ebx,%esi
+ leal 768(%esi),%ebx
+ subl %ebp,%ebx
+ andl $768,%ebx
+ leal 2176(%ebp,%ebx,1),%ebp
+ leal 24(%esp),%edx
+ xchgl %esi,%esp
+ addl $4,%esp
+ movl %ebp,24(%esp)
+ movl %esi,28(%esp)
+ movl %eax,52(%esp)
+ movl (%edx),%eax
+ movl 4(%edx),%ebx
+ movl 16(%edx),%esi
+ movl 20(%edx),%edx
+ movl %eax,32(%esp)
+ movl %ebx,36(%esp)
+ movl %ecx,40(%esp)
+ movl %edi,44(%esp)
+ movl %esi,48(%esp)
+ movl %esi,%edi
+ movl %eax,%esi
+ cmpl $0,%edx
+ je L029slow_decrypt
+ cmpl $16,%ecx
+ movl %ebx,%edx
+ jb L030slow_enc_tail
+ btl $25,52(%esp)
+ jnc L031slow_enc_x86
+ movq (%edi),%mm0
+ movq 8(%edi),%mm4
+.align 4,0x90
+L032slow_enc_loop_sse:
+ pxor (%esi),%mm0
+ pxor 8(%esi),%mm4
+ movl 44(%esp),%edi
+ call __sse_AES_encrypt_compact
+ movl 32(%esp),%esi
+ movl 36(%esp),%edi
+ movl 40(%esp),%ecx
+ movq %mm0,(%edi)
+ movq %mm4,8(%edi)
+ leal 16(%esi),%esi
+ movl %esi,32(%esp)
+ leal 16(%edi),%edx
+ movl %edx,36(%esp)
+ subl $16,%ecx
+ cmpl $16,%ecx
+ movl %ecx,40(%esp)
+ jae L032slow_enc_loop_sse
+ testl $15,%ecx
+ jnz L030slow_enc_tail
+ movl 48(%esp),%esi
+ movq %mm0,(%esi)
+ movq %mm4,8(%esi)
+ emms
+ movl 28(%esp),%esp
+ popfl
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+ pushfl
+.align 4,0x90
+L031slow_enc_x86:
+ movl (%edi),%eax
+ movl 4(%edi),%ebx
+.align 2,0x90
+L033slow_enc_loop_x86:
+ movl 8(%edi),%ecx
+ movl 12(%edi),%edx
+ xorl (%esi),%eax
+ xorl 4(%esi),%ebx
+ xorl 8(%esi),%ecx
+ xorl 12(%esi),%edx
+ movl 44(%esp),%edi
+ call __x86_AES_encrypt_compact
+ movl 32(%esp),%esi
+ movl 36(%esp),%edi
+ movl %eax,(%edi)
+ movl %ebx,4(%edi)
+ movl %ecx,8(%edi)
+ movl %edx,12(%edi)
+ movl 40(%esp),%ecx
+ leal 16(%esi),%esi
+ movl %esi,32(%esp)
+ leal 16(%edi),%edx
+ movl %edx,36(%esp)
+ subl $16,%ecx
+ cmpl $16,%ecx
+ movl %ecx,40(%esp)
+ jae L033slow_enc_loop_x86
+ testl $15,%ecx
+ jnz L030slow_enc_tail
+ movl 48(%esp),%esi
+ movl 8(%edi),%ecx
+ movl 12(%edi),%edx
+ movl %eax,(%esi)
+ movl %ebx,4(%esi)
+ movl %ecx,8(%esi)
+ movl %edx,12(%esi)
+ movl 28(%esp),%esp
+ popfl
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+ pushfl
+.align 4,0x90
+L030slow_enc_tail:
+ emms
+ movl %edx,%edi
+ movl $16,%ebx
+ subl %ecx,%ebx
+ cmpl %esi,%edi
+ je L034enc_in_place
+.align 2,0x90
+.long 2767451785
+ jmp L035enc_skip_in_place
+L034enc_in_place:
+ leal (%edi,%ecx,1),%edi
+L035enc_skip_in_place:
+ movl %ebx,%ecx
+ xorl %eax,%eax
+.align 2,0x90
+.long 2868115081
+ movl 48(%esp),%edi
+ movl %edx,%esi
+ movl (%edi),%eax
+ movl 4(%edi),%ebx
+ movl $16,40(%esp)
+ jmp L033slow_enc_loop_x86
+.align 4,0x90
+L029slow_decrypt:
+ btl $25,52(%esp)
+ jnc L036slow_dec_loop_x86
+.align 2,0x90
+L037slow_dec_loop_sse:
+ movq (%esi),%mm0
+ movq 8(%esi),%mm4
+ movl 44(%esp),%edi
+ call __sse_AES_decrypt_compact
+ movl 32(%esp),%esi
+ leal 60(%esp),%eax
+ movl 36(%esp),%ebx
+ movl 40(%esp),%ecx
+ movl 48(%esp),%edi
+ movq (%esi),%mm1
+ movq 8(%esi),%mm5
+ pxor (%edi),%mm0
+ pxor 8(%edi),%mm4
+ movq %mm1,(%edi)
+ movq %mm5,8(%edi)
+ subl $16,%ecx
+ jc L038slow_dec_partial_sse
+ movq %mm0,(%ebx)
+ movq %mm4,8(%ebx)
+ leal 16(%ebx),%ebx
+ movl %ebx,36(%esp)
+ leal 16(%esi),%esi
+ movl %esi,32(%esp)
+ movl %ecx,40(%esp)
+ jnz L037slow_dec_loop_sse
+ emms
+ movl 28(%esp),%esp
+ popfl
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+ pushfl
+.align 4,0x90
+L038slow_dec_partial_sse:
+ movq %mm0,(%eax)
+ movq %mm4,8(%eax)
+ emms
+ addl $16,%ecx
+ movl %ebx,%edi
+ movl %eax,%esi
+.align 2,0x90
+.long 2767451785
+ movl 28(%esp),%esp
+ popfl
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+ pushfl
+.align 4,0x90
+L036slow_dec_loop_x86:
+ movl (%esi),%eax
+ movl 4(%esi),%ebx
+ movl 8(%esi),%ecx
+ movl 12(%esi),%edx
+ leal 60(%esp),%edi
+ movl %eax,(%edi)
+ movl %ebx,4(%edi)
+ movl %ecx,8(%edi)
+ movl %edx,12(%edi)
+ movl 44(%esp),%edi
+ call __x86_AES_decrypt_compact
+ movl 48(%esp),%edi
+ movl 40(%esp),%esi
+ xorl (%edi),%eax
+ xorl 4(%edi),%ebx
+ xorl 8(%edi),%ecx
+ xorl 12(%edi),%edx
+ subl $16,%esi
+ jc L039slow_dec_partial_x86
+ movl %esi,40(%esp)
+ movl 36(%esp),%esi
+ movl %eax,(%esi)
+ movl %ebx,4(%esi)
+ movl %ecx,8(%esi)
+ movl %edx,12(%esi)
+ leal 16(%esi),%esi
+ movl %esi,36(%esp)
+ leal 60(%esp),%esi
+ movl (%esi),%eax
+ movl 4(%esi),%ebx
+ movl 8(%esi),%ecx
+ movl 12(%esi),%edx
+ movl %eax,(%edi)
+ movl %ebx,4(%edi)
+ movl %ecx,8(%edi)
+ movl %edx,12(%edi)
+ movl 32(%esp),%esi
+ leal 16(%esi),%esi
+ movl %esi,32(%esp)
+ jnz L036slow_dec_loop_x86
+ movl 28(%esp),%esp
+ popfl
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+ pushfl
+.align 4,0x90
+L039slow_dec_partial_x86:
+ leal 60(%esp),%esi
+ movl %eax,(%esi)
+ movl %ebx,4(%esi)
+ movl %ecx,8(%esi)
+ movl %edx,12(%esi)
+ movl 32(%esp),%esi
+ movl (%esi),%eax
+ movl 4(%esi),%ebx
+ movl 8(%esi),%ecx
+ movl 12(%esi),%edx
+ movl %eax,(%edi)
+ movl %ebx,4(%edi)
+ movl %ecx,8(%edi)
+ movl %edx,12(%edi)
+ movl 40(%esp),%ecx
+ movl 36(%esp),%edi
+ leal 60(%esp),%esi
+.align 2,0x90
+.long 2767451785
+ movl 28(%esp),%esp
+ popfl
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.private_extern __x86_AES_set_encrypt_key
+.align 4
+__x86_AES_set_encrypt_key:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ movl 24(%esp),%esi
+ movl 32(%esp),%edi
+ testl $-1,%esi
+ jz L040badpointer
+ testl $-1,%edi
+ jz L040badpointer
+ call L041pic_point
+L041pic_point:
+ popl %ebp
+ leal LAES_Te-L041pic_point(%ebp),%ebp
+ leal 2176(%ebp),%ebp
+ movl -128(%ebp),%eax
+ movl -96(%ebp),%ebx
+ movl -64(%ebp),%ecx
+ movl -32(%ebp),%edx
+ movl (%ebp),%eax
+ movl 32(%ebp),%ebx
+ movl 64(%ebp),%ecx
+ movl 96(%ebp),%edx
+ movl 28(%esp),%ecx
+ cmpl $128,%ecx
+ je L04210rounds
+ cmpl $192,%ecx
+ je L04312rounds
+ cmpl $256,%ecx
+ je L04414rounds
+ movl $-2,%eax
+ jmp L045exit
+L04210rounds:
+ movl (%esi),%eax
+ movl 4(%esi),%ebx
+ movl 8(%esi),%ecx
+ movl 12(%esi),%edx
+ movl %eax,(%edi)
+ movl %ebx,4(%edi)
+ movl %ecx,8(%edi)
+ movl %edx,12(%edi)
+ xorl %ecx,%ecx
+ jmp L04610shortcut
+.align 2,0x90
+L04710loop:
+ movl (%edi),%eax
+ movl 12(%edi),%edx
+L04610shortcut:
+ movzbl %dl,%esi
+ movzbl -128(%ebp,%esi,1),%ebx
+ movzbl %dh,%esi
+ shll $24,%ebx
+ xorl %ebx,%eax
+ movzbl -128(%ebp,%esi,1),%ebx
+ shrl $16,%edx
+ movzbl %dl,%esi
+ xorl %ebx,%eax
+ movzbl -128(%ebp,%esi,1),%ebx
+ movzbl %dh,%esi
+ shll $8,%ebx
+ xorl %ebx,%eax
+ movzbl -128(%ebp,%esi,1),%ebx
+ shll $16,%ebx
+ xorl %ebx,%eax
+ xorl 896(%ebp,%ecx,4),%eax
+ movl %eax,16(%edi)
+ xorl 4(%edi),%eax
+ movl %eax,20(%edi)
+ xorl 8(%edi),%eax
+ movl %eax,24(%edi)
+ xorl 12(%edi),%eax
+ movl %eax,28(%edi)
+ incl %ecx
+ addl $16,%edi
+ cmpl $10,%ecx
+ jl L04710loop
+ movl $10,80(%edi)
+ xorl %eax,%eax
+ jmp L045exit
+L04312rounds:
+ movl (%esi),%eax
+ movl 4(%esi),%ebx
+ movl 8(%esi),%ecx
+ movl 12(%esi),%edx
+ movl %eax,(%edi)
+ movl %ebx,4(%edi)
+ movl %ecx,8(%edi)
+ movl %edx,12(%edi)
+ movl 16(%esi),%ecx
+ movl 20(%esi),%edx
+ movl %ecx,16(%edi)
+ movl %edx,20(%edi)
+ xorl %ecx,%ecx
+ jmp L04812shortcut
+.align 2,0x90
+L04912loop:
+ movl (%edi),%eax
+ movl 20(%edi),%edx
+L04812shortcut:
+ movzbl %dl,%esi
+ movzbl -128(%ebp,%esi,1),%ebx
+ movzbl %dh,%esi
+ shll $24,%ebx
+ xorl %ebx,%eax
+ movzbl -128(%ebp,%esi,1),%ebx
+ shrl $16,%edx
+ movzbl %dl,%esi
+ xorl %ebx,%eax
+ movzbl -128(%ebp,%esi,1),%ebx
+ movzbl %dh,%esi
+ shll $8,%ebx
+ xorl %ebx,%eax
+ movzbl -128(%ebp,%esi,1),%ebx
+ shll $16,%ebx
+ xorl %ebx,%eax
+ xorl 896(%ebp,%ecx,4),%eax
+ movl %eax,24(%edi)
+ xorl 4(%edi),%eax
+ movl %eax,28(%edi)
+ xorl 8(%edi),%eax
+ movl %eax,32(%edi)
+ xorl 12(%edi),%eax
+ movl %eax,36(%edi)
+ cmpl $7,%ecx
+ je L05012break
+ incl %ecx
+ xorl 16(%edi),%eax
+ movl %eax,40(%edi)
+ xorl 20(%edi),%eax
+ movl %eax,44(%edi)
+ addl $24,%edi
+ jmp L04912loop
+L05012break:
+ movl $12,72(%edi)
+ xorl %eax,%eax
+ jmp L045exit
+L04414rounds:
+ movl (%esi),%eax
+ movl 4(%esi),%ebx
+ movl 8(%esi),%ecx
+ movl 12(%esi),%edx
+ movl %eax,(%edi)
+ movl %ebx,4(%edi)
+ movl %ecx,8(%edi)
+ movl %edx,12(%edi)
+ movl 16(%esi),%eax
+ movl 20(%esi),%ebx
+ movl 24(%esi),%ecx
+ movl 28(%esi),%edx
+ movl %eax,16(%edi)
+ movl %ebx,20(%edi)
+ movl %ecx,24(%edi)
+ movl %edx,28(%edi)
+ xorl %ecx,%ecx
+ jmp L05114shortcut
+.align 2,0x90
+L05214loop:
+ movl 28(%edi),%edx
+L05114shortcut:
+ movl (%edi),%eax
+ movzbl %dl,%esi
+ movzbl -128(%ebp,%esi,1),%ebx
+ movzbl %dh,%esi
+ shll $24,%ebx
+ xorl %ebx,%eax
+ movzbl -128(%ebp,%esi,1),%ebx
+ shrl $16,%edx
+ movzbl %dl,%esi
+ xorl %ebx,%eax
+ movzbl -128(%ebp,%esi,1),%ebx
+ movzbl %dh,%esi
+ shll $8,%ebx
+ xorl %ebx,%eax
+ movzbl -128(%ebp,%esi,1),%ebx
+ shll $16,%ebx
+ xorl %ebx,%eax
+ xorl 896(%ebp,%ecx,4),%eax
+ movl %eax,32(%edi)
+ xorl 4(%edi),%eax
+ movl %eax,36(%edi)
+ xorl 8(%edi),%eax
+ movl %eax,40(%edi)
+ xorl 12(%edi),%eax
+ movl %eax,44(%edi)
+ cmpl $6,%ecx
+ je L05314break
+ incl %ecx
+ movl %eax,%edx
+ movl 16(%edi),%eax
+ movzbl %dl,%esi
+ movzbl -128(%ebp,%esi,1),%ebx
+ movzbl %dh,%esi
+ xorl %ebx,%eax
+ movzbl -128(%ebp,%esi,1),%ebx
+ shrl $16,%edx
+ shll $8,%ebx
+ movzbl %dl,%esi
+ xorl %ebx,%eax
+ movzbl -128(%ebp,%esi,1),%ebx
+ movzbl %dh,%esi
+ shll $16,%ebx
+ xorl %ebx,%eax
+ movzbl -128(%ebp,%esi,1),%ebx
+ shll $24,%ebx
+ xorl %ebx,%eax
+ movl %eax,48(%edi)
+ xorl 20(%edi),%eax
+ movl %eax,52(%edi)
+ xorl 24(%edi),%eax
+ movl %eax,56(%edi)
+ xorl 28(%edi),%eax
+ movl %eax,60(%edi)
+ addl $32,%edi
+ jmp L05214loop
+L05314break:
+ movl $14,48(%edi)
+ xorl %eax,%eax
+ jmp L045exit
+L040badpointer:
+ movl $-1,%eax
+L045exit:
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.globl _asm_AES_set_encrypt_key
+.private_extern _asm_AES_set_encrypt_key
+.align 4
+_asm_AES_set_encrypt_key:
+L_asm_AES_set_encrypt_key_begin:
+ call __x86_AES_set_encrypt_key
+ ret
+.globl _asm_AES_set_decrypt_key
+.private_extern _asm_AES_set_decrypt_key
+.align 4
+_asm_AES_set_decrypt_key:
+L_asm_AES_set_decrypt_key_begin:
+ call __x86_AES_set_encrypt_key
+ cmpl $0,%eax
+ je L054proceed
+ ret
+L054proceed:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ movl 28(%esp),%esi
+ movl 240(%esi),%ecx
+ leal (,%ecx,4),%ecx
+ leal (%esi,%ecx,4),%edi
+.align 2,0x90
+L055invert:
+ movl (%esi),%eax
+ movl 4(%esi),%ebx
+ movl (%edi),%ecx
+ movl 4(%edi),%edx
+ movl %eax,(%edi)
+ movl %ebx,4(%edi)
+ movl %ecx,(%esi)
+ movl %edx,4(%esi)
+ movl 8(%esi),%eax
+ movl 12(%esi),%ebx
+ movl 8(%edi),%ecx
+ movl 12(%edi),%edx
+ movl %eax,8(%edi)
+ movl %ebx,12(%edi)
+ movl %ecx,8(%esi)
+ movl %edx,12(%esi)
+ addl $16,%esi
+ subl $16,%edi
+ cmpl %edi,%esi
+ jne L055invert
+ movl 28(%esp),%edi
+ movl 240(%edi),%esi
+ leal -2(%esi,%esi,1),%esi
+ leal (%edi,%esi,8),%esi
+ movl %esi,28(%esp)
+ movl 16(%edi),%eax
+.align 2,0x90
+L056permute:
+ addl $16,%edi
+ movl $2155905152,%ebp
+ andl %eax,%ebp
+ leal (%eax,%eax,1),%ebx
+ movl %ebp,%esi
+ shrl $7,%ebp
+ subl %ebp,%esi
+ andl $4278124286,%ebx
+ andl $454761243,%esi
+ xorl %esi,%ebx
+ movl $2155905152,%ebp
+ andl %ebx,%ebp
+ leal (%ebx,%ebx,1),%ecx
+ movl %ebp,%esi
+ shrl $7,%ebp
+ subl %ebp,%esi
+ andl $4278124286,%ecx
+ andl $454761243,%esi
+ xorl %eax,%ebx
+ xorl %esi,%ecx
+ movl $2155905152,%ebp
+ andl %ecx,%ebp
+ leal (%ecx,%ecx,1),%edx
+ movl %ebp,%esi
+ shrl $7,%ebp
+ xorl %eax,%ecx
+ subl %ebp,%esi
+ andl $4278124286,%edx
+ andl $454761243,%esi
+ roll $8,%eax
+ xorl %esi,%edx
+ movl 4(%edi),%ebp
+ xorl %ebx,%eax
+ xorl %edx,%ebx
+ xorl %ecx,%eax
+ roll $24,%ebx
+ xorl %edx,%ecx
+ xorl %edx,%eax
+ roll $16,%ecx
+ xorl %ebx,%eax
+ roll $8,%edx
+ xorl %ecx,%eax
+ movl %ebp,%ebx
+ xorl %edx,%eax
+ movl %eax,(%edi)
+ movl $2155905152,%ebp
+ andl %ebx,%ebp
+ leal (%ebx,%ebx,1),%ecx
+ movl %ebp,%esi
+ shrl $7,%ebp
+ subl %ebp,%esi
+ andl $4278124286,%ecx
+ andl $454761243,%esi
+ xorl %esi,%ecx
+ movl $2155905152,%ebp
+ andl %ecx,%ebp
+ leal (%ecx,%ecx,1),%edx
+ movl %ebp,%esi
+ shrl $7,%ebp
+ subl %ebp,%esi
+ andl $4278124286,%edx
+ andl $454761243,%esi
+ xorl %ebx,%ecx
+ xorl %esi,%edx
+ movl $2155905152,%ebp
+ andl %edx,%ebp
+ leal (%edx,%edx,1),%eax
+ movl %ebp,%esi
+ shrl $7,%ebp
+ xorl %ebx,%edx
+ subl %ebp,%esi
+ andl $4278124286,%eax
+ andl $454761243,%esi
+ roll $8,%ebx
+ xorl %esi,%eax
+ movl 8(%edi),%ebp
+ xorl %ecx,%ebx
+ xorl %eax,%ecx
+ xorl %edx,%ebx
+ roll $24,%ecx
+ xorl %eax,%edx
+ xorl %eax,%ebx
+ roll $16,%edx
+ xorl %ecx,%ebx
+ roll $8,%eax
+ xorl %edx,%ebx
+ movl %ebp,%ecx
+ xorl %eax,%ebx
+ movl %ebx,4(%edi)
+ movl $2155905152,%ebp
+ andl %ecx,%ebp
+ leal (%ecx,%ecx,1),%edx
+ movl %ebp,%esi
+ shrl $7,%ebp
+ subl %ebp,%esi
+ andl $4278124286,%edx
+ andl $454761243,%esi
+ xorl %esi,%edx
+ movl $2155905152,%ebp
+ andl %edx,%ebp
+ leal (%edx,%edx,1),%eax
+ movl %ebp,%esi
+ shrl $7,%ebp
+ subl %ebp,%esi
+ andl $4278124286,%eax
+ andl $454761243,%esi
+ xorl %ecx,%edx
+ xorl %esi,%eax
+ movl $2155905152,%ebp
+ andl %eax,%ebp
+ leal (%eax,%eax,1),%ebx
+ movl %ebp,%esi
+ shrl $7,%ebp
+ xorl %ecx,%eax
+ subl %ebp,%esi
+ andl $4278124286,%ebx
+ andl $454761243,%esi
+ roll $8,%ecx
+ xorl %esi,%ebx
+ movl 12(%edi),%ebp
+ xorl %edx,%ecx
+ xorl %ebx,%edx
+ xorl %eax,%ecx
+ roll $24,%edx
+ xorl %ebx,%eax
+ xorl %ebx,%ecx
+ roll $16,%eax
+ xorl %edx,%ecx
+ roll $8,%ebx
+ xorl %eax,%ecx
+ movl %ebp,%edx
+ xorl %ebx,%ecx
+ movl %ecx,8(%edi)
+ movl $2155905152,%ebp
+ andl %edx,%ebp
+ leal (%edx,%edx,1),%eax
+ movl %ebp,%esi
+ shrl $7,%ebp
+ subl %ebp,%esi
+ andl $4278124286,%eax
+ andl $454761243,%esi
+ xorl %esi,%eax
+ movl $2155905152,%ebp
+ andl %eax,%ebp
+ leal (%eax,%eax,1),%ebx
+ movl %ebp,%esi
+ shrl $7,%ebp
+ subl %ebp,%esi
+ andl $4278124286,%ebx
+ andl $454761243,%esi
+ xorl %edx,%eax
+ xorl %esi,%ebx
+ movl $2155905152,%ebp
+ andl %ebx,%ebp
+ leal (%ebx,%ebx,1),%ecx
+ movl %ebp,%esi
+ shrl $7,%ebp
+ xorl %edx,%ebx
+ subl %ebp,%esi
+ andl $4278124286,%ecx
+ andl $454761243,%esi
+ roll $8,%edx
+ xorl %esi,%ecx
+ movl 16(%edi),%ebp
+ xorl %eax,%edx
+ xorl %ecx,%eax
+ xorl %ebx,%edx
+ roll $24,%eax
+ xorl %ecx,%ebx
+ xorl %ecx,%edx
+ roll $16,%ebx
+ xorl %eax,%edx
+ roll $8,%ecx
+ xorl %ebx,%edx
+ movl %ebp,%eax
+ xorl %ecx,%edx
+ movl %edx,12(%edi)
+ cmpl 28(%esp),%edi
+ jb L056permute
+ xorl %eax,%eax
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.byte 65,69,83,32,102,111,114,32,120,56,54,44,32,67,82,89
+.byte 80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114
+.byte 111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
+.section __IMPORT,__pointers,non_lazy_symbol_pointers
+L_OPENSSL_ia32cap_P$non_lazy_ptr:
+.indirect_symbol _OPENSSL_ia32cap_P
+.long 0
+#endif
diff --git a/mac-x86/crypto/aes/aesni-x86.S b/mac-x86/crypto/aes/aesni-x86.S
new file mode 100644
index 0000000..9000478
--- /dev/null
+++ b/mac-x86/crypto/aes/aesni-x86.S
@@ -0,0 +1,2178 @@
+#if defined(__i386__)
+.file "src/crypto/aes/asm/aesni-x86.S"
+.text
+.globl _aesni_encrypt
+.private_extern _aesni_encrypt
+.align 4
+_aesni_encrypt:
+L_aesni_encrypt_begin:
+ movl 4(%esp),%eax
+ movl 12(%esp),%edx
+ movups (%eax),%xmm2
+ movl 240(%edx),%ecx
+ movl 8(%esp),%eax
+ movups (%edx),%xmm0
+ movups 16(%edx),%xmm1
+ leal 32(%edx),%edx
+ xorps %xmm0,%xmm2
+L000enc1_loop_1:
+.byte 102,15,56,220,209
+ decl %ecx
+ movups (%edx),%xmm1
+ leal 16(%edx),%edx
+ jnz L000enc1_loop_1
+.byte 102,15,56,221,209
+ movups %xmm2,(%eax)
+ ret
+.globl _aesni_decrypt
+.private_extern _aesni_decrypt
+.align 4
+_aesni_decrypt:
+L_aesni_decrypt_begin:
+ movl 4(%esp),%eax
+ movl 12(%esp),%edx
+ movups (%eax),%xmm2
+ movl 240(%edx),%ecx
+ movl 8(%esp),%eax
+ movups (%edx),%xmm0
+ movups 16(%edx),%xmm1
+ leal 32(%edx),%edx
+ xorps %xmm0,%xmm2
+L001dec1_loop_2:
+.byte 102,15,56,222,209
+ decl %ecx
+ movups (%edx),%xmm1
+ leal 16(%edx),%edx
+ jnz L001dec1_loop_2
+.byte 102,15,56,223,209
+ movups %xmm2,(%eax)
+ ret
+.private_extern __aesni_encrypt2
+.align 4
+__aesni_encrypt2:
+ movups (%edx),%xmm0
+ shll $4,%ecx
+ movups 16(%edx),%xmm1
+ xorps %xmm0,%xmm2
+ pxor %xmm0,%xmm3
+ movups 32(%edx),%xmm0
+ leal 32(%edx,%ecx,1),%edx
+ negl %ecx
+ addl $16,%ecx
+L002enc2_loop:
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+ movups (%edx,%ecx,1),%xmm1
+ addl $32,%ecx
+.byte 102,15,56,220,208
+.byte 102,15,56,220,216
+ movups -16(%edx,%ecx,1),%xmm0
+ jnz L002enc2_loop
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+.byte 102,15,56,221,208
+.byte 102,15,56,221,216
+ ret
+.private_extern __aesni_decrypt2
+.align 4
+__aesni_decrypt2:
+ movups (%edx),%xmm0
+ shll $4,%ecx
+ movups 16(%edx),%xmm1
+ xorps %xmm0,%xmm2
+ pxor %xmm0,%xmm3
+ movups 32(%edx),%xmm0
+ leal 32(%edx,%ecx,1),%edx
+ negl %ecx
+ addl $16,%ecx
+L003dec2_loop:
+.byte 102,15,56,222,209
+.byte 102,15,56,222,217
+ movups (%edx,%ecx,1),%xmm1
+ addl $32,%ecx
+.byte 102,15,56,222,208
+.byte 102,15,56,222,216
+ movups -16(%edx,%ecx,1),%xmm0
+ jnz L003dec2_loop
+.byte 102,15,56,222,209
+.byte 102,15,56,222,217
+.byte 102,15,56,223,208
+.byte 102,15,56,223,216
+ ret
+.private_extern __aesni_encrypt3
+.align 4
+__aesni_encrypt3:
+ movups (%edx),%xmm0
+ shll $4,%ecx
+ movups 16(%edx),%xmm1
+ xorps %xmm0,%xmm2
+ pxor %xmm0,%xmm3
+ pxor %xmm0,%xmm4
+ movups 32(%edx),%xmm0
+ leal 32(%edx,%ecx,1),%edx
+ negl %ecx
+ addl $16,%ecx
+L004enc3_loop:
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+.byte 102,15,56,220,225
+ movups (%edx,%ecx,1),%xmm1
+ addl $32,%ecx
+.byte 102,15,56,220,208
+.byte 102,15,56,220,216
+.byte 102,15,56,220,224
+ movups -16(%edx,%ecx,1),%xmm0
+ jnz L004enc3_loop
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+.byte 102,15,56,220,225
+.byte 102,15,56,221,208
+.byte 102,15,56,221,216
+.byte 102,15,56,221,224
+ ret
+.private_extern __aesni_decrypt3
+.align 4
+__aesni_decrypt3:
+ movups (%edx),%xmm0
+ shll $4,%ecx
+ movups 16(%edx),%xmm1
+ xorps %xmm0,%xmm2
+ pxor %xmm0,%xmm3
+ pxor %xmm0,%xmm4
+ movups 32(%edx),%xmm0
+ leal 32(%edx,%ecx,1),%edx
+ negl %ecx
+ addl $16,%ecx
+L005dec3_loop:
+.byte 102,15,56,222,209
+.byte 102,15,56,222,217
+.byte 102,15,56,222,225
+ movups (%edx,%ecx,1),%xmm1
+ addl $32,%ecx
+.byte 102,15,56,222,208
+.byte 102,15,56,222,216
+.byte 102,15,56,222,224
+ movups -16(%edx,%ecx,1),%xmm0
+ jnz L005dec3_loop
+.byte 102,15,56,222,209
+.byte 102,15,56,222,217
+.byte 102,15,56,222,225
+.byte 102,15,56,223,208
+.byte 102,15,56,223,216
+.byte 102,15,56,223,224
+ ret
+.private_extern __aesni_encrypt4
+.align 4
+__aesni_encrypt4:
+ movups (%edx),%xmm0
+ movups 16(%edx),%xmm1
+ shll $4,%ecx
+ xorps %xmm0,%xmm2
+ pxor %xmm0,%xmm3
+ pxor %xmm0,%xmm4
+ pxor %xmm0,%xmm5
+ movups 32(%edx),%xmm0
+ leal 32(%edx,%ecx,1),%edx
+ negl %ecx
+.byte 15,31,64,0
+ addl $16,%ecx
+L006enc4_loop:
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+.byte 102,15,56,220,225
+.byte 102,15,56,220,233
+ movups (%edx,%ecx,1),%xmm1
+ addl $32,%ecx
+.byte 102,15,56,220,208
+.byte 102,15,56,220,216
+.byte 102,15,56,220,224
+.byte 102,15,56,220,232
+ movups -16(%edx,%ecx,1),%xmm0
+ jnz L006enc4_loop
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+.byte 102,15,56,220,225
+.byte 102,15,56,220,233
+.byte 102,15,56,221,208
+.byte 102,15,56,221,216
+.byte 102,15,56,221,224
+.byte 102,15,56,221,232
+ ret
+.private_extern __aesni_decrypt4
+.align 4
+__aesni_decrypt4:
+ movups (%edx),%xmm0
+ movups 16(%edx),%xmm1
+ shll $4,%ecx
+ xorps %xmm0,%xmm2
+ pxor %xmm0,%xmm3
+ pxor %xmm0,%xmm4
+ pxor %xmm0,%xmm5
+ movups 32(%edx),%xmm0
+ leal 32(%edx,%ecx,1),%edx
+ negl %ecx
+.byte 15,31,64,0
+ addl $16,%ecx
+L007dec4_loop:
+.byte 102,15,56,222,209
+.byte 102,15,56,222,217
+.byte 102,15,56,222,225
+.byte 102,15,56,222,233
+ movups (%edx,%ecx,1),%xmm1
+ addl $32,%ecx
+.byte 102,15,56,222,208
+.byte 102,15,56,222,216
+.byte 102,15,56,222,224
+.byte 102,15,56,222,232
+ movups -16(%edx,%ecx,1),%xmm0
+ jnz L007dec4_loop
+.byte 102,15,56,222,209
+.byte 102,15,56,222,217
+.byte 102,15,56,222,225
+.byte 102,15,56,222,233
+.byte 102,15,56,223,208
+.byte 102,15,56,223,216
+.byte 102,15,56,223,224
+.byte 102,15,56,223,232
+ ret
+.private_extern __aesni_encrypt6
+.align 4
+__aesni_encrypt6:
+ movups (%edx),%xmm0
+ shll $4,%ecx
+ movups 16(%edx),%xmm1
+ xorps %xmm0,%xmm2
+ pxor %xmm0,%xmm3
+ pxor %xmm0,%xmm4
+.byte 102,15,56,220,209
+ pxor %xmm0,%xmm5
+ pxor %xmm0,%xmm6
+.byte 102,15,56,220,217
+ leal 32(%edx,%ecx,1),%edx
+ negl %ecx
+.byte 102,15,56,220,225
+ pxor %xmm0,%xmm7
+ addl $16,%ecx
+.byte 102,15,56,220,233
+.byte 102,15,56,220,241
+.byte 102,15,56,220,249
+ movups -16(%edx,%ecx,1),%xmm0
+ jmp L_aesni_encrypt6_enter
+.align 4,0x90
+L008enc6_loop:
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+.byte 102,15,56,220,225
+.byte 102,15,56,220,233
+.byte 102,15,56,220,241
+.byte 102,15,56,220,249
+L_aesni_encrypt6_enter:
+ movups (%edx,%ecx,1),%xmm1
+ addl $32,%ecx
+.byte 102,15,56,220,208
+.byte 102,15,56,220,216
+.byte 102,15,56,220,224
+.byte 102,15,56,220,232
+.byte 102,15,56,220,240
+.byte 102,15,56,220,248
+ movups -16(%edx,%ecx,1),%xmm0
+ jnz L008enc6_loop
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+.byte 102,15,56,220,225
+.byte 102,15,56,220,233
+.byte 102,15,56,220,241
+.byte 102,15,56,220,249
+.byte 102,15,56,221,208
+.byte 102,15,56,221,216
+.byte 102,15,56,221,224
+.byte 102,15,56,221,232
+.byte 102,15,56,221,240
+.byte 102,15,56,221,248
+ ret
+.private_extern __aesni_decrypt6
+.align 4
+__aesni_decrypt6:
+ movups (%edx),%xmm0
+ shll $4,%ecx
+ movups 16(%edx),%xmm1
+ xorps %xmm0,%xmm2
+ pxor %xmm0,%xmm3
+ pxor %xmm0,%xmm4
+.byte 102,15,56,222,209
+ pxor %xmm0,%xmm5
+ pxor %xmm0,%xmm6
+.byte 102,15,56,222,217
+ leal 32(%edx,%ecx,1),%edx
+ negl %ecx
+.byte 102,15,56,222,225
+ pxor %xmm0,%xmm7
+ addl $16,%ecx
+.byte 102,15,56,222,233
+.byte 102,15,56,222,241
+.byte 102,15,56,222,249
+ movups -16(%edx,%ecx,1),%xmm0
+ jmp L_aesni_decrypt6_enter
+.align 4,0x90
+L009dec6_loop:
+.byte 102,15,56,222,209
+.byte 102,15,56,222,217
+.byte 102,15,56,222,225
+.byte 102,15,56,222,233
+.byte 102,15,56,222,241
+.byte 102,15,56,222,249
+L_aesni_decrypt6_enter:
+ movups (%edx,%ecx,1),%xmm1
+ addl $32,%ecx
+.byte 102,15,56,222,208
+.byte 102,15,56,222,216
+.byte 102,15,56,222,224
+.byte 102,15,56,222,232
+.byte 102,15,56,222,240
+.byte 102,15,56,222,248
+ movups -16(%edx,%ecx,1),%xmm0
+ jnz L009dec6_loop
+.byte 102,15,56,222,209
+.byte 102,15,56,222,217
+.byte 102,15,56,222,225
+.byte 102,15,56,222,233
+.byte 102,15,56,222,241
+.byte 102,15,56,222,249
+.byte 102,15,56,223,208
+.byte 102,15,56,223,216
+.byte 102,15,56,223,224
+.byte 102,15,56,223,232
+.byte 102,15,56,223,240
+.byte 102,15,56,223,248
+ ret
+.globl _aesni_ecb_encrypt
+.private_extern _aesni_ecb_encrypt
+.align 4
+_aesni_ecb_encrypt:
+L_aesni_ecb_encrypt_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ movl 20(%esp),%esi
+ movl 24(%esp),%edi
+ movl 28(%esp),%eax
+ movl 32(%esp),%edx
+ movl 36(%esp),%ebx
+ andl $-16,%eax
+ jz L010ecb_ret
+ movl 240(%edx),%ecx
+ testl %ebx,%ebx
+ jz L011ecb_decrypt
+ movl %edx,%ebp
+ movl %ecx,%ebx
+ cmpl $96,%eax
+ jb L012ecb_enc_tail
+ movdqu (%esi),%xmm2
+ movdqu 16(%esi),%xmm3
+ movdqu 32(%esi),%xmm4
+ movdqu 48(%esi),%xmm5
+ movdqu 64(%esi),%xmm6
+ movdqu 80(%esi),%xmm7
+ leal 96(%esi),%esi
+ subl $96,%eax
+ jmp L013ecb_enc_loop6_enter
+.align 4,0x90
+L014ecb_enc_loop6:
+ movups %xmm2,(%edi)
+ movdqu (%esi),%xmm2
+ movups %xmm3,16(%edi)
+ movdqu 16(%esi),%xmm3
+ movups %xmm4,32(%edi)
+ movdqu 32(%esi),%xmm4
+ movups %xmm5,48(%edi)
+ movdqu 48(%esi),%xmm5
+ movups %xmm6,64(%edi)
+ movdqu 64(%esi),%xmm6
+ movups %xmm7,80(%edi)
+ leal 96(%edi),%edi
+ movdqu 80(%esi),%xmm7
+ leal 96(%esi),%esi
+L013ecb_enc_loop6_enter:
+ call __aesni_encrypt6
+ movl %ebp,%edx
+ movl %ebx,%ecx
+ subl $96,%eax
+ jnc L014ecb_enc_loop6
+ movups %xmm2,(%edi)
+ movups %xmm3,16(%edi)
+ movups %xmm4,32(%edi)
+ movups %xmm5,48(%edi)
+ movups %xmm6,64(%edi)
+ movups %xmm7,80(%edi)
+ leal 96(%edi),%edi
+ addl $96,%eax
+ jz L010ecb_ret
+L012ecb_enc_tail:
+ movups (%esi),%xmm2
+ cmpl $32,%eax
+ jb L015ecb_enc_one
+ movups 16(%esi),%xmm3
+ je L016ecb_enc_two
+ movups 32(%esi),%xmm4
+ cmpl $64,%eax
+ jb L017ecb_enc_three
+ movups 48(%esi),%xmm5
+ je L018ecb_enc_four
+ movups 64(%esi),%xmm6
+ xorps %xmm7,%xmm7
+ call __aesni_encrypt6
+ movups %xmm2,(%edi)
+ movups %xmm3,16(%edi)
+ movups %xmm4,32(%edi)
+ movups %xmm5,48(%edi)
+ movups %xmm6,64(%edi)
+ jmp L010ecb_ret
+.align 4,0x90
+L015ecb_enc_one:
+ movups (%edx),%xmm0
+ movups 16(%edx),%xmm1
+ leal 32(%edx),%edx
+ xorps %xmm0,%xmm2
+L019enc1_loop_3:
+.byte 102,15,56,220,209
+ decl %ecx
+ movups (%edx),%xmm1
+ leal 16(%edx),%edx
+ jnz L019enc1_loop_3
+.byte 102,15,56,221,209
+ movups %xmm2,(%edi)
+ jmp L010ecb_ret
+.align 4,0x90
+L016ecb_enc_two:
+ call __aesni_encrypt2
+ movups %xmm2,(%edi)
+ movups %xmm3,16(%edi)
+ jmp L010ecb_ret
+.align 4,0x90
+L017ecb_enc_three:
+ call __aesni_encrypt3
+ movups %xmm2,(%edi)
+ movups %xmm3,16(%edi)
+ movups %xmm4,32(%edi)
+ jmp L010ecb_ret
+.align 4,0x90
+L018ecb_enc_four:
+ call __aesni_encrypt4
+ movups %xmm2,(%edi)
+ movups %xmm3,16(%edi)
+ movups %xmm4,32(%edi)
+ movups %xmm5,48(%edi)
+ jmp L010ecb_ret
+.align 4,0x90
+L011ecb_decrypt:
+ movl %edx,%ebp
+ movl %ecx,%ebx
+ cmpl $96,%eax
+ jb L020ecb_dec_tail
+ movdqu (%esi),%xmm2
+ movdqu 16(%esi),%xmm3
+ movdqu 32(%esi),%xmm4
+ movdqu 48(%esi),%xmm5
+ movdqu 64(%esi),%xmm6
+ movdqu 80(%esi),%xmm7
+ leal 96(%esi),%esi
+ subl $96,%eax
+ jmp L021ecb_dec_loop6_enter
+.align 4,0x90
+L022ecb_dec_loop6:
+ movups %xmm2,(%edi)
+ movdqu (%esi),%xmm2
+ movups %xmm3,16(%edi)
+ movdqu 16(%esi),%xmm3
+ movups %xmm4,32(%edi)
+ movdqu 32(%esi),%xmm4
+ movups %xmm5,48(%edi)
+ movdqu 48(%esi),%xmm5
+ movups %xmm6,64(%edi)
+ movdqu 64(%esi),%xmm6
+ movups %xmm7,80(%edi)
+ leal 96(%edi),%edi
+ movdqu 80(%esi),%xmm7
+ leal 96(%esi),%esi
+L021ecb_dec_loop6_enter:
+ call __aesni_decrypt6
+ movl %ebp,%edx
+ movl %ebx,%ecx
+ subl $96,%eax
+ jnc L022ecb_dec_loop6
+ movups %xmm2,(%edi)
+ movups %xmm3,16(%edi)
+ movups %xmm4,32(%edi)
+ movups %xmm5,48(%edi)
+ movups %xmm6,64(%edi)
+ movups %xmm7,80(%edi)
+ leal 96(%edi),%edi
+ addl $96,%eax
+ jz L010ecb_ret
+L020ecb_dec_tail:
+ movups (%esi),%xmm2
+ cmpl $32,%eax
+ jb L023ecb_dec_one
+ movups 16(%esi),%xmm3
+ je L024ecb_dec_two
+ movups 32(%esi),%xmm4
+ cmpl $64,%eax
+ jb L025ecb_dec_three
+ movups 48(%esi),%xmm5
+ je L026ecb_dec_four
+ movups 64(%esi),%xmm6
+ xorps %xmm7,%xmm7
+ call __aesni_decrypt6
+ movups %xmm2,(%edi)
+ movups %xmm3,16(%edi)
+ movups %xmm4,32(%edi)
+ movups %xmm5,48(%edi)
+ movups %xmm6,64(%edi)
+ jmp L010ecb_ret
+.align 4,0x90
+L023ecb_dec_one:
+ movups (%edx),%xmm0
+ movups 16(%edx),%xmm1
+ leal 32(%edx),%edx
+ xorps %xmm0,%xmm2
+L027dec1_loop_4:
+.byte 102,15,56,222,209
+ decl %ecx
+ movups (%edx),%xmm1
+ leal 16(%edx),%edx
+ jnz L027dec1_loop_4
+.byte 102,15,56,223,209
+ movups %xmm2,(%edi)
+ jmp L010ecb_ret
+.align 4,0x90
+L024ecb_dec_two:
+ call __aesni_decrypt2
+ movups %xmm2,(%edi)
+ movups %xmm3,16(%edi)
+ jmp L010ecb_ret
+.align 4,0x90
+L025ecb_dec_three:
+ call __aesni_decrypt3
+ movups %xmm2,(%edi)
+ movups %xmm3,16(%edi)
+ movups %xmm4,32(%edi)
+ jmp L010ecb_ret
+.align 4,0x90
+L026ecb_dec_four:
+ call __aesni_decrypt4
+ movups %xmm2,(%edi)
+ movups %xmm3,16(%edi)
+ movups %xmm4,32(%edi)
+ movups %xmm5,48(%edi)
+L010ecb_ret:
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.globl _aesni_ccm64_encrypt_blocks
+.private_extern _aesni_ccm64_encrypt_blocks
+.align 4
+_aesni_ccm64_encrypt_blocks:
+L_aesni_ccm64_encrypt_blocks_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ movl 20(%esp),%esi
+ movl 24(%esp),%edi
+ movl 28(%esp),%eax
+ movl 32(%esp),%edx
+ movl 36(%esp),%ebx
+ movl 40(%esp),%ecx
+ movl %esp,%ebp
+ subl $60,%esp
+ andl $-16,%esp
+ movl %ebp,48(%esp)
+ movdqu (%ebx),%xmm7
+ movdqu (%ecx),%xmm3
+ movl 240(%edx),%ecx
+ movl $202182159,(%esp)
+ movl $134810123,4(%esp)
+ movl $67438087,8(%esp)
+ movl $66051,12(%esp)
+ movl $1,%ebx
+ xorl %ebp,%ebp
+ movl %ebx,16(%esp)
+ movl %ebp,20(%esp)
+ movl %ebp,24(%esp)
+ movl %ebp,28(%esp)
+ shll $4,%ecx
+ movl $16,%ebx
+ leal (%edx),%ebp
+ movdqa (%esp),%xmm5
+ movdqa %xmm7,%xmm2
+ leal 32(%edx,%ecx,1),%edx
+ subl %ecx,%ebx
+.byte 102,15,56,0,253
+L028ccm64_enc_outer:
+ movups (%ebp),%xmm0
+ movl %ebx,%ecx
+ movups (%esi),%xmm6
+ xorps %xmm0,%xmm2
+ movups 16(%ebp),%xmm1
+ xorps %xmm6,%xmm0
+ xorps %xmm0,%xmm3
+ movups 32(%ebp),%xmm0
+L029ccm64_enc2_loop:
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+ movups (%edx,%ecx,1),%xmm1
+ addl $32,%ecx
+.byte 102,15,56,220,208
+.byte 102,15,56,220,216
+ movups -16(%edx,%ecx,1),%xmm0
+ jnz L029ccm64_enc2_loop
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+ paddq 16(%esp),%xmm7
+ decl %eax
+.byte 102,15,56,221,208
+.byte 102,15,56,221,216
+ leal 16(%esi),%esi
+ xorps %xmm2,%xmm6
+ movdqa %xmm7,%xmm2
+ movups %xmm6,(%edi)
+.byte 102,15,56,0,213
+ leal 16(%edi),%edi
+ jnz L028ccm64_enc_outer
+ movl 48(%esp),%esp
+ movl 40(%esp),%edi
+ movups %xmm3,(%edi)
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.globl _aesni_ccm64_decrypt_blocks
+.private_extern _aesni_ccm64_decrypt_blocks
+.align 4
+_aesni_ccm64_decrypt_blocks:
+L_aesni_ccm64_decrypt_blocks_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ movl 20(%esp),%esi
+ movl 24(%esp),%edi
+ movl 28(%esp),%eax
+ movl 32(%esp),%edx
+ movl 36(%esp),%ebx
+ movl 40(%esp),%ecx
+ movl %esp,%ebp
+ subl $60,%esp
+ andl $-16,%esp
+ movl %ebp,48(%esp)
+ movdqu (%ebx),%xmm7
+ movdqu (%ecx),%xmm3
+ movl 240(%edx),%ecx
+ movl $202182159,(%esp)
+ movl $134810123,4(%esp)
+ movl $67438087,8(%esp)
+ movl $66051,12(%esp)
+ movl $1,%ebx
+ xorl %ebp,%ebp
+ movl %ebx,16(%esp)
+ movl %ebp,20(%esp)
+ movl %ebp,24(%esp)
+ movl %ebp,28(%esp)
+ movdqa (%esp),%xmm5
+ movdqa %xmm7,%xmm2
+ movl %edx,%ebp
+ movl %ecx,%ebx
+.byte 102,15,56,0,253
+ movups (%edx),%xmm0
+ movups 16(%edx),%xmm1
+ leal 32(%edx),%edx
+ xorps %xmm0,%xmm2
+L030enc1_loop_5:
+.byte 102,15,56,220,209
+ decl %ecx
+ movups (%edx),%xmm1
+ leal 16(%edx),%edx
+ jnz L030enc1_loop_5
+.byte 102,15,56,221,209
+ shll $4,%ebx
+ movl $16,%ecx
+ movups (%esi),%xmm6
+ paddq 16(%esp),%xmm7
+ leal 16(%esi),%esi
+ subl %ebx,%ecx
+ leal 32(%ebp,%ebx,1),%edx
+ movl %ecx,%ebx
+ jmp L031ccm64_dec_outer
+.align 4,0x90
+L031ccm64_dec_outer:
+ xorps %xmm2,%xmm6
+ movdqa %xmm7,%xmm2
+ movups %xmm6,(%edi)
+ leal 16(%edi),%edi
+.byte 102,15,56,0,213
+ subl $1,%eax
+ jz L032ccm64_dec_break
+ movups (%ebp),%xmm0
+ movl %ebx,%ecx
+ movups 16(%ebp),%xmm1
+ xorps %xmm0,%xmm6
+ xorps %xmm0,%xmm2
+ xorps %xmm6,%xmm3
+ movups 32(%ebp),%xmm0
+L033ccm64_dec2_loop:
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+ movups (%edx,%ecx,1),%xmm1
+ addl $32,%ecx
+.byte 102,15,56,220,208
+.byte 102,15,56,220,216
+ movups -16(%edx,%ecx,1),%xmm0
+ jnz L033ccm64_dec2_loop
+ movups (%esi),%xmm6
+ paddq 16(%esp),%xmm7
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+.byte 102,15,56,221,208
+.byte 102,15,56,221,216
+ leal 16(%esi),%esi
+ jmp L031ccm64_dec_outer
+.align 4,0x90
+L032ccm64_dec_break:
+ movl 240(%ebp),%ecx
+ movl %ebp,%edx
+ movups (%edx),%xmm0
+ movups 16(%edx),%xmm1
+ xorps %xmm0,%xmm6
+ leal 32(%edx),%edx
+ xorps %xmm6,%xmm3
+L034enc1_loop_6:
+.byte 102,15,56,220,217
+ decl %ecx
+ movups (%edx),%xmm1
+ leal 16(%edx),%edx
+ jnz L034enc1_loop_6
+.byte 102,15,56,221,217
+ movl 48(%esp),%esp
+ movl 40(%esp),%edi
+ movups %xmm3,(%edi)
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.globl _aesni_ctr32_encrypt_blocks
+.private_extern _aesni_ctr32_encrypt_blocks
+.align 4
+_aesni_ctr32_encrypt_blocks:
+L_aesni_ctr32_encrypt_blocks_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ movl 20(%esp),%esi
+ movl 24(%esp),%edi
+ movl 28(%esp),%eax
+ movl 32(%esp),%edx
+ movl 36(%esp),%ebx
+ movl %esp,%ebp
+ subl $88,%esp
+ andl $-16,%esp
+ movl %ebp,80(%esp)
+ cmpl $1,%eax
+ je L035ctr32_one_shortcut
+ movdqu (%ebx),%xmm7
+ movl $202182159,(%esp)
+ movl $134810123,4(%esp)
+ movl $67438087,8(%esp)
+ movl $66051,12(%esp)
+ movl $6,%ecx
+ xorl %ebp,%ebp
+ movl %ecx,16(%esp)
+ movl %ecx,20(%esp)
+ movl %ecx,24(%esp)
+ movl %ebp,28(%esp)
+.byte 102,15,58,22,251,3
+.byte 102,15,58,34,253,3
+ movl 240(%edx),%ecx
+ bswap %ebx
+ pxor %xmm0,%xmm0
+ pxor %xmm1,%xmm1
+ movdqa (%esp),%xmm2
+.byte 102,15,58,34,195,0
+ leal 3(%ebx),%ebp
+.byte 102,15,58,34,205,0
+ incl %ebx
+.byte 102,15,58,34,195,1
+ incl %ebp
+.byte 102,15,58,34,205,1
+ incl %ebx
+.byte 102,15,58,34,195,2
+ incl %ebp
+.byte 102,15,58,34,205,2
+ movdqa %xmm0,48(%esp)
+.byte 102,15,56,0,194
+ movdqu (%edx),%xmm6
+ movdqa %xmm1,64(%esp)
+.byte 102,15,56,0,202
+ pshufd $192,%xmm0,%xmm2
+ pshufd $128,%xmm0,%xmm3
+ cmpl $6,%eax
+ jb L036ctr32_tail
+ pxor %xmm6,%xmm7
+ shll $4,%ecx
+ movl $16,%ebx
+ movdqa %xmm7,32(%esp)
+ movl %edx,%ebp
+ subl %ecx,%ebx
+ leal 32(%edx,%ecx,1),%edx
+ subl $6,%eax
+ jmp L037ctr32_loop6
+.align 4,0x90
+L037ctr32_loop6:
+ pshufd $64,%xmm0,%xmm4
+ movdqa 32(%esp),%xmm0
+ pshufd $192,%xmm1,%xmm5
+ pxor %xmm0,%xmm2
+ pshufd $128,%xmm1,%xmm6
+ pxor %xmm0,%xmm3
+ pshufd $64,%xmm1,%xmm7
+ movups 16(%ebp),%xmm1
+ pxor %xmm0,%xmm4
+ pxor %xmm0,%xmm5
+.byte 102,15,56,220,209
+ pxor %xmm0,%xmm6
+ pxor %xmm0,%xmm7
+.byte 102,15,56,220,217
+ movups 32(%ebp),%xmm0
+ movl %ebx,%ecx
+.byte 102,15,56,220,225
+.byte 102,15,56,220,233
+.byte 102,15,56,220,241
+.byte 102,15,56,220,249
+ call L_aesni_encrypt6_enter
+ movups (%esi),%xmm1
+ movups 16(%esi),%xmm0
+ xorps %xmm1,%xmm2
+ movups 32(%esi),%xmm1
+ xorps %xmm0,%xmm3
+ movups %xmm2,(%edi)
+ movdqa 16(%esp),%xmm0
+ xorps %xmm1,%xmm4
+ movdqa 64(%esp),%xmm1
+ movups %xmm3,16(%edi)
+ movups %xmm4,32(%edi)
+ paddd %xmm0,%xmm1
+ paddd 48(%esp),%xmm0
+ movdqa (%esp),%xmm2
+ movups 48(%esi),%xmm3
+ movups 64(%esi),%xmm4
+ xorps %xmm3,%xmm5
+ movups 80(%esi),%xmm3
+ leal 96(%esi),%esi
+ movdqa %xmm0,48(%esp)
+.byte 102,15,56,0,194
+ xorps %xmm4,%xmm6
+ movups %xmm5,48(%edi)
+ xorps %xmm3,%xmm7
+ movdqa %xmm1,64(%esp)
+.byte 102,15,56,0,202
+ movups %xmm6,64(%edi)
+ pshufd $192,%xmm0,%xmm2
+ movups %xmm7,80(%edi)
+ leal 96(%edi),%edi
+ pshufd $128,%xmm0,%xmm3
+ subl $6,%eax
+ jnc L037ctr32_loop6
+ addl $6,%eax
+ jz L038ctr32_ret
+ movdqu (%ebp),%xmm7
+ movl %ebp,%edx
+ pxor 32(%esp),%xmm7
+ movl 240(%ebp),%ecx
+L036ctr32_tail:
+ por %xmm7,%xmm2
+ cmpl $2,%eax
+ jb L039ctr32_one
+ pshufd $64,%xmm0,%xmm4
+ por %xmm7,%xmm3
+ je L040ctr32_two
+ pshufd $192,%xmm1,%xmm5
+ por %xmm7,%xmm4
+ cmpl $4,%eax
+ jb L041ctr32_three
+ pshufd $128,%xmm1,%xmm6
+ por %xmm7,%xmm5
+ je L042ctr32_four
+ por %xmm7,%xmm6
+ call __aesni_encrypt6
+ movups (%esi),%xmm1
+ movups 16(%esi),%xmm0
+ xorps %xmm1,%xmm2
+ movups 32(%esi),%xmm1
+ xorps %xmm0,%xmm3
+ movups 48(%esi),%xmm0
+ xorps %xmm1,%xmm4
+ movups 64(%esi),%xmm1
+ xorps %xmm0,%xmm5
+ movups %xmm2,(%edi)
+ xorps %xmm1,%xmm6
+ movups %xmm3,16(%edi)
+ movups %xmm4,32(%edi)
+ movups %xmm5,48(%edi)
+ movups %xmm6,64(%edi)
+ jmp L038ctr32_ret
+.align 4,0x90
+L035ctr32_one_shortcut:
+ movups (%ebx),%xmm2
+ movl 240(%edx),%ecx
+L039ctr32_one:
+ movups (%edx),%xmm0
+ movups 16(%edx),%xmm1
+ leal 32(%edx),%edx
+ xorps %xmm0,%xmm2
+L043enc1_loop_7:
+.byte 102,15,56,220,209
+ decl %ecx
+ movups (%edx),%xmm1
+ leal 16(%edx),%edx
+ jnz L043enc1_loop_7
+.byte 102,15,56,221,209
+ movups (%esi),%xmm6
+ xorps %xmm2,%xmm6
+ movups %xmm6,(%edi)
+ jmp L038ctr32_ret
+.align 4,0x90
+L040ctr32_two:
+ call __aesni_encrypt2
+ movups (%esi),%xmm5
+ movups 16(%esi),%xmm6
+ xorps %xmm5,%xmm2
+ xorps %xmm6,%xmm3
+ movups %xmm2,(%edi)
+ movups %xmm3,16(%edi)
+ jmp L038ctr32_ret
+.align 4,0x90
+L041ctr32_three:
+ call __aesni_encrypt3
+ movups (%esi),%xmm5
+ movups 16(%esi),%xmm6
+ xorps %xmm5,%xmm2
+ movups 32(%esi),%xmm7
+ xorps %xmm6,%xmm3
+ movups %xmm2,(%edi)
+ xorps %xmm7,%xmm4
+ movups %xmm3,16(%edi)
+ movups %xmm4,32(%edi)
+ jmp L038ctr32_ret
+.align 4,0x90
+L042ctr32_four:
+ call __aesni_encrypt4
+ movups (%esi),%xmm6
+ movups 16(%esi),%xmm7
+ movups 32(%esi),%xmm1
+ xorps %xmm6,%xmm2
+ movups 48(%esi),%xmm0
+ xorps %xmm7,%xmm3
+ movups %xmm2,(%edi)
+ xorps %xmm1,%xmm4
+ movups %xmm3,16(%edi)
+ xorps %xmm0,%xmm5
+ movups %xmm4,32(%edi)
+ movups %xmm5,48(%edi)
+L038ctr32_ret:
+ movl 80(%esp),%esp
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.globl _aesni_xts_encrypt
+.private_extern _aesni_xts_encrypt
+.align 4
+_aesni_xts_encrypt:
+L_aesni_xts_encrypt_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ movl 36(%esp),%edx
+ movl 40(%esp),%esi
+ movl 240(%edx),%ecx
+ movups (%esi),%xmm2
+ movups (%edx),%xmm0
+ movups 16(%edx),%xmm1
+ leal 32(%edx),%edx
+ xorps %xmm0,%xmm2
+L044enc1_loop_8:
+.byte 102,15,56,220,209
+ decl %ecx
+ movups (%edx),%xmm1
+ leal 16(%edx),%edx
+ jnz L044enc1_loop_8
+.byte 102,15,56,221,209
+ movl 20(%esp),%esi
+ movl 24(%esp),%edi
+ movl 28(%esp),%eax
+ movl 32(%esp),%edx
+ movl %esp,%ebp
+ subl $120,%esp
+ movl 240(%edx),%ecx
+ andl $-16,%esp
+ movl $135,96(%esp)
+ movl $0,100(%esp)
+ movl $1,104(%esp)
+ movl $0,108(%esp)
+ movl %eax,112(%esp)
+ movl %ebp,116(%esp)
+ movdqa %xmm2,%xmm1
+ pxor %xmm0,%xmm0
+ movdqa 96(%esp),%xmm3
+ pcmpgtd %xmm1,%xmm0
+ andl $-16,%eax
+ movl %edx,%ebp
+ movl %ecx,%ebx
+ subl $96,%eax
+ jc L045xts_enc_short
+ shll $4,%ecx
+ movl $16,%ebx
+ subl %ecx,%ebx
+ leal 32(%edx,%ecx,1),%edx
+ jmp L046xts_enc_loop6
+.align 4,0x90
+L046xts_enc_loop6:
+ pshufd $19,%xmm0,%xmm2
+ pxor %xmm0,%xmm0
+ movdqa %xmm1,(%esp)
+ paddq %xmm1,%xmm1
+ pand %xmm3,%xmm2
+ pcmpgtd %xmm1,%xmm0
+ pxor %xmm2,%xmm1
+ pshufd $19,%xmm0,%xmm2
+ pxor %xmm0,%xmm0
+ movdqa %xmm1,16(%esp)
+ paddq %xmm1,%xmm1
+ pand %xmm3,%xmm2
+ pcmpgtd %xmm1,%xmm0
+ pxor %xmm2,%xmm1
+ pshufd $19,%xmm0,%xmm2
+ pxor %xmm0,%xmm0
+ movdqa %xmm1,32(%esp)
+ paddq %xmm1,%xmm1
+ pand %xmm3,%xmm2
+ pcmpgtd %xmm1,%xmm0
+ pxor %xmm2,%xmm1
+ pshufd $19,%xmm0,%xmm2
+ pxor %xmm0,%xmm0
+ movdqa %xmm1,48(%esp)
+ paddq %xmm1,%xmm1
+ pand %xmm3,%xmm2
+ pcmpgtd %xmm1,%xmm0
+ pxor %xmm2,%xmm1
+ pshufd $19,%xmm0,%xmm7
+ movdqa %xmm1,64(%esp)
+ paddq %xmm1,%xmm1
+ movups (%ebp),%xmm0
+ pand %xmm3,%xmm7
+ movups (%esi),%xmm2
+ pxor %xmm1,%xmm7
+ movl %ebx,%ecx
+ movdqu 16(%esi),%xmm3
+ xorps %xmm0,%xmm2
+ movdqu 32(%esi),%xmm4
+ pxor %xmm0,%xmm3
+ movdqu 48(%esi),%xmm5
+ pxor %xmm0,%xmm4
+ movdqu 64(%esi),%xmm6
+ pxor %xmm0,%xmm5
+ movdqu 80(%esi),%xmm1
+ pxor %xmm0,%xmm6
+ leal 96(%esi),%esi
+ pxor (%esp),%xmm2
+ movdqa %xmm7,80(%esp)
+ pxor %xmm1,%xmm7
+ movups 16(%ebp),%xmm1
+ pxor 16(%esp),%xmm3
+ pxor 32(%esp),%xmm4
+.byte 102,15,56,220,209
+ pxor 48(%esp),%xmm5
+ pxor 64(%esp),%xmm6
+.byte 102,15,56,220,217
+ pxor %xmm0,%xmm7
+ movups 32(%ebp),%xmm0
+.byte 102,15,56,220,225
+.byte 102,15,56,220,233
+.byte 102,15,56,220,241
+.byte 102,15,56,220,249
+ call L_aesni_encrypt6_enter
+ movdqa 80(%esp),%xmm1
+ pxor %xmm0,%xmm0
+ xorps (%esp),%xmm2
+ pcmpgtd %xmm1,%xmm0
+ xorps 16(%esp),%xmm3
+ movups %xmm2,(%edi)
+ xorps 32(%esp),%xmm4
+ movups %xmm3,16(%edi)
+ xorps 48(%esp),%xmm5
+ movups %xmm4,32(%edi)
+ xorps 64(%esp),%xmm6
+ movups %xmm5,48(%edi)
+ xorps %xmm1,%xmm7
+ movups %xmm6,64(%edi)
+ pshufd $19,%xmm0,%xmm2
+ movups %xmm7,80(%edi)
+ leal 96(%edi),%edi
+ movdqa 96(%esp),%xmm3
+ pxor %xmm0,%xmm0
+ paddq %xmm1,%xmm1
+ pand %xmm3,%xmm2
+ pcmpgtd %xmm1,%xmm0
+ pxor %xmm2,%xmm1
+ subl $96,%eax
+ jnc L046xts_enc_loop6
+ movl 240(%ebp),%ecx
+ movl %ebp,%edx
+ movl %ecx,%ebx
+L045xts_enc_short:
+ addl $96,%eax
+ jz L047xts_enc_done6x
+ movdqa %xmm1,%xmm5
+ cmpl $32,%eax
+ jb L048xts_enc_one
+ pshufd $19,%xmm0,%xmm2
+ pxor %xmm0,%xmm0
+ paddq %xmm1,%xmm1
+ pand %xmm3,%xmm2
+ pcmpgtd %xmm1,%xmm0
+ pxor %xmm2,%xmm1
+ je L049xts_enc_two
+ pshufd $19,%xmm0,%xmm2
+ pxor %xmm0,%xmm0
+ movdqa %xmm1,%xmm6
+ paddq %xmm1,%xmm1
+ pand %xmm3,%xmm2
+ pcmpgtd %xmm1,%xmm0
+ pxor %xmm2,%xmm1
+ cmpl $64,%eax
+ jb L050xts_enc_three
+ pshufd $19,%xmm0,%xmm2
+ pxor %xmm0,%xmm0
+ movdqa %xmm1,%xmm7
+ paddq %xmm1,%xmm1
+ pand %xmm3,%xmm2
+ pcmpgtd %xmm1,%xmm0
+ pxor %xmm2,%xmm1
+ movdqa %xmm5,(%esp)
+ movdqa %xmm6,16(%esp)
+ je L051xts_enc_four
+ movdqa %xmm7,32(%esp)
+ pshufd $19,%xmm0,%xmm7
+ movdqa %xmm1,48(%esp)
+ paddq %xmm1,%xmm1
+ pand %xmm3,%xmm7
+ pxor %xmm1,%xmm7
+ movdqu (%esi),%xmm2
+ movdqu 16(%esi),%xmm3
+ movdqu 32(%esi),%xmm4
+ pxor (%esp),%xmm2
+ movdqu 48(%esi),%xmm5
+ pxor 16(%esp),%xmm3
+ movdqu 64(%esi),%xmm6
+ pxor 32(%esp),%xmm4
+ leal 80(%esi),%esi
+ pxor 48(%esp),%xmm5
+ movdqa %xmm7,64(%esp)
+ pxor %xmm7,%xmm6
+ call __aesni_encrypt6
+ movaps 64(%esp),%xmm1
+ xorps (%esp),%xmm2
+ xorps 16(%esp),%xmm3
+ xorps 32(%esp),%xmm4
+ movups %xmm2,(%edi)
+ xorps 48(%esp),%xmm5
+ movups %xmm3,16(%edi)
+ xorps %xmm1,%xmm6
+ movups %xmm4,32(%edi)
+ movups %xmm5,48(%edi)
+ movups %xmm6,64(%edi)
+ leal 80(%edi),%edi
+ jmp L052xts_enc_done
+.align 4,0x90
+L048xts_enc_one:
+ movups (%esi),%xmm2
+ leal 16(%esi),%esi
+ xorps %xmm5,%xmm2
+ movups (%edx),%xmm0
+ movups 16(%edx),%xmm1
+ leal 32(%edx),%edx
+ xorps %xmm0,%xmm2
+L053enc1_loop_9:
+.byte 102,15,56,220,209
+ decl %ecx
+ movups (%edx),%xmm1
+ leal 16(%edx),%edx
+ jnz L053enc1_loop_9
+.byte 102,15,56,221,209
+ xorps %xmm5,%xmm2
+ movups %xmm2,(%edi)
+ leal 16(%edi),%edi
+ movdqa %xmm5,%xmm1
+ jmp L052xts_enc_done
+.align 4,0x90
+L049xts_enc_two:
+ movaps %xmm1,%xmm6
+ movups (%esi),%xmm2
+ movups 16(%esi),%xmm3
+ leal 32(%esi),%esi
+ xorps %xmm5,%xmm2
+ xorps %xmm6,%xmm3
+ call __aesni_encrypt2
+ xorps %xmm5,%xmm2
+ xorps %xmm6,%xmm3
+ movups %xmm2,(%edi)
+ movups %xmm3,16(%edi)
+ leal 32(%edi),%edi
+ movdqa %xmm6,%xmm1
+ jmp L052xts_enc_done
+.align 4,0x90
+L050xts_enc_three:
+ movaps %xmm1,%xmm7
+ movups (%esi),%xmm2
+ movups 16(%esi),%xmm3
+ movups 32(%esi),%xmm4
+ leal 48(%esi),%esi
+ xorps %xmm5,%xmm2
+ xorps %xmm6,%xmm3
+ xorps %xmm7,%xmm4
+ call __aesni_encrypt3
+ xorps %xmm5,%xmm2
+ xorps %xmm6,%xmm3
+ xorps %xmm7,%xmm4
+ movups %xmm2,(%edi)
+ movups %xmm3,16(%edi)
+ movups %xmm4,32(%edi)
+ leal 48(%edi),%edi
+ movdqa %xmm7,%xmm1
+ jmp L052xts_enc_done
+.align 4,0x90
+L051xts_enc_four:
+ movaps %xmm1,%xmm6
+ movups (%esi),%xmm2
+ movups 16(%esi),%xmm3
+ movups 32(%esi),%xmm4
+ xorps (%esp),%xmm2
+ movups 48(%esi),%xmm5
+ leal 64(%esi),%esi
+ xorps 16(%esp),%xmm3
+ xorps %xmm7,%xmm4
+ xorps %xmm6,%xmm5
+ call __aesni_encrypt4
+ xorps (%esp),%xmm2
+ xorps 16(%esp),%xmm3
+ xorps %xmm7,%xmm4
+ movups %xmm2,(%edi)
+ xorps %xmm6,%xmm5
+ movups %xmm3,16(%edi)
+ movups %xmm4,32(%edi)
+ movups %xmm5,48(%edi)
+ leal 64(%edi),%edi
+ movdqa %xmm6,%xmm1
+ jmp L052xts_enc_done
+.align 4,0x90
+L047xts_enc_done6x:
+ movl 112(%esp),%eax
+ andl $15,%eax
+ jz L054xts_enc_ret
+ movdqa %xmm1,%xmm5
+ movl %eax,112(%esp)
+ jmp L055xts_enc_steal
+.align 4,0x90
+L052xts_enc_done:
+ movl 112(%esp),%eax
+ pxor %xmm0,%xmm0
+ andl $15,%eax
+ jz L054xts_enc_ret
+ pcmpgtd %xmm1,%xmm0
+ movl %eax,112(%esp)
+ pshufd $19,%xmm0,%xmm5
+ paddq %xmm1,%xmm1
+ pand 96(%esp),%xmm5
+ pxor %xmm1,%xmm5
+L055xts_enc_steal:
+ movzbl (%esi),%ecx
+ movzbl -16(%edi),%edx
+ leal 1(%esi),%esi
+ movb %cl,-16(%edi)
+ movb %dl,(%edi)
+ leal 1(%edi),%edi
+ subl $1,%eax
+ jnz L055xts_enc_steal
+ subl 112(%esp),%edi
+ movl %ebp,%edx
+ movl %ebx,%ecx
+ movups -16(%edi),%xmm2
+ xorps %xmm5,%xmm2
+ movups (%edx),%xmm0
+ movups 16(%edx),%xmm1
+ leal 32(%edx),%edx
+ xorps %xmm0,%xmm2
+L056enc1_loop_10:
+.byte 102,15,56,220,209
+ decl %ecx
+ movups (%edx),%xmm1
+ leal 16(%edx),%edx
+ jnz L056enc1_loop_10
+.byte 102,15,56,221,209
+ xorps %xmm5,%xmm2
+ movups %xmm2,-16(%edi)
+L054xts_enc_ret:
+ movl 116(%esp),%esp
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.globl _aesni_xts_decrypt
+.private_extern _aesni_xts_decrypt
+.align 4
+_aesni_xts_decrypt:
+L_aesni_xts_decrypt_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ movl 36(%esp),%edx
+ movl 40(%esp),%esi
+ movl 240(%edx),%ecx
+ movups (%esi),%xmm2
+ movups (%edx),%xmm0
+ movups 16(%edx),%xmm1
+ leal 32(%edx),%edx
+ xorps %xmm0,%xmm2
+L057enc1_loop_11:
+.byte 102,15,56,220,209
+ decl %ecx
+ movups (%edx),%xmm1
+ leal 16(%edx),%edx
+ jnz L057enc1_loop_11
+.byte 102,15,56,221,209
+ movl 20(%esp),%esi
+ movl 24(%esp),%edi
+ movl 28(%esp),%eax
+ movl 32(%esp),%edx
+ movl %esp,%ebp
+ subl $120,%esp
+ andl $-16,%esp
+ xorl %ebx,%ebx
+ testl $15,%eax
+ setnz %bl
+ shll $4,%ebx
+ subl %ebx,%eax
+ movl $135,96(%esp)
+ movl $0,100(%esp)
+ movl $1,104(%esp)
+ movl $0,108(%esp)
+ movl %eax,112(%esp)
+ movl %ebp,116(%esp)
+ movl 240(%edx),%ecx
+ movl %edx,%ebp
+ movl %ecx,%ebx
+ movdqa %xmm2,%xmm1
+ pxor %xmm0,%xmm0
+ movdqa 96(%esp),%xmm3
+ pcmpgtd %xmm1,%xmm0
+ andl $-16,%eax
+ subl $96,%eax
+ jc L058xts_dec_short
+ shll $4,%ecx
+ movl $16,%ebx
+ subl %ecx,%ebx
+ leal 32(%edx,%ecx,1),%edx
+ jmp L059xts_dec_loop6
+.align 4,0x90
+L059xts_dec_loop6:
+ pshufd $19,%xmm0,%xmm2
+ pxor %xmm0,%xmm0
+ movdqa %xmm1,(%esp)
+ paddq %xmm1,%xmm1
+ pand %xmm3,%xmm2
+ pcmpgtd %xmm1,%xmm0
+ pxor %xmm2,%xmm1
+ pshufd $19,%xmm0,%xmm2
+ pxor %xmm0,%xmm0
+ movdqa %xmm1,16(%esp)
+ paddq %xmm1,%xmm1
+ pand %xmm3,%xmm2
+ pcmpgtd %xmm1,%xmm0
+ pxor %xmm2,%xmm1
+ pshufd $19,%xmm0,%xmm2
+ pxor %xmm0,%xmm0
+ movdqa %xmm1,32(%esp)
+ paddq %xmm1,%xmm1
+ pand %xmm3,%xmm2
+ pcmpgtd %xmm1,%xmm0
+ pxor %xmm2,%xmm1
+ pshufd $19,%xmm0,%xmm2
+ pxor %xmm0,%xmm0
+ movdqa %xmm1,48(%esp)
+ paddq %xmm1,%xmm1
+ pand %xmm3,%xmm2
+ pcmpgtd %xmm1,%xmm0
+ pxor %xmm2,%xmm1
+ pshufd $19,%xmm0,%xmm7
+ movdqa %xmm1,64(%esp)
+ paddq %xmm1,%xmm1
+ movups (%ebp),%xmm0
+ pand %xmm3,%xmm7
+ movups (%esi),%xmm2
+ pxor %xmm1,%xmm7
+ movl %ebx,%ecx
+ movdqu 16(%esi),%xmm3
+ xorps %xmm0,%xmm2
+ movdqu 32(%esi),%xmm4
+ pxor %xmm0,%xmm3
+ movdqu 48(%esi),%xmm5
+ pxor %xmm0,%xmm4
+ movdqu 64(%esi),%xmm6
+ pxor %xmm0,%xmm5
+ movdqu 80(%esi),%xmm1
+ pxor %xmm0,%xmm6
+ leal 96(%esi),%esi
+ pxor (%esp),%xmm2
+ movdqa %xmm7,80(%esp)
+ pxor %xmm1,%xmm7
+ movups 16(%ebp),%xmm1
+ pxor 16(%esp),%xmm3
+ pxor 32(%esp),%xmm4
+.byte 102,15,56,222,209
+ pxor 48(%esp),%xmm5
+ pxor 64(%esp),%xmm6
+.byte 102,15,56,222,217
+ pxor %xmm0,%xmm7
+ movups 32(%ebp),%xmm0
+.byte 102,15,56,222,225
+.byte 102,15,56,222,233
+.byte 102,15,56,222,241
+.byte 102,15,56,222,249
+ call L_aesni_decrypt6_enter
+ movdqa 80(%esp),%xmm1
+ pxor %xmm0,%xmm0
+ xorps (%esp),%xmm2
+ pcmpgtd %xmm1,%xmm0
+ xorps 16(%esp),%xmm3
+ movups %xmm2,(%edi)
+ xorps 32(%esp),%xmm4
+ movups %xmm3,16(%edi)
+ xorps 48(%esp),%xmm5
+ movups %xmm4,32(%edi)
+ xorps 64(%esp),%xmm6
+ movups %xmm5,48(%edi)
+ xorps %xmm1,%xmm7
+ movups %xmm6,64(%edi)
+ pshufd $19,%xmm0,%xmm2
+ movups %xmm7,80(%edi)
+ leal 96(%edi),%edi
+ movdqa 96(%esp),%xmm3
+ pxor %xmm0,%xmm0
+ paddq %xmm1,%xmm1
+ pand %xmm3,%xmm2
+ pcmpgtd %xmm1,%xmm0
+ pxor %xmm2,%xmm1
+ subl $96,%eax
+ jnc L059xts_dec_loop6
+ movl 240(%ebp),%ecx
+ movl %ebp,%edx
+ movl %ecx,%ebx
+L058xts_dec_short:
+ addl $96,%eax
+ jz L060xts_dec_done6x
+ movdqa %xmm1,%xmm5
+ cmpl $32,%eax
+ jb L061xts_dec_one
+ pshufd $19,%xmm0,%xmm2
+ pxor %xmm0,%xmm0
+ paddq %xmm1,%xmm1
+ pand %xmm3,%xmm2
+ pcmpgtd %xmm1,%xmm0
+ pxor %xmm2,%xmm1
+ je L062xts_dec_two
+ pshufd $19,%xmm0,%xmm2
+ pxor %xmm0,%xmm0
+ movdqa %xmm1,%xmm6
+ paddq %xmm1,%xmm1
+ pand %xmm3,%xmm2
+ pcmpgtd %xmm1,%xmm0
+ pxor %xmm2,%xmm1
+ cmpl $64,%eax
+ jb L063xts_dec_three
+ pshufd $19,%xmm0,%xmm2
+ pxor %xmm0,%xmm0
+ movdqa %xmm1,%xmm7
+ paddq %xmm1,%xmm1
+ pand %xmm3,%xmm2
+ pcmpgtd %xmm1,%xmm0
+ pxor %xmm2,%xmm1
+ movdqa %xmm5,(%esp)
+ movdqa %xmm6,16(%esp)
+ je L064xts_dec_four
+ movdqa %xmm7,32(%esp)
+ pshufd $19,%xmm0,%xmm7
+ movdqa %xmm1,48(%esp)
+ paddq %xmm1,%xmm1
+ pand %xmm3,%xmm7
+ pxor %xmm1,%xmm7
+ movdqu (%esi),%xmm2
+ movdqu 16(%esi),%xmm3
+ movdqu 32(%esi),%xmm4
+ pxor (%esp),%xmm2
+ movdqu 48(%esi),%xmm5
+ pxor 16(%esp),%xmm3
+ movdqu 64(%esi),%xmm6
+ pxor 32(%esp),%xmm4
+ leal 80(%esi),%esi
+ pxor 48(%esp),%xmm5
+ movdqa %xmm7,64(%esp)
+ pxor %xmm7,%xmm6
+ call __aesni_decrypt6
+ movaps 64(%esp),%xmm1
+ xorps (%esp),%xmm2
+ xorps 16(%esp),%xmm3
+ xorps 32(%esp),%xmm4
+ movups %xmm2,(%edi)
+ xorps 48(%esp),%xmm5
+ movups %xmm3,16(%edi)
+ xorps %xmm1,%xmm6
+ movups %xmm4,32(%edi)
+ movups %xmm5,48(%edi)
+ movups %xmm6,64(%edi)
+ leal 80(%edi),%edi
+ jmp L065xts_dec_done
+.align 4,0x90
+L061xts_dec_one:
+ movups (%esi),%xmm2
+ leal 16(%esi),%esi
+ xorps %xmm5,%xmm2
+ movups (%edx),%xmm0
+ movups 16(%edx),%xmm1
+ leal 32(%edx),%edx
+ xorps %xmm0,%xmm2
+L066dec1_loop_12:
+.byte 102,15,56,222,209
+ decl %ecx
+ movups (%edx),%xmm1
+ leal 16(%edx),%edx
+ jnz L066dec1_loop_12
+.byte 102,15,56,223,209
+ xorps %xmm5,%xmm2
+ movups %xmm2,(%edi)
+ leal 16(%edi),%edi
+ movdqa %xmm5,%xmm1
+ jmp L065xts_dec_done
+.align 4,0x90
+L062xts_dec_two:
+ movaps %xmm1,%xmm6
+ movups (%esi),%xmm2
+ movups 16(%esi),%xmm3
+ leal 32(%esi),%esi
+ xorps %xmm5,%xmm2
+ xorps %xmm6,%xmm3
+ call __aesni_decrypt2
+ xorps %xmm5,%xmm2
+ xorps %xmm6,%xmm3
+ movups %xmm2,(%edi)
+ movups %xmm3,16(%edi)
+ leal 32(%edi),%edi
+ movdqa %xmm6,%xmm1
+ jmp L065xts_dec_done
+.align 4,0x90
+L063xts_dec_three:
+ movaps %xmm1,%xmm7
+ movups (%esi),%xmm2
+ movups 16(%esi),%xmm3
+ movups 32(%esi),%xmm4
+ leal 48(%esi),%esi
+ xorps %xmm5,%xmm2
+ xorps %xmm6,%xmm3
+ xorps %xmm7,%xmm4
+ call __aesni_decrypt3
+ xorps %xmm5,%xmm2
+ xorps %xmm6,%xmm3
+ xorps %xmm7,%xmm4
+ movups %xmm2,(%edi)
+ movups %xmm3,16(%edi)
+ movups %xmm4,32(%edi)
+ leal 48(%edi),%edi
+ movdqa %xmm7,%xmm1
+ jmp L065xts_dec_done
+.align 4,0x90
+L064xts_dec_four:
+ movaps %xmm1,%xmm6
+ movups (%esi),%xmm2
+ movups 16(%esi),%xmm3
+ movups 32(%esi),%xmm4
+ xorps (%esp),%xmm2
+ movups 48(%esi),%xmm5
+ leal 64(%esi),%esi
+ xorps 16(%esp),%xmm3
+ xorps %xmm7,%xmm4
+ xorps %xmm6,%xmm5
+ call __aesni_decrypt4
+ xorps (%esp),%xmm2
+ xorps 16(%esp),%xmm3
+ xorps %xmm7,%xmm4
+ movups %xmm2,(%edi)
+ xorps %xmm6,%xmm5
+ movups %xmm3,16(%edi)
+ movups %xmm4,32(%edi)
+ movups %xmm5,48(%edi)
+ leal 64(%edi),%edi
+ movdqa %xmm6,%xmm1
+ jmp L065xts_dec_done
+.align 4,0x90
+L060xts_dec_done6x:
+ movl 112(%esp),%eax
+ andl $15,%eax
+ jz L067xts_dec_ret
+ movl %eax,112(%esp)
+ jmp L068xts_dec_only_one_more
+.align 4,0x90
+L065xts_dec_done:
+ movl 112(%esp),%eax
+ pxor %xmm0,%xmm0
+ andl $15,%eax
+ jz L067xts_dec_ret
+ pcmpgtd %xmm1,%xmm0
+ movl %eax,112(%esp)
+ pshufd $19,%xmm0,%xmm2
+ pxor %xmm0,%xmm0
+ movdqa 96(%esp),%xmm3
+ paddq %xmm1,%xmm1
+ pand %xmm3,%xmm2
+ pcmpgtd %xmm1,%xmm0
+ pxor %xmm2,%xmm1
+L068xts_dec_only_one_more:
+ pshufd $19,%xmm0,%xmm5
+ movdqa %xmm1,%xmm6
+ paddq %xmm1,%xmm1
+ pand %xmm3,%xmm5
+ pxor %xmm1,%xmm5
+ movl %ebp,%edx
+ movl %ebx,%ecx
+ movups (%esi),%xmm2
+ xorps %xmm5,%xmm2
+ movups (%edx),%xmm0
+ movups 16(%edx),%xmm1
+ leal 32(%edx),%edx
+ xorps %xmm0,%xmm2
+L069dec1_loop_13:
+.byte 102,15,56,222,209
+ decl %ecx
+ movups (%edx),%xmm1
+ leal 16(%edx),%edx
+ jnz L069dec1_loop_13
+.byte 102,15,56,223,209
+ xorps %xmm5,%xmm2
+ movups %xmm2,(%edi)
+L070xts_dec_steal:
+ movzbl 16(%esi),%ecx
+ movzbl (%edi),%edx
+ leal 1(%esi),%esi
+ movb %cl,(%edi)
+ movb %dl,16(%edi)
+ leal 1(%edi),%edi
+ subl $1,%eax
+ jnz L070xts_dec_steal
+ subl 112(%esp),%edi
+ movl %ebp,%edx
+ movl %ebx,%ecx
+ movups (%edi),%xmm2
+ xorps %xmm6,%xmm2
+ movups (%edx),%xmm0
+ movups 16(%edx),%xmm1
+ leal 32(%edx),%edx
+ xorps %xmm0,%xmm2
+L071dec1_loop_14:
+.byte 102,15,56,222,209
+ decl %ecx
+ movups (%edx),%xmm1
+ leal 16(%edx),%edx
+ jnz L071dec1_loop_14
+.byte 102,15,56,223,209
+ xorps %xmm6,%xmm2
+ movups %xmm2,(%edi)
+L067xts_dec_ret:
+ movl 116(%esp),%esp
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.globl _aesni_cbc_encrypt
+.private_extern _aesni_cbc_encrypt
+.align 4
+_aesni_cbc_encrypt:
+L_aesni_cbc_encrypt_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ movl 20(%esp),%esi
+ movl %esp,%ebx
+ movl 24(%esp),%edi
+ subl $24,%ebx
+ movl 28(%esp),%eax
+ andl $-16,%ebx
+ movl 32(%esp),%edx
+ movl 36(%esp),%ebp
+ testl %eax,%eax
+ jz L072cbc_abort
+ cmpl $0,40(%esp)
+ xchgl %esp,%ebx
+ movups (%ebp),%xmm7
+ movl 240(%edx),%ecx
+ movl %edx,%ebp
+ movl %ebx,16(%esp)
+ movl %ecx,%ebx
+ je L073cbc_decrypt
+ movaps %xmm7,%xmm2
+ cmpl $16,%eax
+ jb L074cbc_enc_tail
+ subl $16,%eax
+ jmp L075cbc_enc_loop
+.align 4,0x90
+L075cbc_enc_loop:
+ movups (%esi),%xmm7
+ leal 16(%esi),%esi
+ movups (%edx),%xmm0
+ movups 16(%edx),%xmm1
+ xorps %xmm0,%xmm7
+ leal 32(%edx),%edx
+ xorps %xmm7,%xmm2
+L076enc1_loop_15:
+.byte 102,15,56,220,209
+ decl %ecx
+ movups (%edx),%xmm1
+ leal 16(%edx),%edx
+ jnz L076enc1_loop_15
+.byte 102,15,56,221,209
+ movl %ebx,%ecx
+ movl %ebp,%edx
+ movups %xmm2,(%edi)
+ leal 16(%edi),%edi
+ subl $16,%eax
+ jnc L075cbc_enc_loop
+ addl $16,%eax
+ jnz L074cbc_enc_tail
+ movaps %xmm2,%xmm7
+ jmp L077cbc_ret
+L074cbc_enc_tail:
+ movl %eax,%ecx
+.long 2767451785
+ movl $16,%ecx
+ subl %eax,%ecx
+ xorl %eax,%eax
+.long 2868115081
+ leal -16(%edi),%edi
+ movl %ebx,%ecx
+ movl %edi,%esi
+ movl %ebp,%edx
+ jmp L075cbc_enc_loop
+.align 4,0x90
+L073cbc_decrypt:
+ cmpl $80,%eax
+ jbe L078cbc_dec_tail
+ movaps %xmm7,(%esp)
+ subl $80,%eax
+ jmp L079cbc_dec_loop6_enter
+.align 4,0x90
+L080cbc_dec_loop6:
+ movaps %xmm0,(%esp)
+ movups %xmm7,(%edi)
+ leal 16(%edi),%edi
+L079cbc_dec_loop6_enter:
+ movdqu (%esi),%xmm2
+ movdqu 16(%esi),%xmm3
+ movdqu 32(%esi),%xmm4
+ movdqu 48(%esi),%xmm5
+ movdqu 64(%esi),%xmm6
+ movdqu 80(%esi),%xmm7
+ call __aesni_decrypt6
+ movups (%esi),%xmm1
+ movups 16(%esi),%xmm0
+ xorps (%esp),%xmm2
+ xorps %xmm1,%xmm3
+ movups 32(%esi),%xmm1
+ xorps %xmm0,%xmm4
+ movups 48(%esi),%xmm0
+ xorps %xmm1,%xmm5
+ movups 64(%esi),%xmm1
+ xorps %xmm0,%xmm6
+ movups 80(%esi),%xmm0
+ xorps %xmm1,%xmm7
+ movups %xmm2,(%edi)
+ movups %xmm3,16(%edi)
+ leal 96(%esi),%esi
+ movups %xmm4,32(%edi)
+ movl %ebx,%ecx
+ movups %xmm5,48(%edi)
+ movl %ebp,%edx
+ movups %xmm6,64(%edi)
+ leal 80(%edi),%edi
+ subl $96,%eax
+ ja L080cbc_dec_loop6
+ movaps %xmm7,%xmm2
+ movaps %xmm0,%xmm7
+ addl $80,%eax
+ jle L081cbc_dec_tail_collected
+ movups %xmm2,(%edi)
+ leal 16(%edi),%edi
+L078cbc_dec_tail:
+ movups (%esi),%xmm2
+ movaps %xmm2,%xmm6
+ cmpl $16,%eax
+ jbe L082cbc_dec_one
+ movups 16(%esi),%xmm3
+ movaps %xmm3,%xmm5
+ cmpl $32,%eax
+ jbe L083cbc_dec_two
+ movups 32(%esi),%xmm4
+ cmpl $48,%eax
+ jbe L084cbc_dec_three
+ movups 48(%esi),%xmm5
+ cmpl $64,%eax
+ jbe L085cbc_dec_four
+ movups 64(%esi),%xmm6
+ movaps %xmm7,(%esp)
+ movups (%esi),%xmm2
+ xorps %xmm7,%xmm7
+ call __aesni_decrypt6
+ movups (%esi),%xmm1
+ movups 16(%esi),%xmm0
+ xorps (%esp),%xmm2
+ xorps %xmm1,%xmm3
+ movups 32(%esi),%xmm1
+ xorps %xmm0,%xmm4
+ movups 48(%esi),%xmm0
+ xorps %xmm1,%xmm5
+ movups 64(%esi),%xmm7
+ xorps %xmm0,%xmm6
+ movups %xmm2,(%edi)
+ movups %xmm3,16(%edi)
+ movups %xmm4,32(%edi)
+ movups %xmm5,48(%edi)
+ leal 64(%edi),%edi
+ movaps %xmm6,%xmm2
+ subl $80,%eax
+ jmp L081cbc_dec_tail_collected
+.align 4,0x90
+L082cbc_dec_one:
+ movups (%edx),%xmm0
+ movups 16(%edx),%xmm1
+ leal 32(%edx),%edx
+ xorps %xmm0,%xmm2
+L086dec1_loop_16:
+.byte 102,15,56,222,209
+ decl %ecx
+ movups (%edx),%xmm1
+ leal 16(%edx),%edx
+ jnz L086dec1_loop_16
+.byte 102,15,56,223,209
+ xorps %xmm7,%xmm2
+ movaps %xmm6,%xmm7
+ subl $16,%eax
+ jmp L081cbc_dec_tail_collected
+.align 4,0x90
+L083cbc_dec_two:
+ call __aesni_decrypt2
+ xorps %xmm7,%xmm2
+ xorps %xmm6,%xmm3
+ movups %xmm2,(%edi)
+ movaps %xmm3,%xmm2
+ leal 16(%edi),%edi
+ movaps %xmm5,%xmm7
+ subl $32,%eax
+ jmp L081cbc_dec_tail_collected
+.align 4,0x90
+L084cbc_dec_three:
+ call __aesni_decrypt3
+ xorps %xmm7,%xmm2
+ xorps %xmm6,%xmm3
+ xorps %xmm5,%xmm4
+ movups %xmm2,(%edi)
+ movaps %xmm4,%xmm2
+ movups %xmm3,16(%edi)
+ leal 32(%edi),%edi
+ movups 32(%esi),%xmm7
+ subl $48,%eax
+ jmp L081cbc_dec_tail_collected
+.align 4,0x90
+L085cbc_dec_four:
+ call __aesni_decrypt4
+ movups 16(%esi),%xmm1
+ movups 32(%esi),%xmm0
+ xorps %xmm7,%xmm2
+ movups 48(%esi),%xmm7
+ xorps %xmm6,%xmm3
+ movups %xmm2,(%edi)
+ xorps %xmm1,%xmm4
+ movups %xmm3,16(%edi)
+ xorps %xmm0,%xmm5
+ movups %xmm4,32(%edi)
+ leal 48(%edi),%edi
+ movaps %xmm5,%xmm2
+ subl $64,%eax
+L081cbc_dec_tail_collected:
+ andl $15,%eax
+ jnz L087cbc_dec_tail_partial
+ movups %xmm2,(%edi)
+ jmp L077cbc_ret
+.align 4,0x90
+L087cbc_dec_tail_partial:
+ movaps %xmm2,(%esp)
+ movl $16,%ecx
+ movl %esp,%esi
+ subl %eax,%ecx
+.long 2767451785
+L077cbc_ret:
+ movl 16(%esp),%esp
+ movl 36(%esp),%ebp
+ movups %xmm7,(%ebp)
+L072cbc_abort:
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.private_extern __aesni_set_encrypt_key
+.align 4
+__aesni_set_encrypt_key:
+ testl %eax,%eax
+ jz L088bad_pointer
+ testl %edx,%edx
+ jz L088bad_pointer
+ movups (%eax),%xmm0
+ xorps %xmm4,%xmm4
+ leal 16(%edx),%edx
+ cmpl $256,%ecx
+ je L08914rounds
+ cmpl $192,%ecx
+ je L09012rounds
+ cmpl $128,%ecx
+ jne L091bad_keybits
+.align 4,0x90
+L09210rounds:
+ movl $9,%ecx
+ movups %xmm0,-16(%edx)
+.byte 102,15,58,223,200,1
+ call L093key_128_cold
+.byte 102,15,58,223,200,2
+ call L094key_128
+.byte 102,15,58,223,200,4
+ call L094key_128
+.byte 102,15,58,223,200,8
+ call L094key_128
+.byte 102,15,58,223,200,16
+ call L094key_128
+.byte 102,15,58,223,200,32
+ call L094key_128
+.byte 102,15,58,223,200,64
+ call L094key_128
+.byte 102,15,58,223,200,128
+ call L094key_128
+.byte 102,15,58,223,200,27
+ call L094key_128
+.byte 102,15,58,223,200,54
+ call L094key_128
+ movups %xmm0,(%edx)
+ movl %ecx,80(%edx)
+ xorl %eax,%eax
+ ret
+.align 4,0x90
+L094key_128:
+ movups %xmm0,(%edx)
+ leal 16(%edx),%edx
+L093key_128_cold:
+ shufps $16,%xmm0,%xmm4
+ xorps %xmm4,%xmm0
+ shufps $140,%xmm0,%xmm4
+ xorps %xmm4,%xmm0
+ shufps $255,%xmm1,%xmm1
+ xorps %xmm1,%xmm0
+ ret
+.align 4,0x90
+L09012rounds:
+ movq 16(%eax),%xmm2
+ movl $11,%ecx
+ movups %xmm0,-16(%edx)
+.byte 102,15,58,223,202,1
+ call L095key_192a_cold
+.byte 102,15,58,223,202,2
+ call L096key_192b
+.byte 102,15,58,223,202,4
+ call L097key_192a
+.byte 102,15,58,223,202,8
+ call L096key_192b
+.byte 102,15,58,223,202,16
+ call L097key_192a
+.byte 102,15,58,223,202,32
+ call L096key_192b
+.byte 102,15,58,223,202,64
+ call L097key_192a
+.byte 102,15,58,223,202,128
+ call L096key_192b
+ movups %xmm0,(%edx)
+ movl %ecx,48(%edx)
+ xorl %eax,%eax
+ ret
+.align 4,0x90
+L097key_192a:
+ movups %xmm0,(%edx)
+ leal 16(%edx),%edx
+.align 4,0x90
+L095key_192a_cold:
+ movaps %xmm2,%xmm5
+L098key_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
+ ret
+.align 4,0x90
+L096key_192b:
+ movaps %xmm0,%xmm3
+ shufps $68,%xmm0,%xmm5
+ movups %xmm5,(%edx)
+ shufps $78,%xmm2,%xmm3
+ movups %xmm3,16(%edx)
+ leal 32(%edx),%edx
+ jmp L098key_192b_warm
+.align 4,0x90
+L08914rounds:
+ movups 16(%eax),%xmm2
+ movl $13,%ecx
+ leal 16(%edx),%edx
+ movups %xmm0,-32(%edx)
+ movups %xmm2,-16(%edx)
+.byte 102,15,58,223,202,1
+ call L099key_256a_cold
+.byte 102,15,58,223,200,1
+ call L100key_256b
+.byte 102,15,58,223,202,2
+ call L101key_256a
+.byte 102,15,58,223,200,2
+ call L100key_256b
+.byte 102,15,58,223,202,4
+ call L101key_256a
+.byte 102,15,58,223,200,4
+ call L100key_256b
+.byte 102,15,58,223,202,8
+ call L101key_256a
+.byte 102,15,58,223,200,8
+ call L100key_256b
+.byte 102,15,58,223,202,16
+ call L101key_256a
+.byte 102,15,58,223,200,16
+ call L100key_256b
+.byte 102,15,58,223,202,32
+ call L101key_256a
+.byte 102,15,58,223,200,32
+ call L100key_256b
+.byte 102,15,58,223,202,64
+ call L101key_256a
+ movups %xmm0,(%edx)
+ movl %ecx,16(%edx)
+ xorl %eax,%eax
+ ret
+.align 4,0x90
+L101key_256a:
+ movups %xmm2,(%edx)
+ leal 16(%edx),%edx
+L099key_256a_cold:
+ shufps $16,%xmm0,%xmm4
+ xorps %xmm4,%xmm0
+ shufps $140,%xmm0,%xmm4
+ xorps %xmm4,%xmm0
+ shufps $255,%xmm1,%xmm1
+ xorps %xmm1,%xmm0
+ ret
+.align 4,0x90
+L100key_256b:
+ movups %xmm0,(%edx)
+ leal 16(%edx),%edx
+ shufps $16,%xmm2,%xmm4
+ xorps %xmm4,%xmm2
+ shufps $140,%xmm2,%xmm4
+ xorps %xmm4,%xmm2
+ shufps $170,%xmm1,%xmm1
+ xorps %xmm1,%xmm2
+ ret
+.align 2,0x90
+L088bad_pointer:
+ movl $-1,%eax
+ ret
+.align 2,0x90
+L091bad_keybits:
+ movl $-2,%eax
+ ret
+.globl _aesni_set_encrypt_key
+.private_extern _aesni_set_encrypt_key
+.align 4
+_aesni_set_encrypt_key:
+L_aesni_set_encrypt_key_begin:
+ movl 4(%esp),%eax
+ movl 8(%esp),%ecx
+ movl 12(%esp),%edx
+ call __aesni_set_encrypt_key
+ ret
+.globl _aesni_set_decrypt_key
+.private_extern _aesni_set_decrypt_key
+.align 4
+_aesni_set_decrypt_key:
+L_aesni_set_decrypt_key_begin:
+ movl 4(%esp),%eax
+ movl 8(%esp),%ecx
+ movl 12(%esp),%edx
+ call __aesni_set_encrypt_key
+ movl 12(%esp),%edx
+ shll $4,%ecx
+ testl %eax,%eax
+ jnz L102dec_key_ret
+ leal 16(%edx,%ecx,1),%eax
+ movups (%edx),%xmm0
+ movups (%eax),%xmm1
+ movups %xmm0,(%eax)
+ movups %xmm1,(%edx)
+ leal 16(%edx),%edx
+ leal -16(%eax),%eax
+L103dec_key_inverse:
+ movups (%edx),%xmm0
+ movups (%eax),%xmm1
+.byte 102,15,56,219,192
+.byte 102,15,56,219,201
+ leal 16(%edx),%edx
+ leal -16(%eax),%eax
+ movups %xmm0,16(%eax)
+ movups %xmm1,-16(%edx)
+ cmpl %edx,%eax
+ ja L103dec_key_inverse
+ movups (%edx),%xmm0
+.byte 102,15,56,219,192
+ movups %xmm0,(%edx)
+ xorl %eax,%eax
+L102dec_key_ret:
+ ret
+.byte 65,69,83,32,102,111,114,32,73,110,116,101,108,32,65,69
+.byte 83,45,78,73,44,32,67,82,89,80,84,79,71,65,77,83
+.byte 32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115
+.byte 115,108,46,111,114,103,62,0
+#endif
diff --git a/mac-x86/crypto/aes/vpaes-x86.S b/mac-x86/crypto/aes/vpaes-x86.S
new file mode 100644
index 0000000..8b85709
--- /dev/null
+++ b/mac-x86/crypto/aes/vpaes-x86.S
@@ -0,0 +1,650 @@
+#if defined(__i386__)
+.file "vpaes-x86.S"
+.text
+.align 6,0x90
+L_vpaes_consts:
+.long 218628480,235210255,168496130,67568393
+.long 252381056,17041926,33884169,51187212
+.long 252645135,252645135,252645135,252645135
+.long 1512730624,3266504856,1377990664,3401244816
+.long 830229760,1275146365,2969422977,3447763452
+.long 3411033600,2979783055,338359620,2782886510
+.long 4209124096,907596821,221174255,1006095553
+.long 191964160,3799684038,3164090317,1589111125
+.long 182528256,1777043520,2877432650,3265356744
+.long 1874708224,3503451415,3305285752,363511674
+.long 1606117888,3487855781,1093350906,2384367825
+.long 197121,67569157,134941193,202313229
+.long 67569157,134941193,202313229,197121
+.long 134941193,202313229,197121,67569157
+.long 202313229,197121,67569157,134941193
+.long 33619971,100992007,168364043,235736079
+.long 235736079,33619971,100992007,168364043
+.long 168364043,235736079,33619971,100992007
+.long 100992007,168364043,235736079,33619971
+.long 50462976,117835012,185207048,252579084
+.long 252314880,51251460,117574920,184942860
+.long 184682752,252054788,50987272,118359308
+.long 118099200,185467140,251790600,50727180
+.long 2946363062,528716217,1300004225,1881839624
+.long 1532713819,1532713819,1532713819,1532713819
+.long 3602276352,4288629033,3737020424,4153884961
+.long 1354558464,32357713,2958822624,3775749553
+.long 1201988352,132424512,1572796698,503232858
+.long 2213177600,1597421020,4103937655,675398315
+.long 2749646592,4273543773,1511898873,121693092
+.long 3040248576,1103263732,2871565598,1608280554
+.long 2236667136,2588920351,482954393,64377734
+.long 3069987328,291237287,2117370568,3650299247
+.long 533321216,3573750986,2572112006,1401264716
+.long 1339849704,2721158661,548607111,3445553514
+.long 2128193280,3054596040,2183486460,1257083700
+.long 655635200,1165381986,3923443150,2344132524
+.long 190078720,256924420,290342170,357187870
+.long 1610966272,2263057382,4103205268,309794674
+.long 2592527872,2233205587,1335446729,3402964816
+.long 3973531904,3225098121,3002836325,1918774430
+.long 3870401024,2102906079,2284471353,4117666579
+.long 617007872,1021508343,366931923,691083277
+.long 2528395776,3491914898,2968704004,1613121270
+.long 3445188352,3247741094,844474987,4093578302
+.long 651481088,1190302358,1689581232,574775300
+.long 4289380608,206939853,2555985458,2489840491
+.long 2130264064,327674451,3566485037,3349835193
+.long 2470714624,316102159,3636825756,3393945945
+.byte 86,101,99,116,111,114,32,80,101,114,109,117,116,97,116,105
+.byte 111,110,32,65,69,83,32,102,111,114,32,120,56,54,47,83
+.byte 83,83,69,51,44,32,77,105,107,101,32,72,97,109,98,117
+.byte 114,103,32,40,83,116,97,110,102,111,114,100,32,85,110,105
+.byte 118,101,114,115,105,116,121,41,0
+.align 6,0x90
+.private_extern __vpaes_preheat
+.align 4
+__vpaes_preheat:
+ addl (%esp),%ebp
+ movdqa -48(%ebp),%xmm7
+ movdqa -16(%ebp),%xmm6
+ ret
+.private_extern __vpaes_encrypt_core
+.align 4
+__vpaes_encrypt_core:
+ movl $16,%ecx
+ movl 240(%edx),%eax
+ movdqa %xmm6,%xmm1
+ movdqa (%ebp),%xmm2
+ pandn %xmm0,%xmm1
+ pand %xmm6,%xmm0
+ movdqu (%edx),%xmm5
+.byte 102,15,56,0,208
+ movdqa 16(%ebp),%xmm0
+ pxor %xmm5,%xmm2
+ psrld $4,%xmm1
+ addl $16,%edx
+.byte 102,15,56,0,193
+ leal 192(%ebp),%ebx
+ pxor %xmm2,%xmm0
+ jmp L000enc_entry
+.align 4,0x90
+L001enc_loop:
+ movdqa 32(%ebp),%xmm4
+ movdqa 48(%ebp),%xmm0
+.byte 102,15,56,0,226
+.byte 102,15,56,0,195
+ pxor %xmm5,%xmm4
+ movdqa 64(%ebp),%xmm5
+ pxor %xmm4,%xmm0
+ movdqa -64(%ebx,%ecx,1),%xmm1
+.byte 102,15,56,0,234
+ movdqa 80(%ebp),%xmm2
+ movdqa (%ebx,%ecx,1),%xmm4
+.byte 102,15,56,0,211
+ movdqa %xmm0,%xmm3
+ pxor %xmm5,%xmm2
+.byte 102,15,56,0,193
+ addl $16,%edx
+ pxor %xmm2,%xmm0
+.byte 102,15,56,0,220
+ addl $16,%ecx
+ pxor %xmm0,%xmm3
+.byte 102,15,56,0,193
+ andl $48,%ecx
+ subl $1,%eax
+ pxor %xmm3,%xmm0
+L000enc_entry:
+ movdqa %xmm6,%xmm1
+ movdqa -32(%ebp),%xmm5
+ pandn %xmm0,%xmm1
+ psrld $4,%xmm1
+ pand %xmm6,%xmm0
+.byte 102,15,56,0,232
+ movdqa %xmm7,%xmm3
+ pxor %xmm1,%xmm0
+.byte 102,15,56,0,217
+ movdqa %xmm7,%xmm4
+ pxor %xmm5,%xmm3
+.byte 102,15,56,0,224
+ movdqa %xmm7,%xmm2
+ pxor %xmm5,%xmm4
+.byte 102,15,56,0,211
+ movdqa %xmm7,%xmm3
+ pxor %xmm0,%xmm2
+.byte 102,15,56,0,220
+ movdqu (%edx),%xmm5
+ pxor %xmm1,%xmm3
+ jnz L001enc_loop
+ movdqa 96(%ebp),%xmm4
+ movdqa 112(%ebp),%xmm0
+.byte 102,15,56,0,226
+ pxor %xmm5,%xmm4
+.byte 102,15,56,0,195
+ movdqa 64(%ebx,%ecx,1),%xmm1
+ pxor %xmm4,%xmm0
+.byte 102,15,56,0,193
+ ret
+.private_extern __vpaes_decrypt_core
+.align 4
+__vpaes_decrypt_core:
+ leal 608(%ebp),%ebx
+ movl 240(%edx),%eax
+ movdqa %xmm6,%xmm1
+ movdqa -64(%ebx),%xmm2
+ pandn %xmm0,%xmm1
+ movl %eax,%ecx
+ psrld $4,%xmm1
+ movdqu (%edx),%xmm5
+ shll $4,%ecx
+ pand %xmm6,%xmm0
+.byte 102,15,56,0,208
+ movdqa -48(%ebx),%xmm0
+ xorl $48,%ecx
+.byte 102,15,56,0,193
+ andl $48,%ecx
+ pxor %xmm5,%xmm2
+ movdqa 176(%ebp),%xmm5
+ pxor %xmm2,%xmm0
+ addl $16,%edx
+ leal -352(%ebx,%ecx,1),%ecx
+ jmp L002dec_entry
+.align 4,0x90
+L003dec_loop:
+ movdqa -32(%ebx),%xmm4
+ movdqa -16(%ebx),%xmm1
+.byte 102,15,56,0,226
+.byte 102,15,56,0,203
+ pxor %xmm4,%xmm0
+ movdqa (%ebx),%xmm4
+ pxor %xmm1,%xmm0
+ movdqa 16(%ebx),%xmm1
+.byte 102,15,56,0,226
+.byte 102,15,56,0,197
+.byte 102,15,56,0,203
+ pxor %xmm4,%xmm0
+ movdqa 32(%ebx),%xmm4
+ pxor %xmm1,%xmm0
+ movdqa 48(%ebx),%xmm1
+.byte 102,15,56,0,226
+.byte 102,15,56,0,197
+.byte 102,15,56,0,203
+ pxor %xmm4,%xmm0
+ movdqa 64(%ebx),%xmm4
+ pxor %xmm1,%xmm0
+ movdqa 80(%ebx),%xmm1
+.byte 102,15,56,0,226
+.byte 102,15,56,0,197
+.byte 102,15,56,0,203
+ pxor %xmm4,%xmm0
+ addl $16,%edx
+.byte 102,15,58,15,237,12
+ pxor %xmm1,%xmm0
+ subl $1,%eax
+L002dec_entry:
+ movdqa %xmm6,%xmm1
+ movdqa -32(%ebp),%xmm2
+ pandn %xmm0,%xmm1
+ pand %xmm6,%xmm0
+ psrld $4,%xmm1
+.byte 102,15,56,0,208
+ movdqa %xmm7,%xmm3
+ pxor %xmm1,%xmm0
+.byte 102,15,56,0,217
+ movdqa %xmm7,%xmm4
+ pxor %xmm2,%xmm3
+.byte 102,15,56,0,224
+ pxor %xmm2,%xmm4
+ movdqa %xmm7,%xmm2
+.byte 102,15,56,0,211
+ movdqa %xmm7,%xmm3
+ pxor %xmm0,%xmm2
+.byte 102,15,56,0,220
+ movdqu (%edx),%xmm0
+ pxor %xmm1,%xmm3
+ jnz L003dec_loop
+ movdqa 96(%ebx),%xmm4
+.byte 102,15,56,0,226
+ pxor %xmm0,%xmm4
+ movdqa 112(%ebx),%xmm0
+ movdqa (%ecx),%xmm2
+.byte 102,15,56,0,195
+ pxor %xmm4,%xmm0
+.byte 102,15,56,0,194
+ ret
+.private_extern __vpaes_schedule_core
+.align 4
+__vpaes_schedule_core:
+ addl (%esp),%ebp
+ movdqu (%esi),%xmm0
+ movdqa 320(%ebp),%xmm2
+ movdqa %xmm0,%xmm3
+ leal (%ebp),%ebx
+ movdqa %xmm2,4(%esp)
+ call __vpaes_schedule_transform
+ movdqa %xmm0,%xmm7
+ testl %edi,%edi
+ jnz L004schedule_am_decrypting
+ movdqu %xmm0,(%edx)
+ jmp L005schedule_go
+L004schedule_am_decrypting:
+ movdqa 256(%ebp,%ecx,1),%xmm1
+.byte 102,15,56,0,217
+ movdqu %xmm3,(%edx)
+ xorl $48,%ecx
+L005schedule_go:
+ cmpl $192,%eax
+ ja L006schedule_256
+ je L007schedule_192
+L008schedule_128:
+ movl $10,%eax
+L009loop_schedule_128:
+ call __vpaes_schedule_round
+ decl %eax
+ jz L010schedule_mangle_last
+ call __vpaes_schedule_mangle
+ jmp L009loop_schedule_128
+.align 4,0x90
+L007schedule_192:
+ movdqu 8(%esi),%xmm0
+ call __vpaes_schedule_transform
+ movdqa %xmm0,%xmm6
+ pxor %xmm4,%xmm4
+ movhlps %xmm4,%xmm6
+ movl $4,%eax
+L011loop_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
+ decl %eax
+ jz L010schedule_mangle_last
+ call __vpaes_schedule_mangle
+ call __vpaes_schedule_192_smear
+ jmp L011loop_schedule_192
+.align 4,0x90
+L006schedule_256:
+ movdqu 16(%esi),%xmm0
+ call __vpaes_schedule_transform
+ movl $7,%eax
+L012loop_schedule_256:
+ call __vpaes_schedule_mangle
+ movdqa %xmm0,%xmm6
+ call __vpaes_schedule_round
+ decl %eax
+ jz L010schedule_mangle_last
+ call __vpaes_schedule_mangle
+ pshufd $255,%xmm0,%xmm0
+ movdqa %xmm7,20(%esp)
+ movdqa %xmm6,%xmm7
+ call L_vpaes_schedule_low_round
+ movdqa 20(%esp),%xmm7
+ jmp L012loop_schedule_256
+.align 4,0x90
+L010schedule_mangle_last:
+ leal 384(%ebp),%ebx
+ testl %edi,%edi
+ jnz L013schedule_mangle_last_dec
+ movdqa 256(%ebp,%ecx,1),%xmm1
+.byte 102,15,56,0,193
+ leal 352(%ebp),%ebx
+ addl $32,%edx
+L013schedule_mangle_last_dec:
+ addl $-16,%edx
+ pxor 336(%ebp),%xmm0
+ call __vpaes_schedule_transform
+ movdqu %xmm0,(%edx)
+ pxor %xmm0,%xmm0
+ pxor %xmm1,%xmm1
+ pxor %xmm2,%xmm2
+ pxor %xmm3,%xmm3
+ pxor %xmm4,%xmm4
+ pxor %xmm5,%xmm5
+ pxor %xmm6,%xmm6
+ pxor %xmm7,%xmm7
+ ret
+.private_extern __vpaes_schedule_192_smear
+.align 4
+__vpaes_schedule_192_smear:
+ pshufd $128,%xmm6,%xmm1
+ pshufd $254,%xmm7,%xmm0
+ pxor %xmm1,%xmm6
+ pxor %xmm1,%xmm1
+ pxor %xmm0,%xmm6
+ movdqa %xmm6,%xmm0
+ movhlps %xmm1,%xmm6
+ ret
+.private_extern __vpaes_schedule_round
+.align 4
+__vpaes_schedule_round:
+ movdqa 8(%esp),%xmm2
+ pxor %xmm1,%xmm1
+.byte 102,15,58,15,202,15
+.byte 102,15,58,15,210,15
+ pxor %xmm1,%xmm7
+ pshufd $255,%xmm0,%xmm0
+.byte 102,15,58,15,192,1
+ movdqa %xmm2,8(%esp)
+L_vpaes_schedule_low_round:
+ movdqa %xmm7,%xmm1
+ pslldq $4,%xmm7
+ pxor %xmm1,%xmm7
+ movdqa %xmm7,%xmm1
+ pslldq $8,%xmm7
+ pxor %xmm1,%xmm7
+ pxor 336(%ebp),%xmm7
+ movdqa -16(%ebp),%xmm4
+ movdqa -48(%ebp),%xmm5
+ movdqa %xmm4,%xmm1
+ pandn %xmm0,%xmm1
+ psrld $4,%xmm1
+ pand %xmm4,%xmm0
+ movdqa -32(%ebp),%xmm2
+.byte 102,15,56,0,208
+ pxor %xmm1,%xmm0
+ movdqa %xmm5,%xmm3
+.byte 102,15,56,0,217
+ pxor %xmm2,%xmm3
+ movdqa %xmm5,%xmm4
+.byte 102,15,56,0,224
+ pxor %xmm2,%xmm4
+ movdqa %xmm5,%xmm2
+.byte 102,15,56,0,211
+ pxor %xmm0,%xmm2
+ movdqa %xmm5,%xmm3
+.byte 102,15,56,0,220
+ pxor %xmm1,%xmm3
+ movdqa 32(%ebp),%xmm4
+.byte 102,15,56,0,226
+ movdqa 48(%ebp),%xmm0
+.byte 102,15,56,0,195
+ pxor %xmm4,%xmm0
+ pxor %xmm7,%xmm0
+ movdqa %xmm0,%xmm7
+ ret
+.private_extern __vpaes_schedule_transform
+.align 4
+__vpaes_schedule_transform:
+ movdqa -16(%ebp),%xmm2
+ movdqa %xmm2,%xmm1
+ pandn %xmm0,%xmm1
+ psrld $4,%xmm1
+ pand %xmm2,%xmm0
+ movdqa (%ebx),%xmm2
+.byte 102,15,56,0,208
+ movdqa 16(%ebx),%xmm0
+.byte 102,15,56,0,193
+ pxor %xmm2,%xmm0
+ ret
+.private_extern __vpaes_schedule_mangle
+.align 4
+__vpaes_schedule_mangle:
+ movdqa %xmm0,%xmm4
+ movdqa 128(%ebp),%xmm5
+ testl %edi,%edi
+ jnz L014schedule_mangle_dec
+ addl $16,%edx
+ pxor 336(%ebp),%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 L015schedule_mangle_both
+.align 4,0x90
+L014schedule_mangle_dec:
+ movdqa -16(%ebp),%xmm2
+ leal 416(%ebp),%esi
+ movdqa %xmm2,%xmm1
+ pandn %xmm4,%xmm1
+ psrld $4,%xmm1
+ pand %xmm2,%xmm4
+ movdqa (%esi),%xmm2
+.byte 102,15,56,0,212
+ movdqa 16(%esi),%xmm3
+.byte 102,15,56,0,217
+ pxor %xmm2,%xmm3
+.byte 102,15,56,0,221
+ movdqa 32(%esi),%xmm2
+.byte 102,15,56,0,212
+ pxor %xmm3,%xmm2
+ movdqa 48(%esi),%xmm3
+.byte 102,15,56,0,217
+ pxor %xmm2,%xmm3
+.byte 102,15,56,0,221
+ movdqa 64(%esi),%xmm2
+.byte 102,15,56,0,212
+ pxor %xmm3,%xmm2
+ movdqa 80(%esi),%xmm3
+.byte 102,15,56,0,217
+ pxor %xmm2,%xmm3
+.byte 102,15,56,0,221
+ movdqa 96(%esi),%xmm2
+.byte 102,15,56,0,212
+ pxor %xmm3,%xmm2
+ movdqa 112(%esi),%xmm3
+.byte 102,15,56,0,217
+ pxor %xmm2,%xmm3
+ addl $-16,%edx
+L015schedule_mangle_both:
+ movdqa 256(%ebp,%ecx,1),%xmm1
+.byte 102,15,56,0,217
+ addl $-16,%ecx
+ andl $48,%ecx
+ movdqu %xmm3,(%edx)
+ ret
+.globl _vpaes_set_encrypt_key
+.private_extern _vpaes_set_encrypt_key
+.align 4
+_vpaes_set_encrypt_key:
+L_vpaes_set_encrypt_key_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ movl 20(%esp),%esi
+ leal -56(%esp),%ebx
+ movl 24(%esp),%eax
+ andl $-16,%ebx
+ movl 28(%esp),%edx
+ xchgl %esp,%ebx
+ movl %ebx,48(%esp)
+ movl %eax,%ebx
+ shrl $5,%ebx
+ addl $5,%ebx
+ movl %ebx,240(%edx)
+ movl $48,%ecx
+ movl $0,%edi
+ leal L_vpaes_consts+0x30-L016pic_point,%ebp
+ call __vpaes_schedule_core
+L016pic_point:
+ movl 48(%esp),%esp
+ xorl %eax,%eax
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.globl _vpaes_set_decrypt_key
+.private_extern _vpaes_set_decrypt_key
+.align 4
+_vpaes_set_decrypt_key:
+L_vpaes_set_decrypt_key_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ movl 20(%esp),%esi
+ leal -56(%esp),%ebx
+ movl 24(%esp),%eax
+ andl $-16,%ebx
+ movl 28(%esp),%edx
+ xchgl %esp,%ebx
+ movl %ebx,48(%esp)
+ movl %eax,%ebx
+ shrl $5,%ebx
+ addl $5,%ebx
+ movl %ebx,240(%edx)
+ shll $4,%ebx
+ leal 16(%edx,%ebx,1),%edx
+ movl $1,%edi
+ movl %eax,%ecx
+ shrl $1,%ecx
+ andl $32,%ecx
+ xorl $32,%ecx
+ leal L_vpaes_consts+0x30-L017pic_point,%ebp
+ call __vpaes_schedule_core
+L017pic_point:
+ movl 48(%esp),%esp
+ xorl %eax,%eax
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.globl _vpaes_encrypt
+.private_extern _vpaes_encrypt
+.align 4
+_vpaes_encrypt:
+L_vpaes_encrypt_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ leal L_vpaes_consts+0x30-L018pic_point,%ebp
+ call __vpaes_preheat
+L018pic_point:
+ movl 20(%esp),%esi
+ leal -56(%esp),%ebx
+ movl 24(%esp),%edi
+ andl $-16,%ebx
+ movl 28(%esp),%edx
+ xchgl %esp,%ebx
+ movl %ebx,48(%esp)
+ movdqu (%esi),%xmm0
+ call __vpaes_encrypt_core
+ movdqu %xmm0,(%edi)
+ movl 48(%esp),%esp
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.globl _vpaes_decrypt
+.private_extern _vpaes_decrypt
+.align 4
+_vpaes_decrypt:
+L_vpaes_decrypt_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ leal L_vpaes_consts+0x30-L019pic_point,%ebp
+ call __vpaes_preheat
+L019pic_point:
+ movl 20(%esp),%esi
+ leal -56(%esp),%ebx
+ movl 24(%esp),%edi
+ andl $-16,%ebx
+ movl 28(%esp),%edx
+ xchgl %esp,%ebx
+ movl %ebx,48(%esp)
+ movdqu (%esi),%xmm0
+ call __vpaes_decrypt_core
+ movdqu %xmm0,(%edi)
+ movl 48(%esp),%esp
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.globl _vpaes_cbc_encrypt
+.private_extern _vpaes_cbc_encrypt
+.align 4
+_vpaes_cbc_encrypt:
+L_vpaes_cbc_encrypt_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ movl 20(%esp),%esi
+ movl 24(%esp),%edi
+ movl 28(%esp),%eax
+ movl 32(%esp),%edx
+ subl $16,%eax
+ jc L020cbc_abort
+ leal -56(%esp),%ebx
+ movl 36(%esp),%ebp
+ andl $-16,%ebx
+ movl 40(%esp),%ecx
+ xchgl %esp,%ebx
+ movdqu (%ebp),%xmm1
+ subl %esi,%edi
+ movl %ebx,48(%esp)
+ movl %edi,(%esp)
+ movl %edx,4(%esp)
+ movl %ebp,8(%esp)
+ movl %eax,%edi
+ leal L_vpaes_consts+0x30-L021pic_point,%ebp
+ call __vpaes_preheat
+L021pic_point:
+ cmpl $0,%ecx
+ je L022cbc_dec_loop
+ jmp L023cbc_enc_loop
+.align 4,0x90
+L023cbc_enc_loop:
+ movdqu (%esi),%xmm0
+ pxor %xmm1,%xmm0
+ call __vpaes_encrypt_core
+ movl (%esp),%ebx
+ movl 4(%esp),%edx
+ movdqa %xmm0,%xmm1
+ movdqu %xmm0,(%ebx,%esi,1)
+ leal 16(%esi),%esi
+ subl $16,%edi
+ jnc L023cbc_enc_loop
+ jmp L024cbc_done
+.align 4,0x90
+L022cbc_dec_loop:
+ movdqu (%esi),%xmm0
+ movdqa %xmm1,16(%esp)
+ movdqa %xmm0,32(%esp)
+ call __vpaes_decrypt_core
+ movl (%esp),%ebx
+ movl 4(%esp),%edx
+ pxor 16(%esp),%xmm0
+ movdqa 32(%esp),%xmm1
+ movdqu %xmm0,(%ebx,%esi,1)
+ leal 16(%esi),%esi
+ subl $16,%edi
+ jnc L022cbc_dec_loop
+L024cbc_done:
+ movl 8(%esp),%ebx
+ movl 48(%esp),%esp
+ movdqu %xmm1,(%ebx)
+L020cbc_abort:
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+#endif
diff --git a/mac-x86/crypto/bn/bn-586.S b/mac-x86/crypto/bn/bn-586.S
new file mode 100644
index 0000000..34cf56f
--- /dev/null
+++ b/mac-x86/crypto/bn/bn-586.S
@@ -0,0 +1,1379 @@
+#if defined(__i386__)
+.file "src/crypto/bn/asm/bn-586.S"
+.text
+.globl _bn_mul_add_words
+.private_extern _bn_mul_add_words
+.align 4
+_bn_mul_add_words:
+L_bn_mul_add_words_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+
+ xorl %esi,%esi
+ movl 20(%esp),%edi
+ movl 28(%esp),%ecx
+ movl 24(%esp),%ebx
+ andl $4294967288,%ecx
+ movl 32(%esp),%ebp
+ pushl %ecx
+ jz L000maw_finish
+.align 4,0x90
+L001maw_loop:
+ # Round 0
+ movl (%ebx),%eax
+ mull %ebp
+ addl %esi,%eax
+ adcl $0,%edx
+ addl (%edi),%eax
+ adcl $0,%edx
+ movl %eax,(%edi)
+ movl %edx,%esi
+ # Round 4
+ movl 4(%ebx),%eax
+ mull %ebp
+ addl %esi,%eax
+ adcl $0,%edx
+ addl 4(%edi),%eax
+ adcl $0,%edx
+ movl %eax,4(%edi)
+ movl %edx,%esi
+ # Round 8
+ movl 8(%ebx),%eax
+ mull %ebp
+ addl %esi,%eax
+ adcl $0,%edx
+ addl 8(%edi),%eax
+ adcl $0,%edx
+ movl %eax,8(%edi)
+ movl %edx,%esi
+ # Round 12
+ movl 12(%ebx),%eax
+ mull %ebp
+ addl %esi,%eax
+ adcl $0,%edx
+ addl 12(%edi),%eax
+ adcl $0,%edx
+ movl %eax,12(%edi)
+ movl %edx,%esi
+ # Round 16
+ movl 16(%ebx),%eax
+ mull %ebp
+ addl %esi,%eax
+ adcl $0,%edx
+ addl 16(%edi),%eax
+ adcl $0,%edx
+ movl %eax,16(%edi)
+ movl %edx,%esi
+ # Round 20
+ movl 20(%ebx),%eax
+ mull %ebp
+ addl %esi,%eax
+ adcl $0,%edx
+ addl 20(%edi),%eax
+ adcl $0,%edx
+ movl %eax,20(%edi)
+ movl %edx,%esi
+ # Round 24
+ movl 24(%ebx),%eax
+ mull %ebp
+ addl %esi,%eax
+ adcl $0,%edx
+ addl 24(%edi),%eax
+ adcl $0,%edx
+ movl %eax,24(%edi)
+ movl %edx,%esi
+ # Round 28
+ movl 28(%ebx),%eax
+ mull %ebp
+ addl %esi,%eax
+ adcl $0,%edx
+ addl 28(%edi),%eax
+ adcl $0,%edx
+ movl %eax,28(%edi)
+ movl %edx,%esi
+
+ subl $8,%ecx
+ leal 32(%ebx),%ebx
+ leal 32(%edi),%edi
+ jnz L001maw_loop
+L000maw_finish:
+ movl 32(%esp),%ecx
+ andl $7,%ecx
+ jnz L002maw_finish2
+ jmp L003maw_end
+L002maw_finish2:
+ # Tail Round 0
+ movl (%ebx),%eax
+ mull %ebp
+ addl %esi,%eax
+ adcl $0,%edx
+ addl (%edi),%eax
+ adcl $0,%edx
+ decl %ecx
+ movl %eax,(%edi)
+ movl %edx,%esi
+ jz L003maw_end
+ # Tail Round 1
+ movl 4(%ebx),%eax
+ mull %ebp
+ addl %esi,%eax
+ adcl $0,%edx
+ addl 4(%edi),%eax
+ adcl $0,%edx
+ decl %ecx
+ movl %eax,4(%edi)
+ movl %edx,%esi
+ jz L003maw_end
+ # Tail Round 2
+ movl 8(%ebx),%eax
+ mull %ebp
+ addl %esi,%eax
+ adcl $0,%edx
+ addl 8(%edi),%eax
+ adcl $0,%edx
+ decl %ecx
+ movl %eax,8(%edi)
+ movl %edx,%esi
+ jz L003maw_end
+ # Tail Round 3
+ movl 12(%ebx),%eax
+ mull %ebp
+ addl %esi,%eax
+ adcl $0,%edx
+ addl 12(%edi),%eax
+ adcl $0,%edx
+ decl %ecx
+ movl %eax,12(%edi)
+ movl %edx,%esi
+ jz L003maw_end
+ # Tail Round 4
+ movl 16(%ebx),%eax
+ mull %ebp
+ addl %esi,%eax
+ adcl $0,%edx
+ addl 16(%edi),%eax
+ adcl $0,%edx
+ decl %ecx
+ movl %eax,16(%edi)
+ movl %edx,%esi
+ jz L003maw_end
+ # Tail Round 5
+ movl 20(%ebx),%eax
+ mull %ebp
+ addl %esi,%eax
+ adcl $0,%edx
+ addl 20(%edi),%eax
+ adcl $0,%edx
+ decl %ecx
+ movl %eax,20(%edi)
+ movl %edx,%esi
+ jz L003maw_end
+ # Tail Round 6
+ movl 24(%ebx),%eax
+ mull %ebp
+ addl %esi,%eax
+ adcl $0,%edx
+ addl 24(%edi),%eax
+ adcl $0,%edx
+ movl %eax,24(%edi)
+ movl %edx,%esi
+L003maw_end:
+ movl %esi,%eax
+ popl %ecx
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.globl _bn_mul_words
+.private_extern _bn_mul_words
+.align 4
+_bn_mul_words:
+L_bn_mul_words_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+
+ xorl %esi,%esi
+ movl 20(%esp),%edi
+ movl 24(%esp),%ebx
+ movl 28(%esp),%ebp
+ movl 32(%esp),%ecx
+ andl $4294967288,%ebp
+ jz L004mw_finish
+L005mw_loop:
+ # Round 0
+ movl (%ebx),%eax
+ mull %ecx
+ addl %esi,%eax
+ adcl $0,%edx
+ movl %eax,(%edi)
+ movl %edx,%esi
+ # Round 4
+ movl 4(%ebx),%eax
+ mull %ecx
+ addl %esi,%eax
+ adcl $0,%edx
+ movl %eax,4(%edi)
+ movl %edx,%esi
+ # Round 8
+ movl 8(%ebx),%eax
+ mull %ecx
+ addl %esi,%eax
+ adcl $0,%edx
+ movl %eax,8(%edi)
+ movl %edx,%esi
+ # Round 12
+ movl 12(%ebx),%eax
+ mull %ecx
+ addl %esi,%eax
+ adcl $0,%edx
+ movl %eax,12(%edi)
+ movl %edx,%esi
+ # Round 16
+ movl 16(%ebx),%eax
+ mull %ecx
+ addl %esi,%eax
+ adcl $0,%edx
+ movl %eax,16(%edi)
+ movl %edx,%esi
+ # Round 20
+ movl 20(%ebx),%eax
+ mull %ecx
+ addl %esi,%eax
+ adcl $0,%edx
+ movl %eax,20(%edi)
+ movl %edx,%esi
+ # Round 24
+ movl 24(%ebx),%eax
+ mull %ecx
+ addl %esi,%eax
+ adcl $0,%edx
+ movl %eax,24(%edi)
+ movl %edx,%esi
+ # Round 28
+ movl 28(%ebx),%eax
+ mull %ecx
+ addl %esi,%eax
+ adcl $0,%edx
+ movl %eax,28(%edi)
+ movl %edx,%esi
+
+ addl $32,%ebx
+ addl $32,%edi
+ subl $8,%ebp
+ jz L004mw_finish
+ jmp L005mw_loop
+L004mw_finish:
+ movl 28(%esp),%ebp
+ andl $7,%ebp
+ jnz L006mw_finish2
+ jmp L007mw_end
+L006mw_finish2:
+ # Tail Round 0
+ movl (%ebx),%eax
+ mull %ecx
+ addl %esi,%eax
+ adcl $0,%edx
+ movl %eax,(%edi)
+ movl %edx,%esi
+ decl %ebp
+ jz L007mw_end
+ # Tail Round 1
+ movl 4(%ebx),%eax
+ mull %ecx
+ addl %esi,%eax
+ adcl $0,%edx
+ movl %eax,4(%edi)
+ movl %edx,%esi
+ decl %ebp
+ jz L007mw_end
+ # Tail Round 2
+ movl 8(%ebx),%eax
+ mull %ecx
+ addl %esi,%eax
+ adcl $0,%edx
+ movl %eax,8(%edi)
+ movl %edx,%esi
+ decl %ebp
+ jz L007mw_end
+ # Tail Round 3
+ movl 12(%ebx),%eax
+ mull %ecx
+ addl %esi,%eax
+ adcl $0,%edx
+ movl %eax,12(%edi)
+ movl %edx,%esi
+ decl %ebp
+ jz L007mw_end
+ # Tail Round 4
+ movl 16(%ebx),%eax
+ mull %ecx
+ addl %esi,%eax
+ adcl $0,%edx
+ movl %eax,16(%edi)
+ movl %edx,%esi
+ decl %ebp
+ jz L007mw_end
+ # Tail Round 5
+ movl 20(%ebx),%eax
+ mull %ecx
+ addl %esi,%eax
+ adcl $0,%edx
+ movl %eax,20(%edi)
+ movl %edx,%esi
+ decl %ebp
+ jz L007mw_end
+ # Tail Round 6
+ movl 24(%ebx),%eax
+ mull %ecx
+ addl %esi,%eax
+ adcl $0,%edx
+ movl %eax,24(%edi)
+ movl %edx,%esi
+L007mw_end:
+ movl %esi,%eax
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.globl _bn_sqr_words
+.private_extern _bn_sqr_words
+.align 4
+_bn_sqr_words:
+L_bn_sqr_words_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+
+ movl 20(%esp),%esi
+ movl 24(%esp),%edi
+ movl 28(%esp),%ebx
+ andl $4294967288,%ebx
+ jz L008sw_finish
+L009sw_loop:
+ # Round 0
+ movl (%edi),%eax
+ mull %eax
+ movl %eax,(%esi)
+ movl %edx,4(%esi)
+ # Round 4
+ movl 4(%edi),%eax
+ mull %eax
+ movl %eax,8(%esi)
+ movl %edx,12(%esi)
+ # Round 8
+ movl 8(%edi),%eax
+ mull %eax
+ movl %eax,16(%esi)
+ movl %edx,20(%esi)
+ # Round 12
+ movl 12(%edi),%eax
+ mull %eax
+ movl %eax,24(%esi)
+ movl %edx,28(%esi)
+ # Round 16
+ movl 16(%edi),%eax
+ mull %eax
+ movl %eax,32(%esi)
+ movl %edx,36(%esi)
+ # Round 20
+ movl 20(%edi),%eax
+ mull %eax
+ movl %eax,40(%esi)
+ movl %edx,44(%esi)
+ # Round 24
+ movl 24(%edi),%eax
+ mull %eax
+ movl %eax,48(%esi)
+ movl %edx,52(%esi)
+ # Round 28
+ movl 28(%edi),%eax
+ mull %eax
+ movl %eax,56(%esi)
+ movl %edx,60(%esi)
+
+ addl $32,%edi
+ addl $64,%esi
+ subl $8,%ebx
+ jnz L009sw_loop
+L008sw_finish:
+ movl 28(%esp),%ebx
+ andl $7,%ebx
+ jz L010sw_end
+ # Tail Round 0
+ movl (%edi),%eax
+ mull %eax
+ movl %eax,(%esi)
+ decl %ebx
+ movl %edx,4(%esi)
+ jz L010sw_end
+ # Tail Round 1
+ movl 4(%edi),%eax
+ mull %eax
+ movl %eax,8(%esi)
+ decl %ebx
+ movl %edx,12(%esi)
+ jz L010sw_end
+ # Tail Round 2
+ movl 8(%edi),%eax
+ mull %eax
+ movl %eax,16(%esi)
+ decl %ebx
+ movl %edx,20(%esi)
+ jz L010sw_end
+ # Tail Round 3
+ movl 12(%edi),%eax
+ mull %eax
+ movl %eax,24(%esi)
+ decl %ebx
+ movl %edx,28(%esi)
+ jz L010sw_end
+ # Tail Round 4
+ movl 16(%edi),%eax
+ mull %eax
+ movl %eax,32(%esi)
+ decl %ebx
+ movl %edx,36(%esi)
+ jz L010sw_end
+ # Tail Round 5
+ movl 20(%edi),%eax
+ mull %eax
+ movl %eax,40(%esi)
+ decl %ebx
+ movl %edx,44(%esi)
+ jz L010sw_end
+ # Tail Round 6
+ movl 24(%edi),%eax
+ mull %eax
+ movl %eax,48(%esi)
+ movl %edx,52(%esi)
+L010sw_end:
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.globl _bn_div_words
+.private_extern _bn_div_words
+.align 4
+_bn_div_words:
+L_bn_div_words_begin:
+ movl 4(%esp),%edx
+ movl 8(%esp),%eax
+ movl 12(%esp),%ecx
+ divl %ecx
+ ret
+.globl _bn_add_words
+.private_extern _bn_add_words
+.align 4
+_bn_add_words:
+L_bn_add_words_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+
+ movl 20(%esp),%ebx
+ movl 24(%esp),%esi
+ movl 28(%esp),%edi
+ movl 32(%esp),%ebp
+ xorl %eax,%eax
+ andl $4294967288,%ebp
+ jz L011aw_finish
+L012aw_loop:
+ # Round 0
+ movl (%esi),%ecx
+ movl (%edi),%edx
+ addl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ addl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,(%ebx)
+ # Round 1
+ movl 4(%esi),%ecx
+ movl 4(%edi),%edx
+ addl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ addl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,4(%ebx)
+ # Round 2
+ movl 8(%esi),%ecx
+ movl 8(%edi),%edx
+ addl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ addl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,8(%ebx)
+ # Round 3
+ movl 12(%esi),%ecx
+ movl 12(%edi),%edx
+ addl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ addl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,12(%ebx)
+ # Round 4
+ movl 16(%esi),%ecx
+ movl 16(%edi),%edx
+ addl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ addl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,16(%ebx)
+ # Round 5
+ movl 20(%esi),%ecx
+ movl 20(%edi),%edx
+ addl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ addl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,20(%ebx)
+ # Round 6
+ movl 24(%esi),%ecx
+ movl 24(%edi),%edx
+ addl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ addl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,24(%ebx)
+ # Round 7
+ movl 28(%esi),%ecx
+ movl 28(%edi),%edx
+ addl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ addl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,28(%ebx)
+
+ addl $32,%esi
+ addl $32,%edi
+ addl $32,%ebx
+ subl $8,%ebp
+ jnz L012aw_loop
+L011aw_finish:
+ movl 32(%esp),%ebp
+ andl $7,%ebp
+ jz L013aw_end
+ # Tail Round 0
+ movl (%esi),%ecx
+ movl (%edi),%edx
+ addl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ addl %edx,%ecx
+ adcl $0,%eax
+ decl %ebp
+ movl %ecx,(%ebx)
+ jz L013aw_end
+ # Tail Round 1
+ movl 4(%esi),%ecx
+ movl 4(%edi),%edx
+ addl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ addl %edx,%ecx
+ adcl $0,%eax
+ decl %ebp
+ movl %ecx,4(%ebx)
+ jz L013aw_end
+ # Tail Round 2
+ movl 8(%esi),%ecx
+ movl 8(%edi),%edx
+ addl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ addl %edx,%ecx
+ adcl $0,%eax
+ decl %ebp
+ movl %ecx,8(%ebx)
+ jz L013aw_end
+ # Tail Round 3
+ movl 12(%esi),%ecx
+ movl 12(%edi),%edx
+ addl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ addl %edx,%ecx
+ adcl $0,%eax
+ decl %ebp
+ movl %ecx,12(%ebx)
+ jz L013aw_end
+ # Tail Round 4
+ movl 16(%esi),%ecx
+ movl 16(%edi),%edx
+ addl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ addl %edx,%ecx
+ adcl $0,%eax
+ decl %ebp
+ movl %ecx,16(%ebx)
+ jz L013aw_end
+ # Tail Round 5
+ movl 20(%esi),%ecx
+ movl 20(%edi),%edx
+ addl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ addl %edx,%ecx
+ adcl $0,%eax
+ decl %ebp
+ movl %ecx,20(%ebx)
+ jz L013aw_end
+ # Tail Round 6
+ movl 24(%esi),%ecx
+ movl 24(%edi),%edx
+ addl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ addl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,24(%ebx)
+L013aw_end:
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.globl _bn_sub_words
+.private_extern _bn_sub_words
+.align 4
+_bn_sub_words:
+L_bn_sub_words_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+
+ movl 20(%esp),%ebx
+ movl 24(%esp),%esi
+ movl 28(%esp),%edi
+ movl 32(%esp),%ebp
+ xorl %eax,%eax
+ andl $4294967288,%ebp
+ jz L014aw_finish
+L015aw_loop:
+ # Round 0
+ movl (%esi),%ecx
+ movl (%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,(%ebx)
+ # Round 1
+ movl 4(%esi),%ecx
+ movl 4(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,4(%ebx)
+ # Round 2
+ movl 8(%esi),%ecx
+ movl 8(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,8(%ebx)
+ # Round 3
+ movl 12(%esi),%ecx
+ movl 12(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,12(%ebx)
+ # Round 4
+ movl 16(%esi),%ecx
+ movl 16(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,16(%ebx)
+ # Round 5
+ movl 20(%esi),%ecx
+ movl 20(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,20(%ebx)
+ # Round 6
+ movl 24(%esi),%ecx
+ movl 24(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,24(%ebx)
+ # Round 7
+ movl 28(%esi),%ecx
+ movl 28(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,28(%ebx)
+
+ addl $32,%esi
+ addl $32,%edi
+ addl $32,%ebx
+ subl $8,%ebp
+ jnz L015aw_loop
+L014aw_finish:
+ movl 32(%esp),%ebp
+ andl $7,%ebp
+ jz L016aw_end
+ # Tail Round 0
+ movl (%esi),%ecx
+ movl (%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ decl %ebp
+ movl %ecx,(%ebx)
+ jz L016aw_end
+ # Tail Round 1
+ movl 4(%esi),%ecx
+ movl 4(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ decl %ebp
+ movl %ecx,4(%ebx)
+ jz L016aw_end
+ # Tail Round 2
+ movl 8(%esi),%ecx
+ movl 8(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ decl %ebp
+ movl %ecx,8(%ebx)
+ jz L016aw_end
+ # Tail Round 3
+ movl 12(%esi),%ecx
+ movl 12(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ decl %ebp
+ movl %ecx,12(%ebx)
+ jz L016aw_end
+ # Tail Round 4
+ movl 16(%esi),%ecx
+ movl 16(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ decl %ebp
+ movl %ecx,16(%ebx)
+ jz L016aw_end
+ # Tail Round 5
+ movl 20(%esi),%ecx
+ movl 20(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ decl %ebp
+ movl %ecx,20(%ebx)
+ jz L016aw_end
+ # Tail Round 6
+ movl 24(%esi),%ecx
+ movl 24(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,24(%ebx)
+L016aw_end:
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.globl _bn_sub_part_words
+.private_extern _bn_sub_part_words
+.align 4
+_bn_sub_part_words:
+L_bn_sub_part_words_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+
+ movl 20(%esp),%ebx
+ movl 24(%esp),%esi
+ movl 28(%esp),%edi
+ movl 32(%esp),%ebp
+ xorl %eax,%eax
+ andl $4294967288,%ebp
+ jz L017aw_finish
+L018aw_loop:
+ # Round 0
+ movl (%esi),%ecx
+ movl (%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,(%ebx)
+ # Round 1
+ movl 4(%esi),%ecx
+ movl 4(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,4(%ebx)
+ # Round 2
+ movl 8(%esi),%ecx
+ movl 8(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,8(%ebx)
+ # Round 3
+ movl 12(%esi),%ecx
+ movl 12(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,12(%ebx)
+ # Round 4
+ movl 16(%esi),%ecx
+ movl 16(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,16(%ebx)
+ # Round 5
+ movl 20(%esi),%ecx
+ movl 20(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,20(%ebx)
+ # Round 6
+ movl 24(%esi),%ecx
+ movl 24(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,24(%ebx)
+ # Round 7
+ movl 28(%esi),%ecx
+ movl 28(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,28(%ebx)
+
+ addl $32,%esi
+ addl $32,%edi
+ addl $32,%ebx
+ subl $8,%ebp
+ jnz L018aw_loop
+L017aw_finish:
+ movl 32(%esp),%ebp
+ andl $7,%ebp
+ jz L019aw_end
+ # Tail Round 0
+ movl (%esi),%ecx
+ movl (%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,(%ebx)
+ addl $4,%esi
+ addl $4,%edi
+ addl $4,%ebx
+ decl %ebp
+ jz L019aw_end
+ # Tail Round 1
+ movl (%esi),%ecx
+ movl (%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,(%ebx)
+ addl $4,%esi
+ addl $4,%edi
+ addl $4,%ebx
+ decl %ebp
+ jz L019aw_end
+ # Tail Round 2
+ movl (%esi),%ecx
+ movl (%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,(%ebx)
+ addl $4,%esi
+ addl $4,%edi
+ addl $4,%ebx
+ decl %ebp
+ jz L019aw_end
+ # Tail Round 3
+ movl (%esi),%ecx
+ movl (%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,(%ebx)
+ addl $4,%esi
+ addl $4,%edi
+ addl $4,%ebx
+ decl %ebp
+ jz L019aw_end
+ # Tail Round 4
+ movl (%esi),%ecx
+ movl (%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,(%ebx)
+ addl $4,%esi
+ addl $4,%edi
+ addl $4,%ebx
+ decl %ebp
+ jz L019aw_end
+ # Tail Round 5
+ movl (%esi),%ecx
+ movl (%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,(%ebx)
+ addl $4,%esi
+ addl $4,%edi
+ addl $4,%ebx
+ decl %ebp
+ jz L019aw_end
+ # Tail Round 6
+ movl (%esi),%ecx
+ movl (%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,(%ebx)
+ addl $4,%esi
+ addl $4,%edi
+ addl $4,%ebx
+L019aw_end:
+ cmpl $0,36(%esp)
+ je L020pw_end
+ movl 36(%esp),%ebp
+ cmpl $0,%ebp
+ je L020pw_end
+ jge L021pw_pos
+ # pw_neg
+ movl $0,%edx
+ subl %ebp,%edx
+ movl %edx,%ebp
+ andl $4294967288,%ebp
+ jz L022pw_neg_finish
+L023pw_neg_loop:
+ # dl<0 Round 0
+ movl $0,%ecx
+ movl (%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,(%ebx)
+ # dl<0 Round 1
+ movl $0,%ecx
+ movl 4(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,4(%ebx)
+ # dl<0 Round 2
+ movl $0,%ecx
+ movl 8(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,8(%ebx)
+ # dl<0 Round 3
+ movl $0,%ecx
+ movl 12(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,12(%ebx)
+ # dl<0 Round 4
+ movl $0,%ecx
+ movl 16(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,16(%ebx)
+ # dl<0 Round 5
+ movl $0,%ecx
+ movl 20(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,20(%ebx)
+ # dl<0 Round 6
+ movl $0,%ecx
+ movl 24(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,24(%ebx)
+ # dl<0 Round 7
+ movl $0,%ecx
+ movl 28(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,28(%ebx)
+
+ addl $32,%edi
+ addl $32,%ebx
+ subl $8,%ebp
+ jnz L023pw_neg_loop
+L022pw_neg_finish:
+ movl 36(%esp),%edx
+ movl $0,%ebp
+ subl %edx,%ebp
+ andl $7,%ebp
+ jz L020pw_end
+ # dl<0 Tail Round 0
+ movl $0,%ecx
+ movl (%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ decl %ebp
+ movl %ecx,(%ebx)
+ jz L020pw_end
+ # dl<0 Tail Round 1
+ movl $0,%ecx
+ movl 4(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ decl %ebp
+ movl %ecx,4(%ebx)
+ jz L020pw_end
+ # dl<0 Tail Round 2
+ movl $0,%ecx
+ movl 8(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ decl %ebp
+ movl %ecx,8(%ebx)
+ jz L020pw_end
+ # dl<0 Tail Round 3
+ movl $0,%ecx
+ movl 12(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ decl %ebp
+ movl %ecx,12(%ebx)
+ jz L020pw_end
+ # dl<0 Tail Round 4
+ movl $0,%ecx
+ movl 16(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ decl %ebp
+ movl %ecx,16(%ebx)
+ jz L020pw_end
+ # dl<0 Tail Round 5
+ movl $0,%ecx
+ movl 20(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ decl %ebp
+ movl %ecx,20(%ebx)
+ jz L020pw_end
+ # dl<0 Tail Round 6
+ movl $0,%ecx
+ movl 24(%edi),%edx
+ subl %eax,%ecx
+ movl $0,%eax
+ adcl %eax,%eax
+ subl %edx,%ecx
+ adcl $0,%eax
+ movl %ecx,24(%ebx)
+ jmp L020pw_end
+L021pw_pos:
+ andl $4294967288,%ebp
+ jz L024pw_pos_finish
+L025pw_pos_loop:
+ # dl>0 Round 0
+ movl (%esi),%ecx
+ subl %eax,%ecx
+ movl %ecx,(%ebx)
+ jnc L026pw_nc0
+ # dl>0 Round 1
+ movl 4(%esi),%ecx
+ subl %eax,%ecx
+ movl %ecx,4(%ebx)
+ jnc L027pw_nc1
+ # dl>0 Round 2
+ movl 8(%esi),%ecx
+ subl %eax,%ecx
+ movl %ecx,8(%ebx)
+ jnc L028pw_nc2
+ # dl>0 Round 3
+ movl 12(%esi),%ecx
+ subl %eax,%ecx
+ movl %ecx,12(%ebx)
+ jnc L029pw_nc3
+ # dl>0 Round 4
+ movl 16(%esi),%ecx
+ subl %eax,%ecx
+ movl %ecx,16(%ebx)
+ jnc L030pw_nc4
+ # dl>0 Round 5
+ movl 20(%esi),%ecx
+ subl %eax,%ecx
+ movl %ecx,20(%ebx)
+ jnc L031pw_nc5
+ # dl>0 Round 6
+ movl 24(%esi),%ecx
+ subl %eax,%ecx
+ movl %ecx,24(%ebx)
+ jnc L032pw_nc6
+ # dl>0 Round 7
+ movl 28(%esi),%ecx
+ subl %eax,%ecx
+ movl %ecx,28(%ebx)
+ jnc L033pw_nc7
+
+ addl $32,%esi
+ addl $32,%ebx
+ subl $8,%ebp
+ jnz L025pw_pos_loop
+L024pw_pos_finish:
+ movl 36(%esp),%ebp
+ andl $7,%ebp
+ jz L020pw_end
+ # dl>0 Tail Round 0
+ movl (%esi),%ecx
+ subl %eax,%ecx
+ movl %ecx,(%ebx)
+ jnc L034pw_tail_nc0
+ decl %ebp
+ jz L020pw_end
+ # dl>0 Tail Round 1
+ movl 4(%esi),%ecx
+ subl %eax,%ecx
+ movl %ecx,4(%ebx)
+ jnc L035pw_tail_nc1
+ decl %ebp
+ jz L020pw_end
+ # dl>0 Tail Round 2
+ movl 8(%esi),%ecx
+ subl %eax,%ecx
+ movl %ecx,8(%ebx)
+ jnc L036pw_tail_nc2
+ decl %ebp
+ jz L020pw_end
+ # dl>0 Tail Round 3
+ movl 12(%esi),%ecx
+ subl %eax,%ecx
+ movl %ecx,12(%ebx)
+ jnc L037pw_tail_nc3
+ decl %ebp
+ jz L020pw_end
+ # dl>0 Tail Round 4
+ movl 16(%esi),%ecx
+ subl %eax,%ecx
+ movl %ecx,16(%ebx)
+ jnc L038pw_tail_nc4
+ decl %ebp
+ jz L020pw_end
+ # dl>0 Tail Round 5
+ movl 20(%esi),%ecx
+ subl %eax,%ecx
+ movl %ecx,20(%ebx)
+ jnc L039pw_tail_nc5
+ decl %ebp
+ jz L020pw_end
+ # dl>0 Tail Round 6
+ movl 24(%esi),%ecx
+ subl %eax,%ecx
+ movl %ecx,24(%ebx)
+ jnc L040pw_tail_nc6
+ movl $1,%eax
+ jmp L020pw_end
+L041pw_nc_loop:
+ movl (%esi),%ecx
+ movl %ecx,(%ebx)
+L026pw_nc0:
+ movl 4(%esi),%ecx
+ movl %ecx,4(%ebx)
+L027pw_nc1:
+ movl 8(%esi),%ecx
+ movl %ecx,8(%ebx)
+L028pw_nc2:
+ movl 12(%esi),%ecx
+ movl %ecx,12(%ebx)
+L029pw_nc3:
+ movl 16(%esi),%ecx
+ movl %ecx,16(%ebx)
+L030pw_nc4:
+ movl 20(%esi),%ecx
+ movl %ecx,20(%ebx)
+L031pw_nc5:
+ movl 24(%esi),%ecx
+ movl %ecx,24(%ebx)
+L032pw_nc6:
+ movl 28(%esi),%ecx
+ movl %ecx,28(%ebx)
+L033pw_nc7:
+
+ addl $32,%esi
+ addl $32,%ebx
+ subl $8,%ebp
+ jnz L041pw_nc_loop
+ movl 36(%esp),%ebp
+ andl $7,%ebp
+ jz L042pw_nc_end
+ movl (%esi),%ecx
+ movl %ecx,(%ebx)
+L034pw_tail_nc0:
+ decl %ebp
+ jz L042pw_nc_end
+ movl 4(%esi),%ecx
+ movl %ecx,4(%ebx)
+L035pw_tail_nc1:
+ decl %ebp
+ jz L042pw_nc_end
+ movl 8(%esi),%ecx
+ movl %ecx,8(%ebx)
+L036pw_tail_nc2:
+ decl %ebp
+ jz L042pw_nc_end
+ movl 12(%esi),%ecx
+ movl %ecx,12(%ebx)
+L037pw_tail_nc3:
+ decl %ebp
+ jz L042pw_nc_end
+ movl 16(%esi),%ecx
+ movl %ecx,16(%ebx)
+L038pw_tail_nc4:
+ decl %ebp
+ jz L042pw_nc_end
+ movl 20(%esi),%ecx
+ movl %ecx,20(%ebx)
+L039pw_tail_nc5:
+ decl %ebp
+ jz L042pw_nc_end
+ movl 24(%esi),%ecx
+ movl %ecx,24(%ebx)
+L040pw_tail_nc6:
+L042pw_nc_end:
+ movl $0,%eax
+L020pw_end:
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+#endif
diff --git a/mac-x86/crypto/bn/co-586.S b/mac-x86/crypto/bn/co-586.S
new file mode 100644
index 0000000..7ce8e79
--- /dev/null
+++ b/mac-x86/crypto/bn/co-586.S
@@ -0,0 +1,1252 @@
+#if defined(__i386__)
+.file "src/crypto/bn/asm/co-586.S"
+.text
+.globl _bn_mul_comba8
+.private_extern _bn_mul_comba8
+.align 4
+_bn_mul_comba8:
+L_bn_mul_comba8_begin:
+ pushl %esi
+ movl 12(%esp),%esi
+ pushl %edi
+ movl 20(%esp),%edi
+ pushl %ebp
+ pushl %ebx
+ xorl %ebx,%ebx
+ movl (%esi),%eax
+ xorl %ecx,%ecx
+ movl (%edi),%edx
+ # ################## Calculate word 0
+ xorl %ebp,%ebp
+ # mul a[0]*b[0]
+ mull %edx
+ addl %eax,%ebx
+ movl 20(%esp),%eax
+ adcl %edx,%ecx
+ movl (%edi),%edx
+ adcl $0,%ebp
+ movl %ebx,(%eax)
+ movl 4(%esi),%eax
+ # saved r[0]
+ # ################## Calculate word 1
+ xorl %ebx,%ebx
+ # mul a[1]*b[0]
+ mull %edx
+ addl %eax,%ecx
+ movl (%esi),%eax
+ adcl %edx,%ebp
+ movl 4(%edi),%edx
+ adcl $0,%ebx
+ # mul a[0]*b[1]
+ mull %edx
+ addl %eax,%ecx
+ movl 20(%esp),%eax
+ adcl %edx,%ebp
+ movl (%edi),%edx
+ adcl $0,%ebx
+ movl %ecx,4(%eax)
+ movl 8(%esi),%eax
+ # saved r[1]
+ # ################## Calculate word 2
+ xorl %ecx,%ecx
+ # mul a[2]*b[0]
+ mull %edx
+ addl %eax,%ebp
+ movl 4(%esi),%eax
+ adcl %edx,%ebx
+ movl 4(%edi),%edx
+ adcl $0,%ecx
+ # mul a[1]*b[1]
+ mull %edx
+ addl %eax,%ebp
+ movl (%esi),%eax
+ adcl %edx,%ebx
+ movl 8(%edi),%edx
+ adcl $0,%ecx
+ # mul a[0]*b[2]
+ mull %edx
+ addl %eax,%ebp
+ movl 20(%esp),%eax
+ adcl %edx,%ebx
+ movl (%edi),%edx
+ adcl $0,%ecx
+ movl %ebp,8(%eax)
+ movl 12(%esi),%eax
+ # saved r[2]
+ # ################## Calculate word 3
+ xorl %ebp,%ebp
+ # mul a[3]*b[0]
+ mull %edx
+ addl %eax,%ebx
+ movl 8(%esi),%eax
+ adcl %edx,%ecx
+ movl 4(%edi),%edx
+ adcl $0,%ebp
+ # mul a[2]*b[1]
+ mull %edx
+ addl %eax,%ebx
+ movl 4(%esi),%eax
+ adcl %edx,%ecx
+ movl 8(%edi),%edx
+ adcl $0,%ebp
+ # mul a[1]*b[2]
+ mull %edx
+ addl %eax,%ebx
+ movl (%esi),%eax
+ adcl %edx,%ecx
+ movl 12(%edi),%edx
+ adcl $0,%ebp
+ # mul a[0]*b[3]
+ mull %edx
+ addl %eax,%ebx
+ movl 20(%esp),%eax
+ adcl %edx,%ecx
+ movl (%edi),%edx
+ adcl $0,%ebp
+ movl %ebx,12(%eax)
+ movl 16(%esi),%eax
+ # saved r[3]
+ # ################## Calculate word 4
+ xorl %ebx,%ebx
+ # mul a[4]*b[0]
+ mull %edx
+ addl %eax,%ecx
+ movl 12(%esi),%eax
+ adcl %edx,%ebp
+ movl 4(%edi),%edx
+ adcl $0,%ebx
+ # mul a[3]*b[1]
+ mull %edx
+ addl %eax,%ecx
+ movl 8(%esi),%eax
+ adcl %edx,%ebp
+ movl 8(%edi),%edx
+ adcl $0,%ebx
+ # mul a[2]*b[2]
+ mull %edx
+ addl %eax,%ecx
+ movl 4(%esi),%eax
+ adcl %edx,%ebp
+ movl 12(%edi),%edx
+ adcl $0,%ebx
+ # mul a[1]*b[3]
+ mull %edx
+ addl %eax,%ecx
+ movl (%esi),%eax
+ adcl %edx,%ebp
+ movl 16(%edi),%edx
+ adcl $0,%ebx
+ # mul a[0]*b[4]
+ mull %edx
+ addl %eax,%ecx
+ movl 20(%esp),%eax
+ adcl %edx,%ebp
+ movl (%edi),%edx
+ adcl $0,%ebx
+ movl %ecx,16(%eax)
+ movl 20(%esi),%eax
+ # saved r[4]
+ # ################## Calculate word 5
+ xorl %ecx,%ecx
+ # mul a[5]*b[0]
+ mull %edx
+ addl %eax,%ebp
+ movl 16(%esi),%eax
+ adcl %edx,%ebx
+ movl 4(%edi),%edx
+ adcl $0,%ecx
+ # mul a[4]*b[1]
+ mull %edx
+ addl %eax,%ebp
+ movl 12(%esi),%eax
+ adcl %edx,%ebx
+ movl 8(%edi),%edx
+ adcl $0,%ecx
+ # mul a[3]*b[2]
+ mull %edx
+ addl %eax,%ebp
+ movl 8(%esi),%eax
+ adcl %edx,%ebx
+ movl 12(%edi),%edx
+ adcl $0,%ecx
+ # mul a[2]*b[3]
+ mull %edx
+ addl %eax,%ebp
+ movl 4(%esi),%eax
+ adcl %edx,%ebx
+ movl 16(%edi),%edx
+ adcl $0,%ecx
+ # mul a[1]*b[4]
+ mull %edx
+ addl %eax,%ebp
+ movl (%esi),%eax
+ adcl %edx,%ebx
+ movl 20(%edi),%edx
+ adcl $0,%ecx
+ # mul a[0]*b[5]
+ mull %edx
+ addl %eax,%ebp
+ movl 20(%esp),%eax
+ adcl %edx,%ebx
+ movl (%edi),%edx
+ adcl $0,%ecx
+ movl %ebp,20(%eax)
+ movl 24(%esi),%eax
+ # saved r[5]
+ # ################## Calculate word 6
+ xorl %ebp,%ebp
+ # mul a[6]*b[0]
+ mull %edx
+ addl %eax,%ebx
+ movl 20(%esi),%eax
+ adcl %edx,%ecx
+ movl 4(%edi),%edx
+ adcl $0,%ebp
+ # mul a[5]*b[1]
+ mull %edx
+ addl %eax,%ebx
+ movl 16(%esi),%eax
+ adcl %edx,%ecx
+ movl 8(%edi),%edx
+ adcl $0,%ebp
+ # mul a[4]*b[2]
+ mull %edx
+ addl %eax,%ebx
+ movl 12(%esi),%eax
+ adcl %edx,%ecx
+ movl 12(%edi),%edx
+ adcl $0,%ebp
+ # mul a[3]*b[3]
+ mull %edx
+ addl %eax,%ebx
+ movl 8(%esi),%eax
+ adcl %edx,%ecx
+ movl 16(%edi),%edx
+ adcl $0,%ebp
+ # mul a[2]*b[4]
+ mull %edx
+ addl %eax,%ebx
+ movl 4(%esi),%eax
+ adcl %edx,%ecx
+ movl 20(%edi),%edx
+ adcl $0,%ebp
+ # mul a[1]*b[5]
+ mull %edx
+ addl %eax,%ebx
+ movl (%esi),%eax
+ adcl %edx,%ecx
+ movl 24(%edi),%edx
+ adcl $0,%ebp
+ # mul a[0]*b[6]
+ mull %edx
+ addl %eax,%ebx
+ movl 20(%esp),%eax
+ adcl %edx,%ecx
+ movl (%edi),%edx
+ adcl $0,%ebp
+ movl %ebx,24(%eax)
+ movl 28(%esi),%eax
+ # saved r[6]
+ # ################## Calculate word 7
+ xorl %ebx,%ebx
+ # mul a[7]*b[0]
+ mull %edx
+ addl %eax,%ecx
+ movl 24(%esi),%eax
+ adcl %edx,%ebp
+ movl 4(%edi),%edx
+ adcl $0,%ebx
+ # mul a[6]*b[1]
+ mull %edx
+ addl %eax,%ecx
+ movl 20(%esi),%eax
+ adcl %edx,%ebp
+ movl 8(%edi),%edx
+ adcl $0,%ebx
+ # mul a[5]*b[2]
+ mull %edx
+ addl %eax,%ecx
+ movl 16(%esi),%eax
+ adcl %edx,%ebp
+ movl 12(%edi),%edx
+ adcl $0,%ebx
+ # mul a[4]*b[3]
+ mull %edx
+ addl %eax,%ecx
+ movl 12(%esi),%eax
+ adcl %edx,%ebp
+ movl 16(%edi),%edx
+ adcl $0,%ebx
+ # mul a[3]*b[4]
+ mull %edx
+ addl %eax,%ecx
+ movl 8(%esi),%eax
+ adcl %edx,%ebp
+ movl 20(%edi),%edx
+ adcl $0,%ebx
+ # mul a[2]*b[5]
+ mull %edx
+ addl %eax,%ecx
+ movl 4(%esi),%eax
+ adcl %edx,%ebp
+ movl 24(%edi),%edx
+ adcl $0,%ebx
+ # mul a[1]*b[6]
+ mull %edx
+ addl %eax,%ecx
+ movl (%esi),%eax
+ adcl %edx,%ebp
+ movl 28(%edi),%edx
+ adcl $0,%ebx
+ # mul a[0]*b[7]
+ mull %edx
+ addl %eax,%ecx
+ movl 20(%esp),%eax
+ adcl %edx,%ebp
+ movl 4(%edi),%edx
+ adcl $0,%ebx
+ movl %ecx,28(%eax)
+ movl 28(%esi),%eax
+ # saved r[7]
+ # ################## Calculate word 8
+ xorl %ecx,%ecx
+ # mul a[7]*b[1]
+ mull %edx
+ addl %eax,%ebp
+ movl 24(%esi),%eax
+ adcl %edx,%ebx
+ movl 8(%edi),%edx
+ adcl $0,%ecx
+ # mul a[6]*b[2]
+ mull %edx
+ addl %eax,%ebp
+ movl 20(%esi),%eax
+ adcl %edx,%ebx
+ movl 12(%edi),%edx
+ adcl $0,%ecx
+ # mul a[5]*b[3]
+ mull %edx
+ addl %eax,%ebp
+ movl 16(%esi),%eax
+ adcl %edx,%ebx
+ movl 16(%edi),%edx
+ adcl $0,%ecx
+ # mul a[4]*b[4]
+ mull %edx
+ addl %eax,%ebp
+ movl 12(%esi),%eax
+ adcl %edx,%ebx
+ movl 20(%edi),%edx
+ adcl $0,%ecx
+ # mul a[3]*b[5]
+ mull %edx
+ addl %eax,%ebp
+ movl 8(%esi),%eax
+ adcl %edx,%ebx
+ movl 24(%edi),%edx
+ adcl $0,%ecx
+ # mul a[2]*b[6]
+ mull %edx
+ addl %eax,%ebp
+ movl 4(%esi),%eax
+ adcl %edx,%ebx
+ movl 28(%edi),%edx
+ adcl $0,%ecx
+ # mul a[1]*b[7]
+ mull %edx
+ addl %eax,%ebp
+ movl 20(%esp),%eax
+ adcl %edx,%ebx
+ movl 8(%edi),%edx
+ adcl $0,%ecx
+ movl %ebp,32(%eax)
+ movl 28(%esi),%eax
+ # saved r[8]
+ # ################## Calculate word 9
+ xorl %ebp,%ebp
+ # mul a[7]*b[2]
+ mull %edx
+ addl %eax,%ebx
+ movl 24(%esi),%eax
+ adcl %edx,%ecx
+ movl 12(%edi),%edx
+ adcl $0,%ebp
+ # mul a[6]*b[3]
+ mull %edx
+ addl %eax,%ebx
+ movl 20(%esi),%eax
+ adcl %edx,%ecx
+ movl 16(%edi),%edx
+ adcl $0,%ebp
+ # mul a[5]*b[4]
+ mull %edx
+ addl %eax,%ebx
+ movl 16(%esi),%eax
+ adcl %edx,%ecx
+ movl 20(%edi),%edx
+ adcl $0,%ebp
+ # mul a[4]*b[5]
+ mull %edx
+ addl %eax,%ebx
+ movl 12(%esi),%eax
+ adcl %edx,%ecx
+ movl 24(%edi),%edx
+ adcl $0,%ebp
+ # mul a[3]*b[6]
+ mull %edx
+ addl %eax,%ebx
+ movl 8(%esi),%eax
+ adcl %edx,%ecx
+ movl 28(%edi),%edx
+ adcl $0,%ebp
+ # mul a[2]*b[7]
+ mull %edx
+ addl %eax,%ebx
+ movl 20(%esp),%eax
+ adcl %edx,%ecx
+ movl 12(%edi),%edx
+ adcl $0,%ebp
+ movl %ebx,36(%eax)
+ movl 28(%esi),%eax
+ # saved r[9]
+ # ################## Calculate word 10
+ xorl %ebx,%ebx
+ # mul a[7]*b[3]
+ mull %edx
+ addl %eax,%ecx
+ movl 24(%esi),%eax
+ adcl %edx,%ebp
+ movl 16(%edi),%edx
+ adcl $0,%ebx
+ # mul a[6]*b[4]
+ mull %edx
+ addl %eax,%ecx
+ movl 20(%esi),%eax
+ adcl %edx,%ebp
+ movl 20(%edi),%edx
+ adcl $0,%ebx
+ # mul a[5]*b[5]
+ mull %edx
+ addl %eax,%ecx
+ movl 16(%esi),%eax
+ adcl %edx,%ebp
+ movl 24(%edi),%edx
+ adcl $0,%ebx
+ # mul a[4]*b[6]
+ mull %edx
+ addl %eax,%ecx
+ movl 12(%esi),%eax
+ adcl %edx,%ebp
+ movl 28(%edi),%edx
+ adcl $0,%ebx
+ # mul a[3]*b[7]
+ mull %edx
+ addl %eax,%ecx
+ movl 20(%esp),%eax
+ adcl %edx,%ebp
+ movl 16(%edi),%edx
+ adcl $0,%ebx
+ movl %ecx,40(%eax)
+ movl 28(%esi),%eax
+ # saved r[10]
+ # ################## Calculate word 11
+ xorl %ecx,%ecx
+ # mul a[7]*b[4]
+ mull %edx
+ addl %eax,%ebp
+ movl 24(%esi),%eax
+ adcl %edx,%ebx
+ movl 20(%edi),%edx
+ adcl $0,%ecx
+ # mul a[6]*b[5]
+ mull %edx
+ addl %eax,%ebp
+ movl 20(%esi),%eax
+ adcl %edx,%ebx
+ movl 24(%edi),%edx
+ adcl $0,%ecx
+ # mul a[5]*b[6]
+ mull %edx
+ addl %eax,%ebp
+ movl 16(%esi),%eax
+ adcl %edx,%ebx
+ movl 28(%edi),%edx
+ adcl $0,%ecx
+ # mul a[4]*b[7]
+ mull %edx
+ addl %eax,%ebp
+ movl 20(%esp),%eax
+ adcl %edx,%ebx
+ movl 20(%edi),%edx
+ adcl $0,%ecx
+ movl %ebp,44(%eax)
+ movl 28(%esi),%eax
+ # saved r[11]
+ # ################## Calculate word 12
+ xorl %ebp,%ebp
+ # mul a[7]*b[5]
+ mull %edx
+ addl %eax,%ebx
+ movl 24(%esi),%eax
+ adcl %edx,%ecx
+ movl 24(%edi),%edx
+ adcl $0,%ebp
+ # mul a[6]*b[6]
+ mull %edx
+ addl %eax,%ebx
+ movl 20(%esi),%eax
+ adcl %edx,%ecx
+ movl 28(%edi),%edx
+ adcl $0,%ebp
+ # mul a[5]*b[7]
+ mull %edx
+ addl %eax,%ebx
+ movl 20(%esp),%eax
+ adcl %edx,%ecx
+ movl 24(%edi),%edx
+ adcl $0,%ebp
+ movl %ebx,48(%eax)
+ movl 28(%esi),%eax
+ # saved r[12]
+ # ################## Calculate word 13
+ xorl %ebx,%ebx
+ # mul a[7]*b[6]
+ mull %edx
+ addl %eax,%ecx
+ movl 24(%esi),%eax
+ adcl %edx,%ebp
+ movl 28(%edi),%edx
+ adcl $0,%ebx
+ # mul a[6]*b[7]
+ mull %edx
+ addl %eax,%ecx
+ movl 20(%esp),%eax
+ adcl %edx,%ebp
+ movl 28(%edi),%edx
+ adcl $0,%ebx
+ movl %ecx,52(%eax)
+ movl 28(%esi),%eax
+ # saved r[13]
+ # ################## Calculate word 14
+ xorl %ecx,%ecx
+ # mul a[7]*b[7]
+ mull %edx
+ addl %eax,%ebp
+ movl 20(%esp),%eax
+ adcl %edx,%ebx
+ adcl $0,%ecx
+ movl %ebp,56(%eax)
+ # saved r[14]
+ # save r[15]
+ movl %ebx,60(%eax)
+ popl %ebx
+ popl %ebp
+ popl %edi
+ popl %esi
+ ret
+.globl _bn_mul_comba4
+.private_extern _bn_mul_comba4
+.align 4
+_bn_mul_comba4:
+L_bn_mul_comba4_begin:
+ pushl %esi
+ movl 12(%esp),%esi
+ pushl %edi
+ movl 20(%esp),%edi
+ pushl %ebp
+ pushl %ebx
+ xorl %ebx,%ebx
+ movl (%esi),%eax
+ xorl %ecx,%ecx
+ movl (%edi),%edx
+ # ################## Calculate word 0
+ xorl %ebp,%ebp
+ # mul a[0]*b[0]
+ mull %edx
+ addl %eax,%ebx
+ movl 20(%esp),%eax
+ adcl %edx,%ecx
+ movl (%edi),%edx
+ adcl $0,%ebp
+ movl %ebx,(%eax)
+ movl 4(%esi),%eax
+ # saved r[0]
+ # ################## Calculate word 1
+ xorl %ebx,%ebx
+ # mul a[1]*b[0]
+ mull %edx
+ addl %eax,%ecx
+ movl (%esi),%eax
+ adcl %edx,%ebp
+ movl 4(%edi),%edx
+ adcl $0,%ebx
+ # mul a[0]*b[1]
+ mull %edx
+ addl %eax,%ecx
+ movl 20(%esp),%eax
+ adcl %edx,%ebp
+ movl (%edi),%edx
+ adcl $0,%ebx
+ movl %ecx,4(%eax)
+ movl 8(%esi),%eax
+ # saved r[1]
+ # ################## Calculate word 2
+ xorl %ecx,%ecx
+ # mul a[2]*b[0]
+ mull %edx
+ addl %eax,%ebp
+ movl 4(%esi),%eax
+ adcl %edx,%ebx
+ movl 4(%edi),%edx
+ adcl $0,%ecx
+ # mul a[1]*b[1]
+ mull %edx
+ addl %eax,%ebp
+ movl (%esi),%eax
+ adcl %edx,%ebx
+ movl 8(%edi),%edx
+ adcl $0,%ecx
+ # mul a[0]*b[2]
+ mull %edx
+ addl %eax,%ebp
+ movl 20(%esp),%eax
+ adcl %edx,%ebx
+ movl (%edi),%edx
+ adcl $0,%ecx
+ movl %ebp,8(%eax)
+ movl 12(%esi),%eax
+ # saved r[2]
+ # ################## Calculate word 3
+ xorl %ebp,%ebp
+ # mul a[3]*b[0]
+ mull %edx
+ addl %eax,%ebx
+ movl 8(%esi),%eax
+ adcl %edx,%ecx
+ movl 4(%edi),%edx
+ adcl $0,%ebp
+ # mul a[2]*b[1]
+ mull %edx
+ addl %eax,%ebx
+ movl 4(%esi),%eax
+ adcl %edx,%ecx
+ movl 8(%edi),%edx
+ adcl $0,%ebp
+ # mul a[1]*b[2]
+ mull %edx
+ addl %eax,%ebx
+ movl (%esi),%eax
+ adcl %edx,%ecx
+ movl 12(%edi),%edx
+ adcl $0,%ebp
+ # mul a[0]*b[3]
+ mull %edx
+ addl %eax,%ebx
+ movl 20(%esp),%eax
+ adcl %edx,%ecx
+ movl 4(%edi),%edx
+ adcl $0,%ebp
+ movl %ebx,12(%eax)
+ movl 12(%esi),%eax
+ # saved r[3]
+ # ################## Calculate word 4
+ xorl %ebx,%ebx
+ # mul a[3]*b[1]
+ mull %edx
+ addl %eax,%ecx
+ movl 8(%esi),%eax
+ adcl %edx,%ebp
+ movl 8(%edi),%edx
+ adcl $0,%ebx
+ # mul a[2]*b[2]
+ mull %edx
+ addl %eax,%ecx
+ movl 4(%esi),%eax
+ adcl %edx,%ebp
+ movl 12(%edi),%edx
+ adcl $0,%ebx
+ # mul a[1]*b[3]
+ mull %edx
+ addl %eax,%ecx
+ movl 20(%esp),%eax
+ adcl %edx,%ebp
+ movl 8(%edi),%edx
+ adcl $0,%ebx
+ movl %ecx,16(%eax)
+ movl 12(%esi),%eax
+ # saved r[4]
+ # ################## Calculate word 5
+ xorl %ecx,%ecx
+ # mul a[3]*b[2]
+ mull %edx
+ addl %eax,%ebp
+ movl 8(%esi),%eax
+ adcl %edx,%ebx
+ movl 12(%edi),%edx
+ adcl $0,%ecx
+ # mul a[2]*b[3]
+ mull %edx
+ addl %eax,%ebp
+ movl 20(%esp),%eax
+ adcl %edx,%ebx
+ movl 12(%edi),%edx
+ adcl $0,%ecx
+ movl %ebp,20(%eax)
+ movl 12(%esi),%eax
+ # saved r[5]
+ # ################## Calculate word 6
+ xorl %ebp,%ebp
+ # mul a[3]*b[3]
+ mull %edx
+ addl %eax,%ebx
+ movl 20(%esp),%eax
+ adcl %edx,%ecx
+ adcl $0,%ebp
+ movl %ebx,24(%eax)
+ # saved r[6]
+ # save r[7]
+ movl %ecx,28(%eax)
+ popl %ebx
+ popl %ebp
+ popl %edi
+ popl %esi
+ ret
+.globl _bn_sqr_comba8
+.private_extern _bn_sqr_comba8
+.align 4
+_bn_sqr_comba8:
+L_bn_sqr_comba8_begin:
+ pushl %esi
+ pushl %edi
+ pushl %ebp
+ pushl %ebx
+ movl 20(%esp),%edi
+ movl 24(%esp),%esi
+ xorl %ebx,%ebx
+ xorl %ecx,%ecx
+ movl (%esi),%eax
+ # ############### Calculate word 0
+ xorl %ebp,%ebp
+ # sqr a[0]*a[0]
+ mull %eax
+ addl %eax,%ebx
+ adcl %edx,%ecx
+ movl (%esi),%edx
+ adcl $0,%ebp
+ movl %ebx,(%edi)
+ movl 4(%esi),%eax
+ # saved r[0]
+ # ############### Calculate word 1
+ xorl %ebx,%ebx
+ # sqr a[1]*a[0]
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ebx
+ addl %eax,%ecx
+ adcl %edx,%ebp
+ movl 8(%esi),%eax
+ adcl $0,%ebx
+ movl %ecx,4(%edi)
+ movl (%esi),%edx
+ # saved r[1]
+ # ############### Calculate word 2
+ xorl %ecx,%ecx
+ # sqr a[2]*a[0]
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ecx
+ addl %eax,%ebp
+ adcl %edx,%ebx
+ movl 4(%esi),%eax
+ adcl $0,%ecx
+ # sqr a[1]*a[1]
+ mull %eax
+ addl %eax,%ebp
+ adcl %edx,%ebx
+ movl (%esi),%edx
+ adcl $0,%ecx
+ movl %ebp,8(%edi)
+ movl 12(%esi),%eax
+ # saved r[2]
+ # ############### Calculate word 3
+ xorl %ebp,%ebp
+ # sqr a[3]*a[0]
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ebp
+ addl %eax,%ebx
+ adcl %edx,%ecx
+ movl 8(%esi),%eax
+ adcl $0,%ebp
+ movl 4(%esi),%edx
+ # sqr a[2]*a[1]
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ebp
+ addl %eax,%ebx
+ adcl %edx,%ecx
+ movl 16(%esi),%eax
+ adcl $0,%ebp
+ movl %ebx,12(%edi)
+ movl (%esi),%edx
+ # saved r[3]
+ # ############### Calculate word 4
+ xorl %ebx,%ebx
+ # sqr a[4]*a[0]
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ebx
+ addl %eax,%ecx
+ adcl %edx,%ebp
+ movl 12(%esi),%eax
+ adcl $0,%ebx
+ movl 4(%esi),%edx
+ # sqr a[3]*a[1]
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ebx
+ addl %eax,%ecx
+ adcl %edx,%ebp
+ movl 8(%esi),%eax
+ adcl $0,%ebx
+ # sqr a[2]*a[2]
+ mull %eax
+ addl %eax,%ecx
+ adcl %edx,%ebp
+ movl (%esi),%edx
+ adcl $0,%ebx
+ movl %ecx,16(%edi)
+ movl 20(%esi),%eax
+ # saved r[4]
+ # ############### Calculate word 5
+ xorl %ecx,%ecx
+ # sqr a[5]*a[0]
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ecx
+ addl %eax,%ebp
+ adcl %edx,%ebx
+ movl 16(%esi),%eax
+ adcl $0,%ecx
+ movl 4(%esi),%edx
+ # sqr a[4]*a[1]
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ecx
+ addl %eax,%ebp
+ adcl %edx,%ebx
+ movl 12(%esi),%eax
+ adcl $0,%ecx
+ movl 8(%esi),%edx
+ # sqr a[3]*a[2]
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ecx
+ addl %eax,%ebp
+ adcl %edx,%ebx
+ movl 24(%esi),%eax
+ adcl $0,%ecx
+ movl %ebp,20(%edi)
+ movl (%esi),%edx
+ # saved r[5]
+ # ############### Calculate word 6
+ xorl %ebp,%ebp
+ # sqr a[6]*a[0]
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ebp
+ addl %eax,%ebx
+ adcl %edx,%ecx
+ movl 20(%esi),%eax
+ adcl $0,%ebp
+ movl 4(%esi),%edx
+ # sqr a[5]*a[1]
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ebp
+ addl %eax,%ebx
+ adcl %edx,%ecx
+ movl 16(%esi),%eax
+ adcl $0,%ebp
+ movl 8(%esi),%edx
+ # sqr a[4]*a[2]
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ebp
+ addl %eax,%ebx
+ adcl %edx,%ecx
+ movl 12(%esi),%eax
+ adcl $0,%ebp
+ # sqr a[3]*a[3]
+ mull %eax
+ addl %eax,%ebx
+ adcl %edx,%ecx
+ movl (%esi),%edx
+ adcl $0,%ebp
+ movl %ebx,24(%edi)
+ movl 28(%esi),%eax
+ # saved r[6]
+ # ############### Calculate word 7
+ xorl %ebx,%ebx
+ # sqr a[7]*a[0]
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ebx
+ addl %eax,%ecx
+ adcl %edx,%ebp
+ movl 24(%esi),%eax
+ adcl $0,%ebx
+ movl 4(%esi),%edx
+ # sqr a[6]*a[1]
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ebx
+ addl %eax,%ecx
+ adcl %edx,%ebp
+ movl 20(%esi),%eax
+ adcl $0,%ebx
+ movl 8(%esi),%edx
+ # sqr a[5]*a[2]
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ebx
+ addl %eax,%ecx
+ adcl %edx,%ebp
+ movl 16(%esi),%eax
+ adcl $0,%ebx
+ movl 12(%esi),%edx
+ # sqr a[4]*a[3]
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ebx
+ addl %eax,%ecx
+ adcl %edx,%ebp
+ movl 28(%esi),%eax
+ adcl $0,%ebx
+ movl %ecx,28(%edi)
+ movl 4(%esi),%edx
+ # saved r[7]
+ # ############### Calculate word 8
+ xorl %ecx,%ecx
+ # sqr a[7]*a[1]
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ecx
+ addl %eax,%ebp
+ adcl %edx,%ebx
+ movl 24(%esi),%eax
+ adcl $0,%ecx
+ movl 8(%esi),%edx
+ # sqr a[6]*a[2]
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ecx
+ addl %eax,%ebp
+ adcl %edx,%ebx
+ movl 20(%esi),%eax
+ adcl $0,%ecx
+ movl 12(%esi),%edx
+ # sqr a[5]*a[3]
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ecx
+ addl %eax,%ebp
+ adcl %edx,%ebx
+ movl 16(%esi),%eax
+ adcl $0,%ecx
+ # sqr a[4]*a[4]
+ mull %eax
+ addl %eax,%ebp
+ adcl %edx,%ebx
+ movl 8(%esi),%edx
+ adcl $0,%ecx
+ movl %ebp,32(%edi)
+ movl 28(%esi),%eax
+ # saved r[8]
+ # ############### Calculate word 9
+ xorl %ebp,%ebp
+ # sqr a[7]*a[2]
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ebp
+ addl %eax,%ebx
+ adcl %edx,%ecx
+ movl 24(%esi),%eax
+ adcl $0,%ebp
+ movl 12(%esi),%edx
+ # sqr a[6]*a[3]
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ebp
+ addl %eax,%ebx
+ adcl %edx,%ecx
+ movl 20(%esi),%eax
+ adcl $0,%ebp
+ movl 16(%esi),%edx
+ # sqr a[5]*a[4]
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ebp
+ addl %eax,%ebx
+ adcl %edx,%ecx
+ movl 28(%esi),%eax
+ adcl $0,%ebp
+ movl %ebx,36(%edi)
+ movl 12(%esi),%edx
+ # saved r[9]
+ # ############### Calculate word 10
+ xorl %ebx,%ebx
+ # sqr a[7]*a[3]
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ebx
+ addl %eax,%ecx
+ adcl %edx,%ebp
+ movl 24(%esi),%eax
+ adcl $0,%ebx
+ movl 16(%esi),%edx
+ # sqr a[6]*a[4]
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ebx
+ addl %eax,%ecx
+ adcl %edx,%ebp
+ movl 20(%esi),%eax
+ adcl $0,%ebx
+ # sqr a[5]*a[5]
+ mull %eax
+ addl %eax,%ecx
+ adcl %edx,%ebp
+ movl 16(%esi),%edx
+ adcl $0,%ebx
+ movl %ecx,40(%edi)
+ movl 28(%esi),%eax
+ # saved r[10]
+ # ############### Calculate word 11
+ xorl %ecx,%ecx
+ # sqr a[7]*a[4]
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ecx
+ addl %eax,%ebp
+ adcl %edx,%ebx
+ movl 24(%esi),%eax
+ adcl $0,%ecx
+ movl 20(%esi),%edx
+ # sqr a[6]*a[5]
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ecx
+ addl %eax,%ebp
+ adcl %edx,%ebx
+ movl 28(%esi),%eax
+ adcl $0,%ecx
+ movl %ebp,44(%edi)
+ movl 20(%esi),%edx
+ # saved r[11]
+ # ############### Calculate word 12
+ xorl %ebp,%ebp
+ # sqr a[7]*a[5]
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ebp
+ addl %eax,%ebx
+ adcl %edx,%ecx
+ movl 24(%esi),%eax
+ adcl $0,%ebp
+ # sqr a[6]*a[6]
+ mull %eax
+ addl %eax,%ebx
+ adcl %edx,%ecx
+ movl 24(%esi),%edx
+ adcl $0,%ebp
+ movl %ebx,48(%edi)
+ movl 28(%esi),%eax
+ # saved r[12]
+ # ############### Calculate word 13
+ xorl %ebx,%ebx
+ # sqr a[7]*a[6]
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ebx
+ addl %eax,%ecx
+ adcl %edx,%ebp
+ movl 28(%esi),%eax
+ adcl $0,%ebx
+ movl %ecx,52(%edi)
+ # saved r[13]
+ # ############### Calculate word 14
+ xorl %ecx,%ecx
+ # sqr a[7]*a[7]
+ mull %eax
+ addl %eax,%ebp
+ adcl %edx,%ebx
+ adcl $0,%ecx
+ movl %ebp,56(%edi)
+ # saved r[14]
+ movl %ebx,60(%edi)
+ popl %ebx
+ popl %ebp
+ popl %edi
+ popl %esi
+ ret
+.globl _bn_sqr_comba4
+.private_extern _bn_sqr_comba4
+.align 4
+_bn_sqr_comba4:
+L_bn_sqr_comba4_begin:
+ pushl %esi
+ pushl %edi
+ pushl %ebp
+ pushl %ebx
+ movl 20(%esp),%edi
+ movl 24(%esp),%esi
+ xorl %ebx,%ebx
+ xorl %ecx,%ecx
+ movl (%esi),%eax
+ # ############### Calculate word 0
+ xorl %ebp,%ebp
+ # sqr a[0]*a[0]
+ mull %eax
+ addl %eax,%ebx
+ adcl %edx,%ecx
+ movl (%esi),%edx
+ adcl $0,%ebp
+ movl %ebx,(%edi)
+ movl 4(%esi),%eax
+ # saved r[0]
+ # ############### Calculate word 1
+ xorl %ebx,%ebx
+ # sqr a[1]*a[0]
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ebx
+ addl %eax,%ecx
+ adcl %edx,%ebp
+ movl 8(%esi),%eax
+ adcl $0,%ebx
+ movl %ecx,4(%edi)
+ movl (%esi),%edx
+ # saved r[1]
+ # ############### Calculate word 2
+ xorl %ecx,%ecx
+ # sqr a[2]*a[0]
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ecx
+ addl %eax,%ebp
+ adcl %edx,%ebx
+ movl 4(%esi),%eax
+ adcl $0,%ecx
+ # sqr a[1]*a[1]
+ mull %eax
+ addl %eax,%ebp
+ adcl %edx,%ebx
+ movl (%esi),%edx
+ adcl $0,%ecx
+ movl %ebp,8(%edi)
+ movl 12(%esi),%eax
+ # saved r[2]
+ # ############### Calculate word 3
+ xorl %ebp,%ebp
+ # sqr a[3]*a[0]
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ebp
+ addl %eax,%ebx
+ adcl %edx,%ecx
+ movl 8(%esi),%eax
+ adcl $0,%ebp
+ movl 4(%esi),%edx
+ # sqr a[2]*a[1]
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ebp
+ addl %eax,%ebx
+ adcl %edx,%ecx
+ movl 12(%esi),%eax
+ adcl $0,%ebp
+ movl %ebx,12(%edi)
+ movl 4(%esi),%edx
+ # saved r[3]
+ # ############### Calculate word 4
+ xorl %ebx,%ebx
+ # sqr a[3]*a[1]
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ebx
+ addl %eax,%ecx
+ adcl %edx,%ebp
+ movl 8(%esi),%eax
+ adcl $0,%ebx
+ # sqr a[2]*a[2]
+ mull %eax
+ addl %eax,%ecx
+ adcl %edx,%ebp
+ movl 8(%esi),%edx
+ adcl $0,%ebx
+ movl %ecx,16(%edi)
+ movl 12(%esi),%eax
+ # saved r[4]
+ # ############### Calculate word 5
+ xorl %ecx,%ecx
+ # sqr a[3]*a[2]
+ mull %edx
+ addl %eax,%eax
+ adcl %edx,%edx
+ adcl $0,%ecx
+ addl %eax,%ebp
+ adcl %edx,%ebx
+ movl 12(%esi),%eax
+ adcl $0,%ecx
+ movl %ebp,20(%edi)
+ # saved r[5]
+ # ############### Calculate word 6
+ xorl %ebp,%ebp
+ # sqr a[3]*a[3]
+ mull %eax
+ addl %eax,%ebx
+ adcl %edx,%ecx
+ adcl $0,%ebp
+ movl %ebx,24(%edi)
+ # saved r[6]
+ movl %ecx,28(%edi)
+ popl %ebx
+ popl %ebp
+ popl %edi
+ popl %esi
+ ret
+#endif
diff --git a/mac-x86/crypto/bn/x86-mont.S b/mac-x86/crypto/bn/x86-mont.S
new file mode 100644
index 0000000..1b79c5f
--- /dev/null
+++ b/mac-x86/crypto/bn/x86-mont.S
@@ -0,0 +1,338 @@
+#if defined(__i386__)
+.file "src/crypto/bn/asm/x86-mont.S"
+.text
+.globl _bn_mul_mont
+.private_extern _bn_mul_mont
+.align 4
+_bn_mul_mont:
+L_bn_mul_mont_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ xorl %eax,%eax
+ movl 40(%esp),%edi
+ cmpl $4,%edi
+ jl L000just_leave
+ leal 20(%esp),%esi
+ leal 24(%esp),%edx
+ movl %esp,%ebp
+ addl $2,%edi
+ negl %edi
+ leal -32(%esp,%edi,4),%esp
+ negl %edi
+ movl %esp,%eax
+ subl %edx,%eax
+ andl $2047,%eax
+ subl %eax,%esp
+ xorl %esp,%edx
+ andl $2048,%edx
+ xorl $2048,%edx
+ subl %edx,%esp
+ andl $-64,%esp
+ movl (%esi),%eax
+ movl 4(%esi),%ebx
+ movl 8(%esi),%ecx
+ movl 12(%esi),%edx
+ movl 16(%esi),%esi
+ movl (%esi),%esi
+ movl %eax,4(%esp)
+ movl %ebx,8(%esp)
+ movl %ecx,12(%esp)
+ movl %edx,16(%esp)
+ movl %esi,20(%esp)
+ leal -3(%edi),%ebx
+ movl %ebp,24(%esp)
+ movl 8(%esp),%esi
+ leal 1(%ebx),%ebp
+ movl 12(%esp),%edi
+ xorl %ecx,%ecx
+ movl %esi,%edx
+ andl $1,%ebp
+ subl %edi,%edx
+ leal 4(%edi,%ebx,4),%eax
+ orl %edx,%ebp
+ movl (%edi),%edi
+ jz L001bn_sqr_mont
+ movl %eax,28(%esp)
+ movl (%esi),%eax
+ xorl %edx,%edx
+.align 4,0x90
+L002mull:
+ movl %edx,%ebp
+ mull %edi
+ addl %eax,%ebp
+ leal 1(%ecx),%ecx
+ adcl $0,%edx
+ movl (%esi,%ecx,4),%eax
+ cmpl %ebx,%ecx
+ movl %ebp,28(%esp,%ecx,4)
+ jl L002mull
+ movl %edx,%ebp
+ mull %edi
+ movl 20(%esp),%edi
+ addl %ebp,%eax
+ movl 16(%esp),%esi
+ adcl $0,%edx
+ imull 32(%esp),%edi
+ movl %eax,32(%esp,%ebx,4)
+ xorl %ecx,%ecx
+ movl %edx,36(%esp,%ebx,4)
+ movl %ecx,40(%esp,%ebx,4)
+ movl (%esi),%eax
+ mull %edi
+ addl 32(%esp),%eax
+ movl 4(%esi),%eax
+ adcl $0,%edx
+ incl %ecx
+ jmp L0032ndmadd
+.align 4,0x90
+L0041stmadd:
+ movl %edx,%ebp
+ mull %edi
+ addl 32(%esp,%ecx,4),%ebp
+ leal 1(%ecx),%ecx
+ adcl $0,%edx
+ addl %eax,%ebp
+ movl (%esi,%ecx,4),%eax
+ adcl $0,%edx
+ cmpl %ebx,%ecx
+ movl %ebp,28(%esp,%ecx,4)
+ jl L0041stmadd
+ movl %edx,%ebp
+ mull %edi
+ addl 32(%esp,%ebx,4),%eax
+ movl 20(%esp),%edi
+ adcl $0,%edx
+ movl 16(%esp),%esi
+ addl %eax,%ebp
+ adcl $0,%edx
+ imull 32(%esp),%edi
+ xorl %ecx,%ecx
+ addl 36(%esp,%ebx,4),%edx
+ movl %ebp,32(%esp,%ebx,4)
+ adcl $0,%ecx
+ movl (%esi),%eax
+ movl %edx,36(%esp,%ebx,4)
+ movl %ecx,40(%esp,%ebx,4)
+ mull %edi
+ addl 32(%esp),%eax
+ movl 4(%esi),%eax
+ adcl $0,%edx
+ movl $1,%ecx
+.align 4,0x90
+L0032ndmadd:
+ movl %edx,%ebp
+ mull %edi
+ addl 32(%esp,%ecx,4),%ebp
+ leal 1(%ecx),%ecx
+ adcl $0,%edx
+ addl %eax,%ebp
+ movl (%esi,%ecx,4),%eax
+ adcl $0,%edx
+ cmpl %ebx,%ecx
+ movl %ebp,24(%esp,%ecx,4)
+ jl L0032ndmadd
+ movl %edx,%ebp
+ mull %edi
+ addl 32(%esp,%ebx,4),%ebp
+ adcl $0,%edx
+ addl %eax,%ebp
+ adcl $0,%edx
+ movl %ebp,28(%esp,%ebx,4)
+ xorl %eax,%eax
+ movl 12(%esp),%ecx
+ addl 36(%esp,%ebx,4),%edx
+ adcl 40(%esp,%ebx,4),%eax
+ leal 4(%ecx),%ecx
+ movl %edx,32(%esp,%ebx,4)
+ cmpl 28(%esp),%ecx
+ movl %eax,36(%esp,%ebx,4)
+ je L005common_tail
+ movl (%ecx),%edi
+ movl 8(%esp),%esi
+ movl %ecx,12(%esp)
+ xorl %ecx,%ecx
+ xorl %edx,%edx
+ movl (%esi),%eax
+ jmp L0041stmadd
+.align 4,0x90
+L001bn_sqr_mont:
+ movl %ebx,(%esp)
+ movl %ecx,12(%esp)
+ movl %edi,%eax
+ mull %edi
+ movl %eax,32(%esp)
+ movl %edx,%ebx
+ shrl $1,%edx
+ andl $1,%ebx
+ incl %ecx
+.align 4,0x90
+L006sqr:
+ movl (%esi,%ecx,4),%eax
+ movl %edx,%ebp
+ mull %edi
+ addl %ebp,%eax
+ leal 1(%ecx),%ecx
+ adcl $0,%edx
+ leal (%ebx,%eax,2),%ebp
+ shrl $31,%eax
+ cmpl (%esp),%ecx
+ movl %eax,%ebx
+ movl %ebp,28(%esp,%ecx,4)
+ jl L006sqr
+ movl (%esi,%ecx,4),%eax
+ movl %edx,%ebp
+ mull %edi
+ addl %ebp,%eax
+ movl 20(%esp),%edi
+ adcl $0,%edx
+ movl 16(%esp),%esi
+ leal (%ebx,%eax,2),%ebp
+ imull 32(%esp),%edi
+ shrl $31,%eax
+ movl %ebp,32(%esp,%ecx,4)
+ leal (%eax,%edx,2),%ebp
+ movl (%esi),%eax
+ shrl $31,%edx
+ movl %ebp,36(%esp,%ecx,4)
+ movl %edx,40(%esp,%ecx,4)
+ mull %edi
+ addl 32(%esp),%eax
+ movl %ecx,%ebx
+ adcl $0,%edx
+ movl 4(%esi),%eax
+ movl $1,%ecx
+.align 4,0x90
+L0073rdmadd:
+ movl %edx,%ebp
+ mull %edi
+ addl 32(%esp,%ecx,4),%ebp
+ adcl $0,%edx
+ addl %eax,%ebp
+ movl 4(%esi,%ecx,4),%eax
+ adcl $0,%edx
+ movl %ebp,28(%esp,%ecx,4)
+ movl %edx,%ebp
+ mull %edi
+ addl 36(%esp,%ecx,4),%ebp
+ leal 2(%ecx),%ecx
+ adcl $0,%edx
+ addl %eax,%ebp
+ movl (%esi,%ecx,4),%eax
+ adcl $0,%edx
+ cmpl %ebx,%ecx
+ movl %ebp,24(%esp,%ecx,4)
+ jl L0073rdmadd
+ movl %edx,%ebp
+ mull %edi
+ addl 32(%esp,%ebx,4),%ebp
+ adcl $0,%edx
+ addl %eax,%ebp
+ adcl $0,%edx
+ movl %ebp,28(%esp,%ebx,4)
+ movl 12(%esp),%ecx
+ xorl %eax,%eax
+ movl 8(%esp),%esi
+ addl 36(%esp,%ebx,4),%edx
+ adcl 40(%esp,%ebx,4),%eax
+ movl %edx,32(%esp,%ebx,4)
+ cmpl %ebx,%ecx
+ movl %eax,36(%esp,%ebx,4)
+ je L005common_tail
+ movl 4(%esi,%ecx,4),%edi
+ leal 1(%ecx),%ecx
+ movl %edi,%eax
+ movl %ecx,12(%esp)
+ mull %edi
+ addl 32(%esp,%ecx,4),%eax
+ adcl $0,%edx
+ movl %eax,32(%esp,%ecx,4)
+ xorl %ebp,%ebp
+ cmpl %ebx,%ecx
+ leal 1(%ecx),%ecx
+ je L008sqrlast
+ movl %edx,%ebx
+ shrl $1,%edx
+ andl $1,%ebx
+.align 4,0x90
+L009sqradd:
+ movl (%esi,%ecx,4),%eax
+ movl %edx,%ebp
+ mull %edi
+ addl %ebp,%eax
+ leal (%eax,%eax,1),%ebp
+ adcl $0,%edx
+ shrl $31,%eax
+ addl 32(%esp,%ecx,4),%ebp
+ leal 1(%ecx),%ecx
+ adcl $0,%eax
+ addl %ebx,%ebp
+ adcl $0,%eax
+ cmpl (%esp),%ecx
+ movl %ebp,28(%esp,%ecx,4)
+ movl %eax,%ebx
+ jle L009sqradd
+ movl %edx,%ebp
+ addl %edx,%edx
+ shrl $31,%ebp
+ addl %ebx,%edx
+ adcl $0,%ebp
+L008sqrlast:
+ movl 20(%esp),%edi
+ movl 16(%esp),%esi
+ imull 32(%esp),%edi
+ addl 32(%esp,%ecx,4),%edx
+ movl (%esi),%eax
+ adcl $0,%ebp
+ movl %edx,32(%esp,%ecx,4)
+ movl %ebp,36(%esp,%ecx,4)
+ mull %edi
+ addl 32(%esp),%eax
+ leal -1(%ecx),%ebx
+ adcl $0,%edx
+ movl $1,%ecx
+ movl 4(%esi),%eax
+ jmp L0073rdmadd
+.align 4,0x90
+L005common_tail:
+ movl 16(%esp),%ebp
+ movl 4(%esp),%edi
+ leal 32(%esp),%esi
+ movl (%esi),%eax
+ movl %ebx,%ecx
+ xorl %edx,%edx
+.align 4,0x90
+L010sub:
+ sbbl (%ebp,%edx,4),%eax
+ movl %eax,(%edi,%edx,4)
+ decl %ecx
+ movl 4(%esi,%edx,4),%eax
+ leal 1(%edx),%edx
+ jge L010sub
+ sbbl $0,%eax
+.align 4,0x90
+L011copy:
+ movl (%esi,%ebx,4),%edx
+ movl (%edi,%ebx,4),%ebp
+ xorl %ebp,%edx
+ andl %eax,%edx
+ xorl %ebp,%edx
+ movl %ecx,(%esi,%ebx,4)
+ movl %edx,(%edi,%ebx,4)
+ decl %ebx
+ jge L011copy
+ movl 24(%esp),%esp
+ movl $1,%eax
+L000just_leave:
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.byte 77,111,110,116,103,111,109,101,114,121,32,77,117,108,116,105
+.byte 112,108,105,99,97,116,105,111,110,32,102,111,114,32,120,56
+.byte 54,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121
+.byte 32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46
+.byte 111,114,103,62,0
+#endif
diff --git a/mac-x86/crypto/cpu-x86-asm.S b/mac-x86/crypto/cpu-x86-asm.S
new file mode 100644
index 0000000..7e8c83a
--- /dev/null
+++ b/mac-x86/crypto/cpu-x86-asm.S
@@ -0,0 +1,301 @@
+#if defined(__i386__)
+.file "crypto/cpu-x86-asm.S"
+.text
+.globl _OPENSSL_ia32_cpuid
+.private_extern _OPENSSL_ia32_cpuid
+.align 4
+_OPENSSL_ia32_cpuid:
+L_OPENSSL_ia32_cpuid_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ xorl %edx,%edx
+ pushfl
+ popl %eax
+ movl %eax,%ecx
+ xorl $2097152,%eax
+ pushl %eax
+ popfl
+ pushfl
+ popl %eax
+ xorl %eax,%ecx
+ xorl %eax,%eax
+ btl $21,%ecx
+ jnc L000nocpuid
+ movl 20(%esp),%esi
+ movl %eax,8(%esi)
+ .byte 0x0f,0xa2
+ movl %eax,%edi
+ xorl %eax,%eax
+ cmpl $1970169159,%ebx
+ setne %al
+ movl %eax,%ebp
+ cmpl $1231384169,%edx
+ setne %al
+ orl %eax,%ebp
+ cmpl $1818588270,%ecx
+ setne %al
+ orl %eax,%ebp
+ jz L001intel
+ cmpl $1752462657,%ebx
+ setne %al
+ movl %eax,%esi
+ cmpl $1769238117,%edx
+ setne %al
+ orl %eax,%esi
+ cmpl $1145913699,%ecx
+ setne %al
+ orl %eax,%esi
+ jnz L001intel
+ movl $2147483648,%eax
+ .byte 0x0f,0xa2
+ cmpl $2147483649,%eax
+ jb L001intel
+ movl %eax,%esi
+ movl $2147483649,%eax
+ .byte 0x0f,0xa2
+ orl %ecx,%ebp
+ andl $2049,%ebp
+ cmpl $2147483656,%esi
+ jb L001intel
+ movl $2147483656,%eax
+ .byte 0x0f,0xa2
+ movzbl %cl,%esi
+ incl %esi
+ movl $1,%eax
+ xorl %ecx,%ecx
+ .byte 0x0f,0xa2
+ btl $28,%edx
+ jnc L002generic
+ shrl $16,%ebx
+ andl $255,%ebx
+ cmpl %esi,%ebx
+ ja L002generic
+ andl $4026531839,%edx
+ jmp L002generic
+L001intel:
+ cmpl $7,%edi
+ jb L003cacheinfo
+ movl 20(%esp),%esi
+ movl $7,%eax
+ xorl %ecx,%ecx
+ .byte 0x0f,0xa2
+ movl %ebx,8(%esi)
+L003cacheinfo:
+ cmpl $4,%edi
+ movl $-1,%edi
+ jb L004nocacheinfo
+ movl $4,%eax
+ movl $0,%ecx
+ .byte 0x0f,0xa2
+ movl %eax,%edi
+ shrl $14,%edi
+ andl $4095,%edi
+L004nocacheinfo:
+ movl $1,%eax
+ xorl %ecx,%ecx
+ .byte 0x0f,0xa2
+ andl $3220176895,%edx
+ cmpl $0,%ebp
+ jne L005notintel
+ orl $1073741824,%edx
+ andb $15,%ah
+ cmpb $15,%ah
+ jne L005notintel
+ orl $1048576,%edx
+L005notintel:
+ btl $28,%edx
+ jnc L002generic
+ andl $4026531839,%edx
+ cmpl $0,%edi
+ je L002generic
+ orl $268435456,%edx
+ shrl $16,%ebx
+ cmpb $1,%bl
+ ja L002generic
+ andl $4026531839,%edx
+L002generic:
+ andl $2048,%ebp
+ andl $4294965247,%ecx
+ movl %edx,%esi
+ orl %ecx,%ebp
+ btl $27,%ecx
+ jnc L006clear_avx
+ xorl %ecx,%ecx
+.byte 15,1,208
+ andl $6,%eax
+ cmpl $6,%eax
+ je L007done
+ cmpl $2,%eax
+ je L006clear_avx
+L008clear_xmm:
+ andl $4261412861,%ebp
+ andl $4278190079,%esi
+L006clear_avx:
+ andl $4026525695,%ebp
+ movl 20(%esp),%edi
+ andl $4294967263,8(%edi)
+L007done:
+ movl %esi,%eax
+ movl %ebp,%edx
+L000nocpuid:
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.globl _OPENSSL_rdtsc
+.private_extern _OPENSSL_rdtsc
+.align 4
+_OPENSSL_rdtsc:
+L_OPENSSL_rdtsc_begin:
+ xorl %eax,%eax
+ xorl %edx,%edx
+ call L009PIC_me_up
+L009PIC_me_up:
+ popl %ecx
+ movl L_OPENSSL_ia32cap_P$non_lazy_ptr-L009PIC_me_up(%ecx),%ecx
+ btl $4,(%ecx)
+ jnc L010notsc
+ .byte 0x0f,0x31
+L010notsc:
+ ret
+.globl _OPENSSL_instrument_halt
+.private_extern _OPENSSL_instrument_halt
+.align 4
+_OPENSSL_instrument_halt:
+L_OPENSSL_instrument_halt_begin:
+ call L011PIC_me_up
+L011PIC_me_up:
+ popl %ecx
+ movl L_OPENSSL_ia32cap_P$non_lazy_ptr-L011PIC_me_up(%ecx),%ecx
+ btl $4,(%ecx)
+ jnc L012nohalt
+.long 2421723150
+ andl $3,%eax
+ jnz L012nohalt
+ pushfl
+ popl %eax
+ btl $9,%eax
+ jnc L012nohalt
+ .byte 0x0f,0x31
+ pushl %edx
+ pushl %eax
+ hlt
+ .byte 0x0f,0x31
+ subl (%esp),%eax
+ sbbl 4(%esp),%edx
+ addl $8,%esp
+ ret
+L012nohalt:
+ xorl %eax,%eax
+ xorl %edx,%edx
+ ret
+.globl _OPENSSL_far_spin
+.private_extern _OPENSSL_far_spin
+.align 4
+_OPENSSL_far_spin:
+L_OPENSSL_far_spin_begin:
+ pushfl
+ popl %eax
+ btl $9,%eax
+ jnc L013nospin
+ movl 4(%esp),%eax
+ movl 8(%esp),%ecx
+.long 2430111262
+ xorl %eax,%eax
+ movl (%ecx),%edx
+ jmp L014spin
+.align 4,0x90
+L014spin:
+ incl %eax
+ cmpl (%ecx),%edx
+ je L014spin
+.long 529567888
+ ret
+L013nospin:
+ xorl %eax,%eax
+ xorl %edx,%edx
+ ret
+.globl _OPENSSL_wipe_cpu
+.private_extern _OPENSSL_wipe_cpu
+.align 4
+_OPENSSL_wipe_cpu:
+L_OPENSSL_wipe_cpu_begin:
+ xorl %eax,%eax
+ xorl %edx,%edx
+ call L015PIC_me_up
+L015PIC_me_up:
+ popl %ecx
+ movl L_OPENSSL_ia32cap_P$non_lazy_ptr-L015PIC_me_up(%ecx),%ecx
+ movl (%ecx),%ecx
+ btl $1,(%ecx)
+ jnc L016no_x87
+.long 4007259865,4007259865,4007259865,4007259865,2430851995
+L016no_x87:
+ leal 4(%esp),%eax
+ ret
+.globl _OPENSSL_atomic_add
+.private_extern _OPENSSL_atomic_add
+.align 4
+_OPENSSL_atomic_add:
+L_OPENSSL_atomic_add_begin:
+ movl 4(%esp),%edx
+ movl 8(%esp),%ecx
+ pushl %ebx
+ nop
+ movl (%edx),%eax
+L017spin:
+ leal (%eax,%ecx,1),%ebx
+ nop
+.long 447811568
+ jne L017spin
+ movl %ebx,%eax
+ popl %ebx
+ ret
+.globl _OPENSSL_indirect_call
+.private_extern _OPENSSL_indirect_call
+.align 4
+_OPENSSL_indirect_call:
+L_OPENSSL_indirect_call_begin:
+ pushl %ebp
+ movl %esp,%ebp
+ subl $28,%esp
+ movl 12(%ebp),%ecx
+ movl %ecx,(%esp)
+ movl 16(%ebp),%edx
+ movl %edx,4(%esp)
+ movl 20(%ebp),%eax
+ movl %eax,8(%esp)
+ movl 24(%ebp),%eax
+ movl %eax,12(%esp)
+ movl 28(%ebp),%eax
+ movl %eax,16(%esp)
+ movl 32(%ebp),%eax
+ movl %eax,20(%esp)
+ movl 36(%ebp),%eax
+ movl %eax,24(%esp)
+ call *8(%ebp)
+ movl %ebp,%esp
+ popl %ebp
+ ret
+.globl _OPENSSL_ia32_rdrand
+.private_extern _OPENSSL_ia32_rdrand
+.align 4
+_OPENSSL_ia32_rdrand:
+L_OPENSSL_ia32_rdrand_begin:
+ movl $8,%ecx
+L018loop:
+.byte 15,199,240
+ jc L019break
+ loop L018loop
+L019break:
+ cmpl $0,%eax
+ cmovel %ecx,%eax
+ ret
+.section __IMPORT,__pointers,non_lazy_symbol_pointers
+L_OPENSSL_ia32cap_P$non_lazy_ptr:
+.indirect_symbol _OPENSSL_ia32cap_P
+.long 0
+#endif
diff --git a/mac-x86/crypto/md5/md5-586.S b/mac-x86/crypto/md5/md5-586.S
new file mode 100644
index 0000000..6830b16
--- /dev/null
+++ b/mac-x86/crypto/md5/md5-586.S
@@ -0,0 +1,680 @@
+#if defined(__i386__)
+.file "src/crypto/md5/asm/md5-586.S"
+.text
+.globl _md5_block_asm_data_order
+.private_extern _md5_block_asm_data_order
+.align 4
+_md5_block_asm_data_order:
+L_md5_block_asm_data_order_begin:
+ pushl %esi
+ pushl %edi
+ movl 12(%esp),%edi
+ movl 16(%esp),%esi
+ movl 20(%esp),%ecx
+ pushl %ebp
+ shll $6,%ecx
+ pushl %ebx
+ addl %esi,%ecx
+ subl $64,%ecx
+ movl (%edi),%eax
+ pushl %ecx
+ movl 4(%edi),%ebx
+ movl 8(%edi),%ecx
+ movl 12(%edi),%edx
+L000start:
+
+ # R0 section
+ movl %ecx,%edi
+ movl (%esi),%ebp
+ # R0 0
+ xorl %edx,%edi
+ andl %ebx,%edi
+ leal 3614090360(%eax,%ebp,1),%eax
+ xorl %edx,%edi
+ addl %edi,%eax
+ movl %ebx,%edi
+ roll $7,%eax
+ movl 4(%esi),%ebp
+ addl %ebx,%eax
+ # R0 1
+ xorl %ecx,%edi
+ andl %eax,%edi
+ leal 3905402710(%edx,%ebp,1),%edx
+ xorl %ecx,%edi
+ addl %edi,%edx
+ movl %eax,%edi
+ roll $12,%edx
+ movl 8(%esi),%ebp
+ addl %eax,%edx
+ # R0 2
+ xorl %ebx,%edi
+ andl %edx,%edi
+ leal 606105819(%ecx,%ebp,1),%ecx
+ xorl %ebx,%edi
+ addl %edi,%ecx
+ movl %edx,%edi
+ roll $17,%ecx
+ movl 12(%esi),%ebp
+ addl %edx,%ecx
+ # R0 3
+ xorl %eax,%edi
+ andl %ecx,%edi
+ leal 3250441966(%ebx,%ebp,1),%ebx
+ xorl %eax,%edi
+ addl %edi,%ebx
+ movl %ecx,%edi
+ roll $22,%ebx
+ movl 16(%esi),%ebp
+ addl %ecx,%ebx
+ # R0 4
+ xorl %edx,%edi
+ andl %ebx,%edi
+ leal 4118548399(%eax,%ebp,1),%eax
+ xorl %edx,%edi
+ addl %edi,%eax
+ movl %ebx,%edi
+ roll $7,%eax
+ movl 20(%esi),%ebp
+ addl %ebx,%eax
+ # R0 5
+ xorl %ecx,%edi
+ andl %eax,%edi
+ leal 1200080426(%edx,%ebp,1),%edx
+ xorl %ecx,%edi
+ addl %edi,%edx
+ movl %eax,%edi
+ roll $12,%edx
+ movl 24(%esi),%ebp
+ addl %eax,%edx
+ # R0 6
+ xorl %ebx,%edi
+ andl %edx,%edi
+ leal 2821735955(%ecx,%ebp,1),%ecx
+ xorl %ebx,%edi
+ addl %edi,%ecx
+ movl %edx,%edi
+ roll $17,%ecx
+ movl 28(%esi),%ebp
+ addl %edx,%ecx
+ # R0 7
+ xorl %eax,%edi
+ andl %ecx,%edi
+ leal 4249261313(%ebx,%ebp,1),%ebx
+ xorl %eax,%edi
+ addl %edi,%ebx
+ movl %ecx,%edi
+ roll $22,%ebx
+ movl 32(%esi),%ebp
+ addl %ecx,%ebx
+ # R0 8
+ xorl %edx,%edi
+ andl %ebx,%edi
+ leal 1770035416(%eax,%ebp,1),%eax
+ xorl %edx,%edi
+ addl %edi,%eax
+ movl %ebx,%edi
+ roll $7,%eax
+ movl 36(%esi),%ebp
+ addl %ebx,%eax
+ # R0 9
+ xorl %ecx,%edi
+ andl %eax,%edi
+ leal 2336552879(%edx,%ebp,1),%edx
+ xorl %ecx,%edi
+ addl %edi,%edx
+ movl %eax,%edi
+ roll $12,%edx
+ movl 40(%esi),%ebp
+ addl %eax,%edx
+ # R0 10
+ xorl %ebx,%edi
+ andl %edx,%edi
+ leal 4294925233(%ecx,%ebp,1),%ecx
+ xorl %ebx,%edi
+ addl %edi,%ecx
+ movl %edx,%edi
+ roll $17,%ecx
+ movl 44(%esi),%ebp
+ addl %edx,%ecx
+ # R0 11
+ xorl %eax,%edi
+ andl %ecx,%edi
+ leal 2304563134(%ebx,%ebp,1),%ebx
+ xorl %eax,%edi
+ addl %edi,%ebx
+ movl %ecx,%edi
+ roll $22,%ebx
+ movl 48(%esi),%ebp
+ addl %ecx,%ebx
+ # R0 12
+ xorl %edx,%edi
+ andl %ebx,%edi
+ leal 1804603682(%eax,%ebp,1),%eax
+ xorl %edx,%edi
+ addl %edi,%eax
+ movl %ebx,%edi
+ roll $7,%eax
+ movl 52(%esi),%ebp
+ addl %ebx,%eax
+ # R0 13
+ xorl %ecx,%edi
+ andl %eax,%edi
+ leal 4254626195(%edx,%ebp,1),%edx
+ xorl %ecx,%edi
+ addl %edi,%edx
+ movl %eax,%edi
+ roll $12,%edx
+ movl 56(%esi),%ebp
+ addl %eax,%edx
+ # R0 14
+ xorl %ebx,%edi
+ andl %edx,%edi
+ leal 2792965006(%ecx,%ebp,1),%ecx
+ xorl %ebx,%edi
+ addl %edi,%ecx
+ movl %edx,%edi
+ roll $17,%ecx
+ movl 60(%esi),%ebp
+ addl %edx,%ecx
+ # R0 15
+ xorl %eax,%edi
+ andl %ecx,%edi
+ leal 1236535329(%ebx,%ebp,1),%ebx
+ xorl %eax,%edi
+ addl %edi,%ebx
+ movl %ecx,%edi
+ roll $22,%ebx
+ movl 4(%esi),%ebp
+ addl %ecx,%ebx
+
+ # R1 section
+ # R1 16
+ leal 4129170786(%eax,%ebp,1),%eax
+ xorl %ebx,%edi
+ andl %edx,%edi
+ movl 24(%esi),%ebp
+ xorl %ecx,%edi
+ addl %edi,%eax
+ movl %ebx,%edi
+ roll $5,%eax
+ addl %ebx,%eax
+ # R1 17
+ leal 3225465664(%edx,%ebp,1),%edx
+ xorl %eax,%edi
+ andl %ecx,%edi
+ movl 44(%esi),%ebp
+ xorl %ebx,%edi
+ addl %edi,%edx
+ movl %eax,%edi
+ roll $9,%edx
+ addl %eax,%edx
+ # R1 18
+ leal 643717713(%ecx,%ebp,1),%ecx
+ xorl %edx,%edi
+ andl %ebx,%edi
+ movl (%esi),%ebp
+ xorl %eax,%edi
+ addl %edi,%ecx
+ movl %edx,%edi
+ roll $14,%ecx
+ addl %edx,%ecx
+ # R1 19
+ leal 3921069994(%ebx,%ebp,1),%ebx
+ xorl %ecx,%edi
+ andl %eax,%edi
+ movl 20(%esi),%ebp
+ xorl %edx,%edi
+ addl %edi,%ebx
+ movl %ecx,%edi
+ roll $20,%ebx
+ addl %ecx,%ebx
+ # R1 20
+ leal 3593408605(%eax,%ebp,1),%eax
+ xorl %ebx,%edi
+ andl %edx,%edi
+ movl 40(%esi),%ebp
+ xorl %ecx,%edi
+ addl %edi,%eax
+ movl %ebx,%edi
+ roll $5,%eax
+ addl %ebx,%eax
+ # R1 21
+ leal 38016083(%edx,%ebp,1),%edx
+ xorl %eax,%edi
+ andl %ecx,%edi
+ movl 60(%esi),%ebp
+ xorl %ebx,%edi
+ addl %edi,%edx
+ movl %eax,%edi
+ roll $9,%edx
+ addl %eax,%edx
+ # R1 22
+ leal 3634488961(%ecx,%ebp,1),%ecx
+ xorl %edx,%edi
+ andl %ebx,%edi
+ movl 16(%esi),%ebp
+ xorl %eax,%edi
+ addl %edi,%ecx
+ movl %edx,%edi
+ roll $14,%ecx
+ addl %edx,%ecx
+ # R1 23
+ leal 3889429448(%ebx,%ebp,1),%ebx
+ xorl %ecx,%edi
+ andl %eax,%edi
+ movl 36(%esi),%ebp
+ xorl %edx,%edi
+ addl %edi,%ebx
+ movl %ecx,%edi
+ roll $20,%ebx
+ addl %ecx,%ebx
+ # R1 24
+ leal 568446438(%eax,%ebp,1),%eax
+ xorl %ebx,%edi
+ andl %edx,%edi
+ movl 56(%esi),%ebp
+ xorl %ecx,%edi
+ addl %edi,%eax
+ movl %ebx,%edi
+ roll $5,%eax
+ addl %ebx,%eax
+ # R1 25
+ leal 3275163606(%edx,%ebp,1),%edx
+ xorl %eax,%edi
+ andl %ecx,%edi
+ movl 12(%esi),%ebp
+ xorl %ebx,%edi
+ addl %edi,%edx
+ movl %eax,%edi
+ roll $9,%edx
+ addl %eax,%edx
+ # R1 26
+ leal 4107603335(%ecx,%ebp,1),%ecx
+ xorl %edx,%edi
+ andl %ebx,%edi
+ movl 32(%esi),%ebp
+ xorl %eax,%edi
+ addl %edi,%ecx
+ movl %edx,%edi
+ roll $14,%ecx
+ addl %edx,%ecx
+ # R1 27
+ leal 1163531501(%ebx,%ebp,1),%ebx
+ xorl %ecx,%edi
+ andl %eax,%edi
+ movl 52(%esi),%ebp
+ xorl %edx,%edi
+ addl %edi,%ebx
+ movl %ecx,%edi
+ roll $20,%ebx
+ addl %ecx,%ebx
+ # R1 28
+ leal 2850285829(%eax,%ebp,1),%eax
+ xorl %ebx,%edi
+ andl %edx,%edi
+ movl 8(%esi),%ebp
+ xorl %ecx,%edi
+ addl %edi,%eax
+ movl %ebx,%edi
+ roll $5,%eax
+ addl %ebx,%eax
+ # R1 29
+ leal 4243563512(%edx,%ebp,1),%edx
+ xorl %eax,%edi
+ andl %ecx,%edi
+ movl 28(%esi),%ebp
+ xorl %ebx,%edi
+ addl %edi,%edx
+ movl %eax,%edi
+ roll $9,%edx
+ addl %eax,%edx
+ # R1 30
+ leal 1735328473(%ecx,%ebp,1),%ecx
+ xorl %edx,%edi
+ andl %ebx,%edi
+ movl 48(%esi),%ebp
+ xorl %eax,%edi
+ addl %edi,%ecx
+ movl %edx,%edi
+ roll $14,%ecx
+ addl %edx,%ecx
+ # R1 31
+ leal 2368359562(%ebx,%ebp,1),%ebx
+ xorl %ecx,%edi
+ andl %eax,%edi
+ movl 20(%esi),%ebp
+ xorl %edx,%edi
+ addl %edi,%ebx
+ movl %ecx,%edi
+ roll $20,%ebx
+ addl %ecx,%ebx
+
+ # R2 section
+ # R2 32
+ xorl %edx,%edi
+ xorl %ebx,%edi
+ leal 4294588738(%eax,%ebp,1),%eax
+ addl %edi,%eax
+ roll $4,%eax
+ movl 32(%esi),%ebp
+ movl %ebx,%edi
+ # R2 33
+ leal 2272392833(%edx,%ebp,1),%edx
+ addl %ebx,%eax
+ xorl %ecx,%edi
+ xorl %eax,%edi
+ movl 44(%esi),%ebp
+ addl %edi,%edx
+ movl %eax,%edi
+ roll $11,%edx
+ addl %eax,%edx
+ # R2 34
+ xorl %ebx,%edi
+ xorl %edx,%edi
+ leal 1839030562(%ecx,%ebp,1),%ecx
+ addl %edi,%ecx
+ roll $16,%ecx
+ movl 56(%esi),%ebp
+ movl %edx,%edi
+ # R2 35
+ leal 4259657740(%ebx,%ebp,1),%ebx
+ addl %edx,%ecx
+ xorl %eax,%edi
+ xorl %ecx,%edi
+ movl 4(%esi),%ebp
+ addl %edi,%ebx
+ movl %ecx,%edi
+ roll $23,%ebx
+ addl %ecx,%ebx
+ # R2 36
+ xorl %edx,%edi
+ xorl %ebx,%edi
+ leal 2763975236(%eax,%ebp,1),%eax
+ addl %edi,%eax
+ roll $4,%eax
+ movl 16(%esi),%ebp
+ movl %ebx,%edi
+ # R2 37
+ leal 1272893353(%edx,%ebp,1),%edx
+ addl %ebx,%eax
+ xorl %ecx,%edi
+ xorl %eax,%edi
+ movl 28(%esi),%ebp
+ addl %edi,%edx
+ movl %eax,%edi
+ roll $11,%edx
+ addl %eax,%edx
+ # R2 38
+ xorl %ebx,%edi
+ xorl %edx,%edi
+ leal 4139469664(%ecx,%ebp,1),%ecx
+ addl %edi,%ecx
+ roll $16,%ecx
+ movl 40(%esi),%ebp
+ movl %edx,%edi
+ # R2 39
+ leal 3200236656(%ebx,%ebp,1),%ebx
+ addl %edx,%ecx
+ xorl %eax,%edi
+ xorl %ecx,%edi
+ movl 52(%esi),%ebp
+ addl %edi,%ebx
+ movl %ecx,%edi
+ roll $23,%ebx
+ addl %ecx,%ebx
+ # R2 40
+ xorl %edx,%edi
+ xorl %ebx,%edi
+ leal 681279174(%eax,%ebp,1),%eax
+ addl %edi,%eax
+ roll $4,%eax
+ movl (%esi),%ebp
+ movl %ebx,%edi
+ # R2 41
+ leal 3936430074(%edx,%ebp,1),%edx
+ addl %ebx,%eax
+ xorl %ecx,%edi
+ xorl %eax,%edi
+ movl 12(%esi),%ebp
+ addl %edi,%edx
+ movl %eax,%edi
+ roll $11,%edx
+ addl %eax,%edx
+ # R2 42
+ xorl %ebx,%edi
+ xorl %edx,%edi
+ leal 3572445317(%ecx,%ebp,1),%ecx
+ addl %edi,%ecx
+ roll $16,%ecx
+ movl 24(%esi),%ebp
+ movl %edx,%edi
+ # R2 43
+ leal 76029189(%ebx,%ebp,1),%ebx
+ addl %edx,%ecx
+ xorl %eax,%edi
+ xorl %ecx,%edi
+ movl 36(%esi),%ebp
+ addl %edi,%ebx
+ movl %ecx,%edi
+ roll $23,%ebx
+ addl %ecx,%ebx
+ # R2 44
+ xorl %edx,%edi
+ xorl %ebx,%edi
+ leal 3654602809(%eax,%ebp,1),%eax
+ addl %edi,%eax
+ roll $4,%eax
+ movl 48(%esi),%ebp
+ movl %ebx,%edi
+ # R2 45
+ leal 3873151461(%edx,%ebp,1),%edx
+ addl %ebx,%eax
+ xorl %ecx,%edi
+ xorl %eax,%edi
+ movl 60(%esi),%ebp
+ addl %edi,%edx
+ movl %eax,%edi
+ roll $11,%edx
+ addl %eax,%edx
+ # R2 46
+ xorl %ebx,%edi
+ xorl %edx,%edi
+ leal 530742520(%ecx,%ebp,1),%ecx
+ addl %edi,%ecx
+ roll $16,%ecx
+ movl 8(%esi),%ebp
+ movl %edx,%edi
+ # R2 47
+ leal 3299628645(%ebx,%ebp,1),%ebx
+ addl %edx,%ecx
+ xorl %eax,%edi
+ xorl %ecx,%edi
+ movl (%esi),%ebp
+ addl %edi,%ebx
+ movl $-1,%edi
+ roll $23,%ebx
+ addl %ecx,%ebx
+
+ # R3 section
+ # R3 48
+ xorl %edx,%edi
+ orl %ebx,%edi
+ leal 4096336452(%eax,%ebp,1),%eax
+ xorl %ecx,%edi
+ movl 28(%esi),%ebp
+ addl %edi,%eax
+ movl $-1,%edi
+ roll $6,%eax
+ xorl %ecx,%edi
+ addl %ebx,%eax
+ # R3 49
+ orl %eax,%edi
+ leal 1126891415(%edx,%ebp,1),%edx
+ xorl %ebx,%edi
+ movl 56(%esi),%ebp
+ addl %edi,%edx
+ movl $-1,%edi
+ roll $10,%edx
+ xorl %ebx,%edi
+ addl %eax,%edx
+ # R3 50
+ orl %edx,%edi
+ leal 2878612391(%ecx,%ebp,1),%ecx
+ xorl %eax,%edi
+ movl 20(%esi),%ebp
+ addl %edi,%ecx
+ movl $-1,%edi
+ roll $15,%ecx
+ xorl %eax,%edi
+ addl %edx,%ecx
+ # R3 51
+ orl %ecx,%edi
+ leal 4237533241(%ebx,%ebp,1),%ebx
+ xorl %edx,%edi
+ movl 48(%esi),%ebp
+ addl %edi,%ebx
+ movl $-1,%edi
+ roll $21,%ebx
+ xorl %edx,%edi
+ addl %ecx,%ebx
+ # R3 52
+ orl %ebx,%edi
+ leal 1700485571(%eax,%ebp,1),%eax
+ xorl %ecx,%edi
+ movl 12(%esi),%ebp
+ addl %edi,%eax
+ movl $-1,%edi
+ roll $6,%eax
+ xorl %ecx,%edi
+ addl %ebx,%eax
+ # R3 53
+ orl %eax,%edi
+ leal 2399980690(%edx,%ebp,1),%edx
+ xorl %ebx,%edi
+ movl 40(%esi),%ebp
+ addl %edi,%edx
+ movl $-1,%edi
+ roll $10,%edx
+ xorl %ebx,%edi
+ addl %eax,%edx
+ # R3 54
+ orl %edx,%edi
+ leal 4293915773(%ecx,%ebp,1),%ecx
+ xorl %eax,%edi
+ movl 4(%esi),%ebp
+ addl %edi,%ecx
+ movl $-1,%edi
+ roll $15,%ecx
+ xorl %eax,%edi
+ addl %edx,%ecx
+ # R3 55
+ orl %ecx,%edi
+ leal 2240044497(%ebx,%ebp,1),%ebx
+ xorl %edx,%edi
+ movl 32(%esi),%ebp
+ addl %edi,%ebx
+ movl $-1,%edi
+ roll $21,%ebx
+ xorl %edx,%edi
+ addl %ecx,%ebx
+ # R3 56
+ orl %ebx,%edi
+ leal 1873313359(%eax,%ebp,1),%eax
+ xorl %ecx,%edi
+ movl 60(%esi),%ebp
+ addl %edi,%eax
+ movl $-1,%edi
+ roll $6,%eax
+ xorl %ecx,%edi
+ addl %ebx,%eax
+ # R3 57
+ orl %eax,%edi
+ leal 4264355552(%edx,%ebp,1),%edx
+ xorl %ebx,%edi
+ movl 24(%esi),%ebp
+ addl %edi,%edx
+ movl $-1,%edi
+ roll $10,%edx
+ xorl %ebx,%edi
+ addl %eax,%edx
+ # R3 58
+ orl %edx,%edi
+ leal 2734768916(%ecx,%ebp,1),%ecx
+ xorl %eax,%edi
+ movl 52(%esi),%ebp
+ addl %edi,%ecx
+ movl $-1,%edi
+ roll $15,%ecx
+ xorl %eax,%edi
+ addl %edx,%ecx
+ # R3 59
+ orl %ecx,%edi
+ leal 1309151649(%ebx,%ebp,1),%ebx
+ xorl %edx,%edi
+ movl 16(%esi),%ebp
+ addl %edi,%ebx
+ movl $-1,%edi
+ roll $21,%ebx
+ xorl %edx,%edi
+ addl %ecx,%ebx
+ # R3 60
+ orl %ebx,%edi
+ leal 4149444226(%eax,%ebp,1),%eax
+ xorl %ecx,%edi
+ movl 44(%esi),%ebp
+ addl %edi,%eax
+ movl $-1,%edi
+ roll $6,%eax
+ xorl %ecx,%edi
+ addl %ebx,%eax
+ # R3 61
+ orl %eax,%edi
+ leal 3174756917(%edx,%ebp,1),%edx
+ xorl %ebx,%edi
+ movl 8(%esi),%ebp
+ addl %edi,%edx
+ movl $-1,%edi
+ roll $10,%edx
+ xorl %ebx,%edi
+ addl %eax,%edx
+ # R3 62
+ orl %edx,%edi
+ leal 718787259(%ecx,%ebp,1),%ecx
+ xorl %eax,%edi
+ movl 36(%esi),%ebp
+ addl %edi,%ecx
+ movl $-1,%edi
+ roll $15,%ecx
+ xorl %eax,%edi
+ addl %edx,%ecx
+ # R3 63
+ orl %ecx,%edi
+ leal 3951481745(%ebx,%ebp,1),%ebx
+ xorl %edx,%edi
+ movl 24(%esp),%ebp
+ addl %edi,%ebx
+ addl $64,%esi
+ roll $21,%ebx
+ movl (%ebp),%edi
+ addl %ecx,%ebx
+ addl %edi,%eax
+ movl 4(%ebp),%edi
+ addl %edi,%ebx
+ movl 8(%ebp),%edi
+ addl %edi,%ecx
+ movl 12(%ebp),%edi
+ addl %edi,%edx
+ movl %eax,(%ebp)
+ movl %ebx,4(%ebp)
+ movl (%esp),%edi
+ movl %ecx,8(%ebp)
+ movl %edx,12(%ebp)
+ cmpl %esi,%edi
+ jae L000start
+ popl %eax
+ popl %ebx
+ popl %ebp
+ popl %edi
+ popl %esi
+ ret
+#endif
diff --git a/mac-x86/crypto/modes/ghash-x86.S b/mac-x86/crypto/modes/ghash-x86.S
new file mode 100644
index 0000000..8693b82
--- /dev/null
+++ b/mac-x86/crypto/modes/ghash-x86.S
@@ -0,0 +1,1260 @@
+#if defined(__i386__)
+.file "ghash-x86.S"
+.text
+.globl _gcm_gmult_4bit_x86
+.private_extern _gcm_gmult_4bit_x86
+.align 4
+_gcm_gmult_4bit_x86:
+L_gcm_gmult_4bit_x86_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ subl $84,%esp
+ movl 104(%esp),%edi
+ movl 108(%esp),%esi
+ movl (%edi),%ebp
+ movl 4(%edi),%edx
+ movl 8(%edi),%ecx
+ movl 12(%edi),%ebx
+ movl $0,16(%esp)
+ movl $471859200,20(%esp)
+ movl $943718400,24(%esp)
+ movl $610271232,28(%esp)
+ movl $1887436800,32(%esp)
+ movl $1822425088,36(%esp)
+ movl $1220542464,40(%esp)
+ movl $1423966208,44(%esp)
+ movl $3774873600,48(%esp)
+ movl $4246732800,52(%esp)
+ movl $3644850176,56(%esp)
+ movl $3311403008,60(%esp)
+ movl $2441084928,64(%esp)
+ movl $2376073216,68(%esp)
+ movl $2847932416,72(%esp)
+ movl $3051356160,76(%esp)
+ movl %ebp,(%esp)
+ movl %edx,4(%esp)
+ movl %ecx,8(%esp)
+ movl %ebx,12(%esp)
+ shrl $20,%ebx
+ andl $240,%ebx
+ movl 4(%esi,%ebx,1),%ebp
+ movl (%esi,%ebx,1),%edx
+ movl 12(%esi,%ebx,1),%ecx
+ movl 8(%esi,%ebx,1),%ebx
+ xorl %eax,%eax
+ movl $15,%edi
+ jmp L000x86_loop
+.align 4,0x90
+L000x86_loop:
+ movb %bl,%al
+ shrdl $4,%ecx,%ebx
+ andb $15,%al
+ shrdl $4,%edx,%ecx
+ shrdl $4,%ebp,%edx
+ shrl $4,%ebp
+ xorl 16(%esp,%eax,4),%ebp
+ movb (%esp,%edi,1),%al
+ andb $240,%al
+ xorl 8(%esi,%eax,1),%ebx
+ xorl 12(%esi,%eax,1),%ecx
+ xorl (%esi,%eax,1),%edx
+ xorl 4(%esi,%eax,1),%ebp
+ decl %edi
+ js L001x86_break
+ movb %bl,%al
+ shrdl $4,%ecx,%ebx
+ andb $15,%al
+ shrdl $4,%edx,%ecx
+ shrdl $4,%ebp,%edx
+ shrl $4,%ebp
+ xorl 16(%esp,%eax,4),%ebp
+ movb (%esp,%edi,1),%al
+ shlb $4,%al
+ xorl 8(%esi,%eax,1),%ebx
+ xorl 12(%esi,%eax,1),%ecx
+ xorl (%esi,%eax,1),%edx
+ xorl 4(%esi,%eax,1),%ebp
+ jmp L000x86_loop
+.align 4,0x90
+L001x86_break:
+ bswap %ebx
+ bswap %ecx
+ bswap %edx
+ bswap %ebp
+ movl 104(%esp),%edi
+ movl %ebx,12(%edi)
+ movl %ecx,8(%edi)
+ movl %edx,4(%edi)
+ movl %ebp,(%edi)
+ addl $84,%esp
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.globl _gcm_ghash_4bit_x86
+.private_extern _gcm_ghash_4bit_x86
+.align 4
+_gcm_ghash_4bit_x86:
+L_gcm_ghash_4bit_x86_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ subl $84,%esp
+ movl 104(%esp),%ebx
+ movl 108(%esp),%esi
+ movl 112(%esp),%edi
+ movl 116(%esp),%ecx
+ addl %edi,%ecx
+ movl %ecx,116(%esp)
+ movl (%ebx),%ebp
+ movl 4(%ebx),%edx
+ movl 8(%ebx),%ecx
+ movl 12(%ebx),%ebx
+ movl $0,16(%esp)
+ movl $471859200,20(%esp)
+ movl $943718400,24(%esp)
+ movl $610271232,28(%esp)
+ movl $1887436800,32(%esp)
+ movl $1822425088,36(%esp)
+ movl $1220542464,40(%esp)
+ movl $1423966208,44(%esp)
+ movl $3774873600,48(%esp)
+ movl $4246732800,52(%esp)
+ movl $3644850176,56(%esp)
+ movl $3311403008,60(%esp)
+ movl $2441084928,64(%esp)
+ movl $2376073216,68(%esp)
+ movl $2847932416,72(%esp)
+ movl $3051356160,76(%esp)
+.align 4,0x90
+L002x86_outer_loop:
+ xorl 12(%edi),%ebx
+ xorl 8(%edi),%ecx
+ xorl 4(%edi),%edx
+ xorl (%edi),%ebp
+ movl %ebx,12(%esp)
+ movl %ecx,8(%esp)
+ movl %edx,4(%esp)
+ movl %ebp,(%esp)
+ shrl $20,%ebx
+ andl $240,%ebx
+ movl 4(%esi,%ebx,1),%ebp
+ movl (%esi,%ebx,1),%edx
+ movl 12(%esi,%ebx,1),%ecx
+ movl 8(%esi,%ebx,1),%ebx
+ xorl %eax,%eax
+ movl $15,%edi
+ jmp L003x86_loop
+.align 4,0x90
+L003x86_loop:
+ movb %bl,%al
+ shrdl $4,%ecx,%ebx
+ andb $15,%al
+ shrdl $4,%edx,%ecx
+ shrdl $4,%ebp,%edx
+ shrl $4,%ebp
+ xorl 16(%esp,%eax,4),%ebp
+ movb (%esp,%edi,1),%al
+ andb $240,%al
+ xorl 8(%esi,%eax,1),%ebx
+ xorl 12(%esi,%eax,1),%ecx
+ xorl (%esi,%eax,1),%edx
+ xorl 4(%esi,%eax,1),%ebp
+ decl %edi
+ js L004x86_break
+ movb %bl,%al
+ shrdl $4,%ecx,%ebx
+ andb $15,%al
+ shrdl $4,%edx,%ecx
+ shrdl $4,%ebp,%edx
+ shrl $4,%ebp
+ xorl 16(%esp,%eax,4),%ebp
+ movb (%esp,%edi,1),%al
+ shlb $4,%al
+ xorl 8(%esi,%eax,1),%ebx
+ xorl 12(%esi,%eax,1),%ecx
+ xorl (%esi,%eax,1),%edx
+ xorl 4(%esi,%eax,1),%ebp
+ jmp L003x86_loop
+.align 4,0x90
+L004x86_break:
+ bswap %ebx
+ bswap %ecx
+ bswap %edx
+ bswap %ebp
+ movl 112(%esp),%edi
+ leal 16(%edi),%edi
+ cmpl 116(%esp),%edi
+ movl %edi,112(%esp)
+ jb L002x86_outer_loop
+ movl 104(%esp),%edi
+ movl %ebx,12(%edi)
+ movl %ecx,8(%edi)
+ movl %edx,4(%edi)
+ movl %ebp,(%edi)
+ addl $84,%esp
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.globl _gcm_gmult_4bit_mmx
+.private_extern _gcm_gmult_4bit_mmx
+.align 4
+_gcm_gmult_4bit_mmx:
+L_gcm_gmult_4bit_mmx_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ movl 20(%esp),%edi
+ movl 24(%esp),%esi
+ call L005pic_point
+L005pic_point:
+ popl %eax
+ leal Lrem_4bit-L005pic_point(%eax),%eax
+ movzbl 15(%edi),%ebx
+ xorl %ecx,%ecx
+ movl %ebx,%edx
+ movb %dl,%cl
+ movl $14,%ebp
+ shlb $4,%cl
+ andl $240,%edx
+ movq 8(%esi,%ecx,1),%mm0
+ movq (%esi,%ecx,1),%mm1
+ movd %mm0,%ebx
+ jmp L006mmx_loop
+.align 4,0x90
+L006mmx_loop:
+ psrlq $4,%mm0
+ andl $15,%ebx
+ movq %mm1,%mm2
+ psrlq $4,%mm1
+ pxor 8(%esi,%edx,1),%mm0
+ movb (%edi,%ebp,1),%cl
+ psllq $60,%mm2
+ pxor (%eax,%ebx,8),%mm1
+ decl %ebp
+ movd %mm0,%ebx
+ pxor (%esi,%edx,1),%mm1
+ movl %ecx,%edx
+ pxor %mm2,%mm0
+ js L007mmx_break
+ shlb $4,%cl
+ andl $15,%ebx
+ psrlq $4,%mm0
+ andl $240,%edx
+ movq %mm1,%mm2
+ psrlq $4,%mm1
+ pxor 8(%esi,%ecx,1),%mm0
+ psllq $60,%mm2
+ pxor (%eax,%ebx,8),%mm1
+ movd %mm0,%ebx
+ pxor (%esi,%ecx,1),%mm1
+ pxor %mm2,%mm0
+ jmp L006mmx_loop
+.align 4,0x90
+L007mmx_break:
+ shlb $4,%cl
+ andl $15,%ebx
+ psrlq $4,%mm0
+ andl $240,%edx
+ movq %mm1,%mm2
+ psrlq $4,%mm1
+ pxor 8(%esi,%ecx,1),%mm0
+ psllq $60,%mm2
+ pxor (%eax,%ebx,8),%mm1
+ movd %mm0,%ebx
+ pxor (%esi,%ecx,1),%mm1
+ pxor %mm2,%mm0
+ psrlq $4,%mm0
+ andl $15,%ebx
+ movq %mm1,%mm2
+ psrlq $4,%mm1
+ pxor 8(%esi,%edx,1),%mm0
+ psllq $60,%mm2
+ pxor (%eax,%ebx,8),%mm1
+ movd %mm0,%ebx
+ pxor (%esi,%edx,1),%mm1
+ pxor %mm2,%mm0
+ psrlq $32,%mm0
+ movd %mm1,%edx
+ psrlq $32,%mm1
+ movd %mm0,%ecx
+ movd %mm1,%ebp
+ bswap %ebx
+ bswap %edx
+ bswap %ecx
+ bswap %ebp
+ emms
+ movl %ebx,12(%edi)
+ movl %edx,4(%edi)
+ movl %ecx,8(%edi)
+ movl %ebp,(%edi)
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.globl _gcm_ghash_4bit_mmx
+.private_extern _gcm_ghash_4bit_mmx
+.align 4
+_gcm_ghash_4bit_mmx:
+L_gcm_ghash_4bit_mmx_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ movl 20(%esp),%eax
+ movl 24(%esp),%ebx
+ movl 28(%esp),%ecx
+ movl 32(%esp),%edx
+ movl %esp,%ebp
+ call L008pic_point
+L008pic_point:
+ popl %esi
+ leal Lrem_8bit-L008pic_point(%esi),%esi
+ subl $544,%esp
+ andl $-64,%esp
+ subl $16,%esp
+ addl %ecx,%edx
+ movl %eax,544(%esp)
+ movl %edx,552(%esp)
+ movl %ebp,556(%esp)
+ addl $128,%ebx
+ leal 144(%esp),%edi
+ leal 400(%esp),%ebp
+ movl -120(%ebx),%edx
+ movq -120(%ebx),%mm0
+ movq -128(%ebx),%mm3
+ shll $4,%edx
+ movb %dl,(%esp)
+ movl -104(%ebx),%edx
+ movq -104(%ebx),%mm2
+ movq -112(%ebx),%mm5
+ movq %mm0,-128(%edi)
+ psrlq $4,%mm0
+ movq %mm3,(%edi)
+ movq %mm3,%mm7
+ psrlq $4,%mm3
+ shll $4,%edx
+ movb %dl,1(%esp)
+ movl -88(%ebx),%edx
+ movq -88(%ebx),%mm1
+ psllq $60,%mm7
+ movq -96(%ebx),%mm4
+ por %mm7,%mm0
+ movq %mm2,-120(%edi)
+ psrlq $4,%mm2
+ movq %mm5,8(%edi)
+ movq %mm5,%mm6
+ movq %mm0,-128(%ebp)
+ psrlq $4,%mm5
+ movq %mm3,(%ebp)
+ shll $4,%edx
+ movb %dl,2(%esp)
+ movl -72(%ebx),%edx
+ movq -72(%ebx),%mm0
+ psllq $60,%mm6
+ movq -80(%ebx),%mm3
+ por %mm6,%mm2
+ movq %mm1,-112(%edi)
+ psrlq $4,%mm1
+ movq %mm4,16(%edi)
+ movq %mm4,%mm7
+ movq %mm2,-120(%ebp)
+ psrlq $4,%mm4
+ movq %mm5,8(%ebp)
+ shll $4,%edx
+ movb %dl,3(%esp)
+ movl -56(%ebx),%edx
+ movq -56(%ebx),%mm2
+ psllq $60,%mm7
+ movq -64(%ebx),%mm5
+ por %mm7,%mm1
+ movq %mm0,-104(%edi)
+ psrlq $4,%mm0
+ movq %mm3,24(%edi)
+ movq %mm3,%mm6
+ movq %mm1,-112(%ebp)
+ psrlq $4,%mm3
+ movq %mm4,16(%ebp)
+ shll $4,%edx
+ movb %dl,4(%esp)
+ movl -40(%ebx),%edx
+ movq -40(%ebx),%mm1
+ psllq $60,%mm6
+ movq -48(%ebx),%mm4
+ por %mm6,%mm0
+ movq %mm2,-96(%edi)
+ psrlq $4,%mm2
+ movq %mm5,32(%edi)
+ movq %mm5,%mm7
+ movq %mm0,-104(%ebp)
+ psrlq $4,%mm5
+ movq %mm3,24(%ebp)
+ shll $4,%edx
+ movb %dl,5(%esp)
+ movl -24(%ebx),%edx
+ movq -24(%ebx),%mm0
+ psllq $60,%mm7
+ movq -32(%ebx),%mm3
+ por %mm7,%mm2
+ movq %mm1,-88(%edi)
+ psrlq $4,%mm1
+ movq %mm4,40(%edi)
+ movq %mm4,%mm6
+ movq %mm2,-96(%ebp)
+ psrlq $4,%mm4
+ movq %mm5,32(%ebp)
+ shll $4,%edx
+ movb %dl,6(%esp)
+ movl -8(%ebx),%edx
+ movq -8(%ebx),%mm2
+ psllq $60,%mm6
+ movq -16(%ebx),%mm5
+ por %mm6,%mm1
+ movq %mm0,-80(%edi)
+ psrlq $4,%mm0
+ movq %mm3,48(%edi)
+ movq %mm3,%mm7
+ movq %mm1,-88(%ebp)
+ psrlq $4,%mm3
+ movq %mm4,40(%ebp)
+ shll $4,%edx
+ movb %dl,7(%esp)
+ movl 8(%ebx),%edx
+ movq 8(%ebx),%mm1
+ psllq $60,%mm7
+ movq (%ebx),%mm4
+ por %mm7,%mm0
+ movq %mm2,-72(%edi)
+ psrlq $4,%mm2
+ movq %mm5,56(%edi)
+ movq %mm5,%mm6
+ movq %mm0,-80(%ebp)
+ psrlq $4,%mm5
+ movq %mm3,48(%ebp)
+ shll $4,%edx
+ movb %dl,8(%esp)
+ movl 24(%ebx),%edx
+ movq 24(%ebx),%mm0
+ psllq $60,%mm6
+ movq 16(%ebx),%mm3
+ por %mm6,%mm2
+ movq %mm1,-64(%edi)
+ psrlq $4,%mm1
+ movq %mm4,64(%edi)
+ movq %mm4,%mm7
+ movq %mm2,-72(%ebp)
+ psrlq $4,%mm4
+ movq %mm5,56(%ebp)
+ shll $4,%edx
+ movb %dl,9(%esp)
+ movl 40(%ebx),%edx
+ movq 40(%ebx),%mm2
+ psllq $60,%mm7
+ movq 32(%ebx),%mm5
+ por %mm7,%mm1
+ movq %mm0,-56(%edi)
+ psrlq $4,%mm0
+ movq %mm3,72(%edi)
+ movq %mm3,%mm6
+ movq %mm1,-64(%ebp)
+ psrlq $4,%mm3
+ movq %mm4,64(%ebp)
+ shll $4,%edx
+ movb %dl,10(%esp)
+ movl 56(%ebx),%edx
+ movq 56(%ebx),%mm1
+ psllq $60,%mm6
+ movq 48(%ebx),%mm4
+ por %mm6,%mm0
+ movq %mm2,-48(%edi)
+ psrlq $4,%mm2
+ movq %mm5,80(%edi)
+ movq %mm5,%mm7
+ movq %mm0,-56(%ebp)
+ psrlq $4,%mm5
+ movq %mm3,72(%ebp)
+ shll $4,%edx
+ movb %dl,11(%esp)
+ movl 72(%ebx),%edx
+ movq 72(%ebx),%mm0
+ psllq $60,%mm7
+ movq 64(%ebx),%mm3
+ por %mm7,%mm2
+ movq %mm1,-40(%edi)
+ psrlq $4,%mm1
+ movq %mm4,88(%edi)
+ movq %mm4,%mm6
+ movq %mm2,-48(%ebp)
+ psrlq $4,%mm4
+ movq %mm5,80(%ebp)
+ shll $4,%edx
+ movb %dl,12(%esp)
+ movl 88(%ebx),%edx
+ movq 88(%ebx),%mm2
+ psllq $60,%mm6
+ movq 80(%ebx),%mm5
+ por %mm6,%mm1
+ movq %mm0,-32(%edi)
+ psrlq $4,%mm0
+ movq %mm3,96(%edi)
+ movq %mm3,%mm7
+ movq %mm1,-40(%ebp)
+ psrlq $4,%mm3
+ movq %mm4,88(%ebp)
+ shll $4,%edx
+ movb %dl,13(%esp)
+ movl 104(%ebx),%edx
+ movq 104(%ebx),%mm1
+ psllq $60,%mm7
+ movq 96(%ebx),%mm4
+ por %mm7,%mm0
+ movq %mm2,-24(%edi)
+ psrlq $4,%mm2
+ movq %mm5,104(%edi)
+ movq %mm5,%mm6
+ movq %mm0,-32(%ebp)
+ psrlq $4,%mm5
+ movq %mm3,96(%ebp)
+ shll $4,%edx
+ movb %dl,14(%esp)
+ movl 120(%ebx),%edx
+ movq 120(%ebx),%mm0
+ psllq $60,%mm6
+ movq 112(%ebx),%mm3
+ por %mm6,%mm2
+ movq %mm1,-16(%edi)
+ psrlq $4,%mm1
+ movq %mm4,112(%edi)
+ movq %mm4,%mm7
+ movq %mm2,-24(%ebp)
+ psrlq $4,%mm4
+ movq %mm5,104(%ebp)
+ shll $4,%edx
+ movb %dl,15(%esp)
+ psllq $60,%mm7
+ por %mm7,%mm1
+ movq %mm0,-8(%edi)
+ psrlq $4,%mm0
+ movq %mm3,120(%edi)
+ movq %mm3,%mm6
+ movq %mm1,-16(%ebp)
+ psrlq $4,%mm3
+ movq %mm4,112(%ebp)
+ psllq $60,%mm6
+ por %mm6,%mm0
+ movq %mm0,-8(%ebp)
+ movq %mm3,120(%ebp)
+ movq (%eax),%mm6
+ movl 8(%eax),%ebx
+ movl 12(%eax),%edx
+.align 4,0x90
+L009outer:
+ xorl 12(%ecx),%edx
+ xorl 8(%ecx),%ebx
+ pxor (%ecx),%mm6
+ leal 16(%ecx),%ecx
+ movl %ebx,536(%esp)
+ movq %mm6,528(%esp)
+ movl %ecx,548(%esp)
+ xorl %eax,%eax
+ roll $8,%edx
+ movb %dl,%al
+ movl %eax,%ebp
+ andb $15,%al
+ shrl $4,%ebp
+ pxor %mm0,%mm0
+ roll $8,%edx
+ pxor %mm1,%mm1
+ pxor %mm2,%mm2
+ movq 16(%esp,%eax,8),%mm7
+ movq 144(%esp,%eax,8),%mm6
+ movb %dl,%al
+ movd %mm7,%ebx
+ psrlq $8,%mm7
+ movq %mm6,%mm3
+ movl %eax,%edi
+ psrlq $8,%mm6
+ pxor 272(%esp,%ebp,8),%mm7
+ andb $15,%al
+ psllq $56,%mm3
+ shrl $4,%edi
+ pxor 16(%esp,%eax,8),%mm7
+ roll $8,%edx
+ pxor 144(%esp,%eax,8),%mm6
+ pxor %mm3,%mm7
+ pxor 400(%esp,%ebp,8),%mm6
+ xorb (%esp,%ebp,1),%bl
+ movb %dl,%al
+ movd %mm7,%ecx
+ movzbl %bl,%ebx
+ psrlq $8,%mm7
+ movq %mm6,%mm3
+ movl %eax,%ebp
+ psrlq $8,%mm6
+ pxor 272(%esp,%edi,8),%mm7
+ andb $15,%al
+ psllq $56,%mm3
+ shrl $4,%ebp
+ pinsrw $2,(%esi,%ebx,2),%mm2
+ pxor 16(%esp,%eax,8),%mm7
+ roll $8,%edx
+ pxor 144(%esp,%eax,8),%mm6
+ pxor %mm3,%mm7
+ pxor 400(%esp,%edi,8),%mm6
+ xorb (%esp,%edi,1),%cl
+ movb %dl,%al
+ movl 536(%esp),%edx
+ movd %mm7,%ebx
+ movzbl %cl,%ecx
+ psrlq $8,%mm7
+ movq %mm6,%mm3
+ movl %eax,%edi
+ psrlq $8,%mm6
+ pxor 272(%esp,%ebp,8),%mm7
+ andb $15,%al
+ psllq $56,%mm3
+ pxor %mm2,%mm6
+ shrl $4,%edi
+ pinsrw $2,(%esi,%ecx,2),%mm1
+ pxor 16(%esp,%eax,8),%mm7
+ roll $8,%edx
+ pxor 144(%esp,%eax,8),%mm6
+ pxor %mm3,%mm7
+ pxor 400(%esp,%ebp,8),%mm6
+ xorb (%esp,%ebp,1),%bl
+ movb %dl,%al
+ movd %mm7,%ecx
+ movzbl %bl,%ebx
+ psrlq $8,%mm7
+ movq %mm6,%mm3
+ movl %eax,%ebp
+ psrlq $8,%mm6
+ pxor 272(%esp,%edi,8),%mm7
+ andb $15,%al
+ psllq $56,%mm3
+ pxor %mm1,%mm6
+ shrl $4,%ebp
+ pinsrw $2,(%esi,%ebx,2),%mm0
+ pxor 16(%esp,%eax,8),%mm7
+ roll $8,%edx
+ pxor 144(%esp,%eax,8),%mm6
+ pxor %mm3,%mm7
+ pxor 400(%esp,%edi,8),%mm6
+ xorb (%esp,%edi,1),%cl
+ movb %dl,%al
+ movd %mm7,%ebx
+ movzbl %cl,%ecx
+ psrlq $8,%mm7
+ movq %mm6,%mm3
+ movl %eax,%edi
+ psrlq $8,%mm6
+ pxor 272(%esp,%ebp,8),%mm7
+ andb $15,%al
+ psllq $56,%mm3
+ pxor %mm0,%mm6
+ shrl $4,%edi
+ pinsrw $2,(%esi,%ecx,2),%mm2
+ pxor 16(%esp,%eax,8),%mm7
+ roll $8,%edx
+ pxor 144(%esp,%eax,8),%mm6
+ pxor %mm3,%mm7
+ pxor 400(%esp,%ebp,8),%mm6
+ xorb (%esp,%ebp,1),%bl
+ movb %dl,%al
+ movd %mm7,%ecx
+ movzbl %bl,%ebx
+ psrlq $8,%mm7
+ movq %mm6,%mm3
+ movl %eax,%ebp
+ psrlq $8,%mm6
+ pxor 272(%esp,%edi,8),%mm7
+ andb $15,%al
+ psllq $56,%mm3
+ pxor %mm2,%mm6
+ shrl $4,%ebp
+ pinsrw $2,(%esi,%ebx,2),%mm1
+ pxor 16(%esp,%eax,8),%mm7
+ roll $8,%edx
+ pxor 144(%esp,%eax,8),%mm6
+ pxor %mm3,%mm7
+ pxor 400(%esp,%edi,8),%mm6
+ xorb (%esp,%edi,1),%cl
+ movb %dl,%al
+ movl 532(%esp),%edx
+ movd %mm7,%ebx
+ movzbl %cl,%ecx
+ psrlq $8,%mm7
+ movq %mm6,%mm3
+ movl %eax,%edi
+ psrlq $8,%mm6
+ pxor 272(%esp,%ebp,8),%mm7
+ andb $15,%al
+ psllq $56,%mm3
+ pxor %mm1,%mm6
+ shrl $4,%edi
+ pinsrw $2,(%esi,%ecx,2),%mm0
+ pxor 16(%esp,%eax,8),%mm7
+ roll $8,%edx
+ pxor 144(%esp,%eax,8),%mm6
+ pxor %mm3,%mm7
+ pxor 400(%esp,%ebp,8),%mm6
+ xorb (%esp,%ebp,1),%bl
+ movb %dl,%al
+ movd %mm7,%ecx
+ movzbl %bl,%ebx
+ psrlq $8,%mm7
+ movq %mm6,%mm3
+ movl %eax,%ebp
+ psrlq $8,%mm6
+ pxor 272(%esp,%edi,8),%mm7
+ andb $15,%al
+ psllq $56,%mm3
+ pxor %mm0,%mm6
+ shrl $4,%ebp
+ pinsrw $2,(%esi,%ebx,2),%mm2
+ pxor 16(%esp,%eax,8),%mm7
+ roll $8,%edx
+ pxor 144(%esp,%eax,8),%mm6
+ pxor %mm3,%mm7
+ pxor 400(%esp,%edi,8),%mm6
+ xorb (%esp,%edi,1),%cl
+ movb %dl,%al
+ movd %mm7,%ebx
+ movzbl %cl,%ecx
+ psrlq $8,%mm7
+ movq %mm6,%mm3
+ movl %eax,%edi
+ psrlq $8,%mm6
+ pxor 272(%esp,%ebp,8),%mm7
+ andb $15,%al
+ psllq $56,%mm3
+ pxor %mm2,%mm6
+ shrl $4,%edi
+ pinsrw $2,(%esi,%ecx,2),%mm1
+ pxor 16(%esp,%eax,8),%mm7
+ roll $8,%edx
+ pxor 144(%esp,%eax,8),%mm6
+ pxor %mm3,%mm7
+ pxor 400(%esp,%ebp,8),%mm6
+ xorb (%esp,%ebp,1),%bl
+ movb %dl,%al
+ movd %mm7,%ecx
+ movzbl %bl,%ebx
+ psrlq $8,%mm7
+ movq %mm6,%mm3
+ movl %eax,%ebp
+ psrlq $8,%mm6
+ pxor 272(%esp,%edi,8),%mm7
+ andb $15,%al
+ psllq $56,%mm3
+ pxor %mm1,%mm6
+ shrl $4,%ebp
+ pinsrw $2,(%esi,%ebx,2),%mm0
+ pxor 16(%esp,%eax,8),%mm7
+ roll $8,%edx
+ pxor 144(%esp,%eax,8),%mm6
+ pxor %mm3,%mm7
+ pxor 400(%esp,%edi,8),%mm6
+ xorb (%esp,%edi,1),%cl
+ movb %dl,%al
+ movl 528(%esp),%edx
+ movd %mm7,%ebx
+ movzbl %cl,%ecx
+ psrlq $8,%mm7
+ movq %mm6,%mm3
+ movl %eax,%edi
+ psrlq $8,%mm6
+ pxor 272(%esp,%ebp,8),%mm7
+ andb $15,%al
+ psllq $56,%mm3
+ pxor %mm0,%mm6
+ shrl $4,%edi
+ pinsrw $2,(%esi,%ecx,2),%mm2
+ pxor 16(%esp,%eax,8),%mm7
+ roll $8,%edx
+ pxor 144(%esp,%eax,8),%mm6
+ pxor %mm3,%mm7
+ pxor 400(%esp,%ebp,8),%mm6
+ xorb (%esp,%ebp,1),%bl
+ movb %dl,%al
+ movd %mm7,%ecx
+ movzbl %bl,%ebx
+ psrlq $8,%mm7
+ movq %mm6,%mm3
+ movl %eax,%ebp
+ psrlq $8,%mm6
+ pxor 272(%esp,%edi,8),%mm7
+ andb $15,%al
+ psllq $56,%mm3
+ pxor %mm2,%mm6
+ shrl $4,%ebp
+ pinsrw $2,(%esi,%ebx,2),%mm1
+ pxor 16(%esp,%eax,8),%mm7
+ roll $8,%edx
+ pxor 144(%esp,%eax,8),%mm6
+ pxor %mm3,%mm7
+ pxor 400(%esp,%edi,8),%mm6
+ xorb (%esp,%edi,1),%cl
+ movb %dl,%al
+ movd %mm7,%ebx
+ movzbl %cl,%ecx
+ psrlq $8,%mm7
+ movq %mm6,%mm3
+ movl %eax,%edi
+ psrlq $8,%mm6
+ pxor 272(%esp,%ebp,8),%mm7
+ andb $15,%al
+ psllq $56,%mm3
+ pxor %mm1,%mm6
+ shrl $4,%edi
+ pinsrw $2,(%esi,%ecx,2),%mm0
+ pxor 16(%esp,%eax,8),%mm7
+ roll $8,%edx
+ pxor 144(%esp,%eax,8),%mm6
+ pxor %mm3,%mm7
+ pxor 400(%esp,%ebp,8),%mm6
+ xorb (%esp,%ebp,1),%bl
+ movb %dl,%al
+ movd %mm7,%ecx
+ movzbl %bl,%ebx
+ psrlq $8,%mm7
+ movq %mm6,%mm3
+ movl %eax,%ebp
+ psrlq $8,%mm6
+ pxor 272(%esp,%edi,8),%mm7
+ andb $15,%al
+ psllq $56,%mm3
+ pxor %mm0,%mm6
+ shrl $4,%ebp
+ pinsrw $2,(%esi,%ebx,2),%mm2
+ pxor 16(%esp,%eax,8),%mm7
+ roll $8,%edx
+ pxor 144(%esp,%eax,8),%mm6
+ pxor %mm3,%mm7
+ pxor 400(%esp,%edi,8),%mm6
+ xorb (%esp,%edi,1),%cl
+ movb %dl,%al
+ movl 524(%esp),%edx
+ movd %mm7,%ebx
+ movzbl %cl,%ecx
+ psrlq $8,%mm7
+ movq %mm6,%mm3
+ movl %eax,%edi
+ psrlq $8,%mm6
+ pxor 272(%esp,%ebp,8),%mm7
+ andb $15,%al
+ psllq $56,%mm3
+ pxor %mm2,%mm6
+ shrl $4,%edi
+ pinsrw $2,(%esi,%ecx,2),%mm1
+ pxor 16(%esp,%eax,8),%mm7
+ pxor 144(%esp,%eax,8),%mm6
+ xorb (%esp,%ebp,1),%bl
+ pxor %mm3,%mm7
+ pxor 400(%esp,%ebp,8),%mm6
+ movzbl %bl,%ebx
+ pxor %mm2,%mm2
+ psllq $4,%mm1
+ movd %mm7,%ecx
+ psrlq $4,%mm7
+ movq %mm6,%mm3
+ psrlq $4,%mm6
+ shll $4,%ecx
+ pxor 16(%esp,%edi,8),%mm7
+ psllq $60,%mm3
+ movzbl %cl,%ecx
+ pxor %mm3,%mm7
+ pxor 144(%esp,%edi,8),%mm6
+ pinsrw $2,(%esi,%ebx,2),%mm0
+ pxor %mm1,%mm6
+ movd %mm7,%edx
+ pinsrw $3,(%esi,%ecx,2),%mm2
+ psllq $12,%mm0
+ pxor %mm0,%mm6
+ psrlq $32,%mm7
+ pxor %mm2,%mm6
+ movl 548(%esp),%ecx
+ movd %mm7,%ebx
+ movq %mm6,%mm3
+ psllw $8,%mm6
+ psrlw $8,%mm3
+ por %mm3,%mm6
+ bswap %edx
+ pshufw $27,%mm6,%mm6
+ bswap %ebx
+ cmpl 552(%esp),%ecx
+ jne L009outer
+ movl 544(%esp),%eax
+ movl %edx,12(%eax)
+ movl %ebx,8(%eax)
+ movq %mm6,(%eax)
+ movl 556(%esp),%esp
+ emms
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.globl _gcm_init_clmul
+.private_extern _gcm_init_clmul
+.align 4
+_gcm_init_clmul:
+L_gcm_init_clmul_begin:
+ movl 4(%esp),%edx
+ movl 8(%esp),%eax
+ call L010pic
+L010pic:
+ popl %ecx
+ leal Lbswap-L010pic(%ecx),%ecx
+ movdqu (%eax),%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 16(%ecx),%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
+ xorps %xmm0,%xmm3
+ xorps %xmm1,%xmm3
+ movdqa %xmm3,%xmm4
+ psrldq $8,%xmm3
+ pslldq $8,%xmm4
+ pxor %xmm3,%xmm1
+ pxor %xmm4,%xmm0
+ movdqa %xmm0,%xmm4
+ movdqa %xmm0,%xmm3
+ psllq $5,%xmm0
+ pxor %xmm0,%xmm3
+ psllq $1,%xmm0
+ pxor %xmm3,%xmm0
+ psllq $57,%xmm0
+ movdqa %xmm0,%xmm3
+ pslldq $8,%xmm0
+ psrldq $8,%xmm3
+ pxor %xmm4,%xmm0
+ pxor %xmm3,%xmm1
+ movdqa %xmm0,%xmm4
+ psrlq $1,%xmm0
+ pxor %xmm4,%xmm1
+ pxor %xmm0,%xmm4
+ psrlq $5,%xmm0
+ pxor %xmm4,%xmm0
+ psrlq $1,%xmm0
+ pxor %xmm1,%xmm0
+ pshufd $78,%xmm2,%xmm3
+ pshufd $78,%xmm0,%xmm4
+ pxor %xmm2,%xmm3
+ movdqu %xmm2,(%edx)
+ pxor %xmm0,%xmm4
+ movdqu %xmm0,16(%edx)
+.byte 102,15,58,15,227,8
+ movdqu %xmm4,32(%edx)
+ ret
+.globl _gcm_gmult_clmul
+.private_extern _gcm_gmult_clmul
+.align 4
+_gcm_gmult_clmul:
+L_gcm_gmult_clmul_begin:
+ movl 4(%esp),%eax
+ movl 8(%esp),%edx
+ call L011pic
+L011pic:
+ popl %ecx
+ leal Lbswap-L011pic(%ecx),%ecx
+ movdqu (%eax),%xmm0
+ movdqa (%ecx),%xmm5
+ movups (%edx),%xmm2
+.byte 102,15,56,0,197
+ movups 32(%edx),%xmm4
+ movdqa %xmm0,%xmm1
+ pshufd $78,%xmm0,%xmm3
+ pxor %xmm0,%xmm3
+.byte 102,15,58,68,194,0
+.byte 102,15,58,68,202,17
+.byte 102,15,58,68,220,0
+ xorps %xmm0,%xmm3
+ xorps %xmm1,%xmm3
+ movdqa %xmm3,%xmm4
+ psrldq $8,%xmm3
+ pslldq $8,%xmm4
+ pxor %xmm3,%xmm1
+ pxor %xmm4,%xmm0
+ movdqa %xmm0,%xmm4
+ movdqa %xmm0,%xmm3
+ psllq $5,%xmm0
+ pxor %xmm0,%xmm3
+ psllq $1,%xmm0
+ pxor %xmm3,%xmm0
+ psllq $57,%xmm0
+ movdqa %xmm0,%xmm3
+ pslldq $8,%xmm0
+ psrldq $8,%xmm3
+ pxor %xmm4,%xmm0
+ pxor %xmm3,%xmm1
+ movdqa %xmm0,%xmm4
+ psrlq $1,%xmm0
+ pxor %xmm4,%xmm1
+ pxor %xmm0,%xmm4
+ psrlq $5,%xmm0
+ pxor %xmm4,%xmm0
+ psrlq $1,%xmm0
+ pxor %xmm1,%xmm0
+.byte 102,15,56,0,197
+ movdqu %xmm0,(%eax)
+ ret
+.globl _gcm_ghash_clmul
+.private_extern _gcm_ghash_clmul
+.align 4
+_gcm_ghash_clmul:
+L_gcm_ghash_clmul_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ movl 20(%esp),%eax
+ movl 24(%esp),%edx
+ movl 28(%esp),%esi
+ movl 32(%esp),%ebx
+ call L012pic
+L012pic:
+ popl %ecx
+ leal Lbswap-L012pic(%ecx),%ecx
+ movdqu (%eax),%xmm0
+ movdqa (%ecx),%xmm5
+ movdqu (%edx),%xmm2
+.byte 102,15,56,0,197
+ subl $16,%ebx
+ jz L013odd_tail
+ movdqu (%esi),%xmm3
+ movdqu 16(%esi),%xmm6
+.byte 102,15,56,0,221
+.byte 102,15,56,0,245
+ movdqu 32(%edx),%xmm5
+ pxor %xmm3,%xmm0
+ pshufd $78,%xmm6,%xmm3
+ movdqa %xmm6,%xmm7
+ pxor %xmm6,%xmm3
+ leal 32(%esi),%esi
+.byte 102,15,58,68,242,0
+.byte 102,15,58,68,250,17
+.byte 102,15,58,68,221,0
+ movups 16(%edx),%xmm2
+ nop
+ subl $32,%ebx
+ jbe L014even_tail
+ jmp L015mod_loop
+.align 5,0x90
+L015mod_loop:
+ pshufd $78,%xmm0,%xmm4
+ movdqa %xmm0,%xmm1
+ pxor %xmm0,%xmm4
+ nop
+.byte 102,15,58,68,194,0
+.byte 102,15,58,68,202,17
+.byte 102,15,58,68,229,16
+ movups (%edx),%xmm2
+ xorps %xmm6,%xmm0
+ movdqa (%ecx),%xmm5
+ xorps %xmm7,%xmm1
+ movdqu (%esi),%xmm7
+ pxor %xmm0,%xmm3
+ movdqu 16(%esi),%xmm6
+ pxor %xmm1,%xmm3
+.byte 102,15,56,0,253
+ pxor %xmm3,%xmm4
+ movdqa %xmm4,%xmm3
+ psrldq $8,%xmm4
+ pslldq $8,%xmm3
+ pxor %xmm4,%xmm1
+ pxor %xmm3,%xmm0
+.byte 102,15,56,0,245
+ pxor %xmm7,%xmm1
+ movdqa %xmm6,%xmm7
+ movdqa %xmm0,%xmm4
+ movdqa %xmm0,%xmm3
+ psllq $5,%xmm0
+ pxor %xmm0,%xmm3
+ psllq $1,%xmm0
+ pxor %xmm3,%xmm0
+.byte 102,15,58,68,242,0
+ movups 32(%edx),%xmm5
+ psllq $57,%xmm0
+ movdqa %xmm0,%xmm3
+ pslldq $8,%xmm0
+ psrldq $8,%xmm3
+ pxor %xmm4,%xmm0
+ pxor %xmm3,%xmm1
+ pshufd $78,%xmm7,%xmm3
+ movdqa %xmm0,%xmm4
+ psrlq $1,%xmm0
+ pxor %xmm7,%xmm3
+ pxor %xmm4,%xmm1
+.byte 102,15,58,68,250,17
+ movups 16(%edx),%xmm2
+ pxor %xmm0,%xmm4
+ psrlq $5,%xmm0
+ pxor %xmm4,%xmm0
+ psrlq $1,%xmm0
+ pxor %xmm1,%xmm0
+.byte 102,15,58,68,221,0
+ leal 32(%esi),%esi
+ subl $32,%ebx
+ ja L015mod_loop
+L014even_tail:
+ pshufd $78,%xmm0,%xmm4
+ movdqa %xmm0,%xmm1
+ pxor %xmm0,%xmm4
+.byte 102,15,58,68,194,0
+.byte 102,15,58,68,202,17
+.byte 102,15,58,68,229,16
+ movdqa (%ecx),%xmm5
+ xorps %xmm6,%xmm0
+ xorps %xmm7,%xmm1
+ pxor %xmm0,%xmm3
+ pxor %xmm1,%xmm3
+ pxor %xmm3,%xmm4
+ movdqa %xmm4,%xmm3
+ psrldq $8,%xmm4
+ pslldq $8,%xmm3
+ pxor %xmm4,%xmm1
+ pxor %xmm3,%xmm0
+ movdqa %xmm0,%xmm4
+ movdqa %xmm0,%xmm3
+ psllq $5,%xmm0
+ pxor %xmm0,%xmm3
+ psllq $1,%xmm0
+ pxor %xmm3,%xmm0
+ psllq $57,%xmm0
+ movdqa %xmm0,%xmm3
+ pslldq $8,%xmm0
+ psrldq $8,%xmm3
+ pxor %xmm4,%xmm0
+ pxor %xmm3,%xmm1
+ movdqa %xmm0,%xmm4
+ psrlq $1,%xmm0
+ pxor %xmm4,%xmm1
+ pxor %xmm0,%xmm4
+ psrlq $5,%xmm0
+ pxor %xmm4,%xmm0
+ psrlq $1,%xmm0
+ pxor %xmm1,%xmm0
+ testl %ebx,%ebx
+ jnz L016done
+ movups (%edx),%xmm2
+L013odd_tail:
+ movdqu (%esi),%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
+ xorps %xmm0,%xmm3
+ xorps %xmm1,%xmm3
+ movdqa %xmm3,%xmm4
+ psrldq $8,%xmm3
+ pslldq $8,%xmm4
+ pxor %xmm3,%xmm1
+ pxor %xmm4,%xmm0
+ movdqa %xmm0,%xmm4
+ movdqa %xmm0,%xmm3
+ psllq $5,%xmm0
+ pxor %xmm0,%xmm3
+ psllq $1,%xmm0
+ pxor %xmm3,%xmm0
+ psllq $57,%xmm0
+ movdqa %xmm0,%xmm3
+ pslldq $8,%xmm0
+ psrldq $8,%xmm3
+ pxor %xmm4,%xmm0
+ pxor %xmm3,%xmm1
+ movdqa %xmm0,%xmm4
+ psrlq $1,%xmm0
+ pxor %xmm4,%xmm1
+ pxor %xmm0,%xmm4
+ psrlq $5,%xmm0
+ pxor %xmm4,%xmm0
+ psrlq $1,%xmm0
+ pxor %xmm1,%xmm0
+L016done:
+.byte 102,15,56,0,197
+ movdqu %xmm0,(%eax)
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.align 6,0x90
+Lbswap:
+.byte 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0
+.byte 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,194
+.align 6,0x90
+Lrem_8bit:
+.value 0,450,900,582,1800,1738,1164,1358
+.value 3600,4050,3476,3158,2328,2266,2716,2910
+.value 7200,7650,8100,7782,6952,6890,6316,6510
+.value 4656,5106,4532,4214,5432,5370,5820,6014
+.value 14400,14722,15300,14854,16200,16010,15564,15630
+.value 13904,14226,13780,13334,12632,12442,13020,13086
+.value 9312,9634,10212,9766,9064,8874,8428,8494
+.value 10864,11186,10740,10294,11640,11450,12028,12094
+.value 28800,28994,29444,29382,30600,30282,29708,30158
+.value 32400,32594,32020,31958,31128,30810,31260,31710
+.value 27808,28002,28452,28390,27560,27242,26668,27118
+.value 25264,25458,24884,24822,26040,25722,26172,26622
+.value 18624,18690,19268,19078,20424,19978,19532,19854
+.value 18128,18194,17748,17558,16856,16410,16988,17310
+.value 21728,21794,22372,22182,21480,21034,20588,20910
+.value 23280,23346,22900,22710,24056,23610,24188,24510
+.value 57600,57538,57988,58182,58888,59338,58764,58446
+.value 61200,61138,60564,60758,59416,59866,60316,59998
+.value 64800,64738,65188,65382,64040,64490,63916,63598
+.value 62256,62194,61620,61814,62520,62970,63420,63102
+.value 55616,55426,56004,56070,56904,57226,56780,56334
+.value 55120,54930,54484,54550,53336,53658,54236,53790
+.value 50528,50338,50916,50982,49768,50090,49644,49198
+.value 52080,51890,51444,51510,52344,52666,53244,52798
+.value 37248,36930,37380,37830,38536,38730,38156,38094
+.value 40848,40530,39956,40406,39064,39258,39708,39646
+.value 36256,35938,36388,36838,35496,35690,35116,35054
+.value 33712,33394,32820,33270,33976,34170,34620,34558
+.value 43456,43010,43588,43910,44744,44810,44364,44174
+.value 42960,42514,42068,42390,41176,41242,41820,41630
+.value 46560,46114,46692,47014,45800,45866,45420,45230
+.value 48112,47666,47220,47542,48376,48442,49020,48830
+.align 6,0x90
+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
+.byte 71,72,65,83,72,32,102,111,114,32,120,56,54,44,32,67
+.byte 82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112
+.byte 112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62
+.byte 0
+#endif
diff --git a/mac-x86/crypto/rc4/rc4-586.S b/mac-x86/crypto/rc4/rc4-586.S
new file mode 100644
index 0000000..faecdfa
--- /dev/null
+++ b/mac-x86/crypto/rc4/rc4-586.S
@@ -0,0 +1,383 @@
+#if defined(__i386__)
+.file "rc4-586.S"
+.text
+.globl _asm_RC4
+.private_extern _asm_RC4
+.align 4
+_asm_RC4:
+L_asm_RC4_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ movl 20(%esp),%edi
+ movl 24(%esp),%edx
+ movl 28(%esp),%esi
+ movl 32(%esp),%ebp
+ xorl %eax,%eax
+ xorl %ebx,%ebx
+ cmpl $0,%edx
+ je L000abort
+ movb (%edi),%al
+ movb 4(%edi),%bl
+ addl $8,%edi
+ leal (%esi,%edx,1),%ecx
+ subl %esi,%ebp
+ movl %ecx,24(%esp)
+ incb %al
+ cmpl $-1,256(%edi)
+ je L001RC4_CHAR
+ movl (%edi,%eax,4),%ecx
+ andl $-4,%edx
+ jz L002loop1
+ movl %ebp,32(%esp)
+ testl $-8,%edx
+ jz L003go4loop4
+ call L004PIC_me_up
+L004PIC_me_up:
+ popl %ebp
+ movl L_OPENSSL_ia32cap_P$non_lazy_ptr-L004PIC_me_up(%ebp),%ebp
+ btl $26,(%ebp)
+ jnc L003go4loop4
+ movl 32(%esp),%ebp
+ andl $-8,%edx
+ leal -8(%esi,%edx,1),%edx
+ movl %edx,-4(%edi)
+ addb %cl,%bl
+ movl (%edi,%ebx,4),%edx
+ movl %ecx,(%edi,%ebx,4)
+ movl %edx,(%edi,%eax,4)
+ incl %eax
+ addl %ecx,%edx
+ movzbl %al,%eax
+ movzbl %dl,%edx
+ movq (%esi),%mm0
+ movl (%edi,%eax,4),%ecx
+ movd (%edi,%edx,4),%mm2
+ jmp L005loop_mmx_enter
+.align 4,0x90
+L006loop_mmx:
+ addb %cl,%bl
+ psllq $56,%mm1
+ movl (%edi,%ebx,4),%edx
+ movl %ecx,(%edi,%ebx,4)
+ movl %edx,(%edi,%eax,4)
+ incl %eax
+ addl %ecx,%edx
+ movzbl %al,%eax
+ movzbl %dl,%edx
+ pxor %mm1,%mm2
+ movq (%esi),%mm0
+ movq %mm2,-8(%ebp,%esi,1)
+ movl (%edi,%eax,4),%ecx
+ movd (%edi,%edx,4),%mm2
+L005loop_mmx_enter:
+ addb %cl,%bl
+ movl (%edi,%ebx,4),%edx
+ movl %ecx,(%edi,%ebx,4)
+ movl %edx,(%edi,%eax,4)
+ incl %eax
+ addl %ecx,%edx
+ movzbl %al,%eax
+ movzbl %dl,%edx
+ pxor %mm0,%mm2
+ movl (%edi,%eax,4),%ecx
+ movd (%edi,%edx,4),%mm1
+ addb %cl,%bl
+ psllq $8,%mm1
+ movl (%edi,%ebx,4),%edx
+ movl %ecx,(%edi,%ebx,4)
+ movl %edx,(%edi,%eax,4)
+ incl %eax
+ addl %ecx,%edx
+ movzbl %al,%eax
+ movzbl %dl,%edx
+ pxor %mm1,%mm2
+ movl (%edi,%eax,4),%ecx
+ movd (%edi,%edx,4),%mm1
+ addb %cl,%bl
+ psllq $16,%mm1
+ movl (%edi,%ebx,4),%edx
+ movl %ecx,(%edi,%ebx,4)
+ movl %edx,(%edi,%eax,4)
+ incl %eax
+ addl %ecx,%edx
+ movzbl %al,%eax
+ movzbl %dl,%edx
+ pxor %mm1,%mm2
+ movl (%edi,%eax,4),%ecx
+ movd (%edi,%edx,4),%mm1
+ addb %cl,%bl
+ psllq $24,%mm1
+ movl (%edi,%ebx,4),%edx
+ movl %ecx,(%edi,%ebx,4)
+ movl %edx,(%edi,%eax,4)
+ incl %eax
+ addl %ecx,%edx
+ movzbl %al,%eax
+ movzbl %dl,%edx
+ pxor %mm1,%mm2
+ movl (%edi,%eax,4),%ecx
+ movd (%edi,%edx,4),%mm1
+ addb %cl,%bl
+ psllq $32,%mm1
+ movl (%edi,%ebx,4),%edx
+ movl %ecx,(%edi,%ebx,4)
+ movl %edx,(%edi,%eax,4)
+ incl %eax
+ addl %ecx,%edx
+ movzbl %al,%eax
+ movzbl %dl,%edx
+ pxor %mm1,%mm2
+ movl (%edi,%eax,4),%ecx
+ movd (%edi,%edx,4),%mm1
+ addb %cl,%bl
+ psllq $40,%mm1
+ movl (%edi,%ebx,4),%edx
+ movl %ecx,(%edi,%ebx,4)
+ movl %edx,(%edi,%eax,4)
+ incl %eax
+ addl %ecx,%edx
+ movzbl %al,%eax
+ movzbl %dl,%edx
+ pxor %mm1,%mm2
+ movl (%edi,%eax,4),%ecx
+ movd (%edi,%edx,4),%mm1
+ addb %cl,%bl
+ psllq $48,%mm1
+ movl (%edi,%ebx,4),%edx
+ movl %ecx,(%edi,%ebx,4)
+ movl %edx,(%edi,%eax,4)
+ incl %eax
+ addl %ecx,%edx
+ movzbl %al,%eax
+ movzbl %dl,%edx
+ pxor %mm1,%mm2
+ movl (%edi,%eax,4),%ecx
+ movd (%edi,%edx,4),%mm1
+ movl %ebx,%edx
+ xorl %ebx,%ebx
+ movb %dl,%bl
+ cmpl -4(%edi),%esi
+ leal 8(%esi),%esi
+ jb L006loop_mmx
+ psllq $56,%mm1
+ pxor %mm1,%mm2
+ movq %mm2,-8(%ebp,%esi,1)
+ emms
+ cmpl 24(%esp),%esi
+ je L007done
+ jmp L002loop1
+.align 4,0x90
+L003go4loop4:
+ leal -4(%esi,%edx,1),%edx
+ movl %edx,28(%esp)
+L008loop4:
+ addb %cl,%bl
+ movl (%edi,%ebx,4),%edx
+ movl %ecx,(%edi,%ebx,4)
+ movl %edx,(%edi,%eax,4)
+ addl %ecx,%edx
+ incb %al
+ andl $255,%edx
+ movl (%edi,%eax,4),%ecx
+ movl (%edi,%edx,4),%ebp
+ addb %cl,%bl
+ movl (%edi,%ebx,4),%edx
+ movl %ecx,(%edi,%ebx,4)
+ movl %edx,(%edi,%eax,4)
+ addl %ecx,%edx
+ incb %al
+ andl $255,%edx
+ rorl $8,%ebp
+ movl (%edi,%eax,4),%ecx
+ orl (%edi,%edx,4),%ebp
+ addb %cl,%bl
+ movl (%edi,%ebx,4),%edx
+ movl %ecx,(%edi,%ebx,4)
+ movl %edx,(%edi,%eax,4)
+ addl %ecx,%edx
+ incb %al
+ andl $255,%edx
+ rorl $8,%ebp
+ movl (%edi,%eax,4),%ecx
+ orl (%edi,%edx,4),%ebp
+ addb %cl,%bl
+ movl (%edi,%ebx,4),%edx
+ movl %ecx,(%edi,%ebx,4)
+ movl %edx,(%edi,%eax,4)
+ addl %ecx,%edx
+ incb %al
+ andl $255,%edx
+ rorl $8,%ebp
+ movl 32(%esp),%ecx
+ orl (%edi,%edx,4),%ebp
+ rorl $8,%ebp
+ xorl (%esi),%ebp
+ cmpl 28(%esp),%esi
+ movl %ebp,(%ecx,%esi,1)
+ leal 4(%esi),%esi
+ movl (%edi,%eax,4),%ecx
+ jb L008loop4
+ cmpl 24(%esp),%esi
+ je L007done
+ movl 32(%esp),%ebp
+.align 4,0x90
+L002loop1:
+ addb %cl,%bl
+ movl (%edi,%ebx,4),%edx
+ movl %ecx,(%edi,%ebx,4)
+ movl %edx,(%edi,%eax,4)
+ addl %ecx,%edx
+ incb %al
+ andl $255,%edx
+ movl (%edi,%edx,4),%edx
+ xorb (%esi),%dl
+ leal 1(%esi),%esi
+ movl (%edi,%eax,4),%ecx
+ cmpl 24(%esp),%esi
+ movb %dl,-1(%ebp,%esi,1)
+ jb L002loop1
+ jmp L007done
+.align 4,0x90
+L001RC4_CHAR:
+ movzbl (%edi,%eax,1),%ecx
+L009cloop1:
+ addb %cl,%bl
+ movzbl (%edi,%ebx,1),%edx
+ movb %cl,(%edi,%ebx,1)
+ movb %dl,(%edi,%eax,1)
+ addb %cl,%dl
+ movzbl (%edi,%edx,1),%edx
+ addb $1,%al
+ xorb (%esi),%dl
+ leal 1(%esi),%esi
+ movzbl (%edi,%eax,1),%ecx
+ cmpl 24(%esp),%esi
+ movb %dl,-1(%ebp,%esi,1)
+ jb L009cloop1
+L007done:
+ decb %al
+ movl %ebx,-4(%edi)
+ movb %al,-8(%edi)
+L000abort:
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.globl _asm_RC4_set_key
+.private_extern _asm_RC4_set_key
+.align 4
+_asm_RC4_set_key:
+L_asm_RC4_set_key_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ movl 20(%esp),%edi
+ movl 24(%esp),%ebp
+ movl 28(%esp),%esi
+ call L010PIC_me_up
+L010PIC_me_up:
+ popl %edx
+ movl L_OPENSSL_ia32cap_P$non_lazy_ptr-L010PIC_me_up(%edx),%edx
+ leal 8(%edi),%edi
+ leal (%esi,%ebp,1),%esi
+ negl %ebp
+ xorl %eax,%eax
+ movl %ebp,-4(%edi)
+ btl $20,(%edx)
+ jc L011c1stloop
+.align 4,0x90
+L012w1stloop:
+ movl %eax,(%edi,%eax,4)
+ addb $1,%al
+ jnc L012w1stloop
+ xorl %ecx,%ecx
+ xorl %edx,%edx
+.align 4,0x90
+L013w2ndloop:
+ movl (%edi,%ecx,4),%eax
+ addb (%esi,%ebp,1),%dl
+ addb %al,%dl
+ addl $1,%ebp
+ movl (%edi,%edx,4),%ebx
+ jnz L014wnowrap
+ movl -4(%edi),%ebp
+L014wnowrap:
+ movl %eax,(%edi,%edx,4)
+ movl %ebx,(%edi,%ecx,4)
+ addb $1,%cl
+ jnc L013w2ndloop
+ jmp L015exit
+.align 4,0x90
+L011c1stloop:
+ movb %al,(%edi,%eax,1)
+ addb $1,%al
+ jnc L011c1stloop
+ xorl %ecx,%ecx
+ xorl %edx,%edx
+ xorl %ebx,%ebx
+.align 4,0x90
+L016c2ndloop:
+ movb (%edi,%ecx,1),%al
+ addb (%esi,%ebp,1),%dl
+ addb %al,%dl
+ addl $1,%ebp
+ movb (%edi,%edx,1),%bl
+ jnz L017cnowrap
+ movl -4(%edi),%ebp
+L017cnowrap:
+ movb %al,(%edi,%edx,1)
+ movb %bl,(%edi,%ecx,1)
+ addb $1,%cl
+ jnc L016c2ndloop
+ movl $-1,256(%edi)
+L015exit:
+ xorl %eax,%eax
+ movl %eax,-8(%edi)
+ movl %eax,-4(%edi)
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.globl _RC4_options
+.private_extern _RC4_options
+.align 4
+_RC4_options:
+L_RC4_options_begin:
+ call L018pic_point
+L018pic_point:
+ popl %eax
+ leal L019opts-L018pic_point(%eax),%eax
+ call L020PIC_me_up
+L020PIC_me_up:
+ popl %edx
+ movl L_OPENSSL_ia32cap_P$non_lazy_ptr-L020PIC_me_up(%edx),%edx
+ movl (%edx),%edx
+ btl $20,%edx
+ jc L0211xchar
+ btl $26,%edx
+ jnc L022ret
+ addl $25,%eax
+ ret
+L0211xchar:
+ addl $12,%eax
+L022ret:
+ ret
+.align 6,0x90
+L019opts:
+.byte 114,99,52,40,52,120,44,105,110,116,41,0
+.byte 114,99,52,40,49,120,44,99,104,97,114,41,0
+.byte 114,99,52,40,56,120,44,109,109,120,41,0
+.byte 82,67,52,32,102,111,114,32,120,56,54,44,32,67,82,89
+.byte 80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114
+.byte 111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
+.align 6,0x90
+.section __IMPORT,__pointers,non_lazy_symbol_pointers
+L_OPENSSL_ia32cap_P$non_lazy_ptr:
+.indirect_symbol _OPENSSL_ia32cap_P
+.long 0
+#endif
diff --git a/mac-x86/crypto/sha/sha1-586.S b/mac-x86/crypto/sha/sha1-586.S
new file mode 100644
index 0000000..4dd3fee
--- /dev/null
+++ b/mac-x86/crypto/sha/sha1-586.S
@@ -0,0 +1,1381 @@
+#if defined(__i386__)
+.file "sha1-586.S"
+.text
+.globl _sha1_block_data_order
+.private_extern _sha1_block_data_order
+.align 4
+_sha1_block_data_order:
+L_sha1_block_data_order_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ movl 20(%esp),%ebp
+ movl 24(%esp),%esi
+ movl 28(%esp),%eax
+ subl $76,%esp
+ shll $6,%eax
+ addl %esi,%eax
+ movl %eax,104(%esp)
+ movl 16(%ebp),%edi
+ jmp L000loop
+.align 4,0x90
+L000loop:
+ movl (%esi),%eax
+ movl 4(%esi),%ebx
+ movl 8(%esi),%ecx
+ movl 12(%esi),%edx
+ bswap %eax
+ bswap %ebx
+ bswap %ecx
+ bswap %edx
+ movl %eax,(%esp)
+ movl %ebx,4(%esp)
+ movl %ecx,8(%esp)
+ movl %edx,12(%esp)
+ movl 16(%esi),%eax
+ movl 20(%esi),%ebx
+ movl 24(%esi),%ecx
+ movl 28(%esi),%edx
+ bswap %eax
+ bswap %ebx
+ bswap %ecx
+ bswap %edx
+ movl %eax,16(%esp)
+ movl %ebx,20(%esp)
+ movl %ecx,24(%esp)
+ movl %edx,28(%esp)
+ movl 32(%esi),%eax
+ movl 36(%esi),%ebx
+ movl 40(%esi),%ecx
+ movl 44(%esi),%edx
+ bswap %eax
+ bswap %ebx
+ bswap %ecx
+ bswap %edx
+ movl %eax,32(%esp)
+ movl %ebx,36(%esp)
+ movl %ecx,40(%esp)
+ movl %edx,44(%esp)
+ movl 48(%esi),%eax
+ movl 52(%esi),%ebx
+ movl 56(%esi),%ecx
+ movl 60(%esi),%edx
+ bswap %eax
+ bswap %ebx
+ bswap %ecx
+ bswap %edx
+ movl %eax,48(%esp)
+ movl %ebx,52(%esp)
+ movl %ecx,56(%esp)
+ movl %edx,60(%esp)
+ movl %esi,100(%esp)
+ movl (%ebp),%eax
+ movl 4(%ebp),%ebx
+ movl 8(%ebp),%ecx
+ movl 12(%ebp),%edx
+ # 00_15 0
+ movl %ecx,%esi
+ movl %eax,%ebp
+ roll $5,%ebp
+ xorl %edx,%esi
+ addl %edi,%ebp
+ movl (%esp),%edi
+ andl %ebx,%esi
+ rorl $2,%ebx
+ xorl %edx,%esi
+ leal 1518500249(%ebp,%edi,1),%ebp
+ addl %esi,%ebp
+ # 00_15 1
+ movl %ebx,%edi
+ movl %ebp,%esi
+ roll $5,%ebp
+ xorl %ecx,%edi
+ addl %edx,%ebp
+ movl 4(%esp),%edx
+ andl %eax,%edi
+ rorl $2,%eax
+ xorl %ecx,%edi
+ leal 1518500249(%ebp,%edx,1),%ebp
+ addl %edi,%ebp
+ # 00_15 2
+ movl %eax,%edx
+ movl %ebp,%edi
+ roll $5,%ebp
+ xorl %ebx,%edx
+ addl %ecx,%ebp
+ movl 8(%esp),%ecx
+ andl %esi,%edx
+ rorl $2,%esi
+ xorl %ebx,%edx
+ leal 1518500249(%ebp,%ecx,1),%ebp
+ addl %edx,%ebp
+ # 00_15 3
+ movl %esi,%ecx
+ movl %ebp,%edx
+ roll $5,%ebp
+ xorl %eax,%ecx
+ addl %ebx,%ebp
+ movl 12(%esp),%ebx
+ andl %edi,%ecx
+ rorl $2,%edi
+ xorl %eax,%ecx
+ leal 1518500249(%ebp,%ebx,1),%ebp
+ addl %ecx,%ebp
+ # 00_15 4
+ movl %edi,%ebx
+ movl %ebp,%ecx
+ roll $5,%ebp
+ xorl %esi,%ebx
+ addl %eax,%ebp
+ movl 16(%esp),%eax
+ andl %edx,%ebx
+ rorl $2,%edx
+ xorl %esi,%ebx
+ leal 1518500249(%ebp,%eax,1),%ebp
+ addl %ebx,%ebp
+ # 00_15 5
+ movl %edx,%eax
+ movl %ebp,%ebx
+ roll $5,%ebp
+ xorl %edi,%eax
+ addl %esi,%ebp
+ movl 20(%esp),%esi
+ andl %ecx,%eax
+ rorl $2,%ecx
+ xorl %edi,%eax
+ leal 1518500249(%ebp,%esi,1),%ebp
+ addl %eax,%ebp
+ # 00_15 6
+ movl %ecx,%esi
+ movl %ebp,%eax
+ roll $5,%ebp
+ xorl %edx,%esi
+ addl %edi,%ebp
+ movl 24(%esp),%edi
+ andl %ebx,%esi
+ rorl $2,%ebx
+ xorl %edx,%esi
+ leal 1518500249(%ebp,%edi,1),%ebp
+ addl %esi,%ebp
+ # 00_15 7
+ movl %ebx,%edi
+ movl %ebp,%esi
+ roll $5,%ebp
+ xorl %ecx,%edi
+ addl %edx,%ebp
+ movl 28(%esp),%edx
+ andl %eax,%edi
+ rorl $2,%eax
+ xorl %ecx,%edi
+ leal 1518500249(%ebp,%edx,1),%ebp
+ addl %edi,%ebp
+ # 00_15 8
+ movl %eax,%edx
+ movl %ebp,%edi
+ roll $5,%ebp
+ xorl %ebx,%edx
+ addl %ecx,%ebp
+ movl 32(%esp),%ecx
+ andl %esi,%edx
+ rorl $2,%esi
+ xorl %ebx,%edx
+ leal 1518500249(%ebp,%ecx,1),%ebp
+ addl %edx,%ebp
+ # 00_15 9
+ movl %esi,%ecx
+ movl %ebp,%edx
+ roll $5,%ebp
+ xorl %eax,%ecx
+ addl %ebx,%ebp
+ movl 36(%esp),%ebx
+ andl %edi,%ecx
+ rorl $2,%edi
+ xorl %eax,%ecx
+ leal 1518500249(%ebp,%ebx,1),%ebp
+ addl %ecx,%ebp
+ # 00_15 10
+ movl %edi,%ebx
+ movl %ebp,%ecx
+ roll $5,%ebp
+ xorl %esi,%ebx
+ addl %eax,%ebp
+ movl 40(%esp),%eax
+ andl %edx,%ebx
+ rorl $2,%edx
+ xorl %esi,%ebx
+ leal 1518500249(%ebp,%eax,1),%ebp
+ addl %ebx,%ebp
+ # 00_15 11
+ movl %edx,%eax
+ movl %ebp,%ebx
+ roll $5,%ebp
+ xorl %edi,%eax
+ addl %esi,%ebp
+ movl 44(%esp),%esi
+ andl %ecx,%eax
+ rorl $2,%ecx
+ xorl %edi,%eax
+ leal 1518500249(%ebp,%esi,1),%ebp
+ addl %eax,%ebp
+ # 00_15 12
+ movl %ecx,%esi
+ movl %ebp,%eax
+ roll $5,%ebp
+ xorl %edx,%esi
+ addl %edi,%ebp
+ movl 48(%esp),%edi
+ andl %ebx,%esi
+ rorl $2,%ebx
+ xorl %edx,%esi
+ leal 1518500249(%ebp,%edi,1),%ebp
+ addl %esi,%ebp
+ # 00_15 13
+ movl %ebx,%edi
+ movl %ebp,%esi
+ roll $5,%ebp
+ xorl %ecx,%edi
+ addl %edx,%ebp
+ movl 52(%esp),%edx
+ andl %eax,%edi
+ rorl $2,%eax
+ xorl %ecx,%edi
+ leal 1518500249(%ebp,%edx,1),%ebp
+ addl %edi,%ebp
+ # 00_15 14
+ movl %eax,%edx
+ movl %ebp,%edi
+ roll $5,%ebp
+ xorl %ebx,%edx
+ addl %ecx,%ebp
+ movl 56(%esp),%ecx
+ andl %esi,%edx
+ rorl $2,%esi
+ xorl %ebx,%edx
+ leal 1518500249(%ebp,%ecx,1),%ebp
+ addl %edx,%ebp
+ # 00_15 15
+ movl %esi,%ecx
+ movl %ebp,%edx
+ roll $5,%ebp
+ xorl %eax,%ecx
+ addl %ebx,%ebp
+ movl 60(%esp),%ebx
+ andl %edi,%ecx
+ rorl $2,%edi
+ xorl %eax,%ecx
+ leal 1518500249(%ebp,%ebx,1),%ebp
+ movl (%esp),%ebx
+ addl %ebp,%ecx
+ # 16_19 16
+ movl %edi,%ebp
+ xorl 8(%esp),%ebx
+ xorl %esi,%ebp
+ xorl 32(%esp),%ebx
+ andl %edx,%ebp
+ xorl 52(%esp),%ebx
+ roll $1,%ebx
+ xorl %esi,%ebp
+ addl %ebp,%eax
+ movl %ecx,%ebp
+ rorl $2,%edx
+ movl %ebx,(%esp)
+ roll $5,%ebp
+ leal 1518500249(%ebx,%eax,1),%ebx
+ movl 4(%esp),%eax
+ addl %ebp,%ebx
+ # 16_19 17
+ movl %edx,%ebp
+ xorl 12(%esp),%eax
+ xorl %edi,%ebp
+ xorl 36(%esp),%eax
+ andl %ecx,%ebp
+ xorl 56(%esp),%eax
+ roll $1,%eax
+ xorl %edi,%ebp
+ addl %ebp,%esi
+ movl %ebx,%ebp
+ rorl $2,%ecx
+ movl %eax,4(%esp)
+ roll $5,%ebp
+ leal 1518500249(%eax,%esi,1),%eax
+ movl 8(%esp),%esi
+ addl %ebp,%eax
+ # 16_19 18
+ movl %ecx,%ebp
+ xorl 16(%esp),%esi
+ xorl %edx,%ebp
+ xorl 40(%esp),%esi
+ andl %ebx,%ebp
+ xorl 60(%esp),%esi
+ roll $1,%esi
+ xorl %edx,%ebp
+ addl %ebp,%edi
+ movl %eax,%ebp
+ rorl $2,%ebx
+ movl %esi,8(%esp)
+ roll $5,%ebp
+ leal 1518500249(%esi,%edi,1),%esi
+ movl 12(%esp),%edi
+ addl %ebp,%esi
+ # 16_19 19
+ movl %ebx,%ebp
+ xorl 20(%esp),%edi
+ xorl %ecx,%ebp
+ xorl 44(%esp),%edi
+ andl %eax,%ebp
+ xorl (%esp),%edi
+ roll $1,%edi
+ xorl %ecx,%ebp
+ addl %ebp,%edx
+ movl %esi,%ebp
+ rorl $2,%eax
+ movl %edi,12(%esp)
+ roll $5,%ebp
+ leal 1518500249(%edi,%edx,1),%edi
+ movl 16(%esp),%edx
+ addl %ebp,%edi
+ # 20_39 20
+ movl %esi,%ebp
+ xorl 24(%esp),%edx
+ xorl %eax,%ebp
+ xorl 48(%esp),%edx
+ xorl %ebx,%ebp
+ xorl 4(%esp),%edx
+ roll $1,%edx
+ addl %ebp,%ecx
+ rorl $2,%esi
+ movl %edi,%ebp
+ roll $5,%ebp
+ movl %edx,16(%esp)
+ leal 1859775393(%edx,%ecx,1),%edx
+ movl 20(%esp),%ecx
+ addl %ebp,%edx
+ # 20_39 21
+ movl %edi,%ebp
+ xorl 28(%esp),%ecx
+ xorl %esi,%ebp
+ xorl 52(%esp),%ecx
+ xorl %eax,%ebp
+ xorl 8(%esp),%ecx
+ roll $1,%ecx
+ addl %ebp,%ebx
+ rorl $2,%edi
+ movl %edx,%ebp
+ roll $5,%ebp
+ movl %ecx,20(%esp)
+ leal 1859775393(%ecx,%ebx,1),%ecx
+ movl 24(%esp),%ebx
+ addl %ebp,%ecx
+ # 20_39 22
+ movl %edx,%ebp
+ xorl 32(%esp),%ebx
+ xorl %edi,%ebp
+ xorl 56(%esp),%ebx
+ xorl %esi,%ebp
+ xorl 12(%esp),%ebx
+ roll $1,%ebx
+ addl %ebp,%eax
+ rorl $2,%edx
+ movl %ecx,%ebp
+ roll $5,%ebp
+ movl %ebx,24(%esp)
+ leal 1859775393(%ebx,%eax,1),%ebx
+ movl 28(%esp),%eax
+ addl %ebp,%ebx
+ # 20_39 23
+ movl %ecx,%ebp
+ xorl 36(%esp),%eax
+ xorl %edx,%ebp
+ xorl 60(%esp),%eax
+ xorl %edi,%ebp
+ xorl 16(%esp),%eax
+ roll $1,%eax
+ addl %ebp,%esi
+ rorl $2,%ecx
+ movl %ebx,%ebp
+ roll $5,%ebp
+ movl %eax,28(%esp)
+ leal 1859775393(%eax,%esi,1),%eax
+ movl 32(%esp),%esi
+ addl %ebp,%eax
+ # 20_39 24
+ movl %ebx,%ebp
+ xorl 40(%esp),%esi
+ xorl %ecx,%ebp
+ xorl (%esp),%esi
+ xorl %edx,%ebp
+ xorl 20(%esp),%esi
+ roll $1,%esi
+ addl %ebp,%edi
+ rorl $2,%ebx
+ movl %eax,%ebp
+ roll $5,%ebp
+ movl %esi,32(%esp)
+ leal 1859775393(%esi,%edi,1),%esi
+ movl 36(%esp),%edi
+ addl %ebp,%esi
+ # 20_39 25
+ movl %eax,%ebp
+ xorl 44(%esp),%edi
+ xorl %ebx,%ebp
+ xorl 4(%esp),%edi
+ xorl %ecx,%ebp
+ xorl 24(%esp),%edi
+ roll $1,%edi
+ addl %ebp,%edx
+ rorl $2,%eax
+ movl %esi,%ebp
+ roll $5,%ebp
+ movl %edi,36(%esp)
+ leal 1859775393(%edi,%edx,1),%edi
+ movl 40(%esp),%edx
+ addl %ebp,%edi
+ # 20_39 26
+ movl %esi,%ebp
+ xorl 48(%esp),%edx
+ xorl %eax,%ebp
+ xorl 8(%esp),%edx
+ xorl %ebx,%ebp
+ xorl 28(%esp),%edx
+ roll $1,%edx
+ addl %ebp,%ecx
+ rorl $2,%esi
+ movl %edi,%ebp
+ roll $5,%ebp
+ movl %edx,40(%esp)
+ leal 1859775393(%edx,%ecx,1),%edx
+ movl 44(%esp),%ecx
+ addl %ebp,%edx
+ # 20_39 27
+ movl %edi,%ebp
+ xorl 52(%esp),%ecx
+ xorl %esi,%ebp
+ xorl 12(%esp),%ecx
+ xorl %eax,%ebp
+ xorl 32(%esp),%ecx
+ roll $1,%ecx
+ addl %ebp,%ebx
+ rorl $2,%edi
+ movl %edx,%ebp
+ roll $5,%ebp
+ movl %ecx,44(%esp)
+ leal 1859775393(%ecx,%ebx,1),%ecx
+ movl 48(%esp),%ebx
+ addl %ebp,%ecx
+ # 20_39 28
+ movl %edx,%ebp
+ xorl 56(%esp),%ebx
+ xorl %edi,%ebp
+ xorl 16(%esp),%ebx
+ xorl %esi,%ebp
+ xorl 36(%esp),%ebx
+ roll $1,%ebx
+ addl %ebp,%eax
+ rorl $2,%edx
+ movl %ecx,%ebp
+ roll $5,%ebp
+ movl %ebx,48(%esp)
+ leal 1859775393(%ebx,%eax,1),%ebx
+ movl 52(%esp),%eax
+ addl %ebp,%ebx
+ # 20_39 29
+ movl %ecx,%ebp
+ xorl 60(%esp),%eax
+ xorl %edx,%ebp
+ xorl 20(%esp),%eax
+ xorl %edi,%ebp
+ xorl 40(%esp),%eax
+ roll $1,%eax
+ addl %ebp,%esi
+ rorl $2,%ecx
+ movl %ebx,%ebp
+ roll $5,%ebp
+ movl %eax,52(%esp)
+ leal 1859775393(%eax,%esi,1),%eax
+ movl 56(%esp),%esi
+ addl %ebp,%eax
+ # 20_39 30
+ movl %ebx,%ebp
+ xorl (%esp),%esi
+ xorl %ecx,%ebp
+ xorl 24(%esp),%esi
+ xorl %edx,%ebp
+ xorl 44(%esp),%esi
+ roll $1,%esi
+ addl %ebp,%edi
+ rorl $2,%ebx
+ movl %eax,%ebp
+ roll $5,%ebp
+ movl %esi,56(%esp)
+ leal 1859775393(%esi,%edi,1),%esi
+ movl 60(%esp),%edi
+ addl %ebp,%esi
+ # 20_39 31
+ movl %eax,%ebp
+ xorl 4(%esp),%edi
+ xorl %ebx,%ebp
+ xorl 28(%esp),%edi
+ xorl %ecx,%ebp
+ xorl 48(%esp),%edi
+ roll $1,%edi
+ addl %ebp,%edx
+ rorl $2,%eax
+ movl %esi,%ebp
+ roll $5,%ebp
+ movl %edi,60(%esp)
+ leal 1859775393(%edi,%edx,1),%edi
+ movl (%esp),%edx
+ addl %ebp,%edi
+ # 20_39 32
+ movl %esi,%ebp
+ xorl 8(%esp),%edx
+ xorl %eax,%ebp
+ xorl 32(%esp),%edx
+ xorl %ebx,%ebp
+ xorl 52(%esp),%edx
+ roll $1,%edx
+ addl %ebp,%ecx
+ rorl $2,%esi
+ movl %edi,%ebp
+ roll $5,%ebp
+ movl %edx,(%esp)
+ leal 1859775393(%edx,%ecx,1),%edx
+ movl 4(%esp),%ecx
+ addl %ebp,%edx
+ # 20_39 33
+ movl %edi,%ebp
+ xorl 12(%esp),%ecx
+ xorl %esi,%ebp
+ xorl 36(%esp),%ecx
+ xorl %eax,%ebp
+ xorl 56(%esp),%ecx
+ roll $1,%ecx
+ addl %ebp,%ebx
+ rorl $2,%edi
+ movl %edx,%ebp
+ roll $5,%ebp
+ movl %ecx,4(%esp)
+ leal 1859775393(%ecx,%ebx,1),%ecx
+ movl 8(%esp),%ebx
+ addl %ebp,%ecx
+ # 20_39 34
+ movl %edx,%ebp
+ xorl 16(%esp),%ebx
+ xorl %edi,%ebp
+ xorl 40(%esp),%ebx
+ xorl %esi,%ebp
+ xorl 60(%esp),%ebx
+ roll $1,%ebx
+ addl %ebp,%eax
+ rorl $2,%edx
+ movl %ecx,%ebp
+ roll $5,%ebp
+ movl %ebx,8(%esp)
+ leal 1859775393(%ebx,%eax,1),%ebx
+ movl 12(%esp),%eax
+ addl %ebp,%ebx
+ # 20_39 35
+ movl %ecx,%ebp
+ xorl 20(%esp),%eax
+ xorl %edx,%ebp
+ xorl 44(%esp),%eax
+ xorl %edi,%ebp
+ xorl (%esp),%eax
+ roll $1,%eax
+ addl %ebp,%esi
+ rorl $2,%ecx
+ movl %ebx,%ebp
+ roll $5,%ebp
+ movl %eax,12(%esp)
+ leal 1859775393(%eax,%esi,1),%eax
+ movl 16(%esp),%esi
+ addl %ebp,%eax
+ # 20_39 36
+ movl %ebx,%ebp
+ xorl 24(%esp),%esi
+ xorl %ecx,%ebp
+ xorl 48(%esp),%esi
+ xorl %edx,%ebp
+ xorl 4(%esp),%esi
+ roll $1,%esi
+ addl %ebp,%edi
+ rorl $2,%ebx
+ movl %eax,%ebp
+ roll $5,%ebp
+ movl %esi,16(%esp)
+ leal 1859775393(%esi,%edi,1),%esi
+ movl 20(%esp),%edi
+ addl %ebp,%esi
+ # 20_39 37
+ movl %eax,%ebp
+ xorl 28(%esp),%edi
+ xorl %ebx,%ebp
+ xorl 52(%esp),%edi
+ xorl %ecx,%ebp
+ xorl 8(%esp),%edi
+ roll $1,%edi
+ addl %ebp,%edx
+ rorl $2,%eax
+ movl %esi,%ebp
+ roll $5,%ebp
+ movl %edi,20(%esp)
+ leal 1859775393(%edi,%edx,1),%edi
+ movl 24(%esp),%edx
+ addl %ebp,%edi
+ # 20_39 38
+ movl %esi,%ebp
+ xorl 32(%esp),%edx
+ xorl %eax,%ebp
+ xorl 56(%esp),%edx
+ xorl %ebx,%ebp
+ xorl 12(%esp),%edx
+ roll $1,%edx
+ addl %ebp,%ecx
+ rorl $2,%esi
+ movl %edi,%ebp
+ roll $5,%ebp
+ movl %edx,24(%esp)
+ leal 1859775393(%edx,%ecx,1),%edx
+ movl 28(%esp),%ecx
+ addl %ebp,%edx
+ # 20_39 39
+ movl %edi,%ebp
+ xorl 36(%esp),%ecx
+ xorl %esi,%ebp
+ xorl 60(%esp),%ecx
+ xorl %eax,%ebp
+ xorl 16(%esp),%ecx
+ roll $1,%ecx
+ addl %ebp,%ebx
+ rorl $2,%edi
+ movl %edx,%ebp
+ roll $5,%ebp
+ movl %ecx,28(%esp)
+ leal 1859775393(%ecx,%ebx,1),%ecx
+ movl 32(%esp),%ebx
+ addl %ebp,%ecx
+ # 40_59 40
+ movl %edi,%ebp
+ xorl 40(%esp),%ebx
+ xorl %esi,%ebp
+ xorl (%esp),%ebx
+ andl %edx,%ebp
+ xorl 20(%esp),%ebx
+ roll $1,%ebx
+ addl %eax,%ebp
+ rorl $2,%edx
+ movl %ecx,%eax
+ roll $5,%eax
+ movl %ebx,32(%esp)
+ leal 2400959708(%ebx,%ebp,1),%ebx
+ movl %edi,%ebp
+ addl %eax,%ebx
+ andl %esi,%ebp
+ movl 36(%esp),%eax
+ addl %ebp,%ebx
+ # 40_59 41
+ movl %edx,%ebp
+ xorl 44(%esp),%eax
+ xorl %edi,%ebp
+ xorl 4(%esp),%eax
+ andl %ecx,%ebp
+ xorl 24(%esp),%eax
+ roll $1,%eax
+ addl %esi,%ebp
+ rorl $2,%ecx
+ movl %ebx,%esi
+ roll $5,%esi
+ movl %eax,36(%esp)
+ leal 2400959708(%eax,%ebp,1),%eax
+ movl %edx,%ebp
+ addl %esi,%eax
+ andl %edi,%ebp
+ movl 40(%esp),%esi
+ addl %ebp,%eax
+ # 40_59 42
+ movl %ecx,%ebp
+ xorl 48(%esp),%esi
+ xorl %edx,%ebp
+ xorl 8(%esp),%esi
+ andl %ebx,%ebp
+ xorl 28(%esp),%esi
+ roll $1,%esi
+ addl %edi,%ebp
+ rorl $2,%ebx
+ movl %eax,%edi
+ roll $5,%edi
+ movl %esi,40(%esp)
+ leal 2400959708(%esi,%ebp,1),%esi
+ movl %ecx,%ebp
+ addl %edi,%esi
+ andl %edx,%ebp
+ movl 44(%esp),%edi
+ addl %ebp,%esi
+ # 40_59 43
+ movl %ebx,%ebp
+ xorl 52(%esp),%edi
+ xorl %ecx,%ebp
+ xorl 12(%esp),%edi
+ andl %eax,%ebp
+ xorl 32(%esp),%edi
+ roll $1,%edi
+ addl %edx,%ebp
+ rorl $2,%eax
+ movl %esi,%edx
+ roll $5,%edx
+ movl %edi,44(%esp)
+ leal 2400959708(%edi,%ebp,1),%edi
+ movl %ebx,%ebp
+ addl %edx,%edi
+ andl %ecx,%ebp
+ movl 48(%esp),%edx
+ addl %ebp,%edi
+ # 40_59 44
+ movl %eax,%ebp
+ xorl 56(%esp),%edx
+ xorl %ebx,%ebp
+ xorl 16(%esp),%edx
+ andl %esi,%ebp
+ xorl 36(%esp),%edx
+ roll $1,%edx
+ addl %ecx,%ebp
+ rorl $2,%esi
+ movl %edi,%ecx
+ roll $5,%ecx
+ movl %edx,48(%esp)
+ leal 2400959708(%edx,%ebp,1),%edx
+ movl %eax,%ebp
+ addl %ecx,%edx
+ andl %ebx,%ebp
+ movl 52(%esp),%ecx
+ addl %ebp,%edx
+ # 40_59 45
+ movl %esi,%ebp
+ xorl 60(%esp),%ecx
+ xorl %eax,%ebp
+ xorl 20(%esp),%ecx
+ andl %edi,%ebp
+ xorl 40(%esp),%ecx
+ roll $1,%ecx
+ addl %ebx,%ebp
+ rorl $2,%edi
+ movl %edx,%ebx
+ roll $5,%ebx
+ movl %ecx,52(%esp)
+ leal 2400959708(%ecx,%ebp,1),%ecx
+ movl %esi,%ebp
+ addl %ebx,%ecx
+ andl %eax,%ebp
+ movl 56(%esp),%ebx
+ addl %ebp,%ecx
+ # 40_59 46
+ movl %edi,%ebp
+ xorl (%esp),%ebx
+ xorl %esi,%ebp
+ xorl 24(%esp),%ebx
+ andl %edx,%ebp
+ xorl 44(%esp),%ebx
+ roll $1,%ebx
+ addl %eax,%ebp
+ rorl $2,%edx
+ movl %ecx,%eax
+ roll $5,%eax
+ movl %ebx,56(%esp)
+ leal 2400959708(%ebx,%ebp,1),%ebx
+ movl %edi,%ebp
+ addl %eax,%ebx
+ andl %esi,%ebp
+ movl 60(%esp),%eax
+ addl %ebp,%ebx
+ # 40_59 47
+ movl %edx,%ebp
+ xorl 4(%esp),%eax
+ xorl %edi,%ebp
+ xorl 28(%esp),%eax
+ andl %ecx,%ebp
+ xorl 48(%esp),%eax
+ roll $1,%eax
+ addl %esi,%ebp
+ rorl $2,%ecx
+ movl %ebx,%esi
+ roll $5,%esi
+ movl %eax,60(%esp)
+ leal 2400959708(%eax,%ebp,1),%eax
+ movl %edx,%ebp
+ addl %esi,%eax
+ andl %edi,%ebp
+ movl (%esp),%esi
+ addl %ebp,%eax
+ # 40_59 48
+ movl %ecx,%ebp
+ xorl 8(%esp),%esi
+ xorl %edx,%ebp
+ xorl 32(%esp),%esi
+ andl %ebx,%ebp
+ xorl 52(%esp),%esi
+ roll $1,%esi
+ addl %edi,%ebp
+ rorl $2,%ebx
+ movl %eax,%edi
+ roll $5,%edi
+ movl %esi,(%esp)
+ leal 2400959708(%esi,%ebp,1),%esi
+ movl %ecx,%ebp
+ addl %edi,%esi
+ andl %edx,%ebp
+ movl 4(%esp),%edi
+ addl %ebp,%esi
+ # 40_59 49
+ movl %ebx,%ebp
+ xorl 12(%esp),%edi
+ xorl %ecx,%ebp
+ xorl 36(%esp),%edi
+ andl %eax,%ebp
+ xorl 56(%esp),%edi
+ roll $1,%edi
+ addl %edx,%ebp
+ rorl $2,%eax
+ movl %esi,%edx
+ roll $5,%edx
+ movl %edi,4(%esp)
+ leal 2400959708(%edi,%ebp,1),%edi
+ movl %ebx,%ebp
+ addl %edx,%edi
+ andl %ecx,%ebp
+ movl 8(%esp),%edx
+ addl %ebp,%edi
+ # 40_59 50
+ movl %eax,%ebp
+ xorl 16(%esp),%edx
+ xorl %ebx,%ebp
+ xorl 40(%esp),%edx
+ andl %esi,%ebp
+ xorl 60(%esp),%edx
+ roll $1,%edx
+ addl %ecx,%ebp
+ rorl $2,%esi
+ movl %edi,%ecx
+ roll $5,%ecx
+ movl %edx,8(%esp)
+ leal 2400959708(%edx,%ebp,1),%edx
+ movl %eax,%ebp
+ addl %ecx,%edx
+ andl %ebx,%ebp
+ movl 12(%esp),%ecx
+ addl %ebp,%edx
+ # 40_59 51
+ movl %esi,%ebp
+ xorl 20(%esp),%ecx
+ xorl %eax,%ebp
+ xorl 44(%esp),%ecx
+ andl %edi,%ebp
+ xorl (%esp),%ecx
+ roll $1,%ecx
+ addl %ebx,%ebp
+ rorl $2,%edi
+ movl %edx,%ebx
+ roll $5,%ebx
+ movl %ecx,12(%esp)
+ leal 2400959708(%ecx,%ebp,1),%ecx
+ movl %esi,%ebp
+ addl %ebx,%ecx
+ andl %eax,%ebp
+ movl 16(%esp),%ebx
+ addl %ebp,%ecx
+ # 40_59 52
+ movl %edi,%ebp
+ xorl 24(%esp),%ebx
+ xorl %esi,%ebp
+ xorl 48(%esp),%ebx
+ andl %edx,%ebp
+ xorl 4(%esp),%ebx
+ roll $1,%ebx
+ addl %eax,%ebp
+ rorl $2,%edx
+ movl %ecx,%eax
+ roll $5,%eax
+ movl %ebx,16(%esp)
+ leal 2400959708(%ebx,%ebp,1),%ebx
+ movl %edi,%ebp
+ addl %eax,%ebx
+ andl %esi,%ebp
+ movl 20(%esp),%eax
+ addl %ebp,%ebx
+ # 40_59 53
+ movl %edx,%ebp
+ xorl 28(%esp),%eax
+ xorl %edi,%ebp
+ xorl 52(%esp),%eax
+ andl %ecx,%ebp
+ xorl 8(%esp),%eax
+ roll $1,%eax
+ addl %esi,%ebp
+ rorl $2,%ecx
+ movl %ebx,%esi
+ roll $5,%esi
+ movl %eax,20(%esp)
+ leal 2400959708(%eax,%ebp,1),%eax
+ movl %edx,%ebp
+ addl %esi,%eax
+ andl %edi,%ebp
+ movl 24(%esp),%esi
+ addl %ebp,%eax
+ # 40_59 54
+ movl %ecx,%ebp
+ xorl 32(%esp),%esi
+ xorl %edx,%ebp
+ xorl 56(%esp),%esi
+ andl %ebx,%ebp
+ xorl 12(%esp),%esi
+ roll $1,%esi
+ addl %edi,%ebp
+ rorl $2,%ebx
+ movl %eax,%edi
+ roll $5,%edi
+ movl %esi,24(%esp)
+ leal 2400959708(%esi,%ebp,1),%esi
+ movl %ecx,%ebp
+ addl %edi,%esi
+ andl %edx,%ebp
+ movl 28(%esp),%edi
+ addl %ebp,%esi
+ # 40_59 55
+ movl %ebx,%ebp
+ xorl 36(%esp),%edi
+ xorl %ecx,%ebp
+ xorl 60(%esp),%edi
+ andl %eax,%ebp
+ xorl 16(%esp),%edi
+ roll $1,%edi
+ addl %edx,%ebp
+ rorl $2,%eax
+ movl %esi,%edx
+ roll $5,%edx
+ movl %edi,28(%esp)
+ leal 2400959708(%edi,%ebp,1),%edi
+ movl %ebx,%ebp
+ addl %edx,%edi
+ andl %ecx,%ebp
+ movl 32(%esp),%edx
+ addl %ebp,%edi
+ # 40_59 56
+ movl %eax,%ebp
+ xorl 40(%esp),%edx
+ xorl %ebx,%ebp
+ xorl (%esp),%edx
+ andl %esi,%ebp
+ xorl 20(%esp),%edx
+ roll $1,%edx
+ addl %ecx,%ebp
+ rorl $2,%esi
+ movl %edi,%ecx
+ roll $5,%ecx
+ movl %edx,32(%esp)
+ leal 2400959708(%edx,%ebp,1),%edx
+ movl %eax,%ebp
+ addl %ecx,%edx
+ andl %ebx,%ebp
+ movl 36(%esp),%ecx
+ addl %ebp,%edx
+ # 40_59 57
+ movl %esi,%ebp
+ xorl 44(%esp),%ecx
+ xorl %eax,%ebp
+ xorl 4(%esp),%ecx
+ andl %edi,%ebp
+ xorl 24(%esp),%ecx
+ roll $1,%ecx
+ addl %ebx,%ebp
+ rorl $2,%edi
+ movl %edx,%ebx
+ roll $5,%ebx
+ movl %ecx,36(%esp)
+ leal 2400959708(%ecx,%ebp,1),%ecx
+ movl %esi,%ebp
+ addl %ebx,%ecx
+ andl %eax,%ebp
+ movl 40(%esp),%ebx
+ addl %ebp,%ecx
+ # 40_59 58
+ movl %edi,%ebp
+ xorl 48(%esp),%ebx
+ xorl %esi,%ebp
+ xorl 8(%esp),%ebx
+ andl %edx,%ebp
+ xorl 28(%esp),%ebx
+ roll $1,%ebx
+ addl %eax,%ebp
+ rorl $2,%edx
+ movl %ecx,%eax
+ roll $5,%eax
+ movl %ebx,40(%esp)
+ leal 2400959708(%ebx,%ebp,1),%ebx
+ movl %edi,%ebp
+ addl %eax,%ebx
+ andl %esi,%ebp
+ movl 44(%esp),%eax
+ addl %ebp,%ebx
+ # 40_59 59
+ movl %edx,%ebp
+ xorl 52(%esp),%eax
+ xorl %edi,%ebp
+ xorl 12(%esp),%eax
+ andl %ecx,%ebp
+ xorl 32(%esp),%eax
+ roll $1,%eax
+ addl %esi,%ebp
+ rorl $2,%ecx
+ movl %ebx,%esi
+ roll $5,%esi
+ movl %eax,44(%esp)
+ leal 2400959708(%eax,%ebp,1),%eax
+ movl %edx,%ebp
+ addl %esi,%eax
+ andl %edi,%ebp
+ movl 48(%esp),%esi
+ addl %ebp,%eax
+ # 20_39 60
+ movl %ebx,%ebp
+ xorl 56(%esp),%esi
+ xorl %ecx,%ebp
+ xorl 16(%esp),%esi
+ xorl %edx,%ebp
+ xorl 36(%esp),%esi
+ roll $1,%esi
+ addl %ebp,%edi
+ rorl $2,%ebx
+ movl %eax,%ebp
+ roll $5,%ebp
+ movl %esi,48(%esp)
+ leal 3395469782(%esi,%edi,1),%esi
+ movl 52(%esp),%edi
+ addl %ebp,%esi
+ # 20_39 61
+ movl %eax,%ebp
+ xorl 60(%esp),%edi
+ xorl %ebx,%ebp
+ xorl 20(%esp),%edi
+ xorl %ecx,%ebp
+ xorl 40(%esp),%edi
+ roll $1,%edi
+ addl %ebp,%edx
+ rorl $2,%eax
+ movl %esi,%ebp
+ roll $5,%ebp
+ movl %edi,52(%esp)
+ leal 3395469782(%edi,%edx,1),%edi
+ movl 56(%esp),%edx
+ addl %ebp,%edi
+ # 20_39 62
+ movl %esi,%ebp
+ xorl (%esp),%edx
+ xorl %eax,%ebp
+ xorl 24(%esp),%edx
+ xorl %ebx,%ebp
+ xorl 44(%esp),%edx
+ roll $1,%edx
+ addl %ebp,%ecx
+ rorl $2,%esi
+ movl %edi,%ebp
+ roll $5,%ebp
+ movl %edx,56(%esp)
+ leal 3395469782(%edx,%ecx,1),%edx
+ movl 60(%esp),%ecx
+ addl %ebp,%edx
+ # 20_39 63
+ movl %edi,%ebp
+ xorl 4(%esp),%ecx
+ xorl %esi,%ebp
+ xorl 28(%esp),%ecx
+ xorl %eax,%ebp
+ xorl 48(%esp),%ecx
+ roll $1,%ecx
+ addl %ebp,%ebx
+ rorl $2,%edi
+ movl %edx,%ebp
+ roll $5,%ebp
+ movl %ecx,60(%esp)
+ leal 3395469782(%ecx,%ebx,1),%ecx
+ movl (%esp),%ebx
+ addl %ebp,%ecx
+ # 20_39 64
+ movl %edx,%ebp
+ xorl 8(%esp),%ebx
+ xorl %edi,%ebp
+ xorl 32(%esp),%ebx
+ xorl %esi,%ebp
+ xorl 52(%esp),%ebx
+ roll $1,%ebx
+ addl %ebp,%eax
+ rorl $2,%edx
+ movl %ecx,%ebp
+ roll $5,%ebp
+ movl %ebx,(%esp)
+ leal 3395469782(%ebx,%eax,1),%ebx
+ movl 4(%esp),%eax
+ addl %ebp,%ebx
+ # 20_39 65
+ movl %ecx,%ebp
+ xorl 12(%esp),%eax
+ xorl %edx,%ebp
+ xorl 36(%esp),%eax
+ xorl %edi,%ebp
+ xorl 56(%esp),%eax
+ roll $1,%eax
+ addl %ebp,%esi
+ rorl $2,%ecx
+ movl %ebx,%ebp
+ roll $5,%ebp
+ movl %eax,4(%esp)
+ leal 3395469782(%eax,%esi,1),%eax
+ movl 8(%esp),%esi
+ addl %ebp,%eax
+ # 20_39 66
+ movl %ebx,%ebp
+ xorl 16(%esp),%esi
+ xorl %ecx,%ebp
+ xorl 40(%esp),%esi
+ xorl %edx,%ebp
+ xorl 60(%esp),%esi
+ roll $1,%esi
+ addl %ebp,%edi
+ rorl $2,%ebx
+ movl %eax,%ebp
+ roll $5,%ebp
+ movl %esi,8(%esp)
+ leal 3395469782(%esi,%edi,1),%esi
+ movl 12(%esp),%edi
+ addl %ebp,%esi
+ # 20_39 67
+ movl %eax,%ebp
+ xorl 20(%esp),%edi
+ xorl %ebx,%ebp
+ xorl 44(%esp),%edi
+ xorl %ecx,%ebp
+ xorl (%esp),%edi
+ roll $1,%edi
+ addl %ebp,%edx
+ rorl $2,%eax
+ movl %esi,%ebp
+ roll $5,%ebp
+ movl %edi,12(%esp)
+ leal 3395469782(%edi,%edx,1),%edi
+ movl 16(%esp),%edx
+ addl %ebp,%edi
+ # 20_39 68
+ movl %esi,%ebp
+ xorl 24(%esp),%edx
+ xorl %eax,%ebp
+ xorl 48(%esp),%edx
+ xorl %ebx,%ebp
+ xorl 4(%esp),%edx
+ roll $1,%edx
+ addl %ebp,%ecx
+ rorl $2,%esi
+ movl %edi,%ebp
+ roll $5,%ebp
+ movl %edx,16(%esp)
+ leal 3395469782(%edx,%ecx,1),%edx
+ movl 20(%esp),%ecx
+ addl %ebp,%edx
+ # 20_39 69
+ movl %edi,%ebp
+ xorl 28(%esp),%ecx
+ xorl %esi,%ebp
+ xorl 52(%esp),%ecx
+ xorl %eax,%ebp
+ xorl 8(%esp),%ecx
+ roll $1,%ecx
+ addl %ebp,%ebx
+ rorl $2,%edi
+ movl %edx,%ebp
+ roll $5,%ebp
+ movl %ecx,20(%esp)
+ leal 3395469782(%ecx,%ebx,1),%ecx
+ movl 24(%esp),%ebx
+ addl %ebp,%ecx
+ # 20_39 70
+ movl %edx,%ebp
+ xorl 32(%esp),%ebx
+ xorl %edi,%ebp
+ xorl 56(%esp),%ebx
+ xorl %esi,%ebp
+ xorl 12(%esp),%ebx
+ roll $1,%ebx
+ addl %ebp,%eax
+ rorl $2,%edx
+ movl %ecx,%ebp
+ roll $5,%ebp
+ movl %ebx,24(%esp)
+ leal 3395469782(%ebx,%eax,1),%ebx
+ movl 28(%esp),%eax
+ addl %ebp,%ebx
+ # 20_39 71
+ movl %ecx,%ebp
+ xorl 36(%esp),%eax
+ xorl %edx,%ebp
+ xorl 60(%esp),%eax
+ xorl %edi,%ebp
+ xorl 16(%esp),%eax
+ roll $1,%eax
+ addl %ebp,%esi
+ rorl $2,%ecx
+ movl %ebx,%ebp
+ roll $5,%ebp
+ movl %eax,28(%esp)
+ leal 3395469782(%eax,%esi,1),%eax
+ movl 32(%esp),%esi
+ addl %ebp,%eax
+ # 20_39 72
+ movl %ebx,%ebp
+ xorl 40(%esp),%esi
+ xorl %ecx,%ebp
+ xorl (%esp),%esi
+ xorl %edx,%ebp
+ xorl 20(%esp),%esi
+ roll $1,%esi
+ addl %ebp,%edi
+ rorl $2,%ebx
+ movl %eax,%ebp
+ roll $5,%ebp
+ movl %esi,32(%esp)
+ leal 3395469782(%esi,%edi,1),%esi
+ movl 36(%esp),%edi
+ addl %ebp,%esi
+ # 20_39 73
+ movl %eax,%ebp
+ xorl 44(%esp),%edi
+ xorl %ebx,%ebp
+ xorl 4(%esp),%edi
+ xorl %ecx,%ebp
+ xorl 24(%esp),%edi
+ roll $1,%edi
+ addl %ebp,%edx
+ rorl $2,%eax
+ movl %esi,%ebp
+ roll $5,%ebp
+ movl %edi,36(%esp)
+ leal 3395469782(%edi,%edx,1),%edi
+ movl 40(%esp),%edx
+ addl %ebp,%edi
+ # 20_39 74
+ movl %esi,%ebp
+ xorl 48(%esp),%edx
+ xorl %eax,%ebp
+ xorl 8(%esp),%edx
+ xorl %ebx,%ebp
+ xorl 28(%esp),%edx
+ roll $1,%edx
+ addl %ebp,%ecx
+ rorl $2,%esi
+ movl %edi,%ebp
+ roll $5,%ebp
+ movl %edx,40(%esp)
+ leal 3395469782(%edx,%ecx,1),%edx
+ movl 44(%esp),%ecx
+ addl %ebp,%edx
+ # 20_39 75
+ movl %edi,%ebp
+ xorl 52(%esp),%ecx
+ xorl %esi,%ebp
+ xorl 12(%esp),%ecx
+ xorl %eax,%ebp
+ xorl 32(%esp),%ecx
+ roll $1,%ecx
+ addl %ebp,%ebx
+ rorl $2,%edi
+ movl %edx,%ebp
+ roll $5,%ebp
+ movl %ecx,44(%esp)
+ leal 3395469782(%ecx,%ebx,1),%ecx
+ movl 48(%esp),%ebx
+ addl %ebp,%ecx
+ # 20_39 76
+ movl %edx,%ebp
+ xorl 56(%esp),%ebx
+ xorl %edi,%ebp
+ xorl 16(%esp),%ebx
+ xorl %esi,%ebp
+ xorl 36(%esp),%ebx
+ roll $1,%ebx
+ addl %ebp,%eax
+ rorl $2,%edx
+ movl %ecx,%ebp
+ roll $5,%ebp
+ movl %ebx,48(%esp)
+ leal 3395469782(%ebx,%eax,1),%ebx
+ movl 52(%esp),%eax
+ addl %ebp,%ebx
+ # 20_39 77
+ movl %ecx,%ebp
+ xorl 60(%esp),%eax
+ xorl %edx,%ebp
+ xorl 20(%esp),%eax
+ xorl %edi,%ebp
+ xorl 40(%esp),%eax
+ roll $1,%eax
+ addl %ebp,%esi
+ rorl $2,%ecx
+ movl %ebx,%ebp
+ roll $5,%ebp
+ leal 3395469782(%eax,%esi,1),%eax
+ movl 56(%esp),%esi
+ addl %ebp,%eax
+ # 20_39 78
+ movl %ebx,%ebp
+ xorl (%esp),%esi
+ xorl %ecx,%ebp
+ xorl 24(%esp),%esi
+ xorl %edx,%ebp
+ xorl 44(%esp),%esi
+ roll $1,%esi
+ addl %ebp,%edi
+ rorl $2,%ebx
+ movl %eax,%ebp
+ roll $5,%ebp
+ leal 3395469782(%esi,%edi,1),%esi
+ movl 60(%esp),%edi
+ addl %ebp,%esi
+ # 20_39 79
+ movl %eax,%ebp
+ xorl 4(%esp),%edi
+ xorl %ebx,%ebp
+ xorl 28(%esp),%edi
+ xorl %ecx,%ebp
+ xorl 48(%esp),%edi
+ roll $1,%edi
+ addl %ebp,%edx
+ rorl $2,%eax
+ movl %esi,%ebp
+ roll $5,%ebp
+ leal 3395469782(%edi,%edx,1),%edi
+ addl %ebp,%edi
+ movl 96(%esp),%ebp
+ movl 100(%esp),%edx
+ addl (%ebp),%edi
+ addl 4(%ebp),%esi
+ addl 8(%ebp),%eax
+ addl 12(%ebp),%ebx
+ addl 16(%ebp),%ecx
+ movl %edi,(%ebp)
+ addl $64,%edx
+ movl %esi,4(%ebp)
+ cmpl 104(%esp),%edx
+ movl %eax,8(%ebp)
+ movl %ecx,%edi
+ movl %ebx,12(%ebp)
+ movl %edx,%esi
+ movl %ecx,16(%ebp)
+ jb L000loop
+ addl $76,%esp
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.byte 83,72,65,49,32,98,108,111,99,107,32,116,114,97,110,115
+.byte 102,111,114,109,32,102,111,114,32,120,56,54,44,32,67,82
+.byte 89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112
+.byte 114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
+#endif
diff --git a/mac-x86/crypto/sha/sha256-586.S b/mac-x86/crypto/sha/sha256-586.S
new file mode 100644
index 0000000..d40db0d
--- /dev/null
+++ b/mac-x86/crypto/sha/sha256-586.S
@@ -0,0 +1,3348 @@
+#if defined(__i386__)
+.file "sha512-586.S"
+.text
+.globl _sha256_block_data_order
+.private_extern _sha256_block_data_order
+.align 4
+_sha256_block_data_order:
+L_sha256_block_data_order_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ movl 20(%esp),%esi
+ movl 24(%esp),%edi
+ movl 28(%esp),%eax
+ movl %esp,%ebx
+ call L000pic_point
+L000pic_point:
+ popl %ebp
+ leal L001K256-L000pic_point(%ebp),%ebp
+ subl $16,%esp
+ andl $-64,%esp
+ shll $6,%eax
+ addl %edi,%eax
+ movl %esi,(%esp)
+ movl %edi,4(%esp)
+ movl %eax,8(%esp)
+ movl %ebx,12(%esp)
+ jmp L002loop
+.align 4,0x90
+L002loop:
+ movl (%edi),%eax
+ movl 4(%edi),%ebx
+ movl 8(%edi),%ecx
+ bswap %eax
+ movl 12(%edi),%edx
+ bswap %ebx
+ pushl %eax
+ bswap %ecx
+ pushl %ebx
+ bswap %edx
+ pushl %ecx
+ pushl %edx
+ movl 16(%edi),%eax
+ movl 20(%edi),%ebx
+ movl 24(%edi),%ecx
+ bswap %eax
+ movl 28(%edi),%edx
+ bswap %ebx
+ pushl %eax
+ bswap %ecx
+ pushl %ebx
+ bswap %edx
+ pushl %ecx
+ pushl %edx
+ movl 32(%edi),%eax
+ movl 36(%edi),%ebx
+ movl 40(%edi),%ecx
+ bswap %eax
+ movl 44(%edi),%edx
+ bswap %ebx
+ pushl %eax
+ bswap %ecx
+ pushl %ebx
+ bswap %edx
+ pushl %ecx
+ pushl %edx
+ movl 48(%edi),%eax
+ movl 52(%edi),%ebx
+ movl 56(%edi),%ecx
+ bswap %eax
+ movl 60(%edi),%edx
+ bswap %ebx
+ pushl %eax
+ bswap %ecx
+ pushl %ebx
+ bswap %edx
+ pushl %ecx
+ pushl %edx
+ addl $64,%edi
+ leal -36(%esp),%esp
+ movl %edi,104(%esp)
+ movl (%esi),%eax
+ movl 4(%esi),%ebx
+ movl 8(%esi),%ecx
+ movl 12(%esi),%edi
+ movl %ebx,8(%esp)
+ xorl %ecx,%ebx
+ movl %ecx,12(%esp)
+ movl %edi,16(%esp)
+ movl %ebx,(%esp)
+ movl 16(%esi),%edx
+ movl 20(%esi),%ebx
+ movl 24(%esi),%ecx
+ movl 28(%esi),%edi
+ movl %ebx,24(%esp)
+ movl %ecx,28(%esp)
+ movl %edi,32(%esp)
+.align 4,0x90
+L00300_15:
+ movl %edx,%ecx
+ movl 24(%esp),%esi
+ rorl $14,%ecx
+ movl 28(%esp),%edi
+ xorl %edx,%ecx
+ xorl %edi,%esi
+ movl 96(%esp),%ebx
+ rorl $5,%ecx
+ andl %edx,%esi
+ movl %edx,20(%esp)
+ xorl %ecx,%edx
+ addl 32(%esp),%ebx
+ xorl %edi,%esi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %esi,%ebx
+ rorl $9,%ecx
+ addl %edx,%ebx
+ movl 8(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,4(%esp)
+ leal -4(%esp),%esp
+ rorl $11,%ecx
+ movl (%ebp),%esi
+ xorl %eax,%ecx
+ movl 20(%esp),%edx
+ xorl %edi,%eax
+ rorl $2,%ecx
+ addl %esi,%ebx
+ movl %eax,(%esp)
+ addl %ebx,%edx
+ andl 4(%esp),%eax
+ addl %ecx,%ebx
+ xorl %edi,%eax
+ addl $4,%ebp
+ addl %ebx,%eax
+ cmpl $3248222580,%esi
+ jne L00300_15
+ movl 156(%esp),%ecx
+ jmp L00416_63
+.align 4,0x90
+L00416_63:
+ movl %ecx,%ebx
+ movl 104(%esp),%esi
+ rorl $11,%ecx
+ movl %esi,%edi
+ rorl $2,%esi
+ xorl %ebx,%ecx
+ shrl $3,%ebx
+ rorl $7,%ecx
+ xorl %edi,%esi
+ xorl %ecx,%ebx
+ rorl $17,%esi
+ addl 160(%esp),%ebx
+ shrl $10,%edi
+ addl 124(%esp),%ebx
+ movl %edx,%ecx
+ xorl %esi,%edi
+ movl 24(%esp),%esi
+ rorl $14,%ecx
+ addl %edi,%ebx
+ movl 28(%esp),%edi
+ xorl %edx,%ecx
+ xorl %edi,%esi
+ movl %ebx,96(%esp)
+ rorl $5,%ecx
+ andl %edx,%esi
+ movl %edx,20(%esp)
+ xorl %ecx,%edx
+ addl 32(%esp),%ebx
+ xorl %edi,%esi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %esi,%ebx
+ rorl $9,%ecx
+ addl %edx,%ebx
+ movl 8(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,4(%esp)
+ leal -4(%esp),%esp
+ rorl $11,%ecx
+ movl (%ebp),%esi
+ xorl %eax,%ecx
+ movl 20(%esp),%edx
+ xorl %edi,%eax
+ rorl $2,%ecx
+ addl %esi,%ebx
+ movl %eax,(%esp)
+ addl %ebx,%edx
+ andl 4(%esp),%eax
+ addl %ecx,%ebx
+ xorl %edi,%eax
+ movl 156(%esp),%ecx
+ addl $4,%ebp
+ addl %ebx,%eax
+ cmpl $3329325298,%esi
+ jne L00416_63
+ movl 356(%esp),%esi
+ movl 8(%esp),%ebx
+ movl 16(%esp),%ecx
+ addl (%esi),%eax
+ addl 4(%esi),%ebx
+ addl 8(%esi),%edi
+ addl 12(%esi),%ecx
+ movl %eax,(%esi)
+ movl %ebx,4(%esi)
+ movl %edi,8(%esi)
+ movl %ecx,12(%esi)
+ movl 24(%esp),%eax
+ movl 28(%esp),%ebx
+ movl 32(%esp),%ecx
+ movl 360(%esp),%edi
+ addl 16(%esi),%edx
+ addl 20(%esi),%eax
+ addl 24(%esi),%ebx
+ addl 28(%esi),%ecx
+ movl %edx,16(%esi)
+ movl %eax,20(%esi)
+ movl %ebx,24(%esi)
+ movl %ecx,28(%esi)
+ leal 356(%esp),%esp
+ subl $256,%ebp
+ cmpl 8(%esp),%edi
+ jb L002loop
+ movl 12(%esp),%esp
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.align 5,0x90
+L005loop_shrd:
+ movl (%edi),%eax
+ movl 4(%edi),%ebx
+ movl 8(%edi),%ecx
+ bswap %eax
+ movl 12(%edi),%edx
+ bswap %ebx
+ pushl %eax
+ bswap %ecx
+ pushl %ebx
+ bswap %edx
+ pushl %ecx
+ pushl %edx
+ movl 16(%edi),%eax
+ movl 20(%edi),%ebx
+ movl 24(%edi),%ecx
+ bswap %eax
+ movl 28(%edi),%edx
+ bswap %ebx
+ pushl %eax
+ bswap %ecx
+ pushl %ebx
+ bswap %edx
+ pushl %ecx
+ pushl %edx
+ movl 32(%edi),%eax
+ movl 36(%edi),%ebx
+ movl 40(%edi),%ecx
+ bswap %eax
+ movl 44(%edi),%edx
+ bswap %ebx
+ pushl %eax
+ bswap %ecx
+ pushl %ebx
+ bswap %edx
+ pushl %ecx
+ pushl %edx
+ movl 48(%edi),%eax
+ movl 52(%edi),%ebx
+ movl 56(%edi),%ecx
+ bswap %eax
+ movl 60(%edi),%edx
+ bswap %ebx
+ pushl %eax
+ bswap %ecx
+ pushl %ebx
+ bswap %edx
+ pushl %ecx
+ pushl %edx
+ addl $64,%edi
+ leal -36(%esp),%esp
+ movl %edi,104(%esp)
+ movl (%esi),%eax
+ movl 4(%esi),%ebx
+ movl 8(%esi),%ecx
+ movl 12(%esi),%edi
+ movl %ebx,8(%esp)
+ xorl %ecx,%ebx
+ movl %ecx,12(%esp)
+ movl %edi,16(%esp)
+ movl %ebx,(%esp)
+ movl 16(%esi),%edx
+ movl 20(%esi),%ebx
+ movl 24(%esi),%ecx
+ movl 28(%esi),%edi
+ movl %ebx,24(%esp)
+ movl %ecx,28(%esp)
+ movl %edi,32(%esp)
+.align 4,0x90
+L00600_15_shrd:
+ movl %edx,%ecx
+ movl 24(%esp),%esi
+ shrdl $14,%ecx,%ecx
+ movl 28(%esp),%edi
+ xorl %edx,%ecx
+ xorl %edi,%esi
+ movl 96(%esp),%ebx
+ shrdl $5,%ecx,%ecx
+ andl %edx,%esi
+ movl %edx,20(%esp)
+ xorl %ecx,%edx
+ addl 32(%esp),%ebx
+ xorl %edi,%esi
+ shrdl $6,%edx,%edx
+ movl %eax,%ecx
+ addl %esi,%ebx
+ shrdl $9,%ecx,%ecx
+ addl %edx,%ebx
+ movl 8(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,4(%esp)
+ leal -4(%esp),%esp
+ shrdl $11,%ecx,%ecx
+ movl (%ebp),%esi
+ xorl %eax,%ecx
+ movl 20(%esp),%edx
+ xorl %edi,%eax
+ shrdl $2,%ecx,%ecx
+ addl %esi,%ebx
+ movl %eax,(%esp)
+ addl %ebx,%edx
+ andl 4(%esp),%eax
+ addl %ecx,%ebx
+ xorl %edi,%eax
+ addl $4,%ebp
+ addl %ebx,%eax
+ cmpl $3248222580,%esi
+ jne L00600_15_shrd
+ movl 156(%esp),%ecx
+ jmp L00716_63_shrd
+.align 4,0x90
+L00716_63_shrd:
+ movl %ecx,%ebx
+ movl 104(%esp),%esi
+ shrdl $11,%ecx,%ecx
+ movl %esi,%edi
+ shrdl $2,%esi,%esi
+ xorl %ebx,%ecx
+ shrl $3,%ebx
+ shrdl $7,%ecx,%ecx
+ xorl %edi,%esi
+ xorl %ecx,%ebx
+ shrdl $17,%esi,%esi
+ addl 160(%esp),%ebx
+ shrl $10,%edi
+ addl 124(%esp),%ebx
+ movl %edx,%ecx
+ xorl %esi,%edi
+ movl 24(%esp),%esi
+ shrdl $14,%ecx,%ecx
+ addl %edi,%ebx
+ movl 28(%esp),%edi
+ xorl %edx,%ecx
+ xorl %edi,%esi
+ movl %ebx,96(%esp)
+ shrdl $5,%ecx,%ecx
+ andl %edx,%esi
+ movl %edx,20(%esp)
+ xorl %ecx,%edx
+ addl 32(%esp),%ebx
+ xorl %edi,%esi
+ shrdl $6,%edx,%edx
+ movl %eax,%ecx
+ addl %esi,%ebx
+ shrdl $9,%ecx,%ecx
+ addl %edx,%ebx
+ movl 8(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,4(%esp)
+ leal -4(%esp),%esp
+ shrdl $11,%ecx,%ecx
+ movl (%ebp),%esi
+ xorl %eax,%ecx
+ movl 20(%esp),%edx
+ xorl %edi,%eax
+ shrdl $2,%ecx,%ecx
+ addl %esi,%ebx
+ movl %eax,(%esp)
+ addl %ebx,%edx
+ andl 4(%esp),%eax
+ addl %ecx,%ebx
+ xorl %edi,%eax
+ movl 156(%esp),%ecx
+ addl $4,%ebp
+ addl %ebx,%eax
+ cmpl $3329325298,%esi
+ jne L00716_63_shrd
+ movl 356(%esp),%esi
+ movl 8(%esp),%ebx
+ movl 16(%esp),%ecx
+ addl (%esi),%eax
+ addl 4(%esi),%ebx
+ addl 8(%esi),%edi
+ addl 12(%esi),%ecx
+ movl %eax,(%esi)
+ movl %ebx,4(%esi)
+ movl %edi,8(%esi)
+ movl %ecx,12(%esi)
+ movl 24(%esp),%eax
+ movl 28(%esp),%ebx
+ movl 32(%esp),%ecx
+ movl 360(%esp),%edi
+ addl 16(%esi),%edx
+ addl 20(%esi),%eax
+ addl 24(%esi),%ebx
+ addl 28(%esi),%ecx
+ movl %edx,16(%esi)
+ movl %eax,20(%esi)
+ movl %ebx,24(%esi)
+ movl %ecx,28(%esi)
+ leal 356(%esp),%esp
+ subl $256,%ebp
+ cmpl 8(%esp),%edi
+ jb L005loop_shrd
+ movl 12(%esp),%esp
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.align 6,0x90
+L001K256:
+.long 1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298
+.long 66051,67438087,134810123,202182159
+.byte 83,72,65,50,53,54,32,98,108,111,99,107,32,116,114,97
+.byte 110,115,102,111,114,109,32,102,111,114,32,120,56,54,44,32
+.byte 67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97
+.byte 112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103
+.byte 62,0
+.align 4,0x90
+L008unrolled:
+ leal -96(%esp),%esp
+ movl (%esi),%eax
+ movl 4(%esi),%ebp
+ movl 8(%esi),%ecx
+ movl 12(%esi),%ebx
+ movl %ebp,4(%esp)
+ xorl %ecx,%ebp
+ movl %ecx,8(%esp)
+ movl %ebx,12(%esp)
+ movl 16(%esi),%edx
+ movl 20(%esi),%ebx
+ movl 24(%esi),%ecx
+ movl 28(%esi),%esi
+ movl %ebx,20(%esp)
+ movl %ecx,24(%esp)
+ movl %esi,28(%esp)
+ jmp L009grand_loop
+.align 4,0x90
+L009grand_loop:
+ movl (%edi),%ebx
+ movl 4(%edi),%ecx
+ bswap %ebx
+ movl 8(%edi),%esi
+ bswap %ecx
+ movl %ebx,32(%esp)
+ bswap %esi
+ movl %ecx,36(%esp)
+ movl %esi,40(%esp)
+ movl 12(%edi),%ebx
+ movl 16(%edi),%ecx
+ bswap %ebx
+ movl 20(%edi),%esi
+ bswap %ecx
+ movl %ebx,44(%esp)
+ bswap %esi
+ movl %ecx,48(%esp)
+ movl %esi,52(%esp)
+ movl 24(%edi),%ebx
+ movl 28(%edi),%ecx
+ bswap %ebx
+ movl 32(%edi),%esi
+ bswap %ecx
+ movl %ebx,56(%esp)
+ bswap %esi
+ movl %ecx,60(%esp)
+ movl %esi,64(%esp)
+ movl 36(%edi),%ebx
+ movl 40(%edi),%ecx
+ bswap %ebx
+ movl 44(%edi),%esi
+ bswap %ecx
+ movl %ebx,68(%esp)
+ bswap %esi
+ movl %ecx,72(%esp)
+ movl %esi,76(%esp)
+ movl 48(%edi),%ebx
+ movl 52(%edi),%ecx
+ bswap %ebx
+ movl 56(%edi),%esi
+ bswap %ecx
+ movl %ebx,80(%esp)
+ bswap %esi
+ movl %ecx,84(%esp)
+ movl %esi,88(%esp)
+ movl 60(%edi),%ebx
+ addl $64,%edi
+ bswap %ebx
+ movl %edi,100(%esp)
+ movl %ebx,92(%esp)
+ movl %edx,%ecx
+ movl 20(%esp),%esi
+ rorl $14,%edx
+ movl 24(%esp),%edi
+ xorl %ecx,%edx
+ movl 32(%esp),%ebx
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,16(%esp)
+ xorl %ecx,%edx
+ addl 28(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 4(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 1116352408(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 12(%esp),%edx
+ addl %ecx,%ebp
+ movl %edx,%esi
+ movl 16(%esp),%ecx
+ rorl $14,%edx
+ movl 20(%esp),%edi
+ xorl %esi,%edx
+ movl 36(%esp),%ebx
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,12(%esp)
+ xorl %esi,%edx
+ addl 24(%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl (%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,28(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 1899447441(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ rorl $2,%esi
+ addl %edx,%eax
+ addl 8(%esp),%edx
+ addl %esi,%eax
+ movl %edx,%ecx
+ movl 12(%esp),%esi
+ rorl $14,%edx
+ movl 16(%esp),%edi
+ xorl %ecx,%edx
+ movl 40(%esp),%ebx
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,8(%esp)
+ xorl %ecx,%edx
+ addl 20(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 28(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,24(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 3049323471(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 4(%esp),%edx
+ addl %ecx,%ebp
+ movl %edx,%esi
+ movl 8(%esp),%ecx
+ rorl $14,%edx
+ movl 12(%esp),%edi
+ xorl %esi,%edx
+ movl 44(%esp),%ebx
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,4(%esp)
+ xorl %esi,%edx
+ addl 16(%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl 24(%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,20(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 3921009573(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ rorl $2,%esi
+ addl %edx,%eax
+ addl (%esp),%edx
+ addl %esi,%eax
+ movl %edx,%ecx
+ movl 4(%esp),%esi
+ rorl $14,%edx
+ movl 8(%esp),%edi
+ xorl %ecx,%edx
+ movl 48(%esp),%ebx
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,(%esp)
+ xorl %ecx,%edx
+ addl 12(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 20(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,16(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 961987163(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 28(%esp),%edx
+ addl %ecx,%ebp
+ movl %edx,%esi
+ movl (%esp),%ecx
+ rorl $14,%edx
+ movl 4(%esp),%edi
+ xorl %esi,%edx
+ movl 52(%esp),%ebx
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,28(%esp)
+ xorl %esi,%edx
+ addl 8(%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl 16(%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,12(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 1508970993(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ rorl $2,%esi
+ addl %edx,%eax
+ addl 24(%esp),%edx
+ addl %esi,%eax
+ movl %edx,%ecx
+ movl 28(%esp),%esi
+ rorl $14,%edx
+ movl (%esp),%edi
+ xorl %ecx,%edx
+ movl 56(%esp),%ebx
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,24(%esp)
+ xorl %ecx,%edx
+ addl 4(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 12(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,8(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 2453635748(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 20(%esp),%edx
+ addl %ecx,%ebp
+ movl %edx,%esi
+ movl 24(%esp),%ecx
+ rorl $14,%edx
+ movl 28(%esp),%edi
+ xorl %esi,%edx
+ movl 60(%esp),%ebx
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,20(%esp)
+ xorl %esi,%edx
+ addl (%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl 8(%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,4(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 2870763221(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ rorl $2,%esi
+ addl %edx,%eax
+ addl 16(%esp),%edx
+ addl %esi,%eax
+ movl %edx,%ecx
+ movl 20(%esp),%esi
+ rorl $14,%edx
+ movl 24(%esp),%edi
+ xorl %ecx,%edx
+ movl 64(%esp),%ebx
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,16(%esp)
+ xorl %ecx,%edx
+ addl 28(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 4(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 3624381080(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 12(%esp),%edx
+ addl %ecx,%ebp
+ movl %edx,%esi
+ movl 16(%esp),%ecx
+ rorl $14,%edx
+ movl 20(%esp),%edi
+ xorl %esi,%edx
+ movl 68(%esp),%ebx
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,12(%esp)
+ xorl %esi,%edx
+ addl 24(%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl (%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,28(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 310598401(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ rorl $2,%esi
+ addl %edx,%eax
+ addl 8(%esp),%edx
+ addl %esi,%eax
+ movl %edx,%ecx
+ movl 12(%esp),%esi
+ rorl $14,%edx
+ movl 16(%esp),%edi
+ xorl %ecx,%edx
+ movl 72(%esp),%ebx
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,8(%esp)
+ xorl %ecx,%edx
+ addl 20(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 28(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,24(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 607225278(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 4(%esp),%edx
+ addl %ecx,%ebp
+ movl %edx,%esi
+ movl 8(%esp),%ecx
+ rorl $14,%edx
+ movl 12(%esp),%edi
+ xorl %esi,%edx
+ movl 76(%esp),%ebx
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,4(%esp)
+ xorl %esi,%edx
+ addl 16(%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl 24(%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,20(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 1426881987(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ rorl $2,%esi
+ addl %edx,%eax
+ addl (%esp),%edx
+ addl %esi,%eax
+ movl %edx,%ecx
+ movl 4(%esp),%esi
+ rorl $14,%edx
+ movl 8(%esp),%edi
+ xorl %ecx,%edx
+ movl 80(%esp),%ebx
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,(%esp)
+ xorl %ecx,%edx
+ addl 12(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 20(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,16(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 1925078388(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 28(%esp),%edx
+ addl %ecx,%ebp
+ movl %edx,%esi
+ movl (%esp),%ecx
+ rorl $14,%edx
+ movl 4(%esp),%edi
+ xorl %esi,%edx
+ movl 84(%esp),%ebx
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,28(%esp)
+ xorl %esi,%edx
+ addl 8(%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl 16(%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,12(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 2162078206(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ rorl $2,%esi
+ addl %edx,%eax
+ addl 24(%esp),%edx
+ addl %esi,%eax
+ movl %edx,%ecx
+ movl 28(%esp),%esi
+ rorl $14,%edx
+ movl (%esp),%edi
+ xorl %ecx,%edx
+ movl 88(%esp),%ebx
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,24(%esp)
+ xorl %ecx,%edx
+ addl 4(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 12(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,8(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 2614888103(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 20(%esp),%edx
+ addl %ecx,%ebp
+ movl %edx,%esi
+ movl 24(%esp),%ecx
+ rorl $14,%edx
+ movl 28(%esp),%edi
+ xorl %esi,%edx
+ movl 92(%esp),%ebx
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,20(%esp)
+ xorl %esi,%edx
+ addl (%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl 8(%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,4(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 3248222580(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ movl 36(%esp),%ecx
+ rorl $2,%esi
+ addl %edx,%eax
+ addl 16(%esp),%edx
+ addl %esi,%eax
+ movl 88(%esp),%esi
+ movl %ecx,%ebx
+ rorl $11,%ecx
+ movl %esi,%edi
+ rorl $2,%esi
+ xorl %ebx,%ecx
+ shrl $3,%ebx
+ rorl $7,%ecx
+ xorl %edi,%esi
+ xorl %ecx,%ebx
+ rorl $17,%esi
+ addl 32(%esp),%ebx
+ shrl $10,%edi
+ addl 68(%esp),%ebx
+ movl %edx,%ecx
+ xorl %esi,%edi
+ movl 20(%esp),%esi
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 24(%esp),%edi
+ xorl %ecx,%edx
+ movl %ebx,32(%esp)
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,16(%esp)
+ xorl %ecx,%edx
+ addl 28(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 4(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 3835390401(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ movl 40(%esp),%esi
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 12(%esp),%edx
+ addl %ecx,%ebp
+ movl 92(%esp),%ecx
+ movl %esi,%ebx
+ rorl $11,%esi
+ movl %ecx,%edi
+ rorl $2,%ecx
+ xorl %ebx,%esi
+ shrl $3,%ebx
+ rorl $7,%esi
+ xorl %edi,%ecx
+ xorl %esi,%ebx
+ rorl $17,%ecx
+ addl 36(%esp),%ebx
+ shrl $10,%edi
+ addl 72(%esp),%ebx
+ movl %edx,%esi
+ xorl %ecx,%edi
+ movl 16(%esp),%ecx
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 20(%esp),%edi
+ xorl %esi,%edx
+ movl %ebx,36(%esp)
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,12(%esp)
+ xorl %esi,%edx
+ addl 24(%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl (%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,28(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 4022224774(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ movl 44(%esp),%ecx
+ rorl $2,%esi
+ addl %edx,%eax
+ addl 8(%esp),%edx
+ addl %esi,%eax
+ movl 32(%esp),%esi
+ movl %ecx,%ebx
+ rorl $11,%ecx
+ movl %esi,%edi
+ rorl $2,%esi
+ xorl %ebx,%ecx
+ shrl $3,%ebx
+ rorl $7,%ecx
+ xorl %edi,%esi
+ xorl %ecx,%ebx
+ rorl $17,%esi
+ addl 40(%esp),%ebx
+ shrl $10,%edi
+ addl 76(%esp),%ebx
+ movl %edx,%ecx
+ xorl %esi,%edi
+ movl 12(%esp),%esi
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 16(%esp),%edi
+ xorl %ecx,%edx
+ movl %ebx,40(%esp)
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,8(%esp)
+ xorl %ecx,%edx
+ addl 20(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 28(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,24(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 264347078(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ movl 48(%esp),%esi
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 4(%esp),%edx
+ addl %ecx,%ebp
+ movl 36(%esp),%ecx
+ movl %esi,%ebx
+ rorl $11,%esi
+ movl %ecx,%edi
+ rorl $2,%ecx
+ xorl %ebx,%esi
+ shrl $3,%ebx
+ rorl $7,%esi
+ xorl %edi,%ecx
+ xorl %esi,%ebx
+ rorl $17,%ecx
+ addl 44(%esp),%ebx
+ shrl $10,%edi
+ addl 80(%esp),%ebx
+ movl %edx,%esi
+ xorl %ecx,%edi
+ movl 8(%esp),%ecx
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 12(%esp),%edi
+ xorl %esi,%edx
+ movl %ebx,44(%esp)
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,4(%esp)
+ xorl %esi,%edx
+ addl 16(%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl 24(%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,20(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 604807628(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ movl 52(%esp),%ecx
+ rorl $2,%esi
+ addl %edx,%eax
+ addl (%esp),%edx
+ addl %esi,%eax
+ movl 40(%esp),%esi
+ movl %ecx,%ebx
+ rorl $11,%ecx
+ movl %esi,%edi
+ rorl $2,%esi
+ xorl %ebx,%ecx
+ shrl $3,%ebx
+ rorl $7,%ecx
+ xorl %edi,%esi
+ xorl %ecx,%ebx
+ rorl $17,%esi
+ addl 48(%esp),%ebx
+ shrl $10,%edi
+ addl 84(%esp),%ebx
+ movl %edx,%ecx
+ xorl %esi,%edi
+ movl 4(%esp),%esi
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 8(%esp),%edi
+ xorl %ecx,%edx
+ movl %ebx,48(%esp)
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,(%esp)
+ xorl %ecx,%edx
+ addl 12(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 20(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,16(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 770255983(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ movl 56(%esp),%esi
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 28(%esp),%edx
+ addl %ecx,%ebp
+ movl 44(%esp),%ecx
+ movl %esi,%ebx
+ rorl $11,%esi
+ movl %ecx,%edi
+ rorl $2,%ecx
+ xorl %ebx,%esi
+ shrl $3,%ebx
+ rorl $7,%esi
+ xorl %edi,%ecx
+ xorl %esi,%ebx
+ rorl $17,%ecx
+ addl 52(%esp),%ebx
+ shrl $10,%edi
+ addl 88(%esp),%ebx
+ movl %edx,%esi
+ xorl %ecx,%edi
+ movl (%esp),%ecx
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 4(%esp),%edi
+ xorl %esi,%edx
+ movl %ebx,52(%esp)
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,28(%esp)
+ xorl %esi,%edx
+ addl 8(%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl 16(%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,12(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 1249150122(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ movl 60(%esp),%ecx
+ rorl $2,%esi
+ addl %edx,%eax
+ addl 24(%esp),%edx
+ addl %esi,%eax
+ movl 48(%esp),%esi
+ movl %ecx,%ebx
+ rorl $11,%ecx
+ movl %esi,%edi
+ rorl $2,%esi
+ xorl %ebx,%ecx
+ shrl $3,%ebx
+ rorl $7,%ecx
+ xorl %edi,%esi
+ xorl %ecx,%ebx
+ rorl $17,%esi
+ addl 56(%esp),%ebx
+ shrl $10,%edi
+ addl 92(%esp),%ebx
+ movl %edx,%ecx
+ xorl %esi,%edi
+ movl 28(%esp),%esi
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl (%esp),%edi
+ xorl %ecx,%edx
+ movl %ebx,56(%esp)
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,24(%esp)
+ xorl %ecx,%edx
+ addl 4(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 12(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,8(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 1555081692(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ movl 64(%esp),%esi
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 20(%esp),%edx
+ addl %ecx,%ebp
+ movl 52(%esp),%ecx
+ movl %esi,%ebx
+ rorl $11,%esi
+ movl %ecx,%edi
+ rorl $2,%ecx
+ xorl %ebx,%esi
+ shrl $3,%ebx
+ rorl $7,%esi
+ xorl %edi,%ecx
+ xorl %esi,%ebx
+ rorl $17,%ecx
+ addl 60(%esp),%ebx
+ shrl $10,%edi
+ addl 32(%esp),%ebx
+ movl %edx,%esi
+ xorl %ecx,%edi
+ movl 24(%esp),%ecx
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 28(%esp),%edi
+ xorl %esi,%edx
+ movl %ebx,60(%esp)
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,20(%esp)
+ xorl %esi,%edx
+ addl (%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl 8(%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,4(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 1996064986(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ movl 68(%esp),%ecx
+ rorl $2,%esi
+ addl %edx,%eax
+ addl 16(%esp),%edx
+ addl %esi,%eax
+ movl 56(%esp),%esi
+ movl %ecx,%ebx
+ rorl $11,%ecx
+ movl %esi,%edi
+ rorl $2,%esi
+ xorl %ebx,%ecx
+ shrl $3,%ebx
+ rorl $7,%ecx
+ xorl %edi,%esi
+ xorl %ecx,%ebx
+ rorl $17,%esi
+ addl 64(%esp),%ebx
+ shrl $10,%edi
+ addl 36(%esp),%ebx
+ movl %edx,%ecx
+ xorl %esi,%edi
+ movl 20(%esp),%esi
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 24(%esp),%edi
+ xorl %ecx,%edx
+ movl %ebx,64(%esp)
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,16(%esp)
+ xorl %ecx,%edx
+ addl 28(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 4(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 2554220882(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ movl 72(%esp),%esi
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 12(%esp),%edx
+ addl %ecx,%ebp
+ movl 60(%esp),%ecx
+ movl %esi,%ebx
+ rorl $11,%esi
+ movl %ecx,%edi
+ rorl $2,%ecx
+ xorl %ebx,%esi
+ shrl $3,%ebx
+ rorl $7,%esi
+ xorl %edi,%ecx
+ xorl %esi,%ebx
+ rorl $17,%ecx
+ addl 68(%esp),%ebx
+ shrl $10,%edi
+ addl 40(%esp),%ebx
+ movl %edx,%esi
+ xorl %ecx,%edi
+ movl 16(%esp),%ecx
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 20(%esp),%edi
+ xorl %esi,%edx
+ movl %ebx,68(%esp)
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,12(%esp)
+ xorl %esi,%edx
+ addl 24(%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl (%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,28(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 2821834349(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ movl 76(%esp),%ecx
+ rorl $2,%esi
+ addl %edx,%eax
+ addl 8(%esp),%edx
+ addl %esi,%eax
+ movl 64(%esp),%esi
+ movl %ecx,%ebx
+ rorl $11,%ecx
+ movl %esi,%edi
+ rorl $2,%esi
+ xorl %ebx,%ecx
+ shrl $3,%ebx
+ rorl $7,%ecx
+ xorl %edi,%esi
+ xorl %ecx,%ebx
+ rorl $17,%esi
+ addl 72(%esp),%ebx
+ shrl $10,%edi
+ addl 44(%esp),%ebx
+ movl %edx,%ecx
+ xorl %esi,%edi
+ movl 12(%esp),%esi
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 16(%esp),%edi
+ xorl %ecx,%edx
+ movl %ebx,72(%esp)
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,8(%esp)
+ xorl %ecx,%edx
+ addl 20(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 28(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,24(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 2952996808(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ movl 80(%esp),%esi
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 4(%esp),%edx
+ addl %ecx,%ebp
+ movl 68(%esp),%ecx
+ movl %esi,%ebx
+ rorl $11,%esi
+ movl %ecx,%edi
+ rorl $2,%ecx
+ xorl %ebx,%esi
+ shrl $3,%ebx
+ rorl $7,%esi
+ xorl %edi,%ecx
+ xorl %esi,%ebx
+ rorl $17,%ecx
+ addl 76(%esp),%ebx
+ shrl $10,%edi
+ addl 48(%esp),%ebx
+ movl %edx,%esi
+ xorl %ecx,%edi
+ movl 8(%esp),%ecx
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 12(%esp),%edi
+ xorl %esi,%edx
+ movl %ebx,76(%esp)
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,4(%esp)
+ xorl %esi,%edx
+ addl 16(%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl 24(%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,20(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 3210313671(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ movl 84(%esp),%ecx
+ rorl $2,%esi
+ addl %edx,%eax
+ addl (%esp),%edx
+ addl %esi,%eax
+ movl 72(%esp),%esi
+ movl %ecx,%ebx
+ rorl $11,%ecx
+ movl %esi,%edi
+ rorl $2,%esi
+ xorl %ebx,%ecx
+ shrl $3,%ebx
+ rorl $7,%ecx
+ xorl %edi,%esi
+ xorl %ecx,%ebx
+ rorl $17,%esi
+ addl 80(%esp),%ebx
+ shrl $10,%edi
+ addl 52(%esp),%ebx
+ movl %edx,%ecx
+ xorl %esi,%edi
+ movl 4(%esp),%esi
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 8(%esp),%edi
+ xorl %ecx,%edx
+ movl %ebx,80(%esp)
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,(%esp)
+ xorl %ecx,%edx
+ addl 12(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 20(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,16(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 3336571891(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ movl 88(%esp),%esi
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 28(%esp),%edx
+ addl %ecx,%ebp
+ movl 76(%esp),%ecx
+ movl %esi,%ebx
+ rorl $11,%esi
+ movl %ecx,%edi
+ rorl $2,%ecx
+ xorl %ebx,%esi
+ shrl $3,%ebx
+ rorl $7,%esi
+ xorl %edi,%ecx
+ xorl %esi,%ebx
+ rorl $17,%ecx
+ addl 84(%esp),%ebx
+ shrl $10,%edi
+ addl 56(%esp),%ebx
+ movl %edx,%esi
+ xorl %ecx,%edi
+ movl (%esp),%ecx
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 4(%esp),%edi
+ xorl %esi,%edx
+ movl %ebx,84(%esp)
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,28(%esp)
+ xorl %esi,%edx
+ addl 8(%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl 16(%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,12(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 3584528711(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ movl 92(%esp),%ecx
+ rorl $2,%esi
+ addl %edx,%eax
+ addl 24(%esp),%edx
+ addl %esi,%eax
+ movl 80(%esp),%esi
+ movl %ecx,%ebx
+ rorl $11,%ecx
+ movl %esi,%edi
+ rorl $2,%esi
+ xorl %ebx,%ecx
+ shrl $3,%ebx
+ rorl $7,%ecx
+ xorl %edi,%esi
+ xorl %ecx,%ebx
+ rorl $17,%esi
+ addl 88(%esp),%ebx
+ shrl $10,%edi
+ addl 60(%esp),%ebx
+ movl %edx,%ecx
+ xorl %esi,%edi
+ movl 28(%esp),%esi
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl (%esp),%edi
+ xorl %ecx,%edx
+ movl %ebx,88(%esp)
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,24(%esp)
+ xorl %ecx,%edx
+ addl 4(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 12(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,8(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 113926993(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ movl 32(%esp),%esi
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 20(%esp),%edx
+ addl %ecx,%ebp
+ movl 84(%esp),%ecx
+ movl %esi,%ebx
+ rorl $11,%esi
+ movl %ecx,%edi
+ rorl $2,%ecx
+ xorl %ebx,%esi
+ shrl $3,%ebx
+ rorl $7,%esi
+ xorl %edi,%ecx
+ xorl %esi,%ebx
+ rorl $17,%ecx
+ addl 92(%esp),%ebx
+ shrl $10,%edi
+ addl 64(%esp),%ebx
+ movl %edx,%esi
+ xorl %ecx,%edi
+ movl 24(%esp),%ecx
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 28(%esp),%edi
+ xorl %esi,%edx
+ movl %ebx,92(%esp)
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,20(%esp)
+ xorl %esi,%edx
+ addl (%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl 8(%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,4(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 338241895(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ movl 36(%esp),%ecx
+ rorl $2,%esi
+ addl %edx,%eax
+ addl 16(%esp),%edx
+ addl %esi,%eax
+ movl 88(%esp),%esi
+ movl %ecx,%ebx
+ rorl $11,%ecx
+ movl %esi,%edi
+ rorl $2,%esi
+ xorl %ebx,%ecx
+ shrl $3,%ebx
+ rorl $7,%ecx
+ xorl %edi,%esi
+ xorl %ecx,%ebx
+ rorl $17,%esi
+ addl 32(%esp),%ebx
+ shrl $10,%edi
+ addl 68(%esp),%ebx
+ movl %edx,%ecx
+ xorl %esi,%edi
+ movl 20(%esp),%esi
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 24(%esp),%edi
+ xorl %ecx,%edx
+ movl %ebx,32(%esp)
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,16(%esp)
+ xorl %ecx,%edx
+ addl 28(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 4(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 666307205(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ movl 40(%esp),%esi
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 12(%esp),%edx
+ addl %ecx,%ebp
+ movl 92(%esp),%ecx
+ movl %esi,%ebx
+ rorl $11,%esi
+ movl %ecx,%edi
+ rorl $2,%ecx
+ xorl %ebx,%esi
+ shrl $3,%ebx
+ rorl $7,%esi
+ xorl %edi,%ecx
+ xorl %esi,%ebx
+ rorl $17,%ecx
+ addl 36(%esp),%ebx
+ shrl $10,%edi
+ addl 72(%esp),%ebx
+ movl %edx,%esi
+ xorl %ecx,%edi
+ movl 16(%esp),%ecx
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 20(%esp),%edi
+ xorl %esi,%edx
+ movl %ebx,36(%esp)
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,12(%esp)
+ xorl %esi,%edx
+ addl 24(%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl (%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,28(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 773529912(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ movl 44(%esp),%ecx
+ rorl $2,%esi
+ addl %edx,%eax
+ addl 8(%esp),%edx
+ addl %esi,%eax
+ movl 32(%esp),%esi
+ movl %ecx,%ebx
+ rorl $11,%ecx
+ movl %esi,%edi
+ rorl $2,%esi
+ xorl %ebx,%ecx
+ shrl $3,%ebx
+ rorl $7,%ecx
+ xorl %edi,%esi
+ xorl %ecx,%ebx
+ rorl $17,%esi
+ addl 40(%esp),%ebx
+ shrl $10,%edi
+ addl 76(%esp),%ebx
+ movl %edx,%ecx
+ xorl %esi,%edi
+ movl 12(%esp),%esi
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 16(%esp),%edi
+ xorl %ecx,%edx
+ movl %ebx,40(%esp)
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,8(%esp)
+ xorl %ecx,%edx
+ addl 20(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 28(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,24(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 1294757372(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ movl 48(%esp),%esi
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 4(%esp),%edx
+ addl %ecx,%ebp
+ movl 36(%esp),%ecx
+ movl %esi,%ebx
+ rorl $11,%esi
+ movl %ecx,%edi
+ rorl $2,%ecx
+ xorl %ebx,%esi
+ shrl $3,%ebx
+ rorl $7,%esi
+ xorl %edi,%ecx
+ xorl %esi,%ebx
+ rorl $17,%ecx
+ addl 44(%esp),%ebx
+ shrl $10,%edi
+ addl 80(%esp),%ebx
+ movl %edx,%esi
+ xorl %ecx,%edi
+ movl 8(%esp),%ecx
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 12(%esp),%edi
+ xorl %esi,%edx
+ movl %ebx,44(%esp)
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,4(%esp)
+ xorl %esi,%edx
+ addl 16(%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl 24(%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,20(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 1396182291(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ movl 52(%esp),%ecx
+ rorl $2,%esi
+ addl %edx,%eax
+ addl (%esp),%edx
+ addl %esi,%eax
+ movl 40(%esp),%esi
+ movl %ecx,%ebx
+ rorl $11,%ecx
+ movl %esi,%edi
+ rorl $2,%esi
+ xorl %ebx,%ecx
+ shrl $3,%ebx
+ rorl $7,%ecx
+ xorl %edi,%esi
+ xorl %ecx,%ebx
+ rorl $17,%esi
+ addl 48(%esp),%ebx
+ shrl $10,%edi
+ addl 84(%esp),%ebx
+ movl %edx,%ecx
+ xorl %esi,%edi
+ movl 4(%esp),%esi
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 8(%esp),%edi
+ xorl %ecx,%edx
+ movl %ebx,48(%esp)
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,(%esp)
+ xorl %ecx,%edx
+ addl 12(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 20(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,16(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 1695183700(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ movl 56(%esp),%esi
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 28(%esp),%edx
+ addl %ecx,%ebp
+ movl 44(%esp),%ecx
+ movl %esi,%ebx
+ rorl $11,%esi
+ movl %ecx,%edi
+ rorl $2,%ecx
+ xorl %ebx,%esi
+ shrl $3,%ebx
+ rorl $7,%esi
+ xorl %edi,%ecx
+ xorl %esi,%ebx
+ rorl $17,%ecx
+ addl 52(%esp),%ebx
+ shrl $10,%edi
+ addl 88(%esp),%ebx
+ movl %edx,%esi
+ xorl %ecx,%edi
+ movl (%esp),%ecx
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 4(%esp),%edi
+ xorl %esi,%edx
+ movl %ebx,52(%esp)
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,28(%esp)
+ xorl %esi,%edx
+ addl 8(%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl 16(%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,12(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 1986661051(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ movl 60(%esp),%ecx
+ rorl $2,%esi
+ addl %edx,%eax
+ addl 24(%esp),%edx
+ addl %esi,%eax
+ movl 48(%esp),%esi
+ movl %ecx,%ebx
+ rorl $11,%ecx
+ movl %esi,%edi
+ rorl $2,%esi
+ xorl %ebx,%ecx
+ shrl $3,%ebx
+ rorl $7,%ecx
+ xorl %edi,%esi
+ xorl %ecx,%ebx
+ rorl $17,%esi
+ addl 56(%esp),%ebx
+ shrl $10,%edi
+ addl 92(%esp),%ebx
+ movl %edx,%ecx
+ xorl %esi,%edi
+ movl 28(%esp),%esi
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl (%esp),%edi
+ xorl %ecx,%edx
+ movl %ebx,56(%esp)
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,24(%esp)
+ xorl %ecx,%edx
+ addl 4(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 12(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,8(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 2177026350(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ movl 64(%esp),%esi
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 20(%esp),%edx
+ addl %ecx,%ebp
+ movl 52(%esp),%ecx
+ movl %esi,%ebx
+ rorl $11,%esi
+ movl %ecx,%edi
+ rorl $2,%ecx
+ xorl %ebx,%esi
+ shrl $3,%ebx
+ rorl $7,%esi
+ xorl %edi,%ecx
+ xorl %esi,%ebx
+ rorl $17,%ecx
+ addl 60(%esp),%ebx
+ shrl $10,%edi
+ addl 32(%esp),%ebx
+ movl %edx,%esi
+ xorl %ecx,%edi
+ movl 24(%esp),%ecx
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 28(%esp),%edi
+ xorl %esi,%edx
+ movl %ebx,60(%esp)
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,20(%esp)
+ xorl %esi,%edx
+ addl (%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl 8(%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,4(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 2456956037(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ movl 68(%esp),%ecx
+ rorl $2,%esi
+ addl %edx,%eax
+ addl 16(%esp),%edx
+ addl %esi,%eax
+ movl 56(%esp),%esi
+ movl %ecx,%ebx
+ rorl $11,%ecx
+ movl %esi,%edi
+ rorl $2,%esi
+ xorl %ebx,%ecx
+ shrl $3,%ebx
+ rorl $7,%ecx
+ xorl %edi,%esi
+ xorl %ecx,%ebx
+ rorl $17,%esi
+ addl 64(%esp),%ebx
+ shrl $10,%edi
+ addl 36(%esp),%ebx
+ movl %edx,%ecx
+ xorl %esi,%edi
+ movl 20(%esp),%esi
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 24(%esp),%edi
+ xorl %ecx,%edx
+ movl %ebx,64(%esp)
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,16(%esp)
+ xorl %ecx,%edx
+ addl 28(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 4(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 2730485921(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ movl 72(%esp),%esi
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 12(%esp),%edx
+ addl %ecx,%ebp
+ movl 60(%esp),%ecx
+ movl %esi,%ebx
+ rorl $11,%esi
+ movl %ecx,%edi
+ rorl $2,%ecx
+ xorl %ebx,%esi
+ shrl $3,%ebx
+ rorl $7,%esi
+ xorl %edi,%ecx
+ xorl %esi,%ebx
+ rorl $17,%ecx
+ addl 68(%esp),%ebx
+ shrl $10,%edi
+ addl 40(%esp),%ebx
+ movl %edx,%esi
+ xorl %ecx,%edi
+ movl 16(%esp),%ecx
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 20(%esp),%edi
+ xorl %esi,%edx
+ movl %ebx,68(%esp)
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,12(%esp)
+ xorl %esi,%edx
+ addl 24(%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl (%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,28(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 2820302411(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ movl 76(%esp),%ecx
+ rorl $2,%esi
+ addl %edx,%eax
+ addl 8(%esp),%edx
+ addl %esi,%eax
+ movl 64(%esp),%esi
+ movl %ecx,%ebx
+ rorl $11,%ecx
+ movl %esi,%edi
+ rorl $2,%esi
+ xorl %ebx,%ecx
+ shrl $3,%ebx
+ rorl $7,%ecx
+ xorl %edi,%esi
+ xorl %ecx,%ebx
+ rorl $17,%esi
+ addl 72(%esp),%ebx
+ shrl $10,%edi
+ addl 44(%esp),%ebx
+ movl %edx,%ecx
+ xorl %esi,%edi
+ movl 12(%esp),%esi
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 16(%esp),%edi
+ xorl %ecx,%edx
+ movl %ebx,72(%esp)
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,8(%esp)
+ xorl %ecx,%edx
+ addl 20(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 28(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,24(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 3259730800(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ movl 80(%esp),%esi
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 4(%esp),%edx
+ addl %ecx,%ebp
+ movl 68(%esp),%ecx
+ movl %esi,%ebx
+ rorl $11,%esi
+ movl %ecx,%edi
+ rorl $2,%ecx
+ xorl %ebx,%esi
+ shrl $3,%ebx
+ rorl $7,%esi
+ xorl %edi,%ecx
+ xorl %esi,%ebx
+ rorl $17,%ecx
+ addl 76(%esp),%ebx
+ shrl $10,%edi
+ addl 48(%esp),%ebx
+ movl %edx,%esi
+ xorl %ecx,%edi
+ movl 8(%esp),%ecx
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 12(%esp),%edi
+ xorl %esi,%edx
+ movl %ebx,76(%esp)
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,4(%esp)
+ xorl %esi,%edx
+ addl 16(%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl 24(%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,20(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 3345764771(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ movl 84(%esp),%ecx
+ rorl $2,%esi
+ addl %edx,%eax
+ addl (%esp),%edx
+ addl %esi,%eax
+ movl 72(%esp),%esi
+ movl %ecx,%ebx
+ rorl $11,%ecx
+ movl %esi,%edi
+ rorl $2,%esi
+ xorl %ebx,%ecx
+ shrl $3,%ebx
+ rorl $7,%ecx
+ xorl %edi,%esi
+ xorl %ecx,%ebx
+ rorl $17,%esi
+ addl 80(%esp),%ebx
+ shrl $10,%edi
+ addl 52(%esp),%ebx
+ movl %edx,%ecx
+ xorl %esi,%edi
+ movl 4(%esp),%esi
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 8(%esp),%edi
+ xorl %ecx,%edx
+ movl %ebx,80(%esp)
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,(%esp)
+ xorl %ecx,%edx
+ addl 12(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 20(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,16(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 3516065817(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ movl 88(%esp),%esi
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 28(%esp),%edx
+ addl %ecx,%ebp
+ movl 76(%esp),%ecx
+ movl %esi,%ebx
+ rorl $11,%esi
+ movl %ecx,%edi
+ rorl $2,%ecx
+ xorl %ebx,%esi
+ shrl $3,%ebx
+ rorl $7,%esi
+ xorl %edi,%ecx
+ xorl %esi,%ebx
+ rorl $17,%ecx
+ addl 84(%esp),%ebx
+ shrl $10,%edi
+ addl 56(%esp),%ebx
+ movl %edx,%esi
+ xorl %ecx,%edi
+ movl (%esp),%ecx
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 4(%esp),%edi
+ xorl %esi,%edx
+ movl %ebx,84(%esp)
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,28(%esp)
+ xorl %esi,%edx
+ addl 8(%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl 16(%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,12(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 3600352804(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ movl 92(%esp),%ecx
+ rorl $2,%esi
+ addl %edx,%eax
+ addl 24(%esp),%edx
+ addl %esi,%eax
+ movl 80(%esp),%esi
+ movl %ecx,%ebx
+ rorl $11,%ecx
+ movl %esi,%edi
+ rorl $2,%esi
+ xorl %ebx,%ecx
+ shrl $3,%ebx
+ rorl $7,%ecx
+ xorl %edi,%esi
+ xorl %ecx,%ebx
+ rorl $17,%esi
+ addl 88(%esp),%ebx
+ shrl $10,%edi
+ addl 60(%esp),%ebx
+ movl %edx,%ecx
+ xorl %esi,%edi
+ movl 28(%esp),%esi
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl (%esp),%edi
+ xorl %ecx,%edx
+ movl %ebx,88(%esp)
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,24(%esp)
+ xorl %ecx,%edx
+ addl 4(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 12(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,8(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 4094571909(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ movl 32(%esp),%esi
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 20(%esp),%edx
+ addl %ecx,%ebp
+ movl 84(%esp),%ecx
+ movl %esi,%ebx
+ rorl $11,%esi
+ movl %ecx,%edi
+ rorl $2,%ecx
+ xorl %ebx,%esi
+ shrl $3,%ebx
+ rorl $7,%esi
+ xorl %edi,%ecx
+ xorl %esi,%ebx
+ rorl $17,%ecx
+ addl 92(%esp),%ebx
+ shrl $10,%edi
+ addl 64(%esp),%ebx
+ movl %edx,%esi
+ xorl %ecx,%edi
+ movl 24(%esp),%ecx
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 28(%esp),%edi
+ xorl %esi,%edx
+ movl %ebx,92(%esp)
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,20(%esp)
+ xorl %esi,%edx
+ addl (%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl 8(%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,4(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 275423344(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ movl 36(%esp),%ecx
+ rorl $2,%esi
+ addl %edx,%eax
+ addl 16(%esp),%edx
+ addl %esi,%eax
+ movl 88(%esp),%esi
+ movl %ecx,%ebx
+ rorl $11,%ecx
+ movl %esi,%edi
+ rorl $2,%esi
+ xorl %ebx,%ecx
+ shrl $3,%ebx
+ rorl $7,%ecx
+ xorl %edi,%esi
+ xorl %ecx,%ebx
+ rorl $17,%esi
+ addl 32(%esp),%ebx
+ shrl $10,%edi
+ addl 68(%esp),%ebx
+ movl %edx,%ecx
+ xorl %esi,%edi
+ movl 20(%esp),%esi
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 24(%esp),%edi
+ xorl %ecx,%edx
+ movl %ebx,32(%esp)
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,16(%esp)
+ xorl %ecx,%edx
+ addl 28(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 4(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 430227734(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ movl 40(%esp),%esi
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 12(%esp),%edx
+ addl %ecx,%ebp
+ movl 92(%esp),%ecx
+ movl %esi,%ebx
+ rorl $11,%esi
+ movl %ecx,%edi
+ rorl $2,%ecx
+ xorl %ebx,%esi
+ shrl $3,%ebx
+ rorl $7,%esi
+ xorl %edi,%ecx
+ xorl %esi,%ebx
+ rorl $17,%ecx
+ addl 36(%esp),%ebx
+ shrl $10,%edi
+ addl 72(%esp),%ebx
+ movl %edx,%esi
+ xorl %ecx,%edi
+ movl 16(%esp),%ecx
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 20(%esp),%edi
+ xorl %esi,%edx
+ movl %ebx,36(%esp)
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,12(%esp)
+ xorl %esi,%edx
+ addl 24(%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl (%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,28(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 506948616(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ movl 44(%esp),%ecx
+ rorl $2,%esi
+ addl %edx,%eax
+ addl 8(%esp),%edx
+ addl %esi,%eax
+ movl 32(%esp),%esi
+ movl %ecx,%ebx
+ rorl $11,%ecx
+ movl %esi,%edi
+ rorl $2,%esi
+ xorl %ebx,%ecx
+ shrl $3,%ebx
+ rorl $7,%ecx
+ xorl %edi,%esi
+ xorl %ecx,%ebx
+ rorl $17,%esi
+ addl 40(%esp),%ebx
+ shrl $10,%edi
+ addl 76(%esp),%ebx
+ movl %edx,%ecx
+ xorl %esi,%edi
+ movl 12(%esp),%esi
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 16(%esp),%edi
+ xorl %ecx,%edx
+ movl %ebx,40(%esp)
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,8(%esp)
+ xorl %ecx,%edx
+ addl 20(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 28(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,24(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 659060556(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ movl 48(%esp),%esi
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 4(%esp),%edx
+ addl %ecx,%ebp
+ movl 36(%esp),%ecx
+ movl %esi,%ebx
+ rorl $11,%esi
+ movl %ecx,%edi
+ rorl $2,%ecx
+ xorl %ebx,%esi
+ shrl $3,%ebx
+ rorl $7,%esi
+ xorl %edi,%ecx
+ xorl %esi,%ebx
+ rorl $17,%ecx
+ addl 44(%esp),%ebx
+ shrl $10,%edi
+ addl 80(%esp),%ebx
+ movl %edx,%esi
+ xorl %ecx,%edi
+ movl 8(%esp),%ecx
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 12(%esp),%edi
+ xorl %esi,%edx
+ movl %ebx,44(%esp)
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,4(%esp)
+ xorl %esi,%edx
+ addl 16(%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl 24(%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,20(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 883997877(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ movl 52(%esp),%ecx
+ rorl $2,%esi
+ addl %edx,%eax
+ addl (%esp),%edx
+ addl %esi,%eax
+ movl 40(%esp),%esi
+ movl %ecx,%ebx
+ rorl $11,%ecx
+ movl %esi,%edi
+ rorl $2,%esi
+ xorl %ebx,%ecx
+ shrl $3,%ebx
+ rorl $7,%ecx
+ xorl %edi,%esi
+ xorl %ecx,%ebx
+ rorl $17,%esi
+ addl 48(%esp),%ebx
+ shrl $10,%edi
+ addl 84(%esp),%ebx
+ movl %edx,%ecx
+ xorl %esi,%edi
+ movl 4(%esp),%esi
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 8(%esp),%edi
+ xorl %ecx,%edx
+ movl %ebx,48(%esp)
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,(%esp)
+ xorl %ecx,%edx
+ addl 12(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 20(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,16(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 958139571(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ movl 56(%esp),%esi
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 28(%esp),%edx
+ addl %ecx,%ebp
+ movl 44(%esp),%ecx
+ movl %esi,%ebx
+ rorl $11,%esi
+ movl %ecx,%edi
+ rorl $2,%ecx
+ xorl %ebx,%esi
+ shrl $3,%ebx
+ rorl $7,%esi
+ xorl %edi,%ecx
+ xorl %esi,%ebx
+ rorl $17,%ecx
+ addl 52(%esp),%ebx
+ shrl $10,%edi
+ addl 88(%esp),%ebx
+ movl %edx,%esi
+ xorl %ecx,%edi
+ movl (%esp),%ecx
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 4(%esp),%edi
+ xorl %esi,%edx
+ movl %ebx,52(%esp)
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,28(%esp)
+ xorl %esi,%edx
+ addl 8(%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl 16(%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,12(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 1322822218(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ movl 60(%esp),%ecx
+ rorl $2,%esi
+ addl %edx,%eax
+ addl 24(%esp),%edx
+ addl %esi,%eax
+ movl 48(%esp),%esi
+ movl %ecx,%ebx
+ rorl $11,%ecx
+ movl %esi,%edi
+ rorl $2,%esi
+ xorl %ebx,%ecx
+ shrl $3,%ebx
+ rorl $7,%ecx
+ xorl %edi,%esi
+ xorl %ecx,%ebx
+ rorl $17,%esi
+ addl 56(%esp),%ebx
+ shrl $10,%edi
+ addl 92(%esp),%ebx
+ movl %edx,%ecx
+ xorl %esi,%edi
+ movl 28(%esp),%esi
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl (%esp),%edi
+ xorl %ecx,%edx
+ movl %ebx,56(%esp)
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,24(%esp)
+ xorl %ecx,%edx
+ addl 4(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 12(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,8(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 1537002063(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ movl 64(%esp),%esi
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 20(%esp),%edx
+ addl %ecx,%ebp
+ movl 52(%esp),%ecx
+ movl %esi,%ebx
+ rorl $11,%esi
+ movl %ecx,%edi
+ rorl $2,%ecx
+ xorl %ebx,%esi
+ shrl $3,%ebx
+ rorl $7,%esi
+ xorl %edi,%ecx
+ xorl %esi,%ebx
+ rorl $17,%ecx
+ addl 60(%esp),%ebx
+ shrl $10,%edi
+ addl 32(%esp),%ebx
+ movl %edx,%esi
+ xorl %ecx,%edi
+ movl 24(%esp),%ecx
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 28(%esp),%edi
+ xorl %esi,%edx
+ movl %ebx,60(%esp)
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,20(%esp)
+ xorl %esi,%edx
+ addl (%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl 8(%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,4(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 1747873779(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ movl 68(%esp),%ecx
+ rorl $2,%esi
+ addl %edx,%eax
+ addl 16(%esp),%edx
+ addl %esi,%eax
+ movl 56(%esp),%esi
+ movl %ecx,%ebx
+ rorl $11,%ecx
+ movl %esi,%edi
+ rorl $2,%esi
+ xorl %ebx,%ecx
+ shrl $3,%ebx
+ rorl $7,%ecx
+ xorl %edi,%esi
+ xorl %ecx,%ebx
+ rorl $17,%esi
+ addl 64(%esp),%ebx
+ shrl $10,%edi
+ addl 36(%esp),%ebx
+ movl %edx,%ecx
+ xorl %esi,%edi
+ movl 20(%esp),%esi
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 24(%esp),%edi
+ xorl %ecx,%edx
+ movl %ebx,64(%esp)
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,16(%esp)
+ xorl %ecx,%edx
+ addl 28(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 4(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 1955562222(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ movl 72(%esp),%esi
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 12(%esp),%edx
+ addl %ecx,%ebp
+ movl 60(%esp),%ecx
+ movl %esi,%ebx
+ rorl $11,%esi
+ movl %ecx,%edi
+ rorl $2,%ecx
+ xorl %ebx,%esi
+ shrl $3,%ebx
+ rorl $7,%esi
+ xorl %edi,%ecx
+ xorl %esi,%ebx
+ rorl $17,%ecx
+ addl 68(%esp),%ebx
+ shrl $10,%edi
+ addl 40(%esp),%ebx
+ movl %edx,%esi
+ xorl %ecx,%edi
+ movl 16(%esp),%ecx
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 20(%esp),%edi
+ xorl %esi,%edx
+ movl %ebx,68(%esp)
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,12(%esp)
+ xorl %esi,%edx
+ addl 24(%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl (%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,28(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 2024104815(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ movl 76(%esp),%ecx
+ rorl $2,%esi
+ addl %edx,%eax
+ addl 8(%esp),%edx
+ addl %esi,%eax
+ movl 64(%esp),%esi
+ movl %ecx,%ebx
+ rorl $11,%ecx
+ movl %esi,%edi
+ rorl $2,%esi
+ xorl %ebx,%ecx
+ shrl $3,%ebx
+ rorl $7,%ecx
+ xorl %edi,%esi
+ xorl %ecx,%ebx
+ rorl $17,%esi
+ addl 72(%esp),%ebx
+ shrl $10,%edi
+ addl 44(%esp),%ebx
+ movl %edx,%ecx
+ xorl %esi,%edi
+ movl 12(%esp),%esi
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 16(%esp),%edi
+ xorl %ecx,%edx
+ movl %ebx,72(%esp)
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,8(%esp)
+ xorl %ecx,%edx
+ addl 20(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 28(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,24(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 2227730452(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ movl 80(%esp),%esi
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 4(%esp),%edx
+ addl %ecx,%ebp
+ movl 68(%esp),%ecx
+ movl %esi,%ebx
+ rorl $11,%esi
+ movl %ecx,%edi
+ rorl $2,%ecx
+ xorl %ebx,%esi
+ shrl $3,%ebx
+ rorl $7,%esi
+ xorl %edi,%ecx
+ xorl %esi,%ebx
+ rorl $17,%ecx
+ addl 76(%esp),%ebx
+ shrl $10,%edi
+ addl 48(%esp),%ebx
+ movl %edx,%esi
+ xorl %ecx,%edi
+ movl 8(%esp),%ecx
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 12(%esp),%edi
+ xorl %esi,%edx
+ movl %ebx,76(%esp)
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,4(%esp)
+ xorl %esi,%edx
+ addl 16(%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl 24(%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,20(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 2361852424(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ movl 84(%esp),%ecx
+ rorl $2,%esi
+ addl %edx,%eax
+ addl (%esp),%edx
+ addl %esi,%eax
+ movl 72(%esp),%esi
+ movl %ecx,%ebx
+ rorl $11,%ecx
+ movl %esi,%edi
+ rorl $2,%esi
+ xorl %ebx,%ecx
+ shrl $3,%ebx
+ rorl $7,%ecx
+ xorl %edi,%esi
+ xorl %ecx,%ebx
+ rorl $17,%esi
+ addl 80(%esp),%ebx
+ shrl $10,%edi
+ addl 52(%esp),%ebx
+ movl %edx,%ecx
+ xorl %esi,%edi
+ movl 4(%esp),%esi
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 8(%esp),%edi
+ xorl %ecx,%edx
+ movl %ebx,80(%esp)
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,(%esp)
+ xorl %ecx,%edx
+ addl 12(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 20(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,16(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 2428436474(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ movl 88(%esp),%esi
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 28(%esp),%edx
+ addl %ecx,%ebp
+ movl 76(%esp),%ecx
+ movl %esi,%ebx
+ rorl $11,%esi
+ movl %ecx,%edi
+ rorl $2,%ecx
+ xorl %ebx,%esi
+ shrl $3,%ebx
+ rorl $7,%esi
+ xorl %edi,%ecx
+ xorl %esi,%ebx
+ rorl $17,%ecx
+ addl 84(%esp),%ebx
+ shrl $10,%edi
+ addl 56(%esp),%ebx
+ movl %edx,%esi
+ xorl %ecx,%edi
+ movl (%esp),%ecx
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 4(%esp),%edi
+ xorl %esi,%edx
+ movl %ebx,84(%esp)
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,28(%esp)
+ xorl %esi,%edx
+ addl 8(%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl 16(%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,12(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 2756734187(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ movl 92(%esp),%ecx
+ rorl $2,%esi
+ addl %edx,%eax
+ addl 24(%esp),%edx
+ addl %esi,%eax
+ movl 80(%esp),%esi
+ movl %ecx,%ebx
+ rorl $11,%ecx
+ movl %esi,%edi
+ rorl $2,%esi
+ xorl %ebx,%ecx
+ shrl $3,%ebx
+ rorl $7,%ecx
+ xorl %edi,%esi
+ xorl %ecx,%ebx
+ rorl $17,%esi
+ addl 88(%esp),%ebx
+ shrl $10,%edi
+ addl 60(%esp),%ebx
+ movl %edx,%ecx
+ xorl %esi,%edi
+ movl 28(%esp),%esi
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl (%esp),%edi
+ xorl %ecx,%edx
+ xorl %edi,%esi
+ rorl $5,%edx
+ andl %ecx,%esi
+ movl %ecx,24(%esp)
+ xorl %ecx,%edx
+ addl 4(%esp),%ebx
+ xorl %esi,%edi
+ rorl $6,%edx
+ movl %eax,%ecx
+ addl %edi,%ebx
+ rorl $9,%ecx
+ movl %eax,%esi
+ movl 12(%esp),%edi
+ xorl %eax,%ecx
+ movl %eax,8(%esp)
+ xorl %edi,%eax
+ rorl $11,%ecx
+ andl %eax,%ebp
+ leal 3204031479(%ebx,%edx,1),%edx
+ xorl %esi,%ecx
+ xorl %edi,%ebp
+ movl 32(%esp),%esi
+ rorl $2,%ecx
+ addl %edx,%ebp
+ addl 20(%esp),%edx
+ addl %ecx,%ebp
+ movl 84(%esp),%ecx
+ movl %esi,%ebx
+ rorl $11,%esi
+ movl %ecx,%edi
+ rorl $2,%ecx
+ xorl %ebx,%esi
+ shrl $3,%ebx
+ rorl $7,%esi
+ xorl %edi,%ecx
+ xorl %esi,%ebx
+ rorl $17,%ecx
+ addl 92(%esp),%ebx
+ shrl $10,%edi
+ addl 64(%esp),%ebx
+ movl %edx,%esi
+ xorl %ecx,%edi
+ movl 24(%esp),%ecx
+ rorl $14,%edx
+ addl %edi,%ebx
+ movl 28(%esp),%edi
+ xorl %esi,%edx
+ xorl %edi,%ecx
+ rorl $5,%edx
+ andl %esi,%ecx
+ movl %esi,20(%esp)
+ xorl %esi,%edx
+ addl (%esp),%ebx
+ xorl %ecx,%edi
+ rorl $6,%edx
+ movl %ebp,%esi
+ addl %edi,%ebx
+ rorl $9,%esi
+ movl %ebp,%ecx
+ movl 8(%esp),%edi
+ xorl %ebp,%esi
+ movl %ebp,4(%esp)
+ xorl %edi,%ebp
+ rorl $11,%esi
+ andl %ebp,%eax
+ leal 3329325298(%ebx,%edx,1),%edx
+ xorl %ecx,%esi
+ xorl %edi,%eax
+ rorl $2,%esi
+ addl %edx,%eax
+ addl 16(%esp),%edx
+ addl %esi,%eax
+ movl 96(%esp),%esi
+ xorl %edi,%ebp
+ movl 12(%esp),%ecx
+ addl (%esi),%eax
+ addl 4(%esi),%ebp
+ addl 8(%esi),%edi
+ addl 12(%esi),%ecx
+ movl %eax,(%esi)
+ movl %ebp,4(%esi)
+ movl %edi,8(%esi)
+ movl %ecx,12(%esi)
+ movl %ebp,4(%esp)
+ xorl %edi,%ebp
+ movl %edi,8(%esp)
+ movl %ecx,12(%esp)
+ movl 20(%esp),%edi
+ movl 24(%esp),%ebx
+ movl 28(%esp),%ecx
+ addl 16(%esi),%edx
+ addl 20(%esi),%edi
+ addl 24(%esi),%ebx
+ addl 28(%esi),%ecx
+ movl %edx,16(%esi)
+ movl %edi,20(%esi)
+ movl %ebx,24(%esi)
+ movl %ecx,28(%esi)
+ movl %edi,20(%esp)
+ movl 100(%esp),%edi
+ movl %ebx,24(%esp)
+ movl %ecx,28(%esp)
+ cmpl 104(%esp),%edi
+ jb L009grand_loop
+ movl 108(%esp),%esp
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+#endif
diff --git a/mac-x86/crypto/sha/sha512-586.S b/mac-x86/crypto/sha/sha512-586.S
new file mode 100644
index 0000000..99dbc31
--- /dev/null
+++ b/mac-x86/crypto/sha/sha512-586.S
@@ -0,0 +1,566 @@
+#if defined(__i386__)
+.file "sha512-586.S"
+.text
+.globl _sha512_block_data_order
+.private_extern _sha512_block_data_order
+.align 4
+_sha512_block_data_order:
+L_sha512_block_data_order_begin:
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ movl 20(%esp),%esi
+ movl 24(%esp),%edi
+ movl 28(%esp),%eax
+ movl %esp,%ebx
+ call L000pic_point
+L000pic_point:
+ popl %ebp
+ leal L001K512-L000pic_point(%ebp),%ebp
+ subl $16,%esp
+ andl $-64,%esp
+ shll $7,%eax
+ addl %edi,%eax
+ movl %esi,(%esp)
+ movl %edi,4(%esp)
+ movl %eax,8(%esp)
+ movl %ebx,12(%esp)
+.align 4,0x90
+L002loop_x86:
+ movl (%edi),%eax
+ movl 4(%edi),%ebx
+ movl 8(%edi),%ecx
+ movl 12(%edi),%edx
+ bswap %eax
+ bswap %ebx
+ bswap %ecx
+ bswap %edx
+ pushl %eax
+ pushl %ebx
+ pushl %ecx
+ pushl %edx
+ movl 16(%edi),%eax
+ movl 20(%edi),%ebx
+ movl 24(%edi),%ecx
+ movl 28(%edi),%edx
+ bswap %eax
+ bswap %ebx
+ bswap %ecx
+ bswap %edx
+ pushl %eax
+ pushl %ebx
+ pushl %ecx
+ pushl %edx
+ movl 32(%edi),%eax
+ movl 36(%edi),%ebx
+ movl 40(%edi),%ecx
+ movl 44(%edi),%edx
+ bswap %eax
+ bswap %ebx
+ bswap %ecx
+ bswap %edx
+ pushl %eax
+ pushl %ebx
+ pushl %ecx
+ pushl %edx
+ movl 48(%edi),%eax
+ movl 52(%edi),%ebx
+ movl 56(%edi),%ecx
+ movl 60(%edi),%edx
+ bswap %eax
+ bswap %ebx
+ bswap %ecx
+ bswap %edx
+ pushl %eax
+ pushl %ebx
+ pushl %ecx
+ pushl %edx
+ movl 64(%edi),%eax
+ movl 68(%edi),%ebx
+ movl 72(%edi),%ecx
+ movl 76(%edi),%edx
+ bswap %eax
+ bswap %ebx
+ bswap %ecx
+ bswap %edx
+ pushl %eax
+ pushl %ebx
+ pushl %ecx
+ pushl %edx
+ movl 80(%edi),%eax
+ movl 84(%edi),%ebx
+ movl 88(%edi),%ecx
+ movl 92(%edi),%edx
+ bswap %eax
+ bswap %ebx
+ bswap %ecx
+ bswap %edx
+ pushl %eax
+ pushl %ebx
+ pushl %ecx
+ pushl %edx
+ movl 96(%edi),%eax
+ movl 100(%edi),%ebx
+ movl 104(%edi),%ecx
+ movl 108(%edi),%edx
+ bswap %eax
+ bswap %ebx
+ bswap %ecx
+ bswap %edx
+ pushl %eax
+ pushl %ebx
+ pushl %ecx
+ pushl %edx
+ movl 112(%edi),%eax
+ movl 116(%edi),%ebx
+ movl 120(%edi),%ecx
+ movl 124(%edi),%edx
+ bswap %eax
+ bswap %ebx
+ bswap %ecx
+ bswap %edx
+ pushl %eax
+ pushl %ebx
+ pushl %ecx
+ pushl %edx
+ addl $128,%edi
+ subl $72,%esp
+ movl %edi,204(%esp)
+ leal 8(%esp),%edi
+ movl $16,%ecx
+.long 2784229001
+.align 4,0x90
+L00300_15_x86:
+ movl 40(%esp),%ecx
+ movl 44(%esp),%edx
+ movl %ecx,%esi
+ shrl $9,%ecx
+ movl %edx,%edi
+ shrl $9,%edx
+ movl %ecx,%ebx
+ shll $14,%esi
+ movl %edx,%eax
+ shll $14,%edi
+ xorl %esi,%ebx
+ shrl $5,%ecx
+ xorl %edi,%eax
+ shrl $5,%edx
+ xorl %ecx,%eax
+ shll $4,%esi
+ xorl %edx,%ebx
+ shll $4,%edi
+ xorl %esi,%ebx
+ shrl $4,%ecx
+ xorl %edi,%eax
+ shrl $4,%edx
+ xorl %ecx,%eax
+ shll $5,%esi
+ xorl %edx,%ebx
+ shll $5,%edi
+ xorl %esi,%eax
+ xorl %edi,%ebx
+ movl 48(%esp),%ecx
+ movl 52(%esp),%edx
+ movl 56(%esp),%esi
+ movl 60(%esp),%edi
+ addl 64(%esp),%eax
+ adcl 68(%esp),%ebx
+ xorl %esi,%ecx
+ xorl %edi,%edx
+ andl 40(%esp),%ecx
+ andl 44(%esp),%edx
+ addl 192(%esp),%eax
+ adcl 196(%esp),%ebx
+ xorl %esi,%ecx
+ xorl %edi,%edx
+ movl (%ebp),%esi
+ movl 4(%ebp),%edi
+ addl %ecx,%eax
+ adcl %edx,%ebx
+ movl 32(%esp),%ecx
+ movl 36(%esp),%edx
+ addl %esi,%eax
+ adcl %edi,%ebx
+ movl %eax,(%esp)
+ movl %ebx,4(%esp)
+ addl %ecx,%eax
+ adcl %edx,%ebx
+ movl 8(%esp),%ecx
+ movl 12(%esp),%edx
+ movl %eax,32(%esp)
+ movl %ebx,36(%esp)
+ movl %ecx,%esi
+ shrl $2,%ecx
+ movl %edx,%edi
+ shrl $2,%edx
+ movl %ecx,%ebx
+ shll $4,%esi
+ movl %edx,%eax
+ shll $4,%edi
+ xorl %esi,%ebx
+ shrl $5,%ecx
+ xorl %edi,%eax
+ shrl $5,%edx
+ xorl %ecx,%ebx
+ shll $21,%esi
+ xorl %edx,%eax
+ shll $21,%edi
+ xorl %esi,%eax
+ shrl $21,%ecx
+ xorl %edi,%ebx
+ shrl $21,%edx
+ xorl %ecx,%eax
+ shll $5,%esi
+ xorl %edx,%ebx
+ shll $5,%edi
+ xorl %esi,%eax
+ xorl %edi,%ebx
+ movl 8(%esp),%ecx
+ movl 12(%esp),%edx
+ movl 16(%esp),%esi
+ movl 20(%esp),%edi
+ addl (%esp),%eax
+ adcl 4(%esp),%ebx
+ orl %esi,%ecx
+ orl %edi,%edx
+ andl 24(%esp),%ecx
+ andl 28(%esp),%edx
+ andl 8(%esp),%esi
+ andl 12(%esp),%edi
+ orl %esi,%ecx
+ orl %edi,%edx
+ addl %ecx,%eax
+ adcl %edx,%ebx
+ movl %eax,(%esp)
+ movl %ebx,4(%esp)
+ movb (%ebp),%dl
+ subl $8,%esp
+ leal 8(%ebp),%ebp
+ cmpb $148,%dl
+ jne L00300_15_x86
+.align 4,0x90
+L00416_79_x86:
+ movl 312(%esp),%ecx
+ movl 316(%esp),%edx
+ movl %ecx,%esi
+ shrl $1,%ecx
+ movl %edx,%edi
+ shrl $1,%edx
+ movl %ecx,%eax
+ shll $24,%esi
+ movl %edx,%ebx
+ shll $24,%edi
+ xorl %esi,%ebx
+ shrl $6,%ecx
+ xorl %edi,%eax
+ shrl $6,%edx
+ xorl %ecx,%eax
+ shll $7,%esi
+ xorl %edx,%ebx
+ shll $1,%edi
+ xorl %esi,%ebx
+ shrl $1,%ecx
+ xorl %edi,%eax
+ shrl $1,%edx
+ xorl %ecx,%eax
+ shll $6,%edi
+ xorl %edx,%ebx
+ xorl %edi,%eax
+ movl %eax,(%esp)
+ movl %ebx,4(%esp)
+ movl 208(%esp),%ecx
+ movl 212(%esp),%edx
+ movl %ecx,%esi
+ shrl $6,%ecx
+ movl %edx,%edi
+ shrl $6,%edx
+ movl %ecx,%eax
+ shll $3,%esi
+ movl %edx,%ebx
+ shll $3,%edi
+ xorl %esi,%eax
+ shrl $13,%ecx
+ xorl %edi,%ebx
+ shrl $13,%edx
+ xorl %ecx,%eax
+ shll $10,%esi
+ xorl %edx,%ebx
+ shll $10,%edi
+ xorl %esi,%ebx
+ shrl $10,%ecx
+ xorl %edi,%eax
+ shrl $10,%edx
+ xorl %ecx,%ebx
+ shll $13,%edi
+ xorl %edx,%eax
+ xorl %edi,%eax
+ movl 320(%esp),%ecx
+ movl 324(%esp),%edx
+ addl (%esp),%eax
+ adcl 4(%esp),%ebx
+ movl 248(%esp),%esi
+ movl 252(%esp),%edi
+ addl %ecx,%eax
+ adcl %edx,%ebx
+ addl %esi,%eax
+ adcl %edi,%ebx
+ movl %eax,192(%esp)
+ movl %ebx,196(%esp)
+ movl 40(%esp),%ecx
+ movl 44(%esp),%edx
+ movl %ecx,%esi
+ shrl $9,%ecx
+ movl %edx,%edi
+ shrl $9,%edx
+ movl %ecx,%ebx
+ shll $14,%esi
+ movl %edx,%eax
+ shll $14,%edi
+ xorl %esi,%ebx
+ shrl $5,%ecx
+ xorl %edi,%eax
+ shrl $5,%edx
+ xorl %ecx,%eax
+ shll $4,%esi
+ xorl %edx,%ebx
+ shll $4,%edi
+ xorl %esi,%ebx
+ shrl $4,%ecx
+ xorl %edi,%eax
+ shrl $4,%edx
+ xorl %ecx,%eax
+ shll $5,%esi
+ xorl %edx,%ebx
+ shll $5,%edi
+ xorl %esi,%eax
+ xorl %edi,%ebx
+ movl 48(%esp),%ecx
+ movl 52(%esp),%edx
+ movl 56(%esp),%esi
+ movl 60(%esp),%edi
+ addl 64(%esp),%eax
+ adcl 68(%esp),%ebx
+ xorl %esi,%ecx
+ xorl %edi,%edx
+ andl 40(%esp),%ecx
+ andl 44(%esp),%edx
+ addl 192(%esp),%eax
+ adcl 196(%esp),%ebx
+ xorl %esi,%ecx
+ xorl %edi,%edx
+ movl (%ebp),%esi
+ movl 4(%ebp),%edi
+ addl %ecx,%eax
+ adcl %edx,%ebx
+ movl 32(%esp),%ecx
+ movl 36(%esp),%edx
+ addl %esi,%eax
+ adcl %edi,%ebx
+ movl %eax,(%esp)
+ movl %ebx,4(%esp)
+ addl %ecx,%eax
+ adcl %edx,%ebx
+ movl 8(%esp),%ecx
+ movl 12(%esp),%edx
+ movl %eax,32(%esp)
+ movl %ebx,36(%esp)
+ movl %ecx,%esi
+ shrl $2,%ecx
+ movl %edx,%edi
+ shrl $2,%edx
+ movl %ecx,%ebx
+ shll $4,%esi
+ movl %edx,%eax
+ shll $4,%edi
+ xorl %esi,%ebx
+ shrl $5,%ecx
+ xorl %edi,%eax
+ shrl $5,%edx
+ xorl %ecx,%ebx
+ shll $21,%esi
+ xorl %edx,%eax
+ shll $21,%edi
+ xorl %esi,%eax
+ shrl $21,%ecx
+ xorl %edi,%ebx
+ shrl $21,%edx
+ xorl %ecx,%eax
+ shll $5,%esi
+ xorl %edx,%ebx
+ shll $5,%edi
+ xorl %esi,%eax
+ xorl %edi,%ebx
+ movl 8(%esp),%ecx
+ movl 12(%esp),%edx
+ movl 16(%esp),%esi
+ movl 20(%esp),%edi
+ addl (%esp),%eax
+ adcl 4(%esp),%ebx
+ orl %esi,%ecx
+ orl %edi,%edx
+ andl 24(%esp),%ecx
+ andl 28(%esp),%edx
+ andl 8(%esp),%esi
+ andl 12(%esp),%edi
+ orl %esi,%ecx
+ orl %edi,%edx
+ addl %ecx,%eax
+ adcl %edx,%ebx
+ movl %eax,(%esp)
+ movl %ebx,4(%esp)
+ movb (%ebp),%dl
+ subl $8,%esp
+ leal 8(%ebp),%ebp
+ cmpb $23,%dl
+ jne L00416_79_x86
+ movl 840(%esp),%esi
+ movl 844(%esp),%edi
+ movl (%esi),%eax
+ movl 4(%esi),%ebx
+ movl 8(%esi),%ecx
+ movl 12(%esi),%edx
+ addl 8(%esp),%eax
+ adcl 12(%esp),%ebx
+ movl %eax,(%esi)
+ movl %ebx,4(%esi)
+ addl 16(%esp),%ecx
+ adcl 20(%esp),%edx
+ movl %ecx,8(%esi)
+ movl %edx,12(%esi)
+ movl 16(%esi),%eax
+ movl 20(%esi),%ebx
+ movl 24(%esi),%ecx
+ movl 28(%esi),%edx
+ addl 24(%esp),%eax
+ adcl 28(%esp),%ebx
+ movl %eax,16(%esi)
+ movl %ebx,20(%esi)
+ addl 32(%esp),%ecx
+ adcl 36(%esp),%edx
+ movl %ecx,24(%esi)
+ movl %edx,28(%esi)
+ movl 32(%esi),%eax
+ movl 36(%esi),%ebx
+ movl 40(%esi),%ecx
+ movl 44(%esi),%edx
+ addl 40(%esp),%eax
+ adcl 44(%esp),%ebx
+ movl %eax,32(%esi)
+ movl %ebx,36(%esi)
+ addl 48(%esp),%ecx
+ adcl 52(%esp),%edx
+ movl %ecx,40(%esi)
+ movl %edx,44(%esi)
+ movl 48(%esi),%eax
+ movl 52(%esi),%ebx
+ movl 56(%esi),%ecx
+ movl 60(%esi),%edx
+ addl 56(%esp),%eax
+ adcl 60(%esp),%ebx
+ movl %eax,48(%esi)
+ movl %ebx,52(%esi)
+ addl 64(%esp),%ecx
+ adcl 68(%esp),%edx
+ movl %ecx,56(%esi)
+ movl %edx,60(%esi)
+ addl $840,%esp
+ subl $640,%ebp
+ cmpl 8(%esp),%edi
+ jb L002loop_x86
+ movl 12(%esp),%esp
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+.align 6,0x90
+L001K512:
+.long 3609767458,1116352408
+.long 602891725,1899447441
+.long 3964484399,3049323471
+.long 2173295548,3921009573
+.long 4081628472,961987163
+.long 3053834265,1508970993
+.long 2937671579,2453635748
+.long 3664609560,2870763221
+.long 2734883394,3624381080
+.long 1164996542,310598401
+.long 1323610764,607225278
+.long 3590304994,1426881987
+.long 4068182383,1925078388
+.long 991336113,2162078206
+.long 633803317,2614888103
+.long 3479774868,3248222580
+.long 2666613458,3835390401
+.long 944711139,4022224774
+.long 2341262773,264347078
+.long 2007800933,604807628
+.long 1495990901,770255983
+.long 1856431235,1249150122
+.long 3175218132,1555081692
+.long 2198950837,1996064986
+.long 3999719339,2554220882
+.long 766784016,2821834349
+.long 2566594879,2952996808
+.long 3203337956,3210313671
+.long 1034457026,3336571891
+.long 2466948901,3584528711
+.long 3758326383,113926993
+.long 168717936,338241895
+.long 1188179964,666307205
+.long 1546045734,773529912
+.long 1522805485,1294757372
+.long 2643833823,1396182291
+.long 2343527390,1695183700
+.long 1014477480,1986661051
+.long 1206759142,2177026350
+.long 344077627,2456956037
+.long 1290863460,2730485921
+.long 3158454273,2820302411
+.long 3505952657,3259730800
+.long 106217008,3345764771
+.long 3606008344,3516065817
+.long 1432725776,3600352804
+.long 1467031594,4094571909
+.long 851169720,275423344
+.long 3100823752,430227734
+.long 1363258195,506948616
+.long 3750685593,659060556
+.long 3785050280,883997877
+.long 3318307427,958139571
+.long 3812723403,1322822218
+.long 2003034995,1537002063
+.long 3602036899,1747873779
+.long 1575990012,1955562222
+.long 1125592928,2024104815
+.long 2716904306,2227730452
+.long 442776044,2361852424
+.long 593698344,2428436474
+.long 3733110249,2756734187
+.long 2999351573,3204031479
+.long 3815920427,3329325298
+.long 3928383900,3391569614
+.long 566280711,3515267271
+.long 3454069534,3940187606
+.long 4000239992,4118630271
+.long 1914138554,116418474
+.long 2731055270,174292421
+.long 3203993006,289380356
+.long 320620315,460393269
+.long 587496836,685471733
+.long 1086792851,852142971
+.long 365543100,1017036298
+.long 2618297676,1126000580
+.long 3409855158,1288033470
+.long 4234509866,1501505948
+.long 987167468,1607167915
+.long 1246189591,1816402316
+.long 67438087,66051
+.long 202182159,134810123
+.byte 83,72,65,53,49,50,32,98,108,111,99,107,32,116,114,97
+.byte 110,115,102,111,114,109,32,102,111,114,32,120,56,54,44,32
+.byte 67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97
+.byte 112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103
+.byte 62,0
+#endif
diff --git a/mac-x86_64/crypto/aes/aes-x86_64.S b/mac-x86_64/crypto/aes/aes-x86_64.S
new file mode 100644
index 0000000..02f378b
--- /dev/null
+++ b/mac-x86_64/crypto/aes/aes-x86_64.S
@@ -0,0 +1,2535 @@
+#if defined(__x86_64__)
+.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
+.byte 0xf3,0xc3
+
+
+.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 %dl,%r8d
+ movzbl %bh,%esi
+ movzbl %ch,%edi
+ shrl $16,%ecx
+ movzbl %dh,%ebp
+ movzbl (%r14,%r10,1),%r10d
+ movzbl (%r14,%r11,1),%r11d
+ movzbl (%r14,%r12,1),%r12d
+ movzbl (%r14,%r8,1),%r8d
+
+ movzbl (%r14,%rsi,1),%r9d
+ movzbl %ah,%esi
+ movzbl (%r14,%rdi,1),%r13d
+ movzbl %cl,%edi
+ movzbl (%r14,%rbp,1),%ebp
+ movzbl (%r14,%rsi,1),%esi
+
+ shll $8,%r9d
+ shrl $16,%edx
+ shll $8,%r13d
+ xorl %r9d,%r10d
+ shrl $16,%eax
+ movzbl %dl,%r9d
+ shrl $16,%ebx
+ xorl %r13d,%r11d
+ shll $8,%ebp
+ movzbl %al,%r13d
+ movzbl (%r14,%rdi,1),%edi
+ xorl %ebp,%r12d
+
+ shll $8,%esi
+ movzbl %bl,%ebp
+ shll $16,%edi
+ xorl %esi,%r8d
+ movzbl (%r14,%r9,1),%r9d
+ movzbl %dh,%esi
+ movzbl (%r14,%r13,1),%r13d
+ xorl %edi,%r10d
+
+ shrl $8,%ecx
+ movzbl %ah,%edi
+ shll $16,%r9d
+ shrl $8,%ebx
+ shll $16,%r13d
+ xorl %r9d,%r11d
+ movzbl (%r14,%rbp,1),%ebp
+ movzbl (%r14,%rsi,1),%esi
+ movzbl (%r14,%rdi,1),%edi
+ movzbl (%r14,%rcx,1),%edx
+ movzbl (%r14,%rbx,1),%ecx
+
+ shll $16,%ebp
+ xorl %r13d,%r12d
+ shll $24,%esi
+ xorl %ebp,%r8d
+ shll $24,%edi
+ xorl %esi,%r10d
+ shll $24,%edx
+ xorl %edi,%r11d
+ shll $24,%ecx
+ movl %r10d,%eax
+ movl %r11d,%ebx
+ xorl %r12d,%ecx
+ xorl %r8d,%edx
+ cmpq 16(%rsp),%r15
+ je L$enc_compact_done
+ movl $2155905152,%r10d
+ movl $2155905152,%r11d
+ andl %eax,%r10d
+ andl %ebx,%r11d
+ movl %r10d,%esi
+ movl %r11d,%edi
+ 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 $2155905152,%r12d
+ roll $24,%eax
+ movl $2155905152,%ebp
+ roll $24,%ebx
+ andl %ecx,%r12d
+ andl %edx,%ebp
+ xorl %r8d,%eax
+ xorl %r9d,%ebx
+ movl %r12d,%esi
+ rorl $16,%r10d
+ movl %ebp,%edi
+ rorl $16,%r11d
+ leal (%rcx,%rcx,1),%r8d
+ shrl $7,%r12d
+ xorl %r10d,%eax
+ shrl $7,%ebp
+ xorl %r11d,%ebx
+ rorl $8,%r10d
+ leal (%rdx,%rdx,1),%r9d
+ 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
+
+ rorl $16,%r12d
+ xorl %r8d,%ecx
+ rorl $16,%ebp
+ xorl %r9d,%edx
+ roll $24,%ecx
+ movl 0(%r14),%esi
+ roll $24,%edx
+ xorl %r8d,%ecx
+ movl 64(%r14),%edi
+ xorl %r9d,%edx
+ movl 128(%r14),%r8d
+ xorl %r12d,%ecx
+ rorl $8,%r12d
+ xorl %ebp,%edx
+ rorl $8,%ebp
+ xorl %r12d,%ecx
+ movl 192(%r14),%r9d
+ 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
+.byte 0xf3,0xc3
+
+.p2align 4
+.globl _asm_AES_encrypt
+.private_extern _asm_AES_encrypt
+
+.private_extern _asm_AES_encrypt
+_asm_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:
+ .byte 0xf3,0xc3
+
+
+.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
+.byte 0xf3,0xc3
+
+
+.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 %dl,%r8d
+ movzbl %dh,%esi
+ movzbl %ah,%edi
+ shrl $16,%edx
+ movzbl %bh,%ebp
+ movzbl (%r14,%r10,1),%r10d
+ movzbl (%r14,%r11,1),%r11d
+ movzbl (%r14,%r12,1),%r12d
+ movzbl (%r14,%r8,1),%r8d
+
+ movzbl (%r14,%rsi,1),%r9d
+ movzbl %ch,%esi
+ movzbl (%r14,%rdi,1),%r13d
+ movzbl (%r14,%rbp,1),%ebp
+ movzbl (%r14,%rsi,1),%esi
+
+ shrl $16,%ecx
+ shll $8,%r13d
+ shll $8,%r9d
+ movzbl %cl,%edi
+ shrl $16,%eax
+ xorl %r9d,%r10d
+ shrl $16,%ebx
+ movzbl %dl,%r9d
+
+ shll $8,%ebp
+ xorl %r13d,%r11d
+ shll $8,%esi
+ movzbl %al,%r13d
+ movzbl (%r14,%rdi,1),%edi
+ xorl %ebp,%r12d
+ movzbl %bl,%ebp
+
+ shll $16,%edi
+ xorl %esi,%r8d
+ movzbl (%r14,%r9,1),%r9d
+ movzbl %bh,%esi
+ movzbl (%r14,%rbp,1),%ebp
+ xorl %edi,%r10d
+ movzbl (%r14,%r13,1),%r13d
+ movzbl %ch,%edi
+
+ shll $16,%ebp
+ shll $16,%r9d
+ shll $16,%r13d
+ xorl %ebp,%r8d
+ movzbl %dh,%ebp
+ xorl %r9d,%r11d
+ shrl $8,%eax
+ xorl %r13d,%r12d
+
+ movzbl (%r14,%rsi,1),%esi
+ movzbl (%r14,%rdi,1),%ebx
+ movzbl (%r14,%rbp,1),%ecx
+ movzbl (%r14,%rax,1),%edx
+
+ movl %r10d,%eax
+ shll $24,%esi
+ shll $24,%ebx
+ shll $24,%ecx
+ xorl %esi,%eax
+ shll $24,%edx
+ xorl %r11d,%ebx
+ 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 %rsi,%r9
+ movq %rsi,%r12
+ andq %rax,%r9
+ andq %rcx,%r12
+ movq %r9,%rbx
+ movq %r12,%rdx
+ 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 %rbx,%r8
+ xorq %rdx,%r11
+ movq %rsi,%r10
+ movq %rsi,%r13
+
+ andq %r8,%r10
+ andq %r11,%r13
+ movq %r10,%rbx
+ movq %r13,%rdx
+ 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 %rbx,%r9
+ xorq %rdx,%r12
+ movq %rsi,%r10
+ movq %rsi,%r13
+
+ andq %r9,%r10
+ andq %r12,%r13
+ movq %r10,%rbx
+ movq %r13,%rdx
+ 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
+ shrq $32,%rbx
+ xorq %r13,%r12
+ shrq $32,%rdx
+ xorq %r8,%r10
+ roll $8,%eax
+ xorq %r11,%r13
+ roll $8,%ecx
+ xorq %r9,%r10
+ roll $8,%ebx
+ xorq %r12,%r13
+
+ roll $8,%edx
+ xorl %r10d,%eax
+ shrq $32,%r10
+ xorl %r13d,%ecx
+ shrq $32,%r13
+ xorl %r10d,%ebx
+ xorl %r13d,%edx
+
+ movq %r8,%r10
+ roll $24,%r8d
+ movq %r11,%r13
+ roll $24,%r11d
+ shrq $32,%r10
+ xorl %r8d,%eax
+ shrq $32,%r13
+ xorl %r11d,%ecx
+ roll $24,%r10d
+ movq %r9,%r8
+ roll $24,%r13d
+ movq %r12,%r11
+ shrq $32,%r8
+ xorl %r10d,%ebx
+ shrq $32,%r11
+ xorl %r13d,%edx
+
+ movq 0(%r14),%rsi
+ roll $16,%r9d
+ movq 64(%r14),%rdi
+ roll $16,%r12d
+ movq 128(%r14),%rbp
+ roll $16,%r8d
+ movq 192(%r14),%r10
+ xorl %r9d,%eax
+ roll $16,%r11d
+ 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
+.byte 0xf3,0xc3
+
+.p2align 4
+.globl _asm_AES_decrypt
+.private_extern _asm_AES_decrypt
+
+.private_extern _asm_AES_decrypt
+_asm_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:
+ .byte 0xf3,0xc3
+
+.p2align 4
+.globl _asm_AES_set_encrypt_key
+.private_extern _asm_AES_set_encrypt_key
+
+_asm_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 40(%rsp),%rbp
+ movq 48(%rsp),%rbx
+ addq $56,%rsp
+L$enc_key_epilogue:
+ .byte 0xf3,0xc3
+
+
+
+.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:
+.byte 0xf3,0xc3
+
+.p2align 4
+.globl _asm_AES_set_decrypt_key
+.private_extern _asm_AES_set_decrypt_key
+
+_asm_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 %rsi,%r9
+ movq %rsi,%r12
+ andq %rax,%r9
+ andq %rcx,%r12
+ movq %r9,%rbx
+ movq %r12,%rdx
+ 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 %rbx,%r8
+ xorq %rdx,%r11
+ movq %rsi,%r10
+ movq %rsi,%r13
+
+ andq %r8,%r10
+ andq %r11,%r13
+ movq %r10,%rbx
+ movq %r13,%rdx
+ 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 %rbx,%r9
+ xorq %rdx,%r12
+ movq %rsi,%r10
+ movq %rsi,%r13
+
+ andq %r9,%r10
+ andq %r12,%r13
+ movq %r10,%rbx
+ movq %r13,%rdx
+ 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
+ shrq $32,%rbx
+ xorq %r13,%r12
+ shrq $32,%rdx
+ xorq %r8,%r10
+ roll $8,%eax
+ xorq %r11,%r13
+ roll $8,%ecx
+ xorq %r9,%r10
+ roll $8,%ebx
+ xorq %r12,%r13
+
+ roll $8,%edx
+ xorl %r10d,%eax
+ shrq $32,%r10
+ xorl %r13d,%ecx
+ shrq $32,%r13
+ xorl %r10d,%ebx
+ xorl %r13d,%edx
+
+ movq %r8,%r10
+ roll $24,%r8d
+ movq %r11,%r13
+ roll $24,%r11d
+ shrq $32,%r10
+ xorl %r8d,%eax
+ shrq $32,%r13
+ xorl %r11d,%ecx
+ roll $24,%r10d
+ movq %r9,%r8
+ roll $24,%r13d
+ movq %r12,%r11
+ shrq $32,%r8
+ xorl %r10d,%ebx
+ shrq $32,%r11
+ xorl %r13d,%edx
+
+
+ roll $16,%r9d
+
+ roll $16,%r12d
+
+ roll $16,%r8d
+
+ xorl %r9d,%eax
+ roll $16,%r11d
+ 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:
+ .byte 0xf3,0xc3
+
+.p2align 4
+.globl _asm_AES_cbc_encrypt
+.private_extern _asm_AES_cbc_encrypt
+
+
+.private_extern _asm_AES_cbc_encrypt
+_asm_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 $28,%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:
+ .byte 0xf3,0xc3
+
+.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
+#endif
diff --git a/mac-x86_64/crypto/aes/aesni-x86_64.S b/mac-x86_64/crypto/aes/aesni-x86_64.S
new file mode 100644
index 0000000..032c94d
--- /dev/null
+++ b/mac-x86_64/crypto/aes/aesni-x86_64.S
@@ -0,0 +1,3178 @@
+#if defined(__x86_64__)
+.text
+
+.globl _aesni_encrypt
+.private_extern _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:
+.byte 102,15,56,220,209
+ decl %eax
+ movups (%rdx),%xmm1
+ leaq 16(%rdx),%rdx
+ jnz L$oop_enc1_1
+.byte 102,15,56,221,209
+ movups %xmm2,(%rsi)
+ .byte 0xf3,0xc3
+
+
+.globl _aesni_decrypt
+.private_extern _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:
+.byte 102,15,56,222,209
+ decl %eax
+ movups (%rdx),%xmm1
+ leaq 16(%rdx),%rdx
+ jnz L$oop_dec1_2
+.byte 102,15,56,223,209
+ movups %xmm2,(%rsi)
+ .byte 0xf3,0xc3
+
+
+.p2align 4
+_aesni_encrypt2:
+ movups (%rcx),%xmm0
+ shll $4,%eax
+ movups 16(%rcx),%xmm1
+ xorps %xmm0,%xmm2
+ xorps %xmm0,%xmm3
+ movups 32(%rcx),%xmm0
+ leaq 32(%rcx,%rax,1),%rcx
+ negq %rax
+ addq $16,%rax
+
+L$enc_loop2:
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+ movups (%rcx,%rax,1),%xmm1
+ addq $32,%rax
+.byte 102,15,56,220,208
+.byte 102,15,56,220,216
+ movups -16(%rcx,%rax,1),%xmm0
+ jnz L$enc_loop2
+
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+.byte 102,15,56,221,208
+.byte 102,15,56,221,216
+ .byte 0xf3,0xc3
+
+
+.p2align 4
+_aesni_decrypt2:
+ movups (%rcx),%xmm0
+ shll $4,%eax
+ movups 16(%rcx),%xmm1
+ xorps %xmm0,%xmm2
+ xorps %xmm0,%xmm3
+ movups 32(%rcx),%xmm0
+ leaq 32(%rcx,%rax,1),%rcx
+ negq %rax
+ addq $16,%rax
+
+L$dec_loop2:
+.byte 102,15,56,222,209
+.byte 102,15,56,222,217
+ movups (%rcx,%rax,1),%xmm1
+ addq $32,%rax
+.byte 102,15,56,222,208
+.byte 102,15,56,222,216
+ movups -16(%rcx,%rax,1),%xmm0
+ jnz L$dec_loop2
+
+.byte 102,15,56,222,209
+.byte 102,15,56,222,217
+.byte 102,15,56,223,208
+.byte 102,15,56,223,216
+ .byte 0xf3,0xc3
+
+
+.p2align 4
+_aesni_encrypt3:
+ movups (%rcx),%xmm0
+ shll $4,%eax
+ movups 16(%rcx),%xmm1
+ xorps %xmm0,%xmm2
+ xorps %xmm0,%xmm3
+ xorps %xmm0,%xmm4
+ movups 32(%rcx),%xmm0
+ leaq 32(%rcx,%rax,1),%rcx
+ negq %rax
+ addq $16,%rax
+
+L$enc_loop3:
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+.byte 102,15,56,220,225
+ movups (%rcx,%rax,1),%xmm1
+ addq $32,%rax
+.byte 102,15,56,220,208
+.byte 102,15,56,220,216
+.byte 102,15,56,220,224
+ movups -16(%rcx,%rax,1),%xmm0
+ jnz L$enc_loop3
+
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+.byte 102,15,56,220,225
+.byte 102,15,56,221,208
+.byte 102,15,56,221,216
+.byte 102,15,56,221,224
+ .byte 0xf3,0xc3
+
+
+.p2align 4
+_aesni_decrypt3:
+ movups (%rcx),%xmm0
+ shll $4,%eax
+ movups 16(%rcx),%xmm1
+ xorps %xmm0,%xmm2
+ xorps %xmm0,%xmm3
+ xorps %xmm0,%xmm4
+ movups 32(%rcx),%xmm0
+ leaq 32(%rcx,%rax,1),%rcx
+ negq %rax
+ addq $16,%rax
+
+L$dec_loop3:
+.byte 102,15,56,222,209
+.byte 102,15,56,222,217
+.byte 102,15,56,222,225
+ movups (%rcx,%rax,1),%xmm1
+ addq $32,%rax
+.byte 102,15,56,222,208
+.byte 102,15,56,222,216
+.byte 102,15,56,222,224
+ movups -16(%rcx,%rax,1),%xmm0
+ jnz L$dec_loop3
+
+.byte 102,15,56,222,209
+.byte 102,15,56,222,217
+.byte 102,15,56,222,225
+.byte 102,15,56,223,208
+.byte 102,15,56,223,216
+.byte 102,15,56,223,224
+ .byte 0xf3,0xc3
+
+
+.p2align 4
+_aesni_encrypt4:
+ movups (%rcx),%xmm0
+ shll $4,%eax
+ movups 16(%rcx),%xmm1
+ xorps %xmm0,%xmm2
+ xorps %xmm0,%xmm3
+ xorps %xmm0,%xmm4
+ xorps %xmm0,%xmm5
+ movups 32(%rcx),%xmm0
+ leaq 32(%rcx,%rax,1),%rcx
+ negq %rax
+.byte 0x0f,0x1f,0x00
+ addq $16,%rax
+
+L$enc_loop4:
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+.byte 102,15,56,220,225
+.byte 102,15,56,220,233
+ movups (%rcx,%rax,1),%xmm1
+ addq $32,%rax
+.byte 102,15,56,220,208
+.byte 102,15,56,220,216
+.byte 102,15,56,220,224
+.byte 102,15,56,220,232
+ movups -16(%rcx,%rax,1),%xmm0
+ jnz L$enc_loop4
+
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+.byte 102,15,56,220,225
+.byte 102,15,56,220,233
+.byte 102,15,56,221,208
+.byte 102,15,56,221,216
+.byte 102,15,56,221,224
+.byte 102,15,56,221,232
+ .byte 0xf3,0xc3
+
+
+.p2align 4
+_aesni_decrypt4:
+ movups (%rcx),%xmm0
+ shll $4,%eax
+ movups 16(%rcx),%xmm1
+ xorps %xmm0,%xmm2
+ xorps %xmm0,%xmm3
+ xorps %xmm0,%xmm4
+ xorps %xmm0,%xmm5
+ movups 32(%rcx),%xmm0
+ leaq 32(%rcx,%rax,1),%rcx
+ negq %rax
+.byte 0x0f,0x1f,0x00
+ addq $16,%rax
+
+L$dec_loop4:
+.byte 102,15,56,222,209
+.byte 102,15,56,222,217
+.byte 102,15,56,222,225
+.byte 102,15,56,222,233
+ movups (%rcx,%rax,1),%xmm1
+ addq $32,%rax
+.byte 102,15,56,222,208
+.byte 102,15,56,222,216
+.byte 102,15,56,222,224
+.byte 102,15,56,222,232
+ movups -16(%rcx,%rax,1),%xmm0
+ jnz L$dec_loop4
+
+.byte 102,15,56,222,209
+.byte 102,15,56,222,217
+.byte 102,15,56,222,225
+.byte 102,15,56,222,233
+.byte 102,15,56,223,208
+.byte 102,15,56,223,216
+.byte 102,15,56,223,224
+.byte 102,15,56,223,232
+ .byte 0xf3,0xc3
+
+
+.p2align 4
+_aesni_encrypt6:
+ movups (%rcx),%xmm0
+ shll $4,%eax
+ movups 16(%rcx),%xmm1
+ xorps %xmm0,%xmm2
+ pxor %xmm0,%xmm3
+ pxor %xmm0,%xmm4
+.byte 102,15,56,220,209
+ leaq 32(%rcx,%rax,1),%rcx
+ negq %rax
+.byte 102,15,56,220,217
+ pxor %xmm0,%xmm5
+ pxor %xmm0,%xmm6
+.byte 102,15,56,220,225
+ pxor %xmm0,%xmm7
+ addq $16,%rax
+.byte 102,15,56,220,233
+.byte 102,15,56,220,241
+.byte 102,15,56,220,249
+ movups -16(%rcx,%rax,1),%xmm0
+ jmp L$enc_loop6_enter
+.p2align 4
+L$enc_loop6:
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+.byte 102,15,56,220,225
+.byte 102,15,56,220,233
+.byte 102,15,56,220,241
+.byte 102,15,56,220,249
+L$enc_loop6_enter:
+ movups (%rcx,%rax,1),%xmm1
+ addq $32,%rax
+.byte 102,15,56,220,208
+.byte 102,15,56,220,216
+.byte 102,15,56,220,224
+.byte 102,15,56,220,232
+.byte 102,15,56,220,240
+.byte 102,15,56,220,248
+ movups -16(%rcx,%rax,1),%xmm0
+ jnz L$enc_loop6
+
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+.byte 102,15,56,220,225
+.byte 102,15,56,220,233
+.byte 102,15,56,220,241
+.byte 102,15,56,220,249
+.byte 102,15,56,221,208
+.byte 102,15,56,221,216
+.byte 102,15,56,221,224
+.byte 102,15,56,221,232
+.byte 102,15,56,221,240
+.byte 102,15,56,221,248
+ .byte 0xf3,0xc3
+
+
+.p2align 4
+_aesni_decrypt6:
+ movups (%rcx),%xmm0
+ shll $4,%eax
+ movups 16(%rcx),%xmm1
+ xorps %xmm0,%xmm2
+ pxor %xmm0,%xmm3
+ pxor %xmm0,%xmm4
+.byte 102,15,56,222,209
+ leaq 32(%rcx,%rax,1),%rcx
+ negq %rax
+.byte 102,15,56,222,217
+ pxor %xmm0,%xmm5
+ pxor %xmm0,%xmm6
+.byte 102,15,56,222,225
+ pxor %xmm0,%xmm7
+ addq $16,%rax
+.byte 102,15,56,222,233
+.byte 102,15,56,222,241
+.byte 102,15,56,222,249
+ movups -16(%rcx,%rax,1),%xmm0
+ jmp L$dec_loop6_enter
+.p2align 4
+L$dec_loop6:
+.byte 102,15,56,222,209
+.byte 102,15,56,222,217
+.byte 102,15,56,222,225
+.byte 102,15,56,222,233
+.byte 102,15,56,222,241
+.byte 102,15,56,222,249
+L$dec_loop6_enter:
+ movups (%rcx,%rax,1),%xmm1
+ addq $32,%rax
+.byte 102,15,56,222,208
+.byte 102,15,56,222,216
+.byte 102,15,56,222,224
+.byte 102,15,56,222,232
+.byte 102,15,56,222,240
+.byte 102,15,56,222,248
+ movups -16(%rcx,%rax,1),%xmm0
+ jnz L$dec_loop6
+
+.byte 102,15,56,222,209
+.byte 102,15,56,222,217
+.byte 102,15,56,222,225
+.byte 102,15,56,222,233
+.byte 102,15,56,222,241
+.byte 102,15,56,222,249
+.byte 102,15,56,223,208
+.byte 102,15,56,223,216
+.byte 102,15,56,223,224
+.byte 102,15,56,223,232
+.byte 102,15,56,223,240
+.byte 102,15,56,223,248
+ .byte 0xf3,0xc3
+
+
+.p2align 4
+_aesni_encrypt8:
+ movups (%rcx),%xmm0
+ shll $4,%eax
+ movups 16(%rcx),%xmm1
+ xorps %xmm0,%xmm2
+ xorps %xmm0,%xmm3
+ pxor %xmm0,%xmm4
+ pxor %xmm0,%xmm5
+ pxor %xmm0,%xmm6
+ leaq 32(%rcx,%rax,1),%rcx
+ negq %rax
+.byte 102,15,56,220,209
+ addq $16,%rax
+ pxor %xmm0,%xmm7
+.byte 102,15,56,220,217
+ pxor %xmm0,%xmm8
+ pxor %xmm0,%xmm9
+.byte 102,15,56,220,225
+.byte 102,15,56,220,233
+.byte 102,15,56,220,241
+.byte 102,15,56,220,249
+.byte 102,68,15,56,220,193
+.byte 102,68,15,56,220,201
+ movups -16(%rcx,%rax,1),%xmm0
+ jmp L$enc_loop8_enter
+.p2align 4
+L$enc_loop8:
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+.byte 102,15,56,220,225
+.byte 102,15,56,220,233
+.byte 102,15,56,220,241
+.byte 102,15,56,220,249
+.byte 102,68,15,56,220,193
+.byte 102,68,15,56,220,201
+L$enc_loop8_enter:
+ movups (%rcx,%rax,1),%xmm1
+ addq $32,%rax
+.byte 102,15,56,220,208
+.byte 102,15,56,220,216
+.byte 102,15,56,220,224
+.byte 102,15,56,220,232
+.byte 102,15,56,220,240
+.byte 102,15,56,220,248
+.byte 102,68,15,56,220,192
+.byte 102,68,15,56,220,200
+ movups -16(%rcx,%rax,1),%xmm0
+ jnz L$enc_loop8
+
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+.byte 102,15,56,220,225
+.byte 102,15,56,220,233
+.byte 102,15,56,220,241
+.byte 102,15,56,220,249
+.byte 102,68,15,56,220,193
+.byte 102,68,15,56,220,201
+.byte 102,15,56,221,208
+.byte 102,15,56,221,216
+.byte 102,15,56,221,224
+.byte 102,15,56,221,232
+.byte 102,15,56,221,240
+.byte 102,15,56,221,248
+.byte 102,68,15,56,221,192
+.byte 102,68,15,56,221,200
+ .byte 0xf3,0xc3
+
+
+.p2align 4
+_aesni_decrypt8:
+ movups (%rcx),%xmm0
+ shll $4,%eax
+ movups 16(%rcx),%xmm1
+ xorps %xmm0,%xmm2
+ xorps %xmm0,%xmm3
+ pxor %xmm0,%xmm4
+ pxor %xmm0,%xmm5
+ pxor %xmm0,%xmm6
+ leaq 32(%rcx,%rax,1),%rcx
+ negq %rax
+.byte 102,15,56,222,209
+ addq $16,%rax
+ pxor %xmm0,%xmm7
+.byte 102,15,56,222,217
+ pxor %xmm0,%xmm8
+ pxor %xmm0,%xmm9
+.byte 102,15,56,222,225
+.byte 102,15,56,222,233
+.byte 102,15,56,222,241
+.byte 102,15,56,222,249
+.byte 102,68,15,56,222,193
+.byte 102,68,15,56,222,201
+ movups -16(%rcx,%rax,1),%xmm0
+ jmp L$dec_loop8_enter
+.p2align 4
+L$dec_loop8:
+.byte 102,15,56,222,209
+.byte 102,15,56,222,217
+.byte 102,15,56,222,225
+.byte 102,15,56,222,233
+.byte 102,15,56,222,241
+.byte 102,15,56,222,249
+.byte 102,68,15,56,222,193
+.byte 102,68,15,56,222,201
+L$dec_loop8_enter:
+ movups (%rcx,%rax,1),%xmm1
+ addq $32,%rax
+.byte 102,15,56,222,208
+.byte 102,15,56,222,216
+.byte 102,15,56,222,224
+.byte 102,15,56,222,232
+.byte 102,15,56,222,240
+.byte 102,15,56,222,248
+.byte 102,68,15,56,222,192
+.byte 102,68,15,56,222,200
+ movups -16(%rcx,%rax,1),%xmm0
+ jnz L$dec_loop8
+
+.byte 102,15,56,222,209
+.byte 102,15,56,222,217
+.byte 102,15,56,222,225
+.byte 102,15,56,222,233
+.byte 102,15,56,222,241
+.byte 102,15,56,222,249
+.byte 102,68,15,56,222,193
+.byte 102,68,15,56,222,201
+.byte 102,15,56,223,208
+.byte 102,15,56,223,216
+.byte 102,15,56,223,224
+.byte 102,15,56,223,232
+.byte 102,15,56,223,240
+.byte 102,15,56,223,248
+.byte 102,68,15,56,223,192
+.byte 102,68,15,56,223,200
+ .byte 0xf3,0xc3
+
+.globl _aesni_ecb_encrypt
+.private_extern _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:
+.byte 102,15,56,220,209
+ decl %eax
+ movups (%rcx),%xmm1
+ leaq 16(%rcx),%rcx
+ jnz L$oop_enc1_3
+.byte 102,15,56,221,209
+ movups %xmm2,(%rsi)
+ jmp L$ecb_ret
+.p2align 4
+L$ecb_enc_two:
+ call _aesni_encrypt2
+ 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:
+.byte 102,15,56,222,209
+ decl %eax
+ movups (%rcx),%xmm1
+ leaq 16(%rcx),%rcx
+ jnz L$oop_dec1_4
+.byte 102,15,56,223,209
+ movups %xmm2,(%rsi)
+ jmp L$ecb_ret
+.p2align 4
+L$ecb_dec_two:
+ call _aesni_decrypt2
+ 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:
+ .byte 0xf3,0xc3
+
+.globl _aesni_ccm64_encrypt_blocks
+.private_extern _aesni_ccm64_encrypt_blocks
+
+.p2align 4
+_aesni_ccm64_encrypt_blocks:
+ movl 240(%rcx),%eax
+ movdqu (%r8),%xmm6
+ movdqa L$increment64(%rip),%xmm9
+ movdqa L$bswap_mask(%rip),%xmm7
+
+ shll $4,%eax
+ movl $16,%r10d
+ leaq 0(%rcx),%r11
+ movdqu (%r9),%xmm3
+ movdqa %xmm6,%xmm2
+ leaq 32(%rcx,%rax,1),%rcx
+.byte 102,15,56,0,247
+ subq %rax,%r10
+ jmp L$ccm64_enc_outer
+.p2align 4
+L$ccm64_enc_outer:
+ movups (%r11),%xmm0
+ movq %r10,%rax
+ movups (%rdi),%xmm8
+
+ xorps %xmm0,%xmm2
+ movups 16(%r11),%xmm1
+ xorps %xmm8,%xmm0
+ xorps %xmm0,%xmm3
+ movups 32(%r11),%xmm0
+
+L$ccm64_enc2_loop:
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+ movups (%rcx,%rax,1),%xmm1
+ addq $32,%rax
+.byte 102,15,56,220,208
+.byte 102,15,56,220,216
+ movups -16(%rcx,%rax,1),%xmm0
+ jnz L$ccm64_enc2_loop
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+ paddq %xmm9,%xmm6
+ decq %rdx
+.byte 102,15,56,221,208
+.byte 102,15,56,221,216
+
+ leaq 16(%rdi),%rdi
+ xorps %xmm2,%xmm8
+ movdqa %xmm6,%xmm2
+ movups %xmm8,(%rsi)
+.byte 102,15,56,0,215
+ leaq 16(%rsi),%rsi
+ jnz L$ccm64_enc_outer
+
+ movups %xmm3,(%r9)
+ .byte 0xf3,0xc3
+
+.globl _aesni_ccm64_decrypt_blocks
+.private_extern _aesni_ccm64_decrypt_blocks
+
+.p2align 4
+_aesni_ccm64_decrypt_blocks:
+ movl 240(%rcx),%eax
+ movups (%r8),%xmm6
+ movdqu (%r9),%xmm3
+ movdqa L$increment64(%rip),%xmm9
+ movdqa L$bswap_mask(%rip),%xmm7
+
+ movaps %xmm6,%xmm2
+ movl %eax,%r10d
+ movq %rcx,%r11
+.byte 102,15,56,0,247
+ movups (%rcx),%xmm0
+ movups 16(%rcx),%xmm1
+ leaq 32(%rcx),%rcx
+ xorps %xmm0,%xmm2
+L$oop_enc1_5:
+.byte 102,15,56,220,209
+ decl %eax
+ movups (%rcx),%xmm1
+ leaq 16(%rcx),%rcx
+ jnz L$oop_enc1_5
+.byte 102,15,56,221,209
+ shll $4,%r10d
+ movl $16,%eax
+ movups (%rdi),%xmm8
+ paddq %xmm9,%xmm6
+ leaq 16(%rdi),%rdi
+ subq %r10,%rax
+ leaq 32(%r11,%r10,1),%rcx
+ movq %rax,%r10
+ jmp L$ccm64_dec_outer
+.p2align 4
+L$ccm64_dec_outer:
+ xorps %xmm2,%xmm8
+ movdqa %xmm6,%xmm2
+ movups %xmm8,(%rsi)
+ leaq 16(%rsi),%rsi
+.byte 102,15,56,0,215
+
+ subq $1,%rdx
+ jz L$ccm64_dec_break
+
+ movups (%r11),%xmm0
+ movq %r10,%rax
+ movups 16(%r11),%xmm1
+ xorps %xmm0,%xmm8
+ xorps %xmm0,%xmm2
+ xorps %xmm8,%xmm3
+ movups 32(%r11),%xmm0
+ jmp L$ccm64_dec2_loop
+.p2align 4
+L$ccm64_dec2_loop:
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+ movups (%rcx,%rax,1),%xmm1
+ addq $32,%rax
+.byte 102,15,56,220,208
+.byte 102,15,56,220,216
+ movups -16(%rcx,%rax,1),%xmm0
+ jnz L$ccm64_dec2_loop
+ movups (%rdi),%xmm8
+ paddq %xmm9,%xmm6
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+.byte 102,15,56,221,208
+.byte 102,15,56,221,216
+ leaq 16(%rdi),%rdi
+ jmp L$ccm64_dec_outer
+
+.p2align 4
+L$ccm64_dec_break:
+
+ movl 240(%r11),%eax
+ movups (%r11),%xmm0
+ movups 16(%r11),%xmm1
+ xorps %xmm0,%xmm8
+ leaq 32(%r11),%r11
+ xorps %xmm8,%xmm3
+L$oop_enc1_6:
+.byte 102,15,56,220,217
+ decl %eax
+ movups (%r11),%xmm1
+ leaq 16(%r11),%r11
+ jnz L$oop_enc1_6
+.byte 102,15,56,221,217
+ movups %xmm3,(%r9)
+ .byte 0xf3,0xc3
+
+.globl _aesni_ctr32_encrypt_blocks
+.private_extern _aesni_ctr32_encrypt_blocks
+
+.p2align 4
+_aesni_ctr32_encrypt_blocks:
+ leaq (%rsp),%rax
+ pushq %rbp
+ subq $128,%rsp
+ andq $-16,%rsp
+ leaq -8(%rax),%rbp
+
+ cmpq $1,%rdx
+ je L$ctr32_one_shortcut
+
+ movdqu (%r8),%xmm2
+ movdqu (%rcx),%xmm0
+ movl 12(%r8),%r8d
+ pxor %xmm0,%xmm2
+ movl 12(%rcx),%r11d
+ movdqa %xmm2,0(%rsp)
+ bswapl %r8d
+ movdqa %xmm2,%xmm3
+ movdqa %xmm2,%xmm4
+ movdqa %xmm2,%xmm5
+ movdqa %xmm2,64(%rsp)
+ movdqa %xmm2,80(%rsp)
+ movdqa %xmm2,96(%rsp)
+ movq %rdx,%r10
+ movdqa %xmm2,112(%rsp)
+
+ leaq 1(%r8),%rax
+ leaq 2(%r8),%rdx
+ bswapl %eax
+ bswapl %edx
+ xorl %r11d,%eax
+ xorl %r11d,%edx
+.byte 102,15,58,34,216,3
+ leaq 3(%r8),%rax
+ movdqa %xmm3,16(%rsp)
+.byte 102,15,58,34,226,3
+ bswapl %eax
+ movq %r10,%rdx
+ leaq 4(%r8),%r10
+ movdqa %xmm4,32(%rsp)
+ xorl %r11d,%eax
+ bswapl %r10d
+.byte 102,15,58,34,232,3
+ xorl %r11d,%r10d
+ movdqa %xmm5,48(%rsp)
+ leaq 5(%r8),%r9
+ movl %r10d,64+12(%rsp)
+ bswapl %r9d
+ leaq 6(%r8),%r10
+ movl 240(%rcx),%eax
+ xorl %r11d,%r9d
+ bswapl %r10d
+ movl %r9d,80+12(%rsp)
+ xorl %r11d,%r10d
+ leaq 7(%r8),%r9
+ movl %r10d,96+12(%rsp)
+ bswapl %r9d
+ movl _OPENSSL_ia32cap_P+4(%rip),%r10d
+ xorl %r11d,%r9d
+ andl $71303168,%r10d
+ movl %r9d,112+12(%rsp)
+
+ movups 16(%rcx),%xmm1
+
+ movdqa 64(%rsp),%xmm6
+ movdqa 80(%rsp),%xmm7
+
+ cmpq $8,%rdx
+ jb L$ctr32_tail
+
+ subq $6,%rdx
+ cmpl $4194304,%r10d
+ je L$ctr32_6x
+
+ leaq 128(%rcx),%rcx
+ subq $2,%rdx
+ jmp L$ctr32_loop8
+
+.p2align 4
+L$ctr32_6x:
+ shll $4,%eax
+ movl $48,%r10d
+ bswapl %r11d
+ leaq 32(%rcx,%rax,1),%rcx
+ subq %rax,%r10
+ jmp L$ctr32_loop6
+
+.p2align 4
+L$ctr32_loop6:
+ addl $6,%r8d
+ movups -48(%rcx,%r10,1),%xmm0
+.byte 102,15,56,220,209
+ movl %r8d,%eax
+ xorl %r11d,%eax
+.byte 102,15,56,220,217
+.byte 0x0f,0x38,0xf1,0x44,0x24,12
+ leal 1(%r8),%eax
+.byte 102,15,56,220,225
+ xorl %r11d,%eax
+.byte 0x0f,0x38,0xf1,0x44,0x24,28
+.byte 102,15,56,220,233
+ leal 2(%r8),%eax
+ xorl %r11d,%eax
+.byte 102,15,56,220,241
+.byte 0x0f,0x38,0xf1,0x44,0x24,44
+ leal 3(%r8),%eax
+.byte 102,15,56,220,249
+ movups -32(%rcx,%r10,1),%xmm1
+ xorl %r11d,%eax
+
+.byte 102,15,56,220,208
+.byte 0x0f,0x38,0xf1,0x44,0x24,60
+ leal 4(%r8),%eax
+.byte 102,15,56,220,216
+ xorl %r11d,%eax
+.byte 0x0f,0x38,0xf1,0x44,0x24,76
+.byte 102,15,56,220,224
+ leal 5(%r8),%eax
+ xorl %r11d,%eax
+.byte 102,15,56,220,232
+.byte 0x0f,0x38,0xf1,0x44,0x24,92
+ movq %r10,%rax
+.byte 102,15,56,220,240
+.byte 102,15,56,220,248
+ movups -16(%rcx,%r10,1),%xmm0
+
+ call L$enc_loop6
+
+ movdqu (%rdi),%xmm8
+ movdqu 16(%rdi),%xmm9
+ movdqu 32(%rdi),%xmm10
+ movdqu 48(%rdi),%xmm11
+ movdqu 64(%rdi),%xmm12
+ movdqu 80(%rdi),%xmm13
+ leaq 96(%rdi),%rdi
+ movups -64(%rcx,%r10,1),%xmm1
+ pxor %xmm2,%xmm8
+ movaps 0(%rsp),%xmm2
+ pxor %xmm3,%xmm9
+ movaps 16(%rsp),%xmm3
+ pxor %xmm4,%xmm10
+ movaps 32(%rsp),%xmm4
+ pxor %xmm5,%xmm11
+ movaps 48(%rsp),%xmm5
+ pxor %xmm6,%xmm12
+ movaps 64(%rsp),%xmm6
+ pxor %xmm7,%xmm13
+ movaps 80(%rsp),%xmm7
+ movdqu %xmm8,(%rsi)
+ movdqu %xmm9,16(%rsi)
+ movdqu %xmm10,32(%rsi)
+ movdqu %xmm11,48(%rsi)
+ movdqu %xmm12,64(%rsi)
+ movdqu %xmm13,80(%rsi)
+ leaq 96(%rsi),%rsi
+
+ subq $6,%rdx
+ jnc L$ctr32_loop6
+
+ addq $6,%rdx
+ jz L$ctr32_done
+
+ leal -48(%r10),%eax
+ leaq -80(%rcx,%r10,1),%rcx
+ negl %eax
+ shrl $4,%eax
+ jmp L$ctr32_tail
+
+.p2align 5
+L$ctr32_loop8:
+ addl $8,%r8d
+ movdqa 96(%rsp),%xmm8
+.byte 102,15,56,220,209
+ movl %r8d,%r9d
+ movdqa 112(%rsp),%xmm9
+.byte 102,15,56,220,217
+ bswapl %r9d
+ movups 32-128(%rcx),%xmm0
+.byte 102,15,56,220,225
+ xorl %r11d,%r9d
+ nop
+.byte 102,15,56,220,233
+ movl %r9d,0+12(%rsp)
+ leaq 1(%r8),%r9
+.byte 102,15,56,220,241
+.byte 102,15,56,220,249
+.byte 102,68,15,56,220,193
+.byte 102,68,15,56,220,201
+ movups 48-128(%rcx),%xmm1
+ bswapl %r9d
+.byte 102,15,56,220,208
+.byte 102,15,56,220,216
+ xorl %r11d,%r9d
+.byte 0x66,0x90
+.byte 102,15,56,220,224
+.byte 102,15,56,220,232
+ movl %r9d,16+12(%rsp)
+ leaq 2(%r8),%r9
+.byte 102,15,56,220,240
+.byte 102,15,56,220,248
+.byte 102,68,15,56,220,192
+.byte 102,68,15,56,220,200
+ movups 64-128(%rcx),%xmm0
+ bswapl %r9d
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+ xorl %r11d,%r9d
+.byte 0x66,0x90
+.byte 102,15,56,220,225
+.byte 102,15,56,220,233
+ movl %r9d,32+12(%rsp)
+ leaq 3(%r8),%r9
+.byte 102,15,56,220,241
+.byte 102,15,56,220,249
+.byte 102,68,15,56,220,193
+.byte 102,68,15,56,220,201
+ movups 80-128(%rcx),%xmm1
+ bswapl %r9d
+.byte 102,15,56,220,208
+.byte 102,15,56,220,216
+ xorl %r11d,%r9d
+.byte 0x66,0x90
+.byte 102,15,56,220,224
+.byte 102,15,56,220,232
+ movl %r9d,48+12(%rsp)
+ leaq 4(%r8),%r9
+.byte 102,15,56,220,240
+.byte 102,15,56,220,248
+.byte 102,68,15,56,220,192
+.byte 102,68,15,56,220,200
+ movups 96-128(%rcx),%xmm0
+ bswapl %r9d
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+ xorl %r11d,%r9d
+.byte 0x66,0x90
+.byte 102,15,56,220,225
+.byte 102,15,56,220,233
+ movl %r9d,64+12(%rsp)
+ leaq 5(%r8),%r9
+.byte 102,15,56,220,241
+.byte 102,15,56,220,249
+.byte 102,68,15,56,220,193
+.byte 102,68,15,56,220,201
+ movups 112-128(%rcx),%xmm1
+ bswapl %r9d
+.byte 102,15,56,220,208
+.byte 102,15,56,220,216
+ xorl %r11d,%r9d
+.byte 0x66,0x90
+.byte 102,15,56,220,224
+.byte 102,15,56,220,232
+ movl %r9d,80+12(%rsp)
+ leaq 6(%r8),%r9
+.byte 102,15,56,220,240
+.byte 102,15,56,220,248
+.byte 102,68,15,56,220,192
+.byte 102,68,15,56,220,200
+ movups 128-128(%rcx),%xmm0
+ bswapl %r9d
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+ xorl %r11d,%r9d
+.byte 0x66,0x90
+.byte 102,15,56,220,225
+.byte 102,15,56,220,233
+ movl %r9d,96+12(%rsp)
+ leaq 7(%r8),%r9
+.byte 102,15,56,220,241
+.byte 102,15,56,220,249
+.byte 102,68,15,56,220,193
+.byte 102,68,15,56,220,201
+ movups 144-128(%rcx),%xmm1
+ bswapl %r9d
+.byte 102,15,56,220,208
+.byte 102,15,56,220,216
+.byte 102,15,56,220,224
+ xorl %r11d,%r9d
+ movdqu 0(%rdi),%xmm10
+.byte 102,15,56,220,232
+ movl %r9d,112+12(%rsp)
+ cmpl $11,%eax
+.byte 102,15,56,220,240
+.byte 102,15,56,220,248
+.byte 102,68,15,56,220,192
+.byte 102,68,15,56,220,200
+ movups 160-128(%rcx),%xmm0
+
+ jb L$ctr32_enc_done
+
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+.byte 102,15,56,220,225
+.byte 102,15,56,220,233
+.byte 102,15,56,220,241
+.byte 102,15,56,220,249
+.byte 102,68,15,56,220,193
+.byte 102,68,15,56,220,201
+ movups 176-128(%rcx),%xmm1
+
+.byte 102,15,56,220,208
+.byte 102,15,56,220,216
+.byte 102,15,56,220,224
+.byte 102,15,56,220,232
+.byte 102,15,56,220,240
+.byte 102,15,56,220,248
+.byte 102,68,15,56,220,192
+.byte 102,68,15,56,220,200
+ movups 192-128(%rcx),%xmm0
+ je L$ctr32_enc_done
+
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+.byte 102,15,56,220,225
+.byte 102,15,56,220,233
+.byte 102,15,56,220,241
+.byte 102,15,56,220,249
+.byte 102,68,15,56,220,193
+.byte 102,68,15,56,220,201
+ movups 208-128(%rcx),%xmm1
+
+.byte 102,15,56,220,208
+.byte 102,15,56,220,216
+.byte 102,15,56,220,224
+.byte 102,15,56,220,232
+.byte 102,15,56,220,240
+.byte 102,15,56,220,248
+.byte 102,68,15,56,220,192
+.byte 102,68,15,56,220,200
+ movups 224-128(%rcx),%xmm0
+ jmp L$ctr32_enc_done
+
+.p2align 4
+L$ctr32_enc_done:
+ movdqu 16(%rdi),%xmm11
+ pxor %xmm0,%xmm10
+ movdqu 32(%rdi),%xmm12
+ pxor %xmm0,%xmm11
+ movdqu 48(%rdi),%xmm13
+ pxor %xmm0,%xmm12
+ movdqu 64(%rdi),%xmm14
+ pxor %xmm0,%xmm13
+ movdqu 80(%rdi),%xmm15
+ pxor %xmm0,%xmm14
+ pxor %xmm0,%xmm15
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+.byte 102,15,56,220,225
+.byte 102,15,56,220,233
+.byte 102,15,56,220,241
+.byte 102,15,56,220,249
+.byte 102,68,15,56,220,193
+.byte 102,68,15,56,220,201
+ movdqu 96(%rdi),%xmm1
+ leaq 128(%rdi),%rdi
+
+.byte 102,65,15,56,221,210
+ pxor %xmm0,%xmm1
+ movdqu 112-128(%rdi),%xmm10
+.byte 102,65,15,56,221,219
+ pxor %xmm0,%xmm10
+ movdqa 0(%rsp),%xmm11
+.byte 102,65,15,56,221,228
+.byte 102,65,15,56,221,237
+ movdqa 16(%rsp),%xmm12
+ movdqa 32(%rsp),%xmm13
+.byte 102,65,15,56,221,246
+.byte 102,65,15,56,221,255
+ movdqa 48(%rsp),%xmm14
+ movdqa 64(%rsp),%xmm15
+.byte 102,68,15,56,221,193
+ movdqa 80(%rsp),%xmm0
+ movups 16-128(%rcx),%xmm1
+.byte 102,69,15,56,221,202
+
+ movups %xmm2,(%rsi)
+ movdqa %xmm11,%xmm2
+ movups %xmm3,16(%rsi)
+ movdqa %xmm12,%xmm3
+ movups %xmm4,32(%rsi)
+ movdqa %xmm13,%xmm4
+ movups %xmm5,48(%rsi)
+ movdqa %xmm14,%xmm5
+ movups %xmm6,64(%rsi)
+ movdqa %xmm15,%xmm6
+ movups %xmm7,80(%rsi)
+ movdqa %xmm0,%xmm7
+ movups %xmm8,96(%rsi)
+ movups %xmm9,112(%rsi)
+ leaq 128(%rsi),%rsi
+
+ subq $8,%rdx
+ jnc L$ctr32_loop8
+
+ addq $8,%rdx
+ jz L$ctr32_done
+ leaq -128(%rcx),%rcx
+
+L$ctr32_tail:
+ leaq 16(%rcx),%rcx
+ cmpq $4,%rdx
+ jb L$ctr32_loop3
+ je L$ctr32_loop4
+
+ shll $4,%eax
+ movdqa 96(%rsp),%xmm8
+ pxor %xmm9,%xmm9
+
+ movups 16(%rcx),%xmm0
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+ leaq 32-16(%rcx,%rax,1),%rcx
+ negq %rax
+.byte 102,15,56,220,225
+ addq $16,%rax
+ movups (%rdi),%xmm10
+.byte 102,15,56,220,233
+.byte 102,15,56,220,241
+ movups 16(%rdi),%xmm11
+ movups 32(%rdi),%xmm12
+.byte 102,15,56,220,249
+.byte 102,68,15,56,220,193
+
+ call L$enc_loop8_enter
+
+ movdqu 48(%rdi),%xmm13
+ pxor %xmm10,%xmm2
+ movdqu 64(%rdi),%xmm10
+ pxor %xmm11,%xmm3
+ movdqu %xmm2,(%rsi)
+ pxor %xmm12,%xmm4
+ movdqu %xmm3,16(%rsi)
+ pxor %xmm13,%xmm5
+ movdqu %xmm4,32(%rsi)
+ pxor %xmm10,%xmm6
+ movdqu %xmm5,48(%rsi)
+ movdqu %xmm6,64(%rsi)
+ cmpq $6,%rdx
+ jb L$ctr32_done
+
+ movups 80(%rdi),%xmm11
+ xorps %xmm11,%xmm7
+ movups %xmm7,80(%rsi)
+ je L$ctr32_done
+
+ movups 96(%rdi),%xmm12
+ xorps %xmm12,%xmm8
+ movups %xmm8,96(%rsi)
+ jmp L$ctr32_done
+
+.p2align 5
+L$ctr32_loop4:
+.byte 102,15,56,220,209
+ leaq 16(%rcx),%rcx
+ decl %eax
+.byte 102,15,56,220,217
+.byte 102,15,56,220,225
+.byte 102,15,56,220,233
+ movups (%rcx),%xmm1
+ jnz L$ctr32_loop4
+.byte 102,15,56,221,209
+.byte 102,15,56,221,217
+ movups (%rdi),%xmm10
+ movups 16(%rdi),%xmm11
+.byte 102,15,56,221,225
+.byte 102,15,56,221,233
+ movups 32(%rdi),%xmm12
+ movups 48(%rdi),%xmm13
+
+ xorps %xmm10,%xmm2
+ movups %xmm2,(%rsi)
+ xorps %xmm11,%xmm3
+ movups %xmm3,16(%rsi)
+ pxor %xmm12,%xmm4
+ movdqu %xmm4,32(%rsi)
+ pxor %xmm13,%xmm5
+ movdqu %xmm5,48(%rsi)
+ jmp L$ctr32_done
+
+.p2align 5
+L$ctr32_loop3:
+.byte 102,15,56,220,209
+ leaq 16(%rcx),%rcx
+ decl %eax
+.byte 102,15,56,220,217
+.byte 102,15,56,220,225
+ movups (%rcx),%xmm1
+ jnz L$ctr32_loop3
+.byte 102,15,56,221,209
+.byte 102,15,56,221,217
+.byte 102,15,56,221,225
+
+ movups (%rdi),%xmm10
+ xorps %xmm10,%xmm2
+ movups %xmm2,(%rsi)
+ cmpq $2,%rdx
+ jb L$ctr32_done
+
+ movups 16(%rdi),%xmm11
+ xorps %xmm11,%xmm3
+ movups %xmm3,16(%rsi)
+ je L$ctr32_done
+
+ movups 32(%rdi),%xmm12
+ xorps %xmm12,%xmm4
+ movups %xmm4,32(%rsi)
+ jmp L$ctr32_done
+
+.p2align 4
+L$ctr32_one_shortcut:
+ movups (%r8),%xmm2
+ movups (%rdi),%xmm10
+ movl 240(%rcx),%eax
+ movups (%rcx),%xmm0
+ movups 16(%rcx),%xmm1
+ leaq 32(%rcx),%rcx
+ xorps %xmm0,%xmm2
+L$oop_enc1_7:
+.byte 102,15,56,220,209
+ decl %eax
+ movups (%rcx),%xmm1
+ leaq 16(%rcx),%rcx
+ jnz L$oop_enc1_7
+.byte 102,15,56,221,209
+ xorps %xmm10,%xmm2
+ movups %xmm2,(%rsi)
+ jmp L$ctr32_done
+
+.p2align 4
+L$ctr32_done:
+ leaq (%rbp),%rsp
+ popq %rbp
+L$ctr32_epilogue:
+ .byte 0xf3,0xc3
+
+.globl _aesni_xts_encrypt
+.private_extern _aesni_xts_encrypt
+
+.p2align 4
+_aesni_xts_encrypt:
+ leaq (%rsp),%rax
+ pushq %rbp
+ subq $112,%rsp
+ andq $-16,%rsp
+ leaq -8(%rax),%rbp
+ movups (%r9),%xmm2
+ movl 240(%r8),%eax
+ movl 240(%rcx),%r10d
+ movups (%r8),%xmm0
+ movups 16(%r8),%xmm1
+ leaq 32(%r8),%r8
+ xorps %xmm0,%xmm2
+L$oop_enc1_8:
+.byte 102,15,56,220,209
+ decl %eax
+ movups (%r8),%xmm1
+ leaq 16(%r8),%r8
+ jnz L$oop_enc1_8
+.byte 102,15,56,221,209
+ movups (%rcx),%xmm0
+ movq %rcx,%r11
+ movl %r10d,%eax
+ shll $4,%r10d
+ movq %rdx,%r9
+ andq $-16,%rdx
+
+ movups 16(%rcx,%r10,1),%xmm1
+
+ movdqa L$xts_magic(%rip),%xmm8
+ movdqa %xmm2,%xmm15
+ pshufd $95,%xmm2,%xmm9
+ pxor %xmm0,%xmm1
+ movdqa %xmm9,%xmm14
+ paddd %xmm9,%xmm9
+ movdqa %xmm15,%xmm10
+ psrad $31,%xmm14
+ paddq %xmm15,%xmm15
+ pand %xmm8,%xmm14
+ pxor %xmm0,%xmm10
+ pxor %xmm14,%xmm15
+ movdqa %xmm9,%xmm14
+ paddd %xmm9,%xmm9
+ movdqa %xmm15,%xmm11
+ psrad $31,%xmm14
+ paddq %xmm15,%xmm15
+ pand %xmm8,%xmm14
+ pxor %xmm0,%xmm11
+ pxor %xmm14,%xmm15
+ movdqa %xmm9,%xmm14
+ paddd %xmm9,%xmm9
+ movdqa %xmm15,%xmm12
+ psrad $31,%xmm14
+ paddq %xmm15,%xmm15
+ pand %xmm8,%xmm14
+ pxor %xmm0,%xmm12
+ pxor %xmm14,%xmm15
+ movdqa %xmm9,%xmm14
+ paddd %xmm9,%xmm9
+ movdqa %xmm15,%xmm13
+ psrad $31,%xmm14
+ paddq %xmm15,%xmm15
+ pand %xmm8,%xmm14
+ pxor %xmm0,%xmm13
+ pxor %xmm14,%xmm15
+ movdqa %xmm15,%xmm14
+ psrad $31,%xmm9
+ paddq %xmm15,%xmm15
+ pand %xmm8,%xmm9
+ pxor %xmm0,%xmm14
+ pxor %xmm9,%xmm15
+ movaps %xmm1,96(%rsp)
+
+ subq $96,%rdx
+ jc L$xts_enc_short
+
+ movl $16+96,%eax
+ leaq 32(%r11,%r10,1),%rcx
+ subq %r10,%rax
+ movups 16(%r11),%xmm1
+ movq %rax,%r10
+ leaq L$xts_magic(%rip),%r8
+ jmp L$xts_enc_grandloop
+
+.p2align 5
+L$xts_enc_grandloop:
+ movdqu 0(%rdi),%xmm2
+ movdqa %xmm0,%xmm8
+ movdqu 16(%rdi),%xmm3
+ pxor %xmm10,%xmm2
+ movdqu 32(%rdi),%xmm4
+ pxor %xmm11,%xmm3
+.byte 102,15,56,220,209
+ movdqu 48(%rdi),%xmm5
+ pxor %xmm12,%xmm4
+.byte 102,15,56,220,217
+ movdqu 64(%rdi),%xmm6
+ pxor %xmm13,%xmm5
+.byte 102,15,56,220,225
+ movdqu 80(%rdi),%xmm7
+ pxor %xmm15,%xmm8
+ movdqa 96(%rsp),%xmm9
+ pxor %xmm14,%xmm6
+.byte 102,15,56,220,233
+ movups 32(%r11),%xmm0
+ leaq 96(%rdi),%rdi
+ pxor %xmm8,%xmm7
+
+ pxor %xmm9,%xmm10
+.byte 102,15,56,220,241
+ pxor %xmm9,%xmm11
+ movdqa %xmm10,0(%rsp)
+.byte 102,15,56,220,249
+ movups 48(%r11),%xmm1
+ pxor %xmm9,%xmm12
+
+.byte 102,15,56,220,208
+ pxor %xmm9,%xmm13
+ movdqa %xmm11,16(%rsp)
+.byte 102,15,56,220,216
+ pxor %xmm9,%xmm14
+ movdqa %xmm12,32(%rsp)
+.byte 102,15,56,220,224
+.byte 102,15,56,220,232
+ pxor %xmm9,%xmm8
+ movdqa %xmm14,64(%rsp)
+.byte 102,15,56,220,240
+.byte 102,15,56,220,248
+ movups 64(%r11),%xmm0
+ movdqa %xmm8,80(%rsp)
+ pshufd $95,%xmm15,%xmm9
+ jmp L$xts_enc_loop6
+.p2align 5
+L$xts_enc_loop6:
+.byte 102,15,56,220,209
+.byte 102,15,56,220,217
+.byte 102,15,56,220,225
+.byte 102,15,56,220,233
+.byte 102,15,56,220,241
+.byte 102,15,56,220,249
+ movups -64(%rcx,%rax,1),%xmm1
+ addq $32,%rax
+
+.byte 102,15,56,220,208
+.byte 102,15,56,220,216
+.byte 102,15,56,220,224
+.byte 102,15,56,220,232
+.byte 102,15,56,220,240
+.byte 102,15,56,220,248
+ movups -80(%rcx,%rax,1),%xmm0
+ jnz L$xts_enc_loop6
+
+ movdqa (%r8),%xmm8
+ movdqa %xmm9,%xmm14
+ paddd %xmm9,%xmm9
+.byte 102,15,56,220,209
+ paddq %xmm15,%xmm15
+ psrad $31,%xmm14
+.byte 102,15,56,220,217
+ pand %xmm8,%xmm14
+ movups (%r11),%xmm10
+.byte 102,15,56,220,225
+.byte 102,15,56,220,233
+.byte 102,15,56,220,241
+ pxor %xmm14,%xmm15
+ movaps %xmm10,%xmm11
+.byte 102,15,56,220,249
+ movups -64(%rcx),%xmm1
+
+ movdqa %xmm9,%xmm14
+.byte 102,15,56,220,208
+ paddd %xmm9,%xmm9
+ pxor %xmm15,%xmm10
+.byte 102,15,56,220,216
+ psrad $31,%xmm14
+ paddq %xmm15,%xmm15
+.byte 102,15,56,220,224
+.byte 102,15,56,220,232
+ pand %xmm8,%xmm14
+ movaps %xmm11,%xmm12
+.byte 102,15,56,220,240
+ pxor %xmm14,%xmm15
+ movdqa %xmm9,%xmm14
+.byte 102,15,56,220,248
+ movups -48(%rcx),%xmm0
+
+ paddd %xmm9,%xmm9
+.byte 102,15,56,220,209
+ pxor %xmm15,%xmm11
+ psrad $31,%xmm14
+.byte 102,15,56,220,217
+ paddq %xmm15,%xmm15
+ pand %xmm8,%xmm14
+.byte 102,15,56,220,225
+.byte 102,15,56,220,233
+ movdqa %xmm13,48(%rsp)
+ pxor %xmm14,%xmm15
+.byte 102,15,56,220,241
+ movaps %xmm12,%xmm13
+ movdqa %xmm9,%xmm14
+.byte 102,15,56,220,249
+ movups -32(%rcx),%xmm1
+
+ paddd %xmm9,%xmm9
+.byte 102,15,56,220,208
+ pxor %xmm15,%xmm12
+ psrad $31,%xmm14
+.byte 102,15,56,220,216
+ paddq %xmm15,%xmm15
+ pand %xmm8,%xmm14
+.byte 102,15,56,220,224
+.byte 102,15,56,220,232
+.byte 102,15,56,220,240
+ pxor %xmm14,%xmm15
+ movaps %xmm13,%xmm14
+.byte 102,15,56,220,248
+
+ movdqa %xmm9,%xmm0
+ paddd %xmm9,%xmm9
+.byte 102,15,56,220,209
+ pxor %xmm15,%xmm13
+ psrad $31,%xmm0
+.byte 102,15,56,220,217
+ paddq %xmm15,%xmm15
+ pand %xmm8,%xmm0
+.byte 102,15,56,220,225
+.byte 102,15,56,220,233
+ pxor %xmm0,%xmm15
+ movups (%r11),%xmm0
+.byte 102,15,56,220,241
+.byte 102,15,56,220,249
+ movups 16(%r11),%xmm1
+
+ pxor %xmm15,%xmm14
+.byte 102,15,56,221,84,36,0
+ psrad $31,%xmm9
+ paddq %xmm15,%xmm15
+.byte 102,15,56,221,92,36,16
+.byte 102,15,56,221,100,36,32
+ pand %xmm8,%xmm9
+ movq %r10,%rax
+.byte 102,15,56,221,108,36,48
+.byte 102,15,56,221,116,36,64
+.byte 102,15,56,221,124,36,80
+ pxor %xmm9,%xmm15
+
+ leaq 96(%rsi),%rsi
+ movups %xmm2,-96(%rsi)
+ movups %xmm3,-80(%rsi)
+ movups %xmm4,-64(%rsi)
+ movups %xmm5,-48(%rsi)
+ movups %xmm6,-32(%rsi)
+ movups %xmm7,-16(%rsi)
+ subq $96,%rdx
+ jnc L$xts_enc_grandloop
+
+ movl $16+96,%eax
+ subl %r10d,%eax
+ movq %r11,%rcx
+ shrl $4,%eax
+
+L$xts_enc_short:
+ movl %eax,%r10d
+ pxor %xmm0,%xmm10
+ addq $96,%rdx
+ jz L$xts_enc_done
+
+ pxor %xmm0,%xmm11
+ cmpq $32,%rdx
+ jb L$xts_enc_one
+ pxor %xmm0,%xmm12
+ je L$xts_enc_two
+
+ pxor %xmm0,%xmm13
+ cmpq $64,%rdx
+ jb L$xts_enc_three
+ pxor %xmm0,%xmm14
+ je L$xts_enc_four
+
+ movdqu (%rdi),%xmm2
+ movdqu 16(%rdi),%xmm3
+ 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:
+.byte 102,15,56,220,209
+ decl %eax
+ movups (%rcx),%xmm1
+ leaq 16(%rcx),%rcx
+ jnz L$oop_enc1_9
+.byte 102,15,56,221,209
+ 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_encrypt2
+
+ 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
+
+ pxor %xmm10,%xmm2
+ movdqa %xmm14,%xmm10
+ pxor %xmm11,%xmm3
+ pxor %xmm12,%xmm4
+ movdqu %xmm2,(%rsi)
+ pxor %xmm13,%xmm5
+ movdqu %xmm3,16(%rsi)
+ movdqu %xmm4,32(%rsi)
+ movdqu %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:
+.byte 102,15,56,220,209
+ decl %eax
+ movups (%rcx),%xmm1
+ leaq 16(%rcx),%rcx
+ jnz L$oop_enc1_10
+.byte 102,15,56,221,209
+ xorps %xmm10,%xmm2
+ movups %xmm2,-16(%rsi)
+
+L$xts_enc_ret:
+ leaq (%rbp),%rsp
+ popq %rbp
+L$xts_enc_epilogue:
+ .byte 0xf3,0xc3
+
+.globl _aesni_xts_decrypt
+.private_extern _aesni_xts_decrypt
+
+.p2align 4
+_aesni_xts_decrypt:
+ leaq (%rsp),%rax
+ pushq %rbp
+ subq $112,%rsp
+ andq $-16,%rsp
+ leaq -8(%rax),%rbp
+ movups (%r9),%xmm2
+ movl 240(%r8),%eax
+ movl 240(%rcx),%r10d
+ movups (%r8),%xmm0
+ movups 16(%r8),%xmm1
+ leaq 32(%r8),%r8
+ xorps %xmm0,%xmm2
+L$oop_enc1_11:
+.byte 102,15,56,220,209
+ decl %eax
+ movups (%r8),%xmm1
+ leaq 16(%r8),%r8
+ jnz L$oop_enc1_11
+.byte 102,15,56,221,209
+ xorl %eax,%eax
+ testq $15,%rdx
+ setnz %al
+ shlq $4,%rax
+ subq %rax,%rdx
+
+ movups (%rcx),%xmm0
+ movq %rcx,%r11
+ movl %r10d,%eax
+ shll $4,%r10d
+ movq %rdx,%r9
+ andq $-16,%rdx
+
+ movups 16(%rcx,%r10,1),%xmm1
+
+ movdqa L$xts_magic(%rip),%xmm8
+ movdqa %xmm2,%xmm15
+ pshufd $95,%xmm2,%xmm9
+ pxor %xmm0,%xmm1
+ movdqa %xmm9,%xmm14
+ paddd %xmm9,%xmm9
+ movdqa %xmm15,%xmm10
+ psrad $31,%xmm14
+ paddq %xmm15,%xmm15
+ pand %xmm8,%xmm14
+ pxor %xmm0,%xmm10
+ pxor %xmm14,%xmm15
+ movdqa %xmm9,%xmm14
+ paddd %xmm9,%xmm9
+ movdqa %xmm15,%xmm11
+ psrad $31,%xmm14
+ paddq %xmm15,%xmm15
+ pand %xmm8,%xmm14
+ pxor %xmm0,%xmm11
+ pxor %xmm14,%xmm15
+ movdqa %xmm9,%xmm14
+ paddd %xmm9,%xmm9
+ movdqa %xmm15,%xmm12
+ psrad $31,%xmm14
+ paddq %xmm15,%xmm15
+ pand %xmm8,%xmm14
+ pxor %xmm0,%xmm12
+ pxor %xmm14,%xmm15
+ movdqa %xmm9,%xmm14
+ paddd %xmm9,%xmm9
+ movdqa %xmm15,%xmm13
+ psrad $31,%xmm14
+ paddq %xmm15,%xmm15
+ pand %xmm8,%xmm14
+ pxor %xmm0,%xmm13
+ pxor %xmm14,%xmm15
+ movdqa %xmm15,%xmm14
+ psrad $31,%xmm9
+ paddq %xmm15,%xmm15
+ pand %xmm8,%xmm9
+ pxor %xmm0,%xmm14
+ pxor %xmm9,%xmm15
+ movaps %xmm1,96(%rsp)
+
+ subq $96,%rdx
+ jc L$xts_dec_short
+
+ movl $16+96,%eax
+ leaq 32(%r11,%r10,1),%rcx
+ subq %r10,%rax
+ movups 16(%r11),%xmm1
+ movq %rax,%r10
+ leaq L$xts_magic(%rip),%r8
+ jmp L$xts_dec_grandloop
+
+.p2align 5
+L$xts_dec_grandloop:
+ movdqu 0(%rdi),%xmm2
+ movdqa %xmm0,%xmm8
+ movdqu 16(%rdi),%xmm3
+ pxor %xmm10,%xmm2
+ movdqu 32(%rdi),%xmm4
+ pxor %xmm11,%xmm3
+.byte 102,15,56,222,209
+ movdqu 48(%rdi),%xmm5
+ pxor %xmm12,%xmm4
+.byte 102,15,56,222,217
+ movdqu 64(%rdi),%xmm6
+ pxor %xmm13,%xmm5
+.byte 102,15,56,222,225
+ movdqu 80(%rdi),%xmm7
+ pxor %xmm15,%xmm8
+ movdqa 96(%rsp),%xmm9
+ pxor %xmm14,%xmm6
+.byte 102,15,56,222,233
+ movups 32(%r11),%xmm0
+ leaq 96(%rdi),%rdi
+ pxor %xmm8,%xmm7
+
+ pxor %xmm9,%xmm10
+.byte 102,15,56,222,241
+ pxor %xmm9,%xmm11
+ movdqa %xmm10,0(%rsp)
+.byte 102,15,56,222,249
+ movups 48(%r11),%xmm1
+ pxor %xmm9,%xmm12
+
+.byte 102,15,56,222,208
+ pxor %xmm9,%xmm13
+ movdqa %xmm11,16(%rsp)
+.byte 102,15,56,222,216
+ pxor %xmm9,%xmm14
+ movdqa %xmm12,32(%rsp)
+.byte 102,15,56,222,224
+.byte 102,15,56,222,232
+ pxor %xmm9,%xmm8
+ movdqa %xmm14,64(%rsp)
+.byte 102,15,56,222,240
+.byte 102,15,56,222,248
+ movups 64(%r11),%xmm0
+ movdqa %xmm8,80(%rsp)
+ pshufd $95,%xmm15,%xmm9
+ jmp L$xts_dec_loop6
+.p2align 5
+L$xts_dec_loop6:
+.byte 102,15,56,222,209
+.byte 102,15,56,222,217
+.byte 102,15,56,222,225
+.byte 102,15,56,222,233
+.byte 102,15,56,222,241
+.byte 102,15,56,222,249
+ movups -64(%rcx,%rax,1),%xmm1
+ addq $32,%rax
+
+.byte 102,15,56,222,208
+.byte 102,15,56,222,216
+.byte 102,15,56,222,224
+.byte 102,15,56,222,232
+.byte 102,15,56,222,240
+.byte 102,15,56,222,248
+ movups -80(%rcx,%rax,1),%xmm0
+ jnz L$xts_dec_loop6
+
+ movdqa (%r8),%xmm8
+ movdqa %xmm9,%xmm14
+ paddd %xmm9,%xmm9
+.byte 102,15,56,222,209
+ paddq %xmm15,%xmm15
+ psrad $31,%xmm14
+.byte 102,15,56,222,217
+ pand %xmm8,%xmm14
+ movups (%r11),%xmm10
+.byte 102,15,56,222,225
+.byte 102,15,56,222,233
+.byte 102,15,56,222,241
+ pxor %xmm14,%xmm15
+ movaps %xmm10,%xmm11
+.byte 102,15,56,222,249
+ movups -64(%rcx),%xmm1
+
+ movdqa %xmm9,%xmm14
+.byte 102,15,56,222,208
+ paddd %xmm9,%xmm9
+ pxor %xmm15,%xmm10
+.byte 102,15,56,222,216
+ psrad $31,%xmm14
+ paddq %xmm15,%xmm15
+.byte 102,15,56,222,224
+.byte 102,15,56,222,232
+ pand %xmm8,%xmm14
+ movaps %xmm11,%xmm12
+.byte 102,15,56,222,240
+ pxor %xmm14,%xmm15
+ movdqa %xmm9,%xmm14
+.byte 102,15,56,222,248
+ movups -48(%rcx),%xmm0
+
+ paddd %xmm9,%xmm9
+.byte 102,15,56,222,209
+ pxor %xmm15,%xmm11
+ psrad $31,%xmm14
+.byte 102,15,56,222,217
+ paddq %xmm15,%xmm15
+ pand %xmm8,%xmm14
+.byte 102,15,56,222,225
+.byte 102,15,56,222,233
+ movdqa %xmm13,48(%rsp)
+ pxor %xmm14,%xmm15
+.byte 102,15,56,222,241
+ movaps %xmm12,%xmm13
+ movdqa %xmm9,%xmm14
+.byte 102,15,56,222,249
+ movups -32(%rcx),%xmm1
+
+ paddd %xmm9,%xmm9
+.byte 102,15,56,222,208
+ pxor %xmm15,%xmm12
+ psrad $31,%xmm14
+.byte 102,15,56,222,216
+ paddq %xmm15,%xmm15
+ pand %xmm8,%xmm14
+.byte 102,15,56,222,224
+.byte 102,15,56,222,232
+.byte 102,15,56,222,240
+ pxor %xmm14,%xmm15
+ movaps %xmm13,%xmm14
+.byte 102,15,56,222,248
+
+ movdqa %xmm9,%xmm0
+ paddd %xmm9,%xmm9
+.byte 102,15,56,222,209
+ pxor %xmm15,%xmm13
+ psrad $31,%xmm0
+.byte 102,15,56,222,217
+ paddq %xmm15,%xmm15
+ pand %xmm8,%xmm0
+.byte 102,15,56,222,225
+.byte 102,15,56,222,233
+ pxor %xmm0,%xmm15
+ movups (%r11),%xmm0
+.byte 102,15,56,222,241
+.byte 102,15,56,222,249
+ movups 16(%r11),%xmm1
+
+ pxor %xmm15,%xmm14
+.byte 102,15,56,223,84,36,0
+ psrad $31,%xmm9
+ paddq %xmm15,%xmm15
+.byte 102,15,56,223,92,36,16
+.byte 102,15,56,223,100,36,32
+ pand %xmm8,%xmm9
+ movq %r10,%rax
+.byte 102,15,56,223,108,36,48
+.byte 102,15,56,223,116,36,64
+.byte 102,15,56,223,124,36,80
+ pxor %xmm9,%xmm15
+
+ leaq 96(%rsi),%rsi
+ movups %xmm2,-96(%rsi)
+ movups %xmm3,-80(%rsi)
+ movups %xmm4,-64(%rsi)
+ movups %xmm5,-48(%rsi)
+ movups %xmm6,-32(%rsi)
+ movups %xmm7,-16(%rsi)
+ subq $96,%rdx
+ jnc L$xts_dec_grandloop
+
+ movl $16+96,%eax
+ subl %r10d,%eax
+ movq %r11,%rcx
+ shrl $4,%eax
+
+L$xts_dec_short:
+ movl %eax,%r10d
+ pxor %xmm0,%xmm10
+ pxor %xmm0,%xmm11
+ addq $96,%rdx
+ jz L$xts_dec_done
+
+ pxor %xmm0,%xmm12
+ cmpq $32,%rdx
+ jb L$xts_dec_one
+ pxor %xmm0,%xmm13
+ je L$xts_dec_two
+
+ pxor %xmm0,%xmm14
+ cmpq $64,%rdx
+ jb L$xts_dec_three
+ je L$xts_dec_four
+
+ movdqu (%rdi),%xmm2
+ movdqu 16(%rdi),%xmm3
+ 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:
+.byte 102,15,56,222,209
+ decl %eax
+ movups (%rcx),%xmm1
+ leaq 16(%rcx),%rcx
+ jnz L$oop_dec1_12
+.byte 102,15,56,223,209
+ 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_decrypt2
+
+ 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 %xmm14,%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:
+ 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_decrypt4
+
+ pxor %xmm10,%xmm2
+ movdqa %xmm14,%xmm10
+ pxor %xmm11,%xmm3
+ movdqa %xmm15,%xmm11
+ pxor %xmm12,%xmm4
+ movdqu %xmm2,(%rsi)
+ pxor %xmm13,%xmm5
+ movdqu %xmm3,16(%rsi)
+ movdqu %xmm4,32(%rsi)
+ movdqu %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:
+.byte 102,15,56,222,209
+ decl %eax
+ movups (%rcx),%xmm1
+ leaq 16(%rcx),%rcx
+ jnz L$oop_dec1_13
+.byte 102,15,56,223,209
+ 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:
+.byte 102,15,56,222,209
+ decl %eax
+ movups (%rcx),%xmm1
+ leaq 16(%rcx),%rcx
+ jnz L$oop_dec1_14
+.byte 102,15,56,223,209
+ xorps %xmm10,%xmm2
+ movups %xmm2,(%rsi)
+
+L$xts_dec_ret:
+ leaq (%rbp),%rsp
+ popq %rbp
+L$xts_dec_epilogue:
+ .byte 0xf3,0xc3
+
+.globl _aesni_cbc_encrypt
+.private_extern _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:
+.byte 102,15,56,220,209
+ decl %eax
+ movups (%rcx),%xmm1
+ leaq 16(%rcx),%rcx
+ jnz L$oop_enc1_15
+.byte 102,15,56,221,209
+ 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
+ andq $-16,%rsp
+ leaq -8(%rax),%rbp
+ movups (%r8),%xmm10
+ movl %r10d,%eax
+ cmpq $80,%rdx
+ jbe L$cbc_dec_tail
+
+ movups (%rcx),%xmm0
+ movdqu 0(%rdi),%xmm2
+ movdqu 16(%rdi),%xmm3
+ movdqa %xmm2,%xmm11
+ movdqu 32(%rdi),%xmm4
+ movdqa %xmm3,%xmm12
+ movdqu 48(%rdi),%xmm5
+ movdqa %xmm4,%xmm13
+ movdqu 64(%rdi),%xmm6
+ movdqa %xmm5,%xmm14
+ movdqu 80(%rdi),%xmm7
+ movdqa %xmm6,%xmm15
+ movl _OPENSSL_ia32cap_P+4(%rip),%r9d
+ cmpq $112,%rdx
+ jbe L$cbc_dec_six_or_seven
+
+ andl $71303168,%r9d
+ subq $80,%rdx
+ cmpl $4194304,%r9d
+ je L$cbc_dec_loop6_enter
+ subq $32,%rdx
+ leaq 112(%rcx),%rcx
+ jmp L$cbc_dec_loop8_enter
+.p2align 4
+L$cbc_dec_loop8:
+ movups %xmm9,(%rsi)
+ leaq 16(%rsi),%rsi
+L$cbc_dec_loop8_enter:
+ movdqu 96(%rdi),%xmm8
+ pxor %xmm0,%xmm2
+ movdqu 112(%rdi),%xmm9
+ pxor %xmm0,%xmm3
+ movups 16-112(%rcx),%xmm1
+ pxor %xmm0,%xmm4
+ xorq %r11,%r11
+ cmpq $112,%rdx
+ pxor %xmm0,%xmm5
+ pxor %xmm0,%xmm6
+ pxor %xmm0,%xmm7
+ pxor %xmm0,%xmm8
+
+.byte 102,15,56,222,209
+ pxor %xmm0,%xmm9
+ movups 32-112(%rcx),%xmm0
+.byte 102,15,56,222,217
+.byte 102,15,56,222,225
+.byte 102,15,56,222,233
+.byte 102,15,56,222,241
+.byte 102,15,56,222,249
+.byte 102,68,15,56,222,193
+ setnc %r11b
+ shlq $7,%r11
+.byte 102,68,15,56,222,201
+ addq %rdi,%r11
+ movups 48-112(%rcx),%xmm1
+.byte 102,15,56,222,208
+.byte 102,15,56,222,216
+.byte 102,15,56,222,224
+.byte 102,15,56,222,232
+.byte 102,15,56,222,240
+.byte 102,15,56,222,248
+.byte 102,68,15,56,222,192
+.byte 102,68,15,56,222,200
+ movups 64-112(%rcx),%xmm0
+ nop
+.byte 102,15,56,222,209
+.byte 102,15,56,222,217
+.byte 102,15,56,222,225
+.byte 102,15,56,222,233
+.byte 102,15,56,222,241
+.byte 102,15,56,222,249
+.byte 102,68,15,56,222,193
+.byte 102,68,15,56,222,201
+ movups 80-112(%rcx),%xmm1
+ nop
+.byte 102,15,56,222,208
+.byte 102,15,56,222,216
+.byte 102,15,56,222,224
+.byte 102,15,56,222,232
+.byte 102,15,56,222,240
+.byte 102,15,56,222,248
+.byte 102,68,15,56,222,192
+.byte 102,68,15,56,222,200
+ movups 96-112(%rcx),%xmm0
+ nop
+.byte 102,15,56,222,209
+.byte 102,15,56,222,217
+.byte 102,15,56,222,225
+.byte 102,15,56,222,233
+.byte 102,15,56,222,241
+.byte 102,15,56,222,249
+.byte 102,68,15,56,222,193
+.byte 102,68,15,56,222,201
+ movups 112-112(%rcx),%xmm1
+ nop
+.byte 102,15,56,222,208
+.byte 102,15,56,222,216
+.byte 102,15,56,222,224
+.byte 102,15,56,222,232
+.byte 102,15,56,222,240
+.byte 102,15,56,222,248
+.byte 102,68,15,56,222,192
+.byte 102,68,15,56,222,200
+ movups 128-112(%rcx),%xmm0
+ nop
+.byte 102,15,56,222,209
+.byte 102,15,56,222,217
+.byte 102,15,56,222,225
+.byte 102,15,56,222,233
+.byte 102,15,56,222,241
+.byte 102,15,56,222,249
+.byte 102,68,15,56,222,193
+.byte 102,68,15,56,222,201
+ movups 144-112(%rcx),%xmm1
+ cmpl $11,%eax
+.byte 102,15,56,222,208
+.byte 102,15,56,222,216
+.byte 102,15,56,222,224
+.byte 102,15,56,222,232
+.byte 102,15,56,222,240
+.byte 102,15,56,222,248
+.byte 102,68,15,56,222,192
+.byte 102,68,15,56,222,200
+ movups 160-112(%rcx),%xmm0
+ jb L$cbc_dec_done
+.byte 102,15,56,222,209
+.byte 102,15,56,222,217
+.byte 102,15,56,222,225
+.byte 102,15,56,222,233
+.byte 102,15,56,222,241
+.byte 102,15,56,222,249
+.byte 102,68,15,56,222,193
+.byte 102,68,15,56,222,201
+ movups 176-112(%rcx),%xmm1
+ nop
+.byte 102,15,56,222,208
+.byte 102,15,56,222,216
+.byte 102,15,56,222,224
+.byte 102,15,56,222,232
+.byte 102,15,56,222,240
+.byte 102,15,56,222,248
+.byte 102,68,15,56,222,192
+.byte 102,68,15,56,222,200
+ movups 192-112(%rcx),%xmm0
+ je L$cbc_dec_done
+.byte 102,15,56,222,209
+.byte 102,15,56,222,217
+.byte 102,15,56,222,225
+.byte 102,15,56,222,233
+.byte 102,15,56,222,241
+.byte 102,15,56,222,249
+.byte 102,68,15,56,222,193
+.byte 102,68,15,56,222,201
+ movups 208-112(%rcx),%xmm1
+ nop
+.byte 102,15,56,222,208
+.byte 102,15,56,222,216
+.byte 102,15,56,222,224
+.byte 102,15,56,222,232
+.byte 102,15,56,222,240
+.byte 102,15,56,222,248
+.byte 102,68,15,56,222,192
+.byte 102,68,15,56,222,200
+ movups 224-112(%rcx),%xmm0
+ jmp L$cbc_dec_done
+.p2align 4
+L$cbc_dec_done:
+.byte 102,15,56,222,209
+.byte 102,15,56,222,217
+ pxor %xmm0,%xmm10
+ pxor %xmm0,%xmm11
+.byte 102,15,56,222,225
+.byte 102,15,56,222,233
+ pxor %xmm0,%xmm12
+ pxor %xmm0,%xmm13
+.byte 102,15,56,222,241
+.byte 102,15,56,222,249
+ pxor %xmm0,%xmm14
+ pxor %xmm0,%xmm15
+.byte 102,68,15,56,222,193
+.byte 102,68,15,56,222,201
+ movdqu 80(%rdi),%xmm1
+
+.byte 102,65,15,56,223,210
+ movdqu 96(%rdi),%xmm10
+ pxor %xmm0,%xmm1
+.byte 102,65,15,56,223,219
+ pxor %xmm0,%xmm10
+ movdqu 112(%rdi),%xmm0
+.byte 102,65,15,56,223,228
+ leaq 128(%rdi),%rdi
+ movdqu 0(%r11),%xmm11
+.byte 102,65,15,56,223,237
+.byte 102,65,15,56,223,246
+ movdqu 16(%r11),%xmm12
+ movdqu 32(%r11),%xmm13
+.byte 102,65,15,56,223,255
+.byte 102,68,15,56,223,193
+ movdqu 48(%r11),%xmm14
+ movdqu 64(%r11),%xmm15
+.byte 102,69,15,56,223,202
+ movdqa %xmm0,%xmm10
+ movdqu 80(%r11),%xmm1
+ movups -112(%rcx),%xmm0
+
+ movups %xmm2,(%rsi)
+ movdqa %xmm11,%xmm2
+ movups %xmm3,16(%rsi)
+ movdqa %xmm12,%xmm3
+ movups %xmm4,32(%rsi)
+ movdqa %xmm13,%xmm4
+ movups %xmm5,48(%rsi)
+ movdqa %xmm14,%xmm5
+ movups %xmm6,64(%rsi)
+ movdqa %xmm15,%xmm6
+ movups %xmm7,80(%rsi)
+ movdqa %xmm1,%xmm7
+ movups %xmm8,96(%rsi)
+ leaq 112(%rsi),%rsi
+
+ subq $128,%rdx
+ ja L$cbc_dec_loop8
+
+ movaps %xmm9,%xmm2
+ leaq -112(%rcx),%rcx
+ addq $112,%rdx
+ jle L$cbc_dec_tail_collected
+ movups %xmm9,(%rsi)
+ leaq 16(%rsi),%rsi
+ cmpq $80,%rdx
+ jbe L$cbc_dec_tail
+
+ movaps %xmm11,%xmm2
+L$cbc_dec_six_or_seven:
+ cmpq $96,%rdx
+ ja L$cbc_dec_seven
+
+ movaps %xmm7,%xmm8
+ call _aesni_decrypt6
+ pxor %xmm10,%xmm2
+ movaps %xmm8,%xmm10
+ pxor %xmm11,%xmm3
+ movdqu %xmm2,(%rsi)
+ pxor %xmm12,%xmm4
+ movdqu %xmm3,16(%rsi)
+ pxor %xmm13,%xmm5
+ movdqu %xmm4,32(%rsi)
+ pxor %xmm14,%xmm6
+ movdqu %xmm5,48(%rsi)
+ pxor %xmm15,%xmm7
+ movdqu %xmm6,64(%rsi)
+ leaq 80(%rsi),%rsi
+ movdqa %xmm7,%xmm2
+ jmp L$cbc_dec_tail_collected
+
+.p2align 4
+L$cbc_dec_seven:
+ movups 96(%rdi),%xmm8
+ xorps %xmm9,%xmm9
+ call _aesni_decrypt8
+ movups 80(%rdi),%xmm9
+ pxor %xmm10,%xmm2
+ movups 96(%rdi),%xmm10
+ pxor %xmm11,%xmm3
+ movdqu %xmm2,(%rsi)
+ pxor %xmm12,%xmm4
+ movdqu %xmm3,16(%rsi)
+ pxor %xmm13,%xmm5
+ movdqu %xmm4,32(%rsi)
+ pxor %xmm14,%xmm6
+ movdqu %xmm5,48(%rsi)
+ pxor %xmm15,%xmm7
+ movdqu %xmm6,64(%rsi)
+ pxor %xmm9,%xmm8
+ movdqu %xmm7,80(%rsi)
+ leaq 96(%rsi),%rsi
+ movdqa %xmm8,%xmm2
+ jmp L$cbc_dec_tail_collected
+
+.p2align 4
+L$cbc_dec_loop6:
+ movups %xmm7,(%rsi)
+ leaq 16(%rsi),%rsi
+ movdqu 0(%rdi),%xmm2
+ movdqu 16(%rdi),%xmm3
+ movdqa %xmm2,%xmm11
+ movdqu 32(%rdi),%xmm4
+ movdqa %xmm3,%xmm12
+ movdqu 48(%rdi),%xmm5
+ movdqa %xmm4,%xmm13
+ movdqu 64(%rdi),%xmm6
+ movdqa %xmm5,%xmm14
+ movdqu 80(%rdi),%xmm7
+ movdqa %xmm6,%xmm15
+L$cbc_dec_loop6_enter:
+ leaq 96(%rdi),%rdi
+ movdqa %xmm7,%xmm8
+
+ call _aesni_decrypt6
+
+ pxor %xmm10,%xmm2
+ movdqa %xmm8,%xmm10
+ pxor %xmm11,%xmm3
+ movdqu %xmm2,(%rsi)
+ pxor %xmm12,%xmm4
+ movdqu %xmm3,16(%rsi)
+ pxor %xmm13,%xmm5
+ movdqu %xmm4,32(%rsi)
+ pxor %xmm14,%xmm6
+ movq %r11,%rcx
+ movdqu %xmm5,48(%rsi)
+ pxor %xmm15,%xmm7
+ movl %r10d,%eax
+ movdqu %xmm6,64(%rsi)
+ leaq 80(%rsi),%rsi
+ subq $96,%rdx
+ ja L$cbc_dec_loop6
+
+ movdqa %xmm7,%xmm2
+ addq $80,%rdx
+ jle L$cbc_dec_tail_collected
+ movups %xmm7,(%rsi)
+ leaq 16(%rsi),%rsi
+
+L$cbc_dec_tail:
+ movups (%rdi),%xmm2
+ subq $16,%rdx
+ jbe L$cbc_dec_one
+
+ movups 16(%rdi),%xmm3
+ movaps %xmm2,%xmm11
+ subq $16,%rdx
+ jbe L$cbc_dec_two
+
+ movups 32(%rdi),%xmm4
+ movaps %xmm3,%xmm12
+ subq $16,%rdx
+ jbe L$cbc_dec_three
+
+ movups 48(%rdi),%xmm5
+ movaps %xmm4,%xmm13
+ subq $16,%rdx
+ jbe L$cbc_dec_four
+
+ movups 64(%rdi),%xmm6
+ movaps %xmm5,%xmm14
+ movaps %xmm6,%xmm15
+ xorps %xmm7,%xmm7
+ call _aesni_decrypt6
+ pxor %xmm10,%xmm2
+ movaps %xmm15,%xmm10
+ pxor %xmm11,%xmm3
+ movdqu %xmm2,(%rsi)
+ pxor %xmm12,%xmm4
+ movdqu %xmm3,16(%rsi)
+ pxor %xmm13,%xmm5
+ movdqu %xmm4,32(%rsi)
+ pxor %xmm14,%xmm6
+ movdqu %xmm5,48(%rsi)
+ leaq 64(%rsi),%rsi
+ movdqa %xmm6,%xmm2
+ subq $16,%rdx
+ jmp L$cbc_dec_tail_collected
+
+.p2align 4
+L$cbc_dec_one:
+ movaps %xmm2,%xmm11
+ movups (%rcx),%xmm0
+ movups 16(%rcx),%xmm1
+ leaq 32(%rcx),%rcx
+ xorps %xmm0,%xmm2
+L$oop_dec1_16:
+.byte 102,15,56,222,209
+ decl %eax
+ movups (%rcx),%xmm1
+ leaq 16(%rcx),%rcx
+ jnz L$oop_dec1_16
+.byte 102,15,56,223,209
+ xorps %xmm10,%xmm2
+ movaps %xmm11,%xmm10
+ jmp L$cbc_dec_tail_collected
+.p2align 4
+L$cbc_dec_two:
+ movaps %xmm3,%xmm12
+ call _aesni_decrypt2
+ pxor %xmm10,%xmm2
+ movaps %xmm12,%xmm10
+ pxor %xmm11,%xmm3
+ movdqu %xmm2,(%rsi)
+ movdqa %xmm3,%xmm2
+ leaq 16(%rsi),%rsi
+ jmp L$cbc_dec_tail_collected
+.p2align 4
+L$cbc_dec_three:
+ movaps %xmm4,%xmm13
+ call _aesni_decrypt3
+ pxor %xmm10,%xmm2
+ movaps %xmm13,%xmm10
+ pxor %xmm11,%xmm3
+ movdqu %xmm2,(%rsi)
+ pxor %xmm12,%xmm4
+ movdqu %xmm3,16(%rsi)
+ movdqa %xmm4,%xmm2
+ leaq 32(%rsi),%rsi
+ jmp L$cbc_dec_tail_collected
+.p2align 4
+L$cbc_dec_four:
+ movaps %xmm5,%xmm14
+ call _aesni_decrypt4
+ pxor %xmm10,%xmm2
+ movaps %xmm14,%xmm10
+ pxor %xmm11,%xmm3
+ movdqu %xmm2,(%rsi)
+ pxor %xmm12,%xmm4
+ movdqu %xmm3,16(%rsi)
+ pxor %xmm13,%xmm5
+ movdqu %xmm4,32(%rsi)
+ movdqa %xmm5,%xmm2
+ leaq 48(%rsi),%rsi
+ jmp L$cbc_dec_tail_collected
+
+.p2align 4
+L$cbc_dec_tail_collected:
+ movups %xmm10,(%r8)
+ andq $15,%rdx
+ 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:
+ .byte 0xf3,0xc3
+
+.globl _aesni_set_decrypt_key
+.private_extern _aesni_set_decrypt_key
+
+.p2align 4
+_aesni_set_decrypt_key:
+.byte 0x48,0x83,0xEC,0x08
+ 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
+.byte 102,15,56,219,192
+.byte 102,15,56,219,201
+ 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
+.byte 102,15,56,219,192
+ movups %xmm0,(%rdi)
+L$dec_key_ret:
+ addq $8,%rsp
+ .byte 0xf3,0xc3
+L$SEH_end_set_decrypt_key:
+
+.globl _aesni_set_encrypt_key
+.private_extern _aesni_set_encrypt_key
+
+.p2align 4
+_aesni_set_encrypt_key:
+__aesni_set_encrypt_key:
+.byte 0x48,0x83,0xEC,0x08
+ 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)
+.byte 102,15,58,223,200,1
+ call L$key_expansion_128_cold
+.byte 102,15,58,223,200,2
+ call L$key_expansion_128
+.byte 102,15,58,223,200,4
+ call L$key_expansion_128
+.byte 102,15,58,223,200,8
+ call L$key_expansion_128
+.byte 102,15,58,223,200,16
+ call L$key_expansion_128
+.byte 102,15,58,223,200,32
+ call L$key_expansion_128
+.byte 102,15,58,223,200,64
+ call L$key_expansion_128
+.byte 102,15,58,223,200,128
+ call L$key_expansion_128
+.byte 102,15,58,223,200,27
+ call L$key_expansion_128
+.byte 102,15,58,223,200,54
+ 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)
+.byte 102,15,58,223,202,1
+ call L$key_expansion_192a_cold
+.byte 102,15,58,223,202,2
+ call L$key_expansion_192b
+.byte 102,15,58,223,202,4
+ call L$key_expansion_192a
+.byte 102,15,58,223,202,8
+ call L$key_expansion_192b
+.byte 102,15,58,223,202,16
+ call L$key_expansion_192a
+.byte 102,15,58,223,202,32
+ call L$key_expansion_192b
+.byte 102,15,58,223,202,64
+ call L$key_expansion_192a
+.byte 102,15,58,223,202,128
+ 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)
+.byte 102,15,58,223,202,1
+ call L$key_expansion_256a_cold
+.byte 102,15,58,223,200,1
+ call L$key_expansion_256b
+.byte 102,15,58,223,202,2
+ call L$key_expansion_256a
+.byte 102,15,58,223,200,2
+ call L$key_expansion_256b
+.byte 102,15,58,223,202,4
+ call L$key_expansion_256a
+.byte 102,15,58,223,200,4
+ call L$key_expansion_256b
+.byte 102,15,58,223,202,8
+ call L$key_expansion_256a
+.byte 102,15,58,223,200,8
+ call L$key_expansion_256b
+.byte 102,15,58,223,202,16
+ call L$key_expansion_256a
+.byte 102,15,58,223,200,16
+ call L$key_expansion_256b
+.byte 102,15,58,223,202,32
+ call L$key_expansion_256a
+.byte 102,15,58,223,200,32
+ call L$key_expansion_256b
+.byte 102,15,58,223,202,64
+ 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
+ .byte 0xf3,0xc3
+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
+ .byte 0xf3,0xc3
+
+.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
+ .byte 0xf3,0xc3
+
+.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
+ .byte 0xf3,0xc3
+
+.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
+ .byte 0xf3,0xc3
+
+
+.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
+L$increment1:
+.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
+
+.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
+#endif
diff --git a/mac-x86_64/crypto/aes/bsaes-x86_64.S b/mac-x86_64/crypto/aes/bsaes-x86_64.S
new file mode 100644
index 0000000..c2d0477
--- /dev/null
+++ b/mac-x86_64/crypto/aes/bsaes-x86_64.S
@@ -0,0 +1,2504 @@
+#if defined(__x86_64__)
+.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
+ pxor %xmm8,%xmm1
+ pxor %xmm8,%xmm2
+.byte 102,68,15,56,0,255
+.byte 102,15,56,0,199
+ pxor %xmm8,%xmm3
+ pxor %xmm8,%xmm4
+.byte 102,15,56,0,207
+.byte 102,15,56,0,215
+ pxor %xmm8,%xmm5
+ pxor %xmm8,%xmm6
+.byte 102,15,56,0,223
+.byte 102,15,56,0,231
+.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
+ pxor 32(%rax),%xmm1
+ pxor 48(%rax),%xmm2
+.byte 102,68,15,56,0,255
+.byte 102,15,56,0,199
+ pxor 64(%rax),%xmm3
+ pxor 80(%rax),%xmm4
+.byte 102,15,56,0,207
+.byte 102,15,56,0,215
+ pxor 96(%rax),%xmm5
+ pxor 112(%rax),%xmm6
+.byte 102,15,56,0,223
+.byte 102,15,56,0,231
+.byte 102,15,56,0,239
+.byte 102,15,56,0,247
+ leaq 128(%rax),%rax
+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
+ .byte 0xf3,0xc3
+
+
+
+.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
+ pxor %xmm8,%xmm1
+ pxor %xmm8,%xmm2
+.byte 102,68,15,56,0,255
+.byte 102,15,56,0,199
+ pxor %xmm8,%xmm3
+ pxor %xmm8,%xmm4
+.byte 102,15,56,0,207
+.byte 102,15,56,0,215
+ pxor %xmm8,%xmm5
+ pxor %xmm8,%xmm6
+.byte 102,15,56,0,223
+.byte 102,15,56,0,231
+.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
+ pxor 32(%rax),%xmm1
+ pxor 48(%rax),%xmm2
+.byte 102,68,15,56,0,255
+.byte 102,15,56,0,199
+ pxor 64(%rax),%xmm3
+ pxor 80(%rax),%xmm4
+.byte 102,15,56,0,207
+.byte 102,15,56,0,215
+ pxor 96(%rax),%xmm5
+ pxor 112(%rax),%xmm6
+.byte 102,15,56,0,223
+.byte 102,15,56,0,231
+.byte 102,15,56,0,239
+.byte 102,15,56,0,247
+ leaq 128(%rax),%rax
+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
+ .byte 0xf3,0xc3
+
+
+.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
+
+ .byte 0xf3,0xc3
+
+
+.globl _bsaes_cbc_encrypt
+.private_extern _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:
+ .byte 0xf3,0xc3
+
+
+.globl _bsaes_ctr32_encrypt_blocks
+.private_extern _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
+ pxor %xmm8,%xmm1
+ pxor %xmm8,%xmm2
+.byte 102,68,15,56,0,255
+.byte 102,15,56,0,199
+ pxor %xmm8,%xmm3
+ pxor %xmm8,%xmm4
+.byte 102,15,56,0,207
+.byte 102,15,56,0,215
+ pxor %xmm8,%xmm5
+ pxor %xmm8,%xmm6
+.byte 102,15,56,0,223
+.byte 102,15,56,0,231
+.byte 102,15,56,0,239
+.byte 102,15,56,0,247
+ leaq L$BS0(%rip),%r11
+ 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:
+ .byte 0xf3,0xc3
+
+.globl _bsaes_xts_encrypt
+.private_extern _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:
+ .byte 0xf3,0xc3
+
+
+.globl _bsaes_xts_decrypt
+.private_extern _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:
+ .byte 0xf3,0xc3
+
+
+.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
+
+#endif
diff --git a/mac-x86_64/crypto/aes/vpaes-x86_64.S b/mac-x86_64/crypto/aes/vpaes-x86_64.S
new file mode 100644
index 0000000..711ea43
--- /dev/null
+++ b/mac-x86_64/crypto/aes/vpaes-x86_64.S
@@ -0,0 +1,834 @@
+#if defined(__x86_64__)
+.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
+ addq $16,%r9
+ pxor %xmm2,%xmm0
+ leaq L$k_mc_backward(%rip),%r10
+ jmp L$enc_entry
+
+.p2align 4
+L$enc_loop:
+
+ movdqa %xmm13,%xmm4
+ movdqa %xmm12,%xmm0
+.byte 102,15,56,0,226
+.byte 102,15,56,0,195
+ pxor %xmm5,%xmm4
+ movdqa %xmm15,%xmm5
+ pxor %xmm4,%xmm0
+ movdqa -64(%r11,%r10,1),%xmm1
+.byte 102,15,56,0,234
+ movdqa (%r11,%r10,1),%xmm4
+ movdqa %xmm14,%xmm2
+.byte 102,15,56,0,211
+ movdqa %xmm0,%xmm3
+ pxor %xmm5,%xmm2
+.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
+ subq $1,%rax
+ pxor %xmm3,%xmm0
+
+L$enc_entry:
+
+ movdqa %xmm9,%xmm1
+ movdqa %xmm11,%xmm5
+ pandn %xmm0,%xmm1
+ psrld $4,%xmm1
+ pand %xmm9,%xmm0
+.byte 102,15,56,0,232
+ movdqa %xmm10,%xmm3
+ pxor %xmm1,%xmm0
+.byte 102,15,56,0,217
+ movdqa %xmm10,%xmm4
+ pxor %xmm5,%xmm3
+.byte 102,15,56,0,224
+ movdqa %xmm10,%xmm2
+ pxor %xmm5,%xmm4
+.byte 102,15,56,0,211
+ movdqa %xmm10,%xmm3
+ pxor %xmm0,%xmm2
+.byte 102,15,56,0,220
+ movdqu (%r9),%xmm5
+ 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
+ .byte 0xf3,0xc3
+
+
+
+
+
+
+
+
+.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
+ movdqa -16(%r10),%xmm1
+.byte 102,15,56,0,226
+.byte 102,15,56,0,203
+ pxor %xmm4,%xmm0
+ movdqa 0(%r10),%xmm4
+ pxor %xmm1,%xmm0
+ movdqa 16(%r10),%xmm1
+
+.byte 102,15,56,0,226
+.byte 102,15,56,0,197
+.byte 102,15,56,0,203
+ pxor %xmm4,%xmm0
+ movdqa 32(%r10),%xmm4
+ pxor %xmm1,%xmm0
+ movdqa 48(%r10),%xmm1
+
+.byte 102,15,56,0,226
+.byte 102,15,56,0,197
+.byte 102,15,56,0,203
+ pxor %xmm4,%xmm0
+ movdqa 64(%r10),%xmm4
+ pxor %xmm1,%xmm0
+ movdqa 80(%r10),%xmm1
+
+.byte 102,15,56,0,226
+.byte 102,15,56,0,197
+.byte 102,15,56,0,203
+ pxor %xmm4,%xmm0
+ addq $16,%r9
+.byte 102,15,58,15,237,12
+ pxor %xmm1,%xmm0
+ subq $1,%rax
+
+L$dec_entry:
+
+ movdqa %xmm9,%xmm1
+ pandn %xmm0,%xmm1
+ movdqa %xmm11,%xmm2
+ psrld $4,%xmm1
+ pand %xmm9,%xmm0
+.byte 102,15,56,0,208
+ movdqa %xmm10,%xmm3
+ pxor %xmm1,%xmm0
+.byte 102,15,56,0,217
+ movdqa %xmm10,%xmm4
+ pxor %xmm2,%xmm3
+.byte 102,15,56,0,224
+ pxor %xmm2,%xmm4
+ movdqa %xmm10,%xmm2
+.byte 102,15,56,0,211
+ movdqa %xmm10,%xmm3
+ pxor %xmm0,%xmm2
+.byte 102,15,56,0,220
+ movdqu (%r9),%xmm0
+ pxor %xmm1,%xmm3
+ 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
+ .byte 0xf3,0xc3
+
+
+
+
+
+
+
+
+.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
+ .byte 0xf3,0xc3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+.p2align 4
+_vpaes_schedule_192_smear:
+ pshufd $128,%xmm6,%xmm1
+ pshufd $254,%xmm7,%xmm0
+ pxor %xmm1,%xmm6
+ pxor %xmm1,%xmm1
+ pxor %xmm0,%xmm6
+ movdqa %xmm6,%xmm0
+ movhlps %xmm1,%xmm6
+ .byte 0xf3,0xc3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+.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
+ .byte 0xf3,0xc3
+
+
+
+
+
+
+
+
+
+
+
+
+.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
+ .byte 0xf3,0xc3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+.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)
+ .byte 0xf3,0xc3
+
+
+
+
+
+.globl _vpaes_set_encrypt_key
+.private_extern _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
+ .byte 0xf3,0xc3
+
+
+.globl _vpaes_set_decrypt_key
+.private_extern _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
+ .byte 0xf3,0xc3
+
+
+.globl _vpaes_encrypt
+.private_extern _vpaes_encrypt
+
+.p2align 4
+_vpaes_encrypt:
+ movdqu (%rdi),%xmm0
+ call _vpaes_preheat
+ call _vpaes_encrypt_core
+ movdqu %xmm0,(%rsi)
+ .byte 0xf3,0xc3
+
+
+.globl _vpaes_decrypt
+.private_extern _vpaes_decrypt
+
+.p2align 4
+_vpaes_decrypt:
+ movdqu (%rdi),%xmm0
+ call _vpaes_preheat
+ call _vpaes_decrypt_core
+ movdqu %xmm0,(%rsi)
+ .byte 0xf3,0xc3
+
+.globl _vpaes_cbc_encrypt
+.private_extern _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:
+ .byte 0xf3,0xc3
+
+
+
+
+
+
+
+
+.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
+ .byte 0xf3,0xc3
+
+
+
+
+
+
+
+.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
+
+#endif
diff --git a/mac-x86_64/crypto/bn/modexp512-x86_64.S b/mac-x86_64/crypto/bn/modexp512-x86_64.S
new file mode 100644
index 0000000..beb133e
--- /dev/null
+++ b/mac-x86_64/crypto/bn/modexp512-x86_64.S
@@ -0,0 +1,1776 @@
+#if defined(__x86_64__)
+.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
+ .byte 0xf3,0xc3
+
+
+.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)
+
+ .byte 0xf3,0xc3
+
+
+.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
+.private_extern _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:
+ .byte 0xf3,0xc3
+
+#endif
diff --git a/mac-x86_64/crypto/bn/rsaz-avx2.S b/mac-x86_64/crypto/bn/rsaz-avx2.S
new file mode 100644
index 0000000..8ba2019
--- /dev/null
+++ b/mac-x86_64/crypto/bn/rsaz-avx2.S
@@ -0,0 +1,34 @@
+#if defined(__x86_64__)
+.text
+
+.globl _rsaz_avx2_eligible
+.private_extern _rsaz_avx2_eligible
+
+_rsaz_avx2_eligible:
+ xorl %eax,%eax
+ .byte 0xf3,0xc3
+
+
+.globl _rsaz_1024_sqr_avx2
+.private_extern _rsaz_1024_sqr_avx2
+.globl _rsaz_1024_mul_avx2
+.private_extern _rsaz_1024_mul_avx2
+.globl _rsaz_1024_norm2red_avx2
+.private_extern _rsaz_1024_norm2red_avx2
+.globl _rsaz_1024_red2norm_avx2
+.private_extern _rsaz_1024_red2norm_avx2
+.globl _rsaz_1024_scatter5_avx2
+.private_extern _rsaz_1024_scatter5_avx2
+.globl _rsaz_1024_gather5_avx2
+.private_extern _rsaz_1024_gather5_avx2
+
+_rsaz_1024_sqr_avx2:
+_rsaz_1024_mul_avx2:
+_rsaz_1024_norm2red_avx2:
+_rsaz_1024_red2norm_avx2:
+_rsaz_1024_scatter5_avx2:
+_rsaz_1024_gather5_avx2:
+.byte 0x0f,0x0b
+ .byte 0xf3,0xc3
+
+#endif
diff --git a/mac-x86_64/crypto/bn/rsaz-x86_64.S b/mac-x86_64/crypto/bn/rsaz-x86_64.S
new file mode 100644
index 0000000..5e9e82f
--- /dev/null
+++ b/mac-x86_64/crypto/bn/rsaz-x86_64.S
@@ -0,0 +1,1126 @@
+#if defined(__x86_64__)
+.text
+
+
+
+.globl _rsaz_512_sqr
+.private_extern _rsaz_512_sqr
+
+.p2align 5
+_rsaz_512_sqr:
+ pushq %rbx
+ pushq %rbp
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ pushq %r15
+
+ subq $128+24,%rsp
+L$sqr_body:
+ movq %rdx,%rbp
+ movq (%rsi),%rdx
+ movq 8(%rsi),%rax
+ movq %rcx,128(%rsp)
+ jmp L$oop_sqr
+
+.p2align 5
+L$oop_sqr:
+ movl %r8d,128+8(%rsp)
+
+ movq %rdx,%rbx
+ mulq %rdx
+ movq %rax,%r8
+ movq 16(%rsi),%rax
+ movq %rdx,%r9
+
+ mulq %rbx
+ addq %rax,%r9
+ movq 24(%rsi),%rax
+ movq %rdx,%r10
+ adcq $0,%r10
+
+ mulq %rbx
+ addq %rax,%r10
+ movq 32(%rsi),%rax
+ movq %rdx,%r11
+ adcq $0,%r11
+
+ mulq %rbx
+ addq %rax,%r11
+ movq 40(%rsi),%rax
+ movq %rdx,%r12
+ adcq $0,%r12
+
+ mulq %rbx
+ addq %rax,%r12
+ movq 48(%rsi),%rax
+ movq %rdx,%r13
+ adcq $0,%r13
+
+ mulq %rbx
+ addq %rax,%r13
+ movq 56(%rsi),%rax
+ movq %rdx,%r14
+ adcq $0,%r14
+
+ mulq %rbx
+ addq %rax,%r14
+ movq %rbx,%rax
+ movq %rdx,%r15
+ adcq $0,%r15
+
+ addq %r8,%r8
+ movq %r9,%rcx
+ adcq %r9,%r9
+
+ mulq %rax
+ movq %rax,(%rsp)
+ addq %rdx,%r8
+ adcq $0,%r9
+
+ movq %r8,8(%rsp)
+ shrq $63,%rcx
+
+
+ movq 8(%rsi),%r8
+ movq 16(%rsi),%rax
+ mulq %r8
+ addq %rax,%r10
+ movq 24(%rsi),%rax
+ movq %rdx,%rbx
+ adcq $0,%rbx
+
+ mulq %r8
+ addq %rax,%r11
+ movq 32(%rsi),%rax
+ adcq $0,%rdx
+ addq %rbx,%r11
+ movq %rdx,%rbx
+ adcq $0,%rbx
+
+ mulq %r8
+ addq %rax,%r12
+ movq 40(%rsi),%rax
+ adcq $0,%rdx
+ addq %rbx,%r12
+ movq %rdx,%rbx
+ adcq $0,%rbx
+
+ mulq %r8
+ addq %rax,%r13
+ movq 48(%rsi),%rax
+ adcq $0,%rdx
+ addq %rbx,%r13
+ movq %rdx,%rbx
+ adcq $0,%rbx
+
+ mulq %r8
+ addq %rax,%r14
+ movq 56(%rsi),%rax
+ adcq $0,%rdx
+ addq %rbx,%r14
+ movq %rdx,%rbx
+ adcq $0,%rbx
+
+ mulq %r8
+ addq %rax,%r15
+ movq %r8,%rax
+ adcq $0,%rdx
+ addq %rbx,%r15
+ movq %rdx,%r8
+ movq %r10,%rdx
+ adcq $0,%r8
+
+ addq %rdx,%rdx
+ leaq (%rcx,%r10,2),%r10
+ movq %r11,%rbx
+ adcq %r11,%r11
+
+ mulq %rax
+ addq %rax,%r9
+ adcq %rdx,%r10
+ adcq $0,%r11
+
+ movq %r9,16(%rsp)
+ movq %r10,24(%rsp)
+ shrq $63,%rbx
+
+
+ movq 16(%rsi),%r9
+ movq 24(%rsi),%rax
+ mulq %r9
+ addq %rax,%r12
+ movq 32(%rsi),%rax
+ movq %rdx,%rcx
+ adcq $0,%rcx
+
+ mulq %r9
+ addq %rax,%r13
+ movq 40(%rsi),%rax
+ adcq $0,%rdx
+ addq %rcx,%r13
+ movq %rdx,%rcx
+ adcq $0,%rcx
+
+ mulq %r9
+ addq %rax,%r14
+ movq 48(%rsi),%rax
+ adcq $0,%rdx
+ addq %rcx,%r14
+ movq %rdx,%rcx
+ adcq $0,%rcx
+
+ mulq %r9
+ movq %r12,%r10
+ leaq (%rbx,%r12,2),%r12
+ addq %rax,%r15
+ movq 56(%rsi),%rax
+ adcq $0,%rdx
+ addq %rcx,%r15
+ movq %rdx,%rcx
+ adcq $0,%rcx
+
+ mulq %r9
+ shrq $63,%r10
+ addq %rax,%r8
+ movq %r9,%rax
+ adcq $0,%rdx
+ addq %rcx,%r8
+ movq %rdx,%r9
+ adcq $0,%r9
+
+ movq %r13,%rcx
+ leaq (%r10,%r13,2),%r13
+
+ mulq %rax
+ addq %rax,%r11
+ adcq %rdx,%r12
+ adcq $0,%r13
+
+ movq %r11,32(%rsp)
+ movq %r12,40(%rsp)
+ shrq $63,%rcx
+
+
+ movq 24(%rsi),%r10
+ movq 32(%rsi),%rax
+ mulq %r10
+ addq %rax,%r14
+ movq 40(%rsi),%rax
+ movq %rdx,%rbx
+ adcq $0,%rbx
+
+ mulq %r10
+ addq %rax,%r15
+ movq 48(%rsi),%rax
+ adcq $0,%rdx
+ addq %rbx,%r15
+ movq %rdx,%rbx
+ adcq $0,%rbx
+
+ mulq %r10
+ movq %r14,%r12
+ leaq (%rcx,%r14,2),%r14
+ addq %rax,%r8
+ movq 56(%rsi),%rax
+ adcq $0,%rdx
+ addq %rbx,%r8
+ movq %rdx,%rbx
+ adcq $0,%rbx
+
+ mulq %r10
+ shrq $63,%r12
+ addq %rax,%r9
+ movq %r10,%rax
+ adcq $0,%rdx
+ addq %rbx,%r9
+ movq %rdx,%r10
+ adcq $0,%r10
+
+ movq %r15,%rbx
+ leaq (%r12,%r15,2),%r15
+
+ mulq %rax
+ addq %rax,%r13
+ adcq %rdx,%r14
+ adcq $0,%r15
+
+ movq %r13,48(%rsp)
+ movq %r14,56(%rsp)
+ shrq $63,%rbx
+
+
+ movq 32(%rsi),%r11
+ movq 40(%rsi),%rax
+ mulq %r11
+ addq %rax,%r8
+ movq 48(%rsi),%rax
+ movq %rdx,%rcx
+ adcq $0,%rcx
+
+ mulq %r11
+ addq %rax,%r9
+ movq 56(%rsi),%rax
+ adcq $0,%rdx
+ movq %r8,%r12
+ leaq (%rbx,%r8,2),%r8
+ addq %rcx,%r9
+ movq %rdx,%rcx
+ adcq $0,%rcx
+
+ mulq %r11
+ shrq $63,%r12
+ addq %rax,%r10
+ movq %r11,%rax
+ adcq $0,%rdx
+ addq %rcx,%r10
+ movq %rdx,%r11
+ adcq $0,%r11
+
+ movq %r9,%rcx
+ leaq (%r12,%r9,2),%r9
+
+ mulq %rax
+ addq %rax,%r15
+ adcq %rdx,%r8
+ adcq $0,%r9
+
+ movq %r15,64(%rsp)
+ movq %r8,72(%rsp)
+ shrq $63,%rcx
+
+
+ movq 40(%rsi),%r12
+ movq 48(%rsi),%rax
+ mulq %r12
+ addq %rax,%r10
+ movq 56(%rsi),%rax
+ movq %rdx,%rbx
+ adcq $0,%rbx
+
+ mulq %r12
+ addq %rax,%r11
+ movq %r12,%rax
+ movq %r10,%r15
+ leaq (%rcx,%r10,2),%r10
+ adcq $0,%rdx
+ shrq $63,%r15
+ addq %rbx,%r11
+ movq %rdx,%r12
+ adcq $0,%r12
+
+ movq %r11,%rbx
+ leaq (%r15,%r11,2),%r11
+
+ mulq %rax
+ addq %rax,%r9
+ adcq %rdx,%r10
+ adcq $0,%r11
+
+ movq %r9,80(%rsp)
+ movq %r10,88(%rsp)
+
+
+ movq 48(%rsi),%r13
+ movq 56(%rsi),%rax
+ mulq %r13
+ addq %rax,%r12
+ movq %r13,%rax
+ movq %rdx,%r13
+ adcq $0,%r13
+
+ xorq %r14,%r14
+ shlq $1,%rbx
+ adcq %r12,%r12
+ adcq %r13,%r13
+ adcq %r14,%r14
+
+ mulq %rax
+ addq %rax,%r11
+ adcq %rdx,%r12
+ adcq $0,%r13
+
+ movq %r11,96(%rsp)
+ movq %r12,104(%rsp)
+
+
+ movq 56(%rsi),%rax
+ mulq %rax
+ addq %rax,%r13
+ adcq $0,%rdx
+
+ addq %rdx,%r14
+
+ movq %r13,112(%rsp)
+ movq %r14,120(%rsp)
+
+ movq (%rsp),%r8
+ movq 8(%rsp),%r9
+ movq 16(%rsp),%r10
+ movq 24(%rsp),%r11
+ movq 32(%rsp),%r12
+ movq 40(%rsp),%r13
+ movq 48(%rsp),%r14
+ movq 56(%rsp),%r15
+
+ call __rsaz_512_reduce
+
+ addq 64(%rsp),%r8
+ adcq 72(%rsp),%r9
+ adcq 80(%rsp),%r10
+ adcq 88(%rsp),%r11
+ adcq 96(%rsp),%r12
+ adcq 104(%rsp),%r13
+ adcq 112(%rsp),%r14
+ adcq 120(%rsp),%r15
+ sbbq %rcx,%rcx
+
+ call __rsaz_512_subtract
+
+ movq %r8,%rdx
+ movq %r9,%rax
+ movl 128+8(%rsp),%r8d
+ movq %rdi,%rsi
+
+ decl %r8d
+ jnz L$oop_sqr
+
+ leaq 128+24+48(%rsp),%rax
+ movq -48(%rax),%r15
+ movq -40(%rax),%r14
+ movq -32(%rax),%r13
+ movq -24(%rax),%r12
+ movq -16(%rax),%rbp
+ movq -8(%rax),%rbx
+ leaq (%rax),%rsp
+L$sqr_epilogue:
+ .byte 0xf3,0xc3
+
+.globl _rsaz_512_mul
+.private_extern _rsaz_512_mul
+
+.p2align 5
+_rsaz_512_mul:
+ pushq %rbx
+ pushq %rbp
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ pushq %r15
+
+ subq $128+24,%rsp
+L$mul_body:
+.byte 102,72,15,110,199
+.byte 102,72,15,110,201
+ movq %r8,128(%rsp)
+ movq (%rdx),%rbx
+ movq %rdx,%rbp
+ call __rsaz_512_mul
+
+.byte 102,72,15,126,199
+.byte 102,72,15,126,205
+
+ movq (%rsp),%r8
+ movq 8(%rsp),%r9
+ movq 16(%rsp),%r10
+ movq 24(%rsp),%r11
+ movq 32(%rsp),%r12
+ movq 40(%rsp),%r13
+ movq 48(%rsp),%r14
+ movq 56(%rsp),%r15
+
+ call __rsaz_512_reduce
+ addq 64(%rsp),%r8
+ adcq 72(%rsp),%r9
+ adcq 80(%rsp),%r10
+ adcq 88(%rsp),%r11
+ adcq 96(%rsp),%r12
+ adcq 104(%rsp),%r13
+ adcq 112(%rsp),%r14
+ adcq 120(%rsp),%r15
+ sbbq %rcx,%rcx
+
+ call __rsaz_512_subtract
+
+ leaq 128+24+48(%rsp),%rax
+ movq -48(%rax),%r15
+ movq -40(%rax),%r14
+ movq -32(%rax),%r13
+ movq -24(%rax),%r12
+ movq -16(%rax),%rbp
+ movq -8(%rax),%rbx
+ leaq (%rax),%rsp
+L$mul_epilogue:
+ .byte 0xf3,0xc3
+
+.globl _rsaz_512_mul_gather4
+.private_extern _rsaz_512_mul_gather4
+
+.p2align 5
+_rsaz_512_mul_gather4:
+ pushq %rbx
+ pushq %rbp
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ pushq %r15
+
+ movl %r9d,%r9d
+ subq $128+24,%rsp
+L$mul_gather4_body:
+ movl 64(%rdx,%r9,4),%eax
+.byte 102,72,15,110,199
+ movl (%rdx,%r9,4),%ebx
+.byte 102,72,15,110,201
+ movq %r8,128(%rsp)
+
+ shlq $32,%rax
+ orq %rax,%rbx
+ movq (%rsi),%rax
+ movq 8(%rsi),%rcx
+ leaq 128(%rdx,%r9,4),%rbp
+ mulq %rbx
+ movq %rax,(%rsp)
+ movq %rcx,%rax
+ movq %rdx,%r8
+
+ mulq %rbx
+ movd (%rbp),%xmm4
+ addq %rax,%r8
+ movq 16(%rsi),%rax
+ movq %rdx,%r9
+ adcq $0,%r9
+
+ mulq %rbx
+ movd 64(%rbp),%xmm5
+ addq %rax,%r9
+ movq 24(%rsi),%rax
+ movq %rdx,%r10
+ adcq $0,%r10
+
+ mulq %rbx
+ pslldq $4,%xmm5
+ addq %rax,%r10
+ movq 32(%rsi),%rax
+ movq %rdx,%r11
+ adcq $0,%r11
+
+ mulq %rbx
+ por %xmm5,%xmm4
+ addq %rax,%r11
+ movq 40(%rsi),%rax
+ movq %rdx,%r12
+ adcq $0,%r12
+
+ mulq %rbx
+ addq %rax,%r12
+ movq 48(%rsi),%rax
+ movq %rdx,%r13
+ adcq $0,%r13
+
+ mulq %rbx
+ leaq 128(%rbp),%rbp
+ addq %rax,%r13
+ movq 56(%rsi),%rax
+ movq %rdx,%r14
+ adcq $0,%r14
+
+ mulq %rbx
+.byte 102,72,15,126,227
+ addq %rax,%r14
+ movq (%rsi),%rax
+ movq %rdx,%r15
+ adcq $0,%r15
+
+ leaq 8(%rsp),%rdi
+ movl $7,%ecx
+ jmp L$oop_mul_gather
+
+.p2align 5
+L$oop_mul_gather:
+ mulq %rbx
+ addq %rax,%r8
+ movq 8(%rsi),%rax
+ movq %r8,(%rdi)
+ movq %rdx,%r8
+ adcq $0,%r8
+
+ mulq %rbx
+ movd (%rbp),%xmm4
+ addq %rax,%r9
+ movq 16(%rsi),%rax
+ adcq $0,%rdx
+ addq %r9,%r8
+ movq %rdx,%r9
+ adcq $0,%r9
+
+ mulq %rbx
+ movd 64(%rbp),%xmm5
+ addq %rax,%r10
+ movq 24(%rsi),%rax
+ adcq $0,%rdx
+ addq %r10,%r9
+ movq %rdx,%r10
+ adcq $0,%r10
+
+ mulq %rbx
+ pslldq $4,%xmm5
+ addq %rax,%r11
+ movq 32(%rsi),%rax
+ adcq $0,%rdx
+ addq %r11,%r10
+ movq %rdx,%r11
+ adcq $0,%r11
+
+ mulq %rbx
+ por %xmm5,%xmm4
+ addq %rax,%r12
+ movq 40(%rsi),%rax
+ adcq $0,%rdx
+ addq %r12,%r11
+ movq %rdx,%r12
+ adcq $0,%r12
+
+ mulq %rbx
+ addq %rax,%r13
+ movq 48(%rsi),%rax
+ adcq $0,%rdx
+ addq %r13,%r12
+ movq %rdx,%r13
+ adcq $0,%r13
+
+ mulq %rbx
+ addq %rax,%r14
+ movq 56(%rsi),%rax
+ adcq $0,%rdx
+ addq %r14,%r13
+ movq %rdx,%r14
+ adcq $0,%r14
+
+ mulq %rbx
+.byte 102,72,15,126,227
+ addq %rax,%r15
+ movq (%rsi),%rax
+ adcq $0,%rdx
+ addq %r15,%r14
+ movq %rdx,%r15
+ adcq $0,%r15
+
+ leaq 128(%rbp),%rbp
+ leaq 8(%rdi),%rdi
+
+ decl %ecx
+ jnz L$oop_mul_gather
+
+ movq %r8,(%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)
+
+.byte 102,72,15,126,199
+.byte 102,72,15,126,205
+
+ movq (%rsp),%r8
+ movq 8(%rsp),%r9
+ movq 16(%rsp),%r10
+ movq 24(%rsp),%r11
+ movq 32(%rsp),%r12
+ movq 40(%rsp),%r13
+ movq 48(%rsp),%r14
+ movq 56(%rsp),%r15
+
+ call __rsaz_512_reduce
+ addq 64(%rsp),%r8
+ adcq 72(%rsp),%r9
+ adcq 80(%rsp),%r10
+ adcq 88(%rsp),%r11
+ adcq 96(%rsp),%r12
+ adcq 104(%rsp),%r13
+ adcq 112(%rsp),%r14
+ adcq 120(%rsp),%r15
+ sbbq %rcx,%rcx
+
+ call __rsaz_512_subtract
+
+ leaq 128+24+48(%rsp),%rax
+ movq -48(%rax),%r15
+ movq -40(%rax),%r14
+ movq -32(%rax),%r13
+ movq -24(%rax),%r12
+ movq -16(%rax),%rbp
+ movq -8(%rax),%rbx
+ leaq (%rax),%rsp
+L$mul_gather4_epilogue:
+ .byte 0xf3,0xc3
+
+.globl _rsaz_512_mul_scatter4
+.private_extern _rsaz_512_mul_scatter4
+
+.p2align 5
+_rsaz_512_mul_scatter4:
+ pushq %rbx
+ pushq %rbp
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ pushq %r15
+
+ movl %r9d,%r9d
+ subq $128+24,%rsp
+L$mul_scatter4_body:
+ leaq (%r8,%r9,4),%r8
+.byte 102,72,15,110,199
+.byte 102,72,15,110,202
+.byte 102,73,15,110,208
+ movq %rcx,128(%rsp)
+
+ movq %rdi,%rbp
+ movq (%rdi),%rbx
+ call __rsaz_512_mul
+
+.byte 102,72,15,126,199
+.byte 102,72,15,126,205
+
+ movq (%rsp),%r8
+ movq 8(%rsp),%r9
+ movq 16(%rsp),%r10
+ movq 24(%rsp),%r11
+ movq 32(%rsp),%r12
+ movq 40(%rsp),%r13
+ movq 48(%rsp),%r14
+ movq 56(%rsp),%r15
+
+ call __rsaz_512_reduce
+ addq 64(%rsp),%r8
+ adcq 72(%rsp),%r9
+ adcq 80(%rsp),%r10
+ adcq 88(%rsp),%r11
+ adcq 96(%rsp),%r12
+ adcq 104(%rsp),%r13
+ adcq 112(%rsp),%r14
+ adcq 120(%rsp),%r15
+.byte 102,72,15,126,214
+ sbbq %rcx,%rcx
+
+ call __rsaz_512_subtract
+
+ movl %r8d,0(%rsi)
+ shrq $32,%r8
+ movl %r9d,128(%rsi)
+ shrq $32,%r9
+ movl %r10d,256(%rsi)
+ shrq $32,%r10
+ movl %r11d,384(%rsi)
+ shrq $32,%r11
+ movl %r12d,512(%rsi)
+ shrq $32,%r12
+ movl %r13d,640(%rsi)
+ shrq $32,%r13
+ movl %r14d,768(%rsi)
+ shrq $32,%r14
+ movl %r15d,896(%rsi)
+ shrq $32,%r15
+ movl %r8d,64(%rsi)
+ movl %r9d,192(%rsi)
+ movl %r10d,320(%rsi)
+ movl %r11d,448(%rsi)
+ movl %r12d,576(%rsi)
+ movl %r13d,704(%rsi)
+ movl %r14d,832(%rsi)
+ movl %r15d,960(%rsi)
+
+ leaq 128+24+48(%rsp),%rax
+ movq -48(%rax),%r15
+ movq -40(%rax),%r14
+ movq -32(%rax),%r13
+ movq -24(%rax),%r12
+ movq -16(%rax),%rbp
+ movq -8(%rax),%rbx
+ leaq (%rax),%rsp
+L$mul_scatter4_epilogue:
+ .byte 0xf3,0xc3
+
+.globl _rsaz_512_mul_by_one
+.private_extern _rsaz_512_mul_by_one
+
+.p2align 5
+_rsaz_512_mul_by_one:
+ pushq %rbx
+ pushq %rbp
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ pushq %r15
+
+ subq $128+24,%rsp
+L$mul_by_one_body:
+ movq %rdx,%rbp
+ movq %rcx,128(%rsp)
+
+ movq (%rsi),%r8
+ pxor %xmm0,%xmm0
+ movq 8(%rsi),%r9
+ movq 16(%rsi),%r10
+ movq 24(%rsi),%r11
+ movq 32(%rsi),%r12
+ movq 40(%rsi),%r13
+ movq 48(%rsi),%r14
+ movq 56(%rsi),%r15
+
+ movdqa %xmm0,(%rsp)
+ movdqa %xmm0,16(%rsp)
+ movdqa %xmm0,32(%rsp)
+ movdqa %xmm0,48(%rsp)
+ movdqa %xmm0,64(%rsp)
+ movdqa %xmm0,80(%rsp)
+ movdqa %xmm0,96(%rsp)
+ call __rsaz_512_reduce
+ movq %r8,(%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 128+24+48(%rsp),%rax
+ movq -48(%rax),%r15
+ movq -40(%rax),%r14
+ movq -32(%rax),%r13
+ movq -24(%rax),%r12
+ movq -16(%rax),%rbp
+ movq -8(%rax),%rbx
+ leaq (%rax),%rsp
+L$mul_by_one_epilogue:
+ .byte 0xf3,0xc3
+
+
+.p2align 5
+__rsaz_512_reduce:
+ movq %r8,%rbx
+ imulq 128+8(%rsp),%rbx
+ movq 0(%rbp),%rax
+ movl $8,%ecx
+ jmp L$reduction_loop
+
+.p2align 5
+L$reduction_loop:
+ mulq %rbx
+ movq 8(%rbp),%rax
+ negq %r8
+ movq %rdx,%r8
+ adcq $0,%r8
+
+ mulq %rbx
+ addq %rax,%r9
+ movq 16(%rbp),%rax
+ adcq $0,%rdx
+ addq %r9,%r8
+ movq %rdx,%r9
+ adcq $0,%r9
+
+ mulq %rbx
+ addq %rax,%r10
+ movq 24(%rbp),%rax
+ adcq $0,%rdx
+ addq %r10,%r9
+ movq %rdx,%r10
+ adcq $0,%r10
+
+ mulq %rbx
+ addq %rax,%r11
+ movq 32(%rbp),%rax
+ adcq $0,%rdx
+ addq %r11,%r10
+ movq 128+8(%rsp),%rsi
+
+
+ adcq $0,%rdx
+ movq %rdx,%r11
+
+ mulq %rbx
+ addq %rax,%r12
+ movq 40(%rbp),%rax
+ adcq $0,%rdx
+ imulq %r8,%rsi
+ addq %r12,%r11
+ movq %rdx,%r12
+ adcq $0,%r12
+
+ mulq %rbx
+ addq %rax,%r13
+ movq 48(%rbp),%rax
+ adcq $0,%rdx
+ addq %r13,%r12
+ movq %rdx,%r13
+ adcq $0,%r13
+
+ mulq %rbx
+ addq %rax,%r14
+ movq 56(%rbp),%rax
+ adcq $0,%rdx
+ addq %r14,%r13
+ movq %rdx,%r14
+ adcq $0,%r14
+
+ mulq %rbx
+ movq %rsi,%rbx
+ addq %rax,%r15
+ movq 0(%rbp),%rax
+ adcq $0,%rdx
+ addq %r15,%r14
+ movq %rdx,%r15
+ adcq $0,%r15
+
+ decl %ecx
+ jne L$reduction_loop
+
+ .byte 0xf3,0xc3
+
+
+.p2align 5
+__rsaz_512_subtract:
+ movq %r8,(%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)
+
+ movq 0(%rbp),%r8
+ movq 8(%rbp),%r9
+ negq %r8
+ notq %r9
+ andq %rcx,%r8
+ movq 16(%rbp),%r10
+ andq %rcx,%r9
+ notq %r10
+ movq 24(%rbp),%r11
+ andq %rcx,%r10
+ notq %r11
+ movq 32(%rbp),%r12
+ andq %rcx,%r11
+ notq %r12
+ movq 40(%rbp),%r13
+ andq %rcx,%r12
+ notq %r13
+ movq 48(%rbp),%r14
+ andq %rcx,%r13
+ notq %r14
+ movq 56(%rbp),%r15
+ andq %rcx,%r14
+ notq %r15
+ andq %rcx,%r15
+
+ addq (%rdi),%r8
+ adcq 8(%rdi),%r9
+ adcq 16(%rdi),%r10
+ adcq 24(%rdi),%r11
+ adcq 32(%rdi),%r12
+ adcq 40(%rdi),%r13
+ adcq 48(%rdi),%r14
+ adcq 56(%rdi),%r15
+
+ movq %r8,(%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)
+
+ .byte 0xf3,0xc3
+
+
+.p2align 5
+__rsaz_512_mul:
+ leaq 8(%rsp),%rdi
+
+ movq (%rsi),%rax
+ mulq %rbx
+ movq %rax,(%rdi)
+ movq 8(%rsi),%rax
+ movq %rdx,%r8
+
+ mulq %rbx
+ addq %rax,%r8
+ movq 16(%rsi),%rax
+ movq %rdx,%r9
+ adcq $0,%r9
+
+ mulq %rbx
+ addq %rax,%r9
+ movq 24(%rsi),%rax
+ movq %rdx,%r10
+ adcq $0,%r10
+
+ mulq %rbx
+ addq %rax,%r10
+ movq 32(%rsi),%rax
+ movq %rdx,%r11
+ adcq $0,%r11
+
+ mulq %rbx
+ addq %rax,%r11
+ movq 40(%rsi),%rax
+ movq %rdx,%r12
+ adcq $0,%r12
+
+ mulq %rbx
+ addq %rax,%r12
+ movq 48(%rsi),%rax
+ movq %rdx,%r13
+ adcq $0,%r13
+
+ mulq %rbx
+ addq %rax,%r13
+ movq 56(%rsi),%rax
+ movq %rdx,%r14
+ adcq $0,%r14
+
+ mulq %rbx
+ addq %rax,%r14
+ movq (%rsi),%rax
+ movq %rdx,%r15
+ adcq $0,%r15
+
+ leaq 8(%rbp),%rbp
+ leaq 8(%rdi),%rdi
+
+ movl $7,%ecx
+ jmp L$oop_mul
+
+.p2align 5
+L$oop_mul:
+ movq (%rbp),%rbx
+ mulq %rbx
+ addq %rax,%r8
+ movq 8(%rsi),%rax
+ movq %r8,(%rdi)
+ movq %rdx,%r8
+ adcq $0,%r8
+
+ mulq %rbx
+ addq %rax,%r9
+ movq 16(%rsi),%rax
+ adcq $0,%rdx
+ addq %r9,%r8
+ movq %rdx,%r9
+ adcq $0,%r9
+
+ mulq %rbx
+ addq %rax,%r10
+ movq 24(%rsi),%rax
+ adcq $0,%rdx
+ addq %r10,%r9
+ movq %rdx,%r10
+ adcq $0,%r10
+
+ mulq %rbx
+ addq %rax,%r11
+ movq 32(%rsi),%rax
+ adcq $0,%rdx
+ addq %r11,%r10
+ movq %rdx,%r11
+ adcq $0,%r11
+
+ mulq %rbx
+ addq %rax,%r12
+ movq 40(%rsi),%rax
+ adcq $0,%rdx
+ addq %r12,%r11
+ movq %rdx,%r12
+ adcq $0,%r12
+
+ mulq %rbx
+ addq %rax,%r13
+ movq 48(%rsi),%rax
+ adcq $0,%rdx
+ addq %r13,%r12
+ movq %rdx,%r13
+ adcq $0,%r13
+
+ mulq %rbx
+ addq %rax,%r14
+ movq 56(%rsi),%rax
+ adcq $0,%rdx
+ addq %r14,%r13
+ movq %rdx,%r14
+ leaq 8(%rbp),%rbp
+ adcq $0,%r14
+
+ mulq %rbx
+ addq %rax,%r15
+ movq (%rsi),%rax
+ adcq $0,%rdx
+ addq %r15,%r14
+ movq %rdx,%r15
+ adcq $0,%r15
+
+ leaq 8(%rdi),%rdi
+
+ decl %ecx
+ jnz L$oop_mul
+
+ movq %r8,(%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)
+
+ .byte 0xf3,0xc3
+
+.globl _rsaz_512_scatter4
+.private_extern _rsaz_512_scatter4
+
+.p2align 4
+_rsaz_512_scatter4:
+ leaq (%rdi,%rdx,4),%rdi
+ movl $8,%r9d
+ jmp L$oop_scatter
+.p2align 4
+L$oop_scatter:
+ movq (%rsi),%rax
+ leaq 8(%rsi),%rsi
+ movl %eax,(%rdi)
+ shrq $32,%rax
+ movl %eax,64(%rdi)
+ leaq 128(%rdi),%rdi
+ decl %r9d
+ jnz L$oop_scatter
+ .byte 0xf3,0xc3
+
+
+.globl _rsaz_512_gather4
+.private_extern _rsaz_512_gather4
+
+.p2align 4
+_rsaz_512_gather4:
+ leaq (%rsi,%rdx,4),%rsi
+ movl $8,%r9d
+ jmp L$oop_gather
+.p2align 4
+L$oop_gather:
+ movl (%rsi),%eax
+ movl 64(%rsi),%r8d
+ leaq 128(%rsi),%rsi
+ shlq $32,%r8
+ orq %r8,%rax
+ movq %rax,(%rdi)
+ leaq 8(%rdi),%rdi
+ decl %r9d
+ jnz L$oop_gather
+ .byte 0xf3,0xc3
+
+#endif
diff --git a/mac-x86_64/crypto/bn/x86_64-mont.S b/mac-x86_64/crypto/bn/x86_64-mont.S
new file mode 100644
index 0000000..6b9bc05
--- /dev/null
+++ b/mac-x86_64/crypto/bn/x86_64-mont.S
@@ -0,0 +1,726 @@
+#if defined(__x86_64__)
+.text
+
+
+
+.globl _bn_mul_mont
+.private_extern _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
+ testl $7,%r9d
+ jz L$sqr8x_enter
+ jmp L$mul4x_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
+ jne 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
+ jne 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
+ jb 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
+ movq %r9,%r15
+.p2align 4
+L$copy:
+ movq (%rsp,%r14,8),%rsi
+ movq (%rdi,%r14,8),%rcx
+ xorq %rcx,%rsi
+ andq %rax,%rsi
+ xorq %rcx,%rsi
+ movq %r14,(%rsp,%r14,8)
+ movq %rsi,(%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:
+ .byte 0xf3,0xc3
+
+
+.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
+ jb 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
+ jb 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
+ jb L$outer4x
+ movq 16(%rsp,%r9,8),%rdi
+ movq 0(%rsp),%rax
+ 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 %rax,%xmm0
+ punpcklqdq %xmm0,%xmm0
+ movq %rbp,24(%rdi,%r14,8)
+ xorq %r14,%r14
+
+ movq %r9,%r15
+ pxor %xmm5,%xmm5
+ jmp L$copy4x
+.p2align 4
+L$copy4x:
+ movdqu (%rsp,%r14,1),%xmm2
+ movdqu 16(%rsp,%r14,1),%xmm4
+ movdqu (%rdi,%r14,1),%xmm1
+ movdqu 16(%rdi,%r14,1),%xmm3
+ pxor %xmm1,%xmm2
+ pxor %xmm3,%xmm4
+ pand %xmm0,%xmm2
+ pand %xmm0,%xmm4
+ pxor %xmm1,%xmm2
+ pxor %xmm3,%xmm4
+ movdqu %xmm2,(%rdi,%r14,1)
+ movdqu %xmm4,16(%rdi,%r14,1)
+ movdqa %xmm5,(%rsp,%r14,1)
+ movdqa %xmm5,16(%rsp,%r14,1)
+
+ leaq 32(%r14),%r14
+ decq %r15
+ jnz L$copy4x
+
+ shlq $2,%r9
+ 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:
+ .byte 0xf3,0xc3
+
+
+
+
+.p2align 5
+bn_sqr8x_mont:
+L$sqr8x_enter:
+ movq %rsp,%rax
+ pushq %rbx
+ pushq %rbp
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ pushq %r15
+
+ movl %r9d,%r10d
+ shll $3,%r9d
+ shlq $3+2,%r10
+ negq %r9
+
+
+
+
+
+
+ leaq -64(%rsp,%r9,4),%r11
+ movq (%r8),%r8
+ subq %rsi,%r11
+ andq $4095,%r11
+ cmpq %r11,%r10
+ jb L$sqr8x_sp_alt
+ subq %r11,%rsp
+ leaq -64(%rsp,%r9,4),%rsp
+ jmp L$sqr8x_sp_done
+
+.p2align 5
+L$sqr8x_sp_alt:
+ leaq 4096-64(,%r9,4),%r10
+ leaq -64(%rsp,%r9,4),%rsp
+ subq %r10,%r11
+ movq $0,%r10
+ cmovcq %r10,%r11
+ subq %r11,%rsp
+L$sqr8x_sp_done:
+ andq $-64,%rsp
+ movq %r9,%r10
+ negq %r9
+
+ leaq 64(%rsp,%r9,2),%r11
+ movq %r8,32(%rsp)
+ movq %rax,40(%rsp)
+L$sqr8x_body:
+
+ movq %r9,%rbp
+.byte 102,73,15,110,211
+ shrq $3+2,%rbp
+ movl _OPENSSL_ia32cap_P+8(%rip),%eax
+ jmp L$sqr8x_copy_n
+
+.p2align 5
+L$sqr8x_copy_n:
+ movq 0(%rcx),%xmm0
+ movq 8(%rcx),%xmm1
+ movq 16(%rcx),%xmm3
+ movq 24(%rcx),%xmm4
+ leaq 32(%rcx),%rcx
+ movdqa %xmm0,0(%r11)
+ movdqa %xmm1,16(%r11)
+ movdqa %xmm3,32(%r11)
+ movdqa %xmm4,48(%r11)
+ leaq 64(%r11),%r11
+ decq %rbp
+ jnz L$sqr8x_copy_n
+
+ pxor %xmm0,%xmm0
+.byte 102,72,15,110,207
+.byte 102,73,15,110,218
+ call _bn_sqr8x_internal
+
+ pxor %xmm0,%xmm0
+ leaq 48(%rsp),%rax
+ leaq 64(%rsp,%r9,2),%rdx
+ shrq $3+2,%r9
+ movq 40(%rsp),%rsi
+ jmp L$sqr8x_zero
+
+.p2align 5
+L$sqr8x_zero:
+ movdqa %xmm0,0(%rax)
+ movdqa %xmm0,16(%rax)
+ movdqa %xmm0,32(%rax)
+ movdqa %xmm0,48(%rax)
+ leaq 64(%rax),%rax
+ movdqa %xmm0,0(%rdx)
+ movdqa %xmm0,16(%rdx)
+ movdqa %xmm0,32(%rdx)
+ movdqa %xmm0,48(%rdx)
+ leaq 64(%rdx),%rdx
+ decq %r9
+ jnz L$sqr8x_zero
+
+ movq $1,%rax
+ movq -48(%rsi),%r15
+ movq -40(%rsi),%r14
+ movq -32(%rsi),%r13
+ movq -24(%rsi),%r12
+ movq -16(%rsi),%rbp
+ movq -8(%rsi),%rbx
+ leaq (%rsi),%rsp
+L$sqr8x_epilogue:
+ .byte 0xf3,0xc3
+
+.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
+#endif
diff --git a/mac-x86_64/crypto/bn/x86_64-mont5.S b/mac-x86_64/crypto/bn/x86_64-mont5.S
new file mode 100644
index 0000000..2e8f469
--- /dev/null
+++ b/mac-x86_64/crypto/bn/x86_64-mont5.S
@@ -0,0 +1,1822 @@
+#if defined(__x86_64__)
+.text
+
+
+
+.globl _bn_mul_mont_gather5
+.private_extern _bn_mul_mont_gather5
+
+.p2align 6
+_bn_mul_mont_gather5:
+ testl $7,%r9d
+ jnz L$mul_enter
+ jmp L$mul4x_enter
+
+.p2align 4
+L$mul_enter:
+ movl %r9d,%r9d
+ movq %rsp,%rax
+ movl 8(%rsp),%r10d
+ pushq %rbx
+ pushq %rbp
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ pushq %r15
+ leaq 2(%r9),%r11
+ negq %r11
+ leaq (%rsp,%r11,8),%rsp
+ andq $-1024,%rsp
+
+ movq %rax,8(%rsp,%r9,8)
+L$mul_body:
+ movq %rdx,%r12
+ movq %r10,%r11
+ shrq $3,%r10
+ andq $7,%r11
+ notq %r10
+ leaq L$magic_masks(%rip),%rax
+ andq $3,%r10
+ leaq 96(%r12,%r11,8),%r12
+ movq 0(%rax,%r10,8),%xmm4
+ movq 8(%rax,%r10,8),%xmm5
+ movq 16(%rax,%r10,8),%xmm6
+ movq 24(%rax,%r10,8),%xmm7
+
+ movq -96(%r12),%xmm0
+ movq -32(%r12),%xmm1
+ pand %xmm4,%xmm0
+ movq 32(%r12),%xmm2
+ pand %xmm5,%xmm1
+ movq 96(%r12),%xmm3
+ pand %xmm6,%xmm2
+ por %xmm1,%xmm0
+ pand %xmm7,%xmm3
+ por %xmm2,%xmm0
+ leaq 256(%r12),%r12
+ por %xmm3,%xmm0
+
+.byte 102,72,15,126,195
+
+ movq (%r8),%r8
+ movq (%rsi),%rax
+
+ xorq %r14,%r14
+ xorq %r15,%r15
+
+ movq -96(%r12),%xmm0
+ movq -32(%r12),%xmm1
+ pand %xmm4,%xmm0
+ movq 32(%r12),%xmm2
+ pand %xmm5,%xmm1
+
+ movq %r8,%rbp
+ mulq %rbx
+ movq %rax,%r10
+ movq (%rcx),%rax
+
+ movq 96(%r12),%xmm3
+ pand %xmm6,%xmm2
+ por %xmm1,%xmm0
+ pand %xmm7,%xmm3
+
+ imulq %r10,%rbp
+ movq %rdx,%r11
+
+ por %xmm2,%xmm0
+ leaq 256(%r12),%r12
+ por %xmm3,%xmm0
+
+ 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
+ jne L$1st
+
+.byte 102,72,15,126,195
+
+ 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:
+ xorq %r15,%r15
+ movq %r8,%rbp
+ movq (%rsp),%r10
+
+ movq -96(%r12),%xmm0
+ movq -32(%r12),%xmm1
+ pand %xmm4,%xmm0
+ movq 32(%r12),%xmm2
+ pand %xmm5,%xmm1
+
+ mulq %rbx
+ addq %rax,%r10
+ movq (%rcx),%rax
+ adcq $0,%rdx
+
+ movq 96(%r12),%xmm3
+ pand %xmm6,%xmm2
+ por %xmm1,%xmm0
+ pand %xmm7,%xmm3
+
+ imulq %r10,%rbp
+ movq %rdx,%r11
+
+ por %xmm2,%xmm0
+ leaq 256(%r12),%r12
+ por %xmm3,%xmm0
+
+ 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
+ jne L$inner
+
+.byte 102,72,15,126,195
+
+ 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
+ jb 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
+ movq %r9,%r15
+.p2align 4
+L$copy:
+ movq (%rsp,%r14,8),%rsi
+ movq (%rdi,%r14,8),%rcx
+ xorq %rcx,%rsi
+ andq %rax,%rsi
+ xorq %rcx,%rsi
+ movq %r14,(%rsp,%r14,8)
+ movq %rsi,(%rdi,%r14,8)
+ leaq 1(%r14),%r14
+ subq $1,%r15
+ jnz L$copy
+
+ movq 8(%rsp,%r9,8),%rsi
+ movq $1,%rax
+ movq -48(%rsi),%r15
+ movq -40(%rsi),%r14
+ movq -32(%rsi),%r13
+ movq -24(%rsi),%r12
+ movq -16(%rsi),%rbp
+ movq -8(%rsi),%rbx
+ leaq (%rsi),%rsp
+L$mul_epilogue:
+ .byte 0xf3,0xc3
+
+
+.p2align 5
+bn_mul4x_mont_gather5:
+L$mul4x_enter:
+.byte 0x67
+ movq %rsp,%rax
+ pushq %rbx
+ pushq %rbp
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ pushq %r15
+.byte 0x67
+ movl %r9d,%r10d
+ shll $3,%r9d
+ shll $3+2,%r10d
+ negq %r9
+
+
+
+
+
+
+
+
+ leaq -64(%rsp,%r9,2),%r11
+ subq %rsi,%r11
+ andq $4095,%r11
+ cmpq %r11,%r10
+ jb L$mul4xsp_alt
+ subq %r11,%rsp
+ leaq -64(%rsp,%r9,2),%rsp
+ jmp L$mul4xsp_done
+
+.p2align 5
+L$mul4xsp_alt:
+ leaq 4096-64(,%r9,2),%r10
+ leaq -64(%rsp,%r9,2),%rsp
+ subq %r10,%r11
+ movq $0,%r10
+ cmovcq %r10,%r11
+ subq %r11,%rsp
+L$mul4xsp_done:
+ andq $-64,%rsp
+ negq %r9
+
+ movq %rax,40(%rsp)
+L$mul4x_body:
+
+ call mul4x_internal
+
+ movq 40(%rsp),%rsi
+ movq $1,%rax
+ movq -48(%rsi),%r15
+ movq -40(%rsi),%r14
+ movq -32(%rsi),%r13
+ movq -24(%rsi),%r12
+ movq -16(%rsi),%rbp
+ movq -8(%rsi),%rbx
+ leaq (%rsi),%rsp
+L$mul4x_epilogue:
+ .byte 0xf3,0xc3
+
+
+
+.p2align 5
+mul4x_internal:
+ shlq $5,%r9
+ movl 8(%rax),%r10d
+ leaq 256(%rdx,%r9,1),%r13
+ shrq $5,%r9
+ movq %r10,%r11
+ shrq $3,%r10
+ andq $7,%r11
+ notq %r10
+ leaq L$magic_masks(%rip),%rax
+ andq $3,%r10
+ leaq 96(%rdx,%r11,8),%r12
+ movq 0(%rax,%r10,8),%xmm4
+ movq 8(%rax,%r10,8),%xmm5
+ addq $7,%r11
+ movq 16(%rax,%r10,8),%xmm6
+ movq 24(%rax,%r10,8),%xmm7
+ andq $7,%r11
+
+ movq -96(%r12),%xmm0
+ leaq 256(%r12),%r14
+ movq -32(%r12),%xmm1
+ pand %xmm4,%xmm0
+ movq 32(%r12),%xmm2
+ pand %xmm5,%xmm1
+ movq 96(%r12),%xmm3
+ pand %xmm6,%xmm2
+.byte 0x67
+ por %xmm1,%xmm0
+ movq -96(%r14),%xmm1
+.byte 0x67
+ pand %xmm7,%xmm3
+.byte 0x67
+ por %xmm2,%xmm0
+ movq -32(%r14),%xmm2
+.byte 0x67
+ pand %xmm4,%xmm1
+.byte 0x67
+ por %xmm3,%xmm0
+ movq 32(%r14),%xmm3
+
+.byte 102,72,15,126,195
+ movq 96(%r14),%xmm0
+ movq %r13,16+8(%rsp)
+ movq %rdi,56+8(%rsp)
+
+ movq (%r8),%r8
+ movq (%rsi),%rax
+ leaq (%rsi,%r9,1),%rsi
+ negq %r9
+
+ movq %r8,%rbp
+ mulq %rbx
+ movq %rax,%r10
+ movq (%rcx),%rax
+
+ pand %xmm5,%xmm2
+ pand %xmm6,%xmm3
+ por %xmm2,%xmm1
+
+ imulq %r10,%rbp
+
+
+
+
+
+
+
+ leaq 64+8(%rsp,%r11,8),%r14
+ movq %rdx,%r11
+
+ pand %xmm7,%xmm0
+ por %xmm3,%xmm1
+ leaq 512(%r12),%r12
+ por %xmm1,%xmm0
+
+ mulq %rbp
+ addq %rax,%r10
+ movq 8(%rsi,%r9,1),%rax
+ adcq $0,%rdx
+ movq %rdx,%rdi
+
+ mulq %rbx
+ addq %rax,%r11
+ movq 16(%rcx),%rax
+ adcq $0,%rdx
+ movq %rdx,%r10
+
+ mulq %rbp
+ addq %rax,%rdi
+ movq 16(%rsi,%r9,1),%rax
+ adcq $0,%rdx
+ addq %r11,%rdi
+ leaq 32(%r9),%r15
+ leaq 64(%rcx),%rcx
+ adcq $0,%rdx
+ movq %rdi,(%r14)
+ movq %rdx,%r13
+ jmp L$1st4x
+
+.p2align 5
+L$1st4x:
+ mulq %rbx
+ addq %rax,%r10
+ movq -32(%rcx),%rax
+ leaq 32(%r14),%r14
+ adcq $0,%rdx
+ movq %rdx,%r11
+
+ mulq %rbp
+ addq %rax,%r13
+ movq -8(%rsi,%r15,1),%rax
+ adcq $0,%rdx
+ addq %r10,%r13
+ adcq $0,%rdx
+ movq %r13,-24(%r14)
+ movq %rdx,%rdi
+
+ mulq %rbx
+ addq %rax,%r11
+ movq -16(%rcx),%rax
+ adcq $0,%rdx
+ movq %rdx,%r10
+
+ mulq %rbp
+ addq %rax,%rdi
+ movq (%rsi,%r15,1),%rax
+ adcq $0,%rdx
+ addq %r11,%rdi
+ adcq $0,%rdx
+ movq %rdi,-16(%r14)
+ movq %rdx,%r13
+
+ mulq %rbx
+ addq %rax,%r10
+ movq 0(%rcx),%rax
+ adcq $0,%rdx
+ movq %rdx,%r11
+
+ mulq %rbp
+ addq %rax,%r13
+ movq 8(%rsi,%r15,1),%rax
+ adcq $0,%rdx
+ addq %r10,%r13
+ adcq $0,%rdx
+ movq %r13,-8(%r14)
+ movq %rdx,%rdi
+
+ mulq %rbx
+ addq %rax,%r11
+ movq 16(%rcx),%rax
+ adcq $0,%rdx
+ movq %rdx,%r10
+
+ mulq %rbp
+ addq %rax,%rdi
+ movq 16(%rsi,%r15,1),%rax
+ adcq $0,%rdx
+ addq %r11,%rdi
+ leaq 64(%rcx),%rcx
+ adcq $0,%rdx
+ movq %rdi,(%r14)
+ movq %rdx,%r13
+
+ addq $32,%r15
+ jnz L$1st4x
+
+ mulq %rbx
+ addq %rax,%r10
+ movq -32(%rcx),%rax
+ leaq 32(%r14),%r14
+ adcq $0,%rdx
+ movq %rdx,%r11
+
+ mulq %rbp
+ addq %rax,%r13
+ movq -8(%rsi),%rax
+ adcq $0,%rdx
+ addq %r10,%r13
+ adcq $0,%rdx
+ movq %r13,-24(%r14)
+ movq %rdx,%rdi
+
+ mulq %rbx
+ addq %rax,%r11
+ movq -16(%rcx),%rax
+ adcq $0,%rdx
+ movq %rdx,%r10
+
+ mulq %rbp
+ addq %rax,%rdi
+ movq (%rsi,%r9,1),%rax
+ adcq $0,%rdx
+ addq %r11,%rdi
+ adcq $0,%rdx
+ movq %rdi,-16(%r14)
+ movq %rdx,%r13
+
+.byte 102,72,15,126,195
+ leaq (%rcx,%r9,2),%rcx
+
+ xorq %rdi,%rdi
+ addq %r10,%r13
+ adcq $0,%rdi
+ movq %r13,-8(%r14)
+
+ jmp L$outer4x
+
+.p2align 5
+L$outer4x:
+ movq (%r14,%r9,1),%r10
+ movq %r8,%rbp
+ mulq %rbx
+ addq %rax,%r10
+ movq (%rcx),%rax
+ adcq $0,%rdx
+
+ movq -96(%r12),%xmm0
+ movq -32(%r12),%xmm1
+ pand %xmm4,%xmm0
+ movq 32(%r12),%xmm2
+ pand %xmm5,%xmm1
+ movq 96(%r12),%xmm3
+
+ imulq %r10,%rbp
+.byte 0x67
+ movq %rdx,%r11
+ movq %rdi,(%r14)
+
+ pand %xmm6,%xmm2
+ por %xmm1,%xmm0
+ pand %xmm7,%xmm3
+ por %xmm2,%xmm0
+ leaq (%r14,%r9,1),%r14
+ leaq 256(%r12),%r12
+ por %xmm3,%xmm0
+
+ mulq %rbp
+ addq %rax,%r10
+ movq 8(%rsi,%r9,1),%rax
+ adcq $0,%rdx
+ movq %rdx,%rdi
+
+ mulq %rbx
+ addq %rax,%r11
+ movq 16(%rcx),%rax
+ adcq $0,%rdx
+ addq 8(%r14),%r11
+ adcq $0,%rdx
+ movq %rdx,%r10
+
+ mulq %rbp
+ addq %rax,%rdi
+ movq 16(%rsi,%r9,1),%rax
+ adcq $0,%rdx
+ addq %r11,%rdi
+ leaq 32(%r9),%r15
+ leaq 64(%rcx),%rcx
+ adcq $0,%rdx
+ movq %rdx,%r13
+ jmp L$inner4x
+
+.p2align 5
+L$inner4x:
+ mulq %rbx
+ addq %rax,%r10
+ movq -32(%rcx),%rax
+ adcq $0,%rdx
+ addq 16(%r14),%r10
+ leaq 32(%r14),%r14
+ adcq $0,%rdx
+ movq %rdx,%r11
+
+ mulq %rbp
+ addq %rax,%r13
+ movq -8(%rsi,%r15,1),%rax
+ adcq $0,%rdx
+ addq %r10,%r13
+ adcq $0,%rdx
+ movq %rdi,-32(%r14)
+ movq %rdx,%rdi
+
+ mulq %rbx
+ addq %rax,%r11
+ movq -16(%rcx),%rax
+ adcq $0,%rdx
+ addq -8(%r14),%r11
+ adcq $0,%rdx
+ movq %rdx,%r10
+
+ mulq %rbp
+ addq %rax,%rdi
+ movq (%rsi,%r15,1),%rax
+ adcq $0,%rdx
+ addq %r11,%rdi
+ adcq $0,%rdx
+ movq %r13,-24(%r14)
+ movq %rdx,%r13
+
+ mulq %rbx
+ addq %rax,%r10
+ movq 0(%rcx),%rax
+ adcq $0,%rdx
+ addq (%r14),%r10
+ adcq $0,%rdx
+ movq %rdx,%r11
+
+ mulq %rbp
+ addq %rax,%r13
+ movq 8(%rsi,%r15,1),%rax
+ adcq $0,%rdx
+ addq %r10,%r13
+ adcq $0,%rdx
+ movq %rdi,-16(%r14)
+ movq %rdx,%rdi
+
+ mulq %rbx
+ addq %rax,%r11
+ movq 16(%rcx),%rax
+ adcq $0,%rdx
+ addq 8(%r14),%r11
+ adcq $0,%rdx
+ movq %rdx,%r10
+
+ mulq %rbp
+ addq %rax,%rdi
+ movq 16(%rsi,%r15,1),%rax
+ adcq $0,%rdx
+ addq %r11,%rdi
+ leaq 64(%rcx),%rcx
+ adcq $0,%rdx
+ movq %r13,-8(%r14)
+ movq %rdx,%r13
+
+ addq $32,%r15
+ jnz L$inner4x
+
+ mulq %rbx
+ addq %rax,%r10
+ movq -32(%rcx),%rax
+ adcq $0,%rdx
+ addq 16(%r14),%r10
+ leaq 32(%r14),%r14
+ adcq $0,%rdx
+ movq %rdx,%r11
+
+ mulq %rbp
+ addq %rax,%r13
+ movq -8(%rsi),%rax
+ adcq $0,%rdx
+ addq %r10,%r13
+ adcq $0,%rdx
+ movq %rdi,-32(%r14)
+ movq %rdx,%rdi
+
+ mulq %rbx
+ addq %rax,%r11
+ movq %rbp,%rax
+ movq -16(%rcx),%rbp
+ adcq $0,%rdx
+ addq -8(%r14),%r11
+ adcq $0,%rdx
+ movq %rdx,%r10
+
+ mulq %rbp
+ addq %rax,%rdi
+ movq (%rsi,%r9,1),%rax
+ adcq $0,%rdx
+ addq %r11,%rdi
+ adcq $0,%rdx
+ movq %r13,-24(%r14)
+ movq %rdx,%r13
+
+.byte 102,72,15,126,195
+ movq %rdi,-16(%r14)
+ leaq (%rcx,%r9,2),%rcx
+
+ xorq %rdi,%rdi
+ addq %r10,%r13
+ adcq $0,%rdi
+ addq (%r14),%r13
+ adcq $0,%rdi
+ movq %r13,-8(%r14)
+
+ cmpq 16+8(%rsp),%r12
+ jb L$outer4x
+ subq %r13,%rbp
+ adcq %r15,%r15
+ orq %r15,%rdi
+ xorq $1,%rdi
+ leaq (%r14,%r9,1),%rbx
+ leaq (%rcx,%rdi,8),%rbp
+ movq %r9,%rcx
+ sarq $3+2,%rcx
+ movq 56+8(%rsp),%rdi
+ jmp L$sqr4x_sub
+
+.globl _bn_power5
+.private_extern _bn_power5
+
+.p2align 5
+_bn_power5:
+ movq %rsp,%rax
+ pushq %rbx
+ pushq %rbp
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ pushq %r15
+ movl %r9d,%r10d
+ shll $3,%r9d
+ shll $3+2,%r10d
+ negq %r9
+ movq (%r8),%r8
+
+
+
+
+
+
+
+ leaq -64(%rsp,%r9,2),%r11
+ subq %rsi,%r11
+ andq $4095,%r11
+ cmpq %r11,%r10
+ jb L$pwr_sp_alt
+ subq %r11,%rsp
+ leaq -64(%rsp,%r9,2),%rsp
+ jmp L$pwr_sp_done
+
+.p2align 5
+L$pwr_sp_alt:
+ leaq 4096-64(,%r9,2),%r10
+ leaq -64(%rsp,%r9,2),%rsp
+ subq %r10,%r11
+ movq $0,%r10
+ cmovcq %r10,%r11
+ subq %r11,%rsp
+L$pwr_sp_done:
+ andq $-64,%rsp
+ movq %r9,%r10
+ negq %r9
+
+
+
+
+
+
+
+
+
+
+ movq %r8,32(%rsp)
+ movq %rax,40(%rsp)
+L$power5_body:
+.byte 102,72,15,110,207
+.byte 102,72,15,110,209
+.byte 102,73,15,110,218
+.byte 102,72,15,110,226
+
+ call __bn_sqr8x_internal
+ call __bn_sqr8x_internal
+ call __bn_sqr8x_internal
+ call __bn_sqr8x_internal
+ call __bn_sqr8x_internal
+
+.byte 102,72,15,126,209
+.byte 102,72,15,126,226
+ movq %rsi,%rdi
+ movq 40(%rsp),%rax
+ leaq 32(%rsp),%r8
+
+ call mul4x_internal
+
+ movq 40(%rsp),%rsi
+ movq $1,%rax
+ movq -48(%rsi),%r15
+ movq -40(%rsi),%r14
+ movq -32(%rsi),%r13
+ movq -24(%rsi),%r12
+ movq -16(%rsi),%rbp
+ movq -8(%rsi),%rbx
+ leaq (%rsi),%rsp
+L$power5_epilogue:
+ .byte 0xf3,0xc3
+
+
+.globl _bn_sqr8x_internal
+.private_extern _bn_sqr8x_internal
+.private_extern _bn_sqr8x_internal
+
+.p2align 5
+_bn_sqr8x_internal:
+__bn_sqr8x_internal:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ leaq 32(%r10),%rbp
+ leaq (%rsi,%r9,1),%rsi
+
+ movq %r9,%rcx
+
+
+ movq -32(%rsi,%rbp,1),%r14
+ leaq 48+8(%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)
+
+ mulq %r14
+ addq %rax,%r11
+ movq %rbx,%rax
+ adcq $0,%rdx
+ movq %r11,-16(%rdi,%rbp,1)
+ movq %rdx,%r10
+
+
+ movq -8(%rsi,%rbp,1),%rbx
+ mulq %r15
+ movq %rax,%r12
+ movq %rbx,%rax
+ movq %rdx,%r13
+
+ leaq (%rbp),%rcx
+ mulq %r14
+ addq %rax,%r10
+ movq %rbx,%rax
+ movq %rdx,%r11
+ adcq $0,%r11
+ addq %r12,%r10
+ adcq $0,%r11
+ movq %r10,-8(%rdi,%rcx,1)
+ jmp L$sqr4x_1st
+
+.p2align 5
+L$sqr4x_1st:
+ movq (%rsi,%rcx,1),%rbx
+ mulq %r15
+ addq %rax,%r13
+ movq %rbx,%rax
+ movq %rdx,%r12
+ adcq $0,%r12
+
+ mulq %r14
+ addq %rax,%r11
+ movq %rbx,%rax
+ movq 8(%rsi,%rcx,1),%rbx
+ movq %rdx,%r10
+ adcq $0,%r10
+ addq %r13,%r11
+ adcq $0,%r10
+
+
+ mulq %r15
+ addq %rax,%r12
+ movq %rbx,%rax
+ movq %r11,(%rdi,%rcx,1)
+ movq %rdx,%r13
+ adcq $0,%r13
+
+ mulq %r14
+ addq %rax,%r10
+ movq %rbx,%rax
+ movq 16(%rsi,%rcx,1),%rbx
+ movq %rdx,%r11
+ adcq $0,%r11
+ addq %r12,%r10
+ adcq $0,%r11
+
+ mulq %r15
+ addq %rax,%r13
+ movq %rbx,%rax
+ movq %r10,8(%rdi,%rcx,1)
+ movq %rdx,%r12
+ adcq $0,%r12
+
+ mulq %r14
+ addq %rax,%r11
+ movq %rbx,%rax
+ movq 24(%rsi,%rcx,1),%rbx
+ movq %rdx,%r10
+ adcq $0,%r10
+ addq %r13,%r11
+ adcq $0,%r10
+
+
+ mulq %r15
+ addq %rax,%r12
+ movq %rbx,%rax
+ movq %r11,16(%rdi,%rcx,1)
+ movq %rdx,%r13
+ adcq $0,%r13
+ leaq 32(%rcx),%rcx
+
+ mulq %r14
+ addq %rax,%r10
+ movq %rbx,%rax
+ movq %rdx,%r11
+ adcq $0,%r11
+ addq %r12,%r10
+ adcq $0,%r11
+ movq %r10,-8(%rdi,%rcx,1)
+
+ cmpq $0,%rcx
+ jne L$sqr4x_1st
+
+ mulq %r15
+ addq %rax,%r13
+ leaq 16(%rbp),%rbp
+ adcq $0,%rdx
+ addq %r11,%r13
+ adcq $0,%rdx
+
+ movq %r13,(%rdi)
+ movq %rdx,%r12
+ movq %rdx,8(%rdi)
+ jmp L$sqr4x_outer
+
+.p2align 5
+L$sqr4x_outer:
+ movq -32(%rsi,%rbp,1),%r14
+ leaq 48+8(%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 -24(%rdi,%rbp,1),%r10
+ addq %rax,%r10
+ movq %rbx,%rax
+ adcq $0,%rdx
+ movq %r10,-24(%rdi,%rbp,1)
+ movq %rdx,%r11
+
+ mulq %r14
+ addq %rax,%r11
+ movq %rbx,%rax
+ adcq $0,%rdx
+ addq -16(%rdi,%rbp,1),%r11
+ movq %rdx,%r10
+ adcq $0,%r10
+ movq %r11,-16(%rdi,%rbp,1)
+
+ xorq %r12,%r12
+
+ movq -8(%rsi,%rbp,1),%rbx
+ mulq %r15
+ addq %rax,%r12
+ movq %rbx,%rax
+ adcq $0,%rdx
+ addq -8(%rdi,%rbp,1),%r12
+ movq %rdx,%r13
+ adcq $0,%r13
+
+ mulq %r14
+ addq %rax,%r10
+ movq %rbx,%rax
+ adcq $0,%rdx
+ addq %r12,%r10
+ movq %rdx,%r11
+ adcq $0,%r11
+ movq %r10,-8(%rdi,%rbp,1)
+
+ leaq (%rbp),%rcx
+ jmp L$sqr4x_inner
+
+.p2align 5
+L$sqr4x_inner:
+ movq (%rsi,%rcx,1),%rbx
+ mulq %r15
+ addq %rax,%r13
+ movq %rbx,%rax
+ movq %rdx,%r12
+ adcq $0,%r12
+ addq (%rdi,%rcx,1),%r13
+ adcq $0,%r12
+
+.byte 0x67
+ mulq %r14
+ addq %rax,%r11
+ movq %rbx,%rax
+ movq 8(%rsi,%rcx,1),%rbx
+ movq %rdx,%r10
+ adcq $0,%r10
+ addq %r13,%r11
+ adcq $0,%r10
+
+ mulq %r15
+ addq %rax,%r12
+ movq %r11,(%rdi,%rcx,1)
+ movq %rbx,%rax
+ movq %rdx,%r13
+ adcq $0,%r13
+ addq 8(%rdi,%rcx,1),%r12
+ leaq 16(%rcx),%rcx
+ adcq $0,%r13
+
+ mulq %r14
+ addq %rax,%r10
+ movq %rbx,%rax
+ adcq $0,%rdx
+ addq %r12,%r10
+ movq %rdx,%r11
+ adcq $0,%r11
+ movq %r10,-8(%rdi,%rcx,1)
+
+ cmpq $0,%rcx
+ jne L$sqr4x_inner
+
+.byte 0x67
+ mulq %r15
+ addq %rax,%r13
+ adcq $0,%rdx
+ addq %r11,%r13
+ adcq $0,%rdx
+
+ movq %r13,(%rdi)
+ movq %rdx,%r12
+ movq %rdx,8(%rdi)
+
+ addq $16,%rbp
+ jnz L$sqr4x_outer
+
+
+ movq -32(%rsi),%r14
+ leaq 48+8(%rsp,%r9,2),%rdi
+ movq -24(%rsi),%rax
+ leaq -32(%rdi,%rbp,1),%rdi
+ movq -16(%rsi),%rbx
+ movq %rax,%r15
+
+ mulq %r14
+ addq %rax,%r10
+ movq %rbx,%rax
+ movq %rdx,%r11
+ adcq $0,%r11
+
+ mulq %r14
+ addq %rax,%r11
+ movq %rbx,%rax
+ movq %r10,-24(%rdi)
+ movq %rdx,%r10
+ adcq $0,%r10
+ addq %r13,%r11
+ movq -8(%rsi),%rbx
+ adcq $0,%r10
+
+ mulq %r15
+ addq %rax,%r12
+ movq %rbx,%rax
+ movq %r11,-16(%rdi)
+ movq %rdx,%r13
+ adcq $0,%r13
+
+ mulq %r14
+ addq %rax,%r10
+ movq %rbx,%rax
+ movq %rdx,%r11
+ adcq $0,%r11
+ addq %r12,%r10
+ adcq $0,%r11
+ movq %r10,-8(%rdi)
+
+ mulq %r15
+ addq %rax,%r13
+ movq -16(%rsi),%rax
+ adcq $0,%rdx
+ addq %r11,%r13
+ adcq $0,%rdx
+
+ movq %r13,(%rdi)
+ movq %rdx,%r12
+ movq %rdx,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 48+8(%rsp),%rdi
+ xorq %r10,%r10
+ movq 8(%rdi),%r11
+
+ 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 24(%rdi),%r11
+ adcq %rax,%r12
+ movq -8(%rsi,%rbp,1),%rax
+ movq %r12,(%rdi)
+ adcq %rdx,%r13
+
+ leaq (%r14,%r10,2),%rbx
+ movq %r13,8(%rdi)
+ sbbq %r15,%r15
+ shrq $63,%r10
+ leaq (%rcx,%r11,2),%r8
+ shrq $63,%r11
+ orq %r10,%r8
+ movq 32(%rdi),%r10
+ movq %r11,%r14
+ mulq %rax
+ negq %r15
+ movq 40(%rdi),%r11
+ adcq %rax,%rbx
+ movq 0(%rsi,%rbp,1),%rax
+ movq %rbx,16(%rdi)
+ adcq %rdx,%r8
+ leaq 16(%rbp),%rbp
+ movq %r8,24(%rdi)
+ sbbq %r15,%r15
+ leaq 64(%rdi),%rdi
+ jmp L$sqr4x_shift_n_add
+
+.p2align 5
+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,%rbp,1),%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
+ movq 0(%rdi),%r10
+ movq %r11,%r14
+ mulq %rax
+ negq %r15
+ movq 8(%rdi),%r11
+ adcq %rax,%rbx
+ movq 0(%rsi,%rbp,1),%rax
+ movq %rbx,-16(%rdi)
+ adcq %rdx,%r8
+
+ leaq (%r14,%r10,2),%r12
+ movq %r8,-8(%rdi)
+ sbbq %r15,%r15
+ 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 24(%rdi),%r11
+ adcq %rax,%r12
+ movq 8(%rsi,%rbp,1),%rax
+ movq %r12,0(%rdi)
+ adcq %rdx,%r13
+
+ leaq (%r14,%r10,2),%rbx
+ movq %r13,8(%rdi)
+ sbbq %r15,%r15
+ shrq $63,%r10
+ leaq (%rcx,%r11,2),%r8
+ shrq $63,%r11
+ orq %r10,%r8
+ movq 32(%rdi),%r10
+ movq %r11,%r14
+ mulq %rax
+ negq %r15
+ movq 40(%rdi),%r11
+ adcq %rax,%rbx
+ movq 16(%rsi,%rbp,1),%rax
+ movq %rbx,16(%rdi)
+ adcq %rdx,%r8
+ movq %r8,24(%rdi)
+ sbbq %r15,%r15
+ leaq 64(%rdi),%rdi
+ addq $32,%rbp
+ jnz L$sqr4x_shift_n_add
+
+ leaq (%r14,%r10,2),%r12
+.byte 0x67
+ 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)
+.byte 102,72,15,126,213
+sqr8x_reduction:
+ xorq %rax,%rax
+ leaq (%rbp,%r9,2),%rcx
+ leaq 48+8(%rsp,%r9,2),%rdx
+ movq %rcx,0+8(%rsp)
+ leaq 48+8(%rsp,%r9,1),%rdi
+ movq %rdx,8+8(%rsp)
+ negq %r9
+ jmp L$8x_reduction_loop
+
+.p2align 5
+L$8x_reduction_loop:
+ leaq (%rdi,%r9,1),%rdi
+.byte 0x66
+ movq 0(%rdi),%rbx
+ 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
+ movq %rax,(%rdx)
+ leaq 64(%rdi),%rdi
+
+.byte 0x67
+ movq %rbx,%r8
+ imulq 32+8(%rsp),%rbx
+ movq 0(%rbp),%rax
+ movl $8,%ecx
+ jmp L$8x_reduce
+
+.p2align 5
+L$8x_reduce:
+ mulq %rbx
+ movq 16(%rbp),%rax
+ negq %r8
+ movq %rdx,%r8
+ adcq $0,%r8
+
+ mulq %rbx
+ addq %rax,%r9
+ movq 32(%rbp),%rax
+ adcq $0,%rdx
+ addq %r9,%r8
+ movq %rbx,48-8+8(%rsp,%rcx,8)
+ movq %rdx,%r9
+ adcq $0,%r9
+
+ mulq %rbx
+ addq %rax,%r10
+ movq 48(%rbp),%rax
+ adcq $0,%rdx
+ addq %r10,%r9
+ movq 32+8(%rsp),%rsi
+ movq %rdx,%r10
+ adcq $0,%r10
+
+ mulq %rbx
+ addq %rax,%r11
+ movq 64(%rbp),%rax
+ adcq $0,%rdx
+ imulq %r8,%rsi
+ addq %r11,%r10
+ movq %rdx,%r11
+ adcq $0,%r11
+
+ mulq %rbx
+ addq %rax,%r12
+ movq 80(%rbp),%rax
+ adcq $0,%rdx
+ addq %r12,%r11
+ movq %rdx,%r12
+ adcq $0,%r12
+
+ mulq %rbx
+ addq %rax,%r13
+ movq 96(%rbp),%rax
+ adcq $0,%rdx
+ addq %r13,%r12
+ movq %rdx,%r13
+ adcq $0,%r13
+
+ mulq %rbx
+ addq %rax,%r14
+ movq 112(%rbp),%rax
+ adcq $0,%rdx
+ addq %r14,%r13
+ movq %rdx,%r14
+ adcq $0,%r14
+
+ mulq %rbx
+ movq %rsi,%rbx
+ addq %rax,%r15
+ movq 0(%rbp),%rax
+ adcq $0,%rdx
+ addq %r15,%r14
+ movq %rdx,%r15
+ adcq $0,%r15
+
+ decl %ecx
+ jnz L$8x_reduce
+
+ leaq 128(%rbp),%rbp
+ xorq %rax,%rax
+ movq 8+8(%rsp),%rdx
+ cmpq 0+8(%rsp),%rbp
+ jae L$8x_no_tail
+
+.byte 0x66
+ addq 0(%rdi),%r8
+ adcq 8(%rdi),%r9
+ adcq 16(%rdi),%r10
+ adcq 24(%rdi),%r11
+ adcq 32(%rdi),%r12
+ adcq 40(%rdi),%r13
+ adcq 48(%rdi),%r14
+ adcq 56(%rdi),%r15
+ sbbq %rsi,%rsi
+
+ movq 48+56+8(%rsp),%rbx
+ movl $8,%ecx
+ movq 0(%rbp),%rax
+ jmp L$8x_tail
+
+.p2align 5
+L$8x_tail:
+ mulq %rbx
+ addq %rax,%r8
+ movq 16(%rbp),%rax
+ movq %r8,(%rdi)
+ movq %rdx,%r8
+ adcq $0,%r8
+
+ mulq %rbx
+ addq %rax,%r9
+ movq 32(%rbp),%rax
+ adcq $0,%rdx
+ addq %r9,%r8
+ leaq 8(%rdi),%rdi
+ movq %rdx,%r9
+ adcq $0,%r9
+
+ mulq %rbx
+ addq %rax,%r10
+ movq 48(%rbp),%rax
+ adcq $0,%rdx
+ addq %r10,%r9
+ movq %rdx,%r10
+ adcq $0,%r10
+
+ mulq %rbx
+ addq %rax,%r11
+ movq 64(%rbp),%rax
+ adcq $0,%rdx
+ addq %r11,%r10
+ movq %rdx,%r11
+ adcq $0,%r11
+
+ mulq %rbx
+ addq %rax,%r12
+ movq 80(%rbp),%rax
+ adcq $0,%rdx
+ addq %r12,%r11
+ movq %rdx,%r12
+ adcq $0,%r12
+
+ mulq %rbx
+ addq %rax,%r13
+ movq 96(%rbp),%rax
+ adcq $0,%rdx
+ addq %r13,%r12
+ movq %rdx,%r13
+ adcq $0,%r13
+
+ mulq %rbx
+ addq %rax,%r14
+ movq 112(%rbp),%rax
+ adcq $0,%rdx
+ addq %r14,%r13
+ movq %rdx,%r14
+ adcq $0,%r14
+
+ mulq %rbx
+ movq 48-16+8(%rsp,%rcx,8),%rbx
+ addq %rax,%r15
+ adcq $0,%rdx
+ addq %r15,%r14
+ movq 0(%rbp),%rax
+ movq %rdx,%r15
+ adcq $0,%r15
+
+ decl %ecx
+ jnz L$8x_tail
+
+ leaq 128(%rbp),%rbp
+ movq 8+8(%rsp),%rdx
+ cmpq 0+8(%rsp),%rbp
+ jae L$8x_tail_done
+
+ movq 48+56+8(%rsp),%rbx
+ negq %rsi
+ movq 0(%rbp),%rax
+ adcq 0(%rdi),%r8
+ adcq 8(%rdi),%r9
+ adcq 16(%rdi),%r10
+ adcq 24(%rdi),%r11
+ adcq 32(%rdi),%r12
+ adcq 40(%rdi),%r13
+ adcq 48(%rdi),%r14
+ adcq 56(%rdi),%r15
+ sbbq %rsi,%rsi
+
+ movl $8,%ecx
+ jmp L$8x_tail
+
+.p2align 5
+L$8x_tail_done:
+ addq (%rdx),%r8
+ xorq %rax,%rax
+
+ negq %rsi
+L$8x_no_tail:
+ adcq 0(%rdi),%r8
+ adcq 8(%rdi),%r9
+ adcq 16(%rdi),%r10
+ adcq 24(%rdi),%r11
+ adcq 32(%rdi),%r12
+ adcq 40(%rdi),%r13
+ adcq 48(%rdi),%r14
+ adcq 56(%rdi),%r15
+ adcq $0,%rax
+ movq -16(%rbp),%rcx
+ xorq %rsi,%rsi
+
+.byte 102,72,15,126,213
+
+ movq %r8,0(%rdi)
+ movq %r9,8(%rdi)
+.byte 102,73,15,126,217
+ 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(%rdi),%rdi
+
+ cmpq %rdx,%rdi
+ jb L$8x_reduction_loop
+
+ subq %r15,%rcx
+ leaq (%rdi,%r9,1),%rbx
+ adcq %rsi,%rsi
+ movq %r9,%rcx
+ orq %rsi,%rax
+.byte 102,72,15,126,207
+ xorq $1,%rax
+.byte 102,72,15,126,206
+ leaq (%rbp,%rax,8),%rbp
+ sarq $3+2,%rcx
+ jmp L$sqr4x_sub
+
+.p2align 5
+L$sqr4x_sub:
+.byte 0x66
+ movq 0(%rbx),%r12
+ movq 8(%rbx),%r13
+ sbbq 0(%rbp),%r12
+ movq 16(%rbx),%r14
+ sbbq 16(%rbp),%r13
+ movq 24(%rbx),%r15
+ leaq 32(%rbx),%rbx
+ sbbq 32(%rbp),%r14
+ movq %r12,0(%rdi)
+ sbbq 48(%rbp),%r15
+ leaq 64(%rbp),%rbp
+ movq %r13,8(%rdi)
+ movq %r14,16(%rdi)
+ movq %r15,24(%rdi)
+ leaq 32(%rdi),%rdi
+
+ incq %rcx
+ jnz L$sqr4x_sub
+ movq %r9,%r10
+ negq %r9
+ .byte 0xf3,0xc3
+
+.globl _bn_from_montgomery
+.private_extern _bn_from_montgomery
+
+.p2align 5
+_bn_from_montgomery:
+ testl $7,%r9d
+ jz bn_from_mont8x
+ xorl %eax,%eax
+ .byte 0xf3,0xc3
+
+
+
+.p2align 5
+bn_from_mont8x:
+.byte 0x67
+ movq %rsp,%rax
+ pushq %rbx
+ pushq %rbp
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ pushq %r15
+.byte 0x67
+ movl %r9d,%r10d
+ shll $3,%r9d
+ shll $3+2,%r10d
+ negq %r9
+ movq (%r8),%r8
+
+
+
+
+
+
+
+ leaq -64(%rsp,%r9,2),%r11
+ subq %rsi,%r11
+ andq $4095,%r11
+ cmpq %r11,%r10
+ jb L$from_sp_alt
+ subq %r11,%rsp
+ leaq -64(%rsp,%r9,2),%rsp
+ jmp L$from_sp_done
+
+.p2align 5
+L$from_sp_alt:
+ leaq 4096-64(,%r9,2),%r10
+ leaq -64(%rsp,%r9,2),%rsp
+ subq %r10,%r11
+ movq $0,%r10
+ cmovcq %r10,%r11
+ subq %r11,%rsp
+L$from_sp_done:
+ andq $-64,%rsp
+ movq %r9,%r10
+ negq %r9
+
+
+
+
+
+
+
+
+
+
+ movq %r8,32(%rsp)
+ movq %rax,40(%rsp)
+L$from_body:
+ movq %r9,%r11
+ leaq 48(%rsp),%rax
+ pxor %xmm0,%xmm0
+ jmp L$mul_by_1
+
+.p2align 5
+L$mul_by_1:
+ movdqu (%rsi),%xmm1
+ movdqu 16(%rsi),%xmm2
+ movdqu 32(%rsi),%xmm3
+ movdqa %xmm0,(%rax,%r9,1)
+ movdqu 48(%rsi),%xmm4
+ movdqa %xmm0,16(%rax,%r9,1)
+.byte 0x48,0x8d,0xb6,0x40,0x00,0x00,0x00
+ movdqa %xmm1,(%rax)
+ movdqa %xmm0,32(%rax,%r9,1)
+ movdqa %xmm2,16(%rax)
+ movdqa %xmm0,48(%rax,%r9,1)
+ movdqa %xmm3,32(%rax)
+ movdqa %xmm4,48(%rax)
+ leaq 64(%rax),%rax
+ subq $64,%r11
+ jnz L$mul_by_1
+
+.byte 102,72,15,110,207
+.byte 102,72,15,110,209
+.byte 0x67
+ movq %rcx,%rbp
+.byte 102,73,15,110,218
+ call sqr8x_reduction
+
+ pxor %xmm0,%xmm0
+ leaq 48(%rsp),%rax
+ movq 40(%rsp),%rsi
+ jmp L$from_mont_zero
+
+.p2align 5
+L$from_mont_zero:
+ movdqa %xmm0,0(%rax)
+ movdqa %xmm0,16(%rax)
+ movdqa %xmm0,32(%rax)
+ movdqa %xmm0,48(%rax)
+ leaq 64(%rax),%rax
+ subq $32,%r9
+ jnz L$from_mont_zero
+
+ movq $1,%rax
+ movq -48(%rsi),%r15
+ movq -40(%rsi),%r14
+ movq -32(%rsi),%r13
+ movq -24(%rsi),%r12
+ movq -16(%rsi),%rbp
+ movq -8(%rsi),%rbx
+ leaq (%rsi),%rsp
+L$from_epilogue:
+ .byte 0xf3,0xc3
+
+.globl _bn_scatter5
+.private_extern _bn_scatter5
+
+.p2align 4
+_bn_scatter5:
+ cmpl $0,%esi
+ 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
+ subl $1,%esi
+ jnz L$scatter
+L$scatter_epilogue:
+ .byte 0xf3,0xc3
+
+
+.globl _bn_gather5
+.private_extern _bn_gather5
+
+.p2align 4
+_bn_gather5:
+ movl %ecx,%r11d
+ shrl $3,%ecx
+ andq $7,%r11
+ notl %ecx
+ leaq L$magic_masks(%rip),%rax
+ andl $3,%ecx
+ leaq 128(%rdx,%r11,8),%rdx
+ movq 0(%rax,%rcx,8),%xmm4
+ movq 8(%rax,%rcx,8),%xmm5
+ movq 16(%rax,%rcx,8),%xmm6
+ movq 24(%rax,%rcx,8),%xmm7
+ jmp L$gather
+.p2align 4
+L$gather:
+ movq -128(%rdx),%xmm0
+ movq -64(%rdx),%xmm1
+ pand %xmm4,%xmm0
+ movq 0(%rdx),%xmm2
+ pand %xmm5,%xmm1
+ movq 64(%rdx),%xmm3
+ pand %xmm6,%xmm2
+ por %xmm1,%xmm0
+ pand %xmm7,%xmm3
+.byte 0x67,0x67
+ por %xmm2,%xmm0
+ leaq 256(%rdx),%rdx
+ por %xmm3,%xmm0
+
+ movq %xmm0,(%rdi)
+ leaq 8(%rdi),%rdi
+ subl $1,%esi
+ jnz L$gather
+ .byte 0xf3,0xc3
+L$SEH_end_bn_gather5:
+
+.p2align 6
+L$magic_masks:
+.long 0,0, 0,0, 0,0, -1,-1
+.long 0,0, 0,0, 0,0, 0,0
+.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
+#endif
diff --git a/mac-x86_64/crypto/cpu-x86_64-asm.S b/mac-x86_64/crypto/cpu-x86_64-asm.S
new file mode 100644
index 0000000..faf4e2f
--- /dev/null
+++ b/mac-x86_64/crypto/cpu-x86_64-asm.S
@@ -0,0 +1,147 @@
+#if defined(__x86_64__)
+.text
+
+.globl _OPENSSL_ia32_cpuid
+.private_extern _OPENSSL_ia32_cpuid
+
+.p2align 4
+_OPENSSL_ia32_cpuid:
+
+
+ movq %rdi,%rdi
+ movq %rbx,%r8
+
+ xorl %eax,%eax
+ movl %eax,8(%rdi)
+ 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 $2049,%r9d
+
+ cmpl $2147483656,%r10d
+ jb L$intel
+
+ movl $2147483656,%eax
+ cpuid
+
+ movzbq %cl,%r10
+ incq %r10
+
+ movl $1,%eax
+ cpuid
+
+ btl $28,%edx
+ jnc L$generic
+ shrl $16,%ebx
+ cmpb %r10b,%bl
+ ja L$generic
+ andl $4026531839,%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
+
+ cmpl $7,%r11d
+ jb L$nocacheinfo
+
+ movl $7,%eax
+ xorl %ecx,%ecx
+ cpuid
+ movl %ebx,8(%rdi)
+
+L$nocacheinfo:
+ movl $1,%eax
+ cpuid
+
+ andl $3220176895,%edx
+ cmpl $0,%r9d
+ jne L$notintel
+ orl $1073741824,%edx
+ andb $15,%ah
+ cmpb $15,%ah
+ jne L$notintel
+ orl $1048576,%edx
+L$notintel:
+ btl $28,%edx
+ jnc L$generic
+ andl $4026531839,%edx
+ cmpl $0,%r10d
+ je L$generic
+
+ orl $268435456,%edx
+ shrl $16,%ebx
+ cmpb $1,%bl
+ ja L$generic
+ andl $4026531839,%edx
+L$generic:
+ andl $2048,%r9d
+ andl $4294965247,%ecx
+ orl %ecx,%r9d
+
+ movl %edx,%r10d
+ btl $27,%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 $4026525695,%eax
+ andl %eax,%r9d
+ andl $4294967263,8(%rdi)
+L$done:
+ movl %r9d,4(%rdi)
+ movl %r10d,0(%rdi)
+ movq %r8,%rbx
+ .byte 0xf3,0xc3
+
+
+#endif
diff --git a/mac-x86_64/crypto/md5/md5-x86_64.S b/mac-x86_64/crypto/md5/md5-x86_64.S
new file mode 100644
index 0000000..1e61479
--- /dev/null
+++ b/mac-x86_64/crypto/md5/md5-x86_64.S
@@ -0,0 +1,671 @@
+#if defined(__x86_64__)
+.text
+.p2align 4
+
+.globl _md5_block_asm_data_order
+.private_extern _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:
+ .byte 0xf3,0xc3
+
+#endif
diff --git a/mac-x86_64/crypto/modes/aesni-gcm-x86_64.S b/mac-x86_64/crypto/modes/aesni-gcm-x86_64.S
new file mode 100644
index 0000000..21d5ad6
--- /dev/null
+++ b/mac-x86_64/crypto/modes/aesni-gcm-x86_64.S
@@ -0,0 +1,19 @@
+#if defined(__x86_64__)
+.text
+
+.globl _aesni_gcm_encrypt
+.private_extern _aesni_gcm_encrypt
+
+_aesni_gcm_encrypt:
+ xorl %eax,%eax
+ .byte 0xf3,0xc3
+
+
+.globl _aesni_gcm_decrypt
+.private_extern _aesni_gcm_decrypt
+
+_aesni_gcm_decrypt:
+ xorl %eax,%eax
+ .byte 0xf3,0xc3
+
+#endif
diff --git a/mac-x86_64/crypto/modes/ghash-x86_64.S b/mac-x86_64/crypto/modes/ghash-x86_64.S
new file mode 100644
index 0000000..305a91c
--- /dev/null
+++ b/mac-x86_64/crypto/modes/ghash-x86_64.S
@@ -0,0 +1,1328 @@
+#if defined(__x86_64__)
+.text
+
+
+.globl _gcm_gmult_4bit
+.private_extern _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:
+ .byte 0xf3,0xc3
+
+.globl _gcm_ghash_4bit
+.private_extern _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:
+ .byte 0xf3,0xc3
+
+.globl _gcm_init_clmul
+.private_extern _gcm_init_clmul
+
+.p2align 4
+_gcm_init_clmul:
+L$_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
+
+
+ pshufd $78,%xmm2,%xmm6
+ movdqa %xmm2,%xmm0
+ pxor %xmm2,%xmm6
+ movdqa %xmm0,%xmm1
+ pshufd $78,%xmm0,%xmm3
+ pxor %xmm0,%xmm3
+.byte 102,15,58,68,194,0
+.byte 102,15,58,68,202,17
+.byte 102,15,58,68,222,0
+ pxor %xmm0,%xmm3
+ pxor %xmm1,%xmm3
+
+ movdqa %xmm3,%xmm4
+ psrldq $8,%xmm3
+ pslldq $8,%xmm4
+ pxor %xmm3,%xmm1
+ pxor %xmm4,%xmm0
+
+ movdqa %xmm0,%xmm4
+ movdqa %xmm0,%xmm3
+ psllq $5,%xmm0
+ pxor %xmm0,%xmm3
+ psllq $1,%xmm0
+ pxor %xmm3,%xmm0
+ psllq $57,%xmm0
+ movdqa %xmm0,%xmm3
+ pslldq $8,%xmm0
+ psrldq $8,%xmm3
+ pxor %xmm4,%xmm0
+ pxor %xmm3,%xmm1
+
+
+ movdqa %xmm0,%xmm4
+ psrlq $1,%xmm0
+ pxor %xmm4,%xmm1
+ pxor %xmm0,%xmm4
+ psrlq $5,%xmm0
+ pxor %xmm4,%xmm0
+ psrlq $1,%xmm0
+ pxor %xmm1,%xmm0
+ pshufd $78,%xmm2,%xmm3
+ pshufd $78,%xmm0,%xmm4
+ pxor %xmm2,%xmm3
+ movdqu %xmm2,0(%rdi)
+ pxor %xmm0,%xmm4
+ movdqu %xmm0,16(%rdi)
+.byte 102,15,58,15,227,8
+ movdqu %xmm4,32(%rdi)
+ movdqa %xmm0,%xmm1
+ pshufd $78,%xmm0,%xmm3
+ pxor %xmm0,%xmm3
+.byte 102,15,58,68,194,0
+.byte 102,15,58,68,202,17
+.byte 102,15,58,68,222,0
+ pxor %xmm0,%xmm3
+ pxor %xmm1,%xmm3
+
+ movdqa %xmm3,%xmm4
+ psrldq $8,%xmm3
+ pslldq $8,%xmm4
+ pxor %xmm3,%xmm1
+ pxor %xmm4,%xmm0
+
+ movdqa %xmm0,%xmm4
+ movdqa %xmm0,%xmm3
+ psllq $5,%xmm0
+ pxor %xmm0,%xmm3
+ psllq $1,%xmm0
+ pxor %xmm3,%xmm0
+ psllq $57,%xmm0
+ movdqa %xmm0,%xmm3
+ pslldq $8,%xmm0
+ psrldq $8,%xmm3
+ pxor %xmm4,%xmm0
+ pxor %xmm3,%xmm1
+
+
+ movdqa %xmm0,%xmm4
+ psrlq $1,%xmm0
+ pxor %xmm4,%xmm1
+ pxor %xmm0,%xmm4
+ psrlq $5,%xmm0
+ pxor %xmm4,%xmm0
+ psrlq $1,%xmm0
+ pxor %xmm1,%xmm0
+ movdqa %xmm0,%xmm5
+ movdqa %xmm0,%xmm1
+ pshufd $78,%xmm0,%xmm3
+ pxor %xmm0,%xmm3
+.byte 102,15,58,68,194,0
+.byte 102,15,58,68,202,17
+.byte 102,15,58,68,222,0
+ pxor %xmm0,%xmm3
+ pxor %xmm1,%xmm3
+
+ movdqa %xmm3,%xmm4
+ psrldq $8,%xmm3
+ pslldq $8,%xmm4
+ pxor %xmm3,%xmm1
+ pxor %xmm4,%xmm0
+
+ movdqa %xmm0,%xmm4
+ movdqa %xmm0,%xmm3
+ psllq $5,%xmm0
+ pxor %xmm0,%xmm3
+ psllq $1,%xmm0
+ pxor %xmm3,%xmm0
+ psllq $57,%xmm0
+ movdqa %xmm0,%xmm3
+ pslldq $8,%xmm0
+ psrldq $8,%xmm3
+ pxor %xmm4,%xmm0
+ pxor %xmm3,%xmm1
+
+
+ movdqa %xmm0,%xmm4
+ psrlq $1,%xmm0
+ pxor %xmm4,%xmm1
+ pxor %xmm0,%xmm4
+ psrlq $5,%xmm0
+ pxor %xmm4,%xmm0
+ psrlq $1,%xmm0
+ pxor %xmm1,%xmm0
+ pshufd $78,%xmm5,%xmm3
+ pshufd $78,%xmm0,%xmm4
+ pxor %xmm5,%xmm3
+ movdqu %xmm5,48(%rdi)
+ pxor %xmm0,%xmm4
+ movdqu %xmm0,64(%rdi)
+.byte 102,15,58,15,227,8
+ movdqu %xmm4,80(%rdi)
+ .byte 0xf3,0xc3
+
+.globl _gcm_gmult_clmul
+.private_extern _gcm_gmult_clmul
+
+.p2align 4
+_gcm_gmult_clmul:
+L$_gmult_clmul:
+ movdqu (%rdi),%xmm0
+ movdqa L$bswap_mask(%rip),%xmm5
+ movdqu (%rsi),%xmm2
+ movdqu 32(%rsi),%xmm4
+.byte 102,15,56,0,197
+ movdqa %xmm0,%xmm1
+ pshufd $78,%xmm0,%xmm3
+ pxor %xmm0,%xmm3
+.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,%xmm4
+ movdqa %xmm0,%xmm3
+ psllq $5,%xmm0
+ pxor %xmm0,%xmm3
+ psllq $1,%xmm0
+ pxor %xmm3,%xmm0
+ psllq $57,%xmm0
+ movdqa %xmm0,%xmm3
+ pslldq $8,%xmm0
+ psrldq $8,%xmm3
+ pxor %xmm4,%xmm0
+ pxor %xmm3,%xmm1
+
+
+ movdqa %xmm0,%xmm4
+ psrlq $1,%xmm0
+ pxor %xmm4,%xmm1
+ pxor %xmm0,%xmm4
+ psrlq $5,%xmm0
+ pxor %xmm4,%xmm0
+ psrlq $1,%xmm0
+ pxor %xmm1,%xmm0
+.byte 102,15,56,0,197
+ movdqu %xmm0,(%rdi)
+ .byte 0xf3,0xc3
+
+.globl _gcm_ghash_clmul
+.private_extern _gcm_ghash_clmul
+
+.p2align 5
+_gcm_ghash_clmul:
+L$_ghash_clmul:
+ movdqa L$bswap_mask(%rip),%xmm10
+
+ movdqu (%rdi),%xmm0
+ movdqu (%rsi),%xmm2
+ movdqu 32(%rsi),%xmm7
+.byte 102,65,15,56,0,194
+
+ subq $16,%rcx
+ jz L$odd_tail
+
+ movdqu 16(%rsi),%xmm6
+ movl _OPENSSL_ia32cap_P+4(%rip),%eax
+ cmpq $48,%rcx
+ jb L$skip4x
+
+ andl $71303168,%eax
+ cmpl $4194304,%eax
+ je L$skip4x
+
+ subq $48,%rcx
+ movq $11547335547999543296,%rax
+ movdqu 48(%rsi),%xmm14
+ movdqu 64(%rsi),%xmm15
+
+
+
+
+ movdqu 48(%rdx),%xmm3
+ movdqu 32(%rdx),%xmm11
+.byte 102,65,15,56,0,218
+.byte 102,69,15,56,0,218
+ movdqa %xmm3,%xmm5
+ pshufd $78,%xmm3,%xmm4
+ pxor %xmm3,%xmm4
+.byte 102,15,58,68,218,0
+.byte 102,15,58,68,234,17
+.byte 102,15,58,68,231,0
+
+ movdqa %xmm11,%xmm13
+ pshufd $78,%xmm11,%xmm12
+ pxor %xmm11,%xmm12
+.byte 102,68,15,58,68,222,0
+.byte 102,68,15,58,68,238,17
+.byte 102,68,15,58,68,231,16
+ xorps %xmm11,%xmm3
+ xorps %xmm13,%xmm5
+ movups 80(%rsi),%xmm7
+ xorps %xmm12,%xmm4
+
+ movdqu 16(%rdx),%xmm11
+ movdqu 0(%rdx),%xmm8
+.byte 102,69,15,56,0,218
+.byte 102,69,15,56,0,194
+ movdqa %xmm11,%xmm13
+ pshufd $78,%xmm11,%xmm12
+ pxor %xmm8,%xmm0
+ pxor %xmm11,%xmm12
+.byte 102,69,15,58,68,222,0
+ movdqa %xmm0,%xmm1
+ pshufd $78,%xmm0,%xmm8
+ pxor %xmm0,%xmm8
+.byte 102,69,15,58,68,238,17
+.byte 102,68,15,58,68,231,0
+ xorps %xmm11,%xmm3
+ xorps %xmm13,%xmm5
+
+ leaq 64(%rdx),%rdx
+ subq $64,%rcx
+ jc L$tail4x
+
+ jmp L$mod4_loop
+.p2align 5
+L$mod4_loop:
+.byte 102,65,15,58,68,199,0
+ xorps %xmm12,%xmm4
+ movdqu 48(%rdx),%xmm11
+.byte 102,69,15,56,0,218
+.byte 102,65,15,58,68,207,17
+ xorps %xmm3,%xmm0
+ movdqu 32(%rdx),%xmm3
+ movdqa %xmm11,%xmm13
+.byte 102,68,15,58,68,199,16
+ pshufd $78,%xmm11,%xmm12
+ xorps %xmm5,%xmm1
+ pxor %xmm11,%xmm12
+.byte 102,65,15,56,0,218
+ movups 32(%rsi),%xmm7
+ xorps %xmm4,%xmm8
+.byte 102,68,15,58,68,218,0
+ pshufd $78,%xmm3,%xmm4
+
+ pxor %xmm0,%xmm8
+ movdqa %xmm3,%xmm5
+ pxor %xmm1,%xmm8
+ pxor %xmm3,%xmm4
+ movdqa %xmm8,%xmm9
+.byte 102,68,15,58,68,234,17
+ pslldq $8,%xmm8
+ psrldq $8,%xmm9
+ pxor %xmm8,%xmm0
+ movdqa L$7_mask(%rip),%xmm8
+ pxor %xmm9,%xmm1
+.byte 102,76,15,110,200
+
+ pand %xmm0,%xmm8
+.byte 102,69,15,56,0,200
+ pxor %xmm0,%xmm9
+.byte 102,68,15,58,68,231,0
+ psllq $57,%xmm9
+ movdqa %xmm9,%xmm8
+ pslldq $8,%xmm9
+.byte 102,15,58,68,222,0
+ psrldq $8,%xmm8
+ pxor %xmm9,%xmm0
+ pxor %xmm8,%xmm1
+ movdqu 0(%rdx),%xmm8
+
+ movdqa %xmm0,%xmm9
+ psrlq $1,%xmm0
+.byte 102,15,58,68,238,17
+ xorps %xmm11,%xmm3
+ movdqu 16(%rdx),%xmm11
+.byte 102,69,15,56,0,218
+.byte 102,15,58,68,231,16
+ xorps %xmm13,%xmm5
+ movups 80(%rsi),%xmm7
+.byte 102,69,15,56,0,194
+ pxor %xmm9,%xmm1
+ pxor %xmm0,%xmm9
+ psrlq $5,%xmm0
+
+ movdqa %xmm11,%xmm13
+ pxor %xmm12,%xmm4
+ pshufd $78,%xmm11,%xmm12
+ pxor %xmm9,%xmm0
+ pxor %xmm8,%xmm1
+ pxor %xmm11,%xmm12
+.byte 102,69,15,58,68,222,0
+ psrlq $1,%xmm0
+ pxor %xmm1,%xmm0
+ movdqa %xmm0,%xmm1
+.byte 102,69,15,58,68,238,17
+ xorps %xmm11,%xmm3
+ pshufd $78,%xmm0,%xmm8
+ pxor %xmm0,%xmm8
+
+.byte 102,68,15,58,68,231,0
+ xorps %xmm13,%xmm5
+
+ leaq 64(%rdx),%rdx
+ subq $64,%rcx
+ jnc L$mod4_loop
+
+L$tail4x:
+.byte 102,65,15,58,68,199,0
+.byte 102,65,15,58,68,207,17
+.byte 102,68,15,58,68,199,16
+ xorps %xmm12,%xmm4
+ xorps %xmm3,%xmm0
+ xorps %xmm5,%xmm1
+ pxor %xmm0,%xmm1
+ pxor %xmm4,%xmm8
+
+ pxor %xmm1,%xmm8
+ pxor %xmm0,%xmm1
+
+ movdqa %xmm8,%xmm9
+ psrldq $8,%xmm8
+ pslldq $8,%xmm9
+ pxor %xmm8,%xmm1
+ pxor %xmm9,%xmm0
+
+ movdqa %xmm0,%xmm4
+ movdqa %xmm0,%xmm3
+ psllq $5,%xmm0
+ pxor %xmm0,%xmm3
+ psllq $1,%xmm0
+ pxor %xmm3,%xmm0
+ psllq $57,%xmm0
+ movdqa %xmm0,%xmm3
+ pslldq $8,%xmm0
+ psrldq $8,%xmm3
+ pxor %xmm4,%xmm0
+ pxor %xmm3,%xmm1
+
+
+ movdqa %xmm0,%xmm4
+ psrlq $1,%xmm0
+ pxor %xmm4,%xmm1
+ pxor %xmm0,%xmm4
+ psrlq $5,%xmm0
+ pxor %xmm4,%xmm0
+ psrlq $1,%xmm0
+ pxor %xmm1,%xmm0
+ addq $64,%rcx
+ jz L$done
+ movdqu 32(%rsi),%xmm7
+ subq $16,%rcx
+ jz L$odd_tail
+L$skip4x:
+
+
+
+
+
+ movdqu (%rdx),%xmm8
+ movdqu 16(%rdx),%xmm3
+.byte 102,69,15,56,0,194
+.byte 102,65,15,56,0,218
+ pxor %xmm8,%xmm0
+
+ movdqa %xmm3,%xmm5
+ pshufd $78,%xmm3,%xmm4
+ pxor %xmm3,%xmm4
+.byte 102,15,58,68,218,0
+.byte 102,15,58,68,234,17
+.byte 102,15,58,68,231,0
+
+ leaq 32(%rdx),%rdx
+ nop
+ subq $32,%rcx
+ jbe L$even_tail
+ nop
+ jmp L$mod_loop
+
+.p2align 5
+L$mod_loop:
+ movdqa %xmm0,%xmm1
+ movdqa %xmm4,%xmm8
+ pshufd $78,%xmm0,%xmm4
+ pxor %xmm0,%xmm4
+
+.byte 102,15,58,68,198,0
+.byte 102,15,58,68,206,17
+.byte 102,15,58,68,231,16
+
+ pxor %xmm3,%xmm0
+ pxor %xmm5,%xmm1
+ movdqu (%rdx),%xmm9
+ pxor %xmm0,%xmm8
+.byte 102,69,15,56,0,202
+ movdqu 16(%rdx),%xmm3
+
+ pxor %xmm1,%xmm8
+ pxor %xmm9,%xmm1
+ pxor %xmm8,%xmm4
+.byte 102,65,15,56,0,218
+ movdqa %xmm4,%xmm8
+ psrldq $8,%xmm8
+ pslldq $8,%xmm4
+ pxor %xmm8,%xmm1
+ pxor %xmm4,%xmm0
+
+ movdqa %xmm3,%xmm5
+
+ movdqa %xmm0,%xmm9
+ movdqa %xmm0,%xmm8
+ psllq $5,%xmm0
+ pxor %xmm0,%xmm8
+.byte 102,15,58,68,218,0
+ psllq $1,%xmm0
+ pxor %xmm8,%xmm0
+ psllq $57,%xmm0
+ movdqa %xmm0,%xmm8
+ pslldq $8,%xmm0
+ psrldq $8,%xmm8
+ pxor %xmm9,%xmm0
+ pshufd $78,%xmm5,%xmm4
+ pxor %xmm8,%xmm1
+ pxor %xmm5,%xmm4
+
+ movdqa %xmm0,%xmm9
+ psrlq $1,%xmm0
+.byte 102,15,58,68,234,17
+ pxor %xmm9,%xmm1
+ pxor %xmm0,%xmm9
+ psrlq $5,%xmm0
+ pxor %xmm9,%xmm0
+ leaq 32(%rdx),%rdx
+ psrlq $1,%xmm0
+.byte 102,15,58,68,231,0
+ pxor %xmm1,%xmm0
+
+ subq $32,%rcx
+ ja L$mod_loop
+
+L$even_tail:
+ movdqa %xmm0,%xmm1
+ movdqa %xmm4,%xmm8
+ pshufd $78,%xmm0,%xmm4
+ pxor %xmm0,%xmm4
+
+.byte 102,15,58,68,198,0
+.byte 102,15,58,68,206,17
+.byte 102,15,58,68,231,16
+
+ pxor %xmm3,%xmm0
+ pxor %xmm5,%xmm1
+ pxor %xmm0,%xmm8
+ pxor %xmm1,%xmm8
+ pxor %xmm8,%xmm4
+ movdqa %xmm4,%xmm8
+ psrldq $8,%xmm8
+ pslldq $8,%xmm4
+ pxor %xmm8,%xmm1
+ pxor %xmm4,%xmm0
+
+ movdqa %xmm0,%xmm4
+ movdqa %xmm0,%xmm3
+ psllq $5,%xmm0
+ pxor %xmm0,%xmm3
+ psllq $1,%xmm0
+ pxor %xmm3,%xmm0
+ psllq $57,%xmm0
+ movdqa %xmm0,%xmm3
+ pslldq $8,%xmm0
+ psrldq $8,%xmm3
+ pxor %xmm4,%xmm0
+ pxor %xmm3,%xmm1
+
+
+ movdqa %xmm0,%xmm4
+ psrlq $1,%xmm0
+ pxor %xmm4,%xmm1
+ pxor %xmm0,%xmm4
+ psrlq $5,%xmm0
+ pxor %xmm4,%xmm0
+ psrlq $1,%xmm0
+ pxor %xmm1,%xmm0
+ testq %rcx,%rcx
+ jnz L$done
+
+L$odd_tail:
+ movdqu (%rdx),%xmm8
+.byte 102,69,15,56,0,194
+ pxor %xmm8,%xmm0
+ movdqa %xmm0,%xmm1
+ pshufd $78,%xmm0,%xmm3
+ pxor %xmm0,%xmm3
+.byte 102,15,58,68,194,0
+.byte 102,15,58,68,202,17
+.byte 102,15,58,68,223,0
+ pxor %xmm0,%xmm3
+ pxor %xmm1,%xmm3
+
+ movdqa %xmm3,%xmm4
+ psrldq $8,%xmm3
+ pslldq $8,%xmm4
+ pxor %xmm3,%xmm1
+ pxor %xmm4,%xmm0
+
+ movdqa %xmm0,%xmm4
+ movdqa %xmm0,%xmm3
+ psllq $5,%xmm0
+ pxor %xmm0,%xmm3
+ psllq $1,%xmm0
+ pxor %xmm3,%xmm0
+ psllq $57,%xmm0
+ movdqa %xmm0,%xmm3
+ pslldq $8,%xmm0
+ psrldq $8,%xmm3
+ pxor %xmm4,%xmm0
+ pxor %xmm3,%xmm1
+
+
+ movdqa %xmm0,%xmm4
+ psrlq $1,%xmm0
+ pxor %xmm4,%xmm1
+ pxor %xmm0,%xmm4
+ psrlq $5,%xmm0
+ pxor %xmm4,%xmm0
+ psrlq $1,%xmm0
+ pxor %xmm1,%xmm0
+L$done:
+.byte 102,65,15,56,0,194
+ movdqu %xmm0,(%rdi)
+ .byte 0xf3,0xc3
+
+.globl _gcm_init_avx
+.private_extern _gcm_init_avx
+
+.p2align 5
+_gcm_init_avx:
+ jmp L$_init_clmul
+
+.globl _gcm_gmult_avx
+.private_extern _gcm_gmult_avx
+
+.p2align 5
+_gcm_gmult_avx:
+ jmp L$_gmult_clmul
+
+.globl _gcm_ghash_avx
+.private_extern _gcm_ghash_avx
+
+.p2align 5
+_gcm_ghash_avx:
+ jmp L$_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
+L$7_mask:
+.long 7,0,7,0
+L$7_mask_poly:
+.long 7,0,450,0
+.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
+#endif
diff --git a/mac-x86_64/crypto/rc4/rc4-md5-x86_64.S b/mac-x86_64/crypto/rc4/rc4-md5-x86_64.S
new file mode 100644
index 0000000..31ee7d2
--- /dev/null
+++ b/mac-x86_64/crypto/rc4/rc4-md5-x86_64.S
@@ -0,0 +1,1262 @@
+#if defined(__x86_64__)
+.text
+.p2align 4
+
+.globl _rc4_md5_enc
+.private_extern _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:
+ .byte 0xf3,0xc3
+
+#endif
diff --git a/mac-x86_64/crypto/rc4/rc4-x86_64.S b/mac-x86_64/crypto/rc4/rc4-x86_64.S
new file mode 100644
index 0000000..44147ff
--- /dev/null
+++ b/mac-x86_64/crypto/rc4/rc4-x86_64.S
@@ -0,0 +1,622 @@
+#if defined(__x86_64__)
+.text
+
+
+.globl _asm_RC4
+.private_extern _asm_RC4
+
+.p2align 4
+_asm_RC4:
+ orq %rsi,%rsi
+ jne L$entry
+ .byte 0xf3,0xc3
+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 $30,%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,(%r12,%r13,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,(%r12,%r13,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,(%r12,%r13,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,(%r12,%r13,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,(%r12,%r13,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,(%r12,%r13,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:
+ .byte 0xf3,0xc3
+
+.globl _asm_RC4_set_key
+.private_extern _asm_RC4_set_key
+
+.p2align 4
+_asm_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 $20,%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)
+ .byte 0xf3,0xc3
+
+
+.globl _RC4_options
+.private_extern _RC4_options
+
+.p2align 4
+_RC4_options:
+ leaq L$opts(%rip),%rax
+ movq _OPENSSL_ia32cap_P(%rip),%rdx
+ movl (%rdx),%edx
+ btl $20,%edx
+ jc L$8xchar
+ btl $30,%edx
+ jnc L$done
+ addq $25,%rax
+ .byte 0xf3,0xc3
+L$8xchar:
+ addq $12,%rax
+L$done:
+ .byte 0xf3,0xc3
+.p2align 6
+L$opts:
+.byte 114,99,52,40,56,120,44,105,110,116,41,0
+.byte 114,99,52,40,56,120,44,99,104,97,114,41,0
+.byte 114,99,52,40,49,54,120,44,105,110,116,41,0
+.byte 82,67,52,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
+
+#endif
diff --git a/mac-x86_64/crypto/sha/sha1-x86_64.S b/mac-x86_64/crypto/sha/sha1-x86_64.S
new file mode 100644
index 0000000..044dc5b
--- /dev/null
+++ b/mac-x86_64/crypto/sha/sha1-x86_64.S
@@ -0,0 +1,2425 @@
+#if defined(__x86_64__)
+.text
+
+
+.globl _sha1_block_data_order
+.private_extern _sha1_block_data_order
+
+.p2align 4
+_sha1_block_data_order:
+ movl _OPENSSL_ia32cap_P+0(%rip),%r9d
+ movl _OPENSSL_ia32cap_P+4(%rip),%r8d
+ movl _OPENSSL_ia32cap_P+8(%rip),%r10d
+ testl $512,%r8d
+ jz L$ialu
+ jmp _ssse3_shortcut
+
+.p2align 4
+L$ialu:
+ movq %rsp,%rax
+ pushq %rbx
+ pushq %rbp
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ movq %rdi,%r8
+ subq $72,%rsp
+ movq %rsi,%r9
+ andq $-64,%rsp
+ movq %rdx,%r10
+ movq %rax,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 4(%r9),%ebp
+ movl %r12d,%eax
+ movl %edx,0(%rsp)
+ movl %esi,%ecx
+ bswapl %ebp
+ xorl %r11d,%eax
+ roll $5,%ecx
+ andl %edi,%eax
+ leal 1518500249(%rdx,%r13,1),%r13d
+ addl %ecx,%r13d
+ xorl %r12d,%eax
+ roll $30,%edi
+ addl %eax,%r13d
+ movl 8(%r9),%r14d
+ movl %r11d,%eax
+ movl %ebp,4(%rsp)
+ movl %r13d,%ecx
+ bswapl %r14d
+ xorl %edi,%eax
+ roll $5,%ecx
+ andl %esi,%eax
+ leal 1518500249(%rbp,%r12,1),%r12d
+ addl %ecx,%r12d
+ xorl %r11d,%eax
+ roll $30,%esi
+ addl %eax,%r12d
+ movl 12(%r9),%edx
+ movl %edi,%eax
+ movl %r14d,8(%rsp)
+ movl %r12d,%ecx
+ bswapl %edx
+ xorl %esi,%eax
+ roll $5,%ecx
+ andl %r13d,%eax
+ leal 1518500249(%r14,%r11,1),%r11d
+ addl %ecx,%r11d
+ xorl %edi,%eax
+ roll $30,%r13d
+ addl %eax,%r11d
+ movl 16(%r9),%ebp
+ movl %esi,%eax
+ movl %edx,12(%rsp)
+ movl %r11d,%ecx
+ bswapl %ebp
+ xorl %r13d,%eax
+ roll $5,%ecx
+ andl %r12d,%eax
+ leal 1518500249(%rdx,%rdi,1),%edi
+ addl %ecx,%edi
+ xorl %esi,%eax
+ roll $30,%r12d
+ addl %eax,%edi
+ movl 20(%r9),%r14d
+ movl %r13d,%eax
+ movl %ebp,16(%rsp)
+ movl %edi,%ecx
+ bswapl %r14d
+ xorl %r12d,%eax
+ roll $5,%ecx
+ andl %r11d,%eax
+ leal 1518500249(%rbp,%rsi,1),%esi
+ addl %ecx,%esi
+ xorl %r13d,%eax
+ roll $30,%r11d
+ addl %eax,%esi
+ movl 24(%r9),%edx
+ movl %r12d,%eax
+ movl %r14d,20(%rsp)
+ movl %esi,%ecx
+ bswapl %edx
+ xorl %r11d,%eax
+ roll $5,%ecx
+ andl %edi,%eax
+ leal 1518500249(%r14,%r13,1),%r13d
+ addl %ecx,%r13d
+ xorl %r12d,%eax
+ roll $30,%edi
+ addl %eax,%r13d
+ movl 28(%r9),%ebp
+ movl %r11d,%eax
+ movl %edx,24(%rsp)
+ movl %r13d,%ecx
+ bswapl %ebp
+ xorl %edi,%eax
+ roll $5,%ecx
+ andl %esi,%eax
+ leal 1518500249(%rdx,%r12,1),%r12d
+ addl %ecx,%r12d
+ xorl %r11d,%eax
+ roll $30,%esi
+ addl %eax,%r12d
+ movl 32(%r9),%r14d
+ movl %edi,%eax
+ movl %ebp,28(%rsp)
+ movl %r12d,%ecx
+ bswapl %r14d
+ xorl %esi,%eax
+ roll $5,%ecx
+ andl %r13d,%eax
+ leal 1518500249(%rbp,%r11,1),%r11d
+ addl %ecx,%r11d
+ xorl %edi,%eax
+ roll $30,%r13d
+ addl %eax,%r11d
+ movl 36(%r9),%edx
+ movl %esi,%eax
+ movl %r14d,32(%rsp)
+ movl %r11d,%ecx
+ bswapl %edx
+ xorl %r13d,%eax
+ roll $5,%ecx
+ andl %r12d,%eax
+ leal 1518500249(%r14,%rdi,1),%edi
+ addl %ecx,%edi
+ xorl %esi,%eax
+ roll $30,%r12d
+ addl %eax,%edi
+ movl 40(%r9),%ebp
+ movl %r13d,%eax
+ movl %edx,36(%rsp)
+ movl %edi,%ecx
+ bswapl %ebp
+ xorl %r12d,%eax
+ roll $5,%ecx
+ andl %r11d,%eax
+ leal 1518500249(%rdx,%rsi,1),%esi
+ addl %ecx,%esi
+ xorl %r13d,%eax
+ roll $30,%r11d
+ addl %eax,%esi
+ movl 44(%r9),%r14d
+ movl %r12d,%eax
+ movl %ebp,40(%rsp)
+ movl %esi,%ecx
+ bswapl %r14d
+ xorl %r11d,%eax
+ roll $5,%ecx
+ andl %edi,%eax
+ leal 1518500249(%rbp,%r13,1),%r13d
+ addl %ecx,%r13d
+ xorl %r12d,%eax
+ roll $30,%edi
+ addl %eax,%r13d
+ movl 48(%r9),%edx
+ movl %r11d,%eax
+ movl %r14d,44(%rsp)
+ movl %r13d,%ecx
+ bswapl %edx
+ xorl %edi,%eax
+ roll $5,%ecx
+ andl %esi,%eax
+ leal 1518500249(%r14,%r12,1),%r12d
+ addl %ecx,%r12d
+ xorl %r11d,%eax
+ roll $30,%esi
+ addl %eax,%r12d
+ movl 52(%r9),%ebp
+ movl %edi,%eax
+ movl %edx,48(%rsp)
+ movl %r12d,%ecx
+ bswapl %ebp
+ xorl %esi,%eax
+ roll $5,%ecx
+ andl %r13d,%eax
+ leal 1518500249(%rdx,%r11,1),%r11d
+ addl %ecx,%r11d
+ xorl %edi,%eax
+ roll $30,%r13d
+ addl %eax,%r11d
+ movl 56(%r9),%r14d
+ movl %esi,%eax
+ movl %ebp,52(%rsp)
+ movl %r11d,%ecx
+ bswapl %r14d
+ xorl %r13d,%eax
+ roll $5,%ecx
+ andl %r12d,%eax
+ leal 1518500249(%rbp,%rdi,1),%edi
+ addl %ecx,%edi
+ xorl %esi,%eax
+ roll $30,%r12d
+ addl %eax,%edi
+ movl 60(%r9),%edx
+ movl %r13d,%eax
+ movl %r14d,56(%rsp)
+ movl %edi,%ecx
+ bswapl %edx
+ xorl %r12d,%eax
+ roll $5,%ecx
+ andl %r11d,%eax
+ leal 1518500249(%r14,%rsi,1),%esi
+ addl %ecx,%esi
+ xorl %r13d,%eax
+ roll $30,%r11d
+ addl %eax,%esi
+ xorl 0(%rsp),%ebp
+ movl %r12d,%eax
+ movl %edx,60(%rsp)
+ movl %esi,%ecx
+ xorl 8(%rsp),%ebp
+ xorl %r11d,%eax
+ roll $5,%ecx
+ xorl 32(%rsp),%ebp
+ andl %edi,%eax
+ leal 1518500249(%rdx,%r13,1),%r13d
+ roll $30,%edi
+ xorl %r12d,%eax
+ addl %ecx,%r13d
+ roll $1,%ebp
+ addl %eax,%r13d
+ xorl 4(%rsp),%r14d
+ movl %r11d,%eax
+ movl %ebp,0(%rsp)
+ movl %r13d,%ecx
+ xorl 12(%rsp),%r14d
+ xorl %edi,%eax
+ roll $5,%ecx
+ xorl 36(%rsp),%r14d
+ andl %esi,%eax
+ leal 1518500249(%rbp,%r12,1),%r12d
+ roll $30,%esi
+ xorl %r11d,%eax
+ addl %ecx,%r12d
+ roll $1,%r14d
+ addl %eax,%r12d
+ xorl 8(%rsp),%edx
+ movl %edi,%eax
+ movl %r14d,4(%rsp)
+ movl %r12d,%ecx
+ xorl 16(%rsp),%edx
+ xorl %esi,%eax
+ roll $5,%ecx
+ xorl 40(%rsp),%edx
+ andl %r13d,%eax
+ leal 1518500249(%r14,%r11,1),%r11d
+ roll $30,%r13d
+ xorl %edi,%eax
+ addl %ecx,%r11d
+ roll $1,%edx
+ addl %eax,%r11d
+ xorl 12(%rsp),%ebp
+ movl %esi,%eax
+ movl %edx,8(%rsp)
+ movl %r11d,%ecx
+ xorl 20(%rsp),%ebp
+ xorl %r13d,%eax
+ roll $5,%ecx
+ xorl 44(%rsp),%ebp
+ andl %r12d,%eax
+ leal 1518500249(%rdx,%rdi,1),%edi
+ roll $30,%r12d
+ xorl %esi,%eax
+ addl %ecx,%edi
+ roll $1,%ebp
+ addl %eax,%edi
+ xorl 16(%rsp),%r14d
+ movl %r13d,%eax
+ movl %ebp,12(%rsp)
+ movl %edi,%ecx
+ xorl 24(%rsp),%r14d
+ xorl %r12d,%eax
+ roll $5,%ecx
+ xorl 48(%rsp),%r14d
+ andl %r11d,%eax
+ leal 1518500249(%rbp,%rsi,1),%esi
+ roll $30,%r11d
+ xorl %r13d,%eax
+ addl %ecx,%esi
+ roll $1,%r14d
+ addl %eax,%esi
+ xorl 20(%rsp),%edx
+ movl %edi,%eax
+ movl %r14d,16(%rsp)
+ movl %esi,%ecx
+ xorl 28(%rsp),%edx
+ xorl %r12d,%eax
+ roll $5,%ecx
+ xorl 52(%rsp),%edx
+ leal 1859775393(%r14,%r13,1),%r13d
+ xorl %r11d,%eax
+ addl %ecx,%r13d
+ roll $30,%edi
+ addl %eax,%r13d
+ roll $1,%edx
+ xorl 24(%rsp),%ebp
+ movl %esi,%eax
+ movl %edx,20(%rsp)
+ movl %r13d,%ecx
+ xorl 32(%rsp),%ebp
+ xorl %r11d,%eax
+ roll $5,%ecx
+ xorl 56(%rsp),%ebp
+ leal 1859775393(%rdx,%r12,1),%r12d
+ xorl %edi,%eax
+ addl %ecx,%r12d
+ roll $30,%esi
+ addl %eax,%r12d
+ roll $1,%ebp
+ xorl 28(%rsp),%r14d
+ movl %r13d,%eax
+ movl %ebp,24(%rsp)
+ movl %r12d,%ecx
+ xorl 36(%rsp),%r14d
+ xorl %edi,%eax
+ roll $5,%ecx
+ xorl 60(%rsp),%r14d
+ leal 1859775393(%rbp,%r11,1),%r11d
+ xorl %esi,%eax
+ addl %ecx,%r11d
+ roll $30,%r13d
+ addl %eax,%r11d
+ roll $1,%r14d
+ xorl 32(%rsp),%edx
+ movl %r12d,%eax
+ movl %r14d,28(%rsp)
+ movl %r11d,%ecx
+ xorl 40(%rsp),%edx
+ xorl %esi,%eax
+ roll $5,%ecx
+ xorl 0(%rsp),%edx
+ leal 1859775393(%r14,%rdi,1),%edi
+ xorl %r13d,%eax
+ addl %ecx,%edi
+ roll $30,%r12d
+ addl %eax,%edi
+ roll $1,%edx
+ xorl 36(%rsp),%ebp
+ movl %r11d,%eax
+ movl %edx,32(%rsp)
+ movl %edi,%ecx
+ xorl 44(%rsp),%ebp
+ xorl %r13d,%eax
+ roll $5,%ecx
+ xorl 4(%rsp),%ebp
+ leal 1859775393(%rdx,%rsi,1),%esi
+ xorl %r12d,%eax
+ addl %ecx,%esi
+ roll $30,%r11d
+ addl %eax,%esi
+ roll $1,%ebp
+ xorl 40(%rsp),%r14d
+ movl %edi,%eax
+ movl %ebp,36(%rsp)
+ movl %esi,%ecx
+ xorl 48(%rsp),%r14d
+ xorl %r12d,%eax
+ roll $5,%ecx
+ xorl 8(%rsp),%r14d
+ leal 1859775393(%rbp,%r13,1),%r13d
+ xorl %r11d,%eax
+ addl %ecx,%r13d
+ roll $30,%edi
+ addl %eax,%r13d
+ roll $1,%r14d
+ xorl 44(%rsp),%edx
+ movl %esi,%eax
+ movl %r14d,40(%rsp)
+ movl %r13d,%ecx
+ xorl 52(%rsp),%edx
+ xorl %r11d,%eax
+ roll $5,%ecx
+ xorl 12(%rsp),%edx
+ leal 1859775393(%r14,%r12,1),%r12d
+ xorl %edi,%eax
+ addl %ecx,%r12d
+ roll $30,%esi
+ addl %eax,%r12d
+ roll $1,%edx
+ xorl 48(%rsp),%ebp
+ movl %r13d,%eax
+ movl %edx,44(%rsp)
+ movl %r12d,%ecx
+ xorl 56(%rsp),%ebp
+ xorl %edi,%eax
+ roll $5,%ecx
+ xorl 16(%rsp),%ebp
+ leal 1859775393(%rdx,%r11,1),%r11d
+ xorl %esi,%eax
+ addl %ecx,%r11d
+ roll $30,%r13d
+ addl %eax,%r11d
+ roll $1,%ebp
+ xorl 52(%rsp),%r14d
+ movl %r12d,%eax
+ movl %ebp,48(%rsp)
+ movl %r11d,%ecx
+ xorl 60(%rsp),%r14d
+ xorl %esi,%eax
+ roll $5,%ecx
+ xorl 20(%rsp),%r14d
+ leal 1859775393(%rbp,%rdi,1),%edi
+ xorl %r13d,%eax
+ addl %ecx,%edi
+ roll $30,%r12d
+ addl %eax,%edi
+ roll $1,%r14d
+ xorl 56(%rsp),%edx
+ movl %r11d,%eax
+ movl %r14d,52(%rsp)
+ movl %edi,%ecx
+ xorl 0(%rsp),%edx
+ xorl %r13d,%eax
+ roll $5,%ecx
+ xorl 24(%rsp),%edx
+ leal 1859775393(%r14,%rsi,1),%esi
+ xorl %r12d,%eax
+ addl %ecx,%esi
+ roll $30,%r11d
+ addl %eax,%esi
+ roll $1,%edx
+ xorl 60(%rsp),%ebp
+ movl %edi,%eax
+ movl %edx,56(%rsp)
+ movl %esi,%ecx
+ xorl 4(%rsp),%ebp
+ xorl %r12d,%eax
+ roll $5,%ecx
+ xorl 28(%rsp),%ebp
+ leal 1859775393(%rdx,%r13,1),%r13d
+ xorl %r11d,%eax
+ addl %ecx,%r13d
+ roll $30,%edi
+ addl %eax,%r13d
+ roll $1,%ebp
+ xorl 0(%rsp),%r14d
+ movl %esi,%eax
+ movl %ebp,60(%rsp)
+ movl %r13d,%ecx
+ xorl 8(%rsp),%r14d
+ xorl %r11d,%eax
+ roll $5,%ecx
+ xorl 32(%rsp),%r14d
+ leal 1859775393(%rbp,%r12,1),%r12d
+ xorl %edi,%eax
+ addl %ecx,%r12d
+ roll $30,%esi
+ addl %eax,%r12d
+ roll $1,%r14d
+ xorl 4(%rsp),%edx
+ movl %r13d,%eax
+ movl %r14d,0(%rsp)
+ movl %r12d,%ecx
+ xorl 12(%rsp),%edx
+ xorl %edi,%eax
+ roll $5,%ecx
+ xorl 36(%rsp),%edx
+ leal 1859775393(%r14,%r11,1),%r11d
+ xorl %esi,%eax
+ addl %ecx,%r11d
+ roll $30,%r13d
+ addl %eax,%r11d
+ roll $1,%edx
+ xorl 8(%rsp),%ebp
+ movl %r12d,%eax
+ movl %edx,4(%rsp)
+ movl %r11d,%ecx
+ xorl 16(%rsp),%ebp
+ xorl %esi,%eax
+ roll $5,%ecx
+ xorl 40(%rsp),%ebp
+ leal 1859775393(%rdx,%rdi,1),%edi
+ xorl %r13d,%eax
+ addl %ecx,%edi
+ roll $30,%r12d
+ addl %eax,%edi
+ roll $1,%ebp
+ xorl 12(%rsp),%r14d
+ movl %r11d,%eax
+ movl %ebp,8(%rsp)
+ movl %edi,%ecx
+ xorl 20(%rsp),%r14d
+ xorl %r13d,%eax
+ roll $5,%ecx
+ xorl 44(%rsp),%r14d
+ leal 1859775393(%rbp,%rsi,1),%esi
+ xorl %r12d,%eax
+ addl %ecx,%esi
+ roll $30,%r11d
+ addl %eax,%esi
+ roll $1,%r14d
+ xorl 16(%rsp),%edx
+ movl %edi,%eax
+ movl %r14d,12(%rsp)
+ movl %esi,%ecx
+ xorl 24(%rsp),%edx
+ xorl %r12d,%eax
+ roll $5,%ecx
+ xorl 48(%rsp),%edx
+ leal 1859775393(%r14,%r13,1),%r13d
+ xorl %r11d,%eax
+ addl %ecx,%r13d
+ roll $30,%edi
+ addl %eax,%r13d
+ roll $1,%edx
+ xorl 20(%rsp),%ebp
+ movl %esi,%eax
+ movl %edx,16(%rsp)
+ movl %r13d,%ecx
+ xorl 28(%rsp),%ebp
+ xorl %r11d,%eax
+ roll $5,%ecx
+ xorl 52(%rsp),%ebp
+ leal 1859775393(%rdx,%r12,1),%r12d
+ xorl %edi,%eax
+ addl %ecx,%r12d
+ roll $30,%esi
+ addl %eax,%r12d
+ roll $1,%ebp
+ xorl 24(%rsp),%r14d
+ movl %r13d,%eax
+ movl %ebp,20(%rsp)
+ movl %r12d,%ecx
+ xorl 32(%rsp),%r14d
+ xorl %edi,%eax
+ roll $5,%ecx
+ xorl 56(%rsp),%r14d
+ leal 1859775393(%rbp,%r11,1),%r11d
+ xorl %esi,%eax
+ addl %ecx,%r11d
+ roll $30,%r13d
+ addl %eax,%r11d
+ roll $1,%r14d
+ xorl 28(%rsp),%edx
+ movl %r12d,%eax
+ movl %r14d,24(%rsp)
+ movl %r11d,%ecx
+ xorl 36(%rsp),%edx
+ xorl %esi,%eax
+ roll $5,%ecx
+ xorl 60(%rsp),%edx
+ leal 1859775393(%r14,%rdi,1),%edi
+ xorl %r13d,%eax
+ addl %ecx,%edi
+ roll $30,%r12d
+ addl %eax,%edi
+ roll $1,%edx
+ xorl 32(%rsp),%ebp
+ movl %r11d,%eax
+ movl %edx,28(%rsp)
+ movl %edi,%ecx
+ xorl 40(%rsp),%ebp
+ xorl %r13d,%eax
+ roll $5,%ecx
+ xorl 0(%rsp),%ebp
+ leal 1859775393(%rdx,%rsi,1),%esi
+ xorl %r12d,%eax
+ addl %ecx,%esi
+ roll $30,%r11d
+ addl %eax,%esi
+ roll $1,%ebp
+ xorl 36(%rsp),%r14d
+ movl %r12d,%eax
+ movl %ebp,32(%rsp)
+ movl %r12d,%ebx
+ xorl 44(%rsp),%r14d
+ andl %r11d,%eax
+ movl %esi,%ecx
+ xorl 4(%rsp),%r14d
+ leal -1894007588(%rbp,%r13,1),%r13d
+ xorl %r11d,%ebx
+ roll $5,%ecx
+ addl %eax,%r13d
+ roll $1,%r14d
+ andl %edi,%ebx
+ addl %ecx,%r13d
+ roll $30,%edi
+ addl %ebx,%r13d
+ xorl 40(%rsp),%edx
+ movl %r11d,%eax
+ movl %r14d,36(%rsp)
+ movl %r11d,%ebx
+ xorl 48(%rsp),%edx
+ andl %edi,%eax
+ movl %r13d,%ecx
+ xorl 8(%rsp),%edx
+ leal -1894007588(%r14,%r12,1),%r12d
+ xorl %edi,%ebx
+ roll $5,%ecx
+ addl %eax,%r12d
+ roll $1,%edx
+ andl %esi,%ebx
+ addl %ecx,%r12d
+ roll $30,%esi
+ addl %ebx,%r12d
+ xorl 44(%rsp),%ebp
+ movl %edi,%eax
+ movl %edx,40(%rsp)
+ movl %edi,%ebx
+ xorl 52(%rsp),%ebp
+ andl %esi,%eax
+ movl %r12d,%ecx
+ xorl 12(%rsp),%ebp
+ leal -1894007588(%rdx,%r11,1),%r11d
+ xorl %esi,%ebx
+ roll $5,%ecx
+ addl %eax,%r11d
+ roll $1,%ebp
+ andl %r13d,%ebx
+ addl %ecx,%r11d
+ roll $30,%r13d
+ addl %ebx,%r11d
+ xorl 48(%rsp),%r14d
+ movl %esi,%eax
+ movl %ebp,44(%rsp)
+ movl %esi,%ebx
+ xorl 56(%rsp),%r14d
+ andl %r13d,%eax
+ movl %r11d,%ecx
+ xorl 16(%rsp),%r14d
+ leal -1894007588(%rbp,%rdi,1),%edi
+ xorl %r13d,%ebx
+ roll $5,%ecx
+ addl %eax,%edi
+ roll $1,%r14d
+ andl %r12d,%ebx
+ addl %ecx,%edi
+ roll $30,%r12d
+ addl %ebx,%edi
+ xorl 52(%rsp),%edx
+ movl %r13d,%eax
+ movl %r14d,48(%rsp)
+ movl %r13d,%ebx
+ xorl 60(%rsp),%edx
+ andl %r12d,%eax
+ movl %edi,%ecx
+ xorl 20(%rsp),%edx
+ leal -1894007588(%r14,%rsi,1),%esi
+ xorl %r12d,%ebx
+ roll $5,%ecx
+ addl %eax,%esi
+ roll $1,%edx
+ andl %r11d,%ebx
+ addl %ecx,%esi
+ roll $30,%r11d
+ addl %ebx,%esi
+ xorl 56(%rsp),%ebp
+ movl %r12d,%eax
+ movl %edx,52(%rsp)
+ movl %r12d,%ebx
+ xorl 0(%rsp),%ebp
+ andl %r11d,%eax
+ movl %esi,%ecx
+ xorl 24(%rsp),%ebp
+ leal -1894007588(%rdx,%r13,1),%r13d
+ xorl %r11d,%ebx
+ roll $5,%ecx
+ addl %eax,%r13d
+ roll $1,%ebp
+ andl %edi,%ebx
+ addl %ecx,%r13d
+ roll $30,%edi
+ addl %ebx,%r13d
+ xorl 60(%rsp),%r14d
+ movl %r11d,%eax
+ movl %ebp,56(%rsp)
+ movl %r11d,%ebx
+ xorl 4(%rsp),%r14d
+ andl %edi,%eax
+ movl %r13d,%ecx
+ xorl 28(%rsp),%r14d
+ leal -1894007588(%rbp,%r12,1),%r12d
+ xorl %edi,%ebx
+ roll $5,%ecx
+ addl %eax,%r12d
+ roll $1,%r14d
+ andl %esi,%ebx
+ addl %ecx,%r12d
+ roll $30,%esi
+ addl %ebx,%r12d
+ xorl 0(%rsp),%edx
+ movl %edi,%eax
+ movl %r14d,60(%rsp)
+ movl %edi,%ebx
+ xorl 8(%rsp),%edx
+ andl %esi,%eax
+ movl %r12d,%ecx
+ xorl 32(%rsp),%edx
+ leal -1894007588(%r14,%r11,1),%r11d
+ xorl %esi,%ebx
+ roll $5,%ecx
+ addl %eax,%r11d
+ roll $1,%edx
+ andl %r13d,%ebx
+ addl %ecx,%r11d
+ roll $30,%r13d
+ addl %ebx,%r11d
+ xorl 4(%rsp),%ebp
+ movl %esi,%eax
+ movl %edx,0(%rsp)
+ movl %esi,%ebx
+ xorl 12(%rsp),%ebp
+ andl %r13d,%eax
+ movl %r11d,%ecx
+ xorl 36(%rsp),%ebp
+ leal -1894007588(%rdx,%rdi,1),%edi
+ xorl %r13d,%ebx
+ roll $5,%ecx
+ addl %eax,%edi
+ roll $1,%ebp
+ andl %r12d,%ebx
+ addl %ecx,%edi
+ roll $30,%r12d
+ addl %ebx,%edi
+ xorl 8(%rsp),%r14d
+ movl %r13d,%eax
+ movl %ebp,4(%rsp)
+ movl %r13d,%ebx
+ xorl 16(%rsp),%r14d
+ andl %r12d,%eax
+ movl %edi,%ecx
+ xorl 40(%rsp),%r14d
+ leal -1894007588(%rbp,%rsi,1),%esi
+ xorl %r12d,%ebx
+ roll $5,%ecx
+ addl %eax,%esi
+ roll $1,%r14d
+ andl %r11d,%ebx
+ addl %ecx,%esi
+ roll $30,%r11d
+ addl %ebx,%esi
+ xorl 12(%rsp),%edx
+ movl %r12d,%eax
+ movl %r14d,8(%rsp)
+ movl %r12d,%ebx
+ xorl 20(%rsp),%edx
+ andl %r11d,%eax
+ movl %esi,%ecx
+ xorl 44(%rsp),%edx
+ leal -1894007588(%r14,%r13,1),%r13d
+ xorl %r11d,%ebx
+ roll $5,%ecx
+ addl %eax,%r13d
+ roll $1,%edx
+ andl %edi,%ebx
+ addl %ecx,%r13d
+ roll $30,%edi
+ addl %ebx,%r13d
+ xorl 16(%rsp),%ebp
+ movl %r11d,%eax
+ movl %edx,12(%rsp)
+ movl %r11d,%ebx
+ xorl 24(%rsp),%ebp
+ andl %edi,%eax
+ movl %r13d,%ecx
+ xorl 48(%rsp),%ebp
+ leal -1894007588(%rdx,%r12,1),%r12d
+ xorl %edi,%ebx
+ roll $5,%ecx
+ addl %eax,%r12d
+ roll $1,%ebp
+ andl %esi,%ebx
+ addl %ecx,%r12d
+ roll $30,%esi
+ addl %ebx,%r12d
+ xorl 20(%rsp),%r14d
+ movl %edi,%eax
+ movl %ebp,16(%rsp)
+ movl %edi,%ebx
+ xorl 28(%rsp),%r14d
+ andl %esi,%eax
+ movl %r12d,%ecx
+ xorl 52(%rsp),%r14d
+ leal -1894007588(%rbp,%r11,1),%r11d
+ xorl %esi,%ebx
+ roll $5,%ecx
+ addl %eax,%r11d
+ roll $1,%r14d
+ andl %r13d,%ebx
+ addl %ecx,%r11d
+ roll $30,%r13d
+ addl %ebx,%r11d
+ xorl 24(%rsp),%edx
+ movl %esi,%eax
+ movl %r14d,20(%rsp)
+ movl %esi,%ebx
+ xorl 32(%rsp),%edx
+ andl %r13d,%eax
+ movl %r11d,%ecx
+ xorl 56(%rsp),%edx
+ leal -1894007588(%r14,%rdi,1),%edi
+ xorl %r13d,%ebx
+ roll $5,%ecx
+ addl %eax,%edi
+ roll $1,%edx
+ andl %r12d,%ebx
+ addl %ecx,%edi
+ roll $30,%r12d
+ addl %ebx,%edi
+ xorl 28(%rsp),%ebp
+ movl %r13d,%eax
+ movl %edx,24(%rsp)
+ movl %r13d,%ebx
+ xorl 36(%rsp),%ebp
+ andl %r12d,%eax
+ movl %edi,%ecx
+ xorl 60(%rsp),%ebp
+ leal -1894007588(%rdx,%rsi,1),%esi
+ xorl %r12d,%ebx
+ roll $5,%ecx
+ addl %eax,%esi
+ roll $1,%ebp
+ andl %r11d,%ebx
+ addl %ecx,%esi
+ roll $30,%r11d
+ addl %ebx,%esi
+ xorl 32(%rsp),%r14d
+ movl %r12d,%eax
+ movl %ebp,28(%rsp)
+ movl %r12d,%ebx
+ xorl 40(%rsp),%r14d
+ andl %r11d,%eax
+ movl %esi,%ecx
+ xorl 0(%rsp),%r14d
+ leal -1894007588(%rbp,%r13,1),%r13d
+ xorl %r11d,%ebx
+ roll $5,%ecx
+ addl %eax,%r13d
+ roll $1,%r14d
+ andl %edi,%ebx
+ addl %ecx,%r13d
+ roll $30,%edi
+ addl %ebx,%r13d
+ xorl 36(%rsp),%edx
+ movl %r11d,%eax
+ movl %r14d,32(%rsp)
+ movl %r11d,%ebx
+ xorl 44(%rsp),%edx
+ andl %edi,%eax
+ movl %r13d,%ecx
+ xorl 4(%rsp),%edx
+ leal -1894007588(%r14,%r12,1),%r12d
+ xorl %edi,%ebx
+ roll $5,%ecx
+ addl %eax,%r12d
+ roll $1,%edx
+ andl %esi,%ebx
+ addl %ecx,%r12d
+ roll $30,%esi
+ addl %ebx,%r12d
+ xorl 40(%rsp),%ebp
+ movl %edi,%eax
+ movl %edx,36(%rsp)
+ movl %edi,%ebx
+ xorl 48(%rsp),%ebp
+ andl %esi,%eax
+ movl %r12d,%ecx
+ xorl 8(%rsp),%ebp
+ leal -1894007588(%rdx,%r11,1),%r11d
+ xorl %esi,%ebx
+ roll $5,%ecx
+ addl %eax,%r11d
+ roll $1,%ebp
+ andl %r13d,%ebx
+ addl %ecx,%r11d
+ roll $30,%r13d
+ addl %ebx,%r11d
+ xorl 44(%rsp),%r14d
+ movl %esi,%eax
+ movl %ebp,40(%rsp)
+ movl %esi,%ebx
+ xorl 52(%rsp),%r14d
+ andl %r13d,%eax
+ movl %r11d,%ecx
+ xorl 12(%rsp),%r14d
+ leal -1894007588(%rbp,%rdi,1),%edi
+ xorl %r13d,%ebx
+ roll $5,%ecx
+ addl %eax,%edi
+ roll $1,%r14d
+ andl %r12d,%ebx
+ addl %ecx,%edi
+ roll $30,%r12d
+ addl %ebx,%edi
+ xorl 48(%rsp),%edx
+ movl %r13d,%eax
+ movl %r14d,44(%rsp)
+ movl %r13d,%ebx
+ xorl 56(%rsp),%edx
+ andl %r12d,%eax
+ movl %edi,%ecx
+ xorl 16(%rsp),%edx
+ leal -1894007588(%r14,%rsi,1),%esi
+ xorl %r12d,%ebx
+ roll $5,%ecx
+ addl %eax,%esi
+ roll $1,%edx
+ andl %r11d,%ebx
+ addl %ecx,%esi
+ roll $30,%r11d
+ addl %ebx,%esi
+ xorl 52(%rsp),%ebp
+ movl %edi,%eax
+ movl %edx,48(%rsp)
+ movl %esi,%ecx
+ xorl 60(%rsp),%ebp
+ xorl %r12d,%eax
+ roll $5,%ecx
+ xorl 20(%rsp),%ebp
+ leal -899497514(%rdx,%r13,1),%r13d
+ xorl %r11d,%eax
+ addl %ecx,%r13d
+ roll $30,%edi
+ addl %eax,%r13d
+ roll $1,%ebp
+ xorl 56(%rsp),%r14d
+ movl %esi,%eax
+ movl %ebp,52(%rsp)
+ movl %r13d,%ecx
+ xorl 0(%rsp),%r14d
+ xorl %r11d,%eax
+ roll $5,%ecx
+ xorl 24(%rsp),%r14d
+ leal -899497514(%rbp,%r12,1),%r12d
+ xorl %edi,%eax
+ addl %ecx,%r12d
+ roll $30,%esi
+ addl %eax,%r12d
+ roll $1,%r14d
+ xorl 60(%rsp),%edx
+ movl %r13d,%eax
+ movl %r14d,56(%rsp)
+ movl %r12d,%ecx
+ xorl 4(%rsp),%edx
+ xorl %edi,%eax
+ roll $5,%ecx
+ xorl 28(%rsp),%edx
+ leal -899497514(%r14,%r11,1),%r11d
+ xorl %esi,%eax
+ addl %ecx,%r11d
+ roll $30,%r13d
+ addl %eax,%r11d
+ roll $1,%edx
+ xorl 0(%rsp),%ebp
+ movl %r12d,%eax
+ movl %edx,60(%rsp)
+ movl %r11d,%ecx
+ xorl 8(%rsp),%ebp
+ xorl %esi,%eax
+ roll $5,%ecx
+ xorl 32(%rsp),%ebp
+ leal -899497514(%rdx,%rdi,1),%edi
+ xorl %r13d,%eax
+ addl %ecx,%edi
+ roll $30,%r12d
+ addl %eax,%edi
+ roll $1,%ebp
+ xorl 4(%rsp),%r14d
+ movl %r11d,%eax
+ movl %ebp,0(%rsp)
+ movl %edi,%ecx
+ xorl 12(%rsp),%r14d
+ xorl %r13d,%eax
+ roll $5,%ecx
+ xorl 36(%rsp),%r14d
+ leal -899497514(%rbp,%rsi,1),%esi
+ xorl %r12d,%eax
+ addl %ecx,%esi
+ roll $30,%r11d
+ addl %eax,%esi
+ roll $1,%r14d
+ xorl 8(%rsp),%edx
+ movl %edi,%eax
+ movl %r14d,4(%rsp)
+ movl %esi,%ecx
+ xorl 16(%rsp),%edx
+ xorl %r12d,%eax
+ roll $5,%ecx
+ xorl 40(%rsp),%edx
+ leal -899497514(%r14,%r13,1),%r13d
+ xorl %r11d,%eax
+ addl %ecx,%r13d
+ roll $30,%edi
+ addl %eax,%r13d
+ roll $1,%edx
+ xorl 12(%rsp),%ebp
+ movl %esi,%eax
+ movl %edx,8(%rsp)
+ movl %r13d,%ecx
+ xorl 20(%rsp),%ebp
+ xorl %r11d,%eax
+ roll $5,%ecx
+ xorl 44(%rsp),%ebp
+ leal -899497514(%rdx,%r12,1),%r12d
+ xorl %edi,%eax
+ addl %ecx,%r12d
+ roll $30,%esi
+ addl %eax,%r12d
+ roll $1,%ebp
+ xorl 16(%rsp),%r14d
+ movl %r13d,%eax
+ movl %ebp,12(%rsp)
+ movl %r12d,%ecx
+ xorl 24(%rsp),%r14d
+ xorl %edi,%eax
+ roll $5,%ecx
+ xorl 48(%rsp),%r14d
+ leal -899497514(%rbp,%r11,1),%r11d
+ xorl %esi,%eax
+ addl %ecx,%r11d
+ roll $30,%r13d
+ addl %eax,%r11d
+ roll $1,%r14d
+ xorl 20(%rsp),%edx
+ movl %r12d,%eax
+ movl %r14d,16(%rsp)
+ movl %r11d,%ecx
+ xorl 28(%rsp),%edx
+ xorl %esi,%eax
+ roll $5,%ecx
+ xorl 52(%rsp),%edx
+ leal -899497514(%r14,%rdi,1),%edi
+ xorl %r13d,%eax
+ addl %ecx,%edi
+ roll $30,%r12d
+ addl %eax,%edi
+ roll $1,%edx
+ xorl 24(%rsp),%ebp
+ movl %r11d,%eax
+ movl %edx,20(%rsp)
+ movl %edi,%ecx
+ xorl 32(%rsp),%ebp
+ xorl %r13d,%eax
+ roll $5,%ecx
+ xorl 56(%rsp),%ebp
+ leal -899497514(%rdx,%rsi,1),%esi
+ xorl %r12d,%eax
+ addl %ecx,%esi
+ roll $30,%r11d
+ addl %eax,%esi
+ roll $1,%ebp
+ xorl 28(%rsp),%r14d
+ movl %edi,%eax
+ movl %ebp,24(%rsp)
+ movl %esi,%ecx
+ xorl 36(%rsp),%r14d
+ xorl %r12d,%eax
+ roll $5,%ecx
+ xorl 60(%rsp),%r14d
+ leal -899497514(%rbp,%r13,1),%r13d
+ xorl %r11d,%eax
+ addl %ecx,%r13d
+ roll $30,%edi
+ addl %eax,%r13d
+ roll $1,%r14d
+ xorl 32(%rsp),%edx
+ movl %esi,%eax
+ movl %r14d,28(%rsp)
+ movl %r13d,%ecx
+ xorl 40(%rsp),%edx
+ xorl %r11d,%eax
+ roll $5,%ecx
+ xorl 0(%rsp),%edx
+ leal -899497514(%r14,%r12,1),%r12d
+ xorl %edi,%eax
+ addl %ecx,%r12d
+ roll $30,%esi
+ addl %eax,%r12d
+ roll $1,%edx
+ xorl 36(%rsp),%ebp
+ movl %r13d,%eax
+
+ movl %r12d,%ecx
+ xorl 44(%rsp),%ebp
+ xorl %edi,%eax
+ roll $5,%ecx
+ xorl 4(%rsp),%ebp
+ leal -899497514(%rdx,%r11,1),%r11d
+ xorl %esi,%eax
+ addl %ecx,%r11d
+ roll $30,%r13d
+ addl %eax,%r11d
+ roll $1,%ebp
+ xorl 40(%rsp),%r14d
+ movl %r12d,%eax
+
+ movl %r11d,%ecx
+ xorl 48(%rsp),%r14d
+ xorl %esi,%eax
+ roll $5,%ecx
+ xorl 8(%rsp),%r14d
+ leal -899497514(%rbp,%rdi,1),%edi
+ xorl %r13d,%eax
+ addl %ecx,%edi
+ roll $30,%r12d
+ addl %eax,%edi
+ roll $1,%r14d
+ xorl 44(%rsp),%edx
+ movl %r11d,%eax
+
+ movl %edi,%ecx
+ xorl 52(%rsp),%edx
+ xorl %r13d,%eax
+ roll $5,%ecx
+ xorl 12(%rsp),%edx
+ leal -899497514(%r14,%rsi,1),%esi
+ xorl %r12d,%eax
+ addl %ecx,%esi
+ roll $30,%r11d
+ addl %eax,%esi
+ roll $1,%edx
+ xorl 48(%rsp),%ebp
+ movl %edi,%eax
+
+ movl %esi,%ecx
+ xorl 56(%rsp),%ebp
+ xorl %r12d,%eax
+ roll $5,%ecx
+ xorl 16(%rsp),%ebp
+ leal -899497514(%rdx,%r13,1),%r13d
+ xorl %r11d,%eax
+ addl %ecx,%r13d
+ roll $30,%edi
+ addl %eax,%r13d
+ roll $1,%ebp
+ xorl 52(%rsp),%r14d
+ movl %esi,%eax
+
+ movl %r13d,%ecx
+ xorl 60(%rsp),%r14d
+ xorl %r11d,%eax
+ roll $5,%ecx
+ xorl 20(%rsp),%r14d
+ leal -899497514(%rbp,%r12,1),%r12d
+ xorl %edi,%eax
+ addl %ecx,%r12d
+ roll $30,%esi
+ addl %eax,%r12d
+ roll $1,%r14d
+ xorl 56(%rsp),%edx
+ movl %r13d,%eax
+
+ movl %r12d,%ecx
+ xorl 0(%rsp),%edx
+ xorl %edi,%eax
+ roll $5,%ecx
+ xorl 24(%rsp),%edx
+ leal -899497514(%r14,%r11,1),%r11d
+ xorl %esi,%eax
+ addl %ecx,%r11d
+ roll $30,%r13d
+ addl %eax,%r11d
+ roll $1,%edx
+ xorl 60(%rsp),%ebp
+ movl %r12d,%eax
+
+ movl %r11d,%ecx
+ xorl 4(%rsp),%ebp
+ xorl %esi,%eax
+ roll $5,%ecx
+ xorl 28(%rsp),%ebp
+ leal -899497514(%rdx,%rdi,1),%edi
+ xorl %r13d,%eax
+ addl %ecx,%edi
+ roll $30,%r12d
+ addl %eax,%edi
+ roll $1,%ebp
+ movl %r11d,%eax
+ movl %edi,%ecx
+ xorl %r13d,%eax
+ leal -899497514(%rbp,%rsi,1),%esi
+ roll $5,%ecx
+ xorl %r12d,%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 -40(%rsi),%r14
+ movq -32(%rsi),%r13
+ movq -24(%rsi),%r12
+ movq -16(%rsi),%rbp
+ movq -8(%rsi),%rbx
+ leaq (%rsi),%rsp
+L$epilogue:
+ .byte 0xf3,0xc3
+
+
+.p2align 4
+sha1_block_data_order_ssse3:
+_ssse3_shortcut:
+ movq %rsp,%rax
+ pushq %rbx
+ pushq %rbp
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ leaq -64(%rsp),%rsp
+ movq %rax,%r14
+ andq $-64,%rsp
+ movq %rdi,%r8
+ movq %rsi,%r9
+ movq %rdx,%r10
+
+ shlq $6,%r10
+ addq %r9,%r10
+ leaq K_XX_XX+64(%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
+ movl %ecx,%edi
+ xorl %edx,%edi
+ andl %edi,%esi
+
+ movdqa 64(%r11),%xmm6
+ movdqa -64(%r11),%xmm9
+ movdqu 0(%r9),%xmm0
+ movdqu 16(%r9),%xmm1
+ movdqu 32(%r9),%xmm2
+ movdqu 48(%r9),%xmm3
+.byte 102,15,56,0,198
+.byte 102,15,56,0,206
+.byte 102,15,56,0,214
+ addq $64,%r9
+ paddd %xmm9,%xmm0
+.byte 102,15,56,0,222
+ 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:
+ rorl $2,%ebx
+ pshufd $238,%xmm0,%xmm4
+ xorl %edx,%esi
+ movdqa %xmm3,%xmm8
+ paddd %xmm3,%xmm9
+ movl %eax,%edi
+ addl 0(%rsp),%ebp
+ punpcklqdq %xmm1,%xmm4
+ xorl %ecx,%ebx
+ roll $5,%eax
+ addl %esi,%ebp
+ psrldq $4,%xmm8
+ andl %ebx,%edi
+ xorl %ecx,%ebx
+ pxor %xmm0,%xmm4
+ addl %eax,%ebp
+ rorl $7,%eax
+ pxor %xmm2,%xmm8
+ xorl %ecx,%edi
+ movl %ebp,%esi
+ addl 4(%rsp),%edx
+ pxor %xmm8,%xmm4
+ xorl %ebx,%eax
+ roll $5,%ebp
+ movdqa %xmm9,48(%rsp)
+ addl %edi,%edx
+ andl %eax,%esi
+ movdqa %xmm4,%xmm10
+ xorl %ebx,%eax
+ addl %ebp,%edx
+ rorl $7,%ebp
+ movdqa %xmm4,%xmm8
+ xorl %ebx,%esi
+ pslldq $12,%xmm10
+ paddd %xmm4,%xmm4
+ movl %edx,%edi
+ addl 8(%rsp),%ecx
+ psrld $31,%xmm8
+ xorl %eax,%ebp
+ roll $5,%edx
+ addl %esi,%ecx
+ movdqa %xmm10,%xmm9
+ andl %ebp,%edi
+ xorl %eax,%ebp
+ psrld $30,%xmm10
+ addl %edx,%ecx
+ rorl $7,%edx
+ por %xmm8,%xmm4
+ xorl %eax,%edi
+ movl %ecx,%esi
+ addl 12(%rsp),%ebx
+ pslld $2,%xmm9
+ pxor %xmm10,%xmm4
+ xorl %ebp,%edx
+ movdqa -64(%r11),%xmm10
+ roll $5,%ecx
+ addl %edi,%ebx
+ andl %edx,%esi
+ pxor %xmm9,%xmm4
+ xorl %ebp,%edx
+ addl %ecx,%ebx
+ rorl $7,%ecx
+ pshufd $238,%xmm1,%xmm5
+ xorl %ebp,%esi
+ movdqa %xmm4,%xmm9
+ paddd %xmm4,%xmm10
+ movl %ebx,%edi
+ addl 16(%rsp),%eax
+ punpcklqdq %xmm2,%xmm5
+ xorl %edx,%ecx
+ roll $5,%ebx
+ addl %esi,%eax
+ psrldq $4,%xmm9
+ andl %ecx,%edi
+ xorl %edx,%ecx
+ pxor %xmm1,%xmm5
+ addl %ebx,%eax
+ rorl $7,%ebx
+ pxor %xmm3,%xmm9
+ xorl %edx,%edi
+ movl %eax,%esi
+ addl 20(%rsp),%ebp
+ pxor %xmm9,%xmm5
+ xorl %ecx,%ebx
+ roll $5,%eax
+ movdqa %xmm10,0(%rsp)
+ addl %edi,%ebp
+ andl %ebx,%esi
+ movdqa %xmm5,%xmm8
+ xorl %ecx,%ebx
+ addl %eax,%ebp
+ rorl $7,%eax
+ movdqa %xmm5,%xmm9
+ xorl %ecx,%esi
+ pslldq $12,%xmm8
+ paddd %xmm5,%xmm5
+ movl %ebp,%edi
+ addl 24(%rsp),%edx
+ psrld $31,%xmm9
+ xorl %ebx,%eax
+ roll $5,%ebp
+ addl %esi,%edx
+ movdqa %xmm8,%xmm10
+ andl %eax,%edi
+ xorl %ebx,%eax
+ psrld $30,%xmm8
+ addl %ebp,%edx
+ rorl $7,%ebp
+ por %xmm9,%xmm5
+ xorl %ebx,%edi
+ movl %edx,%esi
+ addl 28(%rsp),%ecx
+ pslld $2,%xmm10
+ pxor %xmm8,%xmm5
+ xorl %eax,%ebp
+ movdqa -32(%r11),%xmm8
+ roll $5,%edx
+ addl %edi,%ecx
+ andl %ebp,%esi
+ pxor %xmm10,%xmm5
+ xorl %eax,%ebp
+ addl %edx,%ecx
+ rorl $7,%edx
+ pshufd $238,%xmm2,%xmm6
+ xorl %eax,%esi
+ movdqa %xmm5,%xmm10
+ paddd %xmm5,%xmm8
+ movl %ecx,%edi
+ addl 32(%rsp),%ebx
+ punpcklqdq %xmm3,%xmm6
+ xorl %ebp,%edx
+ roll $5,%ecx
+ addl %esi,%ebx
+ psrldq $4,%xmm10
+ andl %edx,%edi
+ xorl %ebp,%edx
+ pxor %xmm2,%xmm6
+ addl %ecx,%ebx
+ rorl $7,%ecx
+ pxor %xmm4,%xmm10
+ xorl %ebp,%edi
+ movl %ebx,%esi
+ addl 36(%rsp),%eax
+ pxor %xmm10,%xmm6
+ xorl %edx,%ecx
+ roll $5,%ebx
+ movdqa %xmm8,16(%rsp)
+ addl %edi,%eax
+ andl %ecx,%esi
+ movdqa %xmm6,%xmm9
+ xorl %edx,%ecx
+ addl %ebx,%eax
+ rorl $7,%ebx
+ movdqa %xmm6,%xmm10
+ xorl %edx,%esi
+ pslldq $12,%xmm9
+ paddd %xmm6,%xmm6
+ movl %eax,%edi
+ addl 40(%rsp),%ebp
+ psrld $31,%xmm10
+ xorl %ecx,%ebx
+ roll $5,%eax
+ addl %esi,%ebp
+ movdqa %xmm9,%xmm8
+ andl %ebx,%edi
+ xorl %ecx,%ebx
+ psrld $30,%xmm9
+ addl %eax,%ebp
+ rorl $7,%eax
+ por %xmm10,%xmm6
+ xorl %ecx,%edi
+ movl %ebp,%esi
+ addl 44(%rsp),%edx
+ pslld $2,%xmm8
+ pxor %xmm9,%xmm6
+ xorl %ebx,%eax
+ movdqa -32(%r11),%xmm9
+ roll $5,%ebp
+ addl %edi,%edx
+ andl %eax,%esi
+ pxor %xmm8,%xmm6
+ xorl %ebx,%eax
+ addl %ebp,%edx
+ rorl $7,%ebp
+ pshufd $238,%xmm3,%xmm7
+ xorl %ebx,%esi
+ movdqa %xmm6,%xmm8
+ paddd %xmm6,%xmm9
+ movl %edx,%edi
+ addl 48(%rsp),%ecx
+ punpcklqdq %xmm4,%xmm7
+ xorl %eax,%ebp
+ roll $5,%edx
+ addl %esi,%ecx
+ psrldq $4,%xmm8
+ andl %ebp,%edi
+ xorl %eax,%ebp
+ pxor %xmm3,%xmm7
+ addl %edx,%ecx
+ rorl $7,%edx
+ pxor %xmm5,%xmm8
+ xorl %eax,%edi
+ movl %ecx,%esi
+ addl 52(%rsp),%ebx
+ pxor %xmm8,%xmm7
+ xorl %ebp,%edx
+ roll $5,%ecx
+ movdqa %xmm9,32(%rsp)
+ addl %edi,%ebx
+ andl %edx,%esi
+ movdqa %xmm7,%xmm10
+ xorl %ebp,%edx
+ addl %ecx,%ebx
+ rorl $7,%ecx
+ movdqa %xmm7,%xmm8
+ xorl %ebp,%esi
+ pslldq $12,%xmm10
+ paddd %xmm7,%xmm7
+ movl %ebx,%edi
+ addl 56(%rsp),%eax
+ psrld $31,%xmm8
+ xorl %edx,%ecx
+ roll $5,%ebx
+ addl %esi,%eax
+ movdqa %xmm10,%xmm9
+ andl %ecx,%edi
+ xorl %edx,%ecx
+ psrld $30,%xmm10
+ addl %ebx,%eax
+ rorl $7,%ebx
+ por %xmm8,%xmm7
+ xorl %edx,%edi
+ movl %eax,%esi
+ addl 60(%rsp),%ebp
+ pslld $2,%xmm9
+ pxor %xmm10,%xmm7
+ xorl %ecx,%ebx
+ movdqa -32(%r11),%xmm10
+ roll $5,%eax
+ addl %edi,%ebp
+ andl %ebx,%esi
+ pxor %xmm9,%xmm7
+ pshufd $238,%xmm6,%xmm9
+ xorl %ecx,%ebx
+ addl %eax,%ebp
+ rorl $7,%eax
+ pxor %xmm4,%xmm0
+ xorl %ecx,%esi
+ movl %ebp,%edi
+ addl 0(%rsp),%edx
+ punpcklqdq %xmm7,%xmm9
+ xorl %ebx,%eax
+ roll $5,%ebp
+ pxor %xmm1,%xmm0
+ addl %esi,%edx
+ andl %eax,%edi
+ movdqa %xmm10,%xmm8
+ xorl %ebx,%eax
+ paddd %xmm7,%xmm10
+ addl %ebp,%edx
+ pxor %xmm9,%xmm0
+ rorl $7,%ebp
+ xorl %ebx,%edi
+ movl %edx,%esi
+ addl 4(%rsp),%ecx
+ movdqa %xmm0,%xmm9
+ xorl %eax,%ebp
+ roll $5,%edx
+ movdqa %xmm10,48(%rsp)
+ addl %edi,%ecx
+ andl %ebp,%esi
+ xorl %eax,%ebp
+ pslld $2,%xmm0
+ addl %edx,%ecx
+ rorl $7,%edx
+ psrld $30,%xmm9
+ xorl %eax,%esi
+ movl %ecx,%edi
+ addl 8(%rsp),%ebx
+ por %xmm9,%xmm0
+ xorl %ebp,%edx
+ roll $5,%ecx
+ pshufd $238,%xmm7,%xmm10
+ addl %esi,%ebx
+ andl %edx,%edi
+ xorl %ebp,%edx
+ addl %ecx,%ebx
+ addl 12(%rsp),%eax
+ xorl %ebp,%edi
+ movl %ebx,%esi
+ roll $5,%ebx
+ addl %edi,%eax
+ xorl %edx,%esi
+ rorl $7,%ecx
+ addl %ebx,%eax
+ pxor %xmm5,%xmm1
+ addl 16(%rsp),%ebp
+ xorl %ecx,%esi
+ punpcklqdq %xmm0,%xmm10
+ movl %eax,%edi
+ roll $5,%eax
+ pxor %xmm2,%xmm1
+ addl %esi,%ebp
+ xorl %ecx,%edi
+ movdqa %xmm8,%xmm9
+ rorl $7,%ebx
+ paddd %xmm0,%xmm8
+ addl %eax,%ebp
+ pxor %xmm10,%xmm1
+ addl 20(%rsp),%edx
+ xorl %ebx,%edi
+ movl %ebp,%esi
+ roll $5,%ebp
+ movdqa %xmm1,%xmm10
+ addl %edi,%edx
+ xorl %ebx,%esi
+ movdqa %xmm8,0(%rsp)
+ rorl $7,%eax
+ addl %ebp,%edx
+ addl 24(%rsp),%ecx
+ pslld $2,%xmm1
+ xorl %eax,%esi
+ movl %edx,%edi
+ psrld $30,%xmm10
+ roll $5,%edx
+ addl %esi,%ecx
+ xorl %eax,%edi
+ rorl $7,%ebp
+ por %xmm10,%xmm1
+ addl %edx,%ecx
+ addl 28(%rsp),%ebx
+ pshufd $238,%xmm0,%xmm8
+ xorl %ebp,%edi
+ movl %ecx,%esi
+ roll $5,%ecx
+ addl %edi,%ebx
+ xorl %ebp,%esi
+ rorl $7,%edx
+ addl %ecx,%ebx
+ pxor %xmm6,%xmm2
+ addl 32(%rsp),%eax
+ xorl %edx,%esi
+ punpcklqdq %xmm1,%xmm8
+ movl %ebx,%edi
+ roll $5,%ebx
+ pxor %xmm3,%xmm2
+ addl %esi,%eax
+ xorl %edx,%edi
+ movdqa 0(%r11),%xmm10
+ rorl $7,%ecx
+ paddd %xmm1,%xmm9
+ addl %ebx,%eax
+ pxor %xmm8,%xmm2
+ addl 36(%rsp),%ebp
+ xorl %ecx,%edi
+ movl %eax,%esi
+ roll $5,%eax
+ movdqa %xmm2,%xmm8
+ addl %edi,%ebp
+ xorl %ecx,%esi
+ movdqa %xmm9,16(%rsp)
+ rorl $7,%ebx
+ addl %eax,%ebp
+ addl 40(%rsp),%edx
+ pslld $2,%xmm2
+ xorl %ebx,%esi
+ movl %ebp,%edi
+ psrld $30,%xmm8
+ roll $5,%ebp
+ addl %esi,%edx
+ xorl %ebx,%edi
+ rorl $7,%eax
+ por %xmm8,%xmm2
+ addl %ebp,%edx
+ addl 44(%rsp),%ecx
+ pshufd $238,%xmm1,%xmm9
+ xorl %eax,%edi
+ movl %edx,%esi
+ roll $5,%edx
+ addl %edi,%ecx
+ xorl %eax,%esi
+ rorl $7,%ebp
+ addl %edx,%ecx
+ pxor %xmm7,%xmm3
+ addl 48(%rsp),%ebx
+ xorl %ebp,%esi
+ punpcklqdq %xmm2,%xmm9
+ movl %ecx,%edi
+ roll $5,%ecx
+ pxor %xmm4,%xmm3
+ addl %esi,%ebx
+ xorl %ebp,%edi
+ movdqa %xmm10,%xmm8
+ rorl $7,%edx
+ paddd %xmm2,%xmm10
+ addl %ecx,%ebx
+ pxor %xmm9,%xmm3
+ addl 52(%rsp),%eax
+ xorl %edx,%edi
+ movl %ebx,%esi
+ roll $5,%ebx
+ movdqa %xmm3,%xmm9
+ addl %edi,%eax
+ xorl %edx,%esi
+ movdqa %xmm10,32(%rsp)
+ rorl $7,%ecx
+ addl %ebx,%eax
+ addl 56(%rsp),%ebp
+ pslld $2,%xmm3
+ xorl %ecx,%esi
+ movl %eax,%edi
+ psrld $30,%xmm9
+ roll $5,%eax
+ addl %esi,%ebp
+ xorl %ecx,%edi
+ rorl $7,%ebx
+ por %xmm9,%xmm3
+ addl %eax,%ebp
+ addl 60(%rsp),%edx
+ pshufd $238,%xmm2,%xmm10
+ xorl %ebx,%edi
+ movl %ebp,%esi
+ roll $5,%ebp
+ addl %edi,%edx
+ xorl %ebx,%esi
+ rorl $7,%eax
+ addl %ebp,%edx
+ pxor %xmm0,%xmm4
+ addl 0(%rsp),%ecx
+ xorl %eax,%esi
+ punpcklqdq %xmm3,%xmm10
+ movl %edx,%edi
+ roll $5,%edx
+ pxor %xmm5,%xmm4
+ addl %esi,%ecx
+ xorl %eax,%edi
+ movdqa %xmm8,%xmm9
+ rorl $7,%ebp
+ paddd %xmm3,%xmm8
+ addl %edx,%ecx
+ pxor %xmm10,%xmm4
+ addl 4(%rsp),%ebx
+ xorl %ebp,%edi
+ movl %ecx,%esi
+ roll $5,%ecx
+ movdqa %xmm4,%xmm10
+ addl %edi,%ebx
+ xorl %ebp,%esi
+ movdqa %xmm8,48(%rsp)
+ rorl $7,%edx
+ addl %ecx,%ebx
+ addl 8(%rsp),%eax
+ pslld $2,%xmm4
+ xorl %edx,%esi
+ movl %ebx,%edi
+ psrld $30,%xmm10
+ roll $5,%ebx
+ addl %esi,%eax
+ xorl %edx,%edi
+ rorl $7,%ecx
+ por %xmm10,%xmm4
+ addl %ebx,%eax
+ addl 12(%rsp),%ebp
+ pshufd $238,%xmm3,%xmm8
+ xorl %ecx,%edi
+ movl %eax,%esi
+ roll $5,%eax
+ addl %edi,%ebp
+ xorl %ecx,%esi
+ rorl $7,%ebx
+ addl %eax,%ebp
+ pxor %xmm1,%xmm5
+ addl 16(%rsp),%edx
+ xorl %ebx,%esi
+ punpcklqdq %xmm4,%xmm8
+ movl %ebp,%edi
+ roll $5,%ebp
+ pxor %xmm6,%xmm5
+ addl %esi,%edx
+ xorl %ebx,%edi
+ movdqa %xmm9,%xmm10
+ rorl $7,%eax
+ paddd %xmm4,%xmm9
+ addl %ebp,%edx
+ pxor %xmm8,%xmm5
+ addl 20(%rsp),%ecx
+ xorl %eax,%edi
+ movl %edx,%esi
+ roll $5,%edx
+ movdqa %xmm5,%xmm8
+ addl %edi,%ecx
+ xorl %eax,%esi
+ movdqa %xmm9,0(%rsp)
+ rorl $7,%ebp
+ addl %edx,%ecx
+ addl 24(%rsp),%ebx
+ pslld $2,%xmm5
+ xorl %ebp,%esi
+ movl %ecx,%edi
+ psrld $30,%xmm8
+ roll $5,%ecx
+ addl %esi,%ebx
+ xorl %ebp,%edi
+ rorl $7,%edx
+ por %xmm8,%xmm5
+ addl %ecx,%ebx
+ addl 28(%rsp),%eax
+ pshufd $238,%xmm4,%xmm9
+ rorl $7,%ecx
+ movl %ebx,%esi
+ xorl %edx,%edi
+ roll $5,%ebx
+ addl %edi,%eax
+ xorl %ecx,%esi
+ xorl %edx,%ecx
+ addl %ebx,%eax
+ pxor %xmm2,%xmm6
+ addl 32(%rsp),%ebp
+ andl %ecx,%esi
+ xorl %edx,%ecx
+ rorl $7,%ebx
+ punpcklqdq %xmm5,%xmm9
+ movl %eax,%edi
+ xorl %ecx,%esi
+ pxor %xmm7,%xmm6
+ roll $5,%eax
+ addl %esi,%ebp
+ movdqa %xmm10,%xmm8
+ xorl %ebx,%edi
+ paddd %xmm5,%xmm10
+ xorl %ecx,%ebx
+ pxor %xmm9,%xmm6
+ addl %eax,%ebp
+ addl 36(%rsp),%edx
+ andl %ebx,%edi
+ xorl %ecx,%ebx
+ rorl $7,%eax
+ movdqa %xmm6,%xmm9
+ movl %ebp,%esi
+ xorl %ebx,%edi
+ movdqa %xmm10,16(%rsp)
+ roll $5,%ebp
+ addl %edi,%edx
+ xorl %eax,%esi
+ pslld $2,%xmm6
+ xorl %ebx,%eax
+ addl %ebp,%edx
+ psrld $30,%xmm9
+ addl 40(%rsp),%ecx
+ andl %eax,%esi
+ xorl %ebx,%eax
+ por %xmm9,%xmm6
+ rorl $7,%ebp
+ movl %edx,%edi
+ xorl %eax,%esi
+ roll $5,%edx
+ pshufd $238,%xmm5,%xmm10
+ addl %esi,%ecx
+ xorl %ebp,%edi
+ xorl %eax,%ebp
+ addl %edx,%ecx
+ addl 44(%rsp),%ebx
+ andl %ebp,%edi
+ xorl %eax,%ebp
+ rorl $7,%edx
+ movl %ecx,%esi
+ xorl %ebp,%edi
+ roll $5,%ecx
+ addl %edi,%ebx
+ xorl %edx,%esi
+ xorl %ebp,%edx
+ addl %ecx,%ebx
+ pxor %xmm3,%xmm7
+ addl 48(%rsp),%eax
+ andl %edx,%esi
+ xorl %ebp,%edx
+ rorl $7,%ecx
+ punpcklqdq %xmm6,%xmm10
+ movl %ebx,%edi
+ xorl %edx,%esi
+ pxor %xmm0,%xmm7
+ roll $5,%ebx
+ addl %esi,%eax
+ movdqa 32(%r11),%xmm9
+ xorl %ecx,%edi
+ paddd %xmm6,%xmm8
+ xorl %edx,%ecx
+ pxor %xmm10,%xmm7
+ addl %ebx,%eax
+ addl 52(%rsp),%ebp
+ andl %ecx,%edi
+ xorl %edx,%ecx
+ rorl $7,%ebx
+ movdqa %xmm7,%xmm10
+ movl %eax,%esi
+ xorl %ecx,%edi
+ movdqa %xmm8,32(%rsp)
+ roll $5,%eax
+ addl %edi,%ebp
+ xorl %ebx,%esi
+ pslld $2,%xmm7
+ xorl %ecx,%ebx
+ addl %eax,%ebp
+ psrld $30,%xmm10
+ addl 56(%rsp),%edx
+ andl %ebx,%esi
+ xorl %ecx,%ebx
+ por %xmm10,%xmm7
+ rorl $7,%eax
+ movl %ebp,%edi
+ xorl %ebx,%esi
+ roll $5,%ebp
+ pshufd $238,%xmm6,%xmm8
+ addl %esi,%edx
+ xorl %eax,%edi
+ xorl %ebx,%eax
+ addl %ebp,%edx
+ addl 60(%rsp),%ecx
+ andl %eax,%edi
+ xorl %ebx,%eax
+ rorl $7,%ebp
+ movl %edx,%esi
+ xorl %eax,%edi
+ roll $5,%edx
+ addl %edi,%ecx
+ xorl %ebp,%esi
+ xorl %eax,%ebp
+ addl %edx,%ecx
+ pxor %xmm4,%xmm0
+ addl 0(%rsp),%ebx
+ andl %ebp,%esi
+ xorl %eax,%ebp
+ rorl $7,%edx
+ punpcklqdq %xmm7,%xmm8
+ movl %ecx,%edi
+ xorl %ebp,%esi
+ pxor %xmm1,%xmm0
+ roll $5,%ecx
+ addl %esi,%ebx
+ movdqa %xmm9,%xmm10
+ xorl %edx,%edi
+ paddd %xmm7,%xmm9
+ xorl %ebp,%edx
+ pxor %xmm8,%xmm0
+ addl %ecx,%ebx
+ addl 4(%rsp),%eax
+ andl %edx,%edi
+ xorl %ebp,%edx
+ rorl $7,%ecx
+ movdqa %xmm0,%xmm8
+ movl %ebx,%esi
+ xorl %edx,%edi
+ movdqa %xmm9,48(%rsp)
+ roll $5,%ebx
+ addl %edi,%eax
+ xorl %ecx,%esi
+ pslld $2,%xmm0
+ xorl %edx,%ecx
+ addl %ebx,%eax
+ psrld $30,%xmm8
+ addl 8(%rsp),%ebp
+ andl %ecx,%esi
+ xorl %edx,%ecx
+ por %xmm8,%xmm0
+ rorl $7,%ebx
+ movl %eax,%edi
+ xorl %ecx,%esi
+ roll $5,%eax
+ pshufd $238,%xmm7,%xmm9
+ addl %esi,%ebp
+ xorl %ebx,%edi
+ xorl %ecx,%ebx
+ addl %eax,%ebp
+ addl 12(%rsp),%edx
+ andl %ebx,%edi
+ xorl %ecx,%ebx
+ rorl $7,%eax
+ movl %ebp,%esi
+ xorl %ebx,%edi
+ roll $5,%ebp
+ addl %edi,%edx
+ xorl %eax,%esi
+ xorl %ebx,%eax
+ addl %ebp,%edx
+ pxor %xmm5,%xmm1
+ addl 16(%rsp),%ecx
+ andl %eax,%esi
+ xorl %ebx,%eax
+ rorl $7,%ebp
+ punpcklqdq %xmm0,%xmm9
+ movl %edx,%edi
+ xorl %eax,%esi
+ pxor %xmm2,%xmm1
+ roll $5,%edx
+ addl %esi,%ecx
+ movdqa %xmm10,%xmm8
+ xorl %ebp,%edi
+ paddd %xmm0,%xmm10
+ xorl %eax,%ebp
+ pxor %xmm9,%xmm1
+ addl %edx,%ecx
+ addl 20(%rsp),%ebx
+ andl %ebp,%edi
+ xorl %eax,%ebp
+ rorl $7,%edx
+ movdqa %xmm1,%xmm9
+ movl %ecx,%esi
+ xorl %ebp,%edi
+ movdqa %xmm10,0(%rsp)
+ roll $5,%ecx
+ addl %edi,%ebx
+ xorl %edx,%esi
+ pslld $2,%xmm1
+ xorl %ebp,%edx
+ addl %ecx,%ebx
+ psrld $30,%xmm9
+ addl 24(%rsp),%eax
+ andl %edx,%esi
+ xorl %ebp,%edx
+ por %xmm9,%xmm1
+ rorl $7,%ecx
+ movl %ebx,%edi
+ xorl %edx,%esi
+ roll $5,%ebx
+ pshufd $238,%xmm0,%xmm10
+ addl %esi,%eax
+ xorl %ecx,%edi
+ xorl %edx,%ecx
+ addl %ebx,%eax
+ addl 28(%rsp),%ebp
+ andl %ecx,%edi
+ xorl %edx,%ecx
+ rorl $7,%ebx
+ movl %eax,%esi
+ xorl %ecx,%edi
+ roll $5,%eax
+ addl %edi,%ebp
+ xorl %ebx,%esi
+ xorl %ecx,%ebx
+ addl %eax,%ebp
+ pxor %xmm6,%xmm2
+ addl 32(%rsp),%edx
+ andl %ebx,%esi
+ xorl %ecx,%ebx
+ rorl $7,%eax
+ punpcklqdq %xmm1,%xmm10
+ movl %ebp,%edi
+ xorl %ebx,%esi
+ pxor %xmm3,%xmm2
+ roll $5,%ebp
+ addl %esi,%edx
+ movdqa %xmm8,%xmm9
+ xorl %eax,%edi
+ paddd %xmm1,%xmm8
+ xorl %ebx,%eax
+ pxor %xmm10,%xmm2
+ addl %ebp,%edx
+ addl 36(%rsp),%ecx
+ andl %eax,%edi
+ xorl %ebx,%eax
+ rorl $7,%ebp
+ movdqa %xmm2,%xmm10
+ movl %edx,%esi
+ xorl %eax,%edi
+ movdqa %xmm8,16(%rsp)
+ roll $5,%edx
+ addl %edi,%ecx
+ xorl %ebp,%esi
+ pslld $2,%xmm2
+ xorl %eax,%ebp
+ addl %edx,%ecx
+ psrld $30,%xmm10
+ addl 40(%rsp),%ebx
+ andl %ebp,%esi
+ xorl %eax,%ebp
+ por %xmm10,%xmm2
+ rorl $7,%edx
+ movl %ecx,%edi
+ xorl %ebp,%esi
+ roll $5,%ecx
+ pshufd $238,%xmm1,%xmm8
+ addl %esi,%ebx
+ xorl %edx,%edi
+ xorl %ebp,%edx
+ addl %ecx,%ebx
+ addl 44(%rsp),%eax
+ andl %edx,%edi
+ xorl %ebp,%edx
+ rorl $7,%ecx
+ movl %ebx,%esi
+ xorl %edx,%edi
+ roll $5,%ebx
+ addl %edi,%eax
+ xorl %edx,%esi
+ addl %ebx,%eax
+ pxor %xmm7,%xmm3
+ addl 48(%rsp),%ebp
+ xorl %ecx,%esi
+ punpcklqdq %xmm2,%xmm8
+ movl %eax,%edi
+ roll $5,%eax
+ pxor %xmm4,%xmm3
+ addl %esi,%ebp
+ xorl %ecx,%edi
+ movdqa %xmm9,%xmm10
+ rorl $7,%ebx
+ paddd %xmm2,%xmm9
+ addl %eax,%ebp
+ pxor %xmm8,%xmm3
+ addl 52(%rsp),%edx
+ xorl %ebx,%edi
+ movl %ebp,%esi
+ roll $5,%ebp
+ movdqa %xmm3,%xmm8
+ addl %edi,%edx
+ xorl %ebx,%esi
+ movdqa %xmm9,32(%rsp)
+ rorl $7,%eax
+ addl %ebp,%edx
+ addl 56(%rsp),%ecx
+ pslld $2,%xmm3
+ xorl %eax,%esi
+ movl %edx,%edi
+ psrld $30,%xmm8
+ roll $5,%edx
+ addl %esi,%ecx
+ xorl %eax,%edi
+ rorl $7,%ebp
+ por %xmm8,%xmm3
+ addl %edx,%ecx
+ addl 60(%rsp),%ebx
+ xorl %ebp,%edi
+ movl %ecx,%esi
+ roll $5,%ecx
+ addl %edi,%ebx
+ xorl %ebp,%esi
+ rorl $7,%edx
+ addl %ecx,%ebx
+ addl 0(%rsp),%eax
+ xorl %edx,%esi
+ movl %ebx,%edi
+ roll $5,%ebx
+ paddd %xmm3,%xmm10
+ addl %esi,%eax
+ xorl %edx,%edi
+ movdqa %xmm10,48(%rsp)
+ rorl $7,%ecx
+ addl %ebx,%eax
+ addl 4(%rsp),%ebp
+ xorl %ecx,%edi
+ movl %eax,%esi
+ roll $5,%eax
+ addl %edi,%ebp
+ xorl %ecx,%esi
+ rorl $7,%ebx
+ addl %eax,%ebp
+ addl 8(%rsp),%edx
+ xorl %ebx,%esi
+ movl %ebp,%edi
+ roll $5,%ebp
+ addl %esi,%edx
+ xorl %ebx,%edi
+ rorl $7,%eax
+ addl %ebp,%edx
+ addl 12(%rsp),%ecx
+ xorl %eax,%edi
+ movl %edx,%esi
+ roll $5,%edx
+ addl %edi,%ecx
+ xorl %eax,%esi
+ rorl $7,%ebp
+ addl %edx,%ecx
+ cmpq %r10,%r9
+ je L$done_ssse3
+ movdqa 64(%r11),%xmm6
+ movdqa -64(%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 %ebp,%esi
+ movl %ecx,%edi
+.byte 102,15,56,0,206
+ roll $5,%ecx
+ addl %esi,%ebx
+ xorl %ebp,%edi
+ rorl $7,%edx
+ paddd %xmm9,%xmm0
+ addl %ecx,%ebx
+ addl 20(%rsp),%eax
+ xorl %edx,%edi
+ movl %ebx,%esi
+ movdqa %xmm0,0(%rsp)
+ roll $5,%ebx
+ addl %edi,%eax
+ xorl %edx,%esi
+ rorl $7,%ecx
+ psubd %xmm9,%xmm0
+ addl %ebx,%eax
+ addl 24(%rsp),%ebp
+ xorl %ecx,%esi
+ movl %eax,%edi
+ roll $5,%eax
+ addl %esi,%ebp
+ xorl %ecx,%edi
+ rorl $7,%ebx
+ addl %eax,%ebp
+ addl 28(%rsp),%edx
+ xorl %ebx,%edi
+ movl %ebp,%esi
+ roll $5,%ebp
+ addl %edi,%edx
+ xorl %ebx,%esi
+ rorl $7,%eax
+ addl %ebp,%edx
+ addl 32(%rsp),%ecx
+ xorl %eax,%esi
+ movl %edx,%edi
+.byte 102,15,56,0,214
+ roll $5,%edx
+ addl %esi,%ecx
+ xorl %eax,%edi
+ rorl $7,%ebp
+ paddd %xmm9,%xmm1
+ addl %edx,%ecx
+ addl 36(%rsp),%ebx
+ xorl %ebp,%edi
+ movl %ecx,%esi
+ movdqa %xmm1,16(%rsp)
+ roll $5,%ecx
+ addl %edi,%ebx
+ xorl %ebp,%esi
+ rorl $7,%edx
+ psubd %xmm9,%xmm1
+ addl %ecx,%ebx
+ addl 40(%rsp),%eax
+ xorl %edx,%esi
+ movl %ebx,%edi
+ roll $5,%ebx
+ addl %esi,%eax
+ xorl %edx,%edi
+ rorl $7,%ecx
+ addl %ebx,%eax
+ addl 44(%rsp),%ebp
+ xorl %ecx,%edi
+ movl %eax,%esi
+ roll $5,%eax
+ addl %edi,%ebp
+ xorl %ecx,%esi
+ rorl $7,%ebx
+ addl %eax,%ebp
+ addl 48(%rsp),%edx
+ xorl %ebx,%esi
+ movl %ebp,%edi
+.byte 102,15,56,0,222
+ roll $5,%ebp
+ addl %esi,%edx
+ xorl %ebx,%edi
+ rorl $7,%eax
+ paddd %xmm9,%xmm2
+ addl %ebp,%edx
+ addl 52(%rsp),%ecx
+ xorl %eax,%edi
+ movl %edx,%esi
+ movdqa %xmm2,32(%rsp)
+ roll $5,%edx
+ addl %edi,%ecx
+ xorl %eax,%esi
+ rorl $7,%ebp
+ psubd %xmm9,%xmm2
+ addl %edx,%ecx
+ addl 56(%rsp),%ebx
+ xorl %ebp,%esi
+ movl %ecx,%edi
+ roll $5,%ecx
+ addl %esi,%ebx
+ xorl %ebp,%edi
+ rorl $7,%edx
+ addl %ecx,%ebx
+ addl 60(%rsp),%eax
+ xorl %edx,%edi
+ movl %ebx,%esi
+ roll $5,%ebx
+ addl %edi,%eax
+ rorl $7,%ecx
+ addl %ebx,%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 %ecx,%edi
+ movl %edx,12(%r8)
+ xorl %edx,%edi
+ movl %ebp,16(%r8)
+ andl %edi,%esi
+ jmp L$oop_ssse3
+
+.p2align 4
+L$done_ssse3:
+ addl 16(%rsp),%ebx
+ xorl %ebp,%esi
+ movl %ecx,%edi
+ roll $5,%ecx
+ addl %esi,%ebx
+ xorl %ebp,%edi
+ rorl $7,%edx
+ addl %ecx,%ebx
+ addl 20(%rsp),%eax
+ xorl %edx,%edi
+ movl %ebx,%esi
+ roll $5,%ebx
+ addl %edi,%eax
+ xorl %edx,%esi
+ rorl $7,%ecx
+ addl %ebx,%eax
+ addl 24(%rsp),%ebp
+ xorl %ecx,%esi
+ movl %eax,%edi
+ roll $5,%eax
+ addl %esi,%ebp
+ xorl %ecx,%edi
+ rorl $7,%ebx
+ addl %eax,%ebp
+ addl 28(%rsp),%edx
+ xorl %ebx,%edi
+ movl %ebp,%esi
+ roll $5,%ebp
+ addl %edi,%edx
+ xorl %ebx,%esi
+ rorl $7,%eax
+ addl %ebp,%edx
+ addl 32(%rsp),%ecx
+ xorl %eax,%esi
+ movl %edx,%edi
+ roll $5,%edx
+ addl %esi,%ecx
+ xorl %eax,%edi
+ rorl $7,%ebp
+ addl %edx,%ecx
+ addl 36(%rsp),%ebx
+ xorl %ebp,%edi
+ movl %ecx,%esi
+ roll $5,%ecx
+ addl %edi,%ebx
+ xorl %ebp,%esi
+ rorl $7,%edx
+ addl %ecx,%ebx
+ addl 40(%rsp),%eax
+ xorl %edx,%esi
+ movl %ebx,%edi
+ roll $5,%ebx
+ addl %esi,%eax
+ xorl %edx,%edi
+ rorl $7,%ecx
+ addl %ebx,%eax
+ addl 44(%rsp),%ebp
+ xorl %ecx,%edi
+ movl %eax,%esi
+ roll $5,%eax
+ addl %edi,%ebp
+ xorl %ecx,%esi
+ rorl $7,%ebx
+ addl %eax,%ebp
+ addl 48(%rsp),%edx
+ xorl %ebx,%esi
+ movl %ebp,%edi
+ roll $5,%ebp
+ addl %esi,%edx
+ xorl %ebx,%edi
+ rorl $7,%eax
+ addl %ebp,%edx
+ addl 52(%rsp),%ecx
+ xorl %eax,%edi
+ movl %edx,%esi
+ roll $5,%edx
+ addl %edi,%ecx
+ xorl %eax,%esi
+ rorl $7,%ebp
+ addl %edx,%ecx
+ addl 56(%rsp),%ebx
+ xorl %ebp,%esi
+ movl %ecx,%edi
+ roll $5,%ecx
+ addl %esi,%ebx
+ xorl %ebp,%edi
+ rorl $7,%edx
+ addl %ecx,%ebx
+ addl 60(%rsp),%eax
+ xorl %edx,%edi
+ movl %ebx,%esi
+ roll $5,%ebx
+ addl %edi,%eax
+ rorl $7,%ecx
+ addl %ebx,%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 (%r14),%rsi
+ movq -40(%rsi),%r14
+ movq -32(%rsi),%r13
+ movq -24(%rsi),%r12
+ movq -16(%rsi),%rbp
+ movq -8(%rsi),%rbx
+ leaq (%rsi),%rsp
+L$epilogue_ssse3:
+ .byte 0xf3,0xc3
+
+.p2align 6
+K_XX_XX:
+.long 0x5a827999,0x5a827999,0x5a827999,0x5a827999
+.long 0x5a827999,0x5a827999,0x5a827999,0x5a827999
+.long 0x6ed9eba1,0x6ed9eba1,0x6ed9eba1,0x6ed9eba1
+.long 0x6ed9eba1,0x6ed9eba1,0x6ed9eba1,0x6ed9eba1
+.long 0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc
+.long 0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc
+.long 0xca62c1d6,0xca62c1d6,0xca62c1d6,0xca62c1d6
+.long 0xca62c1d6,0xca62c1d6,0xca62c1d6,0xca62c1d6
+.long 0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f
+.long 0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f
+.byte 0xf,0xe,0xd,0xc,0xb,0xa,0x9,0x8,0x7,0x6,0x5,0x4,0x3,0x2,0x1,0x0
+.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
+#endif
diff --git a/mac-x86_64/crypto/sha/sha256-x86_64.S b/mac-x86_64/crypto/sha/sha256-x86_64.S
new file mode 100644
index 0000000..da02d4c
--- /dev/null
+++ b/mac-x86_64/crypto/sha/sha256-x86_64.S
@@ -0,0 +1,2843 @@
+#if defined(__x86_64__)
+.text
+
+
+.globl _sha256_block_data_order
+.private_extern _sha256_block_data_order
+
+.p2align 4
+_sha256_block_data_order:
+ leaq _OPENSSL_ia32cap_P(%rip),%r11
+ movl 0(%r11),%r9d
+ movl 4(%r11),%r10d
+ movl 8(%r11),%r11d
+ testl $512,%r10d
+ jnz L$ssse3_shortcut
+ 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:
+
+ 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:
+ movl %ebx,%edi
+ leaq K256(%rip),%rbp
+ xorl %ecx,%edi
+ movl 0(%rsi),%r12d
+ movl %r8d,%r13d
+ movl %eax,%r14d
+ bswapl %r12d
+ rorl $14,%r13d
+ movl %r9d,%r15d
+
+ xorl %r8d,%r13d
+ rorl $9,%r14d
+ xorl %r10d,%r15d
+
+ movl %r12d,0(%rsp)
+ xorl %eax,%r14d
+ andl %r8d,%r15d
+
+ rorl $5,%r13d
+ addl %r11d,%r12d
+ xorl %r10d,%r15d
+
+ rorl $11,%r14d
+ xorl %r8d,%r13d
+ addl %r15d,%r12d
+
+ movl %eax,%r15d
+ addl (%rbp),%r12d
+ xorl %eax,%r14d
+
+ xorl %ebx,%r15d
+ rorl $6,%r13d
+ movl %ebx,%r11d
+
+ andl %r15d,%edi
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %edi,%r11d
+ addl %r12d,%edx
+ addl %r12d,%r11d
+
+ leaq 4(%rbp),%rbp
+ addl %r14d,%r11d
+ movl 4(%rsi),%r12d
+ movl %edx,%r13d
+ movl %r11d,%r14d
+ bswapl %r12d
+ rorl $14,%r13d
+ movl %r8d,%edi
+
+ xorl %edx,%r13d
+ rorl $9,%r14d
+ xorl %r9d,%edi
+
+ movl %r12d,4(%rsp)
+ xorl %r11d,%r14d
+ andl %edx,%edi
+
+ rorl $5,%r13d
+ addl %r10d,%r12d
+ xorl %r9d,%edi
+
+ rorl $11,%r14d
+ xorl %edx,%r13d
+ addl %edi,%r12d
+
+ movl %r11d,%edi
+ addl (%rbp),%r12d
+ xorl %r11d,%r14d
+
+ xorl %eax,%edi
+ rorl $6,%r13d
+ movl %eax,%r10d
+
+ andl %edi,%r15d
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %r15d,%r10d
+ addl %r12d,%ecx
+ addl %r12d,%r10d
+
+ leaq 4(%rbp),%rbp
+ addl %r14d,%r10d
+ movl 8(%rsi),%r12d
+ movl %ecx,%r13d
+ movl %r10d,%r14d
+ bswapl %r12d
+ rorl $14,%r13d
+ movl %edx,%r15d
+
+ xorl %ecx,%r13d
+ rorl $9,%r14d
+ xorl %r8d,%r15d
+
+ movl %r12d,8(%rsp)
+ xorl %r10d,%r14d
+ andl %ecx,%r15d
+
+ rorl $5,%r13d
+ addl %r9d,%r12d
+ xorl %r8d,%r15d
+
+ rorl $11,%r14d
+ xorl %ecx,%r13d
+ addl %r15d,%r12d
+
+ movl %r10d,%r15d
+ addl (%rbp),%r12d
+ xorl %r10d,%r14d
+
+ xorl %r11d,%r15d
+ rorl $6,%r13d
+ movl %r11d,%r9d
+
+ andl %r15d,%edi
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %edi,%r9d
+ addl %r12d,%ebx
+ addl %r12d,%r9d
+
+ leaq 4(%rbp),%rbp
+ addl %r14d,%r9d
+ movl 12(%rsi),%r12d
+ movl %ebx,%r13d
+ movl %r9d,%r14d
+ bswapl %r12d
+ rorl $14,%r13d
+ movl %ecx,%edi
+
+ xorl %ebx,%r13d
+ rorl $9,%r14d
+ xorl %edx,%edi
+
+ movl %r12d,12(%rsp)
+ xorl %r9d,%r14d
+ andl %ebx,%edi
+
+ rorl $5,%r13d
+ addl %r8d,%r12d
+ xorl %edx,%edi
+
+ rorl $11,%r14d
+ xorl %ebx,%r13d
+ addl %edi,%r12d
+
+ movl %r9d,%edi
+ addl (%rbp),%r12d
+ xorl %r9d,%r14d
+
+ xorl %r10d,%edi
+ rorl $6,%r13d
+ movl %r10d,%r8d
+
+ andl %edi,%r15d
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %r15d,%r8d
+ addl %r12d,%eax
+ addl %r12d,%r8d
+
+ leaq 20(%rbp),%rbp
+ addl %r14d,%r8d
+ movl 16(%rsi),%r12d
+ movl %eax,%r13d
+ movl %r8d,%r14d
+ bswapl %r12d
+ rorl $14,%r13d
+ movl %ebx,%r15d
+
+ xorl %eax,%r13d
+ rorl $9,%r14d
+ xorl %ecx,%r15d
+
+ movl %r12d,16(%rsp)
+ xorl %r8d,%r14d
+ andl %eax,%r15d
+
+ rorl $5,%r13d
+ addl %edx,%r12d
+ xorl %ecx,%r15d
+
+ rorl $11,%r14d
+ xorl %eax,%r13d
+ addl %r15d,%r12d
+
+ movl %r8d,%r15d
+ addl (%rbp),%r12d
+ xorl %r8d,%r14d
+
+ xorl %r9d,%r15d
+ rorl $6,%r13d
+ movl %r9d,%edx
+
+ andl %r15d,%edi
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %edi,%edx
+ addl %r12d,%r11d
+ addl %r12d,%edx
+
+ leaq 4(%rbp),%rbp
+ addl %r14d,%edx
+ movl 20(%rsi),%r12d
+ movl %r11d,%r13d
+ movl %edx,%r14d
+ bswapl %r12d
+ rorl $14,%r13d
+ movl %eax,%edi
+
+ xorl %r11d,%r13d
+ rorl $9,%r14d
+ xorl %ebx,%edi
+
+ movl %r12d,20(%rsp)
+ xorl %edx,%r14d
+ andl %r11d,%edi
+
+ rorl $5,%r13d
+ addl %ecx,%r12d
+ xorl %ebx,%edi
+
+ rorl $11,%r14d
+ xorl %r11d,%r13d
+ addl %edi,%r12d
+
+ movl %edx,%edi
+ addl (%rbp),%r12d
+ xorl %edx,%r14d
+
+ xorl %r8d,%edi
+ rorl $6,%r13d
+ movl %r8d,%ecx
+
+ andl %edi,%r15d
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %r15d,%ecx
+ addl %r12d,%r10d
+ addl %r12d,%ecx
+
+ leaq 4(%rbp),%rbp
+ addl %r14d,%ecx
+ movl 24(%rsi),%r12d
+ movl %r10d,%r13d
+ movl %ecx,%r14d
+ bswapl %r12d
+ rorl $14,%r13d
+ movl %r11d,%r15d
+
+ xorl %r10d,%r13d
+ rorl $9,%r14d
+ xorl %eax,%r15d
+
+ movl %r12d,24(%rsp)
+ xorl %ecx,%r14d
+ andl %r10d,%r15d
+
+ rorl $5,%r13d
+ addl %ebx,%r12d
+ xorl %eax,%r15d
+
+ rorl $11,%r14d
+ xorl %r10d,%r13d
+ addl %r15d,%r12d
+
+ movl %ecx,%r15d
+ addl (%rbp),%r12d
+ xorl %ecx,%r14d
+
+ xorl %edx,%r15d
+ rorl $6,%r13d
+ movl %edx,%ebx
+
+ andl %r15d,%edi
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %edi,%ebx
+ addl %r12d,%r9d
+ addl %r12d,%ebx
+
+ leaq 4(%rbp),%rbp
+ addl %r14d,%ebx
+ movl 28(%rsi),%r12d
+ movl %r9d,%r13d
+ movl %ebx,%r14d
+ bswapl %r12d
+ rorl $14,%r13d
+ movl %r10d,%edi
+
+ xorl %r9d,%r13d
+ rorl $9,%r14d
+ xorl %r11d,%edi
+
+ movl %r12d,28(%rsp)
+ xorl %ebx,%r14d
+ andl %r9d,%edi
+
+ rorl $5,%r13d
+ addl %eax,%r12d
+ xorl %r11d,%edi
+
+ rorl $11,%r14d
+ xorl %r9d,%r13d
+ addl %edi,%r12d
+
+ movl %ebx,%edi
+ addl (%rbp),%r12d
+ xorl %ebx,%r14d
+
+ xorl %ecx,%edi
+ rorl $6,%r13d
+ movl %ecx,%eax
+
+ andl %edi,%r15d
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %r15d,%eax
+ addl %r12d,%r8d
+ addl %r12d,%eax
+
+ leaq 20(%rbp),%rbp
+ addl %r14d,%eax
+ movl 32(%rsi),%r12d
+ movl %r8d,%r13d
+ movl %eax,%r14d
+ bswapl %r12d
+ rorl $14,%r13d
+ movl %r9d,%r15d
+
+ xorl %r8d,%r13d
+ rorl $9,%r14d
+ xorl %r10d,%r15d
+
+ movl %r12d,32(%rsp)
+ xorl %eax,%r14d
+ andl %r8d,%r15d
+
+ rorl $5,%r13d
+ addl %r11d,%r12d
+ xorl %r10d,%r15d
+
+ rorl $11,%r14d
+ xorl %r8d,%r13d
+ addl %r15d,%r12d
+
+ movl %eax,%r15d
+ addl (%rbp),%r12d
+ xorl %eax,%r14d
+
+ xorl %ebx,%r15d
+ rorl $6,%r13d
+ movl %ebx,%r11d
+
+ andl %r15d,%edi
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %edi,%r11d
+ addl %r12d,%edx
+ addl %r12d,%r11d
+
+ leaq 4(%rbp),%rbp
+ addl %r14d,%r11d
+ movl 36(%rsi),%r12d
+ movl %edx,%r13d
+ movl %r11d,%r14d
+ bswapl %r12d
+ rorl $14,%r13d
+ movl %r8d,%edi
+
+ xorl %edx,%r13d
+ rorl $9,%r14d
+ xorl %r9d,%edi
+
+ movl %r12d,36(%rsp)
+ xorl %r11d,%r14d
+ andl %edx,%edi
+
+ rorl $5,%r13d
+ addl %r10d,%r12d
+ xorl %r9d,%edi
+
+ rorl $11,%r14d
+ xorl %edx,%r13d
+ addl %edi,%r12d
+
+ movl %r11d,%edi
+ addl (%rbp),%r12d
+ xorl %r11d,%r14d
+
+ xorl %eax,%edi
+ rorl $6,%r13d
+ movl %eax,%r10d
+
+ andl %edi,%r15d
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %r15d,%r10d
+ addl %r12d,%ecx
+ addl %r12d,%r10d
+
+ leaq 4(%rbp),%rbp
+ addl %r14d,%r10d
+ movl 40(%rsi),%r12d
+ movl %ecx,%r13d
+ movl %r10d,%r14d
+ bswapl %r12d
+ rorl $14,%r13d
+ movl %edx,%r15d
+
+ xorl %ecx,%r13d
+ rorl $9,%r14d
+ xorl %r8d,%r15d
+
+ movl %r12d,40(%rsp)
+ xorl %r10d,%r14d
+ andl %ecx,%r15d
+
+ rorl $5,%r13d
+ addl %r9d,%r12d
+ xorl %r8d,%r15d
+
+ rorl $11,%r14d
+ xorl %ecx,%r13d
+ addl %r15d,%r12d
+
+ movl %r10d,%r15d
+ addl (%rbp),%r12d
+ xorl %r10d,%r14d
+
+ xorl %r11d,%r15d
+ rorl $6,%r13d
+ movl %r11d,%r9d
+
+ andl %r15d,%edi
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %edi,%r9d
+ addl %r12d,%ebx
+ addl %r12d,%r9d
+
+ leaq 4(%rbp),%rbp
+ addl %r14d,%r9d
+ movl 44(%rsi),%r12d
+ movl %ebx,%r13d
+ movl %r9d,%r14d
+ bswapl %r12d
+ rorl $14,%r13d
+ movl %ecx,%edi
+
+ xorl %ebx,%r13d
+ rorl $9,%r14d
+ xorl %edx,%edi
+
+ movl %r12d,44(%rsp)
+ xorl %r9d,%r14d
+ andl %ebx,%edi
+
+ rorl $5,%r13d
+ addl %r8d,%r12d
+ xorl %edx,%edi
+
+ rorl $11,%r14d
+ xorl %ebx,%r13d
+ addl %edi,%r12d
+
+ movl %r9d,%edi
+ addl (%rbp),%r12d
+ xorl %r9d,%r14d
+
+ xorl %r10d,%edi
+ rorl $6,%r13d
+ movl %r10d,%r8d
+
+ andl %edi,%r15d
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %r15d,%r8d
+ addl %r12d,%eax
+ addl %r12d,%r8d
+
+ leaq 20(%rbp),%rbp
+ addl %r14d,%r8d
+ movl 48(%rsi),%r12d
+ movl %eax,%r13d
+ movl %r8d,%r14d
+ bswapl %r12d
+ rorl $14,%r13d
+ movl %ebx,%r15d
+
+ xorl %eax,%r13d
+ rorl $9,%r14d
+ xorl %ecx,%r15d
+
+ movl %r12d,48(%rsp)
+ xorl %r8d,%r14d
+ andl %eax,%r15d
+
+ rorl $5,%r13d
+ addl %edx,%r12d
+ xorl %ecx,%r15d
+
+ rorl $11,%r14d
+ xorl %eax,%r13d
+ addl %r15d,%r12d
+
+ movl %r8d,%r15d
+ addl (%rbp),%r12d
+ xorl %r8d,%r14d
+
+ xorl %r9d,%r15d
+ rorl $6,%r13d
+ movl %r9d,%edx
+
+ andl %r15d,%edi
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %edi,%edx
+ addl %r12d,%r11d
+ addl %r12d,%edx
+
+ leaq 4(%rbp),%rbp
+ addl %r14d,%edx
+ movl 52(%rsi),%r12d
+ movl %r11d,%r13d
+ movl %edx,%r14d
+ bswapl %r12d
+ rorl $14,%r13d
+ movl %eax,%edi
+
+ xorl %r11d,%r13d
+ rorl $9,%r14d
+ xorl %ebx,%edi
+
+ movl %r12d,52(%rsp)
+ xorl %edx,%r14d
+ andl %r11d,%edi
+
+ rorl $5,%r13d
+ addl %ecx,%r12d
+ xorl %ebx,%edi
+
+ rorl $11,%r14d
+ xorl %r11d,%r13d
+ addl %edi,%r12d
+
+ movl %edx,%edi
+ addl (%rbp),%r12d
+ xorl %edx,%r14d
+
+ xorl %r8d,%edi
+ rorl $6,%r13d
+ movl %r8d,%ecx
+
+ andl %edi,%r15d
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %r15d,%ecx
+ addl %r12d,%r10d
+ addl %r12d,%ecx
+
+ leaq 4(%rbp),%rbp
+ addl %r14d,%ecx
+ movl 56(%rsi),%r12d
+ movl %r10d,%r13d
+ movl %ecx,%r14d
+ bswapl %r12d
+ rorl $14,%r13d
+ movl %r11d,%r15d
+
+ xorl %r10d,%r13d
+ rorl $9,%r14d
+ xorl %eax,%r15d
+
+ movl %r12d,56(%rsp)
+ xorl %ecx,%r14d
+ andl %r10d,%r15d
+
+ rorl $5,%r13d
+ addl %ebx,%r12d
+ xorl %eax,%r15d
+
+ rorl $11,%r14d
+ xorl %r10d,%r13d
+ addl %r15d,%r12d
+
+ movl %ecx,%r15d
+ addl (%rbp),%r12d
+ xorl %ecx,%r14d
+
+ xorl %edx,%r15d
+ rorl $6,%r13d
+ movl %edx,%ebx
+
+ andl %r15d,%edi
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %edi,%ebx
+ addl %r12d,%r9d
+ addl %r12d,%ebx
+
+ leaq 4(%rbp),%rbp
+ addl %r14d,%ebx
+ movl 60(%rsi),%r12d
+ movl %r9d,%r13d
+ movl %ebx,%r14d
+ bswapl %r12d
+ rorl $14,%r13d
+ movl %r10d,%edi
+
+ xorl %r9d,%r13d
+ rorl $9,%r14d
+ xorl %r11d,%edi
+
+ movl %r12d,60(%rsp)
+ xorl %ebx,%r14d
+ andl %r9d,%edi
+
+ rorl $5,%r13d
+ addl %eax,%r12d
+ xorl %r11d,%edi
+
+ rorl $11,%r14d
+ xorl %r9d,%r13d
+ addl %edi,%r12d
+
+ movl %ebx,%edi
+ addl (%rbp),%r12d
+ xorl %ebx,%r14d
+
+ xorl %ecx,%edi
+ rorl $6,%r13d
+ movl %ecx,%eax
+
+ andl %edi,%r15d
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %r15d,%eax
+ addl %r12d,%r8d
+ addl %r12d,%eax
+
+ leaq 20(%rbp),%rbp
+ jmp L$rounds_16_xx
+.p2align 4
+L$rounds_16_xx:
+ movl 4(%rsp),%r13d
+ movl 56(%rsp),%r15d
+
+ movl %r13d,%r12d
+ rorl $11,%r13d
+ addl %r14d,%eax
+ movl %r15d,%r14d
+ rorl $2,%r15d
+
+ xorl %r12d,%r13d
+ shrl $3,%r12d
+ rorl $7,%r13d
+ xorl %r14d,%r15d
+ shrl $10,%r14d
+
+ rorl $17,%r15d
+ xorl %r13d,%r12d
+ xorl %r14d,%r15d
+ addl 36(%rsp),%r12d
+
+ addl 0(%rsp),%r12d
+ movl %r8d,%r13d
+ addl %r15d,%r12d
+ movl %eax,%r14d
+ rorl $14,%r13d
+ movl %r9d,%r15d
+
+ xorl %r8d,%r13d
+ rorl $9,%r14d
+ xorl %r10d,%r15d
+
+ movl %r12d,0(%rsp)
+ xorl %eax,%r14d
+ andl %r8d,%r15d
+
+ rorl $5,%r13d
+ addl %r11d,%r12d
+ xorl %r10d,%r15d
+
+ rorl $11,%r14d
+ xorl %r8d,%r13d
+ addl %r15d,%r12d
+
+ movl %eax,%r15d
+ addl (%rbp),%r12d
+ xorl %eax,%r14d
+
+ xorl %ebx,%r15d
+ rorl $6,%r13d
+ movl %ebx,%r11d
+
+ andl %r15d,%edi
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %edi,%r11d
+ addl %r12d,%edx
+ addl %r12d,%r11d
+
+ leaq 4(%rbp),%rbp
+ movl 8(%rsp),%r13d
+ movl 60(%rsp),%edi
+
+ movl %r13d,%r12d
+ rorl $11,%r13d
+ addl %r14d,%r11d
+ movl %edi,%r14d
+ rorl $2,%edi
+
+ xorl %r12d,%r13d
+ shrl $3,%r12d
+ rorl $7,%r13d
+ xorl %r14d,%edi
+ shrl $10,%r14d
+
+ rorl $17,%edi
+ xorl %r13d,%r12d
+ xorl %r14d,%edi
+ addl 40(%rsp),%r12d
+
+ addl 4(%rsp),%r12d
+ movl %edx,%r13d
+ addl %edi,%r12d
+ movl %r11d,%r14d
+ rorl $14,%r13d
+ movl %r8d,%edi
+
+ xorl %edx,%r13d
+ rorl $9,%r14d
+ xorl %r9d,%edi
+
+ movl %r12d,4(%rsp)
+ xorl %r11d,%r14d
+ andl %edx,%edi
+
+ rorl $5,%r13d
+ addl %r10d,%r12d
+ xorl %r9d,%edi
+
+ rorl $11,%r14d
+ xorl %edx,%r13d
+ addl %edi,%r12d
+
+ movl %r11d,%edi
+ addl (%rbp),%r12d
+ xorl %r11d,%r14d
+
+ xorl %eax,%edi
+ rorl $6,%r13d
+ movl %eax,%r10d
+
+ andl %edi,%r15d
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %r15d,%r10d
+ addl %r12d,%ecx
+ addl %r12d,%r10d
+
+ leaq 4(%rbp),%rbp
+ movl 12(%rsp),%r13d
+ movl 0(%rsp),%r15d
+
+ movl %r13d,%r12d
+ rorl $11,%r13d
+ addl %r14d,%r10d
+ movl %r15d,%r14d
+ rorl $2,%r15d
+
+ xorl %r12d,%r13d
+ shrl $3,%r12d
+ rorl $7,%r13d
+ xorl %r14d,%r15d
+ shrl $10,%r14d
+
+ rorl $17,%r15d
+ xorl %r13d,%r12d
+ xorl %r14d,%r15d
+ addl 44(%rsp),%r12d
+
+ addl 8(%rsp),%r12d
+ movl %ecx,%r13d
+ addl %r15d,%r12d
+ movl %r10d,%r14d
+ rorl $14,%r13d
+ movl %edx,%r15d
+
+ xorl %ecx,%r13d
+ rorl $9,%r14d
+ xorl %r8d,%r15d
+
+ movl %r12d,8(%rsp)
+ xorl %r10d,%r14d
+ andl %ecx,%r15d
+
+ rorl $5,%r13d
+ addl %r9d,%r12d
+ xorl %r8d,%r15d
+
+ rorl $11,%r14d
+ xorl %ecx,%r13d
+ addl %r15d,%r12d
+
+ movl %r10d,%r15d
+ addl (%rbp),%r12d
+ xorl %r10d,%r14d
+
+ xorl %r11d,%r15d
+ rorl $6,%r13d
+ movl %r11d,%r9d
+
+ andl %r15d,%edi
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %edi,%r9d
+ addl %r12d,%ebx
+ addl %r12d,%r9d
+
+ leaq 4(%rbp),%rbp
+ movl 16(%rsp),%r13d
+ movl 4(%rsp),%edi
+
+ movl %r13d,%r12d
+ rorl $11,%r13d
+ addl %r14d,%r9d
+ movl %edi,%r14d
+ rorl $2,%edi
+
+ xorl %r12d,%r13d
+ shrl $3,%r12d
+ rorl $7,%r13d
+ xorl %r14d,%edi
+ shrl $10,%r14d
+
+ rorl $17,%edi
+ xorl %r13d,%r12d
+ xorl %r14d,%edi
+ addl 48(%rsp),%r12d
+
+ addl 12(%rsp),%r12d
+ movl %ebx,%r13d
+ addl %edi,%r12d
+ movl %r9d,%r14d
+ rorl $14,%r13d
+ movl %ecx,%edi
+
+ xorl %ebx,%r13d
+ rorl $9,%r14d
+ xorl %edx,%edi
+
+ movl %r12d,12(%rsp)
+ xorl %r9d,%r14d
+ andl %ebx,%edi
+
+ rorl $5,%r13d
+ addl %r8d,%r12d
+ xorl %edx,%edi
+
+ rorl $11,%r14d
+ xorl %ebx,%r13d
+ addl %edi,%r12d
+
+ movl %r9d,%edi
+ addl (%rbp),%r12d
+ xorl %r9d,%r14d
+
+ xorl %r10d,%edi
+ rorl $6,%r13d
+ movl %r10d,%r8d
+
+ andl %edi,%r15d
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %r15d,%r8d
+ addl %r12d,%eax
+ addl %r12d,%r8d
+
+ leaq 20(%rbp),%rbp
+ movl 20(%rsp),%r13d
+ movl 8(%rsp),%r15d
+
+ movl %r13d,%r12d
+ rorl $11,%r13d
+ addl %r14d,%r8d
+ movl %r15d,%r14d
+ rorl $2,%r15d
+
+ xorl %r12d,%r13d
+ shrl $3,%r12d
+ rorl $7,%r13d
+ xorl %r14d,%r15d
+ shrl $10,%r14d
+
+ rorl $17,%r15d
+ xorl %r13d,%r12d
+ xorl %r14d,%r15d
+ addl 52(%rsp),%r12d
+
+ addl 16(%rsp),%r12d
+ movl %eax,%r13d
+ addl %r15d,%r12d
+ movl %r8d,%r14d
+ rorl $14,%r13d
+ movl %ebx,%r15d
+
+ xorl %eax,%r13d
+ rorl $9,%r14d
+ xorl %ecx,%r15d
+
+ movl %r12d,16(%rsp)
+ xorl %r8d,%r14d
+ andl %eax,%r15d
+
+ rorl $5,%r13d
+ addl %edx,%r12d
+ xorl %ecx,%r15d
+
+ rorl $11,%r14d
+ xorl %eax,%r13d
+ addl %r15d,%r12d
+
+ movl %r8d,%r15d
+ addl (%rbp),%r12d
+ xorl %r8d,%r14d
+
+ xorl %r9d,%r15d
+ rorl $6,%r13d
+ movl %r9d,%edx
+
+ andl %r15d,%edi
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %edi,%edx
+ addl %r12d,%r11d
+ addl %r12d,%edx
+
+ leaq 4(%rbp),%rbp
+ movl 24(%rsp),%r13d
+ movl 12(%rsp),%edi
+
+ movl %r13d,%r12d
+ rorl $11,%r13d
+ addl %r14d,%edx
+ movl %edi,%r14d
+ rorl $2,%edi
+
+ xorl %r12d,%r13d
+ shrl $3,%r12d
+ rorl $7,%r13d
+ xorl %r14d,%edi
+ shrl $10,%r14d
+
+ rorl $17,%edi
+ xorl %r13d,%r12d
+ xorl %r14d,%edi
+ addl 56(%rsp),%r12d
+
+ addl 20(%rsp),%r12d
+ movl %r11d,%r13d
+ addl %edi,%r12d
+ movl %edx,%r14d
+ rorl $14,%r13d
+ movl %eax,%edi
+
+ xorl %r11d,%r13d
+ rorl $9,%r14d
+ xorl %ebx,%edi
+
+ movl %r12d,20(%rsp)
+ xorl %edx,%r14d
+ andl %r11d,%edi
+
+ rorl $5,%r13d
+ addl %ecx,%r12d
+ xorl %ebx,%edi
+
+ rorl $11,%r14d
+ xorl %r11d,%r13d
+ addl %edi,%r12d
+
+ movl %edx,%edi
+ addl (%rbp),%r12d
+ xorl %edx,%r14d
+
+ xorl %r8d,%edi
+ rorl $6,%r13d
+ movl %r8d,%ecx
+
+ andl %edi,%r15d
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %r15d,%ecx
+ addl %r12d,%r10d
+ addl %r12d,%ecx
+
+ leaq 4(%rbp),%rbp
+ movl 28(%rsp),%r13d
+ movl 16(%rsp),%r15d
+
+ movl %r13d,%r12d
+ rorl $11,%r13d
+ addl %r14d,%ecx
+ movl %r15d,%r14d
+ rorl $2,%r15d
+
+ xorl %r12d,%r13d
+ shrl $3,%r12d
+ rorl $7,%r13d
+ xorl %r14d,%r15d
+ shrl $10,%r14d
+
+ rorl $17,%r15d
+ xorl %r13d,%r12d
+ xorl %r14d,%r15d
+ addl 60(%rsp),%r12d
+
+ addl 24(%rsp),%r12d
+ movl %r10d,%r13d
+ addl %r15d,%r12d
+ movl %ecx,%r14d
+ rorl $14,%r13d
+ movl %r11d,%r15d
+
+ xorl %r10d,%r13d
+ rorl $9,%r14d
+ xorl %eax,%r15d
+
+ movl %r12d,24(%rsp)
+ xorl %ecx,%r14d
+ andl %r10d,%r15d
+
+ rorl $5,%r13d
+ addl %ebx,%r12d
+ xorl %eax,%r15d
+
+ rorl $11,%r14d
+ xorl %r10d,%r13d
+ addl %r15d,%r12d
+
+ movl %ecx,%r15d
+ addl (%rbp),%r12d
+ xorl %ecx,%r14d
+
+ xorl %edx,%r15d
+ rorl $6,%r13d
+ movl %edx,%ebx
+
+ andl %r15d,%edi
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %edi,%ebx
+ addl %r12d,%r9d
+ addl %r12d,%ebx
+
+ leaq 4(%rbp),%rbp
+ movl 32(%rsp),%r13d
+ movl 20(%rsp),%edi
+
+ movl %r13d,%r12d
+ rorl $11,%r13d
+ addl %r14d,%ebx
+ movl %edi,%r14d
+ rorl $2,%edi
+
+ xorl %r12d,%r13d
+ shrl $3,%r12d
+ rorl $7,%r13d
+ xorl %r14d,%edi
+ shrl $10,%r14d
+
+ rorl $17,%edi
+ xorl %r13d,%r12d
+ xorl %r14d,%edi
+ addl 0(%rsp),%r12d
+
+ addl 28(%rsp),%r12d
+ movl %r9d,%r13d
+ addl %edi,%r12d
+ movl %ebx,%r14d
+ rorl $14,%r13d
+ movl %r10d,%edi
+
+ xorl %r9d,%r13d
+ rorl $9,%r14d
+ xorl %r11d,%edi
+
+ movl %r12d,28(%rsp)
+ xorl %ebx,%r14d
+ andl %r9d,%edi
+
+ rorl $5,%r13d
+ addl %eax,%r12d
+ xorl %r11d,%edi
+
+ rorl $11,%r14d
+ xorl %r9d,%r13d
+ addl %edi,%r12d
+
+ movl %ebx,%edi
+ addl (%rbp),%r12d
+ xorl %ebx,%r14d
+
+ xorl %ecx,%edi
+ rorl $6,%r13d
+ movl %ecx,%eax
+
+ andl %edi,%r15d
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %r15d,%eax
+ addl %r12d,%r8d
+ addl %r12d,%eax
+
+ leaq 20(%rbp),%rbp
+ movl 36(%rsp),%r13d
+ movl 24(%rsp),%r15d
+
+ movl %r13d,%r12d
+ rorl $11,%r13d
+ addl %r14d,%eax
+ movl %r15d,%r14d
+ rorl $2,%r15d
+
+ xorl %r12d,%r13d
+ shrl $3,%r12d
+ rorl $7,%r13d
+ xorl %r14d,%r15d
+ shrl $10,%r14d
+
+ rorl $17,%r15d
+ xorl %r13d,%r12d
+ xorl %r14d,%r15d
+ addl 4(%rsp),%r12d
+
+ addl 32(%rsp),%r12d
+ movl %r8d,%r13d
+ addl %r15d,%r12d
+ movl %eax,%r14d
+ rorl $14,%r13d
+ movl %r9d,%r15d
+
+ xorl %r8d,%r13d
+ rorl $9,%r14d
+ xorl %r10d,%r15d
+
+ movl %r12d,32(%rsp)
+ xorl %eax,%r14d
+ andl %r8d,%r15d
+
+ rorl $5,%r13d
+ addl %r11d,%r12d
+ xorl %r10d,%r15d
+
+ rorl $11,%r14d
+ xorl %r8d,%r13d
+ addl %r15d,%r12d
+
+ movl %eax,%r15d
+ addl (%rbp),%r12d
+ xorl %eax,%r14d
+
+ xorl %ebx,%r15d
+ rorl $6,%r13d
+ movl %ebx,%r11d
+
+ andl %r15d,%edi
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %edi,%r11d
+ addl %r12d,%edx
+ addl %r12d,%r11d
+
+ leaq 4(%rbp),%rbp
+ movl 40(%rsp),%r13d
+ movl 28(%rsp),%edi
+
+ movl %r13d,%r12d
+ rorl $11,%r13d
+ addl %r14d,%r11d
+ movl %edi,%r14d
+ rorl $2,%edi
+
+ xorl %r12d,%r13d
+ shrl $3,%r12d
+ rorl $7,%r13d
+ xorl %r14d,%edi
+ shrl $10,%r14d
+
+ rorl $17,%edi
+ xorl %r13d,%r12d
+ xorl %r14d,%edi
+ addl 8(%rsp),%r12d
+
+ addl 36(%rsp),%r12d
+ movl %edx,%r13d
+ addl %edi,%r12d
+ movl %r11d,%r14d
+ rorl $14,%r13d
+ movl %r8d,%edi
+
+ xorl %edx,%r13d
+ rorl $9,%r14d
+ xorl %r9d,%edi
+
+ movl %r12d,36(%rsp)
+ xorl %r11d,%r14d
+ andl %edx,%edi
+
+ rorl $5,%r13d
+ addl %r10d,%r12d
+ xorl %r9d,%edi
+
+ rorl $11,%r14d
+ xorl %edx,%r13d
+ addl %edi,%r12d
+
+ movl %r11d,%edi
+ addl (%rbp),%r12d
+ xorl %r11d,%r14d
+
+ xorl %eax,%edi
+ rorl $6,%r13d
+ movl %eax,%r10d
+
+ andl %edi,%r15d
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %r15d,%r10d
+ addl %r12d,%ecx
+ addl %r12d,%r10d
+
+ leaq 4(%rbp),%rbp
+ movl 44(%rsp),%r13d
+ movl 32(%rsp),%r15d
+
+ movl %r13d,%r12d
+ rorl $11,%r13d
+ addl %r14d,%r10d
+ movl %r15d,%r14d
+ rorl $2,%r15d
+
+ xorl %r12d,%r13d
+ shrl $3,%r12d
+ rorl $7,%r13d
+ xorl %r14d,%r15d
+ shrl $10,%r14d
+
+ rorl $17,%r15d
+ xorl %r13d,%r12d
+ xorl %r14d,%r15d
+ addl 12(%rsp),%r12d
+
+ addl 40(%rsp),%r12d
+ movl %ecx,%r13d
+ addl %r15d,%r12d
+ movl %r10d,%r14d
+ rorl $14,%r13d
+ movl %edx,%r15d
+
+ xorl %ecx,%r13d
+ rorl $9,%r14d
+ xorl %r8d,%r15d
+
+ movl %r12d,40(%rsp)
+ xorl %r10d,%r14d
+ andl %ecx,%r15d
+
+ rorl $5,%r13d
+ addl %r9d,%r12d
+ xorl %r8d,%r15d
+
+ rorl $11,%r14d
+ xorl %ecx,%r13d
+ addl %r15d,%r12d
+
+ movl %r10d,%r15d
+ addl (%rbp),%r12d
+ xorl %r10d,%r14d
+
+ xorl %r11d,%r15d
+ rorl $6,%r13d
+ movl %r11d,%r9d
+
+ andl %r15d,%edi
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %edi,%r9d
+ addl %r12d,%ebx
+ addl %r12d,%r9d
+
+ leaq 4(%rbp),%rbp
+ movl 48(%rsp),%r13d
+ movl 36(%rsp),%edi
+
+ movl %r13d,%r12d
+ rorl $11,%r13d
+ addl %r14d,%r9d
+ movl %edi,%r14d
+ rorl $2,%edi
+
+ xorl %r12d,%r13d
+ shrl $3,%r12d
+ rorl $7,%r13d
+ xorl %r14d,%edi
+ shrl $10,%r14d
+
+ rorl $17,%edi
+ xorl %r13d,%r12d
+ xorl %r14d,%edi
+ addl 16(%rsp),%r12d
+
+ addl 44(%rsp),%r12d
+ movl %ebx,%r13d
+ addl %edi,%r12d
+ movl %r9d,%r14d
+ rorl $14,%r13d
+ movl %ecx,%edi
+
+ xorl %ebx,%r13d
+ rorl $9,%r14d
+ xorl %edx,%edi
+
+ movl %r12d,44(%rsp)
+ xorl %r9d,%r14d
+ andl %ebx,%edi
+
+ rorl $5,%r13d
+ addl %r8d,%r12d
+ xorl %edx,%edi
+
+ rorl $11,%r14d
+ xorl %ebx,%r13d
+ addl %edi,%r12d
+
+ movl %r9d,%edi
+ addl (%rbp),%r12d
+ xorl %r9d,%r14d
+
+ xorl %r10d,%edi
+ rorl $6,%r13d
+ movl %r10d,%r8d
+
+ andl %edi,%r15d
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %r15d,%r8d
+ addl %r12d,%eax
+ addl %r12d,%r8d
+
+ leaq 20(%rbp),%rbp
+ movl 52(%rsp),%r13d
+ movl 40(%rsp),%r15d
+
+ movl %r13d,%r12d
+ rorl $11,%r13d
+ addl %r14d,%r8d
+ movl %r15d,%r14d
+ rorl $2,%r15d
+
+ xorl %r12d,%r13d
+ shrl $3,%r12d
+ rorl $7,%r13d
+ xorl %r14d,%r15d
+ shrl $10,%r14d
+
+ rorl $17,%r15d
+ xorl %r13d,%r12d
+ xorl %r14d,%r15d
+ addl 20(%rsp),%r12d
+
+ addl 48(%rsp),%r12d
+ movl %eax,%r13d
+ addl %r15d,%r12d
+ movl %r8d,%r14d
+ rorl $14,%r13d
+ movl %ebx,%r15d
+
+ xorl %eax,%r13d
+ rorl $9,%r14d
+ xorl %ecx,%r15d
+
+ movl %r12d,48(%rsp)
+ xorl %r8d,%r14d
+ andl %eax,%r15d
+
+ rorl $5,%r13d
+ addl %edx,%r12d
+ xorl %ecx,%r15d
+
+ rorl $11,%r14d
+ xorl %eax,%r13d
+ addl %r15d,%r12d
+
+ movl %r8d,%r15d
+ addl (%rbp),%r12d
+ xorl %r8d,%r14d
+
+ xorl %r9d,%r15d
+ rorl $6,%r13d
+ movl %r9d,%edx
+
+ andl %r15d,%edi
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %edi,%edx
+ addl %r12d,%r11d
+ addl %r12d,%edx
+
+ leaq 4(%rbp),%rbp
+ movl 56(%rsp),%r13d
+ movl 44(%rsp),%edi
+
+ movl %r13d,%r12d
+ rorl $11,%r13d
+ addl %r14d,%edx
+ movl %edi,%r14d
+ rorl $2,%edi
+
+ xorl %r12d,%r13d
+ shrl $3,%r12d
+ rorl $7,%r13d
+ xorl %r14d,%edi
+ shrl $10,%r14d
+
+ rorl $17,%edi
+ xorl %r13d,%r12d
+ xorl %r14d,%edi
+ addl 24(%rsp),%r12d
+
+ addl 52(%rsp),%r12d
+ movl %r11d,%r13d
+ addl %edi,%r12d
+ movl %edx,%r14d
+ rorl $14,%r13d
+ movl %eax,%edi
+
+ xorl %r11d,%r13d
+ rorl $9,%r14d
+ xorl %ebx,%edi
+
+ movl %r12d,52(%rsp)
+ xorl %edx,%r14d
+ andl %r11d,%edi
+
+ rorl $5,%r13d
+ addl %ecx,%r12d
+ xorl %ebx,%edi
+
+ rorl $11,%r14d
+ xorl %r11d,%r13d
+ addl %edi,%r12d
+
+ movl %edx,%edi
+ addl (%rbp),%r12d
+ xorl %edx,%r14d
+
+ xorl %r8d,%edi
+ rorl $6,%r13d
+ movl %r8d,%ecx
+
+ andl %edi,%r15d
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %r15d,%ecx
+ addl %r12d,%r10d
+ addl %r12d,%ecx
+
+ leaq 4(%rbp),%rbp
+ movl 60(%rsp),%r13d
+ movl 48(%rsp),%r15d
+
+ movl %r13d,%r12d
+ rorl $11,%r13d
+ addl %r14d,%ecx
+ movl %r15d,%r14d
+ rorl $2,%r15d
+
+ xorl %r12d,%r13d
+ shrl $3,%r12d
+ rorl $7,%r13d
+ xorl %r14d,%r15d
+ shrl $10,%r14d
+
+ rorl $17,%r15d
+ xorl %r13d,%r12d
+ xorl %r14d,%r15d
+ addl 28(%rsp),%r12d
+
+ addl 56(%rsp),%r12d
+ movl %r10d,%r13d
+ addl %r15d,%r12d
+ movl %ecx,%r14d
+ rorl $14,%r13d
+ movl %r11d,%r15d
+
+ xorl %r10d,%r13d
+ rorl $9,%r14d
+ xorl %eax,%r15d
+
+ movl %r12d,56(%rsp)
+ xorl %ecx,%r14d
+ andl %r10d,%r15d
+
+ rorl $5,%r13d
+ addl %ebx,%r12d
+ xorl %eax,%r15d
+
+ rorl $11,%r14d
+ xorl %r10d,%r13d
+ addl %r15d,%r12d
+
+ movl %ecx,%r15d
+ addl (%rbp),%r12d
+ xorl %ecx,%r14d
+
+ xorl %edx,%r15d
+ rorl $6,%r13d
+ movl %edx,%ebx
+
+ andl %r15d,%edi
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %edi,%ebx
+ addl %r12d,%r9d
+ addl %r12d,%ebx
+
+ leaq 4(%rbp),%rbp
+ movl 0(%rsp),%r13d
+ movl 52(%rsp),%edi
+
+ movl %r13d,%r12d
+ rorl $11,%r13d
+ addl %r14d,%ebx
+ movl %edi,%r14d
+ rorl $2,%edi
+
+ xorl %r12d,%r13d
+ shrl $3,%r12d
+ rorl $7,%r13d
+ xorl %r14d,%edi
+ shrl $10,%r14d
+
+ rorl $17,%edi
+ xorl %r13d,%r12d
+ xorl %r14d,%edi
+ addl 32(%rsp),%r12d
+
+ addl 60(%rsp),%r12d
+ movl %r9d,%r13d
+ addl %edi,%r12d
+ movl %ebx,%r14d
+ rorl $14,%r13d
+ movl %r10d,%edi
+
+ xorl %r9d,%r13d
+ rorl $9,%r14d
+ xorl %r11d,%edi
+
+ movl %r12d,60(%rsp)
+ xorl %ebx,%r14d
+ andl %r9d,%edi
+
+ rorl $5,%r13d
+ addl %eax,%r12d
+ xorl %r11d,%edi
+
+ rorl $11,%r14d
+ xorl %r9d,%r13d
+ addl %edi,%r12d
+
+ movl %ebx,%edi
+ addl (%rbp),%r12d
+ xorl %ebx,%r14d
+
+ xorl %ecx,%edi
+ rorl $6,%r13d
+ movl %ecx,%eax
+
+ andl %edi,%r15d
+ rorl $2,%r14d
+ addl %r13d,%r12d
+
+ xorl %r15d,%eax
+ addl %r12d,%r8d
+ addl %r12d,%eax
+
+ leaq 20(%rbp),%rbp
+ cmpb $0,3(%rbp)
+ jnz L$rounds_16_xx
+
+ movq 64+0(%rsp),%rdi
+ addl %r14d,%eax
+ 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:
+ .byte 0xf3,0xc3
+
+.p2align 6
+
+K256:
+.long 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5
+.long 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5
+.long 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5
+.long 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5
+.long 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3
+.long 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3
+.long 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174
+.long 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174
+.long 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc
+.long 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc
+.long 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da
+.long 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da
+.long 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7
+.long 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7
+.long 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967
+.long 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967
+.long 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13
+.long 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13
+.long 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85
+.long 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85
+.long 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3
+.long 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3
+.long 0xd192e819,0xd6990624,0xf40e3585,0x106aa070
+.long 0xd192e819,0xd6990624,0xf40e3585,0x106aa070
+.long 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5
+.long 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5
+.long 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3
+.long 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3
+.long 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208
+.long 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208
+.long 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
+.long 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
+
+.long 0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f
+.long 0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f
+.long 0x03020100,0x0b0a0908,0xffffffff,0xffffffff
+.long 0x03020100,0x0b0a0908,0xffffffff,0xffffffff
+.long 0xffffffff,0xffffffff,0x03020100,0x0b0a0908
+.long 0xffffffff,0xffffffff,0x03020100,0x0b0a0908
+.byte 83,72,65,50,53,54,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
+sha256_block_data_order_ssse3:
+L$ssse3_shortcut:
+ pushq %rbx
+ pushq %rbp
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ pushq %r15
+ movq %rsp,%r11
+ shlq $4,%rdx
+ subq $96,%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_ssse3:
+
+ 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_ssse3
+.p2align 4
+L$loop_ssse3:
+ movdqa K256+512(%rip),%xmm7
+ movdqu 0(%rsi),%xmm0
+ movdqu 16(%rsi),%xmm1
+ movdqu 32(%rsi),%xmm2
+.byte 102,15,56,0,199
+ movdqu 48(%rsi),%xmm3
+ leaq K256(%rip),%rbp
+.byte 102,15,56,0,207
+ movdqa 0(%rbp),%xmm4
+ movdqa 32(%rbp),%xmm5
+.byte 102,15,56,0,215
+ paddd %xmm0,%xmm4
+ movdqa 64(%rbp),%xmm6
+.byte 102,15,56,0,223
+ movdqa 96(%rbp),%xmm7
+ paddd %xmm1,%xmm5
+ paddd %xmm2,%xmm6
+ paddd %xmm3,%xmm7
+ movdqa %xmm4,0(%rsp)
+ movl %eax,%r14d
+ movdqa %xmm5,16(%rsp)
+ movl %ebx,%edi
+ movdqa %xmm6,32(%rsp)
+ xorl %ecx,%edi
+ movdqa %xmm7,48(%rsp)
+ movl %r8d,%r13d
+ jmp L$ssse3_00_47
+
+.p2align 4
+L$ssse3_00_47:
+ subq $-128,%rbp
+ rorl $14,%r13d
+ movdqa %xmm1,%xmm4
+ movl %r14d,%eax
+ movl %r9d,%r12d
+ movdqa %xmm3,%xmm7
+ rorl $9,%r14d
+ xorl %r8d,%r13d
+ xorl %r10d,%r12d
+ rorl $5,%r13d
+ xorl %eax,%r14d
+.byte 102,15,58,15,224,4
+ andl %r8d,%r12d
+ xorl %r8d,%r13d
+.byte 102,15,58,15,250,4
+ addl 0(%rsp),%r11d
+ movl %eax,%r15d
+ xorl %r10d,%r12d
+ rorl $11,%r14d
+ movdqa %xmm4,%xmm5
+ xorl %ebx,%r15d
+ addl %r12d,%r11d
+ movdqa %xmm4,%xmm6
+ rorl $6,%r13d
+ andl %r15d,%edi
+ psrld $3,%xmm4
+ xorl %eax,%r14d
+ addl %r13d,%r11d
+ xorl %ebx,%edi
+ paddd %xmm7,%xmm0
+ rorl $2,%r14d
+ addl %r11d,%edx
+ psrld $7,%xmm6
+ addl %edi,%r11d
+ movl %edx,%r13d
+ pshufd $250,%xmm3,%xmm7
+ addl %r11d,%r14d
+ rorl $14,%r13d
+ pslld $14,%xmm5
+ movl %r14d,%r11d
+ movl %r8d,%r12d
+ pxor %xmm6,%xmm4
+ rorl $9,%r14d
+ xorl %edx,%r13d
+ xorl %r9d,%r12d
+ rorl $5,%r13d
+ psrld $11,%xmm6
+ xorl %r11d,%r14d
+ pxor %xmm5,%xmm4
+ andl %edx,%r12d
+ xorl %edx,%r13d
+ pslld $11,%xmm5
+ addl 4(%rsp),%r10d
+ movl %r11d,%edi
+ pxor %xmm6,%xmm4
+ xorl %r9d,%r12d
+ rorl $11,%r14d
+ movdqa %xmm7,%xmm6
+ xorl %eax,%edi
+ addl %r12d,%r10d
+ pxor %xmm5,%xmm4
+ rorl $6,%r13d
+ andl %edi,%r15d
+ xorl %r11d,%r14d
+ psrld $10,%xmm7
+ addl %r13d,%r10d
+ xorl %eax,%r15d
+ paddd %xmm4,%xmm0
+ rorl $2,%r14d
+ addl %r10d,%ecx
+ psrlq $17,%xmm6
+ addl %r15d,%r10d
+ movl %ecx,%r13d
+ addl %r10d,%r14d
+ pxor %xmm6,%xmm7
+ rorl $14,%r13d
+ movl %r14d,%r10d
+ movl %edx,%r12d
+ rorl $9,%r14d
+ psrlq $2,%xmm6
+ xorl %ecx,%r13d
+ xorl %r8d,%r12d
+ pxor %xmm6,%xmm7
+ rorl $5,%r13d
+ xorl %r10d,%r14d
+ andl %ecx,%r12d
+ pshufd $128,%xmm7,%xmm7
+ xorl %ecx,%r13d
+ addl 8(%rsp),%r9d
+ movl %r10d,%r15d
+ psrldq $8,%xmm7
+ xorl %r8d,%r12d
+ rorl $11,%r14d
+ xorl %r11d,%r15d
+ addl %r12d,%r9d
+ rorl $6,%r13d
+ paddd %xmm7,%xmm0
+ andl %r15d,%edi
+ xorl %r10d,%r14d
+ addl %r13d,%r9d
+ pshufd $80,%xmm0,%xmm7
+ xorl %r11d,%edi
+ rorl $2,%r14d
+ addl %r9d,%ebx
+ movdqa %xmm7,%xmm6
+ addl %edi,%r9d
+ movl %ebx,%r13d
+ psrld $10,%xmm7
+ addl %r9d,%r14d
+ rorl $14,%r13d
+ psrlq $17,%xmm6
+ movl %r14d,%r9d
+ movl %ecx,%r12d
+ pxor %xmm6,%xmm7
+ rorl $9,%r14d
+ xorl %ebx,%r13d
+ xorl %edx,%r12d
+ rorl $5,%r13d
+ xorl %r9d,%r14d
+ psrlq $2,%xmm6
+ andl %ebx,%r12d
+ xorl %ebx,%r13d
+ addl 12(%rsp),%r8d
+ pxor %xmm6,%xmm7
+ movl %r9d,%edi
+ xorl %edx,%r12d
+ rorl $11,%r14d
+ pshufd $8,%xmm7,%xmm7
+ xorl %r10d,%edi
+ addl %r12d,%r8d
+ movdqa 0(%rbp),%xmm6
+ rorl $6,%r13d
+ andl %edi,%r15d
+ pslldq $8,%xmm7
+ xorl %r9d,%r14d
+ addl %r13d,%r8d
+ xorl %r10d,%r15d
+ paddd %xmm7,%xmm0
+ rorl $2,%r14d
+ addl %r8d,%eax
+ addl %r15d,%r8d
+ paddd %xmm0,%xmm6
+ movl %eax,%r13d
+ addl %r8d,%r14d
+ movdqa %xmm6,0(%rsp)
+ rorl $14,%r13d
+ movdqa %xmm2,%xmm4
+ movl %r14d,%r8d
+ movl %ebx,%r12d
+ movdqa %xmm0,%xmm7
+ rorl $9,%r14d
+ xorl %eax,%r13d
+ xorl %ecx,%r12d
+ rorl $5,%r13d
+ xorl %r8d,%r14d
+.byte 102,15,58,15,225,4
+ andl %eax,%r12d
+ xorl %eax,%r13d
+.byte 102,15,58,15,251,4
+ addl 16(%rsp),%edx
+ movl %r8d,%r15d
+ xorl %ecx,%r12d
+ rorl $11,%r14d
+ movdqa %xmm4,%xmm5
+ xorl %r9d,%r15d
+ addl %r12d,%edx
+ movdqa %xmm4,%xmm6
+ rorl $6,%r13d
+ andl %r15d,%edi
+ psrld $3,%xmm4
+ xorl %r8d,%r14d
+ addl %r13d,%edx
+ xorl %r9d,%edi
+ paddd %xmm7,%xmm1
+ rorl $2,%r14d
+ addl %edx,%r11d
+ psrld $7,%xmm6
+ addl %edi,%edx
+ movl %r11d,%r13d
+ pshufd $250,%xmm0,%xmm7
+ addl %edx,%r14d
+ rorl $14,%r13d
+ pslld $14,%xmm5
+ movl %r14d,%edx
+ movl %eax,%r12d
+ pxor %xmm6,%xmm4
+ rorl $9,%r14d
+ xorl %r11d,%r13d
+ xorl %ebx,%r12d
+ rorl $5,%r13d
+ psrld $11,%xmm6
+ xorl %edx,%r14d
+ pxor %xmm5,%xmm4
+ andl %r11d,%r12d
+ xorl %r11d,%r13d
+ pslld $11,%xmm5
+ addl 20(%rsp),%ecx
+ movl %edx,%edi
+ pxor %xmm6,%xmm4
+ xorl %ebx,%r12d
+ rorl $11,%r14d
+ movdqa %xmm7,%xmm6
+ xorl %r8d,%edi
+ addl %r12d,%ecx
+ pxor %xmm5,%xmm4
+ rorl $6,%r13d
+ andl %edi,%r15d
+ xorl %edx,%r14d
+ psrld $10,%xmm7
+ addl %r13d,%ecx
+ xorl %r8d,%r15d
+ paddd %xmm4,%xmm1
+ rorl $2,%r14d
+ addl %ecx,%r10d
+ psrlq $17,%xmm6
+ addl %r15d,%ecx
+ movl %r10d,%r13d
+ addl %ecx,%r14d
+ pxor %xmm6,%xmm7
+ rorl $14,%r13d
+ movl %r14d,%ecx
+ movl %r11d,%r12d
+ rorl $9,%r14d
+ psrlq $2,%xmm6
+ xorl %r10d,%r13d
+ xorl %eax,%r12d
+ pxor %xmm6,%xmm7
+ rorl $5,%r13d
+ xorl %ecx,%r14d
+ andl %r10d,%r12d
+ pshufd $128,%xmm7,%xmm7
+ xorl %r10d,%r13d
+ addl 24(%rsp),%ebx
+ movl %ecx,%r15d
+ psrldq $8,%xmm7
+ xorl %eax,%r12d
+ rorl $11,%r14d
+ xorl %edx,%r15d
+ addl %r12d,%ebx
+ rorl $6,%r13d
+ paddd %xmm7,%xmm1
+ andl %r15d,%edi
+ xorl %ecx,%r14d
+ addl %r13d,%ebx
+ pshufd $80,%xmm1,%xmm7
+ xorl %edx,%edi
+ rorl $2,%r14d
+ addl %ebx,%r9d
+ movdqa %xmm7,%xmm6
+ addl %edi,%ebx
+ movl %r9d,%r13d
+ psrld $10,%xmm7
+ addl %ebx,%r14d
+ rorl $14,%r13d
+ psrlq $17,%xmm6
+ movl %r14d,%ebx
+ movl %r10d,%r12d
+ pxor %xmm6,%xmm7
+ rorl $9,%r14d
+ xorl %r9d,%r13d
+ xorl %r11d,%r12d
+ rorl $5,%r13d
+ xorl %ebx,%r14d
+ psrlq $2,%xmm6
+ andl %r9d,%r12d
+ xorl %r9d,%r13d
+ addl 28(%rsp),%eax
+ pxor %xmm6,%xmm7
+ movl %ebx,%edi
+ xorl %r11d,%r12d
+ rorl $11,%r14d
+ pshufd $8,%xmm7,%xmm7
+ xorl %ecx,%edi
+ addl %r12d,%eax
+ movdqa 32(%rbp),%xmm6
+ rorl $6,%r13d
+ andl %edi,%r15d
+ pslldq $8,%xmm7
+ xorl %ebx,%r14d
+ addl %r13d,%eax
+ xorl %ecx,%r15d
+ paddd %xmm7,%xmm1
+ rorl $2,%r14d
+ addl %eax,%r8d
+ addl %r15d,%eax
+ paddd %xmm1,%xmm6
+ movl %r8d,%r13d
+ addl %eax,%r14d
+ movdqa %xmm6,16(%rsp)
+ rorl $14,%r13d
+ movdqa %xmm3,%xmm4
+ movl %r14d,%eax
+ movl %r9d,%r12d
+ movdqa %xmm1,%xmm7
+ rorl $9,%r14d
+ xorl %r8d,%r13d
+ xorl %r10d,%r12d
+ rorl $5,%r13d
+ xorl %eax,%r14d
+.byte 102,15,58,15,226,4
+ andl %r8d,%r12d
+ xorl %r8d,%r13d
+.byte 102,15,58,15,248,4
+ addl 32(%rsp),%r11d
+ movl %eax,%r15d
+ xorl %r10d,%r12d
+ rorl $11,%r14d
+ movdqa %xmm4,%xmm5
+ xorl %ebx,%r15d
+ addl %r12d,%r11d
+ movdqa %xmm4,%xmm6
+ rorl $6,%r13d
+ andl %r15d,%edi
+ psrld $3,%xmm4
+ xorl %eax,%r14d
+ addl %r13d,%r11d
+ xorl %ebx,%edi
+ paddd %xmm7,%xmm2
+ rorl $2,%r14d
+ addl %r11d,%edx
+ psrld $7,%xmm6
+ addl %edi,%r11d
+ movl %edx,%r13d
+ pshufd $250,%xmm1,%xmm7
+ addl %r11d,%r14d
+ rorl $14,%r13d
+ pslld $14,%xmm5
+ movl %r14d,%r11d
+ movl %r8d,%r12d
+ pxor %xmm6,%xmm4
+ rorl $9,%r14d
+ xorl %edx,%r13d
+ xorl %r9d,%r12d
+ rorl $5,%r13d
+ psrld $11,%xmm6
+ xorl %r11d,%r14d
+ pxor %xmm5,%xmm4
+ andl %edx,%r12d
+ xorl %edx,%r13d
+ pslld $11,%xmm5
+ addl 36(%rsp),%r10d
+ movl %r11d,%edi
+ pxor %xmm6,%xmm4
+ xorl %r9d,%r12d
+ rorl $11,%r14d
+ movdqa %xmm7,%xmm6
+ xorl %eax,%edi
+ addl %r12d,%r10d
+ pxor %xmm5,%xmm4
+ rorl $6,%r13d
+ andl %edi,%r15d
+ xorl %r11d,%r14d
+ psrld $10,%xmm7
+ addl %r13d,%r10d
+ xorl %eax,%r15d
+ paddd %xmm4,%xmm2
+ rorl $2,%r14d
+ addl %r10d,%ecx
+ psrlq $17,%xmm6
+ addl %r15d,%r10d
+ movl %ecx,%r13d
+ addl %r10d,%r14d
+ pxor %xmm6,%xmm7
+ rorl $14,%r13d
+ movl %r14d,%r10d
+ movl %edx,%r12d
+ rorl $9,%r14d
+ psrlq $2,%xmm6
+ xorl %ecx,%r13d
+ xorl %r8d,%r12d
+ pxor %xmm6,%xmm7
+ rorl $5,%r13d
+ xorl %r10d,%r14d
+ andl %ecx,%r12d
+ pshufd $128,%xmm7,%xmm7
+ xorl %ecx,%r13d
+ addl 40(%rsp),%r9d
+ movl %r10d,%r15d
+ psrldq $8,%xmm7
+ xorl %r8d,%r12d
+ rorl $11,%r14d
+ xorl %r11d,%r15d
+ addl %r12d,%r9d
+ rorl $6,%r13d
+ paddd %xmm7,%xmm2
+ andl %r15d,%edi
+ xorl %r10d,%r14d
+ addl %r13d,%r9d
+ pshufd $80,%xmm2,%xmm7
+ xorl %r11d,%edi
+ rorl $2,%r14d
+ addl %r9d,%ebx
+ movdqa %xmm7,%xmm6
+ addl %edi,%r9d
+ movl %ebx,%r13d
+ psrld $10,%xmm7
+ addl %r9d,%r14d
+ rorl $14,%r13d
+ psrlq $17,%xmm6
+ movl %r14d,%r9d
+ movl %ecx,%r12d
+ pxor %xmm6,%xmm7
+ rorl $9,%r14d
+ xorl %ebx,%r13d
+ xorl %edx,%r12d
+ rorl $5,%r13d
+ xorl %r9d,%r14d
+ psrlq $2,%xmm6
+ andl %ebx,%r12d
+ xorl %ebx,%r13d
+ addl 44(%rsp),%r8d
+ pxor %xmm6,%xmm7
+ movl %r9d,%edi
+ xorl %edx,%r12d
+ rorl $11,%r14d
+ pshufd $8,%xmm7,%xmm7
+ xorl %r10d,%edi
+ addl %r12d,%r8d
+ movdqa 64(%rbp),%xmm6
+ rorl $6,%r13d
+ andl %edi,%r15d
+ pslldq $8,%xmm7
+ xorl %r9d,%r14d
+ addl %r13d,%r8d
+ xorl %r10d,%r15d
+ paddd %xmm7,%xmm2
+ rorl $2,%r14d
+ addl %r8d,%eax
+ addl %r15d,%r8d
+ paddd %xmm2,%xmm6
+ movl %eax,%r13d
+ addl %r8d,%r14d
+ movdqa %xmm6,32(%rsp)
+ rorl $14,%r13d
+ movdqa %xmm0,%xmm4
+ movl %r14d,%r8d
+ movl %ebx,%r12d
+ movdqa %xmm2,%xmm7
+ rorl $9,%r14d
+ xorl %eax,%r13d
+ xorl %ecx,%r12d
+ rorl $5,%r13d
+ xorl %r8d,%r14d
+.byte 102,15,58,15,227,4
+ andl %eax,%r12d
+ xorl %eax,%r13d
+.byte 102,15,58,15,249,4
+ addl 48(%rsp),%edx
+ movl %r8d,%r15d
+ xorl %ecx,%r12d
+ rorl $11,%r14d
+ movdqa %xmm4,%xmm5
+ xorl %r9d,%r15d
+ addl %r12d,%edx
+ movdqa %xmm4,%xmm6
+ rorl $6,%r13d
+ andl %r15d,%edi
+ psrld $3,%xmm4
+ xorl %r8d,%r14d
+ addl %r13d,%edx
+ xorl %r9d,%edi
+ paddd %xmm7,%xmm3
+ rorl $2,%r14d
+ addl %edx,%r11d
+ psrld $7,%xmm6
+ addl %edi,%edx
+ movl %r11d,%r13d
+ pshufd $250,%xmm2,%xmm7
+ addl %edx,%r14d
+ rorl $14,%r13d
+ pslld $14,%xmm5
+ movl %r14d,%edx
+ movl %eax,%r12d
+ pxor %xmm6,%xmm4
+ rorl $9,%r14d
+ xorl %r11d,%r13d
+ xorl %ebx,%r12d
+ rorl $5,%r13d
+ psrld $11,%xmm6
+ xorl %edx,%r14d
+ pxor %xmm5,%xmm4
+ andl %r11d,%r12d
+ xorl %r11d,%r13d
+ pslld $11,%xmm5
+ addl 52(%rsp),%ecx
+ movl %edx,%edi
+ pxor %xmm6,%xmm4
+ xorl %ebx,%r12d
+ rorl $11,%r14d
+ movdqa %xmm7,%xmm6
+ xorl %r8d,%edi
+ addl %r12d,%ecx
+ pxor %xmm5,%xmm4
+ rorl $6,%r13d
+ andl %edi,%r15d
+ xorl %edx,%r14d
+ psrld $10,%xmm7
+ addl %r13d,%ecx
+ xorl %r8d,%r15d
+ paddd %xmm4,%xmm3
+ rorl $2,%r14d
+ addl %ecx,%r10d
+ psrlq $17,%xmm6
+ addl %r15d,%ecx
+ movl %r10d,%r13d
+ addl %ecx,%r14d
+ pxor %xmm6,%xmm7
+ rorl $14,%r13d
+ movl %r14d,%ecx
+ movl %r11d,%r12d
+ rorl $9,%r14d
+ psrlq $2,%xmm6
+ xorl %r10d,%r13d
+ xorl %eax,%r12d
+ pxor %xmm6,%xmm7
+ rorl $5,%r13d
+ xorl %ecx,%r14d
+ andl %r10d,%r12d
+ pshufd $128,%xmm7,%xmm7
+ xorl %r10d,%r13d
+ addl 56(%rsp),%ebx
+ movl %ecx,%r15d
+ psrldq $8,%xmm7
+ xorl %eax,%r12d
+ rorl $11,%r14d
+ xorl %edx,%r15d
+ addl %r12d,%ebx
+ rorl $6,%r13d
+ paddd %xmm7,%xmm3
+ andl %r15d,%edi
+ xorl %ecx,%r14d
+ addl %r13d,%ebx
+ pshufd $80,%xmm3,%xmm7
+ xorl %edx,%edi
+ rorl $2,%r14d
+ addl %ebx,%r9d
+ movdqa %xmm7,%xmm6
+ addl %edi,%ebx
+ movl %r9d,%r13d
+ psrld $10,%xmm7
+ addl %ebx,%r14d
+ rorl $14,%r13d
+ psrlq $17,%xmm6
+ movl %r14d,%ebx
+ movl %r10d,%r12d
+ pxor %xmm6,%xmm7
+ rorl $9,%r14d
+ xorl %r9d,%r13d
+ xorl %r11d,%r12d
+ rorl $5,%r13d
+ xorl %ebx,%r14d
+ psrlq $2,%xmm6
+ andl %r9d,%r12d
+ xorl %r9d,%r13d
+ addl 60(%rsp),%eax
+ pxor %xmm6,%xmm7
+ movl %ebx,%edi
+ xorl %r11d,%r12d
+ rorl $11,%r14d
+ pshufd $8,%xmm7,%xmm7
+ xorl %ecx,%edi
+ addl %r12d,%eax
+ movdqa 96(%rbp),%xmm6
+ rorl $6,%r13d
+ andl %edi,%r15d
+ pslldq $8,%xmm7
+ xorl %ebx,%r14d
+ addl %r13d,%eax
+ xorl %ecx,%r15d
+ paddd %xmm7,%xmm3
+ rorl $2,%r14d
+ addl %eax,%r8d
+ addl %r15d,%eax
+ paddd %xmm3,%xmm6
+ movl %r8d,%r13d
+ addl %eax,%r14d
+ movdqa %xmm6,48(%rsp)
+ cmpb $0,131(%rbp)
+ jne L$ssse3_00_47
+ rorl $14,%r13d
+ movl %r14d,%eax
+ movl %r9d,%r12d
+ rorl $9,%r14d
+ xorl %r8d,%r13d
+ xorl %r10d,%r12d
+ rorl $5,%r13d
+ xorl %eax,%r14d
+ andl %r8d,%r12d
+ xorl %r8d,%r13d
+ addl 0(%rsp),%r11d
+ movl %eax,%r15d
+ xorl %r10d,%r12d
+ rorl $11,%r14d
+ xorl %ebx,%r15d
+ addl %r12d,%r11d
+ rorl $6,%r13d
+ andl %r15d,%edi
+ xorl %eax,%r14d
+ addl %r13d,%r11d
+ xorl %ebx,%edi
+ rorl $2,%r14d
+ addl %r11d,%edx
+ addl %edi,%r11d
+ movl %edx,%r13d
+ addl %r11d,%r14d
+ rorl $14,%r13d
+ movl %r14d,%r11d
+ movl %r8d,%r12d
+ rorl $9,%r14d
+ xorl %edx,%r13d
+ xorl %r9d,%r12d
+ rorl $5,%r13d
+ xorl %r11d,%r14d
+ andl %edx,%r12d
+ xorl %edx,%r13d
+ addl 4(%rsp),%r10d
+ movl %r11d,%edi
+ xorl %r9d,%r12d
+ rorl $11,%r14d
+ xorl %eax,%edi
+ addl %r12d,%r10d
+ rorl $6,%r13d
+ andl %edi,%r15d
+ xorl %r11d,%r14d
+ addl %r13d,%r10d
+ xorl %eax,%r15d
+ rorl $2,%r14d
+ addl %r10d,%ecx
+ addl %r15d,%r10d
+ movl %ecx,%r13d
+ addl %r10d,%r14d
+ rorl $14,%r13d
+ movl %r14d,%r10d
+ movl %edx,%r12d
+ rorl $9,%r14d
+ xorl %ecx,%r13d
+ xorl %r8d,%r12d
+ rorl $5,%r13d
+ xorl %r10d,%r14d
+ andl %ecx,%r12d
+ xorl %ecx,%r13d
+ addl 8(%rsp),%r9d
+ movl %r10d,%r15d
+ xorl %r8d,%r12d
+ rorl $11,%r14d
+ xorl %r11d,%r15d
+ addl %r12d,%r9d
+ rorl $6,%r13d
+ andl %r15d,%edi
+ xorl %r10d,%r14d
+ addl %r13d,%r9d
+ xorl %r11d,%edi
+ rorl $2,%r14d
+ addl %r9d,%ebx
+ addl %edi,%r9d
+ movl %ebx,%r13d
+ addl %r9d,%r14d
+ rorl $14,%r13d
+ movl %r14d,%r9d
+ movl %ecx,%r12d
+ rorl $9,%r14d
+ xorl %ebx,%r13d
+ xorl %edx,%r12d
+ rorl $5,%r13d
+ xorl %r9d,%r14d
+ andl %ebx,%r12d
+ xorl %ebx,%r13d
+ addl 12(%rsp),%r8d
+ movl %r9d,%edi
+ xorl %edx,%r12d
+ rorl $11,%r14d
+ xorl %r10d,%edi
+ addl %r12d,%r8d
+ rorl $6,%r13d
+ andl %edi,%r15d
+ xorl %r9d,%r14d
+ addl %r13d,%r8d
+ xorl %r10d,%r15d
+ rorl $2,%r14d
+ addl %r8d,%eax
+ addl %r15d,%r8d
+ movl %eax,%r13d
+ addl %r8d,%r14d
+ rorl $14,%r13d
+ movl %r14d,%r8d
+ movl %ebx,%r12d
+ rorl $9,%r14d
+ xorl %eax,%r13d
+ xorl %ecx,%r12d
+ rorl $5,%r13d
+ xorl %r8d,%r14d
+ andl %eax,%r12d
+ xorl %eax,%r13d
+ addl 16(%rsp),%edx
+ movl %r8d,%r15d
+ xorl %ecx,%r12d
+ rorl $11,%r14d
+ xorl %r9d,%r15d
+ addl %r12d,%edx
+ rorl $6,%r13d
+ andl %r15d,%edi
+ xorl %r8d,%r14d
+ addl %r13d,%edx
+ xorl %r9d,%edi
+ rorl $2,%r14d
+ addl %edx,%r11d
+ addl %edi,%edx
+ movl %r11d,%r13d
+ addl %edx,%r14d
+ rorl $14,%r13d
+ movl %r14d,%edx
+ movl %eax,%r12d
+ rorl $9,%r14d
+ xorl %r11d,%r13d
+ xorl %ebx,%r12d
+ rorl $5,%r13d
+ xorl %edx,%r14d
+ andl %r11d,%r12d
+ xorl %r11d,%r13d
+ addl 20(%rsp),%ecx
+ movl %edx,%edi
+ xorl %ebx,%r12d
+ rorl $11,%r14d
+ xorl %r8d,%edi
+ addl %r12d,%ecx
+ rorl $6,%r13d
+ andl %edi,%r15d
+ xorl %edx,%r14d
+ addl %r13d,%ecx
+ xorl %r8d,%r15d
+ rorl $2,%r14d
+ addl %ecx,%r10d
+ addl %r15d,%ecx
+ movl %r10d,%r13d
+ addl %ecx,%r14d
+ rorl $14,%r13d
+ movl %r14d,%ecx
+ movl %r11d,%r12d
+ rorl $9,%r14d
+ xorl %r10d,%r13d
+ xorl %eax,%r12d
+ rorl $5,%r13d
+ xorl %ecx,%r14d
+ andl %r10d,%r12d
+ xorl %r10d,%r13d
+ addl 24(%rsp),%ebx
+ movl %ecx,%r15d
+ xorl %eax,%r12d
+ rorl $11,%r14d
+ xorl %edx,%r15d
+ addl %r12d,%ebx
+ rorl $6,%r13d
+ andl %r15d,%edi
+ xorl %ecx,%r14d
+ addl %r13d,%ebx
+ xorl %edx,%edi
+ rorl $2,%r14d
+ addl %ebx,%r9d
+ addl %edi,%ebx
+ movl %r9d,%r13d
+ addl %ebx,%r14d
+ rorl $14,%r13d
+ movl %r14d,%ebx
+ movl %r10d,%r12d
+ rorl $9,%r14d
+ xorl %r9d,%r13d
+ xorl %r11d,%r12d
+ rorl $5,%r13d
+ xorl %ebx,%r14d
+ andl %r9d,%r12d
+ xorl %r9d,%r13d
+ addl 28(%rsp),%eax
+ movl %ebx,%edi
+ xorl %r11d,%r12d
+ rorl $11,%r14d
+ xorl %ecx,%edi
+ addl %r12d,%eax
+ rorl $6,%r13d
+ andl %edi,%r15d
+ xorl %ebx,%r14d
+ addl %r13d,%eax
+ xorl %ecx,%r15d
+ rorl $2,%r14d
+ addl %eax,%r8d
+ addl %r15d,%eax
+ movl %r8d,%r13d
+ addl %eax,%r14d
+ rorl $14,%r13d
+ movl %r14d,%eax
+ movl %r9d,%r12d
+ rorl $9,%r14d
+ xorl %r8d,%r13d
+ xorl %r10d,%r12d
+ rorl $5,%r13d
+ xorl %eax,%r14d
+ andl %r8d,%r12d
+ xorl %r8d,%r13d
+ addl 32(%rsp),%r11d
+ movl %eax,%r15d
+ xorl %r10d,%r12d
+ rorl $11,%r14d
+ xorl %ebx,%r15d
+ addl %r12d,%r11d
+ rorl $6,%r13d
+ andl %r15d,%edi
+ xorl %eax,%r14d
+ addl %r13d,%r11d
+ xorl %ebx,%edi
+ rorl $2,%r14d
+ addl %r11d,%edx
+ addl %edi,%r11d
+ movl %edx,%r13d
+ addl %r11d,%r14d
+ rorl $14,%r13d
+ movl %r14d,%r11d
+ movl %r8d,%r12d
+ rorl $9,%r14d
+ xorl %edx,%r13d
+ xorl %r9d,%r12d
+ rorl $5,%r13d
+ xorl %r11d,%r14d
+ andl %edx,%r12d
+ xorl %edx,%r13d
+ addl 36(%rsp),%r10d
+ movl %r11d,%edi
+ xorl %r9d,%r12d
+ rorl $11,%r14d
+ xorl %eax,%edi
+ addl %r12d,%r10d
+ rorl $6,%r13d
+ andl %edi,%r15d
+ xorl %r11d,%r14d
+ addl %r13d,%r10d
+ xorl %eax,%r15d
+ rorl $2,%r14d
+ addl %r10d,%ecx
+ addl %r15d,%r10d
+ movl %ecx,%r13d
+ addl %r10d,%r14d
+ rorl $14,%r13d
+ movl %r14d,%r10d
+ movl %edx,%r12d
+ rorl $9,%r14d
+ xorl %ecx,%r13d
+ xorl %r8d,%r12d
+ rorl $5,%r13d
+ xorl %r10d,%r14d
+ andl %ecx,%r12d
+ xorl %ecx,%r13d
+ addl 40(%rsp),%r9d
+ movl %r10d,%r15d
+ xorl %r8d,%r12d
+ rorl $11,%r14d
+ xorl %r11d,%r15d
+ addl %r12d,%r9d
+ rorl $6,%r13d
+ andl %r15d,%edi
+ xorl %r10d,%r14d
+ addl %r13d,%r9d
+ xorl %r11d,%edi
+ rorl $2,%r14d
+ addl %r9d,%ebx
+ addl %edi,%r9d
+ movl %ebx,%r13d
+ addl %r9d,%r14d
+ rorl $14,%r13d
+ movl %r14d,%r9d
+ movl %ecx,%r12d
+ rorl $9,%r14d
+ xorl %ebx,%r13d
+ xorl %edx,%r12d
+ rorl $5,%r13d
+ xorl %r9d,%r14d
+ andl %ebx,%r12d
+ xorl %ebx,%r13d
+ addl 44(%rsp),%r8d
+ movl %r9d,%edi
+ xorl %edx,%r12d
+ rorl $11,%r14d
+ xorl %r10d,%edi
+ addl %r12d,%r8d
+ rorl $6,%r13d
+ andl %edi,%r15d
+ xorl %r9d,%r14d
+ addl %r13d,%r8d
+ xorl %r10d,%r15d
+ rorl $2,%r14d
+ addl %r8d,%eax
+ addl %r15d,%r8d
+ movl %eax,%r13d
+ addl %r8d,%r14d
+ rorl $14,%r13d
+ movl %r14d,%r8d
+ movl %ebx,%r12d
+ rorl $9,%r14d
+ xorl %eax,%r13d
+ xorl %ecx,%r12d
+ rorl $5,%r13d
+ xorl %r8d,%r14d
+ andl %eax,%r12d
+ xorl %eax,%r13d
+ addl 48(%rsp),%edx
+ movl %r8d,%r15d
+ xorl %ecx,%r12d
+ rorl $11,%r14d
+ xorl %r9d,%r15d
+ addl %r12d,%edx
+ rorl $6,%r13d
+ andl %r15d,%edi
+ xorl %r8d,%r14d
+ addl %r13d,%edx
+ xorl %r9d,%edi
+ rorl $2,%r14d
+ addl %edx,%r11d
+ addl %edi,%edx
+ movl %r11d,%r13d
+ addl %edx,%r14d
+ rorl $14,%r13d
+ movl %r14d,%edx
+ movl %eax,%r12d
+ rorl $9,%r14d
+ xorl %r11d,%r13d
+ xorl %ebx,%r12d
+ rorl $5,%r13d
+ xorl %edx,%r14d
+ andl %r11d,%r12d
+ xorl %r11d,%r13d
+ addl 52(%rsp),%ecx
+ movl %edx,%edi
+ xorl %ebx,%r12d
+ rorl $11,%r14d
+ xorl %r8d,%edi
+ addl %r12d,%ecx
+ rorl $6,%r13d
+ andl %edi,%r15d
+ xorl %edx,%r14d
+ addl %r13d,%ecx
+ xorl %r8d,%r15d
+ rorl $2,%r14d
+ addl %ecx,%r10d
+ addl %r15d,%ecx
+ movl %r10d,%r13d
+ addl %ecx,%r14d
+ rorl $14,%r13d
+ movl %r14d,%ecx
+ movl %r11d,%r12d
+ rorl $9,%r14d
+ xorl %r10d,%r13d
+ xorl %eax,%r12d
+ rorl $5,%r13d
+ xorl %ecx,%r14d
+ andl %r10d,%r12d
+ xorl %r10d,%r13d
+ addl 56(%rsp),%ebx
+ movl %ecx,%r15d
+ xorl %eax,%r12d
+ rorl $11,%r14d
+ xorl %edx,%r15d
+ addl %r12d,%ebx
+ rorl $6,%r13d
+ andl %r15d,%edi
+ xorl %ecx,%r14d
+ addl %r13d,%ebx
+ xorl %edx,%edi
+ rorl $2,%r14d
+ addl %ebx,%r9d
+ addl %edi,%ebx
+ movl %r9d,%r13d
+ addl %ebx,%r14d
+ rorl $14,%r13d
+ movl %r14d,%ebx
+ movl %r10d,%r12d
+ rorl $9,%r14d
+ xorl %r9d,%r13d
+ xorl %r11d,%r12d
+ rorl $5,%r13d
+ xorl %ebx,%r14d
+ andl %r9d,%r12d
+ xorl %r9d,%r13d
+ addl 60(%rsp),%eax
+ movl %ebx,%edi
+ xorl %r11d,%r12d
+ rorl $11,%r14d
+ xorl %ecx,%edi
+ addl %r12d,%eax
+ rorl $6,%r13d
+ andl %edi,%r15d
+ xorl %ebx,%r14d
+ addl %r13d,%eax
+ xorl %ecx,%r15d
+ rorl $2,%r14d
+ addl %eax,%r8d
+ addl %r15d,%eax
+ movl %r8d,%r13d
+ addl %eax,%r14d
+ movq 64+0(%rsp),%rdi
+ movl %r14d,%eax
+
+ addl 0(%rdi),%eax
+ leaq 64(%rsi),%rsi
+ 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_ssse3
+
+ 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_ssse3:
+ .byte 0xf3,0xc3
+
+#endif
diff --git a/mac-x86_64/crypto/sha/sha512-x86_64.S b/mac-x86_64/crypto/sha/sha512-x86_64.S
new file mode 100644
index 0000000..2f5d912
--- /dev/null
+++ b/mac-x86_64/crypto/sha/sha512-x86_64.S
@@ -0,0 +1,1786 @@
+#if defined(__x86_64__)
+.text
+
+
+.globl _sha512_block_data_order
+.private_extern _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:
+
+ 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:
+ movq %rbx,%rdi
+ leaq K512(%rip),%rbp
+ xorq %rcx,%rdi
+ movq 0(%rsi),%r12
+ movq %r8,%r13
+ movq %rax,%r14
+ bswapq %r12
+ rorq $23,%r13
+ movq %r9,%r15
+
+ xorq %r8,%r13
+ rorq $5,%r14
+ xorq %r10,%r15
+
+ movq %r12,0(%rsp)
+ xorq %rax,%r14
+ andq %r8,%r15
+
+ rorq $4,%r13
+ addq %r11,%r12
+ xorq %r10,%r15
+
+ rorq $6,%r14
+ xorq %r8,%r13
+ addq %r15,%r12
+
+ movq %rax,%r15
+ addq (%rbp),%r12
+ xorq %rax,%r14
+
+ xorq %rbx,%r15
+ rorq $14,%r13
+ movq %rbx,%r11
+
+ andq %r15,%rdi
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %rdi,%r11
+ addq %r12,%rdx
+ addq %r12,%r11
+
+ leaq 8(%rbp),%rbp
+ addq %r14,%r11
+ movq 8(%rsi),%r12
+ movq %rdx,%r13
+ movq %r11,%r14
+ bswapq %r12
+ rorq $23,%r13
+ movq %r8,%rdi
+
+ xorq %rdx,%r13
+ rorq $5,%r14
+ xorq %r9,%rdi
+
+ movq %r12,8(%rsp)
+ xorq %r11,%r14
+ andq %rdx,%rdi
+
+ rorq $4,%r13
+ addq %r10,%r12
+ xorq %r9,%rdi
+
+ rorq $6,%r14
+ xorq %rdx,%r13
+ addq %rdi,%r12
+
+ movq %r11,%rdi
+ addq (%rbp),%r12
+ xorq %r11,%r14
+
+ xorq %rax,%rdi
+ rorq $14,%r13
+ movq %rax,%r10
+
+ andq %rdi,%r15
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %r15,%r10
+ addq %r12,%rcx
+ addq %r12,%r10
+
+ leaq 24(%rbp),%rbp
+ addq %r14,%r10
+ movq 16(%rsi),%r12
+ movq %rcx,%r13
+ movq %r10,%r14
+ bswapq %r12
+ rorq $23,%r13
+ movq %rdx,%r15
+
+ xorq %rcx,%r13
+ rorq $5,%r14
+ xorq %r8,%r15
+
+ movq %r12,16(%rsp)
+ xorq %r10,%r14
+ andq %rcx,%r15
+
+ rorq $4,%r13
+ addq %r9,%r12
+ xorq %r8,%r15
+
+ rorq $6,%r14
+ xorq %rcx,%r13
+ addq %r15,%r12
+
+ movq %r10,%r15
+ addq (%rbp),%r12
+ xorq %r10,%r14
+
+ xorq %r11,%r15
+ rorq $14,%r13
+ movq %r11,%r9
+
+ andq %r15,%rdi
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %rdi,%r9
+ addq %r12,%rbx
+ addq %r12,%r9
+
+ leaq 8(%rbp),%rbp
+ addq %r14,%r9
+ movq 24(%rsi),%r12
+ movq %rbx,%r13
+ movq %r9,%r14
+ bswapq %r12
+ rorq $23,%r13
+ movq %rcx,%rdi
+
+ xorq %rbx,%r13
+ rorq $5,%r14
+ xorq %rdx,%rdi
+
+ movq %r12,24(%rsp)
+ xorq %r9,%r14
+ andq %rbx,%rdi
+
+ rorq $4,%r13
+ addq %r8,%r12
+ xorq %rdx,%rdi
+
+ rorq $6,%r14
+ xorq %rbx,%r13
+ addq %rdi,%r12
+
+ movq %r9,%rdi
+ addq (%rbp),%r12
+ xorq %r9,%r14
+
+ xorq %r10,%rdi
+ rorq $14,%r13
+ movq %r10,%r8
+
+ andq %rdi,%r15
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %r15,%r8
+ addq %r12,%rax
+ addq %r12,%r8
+
+ leaq 24(%rbp),%rbp
+ addq %r14,%r8
+ movq 32(%rsi),%r12
+ movq %rax,%r13
+ movq %r8,%r14
+ bswapq %r12
+ rorq $23,%r13
+ movq %rbx,%r15
+
+ xorq %rax,%r13
+ rorq $5,%r14
+ xorq %rcx,%r15
+
+ movq %r12,32(%rsp)
+ xorq %r8,%r14
+ andq %rax,%r15
+
+ rorq $4,%r13
+ addq %rdx,%r12
+ xorq %rcx,%r15
+
+ rorq $6,%r14
+ xorq %rax,%r13
+ addq %r15,%r12
+
+ movq %r8,%r15
+ addq (%rbp),%r12
+ xorq %r8,%r14
+
+ xorq %r9,%r15
+ rorq $14,%r13
+ movq %r9,%rdx
+
+ andq %r15,%rdi
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %rdi,%rdx
+ addq %r12,%r11
+ addq %r12,%rdx
+
+ leaq 8(%rbp),%rbp
+ addq %r14,%rdx
+ movq 40(%rsi),%r12
+ movq %r11,%r13
+ movq %rdx,%r14
+ bswapq %r12
+ rorq $23,%r13
+ movq %rax,%rdi
+
+ xorq %r11,%r13
+ rorq $5,%r14
+ xorq %rbx,%rdi
+
+ movq %r12,40(%rsp)
+ xorq %rdx,%r14
+ andq %r11,%rdi
+
+ rorq $4,%r13
+ addq %rcx,%r12
+ xorq %rbx,%rdi
+
+ rorq $6,%r14
+ xorq %r11,%r13
+ addq %rdi,%r12
+
+ movq %rdx,%rdi
+ addq (%rbp),%r12
+ xorq %rdx,%r14
+
+ xorq %r8,%rdi
+ rorq $14,%r13
+ movq %r8,%rcx
+
+ andq %rdi,%r15
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %r15,%rcx
+ addq %r12,%r10
+ addq %r12,%rcx
+
+ leaq 24(%rbp),%rbp
+ addq %r14,%rcx
+ movq 48(%rsi),%r12
+ movq %r10,%r13
+ movq %rcx,%r14
+ bswapq %r12
+ rorq $23,%r13
+ movq %r11,%r15
+
+ xorq %r10,%r13
+ rorq $5,%r14
+ xorq %rax,%r15
+
+ movq %r12,48(%rsp)
+ xorq %rcx,%r14
+ andq %r10,%r15
+
+ rorq $4,%r13
+ addq %rbx,%r12
+ xorq %rax,%r15
+
+ rorq $6,%r14
+ xorq %r10,%r13
+ addq %r15,%r12
+
+ movq %rcx,%r15
+ addq (%rbp),%r12
+ xorq %rcx,%r14
+
+ xorq %rdx,%r15
+ rorq $14,%r13
+ movq %rdx,%rbx
+
+ andq %r15,%rdi
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %rdi,%rbx
+ addq %r12,%r9
+ addq %r12,%rbx
+
+ leaq 8(%rbp),%rbp
+ addq %r14,%rbx
+ movq 56(%rsi),%r12
+ movq %r9,%r13
+ movq %rbx,%r14
+ bswapq %r12
+ rorq $23,%r13
+ movq %r10,%rdi
+
+ xorq %r9,%r13
+ rorq $5,%r14
+ xorq %r11,%rdi
+
+ movq %r12,56(%rsp)
+ xorq %rbx,%r14
+ andq %r9,%rdi
+
+ rorq $4,%r13
+ addq %rax,%r12
+ xorq %r11,%rdi
+
+ rorq $6,%r14
+ xorq %r9,%r13
+ addq %rdi,%r12
+
+ movq %rbx,%rdi
+ addq (%rbp),%r12
+ xorq %rbx,%r14
+
+ xorq %rcx,%rdi
+ rorq $14,%r13
+ movq %rcx,%rax
+
+ andq %rdi,%r15
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %r15,%rax
+ addq %r12,%r8
+ addq %r12,%rax
+
+ leaq 24(%rbp),%rbp
+ addq %r14,%rax
+ movq 64(%rsi),%r12
+ movq %r8,%r13
+ movq %rax,%r14
+ bswapq %r12
+ rorq $23,%r13
+ movq %r9,%r15
+
+ xorq %r8,%r13
+ rorq $5,%r14
+ xorq %r10,%r15
+
+ movq %r12,64(%rsp)
+ xorq %rax,%r14
+ andq %r8,%r15
+
+ rorq $4,%r13
+ addq %r11,%r12
+ xorq %r10,%r15
+
+ rorq $6,%r14
+ xorq %r8,%r13
+ addq %r15,%r12
+
+ movq %rax,%r15
+ addq (%rbp),%r12
+ xorq %rax,%r14
+
+ xorq %rbx,%r15
+ rorq $14,%r13
+ movq %rbx,%r11
+
+ andq %r15,%rdi
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %rdi,%r11
+ addq %r12,%rdx
+ addq %r12,%r11
+
+ leaq 8(%rbp),%rbp
+ addq %r14,%r11
+ movq 72(%rsi),%r12
+ movq %rdx,%r13
+ movq %r11,%r14
+ bswapq %r12
+ rorq $23,%r13
+ movq %r8,%rdi
+
+ xorq %rdx,%r13
+ rorq $5,%r14
+ xorq %r9,%rdi
+
+ movq %r12,72(%rsp)
+ xorq %r11,%r14
+ andq %rdx,%rdi
+
+ rorq $4,%r13
+ addq %r10,%r12
+ xorq %r9,%rdi
+
+ rorq $6,%r14
+ xorq %rdx,%r13
+ addq %rdi,%r12
+
+ movq %r11,%rdi
+ addq (%rbp),%r12
+ xorq %r11,%r14
+
+ xorq %rax,%rdi
+ rorq $14,%r13
+ movq %rax,%r10
+
+ andq %rdi,%r15
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %r15,%r10
+ addq %r12,%rcx
+ addq %r12,%r10
+
+ leaq 24(%rbp),%rbp
+ addq %r14,%r10
+ movq 80(%rsi),%r12
+ movq %rcx,%r13
+ movq %r10,%r14
+ bswapq %r12
+ rorq $23,%r13
+ movq %rdx,%r15
+
+ xorq %rcx,%r13
+ rorq $5,%r14
+ xorq %r8,%r15
+
+ movq %r12,80(%rsp)
+ xorq %r10,%r14
+ andq %rcx,%r15
+
+ rorq $4,%r13
+ addq %r9,%r12
+ xorq %r8,%r15
+
+ rorq $6,%r14
+ xorq %rcx,%r13
+ addq %r15,%r12
+
+ movq %r10,%r15
+ addq (%rbp),%r12
+ xorq %r10,%r14
+
+ xorq %r11,%r15
+ rorq $14,%r13
+ movq %r11,%r9
+
+ andq %r15,%rdi
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %rdi,%r9
+ addq %r12,%rbx
+ addq %r12,%r9
+
+ leaq 8(%rbp),%rbp
+ addq %r14,%r9
+ movq 88(%rsi),%r12
+ movq %rbx,%r13
+ movq %r9,%r14
+ bswapq %r12
+ rorq $23,%r13
+ movq %rcx,%rdi
+
+ xorq %rbx,%r13
+ rorq $5,%r14
+ xorq %rdx,%rdi
+
+ movq %r12,88(%rsp)
+ xorq %r9,%r14
+ andq %rbx,%rdi
+
+ rorq $4,%r13
+ addq %r8,%r12
+ xorq %rdx,%rdi
+
+ rorq $6,%r14
+ xorq %rbx,%r13
+ addq %rdi,%r12
+
+ movq %r9,%rdi
+ addq (%rbp),%r12
+ xorq %r9,%r14
+
+ xorq %r10,%rdi
+ rorq $14,%r13
+ movq %r10,%r8
+
+ andq %rdi,%r15
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %r15,%r8
+ addq %r12,%rax
+ addq %r12,%r8
+
+ leaq 24(%rbp),%rbp
+ addq %r14,%r8
+ movq 96(%rsi),%r12
+ movq %rax,%r13
+ movq %r8,%r14
+ bswapq %r12
+ rorq $23,%r13
+ movq %rbx,%r15
+
+ xorq %rax,%r13
+ rorq $5,%r14
+ xorq %rcx,%r15
+
+ movq %r12,96(%rsp)
+ xorq %r8,%r14
+ andq %rax,%r15
+
+ rorq $4,%r13
+ addq %rdx,%r12
+ xorq %rcx,%r15
+
+ rorq $6,%r14
+ xorq %rax,%r13
+ addq %r15,%r12
+
+ movq %r8,%r15
+ addq (%rbp),%r12
+ xorq %r8,%r14
+
+ xorq %r9,%r15
+ rorq $14,%r13
+ movq %r9,%rdx
+
+ andq %r15,%rdi
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %rdi,%rdx
+ addq %r12,%r11
+ addq %r12,%rdx
+
+ leaq 8(%rbp),%rbp
+ addq %r14,%rdx
+ movq 104(%rsi),%r12
+ movq %r11,%r13
+ movq %rdx,%r14
+ bswapq %r12
+ rorq $23,%r13
+ movq %rax,%rdi
+
+ xorq %r11,%r13
+ rorq $5,%r14
+ xorq %rbx,%rdi
+
+ movq %r12,104(%rsp)
+ xorq %rdx,%r14
+ andq %r11,%rdi
+
+ rorq $4,%r13
+ addq %rcx,%r12
+ xorq %rbx,%rdi
+
+ rorq $6,%r14
+ xorq %r11,%r13
+ addq %rdi,%r12
+
+ movq %rdx,%rdi
+ addq (%rbp),%r12
+ xorq %rdx,%r14
+
+ xorq %r8,%rdi
+ rorq $14,%r13
+ movq %r8,%rcx
+
+ andq %rdi,%r15
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %r15,%rcx
+ addq %r12,%r10
+ addq %r12,%rcx
+
+ leaq 24(%rbp),%rbp
+ addq %r14,%rcx
+ movq 112(%rsi),%r12
+ movq %r10,%r13
+ movq %rcx,%r14
+ bswapq %r12
+ rorq $23,%r13
+ movq %r11,%r15
+
+ xorq %r10,%r13
+ rorq $5,%r14
+ xorq %rax,%r15
+
+ movq %r12,112(%rsp)
+ xorq %rcx,%r14
+ andq %r10,%r15
+
+ rorq $4,%r13
+ addq %rbx,%r12
+ xorq %rax,%r15
+
+ rorq $6,%r14
+ xorq %r10,%r13
+ addq %r15,%r12
+
+ movq %rcx,%r15
+ addq (%rbp),%r12
+ xorq %rcx,%r14
+
+ xorq %rdx,%r15
+ rorq $14,%r13
+ movq %rdx,%rbx
+
+ andq %r15,%rdi
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %rdi,%rbx
+ addq %r12,%r9
+ addq %r12,%rbx
+
+ leaq 8(%rbp),%rbp
+ addq %r14,%rbx
+ movq 120(%rsi),%r12
+ movq %r9,%r13
+ movq %rbx,%r14
+ bswapq %r12
+ rorq $23,%r13
+ movq %r10,%rdi
+
+ xorq %r9,%r13
+ rorq $5,%r14
+ xorq %r11,%rdi
+
+ movq %r12,120(%rsp)
+ xorq %rbx,%r14
+ andq %r9,%rdi
+
+ rorq $4,%r13
+ addq %rax,%r12
+ xorq %r11,%rdi
+
+ rorq $6,%r14
+ xorq %r9,%r13
+ addq %rdi,%r12
+
+ movq %rbx,%rdi
+ addq (%rbp),%r12
+ xorq %rbx,%r14
+
+ xorq %rcx,%rdi
+ rorq $14,%r13
+ movq %rcx,%rax
+
+ andq %rdi,%r15
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %r15,%rax
+ addq %r12,%r8
+ addq %r12,%rax
+
+ leaq 24(%rbp),%rbp
+ jmp L$rounds_16_xx
+.p2align 4
+L$rounds_16_xx:
+ movq 8(%rsp),%r13
+ movq 112(%rsp),%r15
+
+ movq %r13,%r12
+ rorq $7,%r13
+ addq %r14,%rax
+ movq %r15,%r14
+ rorq $42,%r15
+
+ xorq %r12,%r13
+ shrq $7,%r12
+ rorq $1,%r13
+ xorq %r14,%r15
+ shrq $6,%r14
+
+ rorq $19,%r15
+ xorq %r13,%r12
+ xorq %r14,%r15
+ addq 72(%rsp),%r12
+
+ addq 0(%rsp),%r12
+ movq %r8,%r13
+ addq %r15,%r12
+ movq %rax,%r14
+ rorq $23,%r13
+ movq %r9,%r15
+
+ xorq %r8,%r13
+ rorq $5,%r14
+ xorq %r10,%r15
+
+ movq %r12,0(%rsp)
+ xorq %rax,%r14
+ andq %r8,%r15
+
+ rorq $4,%r13
+ addq %r11,%r12
+ xorq %r10,%r15
+
+ rorq $6,%r14
+ xorq %r8,%r13
+ addq %r15,%r12
+
+ movq %rax,%r15
+ addq (%rbp),%r12
+ xorq %rax,%r14
+
+ xorq %rbx,%r15
+ rorq $14,%r13
+ movq %rbx,%r11
+
+ andq %r15,%rdi
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %rdi,%r11
+ addq %r12,%rdx
+ addq %r12,%r11
+
+ leaq 8(%rbp),%rbp
+ movq 16(%rsp),%r13
+ movq 120(%rsp),%rdi
+
+ movq %r13,%r12
+ rorq $7,%r13
+ addq %r14,%r11
+ movq %rdi,%r14
+ rorq $42,%rdi
+
+ xorq %r12,%r13
+ shrq $7,%r12
+ rorq $1,%r13
+ xorq %r14,%rdi
+ shrq $6,%r14
+
+ rorq $19,%rdi
+ xorq %r13,%r12
+ xorq %r14,%rdi
+ addq 80(%rsp),%r12
+
+ addq 8(%rsp),%r12
+ movq %rdx,%r13
+ addq %rdi,%r12
+ movq %r11,%r14
+ rorq $23,%r13
+ movq %r8,%rdi
+
+ xorq %rdx,%r13
+ rorq $5,%r14
+ xorq %r9,%rdi
+
+ movq %r12,8(%rsp)
+ xorq %r11,%r14
+ andq %rdx,%rdi
+
+ rorq $4,%r13
+ addq %r10,%r12
+ xorq %r9,%rdi
+
+ rorq $6,%r14
+ xorq %rdx,%r13
+ addq %rdi,%r12
+
+ movq %r11,%rdi
+ addq (%rbp),%r12
+ xorq %r11,%r14
+
+ xorq %rax,%rdi
+ rorq $14,%r13
+ movq %rax,%r10
+
+ andq %rdi,%r15
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %r15,%r10
+ addq %r12,%rcx
+ addq %r12,%r10
+
+ leaq 24(%rbp),%rbp
+ movq 24(%rsp),%r13
+ movq 0(%rsp),%r15
+
+ movq %r13,%r12
+ rorq $7,%r13
+ addq %r14,%r10
+ movq %r15,%r14
+ rorq $42,%r15
+
+ xorq %r12,%r13
+ shrq $7,%r12
+ rorq $1,%r13
+ xorq %r14,%r15
+ shrq $6,%r14
+
+ rorq $19,%r15
+ xorq %r13,%r12
+ xorq %r14,%r15
+ addq 88(%rsp),%r12
+
+ addq 16(%rsp),%r12
+ movq %rcx,%r13
+ addq %r15,%r12
+ movq %r10,%r14
+ rorq $23,%r13
+ movq %rdx,%r15
+
+ xorq %rcx,%r13
+ rorq $5,%r14
+ xorq %r8,%r15
+
+ movq %r12,16(%rsp)
+ xorq %r10,%r14
+ andq %rcx,%r15
+
+ rorq $4,%r13
+ addq %r9,%r12
+ xorq %r8,%r15
+
+ rorq $6,%r14
+ xorq %rcx,%r13
+ addq %r15,%r12
+
+ movq %r10,%r15
+ addq (%rbp),%r12
+ xorq %r10,%r14
+
+ xorq %r11,%r15
+ rorq $14,%r13
+ movq %r11,%r9
+
+ andq %r15,%rdi
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %rdi,%r9
+ addq %r12,%rbx
+ addq %r12,%r9
+
+ leaq 8(%rbp),%rbp
+ movq 32(%rsp),%r13
+ movq 8(%rsp),%rdi
+
+ movq %r13,%r12
+ rorq $7,%r13
+ addq %r14,%r9
+ movq %rdi,%r14
+ rorq $42,%rdi
+
+ xorq %r12,%r13
+ shrq $7,%r12
+ rorq $1,%r13
+ xorq %r14,%rdi
+ shrq $6,%r14
+
+ rorq $19,%rdi
+ xorq %r13,%r12
+ xorq %r14,%rdi
+ addq 96(%rsp),%r12
+
+ addq 24(%rsp),%r12
+ movq %rbx,%r13
+ addq %rdi,%r12
+ movq %r9,%r14
+ rorq $23,%r13
+ movq %rcx,%rdi
+
+ xorq %rbx,%r13
+ rorq $5,%r14
+ xorq %rdx,%rdi
+
+ movq %r12,24(%rsp)
+ xorq %r9,%r14
+ andq %rbx,%rdi
+
+ rorq $4,%r13
+ addq %r8,%r12
+ xorq %rdx,%rdi
+
+ rorq $6,%r14
+ xorq %rbx,%r13
+ addq %rdi,%r12
+
+ movq %r9,%rdi
+ addq (%rbp),%r12
+ xorq %r9,%r14
+
+ xorq %r10,%rdi
+ rorq $14,%r13
+ movq %r10,%r8
+
+ andq %rdi,%r15
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %r15,%r8
+ addq %r12,%rax
+ addq %r12,%r8
+
+ leaq 24(%rbp),%rbp
+ movq 40(%rsp),%r13
+ movq 16(%rsp),%r15
+
+ movq %r13,%r12
+ rorq $7,%r13
+ addq %r14,%r8
+ movq %r15,%r14
+ rorq $42,%r15
+
+ xorq %r12,%r13
+ shrq $7,%r12
+ rorq $1,%r13
+ xorq %r14,%r15
+ shrq $6,%r14
+
+ rorq $19,%r15
+ xorq %r13,%r12
+ xorq %r14,%r15
+ addq 104(%rsp),%r12
+
+ addq 32(%rsp),%r12
+ movq %rax,%r13
+ addq %r15,%r12
+ movq %r8,%r14
+ rorq $23,%r13
+ movq %rbx,%r15
+
+ xorq %rax,%r13
+ rorq $5,%r14
+ xorq %rcx,%r15
+
+ movq %r12,32(%rsp)
+ xorq %r8,%r14
+ andq %rax,%r15
+
+ rorq $4,%r13
+ addq %rdx,%r12
+ xorq %rcx,%r15
+
+ rorq $6,%r14
+ xorq %rax,%r13
+ addq %r15,%r12
+
+ movq %r8,%r15
+ addq (%rbp),%r12
+ xorq %r8,%r14
+
+ xorq %r9,%r15
+ rorq $14,%r13
+ movq %r9,%rdx
+
+ andq %r15,%rdi
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %rdi,%rdx
+ addq %r12,%r11
+ addq %r12,%rdx
+
+ leaq 8(%rbp),%rbp
+ movq 48(%rsp),%r13
+ movq 24(%rsp),%rdi
+
+ movq %r13,%r12
+ rorq $7,%r13
+ addq %r14,%rdx
+ movq %rdi,%r14
+ rorq $42,%rdi
+
+ xorq %r12,%r13
+ shrq $7,%r12
+ rorq $1,%r13
+ xorq %r14,%rdi
+ shrq $6,%r14
+
+ rorq $19,%rdi
+ xorq %r13,%r12
+ xorq %r14,%rdi
+ addq 112(%rsp),%r12
+
+ addq 40(%rsp),%r12
+ movq %r11,%r13
+ addq %rdi,%r12
+ movq %rdx,%r14
+ rorq $23,%r13
+ movq %rax,%rdi
+
+ xorq %r11,%r13
+ rorq $5,%r14
+ xorq %rbx,%rdi
+
+ movq %r12,40(%rsp)
+ xorq %rdx,%r14
+ andq %r11,%rdi
+
+ rorq $4,%r13
+ addq %rcx,%r12
+ xorq %rbx,%rdi
+
+ rorq $6,%r14
+ xorq %r11,%r13
+ addq %rdi,%r12
+
+ movq %rdx,%rdi
+ addq (%rbp),%r12
+ xorq %rdx,%r14
+
+ xorq %r8,%rdi
+ rorq $14,%r13
+ movq %r8,%rcx
+
+ andq %rdi,%r15
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %r15,%rcx
+ addq %r12,%r10
+ addq %r12,%rcx
+
+ leaq 24(%rbp),%rbp
+ movq 56(%rsp),%r13
+ movq 32(%rsp),%r15
+
+ movq %r13,%r12
+ rorq $7,%r13
+ addq %r14,%rcx
+ movq %r15,%r14
+ rorq $42,%r15
+
+ xorq %r12,%r13
+ shrq $7,%r12
+ rorq $1,%r13
+ xorq %r14,%r15
+ shrq $6,%r14
+
+ rorq $19,%r15
+ xorq %r13,%r12
+ xorq %r14,%r15
+ addq 120(%rsp),%r12
+
+ addq 48(%rsp),%r12
+ movq %r10,%r13
+ addq %r15,%r12
+ movq %rcx,%r14
+ rorq $23,%r13
+ movq %r11,%r15
+
+ xorq %r10,%r13
+ rorq $5,%r14
+ xorq %rax,%r15
+
+ movq %r12,48(%rsp)
+ xorq %rcx,%r14
+ andq %r10,%r15
+
+ rorq $4,%r13
+ addq %rbx,%r12
+ xorq %rax,%r15
+
+ rorq $6,%r14
+ xorq %r10,%r13
+ addq %r15,%r12
+
+ movq %rcx,%r15
+ addq (%rbp),%r12
+ xorq %rcx,%r14
+
+ xorq %rdx,%r15
+ rorq $14,%r13
+ movq %rdx,%rbx
+
+ andq %r15,%rdi
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %rdi,%rbx
+ addq %r12,%r9
+ addq %r12,%rbx
+
+ leaq 8(%rbp),%rbp
+ movq 64(%rsp),%r13
+ movq 40(%rsp),%rdi
+
+ movq %r13,%r12
+ rorq $7,%r13
+ addq %r14,%rbx
+ movq %rdi,%r14
+ rorq $42,%rdi
+
+ xorq %r12,%r13
+ shrq $7,%r12
+ rorq $1,%r13
+ xorq %r14,%rdi
+ shrq $6,%r14
+
+ rorq $19,%rdi
+ xorq %r13,%r12
+ xorq %r14,%rdi
+ addq 0(%rsp),%r12
+
+ addq 56(%rsp),%r12
+ movq %r9,%r13
+ addq %rdi,%r12
+ movq %rbx,%r14
+ rorq $23,%r13
+ movq %r10,%rdi
+
+ xorq %r9,%r13
+ rorq $5,%r14
+ xorq %r11,%rdi
+
+ movq %r12,56(%rsp)
+ xorq %rbx,%r14
+ andq %r9,%rdi
+
+ rorq $4,%r13
+ addq %rax,%r12
+ xorq %r11,%rdi
+
+ rorq $6,%r14
+ xorq %r9,%r13
+ addq %rdi,%r12
+
+ movq %rbx,%rdi
+ addq (%rbp),%r12
+ xorq %rbx,%r14
+
+ xorq %rcx,%rdi
+ rorq $14,%r13
+ movq %rcx,%rax
+
+ andq %rdi,%r15
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %r15,%rax
+ addq %r12,%r8
+ addq %r12,%rax
+
+ leaq 24(%rbp),%rbp
+ movq 72(%rsp),%r13
+ movq 48(%rsp),%r15
+
+ movq %r13,%r12
+ rorq $7,%r13
+ addq %r14,%rax
+ movq %r15,%r14
+ rorq $42,%r15
+
+ xorq %r12,%r13
+ shrq $7,%r12
+ rorq $1,%r13
+ xorq %r14,%r15
+ shrq $6,%r14
+
+ rorq $19,%r15
+ xorq %r13,%r12
+ xorq %r14,%r15
+ addq 8(%rsp),%r12
+
+ addq 64(%rsp),%r12
+ movq %r8,%r13
+ addq %r15,%r12
+ movq %rax,%r14
+ rorq $23,%r13
+ movq %r9,%r15
+
+ xorq %r8,%r13
+ rorq $5,%r14
+ xorq %r10,%r15
+
+ movq %r12,64(%rsp)
+ xorq %rax,%r14
+ andq %r8,%r15
+
+ rorq $4,%r13
+ addq %r11,%r12
+ xorq %r10,%r15
+
+ rorq $6,%r14
+ xorq %r8,%r13
+ addq %r15,%r12
+
+ movq %rax,%r15
+ addq (%rbp),%r12
+ xorq %rax,%r14
+
+ xorq %rbx,%r15
+ rorq $14,%r13
+ movq %rbx,%r11
+
+ andq %r15,%rdi
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %rdi,%r11
+ addq %r12,%rdx
+ addq %r12,%r11
+
+ leaq 8(%rbp),%rbp
+ movq 80(%rsp),%r13
+ movq 56(%rsp),%rdi
+
+ movq %r13,%r12
+ rorq $7,%r13
+ addq %r14,%r11
+ movq %rdi,%r14
+ rorq $42,%rdi
+
+ xorq %r12,%r13
+ shrq $7,%r12
+ rorq $1,%r13
+ xorq %r14,%rdi
+ shrq $6,%r14
+
+ rorq $19,%rdi
+ xorq %r13,%r12
+ xorq %r14,%rdi
+ addq 16(%rsp),%r12
+
+ addq 72(%rsp),%r12
+ movq %rdx,%r13
+ addq %rdi,%r12
+ movq %r11,%r14
+ rorq $23,%r13
+ movq %r8,%rdi
+
+ xorq %rdx,%r13
+ rorq $5,%r14
+ xorq %r9,%rdi
+
+ movq %r12,72(%rsp)
+ xorq %r11,%r14
+ andq %rdx,%rdi
+
+ rorq $4,%r13
+ addq %r10,%r12
+ xorq %r9,%rdi
+
+ rorq $6,%r14
+ xorq %rdx,%r13
+ addq %rdi,%r12
+
+ movq %r11,%rdi
+ addq (%rbp),%r12
+ xorq %r11,%r14
+
+ xorq %rax,%rdi
+ rorq $14,%r13
+ movq %rax,%r10
+
+ andq %rdi,%r15
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %r15,%r10
+ addq %r12,%rcx
+ addq %r12,%r10
+
+ leaq 24(%rbp),%rbp
+ movq 88(%rsp),%r13
+ movq 64(%rsp),%r15
+
+ movq %r13,%r12
+ rorq $7,%r13
+ addq %r14,%r10
+ movq %r15,%r14
+ rorq $42,%r15
+
+ xorq %r12,%r13
+ shrq $7,%r12
+ rorq $1,%r13
+ xorq %r14,%r15
+ shrq $6,%r14
+
+ rorq $19,%r15
+ xorq %r13,%r12
+ xorq %r14,%r15
+ addq 24(%rsp),%r12
+
+ addq 80(%rsp),%r12
+ movq %rcx,%r13
+ addq %r15,%r12
+ movq %r10,%r14
+ rorq $23,%r13
+ movq %rdx,%r15
+
+ xorq %rcx,%r13
+ rorq $5,%r14
+ xorq %r8,%r15
+
+ movq %r12,80(%rsp)
+ xorq %r10,%r14
+ andq %rcx,%r15
+
+ rorq $4,%r13
+ addq %r9,%r12
+ xorq %r8,%r15
+
+ rorq $6,%r14
+ xorq %rcx,%r13
+ addq %r15,%r12
+
+ movq %r10,%r15
+ addq (%rbp),%r12
+ xorq %r10,%r14
+
+ xorq %r11,%r15
+ rorq $14,%r13
+ movq %r11,%r9
+
+ andq %r15,%rdi
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %rdi,%r9
+ addq %r12,%rbx
+ addq %r12,%r9
+
+ leaq 8(%rbp),%rbp
+ movq 96(%rsp),%r13
+ movq 72(%rsp),%rdi
+
+ movq %r13,%r12
+ rorq $7,%r13
+ addq %r14,%r9
+ movq %rdi,%r14
+ rorq $42,%rdi
+
+ xorq %r12,%r13
+ shrq $7,%r12
+ rorq $1,%r13
+ xorq %r14,%rdi
+ shrq $6,%r14
+
+ rorq $19,%rdi
+ xorq %r13,%r12
+ xorq %r14,%rdi
+ addq 32(%rsp),%r12
+
+ addq 88(%rsp),%r12
+ movq %rbx,%r13
+ addq %rdi,%r12
+ movq %r9,%r14
+ rorq $23,%r13
+ movq %rcx,%rdi
+
+ xorq %rbx,%r13
+ rorq $5,%r14
+ xorq %rdx,%rdi
+
+ movq %r12,88(%rsp)
+ xorq %r9,%r14
+ andq %rbx,%rdi
+
+ rorq $4,%r13
+ addq %r8,%r12
+ xorq %rdx,%rdi
+
+ rorq $6,%r14
+ xorq %rbx,%r13
+ addq %rdi,%r12
+
+ movq %r9,%rdi
+ addq (%rbp),%r12
+ xorq %r9,%r14
+
+ xorq %r10,%rdi
+ rorq $14,%r13
+ movq %r10,%r8
+
+ andq %rdi,%r15
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %r15,%r8
+ addq %r12,%rax
+ addq %r12,%r8
+
+ leaq 24(%rbp),%rbp
+ movq 104(%rsp),%r13
+ movq 80(%rsp),%r15
+
+ movq %r13,%r12
+ rorq $7,%r13
+ addq %r14,%r8
+ movq %r15,%r14
+ rorq $42,%r15
+
+ xorq %r12,%r13
+ shrq $7,%r12
+ rorq $1,%r13
+ xorq %r14,%r15
+ shrq $6,%r14
+
+ rorq $19,%r15
+ xorq %r13,%r12
+ xorq %r14,%r15
+ addq 40(%rsp),%r12
+
+ addq 96(%rsp),%r12
+ movq %rax,%r13
+ addq %r15,%r12
+ movq %r8,%r14
+ rorq $23,%r13
+ movq %rbx,%r15
+
+ xorq %rax,%r13
+ rorq $5,%r14
+ xorq %rcx,%r15
+
+ movq %r12,96(%rsp)
+ xorq %r8,%r14
+ andq %rax,%r15
+
+ rorq $4,%r13
+ addq %rdx,%r12
+ xorq %rcx,%r15
+
+ rorq $6,%r14
+ xorq %rax,%r13
+ addq %r15,%r12
+
+ movq %r8,%r15
+ addq (%rbp),%r12
+ xorq %r8,%r14
+
+ xorq %r9,%r15
+ rorq $14,%r13
+ movq %r9,%rdx
+
+ andq %r15,%rdi
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %rdi,%rdx
+ addq %r12,%r11
+ addq %r12,%rdx
+
+ leaq 8(%rbp),%rbp
+ movq 112(%rsp),%r13
+ movq 88(%rsp),%rdi
+
+ movq %r13,%r12
+ rorq $7,%r13
+ addq %r14,%rdx
+ movq %rdi,%r14
+ rorq $42,%rdi
+
+ xorq %r12,%r13
+ shrq $7,%r12
+ rorq $1,%r13
+ xorq %r14,%rdi
+ shrq $6,%r14
+
+ rorq $19,%rdi
+ xorq %r13,%r12
+ xorq %r14,%rdi
+ addq 48(%rsp),%r12
+
+ addq 104(%rsp),%r12
+ movq %r11,%r13
+ addq %rdi,%r12
+ movq %rdx,%r14
+ rorq $23,%r13
+ movq %rax,%rdi
+
+ xorq %r11,%r13
+ rorq $5,%r14
+ xorq %rbx,%rdi
+
+ movq %r12,104(%rsp)
+ xorq %rdx,%r14
+ andq %r11,%rdi
+
+ rorq $4,%r13
+ addq %rcx,%r12
+ xorq %rbx,%rdi
+
+ rorq $6,%r14
+ xorq %r11,%r13
+ addq %rdi,%r12
+
+ movq %rdx,%rdi
+ addq (%rbp),%r12
+ xorq %rdx,%r14
+
+ xorq %r8,%rdi
+ rorq $14,%r13
+ movq %r8,%rcx
+
+ andq %rdi,%r15
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %r15,%rcx
+ addq %r12,%r10
+ addq %r12,%rcx
+
+ leaq 24(%rbp),%rbp
+ movq 120(%rsp),%r13
+ movq 96(%rsp),%r15
+
+ movq %r13,%r12
+ rorq $7,%r13
+ addq %r14,%rcx
+ movq %r15,%r14
+ rorq $42,%r15
+
+ xorq %r12,%r13
+ shrq $7,%r12
+ rorq $1,%r13
+ xorq %r14,%r15
+ shrq $6,%r14
+
+ rorq $19,%r15
+ xorq %r13,%r12
+ xorq %r14,%r15
+ addq 56(%rsp),%r12
+
+ addq 112(%rsp),%r12
+ movq %r10,%r13
+ addq %r15,%r12
+ movq %rcx,%r14
+ rorq $23,%r13
+ movq %r11,%r15
+
+ xorq %r10,%r13
+ rorq $5,%r14
+ xorq %rax,%r15
+
+ movq %r12,112(%rsp)
+ xorq %rcx,%r14
+ andq %r10,%r15
+
+ rorq $4,%r13
+ addq %rbx,%r12
+ xorq %rax,%r15
+
+ rorq $6,%r14
+ xorq %r10,%r13
+ addq %r15,%r12
+
+ movq %rcx,%r15
+ addq (%rbp),%r12
+ xorq %rcx,%r14
+
+ xorq %rdx,%r15
+ rorq $14,%r13
+ movq %rdx,%rbx
+
+ andq %r15,%rdi
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %rdi,%rbx
+ addq %r12,%r9
+ addq %r12,%rbx
+
+ leaq 8(%rbp),%rbp
+ movq 0(%rsp),%r13
+ movq 104(%rsp),%rdi
+
+ movq %r13,%r12
+ rorq $7,%r13
+ addq %r14,%rbx
+ movq %rdi,%r14
+ rorq $42,%rdi
+
+ xorq %r12,%r13
+ shrq $7,%r12
+ rorq $1,%r13
+ xorq %r14,%rdi
+ shrq $6,%r14
+
+ rorq $19,%rdi
+ xorq %r13,%r12
+ xorq %r14,%rdi
+ addq 64(%rsp),%r12
+
+ addq 120(%rsp),%r12
+ movq %r9,%r13
+ addq %rdi,%r12
+ movq %rbx,%r14
+ rorq $23,%r13
+ movq %r10,%rdi
+
+ xorq %r9,%r13
+ rorq $5,%r14
+ xorq %r11,%rdi
+
+ movq %r12,120(%rsp)
+ xorq %rbx,%r14
+ andq %r9,%rdi
+
+ rorq $4,%r13
+ addq %rax,%r12
+ xorq %r11,%rdi
+
+ rorq $6,%r14
+ xorq %r9,%r13
+ addq %rdi,%r12
+
+ movq %rbx,%rdi
+ addq (%rbp),%r12
+ xorq %rbx,%r14
+
+ xorq %rcx,%rdi
+ rorq $14,%r13
+ movq %rcx,%rax
+
+ andq %rdi,%r15
+ rorq $28,%r14
+ addq %r13,%r12
+
+ xorq %r15,%rax
+ addq %r12,%r8
+ addq %r12,%rax
+
+ leaq 24(%rbp),%rbp
+ cmpb $0,7(%rbp)
+ jnz L$rounds_16_xx
+
+ movq 128+0(%rsp),%rdi
+ addq %r14,%rax
+ 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:
+ .byte 0xf3,0xc3
+
+.p2align 6
+
+K512:
+.quad 0x428a2f98d728ae22,0x7137449123ef65cd
+.quad 0x428a2f98d728ae22,0x7137449123ef65cd
+.quad 0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc
+.quad 0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc
+.quad 0x3956c25bf348b538,0x59f111f1b605d019
+.quad 0x3956c25bf348b538,0x59f111f1b605d019
+.quad 0x923f82a4af194f9b,0xab1c5ed5da6d8118
+.quad 0x923f82a4af194f9b,0xab1c5ed5da6d8118
+.quad 0xd807aa98a3030242,0x12835b0145706fbe
+.quad 0xd807aa98a3030242,0x12835b0145706fbe
+.quad 0x243185be4ee4b28c,0x550c7dc3d5ffb4e2
+.quad 0x243185be4ee4b28c,0x550c7dc3d5ffb4e2
+.quad 0x72be5d74f27b896f,0x80deb1fe3b1696b1
+.quad 0x72be5d74f27b896f,0x80deb1fe3b1696b1
+.quad 0x9bdc06a725c71235,0xc19bf174cf692694
+.quad 0x9bdc06a725c71235,0xc19bf174cf692694
+.quad 0xe49b69c19ef14ad2,0xefbe4786384f25e3
+.quad 0xe49b69c19ef14ad2,0xefbe4786384f25e3
+.quad 0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65
+.quad 0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65
+.quad 0x2de92c6f592b0275,0x4a7484aa6ea6e483
+.quad 0x2de92c6f592b0275,0x4a7484aa6ea6e483
+.quad 0x5cb0a9dcbd41fbd4,0x76f988da831153b5
+.quad 0x5cb0a9dcbd41fbd4,0x76f988da831153b5
+.quad 0x983e5152ee66dfab,0xa831c66d2db43210
+.quad 0x983e5152ee66dfab,0xa831c66d2db43210
+.quad 0xb00327c898fb213f,0xbf597fc7beef0ee4
+.quad 0xb00327c898fb213f,0xbf597fc7beef0ee4
+.quad 0xc6e00bf33da88fc2,0xd5a79147930aa725
+.quad 0xc6e00bf33da88fc2,0xd5a79147930aa725
+.quad 0x06ca6351e003826f,0x142929670a0e6e70
+.quad 0x06ca6351e003826f,0x142929670a0e6e70
+.quad 0x27b70a8546d22ffc,0x2e1b21385c26c926
+.quad 0x27b70a8546d22ffc,0x2e1b21385c26c926
+.quad 0x4d2c6dfc5ac42aed,0x53380d139d95b3df
+.quad 0x4d2c6dfc5ac42aed,0x53380d139d95b3df
+.quad 0x650a73548baf63de,0x766a0abb3c77b2a8
+.quad 0x650a73548baf63de,0x766a0abb3c77b2a8
+.quad 0x81c2c92e47edaee6,0x92722c851482353b
+.quad 0x81c2c92e47edaee6,0x92722c851482353b
+.quad 0xa2bfe8a14cf10364,0xa81a664bbc423001
+.quad 0xa2bfe8a14cf10364,0xa81a664bbc423001
+.quad 0xc24b8b70d0f89791,0xc76c51a30654be30
+.quad 0xc24b8b70d0f89791,0xc76c51a30654be30
+.quad 0xd192e819d6ef5218,0xd69906245565a910
+.quad 0xd192e819d6ef5218,0xd69906245565a910
+.quad 0xf40e35855771202a,0x106aa07032bbd1b8
+.quad 0xf40e35855771202a,0x106aa07032bbd1b8
+.quad 0x19a4c116b8d2d0c8,0x1e376c085141ab53
+.quad 0x19a4c116b8d2d0c8,0x1e376c085141ab53
+.quad 0x2748774cdf8eeb99,0x34b0bcb5e19b48a8
+.quad 0x2748774cdf8eeb99,0x34b0bcb5e19b48a8
+.quad 0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb
+.quad 0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb
+.quad 0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3
+.quad 0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3
+.quad 0x748f82ee5defb2fc,0x78a5636f43172f60
+.quad 0x748f82ee5defb2fc,0x78a5636f43172f60
+.quad 0x84c87814a1f0ab72,0x8cc702081a6439ec
+.quad 0x84c87814a1f0ab72,0x8cc702081a6439ec
+.quad 0x90befffa23631e28,0xa4506cebde82bde9
+.quad 0x90befffa23631e28,0xa4506cebde82bde9
+.quad 0xbef9a3f7b2c67915,0xc67178f2e372532b
+.quad 0xbef9a3f7b2c67915,0xc67178f2e372532b
+.quad 0xca273eceea26619c,0xd186b8c721c0c207
+.quad 0xca273eceea26619c,0xd186b8c721c0c207
+.quad 0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178
+.quad 0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178
+.quad 0x06f067aa72176fba,0x0a637dc5a2c898a6
+.quad 0x06f067aa72176fba,0x0a637dc5a2c898a6
+.quad 0x113f9804bef90dae,0x1b710b35131c471b
+.quad 0x113f9804bef90dae,0x1b710b35131c471b
+.quad 0x28db77f523047d84,0x32caab7b40c72493
+.quad 0x28db77f523047d84,0x32caab7b40c72493
+.quad 0x3c9ebe0a15c9bebc,0x431d67c49c100d4c
+.quad 0x3c9ebe0a15c9bebc,0x431d67c49c100d4c
+.quad 0x4cc5d4becb3e42b6,0x597f299cfc657e2a
+.quad 0x4cc5d4becb3e42b6,0x597f299cfc657e2a
+.quad 0x5fcb6fab3ad6faec,0x6c44198c4a475817
+.quad 0x5fcb6fab3ad6faec,0x6c44198c4a475817
+
+.quad 0x0001020304050607,0x08090a0b0c0d0e0f
+.quad 0x0001020304050607,0x08090a0b0c0d0e0f
+.byte 83,72,65,53,49,50,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
+#endif
diff --git a/sources.mk b/sources.mk
new file mode 100644
index 0000000..cb0a94b
--- /dev/null
+++ b/sources.mk
@@ -0,0 +1,430 @@
+# This file is created by update_gypi_and_asm.py. Do not edit manually.
+
+crypto_sources := \
+ android_compat_hacks.c\
+ src/crypto/aes/aes.c\
+ src/crypto/aes/mode_wrappers.c\
+ src/crypto/asn1/a_bitstr.c\
+ src/crypto/asn1/a_bool.c\
+ src/crypto/asn1/a_bytes.c\
+ src/crypto/asn1/a_d2i_fp.c\
+ src/crypto/asn1/a_dup.c\
+ src/crypto/asn1/a_enum.c\
+ src/crypto/asn1/a_gentm.c\
+ src/crypto/asn1/a_i2d_fp.c\
+ src/crypto/asn1/a_int.c\
+ src/crypto/asn1/a_mbstr.c\
+ src/crypto/asn1/a_object.c\
+ src/crypto/asn1/a_octet.c\
+ src/crypto/asn1/a_print.c\
+ src/crypto/asn1/a_strnid.c\
+ src/crypto/asn1/a_time.c\
+ src/crypto/asn1/a_type.c\
+ src/crypto/asn1/a_utctm.c\
+ src/crypto/asn1/a_utf8.c\
+ src/crypto/asn1/asn1_error.c\
+ src/crypto/asn1/asn1_lib.c\
+ src/crypto/asn1/asn1_par.c\
+ src/crypto/asn1/asn_pack.c\
+ src/crypto/asn1/bio_asn1.c\
+ src/crypto/asn1/bio_ndef.c\
+ src/crypto/asn1/f_enum.c\
+ src/crypto/asn1/f_int.c\
+ src/crypto/asn1/f_string.c\
+ src/crypto/asn1/t_bitst.c\
+ src/crypto/asn1/t_pkey.c\
+ src/crypto/asn1/tasn_dec.c\
+ src/crypto/asn1/tasn_enc.c\
+ src/crypto/asn1/tasn_fre.c\
+ src/crypto/asn1/tasn_new.c\
+ src/crypto/asn1/tasn_prn.c\
+ src/crypto/asn1/tasn_typ.c\
+ src/crypto/asn1/tasn_utl.c\
+ src/crypto/asn1/x_bignum.c\
+ src/crypto/asn1/x_long.c\
+ src/crypto/base64/base64.c\
+ src/crypto/bio/bio.c\
+ src/crypto/bio/bio_error.c\
+ src/crypto/bio/bio_mem.c\
+ src/crypto/bio/buffer.c\
+ src/crypto/bio/connect.c\
+ src/crypto/bio/fd.c\
+ src/crypto/bio/file.c\
+ src/crypto/bio/hexdump.c\
+ src/crypto/bio/pair.c\
+ src/crypto/bio/printf.c\
+ src/crypto/bio/socket.c\
+ src/crypto/bio/socket_helper.c\
+ src/crypto/bn/add.c\
+ src/crypto/bn/asm/x86_64-gcc.c\
+ src/crypto/bn/bn.c\
+ src/crypto/bn/bn_error.c\
+ src/crypto/bn/cmp.c\
+ src/crypto/bn/convert.c\
+ src/crypto/bn/ctx.c\
+ src/crypto/bn/div.c\
+ src/crypto/bn/exponentiation.c\
+ src/crypto/bn/gcd.c\
+ src/crypto/bn/generic.c\
+ src/crypto/bn/kronecker.c\
+ src/crypto/bn/montgomery.c\
+ src/crypto/bn/mul.c\
+ src/crypto/bn/prime.c\
+ src/crypto/bn/random.c\
+ src/crypto/bn/rsaz_exp.c\
+ src/crypto/bn/shift.c\
+ src/crypto/bn/sqrt.c\
+ src/crypto/buf/buf.c\
+ src/crypto/buf/buf_error.c\
+ src/crypto/bytestring/ber.c\
+ src/crypto/bytestring/cbb.c\
+ src/crypto/bytestring/cbs.c\
+ src/crypto/chacha/chacha_generic.c\
+ src/crypto/chacha/chacha_vec.c\
+ src/crypto/cipher/aead.c\
+ src/crypto/cipher/cipher.c\
+ src/crypto/cipher/cipher_error.c\
+ src/crypto/cipher/derive_key.c\
+ src/crypto/cipher/e_aes.c\
+ src/crypto/cipher/e_chacha20poly1305.c\
+ src/crypto/cipher/e_des.c\
+ src/crypto/cipher/e_null.c\
+ src/crypto/cipher/e_rc2.c\
+ src/crypto/cipher/e_rc4.c\
+ src/crypto/cipher/e_ssl3.c\
+ src/crypto/cipher/e_tls.c\
+ src/crypto/cipher/tls_cbc.c\
+ src/crypto/conf/conf.c\
+ src/crypto/conf/conf_error.c\
+ src/crypto/cpu-arm.c\
+ src/crypto/cpu-intel.c\
+ src/crypto/crypto.c\
+ src/crypto/crypto_error.c\
+ src/crypto/des/des.c\
+ src/crypto/dh/check.c\
+ src/crypto/dh/dh.c\
+ src/crypto/dh/dh_asn1.c\
+ src/crypto/dh/dh_error.c\
+ src/crypto/dh/dh_impl.c\
+ src/crypto/dh/params.c\
+ src/crypto/digest/digest.c\
+ src/crypto/digest/digest_error.c\
+ src/crypto/digest/digests.c\
+ src/crypto/directory_posix.c\
+ src/crypto/directory_win.c\
+ src/crypto/dsa/dsa.c\
+ src/crypto/dsa/dsa_asn1.c\
+ src/crypto/dsa/dsa_error.c\
+ src/crypto/dsa/dsa_impl.c\
+ src/crypto/ec/ec.c\
+ src/crypto/ec/ec_asn1.c\
+ src/crypto/ec/ec_error.c\
+ src/crypto/ec/ec_key.c\
+ src/crypto/ec/ec_montgomery.c\
+ src/crypto/ec/oct.c\
+ src/crypto/ec/simple.c\
+ src/crypto/ec/wnaf.c\
+ src/crypto/ecdh/ecdh.c\
+ src/crypto/ecdh/ecdh_error.c\
+ src/crypto/ecdsa/ecdsa.c\
+ src/crypto/ecdsa/ecdsa_asn1.c\
+ src/crypto/ecdsa/ecdsa_error.c\
+ src/crypto/engine/engine.c\
+ src/crypto/engine/engine_error.c\
+ src/crypto/err/err.c\
+ src/crypto/err/err_impl.c\
+ src/crypto/evp/algorithm.c\
+ src/crypto/evp/asn1.c\
+ src/crypto/evp/digestsign.c\
+ src/crypto/evp/evp.c\
+ src/crypto/evp/evp_ctx.c\
+ src/crypto/evp/evp_error.c\
+ src/crypto/evp/p_ec.c\
+ src/crypto/evp/p_ec_asn1.c\
+ src/crypto/evp/p_hmac.c\
+ src/crypto/evp/p_hmac_asn1.c\
+ src/crypto/evp/p_rsa.c\
+ src/crypto/evp/p_rsa_asn1.c\
+ src/crypto/evp/pbkdf.c\
+ src/crypto/evp/sign.c\
+ src/crypto/ex_data.c\
+ src/crypto/ex_data_impl.c\
+ src/crypto/hkdf/hkdf.c\
+ src/crypto/hkdf/hkdf_error.c\
+ src/crypto/hmac/hmac.c\
+ src/crypto/lhash/lhash.c\
+ src/crypto/md4/md4.c\
+ src/crypto/md5/md5.c\
+ src/crypto/mem.c\
+ src/crypto/modes/cbc.c\
+ src/crypto/modes/cfb.c\
+ src/crypto/modes/ctr.c\
+ src/crypto/modes/gcm.c\
+ src/crypto/modes/ofb.c\
+ src/crypto/obj/obj.c\
+ src/crypto/obj/obj_error.c\
+ src/crypto/obj/obj_xref.c\
+ src/crypto/pem/pem_all.c\
+ src/crypto/pem/pem_error.c\
+ src/crypto/pem/pem_info.c\
+ src/crypto/pem/pem_lib.c\
+ src/crypto/pem/pem_oth.c\
+ src/crypto/pem/pem_pk8.c\
+ src/crypto/pem/pem_pkey.c\
+ src/crypto/pem/pem_x509.c\
+ src/crypto/pem/pem_xaux.c\
+ src/crypto/pkcs8/p5_pbe.c\
+ src/crypto/pkcs8/p5_pbev2.c\
+ src/crypto/pkcs8/p8_pkey.c\
+ src/crypto/pkcs8/pkcs8.c\
+ src/crypto/pkcs8/pkcs8_error.c\
+ src/crypto/poly1305/poly1305.c\
+ src/crypto/poly1305/poly1305_arm.c\
+ src/crypto/poly1305/poly1305_vec.c\
+ src/crypto/rand/rand.c\
+ src/crypto/rand/urandom.c\
+ src/crypto/rand/windows.c\
+ src/crypto/rc4/rc4.c\
+ src/crypto/rsa/blinding.c\
+ src/crypto/rsa/padding.c\
+ src/crypto/rsa/rsa.c\
+ src/crypto/rsa/rsa_asn1.c\
+ src/crypto/rsa/rsa_error.c\
+ src/crypto/rsa/rsa_impl.c\
+ src/crypto/sha/sha1.c\
+ src/crypto/sha/sha256.c\
+ src/crypto/sha/sha512.c\
+ src/crypto/stack/stack.c\
+ src/crypto/thread.c\
+ src/crypto/time_support.c\
+ src/crypto/x509/a_digest.c\
+ src/crypto/x509/a_sign.c\
+ src/crypto/x509/a_strex.c\
+ src/crypto/x509/a_verify.c\
+ src/crypto/x509/asn1_gen.c\
+ src/crypto/x509/by_dir.c\
+ src/crypto/x509/by_file.c\
+ src/crypto/x509/i2d_pr.c\
+ src/crypto/x509/pkcs7.c\
+ src/crypto/x509/t_crl.c\
+ src/crypto/x509/t_x509.c\
+ src/crypto/x509/t_x509a.c\
+ src/crypto/x509/x509.c\
+ src/crypto/x509/x509_att.c\
+ src/crypto/x509/x509_cmp.c\
+ src/crypto/x509/x509_d2.c\
+ src/crypto/x509/x509_def.c\
+ src/crypto/x509/x509_error.c\
+ src/crypto/x509/x509_ext.c\
+ src/crypto/x509/x509_lu.c\
+ src/crypto/x509/x509_obj.c\
+ src/crypto/x509/x509_r2x.c\
+ src/crypto/x509/x509_req.c\
+ src/crypto/x509/x509_set.c\
+ src/crypto/x509/x509_trs.c\
+ src/crypto/x509/x509_txt.c\
+ src/crypto/x509/x509_v3.c\
+ src/crypto/x509/x509_vfy.c\
+ src/crypto/x509/x509_vpm.c\
+ src/crypto/x509/x509cset.c\
+ src/crypto/x509/x509name.c\
+ src/crypto/x509/x509rset.c\
+ src/crypto/x509/x509spki.c\
+ src/crypto/x509/x509type.c\
+ src/crypto/x509/x_algor.c\
+ src/crypto/x509/x_all.c\
+ src/crypto/x509/x_attrib.c\
+ src/crypto/x509/x_crl.c\
+ src/crypto/x509/x_exten.c\
+ src/crypto/x509/x_info.c\
+ src/crypto/x509/x_name.c\
+ src/crypto/x509/x_pkey.c\
+ src/crypto/x509/x_pubkey.c\
+ src/crypto/x509/x_req.c\
+ src/crypto/x509/x_sig.c\
+ src/crypto/x509/x_spki.c\
+ src/crypto/x509/x_val.c\
+ src/crypto/x509/x_x509.c\
+ src/crypto/x509/x_x509a.c\
+ src/crypto/x509v3/pcy_cache.c\
+ src/crypto/x509v3/pcy_data.c\
+ src/crypto/x509v3/pcy_lib.c\
+ src/crypto/x509v3/pcy_map.c\
+ src/crypto/x509v3/pcy_node.c\
+ src/crypto/x509v3/pcy_tree.c\
+ src/crypto/x509v3/v3_akey.c\
+ src/crypto/x509v3/v3_akeya.c\
+ src/crypto/x509v3/v3_alt.c\
+ src/crypto/x509v3/v3_bcons.c\
+ src/crypto/x509v3/v3_bitst.c\
+ src/crypto/x509v3/v3_conf.c\
+ src/crypto/x509v3/v3_cpols.c\
+ src/crypto/x509v3/v3_crld.c\
+ src/crypto/x509v3/v3_enum.c\
+ src/crypto/x509v3/v3_extku.c\
+ src/crypto/x509v3/v3_genn.c\
+ src/crypto/x509v3/v3_ia5.c\
+ src/crypto/x509v3/v3_info.c\
+ src/crypto/x509v3/v3_int.c\
+ src/crypto/x509v3/v3_lib.c\
+ src/crypto/x509v3/v3_ncons.c\
+ src/crypto/x509v3/v3_pci.c\
+ src/crypto/x509v3/v3_pcia.c\
+ src/crypto/x509v3/v3_pcons.c\
+ src/crypto/x509v3/v3_pku.c\
+ src/crypto/x509v3/v3_pmaps.c\
+ src/crypto/x509v3/v3_prn.c\
+ src/crypto/x509v3/v3_purp.c\
+ src/crypto/x509v3/v3_skey.c\
+ src/crypto/x509v3/v3_sxnet.c\
+ src/crypto/x509v3/v3_utl.c\
+ src/crypto/x509v3/x509v3_error.c\
+
+ssl_sources := \
+ src/ssl/d1_both.c\
+ src/ssl/d1_clnt.c\
+ src/ssl/d1_lib.c\
+ src/ssl/d1_meth.c\
+ src/ssl/d1_pkt.c\
+ src/ssl/d1_srtp.c\
+ src/ssl/d1_srvr.c\
+ src/ssl/pqueue/pqueue.c\
+ src/ssl/s3_both.c\
+ src/ssl/s3_clnt.c\
+ src/ssl/s3_enc.c\
+ src/ssl/s3_lib.c\
+ src/ssl/s3_meth.c\
+ src/ssl/s3_pkt.c\
+ src/ssl/s3_srvr.c\
+ src/ssl/ssl_algs.c\
+ src/ssl/ssl_asn1.c\
+ src/ssl/ssl_cert.c\
+ src/ssl/ssl_ciph.c\
+ src/ssl/ssl_error.c\
+ src/ssl/ssl_lib.c\
+ src/ssl/ssl_rsa.c\
+ src/ssl/ssl_sess.c\
+ src/ssl/ssl_stat.c\
+ src/ssl/ssl_txt.c\
+ src/ssl/t1_enc.c\
+ src/ssl/t1_lib.c\
+ src/ssl/t1_reneg.c\
+
+tool_sources := \
+ src/tool/args.cc\
+ src/tool/client.cc\
+ src/tool/const.cc\
+ src/tool/digest.cc\
+ src/tool/pkcs12.cc\
+ src/tool/server.cc\
+ src/tool/speed.cc\
+ src/tool/tool.cc\
+ src/tool/transport_common.cc\
+
+linux_aarch64_sources := \
+ linux-aarch64/crypto/aes/aesv8-armx.S\
+ linux-aarch64/crypto/modes/ghashv8-armx.S\
+ linux-aarch64/crypto/sha/sha1-armv8.S\
+ linux-aarch64/crypto/sha/sha256-armv8.S\
+ linux-aarch64/crypto/sha/sha512-armv8.S\
+
+linux_arm_sources := \
+ linux-arm/crypto/aes/aes-armv4.S\
+ linux-arm/crypto/aes/aesv8-armx.S\
+ linux-arm/crypto/aes/bsaes-armv7.S\
+ linux-arm/crypto/bn/armv4-mont.S\
+ linux-arm/crypto/modes/ghash-armv4.S\
+ linux-arm/crypto/modes/ghashv8-armx.S\
+ linux-arm/crypto/sha/sha1-armv4-large.S\
+ linux-arm/crypto/sha/sha256-armv4.S\
+ linux-arm/crypto/sha/sha512-armv4.S\
+ src/crypto/chacha/chacha_vec_arm.S\
+ src/crypto/poly1305/poly1305_arm_asm.S\
+
+linux_x86_sources := \
+ linux-x86/crypto/aes/aes-586.S\
+ linux-x86/crypto/aes/aesni-x86.S\
+ linux-x86/crypto/aes/vpaes-x86.S\
+ linux-x86/crypto/bn/bn-586.S\
+ linux-x86/crypto/bn/co-586.S\
+ linux-x86/crypto/bn/x86-mont.S\
+ linux-x86/crypto/cpu-x86-asm.S\
+ linux-x86/crypto/md5/md5-586.S\
+ linux-x86/crypto/modes/ghash-x86.S\
+ linux-x86/crypto/rc4/rc4-586.S\
+ linux-x86/crypto/sha/sha1-586.S\
+ linux-x86/crypto/sha/sha256-586.S\
+ linux-x86/crypto/sha/sha512-586.S\
+
+linux_x86_64_sources := \
+ linux-x86_64/crypto/aes/aes-x86_64.S\
+ linux-x86_64/crypto/aes/aesni-x86_64.S\
+ linux-x86_64/crypto/aes/bsaes-x86_64.S\
+ linux-x86_64/crypto/aes/vpaes-x86_64.S\
+ linux-x86_64/crypto/bn/rsaz-avx2.S\
+ linux-x86_64/crypto/bn/rsaz-x86_64.S\
+ linux-x86_64/crypto/bn/x86_64-mont.S\
+ linux-x86_64/crypto/bn/x86_64-mont5.S\
+ linux-x86_64/crypto/cpu-x86_64-asm.S\
+ linux-x86_64/crypto/md5/md5-x86_64.S\
+ linux-x86_64/crypto/modes/aesni-gcm-x86_64.S\
+ linux-x86_64/crypto/modes/ghash-x86_64.S\
+ linux-x86_64/crypto/rc4/rc4-md5-x86_64.S\
+ linux-x86_64/crypto/rc4/rc4-x86_64.S\
+ linux-x86_64/crypto/sha/sha1-x86_64.S\
+ linux-x86_64/crypto/sha/sha256-x86_64.S\
+ linux-x86_64/crypto/sha/sha512-x86_64.S\
+
+mac_x86_sources := \
+ mac-x86/crypto/aes/aes-586.S\
+ mac-x86/crypto/aes/aesni-x86.S\
+ mac-x86/crypto/aes/vpaes-x86.S\
+ mac-x86/crypto/bn/bn-586.S\
+ mac-x86/crypto/bn/co-586.S\
+ mac-x86/crypto/bn/x86-mont.S\
+ mac-x86/crypto/cpu-x86-asm.S\
+ mac-x86/crypto/md5/md5-586.S\
+ mac-x86/crypto/modes/ghash-x86.S\
+ mac-x86/crypto/rc4/rc4-586.S\
+ mac-x86/crypto/sha/sha1-586.S\
+ mac-x86/crypto/sha/sha256-586.S\
+ mac-x86/crypto/sha/sha512-586.S\
+
+mac_x86_64_sources := \
+ mac-x86_64/crypto/aes/aes-x86_64.S\
+ mac-x86_64/crypto/aes/aesni-x86_64.S\
+ mac-x86_64/crypto/aes/bsaes-x86_64.S\
+ mac-x86_64/crypto/aes/vpaes-x86_64.S\
+ mac-x86_64/crypto/bn/rsaz-avx2.S\
+ mac-x86_64/crypto/bn/rsaz-x86_64.S\
+ mac-x86_64/crypto/bn/x86_64-mont.S\
+ mac-x86_64/crypto/bn/x86_64-mont5.S\
+ mac-x86_64/crypto/cpu-x86_64-asm.S\
+ mac-x86_64/crypto/md5/md5-x86_64.S\
+ mac-x86_64/crypto/modes/aesni-gcm-x86_64.S\
+ mac-x86_64/crypto/modes/ghash-x86_64.S\
+ mac-x86_64/crypto/rc4/rc4-md5-x86_64.S\
+ mac-x86_64/crypto/rc4/rc4-x86_64.S\
+ mac-x86_64/crypto/sha/sha1-x86_64.S\
+ mac-x86_64/crypto/sha/sha256-x86_64.S\
+ mac-x86_64/crypto/sha/sha512-x86_64.S\
+
+win_x86_64_sources := \
+ win-x86_64/crypto/aes/aes-x86_64.asm\
+ win-x86_64/crypto/aes/aesni-x86_64.asm\
+ win-x86_64/crypto/aes/bsaes-x86_64.asm\
+ win-x86_64/crypto/aes/vpaes-x86_64.asm\
+ win-x86_64/crypto/bn/rsaz-avx2.asm\
+ win-x86_64/crypto/bn/rsaz-x86_64.asm\
+ win-x86_64/crypto/bn/x86_64-mont.asm\
+ win-x86_64/crypto/bn/x86_64-mont5.asm\
+ win-x86_64/crypto/cpu-x86_64-asm.asm\
+ win-x86_64/crypto/md5/md5-x86_64.asm\
+ win-x86_64/crypto/modes/aesni-gcm-x86_64.asm\
+ win-x86_64/crypto/modes/ghash-x86_64.asm\
+ win-x86_64/crypto/rc4/rc4-md5-x86_64.asm\
+ win-x86_64/crypto/rc4/rc4-x86_64.asm\
+ win-x86_64/crypto/sha/sha1-x86_64.asm\
+ win-x86_64/crypto/sha/sha256-x86_64.asm\
+ win-x86_64/crypto/sha/sha512-x86_64.asm\
+
diff --git a/src/.clang-format b/src/.clang-format
new file mode 100644
index 0000000..43032d4
--- /dev/null
+++ b/src/.clang-format
@@ -0,0 +1,4 @@
+BasedOnStyle: Google
+MaxEmptyLinesToKeep: 3
+AllowShortIfStatementsOnASingleLine: false
+AllowShortLoopsOnASingleLine: false
diff --git a/src/.gitignore b/src/.gitignore
new file mode 100644
index 0000000..b54125f
--- /dev/null
+++ b/src/.gitignore
@@ -0,0 +1,5 @@
+build/
+ssl/test/runner/runner
+*.swp
+*.swo
+doc/*.html
diff --git a/src/BUILDING b/src/BUILDING
new file mode 100644
index 0000000..18ddde1
--- /dev/null
+++ b/src/BUILDING
@@ -0,0 +1,81 @@
+Build Prerequisites:
+
+ * CMake[1] 2.8.8 or later is required.
+
+ * Perl 5.6.1 or later is required. On Windows, Strawberry Perl and MSYS Perl
+ have both been reported to work.
+
+ * On Windows you currently must use Ninja[2] to build; on other platforms,
+ it is not required, but recommended, because it makes builds faster.
+
+ * If you need to build Ninja from source, then a recent version of
+ Python[3] is required (Python 2.7.5 works).
+
+ * On Windows only, Yasm[4] is required.
+
+ * A C compiler is required. On Windows, MSVC 12 (Visual Studio 2013) or later
+ with Platform SDK 8.1 or later are supported. Recent versions of GCC and
+ Clang should work on non-Windows platforms, and maybe on Windows too.
+
+ * Bash is required for running some tests, but not for building.
+
+ * Go[5] is required for running some tests, but not for building. Note that
+ these tests do not work on Windows.
+
+Using Ninja (note the 'N' is capitalized in the cmake invocation):
+
+ mkdir build
+ cd build
+ cmake -GNinja ..
+ ninja
+
+Using makefiles (does not work on Windows):
+
+ mkdir build
+ cd build
+ cmake ..
+ make
+
+You usually don't need to run cmake again after changing CMakeLists.txt files
+because the build scripts will detect changes to them and rebuild themselves
+automatically.
+
+Note that the default build flags in the top-level CMakeLists.txt are for
+debugging - optimisation isn't enabled.
+
+If you want to cross-compile then there are example toolchain files for 32-bit
+Intel and ARM in util/. Wipe out the build directory, recreate it and run cmake
+like this:
+
+ cmake -DCMAKE_TOOLCHAIN_FILE=../util/arm-toolchain.cmake -GNinja ..
+
+If you want to build as a shared library, pass -DBUILD_SHARED_LIBS=1. On
+Windows, where functions need to be tagged with "dllimport" when coming from a
+shared library, define BORINGSSL_SHARED_LIBRARY in any code which #includes the
+BoringSSL headers.
+
+Known Limitations on Windows:
+
+ * Versions of cmake since 3.0.2 have a bug in its Ninja generator that causes
+ yasm to output warnings "yasm: warning: can open only one input file, only
+ the last file will be processed". These warnings can be safely ignored.
+ The cmake bug is http://www.cmake.org/Bug/view.php?id=15253.
+
+ * cmake can generate Visual Studio projects, but the generated project files
+ don't have steps for assembling the assembly language source files, so they
+ currently cannot be used to build BoringSSL.
+
+ * The tests written in Go do not work.
+
+[1] http://www.cmake.org/download/
+
+[2] https://martine.github.io/ninja/
+
+[3] https://www.python.org/downloads/
+
+[4] http://yasm.tortall.net/
+
+ Either ensure yasm.exe is in %PATH% or configure CMAKE_ASM_NASM_COMPILER
+ appropriately.
+
+[5] https://golang.org/dl/
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
new file mode 100644
index 0000000..9a61495
--- /dev/null
+++ b/src/CMakeLists.txt
@@ -0,0 +1,100 @@
+cmake_minimum_required (VERSION 2.8.10)
+
+project (BoringSSL)
+
+if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror -ggdb -fvisibility=hidden")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror -ggdb -std=c++0x -fvisibility=hidden")
+elseif(MSVC)
+ set(MSVC_DISABLED_WARNINGS_LIST
+ "C4100" # 'exarg' : unreferenced formal parameter
+ "C4127" # conditional expression is constant
+ "C4200" # nonstandard extension used : zero-sized array in
+ # struct/union.
+ "C4242" # 'function' : conversion from 'int' to 'uint8_t',
+ # possible loss of data
+ "C4244" # 'function' : conversion from 'int' to 'uint8_t',
+ # possible loss of data
+ "C4245" # 'initializing' : conversion from 'long' to
+ # 'unsigned long', signed/unsigned mismatch
+ "C4296" # '>=' : expression is always true
+ "C4350" # behavior change: 'std::_Wrap_alloc...'
+ "C4365" # '=' : conversion from 'size_t' to 'int',
+ # signed/unsigned mismatch
+ "C4389" # '!=' : signed/unsigned mismatch
+ "C4510" # 'argument' : default constructor could not be generated
+ "C4512" # 'argument' : assignment operator could not be generated
+ "C4514" # 'function': unreferenced inline function has been removed
+ "C4548" # expression before comma has no effect; expected expression with
+ # side-effect" caused by FD_* macros.
+ "C4610" # struct 'argument' can never be instantiated - user defined
+ # constructor required.
+ "C4701" # potentially uninitialized local variable 'mdlen' used
+ "C4706" # assignment within conditional expression
+ "C4710" # 'function': function not inlined
+ "C4711" # function 'function' selected for inline expansion
+ "C4800" # 'int' : forcing value to bool 'true' or 'false'
+ # (performance warning)
+ "C4820" # 'bytes' bytes padding added after construct 'member_name'
+ "C4996" # 'read': The POSIX name for this item is deprecated. Instead,
+ # use the ISO C++ conformant name: _read.
+ )
+ string(REPLACE "C" " -wd" MSVC_DISABLED_WARNINGS_STR
+ ${MSVC_DISABLED_WARNINGS_LIST})
+ set(CMAKE_C_FLAGS "-Wall -WX ${MSVC_DISABLED_WARNINGS_STR}")
+ set(CMAKE_CXX_FLAGS "-Wall -WX ${MSVC_DISABLED_WARNINGS_STR}")
+ add_definitions(-D_HAS_EXCEPTIONS=0)
+ add_definitions(-DWIN32_LEAN_AND_MEAN)
+endif()
+
+if((CMAKE_COMPILER_IS_GNUCXX AND CMAKE_C_COMPILER_VERSION VERSION_GREATER "4.5.99") OR
+ CMAKE_CXX_COMPILER_ID MATCHES "Clang")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wshadow")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wshadow")
+endif()
+
+add_definitions(-DBORINGSSL_IMPLEMENTATION)
+
+if (BUILD_SHARED_LIBS)
+ add_definitions(-DBORINGSSL_SHARED_LIBRARY)
+ # Enable position-independent code globally. This is needed because
+ # some library targets are OBJECT libraries.
+ set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)
+endif()
+
+if (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "x86_64")
+ set(ARCH "x86_64")
+elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "amd64")
+ set(ARCH "x86_64")
+elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "AMD64")
+ # cmake reports AMD64 on Windows, but we might be building for 32-bit.
+ if (CMAKE_CL_64)
+ set(ARCH "x86_64")
+ else()
+ set(ARCH "x86")
+ endif()
+elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "x86")
+ set(ARCH "x86")
+elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "i386")
+ set(ARCH "x86")
+elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "i686")
+ set(ARCH "x86")
+elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "arm")
+ set(ARCH "arm")
+elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "aarch64")
+ set(ARCH "aarch64")
+else()
+ message(FATAL_ERROR "Unknown processor:" ${CMAKE_SYSTEM_PROCESSOR})
+endif()
+
+if (${ARCH} STREQUAL "x86" AND APPLE)
+ # With CMake 2.8.x, ${CMAKE_SYSTEM_PROCESSOR} evalutes to i386 on OS X,
+ # but clang defaults to 64-bit builds on OS X unless otherwise told.
+ # Set ARCH to x86_64 so clang and CMake agree. This is fixed in CMake 3.
+ set(ARCH "x86_64")
+endif()
+
+add_subdirectory(crypto)
+add_subdirectory(ssl)
+add_subdirectory(ssl/test)
+add_subdirectory(tool)
diff --git a/src/codereview.settings b/src/codereview.settings
new file mode 100644
index 0000000..1e123a1
--- /dev/null
+++ b/src/codereview.settings
@@ -0,0 +1,4 @@
+# This file is used by gcl to get repository specific information.
+GERRIT_HOST: True
+GERRIT_PORT: True
+CODE_REVIEW_SERVER: https://boringssl-review.googlesource.com
diff --git a/src/crypto/CMakeLists.txt b/src/crypto/CMakeLists.txt
new file mode 100644
index 0000000..cb8f63a
--- /dev/null
+++ b/src/crypto/CMakeLists.txt
@@ -0,0 +1,198 @@
+include_directories(. ../include)
+
+if(APPLE)
+ if (${ARCH} STREQUAL "x86")
+ set(PERLASM_FLAGS "-fPIC")
+ endif()
+ set(PERLASM_STYLE macosx)
+ set(ASM_EXT S)
+ enable_language(ASM)
+elseif(UNIX)
+ if (${ARCH} STREQUAL "aarch64")
+ # The "armx" Perl scripts look for "64" in the style argument
+ # in order to decide whether to generate 32- or 64-bit asm.
+ set(PERLASM_STYLE linux64)
+ elseif (${ARCH} STREQUAL "x86")
+ set(PERLASM_FLAGS "-fPIC")
+ set(PERLASM_STYLE elf)
+ else()
+ set(PERLASM_STYLE elf)
+ endif()
+ set(ASM_EXT S)
+ enable_language(ASM)
+else()
+ if (CMAKE_CL_64)
+ message("Using nasm")
+ set(PERLASM_STYLE nasm)
+ else()
+ message("Using win32n")
+ set(PERLASM_STYLE win32n)
+ endif()
+
+ # On Windows, we use the NASM output, specifically built with Yasm.
+ set(ASM_EXT asm)
+ enable_language(ASM_NASM)
+endif()
+
+function(perlasm dest src)
+ add_custom_command(
+ OUTPUT ${dest}
+ COMMAND perl ${CMAKE_CURRENT_SOURCE_DIR}/${src} ${PERLASM_STYLE} ${PERLASM_FLAGS} ${ARGN} > ${dest}
+ DEPENDS
+ ${src}
+ ${PROJECT_SOURCE_DIR}/crypto/perlasm/x86_64-xlate.pl
+ ${PROJECT_SOURCE_DIR}/crypto/perlasm/x86asm.pl
+ ${PROJECT_SOURCE_DIR}/crypto/perlasm/x86gas.pl
+ ${PROJECT_SOURCE_DIR}/crypto/perlasm/x86masm.pl
+ ${PROJECT_SOURCE_DIR}/crypto/perlasm/x86nasm.pl
+ WORKING_DIRECTORY .
+ )
+endfunction()
+
+if (${ARCH} STREQUAL "x86_64")
+ set(
+ CRYPTO_ARCH_SOURCES
+
+ cpu-x86_64-asm.${ASM_EXT}
+ cpu-intel.c
+ )
+endif()
+
+if (${ARCH} STREQUAL "x86")
+ set(
+ CRYPTO_ARCH_SOURCES
+
+ cpu-x86-asm.${ASM_EXT}
+ cpu-intel.c
+ )
+endif()
+
+if (${ARCH} STREQUAL "arm")
+ set(
+ CRYPTO_ARCH_SOURCES
+
+ cpu-arm.c
+ )
+endif()
+
+if (${ARCH} STREQUAL "aarch64")
+ set(
+ CRYPTO_ARCH_SOURCES
+
+ cpu-arm.c
+ )
+endif()
+
+# Level 0.1 - depends on nothing outside this set.
+add_subdirectory(stack)
+add_subdirectory(lhash)
+add_subdirectory(err)
+add_subdirectory(buf)
+add_subdirectory(base64)
+add_subdirectory(bytestring)
+
+# Level 0.2 - depends on nothing but itself
+add_subdirectory(sha)
+add_subdirectory(md4)
+add_subdirectory(md5)
+add_subdirectory(modes)
+add_subdirectory(aes)
+add_subdirectory(des)
+add_subdirectory(rc4)
+add_subdirectory(conf)
+add_subdirectory(chacha)
+add_subdirectory(poly1305)
+
+# Level 1, depends only on 0.*
+add_subdirectory(digest)
+add_subdirectory(cipher)
+add_subdirectory(rand)
+add_subdirectory(bio)
+add_subdirectory(bn)
+add_subdirectory(obj)
+add_subdirectory(asn1)
+
+# Level 2
+add_subdirectory(engine)
+add_subdirectory(dh)
+add_subdirectory(dsa)
+add_subdirectory(rsa)
+add_subdirectory(ec)
+add_subdirectory(ecdh)
+add_subdirectory(ecdsa)
+add_subdirectory(hmac)
+
+# Level 3
+add_subdirectory(evp)
+add_subdirectory(hkdf)
+add_subdirectory(pem)
+add_subdirectory(x509)
+add_subdirectory(x509v3)
+
+# Level 4
+add_subdirectory(pkcs8)
+
+add_library(
+ crypto
+
+ crypto.c
+ crypto_error.c
+ mem.c
+ thread.c
+ ex_data.c
+ ex_data_impl.c
+ time_support.c
+ directory_posix.c
+ directory_win.c
+
+ ${CRYPTO_ARCH_SOURCES}
+
+ $<TARGET_OBJECTS:stack>
+ $<TARGET_OBJECTS:lhash>
+ $<TARGET_OBJECTS:err>
+ $<TARGET_OBJECTS:base64>
+ $<TARGET_OBJECTS:bytestring>
+ $<TARGET_OBJECTS:sha>
+ $<TARGET_OBJECTS:md4>
+ $<TARGET_OBJECTS:md5>
+ $<TARGET_OBJECTS:digest>
+ $<TARGET_OBJECTS:cipher>
+ $<TARGET_OBJECTS:modes>
+ $<TARGET_OBJECTS:aes>
+ $<TARGET_OBJECTS:des>
+ $<TARGET_OBJECTS:rc4>
+ $<TARGET_OBJECTS:conf>
+ $<TARGET_OBJECTS:chacha>
+ $<TARGET_OBJECTS:poly1305>
+ $<TARGET_OBJECTS:buf>
+ $<TARGET_OBJECTS:bn>
+ $<TARGET_OBJECTS:bio>
+ $<TARGET_OBJECTS:rand>
+ $<TARGET_OBJECTS:obj>
+ $<TARGET_OBJECTS:asn1>
+ $<TARGET_OBJECTS:engine>
+ $<TARGET_OBJECTS:dh>
+ $<TARGET_OBJECTS:dsa>
+ $<TARGET_OBJECTS:rsa>
+ $<TARGET_OBJECTS:ec>
+ $<TARGET_OBJECTS:ecdh>
+ $<TARGET_OBJECTS:ecdsa>
+ $<TARGET_OBJECTS:hmac>
+ $<TARGET_OBJECTS:evp>
+ $<TARGET_OBJECTS:hkdf>
+ $<TARGET_OBJECTS:pem>
+ $<TARGET_OBJECTS:x509>
+ $<TARGET_OBJECTS:x509v3>
+ $<TARGET_OBJECTS:pkcs8>
+)
+
+add_executable(
+ constant_time_test
+
+ constant_time_test.c
+)
+
+target_link_libraries(constant_time_test crypto)
+
+perlasm(cpu-x86_64-asm.${ASM_EXT} cpu-x86_64-asm.pl)
+perlasm(cpu-x86-asm.${ASM_EXT} cpu-x86-asm.pl)
diff --git a/src/crypto/aes/CMakeLists.txt b/src/crypto/aes/CMakeLists.txt
new file mode 100644
index 0000000..490f40a
--- /dev/null
+++ b/src/crypto/aes/CMakeLists.txt
@@ -0,0 +1,62 @@
+include_directories(. .. ../../include)
+
+if (${ARCH} STREQUAL "x86_64")
+ set(
+ AES_ARCH_SOURCES
+
+ aes-x86_64.${ASM_EXT}
+ aesni-x86_64.${ASM_EXT}
+ bsaes-x86_64.${ASM_EXT}
+ vpaes-x86_64.${ASM_EXT}
+ )
+endif()
+
+if (${ARCH} STREQUAL "x86")
+ set(
+ AES_ARCH_SOURCES
+
+ aes-586.${ASM_EXT}
+ vpaes-x86.${ASM_EXT}
+ aesni-x86.${ASM_EXT}
+ )
+endif()
+
+if (${ARCH} STREQUAL "arm")
+ set(
+ AES_ARCH_SOURCES
+
+ aes-armv4.${ASM_EXT}
+ bsaes-armv7.${ASM_EXT}
+ aesv8-armx.${ASM_EXT}
+ )
+endif()
+
+if (${ARCH} STREQUAL "aarch64")
+ set(
+ AES_ARCH_SOURCES
+
+ aesv8-armx.${ASM_EXT}
+ )
+endif()
+
+add_library(
+ aes
+
+ OBJECT
+
+ aes.c
+ mode_wrappers.c
+
+ ${AES_ARCH_SOURCES}
+)
+
+perlasm(aes-x86_64.${ASM_EXT} asm/aes-x86_64.pl)
+perlasm(aesni-x86_64.${ASM_EXT} asm/aesni-x86_64.pl)
+perlasm(bsaes-x86_64.${ASM_EXT} asm/bsaes-x86_64.pl)
+perlasm(vpaes-x86_64.${ASM_EXT} asm/vpaes-x86_64.pl)
+perlasm(aes-586.${ASM_EXT} asm/aes-586.pl)
+perlasm(vpaes-x86.${ASM_EXT} asm/vpaes-x86.pl)
+perlasm(aesni-x86.${ASM_EXT} asm/aesni-x86.pl)
+perlasm(aes-armv4.${ASM_EXT} asm/aes-armv4.pl)
+perlasm(bsaes-armv7.${ASM_EXT} asm/bsaes-armv7.pl)
+perlasm(aesv8-armx.${ASM_EXT} asm/aesv8-armx.pl)
diff --git a/src/crypto/aes/aes.c b/src/crypto/aes/aes.c
new file mode 100644
index 0000000..97b4fbd
--- /dev/null
+++ b/src/crypto/aes/aes.c
@@ -0,0 +1,1077 @@
+/* ====================================================================
+ * 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 <openssl/aes.h>
+
+#include <assert.h>
+
+#include "internal.h"
+
+
+#if defined(OPENSSL_NO_ASM) || \
+ (!defined(OPENSSL_X86) && !defined(OPENSSL_X86_64) && !defined(OPENSSL_ARM))
+
+/* 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 uint32_t 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 uint32_t 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 uint32_t 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 uint32_t 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 uint32_t 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 uint32_t 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 uint32_t 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 uint32_t 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 uint8_t 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 uint32_t rcon[] = {
+ 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000,
+ 0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000,
+ /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
+};
+
+int AES_set_encrypt_key(const uint8_t *key, unsigned bits, AES_KEY *aeskey) {
+ uint32_t *rk;
+ int i = 0;
+ uint32_t temp;
+
+ if (!key || !aeskey) {
+ return -1;
+ }
+
+ switch (bits) {
+ case 128:
+ aeskey->rounds = 10;
+ break;
+ case 192:
+ aeskey->rounds = 12;
+ break;
+ case 256:
+ aeskey->rounds = 14;
+ break;
+ default:
+ return -2;
+ }
+
+ rk = aeskey->rd_key;
+
+ rk[0] = GETU32(key);
+ rk[1] = GETU32(key + 4);
+ rk[2] = GETU32(key + 8);
+ rk[3] = GETU32(key + 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(key + 16);
+ rk[5] = GETU32(key + 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(key + 24);
+ rk[7] = GETU32(key + 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;
+}
+
+int AES_set_decrypt_key(const uint8_t *key, unsigned bits, AES_KEY *aeskey) {
+ uint32_t *rk;
+ int i, j, status;
+ uint32_t temp;
+
+ /* first, start with an encryption schedule */
+ status = AES_set_encrypt_key(key, bits, aeskey);
+ if (status < 0) {
+ return status;
+ }
+
+ rk = aeskey->rd_key;
+
+ /* invert the order of the round keys: */
+ for (i = 0, j = 4 * aeskey->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 < (int)aeskey->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;
+}
+
+void AES_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) {
+ const uint32_t *rk;
+ uint32_t s0, s1, s2, s3, t0, t1, t2, t3;
+#ifndef FULL_UNROLL
+ int r;
+#endif /* ?FULL_UNROLL */
+
+ assert(in && out && key);
+ 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);
+}
+
+void AES_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) {
+ const uint32_t *rk;
+ uint32_t s0, s1, s2, s3, t0, t1, t2, t3;
+#ifndef FULL_UNROLL
+ int r;
+#endif /* ?FULL_UNROLL */
+
+ assert(in && out && key);
+ 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 = (Td4[(t0 >> 24)] << 24) ^ (Td4[(t3 >> 16) & 0xff] << 16) ^
+ (Td4[(t2 >> 8) & 0xff] << 8) ^ (Td4[(t1) & 0xff]) ^ rk[0];
+ PUTU32(out, s0);
+ s1 = (Td4[(t1 >> 24)] << 24) ^ (Td4[(t0 >> 16) & 0xff] << 16) ^
+ (Td4[(t3 >> 8) & 0xff] << 8) ^ (Td4[(t2) & 0xff]) ^ rk[1];
+ PUTU32(out + 4, s1);
+ s2 = (Td4[(t2 >> 24)] << 24) ^ (Td4[(t1 >> 16) & 0xff] << 16) ^
+ (Td4[(t0 >> 8) & 0xff] << 8) ^ (Td4[(t3) & 0xff]) ^ rk[2];
+ PUTU32(out + 8, s2);
+ s3 = (Td4[(t3 >> 24)] << 24) ^ (Td4[(t2 >> 16) & 0xff] << 16) ^
+ (Td4[(t1 >> 8) & 0xff] << 8) ^ (Td4[(t0) & 0xff]) ^ rk[3];
+ PUTU32(out + 12, s3);
+}
+
+#else
+
+/* In this case several functions are provided by asm code. However, one cannot
+ * control asm symbol visibility with command line flags and such so they are
+ * always hidden and wrapped by these C functions, which can be so
+ * controlled. */
+
+void asm_AES_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key);
+void AES_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) {
+ asm_AES_encrypt(in, out, key);
+}
+
+void asm_AES_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key);
+void AES_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) {
+ asm_AES_decrypt(in, out, key);
+}
+
+int asm_AES_set_encrypt_key(const uint8_t *key, unsigned bits, AES_KEY *aeskey);
+int AES_set_encrypt_key(const uint8_t *key, unsigned bits, AES_KEY *aeskey) {
+ return asm_AES_set_encrypt_key(key, bits, aeskey);
+}
+
+int asm_AES_set_decrypt_key(const uint8_t *key, unsigned bits, AES_KEY *aeskey);
+int AES_set_decrypt_key(const uint8_t *key, unsigned bits, AES_KEY *aeskey) {
+ return asm_AES_set_decrypt_key(key, bits, aeskey);
+}
+
+#endif /* OPENSSL_NO_ASM || (!OPENSSL_X86 && !OPENSSL_X86_64 && !OPENSSL_ARM) */
diff --git a/src/crypto/aes/asm/aes-586.pl b/src/crypto/aes/asm/aes-586.pl
new file mode 100755
index 0000000..07fb94c
--- /dev/null
+++ b/src/crypto/aes/asm/aes-586.pl
@@ -0,0 +1,2987 @@
+#!/usr/bin/env perl
+#
+# ====================================================================
+# Written by Andy Polyakov <appro@fy.chalmers.se> for the OpenSSL
+# project. The module is, however, dual licensed under OpenSSL and
+# CRYPTOGAMS licenses depending on where you obtain it. For further
+# details see http://www.openssl.org/~appro/cryptogams/.
+# ====================================================================
+#
+# Version 4.3.
+#
+# You might fail to appreciate this module performance from the first
+# try. If compared to "vanilla" linux-ia32-icc target, i.e. considered
+# to be *the* best Intel C compiler without -KPIC, performance appears
+# to be virtually identical... But try to re-configure with shared
+# library support... Aha! Intel compiler "suddenly" lags behind by 30%
+# [on P4, more on others]:-) And if compared to position-independent
+# code generated by GNU C, this code performs *more* than *twice* as
+# fast! Yes, all this buzz about PIC means that unlike other hand-
+# coded implementations, this one was explicitly designed to be safe
+# to use even in shared library context... This also means that this
+# code isn't necessarily absolutely fastest "ever," because in order
+# to achieve position independence an extra register has to be
+# off-loaded to stack, which affects the benchmark result.
+#
+# Special note about instruction choice. Do you recall RC4_INT code
+# performing poorly on P4? It might be the time to figure out why.
+# RC4_INT code implies effective address calculations in base+offset*4
+# form. Trouble is that it seems that offset scaling turned to be
+# critical path... At least eliminating scaling resulted in 2.8x RC4
+# performance improvement [as you might recall]. As AES code is hungry
+# for scaling too, I [try to] avoid the latter by favoring off-by-2
+# shifts and masking the result with 0xFF<<2 instead of "boring" 0xFF.
+#
+# As was shown by Dean Gaudet <dean@arctic.org>, the above note turned
+# void. Performance improvement with off-by-2 shifts was observed on
+# intermediate implementation, which was spilling yet another register
+# to stack... Final offset*4 code below runs just a tad faster on P4,
+# but exhibits up to 10% improvement on other cores.
+#
+# Second version is "monolithic" replacement for aes_core.c, which in
+# addition to AES_[de|en]crypt implements AES_set_[de|en]cryption_key.
+# This made it possible to implement little-endian variant of the
+# algorithm without modifying the base C code. Motivating factor for
+# the undertaken effort was that it appeared that in tight IA-32
+# register window little-endian flavor could achieve slightly higher
+# Instruction Level Parallelism, and it indeed resulted in up to 15%
+# better performance on most recent µ-archs...
+#
+# Third version adds AES_cbc_encrypt implementation, which resulted in
+# up to 40% performance imrovement of CBC benchmark results. 40% was
+# observed on P4 core, where "overall" imrovement coefficient, i.e. if
+# compared to PIC generated by GCC and in CBC mode, was observed to be
+# as large as 4x:-) CBC performance is virtually identical to ECB now
+# and on some platforms even better, e.g. 17.6 "small" cycles/byte on
+# Opteron, because certain function prologues and epilogues are
+# effectively taken out of the loop...
+#
+# Version 3.2 implements compressed tables and prefetch of these tables
+# in CBC[!] mode. Former means that 3/4 of table references are now
+# misaligned, which unfortunately has negative impact on elder IA-32
+# implementations, Pentium suffered 30% penalty, PIII - 10%.
+#
+# Version 3.3 avoids L1 cache aliasing between stack frame and
+# S-boxes, and 3.4 - L1 cache aliasing even between key schedule. The
+# latter is achieved by copying the key schedule to controlled place in
+# stack. This unfortunately has rather strong impact on small block CBC
+# performance, ~2x deterioration on 16-byte block if compared to 3.3.
+#
+# Version 3.5 checks if there is L1 cache aliasing between user-supplied
+# key schedule and S-boxes and abstains from copying the former if
+# there is no. This allows end-user to consciously retain small block
+# performance by aligning key schedule in specific manner.
+#
+# Version 3.6 compresses Td4 to 256 bytes and prefetches it in ECB.
+#
+# Current ECB performance numbers for 128-bit key in CPU cycles per
+# processed byte [measure commonly used by AES benchmarkers] are:
+#
+# small footprint fully unrolled
+# P4 24 22
+# AMD K8 20 19
+# PIII 25 23
+# Pentium 81 78
+#
+# Version 3.7 reimplements outer rounds as "compact." Meaning that
+# first and last rounds reference compact 256 bytes S-box. This means
+# that first round consumes a lot more CPU cycles and that encrypt
+# and decrypt performance becomes asymmetric. Encrypt performance
+# drops by 10-12%, while decrypt - by 20-25%:-( 256 bytes S-box is
+# aggressively pre-fetched.
+#
+# Version 4.0 effectively rolls back to 3.6 and instead implements
+# additional set of functions, _[x86|sse]_AES_[en|de]crypt_compact,
+# which use exclusively 256 byte S-box. These functions are to be
+# called in modes not concealing plain text, such as ECB, or when
+# we're asked to process smaller amount of data [or unconditionally
+# on hyper-threading CPU]. Currently it's called unconditionally from
+# AES_[en|de]crypt, which affects all modes, but CBC. CBC routine
+# still needs to be modified to switch between slower and faster
+# mode when appropriate... But in either case benchmark landscape
+# changes dramatically and below numbers are CPU cycles per processed
+# byte for 128-bit key.
+#
+# ECB encrypt ECB decrypt CBC large chunk
+# P4 52[54] 83[95] 23
+# AMD K8 46[41] 66[70] 18
+# PIII 41[50] 60[77] 24
+# Core 2 31[36] 45[64] 18.5
+# Atom 76[100] 96[138] 60
+# Pentium 115 150 77
+#
+# Version 4.1 switches to compact S-box even in key schedule setup.
+#
+# Version 4.2 prefetches compact S-box in every SSE round or in other
+# words every cache-line is *guaranteed* to be accessed within ~50
+# cycles window. Why just SSE? Because it's needed on hyper-threading
+# CPU! Which is also why it's prefetched with 64 byte stride. Best
+# part is that it has no negative effect on performance:-)
+#
+# Version 4.3 implements switch between compact and non-compact block
+# functions in AES_cbc_encrypt depending on how much data was asked
+# to be processed in one stroke.
+#
+######################################################################
+# Timing attacks are classified in two classes: synchronous when
+# attacker consciously initiates cryptographic operation and collects
+# timing data of various character afterwards, and asynchronous when
+# malicious code is executed on same CPU simultaneously with AES,
+# instruments itself and performs statistical analysis of this data.
+#
+# As far as synchronous attacks go the root to the AES timing
+# vulnerability is twofold. Firstly, of 256 S-box elements at most 160
+# are referred to in single 128-bit block operation. Well, in C
+# implementation with 4 distinct tables it's actually as little as 40
+# references per 256 elements table, but anyway... Secondly, even
+# though S-box elements are clustered into smaller amount of cache-
+# lines, smaller than 160 and even 40, it turned out that for certain
+# plain-text pattern[s] or simply put chosen plain-text and given key
+# few cache-lines remain unaccessed during block operation. Now, if
+# attacker can figure out this access pattern, he can deduct the key
+# [or at least part of it]. The natural way to mitigate this kind of
+# attacks is to minimize the amount of cache-lines in S-box and/or
+# prefetch them to ensure that every one is accessed for more uniform
+# timing. But note that *if* plain-text was concealed in such way that
+# input to block function is distributed *uniformly*, then attack
+# wouldn't apply. Now note that some encryption modes, most notably
+# CBC, do mask the plain-text in this exact way [secure cipher output
+# is distributed uniformly]. Yes, one still might find input that
+# would reveal the information about given key, but if amount of
+# candidate inputs to be tried is larger than amount of possible key
+# combinations then attack becomes infeasible. This is why revised
+# AES_cbc_encrypt "dares" to switch to larger S-box when larger chunk
+# of data is to be processed in one stroke. The current size limit of
+# 512 bytes is chosen to provide same [diminishigly low] probability
+# for cache-line to remain untouched in large chunk operation with
+# large S-box as for single block operation with compact S-box and
+# surely needs more careful consideration...
+#
+# As for asynchronous attacks. There are two flavours: attacker code
+# being interleaved with AES on hyper-threading CPU at *instruction*
+# level, and two processes time sharing single core. As for latter.
+# Two vectors. 1. Given that attacker process has higher priority,
+# yield execution to process performing AES just before timer fires
+# off the scheduler, immediately regain control of CPU and analyze the
+# cache state. For this attack to be efficient attacker would have to
+# effectively slow down the operation by several *orders* of magnitute,
+# by ratio of time slice to duration of handful of AES rounds, which
+# unlikely to remain unnoticed. Not to mention that this also means
+# that he would spend correspondigly more time to collect enough
+# statistical data to mount the attack. It's probably appropriate to
+# say that if adeversary reckons that this attack is beneficial and
+# risks to be noticed, you probably have larger problems having him
+# mere opportunity. In other words suggested code design expects you
+# to preclude/mitigate this attack by overall system security design.
+# 2. Attacker manages to make his code interrupt driven. In order for
+# this kind of attack to be feasible, interrupt rate has to be high
+# enough, again comparable to duration of handful of AES rounds. But
+# is there interrupt source of such rate? Hardly, not even 1Gbps NIC
+# generates interrupts at such raging rate...
+#
+# And now back to the former, hyper-threading CPU or more specifically
+# Intel P4. Recall that asynchronous attack implies that malicious
+# code instruments itself. And naturally instrumentation granularity
+# has be noticeably lower than duration of codepath accessing S-box.
+# Given that all cache-lines are accessed during that time that is.
+# Current implementation accesses *all* cache-lines within ~50 cycles
+# window, which is actually *less* than RDTSC latency on Intel P4!
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+push(@INC,"${dir}","${dir}../../perlasm");
+require "x86asm.pl";
+
+&asm_init($ARGV[0],"aes-586.pl",$x86only = $ARGV[$#ARGV] eq "386");
+&static_label("AES_Te");
+&static_label("AES_Td");
+
+$s0="eax";
+$s1="ebx";
+$s2="ecx";
+$s3="edx";
+$key="edi";
+$acc="esi";
+$tbl="ebp";
+
+# stack frame layout in _[x86|sse]_AES_* routines, frame is allocated
+# by caller
+$__ra=&DWP(0,"esp"); # return address
+$__s0=&DWP(4,"esp"); # s0 backing store
+$__s1=&DWP(8,"esp"); # s1 backing store
+$__s2=&DWP(12,"esp"); # s2 backing store
+$__s3=&DWP(16,"esp"); # s3 backing store
+$__key=&DWP(20,"esp"); # pointer to key schedule
+$__end=&DWP(24,"esp"); # pointer to end of key schedule
+$__tbl=&DWP(28,"esp"); # %ebp backing store
+
+# stack frame layout in AES_[en|crypt] routines, which differs from
+# above by 4 and overlaps by %ebp backing store
+$_tbl=&DWP(24,"esp");
+$_esp=&DWP(28,"esp");
+
+sub _data_word() { my $i; while(defined($i=shift)) { &data_word($i,$i); } }
+
+$speed_limit=512; # chunks smaller than $speed_limit are
+ # processed with compact routine in CBC mode
+$small_footprint=1; # $small_footprint=1 code is ~5% slower [on
+ # recent µ-archs], but ~5 times smaller!
+ # I favor compact code to minimize cache
+ # contention and in hope to "collect" 5% back
+ # in real-life applications...
+
+$vertical_spin=0; # shift "verticaly" defaults to 0, because of
+ # its proof-of-concept status...
+# Note that there is no decvert(), as well as last encryption round is
+# performed with "horizontal" shifts. This is because this "vertical"
+# implementation [one which groups shifts on a given $s[i] to form a
+# "column," unlike "horizontal" one, which groups shifts on different
+# $s[i] to form a "row"] is work in progress. It was observed to run
+# few percents faster on Intel cores, but not AMD. On AMD K8 core it's
+# whole 12% slower:-( So we face a trade-off... Shall it be resolved
+# some day? Till then the code is considered experimental and by
+# default remains dormant...
+
+sub encvert()
+{ my ($te,@s) = @_;
+ my ($v0,$v1) = ($acc,$key);
+
+ &mov ($v0,$s[3]); # copy s3
+ &mov (&DWP(4,"esp"),$s[2]); # save s2
+ &mov ($v1,$s[0]); # copy s0
+ &mov (&DWP(8,"esp"),$s[1]); # save s1
+
+ &movz ($s[2],&HB($s[0]));
+ &and ($s[0],0xFF);
+ &mov ($s[0],&DWP(0,$te,$s[0],8)); # s0>>0
+ &shr ($v1,16);
+ &mov ($s[3],&DWP(3,$te,$s[2],8)); # s0>>8
+ &movz ($s[1],&HB($v1));
+ &and ($v1,0xFF);
+ &mov ($s[2],&DWP(2,$te,$v1,8)); # s0>>16
+ &mov ($v1,$v0);
+ &mov ($s[1],&DWP(1,$te,$s[1],8)); # s0>>24
+
+ &and ($v0,0xFF);
+ &xor ($s[3],&DWP(0,$te,$v0,8)); # s3>>0
+ &movz ($v0,&HB($v1));
+ &shr ($v1,16);
+ &xor ($s[2],&DWP(3,$te,$v0,8)); # s3>>8
+ &movz ($v0,&HB($v1));
+ &and ($v1,0xFF);
+ &xor ($s[1],&DWP(2,$te,$v1,8)); # s3>>16
+ &mov ($v1,&DWP(4,"esp")); # restore s2
+ &xor ($s[0],&DWP(1,$te,$v0,8)); # s3>>24
+
+ &mov ($v0,$v1);
+ &and ($v1,0xFF);
+ &xor ($s[2],&DWP(0,$te,$v1,8)); # s2>>0
+ &movz ($v1,&HB($v0));
+ &shr ($v0,16);
+ &xor ($s[1],&DWP(3,$te,$v1,8)); # s2>>8
+ &movz ($v1,&HB($v0));
+ &and ($v0,0xFF);
+ &xor ($s[0],&DWP(2,$te,$v0,8)); # s2>>16
+ &mov ($v0,&DWP(8,"esp")); # restore s1
+ &xor ($s[3],&DWP(1,$te,$v1,8)); # s2>>24
+
+ &mov ($v1,$v0);
+ &and ($v0,0xFF);
+ &xor ($s[1],&DWP(0,$te,$v0,8)); # s1>>0
+ &movz ($v0,&HB($v1));
+ &shr ($v1,16);
+ &xor ($s[0],&DWP(3,$te,$v0,8)); # s1>>8
+ &movz ($v0,&HB($v1));
+ &and ($v1,0xFF);
+ &xor ($s[3],&DWP(2,$te,$v1,8)); # s1>>16
+ &mov ($key,$__key); # reincarnate v1 as key
+ &xor ($s[2],&DWP(1,$te,$v0,8)); # s1>>24
+}
+
+# Another experimental routine, which features "horizontal spin," but
+# eliminates one reference to stack. Strangely enough runs slower...
+sub enchoriz()
+{ my ($v0,$v1) = ($key,$acc);
+
+ &movz ($v0,&LB($s0)); # 3, 2, 1, 0*
+ &rotr ($s2,8); # 8,11,10, 9
+ &mov ($v1,&DWP(0,$te,$v0,8)); # 0
+ &movz ($v0,&HB($s1)); # 7, 6, 5*, 4
+ &rotr ($s3,16); # 13,12,15,14
+ &xor ($v1,&DWP(3,$te,$v0,8)); # 5
+ &movz ($v0,&HB($s2)); # 8,11,10*, 9
+ &rotr ($s0,16); # 1, 0, 3, 2
+ &xor ($v1,&DWP(2,$te,$v0,8)); # 10
+ &movz ($v0,&HB($s3)); # 13,12,15*,14
+ &xor ($v1,&DWP(1,$te,$v0,8)); # 15, t[0] collected
+ &mov ($__s0,$v1); # t[0] saved
+
+ &movz ($v0,&LB($s1)); # 7, 6, 5, 4*
+ &shr ($s1,16); # -, -, 7, 6
+ &mov ($v1,&DWP(0,$te,$v0,8)); # 4
+ &movz ($v0,&LB($s3)); # 13,12,15,14*
+ &xor ($v1,&DWP(2,$te,$v0,8)); # 14
+ &movz ($v0,&HB($s0)); # 1, 0, 3*, 2
+ &and ($s3,0xffff0000); # 13,12, -, -
+ &xor ($v1,&DWP(1,$te,$v0,8)); # 3
+ &movz ($v0,&LB($s2)); # 8,11,10, 9*
+ &or ($s3,$s1); # 13,12, 7, 6
+ &xor ($v1,&DWP(3,$te,$v0,8)); # 9, t[1] collected
+ &mov ($s1,$v1); # s[1]=t[1]
+
+ &movz ($v0,&LB($s0)); # 1, 0, 3, 2*
+ &shr ($s2,16); # -, -, 8,11
+ &mov ($v1,&DWP(2,$te,$v0,8)); # 2
+ &movz ($v0,&HB($s3)); # 13,12, 7*, 6
+ &xor ($v1,&DWP(1,$te,$v0,8)); # 7
+ &movz ($v0,&HB($s2)); # -, -, 8*,11
+ &xor ($v1,&DWP(0,$te,$v0,8)); # 8
+ &mov ($v0,$s3);
+ &shr ($v0,24); # 13
+ &xor ($v1,&DWP(3,$te,$v0,8)); # 13, t[2] collected
+
+ &movz ($v0,&LB($s2)); # -, -, 8,11*
+ &shr ($s0,24); # 1*
+ &mov ($s2,&DWP(1,$te,$v0,8)); # 11
+ &xor ($s2,&DWP(3,$te,$s0,8)); # 1
+ &mov ($s0,$__s0); # s[0]=t[0]
+ &movz ($v0,&LB($s3)); # 13,12, 7, 6*
+ &shr ($s3,16); # , ,13,12
+ &xor ($s2,&DWP(2,$te,$v0,8)); # 6
+ &mov ($key,$__key); # reincarnate v0 as key
+ &and ($s3,0xff); # , ,13,12*
+ &mov ($s3,&DWP(0,$te,$s3,8)); # 12
+ &xor ($s3,$s2); # s[2]=t[3] collected
+ &mov ($s2,$v1); # s[2]=t[2]
+}
+
+# More experimental code... SSE one... Even though this one eliminates
+# *all* references to stack, it's not faster...
+sub sse_encbody()
+{
+ &movz ($acc,&LB("eax")); # 0
+ &mov ("ecx",&DWP(0,$tbl,$acc,8)); # 0
+ &pshufw ("mm2","mm0",0x0d); # 7, 6, 3, 2
+ &movz ("edx",&HB("eax")); # 1
+ &mov ("edx",&DWP(3,$tbl,"edx",8)); # 1
+ &shr ("eax",16); # 5, 4
+
+ &movz ($acc,&LB("ebx")); # 10
+ &xor ("ecx",&DWP(2,$tbl,$acc,8)); # 10
+ &pshufw ("mm6","mm4",0x08); # 13,12, 9, 8
+ &movz ($acc,&HB("ebx")); # 11
+ &xor ("edx",&DWP(1,$tbl,$acc,8)); # 11
+ &shr ("ebx",16); # 15,14
+
+ &movz ($acc,&HB("eax")); # 5
+ &xor ("ecx",&DWP(3,$tbl,$acc,8)); # 5
+ &movq ("mm3",QWP(16,$key));
+ &movz ($acc,&HB("ebx")); # 15
+ &xor ("ecx",&DWP(1,$tbl,$acc,8)); # 15
+ &movd ("mm0","ecx"); # t[0] collected
+
+ &movz ($acc,&LB("eax")); # 4
+ &mov ("ecx",&DWP(0,$tbl,$acc,8)); # 4
+ &movd ("eax","mm2"); # 7, 6, 3, 2
+ &movz ($acc,&LB("ebx")); # 14
+ &xor ("ecx",&DWP(2,$tbl,$acc,8)); # 14
+ &movd ("ebx","mm6"); # 13,12, 9, 8
+
+ &movz ($acc,&HB("eax")); # 3
+ &xor ("ecx",&DWP(1,$tbl,$acc,8)); # 3
+ &movz ($acc,&HB("ebx")); # 9
+ &xor ("ecx",&DWP(3,$tbl,$acc,8)); # 9
+ &movd ("mm1","ecx"); # t[1] collected
+
+ &movz ($acc,&LB("eax")); # 2
+ &mov ("ecx",&DWP(2,$tbl,$acc,8)); # 2
+ &shr ("eax",16); # 7, 6
+ &punpckldq ("mm0","mm1"); # t[0,1] collected
+ &movz ($acc,&LB("ebx")); # 8
+ &xor ("ecx",&DWP(0,$tbl,$acc,8)); # 8
+ &shr ("ebx",16); # 13,12
+
+ &movz ($acc,&HB("eax")); # 7
+ &xor ("ecx",&DWP(1,$tbl,$acc,8)); # 7
+ &pxor ("mm0","mm3");
+ &movz ("eax",&LB("eax")); # 6
+ &xor ("edx",&DWP(2,$tbl,"eax",8)); # 6
+ &pshufw ("mm1","mm0",0x08); # 5, 4, 1, 0
+ &movz ($acc,&HB("ebx")); # 13
+ &xor ("ecx",&DWP(3,$tbl,$acc,8)); # 13
+ &xor ("ecx",&DWP(24,$key)); # t[2]
+ &movd ("mm4","ecx"); # t[2] collected
+ &movz ("ebx",&LB("ebx")); # 12
+ &xor ("edx",&DWP(0,$tbl,"ebx",8)); # 12
+ &shr ("ecx",16);
+ &movd ("eax","mm1"); # 5, 4, 1, 0
+ &mov ("ebx",&DWP(28,$key)); # t[3]
+ &xor ("ebx","edx");
+ &movd ("mm5","ebx"); # t[3] collected
+ &and ("ebx",0xffff0000);
+ &or ("ebx","ecx");
+
+ &punpckldq ("mm4","mm5"); # t[2,3] collected
+}
+
+######################################################################
+# "Compact" block function
+######################################################################
+
+sub enccompact()
+{ my $Fn = \&mov;
+ while ($#_>5) { pop(@_); $Fn=sub{}; }
+ my ($i,$te,@s)=@_;
+ my $tmp = $key;
+ my $out = $i==3?$s[0]:$acc;
+
+ # $Fn is used in first compact round and its purpose is to
+ # void restoration of some values from stack, so that after
+ # 4xenccompact with extra argument $key value is left there...
+ if ($i==3) { &$Fn ($key,$__key); }##%edx
+ else { &mov ($out,$s[0]); }
+ &and ($out,0xFF);
+ if ($i==1) { &shr ($s[0],16); }#%ebx[1]
+ if ($i==2) { &shr ($s[0],24); }#%ecx[2]
+ &movz ($out,&BP(-128,$te,$out,1));
+
+ if ($i==3) { $tmp=$s[1]; }##%eax
+ &movz ($tmp,&HB($s[1]));
+ &movz ($tmp,&BP(-128,$te,$tmp,1));
+ &shl ($tmp,8);
+ &xor ($out,$tmp);
+
+ if ($i==3) { $tmp=$s[2]; &mov ($s[1],$__s0); }##%ebx
+ else { &mov ($tmp,$s[2]);
+ &shr ($tmp,16); }
+ if ($i==2) { &and ($s[1],0xFF); }#%edx[2]
+ &and ($tmp,0xFF);
+ &movz ($tmp,&BP(-128,$te,$tmp,1));
+ &shl ($tmp,16);
+ &xor ($out,$tmp);
+
+ if ($i==3) { $tmp=$s[3]; &mov ($s[2],$__s1); }##%ecx
+ elsif($i==2){ &movz ($tmp,&HB($s[3])); }#%ebx[2]
+ else { &mov ($tmp,$s[3]);
+ &shr ($tmp,24); }
+ &movz ($tmp,&BP(-128,$te,$tmp,1));
+ &shl ($tmp,24);
+ &xor ($out,$tmp);
+ if ($i<2) { &mov (&DWP(4+4*$i,"esp"),$out); }
+ if ($i==3) { &mov ($s[3],$acc); }
+ &comment();
+}
+
+sub enctransform()
+{ my @s = ($s0,$s1,$s2,$s3);
+ my $i = shift;
+ my $tmp = $tbl;
+ my $r2 = $key ;
+
+ &and ($tmp,$s[$i]);
+ &lea ($r2,&DWP(0,$s[$i],$s[$i]));
+ &mov ($acc,$tmp);
+ &shr ($tmp,7);
+ &and ($r2,0xfefefefe);
+ &sub ($acc,$tmp);
+ &mov ($tmp,$s[$i]);
+ &and ($acc,0x1b1b1b1b);
+ &rotr ($tmp,16);
+ &xor ($acc,$r2); # r2
+ &mov ($r2,$s[$i]);
+
+ &xor ($s[$i],$acc); # r0 ^ r2
+ &rotr ($r2,16+8);
+ &xor ($acc,$tmp);
+ &rotl ($s[$i],24);
+ &xor ($acc,$r2);
+ &mov ($tmp,0x80808080) if ($i!=1);
+ &xor ($s[$i],$acc); # ROTATE(r2^r0,24) ^ r2
+}
+
+&function_begin_B("_x86_AES_encrypt_compact");
+ # note that caller is expected to allocate stack frame for me!
+ &mov ($__key,$key); # save key
+
+ &xor ($s0,&DWP(0,$key)); # xor with key
+ &xor ($s1,&DWP(4,$key));
+ &xor ($s2,&DWP(8,$key));
+ &xor ($s3,&DWP(12,$key));
+
+ &mov ($acc,&DWP(240,$key)); # load key->rounds
+ &lea ($acc,&DWP(-2,$acc,$acc));
+ &lea ($acc,&DWP(0,$key,$acc,8));
+ &mov ($__end,$acc); # end of key schedule
+
+ # prefetch Te4
+ &mov ($key,&DWP(0-128,$tbl));
+ &mov ($acc,&DWP(32-128,$tbl));
+ &mov ($key,&DWP(64-128,$tbl));
+ &mov ($acc,&DWP(96-128,$tbl));
+ &mov ($key,&DWP(128-128,$tbl));
+ &mov ($acc,&DWP(160-128,$tbl));
+ &mov ($key,&DWP(192-128,$tbl));
+ &mov ($acc,&DWP(224-128,$tbl));
+
+ &set_label("loop",16);
+
+ &enccompact(0,$tbl,$s0,$s1,$s2,$s3,1);
+ &enccompact(1,$tbl,$s1,$s2,$s3,$s0,1);
+ &enccompact(2,$tbl,$s2,$s3,$s0,$s1,1);
+ &enccompact(3,$tbl,$s3,$s0,$s1,$s2,1);
+ &mov ($tbl,0x80808080);
+ &enctransform(2);
+ &enctransform(3);
+ &enctransform(0);
+ &enctransform(1);
+ &mov ($key,$__key);
+ &mov ($tbl,$__tbl);
+ &add ($key,16); # advance rd_key
+ &xor ($s0,&DWP(0,$key));
+ &xor ($s1,&DWP(4,$key));
+ &xor ($s2,&DWP(8,$key));
+ &xor ($s3,&DWP(12,$key));
+
+ &cmp ($key,$__end);
+ &mov ($__key,$key);
+ &jb (&label("loop"));
+
+ &enccompact(0,$tbl,$s0,$s1,$s2,$s3);
+ &enccompact(1,$tbl,$s1,$s2,$s3,$s0);
+ &enccompact(2,$tbl,$s2,$s3,$s0,$s1);
+ &enccompact(3,$tbl,$s3,$s0,$s1,$s2);
+
+ &xor ($s0,&DWP(16,$key));
+ &xor ($s1,&DWP(20,$key));
+ &xor ($s2,&DWP(24,$key));
+ &xor ($s3,&DWP(28,$key));
+
+ &ret ();
+&function_end_B("_x86_AES_encrypt_compact");
+
+######################################################################
+# "Compact" SSE block function.
+######################################################################
+#
+# Performance is not actually extraordinary in comparison to pure
+# x86 code. In particular encrypt performance is virtually the same.
+# Decrypt performance on the other hand is 15-20% better on newer
+# µ-archs [but we're thankful for *any* improvement here], and ~50%
+# better on PIII:-) And additionally on the pros side this code
+# eliminates redundant references to stack and thus relieves/
+# minimizes the pressure on the memory bus.
+#
+# MMX register layout lsb
+# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+# | mm4 | mm0 |
+# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+# | s3 | s2 | s1 | s0 |
+# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+# |15|14|13|12|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0|
+# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+#
+# Indexes translate as s[N/4]>>(8*(N%4)), e.g. 5 means s1>>8.
+# In this terms encryption and decryption "compact" permutation
+# matrices can be depicted as following:
+#
+# encryption lsb # decryption lsb
+# +----++----+----+----+----+ # +----++----+----+----+----+
+# | t0 || 15 | 10 | 5 | 0 | # | t0 || 7 | 10 | 13 | 0 |
+# +----++----+----+----+----+ # +----++----+----+----+----+
+# | t1 || 3 | 14 | 9 | 4 | # | t1 || 11 | 14 | 1 | 4 |
+# +----++----+----+----+----+ # +----++----+----+----+----+
+# | t2 || 7 | 2 | 13 | 8 | # | t2 || 15 | 2 | 5 | 8 |
+# +----++----+----+----+----+ # +----++----+----+----+----+
+# | t3 || 11 | 6 | 1 | 12 | # | t3 || 3 | 6 | 9 | 12 |
+# +----++----+----+----+----+ # +----++----+----+----+----+
+#
+######################################################################
+# Why not xmm registers? Short answer. It was actually tested and
+# was not any faster, but *contrary*, most notably on Intel CPUs.
+# Longer answer. Main advantage of using mm registers is that movd
+# latency is lower, especially on Intel P4. While arithmetic
+# instructions are twice as many, they can be scheduled every cycle
+# and not every second one when they are operating on xmm register,
+# so that "arithmetic throughput" remains virtually the same. And
+# finally the code can be executed even on elder SSE-only CPUs:-)
+
+sub sse_enccompact()
+{
+ &pshufw ("mm1","mm0",0x08); # 5, 4, 1, 0
+ &pshufw ("mm5","mm4",0x0d); # 15,14,11,10
+ &movd ("eax","mm1"); # 5, 4, 1, 0
+ &movd ("ebx","mm5"); # 15,14,11,10
+ &mov ($__key,$key);
+
+ &movz ($acc,&LB("eax")); # 0
+ &movz ("edx",&HB("eax")); # 1
+ &pshufw ("mm2","mm0",0x0d); # 7, 6, 3, 2
+ &movz ("ecx",&BP(-128,$tbl,$acc,1)); # 0
+ &movz ($key,&LB("ebx")); # 10
+ &movz ("edx",&BP(-128,$tbl,"edx",1)); # 1
+ &shr ("eax",16); # 5, 4
+ &shl ("edx",8); # 1
+
+ &movz ($acc,&BP(-128,$tbl,$key,1)); # 10
+ &movz ($key,&HB("ebx")); # 11
+ &shl ($acc,16); # 10
+ &pshufw ("mm6","mm4",0x08); # 13,12, 9, 8
+ &or ("ecx",$acc); # 10
+ &movz ($acc,&BP(-128,$tbl,$key,1)); # 11
+ &movz ($key,&HB("eax")); # 5
+ &shl ($acc,24); # 11
+ &shr ("ebx",16); # 15,14
+ &or ("edx",$acc); # 11
+
+ &movz ($acc,&BP(-128,$tbl,$key,1)); # 5
+ &movz ($key,&HB("ebx")); # 15
+ &shl ($acc,8); # 5
+ &or ("ecx",$acc); # 5
+ &movz ($acc,&BP(-128,$tbl,$key,1)); # 15
+ &movz ($key,&LB("eax")); # 4
+ &shl ($acc,24); # 15
+ &or ("ecx",$acc); # 15
+
+ &movz ($acc,&BP(-128,$tbl,$key,1)); # 4
+ &movz ($key,&LB("ebx")); # 14
+ &movd ("eax","mm2"); # 7, 6, 3, 2
+ &movd ("mm0","ecx"); # t[0] collected
+ &movz ("ecx",&BP(-128,$tbl,$key,1)); # 14
+ &movz ($key,&HB("eax")); # 3
+ &shl ("ecx",16); # 14
+ &movd ("ebx","mm6"); # 13,12, 9, 8
+ &or ("ecx",$acc); # 14
+
+ &movz ($acc,&BP(-128,$tbl,$key,1)); # 3
+ &movz ($key,&HB("ebx")); # 9
+ &shl ($acc,24); # 3
+ &or ("ecx",$acc); # 3
+ &movz ($acc,&BP(-128,$tbl,$key,1)); # 9
+ &movz ($key,&LB("ebx")); # 8
+ &shl ($acc,8); # 9
+ &shr ("ebx",16); # 13,12
+ &or ("ecx",$acc); # 9
+
+ &movz ($acc,&BP(-128,$tbl,$key,1)); # 8
+ &movz ($key,&LB("eax")); # 2
+ &shr ("eax",16); # 7, 6
+ &movd ("mm1","ecx"); # t[1] collected
+ &movz ("ecx",&BP(-128,$tbl,$key,1)); # 2
+ &movz ($key,&HB("eax")); # 7
+ &shl ("ecx",16); # 2
+ &and ("eax",0xff); # 6
+ &or ("ecx",$acc); # 2
+
+ &punpckldq ("mm0","mm1"); # t[0,1] collected
+
+ &movz ($acc,&BP(-128,$tbl,$key,1)); # 7
+ &movz ($key,&HB("ebx")); # 13
+ &shl ($acc,24); # 7
+ &and ("ebx",0xff); # 12
+ &movz ("eax",&BP(-128,$tbl,"eax",1)); # 6
+ &or ("ecx",$acc); # 7
+ &shl ("eax",16); # 6
+ &movz ($acc,&BP(-128,$tbl,$key,1)); # 13
+ &or ("edx","eax"); # 6
+ &shl ($acc,8); # 13
+ &movz ("ebx",&BP(-128,$tbl,"ebx",1)); # 12
+ &or ("ecx",$acc); # 13
+ &or ("edx","ebx"); # 12
+ &mov ($key,$__key);
+ &movd ("mm4","ecx"); # t[2] collected
+ &movd ("mm5","edx"); # t[3] collected
+
+ &punpckldq ("mm4","mm5"); # t[2,3] collected
+}
+
+ if (!$x86only) {
+&function_begin_B("_sse_AES_encrypt_compact");
+ &pxor ("mm0",&QWP(0,$key)); # 7, 6, 5, 4, 3, 2, 1, 0
+ &pxor ("mm4",&QWP(8,$key)); # 15,14,13,12,11,10, 9, 8
+
+ # note that caller is expected to allocate stack frame for me!
+ &mov ($acc,&DWP(240,$key)); # load key->rounds
+ &lea ($acc,&DWP(-2,$acc,$acc));
+ &lea ($acc,&DWP(0,$key,$acc,8));
+ &mov ($__end,$acc); # end of key schedule
+
+ &mov ($s0,0x1b1b1b1b); # magic constant
+ &mov (&DWP(8,"esp"),$s0);
+ &mov (&DWP(12,"esp"),$s0);
+
+ # prefetch Te4
+ &mov ($s0,&DWP(0-128,$tbl));
+ &mov ($s1,&DWP(32-128,$tbl));
+ &mov ($s2,&DWP(64-128,$tbl));
+ &mov ($s3,&DWP(96-128,$tbl));
+ &mov ($s0,&DWP(128-128,$tbl));
+ &mov ($s1,&DWP(160-128,$tbl));
+ &mov ($s2,&DWP(192-128,$tbl));
+ &mov ($s3,&DWP(224-128,$tbl));
+
+ &set_label("loop",16);
+ &sse_enccompact();
+ &add ($key,16);
+ &cmp ($key,$__end);
+ &ja (&label("out"));
+
+ &movq ("mm2",&QWP(8,"esp"));
+ &pxor ("mm3","mm3"); &pxor ("mm7","mm7");
+ &movq ("mm1","mm0"); &movq ("mm5","mm4"); # r0
+ &pcmpgtb("mm3","mm0"); &pcmpgtb("mm7","mm4");
+ &pand ("mm3","mm2"); &pand ("mm7","mm2");
+ &pshufw ("mm2","mm0",0xb1); &pshufw ("mm6","mm4",0xb1);# ROTATE(r0,16)
+ &paddb ("mm0","mm0"); &paddb ("mm4","mm4");
+ &pxor ("mm0","mm3"); &pxor ("mm4","mm7"); # = r2
+ &pshufw ("mm3","mm2",0xb1); &pshufw ("mm7","mm6",0xb1);# r0
+ &pxor ("mm1","mm0"); &pxor ("mm5","mm4"); # r0^r2
+ &pxor ("mm0","mm2"); &pxor ("mm4","mm6"); # ^= ROTATE(r0,16)
+
+ &movq ("mm2","mm3"); &movq ("mm6","mm7");
+ &pslld ("mm3",8); &pslld ("mm7",8);
+ &psrld ("mm2",24); &psrld ("mm6",24);
+ &pxor ("mm0","mm3"); &pxor ("mm4","mm7"); # ^= r0<<8
+ &pxor ("mm0","mm2"); &pxor ("mm4","mm6"); # ^= r0>>24
+
+ &movq ("mm3","mm1"); &movq ("mm7","mm5");
+ &movq ("mm2",&QWP(0,$key)); &movq ("mm6",&QWP(8,$key));
+ &psrld ("mm1",8); &psrld ("mm5",8);
+ &mov ($s0,&DWP(0-128,$tbl));
+ &pslld ("mm3",24); &pslld ("mm7",24);
+ &mov ($s1,&DWP(64-128,$tbl));
+ &pxor ("mm0","mm1"); &pxor ("mm4","mm5"); # ^= (r2^r0)<<8
+ &mov ($s2,&DWP(128-128,$tbl));
+ &pxor ("mm0","mm3"); &pxor ("mm4","mm7"); # ^= (r2^r0)>>24
+ &mov ($s3,&DWP(192-128,$tbl));
+
+ &pxor ("mm0","mm2"); &pxor ("mm4","mm6");
+ &jmp (&label("loop"));
+
+ &set_label("out",16);
+ &pxor ("mm0",&QWP(0,$key));
+ &pxor ("mm4",&QWP(8,$key));
+
+ &ret ();
+&function_end_B("_sse_AES_encrypt_compact");
+ }
+
+######################################################################
+# Vanilla block function.
+######################################################################
+
+sub encstep()
+{ my ($i,$te,@s) = @_;
+ my $tmp = $key;
+ my $out = $i==3?$s[0]:$acc;
+
+ # lines marked with #%e?x[i] denote "reordered" instructions...
+ if ($i==3) { &mov ($key,$__key); }##%edx
+ else { &mov ($out,$s[0]);
+ &and ($out,0xFF); }
+ if ($i==1) { &shr ($s[0],16); }#%ebx[1]
+ if ($i==2) { &shr ($s[0],24); }#%ecx[2]
+ &mov ($out,&DWP(0,$te,$out,8));
+
+ if ($i==3) { $tmp=$s[1]; }##%eax
+ &movz ($tmp,&HB($s[1]));
+ &xor ($out,&DWP(3,$te,$tmp,8));
+
+ if ($i==3) { $tmp=$s[2]; &mov ($s[1],$__s0); }##%ebx
+ else { &mov ($tmp,$s[2]);
+ &shr ($tmp,16); }
+ if ($i==2) { &and ($s[1],0xFF); }#%edx[2]
+ &and ($tmp,0xFF);
+ &xor ($out,&DWP(2,$te,$tmp,8));
+
+ if ($i==3) { $tmp=$s[3]; &mov ($s[2],$__s1); }##%ecx
+ elsif($i==2){ &movz ($tmp,&HB($s[3])); }#%ebx[2]
+ else { &mov ($tmp,$s[3]);
+ &shr ($tmp,24) }
+ &xor ($out,&DWP(1,$te,$tmp,8));
+ if ($i<2) { &mov (&DWP(4+4*$i,"esp"),$out); }
+ if ($i==3) { &mov ($s[3],$acc); }
+ &comment();
+}
+
+sub enclast()
+{ my ($i,$te,@s)=@_;
+ my $tmp = $key;
+ my $out = $i==3?$s[0]:$acc;
+
+ if ($i==3) { &mov ($key,$__key); }##%edx
+ else { &mov ($out,$s[0]); }
+ &and ($out,0xFF);
+ if ($i==1) { &shr ($s[0],16); }#%ebx[1]
+ if ($i==2) { &shr ($s[0],24); }#%ecx[2]
+ &mov ($out,&DWP(2,$te,$out,8));
+ &and ($out,0x000000ff);
+
+ if ($i==3) { $tmp=$s[1]; }##%eax
+ &movz ($tmp,&HB($s[1]));
+ &mov ($tmp,&DWP(0,$te,$tmp,8));
+ &and ($tmp,0x0000ff00);
+ &xor ($out,$tmp);
+
+ if ($i==3) { $tmp=$s[2]; &mov ($s[1],$__s0); }##%ebx
+ else { &mov ($tmp,$s[2]);
+ &shr ($tmp,16); }
+ if ($i==2) { &and ($s[1],0xFF); }#%edx[2]
+ &and ($tmp,0xFF);
+ &mov ($tmp,&DWP(0,$te,$tmp,8));
+ &and ($tmp,0x00ff0000);
+ &xor ($out,$tmp);
+
+ if ($i==3) { $tmp=$s[3]; &mov ($s[2],$__s1); }##%ecx
+ elsif($i==2){ &movz ($tmp,&HB($s[3])); }#%ebx[2]
+ else { &mov ($tmp,$s[3]);
+ &shr ($tmp,24); }
+ &mov ($tmp,&DWP(2,$te,$tmp,8));
+ &and ($tmp,0xff000000);
+ &xor ($out,$tmp);
+ if ($i<2) { &mov (&DWP(4+4*$i,"esp"),$out); }
+ if ($i==3) { &mov ($s[3],$acc); }
+}
+
+&function_begin_B("_x86_AES_encrypt");
+ if ($vertical_spin) {
+ # I need high parts of volatile registers to be accessible...
+ &exch ($s1="edi",$key="ebx");
+ &mov ($s2="esi",$acc="ecx");
+ }
+
+ # note that caller is expected to allocate stack frame for me!
+ &mov ($__key,$key); # save key
+
+ &xor ($s0,&DWP(0,$key)); # xor with key
+ &xor ($s1,&DWP(4,$key));
+ &xor ($s2,&DWP(8,$key));
+ &xor ($s3,&DWP(12,$key));
+
+ &mov ($acc,&DWP(240,$key)); # load key->rounds
+
+ if ($small_footprint) {
+ &lea ($acc,&DWP(-2,$acc,$acc));
+ &lea ($acc,&DWP(0,$key,$acc,8));
+ &mov ($__end,$acc); # end of key schedule
+
+ &set_label("loop",16);
+ if ($vertical_spin) {
+ &encvert($tbl,$s0,$s1,$s2,$s3);
+ } else {
+ &encstep(0,$tbl,$s0,$s1,$s2,$s3);
+ &encstep(1,$tbl,$s1,$s2,$s3,$s0);
+ &encstep(2,$tbl,$s2,$s3,$s0,$s1);
+ &encstep(3,$tbl,$s3,$s0,$s1,$s2);
+ }
+ &add ($key,16); # advance rd_key
+ &xor ($s0,&DWP(0,$key));
+ &xor ($s1,&DWP(4,$key));
+ &xor ($s2,&DWP(8,$key));
+ &xor ($s3,&DWP(12,$key));
+ &cmp ($key,$__end);
+ &mov ($__key,$key);
+ &jb (&label("loop"));
+ }
+ else {
+ &cmp ($acc,10);
+ &jle (&label("10rounds"));
+ &cmp ($acc,12);
+ &jle (&label("12rounds"));
+
+ &set_label("14rounds",4);
+ for ($i=1;$i<3;$i++) {
+ if ($vertical_spin) {
+ &encvert($tbl,$s0,$s1,$s2,$s3);
+ } else {
+ &encstep(0,$tbl,$s0,$s1,$s2,$s3);
+ &encstep(1,$tbl,$s1,$s2,$s3,$s0);
+ &encstep(2,$tbl,$s2,$s3,$s0,$s1);
+ &encstep(3,$tbl,$s3,$s0,$s1,$s2);
+ }
+ &xor ($s0,&DWP(16*$i+0,$key));
+ &xor ($s1,&DWP(16*$i+4,$key));
+ &xor ($s2,&DWP(16*$i+8,$key));
+ &xor ($s3,&DWP(16*$i+12,$key));
+ }
+ &add ($key,32);
+ &mov ($__key,$key); # advance rd_key
+ &set_label("12rounds",4);
+ for ($i=1;$i<3;$i++) {
+ if ($vertical_spin) {
+ &encvert($tbl,$s0,$s1,$s2,$s3);
+ } else {
+ &encstep(0,$tbl,$s0,$s1,$s2,$s3);
+ &encstep(1,$tbl,$s1,$s2,$s3,$s0);
+ &encstep(2,$tbl,$s2,$s3,$s0,$s1);
+ &encstep(3,$tbl,$s3,$s0,$s1,$s2);
+ }
+ &xor ($s0,&DWP(16*$i+0,$key));
+ &xor ($s1,&DWP(16*$i+4,$key));
+ &xor ($s2,&DWP(16*$i+8,$key));
+ &xor ($s3,&DWP(16*$i+12,$key));
+ }
+ &add ($key,32);
+ &mov ($__key,$key); # advance rd_key
+ &set_label("10rounds",4);
+ for ($i=1;$i<10;$i++) {
+ if ($vertical_spin) {
+ &encvert($tbl,$s0,$s1,$s2,$s3);
+ } else {
+ &encstep(0,$tbl,$s0,$s1,$s2,$s3);
+ &encstep(1,$tbl,$s1,$s2,$s3,$s0);
+ &encstep(2,$tbl,$s2,$s3,$s0,$s1);
+ &encstep(3,$tbl,$s3,$s0,$s1,$s2);
+ }
+ &xor ($s0,&DWP(16*$i+0,$key));
+ &xor ($s1,&DWP(16*$i+4,$key));
+ &xor ($s2,&DWP(16*$i+8,$key));
+ &xor ($s3,&DWP(16*$i+12,$key));
+ }
+ }
+
+ if ($vertical_spin) {
+ # "reincarnate" some registers for "horizontal" spin...
+ &mov ($s1="ebx",$key="edi");
+ &mov ($s2="ecx",$acc="esi");
+ }
+ &enclast(0,$tbl,$s0,$s1,$s2,$s3);
+ &enclast(1,$tbl,$s1,$s2,$s3,$s0);
+ &enclast(2,$tbl,$s2,$s3,$s0,$s1);
+ &enclast(3,$tbl,$s3,$s0,$s1,$s2);
+
+ &add ($key,$small_footprint?16:160);
+ &xor ($s0,&DWP(0,$key));
+ &xor ($s1,&DWP(4,$key));
+ &xor ($s2,&DWP(8,$key));
+ &xor ($s3,&DWP(12,$key));
+
+ &ret ();
+
+&set_label("AES_Te",64); # Yes! I keep it in the code segment!
+ &_data_word(0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6);
+ &_data_word(0x0df2f2ff, 0xbd6b6bd6, 0xb16f6fde, 0x54c5c591);
+ &_data_word(0x50303060, 0x03010102, 0xa96767ce, 0x7d2b2b56);
+ &_data_word(0x19fefee7, 0x62d7d7b5, 0xe6abab4d, 0x9a7676ec);
+ &_data_word(0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa);
+ &_data_word(0x15fafaef, 0xeb5959b2, 0xc947478e, 0x0bf0f0fb);
+ &_data_word(0xecadad41, 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45);
+ &_data_word(0xbf9c9c23, 0xf7a4a453, 0x967272e4, 0x5bc0c09b);
+ &_data_word(0xc2b7b775, 0x1cfdfde1, 0xae93933d, 0x6a26264c);
+ &_data_word(0x5a36366c, 0x413f3f7e, 0x02f7f7f5, 0x4fcccc83);
+ &_data_word(0x5c343468, 0xf4a5a551, 0x34e5e5d1, 0x08f1f1f9);
+ &_data_word(0x937171e2, 0x73d8d8ab, 0x53313162, 0x3f15152a);
+ &_data_word(0x0c040408, 0x52c7c795, 0x65232346, 0x5ec3c39d);
+ &_data_word(0x28181830, 0xa1969637, 0x0f05050a, 0xb59a9a2f);
+ &_data_word(0x0907070e, 0x36121224, 0x9b80801b, 0x3de2e2df);
+ &_data_word(0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea);
+ &_data_word(0x1b090912, 0x9e83831d, 0x742c2c58, 0x2e1a1a34);
+ &_data_word(0x2d1b1b36, 0xb26e6edc, 0xee5a5ab4, 0xfba0a05b);
+ &_data_word(0xf65252a4, 0x4d3b3b76, 0x61d6d6b7, 0xceb3b37d);
+ &_data_word(0x7b292952, 0x3ee3e3dd, 0x712f2f5e, 0x97848413);
+ &_data_word(0xf55353a6, 0x68d1d1b9, 0x00000000, 0x2cededc1);
+ &_data_word(0x60202040, 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6);
+ &_data_word(0xbe6a6ad4, 0x46cbcb8d, 0xd9bebe67, 0x4b393972);
+ &_data_word(0xde4a4a94, 0xd44c4c98, 0xe85858b0, 0x4acfcf85);
+ &_data_word(0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed);
+ &_data_word(0xc5434386, 0xd74d4d9a, 0x55333366, 0x94858511);
+ &_data_word(0xcf45458a, 0x10f9f9e9, 0x06020204, 0x817f7ffe);
+ &_data_word(0xf05050a0, 0x443c3c78, 0xba9f9f25, 0xe3a8a84b);
+ &_data_word(0xf35151a2, 0xfea3a35d, 0xc0404080, 0x8a8f8f05);
+ &_data_word(0xad92923f, 0xbc9d9d21, 0x48383870, 0x04f5f5f1);
+ &_data_word(0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142);
+ &_data_word(0x30101020, 0x1affffe5, 0x0ef3f3fd, 0x6dd2d2bf);
+ &_data_word(0x4ccdcd81, 0x140c0c18, 0x35131326, 0x2fececc3);
+ &_data_word(0xe15f5fbe, 0xa2979735, 0xcc444488, 0x3917172e);
+ &_data_word(0x57c4c493, 0xf2a7a755, 0x827e7efc, 0x473d3d7a);
+ &_data_word(0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6);
+ &_data_word(0xa06060c0, 0x98818119, 0xd14f4f9e, 0x7fdcdca3);
+ &_data_word(0x66222244, 0x7e2a2a54, 0xab90903b, 0x8388880b);
+ &_data_word(0xca46468c, 0x29eeeec7, 0xd3b8b86b, 0x3c141428);
+ &_data_word(0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad);
+ &_data_word(0x3be0e0db, 0x56323264, 0x4e3a3a74, 0x1e0a0a14);
+ &_data_word(0xdb494992, 0x0a06060c, 0x6c242448, 0xe45c5cb8);
+ &_data_word(0x5dc2c29f, 0x6ed3d3bd, 0xefacac43, 0xa66262c4);
+ &_data_word(0xa8919139, 0xa4959531, 0x37e4e4d3, 0x8b7979f2);
+ &_data_word(0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda);
+ &_data_word(0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949);
+ &_data_word(0xb46c6cd8, 0xfa5656ac, 0x07f4f4f3, 0x25eaeacf);
+ &_data_word(0xaf6565ca, 0x8e7a7af4, 0xe9aeae47, 0x18080810);
+ &_data_word(0xd5baba6f, 0x887878f0, 0x6f25254a, 0x722e2e5c);
+ &_data_word(0x241c1c38, 0xf1a6a657, 0xc7b4b473, 0x51c6c697);
+ &_data_word(0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e);
+ &_data_word(0xdd4b4b96, 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f);
+ &_data_word(0x907070e0, 0x423e3e7c, 0xc4b5b571, 0xaa6666cc);
+ &_data_word(0xd8484890, 0x05030306, 0x01f6f6f7, 0x120e0e1c);
+ &_data_word(0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969);
+ &_data_word(0x91868617, 0x58c1c199, 0x271d1d3a, 0xb99e9e27);
+ &_data_word(0x38e1e1d9, 0x13f8f8eb, 0xb398982b, 0x33111122);
+ &_data_word(0xbb6969d2, 0x70d9d9a9, 0x898e8e07, 0xa7949433);
+ &_data_word(0xb69b9b2d, 0x221e1e3c, 0x92878715, 0x20e9e9c9);
+ &_data_word(0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5);
+ &_data_word(0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a);
+ &_data_word(0xdabfbf65, 0x31e6e6d7, 0xc6424284, 0xb86868d0);
+ &_data_word(0xc3414182, 0xb0999929, 0x772d2d5a, 0x110f0f1e);
+ &_data_word(0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d, 0x3a16162c);
+
+#Te4 # four copies of Te4 to choose from to avoid L1 aliasing
+ &data_byte(0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5);
+ &data_byte(0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76);
+ &data_byte(0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0);
+ &data_byte(0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0);
+ &data_byte(0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc);
+ &data_byte(0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15);
+ &data_byte(0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a);
+ &data_byte(0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75);
+ &data_byte(0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0);
+ &data_byte(0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84);
+ &data_byte(0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b);
+ &data_byte(0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf);
+ &data_byte(0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85);
+ &data_byte(0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8);
+ &data_byte(0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5);
+ &data_byte(0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2);
+ &data_byte(0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17);
+ &data_byte(0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73);
+ &data_byte(0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88);
+ &data_byte(0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb);
+ &data_byte(0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c);
+ &data_byte(0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79);
+ &data_byte(0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9);
+ &data_byte(0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08);
+ &data_byte(0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6);
+ &data_byte(0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a);
+ &data_byte(0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e);
+ &data_byte(0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e);
+ &data_byte(0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94);
+ &data_byte(0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf);
+ &data_byte(0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68);
+ &data_byte(0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16);
+
+ &data_byte(0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5);
+ &data_byte(0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76);
+ &data_byte(0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0);
+ &data_byte(0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0);
+ &data_byte(0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc);
+ &data_byte(0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15);
+ &data_byte(0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a);
+ &data_byte(0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75);
+ &data_byte(0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0);
+ &data_byte(0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84);
+ &data_byte(0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b);
+ &data_byte(0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf);
+ &data_byte(0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85);
+ &data_byte(0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8);
+ &data_byte(0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5);
+ &data_byte(0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2);
+ &data_byte(0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17);
+ &data_byte(0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73);
+ &data_byte(0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88);
+ &data_byte(0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb);
+ &data_byte(0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c);
+ &data_byte(0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79);
+ &data_byte(0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9);
+ &data_byte(0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08);
+ &data_byte(0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6);
+ &data_byte(0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a);
+ &data_byte(0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e);
+ &data_byte(0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e);
+ &data_byte(0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94);
+ &data_byte(0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf);
+ &data_byte(0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68);
+ &data_byte(0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16);
+
+ &data_byte(0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5);
+ &data_byte(0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76);
+ &data_byte(0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0);
+ &data_byte(0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0);
+ &data_byte(0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc);
+ &data_byte(0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15);
+ &data_byte(0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a);
+ &data_byte(0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75);
+ &data_byte(0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0);
+ &data_byte(0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84);
+ &data_byte(0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b);
+ &data_byte(0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf);
+ &data_byte(0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85);
+ &data_byte(0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8);
+ &data_byte(0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5);
+ &data_byte(0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2);
+ &data_byte(0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17);
+ &data_byte(0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73);
+ &data_byte(0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88);
+ &data_byte(0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb);
+ &data_byte(0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c);
+ &data_byte(0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79);
+ &data_byte(0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9);
+ &data_byte(0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08);
+ &data_byte(0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6);
+ &data_byte(0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a);
+ &data_byte(0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e);
+ &data_byte(0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e);
+ &data_byte(0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94);
+ &data_byte(0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf);
+ &data_byte(0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68);
+ &data_byte(0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16);
+
+ &data_byte(0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5);
+ &data_byte(0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76);
+ &data_byte(0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0);
+ &data_byte(0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0);
+ &data_byte(0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc);
+ &data_byte(0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15);
+ &data_byte(0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a);
+ &data_byte(0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75);
+ &data_byte(0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0);
+ &data_byte(0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84);
+ &data_byte(0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b);
+ &data_byte(0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf);
+ &data_byte(0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85);
+ &data_byte(0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8);
+ &data_byte(0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5);
+ &data_byte(0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2);
+ &data_byte(0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17);
+ &data_byte(0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73);
+ &data_byte(0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88);
+ &data_byte(0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb);
+ &data_byte(0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c);
+ &data_byte(0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79);
+ &data_byte(0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9);
+ &data_byte(0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08);
+ &data_byte(0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6);
+ &data_byte(0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a);
+ &data_byte(0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e);
+ &data_byte(0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e);
+ &data_byte(0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94);
+ &data_byte(0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf);
+ &data_byte(0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68);
+ &data_byte(0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16);
+#rcon:
+ &data_word(0x00000001, 0x00000002, 0x00000004, 0x00000008);
+ &data_word(0x00000010, 0x00000020, 0x00000040, 0x00000080);
+ &data_word(0x0000001b, 0x00000036, 0x00000000, 0x00000000);
+ &data_word(0x00000000, 0x00000000, 0x00000000, 0x00000000);
+&function_end_B("_x86_AES_encrypt");
+
+# void asm_AES_encrypt (const void *inp,void *out,const AES_KEY *key);
+&function_begin("asm_AES_encrypt");
+ &mov ($acc,&wparam(0)); # load inp
+ &mov ($key,&wparam(2)); # load key
+
+ &mov ($s0,"esp");
+ &sub ("esp",36);
+ &and ("esp",-64); # align to cache-line
+
+ # place stack frame just "above" the key schedule
+ &lea ($s1,&DWP(-64-63,$key));
+ &sub ($s1,"esp");
+ &neg ($s1);
+ &and ($s1,0x3C0); # modulo 1024, but aligned to cache-line
+ &sub ("esp",$s1);
+ &add ("esp",4); # 4 is reserved for caller's return address
+ &mov ($_esp,$s0); # save stack pointer
+
+ &call (&label("pic_point")); # make it PIC!
+ &set_label("pic_point");
+ &blindpop($tbl);
+ &picmeup($s0,"OPENSSL_ia32cap_P",$tbl,&label("pic_point")) if (!$x86only);
+ &lea ($tbl,&DWP(&label("AES_Te")."-".&label("pic_point"),$tbl));
+
+ # pick Te4 copy which can't "overlap" with stack frame or key schedule
+ &lea ($s1,&DWP(768-4,"esp"));
+ &sub ($s1,$tbl);
+ &and ($s1,0x300);
+ &lea ($tbl,&DWP(2048+128,$tbl,$s1));
+
+ if (!$x86only) {
+ &bt (&DWP(0,$s0),25); # check for SSE bit
+ &jnc (&label("x86"));
+
+ &movq ("mm0",&QWP(0,$acc));
+ &movq ("mm4",&QWP(8,$acc));
+ &call ("_sse_AES_encrypt_compact");
+ &mov ("esp",$_esp); # restore stack pointer
+ &mov ($acc,&wparam(1)); # load out
+ &movq (&QWP(0,$acc),"mm0"); # write output data
+ &movq (&QWP(8,$acc),"mm4");
+ &emms ();
+ &function_end_A();
+ }
+ &set_label("x86",16);
+ &mov ($_tbl,$tbl);
+ &mov ($s0,&DWP(0,$acc)); # load input data
+ &mov ($s1,&DWP(4,$acc));
+ &mov ($s2,&DWP(8,$acc));
+ &mov ($s3,&DWP(12,$acc));
+ &call ("_x86_AES_encrypt_compact");
+ &mov ("esp",$_esp); # restore stack pointer
+ &mov ($acc,&wparam(1)); # load out
+ &mov (&DWP(0,$acc),$s0); # write output data
+ &mov (&DWP(4,$acc),$s1);
+ &mov (&DWP(8,$acc),$s2);
+ &mov (&DWP(12,$acc),$s3);
+&function_end("asm_AES_encrypt");
+
+#--------------------------------------------------------------------#
+
+######################################################################
+# "Compact" block function
+######################################################################
+
+sub deccompact()
+{ my $Fn = \&mov;
+ while ($#_>5) { pop(@_); $Fn=sub{}; }
+ my ($i,$td,@s)=@_;
+ my $tmp = $key;
+ my $out = $i==3?$s[0]:$acc;
+
+ # $Fn is used in first compact round and its purpose is to
+ # void restoration of some values from stack, so that after
+ # 4xdeccompact with extra argument $key, $s0 and $s1 values
+ # are left there...
+ if($i==3) { &$Fn ($key,$__key); }
+ else { &mov ($out,$s[0]); }
+ &and ($out,0xFF);
+ &movz ($out,&BP(-128,$td,$out,1));
+
+ if ($i==3) { $tmp=$s[1]; }
+ &movz ($tmp,&HB($s[1]));
+ &movz ($tmp,&BP(-128,$td,$tmp,1));
+ &shl ($tmp,8);
+ &xor ($out,$tmp);
+
+ if ($i==3) { $tmp=$s[2]; &mov ($s[1],$acc); }
+ else { mov ($tmp,$s[2]); }
+ &shr ($tmp,16);
+ &and ($tmp,0xFF);
+ &movz ($tmp,&BP(-128,$td,$tmp,1));
+ &shl ($tmp,16);
+ &xor ($out,$tmp);
+
+ if ($i==3) { $tmp=$s[3]; &$Fn ($s[2],$__s1); }
+ else { &mov ($tmp,$s[3]); }
+ &shr ($tmp,24);
+ &movz ($tmp,&BP(-128,$td,$tmp,1));
+ &shl ($tmp,24);
+ &xor ($out,$tmp);
+ if ($i<2) { &mov (&DWP(4+4*$i,"esp"),$out); }
+ if ($i==3) { &$Fn ($s[3],$__s0); }
+}
+
+# must be called with 2,3,0,1 as argument sequence!!!
+sub dectransform()
+{ my @s = ($s0,$s1,$s2,$s3);
+ my $i = shift;
+ my $tmp = $key;
+ my $tp2 = @s[($i+2)%4]; $tp2 = @s[2] if ($i==1);
+ my $tp4 = @s[($i+3)%4]; $tp4 = @s[3] if ($i==1);
+ my $tp8 = $tbl;
+
+ &mov ($tmp,0x80808080);
+ &and ($tmp,$s[$i]);
+ &mov ($acc,$tmp);
+ &shr ($tmp,7);
+ &lea ($tp2,&DWP(0,$s[$i],$s[$i]));
+ &sub ($acc,$tmp);
+ &and ($tp2,0xfefefefe);
+ &and ($acc,0x1b1b1b1b);
+ &xor ($tp2,$acc);
+ &mov ($tmp,0x80808080);
+
+ &and ($tmp,$tp2);
+ &mov ($acc,$tmp);
+ &shr ($tmp,7);
+ &lea ($tp4,&DWP(0,$tp2,$tp2));
+ &sub ($acc,$tmp);
+ &and ($tp4,0xfefefefe);
+ &and ($acc,0x1b1b1b1b);
+ &xor ($tp2,$s[$i]); # tp2^tp1
+ &xor ($tp4,$acc);
+ &mov ($tmp,0x80808080);
+
+ &and ($tmp,$tp4);
+ &mov ($acc,$tmp);
+ &shr ($tmp,7);
+ &lea ($tp8,&DWP(0,$tp4,$tp4));
+ &sub ($acc,$tmp);
+ &and ($tp8,0xfefefefe);
+ &and ($acc,0x1b1b1b1b);
+ &xor ($tp4,$s[$i]); # tp4^tp1
+ &rotl ($s[$i],8); # = ROTATE(tp1,8)
+ &xor ($tp8,$acc);
+
+ &xor ($s[$i],$tp2);
+ &xor ($tp2,$tp8);
+ &xor ($s[$i],$tp4);
+ &xor ($tp4,$tp8);
+ &rotl ($tp2,24);
+ &xor ($s[$i],$tp8); # ^= tp8^(tp4^tp1)^(tp2^tp1)
+ &rotl ($tp4,16);
+ &xor ($s[$i],$tp2); # ^= ROTATE(tp8^tp2^tp1,24)
+ &rotl ($tp8,8);
+ &xor ($s[$i],$tp4); # ^= ROTATE(tp8^tp4^tp1,16)
+ &mov ($s[0],$__s0) if($i==2); #prefetch $s0
+ &mov ($s[1],$__s1) if($i==3); #prefetch $s1
+ &mov ($s[2],$__s2) if($i==1);
+ &xor ($s[$i],$tp8); # ^= ROTATE(tp8,8)
+
+ &mov ($s[3],$__s3) if($i==1);
+ &mov (&DWP(4+4*$i,"esp"),$s[$i]) if($i>=2);
+}
+
+&function_begin_B("_x86_AES_decrypt_compact");
+ # note that caller is expected to allocate stack frame for me!
+ &mov ($__key,$key); # save key
+
+ &xor ($s0,&DWP(0,$key)); # xor with key
+ &xor ($s1,&DWP(4,$key));
+ &xor ($s2,&DWP(8,$key));
+ &xor ($s3,&DWP(12,$key));
+
+ &mov ($acc,&DWP(240,$key)); # load key->rounds
+
+ &lea ($acc,&DWP(-2,$acc,$acc));
+ &lea ($acc,&DWP(0,$key,$acc,8));
+ &mov ($__end,$acc); # end of key schedule
+
+ # prefetch Td4
+ &mov ($key,&DWP(0-128,$tbl));
+ &mov ($acc,&DWP(32-128,$tbl));
+ &mov ($key,&DWP(64-128,$tbl));
+ &mov ($acc,&DWP(96-128,$tbl));
+ &mov ($key,&DWP(128-128,$tbl));
+ &mov ($acc,&DWP(160-128,$tbl));
+ &mov ($key,&DWP(192-128,$tbl));
+ &mov ($acc,&DWP(224-128,$tbl));
+
+ &set_label("loop",16);
+
+ &deccompact(0,$tbl,$s0,$s3,$s2,$s1,1);
+ &deccompact(1,$tbl,$s1,$s0,$s3,$s2,1);
+ &deccompact(2,$tbl,$s2,$s1,$s0,$s3,1);
+ &deccompact(3,$tbl,$s3,$s2,$s1,$s0,1);
+ &dectransform(2);
+ &dectransform(3);
+ &dectransform(0);
+ &dectransform(1);
+ &mov ($key,$__key);
+ &mov ($tbl,$__tbl);
+ &add ($key,16); # advance rd_key
+ &xor ($s0,&DWP(0,$key));
+ &xor ($s1,&DWP(4,$key));
+ &xor ($s2,&DWP(8,$key));
+ &xor ($s3,&DWP(12,$key));
+
+ &cmp ($key,$__end);
+ &mov ($__key,$key);
+ &jb (&label("loop"));
+
+ &deccompact(0,$tbl,$s0,$s3,$s2,$s1);
+ &deccompact(1,$tbl,$s1,$s0,$s3,$s2);
+ &deccompact(2,$tbl,$s2,$s1,$s0,$s3);
+ &deccompact(3,$tbl,$s3,$s2,$s1,$s0);
+
+ &xor ($s0,&DWP(16,$key));
+ &xor ($s1,&DWP(20,$key));
+ &xor ($s2,&DWP(24,$key));
+ &xor ($s3,&DWP(28,$key));
+
+ &ret ();
+&function_end_B("_x86_AES_decrypt_compact");
+
+######################################################################
+# "Compact" SSE block function.
+######################################################################
+
+sub sse_deccompact()
+{
+ &pshufw ("mm1","mm0",0x0c); # 7, 6, 1, 0
+ &pshufw ("mm5","mm4",0x09); # 13,12,11,10
+ &movd ("eax","mm1"); # 7, 6, 1, 0
+ &movd ("ebx","mm5"); # 13,12,11,10
+ &mov ($__key,$key);
+
+ &movz ($acc,&LB("eax")); # 0
+ &movz ("edx",&HB("eax")); # 1
+ &pshufw ("mm2","mm0",0x06); # 3, 2, 5, 4
+ &movz ("ecx",&BP(-128,$tbl,$acc,1)); # 0
+ &movz ($key,&LB("ebx")); # 10
+ &movz ("edx",&BP(-128,$tbl,"edx",1)); # 1
+ &shr ("eax",16); # 7, 6
+ &shl ("edx",8); # 1
+
+ &movz ($acc,&BP(-128,$tbl,$key,1)); # 10
+ &movz ($key,&HB("ebx")); # 11
+ &shl ($acc,16); # 10
+ &pshufw ("mm6","mm4",0x03); # 9, 8,15,14
+ &or ("ecx",$acc); # 10
+ &movz ($acc,&BP(-128,$tbl,$key,1)); # 11
+ &movz ($key,&HB("eax")); # 7
+ &shl ($acc,24); # 11
+ &shr ("ebx",16); # 13,12
+ &or ("edx",$acc); # 11
+
+ &movz ($acc,&BP(-128,$tbl,$key,1)); # 7
+ &movz ($key,&HB("ebx")); # 13
+ &shl ($acc,24); # 7
+ &or ("ecx",$acc); # 7
+ &movz ($acc,&BP(-128,$tbl,$key,1)); # 13
+ &movz ($key,&LB("eax")); # 6
+ &shl ($acc,8); # 13
+ &movd ("eax","mm2"); # 3, 2, 5, 4
+ &or ("ecx",$acc); # 13
+
+ &movz ($acc,&BP(-128,$tbl,$key,1)); # 6
+ &movz ($key,&LB("ebx")); # 12
+ &shl ($acc,16); # 6
+ &movd ("ebx","mm6"); # 9, 8,15,14
+ &movd ("mm0","ecx"); # t[0] collected
+ &movz ("ecx",&BP(-128,$tbl,$key,1)); # 12
+ &movz ($key,&LB("eax")); # 4
+ &or ("ecx",$acc); # 12
+
+ &movz ($acc,&BP(-128,$tbl,$key,1)); # 4
+ &movz ($key,&LB("ebx")); # 14
+ &or ("edx",$acc); # 4
+ &movz ($acc,&BP(-128,$tbl,$key,1)); # 14
+ &movz ($key,&HB("eax")); # 5
+ &shl ($acc,16); # 14
+ &shr ("eax",16); # 3, 2
+ &or ("edx",$acc); # 14
+
+ &movz ($acc,&BP(-128,$tbl,$key,1)); # 5
+ &movz ($key,&HB("ebx")); # 15
+ &shr ("ebx",16); # 9, 8
+ &shl ($acc,8); # 5
+ &movd ("mm1","edx"); # t[1] collected
+ &movz ("edx",&BP(-128,$tbl,$key,1)); # 15
+ &movz ($key,&HB("ebx")); # 9
+ &shl ("edx",24); # 15
+ &and ("ebx",0xff); # 8
+ &or ("edx",$acc); # 15
+
+ &punpckldq ("mm0","mm1"); # t[0,1] collected
+
+ &movz ($acc,&BP(-128,$tbl,$key,1)); # 9
+ &movz ($key,&LB("eax")); # 2
+ &shl ($acc,8); # 9
+ &movz ("eax",&HB("eax")); # 3
+ &movz ("ebx",&BP(-128,$tbl,"ebx",1)); # 8
+ &or ("ecx",$acc); # 9
+ &movz ($acc,&BP(-128,$tbl,$key,1)); # 2
+ &or ("edx","ebx"); # 8
+ &shl ($acc,16); # 2
+ &movz ("eax",&BP(-128,$tbl,"eax",1)); # 3
+ &or ("edx",$acc); # 2
+ &shl ("eax",24); # 3
+ &or ("ecx","eax"); # 3
+ &mov ($key,$__key);
+ &movd ("mm4","edx"); # t[2] collected
+ &movd ("mm5","ecx"); # t[3] collected
+
+ &punpckldq ("mm4","mm5"); # t[2,3] collected
+}
+
+ if (!$x86only) {
+&function_begin_B("_sse_AES_decrypt_compact");
+ &pxor ("mm0",&QWP(0,$key)); # 7, 6, 5, 4, 3, 2, 1, 0
+ &pxor ("mm4",&QWP(8,$key)); # 15,14,13,12,11,10, 9, 8
+
+ # note that caller is expected to allocate stack frame for me!
+ &mov ($acc,&DWP(240,$key)); # load key->rounds
+ &lea ($acc,&DWP(-2,$acc,$acc));
+ &lea ($acc,&DWP(0,$key,$acc,8));
+ &mov ($__end,$acc); # end of key schedule
+
+ &mov ($s0,0x1b1b1b1b); # magic constant
+ &mov (&DWP(8,"esp"),$s0);
+ &mov (&DWP(12,"esp"),$s0);
+
+ # prefetch Td4
+ &mov ($s0,&DWP(0-128,$tbl));
+ &mov ($s1,&DWP(32-128,$tbl));
+ &mov ($s2,&DWP(64-128,$tbl));
+ &mov ($s3,&DWP(96-128,$tbl));
+ &mov ($s0,&DWP(128-128,$tbl));
+ &mov ($s1,&DWP(160-128,$tbl));
+ &mov ($s2,&DWP(192-128,$tbl));
+ &mov ($s3,&DWP(224-128,$tbl));
+
+ &set_label("loop",16);
+ &sse_deccompact();
+ &add ($key,16);
+ &cmp ($key,$__end);
+ &ja (&label("out"));
+
+ # ROTATE(x^y,N) == ROTATE(x,N)^ROTATE(y,N)
+ &movq ("mm3","mm0"); &movq ("mm7","mm4");
+ &movq ("mm2","mm0",1); &movq ("mm6","mm4",1);
+ &movq ("mm1","mm0"); &movq ("mm5","mm4");
+ &pshufw ("mm0","mm0",0xb1); &pshufw ("mm4","mm4",0xb1);# = ROTATE(tp0,16)
+ &pslld ("mm2",8); &pslld ("mm6",8);
+ &psrld ("mm3",8); &psrld ("mm7",8);
+ &pxor ("mm0","mm2"); &pxor ("mm4","mm6"); # ^= tp0<<8
+ &pxor ("mm0","mm3"); &pxor ("mm4","mm7"); # ^= tp0>>8
+ &pslld ("mm2",16); &pslld ("mm6",16);
+ &psrld ("mm3",16); &psrld ("mm7",16);
+ &pxor ("mm0","mm2"); &pxor ("mm4","mm6"); # ^= tp0<<24
+ &pxor ("mm0","mm3"); &pxor ("mm4","mm7"); # ^= tp0>>24
+
+ &movq ("mm3",&QWP(8,"esp"));
+ &pxor ("mm2","mm2"); &pxor ("mm6","mm6");
+ &pcmpgtb("mm2","mm1"); &pcmpgtb("mm6","mm5");
+ &pand ("mm2","mm3"); &pand ("mm6","mm3");
+ &paddb ("mm1","mm1"); &paddb ("mm5","mm5");
+ &pxor ("mm1","mm2"); &pxor ("mm5","mm6"); # tp2
+ &movq ("mm3","mm1"); &movq ("mm7","mm5");
+ &movq ("mm2","mm1"); &movq ("mm6","mm5");
+ &pxor ("mm0","mm1"); &pxor ("mm4","mm5"); # ^= tp2
+ &pslld ("mm3",24); &pslld ("mm7",24);
+ &psrld ("mm2",8); &psrld ("mm6",8);
+ &pxor ("mm0","mm3"); &pxor ("mm4","mm7"); # ^= tp2<<24
+ &pxor ("mm0","mm2"); &pxor ("mm4","mm6"); # ^= tp2>>8
+
+ &movq ("mm2",&QWP(8,"esp"));
+ &pxor ("mm3","mm3"); &pxor ("mm7","mm7");
+ &pcmpgtb("mm3","mm1"); &pcmpgtb("mm7","mm5");
+ &pand ("mm3","mm2"); &pand ("mm7","mm2");
+ &paddb ("mm1","mm1"); &paddb ("mm5","mm5");
+ &pxor ("mm1","mm3"); &pxor ("mm5","mm7"); # tp4
+ &pshufw ("mm3","mm1",0xb1); &pshufw ("mm7","mm5",0xb1);
+ &pxor ("mm0","mm1"); &pxor ("mm4","mm5"); # ^= tp4
+ &pxor ("mm0","mm3"); &pxor ("mm4","mm7"); # ^= ROTATE(tp4,16)
+
+ &pxor ("mm3","mm3"); &pxor ("mm7","mm7");
+ &pcmpgtb("mm3","mm1"); &pcmpgtb("mm7","mm5");
+ &pand ("mm3","mm2"); &pand ("mm7","mm2");
+ &paddb ("mm1","mm1"); &paddb ("mm5","mm5");
+ &pxor ("mm1","mm3"); &pxor ("mm5","mm7"); # tp8
+ &pxor ("mm0","mm1"); &pxor ("mm4","mm5"); # ^= tp8
+ &movq ("mm3","mm1"); &movq ("mm7","mm5");
+ &pshufw ("mm2","mm1",0xb1); &pshufw ("mm6","mm5",0xb1);
+ &pxor ("mm0","mm2"); &pxor ("mm4","mm6"); # ^= ROTATE(tp8,16)
+ &pslld ("mm1",8); &pslld ("mm5",8);
+ &psrld ("mm3",8); &psrld ("mm7",8);
+ &movq ("mm2",&QWP(0,$key)); &movq ("mm6",&QWP(8,$key));
+ &pxor ("mm0","mm1"); &pxor ("mm4","mm5"); # ^= tp8<<8
+ &pxor ("mm0","mm3"); &pxor ("mm4","mm7"); # ^= tp8>>8
+ &mov ($s0,&DWP(0-128,$tbl));
+ &pslld ("mm1",16); &pslld ("mm5",16);
+ &mov ($s1,&DWP(64-128,$tbl));
+ &psrld ("mm3",16); &psrld ("mm7",16);
+ &mov ($s2,&DWP(128-128,$tbl));
+ &pxor ("mm0","mm1"); &pxor ("mm4","mm5"); # ^= tp8<<24
+ &mov ($s3,&DWP(192-128,$tbl));
+ &pxor ("mm0","mm3"); &pxor ("mm4","mm7"); # ^= tp8>>24
+
+ &pxor ("mm0","mm2"); &pxor ("mm4","mm6");
+ &jmp (&label("loop"));
+
+ &set_label("out",16);
+ &pxor ("mm0",&QWP(0,$key));
+ &pxor ("mm4",&QWP(8,$key));
+
+ &ret ();
+&function_end_B("_sse_AES_decrypt_compact");
+ }
+
+######################################################################
+# Vanilla block function.
+######################################################################
+
+sub decstep()
+{ my ($i,$td,@s) = @_;
+ my $tmp = $key;
+ my $out = $i==3?$s[0]:$acc;
+
+ # no instructions are reordered, as performance appears
+ # optimal... or rather that all attempts to reorder didn't
+ # result in better performance [which by the way is not a
+ # bit lower than ecryption].
+ if($i==3) { &mov ($key,$__key); }
+ else { &mov ($out,$s[0]); }
+ &and ($out,0xFF);
+ &mov ($out,&DWP(0,$td,$out,8));
+
+ if ($i==3) { $tmp=$s[1]; }
+ &movz ($tmp,&HB($s[1]));
+ &xor ($out,&DWP(3,$td,$tmp,8));
+
+ if ($i==3) { $tmp=$s[2]; &mov ($s[1],$acc); }
+ else { &mov ($tmp,$s[2]); }
+ &shr ($tmp,16);
+ &and ($tmp,0xFF);
+ &xor ($out,&DWP(2,$td,$tmp,8));
+
+ if ($i==3) { $tmp=$s[3]; &mov ($s[2],$__s1); }
+ else { &mov ($tmp,$s[3]); }
+ &shr ($tmp,24);
+ &xor ($out,&DWP(1,$td,$tmp,8));
+ if ($i<2) { &mov (&DWP(4+4*$i,"esp"),$out); }
+ if ($i==3) { &mov ($s[3],$__s0); }
+ &comment();
+}
+
+sub declast()
+{ my ($i,$td,@s)=@_;
+ my $tmp = $key;
+ my $out = $i==3?$s[0]:$acc;
+
+ if($i==0) { &lea ($td,&DWP(2048+128,$td));
+ &mov ($tmp,&DWP(0-128,$td));
+ &mov ($acc,&DWP(32-128,$td));
+ &mov ($tmp,&DWP(64-128,$td));
+ &mov ($acc,&DWP(96-128,$td));
+ &mov ($tmp,&DWP(128-128,$td));
+ &mov ($acc,&DWP(160-128,$td));
+ &mov ($tmp,&DWP(192-128,$td));
+ &mov ($acc,&DWP(224-128,$td));
+ &lea ($td,&DWP(-128,$td)); }
+ if($i==3) { &mov ($key,$__key); }
+ else { &mov ($out,$s[0]); }
+ &and ($out,0xFF);
+ &movz ($out,&BP(0,$td,$out,1));
+
+ if ($i==3) { $tmp=$s[1]; }
+ &movz ($tmp,&HB($s[1]));
+ &movz ($tmp,&BP(0,$td,$tmp,1));
+ &shl ($tmp,8);
+ &xor ($out,$tmp);
+
+ if ($i==3) { $tmp=$s[2]; &mov ($s[1],$acc); }
+ else { mov ($tmp,$s[2]); }
+ &shr ($tmp,16);
+ &and ($tmp,0xFF);
+ &movz ($tmp,&BP(0,$td,$tmp,1));
+ &shl ($tmp,16);
+ &xor ($out,$tmp);
+
+ if ($i==3) { $tmp=$s[3]; &mov ($s[2],$__s1); }
+ else { &mov ($tmp,$s[3]); }
+ &shr ($tmp,24);
+ &movz ($tmp,&BP(0,$td,$tmp,1));
+ &shl ($tmp,24);
+ &xor ($out,$tmp);
+ if ($i<2) { &mov (&DWP(4+4*$i,"esp"),$out); }
+ if ($i==3) { &mov ($s[3],$__s0);
+ &lea ($td,&DWP(-2048,$td)); }
+}
+
+&function_begin_B("_x86_AES_decrypt");
+ # note that caller is expected to allocate stack frame for me!
+ &mov ($__key,$key); # save key
+
+ &xor ($s0,&DWP(0,$key)); # xor with key
+ &xor ($s1,&DWP(4,$key));
+ &xor ($s2,&DWP(8,$key));
+ &xor ($s3,&DWP(12,$key));
+
+ &mov ($acc,&DWP(240,$key)); # load key->rounds
+
+ if ($small_footprint) {
+ &lea ($acc,&DWP(-2,$acc,$acc));
+ &lea ($acc,&DWP(0,$key,$acc,8));
+ &mov ($__end,$acc); # end of key schedule
+ &set_label("loop",16);
+ &decstep(0,$tbl,$s0,$s3,$s2,$s1);
+ &decstep(1,$tbl,$s1,$s0,$s3,$s2);
+ &decstep(2,$tbl,$s2,$s1,$s0,$s3);
+ &decstep(3,$tbl,$s3,$s2,$s1,$s0);
+ &add ($key,16); # advance rd_key
+ &xor ($s0,&DWP(0,$key));
+ &xor ($s1,&DWP(4,$key));
+ &xor ($s2,&DWP(8,$key));
+ &xor ($s3,&DWP(12,$key));
+ &cmp ($key,$__end);
+ &mov ($__key,$key);
+ &jb (&label("loop"));
+ }
+ else {
+ &cmp ($acc,10);
+ &jle (&label("10rounds"));
+ &cmp ($acc,12);
+ &jle (&label("12rounds"));
+
+ &set_label("14rounds",4);
+ for ($i=1;$i<3;$i++) {
+ &decstep(0,$tbl,$s0,$s3,$s2,$s1);
+ &decstep(1,$tbl,$s1,$s0,$s3,$s2);
+ &decstep(2,$tbl,$s2,$s1,$s0,$s3);
+ &decstep(3,$tbl,$s3,$s2,$s1,$s0);
+ &xor ($s0,&DWP(16*$i+0,$key));
+ &xor ($s1,&DWP(16*$i+4,$key));
+ &xor ($s2,&DWP(16*$i+8,$key));
+ &xor ($s3,&DWP(16*$i+12,$key));
+ }
+ &add ($key,32);
+ &mov ($__key,$key); # advance rd_key
+ &set_label("12rounds",4);
+ for ($i=1;$i<3;$i++) {
+ &decstep(0,$tbl,$s0,$s3,$s2,$s1);
+ &decstep(1,$tbl,$s1,$s0,$s3,$s2);
+ &decstep(2,$tbl,$s2,$s1,$s0,$s3);
+ &decstep(3,$tbl,$s3,$s2,$s1,$s0);
+ &xor ($s0,&DWP(16*$i+0,$key));
+ &xor ($s1,&DWP(16*$i+4,$key));
+ &xor ($s2,&DWP(16*$i+8,$key));
+ &xor ($s3,&DWP(16*$i+12,$key));
+ }
+ &add ($key,32);
+ &mov ($__key,$key); # advance rd_key
+ &set_label("10rounds",4);
+ for ($i=1;$i<10;$i++) {
+ &decstep(0,$tbl,$s0,$s3,$s2,$s1);
+ &decstep(1,$tbl,$s1,$s0,$s3,$s2);
+ &decstep(2,$tbl,$s2,$s1,$s0,$s3);
+ &decstep(3,$tbl,$s3,$s2,$s1,$s0);
+ &xor ($s0,&DWP(16*$i+0,$key));
+ &xor ($s1,&DWP(16*$i+4,$key));
+ &xor ($s2,&DWP(16*$i+8,$key));
+ &xor ($s3,&DWP(16*$i+12,$key));
+ }
+ }
+
+ &declast(0,$tbl,$s0,$s3,$s2,$s1);
+ &declast(1,$tbl,$s1,$s0,$s3,$s2);
+ &declast(2,$tbl,$s2,$s1,$s0,$s3);
+ &declast(3,$tbl,$s3,$s2,$s1,$s0);
+
+ &add ($key,$small_footprint?16:160);
+ &xor ($s0,&DWP(0,$key));
+ &xor ($s1,&DWP(4,$key));
+ &xor ($s2,&DWP(8,$key));
+ &xor ($s3,&DWP(12,$key));
+
+ &ret ();
+
+&set_label("AES_Td",64); # Yes! I keep it in the code segment!
+ &_data_word(0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a);
+ &_data_word(0xcb6bab3b, 0xf1459d1f, 0xab58faac, 0x9303e34b);
+ &_data_word(0x55fa3020, 0xf66d76ad, 0x9176cc88, 0x254c02f5);
+ &_data_word(0xfcd7e54f, 0xd7cb2ac5, 0x80443526, 0x8fa362b5);
+ &_data_word(0x495ab1de, 0x671bba25, 0x980eea45, 0xe1c0fe5d);
+ &_data_word(0x02752fc3, 0x12f04c81, 0xa397468d, 0xc6f9d36b);
+ &_data_word(0xe75f8f03, 0x959c9215, 0xeb7a6dbf, 0xda595295);
+ &_data_word(0x2d83bed4, 0xd3217458, 0x2969e049, 0x44c8c98e);
+ &_data_word(0x6a89c275, 0x78798ef4, 0x6b3e5899, 0xdd71b927);
+ &_data_word(0xb64fe1be, 0x17ad88f0, 0x66ac20c9, 0xb43ace7d);
+ &_data_word(0x184adf63, 0x82311ae5, 0x60335197, 0x457f5362);
+ &_data_word(0xe07764b1, 0x84ae6bbb, 0x1ca081fe, 0x942b08f9);
+ &_data_word(0x58684870, 0x19fd458f, 0x876cde94, 0xb7f87b52);
+ &_data_word(0x23d373ab, 0xe2024b72, 0x578f1fe3, 0x2aab5566);
+ &_data_word(0x0728ebb2, 0x03c2b52f, 0x9a7bc586, 0xa50837d3);
+ &_data_word(0xf2872830, 0xb2a5bf23, 0xba6a0302, 0x5c8216ed);
+ &_data_word(0x2b1ccf8a, 0x92b479a7, 0xf0f207f3, 0xa1e2694e);
+ &_data_word(0xcdf4da65, 0xd5be0506, 0x1f6234d1, 0x8afea6c4);
+ &_data_word(0x9d532e34, 0xa055f3a2, 0x32e18a05, 0x75ebf6a4);
+ &_data_word(0x39ec830b, 0xaaef6040, 0x069f715e, 0x51106ebd);
+ &_data_word(0xf98a213e, 0x3d06dd96, 0xae053edd, 0x46bde64d);
+ &_data_word(0xb58d5491, 0x055dc471, 0x6fd40604, 0xff155060);
+ &_data_word(0x24fb9819, 0x97e9bdd6, 0xcc434089, 0x779ed967);
+ &_data_word(0xbd42e8b0, 0x888b8907, 0x385b19e7, 0xdbeec879);
+ &_data_word(0x470a7ca1, 0xe90f427c, 0xc91e84f8, 0x00000000);
+ &_data_word(0x83868009, 0x48ed2b32, 0xac70111e, 0x4e725a6c);
+ &_data_word(0xfbff0efd, 0x5638850f, 0x1ed5ae3d, 0x27392d36);
+ &_data_word(0x64d90f0a, 0x21a65c68, 0xd1545b9b, 0x3a2e3624);
+ &_data_word(0xb1670a0c, 0x0fe75793, 0xd296eeb4, 0x9e919b1b);
+ &_data_word(0x4fc5c080, 0xa220dc61, 0x694b775a, 0x161a121c);
+ &_data_word(0x0aba93e2, 0xe52aa0c0, 0x43e0223c, 0x1d171b12);
+ &_data_word(0x0b0d090e, 0xadc78bf2, 0xb9a8b62d, 0xc8a91e14);
+ &_data_word(0x8519f157, 0x4c0775af, 0xbbdd99ee, 0xfd607fa3);
+ &_data_word(0x9f2601f7, 0xbcf5725c, 0xc53b6644, 0x347efb5b);
+ &_data_word(0x7629438b, 0xdcc623cb, 0x68fcedb6, 0x63f1e4b8);
+ &_data_word(0xcadc31d7, 0x10856342, 0x40229713, 0x2011c684);
+ &_data_word(0x7d244a85, 0xf83dbbd2, 0x1132f9ae, 0x6da129c7);
+ &_data_word(0x4b2f9e1d, 0xf330b2dc, 0xec52860d, 0xd0e3c177);
+ &_data_word(0x6c16b32b, 0x99b970a9, 0xfa489411, 0x2264e947);
+ &_data_word(0xc48cfca8, 0x1a3ff0a0, 0xd82c7d56, 0xef903322);
+ &_data_word(0xc74e4987, 0xc1d138d9, 0xfea2ca8c, 0x360bd498);
+ &_data_word(0xcf81f5a6, 0x28de7aa5, 0x268eb7da, 0xa4bfad3f);
+ &_data_word(0xe49d3a2c, 0x0d927850, 0x9bcc5f6a, 0x62467e54);
+ &_data_word(0xc2138df6, 0xe8b8d890, 0x5ef7392e, 0xf5afc382);
+ &_data_word(0xbe805d9f, 0x7c93d069, 0xa92dd56f, 0xb31225cf);
+ &_data_word(0x3b99acc8, 0xa77d1810, 0x6e639ce8, 0x7bbb3bdb);
+ &_data_word(0x097826cd, 0xf418596e, 0x01b79aec, 0xa89a4f83);
+ &_data_word(0x656e95e6, 0x7ee6ffaa, 0x08cfbc21, 0xe6e815ef);
+ &_data_word(0xd99be7ba, 0xce366f4a, 0xd4099fea, 0xd67cb029);
+ &_data_word(0xafb2a431, 0x31233f2a, 0x3094a5c6, 0xc066a235);
+ &_data_word(0x37bc4e74, 0xa6ca82fc, 0xb0d090e0, 0x15d8a733);
+ &_data_word(0x4a9804f1, 0xf7daec41, 0x0e50cd7f, 0x2ff69117);
+ &_data_word(0x8dd64d76, 0x4db0ef43, 0x544daacc, 0xdf0496e4);
+ &_data_word(0xe3b5d19e, 0x1b886a4c, 0xb81f2cc1, 0x7f516546);
+ &_data_word(0x04ea5e9d, 0x5d358c01, 0x737487fa, 0x2e410bfb);
+ &_data_word(0x5a1d67b3, 0x52d2db92, 0x335610e9, 0x1347d66d);
+ &_data_word(0x8c61d79a, 0x7a0ca137, 0x8e14f859, 0x893c13eb);
+ &_data_word(0xee27a9ce, 0x35c961b7, 0xede51ce1, 0x3cb1477a);
+ &_data_word(0x59dfd29c, 0x3f73f255, 0x79ce1418, 0xbf37c773);
+ &_data_word(0xeacdf753, 0x5baafd5f, 0x146f3ddf, 0x86db4478);
+ &_data_word(0x81f3afca, 0x3ec468b9, 0x2c342438, 0x5f40a3c2);
+ &_data_word(0x72c31d16, 0x0c25e2bc, 0x8b493c28, 0x41950dff);
+ &_data_word(0x7101a839, 0xdeb30c08, 0x9ce4b4d8, 0x90c15664);
+ &_data_word(0x6184cb7b, 0x70b632d5, 0x745c6c48, 0x4257b8d0);
+
+#Td4: # four copies of Td4 to choose from to avoid L1 aliasing
+ &data_byte(0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38);
+ &data_byte(0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb);
+ &data_byte(0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87);
+ &data_byte(0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb);
+ &data_byte(0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d);
+ &data_byte(0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e);
+ &data_byte(0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2);
+ &data_byte(0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25);
+ &data_byte(0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16);
+ &data_byte(0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92);
+ &data_byte(0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda);
+ &data_byte(0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84);
+ &data_byte(0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a);
+ &data_byte(0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06);
+ &data_byte(0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02);
+ &data_byte(0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b);
+ &data_byte(0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea);
+ &data_byte(0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73);
+ &data_byte(0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85);
+ &data_byte(0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e);
+ &data_byte(0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89);
+ &data_byte(0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b);
+ &data_byte(0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20);
+ &data_byte(0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4);
+ &data_byte(0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31);
+ &data_byte(0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f);
+ &data_byte(0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d);
+ &data_byte(0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef);
+ &data_byte(0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0);
+ &data_byte(0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61);
+ &data_byte(0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26);
+ &data_byte(0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d);
+
+ &data_byte(0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38);
+ &data_byte(0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb);
+ &data_byte(0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87);
+ &data_byte(0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb);
+ &data_byte(0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d);
+ &data_byte(0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e);
+ &data_byte(0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2);
+ &data_byte(0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25);
+ &data_byte(0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16);
+ &data_byte(0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92);
+ &data_byte(0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda);
+ &data_byte(0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84);
+ &data_byte(0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a);
+ &data_byte(0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06);
+ &data_byte(0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02);
+ &data_byte(0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b);
+ &data_byte(0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea);
+ &data_byte(0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73);
+ &data_byte(0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85);
+ &data_byte(0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e);
+ &data_byte(0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89);
+ &data_byte(0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b);
+ &data_byte(0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20);
+ &data_byte(0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4);
+ &data_byte(0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31);
+ &data_byte(0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f);
+ &data_byte(0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d);
+ &data_byte(0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef);
+ &data_byte(0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0);
+ &data_byte(0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61);
+ &data_byte(0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26);
+ &data_byte(0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d);
+
+ &data_byte(0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38);
+ &data_byte(0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb);
+ &data_byte(0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87);
+ &data_byte(0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb);
+ &data_byte(0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d);
+ &data_byte(0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e);
+ &data_byte(0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2);
+ &data_byte(0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25);
+ &data_byte(0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16);
+ &data_byte(0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92);
+ &data_byte(0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda);
+ &data_byte(0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84);
+ &data_byte(0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a);
+ &data_byte(0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06);
+ &data_byte(0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02);
+ &data_byte(0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b);
+ &data_byte(0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea);
+ &data_byte(0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73);
+ &data_byte(0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85);
+ &data_byte(0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e);
+ &data_byte(0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89);
+ &data_byte(0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b);
+ &data_byte(0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20);
+ &data_byte(0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4);
+ &data_byte(0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31);
+ &data_byte(0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f);
+ &data_byte(0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d);
+ &data_byte(0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef);
+ &data_byte(0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0);
+ &data_byte(0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61);
+ &data_byte(0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26);
+ &data_byte(0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d);
+
+ &data_byte(0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38);
+ &data_byte(0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb);
+ &data_byte(0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87);
+ &data_byte(0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb);
+ &data_byte(0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d);
+ &data_byte(0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e);
+ &data_byte(0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2);
+ &data_byte(0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25);
+ &data_byte(0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16);
+ &data_byte(0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92);
+ &data_byte(0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda);
+ &data_byte(0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84);
+ &data_byte(0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a);
+ &data_byte(0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06);
+ &data_byte(0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02);
+ &data_byte(0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b);
+ &data_byte(0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea);
+ &data_byte(0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73);
+ &data_byte(0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85);
+ &data_byte(0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e);
+ &data_byte(0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89);
+ &data_byte(0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b);
+ &data_byte(0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20);
+ &data_byte(0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4);
+ &data_byte(0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31);
+ &data_byte(0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f);
+ &data_byte(0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d);
+ &data_byte(0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef);
+ &data_byte(0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0);
+ &data_byte(0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61);
+ &data_byte(0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26);
+ &data_byte(0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d);
+&function_end_B("_x86_AES_decrypt");
+
+# void asm_AES_decrypt (const void *inp,void *out,const AES_KEY *key);
+&function_begin("asm_AES_decrypt");
+ &mov ($acc,&wparam(0)); # load inp
+ &mov ($key,&wparam(2)); # load key
+
+ &mov ($s0,"esp");
+ &sub ("esp",36);
+ &and ("esp",-64); # align to cache-line
+
+ # place stack frame just "above" the key schedule
+ &lea ($s1,&DWP(-64-63,$key));
+ &sub ($s1,"esp");
+ &neg ($s1);
+ &and ($s1,0x3C0); # modulo 1024, but aligned to cache-line
+ &sub ("esp",$s1);
+ &add ("esp",4); # 4 is reserved for caller's return address
+ &mov ($_esp,$s0); # save stack pointer
+
+ &call (&label("pic_point")); # make it PIC!
+ &set_label("pic_point");
+ &blindpop($tbl);
+ &picmeup($s0,"OPENSSL_ia32cap_P",$tbl,&label("pic_point")) if(!$x86only);
+ &lea ($tbl,&DWP(&label("AES_Td")."-".&label("pic_point"),$tbl));
+
+ # pick Td4 copy which can't "overlap" with stack frame or key schedule
+ &lea ($s1,&DWP(768-4,"esp"));
+ &sub ($s1,$tbl);
+ &and ($s1,0x300);
+ &lea ($tbl,&DWP(2048+128,$tbl,$s1));
+
+ if (!$x86only) {
+ &bt (&DWP(0,$s0),25); # check for SSE bit
+ &jnc (&label("x86"));
+
+ &movq ("mm0",&QWP(0,$acc));
+ &movq ("mm4",&QWP(8,$acc));
+ &call ("_sse_AES_decrypt_compact");
+ &mov ("esp",$_esp); # restore stack pointer
+ &mov ($acc,&wparam(1)); # load out
+ &movq (&QWP(0,$acc),"mm0"); # write output data
+ &movq (&QWP(8,$acc),"mm4");
+ &emms ();
+ &function_end_A();
+ }
+ &set_label("x86",16);
+ &mov ($_tbl,$tbl);
+ &mov ($s0,&DWP(0,$acc)); # load input data
+ &mov ($s1,&DWP(4,$acc));
+ &mov ($s2,&DWP(8,$acc));
+ &mov ($s3,&DWP(12,$acc));
+ &call ("_x86_AES_decrypt_compact");
+ &mov ("esp",$_esp); # restore stack pointer
+ &mov ($acc,&wparam(1)); # load out
+ &mov (&DWP(0,$acc),$s0); # write output data
+ &mov (&DWP(4,$acc),$s1);
+ &mov (&DWP(8,$acc),$s2);
+ &mov (&DWP(12,$acc),$s3);
+&function_end("asm_AES_decrypt");
+
+# void asm_AES_cbc_encrypt (const void char *inp, unsigned char *out,
+# size_t length, const AES_KEY *key,
+# unsigned char *ivp,const int enc);
+{
+# stack frame layout
+# -4(%esp) # return address 0(%esp)
+# 0(%esp) # s0 backing store 4(%esp)
+# 4(%esp) # s1 backing store 8(%esp)
+# 8(%esp) # s2 backing store 12(%esp)
+# 12(%esp) # s3 backing store 16(%esp)
+# 16(%esp) # key backup 20(%esp)
+# 20(%esp) # end of key schedule 24(%esp)
+# 24(%esp) # %ebp backup 28(%esp)
+# 28(%esp) # %esp backup
+my $_inp=&DWP(32,"esp"); # copy of wparam(0)
+my $_out=&DWP(36,"esp"); # copy of wparam(1)
+my $_len=&DWP(40,"esp"); # copy of wparam(2)
+my $_key=&DWP(44,"esp"); # copy of wparam(3)
+my $_ivp=&DWP(48,"esp"); # copy of wparam(4)
+my $_tmp=&DWP(52,"esp"); # volatile variable
+#
+my $ivec=&DWP(60,"esp"); # ivec[16]
+my $aes_key=&DWP(76,"esp"); # copy of aes_key
+my $mark=&DWP(76+240,"esp"); # copy of aes_key->rounds
+
+&function_begin("asm_AES_cbc_encrypt");
+ &mov ($s2 eq "ecx"? $s2 : "",&wparam(2)); # load len
+ &cmp ($s2,0);
+ &je (&label("drop_out"));
+
+ &call (&label("pic_point")); # make it PIC!
+ &set_label("pic_point");
+ &blindpop($tbl);
+ &picmeup($s0,"OPENSSL_ia32cap_P",$tbl,&label("pic_point")) if(!$x86only);
+
+ &cmp (&wparam(5),0);
+ &lea ($tbl,&DWP(&label("AES_Te")."-".&label("pic_point"),$tbl));
+ &jne (&label("picked_te"));
+ &lea ($tbl,&DWP(&label("AES_Td")."-".&label("AES_Te"),$tbl));
+ &set_label("picked_te");
+
+ # one can argue if this is required
+ &pushf ();
+ &cld ();
+
+ &cmp ($s2,$speed_limit);
+ &jb (&label("slow_way"));
+ &test ($s2,15);
+ &jnz (&label("slow_way"));
+ if (!$x86only) {
+ &bt (&DWP(0,$s0),28); # check for hyper-threading bit
+ &jc (&label("slow_way"));
+ }
+ # pre-allocate aligned stack frame...
+ &lea ($acc,&DWP(-80-244,"esp"));
+ &and ($acc,-64);
+
+ # ... and make sure it doesn't alias with $tbl modulo 4096
+ &mov ($s0,$tbl);
+ &lea ($s1,&DWP(2048+256,$tbl));
+ &mov ($s3,$acc);
+ &and ($s0,0xfff); # s = %ebp&0xfff
+ &and ($s1,0xfff); # e = (%ebp+2048+256)&0xfff
+ &and ($s3,0xfff); # p = %esp&0xfff
+
+ &cmp ($s3,$s1); # if (p>=e) %esp =- (p-e);
+ &jb (&label("tbl_break_out"));
+ &sub ($s3,$s1);
+ &sub ($acc,$s3);
+ &jmp (&label("tbl_ok"));
+ &set_label("tbl_break_out",4); # else %esp -= (p-s)&0xfff + framesz;
+ &sub ($s3,$s0);
+ &and ($s3,0xfff);
+ &add ($s3,384);
+ &sub ($acc,$s3);
+ &set_label("tbl_ok",4);
+
+ &lea ($s3,&wparam(0)); # obtain pointer to parameter block
+ &exch ("esp",$acc); # allocate stack frame
+ &add ("esp",4); # reserve for return address!
+ &mov ($_tbl,$tbl); # save %ebp
+ &mov ($_esp,$acc); # save %esp
+
+ &mov ($s0,&DWP(0,$s3)); # load inp
+ &mov ($s1,&DWP(4,$s3)); # load out
+ #&mov ($s2,&DWP(8,$s3)); # load len
+ &mov ($key,&DWP(12,$s3)); # load key
+ &mov ($acc,&DWP(16,$s3)); # load ivp
+ &mov ($s3,&DWP(20,$s3)); # load enc flag
+
+ &mov ($_inp,$s0); # save copy of inp
+ &mov ($_out,$s1); # save copy of out
+ &mov ($_len,$s2); # save copy of len
+ &mov ($_key,$key); # save copy of key
+ &mov ($_ivp,$acc); # save copy of ivp
+
+ &mov ($mark,0); # copy of aes_key->rounds = 0;
+ # do we copy key schedule to stack?
+ &mov ($s1 eq "ebx" ? $s1 : "",$key);
+ &mov ($s2 eq "ecx" ? $s2 : "",244/4);
+ &sub ($s1,$tbl);
+ &mov ("esi",$key);
+ &and ($s1,0xfff);
+ &lea ("edi",$aes_key);
+ &cmp ($s1,2048+256);
+ &jb (&label("do_copy"));
+ &cmp ($s1,4096-244);
+ &jb (&label("skip_copy"));
+ &set_label("do_copy",4);
+ &mov ($_key,"edi");
+ &data_word(0xA5F3F689); # rep movsd
+ &set_label("skip_copy");
+
+ &mov ($key,16);
+ &set_label("prefetch_tbl",4);
+ &mov ($s0,&DWP(0,$tbl));
+ &mov ($s1,&DWP(32,$tbl));
+ &mov ($s2,&DWP(64,$tbl));
+ &mov ($acc,&DWP(96,$tbl));
+ &lea ($tbl,&DWP(128,$tbl));
+ &sub ($key,1);
+ &jnz (&label("prefetch_tbl"));
+ &sub ($tbl,2048);
+
+ &mov ($acc,$_inp);
+ &mov ($key,$_ivp);
+
+ &cmp ($s3,0);
+ &je (&label("fast_decrypt"));
+
+#----------------------------- ENCRYPT -----------------------------#
+ &mov ($s0,&DWP(0,$key)); # load iv
+ &mov ($s1,&DWP(4,$key));
+
+ &set_label("fast_enc_loop",16);
+ &mov ($s2,&DWP(8,$key));
+ &mov ($s3,&DWP(12,$key));
+
+ &xor ($s0,&DWP(0,$acc)); # xor input data
+ &xor ($s1,&DWP(4,$acc));
+ &xor ($s2,&DWP(8,$acc));
+ &xor ($s3,&DWP(12,$acc));
+
+ &mov ($key,$_key); # load key
+ &call ("_x86_AES_encrypt");
+
+ &mov ($acc,$_inp); # load inp
+ &mov ($key,$_out); # load out
+
+ &mov (&DWP(0,$key),$s0); # save output data
+ &mov (&DWP(4,$key),$s1);
+ &mov (&DWP(8,$key),$s2);
+ &mov (&DWP(12,$key),$s3);
+
+ &lea ($acc,&DWP(16,$acc)); # advance inp
+ &mov ($s2,$_len); # load len
+ &mov ($_inp,$acc); # save inp
+ &lea ($s3,&DWP(16,$key)); # advance out
+ &mov ($_out,$s3); # save out
+ &sub ($s2,16); # decrease len
+ &mov ($_len,$s2); # save len
+ &jnz (&label("fast_enc_loop"));
+ &mov ($acc,$_ivp); # load ivp
+ &mov ($s2,&DWP(8,$key)); # restore last 2 dwords
+ &mov ($s3,&DWP(12,$key));
+ &mov (&DWP(0,$acc),$s0); # save ivec
+ &mov (&DWP(4,$acc),$s1);
+ &mov (&DWP(8,$acc),$s2);
+ &mov (&DWP(12,$acc),$s3);
+
+ &cmp ($mark,0); # was the key schedule copied?
+ &mov ("edi",$_key);
+ &je (&label("skip_ezero"));
+ # zero copy of key schedule
+ &mov ("ecx",240/4);
+ &xor ("eax","eax");
+ &align (4);
+ &data_word(0xABF3F689); # rep stosd
+ &set_label("skip_ezero");
+ &mov ("esp",$_esp);
+ &popf ();
+ &set_label("drop_out");
+ &function_end_A();
+ &pushf (); # kludge, never executed
+
+#----------------------------- DECRYPT -----------------------------#
+&set_label("fast_decrypt",16);
+
+ &cmp ($acc,$_out);
+ &je (&label("fast_dec_in_place")); # in-place processing...
+
+ &mov ($_tmp,$key);
+
+ &align (4);
+ &set_label("fast_dec_loop",16);
+ &mov ($s0,&DWP(0,$acc)); # read input
+ &mov ($s1,&DWP(4,$acc));
+ &mov ($s2,&DWP(8,$acc));
+ &mov ($s3,&DWP(12,$acc));
+
+ &mov ($key,$_key); # load key
+ &call ("_x86_AES_decrypt");
+
+ &mov ($key,$_tmp); # load ivp
+ &mov ($acc,$_len); # load len
+ &xor ($s0,&DWP(0,$key)); # xor iv
+ &xor ($s1,&DWP(4,$key));
+ &xor ($s2,&DWP(8,$key));
+ &xor ($s3,&DWP(12,$key));
+
+ &mov ($key,$_out); # load out
+ &mov ($acc,$_inp); # load inp
+
+ &mov (&DWP(0,$key),$s0); # write output
+ &mov (&DWP(4,$key),$s1);
+ &mov (&DWP(8,$key),$s2);
+ &mov (&DWP(12,$key),$s3);
+
+ &mov ($s2,$_len); # load len
+ &mov ($_tmp,$acc); # save ivp
+ &lea ($acc,&DWP(16,$acc)); # advance inp
+ &mov ($_inp,$acc); # save inp
+ &lea ($key,&DWP(16,$key)); # advance out
+ &mov ($_out,$key); # save out
+ &sub ($s2,16); # decrease len
+ &mov ($_len,$s2); # save len
+ &jnz (&label("fast_dec_loop"));
+ &mov ($key,$_tmp); # load temp ivp
+ &mov ($acc,$_ivp); # load user ivp
+ &mov ($s0,&DWP(0,$key)); # load iv
+ &mov ($s1,&DWP(4,$key));
+ &mov ($s2,&DWP(8,$key));
+ &mov ($s3,&DWP(12,$key));
+ &mov (&DWP(0,$acc),$s0); # copy back to user
+ &mov (&DWP(4,$acc),$s1);
+ &mov (&DWP(8,$acc),$s2);
+ &mov (&DWP(12,$acc),$s3);
+ &jmp (&label("fast_dec_out"));
+
+ &set_label("fast_dec_in_place",16);
+ &set_label("fast_dec_in_place_loop");
+ &mov ($s0,&DWP(0,$acc)); # read input
+ &mov ($s1,&DWP(4,$acc));
+ &mov ($s2,&DWP(8,$acc));
+ &mov ($s3,&DWP(12,$acc));
+
+ &lea ($key,$ivec);
+ &mov (&DWP(0,$key),$s0); # copy to temp
+ &mov (&DWP(4,$key),$s1);
+ &mov (&DWP(8,$key),$s2);
+ &mov (&DWP(12,$key),$s3);
+
+ &mov ($key,$_key); # load key
+ &call ("_x86_AES_decrypt");
+
+ &mov ($key,$_ivp); # load ivp
+ &mov ($acc,$_out); # load out
+ &xor ($s0,&DWP(0,$key)); # xor iv
+ &xor ($s1,&DWP(4,$key));
+ &xor ($s2,&DWP(8,$key));
+ &xor ($s3,&DWP(12,$key));
+
+ &mov (&DWP(0,$acc),$s0); # write output
+ &mov (&DWP(4,$acc),$s1);
+ &mov (&DWP(8,$acc),$s2);
+ &mov (&DWP(12,$acc),$s3);
+
+ &lea ($acc,&DWP(16,$acc)); # advance out
+ &mov ($_out,$acc); # save out
+
+ &lea ($acc,$ivec);
+ &mov ($s0,&DWP(0,$acc)); # read temp
+ &mov ($s1,&DWP(4,$acc));
+ &mov ($s2,&DWP(8,$acc));
+ &mov ($s3,&DWP(12,$acc));
+
+ &mov (&DWP(0,$key),$s0); # copy iv
+ &mov (&DWP(4,$key),$s1);
+ &mov (&DWP(8,$key),$s2);
+ &mov (&DWP(12,$key),$s3);
+
+ &mov ($acc,$_inp); # load inp
+ &mov ($s2,$_len); # load len
+ &lea ($acc,&DWP(16,$acc)); # advance inp
+ &mov ($_inp,$acc); # save inp
+ &sub ($s2,16); # decrease len
+ &mov ($_len,$s2); # save len
+ &jnz (&label("fast_dec_in_place_loop"));
+
+ &set_label("fast_dec_out",4);
+ &cmp ($mark,0); # was the key schedule copied?
+ &mov ("edi",$_key);
+ &je (&label("skip_dzero"));
+ # zero copy of key schedule
+ &mov ("ecx",240/4);
+ &xor ("eax","eax");
+ &align (4);
+ &data_word(0xABF3F689); # rep stosd
+ &set_label("skip_dzero");
+ &mov ("esp",$_esp);
+ &popf ();
+ &function_end_A();
+ &pushf (); # kludge, never executed
+
+#--------------------------- SLOW ROUTINE ---------------------------#
+&set_label("slow_way",16);
+
+ &mov ($s0,&DWP(0,$s0)) if (!$x86only);# load OPENSSL_ia32cap
+ &mov ($key,&wparam(3)); # load key
+
+ # pre-allocate aligned stack frame...
+ &lea ($acc,&DWP(-80,"esp"));
+ &and ($acc,-64);
+
+ # ... and make sure it doesn't alias with $key modulo 1024
+ &lea ($s1,&DWP(-80-63,$key));
+ &sub ($s1,$acc);
+ &neg ($s1);
+ &and ($s1,0x3C0); # modulo 1024, but aligned to cache-line
+ &sub ($acc,$s1);
+
+ # pick S-box copy which can't overlap with stack frame or $key
+ &lea ($s1,&DWP(768,$acc));
+ &sub ($s1,$tbl);
+ &and ($s1,0x300);
+ &lea ($tbl,&DWP(2048+128,$tbl,$s1));
+
+ &lea ($s3,&wparam(0)); # pointer to parameter block
+
+ &exch ("esp",$acc);
+ &add ("esp",4); # reserve for return address!
+ &mov ($_tbl,$tbl); # save %ebp
+ &mov ($_esp,$acc); # save %esp
+ &mov ($_tmp,$s0); # save OPENSSL_ia32cap
+
+ &mov ($s0,&DWP(0,$s3)); # load inp
+ &mov ($s1,&DWP(4,$s3)); # load out
+ #&mov ($s2,&DWP(8,$s3)); # load len
+ #&mov ($key,&DWP(12,$s3)); # load key
+ &mov ($acc,&DWP(16,$s3)); # load ivp
+ &mov ($s3,&DWP(20,$s3)); # load enc flag
+
+ &mov ($_inp,$s0); # save copy of inp
+ &mov ($_out,$s1); # save copy of out
+ &mov ($_len,$s2); # save copy of len
+ &mov ($_key,$key); # save copy of key
+ &mov ($_ivp,$acc); # save copy of ivp
+
+ &mov ($key,$acc);
+ &mov ($acc,$s0);
+
+ &cmp ($s3,0);
+ &je (&label("slow_decrypt"));
+
+#--------------------------- SLOW ENCRYPT ---------------------------#
+ &cmp ($s2,16);
+ &mov ($s3,$s1);
+ &jb (&label("slow_enc_tail"));
+
+ if (!$x86only) {
+ &bt ($_tmp,25); # check for SSE bit
+ &jnc (&label("slow_enc_x86"));
+
+ &movq ("mm0",&QWP(0,$key)); # load iv
+ &movq ("mm4",&QWP(8,$key));
+
+ &set_label("slow_enc_loop_sse",16);
+ &pxor ("mm0",&QWP(0,$acc)); # xor input data
+ &pxor ("mm4",&QWP(8,$acc));
+
+ &mov ($key,$_key);
+ &call ("_sse_AES_encrypt_compact");
+
+ &mov ($acc,$_inp); # load inp
+ &mov ($key,$_out); # load out
+ &mov ($s2,$_len); # load len
+
+ &movq (&QWP(0,$key),"mm0"); # save output data
+ &movq (&QWP(8,$key),"mm4");
+
+ &lea ($acc,&DWP(16,$acc)); # advance inp
+ &mov ($_inp,$acc); # save inp
+ &lea ($s3,&DWP(16,$key)); # advance out
+ &mov ($_out,$s3); # save out
+ &sub ($s2,16); # decrease len
+ &cmp ($s2,16);
+ &mov ($_len,$s2); # save len
+ &jae (&label("slow_enc_loop_sse"));
+ &test ($s2,15);
+ &jnz (&label("slow_enc_tail"));
+ &mov ($acc,$_ivp); # load ivp
+ &movq (&QWP(0,$acc),"mm0"); # save ivec
+ &movq (&QWP(8,$acc),"mm4");
+ &emms ();
+ &mov ("esp",$_esp);
+ &popf ();
+ &function_end_A();
+ &pushf (); # kludge, never executed
+ }
+ &set_label("slow_enc_x86",16);
+ &mov ($s0,&DWP(0,$key)); # load iv
+ &mov ($s1,&DWP(4,$key));
+
+ &set_label("slow_enc_loop_x86",4);
+ &mov ($s2,&DWP(8,$key));
+ &mov ($s3,&DWP(12,$key));
+
+ &xor ($s0,&DWP(0,$acc)); # xor input data
+ &xor ($s1,&DWP(4,$acc));
+ &xor ($s2,&DWP(8,$acc));
+ &xor ($s3,&DWP(12,$acc));
+
+ &mov ($key,$_key); # load key
+ &call ("_x86_AES_encrypt_compact");
+
+ &mov ($acc,$_inp); # load inp
+ &mov ($key,$_out); # load out
+
+ &mov (&DWP(0,$key),$s0); # save output data
+ &mov (&DWP(4,$key),$s1);
+ &mov (&DWP(8,$key),$s2);
+ &mov (&DWP(12,$key),$s3);
+
+ &mov ($s2,$_len); # load len
+ &lea ($acc,&DWP(16,$acc)); # advance inp
+ &mov ($_inp,$acc); # save inp
+ &lea ($s3,&DWP(16,$key)); # advance out
+ &mov ($_out,$s3); # save out
+ &sub ($s2,16); # decrease len
+ &cmp ($s2,16);
+ &mov ($_len,$s2); # save len
+ &jae (&label("slow_enc_loop_x86"));
+ &test ($s2,15);
+ &jnz (&label("slow_enc_tail"));
+ &mov ($acc,$_ivp); # load ivp
+ &mov ($s2,&DWP(8,$key)); # restore last dwords
+ &mov ($s3,&DWP(12,$key));
+ &mov (&DWP(0,$acc),$s0); # save ivec
+ &mov (&DWP(4,$acc),$s1);
+ &mov (&DWP(8,$acc),$s2);
+ &mov (&DWP(12,$acc),$s3);
+
+ &mov ("esp",$_esp);
+ &popf ();
+ &function_end_A();
+ &pushf (); # kludge, never executed
+
+ &set_label("slow_enc_tail",16);
+ &emms () if (!$x86only);
+ &mov ($key eq "edi"? $key:"",$s3); # load out to edi
+ &mov ($s1,16);
+ &sub ($s1,$s2);
+ &cmp ($key,$acc eq "esi"? $acc:""); # compare with inp
+ &je (&label("enc_in_place"));
+ &align (4);
+ &data_word(0xA4F3F689); # rep movsb # copy input
+ &jmp (&label("enc_skip_in_place"));
+ &set_label("enc_in_place");
+ &lea ($key,&DWP(0,$key,$s2));
+ &set_label("enc_skip_in_place");
+ &mov ($s2,$s1);
+ &xor ($s0,$s0);
+ &align (4);
+ &data_word(0xAAF3F689); # rep stosb # zero tail
+
+ &mov ($key,$_ivp); # restore ivp
+ &mov ($acc,$s3); # output as input
+ &mov ($s0,&DWP(0,$key));
+ &mov ($s1,&DWP(4,$key));
+ &mov ($_len,16); # len=16
+ &jmp (&label("slow_enc_loop_x86")); # one more spin...
+
+#--------------------------- SLOW DECRYPT ---------------------------#
+&set_label("slow_decrypt",16);
+ if (!$x86only) {
+ &bt ($_tmp,25); # check for SSE bit
+ &jnc (&label("slow_dec_loop_x86"));
+
+ &set_label("slow_dec_loop_sse",4);
+ &movq ("mm0",&QWP(0,$acc)); # read input
+ &movq ("mm4",&QWP(8,$acc));
+
+ &mov ($key,$_key);
+ &call ("_sse_AES_decrypt_compact");
+
+ &mov ($acc,$_inp); # load inp
+ &lea ($s0,$ivec);
+ &mov ($s1,$_out); # load out
+ &mov ($s2,$_len); # load len
+ &mov ($key,$_ivp); # load ivp
+
+ &movq ("mm1",&QWP(0,$acc)); # re-read input
+ &movq ("mm5",&QWP(8,$acc));
+
+ &pxor ("mm0",&QWP(0,$key)); # xor iv
+ &pxor ("mm4",&QWP(8,$key));
+
+ &movq (&QWP(0,$key),"mm1"); # copy input to iv
+ &movq (&QWP(8,$key),"mm5");
+
+ &sub ($s2,16); # decrease len
+ &jc (&label("slow_dec_partial_sse"));
+
+ &movq (&QWP(0,$s1),"mm0"); # write output
+ &movq (&QWP(8,$s1),"mm4");
+
+ &lea ($s1,&DWP(16,$s1)); # advance out
+ &mov ($_out,$s1); # save out
+ &lea ($acc,&DWP(16,$acc)); # advance inp
+ &mov ($_inp,$acc); # save inp
+ &mov ($_len,$s2); # save len
+ &jnz (&label("slow_dec_loop_sse"));
+ &emms ();
+ &mov ("esp",$_esp);
+ &popf ();
+ &function_end_A();
+ &pushf (); # kludge, never executed
+
+ &set_label("slow_dec_partial_sse",16);
+ &movq (&QWP(0,$s0),"mm0"); # save output to temp
+ &movq (&QWP(8,$s0),"mm4");
+ &emms ();
+
+ &add ($s2 eq "ecx" ? "ecx":"",16);
+ &mov ("edi",$s1); # out
+ &mov ("esi",$s0); # temp
+ &align (4);
+ &data_word(0xA4F3F689); # rep movsb # copy partial output
+
+ &mov ("esp",$_esp);
+ &popf ();
+ &function_end_A();
+ &pushf (); # kludge, never executed
+ }
+ &set_label("slow_dec_loop_x86",16);
+ &mov ($s0,&DWP(0,$acc)); # read input
+ &mov ($s1,&DWP(4,$acc));
+ &mov ($s2,&DWP(8,$acc));
+ &mov ($s3,&DWP(12,$acc));
+
+ &lea ($key,$ivec);
+ &mov (&DWP(0,$key),$s0); # copy to temp
+ &mov (&DWP(4,$key),$s1);
+ &mov (&DWP(8,$key),$s2);
+ &mov (&DWP(12,$key),$s3);
+
+ &mov ($key,$_key); # load key
+ &call ("_x86_AES_decrypt_compact");
+
+ &mov ($key,$_ivp); # load ivp
+ &mov ($acc,$_len); # load len
+ &xor ($s0,&DWP(0,$key)); # xor iv
+ &xor ($s1,&DWP(4,$key));
+ &xor ($s2,&DWP(8,$key));
+ &xor ($s3,&DWP(12,$key));
+
+ &sub ($acc,16);
+ &jc (&label("slow_dec_partial_x86"));
+
+ &mov ($_len,$acc); # save len
+ &mov ($acc,$_out); # load out
+
+ &mov (&DWP(0,$acc),$s0); # write output
+ &mov (&DWP(4,$acc),$s1);
+ &mov (&DWP(8,$acc),$s2);
+ &mov (&DWP(12,$acc),$s3);
+
+ &lea ($acc,&DWP(16,$acc)); # advance out
+ &mov ($_out,$acc); # save out
+
+ &lea ($acc,$ivec);
+ &mov ($s0,&DWP(0,$acc)); # read temp
+ &mov ($s1,&DWP(4,$acc));
+ &mov ($s2,&DWP(8,$acc));
+ &mov ($s3,&DWP(12,$acc));
+
+ &mov (&DWP(0,$key),$s0); # copy it to iv
+ &mov (&DWP(4,$key),$s1);
+ &mov (&DWP(8,$key),$s2);
+ &mov (&DWP(12,$key),$s3);
+
+ &mov ($acc,$_inp); # load inp
+ &lea ($acc,&DWP(16,$acc)); # advance inp
+ &mov ($_inp,$acc); # save inp
+ &jnz (&label("slow_dec_loop_x86"));
+ &mov ("esp",$_esp);
+ &popf ();
+ &function_end_A();
+ &pushf (); # kludge, never executed
+
+ &set_label("slow_dec_partial_x86",16);
+ &lea ($acc,$ivec);
+ &mov (&DWP(0,$acc),$s0); # save output to temp
+ &mov (&DWP(4,$acc),$s1);
+ &mov (&DWP(8,$acc),$s2);
+ &mov (&DWP(12,$acc),$s3);
+
+ &mov ($acc,$_inp);
+ &mov ($s0,&DWP(0,$acc)); # re-read input
+ &mov ($s1,&DWP(4,$acc));
+ &mov ($s2,&DWP(8,$acc));
+ &mov ($s3,&DWP(12,$acc));
+
+ &mov (&DWP(0,$key),$s0); # copy it to iv
+ &mov (&DWP(4,$key),$s1);
+ &mov (&DWP(8,$key),$s2);
+ &mov (&DWP(12,$key),$s3);
+
+ &mov ("ecx",$_len);
+ &mov ("edi",$_out);
+ &lea ("esi",$ivec);
+ &align (4);
+ &data_word(0xA4F3F689); # rep movsb # copy partial output
+
+ &mov ("esp",$_esp);
+ &popf ();
+&function_end("asm_AES_cbc_encrypt");
+}
+
+#------------------------------------------------------------------#
+
+sub enckey()
+{
+ &movz ("esi",&LB("edx")); # rk[i]>>0
+ &movz ("ebx",&BP(-128,$tbl,"esi",1));
+ &movz ("esi",&HB("edx")); # rk[i]>>8
+ &shl ("ebx",24);
+ &xor ("eax","ebx");
+
+ &movz ("ebx",&BP(-128,$tbl,"esi",1));
+ &shr ("edx",16);
+ &movz ("esi",&LB("edx")); # rk[i]>>16
+ &xor ("eax","ebx");
+
+ &movz ("ebx",&BP(-128,$tbl,"esi",1));
+ &movz ("esi",&HB("edx")); # rk[i]>>24
+ &shl ("ebx",8);
+ &xor ("eax","ebx");
+
+ &movz ("ebx",&BP(-128,$tbl,"esi",1));
+ &shl ("ebx",16);
+ &xor ("eax","ebx");
+
+ &xor ("eax",&DWP(1024-128,$tbl,"ecx",4)); # rcon
+}
+
+&function_begin("_x86_AES_set_encrypt_key");
+ &mov ("esi",&wparam(1)); # user supplied key
+ &mov ("edi",&wparam(3)); # private key schedule
+
+ &test ("esi",-1);
+ &jz (&label("badpointer"));
+ &test ("edi",-1);
+ &jz (&label("badpointer"));
+
+ &call (&label("pic_point"));
+ &set_label("pic_point");
+ &blindpop($tbl);
+ &lea ($tbl,&DWP(&label("AES_Te")."-".&label("pic_point"),$tbl));
+ &lea ($tbl,&DWP(2048+128,$tbl));
+
+ # prefetch Te4
+ &mov ("eax",&DWP(0-128,$tbl));
+ &mov ("ebx",&DWP(32-128,$tbl));
+ &mov ("ecx",&DWP(64-128,$tbl));
+ &mov ("edx",&DWP(96-128,$tbl));
+ &mov ("eax",&DWP(128-128,$tbl));
+ &mov ("ebx",&DWP(160-128,$tbl));
+ &mov ("ecx",&DWP(192-128,$tbl));
+ &mov ("edx",&DWP(224-128,$tbl));
+
+ &mov ("ecx",&wparam(2)); # number of bits in key
+ &cmp ("ecx",128);
+ &je (&label("10rounds"));
+ &cmp ("ecx",192);
+ &je (&label("12rounds"));
+ &cmp ("ecx",256);
+ &je (&label("14rounds"));
+ &mov ("eax",-2); # invalid number of bits
+ &jmp (&label("exit"));
+
+ &set_label("10rounds");
+ &mov ("eax",&DWP(0,"esi")); # copy first 4 dwords
+ &mov ("ebx",&DWP(4,"esi"));
+ &mov ("ecx",&DWP(8,"esi"));
+ &mov ("edx",&DWP(12,"esi"));
+ &mov (&DWP(0,"edi"),"eax");
+ &mov (&DWP(4,"edi"),"ebx");
+ &mov (&DWP(8,"edi"),"ecx");
+ &mov (&DWP(12,"edi"),"edx");
+
+ &xor ("ecx","ecx");
+ &jmp (&label("10shortcut"));
+
+ &align (4);
+ &set_label("10loop");
+ &mov ("eax",&DWP(0,"edi")); # rk[0]
+ &mov ("edx",&DWP(12,"edi")); # rk[3]
+ &set_label("10shortcut");
+ &enckey ();
+
+ &mov (&DWP(16,"edi"),"eax"); # rk[4]
+ &xor ("eax",&DWP(4,"edi"));
+ &mov (&DWP(20,"edi"),"eax"); # rk[5]
+ &xor ("eax",&DWP(8,"edi"));
+ &mov (&DWP(24,"edi"),"eax"); # rk[6]
+ &xor ("eax",&DWP(12,"edi"));
+ &mov (&DWP(28,"edi"),"eax"); # rk[7]
+ &inc ("ecx");
+ &add ("edi",16);
+ &cmp ("ecx",10);
+ &jl (&label("10loop"));
+
+ &mov (&DWP(80,"edi"),10); # setup number of rounds
+ &xor ("eax","eax");
+ &jmp (&label("exit"));
+
+ &set_label("12rounds");
+ &mov ("eax",&DWP(0,"esi")); # copy first 6 dwords
+ &mov ("ebx",&DWP(4,"esi"));
+ &mov ("ecx",&DWP(8,"esi"));
+ &mov ("edx",&DWP(12,"esi"));
+ &mov (&DWP(0,"edi"),"eax");
+ &mov (&DWP(4,"edi"),"ebx");
+ &mov (&DWP(8,"edi"),"ecx");
+ &mov (&DWP(12,"edi"),"edx");
+ &mov ("ecx",&DWP(16,"esi"));
+ &mov ("edx",&DWP(20,"esi"));
+ &mov (&DWP(16,"edi"),"ecx");
+ &mov (&DWP(20,"edi"),"edx");
+
+ &xor ("ecx","ecx");
+ &jmp (&label("12shortcut"));
+
+ &align (4);
+ &set_label("12loop");
+ &mov ("eax",&DWP(0,"edi")); # rk[0]
+ &mov ("edx",&DWP(20,"edi")); # rk[5]
+ &set_label("12shortcut");
+ &enckey ();
+
+ &mov (&DWP(24,"edi"),"eax"); # rk[6]
+ &xor ("eax",&DWP(4,"edi"));
+ &mov (&DWP(28,"edi"),"eax"); # rk[7]
+ &xor ("eax",&DWP(8,"edi"));
+ &mov (&DWP(32,"edi"),"eax"); # rk[8]
+ &xor ("eax",&DWP(12,"edi"));
+ &mov (&DWP(36,"edi"),"eax"); # rk[9]
+
+ &cmp ("ecx",7);
+ &je (&label("12break"));
+ &inc ("ecx");
+
+ &xor ("eax",&DWP(16,"edi"));
+ &mov (&DWP(40,"edi"),"eax"); # rk[10]
+ &xor ("eax",&DWP(20,"edi"));
+ &mov (&DWP(44,"edi"),"eax"); # rk[11]
+
+ &add ("edi",24);
+ &jmp (&label("12loop"));
+
+ &set_label("12break");
+ &mov (&DWP(72,"edi"),12); # setup number of rounds
+ &xor ("eax","eax");
+ &jmp (&label("exit"));
+
+ &set_label("14rounds");
+ &mov ("eax",&DWP(0,"esi")); # copy first 8 dwords
+ &mov ("ebx",&DWP(4,"esi"));
+ &mov ("ecx",&DWP(8,"esi"));
+ &mov ("edx",&DWP(12,"esi"));
+ &mov (&DWP(0,"edi"),"eax");
+ &mov (&DWP(4,"edi"),"ebx");
+ &mov (&DWP(8,"edi"),"ecx");
+ &mov (&DWP(12,"edi"),"edx");
+ &mov ("eax",&DWP(16,"esi"));
+ &mov ("ebx",&DWP(20,"esi"));
+ &mov ("ecx",&DWP(24,"esi"));
+ &mov ("edx",&DWP(28,"esi"));
+ &mov (&DWP(16,"edi"),"eax");
+ &mov (&DWP(20,"edi"),"ebx");
+ &mov (&DWP(24,"edi"),"ecx");
+ &mov (&DWP(28,"edi"),"edx");
+
+ &xor ("ecx","ecx");
+ &jmp (&label("14shortcut"));
+
+ &align (4);
+ &set_label("14loop");
+ &mov ("edx",&DWP(28,"edi")); # rk[7]
+ &set_label("14shortcut");
+ &mov ("eax",&DWP(0,"edi")); # rk[0]
+
+ &enckey ();
+
+ &mov (&DWP(32,"edi"),"eax"); # rk[8]
+ &xor ("eax",&DWP(4,"edi"));
+ &mov (&DWP(36,"edi"),"eax"); # rk[9]
+ &xor ("eax",&DWP(8,"edi"));
+ &mov (&DWP(40,"edi"),"eax"); # rk[10]
+ &xor ("eax",&DWP(12,"edi"));
+ &mov (&DWP(44,"edi"),"eax"); # rk[11]
+
+ &cmp ("ecx",6);
+ &je (&label("14break"));
+ &inc ("ecx");
+
+ &mov ("edx","eax");
+ &mov ("eax",&DWP(16,"edi")); # rk[4]
+ &movz ("esi",&LB("edx")); # rk[11]>>0
+ &movz ("ebx",&BP(-128,$tbl,"esi",1));
+ &movz ("esi",&HB("edx")); # rk[11]>>8
+ &xor ("eax","ebx");
+
+ &movz ("ebx",&BP(-128,$tbl,"esi",1));
+ &shr ("edx",16);
+ &shl ("ebx",8);
+ &movz ("esi",&LB("edx")); # rk[11]>>16
+ &xor ("eax","ebx");
+
+ &movz ("ebx",&BP(-128,$tbl,"esi",1));
+ &movz ("esi",&HB("edx")); # rk[11]>>24
+ &shl ("ebx",16);
+ &xor ("eax","ebx");
+
+ &movz ("ebx",&BP(-128,$tbl,"esi",1));
+ &shl ("ebx",24);
+ &xor ("eax","ebx");
+
+ &mov (&DWP(48,"edi"),"eax"); # rk[12]
+ &xor ("eax",&DWP(20,"edi"));
+ &mov (&DWP(52,"edi"),"eax"); # rk[13]
+ &xor ("eax",&DWP(24,"edi"));
+ &mov (&DWP(56,"edi"),"eax"); # rk[14]
+ &xor ("eax",&DWP(28,"edi"));
+ &mov (&DWP(60,"edi"),"eax"); # rk[15]
+
+ &add ("edi",32);
+ &jmp (&label("14loop"));
+
+ &set_label("14break");
+ &mov (&DWP(48,"edi"),14); # setup number of rounds
+ &xor ("eax","eax");
+ &jmp (&label("exit"));
+
+ &set_label("badpointer");
+ &mov ("eax",-1);
+ &set_label("exit");
+&function_end("_x86_AES_set_encrypt_key");
+
+# int asm_AES_set_encrypt_key(const unsigned char *userKey, const int bits,
+# AES_KEY *key)
+&function_begin_B("asm_AES_set_encrypt_key");
+ &call ("_x86_AES_set_encrypt_key");
+ &ret ();
+&function_end_B("asm_AES_set_encrypt_key");
+
+sub deckey()
+{ my ($i,$key,$tp1,$tp2,$tp4,$tp8) = @_;
+ my $tmp = $tbl;
+
+ &mov ($tmp,0x80808080);
+ &and ($tmp,$tp1);
+ &lea ($tp2,&DWP(0,$tp1,$tp1));
+ &mov ($acc,$tmp);
+ &shr ($tmp,7);
+ &sub ($acc,$tmp);
+ &and ($tp2,0xfefefefe);
+ &and ($acc,0x1b1b1b1b);
+ &xor ($tp2,$acc);
+ &mov ($tmp,0x80808080);
+
+ &and ($tmp,$tp2);
+ &lea ($tp4,&DWP(0,$tp2,$tp2));
+ &mov ($acc,$tmp);
+ &shr ($tmp,7);
+ &sub ($acc,$tmp);
+ &and ($tp4,0xfefefefe);
+ &and ($acc,0x1b1b1b1b);
+ &xor ($tp2,$tp1); # tp2^tp1
+ &xor ($tp4,$acc);
+ &mov ($tmp,0x80808080);
+
+ &and ($tmp,$tp4);
+ &lea ($tp8,&DWP(0,$tp4,$tp4));
+ &mov ($acc,$tmp);
+ &shr ($tmp,7);
+ &xor ($tp4,$tp1); # tp4^tp1
+ &sub ($acc,$tmp);
+ &and ($tp8,0xfefefefe);
+ &and ($acc,0x1b1b1b1b);
+ &rotl ($tp1,8); # = ROTATE(tp1,8)
+ &xor ($tp8,$acc);
+
+ &mov ($tmp,&DWP(4*($i+1),$key)); # modulo-scheduled load
+
+ &xor ($tp1,$tp2);
+ &xor ($tp2,$tp8);
+ &xor ($tp1,$tp4);
+ &rotl ($tp2,24);
+ &xor ($tp4,$tp8);
+ &xor ($tp1,$tp8); # ^= tp8^(tp4^tp1)^(tp2^tp1)
+ &rotl ($tp4,16);
+ &xor ($tp1,$tp2); # ^= ROTATE(tp8^tp2^tp1,24)
+ &rotl ($tp8,8);
+ &xor ($tp1,$tp4); # ^= ROTATE(tp8^tp4^tp1,16)
+ &mov ($tp2,$tmp);
+ &xor ($tp1,$tp8); # ^= ROTATE(tp8,8)
+
+ &mov (&DWP(4*$i,$key),$tp1);
+}
+
+# int asm_AES_set_decrypt_key(const unsigned char *userKey, const int bits,
+# AES_KEY *key)
+&function_begin_B("asm_AES_set_decrypt_key");
+ &call ("_x86_AES_set_encrypt_key");
+ &cmp ("eax",0);
+ &je (&label("proceed"));
+ &ret ();
+
+ &set_label("proceed");
+ &push ("ebp");
+ &push ("ebx");
+ &push ("esi");
+ &push ("edi");
+
+ &mov ("esi",&wparam(2));
+ &mov ("ecx",&DWP(240,"esi")); # pull number of rounds
+ &lea ("ecx",&DWP(0,"","ecx",4));
+ &lea ("edi",&DWP(0,"esi","ecx",4)); # pointer to last chunk
+
+ &set_label("invert",4); # invert order of chunks
+ &mov ("eax",&DWP(0,"esi"));
+ &mov ("ebx",&DWP(4,"esi"));
+ &mov ("ecx",&DWP(0,"edi"));
+ &mov ("edx",&DWP(4,"edi"));
+ &mov (&DWP(0,"edi"),"eax");
+ &mov (&DWP(4,"edi"),"ebx");
+ &mov (&DWP(0,"esi"),"ecx");
+ &mov (&DWP(4,"esi"),"edx");
+ &mov ("eax",&DWP(8,"esi"));
+ &mov ("ebx",&DWP(12,"esi"));
+ &mov ("ecx",&DWP(8,"edi"));
+ &mov ("edx",&DWP(12,"edi"));
+ &mov (&DWP(8,"edi"),"eax");
+ &mov (&DWP(12,"edi"),"ebx");
+ &mov (&DWP(8,"esi"),"ecx");
+ &mov (&DWP(12,"esi"),"edx");
+ &add ("esi",16);
+ &sub ("edi",16);
+ &cmp ("esi","edi");
+ &jne (&label("invert"));
+
+ &mov ($key,&wparam(2));
+ &mov ($acc,&DWP(240,$key)); # pull number of rounds
+ &lea ($acc,&DWP(-2,$acc,$acc));
+ &lea ($acc,&DWP(0,$key,$acc,8));
+ &mov (&wparam(2),$acc);
+
+ &mov ($s0,&DWP(16,$key)); # modulo-scheduled load
+ &set_label("permute",4); # permute the key schedule
+ &add ($key,16);
+ &deckey (0,$key,$s0,$s1,$s2,$s3);
+ &deckey (1,$key,$s1,$s2,$s3,$s0);
+ &deckey (2,$key,$s2,$s3,$s0,$s1);
+ &deckey (3,$key,$s3,$s0,$s1,$s2);
+ &cmp ($key,&wparam(2));
+ &jb (&label("permute"));
+
+ &xor ("eax","eax"); # return success
+&function_end("asm_AES_set_decrypt_key");
+&asciz("AES for x86, CRYPTOGAMS by <appro\@openssl.org>");
+
+&asm_finish();
diff --git a/src/crypto/aes/asm/aes-armv4.pl b/src/crypto/aes/asm/aes-armv4.pl
new file mode 100644
index 0000000..3bd9a6d
--- /dev/null
+++ b/src/crypto/aes/asm/aes-armv4.pl
@@ -0,0 +1,1224 @@
+#!/usr/bin/env perl
+
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+# project. The module is, however, dual licensed under OpenSSL and
+# CRYPTOGAMS licenses depending on where you obtain it. For further
+# details see http://www.openssl.org/~appro/cryptogams/.
+# ====================================================================
+
+# AES for ARMv4
+
+# January 2007.
+#
+# Code uses single 1K S-box and is >2 times faster than code generated
+# by gcc-3.4.1. This is thanks to unique feature of ARMv4 ISA, which
+# allows to merge logical or arithmetic operation with shift or rotate
+# in one instruction and emit combined result every cycle. The module
+# is endian-neutral. The performance is ~42 cycles/byte for 128-bit
+# key [on single-issue Xscale PXA250 core].
+
+# May 2007.
+#
+# AES_set_[en|de]crypt_key is added.
+
+# July 2010.
+#
+# Rescheduling for dual-issue pipeline resulted in 12% improvement on
+# Cortex A8 core and ~25 cycles per byte processed with 128-bit key.
+
+# February 2011.
+#
+# Profiler-assisted and platform-specific optimization resulted in 16%
+# improvement on Cortex A8 core and ~21.5 cycles per byte.
+
+while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {}
+open STDOUT,">$output";
+
+$s0="r0";
+$s1="r1";
+$s2="r2";
+$s3="r3";
+$t1="r4";
+$t2="r5";
+$t3="r6";
+$i1="r7";
+$i2="r8";
+$i3="r9";
+
+$tbl="r10";
+$key="r11";
+$rounds="r12";
+
+$code=<<___;
+#if defined(__arm__)
+#ifndef __KERNEL__
+# include "arm_arch.h"
+#else
+# define __ARM_ARCH__ __LINUX_ARM_ARCH__
+#endif
+
+.text
+#if __ARM_ARCH__<7
+.code 32
+#else
+.syntax unified
+# ifdef __thumb2__
+.thumb
+# else
+.code 32
+# endif
+#endif
+
+.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 asm_AES_encrypt(const unsigned char *in, unsigned char *out,
+@ const AES_KEY *key) {
+.global asm_AES_encrypt
+.hidden asm_AES_encrypt
+.type asm_AES_encrypt,%function
+.align 5
+asm_AES_encrypt:
+#if __ARM_ARCH__<7
+ sub r3,pc,#8 @ asm_AES_encrypt
+#else
+ adr r3,asm_AES_encrypt
+#endif
+ stmdb sp!,{r1,r4-r12,lr}
+ mov $rounds,r0 @ inp
+ mov $key,r2
+ sub $tbl,r3,#asm_AES_encrypt-AES_Te @ Te
+#if __ARM_ARCH__<7
+ ldrb $s0,[$rounds,#3] @ load input data in endian-neutral
+ ldrb $t1,[$rounds,#2] @ manner...
+ ldrb $t2,[$rounds,#1]
+ ldrb $t3,[$rounds,#0]
+ orr $s0,$s0,$t1,lsl#8
+ ldrb $s1,[$rounds,#7]
+ orr $s0,$s0,$t2,lsl#16
+ ldrb $t1,[$rounds,#6]
+ orr $s0,$s0,$t3,lsl#24
+ ldrb $t2,[$rounds,#5]
+ ldrb $t3,[$rounds,#4]
+ orr $s1,$s1,$t1,lsl#8
+ ldrb $s2,[$rounds,#11]
+ orr $s1,$s1,$t2,lsl#16
+ ldrb $t1,[$rounds,#10]
+ orr $s1,$s1,$t3,lsl#24
+ ldrb $t2,[$rounds,#9]
+ ldrb $t3,[$rounds,#8]
+ orr $s2,$s2,$t1,lsl#8
+ ldrb $s3,[$rounds,#15]
+ orr $s2,$s2,$t2,lsl#16
+ ldrb $t1,[$rounds,#14]
+ orr $s2,$s2,$t3,lsl#24
+ ldrb $t2,[$rounds,#13]
+ ldrb $t3,[$rounds,#12]
+ orr $s3,$s3,$t1,lsl#8
+ orr $s3,$s3,$t2,lsl#16
+ orr $s3,$s3,$t3,lsl#24
+#else
+ ldr $s0,[$rounds,#0]
+ ldr $s1,[$rounds,#4]
+ ldr $s2,[$rounds,#8]
+ ldr $s3,[$rounds,#12]
+#ifdef __ARMEL__
+ rev $s0,$s0
+ rev $s1,$s1
+ rev $s2,$s2
+ rev $s3,$s3
+#endif
+#endif
+ bl _armv4_AES_encrypt
+
+ ldr $rounds,[sp],#4 @ pop out
+#if __ARM_ARCH__>=7
+#ifdef __ARMEL__
+ rev $s0,$s0
+ rev $s1,$s1
+ rev $s2,$s2
+ rev $s3,$s3
+#endif
+ str $s0,[$rounds,#0]
+ str $s1,[$rounds,#4]
+ str $s2,[$rounds,#8]
+ str $s3,[$rounds,#12]
+#else
+ mov $t1,$s0,lsr#24 @ write output in endian-neutral
+ mov $t2,$s0,lsr#16 @ manner...
+ mov $t3,$s0,lsr#8
+ strb $t1,[$rounds,#0]
+ strb $t2,[$rounds,#1]
+ mov $t1,$s1,lsr#24
+ strb $t3,[$rounds,#2]
+ mov $t2,$s1,lsr#16
+ strb $s0,[$rounds,#3]
+ mov $t3,$s1,lsr#8
+ strb $t1,[$rounds,#4]
+ strb $t2,[$rounds,#5]
+ mov $t1,$s2,lsr#24
+ strb $t3,[$rounds,#6]
+ mov $t2,$s2,lsr#16
+ strb $s1,[$rounds,#7]
+ mov $t3,$s2,lsr#8
+ strb $t1,[$rounds,#8]
+ strb $t2,[$rounds,#9]
+ mov $t1,$s3,lsr#24
+ strb $t3,[$rounds,#10]
+ mov $t2,$s3,lsr#16
+ strb $s2,[$rounds,#11]
+ mov $t3,$s3,lsr#8
+ strb $t1,[$rounds,#12]
+ strb $t2,[$rounds,#13]
+ strb $t3,[$rounds,#14]
+ strb $s3,[$rounds,#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
+ bx lr @ interoperable with Thumb ISA:-)
+#endif
+.size asm_AES_encrypt,.-asm_AES_encrypt
+
+.type _armv4_AES_encrypt,%function
+.align 2
+_armv4_AES_encrypt:
+ str lr,[sp,#-4]! @ push lr
+ ldmia $key!,{$t1-$i1}
+ eor $s0,$s0,$t1
+ ldr $rounds,[$key,#240-16]
+ eor $s1,$s1,$t2
+ eor $s2,$s2,$t3
+ eor $s3,$s3,$i1
+ sub $rounds,$rounds,#1
+ mov lr,#255
+
+ and $i1,lr,$s0
+ and $i2,lr,$s0,lsr#8
+ and $i3,lr,$s0,lsr#16
+ mov $s0,$s0,lsr#24
+.Lenc_loop:
+ ldr $t1,[$tbl,$i1,lsl#2] @ Te3[s0>>0]
+ and $i1,lr,$s1,lsr#16 @ i0
+ ldr $t2,[$tbl,$i2,lsl#2] @ Te2[s0>>8]
+ and $i2,lr,$s1
+ ldr $t3,[$tbl,$i3,lsl#2] @ Te1[s0>>16]
+ and $i3,lr,$s1,lsr#8
+ ldr $s0,[$tbl,$s0,lsl#2] @ Te0[s0>>24]
+ mov $s1,$s1,lsr#24
+
+ ldr $i1,[$tbl,$i1,lsl#2] @ Te1[s1>>16]
+ ldr $i2,[$tbl,$i2,lsl#2] @ Te3[s1>>0]
+ ldr $i3,[$tbl,$i3,lsl#2] @ Te2[s1>>8]
+ eor $s0,$s0,$i1,ror#8
+ ldr $s1,[$tbl,$s1,lsl#2] @ Te0[s1>>24]
+ and $i1,lr,$s2,lsr#8 @ i0
+ eor $t2,$t2,$i2,ror#8
+ and $i2,lr,$s2,lsr#16 @ i1
+ eor $t3,$t3,$i3,ror#8
+ and $i3,lr,$s2
+ ldr $i1,[$tbl,$i1,lsl#2] @ Te2[s2>>8]
+ eor $s1,$s1,$t1,ror#24
+ ldr $i2,[$tbl,$i2,lsl#2] @ Te1[s2>>16]
+ mov $s2,$s2,lsr#24
+
+ ldr $i3,[$tbl,$i3,lsl#2] @ Te3[s2>>0]
+ eor $s0,$s0,$i1,ror#16
+ ldr $s2,[$tbl,$s2,lsl#2] @ Te0[s2>>24]
+ and $i1,lr,$s3 @ i0
+ eor $s1,$s1,$i2,ror#8
+ and $i2,lr,$s3,lsr#8 @ i1
+ eor $t3,$t3,$i3,ror#16
+ and $i3,lr,$s3,lsr#16 @ i2
+ ldr $i1,[$tbl,$i1,lsl#2] @ Te3[s3>>0]
+ eor $s2,$s2,$t2,ror#16
+ ldr $i2,[$tbl,$i2,lsl#2] @ Te2[s3>>8]
+ mov $s3,$s3,lsr#24
+
+ ldr $i3,[$tbl,$i3,lsl#2] @ Te1[s3>>16]
+ eor $s0,$s0,$i1,ror#24
+ ldr $i1,[$key],#16
+ eor $s1,$s1,$i2,ror#16
+ ldr $s3,[$tbl,$s3,lsl#2] @ Te0[s3>>24]
+ eor $s2,$s2,$i3,ror#8
+ ldr $t1,[$key,#-12]
+ eor $s3,$s3,$t3,ror#8
+
+ ldr $t2,[$key,#-8]
+ eor $s0,$s0,$i1
+ ldr $t3,[$key,#-4]
+ and $i1,lr,$s0
+ eor $s1,$s1,$t1
+ and $i2,lr,$s0,lsr#8
+ eor $s2,$s2,$t2
+ and $i3,lr,$s0,lsr#16
+ eor $s3,$s3,$t3
+ mov $s0,$s0,lsr#24
+
+ subs $rounds,$rounds,#1
+ bne .Lenc_loop
+
+ add $tbl,$tbl,#2
+
+ ldrb $t1,[$tbl,$i1,lsl#2] @ Te4[s0>>0]
+ and $i1,lr,$s1,lsr#16 @ i0
+ ldrb $t2,[$tbl,$i2,lsl#2] @ Te4[s0>>8]
+ and $i2,lr,$s1
+ ldrb $t3,[$tbl,$i3,lsl#2] @ Te4[s0>>16]
+ and $i3,lr,$s1,lsr#8
+ ldrb $s0,[$tbl,$s0,lsl#2] @ Te4[s0>>24]
+ mov $s1,$s1,lsr#24
+
+ ldrb $i1,[$tbl,$i1,lsl#2] @ Te4[s1>>16]
+ ldrb $i2,[$tbl,$i2,lsl#2] @ Te4[s1>>0]
+ ldrb $i3,[$tbl,$i3,lsl#2] @ Te4[s1>>8]
+ eor $s0,$i1,$s0,lsl#8
+ ldrb $s1,[$tbl,$s1,lsl#2] @ Te4[s1>>24]
+ and $i1,lr,$s2,lsr#8 @ i0
+ eor $t2,$i2,$t2,lsl#8
+ and $i2,lr,$s2,lsr#16 @ i1
+ eor $t3,$i3,$t3,lsl#8
+ and $i3,lr,$s2
+ ldrb $i1,[$tbl,$i1,lsl#2] @ Te4[s2>>8]
+ eor $s1,$t1,$s1,lsl#24
+ ldrb $i2,[$tbl,$i2,lsl#2] @ Te4[s2>>16]
+ mov $s2,$s2,lsr#24
+
+ ldrb $i3,[$tbl,$i3,lsl#2] @ Te4[s2>>0]
+ eor $s0,$i1,$s0,lsl#8
+ ldrb $s2,[$tbl,$s2,lsl#2] @ Te4[s2>>24]
+ and $i1,lr,$s3 @ i0
+ eor $s1,$s1,$i2,lsl#16
+ and $i2,lr,$s3,lsr#8 @ i1
+ eor $t3,$i3,$t3,lsl#8
+ and $i3,lr,$s3,lsr#16 @ i2
+ ldrb $i1,[$tbl,$i1,lsl#2] @ Te4[s3>>0]
+ eor $s2,$t2,$s2,lsl#24
+ ldrb $i2,[$tbl,$i2,lsl#2] @ Te4[s3>>8]
+ mov $s3,$s3,lsr#24
+
+ ldrb $i3,[$tbl,$i3,lsl#2] @ Te4[s3>>16]
+ eor $s0,$i1,$s0,lsl#8
+ ldr $i1,[$key,#0]
+ ldrb $s3,[$tbl,$s3,lsl#2] @ Te4[s3>>24]
+ eor $s1,$s1,$i2,lsl#8
+ ldr $t1,[$key,#4]
+ eor $s2,$s2,$i3,lsl#16
+ ldr $t2,[$key,#8]
+ eor $s3,$t3,$s3,lsl#24
+ ldr $t3,[$key,#12]
+
+ eor $s0,$s0,$i1
+ eor $s1,$s1,$t1
+ eor $s2,$s2,$t2
+ eor $s3,$s3,$t3
+
+ sub $tbl,$tbl,#2
+ ldr pc,[sp],#4 @ pop and return
+.size _armv4_AES_encrypt,.-_armv4_AES_encrypt
+
+.global asm_AES_set_encrypt_key
+.hidden asm_AES_set_encrypt_key
+.type asm_AES_set_encrypt_key,%function
+.align 5
+asm_AES_set_encrypt_key:
+_armv4_AES_set_encrypt_key:
+#if __ARM_ARCH__<7
+ sub r3,pc,#8 @ asm_AES_set_encrypt_key
+#else
+ adr r3,asm_AES_set_encrypt_key
+#endif
+ teq r0,#0
+#if __ARM_ARCH__>=7
+ itt eq @ Thumb2 thing, sanity check in ARM
+#endif
+ moveq r0,#-1
+ beq .Labrt
+ teq r2,#0
+#if __ARM_ARCH__>=7
+ itt eq @ Thumb2 thing, sanity check in ARM
+#endif
+ moveq r0,#-1
+ beq .Labrt
+
+ teq r1,#128
+ beq .Lok
+ teq r1,#192
+ beq .Lok
+ teq r1,#256
+#if __ARM_ARCH__>=7
+ itt ne @ Thumb2 thing, sanity check in ARM
+#endif
+ movne r0,#-1
+ bne .Labrt
+
+.Lok: stmdb sp!,{r4-r12,lr}
+ sub $tbl,r3,#_armv4_AES_set_encrypt_key-AES_Te-1024 @ Te4
+
+ mov $rounds,r0 @ inp
+ mov lr,r1 @ bits
+ mov $key,r2 @ key
+
+#if __ARM_ARCH__<7
+ ldrb $s0,[$rounds,#3] @ load input data in endian-neutral
+ ldrb $t1,[$rounds,#2] @ manner...
+ ldrb $t2,[$rounds,#1]
+ ldrb $t3,[$rounds,#0]
+ orr $s0,$s0,$t1,lsl#8
+ ldrb $s1,[$rounds,#7]
+ orr $s0,$s0,$t2,lsl#16
+ ldrb $t1,[$rounds,#6]
+ orr $s0,$s0,$t3,lsl#24
+ ldrb $t2,[$rounds,#5]
+ ldrb $t3,[$rounds,#4]
+ orr $s1,$s1,$t1,lsl#8
+ ldrb $s2,[$rounds,#11]
+ orr $s1,$s1,$t2,lsl#16
+ ldrb $t1,[$rounds,#10]
+ orr $s1,$s1,$t3,lsl#24
+ ldrb $t2,[$rounds,#9]
+ ldrb $t3,[$rounds,#8]
+ orr $s2,$s2,$t1,lsl#8
+ ldrb $s3,[$rounds,#15]
+ orr $s2,$s2,$t2,lsl#16
+ ldrb $t1,[$rounds,#14]
+ orr $s2,$s2,$t3,lsl#24
+ ldrb $t2,[$rounds,#13]
+ ldrb $t3,[$rounds,#12]
+ orr $s3,$s3,$t1,lsl#8
+ str $s0,[$key],#16
+ orr $s3,$s3,$t2,lsl#16
+ str $s1,[$key,#-12]
+ orr $s3,$s3,$t3,lsl#24
+ str $s2,[$key,#-8]
+ str $s3,[$key,#-4]
+#else
+ ldr $s0,[$rounds,#0]
+ ldr $s1,[$rounds,#4]
+ ldr $s2,[$rounds,#8]
+ ldr $s3,[$rounds,#12]
+#ifdef __ARMEL__
+ rev $s0,$s0
+ rev $s1,$s1
+ rev $s2,$s2
+ rev $s3,$s3
+#endif
+ str $s0,[$key],#16
+ str $s1,[$key,#-12]
+ str $s2,[$key,#-8]
+ str $s3,[$key,#-4]
+#endif
+
+ teq lr,#128
+ bne .Lnot128
+ mov $rounds,#10
+ str $rounds,[$key,#240-16]
+ add $t3,$tbl,#256 @ rcon
+ mov lr,#255
+
+.L128_loop:
+ and $t2,lr,$s3,lsr#24
+ and $i1,lr,$s3,lsr#16
+ ldrb $t2,[$tbl,$t2]
+ and $i2,lr,$s3,lsr#8
+ ldrb $i1,[$tbl,$i1]
+ and $i3,lr,$s3
+ ldrb $i2,[$tbl,$i2]
+ orr $t2,$t2,$i1,lsl#24
+ ldrb $i3,[$tbl,$i3]
+ orr $t2,$t2,$i2,lsl#16
+ ldr $t1,[$t3],#4 @ rcon[i++]
+ orr $t2,$t2,$i3,lsl#8
+ eor $t2,$t2,$t1
+ eor $s0,$s0,$t2 @ rk[4]=rk[0]^...
+ eor $s1,$s1,$s0 @ rk[5]=rk[1]^rk[4]
+ str $s0,[$key],#16
+ eor $s2,$s2,$s1 @ rk[6]=rk[2]^rk[5]
+ str $s1,[$key,#-12]
+ eor $s3,$s3,$s2 @ rk[7]=rk[3]^rk[6]
+ str $s2,[$key,#-8]
+ subs $rounds,$rounds,#1
+ str $s3,[$key,#-4]
+ bne .L128_loop
+ sub r2,$key,#176
+ b .Ldone
+
+.Lnot128:
+#if __ARM_ARCH__<7
+ ldrb $i2,[$rounds,#19]
+ ldrb $t1,[$rounds,#18]
+ ldrb $t2,[$rounds,#17]
+ ldrb $t3,[$rounds,#16]
+ orr $i2,$i2,$t1,lsl#8
+ ldrb $i3,[$rounds,#23]
+ orr $i2,$i2,$t2,lsl#16
+ ldrb $t1,[$rounds,#22]
+ orr $i2,$i2,$t3,lsl#24
+ ldrb $t2,[$rounds,#21]
+ ldrb $t3,[$rounds,#20]
+ orr $i3,$i3,$t1,lsl#8
+ orr $i3,$i3,$t2,lsl#16
+ str $i2,[$key],#8
+ orr $i3,$i3,$t3,lsl#24
+ str $i3,[$key,#-4]
+#else
+ ldr $i2,[$rounds,#16]
+ ldr $i3,[$rounds,#20]
+#ifdef __ARMEL__
+ rev $i2,$i2
+ rev $i3,$i3
+#endif
+ str $i2,[$key],#8
+ str $i3,[$key,#-4]
+#endif
+
+ teq lr,#192
+ bne .Lnot192
+ mov $rounds,#12
+ str $rounds,[$key,#240-24]
+ add $t3,$tbl,#256 @ rcon
+ mov lr,#255
+ mov $rounds,#8
+
+.L192_loop:
+ and $t2,lr,$i3,lsr#24
+ and $i1,lr,$i3,lsr#16
+ ldrb $t2,[$tbl,$t2]
+ and $i2,lr,$i3,lsr#8
+ ldrb $i1,[$tbl,$i1]
+ and $i3,lr,$i3
+ ldrb $i2,[$tbl,$i2]
+ orr $t2,$t2,$i1,lsl#24
+ ldrb $i3,[$tbl,$i3]
+ orr $t2,$t2,$i2,lsl#16
+ ldr $t1,[$t3],#4 @ rcon[i++]
+ orr $t2,$t2,$i3,lsl#8
+ eor $i3,$t2,$t1
+ eor $s0,$s0,$i3 @ rk[6]=rk[0]^...
+ eor $s1,$s1,$s0 @ rk[7]=rk[1]^rk[6]
+ str $s0,[$key],#24
+ eor $s2,$s2,$s1 @ rk[8]=rk[2]^rk[7]
+ str $s1,[$key,#-20]
+ eor $s3,$s3,$s2 @ rk[9]=rk[3]^rk[8]
+ str $s2,[$key,#-16]
+ subs $rounds,$rounds,#1
+ str $s3,[$key,#-12]
+#if __ARM_ARCH__>=7
+ itt eq @ Thumb2 thing, sanity check in ARM
+#endif
+ subeq r2,$key,#216
+ beq .Ldone
+
+ ldr $i1,[$key,#-32]
+ ldr $i2,[$key,#-28]
+ eor $i1,$i1,$s3 @ rk[10]=rk[4]^rk[9]
+ eor $i3,$i2,$i1 @ rk[11]=rk[5]^rk[10]
+ str $i1,[$key,#-8]
+ str $i3,[$key,#-4]
+ b .L192_loop
+
+.Lnot192:
+#if __ARM_ARCH__<7
+ ldrb $i2,[$rounds,#27]
+ ldrb $t1,[$rounds,#26]
+ ldrb $t2,[$rounds,#25]
+ ldrb $t3,[$rounds,#24]
+ orr $i2,$i2,$t1,lsl#8
+ ldrb $i3,[$rounds,#31]
+ orr $i2,$i2,$t2,lsl#16
+ ldrb $t1,[$rounds,#30]
+ orr $i2,$i2,$t3,lsl#24
+ ldrb $t2,[$rounds,#29]
+ ldrb $t3,[$rounds,#28]
+ orr $i3,$i3,$t1,lsl#8
+ orr $i3,$i3,$t2,lsl#16
+ str $i2,[$key],#8
+ orr $i3,$i3,$t3,lsl#24
+ str $i3,[$key,#-4]
+#else
+ ldr $i2,[$rounds,#24]
+ ldr $i3,[$rounds,#28]
+#ifdef __ARMEL__
+ rev $i2,$i2
+ rev $i3,$i3
+#endif
+ str $i2,[$key],#8
+ str $i3,[$key,#-4]
+#endif
+
+ mov $rounds,#14
+ str $rounds,[$key,#240-32]
+ add $t3,$tbl,#256 @ rcon
+ mov lr,#255
+ mov $rounds,#7
+
+.L256_loop:
+ and $t2,lr,$i3,lsr#24
+ and $i1,lr,$i3,lsr#16
+ ldrb $t2,[$tbl,$t2]
+ and $i2,lr,$i3,lsr#8
+ ldrb $i1,[$tbl,$i1]
+ and $i3,lr,$i3
+ ldrb $i2,[$tbl,$i2]
+ orr $t2,$t2,$i1,lsl#24
+ ldrb $i3,[$tbl,$i3]
+ orr $t2,$t2,$i2,lsl#16
+ ldr $t1,[$t3],#4 @ rcon[i++]
+ orr $t2,$t2,$i3,lsl#8
+ eor $i3,$t2,$t1
+ eor $s0,$s0,$i3 @ rk[8]=rk[0]^...
+ eor $s1,$s1,$s0 @ rk[9]=rk[1]^rk[8]
+ str $s0,[$key],#32
+ eor $s2,$s2,$s1 @ rk[10]=rk[2]^rk[9]
+ str $s1,[$key,#-28]
+ eor $s3,$s3,$s2 @ rk[11]=rk[3]^rk[10]
+ str $s2,[$key,#-24]
+ subs $rounds,$rounds,#1
+ str $s3,[$key,#-20]
+#if __ARM_ARCH__>=7
+ itt eq @ Thumb2 thing, sanity check in ARM
+#endif
+ subeq r2,$key,#256
+ beq .Ldone
+
+ and $t2,lr,$s3
+ and $i1,lr,$s3,lsr#8
+ ldrb $t2,[$tbl,$t2]
+ and $i2,lr,$s3,lsr#16
+ ldrb $i1,[$tbl,$i1]
+ and $i3,lr,$s3,lsr#24
+ ldrb $i2,[$tbl,$i2]
+ orr $t2,$t2,$i1,lsl#8
+ ldrb $i3,[$tbl,$i3]
+ orr $t2,$t2,$i2,lsl#16
+ ldr $t1,[$key,#-48]
+ orr $t2,$t2,$i3,lsl#24
+
+ ldr $i1,[$key,#-44]
+ ldr $i2,[$key,#-40]
+ eor $t1,$t1,$t2 @ rk[12]=rk[4]^...
+ ldr $i3,[$key,#-36]
+ eor $i1,$i1,$t1 @ rk[13]=rk[5]^rk[12]
+ str $t1,[$key,#-16]
+ eor $i2,$i2,$i1 @ rk[14]=rk[6]^rk[13]
+ str $i1,[$key,#-12]
+ eor $i3,$i3,$i2 @ rk[15]=rk[7]^rk[14]
+ str $i2,[$key,#-8]
+ str $i3,[$key,#-4]
+ b .L256_loop
+
+.align 2
+.Ldone: mov r0,#0
+ ldmia sp!,{r4-r12,lr}
+.Labrt:
+#if defined(__thumb2__) && __ARM_ARCH__>=7
+ .short 0x4770 @ bx lr in Thumb2 encoding
+#else
+ tst lr,#1
+ moveq pc,lr @ be binary compatible with V4, yet
+ bx lr @ interoperable with Thumb ISA:-)
+#endif
+.size asm_AES_set_encrypt_key,.-asm_AES_set_encrypt_key
+
+.global asm_AES_set_decrypt_key
+.hidden asm_AES_set_decrypt_key
+.type asm_AES_set_decrypt_key,%function
+.align 5
+asm_AES_set_decrypt_key:
+ str lr,[sp,#-4]! @ push lr
+ bl _armv4_AES_set_encrypt_key
+ teq r0,#0
+ ldr lr,[sp],#4 @ pop lr
+ bne .Labrt
+
+ mov r0,r2 @ asm_AES_set_encrypt_key preserves r2,
+ mov r1,r2 @ which is AES_KEY *key
+ b _armv4_AES_set_enc2dec_key
+.size asm_AES_set_decrypt_key,.-asm_AES_set_decrypt_key
+
+@ void AES_set_enc2dec_key(const AES_KEY *inp,AES_KEY *out)
+.global AES_set_enc2dec_key
+.hidden AES_set_enc2dec_key
+.type AES_set_enc2dec_key,%function
+.align 5
+AES_set_enc2dec_key:
+_armv4_AES_set_enc2dec_key:
+ stmdb sp!,{r4-r12,lr}
+
+ ldr $rounds,[r0,#240]
+ mov $i1,r0 @ input
+ add $i2,r0,$rounds,lsl#4
+ mov $key,r1 @ ouput
+ add $tbl,r1,$rounds,lsl#4
+ str $rounds,[r1,#240]
+
+.Linv: ldr $s0,[$i1],#16
+ ldr $s1,[$i1,#-12]
+ ldr $s2,[$i1,#-8]
+ ldr $s3,[$i1,#-4]
+ ldr $t1,[$i2],#-16
+ ldr $t2,[$i2,#16+4]
+ ldr $t3,[$i2,#16+8]
+ ldr $i3,[$i2,#16+12]
+ str $s0,[$tbl],#-16
+ str $s1,[$tbl,#16+4]
+ str $s2,[$tbl,#16+8]
+ str $s3,[$tbl,#16+12]
+ str $t1,[$key],#16
+ str $t2,[$key,#-12]
+ str $t3,[$key,#-8]
+ str $i3,[$key,#-4]
+ teq $i1,$i2
+ bne .Linv
+
+ ldr $s0,[$i1]
+ ldr $s1,[$i1,#4]
+ ldr $s2,[$i1,#8]
+ ldr $s3,[$i1,#12]
+ str $s0,[$key]
+ str $s1,[$key,#4]
+ str $s2,[$key,#8]
+ str $s3,[$key,#12]
+ sub $key,$key,$rounds,lsl#3
+___
+$mask80=$i1;
+$mask1b=$i2;
+$mask7f=$i3;
+$code.=<<___;
+ ldr $s0,[$key,#16]! @ prefetch tp1
+ mov $mask80,#0x80
+ mov $mask1b,#0x1b
+ orr $mask80,$mask80,#0x8000
+ orr $mask1b,$mask1b,#0x1b00
+ orr $mask80,$mask80,$mask80,lsl#16
+ orr $mask1b,$mask1b,$mask1b,lsl#16
+ sub $rounds,$rounds,#1
+ mvn $mask7f,$mask80
+ mov $rounds,$rounds,lsl#2 @ (rounds-1)*4
+
+.Lmix: and $t1,$s0,$mask80
+ and $s1,$s0,$mask7f
+ sub $t1,$t1,$t1,lsr#7
+ and $t1,$t1,$mask1b
+ eor $s1,$t1,$s1,lsl#1 @ tp2
+
+ and $t1,$s1,$mask80
+ and $s2,$s1,$mask7f
+ sub $t1,$t1,$t1,lsr#7
+ and $t1,$t1,$mask1b
+ eor $s2,$t1,$s2,lsl#1 @ tp4
+
+ and $t1,$s2,$mask80
+ and $s3,$s2,$mask7f
+ sub $t1,$t1,$t1,lsr#7
+ and $t1,$t1,$mask1b
+ eor $s3,$t1,$s3,lsl#1 @ tp8
+
+ eor $t1,$s1,$s2
+ eor $t2,$s0,$s3 @ tp9
+ eor $t1,$t1,$s3 @ tpe
+ eor $t1,$t1,$s1,ror#24
+ eor $t1,$t1,$t2,ror#24 @ ^= ROTATE(tpb=tp9^tp2,8)
+ eor $t1,$t1,$s2,ror#16
+ eor $t1,$t1,$t2,ror#16 @ ^= ROTATE(tpd=tp9^tp4,16)
+ eor $t1,$t1,$t2,ror#8 @ ^= ROTATE(tp9,24)
+
+ ldr $s0,[$key,#4] @ prefetch tp1
+ str $t1,[$key],#4
+ subs $rounds,$rounds,#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
+ bx lr @ interoperable with Thumb ISA:-)
+#endif
+.size AES_set_enc2dec_key,.-AES_set_enc2dec_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 asm_AES_decrypt(const unsigned char *in, unsigned char *out,
+@ const AES_KEY *key) {
+.global asm_AES_decrypt
+.hidden asm_AES_decrypt
+.type asm_AES_decrypt,%function
+.align 5
+asm_AES_decrypt:
+#if __ARM_ARCH__<7
+ sub r3,pc,#8 @ asm_AES_decrypt
+#else
+ adr r3,asm_AES_decrypt
+#endif
+ stmdb sp!,{r1,r4-r12,lr}
+ mov $rounds,r0 @ inp
+ mov $key,r2
+ sub $tbl,r3,#asm_AES_decrypt-AES_Td @ Td
+#if __ARM_ARCH__<7
+ ldrb $s0,[$rounds,#3] @ load input data in endian-neutral
+ ldrb $t1,[$rounds,#2] @ manner...
+ ldrb $t2,[$rounds,#1]
+ ldrb $t3,[$rounds,#0]
+ orr $s0,$s0,$t1,lsl#8
+ ldrb $s1,[$rounds,#7]
+ orr $s0,$s0,$t2,lsl#16
+ ldrb $t1,[$rounds,#6]
+ orr $s0,$s0,$t3,lsl#24
+ ldrb $t2,[$rounds,#5]
+ ldrb $t3,[$rounds,#4]
+ orr $s1,$s1,$t1,lsl#8
+ ldrb $s2,[$rounds,#11]
+ orr $s1,$s1,$t2,lsl#16
+ ldrb $t1,[$rounds,#10]
+ orr $s1,$s1,$t3,lsl#24
+ ldrb $t2,[$rounds,#9]
+ ldrb $t3,[$rounds,#8]
+ orr $s2,$s2,$t1,lsl#8
+ ldrb $s3,[$rounds,#15]
+ orr $s2,$s2,$t2,lsl#16
+ ldrb $t1,[$rounds,#14]
+ orr $s2,$s2,$t3,lsl#24
+ ldrb $t2,[$rounds,#13]
+ ldrb $t3,[$rounds,#12]
+ orr $s3,$s3,$t1,lsl#8
+ orr $s3,$s3,$t2,lsl#16
+ orr $s3,$s3,$t3,lsl#24
+#else
+ ldr $s0,[$rounds,#0]
+ ldr $s1,[$rounds,#4]
+ ldr $s2,[$rounds,#8]
+ ldr $s3,[$rounds,#12]
+#ifdef __ARMEL__
+ rev $s0,$s0
+ rev $s1,$s1
+ rev $s2,$s2
+ rev $s3,$s3
+#endif
+#endif
+ bl _armv4_AES_decrypt
+
+ ldr $rounds,[sp],#4 @ pop out
+#if __ARM_ARCH__>=7
+#ifdef __ARMEL__
+ rev $s0,$s0
+ rev $s1,$s1
+ rev $s2,$s2
+ rev $s3,$s3
+#endif
+ str $s0,[$rounds,#0]
+ str $s1,[$rounds,#4]
+ str $s2,[$rounds,#8]
+ str $s3,[$rounds,#12]
+#else
+ mov $t1,$s0,lsr#24 @ write output in endian-neutral
+ mov $t2,$s0,lsr#16 @ manner...
+ mov $t3,$s0,lsr#8
+ strb $t1,[$rounds,#0]
+ strb $t2,[$rounds,#1]
+ mov $t1,$s1,lsr#24
+ strb $t3,[$rounds,#2]
+ mov $t2,$s1,lsr#16
+ strb $s0,[$rounds,#3]
+ mov $t3,$s1,lsr#8
+ strb $t1,[$rounds,#4]
+ strb $t2,[$rounds,#5]
+ mov $t1,$s2,lsr#24
+ strb $t3,[$rounds,#6]
+ mov $t2,$s2,lsr#16
+ strb $s1,[$rounds,#7]
+ mov $t3,$s2,lsr#8
+ strb $t1,[$rounds,#8]
+ strb $t2,[$rounds,#9]
+ mov $t1,$s3,lsr#24
+ strb $t3,[$rounds,#10]
+ mov $t2,$s3,lsr#16
+ strb $s2,[$rounds,#11]
+ mov $t3,$s3,lsr#8
+ strb $t1,[$rounds,#12]
+ strb $t2,[$rounds,#13]
+ strb $t3,[$rounds,#14]
+ strb $s3,[$rounds,#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
+ bx lr @ interoperable with Thumb ISA:-)
+#endif
+.size asm_AES_decrypt,.-asm_AES_decrypt
+
+.type _armv4_AES_decrypt,%function
+.align 2
+_armv4_AES_decrypt:
+ str lr,[sp,#-4]! @ push lr
+ ldmia $key!,{$t1-$i1}
+ eor $s0,$s0,$t1
+ ldr $rounds,[$key,#240-16]
+ eor $s1,$s1,$t2
+ eor $s2,$s2,$t3
+ eor $s3,$s3,$i1
+ sub $rounds,$rounds,#1
+ mov lr,#255
+
+ and $i1,lr,$s0,lsr#16
+ and $i2,lr,$s0,lsr#8
+ and $i3,lr,$s0
+ mov $s0,$s0,lsr#24
+.Ldec_loop:
+ ldr $t1,[$tbl,$i1,lsl#2] @ Td1[s0>>16]
+ and $i1,lr,$s1 @ i0
+ ldr $t2,[$tbl,$i2,lsl#2] @ Td2[s0>>8]
+ and $i2,lr,$s1,lsr#16
+ ldr $t3,[$tbl,$i3,lsl#2] @ Td3[s0>>0]
+ and $i3,lr,$s1,lsr#8
+ ldr $s0,[$tbl,$s0,lsl#2] @ Td0[s0>>24]
+ mov $s1,$s1,lsr#24
+
+ ldr $i1,[$tbl,$i1,lsl#2] @ Td3[s1>>0]
+ ldr $i2,[$tbl,$i2,lsl#2] @ Td1[s1>>16]
+ ldr $i3,[$tbl,$i3,lsl#2] @ Td2[s1>>8]
+ eor $s0,$s0,$i1,ror#24
+ ldr $s1,[$tbl,$s1,lsl#2] @ Td0[s1>>24]
+ and $i1,lr,$s2,lsr#8 @ i0
+ eor $t2,$i2,$t2,ror#8
+ and $i2,lr,$s2 @ i1
+ eor $t3,$i3,$t3,ror#8
+ and $i3,lr,$s2,lsr#16
+ ldr $i1,[$tbl,$i1,lsl#2] @ Td2[s2>>8]
+ eor $s1,$s1,$t1,ror#8
+ ldr $i2,[$tbl,$i2,lsl#2] @ Td3[s2>>0]
+ mov $s2,$s2,lsr#24
+
+ ldr $i3,[$tbl,$i3,lsl#2] @ Td1[s2>>16]
+ eor $s0,$s0,$i1,ror#16
+ ldr $s2,[$tbl,$s2,lsl#2] @ Td0[s2>>24]
+ and $i1,lr,$s3,lsr#16 @ i0
+ eor $s1,$s1,$i2,ror#24
+ and $i2,lr,$s3,lsr#8 @ i1
+ eor $t3,$i3,$t3,ror#8
+ and $i3,lr,$s3 @ i2
+ ldr $i1,[$tbl,$i1,lsl#2] @ Td1[s3>>16]
+ eor $s2,$s2,$t2,ror#8
+ ldr $i2,[$tbl,$i2,lsl#2] @ Td2[s3>>8]
+ mov $s3,$s3,lsr#24
+
+ ldr $i3,[$tbl,$i3,lsl#2] @ Td3[s3>>0]
+ eor $s0,$s0,$i1,ror#8
+ ldr $i1,[$key],#16
+ eor $s1,$s1,$i2,ror#16
+ ldr $s3,[$tbl,$s3,lsl#2] @ Td0[s3>>24]
+ eor $s2,$s2,$i3,ror#24
+
+ ldr $t1,[$key,#-12]
+ eor $s0,$s0,$i1
+ ldr $t2,[$key,#-8]
+ eor $s3,$s3,$t3,ror#8
+ ldr $t3,[$key,#-4]
+ and $i1,lr,$s0,lsr#16
+ eor $s1,$s1,$t1
+ and $i2,lr,$s0,lsr#8
+ eor $s2,$s2,$t2
+ and $i3,lr,$s0
+ eor $s3,$s3,$t3
+ mov $s0,$s0,lsr#24
+
+ subs $rounds,$rounds,#1
+ bne .Ldec_loop
+
+ add $tbl,$tbl,#1024
+
+ ldr $t2,[$tbl,#0] @ prefetch Td4
+ ldr $t3,[$tbl,#32]
+ ldr $t1,[$tbl,#64]
+ ldr $t2,[$tbl,#96]
+ ldr $t3,[$tbl,#128]
+ ldr $t1,[$tbl,#160]
+ ldr $t2,[$tbl,#192]
+ ldr $t3,[$tbl,#224]
+
+ ldrb $s0,[$tbl,$s0] @ Td4[s0>>24]
+ ldrb $t1,[$tbl,$i1] @ Td4[s0>>16]
+ and $i1,lr,$s1 @ i0
+ ldrb $t2,[$tbl,$i2] @ Td4[s0>>8]
+ and $i2,lr,$s1,lsr#16
+ ldrb $t3,[$tbl,$i3] @ Td4[s0>>0]
+ and $i3,lr,$s1,lsr#8
+
+ add $s1,$tbl,$s1,lsr#24
+ ldrb $i1,[$tbl,$i1] @ Td4[s1>>0]
+ ldrb $s1,[$s1] @ Td4[s1>>24]
+ ldrb $i2,[$tbl,$i2] @ Td4[s1>>16]
+ eor $s0,$i1,$s0,lsl#24
+ ldrb $i3,[$tbl,$i3] @ Td4[s1>>8]
+ eor $s1,$t1,$s1,lsl#8
+ and $i1,lr,$s2,lsr#8 @ i0
+ eor $t2,$t2,$i2,lsl#8
+ and $i2,lr,$s2 @ i1
+ ldrb $i1,[$tbl,$i1] @ Td4[s2>>8]
+ eor $t3,$t3,$i3,lsl#8
+ ldrb $i2,[$tbl,$i2] @ Td4[s2>>0]
+ and $i3,lr,$s2,lsr#16
+
+ add $s2,$tbl,$s2,lsr#24
+ ldrb $s2,[$s2] @ Td4[s2>>24]
+ eor $s0,$s0,$i1,lsl#8
+ ldrb $i3,[$tbl,$i3] @ Td4[s2>>16]
+ eor $s1,$i2,$s1,lsl#16
+ and $i1,lr,$s3,lsr#16 @ i0
+ eor $s2,$t2,$s2,lsl#16
+ and $i2,lr,$s3,lsr#8 @ i1
+ ldrb $i1,[$tbl,$i1] @ Td4[s3>>16]
+ eor $t3,$t3,$i3,lsl#16
+ ldrb $i2,[$tbl,$i2] @ Td4[s3>>8]
+ and $i3,lr,$s3 @ i2
+
+ add $s3,$tbl,$s3,lsr#24
+ ldrb $i3,[$tbl,$i3] @ Td4[s3>>0]
+ ldrb $s3,[$s3] @ Td4[s3>>24]
+ eor $s0,$s0,$i1,lsl#16
+ ldr $i1,[$key,#0]
+ eor $s1,$s1,$i2,lsl#8
+ ldr $t1,[$key,#4]
+ eor $s2,$i3,$s2,lsl#8
+ ldr $t2,[$key,#8]
+ eor $s3,$t3,$s3,lsl#24
+ ldr $t3,[$key,#12]
+
+ eor $s0,$s0,$i1
+ eor $s1,$s1,$t1
+ eor $s2,$s2,$t2
+ eor $s3,$s3,$t3
+
+ sub $tbl,$tbl,#1024
+ ldr pc,[sp],#4 @ pop and return
+.size _armv4_AES_decrypt,.-_armv4_AES_decrypt
+.asciz "AES for ARMv4, CRYPTOGAMS by <appro\@openssl.org>"
+.align 2
+
+#endif
+___
+
+$code =~ s/\bbx\s+lr\b/.word\t0xe12fff1e/gm; # make it possible to compile with -march=armv4
+
+open SELF,$0;
+while(<SELF>) {
+ next if (/^#!/);
+ last if (!s/^#/@/ and !/^$/);
+ print;
+}
+close SELF;
+
+print $code;
+close STDOUT; # enforce flush
diff --git a/src/crypto/aes/asm/aes-x86_64.pl b/src/crypto/aes/asm/aes-x86_64.pl
new file mode 100644
index 0000000..4b6e1b4
--- /dev/null
+++ b/src/crypto/aes/asm/aes-x86_64.pl
@@ -0,0 +1,2805 @@
+#!/usr/bin/env perl
+#
+# ====================================================================
+# Written by Andy Polyakov <appro@fy.chalmers.se> for the OpenSSL
+# project. The module is, however, dual licensed under OpenSSL and
+# CRYPTOGAMS licenses depending on where you obtain it. For further
+# details see http://www.openssl.org/~appro/cryptogams/.
+# ====================================================================
+#
+# Version 2.1.
+#
+# aes-*-cbc benchmarks are improved by >70% [compared to gcc 3.3.2 on
+# Opteron 240 CPU] plus all the bells-n-whistles from 32-bit version
+# [you'll notice a lot of resemblance], such as compressed S-boxes
+# in little-endian byte order, prefetch of these tables in CBC mode,
+# as well as avoiding L1 cache aliasing between stack frame and key
+# schedule and already mentioned tables, compressed Td4...
+#
+# Performance in number of cycles per processed byte for 128-bit key:
+#
+# ECB encrypt ECB decrypt CBC large chunk
+# AMD64 33 43 13.0
+# EM64T 38 56 18.6(*)
+# Core 2 30 42 14.5(*)
+# Atom 65 86 32.1(*)
+#
+# (*) with hyper-threading off
+
+$flavour = shift;
+$output = shift;
+if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+
+$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
+( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
+die "can't locate x86_64-xlate.pl";
+
+open OUT,"| \"$^X\" $xlate $flavour $output";
+*STDOUT=*OUT;
+
+$verticalspin=1; # unlike 32-bit version $verticalspin performs
+ # ~15% better on both AMD and Intel cores
+$speed_limit=512; # see aes-586.pl for details
+
+$code=".text\n";
+
+$s0="%eax";
+$s1="%ebx";
+$s2="%ecx";
+$s3="%edx";
+$acc0="%esi"; $mask80="%rsi";
+$acc1="%edi"; $maskfe="%rdi";
+$acc2="%ebp"; $mask1b="%rbp";
+$inp="%r8";
+$out="%r9";
+$t0="%r10d";
+$t1="%r11d";
+$t2="%r12d";
+$rnds="%r13d";
+$sbox="%r14";
+$key="%r15";
+
+sub hi() { my $r=shift; $r =~ s/%[er]([a-d])x/%\1h/; $r; }
+sub lo() { my $r=shift; $r =~ s/%[er]([a-d])x/%\1l/;
+ $r =~ s/%[er]([sd]i)/%\1l/;
+ $r =~ s/%(r[0-9]+)[d]?/%\1b/; $r; }
+sub LO() { my $r=shift; $r =~ s/%r([a-z]+)/%e\1/;
+ $r =~ s/%r([0-9]+)/%r\1d/; $r; }
+sub _data_word()
+{ my $i;
+ while(defined($i=shift)) { $code.=sprintf".long\t0x%08x,0x%08x\n",$i,$i; }
+}
+sub data_word()
+{ my $i;
+ my $last=pop(@_);
+ $code.=".long\t";
+ while(defined($i=shift)) { $code.=sprintf"0x%08x,",$i; }
+ $code.=sprintf"0x%08x\n",$last;
+}
+
+sub data_byte()
+{ my $i;
+ my $last=pop(@_);
+ $code.=".byte\t";
+ while(defined($i=shift)) { $code.=sprintf"0x%02x,",$i&0xff; }
+ $code.=sprintf"0x%02x\n",$last&0xff;
+}
+
+sub encvert()
+{ my $t3="%r8d"; # zaps $inp!
+
+$code.=<<___;
+ # favor 3-way issue Opteron pipeline...
+ movzb `&lo("$s0")`,$acc0
+ movzb `&lo("$s1")`,$acc1
+ movzb `&lo("$s2")`,$acc2
+ mov 0($sbox,$acc0,8),$t0
+ mov 0($sbox,$acc1,8),$t1
+ mov 0($sbox,$acc2,8),$t2
+
+ movzb `&hi("$s1")`,$acc0
+ movzb `&hi("$s2")`,$acc1
+ movzb `&lo("$s3")`,$acc2
+ xor 3($sbox,$acc0,8),$t0
+ xor 3($sbox,$acc1,8),$t1
+ mov 0($sbox,$acc2,8),$t3
+
+ movzb `&hi("$s3")`,$acc0
+ shr \$16,$s2
+ movzb `&hi("$s0")`,$acc2
+ xor 3($sbox,$acc0,8),$t2
+ shr \$16,$s3
+ xor 3($sbox,$acc2,8),$t3
+
+ shr \$16,$s1
+ lea 16($key),$key
+ shr \$16,$s0
+
+ movzb `&lo("$s2")`,$acc0
+ movzb `&lo("$s3")`,$acc1
+ movzb `&lo("$s0")`,$acc2
+ xor 2($sbox,$acc0,8),$t0
+ xor 2($sbox,$acc1,8),$t1
+ xor 2($sbox,$acc2,8),$t2
+
+ movzb `&hi("$s3")`,$acc0
+ movzb `&hi("$s0")`,$acc1
+ movzb `&lo("$s1")`,$acc2
+ xor 1($sbox,$acc0,8),$t0
+ xor 1($sbox,$acc1,8),$t1
+ xor 2($sbox,$acc2,8),$t3
+
+ mov 12($key),$s3
+ movzb `&hi("$s1")`,$acc1
+ movzb `&hi("$s2")`,$acc2
+ mov 0($key),$s0
+ xor 1($sbox,$acc1,8),$t2
+ xor 1($sbox,$acc2,8),$t3
+
+ mov 4($key),$s1
+ mov 8($key),$s2
+ xor $t0,$s0
+ xor $t1,$s1
+ xor $t2,$s2
+ xor $t3,$s3
+___
+}
+
+sub enclastvert()
+{ my $t3="%r8d"; # zaps $inp!
+
+$code.=<<___;
+ movzb `&lo("$s0")`,$acc0
+ movzb `&lo("$s1")`,$acc1
+ movzb `&lo("$s2")`,$acc2
+ movzb 2($sbox,$acc0,8),$t0
+ movzb 2($sbox,$acc1,8),$t1
+ movzb 2($sbox,$acc2,8),$t2
+
+ movzb `&lo("$s3")`,$acc0
+ movzb `&hi("$s1")`,$acc1
+ movzb `&hi("$s2")`,$acc2
+ movzb 2($sbox,$acc0,8),$t3
+ mov 0($sbox,$acc1,8),$acc1 #$t0
+ mov 0($sbox,$acc2,8),$acc2 #$t1
+
+ and \$0x0000ff00,$acc1
+ and \$0x0000ff00,$acc2
+
+ xor $acc1,$t0
+ xor $acc2,$t1
+ shr \$16,$s2
+
+ movzb `&hi("$s3")`,$acc0
+ movzb `&hi("$s0")`,$acc1
+ shr \$16,$s3
+ mov 0($sbox,$acc0,8),$acc0 #$t2
+ mov 0($sbox,$acc1,8),$acc1 #$t3
+
+ and \$0x0000ff00,$acc0
+ and \$0x0000ff00,$acc1
+ shr \$16,$s1
+ xor $acc0,$t2
+ xor $acc1,$t3
+ shr \$16,$s0
+
+ movzb `&lo("$s2")`,$acc0
+ movzb `&lo("$s3")`,$acc1
+ movzb `&lo("$s0")`,$acc2
+ mov 0($sbox,$acc0,8),$acc0 #$t0
+ mov 0($sbox,$acc1,8),$acc1 #$t1
+ mov 0($sbox,$acc2,8),$acc2 #$t2
+
+ and \$0x00ff0000,$acc0
+ and \$0x00ff0000,$acc1
+ and \$0x00ff0000,$acc2
+
+ xor $acc0,$t0
+ xor $acc1,$t1
+ xor $acc2,$t2
+
+ movzb `&lo("$s1")`,$acc0
+ movzb `&hi("$s3")`,$acc1
+ movzb `&hi("$s0")`,$acc2
+ mov 0($sbox,$acc0,8),$acc0 #$t3
+ mov 2($sbox,$acc1,8),$acc1 #$t0
+ mov 2($sbox,$acc2,8),$acc2 #$t1
+
+ and \$0x00ff0000,$acc0
+ and \$0xff000000,$acc1
+ and \$0xff000000,$acc2
+
+ xor $acc0,$t3
+ xor $acc1,$t0
+ xor $acc2,$t1
+
+ movzb `&hi("$s1")`,$acc0
+ movzb `&hi("$s2")`,$acc1
+ mov 16+12($key),$s3
+ mov 2($sbox,$acc0,8),$acc0 #$t2
+ mov 2($sbox,$acc1,8),$acc1 #$t3
+ mov 16+0($key),$s0
+
+ and \$0xff000000,$acc0
+ and \$0xff000000,$acc1
+
+ xor $acc0,$t2
+ xor $acc1,$t3
+
+ mov 16+4($key),$s1
+ mov 16+8($key),$s2
+ xor $t0,$s0
+ xor $t1,$s1
+ xor $t2,$s2
+ xor $t3,$s3
+___
+}
+
+sub encstep()
+{ my ($i,@s) = @_;
+ my $tmp0=$acc0;
+ my $tmp1=$acc1;
+ my $tmp2=$acc2;
+ my $out=($t0,$t1,$t2,$s[0])[$i];
+
+ if ($i==3) {
+ $tmp0=$s[1];
+ $tmp1=$s[2];
+ $tmp2=$s[3];
+ }
+ $code.=" movzb ".&lo($s[0]).",$out\n";
+ $code.=" mov $s[2],$tmp1\n" if ($i!=3);
+ $code.=" lea 16($key),$key\n" if ($i==0);
+
+ $code.=" movzb ".&hi($s[1]).",$tmp0\n";
+ $code.=" mov 0($sbox,$out,8),$out\n";
+
+ $code.=" shr \$16,$tmp1\n";
+ $code.=" mov $s[3],$tmp2\n" if ($i!=3);
+ $code.=" xor 3($sbox,$tmp0,8),$out\n";
+
+ $code.=" movzb ".&lo($tmp1).",$tmp1\n";
+ $code.=" shr \$24,$tmp2\n";
+ $code.=" xor 4*$i($key),$out\n";
+
+ $code.=" xor 2($sbox,$tmp1,8),$out\n";
+ $code.=" xor 1($sbox,$tmp2,8),$out\n";
+
+ $code.=" mov $t0,$s[1]\n" if ($i==3);
+ $code.=" mov $t1,$s[2]\n" if ($i==3);
+ $code.=" mov $t2,$s[3]\n" if ($i==3);
+ $code.="\n";
+}
+
+sub enclast()
+{ my ($i,@s)=@_;
+ my $tmp0=$acc0;
+ my $tmp1=$acc1;
+ my $tmp2=$acc2;
+ my $out=($t0,$t1,$t2,$s[0])[$i];
+
+ if ($i==3) {
+ $tmp0=$s[1];
+ $tmp1=$s[2];
+ $tmp2=$s[3];
+ }
+ $code.=" movzb ".&lo($s[0]).",$out\n";
+ $code.=" mov $s[2],$tmp1\n" if ($i!=3);
+
+ $code.=" mov 2($sbox,$out,8),$out\n";
+ $code.=" shr \$16,$tmp1\n";
+ $code.=" mov $s[3],$tmp2\n" if ($i!=3);
+
+ $code.=" and \$0x000000ff,$out\n";
+ $code.=" movzb ".&hi($s[1]).",$tmp0\n";
+ $code.=" movzb ".&lo($tmp1).",$tmp1\n";
+ $code.=" shr \$24,$tmp2\n";
+
+ $code.=" mov 0($sbox,$tmp0,8),$tmp0\n";
+ $code.=" mov 0($sbox,$tmp1,8),$tmp1\n";
+ $code.=" mov 2($sbox,$tmp2,8),$tmp2\n";
+
+ $code.=" and \$0x0000ff00,$tmp0\n";
+ $code.=" and \$0x00ff0000,$tmp1\n";
+ $code.=" and \$0xff000000,$tmp2\n";
+
+ $code.=" xor $tmp0,$out\n";
+ $code.=" mov $t0,$s[1]\n" if ($i==3);
+ $code.=" xor $tmp1,$out\n";
+ $code.=" mov $t1,$s[2]\n" if ($i==3);
+ $code.=" xor $tmp2,$out\n";
+ $code.=" mov $t2,$s[3]\n" if ($i==3);
+ $code.="\n";
+}
+
+$code.=<<___;
+.type _x86_64_AES_encrypt,\@abi-omnipotent
+.align 16
+_x86_64_AES_encrypt:
+ xor 0($key),$s0 # xor with key
+ xor 4($key),$s1
+ xor 8($key),$s2
+ xor 12($key),$s3
+
+ mov 240($key),$rnds # load key->rounds
+ sub \$1,$rnds
+ jmp .Lenc_loop
+.align 16
+.Lenc_loop:
+___
+ if ($verticalspin) { &encvert(); }
+ else { &encstep(0,$s0,$s1,$s2,$s3);
+ &encstep(1,$s1,$s2,$s3,$s0);
+ &encstep(2,$s2,$s3,$s0,$s1);
+ &encstep(3,$s3,$s0,$s1,$s2);
+ }
+$code.=<<___;
+ sub \$1,$rnds
+ jnz .Lenc_loop
+___
+ if ($verticalspin) { &enclastvert(); }
+ else { &enclast(0,$s0,$s1,$s2,$s3);
+ &enclast(1,$s1,$s2,$s3,$s0);
+ &enclast(2,$s2,$s3,$s0,$s1);
+ &enclast(3,$s3,$s0,$s1,$s2);
+ $code.=<<___;
+ xor 16+0($key),$s0 # xor with key
+ xor 16+4($key),$s1
+ xor 16+8($key),$s2
+ xor 16+12($key),$s3
+___
+ }
+$code.=<<___;
+ .byte 0xf3,0xc3 # rep ret
+.size _x86_64_AES_encrypt,.-_x86_64_AES_encrypt
+___
+
+# it's possible to implement this by shifting tN by 8, filling least
+# significant byte with byte load and finally bswap-ing at the end,
+# but such partial register load kills Core 2...
+sub enccompactvert()
+{ my ($t3,$t4,$t5)=("%r8d","%r9d","%r13d");
+
+$code.=<<___;
+ movzb `&lo("$s0")`,$t0
+ movzb `&lo("$s1")`,$t1
+ movzb `&lo("$s2")`,$t2
+ movzb `&lo("$s3")`,$t3
+ movzb `&hi("$s1")`,$acc0
+ movzb `&hi("$s2")`,$acc1
+ shr \$16,$s2
+ movzb `&hi("$s3")`,$acc2
+ movzb ($sbox,$t0,1),$t0
+ movzb ($sbox,$t1,1),$t1
+ movzb ($sbox,$t2,1),$t2
+ movzb ($sbox,$t3,1),$t3
+
+ movzb ($sbox,$acc0,1),$t4 #$t0
+ movzb `&hi("$s0")`,$acc0
+ movzb ($sbox,$acc1,1),$t5 #$t1
+ movzb `&lo("$s2")`,$acc1
+ movzb ($sbox,$acc2,1),$acc2 #$t2
+ movzb ($sbox,$acc0,1),$acc0 #$t3
+
+ shl \$8,$t4
+ shr \$16,$s3
+ shl \$8,$t5
+ xor $t4,$t0
+ shr \$16,$s0
+ movzb `&lo("$s3")`,$t4
+ shr \$16,$s1
+ xor $t5,$t1
+ shl \$8,$acc2
+ movzb `&lo("$s0")`,$t5
+ movzb ($sbox,$acc1,1),$acc1 #$t0
+ xor $acc2,$t2
+
+ shl \$8,$acc0
+ movzb `&lo("$s1")`,$acc2
+ shl \$16,$acc1
+ xor $acc0,$t3
+ movzb ($sbox,$t4,1),$t4 #$t1
+ movzb `&hi("$s3")`,$acc0
+ movzb ($sbox,$t5,1),$t5 #$t2
+ xor $acc1,$t0
+
+ shr \$8,$s2
+ movzb `&hi("$s0")`,$acc1
+ shl \$16,$t4
+ shr \$8,$s1
+ shl \$16,$t5
+ xor $t4,$t1
+ movzb ($sbox,$acc2,1),$acc2 #$t3
+ movzb ($sbox,$acc0,1),$acc0 #$t0
+ movzb ($sbox,$acc1,1),$acc1 #$t1
+ movzb ($sbox,$s2,1),$s3 #$t3
+ movzb ($sbox,$s1,1),$s2 #$t2
+
+ shl \$16,$acc2
+ xor $t5,$t2
+ shl \$24,$acc0
+ xor $acc2,$t3
+ shl \$24,$acc1
+ xor $acc0,$t0
+ shl \$24,$s3
+ xor $acc1,$t1
+ shl \$24,$s2
+ mov $t0,$s0
+ mov $t1,$s1
+ xor $t2,$s2
+ xor $t3,$s3
+___
+}
+
+sub enctransform_ref()
+{ my $sn = shift;
+ my ($acc,$r2,$tmp)=("%r8d","%r9d","%r13d");
+
+$code.=<<___;
+ mov $sn,$acc
+ and \$0x80808080,$acc
+ mov $acc,$tmp
+ shr \$7,$tmp
+ lea ($sn,$sn),$r2
+ sub $tmp,$acc
+ and \$0xfefefefe,$r2
+ and \$0x1b1b1b1b,$acc
+ mov $sn,$tmp
+ xor $acc,$r2
+
+ xor $r2,$sn
+ rol \$24,$sn
+ xor $r2,$sn
+ ror \$16,$tmp
+ xor $tmp,$sn
+ ror \$8,$tmp
+ xor $tmp,$sn
+___
+}
+
+# unlike decrypt case it does not pay off to parallelize enctransform
+sub enctransform()
+{ my ($t3,$r20,$r21)=($acc2,"%r8d","%r9d");
+
+$code.=<<___;
+ mov \$0x80808080,$t0
+ mov \$0x80808080,$t1
+ and $s0,$t0
+ and $s1,$t1
+ mov $t0,$acc0
+ mov $t1,$acc1
+ shr \$7,$t0
+ lea ($s0,$s0),$r20
+ shr \$7,$t1
+ lea ($s1,$s1),$r21
+ sub $t0,$acc0
+ sub $t1,$acc1
+ and \$0xfefefefe,$r20
+ and \$0xfefefefe,$r21
+ and \$0x1b1b1b1b,$acc0
+ and \$0x1b1b1b1b,$acc1
+ mov $s0,$t0
+ mov $s1,$t1
+ xor $acc0,$r20
+ xor $acc1,$r21
+
+ xor $r20,$s0
+ xor $r21,$s1
+ mov \$0x80808080,$t2
+ rol \$24,$s0
+ mov \$0x80808080,$t3
+ rol \$24,$s1
+ and $s2,$t2
+ and $s3,$t3
+ xor $r20,$s0
+ xor $r21,$s1
+ mov $t2,$acc0
+ ror \$16,$t0
+ mov $t3,$acc1
+ ror \$16,$t1
+ lea ($s2,$s2),$r20
+ shr \$7,$t2
+ xor $t0,$s0
+ shr \$7,$t3
+ xor $t1,$s1
+ ror \$8,$t0
+ lea ($s3,$s3),$r21
+ ror \$8,$t1
+ sub $t2,$acc0
+ sub $t3,$acc1
+ xor $t0,$s0
+ xor $t1,$s1
+
+ and \$0xfefefefe,$r20
+ and \$0xfefefefe,$r21
+ and \$0x1b1b1b1b,$acc0
+ and \$0x1b1b1b1b,$acc1
+ mov $s2,$t2
+ mov $s3,$t3
+ xor $acc0,$r20
+ xor $acc1,$r21
+
+ ror \$16,$t2
+ xor $r20,$s2
+ ror \$16,$t3
+ xor $r21,$s3
+ rol \$24,$s2
+ mov 0($sbox),$acc0 # prefetch Te4
+ rol \$24,$s3
+ xor $r20,$s2
+ mov 64($sbox),$acc1
+ xor $r21,$s3
+ mov 128($sbox),$r20
+ xor $t2,$s2
+ ror \$8,$t2
+ xor $t3,$s3
+ ror \$8,$t3
+ xor $t2,$s2
+ mov 192($sbox),$r21
+ xor $t3,$s3
+___
+}
+
+$code.=<<___;
+.type _x86_64_AES_encrypt_compact,\@abi-omnipotent
+.align 16
+_x86_64_AES_encrypt_compact:
+ lea 128($sbox),$inp # size optimization
+ mov 0-128($inp),$acc1 # prefetch Te4
+ mov 32-128($inp),$acc2
+ mov 64-128($inp),$t0
+ mov 96-128($inp),$t1
+ mov 128-128($inp),$acc1
+ mov 160-128($inp),$acc2
+ mov 192-128($inp),$t0
+ mov 224-128($inp),$t1
+ jmp .Lenc_loop_compact
+.align 16
+.Lenc_loop_compact:
+ xor 0($key),$s0 # xor with key
+ xor 4($key),$s1
+ xor 8($key),$s2
+ xor 12($key),$s3
+ lea 16($key),$key
+___
+ &enccompactvert();
+$code.=<<___;
+ cmp 16(%rsp),$key
+ je .Lenc_compact_done
+___
+ &enctransform();
+$code.=<<___;
+ jmp .Lenc_loop_compact
+.align 16
+.Lenc_compact_done:
+ xor 0($key),$s0
+ xor 4($key),$s1
+ xor 8($key),$s2
+ xor 12($key),$s3
+ .byte 0xf3,0xc3 # rep ret
+.size _x86_64_AES_encrypt_compact,.-_x86_64_AES_encrypt_compact
+___
+
+# void asm_AES_encrypt (const void *inp,void *out,const AES_KEY *key);
+$code.=<<___;
+.align 16
+.globl asm_AES_encrypt
+.type asm_AES_encrypt,\@function,3
+.hidden asm_AES_encrypt
+asm_AES_encrypt:
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+
+ # allocate frame "above" key schedule
+ mov %rsp,%r10
+ lea -63(%rdx),%rcx # %rdx is key argument
+ and \$-64,%rsp
+ sub %rsp,%rcx
+ neg %rcx
+ and \$0x3c0,%rcx
+ sub %rcx,%rsp
+ sub \$32,%rsp
+
+ mov %rsi,16(%rsp) # save out
+ mov %r10,24(%rsp) # save real stack pointer
+.Lenc_prologue:
+
+ mov %rdx,$key
+ mov 240($key),$rnds # load rounds
+
+ mov 0(%rdi),$s0 # load input vector
+ mov 4(%rdi),$s1
+ mov 8(%rdi),$s2
+ mov 12(%rdi),$s3
+
+ shl \$4,$rnds
+ lea ($key,$rnds),%rbp
+ mov $key,(%rsp) # key schedule
+ mov %rbp,8(%rsp) # end of key schedule
+
+ # pick Te4 copy which can't "overlap" with stack frame or key schedule
+ lea .LAES_Te+2048(%rip),$sbox
+ lea 768(%rsp),%rbp
+ sub $sbox,%rbp
+ and \$0x300,%rbp
+ lea ($sbox,%rbp),$sbox
+
+ call _x86_64_AES_encrypt_compact
+
+ mov 16(%rsp),$out # restore out
+ mov 24(%rsp),%rsi # restore saved stack pointer
+ mov $s0,0($out) # write output vector
+ mov $s1,4($out)
+ mov $s2,8($out)
+ mov $s3,12($out)
+
+ mov (%rsi),%r15
+ mov 8(%rsi),%r14
+ mov 16(%rsi),%r13
+ mov 24(%rsi),%r12
+ mov 32(%rsi),%rbp
+ mov 40(%rsi),%rbx
+ lea 48(%rsi),%rsp
+.Lenc_epilogue:
+ ret
+.size asm_AES_encrypt,.-asm_AES_encrypt
+___
+
+#------------------------------------------------------------------#
+
+sub decvert()
+{ my $t3="%r8d"; # zaps $inp!
+
+$code.=<<___;
+ # favor 3-way issue Opteron pipeline...
+ movzb `&lo("$s0")`,$acc0
+ movzb `&lo("$s1")`,$acc1
+ movzb `&lo("$s2")`,$acc2
+ mov 0($sbox,$acc0,8),$t0
+ mov 0($sbox,$acc1,8),$t1
+ mov 0($sbox,$acc2,8),$t2
+
+ movzb `&hi("$s3")`,$acc0
+ movzb `&hi("$s0")`,$acc1
+ movzb `&lo("$s3")`,$acc2
+ xor 3($sbox,$acc0,8),$t0
+ xor 3($sbox,$acc1,8),$t1
+ mov 0($sbox,$acc2,8),$t3
+
+ movzb `&hi("$s1")`,$acc0
+ shr \$16,$s0
+ movzb `&hi("$s2")`,$acc2
+ xor 3($sbox,$acc0,8),$t2
+ shr \$16,$s3
+ xor 3($sbox,$acc2,8),$t3
+
+ shr \$16,$s1
+ lea 16($key),$key
+ shr \$16,$s2
+
+ movzb `&lo("$s2")`,$acc0
+ movzb `&lo("$s3")`,$acc1
+ movzb `&lo("$s0")`,$acc2
+ xor 2($sbox,$acc0,8),$t0
+ xor 2($sbox,$acc1,8),$t1
+ xor 2($sbox,$acc2,8),$t2
+
+ movzb `&hi("$s1")`,$acc0
+ movzb `&hi("$s2")`,$acc1
+ movzb `&lo("$s1")`,$acc2
+ xor 1($sbox,$acc0,8),$t0
+ xor 1($sbox,$acc1,8),$t1
+ xor 2($sbox,$acc2,8),$t3
+
+ movzb `&hi("$s3")`,$acc0
+ mov 12($key),$s3
+ movzb `&hi("$s0")`,$acc2
+ xor 1($sbox,$acc0,8),$t2
+ mov 0($key),$s0
+ xor 1($sbox,$acc2,8),$t3
+
+ xor $t0,$s0
+ mov 4($key),$s1
+ mov 8($key),$s2
+ xor $t2,$s2
+ xor $t1,$s1
+ xor $t3,$s3
+___
+}
+
+sub declastvert()
+{ my $t3="%r8d"; # zaps $inp!
+
+$code.=<<___;
+ lea 2048($sbox),$sbox # size optimization
+ movzb `&lo("$s0")`,$acc0
+ movzb `&lo("$s1")`,$acc1
+ movzb `&lo("$s2")`,$acc2
+ movzb ($sbox,$acc0,1),$t0
+ movzb ($sbox,$acc1,1),$t1
+ movzb ($sbox,$acc2,1),$t2
+
+ movzb `&lo("$s3")`,$acc0
+ movzb `&hi("$s3")`,$acc1
+ movzb `&hi("$s0")`,$acc2
+ movzb ($sbox,$acc0,1),$t3
+ movzb ($sbox,$acc1,1),$acc1 #$t0
+ movzb ($sbox,$acc2,1),$acc2 #$t1
+
+ shl \$8,$acc1
+ shl \$8,$acc2
+
+ xor $acc1,$t0
+ xor $acc2,$t1
+ shr \$16,$s3
+
+ movzb `&hi("$s1")`,$acc0
+ movzb `&hi("$s2")`,$acc1
+ shr \$16,$s0
+ movzb ($sbox,$acc0,1),$acc0 #$t2
+ movzb ($sbox,$acc1,1),$acc1 #$t3
+
+ shl \$8,$acc0
+ shl \$8,$acc1
+ shr \$16,$s1
+ xor $acc0,$t2
+ xor $acc1,$t3
+ shr \$16,$s2
+
+ movzb `&lo("$s2")`,$acc0
+ movzb `&lo("$s3")`,$acc1
+ movzb `&lo("$s0")`,$acc2
+ movzb ($sbox,$acc0,1),$acc0 #$t0
+ movzb ($sbox,$acc1,1),$acc1 #$t1
+ movzb ($sbox,$acc2,1),$acc2 #$t2
+
+ shl \$16,$acc0
+ shl \$16,$acc1
+ shl \$16,$acc2
+
+ xor $acc0,$t0
+ xor $acc1,$t1
+ xor $acc2,$t2
+
+ movzb `&lo("$s1")`,$acc0
+ movzb `&hi("$s1")`,$acc1
+ movzb `&hi("$s2")`,$acc2
+ movzb ($sbox,$acc0,1),$acc0 #$t3
+ movzb ($sbox,$acc1,1),$acc1 #$t0
+ movzb ($sbox,$acc2,1),$acc2 #$t1
+
+ shl \$16,$acc0
+ shl \$24,$acc1
+ shl \$24,$acc2
+
+ xor $acc0,$t3
+ xor $acc1,$t0
+ xor $acc2,$t1
+
+ movzb `&hi("$s3")`,$acc0
+ movzb `&hi("$s0")`,$acc1
+ mov 16+12($key),$s3
+ movzb ($sbox,$acc0,1),$acc0 #$t2
+ movzb ($sbox,$acc1,1),$acc1 #$t3
+ mov 16+0($key),$s0
+
+ shl \$24,$acc0
+ shl \$24,$acc1
+
+ xor $acc0,$t2
+ xor $acc1,$t3
+
+ mov 16+4($key),$s1
+ mov 16+8($key),$s2
+ lea -2048($sbox),$sbox
+ xor $t0,$s0
+ xor $t1,$s1
+ xor $t2,$s2
+ xor $t3,$s3
+___
+}
+
+sub decstep()
+{ my ($i,@s) = @_;
+ my $tmp0=$acc0;
+ my $tmp1=$acc1;
+ my $tmp2=$acc2;
+ my $out=($t0,$t1,$t2,$s[0])[$i];
+
+ $code.=" mov $s[0],$out\n" if ($i!=3);
+ $tmp1=$s[2] if ($i==3);
+ $code.=" mov $s[2],$tmp1\n" if ($i!=3);
+ $code.=" and \$0xFF,$out\n";
+
+ $code.=" mov 0($sbox,$out,8),$out\n";
+ $code.=" shr \$16,$tmp1\n";
+ $tmp2=$s[3] if ($i==3);
+ $code.=" mov $s[3],$tmp2\n" if ($i!=3);
+
+ $tmp0=$s[1] if ($i==3);
+ $code.=" movzb ".&hi($s[1]).",$tmp0\n";
+ $code.=" and \$0xFF,$tmp1\n";
+ $code.=" shr \$24,$tmp2\n";
+
+ $code.=" xor 3($sbox,$tmp0,8),$out\n";
+ $code.=" xor 2($sbox,$tmp1,8),$out\n";
+ $code.=" xor 1($sbox,$tmp2,8),$out\n";
+
+ $code.=" mov $t2,$s[1]\n" if ($i==3);
+ $code.=" mov $t1,$s[2]\n" if ($i==3);
+ $code.=" mov $t0,$s[3]\n" if ($i==3);
+ $code.="\n";
+}
+
+sub declast()
+{ my ($i,@s)=@_;
+ my $tmp0=$acc0;
+ my $tmp1=$acc1;
+ my $tmp2=$acc2;
+ my $out=($t0,$t1,$t2,$s[0])[$i];
+
+ $code.=" mov $s[0],$out\n" if ($i!=3);
+ $tmp1=$s[2] if ($i==3);
+ $code.=" mov $s[2],$tmp1\n" if ($i!=3);
+ $code.=" and \$0xFF,$out\n";
+
+ $code.=" movzb 2048($sbox,$out,1),$out\n";
+ $code.=" shr \$16,$tmp1\n";
+ $tmp2=$s[3] if ($i==3);
+ $code.=" mov $s[3],$tmp2\n" if ($i!=3);
+
+ $tmp0=$s[1] if ($i==3);
+ $code.=" movzb ".&hi($s[1]).",$tmp0\n";
+ $code.=" and \$0xFF,$tmp1\n";
+ $code.=" shr \$24,$tmp2\n";
+
+ $code.=" movzb 2048($sbox,$tmp0,1),$tmp0\n";
+ $code.=" movzb 2048($sbox,$tmp1,1),$tmp1\n";
+ $code.=" movzb 2048($sbox,$tmp2,1),$tmp2\n";
+
+ $code.=" shl \$8,$tmp0\n";
+ $code.=" shl \$16,$tmp1\n";
+ $code.=" shl \$24,$tmp2\n";
+
+ $code.=" xor $tmp0,$out\n";
+ $code.=" mov $t2,$s[1]\n" if ($i==3);
+ $code.=" xor $tmp1,$out\n";
+ $code.=" mov $t1,$s[2]\n" if ($i==3);
+ $code.=" xor $tmp2,$out\n";
+ $code.=" mov $t0,$s[3]\n" if ($i==3);
+ $code.="\n";
+}
+
+$code.=<<___;
+.type _x86_64_AES_decrypt,\@abi-omnipotent
+.align 16
+_x86_64_AES_decrypt:
+ xor 0($key),$s0 # xor with key
+ xor 4($key),$s1
+ xor 8($key),$s2
+ xor 12($key),$s3
+
+ mov 240($key),$rnds # load key->rounds
+ sub \$1,$rnds
+ jmp .Ldec_loop
+.align 16
+.Ldec_loop:
+___
+ if ($verticalspin) { &decvert(); }
+ else { &decstep(0,$s0,$s3,$s2,$s1);
+ &decstep(1,$s1,$s0,$s3,$s2);
+ &decstep(2,$s2,$s1,$s0,$s3);
+ &decstep(3,$s3,$s2,$s1,$s0);
+ $code.=<<___;
+ lea 16($key),$key
+ xor 0($key),$s0 # xor with key
+ xor 4($key),$s1
+ xor 8($key),$s2
+ xor 12($key),$s3
+___
+ }
+$code.=<<___;
+ sub \$1,$rnds
+ jnz .Ldec_loop
+___
+ if ($verticalspin) { &declastvert(); }
+ else { &declast(0,$s0,$s3,$s2,$s1);
+ &declast(1,$s1,$s0,$s3,$s2);
+ &declast(2,$s2,$s1,$s0,$s3);
+ &declast(3,$s3,$s2,$s1,$s0);
+ $code.=<<___;
+ xor 16+0($key),$s0 # xor with key
+ xor 16+4($key),$s1
+ xor 16+8($key),$s2
+ xor 16+12($key),$s3
+___
+ }
+$code.=<<___;
+ .byte 0xf3,0xc3 # rep ret
+.size _x86_64_AES_decrypt,.-_x86_64_AES_decrypt
+___
+
+sub deccompactvert()
+{ my ($t3,$t4,$t5)=("%r8d","%r9d","%r13d");
+
+$code.=<<___;
+ movzb `&lo("$s0")`,$t0
+ movzb `&lo("$s1")`,$t1
+ movzb `&lo("$s2")`,$t2
+ movzb `&lo("$s3")`,$t3
+ movzb `&hi("$s3")`,$acc0
+ movzb `&hi("$s0")`,$acc1
+ shr \$16,$s3
+ movzb `&hi("$s1")`,$acc2
+ movzb ($sbox,$t0,1),$t0
+ movzb ($sbox,$t1,1),$t1
+ movzb ($sbox,$t2,1),$t2
+ movzb ($sbox,$t3,1),$t3
+
+ movzb ($sbox,$acc0,1),$t4 #$t0
+ movzb `&hi("$s2")`,$acc0
+ movzb ($sbox,$acc1,1),$t5 #$t1
+ movzb ($sbox,$acc2,1),$acc2 #$t2
+ movzb ($sbox,$acc0,1),$acc0 #$t3
+
+ shr \$16,$s2
+ shl \$8,$t5
+ shl \$8,$t4
+ movzb `&lo("$s2")`,$acc1
+ shr \$16,$s0
+ xor $t4,$t0
+ shr \$16,$s1
+ movzb `&lo("$s3")`,$t4
+
+ shl \$8,$acc2
+ xor $t5,$t1
+ shl \$8,$acc0
+ movzb `&lo("$s0")`,$t5
+ movzb ($sbox,$acc1,1),$acc1 #$t0
+ xor $acc2,$t2
+ movzb `&lo("$s1")`,$acc2
+
+ shl \$16,$acc1
+ xor $acc0,$t3
+ movzb ($sbox,$t4,1),$t4 #$t1
+ movzb `&hi("$s1")`,$acc0
+ movzb ($sbox,$acc2,1),$acc2 #$t3
+ xor $acc1,$t0
+ movzb ($sbox,$t5,1),$t5 #$t2
+ movzb `&hi("$s2")`,$acc1
+
+ shl \$16,$acc2
+ shl \$16,$t4
+ shl \$16,$t5
+ xor $acc2,$t3
+ movzb `&hi("$s3")`,$acc2
+ xor $t4,$t1
+ shr \$8,$s0
+ xor $t5,$t2
+
+ movzb ($sbox,$acc0,1),$acc0 #$t0
+ movzb ($sbox,$acc1,1),$s1 #$t1
+ movzb ($sbox,$acc2,1),$s2 #$t2
+ movzb ($sbox,$s0,1),$s3 #$t3
+
+ mov $t0,$s0
+ shl \$24,$acc0
+ shl \$24,$s1
+ shl \$24,$s2
+ xor $acc0,$s0
+ shl \$24,$s3
+ xor $t1,$s1
+ xor $t2,$s2
+ xor $t3,$s3
+___
+}
+
+# parallelized version! input is pair of 64-bit values: %rax=s1.s0
+# and %rcx=s3.s2, output is four 32-bit values in %eax=s0, %ebx=s1,
+# %ecx=s2 and %edx=s3.
+sub dectransform()
+{ my ($tp10,$tp20,$tp40,$tp80,$acc0)=("%rax","%r8", "%r9", "%r10","%rbx");
+ my ($tp18,$tp28,$tp48,$tp88,$acc8)=("%rcx","%r11","%r12","%r13","%rdx");
+ my $prefetch = shift;
+
+$code.=<<___;
+ mov $mask80,$tp40
+ mov $mask80,$tp48
+ and $tp10,$tp40
+ and $tp18,$tp48
+ mov $tp40,$acc0
+ mov $tp48,$acc8
+ shr \$7,$tp40
+ lea ($tp10,$tp10),$tp20
+ shr \$7,$tp48
+ lea ($tp18,$tp18),$tp28
+ sub $tp40,$acc0
+ sub $tp48,$acc8
+ and $maskfe,$tp20
+ and $maskfe,$tp28
+ and $mask1b,$acc0
+ and $mask1b,$acc8
+ xor $acc0,$tp20
+ xor $acc8,$tp28
+ mov $mask80,$tp80
+ mov $mask80,$tp88
+
+ and $tp20,$tp80
+ and $tp28,$tp88
+ mov $tp80,$acc0
+ mov $tp88,$acc8
+ shr \$7,$tp80
+ lea ($tp20,$tp20),$tp40
+ shr \$7,$tp88
+ lea ($tp28,$tp28),$tp48
+ sub $tp80,$acc0
+ sub $tp88,$acc8
+ and $maskfe,$tp40
+ and $maskfe,$tp48
+ and $mask1b,$acc0
+ and $mask1b,$acc8
+ xor $acc0,$tp40
+ xor $acc8,$tp48
+ mov $mask80,$tp80
+ mov $mask80,$tp88
+
+ and $tp40,$tp80
+ and $tp48,$tp88
+ mov $tp80,$acc0
+ mov $tp88,$acc8
+ shr \$7,$tp80
+ xor $tp10,$tp20 # tp2^=tp1
+ shr \$7,$tp88
+ xor $tp18,$tp28 # tp2^=tp1
+ sub $tp80,$acc0
+ sub $tp88,$acc8
+ lea ($tp40,$tp40),$tp80
+ lea ($tp48,$tp48),$tp88
+ xor $tp10,$tp40 # tp4^=tp1
+ xor $tp18,$tp48 # tp4^=tp1
+ and $maskfe,$tp80
+ and $maskfe,$tp88
+ and $mask1b,$acc0
+ and $mask1b,$acc8
+ xor $acc0,$tp80
+ xor $acc8,$tp88
+
+ xor $tp80,$tp10 # tp1^=tp8
+ xor $tp88,$tp18 # tp1^=tp8
+ xor $tp80,$tp20 # tp2^tp1^=tp8
+ xor $tp88,$tp28 # tp2^tp1^=tp8
+ mov $tp10,$acc0
+ mov $tp18,$acc8
+ xor $tp80,$tp40 # tp4^tp1^=tp8
+ shr \$32,$acc0
+ xor $tp88,$tp48 # tp4^tp1^=tp8
+ shr \$32,$acc8
+ xor $tp20,$tp80 # tp8^=tp8^tp2^tp1=tp2^tp1
+ rol \$8,`&LO("$tp10")` # ROTATE(tp1^tp8,8)
+ xor $tp28,$tp88 # tp8^=tp8^tp2^tp1=tp2^tp1
+ rol \$8,`&LO("$tp18")` # ROTATE(tp1^tp8,8)
+ xor $tp40,$tp80 # tp2^tp1^=tp8^tp4^tp1=tp8^tp4^tp2
+ rol \$8,`&LO("$acc0")` # ROTATE(tp1^tp8,8)
+ xor $tp48,$tp88 # tp2^tp1^=tp8^tp4^tp1=tp8^tp4^tp2
+
+ rol \$8,`&LO("$acc8")` # ROTATE(tp1^tp8,8)
+ xor `&LO("$tp80")`,`&LO("$tp10")`
+ shr \$32,$tp80
+ xor `&LO("$tp88")`,`&LO("$tp18")`
+ shr \$32,$tp88
+ xor `&LO("$tp80")`,`&LO("$acc0")`
+ xor `&LO("$tp88")`,`&LO("$acc8")`
+
+ mov $tp20,$tp80
+ rol \$24,`&LO("$tp20")` # ROTATE(tp2^tp1^tp8,24)
+ mov $tp28,$tp88
+ rol \$24,`&LO("$tp28")` # ROTATE(tp2^tp1^tp8,24)
+ shr \$32,$tp80
+ xor `&LO("$tp20")`,`&LO("$tp10")`
+ shr \$32,$tp88
+ xor `&LO("$tp28")`,`&LO("$tp18")`
+ rol \$24,`&LO("$tp80")` # ROTATE(tp2^tp1^tp8,24)
+ mov $tp40,$tp20
+ rol \$24,`&LO("$tp88")` # ROTATE(tp2^tp1^tp8,24)
+ mov $tp48,$tp28
+ shr \$32,$tp20
+ xor `&LO("$tp80")`,`&LO("$acc0")`
+ shr \$32,$tp28
+ xor `&LO("$tp88")`,`&LO("$acc8")`
+
+ `"mov 0($sbox),$mask80" if ($prefetch)`
+ rol \$16,`&LO("$tp40")` # ROTATE(tp4^tp1^tp8,16)
+ `"mov 64($sbox),$maskfe" if ($prefetch)`
+ rol \$16,`&LO("$tp48")` # ROTATE(tp4^tp1^tp8,16)
+ `"mov 128($sbox),$mask1b" if ($prefetch)`
+ rol \$16,`&LO("$tp20")` # ROTATE(tp4^tp1^tp8,16)
+ `"mov 192($sbox),$tp80" if ($prefetch)`
+ xor `&LO("$tp40")`,`&LO("$tp10")`
+ rol \$16,`&LO("$tp28")` # ROTATE(tp4^tp1^tp8,16)
+ xor `&LO("$tp48")`,`&LO("$tp18")`
+ `"mov 256($sbox),$tp88" if ($prefetch)`
+ xor `&LO("$tp20")`,`&LO("$acc0")`
+ xor `&LO("$tp28")`,`&LO("$acc8")`
+___
+}
+
+$code.=<<___;
+.type _x86_64_AES_decrypt_compact,\@abi-omnipotent
+.align 16
+_x86_64_AES_decrypt_compact:
+ lea 128($sbox),$inp # size optimization
+ mov 0-128($inp),$acc1 # prefetch Td4
+ mov 32-128($inp),$acc2
+ mov 64-128($inp),$t0
+ mov 96-128($inp),$t1
+ mov 128-128($inp),$acc1
+ mov 160-128($inp),$acc2
+ mov 192-128($inp),$t0
+ mov 224-128($inp),$t1
+ jmp .Ldec_loop_compact
+
+.align 16
+.Ldec_loop_compact:
+ xor 0($key),$s0 # xor with key
+ xor 4($key),$s1
+ xor 8($key),$s2
+ xor 12($key),$s3
+ lea 16($key),$key
+___
+ &deccompactvert();
+$code.=<<___;
+ cmp 16(%rsp),$key
+ je .Ldec_compact_done
+
+ mov 256+0($sbox),$mask80
+ shl \$32,%rbx
+ shl \$32,%rdx
+ mov 256+8($sbox),$maskfe
+ or %rbx,%rax
+ or %rdx,%rcx
+ mov 256+16($sbox),$mask1b
+___
+ &dectransform(1);
+$code.=<<___;
+ jmp .Ldec_loop_compact
+.align 16
+.Ldec_compact_done:
+ xor 0($key),$s0
+ xor 4($key),$s1
+ xor 8($key),$s2
+ xor 12($key),$s3
+ .byte 0xf3,0xc3 # rep ret
+.size _x86_64_AES_decrypt_compact,.-_x86_64_AES_decrypt_compact
+___
+
+# void asm_AES_decrypt (const void *inp,void *out,const AES_KEY *key);
+$code.=<<___;
+.align 16
+.globl asm_AES_decrypt
+.type asm_AES_decrypt,\@function,3
+.hidden asm_AES_decrypt
+asm_AES_decrypt:
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+
+ # allocate frame "above" key schedule
+ mov %rsp,%r10
+ lea -63(%rdx),%rcx # %rdx is key argument
+ and \$-64,%rsp
+ sub %rsp,%rcx
+ neg %rcx
+ and \$0x3c0,%rcx
+ sub %rcx,%rsp
+ sub \$32,%rsp
+
+ mov %rsi,16(%rsp) # save out
+ mov %r10,24(%rsp) # save real stack pointer
+.Ldec_prologue:
+
+ mov %rdx,$key
+ mov 240($key),$rnds # load rounds
+
+ mov 0(%rdi),$s0 # load input vector
+ mov 4(%rdi),$s1
+ mov 8(%rdi),$s2
+ mov 12(%rdi),$s3
+
+ shl \$4,$rnds
+ lea ($key,$rnds),%rbp
+ mov $key,(%rsp) # key schedule
+ mov %rbp,8(%rsp) # end of key schedule
+
+ # pick Td4 copy which can't "overlap" with stack frame or key schedule
+ lea .LAES_Td+2048(%rip),$sbox
+ lea 768(%rsp),%rbp
+ sub $sbox,%rbp
+ and \$0x300,%rbp
+ lea ($sbox,%rbp),$sbox
+ shr \$3,%rbp # recall "magic" constants!
+ add %rbp,$sbox
+
+ call _x86_64_AES_decrypt_compact
+
+ mov 16(%rsp),$out # restore out
+ mov 24(%rsp),%rsi # restore saved stack pointer
+ mov $s0,0($out) # write output vector
+ mov $s1,4($out)
+ mov $s2,8($out)
+ mov $s3,12($out)
+
+ mov (%rsi),%r15
+ mov 8(%rsi),%r14
+ mov 16(%rsi),%r13
+ mov 24(%rsi),%r12
+ mov 32(%rsi),%rbp
+ mov 40(%rsi),%rbx
+ lea 48(%rsi),%rsp
+.Ldec_epilogue:
+ ret
+.size asm_AES_decrypt,.-asm_AES_decrypt
+___
+#------------------------------------------------------------------#
+
+sub enckey()
+{
+$code.=<<___;
+ movz %dl,%esi # rk[i]>>0
+ movzb -128(%rbp,%rsi),%ebx
+ movz %dh,%esi # rk[i]>>8
+ shl \$24,%ebx
+ xor %ebx,%eax
+
+ movzb -128(%rbp,%rsi),%ebx
+ shr \$16,%edx
+ movz %dl,%esi # rk[i]>>16
+ xor %ebx,%eax
+
+ movzb -128(%rbp,%rsi),%ebx
+ movz %dh,%esi # rk[i]>>24
+ shl \$8,%ebx
+ xor %ebx,%eax
+
+ movzb -128(%rbp,%rsi),%ebx
+ shl \$16,%ebx
+ xor %ebx,%eax
+
+ xor 1024-128(%rbp,%rcx,4),%eax # rcon
+___
+}
+
+# int asm_AES_set_encrypt_key(const unsigned char *userKey, const int bits, AES_KEY *key)
+$code.=<<___;
+.align 16
+.globl asm_AES_set_encrypt_key
+.type asm_AES_set_encrypt_key,\@function,3
+asm_AES_set_encrypt_key:
+ push %rbx
+ push %rbp
+ push %r12 # redundant, but allows to share
+ push %r13 # exception handler...
+ push %r14
+ push %r15
+ sub \$8,%rsp
+.Lenc_key_prologue:
+
+ call _x86_64_AES_set_encrypt_key
+
+ mov 40(%rsp),%rbp
+ mov 48(%rsp),%rbx
+ add \$56,%rsp
+.Lenc_key_epilogue:
+ ret
+.size asm_AES_set_encrypt_key,.-asm_AES_set_encrypt_key
+
+.type _x86_64_AES_set_encrypt_key,\@abi-omnipotent
+.align 16
+_x86_64_AES_set_encrypt_key:
+ mov %esi,%ecx # %ecx=bits
+ mov %rdi,%rsi # %rsi=userKey
+ mov %rdx,%rdi # %rdi=key
+
+ test \$-1,%rsi
+ jz .Lbadpointer
+ test \$-1,%rdi
+ jz .Lbadpointer
+
+ lea .LAES_Te(%rip),%rbp
+ lea 2048+128(%rbp),%rbp
+
+ # prefetch Te4
+ mov 0-128(%rbp),%eax
+ mov 32-128(%rbp),%ebx
+ mov 64-128(%rbp),%r8d
+ mov 96-128(%rbp),%edx
+ mov 128-128(%rbp),%eax
+ mov 160-128(%rbp),%ebx
+ mov 192-128(%rbp),%r8d
+ mov 224-128(%rbp),%edx
+
+ cmp \$128,%ecx
+ je .L10rounds
+ cmp \$192,%ecx
+ je .L12rounds
+ cmp \$256,%ecx
+ je .L14rounds
+ mov \$-2,%rax # invalid number of bits
+ jmp .Lexit
+
+.L10rounds:
+ mov 0(%rsi),%rax # copy first 4 dwords
+ mov 8(%rsi),%rdx
+ mov %rax,0(%rdi)
+ mov %rdx,8(%rdi)
+
+ shr \$32,%rdx
+ xor %ecx,%ecx
+ jmp .L10shortcut
+.align 4
+.L10loop:
+ mov 0(%rdi),%eax # rk[0]
+ mov 12(%rdi),%edx # rk[3]
+.L10shortcut:
+___
+ &enckey ();
+$code.=<<___;
+ mov %eax,16(%rdi) # rk[4]
+ xor 4(%rdi),%eax
+ mov %eax,20(%rdi) # rk[5]
+ xor 8(%rdi),%eax
+ mov %eax,24(%rdi) # rk[6]
+ xor 12(%rdi),%eax
+ mov %eax,28(%rdi) # rk[7]
+ add \$1,%ecx
+ lea 16(%rdi),%rdi
+ cmp \$10,%ecx
+ jl .L10loop
+
+ movl \$10,80(%rdi) # setup number of rounds
+ xor %rax,%rax
+ jmp .Lexit
+
+.L12rounds:
+ mov 0(%rsi),%rax # copy first 6 dwords
+ mov 8(%rsi),%rbx
+ mov 16(%rsi),%rdx
+ mov %rax,0(%rdi)
+ mov %rbx,8(%rdi)
+ mov %rdx,16(%rdi)
+
+ shr \$32,%rdx
+ xor %ecx,%ecx
+ jmp .L12shortcut
+.align 4
+.L12loop:
+ mov 0(%rdi),%eax # rk[0]
+ mov 20(%rdi),%edx # rk[5]
+.L12shortcut:
+___
+ &enckey ();
+$code.=<<___;
+ mov %eax,24(%rdi) # rk[6]
+ xor 4(%rdi),%eax
+ mov %eax,28(%rdi) # rk[7]
+ xor 8(%rdi),%eax
+ mov %eax,32(%rdi) # rk[8]
+ xor 12(%rdi),%eax
+ mov %eax,36(%rdi) # rk[9]
+
+ cmp \$7,%ecx
+ je .L12break
+ add \$1,%ecx
+
+ xor 16(%rdi),%eax
+ mov %eax,40(%rdi) # rk[10]
+ xor 20(%rdi),%eax
+ mov %eax,44(%rdi) # rk[11]
+
+ lea 24(%rdi),%rdi
+ jmp .L12loop
+.L12break:
+ movl \$12,72(%rdi) # setup number of rounds
+ xor %rax,%rax
+ jmp .Lexit
+
+.L14rounds:
+ mov 0(%rsi),%rax # copy first 8 dwords
+ mov 8(%rsi),%rbx
+ mov 16(%rsi),%rcx
+ mov 24(%rsi),%rdx
+ mov %rax,0(%rdi)
+ mov %rbx,8(%rdi)
+ mov %rcx,16(%rdi)
+ mov %rdx,24(%rdi)
+
+ shr \$32,%rdx
+ xor %ecx,%ecx
+ jmp .L14shortcut
+.align 4
+.L14loop:
+ mov 0(%rdi),%eax # rk[0]
+ mov 28(%rdi),%edx # rk[4]
+.L14shortcut:
+___
+ &enckey ();
+$code.=<<___;
+ mov %eax,32(%rdi) # rk[8]
+ xor 4(%rdi),%eax
+ mov %eax,36(%rdi) # rk[9]
+ xor 8(%rdi),%eax
+ mov %eax,40(%rdi) # rk[10]
+ xor 12(%rdi),%eax
+ mov %eax,44(%rdi) # rk[11]
+
+ cmp \$6,%ecx
+ je .L14break
+ add \$1,%ecx
+
+ mov %eax,%edx
+ mov 16(%rdi),%eax # rk[4]
+ movz %dl,%esi # rk[11]>>0
+ movzb -128(%rbp,%rsi),%ebx
+ movz %dh,%esi # rk[11]>>8
+ xor %ebx,%eax
+
+ movzb -128(%rbp,%rsi),%ebx
+ shr \$16,%edx
+ shl \$8,%ebx
+ movz %dl,%esi # rk[11]>>16
+ xor %ebx,%eax
+
+ movzb -128(%rbp,%rsi),%ebx
+ movz %dh,%esi # rk[11]>>24
+ shl \$16,%ebx
+ xor %ebx,%eax
+
+ movzb -128(%rbp,%rsi),%ebx
+ shl \$24,%ebx
+ xor %ebx,%eax
+
+ mov %eax,48(%rdi) # rk[12]
+ xor 20(%rdi),%eax
+ mov %eax,52(%rdi) # rk[13]
+ xor 24(%rdi),%eax
+ mov %eax,56(%rdi) # rk[14]
+ xor 28(%rdi),%eax
+ mov %eax,60(%rdi) # rk[15]
+
+ lea 32(%rdi),%rdi
+ jmp .L14loop
+.L14break:
+ movl \$14,48(%rdi) # setup number of rounds
+ xor %rax,%rax
+ jmp .Lexit
+
+.Lbadpointer:
+ mov \$-1,%rax
+.Lexit:
+ .byte 0xf3,0xc3 # rep ret
+.size _x86_64_AES_set_encrypt_key,.-_x86_64_AES_set_encrypt_key
+___
+
+sub deckey_ref()
+{ my ($i,$ptr,$te,$td) = @_;
+ my ($tp1,$tp2,$tp4,$tp8,$acc)=("%eax","%ebx","%edi","%edx","%r8d");
+$code.=<<___;
+ mov $i($ptr),$tp1
+ mov $tp1,$acc
+ and \$0x80808080,$acc
+ mov $acc,$tp4
+ shr \$7,$tp4
+ lea 0($tp1,$tp1),$tp2
+ sub $tp4,$acc
+ and \$0xfefefefe,$tp2
+ and \$0x1b1b1b1b,$acc
+ xor $tp2,$acc
+ mov $acc,$tp2
+
+ and \$0x80808080,$acc
+ mov $acc,$tp8
+ shr \$7,$tp8
+ lea 0($tp2,$tp2),$tp4
+ sub $tp8,$acc
+ and \$0xfefefefe,$tp4
+ and \$0x1b1b1b1b,$acc
+ xor $tp1,$tp2 # tp2^tp1
+ xor $tp4,$acc
+ mov $acc,$tp4
+
+ and \$0x80808080,$acc
+ mov $acc,$tp8
+ shr \$7,$tp8
+ sub $tp8,$acc
+ lea 0($tp4,$tp4),$tp8
+ xor $tp1,$tp4 # tp4^tp1
+ and \$0xfefefefe,$tp8
+ and \$0x1b1b1b1b,$acc
+ xor $acc,$tp8
+
+ xor $tp8,$tp1 # tp1^tp8
+ rol \$8,$tp1 # ROTATE(tp1^tp8,8)
+ xor $tp8,$tp2 # tp2^tp1^tp8
+ xor $tp8,$tp4 # tp4^tp1^tp8
+ xor $tp2,$tp8
+ xor $tp4,$tp8 # tp8^(tp8^tp4^tp1)^(tp8^tp2^tp1)=tp8^tp4^tp2
+
+ xor $tp8,$tp1
+ rol \$24,$tp2 # ROTATE(tp2^tp1^tp8,24)
+ xor $tp2,$tp1
+ rol \$16,$tp4 # ROTATE(tp4^tp1^tp8,16)
+ xor $tp4,$tp1
+
+ mov $tp1,$i($ptr)
+___
+}
+
+# int asm_AES_set_decrypt_key(const unsigned char *userKey, const int bits, AES_KEY *key)
+$code.=<<___;
+.align 16
+.globl asm_AES_set_decrypt_key
+.type asm_AES_set_decrypt_key,\@function,3
+asm_AES_set_decrypt_key:
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+ push %rdx # save key schedule
+.Ldec_key_prologue:
+
+ call _x86_64_AES_set_encrypt_key
+ mov (%rsp),%r8 # restore key schedule
+ cmp \$0,%eax
+ jne .Labort
+
+ mov 240(%r8),%r14d # pull number of rounds
+ xor %rdi,%rdi
+ lea (%rdi,%r14d,4),%rcx
+ mov %r8,%rsi
+ lea (%r8,%rcx,4),%rdi # pointer to last chunk
+.align 4
+.Linvert:
+ mov 0(%rsi),%rax
+ mov 8(%rsi),%rbx
+ mov 0(%rdi),%rcx
+ mov 8(%rdi),%rdx
+ mov %rax,0(%rdi)
+ mov %rbx,8(%rdi)
+ mov %rcx,0(%rsi)
+ mov %rdx,8(%rsi)
+ lea 16(%rsi),%rsi
+ lea -16(%rdi),%rdi
+ cmp %rsi,%rdi
+ jne .Linvert
+
+ lea .LAES_Te+2048+1024(%rip),%rax # rcon
+
+ mov 40(%rax),$mask80
+ mov 48(%rax),$maskfe
+ mov 56(%rax),$mask1b
+
+ mov %r8,$key
+ sub \$1,%r14d
+.align 4
+.Lpermute:
+ lea 16($key),$key
+ mov 0($key),%rax
+ mov 8($key),%rcx
+___
+ &dectransform ();
+$code.=<<___;
+ mov %eax,0($key)
+ mov %ebx,4($key)
+ mov %ecx,8($key)
+ mov %edx,12($key)
+ sub \$1,%r14d
+ jnz .Lpermute
+
+ xor %rax,%rax
+.Labort:
+ mov 8(%rsp),%r15
+ mov 16(%rsp),%r14
+ mov 24(%rsp),%r13
+ mov 32(%rsp),%r12
+ mov 40(%rsp),%rbp
+ mov 48(%rsp),%rbx
+ add \$56,%rsp
+.Ldec_key_epilogue:
+ ret
+.size asm_AES_set_decrypt_key,.-asm_AES_set_decrypt_key
+___
+
+# void asm_AES_cbc_encrypt (const void char *inp, unsigned char *out,
+# size_t length, const AES_KEY *key,
+# unsigned char *ivp,const int enc);
+{
+# stack frame layout
+# -8(%rsp) return address
+my $keyp="0(%rsp)"; # one to pass as $key
+my $keyend="8(%rsp)"; # &(keyp->rd_key[4*keyp->rounds])
+my $_rsp="16(%rsp)"; # saved %rsp
+my $_inp="24(%rsp)"; # copy of 1st parameter, inp
+my $_out="32(%rsp)"; # copy of 2nd parameter, out
+my $_len="40(%rsp)"; # copy of 3rd parameter, length
+my $_key="48(%rsp)"; # copy of 4th parameter, key
+my $_ivp="56(%rsp)"; # copy of 5th parameter, ivp
+my $ivec="64(%rsp)"; # ivec[16]
+my $aes_key="80(%rsp)"; # copy of aes_key
+my $mark="80+240(%rsp)"; # copy of aes_key->rounds
+
+$code.=<<___;
+.align 16
+.globl asm_AES_cbc_encrypt
+.type asm_AES_cbc_encrypt,\@function,6
+.extern OPENSSL_ia32cap_P
+.hidden asm_AES_cbc_encrypt
+asm_AES_cbc_encrypt:
+ cmp \$0,%rdx # check length
+ je .Lcbc_epilogue
+ pushfq
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+.Lcbc_prologue:
+
+ cld
+ mov %r9d,%r9d # clear upper half of enc
+
+ lea .LAES_Te(%rip),$sbox
+ cmp \$0,%r9
+ jne .Lcbc_picked_te
+ lea .LAES_Td(%rip),$sbox
+.Lcbc_picked_te:
+
+ mov OPENSSL_ia32cap_P(%rip),%r10d
+ cmp \$$speed_limit,%rdx
+ jb .Lcbc_slow_prologue
+ test \$15,%rdx
+ jnz .Lcbc_slow_prologue
+ bt \$28,%r10d
+ jc .Lcbc_slow_prologue
+
+ # allocate aligned stack frame...
+ lea -88-248(%rsp),$key
+ and \$-64,$key
+
+ # ... and make sure it doesn't alias with AES_T[ed] modulo 4096
+ mov $sbox,%r10
+ lea 2304($sbox),%r11
+ mov $key,%r12
+ and \$0xFFF,%r10 # s = $sbox&0xfff
+ and \$0xFFF,%r11 # e = ($sbox+2048)&0xfff
+ and \$0xFFF,%r12 # p = %rsp&0xfff
+
+ cmp %r11,%r12 # if (p=>e) %rsp =- (p-e);
+ jb .Lcbc_te_break_out
+ sub %r11,%r12
+ sub %r12,$key
+ jmp .Lcbc_te_ok
+.Lcbc_te_break_out: # else %rsp -= (p-s)&0xfff + framesz
+ sub %r10,%r12
+ and \$0xFFF,%r12
+ add \$320,%r12
+ sub %r12,$key
+.align 4
+.Lcbc_te_ok:
+
+ xchg %rsp,$key
+ #add \$8,%rsp # reserve for return address!
+ mov $key,$_rsp # save %rsp
+.Lcbc_fast_body:
+ mov %rdi,$_inp # save copy of inp
+ mov %rsi,$_out # save copy of out
+ mov %rdx,$_len # save copy of len
+ mov %rcx,$_key # save copy of key
+ mov %r8,$_ivp # save copy of ivp
+ movl \$0,$mark # copy of aes_key->rounds = 0;
+ mov %r8,%rbp # rearrange input arguments
+ mov %r9,%rbx
+ mov %rsi,$out
+ mov %rdi,$inp
+ mov %rcx,$key
+
+ mov 240($key),%eax # key->rounds
+ # do we copy key schedule to stack?
+ mov $key,%r10
+ sub $sbox,%r10
+ and \$0xfff,%r10
+ cmp \$2304,%r10
+ jb .Lcbc_do_ecopy
+ cmp \$4096-248,%r10
+ jb .Lcbc_skip_ecopy
+.align 4
+.Lcbc_do_ecopy:
+ mov $key,%rsi
+ lea $aes_key,%rdi
+ lea $aes_key,$key
+ mov \$240/8,%ecx
+ .long 0x90A548F3 # rep movsq
+ mov %eax,(%rdi) # copy aes_key->rounds
+.Lcbc_skip_ecopy:
+ mov $key,$keyp # save key pointer
+
+ mov \$18,%ecx
+.align 4
+.Lcbc_prefetch_te:
+ mov 0($sbox),%r10
+ mov 32($sbox),%r11
+ mov 64($sbox),%r12
+ mov 96($sbox),%r13
+ lea 128($sbox),$sbox
+ sub \$1,%ecx
+ jnz .Lcbc_prefetch_te
+ lea -2304($sbox),$sbox
+
+ cmp \$0,%rbx
+ je .LFAST_DECRYPT
+
+#----------------------------- ENCRYPT -----------------------------#
+ mov 0(%rbp),$s0 # load iv
+ mov 4(%rbp),$s1
+ mov 8(%rbp),$s2
+ mov 12(%rbp),$s3
+
+.align 4
+.Lcbc_fast_enc_loop:
+ xor 0($inp),$s0
+ xor 4($inp),$s1
+ xor 8($inp),$s2
+ xor 12($inp),$s3
+ mov $keyp,$key # restore key
+ mov $inp,$_inp # if ($verticalspin) save inp
+
+ call _x86_64_AES_encrypt
+
+ mov $_inp,$inp # if ($verticalspin) restore inp
+ mov $_len,%r10
+ mov $s0,0($out)
+ mov $s1,4($out)
+ mov $s2,8($out)
+ mov $s3,12($out)
+
+ lea 16($inp),$inp
+ lea 16($out),$out
+ sub \$16,%r10
+ test \$-16,%r10
+ mov %r10,$_len
+ jnz .Lcbc_fast_enc_loop
+ mov $_ivp,%rbp # restore ivp
+ mov $s0,0(%rbp) # save ivec
+ mov $s1,4(%rbp)
+ mov $s2,8(%rbp)
+ mov $s3,12(%rbp)
+
+ jmp .Lcbc_fast_cleanup
+
+#----------------------------- DECRYPT -----------------------------#
+.align 16
+.LFAST_DECRYPT:
+ cmp $inp,$out
+ je .Lcbc_fast_dec_in_place
+
+ mov %rbp,$ivec
+.align 4
+.Lcbc_fast_dec_loop:
+ mov 0($inp),$s0 # read input
+ mov 4($inp),$s1
+ mov 8($inp),$s2
+ mov 12($inp),$s3
+ mov $keyp,$key # restore key
+ mov $inp,$_inp # if ($verticalspin) save inp
+
+ call _x86_64_AES_decrypt
+
+ mov $ivec,%rbp # load ivp
+ mov $_inp,$inp # if ($verticalspin) restore inp
+ mov $_len,%r10 # load len
+ xor 0(%rbp),$s0 # xor iv
+ xor 4(%rbp),$s1
+ xor 8(%rbp),$s2
+ xor 12(%rbp),$s3
+ mov $inp,%rbp # current input, next iv
+
+ sub \$16,%r10
+ mov %r10,$_len # update len
+ mov %rbp,$ivec # update ivp
+
+ mov $s0,0($out) # write output
+ mov $s1,4($out)
+ mov $s2,8($out)
+ mov $s3,12($out)
+
+ lea 16($inp),$inp
+ lea 16($out),$out
+ jnz .Lcbc_fast_dec_loop
+ mov $_ivp,%r12 # load user ivp
+ mov 0(%rbp),%r10 # load iv
+ mov 8(%rbp),%r11
+ mov %r10,0(%r12) # copy back to user
+ mov %r11,8(%r12)
+ jmp .Lcbc_fast_cleanup
+
+.align 16
+.Lcbc_fast_dec_in_place:
+ mov 0(%rbp),%r10 # copy iv to stack
+ mov 8(%rbp),%r11
+ mov %r10,0+$ivec
+ mov %r11,8+$ivec
+.align 4
+.Lcbc_fast_dec_in_place_loop:
+ mov 0($inp),$s0 # load input
+ mov 4($inp),$s1
+ mov 8($inp),$s2
+ mov 12($inp),$s3
+ mov $keyp,$key # restore key
+ mov $inp,$_inp # if ($verticalspin) save inp
+
+ call _x86_64_AES_decrypt
+
+ mov $_inp,$inp # if ($verticalspin) restore inp
+ mov $_len,%r10
+ xor 0+$ivec,$s0
+ xor 4+$ivec,$s1
+ xor 8+$ivec,$s2
+ xor 12+$ivec,$s3
+
+ mov 0($inp),%r11 # load input
+ mov 8($inp),%r12
+ sub \$16,%r10
+ jz .Lcbc_fast_dec_in_place_done
+
+ mov %r11,0+$ivec # copy input to iv
+ mov %r12,8+$ivec
+
+ mov $s0,0($out) # save output [zaps input]
+ mov $s1,4($out)
+ mov $s2,8($out)
+ mov $s3,12($out)
+
+ lea 16($inp),$inp
+ lea 16($out),$out
+ mov %r10,$_len
+ jmp .Lcbc_fast_dec_in_place_loop
+.Lcbc_fast_dec_in_place_done:
+ mov $_ivp,%rdi
+ mov %r11,0(%rdi) # copy iv back to user
+ mov %r12,8(%rdi)
+
+ mov $s0,0($out) # save output [zaps input]
+ mov $s1,4($out)
+ mov $s2,8($out)
+ mov $s3,12($out)
+
+.align 4
+.Lcbc_fast_cleanup:
+ cmpl \$0,$mark # was the key schedule copied?
+ lea $aes_key,%rdi
+ je .Lcbc_exit
+ mov \$240/8,%ecx
+ xor %rax,%rax
+ .long 0x90AB48F3 # rep stosq
+
+ jmp .Lcbc_exit
+
+#--------------------------- SLOW ROUTINE ---------------------------#
+.align 16
+.Lcbc_slow_prologue:
+ # allocate aligned stack frame...
+ lea -88(%rsp),%rbp
+ and \$-64,%rbp
+ # ... just "above" key schedule
+ lea -88-63(%rcx),%r10
+ sub %rbp,%r10
+ neg %r10
+ and \$0x3c0,%r10
+ sub %r10,%rbp
+
+ xchg %rsp,%rbp
+ #add \$8,%rsp # reserve for return address!
+ mov %rbp,$_rsp # save %rsp
+.Lcbc_slow_body:
+ #mov %rdi,$_inp # save copy of inp
+ #mov %rsi,$_out # save copy of out
+ #mov %rdx,$_len # save copy of len
+ #mov %rcx,$_key # save copy of key
+ mov %r8,$_ivp # save copy of ivp
+ mov %r8,%rbp # rearrange input arguments
+ mov %r9,%rbx
+ mov %rsi,$out
+ mov %rdi,$inp
+ mov %rcx,$key
+ mov %rdx,%r10
+
+ mov 240($key),%eax
+ mov $key,$keyp # save key pointer
+ shl \$4,%eax
+ lea ($key,%rax),%rax
+ mov %rax,$keyend
+
+ # pick Te4 copy which can't "overlap" with stack frame or key scdedule
+ lea 2048($sbox),$sbox
+ lea 768-8(%rsp),%rax
+ sub $sbox,%rax
+ and \$0x300,%rax
+ lea ($sbox,%rax),$sbox
+
+ cmp \$0,%rbx
+ je .LSLOW_DECRYPT
+
+#--------------------------- SLOW ENCRYPT ---------------------------#
+ test \$-16,%r10 # check upon length
+ mov 0(%rbp),$s0 # load iv
+ mov 4(%rbp),$s1
+ mov 8(%rbp),$s2
+ mov 12(%rbp),$s3
+ jz .Lcbc_slow_enc_tail # short input...
+
+.align 4
+.Lcbc_slow_enc_loop:
+ xor 0($inp),$s0
+ xor 4($inp),$s1
+ xor 8($inp),$s2
+ xor 12($inp),$s3
+ mov $keyp,$key # restore key
+ mov $inp,$_inp # save inp
+ mov $out,$_out # save out
+ mov %r10,$_len # save len
+
+ call _x86_64_AES_encrypt_compact
+
+ mov $_inp,$inp # restore inp
+ mov $_out,$out # restore out
+ mov $_len,%r10 # restore len
+ mov $s0,0($out)
+ mov $s1,4($out)
+ mov $s2,8($out)
+ mov $s3,12($out)
+
+ lea 16($inp),$inp
+ lea 16($out),$out
+ sub \$16,%r10
+ test \$-16,%r10
+ jnz .Lcbc_slow_enc_loop
+ test \$15,%r10
+ jnz .Lcbc_slow_enc_tail
+ mov $_ivp,%rbp # restore ivp
+ mov $s0,0(%rbp) # save ivec
+ mov $s1,4(%rbp)
+ mov $s2,8(%rbp)
+ mov $s3,12(%rbp)
+
+ jmp .Lcbc_exit
+
+.align 4
+.Lcbc_slow_enc_tail:
+ mov %rax,%r11
+ mov %rcx,%r12
+ mov %r10,%rcx
+ mov $inp,%rsi
+ mov $out,%rdi
+ .long 0x9066A4F3 # rep movsb
+ mov \$16,%rcx # zero tail
+ sub %r10,%rcx
+ xor %rax,%rax
+ .long 0x9066AAF3 # rep stosb
+ mov $out,$inp # this is not a mistake!
+ mov \$16,%r10 # len=16
+ mov %r11,%rax
+ mov %r12,%rcx
+ jmp .Lcbc_slow_enc_loop # one more spin...
+#--------------------------- SLOW DECRYPT ---------------------------#
+.align 16
+.LSLOW_DECRYPT:
+ shr \$3,%rax
+ add %rax,$sbox # recall "magic" constants!
+
+ mov 0(%rbp),%r11 # copy iv to stack
+ mov 8(%rbp),%r12
+ mov %r11,0+$ivec
+ mov %r12,8+$ivec
+
+.align 4
+.Lcbc_slow_dec_loop:
+ mov 0($inp),$s0 # load input
+ mov 4($inp),$s1
+ mov 8($inp),$s2
+ mov 12($inp),$s3
+ mov $keyp,$key # restore key
+ mov $inp,$_inp # save inp
+ mov $out,$_out # save out
+ mov %r10,$_len # save len
+
+ call _x86_64_AES_decrypt_compact
+
+ mov $_inp,$inp # restore inp
+ mov $_out,$out # restore out
+ mov $_len,%r10
+ xor 0+$ivec,$s0
+ xor 4+$ivec,$s1
+ xor 8+$ivec,$s2
+ xor 12+$ivec,$s3
+
+ mov 0($inp),%r11 # load input
+ mov 8($inp),%r12
+ sub \$16,%r10
+ jc .Lcbc_slow_dec_partial
+ jz .Lcbc_slow_dec_done
+
+ mov %r11,0+$ivec # copy input to iv
+ mov %r12,8+$ivec
+
+ mov $s0,0($out) # save output [can zap input]
+ mov $s1,4($out)
+ mov $s2,8($out)
+ mov $s3,12($out)
+
+ lea 16($inp),$inp
+ lea 16($out),$out
+ jmp .Lcbc_slow_dec_loop
+.Lcbc_slow_dec_done:
+ mov $_ivp,%rdi
+ mov %r11,0(%rdi) # copy iv back to user
+ mov %r12,8(%rdi)
+
+ mov $s0,0($out) # save output [can zap input]
+ mov $s1,4($out)
+ mov $s2,8($out)
+ mov $s3,12($out)
+
+ jmp .Lcbc_exit
+
+.align 4
+.Lcbc_slow_dec_partial:
+ mov $_ivp,%rdi
+ mov %r11,0(%rdi) # copy iv back to user
+ mov %r12,8(%rdi)
+
+ mov $s0,0+$ivec # save output to stack
+ mov $s1,4+$ivec
+ mov $s2,8+$ivec
+ mov $s3,12+$ivec
+
+ mov $out,%rdi
+ lea $ivec,%rsi
+ lea 16(%r10),%rcx
+ .long 0x9066A4F3 # rep movsb
+ jmp .Lcbc_exit
+
+.align 16
+.Lcbc_exit:
+ mov $_rsp,%rsi
+ mov (%rsi),%r15
+ mov 8(%rsi),%r14
+ mov 16(%rsi),%r13
+ mov 24(%rsi),%r12
+ mov 32(%rsi),%rbp
+ mov 40(%rsi),%rbx
+ lea 48(%rsi),%rsp
+.Lcbc_popfq:
+ popfq
+.Lcbc_epilogue:
+ ret
+.size asm_AES_cbc_encrypt,.-asm_AES_cbc_encrypt
+___
+}
+
+$code.=<<___;
+.align 64
+.LAES_Te:
+___
+ &_data_word(0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6);
+ &_data_word(0x0df2f2ff, 0xbd6b6bd6, 0xb16f6fde, 0x54c5c591);
+ &_data_word(0x50303060, 0x03010102, 0xa96767ce, 0x7d2b2b56);
+ &_data_word(0x19fefee7, 0x62d7d7b5, 0xe6abab4d, 0x9a7676ec);
+ &_data_word(0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa);
+ &_data_word(0x15fafaef, 0xeb5959b2, 0xc947478e, 0x0bf0f0fb);
+ &_data_word(0xecadad41, 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45);
+ &_data_word(0xbf9c9c23, 0xf7a4a453, 0x967272e4, 0x5bc0c09b);
+ &_data_word(0xc2b7b775, 0x1cfdfde1, 0xae93933d, 0x6a26264c);
+ &_data_word(0x5a36366c, 0x413f3f7e, 0x02f7f7f5, 0x4fcccc83);
+ &_data_word(0x5c343468, 0xf4a5a551, 0x34e5e5d1, 0x08f1f1f9);
+ &_data_word(0x937171e2, 0x73d8d8ab, 0x53313162, 0x3f15152a);
+ &_data_word(0x0c040408, 0x52c7c795, 0x65232346, 0x5ec3c39d);
+ &_data_word(0x28181830, 0xa1969637, 0x0f05050a, 0xb59a9a2f);
+ &_data_word(0x0907070e, 0x36121224, 0x9b80801b, 0x3de2e2df);
+ &_data_word(0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea);
+ &_data_word(0x1b090912, 0x9e83831d, 0x742c2c58, 0x2e1a1a34);
+ &_data_word(0x2d1b1b36, 0xb26e6edc, 0xee5a5ab4, 0xfba0a05b);
+ &_data_word(0xf65252a4, 0x4d3b3b76, 0x61d6d6b7, 0xceb3b37d);
+ &_data_word(0x7b292952, 0x3ee3e3dd, 0x712f2f5e, 0x97848413);
+ &_data_word(0xf55353a6, 0x68d1d1b9, 0x00000000, 0x2cededc1);
+ &_data_word(0x60202040, 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6);
+ &_data_word(0xbe6a6ad4, 0x46cbcb8d, 0xd9bebe67, 0x4b393972);
+ &_data_word(0xde4a4a94, 0xd44c4c98, 0xe85858b0, 0x4acfcf85);
+ &_data_word(0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed);
+ &_data_word(0xc5434386, 0xd74d4d9a, 0x55333366, 0x94858511);
+ &_data_word(0xcf45458a, 0x10f9f9e9, 0x06020204, 0x817f7ffe);
+ &_data_word(0xf05050a0, 0x443c3c78, 0xba9f9f25, 0xe3a8a84b);
+ &_data_word(0xf35151a2, 0xfea3a35d, 0xc0404080, 0x8a8f8f05);
+ &_data_word(0xad92923f, 0xbc9d9d21, 0x48383870, 0x04f5f5f1);
+ &_data_word(0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142);
+ &_data_word(0x30101020, 0x1affffe5, 0x0ef3f3fd, 0x6dd2d2bf);
+ &_data_word(0x4ccdcd81, 0x140c0c18, 0x35131326, 0x2fececc3);
+ &_data_word(0xe15f5fbe, 0xa2979735, 0xcc444488, 0x3917172e);
+ &_data_word(0x57c4c493, 0xf2a7a755, 0x827e7efc, 0x473d3d7a);
+ &_data_word(0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6);
+ &_data_word(0xa06060c0, 0x98818119, 0xd14f4f9e, 0x7fdcdca3);
+ &_data_word(0x66222244, 0x7e2a2a54, 0xab90903b, 0x8388880b);
+ &_data_word(0xca46468c, 0x29eeeec7, 0xd3b8b86b, 0x3c141428);
+ &_data_word(0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad);
+ &_data_word(0x3be0e0db, 0x56323264, 0x4e3a3a74, 0x1e0a0a14);
+ &_data_word(0xdb494992, 0x0a06060c, 0x6c242448, 0xe45c5cb8);
+ &_data_word(0x5dc2c29f, 0x6ed3d3bd, 0xefacac43, 0xa66262c4);
+ &_data_word(0xa8919139, 0xa4959531, 0x37e4e4d3, 0x8b7979f2);
+ &_data_word(0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda);
+ &_data_word(0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949);
+ &_data_word(0xb46c6cd8, 0xfa5656ac, 0x07f4f4f3, 0x25eaeacf);
+ &_data_word(0xaf6565ca, 0x8e7a7af4, 0xe9aeae47, 0x18080810);
+ &_data_word(0xd5baba6f, 0x887878f0, 0x6f25254a, 0x722e2e5c);
+ &_data_word(0x241c1c38, 0xf1a6a657, 0xc7b4b473, 0x51c6c697);
+ &_data_word(0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e);
+ &_data_word(0xdd4b4b96, 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f);
+ &_data_word(0x907070e0, 0x423e3e7c, 0xc4b5b571, 0xaa6666cc);
+ &_data_word(0xd8484890, 0x05030306, 0x01f6f6f7, 0x120e0e1c);
+ &_data_word(0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969);
+ &_data_word(0x91868617, 0x58c1c199, 0x271d1d3a, 0xb99e9e27);
+ &_data_word(0x38e1e1d9, 0x13f8f8eb, 0xb398982b, 0x33111122);
+ &_data_word(0xbb6969d2, 0x70d9d9a9, 0x898e8e07, 0xa7949433);
+ &_data_word(0xb69b9b2d, 0x221e1e3c, 0x92878715, 0x20e9e9c9);
+ &_data_word(0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5);
+ &_data_word(0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a);
+ &_data_word(0xdabfbf65, 0x31e6e6d7, 0xc6424284, 0xb86868d0);
+ &_data_word(0xc3414182, 0xb0999929, 0x772d2d5a, 0x110f0f1e);
+ &_data_word(0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d, 0x3a16162c);
+
+#Te4 # four copies of Te4 to choose from to avoid L1 aliasing
+ &data_byte(0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5);
+ &data_byte(0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76);
+ &data_byte(0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0);
+ &data_byte(0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0);
+ &data_byte(0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc);
+ &data_byte(0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15);
+ &data_byte(0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a);
+ &data_byte(0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75);
+ &data_byte(0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0);
+ &data_byte(0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84);
+ &data_byte(0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b);
+ &data_byte(0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf);
+ &data_byte(0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85);
+ &data_byte(0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8);
+ &data_byte(0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5);
+ &data_byte(0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2);
+ &data_byte(0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17);
+ &data_byte(0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73);
+ &data_byte(0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88);
+ &data_byte(0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb);
+ &data_byte(0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c);
+ &data_byte(0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79);
+ &data_byte(0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9);
+ &data_byte(0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08);
+ &data_byte(0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6);
+ &data_byte(0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a);
+ &data_byte(0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e);
+ &data_byte(0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e);
+ &data_byte(0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94);
+ &data_byte(0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf);
+ &data_byte(0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68);
+ &data_byte(0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16);
+
+ &data_byte(0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5);
+ &data_byte(0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76);
+ &data_byte(0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0);
+ &data_byte(0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0);
+ &data_byte(0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc);
+ &data_byte(0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15);
+ &data_byte(0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a);
+ &data_byte(0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75);
+ &data_byte(0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0);
+ &data_byte(0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84);
+ &data_byte(0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b);
+ &data_byte(0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf);
+ &data_byte(0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85);
+ &data_byte(0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8);
+ &data_byte(0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5);
+ &data_byte(0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2);
+ &data_byte(0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17);
+ &data_byte(0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73);
+ &data_byte(0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88);
+ &data_byte(0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb);
+ &data_byte(0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c);
+ &data_byte(0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79);
+ &data_byte(0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9);
+ &data_byte(0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08);
+ &data_byte(0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6);
+ &data_byte(0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a);
+ &data_byte(0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e);
+ &data_byte(0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e);
+ &data_byte(0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94);
+ &data_byte(0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf);
+ &data_byte(0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68);
+ &data_byte(0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16);
+
+ &data_byte(0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5);
+ &data_byte(0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76);
+ &data_byte(0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0);
+ &data_byte(0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0);
+ &data_byte(0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc);
+ &data_byte(0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15);
+ &data_byte(0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a);
+ &data_byte(0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75);
+ &data_byte(0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0);
+ &data_byte(0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84);
+ &data_byte(0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b);
+ &data_byte(0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf);
+ &data_byte(0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85);
+ &data_byte(0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8);
+ &data_byte(0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5);
+ &data_byte(0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2);
+ &data_byte(0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17);
+ &data_byte(0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73);
+ &data_byte(0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88);
+ &data_byte(0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb);
+ &data_byte(0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c);
+ &data_byte(0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79);
+ &data_byte(0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9);
+ &data_byte(0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08);
+ &data_byte(0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6);
+ &data_byte(0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a);
+ &data_byte(0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e);
+ &data_byte(0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e);
+ &data_byte(0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94);
+ &data_byte(0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf);
+ &data_byte(0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68);
+ &data_byte(0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16);
+
+ &data_byte(0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5);
+ &data_byte(0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76);
+ &data_byte(0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0);
+ &data_byte(0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0);
+ &data_byte(0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc);
+ &data_byte(0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15);
+ &data_byte(0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a);
+ &data_byte(0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75);
+ &data_byte(0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0);
+ &data_byte(0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84);
+ &data_byte(0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b);
+ &data_byte(0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf);
+ &data_byte(0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85);
+ &data_byte(0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8);
+ &data_byte(0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5);
+ &data_byte(0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2);
+ &data_byte(0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17);
+ &data_byte(0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73);
+ &data_byte(0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88);
+ &data_byte(0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb);
+ &data_byte(0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c);
+ &data_byte(0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79);
+ &data_byte(0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9);
+ &data_byte(0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08);
+ &data_byte(0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6);
+ &data_byte(0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a);
+ &data_byte(0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e);
+ &data_byte(0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e);
+ &data_byte(0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94);
+ &data_byte(0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf);
+ &data_byte(0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68);
+ &data_byte(0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16);
+#rcon:
+$code.=<<___;
+ .long 0x00000001, 0x00000002, 0x00000004, 0x00000008
+ .long 0x00000010, 0x00000020, 0x00000040, 0x00000080
+ .long 0x0000001b, 0x00000036, 0x80808080, 0x80808080
+ .long 0xfefefefe, 0xfefefefe, 0x1b1b1b1b, 0x1b1b1b1b
+___
+$code.=<<___;
+.align 64
+.LAES_Td:
+___
+ &_data_word(0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a);
+ &_data_word(0xcb6bab3b, 0xf1459d1f, 0xab58faac, 0x9303e34b);
+ &_data_word(0x55fa3020, 0xf66d76ad, 0x9176cc88, 0x254c02f5);
+ &_data_word(0xfcd7e54f, 0xd7cb2ac5, 0x80443526, 0x8fa362b5);
+ &_data_word(0x495ab1de, 0x671bba25, 0x980eea45, 0xe1c0fe5d);
+ &_data_word(0x02752fc3, 0x12f04c81, 0xa397468d, 0xc6f9d36b);
+ &_data_word(0xe75f8f03, 0x959c9215, 0xeb7a6dbf, 0xda595295);
+ &_data_word(0x2d83bed4, 0xd3217458, 0x2969e049, 0x44c8c98e);
+ &_data_word(0x6a89c275, 0x78798ef4, 0x6b3e5899, 0xdd71b927);
+ &_data_word(0xb64fe1be, 0x17ad88f0, 0x66ac20c9, 0xb43ace7d);
+ &_data_word(0x184adf63, 0x82311ae5, 0x60335197, 0x457f5362);
+ &_data_word(0xe07764b1, 0x84ae6bbb, 0x1ca081fe, 0x942b08f9);
+ &_data_word(0x58684870, 0x19fd458f, 0x876cde94, 0xb7f87b52);
+ &_data_word(0x23d373ab, 0xe2024b72, 0x578f1fe3, 0x2aab5566);
+ &_data_word(0x0728ebb2, 0x03c2b52f, 0x9a7bc586, 0xa50837d3);
+ &_data_word(0xf2872830, 0xb2a5bf23, 0xba6a0302, 0x5c8216ed);
+ &_data_word(0x2b1ccf8a, 0x92b479a7, 0xf0f207f3, 0xa1e2694e);
+ &_data_word(0xcdf4da65, 0xd5be0506, 0x1f6234d1, 0x8afea6c4);
+ &_data_word(0x9d532e34, 0xa055f3a2, 0x32e18a05, 0x75ebf6a4);
+ &_data_word(0x39ec830b, 0xaaef6040, 0x069f715e, 0x51106ebd);
+ &_data_word(0xf98a213e, 0x3d06dd96, 0xae053edd, 0x46bde64d);
+ &_data_word(0xb58d5491, 0x055dc471, 0x6fd40604, 0xff155060);
+ &_data_word(0x24fb9819, 0x97e9bdd6, 0xcc434089, 0x779ed967);
+ &_data_word(0xbd42e8b0, 0x888b8907, 0x385b19e7, 0xdbeec879);
+ &_data_word(0x470a7ca1, 0xe90f427c, 0xc91e84f8, 0x00000000);
+ &_data_word(0x83868009, 0x48ed2b32, 0xac70111e, 0x4e725a6c);
+ &_data_word(0xfbff0efd, 0x5638850f, 0x1ed5ae3d, 0x27392d36);
+ &_data_word(0x64d90f0a, 0x21a65c68, 0xd1545b9b, 0x3a2e3624);
+ &_data_word(0xb1670a0c, 0x0fe75793, 0xd296eeb4, 0x9e919b1b);
+ &_data_word(0x4fc5c080, 0xa220dc61, 0x694b775a, 0x161a121c);
+ &_data_word(0x0aba93e2, 0xe52aa0c0, 0x43e0223c, 0x1d171b12);
+ &_data_word(0x0b0d090e, 0xadc78bf2, 0xb9a8b62d, 0xc8a91e14);
+ &_data_word(0x8519f157, 0x4c0775af, 0xbbdd99ee, 0xfd607fa3);
+ &_data_word(0x9f2601f7, 0xbcf5725c, 0xc53b6644, 0x347efb5b);
+ &_data_word(0x7629438b, 0xdcc623cb, 0x68fcedb6, 0x63f1e4b8);
+ &_data_word(0xcadc31d7, 0x10856342, 0x40229713, 0x2011c684);
+ &_data_word(0x7d244a85, 0xf83dbbd2, 0x1132f9ae, 0x6da129c7);
+ &_data_word(0x4b2f9e1d, 0xf330b2dc, 0xec52860d, 0xd0e3c177);
+ &_data_word(0x6c16b32b, 0x99b970a9, 0xfa489411, 0x2264e947);
+ &_data_word(0xc48cfca8, 0x1a3ff0a0, 0xd82c7d56, 0xef903322);
+ &_data_word(0xc74e4987, 0xc1d138d9, 0xfea2ca8c, 0x360bd498);
+ &_data_word(0xcf81f5a6, 0x28de7aa5, 0x268eb7da, 0xa4bfad3f);
+ &_data_word(0xe49d3a2c, 0x0d927850, 0x9bcc5f6a, 0x62467e54);
+ &_data_word(0xc2138df6, 0xe8b8d890, 0x5ef7392e, 0xf5afc382);
+ &_data_word(0xbe805d9f, 0x7c93d069, 0xa92dd56f, 0xb31225cf);
+ &_data_word(0x3b99acc8, 0xa77d1810, 0x6e639ce8, 0x7bbb3bdb);
+ &_data_word(0x097826cd, 0xf418596e, 0x01b79aec, 0xa89a4f83);
+ &_data_word(0x656e95e6, 0x7ee6ffaa, 0x08cfbc21, 0xe6e815ef);
+ &_data_word(0xd99be7ba, 0xce366f4a, 0xd4099fea, 0xd67cb029);
+ &_data_word(0xafb2a431, 0x31233f2a, 0x3094a5c6, 0xc066a235);
+ &_data_word(0x37bc4e74, 0xa6ca82fc, 0xb0d090e0, 0x15d8a733);
+ &_data_word(0x4a9804f1, 0xf7daec41, 0x0e50cd7f, 0x2ff69117);
+ &_data_word(0x8dd64d76, 0x4db0ef43, 0x544daacc, 0xdf0496e4);
+ &_data_word(0xe3b5d19e, 0x1b886a4c, 0xb81f2cc1, 0x7f516546);
+ &_data_word(0x04ea5e9d, 0x5d358c01, 0x737487fa, 0x2e410bfb);
+ &_data_word(0x5a1d67b3, 0x52d2db92, 0x335610e9, 0x1347d66d);
+ &_data_word(0x8c61d79a, 0x7a0ca137, 0x8e14f859, 0x893c13eb);
+ &_data_word(0xee27a9ce, 0x35c961b7, 0xede51ce1, 0x3cb1477a);
+ &_data_word(0x59dfd29c, 0x3f73f255, 0x79ce1418, 0xbf37c773);
+ &_data_word(0xeacdf753, 0x5baafd5f, 0x146f3ddf, 0x86db4478);
+ &_data_word(0x81f3afca, 0x3ec468b9, 0x2c342438, 0x5f40a3c2);
+ &_data_word(0x72c31d16, 0x0c25e2bc, 0x8b493c28, 0x41950dff);
+ &_data_word(0x7101a839, 0xdeb30c08, 0x9ce4b4d8, 0x90c15664);
+ &_data_word(0x6184cb7b, 0x70b632d5, 0x745c6c48, 0x4257b8d0);
+
+#Td4: # four copies of Td4 to choose from to avoid L1 aliasing
+ &data_byte(0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38);
+ &data_byte(0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb);
+ &data_byte(0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87);
+ &data_byte(0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb);
+ &data_byte(0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d);
+ &data_byte(0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e);
+ &data_byte(0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2);
+ &data_byte(0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25);
+ &data_byte(0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16);
+ &data_byte(0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92);
+ &data_byte(0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda);
+ &data_byte(0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84);
+ &data_byte(0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a);
+ &data_byte(0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06);
+ &data_byte(0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02);
+ &data_byte(0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b);
+ &data_byte(0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea);
+ &data_byte(0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73);
+ &data_byte(0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85);
+ &data_byte(0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e);
+ &data_byte(0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89);
+ &data_byte(0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b);
+ &data_byte(0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20);
+ &data_byte(0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4);
+ &data_byte(0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31);
+ &data_byte(0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f);
+ &data_byte(0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d);
+ &data_byte(0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef);
+ &data_byte(0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0);
+ &data_byte(0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61);
+ &data_byte(0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26);
+ &data_byte(0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d);
+$code.=<<___;
+ .long 0x80808080, 0x80808080, 0xfefefefe, 0xfefefefe
+ .long 0x1b1b1b1b, 0x1b1b1b1b, 0, 0
+___
+ &data_byte(0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38);
+ &data_byte(0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb);
+ &data_byte(0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87);
+ &data_byte(0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb);
+ &data_byte(0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d);
+ &data_byte(0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e);
+ &data_byte(0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2);
+ &data_byte(0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25);
+ &data_byte(0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16);
+ &data_byte(0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92);
+ &data_byte(0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda);
+ &data_byte(0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84);
+ &data_byte(0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a);
+ &data_byte(0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06);
+ &data_byte(0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02);
+ &data_byte(0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b);
+ &data_byte(0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea);
+ &data_byte(0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73);
+ &data_byte(0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85);
+ &data_byte(0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e);
+ &data_byte(0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89);
+ &data_byte(0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b);
+ &data_byte(0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20);
+ &data_byte(0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4);
+ &data_byte(0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31);
+ &data_byte(0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f);
+ &data_byte(0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d);
+ &data_byte(0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef);
+ &data_byte(0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0);
+ &data_byte(0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61);
+ &data_byte(0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26);
+ &data_byte(0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d);
+$code.=<<___;
+ .long 0x80808080, 0x80808080, 0xfefefefe, 0xfefefefe
+ .long 0x1b1b1b1b, 0x1b1b1b1b, 0, 0
+___
+ &data_byte(0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38);
+ &data_byte(0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb);
+ &data_byte(0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87);
+ &data_byte(0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb);
+ &data_byte(0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d);
+ &data_byte(0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e);
+ &data_byte(0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2);
+ &data_byte(0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25);
+ &data_byte(0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16);
+ &data_byte(0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92);
+ &data_byte(0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda);
+ &data_byte(0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84);
+ &data_byte(0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a);
+ &data_byte(0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06);
+ &data_byte(0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02);
+ &data_byte(0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b);
+ &data_byte(0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea);
+ &data_byte(0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73);
+ &data_byte(0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85);
+ &data_byte(0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e);
+ &data_byte(0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89);
+ &data_byte(0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b);
+ &data_byte(0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20);
+ &data_byte(0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4);
+ &data_byte(0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31);
+ &data_byte(0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f);
+ &data_byte(0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d);
+ &data_byte(0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef);
+ &data_byte(0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0);
+ &data_byte(0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61);
+ &data_byte(0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26);
+ &data_byte(0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d);
+$code.=<<___;
+ .long 0x80808080, 0x80808080, 0xfefefefe, 0xfefefefe
+ .long 0x1b1b1b1b, 0x1b1b1b1b, 0, 0
+___
+ &data_byte(0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38);
+ &data_byte(0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb);
+ &data_byte(0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87);
+ &data_byte(0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb);
+ &data_byte(0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d);
+ &data_byte(0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e);
+ &data_byte(0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2);
+ &data_byte(0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25);
+ &data_byte(0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16);
+ &data_byte(0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92);
+ &data_byte(0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda);
+ &data_byte(0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84);
+ &data_byte(0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a);
+ &data_byte(0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06);
+ &data_byte(0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02);
+ &data_byte(0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b);
+ &data_byte(0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea);
+ &data_byte(0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73);
+ &data_byte(0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85);
+ &data_byte(0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e);
+ &data_byte(0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89);
+ &data_byte(0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b);
+ &data_byte(0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20);
+ &data_byte(0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4);
+ &data_byte(0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31);
+ &data_byte(0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f);
+ &data_byte(0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d);
+ &data_byte(0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef);
+ &data_byte(0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0);
+ &data_byte(0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61);
+ &data_byte(0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26);
+ &data_byte(0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d);
+$code.=<<___;
+ .long 0x80808080, 0x80808080, 0xfefefefe, 0xfefefefe
+ .long 0x1b1b1b1b, 0x1b1b1b1b, 0, 0
+.asciz "AES for x86_64, CRYPTOGAMS by <appro\@openssl.org>"
+.align 64
+___
+
+# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame,
+# CONTEXT *context,DISPATCHER_CONTEXT *disp)
+if ($win64) {
+$rec="%rcx";
+$frame="%rdx";
+$context="%r8";
+$disp="%r9";
+
+$code.=<<___;
+.extern __imp_RtlVirtualUnwind
+.type block_se_handler,\@abi-omnipotent
+.align 16
+block_se_handler:
+ push %rsi
+ push %rdi
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+ pushfq
+ sub \$64,%rsp
+
+ mov 120($context),%rax # pull context->Rax
+ mov 248($context),%rbx # pull context->Rip
+
+ mov 8($disp),%rsi # disp->ImageBase
+ mov 56($disp),%r11 # disp->HandlerData
+
+ mov 0(%r11),%r10d # HandlerData[0]
+ lea (%rsi,%r10),%r10 # prologue label
+ cmp %r10,%rbx # context->Rip<prologue label
+ jb .Lin_block_prologue
+
+ mov 152($context),%rax # pull context->Rsp
+
+ mov 4(%r11),%r10d # HandlerData[1]
+ lea (%rsi,%r10),%r10 # epilogue label
+ cmp %r10,%rbx # context->Rip>=epilogue label
+ jae .Lin_block_prologue
+
+ mov 24(%rax),%rax # pull saved real stack pointer
+ lea 48(%rax),%rax # adjust...
+
+ mov -8(%rax),%rbx
+ mov -16(%rax),%rbp
+ mov -24(%rax),%r12
+ mov -32(%rax),%r13
+ mov -40(%rax),%r14
+ mov -48(%rax),%r15
+ mov %rbx,144($context) # restore context->Rbx
+ mov %rbp,160($context) # restore context->Rbp
+ mov %r12,216($context) # restore context->R12
+ mov %r13,224($context) # restore context->R13
+ mov %r14,232($context) # restore context->R14
+ mov %r15,240($context) # restore context->R15
+
+.Lin_block_prologue:
+ mov 8(%rax),%rdi
+ mov 16(%rax),%rsi
+ mov %rax,152($context) # restore context->Rsp
+ mov %rsi,168($context) # restore context->Rsi
+ mov %rdi,176($context) # restore context->Rdi
+
+ jmp .Lcommon_seh_exit
+.size block_se_handler,.-block_se_handler
+
+.type key_se_handler,\@abi-omnipotent
+.align 16
+key_se_handler:
+ push %rsi
+ push %rdi
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+ pushfq
+ sub \$64,%rsp
+
+ mov 120($context),%rax # pull context->Rax
+ mov 248($context),%rbx # pull context->Rip
+
+ mov 8($disp),%rsi # disp->ImageBase
+ mov 56($disp),%r11 # disp->HandlerData
+
+ mov 0(%r11),%r10d # HandlerData[0]
+ lea (%rsi,%r10),%r10 # prologue label
+ cmp %r10,%rbx # context->Rip<prologue label
+ jb .Lin_key_prologue
+
+ mov 152($context),%rax # pull context->Rsp
+
+ mov 4(%r11),%r10d # HandlerData[1]
+ lea (%rsi,%r10),%r10 # epilogue label
+ cmp %r10,%rbx # context->Rip>=epilogue label
+ jae .Lin_key_prologue
+
+ lea 56(%rax),%rax
+
+ mov -8(%rax),%rbx
+ mov -16(%rax),%rbp
+ mov -24(%rax),%r12
+ mov -32(%rax),%r13
+ mov -40(%rax),%r14
+ mov -48(%rax),%r15
+ mov %rbx,144($context) # restore context->Rbx
+ mov %rbp,160($context) # restore context->Rbp
+ mov %r12,216($context) # restore context->R12
+ mov %r13,224($context) # restore context->R13
+ mov %r14,232($context) # restore context->R14
+ mov %r15,240($context) # restore context->R15
+
+.Lin_key_prologue:
+ mov 8(%rax),%rdi
+ mov 16(%rax),%rsi
+ mov %rax,152($context) # restore context->Rsp
+ mov %rsi,168($context) # restore context->Rsi
+ mov %rdi,176($context) # restore context->Rdi
+
+ jmp .Lcommon_seh_exit
+.size key_se_handler,.-key_se_handler
+
+.type cbc_se_handler,\@abi-omnipotent
+.align 16
+cbc_se_handler:
+ push %rsi
+ push %rdi
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+ pushfq
+ sub \$64,%rsp
+
+ mov 120($context),%rax # pull context->Rax
+ mov 248($context),%rbx # pull context->Rip
+
+ lea .Lcbc_prologue(%rip),%r10
+ cmp %r10,%rbx # context->Rip<.Lcbc_prologue
+ jb .Lin_cbc_prologue
+
+ lea .Lcbc_fast_body(%rip),%r10
+ cmp %r10,%rbx # context->Rip<.Lcbc_fast_body
+ jb .Lin_cbc_frame_setup
+
+ lea .Lcbc_slow_prologue(%rip),%r10
+ cmp %r10,%rbx # context->Rip<.Lcbc_slow_prologue
+ jb .Lin_cbc_body
+
+ lea .Lcbc_slow_body(%rip),%r10
+ cmp %r10,%rbx # context->Rip<.Lcbc_slow_body
+ jb .Lin_cbc_frame_setup
+
+.Lin_cbc_body:
+ mov 152($context),%rax # pull context->Rsp
+
+ lea .Lcbc_epilogue(%rip),%r10
+ cmp %r10,%rbx # context->Rip>=.Lcbc_epilogue
+ jae .Lin_cbc_prologue
+
+ lea 8(%rax),%rax
+
+ lea .Lcbc_popfq(%rip),%r10
+ cmp %r10,%rbx # context->Rip>=.Lcbc_popfq
+ jae .Lin_cbc_prologue
+
+ mov `16-8`(%rax),%rax # biased $_rsp
+ lea 56(%rax),%rax
+
+.Lin_cbc_frame_setup:
+ mov -16(%rax),%rbx
+ mov -24(%rax),%rbp
+ mov -32(%rax),%r12
+ mov -40(%rax),%r13
+ mov -48(%rax),%r14
+ mov -56(%rax),%r15
+ mov %rbx,144($context) # restore context->Rbx
+ mov %rbp,160($context) # restore context->Rbp
+ mov %r12,216($context) # restore context->R12
+ mov %r13,224($context) # restore context->R13
+ mov %r14,232($context) # restore context->R14
+ mov %r15,240($context) # restore context->R15
+
+.Lin_cbc_prologue:
+ mov 8(%rax),%rdi
+ mov 16(%rax),%rsi
+ mov %rax,152($context) # restore context->Rsp
+ mov %rsi,168($context) # restore context->Rsi
+ mov %rdi,176($context) # restore context->Rdi
+
+.Lcommon_seh_exit:
+
+ mov 40($disp),%rdi # disp->ContextRecord
+ mov $context,%rsi # context
+ mov \$`1232/8`,%ecx # sizeof(CONTEXT)
+ .long 0xa548f3fc # cld; rep movsq
+
+ mov $disp,%rsi
+ xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER
+ mov 8(%rsi),%rdx # arg2, disp->ImageBase
+ mov 0(%rsi),%r8 # arg3, disp->ControlPc
+ mov 16(%rsi),%r9 # arg4, disp->FunctionEntry
+ mov 40(%rsi),%r10 # disp->ContextRecord
+ lea 56(%rsi),%r11 # &disp->HandlerData
+ lea 24(%rsi),%r12 # &disp->EstablisherFrame
+ mov %r10,32(%rsp) # arg5
+ mov %r11,40(%rsp) # arg6
+ mov %r12,48(%rsp) # arg7
+ mov %rcx,56(%rsp) # arg8, (NULL)
+ call *__imp_RtlVirtualUnwind(%rip)
+
+ mov \$1,%eax # ExceptionContinueSearch
+ add \$64,%rsp
+ popfq
+ pop %r15
+ pop %r14
+ pop %r13
+ pop %r12
+ pop %rbp
+ pop %rbx
+ pop %rdi
+ pop %rsi
+ ret
+.size cbc_se_handler,.-cbc_se_handler
+
+.section .pdata
+.align 4
+ .rva .LSEH_begin_asm_AES_encrypt
+ .rva .LSEH_end_asm_AES_encrypt
+ .rva .LSEH_info_asm_AES_encrypt
+
+ .rva .LSEH_begin_asm_AES_decrypt
+ .rva .LSEH_end_asm_AES_decrypt
+ .rva .LSEH_info_asm_AES_decrypt
+
+ .rva .LSEH_begin_asm_AES_set_encrypt_key
+ .rva .LSEH_end_asm_AES_set_encrypt_key
+ .rva .LSEH_info_asm_AES_set_encrypt_key
+
+ .rva .LSEH_begin_asm_AES_set_decrypt_key
+ .rva .LSEH_end_asm_AES_set_decrypt_key
+ .rva .LSEH_info_asm_AES_set_decrypt_key
+
+ .rva .LSEH_begin_asm_AES_cbc_encrypt
+ .rva .LSEH_end_asm_AES_cbc_encrypt
+ .rva .LSEH_info_asm_AES_cbc_encrypt
+
+.section .xdata
+.align 8
+.LSEH_info_asm_AES_encrypt:
+ .byte 9,0,0,0
+ .rva block_se_handler
+ .rva .Lenc_prologue,.Lenc_epilogue # HandlerData[]
+.LSEH_info_asm_AES_decrypt:
+ .byte 9,0,0,0
+ .rva block_se_handler
+ .rva .Ldec_prologue,.Ldec_epilogue # HandlerData[]
+.LSEH_info_asm_AES_set_encrypt_key:
+ .byte 9,0,0,0
+ .rva key_se_handler
+ .rva .Lenc_key_prologue,.Lenc_key_epilogue # HandlerData[]
+.LSEH_info_asm_AES_set_decrypt_key:
+ .byte 9,0,0,0
+ .rva key_se_handler
+ .rva .Ldec_key_prologue,.Ldec_key_epilogue # HandlerData[]
+.LSEH_info_asm_AES_cbc_encrypt:
+ .byte 9,0,0,0
+ .rva cbc_se_handler
+___
+}
+
+$code =~ s/\`([^\`]*)\`/eval($1)/gem;
+
+print $code;
+
+close STDOUT;
diff --git a/src/crypto/aes/asm/aesni-x86.pl b/src/crypto/aes/asm/aesni-x86.pl
new file mode 100644
index 0000000..3deb86a
--- /dev/null
+++ b/src/crypto/aes/asm/aesni-x86.pl
@@ -0,0 +1,2232 @@
+#!/usr/bin/env perl
+
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+# project. The module is, however, dual licensed under OpenSSL and
+# CRYPTOGAMS licenses depending on where you obtain it. For further
+# details see http://www.openssl.org/~appro/cryptogams/.
+# ====================================================================
+#
+# This module implements support for Intel AES-NI extension. In
+# OpenSSL context it's used with Intel engine, but can also be used as
+# drop-in replacement for crypto/aes/asm/aes-586.pl [see below for
+# details].
+#
+# Performance.
+#
+# To start with see corresponding paragraph in aesni-x86_64.pl...
+# Instead of filling table similar to one found there I've chosen to
+# summarize *comparison* results for raw ECB, CTR and CBC benchmarks.
+# The simplified table below represents 32-bit performance relative
+# to 64-bit one in every given point. Ratios vary for different
+# encryption modes, therefore interval values.
+#
+# 16-byte 64-byte 256-byte 1-KB 8-KB
+# 53-67% 67-84% 91-94% 95-98% 97-99.5%
+#
+# Lower ratios for smaller block sizes are perfectly understandable,
+# because function call overhead is higher in 32-bit mode. Largest
+# 8-KB block performance is virtually same: 32-bit code is less than
+# 1% slower for ECB, CBC and CCM, and ~3% slower otherwise.
+
+# January 2011
+#
+# See aesni-x86_64.pl for details. Unlike x86_64 version this module
+# interleaves at most 6 aes[enc|dec] instructions, because there are
+# not enough registers for 8x interleave [which should be optimal for
+# Sandy Bridge]. Actually, performance results for 6x interleave
+# factor presented in aesni-x86_64.pl (except for CTR) are for this
+# module.
+
+# April 2011
+#
+# Add aesni_xts_[en|de]crypt. Westmere spends 1.50 cycles processing
+# one byte out of 8KB with 128-bit key, Sandy Bridge - 1.09.
+
+######################################################################
+# Current large-block performance in cycles per byte processed with
+# 128-bit key (less is better).
+#
+# CBC en-/decrypt CTR XTS ECB
+# Westmere 3.77/1.37 1.37 1.52 1.27
+# * Bridge 5.07/0.98 0.99 1.09 0.91
+# Haswell 4.44/0.80 0.97 1.03 0.72
+# Atom 5.77/3.56 3.67 4.03 3.46
+# Bulldozer 5.80/0.98 1.05 1.24 0.93
+
+$PREFIX="aesni"; # if $PREFIX is set to "AES", the script
+ # generates drop-in replacement for
+ # crypto/aes/asm/aes-586.pl:-)
+$inline=1; # inline _aesni_[en|de]crypt
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+push(@INC,"${dir}","${dir}../../perlasm");
+require "x86asm.pl";
+
+&asm_init($ARGV[0],$0);
+
+if ($PREFIX eq "aesni") { $movekey=\&movups; }
+else { $movekey=\&movups; }
+
+$len="eax";
+$rounds="ecx";
+$key="edx";
+$inp="esi";
+$out="edi";
+$rounds_="ebx"; # backup copy for $rounds
+$key_="ebp"; # backup copy for $key
+
+$rndkey0="xmm0";
+$rndkey1="xmm1";
+$inout0="xmm2";
+$inout1="xmm3";
+$inout2="xmm4";
+$inout3="xmm5"; $in1="xmm5";
+$inout4="xmm6"; $in0="xmm6";
+$inout5="xmm7"; $ivec="xmm7";
+
+# AESNI extenstion
+sub aeskeygenassist
+{ my($dst,$src,$imm)=@_;
+ if ("$dst:$src" =~ /xmm([0-7]):xmm([0-7])/)
+ { &data_byte(0x66,0x0f,0x3a,0xdf,0xc0|($1<<3)|$2,$imm); }
+}
+sub aescommon
+{ my($opcodelet,$dst,$src)=@_;
+ if ("$dst:$src" =~ /xmm([0-7]):xmm([0-7])/)
+ { &data_byte(0x66,0x0f,0x38,$opcodelet,0xc0|($1<<3)|$2);}
+}
+sub aesimc { aescommon(0xdb,@_); }
+sub aesenc { aescommon(0xdc,@_); }
+sub aesenclast { aescommon(0xdd,@_); }
+sub aesdec { aescommon(0xde,@_); }
+sub aesdeclast { aescommon(0xdf,@_); }
+
+# Inline version of internal aesni_[en|de]crypt1
+{ my $sn;
+sub aesni_inline_generate1
+{ my ($p,$inout,$ivec)=@_; $inout=$inout0 if (!defined($inout));
+ $sn++;
+
+ &$movekey ($rndkey0,&QWP(0,$key));
+ &$movekey ($rndkey1,&QWP(16,$key));
+ &xorps ($ivec,$rndkey0) if (defined($ivec));
+ &lea ($key,&DWP(32,$key));
+ &xorps ($inout,$ivec) if (defined($ivec));
+ &xorps ($inout,$rndkey0) if (!defined($ivec));
+ &set_label("${p}1_loop_$sn");
+ eval"&aes${p} ($inout,$rndkey1)";
+ &dec ($rounds);
+ &$movekey ($rndkey1,&QWP(0,$key));
+ &lea ($key,&DWP(16,$key));
+ &jnz (&label("${p}1_loop_$sn"));
+ eval"&aes${p}last ($inout,$rndkey1)";
+}}
+
+sub aesni_generate1 # fully unrolled loop
+{ my ($p,$inout)=@_; $inout=$inout0 if (!defined($inout));
+
+ &function_begin_B("_aesni_${p}rypt1");
+ &movups ($rndkey0,&QWP(0,$key));
+ &$movekey ($rndkey1,&QWP(0x10,$key));
+ &xorps ($inout,$rndkey0);
+ &$movekey ($rndkey0,&QWP(0x20,$key));
+ &lea ($key,&DWP(0x30,$key));
+ &cmp ($rounds,11);
+ &jb (&label("${p}128"));
+ &lea ($key,&DWP(0x20,$key));
+ &je (&label("${p}192"));
+ &lea ($key,&DWP(0x20,$key));
+ eval"&aes${p} ($inout,$rndkey1)";
+ &$movekey ($rndkey1,&QWP(-0x40,$key));
+ eval"&aes${p} ($inout,$rndkey0)";
+ &$movekey ($rndkey0,&QWP(-0x30,$key));
+ &set_label("${p}192");
+ eval"&aes${p} ($inout,$rndkey1)";
+ &$movekey ($rndkey1,&QWP(-0x20,$key));
+ eval"&aes${p} ($inout,$rndkey0)";
+ &$movekey ($rndkey0,&QWP(-0x10,$key));
+ &set_label("${p}128");
+ eval"&aes${p} ($inout,$rndkey1)";
+ &$movekey ($rndkey1,&QWP(0,$key));
+ eval"&aes${p} ($inout,$rndkey0)";
+ &$movekey ($rndkey0,&QWP(0x10,$key));
+ eval"&aes${p} ($inout,$rndkey1)";
+ &$movekey ($rndkey1,&QWP(0x20,$key));
+ eval"&aes${p} ($inout,$rndkey0)";
+ &$movekey ($rndkey0,&QWP(0x30,$key));
+ eval"&aes${p} ($inout,$rndkey1)";
+ &$movekey ($rndkey1,&QWP(0x40,$key));
+ eval"&aes${p} ($inout,$rndkey0)";
+ &$movekey ($rndkey0,&QWP(0x50,$key));
+ eval"&aes${p} ($inout,$rndkey1)";
+ &$movekey ($rndkey1,&QWP(0x60,$key));
+ eval"&aes${p} ($inout,$rndkey0)";
+ &$movekey ($rndkey0,&QWP(0x70,$key));
+ eval"&aes${p} ($inout,$rndkey1)";
+ eval"&aes${p}last ($inout,$rndkey0)";
+ &ret();
+ &function_end_B("_aesni_${p}rypt1");
+}
+
+# void $PREFIX_encrypt (const void *inp,void *out,const AES_KEY *key);
+&aesni_generate1("enc") if (!$inline);
+&function_begin_B("${PREFIX}_encrypt");
+ &mov ("eax",&wparam(0));
+ &mov ($key,&wparam(2));
+ &movups ($inout0,&QWP(0,"eax"));
+ &mov ($rounds,&DWP(240,$key));
+ &mov ("eax",&wparam(1));
+ if ($inline)
+ { &aesni_inline_generate1("enc"); }
+ else
+ { &call ("_aesni_encrypt1"); }
+ &movups (&QWP(0,"eax"),$inout0);
+ &ret ();
+&function_end_B("${PREFIX}_encrypt");
+
+# void $PREFIX_decrypt (const void *inp,void *out,const AES_KEY *key);
+&aesni_generate1("dec") if(!$inline);
+&function_begin_B("${PREFIX}_decrypt");
+ &mov ("eax",&wparam(0));
+ &mov ($key,&wparam(2));
+ &movups ($inout0,&QWP(0,"eax"));
+ &mov ($rounds,&DWP(240,$key));
+ &mov ("eax",&wparam(1));
+ if ($inline)
+ { &aesni_inline_generate1("dec"); }
+ else
+ { &call ("_aesni_decrypt1"); }
+ &movups (&QWP(0,"eax"),$inout0);
+ &ret ();
+&function_end_B("${PREFIX}_decrypt");
+
+# _aesni_[en|de]cryptN are private interfaces, N denotes interleave
+# factor. Why 3x subroutine were originally used in loops? Even though
+# aes[enc|dec] latency was originally 6, it could be scheduled only
+# every *2nd* cycle. Thus 3x interleave was the one providing optimal
+# utilization, i.e. when subroutine's throughput is virtually same as
+# of non-interleaved subroutine [for number of input blocks up to 3].
+# This is why it originally made no sense to implement 2x subroutine.
+# But times change and it became appropriate to spend extra 192 bytes
+# on 2x subroutine on Atom Silvermont account. For processors that
+# can schedule aes[enc|dec] every cycle optimal interleave factor
+# equals to corresponding instructions latency. 8x is optimal for
+# * Bridge, but it's unfeasible to accommodate such implementation
+# in XMM registers addreassable in 32-bit mode and therefore maximum
+# of 6x is used instead...
+
+sub aesni_generate2
+{ my $p=shift;
+
+ &function_begin_B("_aesni_${p}rypt2");
+ &$movekey ($rndkey0,&QWP(0,$key));
+ &shl ($rounds,4);
+ &$movekey ($rndkey1,&QWP(16,$key));
+ &xorps ($inout0,$rndkey0);
+ &pxor ($inout1,$rndkey0);
+ &$movekey ($rndkey0,&QWP(32,$key));
+ &lea ($key,&DWP(32,$key,$rounds));
+ &neg ($rounds);
+ &add ($rounds,16);
+
+ &set_label("${p}2_loop");
+ eval"&aes${p} ($inout0,$rndkey1)";
+ eval"&aes${p} ($inout1,$rndkey1)";
+ &$movekey ($rndkey1,&QWP(0,$key,$rounds));
+ &add ($rounds,32);
+ eval"&aes${p} ($inout0,$rndkey0)";
+ eval"&aes${p} ($inout1,$rndkey0)";
+ &$movekey ($rndkey0,&QWP(-16,$key,$rounds));
+ &jnz (&label("${p}2_loop"));
+ eval"&aes${p} ($inout0,$rndkey1)";
+ eval"&aes${p} ($inout1,$rndkey1)";
+ eval"&aes${p}last ($inout0,$rndkey0)";
+ eval"&aes${p}last ($inout1,$rndkey0)";
+ &ret();
+ &function_end_B("_aesni_${p}rypt2");
+}
+
+sub aesni_generate3
+{ my $p=shift;
+
+ &function_begin_B("_aesni_${p}rypt3");
+ &$movekey ($rndkey0,&QWP(0,$key));
+ &shl ($rounds,4);
+ &$movekey ($rndkey1,&QWP(16,$key));
+ &xorps ($inout0,$rndkey0);
+ &pxor ($inout1,$rndkey0);
+ &pxor ($inout2,$rndkey0);
+ &$movekey ($rndkey0,&QWP(32,$key));
+ &lea ($key,&DWP(32,$key,$rounds));
+ &neg ($rounds);
+ &add ($rounds,16);
+
+ &set_label("${p}3_loop");
+ eval"&aes${p} ($inout0,$rndkey1)";
+ eval"&aes${p} ($inout1,$rndkey1)";
+ eval"&aes${p} ($inout2,$rndkey1)";
+ &$movekey ($rndkey1,&QWP(0,$key,$rounds));
+ &add ($rounds,32);
+ eval"&aes${p} ($inout0,$rndkey0)";
+ eval"&aes${p} ($inout1,$rndkey0)";
+ eval"&aes${p} ($inout2,$rndkey0)";
+ &$movekey ($rndkey0,&QWP(-16,$key,$rounds));
+ &jnz (&label("${p}3_loop"));
+ eval"&aes${p} ($inout0,$rndkey1)";
+ eval"&aes${p} ($inout1,$rndkey1)";
+ eval"&aes${p} ($inout2,$rndkey1)";
+ eval"&aes${p}last ($inout0,$rndkey0)";
+ eval"&aes${p}last ($inout1,$rndkey0)";
+ eval"&aes${p}last ($inout2,$rndkey0)";
+ &ret();
+ &function_end_B("_aesni_${p}rypt3");
+}
+
+# 4x interleave is implemented to improve small block performance,
+# most notably [and naturally] 4 block by ~30%. One can argue that one
+# should have implemented 5x as well, but improvement would be <20%,
+# so it's not worth it...
+sub aesni_generate4
+{ my $p=shift;
+
+ &function_begin_B("_aesni_${p}rypt4");
+ &$movekey ($rndkey0,&QWP(0,$key));
+ &$movekey ($rndkey1,&QWP(16,$key));
+ &shl ($rounds,4);
+ &xorps ($inout0,$rndkey0);
+ &pxor ($inout1,$rndkey0);
+ &pxor ($inout2,$rndkey0);
+ &pxor ($inout3,$rndkey0);
+ &$movekey ($rndkey0,&QWP(32,$key));
+ &lea ($key,&DWP(32,$key,$rounds));
+ &neg ($rounds);
+ &data_byte (0x0f,0x1f,0x40,0x00);
+ &add ($rounds,16);
+
+ &set_label("${p}4_loop");
+ eval"&aes${p} ($inout0,$rndkey1)";
+ eval"&aes${p} ($inout1,$rndkey1)";
+ eval"&aes${p} ($inout2,$rndkey1)";
+ eval"&aes${p} ($inout3,$rndkey1)";
+ &$movekey ($rndkey1,&QWP(0,$key,$rounds));
+ &add ($rounds,32);
+ eval"&aes${p} ($inout0,$rndkey0)";
+ eval"&aes${p} ($inout1,$rndkey0)";
+ eval"&aes${p} ($inout2,$rndkey0)";
+ eval"&aes${p} ($inout3,$rndkey0)";
+ &$movekey ($rndkey0,&QWP(-16,$key,$rounds));
+ &jnz (&label("${p}4_loop"));
+
+ eval"&aes${p} ($inout0,$rndkey1)";
+ eval"&aes${p} ($inout1,$rndkey1)";
+ eval"&aes${p} ($inout2,$rndkey1)";
+ eval"&aes${p} ($inout3,$rndkey1)";
+ eval"&aes${p}last ($inout0,$rndkey0)";
+ eval"&aes${p}last ($inout1,$rndkey0)";
+ eval"&aes${p}last ($inout2,$rndkey0)";
+ eval"&aes${p}last ($inout3,$rndkey0)";
+ &ret();
+ &function_end_B("_aesni_${p}rypt4");
+}
+
+sub aesni_generate6
+{ my $p=shift;
+
+ &function_begin_B("_aesni_${p}rypt6");
+ &static_label("_aesni_${p}rypt6_enter");
+ &$movekey ($rndkey0,&QWP(0,$key));
+ &shl ($rounds,4);
+ &$movekey ($rndkey1,&QWP(16,$key));
+ &xorps ($inout0,$rndkey0);
+ &pxor ($inout1,$rndkey0); # pxor does better here
+ &pxor ($inout2,$rndkey0);
+ eval"&aes${p} ($inout0,$rndkey1)";
+ &pxor ($inout3,$rndkey0);
+ &pxor ($inout4,$rndkey0);
+ eval"&aes${p} ($inout1,$rndkey1)";
+ &lea ($key,&DWP(32,$key,$rounds));
+ &neg ($rounds);
+ eval"&aes${p} ($inout2,$rndkey1)";
+ &pxor ($inout5,$rndkey0);
+ &add ($rounds,16);
+ eval"&aes${p} ($inout3,$rndkey1)";
+ eval"&aes${p} ($inout4,$rndkey1)";
+ eval"&aes${p} ($inout5,$rndkey1)";
+ &$movekey ($rndkey0,&QWP(-16,$key,$rounds));
+ &jmp (&label("_aesni_${p}rypt6_enter"));
+
+ &set_label("${p}6_loop",16);
+ eval"&aes${p} ($inout0,$rndkey1)";
+ eval"&aes${p} ($inout1,$rndkey1)";
+ eval"&aes${p} ($inout2,$rndkey1)";
+ eval"&aes${p} ($inout3,$rndkey1)";
+ eval"&aes${p} ($inout4,$rndkey1)";
+ eval"&aes${p} ($inout5,$rndkey1)";
+ &set_label("_aesni_${p}rypt6_enter");
+ &$movekey ($rndkey1,&QWP(0,$key,$rounds));
+ &add ($rounds,32);
+ eval"&aes${p} ($inout0,$rndkey0)";
+ eval"&aes${p} ($inout1,$rndkey0)";
+ eval"&aes${p} ($inout2,$rndkey0)";
+ eval"&aes${p} ($inout3,$rndkey0)";
+ eval"&aes${p} ($inout4,$rndkey0)";
+ eval"&aes${p} ($inout5,$rndkey0)";
+ &$movekey ($rndkey0,&QWP(-16,$key,$rounds));
+ &jnz (&label("${p}6_loop"));
+
+ eval"&aes${p} ($inout0,$rndkey1)";
+ eval"&aes${p} ($inout1,$rndkey1)";
+ eval"&aes${p} ($inout2,$rndkey1)";
+ eval"&aes${p} ($inout3,$rndkey1)";
+ eval"&aes${p} ($inout4,$rndkey1)";
+ eval"&aes${p} ($inout5,$rndkey1)";
+ eval"&aes${p}last ($inout0,$rndkey0)";
+ eval"&aes${p}last ($inout1,$rndkey0)";
+ eval"&aes${p}last ($inout2,$rndkey0)";
+ eval"&aes${p}last ($inout3,$rndkey0)";
+ eval"&aes${p}last ($inout4,$rndkey0)";
+ eval"&aes${p}last ($inout5,$rndkey0)";
+ &ret();
+ &function_end_B("_aesni_${p}rypt6");
+}
+&aesni_generate2("enc") if ($PREFIX eq "aesni");
+&aesni_generate2("dec");
+&aesni_generate3("enc") if ($PREFIX eq "aesni");
+&aesni_generate3("dec");
+&aesni_generate4("enc") if ($PREFIX eq "aesni");
+&aesni_generate4("dec");
+&aesni_generate6("enc") if ($PREFIX eq "aesni");
+&aesni_generate6("dec");
+
+if ($PREFIX eq "aesni") {
+######################################################################
+# void aesni_ecb_encrypt (const void *in, void *out,
+# size_t length, const AES_KEY *key,
+# int enc);
+&function_begin("aesni_ecb_encrypt");
+ &mov ($inp,&wparam(0));
+ &mov ($out,&wparam(1));
+ &mov ($len,&wparam(2));
+ &mov ($key,&wparam(3));
+ &mov ($rounds_,&wparam(4));
+ &and ($len,-16);
+ &jz (&label("ecb_ret"));
+ &mov ($rounds,&DWP(240,$key));
+ &test ($rounds_,$rounds_);
+ &jz (&label("ecb_decrypt"));
+
+ &mov ($key_,$key); # backup $key
+ &mov ($rounds_,$rounds); # backup $rounds
+ &cmp ($len,0x60);
+ &jb (&label("ecb_enc_tail"));
+
+ &movdqu ($inout0,&QWP(0,$inp));
+ &movdqu ($inout1,&QWP(0x10,$inp));
+ &movdqu ($inout2,&QWP(0x20,$inp));
+ &movdqu ($inout3,&QWP(0x30,$inp));
+ &movdqu ($inout4,&QWP(0x40,$inp));
+ &movdqu ($inout5,&QWP(0x50,$inp));
+ &lea ($inp,&DWP(0x60,$inp));
+ &sub ($len,0x60);
+ &jmp (&label("ecb_enc_loop6_enter"));
+
+&set_label("ecb_enc_loop6",16);
+ &movups (&QWP(0,$out),$inout0);
+ &movdqu ($inout0,&QWP(0,$inp));
+ &movups (&QWP(0x10,$out),$inout1);
+ &movdqu ($inout1,&QWP(0x10,$inp));
+ &movups (&QWP(0x20,$out),$inout2);
+ &movdqu ($inout2,&QWP(0x20,$inp));
+ &movups (&QWP(0x30,$out),$inout3);
+ &movdqu ($inout3,&QWP(0x30,$inp));
+ &movups (&QWP(0x40,$out),$inout4);
+ &movdqu ($inout4,&QWP(0x40,$inp));
+ &movups (&QWP(0x50,$out),$inout5);
+ &lea ($out,&DWP(0x60,$out));
+ &movdqu ($inout5,&QWP(0x50,$inp));
+ &lea ($inp,&DWP(0x60,$inp));
+&set_label("ecb_enc_loop6_enter");
+
+ &call ("_aesni_encrypt6");
+
+ &mov ($key,$key_); # restore $key
+ &mov ($rounds,$rounds_); # restore $rounds
+ &sub ($len,0x60);
+ &jnc (&label("ecb_enc_loop6"));
+
+ &movups (&QWP(0,$out),$inout0);
+ &movups (&QWP(0x10,$out),$inout1);
+ &movups (&QWP(0x20,$out),$inout2);
+ &movups (&QWP(0x30,$out),$inout3);
+ &movups (&QWP(0x40,$out),$inout4);
+ &movups (&QWP(0x50,$out),$inout5);
+ &lea ($out,&DWP(0x60,$out));
+ &add ($len,0x60);
+ &jz (&label("ecb_ret"));
+
+&set_label("ecb_enc_tail");
+ &movups ($inout0,&QWP(0,$inp));
+ &cmp ($len,0x20);
+ &jb (&label("ecb_enc_one"));
+ &movups ($inout1,&QWP(0x10,$inp));
+ &je (&label("ecb_enc_two"));
+ &movups ($inout2,&QWP(0x20,$inp));
+ &cmp ($len,0x40);
+ &jb (&label("ecb_enc_three"));
+ &movups ($inout3,&QWP(0x30,$inp));
+ &je (&label("ecb_enc_four"));
+ &movups ($inout4,&QWP(0x40,$inp));
+ &xorps ($inout5,$inout5);
+ &call ("_aesni_encrypt6");
+ &movups (&QWP(0,$out),$inout0);
+ &movups (&QWP(0x10,$out),$inout1);
+ &movups (&QWP(0x20,$out),$inout2);
+ &movups (&QWP(0x30,$out),$inout3);
+ &movups (&QWP(0x40,$out),$inout4);
+ jmp (&label("ecb_ret"));
+
+&set_label("ecb_enc_one",16);
+ if ($inline)
+ { &aesni_inline_generate1("enc"); }
+ else
+ { &call ("_aesni_encrypt1"); }
+ &movups (&QWP(0,$out),$inout0);
+ &jmp (&label("ecb_ret"));
+
+&set_label("ecb_enc_two",16);
+ &call ("_aesni_encrypt2");
+ &movups (&QWP(0,$out),$inout0);
+ &movups (&QWP(0x10,$out),$inout1);
+ &jmp (&label("ecb_ret"));
+
+&set_label("ecb_enc_three",16);
+ &call ("_aesni_encrypt3");
+ &movups (&QWP(0,$out),$inout0);
+ &movups (&QWP(0x10,$out),$inout1);
+ &movups (&QWP(0x20,$out),$inout2);
+ &jmp (&label("ecb_ret"));
+
+&set_label("ecb_enc_four",16);
+ &call ("_aesni_encrypt4");
+ &movups (&QWP(0,$out),$inout0);
+ &movups (&QWP(0x10,$out),$inout1);
+ &movups (&QWP(0x20,$out),$inout2);
+ &movups (&QWP(0x30,$out),$inout3);
+ &jmp (&label("ecb_ret"));
+######################################################################
+&set_label("ecb_decrypt",16);
+ &mov ($key_,$key); # backup $key
+ &mov ($rounds_,$rounds); # backup $rounds
+ &cmp ($len,0x60);
+ &jb (&label("ecb_dec_tail"));
+
+ &movdqu ($inout0,&QWP(0,$inp));
+ &movdqu ($inout1,&QWP(0x10,$inp));
+ &movdqu ($inout2,&QWP(0x20,$inp));
+ &movdqu ($inout3,&QWP(0x30,$inp));
+ &movdqu ($inout4,&QWP(0x40,$inp));
+ &movdqu ($inout5,&QWP(0x50,$inp));
+ &lea ($inp,&DWP(0x60,$inp));
+ &sub ($len,0x60);
+ &jmp (&label("ecb_dec_loop6_enter"));
+
+&set_label("ecb_dec_loop6",16);
+ &movups (&QWP(0,$out),$inout0);
+ &movdqu ($inout0,&QWP(0,$inp));
+ &movups (&QWP(0x10,$out),$inout1);
+ &movdqu ($inout1,&QWP(0x10,$inp));
+ &movups (&QWP(0x20,$out),$inout2);
+ &movdqu ($inout2,&QWP(0x20,$inp));
+ &movups (&QWP(0x30,$out),$inout3);
+ &movdqu ($inout3,&QWP(0x30,$inp));
+ &movups (&QWP(0x40,$out),$inout4);
+ &movdqu ($inout4,&QWP(0x40,$inp));
+ &movups (&QWP(0x50,$out),$inout5);
+ &lea ($out,&DWP(0x60,$out));
+ &movdqu ($inout5,&QWP(0x50,$inp));
+ &lea ($inp,&DWP(0x60,$inp));
+&set_label("ecb_dec_loop6_enter");
+
+ &call ("_aesni_decrypt6");
+
+ &mov ($key,$key_); # restore $key
+ &mov ($rounds,$rounds_); # restore $rounds
+ &sub ($len,0x60);
+ &jnc (&label("ecb_dec_loop6"));
+
+ &movups (&QWP(0,$out),$inout0);
+ &movups (&QWP(0x10,$out),$inout1);
+ &movups (&QWP(0x20,$out),$inout2);
+ &movups (&QWP(0x30,$out),$inout3);
+ &movups (&QWP(0x40,$out),$inout4);
+ &movups (&QWP(0x50,$out),$inout5);
+ &lea ($out,&DWP(0x60,$out));
+ &add ($len,0x60);
+ &jz (&label("ecb_ret"));
+
+&set_label("ecb_dec_tail");
+ &movups ($inout0,&QWP(0,$inp));
+ &cmp ($len,0x20);
+ &jb (&label("ecb_dec_one"));
+ &movups ($inout1,&QWP(0x10,$inp));
+ &je (&label("ecb_dec_two"));
+ &movups ($inout2,&QWP(0x20,$inp));
+ &cmp ($len,0x40);
+ &jb (&label("ecb_dec_three"));
+ &movups ($inout3,&QWP(0x30,$inp));
+ &je (&label("ecb_dec_four"));
+ &movups ($inout4,&QWP(0x40,$inp));
+ &xorps ($inout5,$inout5);
+ &call ("_aesni_decrypt6");
+ &movups (&QWP(0,$out),$inout0);
+ &movups (&QWP(0x10,$out),$inout1);
+ &movups (&QWP(0x20,$out),$inout2);
+ &movups (&QWP(0x30,$out),$inout3);
+ &movups (&QWP(0x40,$out),$inout4);
+ &jmp (&label("ecb_ret"));
+
+&set_label("ecb_dec_one",16);
+ if ($inline)
+ { &aesni_inline_generate1("dec"); }
+ else
+ { &call ("_aesni_decrypt1"); }
+ &movups (&QWP(0,$out),$inout0);
+ &jmp (&label("ecb_ret"));
+
+&set_label("ecb_dec_two",16);
+ &call ("_aesni_decrypt2");
+ &movups (&QWP(0,$out),$inout0);
+ &movups (&QWP(0x10,$out),$inout1);
+ &jmp (&label("ecb_ret"));
+
+&set_label("ecb_dec_three",16);
+ &call ("_aesni_decrypt3");
+ &movups (&QWP(0,$out),$inout0);
+ &movups (&QWP(0x10,$out),$inout1);
+ &movups (&QWP(0x20,$out),$inout2);
+ &jmp (&label("ecb_ret"));
+
+&set_label("ecb_dec_four",16);
+ &call ("_aesni_decrypt4");
+ &movups (&QWP(0,$out),$inout0);
+ &movups (&QWP(0x10,$out),$inout1);
+ &movups (&QWP(0x20,$out),$inout2);
+ &movups (&QWP(0x30,$out),$inout3);
+
+&set_label("ecb_ret");
+&function_end("aesni_ecb_encrypt");
+
+######################################################################
+# void aesni_ccm64_[en|de]crypt_blocks (const void *in, void *out,
+# size_t blocks, const AES_KEY *key,
+# const char *ivec,char *cmac);
+#
+# Handles only complete blocks, operates on 64-bit counter and
+# does not update *ivec! Nor does it finalize CMAC value
+# (see engine/eng_aesni.c for details)
+#
+{ my $cmac=$inout1;
+&function_begin("aesni_ccm64_encrypt_blocks");
+ &mov ($inp,&wparam(0));
+ &mov ($out,&wparam(1));
+ &mov ($len,&wparam(2));
+ &mov ($key,&wparam(3));
+ &mov ($rounds_,&wparam(4));
+ &mov ($rounds,&wparam(5));
+ &mov ($key_,"esp");
+ &sub ("esp",60);
+ &and ("esp",-16); # align stack
+ &mov (&DWP(48,"esp"),$key_);
+
+ &movdqu ($ivec,&QWP(0,$rounds_)); # load ivec
+ &movdqu ($cmac,&QWP(0,$rounds)); # load cmac
+ &mov ($rounds,&DWP(240,$key));
+
+ # compose byte-swap control mask for pshufb on stack
+ &mov (&DWP(0,"esp"),0x0c0d0e0f);
+ &mov (&DWP(4,"esp"),0x08090a0b);
+ &mov (&DWP(8,"esp"),0x04050607);
+ &mov (&DWP(12,"esp"),0x00010203);
+
+ # compose counter increment vector on stack
+ &mov ($rounds_,1);
+ &xor ($key_,$key_);
+ &mov (&DWP(16,"esp"),$rounds_);
+ &mov (&DWP(20,"esp"),$key_);
+ &mov (&DWP(24,"esp"),$key_);
+ &mov (&DWP(28,"esp"),$key_);
+
+ &shl ($rounds,4);
+ &mov ($rounds_,16);
+ &lea ($key_,&DWP(0,$key));
+ &movdqa ($inout3,&QWP(0,"esp"));
+ &movdqa ($inout0,$ivec);
+ &lea ($key,&DWP(32,$key,$rounds));
+ &sub ($rounds_,$rounds);
+ &pshufb ($ivec,$inout3);
+
+&set_label("ccm64_enc_outer");
+ &$movekey ($rndkey0,&QWP(0,$key_));
+ &mov ($rounds,$rounds_);
+ &movups ($in0,&QWP(0,$inp));
+
+ &xorps ($inout0,$rndkey0);
+ &$movekey ($rndkey1,&QWP(16,$key_));
+ &xorps ($rndkey0,$in0);
+ &xorps ($cmac,$rndkey0); # cmac^=inp
+ &$movekey ($rndkey0,&QWP(32,$key_));
+
+&set_label("ccm64_enc2_loop");
+ &aesenc ($inout0,$rndkey1);
+ &aesenc ($cmac,$rndkey1);
+ &$movekey ($rndkey1,&QWP(0,$key,$rounds));
+ &add ($rounds,32);
+ &aesenc ($inout0,$rndkey0);
+ &aesenc ($cmac,$rndkey0);
+ &$movekey ($rndkey0,&QWP(-16,$key,$rounds));
+ &jnz (&label("ccm64_enc2_loop"));
+ &aesenc ($inout0,$rndkey1);
+ &aesenc ($cmac,$rndkey1);
+ &paddq ($ivec,&QWP(16,"esp"));
+ &dec ($len);
+ &aesenclast ($inout0,$rndkey0);
+ &aesenclast ($cmac,$rndkey0);
+
+ &lea ($inp,&DWP(16,$inp));
+ &xorps ($in0,$inout0); # inp^=E(ivec)
+ &movdqa ($inout0,$ivec);
+ &movups (&QWP(0,$out),$in0); # save output
+ &pshufb ($inout0,$inout3);
+ &lea ($out,&DWP(16,$out));
+ &jnz (&label("ccm64_enc_outer"));
+
+ &mov ("esp",&DWP(48,"esp"));
+ &mov ($out,&wparam(5));
+ &movups (&QWP(0,$out),$cmac);
+&function_end("aesni_ccm64_encrypt_blocks");
+
+&function_begin("aesni_ccm64_decrypt_blocks");
+ &mov ($inp,&wparam(0));
+ &mov ($out,&wparam(1));
+ &mov ($len,&wparam(2));
+ &mov ($key,&wparam(3));
+ &mov ($rounds_,&wparam(4));
+ &mov ($rounds,&wparam(5));
+ &mov ($key_,"esp");
+ &sub ("esp",60);
+ &and ("esp",-16); # align stack
+ &mov (&DWP(48,"esp"),$key_);
+
+ &movdqu ($ivec,&QWP(0,$rounds_)); # load ivec
+ &movdqu ($cmac,&QWP(0,$rounds)); # load cmac
+ &mov ($rounds,&DWP(240,$key));
+
+ # compose byte-swap control mask for pshufb on stack
+ &mov (&DWP(0,"esp"),0x0c0d0e0f);
+ &mov (&DWP(4,"esp"),0x08090a0b);
+ &mov (&DWP(8,"esp"),0x04050607);
+ &mov (&DWP(12,"esp"),0x00010203);
+
+ # compose counter increment vector on stack
+ &mov ($rounds_,1);
+ &xor ($key_,$key_);
+ &mov (&DWP(16,"esp"),$rounds_);
+ &mov (&DWP(20,"esp"),$key_);
+ &mov (&DWP(24,"esp"),$key_);
+ &mov (&DWP(28,"esp"),$key_);
+
+ &movdqa ($inout3,&QWP(0,"esp")); # bswap mask
+ &movdqa ($inout0,$ivec);
+
+ &mov ($key_,$key);
+ &mov ($rounds_,$rounds);
+
+ &pshufb ($ivec,$inout3);
+ if ($inline)
+ { &aesni_inline_generate1("enc"); }
+ else
+ { &call ("_aesni_encrypt1"); }
+ &shl ($rounds_,4);
+ &mov ($rounds,16);
+ &movups ($in0,&QWP(0,$inp)); # load inp
+ &paddq ($ivec,&QWP(16,"esp"));
+ &lea ($inp,&QWP(16,$inp));
+ &sub ($rounds,$rounds_);
+ &lea ($key,&DWP(32,$key_,$rounds_));
+ &mov ($rounds_,$rounds);
+ &jmp (&label("ccm64_dec_outer"));
+
+&set_label("ccm64_dec_outer",16);
+ &xorps ($in0,$inout0); # inp ^= E(ivec)
+ &movdqa ($inout0,$ivec);
+ &movups (&QWP(0,$out),$in0); # save output
+ &lea ($out,&DWP(16,$out));
+ &pshufb ($inout0,$inout3);
+
+ &sub ($len,1);
+ &jz (&label("ccm64_dec_break"));
+
+ &$movekey ($rndkey0,&QWP(0,$key_));
+ &mov ($rounds,$rounds_);
+ &$movekey ($rndkey1,&QWP(16,$key_));
+ &xorps ($in0,$rndkey0);
+ &xorps ($inout0,$rndkey0);
+ &xorps ($cmac,$in0); # cmac^=out
+ &$movekey ($rndkey0,&QWP(32,$key_));
+
+&set_label("ccm64_dec2_loop");
+ &aesenc ($inout0,$rndkey1);
+ &aesenc ($cmac,$rndkey1);
+ &$movekey ($rndkey1,&QWP(0,$key,$rounds));
+ &add ($rounds,32);
+ &aesenc ($inout0,$rndkey0);
+ &aesenc ($cmac,$rndkey0);
+ &$movekey ($rndkey0,&QWP(-16,$key,$rounds));
+ &jnz (&label("ccm64_dec2_loop"));
+ &movups ($in0,&QWP(0,$inp)); # load inp
+ &paddq ($ivec,&QWP(16,"esp"));
+ &aesenc ($inout0,$rndkey1);
+ &aesenc ($cmac,$rndkey1);
+ &aesenclast ($inout0,$rndkey0);
+ &aesenclast ($cmac,$rndkey0);
+ &lea ($inp,&QWP(16,$inp));
+ &jmp (&label("ccm64_dec_outer"));
+
+&set_label("ccm64_dec_break",16);
+ &mov ($rounds,&DWP(240,$key_));
+ &mov ($key,$key_);
+ if ($inline)
+ { &aesni_inline_generate1("enc",$cmac,$in0); }
+ else
+ { &call ("_aesni_encrypt1",$cmac); }
+
+ &mov ("esp",&DWP(48,"esp"));
+ &mov ($out,&wparam(5));
+ &movups (&QWP(0,$out),$cmac);
+&function_end("aesni_ccm64_decrypt_blocks");
+}
+
+######################################################################
+# void aesni_ctr32_encrypt_blocks (const void *in, void *out,
+# size_t blocks, const AES_KEY *key,
+# const char *ivec);
+#
+# Handles only complete blocks, operates on 32-bit counter and
+# does not update *ivec! (see crypto/modes/ctr128.c for details)
+#
+# stack layout:
+# 0 pshufb mask
+# 16 vector addend: 0,6,6,6
+# 32 counter-less ivec
+# 48 1st triplet of counter vector
+# 64 2nd triplet of counter vector
+# 80 saved %esp
+
+&function_begin("aesni_ctr32_encrypt_blocks");
+ &mov ($inp,&wparam(0));
+ &mov ($out,&wparam(1));
+ &mov ($len,&wparam(2));
+ &mov ($key,&wparam(3));
+ &mov ($rounds_,&wparam(4));
+ &mov ($key_,"esp");
+ &sub ("esp",88);
+ &and ("esp",-16); # align stack
+ &mov (&DWP(80,"esp"),$key_);
+
+ &cmp ($len,1);
+ &je (&label("ctr32_one_shortcut"));
+
+ &movdqu ($inout5,&QWP(0,$rounds_)); # load ivec
+
+ # compose byte-swap control mask for pshufb on stack
+ &mov (&DWP(0,"esp"),0x0c0d0e0f);
+ &mov (&DWP(4,"esp"),0x08090a0b);
+ &mov (&DWP(8,"esp"),0x04050607);
+ &mov (&DWP(12,"esp"),0x00010203);
+
+ # compose counter increment vector on stack
+ &mov ($rounds,6);
+ &xor ($key_,$key_);
+ &mov (&DWP(16,"esp"),$rounds);
+ &mov (&DWP(20,"esp"),$rounds);
+ &mov (&DWP(24,"esp"),$rounds);
+ &mov (&DWP(28,"esp"),$key_);
+
+ &pextrd ($rounds_,$inout5,3); # pull 32-bit counter
+ &pinsrd ($inout5,$key_,3); # wipe 32-bit counter
+
+ &mov ($rounds,&DWP(240,$key)); # key->rounds
+
+ # compose 2 vectors of 3x32-bit counters
+ &bswap ($rounds_);
+ &pxor ($rndkey0,$rndkey0);
+ &pxor ($rndkey1,$rndkey1);
+ &movdqa ($inout0,&QWP(0,"esp")); # load byte-swap mask
+ &pinsrd ($rndkey0,$rounds_,0);
+ &lea ($key_,&DWP(3,$rounds_));
+ &pinsrd ($rndkey1,$key_,0);
+ &inc ($rounds_);
+ &pinsrd ($rndkey0,$rounds_,1);
+ &inc ($key_);
+ &pinsrd ($rndkey1,$key_,1);
+ &inc ($rounds_);
+ &pinsrd ($rndkey0,$rounds_,2);
+ &inc ($key_);
+ &pinsrd ($rndkey1,$key_,2);
+ &movdqa (&QWP(48,"esp"),$rndkey0); # save 1st triplet
+ &pshufb ($rndkey0,$inout0); # byte swap
+ &movdqu ($inout4,&QWP(0,$key)); # key[0]
+ &movdqa (&QWP(64,"esp"),$rndkey1); # save 2nd triplet
+ &pshufb ($rndkey1,$inout0); # byte swap
+
+ &pshufd ($inout0,$rndkey0,3<<6); # place counter to upper dword
+ &pshufd ($inout1,$rndkey0,2<<6);
+ &cmp ($len,6);
+ &jb (&label("ctr32_tail"));
+ &pxor ($inout5,$inout4); # counter-less ivec^key[0]
+ &shl ($rounds,4);
+ &mov ($rounds_,16);
+ &movdqa (&QWP(32,"esp"),$inout5); # save counter-less ivec^key[0]
+ &mov ($key_,$key); # backup $key
+ &sub ($rounds_,$rounds); # backup twisted $rounds
+ &lea ($key,&DWP(32,$key,$rounds));
+ &sub ($len,6);
+ &jmp (&label("ctr32_loop6"));
+
+&set_label("ctr32_loop6",16);
+ # inlining _aesni_encrypt6's prologue gives ~6% improvement...
+ &pshufd ($inout2,$rndkey0,1<<6);
+ &movdqa ($rndkey0,&QWP(32,"esp")); # pull counter-less ivec
+ &pshufd ($inout3,$rndkey1,3<<6);
+ &pxor ($inout0,$rndkey0); # merge counter-less ivec
+ &pshufd ($inout4,$rndkey1,2<<6);
+ &pxor ($inout1,$rndkey0);
+ &pshufd ($inout5,$rndkey1,1<<6);
+ &$movekey ($rndkey1,&QWP(16,$key_));
+ &pxor ($inout2,$rndkey0);
+ &pxor ($inout3,$rndkey0);
+ &aesenc ($inout0,$rndkey1);
+ &pxor ($inout4,$rndkey0);
+ &pxor ($inout5,$rndkey0);
+ &aesenc ($inout1,$rndkey1);
+ &$movekey ($rndkey0,&QWP(32,$key_));
+ &mov ($rounds,$rounds_);
+ &aesenc ($inout2,$rndkey1);
+ &aesenc ($inout3,$rndkey1);
+ &aesenc ($inout4,$rndkey1);
+ &aesenc ($inout5,$rndkey1);
+
+ &call (&label("_aesni_encrypt6_enter"));
+
+ &movups ($rndkey1,&QWP(0,$inp));
+ &movups ($rndkey0,&QWP(0x10,$inp));
+ &xorps ($inout0,$rndkey1);
+ &movups ($rndkey1,&QWP(0x20,$inp));
+ &xorps ($inout1,$rndkey0);
+ &movups (&QWP(0,$out),$inout0);
+ &movdqa ($rndkey0,&QWP(16,"esp")); # load increment
+ &xorps ($inout2,$rndkey1);
+ &movdqa ($rndkey1,&QWP(64,"esp")); # load 2nd triplet
+ &movups (&QWP(0x10,$out),$inout1);
+ &movups (&QWP(0x20,$out),$inout2);
+
+ &paddd ($rndkey1,$rndkey0); # 2nd triplet increment
+ &paddd ($rndkey0,&QWP(48,"esp")); # 1st triplet increment
+ &movdqa ($inout0,&QWP(0,"esp")); # load byte swap mask
+
+ &movups ($inout1,&QWP(0x30,$inp));
+ &movups ($inout2,&QWP(0x40,$inp));
+ &xorps ($inout3,$inout1);
+ &movups ($inout1,&QWP(0x50,$inp));
+ &lea ($inp,&DWP(0x60,$inp));
+ &movdqa (&QWP(48,"esp"),$rndkey0); # save 1st triplet
+ &pshufb ($rndkey0,$inout0); # byte swap
+ &xorps ($inout4,$inout2);
+ &movups (&QWP(0x30,$out),$inout3);
+ &xorps ($inout5,$inout1);
+ &movdqa (&QWP(64,"esp"),$rndkey1); # save 2nd triplet
+ &pshufb ($rndkey1,$inout0); # byte swap
+ &movups (&QWP(0x40,$out),$inout4);
+ &pshufd ($inout0,$rndkey0,3<<6);
+ &movups (&QWP(0x50,$out),$inout5);
+ &lea ($out,&DWP(0x60,$out));
+
+ &pshufd ($inout1,$rndkey0,2<<6);
+ &sub ($len,6);
+ &jnc (&label("ctr32_loop6"));
+
+ &add ($len,6);
+ &jz (&label("ctr32_ret"));
+ &movdqu ($inout5,&QWP(0,$key_));
+ &mov ($key,$key_);
+ &pxor ($inout5,&QWP(32,"esp")); # restore count-less ivec
+ &mov ($rounds,&DWP(240,$key_)); # restore $rounds
+
+&set_label("ctr32_tail");
+ &por ($inout0,$inout5);
+ &cmp ($len,2);
+ &jb (&label("ctr32_one"));
+
+ &pshufd ($inout2,$rndkey0,1<<6);
+ &por ($inout1,$inout5);
+ &je (&label("ctr32_two"));
+
+ &pshufd ($inout3,$rndkey1,3<<6);
+ &por ($inout2,$inout5);
+ &cmp ($len,4);
+ &jb (&label("ctr32_three"));
+
+ &pshufd ($inout4,$rndkey1,2<<6);
+ &por ($inout3,$inout5);
+ &je (&label("ctr32_four"));
+
+ &por ($inout4,$inout5);
+ &call ("_aesni_encrypt6");
+ &movups ($rndkey1,&QWP(0,$inp));
+ &movups ($rndkey0,&QWP(0x10,$inp));
+ &xorps ($inout0,$rndkey1);
+ &movups ($rndkey1,&QWP(0x20,$inp));
+ &xorps ($inout1,$rndkey0);
+ &movups ($rndkey0,&QWP(0x30,$inp));
+ &xorps ($inout2,$rndkey1);
+ &movups ($rndkey1,&QWP(0x40,$inp));
+ &xorps ($inout3,$rndkey0);
+ &movups (&QWP(0,$out),$inout0);
+ &xorps ($inout4,$rndkey1);
+ &movups (&QWP(0x10,$out),$inout1);
+ &movups (&QWP(0x20,$out),$inout2);
+ &movups (&QWP(0x30,$out),$inout3);
+ &movups (&QWP(0x40,$out),$inout4);
+ &jmp (&label("ctr32_ret"));
+
+&set_label("ctr32_one_shortcut",16);
+ &movups ($inout0,&QWP(0,$rounds_)); # load ivec
+ &mov ($rounds,&DWP(240,$key));
+
+&set_label("ctr32_one");
+ if ($inline)
+ { &aesni_inline_generate1("enc"); }
+ else
+ { &call ("_aesni_encrypt1"); }
+ &movups ($in0,&QWP(0,$inp));
+ &xorps ($in0,$inout0);
+ &movups (&QWP(0,$out),$in0);
+ &jmp (&label("ctr32_ret"));
+
+&set_label("ctr32_two",16);
+ &call ("_aesni_encrypt2");
+ &movups ($inout3,&QWP(0,$inp));
+ &movups ($inout4,&QWP(0x10,$inp));
+ &xorps ($inout0,$inout3);
+ &xorps ($inout1,$inout4);
+ &movups (&QWP(0,$out),$inout0);
+ &movups (&QWP(0x10,$out),$inout1);
+ &jmp (&label("ctr32_ret"));
+
+&set_label("ctr32_three",16);
+ &call ("_aesni_encrypt3");
+ &movups ($inout3,&QWP(0,$inp));
+ &movups ($inout4,&QWP(0x10,$inp));
+ &xorps ($inout0,$inout3);
+ &movups ($inout5,&QWP(0x20,$inp));
+ &xorps ($inout1,$inout4);
+ &movups (&QWP(0,$out),$inout0);
+ &xorps ($inout2,$inout5);
+ &movups (&QWP(0x10,$out),$inout1);
+ &movups (&QWP(0x20,$out),$inout2);
+ &jmp (&label("ctr32_ret"));
+
+&set_label("ctr32_four",16);
+ &call ("_aesni_encrypt4");
+ &movups ($inout4,&QWP(0,$inp));
+ &movups ($inout5,&QWP(0x10,$inp));
+ &movups ($rndkey1,&QWP(0x20,$inp));
+ &xorps ($inout0,$inout4);
+ &movups ($rndkey0,&QWP(0x30,$inp));
+ &xorps ($inout1,$inout5);
+ &movups (&QWP(0,$out),$inout0);
+ &xorps ($inout2,$rndkey1);
+ &movups (&QWP(0x10,$out),$inout1);
+ &xorps ($inout3,$rndkey0);
+ &movups (&QWP(0x20,$out),$inout2);
+ &movups (&QWP(0x30,$out),$inout3);
+
+&set_label("ctr32_ret");
+ &mov ("esp",&DWP(80,"esp"));
+&function_end("aesni_ctr32_encrypt_blocks");
+
+######################################################################
+# void aesni_xts_[en|de]crypt(const char *inp,char *out,size_t len,
+# const AES_KEY *key1, const AES_KEY *key2
+# const unsigned char iv[16]);
+#
+{ my ($tweak,$twtmp,$twres,$twmask)=($rndkey1,$rndkey0,$inout0,$inout1);
+
+&function_begin("aesni_xts_encrypt");
+ &mov ($key,&wparam(4)); # key2
+ &mov ($inp,&wparam(5)); # clear-text tweak
+
+ &mov ($rounds,&DWP(240,$key)); # key2->rounds
+ &movups ($inout0,&QWP(0,$inp));
+ if ($inline)
+ { &aesni_inline_generate1("enc"); }
+ else
+ { &call ("_aesni_encrypt1"); }
+
+ &mov ($inp,&wparam(0));
+ &mov ($out,&wparam(1));
+ &mov ($len,&wparam(2));
+ &mov ($key,&wparam(3)); # key1
+
+ &mov ($key_,"esp");
+ &sub ("esp",16*7+8);
+ &mov ($rounds,&DWP(240,$key)); # key1->rounds
+ &and ("esp",-16); # align stack
+
+ &mov (&DWP(16*6+0,"esp"),0x87); # compose the magic constant
+ &mov (&DWP(16*6+4,"esp"),0);
+ &mov (&DWP(16*6+8,"esp"),1);
+ &mov (&DWP(16*6+12,"esp"),0);
+ &mov (&DWP(16*7+0,"esp"),$len); # save original $len
+ &mov (&DWP(16*7+4,"esp"),$key_); # save original %esp
+
+ &movdqa ($tweak,$inout0);
+ &pxor ($twtmp,$twtmp);
+ &movdqa ($twmask,&QWP(6*16,"esp")); # 0x0...010...87
+ &pcmpgtd($twtmp,$tweak); # broadcast upper bits
+
+ &and ($len,-16);
+ &mov ($key_,$key); # backup $key
+ &mov ($rounds_,$rounds); # backup $rounds
+ &sub ($len,16*6);
+ &jc (&label("xts_enc_short"));
+
+ &shl ($rounds,4);
+ &mov ($rounds_,16);
+ &sub ($rounds_,$rounds);
+ &lea ($key,&DWP(32,$key,$rounds));
+ &jmp (&label("xts_enc_loop6"));
+
+&set_label("xts_enc_loop6",16);
+ for ($i=0;$i<4;$i++) {
+ &pshufd ($twres,$twtmp,0x13);
+ &pxor ($twtmp,$twtmp);
+ &movdqa (&QWP(16*$i,"esp"),$tweak);
+ &paddq ($tweak,$tweak); # &psllq($tweak,1);
+ &pand ($twres,$twmask); # isolate carry and residue
+ &pcmpgtd ($twtmp,$tweak); # broadcast upper bits
+ &pxor ($tweak,$twres);
+ }
+ &pshufd ($inout5,$twtmp,0x13);
+ &movdqa (&QWP(16*$i++,"esp"),$tweak);
+ &paddq ($tweak,$tweak); # &psllq($tweak,1);
+ &$movekey ($rndkey0,&QWP(0,$key_));
+ &pand ($inout5,$twmask); # isolate carry and residue
+ &movups ($inout0,&QWP(0,$inp)); # load input
+ &pxor ($inout5,$tweak);
+
+ # inline _aesni_encrypt6 prologue and flip xor with tweak and key[0]
+ &mov ($rounds,$rounds_); # restore $rounds
+ &movdqu ($inout1,&QWP(16*1,$inp));
+ &xorps ($inout0,$rndkey0); # input^=rndkey[0]
+ &movdqu ($inout2,&QWP(16*2,$inp));
+ &pxor ($inout1,$rndkey0);
+ &movdqu ($inout3,&QWP(16*3,$inp));
+ &pxor ($inout2,$rndkey0);
+ &movdqu ($inout4,&QWP(16*4,$inp));
+ &pxor ($inout3,$rndkey0);
+ &movdqu ($rndkey1,&QWP(16*5,$inp));
+ &pxor ($inout4,$rndkey0);
+ &lea ($inp,&DWP(16*6,$inp));
+ &pxor ($inout0,&QWP(16*0,"esp")); # input^=tweak
+ &movdqa (&QWP(16*$i,"esp"),$inout5); # save last tweak
+ &pxor ($inout5,$rndkey1);
+
+ &$movekey ($rndkey1,&QWP(16,$key_));
+ &pxor ($inout1,&QWP(16*1,"esp"));
+ &pxor ($inout2,&QWP(16*2,"esp"));
+ &aesenc ($inout0,$rndkey1);
+ &pxor ($inout3,&QWP(16*3,"esp"));
+ &pxor ($inout4,&QWP(16*4,"esp"));
+ &aesenc ($inout1,$rndkey1);
+ &pxor ($inout5,$rndkey0);
+ &$movekey ($rndkey0,&QWP(32,$key_));
+ &aesenc ($inout2,$rndkey1);
+ &aesenc ($inout3,$rndkey1);
+ &aesenc ($inout4,$rndkey1);
+ &aesenc ($inout5,$rndkey1);
+ &call (&label("_aesni_encrypt6_enter"));
+
+ &movdqa ($tweak,&QWP(16*5,"esp")); # last tweak
+ &pxor ($twtmp,$twtmp);
+ &xorps ($inout0,&QWP(16*0,"esp")); # output^=tweak
+ &pcmpgtd ($twtmp,$tweak); # broadcast upper bits
+ &xorps ($inout1,&QWP(16*1,"esp"));
+ &movups (&QWP(16*0,$out),$inout0); # write output
+ &xorps ($inout2,&QWP(16*2,"esp"));
+ &movups (&QWP(16*1,$out),$inout1);
+ &xorps ($inout3,&QWP(16*3,"esp"));
+ &movups (&QWP(16*2,$out),$inout2);
+ &xorps ($inout4,&QWP(16*4,"esp"));
+ &movups (&QWP(16*3,$out),$inout3);
+ &xorps ($inout5,$tweak);
+ &movups (&QWP(16*4,$out),$inout4);
+ &pshufd ($twres,$twtmp,0x13);
+ &movups (&QWP(16*5,$out),$inout5);
+ &lea ($out,&DWP(16*6,$out));
+ &movdqa ($twmask,&QWP(16*6,"esp")); # 0x0...010...87
+
+ &pxor ($twtmp,$twtmp);
+ &paddq ($tweak,$tweak); # &psllq($tweak,1);
+ &pand ($twres,$twmask); # isolate carry and residue
+ &pcmpgtd($twtmp,$tweak); # broadcast upper bits
+ &pxor ($tweak,$twres);
+
+ &sub ($len,16*6);
+ &jnc (&label("xts_enc_loop6"));
+
+ &mov ($rounds,&DWP(240,$key_)); # restore $rounds
+ &mov ($key,$key_); # restore $key
+ &mov ($rounds_,$rounds);
+
+&set_label("xts_enc_short");
+ &add ($len,16*6);
+ &jz (&label("xts_enc_done6x"));
+
+ &movdqa ($inout3,$tweak); # put aside previous tweak
+ &cmp ($len,0x20);
+ &jb (&label("xts_enc_one"));
+
+ &pshufd ($twres,$twtmp,0x13);
+ &pxor ($twtmp,$twtmp);
+ &paddq ($tweak,$tweak); # &psllq($tweak,1);
+ &pand ($twres,$twmask); # isolate carry and residue
+ &pcmpgtd($twtmp,$tweak); # broadcast upper bits
+ &pxor ($tweak,$twres);
+ &je (&label("xts_enc_two"));
+
+ &pshufd ($twres,$twtmp,0x13);
+ &pxor ($twtmp,$twtmp);
+ &movdqa ($inout4,$tweak); # put aside previous tweak
+ &paddq ($tweak,$tweak); # &psllq($tweak,1);
+ &pand ($twres,$twmask); # isolate carry and residue
+ &pcmpgtd($twtmp,$tweak); # broadcast upper bits
+ &pxor ($tweak,$twres);
+ &cmp ($len,0x40);
+ &jb (&label("xts_enc_three"));
+
+ &pshufd ($twres,$twtmp,0x13);
+ &pxor ($twtmp,$twtmp);
+ &movdqa ($inout5,$tweak); # put aside previous tweak
+ &paddq ($tweak,$tweak); # &psllq($tweak,1);
+ &pand ($twres,$twmask); # isolate carry and residue
+ &pcmpgtd($twtmp,$tweak); # broadcast upper bits
+ &pxor ($tweak,$twres);
+ &movdqa (&QWP(16*0,"esp"),$inout3);
+ &movdqa (&QWP(16*1,"esp"),$inout4);
+ &je (&label("xts_enc_four"));
+
+ &movdqa (&QWP(16*2,"esp"),$inout5);
+ &pshufd ($inout5,$twtmp,0x13);
+ &movdqa (&QWP(16*3,"esp"),$tweak);
+ &paddq ($tweak,$tweak); # &psllq($inout0,1);
+ &pand ($inout5,$twmask); # isolate carry and residue
+ &pxor ($inout5,$tweak);
+
+ &movdqu ($inout0,&QWP(16*0,$inp)); # load input
+ &movdqu ($inout1,&QWP(16*1,$inp));
+ &movdqu ($inout2,&QWP(16*2,$inp));
+ &pxor ($inout0,&QWP(16*0,"esp")); # input^=tweak
+ &movdqu ($inout3,&QWP(16*3,$inp));
+ &pxor ($inout1,&QWP(16*1,"esp"));
+ &movdqu ($inout4,&QWP(16*4,$inp));
+ &pxor ($inout2,&QWP(16*2,"esp"));
+ &lea ($inp,&DWP(16*5,$inp));
+ &pxor ($inout3,&QWP(16*3,"esp"));
+ &movdqa (&QWP(16*4,"esp"),$inout5); # save last tweak
+ &pxor ($inout4,$inout5);
+
+ &call ("_aesni_encrypt6");
+
+ &movaps ($tweak,&QWP(16*4,"esp")); # last tweak
+ &xorps ($inout0,&QWP(16*0,"esp")); # output^=tweak
+ &xorps ($inout1,&QWP(16*1,"esp"));
+ &xorps ($inout2,&QWP(16*2,"esp"));
+ &movups (&QWP(16*0,$out),$inout0); # write output
+ &xorps ($inout3,&QWP(16*3,"esp"));
+ &movups (&QWP(16*1,$out),$inout1);
+ &xorps ($inout4,$tweak);
+ &movups (&QWP(16*2,$out),$inout2);
+ &movups (&QWP(16*3,$out),$inout3);
+ &movups (&QWP(16*4,$out),$inout4);
+ &lea ($out,&DWP(16*5,$out));
+ &jmp (&label("xts_enc_done"));
+
+&set_label("xts_enc_one",16);
+ &movups ($inout0,&QWP(16*0,$inp)); # load input
+ &lea ($inp,&DWP(16*1,$inp));
+ &xorps ($inout0,$inout3); # input^=tweak
+ if ($inline)
+ { &aesni_inline_generate1("enc"); }
+ else
+ { &call ("_aesni_encrypt1"); }
+ &xorps ($inout0,$inout3); # output^=tweak
+ &movups (&QWP(16*0,$out),$inout0); # write output
+ &lea ($out,&DWP(16*1,$out));
+
+ &movdqa ($tweak,$inout3); # last tweak
+ &jmp (&label("xts_enc_done"));
+
+&set_label("xts_enc_two",16);
+ &movaps ($inout4,$tweak); # put aside last tweak
+
+ &movups ($inout0,&QWP(16*0,$inp)); # load input
+ &movups ($inout1,&QWP(16*1,$inp));
+ &lea ($inp,&DWP(16*2,$inp));
+ &xorps ($inout0,$inout3); # input^=tweak
+ &xorps ($inout1,$inout4);
+
+ &call ("_aesni_encrypt2");
+
+ &xorps ($inout0,$inout3); # output^=tweak
+ &xorps ($inout1,$inout4);
+ &movups (&QWP(16*0,$out),$inout0); # write output
+ &movups (&QWP(16*1,$out),$inout1);
+ &lea ($out,&DWP(16*2,$out));
+
+ &movdqa ($tweak,$inout4); # last tweak
+ &jmp (&label("xts_enc_done"));
+
+&set_label("xts_enc_three",16);
+ &movaps ($inout5,$tweak); # put aside last tweak
+ &movups ($inout0,&QWP(16*0,$inp)); # load input
+ &movups ($inout1,&QWP(16*1,$inp));
+ &movups ($inout2,&QWP(16*2,$inp));
+ &lea ($inp,&DWP(16*3,$inp));
+ &xorps ($inout0,$inout3); # input^=tweak
+ &xorps ($inout1,$inout4);
+ &xorps ($inout2,$inout5);
+
+ &call ("_aesni_encrypt3");
+
+ &xorps ($inout0,$inout3); # output^=tweak
+ &xorps ($inout1,$inout4);
+ &xorps ($inout2,$inout5);
+ &movups (&QWP(16*0,$out),$inout0); # write output
+ &movups (&QWP(16*1,$out),$inout1);
+ &movups (&QWP(16*2,$out),$inout2);
+ &lea ($out,&DWP(16*3,$out));
+
+ &movdqa ($tweak,$inout5); # last tweak
+ &jmp (&label("xts_enc_done"));
+
+&set_label("xts_enc_four",16);
+ &movaps ($inout4,$tweak); # put aside last tweak
+
+ &movups ($inout0,&QWP(16*0,$inp)); # load input
+ &movups ($inout1,&QWP(16*1,$inp));
+ &movups ($inout2,&QWP(16*2,$inp));
+ &xorps ($inout0,&QWP(16*0,"esp")); # input^=tweak
+ &movups ($inout3,&QWP(16*3,$inp));
+ &lea ($inp,&DWP(16*4,$inp));
+ &xorps ($inout1,&QWP(16*1,"esp"));
+ &xorps ($inout2,$inout5);
+ &xorps ($inout3,$inout4);
+
+ &call ("_aesni_encrypt4");
+
+ &xorps ($inout0,&QWP(16*0,"esp")); # output^=tweak
+ &xorps ($inout1,&QWP(16*1,"esp"));
+ &xorps ($inout2,$inout5);
+ &movups (&QWP(16*0,$out),$inout0); # write output
+ &xorps ($inout3,$inout4);
+ &movups (&QWP(16*1,$out),$inout1);
+ &movups (&QWP(16*2,$out),$inout2);
+ &movups (&QWP(16*3,$out),$inout3);
+ &lea ($out,&DWP(16*4,$out));
+
+ &movdqa ($tweak,$inout4); # last tweak
+ &jmp (&label("xts_enc_done"));
+
+&set_label("xts_enc_done6x",16); # $tweak is pre-calculated
+ &mov ($len,&DWP(16*7+0,"esp")); # restore original $len
+ &and ($len,15);
+ &jz (&label("xts_enc_ret"));
+ &movdqa ($inout3,$tweak);
+ &mov (&DWP(16*7+0,"esp"),$len); # save $len%16
+ &jmp (&label("xts_enc_steal"));
+
+&set_label("xts_enc_done",16);
+ &mov ($len,&DWP(16*7+0,"esp")); # restore original $len
+ &pxor ($twtmp,$twtmp);
+ &and ($len,15);
+ &jz (&label("xts_enc_ret"));
+
+ &pcmpgtd($twtmp,$tweak); # broadcast upper bits
+ &mov (&DWP(16*7+0,"esp"),$len); # save $len%16
+ &pshufd ($inout3,$twtmp,0x13);
+ &paddq ($tweak,$tweak); # &psllq($tweak,1);
+ &pand ($inout3,&QWP(16*6,"esp")); # isolate carry and residue
+ &pxor ($inout3,$tweak);
+
+&set_label("xts_enc_steal");
+ &movz ($rounds,&BP(0,$inp));
+ &movz ($key,&BP(-16,$out));
+ &lea ($inp,&DWP(1,$inp));
+ &mov (&BP(-16,$out),&LB($rounds));
+ &mov (&BP(0,$out),&LB($key));
+ &lea ($out,&DWP(1,$out));
+ &sub ($len,1);
+ &jnz (&label("xts_enc_steal"));
+
+ &sub ($out,&DWP(16*7+0,"esp")); # rewind $out
+ &mov ($key,$key_); # restore $key
+ &mov ($rounds,$rounds_); # restore $rounds
+
+ &movups ($inout0,&QWP(-16,$out)); # load input
+ &xorps ($inout0,$inout3); # input^=tweak
+ if ($inline)
+ { &aesni_inline_generate1("enc"); }
+ else
+ { &call ("_aesni_encrypt1"); }
+ &xorps ($inout0,$inout3); # output^=tweak
+ &movups (&QWP(-16,$out),$inout0); # write output
+
+&set_label("xts_enc_ret");
+ &mov ("esp",&DWP(16*7+4,"esp")); # restore %esp
+&function_end("aesni_xts_encrypt");
+
+&function_begin("aesni_xts_decrypt");
+ &mov ($key,&wparam(4)); # key2
+ &mov ($inp,&wparam(5)); # clear-text tweak
+
+ &mov ($rounds,&DWP(240,$key)); # key2->rounds
+ &movups ($inout0,&QWP(0,$inp));
+ if ($inline)
+ { &aesni_inline_generate1("enc"); }
+ else
+ { &call ("_aesni_encrypt1"); }
+
+ &mov ($inp,&wparam(0));
+ &mov ($out,&wparam(1));
+ &mov ($len,&wparam(2));
+ &mov ($key,&wparam(3)); # key1
+
+ &mov ($key_,"esp");
+ &sub ("esp",16*7+8);
+ &and ("esp",-16); # align stack
+
+ &xor ($rounds_,$rounds_); # if(len%16) len-=16;
+ &test ($len,15);
+ &setnz (&LB($rounds_));
+ &shl ($rounds_,4);
+ &sub ($len,$rounds_);
+
+ &mov (&DWP(16*6+0,"esp"),0x87); # compose the magic constant
+ &mov (&DWP(16*6+4,"esp"),0);
+ &mov (&DWP(16*6+8,"esp"),1);
+ &mov (&DWP(16*6+12,"esp"),0);
+ &mov (&DWP(16*7+0,"esp"),$len); # save original $len
+ &mov (&DWP(16*7+4,"esp"),$key_); # save original %esp
+
+ &mov ($rounds,&DWP(240,$key)); # key1->rounds
+ &mov ($key_,$key); # backup $key
+ &mov ($rounds_,$rounds); # backup $rounds
+
+ &movdqa ($tweak,$inout0);
+ &pxor ($twtmp,$twtmp);
+ &movdqa ($twmask,&QWP(6*16,"esp")); # 0x0...010...87
+ &pcmpgtd($twtmp,$tweak); # broadcast upper bits
+
+ &and ($len,-16);
+ &sub ($len,16*6);
+ &jc (&label("xts_dec_short"));
+
+ &shl ($rounds,4);
+ &mov ($rounds_,16);
+ &sub ($rounds_,$rounds);
+ &lea ($key,&DWP(32,$key,$rounds));
+ &jmp (&label("xts_dec_loop6"));
+
+&set_label("xts_dec_loop6",16);
+ for ($i=0;$i<4;$i++) {
+ &pshufd ($twres,$twtmp,0x13);
+ &pxor ($twtmp,$twtmp);
+ &movdqa (&QWP(16*$i,"esp"),$tweak);
+ &paddq ($tweak,$tweak); # &psllq($tweak,1);
+ &pand ($twres,$twmask); # isolate carry and residue
+ &pcmpgtd ($twtmp,$tweak); # broadcast upper bits
+ &pxor ($tweak,$twres);
+ }
+ &pshufd ($inout5,$twtmp,0x13);
+ &movdqa (&QWP(16*$i++,"esp"),$tweak);
+ &paddq ($tweak,$tweak); # &psllq($tweak,1);
+ &$movekey ($rndkey0,&QWP(0,$key_));
+ &pand ($inout5,$twmask); # isolate carry and residue
+ &movups ($inout0,&QWP(0,$inp)); # load input
+ &pxor ($inout5,$tweak);
+
+ # inline _aesni_encrypt6 prologue and flip xor with tweak and key[0]
+ &mov ($rounds,$rounds_);
+ &movdqu ($inout1,&QWP(16*1,$inp));
+ &xorps ($inout0,$rndkey0); # input^=rndkey[0]
+ &movdqu ($inout2,&QWP(16*2,$inp));
+ &pxor ($inout1,$rndkey0);
+ &movdqu ($inout3,&QWP(16*3,$inp));
+ &pxor ($inout2,$rndkey0);
+ &movdqu ($inout4,&QWP(16*4,$inp));
+ &pxor ($inout3,$rndkey0);
+ &movdqu ($rndkey1,&QWP(16*5,$inp));
+ &pxor ($inout4,$rndkey0);
+ &lea ($inp,&DWP(16*6,$inp));
+ &pxor ($inout0,&QWP(16*0,"esp")); # input^=tweak
+ &movdqa (&QWP(16*$i,"esp"),$inout5); # save last tweak
+ &pxor ($inout5,$rndkey1);
+
+ &$movekey ($rndkey1,&QWP(16,$key_));
+ &pxor ($inout1,&QWP(16*1,"esp"));
+ &pxor ($inout2,&QWP(16*2,"esp"));
+ &aesdec ($inout0,$rndkey1);
+ &pxor ($inout3,&QWP(16*3,"esp"));
+ &pxor ($inout4,&QWP(16*4,"esp"));
+ &aesdec ($inout1,$rndkey1);
+ &pxor ($inout5,$rndkey0);
+ &$movekey ($rndkey0,&QWP(32,$key_));
+ &aesdec ($inout2,$rndkey1);
+ &aesdec ($inout3,$rndkey1);
+ &aesdec ($inout4,$rndkey1);
+ &aesdec ($inout5,$rndkey1);
+ &call (&label("_aesni_decrypt6_enter"));
+
+ &movdqa ($tweak,&QWP(16*5,"esp")); # last tweak
+ &pxor ($twtmp,$twtmp);
+ &xorps ($inout0,&QWP(16*0,"esp")); # output^=tweak
+ &pcmpgtd ($twtmp,$tweak); # broadcast upper bits
+ &xorps ($inout1,&QWP(16*1,"esp"));
+ &movups (&QWP(16*0,$out),$inout0); # write output
+ &xorps ($inout2,&QWP(16*2,"esp"));
+ &movups (&QWP(16*1,$out),$inout1);
+ &xorps ($inout3,&QWP(16*3,"esp"));
+ &movups (&QWP(16*2,$out),$inout2);
+ &xorps ($inout4,&QWP(16*4,"esp"));
+ &movups (&QWP(16*3,$out),$inout3);
+ &xorps ($inout5,$tweak);
+ &movups (&QWP(16*4,$out),$inout4);
+ &pshufd ($twres,$twtmp,0x13);
+ &movups (&QWP(16*5,$out),$inout5);
+ &lea ($out,&DWP(16*6,$out));
+ &movdqa ($twmask,&QWP(16*6,"esp")); # 0x0...010...87
+
+ &pxor ($twtmp,$twtmp);
+ &paddq ($tweak,$tweak); # &psllq($tweak,1);
+ &pand ($twres,$twmask); # isolate carry and residue
+ &pcmpgtd($twtmp,$tweak); # broadcast upper bits
+ &pxor ($tweak,$twres);
+
+ &sub ($len,16*6);
+ &jnc (&label("xts_dec_loop6"));
+
+ &mov ($rounds,&DWP(240,$key_)); # restore $rounds
+ &mov ($key,$key_); # restore $key
+ &mov ($rounds_,$rounds);
+
+&set_label("xts_dec_short");
+ &add ($len,16*6);
+ &jz (&label("xts_dec_done6x"));
+
+ &movdqa ($inout3,$tweak); # put aside previous tweak
+ &cmp ($len,0x20);
+ &jb (&label("xts_dec_one"));
+
+ &pshufd ($twres,$twtmp,0x13);
+ &pxor ($twtmp,$twtmp);
+ &paddq ($tweak,$tweak); # &psllq($tweak,1);
+ &pand ($twres,$twmask); # isolate carry and residue
+ &pcmpgtd($twtmp,$tweak); # broadcast upper bits
+ &pxor ($tweak,$twres);
+ &je (&label("xts_dec_two"));
+
+ &pshufd ($twres,$twtmp,0x13);
+ &pxor ($twtmp,$twtmp);
+ &movdqa ($inout4,$tweak); # put aside previous tweak
+ &paddq ($tweak,$tweak); # &psllq($tweak,1);
+ &pand ($twres,$twmask); # isolate carry and residue
+ &pcmpgtd($twtmp,$tweak); # broadcast upper bits
+ &pxor ($tweak,$twres);
+ &cmp ($len,0x40);
+ &jb (&label("xts_dec_three"));
+
+ &pshufd ($twres,$twtmp,0x13);
+ &pxor ($twtmp,$twtmp);
+ &movdqa ($inout5,$tweak); # put aside previous tweak
+ &paddq ($tweak,$tweak); # &psllq($tweak,1);
+ &pand ($twres,$twmask); # isolate carry and residue
+ &pcmpgtd($twtmp,$tweak); # broadcast upper bits
+ &pxor ($tweak,$twres);
+ &movdqa (&QWP(16*0,"esp"),$inout3);
+ &movdqa (&QWP(16*1,"esp"),$inout4);
+ &je (&label("xts_dec_four"));
+
+ &movdqa (&QWP(16*2,"esp"),$inout5);
+ &pshufd ($inout5,$twtmp,0x13);
+ &movdqa (&QWP(16*3,"esp"),$tweak);
+ &paddq ($tweak,$tweak); # &psllq($inout0,1);
+ &pand ($inout5,$twmask); # isolate carry and residue
+ &pxor ($inout5,$tweak);
+
+ &movdqu ($inout0,&QWP(16*0,$inp)); # load input
+ &movdqu ($inout1,&QWP(16*1,$inp));
+ &movdqu ($inout2,&QWP(16*2,$inp));
+ &pxor ($inout0,&QWP(16*0,"esp")); # input^=tweak
+ &movdqu ($inout3,&QWP(16*3,$inp));
+ &pxor ($inout1,&QWP(16*1,"esp"));
+ &movdqu ($inout4,&QWP(16*4,$inp));
+ &pxor ($inout2,&QWP(16*2,"esp"));
+ &lea ($inp,&DWP(16*5,$inp));
+ &pxor ($inout3,&QWP(16*3,"esp"));
+ &movdqa (&QWP(16*4,"esp"),$inout5); # save last tweak
+ &pxor ($inout4,$inout5);
+
+ &call ("_aesni_decrypt6");
+
+ &movaps ($tweak,&QWP(16*4,"esp")); # last tweak
+ &xorps ($inout0,&QWP(16*0,"esp")); # output^=tweak
+ &xorps ($inout1,&QWP(16*1,"esp"));
+ &xorps ($inout2,&QWP(16*2,"esp"));
+ &movups (&QWP(16*0,$out),$inout0); # write output
+ &xorps ($inout3,&QWP(16*3,"esp"));
+ &movups (&QWP(16*1,$out),$inout1);
+ &xorps ($inout4,$tweak);
+ &movups (&QWP(16*2,$out),$inout2);
+ &movups (&QWP(16*3,$out),$inout3);
+ &movups (&QWP(16*4,$out),$inout4);
+ &lea ($out,&DWP(16*5,$out));
+ &jmp (&label("xts_dec_done"));
+
+&set_label("xts_dec_one",16);
+ &movups ($inout0,&QWP(16*0,$inp)); # load input
+ &lea ($inp,&DWP(16*1,$inp));
+ &xorps ($inout0,$inout3); # input^=tweak
+ if ($inline)
+ { &aesni_inline_generate1("dec"); }
+ else
+ { &call ("_aesni_decrypt1"); }
+ &xorps ($inout0,$inout3); # output^=tweak
+ &movups (&QWP(16*0,$out),$inout0); # write output
+ &lea ($out,&DWP(16*1,$out));
+
+ &movdqa ($tweak,$inout3); # last tweak
+ &jmp (&label("xts_dec_done"));
+
+&set_label("xts_dec_two",16);
+ &movaps ($inout4,$tweak); # put aside last tweak
+
+ &movups ($inout0,&QWP(16*0,$inp)); # load input
+ &movups ($inout1,&QWP(16*1,$inp));
+ &lea ($inp,&DWP(16*2,$inp));
+ &xorps ($inout0,$inout3); # input^=tweak
+ &xorps ($inout1,$inout4);
+
+ &call ("_aesni_decrypt2");
+
+ &xorps ($inout0,$inout3); # output^=tweak
+ &xorps ($inout1,$inout4);
+ &movups (&QWP(16*0,$out),$inout0); # write output
+ &movups (&QWP(16*1,$out),$inout1);
+ &lea ($out,&DWP(16*2,$out));
+
+ &movdqa ($tweak,$inout4); # last tweak
+ &jmp (&label("xts_dec_done"));
+
+&set_label("xts_dec_three",16);
+ &movaps ($inout5,$tweak); # put aside last tweak
+ &movups ($inout0,&QWP(16*0,$inp)); # load input
+ &movups ($inout1,&QWP(16*1,$inp));
+ &movups ($inout2,&QWP(16*2,$inp));
+ &lea ($inp,&DWP(16*3,$inp));
+ &xorps ($inout0,$inout3); # input^=tweak
+ &xorps ($inout1,$inout4);
+ &xorps ($inout2,$inout5);
+
+ &call ("_aesni_decrypt3");
+
+ &xorps ($inout0,$inout3); # output^=tweak
+ &xorps ($inout1,$inout4);
+ &xorps ($inout2,$inout5);
+ &movups (&QWP(16*0,$out),$inout0); # write output
+ &movups (&QWP(16*1,$out),$inout1);
+ &movups (&QWP(16*2,$out),$inout2);
+ &lea ($out,&DWP(16*3,$out));
+
+ &movdqa ($tweak,$inout5); # last tweak
+ &jmp (&label("xts_dec_done"));
+
+&set_label("xts_dec_four",16);
+ &movaps ($inout4,$tweak); # put aside last tweak
+
+ &movups ($inout0,&QWP(16*0,$inp)); # load input
+ &movups ($inout1,&QWP(16*1,$inp));
+ &movups ($inout2,&QWP(16*2,$inp));
+ &xorps ($inout0,&QWP(16*0,"esp")); # input^=tweak
+ &movups ($inout3,&QWP(16*3,$inp));
+ &lea ($inp,&DWP(16*4,$inp));
+ &xorps ($inout1,&QWP(16*1,"esp"));
+ &xorps ($inout2,$inout5);
+ &xorps ($inout3,$inout4);
+
+ &call ("_aesni_decrypt4");
+
+ &xorps ($inout0,&QWP(16*0,"esp")); # output^=tweak
+ &xorps ($inout1,&QWP(16*1,"esp"));
+ &xorps ($inout2,$inout5);
+ &movups (&QWP(16*0,$out),$inout0); # write output
+ &xorps ($inout3,$inout4);
+ &movups (&QWP(16*1,$out),$inout1);
+ &movups (&QWP(16*2,$out),$inout2);
+ &movups (&QWP(16*3,$out),$inout3);
+ &lea ($out,&DWP(16*4,$out));
+
+ &movdqa ($tweak,$inout4); # last tweak
+ &jmp (&label("xts_dec_done"));
+
+&set_label("xts_dec_done6x",16); # $tweak is pre-calculated
+ &mov ($len,&DWP(16*7+0,"esp")); # restore original $len
+ &and ($len,15);
+ &jz (&label("xts_dec_ret"));
+ &mov (&DWP(16*7+0,"esp"),$len); # save $len%16
+ &jmp (&label("xts_dec_only_one_more"));
+
+&set_label("xts_dec_done",16);
+ &mov ($len,&DWP(16*7+0,"esp")); # restore original $len
+ &pxor ($twtmp,$twtmp);
+ &and ($len,15);
+ &jz (&label("xts_dec_ret"));
+
+ &pcmpgtd($twtmp,$tweak); # broadcast upper bits
+ &mov (&DWP(16*7+0,"esp"),$len); # save $len%16
+ &pshufd ($twres,$twtmp,0x13);
+ &pxor ($twtmp,$twtmp);
+ &movdqa ($twmask,&QWP(16*6,"esp"));
+ &paddq ($tweak,$tweak); # &psllq($tweak,1);
+ &pand ($twres,$twmask); # isolate carry and residue
+ &pcmpgtd($twtmp,$tweak); # broadcast upper bits
+ &pxor ($tweak,$twres);
+
+&set_label("xts_dec_only_one_more");
+ &pshufd ($inout3,$twtmp,0x13);
+ &movdqa ($inout4,$tweak); # put aside previous tweak
+ &paddq ($tweak,$tweak); # &psllq($tweak,1);
+ &pand ($inout3,$twmask); # isolate carry and residue
+ &pxor ($inout3,$tweak);
+
+ &mov ($key,$key_); # restore $key
+ &mov ($rounds,$rounds_); # restore $rounds
+
+ &movups ($inout0,&QWP(0,$inp)); # load input
+ &xorps ($inout0,$inout3); # input^=tweak
+ if ($inline)
+ { &aesni_inline_generate1("dec"); }
+ else
+ { &call ("_aesni_decrypt1"); }
+ &xorps ($inout0,$inout3); # output^=tweak
+ &movups (&QWP(0,$out),$inout0); # write output
+
+&set_label("xts_dec_steal");
+ &movz ($rounds,&BP(16,$inp));
+ &movz ($key,&BP(0,$out));
+ &lea ($inp,&DWP(1,$inp));
+ &mov (&BP(0,$out),&LB($rounds));
+ &mov (&BP(16,$out),&LB($key));
+ &lea ($out,&DWP(1,$out));
+ &sub ($len,1);
+ &jnz (&label("xts_dec_steal"));
+
+ &sub ($out,&DWP(16*7+0,"esp")); # rewind $out
+ &mov ($key,$key_); # restore $key
+ &mov ($rounds,$rounds_); # restore $rounds
+
+ &movups ($inout0,&QWP(0,$out)); # load input
+ &xorps ($inout0,$inout4); # input^=tweak
+ if ($inline)
+ { &aesni_inline_generate1("dec"); }
+ else
+ { &call ("_aesni_decrypt1"); }
+ &xorps ($inout0,$inout4); # output^=tweak
+ &movups (&QWP(0,$out),$inout0); # write output
+
+&set_label("xts_dec_ret");
+ &mov ("esp",&DWP(16*7+4,"esp")); # restore %esp
+&function_end("aesni_xts_decrypt");
+}
+}
+
+######################################################################
+# void $PREFIX_cbc_encrypt (const void *inp, void *out,
+# size_t length, const AES_KEY *key,
+# unsigned char *ivp,const int enc);
+&function_begin("${PREFIX}_cbc_encrypt");
+ &mov ($inp,&wparam(0));
+ &mov ($rounds_,"esp");
+ &mov ($out,&wparam(1));
+ &sub ($rounds_,24);
+ &mov ($len,&wparam(2));
+ &and ($rounds_,-16);
+ &mov ($key,&wparam(3));
+ &mov ($key_,&wparam(4));
+ &test ($len,$len);
+ &jz (&label("cbc_abort"));
+
+ &cmp (&wparam(5),0);
+ &xchg ($rounds_,"esp"); # alloca
+ &movups ($ivec,&QWP(0,$key_)); # load IV
+ &mov ($rounds,&DWP(240,$key));
+ &mov ($key_,$key); # backup $key
+ &mov (&DWP(16,"esp"),$rounds_); # save original %esp
+ &mov ($rounds_,$rounds); # backup $rounds
+ &je (&label("cbc_decrypt"));
+
+ &movaps ($inout0,$ivec);
+ &cmp ($len,16);
+ &jb (&label("cbc_enc_tail"));
+ &sub ($len,16);
+ &jmp (&label("cbc_enc_loop"));
+
+&set_label("cbc_enc_loop",16);
+ &movups ($ivec,&QWP(0,$inp)); # input actually
+ &lea ($inp,&DWP(16,$inp));
+ if ($inline)
+ { &aesni_inline_generate1("enc",$inout0,$ivec); }
+ else
+ { &xorps($inout0,$ivec); &call("_aesni_encrypt1"); }
+ &mov ($rounds,$rounds_); # restore $rounds
+ &mov ($key,$key_); # restore $key
+ &movups (&QWP(0,$out),$inout0); # store output
+ &lea ($out,&DWP(16,$out));
+ &sub ($len,16);
+ &jnc (&label("cbc_enc_loop"));
+ &add ($len,16);
+ &jnz (&label("cbc_enc_tail"));
+ &movaps ($ivec,$inout0);
+ &jmp (&label("cbc_ret"));
+
+&set_label("cbc_enc_tail");
+ &mov ("ecx",$len); # zaps $rounds
+ &data_word(0xA4F3F689); # rep movsb
+ &mov ("ecx",16); # zero tail
+ &sub ("ecx",$len);
+ &xor ("eax","eax"); # zaps $len
+ &data_word(0xAAF3F689); # rep stosb
+ &lea ($out,&DWP(-16,$out)); # rewind $out by 1 block
+ &mov ($rounds,$rounds_); # restore $rounds
+ &mov ($inp,$out); # $inp and $out are the same
+ &mov ($key,$key_); # restore $key
+ &jmp (&label("cbc_enc_loop"));
+######################################################################
+&set_label("cbc_decrypt",16);
+ &cmp ($len,0x50);
+ &jbe (&label("cbc_dec_tail"));
+ &movaps (&QWP(0,"esp"),$ivec); # save IV
+ &sub ($len,0x50);
+ &jmp (&label("cbc_dec_loop6_enter"));
+
+&set_label("cbc_dec_loop6",16);
+ &movaps (&QWP(0,"esp"),$rndkey0); # save IV
+ &movups (&QWP(0,$out),$inout5);
+ &lea ($out,&DWP(0x10,$out));
+&set_label("cbc_dec_loop6_enter");
+ &movdqu ($inout0,&QWP(0,$inp));
+ &movdqu ($inout1,&QWP(0x10,$inp));
+ &movdqu ($inout2,&QWP(0x20,$inp));
+ &movdqu ($inout3,&QWP(0x30,$inp));
+ &movdqu ($inout4,&QWP(0x40,$inp));
+ &movdqu ($inout5,&QWP(0x50,$inp));
+
+ &call ("_aesni_decrypt6");
+
+ &movups ($rndkey1,&QWP(0,$inp));
+ &movups ($rndkey0,&QWP(0x10,$inp));
+ &xorps ($inout0,&QWP(0,"esp")); # ^=IV
+ &xorps ($inout1,$rndkey1);
+ &movups ($rndkey1,&QWP(0x20,$inp));
+ &xorps ($inout2,$rndkey0);
+ &movups ($rndkey0,&QWP(0x30,$inp));
+ &xorps ($inout3,$rndkey1);
+ &movups ($rndkey1,&QWP(0x40,$inp));
+ &xorps ($inout4,$rndkey0);
+ &movups ($rndkey0,&QWP(0x50,$inp)); # IV
+ &xorps ($inout5,$rndkey1);
+ &movups (&QWP(0,$out),$inout0);
+ &movups (&QWP(0x10,$out),$inout1);
+ &lea ($inp,&DWP(0x60,$inp));
+ &movups (&QWP(0x20,$out),$inout2);
+ &mov ($rounds,$rounds_); # restore $rounds
+ &movups (&QWP(0x30,$out),$inout3);
+ &mov ($key,$key_); # restore $key
+ &movups (&QWP(0x40,$out),$inout4);
+ &lea ($out,&DWP(0x50,$out));
+ &sub ($len,0x60);
+ &ja (&label("cbc_dec_loop6"));
+
+ &movaps ($inout0,$inout5);
+ &movaps ($ivec,$rndkey0);
+ &add ($len,0x50);
+ &jle (&label("cbc_dec_tail_collected"));
+ &movups (&QWP(0,$out),$inout0);
+ &lea ($out,&DWP(0x10,$out));
+&set_label("cbc_dec_tail");
+ &movups ($inout0,&QWP(0,$inp));
+ &movaps ($in0,$inout0);
+ &cmp ($len,0x10);
+ &jbe (&label("cbc_dec_one"));
+
+ &movups ($inout1,&QWP(0x10,$inp));
+ &movaps ($in1,$inout1);
+ &cmp ($len,0x20);
+ &jbe (&label("cbc_dec_two"));
+
+ &movups ($inout2,&QWP(0x20,$inp));
+ &cmp ($len,0x30);
+ &jbe (&label("cbc_dec_three"));
+
+ &movups ($inout3,&QWP(0x30,$inp));
+ &cmp ($len,0x40);
+ &jbe (&label("cbc_dec_four"));
+
+ &movups ($inout4,&QWP(0x40,$inp));
+ &movaps (&QWP(0,"esp"),$ivec); # save IV
+ &movups ($inout0,&QWP(0,$inp));
+ &xorps ($inout5,$inout5);
+ &call ("_aesni_decrypt6");
+ &movups ($rndkey1,&QWP(0,$inp));
+ &movups ($rndkey0,&QWP(0x10,$inp));
+ &xorps ($inout0,&QWP(0,"esp")); # ^= IV
+ &xorps ($inout1,$rndkey1);
+ &movups ($rndkey1,&QWP(0x20,$inp));
+ &xorps ($inout2,$rndkey0);
+ &movups ($rndkey0,&QWP(0x30,$inp));
+ &xorps ($inout3,$rndkey1);
+ &movups ($ivec,&QWP(0x40,$inp)); # IV
+ &xorps ($inout4,$rndkey0);
+ &movups (&QWP(0,$out),$inout0);
+ &movups (&QWP(0x10,$out),$inout1);
+ &movups (&QWP(0x20,$out),$inout2);
+ &movups (&QWP(0x30,$out),$inout3);
+ &lea ($out,&DWP(0x40,$out));
+ &movaps ($inout0,$inout4);
+ &sub ($len,0x50);
+ &jmp (&label("cbc_dec_tail_collected"));
+
+&set_label("cbc_dec_one",16);
+ if ($inline)
+ { &aesni_inline_generate1("dec"); }
+ else
+ { &call ("_aesni_decrypt1"); }
+ &xorps ($inout0,$ivec);
+ &movaps ($ivec,$in0);
+ &sub ($len,0x10);
+ &jmp (&label("cbc_dec_tail_collected"));
+
+&set_label("cbc_dec_two",16);
+ &call ("_aesni_decrypt2");
+ &xorps ($inout0,$ivec);
+ &xorps ($inout1,$in0);
+ &movups (&QWP(0,$out),$inout0);
+ &movaps ($inout0,$inout1);
+ &lea ($out,&DWP(0x10,$out));
+ &movaps ($ivec,$in1);
+ &sub ($len,0x20);
+ &jmp (&label("cbc_dec_tail_collected"));
+
+&set_label("cbc_dec_three",16);
+ &call ("_aesni_decrypt3");
+ &xorps ($inout0,$ivec);
+ &xorps ($inout1,$in0);
+ &xorps ($inout2,$in1);
+ &movups (&QWP(0,$out),$inout0);
+ &movaps ($inout0,$inout2);
+ &movups (&QWP(0x10,$out),$inout1);
+ &lea ($out,&DWP(0x20,$out));
+ &movups ($ivec,&QWP(0x20,$inp));
+ &sub ($len,0x30);
+ &jmp (&label("cbc_dec_tail_collected"));
+
+&set_label("cbc_dec_four",16);
+ &call ("_aesni_decrypt4");
+ &movups ($rndkey1,&QWP(0x10,$inp));
+ &movups ($rndkey0,&QWP(0x20,$inp));
+ &xorps ($inout0,$ivec);
+ &movups ($ivec,&QWP(0x30,$inp));
+ &xorps ($inout1,$in0);
+ &movups (&QWP(0,$out),$inout0);
+ &xorps ($inout2,$rndkey1);
+ &movups (&QWP(0x10,$out),$inout1);
+ &xorps ($inout3,$rndkey0);
+ &movups (&QWP(0x20,$out),$inout2);
+ &lea ($out,&DWP(0x30,$out));
+ &movaps ($inout0,$inout3);
+ &sub ($len,0x40);
+
+&set_label("cbc_dec_tail_collected");
+ &and ($len,15);
+ &jnz (&label("cbc_dec_tail_partial"));
+ &movups (&QWP(0,$out),$inout0);
+ &jmp (&label("cbc_ret"));
+
+&set_label("cbc_dec_tail_partial",16);
+ &movaps (&QWP(0,"esp"),$inout0);
+ &mov ("ecx",16);
+ &mov ($inp,"esp");
+ &sub ("ecx",$len);
+ &data_word(0xA4F3F689); # rep movsb
+
+&set_label("cbc_ret");
+ &mov ("esp",&DWP(16,"esp")); # pull original %esp
+ &mov ($key_,&wparam(4));
+ &movups (&QWP(0,$key_),$ivec); # output IV
+&set_label("cbc_abort");
+&function_end("${PREFIX}_cbc_encrypt");
+
+######################################################################
+# Mechanical port from aesni-x86_64.pl.
+#
+# _aesni_set_encrypt_key is private interface,
+# input:
+# "eax" const unsigned char *userKey
+# $rounds int bits
+# $key AES_KEY *key
+# output:
+# "eax" return code
+# $round rounds
+
+&function_begin_B("_aesni_set_encrypt_key");
+ &test ("eax","eax");
+ &jz (&label("bad_pointer"));
+ &test ($key,$key);
+ &jz (&label("bad_pointer"));
+
+ &movups ("xmm0",&QWP(0,"eax")); # pull first 128 bits of *userKey
+ &xorps ("xmm4","xmm4"); # low dword of xmm4 is assumed 0
+ &lea ($key,&DWP(16,$key));
+ &cmp ($rounds,256);
+ &je (&label("14rounds"));
+ &cmp ($rounds,192);
+ &je (&label("12rounds"));
+ &cmp ($rounds,128);
+ &jne (&label("bad_keybits"));
+
+&set_label("10rounds",16);
+ &mov ($rounds,9);
+ &$movekey (&QWP(-16,$key),"xmm0"); # round 0
+ &aeskeygenassist("xmm1","xmm0",0x01); # round 1
+ &call (&label("key_128_cold"));
+ &aeskeygenassist("xmm1","xmm0",0x2); # round 2
+ &call (&label("key_128"));
+ &aeskeygenassist("xmm1","xmm0",0x04); # round 3
+ &call (&label("key_128"));
+ &aeskeygenassist("xmm1","xmm0",0x08); # round 4
+ &call (&label("key_128"));
+ &aeskeygenassist("xmm1","xmm0",0x10); # round 5
+ &call (&label("key_128"));
+ &aeskeygenassist("xmm1","xmm0",0x20); # round 6
+ &call (&label("key_128"));
+ &aeskeygenassist("xmm1","xmm0",0x40); # round 7
+ &call (&label("key_128"));
+ &aeskeygenassist("xmm1","xmm0",0x80); # round 8
+ &call (&label("key_128"));
+ &aeskeygenassist("xmm1","xmm0",0x1b); # round 9
+ &call (&label("key_128"));
+ &aeskeygenassist("xmm1","xmm0",0x36); # round 10
+ &call (&label("key_128"));
+ &$movekey (&QWP(0,$key),"xmm0");
+ &mov (&DWP(80,$key),$rounds);
+ &xor ("eax","eax");
+ &ret();
+
+&set_label("key_128",16);
+ &$movekey (&QWP(0,$key),"xmm0");
+ &lea ($key,&DWP(16,$key));
+&set_label("key_128_cold");
+ &shufps ("xmm4","xmm0",0b00010000);
+ &xorps ("xmm0","xmm4");
+ &shufps ("xmm4","xmm0",0b10001100);
+ &xorps ("xmm0","xmm4");
+ &shufps ("xmm1","xmm1",0b11111111); # critical path
+ &xorps ("xmm0","xmm1");
+ &ret();
+
+&set_label("12rounds",16);
+ &movq ("xmm2",&QWP(16,"eax")); # remaining 1/3 of *userKey
+ &mov ($rounds,11);
+ &$movekey (&QWP(-16,$key),"xmm0"); # round 0
+ &aeskeygenassist("xmm1","xmm2",0x01); # round 1,2
+ &call (&label("key_192a_cold"));
+ &aeskeygenassist("xmm1","xmm2",0x02); # round 2,3
+ &call (&label("key_192b"));
+ &aeskeygenassist("xmm1","xmm2",0x04); # round 4,5
+ &call (&label("key_192a"));
+ &aeskeygenassist("xmm1","xmm2",0x08); # round 5,6
+ &call (&label("key_192b"));
+ &aeskeygenassist("xmm1","xmm2",0x10); # round 7,8
+ &call (&label("key_192a"));
+ &aeskeygenassist("xmm1","xmm2",0x20); # round 8,9
+ &call (&label("key_192b"));
+ &aeskeygenassist("xmm1","xmm2",0x40); # round 10,11
+ &call (&label("key_192a"));
+ &aeskeygenassist("xmm1","xmm2",0x80); # round 11,12
+ &call (&label("key_192b"));
+ &$movekey (&QWP(0,$key),"xmm0");
+ &mov (&DWP(48,$key),$rounds);
+ &xor ("eax","eax");
+ &ret();
+
+&set_label("key_192a",16);
+ &$movekey (&QWP(0,$key),"xmm0");
+ &lea ($key,&DWP(16,$key));
+&set_label("key_192a_cold",16);
+ &movaps ("xmm5","xmm2");
+&set_label("key_192b_warm");
+ &shufps ("xmm4","xmm0",0b00010000);
+ &movdqa ("xmm3","xmm2");
+ &xorps ("xmm0","xmm4");
+ &shufps ("xmm4","xmm0",0b10001100);
+ &pslldq ("xmm3",4);
+ &xorps ("xmm0","xmm4");
+ &pshufd ("xmm1","xmm1",0b01010101); # critical path
+ &pxor ("xmm2","xmm3");
+ &pxor ("xmm0","xmm1");
+ &pshufd ("xmm3","xmm0",0b11111111);
+ &pxor ("xmm2","xmm3");
+ &ret();
+
+&set_label("key_192b",16);
+ &movaps ("xmm3","xmm0");
+ &shufps ("xmm5","xmm0",0b01000100);
+ &$movekey (&QWP(0,$key),"xmm5");
+ &shufps ("xmm3","xmm2",0b01001110);
+ &$movekey (&QWP(16,$key),"xmm3");
+ &lea ($key,&DWP(32,$key));
+ &jmp (&label("key_192b_warm"));
+
+&set_label("14rounds",16);
+ &movups ("xmm2",&QWP(16,"eax")); # remaining half of *userKey
+ &mov ($rounds,13);
+ &lea ($key,&DWP(16,$key));
+ &$movekey (&QWP(-32,$key),"xmm0"); # round 0
+ &$movekey (&QWP(-16,$key),"xmm2"); # round 1
+ &aeskeygenassist("xmm1","xmm2",0x01); # round 2
+ &call (&label("key_256a_cold"));
+ &aeskeygenassist("xmm1","xmm0",0x01); # round 3
+ &call (&label("key_256b"));
+ &aeskeygenassist("xmm1","xmm2",0x02); # round 4
+ &call (&label("key_256a"));
+ &aeskeygenassist("xmm1","xmm0",0x02); # round 5
+ &call (&label("key_256b"));
+ &aeskeygenassist("xmm1","xmm2",0x04); # round 6
+ &call (&label("key_256a"));
+ &aeskeygenassist("xmm1","xmm0",0x04); # round 7
+ &call (&label("key_256b"));
+ &aeskeygenassist("xmm1","xmm2",0x08); # round 8
+ &call (&label("key_256a"));
+ &aeskeygenassist("xmm1","xmm0",0x08); # round 9
+ &call (&label("key_256b"));
+ &aeskeygenassist("xmm1","xmm2",0x10); # round 10
+ &call (&label("key_256a"));
+ &aeskeygenassist("xmm1","xmm0",0x10); # round 11
+ &call (&label("key_256b"));
+ &aeskeygenassist("xmm1","xmm2",0x20); # round 12
+ &call (&label("key_256a"));
+ &aeskeygenassist("xmm1","xmm0",0x20); # round 13
+ &call (&label("key_256b"));
+ &aeskeygenassist("xmm1","xmm2",0x40); # round 14
+ &call (&label("key_256a"));
+ &$movekey (&QWP(0,$key),"xmm0");
+ &mov (&DWP(16,$key),$rounds);
+ &xor ("eax","eax");
+ &ret();
+
+&set_label("key_256a",16);
+ &$movekey (&QWP(0,$key),"xmm2");
+ &lea ($key,&DWP(16,$key));
+&set_label("key_256a_cold");
+ &shufps ("xmm4","xmm0",0b00010000);
+ &xorps ("xmm0","xmm4");
+ &shufps ("xmm4","xmm0",0b10001100);
+ &xorps ("xmm0","xmm4");
+ &shufps ("xmm1","xmm1",0b11111111); # critical path
+ &xorps ("xmm0","xmm1");
+ &ret();
+
+&set_label("key_256b",16);
+ &$movekey (&QWP(0,$key),"xmm0");
+ &lea ($key,&DWP(16,$key));
+
+ &shufps ("xmm4","xmm2",0b00010000);
+ &xorps ("xmm2","xmm4");
+ &shufps ("xmm4","xmm2",0b10001100);
+ &xorps ("xmm2","xmm4");
+ &shufps ("xmm1","xmm1",0b10101010); # critical path
+ &xorps ("xmm2","xmm1");
+ &ret();
+
+&set_label("bad_pointer",4);
+ &mov ("eax",-1);
+ &ret ();
+&set_label("bad_keybits",4);
+ &mov ("eax",-2);
+ &ret ();
+&function_end_B("_aesni_set_encrypt_key");
+
+# int $PREFIX_set_encrypt_key (const unsigned char *userKey, int bits,
+# AES_KEY *key)
+&function_begin_B("${PREFIX}_set_encrypt_key");
+ &mov ("eax",&wparam(0));
+ &mov ($rounds,&wparam(1));
+ &mov ($key,&wparam(2));
+ &call ("_aesni_set_encrypt_key");
+ &ret ();
+&function_end_B("${PREFIX}_set_encrypt_key");
+
+# int $PREFIX_set_decrypt_key (const unsigned char *userKey, int bits,
+# AES_KEY *key)
+&function_begin_B("${PREFIX}_set_decrypt_key");
+ &mov ("eax",&wparam(0));
+ &mov ($rounds,&wparam(1));
+ &mov ($key,&wparam(2));
+ &call ("_aesni_set_encrypt_key");
+ &mov ($key,&wparam(2));
+ &shl ($rounds,4); # rounds-1 after _aesni_set_encrypt_key
+ &test ("eax","eax");
+ &jnz (&label("dec_key_ret"));
+ &lea ("eax",&DWP(16,$key,$rounds)); # end of key schedule
+
+ &$movekey ("xmm0",&QWP(0,$key)); # just swap
+ &$movekey ("xmm1",&QWP(0,"eax"));
+ &$movekey (&QWP(0,"eax"),"xmm0");
+ &$movekey (&QWP(0,$key),"xmm1");
+ &lea ($key,&DWP(16,$key));
+ &lea ("eax",&DWP(-16,"eax"));
+
+&set_label("dec_key_inverse");
+ &$movekey ("xmm0",&QWP(0,$key)); # swap and inverse
+ &$movekey ("xmm1",&QWP(0,"eax"));
+ &aesimc ("xmm0","xmm0");
+ &aesimc ("xmm1","xmm1");
+ &lea ($key,&DWP(16,$key));
+ &lea ("eax",&DWP(-16,"eax"));
+ &$movekey (&QWP(16,"eax"),"xmm0");
+ &$movekey (&QWP(-16,$key),"xmm1");
+ &cmp ("eax",$key);
+ &ja (&label("dec_key_inverse"));
+
+ &$movekey ("xmm0",&QWP(0,$key)); # inverse middle
+ &aesimc ("xmm0","xmm0");
+ &$movekey (&QWP(0,$key),"xmm0");
+
+ &xor ("eax","eax"); # return success
+&set_label("dec_key_ret");
+ &ret ();
+&function_end_B("${PREFIX}_set_decrypt_key");
+&asciz("AES for Intel AES-NI, CRYPTOGAMS by <appro\@openssl.org>");
+
+&asm_finish();
diff --git a/src/crypto/aes/asm/aesni-x86_64.pl b/src/crypto/aes/asm/aesni-x86_64.pl
new file mode 100644
index 0000000..5f61746
--- /dev/null
+++ b/src/crypto/aes/asm/aesni-x86_64.pl
@@ -0,0 +1,3555 @@
+#!/usr/bin/env perl
+#
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+# project. The module is, however, dual licensed under OpenSSL and
+# CRYPTOGAMS licenses depending on where you obtain it. For further
+# details see http://www.openssl.org/~appro/cryptogams/.
+# ====================================================================
+#
+# This module implements support for Intel AES-NI extension. In
+# OpenSSL context it's used with Intel engine, but can also be used as
+# drop-in replacement for crypto/aes/asm/aes-x86_64.pl [see below for
+# details].
+#
+# Performance.
+#
+# Given aes(enc|dec) instructions' latency asymptotic performance for
+# non-parallelizable modes such as CBC encrypt is 3.75 cycles per byte
+# processed with 128-bit key. And given their throughput asymptotic
+# performance for parallelizable modes is 1.25 cycles per byte. Being
+# asymptotic limit it's not something you commonly achieve in reality,
+# but how close does one get? Below are results collected for
+# different modes and block sized. Pairs of numbers are for en-/
+# decryption.
+#
+# 16-byte 64-byte 256-byte 1-KB 8-KB
+# ECB 4.25/4.25 1.38/1.38 1.28/1.28 1.26/1.26 1.26/1.26
+# CTR 5.42/5.42 1.92/1.92 1.44/1.44 1.28/1.28 1.26/1.26
+# CBC 4.38/4.43 4.15/1.43 4.07/1.32 4.07/1.29 4.06/1.28
+# CCM 5.66/9.42 4.42/5.41 4.16/4.40 4.09/4.15 4.06/4.07
+# OFB 5.42/5.42 4.64/4.64 4.44/4.44 4.39/4.39 4.38/4.38
+# CFB 5.73/5.85 5.56/5.62 5.48/5.56 5.47/5.55 5.47/5.55
+#
+# ECB, CTR, CBC and CCM results are free from EVP overhead. This means
+# that otherwise used 'openssl speed -evp aes-128-??? -engine aesni
+# [-decrypt]' will exhibit 10-15% worse results for smaller blocks.
+# The results were collected with specially crafted speed.c benchmark
+# in order to compare them with results reported in "Intel Advanced
+# Encryption Standard (AES) New Instruction Set" White Paper Revision
+# 3.0 dated May 2010. All above results are consistently better. This
+# module also provides better performance for block sizes smaller than
+# 128 bytes in points *not* represented in the above table.
+#
+# Looking at the results for 8-KB buffer.
+#
+# CFB and OFB results are far from the limit, because implementation
+# uses "generic" CRYPTO_[c|o]fb128_encrypt interfaces relying on
+# single-block aesni_encrypt, which is not the most optimal way to go.
+# CBC encrypt result is unexpectedly high and there is no documented
+# explanation for it. Seemingly there is a small penalty for feeding
+# the result back to AES unit the way it's done in CBC mode. There is
+# nothing one can do and the result appears optimal. CCM result is
+# identical to CBC, because CBC-MAC is essentially CBC encrypt without
+# saving output. CCM CTR "stays invisible," because it's neatly
+# interleaved wih CBC-MAC. This provides ~30% improvement over
+# "straghtforward" CCM implementation with CTR and CBC-MAC performed
+# disjointly. Parallelizable modes practically achieve the theoretical
+# limit.
+#
+# Looking at how results vary with buffer size.
+#
+# Curves are practically saturated at 1-KB buffer size. In most cases
+# "256-byte" performance is >95%, and "64-byte" is ~90% of "8-KB" one.
+# CTR curve doesn't follow this pattern and is "slowest" changing one
+# with "256-byte" result being 87% of "8-KB." This is because overhead
+# in CTR mode is most computationally intensive. Small-block CCM
+# decrypt is slower than encrypt, because first CTR and last CBC-MAC
+# iterations can't be interleaved.
+#
+# Results for 192- and 256-bit keys.
+#
+# EVP-free results were observed to scale perfectly with number of
+# rounds for larger block sizes, i.e. 192-bit result being 10/12 times
+# lower and 256-bit one - 10/14. Well, in CBC encrypt case differences
+# are a tad smaller, because the above mentioned penalty biases all
+# results by same constant value. In similar way function call
+# overhead affects small-block performance, as well as OFB and CFB
+# results. Differences are not large, most common coefficients are
+# 10/11.7 and 10/13.4 (as opposite to 10/12.0 and 10/14.0), but one
+# observe even 10/11.2 and 10/12.4 (CTR, OFB, CFB)...
+
+# January 2011
+#
+# While Westmere processor features 6 cycles latency for aes[enc|dec]
+# instructions, which can be scheduled every second cycle, Sandy
+# Bridge spends 8 cycles per instruction, but it can schedule them
+# every cycle. This means that code targeting Westmere would perform
+# suboptimally on Sandy Bridge. Therefore this update.
+#
+# In addition, non-parallelizable CBC encrypt (as well as CCM) is
+# optimized. Relative improvement might appear modest, 8% on Westmere,
+# but in absolute terms it's 3.77 cycles per byte encrypted with
+# 128-bit key on Westmere, and 5.07 - on Sandy Bridge. These numbers
+# should be compared to asymptotic limits of 3.75 for Westmere and
+# 5.00 for Sandy Bridge. Actually, the fact that they get this close
+# to asymptotic limits is quite amazing. Indeed, the limit is
+# calculated as latency times number of rounds, 10 for 128-bit key,
+# and divided by 16, the number of bytes in block, or in other words
+# it accounts *solely* for aesenc instructions. But there are extra
+# instructions, and numbers so close to the asymptotic limits mean
+# that it's as if it takes as little as *one* additional cycle to
+# execute all of them. How is it possible? It is possible thanks to
+# out-of-order execution logic, which manages to overlap post-
+# processing of previous block, things like saving the output, with
+# actual encryption of current block, as well as pre-processing of
+# current block, things like fetching input and xor-ing it with
+# 0-round element of the key schedule, with actual encryption of
+# previous block. Keep this in mind...
+#
+# For parallelizable modes, such as ECB, CBC decrypt, CTR, higher
+# performance is achieved by interleaving instructions working on
+# independent blocks. In which case asymptotic limit for such modes
+# can be obtained by dividing above mentioned numbers by AES
+# instructions' interleave factor. Westmere can execute at most 3
+# instructions at a time, meaning that optimal interleave factor is 3,
+# and that's where the "magic" number of 1.25 come from. "Optimal
+# interleave factor" means that increase of interleave factor does
+# not improve performance. The formula has proven to reflect reality
+# pretty well on Westmere... Sandy Bridge on the other hand can
+# execute up to 8 AES instructions at a time, so how does varying
+# interleave factor affect the performance? Here is table for ECB
+# (numbers are cycles per byte processed with 128-bit key):
+#
+# instruction interleave factor 3x 6x 8x
+# theoretical asymptotic limit 1.67 0.83 0.625
+# measured performance for 8KB block 1.05 0.86 0.84
+#
+# "as if" interleave factor 4.7x 5.8x 6.0x
+#
+# Further data for other parallelizable modes:
+#
+# CBC decrypt 1.16 0.93 0.74
+# CTR 1.14 0.91 0.74
+#
+# Well, given 3x column it's probably inappropriate to call the limit
+# asymptotic, if it can be surpassed, isn't it? What happens there?
+# Rewind to CBC paragraph for the answer. Yes, out-of-order execution
+# magic is responsible for this. Processor overlaps not only the
+# additional instructions with AES ones, but even AES instuctions
+# processing adjacent triplets of independent blocks. In the 6x case
+# additional instructions still claim disproportionally small amount
+# of additional cycles, but in 8x case number of instructions must be
+# a tad too high for out-of-order logic to cope with, and AES unit
+# remains underutilized... As you can see 8x interleave is hardly
+# justifiable, so there no need to feel bad that 32-bit aesni-x86.pl
+# utilizies 6x interleave because of limited register bank capacity.
+#
+# Higher interleave factors do have negative impact on Westmere
+# performance. While for ECB mode it's negligible ~1.5%, other
+# parallelizables perform ~5% worse, which is outweighed by ~25%
+# improvement on Sandy Bridge. To balance regression on Westmere
+# CTR mode was implemented with 6x aesenc interleave factor.
+
+# April 2011
+#
+# Add aesni_xts_[en|de]crypt. Westmere spends 1.25 cycles processing
+# one byte out of 8KB with 128-bit key, Sandy Bridge - 0.90. Just like
+# in CTR mode AES instruction interleave factor was chosen to be 6x.
+
+######################################################################
+# Current large-block performance in cycles per byte processed with
+# 128-bit key (less is better).
+#
+# CBC en-/decrypt CTR XTS ECB
+# Westmere 3.77/1.25 1.25 1.25 1.26
+# * Bridge 5.07/0.74 0.75 0.90 0.85
+# Haswell 4.44/0.63 0.63 0.73 0.63
+# Atom 5.75/3.54 3.56 4.12 3.87(*)
+# Bulldozer 5.77/0.70 0.72 0.90 0.70
+#
+# (*) Atom ECB result is suboptimal because of penalties incurred
+# by operations on %xmm8-15. As ECB is not considered
+# critical, nothing was done to mitigate the problem.
+
+$PREFIX="aesni"; # if $PREFIX is set to "AES", the script
+ # generates drop-in replacement for
+ # crypto/aes/asm/aes-x86_64.pl:-)
+
+$flavour = shift;
+$output = shift;
+if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+
+$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
+( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
+die "can't locate x86_64-xlate.pl";
+
+open OUT,"| \"$^X\" $xlate $flavour $output";
+*STDOUT=*OUT;
+
+$movkey = $PREFIX eq "aesni" ? "movups" : "movups";
+@_4args=$win64? ("%rcx","%rdx","%r8", "%r9") : # Win64 order
+ ("%rdi","%rsi","%rdx","%rcx"); # Unix order
+
+$code=".text\n";
+$code.=".extern OPENSSL_ia32cap_P\n";
+
+$rounds="%eax"; # input to and changed by aesni_[en|de]cryptN !!!
+# this is natural Unix argument order for public $PREFIX_[ecb|cbc]_encrypt ...
+$inp="%rdi";
+$out="%rsi";
+$len="%rdx";
+$key="%rcx"; # input to and changed by aesni_[en|de]cryptN !!!
+$ivp="%r8"; # cbc, ctr, ...
+
+$rnds_="%r10d"; # backup copy for $rounds
+$key_="%r11"; # backup copy for $key
+
+# %xmm register layout
+$rndkey0="%xmm0"; $rndkey1="%xmm1";
+$inout0="%xmm2"; $inout1="%xmm3";
+$inout2="%xmm4"; $inout3="%xmm5";
+$inout4="%xmm6"; $inout5="%xmm7";
+$inout6="%xmm8"; $inout7="%xmm9";
+
+$in2="%xmm6"; $in1="%xmm7"; # used in CBC decrypt, CTR, ...
+$in0="%xmm8"; $iv="%xmm9";
+
+# Inline version of internal aesni_[en|de]crypt1.
+#
+# Why folded loop? Because aes[enc|dec] is slow enough to accommodate
+# cycles which take care of loop variables...
+{ my $sn;
+sub aesni_generate1 {
+my ($p,$key,$rounds,$inout,$ivec)=@_; $inout=$inout0 if (!defined($inout));
+++$sn;
+$code.=<<___;
+ $movkey ($key),$rndkey0
+ $movkey 16($key),$rndkey1
+___
+$code.=<<___ if (defined($ivec));
+ xorps $rndkey0,$ivec
+ lea 32($key),$key
+ xorps $ivec,$inout
+___
+$code.=<<___ if (!defined($ivec));
+ lea 32($key),$key
+ xorps $rndkey0,$inout
+___
+$code.=<<___;
+.Loop_${p}1_$sn:
+ aes${p} $rndkey1,$inout
+ dec $rounds
+ $movkey ($key),$rndkey1
+ lea 16($key),$key
+ jnz .Loop_${p}1_$sn # loop body is 16 bytes
+ aes${p}last $rndkey1,$inout
+___
+}}
+# void $PREFIX_[en|de]crypt (const void *inp,void *out,const AES_KEY *key);
+#
+{ my ($inp,$out,$key) = @_4args;
+
+$code.=<<___;
+.globl ${PREFIX}_encrypt
+.type ${PREFIX}_encrypt,\@abi-omnipotent
+.align 16
+${PREFIX}_encrypt:
+ movups ($inp),$inout0 # load input
+ mov 240($key),$rounds # key->rounds
+___
+ &aesni_generate1("enc",$key,$rounds);
+$code.=<<___;
+ movups $inout0,($out) # output
+ ret
+.size ${PREFIX}_encrypt,.-${PREFIX}_encrypt
+
+.globl ${PREFIX}_decrypt
+.type ${PREFIX}_decrypt,\@abi-omnipotent
+.align 16
+${PREFIX}_decrypt:
+ movups ($inp),$inout0 # load input
+ mov 240($key),$rounds # key->rounds
+___
+ &aesni_generate1("dec",$key,$rounds);
+$code.=<<___;
+ movups $inout0,($out) # output
+ ret
+.size ${PREFIX}_decrypt, .-${PREFIX}_decrypt
+___
+}
+
+# _aesni_[en|de]cryptN are private interfaces, N denotes interleave
+# factor. Why 3x subroutine were originally used in loops? Even though
+# aes[enc|dec] latency was originally 6, it could be scheduled only
+# every *2nd* cycle. Thus 3x interleave was the one providing optimal
+# utilization, i.e. when subroutine's throughput is virtually same as
+# of non-interleaved subroutine [for number of input blocks up to 3].
+# This is why it originally made no sense to implement 2x subroutine.
+# But times change and it became appropriate to spend extra 192 bytes
+# on 2x subroutine on Atom Silvermont account. For processors that
+# can schedule aes[enc|dec] every cycle optimal interleave factor
+# equals to corresponding instructions latency. 8x is optimal for
+# * Bridge and "super-optimal" for other Intel CPUs...
+
+sub aesni_generate2 {
+my $dir=shift;
+# As already mentioned it takes in $key and $rounds, which are *not*
+# preserved. $inout[0-1] is cipher/clear text...
+$code.=<<___;
+.type _aesni_${dir}rypt2,\@abi-omnipotent
+.align 16
+_aesni_${dir}rypt2:
+ $movkey ($key),$rndkey0
+ shl \$4,$rounds
+ $movkey 16($key),$rndkey1
+ xorps $rndkey0,$inout0
+ xorps $rndkey0,$inout1
+ $movkey 32($key),$rndkey0
+ lea 32($key,$rounds),$key
+ neg %rax # $rounds
+ add \$16,%rax
+
+.L${dir}_loop2:
+ aes${dir} $rndkey1,$inout0
+ aes${dir} $rndkey1,$inout1
+ $movkey ($key,%rax),$rndkey1
+ add \$32,%rax
+ aes${dir} $rndkey0,$inout0
+ aes${dir} $rndkey0,$inout1
+ $movkey -16($key,%rax),$rndkey0
+ jnz .L${dir}_loop2
+
+ aes${dir} $rndkey1,$inout0
+ aes${dir} $rndkey1,$inout1
+ aes${dir}last $rndkey0,$inout0
+ aes${dir}last $rndkey0,$inout1
+ ret
+.size _aesni_${dir}rypt2,.-_aesni_${dir}rypt2
+___
+}
+sub aesni_generate3 {
+my $dir=shift;
+# As already mentioned it takes in $key and $rounds, which are *not*
+# preserved. $inout[0-2] is cipher/clear text...
+$code.=<<___;
+.type _aesni_${dir}rypt3,\@abi-omnipotent
+.align 16
+_aesni_${dir}rypt3:
+ $movkey ($key),$rndkey0
+ shl \$4,$rounds
+ $movkey 16($key),$rndkey1
+ xorps $rndkey0,$inout0
+ xorps $rndkey0,$inout1
+ xorps $rndkey0,$inout2
+ $movkey 32($key),$rndkey0
+ lea 32($key,$rounds),$key
+ neg %rax # $rounds
+ add \$16,%rax
+
+.L${dir}_loop3:
+ aes${dir} $rndkey1,$inout0
+ aes${dir} $rndkey1,$inout1
+ aes${dir} $rndkey1,$inout2
+ $movkey ($key,%rax),$rndkey1
+ add \$32,%rax
+ aes${dir} $rndkey0,$inout0
+ aes${dir} $rndkey0,$inout1
+ aes${dir} $rndkey0,$inout2
+ $movkey -16($key,%rax),$rndkey0
+ jnz .L${dir}_loop3
+
+ aes${dir} $rndkey1,$inout0
+ aes${dir} $rndkey1,$inout1
+ aes${dir} $rndkey1,$inout2
+ aes${dir}last $rndkey0,$inout0
+ aes${dir}last $rndkey0,$inout1
+ aes${dir}last $rndkey0,$inout2
+ ret
+.size _aesni_${dir}rypt3,.-_aesni_${dir}rypt3
+___
+}
+# 4x interleave is implemented to improve small block performance,
+# most notably [and naturally] 4 block by ~30%. One can argue that one
+# should have implemented 5x as well, but improvement would be <20%,
+# so it's not worth it...
+sub aesni_generate4 {
+my $dir=shift;
+# As already mentioned it takes in $key and $rounds, which are *not*
+# preserved. $inout[0-3] is cipher/clear text...
+$code.=<<___;
+.type _aesni_${dir}rypt4,\@abi-omnipotent
+.align 16
+_aesni_${dir}rypt4:
+ $movkey ($key),$rndkey0
+ shl \$4,$rounds
+ $movkey 16($key),$rndkey1
+ xorps $rndkey0,$inout0
+ xorps $rndkey0,$inout1
+ xorps $rndkey0,$inout2
+ xorps $rndkey0,$inout3
+ $movkey 32($key),$rndkey0
+ lea 32($key,$rounds),$key
+ neg %rax # $rounds
+ .byte 0x0f,0x1f,0x00
+ add \$16,%rax
+
+.L${dir}_loop4:
+ aes${dir} $rndkey1,$inout0
+ aes${dir} $rndkey1,$inout1
+ aes${dir} $rndkey1,$inout2
+ aes${dir} $rndkey1,$inout3
+ $movkey ($key,%rax),$rndkey1
+ add \$32,%rax
+ aes${dir} $rndkey0,$inout0
+ aes${dir} $rndkey0,$inout1
+ aes${dir} $rndkey0,$inout2
+ aes${dir} $rndkey0,$inout3
+ $movkey -16($key,%rax),$rndkey0
+ jnz .L${dir}_loop4
+
+ aes${dir} $rndkey1,$inout0
+ aes${dir} $rndkey1,$inout1
+ aes${dir} $rndkey1,$inout2
+ aes${dir} $rndkey1,$inout3
+ aes${dir}last $rndkey0,$inout0
+ aes${dir}last $rndkey0,$inout1
+ aes${dir}last $rndkey0,$inout2
+ aes${dir}last $rndkey0,$inout3
+ ret
+.size _aesni_${dir}rypt4,.-_aesni_${dir}rypt4
+___
+}
+sub aesni_generate6 {
+my $dir=shift;
+# As already mentioned it takes in $key and $rounds, which are *not*
+# preserved. $inout[0-5] is cipher/clear text...
+$code.=<<___;
+.type _aesni_${dir}rypt6,\@abi-omnipotent
+.align 16
+_aesni_${dir}rypt6:
+ $movkey ($key),$rndkey0
+ shl \$4,$rounds
+ $movkey 16($key),$rndkey1
+ xorps $rndkey0,$inout0
+ pxor $rndkey0,$inout1
+ pxor $rndkey0,$inout2
+ aes${dir} $rndkey1,$inout0
+ lea 32($key,$rounds),$key
+ neg %rax # $rounds
+ aes${dir} $rndkey1,$inout1
+ pxor $rndkey0,$inout3
+ pxor $rndkey0,$inout4
+ aes${dir} $rndkey1,$inout2
+ pxor $rndkey0,$inout5
+ add \$16,%rax
+ aes${dir} $rndkey1,$inout3
+ aes${dir} $rndkey1,$inout4
+ aes${dir} $rndkey1,$inout5
+ $movkey -16($key,%rax),$rndkey0
+ jmp .L${dir}_loop6_enter
+.align 16
+.L${dir}_loop6:
+ aes${dir} $rndkey1,$inout0
+ aes${dir} $rndkey1,$inout1
+ aes${dir} $rndkey1,$inout2
+ aes${dir} $rndkey1,$inout3
+ aes${dir} $rndkey1,$inout4
+ aes${dir} $rndkey1,$inout5
+.L${dir}_loop6_enter:
+ $movkey ($key,%rax),$rndkey1
+ add \$32,%rax
+ aes${dir} $rndkey0,$inout0
+ aes${dir} $rndkey0,$inout1
+ aes${dir} $rndkey0,$inout2
+ aes${dir} $rndkey0,$inout3
+ aes${dir} $rndkey0,$inout4
+ aes${dir} $rndkey0,$inout5
+ $movkey -16($key,%rax),$rndkey0
+ jnz .L${dir}_loop6
+
+ aes${dir} $rndkey1,$inout0
+ aes${dir} $rndkey1,$inout1
+ aes${dir} $rndkey1,$inout2
+ aes${dir} $rndkey1,$inout3
+ aes${dir} $rndkey1,$inout4
+ aes${dir} $rndkey1,$inout5
+ aes${dir}last $rndkey0,$inout0
+ aes${dir}last $rndkey0,$inout1
+ aes${dir}last $rndkey0,$inout2
+ aes${dir}last $rndkey0,$inout3
+ aes${dir}last $rndkey0,$inout4
+ aes${dir}last $rndkey0,$inout5
+ ret
+.size _aesni_${dir}rypt6,.-_aesni_${dir}rypt6
+___
+}
+sub aesni_generate8 {
+my $dir=shift;
+# As already mentioned it takes in $key and $rounds, which are *not*
+# preserved. $inout[0-7] is cipher/clear text...
+$code.=<<___;
+.type _aesni_${dir}rypt8,\@abi-omnipotent
+.align 16
+_aesni_${dir}rypt8:
+ $movkey ($key),$rndkey0
+ shl \$4,$rounds
+ $movkey 16($key),$rndkey1
+ xorps $rndkey0,$inout0
+ xorps $rndkey0,$inout1
+ pxor $rndkey0,$inout2
+ pxor $rndkey0,$inout3
+ pxor $rndkey0,$inout4
+ lea 32($key,$rounds),$key
+ neg %rax # $rounds
+ aes${dir} $rndkey1,$inout0
+ add \$16,%rax
+ pxor $rndkey0,$inout5
+ aes${dir} $rndkey1,$inout1
+ pxor $rndkey0,$inout6
+ pxor $rndkey0,$inout7
+ aes${dir} $rndkey1,$inout2
+ aes${dir} $rndkey1,$inout3
+ aes${dir} $rndkey1,$inout4
+ aes${dir} $rndkey1,$inout5
+ aes${dir} $rndkey1,$inout6
+ aes${dir} $rndkey1,$inout7
+ $movkey -16($key,%rax),$rndkey0
+ jmp .L${dir}_loop8_enter
+.align 16
+.L${dir}_loop8:
+ aes${dir} $rndkey1,$inout0
+ aes${dir} $rndkey1,$inout1
+ aes${dir} $rndkey1,$inout2
+ aes${dir} $rndkey1,$inout3
+ aes${dir} $rndkey1,$inout4
+ aes${dir} $rndkey1,$inout5
+ aes${dir} $rndkey1,$inout6
+ aes${dir} $rndkey1,$inout7
+.L${dir}_loop8_enter:
+ $movkey ($key,%rax),$rndkey1
+ add \$32,%rax
+ aes${dir} $rndkey0,$inout0
+ aes${dir} $rndkey0,$inout1
+ aes${dir} $rndkey0,$inout2
+ aes${dir} $rndkey0,$inout3
+ aes${dir} $rndkey0,$inout4
+ aes${dir} $rndkey0,$inout5
+ aes${dir} $rndkey0,$inout6
+ aes${dir} $rndkey0,$inout7
+ $movkey -16($key,%rax),$rndkey0
+ jnz .L${dir}_loop8
+
+ aes${dir} $rndkey1,$inout0
+ aes${dir} $rndkey1,$inout1
+ aes${dir} $rndkey1,$inout2
+ aes${dir} $rndkey1,$inout3
+ aes${dir} $rndkey1,$inout4
+ aes${dir} $rndkey1,$inout5
+ aes${dir} $rndkey1,$inout6
+ aes${dir} $rndkey1,$inout7
+ aes${dir}last $rndkey0,$inout0
+ aes${dir}last $rndkey0,$inout1
+ aes${dir}last $rndkey0,$inout2
+ aes${dir}last $rndkey0,$inout3
+ aes${dir}last $rndkey0,$inout4
+ aes${dir}last $rndkey0,$inout5
+ aes${dir}last $rndkey0,$inout6
+ aes${dir}last $rndkey0,$inout7
+ ret
+.size _aesni_${dir}rypt8,.-_aesni_${dir}rypt8
+___
+}
+&aesni_generate2("enc") if ($PREFIX eq "aesni");
+&aesni_generate2("dec");
+&aesni_generate3("enc") if ($PREFIX eq "aesni");
+&aesni_generate3("dec");
+&aesni_generate4("enc") if ($PREFIX eq "aesni");
+&aesni_generate4("dec");
+&aesni_generate6("enc") if ($PREFIX eq "aesni");
+&aesni_generate6("dec");
+&aesni_generate8("enc") if ($PREFIX eq "aesni");
+&aesni_generate8("dec");
+
+if ($PREFIX eq "aesni") {
+########################################################################
+# void aesni_ecb_encrypt (const void *in, void *out,
+# size_t length, const AES_KEY *key,
+# int enc);
+$code.=<<___;
+.globl aesni_ecb_encrypt
+.type aesni_ecb_encrypt,\@function,5
+.align 16
+aesni_ecb_encrypt:
+___
+$code.=<<___ if ($win64);
+ lea -0x58(%rsp),%rsp
+ movaps %xmm6,(%rsp)
+ movaps %xmm7,0x10(%rsp)
+ movaps %xmm8,0x20(%rsp)
+ movaps %xmm9,0x30(%rsp)
+.Lecb_enc_body:
+___
+$code.=<<___;
+ and \$-16,$len
+ jz .Lecb_ret
+
+ mov 240($key),$rounds # key->rounds
+ $movkey ($key),$rndkey0
+ mov $key,$key_ # backup $key
+ mov $rounds,$rnds_ # backup $rounds
+ test %r8d,%r8d # 5th argument
+ jz .Lecb_decrypt
+#--------------------------- ECB ENCRYPT ------------------------------#
+ cmp \$0x80,$len
+ jb .Lecb_enc_tail
+
+ movdqu ($inp),$inout0
+ movdqu 0x10($inp),$inout1
+ movdqu 0x20($inp),$inout2
+ movdqu 0x30($inp),$inout3
+ movdqu 0x40($inp),$inout4
+ movdqu 0x50($inp),$inout5
+ movdqu 0x60($inp),$inout6
+ movdqu 0x70($inp),$inout7
+ lea 0x80($inp),$inp
+ sub \$0x80,$len
+ jmp .Lecb_enc_loop8_enter
+.align 16
+.Lecb_enc_loop8:
+ movups $inout0,($out)
+ mov $key_,$key # restore $key
+ movdqu ($inp),$inout0
+ mov $rnds_,$rounds # restore $rounds
+ movups $inout1,0x10($out)
+ movdqu 0x10($inp),$inout1
+ movups $inout2,0x20($out)
+ movdqu 0x20($inp),$inout2
+ movups $inout3,0x30($out)
+ movdqu 0x30($inp),$inout3
+ movups $inout4,0x40($out)
+ movdqu 0x40($inp),$inout4
+ movups $inout5,0x50($out)
+ movdqu 0x50($inp),$inout5
+ movups $inout6,0x60($out)
+ movdqu 0x60($inp),$inout6
+ movups $inout7,0x70($out)
+ lea 0x80($out),$out
+ movdqu 0x70($inp),$inout7
+ lea 0x80($inp),$inp
+.Lecb_enc_loop8_enter:
+
+ call _aesni_encrypt8
+
+ sub \$0x80,$len
+ jnc .Lecb_enc_loop8
+
+ movups $inout0,($out)
+ mov $key_,$key # restore $key
+ movups $inout1,0x10($out)
+ mov $rnds_,$rounds # restore $rounds
+ movups $inout2,0x20($out)
+ movups $inout3,0x30($out)
+ movups $inout4,0x40($out)
+ movups $inout5,0x50($out)
+ movups $inout6,0x60($out)
+ movups $inout7,0x70($out)
+ lea 0x80($out),$out
+ add \$0x80,$len
+ jz .Lecb_ret
+
+.Lecb_enc_tail:
+ movups ($inp),$inout0
+ cmp \$0x20,$len
+ jb .Lecb_enc_one
+ movups 0x10($inp),$inout1
+ je .Lecb_enc_two
+ movups 0x20($inp),$inout2
+ cmp \$0x40,$len
+ jb .Lecb_enc_three
+ movups 0x30($inp),$inout3
+ je .Lecb_enc_four
+ movups 0x40($inp),$inout4
+ cmp \$0x60,$len
+ jb .Lecb_enc_five
+ movups 0x50($inp),$inout5
+ je .Lecb_enc_six
+ movdqu 0x60($inp),$inout6
+ call _aesni_encrypt8
+ movups $inout0,($out)
+ movups $inout1,0x10($out)
+ movups $inout2,0x20($out)
+ movups $inout3,0x30($out)
+ movups $inout4,0x40($out)
+ movups $inout5,0x50($out)
+ movups $inout6,0x60($out)
+ jmp .Lecb_ret
+.align 16
+.Lecb_enc_one:
+___
+ &aesni_generate1("enc",$key,$rounds);
+$code.=<<___;
+ movups $inout0,($out)
+ jmp .Lecb_ret
+.align 16
+.Lecb_enc_two:
+ call _aesni_encrypt2
+ movups $inout0,($out)
+ movups $inout1,0x10($out)
+ jmp .Lecb_ret
+.align 16
+.Lecb_enc_three:
+ call _aesni_encrypt3
+ movups $inout0,($out)
+ movups $inout1,0x10($out)
+ movups $inout2,0x20($out)
+ jmp .Lecb_ret
+.align 16
+.Lecb_enc_four:
+ call _aesni_encrypt4
+ movups $inout0,($out)
+ movups $inout1,0x10($out)
+ movups $inout2,0x20($out)
+ movups $inout3,0x30($out)
+ jmp .Lecb_ret
+.align 16
+.Lecb_enc_five:
+ xorps $inout5,$inout5
+ call _aesni_encrypt6
+ movups $inout0,($out)
+ movups $inout1,0x10($out)
+ movups $inout2,0x20($out)
+ movups $inout3,0x30($out)
+ movups $inout4,0x40($out)
+ jmp .Lecb_ret
+.align 16
+.Lecb_enc_six:
+ call _aesni_encrypt6
+ movups $inout0,($out)
+ movups $inout1,0x10($out)
+ movups $inout2,0x20($out)
+ movups $inout3,0x30($out)
+ movups $inout4,0x40($out)
+ movups $inout5,0x50($out)
+ jmp .Lecb_ret
+ #--------------------------- ECB DECRYPT ------------------------------#
+.align 16
+.Lecb_decrypt:
+ cmp \$0x80,$len
+ jb .Lecb_dec_tail
+
+ movdqu ($inp),$inout0
+ movdqu 0x10($inp),$inout1
+ movdqu 0x20($inp),$inout2
+ movdqu 0x30($inp),$inout3
+ movdqu 0x40($inp),$inout4
+ movdqu 0x50($inp),$inout5
+ movdqu 0x60($inp),$inout6
+ movdqu 0x70($inp),$inout7
+ lea 0x80($inp),$inp
+ sub \$0x80,$len
+ jmp .Lecb_dec_loop8_enter
+.align 16
+.Lecb_dec_loop8:
+ movups $inout0,($out)
+ mov $key_,$key # restore $key
+ movdqu ($inp),$inout0
+ mov $rnds_,$rounds # restore $rounds
+ movups $inout1,0x10($out)
+ movdqu 0x10($inp),$inout1
+ movups $inout2,0x20($out)
+ movdqu 0x20($inp),$inout2
+ movups $inout3,0x30($out)
+ movdqu 0x30($inp),$inout3
+ movups $inout4,0x40($out)
+ movdqu 0x40($inp),$inout4
+ movups $inout5,0x50($out)
+ movdqu 0x50($inp),$inout5
+ movups $inout6,0x60($out)
+ movdqu 0x60($inp),$inout6
+ movups $inout7,0x70($out)
+ lea 0x80($out),$out
+ movdqu 0x70($inp),$inout7
+ lea 0x80($inp),$inp
+.Lecb_dec_loop8_enter:
+
+ call _aesni_decrypt8
+
+ $movkey ($key_),$rndkey0
+ sub \$0x80,$len
+ jnc .Lecb_dec_loop8
+
+ movups $inout0,($out)
+ mov $key_,$key # restore $key
+ movups $inout1,0x10($out)
+ mov $rnds_,$rounds # restore $rounds
+ movups $inout2,0x20($out)
+ movups $inout3,0x30($out)
+ movups $inout4,0x40($out)
+ movups $inout5,0x50($out)
+ movups $inout6,0x60($out)
+ movups $inout7,0x70($out)
+ lea 0x80($out),$out
+ add \$0x80,$len
+ jz .Lecb_ret
+
+.Lecb_dec_tail:
+ movups ($inp),$inout0
+ cmp \$0x20,$len
+ jb .Lecb_dec_one
+ movups 0x10($inp),$inout1
+ je .Lecb_dec_two
+ movups 0x20($inp),$inout2
+ cmp \$0x40,$len
+ jb .Lecb_dec_three
+ movups 0x30($inp),$inout3
+ je .Lecb_dec_four
+ movups 0x40($inp),$inout4
+ cmp \$0x60,$len
+ jb .Lecb_dec_five
+ movups 0x50($inp),$inout5
+ je .Lecb_dec_six
+ movups 0x60($inp),$inout6
+ $movkey ($key),$rndkey0
+ call _aesni_decrypt8
+ movups $inout0,($out)
+ movups $inout1,0x10($out)
+ movups $inout2,0x20($out)
+ movups $inout3,0x30($out)
+ movups $inout4,0x40($out)
+ movups $inout5,0x50($out)
+ movups $inout6,0x60($out)
+ jmp .Lecb_ret
+.align 16
+.Lecb_dec_one:
+___
+ &aesni_generate1("dec",$key,$rounds);
+$code.=<<___;
+ movups $inout0,($out)
+ jmp .Lecb_ret
+.align 16
+.Lecb_dec_two:
+ call _aesni_decrypt2
+ movups $inout0,($out)
+ movups $inout1,0x10($out)
+ jmp .Lecb_ret
+.align 16
+.Lecb_dec_three:
+ call _aesni_decrypt3
+ movups $inout0,($out)
+ movups $inout1,0x10($out)
+ movups $inout2,0x20($out)
+ jmp .Lecb_ret
+.align 16
+.Lecb_dec_four:
+ call _aesni_decrypt4
+ movups $inout0,($out)
+ movups $inout1,0x10($out)
+ movups $inout2,0x20($out)
+ movups $inout3,0x30($out)
+ jmp .Lecb_ret
+.align 16
+.Lecb_dec_five:
+ xorps $inout5,$inout5
+ call _aesni_decrypt6
+ movups $inout0,($out)
+ movups $inout1,0x10($out)
+ movups $inout2,0x20($out)
+ movups $inout3,0x30($out)
+ movups $inout4,0x40($out)
+ jmp .Lecb_ret
+.align 16
+.Lecb_dec_six:
+ call _aesni_decrypt6
+ movups $inout0,($out)
+ movups $inout1,0x10($out)
+ movups $inout2,0x20($out)
+ movups $inout3,0x30($out)
+ movups $inout4,0x40($out)
+ movups $inout5,0x50($out)
+
+.Lecb_ret:
+___
+$code.=<<___ if ($win64);
+ movaps (%rsp),%xmm6
+ movaps 0x10(%rsp),%xmm7
+ movaps 0x20(%rsp),%xmm8
+ movaps 0x30(%rsp),%xmm9
+ lea 0x58(%rsp),%rsp
+.Lecb_enc_ret:
+___
+$code.=<<___;
+ ret
+.size aesni_ecb_encrypt,.-aesni_ecb_encrypt
+___
+
+{
+######################################################################
+# void aesni_ccm64_[en|de]crypt_blocks (const void *in, void *out,
+# size_t blocks, const AES_KEY *key,
+# const char *ivec,char *cmac);
+#
+# Handles only complete blocks, operates on 64-bit counter and
+# does not update *ivec! Nor does it finalize CMAC value
+# (see engine/eng_aesni.c for details)
+#
+{
+my $cmac="%r9"; # 6th argument
+
+my $increment="%xmm9";
+my $iv="%xmm6";
+my $bswap_mask="%xmm7";
+
+$code.=<<___;
+.globl aesni_ccm64_encrypt_blocks
+.type aesni_ccm64_encrypt_blocks,\@function,6
+.align 16
+aesni_ccm64_encrypt_blocks:
+___
+$code.=<<___ if ($win64);
+ lea -0x58(%rsp),%rsp
+ movaps %xmm6,(%rsp)
+ movaps %xmm7,0x10(%rsp)
+ movaps %xmm8,0x20(%rsp)
+ movaps %xmm9,0x30(%rsp)
+.Lccm64_enc_body:
+___
+$code.=<<___;
+ mov 240($key),$rounds # key->rounds
+ movdqu ($ivp),$iv
+ movdqa .Lincrement64(%rip),$increment
+ movdqa .Lbswap_mask(%rip),$bswap_mask
+
+ shl \$4,$rounds
+ mov \$16,$rnds_
+ lea 0($key),$key_
+ movdqu ($cmac),$inout1
+ movdqa $iv,$inout0
+ lea 32($key,$rounds),$key # end of key schedule
+ pshufb $bswap_mask,$iv
+ sub %rax,%r10 # twisted $rounds
+ jmp .Lccm64_enc_outer
+.align 16
+.Lccm64_enc_outer:
+ $movkey ($key_),$rndkey0
+ mov %r10,%rax
+ movups ($inp),$in0 # load inp
+
+ xorps $rndkey0,$inout0 # counter
+ $movkey 16($key_),$rndkey1
+ xorps $in0,$rndkey0
+ xorps $rndkey0,$inout1 # cmac^=inp
+ $movkey 32($key_),$rndkey0
+
+.Lccm64_enc2_loop:
+ aesenc $rndkey1,$inout0
+ aesenc $rndkey1,$inout1
+ $movkey ($key,%rax),$rndkey1
+ add \$32,%rax
+ aesenc $rndkey0,$inout0
+ aesenc $rndkey0,$inout1
+ $movkey -16($key,%rax),$rndkey0
+ jnz .Lccm64_enc2_loop
+ aesenc $rndkey1,$inout0
+ aesenc $rndkey1,$inout1
+ paddq $increment,$iv
+ dec $len
+ aesenclast $rndkey0,$inout0
+ aesenclast $rndkey0,$inout1
+
+ lea 16($inp),$inp
+ xorps $inout0,$in0 # inp ^= E(iv)
+ movdqa $iv,$inout0
+ movups $in0,($out) # save output
+ pshufb $bswap_mask,$inout0
+ lea 16($out),$out
+ jnz .Lccm64_enc_outer
+
+ movups $inout1,($cmac)
+___
+$code.=<<___ if ($win64);
+ movaps (%rsp),%xmm6
+ movaps 0x10(%rsp),%xmm7
+ movaps 0x20(%rsp),%xmm8
+ movaps 0x30(%rsp),%xmm9
+ lea 0x58(%rsp),%rsp
+.Lccm64_enc_ret:
+___
+$code.=<<___;
+ ret
+.size aesni_ccm64_encrypt_blocks,.-aesni_ccm64_encrypt_blocks
+___
+######################################################################
+$code.=<<___;
+.globl aesni_ccm64_decrypt_blocks
+.type aesni_ccm64_decrypt_blocks,\@function,6
+.align 16
+aesni_ccm64_decrypt_blocks:
+___
+$code.=<<___ if ($win64);
+ lea -0x58(%rsp),%rsp
+ movaps %xmm6,(%rsp)
+ movaps %xmm7,0x10(%rsp)
+ movaps %xmm8,0x20(%rsp)
+ movaps %xmm9,0x30(%rsp)
+.Lccm64_dec_body:
+___
+$code.=<<___;
+ mov 240($key),$rounds # key->rounds
+ movups ($ivp),$iv
+ movdqu ($cmac),$inout1
+ movdqa .Lincrement64(%rip),$increment
+ movdqa .Lbswap_mask(%rip),$bswap_mask
+
+ movaps $iv,$inout0
+ mov $rounds,$rnds_
+ mov $key,$key_
+ pshufb $bswap_mask,$iv
+___
+ &aesni_generate1("enc",$key,$rounds);
+$code.=<<___;
+ shl \$4,$rnds_
+ mov \$16,$rounds
+ movups ($inp),$in0 # load inp
+ paddq $increment,$iv
+ lea 16($inp),$inp
+ sub %r10,%rax # twisted $rounds
+ lea 32($key_,$rnds_),$key # end of key schedule
+ mov %rax,%r10
+ jmp .Lccm64_dec_outer
+.align 16
+.Lccm64_dec_outer:
+ xorps $inout0,$in0 # inp ^= E(iv)
+ movdqa $iv,$inout0
+ movups $in0,($out) # save output
+ lea 16($out),$out
+ pshufb $bswap_mask,$inout0
+
+ sub \$1,$len
+ jz .Lccm64_dec_break
+
+ $movkey ($key_),$rndkey0
+ mov %r10,%rax
+ $movkey 16($key_),$rndkey1
+ xorps $rndkey0,$in0
+ xorps $rndkey0,$inout0
+ xorps $in0,$inout1 # cmac^=out
+ $movkey 32($key_),$rndkey0
+ jmp .Lccm64_dec2_loop
+.align 16
+.Lccm64_dec2_loop:
+ aesenc $rndkey1,$inout0
+ aesenc $rndkey1,$inout1
+ $movkey ($key,%rax),$rndkey1
+ add \$32,%rax
+ aesenc $rndkey0,$inout0
+ aesenc $rndkey0,$inout1
+ $movkey -16($key,%rax),$rndkey0
+ jnz .Lccm64_dec2_loop
+ movups ($inp),$in0 # load inp
+ paddq $increment,$iv
+ aesenc $rndkey1,$inout0
+ aesenc $rndkey1,$inout1
+ aesenclast $rndkey0,$inout0
+ aesenclast $rndkey0,$inout1
+ lea 16($inp),$inp
+ jmp .Lccm64_dec_outer
+
+.align 16
+.Lccm64_dec_break:
+ #xorps $in0,$inout1 # cmac^=out
+ mov 240($key_),$rounds
+___
+ &aesni_generate1("enc",$key_,$rounds,$inout1,$in0);
+$code.=<<___;
+ movups $inout1,($cmac)
+___
+$code.=<<___ if ($win64);
+ movaps (%rsp),%xmm6
+ movaps 0x10(%rsp),%xmm7
+ movaps 0x20(%rsp),%xmm8
+ movaps 0x30(%rsp),%xmm9
+ lea 0x58(%rsp),%rsp
+.Lccm64_dec_ret:
+___
+$code.=<<___;
+ ret
+.size aesni_ccm64_decrypt_blocks,.-aesni_ccm64_decrypt_blocks
+___
+}
+######################################################################
+# void aesni_ctr32_encrypt_blocks (const void *in, void *out,
+# size_t blocks, const AES_KEY *key,
+# const char *ivec);
+#
+# Handles only complete blocks, operates on 32-bit counter and
+# does not update *ivec! (see crypto/modes/ctr128.c for details)
+#
+# Overhaul based on suggestions from Shay Gueron and Vlad Krasnov,
+# http://rt.openssl.org/Ticket/Display.html?id=3021&user=guest&pass=guest.
+# Keywords are full unroll and modulo-schedule counter calculations
+# with zero-round key xor.
+{
+my ($in0,$in1,$in2,$in3,$in4,$in5)=map("%xmm$_",(10..15));
+my ($key0,$ctr)=("${key_}d","${ivp}d");
+my $frame_size = 0x80 + ($win64?160:0);
+
+$code.=<<___;
+.globl aesni_ctr32_encrypt_blocks
+.type aesni_ctr32_encrypt_blocks,\@function,5
+.align 16
+aesni_ctr32_encrypt_blocks:
+ lea (%rsp),%rax
+ push %rbp
+ sub \$$frame_size,%rsp
+ and \$-16,%rsp # Linux kernel stack can be incorrectly seeded
+___
+$code.=<<___ if ($win64);
+ movaps %xmm6,-0xa8(%rax)
+ movaps %xmm7,-0x98(%rax)
+ movaps %xmm8,-0x88(%rax)
+ movaps %xmm9,-0x78(%rax)
+ movaps %xmm10,-0x68(%rax)
+ movaps %xmm11,-0x58(%rax)
+ movaps %xmm12,-0x48(%rax)
+ movaps %xmm13,-0x38(%rax)
+ movaps %xmm14,-0x28(%rax)
+ movaps %xmm15,-0x18(%rax)
+.Lctr32_body:
+___
+$code.=<<___;
+ lea -8(%rax),%rbp
+
+ cmp \$1,$len
+ je .Lctr32_one_shortcut
+
+ movdqu ($ivp),$inout0
+ movdqu ($key),$rndkey0
+ mov 12($ivp),$ctr # counter LSB
+ pxor $rndkey0,$inout0
+ mov 12($key),$key0 # 0-round key LSB
+ movdqa $inout0,0x00(%rsp) # populate counter block
+ bswap $ctr
+ movdqa $inout0,$inout1
+ movdqa $inout0,$inout2
+ movdqa $inout0,$inout3
+ movdqa $inout0,0x40(%rsp)
+ movdqa $inout0,0x50(%rsp)
+ movdqa $inout0,0x60(%rsp)
+ mov %rdx,%r10 # borrow %rdx
+ movdqa $inout0,0x70(%rsp)
+
+ lea 1($ctr),%rax
+ lea 2($ctr),%rdx
+ bswap %eax
+ bswap %edx
+ xor $key0,%eax
+ xor $key0,%edx
+ pinsrd \$3,%eax,$inout1
+ lea 3($ctr),%rax
+ movdqa $inout1,0x10(%rsp)
+ pinsrd \$3,%edx,$inout2
+ bswap %eax
+ mov %r10,%rdx # restore %rdx
+ lea 4($ctr),%r10
+ movdqa $inout2,0x20(%rsp)
+ xor $key0,%eax
+ bswap %r10d
+ pinsrd \$3,%eax,$inout3
+ xor $key0,%r10d
+ movdqa $inout3,0x30(%rsp)
+ lea 5($ctr),%r9
+ mov %r10d,0x40+12(%rsp)
+ bswap %r9d
+ lea 6($ctr),%r10
+ mov 240($key),$rounds # key->rounds
+ xor $key0,%r9d
+ bswap %r10d
+ mov %r9d,0x50+12(%rsp)
+ xor $key0,%r10d
+ lea 7($ctr),%r9
+ mov %r10d,0x60+12(%rsp)
+ bswap %r9d
+ mov OPENSSL_ia32cap_P+4(%rip),%r10d
+ xor $key0,%r9d
+ and \$`1<<26|1<<22`,%r10d # isolate XSAVE+MOVBE
+ mov %r9d,0x70+12(%rsp)
+
+ $movkey 0x10($key),$rndkey1
+
+ movdqa 0x40(%rsp),$inout4
+ movdqa 0x50(%rsp),$inout5
+
+ cmp \$8,$len
+ jb .Lctr32_tail
+
+ sub \$6,$len
+ cmp \$`1<<22`,%r10d # check for MOVBE without XSAVE
+ je .Lctr32_6x
+
+ lea 0x80($key),$key # size optimization
+ sub \$2,$len
+ jmp .Lctr32_loop8
+
+.align 16
+.Lctr32_6x:
+ shl \$4,$rounds
+ mov \$48,$rnds_
+ bswap $key0
+ lea 32($key,$rounds),$key # end of key schedule
+ sub %rax,%r10 # twisted $rounds
+ jmp .Lctr32_loop6
+
+.align 16
+.Lctr32_loop6:
+ add \$6,$ctr
+ $movkey -48($key,$rnds_),$rndkey0
+ aesenc $rndkey1,$inout0
+ mov $ctr,%eax
+ xor $key0,%eax
+ aesenc $rndkey1,$inout1
+ movbe %eax,`0x00+12`(%rsp)
+ lea 1($ctr),%eax
+ aesenc $rndkey1,$inout2
+ xor $key0,%eax
+ movbe %eax,`0x10+12`(%rsp)
+ aesenc $rndkey1,$inout3
+ lea 2($ctr),%eax
+ xor $key0,%eax
+ aesenc $rndkey1,$inout4
+ movbe %eax,`0x20+12`(%rsp)
+ lea 3($ctr),%eax
+ aesenc $rndkey1,$inout5
+ $movkey -32($key,$rnds_),$rndkey1
+ xor $key0,%eax
+
+ aesenc $rndkey0,$inout0
+ movbe %eax,`0x30+12`(%rsp)
+ lea 4($ctr),%eax
+ aesenc $rndkey0,$inout1
+ xor $key0,%eax
+ movbe %eax,`0x40+12`(%rsp)
+ aesenc $rndkey0,$inout2
+ lea 5($ctr),%eax
+ xor $key0,%eax
+ aesenc $rndkey0,$inout3
+ movbe %eax,`0x50+12`(%rsp)
+ mov %r10,%rax # mov $rnds_,$rounds
+ aesenc $rndkey0,$inout4
+ aesenc $rndkey0,$inout5
+ $movkey -16($key,$rnds_),$rndkey0
+
+ call .Lenc_loop6
+
+ movdqu ($inp),$inout6
+ movdqu 0x10($inp),$inout7
+ movdqu 0x20($inp),$in0
+ movdqu 0x30($inp),$in1
+ movdqu 0x40($inp),$in2
+ movdqu 0x50($inp),$in3
+ lea 0x60($inp),$inp
+ $movkey -64($key,$rnds_),$rndkey1
+ pxor $inout0,$inout6
+ movaps 0x00(%rsp),$inout0
+ pxor $inout1,$inout7
+ movaps 0x10(%rsp),$inout1
+ pxor $inout2,$in0
+ movaps 0x20(%rsp),$inout2
+ pxor $inout3,$in1
+ movaps 0x30(%rsp),$inout3
+ pxor $inout4,$in2
+ movaps 0x40(%rsp),$inout4
+ pxor $inout5,$in3
+ movaps 0x50(%rsp),$inout5
+ movdqu $inout6,($out)
+ movdqu $inout7,0x10($out)
+ movdqu $in0,0x20($out)
+ movdqu $in1,0x30($out)
+ movdqu $in2,0x40($out)
+ movdqu $in3,0x50($out)
+ lea 0x60($out),$out
+
+ sub \$6,$len
+ jnc .Lctr32_loop6
+
+ add \$6,$len
+ jz .Lctr32_done
+
+ lea -48($rnds_),$rounds
+ lea -80($key,$rnds_),$key # restore $key
+ neg $rounds
+ shr \$4,$rounds # restore $rounds
+ jmp .Lctr32_tail
+
+.align 32
+.Lctr32_loop8:
+ add \$8,$ctr
+ movdqa 0x60(%rsp),$inout6
+ aesenc $rndkey1,$inout0
+ mov $ctr,%r9d
+ movdqa 0x70(%rsp),$inout7
+ aesenc $rndkey1,$inout1
+ bswap %r9d
+ $movkey 0x20-0x80($key),$rndkey0
+ aesenc $rndkey1,$inout2
+ xor $key0,%r9d
+ nop
+ aesenc $rndkey1,$inout3
+ mov %r9d,0x00+12(%rsp)
+ lea 1($ctr),%r9
+ aesenc $rndkey1,$inout4
+ aesenc $rndkey1,$inout5
+ aesenc $rndkey1,$inout6
+ aesenc $rndkey1,$inout7
+ $movkey 0x30-0x80($key),$rndkey1
+___
+for($i=2;$i<8;$i++) {
+my $rndkeyx = ($i&1)?$rndkey1:$rndkey0;
+$code.=<<___;
+ bswap %r9d
+ aesenc $rndkeyx,$inout0
+ aesenc $rndkeyx,$inout1
+ xor $key0,%r9d
+ .byte 0x66,0x90
+ aesenc $rndkeyx,$inout2
+ aesenc $rndkeyx,$inout3
+ mov %r9d,`0x10*($i-1)`+12(%rsp)
+ lea $i($ctr),%r9
+ aesenc $rndkeyx,$inout4
+ aesenc $rndkeyx,$inout5
+ aesenc $rndkeyx,$inout6
+ aesenc $rndkeyx,$inout7
+ $movkey `0x20+0x10*$i`-0x80($key),$rndkeyx
+___
+}
+$code.=<<___;
+ bswap %r9d
+ aesenc $rndkey0,$inout0
+ aesenc $rndkey0,$inout1
+ aesenc $rndkey0,$inout2
+ xor $key0,%r9d
+ movdqu 0x00($inp),$in0
+ aesenc $rndkey0,$inout3
+ mov %r9d,0x70+12(%rsp)
+ cmp \$11,$rounds
+ aesenc $rndkey0,$inout4
+ aesenc $rndkey0,$inout5
+ aesenc $rndkey0,$inout6
+ aesenc $rndkey0,$inout7
+ $movkey 0xa0-0x80($key),$rndkey0
+
+ jb .Lctr32_enc_done
+
+ aesenc $rndkey1,$inout0
+ aesenc $rndkey1,$inout1
+ aesenc $rndkey1,$inout2
+ aesenc $rndkey1,$inout3
+ aesenc $rndkey1,$inout4
+ aesenc $rndkey1,$inout5
+ aesenc $rndkey1,$inout6
+ aesenc $rndkey1,$inout7
+ $movkey 0xb0-0x80($key),$rndkey1
+
+ aesenc $rndkey0,$inout0
+ aesenc $rndkey0,$inout1
+ aesenc $rndkey0,$inout2
+ aesenc $rndkey0,$inout3
+ aesenc $rndkey0,$inout4
+ aesenc $rndkey0,$inout5
+ aesenc $rndkey0,$inout6
+ aesenc $rndkey0,$inout7
+ $movkey 0xc0-0x80($key),$rndkey0
+ je .Lctr32_enc_done
+
+ aesenc $rndkey1,$inout0
+ aesenc $rndkey1,$inout1
+ aesenc $rndkey1,$inout2
+ aesenc $rndkey1,$inout3
+ aesenc $rndkey1,$inout4
+ aesenc $rndkey1,$inout5
+ aesenc $rndkey1,$inout6
+ aesenc $rndkey1,$inout7
+ $movkey 0xd0-0x80($key),$rndkey1
+
+ aesenc $rndkey0,$inout0
+ aesenc $rndkey0,$inout1
+ aesenc $rndkey0,$inout2
+ aesenc $rndkey0,$inout3
+ aesenc $rndkey0,$inout4
+ aesenc $rndkey0,$inout5
+ aesenc $rndkey0,$inout6
+ aesenc $rndkey0,$inout7
+ $movkey 0xe0-0x80($key),$rndkey0
+ jmp .Lctr32_enc_done
+
+.align 16
+.Lctr32_enc_done:
+ movdqu 0x10($inp),$in1
+ pxor $rndkey0,$in0
+ movdqu 0x20($inp),$in2
+ pxor $rndkey0,$in1
+ movdqu 0x30($inp),$in3
+ pxor $rndkey0,$in2
+ movdqu 0x40($inp),$in4
+ pxor $rndkey0,$in3
+ movdqu 0x50($inp),$in5
+ pxor $rndkey0,$in4
+ pxor $rndkey0,$in5
+ aesenc $rndkey1,$inout0
+ aesenc $rndkey1,$inout1
+ aesenc $rndkey1,$inout2
+ aesenc $rndkey1,$inout3
+ aesenc $rndkey1,$inout4
+ aesenc $rndkey1,$inout5
+ aesenc $rndkey1,$inout6
+ aesenc $rndkey1,$inout7
+ movdqu 0x60($inp),$rndkey1
+ lea 0x80($inp),$inp
+
+ aesenclast $in0,$inout0
+ pxor $rndkey0,$rndkey1
+ movdqu 0x70-0x80($inp),$in0
+ aesenclast $in1,$inout1
+ pxor $rndkey0,$in0
+ movdqa 0x00(%rsp),$in1 # load next counter block
+ aesenclast $in2,$inout2
+ aesenclast $in3,$inout3
+ movdqa 0x10(%rsp),$in2
+ movdqa 0x20(%rsp),$in3
+ aesenclast $in4,$inout4
+ aesenclast $in5,$inout5
+ movdqa 0x30(%rsp),$in4
+ movdqa 0x40(%rsp),$in5
+ aesenclast $rndkey1,$inout6
+ movdqa 0x50(%rsp),$rndkey0
+ $movkey 0x10-0x80($key),$rndkey1
+ aesenclast $in0,$inout7
+
+ movups $inout0,($out) # store output
+ movdqa $in1,$inout0
+ movups $inout1,0x10($out)
+ movdqa $in2,$inout1
+ movups $inout2,0x20($out)
+ movdqa $in3,$inout2
+ movups $inout3,0x30($out)
+ movdqa $in4,$inout3
+ movups $inout4,0x40($out)
+ movdqa $in5,$inout4
+ movups $inout5,0x50($out)
+ movdqa $rndkey0,$inout5
+ movups $inout6,0x60($out)
+ movups $inout7,0x70($out)
+ lea 0x80($out),$out
+
+ sub \$8,$len
+ jnc .Lctr32_loop8
+
+ add \$8,$len
+ jz .Lctr32_done
+ lea -0x80($key),$key
+
+.Lctr32_tail:
+ lea 16($key),$key
+ cmp \$4,$len
+ jb .Lctr32_loop3
+ je .Lctr32_loop4
+
+ shl \$4,$rounds
+ movdqa 0x60(%rsp),$inout6
+ pxor $inout7,$inout7
+
+ $movkey 16($key),$rndkey0
+ aesenc $rndkey1,$inout0
+ aesenc $rndkey1,$inout1
+ lea 32-16($key,$rounds),$key
+ neg %rax
+ aesenc $rndkey1,$inout2
+ add \$16,%rax
+ movups ($inp),$in0
+ aesenc $rndkey1,$inout3
+ aesenc $rndkey1,$inout4
+ movups 0x10($inp),$in1
+ movups 0x20($inp),$in2
+ aesenc $rndkey1,$inout5
+ aesenc $rndkey1,$inout6
+
+ call .Lenc_loop8_enter
+
+ movdqu 0x30($inp),$in3
+ pxor $in0,$inout0
+ movdqu 0x40($inp),$in0
+ pxor $in1,$inout1
+ movdqu $inout0,($out)
+ pxor $in2,$inout2
+ movdqu $inout1,0x10($out)
+ pxor $in3,$inout3
+ movdqu $inout2,0x20($out)
+ pxor $in0,$inout4
+ movdqu $inout3,0x30($out)
+ movdqu $inout4,0x40($out)
+ cmp \$6,$len
+ jb .Lctr32_done
+
+ movups 0x50($inp),$in1
+ xorps $in1,$inout5
+ movups $inout5,0x50($out)
+ je .Lctr32_done
+
+ movups 0x60($inp),$in2
+ xorps $in2,$inout6
+ movups $inout6,0x60($out)
+ jmp .Lctr32_done
+
+.align 32
+.Lctr32_loop4:
+ aesenc $rndkey1,$inout0
+ lea 16($key),$key
+ dec $rounds
+ aesenc $rndkey1,$inout1
+ aesenc $rndkey1,$inout2
+ aesenc $rndkey1,$inout3
+ $movkey ($key),$rndkey1
+ jnz .Lctr32_loop4
+ aesenclast $rndkey1,$inout0
+ aesenclast $rndkey1,$inout1
+ movups ($inp),$in0
+ movups 0x10($inp),$in1
+ aesenclast $rndkey1,$inout2
+ aesenclast $rndkey1,$inout3
+ movups 0x20($inp),$in2
+ movups 0x30($inp),$in3
+
+ xorps $in0,$inout0
+ movups $inout0,($out)
+ xorps $in1,$inout1
+ movups $inout1,0x10($out)
+ pxor $in2,$inout2
+ movdqu $inout2,0x20($out)
+ pxor $in3,$inout3
+ movdqu $inout3,0x30($out)
+ jmp .Lctr32_done
+
+.align 32
+.Lctr32_loop3:
+ aesenc $rndkey1,$inout0
+ lea 16($key),$key
+ dec $rounds
+ aesenc $rndkey1,$inout1
+ aesenc $rndkey1,$inout2
+ $movkey ($key),$rndkey1
+ jnz .Lctr32_loop3
+ aesenclast $rndkey1,$inout0
+ aesenclast $rndkey1,$inout1
+ aesenclast $rndkey1,$inout2
+
+ movups ($inp),$in0
+ xorps $in0,$inout0
+ movups $inout0,($out)
+ cmp \$2,$len
+ jb .Lctr32_done
+
+ movups 0x10($inp),$in1
+ xorps $in1,$inout1
+ movups $inout1,0x10($out)
+ je .Lctr32_done
+
+ movups 0x20($inp),$in2
+ xorps $in2,$inout2
+ movups $inout2,0x20($out)
+ jmp .Lctr32_done
+
+.align 16
+.Lctr32_one_shortcut:
+ movups ($ivp),$inout0
+ movups ($inp),$in0
+ mov 240($key),$rounds # key->rounds
+___
+ &aesni_generate1("enc",$key,$rounds);
+$code.=<<___;
+ xorps $in0,$inout0
+ movups $inout0,($out)
+ jmp .Lctr32_done
+
+.align 16
+.Lctr32_done:
+___
+$code.=<<___ if ($win64);
+ movaps -0xa0(%rbp),%xmm6
+ movaps -0x90(%rbp),%xmm7
+ movaps -0x80(%rbp),%xmm8
+ movaps -0x70(%rbp),%xmm9
+ movaps -0x60(%rbp),%xmm10
+ movaps -0x50(%rbp),%xmm11
+ movaps -0x40(%rbp),%xmm12
+ movaps -0x30(%rbp),%xmm13
+ movaps -0x20(%rbp),%xmm14
+ movaps -0x10(%rbp),%xmm15
+___
+$code.=<<___;
+ lea (%rbp),%rsp
+ pop %rbp
+.Lctr32_epilogue:
+ ret
+.size aesni_ctr32_encrypt_blocks,.-aesni_ctr32_encrypt_blocks
+___
+}
+
+######################################################################
+# void aesni_xts_[en|de]crypt(const char *inp,char *out,size_t len,
+# const AES_KEY *key1, const AES_KEY *key2
+# const unsigned char iv[16]);
+#
+{
+my @tweak=map("%xmm$_",(10..15));
+my ($twmask,$twres,$twtmp)=("%xmm8","%xmm9",@tweak[4]);
+my ($key2,$ivp,$len_)=("%r8","%r9","%r9");
+my $frame_size = 0x70 + ($win64?160:0);
+
+$code.=<<___;
+.globl aesni_xts_encrypt
+.type aesni_xts_encrypt,\@function,6
+.align 16
+aesni_xts_encrypt:
+ lea (%rsp),%rax
+ push %rbp
+ sub \$$frame_size,%rsp
+ and \$-16,%rsp # Linux kernel stack can be incorrectly seeded
+___
+$code.=<<___ if ($win64);
+ movaps %xmm6,-0xa8(%rax)
+ movaps %xmm7,-0x98(%rax)
+ movaps %xmm8,-0x88(%rax)
+ movaps %xmm9,-0x78(%rax)
+ movaps %xmm10,-0x68(%rax)
+ movaps %xmm11,-0x58(%rax)
+ movaps %xmm12,-0x48(%rax)
+ movaps %xmm13,-0x38(%rax)
+ movaps %xmm14,-0x28(%rax)
+ movaps %xmm15,-0x18(%rax)
+.Lxts_enc_body:
+___
+$code.=<<___;
+ lea -8(%rax),%rbp
+ movups ($ivp),$inout0 # load clear-text tweak
+ mov 240(%r8),$rounds # key2->rounds
+ mov 240($key),$rnds_ # key1->rounds
+___
+ # generate the tweak
+ &aesni_generate1("enc",$key2,$rounds,$inout0);
+$code.=<<___;
+ $movkey ($key),$rndkey0 # zero round key
+ mov $key,$key_ # backup $key
+ mov $rnds_,$rounds # backup $rounds
+ shl \$4,$rnds_
+ mov $len,$len_ # backup $len
+ and \$-16,$len
+
+ $movkey 16($key,$rnds_),$rndkey1 # last round key
+
+ movdqa .Lxts_magic(%rip),$twmask
+ movdqa $inout0,@tweak[5]
+ pshufd \$0x5f,$inout0,$twres
+ pxor $rndkey0,$rndkey1
+___
+ # alternative tweak calculation algorithm is based on suggestions
+ # by Shay Gueron. psrad doesn't conflict with AES-NI instructions
+ # and should help in the future...
+ for ($i=0;$i<4;$i++) {
+ $code.=<<___;
+ movdqa $twres,$twtmp
+ paddd $twres,$twres
+ movdqa @tweak[5],@tweak[$i]
+ psrad \$31,$twtmp # broadcast upper bits
+ paddq @tweak[5],@tweak[5]
+ pand $twmask,$twtmp
+ pxor $rndkey0,@tweak[$i]
+ pxor $twtmp,@tweak[5]
+___
+ }
+$code.=<<___;
+ movdqa @tweak[5],@tweak[4]
+ psrad \$31,$twres
+ paddq @tweak[5],@tweak[5]
+ pand $twmask,$twres
+ pxor $rndkey0,@tweak[4]
+ pxor $twres,@tweak[5]
+ movaps $rndkey1,0x60(%rsp) # save round[0]^round[last]
+
+ sub \$16*6,$len
+ jc .Lxts_enc_short
+
+ mov \$16+96,$rounds
+ lea 32($key_,$rnds_),$key # end of key schedule
+ sub %r10,%rax # twisted $rounds
+ $movkey 16($key_),$rndkey1
+ mov %rax,%r10 # backup twisted $rounds
+ lea .Lxts_magic(%rip),%r8
+ jmp .Lxts_enc_grandloop
+
+.align 32
+.Lxts_enc_grandloop:
+ movdqu `16*0`($inp),$inout0 # load input
+ movdqa $rndkey0,$twmask
+ movdqu `16*1`($inp),$inout1
+ pxor @tweak[0],$inout0
+ movdqu `16*2`($inp),$inout2
+ pxor @tweak[1],$inout1
+ aesenc $rndkey1,$inout0
+ movdqu `16*3`($inp),$inout3
+ pxor @tweak[2],$inout2
+ aesenc $rndkey1,$inout1
+ movdqu `16*4`($inp),$inout4
+ pxor @tweak[3],$inout3
+ aesenc $rndkey1,$inout2
+ movdqu `16*5`($inp),$inout5
+ pxor @tweak[5],$twmask # round[0]^=tweak[5]
+ movdqa 0x60(%rsp),$twres # load round[0]^round[last]
+ pxor @tweak[4],$inout4
+ aesenc $rndkey1,$inout3
+ $movkey 32($key_),$rndkey0
+ lea `16*6`($inp),$inp
+ pxor $twmask,$inout5
+
+ pxor $twres,@tweak[0]
+ aesenc $rndkey1,$inout4
+ pxor $twres,@tweak[1]
+ movdqa @tweak[0],`16*0`(%rsp) # put aside tweaks^last round key
+ aesenc $rndkey1,$inout5
+ $movkey 48($key_),$rndkey1
+ pxor $twres,@tweak[2]
+
+ aesenc $rndkey0,$inout0
+ pxor $twres,@tweak[3]
+ movdqa @tweak[1],`16*1`(%rsp)
+ aesenc $rndkey0,$inout1
+ pxor $twres,@tweak[4]
+ movdqa @tweak[2],`16*2`(%rsp)
+ aesenc $rndkey0,$inout2
+ aesenc $rndkey0,$inout3
+ pxor $twres,$twmask
+ movdqa @tweak[4],`16*4`(%rsp)
+ aesenc $rndkey0,$inout4
+ aesenc $rndkey0,$inout5
+ $movkey 64($key_),$rndkey0
+ movdqa $twmask,`16*5`(%rsp)
+ pshufd \$0x5f,@tweak[5],$twres
+ jmp .Lxts_enc_loop6
+.align 32
+.Lxts_enc_loop6:
+ aesenc $rndkey1,$inout0
+ aesenc $rndkey1,$inout1
+ aesenc $rndkey1,$inout2
+ aesenc $rndkey1,$inout3
+ aesenc $rndkey1,$inout4
+ aesenc $rndkey1,$inout5
+ $movkey -64($key,%rax),$rndkey1
+ add \$32,%rax
+
+ aesenc $rndkey0,$inout0
+ aesenc $rndkey0,$inout1
+ aesenc $rndkey0,$inout2
+ aesenc $rndkey0,$inout3
+ aesenc $rndkey0,$inout4
+ aesenc $rndkey0,$inout5
+ $movkey -80($key,%rax),$rndkey0
+ jnz .Lxts_enc_loop6
+
+ movdqa (%r8),$twmask
+ movdqa $twres,$twtmp
+ paddd $twres,$twres
+ aesenc $rndkey1,$inout0
+ paddq @tweak[5],@tweak[5]
+ psrad \$31,$twtmp
+ aesenc $rndkey1,$inout1
+ pand $twmask,$twtmp
+ $movkey ($key_),@tweak[0] # load round[0]
+ aesenc $rndkey1,$inout2
+ aesenc $rndkey1,$inout3
+ aesenc $rndkey1,$inout4
+ pxor $twtmp,@tweak[5]
+ movaps @tweak[0],@tweak[1] # copy round[0]
+ aesenc $rndkey1,$inout5
+ $movkey -64($key),$rndkey1
+
+ movdqa $twres,$twtmp
+ aesenc $rndkey0,$inout0
+ paddd $twres,$twres
+ pxor @tweak[5],@tweak[0]
+ aesenc $rndkey0,$inout1
+ psrad \$31,$twtmp
+ paddq @tweak[5],@tweak[5]
+ aesenc $rndkey0,$inout2
+ aesenc $rndkey0,$inout3
+ pand $twmask,$twtmp
+ movaps @tweak[1],@tweak[2]
+ aesenc $rndkey0,$inout4
+ pxor $twtmp,@tweak[5]
+ movdqa $twres,$twtmp
+ aesenc $rndkey0,$inout5
+ $movkey -48($key),$rndkey0
+
+ paddd $twres,$twres
+ aesenc $rndkey1,$inout0
+ pxor @tweak[5],@tweak[1]
+ psrad \$31,$twtmp
+ aesenc $rndkey1,$inout1
+ paddq @tweak[5],@tweak[5]
+ pand $twmask,$twtmp
+ aesenc $rndkey1,$inout2
+ aesenc $rndkey1,$inout3
+ movdqa @tweak[3],`16*3`(%rsp)
+ pxor $twtmp,@tweak[5]
+ aesenc $rndkey1,$inout4
+ movaps @tweak[2],@tweak[3]
+ movdqa $twres,$twtmp
+ aesenc $rndkey1,$inout5
+ $movkey -32($key),$rndkey1
+
+ paddd $twres,$twres
+ aesenc $rndkey0,$inout0
+ pxor @tweak[5],@tweak[2]
+ psrad \$31,$twtmp
+ aesenc $rndkey0,$inout1
+ paddq @tweak[5],@tweak[5]
+ pand $twmask,$twtmp
+ aesenc $rndkey0,$inout2
+ aesenc $rndkey0,$inout3
+ aesenc $rndkey0,$inout4
+ pxor $twtmp,@tweak[5]
+ movaps @tweak[3],@tweak[4]
+ aesenc $rndkey0,$inout5
+
+ movdqa $twres,$rndkey0
+ paddd $twres,$twres
+ aesenc $rndkey1,$inout0
+ pxor @tweak[5],@tweak[3]
+ psrad \$31,$rndkey0
+ aesenc $rndkey1,$inout1
+ paddq @tweak[5],@tweak[5]
+ pand $twmask,$rndkey0
+ aesenc $rndkey1,$inout2
+ aesenc $rndkey1,$inout3
+ pxor $rndkey0,@tweak[5]
+ $movkey ($key_),$rndkey0
+ aesenc $rndkey1,$inout4
+ aesenc $rndkey1,$inout5
+ $movkey 16($key_),$rndkey1
+
+ pxor @tweak[5],@tweak[4]
+ aesenclast `16*0`(%rsp),$inout0
+ psrad \$31,$twres
+ paddq @tweak[5],@tweak[5]
+ aesenclast `16*1`(%rsp),$inout1
+ aesenclast `16*2`(%rsp),$inout2
+ pand $twmask,$twres
+ mov %r10,%rax # restore $rounds
+ aesenclast `16*3`(%rsp),$inout3
+ aesenclast `16*4`(%rsp),$inout4
+ aesenclast `16*5`(%rsp),$inout5
+ pxor $twres,@tweak[5]
+
+ lea `16*6`($out),$out
+ movups $inout0,`-16*6`($out) # write output
+ movups $inout1,`-16*5`($out)
+ movups $inout2,`-16*4`($out)
+ movups $inout3,`-16*3`($out)
+ movups $inout4,`-16*2`($out)
+ movups $inout5,`-16*1`($out)
+ sub \$16*6,$len
+ jnc .Lxts_enc_grandloop
+
+ mov \$16+96,$rounds
+ sub $rnds_,$rounds
+ mov $key_,$key # restore $key
+ shr \$4,$rounds # restore original value
+
+.Lxts_enc_short:
+ mov $rounds,$rnds_ # backup $rounds
+ pxor $rndkey0,@tweak[0]
+ add \$16*6,$len
+ jz .Lxts_enc_done
+
+ pxor $rndkey0,@tweak[1]
+ cmp \$0x20,$len
+ jb .Lxts_enc_one
+ pxor $rndkey0,@tweak[2]
+ je .Lxts_enc_two
+
+ pxor $rndkey0,@tweak[3]
+ cmp \$0x40,$len
+ jb .Lxts_enc_three
+ pxor $rndkey0,@tweak[4]
+ je .Lxts_enc_four
+
+ movdqu ($inp),$inout0
+ movdqu 16*1($inp),$inout1
+ movdqu 16*2($inp),$inout2
+ pxor @tweak[0],$inout0
+ movdqu 16*3($inp),$inout3
+ pxor @tweak[1],$inout1
+ movdqu 16*4($inp),$inout4
+ lea 16*5($inp),$inp
+ pxor @tweak[2],$inout2
+ pxor @tweak[3],$inout3
+ pxor @tweak[4],$inout4
+
+ call _aesni_encrypt6
+
+ xorps @tweak[0],$inout0
+ movdqa @tweak[5],@tweak[0]
+ xorps @tweak[1],$inout1
+ xorps @tweak[2],$inout2
+ movdqu $inout0,($out)
+ xorps @tweak[3],$inout3
+ movdqu $inout1,16*1($out)
+ xorps @tweak[4],$inout4
+ movdqu $inout2,16*2($out)
+ movdqu $inout3,16*3($out)
+ movdqu $inout4,16*4($out)
+ lea 16*5($out),$out
+ jmp .Lxts_enc_done
+
+.align 16
+.Lxts_enc_one:
+ movups ($inp),$inout0
+ lea 16*1($inp),$inp
+ xorps @tweak[0],$inout0
+___
+ &aesni_generate1("enc",$key,$rounds);
+$code.=<<___;
+ xorps @tweak[0],$inout0
+ movdqa @tweak[1],@tweak[0]
+ movups $inout0,($out)
+ lea 16*1($out),$out
+ jmp .Lxts_enc_done
+
+.align 16
+.Lxts_enc_two:
+ movups ($inp),$inout0
+ movups 16($inp),$inout1
+ lea 32($inp),$inp
+ xorps @tweak[0],$inout0
+ xorps @tweak[1],$inout1
+
+ call _aesni_encrypt2
+
+ xorps @tweak[0],$inout0
+ movdqa @tweak[2],@tweak[0]
+ xorps @tweak[1],$inout1
+ movups $inout0,($out)
+ movups $inout1,16*1($out)
+ lea 16*2($out),$out
+ jmp .Lxts_enc_done
+
+.align 16
+.Lxts_enc_three:
+ movups ($inp),$inout0
+ movups 16*1($inp),$inout1
+ movups 16*2($inp),$inout2
+ lea 16*3($inp),$inp
+ xorps @tweak[0],$inout0
+ xorps @tweak[1],$inout1
+ xorps @tweak[2],$inout2
+
+ call _aesni_encrypt3
+
+ xorps @tweak[0],$inout0
+ movdqa @tweak[3],@tweak[0]
+ xorps @tweak[1],$inout1
+ xorps @tweak[2],$inout2
+ movups $inout0,($out)
+ movups $inout1,16*1($out)
+ movups $inout2,16*2($out)
+ lea 16*3($out),$out
+ jmp .Lxts_enc_done
+
+.align 16
+.Lxts_enc_four:
+ movups ($inp),$inout0
+ movups 16*1($inp),$inout1
+ movups 16*2($inp),$inout2
+ xorps @tweak[0],$inout0
+ movups 16*3($inp),$inout3
+ lea 16*4($inp),$inp
+ xorps @tweak[1],$inout1
+ xorps @tweak[2],$inout2
+ xorps @tweak[3],$inout3
+
+ call _aesni_encrypt4
+
+ pxor @tweak[0],$inout0
+ movdqa @tweak[4],@tweak[0]
+ pxor @tweak[1],$inout1
+ pxor @tweak[2],$inout2
+ movdqu $inout0,($out)
+ pxor @tweak[3],$inout3
+ movdqu $inout1,16*1($out)
+ movdqu $inout2,16*2($out)
+ movdqu $inout3,16*3($out)
+ lea 16*4($out),$out
+ jmp .Lxts_enc_done
+
+.align 16
+.Lxts_enc_done:
+ and \$15,$len_
+ jz .Lxts_enc_ret
+ mov $len_,$len
+
+.Lxts_enc_steal:
+ movzb ($inp),%eax # borrow $rounds ...
+ movzb -16($out),%ecx # ... and $key
+ lea 1($inp),$inp
+ mov %al,-16($out)
+ mov %cl,0($out)
+ lea 1($out),$out
+ sub \$1,$len
+ jnz .Lxts_enc_steal
+
+ sub $len_,$out # rewind $out
+ mov $key_,$key # restore $key
+ mov $rnds_,$rounds # restore $rounds
+
+ movups -16($out),$inout0
+ xorps @tweak[0],$inout0
+___
+ &aesni_generate1("enc",$key,$rounds);
+$code.=<<___;
+ xorps @tweak[0],$inout0
+ movups $inout0,-16($out)
+
+.Lxts_enc_ret:
+___
+$code.=<<___ if ($win64);
+ movaps -0xa0(%rbp),%xmm6
+ movaps -0x90(%rbp),%xmm7
+ movaps -0x80(%rbp),%xmm8
+ movaps -0x70(%rbp),%xmm9
+ movaps -0x60(%rbp),%xmm10
+ movaps -0x50(%rbp),%xmm11
+ movaps -0x40(%rbp),%xmm12
+ movaps -0x30(%rbp),%xmm13
+ movaps -0x20(%rbp),%xmm14
+ movaps -0x10(%rbp),%xmm15
+___
+$code.=<<___;
+ lea (%rbp),%rsp
+ pop %rbp
+.Lxts_enc_epilogue:
+ ret
+.size aesni_xts_encrypt,.-aesni_xts_encrypt
+___
+
+$code.=<<___;
+.globl aesni_xts_decrypt
+.type aesni_xts_decrypt,\@function,6
+.align 16
+aesni_xts_decrypt:
+ lea (%rsp),%rax
+ push %rbp
+ sub \$$frame_size,%rsp
+ and \$-16,%rsp # Linux kernel stack can be incorrectly seeded
+___
+$code.=<<___ if ($win64);
+ movaps %xmm6,-0xa8(%rax)
+ movaps %xmm7,-0x98(%rax)
+ movaps %xmm8,-0x88(%rax)
+ movaps %xmm9,-0x78(%rax)
+ movaps %xmm10,-0x68(%rax)
+ movaps %xmm11,-0x58(%rax)
+ movaps %xmm12,-0x48(%rax)
+ movaps %xmm13,-0x38(%rax)
+ movaps %xmm14,-0x28(%rax)
+ movaps %xmm15,-0x18(%rax)
+.Lxts_dec_body:
+___
+$code.=<<___;
+ lea -8(%rax),%rbp
+ movups ($ivp),$inout0 # load clear-text tweak
+ mov 240($key2),$rounds # key2->rounds
+ mov 240($key),$rnds_ # key1->rounds
+___
+ # generate the tweak
+ &aesni_generate1("enc",$key2,$rounds,$inout0);
+$code.=<<___;
+ xor %eax,%eax # if ($len%16) len-=16;
+ test \$15,$len
+ setnz %al
+ shl \$4,%rax
+ sub %rax,$len
+
+ $movkey ($key),$rndkey0 # zero round key
+ mov $key,$key_ # backup $key
+ mov $rnds_,$rounds # backup $rounds
+ shl \$4,$rnds_
+ mov $len,$len_ # backup $len
+ and \$-16,$len
+
+ $movkey 16($key,$rnds_),$rndkey1 # last round key
+
+ movdqa .Lxts_magic(%rip),$twmask
+ movdqa $inout0,@tweak[5]
+ pshufd \$0x5f,$inout0,$twres
+ pxor $rndkey0,$rndkey1
+___
+ for ($i=0;$i<4;$i++) {
+ $code.=<<___;
+ movdqa $twres,$twtmp
+ paddd $twres,$twres
+ movdqa @tweak[5],@tweak[$i]
+ psrad \$31,$twtmp # broadcast upper bits
+ paddq @tweak[5],@tweak[5]
+ pand $twmask,$twtmp
+ pxor $rndkey0,@tweak[$i]
+ pxor $twtmp,@tweak[5]
+___
+ }
+$code.=<<___;
+ movdqa @tweak[5],@tweak[4]
+ psrad \$31,$twres
+ paddq @tweak[5],@tweak[5]
+ pand $twmask,$twres
+ pxor $rndkey0,@tweak[4]
+ pxor $twres,@tweak[5]
+ movaps $rndkey1,0x60(%rsp) # save round[0]^round[last]
+
+ sub \$16*6,$len
+ jc .Lxts_dec_short
+
+ mov \$16+96,$rounds
+ lea 32($key_,$rnds_),$key # end of key schedule
+ sub %r10,%rax # twisted $rounds
+ $movkey 16($key_),$rndkey1
+ mov %rax,%r10 # backup twisted $rounds
+ lea .Lxts_magic(%rip),%r8
+ jmp .Lxts_dec_grandloop
+
+.align 32
+.Lxts_dec_grandloop:
+ movdqu `16*0`($inp),$inout0 # load input
+ movdqa $rndkey0,$twmask
+ movdqu `16*1`($inp),$inout1
+ pxor @tweak[0],$inout0
+ movdqu `16*2`($inp),$inout2
+ pxor @tweak[1],$inout1
+ aesdec $rndkey1,$inout0
+ movdqu `16*3`($inp),$inout3
+ pxor @tweak[2],$inout2
+ aesdec $rndkey1,$inout1
+ movdqu `16*4`($inp),$inout4
+ pxor @tweak[3],$inout3
+ aesdec $rndkey1,$inout2
+ movdqu `16*5`($inp),$inout5
+ pxor @tweak[5],$twmask # round[0]^=tweak[5]
+ movdqa 0x60(%rsp),$twres # load round[0]^round[last]
+ pxor @tweak[4],$inout4
+ aesdec $rndkey1,$inout3
+ $movkey 32($key_),$rndkey0
+ lea `16*6`($inp),$inp
+ pxor $twmask,$inout5
+
+ pxor $twres,@tweak[0]
+ aesdec $rndkey1,$inout4
+ pxor $twres,@tweak[1]
+ movdqa @tweak[0],`16*0`(%rsp) # put aside tweaks^last round key
+ aesdec $rndkey1,$inout5
+ $movkey 48($key_),$rndkey1
+ pxor $twres,@tweak[2]
+
+ aesdec $rndkey0,$inout0
+ pxor $twres,@tweak[3]
+ movdqa @tweak[1],`16*1`(%rsp)
+ aesdec $rndkey0,$inout1
+ pxor $twres,@tweak[4]
+ movdqa @tweak[2],`16*2`(%rsp)
+ aesdec $rndkey0,$inout2
+ aesdec $rndkey0,$inout3
+ pxor $twres,$twmask
+ movdqa @tweak[4],`16*4`(%rsp)
+ aesdec $rndkey0,$inout4
+ aesdec $rndkey0,$inout5
+ $movkey 64($key_),$rndkey0
+ movdqa $twmask,`16*5`(%rsp)
+ pshufd \$0x5f,@tweak[5],$twres
+ jmp .Lxts_dec_loop6
+.align 32
+.Lxts_dec_loop6:
+ aesdec $rndkey1,$inout0
+ aesdec $rndkey1,$inout1
+ aesdec $rndkey1,$inout2
+ aesdec $rndkey1,$inout3
+ aesdec $rndkey1,$inout4
+ aesdec $rndkey1,$inout5
+ $movkey -64($key,%rax),$rndkey1
+ add \$32,%rax
+
+ aesdec $rndkey0,$inout0
+ aesdec $rndkey0,$inout1
+ aesdec $rndkey0,$inout2
+ aesdec $rndkey0,$inout3
+ aesdec $rndkey0,$inout4
+ aesdec $rndkey0,$inout5
+ $movkey -80($key,%rax),$rndkey0
+ jnz .Lxts_dec_loop6
+
+ movdqa (%r8),$twmask
+ movdqa $twres,$twtmp
+ paddd $twres,$twres
+ aesdec $rndkey1,$inout0
+ paddq @tweak[5],@tweak[5]
+ psrad \$31,$twtmp
+ aesdec $rndkey1,$inout1
+ pand $twmask,$twtmp
+ $movkey ($key_),@tweak[0] # load round[0]
+ aesdec $rndkey1,$inout2
+ aesdec $rndkey1,$inout3
+ aesdec $rndkey1,$inout4
+ pxor $twtmp,@tweak[5]
+ movaps @tweak[0],@tweak[1] # copy round[0]
+ aesdec $rndkey1,$inout5
+ $movkey -64($key),$rndkey1
+
+ movdqa $twres,$twtmp
+ aesdec $rndkey0,$inout0
+ paddd $twres,$twres
+ pxor @tweak[5],@tweak[0]
+ aesdec $rndkey0,$inout1
+ psrad \$31,$twtmp
+ paddq @tweak[5],@tweak[5]
+ aesdec $rndkey0,$inout2
+ aesdec $rndkey0,$inout3
+ pand $twmask,$twtmp
+ movaps @tweak[1],@tweak[2]
+ aesdec $rndkey0,$inout4
+ pxor $twtmp,@tweak[5]
+ movdqa $twres,$twtmp
+ aesdec $rndkey0,$inout5
+ $movkey -48($key),$rndkey0
+
+ paddd $twres,$twres
+ aesdec $rndkey1,$inout0
+ pxor @tweak[5],@tweak[1]
+ psrad \$31,$twtmp
+ aesdec $rndkey1,$inout1
+ paddq @tweak[5],@tweak[5]
+ pand $twmask,$twtmp
+ aesdec $rndkey1,$inout2
+ aesdec $rndkey1,$inout3
+ movdqa @tweak[3],`16*3`(%rsp)
+ pxor $twtmp,@tweak[5]
+ aesdec $rndkey1,$inout4
+ movaps @tweak[2],@tweak[3]
+ movdqa $twres,$twtmp
+ aesdec $rndkey1,$inout5
+ $movkey -32($key),$rndkey1
+
+ paddd $twres,$twres
+ aesdec $rndkey0,$inout0
+ pxor @tweak[5],@tweak[2]
+ psrad \$31,$twtmp
+ aesdec $rndkey0,$inout1
+ paddq @tweak[5],@tweak[5]
+ pand $twmask,$twtmp
+ aesdec $rndkey0,$inout2
+ aesdec $rndkey0,$inout3
+ aesdec $rndkey0,$inout4
+ pxor $twtmp,@tweak[5]
+ movaps @tweak[3],@tweak[4]
+ aesdec $rndkey0,$inout5
+
+ movdqa $twres,$rndkey0
+ paddd $twres,$twres
+ aesdec $rndkey1,$inout0
+ pxor @tweak[5],@tweak[3]
+ psrad \$31,$rndkey0
+ aesdec $rndkey1,$inout1
+ paddq @tweak[5],@tweak[5]
+ pand $twmask,$rndkey0
+ aesdec $rndkey1,$inout2
+ aesdec $rndkey1,$inout3
+ pxor $rndkey0,@tweak[5]
+ $movkey ($key_),$rndkey0
+ aesdec $rndkey1,$inout4
+ aesdec $rndkey1,$inout5
+ $movkey 16($key_),$rndkey1
+
+ pxor @tweak[5],@tweak[4]
+ aesdeclast `16*0`(%rsp),$inout0
+ psrad \$31,$twres
+ paddq @tweak[5],@tweak[5]
+ aesdeclast `16*1`(%rsp),$inout1
+ aesdeclast `16*2`(%rsp),$inout2
+ pand $twmask,$twres
+ mov %r10,%rax # restore $rounds
+ aesdeclast `16*3`(%rsp),$inout3
+ aesdeclast `16*4`(%rsp),$inout4
+ aesdeclast `16*5`(%rsp),$inout5
+ pxor $twres,@tweak[5]
+
+ lea `16*6`($out),$out
+ movups $inout0,`-16*6`($out) # write output
+ movups $inout1,`-16*5`($out)
+ movups $inout2,`-16*4`($out)
+ movups $inout3,`-16*3`($out)
+ movups $inout4,`-16*2`($out)
+ movups $inout5,`-16*1`($out)
+ sub \$16*6,$len
+ jnc .Lxts_dec_grandloop
+
+ mov \$16+96,$rounds
+ sub $rnds_,$rounds
+ mov $key_,$key # restore $key
+ shr \$4,$rounds # restore original value
+
+.Lxts_dec_short:
+ mov $rounds,$rnds_ # backup $rounds
+ pxor $rndkey0,@tweak[0]
+ pxor $rndkey0,@tweak[1]
+ add \$16*6,$len
+ jz .Lxts_dec_done
+
+ pxor $rndkey0,@tweak[2]
+ cmp \$0x20,$len
+ jb .Lxts_dec_one
+ pxor $rndkey0,@tweak[3]
+ je .Lxts_dec_two
+
+ pxor $rndkey0,@tweak[4]
+ cmp \$0x40,$len
+ jb .Lxts_dec_three
+ je .Lxts_dec_four
+
+ movdqu ($inp),$inout0
+ movdqu 16*1($inp),$inout1
+ movdqu 16*2($inp),$inout2
+ pxor @tweak[0],$inout0
+ movdqu 16*3($inp),$inout3
+ pxor @tweak[1],$inout1
+ movdqu 16*4($inp),$inout4
+ lea 16*5($inp),$inp
+ pxor @tweak[2],$inout2
+ pxor @tweak[3],$inout3
+ pxor @tweak[4],$inout4
+
+ call _aesni_decrypt6
+
+ xorps @tweak[0],$inout0
+ xorps @tweak[1],$inout1
+ xorps @tweak[2],$inout2
+ movdqu $inout0,($out)
+ xorps @tweak[3],$inout3
+ movdqu $inout1,16*1($out)
+ xorps @tweak[4],$inout4
+ movdqu $inout2,16*2($out)
+ pxor $twtmp,$twtmp
+ movdqu $inout3,16*3($out)
+ pcmpgtd @tweak[5],$twtmp
+ movdqu $inout4,16*4($out)
+ lea 16*5($out),$out
+ pshufd \$0x13,$twtmp,@tweak[1] # $twres
+ and \$15,$len_
+ jz .Lxts_dec_ret
+
+ movdqa @tweak[5],@tweak[0]
+ paddq @tweak[5],@tweak[5] # psllq 1,$tweak
+ pand $twmask,@tweak[1] # isolate carry and residue
+ pxor @tweak[5],@tweak[1]
+ jmp .Lxts_dec_done2
+
+.align 16
+.Lxts_dec_one:
+ movups ($inp),$inout0
+ lea 16*1($inp),$inp
+ xorps @tweak[0],$inout0
+___
+ &aesni_generate1("dec",$key,$rounds);
+$code.=<<___;
+ xorps @tweak[0],$inout0
+ movdqa @tweak[1],@tweak[0]
+ movups $inout0,($out)
+ movdqa @tweak[2],@tweak[1]
+ lea 16*1($out),$out
+ jmp .Lxts_dec_done
+
+.align 16
+.Lxts_dec_two:
+ movups ($inp),$inout0
+ movups 16($inp),$inout1
+ lea 32($inp),$inp
+ xorps @tweak[0],$inout0
+ xorps @tweak[1],$inout1
+
+ call _aesni_decrypt2
+
+ xorps @tweak[0],$inout0
+ movdqa @tweak[2],@tweak[0]
+ xorps @tweak[1],$inout1
+ movdqa @tweak[3],@tweak[1]
+ movups $inout0,($out)
+ movups $inout1,16*1($out)
+ lea 16*2($out),$out
+ jmp .Lxts_dec_done
+
+.align 16
+.Lxts_dec_three:
+ movups ($inp),$inout0
+ movups 16*1($inp),$inout1
+ movups 16*2($inp),$inout2
+ lea 16*3($inp),$inp
+ xorps @tweak[0],$inout0
+ xorps @tweak[1],$inout1
+ xorps @tweak[2],$inout2
+
+ call _aesni_decrypt3
+
+ xorps @tweak[0],$inout0
+ movdqa @tweak[3],@tweak[0]
+ xorps @tweak[1],$inout1
+ movdqa @tweak[4],@tweak[1]
+ xorps @tweak[2],$inout2
+ movups $inout0,($out)
+ movups $inout1,16*1($out)
+ movups $inout2,16*2($out)
+ lea 16*3($out),$out
+ jmp .Lxts_dec_done
+
+.align 16
+.Lxts_dec_four:
+ movups ($inp),$inout0
+ movups 16*1($inp),$inout1
+ movups 16*2($inp),$inout2
+ xorps @tweak[0],$inout0
+ movups 16*3($inp),$inout3
+ lea 16*4($inp),$inp
+ xorps @tweak[1],$inout1
+ xorps @tweak[2],$inout2
+ xorps @tweak[3],$inout3
+
+ call _aesni_decrypt4
+
+ pxor @tweak[0],$inout0
+ movdqa @tweak[4],@tweak[0]
+ pxor @tweak[1],$inout1
+ movdqa @tweak[5],@tweak[1]
+ pxor @tweak[2],$inout2
+ movdqu $inout0,($out)
+ pxor @tweak[3],$inout3
+ movdqu $inout1,16*1($out)
+ movdqu $inout2,16*2($out)
+ movdqu $inout3,16*3($out)
+ lea 16*4($out),$out
+ jmp .Lxts_dec_done
+
+.align 16
+.Lxts_dec_done:
+ and \$15,$len_
+ jz .Lxts_dec_ret
+.Lxts_dec_done2:
+ mov $len_,$len
+ mov $key_,$key # restore $key
+ mov $rnds_,$rounds # restore $rounds
+
+ movups ($inp),$inout0
+ xorps @tweak[1],$inout0
+___
+ &aesni_generate1("dec",$key,$rounds);
+$code.=<<___;
+ xorps @tweak[1],$inout0
+ movups $inout0,($out)
+
+.Lxts_dec_steal:
+ movzb 16($inp),%eax # borrow $rounds ...
+ movzb ($out),%ecx # ... and $key
+ lea 1($inp),$inp
+ mov %al,($out)
+ mov %cl,16($out)
+ lea 1($out),$out
+ sub \$1,$len
+ jnz .Lxts_dec_steal
+
+ sub $len_,$out # rewind $out
+ mov $key_,$key # restore $key
+ mov $rnds_,$rounds # restore $rounds
+
+ movups ($out),$inout0
+ xorps @tweak[0],$inout0
+___
+ &aesni_generate1("dec",$key,$rounds);
+$code.=<<___;
+ xorps @tweak[0],$inout0
+ movups $inout0,($out)
+
+.Lxts_dec_ret:
+___
+$code.=<<___ if ($win64);
+ movaps -0xa0(%rbp),%xmm6
+ movaps -0x90(%rbp),%xmm7
+ movaps -0x80(%rbp),%xmm8
+ movaps -0x70(%rbp),%xmm9
+ movaps -0x60(%rbp),%xmm10
+ movaps -0x50(%rbp),%xmm11
+ movaps -0x40(%rbp),%xmm12
+ movaps -0x30(%rbp),%xmm13
+ movaps -0x20(%rbp),%xmm14
+ movaps -0x10(%rbp),%xmm15
+___
+$code.=<<___;
+ lea (%rbp),%rsp
+ pop %rbp
+.Lxts_dec_epilogue:
+ ret
+.size aesni_xts_decrypt,.-aesni_xts_decrypt
+___
+} }}
+
+########################################################################
+# void $PREFIX_cbc_encrypt (const void *inp, void *out,
+# size_t length, const AES_KEY *key,
+# unsigned char *ivp,const int enc);
+{
+my $frame_size = 0x10 + ($win64?0xa0:0); # used in decrypt
+my ($iv,$in0,$in1,$in2,$in3,$in4)=map("%xmm$_",(10..15));
+my $inp_=$key_;
+
+$code.=<<___;
+.globl ${PREFIX}_cbc_encrypt
+.type ${PREFIX}_cbc_encrypt,\@function,6
+.align 16
+${PREFIX}_cbc_encrypt:
+ test $len,$len # check length
+ jz .Lcbc_ret
+
+ mov 240($key),$rnds_ # key->rounds
+ mov $key,$key_ # backup $key
+ test %r9d,%r9d # 6th argument
+ jz .Lcbc_decrypt
+#--------------------------- CBC ENCRYPT ------------------------------#
+ movups ($ivp),$inout0 # load iv as initial state
+ mov $rnds_,$rounds
+ cmp \$16,$len
+ jb .Lcbc_enc_tail
+ sub \$16,$len
+ jmp .Lcbc_enc_loop
+.align 16
+.Lcbc_enc_loop:
+ movups ($inp),$inout1 # load input
+ lea 16($inp),$inp
+ #xorps $inout1,$inout0
+___
+ &aesni_generate1("enc",$key,$rounds,$inout0,$inout1);
+$code.=<<___;
+ mov $rnds_,$rounds # restore $rounds
+ mov $key_,$key # restore $key
+ movups $inout0,0($out) # store output
+ lea 16($out),$out
+ sub \$16,$len
+ jnc .Lcbc_enc_loop
+ add \$16,$len
+ jnz .Lcbc_enc_tail
+ movups $inout0,($ivp)
+ jmp .Lcbc_ret
+
+.Lcbc_enc_tail:
+ mov $len,%rcx # zaps $key
+ xchg $inp,$out # $inp is %rsi and $out is %rdi now
+ .long 0x9066A4F3 # rep movsb
+ mov \$16,%ecx # zero tail
+ sub $len,%rcx
+ xor %eax,%eax
+ .long 0x9066AAF3 # rep stosb
+ lea -16(%rdi),%rdi # rewind $out by 1 block
+ mov $rnds_,$rounds # restore $rounds
+ mov %rdi,%rsi # $inp and $out are the same
+ mov $key_,$key # restore $key
+ xor $len,$len # len=16
+ jmp .Lcbc_enc_loop # one more spin
+ #--------------------------- CBC DECRYPT ------------------------------#
+.align 16
+.Lcbc_decrypt:
+ lea (%rsp),%rax
+ push %rbp
+ sub \$$frame_size,%rsp
+ and \$-16,%rsp # Linux kernel stack can be incorrectly seeded
+___
+$code.=<<___ if ($win64);
+ movaps %xmm6,0x10(%rsp)
+ movaps %xmm7,0x20(%rsp)
+ movaps %xmm8,0x30(%rsp)
+ movaps %xmm9,0x40(%rsp)
+ movaps %xmm10,0x50(%rsp)
+ movaps %xmm11,0x60(%rsp)
+ movaps %xmm12,0x70(%rsp)
+ movaps %xmm13,0x80(%rsp)
+ movaps %xmm14,0x90(%rsp)
+ movaps %xmm15,0xa0(%rsp)
+.Lcbc_decrypt_body:
+___
+$code.=<<___;
+ lea -8(%rax),%rbp
+ movups ($ivp),$iv
+ mov $rnds_,$rounds
+ cmp \$0x50,$len
+ jbe .Lcbc_dec_tail
+
+ $movkey ($key),$rndkey0
+ movdqu 0x00($inp),$inout0 # load input
+ movdqu 0x10($inp),$inout1
+ movdqa $inout0,$in0
+ movdqu 0x20($inp),$inout2
+ movdqa $inout1,$in1
+ movdqu 0x30($inp),$inout3
+ movdqa $inout2,$in2
+ movdqu 0x40($inp),$inout4
+ movdqa $inout3,$in3
+ movdqu 0x50($inp),$inout5
+ movdqa $inout4,$in4
+ mov OPENSSL_ia32cap_P+4(%rip),%r9d
+ cmp \$0x70,$len
+ jbe .Lcbc_dec_six_or_seven
+
+ and \$`1<<26|1<<22`,%r9d # isolate XSAVE+MOVBE
+ sub \$0x50,$len
+ cmp \$`1<<22`,%r9d # check for MOVBE without XSAVE
+ je .Lcbc_dec_loop6_enter
+ sub \$0x20,$len
+ lea 0x70($key),$key # size optimization
+ jmp .Lcbc_dec_loop8_enter
+.align 16
+.Lcbc_dec_loop8:
+ movups $inout7,($out)
+ lea 0x10($out),$out
+.Lcbc_dec_loop8_enter:
+ movdqu 0x60($inp),$inout6
+ pxor $rndkey0,$inout0
+ movdqu 0x70($inp),$inout7
+ pxor $rndkey0,$inout1
+ $movkey 0x10-0x70($key),$rndkey1
+ pxor $rndkey0,$inout2
+ xor $inp_,$inp_
+ cmp \$0x70,$len # is there at least 0x60 bytes ahead?
+ pxor $rndkey0,$inout3
+ pxor $rndkey0,$inout4
+ pxor $rndkey0,$inout5
+ pxor $rndkey0,$inout6
+
+ aesdec $rndkey1,$inout0
+ pxor $rndkey0,$inout7
+ $movkey 0x20-0x70($key),$rndkey0
+ aesdec $rndkey1,$inout1
+ aesdec $rndkey1,$inout2
+ aesdec $rndkey1,$inout3
+ aesdec $rndkey1,$inout4
+ aesdec $rndkey1,$inout5
+ aesdec $rndkey1,$inout6
+ setnc ${inp_}b
+ shl \$7,$inp_
+ aesdec $rndkey1,$inout7
+ add $inp,$inp_
+ $movkey 0x30-0x70($key),$rndkey1
+___
+for($i=1;$i<12;$i++) {
+my $rndkeyx = ($i&1)?$rndkey0:$rndkey1;
+$code.=<<___ if ($i==7);
+ cmp \$11,$rounds
+___
+$code.=<<___;
+ aesdec $rndkeyx,$inout0
+ aesdec $rndkeyx,$inout1
+ aesdec $rndkeyx,$inout2
+ aesdec $rndkeyx,$inout3
+ aesdec $rndkeyx,$inout4
+ aesdec $rndkeyx,$inout5
+ aesdec $rndkeyx,$inout6
+ aesdec $rndkeyx,$inout7
+ $movkey `0x30+0x10*$i`-0x70($key),$rndkeyx
+___
+$code.=<<___ if ($i<6 || (!($i&1) && $i>7));
+ nop
+___
+$code.=<<___ if ($i==7);
+ jb .Lcbc_dec_done
+___
+$code.=<<___ if ($i==9);
+ je .Lcbc_dec_done
+___
+$code.=<<___ if ($i==11);
+ jmp .Lcbc_dec_done
+___
+}
+$code.=<<___;
+.align 16
+.Lcbc_dec_done:
+ aesdec $rndkey1,$inout0
+ aesdec $rndkey1,$inout1
+ pxor $rndkey0,$iv
+ pxor $rndkey0,$in0
+ aesdec $rndkey1,$inout2
+ aesdec $rndkey1,$inout3
+ pxor $rndkey0,$in1
+ pxor $rndkey0,$in2
+ aesdec $rndkey1,$inout4
+ aesdec $rndkey1,$inout5
+ pxor $rndkey0,$in3
+ pxor $rndkey0,$in4
+ aesdec $rndkey1,$inout6
+ aesdec $rndkey1,$inout7
+ movdqu 0x50($inp),$rndkey1
+
+ aesdeclast $iv,$inout0
+ movdqu 0x60($inp),$iv # borrow $iv
+ pxor $rndkey0,$rndkey1
+ aesdeclast $in0,$inout1
+ pxor $rndkey0,$iv
+ movdqu 0x70($inp),$rndkey0 # next IV
+ aesdeclast $in1,$inout2
+ lea 0x80($inp),$inp
+ movdqu 0x00($inp_),$in0
+ aesdeclast $in2,$inout3
+ aesdeclast $in3,$inout4
+ movdqu 0x10($inp_),$in1
+ movdqu 0x20($inp_),$in2
+ aesdeclast $in4,$inout5
+ aesdeclast $rndkey1,$inout6
+ movdqu 0x30($inp_),$in3
+ movdqu 0x40($inp_),$in4
+ aesdeclast $iv,$inout7
+ movdqa $rndkey0,$iv # return $iv
+ movdqu 0x50($inp_),$rndkey1
+ $movkey -0x70($key),$rndkey0
+
+ movups $inout0,($out) # store output
+ movdqa $in0,$inout0
+ movups $inout1,0x10($out)
+ movdqa $in1,$inout1
+ movups $inout2,0x20($out)
+ movdqa $in2,$inout2
+ movups $inout3,0x30($out)
+ movdqa $in3,$inout3
+ movups $inout4,0x40($out)
+ movdqa $in4,$inout4
+ movups $inout5,0x50($out)
+ movdqa $rndkey1,$inout5
+ movups $inout6,0x60($out)
+ lea 0x70($out),$out
+
+ sub \$0x80,$len
+ ja .Lcbc_dec_loop8
+
+ movaps $inout7,$inout0
+ lea -0x70($key),$key
+ add \$0x70,$len
+ jle .Lcbc_dec_tail_collected
+ movups $inout7,($out)
+ lea 0x10($out),$out
+ cmp \$0x50,$len
+ jbe .Lcbc_dec_tail
+
+ movaps $in0,$inout0
+.Lcbc_dec_six_or_seven:
+ cmp \$0x60,$len
+ ja .Lcbc_dec_seven
+
+ movaps $inout5,$inout6
+ call _aesni_decrypt6
+ pxor $iv,$inout0 # ^= IV
+ movaps $inout6,$iv
+ pxor $in0,$inout1
+ movdqu $inout0,($out)
+ pxor $in1,$inout2
+ movdqu $inout1,0x10($out)
+ pxor $in2,$inout3
+ movdqu $inout2,0x20($out)
+ pxor $in3,$inout4
+ movdqu $inout3,0x30($out)
+ pxor $in4,$inout5
+ movdqu $inout4,0x40($out)
+ lea 0x50($out),$out
+ movdqa $inout5,$inout0
+ jmp .Lcbc_dec_tail_collected
+
+.align 16
+.Lcbc_dec_seven:
+ movups 0x60($inp),$inout6
+ xorps $inout7,$inout7
+ call _aesni_decrypt8
+ movups 0x50($inp),$inout7
+ pxor $iv,$inout0 # ^= IV
+ movups 0x60($inp),$iv
+ pxor $in0,$inout1
+ movdqu $inout0,($out)
+ pxor $in1,$inout2
+ movdqu $inout1,0x10($out)
+ pxor $in2,$inout3
+ movdqu $inout2,0x20($out)
+ pxor $in3,$inout4
+ movdqu $inout3,0x30($out)
+ pxor $in4,$inout5
+ movdqu $inout4,0x40($out)
+ pxor $inout7,$inout6
+ movdqu $inout5,0x50($out)
+ lea 0x60($out),$out
+ movdqa $inout6,$inout0
+ jmp .Lcbc_dec_tail_collected
+
+.align 16
+.Lcbc_dec_loop6:
+ movups $inout5,($out)
+ lea 0x10($out),$out
+ movdqu 0x00($inp),$inout0 # load input
+ movdqu 0x10($inp),$inout1
+ movdqa $inout0,$in0
+ movdqu 0x20($inp),$inout2
+ movdqa $inout1,$in1
+ movdqu 0x30($inp),$inout3
+ movdqa $inout2,$in2
+ movdqu 0x40($inp),$inout4
+ movdqa $inout3,$in3
+ movdqu 0x50($inp),$inout5
+ movdqa $inout4,$in4
+.Lcbc_dec_loop6_enter:
+ lea 0x60($inp),$inp
+ movdqa $inout5,$inout6
+
+ call _aesni_decrypt6
+
+ pxor $iv,$inout0 # ^= IV
+ movdqa $inout6,$iv
+ pxor $in0,$inout1
+ movdqu $inout0,($out)
+ pxor $in1,$inout2
+ movdqu $inout1,0x10($out)
+ pxor $in2,$inout3
+ movdqu $inout2,0x20($out)
+ pxor $in3,$inout4
+ mov $key_,$key
+ movdqu $inout3,0x30($out)
+ pxor $in4,$inout5
+ mov $rnds_,$rounds
+ movdqu $inout4,0x40($out)
+ lea 0x50($out),$out
+ sub \$0x60,$len
+ ja .Lcbc_dec_loop6
+
+ movdqa $inout5,$inout0
+ add \$0x50,$len
+ jle .Lcbc_dec_tail_collected
+ movups $inout5,($out)
+ lea 0x10($out),$out
+
+.Lcbc_dec_tail:
+ movups ($inp),$inout0
+ sub \$0x10,$len
+ jbe .Lcbc_dec_one
+
+ movups 0x10($inp),$inout1
+ movaps $inout0,$in0
+ sub \$0x10,$len
+ jbe .Lcbc_dec_two
+
+ movups 0x20($inp),$inout2
+ movaps $inout1,$in1
+ sub \$0x10,$len
+ jbe .Lcbc_dec_three
+
+ movups 0x30($inp),$inout3
+ movaps $inout2,$in2
+ sub \$0x10,$len
+ jbe .Lcbc_dec_four
+
+ movups 0x40($inp),$inout4
+ movaps $inout3,$in3
+ movaps $inout4,$in4
+ xorps $inout5,$inout5
+ call _aesni_decrypt6
+ pxor $iv,$inout0
+ movaps $in4,$iv
+ pxor $in0,$inout1
+ movdqu $inout0,($out)
+ pxor $in1,$inout2
+ movdqu $inout1,0x10($out)
+ pxor $in2,$inout3
+ movdqu $inout2,0x20($out)
+ pxor $in3,$inout4
+ movdqu $inout3,0x30($out)
+ lea 0x40($out),$out
+ movdqa $inout4,$inout0
+ sub \$0x10,$len
+ jmp .Lcbc_dec_tail_collected
+
+.align 16
+.Lcbc_dec_one:
+ movaps $inout0,$in0
+___
+ &aesni_generate1("dec",$key,$rounds);
+$code.=<<___;
+ xorps $iv,$inout0
+ movaps $in0,$iv
+ jmp .Lcbc_dec_tail_collected
+.align 16
+.Lcbc_dec_two:
+ movaps $inout1,$in1
+ call _aesni_decrypt2
+ pxor $iv,$inout0
+ movaps $in1,$iv
+ pxor $in0,$inout1
+ movdqu $inout0,($out)
+ movdqa $inout1,$inout0
+ lea 0x10($out),$out
+ jmp .Lcbc_dec_tail_collected
+.align 16
+.Lcbc_dec_three:
+ movaps $inout2,$in2
+ call _aesni_decrypt3
+ pxor $iv,$inout0
+ movaps $in2,$iv
+ pxor $in0,$inout1
+ movdqu $inout0,($out)
+ pxor $in1,$inout2
+ movdqu $inout1,0x10($out)
+ movdqa $inout2,$inout0
+ lea 0x20($out),$out
+ jmp .Lcbc_dec_tail_collected
+.align 16
+.Lcbc_dec_four:
+ movaps $inout3,$in3
+ call _aesni_decrypt4
+ pxor $iv,$inout0
+ movaps $in3,$iv
+ pxor $in0,$inout1
+ movdqu $inout0,($out)
+ pxor $in1,$inout2
+ movdqu $inout1,0x10($out)
+ pxor $in2,$inout3
+ movdqu $inout2,0x20($out)
+ movdqa $inout3,$inout0
+ lea 0x30($out),$out
+ jmp .Lcbc_dec_tail_collected
+
+.align 16
+.Lcbc_dec_tail_collected:
+ movups $iv,($ivp)
+ and \$15,$len
+ jnz .Lcbc_dec_tail_partial
+ movups $inout0,($out)
+ jmp .Lcbc_dec_ret
+.align 16
+.Lcbc_dec_tail_partial:
+ movaps $inout0,(%rsp)
+ mov \$16,%rcx
+ mov $out,%rdi
+ sub $len,%rcx
+ lea (%rsp),%rsi
+ .long 0x9066A4F3 # rep movsb
+
+.Lcbc_dec_ret:
+___
+$code.=<<___ if ($win64);
+ movaps 0x10(%rsp),%xmm6
+ movaps 0x20(%rsp),%xmm7
+ movaps 0x30(%rsp),%xmm8
+ movaps 0x40(%rsp),%xmm9
+ movaps 0x50(%rsp),%xmm10
+ movaps 0x60(%rsp),%xmm11
+ movaps 0x70(%rsp),%xmm12
+ movaps 0x80(%rsp),%xmm13
+ movaps 0x90(%rsp),%xmm14
+ movaps 0xa0(%rsp),%xmm15
+___
+$code.=<<___;
+ lea (%rbp),%rsp
+ pop %rbp
+.Lcbc_ret:
+ ret
+.size ${PREFIX}_cbc_encrypt,.-${PREFIX}_cbc_encrypt
+___
+}
+# int $PREFIX_set_[en|de]crypt_key (const unsigned char *userKey,
+# int bits, AES_KEY *key)
+{ my ($inp,$bits,$key) = @_4args;
+ $bits =~ s/%r/%e/;
+
+$code.=<<___;
+.globl ${PREFIX}_set_decrypt_key
+.type ${PREFIX}_set_decrypt_key,\@abi-omnipotent
+.align 16
+${PREFIX}_set_decrypt_key:
+ .byte 0x48,0x83,0xEC,0x08 # sub rsp,8
+ call __aesni_set_encrypt_key
+ shl \$4,$bits # rounds-1 after _aesni_set_encrypt_key
+ test %eax,%eax
+ jnz .Ldec_key_ret
+ lea 16($key,$bits),$inp # points at the end of key schedule
+
+ $movkey ($key),%xmm0 # just swap
+ $movkey ($inp),%xmm1
+ $movkey %xmm0,($inp)
+ $movkey %xmm1,($key)
+ lea 16($key),$key
+ lea -16($inp),$inp
+
+.Ldec_key_inverse:
+ $movkey ($key),%xmm0 # swap and inverse
+ $movkey ($inp),%xmm1
+ aesimc %xmm0,%xmm0
+ aesimc %xmm1,%xmm1
+ lea 16($key),$key
+ lea -16($inp),$inp
+ $movkey %xmm0,16($inp)
+ $movkey %xmm1,-16($key)
+ cmp $key,$inp
+ ja .Ldec_key_inverse
+
+ $movkey ($key),%xmm0 # inverse middle
+ aesimc %xmm0,%xmm0
+ $movkey %xmm0,($inp)
+.Ldec_key_ret:
+ add \$8,%rsp
+ ret
+.LSEH_end_set_decrypt_key:
+.size ${PREFIX}_set_decrypt_key,.-${PREFIX}_set_decrypt_key
+___
+
+# This is based on submission by
+#
+# Huang Ying <ying.huang@intel.com>
+# Vinodh Gopal <vinodh.gopal@intel.com>
+# Kahraman Akdemir
+#
+# Agressively optimized in respect to aeskeygenassist's critical path
+# and is contained in %xmm0-5 to meet Win64 ABI requirement.
+#
+$code.=<<___;
+.globl ${PREFIX}_set_encrypt_key
+.type ${PREFIX}_set_encrypt_key,\@abi-omnipotent
+.align 16
+${PREFIX}_set_encrypt_key:
+__aesni_set_encrypt_key:
+ .byte 0x48,0x83,0xEC,0x08 # sub rsp,8
+ mov \$-1,%rax
+ test $inp,$inp
+ jz .Lenc_key_ret
+ test $key,$key
+ jz .Lenc_key_ret
+
+ movups ($inp),%xmm0 # pull first 128 bits of *userKey
+ xorps %xmm4,%xmm4 # low dword of xmm4 is assumed 0
+ lea 16($key),%rax
+ cmp \$256,$bits
+ je .L14rounds
+ cmp \$192,$bits
+ je .L12rounds
+ cmp \$128,$bits
+ jne .Lbad_keybits
+
+.L10rounds:
+ mov \$9,$bits # 10 rounds for 128-bit key
+ $movkey %xmm0,($key) # round 0
+ aeskeygenassist \$0x1,%xmm0,%xmm1 # round 1
+ call .Lkey_expansion_128_cold
+ aeskeygenassist \$0x2,%xmm0,%xmm1 # round 2
+ call .Lkey_expansion_128
+ aeskeygenassist \$0x4,%xmm0,%xmm1 # round 3
+ call .Lkey_expansion_128
+ aeskeygenassist \$0x8,%xmm0,%xmm1 # round 4
+ call .Lkey_expansion_128
+ aeskeygenassist \$0x10,%xmm0,%xmm1 # round 5
+ call .Lkey_expansion_128
+ aeskeygenassist \$0x20,%xmm0,%xmm1 # round 6
+ call .Lkey_expansion_128
+ aeskeygenassist \$0x40,%xmm0,%xmm1 # round 7
+ call .Lkey_expansion_128
+ aeskeygenassist \$0x80,%xmm0,%xmm1 # round 8
+ call .Lkey_expansion_128
+ aeskeygenassist \$0x1b,%xmm0,%xmm1 # round 9
+ call .Lkey_expansion_128
+ aeskeygenassist \$0x36,%xmm0,%xmm1 # round 10
+ call .Lkey_expansion_128
+ $movkey %xmm0,(%rax)
+ mov $bits,80(%rax) # 240(%rdx)
+ xor %eax,%eax
+ jmp .Lenc_key_ret
+
+.align 16
+.L12rounds:
+ movq 16($inp),%xmm2 # remaining 1/3 of *userKey
+ mov \$11,$bits # 12 rounds for 192
+ $movkey %xmm0,($key) # round 0
+ aeskeygenassist \$0x1,%xmm2,%xmm1 # round 1,2
+ call .Lkey_expansion_192a_cold
+ aeskeygenassist \$0x2,%xmm2,%xmm1 # round 2,3
+ call .Lkey_expansion_192b
+ aeskeygenassist \$0x4,%xmm2,%xmm1 # round 4,5
+ call .Lkey_expansion_192a
+ aeskeygenassist \$0x8,%xmm2,%xmm1 # round 5,6
+ call .Lkey_expansion_192b
+ aeskeygenassist \$0x10,%xmm2,%xmm1 # round 7,8
+ call .Lkey_expansion_192a
+ aeskeygenassist \$0x20,%xmm2,%xmm1 # round 8,9
+ call .Lkey_expansion_192b
+ aeskeygenassist \$0x40,%xmm2,%xmm1 # round 10,11
+ call .Lkey_expansion_192a
+ aeskeygenassist \$0x80,%xmm2,%xmm1 # round 11,12
+ call .Lkey_expansion_192b
+ $movkey %xmm0,(%rax)
+ mov $bits,48(%rax) # 240(%rdx)
+ xor %rax, %rax
+ jmp .Lenc_key_ret
+
+.align 16
+.L14rounds:
+ movups 16($inp),%xmm2 # remaning half of *userKey
+ mov \$13,$bits # 14 rounds for 256
+ lea 16(%rax),%rax
+ $movkey %xmm0,($key) # round 0
+ $movkey %xmm2,16($key) # round 1
+ aeskeygenassist \$0x1,%xmm2,%xmm1 # round 2
+ call .Lkey_expansion_256a_cold
+ aeskeygenassist \$0x1,%xmm0,%xmm1 # round 3
+ call .Lkey_expansion_256b
+ aeskeygenassist \$0x2,%xmm2,%xmm1 # round 4
+ call .Lkey_expansion_256a
+ aeskeygenassist \$0x2,%xmm0,%xmm1 # round 5
+ call .Lkey_expansion_256b
+ aeskeygenassist \$0x4,%xmm2,%xmm1 # round 6
+ call .Lkey_expansion_256a
+ aeskeygenassist \$0x4,%xmm0,%xmm1 # round 7
+ call .Lkey_expansion_256b
+ aeskeygenassist \$0x8,%xmm2,%xmm1 # round 8
+ call .Lkey_expansion_256a
+ aeskeygenassist \$0x8,%xmm0,%xmm1 # round 9
+ call .Lkey_expansion_256b
+ aeskeygenassist \$0x10,%xmm2,%xmm1 # round 10
+ call .Lkey_expansion_256a
+ aeskeygenassist \$0x10,%xmm0,%xmm1 # round 11
+ call .Lkey_expansion_256b
+ aeskeygenassist \$0x20,%xmm2,%xmm1 # round 12
+ call .Lkey_expansion_256a
+ aeskeygenassist \$0x20,%xmm0,%xmm1 # round 13
+ call .Lkey_expansion_256b
+ aeskeygenassist \$0x40,%xmm2,%xmm1 # round 14
+ call .Lkey_expansion_256a
+ $movkey %xmm0,(%rax)
+ mov $bits,16(%rax) # 240(%rdx)
+ xor %rax,%rax
+ jmp .Lenc_key_ret
+
+.align 16
+.Lbad_keybits:
+ mov \$-2,%rax
+.Lenc_key_ret:
+ add \$8,%rsp
+ ret
+.LSEH_end_set_encrypt_key:
+
+.align 16
+.Lkey_expansion_128:
+ $movkey %xmm0,(%rax)
+ lea 16(%rax),%rax
+.Lkey_expansion_128_cold:
+ shufps \$0b00010000,%xmm0,%xmm4
+ xorps %xmm4, %xmm0
+ shufps \$0b10001100,%xmm0,%xmm4
+ xorps %xmm4, %xmm0
+ shufps \$0b11111111,%xmm1,%xmm1 # critical path
+ xorps %xmm1,%xmm0
+ ret
+
+.align 16
+.Lkey_expansion_192a:
+ $movkey %xmm0,(%rax)
+ lea 16(%rax),%rax
+.Lkey_expansion_192a_cold:
+ movaps %xmm2, %xmm5
+.Lkey_expansion_192b_warm:
+ shufps \$0b00010000,%xmm0,%xmm4
+ movdqa %xmm2,%xmm3
+ xorps %xmm4,%xmm0
+ shufps \$0b10001100,%xmm0,%xmm4
+ pslldq \$4,%xmm3
+ xorps %xmm4,%xmm0
+ pshufd \$0b01010101,%xmm1,%xmm1 # critical path
+ pxor %xmm3,%xmm2
+ pxor %xmm1,%xmm0
+ pshufd \$0b11111111,%xmm0,%xmm3
+ pxor %xmm3,%xmm2
+ ret
+
+.align 16
+.Lkey_expansion_192b:
+ movaps %xmm0,%xmm3
+ shufps \$0b01000100,%xmm0,%xmm5
+ $movkey %xmm5,(%rax)
+ shufps \$0b01001110,%xmm2,%xmm3
+ $movkey %xmm3,16(%rax)
+ lea 32(%rax),%rax
+ jmp .Lkey_expansion_192b_warm
+
+.align 16
+.Lkey_expansion_256a:
+ $movkey %xmm2,(%rax)
+ lea 16(%rax),%rax
+.Lkey_expansion_256a_cold:
+ shufps \$0b00010000,%xmm0,%xmm4
+ xorps %xmm4,%xmm0
+ shufps \$0b10001100,%xmm0,%xmm4
+ xorps %xmm4,%xmm0
+ shufps \$0b11111111,%xmm1,%xmm1 # critical path
+ xorps %xmm1,%xmm0
+ ret
+
+.align 16
+.Lkey_expansion_256b:
+ $movkey %xmm0,(%rax)
+ lea 16(%rax),%rax
+
+ shufps \$0b00010000,%xmm2,%xmm4
+ xorps %xmm4,%xmm2
+ shufps \$0b10001100,%xmm2,%xmm4
+ xorps %xmm4,%xmm2
+ shufps \$0b10101010,%xmm1,%xmm1 # critical path
+ xorps %xmm1,%xmm2
+ ret
+.size ${PREFIX}_set_encrypt_key,.-${PREFIX}_set_encrypt_key
+.size __aesni_set_encrypt_key,.-__aesni_set_encrypt_key
+___
+}
+
+$code.=<<___;
+.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
+.Lincrement1:
+ .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
+
+.asciz "AES for Intel AES-NI, CRYPTOGAMS by <appro\@openssl.org>"
+.align 64
+___
+
+# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame,
+# CONTEXT *context,DISPATCHER_CONTEXT *disp)
+if ($win64) {
+$rec="%rcx";
+$frame="%rdx";
+$context="%r8";
+$disp="%r9";
+
+$code.=<<___;
+.extern __imp_RtlVirtualUnwind
+___
+$code.=<<___ if ($PREFIX eq "aesni");
+.type ecb_ccm64_se_handler,\@abi-omnipotent
+.align 16
+ecb_ccm64_se_handler:
+ push %rsi
+ push %rdi
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+ pushfq
+ sub \$64,%rsp
+
+ mov 120($context),%rax # pull context->Rax
+ mov 248($context),%rbx # pull context->Rip
+
+ mov 8($disp),%rsi # disp->ImageBase
+ mov 56($disp),%r11 # disp->HandlerData
+
+ mov 0(%r11),%r10d # HandlerData[0]
+ lea (%rsi,%r10),%r10 # prologue label
+ cmp %r10,%rbx # context->Rip<prologue label
+ jb .Lcommon_seh_tail
+
+ mov 152($context),%rax # pull context->Rsp
+
+ mov 4(%r11),%r10d # HandlerData[1]
+ lea (%rsi,%r10),%r10 # epilogue label
+ cmp %r10,%rbx # context->Rip>=epilogue label
+ jae .Lcommon_seh_tail
+
+ lea 0(%rax),%rsi # %xmm save area
+ lea 512($context),%rdi # &context.Xmm6
+ mov \$8,%ecx # 4*sizeof(%xmm0)/sizeof(%rax)
+ .long 0xa548f3fc # cld; rep movsq
+ lea 0x58(%rax),%rax # adjust stack pointer
+
+ jmp .Lcommon_seh_tail
+.size ecb_ccm64_se_handler,.-ecb_ccm64_se_handler
+
+.type ctr_xts_se_handler,\@abi-omnipotent
+.align 16
+ctr_xts_se_handler:
+ push %rsi
+ push %rdi
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+ pushfq
+ sub \$64,%rsp
+
+ mov 120($context),%rax # pull context->Rax
+ mov 248($context),%rbx # pull context->Rip
+
+ mov 8($disp),%rsi # disp->ImageBase
+ mov 56($disp),%r11 # disp->HandlerData
+
+ mov 0(%r11),%r10d # HandlerData[0]
+ lea (%rsi,%r10),%r10 # prologue lable
+ cmp %r10,%rbx # context->Rip<prologue label
+ jb .Lcommon_seh_tail
+
+ mov 152($context),%rax # pull context->Rsp
+
+ mov 4(%r11),%r10d # HandlerData[1]
+ lea (%rsi,%r10),%r10 # epilogue label
+ cmp %r10,%rbx # context->Rip>=epilogue label
+ jae .Lcommon_seh_tail
+
+ mov 160($context),%rax # pull context->Rbp
+ lea -0xa0(%rax),%rsi # %xmm save area
+ lea 512($context),%rdi # & context.Xmm6
+ mov \$20,%ecx # 10*sizeof(%xmm0)/sizeof(%rax)
+ .long 0xa548f3fc # cld; rep movsq
+
+ jmp .Lcommon_rbp_tail
+.size ctr_xts_se_handler,.-ctr_xts_se_handler
+___
+$code.=<<___;
+.type cbc_se_handler,\@abi-omnipotent
+.align 16
+cbc_se_handler:
+ push %rsi
+ push %rdi
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+ pushfq
+ sub \$64,%rsp
+
+ mov 152($context),%rax # pull context->Rsp
+ mov 248($context),%rbx # pull context->Rip
+
+ lea .Lcbc_decrypt(%rip),%r10
+ cmp %r10,%rbx # context->Rip<"prologue" label
+ jb .Lcommon_seh_tail
+
+ lea .Lcbc_decrypt_body(%rip),%r10
+ cmp %r10,%rbx # context->Rip<cbc_decrypt_body
+ jb .Lrestore_cbc_rax
+
+ lea .Lcbc_ret(%rip),%r10
+ cmp %r10,%rbx # context->Rip>="epilogue" label
+ jae .Lcommon_seh_tail
+
+ lea 16(%rax),%rsi # %xmm save area
+ lea 512($context),%rdi # &context.Xmm6
+ mov \$20,%ecx # 10*sizeof(%xmm0)/sizeof(%rax)
+ .long 0xa548f3fc # cld; rep movsq
+
+.Lcommon_rbp_tail:
+ mov 160($context),%rax # pull context->Rbp
+ mov (%rax),%rbp # restore saved %rbp
+ lea 8(%rax),%rax # adjust stack pointer
+ mov %rbp,160($context) # restore context->Rbp
+ jmp .Lcommon_seh_tail
+
+.Lrestore_cbc_rax:
+ mov 120($context),%rax
+
+.Lcommon_seh_tail:
+ mov 8(%rax),%rdi
+ mov 16(%rax),%rsi
+ mov %rax,152($context) # restore context->Rsp
+ mov %rsi,168($context) # restore context->Rsi
+ mov %rdi,176($context) # restore context->Rdi
+
+ mov 40($disp),%rdi # disp->ContextRecord
+ mov $context,%rsi # context
+ mov \$154,%ecx # sizeof(CONTEXT)
+ .long 0xa548f3fc # cld; rep movsq
+
+ mov $disp,%rsi
+ xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER
+ mov 8(%rsi),%rdx # arg2, disp->ImageBase
+ mov 0(%rsi),%r8 # arg3, disp->ControlPc
+ mov 16(%rsi),%r9 # arg4, disp->FunctionEntry
+ mov 40(%rsi),%r10 # disp->ContextRecord
+ lea 56(%rsi),%r11 # &disp->HandlerData
+ lea 24(%rsi),%r12 # &disp->EstablisherFrame
+ mov %r10,32(%rsp) # arg5
+ mov %r11,40(%rsp) # arg6
+ mov %r12,48(%rsp) # arg7
+ mov %rcx,56(%rsp) # arg8, (NULL)
+ call *__imp_RtlVirtualUnwind(%rip)
+
+ mov \$1,%eax # ExceptionContinueSearch
+ add \$64,%rsp
+ popfq
+ pop %r15
+ pop %r14
+ pop %r13
+ pop %r12
+ pop %rbp
+ pop %rbx
+ pop %rdi
+ pop %rsi
+ ret
+.size cbc_se_handler,.-cbc_se_handler
+
+.section .pdata
+.align 4
+___
+$code.=<<___ if ($PREFIX eq "aesni");
+ .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
+___
+$code.=<<___;
+ .rva .LSEH_begin_${PREFIX}_cbc_encrypt
+ .rva .LSEH_end_${PREFIX}_cbc_encrypt
+ .rva .LSEH_info_cbc
+
+ .rva ${PREFIX}_set_decrypt_key
+ .rva .LSEH_end_set_decrypt_key
+ .rva .LSEH_info_key
+
+ .rva ${PREFIX}_set_encrypt_key
+ .rva .LSEH_end_set_encrypt_key
+ .rva .LSEH_info_key
+.section .xdata
+.align 8
+___
+$code.=<<___ if ($PREFIX eq "aesni");
+.LSEH_info_ecb:
+ .byte 9,0,0,0
+ .rva ecb_ccm64_se_handler
+ .rva .Lecb_enc_body,.Lecb_enc_ret # HandlerData[]
+.LSEH_info_ccm64_enc:
+ .byte 9,0,0,0
+ .rva ecb_ccm64_se_handler
+ .rva .Lccm64_enc_body,.Lccm64_enc_ret # HandlerData[]
+.LSEH_info_ccm64_dec:
+ .byte 9,0,0,0
+ .rva ecb_ccm64_se_handler
+ .rva .Lccm64_dec_body,.Lccm64_dec_ret # HandlerData[]
+.LSEH_info_ctr32:
+ .byte 9,0,0,0
+ .rva ctr_xts_se_handler
+ .rva .Lctr32_body,.Lctr32_epilogue # HandlerData[]
+.LSEH_info_xts_enc:
+ .byte 9,0,0,0
+ .rva ctr_xts_se_handler
+ .rva .Lxts_enc_body,.Lxts_enc_epilogue # HandlerData[]
+.LSEH_info_xts_dec:
+ .byte 9,0,0,0
+ .rva ctr_xts_se_handler
+ .rva .Lxts_dec_body,.Lxts_dec_epilogue # HandlerData[]
+___
+$code.=<<___;
+.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 # sub rsp,8
+___
+}
+
+sub rex {
+ local *opcode=shift;
+ my ($dst,$src)=@_;
+ my $rex=0;
+
+ $rex|=0x04 if($dst>=8);
+ $rex|=0x01 if($src>=8);
+ push @opcode,$rex|0x40 if($rex);
+}
+
+sub aesni {
+ my $line=shift;
+ my @opcode=(0x66);
+
+ if ($line=~/(aeskeygenassist)\s+\$([x0-9a-f]+),\s*%xmm([0-9]+),\s*%xmm([0-9]+)/) {
+ rex(\@opcode,$4,$3);
+ push @opcode,0x0f,0x3a,0xdf;
+ push @opcode,0xc0|($3&7)|(($4&7)<<3); # ModR/M
+ my $c=$2;
+ push @opcode,$c=~/^0/?oct($c):$c;
+ return ".byte\t".join(',',@opcode);
+ }
+ elsif ($line=~/(aes[a-z]+)\s+%xmm([0-9]+),\s*%xmm([0-9]+)/) {
+ my %opcodelet = (
+ "aesimc" => 0xdb,
+ "aesenc" => 0xdc, "aesenclast" => 0xdd,
+ "aesdec" => 0xde, "aesdeclast" => 0xdf
+ );
+ return undef if (!defined($opcodelet{$1}));
+ rex(\@opcode,$3,$2);
+ push @opcode,0x0f,0x38,$opcodelet{$1};
+ push @opcode,0xc0|($2&7)|(($3&7)<<3); # ModR/M
+ return ".byte\t".join(',',@opcode);
+ }
+ elsif ($line=~/(aes[a-z]+)\s+([0x1-9a-fA-F]*)\(%rsp\),\s*%xmm([0-9]+)/) {
+ my %opcodelet = (
+ "aesenc" => 0xdc, "aesenclast" => 0xdd,
+ "aesdec" => 0xde, "aesdeclast" => 0xdf
+ );
+ return undef if (!defined($opcodelet{$1}));
+ my $off = $2;
+ push @opcode,0x44 if ($3>=8);
+ push @opcode,0x0f,0x38,$opcodelet{$1};
+ push @opcode,0x44|(($3&7)<<3),0x24; # ModR/M
+ push @opcode,($off=~/^0/?oct($off):$off)&0xff;
+ return ".byte\t".join(',',@opcode);
+ }
+ return $line;
+}
+
+sub movbe {
+ ".byte 0x0f,0x38,0xf1,0x44,0x24,".shift;
+}
+
+$code =~ s/\`([^\`]*)\`/eval($1)/gem;
+$code =~ s/\b(aes.*%xmm[0-9]+).*$/aesni($1)/gem;
+#$code =~ s/\bmovbe\s+%eax/bswap %eax; mov %eax/gm; # debugging artefact
+$code =~ s/\bmovbe\s+%eax,\s*([0-9]+)\(%rsp\)/movbe($1)/gem;
+
+print $code;
+
+close STDOUT;
diff --git a/src/crypto/aes/asm/aesv8-armx.pl b/src/crypto/aes/asm/aesv8-armx.pl
new file mode 100644
index 0000000..1e93f86
--- /dev/null
+++ b/src/crypto/aes/asm/aesv8-armx.pl
@@ -0,0 +1,962 @@
+#!/usr/bin/env perl
+#
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+# project. The module is, however, dual licensed under OpenSSL and
+# CRYPTOGAMS licenses depending on where you obtain it. For further
+# details see http://www.openssl.org/~appro/cryptogams/.
+# ====================================================================
+#
+# This module implements support for ARMv8 AES instructions. The
+# module is endian-agnostic in sense that it supports both big- and
+# little-endian cases. As does it support both 32- and 64-bit modes
+# of operation. Latter is achieved by limiting amount of utilized
+# registers to 16, which implies additional NEON load and integer
+# instructions. This has no effect on mighty Apple A7, where results
+# are literally equal to the theoretical estimates based on AES
+# instruction latencies and issue rates. On Cortex-A53, an in-order
+# execution core, this costs up to 10-15%, which is partially
+# compensated by implementing dedicated code path for 128-bit
+# CBC encrypt case. On Cortex-A57 parallelizable mode performance
+# seems to be limited by sheer amount of NEON instructions...
+#
+# Performance in cycles per byte processed with 128-bit key:
+#
+# CBC enc CBC dec CTR
+# Apple A7 2.39 1.20 1.20
+# Cortex-A53 2.45 1.87 1.94
+# Cortex-A57 3.64 1.34 1.32
+
+$flavour = shift;
+open STDOUT,">".shift;
+
+$prefix="aes_v8";
+
+$code=<<___;
+#include "arm_arch.h"
+
+#if __ARM_MAX_ARCH__>=7
+.text
+___
+$code.=".arch armv8-a+crypto\n" if ($flavour =~ /64/);
+$code.=".arch armv7-a\n.fpu neon\n.code 32\n" if ($flavour !~ /64/);
+ #^^^^^^ this is done to simplify adoption by not depending
+ # on latest binutils.
+
+# Assembler mnemonics are an eclectic mix of 32- and 64-bit syntax,
+# NEON is mostly 32-bit mnemonics, integer - mostly 64. Goal is to
+# maintain both 32- and 64-bit codes within single module and
+# transliterate common code to either flavour with regex vodoo.
+#
+{{{
+my ($inp,$bits,$out,$ptr,$rounds)=("x0","w1","x2","x3","w12");
+my ($zero,$rcon,$mask,$in0,$in1,$tmp,$key)=
+ $flavour=~/64/? map("q$_",(0..6)) : map("q$_",(0..3,8..10));
+
+
+$code.=<<___;
+.align 5
+rcon:
+.long 0x01,0x01,0x01,0x01
+.long 0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d // rotate-n-splat
+.long 0x1b,0x1b,0x1b,0x1b
+
+.globl ${prefix}_set_encrypt_key
+.type ${prefix}_set_encrypt_key,%function
+.align 5
+${prefix}_set_encrypt_key:
+.Lenc_key:
+___
+$code.=<<___ if ($flavour =~ /64/);
+ stp x29,x30,[sp,#-16]!
+ add x29,sp,#0
+___
+$code.=<<___;
+ mov $ptr,#-1
+ cmp $inp,#0
+ b.eq .Lenc_key_abort
+ cmp $out,#0
+ b.eq .Lenc_key_abort
+ mov $ptr,#-2
+ cmp $bits,#128
+ b.lt .Lenc_key_abort
+ cmp $bits,#256
+ b.gt .Lenc_key_abort
+ tst $bits,#0x3f
+ b.ne .Lenc_key_abort
+
+ adr $ptr,rcon
+ cmp $bits,#192
+
+ veor $zero,$zero,$zero
+ vld1.8 {$in0},[$inp],#16
+ mov $bits,#8 // reuse $bits
+ vld1.32 {$rcon,$mask},[$ptr],#32
+
+ b.lt .Loop128
+ b.eq .L192
+ b .L256
+
+.align 4
+.Loop128:
+ vtbl.8 $key,{$in0},$mask
+ vext.8 $tmp,$zero,$in0,#12
+ vst1.32 {$in0},[$out],#16
+ aese $key,$zero
+ subs $bits,$bits,#1
+
+ veor $in0,$in0,$tmp
+ vext.8 $tmp,$zero,$tmp,#12
+ veor $in0,$in0,$tmp
+ vext.8 $tmp,$zero,$tmp,#12
+ veor $key,$key,$rcon
+ veor $in0,$in0,$tmp
+ vshl.u8 $rcon,$rcon,#1
+ veor $in0,$in0,$key
+ b.ne .Loop128
+
+ vld1.32 {$rcon},[$ptr]
+
+ vtbl.8 $key,{$in0},$mask
+ vext.8 $tmp,$zero,$in0,#12
+ vst1.32 {$in0},[$out],#16
+ aese $key,$zero
+
+ veor $in0,$in0,$tmp
+ vext.8 $tmp,$zero,$tmp,#12
+ veor $in0,$in0,$tmp
+ vext.8 $tmp,$zero,$tmp,#12
+ veor $key,$key,$rcon
+ veor $in0,$in0,$tmp
+ vshl.u8 $rcon,$rcon,#1
+ veor $in0,$in0,$key
+
+ vtbl.8 $key,{$in0},$mask
+ vext.8 $tmp,$zero,$in0,#12
+ vst1.32 {$in0},[$out],#16
+ aese $key,$zero
+
+ veor $in0,$in0,$tmp
+ vext.8 $tmp,$zero,$tmp,#12
+ veor $in0,$in0,$tmp
+ vext.8 $tmp,$zero,$tmp,#12
+ veor $key,$key,$rcon
+ veor $in0,$in0,$tmp
+ veor $in0,$in0,$key
+ vst1.32 {$in0},[$out]
+ add $out,$out,#0x50
+
+ mov $rounds,#10
+ b .Ldone
+
+.align 4
+.L192:
+ vld1.8 {$in1},[$inp],#8
+ vmov.i8 $key,#8 // borrow $key
+ vst1.32 {$in0},[$out],#16
+ vsub.i8 $mask,$mask,$key // adjust the mask
+
+.Loop192:
+ vtbl.8 $key,{$in1},$mask
+ vext.8 $tmp,$zero,$in0,#12
+ vst1.32 {$in1},[$out],#8
+ aese $key,$zero
+ subs $bits,$bits,#1
+
+ veor $in0,$in0,$tmp
+ vext.8 $tmp,$zero,$tmp,#12
+ veor $in0,$in0,$tmp
+ vext.8 $tmp,$zero,$tmp,#12
+ veor $in0,$in0,$tmp
+
+ vdup.32 $tmp,${in0}[3]
+ veor $tmp,$tmp,$in1
+ veor $key,$key,$rcon
+ vext.8 $in1,$zero,$in1,#12
+ vshl.u8 $rcon,$rcon,#1
+ veor $in1,$in1,$tmp
+ veor $in0,$in0,$key
+ veor $in1,$in1,$key
+ vst1.32 {$in0},[$out],#16
+ b.ne .Loop192
+
+ mov $rounds,#12
+ add $out,$out,#0x20
+ b .Ldone
+
+.align 4
+.L256:
+ vld1.8 {$in1},[$inp]
+ mov $bits,#7
+ mov $rounds,#14
+ vst1.32 {$in0},[$out],#16
+
+.Loop256:
+ vtbl.8 $key,{$in1},$mask
+ vext.8 $tmp,$zero,$in0,#12
+ vst1.32 {$in1},[$out],#16
+ aese $key,$zero
+ subs $bits,$bits,#1
+
+ veor $in0,$in0,$tmp
+ vext.8 $tmp,$zero,$tmp,#12
+ veor $in0,$in0,$tmp
+ vext.8 $tmp,$zero,$tmp,#12
+ veor $key,$key,$rcon
+ veor $in0,$in0,$tmp
+ vshl.u8 $rcon,$rcon,#1
+ veor $in0,$in0,$key
+ vst1.32 {$in0},[$out],#16
+ b.eq .Ldone
+
+ vdup.32 $key,${in0}[3] // just splat
+ vext.8 $tmp,$zero,$in1,#12
+ aese $key,$zero
+
+ veor $in1,$in1,$tmp
+ vext.8 $tmp,$zero,$tmp,#12
+ veor $in1,$in1,$tmp
+ vext.8 $tmp,$zero,$tmp,#12
+ veor $in1,$in1,$tmp
+
+ veor $in1,$in1,$key
+ b .Loop256
+
+.Ldone:
+ str $rounds,[$out]
+ mov $ptr,#0
+
+.Lenc_key_abort:
+ mov x0,$ptr // return value
+ `"ldr x29,[sp],#16" if ($flavour =~ /64/)`
+ ret
+.size ${prefix}_set_encrypt_key,.-${prefix}_set_encrypt_key
+
+.globl ${prefix}_set_decrypt_key
+.type ${prefix}_set_decrypt_key,%function
+.align 5
+${prefix}_set_decrypt_key:
+___
+$code.=<<___ if ($flavour =~ /64/);
+ stp x29,x30,[sp,#-16]!
+ add x29,sp,#0
+___
+$code.=<<___ if ($flavour !~ /64/);
+ stmdb sp!,{r4,lr}
+___
+$code.=<<___;
+ bl .Lenc_key
+
+ cmp x0,#0
+ b.ne .Ldec_key_abort
+
+ sub $out,$out,#240 // restore original $out
+ mov x4,#-16
+ add $inp,$out,x12,lsl#4 // end of key schedule
+
+ vld1.32 {v0.16b},[$out]
+ vld1.32 {v1.16b},[$inp]
+ vst1.32 {v0.16b},[$inp],x4
+ vst1.32 {v1.16b},[$out],#16
+
+.Loop_imc:
+ vld1.32 {v0.16b},[$out]
+ vld1.32 {v1.16b},[$inp]
+ aesimc v0.16b,v0.16b
+ aesimc v1.16b,v1.16b
+ vst1.32 {v0.16b},[$inp],x4
+ vst1.32 {v1.16b},[$out],#16
+ cmp $inp,$out
+ b.hi .Loop_imc
+
+ vld1.32 {v0.16b},[$out]
+ aesimc v0.16b,v0.16b
+ vst1.32 {v0.16b},[$inp]
+
+ eor x0,x0,x0 // return value
+.Ldec_key_abort:
+___
+$code.=<<___ if ($flavour !~ /64/);
+ ldmia sp!,{r4,pc}
+___
+$code.=<<___ if ($flavour =~ /64/);
+ ldp x29,x30,[sp],#16
+ ret
+___
+$code.=<<___;
+.size ${prefix}_set_decrypt_key,.-${prefix}_set_decrypt_key
+___
+}}}
+{{{
+sub gen_block () {
+my $dir = shift;
+my ($e,$mc) = $dir eq "en" ? ("e","mc") : ("d","imc");
+my ($inp,$out,$key)=map("x$_",(0..2));
+my $rounds="w3";
+my ($rndkey0,$rndkey1,$inout)=map("q$_",(0..3));
+
+$code.=<<___;
+.globl ${prefix}_${dir}crypt
+.type ${prefix}_${dir}crypt,%function
+.align 5
+${prefix}_${dir}crypt:
+ ldr $rounds,[$key,#240]
+ vld1.32 {$rndkey0},[$key],#16
+ vld1.8 {$inout},[$inp]
+ sub $rounds,$rounds,#2
+ vld1.32 {$rndkey1},[$key],#16
+
+.Loop_${dir}c:
+ aes$e $inout,$rndkey0
+ vld1.32 {$rndkey0},[$key],#16
+ aes$mc $inout,$inout
+ subs $rounds,$rounds,#2
+ aes$e $inout,$rndkey1
+ vld1.32 {$rndkey1},[$key],#16
+ aes$mc $inout,$inout
+ b.gt .Loop_${dir}c
+
+ aes$e $inout,$rndkey0
+ vld1.32 {$rndkey0},[$key]
+ aes$mc $inout,$inout
+ aes$e $inout,$rndkey1
+ veor $inout,$inout,$rndkey0
+
+ vst1.8 {$inout},[$out]
+ ret
+.size ${prefix}_${dir}crypt,.-${prefix}_${dir}crypt
+___
+}
+&gen_block("en");
+&gen_block("de");
+}}}
+{{{
+my ($inp,$out,$len,$key,$ivp)=map("x$_",(0..4)); my $enc="w5";
+my ($rounds,$cnt,$key_,$step,$step1)=($enc,"w6","x7","x8","x12");
+my ($dat0,$dat1,$in0,$in1,$tmp0,$tmp1,$ivec,$rndlast)=map("q$_",(0..7));
+
+my ($dat,$tmp,$rndzero_n_last)=($dat0,$tmp0,$tmp1);
+
+### q8-q15 preloaded key schedule
+
+$code.=<<___;
+.globl ${prefix}_cbc_encrypt
+.type ${prefix}_cbc_encrypt,%function
+.align 5
+${prefix}_cbc_encrypt:
+___
+$code.=<<___ if ($flavour =~ /64/);
+ stp x29,x30,[sp,#-16]!
+ add x29,sp,#0
+___
+$code.=<<___ if ($flavour !~ /64/);
+ mov ip,sp
+ stmdb sp!,{r4-r8,lr}
+ vstmdb sp!,{d8-d15} @ ABI specification says so
+ ldmia ip,{r4-r5} @ load remaining args
+___
+$code.=<<___;
+ subs $len,$len,#16
+ mov $step,#16
+ b.lo .Lcbc_abort
+ cclr $step,eq
+
+ cmp $enc,#0 // en- or decrypting?
+ ldr $rounds,[$key,#240]
+ and $len,$len,#-16
+ vld1.8 {$ivec},[$ivp]
+ vld1.8 {$dat},[$inp],$step
+
+ vld1.32 {q8-q9},[$key] // load key schedule...
+ sub $rounds,$rounds,#6
+ add $key_,$key,x5,lsl#4 // pointer to last 7 round keys
+ sub $rounds,$rounds,#2
+ vld1.32 {q10-q11},[$key_],#32
+ vld1.32 {q12-q13},[$key_],#32
+ vld1.32 {q14-q15},[$key_],#32
+ vld1.32 {$rndlast},[$key_]
+
+ add $key_,$key,#32
+ mov $cnt,$rounds
+ b.eq .Lcbc_dec
+
+ cmp $rounds,#2
+ veor $dat,$dat,$ivec
+ veor $rndzero_n_last,q8,$rndlast
+ b.eq .Lcbc_enc128
+
+.Loop_cbc_enc:
+ aese $dat,q8
+ vld1.32 {q8},[$key_],#16
+ aesmc $dat,$dat
+ subs $cnt,$cnt,#2
+ aese $dat,q9
+ vld1.32 {q9},[$key_],#16
+ aesmc $dat,$dat
+ b.gt .Loop_cbc_enc
+
+ aese $dat,q8
+ aesmc $dat,$dat
+ subs $len,$len,#16
+ aese $dat,q9
+ aesmc $dat,$dat
+ cclr $step,eq
+ aese $dat,q10
+ aesmc $dat,$dat
+ add $key_,$key,#16
+ aese $dat,q11
+ aesmc $dat,$dat
+ vld1.8 {q8},[$inp],$step
+ aese $dat,q12
+ aesmc $dat,$dat
+ veor q8,q8,$rndzero_n_last
+ aese $dat,q13
+ aesmc $dat,$dat
+ vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1]
+ aese $dat,q14
+ aesmc $dat,$dat
+ aese $dat,q15
+
+ mov $cnt,$rounds
+ veor $ivec,$dat,$rndlast
+ vst1.8 {$ivec},[$out],#16
+ b.hs .Loop_cbc_enc
+
+ b .Lcbc_done
+
+.align 5
+.Lcbc_enc128:
+ vld1.32 {$in0-$in1},[$key_]
+ aese $dat,q8
+ aesmc $dat,$dat
+ b .Lenter_cbc_enc128
+.Loop_cbc_enc128:
+ aese $dat,q8
+ aesmc $dat,$dat
+ vst1.8 {$ivec},[$out],#16
+.Lenter_cbc_enc128:
+ aese $dat,q9
+ aesmc $dat,$dat
+ subs $len,$len,#16
+ aese $dat,$in0
+ aesmc $dat,$dat
+ cclr $step,eq
+ aese $dat,$in1
+ aesmc $dat,$dat
+ aese $dat,q10
+ aesmc $dat,$dat
+ aese $dat,q11
+ aesmc $dat,$dat
+ vld1.8 {q8},[$inp],$step
+ aese $dat,q12
+ aesmc $dat,$dat
+ aese $dat,q13
+ aesmc $dat,$dat
+ aese $dat,q14
+ aesmc $dat,$dat
+ veor q8,q8,$rndzero_n_last
+ aese $dat,q15
+ veor $ivec,$dat,$rndlast
+ b.hs .Loop_cbc_enc128
+
+ vst1.8 {$ivec},[$out],#16
+ b .Lcbc_done
+___
+{
+my ($dat2,$in2,$tmp2)=map("q$_",(10,11,9));
+$code.=<<___;
+.align 5
+.Lcbc_dec:
+ vld1.8 {$dat2},[$inp],#16
+ subs $len,$len,#32 // bias
+ add $cnt,$rounds,#2
+ vorr $in1,$dat,$dat
+ vorr $dat1,$dat,$dat
+ vorr $in2,$dat2,$dat2
+ b.lo .Lcbc_dec_tail
+
+ vorr $dat1,$dat2,$dat2
+ vld1.8 {$dat2},[$inp],#16
+ vorr $in0,$dat,$dat
+ vorr $in1,$dat1,$dat1
+ vorr $in2,$dat2,$dat2
+
+.Loop3x_cbc_dec:
+ aesd $dat0,q8
+ aesd $dat1,q8
+ aesd $dat2,q8
+ vld1.32 {q8},[$key_],#16
+ aesimc $dat0,$dat0
+ aesimc $dat1,$dat1
+ aesimc $dat2,$dat2
+ subs $cnt,$cnt,#2
+ aesd $dat0,q9
+ aesd $dat1,q9
+ aesd $dat2,q9
+ vld1.32 {q9},[$key_],#16
+ aesimc $dat0,$dat0
+ aesimc $dat1,$dat1
+ aesimc $dat2,$dat2
+ b.gt .Loop3x_cbc_dec
+
+ aesd $dat0,q8
+ aesd $dat1,q8
+ aesd $dat2,q8
+ veor $tmp0,$ivec,$rndlast
+ aesimc $dat0,$dat0
+ aesimc $dat1,$dat1
+ aesimc $dat2,$dat2
+ veor $tmp1,$in0,$rndlast
+ aesd $dat0,q9
+ aesd $dat1,q9
+ aesd $dat2,q9
+ veor $tmp2,$in1,$rndlast
+ subs $len,$len,#0x30
+ aesimc $dat0,$dat0
+ aesimc $dat1,$dat1
+ aesimc $dat2,$dat2
+ vorr $ivec,$in2,$in2
+ mov.lo x6,$len // x6, $cnt, is zero at this point
+ aesd $dat0,q12
+ aesd $dat1,q12
+ aesd $dat2,q12
+ add $inp,$inp,x6 // $inp is adjusted in such way that
+ // at exit from the loop $dat1-$dat2
+ // are loaded with last "words"
+ aesimc $dat0,$dat0
+ aesimc $dat1,$dat1
+ aesimc $dat2,$dat2
+ mov $key_,$key
+ aesd $dat0,q13
+ aesd $dat1,q13
+ aesd $dat2,q13
+ vld1.8 {$in0},[$inp],#16
+ aesimc $dat0,$dat0
+ aesimc $dat1,$dat1
+ aesimc $dat2,$dat2
+ vld1.8 {$in1},[$inp],#16
+ aesd $dat0,q14
+ aesd $dat1,q14
+ aesd $dat2,q14
+ vld1.8 {$in2},[$inp],#16
+ aesimc $dat0,$dat0
+ aesimc $dat1,$dat1
+ aesimc $dat2,$dat2
+ vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0]
+ aesd $dat0,q15
+ aesd $dat1,q15
+ aesd $dat2,q15
+
+ add $cnt,$rounds,#2
+ veor $tmp0,$tmp0,$dat0
+ veor $tmp1,$tmp1,$dat1
+ veor $dat2,$dat2,$tmp2
+ vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1]
+ vorr $dat0,$in0,$in0
+ vst1.8 {$tmp0},[$out],#16
+ vorr $dat1,$in1,$in1
+ vst1.8 {$tmp1},[$out],#16
+ vst1.8 {$dat2},[$out],#16
+ vorr $dat2,$in2,$in2
+ b.hs .Loop3x_cbc_dec
+
+ cmn $len,#0x30
+ b.eq .Lcbc_done
+ nop
+
+.Lcbc_dec_tail:
+ aesd $dat1,q8
+ aesd $dat2,q8
+ vld1.32 {q8},[$key_],#16
+ aesimc $dat1,$dat1
+ aesimc $dat2,$dat2
+ subs $cnt,$cnt,#2
+ aesd $dat1,q9
+ aesd $dat2,q9
+ vld1.32 {q9},[$key_],#16
+ aesimc $dat1,$dat1
+ aesimc $dat2,$dat2
+ b.gt .Lcbc_dec_tail
+
+ aesd $dat1,q8
+ aesd $dat2,q8
+ aesimc $dat1,$dat1
+ aesimc $dat2,$dat2
+ aesd $dat1,q9
+ aesd $dat2,q9
+ aesimc $dat1,$dat1
+ aesimc $dat2,$dat2
+ aesd $dat1,q12
+ aesd $dat2,q12
+ aesimc $dat1,$dat1
+ aesimc $dat2,$dat2
+ cmn $len,#0x20
+ aesd $dat1,q13
+ aesd $dat2,q13
+ aesimc $dat1,$dat1
+ aesimc $dat2,$dat2
+ veor $tmp1,$ivec,$rndlast
+ aesd $dat1,q14
+ aesd $dat2,q14
+ aesimc $dat1,$dat1
+ aesimc $dat2,$dat2
+ veor $tmp2,$in1,$rndlast
+ aesd $dat1,q15
+ aesd $dat2,q15
+ b.eq .Lcbc_dec_one
+ veor $tmp1,$tmp1,$dat1
+ veor $tmp2,$tmp2,$dat2
+ vorr $ivec,$in2,$in2
+ vst1.8 {$tmp1},[$out],#16
+ vst1.8 {$tmp2},[$out],#16
+ b .Lcbc_done
+
+.Lcbc_dec_one:
+ veor $tmp1,$tmp1,$dat2
+ vorr $ivec,$in2,$in2
+ vst1.8 {$tmp1},[$out],#16
+
+.Lcbc_done:
+ vst1.8 {$ivec},[$ivp]
+.Lcbc_abort:
+___
+}
+$code.=<<___ if ($flavour !~ /64/);
+ vldmia sp!,{d8-d15}
+ ldmia sp!,{r4-r8,pc}
+___
+$code.=<<___ if ($flavour =~ /64/);
+ ldr x29,[sp],#16
+ ret
+___
+$code.=<<___;
+.size ${prefix}_cbc_encrypt,.-${prefix}_cbc_encrypt
+___
+}}}
+{{{
+my ($inp,$out,$len,$key,$ivp)=map("x$_",(0..4));
+my ($rounds,$cnt,$key_)=("w5","w6","x7");
+my ($ctr,$tctr0,$tctr1,$tctr2)=map("w$_",(8..10,12));
+my $step="x12"; # aliases with $tctr2
+
+my ($dat0,$dat1,$in0,$in1,$tmp0,$tmp1,$ivec,$rndlast)=map("q$_",(0..7));
+my ($dat2,$in2,$tmp2)=map("q$_",(10,11,9));
+
+my ($dat,$tmp)=($dat0,$tmp0);
+
+### q8-q15 preloaded key schedule
+
+$code.=<<___;
+.globl ${prefix}_ctr32_encrypt_blocks
+.type ${prefix}_ctr32_encrypt_blocks,%function
+.align 5
+${prefix}_ctr32_encrypt_blocks:
+___
+$code.=<<___ if ($flavour =~ /64/);
+ stp x29,x30,[sp,#-16]!
+ add x29,sp,#0
+___
+$code.=<<___ if ($flavour !~ /64/);
+ mov ip,sp
+ stmdb sp!,{r4-r10,lr}
+ vstmdb sp!,{d8-d15} @ ABI specification says so
+ ldr r4, [ip] @ load remaining arg
+___
+$code.=<<___;
+ ldr $rounds,[$key,#240]
+
+ ldr $ctr, [$ivp, #12]
+ vld1.32 {$dat0},[$ivp]
+
+ vld1.32 {q8-q9},[$key] // load key schedule...
+ sub $rounds,$rounds,#4
+ mov $step,#16
+ cmp $len,#2
+ add $key_,$key,x5,lsl#4 // pointer to last 5 round keys
+ sub $rounds,$rounds,#2
+ vld1.32 {q12-q13},[$key_],#32
+ vld1.32 {q14-q15},[$key_],#32
+ vld1.32 {$rndlast},[$key_]
+ add $key_,$key,#32
+ mov $cnt,$rounds
+ cclr $step,lo
+#ifndef __ARMEB__
+ rev $ctr, $ctr
+#endif
+ vorr $dat1,$dat0,$dat0
+ add $tctr1, $ctr, #1
+ vorr $dat2,$dat0,$dat0
+ add $ctr, $ctr, #2
+ vorr $ivec,$dat0,$dat0
+ rev $tctr1, $tctr1
+ vmov.32 ${dat1}[3],$tctr1
+ b.ls .Lctr32_tail
+ rev $tctr2, $ctr
+ sub $len,$len,#3 // bias
+ vmov.32 ${dat2}[3],$tctr2
+ b .Loop3x_ctr32
+
+.align 4
+.Loop3x_ctr32:
+ aese $dat0,q8
+ aese $dat1,q8
+ aese $dat2,q8
+ vld1.32 {q8},[$key_],#16
+ aesmc $dat0,$dat0
+ aesmc $dat1,$dat1
+ aesmc $dat2,$dat2
+ subs $cnt,$cnt,#2
+ aese $dat0,q9
+ aese $dat1,q9
+ aese $dat2,q9
+ vld1.32 {q9},[$key_],#16
+ aesmc $dat0,$dat0
+ aesmc $dat1,$dat1
+ aesmc $dat2,$dat2
+ b.gt .Loop3x_ctr32
+
+ aese $dat0,q8
+ aese $dat1,q8
+ aese $dat2,q8
+ mov $key_,$key
+ aesmc $tmp0,$dat0
+ vld1.8 {$in0},[$inp],#16
+ aesmc $tmp1,$dat1
+ aesmc $dat2,$dat2
+ vorr $dat0,$ivec,$ivec
+ aese $tmp0,q9
+ vld1.8 {$in1},[$inp],#16
+ aese $tmp1,q9
+ aese $dat2,q9
+ vorr $dat1,$ivec,$ivec
+ aesmc $tmp0,$tmp0
+ vld1.8 {$in2},[$inp],#16
+ aesmc $tmp1,$tmp1
+ aesmc $tmp2,$dat2
+ vorr $dat2,$ivec,$ivec
+ add $tctr0,$ctr,#1
+ aese $tmp0,q12
+ aese $tmp1,q12
+ aese $tmp2,q12
+ veor $in0,$in0,$rndlast
+ add $tctr1,$ctr,#2
+ aesmc $tmp0,$tmp0
+ aesmc $tmp1,$tmp1
+ aesmc $tmp2,$tmp2
+ veor $in1,$in1,$rndlast
+ add $ctr,$ctr,#3
+ aese $tmp0,q13
+ aese $tmp1,q13
+ aese $tmp2,q13
+ veor $in2,$in2,$rndlast
+ rev $tctr0,$tctr0
+ aesmc $tmp0,$tmp0
+ vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0]
+ aesmc $tmp1,$tmp1
+ aesmc $tmp2,$tmp2
+ vmov.32 ${dat0}[3], $tctr0
+ rev $tctr1,$tctr1
+ aese $tmp0,q14
+ aese $tmp1,q14
+ aese $tmp2,q14
+ vmov.32 ${dat1}[3], $tctr1
+ rev $tctr2,$ctr
+ aesmc $tmp0,$tmp0
+ aesmc $tmp1,$tmp1
+ aesmc $tmp2,$tmp2
+ vmov.32 ${dat2}[3], $tctr2
+ subs $len,$len,#3
+ aese $tmp0,q15
+ aese $tmp1,q15
+ aese $tmp2,q15
+
+ mov $cnt,$rounds
+ veor $in0,$in0,$tmp0
+ veor $in1,$in1,$tmp1
+ veor $in2,$in2,$tmp2
+ vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1]
+ vst1.8 {$in0},[$out],#16
+ vst1.8 {$in1},[$out],#16
+ vst1.8 {$in2},[$out],#16
+ b.hs .Loop3x_ctr32
+
+ adds $len,$len,#3
+ b.eq .Lctr32_done
+ cmp $len,#1
+ mov $step,#16
+ cclr $step,eq
+
+.Lctr32_tail:
+ aese $dat0,q8
+ aese $dat1,q8
+ vld1.32 {q8},[$key_],#16
+ aesmc $dat0,$dat0
+ aesmc $dat1,$dat1
+ subs $cnt,$cnt,#2
+ aese $dat0,q9
+ aese $dat1,q9
+ vld1.32 {q9},[$key_],#16
+ aesmc $dat0,$dat0
+ aesmc $dat1,$dat1
+ b.gt .Lctr32_tail
+
+ aese $dat0,q8
+ aese $dat1,q8
+ aesmc $dat0,$dat0
+ aesmc $dat1,$dat1
+ aese $dat0,q9
+ aese $dat1,q9
+ aesmc $dat0,$dat0
+ aesmc $dat1,$dat1
+ vld1.8 {$in0},[$inp],$step
+ aese $dat0,q12
+ aese $dat1,q12
+ vld1.8 {$in1},[$inp]
+ aesmc $dat0,$dat0
+ aesmc $dat1,$dat1
+ aese $dat0,q13
+ aese $dat1,q13
+ aesmc $dat0,$dat0
+ aesmc $dat1,$dat1
+ aese $dat0,q14
+ aese $dat1,q14
+ veor $in0,$in0,$rndlast
+ aesmc $dat0,$dat0
+ aesmc $dat1,$dat1
+ veor $in1,$in1,$rndlast
+ aese $dat0,q15
+ aese $dat1,q15
+
+ cmp $len,#1
+ veor $in0,$in0,$dat0
+ veor $in1,$in1,$dat1
+ vst1.8 {$in0},[$out],#16
+ b.eq .Lctr32_done
+ vst1.8 {$in1},[$out]
+
+.Lctr32_done:
+___
+$code.=<<___ if ($flavour !~ /64/);
+ vldmia sp!,{d8-d15}
+ ldmia sp!,{r4-r10,pc}
+___
+$code.=<<___ if ($flavour =~ /64/);
+ ldr x29,[sp],#16
+ ret
+___
+$code.=<<___;
+.size ${prefix}_ctr32_encrypt_blocks,.-${prefix}_ctr32_encrypt_blocks
+___
+}}}
+$code.=<<___;
+#endif
+___
+########################################
+if ($flavour =~ /64/) { ######## 64-bit code
+ my %opcode = (
+ "aesd" => 0x4e285800, "aese" => 0x4e284800,
+ "aesimc"=> 0x4e287800, "aesmc" => 0x4e286800 );
+
+ local *unaes = sub {
+ my ($mnemonic,$arg)=@_;
+
+ $arg =~ m/[qv]([0-9]+)[^,]*,\s*[qv]([0-9]+)/o &&
+ sprintf ".inst\t0x%08x\t//%s %s",
+ $opcode{$mnemonic}|$1|($2<<5),
+ $mnemonic,$arg;
+ };
+
+ foreach(split("\n",$code)) {
+ s/\`([^\`]*)\`/eval($1)/geo;
+
+ s/\bq([0-9]+)\b/"v".($1<8?$1:$1+8).".16b"/geo; # old->new registers
+ s/@\s/\/\//o; # old->new style commentary
+
+ #s/[v]?(aes\w+)\s+([qv].*)/unaes($1,$2)/geo or
+ s/cclr\s+([wx])([^,]+),\s*([a-z]+)/csel $1$2,$1zr,$1$2,$3/o or
+ s/mov\.([a-z]+)\s+([wx][0-9]+),\s*([wx][0-9]+)/csel $2,$3,$2,$1/o or
+ s/vmov\.i8/movi/o or # fix up legacy mnemonics
+ s/vext\.8/ext/o or
+ s/vrev32\.8/rev32/o or
+ s/vtst\.8/cmtst/o or
+ s/vshr/ushr/o or
+ s/^(\s+)v/$1/o or # strip off v prefix
+ s/\bbx\s+lr\b/ret/o;
+
+ # fix up remainig legacy suffixes
+ s/\.[ui]?8//o;
+ m/\],#8/o and s/\.16b/\.8b/go;
+ s/\.[ui]?32//o and s/\.16b/\.4s/go;
+ s/\.[ui]?64//o and s/\.16b/\.2d/go;
+ s/\.[42]([sd])\[([0-3])\]/\.$1\[$2\]/o;
+
+ print $_,"\n";
+ }
+} else { ######## 32-bit code
+ my %opcode = (
+ "aesd" => 0xf3b00340, "aese" => 0xf3b00300,
+ "aesimc"=> 0xf3b003c0, "aesmc" => 0xf3b00380 );
+
+ local *unaes = sub {
+ my ($mnemonic,$arg)=@_;
+
+ if ($arg =~ m/[qv]([0-9]+)[^,]*,\s*[qv]([0-9]+)/o) {
+ my $word = $opcode{$mnemonic}|(($1&7)<<13)|(($1&8)<<19)
+ |(($2&7)<<1) |(($2&8)<<2);
+ # since ARMv7 instructions are always encoded little-endian.
+ # correct solution is to use .inst directive, but older
+ # assemblers don't implement it:-(
+ sprintf ".byte\t0x%02x,0x%02x,0x%02x,0x%02x\t@ %s %s",
+ $word&0xff,($word>>8)&0xff,
+ ($word>>16)&0xff,($word>>24)&0xff,
+ $mnemonic,$arg;
+ }
+ };
+
+ sub unvtbl {
+ my $arg=shift;
+
+ $arg =~ m/q([0-9]+),\s*\{q([0-9]+)\},\s*q([0-9]+)/o &&
+ sprintf "vtbl.8 d%d,{q%d},d%d\n\t".
+ "vtbl.8 d%d,{q%d},d%d", 2*$1,$2,2*$3, 2*$1+1,$2,2*$3+1;
+ }
+
+ sub unvdup32 {
+ my $arg=shift;
+
+ $arg =~ m/q([0-9]+),\s*q([0-9]+)\[([0-3])\]/o &&
+ sprintf "vdup.32 q%d,d%d[%d]",$1,2*$2+($3>>1),$3&1;
+ }
+
+ sub unvmov32 {
+ my $arg=shift;
+
+ $arg =~ m/q([0-9]+)\[([0-3])\],(.*)/o &&
+ sprintf "vmov.32 d%d[%d],%s",2*$1+($2>>1),$2&1,$3;
+ }
+
+ foreach(split("\n",$code)) {
+ s/\`([^\`]*)\`/eval($1)/geo;
+
+ s/\b[wx]([0-9]+)\b/r$1/go; # new->old registers
+ s/\bv([0-9])\.[12468]+[bsd]\b/q$1/go; # new->old registers
+ s/\/\/\s?/@ /o; # new->old style commentary
+
+ # fix up remainig new-style suffixes
+ s/\{q([0-9]+)\},\s*\[(.+)\],#8/sprintf "{d%d},[$2]!",2*$1/eo or
+ s/\],#[0-9]+/]!/o;
+
+ s/[v]?(aes\w+)\s+([qv].*)/unaes($1,$2)/geo or
+ s/cclr\s+([^,]+),\s*([a-z]+)/mov$2 $1,#0/o or
+ s/vtbl\.8\s+(.*)/unvtbl($1)/geo or
+ s/vdup\.32\s+(.*)/unvdup32($1)/geo or
+ s/vmov\.32\s+(.*)/unvmov32($1)/geo or
+ s/^(\s+)b\./$1b/o or
+ s/^(\s+)mov\./$1mov/o or
+ s/^(\s+)ret/$1bx\tlr/o;
+
+ print $_,"\n";
+ }
+}
+
+close STDOUT;
diff --git a/src/crypto/aes/asm/bsaes-armv7.pl b/src/crypto/aes/asm/bsaes-armv7.pl
new file mode 100644
index 0000000..d70f3ea
--- /dev/null
+++ b/src/crypto/aes/asm/bsaes-armv7.pl
@@ -0,0 +1,2477 @@
+#!/usr/bin/env perl
+
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+# project. The module is, however, dual licensed under OpenSSL and
+# CRYPTOGAMS licenses depending on where you obtain it. For further
+# details see http://www.openssl.org/~appro/cryptogams/.
+#
+# Specific modes and adaptation for Linux kernel by Ard Biesheuvel
+# <ard.biesheuvel@linaro.org>. Permission to use under GPL terms is
+# granted.
+# ====================================================================
+
+# Bit-sliced AES for ARM NEON
+#
+# February 2012.
+#
+# This implementation is direct adaptation of bsaes-x86_64 module for
+# ARM NEON. Except that this module is endian-neutral [in sense that
+# it can be compiled for either endianness] by courtesy of vld1.8's
+# neutrality. Initial version doesn't implement interface to OpenSSL,
+# only low-level primitives and unsupported entry points, just enough
+# to collect performance results, which for Cortex-A8 core are:
+#
+# encrypt 19.5 cycles per byte processed with 128-bit key
+# decrypt 22.1 cycles per byte processed with 128-bit key
+# key conv. 440 cycles per 128-bit key/0.18 of 8x block
+#
+# Snapdragon S4 encrypts byte in 17.6 cycles and decrypts in 19.7,
+# which is [much] worse than anticipated (for further details see
+# http://www.openssl.org/~appro/Snapdragon-S4.html).
+#
+# Cortex-A15 manages in 14.2/16.1 cycles [when integer-only code
+# manages in 20.0 cycles].
+#
+# When comparing to x86_64 results keep in mind that NEON unit is
+# [mostly] single-issue and thus can't [fully] benefit from
+# instruction-level parallelism. And when comparing to aes-armv4
+# results keep in mind key schedule conversion overhead (see
+# bsaes-x86_64.pl for further details)...
+#
+# <appro@openssl.org>
+
+# April-August 2013
+#
+# Add CBC, CTR and XTS subroutines, adapt for kernel use.
+#
+# <ard.biesheuvel@linaro.org>
+
+while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {}
+open STDOUT,">$output";
+
+my ($inp,$out,$len,$key)=("r0","r1","r2","r3");
+my @XMM=map("q$_",(0..15));
+
+{
+my ($key,$rounds,$const)=("r4","r5","r6");
+
+sub Dlo() { shift=~m|q([1]?[0-9])|?"d".($1*2):""; }
+sub Dhi() { shift=~m|q([1]?[0-9])|?"d".($1*2+1):""; }
+
+sub Sbox {
+# input in lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb
+# output in lsb > [b0, b1, b4, b6, b3, b7, b2, b5] < msb
+my @b=@_[0..7];
+my @t=@_[8..11];
+my @s=@_[12..15];
+ &InBasisChange (@b);
+ &Inv_GF256 (@b[6,5,0,3,7,1,4,2],@t,@s);
+ &OutBasisChange (@b[7,1,4,2,6,5,0,3]);
+}
+
+sub InBasisChange {
+# input in lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb
+# output in lsb > [b6, b5, b0, b3, b7, b1, b4, b2] < msb
+my @b=@_[0..7];
+$code.=<<___;
+ veor @b[2], @b[2], @b[1]
+ veor @b[5], @b[5], @b[6]
+ veor @b[3], @b[3], @b[0]
+ veor @b[6], @b[6], @b[2]
+ veor @b[5], @b[5], @b[0]
+
+ veor @b[6], @b[6], @b[3]
+ veor @b[3], @b[3], @b[7]
+ veor @b[7], @b[7], @b[5]
+ veor @b[3], @b[3], @b[4]
+ veor @b[4], @b[4], @b[5]
+
+ veor @b[2], @b[2], @b[7]
+ veor @b[3], @b[3], @b[1]
+ veor @b[1], @b[1], @b[5]
+___
+}
+
+sub OutBasisChange {
+# input in lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb
+# output in lsb > [b6, b1, b2, b4, b7, b0, b3, b5] < msb
+my @b=@_[0..7];
+$code.=<<___;
+ veor @b[0], @b[0], @b[6]
+ veor @b[1], @b[1], @b[4]
+ veor @b[4], @b[4], @b[6]
+ veor @b[2], @b[2], @b[0]
+ veor @b[6], @b[6], @b[1]
+
+ veor @b[1], @b[1], @b[5]
+ veor @b[5], @b[5], @b[3]
+ veor @b[3], @b[3], @b[7]
+ veor @b[7], @b[7], @b[5]
+ veor @b[2], @b[2], @b[5]
+
+ veor @b[4], @b[4], @b[7]
+___
+}
+
+sub InvSbox {
+# input in lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb
+# output in lsb > [b0, b1, b6, b4, b2, b7, b3, b5] < msb
+my @b=@_[0..7];
+my @t=@_[8..11];
+my @s=@_[12..15];
+ &InvInBasisChange (@b);
+ &Inv_GF256 (@b[5,1,2,6,3,7,0,4],@t,@s);
+ &InvOutBasisChange (@b[3,7,0,4,5,1,2,6]);
+}
+
+sub InvInBasisChange { # OutBasisChange in reverse (with twist)
+my @b=@_[5,1,2,6,3,7,0,4];
+$code.=<<___
+ veor @b[1], @b[1], @b[7]
+ veor @b[4], @b[4], @b[7]
+
+ veor @b[7], @b[7], @b[5]
+ veor @b[1], @b[1], @b[3]
+ veor @b[2], @b[2], @b[5]
+ veor @b[3], @b[3], @b[7]
+
+ veor @b[6], @b[6], @b[1]
+ veor @b[2], @b[2], @b[0]
+ veor @b[5], @b[5], @b[3]
+ veor @b[4], @b[4], @b[6]
+ veor @b[0], @b[0], @b[6]
+ veor @b[1], @b[1], @b[4]
+___
+}
+
+sub InvOutBasisChange { # InBasisChange in reverse
+my @b=@_[2,5,7,3,6,1,0,4];
+$code.=<<___;
+ veor @b[1], @b[1], @b[5]
+ veor @b[2], @b[2], @b[7]
+
+ veor @b[3], @b[3], @b[1]
+ veor @b[4], @b[4], @b[5]
+ veor @b[7], @b[7], @b[5]
+ veor @b[3], @b[3], @b[4]
+ veor @b[5], @b[5], @b[0]
+ veor @b[3], @b[3], @b[7]
+ veor @b[6], @b[6], @b[2]
+ veor @b[2], @b[2], @b[1]
+ veor @b[6], @b[6], @b[3]
+
+ veor @b[3], @b[3], @b[0]
+ veor @b[5], @b[5], @b[6]
+___
+}
+
+sub Mul_GF4 {
+#;*************************************************************
+#;* Mul_GF4: Input x0-x1,y0-y1 Output x0-x1 Temp t0 (8) *
+#;*************************************************************
+my ($x0,$x1,$y0,$y1,$t0,$t1)=@_;
+$code.=<<___;
+ veor $t0, $y0, $y1
+ vand $t0, $t0, $x0
+ veor $x0, $x0, $x1
+ vand $t1, $x1, $y0
+ vand $x0, $x0, $y1
+ veor $x1, $t1, $t0
+ veor $x0, $x0, $t1
+___
+}
+
+sub Mul_GF4_N { # not used, see next subroutine
+# multiply and scale by N
+my ($x0,$x1,$y0,$y1,$t0)=@_;
+$code.=<<___;
+ veor $t0, $y0, $y1
+ vand $t0, $t0, $x0
+ veor $x0, $x0, $x1
+ vand $x1, $x1, $y0
+ vand $x0, $x0, $y1
+ veor $x1, $x1, $x0
+ veor $x0, $x0, $t0
+___
+}
+
+sub Mul_GF4_N_GF4 {
+# interleaved Mul_GF4_N and Mul_GF4
+my ($x0,$x1,$y0,$y1,$t0,
+ $x2,$x3,$y2,$y3,$t1)=@_;
+$code.=<<___;
+ veor $t0, $y0, $y1
+ veor $t1, $y2, $y3
+ vand $t0, $t0, $x0
+ vand $t1, $t1, $x2
+ veor $x0, $x0, $x1
+ veor $x2, $x2, $x3
+ vand $x1, $x1, $y0
+ vand $x3, $x3, $y2
+ vand $x0, $x0, $y1
+ vand $x2, $x2, $y3
+ veor $x1, $x1, $x0
+ veor $x2, $x2, $x3
+ veor $x0, $x0, $t0
+ veor $x3, $x3, $t1
+___
+}
+sub Mul_GF16_2 {
+my @x=@_[0..7];
+my @y=@_[8..11];
+my @t=@_[12..15];
+$code.=<<___;
+ veor @t[0], @x[0], @x[2]
+ veor @t[1], @x[1], @x[3]
+___
+ &Mul_GF4 (@x[0], @x[1], @y[0], @y[1], @t[2..3]);
+$code.=<<___;
+ veor @y[0], @y[0], @y[2]
+ veor @y[1], @y[1], @y[3]
+___
+ Mul_GF4_N_GF4 (@t[0], @t[1], @y[0], @y[1], @t[3],
+ @x[2], @x[3], @y[2], @y[3], @t[2]);
+$code.=<<___;
+ veor @x[0], @x[0], @t[0]
+ veor @x[2], @x[2], @t[0]
+ veor @x[1], @x[1], @t[1]
+ veor @x[3], @x[3], @t[1]
+
+ veor @t[0], @x[4], @x[6]
+ veor @t[1], @x[5], @x[7]
+___
+ &Mul_GF4_N_GF4 (@t[0], @t[1], @y[0], @y[1], @t[3],
+ @x[6], @x[7], @y[2], @y[3], @t[2]);
+$code.=<<___;
+ veor @y[0], @y[0], @y[2]
+ veor @y[1], @y[1], @y[3]
+___
+ &Mul_GF4 (@x[4], @x[5], @y[0], @y[1], @t[2..3]);
+$code.=<<___;
+ veor @x[4], @x[4], @t[0]
+ veor @x[6], @x[6], @t[0]
+ veor @x[5], @x[5], @t[1]
+ veor @x[7], @x[7], @t[1]
+___
+}
+sub Inv_GF256 {
+#;********************************************************************
+#;* Inv_GF256: Input x0-x7 Output x0-x7 Temp t0-t3,s0-s3 (144) *
+#;********************************************************************
+my @x=@_[0..7];
+my @t=@_[8..11];
+my @s=@_[12..15];
+# direct optimizations from hardware
+$code.=<<___;
+ veor @t[3], @x[4], @x[6]
+ veor @t[2], @x[5], @x[7]
+ veor @t[1], @x[1], @x[3]
+ veor @s[1], @x[7], @x[6]
+ vmov @t[0], @t[2]
+ veor @s[0], @x[0], @x[2]
+
+ vorr @t[2], @t[2], @t[1]
+ veor @s[3], @t[3], @t[0]
+ vand @s[2], @t[3], @s[0]
+ vorr @t[3], @t[3], @s[0]
+ veor @s[0], @s[0], @t[1]
+ vand @t[0], @t[0], @t[1]
+ veor @t[1], @x[3], @x[2]
+ vand @s[3], @s[3], @s[0]
+ vand @s[1], @s[1], @t[1]
+ veor @t[1], @x[4], @x[5]
+ veor @s[0], @x[1], @x[0]
+ veor @t[3], @t[3], @s[1]
+ veor @t[2], @t[2], @s[1]
+ vand @s[1], @t[1], @s[0]
+ vorr @t[1], @t[1], @s[0]
+ veor @t[3], @t[3], @s[3]
+ veor @t[0], @t[0], @s[1]
+ veor @t[2], @t[2], @s[2]
+ veor @t[1], @t[1], @s[3]
+ veor @t[0], @t[0], @s[2]
+ vand @s[0], @x[7], @x[3]
+ veor @t[1], @t[1], @s[2]
+ vand @s[1], @x[6], @x[2]
+ vand @s[2], @x[5], @x[1]
+ vorr @s[3], @x[4], @x[0]
+ veor @t[3], @t[3], @s[0]
+ veor @t[1], @t[1], @s[2]
+ veor @t[0], @t[0], @s[3]
+ veor @t[2], @t[2], @s[1]
+
+ @ Inv_GF16 \t0, \t1, \t2, \t3, \s0, \s1, \s2, \s3
+
+ @ new smaller inversion
+
+ vand @s[2], @t[3], @t[1]
+ vmov @s[0], @t[0]
+
+ veor @s[1], @t[2], @s[2]
+ veor @s[3], @t[0], @s[2]
+ veor @s[2], @t[0], @s[2] @ @s[2]=@s[3]
+
+ vbsl @s[1], @t[1], @t[0]
+ vbsl @s[3], @t[3], @t[2]
+ veor @t[3], @t[3], @t[2]
+
+ vbsl @s[0], @s[1], @s[2]
+ vbsl @t[0], @s[2], @s[1]
+
+ vand @s[2], @s[0], @s[3]
+ veor @t[1], @t[1], @t[0]
+
+ veor @s[2], @s[2], @t[3]
+___
+# output in s3, s2, s1, t1
+
+# Mul_GF16_2 \x0, \x1, \x2, \x3, \x4, \x5, \x6, \x7, \t2, \t3, \t0, \t1, \s0, \s1, \s2, \s3
+
+# Mul_GF16_2 \x0, \x1, \x2, \x3, \x4, \x5, \x6, \x7, \s3, \s2, \s1, \t1, \s0, \t0, \t2, \t3
+ &Mul_GF16_2(@x,@s[3,2,1],@t[1],@s[0],@t[0,2,3]);
+
+### output msb > [x3,x2,x1,x0,x7,x6,x5,x4] < lsb
+}
+
+# AES linear components
+
+sub ShiftRows {
+my @x=@_[0..7];
+my @t=@_[8..11];
+my $mask=pop;
+$code.=<<___;
+ vldmia $key!, {@t[0]-@t[3]}
+ veor @t[0], @t[0], @x[0]
+ veor @t[1], @t[1], @x[1]
+ vtbl.8 `&Dlo(@x[0])`, {@t[0]}, `&Dlo($mask)`
+ vtbl.8 `&Dhi(@x[0])`, {@t[0]}, `&Dhi($mask)`
+ vldmia $key!, {@t[0]}
+ veor @t[2], @t[2], @x[2]
+ vtbl.8 `&Dlo(@x[1])`, {@t[1]}, `&Dlo($mask)`
+ vtbl.8 `&Dhi(@x[1])`, {@t[1]}, `&Dhi($mask)`
+ vldmia $key!, {@t[1]}
+ veor @t[3], @t[3], @x[3]
+ vtbl.8 `&Dlo(@x[2])`, {@t[2]}, `&Dlo($mask)`
+ vtbl.8 `&Dhi(@x[2])`, {@t[2]}, `&Dhi($mask)`
+ vldmia $key!, {@t[2]}
+ vtbl.8 `&Dlo(@x[3])`, {@t[3]}, `&Dlo($mask)`
+ vtbl.8 `&Dhi(@x[3])`, {@t[3]}, `&Dhi($mask)`
+ vldmia $key!, {@t[3]}
+ veor @t[0], @t[0], @x[4]
+ veor @t[1], @t[1], @x[5]
+ vtbl.8 `&Dlo(@x[4])`, {@t[0]}, `&Dlo($mask)`
+ vtbl.8 `&Dhi(@x[4])`, {@t[0]}, `&Dhi($mask)`
+ veor @t[2], @t[2], @x[6]
+ vtbl.8 `&Dlo(@x[5])`, {@t[1]}, `&Dlo($mask)`
+ vtbl.8 `&Dhi(@x[5])`, {@t[1]}, `&Dhi($mask)`
+ veor @t[3], @t[3], @x[7]
+ vtbl.8 `&Dlo(@x[6])`, {@t[2]}, `&Dlo($mask)`
+ vtbl.8 `&Dhi(@x[6])`, {@t[2]}, `&Dhi($mask)`
+ vtbl.8 `&Dlo(@x[7])`, {@t[3]}, `&Dlo($mask)`
+ vtbl.8 `&Dhi(@x[7])`, {@t[3]}, `&Dhi($mask)`
+___
+}
+
+sub MixColumns {
+# modified to emit output in order suitable for feeding back to aesenc[last]
+my @x=@_[0..7];
+my @t=@_[8..15];
+my $inv=@_[16]; # optional
+$code.=<<___;
+ vext.8 @t[0], @x[0], @x[0], #12 @ x0 <<< 32
+ vext.8 @t[1], @x[1], @x[1], #12
+ veor @x[0], @x[0], @t[0] @ x0 ^ (x0 <<< 32)
+ vext.8 @t[2], @x[2], @x[2], #12
+ veor @x[1], @x[1], @t[1]
+ vext.8 @t[3], @x[3], @x[3], #12
+ veor @x[2], @x[2], @t[2]
+ vext.8 @t[4], @x[4], @x[4], #12
+ veor @x[3], @x[3], @t[3]
+ vext.8 @t[5], @x[5], @x[5], #12
+ veor @x[4], @x[4], @t[4]
+ vext.8 @t[6], @x[6], @x[6], #12
+ veor @x[5], @x[5], @t[5]
+ vext.8 @t[7], @x[7], @x[7], #12
+ veor @x[6], @x[6], @t[6]
+
+ veor @t[1], @t[1], @x[0]
+ veor @x[7], @x[7], @t[7]
+ vext.8 @x[0], @x[0], @x[0], #8 @ (x0 ^ (x0 <<< 32)) <<< 64)
+ veor @t[2], @t[2], @x[1]
+ veor @t[0], @t[0], @x[7]
+ veor @t[1], @t[1], @x[7]
+ vext.8 @x[1], @x[1], @x[1], #8
+ veor @t[5], @t[5], @x[4]
+ veor @x[0], @x[0], @t[0]
+ veor @t[6], @t[6], @x[5]
+ veor @x[1], @x[1], @t[1]
+ vext.8 @t[0], @x[4], @x[4], #8
+ veor @t[4], @t[4], @x[3]
+ vext.8 @t[1], @x[5], @x[5], #8
+ veor @t[7], @t[7], @x[6]
+ vext.8 @x[4], @x[3], @x[3], #8
+ veor @t[3], @t[3], @x[2]
+ vext.8 @x[5], @x[7], @x[7], #8
+ veor @t[4], @t[4], @x[7]
+ vext.8 @x[3], @x[6], @x[6], #8
+ veor @t[3], @t[3], @x[7]
+ vext.8 @x[6], @x[2], @x[2], #8
+ veor @x[7], @t[1], @t[5]
+___
+$code.=<<___ if (!$inv);
+ veor @x[2], @t[0], @t[4]
+ veor @x[4], @x[4], @t[3]
+ veor @x[5], @x[5], @t[7]
+ veor @x[3], @x[3], @t[6]
+ @ vmov @x[2], @t[0]
+ veor @x[6], @x[6], @t[2]
+ @ vmov @x[7], @t[1]
+___
+$code.=<<___ if ($inv);
+ veor @t[3], @t[3], @x[4]
+ veor @x[5], @x[5], @t[7]
+ veor @x[2], @x[3], @t[6]
+ veor @x[3], @t[0], @t[4]
+ veor @x[4], @x[6], @t[2]
+ vmov @x[6], @t[3]
+ @ vmov @x[7], @t[1]
+___
+}
+
+sub InvMixColumns_orig {
+my @x=@_[0..7];
+my @t=@_[8..15];
+
+$code.=<<___;
+ @ multiplication by 0x0e
+ vext.8 @t[7], @x[7], @x[7], #12
+ vmov @t[2], @x[2]
+ veor @x[2], @x[2], @x[5] @ 2 5
+ veor @x[7], @x[7], @x[5] @ 7 5
+ vext.8 @t[0], @x[0], @x[0], #12
+ vmov @t[5], @x[5]
+ veor @x[5], @x[5], @x[0] @ 5 0 [1]
+ veor @x[0], @x[0], @x[1] @ 0 1
+ vext.8 @t[1], @x[1], @x[1], #12
+ veor @x[1], @x[1], @x[2] @ 1 25
+ veor @x[0], @x[0], @x[6] @ 01 6 [2]
+ vext.8 @t[3], @x[3], @x[3], #12
+ veor @x[1], @x[1], @x[3] @ 125 3 [4]
+ veor @x[2], @x[2], @x[0] @ 25 016 [3]
+ veor @x[3], @x[3], @x[7] @ 3 75
+ veor @x[7], @x[7], @x[6] @ 75 6 [0]
+ vext.8 @t[6], @x[6], @x[6], #12
+ vmov @t[4], @x[4]
+ veor @x[6], @x[6], @x[4] @ 6 4
+ veor @x[4], @x[4], @x[3] @ 4 375 [6]
+ veor @x[3], @x[3], @x[7] @ 375 756=36
+ veor @x[6], @x[6], @t[5] @ 64 5 [7]
+ veor @x[3], @x[3], @t[2] @ 36 2
+ vext.8 @t[5], @t[5], @t[5], #12
+ veor @x[3], @x[3], @t[4] @ 362 4 [5]
+___
+ my @y = @x[7,5,0,2,1,3,4,6];
+$code.=<<___;
+ @ multiplication by 0x0b
+ veor @y[1], @y[1], @y[0]
+ veor @y[0], @y[0], @t[0]
+ vext.8 @t[2], @t[2], @t[2], #12
+ veor @y[1], @y[1], @t[1]
+ veor @y[0], @y[0], @t[5]
+ vext.8 @t[4], @t[4], @t[4], #12
+ veor @y[1], @y[1], @t[6]
+ veor @y[0], @y[0], @t[7]
+ veor @t[7], @t[7], @t[6] @ clobber t[7]
+
+ veor @y[3], @y[3], @t[0]
+ veor @y[1], @y[1], @y[0]
+ vext.8 @t[0], @t[0], @t[0], #12
+ veor @y[2], @y[2], @t[1]
+ veor @y[4], @y[4], @t[1]
+ vext.8 @t[1], @t[1], @t[1], #12
+ veor @y[2], @y[2], @t[2]
+ veor @y[3], @y[3], @t[2]
+ veor @y[5], @y[5], @t[2]
+ veor @y[2], @y[2], @t[7]
+ vext.8 @t[2], @t[2], @t[2], #12
+ veor @y[3], @y[3], @t[3]
+ veor @y[6], @y[6], @t[3]
+ veor @y[4], @y[4], @t[3]
+ veor @y[7], @y[7], @t[4]
+ vext.8 @t[3], @t[3], @t[3], #12
+ veor @y[5], @y[5], @t[4]
+ veor @y[7], @y[7], @t[7]
+ veor @t[7], @t[7], @t[5] @ clobber t[7] even more
+ veor @y[3], @y[3], @t[5]
+ veor @y[4], @y[4], @t[4]
+
+ veor @y[5], @y[5], @t[7]
+ vext.8 @t[4], @t[4], @t[4], #12
+ veor @y[6], @y[6], @t[7]
+ veor @y[4], @y[4], @t[7]
+
+ veor @t[7], @t[7], @t[5]
+ vext.8 @t[5], @t[5], @t[5], #12
+
+ @ multiplication by 0x0d
+ veor @y[4], @y[4], @y[7]
+ veor @t[7], @t[7], @t[6] @ restore t[7]
+ veor @y[7], @y[7], @t[4]
+ vext.8 @t[6], @t[6], @t[6], #12
+ veor @y[2], @y[2], @t[0]
+ veor @y[7], @y[7], @t[5]
+ vext.8 @t[7], @t[7], @t[7], #12
+ veor @y[2], @y[2], @t[2]
+
+ veor @y[3], @y[3], @y[1]
+ veor @y[1], @y[1], @t[1]
+ veor @y[0], @y[0], @t[0]
+ veor @y[3], @y[3], @t[0]
+ veor @y[1], @y[1], @t[5]
+ veor @y[0], @y[0], @t[5]
+ vext.8 @t[0], @t[0], @t[0], #12
+ veor @y[1], @y[1], @t[7]
+ veor @y[0], @y[0], @t[6]
+ veor @y[3], @y[3], @y[1]
+ veor @y[4], @y[4], @t[1]
+ vext.8 @t[1], @t[1], @t[1], #12
+
+ veor @y[7], @y[7], @t[7]
+ veor @y[4], @y[4], @t[2]
+ veor @y[5], @y[5], @t[2]
+ veor @y[2], @y[2], @t[6]
+ veor @t[6], @t[6], @t[3] @ clobber t[6]
+ vext.8 @t[2], @t[2], @t[2], #12
+ veor @y[4], @y[4], @y[7]
+ veor @y[3], @y[3], @t[6]
+
+ veor @y[6], @y[6], @t[6]
+ veor @y[5], @y[5], @t[5]
+ vext.8 @t[5], @t[5], @t[5], #12
+ veor @y[6], @y[6], @t[4]
+ vext.8 @t[4], @t[4], @t[4], #12
+ veor @y[5], @y[5], @t[6]
+ veor @y[6], @y[6], @t[7]
+ vext.8 @t[7], @t[7], @t[7], #12
+ veor @t[6], @t[6], @t[3] @ restore t[6]
+ vext.8 @t[3], @t[3], @t[3], #12
+
+ @ multiplication by 0x09
+ veor @y[4], @y[4], @y[1]
+ veor @t[1], @t[1], @y[1] @ t[1]=y[1]
+ veor @t[0], @t[0], @t[5] @ clobber t[0]
+ vext.8 @t[6], @t[6], @t[6], #12
+ veor @t[1], @t[1], @t[5]
+ veor @y[3], @y[3], @t[0]
+ veor @t[0], @t[0], @y[0] @ t[0]=y[0]
+ veor @t[1], @t[1], @t[6]
+ veor @t[6], @t[6], @t[7] @ clobber t[6]
+ veor @y[4], @y[4], @t[1]
+ veor @y[7], @y[7], @t[4]
+ veor @y[6], @y[6], @t[3]
+ veor @y[5], @y[5], @t[2]
+ veor @t[4], @t[4], @y[4] @ t[4]=y[4]
+ veor @t[3], @t[3], @y[3] @ t[3]=y[3]
+ veor @t[5], @t[5], @y[5] @ t[5]=y[5]
+ veor @t[2], @t[2], @y[2] @ t[2]=y[2]
+ veor @t[3], @t[3], @t[7]
+ veor @XMM[5], @t[5], @t[6]
+ veor @XMM[6], @t[6], @y[6] @ t[6]=y[6]
+ veor @XMM[2], @t[2], @t[6]
+ veor @XMM[7], @t[7], @y[7] @ t[7]=y[7]
+
+ vmov @XMM[0], @t[0]
+ vmov @XMM[1], @t[1]
+ @ vmov @XMM[2], @t[2]
+ vmov @XMM[3], @t[3]
+ vmov @XMM[4], @t[4]
+ @ vmov @XMM[5], @t[5]
+ @ vmov @XMM[6], @t[6]
+ @ vmov @XMM[7], @t[7]
+___
+}
+
+sub InvMixColumns {
+my @x=@_[0..7];
+my @t=@_[8..15];
+
+# Thanks to Jussi Kivilinna for providing pointer to
+#
+# | 0e 0b 0d 09 | | 02 03 01 01 | | 05 00 04 00 |
+# | 09 0e 0b 0d | = | 01 02 03 01 | x | 00 05 00 04 |
+# | 0d 09 0e 0b | | 01 01 02 03 | | 04 00 05 00 |
+# | 0b 0d 09 0e | | 03 01 01 02 | | 00 04 00 05 |
+
+$code.=<<___;
+ @ multiplication by 0x05-0x00-0x04-0x00
+ vext.8 @t[0], @x[0], @x[0], #8
+ vext.8 @t[6], @x[6], @x[6], #8
+ vext.8 @t[7], @x[7], @x[7], #8
+ veor @t[0], @t[0], @x[0]
+ vext.8 @t[1], @x[1], @x[1], #8
+ veor @t[6], @t[6], @x[6]
+ vext.8 @t[2], @x[2], @x[2], #8
+ veor @t[7], @t[7], @x[7]
+ vext.8 @t[3], @x[3], @x[3], #8
+ veor @t[1], @t[1], @x[1]
+ vext.8 @t[4], @x[4], @x[4], #8
+ veor @t[2], @t[2], @x[2]
+ vext.8 @t[5], @x[5], @x[5], #8
+ veor @t[3], @t[3], @x[3]
+ veor @t[4], @t[4], @x[4]
+ veor @t[5], @t[5], @x[5]
+
+ veor @x[0], @x[0], @t[6]
+ veor @x[1], @x[1], @t[6]
+ veor @x[2], @x[2], @t[0]
+ veor @x[4], @x[4], @t[2]
+ veor @x[3], @x[3], @t[1]
+ veor @x[1], @x[1], @t[7]
+ veor @x[2], @x[2], @t[7]
+ veor @x[4], @x[4], @t[6]
+ veor @x[5], @x[5], @t[3]
+ veor @x[3], @x[3], @t[6]
+ veor @x[6], @x[6], @t[4]
+ veor @x[4], @x[4], @t[7]
+ veor @x[5], @x[5], @t[7]
+ veor @x[7], @x[7], @t[5]
+___
+ &MixColumns (@x,@t,1); # flipped 2<->3 and 4<->6
+}
+
+sub swapmove {
+my ($a,$b,$n,$mask,$t)=@_;
+$code.=<<___;
+ vshr.u64 $t, $b, #$n
+ veor $t, $t, $a
+ vand $t, $t, $mask
+ veor $a, $a, $t
+ vshl.u64 $t, $t, #$n
+ veor $b, $b, $t
+___
+}
+sub swapmove2x {
+my ($a0,$b0,$a1,$b1,$n,$mask,$t0,$t1)=@_;
+$code.=<<___;
+ vshr.u64 $t0, $b0, #$n
+ vshr.u64 $t1, $b1, #$n
+ veor $t0, $t0, $a0
+ veor $t1, $t1, $a1
+ vand $t0, $t0, $mask
+ vand $t1, $t1, $mask
+ veor $a0, $a0, $t0
+ vshl.u64 $t0, $t0, #$n
+ veor $a1, $a1, $t1
+ vshl.u64 $t1, $t1, #$n
+ veor $b0, $b0, $t0
+ veor $b1, $b1, $t1
+___
+}
+
+sub bitslice {
+my @x=reverse(@_[0..7]);
+my ($t0,$t1,$t2,$t3)=@_[8..11];
+$code.=<<___;
+ vmov.i8 $t0,#0x55 @ compose .LBS0
+ vmov.i8 $t1,#0x33 @ compose .LBS1
+___
+ &swapmove2x(@x[0,1,2,3],1,$t0,$t2,$t3);
+ &swapmove2x(@x[4,5,6,7],1,$t0,$t2,$t3);
+$code.=<<___;
+ vmov.i8 $t0,#0x0f @ compose .LBS2
+___
+ &swapmove2x(@x[0,2,1,3],2,$t1,$t2,$t3);
+ &swapmove2x(@x[4,6,5,7],2,$t1,$t2,$t3);
+
+ &swapmove2x(@x[0,4,1,5],4,$t0,$t2,$t3);
+ &swapmove2x(@x[2,6,3,7],4,$t0,$t2,$t3);
+}
+
+$code.=<<___;
+#if defined(__arm__)
+#ifndef __KERNEL__
+# include "arm_arch.h"
+
+# define VFP_ABI_PUSH vstmdb sp!,{d8-d15}
+# define VFP_ABI_POP vldmia sp!,{d8-d15}
+# define VFP_ABI_FRAME 0x40
+#else
+# define VFP_ABI_PUSH
+# define VFP_ABI_POP
+# define VFP_ABI_FRAME 0
+# define BSAES_ASM_EXTENDED_KEY
+# define XTS_CHAIN_TWEAK
+# define __ARM_ARCH__ __LINUX_ARM_ARCH__
+#endif
+
+#ifdef __thumb__
+# define adrl adr
+#endif
+
+#if __ARM_ARCH__>=7
+.text
+.syntax unified @ ARMv7-capable assembler is expected to handle this
+#ifdef __thumb2__
+.thumb
+#else
+.code 32
+#endif
+
+.fpu neon
+
+.type _bsaes_decrypt8,%function
+.align 4
+_bsaes_decrypt8:
+ adr $const,_bsaes_decrypt8
+ vldmia $key!, {@XMM[9]} @ round 0 key
+ add $const,$const,#.LM0ISR-_bsaes_decrypt8
+
+ vldmia $const!, {@XMM[8]} @ .LM0ISR
+ veor @XMM[10], @XMM[0], @XMM[9] @ xor with round0 key
+ veor @XMM[11], @XMM[1], @XMM[9]
+ vtbl.8 `&Dlo(@XMM[0])`, {@XMM[10]}, `&Dlo(@XMM[8])`
+ vtbl.8 `&Dhi(@XMM[0])`, {@XMM[10]}, `&Dhi(@XMM[8])`
+ veor @XMM[12], @XMM[2], @XMM[9]
+ vtbl.8 `&Dlo(@XMM[1])`, {@XMM[11]}, `&Dlo(@XMM[8])`
+ vtbl.8 `&Dhi(@XMM[1])`, {@XMM[11]}, `&Dhi(@XMM[8])`
+ veor @XMM[13], @XMM[3], @XMM[9]
+ vtbl.8 `&Dlo(@XMM[2])`, {@XMM[12]}, `&Dlo(@XMM[8])`
+ vtbl.8 `&Dhi(@XMM[2])`, {@XMM[12]}, `&Dhi(@XMM[8])`
+ veor @XMM[14], @XMM[4], @XMM[9]
+ vtbl.8 `&Dlo(@XMM[3])`, {@XMM[13]}, `&Dlo(@XMM[8])`
+ vtbl.8 `&Dhi(@XMM[3])`, {@XMM[13]}, `&Dhi(@XMM[8])`
+ veor @XMM[15], @XMM[5], @XMM[9]
+ vtbl.8 `&Dlo(@XMM[4])`, {@XMM[14]}, `&Dlo(@XMM[8])`
+ vtbl.8 `&Dhi(@XMM[4])`, {@XMM[14]}, `&Dhi(@XMM[8])`
+ veor @XMM[10], @XMM[6], @XMM[9]
+ vtbl.8 `&Dlo(@XMM[5])`, {@XMM[15]}, `&Dlo(@XMM[8])`
+ vtbl.8 `&Dhi(@XMM[5])`, {@XMM[15]}, `&Dhi(@XMM[8])`
+ veor @XMM[11], @XMM[7], @XMM[9]
+ vtbl.8 `&Dlo(@XMM[6])`, {@XMM[10]}, `&Dlo(@XMM[8])`
+ vtbl.8 `&Dhi(@XMM[6])`, {@XMM[10]}, `&Dhi(@XMM[8])`
+ vtbl.8 `&Dlo(@XMM[7])`, {@XMM[11]}, `&Dlo(@XMM[8])`
+ vtbl.8 `&Dhi(@XMM[7])`, {@XMM[11]}, `&Dhi(@XMM[8])`
+___
+ &bitslice (@XMM[0..7, 8..11]);
+$code.=<<___;
+ sub $rounds,$rounds,#1
+ b .Ldec_sbox
+.align 4
+.Ldec_loop:
+___
+ &ShiftRows (@XMM[0..7, 8..12]);
+$code.=".Ldec_sbox:\n";
+ &InvSbox (@XMM[0..7, 8..15]);
+$code.=<<___;
+ subs $rounds,$rounds,#1
+ bcc .Ldec_done
+___
+ &InvMixColumns (@XMM[0,1,6,4,2,7,3,5, 8..15]);
+$code.=<<___;
+ vldmia $const, {@XMM[12]} @ .LISR
+ ite eq @ Thumb2 thing, sanity check in ARM
+ addeq $const,$const,#0x10
+ bne .Ldec_loop
+ vldmia $const, {@XMM[12]} @ .LISRM0
+ b .Ldec_loop
+.align 4
+.Ldec_done:
+___
+ &bitslice (@XMM[0,1,6,4,2,7,3,5, 8..11]);
+$code.=<<___;
+ vldmia $key, {@XMM[8]} @ last round key
+ veor @XMM[6], @XMM[6], @XMM[8]
+ veor @XMM[4], @XMM[4], @XMM[8]
+ veor @XMM[2], @XMM[2], @XMM[8]
+ veor @XMM[7], @XMM[7], @XMM[8]
+ veor @XMM[3], @XMM[3], @XMM[8]
+ veor @XMM[5], @XMM[5], @XMM[8]
+ veor @XMM[0], @XMM[0], @XMM[8]
+ veor @XMM[1], @XMM[1], @XMM[8]
+ bx lr
+.size _bsaes_decrypt8,.-_bsaes_decrypt8
+
+.type _bsaes_const,%object
+.align 6
+_bsaes_const:
+.LM0ISR: @ InvShiftRows constants
+ .quad 0x0a0e0206070b0f03, 0x0004080c0d010509
+.LISR:
+ .quad 0x0504070602010003, 0x0f0e0d0c080b0a09
+.LISRM0:
+ .quad 0x01040b0e0205080f, 0x0306090c00070a0d
+.LM0SR: @ ShiftRows constants
+ .quad 0x0a0e02060f03070b, 0x0004080c05090d01
+.LSR:
+ .quad 0x0504070600030201, 0x0f0e0d0c0a09080b
+.LSRM0:
+ .quad 0x0304090e00050a0f, 0x01060b0c0207080d
+.LM0:
+ .quad 0x02060a0e03070b0f, 0x0004080c0105090d
+.LREVM0SR:
+ .quad 0x090d01050c000408, 0x03070b0f060a0e02
+.asciz "Bit-sliced AES for NEON, CRYPTOGAMS by <appro\@openssl.org>"
+.align 6
+.size _bsaes_const,.-_bsaes_const
+
+.type _bsaes_encrypt8,%function
+.align 4
+_bsaes_encrypt8:
+ adr $const,_bsaes_encrypt8
+ vldmia $key!, {@XMM[9]} @ round 0 key
+ sub $const,$const,#_bsaes_encrypt8-.LM0SR
+
+ vldmia $const!, {@XMM[8]} @ .LM0SR
+_bsaes_encrypt8_alt:
+ veor @XMM[10], @XMM[0], @XMM[9] @ xor with round0 key
+ veor @XMM[11], @XMM[1], @XMM[9]
+ vtbl.8 `&Dlo(@XMM[0])`, {@XMM[10]}, `&Dlo(@XMM[8])`
+ vtbl.8 `&Dhi(@XMM[0])`, {@XMM[10]}, `&Dhi(@XMM[8])`
+ veor @XMM[12], @XMM[2], @XMM[9]
+ vtbl.8 `&Dlo(@XMM[1])`, {@XMM[11]}, `&Dlo(@XMM[8])`
+ vtbl.8 `&Dhi(@XMM[1])`, {@XMM[11]}, `&Dhi(@XMM[8])`
+ veor @XMM[13], @XMM[3], @XMM[9]
+ vtbl.8 `&Dlo(@XMM[2])`, {@XMM[12]}, `&Dlo(@XMM[8])`
+ vtbl.8 `&Dhi(@XMM[2])`, {@XMM[12]}, `&Dhi(@XMM[8])`
+ veor @XMM[14], @XMM[4], @XMM[9]
+ vtbl.8 `&Dlo(@XMM[3])`, {@XMM[13]}, `&Dlo(@XMM[8])`
+ vtbl.8 `&Dhi(@XMM[3])`, {@XMM[13]}, `&Dhi(@XMM[8])`
+ veor @XMM[15], @XMM[5], @XMM[9]
+ vtbl.8 `&Dlo(@XMM[4])`, {@XMM[14]}, `&Dlo(@XMM[8])`
+ vtbl.8 `&Dhi(@XMM[4])`, {@XMM[14]}, `&Dhi(@XMM[8])`
+ veor @XMM[10], @XMM[6], @XMM[9]
+ vtbl.8 `&Dlo(@XMM[5])`, {@XMM[15]}, `&Dlo(@XMM[8])`
+ vtbl.8 `&Dhi(@XMM[5])`, {@XMM[15]}, `&Dhi(@XMM[8])`
+ veor @XMM[11], @XMM[7], @XMM[9]
+ vtbl.8 `&Dlo(@XMM[6])`, {@XMM[10]}, `&Dlo(@XMM[8])`
+ vtbl.8 `&Dhi(@XMM[6])`, {@XMM[10]}, `&Dhi(@XMM[8])`
+ vtbl.8 `&Dlo(@XMM[7])`, {@XMM[11]}, `&Dlo(@XMM[8])`
+ vtbl.8 `&Dhi(@XMM[7])`, {@XMM[11]}, `&Dhi(@XMM[8])`
+_bsaes_encrypt8_bitslice:
+___
+ &bitslice (@XMM[0..7, 8..11]);
+$code.=<<___;
+ sub $rounds,$rounds,#1
+ b .Lenc_sbox
+.align 4
+.Lenc_loop:
+___
+ &ShiftRows (@XMM[0..7, 8..12]);
+$code.=".Lenc_sbox:\n";
+ &Sbox (@XMM[0..7, 8..15]);
+$code.=<<___;
+ subs $rounds,$rounds,#1
+ bcc .Lenc_done
+___
+ &MixColumns (@XMM[0,1,4,6,3,7,2,5, 8..15]);
+$code.=<<___;
+ vldmia $const, {@XMM[12]} @ .LSR
+ ite eq @ Thumb2 thing, samity check in ARM
+ addeq $const,$const,#0x10
+ bne .Lenc_loop
+ vldmia $const, {@XMM[12]} @ .LSRM0
+ b .Lenc_loop
+.align 4
+.Lenc_done:
+___
+ # output in lsb > [t0, t1, t4, t6, t3, t7, t2, t5] < msb
+ &bitslice (@XMM[0,1,4,6,3,7,2,5, 8..11]);
+$code.=<<___;
+ vldmia $key, {@XMM[8]} @ last round key
+ veor @XMM[4], @XMM[4], @XMM[8]
+ veor @XMM[6], @XMM[6], @XMM[8]
+ veor @XMM[3], @XMM[3], @XMM[8]
+ veor @XMM[7], @XMM[7], @XMM[8]
+ veor @XMM[2], @XMM[2], @XMM[8]
+ veor @XMM[5], @XMM[5], @XMM[8]
+ veor @XMM[0], @XMM[0], @XMM[8]
+ veor @XMM[1], @XMM[1], @XMM[8]
+ bx lr
+.size _bsaes_encrypt8,.-_bsaes_encrypt8
+___
+}
+{
+my ($out,$inp,$rounds,$const)=("r12","r4","r5","r6");
+
+sub bitslice_key {
+my @x=reverse(@_[0..7]);
+my ($bs0,$bs1,$bs2,$t2,$t3)=@_[8..12];
+
+ &swapmove (@x[0,1],1,$bs0,$t2,$t3);
+$code.=<<___;
+ @ &swapmove(@x[2,3],1,$t0,$t2,$t3);
+ vmov @x[2], @x[0]
+ vmov @x[3], @x[1]
+___
+ #&swapmove2x(@x[4,5,6,7],1,$t0,$t2,$t3);
+
+ &swapmove2x (@x[0,2,1,3],2,$bs1,$t2,$t3);
+$code.=<<___;
+ @ &swapmove2x(@x[4,6,5,7],2,$t1,$t2,$t3);
+ vmov @x[4], @x[0]
+ vmov @x[6], @x[2]
+ vmov @x[5], @x[1]
+ vmov @x[7], @x[3]
+___
+ &swapmove2x (@x[0,4,1,5],4,$bs2,$t2,$t3);
+ &swapmove2x (@x[2,6,3,7],4,$bs2,$t2,$t3);
+}
+
+$code.=<<___;
+.type _bsaes_key_convert,%function
+.align 4
+_bsaes_key_convert:
+ adr $const,_bsaes_key_convert
+ vld1.8 {@XMM[7]}, [$inp]! @ load round 0 key
+ sub $const,$const,#_bsaes_key_convert-.LM0
+ vld1.8 {@XMM[15]}, [$inp]! @ load round 1 key
+
+ vmov.i8 @XMM[8], #0x01 @ bit masks
+ vmov.i8 @XMM[9], #0x02
+ vmov.i8 @XMM[10], #0x04
+ vmov.i8 @XMM[11], #0x08
+ vmov.i8 @XMM[12], #0x10
+ vmov.i8 @XMM[13], #0x20
+ vldmia $const, {@XMM[14]} @ .LM0
+
+#ifdef __ARMEL__
+ vrev32.8 @XMM[7], @XMM[7]
+ vrev32.8 @XMM[15], @XMM[15]
+#endif
+ sub $rounds,$rounds,#1
+ vstmia $out!, {@XMM[7]} @ save round 0 key
+ b .Lkey_loop
+
+.align 4
+.Lkey_loop:
+ vtbl.8 `&Dlo(@XMM[7])`,{@XMM[15]},`&Dlo(@XMM[14])`
+ vtbl.8 `&Dhi(@XMM[7])`,{@XMM[15]},`&Dhi(@XMM[14])`
+ vmov.i8 @XMM[6], #0x40
+ vmov.i8 @XMM[15], #0x80
+
+ vtst.8 @XMM[0], @XMM[7], @XMM[8]
+ vtst.8 @XMM[1], @XMM[7], @XMM[9]
+ vtst.8 @XMM[2], @XMM[7], @XMM[10]
+ vtst.8 @XMM[3], @XMM[7], @XMM[11]
+ vtst.8 @XMM[4], @XMM[7], @XMM[12]
+ vtst.8 @XMM[5], @XMM[7], @XMM[13]
+ vtst.8 @XMM[6], @XMM[7], @XMM[6]
+ vtst.8 @XMM[7], @XMM[7], @XMM[15]
+ vld1.8 {@XMM[15]}, [$inp]! @ load next round key
+ vmvn @XMM[0], @XMM[0] @ "pnot"
+ vmvn @XMM[1], @XMM[1]
+ vmvn @XMM[5], @XMM[5]
+ vmvn @XMM[6], @XMM[6]
+#ifdef __ARMEL__
+ vrev32.8 @XMM[15], @XMM[15]
+#endif
+ subs $rounds,$rounds,#1
+ vstmia $out!,{@XMM[0]-@XMM[7]} @ write bit-sliced round key
+ bne .Lkey_loop
+
+ vmov.i8 @XMM[7],#0x63 @ compose .L63
+ @ don't save last round key
+ bx lr
+.size _bsaes_key_convert,.-_bsaes_key_convert
+___
+}
+
+if (0) { # following four functions are unsupported interface
+ # used for benchmarking...
+$code.=<<___;
+.globl bsaes_enc_key_convert
+.hidden bsaes_enc_key_convert
+.type bsaes_enc_key_convert,%function
+.align 4
+bsaes_enc_key_convert:
+ stmdb sp!,{r4-r6,lr}
+ vstmdb sp!,{d8-d15} @ ABI specification says so
+
+ ldr r5,[$inp,#240] @ pass rounds
+ mov r4,$inp @ pass key
+ mov r12,$out @ pass key schedule
+ bl _bsaes_key_convert
+ veor @XMM[7],@XMM[7],@XMM[15] @ fix up last round key
+ vstmia r12, {@XMM[7]} @ save last round key
+
+ vldmia sp!,{d8-d15}
+ ldmia sp!,{r4-r6,pc}
+.size bsaes_enc_key_convert,.-bsaes_enc_key_convert
+
+.globl bsaes_encrypt_128
+.hidden bsaes_encrypt_128
+.type bsaes_encrypt_128,%function
+.align 4
+bsaes_encrypt_128:
+ stmdb sp!,{r4-r6,lr}
+ vstmdb sp!,{d8-d15} @ ABI specification says so
+.Lenc128_loop:
+ vld1.8 {@XMM[0]-@XMM[1]}, [$inp]! @ load input
+ vld1.8 {@XMM[2]-@XMM[3]}, [$inp]!
+ mov r4,$key @ pass the key
+ vld1.8 {@XMM[4]-@XMM[5]}, [$inp]!
+ mov r5,#10 @ pass rounds
+ vld1.8 {@XMM[6]-@XMM[7]}, [$inp]!
+
+ bl _bsaes_encrypt8
+
+ vst1.8 {@XMM[0]-@XMM[1]}, [$out]! @ write output
+ vst1.8 {@XMM[4]}, [$out]!
+ vst1.8 {@XMM[6]}, [$out]!
+ vst1.8 {@XMM[3]}, [$out]!
+ vst1.8 {@XMM[7]}, [$out]!
+ vst1.8 {@XMM[2]}, [$out]!
+ subs $len,$len,#0x80
+ vst1.8 {@XMM[5]}, [$out]!
+ bhi .Lenc128_loop
+
+ vldmia sp!,{d8-d15}
+ ldmia sp!,{r4-r6,pc}
+.size bsaes_encrypt_128,.-bsaes_encrypt_128
+
+.globl bsaes_dec_key_convert
+.hidden bsaes_dec_key_convert
+.type bsaes_dec_key_convert,%function
+.align 4
+bsaes_dec_key_convert:
+ stmdb sp!,{r4-r6,lr}
+ vstmdb sp!,{d8-d15} @ ABI specification says so
+
+ ldr r5,[$inp,#240] @ pass rounds
+ mov r4,$inp @ pass key
+ mov r12,$out @ pass key schedule
+ bl _bsaes_key_convert
+ vldmia $out, {@XMM[6]}
+ vstmia r12, {@XMM[15]} @ save last round key
+ veor @XMM[7], @XMM[7], @XMM[6] @ fix up round 0 key
+ vstmia $out, {@XMM[7]}
+
+ vldmia sp!,{d8-d15}
+ ldmia sp!,{r4-r6,pc}
+.size bsaes_dec_key_convert,.-bsaes_dec_key_convert
+
+.globl bsaes_decrypt_128
+.hidden bsaes_decrypt_128
+.type bsaes_decrypt_128,%function
+.align 4
+bsaes_decrypt_128:
+ stmdb sp!,{r4-r6,lr}
+ vstmdb sp!,{d8-d15} @ ABI specification says so
+.Ldec128_loop:
+ vld1.8 {@XMM[0]-@XMM[1]}, [$inp]! @ load input
+ vld1.8 {@XMM[2]-@XMM[3]}, [$inp]!
+ mov r4,$key @ pass the key
+ vld1.8 {@XMM[4]-@XMM[5]}, [$inp]!
+ mov r5,#10 @ pass rounds
+ vld1.8 {@XMM[6]-@XMM[7]}, [$inp]!
+
+ bl _bsaes_decrypt8
+
+ vst1.8 {@XMM[0]-@XMM[1]}, [$out]! @ write output
+ vst1.8 {@XMM[6]}, [$out]!
+ vst1.8 {@XMM[4]}, [$out]!
+ vst1.8 {@XMM[2]}, [$out]!
+ vst1.8 {@XMM[7]}, [$out]!
+ vst1.8 {@XMM[3]}, [$out]!
+ subs $len,$len,#0x80
+ vst1.8 {@XMM[5]}, [$out]!
+ bhi .Ldec128_loop
+
+ vldmia sp!,{d8-d15}
+ ldmia sp!,{r4-r6,pc}
+.size bsaes_decrypt_128,.-bsaes_decrypt_128
+___
+}
+{
+my ($inp,$out,$len,$key, $ivp,$fp,$rounds)=map("r$_",(0..3,8..10));
+my ($keysched)=("sp");
+
+$code.=<<___;
+.extern AES_cbc_encrypt
+.extern AES_decrypt
+
+.global bsaes_cbc_encrypt
+.hidden bsaes_cbc_encrypt
+.type bsaes_cbc_encrypt,%function
+.align 5
+bsaes_cbc_encrypt:
+#ifndef __KERNEL__
+ cmp $len, #128
+#ifndef __thumb__
+ blo AES_cbc_encrypt
+#else
+ bhs 1f
+ b AES_cbc_encrypt
+1:
+#endif
+#endif
+
+ @ it is up to the caller to make sure we are called with enc == 0
+
+ mov ip, sp
+ stmdb sp!, {r4-r10, lr}
+ VFP_ABI_PUSH
+ ldr $ivp, [ip] @ IV is 1st arg on the stack
+ mov $len, $len, lsr#4 @ len in 16 byte blocks
+ sub sp, #0x10 @ scratch space to carry over the IV
+ mov $fp, sp @ save sp
+
+ ldr $rounds, [$key, #240] @ get # of rounds
+#ifndef BSAES_ASM_EXTENDED_KEY
+ @ allocate the key schedule on the stack
+ sub r12, sp, $rounds, lsl#7 @ 128 bytes per inner round key
+ add r12, #`128-32` @ sifze of bit-slices key schedule
+
+ @ populate the key schedule
+ mov r4, $key @ pass key
+ mov r5, $rounds @ pass # of rounds
+ mov sp, r12 @ sp is $keysched
+ bl _bsaes_key_convert
+ vldmia $keysched, {@XMM[6]}
+ vstmia r12, {@XMM[15]} @ save last round key
+ veor @XMM[7], @XMM[7], @XMM[6] @ fix up round 0 key
+ vstmia $keysched, {@XMM[7]}
+#else
+ ldr r12, [$key, #244]
+ eors r12, #1
+ beq 0f
+
+ @ populate the key schedule
+ str r12, [$key, #244]
+ mov r4, $key @ pass key
+ mov r5, $rounds @ pass # of rounds
+ add r12, $key, #248 @ pass key schedule
+ bl _bsaes_key_convert
+ add r4, $key, #248
+ vldmia r4, {@XMM[6]}
+ vstmia r12, {@XMM[15]} @ save last round key
+ veor @XMM[7], @XMM[7], @XMM[6] @ fix up round 0 key
+ vstmia r4, {@XMM[7]}
+
+.align 2
+0:
+#endif
+
+ vld1.8 {@XMM[15]}, [$ivp] @ load IV
+ b .Lcbc_dec_loop
+
+.align 4
+.Lcbc_dec_loop:
+ subs $len, $len, #0x8
+ bmi .Lcbc_dec_loop_finish
+
+ vld1.8 {@XMM[0]-@XMM[1]}, [$inp]! @ load input
+ vld1.8 {@XMM[2]-@XMM[3]}, [$inp]!
+#ifndef BSAES_ASM_EXTENDED_KEY
+ mov r4, $keysched @ pass the key
+#else
+ add r4, $key, #248
+#endif
+ vld1.8 {@XMM[4]-@XMM[5]}, [$inp]!
+ mov r5, $rounds
+ vld1.8 {@XMM[6]-@XMM[7]}, [$inp]
+ sub $inp, $inp, #0x60
+ vstmia $fp, {@XMM[15]} @ put aside IV
+
+ bl _bsaes_decrypt8
+
+ vldmia $fp, {@XMM[14]} @ reload IV
+ vld1.8 {@XMM[8]-@XMM[9]}, [$inp]! @ reload input
+ veor @XMM[0], @XMM[0], @XMM[14] @ ^= IV
+ vld1.8 {@XMM[10]-@XMM[11]}, [$inp]!
+ veor @XMM[1], @XMM[1], @XMM[8]
+ veor @XMM[6], @XMM[6], @XMM[9]
+ vld1.8 {@XMM[12]-@XMM[13]}, [$inp]!
+ veor @XMM[4], @XMM[4], @XMM[10]
+ veor @XMM[2], @XMM[2], @XMM[11]
+ vld1.8 {@XMM[14]-@XMM[15]}, [$inp]!
+ veor @XMM[7], @XMM[7], @XMM[12]
+ vst1.8 {@XMM[0]-@XMM[1]}, [$out]! @ write output
+ veor @XMM[3], @XMM[3], @XMM[13]
+ vst1.8 {@XMM[6]}, [$out]!
+ veor @XMM[5], @XMM[5], @XMM[14]
+ vst1.8 {@XMM[4]}, [$out]!
+ vst1.8 {@XMM[2]}, [$out]!
+ vst1.8 {@XMM[7]}, [$out]!
+ vst1.8 {@XMM[3]}, [$out]!
+ vst1.8 {@XMM[5]}, [$out]!
+
+ b .Lcbc_dec_loop
+
+.Lcbc_dec_loop_finish:
+ adds $len, $len, #8
+ beq .Lcbc_dec_done
+
+ vld1.8 {@XMM[0]}, [$inp]! @ load input
+ cmp $len, #2
+ blo .Lcbc_dec_one
+ vld1.8 {@XMM[1]}, [$inp]!
+#ifndef BSAES_ASM_EXTENDED_KEY
+ mov r4, $keysched @ pass the key
+#else
+ add r4, $key, #248
+#endif
+ mov r5, $rounds
+ vstmia $fp, {@XMM[15]} @ put aside IV
+ beq .Lcbc_dec_two
+ vld1.8 {@XMM[2]}, [$inp]!
+ cmp $len, #4
+ blo .Lcbc_dec_three
+ vld1.8 {@XMM[3]}, [$inp]!
+ beq .Lcbc_dec_four
+ vld1.8 {@XMM[4]}, [$inp]!
+ cmp $len, #6
+ blo .Lcbc_dec_five
+ vld1.8 {@XMM[5]}, [$inp]!
+ beq .Lcbc_dec_six
+ vld1.8 {@XMM[6]}, [$inp]!
+ sub $inp, $inp, #0x70
+
+ bl _bsaes_decrypt8
+
+ vldmia $fp, {@XMM[14]} @ reload IV
+ vld1.8 {@XMM[8]-@XMM[9]}, [$inp]! @ reload input
+ veor @XMM[0], @XMM[0], @XMM[14] @ ^= IV
+ vld1.8 {@XMM[10]-@XMM[11]}, [$inp]!
+ veor @XMM[1], @XMM[1], @XMM[8]
+ veor @XMM[6], @XMM[6], @XMM[9]
+ vld1.8 {@XMM[12]-@XMM[13]}, [$inp]!
+ veor @XMM[4], @XMM[4], @XMM[10]
+ veor @XMM[2], @XMM[2], @XMM[11]
+ vld1.8 {@XMM[15]}, [$inp]!
+ veor @XMM[7], @XMM[7], @XMM[12]
+ vst1.8 {@XMM[0]-@XMM[1]}, [$out]! @ write output
+ veor @XMM[3], @XMM[3], @XMM[13]
+ vst1.8 {@XMM[6]}, [$out]!
+ vst1.8 {@XMM[4]}, [$out]!
+ vst1.8 {@XMM[2]}, [$out]!
+ vst1.8 {@XMM[7]}, [$out]!
+ vst1.8 {@XMM[3]}, [$out]!
+ b .Lcbc_dec_done
+.align 4
+.Lcbc_dec_six:
+ sub $inp, $inp, #0x60
+ bl _bsaes_decrypt8
+ vldmia $fp,{@XMM[14]} @ reload IV
+ vld1.8 {@XMM[8]-@XMM[9]}, [$inp]! @ reload input
+ veor @XMM[0], @XMM[0], @XMM[14] @ ^= IV
+ vld1.8 {@XMM[10]-@XMM[11]}, [$inp]!
+ veor @XMM[1], @XMM[1], @XMM[8]
+ veor @XMM[6], @XMM[6], @XMM[9]
+ vld1.8 {@XMM[12]}, [$inp]!
+ veor @XMM[4], @XMM[4], @XMM[10]
+ veor @XMM[2], @XMM[2], @XMM[11]
+ vld1.8 {@XMM[15]}, [$inp]!
+ veor @XMM[7], @XMM[7], @XMM[12]
+ vst1.8 {@XMM[0]-@XMM[1]}, [$out]! @ write output
+ vst1.8 {@XMM[6]}, [$out]!
+ vst1.8 {@XMM[4]}, [$out]!
+ vst1.8 {@XMM[2]}, [$out]!
+ vst1.8 {@XMM[7]}, [$out]!
+ b .Lcbc_dec_done
+.align 4
+.Lcbc_dec_five:
+ sub $inp, $inp, #0x50
+ bl _bsaes_decrypt8
+ vldmia $fp, {@XMM[14]} @ reload IV
+ vld1.8 {@XMM[8]-@XMM[9]}, [$inp]! @ reload input
+ veor @XMM[0], @XMM[0], @XMM[14] @ ^= IV
+ vld1.8 {@XMM[10]-@XMM[11]}, [$inp]!
+ veor @XMM[1], @XMM[1], @XMM[8]
+ veor @XMM[6], @XMM[6], @XMM[9]
+ vld1.8 {@XMM[15]}, [$inp]!
+ veor @XMM[4], @XMM[4], @XMM[10]
+ vst1.8 {@XMM[0]-@XMM[1]}, [$out]! @ write output
+ veor @XMM[2], @XMM[2], @XMM[11]
+ vst1.8 {@XMM[6]}, [$out]!
+ vst1.8 {@XMM[4]}, [$out]!
+ vst1.8 {@XMM[2]}, [$out]!
+ b .Lcbc_dec_done
+.align 4
+.Lcbc_dec_four:
+ sub $inp, $inp, #0x40
+ bl _bsaes_decrypt8
+ vldmia $fp, {@XMM[14]} @ reload IV
+ vld1.8 {@XMM[8]-@XMM[9]}, [$inp]! @ reload input
+ veor @XMM[0], @XMM[0], @XMM[14] @ ^= IV
+ vld1.8 {@XMM[10]}, [$inp]!
+ veor @XMM[1], @XMM[1], @XMM[8]
+ veor @XMM[6], @XMM[6], @XMM[9]
+ vld1.8 {@XMM[15]}, [$inp]!
+ veor @XMM[4], @XMM[4], @XMM[10]
+ vst1.8 {@XMM[0]-@XMM[1]}, [$out]! @ write output
+ vst1.8 {@XMM[6]}, [$out]!
+ vst1.8 {@XMM[4]}, [$out]!
+ b .Lcbc_dec_done
+.align 4
+.Lcbc_dec_three:
+ sub $inp, $inp, #0x30
+ bl _bsaes_decrypt8
+ vldmia $fp, {@XMM[14]} @ reload IV
+ vld1.8 {@XMM[8]-@XMM[9]}, [$inp]! @ reload input
+ veor @XMM[0], @XMM[0], @XMM[14] @ ^= IV
+ vld1.8 {@XMM[15]}, [$inp]!
+ veor @XMM[1], @XMM[1], @XMM[8]
+ veor @XMM[6], @XMM[6], @XMM[9]
+ vst1.8 {@XMM[0]-@XMM[1]}, [$out]! @ write output
+ vst1.8 {@XMM[6]}, [$out]!
+ b .Lcbc_dec_done
+.align 4
+.Lcbc_dec_two:
+ sub $inp, $inp, #0x20
+ bl _bsaes_decrypt8
+ vldmia $fp, {@XMM[14]} @ reload IV
+ vld1.8 {@XMM[8]}, [$inp]! @ reload input
+ veor @XMM[0], @XMM[0], @XMM[14] @ ^= IV
+ vld1.8 {@XMM[15]}, [$inp]! @ reload input
+ veor @XMM[1], @XMM[1], @XMM[8]
+ vst1.8 {@XMM[0]-@XMM[1]}, [$out]! @ write output
+ b .Lcbc_dec_done
+.align 4
+.Lcbc_dec_one:
+ sub $inp, $inp, #0x10
+ mov $rounds, $out @ save original out pointer
+ mov $out, $fp @ use the iv scratch space as out buffer
+ mov r2, $key
+ vmov @XMM[4],@XMM[15] @ just in case ensure that IV
+ vmov @XMM[5],@XMM[0] @ and input are preserved
+ bl AES_decrypt
+ vld1.8 {@XMM[0]}, [$fp,:64] @ load result
+ veor @XMM[0], @XMM[0], @XMM[4] @ ^= IV
+ vmov @XMM[15], @XMM[5] @ @XMM[5] holds input
+ vst1.8 {@XMM[0]}, [$rounds] @ write output
+
+.Lcbc_dec_done:
+#ifndef BSAES_ASM_EXTENDED_KEY
+ vmov.i32 q0, #0
+ vmov.i32 q1, #0
+.Lcbc_dec_bzero: @ wipe key schedule [if any]
+ vstmia $keysched!, {q0-q1}
+ cmp $keysched, $fp
+ bne .Lcbc_dec_bzero
+#endif
+
+ mov sp, $fp
+ add sp, #0x10 @ add sp,$fp,#0x10 is no good for thumb
+ vst1.8 {@XMM[15]}, [$ivp] @ return IV
+ VFP_ABI_POP
+ ldmia sp!, {r4-r10, pc}
+.size bsaes_cbc_encrypt,.-bsaes_cbc_encrypt
+___
+}
+{
+my ($inp,$out,$len,$key, $ctr,$fp,$rounds)=(map("r$_",(0..3,8..10)));
+my $const = "r6"; # shared with _bsaes_encrypt8_alt
+my $keysched = "sp";
+
+$code.=<<___;
+.extern AES_encrypt
+.global bsaes_ctr32_encrypt_blocks
+.hidden bsaes_ctr32_encrypt_blocks
+.type bsaes_ctr32_encrypt_blocks,%function
+.align 5
+bsaes_ctr32_encrypt_blocks:
+ cmp $len, #8 @ use plain AES for
+ blo .Lctr_enc_short @ small sizes
+
+ mov ip, sp
+ stmdb sp!, {r4-r10, lr}
+ VFP_ABI_PUSH
+ ldr $ctr, [ip] @ ctr is 1st arg on the stack
+ sub sp, sp, #0x10 @ scratch space to carry over the ctr
+ mov $fp, sp @ save sp
+
+ ldr $rounds, [$key, #240] @ get # of rounds
+#ifndef BSAES_ASM_EXTENDED_KEY
+ @ allocate the key schedule on the stack
+ sub r12, sp, $rounds, lsl#7 @ 128 bytes per inner round key
+ add r12, #`128-32` @ size of bit-sliced key schedule
+
+ @ populate the key schedule
+ mov r4, $key @ pass key
+ mov r5, $rounds @ pass # of rounds
+ mov sp, r12 @ sp is $keysched
+ bl _bsaes_key_convert
+ veor @XMM[7],@XMM[7],@XMM[15] @ fix up last round key
+ vstmia r12, {@XMM[7]} @ save last round key
+
+ vld1.8 {@XMM[0]}, [$ctr] @ load counter
+ add $ctr, $const, #.LREVM0SR-.LM0 @ borrow $ctr
+ vldmia $keysched, {@XMM[4]} @ load round0 key
+#else
+ ldr r12, [$key, #244]
+ eors r12, #1
+ beq 0f
+
+ @ populate the key schedule
+ str r12, [$key, #244]
+ mov r4, $key @ pass key
+ mov r5, $rounds @ pass # of rounds
+ add r12, $key, #248 @ pass key schedule
+ bl _bsaes_key_convert
+ veor @XMM[7],@XMM[7],@XMM[15] @ fix up last round key
+ vstmia r12, {@XMM[7]} @ save last round key
+
+.align 2
+0: add r12, $key, #248
+ vld1.8 {@XMM[0]}, [$ctr] @ load counter
+ adrl $ctr, .LREVM0SR @ borrow $ctr
+ vldmia r12, {@XMM[4]} @ load round0 key
+ sub sp, #0x10 @ place for adjusted round0 key
+#endif
+
+ vmov.i32 @XMM[8],#1 @ compose 1<<96
+ veor @XMM[9],@XMM[9],@XMM[9]
+ vrev32.8 @XMM[0],@XMM[0]
+ vext.8 @XMM[8],@XMM[9],@XMM[8],#4
+ vrev32.8 @XMM[4],@XMM[4]
+ vadd.u32 @XMM[9],@XMM[8],@XMM[8] @ compose 2<<96
+ vstmia $keysched, {@XMM[4]} @ save adjusted round0 key
+ b .Lctr_enc_loop
+
+.align 4
+.Lctr_enc_loop:
+ vadd.u32 @XMM[10], @XMM[8], @XMM[9] @ compose 3<<96
+ vadd.u32 @XMM[1], @XMM[0], @XMM[8] @ +1
+ vadd.u32 @XMM[2], @XMM[0], @XMM[9] @ +2
+ vadd.u32 @XMM[3], @XMM[0], @XMM[10] @ +3
+ vadd.u32 @XMM[4], @XMM[1], @XMM[10]
+ vadd.u32 @XMM[5], @XMM[2], @XMM[10]
+ vadd.u32 @XMM[6], @XMM[3], @XMM[10]
+ vadd.u32 @XMM[7], @XMM[4], @XMM[10]
+ vadd.u32 @XMM[10], @XMM[5], @XMM[10] @ next counter
+
+ @ Borrow prologue from _bsaes_encrypt8 to use the opportunity
+ @ to flip byte order in 32-bit counter
+
+ vldmia $keysched, {@XMM[9]} @ load round0 key
+#ifndef BSAES_ASM_EXTENDED_KEY
+ add r4, $keysched, #0x10 @ pass next round key
+#else
+ add r4, $key, #`248+16`
+#endif
+ vldmia $ctr, {@XMM[8]} @ .LREVM0SR
+ mov r5, $rounds @ pass rounds
+ vstmia $fp, {@XMM[10]} @ save next counter
+ sub $const, $ctr, #.LREVM0SR-.LSR @ pass constants
+
+ bl _bsaes_encrypt8_alt
+
+ subs $len, $len, #8
+ blo .Lctr_enc_loop_done
+
+ vld1.8 {@XMM[8]-@XMM[9]}, [$inp]! @ load input
+ vld1.8 {@XMM[10]-@XMM[11]}, [$inp]!
+ veor @XMM[0], @XMM[8]
+ veor @XMM[1], @XMM[9]
+ vld1.8 {@XMM[12]-@XMM[13]}, [$inp]!
+ veor @XMM[4], @XMM[10]
+ veor @XMM[6], @XMM[11]
+ vld1.8 {@XMM[14]-@XMM[15]}, [$inp]!
+ veor @XMM[3], @XMM[12]
+ vst1.8 {@XMM[0]-@XMM[1]}, [$out]! @ write output
+ veor @XMM[7], @XMM[13]
+ veor @XMM[2], @XMM[14]
+ vst1.8 {@XMM[4]}, [$out]!
+ veor @XMM[5], @XMM[15]
+ vst1.8 {@XMM[6]}, [$out]!
+ vmov.i32 @XMM[8], #1 @ compose 1<<96
+ vst1.8 {@XMM[3]}, [$out]!
+ veor @XMM[9], @XMM[9], @XMM[9]
+ vst1.8 {@XMM[7]}, [$out]!
+ vext.8 @XMM[8], @XMM[9], @XMM[8], #4
+ vst1.8 {@XMM[2]}, [$out]!
+ vadd.u32 @XMM[9],@XMM[8],@XMM[8] @ compose 2<<96
+ vst1.8 {@XMM[5]}, [$out]!
+ vldmia $fp, {@XMM[0]} @ load counter
+
+ bne .Lctr_enc_loop
+ b .Lctr_enc_done
+
+.align 4
+.Lctr_enc_loop_done:
+ add $len, $len, #8
+ vld1.8 {@XMM[8]}, [$inp]! @ load input
+ veor @XMM[0], @XMM[8]
+ vst1.8 {@XMM[0]}, [$out]! @ write output
+ cmp $len, #2
+ blo .Lctr_enc_done
+ vld1.8 {@XMM[9]}, [$inp]!
+ veor @XMM[1], @XMM[9]
+ vst1.8 {@XMM[1]}, [$out]!
+ beq .Lctr_enc_done
+ vld1.8 {@XMM[10]}, [$inp]!
+ veor @XMM[4], @XMM[10]
+ vst1.8 {@XMM[4]}, [$out]!
+ cmp $len, #4
+ blo .Lctr_enc_done
+ vld1.8 {@XMM[11]}, [$inp]!
+ veor @XMM[6], @XMM[11]
+ vst1.8 {@XMM[6]}, [$out]!
+ beq .Lctr_enc_done
+ vld1.8 {@XMM[12]}, [$inp]!
+ veor @XMM[3], @XMM[12]
+ vst1.8 {@XMM[3]}, [$out]!
+ cmp $len, #6
+ blo .Lctr_enc_done
+ vld1.8 {@XMM[13]}, [$inp]!
+ veor @XMM[7], @XMM[13]
+ vst1.8 {@XMM[7]}, [$out]!
+ beq .Lctr_enc_done
+ vld1.8 {@XMM[14]}, [$inp]
+ veor @XMM[2], @XMM[14]
+ vst1.8 {@XMM[2]}, [$out]!
+
+.Lctr_enc_done:
+ vmov.i32 q0, #0
+ vmov.i32 q1, #0
+#ifndef BSAES_ASM_EXTENDED_KEY
+.Lctr_enc_bzero: @ wipe key schedule [if any]
+ vstmia $keysched!, {q0-q1}
+ cmp $keysched, $fp
+ bne .Lctr_enc_bzero
+#else
+ vstmia $keysched, {q0-q1}
+#endif
+
+ mov sp, $fp
+ add sp, #0x10 @ add sp,$fp,#0x10 is no good for thumb
+ VFP_ABI_POP
+ ldmia sp!, {r4-r10, pc} @ return
+
+.align 4
+.Lctr_enc_short:
+ ldr ip, [sp] @ ctr pointer is passed on stack
+ stmdb sp!, {r4-r8, lr}
+
+ mov r4, $inp @ copy arguments
+ mov r5, $out
+ mov r6, $len
+ mov r7, $key
+ ldr r8, [ip, #12] @ load counter LSW
+ vld1.8 {@XMM[1]}, [ip] @ load whole counter value
+#ifdef __ARMEL__
+ rev r8, r8
+#endif
+ sub sp, sp, #0x10
+ vst1.8 {@XMM[1]}, [sp,:64] @ copy counter value
+ sub sp, sp, #0x10
+
+.Lctr_enc_short_loop:
+ add r0, sp, #0x10 @ input counter value
+ mov r1, sp @ output on the stack
+ mov r2, r7 @ key
+
+ bl AES_encrypt
+
+ vld1.8 {@XMM[0]}, [r4]! @ load input
+ vld1.8 {@XMM[1]}, [sp,:64] @ load encrypted counter
+ add r8, r8, #1
+#ifdef __ARMEL__
+ rev r0, r8
+ str r0, [sp, #0x1c] @ next counter value
+#else
+ str r8, [sp, #0x1c] @ next counter value
+#endif
+ veor @XMM[0],@XMM[0],@XMM[1]
+ vst1.8 {@XMM[0]}, [r5]! @ store output
+ subs r6, r6, #1
+ bne .Lctr_enc_short_loop
+
+ vmov.i32 q0, #0
+ vmov.i32 q1, #0
+ vstmia sp!, {q0-q1}
+
+ ldmia sp!, {r4-r8, pc}
+.size bsaes_ctr32_encrypt_blocks,.-bsaes_ctr32_encrypt_blocks
+___
+}
+{
+######################################################################
+# void bsaes_xts_[en|de]crypt(const char *inp,char *out,size_t len,
+# const AES_KEY *key1, const AES_KEY *key2,
+# const unsigned char iv[16]);
+#
+my ($inp,$out,$len,$key,$rounds,$magic,$fp)=(map("r$_",(7..10,1..3)));
+my $const="r6"; # returned by _bsaes_key_convert
+my $twmask=@XMM[5];
+my @T=@XMM[6..7];
+
+$code.=<<___;
+.globl bsaes_xts_encrypt
+.hidden bsaes_xts_encrypt
+.type bsaes_xts_encrypt,%function
+.align 4
+bsaes_xts_encrypt:
+ mov ip, sp
+ stmdb sp!, {r4-r10, lr} @ 0x20
+ VFP_ABI_PUSH
+ mov r6, sp @ future $fp
+
+ mov $inp, r0
+ mov $out, r1
+ mov $len, r2
+ mov $key, r3
+
+ sub r0, sp, #0x10 @ 0x10
+ bic r0, #0xf @ align at 16 bytes
+ mov sp, r0
+
+#ifdef XTS_CHAIN_TWEAK
+ ldr r0, [ip] @ pointer to input tweak
+#else
+ @ generate initial tweak
+ ldr r0, [ip, #4] @ iv[]
+ mov r1, sp
+ ldr r2, [ip, #0] @ key2
+ bl AES_encrypt
+ mov r0,sp @ pointer to initial tweak
+#endif
+
+ ldr $rounds, [$key, #240] @ get # of rounds
+ mov $fp, r6
+#ifndef BSAES_ASM_EXTENDED_KEY
+ @ allocate the key schedule on the stack
+ sub r12, sp, $rounds, lsl#7 @ 128 bytes per inner round key
+ @ add r12, #`128-32` @ size of bit-sliced key schedule
+ sub r12, #`32+16` @ place for tweak[9]
+
+ @ populate the key schedule
+ mov r4, $key @ pass key
+ mov r5, $rounds @ pass # of rounds
+ mov sp, r12
+ add r12, #0x90 @ pass key schedule
+ bl _bsaes_key_convert
+ veor @XMM[7], @XMM[7], @XMM[15] @ fix up last round key
+ vstmia r12, {@XMM[7]} @ save last round key
+#else
+ ldr r12, [$key, #244]
+ eors r12, #1
+ beq 0f
+
+ str r12, [$key, #244]
+ mov r4, $key @ pass key
+ mov r5, $rounds @ pass # of rounds
+ add r12, $key, #248 @ pass key schedule
+ bl _bsaes_key_convert
+ veor @XMM[7], @XMM[7], @XMM[15] @ fix up last round key
+ vstmia r12, {@XMM[7]}
+
+.align 2
+0: sub sp, #0x90 @ place for tweak[9]
+#endif
+
+ vld1.8 {@XMM[8]}, [r0] @ initial tweak
+ adr $magic, .Lxts_magic
+
+ subs $len, #0x80
+ blo .Lxts_enc_short
+ b .Lxts_enc_loop
+
+.align 4
+.Lxts_enc_loop:
+ vldmia $magic, {$twmask} @ load XTS magic
+ vshr.s64 @T[0], @XMM[8], #63
+ mov r0, sp
+ vand @T[0], @T[0], $twmask
+___
+for($i=9;$i<16;$i++) {
+$code.=<<___;
+ vadd.u64 @XMM[$i], @XMM[$i-1], @XMM[$i-1]
+ vst1.64 {@XMM[$i-1]}, [r0,:128]!
+ vswp `&Dhi("@T[0]")`,`&Dlo("@T[0]")`
+ vshr.s64 @T[1], @XMM[$i], #63
+ veor @XMM[$i], @XMM[$i], @T[0]
+ vand @T[1], @T[1], $twmask
+___
+ @T=reverse(@T);
+
+$code.=<<___ if ($i>=10);
+ vld1.8 {@XMM[$i-10]}, [$inp]!
+___
+$code.=<<___ if ($i>=11);
+ veor @XMM[$i-11], @XMM[$i-11], @XMM[$i-3]
+___
+}
+$code.=<<___;
+ vadd.u64 @XMM[8], @XMM[15], @XMM[15]
+ vst1.64 {@XMM[15]}, [r0,:128]!
+ vswp `&Dhi("@T[0]")`,`&Dlo("@T[0]")`
+ veor @XMM[8], @XMM[8], @T[0]
+ vst1.64 {@XMM[8]}, [r0,:128] @ next round tweak
+
+ vld1.8 {@XMM[6]-@XMM[7]}, [$inp]!
+ veor @XMM[5], @XMM[5], @XMM[13]
+#ifndef BSAES_ASM_EXTENDED_KEY
+ add r4, sp, #0x90 @ pass key schedule
+#else
+ add r4, $key, #248 @ pass key schedule
+#endif
+ veor @XMM[6], @XMM[6], @XMM[14]
+ mov r5, $rounds @ pass rounds
+ veor @XMM[7], @XMM[7], @XMM[15]
+ mov r0, sp
+
+ bl _bsaes_encrypt8
+
+ vld1.64 {@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
+ vld1.64 {@XMM[10]-@XMM[11]}, [r0,:128]!
+ veor @XMM[0], @XMM[0], @XMM[ 8]
+ vld1.64 {@XMM[12]-@XMM[13]}, [r0,:128]!
+ veor @XMM[1], @XMM[1], @XMM[ 9]
+ veor @XMM[8], @XMM[4], @XMM[10]
+ vst1.8 {@XMM[0]-@XMM[1]}, [$out]!
+ veor @XMM[9], @XMM[6], @XMM[11]
+ vld1.64 {@XMM[14]-@XMM[15]}, [r0,:128]!
+ veor @XMM[10], @XMM[3], @XMM[12]
+ vst1.8 {@XMM[8]-@XMM[9]}, [$out]!
+ veor @XMM[11], @XMM[7], @XMM[13]
+ veor @XMM[12], @XMM[2], @XMM[14]
+ vst1.8 {@XMM[10]-@XMM[11]}, [$out]!
+ veor @XMM[13], @XMM[5], @XMM[15]
+ vst1.8 {@XMM[12]-@XMM[13]}, [$out]!
+
+ vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak
+
+ subs $len, #0x80
+ bpl .Lxts_enc_loop
+
+.Lxts_enc_short:
+ adds $len, #0x70
+ bmi .Lxts_enc_done
+
+ vldmia $magic, {$twmask} @ load XTS magic
+ vshr.s64 @T[0], @XMM[8], #63
+ mov r0, sp
+ vand @T[0], @T[0], $twmask
+___
+for($i=9;$i<16;$i++) {
+$code.=<<___;
+ vadd.u64 @XMM[$i], @XMM[$i-1], @XMM[$i-1]
+ vst1.64 {@XMM[$i-1]}, [r0,:128]!
+ vswp `&Dhi("@T[0]")`,`&Dlo("@T[0]")`
+ vshr.s64 @T[1], @XMM[$i], #63
+ veor @XMM[$i], @XMM[$i], @T[0]
+ vand @T[1], @T[1], $twmask
+___
+ @T=reverse(@T);
+
+$code.=<<___ if ($i>=10);
+ vld1.8 {@XMM[$i-10]}, [$inp]!
+ subs $len, #0x10
+ bmi .Lxts_enc_`$i-9`
+___
+$code.=<<___ if ($i>=11);
+ veor @XMM[$i-11], @XMM[$i-11], @XMM[$i-3]
+___
+}
+$code.=<<___;
+ sub $len, #0x10
+ vst1.64 {@XMM[15]}, [r0,:128] @ next round tweak
+
+ vld1.8 {@XMM[6]}, [$inp]!
+ veor @XMM[5], @XMM[5], @XMM[13]
+#ifndef BSAES_ASM_EXTENDED_KEY
+ add r4, sp, #0x90 @ pass key schedule
+#else
+ add r4, $key, #248 @ pass key schedule
+#endif
+ veor @XMM[6], @XMM[6], @XMM[14]
+ mov r5, $rounds @ pass rounds
+ mov r0, sp
+
+ bl _bsaes_encrypt8
+
+ vld1.64 {@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
+ vld1.64 {@XMM[10]-@XMM[11]}, [r0,:128]!
+ veor @XMM[0], @XMM[0], @XMM[ 8]
+ vld1.64 {@XMM[12]-@XMM[13]}, [r0,:128]!
+ veor @XMM[1], @XMM[1], @XMM[ 9]
+ veor @XMM[8], @XMM[4], @XMM[10]
+ vst1.8 {@XMM[0]-@XMM[1]}, [$out]!
+ veor @XMM[9], @XMM[6], @XMM[11]
+ vld1.64 {@XMM[14]}, [r0,:128]!
+ veor @XMM[10], @XMM[3], @XMM[12]
+ vst1.8 {@XMM[8]-@XMM[9]}, [$out]!
+ veor @XMM[11], @XMM[7], @XMM[13]
+ veor @XMM[12], @XMM[2], @XMM[14]
+ vst1.8 {@XMM[10]-@XMM[11]}, [$out]!
+ vst1.8 {@XMM[12]}, [$out]!
+
+ vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak
+ b .Lxts_enc_done
+.align 4
+.Lxts_enc_6:
+ vst1.64 {@XMM[14]}, [r0,:128] @ next round tweak
+
+ veor @XMM[4], @XMM[4], @XMM[12]
+#ifndef BSAES_ASM_EXTENDED_KEY
+ add r4, sp, #0x90 @ pass key schedule
+#else
+ add r4, $key, #248 @ pass key schedule
+#endif
+ veor @XMM[5], @XMM[5], @XMM[13]
+ mov r5, $rounds @ pass rounds
+ mov r0, sp
+
+ bl _bsaes_encrypt8
+
+ vld1.64 {@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
+ vld1.64 {@XMM[10]-@XMM[11]}, [r0,:128]!
+ veor @XMM[0], @XMM[0], @XMM[ 8]
+ vld1.64 {@XMM[12]-@XMM[13]}, [r0,:128]!
+ veor @XMM[1], @XMM[1], @XMM[ 9]
+ veor @XMM[8], @XMM[4], @XMM[10]
+ vst1.8 {@XMM[0]-@XMM[1]}, [$out]!
+ veor @XMM[9], @XMM[6], @XMM[11]
+ veor @XMM[10], @XMM[3], @XMM[12]
+ vst1.8 {@XMM[8]-@XMM[9]}, [$out]!
+ veor @XMM[11], @XMM[7], @XMM[13]
+ vst1.8 {@XMM[10]-@XMM[11]}, [$out]!
+
+ vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak
+ b .Lxts_enc_done
+
+@ put this in range for both ARM and Thumb mode adr instructions
+.align 5
+.Lxts_magic:
+ .quad 1, 0x87
+
+.align 5
+.Lxts_enc_5:
+ vst1.64 {@XMM[13]}, [r0,:128] @ next round tweak
+
+ veor @XMM[3], @XMM[3], @XMM[11]
+#ifndef BSAES_ASM_EXTENDED_KEY
+ add r4, sp, #0x90 @ pass key schedule
+#else
+ add r4, $key, #248 @ pass key schedule
+#endif
+ veor @XMM[4], @XMM[4], @XMM[12]
+ mov r5, $rounds @ pass rounds
+ mov r0, sp
+
+ bl _bsaes_encrypt8
+
+ vld1.64 {@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
+ vld1.64 {@XMM[10]-@XMM[11]}, [r0,:128]!
+ veor @XMM[0], @XMM[0], @XMM[ 8]
+ vld1.64 {@XMM[12]}, [r0,:128]!
+ veor @XMM[1], @XMM[1], @XMM[ 9]
+ veor @XMM[8], @XMM[4], @XMM[10]
+ vst1.8 {@XMM[0]-@XMM[1]}, [$out]!
+ veor @XMM[9], @XMM[6], @XMM[11]
+ veor @XMM[10], @XMM[3], @XMM[12]
+ vst1.8 {@XMM[8]-@XMM[9]}, [$out]!
+ vst1.8 {@XMM[10]}, [$out]!
+
+ vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak
+ b .Lxts_enc_done
+.align 4
+.Lxts_enc_4:
+ vst1.64 {@XMM[12]}, [r0,:128] @ next round tweak
+
+ veor @XMM[2], @XMM[2], @XMM[10]
+#ifndef BSAES_ASM_EXTENDED_KEY
+ add r4, sp, #0x90 @ pass key schedule
+#else
+ add r4, $key, #248 @ pass key schedule
+#endif
+ veor @XMM[3], @XMM[3], @XMM[11]
+ mov r5, $rounds @ pass rounds
+ mov r0, sp
+
+ bl _bsaes_encrypt8
+
+ vld1.64 {@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
+ vld1.64 {@XMM[10]-@XMM[11]}, [r0,:128]!
+ veor @XMM[0], @XMM[0], @XMM[ 8]
+ veor @XMM[1], @XMM[1], @XMM[ 9]
+ veor @XMM[8], @XMM[4], @XMM[10]
+ vst1.8 {@XMM[0]-@XMM[1]}, [$out]!
+ veor @XMM[9], @XMM[6], @XMM[11]
+ vst1.8 {@XMM[8]-@XMM[9]}, [$out]!
+
+ vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak
+ b .Lxts_enc_done
+.align 4
+.Lxts_enc_3:
+ vst1.64 {@XMM[11]}, [r0,:128] @ next round tweak
+
+ veor @XMM[1], @XMM[1], @XMM[9]
+#ifndef BSAES_ASM_EXTENDED_KEY
+ add r4, sp, #0x90 @ pass key schedule
+#else
+ add r4, $key, #248 @ pass key schedule
+#endif
+ veor @XMM[2], @XMM[2], @XMM[10]
+ mov r5, $rounds @ pass rounds
+ mov r0, sp
+
+ bl _bsaes_encrypt8
+
+ vld1.64 {@XMM[8]-@XMM[9]}, [r0,:128]!
+ vld1.64 {@XMM[10]}, [r0,:128]!
+ veor @XMM[0], @XMM[0], @XMM[ 8]
+ veor @XMM[1], @XMM[1], @XMM[ 9]
+ veor @XMM[8], @XMM[4], @XMM[10]
+ vst1.8 {@XMM[0]-@XMM[1]}, [$out]!
+ vst1.8 {@XMM[8]}, [$out]!
+
+ vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak
+ b .Lxts_enc_done
+.align 4
+.Lxts_enc_2:
+ vst1.64 {@XMM[10]}, [r0,:128] @ next round tweak
+
+ veor @XMM[0], @XMM[0], @XMM[8]
+#ifndef BSAES_ASM_EXTENDED_KEY
+ add r4, sp, #0x90 @ pass key schedule
+#else
+ add r4, $key, #248 @ pass key schedule
+#endif
+ veor @XMM[1], @XMM[1], @XMM[9]
+ mov r5, $rounds @ pass rounds
+ mov r0, sp
+
+ bl _bsaes_encrypt8
+
+ vld1.64 {@XMM[8]-@XMM[9]}, [r0,:128]!
+ veor @XMM[0], @XMM[0], @XMM[ 8]
+ veor @XMM[1], @XMM[1], @XMM[ 9]
+ vst1.8 {@XMM[0]-@XMM[1]}, [$out]!
+
+ vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak
+ b .Lxts_enc_done
+.align 4
+.Lxts_enc_1:
+ mov r0, sp
+ veor @XMM[0], @XMM[8]
+ mov r1, sp
+ vst1.8 {@XMM[0]}, [sp,:128]
+ mov r2, $key
+ mov r4, $fp @ preserve fp
+
+ bl AES_encrypt
+
+ vld1.8 {@XMM[0]}, [sp,:128]
+ veor @XMM[0], @XMM[0], @XMM[8]
+ vst1.8 {@XMM[0]}, [$out]!
+ mov $fp, r4
+
+ vmov @XMM[8], @XMM[9] @ next round tweak
+
+.Lxts_enc_done:
+#ifndef XTS_CHAIN_TWEAK
+ adds $len, #0x10
+ beq .Lxts_enc_ret
+ sub r6, $out, #0x10
+
+.Lxts_enc_steal:
+ ldrb r0, [$inp], #1
+ ldrb r1, [$out, #-0x10]
+ strb r0, [$out, #-0x10]
+ strb r1, [$out], #1
+
+ subs $len, #1
+ bhi .Lxts_enc_steal
+
+ vld1.8 {@XMM[0]}, [r6]
+ mov r0, sp
+ veor @XMM[0], @XMM[0], @XMM[8]
+ mov r1, sp
+ vst1.8 {@XMM[0]}, [sp,:128]
+ mov r2, $key
+ mov r4, $fp @ preserve fp
+
+ bl AES_encrypt
+
+ vld1.8 {@XMM[0]}, [sp,:128]
+ veor @XMM[0], @XMM[0], @XMM[8]
+ vst1.8 {@XMM[0]}, [r6]
+ mov $fp, r4
+#endif
+
+.Lxts_enc_ret:
+ bic r0, $fp, #0xf
+ vmov.i32 q0, #0
+ vmov.i32 q1, #0
+#ifdef XTS_CHAIN_TWEAK
+ ldr r1, [$fp, #0x20+VFP_ABI_FRAME] @ chain tweak
+#endif
+.Lxts_enc_bzero: @ wipe key schedule [if any]
+ vstmia sp!, {q0-q1}
+ cmp sp, r0
+ bne .Lxts_enc_bzero
+
+ mov sp, $fp
+#ifdef XTS_CHAIN_TWEAK
+ vst1.8 {@XMM[8]}, [r1]
+#endif
+ VFP_ABI_POP
+ ldmia sp!, {r4-r10, pc} @ return
+
+.size bsaes_xts_encrypt,.-bsaes_xts_encrypt
+
+.globl bsaes_xts_decrypt
+.hidden bsaes_xts_decrypt
+.type bsaes_xts_decrypt,%function
+.align 4
+bsaes_xts_decrypt:
+ mov ip, sp
+ stmdb sp!, {r4-r10, lr} @ 0x20
+ VFP_ABI_PUSH
+ mov r6, sp @ future $fp
+
+ mov $inp, r0
+ mov $out, r1
+ mov $len, r2
+ mov $key, r3
+
+ sub r0, sp, #0x10 @ 0x10
+ bic r0, #0xf @ align at 16 bytes
+ mov sp, r0
+
+#ifdef XTS_CHAIN_TWEAK
+ ldr r0, [ip] @ pointer to input tweak
+#else
+ @ generate initial tweak
+ ldr r0, [ip, #4] @ iv[]
+ mov r1, sp
+ ldr r2, [ip, #0] @ key2
+ bl AES_encrypt
+ mov r0, sp @ pointer to initial tweak
+#endif
+
+ ldr $rounds, [$key, #240] @ get # of rounds
+ mov $fp, r6
+#ifndef BSAES_ASM_EXTENDED_KEY
+ @ allocate the key schedule on the stack
+ sub r12, sp, $rounds, lsl#7 @ 128 bytes per inner round key
+ @ add r12, #`128-32` @ size of bit-sliced key schedule
+ sub r12, #`32+16` @ place for tweak[9]
+
+ @ populate the key schedule
+ mov r4, $key @ pass key
+ mov r5, $rounds @ pass # of rounds
+ mov sp, r12
+ add r12, #0x90 @ pass key schedule
+ bl _bsaes_key_convert
+ add r4, sp, #0x90
+ vldmia r4, {@XMM[6]}
+ vstmia r12, {@XMM[15]} @ save last round key
+ veor @XMM[7], @XMM[7], @XMM[6] @ fix up round 0 key
+ vstmia r4, {@XMM[7]}
+#else
+ ldr r12, [$key, #244]
+ eors r12, #1
+ beq 0f
+
+ str r12, [$key, #244]
+ mov r4, $key @ pass key
+ mov r5, $rounds @ pass # of rounds
+ add r12, $key, #248 @ pass key schedule
+ bl _bsaes_key_convert
+ add r4, $key, #248
+ vldmia r4, {@XMM[6]}
+ vstmia r12, {@XMM[15]} @ save last round key
+ veor @XMM[7], @XMM[7], @XMM[6] @ fix up round 0 key
+ vstmia r4, {@XMM[7]}
+
+.align 2
+0: sub sp, #0x90 @ place for tweak[9]
+#endif
+ vld1.8 {@XMM[8]}, [r0] @ initial tweak
+ adr $magic, .Lxts_magic
+
+ tst $len, #0xf @ if not multiple of 16
+ it ne @ Thumb2 thing, sanity check in ARM
+ subne $len, #0x10 @ subtract another 16 bytes
+ subs $len, #0x80
+
+ blo .Lxts_dec_short
+ b .Lxts_dec_loop
+
+.align 4
+.Lxts_dec_loop:
+ vldmia $magic, {$twmask} @ load XTS magic
+ vshr.s64 @T[0], @XMM[8], #63
+ mov r0, sp
+ vand @T[0], @T[0], $twmask
+___
+for($i=9;$i<16;$i++) {
+$code.=<<___;
+ vadd.u64 @XMM[$i], @XMM[$i-1], @XMM[$i-1]
+ vst1.64 {@XMM[$i-1]}, [r0,:128]!
+ vswp `&Dhi("@T[0]")`,`&Dlo("@T[0]")`
+ vshr.s64 @T[1], @XMM[$i], #63
+ veor @XMM[$i], @XMM[$i], @T[0]
+ vand @T[1], @T[1], $twmask
+___
+ @T=reverse(@T);
+
+$code.=<<___ if ($i>=10);
+ vld1.8 {@XMM[$i-10]}, [$inp]!
+___
+$code.=<<___ if ($i>=11);
+ veor @XMM[$i-11], @XMM[$i-11], @XMM[$i-3]
+___
+}
+$code.=<<___;
+ vadd.u64 @XMM[8], @XMM[15], @XMM[15]
+ vst1.64 {@XMM[15]}, [r0,:128]!
+ vswp `&Dhi("@T[0]")`,`&Dlo("@T[0]")`
+ veor @XMM[8], @XMM[8], @T[0]
+ vst1.64 {@XMM[8]}, [r0,:128] @ next round tweak
+
+ vld1.8 {@XMM[6]-@XMM[7]}, [$inp]!
+ veor @XMM[5], @XMM[5], @XMM[13]
+#ifndef BSAES_ASM_EXTENDED_KEY
+ add r4, sp, #0x90 @ pass key schedule
+#else
+ add r4, $key, #248 @ pass key schedule
+#endif
+ veor @XMM[6], @XMM[6], @XMM[14]
+ mov r5, $rounds @ pass rounds
+ veor @XMM[7], @XMM[7], @XMM[15]
+ mov r0, sp
+
+ bl _bsaes_decrypt8
+
+ vld1.64 {@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
+ vld1.64 {@XMM[10]-@XMM[11]}, [r0,:128]!
+ veor @XMM[0], @XMM[0], @XMM[ 8]
+ vld1.64 {@XMM[12]-@XMM[13]}, [r0,:128]!
+ veor @XMM[1], @XMM[1], @XMM[ 9]
+ veor @XMM[8], @XMM[6], @XMM[10]
+ vst1.8 {@XMM[0]-@XMM[1]}, [$out]!
+ veor @XMM[9], @XMM[4], @XMM[11]
+ vld1.64 {@XMM[14]-@XMM[15]}, [r0,:128]!
+ veor @XMM[10], @XMM[2], @XMM[12]
+ vst1.8 {@XMM[8]-@XMM[9]}, [$out]!
+ veor @XMM[11], @XMM[7], @XMM[13]
+ veor @XMM[12], @XMM[3], @XMM[14]
+ vst1.8 {@XMM[10]-@XMM[11]}, [$out]!
+ veor @XMM[13], @XMM[5], @XMM[15]
+ vst1.8 {@XMM[12]-@XMM[13]}, [$out]!
+
+ vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak
+
+ subs $len, #0x80
+ bpl .Lxts_dec_loop
+
+.Lxts_dec_short:
+ adds $len, #0x70
+ bmi .Lxts_dec_done
+
+ vldmia $magic, {$twmask} @ load XTS magic
+ vshr.s64 @T[0], @XMM[8], #63
+ mov r0, sp
+ vand @T[0], @T[0], $twmask
+___
+for($i=9;$i<16;$i++) {
+$code.=<<___;
+ vadd.u64 @XMM[$i], @XMM[$i-1], @XMM[$i-1]
+ vst1.64 {@XMM[$i-1]}, [r0,:128]!
+ vswp `&Dhi("@T[0]")`,`&Dlo("@T[0]")`
+ vshr.s64 @T[1], @XMM[$i], #63
+ veor @XMM[$i], @XMM[$i], @T[0]
+ vand @T[1], @T[1], $twmask
+___
+ @T=reverse(@T);
+
+$code.=<<___ if ($i>=10);
+ vld1.8 {@XMM[$i-10]}, [$inp]!
+ subs $len, #0x10
+ bmi .Lxts_dec_`$i-9`
+___
+$code.=<<___ if ($i>=11);
+ veor @XMM[$i-11], @XMM[$i-11], @XMM[$i-3]
+___
+}
+$code.=<<___;
+ sub $len, #0x10
+ vst1.64 {@XMM[15]}, [r0,:128] @ next round tweak
+
+ vld1.8 {@XMM[6]}, [$inp]!
+ veor @XMM[5], @XMM[5], @XMM[13]
+#ifndef BSAES_ASM_EXTENDED_KEY
+ add r4, sp, #0x90 @ pass key schedule
+#else
+ add r4, $key, #248 @ pass key schedule
+#endif
+ veor @XMM[6], @XMM[6], @XMM[14]
+ mov r5, $rounds @ pass rounds
+ mov r0, sp
+
+ bl _bsaes_decrypt8
+
+ vld1.64 {@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
+ vld1.64 {@XMM[10]-@XMM[11]}, [r0,:128]!
+ veor @XMM[0], @XMM[0], @XMM[ 8]
+ vld1.64 {@XMM[12]-@XMM[13]}, [r0,:128]!
+ veor @XMM[1], @XMM[1], @XMM[ 9]
+ veor @XMM[8], @XMM[6], @XMM[10]
+ vst1.8 {@XMM[0]-@XMM[1]}, [$out]!
+ veor @XMM[9], @XMM[4], @XMM[11]
+ vld1.64 {@XMM[14]}, [r0,:128]!
+ veor @XMM[10], @XMM[2], @XMM[12]
+ vst1.8 {@XMM[8]-@XMM[9]}, [$out]!
+ veor @XMM[11], @XMM[7], @XMM[13]
+ veor @XMM[12], @XMM[3], @XMM[14]
+ vst1.8 {@XMM[10]-@XMM[11]}, [$out]!
+ vst1.8 {@XMM[12]}, [$out]!
+
+ vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak
+ b .Lxts_dec_done
+.align 4
+.Lxts_dec_6:
+ vst1.64 {@XMM[14]}, [r0,:128] @ next round tweak
+
+ veor @XMM[4], @XMM[4], @XMM[12]
+#ifndef BSAES_ASM_EXTENDED_KEY
+ add r4, sp, #0x90 @ pass key schedule
+#else
+ add r4, $key, #248 @ pass key schedule
+#endif
+ veor @XMM[5], @XMM[5], @XMM[13]
+ mov r5, $rounds @ pass rounds
+ mov r0, sp
+
+ bl _bsaes_decrypt8
+
+ vld1.64 {@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
+ vld1.64 {@XMM[10]-@XMM[11]}, [r0,:128]!
+ veor @XMM[0], @XMM[0], @XMM[ 8]
+ vld1.64 {@XMM[12]-@XMM[13]}, [r0,:128]!
+ veor @XMM[1], @XMM[1], @XMM[ 9]
+ veor @XMM[8], @XMM[6], @XMM[10]
+ vst1.8 {@XMM[0]-@XMM[1]}, [$out]!
+ veor @XMM[9], @XMM[4], @XMM[11]
+ veor @XMM[10], @XMM[2], @XMM[12]
+ vst1.8 {@XMM[8]-@XMM[9]}, [$out]!
+ veor @XMM[11], @XMM[7], @XMM[13]
+ vst1.8 {@XMM[10]-@XMM[11]}, [$out]!
+
+ vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak
+ b .Lxts_dec_done
+.align 4
+.Lxts_dec_5:
+ vst1.64 {@XMM[13]}, [r0,:128] @ next round tweak
+
+ veor @XMM[3], @XMM[3], @XMM[11]
+#ifndef BSAES_ASM_EXTENDED_KEY
+ add r4, sp, #0x90 @ pass key schedule
+#else
+ add r4, $key, #248 @ pass key schedule
+#endif
+ veor @XMM[4], @XMM[4], @XMM[12]
+ mov r5, $rounds @ pass rounds
+ mov r0, sp
+
+ bl _bsaes_decrypt8
+
+ vld1.64 {@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
+ vld1.64 {@XMM[10]-@XMM[11]}, [r0,:128]!
+ veor @XMM[0], @XMM[0], @XMM[ 8]
+ vld1.64 {@XMM[12]}, [r0,:128]!
+ veor @XMM[1], @XMM[1], @XMM[ 9]
+ veor @XMM[8], @XMM[6], @XMM[10]
+ vst1.8 {@XMM[0]-@XMM[1]}, [$out]!
+ veor @XMM[9], @XMM[4], @XMM[11]
+ veor @XMM[10], @XMM[2], @XMM[12]
+ vst1.8 {@XMM[8]-@XMM[9]}, [$out]!
+ vst1.8 {@XMM[10]}, [$out]!
+
+ vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak
+ b .Lxts_dec_done
+.align 4
+.Lxts_dec_4:
+ vst1.64 {@XMM[12]}, [r0,:128] @ next round tweak
+
+ veor @XMM[2], @XMM[2], @XMM[10]
+#ifndef BSAES_ASM_EXTENDED_KEY
+ add r4, sp, #0x90 @ pass key schedule
+#else
+ add r4, $key, #248 @ pass key schedule
+#endif
+ veor @XMM[3], @XMM[3], @XMM[11]
+ mov r5, $rounds @ pass rounds
+ mov r0, sp
+
+ bl _bsaes_decrypt8
+
+ vld1.64 {@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
+ vld1.64 {@XMM[10]-@XMM[11]}, [r0,:128]!
+ veor @XMM[0], @XMM[0], @XMM[ 8]
+ veor @XMM[1], @XMM[1], @XMM[ 9]
+ veor @XMM[8], @XMM[6], @XMM[10]
+ vst1.8 {@XMM[0]-@XMM[1]}, [$out]!
+ veor @XMM[9], @XMM[4], @XMM[11]
+ vst1.8 {@XMM[8]-@XMM[9]}, [$out]!
+
+ vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak
+ b .Lxts_dec_done
+.align 4
+.Lxts_dec_3:
+ vst1.64 {@XMM[11]}, [r0,:128] @ next round tweak
+
+ veor @XMM[1], @XMM[1], @XMM[9]
+#ifndef BSAES_ASM_EXTENDED_KEY
+ add r4, sp, #0x90 @ pass key schedule
+#else
+ add r4, $key, #248 @ pass key schedule
+#endif
+ veor @XMM[2], @XMM[2], @XMM[10]
+ mov r5, $rounds @ pass rounds
+ mov r0, sp
+
+ bl _bsaes_decrypt8
+
+ vld1.64 {@XMM[8]-@XMM[9]}, [r0,:128]!
+ vld1.64 {@XMM[10]}, [r0,:128]!
+ veor @XMM[0], @XMM[0], @XMM[ 8]
+ veor @XMM[1], @XMM[1], @XMM[ 9]
+ veor @XMM[8], @XMM[6], @XMM[10]
+ vst1.8 {@XMM[0]-@XMM[1]}, [$out]!
+ vst1.8 {@XMM[8]}, [$out]!
+
+ vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak
+ b .Lxts_dec_done
+.align 4
+.Lxts_dec_2:
+ vst1.64 {@XMM[10]}, [r0,:128] @ next round tweak
+
+ veor @XMM[0], @XMM[0], @XMM[8]
+#ifndef BSAES_ASM_EXTENDED_KEY
+ add r4, sp, #0x90 @ pass key schedule
+#else
+ add r4, $key, #248 @ pass key schedule
+#endif
+ veor @XMM[1], @XMM[1], @XMM[9]
+ mov r5, $rounds @ pass rounds
+ mov r0, sp
+
+ bl _bsaes_decrypt8
+
+ vld1.64 {@XMM[8]-@XMM[9]}, [r0,:128]!
+ veor @XMM[0], @XMM[0], @XMM[ 8]
+ veor @XMM[1], @XMM[1], @XMM[ 9]
+ vst1.8 {@XMM[0]-@XMM[1]}, [$out]!
+
+ vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak
+ b .Lxts_dec_done
+.align 4
+.Lxts_dec_1:
+ mov r0, sp
+ veor @XMM[0], @XMM[8]
+ mov r1, sp
+ vst1.8 {@XMM[0]}, [sp,:128]
+ mov r2, $key
+ mov r4, $fp @ preserve fp
+ mov r5, $magic @ preserve magic
+
+ bl AES_decrypt
+
+ vld1.8 {@XMM[0]}, [sp,:128]
+ veor @XMM[0], @XMM[0], @XMM[8]
+ vst1.8 {@XMM[0]}, [$out]!
+ mov $fp, r4
+ mov $magic, r5
+
+ vmov @XMM[8], @XMM[9] @ next round tweak
+
+.Lxts_dec_done:
+#ifndef XTS_CHAIN_TWEAK
+ adds $len, #0x10
+ beq .Lxts_dec_ret
+
+ @ calculate one round of extra tweak for the stolen ciphertext
+ vldmia $magic, {$twmask}
+ vshr.s64 @XMM[6], @XMM[8], #63
+ vand @XMM[6], @XMM[6], $twmask
+ vadd.u64 @XMM[9], @XMM[8], @XMM[8]
+ vswp `&Dhi("@XMM[6]")`,`&Dlo("@XMM[6]")`
+ veor @XMM[9], @XMM[9], @XMM[6]
+
+ @ perform the final decryption with the last tweak value
+ vld1.8 {@XMM[0]}, [$inp]!
+ mov r0, sp
+ veor @XMM[0], @XMM[0], @XMM[9]
+ mov r1, sp
+ vst1.8 {@XMM[0]}, [sp,:128]
+ mov r2, $key
+ mov r4, $fp @ preserve fp
+
+ bl AES_decrypt
+
+ vld1.8 {@XMM[0]}, [sp,:128]
+ veor @XMM[0], @XMM[0], @XMM[9]
+ vst1.8 {@XMM[0]}, [$out]
+
+ mov r6, $out
+.Lxts_dec_steal:
+ ldrb r1, [$out]
+ ldrb r0, [$inp], #1
+ strb r1, [$out, #0x10]
+ strb r0, [$out], #1
+
+ subs $len, #1
+ bhi .Lxts_dec_steal
+
+ vld1.8 {@XMM[0]}, [r6]
+ mov r0, sp
+ veor @XMM[0], @XMM[8]
+ mov r1, sp
+ vst1.8 {@XMM[0]}, [sp,:128]
+ mov r2, $key
+
+ bl AES_decrypt
+
+ vld1.8 {@XMM[0]}, [sp,:128]
+ veor @XMM[0], @XMM[0], @XMM[8]
+ vst1.8 {@XMM[0]}, [r6]
+ mov $fp, r4
+#endif
+
+.Lxts_dec_ret:
+ bic r0, $fp, #0xf
+ vmov.i32 q0, #0
+ vmov.i32 q1, #0
+#ifdef XTS_CHAIN_TWEAK
+ ldr r1, [$fp, #0x20+VFP_ABI_FRAME] @ chain tweak
+#endif
+.Lxts_dec_bzero: @ wipe key schedule [if any]
+ vstmia sp!, {q0-q1}
+ cmp sp, r0
+ bne .Lxts_dec_bzero
+
+ mov sp, $fp
+#ifdef XTS_CHAIN_TWEAK
+ vst1.8 {@XMM[8]}, [r1]
+#endif
+ VFP_ABI_POP
+ ldmia sp!, {r4-r10, pc} @ return
+
+.size bsaes_xts_decrypt,.-bsaes_xts_decrypt
+___
+}
+$code.=<<___;
+#endif
+#endif
+___
+
+$code =~ s/\`([^\`]*)\`/eval($1)/gem;
+
+open SELF,$0;
+while(<SELF>) {
+ next if (/^#!/);
+ last if (!s/^#/@/ and !/^$/);
+ print;
+}
+close SELF;
+
+print $code;
+
+close STDOUT;
diff --git a/src/crypto/aes/asm/bsaes-x86_64.pl b/src/crypto/aes/asm/bsaes-x86_64.pl
new file mode 100644
index 0000000..3f7d33c
--- /dev/null
+++ b/src/crypto/aes/asm/bsaes-x86_64.pl
@@ -0,0 +1,3102 @@
+#!/usr/bin/env perl
+
+###################################################################
+### AES-128 [originally in CTR mode] ###
+### bitsliced implementation for Intel Core 2 processors ###
+### requires support of SSE extensions up to SSSE3 ###
+### Author: Emilia Käsper and Peter Schwabe ###
+### Date: 2009-03-19 ###
+### Public domain ###
+### ###
+### See http://homes.esat.kuleuven.be/~ekasper/#software for ###
+### further information. ###
+###################################################################
+#
+# September 2011.
+#
+# Started as transliteration to "perlasm" the original code has
+# undergone following changes:
+#
+# - code was made position-independent;
+# - rounds were folded into a loop resulting in >5x size reduction
+# from 12.5KB to 2.2KB;
+# - above was possibile thanks to mixcolumns() modification that
+# allowed to feed its output back to aesenc[last], this was
+# achieved at cost of two additional inter-registers moves;
+# - some instruction reordering and interleaving;
+# - this module doesn't implement key setup subroutine, instead it
+# relies on conversion of "conventional" key schedule as returned
+# by AES_set_encrypt_key (see discussion below);
+# - first and last round keys are treated differently, which allowed
+# to skip one shiftrows(), reduce bit-sliced key schedule and
+# speed-up conversion by 22%;
+# - support for 192- and 256-bit keys was added;
+#
+# Resulting performance in CPU cycles spent to encrypt one byte out
+# of 4096-byte buffer with 128-bit key is:
+#
+# Emilia's this(*) difference
+#
+# Core 2 9.30 8.69 +7%
+# Nehalem(**) 7.63 6.88 +11%
+# Atom 17.1 16.4 +4%
+# Silvermont - 12.9
+#
+# (*) Comparison is not completely fair, because "this" is ECB,
+# i.e. no extra processing such as counter values calculation
+# and xor-ing input as in Emilia's CTR implementation is
+# performed. However, the CTR calculations stand for not more
+# than 1% of total time, so comparison is *rather* fair.
+#
+# (**) Results were collected on Westmere, which is considered to
+# be equivalent to Nehalem for this code.
+#
+# As for key schedule conversion subroutine. Interface to OpenSSL
+# relies on per-invocation on-the-fly conversion. This naturally
+# has impact on performance, especially for short inputs. Conversion
+# time in CPU cycles and its ratio to CPU cycles spent in 8x block
+# function is:
+#
+# conversion conversion/8x block
+# Core 2 240 0.22
+# Nehalem 180 0.20
+# Atom 430 0.20
+#
+# The ratio values mean that 128-byte blocks will be processed
+# 16-18% slower, 256-byte blocks - 9-10%, 384-byte blocks - 6-7%,
+# etc. Then keep in mind that input sizes not divisible by 128 are
+# *effectively* slower, especially shortest ones, e.g. consecutive
+# 144-byte blocks are processed 44% slower than one would expect,
+# 272 - 29%, 400 - 22%, etc. Yet, despite all these "shortcomings"
+# it's still faster than ["hyper-threading-safe" code path in]
+# aes-x86_64.pl on all lengths above 64 bytes...
+#
+# October 2011.
+#
+# Add decryption procedure. Performance in CPU cycles spent to decrypt
+# one byte out of 4096-byte buffer with 128-bit key is:
+#
+# Core 2 9.98
+# Nehalem 7.80
+# Atom 17.9
+# Silvermont 14.0
+#
+# November 2011.
+#
+# Add bsaes_xts_[en|de]crypt. Less-than-80-bytes-block performance is
+# suboptimal, but XTS is meant to be used with larger blocks...
+#
+# <appro@openssl.org>
+
+$flavour = shift;
+$output = shift;
+if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+
+$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
+( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
+die "can't locate x86_64-xlate.pl";
+
+open OUT,"| \"$^X\" $xlate $flavour $output";
+*STDOUT=*OUT;
+
+my ($inp,$out,$len,$key,$ivp)=("%rdi","%rsi","%rdx","%rcx");
+my @XMM=map("%xmm$_",(15,0..14)); # best on Atom, +10% over (0..15)
+my $ecb=0; # suppress unreferenced ECB subroutines, spare some space...
+
+{
+my ($key,$rounds,$const)=("%rax","%r10d","%r11");
+
+sub Sbox {
+# input in lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb
+# output in lsb > [b0, b1, b4, b6, b3, b7, b2, b5] < msb
+my @b=@_[0..7];
+my @t=@_[8..11];
+my @s=@_[12..15];
+ &InBasisChange (@b);
+ &Inv_GF256 (@b[6,5,0,3,7,1,4,2],@t,@s);
+ &OutBasisChange (@b[7,1,4,2,6,5,0,3]);
+}
+
+sub InBasisChange {
+# input in lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb
+# output in lsb > [b6, b5, b0, b3, b7, b1, b4, b2] < msb
+my @b=@_[0..7];
+$code.=<<___;
+ pxor @b[6], @b[5]
+ pxor @b[1], @b[2]
+ pxor @b[0], @b[3]
+ pxor @b[2], @b[6]
+ pxor @b[0], @b[5]
+
+ pxor @b[3], @b[6]
+ pxor @b[7], @b[3]
+ pxor @b[5], @b[7]
+ pxor @b[4], @b[3]
+ pxor @b[5], @b[4]
+ pxor @b[1], @b[3]
+
+ pxor @b[7], @b[2]
+ pxor @b[5], @b[1]
+___
+}
+
+sub OutBasisChange {
+# input in lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb
+# output in lsb > [b6, b1, b2, b4, b7, b0, b3, b5] < msb
+my @b=@_[0..7];
+$code.=<<___;
+ pxor @b[6], @b[0]
+ pxor @b[4], @b[1]
+ pxor @b[0], @b[2]
+ pxor @b[6], @b[4]
+ pxor @b[1], @b[6]
+
+ pxor @b[5], @b[1]
+ pxor @b[3], @b[5]
+ pxor @b[7], @b[3]
+ pxor @b[5], @b[7]
+ pxor @b[5], @b[2]
+
+ pxor @b[7], @b[4]
+___
+}
+
+sub InvSbox {
+# input in lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb
+# output in lsb > [b0, b1, b6, b4, b2, b7, b3, b5] < msb
+my @b=@_[0..7];
+my @t=@_[8..11];
+my @s=@_[12..15];
+ &InvInBasisChange (@b);
+ &Inv_GF256 (@b[5,1,2,6,3,7,0,4],@t,@s);
+ &InvOutBasisChange (@b[3,7,0,4,5,1,2,6]);
+}
+
+sub InvInBasisChange { # OutBasisChange in reverse
+my @b=@_[5,1,2,6,3,7,0,4];
+$code.=<<___
+ pxor @b[7], @b[4]
+
+ pxor @b[5], @b[7]
+ pxor @b[5], @b[2]
+ pxor @b[7], @b[3]
+ pxor @b[3], @b[5]
+ pxor @b[5], @b[1]
+
+ pxor @b[1], @b[6]
+ pxor @b[0], @b[2]
+ pxor @b[6], @b[4]
+ pxor @b[6], @b[0]
+ pxor @b[4], @b[1]
+___
+}
+
+sub InvOutBasisChange { # InBasisChange in reverse
+my @b=@_[2,5,7,3,6,1,0,4];
+$code.=<<___;
+ pxor @b[5], @b[1]
+ pxor @b[7], @b[2]
+
+ pxor @b[1], @b[3]
+ pxor @b[5], @b[4]
+ pxor @b[5], @b[7]
+ pxor @b[4], @b[3]
+ pxor @b[0], @b[5]
+ pxor @b[7], @b[3]
+ pxor @b[2], @b[6]
+ pxor @b[1], @b[2]
+ pxor @b[3], @b[6]
+
+ pxor @b[0], @b[3]
+ pxor @b[6], @b[5]
+___
+}
+
+sub Mul_GF4 {
+#;*************************************************************
+#;* Mul_GF4: Input x0-x1,y0-y1 Output x0-x1 Temp t0 (8) *
+#;*************************************************************
+my ($x0,$x1,$y0,$y1,$t0)=@_;
+$code.=<<___;
+ movdqa $y0, $t0
+ pxor $y1, $t0
+ pand $x0, $t0
+ pxor $x1, $x0
+ pand $y0, $x1
+ pand $y1, $x0
+ pxor $x1, $x0
+ pxor $t0, $x1
+___
+}
+
+sub Mul_GF4_N { # not used, see next subroutine
+# multiply and scale by N
+my ($x0,$x1,$y0,$y1,$t0)=@_;
+$code.=<<___;
+ movdqa $y0, $t0
+ pxor $y1, $t0
+ pand $x0, $t0
+ pxor $x1, $x0
+ pand $y0, $x1
+ pand $y1, $x0
+ pxor $x0, $x1
+ pxor $t0, $x0
+___
+}
+
+sub Mul_GF4_N_GF4 {
+# interleaved Mul_GF4_N and Mul_GF4
+my ($x0,$x1,$y0,$y1,$t0,
+ $x2,$x3,$y2,$y3,$t1)=@_;
+$code.=<<___;
+ movdqa $y0, $t0
+ movdqa $y2, $t1
+ pxor $y1, $t0
+ pxor $y3, $t1
+ pand $x0, $t0
+ pand $x2, $t1
+ pxor $x1, $x0
+ pxor $x3, $x2
+ pand $y0, $x1
+ pand $y2, $x3
+ pand $y1, $x0
+ pand $y3, $x2
+ pxor $x0, $x1
+ pxor $x3, $x2
+ pxor $t0, $x0
+ pxor $t1, $x3
+___
+}
+sub Mul_GF16_2 {
+my @x=@_[0..7];
+my @y=@_[8..11];
+my @t=@_[12..15];
+$code.=<<___;
+ movdqa @x[0], @t[0]
+ movdqa @x[1], @t[1]
+___
+ &Mul_GF4 (@x[0], @x[1], @y[0], @y[1], @t[2]);
+$code.=<<___;
+ pxor @x[2], @t[0]
+ pxor @x[3], @t[1]
+ pxor @y[2], @y[0]
+ pxor @y[3], @y[1]
+___
+ Mul_GF4_N_GF4 (@t[0], @t[1], @y[0], @y[1], @t[3],
+ @x[2], @x[3], @y[2], @y[3], @t[2]);
+$code.=<<___;
+ pxor @t[0], @x[0]
+ pxor @t[0], @x[2]
+ pxor @t[1], @x[1]
+ pxor @t[1], @x[3]
+
+ movdqa @x[4], @t[0]
+ movdqa @x[5], @t[1]
+ pxor @x[6], @t[0]
+ pxor @x[7], @t[1]
+___
+ &Mul_GF4_N_GF4 (@t[0], @t[1], @y[0], @y[1], @t[3],
+ @x[6], @x[7], @y[2], @y[3], @t[2]);
+$code.=<<___;
+ pxor @y[2], @y[0]
+ pxor @y[3], @y[1]
+___
+ &Mul_GF4 (@x[4], @x[5], @y[0], @y[1], @t[3]);
+$code.=<<___;
+ pxor @t[0], @x[4]
+ pxor @t[0], @x[6]
+ pxor @t[1], @x[5]
+ pxor @t[1], @x[7]
+___
+}
+sub Inv_GF256 {
+#;********************************************************************
+#;* Inv_GF256: Input x0-x7 Output x0-x7 Temp t0-t3,s0-s3 (144) *
+#;********************************************************************
+my @x=@_[0..7];
+my @t=@_[8..11];
+my @s=@_[12..15];
+# direct optimizations from hardware
+$code.=<<___;
+ movdqa @x[4], @t[3]
+ movdqa @x[5], @t[2]
+ movdqa @x[1], @t[1]
+ movdqa @x[7], @s[1]
+ movdqa @x[0], @s[0]
+
+ pxor @x[6], @t[3]
+ pxor @x[7], @t[2]
+ pxor @x[3], @t[1]
+ movdqa @t[3], @s[2]
+ pxor @x[6], @s[1]
+ movdqa @t[2], @t[0]
+ pxor @x[2], @s[0]
+ movdqa @t[3], @s[3]
+
+ por @t[1], @t[2]
+ por @s[0], @t[3]
+ pxor @t[0], @s[3]
+ pand @s[0], @s[2]
+ pxor @t[1], @s[0]
+ pand @t[1], @t[0]
+ pand @s[0], @s[3]
+ movdqa @x[3], @s[0]
+ pxor @x[2], @s[0]
+ pand @s[0], @s[1]
+ pxor @s[1], @t[3]
+ pxor @s[1], @t[2]
+ movdqa @x[4], @s[1]
+ movdqa @x[1], @s[0]
+ pxor @x[5], @s[1]
+ pxor @x[0], @s[0]
+ movdqa @s[1], @t[1]
+ pand @s[0], @s[1]
+ por @s[0], @t[1]
+ pxor @s[1], @t[0]
+ pxor @s[3], @t[3]
+ pxor @s[2], @t[2]
+ pxor @s[3], @t[1]
+ movdqa @x[7], @s[0]
+ pxor @s[2], @t[0]
+ movdqa @x[6], @s[1]
+ pxor @s[2], @t[1]
+ movdqa @x[5], @s[2]
+ pand @x[3], @s[0]
+ movdqa @x[4], @s[3]
+ pand @x[2], @s[1]
+ pand @x[1], @s[2]
+ por @x[0], @s[3]
+ pxor @s[0], @t[3]
+ pxor @s[1], @t[2]
+ pxor @s[2], @t[1]
+ pxor @s[3], @t[0]
+
+ #Inv_GF16 \t0, \t1, \t2, \t3, \s0, \s1, \s2, \s3
+
+ # new smaller inversion
+
+ movdqa @t[3], @s[0]
+ pand @t[1], @t[3]
+ pxor @t[2], @s[0]
+
+ movdqa @t[0], @s[2]
+ movdqa @s[0], @s[3]
+ pxor @t[3], @s[2]
+ pand @s[2], @s[3]
+
+ movdqa @t[1], @s[1]
+ pxor @t[2], @s[3]
+ pxor @t[0], @s[1]
+
+ pxor @t[2], @t[3]
+
+ pand @t[3], @s[1]
+
+ movdqa @s[2], @t[2]
+ pxor @t[0], @s[1]
+
+ pxor @s[1], @t[2]
+ pxor @s[1], @t[1]
+
+ pand @t[0], @t[2]
+
+ pxor @t[2], @s[2]
+ pxor @t[2], @t[1]
+
+ pand @s[3], @s[2]
+
+ pxor @s[0], @s[2]
+___
+# output in s3, s2, s1, t1
+
+# Mul_GF16_2 \x0, \x1, \x2, \x3, \x4, \x5, \x6, \x7, \t2, \t3, \t0, \t1, \s0, \s1, \s2, \s3
+
+# Mul_GF16_2 \x0, \x1, \x2, \x3, \x4, \x5, \x6, \x7, \s3, \s2, \s1, \t1, \s0, \t0, \t2, \t3
+ &Mul_GF16_2(@x,@s[3,2,1],@t[1],@s[0],@t[0,2,3]);
+
+### output msb > [x3,x2,x1,x0,x7,x6,x5,x4] < lsb
+}
+
+# AES linear components
+
+sub ShiftRows {
+my @x=@_[0..7];
+my $mask=pop;
+$code.=<<___;
+ pxor 0x00($key),@x[0]
+ pxor 0x10($key),@x[1]
+ pxor 0x20($key),@x[2]
+ pxor 0x30($key),@x[3]
+ pshufb $mask,@x[0]
+ pshufb $mask,@x[1]
+ pxor 0x40($key),@x[4]
+ pxor 0x50($key),@x[5]
+ pshufb $mask,@x[2]
+ pshufb $mask,@x[3]
+ pxor 0x60($key),@x[6]
+ pxor 0x70($key),@x[7]
+ pshufb $mask,@x[4]
+ pshufb $mask,@x[5]
+ pshufb $mask,@x[6]
+ pshufb $mask,@x[7]
+ lea 0x80($key),$key
+___
+}
+
+sub MixColumns {
+# modified to emit output in order suitable for feeding back to aesenc[last]
+my @x=@_[0..7];
+my @t=@_[8..15];
+my $inv=@_[16]; # optional
+$code.=<<___;
+ pshufd \$0x93, @x[0], @t[0] # x0 <<< 32
+ pshufd \$0x93, @x[1], @t[1]
+ pxor @t[0], @x[0] # x0 ^ (x0 <<< 32)
+ pshufd \$0x93, @x[2], @t[2]
+ pxor @t[1], @x[1]
+ pshufd \$0x93, @x[3], @t[3]
+ pxor @t[2], @x[2]
+ pshufd \$0x93, @x[4], @t[4]
+ pxor @t[3], @x[3]
+ pshufd \$0x93, @x[5], @t[5]
+ pxor @t[4], @x[4]
+ pshufd \$0x93, @x[6], @t[6]
+ pxor @t[5], @x[5]
+ pshufd \$0x93, @x[7], @t[7]
+ pxor @t[6], @x[6]
+ pxor @t[7], @x[7]
+
+ pxor @x[0], @t[1]
+ pxor @x[7], @t[0]
+ pxor @x[7], @t[1]
+ pshufd \$0x4E, @x[0], @x[0] # (x0 ^ (x0 <<< 32)) <<< 64)
+ pxor @x[1], @t[2]
+ pshufd \$0x4E, @x[1], @x[1]
+ pxor @x[4], @t[5]
+ pxor @t[0], @x[0]
+ pxor @x[5], @t[6]
+ pxor @t[1], @x[1]
+ pxor @x[3], @t[4]
+ pshufd \$0x4E, @x[4], @t[0]
+ pxor @x[6], @t[7]
+ pshufd \$0x4E, @x[5], @t[1]
+ pxor @x[2], @t[3]
+ pshufd \$0x4E, @x[3], @x[4]
+ pxor @x[7], @t[3]
+ pshufd \$0x4E, @x[7], @x[5]
+ pxor @x[7], @t[4]
+ pshufd \$0x4E, @x[6], @x[3]
+ pxor @t[4], @t[0]
+ pshufd \$0x4E, @x[2], @x[6]
+ pxor @t[5], @t[1]
+___
+$code.=<<___ if (!$inv);
+ pxor @t[3], @x[4]
+ pxor @t[7], @x[5]
+ pxor @t[6], @x[3]
+ movdqa @t[0], @x[2]
+ pxor @t[2], @x[6]
+ movdqa @t[1], @x[7]
+___
+$code.=<<___ if ($inv);
+ pxor @x[4], @t[3]
+ pxor @t[7], @x[5]
+ pxor @x[3], @t[6]
+ movdqa @t[0], @x[3]
+ pxor @t[2], @x[6]
+ movdqa @t[6], @x[2]
+ movdqa @t[1], @x[7]
+ movdqa @x[6], @x[4]
+ movdqa @t[3], @x[6]
+___
+}
+
+sub InvMixColumns_orig {
+my @x=@_[0..7];
+my @t=@_[8..15];
+
+$code.=<<___;
+ # multiplication by 0x0e
+ pshufd \$0x93, @x[7], @t[7]
+ movdqa @x[2], @t[2]
+ pxor @x[5], @x[7] # 7 5
+ pxor @x[5], @x[2] # 2 5
+ pshufd \$0x93, @x[0], @t[0]
+ movdqa @x[5], @t[5]
+ pxor @x[0], @x[5] # 5 0 [1]
+ pxor @x[1], @x[0] # 0 1
+ pshufd \$0x93, @x[1], @t[1]
+ pxor @x[2], @x[1] # 1 25
+ pxor @x[6], @x[0] # 01 6 [2]
+ pxor @x[3], @x[1] # 125 3 [4]
+ pshufd \$0x93, @x[3], @t[3]
+ pxor @x[0], @x[2] # 25 016 [3]
+ pxor @x[7], @x[3] # 3 75
+ pxor @x[6], @x[7] # 75 6 [0]
+ pshufd \$0x93, @x[6], @t[6]
+ movdqa @x[4], @t[4]
+ pxor @x[4], @x[6] # 6 4
+ pxor @x[3], @x[4] # 4 375 [6]
+ pxor @x[7], @x[3] # 375 756=36
+ pxor @t[5], @x[6] # 64 5 [7]
+ pxor @t[2], @x[3] # 36 2
+ pxor @t[4], @x[3] # 362 4 [5]
+ pshufd \$0x93, @t[5], @t[5]
+___
+ my @y = @x[7,5,0,2,1,3,4,6];
+$code.=<<___;
+ # multiplication by 0x0b
+ pxor @y[0], @y[1]
+ pxor @t[0], @y[0]
+ pxor @t[1], @y[1]
+ pshufd \$0x93, @t[2], @t[2]
+ pxor @t[5], @y[0]
+ pxor @t[6], @y[1]
+ pxor @t[7], @y[0]
+ pshufd \$0x93, @t[4], @t[4]
+ pxor @t[6], @t[7] # clobber t[7]
+ pxor @y[0], @y[1]
+
+ pxor @t[0], @y[3]
+ pshufd \$0x93, @t[0], @t[0]
+ pxor @t[1], @y[2]
+ pxor @t[1], @y[4]
+ pxor @t[2], @y[2]
+ pshufd \$0x93, @t[1], @t[1]
+ pxor @t[2], @y[3]
+ pxor @t[2], @y[5]
+ pxor @t[7], @y[2]
+ pshufd \$0x93, @t[2], @t[2]
+ pxor @t[3], @y[3]
+ pxor @t[3], @y[6]
+ pxor @t[3], @y[4]
+ pshufd \$0x93, @t[3], @t[3]
+ pxor @t[4], @y[7]
+ pxor @t[4], @y[5]
+ pxor @t[7], @y[7]
+ pxor @t[5], @y[3]
+ pxor @t[4], @y[4]
+ pxor @t[5], @t[7] # clobber t[7] even more
+
+ pxor @t[7], @y[5]
+ pshufd \$0x93, @t[4], @t[4]
+ pxor @t[7], @y[6]
+ pxor @t[7], @y[4]
+
+ pxor @t[5], @t[7]
+ pshufd \$0x93, @t[5], @t[5]
+ pxor @t[6], @t[7] # restore t[7]
+
+ # multiplication by 0x0d
+ pxor @y[7], @y[4]
+ pxor @t[4], @y[7]
+ pshufd \$0x93, @t[6], @t[6]
+ pxor @t[0], @y[2]
+ pxor @t[5], @y[7]
+ pxor @t[2], @y[2]
+ pshufd \$0x93, @t[7], @t[7]
+
+ pxor @y[1], @y[3]
+ pxor @t[1], @y[1]
+ pxor @t[0], @y[0]
+ pxor @t[0], @y[3]
+ pxor @t[5], @y[1]
+ pxor @t[5], @y[0]
+ pxor @t[7], @y[1]
+ pshufd \$0x93, @t[0], @t[0]
+ pxor @t[6], @y[0]
+ pxor @y[1], @y[3]
+ pxor @t[1], @y[4]
+ pshufd \$0x93, @t[1], @t[1]
+
+ pxor @t[7], @y[7]
+ pxor @t[2], @y[4]
+ pxor @t[2], @y[5]
+ pshufd \$0x93, @t[2], @t[2]
+ pxor @t[6], @y[2]
+ pxor @t[3], @t[6] # clobber t[6]
+ pxor @y[7], @y[4]
+ pxor @t[6], @y[3]
+
+ pxor @t[6], @y[6]
+ pxor @t[5], @y[5]
+ pxor @t[4], @y[6]
+ pshufd \$0x93, @t[4], @t[4]
+ pxor @t[6], @y[5]
+ pxor @t[7], @y[6]
+ pxor @t[3], @t[6] # restore t[6]
+
+ pshufd \$0x93, @t[5], @t[5]
+ pshufd \$0x93, @t[6], @t[6]
+ pshufd \$0x93, @t[7], @t[7]
+ pshufd \$0x93, @t[3], @t[3]
+
+ # multiplication by 0x09
+ pxor @y[1], @y[4]
+ pxor @y[1], @t[1] # t[1]=y[1]
+ pxor @t[5], @t[0] # clobber t[0]
+ pxor @t[5], @t[1]
+ pxor @t[0], @y[3]
+ pxor @y[0], @t[0] # t[0]=y[0]
+ pxor @t[6], @t[1]
+ pxor @t[7], @t[6] # clobber t[6]
+ pxor @t[1], @y[4]
+ pxor @t[4], @y[7]
+ pxor @y[4], @t[4] # t[4]=y[4]
+ pxor @t[3], @y[6]
+ pxor @y[3], @t[3] # t[3]=y[3]
+ pxor @t[2], @y[5]
+ pxor @y[2], @t[2] # t[2]=y[2]
+ pxor @t[7], @t[3]
+ pxor @y[5], @t[5] # t[5]=y[5]
+ pxor @t[6], @t[2]
+ pxor @t[6], @t[5]
+ pxor @y[6], @t[6] # t[6]=y[6]
+ pxor @y[7], @t[7] # t[7]=y[7]
+
+ movdqa @t[0],@XMM[0]
+ movdqa @t[1],@XMM[1]
+ movdqa @t[2],@XMM[2]
+ movdqa @t[3],@XMM[3]
+ movdqa @t[4],@XMM[4]
+ movdqa @t[5],@XMM[5]
+ movdqa @t[6],@XMM[6]
+ movdqa @t[7],@XMM[7]
+___
+}
+
+sub InvMixColumns {
+my @x=@_[0..7];
+my @t=@_[8..15];
+
+# Thanks to Jussi Kivilinna for providing pointer to
+#
+# | 0e 0b 0d 09 | | 02 03 01 01 | | 05 00 04 00 |
+# | 09 0e 0b 0d | = | 01 02 03 01 | x | 00 05 00 04 |
+# | 0d 09 0e 0b | | 01 01 02 03 | | 04 00 05 00 |
+# | 0b 0d 09 0e | | 03 01 01 02 | | 00 04 00 05 |
+
+$code.=<<___;
+ # multiplication by 0x05-0x00-0x04-0x00
+ pshufd \$0x4E, @x[0], @t[0]
+ pshufd \$0x4E, @x[6], @t[6]
+ pxor @x[0], @t[0]
+ pshufd \$0x4E, @x[7], @t[7]
+ pxor @x[6], @t[6]
+ pshufd \$0x4E, @x[1], @t[1]
+ pxor @x[7], @t[7]
+ pshufd \$0x4E, @x[2], @t[2]
+ pxor @x[1], @t[1]
+ pshufd \$0x4E, @x[3], @t[3]
+ pxor @x[2], @t[2]
+ pxor @t[6], @x[0]
+ pxor @t[6], @x[1]
+ pshufd \$0x4E, @x[4], @t[4]
+ pxor @x[3], @t[3]
+ pxor @t[0], @x[2]
+ pxor @t[1], @x[3]
+ pshufd \$0x4E, @x[5], @t[5]
+ pxor @x[4], @t[4]
+ pxor @t[7], @x[1]
+ pxor @t[2], @x[4]
+ pxor @x[5], @t[5]
+
+ pxor @t[7], @x[2]
+ pxor @t[6], @x[3]
+ pxor @t[6], @x[4]
+ pxor @t[3], @x[5]
+ pxor @t[4], @x[6]
+ pxor @t[7], @x[4]
+ pxor @t[7], @x[5]
+ pxor @t[5], @x[7]
+___
+ &MixColumns (@x,@t,1); # flipped 2<->3 and 4<->6
+}
+
+sub aesenc { # not used
+my @b=@_[0..7];
+my @t=@_[8..15];
+$code.=<<___;
+ movdqa 0x30($const),@t[0] # .LSR
+___
+ &ShiftRows (@b,@t[0]);
+ &Sbox (@b,@t);
+ &MixColumns (@b[0,1,4,6,3,7,2,5],@t);
+}
+
+sub aesenclast { # not used
+my @b=@_[0..7];
+my @t=@_[8..15];
+$code.=<<___;
+ movdqa 0x40($const),@t[0] # .LSRM0
+___
+ &ShiftRows (@b,@t[0]);
+ &Sbox (@b,@t);
+$code.=<<___
+ pxor 0x00($key),@b[0]
+ pxor 0x10($key),@b[1]
+ pxor 0x20($key),@b[4]
+ pxor 0x30($key),@b[6]
+ pxor 0x40($key),@b[3]
+ pxor 0x50($key),@b[7]
+ pxor 0x60($key),@b[2]
+ pxor 0x70($key),@b[5]
+___
+}
+
+sub swapmove {
+my ($a,$b,$n,$mask,$t)=@_;
+$code.=<<___;
+ movdqa $b,$t
+ psrlq \$$n,$b
+ pxor $a,$b
+ pand $mask,$b
+ pxor $b,$a
+ psllq \$$n,$b
+ pxor $t,$b
+___
+}
+sub swapmove2x {
+my ($a0,$b0,$a1,$b1,$n,$mask,$t0,$t1)=@_;
+$code.=<<___;
+ movdqa $b0,$t0
+ psrlq \$$n,$b0
+ movdqa $b1,$t1
+ psrlq \$$n,$b1
+ pxor $a0,$b0
+ pxor $a1,$b1
+ pand $mask,$b0
+ pand $mask,$b1
+ pxor $b0,$a0
+ psllq \$$n,$b0
+ pxor $b1,$a1
+ psllq \$$n,$b1
+ pxor $t0,$b0
+ pxor $t1,$b1
+___
+}
+
+sub bitslice {
+my @x=reverse(@_[0..7]);
+my ($t0,$t1,$t2,$t3)=@_[8..11];
+$code.=<<___;
+ movdqa 0x00($const),$t0 # .LBS0
+ movdqa 0x10($const),$t1 # .LBS1
+___
+ &swapmove2x(@x[0,1,2,3],1,$t0,$t2,$t3);
+ &swapmove2x(@x[4,5,6,7],1,$t0,$t2,$t3);
+$code.=<<___;
+ movdqa 0x20($const),$t0 # .LBS2
+___
+ &swapmove2x(@x[0,2,1,3],2,$t1,$t2,$t3);
+ &swapmove2x(@x[4,6,5,7],2,$t1,$t2,$t3);
+
+ &swapmove2x(@x[0,4,1,5],4,$t0,$t2,$t3);
+ &swapmove2x(@x[2,6,3,7],4,$t0,$t2,$t3);
+}
+
+$code.=<<___;
+.text
+
+.extern asm_AES_encrypt
+.extern asm_AES_decrypt
+
+.type _bsaes_encrypt8,\@abi-omnipotent
+.align 64
+_bsaes_encrypt8:
+ lea .LBS0(%rip), $const # constants table
+
+ movdqa ($key), @XMM[9] # round 0 key
+ lea 0x10($key), $key
+ movdqa 0x50($const), @XMM[8] # .LM0SR
+ pxor @XMM[9], @XMM[0] # xor with round0 key
+ pxor @XMM[9], @XMM[1]
+ pxor @XMM[9], @XMM[2]
+ pxor @XMM[9], @XMM[3]
+ pshufb @XMM[8], @XMM[0]
+ pshufb @XMM[8], @XMM[1]
+ pxor @XMM[9], @XMM[4]
+ pxor @XMM[9], @XMM[5]
+ pshufb @XMM[8], @XMM[2]
+ pshufb @XMM[8], @XMM[3]
+ pxor @XMM[9], @XMM[6]
+ pxor @XMM[9], @XMM[7]
+ pshufb @XMM[8], @XMM[4]
+ pshufb @XMM[8], @XMM[5]
+ pshufb @XMM[8], @XMM[6]
+ pshufb @XMM[8], @XMM[7]
+_bsaes_encrypt8_bitslice:
+___
+ &bitslice (@XMM[0..7, 8..11]);
+$code.=<<___;
+ dec $rounds
+ jmp .Lenc_sbox
+.align 16
+.Lenc_loop:
+___
+ &ShiftRows (@XMM[0..7, 8]);
+$code.=".Lenc_sbox:\n";
+ &Sbox (@XMM[0..7, 8..15]);
+$code.=<<___;
+ dec $rounds
+ jl .Lenc_done
+___
+ &MixColumns (@XMM[0,1,4,6,3,7,2,5, 8..15]);
+$code.=<<___;
+ movdqa 0x30($const), @XMM[8] # .LSR
+ jnz .Lenc_loop
+ movdqa 0x40($const), @XMM[8] # .LSRM0
+ jmp .Lenc_loop
+.align 16
+.Lenc_done:
+___
+ # output in lsb > [t0, t1, t4, t6, t3, t7, t2, t5] < msb
+ &bitslice (@XMM[0,1,4,6,3,7,2,5, 8..11]);
+$code.=<<___;
+ movdqa ($key), @XMM[8] # last round key
+ pxor @XMM[8], @XMM[4]
+ pxor @XMM[8], @XMM[6]
+ pxor @XMM[8], @XMM[3]
+ pxor @XMM[8], @XMM[7]
+ pxor @XMM[8], @XMM[2]
+ pxor @XMM[8], @XMM[5]
+ pxor @XMM[8], @XMM[0]
+ pxor @XMM[8], @XMM[1]
+ ret
+.size _bsaes_encrypt8,.-_bsaes_encrypt8
+
+.type _bsaes_decrypt8,\@abi-omnipotent
+.align 64
+_bsaes_decrypt8:
+ lea .LBS0(%rip), $const # constants table
+
+ movdqa ($key), @XMM[9] # round 0 key
+ lea 0x10($key), $key
+ movdqa -0x30($const), @XMM[8] # .LM0ISR
+ pxor @XMM[9], @XMM[0] # xor with round0 key
+ pxor @XMM[9], @XMM[1]
+ pxor @XMM[9], @XMM[2]
+ pxor @XMM[9], @XMM[3]
+ pshufb @XMM[8], @XMM[0]
+ pshufb @XMM[8], @XMM[1]
+ pxor @XMM[9], @XMM[4]
+ pxor @XMM[9], @XMM[5]
+ pshufb @XMM[8], @XMM[2]
+ pshufb @XMM[8], @XMM[3]
+ pxor @XMM[9], @XMM[6]
+ pxor @XMM[9], @XMM[7]
+ pshufb @XMM[8], @XMM[4]
+ pshufb @XMM[8], @XMM[5]
+ pshufb @XMM[8], @XMM[6]
+ pshufb @XMM[8], @XMM[7]
+___
+ &bitslice (@XMM[0..7, 8..11]);
+$code.=<<___;
+ dec $rounds
+ jmp .Ldec_sbox
+.align 16
+.Ldec_loop:
+___
+ &ShiftRows (@XMM[0..7, 8]);
+$code.=".Ldec_sbox:\n";
+ &InvSbox (@XMM[0..7, 8..15]);
+$code.=<<___;
+ dec $rounds
+ jl .Ldec_done
+___
+ &InvMixColumns (@XMM[0,1,6,4,2,7,3,5, 8..15]);
+$code.=<<___;
+ movdqa -0x10($const), @XMM[8] # .LISR
+ jnz .Ldec_loop
+ movdqa -0x20($const), @XMM[8] # .LISRM0
+ jmp .Ldec_loop
+.align 16
+.Ldec_done:
+___
+ &bitslice (@XMM[0,1,6,4,2,7,3,5, 8..11]);
+$code.=<<___;
+ movdqa ($key), @XMM[8] # last round key
+ pxor @XMM[8], @XMM[6]
+ pxor @XMM[8], @XMM[4]
+ pxor @XMM[8], @XMM[2]
+ pxor @XMM[8], @XMM[7]
+ pxor @XMM[8], @XMM[3]
+ pxor @XMM[8], @XMM[5]
+ pxor @XMM[8], @XMM[0]
+ pxor @XMM[8], @XMM[1]
+ ret
+.size _bsaes_decrypt8,.-_bsaes_decrypt8
+___
+}
+{
+my ($out,$inp,$rounds,$const)=("%rax","%rcx","%r10d","%r11");
+
+sub bitslice_key {
+my @x=reverse(@_[0..7]);
+my ($bs0,$bs1,$bs2,$t2,$t3)=@_[8..12];
+
+ &swapmove (@x[0,1],1,$bs0,$t2,$t3);
+$code.=<<___;
+ #&swapmove(@x[2,3],1,$t0,$t2,$t3);
+ movdqa @x[0], @x[2]
+ movdqa @x[1], @x[3]
+___
+ #&swapmove2x(@x[4,5,6,7],1,$t0,$t2,$t3);
+
+ &swapmove2x (@x[0,2,1,3],2,$bs1,$t2,$t3);
+$code.=<<___;
+ #&swapmove2x(@x[4,6,5,7],2,$t1,$t2,$t3);
+ movdqa @x[0], @x[4]
+ movdqa @x[2], @x[6]
+ movdqa @x[1], @x[5]
+ movdqa @x[3], @x[7]
+___
+ &swapmove2x (@x[0,4,1,5],4,$bs2,$t2,$t3);
+ &swapmove2x (@x[2,6,3,7],4,$bs2,$t2,$t3);
+}
+
+$code.=<<___;
+.type _bsaes_key_convert,\@abi-omnipotent
+.align 16
+_bsaes_key_convert:
+ lea .Lmasks(%rip), $const
+ movdqu ($inp), %xmm7 # load round 0 key
+ lea 0x10($inp), $inp
+ movdqa 0x00($const), %xmm0 # 0x01...
+ movdqa 0x10($const), %xmm1 # 0x02...
+ movdqa 0x20($const), %xmm2 # 0x04...
+ movdqa 0x30($const), %xmm3 # 0x08...
+ movdqa 0x40($const), %xmm4 # .LM0
+ pcmpeqd %xmm5, %xmm5 # .LNOT
+
+ movdqu ($inp), %xmm6 # load round 1 key
+ movdqa %xmm7, ($out) # save round 0 key
+ lea 0x10($out), $out
+ dec $rounds
+ jmp .Lkey_loop
+.align 16
+.Lkey_loop:
+ pshufb %xmm4, %xmm6 # .LM0
+
+ movdqa %xmm0, %xmm8
+ movdqa %xmm1, %xmm9
+
+ pand %xmm6, %xmm8
+ pand %xmm6, %xmm9
+ movdqa %xmm2, %xmm10
+ pcmpeqb %xmm0, %xmm8
+ psllq \$4, %xmm0 # 0x10...
+ movdqa %xmm3, %xmm11
+ pcmpeqb %xmm1, %xmm9
+ psllq \$4, %xmm1 # 0x20...
+
+ pand %xmm6, %xmm10
+ pand %xmm6, %xmm11
+ movdqa %xmm0, %xmm12
+ pcmpeqb %xmm2, %xmm10
+ psllq \$4, %xmm2 # 0x40...
+ movdqa %xmm1, %xmm13
+ pcmpeqb %xmm3, %xmm11
+ psllq \$4, %xmm3 # 0x80...
+
+ movdqa %xmm2, %xmm14
+ movdqa %xmm3, %xmm15
+ pxor %xmm5, %xmm8 # "pnot"
+ pxor %xmm5, %xmm9
+
+ pand %xmm6, %xmm12
+ pand %xmm6, %xmm13
+ movdqa %xmm8, 0x00($out) # write bit-sliced round key
+ pcmpeqb %xmm0, %xmm12
+ psrlq \$4, %xmm0 # 0x01...
+ movdqa %xmm9, 0x10($out)
+ pcmpeqb %xmm1, %xmm13
+ psrlq \$4, %xmm1 # 0x02...
+ lea 0x10($inp), $inp
+
+ pand %xmm6, %xmm14
+ pand %xmm6, %xmm15
+ movdqa %xmm10, 0x20($out)
+ pcmpeqb %xmm2, %xmm14
+ psrlq \$4, %xmm2 # 0x04...
+ movdqa %xmm11, 0x30($out)
+ pcmpeqb %xmm3, %xmm15
+ psrlq \$4, %xmm3 # 0x08...
+ movdqu ($inp), %xmm6 # load next round key
+
+ pxor %xmm5, %xmm13 # "pnot"
+ pxor %xmm5, %xmm14
+ movdqa %xmm12, 0x40($out)
+ movdqa %xmm13, 0x50($out)
+ movdqa %xmm14, 0x60($out)
+ movdqa %xmm15, 0x70($out)
+ lea 0x80($out),$out
+ dec $rounds
+ jnz .Lkey_loop
+
+ movdqa 0x50($const), %xmm7 # .L63
+ #movdqa %xmm6, ($out) # don't save last round key
+ ret
+.size _bsaes_key_convert,.-_bsaes_key_convert
+___
+}
+
+if (0 && !$win64) { # following four functions are unsupported interface
+ # used for benchmarking...
+$code.=<<___;
+.globl bsaes_enc_key_convert
+.type bsaes_enc_key_convert,\@function,2
+.align 16
+bsaes_enc_key_convert:
+ mov 240($inp),%r10d # pass rounds
+ mov $inp,%rcx # pass key
+ mov $out,%rax # pass key schedule
+ call _bsaes_key_convert
+ pxor %xmm6,%xmm7 # fix up last round key
+ movdqa %xmm7,(%rax) # save last round key
+ ret
+.size bsaes_enc_key_convert,.-bsaes_enc_key_convert
+
+.globl bsaes_encrypt_128
+.type bsaes_encrypt_128,\@function,4
+.align 16
+bsaes_encrypt_128:
+.Lenc128_loop:
+ movdqu 0x00($inp), @XMM[0] # load input
+ movdqu 0x10($inp), @XMM[1]
+ movdqu 0x20($inp), @XMM[2]
+ movdqu 0x30($inp), @XMM[3]
+ movdqu 0x40($inp), @XMM[4]
+ movdqu 0x50($inp), @XMM[5]
+ movdqu 0x60($inp), @XMM[6]
+ movdqu 0x70($inp), @XMM[7]
+ mov $key, %rax # pass the $key
+ lea 0x80($inp), $inp
+ mov \$10,%r10d
+
+ call _bsaes_encrypt8
+
+ movdqu @XMM[0], 0x00($out) # write output
+ movdqu @XMM[1], 0x10($out)
+ movdqu @XMM[4], 0x20($out)
+ movdqu @XMM[6], 0x30($out)
+ movdqu @XMM[3], 0x40($out)
+ movdqu @XMM[7], 0x50($out)
+ movdqu @XMM[2], 0x60($out)
+ movdqu @XMM[5], 0x70($out)
+ lea 0x80($out), $out
+ sub \$0x80,$len
+ ja .Lenc128_loop
+ ret
+.size bsaes_encrypt_128,.-bsaes_encrypt_128
+
+.globl bsaes_dec_key_convert
+.type bsaes_dec_key_convert,\@function,2
+.align 16
+bsaes_dec_key_convert:
+ mov 240($inp),%r10d # pass rounds
+ mov $inp,%rcx # pass key
+ mov $out,%rax # pass key schedule
+ call _bsaes_key_convert
+ pxor ($out),%xmm7 # fix up round 0 key
+ movdqa %xmm6,(%rax) # save last round key
+ movdqa %xmm7,($out)
+ ret
+.size bsaes_dec_key_convert,.-bsaes_dec_key_convert
+
+.globl bsaes_decrypt_128
+.type bsaes_decrypt_128,\@function,4
+.align 16
+bsaes_decrypt_128:
+.Ldec128_loop:
+ movdqu 0x00($inp), @XMM[0] # load input
+ movdqu 0x10($inp), @XMM[1]
+ movdqu 0x20($inp), @XMM[2]
+ movdqu 0x30($inp), @XMM[3]
+ movdqu 0x40($inp), @XMM[4]
+ movdqu 0x50($inp), @XMM[5]
+ movdqu 0x60($inp), @XMM[6]
+ movdqu 0x70($inp), @XMM[7]
+ mov $key, %rax # pass the $key
+ lea 0x80($inp), $inp
+ mov \$10,%r10d
+
+ call _bsaes_decrypt8
+
+ movdqu @XMM[0], 0x00($out) # write output
+ movdqu @XMM[1], 0x10($out)
+ movdqu @XMM[6], 0x20($out)
+ movdqu @XMM[4], 0x30($out)
+ movdqu @XMM[2], 0x40($out)
+ movdqu @XMM[7], 0x50($out)
+ movdqu @XMM[3], 0x60($out)
+ movdqu @XMM[5], 0x70($out)
+ lea 0x80($out), $out
+ sub \$0x80,$len
+ ja .Ldec128_loop
+ ret
+.size bsaes_decrypt_128,.-bsaes_decrypt_128
+___
+}
+{
+######################################################################
+#
+# OpenSSL interface
+#
+my ($arg1,$arg2,$arg3,$arg4,$arg5,$arg6)=$win64 ? ("%rcx","%rdx","%r8","%r9","%r10","%r11d")
+ : ("%rdi","%rsi","%rdx","%rcx","%r8","%r9d");
+my ($inp,$out,$len,$key)=("%r12","%r13","%r14","%r15");
+
+if ($ecb) {
+$code.=<<___;
+.globl bsaes_ecb_encrypt_blocks
+.type bsaes_ecb_encrypt_blocks,\@abi-omnipotent
+.align 16
+bsaes_ecb_encrypt_blocks:
+ mov %rsp, %rax
+.Lecb_enc_prologue:
+ push %rbp
+ push %rbx
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+ lea -0x48(%rsp),%rsp
+___
+$code.=<<___ if ($win64);
+ lea -0xa0(%rsp), %rsp
+ movaps %xmm6, 0x40(%rsp)
+ movaps %xmm7, 0x50(%rsp)
+ movaps %xmm8, 0x60(%rsp)
+ movaps %xmm9, 0x70(%rsp)
+ movaps %xmm10, 0x80(%rsp)
+ movaps %xmm11, 0x90(%rsp)
+ movaps %xmm12, 0xa0(%rsp)
+ movaps %xmm13, 0xb0(%rsp)
+ movaps %xmm14, 0xc0(%rsp)
+ movaps %xmm15, 0xd0(%rsp)
+.Lecb_enc_body:
+___
+$code.=<<___;
+ mov %rsp,%rbp # backup %rsp
+ mov 240($arg4),%eax # rounds
+ mov $arg1,$inp # backup arguments
+ mov $arg2,$out
+ mov $arg3,$len
+ mov $arg4,$key
+ cmp \$8,$arg3
+ jb .Lecb_enc_short
+
+ mov %eax,%ebx # backup rounds
+ shl \$7,%rax # 128 bytes per inner round key
+ sub \$`128-32`,%rax # size of bit-sliced key schedule
+ sub %rax,%rsp
+ mov %rsp,%rax # pass key schedule
+ mov $key,%rcx # pass key
+ mov %ebx,%r10d # pass rounds
+ call _bsaes_key_convert
+ pxor %xmm6,%xmm7 # fix up last round key
+ movdqa %xmm7,(%rax) # save last round key
+
+ sub \$8,$len
+.Lecb_enc_loop:
+ movdqu 0x00($inp), @XMM[0] # load input
+ movdqu 0x10($inp), @XMM[1]
+ movdqu 0x20($inp), @XMM[2]
+ movdqu 0x30($inp), @XMM[3]
+ movdqu 0x40($inp), @XMM[4]
+ movdqu 0x50($inp), @XMM[5]
+ mov %rsp, %rax # pass key schedule
+ movdqu 0x60($inp), @XMM[6]
+ mov %ebx,%r10d # pass rounds
+ movdqu 0x70($inp), @XMM[7]
+ lea 0x80($inp), $inp
+
+ call _bsaes_encrypt8
+
+ movdqu @XMM[0], 0x00($out) # write output
+ movdqu @XMM[1], 0x10($out)
+ movdqu @XMM[4], 0x20($out)
+ movdqu @XMM[6], 0x30($out)
+ movdqu @XMM[3], 0x40($out)
+ movdqu @XMM[7], 0x50($out)
+ movdqu @XMM[2], 0x60($out)
+ movdqu @XMM[5], 0x70($out)
+ lea 0x80($out), $out
+ sub \$8,$len
+ jnc .Lecb_enc_loop
+
+ add \$8,$len
+ jz .Lecb_enc_done
+
+ movdqu 0x00($inp), @XMM[0] # load input
+ mov %rsp, %rax # pass key schedule
+ mov %ebx,%r10d # pass rounds
+ cmp \$2,$len
+ jb .Lecb_enc_one
+ movdqu 0x10($inp), @XMM[1]
+ je .Lecb_enc_two
+ movdqu 0x20($inp), @XMM[2]
+ cmp \$4,$len
+ jb .Lecb_enc_three
+ movdqu 0x30($inp), @XMM[3]
+ je .Lecb_enc_four
+ movdqu 0x40($inp), @XMM[4]
+ cmp \$6,$len
+ jb .Lecb_enc_five
+ movdqu 0x50($inp), @XMM[5]
+ je .Lecb_enc_six
+ movdqu 0x60($inp), @XMM[6]
+ call _bsaes_encrypt8
+ movdqu @XMM[0], 0x00($out) # write output
+ movdqu @XMM[1], 0x10($out)
+ movdqu @XMM[4], 0x20($out)
+ movdqu @XMM[6], 0x30($out)
+ movdqu @XMM[3], 0x40($out)
+ movdqu @XMM[7], 0x50($out)
+ movdqu @XMM[2], 0x60($out)
+ jmp .Lecb_enc_done
+.align 16
+.Lecb_enc_six:
+ call _bsaes_encrypt8
+ movdqu @XMM[0], 0x00($out) # write output
+ movdqu @XMM[1], 0x10($out)
+ movdqu @XMM[4], 0x20($out)
+ movdqu @XMM[6], 0x30($out)
+ movdqu @XMM[3], 0x40($out)
+ movdqu @XMM[7], 0x50($out)
+ jmp .Lecb_enc_done
+.align 16
+.Lecb_enc_five:
+ call _bsaes_encrypt8
+ movdqu @XMM[0], 0x00($out) # write output
+ movdqu @XMM[1], 0x10($out)
+ movdqu @XMM[4], 0x20($out)
+ movdqu @XMM[6], 0x30($out)
+ movdqu @XMM[3], 0x40($out)
+ jmp .Lecb_enc_done
+.align 16
+.Lecb_enc_four:
+ call _bsaes_encrypt8
+ movdqu @XMM[0], 0x00($out) # write output
+ movdqu @XMM[1], 0x10($out)
+ movdqu @XMM[4], 0x20($out)
+ movdqu @XMM[6], 0x30($out)
+ jmp .Lecb_enc_done
+.align 16
+.Lecb_enc_three:
+ call _bsaes_encrypt8
+ movdqu @XMM[0], 0x00($out) # write output
+ movdqu @XMM[1], 0x10($out)
+ movdqu @XMM[4], 0x20($out)
+ jmp .Lecb_enc_done
+.align 16
+.Lecb_enc_two:
+ call _bsaes_encrypt8
+ movdqu @XMM[0], 0x00($out) # write output
+ movdqu @XMM[1], 0x10($out)
+ jmp .Lecb_enc_done
+.align 16
+.Lecb_enc_one:
+ call _bsaes_encrypt8
+ movdqu @XMM[0], 0x00($out) # write output
+ jmp .Lecb_enc_done
+.align 16
+.Lecb_enc_short:
+ lea ($inp), $arg1
+ lea ($out), $arg2
+ lea ($key), $arg3
+ call asm_AES_encrypt
+ lea 16($inp), $inp
+ lea 16($out), $out
+ dec $len
+ jnz .Lecb_enc_short
+
+.Lecb_enc_done:
+ lea (%rsp),%rax
+ pxor %xmm0, %xmm0
+.Lecb_enc_bzero: # wipe key schedule [if any]
+ movdqa %xmm0, 0x00(%rax)
+ movdqa %xmm0, 0x10(%rax)
+ lea 0x20(%rax), %rax
+ cmp %rax, %rbp
+ jb .Lecb_enc_bzero
+
+ lea (%rbp),%rsp # restore %rsp
+___
+$code.=<<___ if ($win64);
+ movaps 0x40(%rbp), %xmm6
+ movaps 0x50(%rbp), %xmm7
+ movaps 0x60(%rbp), %xmm8
+ movaps 0x70(%rbp), %xmm9
+ movaps 0x80(%rbp), %xmm10
+ movaps 0x90(%rbp), %xmm11
+ movaps 0xa0(%rbp), %xmm12
+ movaps 0xb0(%rbp), %xmm13
+ movaps 0xc0(%rbp), %xmm14
+ movaps 0xd0(%rbp), %xmm15
+ lea 0xa0(%rbp), %rsp
+___
+$code.=<<___;
+ mov 0x48(%rsp), %r15
+ mov 0x50(%rsp), %r14
+ mov 0x58(%rsp), %r13
+ mov 0x60(%rsp), %r12
+ mov 0x68(%rsp), %rbx
+ mov 0x70(%rsp), %rax
+ lea 0x78(%rsp), %rsp
+ mov %rax, %rbp
+.Lecb_enc_epilogue:
+ ret
+.size bsaes_ecb_encrypt_blocks,.-bsaes_ecb_encrypt_blocks
+
+.globl bsaes_ecb_decrypt_blocks
+.type bsaes_ecb_decrypt_blocks,\@abi-omnipotent
+.align 16
+bsaes_ecb_decrypt_blocks:
+ mov %rsp, %rax
+.Lecb_dec_prologue:
+ push %rbp
+ push %rbx
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+ lea -0x48(%rsp),%rsp
+___
+$code.=<<___ if ($win64);
+ lea -0xa0(%rsp), %rsp
+ movaps %xmm6, 0x40(%rsp)
+ movaps %xmm7, 0x50(%rsp)
+ movaps %xmm8, 0x60(%rsp)
+ movaps %xmm9, 0x70(%rsp)
+ movaps %xmm10, 0x80(%rsp)
+ movaps %xmm11, 0x90(%rsp)
+ movaps %xmm12, 0xa0(%rsp)
+ movaps %xmm13, 0xb0(%rsp)
+ movaps %xmm14, 0xc0(%rsp)
+ movaps %xmm15, 0xd0(%rsp)
+.Lecb_dec_body:
+___
+$code.=<<___;
+ mov %rsp,%rbp # backup %rsp
+ mov 240($arg4),%eax # rounds
+ mov $arg1,$inp # backup arguments
+ mov $arg2,$out
+ mov $arg3,$len
+ mov $arg4,$key
+ cmp \$8,$arg3
+ jb .Lecb_dec_short
+
+ mov %eax,%ebx # backup rounds
+ shl \$7,%rax # 128 bytes per inner round key
+ sub \$`128-32`,%rax # size of bit-sliced key schedule
+ sub %rax,%rsp
+ mov %rsp,%rax # pass key schedule
+ mov $key,%rcx # pass key
+ mov %ebx,%r10d # pass rounds
+ call _bsaes_key_convert
+ pxor (%rsp),%xmm7 # fix up 0 round key
+ movdqa %xmm6,(%rax) # save last round key
+ movdqa %xmm7,(%rsp)
+
+ sub \$8,$len
+.Lecb_dec_loop:
+ movdqu 0x00($inp), @XMM[0] # load input
+ movdqu 0x10($inp), @XMM[1]
+ movdqu 0x20($inp), @XMM[2]
+ movdqu 0x30($inp), @XMM[3]
+ movdqu 0x40($inp), @XMM[4]
+ movdqu 0x50($inp), @XMM[5]
+ mov %rsp, %rax # pass key schedule
+ movdqu 0x60($inp), @XMM[6]
+ mov %ebx,%r10d # pass rounds
+ movdqu 0x70($inp), @XMM[7]
+ lea 0x80($inp), $inp
+
+ call _bsaes_decrypt8
+
+ movdqu @XMM[0], 0x00($out) # write output
+ movdqu @XMM[1], 0x10($out)
+ movdqu @XMM[6], 0x20($out)
+ movdqu @XMM[4], 0x30($out)
+ movdqu @XMM[2], 0x40($out)
+ movdqu @XMM[7], 0x50($out)
+ movdqu @XMM[3], 0x60($out)
+ movdqu @XMM[5], 0x70($out)
+ lea 0x80($out), $out
+ sub \$8,$len
+ jnc .Lecb_dec_loop
+
+ add \$8,$len
+ jz .Lecb_dec_done
+
+ movdqu 0x00($inp), @XMM[0] # load input
+ mov %rsp, %rax # pass key schedule
+ mov %ebx,%r10d # pass rounds
+ cmp \$2,$len
+ jb .Lecb_dec_one
+ movdqu 0x10($inp), @XMM[1]
+ je .Lecb_dec_two
+ movdqu 0x20($inp), @XMM[2]
+ cmp \$4,$len
+ jb .Lecb_dec_three
+ movdqu 0x30($inp), @XMM[3]
+ je .Lecb_dec_four
+ movdqu 0x40($inp), @XMM[4]
+ cmp \$6,$len
+ jb .Lecb_dec_five
+ movdqu 0x50($inp), @XMM[5]
+ je .Lecb_dec_six
+ movdqu 0x60($inp), @XMM[6]
+ call _bsaes_decrypt8
+ movdqu @XMM[0], 0x00($out) # write output
+ movdqu @XMM[1], 0x10($out)
+ movdqu @XMM[6], 0x20($out)
+ movdqu @XMM[4], 0x30($out)
+ movdqu @XMM[2], 0x40($out)
+ movdqu @XMM[7], 0x50($out)
+ movdqu @XMM[3], 0x60($out)
+ jmp .Lecb_dec_done
+.align 16
+.Lecb_dec_six:
+ call _bsaes_decrypt8
+ movdqu @XMM[0], 0x00($out) # write output
+ movdqu @XMM[1], 0x10($out)
+ movdqu @XMM[6], 0x20($out)
+ movdqu @XMM[4], 0x30($out)
+ movdqu @XMM[2], 0x40($out)
+ movdqu @XMM[7], 0x50($out)
+ jmp .Lecb_dec_done
+.align 16
+.Lecb_dec_five:
+ call _bsaes_decrypt8
+ movdqu @XMM[0], 0x00($out) # write output
+ movdqu @XMM[1], 0x10($out)
+ movdqu @XMM[6], 0x20($out)
+ movdqu @XMM[4], 0x30($out)
+ movdqu @XMM[2], 0x40($out)
+ jmp .Lecb_dec_done
+.align 16
+.Lecb_dec_four:
+ call _bsaes_decrypt8
+ movdqu @XMM[0], 0x00($out) # write output
+ movdqu @XMM[1], 0x10($out)
+ movdqu @XMM[6], 0x20($out)
+ movdqu @XMM[4], 0x30($out)
+ jmp .Lecb_dec_done
+.align 16
+.Lecb_dec_three:
+ call _bsaes_decrypt8
+ movdqu @XMM[0], 0x00($out) # write output
+ movdqu @XMM[1], 0x10($out)
+ movdqu @XMM[6], 0x20($out)
+ jmp .Lecb_dec_done
+.align 16
+.Lecb_dec_two:
+ call _bsaes_decrypt8
+ movdqu @XMM[0], 0x00($out) # write output
+ movdqu @XMM[1], 0x10($out)
+ jmp .Lecb_dec_done
+.align 16
+.Lecb_dec_one:
+ call _bsaes_decrypt8
+ movdqu @XMM[0], 0x00($out) # write output
+ jmp .Lecb_dec_done
+.align 16
+.Lecb_dec_short:
+ lea ($inp), $arg1
+ lea ($out), $arg2
+ lea ($key), $arg3
+ call asm_AES_decrypt
+ lea 16($inp), $inp
+ lea 16($out), $out
+ dec $len
+ jnz .Lecb_dec_short
+
+.Lecb_dec_done:
+ lea (%rsp),%rax
+ pxor %xmm0, %xmm0
+.Lecb_dec_bzero: # wipe key schedule [if any]
+ movdqa %xmm0, 0x00(%rax)
+ movdqa %xmm0, 0x10(%rax)
+ lea 0x20(%rax), %rax
+ cmp %rax, %rbp
+ jb .Lecb_dec_bzero
+
+ lea (%rbp),%rsp # restore %rsp
+___
+$code.=<<___ if ($win64);
+ movaps 0x40(%rbp), %xmm6
+ movaps 0x50(%rbp), %xmm7
+ movaps 0x60(%rbp), %xmm8
+ movaps 0x70(%rbp), %xmm9
+ movaps 0x80(%rbp), %xmm10
+ movaps 0x90(%rbp), %xmm11
+ movaps 0xa0(%rbp), %xmm12
+ movaps 0xb0(%rbp), %xmm13
+ movaps 0xc0(%rbp), %xmm14
+ movaps 0xd0(%rbp), %xmm15
+ lea 0xa0(%rbp), %rsp
+___
+$code.=<<___;
+ mov 0x48(%rsp), %r15
+ mov 0x50(%rsp), %r14
+ mov 0x58(%rsp), %r13
+ mov 0x60(%rsp), %r12
+ mov 0x68(%rsp), %rbx
+ mov 0x70(%rsp), %rax
+ lea 0x78(%rsp), %rsp
+ mov %rax, %rbp
+.Lecb_dec_epilogue:
+ ret
+.size bsaes_ecb_decrypt_blocks,.-bsaes_ecb_decrypt_blocks
+___
+}
+$code.=<<___;
+.extern asm_AES_cbc_encrypt
+.globl bsaes_cbc_encrypt
+.type bsaes_cbc_encrypt,\@abi-omnipotent
+.align 16
+bsaes_cbc_encrypt:
+___
+$code.=<<___ if ($win64);
+ mov 48(%rsp),$arg6 # pull direction flag
+___
+$code.=<<___;
+ cmp \$0,$arg6
+ jne asm_AES_cbc_encrypt
+ cmp \$128,$arg3
+ jb asm_AES_cbc_encrypt
+
+ mov %rsp, %rax
+.Lcbc_dec_prologue:
+ push %rbp
+ push %rbx
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+ lea -0x48(%rsp), %rsp
+___
+$code.=<<___ if ($win64);
+ mov 0xa0(%rsp),$arg5 # pull ivp
+ lea -0xa0(%rsp), %rsp
+ movaps %xmm6, 0x40(%rsp)
+ movaps %xmm7, 0x50(%rsp)
+ movaps %xmm8, 0x60(%rsp)
+ movaps %xmm9, 0x70(%rsp)
+ movaps %xmm10, 0x80(%rsp)
+ movaps %xmm11, 0x90(%rsp)
+ movaps %xmm12, 0xa0(%rsp)
+ movaps %xmm13, 0xb0(%rsp)
+ movaps %xmm14, 0xc0(%rsp)
+ movaps %xmm15, 0xd0(%rsp)
+.Lcbc_dec_body:
+___
+$code.=<<___;
+ mov %rsp, %rbp # backup %rsp
+ mov 240($arg4), %eax # rounds
+ mov $arg1, $inp # backup arguments
+ mov $arg2, $out
+ mov $arg3, $len
+ mov $arg4, $key
+ mov $arg5, %rbx
+ shr \$4, $len # bytes to blocks
+
+ mov %eax, %edx # rounds
+ shl \$7, %rax # 128 bytes per inner round key
+ sub \$`128-32`, %rax # size of bit-sliced key schedule
+ sub %rax, %rsp
+
+ mov %rsp, %rax # pass key schedule
+ mov $key, %rcx # pass key
+ mov %edx, %r10d # pass rounds
+ call _bsaes_key_convert
+ pxor (%rsp),%xmm7 # fix up 0 round key
+ movdqa %xmm6,(%rax) # save last round key
+ movdqa %xmm7,(%rsp)
+
+ movdqu (%rbx), @XMM[15] # load IV
+ sub \$8,$len
+.Lcbc_dec_loop:
+ movdqu 0x00($inp), @XMM[0] # load input
+ movdqu 0x10($inp), @XMM[1]
+ movdqu 0x20($inp), @XMM[2]
+ movdqu 0x30($inp), @XMM[3]
+ movdqu 0x40($inp), @XMM[4]
+ movdqu 0x50($inp), @XMM[5]
+ mov %rsp, %rax # pass key schedule
+ movdqu 0x60($inp), @XMM[6]
+ mov %edx,%r10d # pass rounds
+ movdqu 0x70($inp), @XMM[7]
+ movdqa @XMM[15], 0x20(%rbp) # put aside IV
+
+ call _bsaes_decrypt8
+
+ pxor 0x20(%rbp), @XMM[0] # ^= IV
+ movdqu 0x00($inp), @XMM[8] # re-load input
+ movdqu 0x10($inp), @XMM[9]
+ pxor @XMM[8], @XMM[1]
+ movdqu 0x20($inp), @XMM[10]
+ pxor @XMM[9], @XMM[6]
+ movdqu 0x30($inp), @XMM[11]
+ pxor @XMM[10], @XMM[4]
+ movdqu 0x40($inp), @XMM[12]
+ pxor @XMM[11], @XMM[2]
+ movdqu 0x50($inp), @XMM[13]
+ pxor @XMM[12], @XMM[7]
+ movdqu 0x60($inp), @XMM[14]
+ pxor @XMM[13], @XMM[3]
+ movdqu 0x70($inp), @XMM[15] # IV
+ pxor @XMM[14], @XMM[5]
+ movdqu @XMM[0], 0x00($out) # write output
+ lea 0x80($inp), $inp
+ movdqu @XMM[1], 0x10($out)
+ movdqu @XMM[6], 0x20($out)
+ movdqu @XMM[4], 0x30($out)
+ movdqu @XMM[2], 0x40($out)
+ movdqu @XMM[7], 0x50($out)
+ movdqu @XMM[3], 0x60($out)
+ movdqu @XMM[5], 0x70($out)
+ lea 0x80($out), $out
+ sub \$8,$len
+ jnc .Lcbc_dec_loop
+
+ add \$8,$len
+ jz .Lcbc_dec_done
+
+ movdqu 0x00($inp), @XMM[0] # load input
+ mov %rsp, %rax # pass key schedule
+ mov %edx, %r10d # pass rounds
+ cmp \$2,$len
+ jb .Lcbc_dec_one
+ movdqu 0x10($inp), @XMM[1]
+ je .Lcbc_dec_two
+ movdqu 0x20($inp), @XMM[2]
+ cmp \$4,$len
+ jb .Lcbc_dec_three
+ movdqu 0x30($inp), @XMM[3]
+ je .Lcbc_dec_four
+ movdqu 0x40($inp), @XMM[4]
+ cmp \$6,$len
+ jb .Lcbc_dec_five
+ movdqu 0x50($inp), @XMM[5]
+ je .Lcbc_dec_six
+ movdqu 0x60($inp), @XMM[6]
+ movdqa @XMM[15], 0x20(%rbp) # put aside IV
+ call _bsaes_decrypt8
+ pxor 0x20(%rbp), @XMM[0] # ^= IV
+ movdqu 0x00($inp), @XMM[8] # re-load input
+ movdqu 0x10($inp), @XMM[9]
+ pxor @XMM[8], @XMM[1]
+ movdqu 0x20($inp), @XMM[10]
+ pxor @XMM[9], @XMM[6]
+ movdqu 0x30($inp), @XMM[11]
+ pxor @XMM[10], @XMM[4]
+ movdqu 0x40($inp), @XMM[12]
+ pxor @XMM[11], @XMM[2]
+ movdqu 0x50($inp), @XMM[13]
+ pxor @XMM[12], @XMM[7]
+ movdqu 0x60($inp), @XMM[15] # IV
+ pxor @XMM[13], @XMM[3]
+ movdqu @XMM[0], 0x00($out) # write output
+ movdqu @XMM[1], 0x10($out)
+ movdqu @XMM[6], 0x20($out)
+ movdqu @XMM[4], 0x30($out)
+ movdqu @XMM[2], 0x40($out)
+ movdqu @XMM[7], 0x50($out)
+ movdqu @XMM[3], 0x60($out)
+ jmp .Lcbc_dec_done
+.align 16
+.Lcbc_dec_six:
+ movdqa @XMM[15], 0x20(%rbp) # put aside IV
+ call _bsaes_decrypt8
+ pxor 0x20(%rbp), @XMM[0] # ^= IV
+ movdqu 0x00($inp), @XMM[8] # re-load input
+ movdqu 0x10($inp), @XMM[9]
+ pxor @XMM[8], @XMM[1]
+ movdqu 0x20($inp), @XMM[10]
+ pxor @XMM[9], @XMM[6]
+ movdqu 0x30($inp), @XMM[11]
+ pxor @XMM[10], @XMM[4]
+ movdqu 0x40($inp), @XMM[12]
+ pxor @XMM[11], @XMM[2]
+ movdqu 0x50($inp), @XMM[15] # IV
+ pxor @XMM[12], @XMM[7]
+ movdqu @XMM[0], 0x00($out) # write output
+ movdqu @XMM[1], 0x10($out)
+ movdqu @XMM[6], 0x20($out)
+ movdqu @XMM[4], 0x30($out)
+ movdqu @XMM[2], 0x40($out)
+ movdqu @XMM[7], 0x50($out)
+ jmp .Lcbc_dec_done
+.align 16
+.Lcbc_dec_five:
+ movdqa @XMM[15], 0x20(%rbp) # put aside IV
+ call _bsaes_decrypt8
+ pxor 0x20(%rbp), @XMM[0] # ^= IV
+ movdqu 0x00($inp), @XMM[8] # re-load input
+ movdqu 0x10($inp), @XMM[9]
+ pxor @XMM[8], @XMM[1]
+ movdqu 0x20($inp), @XMM[10]
+ pxor @XMM[9], @XMM[6]
+ movdqu 0x30($inp), @XMM[11]
+ pxor @XMM[10], @XMM[4]
+ movdqu 0x40($inp), @XMM[15] # IV
+ pxor @XMM[11], @XMM[2]
+ movdqu @XMM[0], 0x00($out) # write output
+ movdqu @XMM[1], 0x10($out)
+ movdqu @XMM[6], 0x20($out)
+ movdqu @XMM[4], 0x30($out)
+ movdqu @XMM[2], 0x40($out)
+ jmp .Lcbc_dec_done
+.align 16
+.Lcbc_dec_four:
+ movdqa @XMM[15], 0x20(%rbp) # put aside IV
+ call _bsaes_decrypt8
+ pxor 0x20(%rbp), @XMM[0] # ^= IV
+ movdqu 0x00($inp), @XMM[8] # re-load input
+ movdqu 0x10($inp), @XMM[9]
+ pxor @XMM[8], @XMM[1]
+ movdqu 0x20($inp), @XMM[10]
+ pxor @XMM[9], @XMM[6]
+ movdqu 0x30($inp), @XMM[15] # IV
+ pxor @XMM[10], @XMM[4]
+ movdqu @XMM[0], 0x00($out) # write output
+ movdqu @XMM[1], 0x10($out)
+ movdqu @XMM[6], 0x20($out)
+ movdqu @XMM[4], 0x30($out)
+ jmp .Lcbc_dec_done
+.align 16
+.Lcbc_dec_three:
+ movdqa @XMM[15], 0x20(%rbp) # put aside IV
+ call _bsaes_decrypt8
+ pxor 0x20(%rbp), @XMM[0] # ^= IV
+ movdqu 0x00($inp), @XMM[8] # re-load input
+ movdqu 0x10($inp), @XMM[9]
+ pxor @XMM[8], @XMM[1]
+ movdqu 0x20($inp), @XMM[15] # IV
+ pxor @XMM[9], @XMM[6]
+ movdqu @XMM[0], 0x00($out) # write output
+ movdqu @XMM[1], 0x10($out)
+ movdqu @XMM[6], 0x20($out)
+ jmp .Lcbc_dec_done
+.align 16
+.Lcbc_dec_two:
+ movdqa @XMM[15], 0x20(%rbp) # put aside IV
+ call _bsaes_decrypt8
+ pxor 0x20(%rbp), @XMM[0] # ^= IV
+ movdqu 0x00($inp), @XMM[8] # re-load input
+ movdqu 0x10($inp), @XMM[15] # IV
+ pxor @XMM[8], @XMM[1]
+ movdqu @XMM[0], 0x00($out) # write output
+ movdqu @XMM[1], 0x10($out)
+ jmp .Lcbc_dec_done
+.align 16
+.Lcbc_dec_one:
+ lea ($inp), $arg1
+ lea 0x20(%rbp), $arg2 # buffer output
+ lea ($key), $arg3
+ call asm_AES_decrypt # doesn't touch %xmm
+ pxor 0x20(%rbp), @XMM[15] # ^= IV
+ movdqu @XMM[15], ($out) # write output
+ movdqa @XMM[0], @XMM[15] # IV
+
+.Lcbc_dec_done:
+ movdqu @XMM[15], (%rbx) # return IV
+ lea (%rsp), %rax
+ pxor %xmm0, %xmm0
+.Lcbc_dec_bzero: # wipe key schedule [if any]
+ movdqa %xmm0, 0x00(%rax)
+ movdqa %xmm0, 0x10(%rax)
+ lea 0x20(%rax), %rax
+ cmp %rax, %rbp
+ ja .Lcbc_dec_bzero
+
+ lea (%rbp),%rsp # restore %rsp
+___
+$code.=<<___ if ($win64);
+ movaps 0x40(%rbp), %xmm6
+ movaps 0x50(%rbp), %xmm7
+ movaps 0x60(%rbp), %xmm8
+ movaps 0x70(%rbp), %xmm9
+ movaps 0x80(%rbp), %xmm10
+ movaps 0x90(%rbp), %xmm11
+ movaps 0xa0(%rbp), %xmm12
+ movaps 0xb0(%rbp), %xmm13
+ movaps 0xc0(%rbp), %xmm14
+ movaps 0xd0(%rbp), %xmm15
+ lea 0xa0(%rbp), %rsp
+___
+$code.=<<___;
+ mov 0x48(%rsp), %r15
+ mov 0x50(%rsp), %r14
+ mov 0x58(%rsp), %r13
+ mov 0x60(%rsp), %r12
+ mov 0x68(%rsp), %rbx
+ mov 0x70(%rsp), %rax
+ lea 0x78(%rsp), %rsp
+ mov %rax, %rbp
+.Lcbc_dec_epilogue:
+ ret
+.size bsaes_cbc_encrypt,.-bsaes_cbc_encrypt
+
+.globl bsaes_ctr32_encrypt_blocks
+.type bsaes_ctr32_encrypt_blocks,\@abi-omnipotent
+.align 16
+bsaes_ctr32_encrypt_blocks:
+ mov %rsp, %rax
+.Lctr_enc_prologue:
+ push %rbp
+ push %rbx
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+ lea -0x48(%rsp), %rsp
+___
+$code.=<<___ if ($win64);
+ mov 0xa0(%rsp),$arg5 # pull ivp
+ lea -0xa0(%rsp), %rsp
+ movaps %xmm6, 0x40(%rsp)
+ movaps %xmm7, 0x50(%rsp)
+ movaps %xmm8, 0x60(%rsp)
+ movaps %xmm9, 0x70(%rsp)
+ movaps %xmm10, 0x80(%rsp)
+ movaps %xmm11, 0x90(%rsp)
+ movaps %xmm12, 0xa0(%rsp)
+ movaps %xmm13, 0xb0(%rsp)
+ movaps %xmm14, 0xc0(%rsp)
+ movaps %xmm15, 0xd0(%rsp)
+.Lctr_enc_body:
+___
+$code.=<<___;
+ mov %rsp, %rbp # backup %rsp
+ movdqu ($arg5), %xmm0 # load counter
+ mov 240($arg4), %eax # rounds
+ mov $arg1, $inp # backup arguments
+ mov $arg2, $out
+ mov $arg3, $len
+ mov $arg4, $key
+ movdqa %xmm0, 0x20(%rbp) # copy counter
+ cmp \$8, $arg3
+ jb .Lctr_enc_short
+
+ mov %eax, %ebx # rounds
+ shl \$7, %rax # 128 bytes per inner round key
+ sub \$`128-32`, %rax # size of bit-sliced key schedule
+ sub %rax, %rsp
+
+ mov %rsp, %rax # pass key schedule
+ mov $key, %rcx # pass key
+ mov %ebx, %r10d # pass rounds
+ call _bsaes_key_convert
+ pxor %xmm6,%xmm7 # fix up last round key
+ movdqa %xmm7,(%rax) # save last round key
+
+ movdqa (%rsp), @XMM[9] # load round0 key
+ lea .LADD1(%rip), %r11
+ movdqa 0x20(%rbp), @XMM[0] # counter copy
+ movdqa -0x20(%r11), @XMM[8] # .LSWPUP
+ pshufb @XMM[8], @XMM[9] # byte swap upper part
+ pshufb @XMM[8], @XMM[0]
+ movdqa @XMM[9], (%rsp) # save adjusted round0 key
+ jmp .Lctr_enc_loop
+.align 16
+.Lctr_enc_loop:
+ movdqa @XMM[0], 0x20(%rbp) # save counter
+ movdqa @XMM[0], @XMM[1] # prepare 8 counter values
+ movdqa @XMM[0], @XMM[2]
+ paddd 0x00(%r11), @XMM[1] # .LADD1
+ movdqa @XMM[0], @XMM[3]
+ paddd 0x10(%r11), @XMM[2] # .LADD2
+ movdqa @XMM[0], @XMM[4]
+ paddd 0x20(%r11), @XMM[3] # .LADD3
+ movdqa @XMM[0], @XMM[5]
+ paddd 0x30(%r11), @XMM[4] # .LADD4
+ movdqa @XMM[0], @XMM[6]
+ paddd 0x40(%r11), @XMM[5] # .LADD5
+ movdqa @XMM[0], @XMM[7]
+ paddd 0x50(%r11), @XMM[6] # .LADD6
+ paddd 0x60(%r11), @XMM[7] # .LADD7
+
+ # Borrow prologue from _bsaes_encrypt8 to use the opportunity
+ # to flip byte order in 32-bit counter
+ movdqa (%rsp), @XMM[9] # round 0 key
+ lea 0x10(%rsp), %rax # pass key schedule
+ movdqa -0x10(%r11), @XMM[8] # .LSWPUPM0SR
+ pxor @XMM[9], @XMM[0] # xor with round0 key
+ pxor @XMM[9], @XMM[1]
+ pxor @XMM[9], @XMM[2]
+ pxor @XMM[9], @XMM[3]
+ pshufb @XMM[8], @XMM[0]
+ pshufb @XMM[8], @XMM[1]
+ pxor @XMM[9], @XMM[4]
+ pxor @XMM[9], @XMM[5]
+ pshufb @XMM[8], @XMM[2]
+ pshufb @XMM[8], @XMM[3]
+ pxor @XMM[9], @XMM[6]
+ pxor @XMM[9], @XMM[7]
+ pshufb @XMM[8], @XMM[4]
+ pshufb @XMM[8], @XMM[5]
+ pshufb @XMM[8], @XMM[6]
+ pshufb @XMM[8], @XMM[7]
+ lea .LBS0(%rip), %r11 # constants table
+ mov %ebx,%r10d # pass rounds
+
+ call _bsaes_encrypt8_bitslice
+
+ sub \$8,$len
+ jc .Lctr_enc_loop_done
+
+ movdqu 0x00($inp), @XMM[8] # load input
+ movdqu 0x10($inp), @XMM[9]
+ movdqu 0x20($inp), @XMM[10]
+ movdqu 0x30($inp), @XMM[11]
+ movdqu 0x40($inp), @XMM[12]
+ movdqu 0x50($inp), @XMM[13]
+ movdqu 0x60($inp), @XMM[14]
+ movdqu 0x70($inp), @XMM[15]
+ lea 0x80($inp),$inp
+ pxor @XMM[0], @XMM[8]
+ movdqa 0x20(%rbp), @XMM[0] # load counter
+ pxor @XMM[9], @XMM[1]
+ movdqu @XMM[8], 0x00($out) # write output
+ pxor @XMM[10], @XMM[4]
+ movdqu @XMM[1], 0x10($out)
+ pxor @XMM[11], @XMM[6]
+ movdqu @XMM[4], 0x20($out)
+ pxor @XMM[12], @XMM[3]
+ movdqu @XMM[6], 0x30($out)
+ pxor @XMM[13], @XMM[7]
+ movdqu @XMM[3], 0x40($out)
+ pxor @XMM[14], @XMM[2]
+ movdqu @XMM[7], 0x50($out)
+ pxor @XMM[15], @XMM[5]
+ movdqu @XMM[2], 0x60($out)
+ lea .LADD1(%rip), %r11
+ movdqu @XMM[5], 0x70($out)
+ lea 0x80($out), $out
+ paddd 0x70(%r11), @XMM[0] # .LADD8
+ jnz .Lctr_enc_loop
+
+ jmp .Lctr_enc_done
+.align 16
+.Lctr_enc_loop_done:
+ add \$8, $len
+ movdqu 0x00($inp), @XMM[8] # load input
+ pxor @XMM[8], @XMM[0]
+ movdqu @XMM[0], 0x00($out) # write output
+ cmp \$2,$len
+ jb .Lctr_enc_done
+ movdqu 0x10($inp), @XMM[9]
+ pxor @XMM[9], @XMM[1]
+ movdqu @XMM[1], 0x10($out)
+ je .Lctr_enc_done
+ movdqu 0x20($inp), @XMM[10]
+ pxor @XMM[10], @XMM[4]
+ movdqu @XMM[4], 0x20($out)
+ cmp \$4,$len
+ jb .Lctr_enc_done
+ movdqu 0x30($inp), @XMM[11]
+ pxor @XMM[11], @XMM[6]
+ movdqu @XMM[6], 0x30($out)
+ je .Lctr_enc_done
+ movdqu 0x40($inp), @XMM[12]
+ pxor @XMM[12], @XMM[3]
+ movdqu @XMM[3], 0x40($out)
+ cmp \$6,$len
+ jb .Lctr_enc_done
+ movdqu 0x50($inp), @XMM[13]
+ pxor @XMM[13], @XMM[7]
+ movdqu @XMM[7], 0x50($out)
+ je .Lctr_enc_done
+ movdqu 0x60($inp), @XMM[14]
+ pxor @XMM[14], @XMM[2]
+ movdqu @XMM[2], 0x60($out)
+ jmp .Lctr_enc_done
+
+.align 16
+.Lctr_enc_short:
+ lea 0x20(%rbp), $arg1
+ lea 0x30(%rbp), $arg2
+ lea ($key), $arg3
+ call asm_AES_encrypt
+ movdqu ($inp), @XMM[1]
+ lea 16($inp), $inp
+ mov 0x2c(%rbp), %eax # load 32-bit counter
+ bswap %eax
+ pxor 0x30(%rbp), @XMM[1]
+ inc %eax # increment
+ movdqu @XMM[1], ($out)
+ bswap %eax
+ lea 16($out), $out
+ mov %eax, 0x2c(%rsp) # save 32-bit counter
+ dec $len
+ jnz .Lctr_enc_short
+
+.Lctr_enc_done:
+ lea (%rsp), %rax
+ pxor %xmm0, %xmm0
+.Lctr_enc_bzero: # wipe key schedule [if any]
+ movdqa %xmm0, 0x00(%rax)
+ movdqa %xmm0, 0x10(%rax)
+ lea 0x20(%rax), %rax
+ cmp %rax, %rbp
+ ja .Lctr_enc_bzero
+
+ lea (%rbp),%rsp # restore %rsp
+___
+$code.=<<___ if ($win64);
+ movaps 0x40(%rbp), %xmm6
+ movaps 0x50(%rbp), %xmm7
+ movaps 0x60(%rbp), %xmm8
+ movaps 0x70(%rbp), %xmm9
+ movaps 0x80(%rbp), %xmm10
+ movaps 0x90(%rbp), %xmm11
+ movaps 0xa0(%rbp), %xmm12
+ movaps 0xb0(%rbp), %xmm13
+ movaps 0xc0(%rbp), %xmm14
+ movaps 0xd0(%rbp), %xmm15
+ lea 0xa0(%rbp), %rsp
+___
+$code.=<<___;
+ mov 0x48(%rsp), %r15
+ mov 0x50(%rsp), %r14
+ mov 0x58(%rsp), %r13
+ mov 0x60(%rsp), %r12
+ mov 0x68(%rsp), %rbx
+ mov 0x70(%rsp), %rax
+ lea 0x78(%rsp), %rsp
+ mov %rax, %rbp
+.Lctr_enc_epilogue:
+ ret
+.size bsaes_ctr32_encrypt_blocks,.-bsaes_ctr32_encrypt_blocks
+___
+######################################################################
+# void bsaes_xts_[en|de]crypt(const char *inp,char *out,size_t len,
+# const AES_KEY *key1, const AES_KEY *key2,
+# const unsigned char iv[16]);
+#
+my ($twmask,$twres,$twtmp)=@XMM[13..15];
+$arg6=~s/d$//;
+
+$code.=<<___;
+.globl bsaes_xts_encrypt
+.type bsaes_xts_encrypt,\@abi-omnipotent
+.align 16
+bsaes_xts_encrypt:
+ mov %rsp, %rax
+.Lxts_enc_prologue:
+ push %rbp
+ push %rbx
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+ lea -0x48(%rsp), %rsp
+___
+$code.=<<___ if ($win64);
+ mov 0xa0(%rsp),$arg5 # pull key2
+ mov 0xa8(%rsp),$arg6 # pull ivp
+ lea -0xa0(%rsp), %rsp
+ movaps %xmm6, 0x40(%rsp)
+ movaps %xmm7, 0x50(%rsp)
+ movaps %xmm8, 0x60(%rsp)
+ movaps %xmm9, 0x70(%rsp)
+ movaps %xmm10, 0x80(%rsp)
+ movaps %xmm11, 0x90(%rsp)
+ movaps %xmm12, 0xa0(%rsp)
+ movaps %xmm13, 0xb0(%rsp)
+ movaps %xmm14, 0xc0(%rsp)
+ movaps %xmm15, 0xd0(%rsp)
+.Lxts_enc_body:
+___
+$code.=<<___;
+ mov %rsp, %rbp # backup %rsp
+ mov $arg1, $inp # backup arguments
+ mov $arg2, $out
+ mov $arg3, $len
+ mov $arg4, $key
+
+ lea ($arg6), $arg1
+ lea 0x20(%rbp), $arg2
+ lea ($arg5), $arg3
+ call asm_AES_encrypt # generate initial tweak
+
+ mov 240($key), %eax # rounds
+ mov $len, %rbx # backup $len
+
+ mov %eax, %edx # rounds
+ shl \$7, %rax # 128 bytes per inner round key
+ sub \$`128-32`, %rax # size of bit-sliced key schedule
+ sub %rax, %rsp
+
+ mov %rsp, %rax # pass key schedule
+ mov $key, %rcx # pass key
+ mov %edx, %r10d # pass rounds
+ call _bsaes_key_convert
+ pxor %xmm6, %xmm7 # fix up last round key
+ movdqa %xmm7, (%rax) # save last round key
+
+ and \$-16, $len
+ sub \$0x80, %rsp # place for tweak[8]
+ movdqa 0x20(%rbp), @XMM[7] # initial tweak
+
+ pxor $twtmp, $twtmp
+ movdqa .Lxts_magic(%rip), $twmask
+ pcmpgtd @XMM[7], $twtmp # broadcast upper bits
+
+ sub \$0x80, $len
+ jc .Lxts_enc_short
+ jmp .Lxts_enc_loop
+
+.align 16
+.Lxts_enc_loop:
+___
+ for ($i=0;$i<7;$i++) {
+ $code.=<<___;
+ pshufd \$0x13, $twtmp, $twres
+ pxor $twtmp, $twtmp
+ movdqa @XMM[7], @XMM[$i]
+ movdqa @XMM[7], `0x10*$i`(%rsp)# save tweak[$i]
+ paddq @XMM[7], @XMM[7] # psllq 1,$tweak
+ pand $twmask, $twres # isolate carry and residue
+ pcmpgtd @XMM[7], $twtmp # broadcast upper bits
+ pxor $twres, @XMM[7]
+___
+ $code.=<<___ if ($i>=1);
+ movdqu `0x10*($i-1)`($inp), @XMM[8+$i-1]
+___
+ $code.=<<___ if ($i>=2);
+ pxor @XMM[8+$i-2], @XMM[$i-2]# input[] ^ tweak[]
+___
+ }
+$code.=<<___;
+ movdqu 0x60($inp), @XMM[8+6]
+ pxor @XMM[8+5], @XMM[5]
+ movdqu 0x70($inp), @XMM[8+7]
+ lea 0x80($inp), $inp
+ movdqa @XMM[7], 0x70(%rsp)
+ pxor @XMM[8+6], @XMM[6]
+ lea 0x80(%rsp), %rax # pass key schedule
+ pxor @XMM[8+7], @XMM[7]
+ mov %edx, %r10d # pass rounds
+
+ call _bsaes_encrypt8
+
+ pxor 0x00(%rsp), @XMM[0] # ^= tweak[]
+ pxor 0x10(%rsp), @XMM[1]
+ movdqu @XMM[0], 0x00($out) # write output
+ pxor 0x20(%rsp), @XMM[4]
+ movdqu @XMM[1], 0x10($out)
+ pxor 0x30(%rsp), @XMM[6]
+ movdqu @XMM[4], 0x20($out)
+ pxor 0x40(%rsp), @XMM[3]
+ movdqu @XMM[6], 0x30($out)
+ pxor 0x50(%rsp), @XMM[7]
+ movdqu @XMM[3], 0x40($out)
+ pxor 0x60(%rsp), @XMM[2]
+ movdqu @XMM[7], 0x50($out)
+ pxor 0x70(%rsp), @XMM[5]
+ movdqu @XMM[2], 0x60($out)
+ movdqu @XMM[5], 0x70($out)
+ lea 0x80($out), $out
+
+ movdqa 0x70(%rsp), @XMM[7] # prepare next iteration tweak
+ pxor $twtmp, $twtmp
+ movdqa .Lxts_magic(%rip), $twmask
+ pcmpgtd @XMM[7], $twtmp
+ pshufd \$0x13, $twtmp, $twres
+ pxor $twtmp, $twtmp
+ paddq @XMM[7], @XMM[7] # psllq 1,$tweak
+ pand $twmask, $twres # isolate carry and residue
+ pcmpgtd @XMM[7], $twtmp # broadcast upper bits
+ pxor $twres, @XMM[7]
+
+ sub \$0x80,$len
+ jnc .Lxts_enc_loop
+
+.Lxts_enc_short:
+ add \$0x80, $len
+ jz .Lxts_enc_done
+___
+ for ($i=0;$i<7;$i++) {
+ $code.=<<___;
+ pshufd \$0x13, $twtmp, $twres
+ pxor $twtmp, $twtmp
+ movdqa @XMM[7], @XMM[$i]
+ movdqa @XMM[7], `0x10*$i`(%rsp)# save tweak[$i]
+ paddq @XMM[7], @XMM[7] # psllq 1,$tweak
+ pand $twmask, $twres # isolate carry and residue
+ pcmpgtd @XMM[7], $twtmp # broadcast upper bits
+ pxor $twres, @XMM[7]
+___
+ $code.=<<___ if ($i>=1);
+ movdqu `0x10*($i-1)`($inp), @XMM[8+$i-1]
+ cmp \$`0x10*$i`,$len
+ je .Lxts_enc_$i
+___
+ $code.=<<___ if ($i>=2);
+ pxor @XMM[8+$i-2], @XMM[$i-2]# input[] ^ tweak[]
+___
+ }
+$code.=<<___;
+ movdqu 0x60($inp), @XMM[8+6]
+ pxor @XMM[8+5], @XMM[5]
+ movdqa @XMM[7], 0x70(%rsp)
+ lea 0x70($inp), $inp
+ pxor @XMM[8+6], @XMM[6]
+ lea 0x80(%rsp), %rax # pass key schedule
+ mov %edx, %r10d # pass rounds
+
+ call _bsaes_encrypt8
+
+ pxor 0x00(%rsp), @XMM[0] # ^= tweak[]
+ pxor 0x10(%rsp), @XMM[1]
+ movdqu @XMM[0], 0x00($out) # write output
+ pxor 0x20(%rsp), @XMM[4]
+ movdqu @XMM[1], 0x10($out)
+ pxor 0x30(%rsp), @XMM[6]
+ movdqu @XMM[4], 0x20($out)
+ pxor 0x40(%rsp), @XMM[3]
+ movdqu @XMM[6], 0x30($out)
+ pxor 0x50(%rsp), @XMM[7]
+ movdqu @XMM[3], 0x40($out)
+ pxor 0x60(%rsp), @XMM[2]
+ movdqu @XMM[7], 0x50($out)
+ movdqu @XMM[2], 0x60($out)
+ lea 0x70($out), $out
+
+ movdqa 0x70(%rsp), @XMM[7] # next iteration tweak
+ jmp .Lxts_enc_done
+.align 16
+.Lxts_enc_6:
+ pxor @XMM[8+4], @XMM[4]
+ lea 0x60($inp), $inp
+ pxor @XMM[8+5], @XMM[5]
+ lea 0x80(%rsp), %rax # pass key schedule
+ mov %edx, %r10d # pass rounds
+
+ call _bsaes_encrypt8
+
+ pxor 0x00(%rsp), @XMM[0] # ^= tweak[]
+ pxor 0x10(%rsp), @XMM[1]
+ movdqu @XMM[0], 0x00($out) # write output
+ pxor 0x20(%rsp), @XMM[4]
+ movdqu @XMM[1], 0x10($out)
+ pxor 0x30(%rsp), @XMM[6]
+ movdqu @XMM[4], 0x20($out)
+ pxor 0x40(%rsp), @XMM[3]
+ movdqu @XMM[6], 0x30($out)
+ pxor 0x50(%rsp), @XMM[7]
+ movdqu @XMM[3], 0x40($out)
+ movdqu @XMM[7], 0x50($out)
+ lea 0x60($out), $out
+
+ movdqa 0x60(%rsp), @XMM[7] # next iteration tweak
+ jmp .Lxts_enc_done
+.align 16
+.Lxts_enc_5:
+ pxor @XMM[8+3], @XMM[3]
+ lea 0x50($inp), $inp
+ pxor @XMM[8+4], @XMM[4]
+ lea 0x80(%rsp), %rax # pass key schedule
+ mov %edx, %r10d # pass rounds
+
+ call _bsaes_encrypt8
+
+ pxor 0x00(%rsp), @XMM[0] # ^= tweak[]
+ pxor 0x10(%rsp), @XMM[1]
+ movdqu @XMM[0], 0x00($out) # write output
+ pxor 0x20(%rsp), @XMM[4]
+ movdqu @XMM[1], 0x10($out)
+ pxor 0x30(%rsp), @XMM[6]
+ movdqu @XMM[4], 0x20($out)
+ pxor 0x40(%rsp), @XMM[3]
+ movdqu @XMM[6], 0x30($out)
+ movdqu @XMM[3], 0x40($out)
+ lea 0x50($out), $out
+
+ movdqa 0x50(%rsp), @XMM[7] # next iteration tweak
+ jmp .Lxts_enc_done
+.align 16
+.Lxts_enc_4:
+ pxor @XMM[8+2], @XMM[2]
+ lea 0x40($inp), $inp
+ pxor @XMM[8+3], @XMM[3]
+ lea 0x80(%rsp), %rax # pass key schedule
+ mov %edx, %r10d # pass rounds
+
+ call _bsaes_encrypt8
+
+ pxor 0x00(%rsp), @XMM[0] # ^= tweak[]
+ pxor 0x10(%rsp), @XMM[1]
+ movdqu @XMM[0], 0x00($out) # write output
+ pxor 0x20(%rsp), @XMM[4]
+ movdqu @XMM[1], 0x10($out)
+ pxor 0x30(%rsp), @XMM[6]
+ movdqu @XMM[4], 0x20($out)
+ movdqu @XMM[6], 0x30($out)
+ lea 0x40($out), $out
+
+ movdqa 0x40(%rsp), @XMM[7] # next iteration tweak
+ jmp .Lxts_enc_done
+.align 16
+.Lxts_enc_3:
+ pxor @XMM[8+1], @XMM[1]
+ lea 0x30($inp), $inp
+ pxor @XMM[8+2], @XMM[2]
+ lea 0x80(%rsp), %rax # pass key schedule
+ mov %edx, %r10d # pass rounds
+
+ call _bsaes_encrypt8
+
+ pxor 0x00(%rsp), @XMM[0] # ^= tweak[]
+ pxor 0x10(%rsp), @XMM[1]
+ movdqu @XMM[0], 0x00($out) # write output
+ pxor 0x20(%rsp), @XMM[4]
+ movdqu @XMM[1], 0x10($out)
+ movdqu @XMM[4], 0x20($out)
+ lea 0x30($out), $out
+
+ movdqa 0x30(%rsp), @XMM[7] # next iteration tweak
+ jmp .Lxts_enc_done
+.align 16
+.Lxts_enc_2:
+ pxor @XMM[8+0], @XMM[0]
+ lea 0x20($inp), $inp
+ pxor @XMM[8+1], @XMM[1]
+ lea 0x80(%rsp), %rax # pass key schedule
+ mov %edx, %r10d # pass rounds
+
+ call _bsaes_encrypt8
+
+ pxor 0x00(%rsp), @XMM[0] # ^= tweak[]
+ pxor 0x10(%rsp), @XMM[1]
+ movdqu @XMM[0], 0x00($out) # write output
+ movdqu @XMM[1], 0x10($out)
+ lea 0x20($out), $out
+
+ movdqa 0x20(%rsp), @XMM[7] # next iteration tweak
+ jmp .Lxts_enc_done
+.align 16
+.Lxts_enc_1:
+ pxor @XMM[0], @XMM[8]
+ lea 0x10($inp), $inp
+ movdqa @XMM[8], 0x20(%rbp)
+ lea 0x20(%rbp), $arg1
+ lea 0x20(%rbp), $arg2
+ lea ($key), $arg3
+ call asm_AES_encrypt # doesn't touch %xmm
+ pxor 0x20(%rbp), @XMM[0] # ^= tweak[]
+ #pxor @XMM[8], @XMM[0]
+ #lea 0x80(%rsp), %rax # pass key schedule
+ #mov %edx, %r10d # pass rounds
+ #call _bsaes_encrypt8
+ #pxor 0x00(%rsp), @XMM[0] # ^= tweak[]
+ movdqu @XMM[0], 0x00($out) # write output
+ lea 0x10($out), $out
+
+ movdqa 0x10(%rsp), @XMM[7] # next iteration tweak
+
+.Lxts_enc_done:
+ and \$15, %ebx
+ jz .Lxts_enc_ret
+ mov $out, %rdx
+
+.Lxts_enc_steal:
+ movzb ($inp), %eax
+ movzb -16(%rdx), %ecx
+ lea 1($inp), $inp
+ mov %al, -16(%rdx)
+ mov %cl, 0(%rdx)
+ lea 1(%rdx), %rdx
+ sub \$1,%ebx
+ jnz .Lxts_enc_steal
+
+ movdqu -16($out), @XMM[0]
+ lea 0x20(%rbp), $arg1
+ pxor @XMM[7], @XMM[0]
+ lea 0x20(%rbp), $arg2
+ movdqa @XMM[0], 0x20(%rbp)
+ lea ($key), $arg3
+ call asm_AES_encrypt # doesn't touch %xmm
+ pxor 0x20(%rbp), @XMM[7]
+ movdqu @XMM[7], -16($out)
+
+.Lxts_enc_ret:
+ lea (%rsp), %rax
+ pxor %xmm0, %xmm0
+.Lxts_enc_bzero: # wipe key schedule [if any]
+ movdqa %xmm0, 0x00(%rax)
+ movdqa %xmm0, 0x10(%rax)
+ lea 0x20(%rax), %rax
+ cmp %rax, %rbp
+ ja .Lxts_enc_bzero
+
+ lea (%rbp),%rsp # restore %rsp
+___
+$code.=<<___ if ($win64);
+ movaps 0x40(%rbp), %xmm6
+ movaps 0x50(%rbp), %xmm7
+ movaps 0x60(%rbp), %xmm8
+ movaps 0x70(%rbp), %xmm9
+ movaps 0x80(%rbp), %xmm10
+ movaps 0x90(%rbp), %xmm11
+ movaps 0xa0(%rbp), %xmm12
+ movaps 0xb0(%rbp), %xmm13
+ movaps 0xc0(%rbp), %xmm14
+ movaps 0xd0(%rbp), %xmm15
+ lea 0xa0(%rbp), %rsp
+___
+$code.=<<___;
+ mov 0x48(%rsp), %r15
+ mov 0x50(%rsp), %r14
+ mov 0x58(%rsp), %r13
+ mov 0x60(%rsp), %r12
+ mov 0x68(%rsp), %rbx
+ mov 0x70(%rsp), %rax
+ lea 0x78(%rsp), %rsp
+ mov %rax, %rbp
+.Lxts_enc_epilogue:
+ ret
+.size bsaes_xts_encrypt,.-bsaes_xts_encrypt
+
+.globl bsaes_xts_decrypt
+.type bsaes_xts_decrypt,\@abi-omnipotent
+.align 16
+bsaes_xts_decrypt:
+ mov %rsp, %rax
+.Lxts_dec_prologue:
+ push %rbp
+ push %rbx
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+ lea -0x48(%rsp), %rsp
+___
+$code.=<<___ if ($win64);
+ mov 0xa0(%rsp),$arg5 # pull key2
+ mov 0xa8(%rsp),$arg6 # pull ivp
+ lea -0xa0(%rsp), %rsp
+ movaps %xmm6, 0x40(%rsp)
+ movaps %xmm7, 0x50(%rsp)
+ movaps %xmm8, 0x60(%rsp)
+ movaps %xmm9, 0x70(%rsp)
+ movaps %xmm10, 0x80(%rsp)
+ movaps %xmm11, 0x90(%rsp)
+ movaps %xmm12, 0xa0(%rsp)
+ movaps %xmm13, 0xb0(%rsp)
+ movaps %xmm14, 0xc0(%rsp)
+ movaps %xmm15, 0xd0(%rsp)
+.Lxts_dec_body:
+___
+$code.=<<___;
+ mov %rsp, %rbp # backup %rsp
+ mov $arg1, $inp # backup arguments
+ mov $arg2, $out
+ mov $arg3, $len
+ mov $arg4, $key
+
+ lea ($arg6), $arg1
+ lea 0x20(%rbp), $arg2
+ lea ($arg5), $arg3
+ call asm_AES_encrypt # generate initial tweak
+
+ mov 240($key), %eax # rounds
+ mov $len, %rbx # backup $len
+
+ mov %eax, %edx # rounds
+ shl \$7, %rax # 128 bytes per inner round key
+ sub \$`128-32`, %rax # size of bit-sliced key schedule
+ sub %rax, %rsp
+
+ mov %rsp, %rax # pass key schedule
+ mov $key, %rcx # pass key
+ mov %edx, %r10d # pass rounds
+ call _bsaes_key_convert
+ pxor (%rsp), %xmm7 # fix up round 0 key
+ movdqa %xmm6, (%rax) # save last round key
+ movdqa %xmm7, (%rsp)
+
+ xor %eax, %eax # if ($len%16) len-=16;
+ and \$-16, $len
+ test \$15, %ebx
+ setnz %al
+ shl \$4, %rax
+ sub %rax, $len
+
+ sub \$0x80, %rsp # place for tweak[8]
+ movdqa 0x20(%rbp), @XMM[7] # initial tweak
+
+ pxor $twtmp, $twtmp
+ movdqa .Lxts_magic(%rip), $twmask
+ pcmpgtd @XMM[7], $twtmp # broadcast upper bits
+
+ sub \$0x80, $len
+ jc .Lxts_dec_short
+ jmp .Lxts_dec_loop
+
+.align 16
+.Lxts_dec_loop:
+___
+ for ($i=0;$i<7;$i++) {
+ $code.=<<___;
+ pshufd \$0x13, $twtmp, $twres
+ pxor $twtmp, $twtmp
+ movdqa @XMM[7], @XMM[$i]
+ movdqa @XMM[7], `0x10*$i`(%rsp)# save tweak[$i]
+ paddq @XMM[7], @XMM[7] # psllq 1,$tweak
+ pand $twmask, $twres # isolate carry and residue
+ pcmpgtd @XMM[7], $twtmp # broadcast upper bits
+ pxor $twres, @XMM[7]
+___
+ $code.=<<___ if ($i>=1);
+ movdqu `0x10*($i-1)`($inp), @XMM[8+$i-1]
+___
+ $code.=<<___ if ($i>=2);
+ pxor @XMM[8+$i-2], @XMM[$i-2]# input[] ^ tweak[]
+___
+ }
+$code.=<<___;
+ movdqu 0x60($inp), @XMM[8+6]
+ pxor @XMM[8+5], @XMM[5]
+ movdqu 0x70($inp), @XMM[8+7]
+ lea 0x80($inp), $inp
+ movdqa @XMM[7], 0x70(%rsp)
+ pxor @XMM[8+6], @XMM[6]
+ lea 0x80(%rsp), %rax # pass key schedule
+ pxor @XMM[8+7], @XMM[7]
+ mov %edx, %r10d # pass rounds
+
+ call _bsaes_decrypt8
+
+ pxor 0x00(%rsp), @XMM[0] # ^= tweak[]
+ pxor 0x10(%rsp), @XMM[1]
+ movdqu @XMM[0], 0x00($out) # write output
+ pxor 0x20(%rsp), @XMM[6]
+ movdqu @XMM[1], 0x10($out)
+ pxor 0x30(%rsp), @XMM[4]
+ movdqu @XMM[6], 0x20($out)
+ pxor 0x40(%rsp), @XMM[2]
+ movdqu @XMM[4], 0x30($out)
+ pxor 0x50(%rsp), @XMM[7]
+ movdqu @XMM[2], 0x40($out)
+ pxor 0x60(%rsp), @XMM[3]
+ movdqu @XMM[7], 0x50($out)
+ pxor 0x70(%rsp), @XMM[5]
+ movdqu @XMM[3], 0x60($out)
+ movdqu @XMM[5], 0x70($out)
+ lea 0x80($out), $out
+
+ movdqa 0x70(%rsp), @XMM[7] # prepare next iteration tweak
+ pxor $twtmp, $twtmp
+ movdqa .Lxts_magic(%rip), $twmask
+ pcmpgtd @XMM[7], $twtmp
+ pshufd \$0x13, $twtmp, $twres
+ pxor $twtmp, $twtmp
+ paddq @XMM[7], @XMM[7] # psllq 1,$tweak
+ pand $twmask, $twres # isolate carry and residue
+ pcmpgtd @XMM[7], $twtmp # broadcast upper bits
+ pxor $twres, @XMM[7]
+
+ sub \$0x80,$len
+ jnc .Lxts_dec_loop
+
+.Lxts_dec_short:
+ add \$0x80, $len
+ jz .Lxts_dec_done
+___
+ for ($i=0;$i<7;$i++) {
+ $code.=<<___;
+ pshufd \$0x13, $twtmp, $twres
+ pxor $twtmp, $twtmp
+ movdqa @XMM[7], @XMM[$i]
+ movdqa @XMM[7], `0x10*$i`(%rsp)# save tweak[$i]
+ paddq @XMM[7], @XMM[7] # psllq 1,$tweak
+ pand $twmask, $twres # isolate carry and residue
+ pcmpgtd @XMM[7], $twtmp # broadcast upper bits
+ pxor $twres, @XMM[7]
+___
+ $code.=<<___ if ($i>=1);
+ movdqu `0x10*($i-1)`($inp), @XMM[8+$i-1]
+ cmp \$`0x10*$i`,$len
+ je .Lxts_dec_$i
+___
+ $code.=<<___ if ($i>=2);
+ pxor @XMM[8+$i-2], @XMM[$i-2]# input[] ^ tweak[]
+___
+ }
+$code.=<<___;
+ movdqu 0x60($inp), @XMM[8+6]
+ pxor @XMM[8+5], @XMM[5]
+ movdqa @XMM[7], 0x70(%rsp)
+ lea 0x70($inp), $inp
+ pxor @XMM[8+6], @XMM[6]
+ lea 0x80(%rsp), %rax # pass key schedule
+ mov %edx, %r10d # pass rounds
+
+ call _bsaes_decrypt8
+
+ pxor 0x00(%rsp), @XMM[0] # ^= tweak[]
+ pxor 0x10(%rsp), @XMM[1]
+ movdqu @XMM[0], 0x00($out) # write output
+ pxor 0x20(%rsp), @XMM[6]
+ movdqu @XMM[1], 0x10($out)
+ pxor 0x30(%rsp), @XMM[4]
+ movdqu @XMM[6], 0x20($out)
+ pxor 0x40(%rsp), @XMM[2]
+ movdqu @XMM[4], 0x30($out)
+ pxor 0x50(%rsp), @XMM[7]
+ movdqu @XMM[2], 0x40($out)
+ pxor 0x60(%rsp), @XMM[3]
+ movdqu @XMM[7], 0x50($out)
+ movdqu @XMM[3], 0x60($out)
+ lea 0x70($out), $out
+
+ movdqa 0x70(%rsp), @XMM[7] # next iteration tweak
+ jmp .Lxts_dec_done
+.align 16
+.Lxts_dec_6:
+ pxor @XMM[8+4], @XMM[4]
+ lea 0x60($inp), $inp
+ pxor @XMM[8+5], @XMM[5]
+ lea 0x80(%rsp), %rax # pass key schedule
+ mov %edx, %r10d # pass rounds
+
+ call _bsaes_decrypt8
+
+ pxor 0x00(%rsp), @XMM[0] # ^= tweak[]
+ pxor 0x10(%rsp), @XMM[1]
+ movdqu @XMM[0], 0x00($out) # write output
+ pxor 0x20(%rsp), @XMM[6]
+ movdqu @XMM[1], 0x10($out)
+ pxor 0x30(%rsp), @XMM[4]
+ movdqu @XMM[6], 0x20($out)
+ pxor 0x40(%rsp), @XMM[2]
+ movdqu @XMM[4], 0x30($out)
+ pxor 0x50(%rsp), @XMM[7]
+ movdqu @XMM[2], 0x40($out)
+ movdqu @XMM[7], 0x50($out)
+ lea 0x60($out), $out
+
+ movdqa 0x60(%rsp), @XMM[7] # next iteration tweak
+ jmp .Lxts_dec_done
+.align 16
+.Lxts_dec_5:
+ pxor @XMM[8+3], @XMM[3]
+ lea 0x50($inp), $inp
+ pxor @XMM[8+4], @XMM[4]
+ lea 0x80(%rsp), %rax # pass key schedule
+ mov %edx, %r10d # pass rounds
+
+ call _bsaes_decrypt8
+
+ pxor 0x00(%rsp), @XMM[0] # ^= tweak[]
+ pxor 0x10(%rsp), @XMM[1]
+ movdqu @XMM[0], 0x00($out) # write output
+ pxor 0x20(%rsp), @XMM[6]
+ movdqu @XMM[1], 0x10($out)
+ pxor 0x30(%rsp), @XMM[4]
+ movdqu @XMM[6], 0x20($out)
+ pxor 0x40(%rsp), @XMM[2]
+ movdqu @XMM[4], 0x30($out)
+ movdqu @XMM[2], 0x40($out)
+ lea 0x50($out), $out
+
+ movdqa 0x50(%rsp), @XMM[7] # next iteration tweak
+ jmp .Lxts_dec_done
+.align 16
+.Lxts_dec_4:
+ pxor @XMM[8+2], @XMM[2]
+ lea 0x40($inp), $inp
+ pxor @XMM[8+3], @XMM[3]
+ lea 0x80(%rsp), %rax # pass key schedule
+ mov %edx, %r10d # pass rounds
+
+ call _bsaes_decrypt8
+
+ pxor 0x00(%rsp), @XMM[0] # ^= tweak[]
+ pxor 0x10(%rsp), @XMM[1]
+ movdqu @XMM[0], 0x00($out) # write output
+ pxor 0x20(%rsp), @XMM[6]
+ movdqu @XMM[1], 0x10($out)
+ pxor 0x30(%rsp), @XMM[4]
+ movdqu @XMM[6], 0x20($out)
+ movdqu @XMM[4], 0x30($out)
+ lea 0x40($out), $out
+
+ movdqa 0x40(%rsp), @XMM[7] # next iteration tweak
+ jmp .Lxts_dec_done
+.align 16
+.Lxts_dec_3:
+ pxor @XMM[8+1], @XMM[1]
+ lea 0x30($inp), $inp
+ pxor @XMM[8+2], @XMM[2]
+ lea 0x80(%rsp), %rax # pass key schedule
+ mov %edx, %r10d # pass rounds
+
+ call _bsaes_decrypt8
+
+ pxor 0x00(%rsp), @XMM[0] # ^= tweak[]
+ pxor 0x10(%rsp), @XMM[1]
+ movdqu @XMM[0], 0x00($out) # write output
+ pxor 0x20(%rsp), @XMM[6]
+ movdqu @XMM[1], 0x10($out)
+ movdqu @XMM[6], 0x20($out)
+ lea 0x30($out), $out
+
+ movdqa 0x30(%rsp), @XMM[7] # next iteration tweak
+ jmp .Lxts_dec_done
+.align 16
+.Lxts_dec_2:
+ pxor @XMM[8+0], @XMM[0]
+ lea 0x20($inp), $inp
+ pxor @XMM[8+1], @XMM[1]
+ lea 0x80(%rsp), %rax # pass key schedule
+ mov %edx, %r10d # pass rounds
+
+ call _bsaes_decrypt8
+
+ pxor 0x00(%rsp), @XMM[0] # ^= tweak[]
+ pxor 0x10(%rsp), @XMM[1]
+ movdqu @XMM[0], 0x00($out) # write output
+ movdqu @XMM[1], 0x10($out)
+ lea 0x20($out), $out
+
+ movdqa 0x20(%rsp), @XMM[7] # next iteration tweak
+ jmp .Lxts_dec_done
+.align 16
+.Lxts_dec_1:
+ pxor @XMM[0], @XMM[8]
+ lea 0x10($inp), $inp
+ movdqa @XMM[8], 0x20(%rbp)
+ lea 0x20(%rbp), $arg1
+ lea 0x20(%rbp), $arg2
+ lea ($key), $arg3
+ call asm_AES_decrypt # doesn't touch %xmm
+ pxor 0x20(%rbp), @XMM[0] # ^= tweak[]
+ #pxor @XMM[8], @XMM[0]
+ #lea 0x80(%rsp), %rax # pass key schedule
+ #mov %edx, %r10d # pass rounds
+ #call _bsaes_decrypt8
+ #pxor 0x00(%rsp), @XMM[0] # ^= tweak[]
+ movdqu @XMM[0], 0x00($out) # write output
+ lea 0x10($out), $out
+
+ movdqa 0x10(%rsp), @XMM[7] # next iteration tweak
+
+.Lxts_dec_done:
+ and \$15, %ebx
+ jz .Lxts_dec_ret
+
+ pxor $twtmp, $twtmp
+ movdqa .Lxts_magic(%rip), $twmask
+ pcmpgtd @XMM[7], $twtmp
+ pshufd \$0x13, $twtmp, $twres
+ movdqa @XMM[7], @XMM[6]
+ paddq @XMM[7], @XMM[7] # psllq 1,$tweak
+ pand $twmask, $twres # isolate carry and residue
+ movdqu ($inp), @XMM[0]
+ pxor $twres, @XMM[7]
+
+ lea 0x20(%rbp), $arg1
+ pxor @XMM[7], @XMM[0]
+ lea 0x20(%rbp), $arg2
+ movdqa @XMM[0], 0x20(%rbp)
+ lea ($key), $arg3
+ call asm_AES_decrypt # doesn't touch %xmm
+ pxor 0x20(%rbp), @XMM[7]
+ mov $out, %rdx
+ movdqu @XMM[7], ($out)
+
+.Lxts_dec_steal:
+ movzb 16($inp), %eax
+ movzb (%rdx), %ecx
+ lea 1($inp), $inp
+ mov %al, (%rdx)
+ mov %cl, 16(%rdx)
+ lea 1(%rdx), %rdx
+ sub \$1,%ebx
+ jnz .Lxts_dec_steal
+
+ movdqu ($out), @XMM[0]
+ lea 0x20(%rbp), $arg1
+ pxor @XMM[6], @XMM[0]
+ lea 0x20(%rbp), $arg2
+ movdqa @XMM[0], 0x20(%rbp)
+ lea ($key), $arg3
+ call asm_AES_decrypt # doesn't touch %xmm
+ pxor 0x20(%rbp), @XMM[6]
+ movdqu @XMM[6], ($out)
+
+.Lxts_dec_ret:
+ lea (%rsp), %rax
+ pxor %xmm0, %xmm0
+.Lxts_dec_bzero: # wipe key schedule [if any]
+ movdqa %xmm0, 0x00(%rax)
+ movdqa %xmm0, 0x10(%rax)
+ lea 0x20(%rax), %rax
+ cmp %rax, %rbp
+ ja .Lxts_dec_bzero
+
+ lea (%rbp),%rsp # restore %rsp
+___
+$code.=<<___ if ($win64);
+ movaps 0x40(%rbp), %xmm6
+ movaps 0x50(%rbp), %xmm7
+ movaps 0x60(%rbp), %xmm8
+ movaps 0x70(%rbp), %xmm9
+ movaps 0x80(%rbp), %xmm10
+ movaps 0x90(%rbp), %xmm11
+ movaps 0xa0(%rbp), %xmm12
+ movaps 0xb0(%rbp), %xmm13
+ movaps 0xc0(%rbp), %xmm14
+ movaps 0xd0(%rbp), %xmm15
+ lea 0xa0(%rbp), %rsp
+___
+$code.=<<___;
+ mov 0x48(%rsp), %r15
+ mov 0x50(%rsp), %r14
+ mov 0x58(%rsp), %r13
+ mov 0x60(%rsp), %r12
+ mov 0x68(%rsp), %rbx
+ mov 0x70(%rsp), %rax
+ lea 0x78(%rsp), %rsp
+ mov %rax, %rbp
+.Lxts_dec_epilogue:
+ ret
+.size bsaes_xts_decrypt,.-bsaes_xts_decrypt
+___
+}
+$code.=<<___;
+.type _bsaes_const,\@object
+.align 64
+_bsaes_const:
+.LM0ISR: # InvShiftRows constants
+ .quad 0x0a0e0206070b0f03, 0x0004080c0d010509
+.LISRM0:
+ .quad 0x01040b0e0205080f, 0x0306090c00070a0d
+.LISR:
+ .quad 0x0504070602010003, 0x0f0e0d0c080b0a09
+.LBS0: # bit-slice constants
+ .quad 0x5555555555555555, 0x5555555555555555
+.LBS1:
+ .quad 0x3333333333333333, 0x3333333333333333
+.LBS2:
+ .quad 0x0f0f0f0f0f0f0f0f, 0x0f0f0f0f0f0f0f0f
+.LSR: # shiftrows constants
+ .quad 0x0504070600030201, 0x0f0e0d0c0a09080b
+.LSRM0:
+ .quad 0x0304090e00050a0f, 0x01060b0c0207080d
+.LM0SR:
+ .quad 0x0a0e02060f03070b, 0x0004080c05090d01
+.LSWPUP: # byte-swap upper dword
+ .quad 0x0706050403020100, 0x0c0d0e0f0b0a0908
+.LSWPUPM0SR:
+ .quad 0x0a0d02060c03070b, 0x0004080f05090e01
+.LADD1: # counter increment constants
+ .quad 0x0000000000000000, 0x0000000100000000
+.LADD2:
+ .quad 0x0000000000000000, 0x0000000200000000
+.LADD3:
+ .quad 0x0000000000000000, 0x0000000300000000
+.LADD4:
+ .quad 0x0000000000000000, 0x0000000400000000
+.LADD5:
+ .quad 0x0000000000000000, 0x0000000500000000
+.LADD6:
+ .quad 0x0000000000000000, 0x0000000600000000
+.LADD7:
+ .quad 0x0000000000000000, 0x0000000700000000
+.LADD8:
+ .quad 0x0000000000000000, 0x0000000800000000
+.Lxts_magic:
+ .long 0x87,0,1,0
+.Lmasks:
+ .quad 0x0101010101010101, 0x0101010101010101
+ .quad 0x0202020202020202, 0x0202020202020202
+ .quad 0x0404040404040404, 0x0404040404040404
+ .quad 0x0808080808080808, 0x0808080808080808
+.LM0:
+ .quad 0x02060a0e03070b0f, 0x0004080c0105090d
+.L63:
+ .quad 0x6363636363636363, 0x6363636363636363
+.asciz "Bit-sliced AES for x86_64/SSSE3, Emilia Käsper, Peter Schwabe, Andy Polyakov"
+.align 64
+.size _bsaes_const,.-_bsaes_const
+___
+
+# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame,
+# CONTEXT *context,DISPATCHER_CONTEXT *disp)
+if ($win64) {
+$rec="%rcx";
+$frame="%rdx";
+$context="%r8";
+$disp="%r9";
+
+$code.=<<___;
+.extern __imp_RtlVirtualUnwind
+.type se_handler,\@abi-omnipotent
+.align 16
+se_handler:
+ push %rsi
+ push %rdi
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+ pushfq
+ sub \$64,%rsp
+
+ mov 120($context),%rax # pull context->Rax
+ mov 248($context),%rbx # pull context->Rip
+
+ mov 8($disp),%rsi # disp->ImageBase
+ mov 56($disp),%r11 # disp->HandlerData
+
+ mov 0(%r11),%r10d # HandlerData[0]
+ lea (%rsi,%r10),%r10 # prologue label
+ cmp %r10,%rbx # context->Rip<prologue label
+ jb .Lin_prologue
+
+ mov 152($context),%rax # pull context->Rsp
+
+ mov 4(%r11),%r10d # HandlerData[1]
+ lea (%rsi,%r10),%r10 # epilogue label
+ cmp %r10,%rbx # context->Rip>=epilogue label
+ jae .Lin_prologue
+
+ mov 160($context),%rax # pull context->Rbp
+
+ lea 0x40(%rax),%rsi # %xmm save area
+ lea 512($context),%rdi # &context.Xmm6
+ mov \$20,%ecx # 10*sizeof(%xmm0)/sizeof(%rax)
+ .long 0xa548f3fc # cld; rep movsq
+ lea 0xa0(%rax),%rax # adjust stack pointer
+
+ mov 0x70(%rax),%rbp
+ mov 0x68(%rax),%rbx
+ mov 0x60(%rax),%r12
+ mov 0x58(%rax),%r13
+ mov 0x50(%rax),%r14
+ mov 0x48(%rax),%r15
+ lea 0x78(%rax),%rax # adjust stack pointer
+ mov %rbx,144($context) # restore context->Rbx
+ mov %rbp,160($context) # restore context->Rbp
+ mov %r12,216($context) # restore context->R12
+ mov %r13,224($context) # restore context->R13
+ mov %r14,232($context) # restore context->R14
+ mov %r15,240($context) # restore context->R15
+
+.Lin_prologue:
+ mov %rax,152($context) # restore context->Rsp
+
+ mov 40($disp),%rdi # disp->ContextRecord
+ mov $context,%rsi # context
+ mov \$`1232/8`,%ecx # sizeof(CONTEXT)
+ .long 0xa548f3fc # cld; rep movsq
+
+ mov $disp,%rsi
+ xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER
+ mov 8(%rsi),%rdx # arg2, disp->ImageBase
+ mov 0(%rsi),%r8 # arg3, disp->ControlPc
+ mov 16(%rsi),%r9 # arg4, disp->FunctionEntry
+ mov 40(%rsi),%r10 # disp->ContextRecord
+ lea 56(%rsi),%r11 # &disp->HandlerData
+ lea 24(%rsi),%r12 # &disp->EstablisherFrame
+ mov %r10,32(%rsp) # arg5
+ mov %r11,40(%rsp) # arg6
+ mov %r12,48(%rsp) # arg7
+ mov %rcx,56(%rsp) # arg8, (NULL)
+ call *__imp_RtlVirtualUnwind(%rip)
+
+ mov \$1,%eax # ExceptionContinueSearch
+ add \$64,%rsp
+ popfq
+ pop %r15
+ pop %r14
+ pop %r13
+ pop %r12
+ pop %rbp
+ pop %rbx
+ pop %rdi
+ pop %rsi
+ ret
+.size se_handler,.-se_handler
+
+.section .pdata
+.align 4
+___
+$code.=<<___ if ($ecb);
+ .rva .Lecb_enc_prologue
+ .rva .Lecb_enc_epilogue
+ .rva .Lecb_enc_info
+
+ .rva .Lecb_dec_prologue
+ .rva .Lecb_dec_epilogue
+ .rva .Lecb_dec_info
+___
+$code.=<<___;
+ .rva .Lcbc_dec_prologue
+ .rva .Lcbc_dec_epilogue
+ .rva .Lcbc_dec_info
+
+ .rva .Lctr_enc_prologue
+ .rva .Lctr_enc_epilogue
+ .rva .Lctr_enc_info
+
+ .rva .Lxts_enc_prologue
+ .rva .Lxts_enc_epilogue
+ .rva .Lxts_enc_info
+
+ .rva .Lxts_dec_prologue
+ .rva .Lxts_dec_epilogue
+ .rva .Lxts_dec_info
+
+.section .xdata
+.align 8
+___
+$code.=<<___ if ($ecb);
+.Lecb_enc_info:
+ .byte 9,0,0,0
+ .rva se_handler
+ .rva .Lecb_enc_body,.Lecb_enc_epilogue # HandlerData[]
+.Lecb_dec_info:
+ .byte 9,0,0,0
+ .rva se_handler
+ .rva .Lecb_dec_body,.Lecb_dec_epilogue # HandlerData[]
+___
+$code.=<<___;
+.Lcbc_dec_info:
+ .byte 9,0,0,0
+ .rva se_handler
+ .rva .Lcbc_dec_body,.Lcbc_dec_epilogue # HandlerData[]
+.Lctr_enc_info:
+ .byte 9,0,0,0
+ .rva se_handler
+ .rva .Lctr_enc_body,.Lctr_enc_epilogue # HandlerData[]
+.Lxts_enc_info:
+ .byte 9,0,0,0
+ .rva se_handler
+ .rva .Lxts_enc_body,.Lxts_enc_epilogue # HandlerData[]
+.Lxts_dec_info:
+ .byte 9,0,0,0
+ .rva se_handler
+ .rva .Lxts_dec_body,.Lxts_dec_epilogue # HandlerData[]
+___
+}
+
+$code =~ s/\`([^\`]*)\`/eval($1)/gem;
+
+print $code;
+
+close STDOUT;
diff --git a/src/crypto/aes/asm/vpaes-x86.pl b/src/crypto/aes/asm/vpaes-x86.pl
new file mode 100644
index 0000000..2ba149c
--- /dev/null
+++ b/src/crypto/aes/asm/vpaes-x86.pl
@@ -0,0 +1,903 @@
+#!/usr/bin/env perl
+
+######################################################################
+## Constant-time SSSE3 AES core implementation.
+## version 0.1
+##
+## By Mike Hamburg (Stanford University), 2009
+## Public domain.
+##
+## For details see http://shiftleft.org/papers/vector_aes/ and
+## http://crypto.stanford.edu/vpaes/.
+
+######################################################################
+# September 2011.
+#
+# Port vpaes-x86_64.pl as 32-bit "almost" drop-in replacement for
+# aes-586.pl. "Almost" refers to the fact that AES_cbc_encrypt
+# doesn't handle partial vectors (doesn't have to if called from
+# EVP only). "Drop-in" implies that this module doesn't share key
+# schedule structure with the original nor does it make assumption
+# about its alignment...
+#
+# Performance summary. aes-586.pl column lists large-block CBC
+# encrypt/decrypt/with-hyper-threading-off(*) results in cycles per
+# byte processed with 128-bit key, and vpaes-x86.pl column - [also
+# large-block CBC] encrypt/decrypt.
+#
+# aes-586.pl vpaes-x86.pl
+#
+# Core 2(**) 28.1/41.4/18.3 21.9/25.2(***)
+# Nehalem 27.9/40.4/18.1 10.2/11.9
+# Atom 70.7/92.1/60.1 61.1/75.4(***)
+# Silvermont 45.4/62.9/24.1 49.2/61.1(***)
+#
+# (*) "Hyper-threading" in the context refers rather to cache shared
+# among multiple cores, than to specifically Intel HTT. As vast
+# majority of contemporary cores share cache, slower code path
+# is common place. In other words "with-hyper-threading-off"
+# results are presented mostly for reference purposes.
+#
+# (**) "Core 2" refers to initial 65nm design, a.k.a. Conroe.
+#
+# (***) Less impressive improvement on Core 2 and Atom is due to slow
+# pshufb, yet it's respectable +28%/64% improvement on Core 2
+# and +15% on Atom (as implied, over "hyper-threading-safe"
+# code path).
+#
+# <appro@openssl.org>
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+push(@INC,"${dir}","${dir}../../perlasm");
+require "x86asm.pl";
+
+&asm_init($ARGV[0],"vpaes-x86.pl",$x86only = $ARGV[$#ARGV] eq "386");
+
+$PREFIX="vpaes";
+
+my ($round, $base, $magic, $key, $const, $inp, $out)=
+ ("eax", "ebx", "ecx", "edx","ebp", "esi","edi");
+
+&static_label("_vpaes_consts");
+&static_label("_vpaes_schedule_low_round");
+
+&set_label("_vpaes_consts",64);
+$k_inv=-0x30; # inv, inva
+ &data_word(0x0D080180,0x0E05060F,0x0A0B0C02,0x04070309);
+ &data_word(0x0F0B0780,0x01040A06,0x02050809,0x030D0E0C);
+
+$k_s0F=-0x10; # s0F
+ &data_word(0x0F0F0F0F,0x0F0F0F0F,0x0F0F0F0F,0x0F0F0F0F);
+
+$k_ipt=0x00; # input transform (lo, hi)
+ &data_word(0x5A2A7000,0xC2B2E898,0x52227808,0xCABAE090);
+ &data_word(0x317C4D00,0x4C01307D,0xB0FDCC81,0xCD80B1FC);
+
+$k_sb1=0x20; # sb1u, sb1t
+ &data_word(0xCB503E00,0xB19BE18F,0x142AF544,0xA5DF7A6E);
+ &data_word(0xFAE22300,0x3618D415,0x0D2ED9EF,0x3BF7CCC1);
+$k_sb2=0x40; # sb2u, sb2t
+ &data_word(0x0B712400,0xE27A93C6,0xBC982FCD,0x5EB7E955);
+ &data_word(0x0AE12900,0x69EB8840,0xAB82234A,0xC2A163C8);
+$k_sbo=0x60; # sbou, sbot
+ &data_word(0x6FBDC700,0xD0D26D17,0xC502A878,0x15AABF7A);
+ &data_word(0x5FBB6A00,0xCFE474A5,0x412B35FA,0x8E1E90D1);
+
+$k_mc_forward=0x80; # mc_forward
+ &data_word(0x00030201,0x04070605,0x080B0A09,0x0C0F0E0D);
+ &data_word(0x04070605,0x080B0A09,0x0C0F0E0D,0x00030201);
+ &data_word(0x080B0A09,0x0C0F0E0D,0x00030201,0x04070605);
+ &data_word(0x0C0F0E0D,0x00030201,0x04070605,0x080B0A09);
+
+$k_mc_backward=0xc0; # mc_backward
+ &data_word(0x02010003,0x06050407,0x0A09080B,0x0E0D0C0F);
+ &data_word(0x0E0D0C0F,0x02010003,0x06050407,0x0A09080B);
+ &data_word(0x0A09080B,0x0E0D0C0F,0x02010003,0x06050407);
+ &data_word(0x06050407,0x0A09080B,0x0E0D0C0F,0x02010003);
+
+$k_sr=0x100; # sr
+ &data_word(0x03020100,0x07060504,0x0B0A0908,0x0F0E0D0C);
+ &data_word(0x0F0A0500,0x030E0904,0x07020D08,0x0B06010C);
+ &data_word(0x0B020900,0x0F060D04,0x030A0108,0x070E050C);
+ &data_word(0x070A0D00,0x0B0E0104,0x0F020508,0x0306090C);
+
+$k_rcon=0x140; # rcon
+ &data_word(0xAF9DEEB6,0x1F8391B9,0x4D7C7D81,0x702A9808);
+
+$k_s63=0x150; # s63: all equal to 0x63 transformed
+ &data_word(0x5B5B5B5B,0x5B5B5B5B,0x5B5B5B5B,0x5B5B5B5B);
+
+$k_opt=0x160; # output transform
+ &data_word(0xD6B66000,0xFF9F4929,0xDEBE6808,0xF7974121);
+ &data_word(0x50BCEC00,0x01EDBD51,0xB05C0CE0,0xE10D5DB1);
+
+$k_deskew=0x180; # deskew tables: inverts the sbox's "skew"
+ &data_word(0x47A4E300,0x07E4A340,0x5DBEF91A,0x1DFEB95A);
+ &data_word(0x83EA6900,0x5F36B5DC,0xF49D1E77,0x2841C2AB);
+##
+## Decryption stuff
+## Key schedule constants
+##
+$k_dksd=0x1a0; # decryption key schedule: invskew x*D
+ &data_word(0xA3E44700,0xFEB91A5D,0x5A1DBEF9,0x0740E3A4);
+ &data_word(0xB5368300,0x41C277F4,0xAB289D1E,0x5FDC69EA);
+$k_dksb=0x1c0; # decryption key schedule: invskew x*B
+ &data_word(0x8550D500,0x9A4FCA1F,0x1CC94C99,0x03D65386);
+ &data_word(0xB6FC4A00,0x115BEDA7,0x7E3482C8,0xD993256F);
+$k_dkse=0x1e0; # decryption key schedule: invskew x*E + 0x63
+ &data_word(0x1FC9D600,0xD5031CCA,0x994F5086,0x53859A4C);
+ &data_word(0x4FDC7BE8,0xA2319605,0x20B31487,0xCD5EF96A);
+$k_dks9=0x200; # decryption key schedule: invskew x*9
+ &data_word(0x7ED9A700,0xB6116FC8,0x82255BFC,0x4AED9334);
+ &data_word(0x27143300,0x45765162,0xE9DAFDCE,0x8BB89FAC);
+
+##
+## Decryption stuff
+## Round function constants
+##
+$k_dipt=0x220; # decryption input transform
+ &data_word(0x0B545F00,0x0F505B04,0x114E451A,0x154A411E);
+ &data_word(0x60056500,0x86E383E6,0xF491F194,0x12771772);
+
+$k_dsb9=0x240; # decryption sbox output *9*u, *9*t
+ &data_word(0x9A86D600,0x851C0353,0x4F994CC9,0xCAD51F50);
+ &data_word(0xECD74900,0xC03B1789,0xB2FBA565,0x725E2C9E);
+$k_dsbd=0x260; # decryption sbox output *D*u, *D*t
+ &data_word(0xE6B1A200,0x7D57CCDF,0x882A4439,0xF56E9B13);
+ &data_word(0x24C6CB00,0x3CE2FAF7,0x15DEEFD3,0x2931180D);
+$k_dsbb=0x280; # decryption sbox output *B*u, *B*t
+ &data_word(0x96B44200,0xD0226492,0xB0F2D404,0x602646F6);
+ &data_word(0xCD596700,0xC19498A6,0x3255AA6B,0xF3FF0C3E);
+$k_dsbe=0x2a0; # decryption sbox output *E*u, *E*t
+ &data_word(0x26D4D000,0x46F29296,0x64B4F6B0,0x22426004);
+ &data_word(0xFFAAC100,0x0C55A6CD,0x98593E32,0x9467F36B);
+$k_dsbo=0x2c0; # decryption sbox final output
+ &data_word(0x7EF94000,0x1387EA53,0xD4943E2D,0xC7AA6DB9);
+ &data_word(0x93441D00,0x12D7560F,0xD8C58E9C,0xCA4B8159);
+&asciz ("Vector Permutation AES for x86/SSSE3, Mike Hamburg (Stanford University)");
+&align (64);
+
+&function_begin_B("_vpaes_preheat");
+ &add ($const,&DWP(0,"esp"));
+ &movdqa ("xmm7",&QWP($k_inv,$const));
+ &movdqa ("xmm6",&QWP($k_s0F,$const));
+ &ret ();
+&function_end_B("_vpaes_preheat");
+
+##
+## _aes_encrypt_core
+##
+## AES-encrypt %xmm0.
+##
+## Inputs:
+## %xmm0 = input
+## %xmm6-%xmm7 as in _vpaes_preheat
+## (%edx) = scheduled keys
+##
+## Output in %xmm0
+## Clobbers %xmm1-%xmm5, %eax, %ebx, %ecx, %edx
+##
+##
+&function_begin_B("_vpaes_encrypt_core");
+ &mov ($magic,16);
+ &mov ($round,&DWP(240,$key));
+ &movdqa ("xmm1","xmm6")
+ &movdqa ("xmm2",&QWP($k_ipt,$const));
+ &pandn ("xmm1","xmm0");
+ &pand ("xmm0","xmm6");
+ &movdqu ("xmm5",&QWP(0,$key));
+ &pshufb ("xmm2","xmm0");
+ &movdqa ("xmm0",&QWP($k_ipt+16,$const));
+ &pxor ("xmm2","xmm5");
+ &psrld ("xmm1",4);
+ &add ($key,16);
+ &pshufb ("xmm0","xmm1");
+ &lea ($base,&DWP($k_mc_backward,$const));
+ &pxor ("xmm0","xmm2");
+ &jmp (&label("enc_entry"));
+
+
+&set_label("enc_loop",16);
+ # middle of middle round
+ &movdqa ("xmm4",&QWP($k_sb1,$const)); # 4 : sb1u
+ &movdqa ("xmm0",&QWP($k_sb1+16,$const));# 0 : sb1t
+ &pshufb ("xmm4","xmm2"); # 4 = sb1u
+ &pshufb ("xmm0","xmm3"); # 0 = sb1t
+ &pxor ("xmm4","xmm5"); # 4 = sb1u + k
+ &movdqa ("xmm5",&QWP($k_sb2,$const)); # 4 : sb2u
+ &pxor ("xmm0","xmm4"); # 0 = A
+ &movdqa ("xmm1",&QWP(-0x40,$base,$magic));# .Lk_mc_forward[]
+ &pshufb ("xmm5","xmm2"); # 4 = sb2u
+ &movdqa ("xmm2",&QWP($k_sb2+16,$const));# 2 : sb2t
+ &movdqa ("xmm4",&QWP(0,$base,$magic)); # .Lk_mc_backward[]
+ &pshufb ("xmm2","xmm3"); # 2 = sb2t
+ &movdqa ("xmm3","xmm0"); # 3 = A
+ &pxor ("xmm2","xmm5"); # 2 = 2A
+ &pshufb ("xmm0","xmm1"); # 0 = B
+ &add ($key,16); # next key
+ &pxor ("xmm0","xmm2"); # 0 = 2A+B
+ &pshufb ("xmm3","xmm4"); # 3 = D
+ &add ($magic,16); # next mc
+ &pxor ("xmm3","xmm0"); # 3 = 2A+B+D
+ &pshufb ("xmm0","xmm1"); # 0 = 2B+C
+ &and ($magic,0x30); # ... mod 4
+ &sub ($round,1); # nr--
+ &pxor ("xmm0","xmm3"); # 0 = 2A+3B+C+D
+
+&set_label("enc_entry");
+ # top of round
+ &movdqa ("xmm1","xmm6"); # 1 : i
+ &movdqa ("xmm5",&QWP($k_inv+16,$const));# 2 : a/k
+ &pandn ("xmm1","xmm0"); # 1 = i<<4
+ &psrld ("xmm1",4); # 1 = i
+ &pand ("xmm0","xmm6"); # 0 = k
+ &pshufb ("xmm5","xmm0"); # 2 = a/k
+ &movdqa ("xmm3","xmm7"); # 3 : 1/i
+ &pxor ("xmm0","xmm1"); # 0 = j
+ &pshufb ("xmm3","xmm1"); # 3 = 1/i
+ &movdqa ("xmm4","xmm7"); # 4 : 1/j
+ &pxor ("xmm3","xmm5"); # 3 = iak = 1/i + a/k
+ &pshufb ("xmm4","xmm0"); # 4 = 1/j
+ &movdqa ("xmm2","xmm7"); # 2 : 1/iak
+ &pxor ("xmm4","xmm5"); # 4 = jak = 1/j + a/k
+ &pshufb ("xmm2","xmm3"); # 2 = 1/iak
+ &movdqa ("xmm3","xmm7"); # 3 : 1/jak
+ &pxor ("xmm2","xmm0"); # 2 = io
+ &pshufb ("xmm3","xmm4"); # 3 = 1/jak
+ &movdqu ("xmm5",&QWP(0,$key));
+ &pxor ("xmm3","xmm1"); # 3 = jo
+ &jnz (&label("enc_loop"));
+
+ # middle of last round
+ &movdqa ("xmm4",&QWP($k_sbo,$const)); # 3 : sbou .Lk_sbo
+ &movdqa ("xmm0",&QWP($k_sbo+16,$const));# 3 : sbot .Lk_sbo+16
+ &pshufb ("xmm4","xmm2"); # 4 = sbou
+ &pxor ("xmm4","xmm5"); # 4 = sb1u + k
+ &pshufb ("xmm0","xmm3"); # 0 = sb1t
+ &movdqa ("xmm1",&QWP(0x40,$base,$magic));# .Lk_sr[]
+ &pxor ("xmm0","xmm4"); # 0 = A
+ &pshufb ("xmm0","xmm1");
+ &ret ();
+&function_end_B("_vpaes_encrypt_core");
+
+##
+## Decryption core
+##
+## Same API as encryption core.
+##
+&function_begin_B("_vpaes_decrypt_core");
+ &lea ($base,&DWP($k_dsbd,$const));
+ &mov ($round,&DWP(240,$key));
+ &movdqa ("xmm1","xmm6");
+ &movdqa ("xmm2",&QWP($k_dipt-$k_dsbd,$base));
+ &pandn ("xmm1","xmm0");
+ &mov ($magic,$round);
+ &psrld ("xmm1",4)
+ &movdqu ("xmm5",&QWP(0,$key));
+ &shl ($magic,4);
+ &pand ("xmm0","xmm6");
+ &pshufb ("xmm2","xmm0");
+ &movdqa ("xmm0",&QWP($k_dipt-$k_dsbd+16,$base));
+ &xor ($magic,0x30);
+ &pshufb ("xmm0","xmm1");
+ &and ($magic,0x30);
+ &pxor ("xmm2","xmm5");
+ &movdqa ("xmm5",&QWP($k_mc_forward+48,$const));
+ &pxor ("xmm0","xmm2");
+ &add ($key,16);
+ &lea ($magic,&DWP($k_sr-$k_dsbd,$base,$magic));
+ &jmp (&label("dec_entry"));
+
+&set_label("dec_loop",16);
+##
+## Inverse mix columns
+##
+ &movdqa ("xmm4",&QWP(-0x20,$base)); # 4 : sb9u
+ &movdqa ("xmm1",&QWP(-0x10,$base)); # 0 : sb9t
+ &pshufb ("xmm4","xmm2"); # 4 = sb9u
+ &pshufb ("xmm1","xmm3"); # 0 = sb9t
+ &pxor ("xmm0","xmm4");
+ &movdqa ("xmm4",&QWP(0,$base)); # 4 : sbdu
+ &pxor ("xmm0","xmm1"); # 0 = ch
+ &movdqa ("xmm1",&QWP(0x10,$base)); # 0 : sbdt
+
+ &pshufb ("xmm4","xmm2"); # 4 = sbdu
+ &pshufb ("xmm0","xmm5"); # MC ch
+ &pshufb ("xmm1","xmm3"); # 0 = sbdt
+ &pxor ("xmm0","xmm4"); # 4 = ch
+ &movdqa ("xmm4",&QWP(0x20,$base)); # 4 : sbbu
+ &pxor ("xmm0","xmm1"); # 0 = ch
+ &movdqa ("xmm1",&QWP(0x30,$base)); # 0 : sbbt
+
+ &pshufb ("xmm4","xmm2"); # 4 = sbbu
+ &pshufb ("xmm0","xmm5"); # MC ch
+ &pshufb ("xmm1","xmm3"); # 0 = sbbt
+ &pxor ("xmm0","xmm4"); # 4 = ch
+ &movdqa ("xmm4",&QWP(0x40,$base)); # 4 : sbeu
+ &pxor ("xmm0","xmm1"); # 0 = ch
+ &movdqa ("xmm1",&QWP(0x50,$base)); # 0 : sbet
+
+ &pshufb ("xmm4","xmm2"); # 4 = sbeu
+ &pshufb ("xmm0","xmm5"); # MC ch
+ &pshufb ("xmm1","xmm3"); # 0 = sbet
+ &pxor ("xmm0","xmm4"); # 4 = ch
+ &add ($key,16); # next round key
+ &palignr("xmm5","xmm5",12);
+ &pxor ("xmm0","xmm1"); # 0 = ch
+ &sub ($round,1); # nr--
+
+&set_label("dec_entry");
+ # top of round
+ &movdqa ("xmm1","xmm6"); # 1 : i
+ &movdqa ("xmm2",&QWP($k_inv+16,$const));# 2 : a/k
+ &pandn ("xmm1","xmm0"); # 1 = i<<4
+ &pand ("xmm0","xmm6"); # 0 = k
+ &psrld ("xmm1",4); # 1 = i
+ &pshufb ("xmm2","xmm0"); # 2 = a/k
+ &movdqa ("xmm3","xmm7"); # 3 : 1/i
+ &pxor ("xmm0","xmm1"); # 0 = j
+ &pshufb ("xmm3","xmm1"); # 3 = 1/i
+ &movdqa ("xmm4","xmm7"); # 4 : 1/j
+ &pxor ("xmm3","xmm2"); # 3 = iak = 1/i + a/k
+ &pshufb ("xmm4","xmm0"); # 4 = 1/j
+ &pxor ("xmm4","xmm2"); # 4 = jak = 1/j + a/k
+ &movdqa ("xmm2","xmm7"); # 2 : 1/iak
+ &pshufb ("xmm2","xmm3"); # 2 = 1/iak
+ &movdqa ("xmm3","xmm7"); # 3 : 1/jak
+ &pxor ("xmm2","xmm0"); # 2 = io
+ &pshufb ("xmm3","xmm4"); # 3 = 1/jak
+ &movdqu ("xmm0",&QWP(0,$key));
+ &pxor ("xmm3","xmm1"); # 3 = jo
+ &jnz (&label("dec_loop"));
+
+ # middle of last round
+ &movdqa ("xmm4",&QWP(0x60,$base)); # 3 : sbou
+ &pshufb ("xmm4","xmm2"); # 4 = sbou
+ &pxor ("xmm4","xmm0"); # 4 = sb1u + k
+ &movdqa ("xmm0",&QWP(0x70,$base)); # 0 : sbot
+ &movdqa ("xmm2",&QWP(0,$magic));
+ &pshufb ("xmm0","xmm3"); # 0 = sb1t
+ &pxor ("xmm0","xmm4"); # 0 = A
+ &pshufb ("xmm0","xmm2");
+ &ret ();
+&function_end_B("_vpaes_decrypt_core");
+
+########################################################
+## ##
+## AES key schedule ##
+## ##
+########################################################
+&function_begin_B("_vpaes_schedule_core");
+ &add ($const,&DWP(0,"esp"));
+ &movdqu ("xmm0",&QWP(0,$inp)); # load key (unaligned)
+ &movdqa ("xmm2",&QWP($k_rcon,$const)); # load rcon
+
+ # input transform
+ &movdqa ("xmm3","xmm0");
+ &lea ($base,&DWP($k_ipt,$const));
+ &movdqa (&QWP(4,"esp"),"xmm2"); # xmm8
+ &call ("_vpaes_schedule_transform");
+ &movdqa ("xmm7","xmm0");
+
+ &test ($out,$out);
+ &jnz (&label("schedule_am_decrypting"));
+
+ # encrypting, output zeroth round key after transform
+ &movdqu (&QWP(0,$key),"xmm0");
+ &jmp (&label("schedule_go"));
+
+&set_label("schedule_am_decrypting");
+ # decrypting, output zeroth round key after shiftrows
+ &movdqa ("xmm1",&QWP($k_sr,$const,$magic));
+ &pshufb ("xmm3","xmm1");
+ &movdqu (&QWP(0,$key),"xmm3");
+ &xor ($magic,0x30);
+
+&set_label("schedule_go");
+ &cmp ($round,192);
+ &ja (&label("schedule_256"));
+ &je (&label("schedule_192"));
+ # 128: fall though
+
+##
+## .schedule_128
+##
+## 128-bit specific part of key schedule.
+##
+## This schedule is really simple, because all its parts
+## are accomplished by the subroutines.
+##
+&set_label("schedule_128");
+ &mov ($round,10);
+
+&set_label("loop_schedule_128");
+ &call ("_vpaes_schedule_round");
+ &dec ($round);
+ &jz (&label("schedule_mangle_last"));
+ &call ("_vpaes_schedule_mangle"); # write output
+ &jmp (&label("loop_schedule_128"));
+
+##
+## .aes_schedule_192
+##
+## 192-bit specific part of key schedule.
+##
+## The main body of this schedule is the same as the 128-bit
+## schedule, but with more smearing. The long, high side is
+## stored in %xmm7 as before, and the short, low side is in
+## the high bits of %xmm6.
+##
+## This schedule is somewhat nastier, however, because each
+## round produces 192 bits of key material, or 1.5 round keys.
+## Therefore, on each cycle we do 2 rounds and produce 3 round
+## keys.
+##
+&set_label("schedule_192",16);
+ &movdqu ("xmm0",&QWP(8,$inp)); # load key part 2 (very unaligned)
+ &call ("_vpaes_schedule_transform"); # input transform
+ &movdqa ("xmm6","xmm0"); # save short part
+ &pxor ("xmm4","xmm4"); # clear 4
+ &movhlps("xmm6","xmm4"); # clobber low side with zeros
+ &mov ($round,4);
+
+&set_label("loop_schedule_192");
+ &call ("_vpaes_schedule_round");
+ &palignr("xmm0","xmm6",8);
+ &call ("_vpaes_schedule_mangle"); # save key n
+ &call ("_vpaes_schedule_192_smear");
+ &call ("_vpaes_schedule_mangle"); # save key n+1
+ &call ("_vpaes_schedule_round");
+ &dec ($round);
+ &jz (&label("schedule_mangle_last"));
+ &call ("_vpaes_schedule_mangle"); # save key n+2
+ &call ("_vpaes_schedule_192_smear");
+ &jmp (&label("loop_schedule_192"));
+
+##
+## .aes_schedule_256
+##
+## 256-bit specific part of key schedule.
+##
+## The structure here is very similar to the 128-bit
+## schedule, but with an additional "low side" in
+## %xmm6. The low side's rounds are the same as the
+## high side's, except no rcon and no rotation.
+##
+&set_label("schedule_256",16);
+ &movdqu ("xmm0",&QWP(16,$inp)); # load key part 2 (unaligned)
+ &call ("_vpaes_schedule_transform"); # input transform
+ &mov ($round,7);
+
+&set_label("loop_schedule_256");
+ &call ("_vpaes_schedule_mangle"); # output low result
+ &movdqa ("xmm6","xmm0"); # save cur_lo in xmm6
+
+ # high round
+ &call ("_vpaes_schedule_round");
+ &dec ($round);
+ &jz (&label("schedule_mangle_last"));
+ &call ("_vpaes_schedule_mangle");
+
+ # low round. swap xmm7 and xmm6
+ &pshufd ("xmm0","xmm0",0xFF);
+ &movdqa (&QWP(20,"esp"),"xmm7");
+ &movdqa ("xmm7","xmm6");
+ &call ("_vpaes_schedule_low_round");
+ &movdqa ("xmm7",&QWP(20,"esp"));
+
+ &jmp (&label("loop_schedule_256"));
+
+##
+## .aes_schedule_mangle_last
+##
+## Mangler for last round of key schedule
+## Mangles %xmm0
+## when encrypting, outputs out(%xmm0) ^ 63
+## when decrypting, outputs unskew(%xmm0)
+##
+## Always called right before return... jumps to cleanup and exits
+##
+&set_label("schedule_mangle_last",16);
+ # schedule last round key from xmm0
+ &lea ($base,&DWP($k_deskew,$const));
+ &test ($out,$out);
+ &jnz (&label("schedule_mangle_last_dec"));
+
+ # encrypting
+ &movdqa ("xmm1",&QWP($k_sr,$const,$magic));
+ &pshufb ("xmm0","xmm1"); # output permute
+ &lea ($base,&DWP($k_opt,$const)); # prepare to output transform
+ &add ($key,32);
+
+&set_label("schedule_mangle_last_dec");
+ &add ($key,-16);
+ &pxor ("xmm0",&QWP($k_s63,$const));
+ &call ("_vpaes_schedule_transform"); # output transform
+ &movdqu (&QWP(0,$key),"xmm0"); # save last key
+
+ # cleanup
+ &pxor ("xmm0","xmm0");
+ &pxor ("xmm1","xmm1");
+ &pxor ("xmm2","xmm2");
+ &pxor ("xmm3","xmm3");
+ &pxor ("xmm4","xmm4");
+ &pxor ("xmm5","xmm5");
+ &pxor ("xmm6","xmm6");
+ &pxor ("xmm7","xmm7");
+ &ret ();
+&function_end_B("_vpaes_schedule_core");
+
+##
+## .aes_schedule_192_smear
+##
+## Smear the short, low side in the 192-bit key schedule.
+##
+## Inputs:
+## %xmm7: high side, b a x y
+## %xmm6: low side, d c 0 0
+## %xmm13: 0
+##
+## Outputs:
+## %xmm6: b+c+d b+c 0 0
+## %xmm0: b+c+d b+c b a
+##
+&function_begin_B("_vpaes_schedule_192_smear");
+ &pshufd ("xmm1","xmm6",0x80); # d c 0 0 -> c 0 0 0
+ &pshufd ("xmm0","xmm7",0xFE); # b a _ _ -> b b b a
+ &pxor ("xmm6","xmm1"); # -> c+d c 0 0
+ &pxor ("xmm1","xmm1");
+ &pxor ("xmm6","xmm0"); # -> b+c+d b+c b a
+ &movdqa ("xmm0","xmm6");
+ &movhlps("xmm6","xmm1"); # clobber low side with zeros
+ &ret ();
+&function_end_B("_vpaes_schedule_192_smear");
+
+##
+## .aes_schedule_round
+##
+## Runs one main round of the key schedule on %xmm0, %xmm7
+##
+## Specifically, runs subbytes on the high dword of %xmm0
+## then rotates it by one byte and xors into the low dword of
+## %xmm7.
+##
+## Adds rcon from low byte of %xmm8, then rotates %xmm8 for
+## next rcon.
+##
+## Smears the dwords of %xmm7 by xoring the low into the
+## second low, result into third, result into highest.
+##
+## Returns results in %xmm7 = %xmm0.
+## Clobbers %xmm1-%xmm5.
+##
+&function_begin_B("_vpaes_schedule_round");
+ # extract rcon from xmm8
+ &movdqa ("xmm2",&QWP(8,"esp")); # xmm8
+ &pxor ("xmm1","xmm1");
+ &palignr("xmm1","xmm2",15);
+ &palignr("xmm2","xmm2",15);
+ &pxor ("xmm7","xmm1");
+
+ # rotate
+ &pshufd ("xmm0","xmm0",0xFF);
+ &palignr("xmm0","xmm0",1);
+
+ # fall through...
+ &movdqa (&QWP(8,"esp"),"xmm2"); # xmm8
+
+ # low round: same as high round, but no rotation and no rcon.
+&set_label("_vpaes_schedule_low_round");
+ # smear xmm7
+ &movdqa ("xmm1","xmm7");
+ &pslldq ("xmm7",4);
+ &pxor ("xmm7","xmm1");
+ &movdqa ("xmm1","xmm7");
+ &pslldq ("xmm7",8);
+ &pxor ("xmm7","xmm1");
+ &pxor ("xmm7",&QWP($k_s63,$const));
+
+ # subbyte
+ &movdqa ("xmm4",&QWP($k_s0F,$const));
+ &movdqa ("xmm5",&QWP($k_inv,$const)); # 4 : 1/j
+ &movdqa ("xmm1","xmm4");
+ &pandn ("xmm1","xmm0");
+ &psrld ("xmm1",4); # 1 = i
+ &pand ("xmm0","xmm4"); # 0 = k
+ &movdqa ("xmm2",&QWP($k_inv+16,$const));# 2 : a/k
+ &pshufb ("xmm2","xmm0"); # 2 = a/k
+ &pxor ("xmm0","xmm1"); # 0 = j
+ &movdqa ("xmm3","xmm5"); # 3 : 1/i
+ &pshufb ("xmm3","xmm1"); # 3 = 1/i
+ &pxor ("xmm3","xmm2"); # 3 = iak = 1/i + a/k
+ &movdqa ("xmm4","xmm5"); # 4 : 1/j
+ &pshufb ("xmm4","xmm0"); # 4 = 1/j
+ &pxor ("xmm4","xmm2"); # 4 = jak = 1/j + a/k
+ &movdqa ("xmm2","xmm5"); # 2 : 1/iak
+ &pshufb ("xmm2","xmm3"); # 2 = 1/iak
+ &pxor ("xmm2","xmm0"); # 2 = io
+ &movdqa ("xmm3","xmm5"); # 3 : 1/jak
+ &pshufb ("xmm3","xmm4"); # 3 = 1/jak
+ &pxor ("xmm3","xmm1"); # 3 = jo
+ &movdqa ("xmm4",&QWP($k_sb1,$const)); # 4 : sbou
+ &pshufb ("xmm4","xmm2"); # 4 = sbou
+ &movdqa ("xmm0",&QWP($k_sb1+16,$const));# 0 : sbot
+ &pshufb ("xmm0","xmm3"); # 0 = sb1t
+ &pxor ("xmm0","xmm4"); # 0 = sbox output
+
+ # add in smeared stuff
+ &pxor ("xmm0","xmm7");
+ &movdqa ("xmm7","xmm0");
+ &ret ();
+&function_end_B("_vpaes_schedule_round");
+
+##
+## .aes_schedule_transform
+##
+## Linear-transform %xmm0 according to tables at (%ebx)
+##
+## Output in %xmm0
+## Clobbers %xmm1, %xmm2
+##
+&function_begin_B("_vpaes_schedule_transform");
+ &movdqa ("xmm2",&QWP($k_s0F,$const));
+ &movdqa ("xmm1","xmm2");
+ &pandn ("xmm1","xmm0");
+ &psrld ("xmm1",4);
+ &pand ("xmm0","xmm2");
+ &movdqa ("xmm2",&QWP(0,$base));
+ &pshufb ("xmm2","xmm0");
+ &movdqa ("xmm0",&QWP(16,$base));
+ &pshufb ("xmm0","xmm1");
+ &pxor ("xmm0","xmm2");
+ &ret ();
+&function_end_B("_vpaes_schedule_transform");
+
+##
+## .aes_schedule_mangle
+##
+## Mangle xmm0 from (basis-transformed) standard version
+## to our version.
+##
+## On encrypt,
+## xor with 0x63
+## multiply by circulant 0,1,1,1
+## apply shiftrows transform
+##
+## On decrypt,
+## xor with 0x63
+## multiply by "inverse mixcolumns" circulant E,B,D,9
+## deskew
+## apply shiftrows transform
+##
+##
+## Writes out to (%edx), and increments or decrements it
+## Keeps track of round number mod 4 in %ecx
+## Preserves xmm0
+## Clobbers xmm1-xmm5
+##
+&function_begin_B("_vpaes_schedule_mangle");
+ &movdqa ("xmm4","xmm0"); # save xmm0 for later
+ &movdqa ("xmm5",&QWP($k_mc_forward,$const));
+ &test ($out,$out);
+ &jnz (&label("schedule_mangle_dec"));
+
+ # encrypting
+ &add ($key,16);
+ &pxor ("xmm4",&QWP($k_s63,$const));
+ &pshufb ("xmm4","xmm5");
+ &movdqa ("xmm3","xmm4");
+ &pshufb ("xmm4","xmm5");
+ &pxor ("xmm3","xmm4");
+ &pshufb ("xmm4","xmm5");
+ &pxor ("xmm3","xmm4");
+
+ &jmp (&label("schedule_mangle_both"));
+
+&set_label("schedule_mangle_dec",16);
+ # inverse mix columns
+ &movdqa ("xmm2",&QWP($k_s0F,$const));
+ &lea ($inp,&DWP($k_dksd,$const));
+ &movdqa ("xmm1","xmm2");
+ &pandn ("xmm1","xmm4");
+ &psrld ("xmm1",4); # 1 = hi
+ &pand ("xmm4","xmm2"); # 4 = lo
+
+ &movdqa ("xmm2",&QWP(0,$inp));
+ &pshufb ("xmm2","xmm4");
+ &movdqa ("xmm3",&QWP(0x10,$inp));
+ &pshufb ("xmm3","xmm1");
+ &pxor ("xmm3","xmm2");
+ &pshufb ("xmm3","xmm5");
+
+ &movdqa ("xmm2",&QWP(0x20,$inp));
+ &pshufb ("xmm2","xmm4");
+ &pxor ("xmm2","xmm3");
+ &movdqa ("xmm3",&QWP(0x30,$inp));
+ &pshufb ("xmm3","xmm1");
+ &pxor ("xmm3","xmm2");
+ &pshufb ("xmm3","xmm5");
+
+ &movdqa ("xmm2",&QWP(0x40,$inp));
+ &pshufb ("xmm2","xmm4");
+ &pxor ("xmm2","xmm3");
+ &movdqa ("xmm3",&QWP(0x50,$inp));
+ &pshufb ("xmm3","xmm1");
+ &pxor ("xmm3","xmm2");
+ &pshufb ("xmm3","xmm5");
+
+ &movdqa ("xmm2",&QWP(0x60,$inp));
+ &pshufb ("xmm2","xmm4");
+ &pxor ("xmm2","xmm3");
+ &movdqa ("xmm3",&QWP(0x70,$inp));
+ &pshufb ("xmm3","xmm1");
+ &pxor ("xmm3","xmm2");
+
+ &add ($key,-16);
+
+&set_label("schedule_mangle_both");
+ &movdqa ("xmm1",&QWP($k_sr,$const,$magic));
+ &pshufb ("xmm3","xmm1");
+ &add ($magic,-16);
+ &and ($magic,0x30);
+ &movdqu (&QWP(0,$key),"xmm3");
+ &ret ();
+&function_end_B("_vpaes_schedule_mangle");
+
+#
+# Interface to OpenSSL
+#
+&function_begin("${PREFIX}_set_encrypt_key");
+ &mov ($inp,&wparam(0)); # inp
+ &lea ($base,&DWP(-56,"esp"));
+ &mov ($round,&wparam(1)); # bits
+ &and ($base,-16);
+ &mov ($key,&wparam(2)); # key
+ &xchg ($base,"esp"); # alloca
+ &mov (&DWP(48,"esp"),$base);
+
+ &mov ($base,$round);
+ &shr ($base,5);
+ &add ($base,5);
+ &mov (&DWP(240,$key),$base); # AES_KEY->rounds = nbits/32+5;
+ &mov ($magic,0x30);
+ &mov ($out,0);
+
+ &lea ($const,&DWP(&label("_vpaes_consts")."+0x30-".&label("pic_point")));
+ &call ("_vpaes_schedule_core");
+&set_label("pic_point");
+
+ &mov ("esp",&DWP(48,"esp"));
+ &xor ("eax","eax");
+&function_end("${PREFIX}_set_encrypt_key");
+
+&function_begin("${PREFIX}_set_decrypt_key");
+ &mov ($inp,&wparam(0)); # inp
+ &lea ($base,&DWP(-56,"esp"));
+ &mov ($round,&wparam(1)); # bits
+ &and ($base,-16);
+ &mov ($key,&wparam(2)); # key
+ &xchg ($base,"esp"); # alloca
+ &mov (&DWP(48,"esp"),$base);
+
+ &mov ($base,$round);
+ &shr ($base,5);
+ &add ($base,5);
+ &mov (&DWP(240,$key),$base); # AES_KEY->rounds = nbits/32+5;
+ &shl ($base,4);
+ &lea ($key,&DWP(16,$key,$base));
+
+ &mov ($out,1);
+ &mov ($magic,$round);
+ &shr ($magic,1);
+ &and ($magic,32);
+ &xor ($magic,32); # nbist==192?0:32;
+
+ &lea ($const,&DWP(&label("_vpaes_consts")."+0x30-".&label("pic_point")));
+ &call ("_vpaes_schedule_core");
+&set_label("pic_point");
+
+ &mov ("esp",&DWP(48,"esp"));
+ &xor ("eax","eax");
+&function_end("${PREFIX}_set_decrypt_key");
+
+&function_begin("${PREFIX}_encrypt");
+ &lea ($const,&DWP(&label("_vpaes_consts")."+0x30-".&label("pic_point")));
+ &call ("_vpaes_preheat");
+&set_label("pic_point");
+ &mov ($inp,&wparam(0)); # inp
+ &lea ($base,&DWP(-56,"esp"));
+ &mov ($out,&wparam(1)); # out
+ &and ($base,-16);
+ &mov ($key,&wparam(2)); # key
+ &xchg ($base,"esp"); # alloca
+ &mov (&DWP(48,"esp"),$base);
+
+ &movdqu ("xmm0",&QWP(0,$inp));
+ &call ("_vpaes_encrypt_core");
+ &movdqu (&QWP(0,$out),"xmm0");
+
+ &mov ("esp",&DWP(48,"esp"));
+&function_end("${PREFIX}_encrypt");
+
+&function_begin("${PREFIX}_decrypt");
+ &lea ($const,&DWP(&label("_vpaes_consts")."+0x30-".&label("pic_point")));
+ &call ("_vpaes_preheat");
+&set_label("pic_point");
+ &mov ($inp,&wparam(0)); # inp
+ &lea ($base,&DWP(-56,"esp"));
+ &mov ($out,&wparam(1)); # out
+ &and ($base,-16);
+ &mov ($key,&wparam(2)); # key
+ &xchg ($base,"esp"); # alloca
+ &mov (&DWP(48,"esp"),$base);
+
+ &movdqu ("xmm0",&QWP(0,$inp));
+ &call ("_vpaes_decrypt_core");
+ &movdqu (&QWP(0,$out),"xmm0");
+
+ &mov ("esp",&DWP(48,"esp"));
+&function_end("${PREFIX}_decrypt");
+
+&function_begin("${PREFIX}_cbc_encrypt");
+ &mov ($inp,&wparam(0)); # inp
+ &mov ($out,&wparam(1)); # out
+ &mov ($round,&wparam(2)); # len
+ &mov ($key,&wparam(3)); # key
+ &sub ($round,16);
+ &jc (&label("cbc_abort"));
+ &lea ($base,&DWP(-56,"esp"));
+ &mov ($const,&wparam(4)); # ivp
+ &and ($base,-16);
+ &mov ($magic,&wparam(5)); # enc
+ &xchg ($base,"esp"); # alloca
+ &movdqu ("xmm1",&QWP(0,$const)); # load IV
+ &sub ($out,$inp);
+ &mov (&DWP(48,"esp"),$base);
+
+ &mov (&DWP(0,"esp"),$out); # save out
+ &mov (&DWP(4,"esp"),$key) # save key
+ &mov (&DWP(8,"esp"),$const); # save ivp
+ &mov ($out,$round); # $out works as $len
+
+ &lea ($const,&DWP(&label("_vpaes_consts")."+0x30-".&label("pic_point")));
+ &call ("_vpaes_preheat");
+&set_label("pic_point");
+ &cmp ($magic,0);
+ &je (&label("cbc_dec_loop"));
+ &jmp (&label("cbc_enc_loop"));
+
+&set_label("cbc_enc_loop",16);
+ &movdqu ("xmm0",&QWP(0,$inp)); # load input
+ &pxor ("xmm0","xmm1"); # inp^=iv
+ &call ("_vpaes_encrypt_core");
+ &mov ($base,&DWP(0,"esp")); # restore out
+ &mov ($key,&DWP(4,"esp")); # restore key
+ &movdqa ("xmm1","xmm0");
+ &movdqu (&QWP(0,$base,$inp),"xmm0"); # write output
+ &lea ($inp,&DWP(16,$inp));
+ &sub ($out,16);
+ &jnc (&label("cbc_enc_loop"));
+ &jmp (&label("cbc_done"));
+
+&set_label("cbc_dec_loop",16);
+ &movdqu ("xmm0",&QWP(0,$inp)); # load input
+ &movdqa (&QWP(16,"esp"),"xmm1"); # save IV
+ &movdqa (&QWP(32,"esp"),"xmm0"); # save future IV
+ &call ("_vpaes_decrypt_core");
+ &mov ($base,&DWP(0,"esp")); # restore out
+ &mov ($key,&DWP(4,"esp")); # restore key
+ &pxor ("xmm0",&QWP(16,"esp")); # out^=iv
+ &movdqa ("xmm1",&QWP(32,"esp")); # load next IV
+ &movdqu (&QWP(0,$base,$inp),"xmm0"); # write output
+ &lea ($inp,&DWP(16,$inp));
+ &sub ($out,16);
+ &jnc (&label("cbc_dec_loop"));
+
+&set_label("cbc_done");
+ &mov ($base,&DWP(8,"esp")); # restore ivp
+ &mov ("esp",&DWP(48,"esp"));
+ &movdqu (&QWP(0,$base),"xmm1"); # write IV
+&set_label("cbc_abort");
+&function_end("${PREFIX}_cbc_encrypt");
+
+&asm_finish();
diff --git a/src/crypto/aes/asm/vpaes-x86_64.pl b/src/crypto/aes/asm/vpaes-x86_64.pl
new file mode 100644
index 0000000..f2ef318
--- /dev/null
+++ b/src/crypto/aes/asm/vpaes-x86_64.pl
@@ -0,0 +1,1207 @@
+#!/usr/bin/env perl
+
+######################################################################
+## Constant-time SSSE3 AES core implementation.
+## version 0.1
+##
+## By Mike Hamburg (Stanford University), 2009
+## Public domain.
+##
+## For details see http://shiftleft.org/papers/vector_aes/ and
+## http://crypto.stanford.edu/vpaes/.
+
+######################################################################
+# September 2011.
+#
+# Interface to OpenSSL as "almost" drop-in replacement for
+# aes-x86_64.pl. "Almost" refers to the fact that AES_cbc_encrypt
+# doesn't handle partial vectors (doesn't have to if called from
+# EVP only). "Drop-in" implies that this module doesn't share key
+# schedule structure with the original nor does it make assumption
+# about its alignment...
+#
+# Performance summary. aes-x86_64.pl column lists large-block CBC
+# encrypt/decrypt/with-hyper-threading-off(*) results in cycles per
+# byte processed with 128-bit key, and vpaes-x86_64.pl column -
+# [also large-block CBC] encrypt/decrypt.
+#
+# aes-x86_64.pl vpaes-x86_64.pl
+#
+# Core 2(**) 29.6/41.1/14.3 21.9/25.2(***)
+# Nehalem 29.6/40.3/14.6 10.0/11.8
+# Atom 57.3/74.2/32.1 60.9/77.2(***)
+# Silvermont 52.7/64.0/19.5 48.8/60.8(***)
+#
+# (*) "Hyper-threading" in the context refers rather to cache shared
+# among multiple cores, than to specifically Intel HTT. As vast
+# majority of contemporary cores share cache, slower code path
+# is common place. In other words "with-hyper-threading-off"
+# results are presented mostly for reference purposes.
+#
+# (**) "Core 2" refers to initial 65nm design, a.k.a. Conroe.
+#
+# (***) Less impressive improvement on Core 2 and Atom is due to slow
+# pshufb, yet it's respectable +36%/62% improvement on Core 2
+# (as implied, over "hyper-threading-safe" code path).
+#
+# <appro@openssl.org>
+
+$flavour = shift;
+$output = shift;
+if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+
+$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
+( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
+die "can't locate x86_64-xlate.pl";
+
+open OUT,"| \"$^X\" $xlate $flavour $output";
+*STDOUT=*OUT;
+
+$PREFIX="vpaes";
+
+$code.=<<___;
+.text
+
+##
+## _aes_encrypt_core
+##
+## AES-encrypt %xmm0.
+##
+## Inputs:
+## %xmm0 = input
+## %xmm9-%xmm15 as in _vpaes_preheat
+## (%rdx) = scheduled keys
+##
+## Output in %xmm0
+## Clobbers %xmm1-%xmm5, %r9, %r10, %r11, %rax
+## Preserves %xmm6 - %xmm8 so you get some local vectors
+##
+##
+.type _vpaes_encrypt_core,\@abi-omnipotent
+.align 16
+_vpaes_encrypt_core:
+ mov %rdx, %r9
+ mov \$16, %r11
+ mov 240(%rdx),%eax
+ movdqa %xmm9, %xmm1
+ movdqa .Lk_ipt(%rip), %xmm2 # iptlo
+ pandn %xmm0, %xmm1
+ movdqu (%r9), %xmm5 # round0 key
+ psrld \$4, %xmm1
+ pand %xmm9, %xmm0
+ pshufb %xmm0, %xmm2
+ movdqa .Lk_ipt+16(%rip), %xmm0 # ipthi
+ pshufb %xmm1, %xmm0
+ pxor %xmm5, %xmm2
+ add \$16, %r9
+ pxor %xmm2, %xmm0
+ lea .Lk_mc_backward(%rip),%r10
+ jmp .Lenc_entry
+
+.align 16
+.Lenc_loop:
+ # middle of middle round
+ movdqa %xmm13, %xmm4 # 4 : sb1u
+ movdqa %xmm12, %xmm0 # 0 : sb1t
+ pshufb %xmm2, %xmm4 # 4 = sb1u
+ pshufb %xmm3, %xmm0 # 0 = sb1t
+ pxor %xmm5, %xmm4 # 4 = sb1u + k
+ movdqa %xmm15, %xmm5 # 4 : sb2u
+ pxor %xmm4, %xmm0 # 0 = A
+ movdqa -0x40(%r11,%r10), %xmm1 # .Lk_mc_forward[]
+ pshufb %xmm2, %xmm5 # 4 = sb2u
+ movdqa (%r11,%r10), %xmm4 # .Lk_mc_backward[]
+ movdqa %xmm14, %xmm2 # 2 : sb2t
+ pshufb %xmm3, %xmm2 # 2 = sb2t
+ movdqa %xmm0, %xmm3 # 3 = A
+ pxor %xmm5, %xmm2 # 2 = 2A
+ pshufb %xmm1, %xmm0 # 0 = B
+ add \$16, %r9 # next key
+ pxor %xmm2, %xmm0 # 0 = 2A+B
+ pshufb %xmm4, %xmm3 # 3 = D
+ add \$16, %r11 # next mc
+ pxor %xmm0, %xmm3 # 3 = 2A+B+D
+ pshufb %xmm1, %xmm0 # 0 = 2B+C
+ and \$0x30, %r11 # ... mod 4
+ sub \$1,%rax # nr--
+ pxor %xmm3, %xmm0 # 0 = 2A+3B+C+D
+
+.Lenc_entry:
+ # top of round
+ movdqa %xmm9, %xmm1 # 1 : i
+ movdqa %xmm11, %xmm5 # 2 : a/k
+ pandn %xmm0, %xmm1 # 1 = i<<4
+ psrld \$4, %xmm1 # 1 = i
+ pand %xmm9, %xmm0 # 0 = k
+ pshufb %xmm0, %xmm5 # 2 = a/k
+ movdqa %xmm10, %xmm3 # 3 : 1/i
+ pxor %xmm1, %xmm0 # 0 = j
+ pshufb %xmm1, %xmm3 # 3 = 1/i
+ movdqa %xmm10, %xmm4 # 4 : 1/j
+ pxor %xmm5, %xmm3 # 3 = iak = 1/i + a/k
+ pshufb %xmm0, %xmm4 # 4 = 1/j
+ movdqa %xmm10, %xmm2 # 2 : 1/iak
+ pxor %xmm5, %xmm4 # 4 = jak = 1/j + a/k
+ pshufb %xmm3, %xmm2 # 2 = 1/iak
+ movdqa %xmm10, %xmm3 # 3 : 1/jak
+ pxor %xmm0, %xmm2 # 2 = io
+ pshufb %xmm4, %xmm3 # 3 = 1/jak
+ movdqu (%r9), %xmm5
+ pxor %xmm1, %xmm3 # 3 = jo
+ jnz .Lenc_loop
+
+ # middle of last round
+ movdqa -0x60(%r10), %xmm4 # 3 : sbou .Lk_sbo
+ movdqa -0x50(%r10), %xmm0 # 0 : sbot .Lk_sbo+16
+ pshufb %xmm2, %xmm4 # 4 = sbou
+ pxor %xmm5, %xmm4 # 4 = sb1u + k
+ pshufb %xmm3, %xmm0 # 0 = sb1t
+ movdqa 0x40(%r11,%r10), %xmm1 # .Lk_sr[]
+ pxor %xmm4, %xmm0 # 0 = A
+ pshufb %xmm1, %xmm0
+ ret
+.size _vpaes_encrypt_core,.-_vpaes_encrypt_core
+
+##
+## Decryption core
+##
+## Same API as encryption core.
+##
+.type _vpaes_decrypt_core,\@abi-omnipotent
+.align 16
+_vpaes_decrypt_core:
+ mov %rdx, %r9 # load key
+ mov 240(%rdx),%eax
+ movdqa %xmm9, %xmm1
+ movdqa .Lk_dipt(%rip), %xmm2 # iptlo
+ pandn %xmm0, %xmm1
+ mov %rax, %r11
+ psrld \$4, %xmm1
+ movdqu (%r9), %xmm5 # round0 key
+ shl \$4, %r11
+ pand %xmm9, %xmm0
+ pshufb %xmm0, %xmm2
+ movdqa .Lk_dipt+16(%rip), %xmm0 # ipthi
+ xor \$0x30, %r11
+ lea .Lk_dsbd(%rip),%r10
+ pshufb %xmm1, %xmm0
+ and \$0x30, %r11
+ pxor %xmm5, %xmm2
+ movdqa .Lk_mc_forward+48(%rip), %xmm5
+ pxor %xmm2, %xmm0
+ add \$16, %r9
+ add %r10, %r11
+ jmp .Ldec_entry
+
+.align 16
+.Ldec_loop:
+##
+## Inverse mix columns
+##
+ movdqa -0x20(%r10),%xmm4 # 4 : sb9u
+ movdqa -0x10(%r10),%xmm1 # 0 : sb9t
+ pshufb %xmm2, %xmm4 # 4 = sb9u
+ pshufb %xmm3, %xmm1 # 0 = sb9t
+ pxor %xmm4, %xmm0
+ movdqa 0x00(%r10),%xmm4 # 4 : sbdu
+ pxor %xmm1, %xmm0 # 0 = ch
+ movdqa 0x10(%r10),%xmm1 # 0 : sbdt
+
+ pshufb %xmm2, %xmm4 # 4 = sbdu
+ pshufb %xmm5, %xmm0 # MC ch
+ pshufb %xmm3, %xmm1 # 0 = sbdt
+ pxor %xmm4, %xmm0 # 4 = ch
+ movdqa 0x20(%r10),%xmm4 # 4 : sbbu
+ pxor %xmm1, %xmm0 # 0 = ch
+ movdqa 0x30(%r10),%xmm1 # 0 : sbbt
+
+ pshufb %xmm2, %xmm4 # 4 = sbbu
+ pshufb %xmm5, %xmm0 # MC ch
+ pshufb %xmm3, %xmm1 # 0 = sbbt
+ pxor %xmm4, %xmm0 # 4 = ch
+ movdqa 0x40(%r10),%xmm4 # 4 : sbeu
+ pxor %xmm1, %xmm0 # 0 = ch
+ movdqa 0x50(%r10),%xmm1 # 0 : sbet
+
+ pshufb %xmm2, %xmm4 # 4 = sbeu
+ pshufb %xmm5, %xmm0 # MC ch
+ pshufb %xmm3, %xmm1 # 0 = sbet
+ pxor %xmm4, %xmm0 # 4 = ch
+ add \$16, %r9 # next round key
+ palignr \$12, %xmm5, %xmm5
+ pxor %xmm1, %xmm0 # 0 = ch
+ sub \$1,%rax # nr--
+
+.Ldec_entry:
+ # top of round
+ movdqa %xmm9, %xmm1 # 1 : i
+ pandn %xmm0, %xmm1 # 1 = i<<4
+ movdqa %xmm11, %xmm2 # 2 : a/k
+ psrld \$4, %xmm1 # 1 = i
+ pand %xmm9, %xmm0 # 0 = k
+ pshufb %xmm0, %xmm2 # 2 = a/k
+ movdqa %xmm10, %xmm3 # 3 : 1/i
+ pxor %xmm1, %xmm0 # 0 = j
+ pshufb %xmm1, %xmm3 # 3 = 1/i
+ movdqa %xmm10, %xmm4 # 4 : 1/j
+ pxor %xmm2, %xmm3 # 3 = iak = 1/i + a/k
+ pshufb %xmm0, %xmm4 # 4 = 1/j
+ pxor %xmm2, %xmm4 # 4 = jak = 1/j + a/k
+ movdqa %xmm10, %xmm2 # 2 : 1/iak
+ pshufb %xmm3, %xmm2 # 2 = 1/iak
+ movdqa %xmm10, %xmm3 # 3 : 1/jak
+ pxor %xmm0, %xmm2 # 2 = io
+ pshufb %xmm4, %xmm3 # 3 = 1/jak
+ movdqu (%r9), %xmm0
+ pxor %xmm1, %xmm3 # 3 = jo
+ jnz .Ldec_loop
+
+ # middle of last round
+ movdqa 0x60(%r10), %xmm4 # 3 : sbou
+ pshufb %xmm2, %xmm4 # 4 = sbou
+ pxor %xmm0, %xmm4 # 4 = sb1u + k
+ movdqa 0x70(%r10), %xmm0 # 0 : sbot
+ movdqa -0x160(%r11), %xmm2 # .Lk_sr-.Lk_dsbd=-0x160
+ pshufb %xmm3, %xmm0 # 0 = sb1t
+ pxor %xmm4, %xmm0 # 0 = A
+ pshufb %xmm2, %xmm0
+ ret
+.size _vpaes_decrypt_core,.-_vpaes_decrypt_core
+
+########################################################
+## ##
+## AES key schedule ##
+## ##
+########################################################
+.type _vpaes_schedule_core,\@abi-omnipotent
+.align 16
+_vpaes_schedule_core:
+ # rdi = key
+ # rsi = size in bits
+ # rdx = buffer
+ # rcx = direction. 0=encrypt, 1=decrypt
+
+ call _vpaes_preheat # load the tables
+ movdqa .Lk_rcon(%rip), %xmm8 # load rcon
+ movdqu (%rdi), %xmm0 # load key (unaligned)
+
+ # input transform
+ movdqa %xmm0, %xmm3
+ lea .Lk_ipt(%rip), %r11
+ call _vpaes_schedule_transform
+ movdqa %xmm0, %xmm7
+
+ lea .Lk_sr(%rip),%r10
+ test %rcx, %rcx
+ jnz .Lschedule_am_decrypting
+
+ # encrypting, output zeroth round key after transform
+ movdqu %xmm0, (%rdx)
+ jmp .Lschedule_go
+
+.Lschedule_am_decrypting:
+ # decrypting, output zeroth round key after shiftrows
+ movdqa (%r8,%r10),%xmm1
+ pshufb %xmm1, %xmm3
+ movdqu %xmm3, (%rdx)
+ xor \$0x30, %r8
+
+.Lschedule_go:
+ cmp \$192, %esi
+ ja .Lschedule_256
+ je .Lschedule_192
+ # 128: fall though
+
+##
+## .schedule_128
+##
+## 128-bit specific part of key schedule.
+##
+## This schedule is really simple, because all its parts
+## are accomplished by the subroutines.
+##
+.Lschedule_128:
+ mov \$10, %esi
+
+.Loop_schedule_128:
+ call _vpaes_schedule_round
+ dec %rsi
+ jz .Lschedule_mangle_last
+ call _vpaes_schedule_mangle # write output
+ jmp .Loop_schedule_128
+
+##
+## .aes_schedule_192
+##
+## 192-bit specific part of key schedule.
+##
+## The main body of this schedule is the same as the 128-bit
+## schedule, but with more smearing. The long, high side is
+## stored in %xmm7 as before, and the short, low side is in
+## the high bits of %xmm6.
+##
+## This schedule is somewhat nastier, however, because each
+## round produces 192 bits of key material, or 1.5 round keys.
+## Therefore, on each cycle we do 2 rounds and produce 3 round
+## keys.
+##
+.align 16
+.Lschedule_192:
+ movdqu 8(%rdi),%xmm0 # load key part 2 (very unaligned)
+ call _vpaes_schedule_transform # input transform
+ movdqa %xmm0, %xmm6 # save short part
+ pxor %xmm4, %xmm4 # clear 4
+ movhlps %xmm4, %xmm6 # clobber low side with zeros
+ mov \$4, %esi
+
+.Loop_schedule_192:
+ call _vpaes_schedule_round
+ palignr \$8,%xmm6,%xmm0
+ call _vpaes_schedule_mangle # save key n
+ call _vpaes_schedule_192_smear
+ call _vpaes_schedule_mangle # save key n+1
+ call _vpaes_schedule_round
+ dec %rsi
+ jz .Lschedule_mangle_last
+ call _vpaes_schedule_mangle # save key n+2
+ call _vpaes_schedule_192_smear
+ jmp .Loop_schedule_192
+
+##
+## .aes_schedule_256
+##
+## 256-bit specific part of key schedule.
+##
+## The structure here is very similar to the 128-bit
+## schedule, but with an additional "low side" in
+## %xmm6. The low side's rounds are the same as the
+## high side's, except no rcon and no rotation.
+##
+.align 16
+.Lschedule_256:
+ movdqu 16(%rdi),%xmm0 # load key part 2 (unaligned)
+ call _vpaes_schedule_transform # input transform
+ mov \$7, %esi
+
+.Loop_schedule_256:
+ call _vpaes_schedule_mangle # output low result
+ movdqa %xmm0, %xmm6 # save cur_lo in xmm6
+
+ # high round
+ call _vpaes_schedule_round
+ dec %rsi
+ jz .Lschedule_mangle_last
+ call _vpaes_schedule_mangle
+
+ # low round. swap xmm7 and xmm6
+ pshufd \$0xFF, %xmm0, %xmm0
+ movdqa %xmm7, %xmm5
+ movdqa %xmm6, %xmm7
+ call _vpaes_schedule_low_round
+ movdqa %xmm5, %xmm7
+
+ jmp .Loop_schedule_256
+
+
+##
+## .aes_schedule_mangle_last
+##
+## Mangler for last round of key schedule
+## Mangles %xmm0
+## when encrypting, outputs out(%xmm0) ^ 63
+## when decrypting, outputs unskew(%xmm0)
+##
+## Always called right before return... jumps to cleanup and exits
+##
+.align 16
+.Lschedule_mangle_last:
+ # schedule last round key from xmm0
+ lea .Lk_deskew(%rip),%r11 # prepare to deskew
+ test %rcx, %rcx
+ jnz .Lschedule_mangle_last_dec
+
+ # encrypting
+ movdqa (%r8,%r10),%xmm1
+ pshufb %xmm1, %xmm0 # output permute
+ lea .Lk_opt(%rip), %r11 # prepare to output transform
+ add \$32, %rdx
+
+.Lschedule_mangle_last_dec:
+ add \$-16, %rdx
+ pxor .Lk_s63(%rip), %xmm0
+ call _vpaes_schedule_transform # output transform
+ movdqu %xmm0, (%rdx) # save last key
+
+ # cleanup
+ pxor %xmm0, %xmm0
+ pxor %xmm1, %xmm1
+ pxor %xmm2, %xmm2
+ pxor %xmm3, %xmm3
+ pxor %xmm4, %xmm4
+ pxor %xmm5, %xmm5
+ pxor %xmm6, %xmm6
+ pxor %xmm7, %xmm7
+ ret
+.size _vpaes_schedule_core,.-_vpaes_schedule_core
+
+##
+## .aes_schedule_192_smear
+##
+## Smear the short, low side in the 192-bit key schedule.
+##
+## Inputs:
+## %xmm7: high side, b a x y
+## %xmm6: low side, d c 0 0
+## %xmm13: 0
+##
+## Outputs:
+## %xmm6: b+c+d b+c 0 0
+## %xmm0: b+c+d b+c b a
+##
+.type _vpaes_schedule_192_smear,\@abi-omnipotent
+.align 16
+_vpaes_schedule_192_smear:
+ pshufd \$0x80, %xmm6, %xmm1 # d c 0 0 -> c 0 0 0
+ pshufd \$0xFE, %xmm7, %xmm0 # b a _ _ -> b b b a
+ pxor %xmm1, %xmm6 # -> c+d c 0 0
+ pxor %xmm1, %xmm1
+ pxor %xmm0, %xmm6 # -> b+c+d b+c b a
+ movdqa %xmm6, %xmm0
+ movhlps %xmm1, %xmm6 # clobber low side with zeros
+ ret
+.size _vpaes_schedule_192_smear,.-_vpaes_schedule_192_smear
+
+##
+## .aes_schedule_round
+##
+## Runs one main round of the key schedule on %xmm0, %xmm7
+##
+## Specifically, runs subbytes on the high dword of %xmm0
+## then rotates it by one byte and xors into the low dword of
+## %xmm7.
+##
+## Adds rcon from low byte of %xmm8, then rotates %xmm8 for
+## next rcon.
+##
+## Smears the dwords of %xmm7 by xoring the low into the
+## second low, result into third, result into highest.
+##
+## Returns results in %xmm7 = %xmm0.
+## Clobbers %xmm1-%xmm4, %r11.
+##
+.type _vpaes_schedule_round,\@abi-omnipotent
+.align 16
+_vpaes_schedule_round:
+ # extract rcon from xmm8
+ pxor %xmm1, %xmm1
+ palignr \$15, %xmm8, %xmm1
+ palignr \$15, %xmm8, %xmm8
+ pxor %xmm1, %xmm7
+
+ # rotate
+ pshufd \$0xFF, %xmm0, %xmm0
+ palignr \$1, %xmm0, %xmm0
+
+ # fall through...
+
+ # low round: same as high round, but no rotation and no rcon.
+_vpaes_schedule_low_round:
+ # smear xmm7
+ movdqa %xmm7, %xmm1
+ pslldq \$4, %xmm7
+ pxor %xmm1, %xmm7
+ movdqa %xmm7, %xmm1
+ pslldq \$8, %xmm7
+ pxor %xmm1, %xmm7
+ pxor .Lk_s63(%rip), %xmm7
+
+ # subbytes
+ movdqa %xmm9, %xmm1
+ pandn %xmm0, %xmm1
+ psrld \$4, %xmm1 # 1 = i
+ pand %xmm9, %xmm0 # 0 = k
+ movdqa %xmm11, %xmm2 # 2 : a/k
+ pshufb %xmm0, %xmm2 # 2 = a/k
+ pxor %xmm1, %xmm0 # 0 = j
+ movdqa %xmm10, %xmm3 # 3 : 1/i
+ pshufb %xmm1, %xmm3 # 3 = 1/i
+ pxor %xmm2, %xmm3 # 3 = iak = 1/i + a/k
+ movdqa %xmm10, %xmm4 # 4 : 1/j
+ pshufb %xmm0, %xmm4 # 4 = 1/j
+ pxor %xmm2, %xmm4 # 4 = jak = 1/j + a/k
+ movdqa %xmm10, %xmm2 # 2 : 1/iak
+ pshufb %xmm3, %xmm2 # 2 = 1/iak
+ pxor %xmm0, %xmm2 # 2 = io
+ movdqa %xmm10, %xmm3 # 3 : 1/jak
+ pshufb %xmm4, %xmm3 # 3 = 1/jak
+ pxor %xmm1, %xmm3 # 3 = jo
+ movdqa %xmm13, %xmm4 # 4 : sbou
+ pshufb %xmm2, %xmm4 # 4 = sbou
+ movdqa %xmm12, %xmm0 # 0 : sbot
+ pshufb %xmm3, %xmm0 # 0 = sb1t
+ pxor %xmm4, %xmm0 # 0 = sbox output
+
+ # add in smeared stuff
+ pxor %xmm7, %xmm0
+ movdqa %xmm0, %xmm7
+ ret
+.size _vpaes_schedule_round,.-_vpaes_schedule_round
+
+##
+## .aes_schedule_transform
+##
+## Linear-transform %xmm0 according to tables at (%r11)
+##
+## Requires that %xmm9 = 0x0F0F... as in preheat
+## Output in %xmm0
+## Clobbers %xmm1, %xmm2
+##
+.type _vpaes_schedule_transform,\@abi-omnipotent
+.align 16
+_vpaes_schedule_transform:
+ movdqa %xmm9, %xmm1
+ pandn %xmm0, %xmm1
+ psrld \$4, %xmm1
+ pand %xmm9, %xmm0
+ movdqa (%r11), %xmm2 # lo
+ pshufb %xmm0, %xmm2
+ movdqa 16(%r11), %xmm0 # hi
+ pshufb %xmm1, %xmm0
+ pxor %xmm2, %xmm0
+ ret
+.size _vpaes_schedule_transform,.-_vpaes_schedule_transform
+
+##
+## .aes_schedule_mangle
+##
+## Mangle xmm0 from (basis-transformed) standard version
+## to our version.
+##
+## On encrypt,
+## xor with 0x63
+## multiply by circulant 0,1,1,1
+## apply shiftrows transform
+##
+## On decrypt,
+## xor with 0x63
+## multiply by "inverse mixcolumns" circulant E,B,D,9
+## deskew
+## apply shiftrows transform
+##
+##
+## Writes out to (%rdx), and increments or decrements it
+## Keeps track of round number mod 4 in %r8
+## Preserves xmm0
+## Clobbers xmm1-xmm5
+##
+.type _vpaes_schedule_mangle,\@abi-omnipotent
+.align 16
+_vpaes_schedule_mangle:
+ movdqa %xmm0, %xmm4 # save xmm0 for later
+ movdqa .Lk_mc_forward(%rip),%xmm5
+ test %rcx, %rcx
+ jnz .Lschedule_mangle_dec
+
+ # encrypting
+ add \$16, %rdx
+ pxor .Lk_s63(%rip),%xmm4
+ pshufb %xmm5, %xmm4
+ movdqa %xmm4, %xmm3
+ pshufb %xmm5, %xmm4
+ pxor %xmm4, %xmm3
+ pshufb %xmm5, %xmm4
+ pxor %xmm4, %xmm3
+
+ jmp .Lschedule_mangle_both
+.align 16
+.Lschedule_mangle_dec:
+ # inverse mix columns
+ lea .Lk_dksd(%rip),%r11
+ movdqa %xmm9, %xmm1
+ pandn %xmm4, %xmm1
+ psrld \$4, %xmm1 # 1 = hi
+ pand %xmm9, %xmm4 # 4 = lo
+
+ movdqa 0x00(%r11), %xmm2
+ pshufb %xmm4, %xmm2
+ movdqa 0x10(%r11), %xmm3
+ pshufb %xmm1, %xmm3
+ pxor %xmm2, %xmm3
+ pshufb %xmm5, %xmm3
+
+ movdqa 0x20(%r11), %xmm2
+ pshufb %xmm4, %xmm2
+ pxor %xmm3, %xmm2
+ movdqa 0x30(%r11), %xmm3
+ pshufb %xmm1, %xmm3
+ pxor %xmm2, %xmm3
+ pshufb %xmm5, %xmm3
+
+ movdqa 0x40(%r11), %xmm2
+ pshufb %xmm4, %xmm2
+ pxor %xmm3, %xmm2
+ movdqa 0x50(%r11), %xmm3
+ pshufb %xmm1, %xmm3
+ pxor %xmm2, %xmm3
+ pshufb %xmm5, %xmm3
+
+ movdqa 0x60(%r11), %xmm2
+ pshufb %xmm4, %xmm2
+ pxor %xmm3, %xmm2
+ movdqa 0x70(%r11), %xmm3
+ pshufb %xmm1, %xmm3
+ pxor %xmm2, %xmm3
+
+ add \$-16, %rdx
+
+.Lschedule_mangle_both:
+ movdqa (%r8,%r10),%xmm1
+ pshufb %xmm1,%xmm3
+ add \$-16, %r8
+ and \$0x30, %r8
+ movdqu %xmm3, (%rdx)
+ ret
+.size _vpaes_schedule_mangle,.-_vpaes_schedule_mangle
+
+#
+# Interface to OpenSSL
+#
+.globl ${PREFIX}_set_encrypt_key
+.type ${PREFIX}_set_encrypt_key,\@function,3
+.align 16
+${PREFIX}_set_encrypt_key:
+___
+$code.=<<___ if ($win64);
+ lea -0xb8(%rsp),%rsp
+ movaps %xmm6,0x10(%rsp)
+ movaps %xmm7,0x20(%rsp)
+ movaps %xmm8,0x30(%rsp)
+ movaps %xmm9,0x40(%rsp)
+ movaps %xmm10,0x50(%rsp)
+ movaps %xmm11,0x60(%rsp)
+ movaps %xmm12,0x70(%rsp)
+ movaps %xmm13,0x80(%rsp)
+ movaps %xmm14,0x90(%rsp)
+ movaps %xmm15,0xa0(%rsp)
+.Lenc_key_body:
+___
+$code.=<<___;
+ mov %esi,%eax
+ shr \$5,%eax
+ add \$5,%eax
+ mov %eax,240(%rdx) # AES_KEY->rounds = nbits/32+5;
+
+ mov \$0,%ecx
+ mov \$0x30,%r8d
+ call _vpaes_schedule_core
+___
+$code.=<<___ if ($win64);
+ movaps 0x10(%rsp),%xmm6
+ movaps 0x20(%rsp),%xmm7
+ movaps 0x30(%rsp),%xmm8
+ movaps 0x40(%rsp),%xmm9
+ movaps 0x50(%rsp),%xmm10
+ movaps 0x60(%rsp),%xmm11
+ movaps 0x70(%rsp),%xmm12
+ movaps 0x80(%rsp),%xmm13
+ movaps 0x90(%rsp),%xmm14
+ movaps 0xa0(%rsp),%xmm15
+ lea 0xb8(%rsp),%rsp
+.Lenc_key_epilogue:
+___
+$code.=<<___;
+ xor %eax,%eax
+ ret
+.size ${PREFIX}_set_encrypt_key,.-${PREFIX}_set_encrypt_key
+
+.globl ${PREFIX}_set_decrypt_key
+.type ${PREFIX}_set_decrypt_key,\@function,3
+.align 16
+${PREFIX}_set_decrypt_key:
+___
+$code.=<<___ if ($win64);
+ lea -0xb8(%rsp),%rsp
+ movaps %xmm6,0x10(%rsp)
+ movaps %xmm7,0x20(%rsp)
+ movaps %xmm8,0x30(%rsp)
+ movaps %xmm9,0x40(%rsp)
+ movaps %xmm10,0x50(%rsp)
+ movaps %xmm11,0x60(%rsp)
+ movaps %xmm12,0x70(%rsp)
+ movaps %xmm13,0x80(%rsp)
+ movaps %xmm14,0x90(%rsp)
+ movaps %xmm15,0xa0(%rsp)
+.Ldec_key_body:
+___
+$code.=<<___;
+ mov %esi,%eax
+ shr \$5,%eax
+ add \$5,%eax
+ mov %eax,240(%rdx) # AES_KEY->rounds = nbits/32+5;
+ shl \$4,%eax
+ lea 16(%rdx,%rax),%rdx
+
+ mov \$1,%ecx
+ mov %esi,%r8d
+ shr \$1,%r8d
+ and \$32,%r8d
+ xor \$32,%r8d # nbits==192?0:32
+ call _vpaes_schedule_core
+___
+$code.=<<___ if ($win64);
+ movaps 0x10(%rsp),%xmm6
+ movaps 0x20(%rsp),%xmm7
+ movaps 0x30(%rsp),%xmm8
+ movaps 0x40(%rsp),%xmm9
+ movaps 0x50(%rsp),%xmm10
+ movaps 0x60(%rsp),%xmm11
+ movaps 0x70(%rsp),%xmm12
+ movaps 0x80(%rsp),%xmm13
+ movaps 0x90(%rsp),%xmm14
+ movaps 0xa0(%rsp),%xmm15
+ lea 0xb8(%rsp),%rsp
+.Ldec_key_epilogue:
+___
+$code.=<<___;
+ xor %eax,%eax
+ ret
+.size ${PREFIX}_set_decrypt_key,.-${PREFIX}_set_decrypt_key
+
+.globl ${PREFIX}_encrypt
+.type ${PREFIX}_encrypt,\@function,3
+.align 16
+${PREFIX}_encrypt:
+___
+$code.=<<___ if ($win64);
+ lea -0xb8(%rsp),%rsp
+ movaps %xmm6,0x10(%rsp)
+ movaps %xmm7,0x20(%rsp)
+ movaps %xmm8,0x30(%rsp)
+ movaps %xmm9,0x40(%rsp)
+ movaps %xmm10,0x50(%rsp)
+ movaps %xmm11,0x60(%rsp)
+ movaps %xmm12,0x70(%rsp)
+ movaps %xmm13,0x80(%rsp)
+ movaps %xmm14,0x90(%rsp)
+ movaps %xmm15,0xa0(%rsp)
+.Lenc_body:
+___
+$code.=<<___;
+ movdqu (%rdi),%xmm0
+ call _vpaes_preheat
+ call _vpaes_encrypt_core
+ movdqu %xmm0,(%rsi)
+___
+$code.=<<___ if ($win64);
+ movaps 0x10(%rsp),%xmm6
+ movaps 0x20(%rsp),%xmm7
+ movaps 0x30(%rsp),%xmm8
+ movaps 0x40(%rsp),%xmm9
+ movaps 0x50(%rsp),%xmm10
+ movaps 0x60(%rsp),%xmm11
+ movaps 0x70(%rsp),%xmm12
+ movaps 0x80(%rsp),%xmm13
+ movaps 0x90(%rsp),%xmm14
+ movaps 0xa0(%rsp),%xmm15
+ lea 0xb8(%rsp),%rsp
+.Lenc_epilogue:
+___
+$code.=<<___;
+ ret
+.size ${PREFIX}_encrypt,.-${PREFIX}_encrypt
+
+.globl ${PREFIX}_decrypt
+.type ${PREFIX}_decrypt,\@function,3
+.align 16
+${PREFIX}_decrypt:
+___
+$code.=<<___ if ($win64);
+ lea -0xb8(%rsp),%rsp
+ movaps %xmm6,0x10(%rsp)
+ movaps %xmm7,0x20(%rsp)
+ movaps %xmm8,0x30(%rsp)
+ movaps %xmm9,0x40(%rsp)
+ movaps %xmm10,0x50(%rsp)
+ movaps %xmm11,0x60(%rsp)
+ movaps %xmm12,0x70(%rsp)
+ movaps %xmm13,0x80(%rsp)
+ movaps %xmm14,0x90(%rsp)
+ movaps %xmm15,0xa0(%rsp)
+.Ldec_body:
+___
+$code.=<<___;
+ movdqu (%rdi),%xmm0
+ call _vpaes_preheat
+ call _vpaes_decrypt_core
+ movdqu %xmm0,(%rsi)
+___
+$code.=<<___ if ($win64);
+ movaps 0x10(%rsp),%xmm6
+ movaps 0x20(%rsp),%xmm7
+ movaps 0x30(%rsp),%xmm8
+ movaps 0x40(%rsp),%xmm9
+ movaps 0x50(%rsp),%xmm10
+ movaps 0x60(%rsp),%xmm11
+ movaps 0x70(%rsp),%xmm12
+ movaps 0x80(%rsp),%xmm13
+ movaps 0x90(%rsp),%xmm14
+ movaps 0xa0(%rsp),%xmm15
+ lea 0xb8(%rsp),%rsp
+.Ldec_epilogue:
+___
+$code.=<<___;
+ ret
+.size ${PREFIX}_decrypt,.-${PREFIX}_decrypt
+___
+{
+my ($inp,$out,$len,$key,$ivp,$enc)=("%rdi","%rsi","%rdx","%rcx","%r8","%r9");
+# void AES_cbc_encrypt (const void char *inp, unsigned char *out,
+# size_t length, const AES_KEY *key,
+# unsigned char *ivp,const int enc);
+$code.=<<___;
+.globl ${PREFIX}_cbc_encrypt
+.type ${PREFIX}_cbc_encrypt,\@function,6
+.align 16
+${PREFIX}_cbc_encrypt:
+ xchg $key,$len
+___
+($len,$key)=($key,$len);
+$code.=<<___;
+ sub \$16,$len
+ jc .Lcbc_abort
+___
+$code.=<<___ if ($win64);
+ lea -0xb8(%rsp),%rsp
+ movaps %xmm6,0x10(%rsp)
+ movaps %xmm7,0x20(%rsp)
+ movaps %xmm8,0x30(%rsp)
+ movaps %xmm9,0x40(%rsp)
+ movaps %xmm10,0x50(%rsp)
+ movaps %xmm11,0x60(%rsp)
+ movaps %xmm12,0x70(%rsp)
+ movaps %xmm13,0x80(%rsp)
+ movaps %xmm14,0x90(%rsp)
+ movaps %xmm15,0xa0(%rsp)
+.Lcbc_body:
+___
+$code.=<<___;
+ movdqu ($ivp),%xmm6 # load IV
+ sub $inp,$out
+ call _vpaes_preheat
+ cmp \$0,${enc}d
+ je .Lcbc_dec_loop
+ jmp .Lcbc_enc_loop
+.align 16
+.Lcbc_enc_loop:
+ movdqu ($inp),%xmm0
+ pxor %xmm6,%xmm0
+ call _vpaes_encrypt_core
+ movdqa %xmm0,%xmm6
+ movdqu %xmm0,($out,$inp)
+ lea 16($inp),$inp
+ sub \$16,$len
+ jnc .Lcbc_enc_loop
+ jmp .Lcbc_done
+.align 16
+.Lcbc_dec_loop:
+ movdqu ($inp),%xmm0
+ movdqa %xmm0,%xmm7
+ call _vpaes_decrypt_core
+ pxor %xmm6,%xmm0
+ movdqa %xmm7,%xmm6
+ movdqu %xmm0,($out,$inp)
+ lea 16($inp),$inp
+ sub \$16,$len
+ jnc .Lcbc_dec_loop
+.Lcbc_done:
+ movdqu %xmm6,($ivp) # save IV
+___
+$code.=<<___ if ($win64);
+ movaps 0x10(%rsp),%xmm6
+ movaps 0x20(%rsp),%xmm7
+ movaps 0x30(%rsp),%xmm8
+ movaps 0x40(%rsp),%xmm9
+ movaps 0x50(%rsp),%xmm10
+ movaps 0x60(%rsp),%xmm11
+ movaps 0x70(%rsp),%xmm12
+ movaps 0x80(%rsp),%xmm13
+ movaps 0x90(%rsp),%xmm14
+ movaps 0xa0(%rsp),%xmm15
+ lea 0xb8(%rsp),%rsp
+.Lcbc_epilogue:
+___
+$code.=<<___;
+.Lcbc_abort:
+ ret
+.size ${PREFIX}_cbc_encrypt,.-${PREFIX}_cbc_encrypt
+___
+}
+$code.=<<___;
+##
+## _aes_preheat
+##
+## Fills register %r10 -> .aes_consts (so you can -fPIC)
+## and %xmm9-%xmm15 as specified below.
+##
+.type _vpaes_preheat,\@abi-omnipotent
+.align 16
+_vpaes_preheat:
+ lea .Lk_s0F(%rip), %r10
+ movdqa -0x20(%r10), %xmm10 # .Lk_inv
+ movdqa -0x10(%r10), %xmm11 # .Lk_inv+16
+ movdqa 0x00(%r10), %xmm9 # .Lk_s0F
+ movdqa 0x30(%r10), %xmm13 # .Lk_sb1
+ movdqa 0x40(%r10), %xmm12 # .Lk_sb1+16
+ movdqa 0x50(%r10), %xmm15 # .Lk_sb2
+ movdqa 0x60(%r10), %xmm14 # .Lk_sb2+16
+ ret
+.size _vpaes_preheat,.-_vpaes_preheat
+########################################################
+## ##
+## Constants ##
+## ##
+########################################################
+.type _vpaes_consts,\@object
+.align 64
+_vpaes_consts:
+.Lk_inv: # inv, inva
+ .quad 0x0E05060F0D080180, 0x040703090A0B0C02
+ .quad 0x01040A060F0B0780, 0x030D0E0C02050809
+
+.Lk_s0F: # s0F
+ .quad 0x0F0F0F0F0F0F0F0F, 0x0F0F0F0F0F0F0F0F
+
+.Lk_ipt: # input transform (lo, hi)
+ .quad 0xC2B2E8985A2A7000, 0xCABAE09052227808
+ .quad 0x4C01307D317C4D00, 0xCD80B1FCB0FDCC81
+
+.Lk_sb1: # sb1u, sb1t
+ .quad 0xB19BE18FCB503E00, 0xA5DF7A6E142AF544
+ .quad 0x3618D415FAE22300, 0x3BF7CCC10D2ED9EF
+.Lk_sb2: # sb2u, sb2t
+ .quad 0xE27A93C60B712400, 0x5EB7E955BC982FCD
+ .quad 0x69EB88400AE12900, 0xC2A163C8AB82234A
+.Lk_sbo: # sbou, sbot
+ .quad 0xD0D26D176FBDC700, 0x15AABF7AC502A878
+ .quad 0xCFE474A55FBB6A00, 0x8E1E90D1412B35FA
+
+.Lk_mc_forward: # mc_forward
+ .quad 0x0407060500030201, 0x0C0F0E0D080B0A09
+ .quad 0x080B0A0904070605, 0x000302010C0F0E0D
+ .quad 0x0C0F0E0D080B0A09, 0x0407060500030201
+ .quad 0x000302010C0F0E0D, 0x080B0A0904070605
+
+.Lk_mc_backward:# mc_backward
+ .quad 0x0605040702010003, 0x0E0D0C0F0A09080B
+ .quad 0x020100030E0D0C0F, 0x0A09080B06050407
+ .quad 0x0E0D0C0F0A09080B, 0x0605040702010003
+ .quad 0x0A09080B06050407, 0x020100030E0D0C0F
+
+.Lk_sr: # sr
+ .quad 0x0706050403020100, 0x0F0E0D0C0B0A0908
+ .quad 0x030E09040F0A0500, 0x0B06010C07020D08
+ .quad 0x0F060D040B020900, 0x070E050C030A0108
+ .quad 0x0B0E0104070A0D00, 0x0306090C0F020508
+
+.Lk_rcon: # rcon
+ .quad 0x1F8391B9AF9DEEB6, 0x702A98084D7C7D81
+
+.Lk_s63: # s63: all equal to 0x63 transformed
+ .quad 0x5B5B5B5B5B5B5B5B, 0x5B5B5B5B5B5B5B5B
+
+.Lk_opt: # output transform
+ .quad 0xFF9F4929D6B66000, 0xF7974121DEBE6808
+ .quad 0x01EDBD5150BCEC00, 0xE10D5DB1B05C0CE0
+
+.Lk_deskew: # deskew tables: inverts the sbox's "skew"
+ .quad 0x07E4A34047A4E300, 0x1DFEB95A5DBEF91A
+ .quad 0x5F36B5DC83EA6900, 0x2841C2ABF49D1E77
+
+##
+## Decryption stuff
+## Key schedule constants
+##
+.Lk_dksd: # decryption key schedule: invskew x*D
+ .quad 0xFEB91A5DA3E44700, 0x0740E3A45A1DBEF9
+ .quad 0x41C277F4B5368300, 0x5FDC69EAAB289D1E
+.Lk_dksb: # decryption key schedule: invskew x*B
+ .quad 0x9A4FCA1F8550D500, 0x03D653861CC94C99
+ .quad 0x115BEDA7B6FC4A00, 0xD993256F7E3482C8
+.Lk_dkse: # decryption key schedule: invskew x*E + 0x63
+ .quad 0xD5031CCA1FC9D600, 0x53859A4C994F5086
+ .quad 0xA23196054FDC7BE8, 0xCD5EF96A20B31487
+.Lk_dks9: # decryption key schedule: invskew x*9
+ .quad 0xB6116FC87ED9A700, 0x4AED933482255BFC
+ .quad 0x4576516227143300, 0x8BB89FACE9DAFDCE
+
+##
+## Decryption stuff
+## Round function constants
+##
+.Lk_dipt: # decryption input transform
+ .quad 0x0F505B040B545F00, 0x154A411E114E451A
+ .quad 0x86E383E660056500, 0x12771772F491F194
+
+.Lk_dsb9: # decryption sbox output *9*u, *9*t
+ .quad 0x851C03539A86D600, 0xCAD51F504F994CC9
+ .quad 0xC03B1789ECD74900, 0x725E2C9EB2FBA565
+.Lk_dsbd: # decryption sbox output *D*u, *D*t
+ .quad 0x7D57CCDFE6B1A200, 0xF56E9B13882A4439
+ .quad 0x3CE2FAF724C6CB00, 0x2931180D15DEEFD3
+.Lk_dsbb: # decryption sbox output *B*u, *B*t
+ .quad 0xD022649296B44200, 0x602646F6B0F2D404
+ .quad 0xC19498A6CD596700, 0xF3FF0C3E3255AA6B
+.Lk_dsbe: # decryption sbox output *E*u, *E*t
+ .quad 0x46F2929626D4D000, 0x2242600464B4F6B0
+ .quad 0x0C55A6CDFFAAC100, 0x9467F36B98593E32
+.Lk_dsbo: # decryption sbox final output
+ .quad 0x1387EA537EF94000, 0xC7AA6DB9D4943E2D
+ .quad 0x12D7560F93441D00, 0xCA4B8159D8C58E9C
+.asciz "Vector Permutation AES for x86_64/SSSE3, Mike Hamburg (Stanford University)"
+.align 64
+.size _vpaes_consts,.-_vpaes_consts
+___
+
+if ($win64) {
+# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame,
+# CONTEXT *context,DISPATCHER_CONTEXT *disp)
+$rec="%rcx";
+$frame="%rdx";
+$context="%r8";
+$disp="%r9";
+
+$code.=<<___;
+.extern __imp_RtlVirtualUnwind
+.type se_handler,\@abi-omnipotent
+.align 16
+se_handler:
+ push %rsi
+ push %rdi
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+ pushfq
+ sub \$64,%rsp
+
+ mov 120($context),%rax # pull context->Rax
+ mov 248($context),%rbx # pull context->Rip
+
+ mov 8($disp),%rsi # disp->ImageBase
+ mov 56($disp),%r11 # disp->HandlerData
+
+ mov 0(%r11),%r10d # HandlerData[0]
+ lea (%rsi,%r10),%r10 # prologue label
+ cmp %r10,%rbx # context->Rip<prologue label
+ jb .Lin_prologue
+
+ mov 152($context),%rax # pull context->Rsp
+
+ mov 4(%r11),%r10d # HandlerData[1]
+ lea (%rsi,%r10),%r10 # epilogue label
+ cmp %r10,%rbx # context->Rip>=epilogue label
+ jae .Lin_prologue
+
+ lea 16(%rax),%rsi # %xmm save area
+ lea 512($context),%rdi # &context.Xmm6
+ mov \$20,%ecx # 10*sizeof(%xmm0)/sizeof(%rax)
+ .long 0xa548f3fc # cld; rep movsq
+ lea 0xb8(%rax),%rax # adjust stack pointer
+
+.Lin_prologue:
+ mov 8(%rax),%rdi
+ mov 16(%rax),%rsi
+ mov %rax,152($context) # restore context->Rsp
+ mov %rsi,168($context) # restore context->Rsi
+ mov %rdi,176($context) # restore context->Rdi
+
+ mov 40($disp),%rdi # disp->ContextRecord
+ mov $context,%rsi # context
+ mov \$`1232/8`,%ecx # sizeof(CONTEXT)
+ .long 0xa548f3fc # cld; rep movsq
+
+ mov $disp,%rsi
+ xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER
+ mov 8(%rsi),%rdx # arg2, disp->ImageBase
+ mov 0(%rsi),%r8 # arg3, disp->ControlPc
+ mov 16(%rsi),%r9 # arg4, disp->FunctionEntry
+ mov 40(%rsi),%r10 # disp->ContextRecord
+ lea 56(%rsi),%r11 # &disp->HandlerData
+ lea 24(%rsi),%r12 # &disp->EstablisherFrame
+ mov %r10,32(%rsp) # arg5
+ mov %r11,40(%rsp) # arg6
+ mov %r12,48(%rsp) # arg7
+ mov %rcx,56(%rsp) # arg8, (NULL)
+ call *__imp_RtlVirtualUnwind(%rip)
+
+ mov \$1,%eax # ExceptionContinueSearch
+ add \$64,%rsp
+ popfq
+ pop %r15
+ pop %r14
+ pop %r13
+ pop %r12
+ pop %rbp
+ pop %rbx
+ pop %rdi
+ pop %rsi
+ ret
+.size se_handler,.-se_handler
+
+.section .pdata
+.align 4
+ .rva .LSEH_begin_${PREFIX}_set_encrypt_key
+ .rva .LSEH_end_${PREFIX}_set_encrypt_key
+ .rva .LSEH_info_${PREFIX}_set_encrypt_key
+
+ .rva .LSEH_begin_${PREFIX}_set_decrypt_key
+ .rva .LSEH_end_${PREFIX}_set_decrypt_key
+ .rva .LSEH_info_${PREFIX}_set_decrypt_key
+
+ .rva .LSEH_begin_${PREFIX}_encrypt
+ .rva .LSEH_end_${PREFIX}_encrypt
+ .rva .LSEH_info_${PREFIX}_encrypt
+
+ .rva .LSEH_begin_${PREFIX}_decrypt
+ .rva .LSEH_end_${PREFIX}_decrypt
+ .rva .LSEH_info_${PREFIX}_decrypt
+
+ .rva .LSEH_begin_${PREFIX}_cbc_encrypt
+ .rva .LSEH_end_${PREFIX}_cbc_encrypt
+ .rva .LSEH_info_${PREFIX}_cbc_encrypt
+
+.section .xdata
+.align 8
+.LSEH_info_${PREFIX}_set_encrypt_key:
+ .byte 9,0,0,0
+ .rva se_handler
+ .rva .Lenc_key_body,.Lenc_key_epilogue # HandlerData[]
+.LSEH_info_${PREFIX}_set_decrypt_key:
+ .byte 9,0,0,0
+ .rva se_handler
+ .rva .Ldec_key_body,.Ldec_key_epilogue # HandlerData[]
+.LSEH_info_${PREFIX}_encrypt:
+ .byte 9,0,0,0
+ .rva se_handler
+ .rva .Lenc_body,.Lenc_epilogue # HandlerData[]
+.LSEH_info_${PREFIX}_decrypt:
+ .byte 9,0,0,0
+ .rva se_handler
+ .rva .Ldec_body,.Ldec_epilogue # HandlerData[]
+.LSEH_info_${PREFIX}_cbc_encrypt:
+ .byte 9,0,0,0
+ .rva se_handler
+ .rva .Lcbc_body,.Lcbc_epilogue # HandlerData[]
+___
+}
+
+$code =~ s/\`([^\`]*)\`/eval($1)/gem;
+
+print $code;
+
+close STDOUT;
diff --git a/src/crypto/aes/internal.h b/src/crypto/aes/internal.h
new file mode 100644
index 0000000..3dc5c63
--- /dev/null
+++ b/src/crypto/aes/internal.h
@@ -0,0 +1,87 @@
+/* ====================================================================
+ * 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.
+ * ==================================================================== */
+
+#ifndef OPENSSL_HEADER_AES_INTERNAL_H
+#define OPENSSL_HEADER_AES_INTERNAL_H
+
+#include <openssl/base.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+#if defined(_MSC_VER) && \
+ (defined(_M_IX86) || defined(_M_AMD64) || defined(_M_X64))
+#define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00)
+#define GETU32(p) SWAP(*((uint32_t *)(p)))
+#define PUTU32(ct, st) \
+ { *((uint32_t *)(ct)) = SWAP((st)); }
+#else
+#define GETU32(pt) \
+ (((uint32_t)(pt)[0] << 24) ^ ((uint32_t)(pt)[1] << 16) ^ \
+ ((uint32_t)(pt)[2] << 8) ^ ((uint32_t)(pt)[3]))
+#define PUTU32(ct, st) \
+ { \
+ (ct)[0] = (uint8_t)((st) >> 24); \
+ (ct)[1] = (uint8_t)((st) >> 16); \
+ (ct)[2] = (uint8_t)((st) >> 8); \
+ (ct)[3] = (uint8_t)(st); \
+ }
+#endif
+
+#define MAXKC (256 / 32)
+#define MAXKB (256 / 8)
+#define MAXNR 14
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_AES_INTERNAL_H */
diff --git a/src/crypto/aes/mode_wrappers.c b/src/crypto/aes/mode_wrappers.c
new file mode 100644
index 0000000..c706896
--- /dev/null
+++ b/src/crypto/aes/mode_wrappers.c
@@ -0,0 +1,108 @@
+/* ====================================================================
+ * 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 <openssl/aes.h>
+
+#include "assert.h"
+
+#include <openssl/modes.h>
+
+
+void AES_ctr128_encrypt(const uint8_t *in, uint8_t *out, size_t len,
+ const AES_KEY *key, uint8_t ivec[AES_BLOCK_SIZE],
+ uint8_t ecount_buf[AES_BLOCK_SIZE], unsigned int *num) {
+ CRYPTO_ctr128_encrypt(in, out, len, key, ivec, ecount_buf, num,
+ (block128_f)AES_encrypt);
+}
+
+void AES_ecb_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key,
+ const int enc) {
+ assert(in && out && key);
+ assert((AES_ENCRYPT == enc) || (AES_DECRYPT == enc));
+
+ if (AES_ENCRYPT == enc) {
+ AES_encrypt(in, out, key);
+ } else {
+ AES_decrypt(in, out, key);
+ }
+}
+
+#if defined(OPENSSL_NO_ASM) || \
+ (!defined(OPENSSL_X86_64) && !defined(OPENSSL_X86))
+void AES_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t len,
+ const AES_KEY *key, uint8_t *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);
+ }
+}
+#else
+
+void asm_AES_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t len,
+ const AES_KEY *key, uint8_t *ivec, const int enc);
+void AES_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t len,
+ const AES_KEY *key, uint8_t *ivec, const int enc) {
+ asm_AES_cbc_encrypt(in, out, len, key, ivec, enc);
+}
+
+#endif /* OPENSSL_NO_ASM || (!OPENSSL_X86_64 && !OPENSSL_X86) */
+
+void AES_ofb128_encrypt(const uint8_t *in, uint8_t *out, size_t length,
+ const AES_KEY *key, uint8_t *ivec, int *num) {
+ CRYPTO_ofb128_encrypt(in, out, length, key, ivec, num,
+ (block128_f)AES_encrypt);
+}
+
+void AES_cfb128_encrypt(const uint8_t *in, uint8_t *out, size_t length,
+ const AES_KEY *key, uint8_t *ivec, int *num,
+ int enc) {
+ CRYPTO_cfb128_encrypt(in, out, length, key, ivec, num, enc,
+ (block128_f)AES_encrypt);
+}
diff --git a/src/crypto/arm_arch.h b/src/crypto/arm_arch.h
new file mode 100644
index 0000000..0600fbb
--- /dev/null
+++ b/src/crypto/arm_arch.h
@@ -0,0 +1,136 @@
+/* ====================================================================
+ * 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). */
+
+#ifndef OPENSSL_HEADER_ARM_ARCH_H
+#define OPENSSL_HEADER_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__)
+# if defined(__aarch64__)
+# define __ARM_ARCH__ 8
+# if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+# define __ARMEB__
+# else
+# define __ARMEL__
+# endif
+ /* Why doesn't gcc define __ARM_ARCH__? Instead it defines
+ * bunch of below macros. See all_architectires[] table in
+ * gcc/config/arm/arm.c. On a side note it defines
+ * __ARMEL__/__ARMEB__ for little-/big-endian. */
+# elif 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
+
+/* Even when building for 32-bit ARM, support for aarch64 crypto instructions
+ * will be included. */
+#define __ARM_MAX_ARCH__ 8
+
+#if !__ASSEMBLER__
+
+/* OPENSSL_armcap_P contains flags describing the capabilities of the CPU and
+ * is easy for assembly code to acesss. For C code, see the functions in
+ * |cpu.h|. */
+extern uint32_t OPENSSL_armcap_P;
+
+#endif /* !__ASSEMBLER__ */
+
+/* ARMV7_NEON is true when a NEON unit is present in the current CPU. */
+#define ARMV7_NEON (1 << 0)
+
+/* ARMV7_NEON_FUNCTIONAL is true when the NEON unit doesn't contain subtle bugs.
+ * The Poly1305 NEON code is known to trigger bugs in the NEON units of some
+ * phones. If this bit isn't set then the Poly1305 NEON code won't be used.
+ * See https://code.google.com/p/chromium/issues/detail?id=341598. */
+#define ARMV7_NEON_FUNCTIONAL (1 << 10)
+
+/* ARMV8_AES indicates support for hardware AES instructions. */
+#define ARMV8_AES (1 << 2)
+
+/* ARMV8_SHA1 indicates support for hardware SHA-1 instructions. */
+#define ARMV8_SHA1 (1 << 3)
+
+/* ARMV8_SHA256 indicates support for hardware SHA-256 instructions. */
+#define ARMV8_SHA256 (1 << 4)
+
+/* ARMV8_PMULL indicates support for carryless multiplication. */
+#define ARMV8_PMULL (1 << 5)
+
+
+#endif /* OPENSSL_HEADER_THREAD_H */
diff --git a/src/crypto/asn1/CMakeLists.txt b/src/crypto/asn1/CMakeLists.txt
new file mode 100644
index 0000000..35e1bec
--- /dev/null
+++ b/src/crypto/asn1/CMakeLists.txt
@@ -0,0 +1,46 @@
+include_directories(. .. ../../include)
+
+add_library(
+ asn1
+
+ OBJECT
+
+ a_bitstr.c
+ a_bool.c
+ a_bytes.c
+ a_d2i_fp.c
+ a_dup.c
+ a_enum.c
+ a_gentm.c
+ a_i2d_fp.c
+ a_int.c
+ a_mbstr.c
+ a_object.c
+ a_octet.c
+ a_print.c
+ a_strnid.c
+ a_time.c
+ a_type.c
+ a_utctm.c
+ a_utf8.c
+ asn1_error.c
+ asn1_lib.c
+ asn1_par.c
+ asn_pack.c
+ bio_asn1.c
+ bio_ndef.c
+ f_enum.c
+ f_int.c
+ f_string.c
+ t_bitst.c
+ t_pkey.c
+ tasn_dec.c
+ tasn_enc.c
+ tasn_fre.c
+ tasn_new.c
+ tasn_prn.c
+ tasn_typ.c
+ tasn_utl.c
+ x_bignum.c
+ x_long.c
+)
diff --git a/src/crypto/asn1/a_bitstr.c b/src/crypto/asn1/a_bitstr.c
new file mode 100644
index 0000000..8055f0c
--- /dev/null
+++ b/src/crypto/asn1/a_bitstr.c
@@ -0,0 +1,258 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/asn1.h>
+
+#include <string.h>
+
+#include <openssl/err.h>
+#include <openssl/mem.h>
+
+
+int ASN1_BIT_STRING_set(ASN1_BIT_STRING *x, unsigned char *d, int len)
+{ return M_ASN1_BIT_STRING_set(x, d, len); }
+
+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);
+
+ len=a->length;
+
+ if (len > 0)
+ {
+ if (a->flags & ASN1_STRING_FLAG_BITS_LEFT)
+ {
+ bits=(int)a->flags&0x07;
+ }
+ else
+ {
+ for ( ; len > 0; len--)
+ {
+ if (a->data[len-1]) break;
+ }
+ 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;
+
+ ret=1+len;
+ if (pp == NULL) return(ret);
+
+ p= *pp;
+
+ *(p++)=(unsigned char)bits;
+ d=a->data;
+ memcpy(p,d,len);
+ p+=len;
+ if (len > 0) p[-1]&=(0xff<<bits);
+ *pp=p;
+ return(ret);
+ }
+
+ASN1_BIT_STRING *c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a,
+ const unsigned char **pp, long len)
+ {
+ ASN1_BIT_STRING *ret=NULL;
+ const unsigned char *p;
+ unsigned char *s;
+ int padding;
+
+ if (len < 1)
+ {
+ OPENSSL_PUT_ERROR(ASN1, c2i_ASN1_BIT_STRING,
+ ASN1_R_STRING_TOO_SHORT);
+ goto err;
+ }
+
+ if ((a == NULL) || ((*a) == NULL))
+ {
+ if ((ret=M_ASN1_BIT_STRING_new()) == NULL) return(NULL);
+ }
+ else
+ ret=(*a);
+
+ p= *pp;
+ padding = *(p++);
+ if (padding > 7)
+ {
+ OPENSSL_PUT_ERROR(ASN1, c2i_ASN1_BIT_STRING,
+ ASN1_R_INVALID_BIT_STRING_BITS_LEFT);
+ goto err;
+ }
+
+ /* We do this to preserve the settings. If we modify
+ * the settings, via the _set_bit function, we will recalculate
+ * on output */
+ ret->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07); /* clear */
+ ret->flags|=(ASN1_STRING_FLAG_BITS_LEFT|padding); /* set */
+
+ if (len-- > 1) /* using one because of the bits left byte */
+ {
+ s=(unsigned char *)OPENSSL_malloc((int)len);
+ if (s == NULL)
+ {
+ OPENSSL_PUT_ERROR(ASN1, c2i_ASN1_BIT_STRING,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ memcpy(s,p,(int)len);
+ s[len-1]&=(0xff<<padding);
+ p+=len;
+ }
+ else
+ s=NULL;
+
+ ret->length=(int)len;
+ if (ret->data != NULL) OPENSSL_free(ret->data);
+ ret->data=s;
+ ret->type=V_ASN1_BIT_STRING;
+ if (a != NULL) (*a)=ret;
+ *pp=p;
+ return(ret);
+err:
+ if ((ret != NULL) && ((a == NULL) || (*a != ret)))
+ M_ASN1_BIT_STRING_free(ret);
+ return(NULL);
+ }
+
+/* These next 2 functions from Goetz Babin-Ebell <babinebell@trustcenter.de>
+ */
+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;
+
+ a->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07); /* clear, set on write */
+
+ if ((a->length < (w+1)) || (a->data == NULL))
+ {
+ if (!value) return(1); /* Don't need to set */
+ if (a->data == NULL)
+ c=(unsigned char *)OPENSSL_malloc(w+1);
+ else
+ c=(unsigned char *)OPENSSL_realloc_clean(a->data,
+ a->length,
+ w+1);
+ if (c == NULL)
+ {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_BIT_STRING_set_bit, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ if (w+1-a->length > 0) memset(c+a->length, 0, w+1-a->length);
+ 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);
+ }
+
+int ASN1_BIT_STRING_get_bit(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);
+ }
+
+/*
+ * Checks if the given bit string contains only bits specified by
+ * the flags vector. Returns 0 if there is at least one bit set in 'a'
+ * which is not specified in 'flags', 1 otherwise.
+ * 'len' is the length of 'flags'.
+ */
+int ASN1_BIT_STRING_check(ASN1_BIT_STRING *a,
+ unsigned char *flags, int flags_len)
+ {
+ int i, ok;
+ /* Check if there is one bit set at all. */
+ if (!a || !a->data) return 1;
+
+ /* Check each byte of the internal representation of the bit string. */
+ ok = 1;
+ for (i = 0; i < a->length && ok; ++i)
+ {
+ unsigned char mask = i < flags_len ? ~flags[i] : 0xff;
+ /* We are done if there is an unneeded bit set. */
+ ok = (a->data[i] & mask) == 0;
+ }
+ return ok;
+ }
diff --git a/src/crypto/asn1/a_bool.c b/src/crypto/asn1/a_bool.c
new file mode 100644
index 0000000..c30ee48
--- /dev/null
+++ b/src/crypto/asn1/a_bool.c
@@ -0,0 +1,112 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/asn1.h>
+
+#include <openssl/err.h>
+#include <openssl/mem.h>
+
+
+int i2d_ASN1_BOOLEAN(int a, unsigned char **pp)
+ {
+ int r;
+ unsigned char *p;
+
+ r=ASN1_object_size(0,1,V_ASN1_BOOLEAN);
+ if (pp == NULL) return(r);
+ p= *pp;
+
+ ASN1_put_object(&p,0,1,V_ASN1_BOOLEAN,V_ASN1_UNIVERSAL);
+ *(p++)= (unsigned char)a;
+ *pp=p;
+ return(r);
+ }
+
+int d2i_ASN1_BOOLEAN(int *a, const unsigned char **pp, long length)
+ {
+ int ret= -1;
+ const unsigned char *p;
+ long len;
+ int inf,tag,xclass;
+ int i=0;
+
+ 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_BOOLEAN)
+ {
+ i=ASN1_R_EXPECTING_A_BOOLEAN;
+ goto err;
+ }
+
+ if (len != 1)
+ {
+ i=ASN1_R_BOOLEAN_IS_WRONG_LENGTH;
+ goto err;
+ }
+ ret= (int)*(p++);
+ if (a != NULL) (*a)=ret;
+ *pp=p;
+ return(ret);
+err:
+ OPENSSL_PUT_ERROR(ASN1, d2i_ASN1_BOOLEAN, i);
+ return(ret);
+ }
diff --git a/src/crypto/asn1/a_bytes.c b/src/crypto/asn1/a_bytes.c
new file mode 100644
index 0000000..8874f48
--- /dev/null
+++ b/src/crypto/asn1/a_bytes.c
@@ -0,0 +1,317 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/asn1.h>
+
+#include <string.h>
+
+#include <openssl/buf.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+
+
+static int asn1_collate_primitive(ASN1_STRING *a, ASN1_const_CTX *c);
+/* type is a 'bitmap' of acceptable string types.
+ */
+ASN1_STRING *d2i_ASN1_type_bytes(ASN1_STRING **a, const unsigned char **pp,
+ long length, int type)
+ {
+ ASN1_STRING *ret=NULL;
+ const unsigned char *p;
+ unsigned char *s;
+ long len;
+ int inf,tag,xclass;
+ int i=0;
+
+ p= *pp;
+ inf=ASN1_get_object(&p,&len,&tag,&xclass,length);
+ if (inf & 0x80) goto err;
+
+ if (tag >= 32)
+ {
+ i=ASN1_R_TAG_VALUE_TOO_HIGH;
+ goto err;
+ }
+ if (!(ASN1_tag2bit(tag) & type))
+ {
+ i=ASN1_R_WRONG_TYPE;
+ goto err;
+ }
+
+ /* If a bit-string, exit early */
+ if (tag == V_ASN1_BIT_STRING)
+ return(d2i_ASN1_BIT_STRING(a,pp,length));
+
+ if ((a == NULL) || ((*a) == NULL))
+ {
+ if ((ret=ASN1_STRING_new()) == NULL) return(NULL);
+ }
+ else
+ ret=(*a);
+
+ if (len != 0)
+ {
+ s=(unsigned char *)OPENSSL_malloc((int)len+1);
+ if (s == NULL)
+ {
+ i=ERR_R_MALLOC_FAILURE;
+ goto err;
+ }
+ memcpy(s,p,(int)len);
+ s[len]='\0';
+ p+=len;
+ }
+ else
+ s=NULL;
+
+ if (ret->data != NULL) OPENSSL_free(ret->data);
+ ret->length=(int)len;
+ ret->data=s;
+ ret->type=tag;
+ if (a != NULL) (*a)=ret;
+ *pp=p;
+ return(ret);
+err:
+ OPENSSL_PUT_ERROR(ASN1, d2i_ASN1_type_bytes, i);
+ if ((ret != NULL) && ((a == NULL) || (*a != ret)))
+ ASN1_STRING_free(ret);
+ return(NULL);
+ }
+
+int i2d_ASN1_bytes(ASN1_STRING *a, unsigned char **pp, int tag, int xclass)
+ {
+ int ret,r,constructed;
+ unsigned char *p;
+
+ if (a == NULL) return(0);
+
+ if (tag == V_ASN1_BIT_STRING)
+ return(i2d_ASN1_BIT_STRING(a,pp));
+
+ ret=a->length;
+ r=ASN1_object_size(0,ret,tag);
+ if (pp == NULL) return(r);
+ p= *pp;
+
+ if ((tag == V_ASN1_SEQUENCE) || (tag == V_ASN1_SET))
+ constructed=1;
+ else
+ constructed=0;
+ ASN1_put_object(&p,constructed,ret,tag,xclass);
+ memcpy(p,a->data,a->length);
+ p+=a->length;
+ *pp= p;
+ return(r);
+ }
+
+ASN1_STRING *d2i_ASN1_bytes(ASN1_STRING **a, const unsigned char **pp,
+ long length, int Ptag, int Pclass)
+ {
+ ASN1_STRING *ret=NULL;
+ const unsigned char *p;
+ unsigned char *s;
+ long len;
+ int inf,tag,xclass;
+ int i=0;
+
+ if ((a == NULL) || ((*a) == NULL))
+ {
+ if ((ret=ASN1_STRING_new()) == NULL) return(NULL);
+ }
+ else
+ ret=(*a);
+
+ p= *pp;
+ inf=ASN1_get_object(&p,&len,&tag,&xclass,length);
+ if (inf & 0x80)
+ {
+ i=ASN1_R_BAD_OBJECT_HEADER;
+ goto err;
+ }
+
+ if (tag != Ptag)
+ {
+ i=ASN1_R_WRONG_TAG;
+ goto err;
+ }
+
+ if (inf & V_ASN1_CONSTRUCTED)
+ {
+ ASN1_const_CTX c;
+
+ c.pp=pp;
+ c.p=p;
+ c.inf=inf;
+ c.slen=len;
+ c.tag=Ptag;
+ c.xclass=Pclass;
+ c.max=(length == 0)?0:(p+length);
+ if (!asn1_collate_primitive(ret,&c))
+ goto err;
+ else
+ {
+ p=c.p;
+ }
+ }
+ else
+ {
+ if (len != 0)
+ {
+ if ((ret->length < len) || (ret->data == NULL))
+ {
+ if (ret->data != NULL) OPENSSL_free(ret->data);
+ s=(unsigned char *)OPENSSL_malloc((int)len + 1);
+ if (s == NULL)
+ {
+ i=ERR_R_MALLOC_FAILURE;
+ goto err;
+ }
+ }
+ else
+ s=ret->data;
+ memcpy(s,p,(int)len);
+ s[len] = '\0';
+ p+=len;
+ }
+ else
+ {
+ s=NULL;
+ if (ret->data != NULL) OPENSSL_free(ret->data);
+ }
+
+ ret->length=(int)len;
+ ret->data=s;
+ ret->type=Ptag;
+ }
+
+ if (a != NULL) (*a)=ret;
+ *pp=p;
+ return(ret);
+err:
+ if ((ret != NULL) && ((a == NULL) || (*a != ret)))
+ ASN1_STRING_free(ret);
+ OPENSSL_PUT_ERROR(ASN1, d2i_ASN1_bytes, i);
+ return(NULL);
+ }
+
+
+/* We are about to parse 0..n d2i_ASN1_bytes objects, we are to collapse
+ * them into the one structure that is then returned */
+/* There have been a few bug fixes for this function from
+ * Paul Keogh <paul.keogh@sse.ie>, many thanks to him */
+static int asn1_collate_primitive(ASN1_STRING *a, ASN1_const_CTX *c)
+ {
+ ASN1_STRING *os=NULL;
+ BUF_MEM b;
+ int num;
+
+ b.length=0;
+ b.max=0;
+ b.data=NULL;
+
+ if (a == NULL)
+ {
+ c->error=ERR_R_PASSED_NULL_PARAMETER;
+ goto err;
+ }
+
+ num=0;
+ for (;;)
+ {
+ if (c->inf & 1)
+ {
+ c->eos=ASN1_const_check_infinite_end(&c->p,
+ (long)(c->max-c->p));
+ if (c->eos) break;
+ }
+ else
+ {
+ if (c->slen <= 0) break;
+ }
+
+ c->q=c->p;
+ if (d2i_ASN1_bytes(&os,&c->p,c->max-c->p,c->tag,c->xclass)
+ == NULL)
+ {
+ c->error=ERR_R_ASN1_LIB;
+ goto err;
+ }
+
+ if (!BUF_MEM_grow_clean(&b,num+os->length))
+ {
+ c->error=ERR_R_BUF_LIB;
+ goto err;
+ }
+ memcpy(&(b.data[num]),os->data,os->length);
+ if (!(c->inf & 1))
+ c->slen-=(c->p-c->q);
+ num+=os->length;
+ }
+
+ if (!asn1_const_Finish(c)) goto err;
+
+ a->length=num;
+ if (a->data != NULL) OPENSSL_free(a->data);
+ a->data=(unsigned char *)b.data;
+ if (os != NULL) ASN1_STRING_free(os);
+ return(1);
+err:
+ OPENSSL_PUT_ERROR(ASN1, asn1_collate_primitive, c->error);
+ if (os != NULL) ASN1_STRING_free(os);
+ if (b.data != NULL) OPENSSL_free(b.data);
+ return(0);
+ }
+
diff --git a/src/crypto/asn1/a_d2i_fp.c b/src/crypto/asn1/a_d2i_fp.c
new file mode 100644
index 0000000..c28532b
--- /dev/null
+++ b/src/crypto/asn1/a_d2i_fp.c
@@ -0,0 +1,286 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/asn1.h>
+
+#include <limits.h>
+
+#include <openssl/buf.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+
+
+static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb);
+
+#ifndef NO_OLD_ASN1
+#ifndef OPENSSL_NO_FP_API
+
+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)
+ {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_d2i_fp, 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);
+ }
+#endif
+
+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);
+ }
+
+#endif
+
+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);
+ }
+
+#ifndef OPENSSL_NO_FP_API
+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)
+ {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_item_d2i_fp, 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);
+ }
+#endif
+
+#define HEADER_SIZE 8
+static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
+ {
+ BUF_MEM *b;
+ unsigned char *p;
+ int i;
+ ASN1_const_CTX c;
+ size_t want=HEADER_SIZE;
+ int eos=0;
+ size_t off=0;
+ size_t len=0;
+
+ b=BUF_MEM_new();
+ if (b == NULL)
+ {
+ OPENSSL_PUT_ERROR(ASN1, asn1_d2i_read_bio, 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))
+ {
+ OPENSSL_PUT_ERROR(ASN1, asn1_d2i_read_bio, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ i=BIO_read(in,&(b->data[len]),want);
+ if ((i < 0) && ((len-off) == 0))
+ {
+ OPENSSL_PUT_ERROR(ASN1, asn1_d2i_read_bio, ASN1_R_NOT_ENOUGH_DATA);
+ goto err;
+ }
+ if (i > 0)
+ {
+ if (len+i < len)
+ {
+ OPENSSL_PUT_ERROR(ASN1, asn1_d2i_read_bio, ASN1_R_TOO_LONG);
+ goto err;
+ }
+ len+=i;
+ }
+ }
+ /* else data already loaded */
+
+ p=(unsigned char *)&(b->data[off]);
+ c.p=p;
+ c.inf=ASN1_get_object(&(c.p),&(c.slen),&(c.tag),&(c.xclass),
+ len-off);
+ if (c.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=c.p-p;/* header length */
+ off+=i; /* end of data */
+
+ if (c.inf & 1)
+ {
+ /* no data body so go round again */
+ eos++;
+ if (eos < 0)
+ {
+ OPENSSL_PUT_ERROR(ASN1, asn1_d2i_read_bio, ASN1_R_HEADER_TOO_LONG);
+ goto err;
+ }
+ want=HEADER_SIZE;
+ }
+ else if (eos && (c.slen == 0) && (c.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 c.slen bytes of data */
+ want=c.slen;
+ if (want > (len-off))
+ {
+ want-=(len-off);
+ if (want > INT_MAX /* BIO_read takes an int length */ ||
+ len+want < len)
+ {
+ OPENSSL_PUT_ERROR(ASN1, asn1_d2i_read_bio, ASN1_R_TOO_LONG);
+ goto err;
+ }
+ if (!BUF_MEM_grow_clean(b,len+want))
+ {
+ OPENSSL_PUT_ERROR(ASN1, asn1_d2i_read_bio, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ while (want > 0)
+ {
+ i=BIO_read(in,&(b->data[len]),want);
+ if (i <= 0)
+ {
+ OPENSSL_PUT_ERROR(ASN1, asn1_d2i_read_bio, ASN1_R_NOT_ENOUGH_DATA);
+ goto err;
+ }
+ /* This can't overflow because
+ * |len+want| didn't overflow. */
+ len+=i;
+ want-=i;
+ }
+ }
+ if (off + c.slen < off)
+ {
+ OPENSSL_PUT_ERROR(ASN1, asn1_d2i_read_bio, ASN1_R_TOO_LONG);
+ goto err;
+ }
+ off+=c.slen;
+ if (eos <= 0)
+ {
+ break;
+ }
+ else
+ want=HEADER_SIZE;
+ }
+ }
+
+ if (off > INT_MAX)
+ {
+ OPENSSL_PUT_ERROR(ASN1, asn1_d2i_read_bio, ASN1_R_TOO_LONG);
+ goto err;
+ }
+
+ *pb = b;
+ return off;
+err:
+ if (b != NULL) BUF_MEM_free(b);
+ return -1;
+ }
diff --git a/src/crypto/asn1/a_dup.c b/src/crypto/asn1/a_dup.c
new file mode 100644
index 0000000..8ec1c5f
--- /dev/null
+++ b/src/crypto/asn1/a_dup.c
@@ -0,0 +1,103 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/asn1.h>
+
+#include <openssl/err.h>
+#include <openssl/mem.h>
+
+
+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=OPENSSL_malloc(i+10);
+ if (b == NULL)
+ { OPENSSL_PUT_ERROR(ASN1, ASN1_dup, ERR_R_MALLOC_FAILURE); return(NULL); }
+ p= b;
+ i=i2d(x,&p);
+ p2= b;
+ ret=d2i(NULL,&p2,i);
+ OPENSSL_free(b);
+ return(ret);
+ }
+
+/* ASN1_ITEM version of dup: this follows the model above except we don't need
+ * to allocate the buffer. At some point this could be rewritten to directly dup
+ * the underlying structure instead of doing and 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)
+ { OPENSSL_PUT_ERROR(ASN1, ASN1_item_dup, ERR_R_MALLOC_FAILURE); return(NULL); }
+ p= b;
+ ret=ASN1_item_d2i(NULL,&p,i, it);
+ OPENSSL_free(b);
+ return(ret);
+ }
diff --git a/src/crypto/asn1/a_enum.c b/src/crypto/asn1/a_enum.c
new file mode 100644
index 0000000..a581a34
--- /dev/null
+++ b/src/crypto/asn1/a_enum.c
@@ -0,0 +1,183 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/asn1.h>
+
+#include <string.h>
+
+#include <openssl/err.h>
+#include <openssl/mem.h>
+
+
+/*
+ * Code for ENUMERATED type: identical to INTEGER apart from a different tag.
+ * for comments on encoding see a_int.c
+ */
+
+int ASN1_ENUMERATED_set(ASN1_ENUMERATED *a, long v)
+ {
+ int j,k;
+ unsigned int i;
+ unsigned char buf[sizeof(long)+1];
+ long d;
+
+ a->type=V_ASN1_ENUMERATED;
+ if (a->length < (int)(sizeof(long)+1))
+ {
+ if (a->data != NULL)
+ OPENSSL_free(a->data);
+ if ((a->data=(unsigned char *)OPENSSL_malloc(sizeof(long)+1)) != NULL)
+ memset((char *)a->data,0,sizeof(long)+1);
+ }
+ if (a->data == NULL)
+ {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_ENUMERATED_set, ERR_R_MALLOC_FAILURE);
+ return(0);
+ }
+ d=v;
+ if (d < 0)
+ {
+ d= -d;
+ a->type=V_ASN1_NEG_ENUMERATED;
+ }
+
+ for (i=0; i<sizeof(long); i++)
+ {
+ if (d == 0) break;
+ buf[i]=(int)d&0xff;
+ d>>=8;
+ }
+ j=0;
+ for (k=i-1; k >=0; k--)
+ a->data[j++]=buf[k];
+ a->length=j;
+ return(1);
+ }
+
+long ASN1_ENUMERATED_get(ASN1_ENUMERATED *a)
+ {
+ int neg=0,i;
+ long r=0;
+
+ if (a == NULL) return(0L);
+ i=a->type;
+ if (i == V_ASN1_NEG_ENUMERATED)
+ neg=1;
+ else if (i != V_ASN1_ENUMERATED)
+ return -1;
+
+ if (a->length > (int)sizeof(long))
+ {
+ /* hmm... a bit ugly */
+ return(0xffffffffL);
+ }
+ if (a->data == NULL)
+ return 0;
+
+ for (i=0; i<a->length; i++)
+ {
+ r<<=8;
+ r|=(unsigned char)a->data[i];
+ }
+ if (neg) r= -r;
+ return(r);
+ }
+
+ASN1_ENUMERATED *BN_to_ASN1_ENUMERATED(BIGNUM *bn, ASN1_ENUMERATED *ai)
+ {
+ ASN1_ENUMERATED *ret;
+ int len,j;
+
+ if (ai == NULL)
+ ret=M_ASN1_ENUMERATED_new();
+ else
+ ret=ai;
+ if (ret == NULL)
+ {
+ OPENSSL_PUT_ERROR(ASN1, BN_to_ASN1_ENUMERATED, ASN1_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=OPENSSL_realloc(ret->data, len+4);
+ if (!new_data)
+ {
+ OPENSSL_PUT_ERROR(ASN1, BN_to_ASN1_ENUMERATED, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ ret->data=new_data;
+ }
+
+ ret->length=BN_bn2bin(bn,ret->data);
+ return(ret);
+err:
+ if (ret != ai) M_ASN1_ENUMERATED_free(ret);
+ return(NULL);
+ }
+
+BIGNUM *ASN1_ENUMERATED_to_BN(ASN1_ENUMERATED *ai, BIGNUM *bn)
+ {
+ BIGNUM *ret;
+
+ if ((ret=BN_bin2bn(ai->data,ai->length,bn)) == NULL)
+ OPENSSL_PUT_ERROR(ASN1, ASN1_ENUMERATED_to_BN, ASN1_R_BN_LIB);
+ else if(ai->type == V_ASN1_NEG_ENUMERATED) BN_set_negative(ret,1);
+ return(ret);
+ }
diff --git a/src/crypto/asn1/a_gentm.c b/src/crypto/asn1/a_gentm.c
new file mode 100644
index 0000000..355feff
--- /dev/null
+++ b/src/crypto/asn1/a_gentm.c
@@ -0,0 +1,254 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/asn1.h>
+
+#include <string.h>
+
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/time_support.h>
+
+
+int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d)
+ {
+ static const int min[9]={ 0, 0, 1, 1, 0, 0, 0, 0, 0};
+ static const int max[9]={99, 99,12,31,23,59,59,12,59};
+ char *a;
+ int n,i,l,o;
+
+ if (d->type != V_ASN1_GENERALIZEDTIME) return(0);
+ l=d->length;
+ a=(char *)d->data;
+ o=0;
+ /* GENERALIZEDTIME is similar to UTCTIME except the year is
+ * represented as YYYY. This stuff treats everything as a two digit
+ * field so make first two fields 00 to 99
+ */
+ if (l < 13) goto err;
+ for (i=0; i<7; i++)
+ {
+ if ((i == 6) && ((a[o] == 'Z') ||
+ (a[o] == '+') || (a[o] == '-')))
+ {
+ i++;
+ if (tm)
+ tm->tm_sec = 0;
+ break;
+ }
+ if ((a[o] < '0') || (a[o] > '9')) goto err;
+ n= a[o]-'0';
+ if (++o > l) goto err;
+
+ if ((a[o] < '0') || (a[o] > '9')) goto err;
+ n=(n*10)+ a[o]-'0';
+ if (++o > l) goto err;
+
+ if ((n < min[i]) || (n > max[i])) goto err;
+ if (tm)
+ {
+ switch(i)
+ {
+ case 0:
+ tm->tm_year = n * 100 - 1900;
+ break;
+ case 1:
+ tm->tm_year += n;
+ break;
+ case 2:
+ tm->tm_mon = n - 1;
+ break;
+ case 3:
+ tm->tm_mday = n;
+ break;
+ case 4:
+ tm->tm_hour = n;
+ break;
+ case 5:
+ tm->tm_min = n;
+ break;
+ case 6:
+ tm->tm_sec = n;
+ break;
+ }
+ }
+ }
+ /* Optional fractional seconds: decimal point followed by one
+ * or more digits.
+ */
+ if (a[o] == '.')
+ {
+ if (++o > l) goto err;
+ i = o;
+ while ((a[o] >= '0') && (a[o] <= '9') && (o <= l))
+ o++;
+ /* Must have at least one digit after decimal point */
+ if (i == o) goto err;
+ }
+
+ if (a[o] == 'Z')
+ o++;
+ else if ((a[o] == '+') || (a[o] == '-'))
+ {
+ int offsign = a[o] == '-' ? -1 : 1, offset = 0;
+ o++;
+ if (o+4 > l) goto err;
+ for (i=7; i<9; i++)
+ {
+ if ((a[o] < '0') || (a[o] > '9')) goto err;
+ n= a[o]-'0';
+ o++;
+ if ((a[o] < '0') || (a[o] > '9')) goto err;
+ n=(n*10)+ a[o]-'0';
+ if ((n < min[i]) || (n > max[i])) goto err;
+ if (tm)
+ {
+ if (i == 7)
+ offset = n * 3600;
+ else if (i == 8)
+ offset += n * 60;
+ }
+ o++;
+ }
+ if (offset && !OPENSSL_gmtime_adj(tm, 0, offset * offsign))
+ return 0;
+ }
+ else if (a[o])
+ {
+ /* Missing time zone information. */
+ goto err;
+ }
+ return(o == l);
+err:
+ return(0);
+ }
+
+int ASN1_GENERALIZEDTIME_check(const ASN1_GENERALIZEDTIME *d)
+ {
+ return asn1_generalizedtime_to_tm(NULL, d);
+ }
+
+int ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *s, const char *str)
+ {
+ ASN1_GENERALIZEDTIME t;
+
+ t.type=V_ASN1_GENERALIZEDTIME;
+ t.length=strlen(str);
+ t.data=(unsigned char *)str;
+ if (ASN1_GENERALIZEDTIME_check(&t))
+ {
+ if (s != NULL)
+ {
+ if (!ASN1_STRING_set((ASN1_STRING *)s,
+ (unsigned char *)str,t.length))
+ return 0;
+ s->type=V_ASN1_GENERALIZEDTIME;
+ }
+ return(1);
+ }
+ else
+ return(0);
+ }
+
+ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_set(ASN1_GENERALIZEDTIME *s,
+ time_t t)
+ {
+ return ASN1_GENERALIZEDTIME_adj(s, t, 0, 0);
+ }
+
+ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME *s,
+ time_t t, int offset_day, long offset_sec)
+ {
+ char *p;
+ struct tm *ts;
+ struct tm data;
+ size_t len = 20;
+
+ if (s == NULL)
+ s=M_ASN1_GENERALIZEDTIME_new();
+ if (s == NULL)
+ return(NULL);
+
+ ts=OPENSSL_gmtime(&t, &data);
+ if (ts == NULL)
+ return(NULL);
+
+ if (offset_day || offset_sec)
+ {
+ if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
+ return NULL;
+ }
+
+ p=(char *)s->data;
+ if ((p == NULL) || ((size_t)s->length < len))
+ {
+ p=OPENSSL_malloc(len);
+ if (p == NULL)
+ {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_GENERALIZEDTIME_adj, ERR_R_MALLOC_FAILURE);
+ return(NULL);
+ }
+ if (s->data != NULL)
+ OPENSSL_free(s->data);
+ s->data=(unsigned char *)p;
+ }
+
+ BIO_snprintf(p,len,"%04d%02d%02d%02d%02d%02dZ",ts->tm_year + 1900,
+ ts->tm_mon+1,ts->tm_mday,ts->tm_hour,ts->tm_min,ts->tm_sec);
+ s->length=strlen(p);
+ s->type=V_ASN1_GENERALIZEDTIME;
+ return(s);
+ }
diff --git a/src/crypto/asn1/a_i2d_fp.c b/src/crypto/asn1/a_i2d_fp.c
new file mode 100644
index 0000000..11e40d3
--- /dev/null
+++ b/src/crypto/asn1/a_i2d_fp.c
@@ -0,0 +1,154 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/asn1.h>
+
+#include <openssl/err.h>
+#include <openssl/mem.h>
+
+
+int ASN1_i2d_fp(i2d_of_void *i2d, FILE *out, void *x)
+ {
+ BIO *b;
+ int ret;
+
+ if ((b=BIO_new(BIO_s_file())) == NULL)
+ {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_i2d_fp, 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);
+ }
+
+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=(char *)OPENSSL_malloc(n);
+ if (b == NULL)
+ {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_i2d_bio, 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;
+ }
+ OPENSSL_free(b);
+ return(ret);
+ }
+
+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)
+ {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_item_i2d_fp, 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);
+ }
+
+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)
+ {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_item_i2d_bio, 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;
+ }
+ OPENSSL_free(b);
+ return(ret);
+ }
diff --git a/src/crypto/asn1/a_int.c b/src/crypto/asn1/a_int.c
new file mode 100644
index 0000000..eb0887a
--- /dev/null
+++ b/src/crypto/asn1/a_int.c
@@ -0,0 +1,456 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/asn1.h>
+
+#include <string.h>
+
+#include <openssl/err.h>
+#include <openssl/mem.h>
+
+
+ASN1_INTEGER *ASN1_INTEGER_dup(const ASN1_INTEGER *x)
+{ return M_ASN1_INTEGER_dup(x);}
+
+int ASN1_INTEGER_cmp(const ASN1_INTEGER *x, const ASN1_INTEGER *y)
+ {
+ int neg, ret;
+ /* Compare signs */
+ neg = x->type & V_ASN1_NEG;
+ if (neg != (y->type & V_ASN1_NEG))
+ {
+ if (neg)
+ return -1;
+ else
+ return 1;
+ }
+
+ ret = ASN1_STRING_cmp(x, y);
+
+ if (neg)
+ return -ret;
+ else
+ return ret;
+ }
+
+
+/*
+ * This converts an ASN1 INTEGER into its content encoding.
+ * The internal representation is an ASN1_STRING whose data is a big endian
+ * representation of the value, ignoring the sign. The sign is determined by
+ * the type: V_ASN1_INTEGER for positive and V_ASN1_NEG_INTEGER for negative.
+ *
+ * Positive integers are no problem: they are almost the same as the DER
+ * encoding, except if the first byte is >= 0x80 we need to add a zero pad.
+ *
+ * Negative integers are a bit trickier...
+ * The DER representation of negative integers is in 2s complement form.
+ * The internal form is converted by complementing each octet and finally
+ * adding one to the result. This can be done less messily with a little trick.
+ * If the internal form has trailing zeroes then they will become FF by the
+ * complement and 0 by the add one (due to carry) so just copy as many trailing
+ * zeros to the destination as there are in the source. The carry will add one
+ * to the last none zero octet: so complement this octet and add one and finally
+ * complement any left over until you get to the start of the string.
+ *
+ * Padding is a little trickier too. If the first bytes is > 0x80 then we pad
+ * with 0xff. However if the first byte is 0x80 and one of the following bytes
+ * is non-zero we pad with 0xff. The reason for this distinction is that 0x80
+ * followed by optional zeros isn't padded.
+ */
+
+int i2c_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **pp)
+ {
+ int pad=0,ret,i,neg;
+ unsigned char *p,*n,pb=0;
+
+ if (a == NULL) return(0);
+ neg=a->type & V_ASN1_NEG;
+ if (a->length == 0)
+ ret=1;
+ else
+ {
+ ret=a->length;
+ i=a->data[0];
+ if (!neg && (i > 127)) {
+ pad=1;
+ pb=0;
+ } else if(neg) {
+ if(i>128) {
+ pad=1;
+ pb=0xFF;
+ } else if(i == 128) {
+ /*
+ * Special case: if any other bytes non zero we pad:
+ * otherwise we don't.
+ */
+ for(i = 1; i < a->length; i++) if(a->data[i]) {
+ pad=1;
+ pb=0xFF;
+ break;
+ }
+ }
+ }
+ ret+=pad;
+ }
+ if (pp == NULL) return(ret);
+ p= *pp;
+
+ if (pad) *(p++)=pb;
+ if (a->length == 0) *(p++)=0;
+ else if (!neg) memcpy(p,a->data,(unsigned int)a->length);
+ else {
+ /* Begin at the end of the encoding */
+ n=a->data + a->length - 1;
+ p += a->length - 1;
+ i = a->length;
+ /* Copy zeros to destination as long as source is zero */
+ while(!*n) {
+ *(p--) = 0;
+ n--;
+ i--;
+ }
+ /* Complement and increment next octet */
+ *(p--) = ((*(n--)) ^ 0xff) + 1;
+ i--;
+ /* Complement any octets left */
+ for(;i > 0; i--) *(p--) = *(n--) ^ 0xff;
+ }
+
+ *pp+=ret;
+ return(ret);
+ }
+
+/* Convert just ASN1 INTEGER content octets to ASN1_INTEGER structure */
+
+ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **pp,
+ long len)
+ {
+ ASN1_INTEGER *ret=NULL;
+ const unsigned char *p, *pend;
+ unsigned char *to,*s;
+ int i;
+
+ if ((a == NULL) || ((*a) == NULL))
+ {
+ if ((ret=M_ASN1_INTEGER_new()) == NULL) return(NULL);
+ ret->type=V_ASN1_INTEGER;
+ }
+ else
+ ret=(*a);
+
+ p= *pp;
+ pend = p + len;
+
+ /* We must OPENSSL_malloc stuff, even for 0 bytes otherwise it
+ * signifies a missing NULL parameter. */
+ s=(unsigned char *)OPENSSL_malloc((int)len+1);
+ if (s == NULL)
+ {
+ i=ERR_R_MALLOC_FAILURE;
+ goto err;
+ }
+ to=s;
+ if(!len) {
+ /* Strictly speaking this is an illegal INTEGER but we
+ * tolerate it.
+ */
+ ret->type=V_ASN1_INTEGER;
+ } else if (*p & 0x80) /* a negative number */
+ {
+ ret->type=V_ASN1_NEG_INTEGER;
+ if ((*p == 0xff) && (len != 1)) {
+ p++;
+ len--;
+ }
+ i = len;
+ p += i - 1;
+ to += i - 1;
+ while((!*p) && i) {
+ *(to--) = 0;
+ i--;
+ p--;
+ }
+ /* Special case: if all zeros then the number will be of
+ * the form FF followed by n zero bytes: this corresponds to
+ * 1 followed by n zero bytes. We've already written n zeros
+ * so we just append an extra one and set the first byte to
+ * a 1. This is treated separately because it is the only case
+ * where the number of bytes is larger than len.
+ */
+ if(!i) {
+ *s = 1;
+ s[len] = 0;
+ len++;
+ } else {
+ *(to--) = (*(p--) ^ 0xff) + 1;
+ i--;
+ for(;i > 0; i--) *(to--) = *(p--) ^ 0xff;
+ }
+ } else {
+ ret->type=V_ASN1_INTEGER;
+ if ((*p == 0) && (len != 1))
+ {
+ p++;
+ len--;
+ }
+ memcpy(s,p,(int)len);
+ }
+
+ if (ret->data != NULL) OPENSSL_free(ret->data);
+ ret->data=s;
+ ret->length=(int)len;
+ if (a != NULL) (*a)=ret;
+ *pp=pend;
+ return(ret);
+err:
+ OPENSSL_PUT_ERROR(ASN1, c2i_ASN1_INTEGER, i);
+ if ((ret != NULL) && ((a == NULL) || (*a != ret)))
+ M_ASN1_INTEGER_free(ret);
+ return(NULL);
+ }
+
+
+/* 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=M_ASN1_INTEGER_new()) == NULL) return(NULL);
+ ret->type=V_ASN1_INTEGER;
+ }
+ else
+ ret=(*a);
+
+ 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 OPENSSL_malloc stuff, even for 0 bytes otherwise it
+ * signifies a missing NULL parameter. */
+ s=(unsigned char *)OPENSSL_malloc((int)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,(int)len);
+ p+=len;
+ }
+
+ if (ret->data != NULL) OPENSSL_free(ret->data);
+ ret->data=s;
+ ret->length=(int)len;
+ if (a != NULL) (*a)=ret;
+ *pp=p;
+ return(ret);
+err:
+ OPENSSL_PUT_ERROR(ASN1, d2i_ASN1_UINTEGER, i);
+ if ((ret != NULL) && ((a == NULL) || (*a != ret)))
+ M_ASN1_INTEGER_free(ret);
+ return(NULL);
+ }
+
+int ASN1_INTEGER_set(ASN1_INTEGER *a, long v)
+ {
+ int j,k;
+ unsigned int i;
+ unsigned char buf[sizeof(long)+1];
+ long d;
+
+ a->type=V_ASN1_INTEGER;
+ if (a->length < (int)(sizeof(long)+1))
+ {
+ if (a->data != NULL)
+ OPENSSL_free(a->data);
+ if ((a->data=(unsigned char *)OPENSSL_malloc(sizeof(long)+1)) != NULL)
+ memset((char *)a->data,0,sizeof(long)+1);
+ }
+ if (a->data == NULL)
+ {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_INTEGER_set, ERR_R_MALLOC_FAILURE);
+ return(0);
+ }
+ d=v;
+ if (d < 0)
+ {
+ d= -d;
+ a->type=V_ASN1_NEG_INTEGER;
+ }
+
+ for (i=0; i<sizeof(long); i++)
+ {
+ if (d == 0) break;
+ buf[i]=(int)d&0xff;
+ d>>=8;
+ }
+ j=0;
+ for (k=i-1; k >=0; k--)
+ a->data[j++]=buf[k];
+ a->length=j;
+ return(1);
+ }
+
+long ASN1_INTEGER_get(const ASN1_INTEGER *a)
+ {
+ int neg=0,i;
+ long r=0;
+
+ if (a == NULL) return(0L);
+ i=a->type;
+ if (i == V_ASN1_NEG_INTEGER)
+ neg=1;
+ else if (i != V_ASN1_INTEGER)
+ return -1;
+
+ if (a->length > (int)sizeof(long))
+ {
+ /* hmm... a bit ugly, return all ones */
+ return -1;
+ }
+ if (a->data == NULL)
+ return 0;
+
+ for (i=0; i<a->length; i++)
+ {
+ r<<=8;
+ r|=(unsigned char)a->data[i];
+ }
+ if (neg) r= -r;
+ return(r);
+ }
+
+ASN1_INTEGER *BN_to_ASN1_INTEGER(const BIGNUM *bn, ASN1_INTEGER *ai)
+ {
+ ASN1_INTEGER *ret;
+ int len,j;
+
+ if (ai == NULL)
+ ret=M_ASN1_INTEGER_new();
+ else
+ ret=ai;
+ if (ret == NULL)
+ {
+ OPENSSL_PUT_ERROR(ASN1, BN_to_ASN1_INTEGER, ASN1_R_NESTED_ASN1_ERROR);
+ 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=OPENSSL_realloc(ret->data, len+4);
+ if (!new_data)
+ {
+ OPENSSL_PUT_ERROR(ASN1, BN_to_ASN1_INTEGER, 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) M_ASN1_INTEGER_free(ret);
+ return(NULL);
+ }
+
+BIGNUM *ASN1_INTEGER_to_BN(const ASN1_INTEGER *ai, BIGNUM *bn)
+ {
+ BIGNUM *ret;
+
+ if ((ret=BN_bin2bn(ai->data,ai->length,bn)) == NULL)
+ OPENSSL_PUT_ERROR(ASN1, ASN1_INTEGER_to_BN, ASN1_R_BN_LIB);
+ else if(ai->type == V_ASN1_NEG_INTEGER)
+ BN_set_negative(ret, 1);
+ return(ret);
+ }
diff --git a/src/crypto/asn1/a_mbstr.c b/src/crypto/asn1/a_mbstr.c
new file mode 100644
index 0000000..9abe659
--- /dev/null
+++ b/src/crypto/asn1/a_mbstr.c
@@ -0,0 +1,390 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/asn1.h>
+
+#include <string.h>
+
+#include <openssl/err.h>
+#include <openssl/mem.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);
+}
+
+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;
+ char strbuf[32];
+ int (*cpyfunc)(unsigned long,void *) = NULL;
+ if(len == -1) 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) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_mbstring_ncopy, ASN1_R_INVALID_BMPSTRING_LENGTH);
+ return -1;
+ }
+ nchar = len >> 1;
+ break;
+
+ case MBSTRING_UNIV:
+ if(len & 3) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_mbstring_ncopy, 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) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_mbstring_ncopy, ASN1_R_INVALID_UTF8STRING);
+ return -1;
+ }
+ break;
+
+ case MBSTRING_ASC:
+ nchar = len;
+ break;
+
+ default:
+ OPENSSL_PUT_ERROR(ASN1, ASN1_mbstring_ncopy, ASN1_R_UNKNOWN_FORMAT);
+ return -1;
+ }
+
+ if((minsize > 0) && (nchar < minsize)) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_mbstring_ncopy, ASN1_R_STRING_TOO_SHORT);
+ BIO_snprintf(strbuf, sizeof strbuf, "%ld", minsize);
+ ERR_add_error_data(2, "minsize=", strbuf);
+ return -1;
+ }
+
+ if((maxsize > 0) && (nchar > maxsize)) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_mbstring_ncopy, ASN1_R_STRING_TOO_LONG);
+ BIO_snprintf(strbuf, sizeof strbuf, "%ld", maxsize);
+ ERR_add_error_data(2, "maxsize=", strbuf);
+ return -1;
+ }
+
+ /* Now work out minimal type (if any) */
+ if(traverse_string(in, len, inform, type_str, &mask) < 0) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_mbstring_ncopy, 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;
+ OPENSSL_free(dest->data);
+ dest->data = NULL;
+ }
+ dest->type = str_type;
+ } else {
+ free_out = 1;
+ dest = ASN1_STRING_type_new(str_type);
+ if(!dest) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_mbstring_ncopy, 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)) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_mbstring_ncopy, ERR_R_MALLOC_FAILURE);
+ return -1;
+ }
+ 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;
+ traverse_string(in, len, inform, out_utf8, &outlen);
+ cpyfunc = cpy_utf8;
+ break;
+ }
+ if(!(p = OPENSSL_malloc(outlen + 1))) {
+ if(free_out) ASN1_STRING_free(dest);
+ OPENSSL_PUT_ERROR(ASN1, ASN1_mbstring_ncopy, ERR_R_MALLOC_FAILURE);
+ return -1;
+ }
+ dest->length = outlen;
+ dest->data = p;
+ p[outlen] = 0;
+ traverse_string(in, len, inform, cpyfunc, &p);
+ return str_type;
+}
+
+/* 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) {
+ if(inform == MBSTRING_ASC) {
+ value = *p++;
+ len--;
+ } else if(inform == MBSTRING_BMP) {
+ value = *p++ << 8;
+ value |= *p++;
+ len -= 2;
+ } else if(inform == MBSTRING_UNIV) {
+ value = ((unsigned long)*p++) << 24;
+ value |= ((unsigned long)*p++) << 16;
+ value |= *p++ << 8;
+ value |= *p++;
+ len -= 4;
+ } else {
+ ret = UTF8_getc(p, len, &value);
+ if(ret < 0) return -1;
+ len -= ret;
+ p += ret;
+ }
+ 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;
+ outlen = arg;
+ *outlen += UTF8_putc(NULL, -1, value);
+ 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 = (unsigned char) 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++ = (unsigned char) ((value >> 8) & 0xff);
+ *q = (unsigned char) (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++ = (unsigned char) ((value >> 24) & 0xff);
+ *q++ = (unsigned char) ((value >> 16) & 0xff);
+ *q++ = (unsigned char) ((value >> 8) & 0xff);
+ *q = (unsigned char) (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/src/crypto/asn1/a_object.c b/src/crypto/asn1/a_object.c
new file mode 100644
index 0000000..189886c
--- /dev/null
+++ b/src/crypto/asn1/a_object.c
@@ -0,0 +1,412 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/asn1.h>
+
+#include <limits.h>
+#include <string.h>
+
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+
+
+int i2d_ASN1_OBJECT(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);
+ }
+
+int a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num)
+ {
+ int i,first,len=0,c, use_bn;
+ char ftmp[24], *tmp = ftmp;
+ int tmpsize = sizeof ftmp;
+ const char *p;
+ unsigned long l;
+ BIGNUM *bl = NULL;
+
+ if (num == 0)
+ return(0);
+ else if (num == -1)
+ num=strlen(buf);
+
+ p=buf;
+ c= *(p++);
+ num--;
+ if ((c >= '0') && (c <= '2'))
+ {
+ first= c-'0';
+ }
+ else
+ {
+ OPENSSL_PUT_ERROR(ASN1, a2d_ASN1_OBJECT, ASN1_R_FIRST_NUM_TOO_LARGE);
+ goto err;
+ }
+
+ if (num <= 0)
+ {
+ OPENSSL_PUT_ERROR(ASN1, a2d_ASN1_OBJECT, ASN1_R_MISSING_SECOND_NUMBER);
+ goto err;
+ }
+ c= *(p++);
+ num--;
+ for (;;)
+ {
+ if (num <= 0) break;
+ if ((c != '.') && (c != ' '))
+ {
+ OPENSSL_PUT_ERROR(ASN1, a2d_ASN1_OBJECT, ASN1_R_INVALID_SEPARATOR);
+ goto err;
+ }
+ l=0;
+ use_bn = 0;
+ for (;;)
+ {
+ if (num <= 0) break;
+ num--;
+ c= *(p++);
+ if ((c == ' ') || (c == '.'))
+ break;
+ if ((c < '0') || (c > '9'))
+ {
+ OPENSSL_PUT_ERROR(ASN1, a2d_ASN1_OBJECT, ASN1_R_INVALID_DIGIT);
+ goto err;
+ }
+ if (!use_bn && l >= ((ULONG_MAX - 80) / 10L))
+ {
+ use_bn = 1;
+ if (!bl)
+ bl = BN_new();
+ if (!bl || !BN_set_word(bl, l))
+ goto err;
+ }
+ if (use_bn)
+ {
+ if (!BN_mul_word(bl, 10L)
+ || !BN_add_word(bl, c-'0'))
+ goto err;
+ }
+ else
+ l=l*10L+(long)(c-'0');
+ }
+ if (len == 0)
+ {
+ if ((first < 2) && (l >= 40))
+ {
+ OPENSSL_PUT_ERROR(ASN1, a2d_ASN1_OBJECT, ASN1_R_SECOND_NUMBER_TOO_LARGE);
+ goto err;
+ }
+ if (use_bn)
+ {
+ if (!BN_add_word(bl, first * 40))
+ goto err;
+ }
+ else
+ l+=(long)first*40;
+ }
+ i=0;
+ if (use_bn)
+ {
+ int blsize;
+ blsize = BN_num_bits(bl);
+ blsize = (blsize + 6)/7;
+ if (blsize > tmpsize)
+ {
+ if (tmp != ftmp)
+ OPENSSL_free(tmp);
+ tmpsize = blsize + 32;
+ tmp = OPENSSL_malloc(tmpsize);
+ if (!tmp)
+ goto err;
+ }
+ while(blsize--)
+ tmp[i++] = (unsigned char)BN_div_word(bl, 0x80L);
+ }
+ else
+ {
+
+ for (;;)
+ {
+ tmp[i++]=(unsigned char)l&0x7f;
+ l>>=7L;
+ if (l == 0L) break;
+ }
+
+ }
+ if (out != NULL)
+ {
+ if (len+i > olen)
+ {
+ OPENSSL_PUT_ERROR(ASN1, a2d_ASN1_OBJECT, ASN1_R_BUFFER_TOO_SMALL);
+ goto err;
+ }
+ while (--i > 0)
+ out[len++]=tmp[i]|0x80;
+ out[len++]=tmp[0];
+ }
+ else
+ len+=i;
+ }
+ if (tmp != ftmp)
+ OPENSSL_free(tmp);
+ if (bl)
+ BN_free(bl);
+ return(len);
+err:
+ if (tmp != ftmp)
+ OPENSSL_free(tmp);
+ if (bl)
+ BN_free(bl);
+ return(0);
+ }
+
+int i2t_ASN1_OBJECT(char *buf, int buf_len, ASN1_OBJECT *a)
+{
+ return OBJ_obj2txt(buf, buf_len, a, 0);
+}
+
+int i2a_ASN1_OBJECT(BIO *bp, ASN1_OBJECT *a)
+ {
+ char buf[80], *p = buf;
+ int i;
+
+ if ((a == NULL) || (a->data == NULL))
+ return(BIO_write(bp,"NULL",4));
+ i=i2t_ASN1_OBJECT(buf,sizeof buf,a);
+ if (i > (int)(sizeof(buf) - 1))
+ {
+ p = OPENSSL_malloc(i + 1);
+ if (!p)
+ return -1;
+ i2t_ASN1_OBJECT(p,i + 1,a);
+ }
+ if (i <= 0)
+ return BIO_write(bp, "<INVALID>", 9);
+ BIO_write(bp,p,i);
+ if (p != buf)
+ OPENSSL_free(p);
+ return(i);
+ }
+
+ASN1_OBJECT *d2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
+ long length)
+{
+ const unsigned char *p;
+ long len;
+ int tag,xclass;
+ int inf,i;
+ ASN1_OBJECT *ret = NULL;
+ 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_OBJECT)
+ {
+ i=ASN1_R_EXPECTING_AN_OBJECT;
+ goto err;
+ }
+ ret = c2i_ASN1_OBJECT(a, &p, len);
+ if(ret) *pp = p;
+ return ret;
+err:
+ OPENSSL_PUT_ERROR(ASN1, d2i_ASN1_OBJECT, i);
+ return(NULL);
+}
+
+ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
+ long len)
+ {
+ ASN1_OBJECT *ret=NULL;
+ const unsigned char *p;
+ unsigned char *data;
+ int i, length;
+
+ /* Sanity check OID encoding.
+ * Need at least one content octet.
+ * MSB must be clear in the last octet.
+ * can't have leading 0x80 in subidentifiers, see: X.690 8.19.2
+ */
+ if (len <= 0 || len > INT_MAX || pp == NULL || (p = *pp) == NULL ||
+ p[len - 1] & 0x80)
+ {
+ OPENSSL_PUT_ERROR(ASN1, c2i_ASN1_OBJECT, ASN1_R_INVALID_OBJECT_ENCODING);
+ return NULL;
+ }
+ /* Now 0 < len <= INT_MAX, so the cast is safe. */
+ length = (int)len;
+ for (i = 0; i < length; i++, p++)
+ {
+ if (*p == 0x80 && (!i || !(p[-1] & 0x80)))
+ {
+ OPENSSL_PUT_ERROR(ASN1, c2i_ASN1_OBJECT, ASN1_R_INVALID_OBJECT_ENCODING);
+ return NULL;
+ }
+ }
+
+ /* only the ASN1_OBJECTs from the 'table' will have values
+ * for ->sn or ->ln */
+ if ((a == NULL) || ((*a) == NULL) ||
+ !((*a)->flags & ASN1_OBJECT_FLAG_DYNAMIC))
+ {
+ if ((ret=ASN1_OBJECT_new()) == NULL) return(NULL);
+ }
+ else ret=(*a);
+
+ p= *pp;
+ /* detach data from object */
+ data = (unsigned char *)ret->data;
+ ret->data = NULL;
+ /* once detached we can change it */
+ if ((data == NULL) || (ret->length < length))
+ {
+ ret->length=0;
+ if (data != NULL) OPENSSL_free(data);
+ data=(unsigned char *)OPENSSL_malloc(length);
+ if (data == NULL)
+ { i=ERR_R_MALLOC_FAILURE; goto err; }
+ ret->flags|=ASN1_OBJECT_FLAG_DYNAMIC_DATA;
+ }
+ memcpy(data,p,length);
+ /* reattach data to object, after which it remains const */
+ ret->data =data;
+ ret->length=length;
+ ret->sn=NULL;
+ ret->ln=NULL;
+ /* ret->flags=ASN1_OBJECT_FLAG_DYNAMIC; we know it is dynamic */
+ p+=length;
+
+ if (a != NULL) (*a)=ret;
+ *pp=p;
+ return(ret);
+err:
+ OPENSSL_PUT_ERROR(ASN1, c2i_ASN1_OBJECT, i);
+ if ((ret != NULL) && ((a == NULL) || (*a != ret)))
+ ASN1_OBJECT_free(ret);
+ return(NULL);
+ }
+
+ASN1_OBJECT *ASN1_OBJECT_new(void)
+ {
+ ASN1_OBJECT *ret;
+
+ ret=(ASN1_OBJECT *)OPENSSL_malloc(sizeof(ASN1_OBJECT));
+ if (ret == NULL)
+ {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_OBJECT_new, ERR_R_MALLOC_FAILURE);
+ return(NULL);
+ }
+ ret->length=0;
+ ret->data=NULL;
+ ret->nid=0;
+ ret->sn=NULL;
+ ret->ln=NULL;
+ ret->flags=ASN1_OBJECT_FLAG_DYNAMIC;
+ return(ret);
+ }
+
+void ASN1_OBJECT_free(ASN1_OBJECT *a)
+ {
+ if (a == NULL) return;
+ if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_STRINGS)
+ {
+#ifndef CONST_STRICT /* disable purely for compile-time strict const checking. Doing this on a "real" compile will cause memory leaks */
+ if (a->sn != NULL) OPENSSL_free((void *)a->sn);
+ if (a->ln != NULL) OPENSSL_free((void *)a->ln);
+#endif
+ a->sn=a->ln=NULL;
+ }
+ if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_DATA)
+ {
+ if (a->data != NULL) OPENSSL_free((void *)a->data);
+ a->data=NULL;
+ a->length=0;
+ }
+ if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC)
+ OPENSSL_free(a);
+ }
+
+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));
+ }
diff --git a/src/crypto/asn1/a_octet.c b/src/crypto/asn1/a_octet.c
new file mode 100644
index 0000000..583c9e9
--- /dev/null
+++ b/src/crypto/asn1/a_octet.c
@@ -0,0 +1,70 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/asn1.h>
+
+#include <openssl/err.h>
+#include <openssl/mem.h>
+
+
+ASN1_OCTET_STRING *ASN1_OCTET_STRING_dup(const ASN1_OCTET_STRING *x)
+{ return M_ASN1_OCTET_STRING_dup(x); }
+
+int ASN1_OCTET_STRING_cmp(const ASN1_OCTET_STRING *a, const ASN1_OCTET_STRING *b)
+{ return M_ASN1_OCTET_STRING_cmp(a, b); }
+
+int ASN1_OCTET_STRING_set(ASN1_OCTET_STRING *x, const unsigned char *d, int len)
+{ return M_ASN1_OCTET_STRING_set(x, d, len); }
diff --git a/src/crypto/asn1/a_print.c b/src/crypto/asn1/a_print.c
new file mode 100644
index 0000000..3b6be10
--- /dev/null
+++ b/src/crypto/asn1/a_print.c
@@ -0,0 +1,119 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/asn1.h>
+
+#include <openssl/err.h>
+#include <openssl/mem.h>
+
+
+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 ((*s) && (len-- != 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);
+ }
+
+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);
+ }
diff --git a/src/crypto/asn1/a_strnid.c b/src/crypto/asn1/a_strnid.c
new file mode 100644
index 0000000..df849e1
--- /dev/null
+++ b/src/crypto/asn1/a_strnid.c
@@ -0,0 +1,286 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/asn1.h>
+
+#include <stdlib.h> /* For bsearch */
+#include <string.h>
+
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+
+
+static STACK_OF(ASN1_STRING_TABLE) *stable = NULL;
+static void st_free(ASN1_STRING_TABLE *tbl);
+
+/* This is the global mask for the mbstring functions: this is use 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;
+}
+
+unsigned long ASN1_STRING_get_default_mask(void)
+{
+ return global_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;
+ if(!strncmp(p, "MASK:", 5)) {
+ if(!p[5]) return 0;
+ mask = strtoul(p + 5, &end, 0);
+ if(*end) return 0;
+ } else if(!strcmp(p, "nombstr"))
+ mask = ~((unsigned long)(B_ASN1_BMPSTRING|B_ASN1_UTF8STRING));
+ else if(!strcmp(p, "pkix"))
+ mask = ~((unsigned long)B_ASN1_T61STRING);
+ else if(!strcmp(p, "utf8only")) mask = B_ASN1_UTF8STRING;
+ else if(!strcmp(p, "default"))
+ mask = 0xFFFFFFFFL;
+ else return 0;
+ ASN1_STRING_set_default_mask(mask);
+ return 1;
+}
+
+/* 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) out = &str;
+ tbl = ASN1_STRING_TABLE_get(nid);
+ if(tbl) {
+ mask = tbl->mask;
+ if(!(tbl->flags & STABLE_NO_MASK)) 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;
+}
+
+/* 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_commonName, 1, ub_common_name, DIRSTRING_TYPE, 0},
+{NID_countryName, 2, 2, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK},
+{NID_localityName, 1, ub_locality_name, DIRSTRING_TYPE, 0},
+{NID_stateOrProvinceName, 1, ub_state_name, DIRSTRING_TYPE, 0},
+{NID_organizationName, 1, ub_organization_name, DIRSTRING_TYPE, 0},
+{NID_organizationalUnitName, 1, ub_organization_unit_name, DIRSTRING_TYPE, 0},
+{NID_pkcs9_emailAddress, 1, ub_email_address, B_ASN1_IA5STRING, STABLE_NO_MASK},
+{NID_pkcs9_unstructuredName, 1, -1, PKCS9STRING_TYPE, 0},
+{NID_pkcs9_challengePassword, 1, -1, PKCS9STRING_TYPE, 0},
+{NID_pkcs9_unstructuredAddress, 1, -1, DIRSTRING_TYPE, 0},
+{NID_givenName, 1, ub_name, DIRSTRING_TYPE, 0},
+{NID_surname, 1, ub_name, DIRSTRING_TYPE, 0},
+{NID_initials, 1, ub_name, DIRSTRING_TYPE, 0},
+{NID_serialNumber, 1, ub_serial_number, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK},
+{NID_friendlyName, -1, -1, B_ASN1_BMPSTRING, STABLE_NO_MASK},
+{NID_name, 1, ub_name, DIRSTRING_TYPE, 0},
+{NID_dnQualifier, -1, -1, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK},
+{NID_domainComponent, 1, -1, B_ASN1_IA5STRING, STABLE_NO_MASK},
+{NID_ms_csp_name, -1, -1, B_ASN1_BMPSTRING, STABLE_NO_MASK}
+};
+
+static int sk_table_cmp(const ASN1_STRING_TABLE **a,
+ const ASN1_STRING_TABLE **b)
+{
+ return (*a)->nid - (*b)->nid;
+}
+
+static int table_cmp(const void *in_a, const void *in_b)
+{
+ const ASN1_STRING_TABLE *a = in_a;
+ const ASN1_STRING_TABLE *b = in_b;
+ return a->nid - b->nid;
+}
+
+ASN1_STRING_TABLE *ASN1_STRING_TABLE_get(int nid)
+{
+ int found;
+ size_t idx;
+ ASN1_STRING_TABLE *ttmp;
+ ASN1_STRING_TABLE fnd;
+ fnd.nid = nid;
+
+ ttmp = bsearch(&fnd, tbl_standard, sizeof(tbl_standard)/sizeof(ASN1_STRING_TABLE), sizeof(ASN1_STRING_TABLE), table_cmp);
+ if(ttmp) return ttmp;
+ if(!stable) return NULL;
+ found = sk_ASN1_STRING_TABLE_find(stable, &idx, &fnd);
+ if (!found) return NULL;
+ return sk_ASN1_STRING_TABLE_value(stable, idx);
+}
+
+int ASN1_STRING_TABLE_add(int nid,
+ long minsize, long maxsize, unsigned long mask,
+ unsigned long flags)
+{
+ ASN1_STRING_TABLE *tmp;
+ char new_nid = 0;
+ flags &= ~STABLE_FLAGS_MALLOC;
+ if(!stable) stable = sk_ASN1_STRING_TABLE_new(sk_table_cmp);
+ if(!stable) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_STRING_TABLE_add, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ if(!(tmp = ASN1_STRING_TABLE_get(nid))) {
+ tmp = OPENSSL_malloc(sizeof(ASN1_STRING_TABLE));
+ if(!tmp) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_STRING_TABLE_add, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ tmp->flags = flags | STABLE_FLAGS_MALLOC;
+ tmp->nid = nid;
+ new_nid = 1;
+ } else tmp->flags = (tmp->flags & STABLE_FLAGS_MALLOC) | flags;
+ if(minsize != -1) tmp->minsize = minsize;
+ if(maxsize != -1) tmp->maxsize = maxsize;
+ tmp->mask = mask;
+ if(new_nid) sk_ASN1_STRING_TABLE_push(stable, tmp);
+ return 1;
+}
+
+void ASN1_STRING_TABLE_cleanup(void)
+{
+ STACK_OF(ASN1_STRING_TABLE) *tmp;
+ tmp = stable;
+ if(!tmp) return;
+ stable = NULL;
+ sk_ASN1_STRING_TABLE_pop_free(tmp, st_free);
+}
+
+static void st_free(ASN1_STRING_TABLE *tbl)
+{
+ if(tbl->flags & STABLE_FLAGS_MALLOC) OPENSSL_free(tbl);
+}
+
+
+#ifdef STRING_TABLE_TEST
+
+int
+main(void)
+{
+ ASN1_STRING_TABLE *tmp;
+ int i, last_nid = -1;
+
+ for (tmp = tbl_standard, i = 0;
+ i < sizeof(tbl_standard)/sizeof(ASN1_STRING_TABLE); i++, tmp++)
+ {
+ if (tmp->nid < last_nid)
+ {
+ last_nid = 0;
+ break;
+ }
+ last_nid = tmp->nid;
+ }
+
+ if (last_nid != 0)
+ {
+ printf("Table order OK\n");
+ exit(0);
+ }
+
+ for (tmp = tbl_standard, i = 0;
+ i < sizeof(tbl_standard)/sizeof(ASN1_STRING_TABLE); i++, tmp++)
+ printf("Index %d, NID %d, Name=%s\n", i, tmp->nid,
+ OBJ_nid2ln(tmp->nid));
+
+ return 0;
+}
+
+#endif
diff --git a/src/crypto/asn1/a_time.c b/src/crypto/asn1/a_time.c
new file mode 100644
index 0000000..f0badcc
--- /dev/null
+++ b/src/crypto/asn1/a_time.c
@@ -0,0 +1,220 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/asn1.h>
+
+#include <string.h>
+
+#include <openssl/asn1t.h>
+#include <openssl/buf.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/time_support.h>
+
+#include "asn1_locl.h"
+
+
+/* This is an implementation of the ASN1 Time structure which is:
+ * Time ::= CHOICE {
+ * utcTime UTCTime,
+ * generalTime GeneralizedTime }
+ * written by Steve Henson.
+ */
+
+IMPLEMENT_ASN1_MSTRING(ASN1_TIME, B_ASN1_TIME)
+
+IMPLEMENT_ASN1_FUNCTIONS(ASN1_TIME)
+
+#if 0
+int i2d_ASN1_TIME(ASN1_TIME *a, unsigned char **pp)
+ {
+ if(a->type == V_ASN1_UTCTIME || a->type == V_ASN1_GENERALIZEDTIME)
+ return(i2d_ASN1_bytes((ASN1_STRING *)a,pp,
+ a->type ,V_ASN1_UNIVERSAL));
+ OPENSSL_PUT_ERROR(ASN1, XXX, ASN1_R_EXPECTING_A_TIME);
+ return -1;
+ }
+#endif
+
+
+ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s, time_t t)
+ {
+ return ASN1_TIME_adj(s, t, 0, 0);
+ }
+
+ASN1_TIME *ASN1_TIME_adj(ASN1_TIME *s, time_t t,
+ int offset_day, long offset_sec)
+ {
+ struct tm *ts;
+ struct tm data;
+
+ ts=OPENSSL_gmtime(&t,&data);
+ if (ts == NULL)
+ {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_TIME_adj, ASN1_R_ERROR_GETTING_TIME);
+ return NULL;
+ }
+ if (offset_day || offset_sec)
+ {
+ if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
+ return NULL;
+ }
+ if((ts->tm_year >= 50) && (ts->tm_year < 150))
+ return ASN1_UTCTIME_adj(s, t, offset_day, offset_sec);
+ return ASN1_GENERALIZEDTIME_adj(s, t, offset_day, offset_sec);
+ }
+
+int ASN1_TIME_check(ASN1_TIME *t)
+ {
+ if (t->type == V_ASN1_GENERALIZEDTIME)
+ return ASN1_GENERALIZEDTIME_check(t);
+ else if (t->type == V_ASN1_UTCTIME)
+ return ASN1_UTCTIME_check(t);
+ return 0;
+ }
+
+/* Convert an ASN1_TIME structure to GeneralizedTime */
+ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *t, ASN1_GENERALIZEDTIME **out)
+ {
+ ASN1_GENERALIZEDTIME *ret;
+ char *str;
+ int newlen;
+
+ if (!ASN1_TIME_check(t)) return NULL;
+
+ if (!out || !*out)
+ {
+ if (!(ret = ASN1_GENERALIZEDTIME_new ()))
+ return NULL;
+ if (out) *out = ret;
+ }
+ else ret = *out;
+
+ /* If already GeneralizedTime just copy across */
+ if (t->type == V_ASN1_GENERALIZEDTIME)
+ {
+ if(!ASN1_STRING_set(ret, t->data, t->length))
+ return NULL;
+ return ret;
+ }
+
+ /* grow the string */
+ if (!ASN1_STRING_set(ret, NULL, t->length + 2))
+ return NULL;
+ /* ASN1_STRING_set() allocated 'len + 1' bytes. */
+ newlen = t->length + 2 + 1;
+ str = (char *)ret->data;
+ /* Work out the century and prepend */
+ if (t->data[0] >= '5') BUF_strlcpy(str, "19", newlen);
+ else BUF_strlcpy(str, "20", newlen);
+
+ BUF_strlcat(str, (char *)t->data, newlen);
+
+ return ret;
+ }
+
+int ASN1_TIME_set_string(ASN1_TIME *s, const char *str)
+ {
+ ASN1_TIME t;
+
+ t.length = strlen(str);
+ t.data = (unsigned char *)str;
+ t.flags = 0;
+
+ t.type = V_ASN1_UTCTIME;
+
+ if (!ASN1_TIME_check(&t))
+ {
+ t.type = V_ASN1_GENERALIZEDTIME;
+ if (!ASN1_TIME_check(&t))
+ return 0;
+ }
+
+ if (s && !ASN1_STRING_copy((ASN1_STRING *)s, (ASN1_STRING *)&t))
+ return 0;
+
+ return 1;
+ }
+
+static int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *t)
+ {
+ if (t == NULL)
+ {
+ time_t now_t;
+ time(&now_t);
+ if (OPENSSL_gmtime(&now_t, tm))
+ return 1;
+ return 0;
+ }
+
+ if (t->type == V_ASN1_UTCTIME)
+ return asn1_utctime_to_tm(tm, t);
+ else if (t->type == V_ASN1_GENERALIZEDTIME)
+ return asn1_generalizedtime_to_tm(tm, t);
+
+ return 0;
+ }
+
+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(&tm_from, from))
+ return 0;
+ if (!asn1_time_to_tm(&tm_to, to))
+ return 0;
+ return OPENSSL_gmtime_diff(pday, psec, &tm_from, &tm_to);
+ }
diff --git a/src/crypto/asn1/a_type.c b/src/crypto/asn1/a_type.c
new file mode 100644
index 0000000..75a17d5
--- /dev/null
+++ b/src/crypto/asn1/a_type.c
@@ -0,0 +1,157 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/asn1.h>
+
+#include <openssl/asn1t.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+
+
+int ASN1_TYPE_get(ASN1_TYPE *a)
+ {
+ if ((a->value.ptr != NULL) || (a->type == V_ASN1_NULL))
+ return(a->type);
+ else
+ return(0);
+ }
+
+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;
+ }
+
+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;
+ }
+
+/* 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_NULL:
+ result = 0; /* They do not have content. */
+ break;
+ case V_ASN1_INTEGER:
+ case V_ASN1_NEG_INTEGER:
+ case V_ASN1_ENUMERATED:
+ case V_ASN1_NEG_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;
+ }
diff --git a/src/crypto/asn1/a_utctm.c b/src/crypto/asn1/a_utctm.c
new file mode 100644
index 0000000..7a3f5f6
--- /dev/null
+++ b/src/crypto/asn1/a_utctm.c
@@ -0,0 +1,341 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/asn1.h>
+
+#include <string.h>
+
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/time_support.h>
+
+
+#if 0
+int i2d_ASN1_UTCTIME(ASN1_UTCTIME *a, unsigned char **pp)
+ {
+ return(i2d_ASN1_bytes((ASN1_STRING *)a,pp,
+ V_ASN1_UTCTIME,V_ASN1_UNIVERSAL));
+ }
+
+
+ASN1_UTCTIME *d2i_ASN1_UTCTIME(ASN1_UTCTIME **a, unsigned char **pp,
+ long length)
+ {
+ ASN1_UTCTIME *ret=NULL;
+
+ ret=(ASN1_UTCTIME *)d2i_ASN1_bytes((ASN1_STRING **)a,pp,length,
+ V_ASN1_UTCTIME,V_ASN1_UNIVERSAL);
+ if (ret == NULL)
+ {
+ OPENSSL_PUT_ERROR(ASN1, XXX, ERR_R_NESTED_ASN1_ERROR);
+ return(NULL);
+ }
+ if (!ASN1_UTCTIME_check(ret))
+ {
+ OPENSSL_PUT_ERROR(ASN1, XXX, ASN1_R_INVALID_TIME_FORMAT);
+ goto err;
+ }
+
+ return(ret);
+err:
+ if ((ret != NULL) && ((a == NULL) || (*a != ret)))
+ M_ASN1_UTCTIME_free(ret);
+ return(NULL);
+ }
+
+#endif
+
+int asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d)
+ {
+ static const int min[8]={ 0, 1, 1, 0, 0, 0, 0, 0};
+ static const int max[8]={99,12,31,23,59,59,12,59};
+ char *a;
+ int n,i,l,o;
+
+ if (d->type != V_ASN1_UTCTIME) return(0);
+ l=d->length;
+ a=(char *)d->data;
+ o=0;
+
+ if (l < 11) goto err;
+ for (i=0; i<6; i++)
+ {
+ if ((i == 5) && ((a[o] == 'Z') ||
+ (a[o] == '+') || (a[o] == '-')))
+ {
+ i++;
+ if (tm)
+ tm->tm_sec = 0;
+ break;
+ }
+ if ((a[o] < '0') || (a[o] > '9')) goto err;
+ n= a[o]-'0';
+ if (++o > l) goto err;
+
+ if ((a[o] < '0') || (a[o] > '9')) goto err;
+ n=(n*10)+ a[o]-'0';
+ if (++o > l) goto err;
+
+ if ((n < min[i]) || (n > max[i])) goto err;
+ if (tm)
+ {
+ switch(i)
+ {
+ case 0:
+ tm->tm_year = n < 50 ? n + 100 : n;
+ break;
+ case 1:
+ tm->tm_mon = n - 1;
+ break;
+ case 2:
+ tm->tm_mday = n;
+ break;
+ case 3:
+ tm->tm_hour = n;
+ break;
+ case 4:
+ tm->tm_min = n;
+ break;
+ case 5:
+ tm->tm_sec = n;
+ break;
+ }
+ }
+ }
+ if (a[o] == 'Z')
+ o++;
+ else if ((a[o] == '+') || (a[o] == '-'))
+ {
+ int offsign = a[o] == '-' ? -1 : 1, offset = 0;
+ o++;
+ if (o+4 > l) goto err;
+ for (i=6; i<8; i++)
+ {
+ if ((a[o] < '0') || (a[o] > '9')) goto err;
+ n= a[o]-'0';
+ o++;
+ if ((a[o] < '0') || (a[o] > '9')) goto err;
+ n=(n*10)+ a[o]-'0';
+ if ((n < min[i]) || (n > max[i])) goto err;
+ if (tm)
+ {
+ if (i == 6)
+ offset = n * 3600;
+ else if (i == 7)
+ offset += n * 60;
+ }
+ o++;
+ }
+ if (offset && !OPENSSL_gmtime_adj(tm, 0, offset * offsign))
+ return 0;
+ }
+ return o == l;
+err:
+ return 0;
+ }
+
+int ASN1_UTCTIME_check(const ASN1_UTCTIME *d)
+ {
+ return asn1_utctime_to_tm(NULL, d);
+ }
+
+int ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str)
+ {
+ ASN1_UTCTIME t;
+
+ t.type=V_ASN1_UTCTIME;
+ t.length=strlen(str);
+ t.data=(unsigned char *)str;
+ if (ASN1_UTCTIME_check(&t))
+ {
+ if (s != NULL)
+ {
+ if (!ASN1_STRING_set((ASN1_STRING *)s,
+ (unsigned char *)str,t.length))
+ return 0;
+ s->type = V_ASN1_UTCTIME;
+ }
+ return(1);
+ }
+ else
+ return(0);
+ }
+
+ASN1_UTCTIME *ASN1_UTCTIME_set(ASN1_UTCTIME *s, time_t t)
+ {
+ return ASN1_UTCTIME_adj(s, t, 0, 0);
+ }
+
+ASN1_UTCTIME *ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t,
+ int offset_day, long offset_sec)
+ {
+ char *p;
+ struct tm *ts;
+ struct tm data;
+ size_t len = 20;
+ int free_s = 0;
+
+ if (s == NULL)
+ {
+ free_s = 1;
+ s=M_ASN1_UTCTIME_new();
+ }
+ if (s == NULL)
+ goto err;
+
+
+ ts=OPENSSL_gmtime(&t, &data);
+ if (ts == NULL)
+ goto err;
+
+ if (offset_day || offset_sec)
+ {
+ if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
+ goto err;
+ }
+
+ if((ts->tm_year < 50) || (ts->tm_year >= 150))
+ goto err;
+
+ p=(char *)s->data;
+ if ((p == NULL) || ((size_t)s->length < len))
+ {
+ p=OPENSSL_malloc(len);
+ if (p == NULL)
+ {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_UTCTIME_adj, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ if (s->data != NULL)
+ OPENSSL_free(s->data);
+ s->data=(unsigned char *)p;
+ }
+
+ BIO_snprintf(p,len,"%02d%02d%02d%02d%02d%02dZ",ts->tm_year%100,
+ ts->tm_mon+1,ts->tm_mday,ts->tm_hour,ts->tm_min,ts->tm_sec);
+ s->length=strlen(p);
+ s->type=V_ASN1_UTCTIME;
+ return(s);
+ err:
+ if (free_s && s)
+ M_ASN1_UTCTIME_free(s);
+ return NULL;
+ }
+
+
+int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t)
+ {
+ struct tm stm, ttm;
+ int day, sec;
+
+ if (!asn1_utctime_to_tm(&stm, s))
+ return -2;
+
+ if (!OPENSSL_gmtime(&t, &ttm))
+ return -2;
+
+ if (!OPENSSL_gmtime_diff(&day, &sec, &stm, &ttm))
+ return -2;
+
+ if (day > 0)
+ return 1;
+ if (day < 0)
+ return -1;
+ if (sec > 0)
+ return 1;
+ if (sec < 0)
+ return -1;
+ return 0;
+ }
+
+
+#if 0
+time_t ASN1_UTCTIME_get(const ASN1_UTCTIME *s)
+ {
+ struct tm tm;
+ int offset;
+
+ memset(&tm,'\0',sizeof tm);
+
+#define g2(p) (((p)[0]-'0')*10+(p)[1]-'0')
+ tm.tm_year=g2(s->data);
+ if(tm.tm_year < 50)
+ tm.tm_year+=100;
+ tm.tm_mon=g2(s->data+2)-1;
+ tm.tm_mday=g2(s->data+4);
+ tm.tm_hour=g2(s->data+6);
+ tm.tm_min=g2(s->data+8);
+ tm.tm_sec=g2(s->data+10);
+ if(s->data[12] == 'Z')
+ offset=0;
+ else
+ {
+ offset=g2(s->data+13)*60+g2(s->data+15);
+ if(s->data[12] == '-')
+ offset= -offset;
+ }
+#undef g2
+
+ return mktime(&tm)-offset*60; /* FIXME: mktime assumes the current timezone
+ * instead of UTC, and unless we rewrite OpenSSL
+ * in Lisp we cannot locally change the timezone
+ * without possibly interfering with other parts
+ * of the program. timegm, which uses UTC, is
+ * non-standard.
+ * Also time_t is inappropriate for general
+ * UTC times because it may a 32 bit type. */
+ }
+#endif
diff --git a/src/crypto/asn1/a_utf8.c b/src/crypto/asn1/a_utf8.c
new file mode 100644
index 0000000..ed6e98d
--- /dev/null
+++ b/src/crypto/asn1/a_utf8.c
@@ -0,0 +1,210 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/asn1.h>
+
+#include <openssl/err.h>
+#include <openssl/mem.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(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;
+ ret = 3;
+ } else if((*p & 0xf8) == 0xf0) {
+ 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;
+ ret = 4;
+ } else if((*p & 0xfc) == 0xf8) {
+ if(len < 5) return -1;
+ if( ((p[1] & 0xc0) != 0x80)
+ || ((p[2] & 0xc0) != 0x80)
+ || ((p[3] & 0xc0) != 0x80)
+ || ((p[4] & 0xc0) != 0x80) ) return -3;
+ value = ((unsigned long)(*p++ & 0x3)) << 24;
+ value |= ((unsigned long)(*p++ & 0x3f)) << 18;
+ value |= ((unsigned long)(*p++ & 0x3f)) << 12;
+ value |= (*p++ & 0x3f) << 6;
+ value |= *p++ & 0x3f;
+ if(value < 0x200000) return -4;
+ ret = 5;
+ } else if((*p & 0xfe) == 0xfc) {
+ if(len < 6) return -1;
+ if( ((p[1] & 0xc0) != 0x80)
+ || ((p[2] & 0xc0) != 0x80)
+ || ((p[3] & 0xc0) != 0x80)
+ || ((p[4] & 0xc0) != 0x80)
+ || ((p[5] & 0xc0) != 0x80) ) return -3;
+ value = ((unsigned long)(*p++ & 0x1)) << 30;
+ value |= ((unsigned long)(*p++ & 0x3f)) << 24;
+ value |= ((unsigned long)(*p++ & 0x3f)) << 18;
+ value |= ((unsigned long)(*p++ & 0x3f)) << 12;
+ value |= (*p++ & 0x3f) << 6;
+ value |= *p++ & 0x3f;
+ if(value < 0x4000000) return -4;
+ ret = 6;
+ } else return -2;
+ *val = value;
+ return ret;
+}
+
+/* This takes a character 'value' and writes the UTF8 encoded value in
+ * 'str' where 'str' is a buffer containing 'len' characters. Returns
+ * the number of characters written or -1 if 'len' is too small. 'str' can
+ * be set to NULL in which case it just returns the number of characters.
+ * It will need at most 6 characters.
+ */
+
+int UTF8_putc(unsigned char *str, int len, unsigned long value)
+{
+ if(!str) len = 6; /* Maximum we will need */
+ else if(len <= 0) return -1;
+ if(value < 0x80) {
+ if(str) *str = (unsigned char)value;
+ return 1;
+ }
+ if(value < 0x800) {
+ if(len < 2) return -1;
+ if(str) {
+ *str++ = (unsigned char)(((value >> 6) & 0x1f) | 0xc0);
+ *str = (unsigned char)((value & 0x3f) | 0x80);
+ }
+ return 2;
+ }
+ if(value < 0x10000) {
+ if(len < 3) return -1;
+ if(str) {
+ *str++ = (unsigned char)(((value >> 12) & 0xf) | 0xe0);
+ *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
+ *str = (unsigned char)((value & 0x3f) | 0x80);
+ }
+ return 3;
+ }
+ if(value < 0x200000) {
+ if(len < 4) return -1;
+ if(str) {
+ *str++ = (unsigned char)(((value >> 18) & 0x7) | 0xf0);
+ *str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80);
+ *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
+ *str = (unsigned char)((value & 0x3f) | 0x80);
+ }
+ return 4;
+ }
+ if(value < 0x4000000) {
+ if(len < 5) return -1;
+ if(str) {
+ *str++ = (unsigned char)(((value >> 24) & 0x3) | 0xf8);
+ *str++ = (unsigned char)(((value >> 18) & 0x3f) | 0x80);
+ *str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80);
+ *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
+ *str = (unsigned char)((value & 0x3f) | 0x80);
+ }
+ return 5;
+ }
+ if(len < 6) return -1;
+ if(str) {
+ *str++ = (unsigned char)(((value >> 30) & 0x1) | 0xfc);
+ *str++ = (unsigned char)(((value >> 24) & 0x3f) | 0x80);
+ *str++ = (unsigned char)(((value >> 18) & 0x3f) | 0x80);
+ *str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80);
+ *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
+ *str = (unsigned char)((value & 0x3f) | 0x80);
+ }
+ return 6;
+}
diff --git a/src/crypto/asn1/asn1_error.c b/src/crypto/asn1/asn1_error.c
new file mode 100644
index 0000000..5e9fcaa
--- /dev/null
+++ b/src/crypto/asn1/asn1_error.c
@@ -0,0 +1,203 @@
+/* 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 <openssl/err.h>
+
+#include <openssl/asn1.h>
+
+const ERR_STRING_DATA ASN1_error_string_data[] = {
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_BIT_STRING_set_bit, 0), "ASN1_BIT_STRING_set_bit"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ENUMERATED_set, 0), "ASN1_ENUMERATED_set"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ENUMERATED_to_BN, 0), "ASN1_ENUMERATED_to_BN"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_GENERALIZEDTIME_adj, 0), "ASN1_GENERALIZEDTIME_adj"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_INTEGER_set, 0), "ASN1_INTEGER_set"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_INTEGER_to_BN, 0), "ASN1_INTEGER_to_BN"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_OBJECT_new, 0), "ASN1_OBJECT_new"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_PCTX_new, 0), "ASN1_PCTX_new"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_STRING_TABLE_add, 0), "ASN1_STRING_TABLE_add"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_STRING_set, 0), "ASN1_STRING_set"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_STRING_type_new, 0), "ASN1_STRING_type_new"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_TIME_adj, 0), "ASN1_TIME_adj"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_UTCTIME_adj, 0), "ASN1_UTCTIME_adj"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_d2i_fp, 0), "ASN1_d2i_fp"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_dup, 0), "ASN1_dup"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_get_object, 0), "ASN1_get_object"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_i2d_bio, 0), "ASN1_i2d_bio"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_i2d_fp, 0), "ASN1_i2d_fp"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_item_d2i_fp, 0), "ASN1_item_d2i_fp"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_item_dup, 0), "ASN1_item_dup"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_item_ex_d2i, 0), "ASN1_item_ex_d2i"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_item_i2d_bio, 0), "ASN1_item_i2d_bio"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_item_i2d_fp, 0), "ASN1_item_i2d_fp"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_item_pack, 0), "ASN1_item_pack"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_item_unpack, 0), "ASN1_item_unpack"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_mbstring_ncopy, 0), "ASN1_mbstring_ncopy"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_pack_string, 0), "ASN1_pack_string"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_seq_pack, 0), "ASN1_seq_pack"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_seq_unpack, 0), "ASN1_seq_unpack"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_template_new, 0), "ASN1_template_new"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_unpack_string, 0), "ASN1_unpack_string"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_BIO_new_NDEF, 0), "BIO_new_NDEF"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_BN_to_ASN1_ENUMERATED, 0), "BN_to_ASN1_ENUMERATED"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_BN_to_ASN1_INTEGER, 0), "BN_to_ASN1_INTEGER"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_a2d_ASN1_OBJECT, 0), "a2d_ASN1_OBJECT"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_a2i_ASN1_ENUMERATED, 0), "a2i_ASN1_ENUMERATED"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_a2i_ASN1_INTEGER, 0), "a2i_ASN1_INTEGER"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_a2i_ASN1_STRING, 0), "a2i_ASN1_STRING"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_asn1_check_tlen, 0), "asn1_check_tlen"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_asn1_collate_primitive, 0), "asn1_collate_primitive"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_asn1_collect, 0), "asn1_collect"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_asn1_d2i_ex_primitive, 0), "asn1_d2i_ex_primitive"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_asn1_d2i_read_bio, 0), "asn1_d2i_read_bio"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_asn1_do_adb, 0), "asn1_do_adb"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_asn1_ex_c2i, 0), "asn1_ex_c2i"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_asn1_find_end, 0), "asn1_find_end"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_asn1_item_ex_combine_new, 0), "asn1_item_ex_combine_new"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_asn1_template_ex_d2i, 0), "asn1_template_ex_d2i"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_asn1_template_noexp_d2i, 0), "asn1_template_noexp_d2i"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_c2i_ASN1_BIT_STRING, 0), "c2i_ASN1_BIT_STRING"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_c2i_ASN1_INTEGER, 0), "c2i_ASN1_INTEGER"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_c2i_ASN1_OBJECT, 0), "c2i_ASN1_OBJECT"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_collect_data, 0), "collect_data"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_d2i_ASN1_BOOLEAN, 0), "d2i_ASN1_BOOLEAN"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_d2i_ASN1_OBJECT, 0), "d2i_ASN1_OBJECT"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_d2i_ASN1_UINTEGER, 0), "d2i_ASN1_UINTEGER"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_d2i_ASN1_UTCTIME, 0), "d2i_ASN1_UTCTIME"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_d2i_ASN1_bytes, 0), "d2i_ASN1_bytes"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_d2i_ASN1_type_bytes, 0), "d2i_ASN1_type_bytes"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_i2d_ASN1_TIME, 0), "i2d_ASN1_TIME"},
+ {ERR_PACK(ERR_LIB_ASN1, ASN1_F_long_c2i, 0), "long_c2i"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ADDING_OBJECT), "ADDING_OBJECT"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ASN1_LENGTH_MISMATCH), "ASN1_LENGTH_MISMATCH"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ASN1_PARSE_ERROR), "ASN1_PARSE_ERROR"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ASN1_SIG_PARSE_ERROR), "ASN1_SIG_PARSE_ERROR"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_AUX_ERROR), "AUX_ERROR"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_BAD_CLASS), "BAD_CLASS"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_BAD_GET_ASN1_OBJECT_CALL), "BAD_GET_ASN1_OBJECT_CALL"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_BAD_OBJECT_HEADER), "BAD_OBJECT_HEADER"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_BAD_PASSWORD_READ), "BAD_PASSWORD_READ"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_BAD_TAG), "BAD_TAG"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_BMPSTRING_IS_WRONG_LENGTH), "BMPSTRING_IS_WRONG_LENGTH"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_BN_LIB), "BN_LIB"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_BOOLEAN_IS_WRONG_LENGTH), "BOOLEAN_IS_WRONG_LENGTH"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_BUFFER_TOO_SMALL), "BUFFER_TOO_SMALL"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER), "CIPHER_HAS_NO_OBJECT_IDENTIFIER"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_CONTEXT_NOT_INITIALISED), "CONTEXT_NOT_INITIALISED"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_DATA_IS_WRONG), "DATA_IS_WRONG"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_DECODE_ERROR), "DECODE_ERROR"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_DECODING_ERROR), "DECODING_ERROR"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_DEPTH_EXCEEDED), "DEPTH_EXCEEDED"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ENCODE_ERROR), "ENCODE_ERROR"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ERROR_GETTING_TIME), "ERROR_GETTING_TIME"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ERROR_LOADING_SECTION), "ERROR_LOADING_SECTION"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ERROR_PARSING_SET_ELEMENT), "ERROR_PARSING_SET_ELEMENT"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ERROR_SETTING_CIPHER_PARAMS), "ERROR_SETTING_CIPHER_PARAMS"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_EXPECTING_AN_ASN1_SEQUENCE), "EXPECTING_AN_ASN1_SEQUENCE"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_EXPECTING_AN_INTEGER), "EXPECTING_AN_INTEGER"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_EXPECTING_AN_OBJECT), "EXPECTING_AN_OBJECT"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_EXPECTING_A_BOOLEAN), "EXPECTING_A_BOOLEAN"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_EXPECTING_A_TIME), "EXPECTING_A_TIME"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_EXPLICIT_LENGTH_MISMATCH), "EXPLICIT_LENGTH_MISMATCH"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED), "EXPLICIT_TAG_NOT_CONSTRUCTED"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_FIELD_MISSING), "FIELD_MISSING"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_FIRST_NUM_TOO_LARGE), "FIRST_NUM_TOO_LARGE"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_HEADER_TOO_LONG), "HEADER_TOO_LONG"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_BITSTRING_FORMAT), "ILLEGAL_BITSTRING_FORMAT"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_BOOLEAN), "ILLEGAL_BOOLEAN"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_CHARACTERS), "ILLEGAL_CHARACTERS"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_FORMAT), "ILLEGAL_FORMAT"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_HEX), "ILLEGAL_HEX"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_IMPLICIT_TAG), "ILLEGAL_IMPLICIT_TAG"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_INTEGER), "ILLEGAL_INTEGER"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_NESTED_TAGGING), "ILLEGAL_NESTED_TAGGING"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_NULL), "ILLEGAL_NULL"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_NULL_VALUE), "ILLEGAL_NULL_VALUE"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_OBJECT), "ILLEGAL_OBJECT"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_OPTIONAL_ANY), "ILLEGAL_OPTIONAL_ANY"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE), "ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_TAGGED_ANY), "ILLEGAL_TAGGED_ANY"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_TIME_VALUE), "ILLEGAL_TIME_VALUE"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INTEGER_NOT_ASCII_FORMAT), "INTEGER_NOT_ASCII_FORMAT"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG), "INTEGER_TOO_LARGE_FOR_LONG"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_BIT_STRING_BITS_LEFT), "INVALID_BIT_STRING_BITS_LEFT"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_BMPSTRING_LENGTH), "INVALID_BMPSTRING_LENGTH"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_DIGIT), "INVALID_DIGIT"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_MIME_TYPE), "INVALID_MIME_TYPE"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_MODIFIER), "INVALID_MODIFIER"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_NUMBER), "INVALID_NUMBER"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_OBJECT_ENCODING), "INVALID_OBJECT_ENCODING"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_SEPARATOR), "INVALID_SEPARATOR"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_TIME_FORMAT), "INVALID_TIME_FORMAT"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_UNIVERSALSTRING_LENGTH), "INVALID_UNIVERSALSTRING_LENGTH"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_UTF8STRING), "INVALID_UTF8STRING"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_IV_TOO_LARGE), "IV_TOO_LARGE"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_LENGTH_ERROR), "LENGTH_ERROR"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_LIST_ERROR), "LIST_ERROR"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MALLOC_FAILURE), "MALLOC_FAILURE"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MIME_NO_CONTENT_TYPE), "MIME_NO_CONTENT_TYPE"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MIME_PARSE_ERROR), "MIME_PARSE_ERROR"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MIME_SIG_PARSE_ERROR), "MIME_SIG_PARSE_ERROR"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MISSING_ASN1_EOS), "MISSING_ASN1_EOS"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MISSING_EOC), "MISSING_EOC"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MISSING_SECOND_NUMBER), "MISSING_SECOND_NUMBER"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MISSING_VALUE), "MISSING_VALUE"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MSTRING_NOT_UNIVERSAL), "MSTRING_NOT_UNIVERSAL"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MSTRING_WRONG_TAG), "MSTRING_WRONG_TAG"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NESTED_ASN1_ERROR), "NESTED_ASN1_ERROR"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NESTED_ASN1_STRING), "NESTED_ASN1_STRING"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NON_HEX_CHARACTERS), "NON_HEX_CHARACTERS"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NOT_ASCII_FORMAT), "NOT_ASCII_FORMAT"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NOT_ENOUGH_DATA), "NOT_ENOUGH_DATA"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NO_CONTENT_TYPE), "NO_CONTENT_TYPE"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NO_DEFAULT_DIGEST), "NO_DEFAULT_DIGEST"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NO_MATCHING_CHOICE_TYPE), "NO_MATCHING_CHOICE_TYPE"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NO_MULTIPART_BODY_FAILURE), "NO_MULTIPART_BODY_FAILURE"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NO_MULTIPART_BOUNDARY), "NO_MULTIPART_BOUNDARY"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NO_SIG_CONTENT_TYPE), "NO_SIG_CONTENT_TYPE"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NULL_IS_WRONG_LENGTH), "NULL_IS_WRONG_LENGTH"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_OBJECT_NOT_ASCII_FORMAT), "OBJECT_NOT_ASCII_FORMAT"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ODD_NUMBER_OF_CHARS), "ODD_NUMBER_OF_CHARS"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_PRIVATE_KEY_HEADER_MISSING), "PRIVATE_KEY_HEADER_MISSING"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_SECOND_NUMBER_TOO_LARGE), "SECOND_NUMBER_TOO_LARGE"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_SEQUENCE_LENGTH_MISMATCH), "SEQUENCE_LENGTH_MISMATCH"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_SEQUENCE_NOT_CONSTRUCTED), "SEQUENCE_NOT_CONSTRUCTED"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG), "SEQUENCE_OR_SET_NEEDS_CONFIG"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_SHORT_LINE), "SHORT_LINE"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_SIG_INVALID_MIME_TYPE), "SIG_INVALID_MIME_TYPE"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_STREAMING_NOT_SUPPORTED), "STREAMING_NOT_SUPPORTED"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_STRING_TOO_LONG), "STRING_TOO_LONG"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_STRING_TOO_SHORT), "STRING_TOO_SHORT"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_TAG_VALUE_TOO_HIGH), "TAG_VALUE_TOO_HIGH"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD), "THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_TIME_NOT_ASCII_FORMAT), "TIME_NOT_ASCII_FORMAT"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_TOO_LONG), "TOO_LONG"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_TYPE_NOT_CONSTRUCTED), "TYPE_NOT_CONSTRUCTED"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_TYPE_NOT_PRIMITIVE), "TYPE_NOT_PRIMITIVE"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNABLE_TO_DECODE_RSA_KEY), "UNABLE_TO_DECODE_RSA_KEY"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNABLE_TO_DECODE_RSA_PRIVATE_KEY), "UNABLE_TO_DECODE_RSA_PRIVATE_KEY"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNEXPECTED_EOC), "UNEXPECTED_EOC"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH), "UNIVERSALSTRING_IS_WRONG_LENGTH"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNKNOWN_FORMAT), "UNKNOWN_FORMAT"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNKNOWN_OBJECT_TYPE), "UNKNOWN_OBJECT_TYPE"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE), "UNKNOWN_PUBLIC_KEY_TYPE"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNKNOWN_TAG), "UNKNOWN_TAG"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE), "UNSUPPORTED_ANY_DEFINED_BY_TYPE"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNSUPPORTED_CIPHER), "UNSUPPORTED_CIPHER"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNSUPPORTED_ENCRYPTION_ALGORITHM), "UNSUPPORTED_ENCRYPTION_ALGORITHM"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE), "UNSUPPORTED_PUBLIC_KEY_TYPE"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNSUPPORTED_TYPE), "UNSUPPORTED_TYPE"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_WRONG_TAG), "WRONG_TAG"},
+ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_WRONG_TYPE), "WRONG_TYPE"},
+ {0, NULL},
+};
diff --git a/src/crypto/asn1/asn1_lib.c b/src/crypto/asn1/asn1_lib.c
new file mode 100644
index 0000000..1fc2c06
--- /dev/null
+++ b/src/crypto/asn1/asn1_lib.c
@@ -0,0 +1,488 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/asn1.h>
+
+#include <limits.h>
+#include <string.h>
+
+#include <openssl/asn1_mac.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+
+OPENSSL_DECLARE_ERROR_REASON(ASN1, MALLOC_FAILURE);
+
+
+static int asn1_get_length(const unsigned char **pp,int *inf,long *rl,int max);
+static void asn1_put_length(unsigned char **pp, int length);
+
+static int _asn1_check_infinite_end(const unsigned char **p, long len)
+ {
+ /* If there is 0 or 1 byte left, the length check should pick
+ * things up */
+ if (len <= 0)
+ return(1);
+ else if ((len >= 2) && ((*p)[0] == 0) && ((*p)[1] == 0))
+ {
+ (*p)+=2;
+ return(1);
+ }
+ return(0);
+ }
+
+int ASN1_check_infinite_end(unsigned char **p, long len)
+ {
+ return _asn1_check_infinite_end((const unsigned char **)p, len);
+ }
+
+int ASN1_const_check_infinite_end(const unsigned char **p, long len)
+ {
+ return _asn1_check_infinite_end(p, len);
+ }
+
+
+int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag,
+ int *pclass, long omax)
+ {
+ int i,ret;
+ long l;
+ const unsigned char *p= *pp;
+ int tag,xclass,inf;
+ long max=omax;
+
+ if (!max) goto err;
+ ret=(*p&V_ASN1_CONSTRUCTED);
+ xclass=(*p&V_ASN1_PRIVATE);
+ i= *p&V_ASN1_PRIMITIVE_TAG;
+ if (i == V_ASN1_PRIMITIVE_TAG)
+ { /* high-tag */
+ p++;
+ if (--max == 0) goto err;
+ l=0;
+ while (*p&0x80)
+ {
+ l<<=7L;
+ l|= *(p++)&0x7f;
+ if (--max == 0) goto err;
+ if (l > (INT_MAX >> 7L)) goto err;
+ }
+ l<<=7L;
+ l|= *(p++)&0x7f;
+ tag=(int)l;
+ if (--max == 0) goto err;
+ }
+ else
+ {
+ tag=i;
+ p++;
+ if (--max == 0) goto err;
+ }
+ *ptag=tag;
+ *pclass=xclass;
+ if (!asn1_get_length(&p,&inf,plength,(int)max)) goto err;
+
+ if (inf && !(ret & V_ASN1_CONSTRUCTED))
+ goto err;
+
+#if 0
+ fprintf(stderr,"p=%d + *plength=%ld > omax=%ld + *pp=%d (%d > %d)\n",
+ (int)p,*plength,omax,(int)*pp,(int)(p+ *plength),
+ (int)(omax+ *pp));
+
+#endif
+ if (*plength > (omax - (p - *pp)))
+ {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_get_object, ASN1_R_TOO_LONG);
+ /* Set this so that even if things are not long enough
+ * the values are set correctly */
+ ret|=0x80;
+ }
+ *pp=p;
+ return(ret|inf);
+err:
+ OPENSSL_PUT_ERROR(ASN1, ASN1_get_object, ASN1_R_HEADER_TOO_LONG);
+ return(0x80);
+ }
+
+static int asn1_get_length(const unsigned char **pp, int *inf, long *rl, int max)
+ {
+ const unsigned char *p= *pp;
+ unsigned long ret=0;
+ unsigned int i;
+
+ if (max-- < 1) return(0);
+ if (*p == 0x80)
+ {
+ *inf=1;
+ ret=0;
+ p++;
+ }
+ else
+ {
+ *inf=0;
+ i= *p&0x7f;
+ if (*(p++) & 0x80)
+ {
+ if (i > sizeof(long))
+ return 0;
+ if (max-- == 0) return(0);
+ while (i-- > 0)
+ {
+ ret<<=8L;
+ ret|= *(p++);
+ if (max-- == 0) return(0);
+ }
+ }
+ else
+ ret=i;
+ }
+ if (ret > LONG_MAX)
+ return 0;
+ *pp=p;
+ *rl=(long)ret;
+ return(1);
+ }
+
+/* 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;
+ }
+
+int ASN1_put_eoc(unsigned char **pp)
+ {
+ unsigned char *p = *pp;
+ *p++ = 0;
+ *p++ = 0;
+ *pp = p;
+ return 2;
+ }
+
+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);
+ }
+
+static int _asn1_Finish(ASN1_const_CTX *c)
+ {
+ if ((c->inf == (1|V_ASN1_CONSTRUCTED)) && (!c->eos))
+ {
+ if (!ASN1_const_check_infinite_end(&c->p,c->slen))
+ {
+ c->error=ASN1_R_MISSING_ASN1_EOS;
+ return(0);
+ }
+ }
+ if ( ((c->slen != 0) && !(c->inf & 1)) ||
+ ((c->slen < 0) && (c->inf & 1)))
+ {
+ c->error=ASN1_R_ASN1_LENGTH_MISMATCH;
+ return(0);
+ }
+ return(1);
+ }
+
+int asn1_Finish(ASN1_CTX *c)
+ {
+ return _asn1_Finish((ASN1_const_CTX *)c);
+ }
+
+int asn1_const_Finish(ASN1_const_CTX *c)
+ {
+ return _asn1_Finish(c);
+ }
+
+int asn1_GetSequence(ASN1_const_CTX *c, long *length)
+ {
+ const unsigned char *q;
+
+ q=c->p;
+ c->inf=ASN1_get_object(&(c->p),&(c->slen),&(c->tag),&(c->xclass),
+ *length);
+ if (c->inf & 0x80)
+ {
+ c->error=ASN1_R_BAD_GET_ASN1_OBJECT_CALL;
+ return(0);
+ }
+ if (c->tag != V_ASN1_SEQUENCE)
+ {
+ c->error=ASN1_R_EXPECTING_AN_ASN1_SEQUENCE;
+ return(0);
+ }
+ (*length)-=(c->p-q);
+ if (c->max && (*length < 0))
+ {
+ c->error=ASN1_R_ASN1_LENGTH_MISMATCH;
+ return(0);
+ }
+ if (c->inf == (1|V_ASN1_CONSTRUCTED))
+ c->slen= *length+ *(c->pp)-c->p;
+ c->eos=0;
+ return(1);
+ }
+
+int ASN1_STRING_copy(ASN1_STRING *dst, const ASN1_STRING *str)
+ {
+ if (str == NULL)
+ return 0;
+ dst->type = str->type;
+ if (!ASN1_STRING_set(dst,str->data,str->length))
+ return 0;
+ dst->flags = str->flags;
+ return 1;
+ }
+
+ASN1_STRING *ASN1_STRING_dup(const ASN1_STRING *str)
+ {
+ ASN1_STRING *ret;
+ if (!str)
+ return NULL;
+ ret=ASN1_STRING_new();
+ if (!ret)
+ return NULL;
+ if (!ASN1_STRING_copy(ret,str))
+ {
+ ASN1_STRING_free(ret);
+ return NULL;
+ }
+ return ret;
+ }
+
+int ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len)
+ {
+ unsigned char *c;
+ const char *data=_data;
+
+ if (len < 0)
+ {
+ if (data == NULL)
+ return(0);
+ else
+ len=strlen(data);
+ }
+ if ((str->length < len) || (str->data == NULL))
+ {
+ c=str->data;
+ if (c == NULL)
+ str->data=OPENSSL_malloc(len+1);
+ else
+ str->data=OPENSSL_realloc(c,len+1);
+
+ if (str->data == NULL)
+ {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_STRING_set, ERR_R_MALLOC_FAILURE);
+ str->data=c;
+ return(0);
+ }
+ }
+ str->length=len;
+ if (data != NULL)
+ {
+ memcpy(str->data,data,len);
+ /* an allowance for strings :-) */
+ str->data[len]='\0';
+ }
+ return(1);
+ }
+
+void ASN1_STRING_set0(ASN1_STRING *str, void *data, int len)
+ {
+ if (str->data)
+ OPENSSL_free(str->data);
+ str->data = data;
+ str->length = len;
+ }
+
+ASN1_STRING *ASN1_STRING_new(void)
+ {
+ return(ASN1_STRING_type_new(V_ASN1_OCTET_STRING));
+ }
+
+
+ASN1_STRING *ASN1_STRING_type_new(int type)
+ {
+ ASN1_STRING *ret;
+
+ ret=(ASN1_STRING *)OPENSSL_malloc(sizeof(ASN1_STRING));
+ if (ret == NULL)
+ {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_STRING_type_new, ERR_R_MALLOC_FAILURE);
+ return(NULL);
+ }
+ ret->length=0;
+ ret->type=type;
+ ret->data=NULL;
+ ret->flags=0;
+ return(ret);
+ }
+
+void ASN1_STRING_free(ASN1_STRING *a)
+ {
+ if (a == NULL) return;
+ if (a->data && !(a->flags & ASN1_STRING_FLAG_NDEF))
+ OPENSSL_free(a->data);
+ OPENSSL_free(a);
+ }
+
+int ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b)
+ {
+ int i;
+
+ i=(a->length-b->length);
+ if (i == 0)
+ {
+ i=memcmp(a->data,b->data,a->length);
+ if (i == 0)
+ return(a->type-b->type);
+ else
+ return(i);
+ }
+ else
+ return(i);
+ }
+
+void asn1_add_error(const unsigned char *address, int offset)
+ {
+ char buf1[DECIMAL_SIZE(address)+1],buf2[DECIMAL_SIZE(offset)+1];
+
+ BIO_snprintf(buf1,sizeof buf1,"%lu",(unsigned long)address);
+ BIO_snprintf(buf2,sizeof buf2,"%d",offset);
+ ERR_add_error_data(4,"address=",buf1," offset=",buf2);
+ }
+
+int ASN1_STRING_length(const ASN1_STRING *x)
+{ return M_ASN1_STRING_length(x); }
+
+void ASN1_STRING_length_set(ASN1_STRING *x, int len)
+{ M_ASN1_STRING_length_set(x, len); return; }
+
+int ASN1_STRING_type(ASN1_STRING *x)
+{ return M_ASN1_STRING_type(x); }
+
+unsigned char * ASN1_STRING_data(ASN1_STRING *x)
+{ return M_ASN1_STRING_data(x); }
diff --git a/src/crypto/asn1/asn1_locl.h b/src/crypto/asn1/asn1_locl.h
new file mode 100644
index 0000000..ca5f612
--- /dev/null
+++ b/src/crypto/asn1/asn1_locl.h
@@ -0,0 +1,73 @@
+/* asn1t.h */
+/* 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).
+ *
+ */
+
+/* Internal ASN1 structures and functions: not for application use */
+
+int asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d);
+int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d);
+
+/* 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 */;
diff --git a/src/crypto/asn1/asn1_par.c b/src/crypto/asn1/asn1_par.c
new file mode 100644
index 0000000..53b11fe
--- /dev/null
+++ b/src/crypto/asn1/asn1_par.c
@@ -0,0 +1,435 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/asn1.h>
+
+#include <openssl/bio.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+
+
+static int asn1_print_info(BIO *bp, int tag, int xclass,int constructed,
+ int indent);
+static int asn1_parse2(BIO *bp, const unsigned char **pp, long length,
+ int offset, int depth, int indent, int dump);
+static int asn1_print_info(BIO *bp, int tag, int xclass, int constructed,
+ int indent)
+ {
+ static const char fmt[]="%-18s";
+ char str[128];
+ const char *p;
+
+ if (constructed & V_ASN1_CONSTRUCTED)
+ p="cons: ";
+ else
+ p="prim: ";
+ if (BIO_write(bp,p,6) < 6) goto err;
+ BIO_indent(bp,indent,128);
+
+ p=str;
+ if ((xclass & V_ASN1_PRIVATE) == V_ASN1_PRIVATE)
+ BIO_snprintf(str,sizeof str,"priv [ %d ] ",tag);
+ else if ((xclass & V_ASN1_CONTEXT_SPECIFIC) == V_ASN1_CONTEXT_SPECIFIC)
+ BIO_snprintf(str,sizeof str,"cont [ %d ]",tag);
+ else if ((xclass & V_ASN1_APPLICATION) == V_ASN1_APPLICATION)
+ BIO_snprintf(str,sizeof str,"appl [ %d ]",tag);
+ else if (tag > 30)
+ BIO_snprintf(str,sizeof str,"<ASN1 %d>",tag);
+ else
+ p = ASN1_tag2str(tag);
+
+ if (BIO_printf(bp,fmt,p) <= 0)
+ goto err;
+ return(1);
+err:
+ return(0);
+ }
+
+int ASN1_parse(BIO *bp, const unsigned char *pp, long len, int indent)
+ {
+ return(asn1_parse2(bp,&pp,len,0,0,indent,0));
+ }
+
+int ASN1_parse_dump(BIO *bp, const unsigned char *pp, long len, int indent, int dump)
+ {
+ return(asn1_parse2(bp,&pp,len,0,0,indent,dump));
+ }
+
+static int asn1_parse2(BIO *bp, const unsigned char **pp, long length, int offset,
+ int depth, int indent, int dump)
+ {
+ const unsigned char *p,*ep,*tot,*op,*opp;
+ long len;
+ int tag,xclass,ret=0;
+ int nl,hl,j,r;
+ ASN1_OBJECT *o=NULL;
+ ASN1_OCTET_STRING *os=NULL;
+ /* ASN1_BMPSTRING *bmp=NULL;*/
+ int dump_indent;
+
+#if 0
+ dump_indent = indent;
+#else
+ dump_indent = 6; /* Because we know BIO_dump_indent() */
+#endif
+ p= *pp;
+ tot=p+length;
+ op=p-1;
+ while ((p < tot) && (op < p))
+ {
+ op=p;
+ j=ASN1_get_object(&p,&len,&tag,&xclass,length);
+#ifdef LINT
+ j=j;
+#endif
+ 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)) break;
+ }
+ }
+ else
+ while (p < ep)
+ {
+ r=asn1_parse2(bp,&p,(long)len,
+ 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)
+ {
+ int ii;
+
+ opp=op;
+ ii=d2i_ASN1_BOOLEAN(NULL,&opp,len+hl);
+ if (ii < 0)
+ {
+ if (BIO_write(bp,"Bad boolean\n",12) <= 0)
+ goto end;
+ }
+ BIO_printf(bp,":%d",ii);
+ }
+ 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_hexdump(bp, opp,
+ ((dump == -1 || dump >
+ os->length)?os->length:dump),
+ dump_indent))
+ goto end;
+ nl=1;
+ }
+ }
+ if (os != NULL)
+ {
+ M_ASN1_OCTET_STRING_free(os);
+ os=NULL;
+ }
+ }
+ else if (tag == V_ASN1_INTEGER)
+ {
+ ASN1_INTEGER *bs;
+ int i;
+
+ opp=op;
+ bs=d2i_ASN1_INTEGER(NULL,&opp,len+hl);
+ if (bs != NULL)
+ {
+ if (BIO_write(bp,":",1) <= 0) goto end;
+ if (bs->type == V_ASN1_NEG_INTEGER)
+ if (BIO_write(bp,"-",1) <= 0)
+ goto end;
+ for (i=0; i<bs->length; i++)
+ {
+ if (BIO_printf(bp,"%02X",
+ bs->data[i]) <= 0)
+ goto end;
+ }
+ if (bs->length == 0)
+ {
+ if (BIO_write(bp,"00",2) <= 0)
+ goto end;
+ }
+ }
+ else
+ {
+ if (BIO_write(bp,"BAD INTEGER",11) <= 0)
+ goto end;
+ }
+ M_ASN1_INTEGER_free(bs);
+ }
+ else if (tag == V_ASN1_ENUMERATED)
+ {
+ ASN1_ENUMERATED *bs;
+ int i;
+
+ opp=op;
+ bs=d2i_ASN1_ENUMERATED(NULL,&opp,len+hl);
+ if (bs != NULL)
+ {
+ if (BIO_write(bp,":",1) <= 0) goto end;
+ if (bs->type == V_ASN1_NEG_ENUMERATED)
+ if (BIO_write(bp,"-",1) <= 0)
+ goto end;
+ for (i=0; i<bs->length; i++)
+ {
+ if (BIO_printf(bp,"%02X",
+ bs->data[i]) <= 0)
+ goto end;
+ }
+ if (bs->length == 0)
+ {
+ if (BIO_write(bp,"00",2) <= 0)
+ goto end;
+ }
+ }
+ else
+ {
+ if (BIO_write(bp,"BAD ENUMERATED",11) <= 0)
+ goto end;
+ }
+ M_ASN1_ENUMERATED_free(bs);
+ }
+ else if (len > 0 && dump)
+ {
+ if (!nl)
+ {
+ if (BIO_write(bp,"\n",1) <= 0)
+ goto end;
+ }
+ if (!BIO_hexdump(bp,p,
+ ((dump == -1 || dump > len)?len:dump),
+ dump_indent))
+ 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);
+ if (os != NULL) M_ASN1_OCTET_STRING_free(os);
+ *pp=p;
+ return(ret);
+ }
+
+const char *ASN1_tag2str(int tag)
+{
+ static const char * const tag2str[] = {
+ "EOC", "BOOLEAN", "INTEGER", "BIT STRING", "OCTET STRING", /* 0-4 */
+ "NULL", "OBJECT", "OBJECT DESCRIPTOR", "EXTERNAL", "REAL", /* 5-9 */
+ "ENUMERATED", "<ASN1 11>", "UTF8STRING", "<ASN1 13>", /* 10-13 */
+ "<ASN1 14>", "<ASN1 15>", "SEQUENCE", "SET", /* 15-17 */
+ "NUMERICSTRING", "PRINTABLESTRING", "T61STRING", /* 18-20 */
+ "VIDEOTEXSTRING", "IA5STRING", "UTCTIME","GENERALIZEDTIME", /* 21-24 */
+ "GRAPHICSTRING", "VISIBLESTRING", "GENERALSTRING", /* 25-27 */
+ "UNIVERSALSTRING", "<ASN1 29>", "BMPSTRING" /* 28-30 */
+ };
+
+ if((tag == V_ASN1_NEG_INTEGER) || (tag == V_ASN1_NEG_ENUMERATED))
+ tag &= ~0x100;
+
+ if(tag < 0 || tag > 30) return "(unknown)";
+ return tag2str[tag];
+}
+
diff --git a/src/crypto/asn1/asn_pack.c b/src/crypto/asn1/asn_pack.c
new file mode 100644
index 0000000..ee58fa5
--- /dev/null
+++ b/src/crypto/asn1/asn_pack.c
@@ -0,0 +1,104 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/asn1.h>
+
+#include <openssl/err.h>
+#include <openssl/mem.h>
+
+
+/* ASN1_ITEM versions of the above */
+
+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 ())) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_item_pack, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ if (oct) *oct = octmp;
+ } else octmp = *oct;
+
+ if(octmp->data) {
+ OPENSSL_free(octmp->data);
+ octmp->data = NULL;
+ }
+
+ if (!(octmp->length = ASN1_item_i2d(obj, &octmp->data, it))) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_item_pack, ASN1_R_ENCODE_ERROR);
+ return NULL;
+ }
+ if (!octmp->data) {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_item_pack, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ return octmp;
+}
+
+/* Extract an ASN1 object from an ASN1_STRING */
+
+void *ASN1_item_unpack(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)))
+ OPENSSL_PUT_ERROR(ASN1, ASN1_item_unpack, ASN1_R_DECODE_ERROR);
+ return ret;
+}
diff --git a/src/crypto/asn1/bio_asn1.c b/src/crypto/asn1/bio_asn1.c
new file mode 100644
index 0000000..15f233b
--- /dev/null
+++ b/src/crypto/asn1/bio_asn1.c
@@ -0,0 +1,496 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/asn1.h>
+
+#include <assert.h>
+#include <string.h>
+
+#include <openssl/bio.h>
+#include <openssl/mem.h>
+
+
+/* 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_init(BIO_ASN1_BUF_CTX *ctx, int size);
+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=
+ {
+ BIO_TYPE_ASN1,
+ "asn1",
+ asn1_bio_write,
+ asn1_bio_read,
+ asn1_bio_puts,
+ asn1_bio_gets,
+ asn1_bio_ctrl,
+ asn1_bio_new,
+ asn1_bio_free,
+ 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;
+ ctx = OPENSSL_malloc(sizeof(BIO_ASN1_BUF_CTX));
+ if (!ctx)
+ return 0;
+ if (!asn1_bio_init(ctx, DEFAULT_ASN1_BUF_SIZE))
+ {
+ OPENSSL_free(ctx);
+ return 0;
+ }
+ b->init = 1;
+ b->ptr = (char *)ctx;
+ b->flags = 0;
+ return 1;
+ }
+
+static int asn1_bio_init(BIO_ASN1_BUF_CTX *ctx, int size)
+ {
+ ctx->buf = OPENSSL_malloc(size);
+ if (!ctx->buf)
+ return 0;
+ ctx->bufsize = size;
+ ctx->bufpos = 0;
+ ctx->buflen = 0;
+ ctx->copylen = 0;
+ ctx->asn1_class = V_ASN1_UNIVERSAL;
+ ctx->asn1_tag = V_ASN1_OCTET_STRING;
+ ctx->ex_buf = 0;
+ ctx->ex_pos = 0;
+ ctx->ex_len = 0;
+ ctx->state = ASN1_STATE_START;
+ return 1;
+ }
+
+static int asn1_bio_free(BIO *b)
+ {
+ BIO_ASN1_BUF_CTX *ctx;
+ ctx = (BIO_ASN1_BUF_CTX *) b->ptr;
+ if (ctx == NULL)
+ return 0;
+ if (ctx->buf)
+ OPENSSL_free(ctx->buf);
+ OPENSSL_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;
+ unsigned char *p;
+ if (!in || (inl < 0) || (b->next_bio == NULL))
+ return 0;
+ ctx = (BIO_ASN1_BUF_CTX *) b->ptr;
+ if (ctx == 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:
+ ctx->buflen =
+ ASN1_object_size(0, inl, ctx->asn1_tag) - inl;
+ assert(ctx->buflen <= ctx->bufsize);
+ 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)
+ break;
+ 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;
+ ctx = (BIO_ASN1_BUF_CTX *) b->ptr;
+ if (ctx == 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_GET_PREFIX:
+ ex_func = arg2;
+ ex_func->ex_func = ctx->prefix;
+ ex_func->ex_free_func = ctx->prefix_free;
+ 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_GET_SUFFIX:
+ ex_func = arg2;
+ ex_func->ex_func = ctx->suffix;
+ ex_func->ex_free_func = ctx->suffix_free;
+ 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);
+ }
+
+static int asn1_bio_get_ex(BIO *b, int cmd,
+ asn1_ps_func **ex_func, asn1_ps_func **ex_free_func)
+ {
+ BIO_ASN1_EX_FUNCS extmp;
+ int ret;
+ ret = BIO_ctrl(b, cmd, 0, &extmp);
+ if (ret > 0)
+ {
+ *ex_func = extmp.ex_func;
+ *ex_free_func = extmp.ex_free_func;
+ }
+ return ret;
+ }
+
+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_get_prefix(BIO *b, asn1_ps_func **pprefix, asn1_ps_func **pprefix_free)
+ {
+ return asn1_bio_get_ex(b, BIO_C_GET_PREFIX, pprefix, pprefix_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);
+ }
+
+int BIO_asn1_get_suffix(BIO *b, asn1_ps_func **psuffix, asn1_ps_func **psuffix_free)
+ {
+ return asn1_bio_get_ex(b, BIO_C_GET_SUFFIX, psuffix, psuffix_free);
+ }
diff --git a/src/crypto/asn1/bio_ndef.c b/src/crypto/asn1/bio_ndef.c
new file mode 100644
index 0000000..c814814
--- /dev/null
+++ b/src/crypto/asn1/bio_ndef.c
@@ -0,0 +1,248 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/asn1.h>
+
+#include <assert.h>
+
+#include <openssl/asn1t.h>
+#include <openssl/bio.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+
+
+/* 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;
+ const ASN1_AUX *aux = it->funcs;
+ ASN1_STREAM_ARG sarg;
+
+ if (!aux || !aux->asn1_cb)
+ {
+ OPENSSL_PUT_ERROR(ASN1, BIO_new_NDEF, ASN1_R_STREAMING_NOT_SUPPORTED);
+ return NULL;
+ }
+ ndef_aux = OPENSSL_malloc(sizeof(NDEF_SUPPORT));
+ asn_bio = BIO_new(BIO_f_asn1());
+
+ /* ASN1 bio needs to be next to output BIO */
+
+ out = BIO_push(asn_bio, out);
+
+ if (!ndef_aux || !asn_bio || !out)
+ goto err;
+
+ BIO_asn1_set_prefix(asn_bio, ndef_prefix, ndef_prefix_free);
+ BIO_asn1_set_suffix(asn_bio, ndef_suffix, ndef_suffix_free);
+
+ /* Now let callback prepend any digest, cipher etc BIOs
+ * ASN1 structure needs.
+ */
+
+ sarg.out = out;
+ 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 = out;
+
+ BIO_ctrl(asn_bio, BIO_C_SET_EX_ARG, 0, ndef_aux);
+
+ return sarg.ndef_bio;
+
+ err:
+ if (asn_bio)
+ BIO_free(asn_bio);
+ if (ndef_aux)
+ OPENSSL_free(ndef_aux);
+ return NULL;
+ }
+
+static int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg)
+ {
+ NDEF_SUPPORT *ndef_aux;
+ unsigned char *p;
+ int derlen;
+
+ if (!parg)
+ return 0;
+
+ ndef_aux = *(NDEF_SUPPORT **)parg;
+
+ derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it);
+ p = OPENSSL_malloc(derlen);
+ ndef_aux->derbuf = p;
+ *pbuf = p;
+ derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it);
+
+ if (!*ndef_aux->boundary)
+ 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 *ndef_aux;
+
+ if (!parg)
+ return 0;
+
+ ndef_aux = *(NDEF_SUPPORT **)parg;
+
+ if (ndef_aux->derbuf)
+ OPENSSL_free(ndef_aux->derbuf);
+
+ ndef_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 = (NDEF_SUPPORT **)parg;
+ if (!ndef_prefix_free(b, pbuf, plen, parg))
+ return 0;
+ OPENSSL_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;
+ 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;
+
+ derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it);
+ p = OPENSSL_malloc(derlen);
+ ndef_aux->derbuf = p;
+ *pbuf = p;
+ derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it);
+
+ if (!*ndef_aux->boundary)
+ return 0;
+ *pbuf = *ndef_aux->boundary;
+ *plen = derlen - (*ndef_aux->boundary - ndef_aux->derbuf);
+
+ return 1;
+ }
diff --git a/src/crypto/asn1/charmap.pl b/src/crypto/asn1/charmap.pl
new file mode 100644
index 0000000..71bc7b8
--- /dev/null
+++ b/src/crypto/asn1/charmap.pl
@@ -0,0 +1,135 @@
+#!/usr/local/bin/perl -w
+
+# 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).
+
+use strict;
+
+my ($i, @arr);
+
+# Set up an array with the type of ASCII characters
+# Each set bit represents a character property.
+
+# RFC2253 character properties
+my $RFC2253_ESC = 1; # Character escaped with \
+my $ESC_CTRL = 2; # Escaped control character
+# These are used with RFC1779 quoting using "
+my $NOESC_QUOTE = 8; # Not escaped if quoted
+my $PSTRING_CHAR = 0x10; # Valid PrintableString character
+my $RFC2253_FIRST_ESC = 0x20; # Escaped with \ if first character
+my $RFC2253_LAST_ESC = 0x40; # Escaped with \ if last character
+
+for($i = 0; $i < 128; $i++) {
+ # Set the RFC2253 escape characters (control)
+ $arr[$i] = 0;
+ if(($i < 32) || ($i > 126)) {
+ $arr[$i] |= $ESC_CTRL;
+ }
+
+ # Some PrintableString characters
+ if( ( ( $i >= ord("a")) && ( $i <= ord("z")) )
+ || ( ( $i >= ord("A")) && ( $i <= ord("Z")) )
+ || ( ( $i >= ord("0")) && ( $i <= ord("9")) ) ) {
+ $arr[$i] |= $PSTRING_CHAR;
+ }
+}
+
+# Now setup the rest
+
+# Remaining RFC2253 escaped characters
+
+$arr[ord(" ")] |= $NOESC_QUOTE | $RFC2253_FIRST_ESC | $RFC2253_LAST_ESC;
+$arr[ord("#")] |= $NOESC_QUOTE | $RFC2253_FIRST_ESC;
+
+$arr[ord(",")] |= $NOESC_QUOTE | $RFC2253_ESC;
+$arr[ord("+")] |= $NOESC_QUOTE | $RFC2253_ESC;
+$arr[ord("\"")] |= $RFC2253_ESC;
+$arr[ord("\\")] |= $RFC2253_ESC;
+$arr[ord("<")] |= $NOESC_QUOTE | $RFC2253_ESC;
+$arr[ord(">")] |= $NOESC_QUOTE | $RFC2253_ESC;
+$arr[ord(";")] |= $NOESC_QUOTE | $RFC2253_ESC;
+
+# Remaining PrintableString characters
+
+$arr[ord(" ")] |= $PSTRING_CHAR;
+$arr[ord("'")] |= $PSTRING_CHAR;
+$arr[ord("(")] |= $PSTRING_CHAR;
+$arr[ord(")")] |= $PSTRING_CHAR;
+$arr[ord("+")] |= $PSTRING_CHAR;
+$arr[ord(",")] |= $PSTRING_CHAR;
+$arr[ord("-")] |= $PSTRING_CHAR;
+$arr[ord(".")] |= $PSTRING_CHAR;
+$arr[ord("/")] |= $PSTRING_CHAR;
+$arr[ord(":")] |= $PSTRING_CHAR;
+$arr[ord("=")] |= $PSTRING_CHAR;
+$arr[ord("?")] |= $PSTRING_CHAR;
+
+# Now generate the C code
+
+print <<EOF;
+/* Auto generated with chartype.pl script.
+ * Mask of various character properties
+ */
+
+static const unsigned char char_type[] = {
+EOF
+
+for($i = 0; $i < 128; $i++) {
+ print("\n") if($i && (($i % 16) == 0));
+ printf("%2d", $arr[$i]);
+ print(",") if ($i != 127);
+}
+print("\n};\n\n");
+
diff --git a/src/crypto/asn1/f_enum.c b/src/crypto/asn1/f_enum.c
new file mode 100644
index 0000000..530afe5
--- /dev/null
+++ b/src/crypto/asn1/f_enum.c
@@ -0,0 +1,206 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/asn1.h>
+
+#include <openssl/err.h>
+#include <openssl/mem.h>
+
+/* Based on a_int.c: equivalent ENUMERATED functions */
+
+int i2a_ASN1_ENUMERATED(BIO *bp, 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);
+ }
+
+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 num=0,slen=0,first=1;
+
+ 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;
+ again=(buf[i-1] == '\\');
+
+ for (j=0; j<i; j++)
+ {
+ if (!( ((buf[j] >= '0') && (buf[j] <= '9')) ||
+ ((buf[j] >= 'a') && (buf[j] <= 'f')) ||
+ ((buf[j] >= 'A') && (buf[j] <= 'F'))))
+ {
+ i=j;
+ break;
+ }
+ }
+ buf[i]='\0';
+ /* We have now cleared all the crap off the end of the
+ * line */
+ 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;
+ i-=again;
+ if (i%2 != 0)
+ {
+ OPENSSL_PUT_ERROR(ASN1, a2i_ASN1_ENUMERATED, ASN1_R_ODD_NUMBER_OF_CHARS);
+ goto err;
+ }
+ i/=2;
+ if (num+i > slen)
+ {
+ if (s == NULL)
+ sp=(unsigned char *)OPENSSL_malloc(
+ (unsigned int)num+i*2);
+ else
+ sp=(unsigned char *)OPENSSL_realloc(s,
+ (unsigned int)num+i*2);
+ if (sp == NULL)
+ {
+ OPENSSL_PUT_ERROR(ASN1, a2i_ASN1_ENUMERATED, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ s=sp;
+ slen=num+i*2;
+ }
+ 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
+ {
+ OPENSSL_PUT_ERROR(ASN1, a2i_ASN1_ENUMERATED, 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;
+ ret=1;
+err:
+ if (0)
+ {
+err_sl:
+ OPENSSL_PUT_ERROR(ASN1, a2i_ASN1_ENUMERATED, ASN1_R_SHORT_LINE);
+ }
+ if (s != NULL)
+ OPENSSL_free(s);
+ return(ret);
+ }
+
diff --git a/src/crypto/asn1/f_int.c b/src/crypto/asn1/f_int.c
new file mode 100644
index 0000000..2c4fe6f
--- /dev/null
+++ b/src/crypto/asn1/f_int.c
@@ -0,0 +1,210 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/asn1.h>
+
+#include <openssl/err.h>
+#include <openssl/mem.h>
+
+
+int i2a_ASN1_INTEGER(BIO *bp, 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);
+ }
+
+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;
+ again=(buf[i-1] == '\\');
+
+ for (j=0; j<i; j++)
+ {
+ if (!( ((buf[j] >= '0') && (buf[j] <= '9')) ||
+ ((buf[j] >= 'a') && (buf[j] <= 'f')) ||
+ ((buf[j] >= 'A') && (buf[j] <= 'F'))))
+ {
+ i=j;
+ break;
+ }
+ }
+ buf[i]='\0';
+ /* We have now cleared all the crap off the end of the
+ * line */
+ 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;
+ i-=again;
+ if (i%2 != 0)
+ {
+ OPENSSL_PUT_ERROR(ASN1, a2i_ASN1_INTEGER, ASN1_R_ODD_NUMBER_OF_CHARS);
+ goto err;
+ }
+ i/=2;
+ if (num+i > slen)
+ {
+ if (s == NULL)
+ sp=(unsigned char *)OPENSSL_malloc(
+ (unsigned int)num+i*2);
+ else
+ sp=OPENSSL_realloc_clean(s,slen,num+i*2);
+ if (sp == NULL)
+ {
+ OPENSSL_PUT_ERROR(ASN1, a2i_ASN1_INTEGER, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ s=sp;
+ slen=num+i*2;
+ }
+ 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
+ {
+ OPENSSL_PUT_ERROR(ASN1, a2i_ASN1_INTEGER, 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;
+ ret=1;
+err:
+ if (0)
+ {
+err_sl:
+ OPENSSL_PUT_ERROR(ASN1, a2i_ASN1_INTEGER, ASN1_R_SHORT_LINE);
+ }
+ if (s != NULL)
+ OPENSSL_free(s);
+ return(ret);
+ }
+
diff --git a/src/crypto/asn1/f_string.c b/src/crypto/asn1/f_string.c
new file mode 100644
index 0000000..2f53670
--- /dev/null
+++ b/src/crypto/asn1/f_string.c
@@ -0,0 +1,204 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/asn1.h>
+
+#include <openssl/err.h>
+#include <openssl/mem.h>
+
+
+
+int i2a_ASN1_STRING(BIO *bp, ASN1_STRING *a, int type)
+ {
+ 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,"0",1) != 1) goto err;
+ n=1;
+ }
+ 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);
+ }
+
+int a2i_ASN1_STRING(BIO *bp, ASN1_STRING *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;
+
+ 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;
+ again=(buf[i-1] == '\\');
+
+ for (j=i-1; j>0; j--)
+ {
+ if (!( ((buf[j] >= '0') && (buf[j] <= '9')) ||
+ ((buf[j] >= 'a') && (buf[j] <= 'f')) ||
+ ((buf[j] >= 'A') && (buf[j] <= 'F'))))
+ {
+ i=j;
+ break;
+ }
+ }
+ buf[i]='\0';
+ /* We have now cleared all the crap off the end of the
+ * line */
+ if (i < 2) goto err_sl;
+
+ bufp=(unsigned char *)buf;
+
+ k=0;
+ i-=again;
+ if (i%2 != 0)
+ {
+ OPENSSL_PUT_ERROR(ASN1, a2i_ASN1_STRING, ASN1_R_ODD_NUMBER_OF_CHARS);
+ goto err;
+ }
+ i/=2;
+ if (num+i > slen)
+ {
+ if (s == NULL)
+ sp=(unsigned char *)OPENSSL_malloc(
+ (unsigned int)num+i*2);
+ else
+ sp=(unsigned char *)OPENSSL_realloc(s,
+ (unsigned int)num+i*2);
+ if (sp == NULL)
+ {
+ OPENSSL_PUT_ERROR(ASN1, a2i_ASN1_STRING, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ s=sp;
+ slen=num+i*2;
+ }
+ 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
+ {
+ OPENSSL_PUT_ERROR(ASN1, a2i_ASN1_STRING, 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;
+ ret=1;
+err:
+ if (0)
+ {
+err_sl:
+ OPENSSL_PUT_ERROR(ASN1, a2i_ASN1_STRING, ASN1_R_SHORT_LINE);
+ }
+ if (s != NULL)
+ OPENSSL_free(s);
+ return(ret);
+ }
+
diff --git a/src/crypto/asn1/t_bitst.c b/src/crypto/asn1/t_bitst.c
new file mode 100644
index 0000000..1ca6e08
--- /dev/null
+++ b/src/crypto/asn1/t_bitst.c
@@ -0,0 +1,102 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/asn1.h>
+
+#include <string.h>
+
+#include <openssl/mem.h>
+
+
+int ASN1_BIT_STRING_name_print(BIO *out, ASN1_BIT_STRING *bs,
+ BIT_STRING_BITNAME *tbl, int indent)
+{
+ BIT_STRING_BITNAME *bnam;
+ char first = 1;
+ BIO_printf(out, "%*s", indent, "");
+ for(bnam = tbl; bnam->lname; bnam++) {
+ if(ASN1_BIT_STRING_get_bit(bs, bnam->bitnum)) {
+ if(!first) BIO_puts(out, ", ");
+ BIO_puts(out, bnam->lname);
+ first = 0;
+ }
+ }
+ BIO_puts(out, "\n");
+ return 1;
+}
+
+int ASN1_BIT_STRING_set_asc(ASN1_BIT_STRING *bs, char *name, int value,
+ BIT_STRING_BITNAME *tbl)
+{
+ int bitnum;
+ bitnum = ASN1_BIT_STRING_num_asc(name, tbl);
+ if(bitnum < 0) return 0;
+ if(bs) {
+ if(!ASN1_BIT_STRING_set_bit(bs, bitnum, value))
+ return 0;
+ }
+ return 1;
+}
+
+int ASN1_BIT_STRING_num_asc(char *name, BIT_STRING_BITNAME *tbl)
+{
+ BIT_STRING_BITNAME *bnam;
+ for(bnam = tbl; bnam->lname; bnam++) {
+ if(!strcmp(bnam->sname, name) ||
+ !strcmp(bnam->lname, name) ) return bnam->bitnum;
+ }
+ return -1;
+}
diff --git a/src/crypto/asn1/t_pkey.c b/src/crypto/asn1/t_pkey.c
new file mode 100644
index 0000000..6ac9b3d
--- /dev/null
+++ b/src/crypto/asn1/t_pkey.c
@@ -0,0 +1,112 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/asn1.h>
+
+#include <openssl/bio.h>
+#include <openssl/mem.h>
+
+
+int ASN1_bn_print(BIO *bp, const char *number, const BIGNUM *num,
+ unsigned char *buf, int off)
+ {
+ int n,i;
+ const char *neg;
+
+ if (num == NULL) return(1);
+ neg = (BN_is_negative(num))?"-":"";
+ if(!BIO_indent(bp,off,128))
+ return 0;
+ if (BN_is_zero(num))
+ {
+ if (BIO_printf(bp, "%s 0\n", number) <= 0)
+ return 0;
+ return 1;
+ }
+
+ if (BN_num_bytes(num) <= sizeof(long))
+ {
+ if (BIO_printf(bp,"%s %s%lu (%s0x%lx)\n",number,neg,
+ (unsigned long)num->d[0],neg,(unsigned long)num->d[0])
+ <= 0) return(0);
+ }
+ else
+ {
+ buf[0]=0;
+ if (BIO_printf(bp,"%s%s",number,
+ (neg[0] == '-')?" (Negative)":"") <= 0)
+ return(0);
+ n=BN_bn2bin(num,&buf[1]);
+
+ if (buf[1] & 0x80)
+ n++;
+ else buf++;
+
+ for (i=0; i<n; i++)
+ {
+ if ((i%15) == 0)
+ {
+ if(BIO_puts(bp,"\n") <= 0
+ || !BIO_indent(bp,off+4,128))
+ return 0;
+ }
+ if (BIO_printf(bp,"%02x%s",buf[i],((i+1) == n)?"":":")
+ <= 0) return(0);
+ }
+ if (BIO_write(bp,"\n",1) <= 0) return(0);
+ }
+ return(1);
+ }
diff --git a/src/crypto/asn1/tasn_dec.c b/src/crypto/asn1/tasn_dec.c
new file mode 100644
index 0000000..4cece89
--- /dev/null
+++ b/src/crypto/asn1/tasn_dec.c
@@ -0,0 +1,1314 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/asn1.h>
+
+#include <string.h>
+
+#include <openssl/asn1t.h>
+#include <openssl/buf.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+
+
+static int asn1_check_eoc(const unsigned char **in, long len);
+static int asn1_find_end(const unsigned char **in, long len, char inf);
+
+static int asn1_collect(BUF_MEM *buf, const unsigned char **in, long len,
+ char inf, int tag, int aclass, int depth);
+
+static int collect_data(BUF_MEM *buf, const unsigned char **p, long plen);
+
+static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass,
+ char *inf, char *cst,
+ const unsigned char **in, long len,
+ int exptag, int expclass, char opt,
+ ASN1_TLC *ctx);
+
+static int asn1_template_ex_d2i(ASN1_VALUE **pval,
+ const unsigned char **in, long len,
+ const ASN1_TEMPLATE *tt, char opt,
+ ASN1_TLC *ctx);
+static int asn1_template_noexp_d2i(ASN1_VALUE **val,
+ const unsigned char **in, long len,
+ const ASN1_TEMPLATE *tt, char opt,
+ ASN1_TLC *ctx);
+static int asn1_d2i_ex_primitive(ASN1_VALUE **pval,
+ const unsigned char **in, long len,
+ const ASN1_ITEM *it,
+ int tag, int aclass, char opt, ASN1_TLC *ctx);
+
+/* Table to convert tags to bit values, used for MSTRING type */
+static const unsigned long tag2bit[32] = {
+0, 0, 0, B_ASN1_BIT_STRING, /* tags 0 - 3 */
+B_ASN1_OCTET_STRING, 0, 0, B_ASN1_UNKNOWN,/* tags 4- 7 */
+B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN,/* tags 8-11 */
+B_ASN1_UTF8STRING,B_ASN1_UNKNOWN,B_ASN1_UNKNOWN,B_ASN1_UNKNOWN,/* tags 12-15 */
+B_ASN1_SEQUENCE,0,B_ASN1_NUMERICSTRING,B_ASN1_PRINTABLESTRING, /* tags 16-19 */
+B_ASN1_T61STRING,B_ASN1_VIDEOTEXSTRING,B_ASN1_IA5STRING, /* tags 20-22 */
+B_ASN1_UTCTIME, B_ASN1_GENERALIZEDTIME, /* tags 23-24 */
+B_ASN1_GRAPHICSTRING,B_ASN1_ISO64STRING,B_ASN1_GENERALSTRING, /* tags 25-27 */
+B_ASN1_UNIVERSALSTRING,B_ASN1_UNKNOWN,B_ASN1_BMPSTRING,B_ASN1_UNKNOWN, /* tags 28-31 */
+ };
+
+unsigned long ASN1_tag2bit(int tag)
+ {
+ if ((tag < 0) || (tag > 30)) return 0;
+ return tag2bit[tag];
+ }
+
+/* Macro to initialize and invalidate the cache */
+
+#define asn1_tlc_clear(c) if (c) (c)->valid = 0
+/* Version to avoid compiler warning about 'c' always non-NULL */
+#define asn1_tlc_clear_nc(c) (c)->valid = 0
+
+/* Decode an ASN1 item, this currently behaves just
+ * like a standard 'd2i' function. 'in' points to
+ * a buffer to read the data from, in future we will
+ * have more advanced versions that can input data
+ * a piece at a time and this will simply be a special
+ * case.
+ */
+
+ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **pval,
+ const unsigned char **in, long len, const ASN1_ITEM *it)
+ {
+ ASN1_TLC c;
+ ASN1_VALUE *ptmpval = NULL;
+ if (!pval)
+ pval = &ptmpval;
+ asn1_tlc_clear_nc(&c);
+ if (ASN1_item_ex_d2i(pval, in, len, it, -1, 0, 0, &c) > 0)
+ return *pval;
+ return NULL;
+ }
+
+int ASN1_template_d2i(ASN1_VALUE **pval,
+ const unsigned char **in, long len, const ASN1_TEMPLATE *tt)
+ {
+ ASN1_TLC c;
+ asn1_tlc_clear_nc(&c);
+ return asn1_template_ex_d2i(pval, in, len, tt, 0, &c);
+ }
+
+
+/* Decode an item, taking care of IMPLICIT tagging, if any.
+ * If 'opt' set and tag mismatch return -1 to handle OPTIONAL
+ */
+
+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)
+ {
+ const ASN1_TEMPLATE *tt, *errtt = NULL;
+ const ASN1_COMPAT_FUNCS *cf;
+ const ASN1_EXTERN_FUNCS *ef;
+ const ASN1_AUX *aux = it->funcs;
+ ASN1_aux_cb *asn1_cb;
+ const unsigned char *p = NULL, *q;
+ unsigned char *wp=NULL; /* BIG FAT WARNING! BREAKS CONST WHERE USED */
+ unsigned char imphack = 0, oclass;
+ char seq_eoc, seq_nolen, cst, isopt;
+ long tmplen;
+ int i;
+ int otag;
+ int ret = 0;
+ ASN1_VALUE **pchptr, *ptmpval;
+ if (!pval)
+ return 0;
+ if (aux && aux->asn1_cb)
+ asn1_cb = aux->asn1_cb;
+ else asn1_cb = 0;
+
+ switch(it->itype)
+ {
+ case ASN1_ITYPE_PRIMITIVE:
+ if (it->templates)
+ {
+ /* 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 != -1) || opt)
+ {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_item_ex_d2i, ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE);
+ goto err;
+ }
+ return asn1_template_ex_d2i(pval, in, len,
+ it->templates, opt, ctx);
+ }
+ return asn1_d2i_ex_primitive(pval, in, len, it,
+ tag, aclass, opt, ctx);
+ break;
+
+ case ASN1_ITYPE_MSTRING:
+ p = *in;
+ /* Just read in tag and class */
+ ret = asn1_check_tlen(NULL, &otag, &oclass, NULL, NULL,
+ &p, len, -1, 0, 1, ctx);
+ if (!ret)
+ {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_item_ex_d2i, ASN1_R_NESTED_ASN1_ERROR);
+ goto err;
+ }
+
+ /* Must be UNIVERSAL class */
+ if (oclass != V_ASN1_UNIVERSAL)
+ {
+ /* If OPTIONAL, assume this is OK */
+ if (opt) return -1;
+ OPENSSL_PUT_ERROR(ASN1, ASN1_item_ex_d2i, ASN1_R_MSTRING_NOT_UNIVERSAL);
+ goto err;
+ }
+ /* Check tag matches bit map */
+ if (!(ASN1_tag2bit(otag) & it->utype))
+ {
+ /* If OPTIONAL, assume this is OK */
+ if (opt)
+ return -1;
+ OPENSSL_PUT_ERROR(ASN1, ASN1_item_ex_d2i, ASN1_R_MSTRING_WRONG_TAG);
+ goto err;
+ }
+ return asn1_d2i_ex_primitive(pval, in, len,
+ it, otag, 0, 0, ctx);
+
+ case ASN1_ITYPE_EXTERN:
+ /* Use new style d2i */
+ ef = it->funcs;
+ return ef->asn1_ex_d2i(pval, in, len,
+ it, tag, aclass, opt, ctx);
+
+ case ASN1_ITYPE_COMPAT:
+ /* we must resort to old style evil hackery */
+ cf = it->funcs;
+
+ /* If OPTIONAL see if it is there */
+ if (opt)
+ {
+ int exptag;
+ p = *in;
+ if (tag == -1)
+ exptag = it->utype;
+ else exptag = tag;
+ /* Don't care about anything other than presence
+ * of expected tag */
+
+ ret = asn1_check_tlen(NULL, NULL, NULL, NULL, NULL,
+ &p, len, exptag, aclass, 1, ctx);
+ if (!ret)
+ {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_item_ex_d2i, ASN1_R_NESTED_ASN1_ERROR);
+ goto err;
+ }
+ if (ret == -1)
+ return -1;
+ }
+
+ /* This is the old style evil hack IMPLICIT handling:
+ * since the underlying code is expecting a tag and
+ * class other than the one present we change the
+ * buffer temporarily then change it back afterwards.
+ * This doesn't and never did work for tags > 30.
+ *
+ * Yes this is *horrible* but it is only needed for
+ * old style d2i which will hopefully not be around
+ * for much longer.
+ * FIXME: should copy the buffer then modify it so
+ * the input buffer can be const: we should *always*
+ * copy because the old style d2i might modify the
+ * buffer.
+ */
+
+ if (tag != -1)
+ {
+ wp = *(unsigned char **)in;
+ imphack = *wp;
+ if (p == NULL)
+ {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_item_ex_d2i, ASN1_R_NESTED_ASN1_ERROR);
+ goto err;
+ }
+ *wp = (unsigned char)((*p & V_ASN1_CONSTRUCTED)
+ | it->utype);
+ }
+
+ ptmpval = cf->asn1_d2i(pval, in, len);
+
+ if (tag != -1)
+ *wp = imphack;
+
+ if (ptmpval)
+ return 1;
+
+ OPENSSL_PUT_ERROR(ASN1, ASN1_item_ex_d2i, ASN1_R_NESTED_ASN1_ERROR);
+ goto err;
+
+
+ case ASN1_ITYPE_CHOICE:
+ if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it, NULL))
+ goto auxerr;
+
+ /* Allocate structure */
+ if (!*pval && !ASN1_item_ex_new(pval, it))
+ {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_item_ex_d2i, ASN1_R_NESTED_ASN1_ERROR);
+ goto err;
+ }
+ /* CHOICE type, try each possibility in turn */
+ p = *in;
+ for (i = 0, tt=it->templates; i < it->tcount; i++, tt++)
+ {
+ pchptr = asn1_get_field_ptr(pval, tt);
+ /* We mark field as OPTIONAL so its absence
+ * can be recognised.
+ */
+ ret = asn1_template_ex_d2i(pchptr, &p, len, tt, 1, ctx);
+ /* If field not present, try the next one */
+ if (ret == -1)
+ continue;
+ /* If positive return, read OK, break loop */
+ if (ret > 0)
+ break;
+ /* Otherwise must be an ASN1 parsing error */
+ errtt = tt;
+ OPENSSL_PUT_ERROR(ASN1, ASN1_item_ex_d2i, ASN1_R_NESTED_ASN1_ERROR);
+ goto err;
+ }
+
+ /* Did we fall off the end without reading anything? */
+ if (i == it->tcount)
+ {
+ /* If OPTIONAL, this is OK */
+ if (opt)
+ {
+ /* Free and zero it */
+ ASN1_item_ex_free(pval, it);
+ return -1;
+ }
+ OPENSSL_PUT_ERROR(ASN1, ASN1_item_ex_d2i, ASN1_R_NO_MATCHING_CHOICE_TYPE);
+ goto err;
+ }
+
+ asn1_set_choice_selector(pval, i, it);
+ *in = p;
+ if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it, NULL))
+ goto auxerr;
+ return 1;
+
+ case ASN1_ITYPE_NDEF_SEQUENCE:
+ case ASN1_ITYPE_SEQUENCE:
+ p = *in;
+ tmplen = len;
+
+ /* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */
+ if (tag == -1)
+ {
+ tag = V_ASN1_SEQUENCE;
+ aclass = V_ASN1_UNIVERSAL;
+ }
+ /* Get SEQUENCE length and update len, p */
+ ret = asn1_check_tlen(&len, NULL, NULL, &seq_eoc, &cst,
+ &p, len, tag, aclass, opt, ctx);
+ if (!ret)
+ {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_item_ex_d2i, ASN1_R_NESTED_ASN1_ERROR);
+ goto err;
+ }
+ else if (ret == -1)
+ return -1;
+ if (aux && (aux->flags & ASN1_AFLG_BROKEN))
+ {
+ len = tmplen - (p - *in);
+ seq_nolen = 1;
+ }
+ /* If indefinite we don't do a length check */
+ else seq_nolen = seq_eoc;
+ if (!cst)
+ {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_item_ex_d2i, ASN1_R_SEQUENCE_NOT_CONSTRUCTED);
+ goto err;
+ }
+
+ if (!*pval && !ASN1_item_ex_new(pval, it))
+ {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_item_ex_d2i, ASN1_R_NESTED_ASN1_ERROR);
+ goto err;
+ }
+
+ if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it, NULL))
+ goto auxerr;
+
+ /* Get each field entry */
+ for (i = 0, tt = it->templates; i < it->tcount; i++, tt++)
+ {
+ const ASN1_TEMPLATE *seqtt;
+ ASN1_VALUE **pseqval;
+ seqtt = asn1_do_adb(pval, tt, 1);
+ if (!seqtt)
+ goto err;
+ pseqval = asn1_get_field_ptr(pval, seqtt);
+ /* Have we ran out of data? */
+ if (!len)
+ break;
+ q = p;
+ if (asn1_check_eoc(&p, len))
+ {
+ if (!seq_eoc)
+ {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_item_ex_d2i, ASN1_R_UNEXPECTED_EOC);
+ goto err;
+ }
+ len -= p - q;
+ seq_eoc = 0;
+ q = p;
+ break;
+ }
+ /* This determines the OPTIONAL flag value. The field
+ * cannot be omitted if it is the last of a SEQUENCE
+ * and there is still data to be read. This isn't
+ * strictly necessary but it increases efficiency in
+ * some cases.
+ */
+ if (i == (it->tcount - 1))
+ isopt = 0;
+ else isopt = (char)(seqtt->flags & ASN1_TFLG_OPTIONAL);
+ /* attempt to read in field, allowing each to be
+ * OPTIONAL */
+
+ ret = asn1_template_ex_d2i(pseqval, &p, len,
+ seqtt, isopt, ctx);
+ if (!ret)
+ {
+ errtt = seqtt;
+ goto err;
+ }
+ else if (ret == -1)
+ {
+ /* OPTIONAL component absent.
+ * Free and zero the field.
+ */
+ ASN1_template_free(pseqval, seqtt);
+ continue;
+ }
+ /* Update length */
+ len -= p - q;
+ }
+
+ /* Check for EOC if expecting one */
+ if (seq_eoc && !asn1_check_eoc(&p, len))
+ {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_item_ex_d2i, ASN1_R_MISSING_EOC);
+ goto err;
+ }
+ /* Check all data read */
+ if (!seq_nolen && len)
+ {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_item_ex_d2i, ASN1_R_SEQUENCE_LENGTH_MISMATCH);
+ goto err;
+ }
+
+ /* If we get here we've got no more data in the SEQUENCE,
+ * however we may not have read all fields so check all
+ * remaining are OPTIONAL and clear any that are.
+ */
+ for (; i < it->tcount; tt++, i++)
+ {
+ const ASN1_TEMPLATE *seqtt;
+ seqtt = asn1_do_adb(pval, tt, 1);
+ if (!seqtt)
+ goto err;
+ if (seqtt->flags & ASN1_TFLG_OPTIONAL)
+ {
+ ASN1_VALUE **pseqval;
+ pseqval = asn1_get_field_ptr(pval, seqtt);
+ ASN1_template_free(pseqval, seqtt);
+ }
+ else
+ {
+ errtt = seqtt;
+ OPENSSL_PUT_ERROR(ASN1, ASN1_item_ex_d2i, ASN1_R_FIELD_MISSING);
+ goto err;
+ }
+ }
+ /* Save encoding */
+ if (!asn1_enc_save(pval, *in, p - *in, it))
+ goto auxerr;
+ *in = p;
+ if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it, NULL))
+ goto auxerr;
+ return 1;
+
+ default:
+ return 0;
+ }
+ auxerr:
+ OPENSSL_PUT_ERROR(ASN1, ASN1_item_ex_d2i, ASN1_R_AUX_ERROR);
+ err:
+ ASN1_item_ex_free(pval, it);
+ if (errtt)
+ ERR_add_error_data(4, "Field=", errtt->field_name,
+ ", Type=", it->sname);
+ else
+ ERR_add_error_data(2, "Type=", it->sname);
+ return 0;
+ }
+
+/* Templates are handled with two separate functions.
+ * One handles any EXPLICIT tag and the other handles the rest.
+ */
+
+static int asn1_template_ex_d2i(ASN1_VALUE **val,
+ const unsigned char **in, long inlen,
+ const ASN1_TEMPLATE *tt, char opt,
+ ASN1_TLC *ctx)
+ {
+ int flags, aclass;
+ int ret;
+ long len;
+ const unsigned char *p, *q;
+ char exp_eoc;
+ if (!val)
+ return 0;
+ flags = tt->flags;
+ aclass = flags & ASN1_TFLG_TAG_CLASS;
+
+ p = *in;
+
+ /* Check if EXPLICIT tag expected */
+ if (flags & ASN1_TFLG_EXPTAG)
+ {
+ char cst;
+ /* Need to work out amount of data available to the inner
+ * content and where it starts: so read in EXPLICIT header to
+ * get the info.
+ */
+ ret = asn1_check_tlen(&len, NULL, NULL, &exp_eoc, &cst,
+ &p, inlen, tt->tag, aclass, opt, ctx);
+ q = p;
+ if (!ret)
+ {
+ OPENSSL_PUT_ERROR(ASN1, asn1_template_ex_d2i, ASN1_R_NESTED_ASN1_ERROR);
+ return 0;
+ }
+ else if (ret == -1)
+ return -1;
+ if (!cst)
+ {
+ OPENSSL_PUT_ERROR(ASN1, asn1_template_ex_d2i, ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED);
+ return 0;
+ }
+ /* We've found the field so it can't be OPTIONAL now */
+ ret = asn1_template_noexp_d2i(val, &p, len, tt, 0, ctx);
+ if (!ret)
+ {
+ OPENSSL_PUT_ERROR(ASN1, asn1_template_ex_d2i, ASN1_R_NESTED_ASN1_ERROR);
+ return 0;
+ }
+ /* We read the field in OK so update length */
+ len -= p - q;
+ if (exp_eoc)
+ {
+ /* If NDEF we must have an EOC here */
+ if (!asn1_check_eoc(&p, len))
+ {
+ OPENSSL_PUT_ERROR(ASN1, asn1_template_ex_d2i, ASN1_R_MISSING_EOC);
+ goto err;
+ }
+ }
+ else
+ {
+ /* Otherwise we must hit the EXPLICIT tag end or its
+ * an error */
+ if (len)
+ {
+ OPENSSL_PUT_ERROR(ASN1, asn1_template_ex_d2i, ASN1_R_EXPLICIT_LENGTH_MISMATCH);
+ goto err;
+ }
+ }
+ }
+ else
+ return asn1_template_noexp_d2i(val, in, inlen,
+ tt, opt, ctx);
+
+ *in = p;
+ return 1;
+
+ err:
+ ASN1_template_free(val, tt);
+ return 0;
+ }
+
+static int asn1_template_noexp_d2i(ASN1_VALUE **val,
+ const unsigned char **in, long len,
+ const ASN1_TEMPLATE *tt, char opt,
+ ASN1_TLC *ctx)
+ {
+ int flags, aclass;
+ int ret;
+ const unsigned char *p;
+ if (!val)
+ return 0;
+ flags = tt->flags;
+ aclass = flags & ASN1_TFLG_TAG_CLASS;
+
+ p = *in;
+
+ if (flags & ASN1_TFLG_SK_MASK)
+ {
+ /* SET OF, SEQUENCE OF */
+ int sktag, skaclass;
+ char sk_eoc;
+ /* First work out expected inner tag value */
+ if (flags & ASN1_TFLG_IMPTAG)
+ {
+ sktag = tt->tag;
+ skaclass = aclass;
+ }
+ else
+ {
+ skaclass = V_ASN1_UNIVERSAL;
+ if (flags & ASN1_TFLG_SET_OF)
+ sktag = V_ASN1_SET;
+ else
+ sktag = V_ASN1_SEQUENCE;
+ }
+ /* Get the tag */
+ ret = asn1_check_tlen(&len, NULL, NULL, &sk_eoc, NULL,
+ &p, len, sktag, skaclass, opt, ctx);
+ if (!ret)
+ {
+ OPENSSL_PUT_ERROR(ASN1, asn1_template_noexp_d2i, ASN1_R_NESTED_ASN1_ERROR);
+ return 0;
+ }
+ else if (ret == -1)
+ return -1;
+ if (!*val)
+ *val = (ASN1_VALUE *)sk_new_null();
+ else
+ {
+ /* We've got a valid STACK: free up any items present */
+ STACK_OF(ASN1_VALUE) *sktmp
+ = (STACK_OF(ASN1_VALUE) *)*val;
+ ASN1_VALUE *vtmp;
+ while(sk_ASN1_VALUE_num(sktmp) > 0)
+ {
+ vtmp = sk_ASN1_VALUE_pop(sktmp);
+ ASN1_item_ex_free(&vtmp,
+ ASN1_ITEM_ptr(tt->item));
+ }
+ }
+
+ if (!*val)
+ {
+ OPENSSL_PUT_ERROR(ASN1, asn1_template_noexp_d2i, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ /* Read as many items as we can */
+ while(len > 0)
+ {
+ ASN1_VALUE *skfield;
+ const unsigned char *q = p;
+ /* See if EOC found */
+ if (asn1_check_eoc(&p, len))
+ {
+ if (!sk_eoc)
+ {
+ OPENSSL_PUT_ERROR(ASN1, asn1_template_noexp_d2i, ASN1_R_UNEXPECTED_EOC);
+ goto err;
+ }
+ len -= p - q;
+ sk_eoc = 0;
+ break;
+ }
+ skfield = NULL;
+ if (!ASN1_item_ex_d2i(&skfield, &p, len,
+ ASN1_ITEM_ptr(tt->item),
+ -1, 0, 0, ctx))
+ {
+ OPENSSL_PUT_ERROR(ASN1, asn1_template_noexp_d2i, ASN1_R_NESTED_ASN1_ERROR);
+ goto err;
+ }
+ len -= p - q;
+ if (!sk_ASN1_VALUE_push((STACK_OF(ASN1_VALUE) *)*val,
+ skfield))
+ {
+ OPENSSL_PUT_ERROR(ASN1, asn1_template_noexp_d2i, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+ if (sk_eoc)
+ {
+ OPENSSL_PUT_ERROR(ASN1, asn1_template_noexp_d2i, ASN1_R_MISSING_EOC);
+ goto err;
+ }
+ }
+ else if (flags & ASN1_TFLG_IMPTAG)
+ {
+ /* IMPLICIT tagging */
+ ret = ASN1_item_ex_d2i(val, &p, len,
+ ASN1_ITEM_ptr(tt->item), tt->tag, aclass, opt, ctx);
+ if (!ret)
+ {
+ OPENSSL_PUT_ERROR(ASN1, asn1_template_noexp_d2i, ASN1_R_NESTED_ASN1_ERROR);
+ goto err;
+ }
+ else if (ret == -1)
+ return -1;
+ }
+ else
+ {
+ /* Nothing special */
+ ret = ASN1_item_ex_d2i(val, &p, len, ASN1_ITEM_ptr(tt->item),
+ -1, 0, opt, ctx);
+ if (!ret)
+ {
+ OPENSSL_PUT_ERROR(ASN1, asn1_template_noexp_d2i, ASN1_R_NESTED_ASN1_ERROR);
+ goto err;
+ }
+ else if (ret == -1)
+ return -1;
+ }
+
+ *in = p;
+ return 1;
+
+ err:
+ ASN1_template_free(val, tt);
+ return 0;
+ }
+
+static int asn1_d2i_ex_primitive(ASN1_VALUE **pval,
+ const unsigned char **in, long inlen,
+ const ASN1_ITEM *it,
+ int tag, int aclass, char opt, ASN1_TLC *ctx)
+ {
+ int ret = 0, utype;
+ long plen;
+ char cst, inf, free_cont = 0;
+ const unsigned char *p;
+ BUF_MEM buf;
+ const unsigned char *cont = NULL;
+ long len;
+ if (!pval)
+ {
+ OPENSSL_PUT_ERROR(ASN1, asn1_d2i_ex_primitive, ASN1_R_ILLEGAL_NULL);
+ return 0; /* Should never happen */
+ }
+
+ if (it->itype == ASN1_ITYPE_MSTRING)
+ {
+ utype = tag;
+ tag = -1;
+ }
+ else
+ utype = it->utype;
+
+ if (utype == V_ASN1_ANY)
+ {
+ /* If type is ANY need to figure out type from tag */
+ unsigned char oclass;
+ if (tag >= 0)
+ {
+ OPENSSL_PUT_ERROR(ASN1, asn1_d2i_ex_primitive, ASN1_R_ILLEGAL_TAGGED_ANY);
+ return 0;
+ }
+ if (opt)
+ {
+ OPENSSL_PUT_ERROR(ASN1, asn1_d2i_ex_primitive, ASN1_R_ILLEGAL_OPTIONAL_ANY);
+ return 0;
+ }
+ p = *in;
+ ret = asn1_check_tlen(NULL, &utype, &oclass, NULL, NULL,
+ &p, inlen, -1, 0, 0, ctx);
+ if (!ret)
+ {
+ OPENSSL_PUT_ERROR(ASN1, asn1_d2i_ex_primitive, ASN1_R_NESTED_ASN1_ERROR);
+ return 0;
+ }
+ if (oclass != V_ASN1_UNIVERSAL)
+ utype = V_ASN1_OTHER;
+ }
+ if (tag == -1)
+ {
+ tag = utype;
+ aclass = V_ASN1_UNIVERSAL;
+ }
+ p = *in;
+ /* Check header */
+ ret = asn1_check_tlen(&plen, NULL, NULL, &inf, &cst,
+ &p, inlen, tag, aclass, opt, ctx);
+ if (!ret)
+ {
+ OPENSSL_PUT_ERROR(ASN1, asn1_d2i_ex_primitive, ASN1_R_NESTED_ASN1_ERROR);
+ return 0;
+ }
+ else if (ret == -1)
+ return -1;
+ ret = 0;
+ /* SEQUENCE, SET and "OTHER" are left in encoded form */
+ if ((utype == V_ASN1_SEQUENCE)
+ || (utype == V_ASN1_SET) || (utype == V_ASN1_OTHER))
+ {
+ /* Clear context cache for type OTHER because the auto clear
+ * when we have a exact match wont work
+ */
+ if (utype == V_ASN1_OTHER)
+ {
+ asn1_tlc_clear(ctx);
+ }
+ /* SEQUENCE and SET must be constructed */
+ else if (!cst)
+ {
+ OPENSSL_PUT_ERROR(ASN1, asn1_d2i_ex_primitive, ASN1_R_TYPE_NOT_CONSTRUCTED);
+ return 0;
+ }
+
+ cont = *in;
+ /* If indefinite length constructed find the real end */
+ if (inf)
+ {
+ if (!asn1_find_end(&p, plen, inf))
+ goto err;
+ len = p - cont;
+ }
+ else
+ {
+ len = p - cont + plen;
+ p += plen;
+ buf.data = NULL;
+ }
+ }
+ else if (cst)
+ {
+ if (utype == V_ASN1_NULL || utype == V_ASN1_BOOLEAN
+ || utype == V_ASN1_OBJECT || utype == V_ASN1_INTEGER
+ || utype == V_ASN1_ENUMERATED)
+ {
+ /* These types only have primitive encodings. */
+ OPENSSL_PUT_ERROR(ASN1, asn1_d2i_ex_primitive,
+ ASN1_R_TYPE_NOT_PRIMITIVE);
+ return 0;
+ }
+
+ buf.length = 0;
+ buf.max = 0;
+ buf.data = NULL;
+ /* 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 (!asn1_collect(&buf, &p, plen, inf, -1, V_ASN1_UNIVERSAL, 0))
+ {
+ free_cont = 1;
+ goto err;
+ }
+ len = buf.length;
+ /* Append a final null to string */
+ if (!BUF_MEM_grow_clean(&buf, len + 1))
+ {
+ OPENSSL_PUT_ERROR(ASN1, asn1_d2i_ex_primitive, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ buf.data[len] = 0;
+ cont = (const unsigned char *)buf.data;
+ free_cont = 1;
+ }
+ else
+ {
+ cont = p;
+ len = plen;
+ p += plen;
+ }
+
+ /* We now have content length and type: translate into a structure */
+ if (!asn1_ex_c2i(pval, cont, len, utype, &free_cont, it))
+ goto err;
+
+ *in = p;
+ ret = 1;
+ err:
+ if (free_cont && buf.data) OPENSSL_free(buf.data);
+ return ret;
+ }
+
+/* Translate ASN1 content octets into a structure */
+
+int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
+ int utype, char *free_cont, const ASN1_ITEM *it)
+ {
+ ASN1_VALUE **opval = NULL;
+ ASN1_STRING *stmp;
+ ASN1_TYPE *typ = NULL;
+ int ret = 0;
+ const ASN1_PRIMITIVE_FUNCS *pf;
+ ASN1_INTEGER **tint;
+ pf = it->funcs;
+
+ if (pf && pf->prim_c2i)
+ return pf->prim_c2i(pval, cont, len, utype, free_cont, it);
+ /* If ANY type clear type and set pointer to internal value */
+ if (it->utype == V_ASN1_ANY)
+ {
+ if (!*pval)
+ {
+ typ = ASN1_TYPE_new();
+ if (typ == NULL)
+ goto err;
+ *pval = (ASN1_VALUE *)typ;
+ }
+ else
+ typ = (ASN1_TYPE *)*pval;
+
+ if (utype != typ->type)
+ ASN1_TYPE_set(typ, utype, NULL);
+ opval = pval;
+ pval = &typ->value.asn1_value;
+ }
+ switch(utype)
+ {
+ case V_ASN1_OBJECT:
+ if (!c2i_ASN1_OBJECT((ASN1_OBJECT **)pval, &cont, len))
+ goto err;
+ break;
+
+ case V_ASN1_NULL:
+ if (len)
+ {
+ OPENSSL_PUT_ERROR(ASN1, asn1_ex_c2i, ASN1_R_NULL_IS_WRONG_LENGTH);
+ goto err;
+ }
+ *pval = (ASN1_VALUE *)1;
+ break;
+
+ case V_ASN1_BOOLEAN:
+ if (len != 1)
+ {
+ OPENSSL_PUT_ERROR(ASN1, asn1_ex_c2i, ASN1_R_BOOLEAN_IS_WRONG_LENGTH);
+ goto err;
+ }
+ else
+ {
+ ASN1_BOOLEAN *tbool;
+ tbool = (ASN1_BOOLEAN *)pval;
+ *tbool = *cont;
+ }
+ break;
+
+ case V_ASN1_BIT_STRING:
+ if (!c2i_ASN1_BIT_STRING((ASN1_BIT_STRING **)pval, &cont, len))
+ goto err;
+ break;
+
+ case V_ASN1_INTEGER:
+ case V_ASN1_NEG_INTEGER:
+ case V_ASN1_ENUMERATED:
+ case V_ASN1_NEG_ENUMERATED:
+ tint = (ASN1_INTEGER **)pval;
+ if (!c2i_ASN1_INTEGER(tint, &cont, len))
+ goto err;
+ /* Fixup type to match the expected form */
+ (*tint)->type = utype | ((*tint)->type & V_ASN1_NEG);
+ 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 && (len & 1))
+ {
+ OPENSSL_PUT_ERROR(ASN1, asn1_ex_c2i, ASN1_R_BMPSTRING_IS_WRONG_LENGTH);
+ goto err;
+ }
+ if (utype == V_ASN1_UNIVERSALSTRING && (len & 3))
+ {
+ OPENSSL_PUT_ERROR(ASN1, asn1_ex_c2i, ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH);
+ goto err;
+ }
+ /* All based on ASN1_STRING and handled the same */
+ if (!*pval)
+ {
+ stmp = ASN1_STRING_type_new(utype);
+ if (!stmp)
+ {
+ OPENSSL_PUT_ERROR(ASN1, asn1_ex_c2i, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ *pval = (ASN1_VALUE *)stmp;
+ }
+ else
+ {
+ stmp = (ASN1_STRING *)*pval;
+ stmp->type = utype;
+ }
+ /* If we've already allocated a buffer use it */
+ if (*free_cont)
+ {
+ if (stmp->data)
+ OPENSSL_free(stmp->data);
+ stmp->data = (unsigned char *)cont; /* UGLY CAST! RL */
+ stmp->length = len;
+ *free_cont = 0;
+ }
+ else
+ {
+ if (!ASN1_STRING_set(stmp, cont, len))
+ {
+ OPENSSL_PUT_ERROR(ASN1, asn1_ex_c2i, ERR_R_MALLOC_FAILURE);
+ ASN1_STRING_free(stmp);
+ *pval = NULL;
+ goto err;
+ }
+ }
+ break;
+ }
+ /* If ASN1_ANY and NULL type fix up value */
+ if (typ && (utype == V_ASN1_NULL))
+ typ->value.ptr = NULL;
+
+ ret = 1;
+ err:
+ if (!ret)
+ {
+ ASN1_TYPE_free(typ);
+ if (opval)
+ *opval = NULL;
+ }
+ return ret;
+ }
+
+
+/* This function finds the end of an ASN1 structure when passed its maximum
+ * length, whether it is indefinite length and a pointer to the content.
+ * This is more efficient than calling asn1_collect because it does not
+ * recurse on each indefinite length header.
+ */
+
+static int asn1_find_end(const unsigned char **in, long len, char inf)
+ {
+ int expected_eoc;
+ long plen;
+ const unsigned char *p = *in, *q;
+ /* If not indefinite length constructed just add length */
+ if (inf == 0)
+ {
+ *in += len;
+ return 1;
+ }
+ expected_eoc = 1;
+ /* Indefinite length constructed form. Find the end when enough EOCs
+ * are found. If more indefinite length constructed headers
+ * are encountered increment the expected eoc count otherwise just
+ * skip to the end of the data.
+ */
+ while (len > 0)
+ {
+ if(asn1_check_eoc(&p, len))
+ {
+ expected_eoc--;
+ if (expected_eoc == 0)
+ break;
+ len -= 2;
+ continue;
+ }
+ q = p;
+ /* Just read in a header: only care about the length */
+ if(!asn1_check_tlen(&plen, NULL, NULL, &inf, NULL, &p, len,
+ -1, 0, 0, NULL))
+ {
+ OPENSSL_PUT_ERROR(ASN1, asn1_find_end, ASN1_R_NESTED_ASN1_ERROR);
+ return 0;
+ }
+ if (inf)
+ expected_eoc++;
+ else
+ p += plen;
+ len -= p - q;
+ }
+ if (expected_eoc)
+ {
+ OPENSSL_PUT_ERROR(ASN1, asn1_find_end, ASN1_R_MISSING_EOC);
+ return 0;
+ }
+ *in = p;
+ return 1;
+ }
+/* This function collects the asn1 data from a constructred string
+ * type into a buffer. The values of 'in' and 'len' should refer
+ * to the contents of the constructed type and 'inf' should be set
+ * if it is indefinite length.
+ */
+
+#ifndef ASN1_MAX_STRING_NEST
+/* This determines how many levels of recursion are permitted in ASN1
+ * string types. If it is not limited stack overflows can occur. If set
+ * to zero no recursion is allowed at all. Although zero should be adequate
+ * examples exist that require a value of 1. So 5 should be more than enough.
+ */
+#define ASN1_MAX_STRING_NEST 5
+#endif
+
+
+static int asn1_collect(BUF_MEM *buf, const unsigned char **in, long len,
+ char inf, int tag, int aclass, int depth)
+ {
+ const unsigned char *p, *q;
+ long plen;
+ char cst, ininf;
+ p = *in;
+ inf &= 1;
+ /* If no buffer and not indefinite length constructed just pass over
+ * the encoded data */
+ if (!buf && !inf)
+ {
+ *in += len;
+ return 1;
+ }
+ while(len > 0)
+ {
+ q = p;
+ /* Check for EOC */
+ if (asn1_check_eoc(&p, len))
+ {
+ /* EOC is illegal outside indefinite length
+ * constructed form */
+ if (!inf)
+ {
+ OPENSSL_PUT_ERROR(ASN1, asn1_collect, ASN1_R_UNEXPECTED_EOC);
+ return 0;
+ }
+ inf = 0;
+ break;
+ }
+
+ if (!asn1_check_tlen(&plen, NULL, NULL, &ininf, &cst, &p,
+ len, tag, aclass, 0, NULL))
+ {
+ OPENSSL_PUT_ERROR(ASN1, asn1_collect, ASN1_R_NESTED_ASN1_ERROR);
+ return 0;
+ }
+
+ /* If indefinite length constructed update max length */
+ if (cst)
+ {
+ if (depth >= ASN1_MAX_STRING_NEST)
+ {
+ OPENSSL_PUT_ERROR(ASN1, asn1_collect, ASN1_R_NESTED_ASN1_STRING);
+ return 0;
+ }
+ if (!asn1_collect(buf, &p, plen, ininf, tag, aclass,
+ depth + 1))
+ return 0;
+ }
+ else if (plen && !collect_data(buf, &p, plen))
+ return 0;
+ len -= p - q;
+ }
+ if (inf)
+ {
+ OPENSSL_PUT_ERROR(ASN1, asn1_collect, ASN1_R_MISSING_EOC);
+ return 0;
+ }
+ *in = p;
+ return 1;
+ }
+
+static int collect_data(BUF_MEM *buf, const unsigned char **p, long plen)
+ {
+ int len;
+ if (buf)
+ {
+ len = buf->length;
+ if (!BUF_MEM_grow_clean(buf, len + plen))
+ {
+ OPENSSL_PUT_ERROR(ASN1, asn1_collect, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ memcpy(buf->data + len, *p, plen);
+ }
+ *p += plen;
+ return 1;
+ }
+
+/* Check for ASN1 EOC and swallow it if found */
+
+static int asn1_check_eoc(const unsigned char **in, long len)
+ {
+ const unsigned char *p;
+ if (len < 2) return 0;
+ p = *in;
+ if (!p[0] && !p[1])
+ {
+ *in += 2;
+ return 1;
+ }
+ return 0;
+ }
+
+/* Check an ASN1 tag and length: a bit like ASN1_get_object
+ * but it sets the length for indefinite length constructed
+ * form, we don't know the exact length but we can set an
+ * upper bound to the amount of data available minus the
+ * header length just read.
+ */
+
+static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass,
+ char *inf, char *cst,
+ const unsigned char **in, long len,
+ int exptag, int expclass, char opt,
+ ASN1_TLC *ctx)
+ {
+ int i;
+ int ptag, pclass;
+ long plen;
+ const unsigned char *p, *q;
+ p = *in;
+ q = p;
+
+ if (ctx && ctx->valid)
+ {
+ i = ctx->ret;
+ plen = ctx->plen;
+ pclass = ctx->pclass;
+ ptag = ctx->ptag;
+ p += ctx->hdrlen;
+ }
+ else
+ {
+ i = ASN1_get_object(&p, &plen, &ptag, &pclass, len);
+ if (ctx)
+ {
+ ctx->ret = i;
+ ctx->plen = plen;
+ ctx->pclass = pclass;
+ ctx->ptag = ptag;
+ ctx->hdrlen = p - q;
+ ctx->valid = 1;
+ /* If definite length, and no error, length +
+ * header can't exceed total amount of data available.
+ */
+ if (!(i & 0x81) && ((plen + ctx->hdrlen) > len))
+ {
+ OPENSSL_PUT_ERROR(ASN1, asn1_check_tlen, ASN1_R_TOO_LONG);
+ asn1_tlc_clear(ctx);
+ return 0;
+ }
+ }
+ }
+
+ if (i & 0x80)
+ {
+ OPENSSL_PUT_ERROR(ASN1, asn1_check_tlen, ASN1_R_BAD_OBJECT_HEADER);
+ asn1_tlc_clear(ctx);
+ return 0;
+ }
+ if (exptag >= 0)
+ {
+ if ((exptag != ptag) || (expclass != pclass))
+ {
+ /* If type is OPTIONAL, not an error:
+ * indicate missing type.
+ */
+ if (opt) return -1;
+ asn1_tlc_clear(ctx);
+ OPENSSL_PUT_ERROR(ASN1, asn1_check_tlen, ASN1_R_WRONG_TAG);
+ return 0;
+ }
+ /* We have a tag and class match:
+ * assume we are going to do something with it */
+ asn1_tlc_clear(ctx);
+ }
+
+ if (i & 1)
+ plen = len - (p - q);
+
+ if (inf)
+ *inf = i & 1;
+
+ if (cst)
+ *cst = i & V_ASN1_CONSTRUCTED;
+
+ if (olen)
+ *olen = plen;
+
+ if (oclass)
+ *oclass = pclass;
+
+ if (otag)
+ *otag = ptag;
+
+ *in = p;
+ return 1;
+ }
diff --git a/src/crypto/asn1/tasn_enc.c b/src/crypto/asn1/tasn_enc.c
new file mode 100644
index 0000000..38e14d2
--- /dev/null
+++ b/src/crypto/asn1/tasn_enc.c
@@ -0,0 +1,695 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/asn1.h>
+
+#include <string.h>
+
+#include <openssl/asn1t.h>
+#include <openssl/mem.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);
+
+/* 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);
+ }
+
+/* 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)
+ {
+ if (out && !*out)
+ {
+ unsigned char *p, *buf;
+ int len;
+ len = ASN1_item_ex_i2d(&val, NULL, it, -1, flags);
+ if (len <= 0)
+ return len;
+ buf = OPENSSL_malloc(len);
+ if (!buf)
+ return -1;
+ p = buf;
+ ASN1_item_ex_i2d(&val, &p, it, -1, flags);
+ *out = buf;
+ return len;
+ }
+
+ return ASN1_item_ex_i2d(&val, out, it, -1, flags);
+ }
+
+/* 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;
+ unsigned char *p = NULL;
+ int i, seqcontlen, seqlen, ndef = 1;
+ const ASN1_COMPAT_FUNCS *cf;
+ const ASN1_EXTERN_FUNCS *ef;
+ const ASN1_AUX *aux = it->funcs;
+ ASN1_aux_cb *asn1_cb = 0;
+
+ 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:
+ return asn1_i2d_ex_primitive(pval, out, it, -1, aclass);
+
+ case ASN1_ITYPE_CHOICE:
+ 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_COMPAT:
+ /* old style hackery... */
+ cf = it->funcs;
+ if (out)
+ p = *out;
+ i = cf->asn1_i2d(*pval, out);
+ /* Fixup for IMPLICIT tag: note this messes up for tags > 30,
+ * but so did the old code. Tags > 30 are very rare anyway.
+ */
+ if (out && (tag != -1))
+ *p = aclass | tag | (*p & V_ASN1_CONSTRUCTED);
+ return i;
+
+ 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;
+ }
+
+int ASN1_template_i2d(ASN1_VALUE **pval, unsigned char **out,
+ const ASN1_TEMPLATE *tt)
+ {
+ return asn1_template_ex_i2d(pval, out, tt, -1, 0);
+ }
+
+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;
+ size_t j;
+ 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 (j = 0; j < sk_ASN1_VALUE_num(sk); j++)
+ {
+ skitem = sk_ASN1_VALUE_value(sk, j);
+ skcontlen += ASN1_item_ex_i2d(&skitem, NULL,
+ ASN1_ITEM_ptr(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, ASN1_ITEM_ptr(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, ASN1_ITEM_ptr(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, ASN1_ITEM_ptr(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, ASN1_ITEM_ptr(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)
+ {
+ size_t 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 = OPENSSL_malloc(sk_ASN1_VALUE_num(sk)
+ * sizeof(*derlst));
+ if (!derlst)
+ return 0;
+ tmpdat = OPENSSL_malloc(skcontlen);
+ if (!tmpdat)
+ {
+ OPENSSL_free(derlst);
+ 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);
+ }
+ OPENSSL_free(derlst);
+ OPENSSL_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 len;
+ int utype;
+ int usetag;
+ int ndef = 0;
+
+ utype = it->utype;
+
+ /* Get length of content octets and maybe find
+ * out the underlying type.
+ */
+
+ 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;
+ }
+
+ /* 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);
+ asn1_ex_i2c(pval, *out, &utype, it);
+ 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 */
+
+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;
+ const ASN1_PRIMITIVE_FUNCS *pf;
+ pf = it->funcs;
+ if (pf && pf->prim_i2c)
+ 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_NEG_INTEGER:
+ case V_ASN1_ENUMERATED:
+ case V_ASN1_NEG_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/src/crypto/asn1/tasn_fre.c b/src/crypto/asn1/tasn_fre.c
new file mode 100644
index 0000000..c344ed7
--- /dev/null
+++ b/src/crypto/asn1/tasn_fre.c
@@ -0,0 +1,264 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/asn1.h>
+
+#include <openssl/asn1t.h>
+#include <openssl/mem.h>
+
+
+static void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int combine);
+
+/* Free up an ASN1 structure */
+
+void ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it)
+ {
+ asn1_item_combine_free(&val, it, 0);
+ }
+
+void ASN1_item_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
+ {
+ asn1_item_combine_free(pval, it, 0);
+ }
+
+static void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int combine)
+ {
+ const ASN1_TEMPLATE *tt = NULL, *seqtt;
+ const ASN1_EXTERN_FUNCS *ef;
+ const ASN1_COMPAT_FUNCS *cf;
+ const ASN1_AUX *aux = it->funcs;
+ ASN1_aux_cb *asn1_cb;
+ int i;
+ if (!pval)
+ return;
+ if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval)
+ return;
+ if (aux && aux->asn1_cb)
+ asn1_cb = aux->asn1_cb;
+ else
+ asn1_cb = 0;
+
+ 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);
+ if (!combine)
+ {
+ OPENSSL_free(*pval);
+ *pval = NULL;
+ }
+ break;
+
+ case ASN1_ITYPE_COMPAT:
+ cf = it->funcs;
+ if (cf && cf->asn1_free)
+ cf->asn1_free(*pval);
+ 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_free(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);
+ if (!combine)
+ {
+ OPENSSL_free(*pval);
+ *pval = NULL;
+ }
+ break;
+ }
+ }
+
+void ASN1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
+ {
+ size_t 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_combine_free(&vtmp, ASN1_ITEM_ptr(tt->item),
+ 0);
+ }
+ sk_ASN1_VALUE_free(sk);
+ *pval = NULL;
+ }
+ else
+ asn1_item_combine_free(pval, ASN1_ITEM_ptr(tt->item),
+ tt->flags & ASN1_TFLG_COMBINE);
+ }
+
+void ASN1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
+ {
+ int utype;
+ if (it)
+ {
+ const ASN1_PRIMITIVE_FUNCS *pf;
+ pf = it->funcs;
+ if (pf && pf->prim_free)
+ {
+ 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);
+ OPENSSL_free(*pval);
+ break;
+
+ default:
+ ASN1_STRING_free((ASN1_STRING *)*pval);
+ *pval = NULL;
+ break;
+ }
+ *pval = NULL;
+ }
diff --git a/src/crypto/asn1/tasn_new.c b/src/crypto/asn1/tasn_new.c
new file mode 100644
index 0000000..b68eed7
--- /dev/null
+++ b/src/crypto/asn1/tasn_new.c
@@ -0,0 +1,396 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/asn1.h>
+
+#include <string.h>
+
+#include <openssl/asn1t.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+
+
+static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
+ int combine);
+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;
+ }
+
+/* Allocate an ASN1 structure */
+
+int ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
+ {
+ return asn1_item_ex_combine_new(pval, it, 0);
+ }
+
+static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
+ int combine)
+ {
+ const ASN1_TEMPLATE *tt = NULL;
+ const ASN1_COMPAT_FUNCS *cf;
+ const ASN1_EXTERN_FUNCS *ef;
+ const ASN1_AUX *aux = it->funcs;
+ ASN1_aux_cb *asn1_cb;
+ ASN1_VALUE **pseqval;
+ int i;
+ if (aux && aux->asn1_cb)
+ asn1_cb = aux->asn1_cb;
+ else
+ asn1_cb = 0;
+
+ if (!combine) *pval = NULL;
+
+#ifdef CRYPTO_MDEBUG
+ if (it->sname)
+ CRYPTO_push_info(it->sname);
+#endif
+
+ switch(it->itype)
+ {
+
+ case ASN1_ITYPE_EXTERN:
+ ef = it->funcs;
+ if (ef && ef->asn1_ex_new)
+ {
+ if (!ef->asn1_ex_new(pval, it))
+ goto memerr;
+ }
+ break;
+
+ case ASN1_ITYPE_COMPAT:
+ cf = it->funcs;
+ if (cf && cf->asn1_new) {
+ *pval = cf->asn1_new();
+ if (!*pval)
+ 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)
+ {
+#ifdef CRYPTO_MDEBUG
+ if (it->sname)
+ CRYPTO_pop_info();
+#endif
+ return 1;
+ }
+ }
+ if (!combine)
+ {
+ *pval = OPENSSL_malloc(it->size);
+ if (!*pval)
+ goto memerr;
+ memset(*pval, 0, it->size);
+ }
+ 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)
+ {
+#ifdef CRYPTO_MDEBUG
+ if (it->sname)
+ CRYPTO_pop_info();
+#endif
+ return 1;
+ }
+ }
+ if (!combine)
+ {
+ *pval = OPENSSL_malloc(it->size);
+ if (!*pval)
+ goto memerr;
+ memset(*pval, 0, it->size);
+ 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;
+ }
+#ifdef CRYPTO_MDEBUG
+ if (it->sname) CRYPTO_pop_info();
+#endif
+ return 1;
+
+ memerr:
+ OPENSSL_PUT_ERROR(ASN1, asn1_item_ex_combine_new, ERR_R_MALLOC_FAILURE);
+#ifdef CRYPTO_MDEBUG
+ if (it->sname) CRYPTO_pop_info();
+#endif
+ return 0;
+
+ auxerr:
+ OPENSSL_PUT_ERROR(ASN1, asn1_item_ex_combine_new, ASN1_R_AUX_ERROR);
+ ASN1_item_ex_free(pval, it);
+#ifdef CRYPTO_MDEBUG
+ if (it->sname) CRYPTO_pop_info();
+#endif
+ 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_COMPAT:
+ 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 = ASN1_ITEM_ptr(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;
+ }
+#ifdef CRYPTO_MDEBUG
+ if (tt->field_name)
+ CRYPTO_push_info(tt->field_name);
+#endif
+ /* If SET OF or SEQUENCE OF, its a STACK */
+ if (tt->flags & ASN1_TFLG_SK_MASK)
+ {
+ STACK_OF(ASN1_VALUE) *skval;
+ skval = sk_ASN1_VALUE_new_null();
+ if (!skval)
+ {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_template_new, 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_combine_new(pval, it, tt->flags & ASN1_TFLG_COMBINE);
+ done:
+#ifdef CRYPTO_MDEBUG
+ if (it->sname)
+ CRYPTO_pop_info();
+#endif
+ 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, ASN1_ITEM_ptr(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 && it->funcs)
+ {
+ const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
+ if (pf->prim_new)
+ return pf->prim_new(pval, it);
+ }
+
+ if (!it || (it->itype == ASN1_ITYPE_MSTRING))
+ utype = -1;
+ 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 = OPENSSL_malloc(sizeof(ASN1_TYPE));
+ if (!typ)
+ return 0;
+ typ->value.ptr = NULL;
+ typ->type = -1;
+ *pval = (ASN1_VALUE *)typ;
+ break;
+
+ default:
+ str = ASN1_STRING_type_new(utype);
+ if (it->itype == ASN1_ITYPE_MSTRING && str)
+ 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 && it->funcs)
+ {
+ 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 = -1;
+ else
+ utype = it->utype;
+ if (utype == V_ASN1_BOOLEAN)
+ *(ASN1_BOOLEAN *)pval = it->size;
+ else *pval = NULL;
+ }
diff --git a/src/crypto/asn1/tasn_prn.c b/src/crypto/asn1/tasn_prn.c
new file mode 100644
index 0000000..4eb522d
--- /dev/null
+++ b/src/crypto/asn1/tasn_prn.c
@@ -0,0 +1,639 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/asn1.h>
+
+#include <time.h>
+
+#include <openssl/asn1t.h>
+#include <openssl/err.h>
+#include <openssl/obj.h>
+#include <openssl/mem.h>
+
+#include "asn1_locl.h"
+
+
+
+/* Print routines.
+ */
+
+/* ASN1_PCTX routines */
+
+ASN1_PCTX default_pctx =
+ {
+ ASN1_PCTX_FLAGS_SHOW_ABSENT, /* flags */
+ 0, /* nm_flags */
+ 0, /* cert_flags */
+ 0, /* oid_flags */
+ 0 /* str_flags */
+ };
+
+
+ASN1_PCTX *ASN1_PCTX_new(void)
+ {
+ ASN1_PCTX *ret;
+ ret = OPENSSL_malloc(sizeof(ASN1_PCTX));
+ if (ret == NULL)
+ {
+ OPENSSL_PUT_ERROR(ASN1, ASN1_PCTX_new, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ ret->flags = 0;
+ ret->nm_flags = 0;
+ ret->cert_flags = 0;
+ ret->oid_flags = 0;
+ ret->str_flags = 0;
+ return ret;
+ }
+
+void ASN1_PCTX_free(ASN1_PCTX *p)
+ {
+ OPENSSL_free(p);
+ }
+
+unsigned long ASN1_PCTX_get_flags(ASN1_PCTX *p)
+ {
+ return p->flags;
+ }
+
+void ASN1_PCTX_set_flags(ASN1_PCTX *p, unsigned long flags)
+ {
+ p->flags = flags;
+ }
+
+unsigned long ASN1_PCTX_get_nm_flags(ASN1_PCTX *p)
+ {
+ return p->nm_flags;
+ }
+
+void ASN1_PCTX_set_nm_flags(ASN1_PCTX *p, unsigned long flags)
+ {
+ p->nm_flags = flags;
+ }
+
+unsigned long ASN1_PCTX_get_cert_flags(ASN1_PCTX *p)
+ {
+ return p->cert_flags;
+ }
+
+void ASN1_PCTX_set_cert_flags(ASN1_PCTX *p, unsigned long flags)
+ {
+ p->cert_flags = flags;
+ }
+
+unsigned long ASN1_PCTX_get_oid_flags(ASN1_PCTX *p)
+ {
+ return p->oid_flags;
+ }
+
+void ASN1_PCTX_set_oid_flags(ASN1_PCTX *p, unsigned long flags)
+ {
+ p->oid_flags = flags;
+ }
+
+unsigned long ASN1_PCTX_get_str_flags(ASN1_PCTX *p)
+ {
+ return p->str_flags;
+ }
+
+void ASN1_PCTX_set_str_flags(ASN1_PCTX *p, unsigned long flags)
+ {
+ p->str_flags = 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);
+ }
+
+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 = 0;
+
+ if(*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, "<ABSENT>\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:
+#if 0
+ if (!nohdr && !asn1_print_fsname(out, indent, fname, sname, pctx))
+ return 0;
+#endif
+ /* 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);
+ 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 flags;
+ size_t i;
+ const char *sname, *fname;
+ flags = tt->flags;
+ if(pctx->flags & ASN1_PCTX_FLAGS_SHOW_FIELD_STRUCT_NAME)
+ sname = ASN1_ITEM_ptr(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)
+ {
+ const 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,
+ ASN1_ITEM_ptr(tt->item), NULL, NULL, 1, pctx))
+ return 0;
+ }
+ if (!i && BIO_printf(out, "%*s<EMPTY>\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, ASN1_ITEM_ptr(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;
+
+#if 0
+ if (!sname && !fname)
+ return 1;
+#endif
+
+ 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)
+ {
+ BIGNUM *bn = NULL;
+ char *s = NULL;
+ int ret = 1;
+
+ bn = ASN1_INTEGER_to_BN(str, NULL);
+ if (bn == NULL) {
+ return 0;
+ }
+ s = BN_bn2dec(bn);
+ BN_free(bn);
+ if (s == NULL) {
+ return 0;
+ }
+
+ if (BIO_puts(out, s) <= 0) {
+ ret = 0;
+ }
+ OPENSSL_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_hexdump(out, str->data, str->length, indent + 2)) {
+ 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;
+ const ASN1_PRIMITIVE_FUNCS *pf;
+ pf = it->funcs;
+ if (!asn1_print_fsname(out, indent, fname, sname, pctx))
+ return 0;
+ if (pf && pf->prim_print)
+ return pf->prim_print(out, fld, it, indent, pctx);
+ str = (ASN1_STRING *)*fld;
+ if (it->itype == ASN1_ITYPE_MSTRING)
+ utype = str->type & ~V_ASN1_NEG;
+ else
+ utype = it->utype;
+ 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/src/crypto/asn1/tasn_typ.c b/src/crypto/asn1/tasn_typ.c
new file mode 100644
index 0000000..f2bbbc8
--- /dev/null
+++ b/src/crypto/asn1/tasn_typ.c
@@ -0,0 +1,152 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/asn1.h>
+
+#include <openssl/asn1t.h>
+
+
+/* Declarations for string types */
+
+IMPLEMENT_ASN1_TYPE(ASN1_INTEGER);
+IMPLEMENT_ASN1_FUNCTIONS(ASN1_INTEGER);
+
+IMPLEMENT_ASN1_TYPE(ASN1_ENUMERATED);
+IMPLEMENT_ASN1_FUNCTIONS(ASN1_ENUMERATED);
+
+IMPLEMENT_ASN1_TYPE(ASN1_BIT_STRING);
+IMPLEMENT_ASN1_FUNCTIONS(ASN1_BIT_STRING);
+
+IMPLEMENT_ASN1_TYPE(ASN1_OCTET_STRING);
+IMPLEMENT_ASN1_FUNCTIONS(ASN1_OCTET_STRING);
+
+IMPLEMENT_ASN1_TYPE(ASN1_NULL);
+IMPLEMENT_ASN1_FUNCTIONS(ASN1_NULL);
+
+IMPLEMENT_ASN1_TYPE(ASN1_OBJECT);
+
+IMPLEMENT_ASN1_TYPE(ASN1_UTF8STRING);
+IMPLEMENT_ASN1_FUNCTIONS(ASN1_UTF8STRING);
+
+IMPLEMENT_ASN1_TYPE(ASN1_PRINTABLESTRING);
+IMPLEMENT_ASN1_FUNCTIONS(ASN1_PRINTABLESTRING);
+
+IMPLEMENT_ASN1_TYPE(ASN1_T61STRING);
+IMPLEMENT_ASN1_FUNCTIONS(ASN1_T61STRING);
+
+IMPLEMENT_ASN1_TYPE(ASN1_IA5STRING);
+IMPLEMENT_ASN1_FUNCTIONS(ASN1_IA5STRING);
+
+IMPLEMENT_ASN1_TYPE(ASN1_GENERALSTRING);
+IMPLEMENT_ASN1_FUNCTIONS(ASN1_GENERALSTRING);
+
+IMPLEMENT_ASN1_TYPE(ASN1_UTCTIME);
+IMPLEMENT_ASN1_FUNCTIONS(ASN1_UTCTIME);
+
+IMPLEMENT_ASN1_TYPE(ASN1_GENERALIZEDTIME);
+IMPLEMENT_ASN1_FUNCTIONS(ASN1_GENERALIZEDTIME);
+
+IMPLEMENT_ASN1_TYPE(ASN1_VISIBLESTRING);
+IMPLEMENT_ASN1_FUNCTIONS(ASN1_VISIBLESTRING);
+
+IMPLEMENT_ASN1_TYPE(ASN1_UNIVERSALSTRING);
+IMPLEMENT_ASN1_FUNCTIONS(ASN1_UNIVERSALSTRING);
+
+IMPLEMENT_ASN1_TYPE(ASN1_BMPSTRING);
+IMPLEMENT_ASN1_FUNCTIONS(ASN1_BMPSTRING);
+
+IMPLEMENT_ASN1_TYPE(ASN1_ANY);
+
+/* Just swallow an ASN1_SEQUENCE in an ASN1_STRING */;
+IMPLEMENT_ASN1_TYPE(ASN1_SEQUENCE);
+
+IMPLEMENT_ASN1_FUNCTIONS_fname(ASN1_TYPE, ASN1_ANY, ASN1_TYPE);
+
+/* Multistring types */;
+
+IMPLEMENT_ASN1_MSTRING(ASN1_PRINTABLE, B_ASN1_PRINTABLE);
+IMPLEMENT_ASN1_FUNCTIONS_name(ASN1_STRING, ASN1_PRINTABLE);
+
+IMPLEMENT_ASN1_MSTRING(DISPLAYTEXT, B_ASN1_DISPLAYTEXT);
+IMPLEMENT_ASN1_FUNCTIONS_name(ASN1_STRING, DISPLAYTEXT);
+
+IMPLEMENT_ASN1_MSTRING(DIRECTORYSTRING, B_ASN1_DIRECTORYSTRING);
+IMPLEMENT_ASN1_FUNCTIONS_name(ASN1_STRING, DIRECTORYSTRING);
+
+/* Three separate BOOLEAN type: normal, DEFAULT TRUE and DEFAULT FALSE */;
+IMPLEMENT_ASN1_TYPE_ex(ASN1_BOOLEAN, ASN1_BOOLEAN, -1);
+IMPLEMENT_ASN1_TYPE_ex(ASN1_TBOOLEAN, ASN1_BOOLEAN, 1);
+IMPLEMENT_ASN1_TYPE_ex(ASN1_FBOOLEAN, ASN1_BOOLEAN, 0);
+
+/* Special, OCTET STRING with indefinite length constructed support */;
+
+IMPLEMENT_ASN1_TYPE_ex(ASN1_OCTET_STRING_NDEF, ASN1_OCTET_STRING,
+ ASN1_TFLG_NDEF);
+
+ASN1_ITEM_TEMPLATE(ASN1_SEQUENCE_ANY) = ASN1_EX_TEMPLATE_TYPE(
+ ASN1_TFLG_SEQUENCE_OF, 0, ASN1_SEQUENCE_ANY, ASN1_ANY);
+ASN1_ITEM_TEMPLATE_END(ASN1_SEQUENCE_ANY);
+
+ASN1_ITEM_TEMPLATE(ASN1_SET_ANY) = ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SET_OF, 0,
+ ASN1_SET_ANY,
+ ASN1_ANY);
+ASN1_ITEM_TEMPLATE_END(ASN1_SET_ANY);
+
+IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(ASN1_SEQUENCE_ANY,
+ ASN1_SEQUENCE_ANY,
+ ASN1_SEQUENCE_ANY);
+IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(ASN1_SEQUENCE_ANY, ASN1_SET_ANY,
+ ASN1_SET_ANY);
diff --git a/src/crypto/asn1/tasn_utl.c b/src/crypto/asn1/tasn_utl.c
new file mode 100644
index 0000000..f6045e4
--- /dev/null
+++ b/src/crypto/asn1/tasn_utl.c
@@ -0,0 +1,260 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/asn1.h>
+
+#include <string.h>
+
+#include <openssl/asn1t.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/err.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 refrence 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;
+ if (!pval || !*pval) {
+ return NULL;
+ }
+ aux = it->funcs;
+ if (!aux || !(aux->flags & ASN1_AFLG_ENCODING)) {
+ return NULL;
+ }
+ return offset2ptr(*pval, aux->enc_offset);
+}
+
+void asn1_enc_init(ASN1_VALUE **pval, const ASN1_ITEM *it) {
+ ASN1_ENCODING *enc;
+ enc = asn1_get_enc_ptr(pval, it);
+ if (enc) {
+ enc->enc = NULL;
+ enc->len = 0;
+ enc->modified = 1;
+ }
+}
+
+void asn1_enc_free(ASN1_VALUE **pval, const ASN1_ITEM *it) {
+ ASN1_ENCODING *enc;
+ enc = asn1_get_enc_ptr(pval, it);
+ if (enc) {
+ if (enc->enc) {
+ OPENSSL_free(enc->enc);
+ }
+ enc->enc = NULL;
+ enc->len = 0;
+ enc->modified = 1;
+ }
+}
+
+int asn1_enc_save(ASN1_VALUE **pval, const unsigned char *in, int inlen,
+ const ASN1_ITEM *it) {
+ ASN1_ENCODING *enc;
+ enc = asn1_get_enc_ptr(pval, it);
+ if (!enc) {
+ return 1;
+ }
+
+ if (enc->enc) {
+ OPENSSL_free(enc->enc);
+ }
+ enc->enc = OPENSSL_malloc(inlen);
+ if (!enc->enc) {
+ return 0;
+ }
+ memcpy(enc->enc, in, inlen);
+ enc->len = inlen;
+ enc->modified = 0;
+
+ return 1;
+}
+
+int asn1_enc_restore(int *len, unsigned char **out, ASN1_VALUE **pval,
+ const ASN1_ITEM *it) {
+ ASN1_ENCODING *enc;
+ enc = asn1_get_enc_ptr(pval, it);
+ if (!enc || enc->modified) {
+ return 0;
+ }
+ if (out) {
+ memcpy(*out, enc->enc, enc->len);
+ *out += enc->len;
+ }
+ if (len) {
+ *len = enc->len;
+ }
+ return 1;
+}
+
+/* Given an ASN1_TEMPLATE get a pointer to a field */
+ASN1_VALUE **asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) {
+ ASN1_VALUE **pvaltmp;
+ if (tt->flags & ASN1_TFLG_COMBINE) {
+ return pval;
+ }
+ 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 = ASN1_ADB_ptr(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) {
+ OPENSSL_PUT_ERROR(ASN1, asn1_do_adb,
+ ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE);
+ }
+ return NULL;
+}
diff --git a/src/crypto/asn1/x_bignum.c b/src/crypto/asn1/x_bignum.c
new file mode 100644
index 0000000..f8c62fd
--- /dev/null
+++ b/src/crypto/asn1/x_bignum.c
@@ -0,0 +1,142 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/asn1.h>
+
+#include <openssl/asn1t.h>
+#include <openssl/bn.h>
+
+
+/* Custom primitive type for BIGNUM handling. This reads in an ASN1_INTEGER as a
+ * BIGNUM directly. Currently it ignores the sign which isn't a problem since all
+ * BIGNUMs used are non negative and anything that looks negative is normally due
+ * to an encoding error.
+ */
+
+#define BN_SENSITIVE 1
+
+static int bn_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
+static void bn_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
+
+static int bn_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, 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 const ASN1_PRIMITIVE_FUNCS bignum_pf = {
+ NULL, 0,
+ bn_new,
+ bn_free,
+ 0,
+ bn_c2i,
+ bn_i2c
+};
+
+ASN1_ITEM_start(BIGNUM)
+ ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &bignum_pf, 0, "BIGNUM"
+ASN1_ITEM_end(BIGNUM)
+
+ASN1_ITEM_start(CBIGNUM)
+ ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &bignum_pf, BN_SENSITIVE, "BIGNUM"
+ASN1_ITEM_end(CBIGNUM)
+
+static int bn_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
+{
+ *pval = (ASN1_VALUE *)BN_new();
+ if(*pval) return 1;
+ else return 0;
+}
+
+static void bn_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
+{
+ if(!*pval) return;
+ if(it->size & BN_SENSITIVE) BN_clear_free((BIGNUM *)*pval);
+ else BN_free((BIGNUM *)*pval);
+ *pval = NULL;
+}
+
+static int bn_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, const ASN1_ITEM *it)
+{
+ BIGNUM *bn;
+ int pad;
+ if(!*pval) return -1;
+ bn = (BIGNUM *)*pval;
+ /* If MSB set in an octet we need a padding byte */
+ if(BN_num_bits(bn) & 0x7) pad = 0;
+ else pad = 1;
+ if(cont) {
+ if(pad) *cont++ = 0;
+ BN_bn2bin(bn, cont);
+ }
+ return pad + BN_num_bytes(bn);
+}
+
+static int bn_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
+ int utype, char *free_cont, const ASN1_ITEM *it)
+{
+ BIGNUM *bn;
+ if(!*pval)
+ {
+ if (!bn_new(pval, it))
+ {
+ return 0;
+ }
+ }
+ bn = (BIGNUM *)*pval;
+ if(!BN_bin2bn(cont, len, bn)) {
+ bn_free(pval, it);
+ return 0;
+ }
+ return 1;
+}
diff --git a/src/crypto/asn1/x_long.c b/src/crypto/asn1/x_long.c
new file mode 100644
index 0000000..5c2f96e
--- /dev/null
+++ b/src/crypto/asn1/x_long.c
@@ -0,0 +1,182 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/asn1.h>
+
+#include <string.h>
+
+#include <openssl/asn1t.h>
+#include <openssl/bn.h>
+#include <openssl/err.h>
+#include <openssl/mem.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 int long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, const ASN1_ITEM *it);
+static int long_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, int utype, char *free_cont, const ASN1_ITEM *it);
+static int long_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it, int indent, const ASN1_PCTX *pctx);
+
+static const ASN1_PRIMITIVE_FUNCS long_pf = {
+ NULL, 0,
+ long_new,
+ long_free,
+ long_free, /* Clear should set to initial value */
+ long_c2i,
+ long_i2c,
+ long_print
+};
+
+ASN1_ITEM_start(LONG)
+ ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &long_pf, ASN1_LONG_UNDEF, "LONG"
+ASN1_ITEM_end(LONG)
+
+ASN1_ITEM_start(ZLONG)
+ ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &long_pf, 0, "ZLONG"
+ASN1_ITEM_end(ZLONG)
+
+static int long_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
+{
+ *(long *)pval = it->size;
+ return 1;
+}
+
+static void long_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
+{
+ *(long *)pval = it->size;
+}
+
+static int long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, const ASN1_ITEM *it)
+{
+ long ltmp;
+ unsigned long utmp;
+ int clen, pad, i;
+ /* this exists to bypass broken gcc optimization */
+ char *cp = (char *)pval;
+
+ /* use memcpy, because we may not be long aligned */
+ memcpy(&ltmp, cp, sizeof(long));
+
+ if(ltmp == it->size) return -1;
+ /* Convert the long to positive: we subtract one if negative so
+ * we can cleanly handle the padding if only the MSB of the leading
+ * octet is set.
+ */
+ if(ltmp < 0) utmp = -ltmp - 1;
+ else utmp = ltmp;
+ clen = BN_num_bits_word(utmp);
+ /* If MSB of leading octet set we need to pad */
+ if(!(clen & 0x7)) pad = 1;
+ else pad = 0;
+
+ /* Convert number of bits to number of octets */
+ clen = (clen + 7) >> 3;
+
+ if(cont) {
+ if(pad) *cont++ = (ltmp < 0) ? 0xff : 0;
+ for(i = clen - 1; i >= 0; i--) {
+ cont[i] = (unsigned char)(utmp & 0xff);
+ if(ltmp < 0) cont[i] ^= 0xff;
+ utmp >>= 8;
+ }
+ }
+ return clen + pad;
+}
+
+static int long_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
+ int utype, char *free_cont, const ASN1_ITEM *it)
+{
+ int neg, i;
+ long ltmp;
+ unsigned long utmp = 0;
+ char *cp = (char *)pval;
+ if(len > (int)sizeof(long)) {
+ OPENSSL_PUT_ERROR(ASN1, long_c2i, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG);
+ return 0;
+ }
+ /* Is it negative? */
+ if(len && (cont[0] & 0x80)) neg = 1;
+ else neg = 0;
+ utmp = 0;
+ for(i = 0; i < len; i++) {
+ utmp <<= 8;
+ if(neg) utmp |= cont[i] ^ 0xff;
+ else utmp |= cont[i];
+ }
+ ltmp = (long)utmp;
+ if(neg) {
+ ltmp++;
+ ltmp = -ltmp;
+ }
+ if(ltmp == it->size) {
+ OPENSSL_PUT_ERROR(ASN1, long_c2i, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG);
+ return 0;
+ }
+ memcpy(cp, &ltmp, sizeof(long));
+ return 1;
+}
+
+static int long_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
+ int indent, const ASN1_PCTX *pctx)
+ {
+ return BIO_printf(out, "%ld\n", *(long *)pval);
+ }
diff --git a/src/crypto/base64/CMakeLists.txt b/src/crypto/base64/CMakeLists.txt
new file mode 100644
index 0000000..2b4f081
--- /dev/null
+++ b/src/crypto/base64/CMakeLists.txt
@@ -0,0 +1,17 @@
+include_directories(. .. ../../include)
+
+add_library(
+ base64
+
+ OBJECT
+
+ base64.c
+)
+
+add_executable(
+ base64_test
+
+ base64_test.c
+)
+
+target_link_libraries(base64_test crypto)
diff --git a/src/crypto/base64/base64.c b/src/crypto/base64/base64.c
new file mode 100644
index 0000000..12a52cf
--- /dev/null
+++ b/src/crypto/base64/base64.c
@@ -0,0 +1,474 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/base64.h>
+
+#include <assert.h>
+#include <limits.h>
+#include <string.h>
+
+
+static const unsigned char data_bin2ascii[65] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+#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)
+
+/* 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)
+
+static const uint8_t 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, 0xFF, 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 uint8_t conv_ascii2bin(uint8_t a) {
+ if (a >= 128) {
+ return 0xFF;
+ }
+ return data_ascii2bin[a];
+}
+
+void EVP_EncodeInit(EVP_ENCODE_CTX *ctx) {
+ ctx->length = 48;
+ ctx->num = 0;
+ ctx->line_num = 0;
+}
+
+void EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len,
+ const uint8_t *in, size_t in_len) {
+ unsigned i, j;
+ unsigned total = 0;
+
+ *out_len = 0;
+ if (in_len == 0) {
+ return;
+ }
+
+ assert(ctx->length <= sizeof(ctx->enc_data));
+
+ if (ctx->num + in_len < ctx->length) {
+ memcpy(&ctx->enc_data[ctx->num], in, in_len);
+ ctx->num += in_len;
+ return;
+ }
+ if (ctx->num != 0) {
+ i = ctx->length - ctx->num;
+ memcpy(&ctx->enc_data[ctx->num], in, i);
+ in += i;
+ in_len -= i;
+ j = EVP_EncodeBlock(out, ctx->enc_data, ctx->length);
+ ctx->num = 0;
+ out += j;
+ *(out++) = '\n';
+ *out = '\0';
+ total = j + 1;
+ }
+ while (in_len >= ctx->length) {
+ j = EVP_EncodeBlock(out, in, ctx->length);
+ in += ctx->length;
+ in_len -= ctx->length;
+ out += j;
+ *(out++) = '\n';
+ *out = '\0';
+ total += j + 1;
+ }
+ if (in_len != 0) {
+ memcpy(&ctx->enc_data[0], in, in_len);
+ }
+ ctx->num = in_len;
+ *out_len = total;
+}
+
+void EVP_EncodeFinal(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len) {
+ unsigned ret = 0;
+
+ if (ctx->num != 0) {
+ ret = EVP_EncodeBlock(out, ctx->enc_data, ctx->num);
+ out[ret++] = '\n';
+ out[ret] = '\0';
+ ctx->num = 0;
+ }
+ *out_len = ret;
+}
+
+size_t EVP_EncodeBlock(uint8_t *dst, const uint8_t *src, size_t src_len) {
+ uint32_t l;
+ size_t remaining = src_len, ret = 0;
+
+ while (remaining) {
+ if (remaining >= 3) {
+ l = (((uint32_t)src[0]) << 16L) | (((uint32_t)src[1]) << 8L) | src[2];
+ *(dst++) = conv_bin2ascii(l >> 18L);
+ *(dst++) = conv_bin2ascii(l >> 12L);
+ *(dst++) = conv_bin2ascii(l >> 6L);
+ *(dst++) = conv_bin2ascii(l);
+ remaining -= 3;
+ } else {
+ l = ((uint32_t)src[0]) << 16L;
+ if (remaining == 2) {
+ l |= ((uint32_t)src[1] << 8L);
+ }
+
+ *(dst++) = conv_bin2ascii(l >> 18L);
+ *(dst++) = conv_bin2ascii(l >> 12L);
+ *(dst++) = (remaining == 1) ? '=' : conv_bin2ascii(l >> 6L);
+ *(dst++) = '=';
+ remaining = 0;
+ }
+ ret += 4;
+ src += 3;
+ }
+
+ *dst = '\0';
+ return ret;
+}
+
+int EVP_DecodedLength(size_t *out_len, size_t len) {
+ if (len % 4 != 0) {
+ return 0;
+ }
+ *out_len = (len / 4) * 3;
+ return 1;
+}
+
+int EVP_DecodeBase64(uint8_t *out, size_t *out_len, size_t max_out,
+ const uint8_t *in, size_t in_len) {
+ uint8_t a, b, c, d;
+ size_t pad_len = 0, len = 0, max_len, i;
+ uint32_t l;
+
+ if (!EVP_DecodedLength(&max_len, in_len) || max_out < max_len) {
+ return 0;
+ }
+
+ for (i = 0; i < in_len; i += 4) {
+ a = conv_ascii2bin(*(in++));
+ b = conv_ascii2bin(*(in++));
+ if (i + 4 == in_len && in[1] == '=') {
+ if (in[0] == '=') {
+ pad_len = 2;
+ } else {
+ pad_len = 1;
+ }
+ }
+ if (pad_len < 2) {
+ c = conv_ascii2bin(*(in++));
+ } else {
+ c = 0;
+ }
+ if (pad_len < 1) {
+ d = conv_ascii2bin(*(in++));
+ } else {
+ d = 0;
+ }
+ if ((a & 0x80) || (b & 0x80) || (c & 0x80) || (d & 0x80)) {
+ return 0;
+ }
+ l = ((((uint32_t)a) << 18L) | (((uint32_t)b) << 12L) |
+ (((uint32_t)c) << 6L) | (((uint32_t)d)));
+ *(out++) = (uint8_t)(l >> 16L) & 0xff;
+ if (pad_len < 2) {
+ *(out++) = (uint8_t)(l >> 8L) & 0xff;
+ }
+ if (pad_len < 1) {
+ *(out++) = (uint8_t)(l) & 0xff;
+ }
+ len += 3 - pad_len;
+ }
+ *out_len = len;
+ return 1;
+}
+
+void EVP_DecodeInit(EVP_ENCODE_CTX *ctx) {
+ ctx->length = 30;
+ ctx->num = 0;
+ ctx->line_num = 0;
+ ctx->expect_nl = 0;
+}
+
+int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len,
+ const uint8_t *in, size_t in_len) {
+ int seof = -1, eof = 0, rv = -1, v, tmp, exp_nl;
+ uint8_t *d;
+ unsigned i, n, ln, ret = 0;
+
+ n = ctx->num;
+ d = ctx->enc_data;
+ ln = ctx->line_num;
+ exp_nl = ctx->expect_nl;
+
+ /* last line of input. */
+ if (in_len == 0 || (n == 0 && conv_ascii2bin(in[0]) == B64_EOF)) {
+ rv = 0;
+ goto end;
+ }
+
+ /* We parse the input data */
+ for (i = 0; i < in_len; i++) {
+ /* If the current line is > 80 characters, scream alot */
+ if (ln >= 80) {
+ rv = -1;
+ goto end;
+ }
+
+ /* Get char and put it into the buffer */
+ tmp = *(in++);
+ v = conv_ascii2bin(tmp);
+ /* only save the good data :-) */
+ if (!B64_NOT_BASE64(v)) {
+ assert(n < sizeof(ctx->enc_data));
+ d[n++] = tmp;
+ ln++;
+ } else if (v == B64_ERROR) {
+ rv = -1;
+ goto end;
+ }
+
+ /* have we seen a '=' which is 'definitly' the last
+ * input line. seof will point to the character that
+ * holds it. and eof will hold how many characters to
+ * chop off. */
+ if (tmp == '=') {
+ if (seof == -1) {
+ seof = n;
+ }
+ eof++;
+ if (eof > 2) {
+ /* There are, at most, two equals signs at the end of base64 data. */
+ rv = -1;
+ goto end;
+ }
+ }
+
+ if (v == B64_CR) {
+ ln = 0;
+ if (exp_nl) {
+ continue;
+ }
+ }
+
+ /* eoln */
+ if (v == B64_EOLN) {
+ ln = 0;
+ if (exp_nl) {
+ exp_nl = 0;
+ continue;
+ }
+ }
+ exp_nl = 0;
+
+ /* If we are at the end of input and it looks like a
+ * line, process it. */
+ if ((i + 1) == in_len && (((n & 3) == 0) || eof)) {
+ v = B64_EOF;
+ /* In case things were given us in really small
+ records (so two '=' were given in separate
+ updates), eof may contain the incorrect number
+ of ending bytes to skip, so let's redo the count */
+ eof = 0;
+ if (d[n - 1] == '=') {
+ eof++;
+ }
+ if (d[n - 2] == '=') {
+ eof++;
+ }
+ /* There will never be more than two '=' */
+ }
+
+ if ((v == B64_EOF && (n & 3) == 0) || n >= 64) {
+ /* This is needed to work correctly on 64 byte input
+ * lines. We process the line and then need to
+ * accept the '\n' */
+ if (v != B64_EOF && n >= 64) {
+ exp_nl = 1;
+ }
+ if (n > 0) {
+ /* TODO(davidben): Switch this to EVP_DecodeBase64. */
+ v = EVP_DecodeBlock(out, d, n);
+ n = 0;
+ if (v < 0) {
+ rv = 0;
+ goto end;
+ }
+ ret += (v - eof);
+ } else {
+ eof = 1;
+ v = 0;
+ }
+
+ /* This is the case where we have had a short
+ * but valid input line */
+ if (v < (int)ctx->length && eof) {
+ rv = 0;
+ goto end;
+ } else {
+ ctx->length = v;
+ }
+
+ if (seof >= 0) {
+ rv = 0;
+ goto end;
+ }
+ out += v;
+ }
+ }
+ rv = 1;
+
+end:
+ *out_len = ret;
+ ctx->num = n;
+ ctx->line_num = ln;
+ ctx->expect_nl = exp_nl;
+ return rv;
+}
+
+int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, uint8_t *out, int *outl) {
+ int i;
+
+ *outl = 0;
+ if (ctx->num != 0) {
+ /* TODO(davidben): Switch this to EVP_DecodeBase64. */
+ i = EVP_DecodeBlock(out, ctx->enc_data, ctx->num);
+ if (i < 0) {
+ return -1;
+ }
+ ctx->num = 0;
+ *outl = i;
+ return 1;
+ } else {
+ return 1;
+ }
+}
+
+int EVP_DecodeBlock(uint8_t *dst, const uint8_t *src, size_t src_len) {
+ size_t dst_len;
+
+ /* trim white space from the start of the line. */
+ while (conv_ascii2bin(*src) == B64_WS && src_len > 0) {
+ src++;
+ src_len--;
+ }
+
+ /* strip off stuff at the end of the line
+ * ascii2bin values B64_WS, B64_EOLN, B64_EOLN and B64_EOF */
+ while (src_len > 3 && B64_NOT_BASE64(conv_ascii2bin(src[src_len - 1]))) {
+ src_len--;
+ }
+
+ if (!EVP_DecodedLength(&dst_len, src_len) || dst_len > INT_MAX) {
+ return -1;
+ }
+ if (!EVP_DecodeBase64(dst, &dst_len, dst_len, src, src_len)) {
+ return -1;
+ }
+
+ /* EVP_DecodeBlock does not take padding into account, so put the
+ * NULs back in... so the caller can strip them back out. */
+ while (dst_len % 3 != 0) {
+ dst[dst_len++] = '\0';
+ }
+ assert(dst_len <= INT_MAX);
+
+ return dst_len;
+}
+
+int EVP_EncodedLength(size_t *out_len, size_t len) {
+ if (len + 2 < len) {
+ return 0;
+ }
+ len += 2;
+ len /= 3;
+ if (((len << 2) >> 2) != len) {
+ return 0;
+ }
+ len <<= 2;
+ if (len + 1 < len) {
+ return 0;
+ }
+ len++;
+ *out_len = len;
+ return 1;
+}
diff --git a/src/crypto/base64/base64_test.c b/src/crypto/base64/base64_test.c
new file mode 100644
index 0000000..411323f
--- /dev/null
+++ b/src/crypto/base64/base64_test.c
@@ -0,0 +1,133 @@
+/* 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 <stdio.h>
+#include <string.h>
+
+#include <openssl/base64.h>
+#include <openssl/crypto.h>
+#include <openssl/err.h>
+
+
+typedef struct {
+ const char *decoded;
+ const char *encoded;
+} TEST_VECTOR;
+
+/* Test vectors from RFC 4648. */
+static const TEST_VECTOR test_vectors[] = {
+ { "", "" },
+ { "f" , "Zg==" },
+ { "fo", "Zm8=" },
+ { "foo", "Zm9v" },
+ { "foob", "Zm9vYg==" },
+ { "fooba", "Zm9vYmE=" },
+ { "foobar", "Zm9vYmFy" },
+};
+
+static const size_t kNumTests = sizeof(test_vectors) / sizeof(test_vectors[0]);
+
+static int test_encode(void) {
+ uint8_t out[9];
+ size_t i, len;
+
+ for (i = 0; i < kNumTests; i++) {
+ const TEST_VECTOR *t = &test_vectors[i];
+ len = EVP_EncodeBlock(out, (const uint8_t*)t->decoded, strlen(t->decoded));
+ if (len != strlen(t->encoded) ||
+ memcmp(out, t->encoded, len) != 0) {
+ fprintf(stderr, "encode(\"%s\") = \"%.*s\", want \"%s\"\n",
+ t->decoded, (int)len, (const char*)out, t->encoded);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static int test_decode(void) {
+ uint8_t out[6];
+ size_t i, len;
+ int ret;
+
+ for (i = 0; i < kNumTests; i++) {
+ /* Test the normal API. */
+ const TEST_VECTOR *t = &test_vectors[i];
+ size_t expected_len = strlen(t->decoded);
+ if (!EVP_DecodeBase64(out, &len, sizeof(out),
+ (const uint8_t*)t->encoded, strlen(t->encoded))) {
+ fprintf(stderr, "decode(\"%s\") failed\n", t->encoded);
+ return 0;
+ }
+ if (len != strlen(t->decoded) ||
+ memcmp(out, t->decoded, len) != 0) {
+ fprintf(stderr, "decode(\"%s\") = \"%.*s\", want \"%s\"\n",
+ t->encoded, (int)len, (const char*)out, t->decoded);
+ return 0;
+ }
+
+ /* Test that the padding behavior of the deprecated API is
+ * preserved. */
+ ret = EVP_DecodeBlock(out, (const uint8_t*)t->encoded, strlen(t->encoded));
+ if (ret < 0) {
+ fprintf(stderr, "decode(\"%s\") failed\n", t->encoded);
+ return 0;
+ }
+ if (ret % 3 != 0) {
+ fprintf(stderr, "EVP_DecodeBlock did not ignore padding\n");
+ return 0;
+ }
+ if (expected_len % 3 != 0) {
+ ret -= 3 - (expected_len % 3);
+ }
+ if (ret != strlen(t->decoded) ||
+ memcmp(out, t->decoded, ret) != 0) {
+ fprintf(stderr, "decode(\"%s\") = \"%.*s\", want \"%s\"\n",
+ t->encoded, ret, (const char*)out, t->decoded);
+ return 0;
+ }
+ }
+
+ if (EVP_DecodeBase64(out, &len, sizeof(out), (const uint8_t*)"a!bc", 4)) {
+ fprintf(stderr, "Failed to reject invalid characters in the middle.\n");
+ return 0;
+ }
+
+ if (EVP_DecodeBase64(out, &len, sizeof(out), (const uint8_t*)"a=bc", 4)) {
+ fprintf(stderr, "Failed to reject invalid characters in the middle.\n");
+ return 0;
+ }
+
+ if (EVP_DecodeBase64(out, &len, sizeof(out), (const uint8_t*)"abc", 4)) {
+ fprintf(stderr, "Failed to reject invalid input length.\n");
+ return 0;
+ }
+
+ return 1;
+}
+
+int main(void) {
+ CRYPTO_library_init();
+ ERR_load_crypto_strings();
+
+ if (!test_encode()) {
+ return 1;
+ }
+
+ if (!test_decode()) {
+ return 1;
+ }
+
+ printf("PASS\n");
+ return 0;
+}
diff --git a/src/crypto/bio/CMakeLists.txt b/src/crypto/bio/CMakeLists.txt
new file mode 100644
index 0000000..6211e85
--- /dev/null
+++ b/src/crypto/bio/CMakeLists.txt
@@ -0,0 +1,31 @@
+include_directories(. .. ../../include)
+
+add_library(
+ bio
+
+ OBJECT
+
+ bio.c
+ bio_error.c
+ bio_mem.c
+ buffer.c
+ connect.c
+ fd.c
+ file.c
+ hexdump.c
+ pair.c
+ printf.c
+ socket.c
+ socket_helper.c
+)
+
+add_executable(
+ bio_test
+
+ bio_test.c
+)
+
+target_link_libraries(bio_test crypto)
+if (WIN32)
+ target_link_libraries(bio_test ws2_32)
+endif()
diff --git a/src/crypto/bio/bio.c b/src/crypto/bio/bio.c
new file mode 100644
index 0000000..4d947a6
--- /dev/null
+++ b/src/crypto/bio/bio.c
@@ -0,0 +1,477 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/bio.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <stddef.h>
+#include <string.h>
+
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/thread.h>
+
+
+/* BIO_set initialises a BIO structure to have the given type and sets the
+ * reference count to one. It returns one on success or zero on error. */
+static int bio_set(BIO *bio, const BIO_METHOD *method) {
+ /* This function can be called with a stack allocated |BIO| so we have to
+ * assume that the contents of |BIO| are arbitary. This also means that it'll
+ * leak memory if you call |BIO_set| twice on the same BIO. */
+ memset(bio, 0, sizeof(BIO));
+
+ bio->method = method;
+ bio->shutdown = 1;
+ bio->references = 1;
+
+ if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data)) {
+ return 0;
+ }
+
+ if (method->create != NULL) {
+ if (!method->create(bio)) {
+ CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data);
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+BIO *BIO_new(const BIO_METHOD *method) {
+ BIO *ret = OPENSSL_malloc(sizeof(BIO));
+ if (ret == NULL) {
+ OPENSSL_PUT_ERROR(BIO, BIO_new, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ if (!bio_set(ret, method)) {
+ OPENSSL_free(ret);
+ ret = NULL;
+ }
+
+ return ret;
+}
+
+int BIO_free(BIO *bio) {
+ BIO *next_bio;
+
+ for (; bio != NULL; bio = next_bio) {
+ int refs = CRYPTO_add(&bio->references, -1, CRYPTO_LOCK_BIO);
+ if (refs > 0) {
+ return 0;
+ }
+
+ if (bio->callback != NULL) {
+ int i = (int)bio->callback(bio, BIO_CB_FREE, NULL, 0, 0, 1);
+ if (i <= 0) {
+ return i;
+ }
+ }
+
+ next_bio = BIO_pop(bio);
+
+ CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data);
+
+ if (bio->method != NULL && bio->method->destroy != NULL) {
+ bio->method->destroy(bio);
+ }
+
+ OPENSSL_free(bio);
+ }
+ return 1;
+}
+
+void BIO_vfree(BIO *bio) {
+ BIO_free(bio);
+}
+
+void BIO_free_all(BIO *bio) {
+ BIO_free(bio);
+}
+
+static int bio_io(BIO *bio, void *buf, int len, size_t method_offset,
+ int callback_flags, size_t *num) {
+ int i;
+ typedef int (*io_func_t)(BIO *, char *, int);
+ io_func_t io_func = NULL;
+
+ if (bio != NULL && bio->method != NULL) {
+ io_func =
+ *((const io_func_t *)(((const uint8_t *)bio->method) + method_offset));
+ }
+
+ if (io_func == NULL) {
+ OPENSSL_PUT_ERROR(BIO, bio_io, BIO_R_UNSUPPORTED_METHOD);
+ return -2;
+ }
+
+ if (bio->callback != NULL) {
+ i = (int) bio->callback(bio, callback_flags, buf, len, 0L, 1L);
+ if (i <= 0) {
+ return i;
+ }
+ }
+
+ if (!bio->init) {
+ OPENSSL_PUT_ERROR(BIO, bio_io, BIO_R_UNINITIALIZED);
+ return -2;
+ }
+
+ i = 0;
+ if (buf != NULL && len > 0) {
+ i = io_func(bio, buf, len);
+ }
+
+ if (i > 0) {
+ *num += i;
+ }
+
+ if (bio->callback != NULL) {
+ i = (int)(bio->callback(bio, callback_flags | BIO_CB_RETURN, buf, len, 0L,
+ (long)i));
+ }
+
+ return i;
+}
+
+int BIO_read(BIO *bio, void *buf, int len) {
+ return bio_io(bio, buf, len, offsetof(BIO_METHOD, bread), BIO_CB_READ,
+ &bio->num_read);
+}
+
+int BIO_gets(BIO *bio, char *buf, int len) {
+ return bio_io(bio, buf, len, offsetof(BIO_METHOD, bgets), BIO_CB_GETS,
+ &bio->num_read);
+}
+
+int BIO_write(BIO *bio, const void *in, int inl) {
+ return bio_io(bio, (char *)in, inl, offsetof(BIO_METHOD, bwrite),
+ BIO_CB_WRITE, &bio->num_write);
+}
+
+int BIO_puts(BIO *bio, const char *in) {
+ return BIO_write(bio, in, strlen(in));
+}
+
+int BIO_flush(BIO *bio) {
+ return BIO_ctrl(bio, BIO_CTRL_FLUSH, 0, NULL);
+}
+
+long BIO_ctrl(BIO *bio, int cmd, long larg, void *parg) {
+ long ret;
+
+ if (bio == NULL) {
+ return 0;
+ }
+
+ if (bio->method == NULL || bio->method->ctrl == NULL) {
+ OPENSSL_PUT_ERROR(BIO, BIO_ctrl, BIO_R_UNSUPPORTED_METHOD);
+ return -2;
+ }
+
+ if (bio->callback != NULL) {
+ ret = bio->callback(bio, BIO_CB_CTRL, parg, cmd, larg, 1);
+ if (ret <= 0) {
+ return ret;
+ }
+ }
+
+ ret = bio->method->ctrl(bio, cmd, larg, parg);
+
+ if (bio->callback != NULL) {
+ ret = bio->callback(bio, BIO_CB_CTRL | BIO_CB_RETURN, parg, cmd, larg, ret);
+ }
+
+ return ret;
+}
+
+char *BIO_ptr_ctrl(BIO *b, int cmd, long larg) {
+ char *p = NULL;
+
+ if (BIO_ctrl(b, cmd, larg, (void *)&p) <= 0) {
+ return NULL;
+ }
+
+ return p;
+}
+
+long BIO_int_ctrl(BIO *b, int cmd, long larg, int iarg) {
+ int i = iarg;
+
+ return BIO_ctrl(b, cmd, larg, (void *)&i);
+}
+
+int BIO_reset(BIO *bio) {
+ return BIO_ctrl(bio, BIO_CTRL_RESET, 0, NULL);
+}
+
+void BIO_set_flags(BIO *bio, int flags) {
+ bio->flags |= flags;
+}
+
+int BIO_test_flags(const BIO *bio, int flags) {
+ return bio->flags & flags;
+}
+
+int BIO_should_read(const BIO *bio) {
+ return BIO_test_flags(bio, BIO_FLAGS_READ);
+}
+
+int BIO_should_write(const BIO *bio) {
+ return BIO_test_flags(bio, BIO_FLAGS_WRITE);
+}
+
+int BIO_should_retry(const BIO *bio) {
+ return BIO_test_flags(bio, BIO_FLAGS_SHOULD_RETRY);
+}
+
+int BIO_should_io_special(const BIO *bio) {
+ return BIO_test_flags(bio, BIO_FLAGS_IO_SPECIAL);
+}
+
+int BIO_get_retry_reason(const BIO *bio) { return bio->retry_reason; }
+
+void BIO_clear_flags(BIO *bio, int flags) {
+ bio->flags &= ~flags;
+}
+
+void BIO_set_retry_read(BIO *bio) {
+ bio->flags |= BIO_FLAGS_READ | BIO_FLAGS_SHOULD_RETRY;
+}
+
+void BIO_set_retry_write(BIO *bio) {
+ bio->flags |= BIO_FLAGS_WRITE | BIO_FLAGS_SHOULD_RETRY;
+}
+
+static const int kRetryFlags = BIO_FLAGS_RWS | BIO_FLAGS_SHOULD_RETRY;
+
+int BIO_get_retry_flags(BIO *bio) {
+ return bio->flags & kRetryFlags;
+}
+
+void BIO_clear_retry_flags(BIO *bio) {
+ bio->flags &= ~kRetryFlags;
+ bio->retry_reason = 0;
+}
+
+int BIO_method_type(const BIO *bio) { return bio->method->type; }
+
+void BIO_copy_next_retry(BIO *bio) {
+ BIO_clear_retry_flags(bio);
+ BIO_set_flags(bio, BIO_get_retry_flags(bio->next_bio));
+ bio->retry_reason = bio->next_bio->retry_reason;
+}
+
+long BIO_callback_ctrl(BIO *bio, int cmd, bio_info_cb fp) {
+ long ret;
+ bio_info_cb cb;
+
+ if (bio == NULL) {
+ return 0;
+ }
+
+ if (bio->method == NULL || bio->method->callback_ctrl == NULL) {
+ OPENSSL_PUT_ERROR(BIO, BIO_callback_ctrl, BIO_R_UNSUPPORTED_METHOD);
+ return 0;
+ }
+
+ cb = bio->callback;
+
+ if (cb != NULL) {
+ ret = cb(bio, BIO_CB_CTRL, (void *)&fp, cmd, 0, 1L);
+ if (ret <= 0) {
+ return ret;
+ }
+ }
+
+ ret = bio->method->callback_ctrl(bio, cmd, fp);
+
+ if (cb != NULL) {
+ ret = cb(bio, BIO_CB_CTRL | BIO_CB_RETURN, (void *)&fp, cmd, 0, ret);
+ }
+
+ return ret;
+}
+
+size_t BIO_pending(const BIO *bio) {
+ return BIO_ctrl((BIO *) bio, BIO_CTRL_PENDING, 0, NULL);
+}
+
+size_t BIO_ctrl_pending(const BIO *bio) {
+ return BIO_pending(bio);
+}
+
+size_t BIO_wpending(const BIO *bio) {
+ return BIO_ctrl((BIO *) bio, BIO_CTRL_WPENDING, 0, NULL);
+}
+
+int BIO_set_close(BIO *bio, int close_flag) {
+ return BIO_ctrl(bio, BIO_CTRL_SET_CLOSE, close_flag, NULL);
+}
+
+void BIO_set_callback(BIO *bio, bio_info_cb callback_func) {
+ bio->callback = callback_func;
+}
+
+void BIO_set_callback_arg(BIO *bio, char *arg) {
+ bio->cb_arg = arg;
+}
+
+char *BIO_get_callback_arg(const BIO *bio) {
+ return bio->cb_arg;
+}
+
+OPENSSL_EXPORT size_t BIO_number_read(const BIO *bio) {
+ return bio->num_read;
+}
+
+OPENSSL_EXPORT size_t BIO_number_written(const BIO *bio) {
+ return bio->num_write;
+}
+
+BIO *BIO_push(BIO *bio, BIO *appended_bio) {
+ BIO *last_bio;
+
+ if (bio == NULL) {
+ return bio;
+ }
+
+ last_bio = bio;
+ while (last_bio->next_bio != NULL) {
+ last_bio = last_bio->next_bio;
+ }
+
+ last_bio->next_bio = appended_bio;
+ /* TODO(fork): this seems very suspect. If we got rid of BIO SSL, we could
+ * get rid of this. */
+ BIO_ctrl(bio, BIO_CTRL_PUSH, 0, bio);
+
+ return bio;
+}
+
+BIO *BIO_pop(BIO *bio) {
+ BIO *ret;
+
+ if (bio == NULL) {
+ return NULL;
+ }
+ ret = bio->next_bio;
+ BIO_ctrl(bio, BIO_CTRL_POP, 0, bio);
+ bio->next_bio = NULL;
+ return ret;
+}
+
+BIO *BIO_next(BIO *bio) {
+ if (!bio) {
+ return NULL;
+ }
+ return bio->next_bio;
+}
+
+BIO *BIO_find_type(BIO *bio, int type) {
+ int method_type, mask;
+
+ if (!bio) {
+ return NULL;
+ }
+ mask = type & 0xff;
+
+ do {
+ if (bio->method != NULL) {
+ method_type = bio->method->type;
+
+ if (!mask) {
+ if (method_type & type) {
+ return bio;
+ }
+ } else if (method_type == type) {
+ return bio;
+ }
+ }
+ bio = bio->next_bio;
+ } while (bio != NULL);
+
+ return NULL;
+}
+
+int BIO_indent(BIO *bio, unsigned indent, unsigned max_indent) {
+ if (indent > max_indent) {
+ indent = max_indent;
+ }
+
+ while (indent--) {
+ if (BIO_puts(bio, " ") != 1) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+void BIO_print_errors_fp(FILE *out) {
+ BIO *bio = BIO_new_fp(out, BIO_NOCLOSE);
+ BIO_print_errors(bio);
+ BIO_free(bio);
+}
+
+static int print_bio(const char *str, size_t len, void *bio) {
+ return BIO_write((BIO *)bio, str, len);
+}
+
+void BIO_print_errors(BIO *bio) {
+ ERR_print_errors_cb(print_bio, bio);
+}
diff --git a/src/crypto/bio/bio_error.c b/src/crypto/bio/bio_error.c
new file mode 100644
index 0000000..09585e4
--- /dev/null
+++ b/src/crypto/bio/bio_error.c
@@ -0,0 +1,59 @@
+/* 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 <openssl/err.h>
+
+#include <openssl/bio.h>
+
+const ERR_STRING_DATA BIO_error_string_data[] = {
+ {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_callback_ctrl, 0), "BIO_callback_ctrl"},
+ {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_ctrl, 0), "BIO_ctrl"},
+ {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_new, 0), "BIO_new"},
+ {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_new_file, 0), "BIO_new_file"},
+ {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_new_mem_buf, 0), "BIO_new_mem_buf"},
+ {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_zero_copy_get_read_buf, 0), "BIO_zero_copy_get_read_buf"},
+ {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_zero_copy_get_read_buf_done, 0), "BIO_zero_copy_get_read_buf_done"},
+ {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_zero_copy_get_write_buf, 0), "BIO_zero_copy_get_write_buf"},
+ {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_zero_copy_get_write_buf_done, 0), "BIO_zero_copy_get_write_buf_done"},
+ {ERR_PACK(ERR_LIB_BIO, BIO_F_bio_ctrl, 0), "bio_ctrl"},
+ {ERR_PACK(ERR_LIB_BIO, BIO_F_bio_io, 0), "bio_io"},
+ {ERR_PACK(ERR_LIB_BIO, BIO_F_bio_ip_and_port_to_socket_and_addr, 0), "bio_ip_and_port_to_socket_and_addr"},
+ {ERR_PACK(ERR_LIB_BIO, BIO_F_bio_make_pair, 0), "bio_make_pair"},
+ {ERR_PACK(ERR_LIB_BIO, BIO_F_bio_write, 0), "bio_write"},
+ {ERR_PACK(ERR_LIB_BIO, BIO_F_buffer_ctrl, 0), "buffer_ctrl"},
+ {ERR_PACK(ERR_LIB_BIO, BIO_F_conn_ctrl, 0), "conn_ctrl"},
+ {ERR_PACK(ERR_LIB_BIO, BIO_F_conn_state, 0), "conn_state"},
+ {ERR_PACK(ERR_LIB_BIO, BIO_F_file_ctrl, 0), "file_ctrl"},
+ {ERR_PACK(ERR_LIB_BIO, BIO_F_file_read, 0), "file_read"},
+ {ERR_PACK(ERR_LIB_BIO, BIO_F_mem_write, 0), "mem_write"},
+ {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_ASN1_OBJECT_TOO_LONG), "ASN1_OBJECT_TOO_LONG"},
+ {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_BAD_FOPEN_MODE), "BAD_FOPEN_MODE"},
+ {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_BROKEN_PIPE), "BROKEN_PIPE"},
+ {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_CONNECT_ERROR), "CONNECT_ERROR"},
+ {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_ERROR_SETTING_NBIO), "ERROR_SETTING_NBIO"},
+ {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_INVALID_ARGUMENT), "INVALID_ARGUMENT"},
+ {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_IN_USE), "IN_USE"},
+ {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_KEEPALIVE), "KEEPALIVE"},
+ {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_NBIO_CONNECT_ERROR), "NBIO_CONNECT_ERROR"},
+ {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_NO_HOSTNAME_SPECIFIED), "NO_HOSTNAME_SPECIFIED"},
+ {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_NO_PORT_SPECIFIED), "NO_PORT_SPECIFIED"},
+ {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_NO_SUCH_FILE), "NO_SUCH_FILE"},
+ {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_NULL_PARAMETER), "NULL_PARAMETER"},
+ {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_SYS_LIB), "SYS_LIB"},
+ {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_UNABLE_TO_CREATE_SOCKET), "UNABLE_TO_CREATE_SOCKET"},
+ {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_UNINITIALIZED), "UNINITIALIZED"},
+ {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_UNSUPPORTED_METHOD), "UNSUPPORTED_METHOD"},
+ {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_WRITE_TO_READ_ONLY_BIO), "WRITE_TO_READ_ONLY_BIO"},
+ {0, NULL},
+};
diff --git a/src/crypto/bio/bio_mem.c b/src/crypto/bio/bio_mem.c
new file mode 100644
index 0000000..f3aad6f
--- /dev/null
+++ b/src/crypto/bio/bio_mem.c
@@ -0,0 +1,327 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/bio.h>
+
+#include <limits.h>
+#include <string.h>
+
+#include <openssl/buf.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+
+
+BIO *BIO_new_mem_buf(void *buf, int len) {
+ BIO *ret;
+ BUF_MEM *b;
+ const size_t size = len < 0 ? strlen((char *)buf) : (size_t)len;
+
+ if (!buf && len != 0) {
+ OPENSSL_PUT_ERROR(BIO, BIO_new_mem_buf, BIO_R_NULL_PARAMETER);
+ return NULL;
+ }
+
+ ret = BIO_new(BIO_s_mem());
+ if (ret == NULL) {
+ return NULL;
+ }
+
+ b = (BUF_MEM *)ret->ptr;
+ b->data = buf;
+ b->length = size;
+ b->max = size;
+
+ ret->flags |= BIO_FLAGS_MEM_RDONLY;
+
+ /* |num| is used to store the value that this BIO will return when it runs
+ * out of data. If it's negative then the retry flags will also be set. Since
+ * this is static data, retrying wont help */
+ ret->num = 0;
+
+ return ret;
+}
+
+static int mem_new(BIO *bio) {
+ BUF_MEM *b;
+
+ b = BUF_MEM_new();
+ if (b == NULL) {
+ return 0;
+ }
+
+ /* |shutdown| is used to store the close flag: whether the BIO has ownership
+ * of the BUF_MEM. */
+ bio->shutdown = 1;
+ bio->init = 1;
+ bio->num = -1;
+ bio->ptr = (char *)b;
+
+ return 1;
+}
+
+static int mem_free(BIO *bio) {
+ BUF_MEM *b;
+
+ if (bio == NULL) {
+ return 0;
+ }
+
+ if (!bio->shutdown || !bio->init || bio->ptr == NULL) {
+ return 1;
+ }
+
+ b = (BUF_MEM *)bio->ptr;
+ if (bio->flags & BIO_FLAGS_MEM_RDONLY) {
+ b->data = NULL;
+ }
+ BUF_MEM_free(b);
+ bio->ptr = NULL;
+ return 1;
+}
+
+static int mem_read(BIO *bio, char *out, int outl) {
+ int ret;
+ BUF_MEM *b = (BUF_MEM*) bio->ptr;
+
+ BIO_clear_retry_flags(bio);
+ ret = outl;
+ if (b->length < INT_MAX && ret > (int)b->length) {
+ ret = b->length;
+ }
+
+ if (ret > 0) {
+ memcpy(out, b->data, ret);
+ b->length -= ret;
+ if (bio->flags & BIO_FLAGS_MEM_RDONLY) {
+ b->data += ret;
+ } else {
+ memmove(b->data, &b->data[ret], b->length);
+ }
+ } else if (b->length == 0) {
+ ret = bio->num;
+ if (ret != 0) {
+ BIO_set_retry_read(bio);
+ }
+ }
+ return ret;
+}
+
+static int mem_write(BIO *bio, const char *in, int inl) {
+ int ret = -1;
+ int blen;
+ BUF_MEM *b;
+
+ b = (BUF_MEM *)bio->ptr;
+
+ if (bio->flags & BIO_FLAGS_MEM_RDONLY) {
+ OPENSSL_PUT_ERROR(BIO, mem_write, BIO_R_WRITE_TO_READ_ONLY_BIO);
+ goto err;
+ }
+
+ BIO_clear_retry_flags(bio);
+ blen = b->length;
+ if (INT_MAX - blen < inl) {
+ goto err;
+ }
+ if (BUF_MEM_grow_clean(b, blen + inl) != (blen + inl)) {
+ goto err;
+ }
+ memcpy(&b->data[blen], in, inl);
+ ret = inl;
+
+err:
+ return ret;
+}
+
+static int mem_puts(BIO *bp, const char *str) {
+ return mem_write(bp, str, strlen(str));
+}
+
+static int mem_gets(BIO *bio, char *buf, int size) {
+ int i, j;
+ char *p;
+ BUF_MEM *b = (BUF_MEM *)bio->ptr;
+
+ BIO_clear_retry_flags(bio);
+ j = b->length;
+ if (size - 1 < j) {
+ j = size - 1;
+ }
+ if (j <= 0) {
+ if (size > 0) {
+ *buf = 0;
+ }
+ return 0;
+ }
+
+ p = b->data;
+ for (i = 0; i < j; i++) {
+ if (p[i] == '\n') {
+ i++;
+ break;
+ }
+ }
+
+ /* i is now the max num of bytes to copy, either j or up to and including the
+ * first newline */
+
+ i = mem_read(bio, buf, i);
+ if (i > 0) {
+ buf[i] = '\0';
+ }
+ return i;
+}
+
+static long mem_ctrl(BIO *bio, int cmd, long num, void *ptr) {
+ long ret = 1;
+ char **pptr;
+
+ BUF_MEM *b = (BUF_MEM *)bio->ptr;
+
+ switch (cmd) {
+ case BIO_CTRL_RESET:
+ if (b->data != NULL) {
+ /* For read only case reset to the start again */
+ if (bio->flags & BIO_FLAGS_MEM_RDONLY) {
+ b->data -= b->max - b->length;
+ b->length = b->max;
+ } else {
+ memset(b->data, 0, b->max);
+ b->length = 0;
+ }
+ }
+ break;
+ case BIO_CTRL_EOF:
+ ret = (long)(b->length == 0);
+ break;
+ case BIO_C_SET_BUF_MEM_EOF_RETURN:
+ bio->num = (int)num;
+ break;
+ case BIO_CTRL_INFO:
+ ret = (long)b->length;
+ if (ptr != NULL) {
+ pptr = (char **)ptr;
+ *pptr = (char *)&b->data[0];
+ }
+ break;
+ case BIO_C_SET_BUF_MEM:
+ mem_free(bio);
+ bio->shutdown = (int)num;
+ bio->ptr = ptr;
+ break;
+ case BIO_C_GET_BUF_MEM_PTR:
+ if (ptr != NULL) {
+ pptr = (char **)ptr;
+ *pptr = (char *)b;
+ }
+ 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)b->length;
+ break;
+ case BIO_CTRL_FLUSH:
+ ret = 1;
+ break;
+ default:
+ ret = 0;
+ break;
+ }
+ return ret;
+}
+
+static const BIO_METHOD mem_method = {
+ BIO_TYPE_MEM, "memory buffer", mem_write, mem_read, mem_puts,
+ mem_gets, mem_ctrl, mem_new, mem_free, NULL, };
+
+const BIO_METHOD *BIO_s_mem(void) { return &mem_method; }
+
+int BIO_mem_contents(const BIO *bio, const uint8_t **out_contents,
+ size_t *out_len) {
+ const BUF_MEM *b;
+ if (bio->method != &mem_method) {
+ return 0;
+ }
+
+ b = (BUF_MEM *)bio->ptr;
+ *out_contents = (uint8_t *)b->data;
+ *out_len = b->length;
+ return 1;
+}
+
+long BIO_get_mem_data(BIO *bio, char **contents) {
+ return BIO_ctrl(bio, BIO_CTRL_INFO, 0, (char *) contents);
+}
+
+int BIO_get_mem_ptr(BIO *bio, BUF_MEM **out) {
+ return BIO_ctrl(bio, BIO_C_GET_BUF_MEM_PTR, 0, (char *) out);
+}
+
+int BIO_set_mem_buf(BIO *bio, BUF_MEM *b, int take_ownership) {
+ return BIO_ctrl(bio, BIO_C_SET_BUF_MEM, take_ownership, (char *) b);
+}
+
+int BIO_set_mem_eof_return(BIO *bio, int eof_value) {
+ return BIO_ctrl(bio, BIO_C_SET_BUF_MEM_EOF_RETURN, eof_value, NULL);
+}
diff --git a/src/crypto/bio/bio_test.c b/src/crypto/bio/bio_test.c
new file mode 100644
index 0000000..cad4cf3
--- /dev/null
+++ b/src/crypto/bio/bio_test.c
@@ -0,0 +1,362 @@
+/* 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. */
+
+#if !defined(_POSIX_C_SOURCE)
+#define _POSIX_C_SOURCE 201410L
+#endif
+
+#include <openssl/base.h>
+
+#if !defined(OPENSSL_WINDOWS)
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#else
+#include <io.h>
+#pragma warning(push, 3)
+#include <WinSock2.h>
+#include <WS2tcpip.h>
+#pragma warning(pop)
+#endif
+
+#include <openssl/bio.h>
+#include <openssl/crypto.h>
+#include <openssl/err.h>
+
+#define MIN(a, b) ((a < b) ? a : b)
+
+#if !defined(OPENSSL_WINDOWS)
+static int closesocket(int sock) {
+ return close(sock);
+}
+
+static void print_socket_error(const char *func) {
+ perror(func);
+}
+#else
+static void print_socket_error(const char *func) {
+ fprintf(stderr, "%s: %d\n", func, WSAGetLastError());
+}
+#endif
+
+static int test_socket_connect(void) {
+ int listening_sock = socket(AF_INET, SOCK_STREAM, 0);
+ int sock;
+ struct sockaddr_in sin;
+ socklen_t sockaddr_len = sizeof(sin);
+ static const char kTestMessage[] = "test";
+ char hostname[80], buf[5];
+ BIO *bio;
+
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ if (!inet_pton(AF_INET, "127.0.0.1", &sin.sin_addr)) {
+ print_socket_error("inet_pton");
+ return 0;
+ }
+
+ if (bind(listening_sock, (struct sockaddr *)&sin, sizeof(sin)) != 0) {
+ print_socket_error("bind");
+ return 0;
+ }
+
+ if (listen(listening_sock, 1)) {
+ print_socket_error("listen");
+ return 0;
+ }
+
+ if (getsockname(listening_sock, (struct sockaddr *)&sin, &sockaddr_len) ||
+ sockaddr_len != sizeof(sin)) {
+ print_socket_error("getsockname");
+ return 0;
+ }
+
+ BIO_snprintf(hostname, sizeof(hostname), "%s:%d", "127.0.0.1",
+ ntohs(sin.sin_port));
+ bio = BIO_new_connect(hostname);
+ if (!bio) {
+ fprintf(stderr, "BIO_new_connect failed.\n");
+ return 0;
+ }
+
+ if (BIO_write(bio, kTestMessage, sizeof(kTestMessage)) !=
+ sizeof(kTestMessage)) {
+ fprintf(stderr, "BIO_write failed.\n");
+ BIO_print_errors_fp(stderr);
+ return 0;
+ }
+
+ sock = accept(listening_sock, (struct sockaddr *) &sin, &sockaddr_len);
+ if (sock < 0) {
+ print_socket_error("accept");
+ return 0;
+ }
+
+ if (recv(sock, buf, sizeof(buf), 0) != sizeof(kTestMessage)) {
+ print_socket_error("read");
+ return 0;
+ }
+
+ if (memcmp(buf, kTestMessage, sizeof(kTestMessage))) {
+ return 0;
+ }
+
+ closesocket(sock);
+ closesocket(listening_sock);
+ BIO_free(bio);
+
+ return 1;
+}
+
+
+/* bio_read_zero_copy_wrapper is a wrapper around the zero-copy APIs to make
+ * testing easier. */
+static size_t bio_read_zero_copy_wrapper(BIO *bio, uint8_t *data, size_t len) {
+ uint8_t *read_buf;
+ size_t read_buf_offset;
+ size_t available_bytes;
+ size_t len_read = 0;
+
+ do {
+ if (!BIO_zero_copy_get_read_buf(bio, &read_buf, &read_buf_offset,
+ &available_bytes)) {
+ return 0;
+ }
+
+ available_bytes = MIN(available_bytes, len - len_read);
+ memmove(data + len_read, read_buf + read_buf_offset, available_bytes);
+
+ BIO_zero_copy_get_read_buf_done(bio, available_bytes);
+
+ len_read += available_bytes;
+ } while (len - len_read > 0 && available_bytes > 0);
+
+ return len_read;
+}
+
+/* bio_write_zero_copy_wrapper is a wrapper around the zero-copy APIs to make
+ * testing easier. */
+static size_t bio_write_zero_copy_wrapper(BIO *bio, const uint8_t *data,
+ size_t len) {
+ uint8_t *write_buf;
+ size_t write_buf_offset;
+ size_t available_bytes;
+ size_t len_written = 0;
+
+ do {
+ if (!BIO_zero_copy_get_write_buf(bio, &write_buf, &write_buf_offset,
+ &available_bytes)) {
+ return 0;
+ }
+
+ available_bytes = MIN(available_bytes, len - len_written);
+ memmove(write_buf + write_buf_offset, data + len_written, available_bytes);
+
+ BIO_zero_copy_get_write_buf_done(bio, available_bytes);
+
+ len_written += available_bytes;
+ } while (len - len_written > 0 && available_bytes > 0);
+
+ return len_written;
+}
+
+static int test_zero_copy_bio_pairs(void) {
+ /* Test read and write, especially triggering the ring buffer wrap-around.*/
+ BIO* bio1;
+ BIO* bio2;
+ size_t i, j;
+ uint8_t bio1_application_send_buffer[1024];
+ uint8_t bio2_application_recv_buffer[1024];
+ size_t total_read = 0;
+ size_t total_write = 0;
+ uint8_t* write_buf;
+ size_t write_buf_offset;
+ size_t available_bytes;
+ size_t bytes_left;
+
+ const size_t kLengths[] = {254, 255, 256, 257, 510, 511, 512, 513};
+
+ /* These trigger ring buffer wrap around. */
+ const size_t kPartialLengths[] = {0, 1, 2, 3, 128, 255, 256, 257, 511, 512};
+
+ static const size_t kBufferSize = 512;
+
+ srand(1);
+ for (i = 0; i < sizeof(bio1_application_send_buffer); i++) {
+ bio1_application_send_buffer[i] = rand() & 255;
+ }
+
+ /* Transfer bytes from bio1_application_send_buffer to
+ * bio2_application_recv_buffer in various ways. */
+ for (i = 0; i < sizeof(kLengths) / sizeof(kLengths[0]); i++) {
+ for (j = 0; j < sizeof(kPartialLengths) / sizeof(kPartialLengths[0]); j++) {
+ total_write = 0;
+ total_read = 0;
+
+ BIO_new_bio_pair(&bio1, kBufferSize, &bio2, kBufferSize);
+
+ total_write += bio_write_zero_copy_wrapper(
+ bio1, bio1_application_send_buffer, kLengths[i]);
+
+ /* This tests interleaved read/write calls. Do a read between zero copy
+ * write calls. */
+ if (!BIO_zero_copy_get_write_buf(bio1, &write_buf, &write_buf_offset,
+ &available_bytes)) {
+ return 0;
+ }
+
+ /* Free kPartialLengths[j] bytes in the beginning of bio1 write buffer.
+ * This enables ring buffer wrap around for the next write. */
+ total_read += BIO_read(bio2, bio2_application_recv_buffer + total_read,
+ kPartialLengths[j]);
+
+ size_t interleaved_write_len = MIN(kPartialLengths[j], available_bytes);
+
+ /* Write the data for the interleaved write call. If the buffer becomes
+ * empty after a read, the write offset is normally set to 0. Check that
+ * this does not happen for interleaved read/write and that
+ * |write_buf_offset| is still valid. */
+ memcpy(write_buf + write_buf_offset,
+ bio1_application_send_buffer + total_write, interleaved_write_len);
+ if (BIO_zero_copy_get_write_buf_done(bio1, interleaved_write_len)) {
+ total_write += interleaved_write_len;
+ }
+
+ /* Do another write in case |write_buf_offset| was wrapped */
+ total_write += bio_write_zero_copy_wrapper(
+ bio1, bio1_application_send_buffer + total_write,
+ kPartialLengths[j] - interleaved_write_len);
+
+ /* Drain the rest. */
+ bytes_left = BIO_pending(bio2);
+ total_read += bio_read_zero_copy_wrapper(
+ bio2, bio2_application_recv_buffer + total_read, bytes_left);
+
+ BIO_free(bio1);
+ BIO_free(bio2);
+
+ if (total_read != total_write) {
+ fprintf(stderr, "Lengths not equal in round (%u, %u)\n", (unsigned)i,
+ (unsigned)j);
+ return 0;
+ }
+ if (total_read > kLengths[i] + kPartialLengths[j]) {
+ fprintf(stderr, "Bad lengths in round (%u, %u)\n", (unsigned)i,
+ (unsigned)j);
+ return 0;
+ }
+ if (memcmp(bio1_application_send_buffer, bio2_application_recv_buffer,
+ total_read) != 0) {
+ fprintf(stderr, "Buffers not equal in round (%u, %u)\n", (unsigned)i,
+ (unsigned)j);
+ return 0;
+ }
+ }
+ }
+
+ return 1;
+}
+
+static int test_printf(void) {
+ /* Test a short output, a very long one, and various sizes around
+ * 256 (the size of the buffer) to ensure edge cases are correct. */
+ static const size_t kLengths[] = { 5, 250, 251, 252, 253, 254, 1023 };
+ BIO *bio;
+ char string[1024];
+ int ret;
+ const uint8_t *contents;
+ size_t i, len;
+
+ bio = BIO_new(BIO_s_mem());
+ if (!bio) {
+ fprintf(stderr, "BIO_new failed\n");
+ return 0;
+ }
+
+ for (i = 0; i < sizeof(kLengths) / sizeof(kLengths[0]); i++) {
+ if (kLengths[i] >= sizeof(string)) {
+ fprintf(stderr, "Bad test string length\n");
+ return 0;
+ }
+ memset(string, 'a', sizeof(string));
+ string[kLengths[i]] = '\0';
+
+ ret = BIO_printf(bio, "test %s", string);
+ if (ret != 5 + kLengths[i]) {
+ fprintf(stderr, "BIO_printf failed: %d\n", ret);
+ return 0;
+ }
+ if (!BIO_mem_contents(bio, &contents, &len)) {
+ fprintf(stderr, "BIO_mem_contents failed\n");
+ return 0;
+ }
+ if (len != 5 + kLengths[i] ||
+ strncmp((const char *)contents, "test ", 5) != 0 ||
+ strncmp((const char *)contents + 5, string, kLengths[i]) != 0) {
+ fprintf(stderr, "Contents did not match: %.*s\n", (int)len, contents);
+ return 0;
+ }
+
+ if (!BIO_reset(bio)) {
+ fprintf(stderr, "BIO_reset failed\n");
+ return 0;
+ }
+ }
+
+ BIO_free(bio);
+ return 1;
+}
+
+int main(void) {
+#if defined(OPENSSL_WINDOWS)
+ WSADATA wsa_data;
+ WORD wsa_version;
+ int wsa_err;
+#endif
+
+ CRYPTO_library_init();
+ ERR_load_crypto_strings();
+
+#if defined(OPENSSL_WINDOWS)
+ /* Initialize Winsock. */
+ wsa_version = MAKEWORD(2, 2);
+ wsa_err = WSAStartup(wsa_version, &wsa_data);
+ if (wsa_err != 0) {
+ fprintf(stderr, "WSAStartup failed: %d\n", wsa_err);
+ return 1;
+ }
+ if (wsa_data.wVersion != wsa_version) {
+ fprintf(stderr, "Didn't get expected version: %x\n", wsa_data.wVersion);
+ return 1;
+ }
+#endif
+
+ if (!test_socket_connect()) {
+ return 1;
+ }
+
+ if (!test_printf()) {
+ return 1;
+ }
+
+ if (!test_zero_copy_bio_pairs()) {
+ return 1;
+ }
+
+ printf("PASS\n");
+ return 0;
+}
diff --git a/src/crypto/bio/buffer.c b/src/crypto/bio/buffer.c
new file mode 100644
index 0000000..5e423a1
--- /dev/null
+++ b/src/crypto/bio/buffer.c
@@ -0,0 +1,499 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/bio.h>
+
+#include <string.h>
+
+#include <openssl/buf.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+
+
+#define DEFAULT_BUFFER_SIZE 4096
+
+typedef struct bio_f_buffer_ctx_struct {
+ /* Buffers are setup like this:
+ *
+ * <---------------------- size ----------------------->
+ * +---------------------------------------------------+
+ * | consumed | remaining | free space |
+ * +---------------------------------------------------+
+ * <-- off --><------- len ------->
+ */
+
+ 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;
+
+static int buffer_new(BIO *bio) {
+ BIO_F_BUFFER_CTX *ctx;
+
+ ctx = OPENSSL_malloc(sizeof(BIO_F_BUFFER_CTX));
+ if (ctx == NULL) {
+ return 0;
+ }
+ memset(ctx, 0, sizeof(BIO_F_BUFFER_CTX));
+
+ ctx->ibuf = OPENSSL_malloc(DEFAULT_BUFFER_SIZE);
+ if (ctx->ibuf == NULL) {
+ goto err1;
+ }
+ ctx->obuf = (char *)OPENSSL_malloc(DEFAULT_BUFFER_SIZE);
+ if (ctx->obuf == NULL) {
+ goto err2;
+ }
+ ctx->ibuf_size = DEFAULT_BUFFER_SIZE;
+ ctx->obuf_size = DEFAULT_BUFFER_SIZE;
+
+ bio->init = 1;
+ bio->ptr = (char *)ctx;
+ return 1;
+
+err2:
+ OPENSSL_free(ctx->ibuf);
+
+err1:
+ OPENSSL_free(ctx);
+ return 0;
+}
+
+static int buffer_free(BIO *bio) {
+ BIO_F_BUFFER_CTX *ctx;
+
+ if (bio == NULL) {
+ return 0;
+ }
+
+ ctx = (BIO_F_BUFFER_CTX *)bio->ptr;
+ if (ctx->ibuf != NULL) {
+ OPENSSL_free(ctx->ibuf);
+ }
+ if (ctx->obuf != NULL) {
+ OPENSSL_free(ctx->obuf);
+ }
+ OPENSSL_free(bio->ptr);
+
+ bio->ptr = NULL;
+ bio->init = 0;
+ bio->flags = 0;
+
+ return 1;
+}
+
+static int buffer_read(BIO *bio, char *out, int outl) {
+ int i, num = 0;
+ BIO_F_BUFFER_CTX *ctx;
+
+ ctx = (BIO_F_BUFFER_CTX *)bio->ptr;
+
+ if (ctx == NULL || bio->next_bio == NULL) {
+ return 0;
+ }
+
+ num = 0;
+ BIO_clear_retry_flags(bio);
+
+ for (;;) {
+ 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(bio->next_bio, out, outl);
+ if (i <= 0) {
+ BIO_copy_next_retry(bio);
+ if (i < 0) {
+ return (num > 0) ? num : i;
+ }
+ 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(bio->next_bio, ctx->ibuf, ctx->ibuf_size);
+ if (i <= 0) {
+ BIO_copy_next_retry(bio);
+ if (i < 0) {
+ return (num > 0) ? num : i;
+ }
+ return num;
+ }
+ ctx->ibuf_off = 0;
+ ctx->ibuf_len = i;
+ }
+}
+
+static int buffer_write(BIO *b, const char *in, int inl) {
+ int i, num = 0;
+ BIO_F_BUFFER_CTX *ctx;
+
+ ctx = (BIO_F_BUFFER_CTX *)b->ptr;
+ if (ctx == NULL || b->next_bio == NULL) {
+ return 0;
+ }
+
+ BIO_clear_retry_flags(b);
+
+ for (;;) {
+ i = ctx->obuf_size - (ctx->obuf_off + ctx->obuf_len);
+ /* 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) {
+ 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;
+ }
+ 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;
+ }
+ 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 */
+ }
+}
+
+static long buffer_ctrl(BIO *b, int cmd, long num, void *ptr) {
+ BIO_F_BUFFER_CTX *ctx;
+ long ret = 1;
+ char *p1, *p2;
+ int r, *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 = ctx->obuf_len;
+ 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_SIZE:
+ ip = (int *)ptr;
+ if (*ip == 0) {
+ ibs = (int)num;
+ obs = ctx->obuf_size;
+ } else /* if (*ip == 1) */ {
+ ibs = ctx->ibuf_size;
+ obs = (int)num;
+ }
+ p1 = ctx->ibuf;
+ p2 = ctx->obuf;
+ if (ibs > DEFAULT_BUFFER_SIZE && ibs != ctx->ibuf_size) {
+ p1 = (char *)OPENSSL_malloc(ibs);
+ if (p1 == NULL) {
+ goto malloc_error;
+ }
+ }
+ if (obs > DEFAULT_BUFFER_SIZE && obs != ctx->obuf_size) {
+ p2 = (char *)OPENSSL_malloc(obs);
+ if (p2 == NULL) {
+ if (p1 != ctx->ibuf) {
+ OPENSSL_free(p1);
+ }
+ goto malloc_error;
+ }
+ }
+
+ if (ctx->ibuf != p1) {
+ OPENSSL_free(ctx->ibuf);
+ ctx->ibuf = p1;
+ ctx->ibuf_size = ibs;
+ }
+ ctx->ibuf_off = 0;
+ ctx->ibuf_len = 0;
+
+ if (ctx->obuf != p2) {
+ OPENSSL_free(ctx->obuf);
+ ctx->obuf = p2;
+ ctx->obuf_size = obs;
+ }
+ ctx->obuf_off = 0;
+ ctx->obuf_len = 0;
+ break;
+
+ case BIO_CTRL_FLUSH:
+ if (b->next_bio == NULL) {
+ return 0;
+ }
+
+ while (ctx->obuf_len > 0) {
+ BIO_clear_retry_flags(b);
+ r = BIO_write(b->next_bio, &(ctx->obuf[ctx->obuf_off]),
+ ctx->obuf_len);
+ BIO_copy_next_retry(b);
+ if (r <= 0) {
+ return r;
+ }
+ ctx->obuf_off += r;
+ ctx->obuf_len -= r;
+ }
+
+ ctx->obuf_len = 0;
+ ctx->obuf_off = 0;
+ ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
+ break;
+
+ default:
+ 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;
+ }
+ return ret;
+
+malloc_error:
+ OPENSSL_PUT_ERROR(BIO, buffer_ctrl, 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;
+ if (buf == NULL || size <= 0) {
+ return 0;
+ }
+
+ 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;
+ }
+ 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));
+}
+
+static const BIO_METHOD methods_buffer = {
+ BIO_TYPE_BUFFER, "buffer", buffer_write, buffer_read,
+ buffer_puts, buffer_gets, buffer_ctrl, buffer_new,
+ buffer_free, buffer_callback_ctrl,
+};
+
+const BIO_METHOD *BIO_f_buffer(void) { return &methods_buffer; }
+
+int BIO_set_read_buffer_size(BIO *bio, int buffer_size) {
+ return BIO_int_ctrl(bio, BIO_C_SET_BUFF_SIZE, buffer_size, 0);
+}
+
+int BIO_set_write_buffer_size(BIO *bio, int buffer_size) {
+ return BIO_int_ctrl(bio, BIO_C_SET_BUFF_SIZE, buffer_size, 1);
+}
diff --git a/src/crypto/bio/connect.c b/src/crypto/bio/connect.c
new file mode 100644
index 0000000..66ac3a7
--- /dev/null
+++ b/src/crypto/bio/connect.c
@@ -0,0 +1,541 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/bio.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#if !defined(OPENSSL_WINDOWS)
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#else
+#pragma warning(push, 3)
+#include <WinSock2.h>
+#include <WS2tcpip.h>
+#pragma warning(pop)
+#endif
+
+#include <openssl/buf.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+
+#include "internal.h"
+
+
+enum {
+ BIO_CONN_S_BEFORE,
+ BIO_CONN_S_BLOCKED_CONNECT,
+ BIO_CONN_S_OK,
+};
+
+typedef struct bio_connect_st {
+ int state;
+
+ char *param_hostname;
+ char *param_port;
+ int nbio;
+
+ uint8_t ip[4];
+ unsigned short port;
+
+ struct sockaddr_storage them;
+ socklen_t them_length;
+
+ /* the file descriptor is kept in bio->num in order to match the socket
+ * BIO. */
+
+ /* info_callback is 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. */
+ int (*info_callback)(const BIO *bio, int state, int ret);
+} BIO_CONNECT;
+
+#if !defined(OPENSSL_WINDOWS)
+static int closesocket(int sock) {
+ return close(sock);
+}
+#endif
+
+/* maybe_copy_ipv4_address sets |*ipv4| to the IPv4 address from |ss| (in
+ * big-endian order), if |ss| contains an IPv4 socket address. */
+static void maybe_copy_ipv4_address(uint8_t *ipv4,
+ const struct sockaddr_storage *ss) {
+ const struct sockaddr_in *sin;
+
+ if (ss->ss_family != AF_INET) {
+ return;
+ }
+
+ sin = (const struct sockaddr_in*) ss;
+ memcpy(ipv4, &sin->sin_addr, 4);
+}
+
+static int conn_state(BIO *bio, BIO_CONNECT *c) {
+ int ret = -1, i;
+ char *p, *q;
+ int (*cb)(const BIO *, int, int) = 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) {
+ OPENSSL_PUT_ERROR(BIO, conn_state, 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;
+ }
+ }
+ if (c->param_port != NULL) {
+ OPENSSL_free(c->param_port);
+ }
+ c->param_port = BUF_strdup(p);
+ }
+ }
+
+ if (c->param_port == NULL) {
+ OPENSSL_PUT_ERROR(BIO, conn_state, BIO_R_NO_PORT_SPECIFIED);
+ ERR_add_error_data(2, "host=", c->param_hostname);
+ goto exit_loop;
+ }
+
+ if (!bio_ip_and_port_to_socket_and_addr(
+ &bio->num, &c->them, &c->them_length, c->param_hostname,
+ c->param_port)) {
+ OPENSSL_PUT_ERROR(BIO, conn_state, BIO_R_UNABLE_TO_CREATE_SOCKET);
+ ERR_add_error_data(4, "host=", c->param_hostname, ":", c->param_port);
+ goto exit_loop;
+ }
+
+ memset(c->ip, 0, 4);
+ maybe_copy_ipv4_address(c->ip, &c->them);
+
+ if (c->nbio) {
+ if (!bio_socket_nbio(bio->num, 1)) {
+ OPENSSL_PUT_ERROR(BIO, conn_state, BIO_R_ERROR_SETTING_NBIO);
+ ERR_add_error_data(4, "host=", c->param_hostname, ":",
+ c->param_port);
+ goto exit_loop;
+ }
+ }
+
+ i = 1;
+ ret = setsockopt(bio->num, SOL_SOCKET, SO_KEEPALIVE, (char *)&i,
+ sizeof(i));
+ if (ret < 0) {
+ OPENSSL_PUT_SYSTEM_ERROR(setsockopt);
+ OPENSSL_PUT_ERROR(BIO, conn_state, BIO_R_KEEPALIVE);
+ ERR_add_error_data(4, "host=", c->param_hostname, ":", c->param_port);
+ goto exit_loop;
+ }
+
+ BIO_clear_retry_flags(bio);
+ ret = connect(bio->num, (struct sockaddr*) &c->them, c->them_length);
+ if (ret < 0) {
+ if (bio_fd_should_retry(ret)) {
+ BIO_set_flags(bio, (BIO_FLAGS_IO_SPECIAL | BIO_FLAGS_SHOULD_RETRY));
+ c->state = BIO_CONN_S_BLOCKED_CONNECT;
+ bio->retry_reason = BIO_RR_CONNECT;
+ } else {
+ OPENSSL_PUT_SYSTEM_ERROR(connect);
+ OPENSSL_PUT_ERROR(BIO, conn_state, BIO_R_CONNECT_ERROR);
+ ERR_add_error_data(4, "host=", c->param_hostname, ":",
+ c->param_port);
+ }
+ goto exit_loop;
+ } else {
+ c->state = BIO_CONN_S_OK;
+ }
+ break;
+
+ case BIO_CONN_S_BLOCKED_CONNECT:
+ i = bio_sock_error(bio->num);
+ if (i) {
+ if (bio_fd_should_retry(ret)) {
+ BIO_set_flags(bio, (BIO_FLAGS_IO_SPECIAL | BIO_FLAGS_SHOULD_RETRY));
+ c->state = BIO_CONN_S_BLOCKED_CONNECT;
+ bio->retry_reason = BIO_RR_CONNECT;
+ ret = -1;
+ } else {
+ BIO_clear_retry_flags(bio);
+ OPENSSL_PUT_SYSTEM_ERROR(connect);
+ OPENSSL_PUT_ERROR(BIO, conn_state, BIO_R_NBIO_CONNECT_ERROR);
+ ERR_add_error_data(4, "host=", c->param_hostname, ":", c->param_port);
+ ret = 0;
+ }
+ goto exit_loop;
+ } else {
+ c->state = BIO_CONN_S_OK;
+ }
+ break;
+
+ case BIO_CONN_S_OK:
+ ret = 1;
+ goto exit_loop;
+ default:
+ assert(0);
+ goto exit_loop;
+ }
+
+ if (cb != NULL) {
+ ret = cb((BIO *)bio, c->state, ret);
+ if (ret == 0) {
+ goto end;
+ }
+ }
+ }
+
+exit_loop:
+ if (cb != NULL) {
+ ret = cb((BIO *)bio, c->state, ret);
+ }
+
+end:
+ return ret;
+}
+
+static BIO_CONNECT *BIO_CONNECT_new(void) {
+ BIO_CONNECT *ret = OPENSSL_malloc(sizeof(BIO_CONNECT));
+
+ if (ret == NULL) {
+ return NULL;
+ }
+ memset(ret, 0, sizeof(BIO_CONNECT));
+
+ ret->state = BIO_CONN_S_BEFORE;
+ return ret;
+}
+
+static void BIO_CONNECT_free(BIO_CONNECT *c) {
+ if (c == NULL) {
+ return;
+ }
+
+ if (c->param_hostname != NULL) {
+ OPENSSL_free(c->param_hostname);
+ }
+ if (c->param_port != NULL) {
+ OPENSSL_free(c->param_port);
+ }
+ OPENSSL_free(c);
+}
+
+static int conn_new(BIO *bio) {
+ bio->init = 0;
+ bio->num = -1;
+ bio->flags = 0;
+ bio->ptr = (char *)BIO_CONNECT_new();
+ return bio->ptr != NULL;
+}
+
+static void conn_close_socket(BIO *bio) {
+ BIO_CONNECT *c = (BIO_CONNECT *) bio->ptr;
+
+ if (bio->num == -1) {
+ return;
+ }
+
+ /* Only do a shutdown if things were established */
+ if (c->state == BIO_CONN_S_OK) {
+ shutdown(bio->num, 2);
+ }
+ closesocket(bio->num);
+ bio->num = -1;
+}
+
+static int conn_free(BIO *bio) {
+ if (bio == NULL) {
+ return 0;
+ }
+
+ if (bio->shutdown) {
+ conn_close_socket(bio);
+ }
+
+ BIO_CONNECT_free((BIO_CONNECT*) bio->ptr);
+
+ return 1;
+}
+
+static int conn_read(BIO *bio, char *out, int out_len) {
+ int ret = 0;
+ BIO_CONNECT *data;
+
+ data = (BIO_CONNECT *)bio->ptr;
+ if (data->state != BIO_CONN_S_OK) {
+ ret = conn_state(bio, data);
+ if (ret <= 0) {
+ return ret;
+ }
+ }
+
+ bio_clear_socket_error();
+ ret = recv(bio->num, out, out_len, 0);
+ BIO_clear_retry_flags(bio);
+ if (ret <= 0) {
+ if (bio_fd_should_retry(ret)) {
+ BIO_set_retry_read(bio);
+ }
+ }
+
+ return ret;
+}
+
+static int conn_write(BIO *bio, const char *in, int in_len) {
+ int ret;
+ BIO_CONNECT *data;
+
+ data = (BIO_CONNECT *)bio->ptr;
+ if (data->state != BIO_CONN_S_OK) {
+ ret = conn_state(bio, data);
+ if (ret <= 0) {
+ return ret;
+ }
+ }
+
+ bio_clear_socket_error();
+ ret = send(bio->num, in, in_len, 0);
+ BIO_clear_retry_flags(bio);
+ if (ret <= 0) {
+ if (bio_fd_should_retry(ret)) {
+ BIO_set_retry_write(bio);
+ }
+ }
+
+ return ret;
+}
+
+static long conn_ctrl(BIO *bio, int cmd, long num, void *ptr) {
+ int *ip;
+ const char **pptr;
+ long ret = 1;
+ BIO_CONNECT *data;
+
+ data = (BIO_CONNECT *)bio->ptr;
+
+ switch (cmd) {
+ case BIO_CTRL_RESET:
+ ret = 0;
+ data->state = BIO_CONN_S_BEFORE;
+ conn_close_socket(bio);
+ bio->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(bio, data);
+ else
+ ret = 1;
+ break;
+ case BIO_C_GET_CONNECT:
+ /* TODO(fork): can this be removed? (Or maybe this whole file). */
+ 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 (!bio->init) {
+ *pptr = "not initialized";
+ }
+ ret = 1;
+ }
+ break;
+ case BIO_C_SET_CONNECT:
+ if (ptr != NULL) {
+ bio->init = 1;
+ if (num == 0) {
+ if (data->param_hostname != NULL) {
+ OPENSSL_free(data->param_hostname);
+ }
+ data->param_hostname = BUF_strdup(ptr);
+ } else if (num == 1) {
+ if (data->param_port != NULL) {
+ OPENSSL_free(data->param_port);
+ }
+ data->param_port = BUF_strdup(ptr);
+ } else {
+ ret = 0;
+ }
+ }
+ break;
+ case BIO_C_SET_NBIO:
+ data->nbio = (int)num;
+ break;
+ case BIO_C_GET_FD:
+ if (bio->init) {
+ ip = (int *)ptr;
+ if (ip != NULL) {
+ *ip = bio->num;
+ }
+ ret = 1;
+ } else {
+ ret = 0;
+ }
+ break;
+ case BIO_CTRL_GET_CLOSE:
+ ret = bio->shutdown;
+ break;
+ case BIO_CTRL_SET_CLOSE:
+ bio->shutdown = (int)num;
+ break;
+ case BIO_CTRL_PENDING:
+ case BIO_CTRL_WPENDING:
+ ret = 0;
+ break;
+ case BIO_CTRL_FLUSH:
+ break;
+ case BIO_CTRL_SET_CALLBACK: {
+#if 0 /* FIXME: Should this be used? -- Richard Levitte */
+ OPENSSL_PUT_ERROR(BIO, XXX, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ ret = -1;
+#else
+ ret = 0;
+#endif
+ } break;
+ case BIO_CTRL_GET_CALLBACK: {
+ int (**fptr)(const BIO *bio, int state, int xret);
+ fptr = (int (**)(const BIO *bio, int state, int xret))ptr;
+ *fptr = data->info_callback;
+ } break;
+ default:
+ ret = 0;
+ break;
+ }
+ return (ret);
+}
+
+static long conn_callback_ctrl(BIO *bio, int cmd, bio_info_cb fp) {
+ long ret = 1;
+ BIO_CONNECT *data;
+
+ data = (BIO_CONNECT *)bio->ptr;
+
+ switch (cmd) {
+ case BIO_CTRL_SET_CALLBACK: {
+ data->info_callback = (int (*)(const struct bio_st *, int, int))fp;
+ } break;
+ default:
+ ret = 0;
+ break;
+ }
+ return ret;
+}
+
+static int conn_puts(BIO *bp, const char *str) {
+ return conn_write(bp, str, strlen(str));
+}
+
+BIO *BIO_new_connect(const char *hostname) {
+ BIO *ret;
+
+ ret = BIO_new(BIO_s_connect());
+ if (ret == NULL) {
+ return NULL;
+ }
+ if (!BIO_set_conn_hostname(ret, hostname)) {
+ BIO_free(ret);
+ return NULL;
+ }
+ return ret;
+}
+
+static const BIO_METHOD methods_connectp = {
+ BIO_TYPE_CONNECT, "socket connect", conn_write, conn_read,
+ conn_puts, NULL /* connect_gets, */, conn_ctrl, conn_new,
+ conn_free, conn_callback_ctrl,
+};
+
+const BIO_METHOD *BIO_s_connect(void) { return &methods_connectp; }
+
+int BIO_set_conn_hostname(BIO *bio, const char *name) {
+ return BIO_ctrl(bio, BIO_C_SET_CONNECT, 0, (void*) name);
+}
+
+int BIO_set_conn_port(BIO *bio, const char *port_str) {
+ return BIO_ctrl(bio, BIO_C_SET_CONNECT, 1, (void*) port_str);
+}
+
+int BIO_set_nbio(BIO *bio, int on) {
+ return BIO_ctrl(bio, BIO_C_SET_NBIO, on, NULL);
+}
diff --git a/src/crypto/bio/fd.c b/src/crypto/bio/fd.c
new file mode 100644
index 0000000..6b70eac
--- /dev/null
+++ b/src/crypto/bio/fd.c
@@ -0,0 +1,270 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/bio.h>
+
+#include <errno.h>
+#include <string.h>
+
+#if !defined(OPENSSL_WINDOWS)
+#include <unistd.h>
+#else
+#include <io.h>
+#pragma warning(push, 3)
+#include <Windows.h>
+#pragma warning(pop)
+#endif
+
+#include <openssl/buf.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+
+
+static int bio_fd_non_fatal_error(int err) {
+ if (
+#ifdef EWOULDBLOCK
+ err == EWOULDBLOCK ||
+#endif
+#ifdef WSAEWOULDBLOCK
+ err == WSAEWOULDBLOCK ||
+#endif
+#ifdef ENOTCONN
+ err == ENOTCONN ||
+#endif
+#ifdef EINTR
+ err == EINTR ||
+#endif
+#ifdef EAGAIN
+ err == EAGAIN ||
+#endif
+#ifdef EPROTO
+ err == EPROTO ||
+#endif
+#ifdef EINPROGRESS
+ err == EINPROGRESS ||
+#endif
+#ifdef EALREADY
+ err == EALREADY ||
+#endif
+ 0) {
+ return 1;
+ }
+ return 0;
+}
+
+#if defined(OPENSSL_WINDOWS)
+int bio_fd_should_retry(int i) {
+ if (i == -1) {
+ return bio_fd_non_fatal_error((int)GetLastError());
+ }
+ return 0;
+}
+#else
+int bio_fd_should_retry(int i) {
+ if (i == -1) {
+ return bio_fd_non_fatal_error(errno);
+ }
+ return 0;
+}
+#endif
+
+BIO *BIO_new_fd(int fd, int close_flag) {
+ BIO *ret = BIO_new(BIO_s_fd());
+ if (ret == NULL) {
+ return NULL;
+ }
+ BIO_set_fd(ret, fd, close_flag);
+ return ret;
+}
+
+static int fd_new(BIO *bio) {
+ /* num is used to store the file descriptor. */
+ bio->num = -1;
+ return 1;
+}
+
+static int fd_free(BIO *bio) {
+ if (bio == NULL) {
+ return 0;
+ }
+
+ if (bio->shutdown) {
+ if (bio->init) {
+ close(bio->num);
+ }
+ bio->init = 0;
+ }
+ return 1;
+}
+
+static int fd_read(BIO *b, char *out, int outl) {
+ int ret = 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 = 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 = 0;
+ if (b->init) {
+ ret = (long)lseek(b->num, num, SEEK_SET);
+ }
+ break;
+ case BIO_C_FILE_TELL:
+ case BIO_CTRL_INFO:
+ ret = 0;
+ if (b->init) {
+ ret = (long)lseek(b->num, 0, SEEK_CUR);
+ }
+ 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;
+ }
+ return 1;
+ } 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_PENDING:
+ case BIO_CTRL_WPENDING:
+ ret = 0;
+ break;
+ case BIO_CTRL_FLUSH:
+ ret = 1;
+ break;
+ default:
+ ret = 0;
+ break;
+ }
+
+ return ret;
+}
+
+static int fd_puts(BIO *bp, const char *str) {
+ return fd_write(bp, str, strlen(str));
+}
+
+static int fd_gets(BIO *bp, char *buf, int size) {
+ char *ptr = buf;
+ char *end = buf + size - 1;
+
+ if (size <= 0) {
+ return 0;
+ }
+
+ while (ptr < end && fd_read(bp, ptr, 1) > 0 && ptr[0] != '\n') {
+ ptr++;
+ }
+
+ ptr[0] = '\0';
+
+ return ptr - buf;
+}
+
+static const BIO_METHOD methods_fdp = {
+ BIO_TYPE_FD, "file descriptor", fd_write, fd_read, fd_puts,
+ fd_gets, fd_ctrl, fd_new, fd_free, NULL, };
+
+const BIO_METHOD *BIO_s_fd(void) { return &methods_fdp; }
+
+int BIO_set_fd(BIO *bio, int fd, int close_flag) {
+ return BIO_int_ctrl(bio, BIO_C_SET_FD, close_flag, fd);
+}
+
+int BIO_get_fd(BIO *bio, int *out_fd) {
+ return BIO_ctrl(bio, BIO_C_GET_FD, 0, (char *) out_fd);
+}
diff --git a/src/crypto/bio/file.c b/src/crypto/bio/file.c
new file mode 100644
index 0000000..7f57aad
--- /dev/null
+++ b/src/crypto/bio/file.c
@@ -0,0 +1,350 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#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 <openssl/bio.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <openssl/buf.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+
+
+#define BIO_FP_READ 0x02
+#define BIO_FP_WRITE 0x04
+#define BIO_FP_APPEND 0x08
+
+static FILE *open_file(const char *filename, const char *mode) {
+#if defined(_WIN32) && defined(CP_UTF8)
+ int sz, len_0 = (int)strlen(filename) + 1;
+ DWORD flags;
+
+ /* Basically there are three cases to cover: a) filename is pure ASCII
+ * string; b) actual UTF-8 encoded string and c) locale-ized string, i.e. one
+ * containing 8-bit characters that are meaningful in current system locale.
+ * If filename is pure ASCII or real UTF-8 encoded string,
+ * MultiByteToWideChar succeeds and _wfopen works. If filename is locale-ized
+ * string, chances are that MultiByteToWideChar fails reporting
+ * ERROR_NO_UNICODE_TRANSLATION, in which case we fall back to fopen... */
+ if ((sz = MultiByteToWideChar(CP_UTF8, (flags = MB_ERR_INVALID_CHARS),
+ filename, len_0, NULL, 0)) > 0 ||
+ (GetLastError() == ERROR_INVALID_FLAGS &&
+ (sz = MultiByteToWideChar(CP_UTF8, (flags = 0), filename, len_0, NULL,
+ 0)) > 0)) {
+ WCHAR wmode[8];
+ WCHAR *wfilename = _alloca(sz * sizeof(WCHAR));
+
+ if (MultiByteToWideChar(CP_UTF8, flags, filename, len_0, wfilename, sz) &&
+ MultiByteToWideChar(CP_UTF8, 0, mode, strlen(mode) + 1, wmode,
+ sizeof(wmode) / sizeof(wmode[0])) &&
+ (file = _wfopen(wfilename, wmode)) == NULL &&
+ (errno == ENOENT ||
+ errno == EBADF)) /* UTF-8 decode succeeded, but no file, filename
+ * could still have been locale-ized... */
+ return fopen(filename, mode);
+ } else if (GetLastError() == ERROR_NO_UNICODE_TRANSLATION) {
+ return fopen(filename, mode);
+ }
+#else
+ return fopen(filename, mode);
+#endif
+}
+
+BIO *BIO_new_file(const char *filename, const char *mode) {
+ BIO *ret;
+ FILE *file;
+
+ file = open_file(filename, mode);
+ if (file == NULL) {
+ OPENSSL_PUT_SYSTEM_ERROR(fopen);
+
+ ERR_add_error_data(5, "fopen('", filename, "','", mode, "')");
+ if (errno == ENOENT) {
+ OPENSSL_PUT_ERROR(BIO, BIO_new_file, BIO_R_NO_SUCH_FILE);
+ } else {
+ OPENSSL_PUT_ERROR(BIO, BIO_new_file, BIO_R_SYS_LIB);
+ }
+ return NULL;
+ }
+
+ ret = BIO_new(BIO_s_file());
+ if (ret == NULL) {
+ fclose(file);
+ return NULL;
+ }
+
+ BIO_set_fp(ret, file, BIO_CLOSE);
+ return ret;
+}
+
+BIO *BIO_new_fp(FILE *stream, int close_flag) {
+ BIO *ret = BIO_new(BIO_s_file());
+
+ if (ret == NULL) {
+ return NULL;
+ }
+
+ BIO_set_fp(ret, stream, close_flag);
+ return ret;
+}
+
+static int file_new(BIO *bio) { return 1; }
+
+static int file_free(BIO *bio) {
+ if (bio == NULL) {
+ return 0;
+ }
+
+ if (!bio->shutdown) {
+ return 1;
+ }
+
+ if (bio->init && bio->ptr != NULL) {
+ fclose(bio->ptr);
+ bio->ptr = NULL;
+ }
+ bio->init = 0;
+
+ return 1;
+}
+
+static int file_read(BIO *b, char *out, int outl) {
+ int ret = 0;
+
+ if (!b->init) {
+ return 0;
+ }
+
+ ret = fread(out, 1, outl, (FILE *)b->ptr);
+ if (ret == 0 && ferror((FILE *)b->ptr)) {
+ OPENSSL_PUT_SYSTEM_ERROR(fread);
+ OPENSSL_PUT_ERROR(BIO, file_read, 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) {
+ return 0;
+ }
+
+ ret = fwrite(in, inl, 1, (FILE *)b->ptr);
+ if (ret > 0) {
+ ret = inl;
+ }
+ 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_CTRL_RESET:
+ num = 0;
+ case BIO_C_FILE_SEEK:
+ 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) {
+ BUF_strlcpy(p, "a+", sizeof(p));
+ } else {
+ BUF_strlcpy(p, "a", sizeof(p));
+ }
+ } else if ((num & BIO_FP_READ) && (num & BIO_FP_WRITE)) {
+ BUF_strlcpy(p, "r+", sizeof(p));
+ } else if (num & BIO_FP_WRITE) {
+ BUF_strlcpy(p, "w", sizeof(p));
+ } else if (num & BIO_FP_READ) {
+ BUF_strlcpy(p, "r", sizeof(p));
+ } else {
+ OPENSSL_PUT_ERROR(BIO, file_ctrl, BIO_R_BAD_FOPEN_MODE);
+ ret = 0;
+ break;
+ }
+ fp = open_file(ptr, p);
+ if (fp == NULL) {
+ OPENSSL_PUT_SYSTEM_ERROR(fopen);
+ ERR_add_error_data(5, "fopen('", ptr, "','", p, "')");
+ OPENSSL_PUT_ERROR(BIO, file_ctrl, 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:
+ ret = 0 == fflush((FILE *)b->ptr);
+ break;
+ case BIO_CTRL_WPENDING:
+ case BIO_CTRL_PENDING:
+ default:
+ ret = 0;
+ break;
+ }
+ return ret;
+}
+
+static int file_gets(BIO *bp, char *buf, int size) {
+ int ret = 0;
+
+ if (size == 0) {
+ return 0;
+ }
+
+ if (!fgets(buf, size, (FILE *)bp->ptr)) {
+ buf[0] = 0;
+ goto err;
+ }
+ ret = strlen(buf);
+
+err:
+ return ret;
+}
+
+static int file_puts(BIO *bp, const char *str) {
+ return file_write(bp, str, strlen(str));
+}
+
+static const BIO_METHOD methods_filep = {
+ BIO_TYPE_FILE, "FILE pointer", file_write, file_read, file_puts,
+ file_gets, file_ctrl, file_new, file_free, NULL, };
+
+const BIO_METHOD *BIO_s_file(void) { return &methods_filep; }
+
+
+int BIO_get_fp(BIO *bio, FILE **out_file) {
+ return BIO_ctrl(bio, BIO_C_GET_FILE_PTR, 0, (char*) out_file);
+}
+
+int BIO_set_fp(BIO *bio, FILE *file, int close_flag) {
+ return BIO_ctrl(bio, BIO_C_SET_FILE_PTR, close_flag, (char *) file);
+}
+
+int BIO_read_filename(BIO *bio, const char *filename) {
+ return BIO_ctrl(bio, BIO_C_SET_FILENAME, BIO_CLOSE | BIO_FP_READ,
+ (char *)filename);
+}
+
+int BIO_write_filename(BIO *bio, const char *filename) {
+ return BIO_ctrl(bio, BIO_C_SET_FILENAME, BIO_CLOSE | BIO_FP_WRITE,
+ (char *)filename);
+}
+
+int BIO_append_filename(BIO *bio, const char *filename) {
+ return BIO_ctrl(bio, BIO_C_SET_FILENAME, BIO_CLOSE | BIO_FP_APPEND,
+ (char *)filename);
+}
+
+int BIO_rw_filename(BIO *bio, const char *filename) {
+ return BIO_ctrl(bio, BIO_C_SET_FILENAME,
+ BIO_CLOSE | BIO_FP_READ | BIO_FP_WRITE, (char *)filename);
+}
diff --git a/src/crypto/bio/hexdump.c b/src/crypto/bio/hexdump.c
new file mode 100644
index 0000000..17f5518
--- /dev/null
+++ b/src/crypto/bio/hexdump.c
@@ -0,0 +1,192 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/bio.h>
+
+#include <limits.h>
+#include <string.h>
+
+
+/* hexdump_ctx contains the state of a hexdump. */
+struct hexdump_ctx {
+ BIO *bio;
+ char right_chars[18]; /* the contents of the right-hand side, ASCII dump. */
+ unsigned used; /* number of bytes in the current line. */
+ size_t n; /* number of bytes total. */
+ unsigned indent;
+};
+
+static void hexbyte(char *out, uint8_t b) {
+ static const char hextable[] = "0123456789abcdef";
+ out[0] = hextable[b>>4];
+ out[1] = hextable[b&0x0f];
+}
+
+static char to_char(uint8_t b) {
+ if (b < 32 || b > 126) {
+ return '.';
+ }
+ return b;
+}
+
+/* hexdump_write adds |len| bytes of |data| to the current hex dump described by
+ * |ctx|. */
+static int hexdump_write(struct hexdump_ctx *ctx, const uint8_t *data,
+ size_t len) {
+ size_t i;
+ char buf[10];
+ unsigned l;
+
+ /* Output lines look like:
+ * 00000010 2e 2f 30 31 32 33 34 35 36 37 38 ... 3c 3d // |./0123456789:;<=|
+ * ^ offset ^ extra space ^ ASCII of line
+ */
+
+ for (i = 0; i < len; i++) {
+ if (ctx->used == 0) {
+ /* The beginning of a line. */
+ BIO_indent(ctx->bio, ctx->indent, UINT_MAX);
+
+ hexbyte(&buf[0], ctx->n >> 24);
+ hexbyte(&buf[2], ctx->n >> 16);
+ hexbyte(&buf[4], ctx->n >> 8);
+ hexbyte(&buf[6], ctx->n);
+ buf[8] = buf[9] = ' ';
+ if (BIO_write(ctx->bio, buf, 10) < 0) {
+ return 0;
+ }
+ }
+
+ hexbyte(buf, data[i]);
+ buf[2] = ' ';
+ l = 3;
+ if (ctx->used == 7) {
+ /* There's an additional space after the 8th byte. */
+ buf[3] = ' ';
+ l = 4;
+ } else if (ctx->used == 15) {
+ /* At the end of the line there's an extra space and the bar for the
+ * right column. */
+ buf[3] = ' ';
+ buf[4] = '|';
+ l = 5;
+ }
+
+ if (BIO_write(ctx->bio, buf, l) < 0) {
+ return 0;
+ }
+ ctx->right_chars[ctx->used] = to_char(data[i]);
+ ctx->used++;
+ ctx->n++;
+ if (ctx->used == 16) {
+ ctx->right_chars[16] = '|';
+ ctx->right_chars[17] = '\n';
+ if (BIO_write(ctx->bio, ctx->right_chars, sizeof(ctx->right_chars)) < 0) {
+ return 0;
+ }
+ ctx->used = 0;
+ }
+ }
+
+ return 1;
+}
+
+/* finish flushes any buffered data in |ctx|. */
+static int finish(struct hexdump_ctx *ctx) {
+ /* See the comments in |hexdump| for the details of this format. */
+ const unsigned n_bytes = ctx->used;
+ unsigned l;
+ char buf[5];
+
+ if (n_bytes == 0) {
+ return 1;
+ }
+
+ memset(buf, ' ', 4);
+ buf[4] = '|';
+
+ for (; ctx->used < 16; ctx->used++) {
+ l = 3;
+ if (ctx->used == 7) {
+ l = 4;
+ } else if (ctx->used == 15) {
+ l = 5;
+ }
+ if (BIO_write(ctx->bio, buf, l) < 0) {
+ return 0;
+ }
+ }
+
+ ctx->right_chars[n_bytes] = '|';
+ ctx->right_chars[n_bytes + 1] = '\n';
+ if (BIO_write(ctx->bio, ctx->right_chars, n_bytes + 2) < 0) {
+ return 0;
+ }
+ return 1;
+}
+
+int BIO_hexdump(BIO *bio, const uint8_t *data, size_t len, unsigned indent) {
+ struct hexdump_ctx ctx;
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.bio = bio;
+ ctx.indent = indent;
+
+ if (!hexdump_write(&ctx, data, len) || !finish(&ctx)) {
+ return 0;
+ }
+
+ return 1;
+}
diff --git a/src/crypto/bio/internal.h b/src/crypto/bio/internal.h
new file mode 100644
index 0000000..d9a34f1
--- /dev/null
+++ b/src/crypto/bio/internal.h
@@ -0,0 +1,108 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 OPENSSL_HEADER_BIO_INTERNAL_H
+#define OPENSSL_HEADER_BIO_INTERNAL_H
+
+#include <openssl/base.h>
+
+#if !defined(OPENSSL_WINDOWS)
+#if defined(OPENSSL_PNACL)
+/* newlib uses u_short in socket.h without defining it. */
+typedef unsigned short u_short;
+#endif
+#include <sys/types.h>
+#include <sys/socket.h>
+#else
+typedef int socklen_t;
+#endif
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* BIO_ip_and_port_to_socket_and_addr creates a socket and fills in |*out_addr|
+ * and |*out_addr_length| with the correct values for connecting to |hostname|
+ * on |port_str|. It returns one on success or zero on error. */
+int bio_ip_and_port_to_socket_and_addr(int *out_sock,
+ struct sockaddr_storage *out_addr,
+ socklen_t *out_addr_length,
+ const char *hostname,
+ const char *port_str);
+
+/* BIO_socket_nbio sets whether |sock| is non-blocking. It returns one on
+ * success and zero otherwise. */
+int bio_socket_nbio(int sock, int on);
+
+/* BIO_clear_socket_error clears the last system socket error.
+ *
+ * TODO(fork): remove all callers of this. */
+void bio_clear_socket_error(void);
+
+/* BIO_sock_error returns the last socket error on |sock|. */
+int bio_sock_error(int sock);
+
+/* BIO_fd_should_retry returns non-zero if |return_value| indicates an error
+ * and |errno| indicates that it's non-fatal. */
+int bio_fd_should_retry(int return_value);
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_BIO_INTERNAL_H */
diff --git a/src/crypto/bio/pair.c b/src/crypto/bio/pair.c
new file mode 100644
index 0000000..de2b4cb
--- /dev/null
+++ b/src/crypto/bio/pair.c
@@ -0,0 +1,821 @@
+/* ====================================================================
+ * 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 <openssl/bio.h>
+
+#include <assert.h>
+#include <string.h>
+
+#include <openssl/buf.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+
+
+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;
+ uint8_t *buf; /* "size" elements (if != NULL) */
+ char buf_externally_allocated; /* true iff buf was externally allocated. */
+
+ char zero_copy_read_lock; /* true iff a zero copy read operation
+ * is in progress. */
+ char zero_copy_write_lock; /* true iff a zero copy write operation
+ * is in progress. */
+
+ 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 = OPENSSL_malloc(sizeof *b);
+ if (b == NULL) {
+ return 0;
+ }
+ memset(b, 0, sizeof(struct bio_bio_st));
+
+ b->size = 17 * 1024; /* enough for one TLS record (just a default) */
+ bio->ptr = b;
+ return 1;
+}
+
+static void bio_destroy_pair(BIO *bio) {
+ struct bio_bio_st *b = bio->ptr;
+ BIO *peer_bio;
+ struct bio_bio_st *peer_b;
+
+ if (b == NULL) {
+ return;
+ }
+
+ peer_bio = b->peer;
+ if (peer_bio == NULL) {
+ return;
+ }
+
+ 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;
+}
+
+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);
+ }
+
+ if (b->buf != NULL && !b->buf_externally_allocated) {
+ OPENSSL_free(b->buf);
+ }
+
+ OPENSSL_free(b);
+
+ return 1;
+}
+
+static size_t bio_zero_copy_get_read_buf(struct bio_bio_st* peer_b,
+ uint8_t** out_read_buf,
+ size_t* out_buf_offset) {
+ size_t max_available;
+ if (peer_b->len > peer_b->size - peer_b->offset) {
+ /* Only the first half of the ring buffer can be read. */
+ max_available = peer_b->size - peer_b->offset;
+ } else {
+ max_available = peer_b->len;
+ }
+
+ *out_read_buf = peer_b->buf;
+ *out_buf_offset = peer_b->offset;
+ return max_available;
+}
+
+int BIO_zero_copy_get_read_buf(BIO* bio, uint8_t** out_read_buf,
+ size_t* out_buf_offset,
+ size_t* out_available_bytes) {
+ struct bio_bio_st* b;
+ struct bio_bio_st* peer_b;
+ size_t max_available;
+ *out_available_bytes = 0;
+
+ BIO_clear_retry_flags(bio);
+
+ if (!bio->init) {
+ OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_read_buf, BIO_R_UNINITIALIZED);
+ return 0;
+ }
+
+ b = bio->ptr;
+
+ if (!b || !b->peer) {
+ OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_read_buf,
+ BIO_R_UNSUPPORTED_METHOD);
+ return 0;
+ }
+
+ peer_b = b->peer->ptr;
+ if (!peer_b || !peer_b->peer || peer_b->peer->ptr != b) {
+ OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_read_buf,
+ BIO_R_UNSUPPORTED_METHOD);
+ return 0;
+ }
+
+ if (peer_b->zero_copy_read_lock) {
+ OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_read_buf, BIO_R_INVALID_ARGUMENT);
+ return 0;
+ }
+
+ peer_b->request = 0; /* Is not used by zero-copy API. */
+
+ max_available =
+ bio_zero_copy_get_read_buf(peer_b, out_read_buf, out_buf_offset);
+
+ assert(peer_b->buf != NULL);
+ if (max_available > 0) {
+ peer_b->zero_copy_read_lock = 1;
+ }
+
+ *out_available_bytes = max_available;
+ return 1;
+}
+
+int BIO_zero_copy_get_read_buf_done(BIO* bio, size_t bytes_read) {
+ struct bio_bio_st* b;
+ struct bio_bio_st* peer_b;
+ size_t max_available;
+ size_t dummy_read_offset;
+ uint8_t* dummy_read_buf;
+
+ assert(BIO_get_retry_flags(bio) == 0);
+
+ if (!bio->init) {
+ OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_read_buf_done,
+ BIO_R_UNINITIALIZED);
+ return 0;
+ }
+
+ b = bio->ptr;
+
+ if (!b || !b->peer) {
+ OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_read_buf_done,
+ BIO_R_UNSUPPORTED_METHOD);
+ return 0;
+ }
+
+ peer_b = b->peer->ptr;
+ if (!peer_b || !peer_b->peer || peer_b->peer->ptr != b) {
+ OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_read_buf_done,
+ BIO_R_UNSUPPORTED_METHOD);
+ return 0;
+ }
+
+ if (!peer_b->zero_copy_read_lock) {
+ OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_read_buf_done,
+ BIO_R_INVALID_ARGUMENT);
+ return 0;
+ }
+
+ max_available =
+ bio_zero_copy_get_read_buf(peer_b, &dummy_read_buf, &dummy_read_offset);
+ if (bytes_read > max_available) {
+ OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_read_buf_done,
+ BIO_R_INVALID_ARGUMENT);
+ return 0;
+ }
+
+ peer_b->len -= bytes_read;
+ assert(peer_b->len >= 0);
+ assert(peer_b->offset + bytes_read <= peer_b->size);
+
+ /* Move read offset. If zero_copy_write_lock == 1 we must advance the
+ * offset even if buffer becomes empty, to make sure
+ * write_offset = (offset + len) mod size does not change. */
+ if (peer_b->offset + bytes_read == peer_b->size ||
+ (!peer_b->zero_copy_write_lock && peer_b->len == 0)) {
+ peer_b->offset = 0;
+ } else {
+ peer_b->offset += bytes_read;
+ }
+
+ bio->num_read += bytes_read;
+ peer_b->zero_copy_read_lock = 0;
+ return 1;
+}
+
+static size_t bio_zero_copy_get_write_buf(struct bio_bio_st* b,
+ uint8_t** out_write_buf,
+ size_t* out_buf_offset) {
+ size_t write_offset;
+ size_t max_available;
+
+ assert(b->len <= b->size);
+
+ write_offset = b->offset + b->len;
+
+ if (write_offset >= b->size) {
+ /* Only the first half of the ring buffer can be written to. */
+ write_offset -= b->size;
+ /* write up to the start of the ring buffer. */
+ max_available = b->offset - write_offset;
+ } else {
+ /* write up to the end the buffer. */
+ max_available = b->size - write_offset;
+ }
+
+ *out_write_buf = b->buf;
+ *out_buf_offset = write_offset;
+ return max_available;
+}
+
+int BIO_zero_copy_get_write_buf(BIO* bio, uint8_t** out_write_buf,
+ size_t* out_buf_offset,
+ size_t* out_available_bytes) {
+ struct bio_bio_st* b;
+ struct bio_bio_st* peer_b;
+ size_t max_available;
+
+ *out_available_bytes = 0;
+ BIO_clear_retry_flags(bio);
+
+ if (!bio->init) {
+ OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_write_buf, BIO_R_UNINITIALIZED);
+ return 0;
+ }
+
+ b = bio->ptr;
+
+ if (!b || !b->buf || !b->peer) {
+ OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_write_buf,
+ BIO_R_UNSUPPORTED_METHOD);
+ return 0;
+ }
+ peer_b = b->peer->ptr;
+ if (!peer_b || !peer_b->peer || peer_b->peer->ptr != b) {
+ OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_write_buf,
+ BIO_R_UNSUPPORTED_METHOD);
+ return 0;
+ }
+
+ assert(b->buf != NULL);
+
+ if (b->zero_copy_write_lock) {
+ OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_write_buf, BIO_R_INVALID_ARGUMENT);
+ return 0;
+ }
+
+ b->request = 0;
+ if (b->closed) {
+ /* Bio is already closed. */
+ OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_write_buf, BIO_R_BROKEN_PIPE);
+ return 0;
+ }
+
+ max_available = bio_zero_copy_get_write_buf(b, out_write_buf, out_buf_offset);
+
+ if (max_available > 0) {
+ b->zero_copy_write_lock = 1;
+ }
+
+ *out_available_bytes = max_available;
+ return 1;
+}
+
+int BIO_zero_copy_get_write_buf_done(BIO* bio, size_t bytes_written) {
+ struct bio_bio_st* b;
+ struct bio_bio_st* peer_b;
+
+ size_t rest;
+ size_t dummy_write_offset;
+ uint8_t* dummy_write_buf;
+
+ if (!bio->init) {
+ OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_write_buf_done,
+ BIO_R_UNINITIALIZED);
+ return 0;
+ }
+
+ b = bio->ptr;
+
+ if (!b || !b->buf || !b->peer) {
+ OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_write_buf_done,
+ BIO_R_UNSUPPORTED_METHOD);
+ return 0;
+ }
+ peer_b = b->peer->ptr;
+ if (!peer_b || !peer_b->peer || peer_b->peer->ptr != b) {
+ OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_write_buf_done,
+ BIO_R_UNSUPPORTED_METHOD);
+ return 0;
+ }
+
+ b->request = 0;
+ if (b->closed) {
+ /* BIO is already closed. */
+ OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_write_buf_done, BIO_R_BROKEN_PIPE);
+ return 0;
+ }
+
+ if (!b->zero_copy_write_lock) {
+ OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_write_buf_done,
+ BIO_R_INVALID_ARGUMENT);
+ return 0;
+ }
+
+ rest = bio_zero_copy_get_write_buf(b, &dummy_write_buf, &dummy_write_offset);
+
+ if (bytes_written > rest) {
+ OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_write_buf_done,
+ BIO_R_INVALID_ARGUMENT);
+ return 0;
+ }
+
+ bio->num_write += bytes_written;
+ /* Move write offset. */
+ b->len += bytes_written;
+ b->zero_copy_write_lock = 0;
+ 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 || peer_b->zero_copy_read_lock) {
+ 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);
+ /* one or two iterations */
+ do {
+ 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 zero_copy_write_lock == 1 we must advance the offset even if buffer
+ * becomes empty, to make sure write_offset = (offset + len) % size
+ * does not change. */
+ if (peer_b->len || peer_b->zero_copy_write_lock) {
+ 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);
+
+ if (b->zero_copy_write_lock) {
+ return 0;
+ }
+
+ b->request = 0;
+ if (b->closed) {
+ /* we already closed */
+ OPENSSL_PUT_ERROR(BIO, bio_write, 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);
+ /* one or two iterations */
+ do {
+ 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 int bio_make_pair(BIO* bio1, BIO* bio2,
+ size_t writebuf1_len, uint8_t* ext_writebuf1,
+ size_t writebuf2_len, uint8_t* ext_writebuf2) {
+ 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) {
+ OPENSSL_PUT_ERROR(BIO, bio_make_pair, BIO_R_IN_USE);
+ return 0;
+ }
+
+ assert(b1->buf_externally_allocated == 0);
+ assert(b2->buf_externally_allocated == 0);
+
+ if (b1->buf == NULL) {
+ if (writebuf1_len) {
+ b1->size = writebuf1_len;
+ }
+ if (!ext_writebuf1) {
+ b1->buf_externally_allocated = 0;
+ b1->buf = OPENSSL_malloc(b1->size);
+ if (b1->buf == NULL) {
+ OPENSSL_PUT_ERROR(BIO, bio_make_pair, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ } else {
+ b1->buf = ext_writebuf1;
+ b1->buf_externally_allocated = 1;
+ }
+ b1->len = 0;
+ b1->offset = 0;
+ }
+
+ if (b2->buf == NULL) {
+ if (writebuf2_len) {
+ b2->size = writebuf2_len;
+ }
+ if (!ext_writebuf2) {
+ b2->buf_externally_allocated = 0;
+ b2->buf = OPENSSL_malloc(b2->size);
+ if (b2->buf == NULL) {
+ OPENSSL_PUT_ERROR(BIO, bio_make_pair, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ } else {
+ b2->buf = ext_writebuf2;
+ b2->buf_externally_allocated = 1;
+ }
+ b2->len = 0;
+ b2->offset = 0;
+ }
+
+ b1->peer = bio2;
+ b1->closed = 0;
+ b1->request = 0;
+ b1->zero_copy_read_lock = 0;
+ b1->zero_copy_write_lock = 0;
+ b2->peer = bio1;
+ b2->closed = 0;
+ b2->request = 0;
+ b2->zero_copy_read_lock = 0;
+ b2->zero_copy_write_lock = 0;
+
+ bio1->init = 1;
+ bio2->init = 1;
+
+ return 1;
+}
+
+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_GET_WRITE_BUF_SIZE:
+ ret = (long)b->size;
+ 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_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:
+ ret = 0;
+ if (b->buf != NULL) {
+ ret = (long)b->len;
+ }
+ 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 const BIO_METHOD methods_biop = {
+ BIO_TYPE_BIO, "BIO pair", bio_write, bio_read,
+ bio_puts, NULL /* no bio_gets */, bio_ctrl, bio_new,
+ bio_free, NULL /* no bio_callback_ctrl */
+};
+
+const BIO_METHOD *bio_s_bio(void) { return &methods_biop; }
+
+int BIO_new_bio_pair(BIO** bio1_p, size_t writebuf1,
+ BIO** bio2_p, size_t writebuf2) {
+ return BIO_new_bio_pair_external_buf(bio1_p, writebuf1, NULL, bio2_p,
+ writebuf2, NULL);
+}
+
+int BIO_new_bio_pair_external_buf(BIO** bio1_p, size_t writebuf1_len,
+ uint8_t* ext_writebuf1,
+ BIO** bio2_p, size_t writebuf2_len,
+ uint8_t* ext_writebuf2) {
+ BIO *bio1 = NULL, *bio2 = NULL;
+ int ret = 0;
+
+ /* External buffers must have sizes greater than 0. */
+ if ((ext_writebuf1 && !writebuf1_len) || (ext_writebuf2 && !writebuf2_len)) {
+ goto err;
+ }
+
+ bio1 = BIO_new(bio_s_bio());
+ if (bio1 == NULL) {
+ goto err;
+ }
+ bio2 = BIO_new(bio_s_bio());
+ if (bio2 == NULL) {
+ goto err;
+ }
+
+ if (!bio_make_pair(bio1, bio2, writebuf1_len, ext_writebuf1, writebuf2_len,
+ ext_writebuf2)) {
+ 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_read_request(BIO *bio) {
+ return BIO_ctrl(bio, BIO_C_GET_READ_REQUEST, 0, NULL);
+}
+
+size_t BIO_ctrl_get_write_guarantee(BIO *bio) {
+ return BIO_ctrl(bio, BIO_C_GET_WRITE_GUARANTEE, 0, NULL);
+}
+
+int BIO_shutdown_wr(BIO *bio) {
+ return BIO_ctrl(bio, BIO_C_SHUTDOWN_WR, 0, NULL);
+}
diff --git a/src/crypto/bio/printf.c b/src/crypto/bio/printf.c
new file mode 100644
index 0000000..3638915
--- /dev/null
+++ b/src/crypto/bio/printf.c
@@ -0,0 +1,115 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#if !defined(_POSIX_C_SOURCE)
+#define _POSIX_C_SOURCE 201410L /* for snprintf, vprintf etc */
+#endif
+
+#include <openssl/bio.h>
+
+#include <assert.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+#include <openssl/mem.h>
+
+int BIO_printf(BIO *bio, const char *format, ...) {
+ va_list args;
+ char buf[256], *out, out_malloced = 0;
+ int out_len, ret;
+
+ va_start(args, format);
+ out_len = vsnprintf(buf, sizeof(buf), format, args);
+ va_end(args);
+
+#if defined(OPENSSL_WINDOWS)
+ /* On Windows, vsnprintf returns -1 rather than the requested length on
+ * truncation */
+ if (out_len < 0) {
+ va_start(args, format);
+ out_len = _vscprintf(format, args);
+ va_end(args);
+ assert(out_len >= sizeof(buf));
+ }
+#endif
+
+ if (out_len >= sizeof(buf)) {
+ const int requested_len = out_len;
+ /* The output was truncated. Note that vsnprintf's return value
+ * does not include a trailing NUL, but the buffer must be sized
+ * for it. */
+ out = OPENSSL_malloc(requested_len + 1);
+ out_malloced = 1;
+ if (out == NULL) {
+ /* Unclear what can be done in this situation. OpenSSL has historically
+ * crashed and that seems better than producing the wrong output. */
+ abort();
+ }
+ va_start(args, format);
+ out_len = vsnprintf(out, requested_len + 1, format, args);
+ va_end(args);
+ assert(out_len == requested_len);
+ } else {
+ out = buf;
+ }
+
+ ret = BIO_write(bio, out, out_len);
+ if (out_malloced) {
+ OPENSSL_free(out);
+ }
+
+ return ret;
+}
diff --git a/src/crypto/bio/socket.c b/src/crypto/bio/socket.c
new file mode 100644
index 0000000..590447f
--- /dev/null
+++ b/src/crypto/bio/socket.c
@@ -0,0 +1,191 @@
+/* crypto/bio/bss_sock.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 <openssl/bio.h>
+
+#include <fcntl.h>
+#include <string.h>
+
+#if !defined(OPENSSL_WINDOWS)
+#include <unistd.h>
+#else
+#pragma warning(push, 3)
+#include <WinSock2.h>
+#pragma warning(pop)
+#endif
+
+#include "internal.h"
+
+
+#if !defined(OPENSSL_WINDOWS)
+static int closesocket(int sock) {
+ return close(sock);
+}
+#endif
+
+static int sock_new(BIO *bio) {
+ bio->init = 0;
+ bio->num = 0;
+ bio->ptr = NULL;
+ bio->flags = 0;
+ return 1;
+}
+
+static int sock_free(BIO *bio) {
+ if (bio == NULL) {
+ return 0;
+ }
+
+ if (bio->shutdown) {
+ if (bio->init) {
+ closesocket(bio->num);
+ }
+ bio->init = 0;
+ bio->flags = 0;
+ }
+ return 1;
+}
+
+static int sock_read(BIO *b, char *out, int outl) {
+ int ret = 0;
+
+ if (out == NULL) {
+ return 0;
+ }
+
+ bio_clear_socket_error();
+ ret = recv(b->num, out, outl, 0);
+ BIO_clear_retry_flags(b);
+ if (ret <= 0) {
+ if (bio_fd_should_retry(ret)) {
+ BIO_set_retry_read(b);
+ }
+ }
+ return ret;
+}
+
+static int sock_write(BIO *b, const char *in, int inl) {
+ int ret;
+
+ bio_clear_socket_error();
+ ret = send(b->num, in, inl, 0);
+ BIO_clear_retry_flags(b);
+ if (ret <= 0) {
+ if (bio_fd_should_retry(ret)) {
+ BIO_set_retry_write(b);
+ }
+ }
+ return ret;
+}
+
+static int sock_puts(BIO *bp, const char *str) {
+ return sock_write(bp, str, strlen(str));
+}
+
+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_FLUSH:
+ ret = 1;
+ break;
+ default:
+ ret = 0;
+ break;
+ }
+ return ret;
+}
+
+static const BIO_METHOD methods_sockp = {
+ BIO_TYPE_SOCKET, "socket", sock_write, sock_read, sock_puts,
+ NULL /* gets, */, sock_ctrl, sock_new, sock_free, NULL,
+};
+
+const BIO_METHOD *BIO_s_socket(void) { return &methods_sockp; }
+
+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;
+}
diff --git a/src/crypto/bio/socket_helper.c b/src/crypto/bio/socket_helper.c
new file mode 100644
index 0000000..52e1606
--- /dev/null
+++ b/src/crypto/bio/socket_helper.c
@@ -0,0 +1,112 @@
+/* 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. */
+
+#define _POSIX_SOURCE
+
+#include <openssl/bio.h>
+#include <openssl/err.h>
+
+#include <fcntl.h>
+#include <string.h>
+#include <sys/types.h>
+
+#if !defined(OPENSSL_WINDOWS)
+#include <netdb.h>
+#include <unistd.h>
+#else
+#pragma warning(push, 3)
+#include <WinSock2.h>
+#include <WS2tcpip.h>
+#pragma warning(pop)
+#endif
+
+#include "internal.h"
+
+
+int bio_ip_and_port_to_socket_and_addr(int *out_sock,
+ struct sockaddr_storage *out_addr,
+ socklen_t *out_addr_length,
+ const char *hostname,
+ const char *port_str) {
+ struct addrinfo hint, *result, *cur;
+ int ret;
+
+ *out_sock = -1;
+
+ memset(&hint, 0, sizeof(hint));
+ hint.ai_family = AF_UNSPEC;
+ hint.ai_socktype = SOCK_STREAM;
+
+ ret = getaddrinfo(hostname, port_str, &hint, &result);
+ if (ret != 0) {
+ OPENSSL_PUT_ERROR(SYS, getaddrinfo, 0);
+ ERR_add_error_data(2, gai_strerror(ret));
+ return 0;
+ }
+
+ ret = 0;
+
+ for (cur = result; cur; cur = cur->ai_next) {
+ if (cur->ai_addrlen > sizeof(struct sockaddr_storage)) {
+ continue;
+ }
+ memset(out_addr, 0, sizeof(struct sockaddr_storage));
+ memcpy(out_addr, cur->ai_addr, cur->ai_addrlen);
+ *out_addr_length = cur->ai_addrlen;
+
+ *out_sock = socket(cur->ai_family, cur->ai_socktype, cur->ai_protocol);
+ if (*out_sock < 0) {
+ OPENSSL_PUT_SYSTEM_ERROR(socket);
+ goto out;
+ }
+
+ ret = 1;
+ break;
+ }
+
+out:
+ freeaddrinfo(result);
+ return ret;
+}
+
+int bio_socket_nbio(int sock, int on) {
+#if defined(OPENSSL_WINDOWS)
+ u_long arg = on;
+
+ return 0 == ioctlsocket(sock, FIONBIO, &arg);
+#else
+ int flags = fcntl(sock, F_GETFL, 0);
+ if (flags < 0) {
+ return 0;
+ }
+ if (!on) {
+ flags &= ~O_NONBLOCK;
+ } else {
+ flags |= O_NONBLOCK;
+ }
+ return fcntl(sock, F_SETFL, flags) == 0;
+#endif
+}
+
+void bio_clear_socket_error(void) {}
+
+int bio_sock_error(int sock) {
+ int error;
+ socklen_t error_size = sizeof(error);
+
+ if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (char *)&error, &error_size) < 0) {
+ return 1;
+ }
+ return error;
+}
diff --git a/src/crypto/bn/CMakeLists.txt b/src/crypto/bn/CMakeLists.txt
new file mode 100644
index 0000000..600be4d
--- /dev/null
+++ b/src/crypto/bn/CMakeLists.txt
@@ -0,0 +1,76 @@
+include_directories(. .. ../../include)
+
+if (${ARCH} STREQUAL "x86_64")
+ set(
+ BN_ARCH_SOURCES
+
+ asm/x86_64-gcc.c
+ x86_64-mont.${ASM_EXT}
+ x86_64-mont5.${ASM_EXT}
+ rsaz-x86_64.${ASM_EXT}
+ rsaz-avx2.${ASM_EXT}
+
+ rsaz_exp.c
+ )
+endif()
+
+if (${ARCH} STREQUAL "x86")
+ set(
+ BN_ARCH_SOURCES
+
+ bn-586.${ASM_EXT}
+ co-586.${ASM_EXT}
+ x86-mont.${ASM_EXT}
+ )
+endif()
+
+if (${ARCH} STREQUAL "arm")
+ set(
+ BN_ARCH_SOURCES
+
+ armv4-mont.${ASM_EXT}
+ )
+endif()
+
+add_library(
+ bn
+
+ OBJECT
+
+ bn_error.c
+ add.c
+ bn.c
+ cmp.c
+ convert.c
+ ctx.c
+ div.c
+ exponentiation.c
+ generic.c
+ gcd.c
+ kronecker.c
+ montgomery.c
+ mul.c
+ prime.c
+ random.c
+ shift.c
+ sqrt.c
+
+ ${BN_ARCH_SOURCES}
+)
+
+perlasm(x86_64-mont.${ASM_EXT} asm/x86_64-mont.pl)
+perlasm(x86_64-mont5.${ASM_EXT} asm/x86_64-mont5.pl)
+perlasm(rsaz-x86_64.${ASM_EXT} asm/rsaz-x86_64.pl)
+perlasm(rsaz-avx2.${ASM_EXT} asm/rsaz-avx2.pl)
+perlasm(bn-586.${ASM_EXT} asm/bn-586.pl)
+perlasm(co-586.${ASM_EXT} asm/co-586.pl)
+perlasm(x86-mont.${ASM_EXT} asm/x86-mont.pl)
+perlasm(armv4-mont.${ASM_EXT} asm/armv4-mont.pl)
+
+add_executable(
+ bn_test
+
+ bn_test.c
+)
+
+target_link_libraries(bn_test crypto)
diff --git a/src/crypto/bn/add.c b/src/crypto/bn/add.c
new file mode 100644
index 0000000..1c6b2d7
--- /dev/null
+++ b/src/crypto/bn/add.c
@@ -0,0 +1,394 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/bn.h>
+
+#include <openssl/err.h>
+#include <openssl/mem.h>
+
+#include "internal.h"
+
+
+int BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) {
+ const BIGNUM *tmp;
+ int a_neg = a->neg, ret;
+
+ /* a + b a+b
+ * a + -b a-b
+ * -a + b b-a
+ * -a + -b -(a+b)
+ */
+ if (a_neg ^ b->neg) {
+ /* only one is negative */
+ if (a_neg) {
+ tmp = a;
+ a = b;
+ b = tmp;
+ }
+
+ /* we are now a - b */
+ if (BN_ucmp(a, b) < 0) {
+ if (!BN_usub(r, b, a)) {
+ return 0;
+ }
+ r->neg = 1;
+ } else {
+ if (!BN_usub(r, a, b)) {
+ return 0;
+ }
+ r->neg = 0;
+ }
+ return 1;
+ }
+
+ ret = BN_uadd(r, a, b);
+ r->neg = a_neg;
+ return ret;
+}
+
+int BN_uadd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) {
+ int max, min, dif;
+ BN_ULONG *ap, *bp, *rp, carry, t1, t2;
+ const BIGNUM *tmp;
+
+ if (a->top < b->top) {
+ tmp = a;
+ a = b;
+ b = tmp;
+ }
+ max = a->top;
+ min = b->top;
+ dif = max - min;
+
+ if (bn_wexpand(r, max + 1) == NULL) {
+ return 0;
+ }
+
+ r->top = max;
+
+ ap = a->d;
+ bp = b->d;
+ rp = r->d;
+
+ carry = bn_add_words(rp, ap, bp, min);
+ rp += min;
+ ap += min;
+ bp += min;
+
+ if (carry) {
+ while (dif) {
+ dif--;
+ t1 = *(ap++);
+ t2 = (t1 + 1) & BN_MASK2;
+ *(rp++) = t2;
+ if (t2) {
+ carry = 0;
+ break;
+ }
+ }
+ if (carry) {
+ /* carry != 0 => dif == 0 */
+ *rp = 1;
+ r->top++;
+ }
+ }
+
+ if (dif && rp != ap) {
+ while (dif--) {
+ /* copy remaining words if ap != rp */
+ *(rp++) = *(ap++);
+ }
+ }
+
+ r->neg = 0;
+ return 1;
+}
+
+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);
+ if (!BN_is_zero(a)) {
+ a->neg = !(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) == NULL) {
+ return 0;
+ }
+ a->top++;
+ a->d[i] = w;
+ }
+
+ return 1;
+}
+
+int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) {
+ int max;
+ int add = 0, neg = 0;
+ const BIGNUM *tmp;
+
+ /* a - b a-b
+ * a - -b a+b
+ * -a - b -(a+b)
+ * -a - -b b-a
+ */
+ if (a->neg) {
+ if (b->neg) {
+ tmp = a;
+ a = b;
+ b = tmp;
+ } else {
+ add = 1;
+ neg = 1;
+ }
+ } else {
+ if (b->neg) {
+ add = 1;
+ neg = 0;
+ }
+ }
+
+ if (add) {
+ if (!BN_uadd(r, a, b)) {
+ return 0;
+ }
+
+ r->neg = neg;
+ return 1;
+ }
+
+ /* We are actually doing a - b :-) */
+
+ max = (a->top > b->top) ? a->top : b->top;
+ if (bn_wexpand(r, max) == NULL) {
+ return 0;
+ }
+
+ if (BN_ucmp(a, b) < 0) {
+ if (!BN_usub(r, b, a)) {
+ return 0;
+ }
+ r->neg = 1;
+ } else {
+ if (!BN_usub(r, a, b)) {
+ return 0;
+ }
+ r->neg = 0;
+ }
+
+ return 1;
+}
+
+int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) {
+ int max, min, dif;
+ register BN_ULONG t1, t2, *ap, *bp, *rp;
+ int i, carry;
+
+ max = a->top;
+ min = b->top;
+ dif = max - min;
+
+ if (dif < 0) /* hmm... should not be happening */
+ {
+ OPENSSL_PUT_ERROR(BN, BN_usub, BN_R_ARG2_LT_ARG3);
+ return 0;
+ }
+
+ if (bn_wexpand(r, max) == NULL) {
+ return 0;
+ }
+
+ ap = a->d;
+ bp = b->d;
+ rp = r->d;
+
+ carry = 0;
+ for (i = min; i != 0; i--) {
+ t1 = *(ap++);
+ t2 = *(bp++);
+ if (carry) {
+ carry = (t1 <= t2);
+ t1 = (t1 - t2 - 1) & BN_MASK2;
+ } else {
+ carry = (t1 < t2);
+ t1 = (t1 - t2) & BN_MASK2;
+ }
+ *(rp++) = t1 & BN_MASK2;
+ }
+
+ if (carry) /* subtracted */
+ {
+ if (!dif) {
+ /* error: a < b */
+ return 0;
+ }
+
+ while (dif) {
+ dif--;
+ t1 = *(ap++);
+ t2 = (t1 - 1) & BN_MASK2;
+ *(rp++) = t2;
+ if (t1) {
+ break;
+ }
+ }
+ }
+
+ if (rp != ap) {
+ for (;;) {
+ if (!dif--) {
+ break;
+ }
+ rp[0] = ap[0];
+ if (!dif--) {
+ break;
+ }
+ rp[1] = ap[1];
+ if (!dif--) {
+ break;
+ }
+ rp[2] = ap[2];
+ if (!dif--) {
+ break;
+ }
+ rp[3] = ap[3];
+ rp += 4;
+ ap += 4;
+ }
+ }
+
+ r->top = max;
+ r->neg = 0;
+ bn_correct_top(r);
+
+ return 1;
+}
+
+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);
+ a->neg = 1;
+ return i;
+ }
+
+ if ((a->top == 1) && (a->d[0] < w)) {
+ a->d[0] = w - a->d[0];
+ a->neg = 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;
+}
diff --git a/src/crypto/bn/asm/armv4-mont.pl b/src/crypto/bn/asm/armv4-mont.pl
new file mode 100644
index 0000000..5cc1328
--- /dev/null
+++ b/src/crypto/bn/asm/armv4-mont.pl
@@ -0,0 +1,670 @@
+#!/usr/bin/env perl
+
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+# project. The module is, however, dual licensed under OpenSSL and
+# CRYPTOGAMS licenses depending on where you obtain it. For further
+# details see http://www.openssl.org/~appro/cryptogams/.
+# ====================================================================
+
+# January 2007.
+
+# Montgomery multiplication for ARMv4.
+#
+# Performance improvement naturally varies among CPU implementations
+# and compilers. The code was observed to provide +65-35% improvement
+# [depending on key length, less for longer keys] on ARM920T, and
+# +115-80% on Intel IXP425. This is compared to pre-bn_mul_mont code
+# base and compiler generated code with in-lined umull and even umlal
+# instructions. The latter means that this code didn't really have an
+# "advantage" of utilizing some "secret" instruction.
+#
+# The code is interoperable with Thumb ISA and is rather compact, less
+# than 1/2KB. Windows CE port would be trivial, as it's exclusively
+# about decorations, ABI and instruction syntax are identical.
+
+# November 2013
+#
+# Add NEON code path, which handles lengths divisible by 8. RSA/DSA
+# performance improvement on Cortex-A8 is ~45-100% depending on key
+# length, more for longer keys. On Cortex-A15 the span is ~10-105%.
+# On Snapdragon S4 improvement was measured to vary from ~70% to
+# incredible ~380%, yes, 4.8x faster, for RSA4096 sign. But this is
+# rather because original integer-only code seems to perform
+# suboptimally on S4. Situation on Cortex-A9 is unfortunately
+# different. It's being looked into, but the trouble is that
+# performance for vectors longer than 256 bits is actually couple
+# of percent worse than for integer-only code. The code is chosen
+# for execution on all NEON-capable processors, because gain on
+# others outweighs the marginal loss on Cortex-A9.
+
+while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {}
+open STDOUT,">$output";
+
+$num="r0"; # starts as num argument, but holds &tp[num-1]
+$ap="r1";
+$bp="r2"; $bi="r2"; $rp="r2";
+$np="r3";
+$tp="r4";
+$aj="r5";
+$nj="r6";
+$tj="r7";
+$n0="r8";
+########### # r9 is reserved by ELF as platform specific, e.g. TLS pointer
+$alo="r10"; # sl, gcc uses it to keep @GOT
+$ahi="r11"; # fp
+$nlo="r12"; # ip
+########### # r13 is stack pointer
+$nhi="r14"; # lr
+########### # r15 is program counter
+
+#### argument block layout relative to &tp[num-1], a.k.a. $num
+$_rp="$num,#12*4";
+# ap permanently resides in r1
+$_bp="$num,#13*4";
+# np permanently resides in r3
+$_n0="$num,#14*4";
+$_num="$num,#15*4"; $_bpend=$_num;
+
+$code=<<___;
+#include "arm_arch.h"
+
+.text
+.code 32
+
+#if __ARM_ARCH__>=7
+.align 5
+.LOPENSSL_armcap:
+.word OPENSSL_armcap_P-bn_mul_mont
+#endif
+
+.global bn_mul_mont
+.hidden bn_mul_mont
+.type bn_mul_mont,%function
+
+.align 5
+bn_mul_mont:
+ ldr ip,[sp,#4] @ load num
+ stmdb sp!,{r0,r2} @ sp points at argument block
+#if __ARM_ARCH__>=7
+ tst ip,#7
+ bne .Lialu
+ adr r0,bn_mul_mont
+ ldr r2,.LOPENSSL_armcap
+ ldr r0,[r0,r2]
+ tst r0,#1 @ NEON available?
+ ldmia sp, {r0,r2}
+ beq .Lialu
+ add sp,sp,#8
+ b bn_mul8x_mont_neon
+.align 4
+.Lialu:
+#endif
+ cmp ip,#2
+ mov $num,ip @ load num
+ movlt r0,#0
+ addlt sp,sp,#2*4
+ blt .Labrt
+
+ stmdb sp!,{r4-r12,lr} @ save 10 registers
+
+ mov $num,$num,lsl#2 @ rescale $num for byte count
+ sub sp,sp,$num @ alloca(4*num)
+ sub sp,sp,#4 @ +extra dword
+ sub $num,$num,#4 @ "num=num-1"
+ add $tp,$bp,$num @ &bp[num-1]
+
+ add $num,sp,$num @ $num to point at &tp[num-1]
+ ldr $n0,[$_n0] @ &n0
+ ldr $bi,[$bp] @ bp[0]
+ ldr $aj,[$ap],#4 @ ap[0],ap++
+ ldr $nj,[$np],#4 @ np[0],np++
+ ldr $n0,[$n0] @ *n0
+ str $tp,[$_bpend] @ save &bp[num]
+
+ umull $alo,$ahi,$aj,$bi @ ap[0]*bp[0]
+ str $n0,[$_n0] @ save n0 value
+ mul $n0,$alo,$n0 @ "tp[0]"*n0
+ mov $nlo,#0
+ umlal $alo,$nlo,$nj,$n0 @ np[0]*n0+"t[0]"
+ mov $tp,sp
+
+.L1st:
+ ldr $aj,[$ap],#4 @ ap[j],ap++
+ mov $alo,$ahi
+ ldr $nj,[$np],#4 @ np[j],np++
+ mov $ahi,#0
+ umlal $alo,$ahi,$aj,$bi @ ap[j]*bp[0]
+ mov $nhi,#0
+ umlal $nlo,$nhi,$nj,$n0 @ np[j]*n0
+ adds $nlo,$nlo,$alo
+ str $nlo,[$tp],#4 @ tp[j-1]=,tp++
+ adc $nlo,$nhi,#0
+ cmp $tp,$num
+ bne .L1st
+
+ adds $nlo,$nlo,$ahi
+ ldr $tp,[$_bp] @ restore bp
+ mov $nhi,#0
+ ldr $n0,[$_n0] @ restore n0
+ adc $nhi,$nhi,#0
+ str $nlo,[$num] @ tp[num-1]=
+ str $nhi,[$num,#4] @ tp[num]=
+
+.Louter:
+ sub $tj,$num,sp @ "original" $num-1 value
+ sub $ap,$ap,$tj @ "rewind" ap to &ap[1]
+ ldr $bi,[$tp,#4]! @ *(++bp)
+ sub $np,$np,$tj @ "rewind" np to &np[1]
+ ldr $aj,[$ap,#-4] @ ap[0]
+ ldr $alo,[sp] @ tp[0]
+ ldr $nj,[$np,#-4] @ np[0]
+ ldr $tj,[sp,#4] @ tp[1]
+
+ mov $ahi,#0
+ umlal $alo,$ahi,$aj,$bi @ ap[0]*bp[i]+tp[0]
+ str $tp,[$_bp] @ save bp
+ mul $n0,$alo,$n0
+ mov $nlo,#0
+ umlal $alo,$nlo,$nj,$n0 @ np[0]*n0+"tp[0]"
+ mov $tp,sp
+
+.Linner:
+ ldr $aj,[$ap],#4 @ ap[j],ap++
+ adds $alo,$ahi,$tj @ +=tp[j]
+ ldr $nj,[$np],#4 @ np[j],np++
+ mov $ahi,#0
+ umlal $alo,$ahi,$aj,$bi @ ap[j]*bp[i]
+ mov $nhi,#0
+ umlal $nlo,$nhi,$nj,$n0 @ np[j]*n0
+ adc $ahi,$ahi,#0
+ ldr $tj,[$tp,#8] @ tp[j+1]
+ adds $nlo,$nlo,$alo
+ str $nlo,[$tp],#4 @ tp[j-1]=,tp++
+ adc $nlo,$nhi,#0
+ cmp $tp,$num
+ bne .Linner
+
+ adds $nlo,$nlo,$ahi
+ mov $nhi,#0
+ ldr $tp,[$_bp] @ restore bp
+ adc $nhi,$nhi,#0
+ ldr $n0,[$_n0] @ restore n0
+ adds $nlo,$nlo,$tj
+ ldr $tj,[$_bpend] @ restore &bp[num]
+ adc $nhi,$nhi,#0
+ str $nlo,[$num] @ tp[num-1]=
+ str $nhi,[$num,#4] @ tp[num]=
+
+ cmp $tp,$tj
+ bne .Louter
+
+ ldr $rp,[$_rp] @ pull rp
+ add $num,$num,#4 @ $num to point at &tp[num]
+ sub $aj,$num,sp @ "original" num value
+ mov $tp,sp @ "rewind" $tp
+ mov $ap,$tp @ "borrow" $ap
+ sub $np,$np,$aj @ "rewind" $np to &np[0]
+
+ subs $tj,$tj,$tj @ "clear" carry flag
+.Lsub: ldr $tj,[$tp],#4
+ ldr $nj,[$np],#4
+ sbcs $tj,$tj,$nj @ tp[j]-np[j]
+ str $tj,[$rp],#4 @ rp[j]=
+ teq $tp,$num @ preserve carry
+ bne .Lsub
+ sbcs $nhi,$nhi,#0 @ upmost carry
+ mov $tp,sp @ "rewind" $tp
+ sub $rp,$rp,$aj @ "rewind" $rp
+
+ and $ap,$tp,$nhi
+ bic $np,$rp,$nhi
+ orr $ap,$ap,$np @ ap=borrow?tp:rp
+
+.Lcopy: ldr $tj,[$ap],#4 @ copy or in-place refresh
+ str sp,[$tp],#4 @ zap tp
+ str $tj,[$rp],#4
+ cmp $tp,$num
+ bne .Lcopy
+
+ add sp,$num,#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
+ bx lr @ interoperable with Thumb ISA:-)
+.size bn_mul_mont,.-bn_mul_mont
+___
+{
+sub Dlo() { shift=~m|q([1]?[0-9])|?"d".($1*2):""; }
+sub Dhi() { shift=~m|q([1]?[0-9])|?"d".($1*2+1):""; }
+
+my ($A0,$A1,$A2,$A3)=map("d$_",(0..3));
+my ($N0,$N1,$N2,$N3)=map("d$_",(4..7));
+my ($Z,$Temp)=("q4","q5");
+my ($A0xB,$A1xB,$A2xB,$A3xB,$A4xB,$A5xB,$A6xB,$A7xB)=map("q$_",(6..13));
+my ($Bi,$Ni,$M0)=map("d$_",(28..31));
+my $zero=&Dlo($Z);
+my $temp=&Dlo($Temp);
+
+my ($rptr,$aptr,$bptr,$nptr,$n0,$num)=map("r$_",(0..5));
+my ($tinptr,$toutptr,$inner,$outer)=map("r$_",(6..9));
+
+$code.=<<___;
+#if __ARM_ARCH__>=7
+.fpu neon
+
+.type bn_mul8x_mont_neon,%function
+.align 5
+bn_mul8x_mont_neon:
+ mov ip,sp
+ stmdb sp!,{r4-r11}
+ vstmdb sp!,{d8-d15} @ ABI specification says so
+ ldmia ip,{r4-r5} @ load rest of parameter block
+
+ sub $toutptr,sp,#16
+ vld1.32 {${Bi}[0]}, [$bptr,:32]!
+ sub $toutptr,$toutptr,$num,lsl#4
+ vld1.32 {$A0-$A3}, [$aptr]! @ can't specify :32 :-(
+ and $toutptr,$toutptr,#-64
+ vld1.32 {${M0}[0]}, [$n0,:32]
+ mov sp,$toutptr @ alloca
+ veor $zero,$zero,$zero
+ subs $inner,$num,#8
+ vzip.16 $Bi,$zero
+
+ vmull.u32 $A0xB,$Bi,${A0}[0]
+ vmull.u32 $A1xB,$Bi,${A0}[1]
+ vmull.u32 $A2xB,$Bi,${A1}[0]
+ vshl.i64 $temp,`&Dhi("$A0xB")`,#16
+ vmull.u32 $A3xB,$Bi,${A1}[1]
+
+ vadd.u64 $temp,$temp,`&Dlo("$A0xB")`
+ veor $zero,$zero,$zero
+ vmul.u32 $Ni,$temp,$M0
+
+ vmull.u32 $A4xB,$Bi,${A2}[0]
+ vld1.32 {$N0-$N3}, [$nptr]!
+ vmull.u32 $A5xB,$Bi,${A2}[1]
+ vmull.u32 $A6xB,$Bi,${A3}[0]
+ vzip.16 $Ni,$zero
+ vmull.u32 $A7xB,$Bi,${A3}[1]
+
+ bne .LNEON_1st
+
+ @ special case for num=8, everything is in register bank...
+
+ vmlal.u32 $A0xB,$Ni,${N0}[0]
+ sub $outer,$num,#1
+ vmlal.u32 $A1xB,$Ni,${N0}[1]
+ vmlal.u32 $A2xB,$Ni,${N1}[0]
+ vmlal.u32 $A3xB,$Ni,${N1}[1]
+
+ vmlal.u32 $A4xB,$Ni,${N2}[0]
+ vmov $Temp,$A0xB
+ vmlal.u32 $A5xB,$Ni,${N2}[1]
+ vmov $A0xB,$A1xB
+ vmlal.u32 $A6xB,$Ni,${N3}[0]
+ vmov $A1xB,$A2xB
+ vmlal.u32 $A7xB,$Ni,${N3}[1]
+ vmov $A2xB,$A3xB
+ vmov $A3xB,$A4xB
+ vshr.u64 $temp,$temp,#16
+ vmov $A4xB,$A5xB
+ vmov $A5xB,$A6xB
+ vadd.u64 $temp,$temp,`&Dhi("$Temp")`
+ vmov $A6xB,$A7xB
+ veor $A7xB,$A7xB
+ vshr.u64 $temp,$temp,#16
+
+ b .LNEON_outer8
+
+.align 4
+.LNEON_outer8:
+ vld1.32 {${Bi}[0]}, [$bptr,:32]!
+ veor $zero,$zero,$zero
+ vzip.16 $Bi,$zero
+ vadd.u64 `&Dlo("$A0xB")`,`&Dlo("$A0xB")`,$temp
+
+ vmlal.u32 $A0xB,$Bi,${A0}[0]
+ vmlal.u32 $A1xB,$Bi,${A0}[1]
+ vmlal.u32 $A2xB,$Bi,${A1}[0]
+ vshl.i64 $temp,`&Dhi("$A0xB")`,#16
+ vmlal.u32 $A3xB,$Bi,${A1}[1]
+
+ vadd.u64 $temp,$temp,`&Dlo("$A0xB")`
+ veor $zero,$zero,$zero
+ subs $outer,$outer,#1
+ vmul.u32 $Ni,$temp,$M0
+
+ vmlal.u32 $A4xB,$Bi,${A2}[0]
+ vmlal.u32 $A5xB,$Bi,${A2}[1]
+ vmlal.u32 $A6xB,$Bi,${A3}[0]
+ vzip.16 $Ni,$zero
+ vmlal.u32 $A7xB,$Bi,${A3}[1]
+
+ vmlal.u32 $A0xB,$Ni,${N0}[0]
+ vmlal.u32 $A1xB,$Ni,${N0}[1]
+ vmlal.u32 $A2xB,$Ni,${N1}[0]
+ vmlal.u32 $A3xB,$Ni,${N1}[1]
+
+ vmlal.u32 $A4xB,$Ni,${N2}[0]
+ vmov $Temp,$A0xB
+ vmlal.u32 $A5xB,$Ni,${N2}[1]
+ vmov $A0xB,$A1xB
+ vmlal.u32 $A6xB,$Ni,${N3}[0]
+ vmov $A1xB,$A2xB
+ vmlal.u32 $A7xB,$Ni,${N3}[1]
+ vmov $A2xB,$A3xB
+ vmov $A3xB,$A4xB
+ vshr.u64 $temp,$temp,#16
+ vmov $A4xB,$A5xB
+ vmov $A5xB,$A6xB
+ vadd.u64 $temp,$temp,`&Dhi("$Temp")`
+ vmov $A6xB,$A7xB
+ veor $A7xB,$A7xB
+ vshr.u64 $temp,$temp,#16
+
+ bne .LNEON_outer8
+
+ vadd.u64 `&Dlo("$A0xB")`,`&Dlo("$A0xB")`,$temp
+ mov $toutptr,sp
+ vshr.u64 $temp,`&Dlo("$A0xB")`,#16
+ mov $inner,$num
+ vadd.u64 `&Dhi("$A0xB")`,`&Dhi("$A0xB")`,$temp
+ add $tinptr,sp,#16
+ vshr.u64 $temp,`&Dhi("$A0xB")`,#16
+ vzip.16 `&Dlo("$A0xB")`,`&Dhi("$A0xB")`
+
+ b .LNEON_tail2
+
+.align 4
+.LNEON_1st:
+ vmlal.u32 $A0xB,$Ni,${N0}[0]
+ vld1.32 {$A0-$A3}, [$aptr]!
+ vmlal.u32 $A1xB,$Ni,${N0}[1]
+ subs $inner,$inner,#8
+ vmlal.u32 $A2xB,$Ni,${N1}[0]
+ vmlal.u32 $A3xB,$Ni,${N1}[1]
+
+ vmlal.u32 $A4xB,$Ni,${N2}[0]
+ vld1.32 {$N0-$N1}, [$nptr]!
+ vmlal.u32 $A5xB,$Ni,${N2}[1]
+ vst1.64 {$A0xB-$A1xB}, [$toutptr,:256]!
+ vmlal.u32 $A6xB,$Ni,${N3}[0]
+ vmlal.u32 $A7xB,$Ni,${N3}[1]
+ vst1.64 {$A2xB-$A3xB}, [$toutptr,:256]!
+
+ vmull.u32 $A0xB,$Bi,${A0}[0]
+ vld1.32 {$N2-$N3}, [$nptr]!
+ vmull.u32 $A1xB,$Bi,${A0}[1]
+ vst1.64 {$A4xB-$A5xB}, [$toutptr,:256]!
+ vmull.u32 $A2xB,$Bi,${A1}[0]
+ vmull.u32 $A3xB,$Bi,${A1}[1]
+ vst1.64 {$A6xB-$A7xB}, [$toutptr,:256]!
+
+ vmull.u32 $A4xB,$Bi,${A2}[0]
+ vmull.u32 $A5xB,$Bi,${A2}[1]
+ vmull.u32 $A6xB,$Bi,${A3}[0]
+ vmull.u32 $A7xB,$Bi,${A3}[1]
+
+ bne .LNEON_1st
+
+ vmlal.u32 $A0xB,$Ni,${N0}[0]
+ add $tinptr,sp,#16
+ vmlal.u32 $A1xB,$Ni,${N0}[1]
+ sub $aptr,$aptr,$num,lsl#2 @ rewind $aptr
+ vmlal.u32 $A2xB,$Ni,${N1}[0]
+ vld1.64 {$Temp}, [sp,:128]
+ vmlal.u32 $A3xB,$Ni,${N1}[1]
+ sub $outer,$num,#1
+
+ vmlal.u32 $A4xB,$Ni,${N2}[0]
+ vst1.64 {$A0xB-$A1xB}, [$toutptr,:256]!
+ vmlal.u32 $A5xB,$Ni,${N2}[1]
+ vshr.u64 $temp,$temp,#16
+ vld1.64 {$A0xB}, [$tinptr, :128]!
+ vmlal.u32 $A6xB,$Ni,${N3}[0]
+ vst1.64 {$A2xB-$A3xB}, [$toutptr,:256]!
+ vmlal.u32 $A7xB,$Ni,${N3}[1]
+
+ vst1.64 {$A4xB-$A5xB}, [$toutptr,:256]!
+ vadd.u64 $temp,$temp,`&Dhi("$Temp")`
+ veor $Z,$Z,$Z
+ vst1.64 {$A6xB-$A7xB}, [$toutptr,:256]!
+ vld1.64 {$A1xB-$A2xB}, [$tinptr, :256]!
+ vst1.64 {$Z}, [$toutptr,:128]
+ vshr.u64 $temp,$temp,#16
+
+ b .LNEON_outer
+
+.align 4
+.LNEON_outer:
+ vld1.32 {${Bi}[0]}, [$bptr,:32]!
+ sub $nptr,$nptr,$num,lsl#2 @ rewind $nptr
+ vld1.32 {$A0-$A3}, [$aptr]!
+ veor $zero,$zero,$zero
+ mov $toutptr,sp
+ vzip.16 $Bi,$zero
+ sub $inner,$num,#8
+ vadd.u64 `&Dlo("$A0xB")`,`&Dlo("$A0xB")`,$temp
+
+ vmlal.u32 $A0xB,$Bi,${A0}[0]
+ vld1.64 {$A3xB-$A4xB},[$tinptr,:256]!
+ vmlal.u32 $A1xB,$Bi,${A0}[1]
+ vmlal.u32 $A2xB,$Bi,${A1}[0]
+ vld1.64 {$A5xB-$A6xB},[$tinptr,:256]!
+ vmlal.u32 $A3xB,$Bi,${A1}[1]
+
+ vshl.i64 $temp,`&Dhi("$A0xB")`,#16
+ veor $zero,$zero,$zero
+ vadd.u64 $temp,$temp,`&Dlo("$A0xB")`
+ vld1.64 {$A7xB},[$tinptr,:128]!
+ vmul.u32 $Ni,$temp,$M0
+
+ vmlal.u32 $A4xB,$Bi,${A2}[0]
+ vld1.32 {$N0-$N3}, [$nptr]!
+ vmlal.u32 $A5xB,$Bi,${A2}[1]
+ vmlal.u32 $A6xB,$Bi,${A3}[0]
+ vzip.16 $Ni,$zero
+ vmlal.u32 $A7xB,$Bi,${A3}[1]
+
+.LNEON_inner:
+ vmlal.u32 $A0xB,$Ni,${N0}[0]
+ vld1.32 {$A0-$A3}, [$aptr]!
+ vmlal.u32 $A1xB,$Ni,${N0}[1]
+ subs $inner,$inner,#8
+ vmlal.u32 $A2xB,$Ni,${N1}[0]
+ vmlal.u32 $A3xB,$Ni,${N1}[1]
+ vst1.64 {$A0xB-$A1xB}, [$toutptr,:256]!
+
+ vmlal.u32 $A4xB,$Ni,${N2}[0]
+ vld1.64 {$A0xB}, [$tinptr, :128]!
+ vmlal.u32 $A5xB,$Ni,${N2}[1]
+ vst1.64 {$A2xB-$A3xB}, [$toutptr,:256]!
+ vmlal.u32 $A6xB,$Ni,${N3}[0]
+ vld1.64 {$A1xB-$A2xB}, [$tinptr, :256]!
+ vmlal.u32 $A7xB,$Ni,${N3}[1]
+ vst1.64 {$A4xB-$A5xB}, [$toutptr,:256]!
+
+ vmlal.u32 $A0xB,$Bi,${A0}[0]
+ vld1.64 {$A3xB-$A4xB}, [$tinptr, :256]!
+ vmlal.u32 $A1xB,$Bi,${A0}[1]
+ vst1.64 {$A6xB-$A7xB}, [$toutptr,:256]!
+ vmlal.u32 $A2xB,$Bi,${A1}[0]
+ vld1.64 {$A5xB-$A6xB}, [$tinptr, :256]!
+ vmlal.u32 $A3xB,$Bi,${A1}[1]
+ vld1.32 {$N0-$N3}, [$nptr]!
+
+ vmlal.u32 $A4xB,$Bi,${A2}[0]
+ vld1.64 {$A7xB}, [$tinptr, :128]!
+ vmlal.u32 $A5xB,$Bi,${A2}[1]
+ vmlal.u32 $A6xB,$Bi,${A3}[0]
+ vmlal.u32 $A7xB,$Bi,${A3}[1]
+
+ bne .LNEON_inner
+
+ vmlal.u32 $A0xB,$Ni,${N0}[0]
+ add $tinptr,sp,#16
+ vmlal.u32 $A1xB,$Ni,${N0}[1]
+ sub $aptr,$aptr,$num,lsl#2 @ rewind $aptr
+ vmlal.u32 $A2xB,$Ni,${N1}[0]
+ vld1.64 {$Temp}, [sp,:128]
+ vmlal.u32 $A3xB,$Ni,${N1}[1]
+ subs $outer,$outer,#1
+
+ vmlal.u32 $A4xB,$Ni,${N2}[0]
+ vst1.64 {$A0xB-$A1xB}, [$toutptr,:256]!
+ vmlal.u32 $A5xB,$Ni,${N2}[1]
+ vld1.64 {$A0xB}, [$tinptr, :128]!
+ vshr.u64 $temp,$temp,#16
+ vst1.64 {$A2xB-$A3xB}, [$toutptr,:256]!
+ vmlal.u32 $A6xB,$Ni,${N3}[0]
+ vld1.64 {$A1xB-$A2xB}, [$tinptr, :256]!
+ vmlal.u32 $A7xB,$Ni,${N3}[1]
+
+ vst1.64 {$A4xB-$A5xB}, [$toutptr,:256]!
+ vadd.u64 $temp,$temp,`&Dhi("$Temp")`
+ vst1.64 {$A6xB-$A7xB}, [$toutptr,:256]!
+ vshr.u64 $temp,$temp,#16
+
+ bne .LNEON_outer
+
+ mov $toutptr,sp
+ mov $inner,$num
+
+.LNEON_tail:
+ vadd.u64 `&Dlo("$A0xB")`,`&Dlo("$A0xB")`,$temp
+ vld1.64 {$A3xB-$A4xB}, [$tinptr, :256]!
+ vshr.u64 $temp,`&Dlo("$A0xB")`,#16
+ vadd.u64 `&Dhi("$A0xB")`,`&Dhi("$A0xB")`,$temp
+ vld1.64 {$A5xB-$A6xB}, [$tinptr, :256]!
+ vshr.u64 $temp,`&Dhi("$A0xB")`,#16
+ vld1.64 {$A7xB}, [$tinptr, :128]!
+ vzip.16 `&Dlo("$A0xB")`,`&Dhi("$A0xB")`
+
+.LNEON_tail2:
+ vadd.u64 `&Dlo("$A1xB")`,`&Dlo("$A1xB")`,$temp
+ vst1.32 {`&Dlo("$A0xB")`[0]}, [$toutptr, :32]!
+ vshr.u64 $temp,`&Dlo("$A1xB")`,#16
+ vadd.u64 `&Dhi("$A1xB")`,`&Dhi("$A1xB")`,$temp
+ vshr.u64 $temp,`&Dhi("$A1xB")`,#16
+ vzip.16 `&Dlo("$A1xB")`,`&Dhi("$A1xB")`
+
+ vadd.u64 `&Dlo("$A2xB")`,`&Dlo("$A2xB")`,$temp
+ vst1.32 {`&Dlo("$A1xB")`[0]}, [$toutptr, :32]!
+ vshr.u64 $temp,`&Dlo("$A2xB")`,#16
+ vadd.u64 `&Dhi("$A2xB")`,`&Dhi("$A2xB")`,$temp
+ vshr.u64 $temp,`&Dhi("$A2xB")`,#16
+ vzip.16 `&Dlo("$A2xB")`,`&Dhi("$A2xB")`
+
+ vadd.u64 `&Dlo("$A3xB")`,`&Dlo("$A3xB")`,$temp
+ vst1.32 {`&Dlo("$A2xB")`[0]}, [$toutptr, :32]!
+ vshr.u64 $temp,`&Dlo("$A3xB")`,#16
+ vadd.u64 `&Dhi("$A3xB")`,`&Dhi("$A3xB")`,$temp
+ vshr.u64 $temp,`&Dhi("$A3xB")`,#16
+ vzip.16 `&Dlo("$A3xB")`,`&Dhi("$A3xB")`
+
+ vadd.u64 `&Dlo("$A4xB")`,`&Dlo("$A4xB")`,$temp
+ vst1.32 {`&Dlo("$A3xB")`[0]}, [$toutptr, :32]!
+ vshr.u64 $temp,`&Dlo("$A4xB")`,#16
+ vadd.u64 `&Dhi("$A4xB")`,`&Dhi("$A4xB")`,$temp
+ vshr.u64 $temp,`&Dhi("$A4xB")`,#16
+ vzip.16 `&Dlo("$A4xB")`,`&Dhi("$A4xB")`
+
+ vadd.u64 `&Dlo("$A5xB")`,`&Dlo("$A5xB")`,$temp
+ vst1.32 {`&Dlo("$A4xB")`[0]}, [$toutptr, :32]!
+ vshr.u64 $temp,`&Dlo("$A5xB")`,#16
+ vadd.u64 `&Dhi("$A5xB")`,`&Dhi("$A5xB")`,$temp
+ vshr.u64 $temp,`&Dhi("$A5xB")`,#16
+ vzip.16 `&Dlo("$A5xB")`,`&Dhi("$A5xB")`
+
+ vadd.u64 `&Dlo("$A6xB")`,`&Dlo("$A6xB")`,$temp
+ vst1.32 {`&Dlo("$A5xB")`[0]}, [$toutptr, :32]!
+ vshr.u64 $temp,`&Dlo("$A6xB")`,#16
+ vadd.u64 `&Dhi("$A6xB")`,`&Dhi("$A6xB")`,$temp
+ vld1.64 {$A0xB}, [$tinptr, :128]!
+ vshr.u64 $temp,`&Dhi("$A6xB")`,#16
+ vzip.16 `&Dlo("$A6xB")`,`&Dhi("$A6xB")`
+
+ vadd.u64 `&Dlo("$A7xB")`,`&Dlo("$A7xB")`,$temp
+ vst1.32 {`&Dlo("$A6xB")`[0]}, [$toutptr, :32]!
+ vshr.u64 $temp,`&Dlo("$A7xB")`,#16
+ vadd.u64 `&Dhi("$A7xB")`,`&Dhi("$A7xB")`,$temp
+ vld1.64 {$A1xB-$A2xB}, [$tinptr, :256]!
+ vshr.u64 $temp,`&Dhi("$A7xB")`,#16
+ vzip.16 `&Dlo("$A7xB")`,`&Dhi("$A7xB")`
+ subs $inner,$inner,#8
+ vst1.32 {`&Dlo("$A7xB")`[0]}, [$toutptr, :32]!
+
+ bne .LNEON_tail
+
+ vst1.32 {${temp}[0]}, [$toutptr, :32] @ top-most bit
+ sub $nptr,$nptr,$num,lsl#2 @ rewind $nptr
+ subs $aptr,sp,#0 @ clear carry flag
+ add $bptr,sp,$num,lsl#2
+
+.LNEON_sub:
+ ldmia $aptr!, {r4-r7}
+ ldmia $nptr!, {r8-r11}
+ sbcs r8, r4,r8
+ sbcs r9, r5,r9
+ sbcs r10,r6,r10
+ sbcs r11,r7,r11
+ teq $aptr,$bptr @ preserves carry
+ stmia $rptr!, {r8-r11}
+ bne .LNEON_sub
+
+ ldr r10, [$aptr] @ load top-most bit
+ veor q0,q0,q0
+ sub r11,$bptr,sp @ this is num*4
+ veor q1,q1,q1
+ mov $aptr,sp
+ sub $rptr,$rptr,r11 @ rewind $rptr
+ mov $nptr,$bptr @ second 3/4th of frame
+ sbcs r10,r10,#0 @ result is carry flag
+
+.LNEON_copy_n_zap:
+ ldmia $aptr!, {r4-r7}
+ ldmia $rptr, {r8-r11}
+ movcc r8, r4
+ vst1.64 {q0-q1}, [$nptr,:256]! @ wipe
+ movcc r9, r5
+ movcc r10,r6
+ vst1.64 {q0-q1}, [$nptr,:256]! @ wipe
+ movcc r11,r7
+ ldmia $aptr, {r4-r7}
+ stmia $rptr!, {r8-r11}
+ sub $aptr,$aptr,#16
+ ldmia $rptr, {r8-r11}
+ movcc r8, r4
+ vst1.64 {q0-q1}, [$aptr,:256]! @ wipe
+ movcc r9, r5
+ movcc r10,r6
+ vst1.64 {q0-q1}, [$nptr,:256]! @ wipe
+ movcc r11,r7
+ teq $aptr,$bptr @ preserves carry
+ stmia $rptr!, {r8-r11}
+ bne .LNEON_copy_n_zap
+
+ sub sp,ip,#96
+ vldmia sp!,{d8-d15}
+ ldmia sp!,{r4-r11}
+ bx lr
+.size bn_mul8x_mont_neon,.-bn_mul8x_mont_neon
+#endif
+___
+}
+$code.=<<___;
+.asciz "Montgomery multiplication for ARMv4/NEON, CRYPTOGAMS by <appro\@openssl.org>"
+.align 2
+#if __ARM_ARCH__>=7
+.comm OPENSSL_armcap_P,4,4
+#endif
+___
+
+$code =~ s/\`([^\`]*)\`/eval $1/gem;
+$code =~ s/\bbx\s+lr\b/.word\t0xe12fff1e/gm; # make it possible to compile with -march=armv4
+print $code;
+close STDOUT;
diff --git a/src/crypto/bn/asm/bn-586.pl b/src/crypto/bn/asm/bn-586.pl
new file mode 100644
index 0000000..26d9bcb
--- /dev/null
+++ b/src/crypto/bn/asm/bn-586.pl
@@ -0,0 +1,774 @@
+#!/usr/bin/env perl
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+push(@INC,"${dir}","${dir}../../perlasm");
+require "x86asm.pl";
+
+&asm_init($ARGV[0],$0);
+
+$sse2=0;
+for (@ARGV) { $sse2=1 if (/-DOPENSSL_IA32_SSE2/); }
+
+&external_label("OPENSSL_ia32cap_P") if ($sse2);
+
+&bn_mul_add_words("bn_mul_add_words");
+&bn_mul_words("bn_mul_words");
+&bn_sqr_words("bn_sqr_words");
+&bn_div_words("bn_div_words");
+&bn_add_words("bn_add_words");
+&bn_sub_words("bn_sub_words");
+&bn_sub_part_words("bn_sub_part_words");
+
+&asm_finish();
+
+sub bn_mul_add_words
+ {
+ local($name)=@_;
+
+ &function_begin_B($name,$sse2?"EXTRN\t_OPENSSL_ia32cap_P:DWORD":"");
+
+ $r="eax";
+ $a="edx";
+ $c="ecx";
+
+ if ($sse2) {
+ &picmeup("eax","OPENSSL_ia32cap_P");
+ &bt(&DWP(0,"eax"),26);
+ &jnc(&label("maw_non_sse2"));
+
+ &mov($r,&wparam(0));
+ &mov($a,&wparam(1));
+ &mov($c,&wparam(2));
+ &movd("mm0",&wparam(3)); # mm0 = w
+ &pxor("mm1","mm1"); # mm1 = carry_in
+ &jmp(&label("maw_sse2_entry"));
+
+ &set_label("maw_sse2_unrolled",16);
+ &movd("mm3",&DWP(0,$r,"",0)); # mm3 = r[0]
+ &paddq("mm1","mm3"); # mm1 = carry_in + r[0]
+ &movd("mm2",&DWP(0,$a,"",0)); # mm2 = a[0]
+ &pmuludq("mm2","mm0"); # mm2 = w*a[0]
+ &movd("mm4",&DWP(4,$a,"",0)); # mm4 = a[1]
+ &pmuludq("mm4","mm0"); # mm4 = w*a[1]
+ &movd("mm6",&DWP(8,$a,"",0)); # mm6 = a[2]
+ &pmuludq("mm6","mm0"); # mm6 = w*a[2]
+ &movd("mm7",&DWP(12,$a,"",0)); # mm7 = a[3]
+ &pmuludq("mm7","mm0"); # mm7 = w*a[3]
+ &paddq("mm1","mm2"); # mm1 = carry_in + r[0] + w*a[0]
+ &movd("mm3",&DWP(4,$r,"",0)); # mm3 = r[1]
+ &paddq("mm3","mm4"); # mm3 = r[1] + w*a[1]
+ &movd("mm5",&DWP(8,$r,"",0)); # mm5 = r[2]
+ &paddq("mm5","mm6"); # mm5 = r[2] + w*a[2]
+ &movd("mm4",&DWP(12,$r,"",0)); # mm4 = r[3]
+ &paddq("mm7","mm4"); # mm7 = r[3] + w*a[3]
+ &movd(&DWP(0,$r,"",0),"mm1");
+ &movd("mm2",&DWP(16,$a,"",0)); # mm2 = a[4]
+ &pmuludq("mm2","mm0"); # mm2 = w*a[4]
+ &psrlq("mm1",32); # mm1 = carry0
+ &movd("mm4",&DWP(20,$a,"",0)); # mm4 = a[5]
+ &pmuludq("mm4","mm0"); # mm4 = w*a[5]
+ &paddq("mm1","mm3"); # mm1 = carry0 + r[1] + w*a[1]
+ &movd("mm6",&DWP(24,$a,"",0)); # mm6 = a[6]
+ &pmuludq("mm6","mm0"); # mm6 = w*a[6]
+ &movd(&DWP(4,$r,"",0),"mm1");
+ &psrlq("mm1",32); # mm1 = carry1
+ &movd("mm3",&DWP(28,$a,"",0)); # mm3 = a[7]
+ &add($a,32);
+ &pmuludq("mm3","mm0"); # mm3 = w*a[7]
+ &paddq("mm1","mm5"); # mm1 = carry1 + r[2] + w*a[2]
+ &movd("mm5",&DWP(16,$r,"",0)); # mm5 = r[4]
+ &paddq("mm2","mm5"); # mm2 = r[4] + w*a[4]
+ &movd(&DWP(8,$r,"",0),"mm1");
+ &psrlq("mm1",32); # mm1 = carry2
+ &paddq("mm1","mm7"); # mm1 = carry2 + r[3] + w*a[3]
+ &movd("mm5",&DWP(20,$r,"",0)); # mm5 = r[5]
+ &paddq("mm4","mm5"); # mm4 = r[5] + w*a[5]
+ &movd(&DWP(12,$r,"",0),"mm1");
+ &psrlq("mm1",32); # mm1 = carry3
+ &paddq("mm1","mm2"); # mm1 = carry3 + r[4] + w*a[4]
+ &movd("mm5",&DWP(24,$r,"",0)); # mm5 = r[6]
+ &paddq("mm6","mm5"); # mm6 = r[6] + w*a[6]
+ &movd(&DWP(16,$r,"",0),"mm1");
+ &psrlq("mm1",32); # mm1 = carry4
+ &paddq("mm1","mm4"); # mm1 = carry4 + r[5] + w*a[5]
+ &movd("mm5",&DWP(28,$r,"",0)); # mm5 = r[7]
+ &paddq("mm3","mm5"); # mm3 = r[7] + w*a[7]
+ &movd(&DWP(20,$r,"",0),"mm1");
+ &psrlq("mm1",32); # mm1 = carry5
+ &paddq("mm1","mm6"); # mm1 = carry5 + r[6] + w*a[6]
+ &movd(&DWP(24,$r,"",0),"mm1");
+ &psrlq("mm1",32); # mm1 = carry6
+ &paddq("mm1","mm3"); # mm1 = carry6 + r[7] + w*a[7]
+ &movd(&DWP(28,$r,"",0),"mm1");
+ &lea($r,&DWP(32,$r));
+ &psrlq("mm1",32); # mm1 = carry_out
+
+ &sub($c,8);
+ &jz(&label("maw_sse2_exit"));
+ &set_label("maw_sse2_entry");
+ &test($c,0xfffffff8);
+ &jnz(&label("maw_sse2_unrolled"));
+
+ &set_label("maw_sse2_loop",4);
+ &movd("mm2",&DWP(0,$a)); # mm2 = a[i]
+ &movd("mm3",&DWP(0,$r)); # mm3 = r[i]
+ &pmuludq("mm2","mm0"); # a[i] *= w
+ &lea($a,&DWP(4,$a));
+ &paddq("mm1","mm3"); # carry += r[i]
+ &paddq("mm1","mm2"); # carry += a[i]*w
+ &movd(&DWP(0,$r),"mm1"); # r[i] = carry_low
+ &sub($c,1);
+ &psrlq("mm1",32); # carry = carry_high
+ &lea($r,&DWP(4,$r));
+ &jnz(&label("maw_sse2_loop"));
+ &set_label("maw_sse2_exit");
+ &movd("eax","mm1"); # c = carry_out
+ &emms();
+ &ret();
+
+ &set_label("maw_non_sse2",16);
+ }
+
+ # function_begin prologue
+ &push("ebp");
+ &push("ebx");
+ &push("esi");
+ &push("edi");
+
+ &comment("");
+ $Low="eax";
+ $High="edx";
+ $a="ebx";
+ $w="ebp";
+ $r="edi";
+ $c="esi";
+
+ &xor($c,$c); # clear carry
+ &mov($r,&wparam(0)); #
+
+ &mov("ecx",&wparam(2)); #
+ &mov($a,&wparam(1)); #
+
+ &and("ecx",0xfffffff8); # num / 8
+ &mov($w,&wparam(3)); #
+
+ &push("ecx"); # Up the stack for a tmp variable
+
+ &jz(&label("maw_finish"));
+
+ &set_label("maw_loop",16);
+
+ for ($i=0; $i<32; $i+=4)
+ {
+ &comment("Round $i");
+
+ &mov("eax",&DWP($i,$a)); # *a
+ &mul($w); # *a * w
+ &add("eax",$c); # L(t)+= c
+ &adc("edx",0); # H(t)+=carry
+ &add("eax",&DWP($i,$r)); # L(t)+= *r
+ &adc("edx",0); # H(t)+=carry
+ &mov(&DWP($i,$r),"eax"); # *r= L(t);
+ &mov($c,"edx"); # c= H(t);
+ }
+
+ &comment("");
+ &sub("ecx",8);
+ &lea($a,&DWP(32,$a));
+ &lea($r,&DWP(32,$r));
+ &jnz(&label("maw_loop"));
+
+ &set_label("maw_finish",0);
+ &mov("ecx",&wparam(2)); # get num
+ &and("ecx",7);
+ &jnz(&label("maw_finish2")); # helps branch prediction
+ &jmp(&label("maw_end"));
+
+ &set_label("maw_finish2",1);
+ for ($i=0; $i<7; $i++)
+ {
+ &comment("Tail Round $i");
+ &mov("eax",&DWP($i*4,$a)); # *a
+ &mul($w); # *a * w
+ &add("eax",$c); # L(t)+=c
+ &adc("edx",0); # H(t)+=carry
+ &add("eax",&DWP($i*4,$r)); # L(t)+= *r
+ &adc("edx",0); # H(t)+=carry
+ &dec("ecx") if ($i != 7-1);
+ &mov(&DWP($i*4,$r),"eax"); # *r= L(t);
+ &mov($c,"edx"); # c= H(t);
+ &jz(&label("maw_end")) if ($i != 7-1);
+ }
+ &set_label("maw_end",0);
+ &mov("eax",$c);
+
+ &pop("ecx"); # clear variable from
+
+ &function_end($name);
+ }
+
+sub bn_mul_words
+ {
+ local($name)=@_;
+
+ &function_begin_B($name,$sse2?"EXTRN\t_OPENSSL_ia32cap_P:DWORD":"");
+
+ $r="eax";
+ $a="edx";
+ $c="ecx";
+
+ if ($sse2) {
+ &picmeup("eax","OPENSSL_ia32cap_P");
+ &bt(&DWP(0,"eax"),26);
+ &jnc(&label("mw_non_sse2"));
+
+ &mov($r,&wparam(0));
+ &mov($a,&wparam(1));
+ &mov($c,&wparam(2));
+ &movd("mm0",&wparam(3)); # mm0 = w
+ &pxor("mm1","mm1"); # mm1 = carry = 0
+
+ &set_label("mw_sse2_loop",16);
+ &movd("mm2",&DWP(0,$a)); # mm2 = a[i]
+ &pmuludq("mm2","mm0"); # a[i] *= w
+ &lea($a,&DWP(4,$a));
+ &paddq("mm1","mm2"); # carry += a[i]*w
+ &movd(&DWP(0,$r),"mm1"); # r[i] = carry_low
+ &sub($c,1);
+ &psrlq("mm1",32); # carry = carry_high
+ &lea($r,&DWP(4,$r));
+ &jnz(&label("mw_sse2_loop"));
+
+ &movd("eax","mm1"); # return carry
+ &emms();
+ &ret();
+ &set_label("mw_non_sse2",16);
+ }
+
+ # function_begin prologue
+ &push("ebp");
+ &push("ebx");
+ &push("esi");
+ &push("edi");
+
+ &comment("");
+ $Low="eax";
+ $High="edx";
+ $a="ebx";
+ $w="ecx";
+ $r="edi";
+ $c="esi";
+ $num="ebp";
+
+ &xor($c,$c); # clear carry
+ &mov($r,&wparam(0)); #
+ &mov($a,&wparam(1)); #
+ &mov($num,&wparam(2)); #
+ &mov($w,&wparam(3)); #
+
+ &and($num,0xfffffff8); # num / 8
+ &jz(&label("mw_finish"));
+
+ &set_label("mw_loop",0);
+ for ($i=0; $i<32; $i+=4)
+ {
+ &comment("Round $i");
+
+ &mov("eax",&DWP($i,$a,"",0)); # *a
+ &mul($w); # *a * w
+ &add("eax",$c); # L(t)+=c
+ # XXX
+
+ &adc("edx",0); # H(t)+=carry
+ &mov(&DWP($i,$r,"",0),"eax"); # *r= L(t);
+
+ &mov($c,"edx"); # c= H(t);
+ }
+
+ &comment("");
+ &add($a,32);
+ &add($r,32);
+ &sub($num,8);
+ &jz(&label("mw_finish"));
+ &jmp(&label("mw_loop"));
+
+ &set_label("mw_finish",0);
+ &mov($num,&wparam(2)); # get num
+ &and($num,7);
+ &jnz(&label("mw_finish2"));
+ &jmp(&label("mw_end"));
+
+ &set_label("mw_finish2",1);
+ for ($i=0; $i<7; $i++)
+ {
+ &comment("Tail Round $i");
+ &mov("eax",&DWP($i*4,$a,"",0));# *a
+ &mul($w); # *a * w
+ &add("eax",$c); # L(t)+=c
+ # XXX
+ &adc("edx",0); # H(t)+=carry
+ &mov(&DWP($i*4,$r,"",0),"eax");# *r= L(t);
+ &mov($c,"edx"); # c= H(t);
+ &dec($num) if ($i != 7-1);
+ &jz(&label("mw_end")) if ($i != 7-1);
+ }
+ &set_label("mw_end",0);
+ &mov("eax",$c);
+
+ &function_end($name);
+ }
+
+sub bn_sqr_words
+ {
+ local($name)=@_;
+
+ &function_begin_B($name,$sse2?"EXTRN\t_OPENSSL_ia32cap_P:DWORD":"");
+
+ $r="eax";
+ $a="edx";
+ $c="ecx";
+
+ if ($sse2) {
+ &picmeup("eax","OPENSSL_ia32cap_P");
+ &bt(&DWP(0,"eax"),26);
+ &jnc(&label("sqr_non_sse2"));
+
+ &mov($r,&wparam(0));
+ &mov($a,&wparam(1));
+ &mov($c,&wparam(2));
+
+ &set_label("sqr_sse2_loop",16);
+ &movd("mm0",&DWP(0,$a)); # mm0 = a[i]
+ &pmuludq("mm0","mm0"); # a[i] *= a[i]
+ &lea($a,&DWP(4,$a)); # a++
+ &movq(&QWP(0,$r),"mm0"); # r[i] = a[i]*a[i]
+ &sub($c,1);
+ &lea($r,&DWP(8,$r)); # r += 2
+ &jnz(&label("sqr_sse2_loop"));
+
+ &emms();
+ &ret();
+ &set_label("sqr_non_sse2",16);
+ }
+
+ # function_begin prologue
+ &push("ebp");
+ &push("ebx");
+ &push("esi");
+ &push("edi");
+
+ &comment("");
+ $r="esi";
+ $a="edi";
+ $num="ebx";
+
+ &mov($r,&wparam(0)); #
+ &mov($a,&wparam(1)); #
+ &mov($num,&wparam(2)); #
+
+ &and($num,0xfffffff8); # num / 8
+ &jz(&label("sw_finish"));
+
+ &set_label("sw_loop",0);
+ for ($i=0; $i<32; $i+=4)
+ {
+ &comment("Round $i");
+ &mov("eax",&DWP($i,$a,"",0)); # *a
+ # XXX
+ &mul("eax"); # *a * *a
+ &mov(&DWP($i*2,$r,"",0),"eax"); #
+ &mov(&DWP($i*2+4,$r,"",0),"edx");#
+ }
+
+ &comment("");
+ &add($a,32);
+ &add($r,64);
+ &sub($num,8);
+ &jnz(&label("sw_loop"));
+
+ &set_label("sw_finish",0);
+ &mov($num,&wparam(2)); # get num
+ &and($num,7);
+ &jz(&label("sw_end"));
+
+ for ($i=0; $i<7; $i++)
+ {
+ &comment("Tail Round $i");
+ &mov("eax",&DWP($i*4,$a,"",0)); # *a
+ # XXX
+ &mul("eax"); # *a * *a
+ &mov(&DWP($i*8,$r,"",0),"eax"); #
+ &dec($num) if ($i != 7-1);
+ &mov(&DWP($i*8+4,$r,"",0),"edx");
+ &jz(&label("sw_end")) if ($i != 7-1);
+ }
+ &set_label("sw_end",0);
+
+ &function_end($name);
+ }
+
+sub bn_div_words
+ {
+ local($name)=@_;
+
+ &function_begin_B($name,"");
+ &mov("edx",&wparam(0)); #
+ &mov("eax",&wparam(1)); #
+ &mov("ecx",&wparam(2)); #
+ &div("ecx");
+ &ret();
+ &function_end_B($name);
+ }
+
+sub bn_add_words
+ {
+ local($name)=@_;
+
+ &function_begin($name,"");
+
+ &comment("");
+ $a="esi";
+ $b="edi";
+ $c="eax";
+ $r="ebx";
+ $tmp1="ecx";
+ $tmp2="edx";
+ $num="ebp";
+
+ &mov($r,&wparam(0)); # get r
+ &mov($a,&wparam(1)); # get a
+ &mov($b,&wparam(2)); # get b
+ &mov($num,&wparam(3)); # get num
+ &xor($c,$c); # clear carry
+ &and($num,0xfffffff8); # num / 8
+
+ &jz(&label("aw_finish"));
+
+ &set_label("aw_loop",0);
+ for ($i=0; $i<8; $i++)
+ {
+ &comment("Round $i");
+
+ &mov($tmp1,&DWP($i*4,$a,"",0)); # *a
+ &mov($tmp2,&DWP($i*4,$b,"",0)); # *b
+ &add($tmp1,$c);
+ &mov($c,0);
+ &adc($c,$c);
+ &add($tmp1,$tmp2);
+ &adc($c,0);
+ &mov(&DWP($i*4,$r,"",0),$tmp1); # *r
+ }
+
+ &comment("");
+ &add($a,32);
+ &add($b,32);
+ &add($r,32);
+ &sub($num,8);
+ &jnz(&label("aw_loop"));
+
+ &set_label("aw_finish",0);
+ &mov($num,&wparam(3)); # get num
+ &and($num,7);
+ &jz(&label("aw_end"));
+
+ for ($i=0; $i<7; $i++)
+ {
+ &comment("Tail Round $i");
+ &mov($tmp1,&DWP($i*4,$a,"",0)); # *a
+ &mov($tmp2,&DWP($i*4,$b,"",0));# *b
+ &add($tmp1,$c);
+ &mov($c,0);
+ &adc($c,$c);
+ &add($tmp1,$tmp2);
+ &adc($c,0);
+ &dec($num) if ($i != 6);
+ &mov(&DWP($i*4,$r,"",0),$tmp1); # *r
+ &jz(&label("aw_end")) if ($i != 6);
+ }
+ &set_label("aw_end",0);
+
+# &mov("eax",$c); # $c is "eax"
+
+ &function_end($name);
+ }
+
+sub bn_sub_words
+ {
+ local($name)=@_;
+
+ &function_begin($name,"");
+
+ &comment("");
+ $a="esi";
+ $b="edi";
+ $c="eax";
+ $r="ebx";
+ $tmp1="ecx";
+ $tmp2="edx";
+ $num="ebp";
+
+ &mov($r,&wparam(0)); # get r
+ &mov($a,&wparam(1)); # get a
+ &mov($b,&wparam(2)); # get b
+ &mov($num,&wparam(3)); # get num
+ &xor($c,$c); # clear carry
+ &and($num,0xfffffff8); # num / 8
+
+ &jz(&label("aw_finish"));
+
+ &set_label("aw_loop",0);
+ for ($i=0; $i<8; $i++)
+ {
+ &comment("Round $i");
+
+ &mov($tmp1,&DWP($i*4,$a,"",0)); # *a
+ &mov($tmp2,&DWP($i*4,$b,"",0)); # *b
+ &sub($tmp1,$c);
+ &mov($c,0);
+ &adc($c,$c);
+ &sub($tmp1,$tmp2);
+ &adc($c,0);
+ &mov(&DWP($i*4,$r,"",0),$tmp1); # *r
+ }
+
+ &comment("");
+ &add($a,32);
+ &add($b,32);
+ &add($r,32);
+ &sub($num,8);
+ &jnz(&label("aw_loop"));
+
+ &set_label("aw_finish",0);
+ &mov($num,&wparam(3)); # get num
+ &and($num,7);
+ &jz(&label("aw_end"));
+
+ for ($i=0; $i<7; $i++)
+ {
+ &comment("Tail Round $i");
+ &mov($tmp1,&DWP($i*4,$a,"",0)); # *a
+ &mov($tmp2,&DWP($i*4,$b,"",0));# *b
+ &sub($tmp1,$c);
+ &mov($c,0);
+ &adc($c,$c);
+ &sub($tmp1,$tmp2);
+ &adc($c,0);
+ &dec($num) if ($i != 6);
+ &mov(&DWP($i*4,$r,"",0),$tmp1); # *r
+ &jz(&label("aw_end")) if ($i != 6);
+ }
+ &set_label("aw_end",0);
+
+# &mov("eax",$c); # $c is "eax"
+
+ &function_end($name);
+ }
+
+sub bn_sub_part_words
+ {
+ local($name)=@_;
+
+ &function_begin($name,"");
+
+ &comment("");
+ $a="esi";
+ $b="edi";
+ $c="eax";
+ $r="ebx";
+ $tmp1="ecx";
+ $tmp2="edx";
+ $num="ebp";
+
+ &mov($r,&wparam(0)); # get r
+ &mov($a,&wparam(1)); # get a
+ &mov($b,&wparam(2)); # get b
+ &mov($num,&wparam(3)); # get num
+ &xor($c,$c); # clear carry
+ &and($num,0xfffffff8); # num / 8
+
+ &jz(&label("aw_finish"));
+
+ &set_label("aw_loop",0);
+ for ($i=0; $i<8; $i++)
+ {
+ &comment("Round $i");
+
+ &mov($tmp1,&DWP($i*4,$a,"",0)); # *a
+ &mov($tmp2,&DWP($i*4,$b,"",0)); # *b
+ &sub($tmp1,$c);
+ &mov($c,0);
+ &adc($c,$c);
+ &sub($tmp1,$tmp2);
+ &adc($c,0);
+ &mov(&DWP($i*4,$r,"",0),$tmp1); # *r
+ }
+
+ &comment("");
+ &add($a,32);
+ &add($b,32);
+ &add($r,32);
+ &sub($num,8);
+ &jnz(&label("aw_loop"));
+
+ &set_label("aw_finish",0);
+ &mov($num,&wparam(3)); # get num
+ &and($num,7);
+ &jz(&label("aw_end"));
+
+ for ($i=0; $i<7; $i++)
+ {
+ &comment("Tail Round $i");
+ &mov($tmp1,&DWP(0,$a,"",0)); # *a
+ &mov($tmp2,&DWP(0,$b,"",0));# *b
+ &sub($tmp1,$c);
+ &mov($c,0);
+ &adc($c,$c);
+ &sub($tmp1,$tmp2);
+ &adc($c,0);
+ &mov(&DWP(0,$r,"",0),$tmp1); # *r
+ &add($a, 4);
+ &add($b, 4);
+ &add($r, 4);
+ &dec($num) if ($i != 6);
+ &jz(&label("aw_end")) if ($i != 6);
+ }
+ &set_label("aw_end",0);
+
+ &cmp(&wparam(4),0);
+ &je(&label("pw_end"));
+
+ &mov($num,&wparam(4)); # get dl
+ &cmp($num,0);
+ &je(&label("pw_end"));
+ &jge(&label("pw_pos"));
+
+ &comment("pw_neg");
+ &mov($tmp2,0);
+ &sub($tmp2,$num);
+ &mov($num,$tmp2);
+ &and($num,0xfffffff8); # num / 8
+ &jz(&label("pw_neg_finish"));
+
+ &set_label("pw_neg_loop",0);
+ for ($i=0; $i<8; $i++)
+ {
+ &comment("dl<0 Round $i");
+
+ &mov($tmp1,0);
+ &mov($tmp2,&DWP($i*4,$b,"",0)); # *b
+ &sub($tmp1,$c);
+ &mov($c,0);
+ &adc($c,$c);
+ &sub($tmp1,$tmp2);
+ &adc($c,0);
+ &mov(&DWP($i*4,$r,"",0),$tmp1); # *r
+ }
+
+ &comment("");
+ &add($b,32);
+ &add($r,32);
+ &sub($num,8);
+ &jnz(&label("pw_neg_loop"));
+
+ &set_label("pw_neg_finish",0);
+ &mov($tmp2,&wparam(4)); # get dl
+ &mov($num,0);
+ &sub($num,$tmp2);
+ &and($num,7);
+ &jz(&label("pw_end"));
+
+ for ($i=0; $i<7; $i++)
+ {
+ &comment("dl<0 Tail Round $i");
+ &mov($tmp1,0);
+ &mov($tmp2,&DWP($i*4,$b,"",0));# *b
+ &sub($tmp1,$c);
+ &mov($c,0);
+ &adc($c,$c);
+ &sub($tmp1,$tmp2);
+ &adc($c,0);
+ &dec($num) if ($i != 6);
+ &mov(&DWP($i*4,$r,"",0),$tmp1); # *r
+ &jz(&label("pw_end")) if ($i != 6);
+ }
+
+ &jmp(&label("pw_end"));
+
+ &set_label("pw_pos",0);
+
+ &and($num,0xfffffff8); # num / 8
+ &jz(&label("pw_pos_finish"));
+
+ &set_label("pw_pos_loop",0);
+
+ for ($i=0; $i<8; $i++)
+ {
+ &comment("dl>0 Round $i");
+
+ &mov($tmp1,&DWP($i*4,$a,"",0)); # *a
+ &sub($tmp1,$c);
+ &mov(&DWP($i*4,$r,"",0),$tmp1); # *r
+ &jnc(&label("pw_nc".$i));
+ }
+
+ &comment("");
+ &add($a,32);
+ &add($r,32);
+ &sub($num,8);
+ &jnz(&label("pw_pos_loop"));
+
+ &set_label("pw_pos_finish",0);
+ &mov($num,&wparam(4)); # get dl
+ &and($num,7);
+ &jz(&label("pw_end"));
+
+ for ($i=0; $i<7; $i++)
+ {
+ &comment("dl>0 Tail Round $i");
+ &mov($tmp1,&DWP($i*4,$a,"",0)); # *a
+ &sub($tmp1,$c);
+ &mov(&DWP($i*4,$r,"",0),$tmp1); # *r
+ &jnc(&label("pw_tail_nc".$i));
+ &dec($num) if ($i != 6);
+ &jz(&label("pw_end")) if ($i != 6);
+ }
+ &mov($c,1);
+ &jmp(&label("pw_end"));
+
+ &set_label("pw_nc_loop",0);
+ for ($i=0; $i<8; $i++)
+ {
+ &mov($tmp1,&DWP($i*4,$a,"",0)); # *a
+ &mov(&DWP($i*4,$r,"",0),$tmp1); # *r
+ &set_label("pw_nc".$i,0);
+ }
+
+ &comment("");
+ &add($a,32);
+ &add($r,32);
+ &sub($num,8);
+ &jnz(&label("pw_nc_loop"));
+
+ &mov($num,&wparam(4)); # get dl
+ &and($num,7);
+ &jz(&label("pw_nc_end"));
+
+ for ($i=0; $i<7; $i++)
+ {
+ &mov($tmp1,&DWP($i*4,$a,"",0)); # *a
+ &mov(&DWP($i*4,$r,"",0),$tmp1); # *r
+ &set_label("pw_tail_nc".$i,0);
+ &dec($num) if ($i != 6);
+ &jz(&label("pw_nc_end")) if ($i != 6);
+ }
+
+ &set_label("pw_nc_end",0);
+ &mov($c,0);
+
+ &set_label("pw_end",0);
+
+# &mov("eax",$c); # $c is "eax"
+
+ &function_end($name);
+ }
+
diff --git a/src/crypto/bn/asm/co-586.pl b/src/crypto/bn/asm/co-586.pl
new file mode 100644
index 0000000..57101a6
--- /dev/null
+++ b/src/crypto/bn/asm/co-586.pl
@@ -0,0 +1,287 @@
+#!/usr/local/bin/perl
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+push(@INC,"${dir}","${dir}../../perlasm");
+require "x86asm.pl";
+
+&asm_init($ARGV[0],$0);
+
+&bn_mul_comba("bn_mul_comba8",8);
+&bn_mul_comba("bn_mul_comba4",4);
+&bn_sqr_comba("bn_sqr_comba8",8);
+&bn_sqr_comba("bn_sqr_comba4",4);
+
+&asm_finish();
+
+sub mul_add_c
+ {
+ local($a,$ai,$b,$bi,$c0,$c1,$c2,$pos,$i,$na,$nb)=@_;
+
+ # pos == -1 if eax and edx are pre-loaded, 0 to load from next
+ # words, and 1 if load return value
+
+ &comment("mul a[$ai]*b[$bi]");
+
+ # "eax" and "edx" will always be pre-loaded.
+ # &mov("eax",&DWP($ai*4,$a,"",0)) ;
+ # &mov("edx",&DWP($bi*4,$b,"",0));
+
+ &mul("edx");
+ &add($c0,"eax");
+ &mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 0; # laod next a
+ &mov("eax",&wparam(0)) if $pos > 0; # load r[]
+ ###
+ &adc($c1,"edx");
+ &mov("edx",&DWP(($nb)*4,$b,"",0)) if $pos == 0; # laod next b
+ &mov("edx",&DWP(($nb)*4,$b,"",0)) if $pos == 1; # laod next b
+ ###
+ &adc($c2,0);
+ # is pos > 1, it means it is the last loop
+ &mov(&DWP($i*4,"eax","",0),$c0) if $pos > 0; # save r[];
+ &mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 1; # laod next a
+ }
+
+sub sqr_add_c
+ {
+ local($r,$a,$ai,$bi,$c0,$c1,$c2,$pos,$i,$na,$nb)=@_;
+
+ # pos == -1 if eax and edx are pre-loaded, 0 to load from next
+ # words, and 1 if load return value
+
+ &comment("sqr a[$ai]*a[$bi]");
+
+ # "eax" and "edx" will always be pre-loaded.
+ # &mov("eax",&DWP($ai*4,$a,"",0)) ;
+ # &mov("edx",&DWP($bi*4,$b,"",0));
+
+ if ($ai == $bi)
+ { &mul("eax");}
+ else
+ { &mul("edx");}
+ &add($c0,"eax");
+ &mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 0; # load next a
+ ###
+ &adc($c1,"edx");
+ &mov("edx",&DWP(($nb)*4,$a,"",0)) if ($pos == 1) && ($na != $nb);
+ ###
+ &adc($c2,0);
+ # is pos > 1, it means it is the last loop
+ &mov(&DWP($i*4,$r,"",0),$c0) if $pos > 0; # save r[];
+ &mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 1; # load next b
+ }
+
+sub sqr_add_c2
+ {
+ local($r,$a,$ai,$bi,$c0,$c1,$c2,$pos,$i,$na,$nb)=@_;
+
+ # pos == -1 if eax and edx are pre-loaded, 0 to load from next
+ # words, and 1 if load return value
+
+ &comment("sqr a[$ai]*a[$bi]");
+
+ # "eax" and "edx" will always be pre-loaded.
+ # &mov("eax",&DWP($ai*4,$a,"",0)) ;
+ # &mov("edx",&DWP($bi*4,$a,"",0));
+
+ if ($ai == $bi)
+ { &mul("eax");}
+ else
+ { &mul("edx");}
+ &add("eax","eax");
+ ###
+ &adc("edx","edx");
+ ###
+ &adc($c2,0);
+ &add($c0,"eax");
+ &adc($c1,"edx");
+ &mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 0; # load next a
+ &mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 1; # load next b
+ &adc($c2,0);
+ &mov(&DWP($i*4,$r,"",0),$c0) if $pos > 0; # save r[];
+ &mov("edx",&DWP(($nb)*4,$a,"",0)) if ($pos <= 1) && ($na != $nb);
+ ###
+ }
+
+sub bn_mul_comba
+ {
+ local($name,$num)=@_;
+ local($a,$b,$c0,$c1,$c2);
+ local($i,$as,$ae,$bs,$be,$ai,$bi);
+ local($tot,$end);
+
+ &function_begin_B($name,"");
+
+ $c0="ebx";
+ $c1="ecx";
+ $c2="ebp";
+ $a="esi";
+ $b="edi";
+
+ $as=0;
+ $ae=0;
+ $bs=0;
+ $be=0;
+ $tot=$num+$num-1;
+
+ &push("esi");
+ &mov($a,&wparam(1));
+ &push("edi");
+ &mov($b,&wparam(2));
+ &push("ebp");
+ &push("ebx");
+
+ &xor($c0,$c0);
+ &mov("eax",&DWP(0,$a,"",0)); # load the first word
+ &xor($c1,$c1);
+ &mov("edx",&DWP(0,$b,"",0)); # load the first second
+
+ for ($i=0; $i<$tot; $i++)
+ {
+ $ai=$as;
+ $bi=$bs;
+ $end=$be+1;
+
+ &comment("################## Calculate word $i");
+
+ for ($j=$bs; $j<$end; $j++)
+ {
+ &xor($c2,$c2) if ($j == $bs);
+ if (($j+1) == $end)
+ {
+ $v=1;
+ $v=2 if (($i+1) == $tot);
+ }
+ else
+ { $v=0; }
+ if (($j+1) != $end)
+ {
+ $na=($ai-1);
+ $nb=($bi+1);
+ }
+ else
+ {
+ $na=$as+($i < ($num-1));
+ $nb=$bs+($i >= ($num-1));
+ }
+#printf STDERR "[$ai,$bi] -> [$na,$nb]\n";
+ &mul_add_c($a,$ai,$b,$bi,$c0,$c1,$c2,$v,$i,$na,$nb);
+ if ($v)
+ {
+ &comment("saved r[$i]");
+ # &mov("eax",&wparam(0));
+ # &mov(&DWP($i*4,"eax","",0),$c0);
+ ($c0,$c1,$c2)=($c1,$c2,$c0);
+ }
+ $ai--;
+ $bi++;
+ }
+ $as++ if ($i < ($num-1));
+ $ae++ if ($i >= ($num-1));
+
+ $bs++ if ($i >= ($num-1));
+ $be++ if ($i < ($num-1));
+ }
+ &comment("save r[$i]");
+ # &mov("eax",&wparam(0));
+ &mov(&DWP($i*4,"eax","",0),$c0);
+
+ &pop("ebx");
+ &pop("ebp");
+ &pop("edi");
+ &pop("esi");
+ &ret();
+ &function_end_B($name);
+ }
+
+sub bn_sqr_comba
+ {
+ local($name,$num)=@_;
+ local($r,$a,$c0,$c1,$c2)=@_;
+ local($i,$as,$ae,$bs,$be,$ai,$bi);
+ local($b,$tot,$end,$half);
+
+ &function_begin_B($name,"");
+
+ $c0="ebx";
+ $c1="ecx";
+ $c2="ebp";
+ $a="esi";
+ $r="edi";
+
+ &push("esi");
+ &push("edi");
+ &push("ebp");
+ &push("ebx");
+ &mov($r,&wparam(0));
+ &mov($a,&wparam(1));
+ &xor($c0,$c0);
+ &xor($c1,$c1);
+ &mov("eax",&DWP(0,$a,"",0)); # load the first word
+
+ $as=0;
+ $ae=0;
+ $bs=0;
+ $be=0;
+ $tot=$num+$num-1;
+
+ for ($i=0; $i<$tot; $i++)
+ {
+ $ai=$as;
+ $bi=$bs;
+ $end=$be+1;
+
+ &comment("############### Calculate word $i");
+ for ($j=$bs; $j<$end; $j++)
+ {
+ &xor($c2,$c2) if ($j == $bs);
+ if (($ai-1) < ($bi+1))
+ {
+ $v=1;
+ $v=2 if ($i+1) == $tot;
+ }
+ else
+ { $v=0; }
+ if (!$v)
+ {
+ $na=$ai-1;
+ $nb=$bi+1;
+ }
+ else
+ {
+ $na=$as+($i < ($num-1));
+ $nb=$bs+($i >= ($num-1));
+ }
+ if ($ai == $bi)
+ {
+ &sqr_add_c($r,$a,$ai,$bi,
+ $c0,$c1,$c2,$v,$i,$na,$nb);
+ }
+ else
+ {
+ &sqr_add_c2($r,$a,$ai,$bi,
+ $c0,$c1,$c2,$v,$i,$na,$nb);
+ }
+ if ($v)
+ {
+ &comment("saved r[$i]");
+ #&mov(&DWP($i*4,$r,"",0),$c0);
+ ($c0,$c1,$c2)=($c1,$c2,$c0);
+ last;
+ }
+ $ai--;
+ $bi++;
+ }
+ $as++ if ($i < ($num-1));
+ $ae++ if ($i >= ($num-1));
+
+ $bs++ if ($i >= ($num-1));
+ $be++ if ($i < ($num-1));
+ }
+ &mov(&DWP($i*4,$r,"",0),$c0);
+ &pop("ebx");
+ &pop("ebp");
+ &pop("edi");
+ &pop("esi");
+ &ret();
+ &function_end_B($name);
+ }
diff --git a/src/crypto/bn/asm/rsaz-avx2.pl b/src/crypto/bn/asm/rsaz-avx2.pl
new file mode 100644
index 0000000..3b6ccf8
--- /dev/null
+++ b/src/crypto/bn/asm/rsaz-avx2.pl
@@ -0,0 +1,1898 @@
+#!/usr/bin/env perl
+
+##############################################################################
+# #
+# Copyright (c) 2012, Intel Corporation #
+# #
+# All rights reserved. #
+# #
+# Redistribution and use in source and binary forms, with or without #
+# modification, are permitted provided that the following conditions are #
+# met: #
+# #
+# * Redistributions of source code must retain the above copyright #
+# notice, this list of conditions and the following disclaimer. #
+# #
+# * Redistributions in binary form must reproduce the above copyright #
+# notice, this list of conditions and the following disclaimer in the #
+# documentation and/or other materials provided with the #
+# distribution. #
+# #
+# * Neither the name of the Intel Corporation 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 INTEL CORPORATION ""AS IS"" AND ANY #
+# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE #
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR #
+# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR #
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, #
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, #
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR #
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF #
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING #
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS #
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #
+# #
+##############################################################################
+# Developers and authors: #
+# Shay Gueron (1, 2), and Vlad Krasnov (1) #
+# (1) Intel Corporation, Israel Development Center, Haifa, Israel #
+# (2) University of Haifa, Israel #
+##############################################################################
+# Reference: #
+# [1] S. Gueron, V. Krasnov: "Software Implementation of Modular #
+# Exponentiation, Using Advanced Vector Instructions Architectures", #
+# F. Ozbudak and F. Rodriguez-Henriquez (Eds.): WAIFI 2012, LNCS 7369, #
+# pp. 119?135, 2012. Springer-Verlag Berlin Heidelberg 2012 #
+# [2] S. Gueron: "Efficient Software Implementations of Modular #
+# Exponentiation", Journal of Cryptographic Engineering 2:31-43 (2012). #
+# [3] S. Gueron, V. Krasnov: "Speeding up Big-numbers Squaring",IEEE #
+# Proceedings of 9th International Conference on Information Technology: #
+# New Generations (ITNG 2012), pp.821-823 (2012) #
+# [4] S. Gueron, V. Krasnov: "[PATCH] Efficient and side channel analysis #
+# resistant 1024-bit modular exponentiation, for optimizing RSA2048 #
+# on AVX2 capable x86_64 platforms", #
+# http://rt.openssl.org/Ticket/Display.html?id=2850&user=guest&pass=guest#
+##############################################################################
+#
+# +13% improvement over original submission by <appro@openssl.org>
+#
+# rsa2048 sign/sec OpenSSL 1.0.1 scalar(*) this
+# 2.3GHz Haswell 621 765/+23% 1113/+79%
+# 2.3GHz Broadwell(**) 688 1200(***)/+74% 1120/+63%
+#
+# (*) if system doesn't support AVX2, for reference purposes;
+# (**) scaled to 2.3GHz to simplify comparison;
+# (***) scalar AD*X code is faster than AVX2 and is preferred code
+# path for Broadwell;
+
+$flavour = shift;
+$output = shift;
+if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+
+$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
+( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
+die "can't locate x86_64-xlate.pl";
+
+if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
+ =~ /GNU assembler version ([2-9]\.[0-9]+)/) {
+ $avx = ($1>=2.19) + ($1>=2.22);
+ $addx = ($1>=2.23);
+}
+
+if (!$avx && $win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) &&
+ `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)/) {
+ $avx = ($1>=2.09) + ($1>=2.10);
+ $addx = ($1>=2.10);
+}
+
+if (!$avx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) &&
+ `ml64 2>&1` =~ /Version ([0-9]+)\./) {
+ $avx = ($1>=10) + ($1>=11);
+ $addx = ($1>=11);
+}
+
+if (!$avx && `$ENV{CC} -v 2>&1` =~ /(^clang version|based on LLVM) ([3-9])\.([0-9]+)/) {
+ my $ver = $2 + $3/100.0; # 3.1->3.01, 3.10->3.10
+ $avx = ($ver>=3.0) + ($ver>=3.01);
+ $addx = ($ver>=3.03);
+}
+
+open OUT,"| \"$^X\" $xlate $flavour $output";
+*STDOUT = *OUT;
+
+if ($avx>1) {{{
+{ # void AMS_WW(
+my $rp="%rdi"; # BN_ULONG *rp,
+my $ap="%rsi"; # const BN_ULONG *ap,
+my $np="%rdx"; # const BN_ULONG *np,
+my $n0="%ecx"; # const BN_ULONG n0,
+my $rep="%r8d"; # int repeat);
+
+# The registers that hold the accumulated redundant result
+# The AMM works on 1024 bit operands, and redundant word size is 29
+# Therefore: ceil(1024/29)/4 = 9
+my $ACC0="%ymm0";
+my $ACC1="%ymm1";
+my $ACC2="%ymm2";
+my $ACC3="%ymm3";
+my $ACC4="%ymm4";
+my $ACC5="%ymm5";
+my $ACC6="%ymm6";
+my $ACC7="%ymm7";
+my $ACC8="%ymm8";
+my $ACC9="%ymm9";
+# Registers that hold the broadcasted words of bp, currently used
+my $B1="%ymm10";
+my $B2="%ymm11";
+# Registers that hold the broadcasted words of Y, currently used
+my $Y1="%ymm12";
+my $Y2="%ymm13";
+# Helper registers
+my $TEMP1="%ymm14";
+my $AND_MASK="%ymm15";
+# alu registers that hold the first words of the ACC
+my $r0="%r9";
+my $r1="%r10";
+my $r2="%r11";
+my $r3="%r12";
+
+my $i="%r14d"; # loop counter
+my $tmp = "%r15";
+
+my $FrameSize=32*18+32*8; # place for A^2 and 2*A
+
+my $aap=$r0;
+my $tp0="%rbx";
+my $tp1=$r3;
+my $tpa=$tmp;
+
+$np="%r13"; # reassigned argument
+
+$code.=<<___;
+.text
+
+.globl rsaz_1024_sqr_avx2
+.type rsaz_1024_sqr_avx2,\@function,5
+.align 64
+rsaz_1024_sqr_avx2: # 702 cycles, 14% faster than rsaz_1024_mul_avx2
+ lea (%rsp), %rax
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+ vzeroupper
+___
+$code.=<<___ if ($win64);
+ lea -0xa8(%rsp),%rsp
+ vmovaps %xmm6,-0xd8(%rax)
+ vmovaps %xmm7,-0xc8(%rax)
+ vmovaps %xmm8,-0xb8(%rax)
+ vmovaps %xmm9,-0xa8(%rax)
+ vmovaps %xmm10,-0x98(%rax)
+ vmovaps %xmm11,-0x88(%rax)
+ vmovaps %xmm12,-0x78(%rax)
+ vmovaps %xmm13,-0x68(%rax)
+ vmovaps %xmm14,-0x58(%rax)
+ vmovaps %xmm15,-0x48(%rax)
+.Lsqr_1024_body:
+___
+$code.=<<___;
+ mov %rax,%rbp
+ mov %rdx, $np # reassigned argument
+ sub \$$FrameSize, %rsp
+ mov $np, $tmp
+ sub \$-128, $rp # size optimization
+ sub \$-128, $ap
+ sub \$-128, $np
+
+ and \$4095, $tmp # see if $np crosses page
+ add \$32*10, $tmp
+ shr \$12, $tmp
+ vpxor $ACC9,$ACC9,$ACC9
+ jz .Lsqr_1024_no_n_copy
+
+ # unaligned 256-bit load that crosses page boundary can
+ # cause >2x performance degradation here, so if $np does
+ # cross page boundary, copy it to stack and make sure stack
+ # frame doesn't...
+ sub \$32*10,%rsp
+ vmovdqu 32*0-128($np), $ACC0
+ and \$-2048, %rsp
+ vmovdqu 32*1-128($np), $ACC1
+ vmovdqu 32*2-128($np), $ACC2
+ vmovdqu 32*3-128($np), $ACC3
+ vmovdqu 32*4-128($np), $ACC4
+ vmovdqu 32*5-128($np), $ACC5
+ vmovdqu 32*6-128($np), $ACC6
+ vmovdqu 32*7-128($np), $ACC7
+ vmovdqu 32*8-128($np), $ACC8
+ lea $FrameSize+128(%rsp),$np
+ vmovdqu $ACC0, 32*0-128($np)
+ vmovdqu $ACC1, 32*1-128($np)
+ vmovdqu $ACC2, 32*2-128($np)
+ vmovdqu $ACC3, 32*3-128($np)
+ vmovdqu $ACC4, 32*4-128($np)
+ vmovdqu $ACC5, 32*5-128($np)
+ vmovdqu $ACC6, 32*6-128($np)
+ vmovdqu $ACC7, 32*7-128($np)
+ vmovdqu $ACC8, 32*8-128($np)
+ vmovdqu $ACC9, 32*9-128($np) # $ACC9 is zero
+
+.Lsqr_1024_no_n_copy:
+ and \$-1024, %rsp
+
+ vmovdqu 32*1-128($ap), $ACC1
+ vmovdqu 32*2-128($ap), $ACC2
+ vmovdqu 32*3-128($ap), $ACC3
+ vmovdqu 32*4-128($ap), $ACC4
+ vmovdqu 32*5-128($ap), $ACC5
+ vmovdqu 32*6-128($ap), $ACC6
+ vmovdqu 32*7-128($ap), $ACC7
+ vmovdqu 32*8-128($ap), $ACC8
+
+ lea 192(%rsp), $tp0 # 64+128=192
+ vpbroadcastq .Land_mask(%rip), $AND_MASK
+ jmp .LOOP_GRANDE_SQR_1024
+
+.align 32
+.LOOP_GRANDE_SQR_1024:
+ lea 32*18+128(%rsp), $aap # size optimization
+ lea 448(%rsp), $tp1 # 64+128+256=448
+
+ # the squaring is performed as described in Variant B of
+ # "Speeding up Big-Number Squaring", so start by calculating
+ # the A*2=A+A vector
+ vpaddq $ACC1, $ACC1, $ACC1
+ vpbroadcastq 32*0-128($ap), $B1
+ vpaddq $ACC2, $ACC2, $ACC2
+ vmovdqa $ACC1, 32*0-128($aap)
+ vpaddq $ACC3, $ACC3, $ACC3
+ vmovdqa $ACC2, 32*1-128($aap)
+ vpaddq $ACC4, $ACC4, $ACC4
+ vmovdqa $ACC3, 32*2-128($aap)
+ vpaddq $ACC5, $ACC5, $ACC5
+ vmovdqa $ACC4, 32*3-128($aap)
+ vpaddq $ACC6, $ACC6, $ACC6
+ vmovdqa $ACC5, 32*4-128($aap)
+ vpaddq $ACC7, $ACC7, $ACC7
+ vmovdqa $ACC6, 32*5-128($aap)
+ vpaddq $ACC8, $ACC8, $ACC8
+ vmovdqa $ACC7, 32*6-128($aap)
+ vpxor $ACC9, $ACC9, $ACC9
+ vmovdqa $ACC8, 32*7-128($aap)
+
+ vpmuludq 32*0-128($ap), $B1, $ACC0
+ vpbroadcastq 32*1-128($ap), $B2
+ vmovdqu $ACC9, 32*9-192($tp0) # zero upper half
+ vpmuludq $B1, $ACC1, $ACC1
+ vmovdqu $ACC9, 32*10-448($tp1)
+ vpmuludq $B1, $ACC2, $ACC2
+ vmovdqu $ACC9, 32*11-448($tp1)
+ vpmuludq $B1, $ACC3, $ACC3
+ vmovdqu $ACC9, 32*12-448($tp1)
+ vpmuludq $B1, $ACC4, $ACC4
+ vmovdqu $ACC9, 32*13-448($tp1)
+ vpmuludq $B1, $ACC5, $ACC5
+ vmovdqu $ACC9, 32*14-448($tp1)
+ vpmuludq $B1, $ACC6, $ACC6
+ vmovdqu $ACC9, 32*15-448($tp1)
+ vpmuludq $B1, $ACC7, $ACC7
+ vmovdqu $ACC9, 32*16-448($tp1)
+ vpmuludq $B1, $ACC8, $ACC8
+ vpbroadcastq 32*2-128($ap), $B1
+ vmovdqu $ACC9, 32*17-448($tp1)
+
+ mov $ap, $tpa
+ mov \$4, $i
+ jmp .Lsqr_entry_1024
+___
+$TEMP0=$Y1;
+$TEMP2=$Y2;
+$code.=<<___;
+.align 32
+.LOOP_SQR_1024:
+ vpbroadcastq 32*1-128($tpa), $B2
+ vpmuludq 32*0-128($ap), $B1, $ACC0
+ vpaddq 32*0-192($tp0), $ACC0, $ACC0
+ vpmuludq 32*0-128($aap), $B1, $ACC1
+ vpaddq 32*1-192($tp0), $ACC1, $ACC1
+ vpmuludq 32*1-128($aap), $B1, $ACC2
+ vpaddq 32*2-192($tp0), $ACC2, $ACC2
+ vpmuludq 32*2-128($aap), $B1, $ACC3
+ vpaddq 32*3-192($tp0), $ACC3, $ACC3
+ vpmuludq 32*3-128($aap), $B1, $ACC4
+ vpaddq 32*4-192($tp0), $ACC4, $ACC4
+ vpmuludq 32*4-128($aap), $B1, $ACC5
+ vpaddq 32*5-192($tp0), $ACC5, $ACC5
+ vpmuludq 32*5-128($aap), $B1, $ACC6
+ vpaddq 32*6-192($tp0), $ACC6, $ACC6
+ vpmuludq 32*6-128($aap), $B1, $ACC7
+ vpaddq 32*7-192($tp0), $ACC7, $ACC7
+ vpmuludq 32*7-128($aap), $B1, $ACC8
+ vpbroadcastq 32*2-128($tpa), $B1
+ vpaddq 32*8-192($tp0), $ACC8, $ACC8
+.Lsqr_entry_1024:
+ vmovdqu $ACC0, 32*0-192($tp0)
+ vmovdqu $ACC1, 32*1-192($tp0)
+
+ vpmuludq 32*1-128($ap), $B2, $TEMP0
+ vpaddq $TEMP0, $ACC2, $ACC2
+ vpmuludq 32*1-128($aap), $B2, $TEMP1
+ vpaddq $TEMP1, $ACC3, $ACC3
+ vpmuludq 32*2-128($aap), $B2, $TEMP2
+ vpaddq $TEMP2, $ACC4, $ACC4
+ vpmuludq 32*3-128($aap), $B2, $TEMP0
+ vpaddq $TEMP0, $ACC5, $ACC5
+ vpmuludq 32*4-128($aap), $B2, $TEMP1
+ vpaddq $TEMP1, $ACC6, $ACC6
+ vpmuludq 32*5-128($aap), $B2, $TEMP2
+ vpaddq $TEMP2, $ACC7, $ACC7
+ vpmuludq 32*6-128($aap), $B2, $TEMP0
+ vpaddq $TEMP0, $ACC8, $ACC8
+ vpmuludq 32*7-128($aap), $B2, $ACC0
+ vpbroadcastq 32*3-128($tpa), $B2
+ vpaddq 32*9-192($tp0), $ACC0, $ACC0
+
+ vmovdqu $ACC2, 32*2-192($tp0)
+ vmovdqu $ACC3, 32*3-192($tp0)
+
+ vpmuludq 32*2-128($ap), $B1, $TEMP2
+ vpaddq $TEMP2, $ACC4, $ACC4
+ vpmuludq 32*2-128($aap), $B1, $TEMP0
+ vpaddq $TEMP0, $ACC5, $ACC5
+ vpmuludq 32*3-128($aap), $B1, $TEMP1
+ vpaddq $TEMP1, $ACC6, $ACC6
+ vpmuludq 32*4-128($aap), $B1, $TEMP2
+ vpaddq $TEMP2, $ACC7, $ACC7
+ vpmuludq 32*5-128($aap), $B1, $TEMP0
+ vpaddq $TEMP0, $ACC8, $ACC8
+ vpmuludq 32*6-128($aap), $B1, $TEMP1
+ vpaddq $TEMP1, $ACC0, $ACC0
+ vpmuludq 32*7-128($aap), $B1, $ACC1
+ vpbroadcastq 32*4-128($tpa), $B1
+ vpaddq 32*10-448($tp1), $ACC1, $ACC1
+
+ vmovdqu $ACC4, 32*4-192($tp0)
+ vmovdqu $ACC5, 32*5-192($tp0)
+
+ vpmuludq 32*3-128($ap), $B2, $TEMP0
+ vpaddq $TEMP0, $ACC6, $ACC6
+ vpmuludq 32*3-128($aap), $B2, $TEMP1
+ vpaddq $TEMP1, $ACC7, $ACC7
+ vpmuludq 32*4-128($aap), $B2, $TEMP2
+ vpaddq $TEMP2, $ACC8, $ACC8
+ vpmuludq 32*5-128($aap), $B2, $TEMP0
+ vpaddq $TEMP0, $ACC0, $ACC0
+ vpmuludq 32*6-128($aap), $B2, $TEMP1
+ vpaddq $TEMP1, $ACC1, $ACC1
+ vpmuludq 32*7-128($aap), $B2, $ACC2
+ vpbroadcastq 32*5-128($tpa), $B2
+ vpaddq 32*11-448($tp1), $ACC2, $ACC2
+
+ vmovdqu $ACC6, 32*6-192($tp0)
+ vmovdqu $ACC7, 32*7-192($tp0)
+
+ vpmuludq 32*4-128($ap), $B1, $TEMP0
+ vpaddq $TEMP0, $ACC8, $ACC8
+ vpmuludq 32*4-128($aap), $B1, $TEMP1
+ vpaddq $TEMP1, $ACC0, $ACC0
+ vpmuludq 32*5-128($aap), $B1, $TEMP2
+ vpaddq $TEMP2, $ACC1, $ACC1
+ vpmuludq 32*6-128($aap), $B1, $TEMP0
+ vpaddq $TEMP0, $ACC2, $ACC2
+ vpmuludq 32*7-128($aap), $B1, $ACC3
+ vpbroadcastq 32*6-128($tpa), $B1
+ vpaddq 32*12-448($tp1), $ACC3, $ACC3
+
+ vmovdqu $ACC8, 32*8-192($tp0)
+ vmovdqu $ACC0, 32*9-192($tp0)
+ lea 8($tp0), $tp0
+
+ vpmuludq 32*5-128($ap), $B2, $TEMP2
+ vpaddq $TEMP2, $ACC1, $ACC1
+ vpmuludq 32*5-128($aap), $B2, $TEMP0
+ vpaddq $TEMP0, $ACC2, $ACC2
+ vpmuludq 32*6-128($aap), $B2, $TEMP1
+ vpaddq $TEMP1, $ACC3, $ACC3
+ vpmuludq 32*7-128($aap), $B2, $ACC4
+ vpbroadcastq 32*7-128($tpa), $B2
+ vpaddq 32*13-448($tp1), $ACC4, $ACC4
+
+ vmovdqu $ACC1, 32*10-448($tp1)
+ vmovdqu $ACC2, 32*11-448($tp1)
+
+ vpmuludq 32*6-128($ap), $B1, $TEMP0
+ vpaddq $TEMP0, $ACC3, $ACC3
+ vpmuludq 32*6-128($aap), $B1, $TEMP1
+ vpbroadcastq 32*8-128($tpa), $ACC0 # borrow $ACC0 for $B1
+ vpaddq $TEMP1, $ACC4, $ACC4
+ vpmuludq 32*7-128($aap), $B1, $ACC5
+ vpbroadcastq 32*0+8-128($tpa), $B1 # for next iteration
+ vpaddq 32*14-448($tp1), $ACC5, $ACC5
+
+ vmovdqu $ACC3, 32*12-448($tp1)
+ vmovdqu $ACC4, 32*13-448($tp1)
+ lea 8($tpa), $tpa
+
+ vpmuludq 32*7-128($ap), $B2, $TEMP0
+ vpaddq $TEMP0, $ACC5, $ACC5
+ vpmuludq 32*7-128($aap), $B2, $ACC6
+ vpaddq 32*15-448($tp1), $ACC6, $ACC6
+
+ vpmuludq 32*8-128($ap), $ACC0, $ACC7
+ vmovdqu $ACC5, 32*14-448($tp1)
+ vpaddq 32*16-448($tp1), $ACC7, $ACC7
+ vmovdqu $ACC6, 32*15-448($tp1)
+ vmovdqu $ACC7, 32*16-448($tp1)
+ lea 8($tp1), $tp1
+
+ dec $i
+ jnz .LOOP_SQR_1024
+___
+$ZERO = $ACC9;
+$TEMP0 = $B1;
+$TEMP2 = $B2;
+$TEMP3 = $Y1;
+$TEMP4 = $Y2;
+$code.=<<___;
+ #we need to fix indexes 32-39 to avoid overflow
+ vmovdqu 32*8(%rsp), $ACC8 # 32*8-192($tp0),
+ vmovdqu 32*9(%rsp), $ACC1 # 32*9-192($tp0)
+ vmovdqu 32*10(%rsp), $ACC2 # 32*10-192($tp0)
+ lea 192(%rsp), $tp0 # 64+128=192
+
+ vpsrlq \$29, $ACC8, $TEMP1
+ vpand $AND_MASK, $ACC8, $ACC8
+ vpsrlq \$29, $ACC1, $TEMP2
+ vpand $AND_MASK, $ACC1, $ACC1
+
+ vpermq \$0x93, $TEMP1, $TEMP1
+ vpxor $ZERO, $ZERO, $ZERO
+ vpermq \$0x93, $TEMP2, $TEMP2
+
+ vpblendd \$3, $ZERO, $TEMP1, $TEMP0
+ vpblendd \$3, $TEMP1, $TEMP2, $TEMP1
+ vpaddq $TEMP0, $ACC8, $ACC8
+ vpblendd \$3, $TEMP2, $ZERO, $TEMP2
+ vpaddq $TEMP1, $ACC1, $ACC1
+ vpaddq $TEMP2, $ACC2, $ACC2
+ vmovdqu $ACC1, 32*9-192($tp0)
+ vmovdqu $ACC2, 32*10-192($tp0)
+
+ mov (%rsp), %rax
+ mov 8(%rsp), $r1
+ mov 16(%rsp), $r2
+ mov 24(%rsp), $r3
+ vmovdqu 32*1(%rsp), $ACC1
+ vmovdqu 32*2-192($tp0), $ACC2
+ vmovdqu 32*3-192($tp0), $ACC3
+ vmovdqu 32*4-192($tp0), $ACC4
+ vmovdqu 32*5-192($tp0), $ACC5
+ vmovdqu 32*6-192($tp0), $ACC6
+ vmovdqu 32*7-192($tp0), $ACC7
+
+ mov %rax, $r0
+ imull $n0, %eax
+ and \$0x1fffffff, %eax
+ vmovd %eax, $Y1
+
+ mov %rax, %rdx
+ imulq -128($np), %rax
+ vpbroadcastq $Y1, $Y1
+ add %rax, $r0
+ mov %rdx, %rax
+ imulq 8-128($np), %rax
+ shr \$29, $r0
+ add %rax, $r1
+ mov %rdx, %rax
+ imulq 16-128($np), %rax
+ add $r0, $r1
+ add %rax, $r2
+ imulq 24-128($np), %rdx
+ add %rdx, $r3
+
+ mov $r1, %rax
+ imull $n0, %eax
+ and \$0x1fffffff, %eax
+
+ mov \$9, $i
+ jmp .LOOP_REDUCE_1024
+
+.align 32
+.LOOP_REDUCE_1024:
+ vmovd %eax, $Y2
+ vpbroadcastq $Y2, $Y2
+
+ vpmuludq 32*1-128($np), $Y1, $TEMP0
+ mov %rax, %rdx
+ imulq -128($np), %rax
+ vpaddq $TEMP0, $ACC1, $ACC1
+ add %rax, $r1
+ vpmuludq 32*2-128($np), $Y1, $TEMP1
+ mov %rdx, %rax
+ imulq 8-128($np), %rax
+ vpaddq $TEMP1, $ACC2, $ACC2
+ vpmuludq 32*3-128($np), $Y1, $TEMP2
+ .byte 0x67
+ add %rax, $r2
+ .byte 0x67
+ mov %rdx, %rax
+ imulq 16-128($np), %rax
+ shr \$29, $r1
+ vpaddq $TEMP2, $ACC3, $ACC3
+ vpmuludq 32*4-128($np), $Y1, $TEMP0
+ add %rax, $r3
+ add $r1, $r2
+ vpaddq $TEMP0, $ACC4, $ACC4
+ vpmuludq 32*5-128($np), $Y1, $TEMP1
+ mov $r2, %rax
+ imull $n0, %eax
+ vpaddq $TEMP1, $ACC5, $ACC5
+ vpmuludq 32*6-128($np), $Y1, $TEMP2
+ and \$0x1fffffff, %eax
+ vpaddq $TEMP2, $ACC6, $ACC6
+ vpmuludq 32*7-128($np), $Y1, $TEMP0
+ vpaddq $TEMP0, $ACC7, $ACC7
+ vpmuludq 32*8-128($np), $Y1, $TEMP1
+ vmovd %eax, $Y1
+ #vmovdqu 32*1-8-128($np), $TEMP2 # moved below
+ vpaddq $TEMP1, $ACC8, $ACC8
+ #vmovdqu 32*2-8-128($np), $TEMP0 # moved below
+ vpbroadcastq $Y1, $Y1
+
+ vpmuludq 32*1-8-128($np), $Y2, $TEMP2 # see above
+ vmovdqu 32*3-8-128($np), $TEMP1
+ mov %rax, %rdx
+ imulq -128($np), %rax
+ vpaddq $TEMP2, $ACC1, $ACC1
+ vpmuludq 32*2-8-128($np), $Y2, $TEMP0 # see above
+ vmovdqu 32*4-8-128($np), $TEMP2
+ add %rax, $r2
+ mov %rdx, %rax
+ imulq 8-128($np), %rax
+ vpaddq $TEMP0, $ACC2, $ACC2
+ add $r3, %rax
+ shr \$29, $r2
+ vpmuludq $Y2, $TEMP1, $TEMP1
+ vmovdqu 32*5-8-128($np), $TEMP0
+ add $r2, %rax
+ vpaddq $TEMP1, $ACC3, $ACC3
+ vpmuludq $Y2, $TEMP2, $TEMP2
+ vmovdqu 32*6-8-128($np), $TEMP1
+ .byte 0x67
+ mov %rax, $r3
+ imull $n0, %eax
+ vpaddq $TEMP2, $ACC4, $ACC4
+ vpmuludq $Y2, $TEMP0, $TEMP0
+ .byte 0xc4,0x41,0x7e,0x6f,0x9d,0x58,0x00,0x00,0x00 # vmovdqu 32*7-8-128($np), $TEMP2
+ and \$0x1fffffff, %eax
+ vpaddq $TEMP0, $ACC5, $ACC5
+ vpmuludq $Y2, $TEMP1, $TEMP1
+ vmovdqu 32*8-8-128($np), $TEMP0
+ vpaddq $TEMP1, $ACC6, $ACC6
+ vpmuludq $Y2, $TEMP2, $TEMP2
+ vmovdqu 32*9-8-128($np), $ACC9
+ vmovd %eax, $ACC0 # borrow ACC0 for Y2
+ imulq -128($np), %rax
+ vpaddq $TEMP2, $ACC7, $ACC7
+ vpmuludq $Y2, $TEMP0, $TEMP0
+ vmovdqu 32*1-16-128($np), $TEMP1
+ vpbroadcastq $ACC0, $ACC0
+ vpaddq $TEMP0, $ACC8, $ACC8
+ vpmuludq $Y2, $ACC9, $ACC9
+ vmovdqu 32*2-16-128($np), $TEMP2
+ add %rax, $r3
+
+___
+($ACC0,$Y2)=($Y2,$ACC0);
+$code.=<<___;
+ vmovdqu 32*1-24-128($np), $ACC0
+ vpmuludq $Y1, $TEMP1, $TEMP1
+ vmovdqu 32*3-16-128($np), $TEMP0
+ vpaddq $TEMP1, $ACC1, $ACC1
+ vpmuludq $Y2, $ACC0, $ACC0
+ vpmuludq $Y1, $TEMP2, $TEMP2
+ .byte 0xc4,0x41,0x7e,0x6f,0xb5,0xf0,0xff,0xff,0xff # vmovdqu 32*4-16-128($np), $TEMP1
+ vpaddq $ACC1, $ACC0, $ACC0
+ vpaddq $TEMP2, $ACC2, $ACC2
+ vpmuludq $Y1, $TEMP0, $TEMP0
+ vmovdqu 32*5-16-128($np), $TEMP2
+ .byte 0x67
+ vmovq $ACC0, %rax
+ vmovdqu $ACC0, (%rsp) # transfer $r0-$r3
+ vpaddq $TEMP0, $ACC3, $ACC3
+ vpmuludq $Y1, $TEMP1, $TEMP1
+ vmovdqu 32*6-16-128($np), $TEMP0
+ vpaddq $TEMP1, $ACC4, $ACC4
+ vpmuludq $Y1, $TEMP2, $TEMP2
+ vmovdqu 32*7-16-128($np), $TEMP1
+ vpaddq $TEMP2, $ACC5, $ACC5
+ vpmuludq $Y1, $TEMP0, $TEMP0
+ vmovdqu 32*8-16-128($np), $TEMP2
+ vpaddq $TEMP0, $ACC6, $ACC6
+ vpmuludq $Y1, $TEMP1, $TEMP1
+ shr \$29, $r3
+ vmovdqu 32*9-16-128($np), $TEMP0
+ add $r3, %rax
+ vpaddq $TEMP1, $ACC7, $ACC7
+ vpmuludq $Y1, $TEMP2, $TEMP2
+ #vmovdqu 32*2-24-128($np), $TEMP1 # moved below
+ mov %rax, $r0
+ imull $n0, %eax
+ vpaddq $TEMP2, $ACC8, $ACC8
+ vpmuludq $Y1, $TEMP0, $TEMP0
+ and \$0x1fffffff, %eax
+ vmovd %eax, $Y1
+ vmovdqu 32*3-24-128($np), $TEMP2
+ .byte 0x67
+ vpaddq $TEMP0, $ACC9, $ACC9
+ vpbroadcastq $Y1, $Y1
+
+ vpmuludq 32*2-24-128($np), $Y2, $TEMP1 # see above
+ vmovdqu 32*4-24-128($np), $TEMP0
+ mov %rax, %rdx
+ imulq -128($np), %rax
+ mov 8(%rsp), $r1
+ vpaddq $TEMP1, $ACC2, $ACC1
+ vpmuludq $Y2, $TEMP2, $TEMP2
+ vmovdqu 32*5-24-128($np), $TEMP1
+ add %rax, $r0
+ mov %rdx, %rax
+ imulq 8-128($np), %rax
+ .byte 0x67
+ shr \$29, $r0
+ mov 16(%rsp), $r2
+ vpaddq $TEMP2, $ACC3, $ACC2
+ vpmuludq $Y2, $TEMP0, $TEMP0
+ vmovdqu 32*6-24-128($np), $TEMP2
+ add %rax, $r1
+ mov %rdx, %rax
+ imulq 16-128($np), %rax
+ vpaddq $TEMP0, $ACC4, $ACC3
+ vpmuludq $Y2, $TEMP1, $TEMP1
+ vmovdqu 32*7-24-128($np), $TEMP0
+ imulq 24-128($np), %rdx # future $r3
+ add %rax, $r2
+ lea ($r0,$r1), %rax
+ vpaddq $TEMP1, $ACC5, $ACC4
+ vpmuludq $Y2, $TEMP2, $TEMP2
+ vmovdqu 32*8-24-128($np), $TEMP1
+ mov %rax, $r1
+ imull $n0, %eax
+ vpmuludq $Y2, $TEMP0, $TEMP0
+ vpaddq $TEMP2, $ACC6, $ACC5
+ vmovdqu 32*9-24-128($np), $TEMP2
+ and \$0x1fffffff, %eax
+ vpaddq $TEMP0, $ACC7, $ACC6
+ vpmuludq $Y2, $TEMP1, $TEMP1
+ add 24(%rsp), %rdx
+ vpaddq $TEMP1, $ACC8, $ACC7
+ vpmuludq $Y2, $TEMP2, $TEMP2
+ vpaddq $TEMP2, $ACC9, $ACC8
+ vmovq $r3, $ACC9
+ mov %rdx, $r3
+
+ dec $i
+ jnz .LOOP_REDUCE_1024
+___
+($ACC0,$Y2)=($Y2,$ACC0);
+$code.=<<___;
+ lea 448(%rsp), $tp1 # size optimization
+ vpaddq $ACC9, $Y2, $ACC0
+ vpxor $ZERO, $ZERO, $ZERO
+
+ vpaddq 32*9-192($tp0), $ACC0, $ACC0
+ vpaddq 32*10-448($tp1), $ACC1, $ACC1
+ vpaddq 32*11-448($tp1), $ACC2, $ACC2
+ vpaddq 32*12-448($tp1), $ACC3, $ACC3
+ vpaddq 32*13-448($tp1), $ACC4, $ACC4
+ vpaddq 32*14-448($tp1), $ACC5, $ACC5
+ vpaddq 32*15-448($tp1), $ACC6, $ACC6
+ vpaddq 32*16-448($tp1), $ACC7, $ACC7
+ vpaddq 32*17-448($tp1), $ACC8, $ACC8
+
+ vpsrlq \$29, $ACC0, $TEMP1
+ vpand $AND_MASK, $ACC0, $ACC0
+ vpsrlq \$29, $ACC1, $TEMP2
+ vpand $AND_MASK, $ACC1, $ACC1
+ vpsrlq \$29, $ACC2, $TEMP3
+ vpermq \$0x93, $TEMP1, $TEMP1
+ vpand $AND_MASK, $ACC2, $ACC2
+ vpsrlq \$29, $ACC3, $TEMP4
+ vpermq \$0x93, $TEMP2, $TEMP2
+ vpand $AND_MASK, $ACC3, $ACC3
+ vpermq \$0x93, $TEMP3, $TEMP3
+
+ vpblendd \$3, $ZERO, $TEMP1, $TEMP0
+ vpermq \$0x93, $TEMP4, $TEMP4
+ vpblendd \$3, $TEMP1, $TEMP2, $TEMP1
+ vpaddq $TEMP0, $ACC0, $ACC0
+ vpblendd \$3, $TEMP2, $TEMP3, $TEMP2
+ vpaddq $TEMP1, $ACC1, $ACC1
+ vpblendd \$3, $TEMP3, $TEMP4, $TEMP3
+ vpaddq $TEMP2, $ACC2, $ACC2
+ vpblendd \$3, $TEMP4, $ZERO, $TEMP4
+ vpaddq $TEMP3, $ACC3, $ACC3
+ vpaddq $TEMP4, $ACC4, $ACC4
+
+ vpsrlq \$29, $ACC0, $TEMP1
+ vpand $AND_MASK, $ACC0, $ACC0
+ vpsrlq \$29, $ACC1, $TEMP2
+ vpand $AND_MASK, $ACC1, $ACC1
+ vpsrlq \$29, $ACC2, $TEMP3
+ vpermq \$0x93, $TEMP1, $TEMP1
+ vpand $AND_MASK, $ACC2, $ACC2
+ vpsrlq \$29, $ACC3, $TEMP4
+ vpermq \$0x93, $TEMP2, $TEMP2
+ vpand $AND_MASK, $ACC3, $ACC3
+ vpermq \$0x93, $TEMP3, $TEMP3
+
+ vpblendd \$3, $ZERO, $TEMP1, $TEMP0
+ vpermq \$0x93, $TEMP4, $TEMP4
+ vpblendd \$3, $TEMP1, $TEMP2, $TEMP1
+ vpaddq $TEMP0, $ACC0, $ACC0
+ vpblendd \$3, $TEMP2, $TEMP3, $TEMP2
+ vpaddq $TEMP1, $ACC1, $ACC1
+ vmovdqu $ACC0, 32*0-128($rp)
+ vpblendd \$3, $TEMP3, $TEMP4, $TEMP3
+ vpaddq $TEMP2, $ACC2, $ACC2
+ vmovdqu $ACC1, 32*1-128($rp)
+ vpblendd \$3, $TEMP4, $ZERO, $TEMP4
+ vpaddq $TEMP3, $ACC3, $ACC3
+ vmovdqu $ACC2, 32*2-128($rp)
+ vpaddq $TEMP4, $ACC4, $ACC4
+ vmovdqu $ACC3, 32*3-128($rp)
+___
+$TEMP5=$ACC0;
+$code.=<<___;
+ vpsrlq \$29, $ACC4, $TEMP1
+ vpand $AND_MASK, $ACC4, $ACC4
+ vpsrlq \$29, $ACC5, $TEMP2
+ vpand $AND_MASK, $ACC5, $ACC5
+ vpsrlq \$29, $ACC6, $TEMP3
+ vpermq \$0x93, $TEMP1, $TEMP1
+ vpand $AND_MASK, $ACC6, $ACC6
+ vpsrlq \$29, $ACC7, $TEMP4
+ vpermq \$0x93, $TEMP2, $TEMP2
+ vpand $AND_MASK, $ACC7, $ACC7
+ vpsrlq \$29, $ACC8, $TEMP5
+ vpermq \$0x93, $TEMP3, $TEMP3
+ vpand $AND_MASK, $ACC8, $ACC8
+ vpermq \$0x93, $TEMP4, $TEMP4
+
+ vpblendd \$3, $ZERO, $TEMP1, $TEMP0
+ vpermq \$0x93, $TEMP5, $TEMP5
+ vpblendd \$3, $TEMP1, $TEMP2, $TEMP1
+ vpaddq $TEMP0, $ACC4, $ACC4
+ vpblendd \$3, $TEMP2, $TEMP3, $TEMP2
+ vpaddq $TEMP1, $ACC5, $ACC5
+ vpblendd \$3, $TEMP3, $TEMP4, $TEMP3
+ vpaddq $TEMP2, $ACC6, $ACC6
+ vpblendd \$3, $TEMP4, $TEMP5, $TEMP4
+ vpaddq $TEMP3, $ACC7, $ACC7
+ vpaddq $TEMP4, $ACC8, $ACC8
+
+ vpsrlq \$29, $ACC4, $TEMP1
+ vpand $AND_MASK, $ACC4, $ACC4
+ vpsrlq \$29, $ACC5, $TEMP2
+ vpand $AND_MASK, $ACC5, $ACC5
+ vpsrlq \$29, $ACC6, $TEMP3
+ vpermq \$0x93, $TEMP1, $TEMP1
+ vpand $AND_MASK, $ACC6, $ACC6
+ vpsrlq \$29, $ACC7, $TEMP4
+ vpermq \$0x93, $TEMP2, $TEMP2
+ vpand $AND_MASK, $ACC7, $ACC7
+ vpsrlq \$29, $ACC8, $TEMP5
+ vpermq \$0x93, $TEMP3, $TEMP3
+ vpand $AND_MASK, $ACC8, $ACC8
+ vpermq \$0x93, $TEMP4, $TEMP4
+
+ vpblendd \$3, $ZERO, $TEMP1, $TEMP0
+ vpermq \$0x93, $TEMP5, $TEMP5
+ vpblendd \$3, $TEMP1, $TEMP2, $TEMP1
+ vpaddq $TEMP0, $ACC4, $ACC4
+ vpblendd \$3, $TEMP2, $TEMP3, $TEMP2
+ vpaddq $TEMP1, $ACC5, $ACC5
+ vmovdqu $ACC4, 32*4-128($rp)
+ vpblendd \$3, $TEMP3, $TEMP4, $TEMP3
+ vpaddq $TEMP2, $ACC6, $ACC6
+ vmovdqu $ACC5, 32*5-128($rp)
+ vpblendd \$3, $TEMP4, $TEMP5, $TEMP4
+ vpaddq $TEMP3, $ACC7, $ACC7
+ vmovdqu $ACC6, 32*6-128($rp)
+ vpaddq $TEMP4, $ACC8, $ACC8
+ vmovdqu $ACC7, 32*7-128($rp)
+ vmovdqu $ACC8, 32*8-128($rp)
+
+ mov $rp, $ap
+ dec $rep
+ jne .LOOP_GRANDE_SQR_1024
+
+ vzeroall
+ mov %rbp, %rax
+___
+$code.=<<___ if ($win64);
+ movaps -0xd8(%rax),%xmm6
+ movaps -0xc8(%rax),%xmm7
+ movaps -0xb8(%rax),%xmm8
+ movaps -0xa8(%rax),%xmm9
+ movaps -0x98(%rax),%xmm10
+ movaps -0x88(%rax),%xmm11
+ movaps -0x78(%rax),%xmm12
+ movaps -0x68(%rax),%xmm13
+ movaps -0x58(%rax),%xmm14
+ movaps -0x48(%rax),%xmm15
+___
+$code.=<<___;
+ mov -48(%rax),%r15
+ mov -40(%rax),%r14
+ mov -32(%rax),%r13
+ mov -24(%rax),%r12
+ mov -16(%rax),%rbp
+ mov -8(%rax),%rbx
+ lea (%rax),%rsp # restore %rsp
+.Lsqr_1024_epilogue:
+ ret
+.size rsaz_1024_sqr_avx2,.-rsaz_1024_sqr_avx2
+___
+}
+
+{ # void AMM_WW(
+my $rp="%rdi"; # BN_ULONG *rp,
+my $ap="%rsi"; # const BN_ULONG *ap,
+my $bp="%rdx"; # const BN_ULONG *bp,
+my $np="%rcx"; # const BN_ULONG *np,
+my $n0="%r8d"; # unsigned int n0);
+
+# The registers that hold the accumulated redundant result
+# The AMM works on 1024 bit operands, and redundant word size is 29
+# Therefore: ceil(1024/29)/4 = 9
+my $ACC0="%ymm0";
+my $ACC1="%ymm1";
+my $ACC2="%ymm2";
+my $ACC3="%ymm3";
+my $ACC4="%ymm4";
+my $ACC5="%ymm5";
+my $ACC6="%ymm6";
+my $ACC7="%ymm7";
+my $ACC8="%ymm8";
+my $ACC9="%ymm9";
+
+# Registers that hold the broadcasted words of multiplier, currently used
+my $Bi="%ymm10";
+my $Yi="%ymm11";
+
+# Helper registers
+my $TEMP0=$ACC0;
+my $TEMP1="%ymm12";
+my $TEMP2="%ymm13";
+my $ZERO="%ymm14";
+my $AND_MASK="%ymm15";
+
+# alu registers that hold the first words of the ACC
+my $r0="%r9";
+my $r1="%r10";
+my $r2="%r11";
+my $r3="%r12";
+
+my $i="%r14d";
+my $tmp="%r15";
+
+$bp="%r13"; # reassigned argument
+
+$code.=<<___;
+.globl rsaz_1024_mul_avx2
+.type rsaz_1024_mul_avx2,\@function,5
+.align 64
+rsaz_1024_mul_avx2:
+ lea (%rsp), %rax
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+___
+$code.=<<___ if ($win64);
+ vzeroupper
+ lea -0xa8(%rsp),%rsp
+ vmovaps %xmm6,-0xd8(%rax)
+ vmovaps %xmm7,-0xc8(%rax)
+ vmovaps %xmm8,-0xb8(%rax)
+ vmovaps %xmm9,-0xa8(%rax)
+ vmovaps %xmm10,-0x98(%rax)
+ vmovaps %xmm11,-0x88(%rax)
+ vmovaps %xmm12,-0x78(%rax)
+ vmovaps %xmm13,-0x68(%rax)
+ vmovaps %xmm14,-0x58(%rax)
+ vmovaps %xmm15,-0x48(%rax)
+.Lmul_1024_body:
+___
+$code.=<<___;
+ mov %rax,%rbp
+ vzeroall
+ mov %rdx, $bp # reassigned argument
+ sub \$64,%rsp
+
+ # unaligned 256-bit load that crosses page boundary can
+ # cause severe performance degradation here, so if $ap does
+ # cross page boundary, swap it with $bp [meaning that caller
+ # is advised to lay down $ap and $bp next to each other, so
+ # that only one can cross page boundary].
+ .byte 0x67,0x67
+ mov $ap, $tmp
+ and \$4095, $tmp
+ add \$32*10, $tmp
+ shr \$12, $tmp
+ mov $ap, $tmp
+ cmovnz $bp, $ap
+ cmovnz $tmp, $bp
+
+ mov $np, $tmp
+ sub \$-128,$ap # size optimization
+ sub \$-128,$np
+ sub \$-128,$rp
+
+ and \$4095, $tmp # see if $np crosses page
+ add \$32*10, $tmp
+ .byte 0x67,0x67
+ shr \$12, $tmp
+ jz .Lmul_1024_no_n_copy
+
+ # unaligned 256-bit load that crosses page boundary can
+ # cause severe performance degradation here, so if $np does
+ # cross page boundary, copy it to stack and make sure stack
+ # frame doesn't...
+ sub \$32*10,%rsp
+ vmovdqu 32*0-128($np), $ACC0
+ and \$-512, %rsp
+ vmovdqu 32*1-128($np), $ACC1
+ vmovdqu 32*2-128($np), $ACC2
+ vmovdqu 32*3-128($np), $ACC3
+ vmovdqu 32*4-128($np), $ACC4
+ vmovdqu 32*5-128($np), $ACC5
+ vmovdqu 32*6-128($np), $ACC6
+ vmovdqu 32*7-128($np), $ACC7
+ vmovdqu 32*8-128($np), $ACC8
+ lea 64+128(%rsp),$np
+ vmovdqu $ACC0, 32*0-128($np)
+ vpxor $ACC0, $ACC0, $ACC0
+ vmovdqu $ACC1, 32*1-128($np)
+ vpxor $ACC1, $ACC1, $ACC1
+ vmovdqu $ACC2, 32*2-128($np)
+ vpxor $ACC2, $ACC2, $ACC2
+ vmovdqu $ACC3, 32*3-128($np)
+ vpxor $ACC3, $ACC3, $ACC3
+ vmovdqu $ACC4, 32*4-128($np)
+ vpxor $ACC4, $ACC4, $ACC4
+ vmovdqu $ACC5, 32*5-128($np)
+ vpxor $ACC5, $ACC5, $ACC5
+ vmovdqu $ACC6, 32*6-128($np)
+ vpxor $ACC6, $ACC6, $ACC6
+ vmovdqu $ACC7, 32*7-128($np)
+ vpxor $ACC7, $ACC7, $ACC7
+ vmovdqu $ACC8, 32*8-128($np)
+ vmovdqa $ACC0, $ACC8
+ vmovdqu $ACC9, 32*9-128($np) # $ACC9 is zero after vzeroall
+.Lmul_1024_no_n_copy:
+ and \$-64,%rsp
+
+ mov ($bp), %rbx
+ vpbroadcastq ($bp), $Bi
+ vmovdqu $ACC0, (%rsp) # clear top of stack
+ xor $r0, $r0
+ .byte 0x67
+ xor $r1, $r1
+ xor $r2, $r2
+ xor $r3, $r3
+
+ vmovdqu .Land_mask(%rip), $AND_MASK
+ mov \$9, $i
+ vmovdqu $ACC9, 32*9-128($rp) # $ACC9 is zero after vzeroall
+ jmp .Loop_mul_1024
+
+.align 32
+.Loop_mul_1024:
+ vpsrlq \$29, $ACC3, $ACC9 # correct $ACC3(*)
+ mov %rbx, %rax
+ imulq -128($ap), %rax
+ add $r0, %rax
+ mov %rbx, $r1
+ imulq 8-128($ap), $r1
+ add 8(%rsp), $r1
+
+ mov %rax, $r0
+ imull $n0, %eax
+ and \$0x1fffffff, %eax
+
+ mov %rbx, $r2
+ imulq 16-128($ap), $r2
+ add 16(%rsp), $r2
+
+ mov %rbx, $r3
+ imulq 24-128($ap), $r3
+ add 24(%rsp), $r3
+ vpmuludq 32*1-128($ap),$Bi,$TEMP0
+ vmovd %eax, $Yi
+ vpaddq $TEMP0,$ACC1,$ACC1
+ vpmuludq 32*2-128($ap),$Bi,$TEMP1
+ vpbroadcastq $Yi, $Yi
+ vpaddq $TEMP1,$ACC2,$ACC2
+ vpmuludq 32*3-128($ap),$Bi,$TEMP2
+ vpand $AND_MASK, $ACC3, $ACC3 # correct $ACC3
+ vpaddq $TEMP2,$ACC3,$ACC3
+ vpmuludq 32*4-128($ap),$Bi,$TEMP0
+ vpaddq $TEMP0,$ACC4,$ACC4
+ vpmuludq 32*5-128($ap),$Bi,$TEMP1
+ vpaddq $TEMP1,$ACC5,$ACC5
+ vpmuludq 32*6-128($ap),$Bi,$TEMP2
+ vpaddq $TEMP2,$ACC6,$ACC6
+ vpmuludq 32*7-128($ap),$Bi,$TEMP0
+ vpermq \$0x93, $ACC9, $ACC9 # correct $ACC3
+ vpaddq $TEMP0,$ACC7,$ACC7
+ vpmuludq 32*8-128($ap),$Bi,$TEMP1
+ vpbroadcastq 8($bp), $Bi
+ vpaddq $TEMP1,$ACC8,$ACC8
+
+ mov %rax,%rdx
+ imulq -128($np),%rax
+ add %rax,$r0
+ mov %rdx,%rax
+ imulq 8-128($np),%rax
+ add %rax,$r1
+ mov %rdx,%rax
+ imulq 16-128($np),%rax
+ add %rax,$r2
+ shr \$29, $r0
+ imulq 24-128($np),%rdx
+ add %rdx,$r3
+ add $r0, $r1
+
+ vpmuludq 32*1-128($np),$Yi,$TEMP2
+ vmovq $Bi, %rbx
+ vpaddq $TEMP2,$ACC1,$ACC1
+ vpmuludq 32*2-128($np),$Yi,$TEMP0
+ vpaddq $TEMP0,$ACC2,$ACC2
+ vpmuludq 32*3-128($np),$Yi,$TEMP1
+ vpaddq $TEMP1,$ACC3,$ACC3
+ vpmuludq 32*4-128($np),$Yi,$TEMP2
+ vpaddq $TEMP2,$ACC4,$ACC4
+ vpmuludq 32*5-128($np),$Yi,$TEMP0
+ vpaddq $TEMP0,$ACC5,$ACC5
+ vpmuludq 32*6-128($np),$Yi,$TEMP1
+ vpaddq $TEMP1,$ACC6,$ACC6
+ vpmuludq 32*7-128($np),$Yi,$TEMP2
+ vpblendd \$3, $ZERO, $ACC9, $ACC9 # correct $ACC3
+ vpaddq $TEMP2,$ACC7,$ACC7
+ vpmuludq 32*8-128($np),$Yi,$TEMP0
+ vpaddq $ACC9, $ACC3, $ACC3 # correct $ACC3
+ vpaddq $TEMP0,$ACC8,$ACC8
+
+ mov %rbx, %rax
+ imulq -128($ap),%rax
+ add %rax,$r1
+ vmovdqu -8+32*1-128($ap),$TEMP1
+ mov %rbx, %rax
+ imulq 8-128($ap),%rax
+ add %rax,$r2
+ vmovdqu -8+32*2-128($ap),$TEMP2
+
+ mov $r1, %rax
+ imull $n0, %eax
+ and \$0x1fffffff, %eax
+
+ imulq 16-128($ap),%rbx
+ add %rbx,$r3
+ vpmuludq $Bi,$TEMP1,$TEMP1
+ vmovd %eax, $Yi
+ vmovdqu -8+32*3-128($ap),$TEMP0
+ vpaddq $TEMP1,$ACC1,$ACC1
+ vpmuludq $Bi,$TEMP2,$TEMP2
+ vpbroadcastq $Yi, $Yi
+ vmovdqu -8+32*4-128($ap),$TEMP1
+ vpaddq $TEMP2,$ACC2,$ACC2
+ vpmuludq $Bi,$TEMP0,$TEMP0
+ vmovdqu -8+32*5-128($ap),$TEMP2
+ vpaddq $TEMP0,$ACC3,$ACC3
+ vpmuludq $Bi,$TEMP1,$TEMP1
+ vmovdqu -8+32*6-128($ap),$TEMP0
+ vpaddq $TEMP1,$ACC4,$ACC4
+ vpmuludq $Bi,$TEMP2,$TEMP2
+ vmovdqu -8+32*7-128($ap),$TEMP1
+ vpaddq $TEMP2,$ACC5,$ACC5
+ vpmuludq $Bi,$TEMP0,$TEMP0
+ vmovdqu -8+32*8-128($ap),$TEMP2
+ vpaddq $TEMP0,$ACC6,$ACC6
+ vpmuludq $Bi,$TEMP1,$TEMP1
+ vmovdqu -8+32*9-128($ap),$ACC9
+ vpaddq $TEMP1,$ACC7,$ACC7
+ vpmuludq $Bi,$TEMP2,$TEMP2
+ vpaddq $TEMP2,$ACC8,$ACC8
+ vpmuludq $Bi,$ACC9,$ACC9
+ vpbroadcastq 16($bp), $Bi
+
+ mov %rax,%rdx
+ imulq -128($np),%rax
+ add %rax,$r1
+ vmovdqu -8+32*1-128($np),$TEMP0
+ mov %rdx,%rax
+ imulq 8-128($np),%rax
+ add %rax,$r2
+ vmovdqu -8+32*2-128($np),$TEMP1
+ shr \$29, $r1
+ imulq 16-128($np),%rdx
+ add %rdx,$r3
+ add $r1, $r2
+
+ vpmuludq $Yi,$TEMP0,$TEMP0
+ vmovq $Bi, %rbx
+ vmovdqu -8+32*3-128($np),$TEMP2
+ vpaddq $TEMP0,$ACC1,$ACC1
+ vpmuludq $Yi,$TEMP1,$TEMP1
+ vmovdqu -8+32*4-128($np),$TEMP0
+ vpaddq $TEMP1,$ACC2,$ACC2
+ vpmuludq $Yi,$TEMP2,$TEMP2
+ vmovdqu -8+32*5-128($np),$TEMP1
+ vpaddq $TEMP2,$ACC3,$ACC3
+ vpmuludq $Yi,$TEMP0,$TEMP0
+ vmovdqu -8+32*6-128($np),$TEMP2
+ vpaddq $TEMP0,$ACC4,$ACC4
+ vpmuludq $Yi,$TEMP1,$TEMP1
+ vmovdqu -8+32*7-128($np),$TEMP0
+ vpaddq $TEMP1,$ACC5,$ACC5
+ vpmuludq $Yi,$TEMP2,$TEMP2
+ vmovdqu -8+32*8-128($np),$TEMP1
+ vpaddq $TEMP2,$ACC6,$ACC6
+ vpmuludq $Yi,$TEMP0,$TEMP0
+ vmovdqu -8+32*9-128($np),$TEMP2
+ vpaddq $TEMP0,$ACC7,$ACC7
+ vpmuludq $Yi,$TEMP1,$TEMP1
+ vpaddq $TEMP1,$ACC8,$ACC8
+ vpmuludq $Yi,$TEMP2,$TEMP2
+ vpaddq $TEMP2,$ACC9,$ACC9
+
+ vmovdqu -16+32*1-128($ap),$TEMP0
+ mov %rbx,%rax
+ imulq -128($ap),%rax
+ add $r2,%rax
+
+ vmovdqu -16+32*2-128($ap),$TEMP1
+ mov %rax,$r2
+ imull $n0, %eax
+ and \$0x1fffffff, %eax
+
+ imulq 8-128($ap),%rbx
+ add %rbx,$r3
+ vpmuludq $Bi,$TEMP0,$TEMP0
+ vmovd %eax, $Yi
+ vmovdqu -16+32*3-128($ap),$TEMP2
+ vpaddq $TEMP0,$ACC1,$ACC1
+ vpmuludq $Bi,$TEMP1,$TEMP1
+ vpbroadcastq $Yi, $Yi
+ vmovdqu -16+32*4-128($ap),$TEMP0
+ vpaddq $TEMP1,$ACC2,$ACC2
+ vpmuludq $Bi,$TEMP2,$TEMP2
+ vmovdqu -16+32*5-128($ap),$TEMP1
+ vpaddq $TEMP2,$ACC3,$ACC3
+ vpmuludq $Bi,$TEMP0,$TEMP0
+ vmovdqu -16+32*6-128($ap),$TEMP2
+ vpaddq $TEMP0,$ACC4,$ACC4
+ vpmuludq $Bi,$TEMP1,$TEMP1
+ vmovdqu -16+32*7-128($ap),$TEMP0
+ vpaddq $TEMP1,$ACC5,$ACC5
+ vpmuludq $Bi,$TEMP2,$TEMP2
+ vmovdqu -16+32*8-128($ap),$TEMP1
+ vpaddq $TEMP2,$ACC6,$ACC6
+ vpmuludq $Bi,$TEMP0,$TEMP0
+ vmovdqu -16+32*9-128($ap),$TEMP2
+ vpaddq $TEMP0,$ACC7,$ACC7
+ vpmuludq $Bi,$TEMP1,$TEMP1
+ vpaddq $TEMP1,$ACC8,$ACC8
+ vpmuludq $Bi,$TEMP2,$TEMP2
+ vpbroadcastq 24($bp), $Bi
+ vpaddq $TEMP2,$ACC9,$ACC9
+
+ vmovdqu -16+32*1-128($np),$TEMP0
+ mov %rax,%rdx
+ imulq -128($np),%rax
+ add %rax,$r2
+ vmovdqu -16+32*2-128($np),$TEMP1
+ imulq 8-128($np),%rdx
+ add %rdx,$r3
+ shr \$29, $r2
+
+ vpmuludq $Yi,$TEMP0,$TEMP0
+ vmovq $Bi, %rbx
+ vmovdqu -16+32*3-128($np),$TEMP2
+ vpaddq $TEMP0,$ACC1,$ACC1
+ vpmuludq $Yi,$TEMP1,$TEMP1
+ vmovdqu -16+32*4-128($np),$TEMP0
+ vpaddq $TEMP1,$ACC2,$ACC2
+ vpmuludq $Yi,$TEMP2,$TEMP2
+ vmovdqu -16+32*5-128($np),$TEMP1
+ vpaddq $TEMP2,$ACC3,$ACC3
+ vpmuludq $Yi,$TEMP0,$TEMP0
+ vmovdqu -16+32*6-128($np),$TEMP2
+ vpaddq $TEMP0,$ACC4,$ACC4
+ vpmuludq $Yi,$TEMP1,$TEMP1
+ vmovdqu -16+32*7-128($np),$TEMP0
+ vpaddq $TEMP1,$ACC5,$ACC5
+ vpmuludq $Yi,$TEMP2,$TEMP2
+ vmovdqu -16+32*8-128($np),$TEMP1
+ vpaddq $TEMP2,$ACC6,$ACC6
+ vpmuludq $Yi,$TEMP0,$TEMP0
+ vmovdqu -16+32*9-128($np),$TEMP2
+ vpaddq $TEMP0,$ACC7,$ACC7
+ vpmuludq $Yi,$TEMP1,$TEMP1
+ vmovdqu -24+32*1-128($ap),$TEMP0
+ vpaddq $TEMP1,$ACC8,$ACC8
+ vpmuludq $Yi,$TEMP2,$TEMP2
+ vmovdqu -24+32*2-128($ap),$TEMP1
+ vpaddq $TEMP2,$ACC9,$ACC9
+
+ add $r2, $r3
+ imulq -128($ap),%rbx
+ add %rbx,$r3
+
+ mov $r3, %rax
+ imull $n0, %eax
+ and \$0x1fffffff, %eax
+
+ vpmuludq $Bi,$TEMP0,$TEMP0
+ vmovd %eax, $Yi
+ vmovdqu -24+32*3-128($ap),$TEMP2
+ vpaddq $TEMP0,$ACC1,$ACC1
+ vpmuludq $Bi,$TEMP1,$TEMP1
+ vpbroadcastq $Yi, $Yi
+ vmovdqu -24+32*4-128($ap),$TEMP0
+ vpaddq $TEMP1,$ACC2,$ACC2
+ vpmuludq $Bi,$TEMP2,$TEMP2
+ vmovdqu -24+32*5-128($ap),$TEMP1
+ vpaddq $TEMP2,$ACC3,$ACC3
+ vpmuludq $Bi,$TEMP0,$TEMP0
+ vmovdqu -24+32*6-128($ap),$TEMP2
+ vpaddq $TEMP0,$ACC4,$ACC4
+ vpmuludq $Bi,$TEMP1,$TEMP1
+ vmovdqu -24+32*7-128($ap),$TEMP0
+ vpaddq $TEMP1,$ACC5,$ACC5
+ vpmuludq $Bi,$TEMP2,$TEMP2
+ vmovdqu -24+32*8-128($ap),$TEMP1
+ vpaddq $TEMP2,$ACC6,$ACC6
+ vpmuludq $Bi,$TEMP0,$TEMP0
+ vmovdqu -24+32*9-128($ap),$TEMP2
+ vpaddq $TEMP0,$ACC7,$ACC7
+ vpmuludq $Bi,$TEMP1,$TEMP1
+ vpaddq $TEMP1,$ACC8,$ACC8
+ vpmuludq $Bi,$TEMP2,$TEMP2
+ vpbroadcastq 32($bp), $Bi
+ vpaddq $TEMP2,$ACC9,$ACC9
+ add \$32, $bp # $bp++
+
+ vmovdqu -24+32*1-128($np),$TEMP0
+ imulq -128($np),%rax
+ add %rax,$r3
+ shr \$29, $r3
+
+ vmovdqu -24+32*2-128($np),$TEMP1
+ vpmuludq $Yi,$TEMP0,$TEMP0
+ vmovq $Bi, %rbx
+ vmovdqu -24+32*3-128($np),$TEMP2
+ vpaddq $TEMP0,$ACC1,$ACC0 # $ACC0==$TEMP0
+ vpmuludq $Yi,$TEMP1,$TEMP1
+ vmovdqu $ACC0, (%rsp) # transfer $r0-$r3
+ vpaddq $TEMP1,$ACC2,$ACC1
+ vmovdqu -24+32*4-128($np),$TEMP0
+ vpmuludq $Yi,$TEMP2,$TEMP2
+ vmovdqu -24+32*5-128($np),$TEMP1
+ vpaddq $TEMP2,$ACC3,$ACC2
+ vpmuludq $Yi,$TEMP0,$TEMP0
+ vmovdqu -24+32*6-128($np),$TEMP2
+ vpaddq $TEMP0,$ACC4,$ACC3
+ vpmuludq $Yi,$TEMP1,$TEMP1
+ vmovdqu -24+32*7-128($np),$TEMP0
+ vpaddq $TEMP1,$ACC5,$ACC4
+ vpmuludq $Yi,$TEMP2,$TEMP2
+ vmovdqu -24+32*8-128($np),$TEMP1
+ vpaddq $TEMP2,$ACC6,$ACC5
+ vpmuludq $Yi,$TEMP0,$TEMP0
+ vmovdqu -24+32*9-128($np),$TEMP2
+ mov $r3, $r0
+ vpaddq $TEMP0,$ACC7,$ACC6
+ vpmuludq $Yi,$TEMP1,$TEMP1
+ add (%rsp), $r0
+ vpaddq $TEMP1,$ACC8,$ACC7
+ vpmuludq $Yi,$TEMP2,$TEMP2
+ vmovq $r3, $TEMP1
+ vpaddq $TEMP2,$ACC9,$ACC8
+
+ dec $i
+ jnz .Loop_mul_1024
+___
+
+# (*) Original implementation was correcting ACC1-ACC3 for overflow
+# after 7 loop runs, or after 28 iterations, or 56 additions.
+# But as we underutilize resources, it's possible to correct in
+# each iteration with marginal performance loss. But then, as
+# we do it in each iteration, we can correct less digits, and
+# avoid performance penalties completely. Also note that we
+# correct only three digits out of four. This works because
+# most significant digit is subjected to less additions.
+
+$TEMP0 = $ACC9;
+$TEMP3 = $Bi;
+$TEMP4 = $Yi;
+$code.=<<___;
+ vpermq \$0, $AND_MASK, $AND_MASK
+ vpaddq (%rsp), $TEMP1, $ACC0
+
+ vpsrlq \$29, $ACC0, $TEMP1
+ vpand $AND_MASK, $ACC0, $ACC0
+ vpsrlq \$29, $ACC1, $TEMP2
+ vpand $AND_MASK, $ACC1, $ACC1
+ vpsrlq \$29, $ACC2, $TEMP3
+ vpermq \$0x93, $TEMP1, $TEMP1
+ vpand $AND_MASK, $ACC2, $ACC2
+ vpsrlq \$29, $ACC3, $TEMP4
+ vpermq \$0x93, $TEMP2, $TEMP2
+ vpand $AND_MASK, $ACC3, $ACC3
+
+ vpblendd \$3, $ZERO, $TEMP1, $TEMP0
+ vpermq \$0x93, $TEMP3, $TEMP3
+ vpblendd \$3, $TEMP1, $TEMP2, $TEMP1
+ vpermq \$0x93, $TEMP4, $TEMP4
+ vpaddq $TEMP0, $ACC0, $ACC0
+ vpblendd \$3, $TEMP2, $TEMP3, $TEMP2
+ vpaddq $TEMP1, $ACC1, $ACC1
+ vpblendd \$3, $TEMP3, $TEMP4, $TEMP3
+ vpaddq $TEMP2, $ACC2, $ACC2
+ vpblendd \$3, $TEMP4, $ZERO, $TEMP4
+ vpaddq $TEMP3, $ACC3, $ACC3
+ vpaddq $TEMP4, $ACC4, $ACC4
+
+ vpsrlq \$29, $ACC0, $TEMP1
+ vpand $AND_MASK, $ACC0, $ACC0
+ vpsrlq \$29, $ACC1, $TEMP2
+ vpand $AND_MASK, $ACC1, $ACC1
+ vpsrlq \$29, $ACC2, $TEMP3
+ vpermq \$0x93, $TEMP1, $TEMP1
+ vpand $AND_MASK, $ACC2, $ACC2
+ vpsrlq \$29, $ACC3, $TEMP4
+ vpermq \$0x93, $TEMP2, $TEMP2
+ vpand $AND_MASK, $ACC3, $ACC3
+ vpermq \$0x93, $TEMP3, $TEMP3
+
+ vpblendd \$3, $ZERO, $TEMP1, $TEMP0
+ vpermq \$0x93, $TEMP4, $TEMP4
+ vpblendd \$3, $TEMP1, $TEMP2, $TEMP1
+ vpaddq $TEMP0, $ACC0, $ACC0
+ vpblendd \$3, $TEMP2, $TEMP3, $TEMP2
+ vpaddq $TEMP1, $ACC1, $ACC1
+ vpblendd \$3, $TEMP3, $TEMP4, $TEMP3
+ vpaddq $TEMP2, $ACC2, $ACC2
+ vpblendd \$3, $TEMP4, $ZERO, $TEMP4
+ vpaddq $TEMP3, $ACC3, $ACC3
+ vpaddq $TEMP4, $ACC4, $ACC4
+
+ vmovdqu $ACC0, 0-128($rp)
+ vmovdqu $ACC1, 32-128($rp)
+ vmovdqu $ACC2, 64-128($rp)
+ vmovdqu $ACC3, 96-128($rp)
+___
+
+$TEMP5=$ACC0;
+$code.=<<___;
+ vpsrlq \$29, $ACC4, $TEMP1
+ vpand $AND_MASK, $ACC4, $ACC4
+ vpsrlq \$29, $ACC5, $TEMP2
+ vpand $AND_MASK, $ACC5, $ACC5
+ vpsrlq \$29, $ACC6, $TEMP3
+ vpermq \$0x93, $TEMP1, $TEMP1
+ vpand $AND_MASK, $ACC6, $ACC6
+ vpsrlq \$29, $ACC7, $TEMP4
+ vpermq \$0x93, $TEMP2, $TEMP2
+ vpand $AND_MASK, $ACC7, $ACC7
+ vpsrlq \$29, $ACC8, $TEMP5
+ vpermq \$0x93, $TEMP3, $TEMP3
+ vpand $AND_MASK, $ACC8, $ACC8
+ vpermq \$0x93, $TEMP4, $TEMP4
+
+ vpblendd \$3, $ZERO, $TEMP1, $TEMP0
+ vpermq \$0x93, $TEMP5, $TEMP5
+ vpblendd \$3, $TEMP1, $TEMP2, $TEMP1
+ vpaddq $TEMP0, $ACC4, $ACC4
+ vpblendd \$3, $TEMP2, $TEMP3, $TEMP2
+ vpaddq $TEMP1, $ACC5, $ACC5
+ vpblendd \$3, $TEMP3, $TEMP4, $TEMP3
+ vpaddq $TEMP2, $ACC6, $ACC6
+ vpblendd \$3, $TEMP4, $TEMP5, $TEMP4
+ vpaddq $TEMP3, $ACC7, $ACC7
+ vpaddq $TEMP4, $ACC8, $ACC8
+
+ vpsrlq \$29, $ACC4, $TEMP1
+ vpand $AND_MASK, $ACC4, $ACC4
+ vpsrlq \$29, $ACC5, $TEMP2
+ vpand $AND_MASK, $ACC5, $ACC5
+ vpsrlq \$29, $ACC6, $TEMP3
+ vpermq \$0x93, $TEMP1, $TEMP1
+ vpand $AND_MASK, $ACC6, $ACC6
+ vpsrlq \$29, $ACC7, $TEMP4
+ vpermq \$0x93, $TEMP2, $TEMP2
+ vpand $AND_MASK, $ACC7, $ACC7
+ vpsrlq \$29, $ACC8, $TEMP5
+ vpermq \$0x93, $TEMP3, $TEMP3
+ vpand $AND_MASK, $ACC8, $ACC8
+ vpermq \$0x93, $TEMP4, $TEMP4
+
+ vpblendd \$3, $ZERO, $TEMP1, $TEMP0
+ vpermq \$0x93, $TEMP5, $TEMP5
+ vpblendd \$3, $TEMP1, $TEMP2, $TEMP1
+ vpaddq $TEMP0, $ACC4, $ACC4
+ vpblendd \$3, $TEMP2, $TEMP3, $TEMP2
+ vpaddq $TEMP1, $ACC5, $ACC5
+ vpblendd \$3, $TEMP3, $TEMP4, $TEMP3
+ vpaddq $TEMP2, $ACC6, $ACC6
+ vpblendd \$3, $TEMP4, $TEMP5, $TEMP4
+ vpaddq $TEMP3, $ACC7, $ACC7
+ vpaddq $TEMP4, $ACC8, $ACC8
+
+ vmovdqu $ACC4, 128-128($rp)
+ vmovdqu $ACC5, 160-128($rp)
+ vmovdqu $ACC6, 192-128($rp)
+ vmovdqu $ACC7, 224-128($rp)
+ vmovdqu $ACC8, 256-128($rp)
+ vzeroupper
+
+ mov %rbp, %rax
+___
+$code.=<<___ if ($win64);
+ movaps -0xd8(%rax),%xmm6
+ movaps -0xc8(%rax),%xmm7
+ movaps -0xb8(%rax),%xmm8
+ movaps -0xa8(%rax),%xmm9
+ movaps -0x98(%rax),%xmm10
+ movaps -0x88(%rax),%xmm11
+ movaps -0x78(%rax),%xmm12
+ movaps -0x68(%rax),%xmm13
+ movaps -0x58(%rax),%xmm14
+ movaps -0x48(%rax),%xmm15
+___
+$code.=<<___;
+ mov -48(%rax),%r15
+ mov -40(%rax),%r14
+ mov -32(%rax),%r13
+ mov -24(%rax),%r12
+ mov -16(%rax),%rbp
+ mov -8(%rax),%rbx
+ lea (%rax),%rsp # restore %rsp
+.Lmul_1024_epilogue:
+ ret
+.size rsaz_1024_mul_avx2,.-rsaz_1024_mul_avx2
+___
+}
+{
+my ($out,$inp) = $win64 ? ("%rcx","%rdx") : ("%rdi","%rsi");
+my @T = map("%r$_",(8..11));
+
+$code.=<<___;
+.globl rsaz_1024_red2norm_avx2
+.type rsaz_1024_red2norm_avx2,\@abi-omnipotent
+.align 32
+rsaz_1024_red2norm_avx2:
+ sub \$-128,$inp # size optimization
+ xor %rax,%rax
+___
+
+for ($j=0,$i=0; $i<16; $i++) {
+ my $k=0;
+ while (29*$j<64*($i+1)) { # load data till boundary
+ $code.=" mov `8*$j-128`($inp), @T[0]\n";
+ $j++; $k++; push(@T,shift(@T));
+ }
+ $l=$k;
+ while ($k>1) { # shift loaded data but last value
+ $code.=" shl \$`29*($j-$k)`,@T[-$k]\n";
+ $k--;
+ }
+ $code.=<<___; # shift last value
+ mov @T[-1], @T[0]
+ shl \$`29*($j-1)`, @T[-1]
+ shr \$`-29*($j-1)`, @T[0]
+___
+ while ($l) { # accumulate all values
+ $code.=" add @T[-$l], %rax\n";
+ $l--;
+ }
+ $code.=<<___;
+ adc \$0, @T[0] # consume eventual carry
+ mov %rax, 8*$i($out)
+ mov @T[0], %rax
+___
+ push(@T,shift(@T));
+}
+$code.=<<___;
+ ret
+.size rsaz_1024_red2norm_avx2,.-rsaz_1024_red2norm_avx2
+
+.globl rsaz_1024_norm2red_avx2
+.type rsaz_1024_norm2red_avx2,\@abi-omnipotent
+.align 32
+rsaz_1024_norm2red_avx2:
+ sub \$-128,$out # size optimization
+ mov ($inp),@T[0]
+ mov \$0x1fffffff,%eax
+___
+for ($j=0,$i=0; $i<16; $i++) {
+ $code.=" mov `8*($i+1)`($inp),@T[1]\n" if ($i<15);
+ $code.=" xor @T[1],@T[1]\n" if ($i==15);
+ my $k=1;
+ while (29*($j+1)<64*($i+1)) {
+ $code.=<<___;
+ mov @T[0],@T[-$k]
+ shr \$`29*$j`,@T[-$k]
+ and %rax,@T[-$k] # &0x1fffffff
+ mov @T[-$k],`8*$j-128`($out)
+___
+ $j++; $k++;
+ }
+ $code.=<<___;
+ shrd \$`29*$j`,@T[1],@T[0]
+ and %rax,@T[0]
+ mov @T[0],`8*$j-128`($out)
+___
+ $j++;
+ push(@T,shift(@T));
+}
+$code.=<<___;
+ mov @T[0],`8*$j-128`($out) # zero
+ mov @T[0],`8*($j+1)-128`($out)
+ mov @T[0],`8*($j+2)-128`($out)
+ mov @T[0],`8*($j+3)-128`($out)
+ ret
+.size rsaz_1024_norm2red_avx2,.-rsaz_1024_norm2red_avx2
+___
+}
+{
+my ($out,$inp,$power) = $win64 ? ("%rcx","%rdx","%r8d") : ("%rdi","%rsi","%edx");
+
+$code.=<<___;
+.globl rsaz_1024_scatter5_avx2
+.type rsaz_1024_scatter5_avx2,\@abi-omnipotent
+.align 32
+rsaz_1024_scatter5_avx2:
+ vzeroupper
+ vmovdqu .Lscatter_permd(%rip),%ymm5
+ shl \$4,$power
+ lea ($out,$power),$out
+ mov \$9,%eax
+ jmp .Loop_scatter_1024
+
+.align 32
+.Loop_scatter_1024:
+ vmovdqu ($inp),%ymm0
+ lea 32($inp),$inp
+ vpermd %ymm0,%ymm5,%ymm0
+ vmovdqu %xmm0,($out)
+ lea 16*32($out),$out
+ dec %eax
+ jnz .Loop_scatter_1024
+
+ vzeroupper
+ ret
+.size rsaz_1024_scatter5_avx2,.-rsaz_1024_scatter5_avx2
+
+.globl rsaz_1024_gather5_avx2
+.type rsaz_1024_gather5_avx2,\@abi-omnipotent
+.align 32
+rsaz_1024_gather5_avx2:
+___
+$code.=<<___ if ($win64);
+ lea -0x88(%rsp),%rax
+ vzeroupper
+.LSEH_begin_rsaz_1024_gather5:
+ # I can't trust assembler to use specific encoding:-(
+ .byte 0x48,0x8d,0x60,0xe0 #lea -0x20(%rax),%rsp
+ .byte 0xc5,0xf8,0x29,0x70,0xe0 #vmovaps %xmm6,-0x20(%rax)
+ .byte 0xc5,0xf8,0x29,0x78,0xf0 #vmovaps %xmm7,-0x10(%rax)
+ .byte 0xc5,0x78,0x29,0x40,0x00 #vmovaps %xmm8,0(%rax)
+ .byte 0xc5,0x78,0x29,0x48,0x10 #vmovaps %xmm9,0x10(%rax)
+ .byte 0xc5,0x78,0x29,0x50,0x20 #vmovaps %xmm10,0x20(%rax)
+ .byte 0xc5,0x78,0x29,0x58,0x30 #vmovaps %xmm11,0x30(%rax)
+ .byte 0xc5,0x78,0x29,0x60,0x40 #vmovaps %xmm12,0x40(%rax)
+ .byte 0xc5,0x78,0x29,0x68,0x50 #vmovaps %xmm13,0x50(%rax)
+ .byte 0xc5,0x78,0x29,0x70,0x60 #vmovaps %xmm14,0x60(%rax)
+ .byte 0xc5,0x78,0x29,0x78,0x70 #vmovaps %xmm15,0x70(%rax)
+___
+$code.=<<___;
+ lea .Lgather_table(%rip),%r11
+ mov $power,%eax
+ and \$3,$power
+ shr \$2,%eax # cache line number
+ shl \$4,$power # offset within cache line
+
+ vmovdqu -32(%r11),%ymm7 # .Lgather_permd
+ vpbroadcastb 8(%r11,%rax), %xmm8
+ vpbroadcastb 7(%r11,%rax), %xmm9
+ vpbroadcastb 6(%r11,%rax), %xmm10
+ vpbroadcastb 5(%r11,%rax), %xmm11
+ vpbroadcastb 4(%r11,%rax), %xmm12
+ vpbroadcastb 3(%r11,%rax), %xmm13
+ vpbroadcastb 2(%r11,%rax), %xmm14
+ vpbroadcastb 1(%r11,%rax), %xmm15
+
+ lea 64($inp,$power),$inp
+ mov \$64,%r11 # size optimization
+ mov \$9,%eax
+ jmp .Loop_gather_1024
+
+.align 32
+.Loop_gather_1024:
+ vpand -64($inp), %xmm8,%xmm0
+ vpand ($inp), %xmm9,%xmm1
+ vpand 64($inp), %xmm10,%xmm2
+ vpand ($inp,%r11,2), %xmm11,%xmm3
+ vpor %xmm0,%xmm1,%xmm1
+ vpand 64($inp,%r11,2), %xmm12,%xmm4
+ vpor %xmm2,%xmm3,%xmm3
+ vpand ($inp,%r11,4), %xmm13,%xmm5
+ vpor %xmm1,%xmm3,%xmm3
+ vpand 64($inp,%r11,4), %xmm14,%xmm6
+ vpor %xmm4,%xmm5,%xmm5
+ vpand -128($inp,%r11,8), %xmm15,%xmm2
+ lea ($inp,%r11,8),$inp
+ vpor %xmm3,%xmm5,%xmm5
+ vpor %xmm2,%xmm6,%xmm6
+ vpor %xmm5,%xmm6,%xmm6
+ vpermd %ymm6,%ymm7,%ymm6
+ vmovdqu %ymm6,($out)
+ lea 32($out),$out
+ dec %eax
+ jnz .Loop_gather_1024
+
+ vpxor %ymm0,%ymm0,%ymm0
+ vmovdqu %ymm0,($out)
+ vzeroupper
+___
+$code.=<<___ if ($win64);
+ movaps (%rsp),%xmm6
+ movaps 0x10(%rsp),%xmm7
+ movaps 0x20(%rsp),%xmm8
+ movaps 0x30(%rsp),%xmm9
+ movaps 0x40(%rsp),%xmm10
+ movaps 0x50(%rsp),%xmm11
+ movaps 0x60(%rsp),%xmm12
+ movaps 0x70(%rsp),%xmm13
+ movaps 0x80(%rsp),%xmm14
+ movaps 0x90(%rsp),%xmm15
+ lea 0xa8(%rsp),%rsp
+.LSEH_end_rsaz_1024_gather5:
+___
+$code.=<<___;
+ ret
+.size rsaz_1024_gather5_avx2,.-rsaz_1024_gather5_avx2
+___
+}
+
+$code.=<<___;
+.extern OPENSSL_ia32cap_P
+.globl rsaz_avx2_eligible
+.type rsaz_avx2_eligible,\@abi-omnipotent
+.align 32
+rsaz_avx2_eligible:
+ mov OPENSSL_ia32cap_P+8(%rip),%eax
+___
+$code.=<<___ if ($addx);
+ mov \$`1<<8|1<<19`,%ecx
+ mov \$0,%edx
+ and %eax,%ecx
+ cmp \$`1<<8|1<<19`,%ecx # check for BMI2+AD*X
+ cmove %edx,%eax
+___
+$code.=<<___;
+ and \$`1<<5`,%eax
+ shr \$5,%eax
+ ret
+.size rsaz_avx2_eligible,.-rsaz_avx2_eligible
+
+.align 64
+.Land_mask:
+ .quad 0x1fffffff,0x1fffffff,0x1fffffff,-1
+.Lscatter_permd:
+ .long 0,2,4,6,7,7,7,7
+.Lgather_permd:
+ .long 0,7,1,7,2,7,3,7
+.Lgather_table:
+ .byte 0,0,0,0,0,0,0,0, 0xff,0,0,0,0,0,0,0
+.align 64
+___
+
+if ($win64) {
+$rec="%rcx";
+$frame="%rdx";
+$context="%r8";
+$disp="%r9";
+
+$code.=<<___
+.extern __imp_RtlVirtualUnwind
+.type rsaz_se_handler,\@abi-omnipotent
+.align 16
+rsaz_se_handler:
+ push %rsi
+ push %rdi
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+ pushfq
+ sub \$64,%rsp
+
+ mov 120($context),%rax # pull context->Rax
+ mov 248($context),%rbx # pull context->Rip
+
+ mov 8($disp),%rsi # disp->ImageBase
+ mov 56($disp),%r11 # disp->HandlerData
+
+ mov 0(%r11),%r10d # HandlerData[0]
+ lea (%rsi,%r10),%r10 # prologue label
+ cmp %r10,%rbx # context->Rip<prologue label
+ jb .Lcommon_seh_tail
+
+ mov 152($context),%rax # pull context->Rsp
+
+ mov 4(%r11),%r10d # HandlerData[1]
+ lea (%rsi,%r10),%r10 # epilogue label
+ cmp %r10,%rbx # context->Rip>=epilogue label
+ jae .Lcommon_seh_tail
+
+ mov 160($context),%rax # pull context->Rbp
+
+ mov -48(%rax),%r15
+ mov -40(%rax),%r14
+ mov -32(%rax),%r13
+ mov -24(%rax),%r12
+ mov -16(%rax),%rbp
+ mov -8(%rax),%rbx
+ mov %r15,240($context)
+ mov %r14,232($context)
+ mov %r13,224($context)
+ mov %r12,216($context)
+ mov %rbp,160($context)
+ mov %rbx,144($context)
+
+ lea -0xd8(%rax),%rsi # %xmm save area
+ lea 512($context),%rdi # & context.Xmm6
+ mov \$20,%ecx # 10*sizeof(%xmm0)/sizeof(%rax)
+ .long 0xa548f3fc # cld; rep movsq
+
+.Lcommon_seh_tail:
+ mov 8(%rax),%rdi
+ mov 16(%rax),%rsi
+ mov %rax,152($context) # restore context->Rsp
+ mov %rsi,168($context) # restore context->Rsi
+ mov %rdi,176($context) # restore context->Rdi
+
+ mov 40($disp),%rdi # disp->ContextRecord
+ mov $context,%rsi # context
+ mov \$154,%ecx # sizeof(CONTEXT)
+ .long 0xa548f3fc # cld; rep movsq
+
+ mov $disp,%rsi
+ xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER
+ mov 8(%rsi),%rdx # arg2, disp->ImageBase
+ mov 0(%rsi),%r8 # arg3, disp->ControlPc
+ mov 16(%rsi),%r9 # arg4, disp->FunctionEntry
+ mov 40(%rsi),%r10 # disp->ContextRecord
+ lea 56(%rsi),%r11 # &disp->HandlerData
+ lea 24(%rsi),%r12 # &disp->EstablisherFrame
+ mov %r10,32(%rsp) # arg5
+ mov %r11,40(%rsp) # arg6
+ mov %r12,48(%rsp) # arg7
+ mov %rcx,56(%rsp) # arg8, (NULL)
+ call *__imp_RtlVirtualUnwind(%rip)
+
+ mov \$1,%eax # ExceptionContinueSearch
+ add \$64,%rsp
+ popfq
+ pop %r15
+ pop %r14
+ pop %r13
+ pop %r12
+ pop %rbp
+ pop %rbx
+ pop %rdi
+ pop %rsi
+ ret
+.size rsaz_se_handler,.-rsaz_se_handler
+
+.section .pdata
+.align 4
+ .rva .LSEH_begin_rsaz_1024_sqr_avx2
+ .rva .LSEH_end_rsaz_1024_sqr_avx2
+ .rva .LSEH_info_rsaz_1024_sqr_avx2
+
+ .rva .LSEH_begin_rsaz_1024_mul_avx2
+ .rva .LSEH_end_rsaz_1024_mul_avx2
+ .rva .LSEH_info_rsaz_1024_mul_avx2
+
+ .rva .LSEH_begin_rsaz_1024_gather5
+ .rva .LSEH_end_rsaz_1024_gather5
+ .rva .LSEH_info_rsaz_1024_gather5
+.section .xdata
+.align 8
+.LSEH_info_rsaz_1024_sqr_avx2:
+ .byte 9,0,0,0
+ .rva rsaz_se_handler
+ .rva .Lsqr_1024_body,.Lsqr_1024_epilogue
+.LSEH_info_rsaz_1024_mul_avx2:
+ .byte 9,0,0,0
+ .rva rsaz_se_handler
+ .rva .Lmul_1024_body,.Lmul_1024_epilogue
+.LSEH_info_rsaz_1024_gather5:
+ .byte 0x01,0x33,0x16,0x00
+ .byte 0x36,0xf8,0x09,0x00 #vmovaps 0x90(rsp),xmm15
+ .byte 0x31,0xe8,0x08,0x00 #vmovaps 0x80(rsp),xmm14
+ .byte 0x2c,0xd8,0x07,0x00 #vmovaps 0x70(rsp),xmm13
+ .byte 0x27,0xc8,0x06,0x00 #vmovaps 0x60(rsp),xmm12
+ .byte 0x22,0xb8,0x05,0x00 #vmovaps 0x50(rsp),xmm11
+ .byte 0x1d,0xa8,0x04,0x00 #vmovaps 0x40(rsp),xmm10
+ .byte 0x18,0x98,0x03,0x00 #vmovaps 0x30(rsp),xmm9
+ .byte 0x13,0x88,0x02,0x00 #vmovaps 0x20(rsp),xmm8
+ .byte 0x0e,0x78,0x01,0x00 #vmovaps 0x10(rsp),xmm7
+ .byte 0x09,0x68,0x00,0x00 #vmovaps 0x00(rsp),xmm6
+ .byte 0x04,0x01,0x15,0x00 #sub rsp,0xa8
+___
+}
+
+foreach (split("\n",$code)) {
+ s/\`([^\`]*)\`/eval($1)/ge;
+
+ s/\b(sh[rl]d?\s+\$)(-?[0-9]+)/$1.$2%64/ge or
+
+ s/\b(vmov[dq])\b(.+)%ymm([0-9]+)/$1$2%xmm$3/go or
+ s/\b(vmovdqu)\b(.+)%x%ymm([0-9]+)/$1$2%xmm$3/go or
+ s/\b(vpinsr[qd])\b(.+)%ymm([0-9]+)/$1$2%xmm$3/go or
+ s/\b(vpextr[qd])\b(.+)%ymm([0-9]+)/$1$2%xmm$3/go or
+ s/\b(vpbroadcast[qd]\s+)%ymm([0-9]+)/$1%xmm$2/go;
+ print $_,"\n";
+}
+
+}}} else {{{
+print <<___; # assembler is too old
+.text
+
+.globl rsaz_avx2_eligible
+.type rsaz_avx2_eligible,\@abi-omnipotent
+rsaz_avx2_eligible:
+ xor %eax,%eax
+ ret
+.size rsaz_avx2_eligible,.-rsaz_avx2_eligible
+
+.globl rsaz_1024_sqr_avx2
+.globl rsaz_1024_mul_avx2
+.globl rsaz_1024_norm2red_avx2
+.globl rsaz_1024_red2norm_avx2
+.globl rsaz_1024_scatter5_avx2
+.globl rsaz_1024_gather5_avx2
+.type rsaz_1024_sqr_avx2,\@abi-omnipotent
+rsaz_1024_sqr_avx2:
+rsaz_1024_mul_avx2:
+rsaz_1024_norm2red_avx2:
+rsaz_1024_red2norm_avx2:
+rsaz_1024_scatter5_avx2:
+rsaz_1024_gather5_avx2:
+ .byte 0x0f,0x0b # ud2
+ ret
+.size rsaz_1024_sqr_avx2,.-rsaz_1024_sqr_avx2
+___
+}}}
+
+close STDOUT;
diff --git a/src/crypto/bn/asm/rsaz-x86_64.pl b/src/crypto/bn/asm/rsaz-x86_64.pl
new file mode 100644
index 0000000..3bd45db
--- /dev/null
+++ b/src/crypto/bn/asm/rsaz-x86_64.pl
@@ -0,0 +1,2144 @@
+#!/usr/bin/env perl
+
+##############################################################################
+# #
+# Copyright (c) 2012, Intel Corporation #
+# #
+# All rights reserved. #
+# #
+# Redistribution and use in source and binary forms, with or without #
+# modification, are permitted provided that the following conditions are #
+# met: #
+# #
+# * Redistributions of source code must retain the above copyright #
+# notice, this list of conditions and the following disclaimer. #
+# #
+# * Redistributions in binary form must reproduce the above copyright #
+# notice, this list of conditions and the following disclaimer in the #
+# documentation and/or other materials provided with the #
+# distribution. #
+# #
+# * Neither the name of the Intel Corporation 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 INTEL CORPORATION ""AS IS"" AND ANY #
+# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE #
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR #
+# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR #
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, #
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, #
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR #
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF #
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING #
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS #
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #
+# #
+##############################################################################
+# Developers and authors: #
+# Shay Gueron (1, 2), and Vlad Krasnov (1) #
+# (1) Intel Architecture Group, Microprocessor and Chipset Development, #
+# Israel Development Center, Haifa, Israel #
+# (2) University of Haifa #
+##############################################################################
+# Reference: #
+# [1] S. Gueron, "Efficient Software Implementations of Modular #
+# Exponentiation", http://eprint.iacr.org/2011/239 #
+# [2] S. Gueron, V. Krasnov. "Speeding up Big-Numbers Squaring". #
+# IEEE Proceedings of 9th International Conference on Information #
+# Technology: New Generations (ITNG 2012), 821-823 (2012). #
+# [3] S. Gueron, Efficient Software Implementations of Modular Exponentiation#
+# Journal of Cryptographic Engineering 2:31-43 (2012). #
+# [4] S. Gueron, V. Krasnov: "[PATCH] Efficient and side channel analysis #
+# resistant 512-bit and 1024-bit modular exponentiation for optimizing #
+# RSA1024 and RSA2048 on x86_64 platforms", #
+# http://rt.openssl.org/Ticket/Display.html?id=2582&user=guest&pass=guest#
+##############################################################################
+
+# While original submission covers 512- and 1024-bit exponentiation,
+# this module is limited to 512-bit version only (and as such
+# accelerates RSA1024 sign). This is because improvement for longer
+# keys is not high enough to justify the effort, highest measured
+# was ~5% on Westmere. [This is relative to OpenSSL 1.0.2, upcoming
+# for the moment of this writing!] Nor does this module implement
+# "monolithic" complete exponentiation jumbo-subroutine, but adheres
+# to more modular mixture of C and assembly. And it's optimized even
+# for processors other than Intel Core family (see table below for
+# improvement coefficients).
+# <appro@openssl.org>
+#
+# RSA1024 sign/sec this/original |this/rsax(*) this/fips(*)
+# ----------------+---------------------------
+# Opteron +13% |+5% +20%
+# Bulldozer -0% |-1% +10%
+# P4 +11% |+7% +8%
+# Westmere +5% |+14% +17%
+# Sandy Bridge +2% |+12% +29%
+# Ivy Bridge +1% |+11% +35%
+# Haswell(**) -0% |+12% +39%
+# Atom +13% |+11% +4%
+# VIA Nano +70% |+9% +25%
+#
+# (*) rsax engine and fips numbers are presented for reference
+# purposes;
+# (**) MULX was attempted, but found to give only marginal improvement;
+
+$flavour = shift;
+$output = shift;
+if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+
+$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
+( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
+die "can't locate x86_64-xlate.pl";
+
+open OUT,"| \"$^X\" $xlate $flavour $output";
+*STDOUT=*OUT;
+
+if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
+ =~ /GNU assembler version ([2-9]\.[0-9]+)/) {
+ $addx = ($1>=2.23);
+}
+
+if (!$addx && $win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) &&
+ `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)/) {
+ $addx = ($1>=2.10);
+}
+
+if (!$addx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) &&
+ `ml64 2>&1` =~ /Version ([0-9]+)\./) {
+ $addx = ($1>=12);
+}
+
+if (!$addx && `$ENV{CC} -v 2>&1` =~ /(^clang version|based on LLVM) ([3-9])\.([0-9]+)/) {
+ my $ver = $2 + $3/100.0; # 3.1->3.01, 3.10->3.10
+ $addx = ($ver>=3.03);
+}
+
+($out, $inp, $mod) = ("%rdi", "%rsi", "%rbp"); # common internal API
+{
+my ($out,$inp,$mod,$n0,$times) = ("%rdi","%rsi","%rdx","%rcx","%r8d");
+
+$code.=<<___;
+.text
+
+.extern OPENSSL_ia32cap_P
+
+.globl rsaz_512_sqr
+.type rsaz_512_sqr,\@function,5
+.align 32
+rsaz_512_sqr: # 25-29% faster than rsaz_512_mul
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+
+ subq \$128+24, %rsp
+.Lsqr_body:
+ movq $mod, %rbp # common argument
+ movq ($inp), %rdx
+ movq 8($inp), %rax
+ movq $n0, 128(%rsp)
+___
+$code.=<<___ if ($addx);
+ movl \$0x80100,%r11d
+ andl OPENSSL_ia32cap_P+8(%rip),%r11d
+ cmpl \$0x80100,%r11d # check for MULX and ADO/CX
+ je .Loop_sqrx
+___
+$code.=<<___;
+ jmp .Loop_sqr
+
+.align 32
+.Loop_sqr:
+ movl $times,128+8(%rsp)
+#first iteration
+ movq %rdx, %rbx
+ mulq %rdx
+ movq %rax, %r8
+ movq 16($inp), %rax
+ movq %rdx, %r9
+
+ mulq %rbx
+ addq %rax, %r9
+ movq 24($inp), %rax
+ movq %rdx, %r10
+ adcq \$0, %r10
+
+ mulq %rbx
+ addq %rax, %r10
+ movq 32($inp), %rax
+ movq %rdx, %r11
+ adcq \$0, %r11
+
+ mulq %rbx
+ addq %rax, %r11
+ movq 40($inp), %rax
+ movq %rdx, %r12
+ adcq \$0, %r12
+
+ mulq %rbx
+ addq %rax, %r12
+ movq 48($inp), %rax
+ movq %rdx, %r13
+ adcq \$0, %r13
+
+ mulq %rbx
+ addq %rax, %r13
+ movq 56($inp), %rax
+ movq %rdx, %r14
+ adcq \$0, %r14
+
+ mulq %rbx
+ addq %rax, %r14
+ movq %rbx, %rax
+ movq %rdx, %r15
+ adcq \$0, %r15
+
+ addq %r8, %r8 #shlq \$1, %r8
+ movq %r9, %rcx
+ adcq %r9, %r9 #shld \$1, %r8, %r9
+
+ mulq %rax
+ movq %rax, (%rsp)
+ addq %rdx, %r8
+ adcq \$0, %r9
+
+ movq %r8, 8(%rsp)
+ shrq \$63, %rcx
+
+#second iteration
+ movq 8($inp), %r8
+ movq 16($inp), %rax
+ mulq %r8
+ addq %rax, %r10
+ movq 24($inp), %rax
+ movq %rdx, %rbx
+ adcq \$0, %rbx
+
+ mulq %r8
+ addq %rax, %r11
+ movq 32($inp), %rax
+ adcq \$0, %rdx
+ addq %rbx, %r11
+ movq %rdx, %rbx
+ adcq \$0, %rbx
+
+ mulq %r8
+ addq %rax, %r12
+ movq 40($inp), %rax
+ adcq \$0, %rdx
+ addq %rbx, %r12
+ movq %rdx, %rbx
+ adcq \$0, %rbx
+
+ mulq %r8
+ addq %rax, %r13
+ movq 48($inp), %rax
+ adcq \$0, %rdx
+ addq %rbx, %r13
+ movq %rdx, %rbx
+ adcq \$0, %rbx
+
+ mulq %r8
+ addq %rax, %r14
+ movq 56($inp), %rax
+ adcq \$0, %rdx
+ addq %rbx, %r14
+ movq %rdx, %rbx
+ adcq \$0, %rbx
+
+ mulq %r8
+ addq %rax, %r15
+ movq %r8, %rax
+ adcq \$0, %rdx
+ addq %rbx, %r15
+ movq %rdx, %r8
+ movq %r10, %rdx
+ adcq \$0, %r8
+
+ add %rdx, %rdx
+ lea (%rcx,%r10,2), %r10 #shld \$1, %rcx, %r10
+ movq %r11, %rbx
+ adcq %r11, %r11 #shld \$1, %r10, %r11
+
+ mulq %rax
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq \$0, %r11
+
+ movq %r9, 16(%rsp)
+ movq %r10, 24(%rsp)
+ shrq \$63, %rbx
+
+#third iteration
+ movq 16($inp), %r9
+ movq 24($inp), %rax
+ mulq %r9
+ addq %rax, %r12
+ movq 32($inp), %rax
+ movq %rdx, %rcx
+ adcq \$0, %rcx
+
+ mulq %r9
+ addq %rax, %r13
+ movq 40($inp), %rax
+ adcq \$0, %rdx
+ addq %rcx, %r13
+ movq %rdx, %rcx
+ adcq \$0, %rcx
+
+ mulq %r9
+ addq %rax, %r14
+ movq 48($inp), %rax
+ adcq \$0, %rdx
+ addq %rcx, %r14
+ movq %rdx, %rcx
+ adcq \$0, %rcx
+
+ mulq %r9
+ movq %r12, %r10
+ lea (%rbx,%r12,2), %r12 #shld \$1, %rbx, %r12
+ addq %rax, %r15
+ movq 56($inp), %rax
+ adcq \$0, %rdx
+ addq %rcx, %r15
+ movq %rdx, %rcx
+ adcq \$0, %rcx
+
+ mulq %r9
+ shrq \$63, %r10
+ addq %rax, %r8
+ movq %r9, %rax
+ adcq \$0, %rdx
+ addq %rcx, %r8
+ movq %rdx, %r9
+ adcq \$0, %r9
+
+ movq %r13, %rcx
+ leaq (%r10,%r13,2), %r13 #shld \$1, %r12, %r13
+
+ mulq %rax
+ addq %rax, %r11
+ adcq %rdx, %r12
+ adcq \$0, %r13
+
+ movq %r11, 32(%rsp)
+ movq %r12, 40(%rsp)
+ shrq \$63, %rcx
+
+#fourth iteration
+ movq 24($inp), %r10
+ movq 32($inp), %rax
+ mulq %r10
+ addq %rax, %r14
+ movq 40($inp), %rax
+ movq %rdx, %rbx
+ adcq \$0, %rbx
+
+ mulq %r10
+ addq %rax, %r15
+ movq 48($inp), %rax
+ adcq \$0, %rdx
+ addq %rbx, %r15
+ movq %rdx, %rbx
+ adcq \$0, %rbx
+
+ mulq %r10
+ movq %r14, %r12
+ leaq (%rcx,%r14,2), %r14 #shld \$1, %rcx, %r14
+ addq %rax, %r8
+ movq 56($inp), %rax
+ adcq \$0, %rdx
+ addq %rbx, %r8
+ movq %rdx, %rbx
+ adcq \$0, %rbx
+
+ mulq %r10
+ shrq \$63, %r12
+ addq %rax, %r9
+ movq %r10, %rax
+ adcq \$0, %rdx
+ addq %rbx, %r9
+ movq %rdx, %r10
+ adcq \$0, %r10
+
+ movq %r15, %rbx
+ leaq (%r12,%r15,2),%r15 #shld \$1, %r14, %r15
+
+ mulq %rax
+ addq %rax, %r13
+ adcq %rdx, %r14
+ adcq \$0, %r15
+
+ movq %r13, 48(%rsp)
+ movq %r14, 56(%rsp)
+ shrq \$63, %rbx
+
+#fifth iteration
+ movq 32($inp), %r11
+ movq 40($inp), %rax
+ mulq %r11
+ addq %rax, %r8
+ movq 48($inp), %rax
+ movq %rdx, %rcx
+ adcq \$0, %rcx
+
+ mulq %r11
+ addq %rax, %r9
+ movq 56($inp), %rax
+ adcq \$0, %rdx
+ movq %r8, %r12
+ leaq (%rbx,%r8,2), %r8 #shld \$1, %rbx, %r8
+ addq %rcx, %r9
+ movq %rdx, %rcx
+ adcq \$0, %rcx
+
+ mulq %r11
+ shrq \$63, %r12
+ addq %rax, %r10
+ movq %r11, %rax
+ adcq \$0, %rdx
+ addq %rcx, %r10
+ movq %rdx, %r11
+ adcq \$0, %r11
+
+ movq %r9, %rcx
+ leaq (%r12,%r9,2), %r9 #shld \$1, %r8, %r9
+
+ mulq %rax
+ addq %rax, %r15
+ adcq %rdx, %r8
+ adcq \$0, %r9
+
+ movq %r15, 64(%rsp)
+ movq %r8, 72(%rsp)
+ shrq \$63, %rcx
+
+#sixth iteration
+ movq 40($inp), %r12
+ movq 48($inp), %rax
+ mulq %r12
+ addq %rax, %r10
+ movq 56($inp), %rax
+ movq %rdx, %rbx
+ adcq \$0, %rbx
+
+ mulq %r12
+ addq %rax, %r11
+ movq %r12, %rax
+ movq %r10, %r15
+ leaq (%rcx,%r10,2), %r10 #shld \$1, %rcx, %r10
+ adcq \$0, %rdx
+ shrq \$63, %r15
+ addq %rbx, %r11
+ movq %rdx, %r12
+ adcq \$0, %r12
+
+ movq %r11, %rbx
+ leaq (%r15,%r11,2), %r11 #shld \$1, %r10, %r11
+
+ mulq %rax
+ addq %rax, %r9
+ adcq %rdx, %r10
+ adcq \$0, %r11
+
+ movq %r9, 80(%rsp)
+ movq %r10, 88(%rsp)
+
+#seventh iteration
+ movq 48($inp), %r13
+ movq 56($inp), %rax
+ mulq %r13
+ addq %rax, %r12
+ movq %r13, %rax
+ movq %rdx, %r13
+ adcq \$0, %r13
+
+ xorq %r14, %r14
+ shlq \$1, %rbx
+ adcq %r12, %r12 #shld \$1, %rbx, %r12
+ adcq %r13, %r13 #shld \$1, %r12, %r13
+ adcq %r14, %r14 #shld \$1, %r13, %r14
+
+ mulq %rax
+ addq %rax, %r11
+ adcq %rdx, %r12
+ adcq \$0, %r13
+
+ movq %r11, 96(%rsp)
+ movq %r12, 104(%rsp)
+
+#eighth iteration
+ movq 56($inp), %rax
+ mulq %rax
+ addq %rax, %r13
+ adcq \$0, %rdx
+
+ addq %rdx, %r14
+
+ movq %r13, 112(%rsp)
+ movq %r14, 120(%rsp)
+
+ movq (%rsp), %r8
+ movq 8(%rsp), %r9
+ movq 16(%rsp), %r10
+ movq 24(%rsp), %r11
+ movq 32(%rsp), %r12
+ movq 40(%rsp), %r13
+ movq 48(%rsp), %r14
+ movq 56(%rsp), %r15
+
+ call __rsaz_512_reduce
+
+ addq 64(%rsp), %r8
+ adcq 72(%rsp), %r9
+ adcq 80(%rsp), %r10
+ adcq 88(%rsp), %r11
+ adcq 96(%rsp), %r12
+ adcq 104(%rsp), %r13
+ adcq 112(%rsp), %r14
+ adcq 120(%rsp), %r15
+ sbbq %rcx, %rcx
+
+ call __rsaz_512_subtract
+
+ movq %r8, %rdx
+ movq %r9, %rax
+ movl 128+8(%rsp), $times
+ movq $out, $inp
+
+ decl $times
+ jnz .Loop_sqr
+___
+if ($addx) {
+$code.=<<___;
+ jmp .Lsqr_tail
+
+.align 32
+.Loop_sqrx:
+ movl $times,128+8(%rsp)
+ movq $out, %xmm0 # off-load
+ movq %rbp, %xmm1 # off-load
+#first iteration
+ mulx %rax, %r8, %r9
+
+ mulx 16($inp), %rcx, %r10
+ xor %rbp, %rbp # cf=0, of=0
+
+ mulx 24($inp), %rax, %r11
+ adcx %rcx, %r9
+
+ mulx 32($inp), %rcx, %r12
+ adcx %rax, %r10
+
+ mulx 40($inp), %rax, %r13
+ adcx %rcx, %r11
+
+ .byte 0xc4,0x62,0xf3,0xf6,0xb6,0x30,0x00,0x00,0x00 # mulx 48($inp), %rcx, %r14
+ adcx %rax, %r12
+ adcx %rcx, %r13
+
+ .byte 0xc4,0x62,0xfb,0xf6,0xbe,0x38,0x00,0x00,0x00 # mulx 56($inp), %rax, %r15
+ adcx %rax, %r14
+ adcx %rbp, %r15 # %rbp is 0
+
+ mov %r9, %rcx
+ shld \$1, %r8, %r9
+ shl \$1, %r8
+
+ xor %ebp, %ebp
+ mulx %rdx, %rax, %rdx
+ adcx %rdx, %r8
+ mov 8($inp), %rdx
+ adcx %rbp, %r9
+
+ mov %rax, (%rsp)
+ mov %r8, 8(%rsp)
+
+#second iteration
+ mulx 16($inp), %rax, %rbx
+ adox %rax, %r10
+ adcx %rbx, %r11
+
+ .byte 0xc4,0x62,0xc3,0xf6,0x86,0x18,0x00,0x00,0x00 # mulx 24($inp), $out, %r8
+ adox $out, %r11
+ adcx %r8, %r12
+
+ mulx 32($inp), %rax, %rbx
+ adox %rax, %r12
+ adcx %rbx, %r13
+
+ mulx 40($inp), $out, %r8
+ adox $out, %r13
+ adcx %r8, %r14
+
+ .byte 0xc4,0xe2,0xfb,0xf6,0x9e,0x30,0x00,0x00,0x00 # mulx 48($inp), %rax, %rbx
+ adox %rax, %r14
+ adcx %rbx, %r15
+
+ .byte 0xc4,0x62,0xc3,0xf6,0x86,0x38,0x00,0x00,0x00 # mulx 56($inp), $out, %r8
+ adox $out, %r15
+ adcx %rbp, %r8
+ adox %rbp, %r8
+
+ mov %r11, %rbx
+ shld \$1, %r10, %r11
+ shld \$1, %rcx, %r10
+
+ xor %ebp,%ebp
+ mulx %rdx, %rax, %rcx
+ mov 16($inp), %rdx
+ adcx %rax, %r9
+ adcx %rcx, %r10
+ adcx %rbp, %r11
+
+ mov %r9, 16(%rsp)
+ .byte 0x4c,0x89,0x94,0x24,0x18,0x00,0x00,0x00 # mov %r10, 24(%rsp)
+
+#third iteration
+ .byte 0xc4,0x62,0xc3,0xf6,0x8e,0x18,0x00,0x00,0x00 # mulx 24($inp), $out, %r9
+ adox $out, %r12
+ adcx %r9, %r13
+
+ mulx 32($inp), %rax, %rcx
+ adox %rax, %r13
+ adcx %rcx, %r14
+
+ mulx 40($inp), $out, %r9
+ adox $out, %r14
+ adcx %r9, %r15
+
+ .byte 0xc4,0xe2,0xfb,0xf6,0x8e,0x30,0x00,0x00,0x00 # mulx 48($inp), %rax, %rcx
+ adox %rax, %r15
+ adcx %rcx, %r8
+
+ .byte 0xc4,0x62,0xc3,0xf6,0x8e,0x38,0x00,0x00,0x00 # mulx 56($inp), $out, %r9
+ adox $out, %r8
+ adcx %rbp, %r9
+ adox %rbp, %r9
+
+ mov %r13, %rcx
+ shld \$1, %r12, %r13
+ shld \$1, %rbx, %r12
+
+ xor %ebp, %ebp
+ mulx %rdx, %rax, %rdx
+ adcx %rax, %r11
+ adcx %rdx, %r12
+ mov 24($inp), %rdx
+ adcx %rbp, %r13
+
+ mov %r11, 32(%rsp)
+ .byte 0x4c,0x89,0xa4,0x24,0x28,0x00,0x00,0x00 # mov %r12, 40(%rsp)
+
+#fourth iteration
+ .byte 0xc4,0xe2,0xfb,0xf6,0x9e,0x20,0x00,0x00,0x00 # mulx 32($inp), %rax, %rbx
+ adox %rax, %r14
+ adcx %rbx, %r15
+
+ mulx 40($inp), $out, %r10
+ adox $out, %r15
+ adcx %r10, %r8
+
+ mulx 48($inp), %rax, %rbx
+ adox %rax, %r8
+ adcx %rbx, %r9
+
+ mulx 56($inp), $out, %r10
+ adox $out, %r9
+ adcx %rbp, %r10
+ adox %rbp, %r10
+
+ .byte 0x66
+ mov %r15, %rbx
+ shld \$1, %r14, %r15
+ shld \$1, %rcx, %r14
+
+ xor %ebp, %ebp
+ mulx %rdx, %rax, %rdx
+ adcx %rax, %r13
+ adcx %rdx, %r14
+ mov 32($inp), %rdx
+ adcx %rbp, %r15
+
+ mov %r13, 48(%rsp)
+ mov %r14, 56(%rsp)
+
+#fifth iteration
+ .byte 0xc4,0x62,0xc3,0xf6,0x9e,0x28,0x00,0x00,0x00 # mulx 40($inp), $out, %r11
+ adox $out, %r8
+ adcx %r11, %r9
+
+ mulx 48($inp), %rax, %rcx
+ adox %rax, %r9
+ adcx %rcx, %r10
+
+ mulx 56($inp), $out, %r11
+ adox $out, %r10
+ adcx %rbp, %r11
+ adox %rbp, %r11
+
+ mov %r9, %rcx
+ shld \$1, %r8, %r9
+ shld \$1, %rbx, %r8
+
+ xor %ebp, %ebp
+ mulx %rdx, %rax, %rdx
+ adcx %rax, %r15
+ adcx %rdx, %r8
+ mov 40($inp), %rdx
+ adcx %rbp, %r9
+
+ mov %r15, 64(%rsp)
+ mov %r8, 72(%rsp)
+
+#sixth iteration
+ .byte 0xc4,0xe2,0xfb,0xf6,0x9e,0x30,0x00,0x00,0x00 # mulx 48($inp), %rax, %rbx
+ adox %rax, %r10
+ adcx %rbx, %r11
+
+ .byte 0xc4,0x62,0xc3,0xf6,0xa6,0x38,0x00,0x00,0x00 # mulx 56($inp), $out, %r12
+ adox $out, %r11
+ adcx %rbp, %r12
+ adox %rbp, %r12
+
+ mov %r11, %rbx
+ shld \$1, %r10, %r11
+ shld \$1, %rcx, %r10
+
+ xor %ebp, %ebp
+ mulx %rdx, %rax, %rdx
+ adcx %rax, %r9
+ adcx %rdx, %r10
+ mov 48($inp), %rdx
+ adcx %rbp, %r11
+
+ mov %r9, 80(%rsp)
+ mov %r10, 88(%rsp)
+
+#seventh iteration
+ .byte 0xc4,0x62,0xfb,0xf6,0xae,0x38,0x00,0x00,0x00 # mulx 56($inp), %rax, %r13
+ adox %rax, %r12
+ adox %rbp, %r13
+
+ xor %r14, %r14
+ shld \$1, %r13, %r14
+ shld \$1, %r12, %r13
+ shld \$1, %rbx, %r12
+
+ xor %ebp, %ebp
+ mulx %rdx, %rax, %rdx
+ adcx %rax, %r11
+ adcx %rdx, %r12
+ mov 56($inp), %rdx
+ adcx %rbp, %r13
+
+ .byte 0x4c,0x89,0x9c,0x24,0x60,0x00,0x00,0x00 # mov %r11, 96(%rsp)
+ .byte 0x4c,0x89,0xa4,0x24,0x68,0x00,0x00,0x00 # mov %r12, 104(%rsp)
+
+#eighth iteration
+ mulx %rdx, %rax, %rdx
+ adox %rax, %r13
+ adox %rbp, %rdx
+
+ .byte 0x66
+ add %rdx, %r14
+
+ movq %r13, 112(%rsp)
+ movq %r14, 120(%rsp)
+ movq %xmm0, $out
+ movq %xmm1, %rbp
+
+ movq 128(%rsp), %rdx # pull $n0
+ movq (%rsp), %r8
+ movq 8(%rsp), %r9
+ movq 16(%rsp), %r10
+ movq 24(%rsp), %r11
+ movq 32(%rsp), %r12
+ movq 40(%rsp), %r13
+ movq 48(%rsp), %r14
+ movq 56(%rsp), %r15
+
+ call __rsaz_512_reducex
+
+ addq 64(%rsp), %r8
+ adcq 72(%rsp), %r9
+ adcq 80(%rsp), %r10
+ adcq 88(%rsp), %r11
+ adcq 96(%rsp), %r12
+ adcq 104(%rsp), %r13
+ adcq 112(%rsp), %r14
+ adcq 120(%rsp), %r15
+ sbbq %rcx, %rcx
+
+ call __rsaz_512_subtract
+
+ movq %r8, %rdx
+ movq %r9, %rax
+ movl 128+8(%rsp), $times
+ movq $out, $inp
+
+ decl $times
+ jnz .Loop_sqrx
+
+.Lsqr_tail:
+___
+}
+$code.=<<___;
+
+ leaq 128+24+48(%rsp), %rax
+ movq -48(%rax), %r15
+ movq -40(%rax), %r14
+ movq -32(%rax), %r13
+ movq -24(%rax), %r12
+ movq -16(%rax), %rbp
+ movq -8(%rax), %rbx
+ leaq (%rax), %rsp
+.Lsqr_epilogue:
+ ret
+.size rsaz_512_sqr,.-rsaz_512_sqr
+___
+}
+{
+my ($out,$ap,$bp,$mod,$n0) = ("%rdi","%rsi","%rdx","%rcx","%r8");
+$code.=<<___;
+.globl rsaz_512_mul
+.type rsaz_512_mul,\@function,5
+.align 32
+rsaz_512_mul:
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+
+ subq \$128+24, %rsp
+.Lmul_body:
+ movq $out, %xmm0 # off-load arguments
+ movq $mod, %xmm1
+ movq $n0, 128(%rsp)
+___
+$code.=<<___ if ($addx);
+ movl \$0x80100,%r11d
+ andl OPENSSL_ia32cap_P+8(%rip),%r11d
+ cmpl \$0x80100,%r11d # check for MULX and ADO/CX
+ je .Lmulx
+___
+$code.=<<___;
+ movq ($bp), %rbx # pass b[0]
+ movq $bp, %rbp # pass argument
+ call __rsaz_512_mul
+
+ movq %xmm0, $out
+ movq %xmm1, %rbp
+
+ movq (%rsp), %r8
+ movq 8(%rsp), %r9
+ movq 16(%rsp), %r10
+ movq 24(%rsp), %r11
+ movq 32(%rsp), %r12
+ movq 40(%rsp), %r13
+ movq 48(%rsp), %r14
+ movq 56(%rsp), %r15
+
+ call __rsaz_512_reduce
+___
+$code.=<<___ if ($addx);
+ jmp .Lmul_tail
+
+.align 32
+.Lmulx:
+ movq $bp, %rbp # pass argument
+ movq ($bp), %rdx # pass b[0]
+ call __rsaz_512_mulx
+
+ movq %xmm0, $out
+ movq %xmm1, %rbp
+
+ movq 128(%rsp), %rdx # pull $n0
+ movq (%rsp), %r8
+ movq 8(%rsp), %r9
+ movq 16(%rsp), %r10
+ movq 24(%rsp), %r11
+ movq 32(%rsp), %r12
+ movq 40(%rsp), %r13
+ movq 48(%rsp), %r14
+ movq 56(%rsp), %r15
+
+ call __rsaz_512_reducex
+.Lmul_tail:
+___
+$code.=<<___;
+ addq 64(%rsp), %r8
+ adcq 72(%rsp), %r9
+ adcq 80(%rsp), %r10
+ adcq 88(%rsp), %r11
+ adcq 96(%rsp), %r12
+ adcq 104(%rsp), %r13
+ adcq 112(%rsp), %r14
+ adcq 120(%rsp), %r15
+ sbbq %rcx, %rcx
+
+ call __rsaz_512_subtract
+
+ leaq 128+24+48(%rsp), %rax
+ movq -48(%rax), %r15
+ movq -40(%rax), %r14
+ movq -32(%rax), %r13
+ movq -24(%rax), %r12
+ movq -16(%rax), %rbp
+ movq -8(%rax), %rbx
+ leaq (%rax), %rsp
+.Lmul_epilogue:
+ ret
+.size rsaz_512_mul,.-rsaz_512_mul
+___
+}
+{
+my ($out,$ap,$bp,$mod,$n0,$pwr) = ("%rdi","%rsi","%rdx","%rcx","%r8","%r9d");
+$code.=<<___;
+.globl rsaz_512_mul_gather4
+.type rsaz_512_mul_gather4,\@function,6
+.align 32
+rsaz_512_mul_gather4:
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+
+ mov $pwr, $pwr
+ subq \$128+24, %rsp
+.Lmul_gather4_body:
+___
+$code.=<<___ if ($addx);
+ movl \$0x80100,%r11d
+ andl OPENSSL_ia32cap_P+8(%rip),%r11d
+ cmpl \$0x80100,%r11d # check for MULX and ADO/CX
+ je .Lmulx_gather
+___
+$code.=<<___;
+ movl 64($bp,$pwr,4), %eax
+ movq $out, %xmm0 # off-load arguments
+ movl ($bp,$pwr,4), %ebx
+ movq $mod, %xmm1
+ movq $n0, 128(%rsp)
+
+ shlq \$32, %rax
+ or %rax, %rbx
+ movq ($ap), %rax
+ movq 8($ap), %rcx
+ leaq 128($bp,$pwr,4), %rbp
+ mulq %rbx # 0 iteration
+ movq %rax, (%rsp)
+ movq %rcx, %rax
+ movq %rdx, %r8
+
+ mulq %rbx
+ movd (%rbp), %xmm4
+ addq %rax, %r8
+ movq 16($ap), %rax
+ movq %rdx, %r9
+ adcq \$0, %r9
+
+ mulq %rbx
+ movd 64(%rbp), %xmm5
+ addq %rax, %r9
+ movq 24($ap), %rax
+ movq %rdx, %r10
+ adcq \$0, %r10
+
+ mulq %rbx
+ pslldq \$4, %xmm5
+ addq %rax, %r10
+ movq 32($ap), %rax
+ movq %rdx, %r11
+ adcq \$0, %r11
+
+ mulq %rbx
+ por %xmm5, %xmm4
+ addq %rax, %r11
+ movq 40($ap), %rax
+ movq %rdx, %r12
+ adcq \$0, %r12
+
+ mulq %rbx
+ addq %rax, %r12
+ movq 48($ap), %rax
+ movq %rdx, %r13
+ adcq \$0, %r13
+
+ mulq %rbx
+ leaq 128(%rbp), %rbp
+ addq %rax, %r13
+ movq 56($ap), %rax
+ movq %rdx, %r14
+ adcq \$0, %r14
+
+ mulq %rbx
+ movq %xmm4, %rbx
+ addq %rax, %r14
+ movq ($ap), %rax
+ movq %rdx, %r15
+ adcq \$0, %r15
+
+ leaq 8(%rsp), %rdi
+ movl \$7, %ecx
+ jmp .Loop_mul_gather
+
+.align 32
+.Loop_mul_gather:
+ mulq %rbx
+ addq %rax, %r8
+ movq 8($ap), %rax
+ movq %r8, (%rdi)
+ movq %rdx, %r8
+ adcq \$0, %r8
+
+ mulq %rbx
+ movd (%rbp), %xmm4
+ addq %rax, %r9
+ movq 16($ap), %rax
+ adcq \$0, %rdx
+ addq %r9, %r8
+ movq %rdx, %r9
+ adcq \$0, %r9
+
+ mulq %rbx
+ movd 64(%rbp), %xmm5
+ addq %rax, %r10
+ movq 24($ap), %rax
+ adcq \$0, %rdx
+ addq %r10, %r9
+ movq %rdx, %r10
+ adcq \$0, %r10
+
+ mulq %rbx
+ pslldq \$4, %xmm5
+ addq %rax, %r11
+ movq 32($ap), %rax
+ adcq \$0, %rdx
+ addq %r11, %r10
+ movq %rdx, %r11
+ adcq \$0, %r11
+
+ mulq %rbx
+ por %xmm5, %xmm4
+ addq %rax, %r12
+ movq 40($ap), %rax
+ adcq \$0, %rdx
+ addq %r12, %r11
+ movq %rdx, %r12
+ adcq \$0, %r12
+
+ mulq %rbx
+ addq %rax, %r13
+ movq 48($ap), %rax
+ adcq \$0, %rdx
+ addq %r13, %r12
+ movq %rdx, %r13
+ adcq \$0, %r13
+
+ mulq %rbx
+ addq %rax, %r14
+ movq 56($ap), %rax
+ adcq \$0, %rdx
+ addq %r14, %r13
+ movq %rdx, %r14
+ adcq \$0, %r14
+
+ mulq %rbx
+ movq %xmm4, %rbx
+ addq %rax, %r15
+ movq ($ap), %rax
+ adcq \$0, %rdx
+ addq %r15, %r14
+ movq %rdx, %r15
+ adcq \$0, %r15
+
+ leaq 128(%rbp), %rbp
+ leaq 8(%rdi), %rdi
+
+ decl %ecx
+ jnz .Loop_mul_gather
+
+ movq %r8, (%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)
+
+ movq %xmm0, $out
+ movq %xmm1, %rbp
+
+ movq (%rsp), %r8
+ movq 8(%rsp), %r9
+ movq 16(%rsp), %r10
+ movq 24(%rsp), %r11
+ movq 32(%rsp), %r12
+ movq 40(%rsp), %r13
+ movq 48(%rsp), %r14
+ movq 56(%rsp), %r15
+
+ call __rsaz_512_reduce
+___
+$code.=<<___ if ($addx);
+ jmp .Lmul_gather_tail
+
+.align 32
+.Lmulx_gather:
+ mov 64($bp,$pwr,4), %eax
+ movq $out, %xmm0 # off-load arguments
+ lea 128($bp,$pwr,4), %rbp
+ mov ($bp,$pwr,4), %edx
+ movq $mod, %xmm1
+ mov $n0, 128(%rsp)
+
+ shl \$32, %rax
+ or %rax, %rdx
+ mulx ($ap), %rbx, %r8 # 0 iteration
+ mov %rbx, (%rsp)
+ xor %edi, %edi # cf=0, of=0
+
+ mulx 8($ap), %rax, %r9
+ movd (%rbp), %xmm4
+
+ mulx 16($ap), %rbx, %r10
+ movd 64(%rbp), %xmm5
+ adcx %rax, %r8
+
+ mulx 24($ap), %rax, %r11
+ pslldq \$4, %xmm5
+ adcx %rbx, %r9
+
+ mulx 32($ap), %rbx, %r12
+ por %xmm5, %xmm4
+ adcx %rax, %r10
+
+ mulx 40($ap), %rax, %r13
+ adcx %rbx, %r11
+
+ mulx 48($ap), %rbx, %r14
+ lea 128(%rbp), %rbp
+ adcx %rax, %r12
+
+ mulx 56($ap), %rax, %r15
+ movq %xmm4, %rdx
+ adcx %rbx, %r13
+ adcx %rax, %r14
+ mov %r8, %rbx
+ adcx %rdi, %r15 # %rdi is 0
+
+ mov \$-7, %rcx
+ jmp .Loop_mulx_gather
+
+.align 32
+.Loop_mulx_gather:
+ mulx ($ap), %rax, %r8
+ adcx %rax, %rbx
+ adox %r9, %r8
+
+ mulx 8($ap), %rax, %r9
+ .byte 0x66,0x0f,0x6e,0xa5,0x00,0x00,0x00,0x00 # movd (%rbp), %xmm4
+ adcx %rax, %r8
+ adox %r10, %r9
+
+ mulx 16($ap), %rax, %r10
+ movd 64(%rbp), %xmm5
+ lea 128(%rbp), %rbp
+ adcx %rax, %r9
+ adox %r11, %r10
+
+ .byte 0xc4,0x62,0xfb,0xf6,0x9e,0x18,0x00,0x00,0x00 # mulx 24($ap), %rax, %r11
+ pslldq \$4, %xmm5
+ por %xmm5, %xmm4
+ adcx %rax, %r10
+ adox %r12, %r11
+
+ mulx 32($ap), %rax, %r12
+ adcx %rax, %r11
+ adox %r13, %r12
+
+ mulx 40($ap), %rax, %r13
+ adcx %rax, %r12
+ adox %r14, %r13
+
+ .byte 0xc4,0x62,0xfb,0xf6,0xb6,0x30,0x00,0x00,0x00 # mulx 48($ap), %rax, %r14
+ adcx %rax, %r13
+ adox %r15, %r14
+
+ mulx 56($ap), %rax, %r15
+ movq %xmm4, %rdx
+ mov %rbx, 64(%rsp,%rcx,8)
+ adcx %rax, %r14
+ adox %rdi, %r15
+ mov %r8, %rbx
+ adcx %rdi, %r15 # cf=0
+
+ inc %rcx # of=0
+ jnz .Loop_mulx_gather
+
+ mov %r8, 64(%rsp)
+ mov %r9, 64+8(%rsp)
+ mov %r10, 64+16(%rsp)
+ mov %r11, 64+24(%rsp)
+ mov %r12, 64+32(%rsp)
+ mov %r13, 64+40(%rsp)
+ mov %r14, 64+48(%rsp)
+ mov %r15, 64+56(%rsp)
+
+ movq %xmm0, $out
+ movq %xmm1, %rbp
+
+ mov 128(%rsp), %rdx # pull $n0
+ mov (%rsp), %r8
+ mov 8(%rsp), %r9
+ mov 16(%rsp), %r10
+ mov 24(%rsp), %r11
+ mov 32(%rsp), %r12
+ mov 40(%rsp), %r13
+ mov 48(%rsp), %r14
+ mov 56(%rsp), %r15
+
+ call __rsaz_512_reducex
+
+.Lmul_gather_tail:
+___
+$code.=<<___;
+ addq 64(%rsp), %r8
+ adcq 72(%rsp), %r9
+ adcq 80(%rsp), %r10
+ adcq 88(%rsp), %r11
+ adcq 96(%rsp), %r12
+ adcq 104(%rsp), %r13
+ adcq 112(%rsp), %r14
+ adcq 120(%rsp), %r15
+ sbbq %rcx, %rcx
+
+ call __rsaz_512_subtract
+
+ leaq 128+24+48(%rsp), %rax
+ movq -48(%rax), %r15
+ movq -40(%rax), %r14
+ movq -32(%rax), %r13
+ movq -24(%rax), %r12
+ movq -16(%rax), %rbp
+ movq -8(%rax), %rbx
+ leaq (%rax), %rsp
+.Lmul_gather4_epilogue:
+ ret
+.size rsaz_512_mul_gather4,.-rsaz_512_mul_gather4
+___
+}
+{
+my ($out,$ap,$mod,$n0,$tbl,$pwr) = ("%rdi","%rsi","%rdx","%rcx","%r8","%r9d");
+$code.=<<___;
+.globl rsaz_512_mul_scatter4
+.type rsaz_512_mul_scatter4,\@function,6
+.align 32
+rsaz_512_mul_scatter4:
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+
+ mov $pwr, $pwr
+ subq \$128+24, %rsp
+.Lmul_scatter4_body:
+ leaq ($tbl,$pwr,4), $tbl
+ movq $out, %xmm0 # off-load arguments
+ movq $mod, %xmm1
+ movq $tbl, %xmm2
+ movq $n0, 128(%rsp)
+
+ movq $out, %rbp
+___
+$code.=<<___ if ($addx);
+ movl \$0x80100,%r11d
+ andl OPENSSL_ia32cap_P+8(%rip),%r11d
+ cmpl \$0x80100,%r11d # check for MULX and ADO/CX
+ je .Lmulx_scatter
+___
+$code.=<<___;
+ movq ($out),%rbx # pass b[0]
+ call __rsaz_512_mul
+
+ movq %xmm0, $out
+ movq %xmm1, %rbp
+
+ movq (%rsp), %r8
+ movq 8(%rsp), %r9
+ movq 16(%rsp), %r10
+ movq 24(%rsp), %r11
+ movq 32(%rsp), %r12
+ movq 40(%rsp), %r13
+ movq 48(%rsp), %r14
+ movq 56(%rsp), %r15
+
+ call __rsaz_512_reduce
+___
+$code.=<<___ if ($addx);
+ jmp .Lmul_scatter_tail
+
+.align 32
+.Lmulx_scatter:
+ movq ($out), %rdx # pass b[0]
+ call __rsaz_512_mulx
+
+ movq %xmm0, $out
+ movq %xmm1, %rbp
+
+ movq 128(%rsp), %rdx # pull $n0
+ movq (%rsp), %r8
+ movq 8(%rsp), %r9
+ movq 16(%rsp), %r10
+ movq 24(%rsp), %r11
+ movq 32(%rsp), %r12
+ movq 40(%rsp), %r13
+ movq 48(%rsp), %r14
+ movq 56(%rsp), %r15
+
+ call __rsaz_512_reducex
+
+.Lmul_scatter_tail:
+___
+$code.=<<___;
+ addq 64(%rsp), %r8
+ adcq 72(%rsp), %r9
+ adcq 80(%rsp), %r10
+ adcq 88(%rsp), %r11
+ adcq 96(%rsp), %r12
+ adcq 104(%rsp), %r13
+ adcq 112(%rsp), %r14
+ adcq 120(%rsp), %r15
+ movq %xmm2, $inp
+ sbbq %rcx, %rcx
+
+ call __rsaz_512_subtract
+
+ movl %r8d, 64*0($inp) # scatter
+ shrq \$32, %r8
+ movl %r9d, 64*2($inp)
+ shrq \$32, %r9
+ movl %r10d, 64*4($inp)
+ shrq \$32, %r10
+ movl %r11d, 64*6($inp)
+ shrq \$32, %r11
+ movl %r12d, 64*8($inp)
+ shrq \$32, %r12
+ movl %r13d, 64*10($inp)
+ shrq \$32, %r13
+ movl %r14d, 64*12($inp)
+ shrq \$32, %r14
+ movl %r15d, 64*14($inp)
+ shrq \$32, %r15
+ movl %r8d, 64*1($inp)
+ movl %r9d, 64*3($inp)
+ movl %r10d, 64*5($inp)
+ movl %r11d, 64*7($inp)
+ movl %r12d, 64*9($inp)
+ movl %r13d, 64*11($inp)
+ movl %r14d, 64*13($inp)
+ movl %r15d, 64*15($inp)
+
+ leaq 128+24+48(%rsp), %rax
+ movq -48(%rax), %r15
+ movq -40(%rax), %r14
+ movq -32(%rax), %r13
+ movq -24(%rax), %r12
+ movq -16(%rax), %rbp
+ movq -8(%rax), %rbx
+ leaq (%rax), %rsp
+.Lmul_scatter4_epilogue:
+ ret
+.size rsaz_512_mul_scatter4,.-rsaz_512_mul_scatter4
+___
+}
+{
+my ($out,$inp,$mod,$n0) = ("%rdi","%rsi","%rdx","%rcx");
+$code.=<<___;
+.globl rsaz_512_mul_by_one
+.type rsaz_512_mul_by_one,\@function,4
+.align 32
+rsaz_512_mul_by_one:
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+
+ subq \$128+24, %rsp
+.Lmul_by_one_body:
+___
+$code.=<<___ if ($addx);
+ movl OPENSSL_ia32cap_P+8(%rip),%eax
+___
+$code.=<<___;
+ movq $mod, %rbp # reassign argument
+ movq $n0, 128(%rsp)
+
+ movq ($inp), %r8
+ pxor %xmm0, %xmm0
+ movq 8($inp), %r9
+ movq 16($inp), %r10
+ movq 24($inp), %r11
+ movq 32($inp), %r12
+ movq 40($inp), %r13
+ movq 48($inp), %r14
+ movq 56($inp), %r15
+
+ movdqa %xmm0, (%rsp)
+ movdqa %xmm0, 16(%rsp)
+ movdqa %xmm0, 32(%rsp)
+ movdqa %xmm0, 48(%rsp)
+ movdqa %xmm0, 64(%rsp)
+ movdqa %xmm0, 80(%rsp)
+ movdqa %xmm0, 96(%rsp)
+___
+$code.=<<___ if ($addx);
+ andl \$0x80100,%eax
+ cmpl \$0x80100,%eax # check for MULX and ADO/CX
+ je .Lby_one_callx
+___
+$code.=<<___;
+ call __rsaz_512_reduce
+___
+$code.=<<___ if ($addx);
+ jmp .Lby_one_tail
+.align 32
+.Lby_one_callx:
+ movq 128(%rsp), %rdx # pull $n0
+ call __rsaz_512_reducex
+.Lby_one_tail:
+___
+$code.=<<___;
+ movq %r8, ($out)
+ movq %r9, 8($out)
+ movq %r10, 16($out)
+ movq %r11, 24($out)
+ movq %r12, 32($out)
+ movq %r13, 40($out)
+ movq %r14, 48($out)
+ movq %r15, 56($out)
+
+ leaq 128+24+48(%rsp), %rax
+ movq -48(%rax), %r15
+ movq -40(%rax), %r14
+ movq -32(%rax), %r13
+ movq -24(%rax), %r12
+ movq -16(%rax), %rbp
+ movq -8(%rax), %rbx
+ leaq (%rax), %rsp
+.Lmul_by_one_epilogue:
+ ret
+.size rsaz_512_mul_by_one,.-rsaz_512_mul_by_one
+___
+}
+{ # __rsaz_512_reduce
+ #
+ # input: %r8-%r15, %rbp - mod, 128(%rsp) - n0
+ # output: %r8-%r15
+ # clobbers: everything except %rbp and %rdi
+$code.=<<___;
+.type __rsaz_512_reduce,\@abi-omnipotent
+.align 32
+__rsaz_512_reduce:
+ movq %r8, %rbx
+ imulq 128+8(%rsp), %rbx
+ movq 0(%rbp), %rax
+ movl \$8, %ecx
+ jmp .Lreduction_loop
+
+.align 32
+.Lreduction_loop:
+ mulq %rbx
+ movq 8(%rbp), %rax
+ negq %r8
+ movq %rdx, %r8
+ adcq \$0, %r8
+
+ mulq %rbx
+ addq %rax, %r9
+ movq 16(%rbp), %rax
+ adcq \$0, %rdx
+ addq %r9, %r8
+ movq %rdx, %r9
+ adcq \$0, %r9
+
+ mulq %rbx
+ addq %rax, %r10
+ movq 24(%rbp), %rax
+ adcq \$0, %rdx
+ addq %r10, %r9
+ movq %rdx, %r10
+ adcq \$0, %r10
+
+ mulq %rbx
+ addq %rax, %r11
+ movq 32(%rbp), %rax
+ adcq \$0, %rdx
+ addq %r11, %r10
+ movq 128+8(%rsp), %rsi
+ #movq %rdx, %r11
+ #adcq \$0, %r11
+ adcq \$0, %rdx
+ movq %rdx, %r11
+
+ mulq %rbx
+ addq %rax, %r12
+ movq 40(%rbp), %rax
+ adcq \$0, %rdx
+ imulq %r8, %rsi
+ addq %r12, %r11
+ movq %rdx, %r12
+ adcq \$0, %r12
+
+ mulq %rbx
+ addq %rax, %r13
+ movq 48(%rbp), %rax
+ adcq \$0, %rdx
+ addq %r13, %r12
+ movq %rdx, %r13
+ adcq \$0, %r13
+
+ mulq %rbx
+ addq %rax, %r14
+ movq 56(%rbp), %rax
+ adcq \$0, %rdx
+ addq %r14, %r13
+ movq %rdx, %r14
+ adcq \$0, %r14
+
+ mulq %rbx
+ movq %rsi, %rbx
+ addq %rax, %r15
+ movq 0(%rbp), %rax
+ adcq \$0, %rdx
+ addq %r15, %r14
+ movq %rdx, %r15
+ adcq \$0, %r15
+
+ decl %ecx
+ jne .Lreduction_loop
+
+ ret
+.size __rsaz_512_reduce,.-__rsaz_512_reduce
+___
+}
+if ($addx) {
+ # __rsaz_512_reducex
+ #
+ # input: %r8-%r15, %rbp - mod, 128(%rsp) - n0
+ # output: %r8-%r15
+ # clobbers: everything except %rbp and %rdi
+$code.=<<___;
+.type __rsaz_512_reducex,\@abi-omnipotent
+.align 32
+__rsaz_512_reducex:
+ #movq 128+8(%rsp), %rdx # pull $n0
+ imulq %r8, %rdx
+ xorq %rsi, %rsi # cf=0,of=0
+ movl \$8, %ecx
+ jmp .Lreduction_loopx
+
+.align 32
+.Lreduction_loopx:
+ mov %r8, %rbx
+ mulx 0(%rbp), %rax, %r8
+ adcx %rbx, %rax
+ adox %r9, %r8
+
+ mulx 8(%rbp), %rax, %r9
+ adcx %rax, %r8
+ adox %r10, %r9
+
+ mulx 16(%rbp), %rbx, %r10
+ adcx %rbx, %r9
+ adox %r11, %r10
+
+ mulx 24(%rbp), %rbx, %r11
+ adcx %rbx, %r10
+ adox %r12, %r11
+
+ .byte 0xc4,0x62,0xe3,0xf6,0xa5,0x20,0x00,0x00,0x00 # mulx 32(%rbp), %rbx, %r12
+ mov %rdx, %rax
+ mov %r8, %rdx
+ adcx %rbx, %r11
+ adox %r13, %r12
+
+ mulx 128+8(%rsp), %rbx, %rdx
+ mov %rax, %rdx
+
+ mulx 40(%rbp), %rax, %r13
+ adcx %rax, %r12
+ adox %r14, %r13
+
+ .byte 0xc4,0x62,0xfb,0xf6,0xb5,0x30,0x00,0x00,0x00 # mulx 48(%rbp), %rax, %r14
+ adcx %rax, %r13
+ adox %r15, %r14
+
+ mulx 56(%rbp), %rax, %r15
+ mov %rbx, %rdx
+ adcx %rax, %r14
+ adox %rsi, %r15 # %rsi is 0
+ adcx %rsi, %r15 # cf=0
+
+ decl %ecx # of=0
+ jne .Lreduction_loopx
+
+ ret
+.size __rsaz_512_reducex,.-__rsaz_512_reducex
+___
+}
+{ # __rsaz_512_subtract
+ # input: %r8-%r15, %rdi - $out, %rbp - $mod, %rcx - mask
+ # output:
+ # clobbers: everything but %rdi, %rsi and %rbp
+$code.=<<___;
+.type __rsaz_512_subtract,\@abi-omnipotent
+.align 32
+__rsaz_512_subtract:
+ movq %r8, ($out)
+ movq %r9, 8($out)
+ movq %r10, 16($out)
+ movq %r11, 24($out)
+ movq %r12, 32($out)
+ movq %r13, 40($out)
+ movq %r14, 48($out)
+ movq %r15, 56($out)
+
+ movq 0($mod), %r8
+ movq 8($mod), %r9
+ negq %r8
+ notq %r9
+ andq %rcx, %r8
+ movq 16($mod), %r10
+ andq %rcx, %r9
+ notq %r10
+ movq 24($mod), %r11
+ andq %rcx, %r10
+ notq %r11
+ movq 32($mod), %r12
+ andq %rcx, %r11
+ notq %r12
+ movq 40($mod), %r13
+ andq %rcx, %r12
+ notq %r13
+ movq 48($mod), %r14
+ andq %rcx, %r13
+ notq %r14
+ movq 56($mod), %r15
+ andq %rcx, %r14
+ notq %r15
+ andq %rcx, %r15
+
+ addq ($out), %r8
+ adcq 8($out), %r9
+ adcq 16($out), %r10
+ adcq 24($out), %r11
+ adcq 32($out), %r12
+ adcq 40($out), %r13
+ adcq 48($out), %r14
+ adcq 56($out), %r15
+
+ movq %r8, ($out)
+ movq %r9, 8($out)
+ movq %r10, 16($out)
+ movq %r11, 24($out)
+ movq %r12, 32($out)
+ movq %r13, 40($out)
+ movq %r14, 48($out)
+ movq %r15, 56($out)
+
+ ret
+.size __rsaz_512_subtract,.-__rsaz_512_subtract
+___
+}
+{ # __rsaz_512_mul
+ #
+ # input: %rsi - ap, %rbp - bp
+ # ouput:
+ # clobbers: everything
+my ($ap,$bp) = ("%rsi","%rbp");
+$code.=<<___;
+.type __rsaz_512_mul,\@abi-omnipotent
+.align 32
+__rsaz_512_mul:
+ leaq 8(%rsp), %rdi
+
+ movq ($ap), %rax
+ mulq %rbx
+ movq %rax, (%rdi)
+ movq 8($ap), %rax
+ movq %rdx, %r8
+
+ mulq %rbx
+ addq %rax, %r8
+ movq 16($ap), %rax
+ movq %rdx, %r9
+ adcq \$0, %r9
+
+ mulq %rbx
+ addq %rax, %r9
+ movq 24($ap), %rax
+ movq %rdx, %r10
+ adcq \$0, %r10
+
+ mulq %rbx
+ addq %rax, %r10
+ movq 32($ap), %rax
+ movq %rdx, %r11
+ adcq \$0, %r11
+
+ mulq %rbx
+ addq %rax, %r11
+ movq 40($ap), %rax
+ movq %rdx, %r12
+ adcq \$0, %r12
+
+ mulq %rbx
+ addq %rax, %r12
+ movq 48($ap), %rax
+ movq %rdx, %r13
+ adcq \$0, %r13
+
+ mulq %rbx
+ addq %rax, %r13
+ movq 56($ap), %rax
+ movq %rdx, %r14
+ adcq \$0, %r14
+
+ mulq %rbx
+ addq %rax, %r14
+ movq ($ap), %rax
+ movq %rdx, %r15
+ adcq \$0, %r15
+
+ leaq 8($bp), $bp
+ leaq 8(%rdi), %rdi
+
+ movl \$7, %ecx
+ jmp .Loop_mul
+
+.align 32
+.Loop_mul:
+ movq ($bp), %rbx
+ mulq %rbx
+ addq %rax, %r8
+ movq 8($ap), %rax
+ movq %r8, (%rdi)
+ movq %rdx, %r8
+ adcq \$0, %r8
+
+ mulq %rbx
+ addq %rax, %r9
+ movq 16($ap), %rax
+ adcq \$0, %rdx
+ addq %r9, %r8
+ movq %rdx, %r9
+ adcq \$0, %r9
+
+ mulq %rbx
+ addq %rax, %r10
+ movq 24($ap), %rax
+ adcq \$0, %rdx
+ addq %r10, %r9
+ movq %rdx, %r10
+ adcq \$0, %r10
+
+ mulq %rbx
+ addq %rax, %r11
+ movq 32($ap), %rax
+ adcq \$0, %rdx
+ addq %r11, %r10
+ movq %rdx, %r11
+ adcq \$0, %r11
+
+ mulq %rbx
+ addq %rax, %r12
+ movq 40($ap), %rax
+ adcq \$0, %rdx
+ addq %r12, %r11
+ movq %rdx, %r12
+ adcq \$0, %r12
+
+ mulq %rbx
+ addq %rax, %r13
+ movq 48($ap), %rax
+ adcq \$0, %rdx
+ addq %r13, %r12
+ movq %rdx, %r13
+ adcq \$0, %r13
+
+ mulq %rbx
+ addq %rax, %r14
+ movq 56($ap), %rax
+ adcq \$0, %rdx
+ addq %r14, %r13
+ movq %rdx, %r14
+ leaq 8($bp), $bp
+ adcq \$0, %r14
+
+ mulq %rbx
+ addq %rax, %r15
+ movq ($ap), %rax
+ adcq \$0, %rdx
+ addq %r15, %r14
+ movq %rdx, %r15
+ adcq \$0, %r15
+
+ leaq 8(%rdi), %rdi
+
+ decl %ecx
+ jnz .Loop_mul
+
+ movq %r8, (%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)
+
+ ret
+.size __rsaz_512_mul,.-__rsaz_512_mul
+___
+}
+if ($addx) {
+ # __rsaz_512_mulx
+ #
+ # input: %rsi - ap, %rbp - bp
+ # ouput:
+ # clobbers: everything
+my ($ap,$bp,$zero) = ("%rsi","%rbp","%rdi");
+$code.=<<___;
+.type __rsaz_512_mulx,\@abi-omnipotent
+.align 32
+__rsaz_512_mulx:
+ mulx ($ap), %rbx, %r8 # initial %rdx preloaded by caller
+ mov \$-6, %rcx
+
+ mulx 8($ap), %rax, %r9
+ movq %rbx, 8(%rsp)
+
+ mulx 16($ap), %rbx, %r10
+ adc %rax, %r8
+
+ mulx 24($ap), %rax, %r11
+ adc %rbx, %r9
+
+ mulx 32($ap), %rbx, %r12
+ adc %rax, %r10
+
+ mulx 40($ap), %rax, %r13
+ adc %rbx, %r11
+
+ mulx 48($ap), %rbx, %r14
+ adc %rax, %r12
+
+ mulx 56($ap), %rax, %r15
+ mov 8($bp), %rdx
+ adc %rbx, %r13
+ adc %rax, %r14
+ adc \$0, %r15
+
+ xor $zero, $zero # cf=0,of=0
+ jmp .Loop_mulx
+
+.align 32
+.Loop_mulx:
+ movq %r8, %rbx
+ mulx ($ap), %rax, %r8
+ adcx %rax, %rbx
+ adox %r9, %r8
+
+ mulx 8($ap), %rax, %r9
+ adcx %rax, %r8
+ adox %r10, %r9
+
+ mulx 16($ap), %rax, %r10
+ adcx %rax, %r9
+ adox %r11, %r10
+
+ mulx 24($ap), %rax, %r11
+ adcx %rax, %r10
+ adox %r12, %r11
+
+ .byte 0x3e,0xc4,0x62,0xfb,0xf6,0xa6,0x20,0x00,0x00,0x00 # mulx 32($ap), %rax, %r12
+ adcx %rax, %r11
+ adox %r13, %r12
+
+ mulx 40($ap), %rax, %r13
+ adcx %rax, %r12
+ adox %r14, %r13
+
+ mulx 48($ap), %rax, %r14
+ adcx %rax, %r13
+ adox %r15, %r14
+
+ mulx 56($ap), %rax, %r15
+ movq 64($bp,%rcx,8), %rdx
+ movq %rbx, 8+64-8(%rsp,%rcx,8)
+ adcx %rax, %r14
+ adox $zero, %r15
+ adcx $zero, %r15 # cf=0
+
+ inc %rcx # of=0
+ jnz .Loop_mulx
+
+ movq %r8, %rbx
+ mulx ($ap), %rax, %r8
+ adcx %rax, %rbx
+ adox %r9, %r8
+
+ .byte 0xc4,0x62,0xfb,0xf6,0x8e,0x08,0x00,0x00,0x00 # mulx 8($ap), %rax, %r9
+ adcx %rax, %r8
+ adox %r10, %r9
+
+ .byte 0xc4,0x62,0xfb,0xf6,0x96,0x10,0x00,0x00,0x00 # mulx 16($ap), %rax, %r10
+ adcx %rax, %r9
+ adox %r11, %r10
+
+ mulx 24($ap), %rax, %r11
+ adcx %rax, %r10
+ adox %r12, %r11
+
+ mulx 32($ap), %rax, %r12
+ adcx %rax, %r11
+ adox %r13, %r12
+
+ mulx 40($ap), %rax, %r13
+ adcx %rax, %r12
+ adox %r14, %r13
+
+ .byte 0xc4,0x62,0xfb,0xf6,0xb6,0x30,0x00,0x00,0x00 # mulx 48($ap), %rax, %r14
+ adcx %rax, %r13
+ adox %r15, %r14
+
+ .byte 0xc4,0x62,0xfb,0xf6,0xbe,0x38,0x00,0x00,0x00 # mulx 56($ap), %rax, %r15
+ adcx %rax, %r14
+ adox $zero, %r15
+ adcx $zero, %r15
+
+ mov %rbx, 8+64-8(%rsp)
+ mov %r8, 8+64(%rsp)
+ mov %r9, 8+64+8(%rsp)
+ mov %r10, 8+64+16(%rsp)
+ mov %r11, 8+64+24(%rsp)
+ mov %r12, 8+64+32(%rsp)
+ mov %r13, 8+64+40(%rsp)
+ mov %r14, 8+64+48(%rsp)
+ mov %r15, 8+64+56(%rsp)
+
+ ret
+.size __rsaz_512_mulx,.-__rsaz_512_mulx
+___
+}
+{
+my ($out,$inp,$power)= $win64 ? ("%rcx","%rdx","%r8d") : ("%rdi","%rsi","%edx");
+$code.=<<___;
+.globl rsaz_512_scatter4
+.type rsaz_512_scatter4,\@abi-omnipotent
+.align 16
+rsaz_512_scatter4:
+ leaq ($out,$power,4), $out
+ movl \$8, %r9d
+ jmp .Loop_scatter
+.align 16
+.Loop_scatter:
+ movq ($inp), %rax
+ leaq 8($inp), $inp
+ movl %eax, ($out)
+ shrq \$32, %rax
+ movl %eax, 64($out)
+ leaq 128($out), $out
+ decl %r9d
+ jnz .Loop_scatter
+ ret
+.size rsaz_512_scatter4,.-rsaz_512_scatter4
+
+.globl rsaz_512_gather4
+.type rsaz_512_gather4,\@abi-omnipotent
+.align 16
+rsaz_512_gather4:
+ leaq ($inp,$power,4), $inp
+ movl \$8, %r9d
+ jmp .Loop_gather
+.align 16
+.Loop_gather:
+ movl ($inp), %eax
+ movl 64($inp), %r8d
+ leaq 128($inp), $inp
+ shlq \$32, %r8
+ or %r8, %rax
+ movq %rax, ($out)
+ leaq 8($out), $out
+ decl %r9d
+ jnz .Loop_gather
+ ret
+.size rsaz_512_gather4,.-rsaz_512_gather4
+___
+}
+
+# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame,
+# CONTEXT *context,DISPATCHER_CONTEXT *disp)
+if ($win64) {
+$rec="%rcx";
+$frame="%rdx";
+$context="%r8";
+$disp="%r9";
+
+$code.=<<___;
+.extern __imp_RtlVirtualUnwind
+.type se_handler,\@abi-omnipotent
+.align 16
+se_handler:
+ push %rsi
+ push %rdi
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+ pushfq
+ sub \$64,%rsp
+
+ mov 120($context),%rax # pull context->Rax
+ mov 248($context),%rbx # pull context->Rip
+
+ mov 8($disp),%rsi # disp->ImageBase
+ mov 56($disp),%r11 # disp->HandlerData
+
+ mov 0(%r11),%r10d # HandlerData[0]
+ lea (%rsi,%r10),%r10 # end of prologue label
+ cmp %r10,%rbx # context->Rip<end of prologue label
+ jb .Lcommon_seh_tail
+
+ mov 152($context),%rax # pull context->Rsp
+
+ mov 4(%r11),%r10d # HandlerData[1]
+ lea (%rsi,%r10),%r10 # epilogue label
+ cmp %r10,%rbx # context->Rip>=epilogue label
+ jae .Lcommon_seh_tail
+
+ lea 128+24+48(%rax),%rax
+
+ mov -8(%rax),%rbx
+ mov -16(%rax),%rbp
+ mov -24(%rax),%r12
+ mov -32(%rax),%r13
+ mov -40(%rax),%r14
+ mov -48(%rax),%r15
+ mov %rbx,144($context) # restore context->Rbx
+ mov %rbp,160($context) # restore context->Rbp
+ mov %r12,216($context) # restore context->R12
+ mov %r13,224($context) # restore context->R13
+ mov %r14,232($context) # restore context->R14
+ mov %r15,240($context) # restore context->R15
+
+.Lcommon_seh_tail:
+ mov 8(%rax),%rdi
+ mov 16(%rax),%rsi
+ mov %rax,152($context) # restore context->Rsp
+ mov %rsi,168($context) # restore context->Rsi
+ mov %rdi,176($context) # restore context->Rdi
+
+ mov 40($disp),%rdi # disp->ContextRecord
+ mov $context,%rsi # context
+ mov \$154,%ecx # sizeof(CONTEXT)
+ .long 0xa548f3fc # cld; rep movsq
+
+ mov $disp,%rsi
+ xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER
+ mov 8(%rsi),%rdx # arg2, disp->ImageBase
+ mov 0(%rsi),%r8 # arg3, disp->ControlPc
+ mov 16(%rsi),%r9 # arg4, disp->FunctionEntry
+ mov 40(%rsi),%r10 # disp->ContextRecord
+ lea 56(%rsi),%r11 # &disp->HandlerData
+ lea 24(%rsi),%r12 # &disp->EstablisherFrame
+ mov %r10,32(%rsp) # arg5
+ mov %r11,40(%rsp) # arg6
+ mov %r12,48(%rsp) # arg7
+ mov %rcx,56(%rsp) # arg8, (NULL)
+ call *__imp_RtlVirtualUnwind(%rip)
+
+ mov \$1,%eax # ExceptionContinueSearch
+ add \$64,%rsp
+ popfq
+ pop %r15
+ pop %r14
+ pop %r13
+ pop %r12
+ pop %rbp
+ pop %rbx
+ pop %rdi
+ pop %rsi
+ ret
+.size sqr_handler,.-sqr_handler
+
+.section .pdata
+.align 4
+ .rva .LSEH_begin_rsaz_512_sqr
+ .rva .LSEH_end_rsaz_512_sqr
+ .rva .LSEH_info_rsaz_512_sqr
+
+ .rva .LSEH_begin_rsaz_512_mul
+ .rva .LSEH_end_rsaz_512_mul
+ .rva .LSEH_info_rsaz_512_mul
+
+ .rva .LSEH_begin_rsaz_512_mul_gather4
+ .rva .LSEH_end_rsaz_512_mul_gather4
+ .rva .LSEH_info_rsaz_512_mul_gather4
+
+ .rva .LSEH_begin_rsaz_512_mul_scatter4
+ .rva .LSEH_end_rsaz_512_mul_scatter4
+ .rva .LSEH_info_rsaz_512_mul_scatter4
+
+ .rva .LSEH_begin_rsaz_512_mul_by_one
+ .rva .LSEH_end_rsaz_512_mul_by_one
+ .rva .LSEH_info_rsaz_512_mul_by_one
+
+.section .xdata
+.align 8
+.LSEH_info_rsaz_512_sqr:
+ .byte 9,0,0,0
+ .rva se_handler
+ .rva .Lsqr_body,.Lsqr_epilogue # HandlerData[]
+.LSEH_info_rsaz_512_mul:
+ .byte 9,0,0,0
+ .rva se_handler
+ .rva .Lmul_body,.Lmul_epilogue # HandlerData[]
+.LSEH_info_rsaz_512_mul_gather4:
+ .byte 9,0,0,0
+ .rva se_handler
+ .rva .Lmul_gather4_body,.Lmul_gather4_epilogue # HandlerData[]
+.LSEH_info_rsaz_512_mul_scatter4:
+ .byte 9,0,0,0
+ .rva se_handler
+ .rva .Lmul_scatter4_body,.Lmul_scatter4_epilogue # HandlerData[]
+.LSEH_info_rsaz_512_mul_by_one:
+ .byte 9,0,0,0
+ .rva se_handler
+ .rva .Lmul_by_one_body,.Lmul_by_one_epilogue # HandlerData[]
+___
+}
+
+$code =~ s/\`([^\`]*)\`/eval $1/gem;
+print $code;
+close STDOUT;
diff --git a/src/crypto/bn/asm/x86-mont.pl b/src/crypto/bn/asm/x86-mont.pl
new file mode 100644
index 0000000..0626b48
--- /dev/null
+++ b/src/crypto/bn/asm/x86-mont.pl
@@ -0,0 +1,592 @@
+#!/usr/bin/env perl
+
+# ====================================================================
+# Written by Andy Polyakov <appro@fy.chalmers.se> for the OpenSSL
+# project. The module is, however, dual licensed under OpenSSL and
+# CRYPTOGAMS licenses depending on where you obtain it. For further
+# details see http://www.openssl.org/~appro/cryptogams/.
+# ====================================================================
+
+# October 2005
+#
+# This is a "teaser" code, as it can be improved in several ways...
+# First of all non-SSE2 path should be implemented (yes, for now it
+# performs Montgomery multiplication/convolution only on SSE2-capable
+# CPUs such as P4, others fall down to original code). Then inner loop
+# can be unrolled and modulo-scheduled to improve ILP and possibly
+# moved to 128-bit XMM register bank (though it would require input
+# rearrangement and/or increase bus bandwidth utilization). Dedicated
+# squaring procedure should give further performance improvement...
+# Yet, for being draft, the code improves rsa512 *sign* benchmark by
+# 110%(!), rsa1024 one - by 70% and rsa4096 - by 20%:-)
+
+# December 2006
+#
+# Modulo-scheduling SSE2 loops results in further 15-20% improvement.
+# Integer-only code [being equipped with dedicated squaring procedure]
+# gives ~40% on rsa512 sign benchmark...
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+push(@INC,"${dir}","${dir}../../perlasm");
+require "x86asm.pl";
+
+&asm_init($ARGV[0],$0);
+
+$sse2=0;
+for (@ARGV) { $sse2=1 if (/-DOPENSSL_IA32_SSE2/); }
+
+&external_label("OPENSSL_ia32cap_P") if ($sse2);
+
+&function_begin("bn_mul_mont");
+
+$i="edx";
+$j="ecx";
+$ap="esi"; $tp="esi"; # overlapping variables!!!
+$rp="edi"; $bp="edi"; # overlapping variables!!!
+$np="ebp";
+$num="ebx";
+
+$_num=&DWP(4*0,"esp"); # stack top layout
+$_rp=&DWP(4*1,"esp");
+$_ap=&DWP(4*2,"esp");
+$_bp=&DWP(4*3,"esp");
+$_np=&DWP(4*4,"esp");
+$_n0=&DWP(4*5,"esp"); $_n0q=&QWP(4*5,"esp");
+$_sp=&DWP(4*6,"esp");
+$_bpend=&DWP(4*7,"esp");
+$frame=32; # size of above frame rounded up to 16n
+
+ &xor ("eax","eax");
+ &mov ("edi",&wparam(5)); # int num
+ &cmp ("edi",4);
+ &jl (&label("just_leave"));
+
+ &lea ("esi",&wparam(0)); # put aside pointer to argument block
+ &lea ("edx",&wparam(1)); # load ap
+ &mov ("ebp","esp"); # saved stack pointer!
+ &add ("edi",2); # extra two words on top of tp
+ &neg ("edi");
+ &lea ("esp",&DWP(-$frame,"esp","edi",4)); # alloca($frame+4*(num+2))
+ &neg ("edi");
+
+ # minimize cache contention by arraning 2K window between stack
+ # pointer and ap argument [np is also position sensitive vector,
+ # but it's assumed to be near ap, as it's allocated at ~same
+ # time].
+ &mov ("eax","esp");
+ &sub ("eax","edx");
+ &and ("eax",2047);
+ &sub ("esp","eax"); # this aligns sp and ap modulo 2048
+
+ &xor ("edx","esp");
+ &and ("edx",2048);
+ &xor ("edx",2048);
+ &sub ("esp","edx"); # this splits them apart modulo 4096
+
+ &and ("esp",-64); # align to cache line
+
+ ################################# load argument block...
+ &mov ("eax",&DWP(0*4,"esi"));# BN_ULONG *rp
+ &mov ("ebx",&DWP(1*4,"esi"));# const BN_ULONG *ap
+ &mov ("ecx",&DWP(2*4,"esi"));# const BN_ULONG *bp
+ &mov ("edx",&DWP(3*4,"esi"));# const BN_ULONG *np
+ &mov ("esi",&DWP(4*4,"esi"));# const BN_ULONG *n0
+ #&mov ("edi",&DWP(5*4,"esi"));# int num
+
+ &mov ("esi",&DWP(0,"esi")); # pull n0[0]
+ &mov ($_rp,"eax"); # ... save a copy of argument block
+ &mov ($_ap,"ebx");
+ &mov ($_bp,"ecx");
+ &mov ($_np,"edx");
+ &mov ($_n0,"esi");
+ &lea ($num,&DWP(-3,"edi")); # num=num-1 to assist modulo-scheduling
+ #&mov ($_num,$num); # redundant as $num is not reused
+ &mov ($_sp,"ebp"); # saved stack pointer!
+
+if($sse2) {
+$acc0="mm0"; # mmx register bank layout
+$acc1="mm1";
+$car0="mm2";
+$car1="mm3";
+$mul0="mm4";
+$mul1="mm5";
+$temp="mm6";
+$mask="mm7";
+
+ &picmeup("eax","OPENSSL_ia32cap_P");
+ &bt (&DWP(0,"eax"),26);
+ &jnc (&label("non_sse2"));
+
+ &mov ("eax",-1);
+ &movd ($mask,"eax"); # mask 32 lower bits
+
+ &mov ($ap,$_ap); # load input pointers
+ &mov ($bp,$_bp);
+ &mov ($np,$_np);
+
+ &xor ($i,$i); # i=0
+ &xor ($j,$j); # j=0
+
+ &movd ($mul0,&DWP(0,$bp)); # bp[0]
+ &movd ($mul1,&DWP(0,$ap)); # ap[0]
+ &movd ($car1,&DWP(0,$np)); # np[0]
+
+ &pmuludq($mul1,$mul0); # ap[0]*bp[0]
+ &movq ($car0,$mul1);
+ &movq ($acc0,$mul1); # I wish movd worked for
+ &pand ($acc0,$mask); # inter-register transfers
+
+ &pmuludq($mul1,$_n0q); # *=n0
+
+ &pmuludq($car1,$mul1); # "t[0]"*np[0]*n0
+ &paddq ($car1,$acc0);
+
+ &movd ($acc1,&DWP(4,$np)); # np[1]
+ &movd ($acc0,&DWP(4,$ap)); # ap[1]
+
+ &psrlq ($car0,32);
+ &psrlq ($car1,32);
+
+ &inc ($j); # j++
+&set_label("1st",16);
+ &pmuludq($acc0,$mul0); # ap[j]*bp[0]
+ &pmuludq($acc1,$mul1); # np[j]*m1
+ &paddq ($car0,$acc0); # +=c0
+ &paddq ($car1,$acc1); # +=c1
+
+ &movq ($acc0,$car0);
+ &pand ($acc0,$mask);
+ &movd ($acc1,&DWP(4,$np,$j,4)); # np[j+1]
+ &paddq ($car1,$acc0); # +=ap[j]*bp[0];
+ &movd ($acc0,&DWP(4,$ap,$j,4)); # ap[j+1]
+ &psrlq ($car0,32);
+ &movd (&DWP($frame-4,"esp",$j,4),$car1); # tp[j-1]=
+ &psrlq ($car1,32);
+
+ &lea ($j,&DWP(1,$j));
+ &cmp ($j,$num);
+ &jl (&label("1st"));
+
+ &pmuludq($acc0,$mul0); # ap[num-1]*bp[0]
+ &pmuludq($acc1,$mul1); # np[num-1]*m1
+ &paddq ($car0,$acc0); # +=c0
+ &paddq ($car1,$acc1); # +=c1
+
+ &movq ($acc0,$car0);
+ &pand ($acc0,$mask);
+ &paddq ($car1,$acc0); # +=ap[num-1]*bp[0];
+ &movd (&DWP($frame-4,"esp",$j,4),$car1); # tp[num-2]=
+
+ &psrlq ($car0,32);
+ &psrlq ($car1,32);
+
+ &paddq ($car1,$car0);
+ &movq (&QWP($frame,"esp",$num,4),$car1); # tp[num].tp[num-1]
+
+ &inc ($i); # i++
+&set_label("outer");
+ &xor ($j,$j); # j=0
+
+ &movd ($mul0,&DWP(0,$bp,$i,4)); # bp[i]
+ &movd ($mul1,&DWP(0,$ap)); # ap[0]
+ &movd ($temp,&DWP($frame,"esp")); # tp[0]
+ &movd ($car1,&DWP(0,$np)); # np[0]
+ &pmuludq($mul1,$mul0); # ap[0]*bp[i]
+
+ &paddq ($mul1,$temp); # +=tp[0]
+ &movq ($acc0,$mul1);
+ &movq ($car0,$mul1);
+ &pand ($acc0,$mask);
+
+ &pmuludq($mul1,$_n0q); # *=n0
+
+ &pmuludq($car1,$mul1);
+ &paddq ($car1,$acc0);
+
+ &movd ($temp,&DWP($frame+4,"esp")); # tp[1]
+ &movd ($acc1,&DWP(4,$np)); # np[1]
+ &movd ($acc0,&DWP(4,$ap)); # ap[1]
+
+ &psrlq ($car0,32);
+ &psrlq ($car1,32);
+ &paddq ($car0,$temp); # +=tp[1]
+
+ &inc ($j); # j++
+ &dec ($num);
+&set_label("inner");
+ &pmuludq($acc0,$mul0); # ap[j]*bp[i]
+ &pmuludq($acc1,$mul1); # np[j]*m1
+ &paddq ($car0,$acc0); # +=c0
+ &paddq ($car1,$acc1); # +=c1
+
+ &movq ($acc0,$car0);
+ &movd ($temp,&DWP($frame+4,"esp",$j,4));# tp[j+1]
+ &pand ($acc0,$mask);
+ &movd ($acc1,&DWP(4,$np,$j,4)); # np[j+1]
+ &paddq ($car1,$acc0); # +=ap[j]*bp[i]+tp[j]
+ &movd ($acc0,&DWP(4,$ap,$j,4)); # ap[j+1]
+ &psrlq ($car0,32);
+ &movd (&DWP($frame-4,"esp",$j,4),$car1);# tp[j-1]=
+ &psrlq ($car1,32);
+ &paddq ($car0,$temp); # +=tp[j+1]
+
+ &dec ($num);
+ &lea ($j,&DWP(1,$j)); # j++
+ &jnz (&label("inner"));
+
+ &mov ($num,$j);
+ &pmuludq($acc0,$mul0); # ap[num-1]*bp[i]
+ &pmuludq($acc1,$mul1); # np[num-1]*m1
+ &paddq ($car0,$acc0); # +=c0
+ &paddq ($car1,$acc1); # +=c1
+
+ &movq ($acc0,$car0);
+ &pand ($acc0,$mask);
+ &paddq ($car1,$acc0); # +=ap[num-1]*bp[i]+tp[num-1]
+ &movd (&DWP($frame-4,"esp",$j,4),$car1); # tp[num-2]=
+ &psrlq ($car0,32);
+ &psrlq ($car1,32);
+
+ &movd ($temp,&DWP($frame+4,"esp",$num,4)); # += tp[num]
+ &paddq ($car1,$car0);
+ &paddq ($car1,$temp);
+ &movq (&QWP($frame,"esp",$num,4),$car1); # tp[num].tp[num-1]
+
+ &lea ($i,&DWP(1,$i)); # i++
+ &cmp ($i,$num);
+ &jle (&label("outer"));
+
+ &emms (); # done with mmx bank
+ &jmp (&label("common_tail"));
+
+&set_label("non_sse2",16);
+}
+
+if (0) {
+ &mov ("esp",$_sp);
+ &xor ("eax","eax"); # signal "not fast enough [yet]"
+ &jmp (&label("just_leave"));
+ # While the below code provides competitive performance for
+ # all key lengthes on modern Intel cores, it's still more
+ # than 10% slower for 4096-bit key elsewhere:-( "Competitive"
+ # means compared to the original integer-only assembler.
+ # 512-bit RSA sign is better by ~40%, but that's about all
+ # one can say about all CPUs...
+} else {
+$inp="esi"; # integer path uses these registers differently
+$word="edi";
+$carry="ebp";
+
+ &mov ($inp,$_ap);
+ &lea ($carry,&DWP(1,$num));
+ &mov ($word,$_bp);
+ &xor ($j,$j); # j=0
+ &mov ("edx",$inp);
+ &and ($carry,1); # see if num is even
+ &sub ("edx",$word); # see if ap==bp
+ &lea ("eax",&DWP(4,$word,$num,4)); # &bp[num]
+ &or ($carry,"edx");
+ &mov ($word,&DWP(0,$word)); # bp[0]
+ &jz (&label("bn_sqr_mont"));
+ &mov ($_bpend,"eax");
+ &mov ("eax",&DWP(0,$inp));
+ &xor ("edx","edx");
+
+&set_label("mull",16);
+ &mov ($carry,"edx");
+ &mul ($word); # ap[j]*bp[0]
+ &add ($carry,"eax");
+ &lea ($j,&DWP(1,$j));
+ &adc ("edx",0);
+ &mov ("eax",&DWP(0,$inp,$j,4)); # ap[j+1]
+ &cmp ($j,$num);
+ &mov (&DWP($frame-4,"esp",$j,4),$carry); # tp[j]=
+ &jl (&label("mull"));
+
+ &mov ($carry,"edx");
+ &mul ($word); # ap[num-1]*bp[0]
+ &mov ($word,$_n0);
+ &add ("eax",$carry);
+ &mov ($inp,$_np);
+ &adc ("edx",0);
+ &imul ($word,&DWP($frame,"esp")); # n0*tp[0]
+
+ &mov (&DWP($frame,"esp",$num,4),"eax"); # tp[num-1]=
+ &xor ($j,$j);
+ &mov (&DWP($frame+4,"esp",$num,4),"edx"); # tp[num]=
+ &mov (&DWP($frame+8,"esp",$num,4),$j); # tp[num+1]=
+
+ &mov ("eax",&DWP(0,$inp)); # np[0]
+ &mul ($word); # np[0]*m
+ &add ("eax",&DWP($frame,"esp")); # +=tp[0]
+ &mov ("eax",&DWP(4,$inp)); # np[1]
+ &adc ("edx",0);
+ &inc ($j);
+
+ &jmp (&label("2ndmadd"));
+
+&set_label("1stmadd",16);
+ &mov ($carry,"edx");
+ &mul ($word); # ap[j]*bp[i]
+ &add ($carry,&DWP($frame,"esp",$j,4)); # +=tp[j]
+ &lea ($j,&DWP(1,$j));
+ &adc ("edx",0);
+ &add ($carry,"eax");
+ &mov ("eax",&DWP(0,$inp,$j,4)); # ap[j+1]
+ &adc ("edx",0);
+ &cmp ($j,$num);
+ &mov (&DWP($frame-4,"esp",$j,4),$carry); # tp[j]=
+ &jl (&label("1stmadd"));
+
+ &mov ($carry,"edx");
+ &mul ($word); # ap[num-1]*bp[i]
+ &add ("eax",&DWP($frame,"esp",$num,4)); # +=tp[num-1]
+ &mov ($word,$_n0);
+ &adc ("edx",0);
+ &mov ($inp,$_np);
+ &add ($carry,"eax");
+ &adc ("edx",0);
+ &imul ($word,&DWP($frame,"esp")); # n0*tp[0]
+
+ &xor ($j,$j);
+ &add ("edx",&DWP($frame+4,"esp",$num,4)); # carry+=tp[num]
+ &mov (&DWP($frame,"esp",$num,4),$carry); # tp[num-1]=
+ &adc ($j,0);
+ &mov ("eax",&DWP(0,$inp)); # np[0]
+ &mov (&DWP($frame+4,"esp",$num,4),"edx"); # tp[num]=
+ &mov (&DWP($frame+8,"esp",$num,4),$j); # tp[num+1]=
+
+ &mul ($word); # np[0]*m
+ &add ("eax",&DWP($frame,"esp")); # +=tp[0]
+ &mov ("eax",&DWP(4,$inp)); # np[1]
+ &adc ("edx",0);
+ &mov ($j,1);
+
+&set_label("2ndmadd",16);
+ &mov ($carry,"edx");
+ &mul ($word); # np[j]*m
+ &add ($carry,&DWP($frame,"esp",$j,4)); # +=tp[j]
+ &lea ($j,&DWP(1,$j));
+ &adc ("edx",0);
+ &add ($carry,"eax");
+ &mov ("eax",&DWP(0,$inp,$j,4)); # np[j+1]
+ &adc ("edx",0);
+ &cmp ($j,$num);
+ &mov (&DWP($frame-8,"esp",$j,4),$carry); # tp[j-1]=
+ &jl (&label("2ndmadd"));
+
+ &mov ($carry,"edx");
+ &mul ($word); # np[j]*m
+ &add ($carry,&DWP($frame,"esp",$num,4)); # +=tp[num-1]
+ &adc ("edx",0);
+ &add ($carry,"eax");
+ &adc ("edx",0);
+ &mov (&DWP($frame-4,"esp",$num,4),$carry); # tp[num-2]=
+
+ &xor ("eax","eax");
+ &mov ($j,$_bp); # &bp[i]
+ &add ("edx",&DWP($frame+4,"esp",$num,4)); # carry+=tp[num]
+ &adc ("eax",&DWP($frame+8,"esp",$num,4)); # +=tp[num+1]
+ &lea ($j,&DWP(4,$j));
+ &mov (&DWP($frame,"esp",$num,4),"edx"); # tp[num-1]=
+ &cmp ($j,$_bpend);
+ &mov (&DWP($frame+4,"esp",$num,4),"eax"); # tp[num]=
+ &je (&label("common_tail"));
+
+ &mov ($word,&DWP(0,$j)); # bp[i+1]
+ &mov ($inp,$_ap);
+ &mov ($_bp,$j); # &bp[++i]
+ &xor ($j,$j);
+ &xor ("edx","edx");
+ &mov ("eax",&DWP(0,$inp));
+ &jmp (&label("1stmadd"));
+
+&set_label("bn_sqr_mont",16);
+$sbit=$num;
+ &mov ($_num,$num);
+ &mov ($_bp,$j); # i=0
+
+ &mov ("eax",$word); # ap[0]
+ &mul ($word); # ap[0]*ap[0]
+ &mov (&DWP($frame,"esp"),"eax"); # tp[0]=
+ &mov ($sbit,"edx");
+ &shr ("edx",1);
+ &and ($sbit,1);
+ &inc ($j);
+&set_label("sqr",16);
+ &mov ("eax",&DWP(0,$inp,$j,4)); # ap[j]
+ &mov ($carry,"edx");
+ &mul ($word); # ap[j]*ap[0]
+ &add ("eax",$carry);
+ &lea ($j,&DWP(1,$j));
+ &adc ("edx",0);
+ &lea ($carry,&DWP(0,$sbit,"eax",2));
+ &shr ("eax",31);
+ &cmp ($j,$_num);
+ &mov ($sbit,"eax");
+ &mov (&DWP($frame-4,"esp",$j,4),$carry); # tp[j]=
+ &jl (&label("sqr"));
+
+ &mov ("eax",&DWP(0,$inp,$j,4)); # ap[num-1]
+ &mov ($carry,"edx");
+ &mul ($word); # ap[num-1]*ap[0]
+ &add ("eax",$carry);
+ &mov ($word,$_n0);
+ &adc ("edx",0);
+ &mov ($inp,$_np);
+ &lea ($carry,&DWP(0,$sbit,"eax",2));
+ &imul ($word,&DWP($frame,"esp")); # n0*tp[0]
+ &shr ("eax",31);
+ &mov (&DWP($frame,"esp",$j,4),$carry); # tp[num-1]=
+
+ &lea ($carry,&DWP(0,"eax","edx",2));
+ &mov ("eax",&DWP(0,$inp)); # np[0]
+ &shr ("edx",31);
+ &mov (&DWP($frame+4,"esp",$j,4),$carry); # tp[num]=
+ &mov (&DWP($frame+8,"esp",$j,4),"edx"); # tp[num+1]=
+
+ &mul ($word); # np[0]*m
+ &add ("eax",&DWP($frame,"esp")); # +=tp[0]
+ &mov ($num,$j);
+ &adc ("edx",0);
+ &mov ("eax",&DWP(4,$inp)); # np[1]
+ &mov ($j,1);
+
+&set_label("3rdmadd",16);
+ &mov ($carry,"edx");
+ &mul ($word); # np[j]*m
+ &add ($carry,&DWP($frame,"esp",$j,4)); # +=tp[j]
+ &adc ("edx",0);
+ &add ($carry,"eax");
+ &mov ("eax",&DWP(4,$inp,$j,4)); # np[j+1]
+ &adc ("edx",0);
+ &mov (&DWP($frame-4,"esp",$j,4),$carry); # tp[j-1]=
+
+ &mov ($carry,"edx");
+ &mul ($word); # np[j+1]*m
+ &add ($carry,&DWP($frame+4,"esp",$j,4)); # +=tp[j+1]
+ &lea ($j,&DWP(2,$j));
+ &adc ("edx",0);
+ &add ($carry,"eax");
+ &mov ("eax",&DWP(0,$inp,$j,4)); # np[j+2]
+ &adc ("edx",0);
+ &cmp ($j,$num);
+ &mov (&DWP($frame-8,"esp",$j,4),$carry); # tp[j]=
+ &jl (&label("3rdmadd"));
+
+ &mov ($carry,"edx");
+ &mul ($word); # np[j]*m
+ &add ($carry,&DWP($frame,"esp",$num,4)); # +=tp[num-1]
+ &adc ("edx",0);
+ &add ($carry,"eax");
+ &adc ("edx",0);
+ &mov (&DWP($frame-4,"esp",$num,4),$carry); # tp[num-2]=
+
+ &mov ($j,$_bp); # i
+ &xor ("eax","eax");
+ &mov ($inp,$_ap);
+ &add ("edx",&DWP($frame+4,"esp",$num,4)); # carry+=tp[num]
+ &adc ("eax",&DWP($frame+8,"esp",$num,4)); # +=tp[num+1]
+ &mov (&DWP($frame,"esp",$num,4),"edx"); # tp[num-1]=
+ &cmp ($j,$num);
+ &mov (&DWP($frame+4,"esp",$num,4),"eax"); # tp[num]=
+ &je (&label("common_tail"));
+
+ &mov ($word,&DWP(4,$inp,$j,4)); # ap[i]
+ &lea ($j,&DWP(1,$j));
+ &mov ("eax",$word);
+ &mov ($_bp,$j); # ++i
+ &mul ($word); # ap[i]*ap[i]
+ &add ("eax",&DWP($frame,"esp",$j,4)); # +=tp[i]
+ &adc ("edx",0);
+ &mov (&DWP($frame,"esp",$j,4),"eax"); # tp[i]=
+ &xor ($carry,$carry);
+ &cmp ($j,$num);
+ &lea ($j,&DWP(1,$j));
+ &je (&label("sqrlast"));
+
+ &mov ($sbit,"edx"); # zaps $num
+ &shr ("edx",1);
+ &and ($sbit,1);
+&set_label("sqradd",16);
+ &mov ("eax",&DWP(0,$inp,$j,4)); # ap[j]
+ &mov ($carry,"edx");
+ &mul ($word); # ap[j]*ap[i]
+ &add ("eax",$carry);
+ &lea ($carry,&DWP(0,"eax","eax"));
+ &adc ("edx",0);
+ &shr ("eax",31);
+ &add ($carry,&DWP($frame,"esp",$j,4)); # +=tp[j]
+ &lea ($j,&DWP(1,$j));
+ &adc ("eax",0);
+ &add ($carry,$sbit);
+ &adc ("eax",0);
+ &cmp ($j,$_num);
+ &mov (&DWP($frame-4,"esp",$j,4),$carry); # tp[j]=
+ &mov ($sbit,"eax");
+ &jle (&label("sqradd"));
+
+ &mov ($carry,"edx");
+ &add ("edx","edx");
+ &shr ($carry,31);
+ &add ("edx",$sbit);
+ &adc ($carry,0);
+&set_label("sqrlast");
+ &mov ($word,$_n0);
+ &mov ($inp,$_np);
+ &imul ($word,&DWP($frame,"esp")); # n0*tp[0]
+
+ &add ("edx",&DWP($frame,"esp",$j,4)); # +=tp[num]
+ &mov ("eax",&DWP(0,$inp)); # np[0]
+ &adc ($carry,0);
+ &mov (&DWP($frame,"esp",$j,4),"edx"); # tp[num]=
+ &mov (&DWP($frame+4,"esp",$j,4),$carry); # tp[num+1]=
+
+ &mul ($word); # np[0]*m
+ &add ("eax",&DWP($frame,"esp")); # +=tp[0]
+ &lea ($num,&DWP(-1,$j));
+ &adc ("edx",0);
+ &mov ($j,1);
+ &mov ("eax",&DWP(4,$inp)); # np[1]
+
+ &jmp (&label("3rdmadd"));
+}
+
+&set_label("common_tail",16);
+ &mov ($np,$_np); # load modulus pointer
+ &mov ($rp,$_rp); # load result pointer
+ &lea ($tp,&DWP($frame,"esp")); # [$ap and $bp are zapped]
+
+ &mov ("eax",&DWP(0,$tp)); # tp[0]
+ &mov ($j,$num); # j=num-1
+ &xor ($i,$i); # i=0 and clear CF!
+
+&set_label("sub",16);
+ &sbb ("eax",&DWP(0,$np,$i,4));
+ &mov (&DWP(0,$rp,$i,4),"eax"); # rp[i]=tp[i]-np[i]
+ &dec ($j); # doesn't affect CF!
+ &mov ("eax",&DWP(4,$tp,$i,4)); # tp[i+1]
+ &lea ($i,&DWP(1,$i)); # i++
+ &jge (&label("sub"));
+
+ &sbb ("eax",0); # handle upmost overflow bit
+
+&set_label("copy",16); # copy or in-place refresh
+ &mov ("edx",&DWP(0,$tp,$num,4));
+ &mov ($np,&DWP(0,$rp,$num,4));
+ &xor ("edx",$np); # conditional select
+ &and ("edx","eax");
+ &xor ("edx",$np);
+ &mov (&DWP(0,$tp,$num,4),$j) # zap temporary vector
+ &mov (&DWP(0,$rp,$num,4),"edx"); # rp[i]=tp[i]
+ &dec ($num);
+ &jge (&label("copy"));
+
+ &mov ("esp",$_sp); # pull saved stack pointer
+ &mov ("eax",1);
+&set_label("just_leave");
+&function_end("bn_mul_mont");
+
+&asciz("Montgomery Multiplication for x86, CRYPTOGAMS by <appro\@openssl.org>");
+
+&asm_finish();
diff --git a/src/crypto/bn/asm/x86_64-gcc.c b/src/crypto/bn/asm/x86_64-gcc.c
new file mode 100644
index 0000000..b3d1965
--- /dev/null
+++ b/src/crypto/bn/asm/x86_64-gcc.c
@@ -0,0 +1,579 @@
+#include <openssl/bn.h>
+
+#if defined(OPENSSL_X86_64) && !defined(OPENSSL_WINDOWS)
+
+#include "../internal.h"
+
+/* x86_64 BIGNUM accelerator version 0.1, December 2002.
+ *
+ * Implemented by Andy Polyakov <appro@fy.chalmers.se> for the OpenSSL
+ * project.
+ *
+ * Rights for redistribution and usage in source and binary forms are
+ * granted according to the OpenSSL license. Warranty of any kind is
+ * disclaimed.
+ *
+ * Q. Version 0.1? It doesn't sound like Andy, he used to assign real
+ * versions, like 1.0...
+ * A. Well, that's because this code is basically a quick-n-dirty
+ * proof-of-concept hack. As you can see it's implemented with
+ * inline assembler, which means that you're bound to GCC and that
+ * there might be enough room for further improvement.
+ *
+ * Q. Why inline assembler?
+ * A. x86_64 features own ABI which I'm not familiar with. This is
+ * why I decided to let the compiler take care of subroutine
+ * prologue/epilogue as well as register allocation. For reference.
+ * Win64 implements different ABI for AMD64, different from Linux.
+ *
+ * Q. How much faster does it get?
+ * A. 'apps/openssl speed rsa dsa' output with no-asm:
+ *
+ * sign verify sign/s verify/s
+ * rsa 512 bits 0.0006s 0.0001s 1683.8 18456.2
+ * rsa 1024 bits 0.0028s 0.0002s 356.0 6407.0
+ * rsa 2048 bits 0.0172s 0.0005s 58.0 1957.8
+ * rsa 4096 bits 0.1155s 0.0018s 8.7 555.6
+ * sign verify sign/s verify/s
+ * dsa 512 bits 0.0005s 0.0006s 2100.8 1768.3
+ * dsa 1024 bits 0.0014s 0.0018s 692.3 559.2
+ * dsa 2048 bits 0.0049s 0.0061s 204.7 165.0
+ *
+ * 'apps/openssl speed rsa dsa' output with this module:
+ *
+ * sign verify sign/s verify/s
+ * rsa 512 bits 0.0004s 0.0000s 2767.1 33297.9
+ * rsa 1024 bits 0.0012s 0.0001s 867.4 14674.7
+ * rsa 2048 bits 0.0061s 0.0002s 164.0 5270.0
+ * rsa 4096 bits 0.0384s 0.0006s 26.1 1650.8
+ * sign verify sign/s verify/s
+ * dsa 512 bits 0.0002s 0.0003s 4442.2 3786.3
+ * dsa 1024 bits 0.0005s 0.0007s 1835.1 1497.4
+ * dsa 2048 bits 0.0016s 0.0020s 620.4 504.6
+ *
+ * For the reference. IA-32 assembler implementation performs
+ * very much like 64-bit code compiled with no-asm on the same
+ * machine.
+ */
+
+ /* TODO(davidben): Get this file working on Windows x64. */
+
+#undef mul
+#undef mul_add
+
+#define asm __asm__
+
+/*
+ * "m"(a), "+m"(r) is the way to favor DirectPath µ-code;
+ * "g"(0) let the compiler to decide where does it
+ * want to keep the value of zero;
+ */
+#define mul_add(r, a, word, carry) \
+ do { \
+ register BN_ULONG high, low; \
+ asm("mulq %3" : "=a"(low), "=d"(high) : "a"(word), "m"(a) : "cc"); \
+ asm("addq %2,%0; adcq %3,%1" \
+ : "+r"(carry), "+d"(high) \
+ : "a"(low), "g"(0) \
+ : "cc"); \
+ asm("addq %2,%0; adcq %3,%1" \
+ : "+m"(r), "+d"(high) \
+ : "r"(carry), "g"(0) \
+ : "cc"); \
+ carry = high; \
+ } while (0)
+
+#define mul(r, a, word, carry) \
+ do { \
+ register BN_ULONG high, low; \
+ asm("mulq %3" : "=a"(low), "=d"(high) : "a"(word), "g"(a) : "cc"); \
+ asm("addq %2,%0; adcq %3,%1" \
+ : "+r"(carry), "+d"(high) \
+ : "a"(low), "g"(0) \
+ : "cc"); \
+ (r) = carry, carry = high; \
+ } while (0)
+#undef sqr
+#define sqr(r0, r1, a) asm("mulq %2" : "=a"(r0), "=d"(r1) : "a"(a) : "cc");
+
+BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num,
+ BN_ULONG w) {
+ BN_ULONG c1 = 0;
+
+ if (num <= 0)
+ return (c1);
+
+ while (num & ~3) {
+ mul_add(rp[0], ap[0], w, c1);
+ mul_add(rp[1], ap[1], w, c1);
+ mul_add(rp[2], ap[2], w, c1);
+ mul_add(rp[3], ap[3], w, c1);
+ ap += 4;
+ rp += 4;
+ num -= 4;
+ }
+ if (num) {
+ mul_add(rp[0], ap[0], w, c1);
+ if (--num == 0)
+ return c1;
+ mul_add(rp[1], ap[1], w, c1);
+ if (--num == 0)
+ return c1;
+ mul_add(rp[2], ap[2], w, c1);
+ return c1;
+ }
+
+ return (c1);
+}
+
+BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w) {
+ BN_ULONG c1 = 0;
+
+ if (num <= 0)
+ return (c1);
+
+ while (num & ~3) {
+ mul(rp[0], ap[0], w, c1);
+ mul(rp[1], ap[1], w, c1);
+ mul(rp[2], ap[2], w, c1);
+ mul(rp[3], ap[3], w, c1);
+ ap += 4;
+ rp += 4;
+ num -= 4;
+ }
+ if (num) {
+ mul(rp[0], ap[0], w, c1);
+ if (--num == 0)
+ return c1;
+ mul(rp[1], ap[1], w, c1);
+ if (--num == 0)
+ return c1;
+ mul(rp[2], ap[2], w, c1);
+ }
+ return (c1);
+}
+
+void bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, int n) {
+ if (n <= 0)
+ return;
+
+ while (n & ~3) {
+ sqr(r[0], r[1], a[0]);
+ sqr(r[2], r[3], a[1]);
+ sqr(r[4], r[5], a[2]);
+ sqr(r[6], r[7], a[3]);
+ a += 4;
+ r += 8;
+ n -= 4;
+ }
+ if (n) {
+ sqr(r[0], r[1], a[0]);
+ if (--n == 0)
+ return;
+ sqr(r[2], r[3], a[1]);
+ if (--n == 0)
+ return;
+ sqr(r[4], r[5], a[2]);
+ }
+}
+
+BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d) {
+ BN_ULONG ret, waste;
+
+ asm("divq %4" : "=a"(ret), "=d"(waste) : "a"(l), "d"(h), "g"(d) : "cc");
+
+ return ret;
+}
+
+BN_ULONG bn_add_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
+ int n) {
+ BN_ULONG ret;
+ size_t i = 0;
+
+ if (n <= 0)
+ return 0;
+
+ asm volatile (
+ " subq %0,%0 \n" /* clear carry */
+ " jmp 1f \n"
+ ".p2align 4 \n"
+ "1: movq (%4,%2,8),%0 \n"
+ " adcq (%5,%2,8),%0 \n"
+ " movq %0,(%3,%2,8) \n"
+ " lea 1(%2),%2 \n"
+ " loop 1b \n"
+ " sbbq %0,%0 \n"
+ : "=&r"(ret), "+c"(n), "+r"(i)
+ : "r"(rp), "r"(ap), "r"(bp)
+ : "cc", "memory");
+
+ return ret & 1;
+}
+
+#ifndef SIMICS
+BN_ULONG bn_sub_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
+ int n) {
+ BN_ULONG ret;
+ size_t i = 0;
+
+ if (n <= 0)
+ return 0;
+
+ asm volatile (
+ " subq %0,%0 \n" /* clear borrow */
+ " jmp 1f \n"
+ ".p2align 4 \n"
+ "1: movq (%4,%2,8),%0 \n"
+ " sbbq (%5,%2,8),%0 \n"
+ " movq %0,(%3,%2,8) \n"
+ " lea 1(%2),%2 \n"
+ " loop 1b \n"
+ " sbbq %0,%0 \n"
+ : "=&r"(ret), "+c"(n), "+r"(i)
+ : "r"(rp), "r"(ap), "r"(bp)
+ : "cc", "memory");
+
+ return ret & 1;
+}
+#else
+/* Simics 1.4<7 has buggy sbbq:-( */
+#define BN_MASK2 0xffffffffffffffffL
+BN_ULONG bn_sub_words(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n) {
+ BN_ULONG t1, t2;
+ int c = 0;
+
+ if (n <= 0)
+ return ((BN_ULONG)0);
+
+ for (;;) {
+ t1 = a[0];
+ t2 = b[0];
+ r[0] = (t1 - t2 - c) & BN_MASK2;
+ if (t1 != t2)
+ c = (t1 < t2);
+ if (--n <= 0)
+ break;
+
+ t1 = a[1];
+ t2 = b[1];
+ r[1] = (t1 - t2 - c) & BN_MASK2;
+ if (t1 != t2)
+ c = (t1 < t2);
+ if (--n <= 0)
+ break;
+
+ t1 = a[2];
+ t2 = b[2];
+ r[2] = (t1 - t2 - c) & BN_MASK2;
+ if (t1 != t2)
+ c = (t1 < t2);
+ if (--n <= 0)
+ break;
+
+ t1 = a[3];
+ t2 = b[3];
+ r[3] = (t1 - t2 - c) & BN_MASK2;
+ if (t1 != t2)
+ c = (t1 < t2);
+ if (--n <= 0)
+ break;
+
+ a += 4;
+ b += 4;
+ r += 4;
+ }
+ return (c);
+}
+#endif
+
+/* mul_add_c(a,b,c0,c1,c2) -- c+=a*b for three word number c=(c2,c1,c0) */
+/* mul_add_c2(a,b,c0,c1,c2) -- c+=2*a*b for three word number c=(c2,c1,c0) */
+/* sqr_add_c(a,i,c0,c1,c2) -- c+=a[i]^2 for three word number c=(c2,c1,c0) */
+/* sqr_add_c2(a,i,c0,c1,c2) -- c+=2*a[i]*a[j] for three word number c=(c2,c1,c0)
+ */
+
+/* Keep in mind that carrying into high part of multiplication result can not
+ * overflow, because it cannot be all-ones. */
+#define mul_add_c(a, b, c0, c1, c2) \
+ do { \
+ BN_ULONG t1, t2; \
+ asm("mulq %3" : "=a"(t1), "=d"(t2) : "a"(a), "m"(b) : "cc"); \
+ asm("addq %3,%0; adcq %4,%1; adcq %5,%2" \
+ : "+r"(c0), "+r"(c1), "+r"(c2) \
+ : "r"(t1), "r"(t2), "g"(0) \
+ : "cc"); \
+ } while (0)
+
+#define sqr_add_c(a, i, c0, c1, c2) \
+ do { \
+ BN_ULONG t1, t2; \
+ asm("mulq %2" : "=a"(t1), "=d"(t2) : "a"(a[i]) : "cc"); \
+ asm("addq %3,%0; adcq %4,%1; adcq %5,%2" \
+ : "+r"(c0), "+r"(c1), "+r"(c2) \
+ : "r"(t1), "r"(t2), "g"(0) \
+ : "cc"); \
+ } while (0)
+
+#define mul_add_c2(a, b, c0, c1, c2) \
+ do { \
+ BN_ULONG t1, t2; \
+ asm("mulq %3" : "=a"(t1), "=d"(t2) : "a"(a), "m"(b) : "cc"); \
+ asm("addq %3,%0; adcq %4,%1; adcq %5,%2" \
+ : "+r"(c0), "+r"(c1), "+r"(c2) \
+ : "r"(t1), "r"(t2), "g"(0) \
+ : "cc"); \
+ asm("addq %3,%0; adcq %4,%1; adcq %5,%2" \
+ : "+r"(c0), "+r"(c1), "+r"(c2) \
+ : "r"(t1), "r"(t2), "g"(0) \
+ : "cc"); \
+ } while (0)
+
+#define sqr_add_c2(a, i, j, c0, c1, c2) mul_add_c2((a)[i], (a)[j], c0, c1, c2)
+
+void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) {
+ BN_ULONG c1, c2, c3;
+
+ c1 = 0;
+ c2 = 0;
+ c3 = 0;
+ mul_add_c(a[0], b[0], c1, c2, c3);
+ r[0] = c1;
+ c1 = 0;
+ mul_add_c(a[0], b[1], c2, c3, c1);
+ mul_add_c(a[1], b[0], c2, c3, c1);
+ r[1] = c2;
+ c2 = 0;
+ mul_add_c(a[2], b[0], c3, c1, c2);
+ mul_add_c(a[1], b[1], c3, c1, c2);
+ mul_add_c(a[0], b[2], c3, c1, c2);
+ r[2] = c3;
+ c3 = 0;
+ mul_add_c(a[0], b[3], c1, c2, c3);
+ mul_add_c(a[1], b[2], c1, c2, c3);
+ mul_add_c(a[2], b[1], c1, c2, c3);
+ mul_add_c(a[3], b[0], c1, c2, c3);
+ r[3] = c1;
+ c1 = 0;
+ mul_add_c(a[4], b[0], c2, c3, c1);
+ mul_add_c(a[3], b[1], c2, c3, c1);
+ mul_add_c(a[2], b[2], c2, c3, c1);
+ mul_add_c(a[1], b[3], c2, c3, c1);
+ mul_add_c(a[0], b[4], c2, c3, c1);
+ r[4] = c2;
+ c2 = 0;
+ mul_add_c(a[0], b[5], c3, c1, c2);
+ mul_add_c(a[1], b[4], c3, c1, c2);
+ mul_add_c(a[2], b[3], c3, c1, c2);
+ mul_add_c(a[3], b[2], c3, c1, c2);
+ mul_add_c(a[4], b[1], c3, c1, c2);
+ mul_add_c(a[5], b[0], c3, c1, c2);
+ r[5] = c3;
+ c3 = 0;
+ mul_add_c(a[6], b[0], c1, c2, c3);
+ mul_add_c(a[5], b[1], c1, c2, c3);
+ mul_add_c(a[4], b[2], c1, c2, c3);
+ mul_add_c(a[3], b[3], c1, c2, c3);
+ mul_add_c(a[2], b[4], c1, c2, c3);
+ mul_add_c(a[1], b[5], c1, c2, c3);
+ mul_add_c(a[0], b[6], c1, c2, c3);
+ r[6] = c1;
+ c1 = 0;
+ mul_add_c(a[0], b[7], c2, c3, c1);
+ mul_add_c(a[1], b[6], c2, c3, c1);
+ mul_add_c(a[2], b[5], c2, c3, c1);
+ mul_add_c(a[3], b[4], c2, c3, c1);
+ mul_add_c(a[4], b[3], c2, c3, c1);
+ mul_add_c(a[5], b[2], c2, c3, c1);
+ mul_add_c(a[6], b[1], c2, c3, c1);
+ mul_add_c(a[7], b[0], c2, c3, c1);
+ r[7] = c2;
+ c2 = 0;
+ mul_add_c(a[7], b[1], c3, c1, c2);
+ mul_add_c(a[6], b[2], c3, c1, c2);
+ mul_add_c(a[5], b[3], c3, c1, c2);
+ mul_add_c(a[4], b[4], c3, c1, c2);
+ mul_add_c(a[3], b[5], c3, c1, c2);
+ mul_add_c(a[2], b[6], c3, c1, c2);
+ mul_add_c(a[1], b[7], c3, c1, c2);
+ r[8] = c3;
+ c3 = 0;
+ mul_add_c(a[2], b[7], c1, c2, c3);
+ mul_add_c(a[3], b[6], c1, c2, c3);
+ mul_add_c(a[4], b[5], c1, c2, c3);
+ mul_add_c(a[5], b[4], c1, c2, c3);
+ mul_add_c(a[6], b[3], c1, c2, c3);
+ mul_add_c(a[7], b[2], c1, c2, c3);
+ r[9] = c1;
+ c1 = 0;
+ mul_add_c(a[7], b[3], c2, c3, c1);
+ mul_add_c(a[6], b[4], c2, c3, c1);
+ mul_add_c(a[5], b[5], c2, c3, c1);
+ mul_add_c(a[4], b[6], c2, c3, c1);
+ mul_add_c(a[3], b[7], c2, c3, c1);
+ r[10] = c2;
+ c2 = 0;
+ mul_add_c(a[4], b[7], c3, c1, c2);
+ mul_add_c(a[5], b[6], c3, c1, c2);
+ mul_add_c(a[6], b[5], c3, c1, c2);
+ mul_add_c(a[7], b[4], c3, c1, c2);
+ r[11] = c3;
+ c3 = 0;
+ mul_add_c(a[7], b[5], c1, c2, c3);
+ mul_add_c(a[6], b[6], c1, c2, c3);
+ mul_add_c(a[5], b[7], c1, c2, c3);
+ r[12] = c1;
+ c1 = 0;
+ mul_add_c(a[6], b[7], c2, c3, c1);
+ mul_add_c(a[7], b[6], c2, c3, c1);
+ r[13] = c2;
+ c2 = 0;
+ mul_add_c(a[7], b[7], c3, c1, c2);
+ r[14] = c3;
+ r[15] = c1;
+}
+
+void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) {
+ BN_ULONG c1, c2, c3;
+
+ c1 = 0;
+ c2 = 0;
+ c3 = 0;
+ mul_add_c(a[0], b[0], c1, c2, c3);
+ r[0] = c1;
+ c1 = 0;
+ mul_add_c(a[0], b[1], c2, c3, c1);
+ mul_add_c(a[1], b[0], c2, c3, c1);
+ r[1] = c2;
+ c2 = 0;
+ mul_add_c(a[2], b[0], c3, c1, c2);
+ mul_add_c(a[1], b[1], c3, c1, c2);
+ mul_add_c(a[0], b[2], c3, c1, c2);
+ r[2] = c3;
+ c3 = 0;
+ mul_add_c(a[0], b[3], c1, c2, c3);
+ mul_add_c(a[1], b[2], c1, c2, c3);
+ mul_add_c(a[2], b[1], c1, c2, c3);
+ mul_add_c(a[3], b[0], c1, c2, c3);
+ r[3] = c1;
+ c1 = 0;
+ mul_add_c(a[3], b[1], c2, c3, c1);
+ mul_add_c(a[2], b[2], c2, c3, c1);
+ mul_add_c(a[1], b[3], c2, c3, c1);
+ r[4] = c2;
+ c2 = 0;
+ mul_add_c(a[2], b[3], c3, c1, c2);
+ mul_add_c(a[3], b[2], c3, c1, c2);
+ r[5] = c3;
+ c3 = 0;
+ mul_add_c(a[3], b[3], c1, c2, c3);
+ r[6] = c1;
+ r[7] = c2;
+}
+
+void bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a) {
+ BN_ULONG c1, c2, c3;
+
+ c1 = 0;
+ c2 = 0;
+ c3 = 0;
+ sqr_add_c(a, 0, c1, c2, c3);
+ r[0] = c1;
+ c1 = 0;
+ sqr_add_c2(a, 1, 0, c2, c3, c1);
+ r[1] = c2;
+ c2 = 0;
+ sqr_add_c(a, 1, c3, c1, c2);
+ sqr_add_c2(a, 2, 0, c3, c1, c2);
+ r[2] = c3;
+ c3 = 0;
+ sqr_add_c2(a, 3, 0, c1, c2, c3);
+ sqr_add_c2(a, 2, 1, c1, c2, c3);
+ r[3] = c1;
+ c1 = 0;
+ sqr_add_c(a, 2, c2, c3, c1);
+ sqr_add_c2(a, 3, 1, c2, c3, c1);
+ sqr_add_c2(a, 4, 0, c2, c3, c1);
+ r[4] = c2;
+ c2 = 0;
+ sqr_add_c2(a, 5, 0, c3, c1, c2);
+ sqr_add_c2(a, 4, 1, c3, c1, c2);
+ sqr_add_c2(a, 3, 2, c3, c1, c2);
+ r[5] = c3;
+ c3 = 0;
+ sqr_add_c(a, 3, c1, c2, c3);
+ sqr_add_c2(a, 4, 2, c1, c2, c3);
+ sqr_add_c2(a, 5, 1, c1, c2, c3);
+ sqr_add_c2(a, 6, 0, c1, c2, c3);
+ r[6] = c1;
+ c1 = 0;
+ sqr_add_c2(a, 7, 0, c2, c3, c1);
+ sqr_add_c2(a, 6, 1, c2, c3, c1);
+ sqr_add_c2(a, 5, 2, c2, c3, c1);
+ sqr_add_c2(a, 4, 3, c2, c3, c1);
+ r[7] = c2;
+ c2 = 0;
+ sqr_add_c(a, 4, c3, c1, c2);
+ sqr_add_c2(a, 5, 3, c3, c1, c2);
+ sqr_add_c2(a, 6, 2, c3, c1, c2);
+ sqr_add_c2(a, 7, 1, c3, c1, c2);
+ r[8] = c3;
+ c3 = 0;
+ sqr_add_c2(a, 7, 2, c1, c2, c3);
+ sqr_add_c2(a, 6, 3, c1, c2, c3);
+ sqr_add_c2(a, 5, 4, c1, c2, c3);
+ r[9] = c1;
+ c1 = 0;
+ sqr_add_c(a, 5, c2, c3, c1);
+ sqr_add_c2(a, 6, 4, c2, c3, c1);
+ sqr_add_c2(a, 7, 3, c2, c3, c1);
+ r[10] = c2;
+ c2 = 0;
+ sqr_add_c2(a, 7, 4, c3, c1, c2);
+ sqr_add_c2(a, 6, 5, c3, c1, c2);
+ r[11] = c3;
+ c3 = 0;
+ sqr_add_c(a, 6, c1, c2, c3);
+ sqr_add_c2(a, 7, 5, c1, c2, c3);
+ r[12] = c1;
+ c1 = 0;
+ sqr_add_c2(a, 7, 6, c2, c3, c1);
+ r[13] = c2;
+ c2 = 0;
+ sqr_add_c(a, 7, c3, c1, c2);
+ r[14] = c3;
+ r[15] = c1;
+}
+
+void bn_sqr_comba4(BN_ULONG *r, const BN_ULONG *a) {
+ BN_ULONG c1, c2, c3;
+
+ c1 = 0;
+ c2 = 0;
+ c3 = 0;
+ sqr_add_c(a, 0, c1, c2, c3);
+ r[0] = c1;
+ c1 = 0;
+ sqr_add_c2(a, 1, 0, c2, c3, c1);
+ r[1] = c2;
+ c2 = 0;
+ sqr_add_c(a, 1, c3, c1, c2);
+ sqr_add_c2(a, 2, 0, c3, c1, c2);
+ r[2] = c3;
+ c3 = 0;
+ sqr_add_c2(a, 3, 0, c1, c2, c3);
+ sqr_add_c2(a, 2, 1, c1, c2, c3);
+ r[3] = c1;
+ c1 = 0;
+ sqr_add_c(a, 2, c2, c3, c1);
+ sqr_add_c2(a, 3, 1, c2, c3, c1);
+ r[4] = c2;
+ c2 = 0;
+ sqr_add_c2(a, 3, 2, c3, c1, c2);
+ r[5] = c3;
+ c3 = 0;
+ sqr_add_c(a, 3, c1, c2, c3);
+ r[6] = c1;
+ r[7] = c2;
+}
+
+#endif /* defined(OPENSSL_X86_64) && !defined(OPENSSL_WINDOWS) */
diff --git a/src/crypto/bn/asm/x86_64-mont.pl b/src/crypto/bn/asm/x86_64-mont.pl
new file mode 100644
index 0000000..39476ab
--- /dev/null
+++ b/src/crypto/bn/asm/x86_64-mont.pl
@@ -0,0 +1,1401 @@
+#!/usr/bin/env perl
+
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+# project. The module is, however, dual licensed under OpenSSL and
+# CRYPTOGAMS licenses depending on where you obtain it. For further
+# details see http://www.openssl.org/~appro/cryptogams/.
+# ====================================================================
+
+# October 2005.
+#
+# Montgomery multiplication routine for x86_64. While it gives modest
+# 9% improvement of rsa4096 sign on Opteron, rsa512 sign runs more
+# than twice, >2x, as fast. Most common rsa1024 sign is improved by
+# respectful 50%. It remains to be seen if loop unrolling and
+# dedicated squaring routine can provide further improvement...
+
+# July 2011.
+#
+# Add dedicated squaring procedure. Performance improvement varies
+# from platform to platform, but in average it's ~5%/15%/25%/33%
+# for 512-/1024-/2048-/4096-bit RSA *sign* benchmarks respectively.
+
+# August 2011.
+#
+# Unroll and modulo-schedule inner loops in such manner that they
+# are "fallen through" for input lengths of 8, which is critical for
+# 1024-bit RSA *sign*. Average performance improvement in comparison
+# to *initial* version of this module from 2005 is ~0%/30%/40%/45%
+# for 512-/1024-/2048-/4096-bit RSA *sign* benchmarks respectively.
+
+# June 2013.
+#
+# Optimize reduction in squaring procedure and improve 1024+-bit RSA
+# sign performance by 10-16% on Intel Sandy Bridge and later
+# (virtually same on non-Intel processors).
+
+# August 2013.
+#
+# Add MULX/ADOX/ADCX code path.
+
+$flavour = shift;
+$output = shift;
+if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+
+$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
+( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
+die "can't locate x86_64-xlate.pl";
+
+open OUT,"| \"$^X\" $xlate $flavour $output";
+*STDOUT=*OUT;
+
+if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
+ =~ /GNU assembler version ([2-9]\.[0-9]+)/) {
+ $addx = ($1>=2.23);
+}
+
+if (!$addx && $win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) &&
+ `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)/) {
+ $addx = ($1>=2.10);
+}
+
+if (!$addx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) &&
+ `ml64 2>&1` =~ /Version ([0-9]+)\./) {
+ $addx = ($1>=12);
+}
+
+# int bn_mul_mont(
+$rp="%rdi"; # BN_ULONG *rp,
+$ap="%rsi"; # const BN_ULONG *ap,
+$bp="%rdx"; # const BN_ULONG *bp,
+$np="%rcx"; # const BN_ULONG *np,
+$n0="%r8"; # const BN_ULONG *n0,
+$num="%r9"; # int num);
+$lo0="%r10";
+$hi0="%r11";
+$hi1="%r13";
+$i="%r14";
+$j="%r15";
+$m0="%rbx";
+$m1="%rbp";
+
+$code=<<___;
+.text
+
+.extern OPENSSL_ia32cap_P
+
+.globl bn_mul_mont
+.type bn_mul_mont,\@function,6
+.align 16
+bn_mul_mont:
+ test \$3,${num}d
+ jnz .Lmul_enter
+ cmp \$8,${num}d
+ jb .Lmul_enter
+___
+$code.=<<___ if ($addx);
+ mov OPENSSL_ia32cap_P+8(%rip),%r11d
+___
+$code.=<<___;
+ cmp $ap,$bp
+ jne .Lmul4x_enter
+ test \$7,${num}d
+ jz .Lsqr8x_enter
+ jmp .Lmul4x_enter
+
+.align 16
+.Lmul_enter:
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+
+ mov ${num}d,${num}d
+ lea 2($num),%r10
+ mov %rsp,%r11
+ neg %r10
+ lea (%rsp,%r10,8),%rsp # tp=alloca(8*(num+2))
+ and \$-1024,%rsp # minimize TLB usage
+
+ mov %r11,8(%rsp,$num,8) # tp[num+1]=%rsp
+.Lmul_body:
+ mov $bp,%r12 # reassign $bp
+___
+ $bp="%r12";
+$code.=<<___;
+ mov ($n0),$n0 # pull n0[0] value
+ mov ($bp),$m0 # m0=bp[0]
+ mov ($ap),%rax
+
+ xor $i,$i # i=0
+ xor $j,$j # j=0
+
+ mov $n0,$m1
+ mulq $m0 # ap[0]*bp[0]
+ mov %rax,$lo0
+ mov ($np),%rax
+
+ imulq $lo0,$m1 # "tp[0]"*n0
+ mov %rdx,$hi0
+
+ mulq $m1 # np[0]*m1
+ add %rax,$lo0 # discarded
+ mov 8($ap),%rax
+ adc \$0,%rdx
+ mov %rdx,$hi1
+
+ lea 1($j),$j # j++
+ jmp .L1st_enter
+
+.align 16
+.L1st:
+ add %rax,$hi1
+ mov ($ap,$j,8),%rax
+ adc \$0,%rdx
+ add $hi0,$hi1 # np[j]*m1+ap[j]*bp[0]
+ mov $lo0,$hi0
+ adc \$0,%rdx
+ mov $hi1,-16(%rsp,$j,8) # tp[j-1]
+ mov %rdx,$hi1
+
+.L1st_enter:
+ mulq $m0 # ap[j]*bp[0]
+ add %rax,$hi0
+ mov ($np,$j,8),%rax
+ adc \$0,%rdx
+ lea 1($j),$j # j++
+ mov %rdx,$lo0
+
+ mulq $m1 # np[j]*m1
+ cmp $num,$j
+ jne .L1st
+
+ add %rax,$hi1
+ mov ($ap),%rax # ap[0]
+ adc \$0,%rdx
+ add $hi0,$hi1 # np[j]*m1+ap[j]*bp[0]
+ adc \$0,%rdx
+ mov $hi1,-16(%rsp,$j,8) # tp[j-1]
+ mov %rdx,$hi1
+ mov $lo0,$hi0
+
+ xor %rdx,%rdx
+ add $hi0,$hi1
+ adc \$0,%rdx
+ mov $hi1,-8(%rsp,$num,8)
+ mov %rdx,(%rsp,$num,8) # store upmost overflow bit
+
+ lea 1($i),$i # i++
+ jmp .Louter
+.align 16
+.Louter:
+ mov ($bp,$i,8),$m0 # m0=bp[i]
+ xor $j,$j # j=0
+ mov $n0,$m1
+ mov (%rsp),$lo0
+ mulq $m0 # ap[0]*bp[i]
+ add %rax,$lo0 # ap[0]*bp[i]+tp[0]
+ mov ($np),%rax
+ adc \$0,%rdx
+
+ imulq $lo0,$m1 # tp[0]*n0
+ mov %rdx,$hi0
+
+ mulq $m1 # np[0]*m1
+ add %rax,$lo0 # discarded
+ mov 8($ap),%rax
+ adc \$0,%rdx
+ mov 8(%rsp),$lo0 # tp[1]
+ mov %rdx,$hi1
+
+ lea 1($j),$j # j++
+ jmp .Linner_enter
+
+.align 16
+.Linner:
+ add %rax,$hi1
+ mov ($ap,$j,8),%rax
+ adc \$0,%rdx
+ add $lo0,$hi1 # np[j]*m1+ap[j]*bp[i]+tp[j]
+ mov (%rsp,$j,8),$lo0
+ adc \$0,%rdx
+ mov $hi1,-16(%rsp,$j,8) # tp[j-1]
+ mov %rdx,$hi1
+
+.Linner_enter:
+ mulq $m0 # ap[j]*bp[i]
+ add %rax,$hi0
+ mov ($np,$j,8),%rax
+ adc \$0,%rdx
+ add $hi0,$lo0 # ap[j]*bp[i]+tp[j]
+ mov %rdx,$hi0
+ adc \$0,$hi0
+ lea 1($j),$j # j++
+
+ mulq $m1 # np[j]*m1
+ cmp $num,$j
+ jne .Linner
+
+ add %rax,$hi1
+ mov ($ap),%rax # ap[0]
+ adc \$0,%rdx
+ add $lo0,$hi1 # np[j]*m1+ap[j]*bp[i]+tp[j]
+ mov (%rsp,$j,8),$lo0
+ adc \$0,%rdx
+ mov $hi1,-16(%rsp,$j,8) # tp[j-1]
+ mov %rdx,$hi1
+
+ xor %rdx,%rdx
+ add $hi0,$hi1
+ adc \$0,%rdx
+ add $lo0,$hi1 # pull upmost overflow bit
+ adc \$0,%rdx
+ mov $hi1,-8(%rsp,$num,8)
+ mov %rdx,(%rsp,$num,8) # store upmost overflow bit
+
+ lea 1($i),$i # i++
+ cmp $num,$i
+ jb .Louter
+
+ xor $i,$i # i=0 and clear CF!
+ mov (%rsp),%rax # tp[0]
+ lea (%rsp),$ap # borrow ap for tp
+ mov $num,$j # j=num
+ jmp .Lsub
+.align 16
+.Lsub: sbb ($np,$i,8),%rax
+ mov %rax,($rp,$i,8) # rp[i]=tp[i]-np[i]
+ mov 8($ap,$i,8),%rax # tp[i+1]
+ lea 1($i),$i # i++
+ dec $j # doesn't affect CF!
+ jnz .Lsub
+
+ sbb \$0,%rax # handle upmost overflow bit
+ xor $i,$i
+ mov $num,$j # j=num
+.align 16
+.Lcopy: # copy or in-place refresh
+ mov (%rsp,$i,8),$ap
+ mov ($rp,$i,8),$np
+ xor $np,$ap # conditional select:
+ and %rax,$ap # ((ap ^ np) & %rax) ^ np
+ xor $np,$ap # ap = borrow?tp:rp
+ mov $i,(%rsp,$i,8) # zap temporary vector
+ mov $ap,($rp,$i,8) # rp[i]=tp[i]
+ lea 1($i),$i
+ sub \$1,$j
+ jnz .Lcopy
+
+ mov 8(%rsp,$num,8),%rsi # restore %rsp
+ mov \$1,%rax
+ mov (%rsi),%r15
+ mov 8(%rsi),%r14
+ mov 16(%rsi),%r13
+ mov 24(%rsi),%r12
+ mov 32(%rsi),%rbp
+ mov 40(%rsi),%rbx
+ lea 48(%rsi),%rsp
+.Lmul_epilogue:
+ ret
+.size bn_mul_mont,.-bn_mul_mont
+___
+{{{
+my @A=("%r10","%r11");
+my @N=("%r13","%rdi");
+$code.=<<___;
+.type bn_mul4x_mont,\@function,6
+.align 16
+bn_mul4x_mont:
+.Lmul4x_enter:
+___
+$code.=<<___ if ($addx);
+ and \$0x80100,%r11d
+ cmp \$0x80100,%r11d
+ je .Lmulx4x_enter
+___
+$code.=<<___;
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+
+ mov ${num}d,${num}d
+ lea 4($num),%r10
+ mov %rsp,%r11
+ neg %r10
+ lea (%rsp,%r10,8),%rsp # tp=alloca(8*(num+4))
+ and \$-1024,%rsp # minimize TLB usage
+
+ mov %r11,8(%rsp,$num,8) # tp[num+1]=%rsp
+.Lmul4x_body:
+ mov $rp,16(%rsp,$num,8) # tp[num+2]=$rp
+ mov %rdx,%r12 # reassign $bp
+___
+ $bp="%r12";
+$code.=<<___;
+ mov ($n0),$n0 # pull n0[0] value
+ mov ($bp),$m0 # m0=bp[0]
+ mov ($ap),%rax
+
+ xor $i,$i # i=0
+ xor $j,$j # j=0
+
+ mov $n0,$m1
+ mulq $m0 # ap[0]*bp[0]
+ mov %rax,$A[0]
+ mov ($np),%rax
+
+ imulq $A[0],$m1 # "tp[0]"*n0
+ mov %rdx,$A[1]
+
+ mulq $m1 # np[0]*m1
+ add %rax,$A[0] # discarded
+ mov 8($ap),%rax
+ adc \$0,%rdx
+ mov %rdx,$N[1]
+
+ mulq $m0
+ add %rax,$A[1]
+ mov 8($np),%rax
+ adc \$0,%rdx
+ mov %rdx,$A[0]
+
+ mulq $m1
+ add %rax,$N[1]
+ mov 16($ap),%rax
+ adc \$0,%rdx
+ add $A[1],$N[1]
+ lea 4($j),$j # j++
+ adc \$0,%rdx
+ mov $N[1],(%rsp)
+ mov %rdx,$N[0]
+ jmp .L1st4x
+.align 16
+.L1st4x:
+ mulq $m0 # ap[j]*bp[0]
+ add %rax,$A[0]
+ mov -16($np,$j,8),%rax
+ adc \$0,%rdx
+ mov %rdx,$A[1]
+
+ mulq $m1 # np[j]*m1
+ add %rax,$N[0]
+ mov -8($ap,$j,8),%rax
+ adc \$0,%rdx
+ add $A[0],$N[0] # np[j]*m1+ap[j]*bp[0]
+ adc \$0,%rdx
+ mov $N[0],-24(%rsp,$j,8) # tp[j-1]
+ mov %rdx,$N[1]
+
+ mulq $m0 # ap[j]*bp[0]
+ add %rax,$A[1]
+ mov -8($np,$j,8),%rax
+ adc \$0,%rdx
+ mov %rdx,$A[0]
+
+ mulq $m1 # np[j]*m1
+ add %rax,$N[1]
+ mov ($ap,$j,8),%rax
+ adc \$0,%rdx
+ add $A[1],$N[1] # np[j]*m1+ap[j]*bp[0]
+ adc \$0,%rdx
+ mov $N[1],-16(%rsp,$j,8) # tp[j-1]
+ mov %rdx,$N[0]
+
+ mulq $m0 # ap[j]*bp[0]
+ add %rax,$A[0]
+ mov ($np,$j,8),%rax
+ adc \$0,%rdx
+ mov %rdx,$A[1]
+
+ mulq $m1 # np[j]*m1
+ add %rax,$N[0]
+ mov 8($ap,$j,8),%rax
+ adc \$0,%rdx
+ add $A[0],$N[0] # np[j]*m1+ap[j]*bp[0]
+ adc \$0,%rdx
+ mov $N[0],-8(%rsp,$j,8) # tp[j-1]
+ mov %rdx,$N[1]
+
+ mulq $m0 # ap[j]*bp[0]
+ add %rax,$A[1]
+ mov 8($np,$j,8),%rax
+ adc \$0,%rdx
+ lea 4($j),$j # j++
+ mov %rdx,$A[0]
+
+ mulq $m1 # np[j]*m1
+ add %rax,$N[1]
+ mov -16($ap,$j,8),%rax
+ adc \$0,%rdx
+ add $A[1],$N[1] # np[j]*m1+ap[j]*bp[0]
+ adc \$0,%rdx
+ mov $N[1],-32(%rsp,$j,8) # tp[j-1]
+ mov %rdx,$N[0]
+ cmp $num,$j
+ jb .L1st4x
+
+ mulq $m0 # ap[j]*bp[0]
+ add %rax,$A[0]
+ mov -16($np,$j,8),%rax
+ adc \$0,%rdx
+ mov %rdx,$A[1]
+
+ mulq $m1 # np[j]*m1
+ add %rax,$N[0]
+ mov -8($ap,$j,8),%rax
+ adc \$0,%rdx
+ add $A[0],$N[0] # np[j]*m1+ap[j]*bp[0]
+ adc \$0,%rdx
+ mov $N[0],-24(%rsp,$j,8) # tp[j-1]
+ mov %rdx,$N[1]
+
+ mulq $m0 # ap[j]*bp[0]
+ add %rax,$A[1]
+ mov -8($np,$j,8),%rax
+ adc \$0,%rdx
+ mov %rdx,$A[0]
+
+ mulq $m1 # np[j]*m1
+ add %rax,$N[1]
+ mov ($ap),%rax # ap[0]
+ adc \$0,%rdx
+ add $A[1],$N[1] # np[j]*m1+ap[j]*bp[0]
+ adc \$0,%rdx
+ mov $N[1],-16(%rsp,$j,8) # tp[j-1]
+ mov %rdx,$N[0]
+
+ xor $N[1],$N[1]
+ add $A[0],$N[0]
+ adc \$0,$N[1]
+ mov $N[0],-8(%rsp,$j,8)
+ mov $N[1],(%rsp,$j,8) # store upmost overflow bit
+
+ lea 1($i),$i # i++
+.align 4
+.Louter4x:
+ mov ($bp,$i,8),$m0 # m0=bp[i]
+ xor $j,$j # j=0
+ mov (%rsp),$A[0]
+ mov $n0,$m1
+ mulq $m0 # ap[0]*bp[i]
+ add %rax,$A[0] # ap[0]*bp[i]+tp[0]
+ mov ($np),%rax
+ adc \$0,%rdx
+
+ imulq $A[0],$m1 # tp[0]*n0
+ mov %rdx,$A[1]
+
+ mulq $m1 # np[0]*m1
+ add %rax,$A[0] # "$N[0]", discarded
+ mov 8($ap),%rax
+ adc \$0,%rdx
+ mov %rdx,$N[1]
+
+ mulq $m0 # ap[j]*bp[i]
+ add %rax,$A[1]
+ mov 8($np),%rax
+ adc \$0,%rdx
+ add 8(%rsp),$A[1] # +tp[1]
+ adc \$0,%rdx
+ mov %rdx,$A[0]
+
+ mulq $m1 # np[j]*m1
+ add %rax,$N[1]
+ mov 16($ap),%rax
+ adc \$0,%rdx
+ add $A[1],$N[1] # np[j]*m1+ap[j]*bp[i]+tp[j]
+ lea 4($j),$j # j+=2
+ adc \$0,%rdx
+ mov $N[1],(%rsp) # tp[j-1]
+ mov %rdx,$N[0]
+ jmp .Linner4x
+.align 16
+.Linner4x:
+ mulq $m0 # ap[j]*bp[i]
+ add %rax,$A[0]
+ mov -16($np,$j,8),%rax
+ adc \$0,%rdx
+ add -16(%rsp,$j,8),$A[0] # ap[j]*bp[i]+tp[j]
+ adc \$0,%rdx
+ mov %rdx,$A[1]
+
+ mulq $m1 # np[j]*m1
+ add %rax,$N[0]
+ mov -8($ap,$j,8),%rax
+ adc \$0,%rdx
+ add $A[0],$N[0]
+ adc \$0,%rdx
+ mov $N[0],-24(%rsp,$j,8) # tp[j-1]
+ mov %rdx,$N[1]
+
+ mulq $m0 # ap[j]*bp[i]
+ add %rax,$A[1]
+ mov -8($np,$j,8),%rax
+ adc \$0,%rdx
+ add -8(%rsp,$j,8),$A[1]
+ adc \$0,%rdx
+ mov %rdx,$A[0]
+
+ mulq $m1 # np[j]*m1
+ add %rax,$N[1]
+ mov ($ap,$j,8),%rax
+ adc \$0,%rdx
+ add $A[1],$N[1]
+ adc \$0,%rdx
+ mov $N[1],-16(%rsp,$j,8) # tp[j-1]
+ mov %rdx,$N[0]
+
+ mulq $m0 # ap[j]*bp[i]
+ add %rax,$A[0]
+ mov ($np,$j,8),%rax
+ adc \$0,%rdx
+ add (%rsp,$j,8),$A[0] # ap[j]*bp[i]+tp[j]
+ adc \$0,%rdx
+ mov %rdx,$A[1]
+
+ mulq $m1 # np[j]*m1
+ add %rax,$N[0]
+ mov 8($ap,$j,8),%rax
+ adc \$0,%rdx
+ add $A[0],$N[0]
+ adc \$0,%rdx
+ mov $N[0],-8(%rsp,$j,8) # tp[j-1]
+ mov %rdx,$N[1]
+
+ mulq $m0 # ap[j]*bp[i]
+ add %rax,$A[1]
+ mov 8($np,$j,8),%rax
+ adc \$0,%rdx
+ add 8(%rsp,$j,8),$A[1]
+ adc \$0,%rdx
+ lea 4($j),$j # j++
+ mov %rdx,$A[0]
+
+ mulq $m1 # np[j]*m1
+ add %rax,$N[1]
+ mov -16($ap,$j,8),%rax
+ adc \$0,%rdx
+ add $A[1],$N[1]
+ adc \$0,%rdx
+ mov $N[1],-32(%rsp,$j,8) # tp[j-1]
+ mov %rdx,$N[0]
+ cmp $num,$j
+ jb .Linner4x
+
+ mulq $m0 # ap[j]*bp[i]
+ add %rax,$A[0]
+ mov -16($np,$j,8),%rax
+ adc \$0,%rdx
+ add -16(%rsp,$j,8),$A[0] # ap[j]*bp[i]+tp[j]
+ adc \$0,%rdx
+ mov %rdx,$A[1]
+
+ mulq $m1 # np[j]*m1
+ add %rax,$N[0]
+ mov -8($ap,$j,8),%rax
+ adc \$0,%rdx
+ add $A[0],$N[0]
+ adc \$0,%rdx
+ mov $N[0],-24(%rsp,$j,8) # tp[j-1]
+ mov %rdx,$N[1]
+
+ mulq $m0 # ap[j]*bp[i]
+ add %rax,$A[1]
+ mov -8($np,$j,8),%rax
+ adc \$0,%rdx
+ add -8(%rsp,$j,8),$A[1]
+ adc \$0,%rdx
+ lea 1($i),$i # i++
+ mov %rdx,$A[0]
+
+ mulq $m1 # np[j]*m1
+ add %rax,$N[1]
+ mov ($ap),%rax # ap[0]
+ adc \$0,%rdx
+ add $A[1],$N[1]
+ adc \$0,%rdx
+ mov $N[1],-16(%rsp,$j,8) # tp[j-1]
+ mov %rdx,$N[0]
+
+ xor $N[1],$N[1]
+ add $A[0],$N[0]
+ adc \$0,$N[1]
+ add (%rsp,$num,8),$N[0] # pull upmost overflow bit
+ adc \$0,$N[1]
+ mov $N[0],-8(%rsp,$j,8)
+ mov $N[1],(%rsp,$j,8) # store upmost overflow bit
+
+ cmp $num,$i
+ jb .Louter4x
+___
+{
+my @ri=("%rax","%rdx",$m0,$m1);
+$code.=<<___;
+ mov 16(%rsp,$num,8),$rp # restore $rp
+ mov 0(%rsp),@ri[0] # tp[0]
+ mov 8(%rsp),@ri[1] # tp[1]
+ shr \$2,$num # num/=4
+ lea (%rsp),$ap # borrow ap for tp
+ xor $i,$i # i=0 and clear CF!
+
+ sub 0($np),@ri[0]
+ mov 16($ap),@ri[2] # tp[2]
+ mov 24($ap),@ri[3] # tp[3]
+ sbb 8($np),@ri[1]
+ lea -1($num),$j # j=num/4-1
+ jmp .Lsub4x
+.align 16
+.Lsub4x:
+ mov @ri[0],0($rp,$i,8) # rp[i]=tp[i]-np[i]
+ mov @ri[1],8($rp,$i,8) # rp[i]=tp[i]-np[i]
+ sbb 16($np,$i,8),@ri[2]
+ mov 32($ap,$i,8),@ri[0] # tp[i+1]
+ mov 40($ap,$i,8),@ri[1]
+ sbb 24($np,$i,8),@ri[3]
+ mov @ri[2],16($rp,$i,8) # rp[i]=tp[i]-np[i]
+ mov @ri[3],24($rp,$i,8) # rp[i]=tp[i]-np[i]
+ sbb 32($np,$i,8),@ri[0]
+ mov 48($ap,$i,8),@ri[2]
+ mov 56($ap,$i,8),@ri[3]
+ sbb 40($np,$i,8),@ri[1]
+ lea 4($i),$i # i++
+ dec $j # doesnn't affect CF!
+ jnz .Lsub4x
+
+ mov @ri[0],0($rp,$i,8) # rp[i]=tp[i]-np[i]
+ mov 32($ap,$i,8),@ri[0] # load overflow bit
+ sbb 16($np,$i,8),@ri[2]
+ mov @ri[1],8($rp,$i,8) # rp[i]=tp[i]-np[i]
+ sbb 24($np,$i,8),@ri[3]
+ mov @ri[2],16($rp,$i,8) # rp[i]=tp[i]-np[i]
+
+ sbb \$0,@ri[0] # handle upmost overflow bit
+ mov @ri[0],%xmm0
+ punpcklqdq %xmm0,%xmm0 # extend mask to 128 bits
+ mov @ri[3],24($rp,$i,8) # rp[i]=tp[i]-np[i]
+ xor $i,$i # i=0
+
+ mov $num,$j
+ pxor %xmm5,%xmm5
+ jmp .Lcopy4x
+.align 16
+.Lcopy4x: # copy or in-place refresh
+ movdqu (%rsp,$i),%xmm2
+ movdqu 16(%rsp,$i),%xmm4
+ movdqu ($rp,$i),%xmm1
+ movdqu 16($rp,$i),%xmm3
+ pxor %xmm1,%xmm2 # conditional select
+ pxor %xmm3,%xmm4
+ pand %xmm0,%xmm2
+ pand %xmm0,%xmm4
+ pxor %xmm1,%xmm2
+ pxor %xmm3,%xmm4
+ movdqu %xmm2,($rp,$i)
+ movdqu %xmm4,16($rp,$i)
+ movdqa %xmm5,(%rsp,$i) # zap temporary vectors
+ movdqa %xmm5,16(%rsp,$i)
+
+ lea 32($i),$i
+ dec $j
+ jnz .Lcopy4x
+
+ shl \$2,$num
+___
+}
+$code.=<<___;
+ mov 8(%rsp,$num,8),%rsi # restore %rsp
+ mov \$1,%rax
+ mov (%rsi),%r15
+ mov 8(%rsi),%r14
+ mov 16(%rsi),%r13
+ mov 24(%rsi),%r12
+ mov 32(%rsi),%rbp
+ mov 40(%rsi),%rbx
+ lea 48(%rsi),%rsp
+.Lmul4x_epilogue:
+ ret
+.size bn_mul4x_mont,.-bn_mul4x_mont
+___
+}}}
+ {{{
+######################################################################
+# void bn_sqr8x_mont(
+my $rptr="%rdi"; # const BN_ULONG *rptr,
+my $aptr="%rsi"; # const BN_ULONG *aptr,
+my $bptr="%rdx"; # not used
+my $nptr="%rcx"; # const BN_ULONG *nptr,
+my $n0 ="%r8"; # const BN_ULONG *n0);
+my $num ="%r9"; # int num, has to be divisible by 8
+
+my ($i,$j,$tptr)=("%rbp","%rcx",$rptr);
+my @A0=("%r10","%r11");
+my @A1=("%r12","%r13");
+my ($a0,$a1,$ai)=("%r14","%r15","%rbx");
+
+$code.=<<___ if ($addx);
+.extern bn_sqrx8x_internal # see x86_64-mont5 module
+___
+$code.=<<___;
+.extern bn_sqr8x_internal # see x86_64-mont5 module
+
+.type bn_sqr8x_mont,\@function,6
+.align 32
+bn_sqr8x_mont:
+.Lsqr8x_enter:
+ mov %rsp,%rax
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+
+ mov ${num}d,%r10d
+ shl \$3,${num}d # convert $num to bytes
+ shl \$3+2,%r10 # 4*$num
+ neg $num
+
+ ##############################################################
+ # ensure that stack frame doesn't alias with $aptr modulo
+ # 4096. this is done to allow memory disambiguation logic
+ # do its job.
+ #
+ lea -64(%rsp,$num,4),%r11
+ mov ($n0),$n0 # *n0
+ sub $aptr,%r11
+ and \$4095,%r11
+ cmp %r11,%r10
+ jb .Lsqr8x_sp_alt
+ sub %r11,%rsp # align with $aptr
+ lea -64(%rsp,$num,4),%rsp # alloca(frame+4*$num)
+ jmp .Lsqr8x_sp_done
+
+.align 32
+.Lsqr8x_sp_alt:
+ lea 4096-64(,$num,4),%r10 # 4096-frame-4*$num
+ lea -64(%rsp,$num,4),%rsp # alloca(frame+4*$num)
+ sub %r10,%r11
+ mov \$0,%r10
+ cmovc %r10,%r11
+ sub %r11,%rsp
+.Lsqr8x_sp_done:
+ and \$-64,%rsp
+ mov $num,%r10
+ neg $num
+
+ lea 64(%rsp,$num,2),%r11 # copy of modulus
+ mov $n0, 32(%rsp)
+ mov %rax, 40(%rsp) # save original %rsp
+.Lsqr8x_body:
+
+ mov $num,$i
+ movq %r11, %xmm2 # save pointer to modulus copy
+ shr \$3+2,$i
+ mov OPENSSL_ia32cap_P+8(%rip),%eax
+ jmp .Lsqr8x_copy_n
+
+.align 32
+.Lsqr8x_copy_n:
+ movq 8*0($nptr),%xmm0
+ movq 8*1($nptr),%xmm1
+ movq 8*2($nptr),%xmm3
+ movq 8*3($nptr),%xmm4
+ lea 8*4($nptr),$nptr
+ movdqa %xmm0,16*0(%r11)
+ movdqa %xmm1,16*1(%r11)
+ movdqa %xmm3,16*2(%r11)
+ movdqa %xmm4,16*3(%r11)
+ lea 16*4(%r11),%r11
+ dec $i
+ jnz .Lsqr8x_copy_n
+
+ pxor %xmm0,%xmm0
+ movq $rptr,%xmm1 # save $rptr
+ movq %r10, %xmm3 # -$num
+___
+$code.=<<___ if ($addx);
+ and \$0x80100,%eax
+ cmp \$0x80100,%eax
+ jne .Lsqr8x_nox
+
+ call bn_sqrx8x_internal # see x86_64-mont5 module
+
+ pxor %xmm0,%xmm0
+ lea 48(%rsp),%rax
+ lea 64(%rsp,$num,2),%rdx
+ shr \$3+2,$num
+ mov 40(%rsp),%rsi # restore %rsp
+ jmp .Lsqr8x_zero
+
+.align 32
+.Lsqr8x_nox:
+___
+$code.=<<___;
+ call bn_sqr8x_internal # see x86_64-mont5 module
+
+ pxor %xmm0,%xmm0
+ lea 48(%rsp),%rax
+ lea 64(%rsp,$num,2),%rdx
+ shr \$3+2,$num
+ mov 40(%rsp),%rsi # restore %rsp
+ jmp .Lsqr8x_zero
+
+.align 32
+.Lsqr8x_zero:
+ movdqa %xmm0,16*0(%rax) # wipe t
+ movdqa %xmm0,16*1(%rax)
+ movdqa %xmm0,16*2(%rax)
+ movdqa %xmm0,16*3(%rax)
+ lea 16*4(%rax),%rax
+ movdqa %xmm0,16*0(%rdx) # wipe n
+ movdqa %xmm0,16*1(%rdx)
+ movdqa %xmm0,16*2(%rdx)
+ movdqa %xmm0,16*3(%rdx)
+ lea 16*4(%rdx),%rdx
+ dec $num
+ jnz .Lsqr8x_zero
+
+ mov \$1,%rax
+ mov -48(%rsi),%r15
+ mov -40(%rsi),%r14
+ mov -32(%rsi),%r13
+ mov -24(%rsi),%r12
+ mov -16(%rsi),%rbp
+ mov -8(%rsi),%rbx
+ lea (%rsi),%rsp
+.Lsqr8x_epilogue:
+ ret
+.size bn_sqr8x_mont,.-bn_sqr8x_mont
+___
+}}}
+
+if ($addx) {{{
+my $bp="%rdx"; # original value
+
+$code.=<<___;
+.type bn_mulx4x_mont,\@function,6
+.align 32
+bn_mulx4x_mont:
+.Lmulx4x_enter:
+ mov %rsp,%rax
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+
+ shl \$3,${num}d # convert $num to bytes
+ .byte 0x67
+ xor %r10,%r10
+ sub $num,%r10 # -$num
+ mov ($n0),$n0 # *n0
+ lea -72(%rsp,%r10),%rsp # alloca(frame+$num+8)
+ lea ($bp,$num),%r10
+ and \$-128,%rsp
+ ##############################################################
+ # Stack layout
+ # +0 num
+ # +8 off-loaded &b[i]
+ # +16 end of b[num]
+ # +24 saved n0
+ # +32 saved rp
+ # +40 saved %rsp
+ # +48 inner counter
+ # +56
+ # +64 tmp[num+1]
+ #
+ mov $num,0(%rsp) # save $num
+ shr \$5,$num
+ mov %r10,16(%rsp) # end of b[num]
+ sub \$1,$num
+ mov $n0, 24(%rsp) # save *n0
+ mov $rp, 32(%rsp) # save $rp
+ mov %rax,40(%rsp) # save original %rsp
+ mov $num,48(%rsp) # inner counter
+ jmp .Lmulx4x_body
+
+.align 32
+.Lmulx4x_body:
+___
+my ($aptr, $bptr, $nptr, $tptr, $mi, $bi, $zero, $num)=
+ ("%rsi","%rdi","%rcx","%rbx","%r8","%r9","%rbp","%rax");
+my $rptr=$bptr;
+$code.=<<___;
+ lea 8($bp),$bptr
+ mov ($bp),%rdx # b[0], $bp==%rdx actually
+ lea 64+32(%rsp),$tptr
+ mov %rdx,$bi
+
+ mulx 0*8($aptr),$mi,%rax # a[0]*b[0]
+ mulx 1*8($aptr),%r11,%r14 # a[1]*b[0]
+ add %rax,%r11
+ mov $bptr,8(%rsp) # off-load &b[i]
+ mulx 2*8($aptr),%r12,%r13 # ...
+ adc %r14,%r12
+ adc \$0,%r13
+
+ mov $mi,$bptr # borrow $bptr
+ imulq 24(%rsp),$mi # "t[0]"*n0
+ xor $zero,$zero # cf=0, of=0
+
+ mulx 3*8($aptr),%rax,%r14
+ mov $mi,%rdx
+ lea 4*8($aptr),$aptr
+ adcx %rax,%r13
+ adcx $zero,%r14 # cf=0
+
+ mulx 0*8($nptr),%rax,%r10
+ adcx %rax,$bptr # discarded
+ adox %r11,%r10
+ mulx 1*8($nptr),%rax,%r11
+ adcx %rax,%r10
+ adox %r12,%r11
+ .byte 0xc4,0x62,0xfb,0xf6,0xa1,0x10,0x00,0x00,0x00 # mulx 2*8($nptr),%rax,%r12
+ mov 48(%rsp),$bptr # counter value
+ mov %r10,-4*8($tptr)
+ adcx %rax,%r11
+ adox %r13,%r12
+ mulx 3*8($nptr),%rax,%r15
+ mov $bi,%rdx
+ mov %r11,-3*8($tptr)
+ adcx %rax,%r12
+ adox $zero,%r15 # of=0
+ lea 4*8($nptr),$nptr
+ mov %r12,-2*8($tptr)
+
+ jmp .Lmulx4x_1st
+
+.align 32
+.Lmulx4x_1st:
+ adcx $zero,%r15 # cf=0, modulo-scheduled
+ mulx 0*8($aptr),%r10,%rax # a[4]*b[0]
+ adcx %r14,%r10
+ mulx 1*8($aptr),%r11,%r14 # a[5]*b[0]
+ adcx %rax,%r11
+ mulx 2*8($aptr),%r12,%rax # ...
+ adcx %r14,%r12
+ mulx 3*8($aptr),%r13,%r14
+ .byte 0x67,0x67
+ mov $mi,%rdx
+ adcx %rax,%r13
+ adcx $zero,%r14 # cf=0
+ lea 4*8($aptr),$aptr
+ lea 4*8($tptr),$tptr
+
+ adox %r15,%r10
+ mulx 0*8($nptr),%rax,%r15
+ adcx %rax,%r10
+ adox %r15,%r11
+ mulx 1*8($nptr),%rax,%r15
+ adcx %rax,%r11
+ adox %r15,%r12
+ mulx 2*8($nptr),%rax,%r15
+ mov %r10,-5*8($tptr)
+ adcx %rax,%r12
+ mov %r11,-4*8($tptr)
+ adox %r15,%r13
+ mulx 3*8($nptr),%rax,%r15
+ mov $bi,%rdx
+ mov %r12,-3*8($tptr)
+ adcx %rax,%r13
+ adox $zero,%r15
+ lea 4*8($nptr),$nptr
+ mov %r13,-2*8($tptr)
+
+ dec $bptr # of=0, pass cf
+ jnz .Lmulx4x_1st
+
+ mov 0(%rsp),$num # load num
+ mov 8(%rsp),$bptr # re-load &b[i]
+ adc $zero,%r15 # modulo-scheduled
+ add %r15,%r14
+ sbb %r15,%r15 # top-most carry
+ mov %r14,-1*8($tptr)
+ jmp .Lmulx4x_outer
+
+.align 32
+.Lmulx4x_outer:
+ mov ($bptr),%rdx # b[i]
+ lea 8($bptr),$bptr # b++
+ sub $num,$aptr # rewind $aptr
+ mov %r15,($tptr) # save top-most carry
+ lea 64+4*8(%rsp),$tptr
+ sub $num,$nptr # rewind $nptr
+
+ mulx 0*8($aptr),$mi,%r11 # a[0]*b[i]
+ xor %ebp,%ebp # xor $zero,$zero # cf=0, of=0
+ mov %rdx,$bi
+ mulx 1*8($aptr),%r14,%r12 # a[1]*b[i]
+ adox -4*8($tptr),$mi
+ adcx %r14,%r11
+ mulx 2*8($aptr),%r15,%r13 # ...
+ adox -3*8($tptr),%r11
+ adcx %r15,%r12
+ adox $zero,%r12
+ adcx $zero,%r13
+
+ mov $bptr,8(%rsp) # off-load &b[i]
+ .byte 0x67
+ mov $mi,%r15
+ imulq 24(%rsp),$mi # "t[0]"*n0
+ xor %ebp,%ebp # xor $zero,$zero # cf=0, of=0
+
+ mulx 3*8($aptr),%rax,%r14
+ mov $mi,%rdx
+ adox -2*8($tptr),%r12
+ adcx %rax,%r13
+ adox -1*8($tptr),%r13
+ adcx $zero,%r14
+ lea 4*8($aptr),$aptr
+ adox $zero,%r14
+
+ mulx 0*8($nptr),%rax,%r10
+ adcx %rax,%r15 # discarded
+ adox %r11,%r10
+ mulx 1*8($nptr),%rax,%r11
+ adcx %rax,%r10
+ adox %r12,%r11
+ mulx 2*8($nptr),%rax,%r12
+ mov %r10,-4*8($tptr)
+ adcx %rax,%r11
+ adox %r13,%r12
+ mulx 3*8($nptr),%rax,%r15
+ mov $bi,%rdx
+ mov %r11,-3*8($tptr)
+ lea 4*8($nptr),$nptr
+ adcx %rax,%r12
+ adox $zero,%r15 # of=0
+ mov 48(%rsp),$bptr # counter value
+ mov %r12,-2*8($tptr)
+
+ jmp .Lmulx4x_inner
+
+.align 32
+.Lmulx4x_inner:
+ mulx 0*8($aptr),%r10,%rax # a[4]*b[i]
+ adcx $zero,%r15 # cf=0, modulo-scheduled
+ adox %r14,%r10
+ mulx 1*8($aptr),%r11,%r14 # a[5]*b[i]
+ adcx 0*8($tptr),%r10
+ adox %rax,%r11
+ mulx 2*8($aptr),%r12,%rax # ...
+ adcx 1*8($tptr),%r11
+ adox %r14,%r12
+ mulx 3*8($aptr),%r13,%r14
+ mov $mi,%rdx
+ adcx 2*8($tptr),%r12
+ adox %rax,%r13
+ adcx 3*8($tptr),%r13
+ adox $zero,%r14 # of=0
+ lea 4*8($aptr),$aptr
+ lea 4*8($tptr),$tptr
+ adcx $zero,%r14 # cf=0
+
+ adox %r15,%r10
+ mulx 0*8($nptr),%rax,%r15
+ adcx %rax,%r10
+ adox %r15,%r11
+ mulx 1*8($nptr),%rax,%r15
+ adcx %rax,%r11
+ adox %r15,%r12
+ mulx 2*8($nptr),%rax,%r15
+ mov %r10,-5*8($tptr)
+ adcx %rax,%r12
+ adox %r15,%r13
+ mulx 3*8($nptr),%rax,%r15
+ mov $bi,%rdx
+ mov %r11,-4*8($tptr)
+ mov %r12,-3*8($tptr)
+ adcx %rax,%r13
+ adox $zero,%r15
+ lea 4*8($nptr),$nptr
+ mov %r13,-2*8($tptr)
+
+ dec $bptr # of=0, pass cf
+ jnz .Lmulx4x_inner
+
+ mov 0(%rsp),$num # load num
+ mov 8(%rsp),$bptr # re-load &b[i]
+ adc $zero,%r15 # modulo-scheduled
+ sub 0*8($tptr),$zero # pull top-most carry
+ adc %r15,%r14
+ mov -8($nptr),$mi
+ sbb %r15,%r15 # top-most carry
+ mov %r14,-1*8($tptr)
+
+ cmp 16(%rsp),$bptr
+ jne .Lmulx4x_outer
+
+ sub %r14,$mi # compare top-most words
+ sbb $mi,$mi
+ or $mi,%r15
+
+ neg $num
+ xor %rdx,%rdx
+ mov 32(%rsp),$rptr # restore rp
+ lea 64(%rsp),$tptr
+
+ pxor %xmm0,%xmm0
+ mov 0*8($nptr,$num),%r8
+ mov 1*8($nptr,$num),%r9
+ neg %r8
+ jmp .Lmulx4x_sub_entry
+
+.align 32
+.Lmulx4x_sub:
+ mov 0*8($nptr,$num),%r8
+ mov 1*8($nptr,$num),%r9
+ not %r8
+.Lmulx4x_sub_entry:
+ mov 2*8($nptr,$num),%r10
+ not %r9
+ and %r15,%r8
+ mov 3*8($nptr,$num),%r11
+ not %r10
+ and %r15,%r9
+ not %r11
+ and %r15,%r10
+ and %r15,%r11
+
+ neg %rdx # mov %rdx,%cf
+ adc 0*8($tptr),%r8
+ adc 1*8($tptr),%r9
+ movdqa %xmm0,($tptr)
+ adc 2*8($tptr),%r10
+ adc 3*8($tptr),%r11
+ movdqa %xmm0,16($tptr)
+ lea 4*8($tptr),$tptr
+ sbb %rdx,%rdx # mov %cf,%rdx
+
+ mov %r8,0*8($rptr)
+ mov %r9,1*8($rptr)
+ mov %r10,2*8($rptr)
+ mov %r11,3*8($rptr)
+ lea 4*8($rptr),$rptr
+
+ add \$32,$num
+ jnz .Lmulx4x_sub
+
+ mov 40(%rsp),%rsi # restore %rsp
+ mov \$1,%rax
+ mov -48(%rsi),%r15
+ mov -40(%rsi),%r14
+ mov -32(%rsi),%r13
+ mov -24(%rsi),%r12
+ mov -16(%rsi),%rbp
+ mov -8(%rsi),%rbx
+ lea (%rsi),%rsp
+.Lmulx4x_epilogue:
+ ret
+.size bn_mulx4x_mont,.-bn_mulx4x_mont
+___
+}}}
+$code.=<<___;
+.asciz "Montgomery Multiplication for x86_64, CRYPTOGAMS by <appro\@openssl.org>"
+.align 16
+___
+
+# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame,
+# CONTEXT *context,DISPATCHER_CONTEXT *disp)
+if ($win64) {
+$rec="%rcx";
+$frame="%rdx";
+$context="%r8";
+$disp="%r9";
+
+$code.=<<___;
+.extern __imp_RtlVirtualUnwind
+.type mul_handler,\@abi-omnipotent
+.align 16
+mul_handler:
+ push %rsi
+ push %rdi
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+ pushfq
+ sub \$64,%rsp
+
+ mov 120($context),%rax # pull context->Rax
+ mov 248($context),%rbx # pull context->Rip
+
+ mov 8($disp),%rsi # disp->ImageBase
+ mov 56($disp),%r11 # disp->HandlerData
+
+ mov 0(%r11),%r10d # HandlerData[0]
+ lea (%rsi,%r10),%r10 # end of prologue label
+ cmp %r10,%rbx # context->Rip<end of prologue label
+ jb .Lcommon_seh_tail
+
+ mov 152($context),%rax # pull context->Rsp
+
+ mov 4(%r11),%r10d # HandlerData[1]
+ lea (%rsi,%r10),%r10 # epilogue label
+ cmp %r10,%rbx # context->Rip>=epilogue label
+ jae .Lcommon_seh_tail
+
+ mov 192($context),%r10 # pull $num
+ mov 8(%rax,%r10,8),%rax # pull saved stack pointer
+ lea 48(%rax),%rax
+
+ mov -8(%rax),%rbx
+ mov -16(%rax),%rbp
+ mov -24(%rax),%r12
+ mov -32(%rax),%r13
+ mov -40(%rax),%r14
+ mov -48(%rax),%r15
+ mov %rbx,144($context) # restore context->Rbx
+ mov %rbp,160($context) # restore context->Rbp
+ mov %r12,216($context) # restore context->R12
+ mov %r13,224($context) # restore context->R13
+ mov %r14,232($context) # restore context->R14
+ mov %r15,240($context) # restore context->R15
+
+ jmp .Lcommon_seh_tail
+.size mul_handler,.-mul_handler
+
+.type sqr_handler,\@abi-omnipotent
+.align 16
+sqr_handler:
+ push %rsi
+ push %rdi
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+ pushfq
+ sub \$64,%rsp
+
+ mov 120($context),%rax # pull context->Rax
+ mov 248($context),%rbx # pull context->Rip
+
+ mov 8($disp),%rsi # disp->ImageBase
+ mov 56($disp),%r11 # disp->HandlerData
+
+ mov 0(%r11),%r10d # HandlerData[0]
+ lea (%rsi,%r10),%r10 # end of prologue label
+ cmp %r10,%rbx # context->Rip<.Lsqr_body
+ jb .Lcommon_seh_tail
+
+ mov 152($context),%rax # pull context->Rsp
+
+ mov 4(%r11),%r10d # HandlerData[1]
+ lea (%rsi,%r10),%r10 # epilogue label
+ cmp %r10,%rbx # context->Rip>=.Lsqr_epilogue
+ jae .Lcommon_seh_tail
+
+ mov 40(%rax),%rax # pull saved stack pointer
+
+ mov -8(%rax),%rbx
+ mov -16(%rax),%rbp
+ mov -24(%rax),%r12
+ mov -32(%rax),%r13
+ mov -40(%rax),%r14
+ mov -48(%rax),%r15
+ mov %rbx,144($context) # restore context->Rbx
+ mov %rbp,160($context) # restore context->Rbp
+ mov %r12,216($context) # restore context->R12
+ mov %r13,224($context) # restore context->R13
+ mov %r14,232($context) # restore context->R14
+ mov %r15,240($context) # restore context->R15
+
+.Lcommon_seh_tail:
+ mov 8(%rax),%rdi
+ mov 16(%rax),%rsi
+ mov %rax,152($context) # restore context->Rsp
+ mov %rsi,168($context) # restore context->Rsi
+ mov %rdi,176($context) # restore context->Rdi
+
+ mov 40($disp),%rdi # disp->ContextRecord
+ mov $context,%rsi # context
+ mov \$154,%ecx # sizeof(CONTEXT)
+ .long 0xa548f3fc # cld; rep movsq
+
+ mov $disp,%rsi
+ xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER
+ mov 8(%rsi),%rdx # arg2, disp->ImageBase
+ mov 0(%rsi),%r8 # arg3, disp->ControlPc
+ mov 16(%rsi),%r9 # arg4, disp->FunctionEntry
+ mov 40(%rsi),%r10 # disp->ContextRecord
+ lea 56(%rsi),%r11 # &disp->HandlerData
+ lea 24(%rsi),%r12 # &disp->EstablisherFrame
+ mov %r10,32(%rsp) # arg5
+ mov %r11,40(%rsp) # arg6
+ mov %r12,48(%rsp) # arg7
+ mov %rcx,56(%rsp) # arg8, (NULL)
+ call *__imp_RtlVirtualUnwind(%rip)
+
+ mov \$1,%eax # ExceptionContinueSearch
+ add \$64,%rsp
+ popfq
+ pop %r15
+ pop %r14
+ pop %r13
+ pop %r12
+ pop %rbp
+ pop %rbx
+ pop %rdi
+ pop %rsi
+ ret
+.size sqr_handler,.-sqr_handler
+
+.section .pdata
+.align 4
+ .rva .LSEH_begin_bn_mul_mont
+ .rva .LSEH_end_bn_mul_mont
+ .rva .LSEH_info_bn_mul_mont
+
+ .rva .LSEH_begin_bn_mul4x_mont
+ .rva .LSEH_end_bn_mul4x_mont
+ .rva .LSEH_info_bn_mul4x_mont
+
+ .rva .LSEH_begin_bn_sqr8x_mont
+ .rva .LSEH_end_bn_sqr8x_mont
+ .rva .LSEH_info_bn_sqr8x_mont
+___
+$code.=<<___ if ($addx);
+ .rva .LSEH_begin_bn_mulx4x_mont
+ .rva .LSEH_end_bn_mulx4x_mont
+ .rva .LSEH_info_bn_mulx4x_mont
+___
+$code.=<<___;
+.section .xdata
+.align 8
+.LSEH_info_bn_mul_mont:
+ .byte 9,0,0,0
+ .rva mul_handler
+ .rva .Lmul_body,.Lmul_epilogue # HandlerData[]
+.LSEH_info_bn_mul4x_mont:
+ .byte 9,0,0,0
+ .rva mul_handler
+ .rva .Lmul4x_body,.Lmul4x_epilogue # HandlerData[]
+.LSEH_info_bn_sqr8x_mont:
+ .byte 9,0,0,0
+ .rva sqr_handler
+ .rva .Lsqr8x_body,.Lsqr8x_epilogue # HandlerData[]
+___
+$code.=<<___ if ($addx);
+.LSEH_info_bn_mulx4x_mont:
+ .byte 9,0,0,0
+ .rva sqr_handler
+ .rva .Lmulx4x_body,.Lmulx4x_epilogue # HandlerData[]
+___
+}
+
+print $code;
+close STDOUT;
diff --git a/src/crypto/bn/asm/x86_64-mont5.pl b/src/crypto/bn/asm/x86_64-mont5.pl
new file mode 100644
index 0000000..80e9126
--- /dev/null
+++ b/src/crypto/bn/asm/x86_64-mont5.pl
@@ -0,0 +1,3499 @@
+#!/usr/bin/env perl
+
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+# project. The module is, however, dual licensed under OpenSSL and
+# CRYPTOGAMS licenses depending on where you obtain it. For further
+# details see http://www.openssl.org/~appro/cryptogams/.
+# ====================================================================
+
+# August 2011.
+#
+# Companion to x86_64-mont.pl that optimizes cache-timing attack
+# countermeasures. The subroutines are produced by replacing bp[i]
+# references in their x86_64-mont.pl counterparts with cache-neutral
+# references to powers table computed in BN_mod_exp_mont_consttime.
+# In addition subroutine that scatters elements of the powers table
+# is implemented, so that scatter-/gathering can be tuned without
+# bn_exp.c modifications.
+
+# August 2013.
+#
+# Add MULX/AD*X code paths and additional interfaces to optimize for
+# branch prediction unit. For input lengths that are multiples of 8
+# the np argument is not just modulus value, but one interleaved
+# with 0. This is to optimize post-condition...
+
+$flavour = shift;
+$output = shift;
+if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+
+$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
+( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
+die "can't locate x86_64-xlate.pl";
+
+open OUT,"| \"$^X\" $xlate $flavour $output";
+*STDOUT=*OUT;
+
+if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
+ =~ /GNU assembler version ([2-9]\.[0-9]+)/) {
+ $addx = ($1>=2.23);
+}
+
+if (!$addx && $win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) &&
+ `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)/) {
+ $addx = ($1>=2.10);
+}
+
+if (!$addx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) &&
+ `ml64 2>&1` =~ /Version ([0-9]+)\./) {
+ $addx = ($1>=12);
+}
+
+# int bn_mul_mont_gather5(
+$rp="%rdi"; # BN_ULONG *rp,
+$ap="%rsi"; # const BN_ULONG *ap,
+$bp="%rdx"; # const BN_ULONG *bp,
+$np="%rcx"; # const BN_ULONG *np,
+$n0="%r8"; # const BN_ULONG *n0,
+$num="%r9"; # int num,
+ # int idx); # 0 to 2^5-1, "index" in $bp holding
+ # pre-computed powers of a', interlaced
+ # in such manner that b[0] is $bp[idx],
+ # b[1] is [2^5+idx], etc.
+$lo0="%r10";
+$hi0="%r11";
+$hi1="%r13";
+$i="%r14";
+$j="%r15";
+$m0="%rbx";
+$m1="%rbp";
+
+$code=<<___;
+.text
+
+.extern OPENSSL_ia32cap_P
+
+.globl bn_mul_mont_gather5
+.type bn_mul_mont_gather5,\@function,6
+.align 64
+bn_mul_mont_gather5:
+ test \$7,${num}d
+ jnz .Lmul_enter
+___
+$code.=<<___ if ($addx);
+ mov OPENSSL_ia32cap_P+8(%rip),%r11d
+___
+$code.=<<___;
+ jmp .Lmul4x_enter
+
+.align 16
+.Lmul_enter:
+ mov ${num}d,${num}d
+ mov %rsp,%rax
+ mov `($win64?56:8)`(%rsp),%r10d # load 7th argument
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+___
+$code.=<<___ if ($win64);
+ lea -0x28(%rsp),%rsp
+ movaps %xmm6,(%rsp)
+ movaps %xmm7,0x10(%rsp)
+___
+$code.=<<___;
+ lea 2($num),%r11
+ neg %r11
+ lea (%rsp,%r11,8),%rsp # tp=alloca(8*(num+2))
+ and \$-1024,%rsp # minimize TLB usage
+
+ mov %rax,8(%rsp,$num,8) # tp[num+1]=%rsp
+.Lmul_body:
+ mov $bp,%r12 # reassign $bp
+___
+ $bp="%r12";
+ $STRIDE=2**5*8; # 5 is "window size"
+ $N=$STRIDE/4; # should match cache line size
+$code.=<<___;
+ mov %r10,%r11
+ shr \$`log($N/8)/log(2)`,%r10
+ and \$`$N/8-1`,%r11
+ not %r10
+ lea .Lmagic_masks(%rip),%rax
+ and \$`2**5/($N/8)-1`,%r10 # 5 is "window size"
+ lea 96($bp,%r11,8),$bp # pointer within 1st cache line
+ movq 0(%rax,%r10,8),%xmm4 # set of masks denoting which
+ movq 8(%rax,%r10,8),%xmm5 # cache line contains element
+ movq 16(%rax,%r10,8),%xmm6 # denoted by 7th argument
+ movq 24(%rax,%r10,8),%xmm7
+
+ movq `0*$STRIDE/4-96`($bp),%xmm0
+ movq `1*$STRIDE/4-96`($bp),%xmm1
+ pand %xmm4,%xmm0
+ movq `2*$STRIDE/4-96`($bp),%xmm2
+ pand %xmm5,%xmm1
+ movq `3*$STRIDE/4-96`($bp),%xmm3
+ pand %xmm6,%xmm2
+ por %xmm1,%xmm0
+ pand %xmm7,%xmm3
+ por %xmm2,%xmm0
+ lea $STRIDE($bp),$bp
+ por %xmm3,%xmm0
+
+ movq %xmm0,$m0 # m0=bp[0]
+
+ mov ($n0),$n0 # pull n0[0] value
+ mov ($ap),%rax
+
+ xor $i,$i # i=0
+ xor $j,$j # j=0
+
+ movq `0*$STRIDE/4-96`($bp),%xmm0
+ movq `1*$STRIDE/4-96`($bp),%xmm1
+ pand %xmm4,%xmm0
+ movq `2*$STRIDE/4-96`($bp),%xmm2
+ pand %xmm5,%xmm1
+
+ mov $n0,$m1
+ mulq $m0 # ap[0]*bp[0]
+ mov %rax,$lo0
+ mov ($np),%rax
+
+ movq `3*$STRIDE/4-96`($bp),%xmm3
+ pand %xmm6,%xmm2
+ por %xmm1,%xmm0
+ pand %xmm7,%xmm3
+
+ imulq $lo0,$m1 # "tp[0]"*n0
+ mov %rdx,$hi0
+
+ por %xmm2,%xmm0
+ lea $STRIDE($bp),$bp
+ por %xmm3,%xmm0
+
+ mulq $m1 # np[0]*m1
+ add %rax,$lo0 # discarded
+ mov 8($ap),%rax
+ adc \$0,%rdx
+ mov %rdx,$hi1
+
+ lea 1($j),$j # j++
+ jmp .L1st_enter
+
+.align 16
+.L1st:
+ add %rax,$hi1
+ mov ($ap,$j,8),%rax
+ adc \$0,%rdx
+ add $hi0,$hi1 # np[j]*m1+ap[j]*bp[0]
+ mov $lo0,$hi0
+ adc \$0,%rdx
+ mov $hi1,-16(%rsp,$j,8) # tp[j-1]
+ mov %rdx,$hi1
+
+.L1st_enter:
+ mulq $m0 # ap[j]*bp[0]
+ add %rax,$hi0
+ mov ($np,$j,8),%rax
+ adc \$0,%rdx
+ lea 1($j),$j # j++
+ mov %rdx,$lo0
+
+ mulq $m1 # np[j]*m1
+ cmp $num,$j
+ jne .L1st
+
+ movq %xmm0,$m0 # bp[1]
+
+ add %rax,$hi1
+ mov ($ap),%rax # ap[0]
+ adc \$0,%rdx
+ add $hi0,$hi1 # np[j]*m1+ap[j]*bp[0]
+ adc \$0,%rdx
+ mov $hi1,-16(%rsp,$j,8) # tp[j-1]
+ mov %rdx,$hi1
+ mov $lo0,$hi0
+
+ xor %rdx,%rdx
+ add $hi0,$hi1
+ adc \$0,%rdx
+ mov $hi1,-8(%rsp,$num,8)
+ mov %rdx,(%rsp,$num,8) # store upmost overflow bit
+
+ lea 1($i),$i # i++
+ jmp .Louter
+.align 16
+.Louter:
+ xor $j,$j # j=0
+ mov $n0,$m1
+ mov (%rsp),$lo0
+
+ movq `0*$STRIDE/4-96`($bp),%xmm0
+ movq `1*$STRIDE/4-96`($bp),%xmm1
+ pand %xmm4,%xmm0
+ movq `2*$STRIDE/4-96`($bp),%xmm2
+ pand %xmm5,%xmm1
+
+ mulq $m0 # ap[0]*bp[i]
+ add %rax,$lo0 # ap[0]*bp[i]+tp[0]
+ mov ($np),%rax
+ adc \$0,%rdx
+
+ movq `3*$STRIDE/4-96`($bp),%xmm3
+ pand %xmm6,%xmm2
+ por %xmm1,%xmm0
+ pand %xmm7,%xmm3
+
+ imulq $lo0,$m1 # tp[0]*n0
+ mov %rdx,$hi0
+
+ por %xmm2,%xmm0
+ lea $STRIDE($bp),$bp
+ por %xmm3,%xmm0
+
+ mulq $m1 # np[0]*m1
+ add %rax,$lo0 # discarded
+ mov 8($ap),%rax
+ adc \$0,%rdx
+ mov 8(%rsp),$lo0 # tp[1]
+ mov %rdx,$hi1
+
+ lea 1($j),$j # j++
+ jmp .Linner_enter
+
+.align 16
+.Linner:
+ add %rax,$hi1
+ mov ($ap,$j,8),%rax
+ adc \$0,%rdx
+ add $lo0,$hi1 # np[j]*m1+ap[j]*bp[i]+tp[j]
+ mov (%rsp,$j,8),$lo0
+ adc \$0,%rdx
+ mov $hi1,-16(%rsp,$j,8) # tp[j-1]
+ mov %rdx,$hi1
+
+.Linner_enter:
+ mulq $m0 # ap[j]*bp[i]
+ add %rax,$hi0
+ mov ($np,$j,8),%rax
+ adc \$0,%rdx
+ add $hi0,$lo0 # ap[j]*bp[i]+tp[j]
+ mov %rdx,$hi0
+ adc \$0,$hi0
+ lea 1($j),$j # j++
+
+ mulq $m1 # np[j]*m1
+ cmp $num,$j
+ jne .Linner
+
+ movq %xmm0,$m0 # bp[i+1]
+
+ add %rax,$hi1
+ mov ($ap),%rax # ap[0]
+ adc \$0,%rdx
+ add $lo0,$hi1 # np[j]*m1+ap[j]*bp[i]+tp[j]
+ mov (%rsp,$j,8),$lo0
+ adc \$0,%rdx
+ mov $hi1,-16(%rsp,$j,8) # tp[j-1]
+ mov %rdx,$hi1
+
+ xor %rdx,%rdx
+ add $hi0,$hi1
+ adc \$0,%rdx
+ add $lo0,$hi1 # pull upmost overflow bit
+ adc \$0,%rdx
+ mov $hi1,-8(%rsp,$num,8)
+ mov %rdx,(%rsp,$num,8) # store upmost overflow bit
+
+ lea 1($i),$i # i++
+ cmp $num,$i
+ jb .Louter
+
+ xor $i,$i # i=0 and clear CF!
+ mov (%rsp),%rax # tp[0]
+ lea (%rsp),$ap # borrow ap for tp
+ mov $num,$j # j=num
+ jmp .Lsub
+.align 16
+.Lsub: sbb ($np,$i,8),%rax
+ mov %rax,($rp,$i,8) # rp[i]=tp[i]-np[i]
+ mov 8($ap,$i,8),%rax # tp[i+1]
+ lea 1($i),$i # i++
+ dec $j # doesnn't affect CF!
+ jnz .Lsub
+
+ sbb \$0,%rax # handle upmost overflow bit
+ xor $i,$i
+ mov $num,$j # j=num
+.align 16
+.Lcopy: # copy or in-place refresh
+ mov (%rsp,$i,8),$ap
+ mov ($rp,$i,8),$np
+ xor $np,$ap # conditional select:
+ and %rax,$ap # ((ap ^ np) & %rax) ^ np
+ xor $np,$ap # ap = borrow?tp:rp
+ mov $i,(%rsp,$i,8) # zap temporary vector
+ mov $ap,($rp,$i,8) # rp[i]=tp[i]
+ lea 1($i),$i
+ sub \$1,$j
+ jnz .Lcopy
+
+ mov 8(%rsp,$num,8),%rsi # restore %rsp
+ mov \$1,%rax
+___
+$code.=<<___ if ($win64);
+ movaps -88(%rsi),%xmm6
+ movaps -72(%rsi),%xmm7
+___
+$code.=<<___;
+ mov -48(%rsi),%r15
+ mov -40(%rsi),%r14
+ mov -32(%rsi),%r13
+ mov -24(%rsi),%r12
+ mov -16(%rsi),%rbp
+ mov -8(%rsi),%rbx
+ lea (%rsi),%rsp
+.Lmul_epilogue:
+ ret
+.size bn_mul_mont_gather5,.-bn_mul_mont_gather5
+___
+{{{
+my @A=("%r10","%r11");
+my @N=("%r13","%rdi");
+$code.=<<___;
+.type bn_mul4x_mont_gather5,\@function,6
+.align 32
+bn_mul4x_mont_gather5:
+.Lmul4x_enter:
+___
+$code.=<<___ if ($addx);
+ and \$0x80100,%r11d
+ cmp \$0x80100,%r11d
+ je .Lmulx4x_enter
+___
+$code.=<<___;
+ .byte 0x67
+ mov %rsp,%rax
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+___
+$code.=<<___ if ($win64);
+ lea -0x28(%rsp),%rsp
+ movaps %xmm6,(%rsp)
+ movaps %xmm7,0x10(%rsp)
+___
+$code.=<<___;
+ .byte 0x67
+ mov ${num}d,%r10d
+ shl \$3,${num}d
+ shl \$3+2,%r10d # 4*$num
+ neg $num # -$num
+
+ ##############################################################
+ # ensure that stack frame doesn't alias with $aptr+4*$num
+ # modulo 4096, which covers ret[num], am[num] and n[2*num]
+ # (see bn_exp.c). this is done to allow memory disambiguation
+ # logic do its magic. [excessive frame is allocated in order
+ # to allow bn_from_mont8x to clear it.]
+ #
+ lea -64(%rsp,$num,2),%r11
+ sub $ap,%r11
+ and \$4095,%r11
+ cmp %r11,%r10
+ jb .Lmul4xsp_alt
+ sub %r11,%rsp # align with $ap
+ lea -64(%rsp,$num,2),%rsp # alloca(128+num*8)
+ jmp .Lmul4xsp_done
+
+.align 32
+.Lmul4xsp_alt:
+ lea 4096-64(,$num,2),%r10
+ lea -64(%rsp,$num,2),%rsp # alloca(128+num*8)
+ sub %r10,%r11
+ mov \$0,%r10
+ cmovc %r10,%r11
+ sub %r11,%rsp
+.Lmul4xsp_done:
+ and \$-64,%rsp
+ neg $num
+
+ mov %rax,40(%rsp)
+.Lmul4x_body:
+
+ call mul4x_internal
+
+ mov 40(%rsp),%rsi # restore %rsp
+ mov \$1,%rax
+___
+$code.=<<___ if ($win64);
+ movaps -88(%rsi),%xmm6
+ movaps -72(%rsi),%xmm7
+___
+$code.=<<___;
+ mov -48(%rsi),%r15
+ mov -40(%rsi),%r14
+ mov -32(%rsi),%r13
+ mov -24(%rsi),%r12
+ mov -16(%rsi),%rbp
+ mov -8(%rsi),%rbx
+ lea (%rsi),%rsp
+.Lmul4x_epilogue:
+ ret
+.size bn_mul4x_mont_gather5,.-bn_mul4x_mont_gather5
+
+.type mul4x_internal,\@abi-omnipotent
+.align 32
+mul4x_internal:
+ shl \$5,$num
+ mov `($win64?56:8)`(%rax),%r10d # load 7th argument
+ lea 256(%rdx,$num),%r13
+ shr \$5,$num # restore $num
+___
+ $bp="%r12";
+ $STRIDE=2**5*8; # 5 is "window size"
+ $N=$STRIDE/4; # should match cache line size
+ $tp=$i;
+$code.=<<___;
+ mov %r10,%r11
+ shr \$`log($N/8)/log(2)`,%r10
+ and \$`$N/8-1`,%r11
+ not %r10
+ lea .Lmagic_masks(%rip),%rax
+ and \$`2**5/($N/8)-1`,%r10 # 5 is "window size"
+ lea 96(%rdx,%r11,8),$bp # pointer within 1st cache line
+ movq 0(%rax,%r10,8),%xmm4 # set of masks denoting which
+ movq 8(%rax,%r10,8),%xmm5 # cache line contains element
+ add \$7,%r11
+ movq 16(%rax,%r10,8),%xmm6 # denoted by 7th argument
+ movq 24(%rax,%r10,8),%xmm7
+ and \$7,%r11
+
+ movq `0*$STRIDE/4-96`($bp),%xmm0
+ lea $STRIDE($bp),$tp # borrow $tp
+ movq `1*$STRIDE/4-96`($bp),%xmm1
+ pand %xmm4,%xmm0
+ movq `2*$STRIDE/4-96`($bp),%xmm2
+ pand %xmm5,%xmm1
+ movq `3*$STRIDE/4-96`($bp),%xmm3
+ pand %xmm6,%xmm2
+ .byte 0x67
+ por %xmm1,%xmm0
+ movq `0*$STRIDE/4-96`($tp),%xmm1
+ .byte 0x67
+ pand %xmm7,%xmm3
+ .byte 0x67
+ por %xmm2,%xmm0
+ movq `1*$STRIDE/4-96`($tp),%xmm2
+ .byte 0x67
+ pand %xmm4,%xmm1
+ .byte 0x67
+ por %xmm3,%xmm0
+ movq `2*$STRIDE/4-96`($tp),%xmm3
+
+ movq %xmm0,$m0 # m0=bp[0]
+ movq `3*$STRIDE/4-96`($tp),%xmm0
+ mov %r13,16+8(%rsp) # save end of b[num]
+ mov $rp, 56+8(%rsp) # save $rp
+
+ mov ($n0),$n0 # pull n0[0] value
+ mov ($ap),%rax
+ lea ($ap,$num),$ap # end of a[num]
+ neg $num
+
+ mov $n0,$m1
+ mulq $m0 # ap[0]*bp[0]
+ mov %rax,$A[0]
+ mov ($np),%rax
+
+ pand %xmm5,%xmm2
+ pand %xmm6,%xmm3
+ por %xmm2,%xmm1
+
+ imulq $A[0],$m1 # "tp[0]"*n0
+ ##############################################################
+ # $tp is chosen so that writing to top-most element of the
+ # vector occurs just "above" references to powers table,
+ # "above" modulo cache-line size, which effectively precludes
+ # possibility of memory disambiguation logic failure when
+ # accessing the table.
+ #
+ lea 64+8(%rsp,%r11,8),$tp
+ mov %rdx,$A[1]
+
+ pand %xmm7,%xmm0
+ por %xmm3,%xmm1
+ lea 2*$STRIDE($bp),$bp
+ por %xmm1,%xmm0
+
+ mulq $m1 # np[0]*m1
+ add %rax,$A[0] # discarded
+ mov 8($ap,$num),%rax
+ adc \$0,%rdx
+ mov %rdx,$N[1]
+
+ mulq $m0
+ add %rax,$A[1]
+ mov 16*1($np),%rax # interleaved with 0, therefore 16*n
+ adc \$0,%rdx
+ mov %rdx,$A[0]
+
+ mulq $m1
+ add %rax,$N[1]
+ mov 16($ap,$num),%rax
+ adc \$0,%rdx
+ add $A[1],$N[1]
+ lea 4*8($num),$j # j=4
+ lea 16*4($np),$np
+ adc \$0,%rdx
+ mov $N[1],($tp)
+ mov %rdx,$N[0]
+ jmp .L1st4x
+
+.align 32
+.L1st4x:
+ mulq $m0 # ap[j]*bp[0]
+ add %rax,$A[0]
+ mov -16*2($np),%rax
+ lea 32($tp),$tp
+ adc \$0,%rdx
+ mov %rdx,$A[1]
+
+ mulq $m1 # np[j]*m1
+ add %rax,$N[0]
+ mov -8($ap,$j),%rax
+ adc \$0,%rdx
+ add $A[0],$N[0] # np[j]*m1+ap[j]*bp[0]
+ adc \$0,%rdx
+ mov $N[0],-24($tp) # tp[j-1]
+ mov %rdx,$N[1]
+
+ mulq $m0 # ap[j]*bp[0]
+ add %rax,$A[1]
+ mov -16*1($np),%rax
+ adc \$0,%rdx
+ mov %rdx,$A[0]
+
+ mulq $m1 # np[j]*m1
+ add %rax,$N[1]
+ mov ($ap,$j),%rax
+ adc \$0,%rdx
+ add $A[1],$N[1] # np[j]*m1+ap[j]*bp[0]
+ adc \$0,%rdx
+ mov $N[1],-16($tp) # tp[j-1]
+ mov %rdx,$N[0]
+
+ mulq $m0 # ap[j]*bp[0]
+ add %rax,$A[0]
+ mov 16*0($np),%rax
+ adc \$0,%rdx
+ mov %rdx,$A[1]
+
+ mulq $m1 # np[j]*m1
+ add %rax,$N[0]
+ mov 8($ap,$j),%rax
+ adc \$0,%rdx
+ add $A[0],$N[0] # np[j]*m1+ap[j]*bp[0]
+ adc \$0,%rdx
+ mov $N[0],-8($tp) # tp[j-1]
+ mov %rdx,$N[1]
+
+ mulq $m0 # ap[j]*bp[0]
+ add %rax,$A[1]
+ mov 16*1($np),%rax
+ adc \$0,%rdx
+ mov %rdx,$A[0]
+
+ mulq $m1 # np[j]*m1
+ add %rax,$N[1]
+ mov 16($ap,$j),%rax
+ adc \$0,%rdx
+ add $A[1],$N[1] # np[j]*m1+ap[j]*bp[0]
+ lea 16*4($np),$np
+ adc \$0,%rdx
+ mov $N[1],($tp) # tp[j-1]
+ mov %rdx,$N[0]
+
+ add \$32,$j # j+=4
+ jnz .L1st4x
+
+ mulq $m0 # ap[j]*bp[0]
+ add %rax,$A[0]
+ mov -16*2($np),%rax
+ lea 32($tp),$tp
+ adc \$0,%rdx
+ mov %rdx,$A[1]
+
+ mulq $m1 # np[j]*m1
+ add %rax,$N[0]
+ mov -8($ap),%rax
+ adc \$0,%rdx
+ add $A[0],$N[0] # np[j]*m1+ap[j]*bp[0]
+ adc \$0,%rdx
+ mov $N[0],-24($tp) # tp[j-1]
+ mov %rdx,$N[1]
+
+ mulq $m0 # ap[j]*bp[0]
+ add %rax,$A[1]
+ mov -16*1($np),%rax
+ adc \$0,%rdx
+ mov %rdx,$A[0]
+
+ mulq $m1 # np[j]*m1
+ add %rax,$N[1]
+ mov ($ap,$num),%rax # ap[0]
+ adc \$0,%rdx
+ add $A[1],$N[1] # np[j]*m1+ap[j]*bp[0]
+ adc \$0,%rdx
+ mov $N[1],-16($tp) # tp[j-1]
+ mov %rdx,$N[0]
+
+ movq %xmm0,$m0 # bp[1]
+ lea ($np,$num,2),$np # rewind $np
+
+ xor $N[1],$N[1]
+ add $A[0],$N[0]
+ adc \$0,$N[1]
+ mov $N[0],-8($tp)
+
+ jmp .Louter4x
+
+.align 32
+.Louter4x:
+ mov ($tp,$num),$A[0]
+ mov $n0,$m1
+ mulq $m0 # ap[0]*bp[i]
+ add %rax,$A[0] # ap[0]*bp[i]+tp[0]
+ mov ($np),%rax
+ adc \$0,%rdx
+
+ movq `0*$STRIDE/4-96`($bp),%xmm0
+ movq `1*$STRIDE/4-96`($bp),%xmm1
+ pand %xmm4,%xmm0
+ movq `2*$STRIDE/4-96`($bp),%xmm2
+ pand %xmm5,%xmm1
+ movq `3*$STRIDE/4-96`($bp),%xmm3
+
+ imulq $A[0],$m1 # tp[0]*n0
+ .byte 0x67
+ mov %rdx,$A[1]
+ mov $N[1],($tp) # store upmost overflow bit
+
+ pand %xmm6,%xmm2
+ por %xmm1,%xmm0
+ pand %xmm7,%xmm3
+ por %xmm2,%xmm0
+ lea ($tp,$num),$tp # rewind $tp
+ lea $STRIDE($bp),$bp
+ por %xmm3,%xmm0
+
+ mulq $m1 # np[0]*m1
+ add %rax,$A[0] # "$N[0]", discarded
+ mov 8($ap,$num),%rax
+ adc \$0,%rdx
+ mov %rdx,$N[1]
+
+ mulq $m0 # ap[j]*bp[i]
+ add %rax,$A[1]
+ mov 16*1($np),%rax # interleaved with 0, therefore 16*n
+ adc \$0,%rdx
+ add 8($tp),$A[1] # +tp[1]
+ adc \$0,%rdx
+ mov %rdx,$A[0]
+
+ mulq $m1 # np[j]*m1
+ add %rax,$N[1]
+ mov 16($ap,$num),%rax
+ adc \$0,%rdx
+ add $A[1],$N[1] # np[j]*m1+ap[j]*bp[i]+tp[j]
+ lea 4*8($num),$j # j=4
+ lea 16*4($np),$np
+ adc \$0,%rdx
+ mov %rdx,$N[0]
+ jmp .Linner4x
+
+.align 32
+.Linner4x:
+ mulq $m0 # ap[j]*bp[i]
+ add %rax,$A[0]
+ mov -16*2($np),%rax
+ adc \$0,%rdx
+ add 16($tp),$A[0] # ap[j]*bp[i]+tp[j]
+ lea 32($tp),$tp
+ adc \$0,%rdx
+ mov %rdx,$A[1]
+
+ mulq $m1 # np[j]*m1
+ add %rax,$N[0]
+ mov -8($ap,$j),%rax
+ adc \$0,%rdx
+ add $A[0],$N[0]
+ adc \$0,%rdx
+ mov $N[1],-32($tp) # tp[j-1]
+ mov %rdx,$N[1]
+
+ mulq $m0 # ap[j]*bp[i]
+ add %rax,$A[1]
+ mov -16*1($np),%rax
+ adc \$0,%rdx
+ add -8($tp),$A[1]
+ adc \$0,%rdx
+ mov %rdx,$A[0]
+
+ mulq $m1 # np[j]*m1
+ add %rax,$N[1]
+ mov ($ap,$j),%rax
+ adc \$0,%rdx
+ add $A[1],$N[1]
+ adc \$0,%rdx
+ mov $N[0],-24($tp) # tp[j-1]
+ mov %rdx,$N[0]
+
+ mulq $m0 # ap[j]*bp[i]
+ add %rax,$A[0]
+ mov 16*0($np),%rax
+ adc \$0,%rdx
+ add ($tp),$A[0] # ap[j]*bp[i]+tp[j]
+ adc \$0,%rdx
+ mov %rdx,$A[1]
+
+ mulq $m1 # np[j]*m1
+ add %rax,$N[0]
+ mov 8($ap,$j),%rax
+ adc \$0,%rdx
+ add $A[0],$N[0]
+ adc \$0,%rdx
+ mov $N[1],-16($tp) # tp[j-1]
+ mov %rdx,$N[1]
+
+ mulq $m0 # ap[j]*bp[i]
+ add %rax,$A[1]
+ mov 16*1($np),%rax
+ adc \$0,%rdx
+ add 8($tp),$A[1]
+ adc \$0,%rdx
+ mov %rdx,$A[0]
+
+ mulq $m1 # np[j]*m1
+ add %rax,$N[1]
+ mov 16($ap,$j),%rax
+ adc \$0,%rdx
+ add $A[1],$N[1]
+ lea 16*4($np),$np
+ adc \$0,%rdx
+ mov $N[0],-8($tp) # tp[j-1]
+ mov %rdx,$N[0]
+
+ add \$32,$j # j+=4
+ jnz .Linner4x
+
+ mulq $m0 # ap[j]*bp[i]
+ add %rax,$A[0]
+ mov -16*2($np),%rax
+ adc \$0,%rdx
+ add 16($tp),$A[0] # ap[j]*bp[i]+tp[j]
+ lea 32($tp),$tp
+ adc \$0,%rdx
+ mov %rdx,$A[1]
+
+ mulq $m1 # np[j]*m1
+ add %rax,$N[0]
+ mov -8($ap),%rax
+ adc \$0,%rdx
+ add $A[0],$N[0]
+ adc \$0,%rdx
+ mov $N[1],-32($tp) # tp[j-1]
+ mov %rdx,$N[1]
+
+ mulq $m0 # ap[j]*bp[i]
+ add %rax,$A[1]
+ mov $m1,%rax
+ mov -16*1($np),$m1
+ adc \$0,%rdx
+ add -8($tp),$A[1]
+ adc \$0,%rdx
+ mov %rdx,$A[0]
+
+ mulq $m1 # np[j]*m1
+ add %rax,$N[1]
+ mov ($ap,$num),%rax # ap[0]
+ adc \$0,%rdx
+ add $A[1],$N[1]
+ adc \$0,%rdx
+ mov $N[0],-24($tp) # tp[j-1]
+ mov %rdx,$N[0]
+
+ movq %xmm0,$m0 # bp[i+1]
+ mov $N[1],-16($tp) # tp[j-1]
+ lea ($np,$num,2),$np # rewind $np
+
+ xor $N[1],$N[1]
+ add $A[0],$N[0]
+ adc \$0,$N[1]
+ add ($tp),$N[0] # pull upmost overflow bit
+ adc \$0,$N[1] # upmost overflow bit
+ mov $N[0],-8($tp)
+
+ cmp 16+8(%rsp),$bp
+ jb .Louter4x
+___
+if (1) {
+$code.=<<___;
+ sub $N[0],$m1 # compare top-most words
+ adc $j,$j # $j is zero
+ or $j,$N[1]
+ xor \$1,$N[1]
+ lea ($tp,$num),%rbx # tptr in .sqr4x_sub
+ lea ($np,$N[1],8),%rbp # nptr in .sqr4x_sub
+ mov %r9,%rcx
+ sar \$3+2,%rcx # cf=0
+ mov 56+8(%rsp),%rdi # rptr in .sqr4x_sub
+ jmp .Lsqr4x_sub
+___
+} else {
+my @ri=("%rax",$bp,$m0,$m1);
+my $rp="%rdx";
+$code.=<<___
+ xor \$1,$N[1]
+ lea ($tp,$num),$tp # rewind $tp
+ sar \$5,$num # cf=0
+ lea ($np,$N[1],8),$np
+ mov 56+8(%rsp),$rp # restore $rp
+ jmp .Lsub4x
+
+.align 32
+.Lsub4x:
+ .byte 0x66
+ mov 8*0($tp),@ri[0]
+ mov 8*1($tp),@ri[1]
+ .byte 0x66
+ sbb 16*0($np),@ri[0]
+ mov 8*2($tp),@ri[2]
+ sbb 16*1($np),@ri[1]
+ mov 3*8($tp),@ri[3]
+ lea 4*8($tp),$tp
+ sbb 16*2($np),@ri[2]
+ mov @ri[0],8*0($rp)
+ sbb 16*3($np),@ri[3]
+ lea 16*4($np),$np
+ mov @ri[1],8*1($rp)
+ mov @ri[2],8*2($rp)
+ mov @ri[3],8*3($rp)
+ lea 8*4($rp),$rp
+
+ inc $num
+ jnz .Lsub4x
+
+ ret
+___
+}
+$code.=<<___;
+.size mul4x_internal,.-mul4x_internal
+___
+}}}
+ {{{
+######################################################################
+# void bn_power5(
+my $rptr="%rdi"; # BN_ULONG *rptr,
+my $aptr="%rsi"; # const BN_ULONG *aptr,
+my $bptr="%rdx"; # const void *table,
+my $nptr="%rcx"; # const BN_ULONG *nptr,
+my $n0 ="%r8"; # const BN_ULONG *n0);
+my $num ="%r9"; # int num, has to be divisible by 8
+ # int pwr
+
+my ($i,$j,$tptr)=("%rbp","%rcx",$rptr);
+my @A0=("%r10","%r11");
+my @A1=("%r12","%r13");
+my ($a0,$a1,$ai)=("%r14","%r15","%rbx");
+
+$code.=<<___;
+.globl bn_power5
+.type bn_power5,\@function,6
+.align 32
+bn_power5:
+___
+$code.=<<___ if ($addx);
+ mov OPENSSL_ia32cap_P+8(%rip),%r11d
+ and \$0x80100,%r11d
+ cmp \$0x80100,%r11d
+ je .Lpowerx5_enter
+___
+$code.=<<___;
+ mov %rsp,%rax
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+___
+$code.=<<___ if ($win64);
+ lea -0x28(%rsp),%rsp
+ movaps %xmm6,(%rsp)
+ movaps %xmm7,0x10(%rsp)
+___
+$code.=<<___;
+ mov ${num}d,%r10d
+ shl \$3,${num}d # convert $num to bytes
+ shl \$3+2,%r10d # 4*$num
+ neg $num
+ mov ($n0),$n0 # *n0
+
+ ##############################################################
+ # ensure that stack frame doesn't alias with $aptr+4*$num
+ # modulo 4096, which covers ret[num], am[num] and n[2*num]
+ # (see bn_exp.c). this is done to allow memory disambiguation
+ # logic do its magic.
+ #
+ lea -64(%rsp,$num,2),%r11
+ sub $aptr,%r11
+ and \$4095,%r11
+ cmp %r11,%r10
+ jb .Lpwr_sp_alt
+ sub %r11,%rsp # align with $aptr
+ lea -64(%rsp,$num,2),%rsp # alloca(frame+2*$num)
+ jmp .Lpwr_sp_done
+
+.align 32
+.Lpwr_sp_alt:
+ lea 4096-64(,$num,2),%r10 # 4096-frame-2*$num
+ lea -64(%rsp,$num,2),%rsp # alloca(frame+2*$num)
+ sub %r10,%r11
+ mov \$0,%r10
+ cmovc %r10,%r11
+ sub %r11,%rsp
+.Lpwr_sp_done:
+ and \$-64,%rsp
+ mov $num,%r10
+ neg $num
+
+ ##############################################################
+ # Stack layout
+ #
+ # +0 saved $num, used in reduction section
+ # +8 &t[2*$num], used in reduction section
+ # +32 saved *n0
+ # +40 saved %rsp
+ # +48 t[2*$num]
+ #
+ mov $n0, 32(%rsp)
+ mov %rax, 40(%rsp) # save original %rsp
+.Lpower5_body:
+ movq $rptr,%xmm1 # save $rptr
+ movq $nptr,%xmm2 # save $nptr
+ movq %r10, %xmm3 # -$num
+ movq $bptr,%xmm4
+
+ call __bn_sqr8x_internal
+ call __bn_sqr8x_internal
+ call __bn_sqr8x_internal
+ call __bn_sqr8x_internal
+ call __bn_sqr8x_internal
+
+ movq %xmm2,$nptr
+ movq %xmm4,$bptr
+ mov $aptr,$rptr
+ mov 40(%rsp),%rax
+ lea 32(%rsp),$n0
+
+ call mul4x_internal
+
+ mov 40(%rsp),%rsi # restore %rsp
+ mov \$1,%rax
+ mov -48(%rsi),%r15
+ mov -40(%rsi),%r14
+ mov -32(%rsi),%r13
+ mov -24(%rsi),%r12
+ mov -16(%rsi),%rbp
+ mov -8(%rsi),%rbx
+ lea (%rsi),%rsp
+.Lpower5_epilogue:
+ ret
+.size bn_power5,.-bn_power5
+
+.globl bn_sqr8x_internal
+.hidden bn_sqr8x_internal
+.type bn_sqr8x_internal,\@abi-omnipotent
+.align 32
+bn_sqr8x_internal:
+__bn_sqr8x_internal:
+ ##############################################################
+ # Squaring part:
+ #
+ # a) multiply-n-add everything but a[i]*a[i];
+ # b) shift result of a) by 1 to the left and accumulate
+ # a[i]*a[i] products;
+ #
+ ##############################################################
+ # a[1]a[0]
+ # a[2]a[0]
+ # a[3]a[0]
+ # a[2]a[1]
+ # a[4]a[0]
+ # a[3]a[1]
+ # a[5]a[0]
+ # a[4]a[1]
+ # a[3]a[2]
+ # a[6]a[0]
+ # a[5]a[1]
+ # a[4]a[2]
+ # a[7]a[0]
+ # a[6]a[1]
+ # a[5]a[2]
+ # a[4]a[3]
+ # a[7]a[1]
+ # a[6]a[2]
+ # a[5]a[3]
+ # a[7]a[2]
+ # a[6]a[3]
+ # a[5]a[4]
+ # a[7]a[3]
+ # a[6]a[4]
+ # a[7]a[4]
+ # a[6]a[5]
+ # a[7]a[5]
+ # a[7]a[6]
+ # a[1]a[0]
+ # a[2]a[0]
+ # a[3]a[0]
+ # a[4]a[0]
+ # a[5]a[0]
+ # a[6]a[0]
+ # a[7]a[0]
+ # a[2]a[1]
+ # a[3]a[1]
+ # a[4]a[1]
+ # a[5]a[1]
+ # a[6]a[1]
+ # a[7]a[1]
+ # a[3]a[2]
+ # a[4]a[2]
+ # a[5]a[2]
+ # a[6]a[2]
+ # a[7]a[2]
+ # a[4]a[3]
+ # a[5]a[3]
+ # a[6]a[3]
+ # a[7]a[3]
+ # a[5]a[4]
+ # a[6]a[4]
+ # a[7]a[4]
+ # a[6]a[5]
+ # a[7]a[5]
+ # a[7]a[6]
+ # a[0]a[0]
+ # a[1]a[1]
+ # a[2]a[2]
+ # a[3]a[3]
+ # a[4]a[4]
+ # a[5]a[5]
+ # a[6]a[6]
+ # a[7]a[7]
+
+ lea 32(%r10),$i # $i=-($num-32)
+ lea ($aptr,$num),$aptr # end of a[] buffer, ($aptr,$i)=&ap[2]
+
+ mov $num,$j # $j=$num
+
+ # comments apply to $num==8 case
+ mov -32($aptr,$i),$a0 # a[0]
+ lea 48+8(%rsp,$num,2),$tptr # end of tp[] buffer, &tp[2*$num]
+ mov -24($aptr,$i),%rax # a[1]
+ lea -32($tptr,$i),$tptr # end of tp[] window, &tp[2*$num-"$i"]
+ mov -16($aptr,$i),$ai # a[2]
+ mov %rax,$a1
+
+ mul $a0 # a[1]*a[0]
+ mov %rax,$A0[0] # a[1]*a[0]
+ mov $ai,%rax # a[2]
+ mov %rdx,$A0[1]
+ mov $A0[0],-24($tptr,$i) # t[1]
+
+ mul $a0 # a[2]*a[0]
+ add %rax,$A0[1]
+ mov $ai,%rax
+ adc \$0,%rdx
+ mov $A0[1],-16($tptr,$i) # t[2]
+ mov %rdx,$A0[0]
+
+
+ mov -8($aptr,$i),$ai # a[3]
+ mul $a1 # a[2]*a[1]
+ mov %rax,$A1[0] # a[2]*a[1]+t[3]
+ mov $ai,%rax
+ mov %rdx,$A1[1]
+
+ lea ($i),$j
+ mul $a0 # a[3]*a[0]
+ add %rax,$A0[0] # a[3]*a[0]+a[2]*a[1]+t[3]
+ mov $ai,%rax
+ mov %rdx,$A0[1]
+ adc \$0,$A0[1]
+ add $A1[0],$A0[0]
+ adc \$0,$A0[1]
+ mov $A0[0],-8($tptr,$j) # t[3]
+ jmp .Lsqr4x_1st
+
+.align 32
+.Lsqr4x_1st:
+ mov ($aptr,$j),$ai # a[4]
+ mul $a1 # a[3]*a[1]
+ add %rax,$A1[1] # a[3]*a[1]+t[4]
+ mov $ai,%rax
+ mov %rdx,$A1[0]
+ adc \$0,$A1[0]
+
+ mul $a0 # a[4]*a[0]
+ add %rax,$A0[1] # a[4]*a[0]+a[3]*a[1]+t[4]
+ mov $ai,%rax # a[3]
+ mov 8($aptr,$j),$ai # a[5]
+ mov %rdx,$A0[0]
+ adc \$0,$A0[0]
+ add $A1[1],$A0[1]
+ adc \$0,$A0[0]
+
+
+ mul $a1 # a[4]*a[3]
+ add %rax,$A1[0] # a[4]*a[3]+t[5]
+ mov $ai,%rax
+ mov $A0[1],($tptr,$j) # t[4]
+ mov %rdx,$A1[1]
+ adc \$0,$A1[1]
+
+ mul $a0 # a[5]*a[2]
+ add %rax,$A0[0] # a[5]*a[2]+a[4]*a[3]+t[5]
+ mov $ai,%rax
+ mov 16($aptr,$j),$ai # a[6]
+ mov %rdx,$A0[1]
+ adc \$0,$A0[1]
+ add $A1[0],$A0[0]
+ adc \$0,$A0[1]
+
+ mul $a1 # a[5]*a[3]
+ add %rax,$A1[1] # a[5]*a[3]+t[6]
+ mov $ai,%rax
+ mov $A0[0],8($tptr,$j) # t[5]
+ mov %rdx,$A1[0]
+ adc \$0,$A1[0]
+
+ mul $a0 # a[6]*a[2]
+ add %rax,$A0[1] # a[6]*a[2]+a[5]*a[3]+t[6]
+ mov $ai,%rax # a[3]
+ mov 24($aptr,$j),$ai # a[7]
+ mov %rdx,$A0[0]
+ adc \$0,$A0[0]
+ add $A1[1],$A0[1]
+ adc \$0,$A0[0]
+
+
+ mul $a1 # a[6]*a[5]
+ add %rax,$A1[0] # a[6]*a[5]+t[7]
+ mov $ai,%rax
+ mov $A0[1],16($tptr,$j) # t[6]
+ mov %rdx,$A1[1]
+ adc \$0,$A1[1]
+ lea 32($j),$j
+
+ mul $a0 # a[7]*a[4]
+ add %rax,$A0[0] # a[7]*a[4]+a[6]*a[5]+t[6]
+ mov $ai,%rax
+ mov %rdx,$A0[1]
+ adc \$0,$A0[1]
+ add $A1[0],$A0[0]
+ adc \$0,$A0[1]
+ mov $A0[0],-8($tptr,$j) # t[7]
+
+ cmp \$0,$j
+ jne .Lsqr4x_1st
+
+ mul $a1 # a[7]*a[5]
+ add %rax,$A1[1]
+ lea 16($i),$i
+ adc \$0,%rdx
+ add $A0[1],$A1[1]
+ adc \$0,%rdx
+
+ mov $A1[1],($tptr) # t[8]
+ mov %rdx,$A1[0]
+ mov %rdx,8($tptr) # t[9]
+ jmp .Lsqr4x_outer
+
+.align 32
+.Lsqr4x_outer: # comments apply to $num==6 case
+ mov -32($aptr,$i),$a0 # a[0]
+ lea 48+8(%rsp,$num,2),$tptr # end of tp[] buffer, &tp[2*$num]
+ mov -24($aptr,$i),%rax # a[1]
+ lea -32($tptr,$i),$tptr # end of tp[] window, &tp[2*$num-"$i"]
+ mov -16($aptr,$i),$ai # a[2]
+ mov %rax,$a1
+
+ mul $a0 # a[1]*a[0]
+ mov -24($tptr,$i),$A0[0] # t[1]
+ add %rax,$A0[0] # a[1]*a[0]+t[1]
+ mov $ai,%rax # a[2]
+ adc \$0,%rdx
+ mov $A0[0],-24($tptr,$i) # t[1]
+ mov %rdx,$A0[1]
+
+ mul $a0 # a[2]*a[0]
+ add %rax,$A0[1]
+ mov $ai,%rax
+ adc \$0,%rdx
+ add -16($tptr,$i),$A0[1] # a[2]*a[0]+t[2]
+ mov %rdx,$A0[0]
+ adc \$0,$A0[0]
+ mov $A0[1],-16($tptr,$i) # t[2]
+
+ xor $A1[0],$A1[0]
+
+ mov -8($aptr,$i),$ai # a[3]
+ mul $a1 # a[2]*a[1]
+ add %rax,$A1[0] # a[2]*a[1]+t[3]
+ mov $ai,%rax
+ adc \$0,%rdx
+ add -8($tptr,$i),$A1[0]
+ mov %rdx,$A1[1]
+ adc \$0,$A1[1]
+
+ mul $a0 # a[3]*a[0]
+ add %rax,$A0[0] # a[3]*a[0]+a[2]*a[1]+t[3]
+ mov $ai,%rax
+ adc \$0,%rdx
+ add $A1[0],$A0[0]
+ mov %rdx,$A0[1]
+ adc \$0,$A0[1]
+ mov $A0[0],-8($tptr,$i) # t[3]
+
+ lea ($i),$j
+ jmp .Lsqr4x_inner
+
+.align 32
+.Lsqr4x_inner:
+ mov ($aptr,$j),$ai # a[4]
+ mul $a1 # a[3]*a[1]
+ add %rax,$A1[1] # a[3]*a[1]+t[4]
+ mov $ai,%rax
+ mov %rdx,$A1[0]
+ adc \$0,$A1[0]
+ add ($tptr,$j),$A1[1]
+ adc \$0,$A1[0]
+
+ .byte 0x67
+ mul $a0 # a[4]*a[0]
+ add %rax,$A0[1] # a[4]*a[0]+a[3]*a[1]+t[4]
+ mov $ai,%rax # a[3]
+ mov 8($aptr,$j),$ai # a[5]
+ mov %rdx,$A0[0]
+ adc \$0,$A0[0]
+ add $A1[1],$A0[1]
+ adc \$0,$A0[0]
+
+ mul $a1 # a[4]*a[3]
+ add %rax,$A1[0] # a[4]*a[3]+t[5]
+ mov $A0[1],($tptr,$j) # t[4]
+ mov $ai,%rax
+ mov %rdx,$A1[1]
+ adc \$0,$A1[1]
+ add 8($tptr,$j),$A1[0]
+ lea 16($j),$j # j++
+ adc \$0,$A1[1]
+
+ mul $a0 # a[5]*a[2]
+ add %rax,$A0[0] # a[5]*a[2]+a[4]*a[3]+t[5]
+ mov $ai,%rax
+ adc \$0,%rdx
+ add $A1[0],$A0[0]
+ mov %rdx,$A0[1]
+ adc \$0,$A0[1]
+ mov $A0[0],-8($tptr,$j) # t[5], "preloaded t[1]" below
+
+ cmp \$0,$j
+ jne .Lsqr4x_inner
+
+ .byte 0x67
+ mul $a1 # a[5]*a[3]
+ add %rax,$A1[1]
+ adc \$0,%rdx
+ add $A0[1],$A1[1]
+ adc \$0,%rdx
+
+ mov $A1[1],($tptr) # t[6], "preloaded t[2]" below
+ mov %rdx,$A1[0]
+ mov %rdx,8($tptr) # t[7], "preloaded t[3]" below
+
+ add \$16,$i
+ jnz .Lsqr4x_outer
+
+ # comments apply to $num==4 case
+ mov -32($aptr),$a0 # a[0]
+ lea 48+8(%rsp,$num,2),$tptr # end of tp[] buffer, &tp[2*$num]
+ mov -24($aptr),%rax # a[1]
+ lea -32($tptr,$i),$tptr # end of tp[] window, &tp[2*$num-"$i"]
+ mov -16($aptr),$ai # a[2]
+ mov %rax,$a1
+
+ mul $a0 # a[1]*a[0]
+ add %rax,$A0[0] # a[1]*a[0]+t[1], preloaded t[1]
+ mov $ai,%rax # a[2]
+ mov %rdx,$A0[1]
+ adc \$0,$A0[1]
+
+ mul $a0 # a[2]*a[0]
+ add %rax,$A0[1]
+ mov $ai,%rax
+ mov $A0[0],-24($tptr) # t[1]
+ mov %rdx,$A0[0]
+ adc \$0,$A0[0]
+ add $A1[1],$A0[1] # a[2]*a[0]+t[2], preloaded t[2]
+ mov -8($aptr),$ai # a[3]
+ adc \$0,$A0[0]
+
+ mul $a1 # a[2]*a[1]
+ add %rax,$A1[0] # a[2]*a[1]+t[3], preloaded t[3]
+ mov $ai,%rax
+ mov $A0[1],-16($tptr) # t[2]
+ mov %rdx,$A1[1]
+ adc \$0,$A1[1]
+
+ mul $a0 # a[3]*a[0]
+ add %rax,$A0[0] # a[3]*a[0]+a[2]*a[1]+t[3]
+ mov $ai,%rax
+ mov %rdx,$A0[1]
+ adc \$0,$A0[1]
+ add $A1[0],$A0[0]
+ adc \$0,$A0[1]
+ mov $A0[0],-8($tptr) # t[3]
+
+ mul $a1 # a[3]*a[1]
+ add %rax,$A1[1]
+ mov -16($aptr),%rax # a[2]
+ adc \$0,%rdx
+ add $A0[1],$A1[1]
+ adc \$0,%rdx
+
+ mov $A1[1],($tptr) # t[4]
+ mov %rdx,$A1[0]
+ mov %rdx,8($tptr) # t[5]
+
+ mul $ai # a[2]*a[3]
+___
+{
+my ($shift,$carry)=($a0,$a1);
+my @S=(@A1,$ai,$n0);
+$code.=<<___;
+ add \$16,$i
+ xor $shift,$shift
+ sub $num,$i # $i=16-$num
+ xor $carry,$carry
+
+ add $A1[0],%rax # t[5]
+ adc \$0,%rdx
+ mov %rax,8($tptr) # t[5]
+ mov %rdx,16($tptr) # t[6]
+ mov $carry,24($tptr) # t[7]
+
+ mov -16($aptr,$i),%rax # a[0]
+ lea 48+8(%rsp),$tptr
+ xor $A0[0],$A0[0] # t[0]
+ mov 8($tptr),$A0[1] # t[1]
+
+ lea ($shift,$A0[0],2),$S[0] # t[2*i]<<1 | shift
+ shr \$63,$A0[0]
+ lea ($j,$A0[1],2),$S[1] # t[2*i+1]<<1 |
+ shr \$63,$A0[1]
+ or $A0[0],$S[1] # | t[2*i]>>63
+ mov 16($tptr),$A0[0] # t[2*i+2] # prefetch
+ mov $A0[1],$shift # shift=t[2*i+1]>>63
+ mul %rax # a[i]*a[i]
+ neg $carry # mov $carry,cf
+ mov 24($tptr),$A0[1] # t[2*i+2+1] # prefetch
+ adc %rax,$S[0]
+ mov -8($aptr,$i),%rax # a[i+1] # prefetch
+ mov $S[0],($tptr)
+ adc %rdx,$S[1]
+
+ lea ($shift,$A0[0],2),$S[2] # t[2*i]<<1 | shift
+ mov $S[1],8($tptr)
+ sbb $carry,$carry # mov cf,$carry
+ shr \$63,$A0[0]
+ lea ($j,$A0[1],2),$S[3] # t[2*i+1]<<1 |
+ shr \$63,$A0[1]
+ or $A0[0],$S[3] # | t[2*i]>>63
+ mov 32($tptr),$A0[0] # t[2*i+2] # prefetch
+ mov $A0[1],$shift # shift=t[2*i+1]>>63
+ mul %rax # a[i]*a[i]
+ neg $carry # mov $carry,cf
+ mov 40($tptr),$A0[1] # t[2*i+2+1] # prefetch
+ adc %rax,$S[2]
+ mov 0($aptr,$i),%rax # a[i+1] # prefetch
+ mov $S[2],16($tptr)
+ adc %rdx,$S[3]
+ lea 16($i),$i
+ mov $S[3],24($tptr)
+ sbb $carry,$carry # mov cf,$carry
+ lea 64($tptr),$tptr
+ jmp .Lsqr4x_shift_n_add
+
+.align 32
+.Lsqr4x_shift_n_add:
+ lea ($shift,$A0[0],2),$S[0] # t[2*i]<<1 | shift
+ shr \$63,$A0[0]
+ lea ($j,$A0[1],2),$S[1] # t[2*i+1]<<1 |
+ shr \$63,$A0[1]
+ or $A0[0],$S[1] # | t[2*i]>>63
+ mov -16($tptr),$A0[0] # t[2*i+2] # prefetch
+ mov $A0[1],$shift # shift=t[2*i+1]>>63
+ mul %rax # a[i]*a[i]
+ neg $carry # mov $carry,cf
+ mov -8($tptr),$A0[1] # t[2*i+2+1] # prefetch
+ adc %rax,$S[0]
+ mov -8($aptr,$i),%rax # a[i+1] # prefetch
+ mov $S[0],-32($tptr)
+ adc %rdx,$S[1]
+
+ lea ($shift,$A0[0],2),$S[2] # t[2*i]<<1 | shift
+ mov $S[1],-24($tptr)
+ sbb $carry,$carry # mov cf,$carry
+ shr \$63,$A0[0]
+ lea ($j,$A0[1],2),$S[3] # t[2*i+1]<<1 |
+ shr \$63,$A0[1]
+ or $A0[0],$S[3] # | t[2*i]>>63
+ mov 0($tptr),$A0[0] # t[2*i+2] # prefetch
+ mov $A0[1],$shift # shift=t[2*i+1]>>63
+ mul %rax # a[i]*a[i]
+ neg $carry # mov $carry,cf
+ mov 8($tptr),$A0[1] # t[2*i+2+1] # prefetch
+ adc %rax,$S[2]
+ mov 0($aptr,$i),%rax # a[i+1] # prefetch
+ mov $S[2],-16($tptr)
+ adc %rdx,$S[3]
+
+ lea ($shift,$A0[0],2),$S[0] # t[2*i]<<1 | shift
+ mov $S[3],-8($tptr)
+ sbb $carry,$carry # mov cf,$carry
+ shr \$63,$A0[0]
+ lea ($j,$A0[1],2),$S[1] # t[2*i+1]<<1 |
+ shr \$63,$A0[1]
+ or $A0[0],$S[1] # | t[2*i]>>63
+ mov 16($tptr),$A0[0] # t[2*i+2] # prefetch
+ mov $A0[1],$shift # shift=t[2*i+1]>>63
+ mul %rax # a[i]*a[i]
+ neg $carry # mov $carry,cf
+ mov 24($tptr),$A0[1] # t[2*i+2+1] # prefetch
+ adc %rax,$S[0]
+ mov 8($aptr,$i),%rax # a[i+1] # prefetch
+ mov $S[0],0($tptr)
+ adc %rdx,$S[1]
+
+ lea ($shift,$A0[0],2),$S[2] # t[2*i]<<1 | shift
+ mov $S[1],8($tptr)
+ sbb $carry,$carry # mov cf,$carry
+ shr \$63,$A0[0]
+ lea ($j,$A0[1],2),$S[3] # t[2*i+1]<<1 |
+ shr \$63,$A0[1]
+ or $A0[0],$S[3] # | t[2*i]>>63
+ mov 32($tptr),$A0[0] # t[2*i+2] # prefetch
+ mov $A0[1],$shift # shift=t[2*i+1]>>63
+ mul %rax # a[i]*a[i]
+ neg $carry # mov $carry,cf
+ mov 40($tptr),$A0[1] # t[2*i+2+1] # prefetch
+ adc %rax,$S[2]
+ mov 16($aptr,$i),%rax # a[i+1] # prefetch
+ mov $S[2],16($tptr)
+ adc %rdx,$S[3]
+ mov $S[3],24($tptr)
+ sbb $carry,$carry # mov cf,$carry
+ lea 64($tptr),$tptr
+ add \$32,$i
+ jnz .Lsqr4x_shift_n_add
+
+ lea ($shift,$A0[0],2),$S[0] # t[2*i]<<1 | shift
+ .byte 0x67
+ shr \$63,$A0[0]
+ lea ($j,$A0[1],2),$S[1] # t[2*i+1]<<1 |
+ shr \$63,$A0[1]
+ or $A0[0],$S[1] # | t[2*i]>>63
+ mov -16($tptr),$A0[0] # t[2*i+2] # prefetch
+ mov $A0[1],$shift # shift=t[2*i+1]>>63
+ mul %rax # a[i]*a[i]
+ neg $carry # mov $carry,cf
+ mov -8($tptr),$A0[1] # t[2*i+2+1] # prefetch
+ adc %rax,$S[0]
+ mov -8($aptr),%rax # a[i+1] # prefetch
+ mov $S[0],-32($tptr)
+ adc %rdx,$S[1]
+
+ lea ($shift,$A0[0],2),$S[2] # t[2*i]<<1|shift
+ mov $S[1],-24($tptr)
+ sbb $carry,$carry # mov cf,$carry
+ shr \$63,$A0[0]
+ lea ($j,$A0[1],2),$S[3] # t[2*i+1]<<1 |
+ shr \$63,$A0[1]
+ or $A0[0],$S[3] # | t[2*i]>>63
+ mul %rax # a[i]*a[i]
+ neg $carry # mov $carry,cf
+ adc %rax,$S[2]
+ adc %rdx,$S[3]
+ mov $S[2],-16($tptr)
+ mov $S[3],-8($tptr)
+___
+}
+######################################################################
+# Montgomery reduction part, "word-by-word" algorithm.
+#
+# This new path is inspired by multiple submissions from Intel, by
+# Shay Gueron, Vlad Krasnov, Erdinc Ozturk, James Guilford,
+# Vinodh Gopal...
+{
+my ($nptr,$tptr,$carry,$m0)=("%rbp","%rdi","%rsi","%rbx");
+
+$code.=<<___;
+ movq %xmm2,$nptr
+sqr8x_reduction:
+ xor %rax,%rax
+ lea ($nptr,$num,2),%rcx # end of n[]
+ lea 48+8(%rsp,$num,2),%rdx # end of t[] buffer
+ mov %rcx,0+8(%rsp)
+ lea 48+8(%rsp,$num),$tptr # end of initial t[] window
+ mov %rdx,8+8(%rsp)
+ neg $num
+ jmp .L8x_reduction_loop
+
+.align 32
+.L8x_reduction_loop:
+ lea ($tptr,$num),$tptr # start of current t[] window
+ .byte 0x66
+ mov 8*0($tptr),$m0
+ mov 8*1($tptr),%r9
+ mov 8*2($tptr),%r10
+ mov 8*3($tptr),%r11
+ mov 8*4($tptr),%r12
+ mov 8*5($tptr),%r13
+ mov 8*6($tptr),%r14
+ mov 8*7($tptr),%r15
+ mov %rax,(%rdx) # store top-most carry bit
+ lea 8*8($tptr),$tptr
+
+ .byte 0x67
+ mov $m0,%r8
+ imulq 32+8(%rsp),$m0 # n0*a[0]
+ mov 16*0($nptr),%rax # n[0]
+ mov \$8,%ecx
+ jmp .L8x_reduce
+
+.align 32
+.L8x_reduce:
+ mulq $m0
+ mov 16*1($nptr),%rax # n[1]
+ neg %r8
+ mov %rdx,%r8
+ adc \$0,%r8
+
+ mulq $m0
+ add %rax,%r9
+ mov 16*2($nptr),%rax
+ adc \$0,%rdx
+ add %r9,%r8
+ mov $m0,48-8+8(%rsp,%rcx,8) # put aside n0*a[i]
+ mov %rdx,%r9
+ adc \$0,%r9
+
+ mulq $m0
+ add %rax,%r10
+ mov 16*3($nptr),%rax
+ adc \$0,%rdx
+ add %r10,%r9
+ mov 32+8(%rsp),$carry # pull n0, borrow $carry
+ mov %rdx,%r10
+ adc \$0,%r10
+
+ mulq $m0
+ add %rax,%r11
+ mov 16*4($nptr),%rax
+ adc \$0,%rdx
+ imulq %r8,$carry # modulo-scheduled
+ add %r11,%r10
+ mov %rdx,%r11
+ adc \$0,%r11
+
+ mulq $m0
+ add %rax,%r12
+ mov 16*5($nptr),%rax
+ adc \$0,%rdx
+ add %r12,%r11
+ mov %rdx,%r12
+ adc \$0,%r12
+
+ mulq $m0
+ add %rax,%r13
+ mov 16*6($nptr),%rax
+ adc \$0,%rdx
+ add %r13,%r12
+ mov %rdx,%r13
+ adc \$0,%r13
+
+ mulq $m0
+ add %rax,%r14
+ mov 16*7($nptr),%rax
+ adc \$0,%rdx
+ add %r14,%r13
+ mov %rdx,%r14
+ adc \$0,%r14
+
+ mulq $m0
+ mov $carry,$m0 # n0*a[i]
+ add %rax,%r15
+ mov 16*0($nptr),%rax # n[0]
+ adc \$0,%rdx
+ add %r15,%r14
+ mov %rdx,%r15
+ adc \$0,%r15
+
+ dec %ecx
+ jnz .L8x_reduce
+
+ lea 16*8($nptr),$nptr
+ xor %rax,%rax
+ mov 8+8(%rsp),%rdx # pull end of t[]
+ cmp 0+8(%rsp),$nptr # end of n[]?
+ jae .L8x_no_tail
+
+ .byte 0x66
+ add 8*0($tptr),%r8
+ adc 8*1($tptr),%r9
+ adc 8*2($tptr),%r10
+ adc 8*3($tptr),%r11
+ adc 8*4($tptr),%r12
+ adc 8*5($tptr),%r13
+ adc 8*6($tptr),%r14
+ adc 8*7($tptr),%r15
+ sbb $carry,$carry # top carry
+
+ mov 48+56+8(%rsp),$m0 # pull n0*a[0]
+ mov \$8,%ecx
+ mov 16*0($nptr),%rax
+ jmp .L8x_tail
+
+.align 32
+.L8x_tail:
+ mulq $m0
+ add %rax,%r8
+ mov 16*1($nptr),%rax
+ mov %r8,($tptr) # save result
+ mov %rdx,%r8
+ adc \$0,%r8
+
+ mulq $m0
+ add %rax,%r9
+ mov 16*2($nptr),%rax
+ adc \$0,%rdx
+ add %r9,%r8
+ lea 8($tptr),$tptr # $tptr++
+ mov %rdx,%r9
+ adc \$0,%r9
+
+ mulq $m0
+ add %rax,%r10
+ mov 16*3($nptr),%rax
+ adc \$0,%rdx
+ add %r10,%r9
+ mov %rdx,%r10
+ adc \$0,%r10
+
+ mulq $m0
+ add %rax,%r11
+ mov 16*4($nptr),%rax
+ adc \$0,%rdx
+ add %r11,%r10
+ mov %rdx,%r11
+ adc \$0,%r11
+
+ mulq $m0
+ add %rax,%r12
+ mov 16*5($nptr),%rax
+ adc \$0,%rdx
+ add %r12,%r11
+ mov %rdx,%r12
+ adc \$0,%r12
+
+ mulq $m0
+ add %rax,%r13
+ mov 16*6($nptr),%rax
+ adc \$0,%rdx
+ add %r13,%r12
+ mov %rdx,%r13
+ adc \$0,%r13
+
+ mulq $m0
+ add %rax,%r14
+ mov 16*7($nptr),%rax
+ adc \$0,%rdx
+ add %r14,%r13
+ mov %rdx,%r14
+ adc \$0,%r14
+
+ mulq $m0
+ mov 48-16+8(%rsp,%rcx,8),$m0# pull n0*a[i]
+ add %rax,%r15
+ adc \$0,%rdx
+ add %r15,%r14
+ mov 16*0($nptr),%rax # pull n[0]
+ mov %rdx,%r15
+ adc \$0,%r15
+
+ dec %ecx
+ jnz .L8x_tail
+
+ lea 16*8($nptr),$nptr
+ mov 8+8(%rsp),%rdx # pull end of t[]
+ cmp 0+8(%rsp),$nptr # end of n[]?
+ jae .L8x_tail_done # break out of loop
+
+ mov 48+56+8(%rsp),$m0 # pull n0*a[0]
+ neg $carry
+ mov 8*0($nptr),%rax # pull n[0]
+ adc 8*0($tptr),%r8
+ adc 8*1($tptr),%r9
+ adc 8*2($tptr),%r10
+ adc 8*3($tptr),%r11
+ adc 8*4($tptr),%r12
+ adc 8*5($tptr),%r13
+ adc 8*6($tptr),%r14
+ adc 8*7($tptr),%r15
+ sbb $carry,$carry # top carry
+
+ mov \$8,%ecx
+ jmp .L8x_tail
+
+.align 32
+.L8x_tail_done:
+ add (%rdx),%r8 # can this overflow?
+ xor %rax,%rax
+
+ neg $carry
+.L8x_no_tail:
+ adc 8*0($tptr),%r8
+ adc 8*1($tptr),%r9
+ adc 8*2($tptr),%r10
+ adc 8*3($tptr),%r11
+ adc 8*4($tptr),%r12
+ adc 8*5($tptr),%r13
+ adc 8*6($tptr),%r14
+ adc 8*7($tptr),%r15
+ adc \$0,%rax # top-most carry
+ mov -16($nptr),%rcx # np[num-1]
+ xor $carry,$carry
+
+ movq %xmm2,$nptr # restore $nptr
+
+ mov %r8,8*0($tptr) # store top 512 bits
+ mov %r9,8*1($tptr)
+ movq %xmm3,$num # $num is %r9, can't be moved upwards
+ mov %r10,8*2($tptr)
+ mov %r11,8*3($tptr)
+ mov %r12,8*4($tptr)
+ mov %r13,8*5($tptr)
+ mov %r14,8*6($tptr)
+ mov %r15,8*7($tptr)
+ lea 8*8($tptr),$tptr
+
+ cmp %rdx,$tptr # end of t[]?
+ jb .L8x_reduction_loop
+___
+}
+##############################################################
+# Post-condition, 4x unrolled
+#
+{
+my ($tptr,$nptr)=("%rbx","%rbp");
+$code.=<<___;
+ #xor %rsi,%rsi # %rsi was $carry above
+ sub %r15,%rcx # compare top-most words
+ lea (%rdi,$num),$tptr # %rdi was $tptr above
+ adc %rsi,%rsi
+ mov $num,%rcx
+ or %rsi,%rax
+ movq %xmm1,$rptr # restore $rptr
+ xor \$1,%rax
+ movq %xmm1,$aptr # prepare for back-to-back call
+ lea ($nptr,%rax,8),$nptr
+ sar \$3+2,%rcx # cf=0
+ jmp .Lsqr4x_sub
+
+.align 32
+.Lsqr4x_sub:
+ .byte 0x66
+ mov 8*0($tptr),%r12
+ mov 8*1($tptr),%r13
+ sbb 16*0($nptr),%r12
+ mov 8*2($tptr),%r14
+ sbb 16*1($nptr),%r13
+ mov 8*3($tptr),%r15
+ lea 8*4($tptr),$tptr
+ sbb 16*2($nptr),%r14
+ mov %r12,8*0($rptr)
+ sbb 16*3($nptr),%r15
+ lea 16*4($nptr),$nptr
+ mov %r13,8*1($rptr)
+ mov %r14,8*2($rptr)
+ mov %r15,8*3($rptr)
+ lea 8*4($rptr),$rptr
+
+ inc %rcx # pass %cf
+ jnz .Lsqr4x_sub
+___
+}
+$code.=<<___;
+ mov $num,%r10 # prepare for back-to-back call
+ neg $num # restore $num
+ ret
+.size bn_sqr8x_internal,.-bn_sqr8x_internal
+___
+{
+$code.=<<___;
+.globl bn_from_montgomery
+.type bn_from_montgomery,\@abi-omnipotent
+.align 32
+bn_from_montgomery:
+ testl \$7,`($win64?"48(%rsp)":"%r9d")`
+ jz bn_from_mont8x
+ xor %eax,%eax
+ ret
+.size bn_from_montgomery,.-bn_from_montgomery
+
+.type bn_from_mont8x,\@function,6
+.align 32
+bn_from_mont8x:
+ .byte 0x67
+ mov %rsp,%rax
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+___
+$code.=<<___ if ($win64);
+ lea -0x28(%rsp),%rsp
+ movaps %xmm6,(%rsp)
+ movaps %xmm7,0x10(%rsp)
+___
+$code.=<<___;
+ .byte 0x67
+ mov ${num}d,%r10d
+ shl \$3,${num}d # convert $num to bytes
+ shl \$3+2,%r10d # 4*$num
+ neg $num
+ mov ($n0),$n0 # *n0
+
+ ##############################################################
+ # ensure that stack frame doesn't alias with $aptr+4*$num
+ # modulo 4096, which covers ret[num], am[num] and n[2*num]
+ # (see bn_exp.c). this is done to allow memory disambiguation
+ # logic do its magic.
+ #
+ lea -64(%rsp,$num,2),%r11
+ sub $aptr,%r11
+ and \$4095,%r11
+ cmp %r11,%r10
+ jb .Lfrom_sp_alt
+ sub %r11,%rsp # align with $aptr
+ lea -64(%rsp,$num,2),%rsp # alloca(frame+2*$num)
+ jmp .Lfrom_sp_done
+
+.align 32
+.Lfrom_sp_alt:
+ lea 4096-64(,$num,2),%r10 # 4096-frame-2*$num
+ lea -64(%rsp,$num,2),%rsp # alloca(frame+2*$num)
+ sub %r10,%r11
+ mov \$0,%r10
+ cmovc %r10,%r11
+ sub %r11,%rsp
+.Lfrom_sp_done:
+ and \$-64,%rsp
+ mov $num,%r10
+ neg $num
+
+ ##############################################################
+ # Stack layout
+ #
+ # +0 saved $num, used in reduction section
+ # +8 &t[2*$num], used in reduction section
+ # +32 saved *n0
+ # +40 saved %rsp
+ # +48 t[2*$num]
+ #
+ mov $n0, 32(%rsp)
+ mov %rax, 40(%rsp) # save original %rsp
+.Lfrom_body:
+ mov $num,%r11
+ lea 48(%rsp),%rax
+ pxor %xmm0,%xmm0
+ jmp .Lmul_by_1
+
+.align 32
+.Lmul_by_1:
+ movdqu ($aptr),%xmm1
+ movdqu 16($aptr),%xmm2
+ movdqu 32($aptr),%xmm3
+ movdqa %xmm0,(%rax,$num)
+ movdqu 48($aptr),%xmm4
+ movdqa %xmm0,16(%rax,$num)
+ .byte 0x48,0x8d,0xb6,0x40,0x00,0x00,0x00 # lea 64($aptr),$aptr
+ movdqa %xmm1,(%rax)
+ movdqa %xmm0,32(%rax,$num)
+ movdqa %xmm2,16(%rax)
+ movdqa %xmm0,48(%rax,$num)
+ movdqa %xmm3,32(%rax)
+ movdqa %xmm4,48(%rax)
+ lea 64(%rax),%rax
+ sub \$64,%r11
+ jnz .Lmul_by_1
+
+ movq $rptr,%xmm1
+ movq $nptr,%xmm2
+ .byte 0x67
+ mov $nptr,%rbp
+ movq %r10, %xmm3 # -num
+___
+$code.=<<___ if ($addx);
+ mov OPENSSL_ia32cap_P+8(%rip),%r11d
+ and \$0x80100,%r11d
+ cmp \$0x80100,%r11d
+ jne .Lfrom_mont_nox
+
+ lea (%rax,$num),$rptr
+ call sqrx8x_reduction
+
+ pxor %xmm0,%xmm0
+ lea 48(%rsp),%rax
+ mov 40(%rsp),%rsi # restore %rsp
+ jmp .Lfrom_mont_zero
+
+.align 32
+.Lfrom_mont_nox:
+___
+$code.=<<___;
+ call sqr8x_reduction
+
+ pxor %xmm0,%xmm0
+ lea 48(%rsp),%rax
+ mov 40(%rsp),%rsi # restore %rsp
+ jmp .Lfrom_mont_zero
+
+.align 32
+.Lfrom_mont_zero:
+ movdqa %xmm0,16*0(%rax)
+ movdqa %xmm0,16*1(%rax)
+ movdqa %xmm0,16*2(%rax)
+ movdqa %xmm0,16*3(%rax)
+ lea 16*4(%rax),%rax
+ sub \$32,$num
+ jnz .Lfrom_mont_zero
+
+ mov \$1,%rax
+ mov -48(%rsi),%r15
+ mov -40(%rsi),%r14
+ mov -32(%rsi),%r13
+ mov -24(%rsi),%r12
+ mov -16(%rsi),%rbp
+ mov -8(%rsi),%rbx
+ lea (%rsi),%rsp
+.Lfrom_epilogue:
+ ret
+.size bn_from_mont8x,.-bn_from_mont8x
+___
+}
+}}}
+
+if ($addx) {{{
+my $bp="%rdx"; # restore original value
+
+$code.=<<___;
+.type bn_mulx4x_mont_gather5,\@function,6
+.align 32
+bn_mulx4x_mont_gather5:
+.Lmulx4x_enter:
+ .byte 0x67
+ mov %rsp,%rax
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+___
+$code.=<<___ if ($win64);
+ lea -0x28(%rsp),%rsp
+ movaps %xmm6,(%rsp)
+ movaps %xmm7,0x10(%rsp)
+___
+$code.=<<___;
+ .byte 0x67
+ mov ${num}d,%r10d
+ shl \$3,${num}d # convert $num to bytes
+ shl \$3+2,%r10d # 4*$num
+ neg $num # -$num
+ mov ($n0),$n0 # *n0
+
+ ##############################################################
+ # ensure that stack frame doesn't alias with $aptr+4*$num
+ # modulo 4096, which covers a[num], ret[num] and n[2*num]
+ # (see bn_exp.c). this is done to allow memory disambiguation
+ # logic do its magic. [excessive frame is allocated in order
+ # to allow bn_from_mont8x to clear it.]
+ #
+ lea -64(%rsp,$num,2),%r11
+ sub $ap,%r11
+ and \$4095,%r11
+ cmp %r11,%r10
+ jb .Lmulx4xsp_alt
+ sub %r11,%rsp # align with $aptr
+ lea -64(%rsp,$num,2),%rsp # alloca(frame+$num)
+ jmp .Lmulx4xsp_done
+
+.align 32
+.Lmulx4xsp_alt:
+ lea 4096-64(,$num,2),%r10 # 4096-frame-$num
+ lea -64(%rsp,$num,2),%rsp # alloca(frame+$num)
+ sub %r10,%r11
+ mov \$0,%r10
+ cmovc %r10,%r11
+ sub %r11,%rsp
+.Lmulx4xsp_done:
+ and \$-64,%rsp # ensure alignment
+ ##############################################################
+ # Stack layout
+ # +0 -num
+ # +8 off-loaded &b[i]
+ # +16 end of b[num]
+ # +24 inner counter
+ # +32 saved n0
+ # +40 saved %rsp
+ # +48
+ # +56 saved rp
+ # +64 tmp[num+1]
+ #
+ mov $n0, 32(%rsp) # save *n0
+ mov %rax,40(%rsp) # save original %rsp
+.Lmulx4x_body:
+ call mulx4x_internal
+
+ mov 40(%rsp),%rsi # restore %rsp
+ mov \$1,%rax
+___
+$code.=<<___ if ($win64);
+ movaps -88(%rsi),%xmm6
+ movaps -72(%rsi),%xmm7
+___
+$code.=<<___;
+ mov -48(%rsi),%r15
+ mov -40(%rsi),%r14
+ mov -32(%rsi),%r13
+ mov -24(%rsi),%r12
+ mov -16(%rsi),%rbp
+ mov -8(%rsi),%rbx
+ lea (%rsi),%rsp
+.Lmulx4x_epilogue:
+ ret
+.size bn_mulx4x_mont_gather5,.-bn_mulx4x_mont_gather5
+
+.type mulx4x_internal,\@abi-omnipotent
+.align 32
+mulx4x_internal:
+ .byte 0x4c,0x89,0x8c,0x24,0x08,0x00,0x00,0x00 # mov $num,8(%rsp) # save -$num
+ .byte 0x67
+ neg $num # restore $num
+ shl \$5,$num
+ lea 256($bp,$num),%r13
+ shr \$5+5,$num
+ mov `($win64?56:8)`(%rax),%r10d # load 7th argument
+ sub \$1,$num
+ mov %r13,16+8(%rsp) # end of b[num]
+ mov $num,24+8(%rsp) # inner counter
+ mov $rp, 56+8(%rsp) # save $rp
+___
+my ($aptr, $bptr, $nptr, $tptr, $mi, $bi, $zero, $num)=
+ ("%rsi","%rdi","%rcx","%rbx","%r8","%r9","%rbp","%rax");
+my $rptr=$bptr;
+my $STRIDE=2**5*8; # 5 is "window size"
+my $N=$STRIDE/4; # should match cache line size
+$code.=<<___;
+ mov %r10,%r11
+ shr \$`log($N/8)/log(2)`,%r10
+ and \$`$N/8-1`,%r11
+ not %r10
+ lea .Lmagic_masks(%rip),%rax
+ and \$`2**5/($N/8)-1`,%r10 # 5 is "window size"
+ lea 96($bp,%r11,8),$bptr # pointer within 1st cache line
+ movq 0(%rax,%r10,8),%xmm4 # set of masks denoting which
+ movq 8(%rax,%r10,8),%xmm5 # cache line contains element
+ add \$7,%r11
+ movq 16(%rax,%r10,8),%xmm6 # denoted by 7th argument
+ movq 24(%rax,%r10,8),%xmm7
+ and \$7,%r11
+
+ movq `0*$STRIDE/4-96`($bptr),%xmm0
+ lea $STRIDE($bptr),$tptr # borrow $tptr
+ movq `1*$STRIDE/4-96`($bptr),%xmm1
+ pand %xmm4,%xmm0
+ movq `2*$STRIDE/4-96`($bptr),%xmm2
+ pand %xmm5,%xmm1
+ movq `3*$STRIDE/4-96`($bptr),%xmm3
+ pand %xmm6,%xmm2
+ por %xmm1,%xmm0
+ movq `0*$STRIDE/4-96`($tptr),%xmm1
+ pand %xmm7,%xmm3
+ por %xmm2,%xmm0
+ movq `1*$STRIDE/4-96`($tptr),%xmm2
+ por %xmm3,%xmm0
+ .byte 0x67,0x67
+ pand %xmm4,%xmm1
+ movq `2*$STRIDE/4-96`($tptr),%xmm3
+
+ movq %xmm0,%rdx # bp[0]
+ movq `3*$STRIDE/4-96`($tptr),%xmm0
+ lea 2*$STRIDE($bptr),$bptr # next &b[i]
+ pand %xmm5,%xmm2
+ .byte 0x67,0x67
+ pand %xmm6,%xmm3
+ ##############################################################
+ # $tptr is chosen so that writing to top-most element of the
+ # vector occurs just "above" references to powers table,
+ # "above" modulo cache-line size, which effectively precludes
+ # possibility of memory disambiguation logic failure when
+ # accessing the table.
+ #
+ lea 64+8*4+8(%rsp,%r11,8),$tptr
+
+ mov %rdx,$bi
+ mulx 0*8($aptr),$mi,%rax # a[0]*b[0]
+ mulx 1*8($aptr),%r11,%r12 # a[1]*b[0]
+ add %rax,%r11
+ mulx 2*8($aptr),%rax,%r13 # ...
+ adc %rax,%r12
+ adc \$0,%r13
+ mulx 3*8($aptr),%rax,%r14
+
+ mov $mi,%r15
+ imulq 32+8(%rsp),$mi # "t[0]"*n0
+ xor $zero,$zero # cf=0, of=0
+ mov $mi,%rdx
+
+ por %xmm2,%xmm1
+ pand %xmm7,%xmm0
+ por %xmm3,%xmm1
+ mov $bptr,8+8(%rsp) # off-load &b[i]
+ por %xmm1,%xmm0
+
+ .byte 0x48,0x8d,0xb6,0x20,0x00,0x00,0x00 # lea 4*8($aptr),$aptr
+ adcx %rax,%r13
+ adcx $zero,%r14 # cf=0
+
+ mulx 0*16($nptr),%rax,%r10
+ adcx %rax,%r15 # discarded
+ adox %r11,%r10
+ mulx 1*16($nptr),%rax,%r11
+ adcx %rax,%r10
+ adox %r12,%r11
+ mulx 2*16($nptr),%rax,%r12
+ mov 24+8(%rsp),$bptr # counter value
+ .byte 0x66
+ mov %r10,-8*4($tptr)
+ adcx %rax,%r11
+ adox %r13,%r12
+ mulx 3*16($nptr),%rax,%r15
+ .byte 0x67,0x67
+ mov $bi,%rdx
+ mov %r11,-8*3($tptr)
+ adcx %rax,%r12
+ adox $zero,%r15 # of=0
+ .byte 0x48,0x8d,0x89,0x40,0x00,0x00,0x00 # lea 4*16($nptr),$nptr
+ mov %r12,-8*2($tptr)
+ #jmp .Lmulx4x_1st
+
+.align 32
+.Lmulx4x_1st:
+ adcx $zero,%r15 # cf=0, modulo-scheduled
+ mulx 0*8($aptr),%r10,%rax # a[4]*b[0]
+ adcx %r14,%r10
+ mulx 1*8($aptr),%r11,%r14 # a[5]*b[0]
+ adcx %rax,%r11
+ mulx 2*8($aptr),%r12,%rax # ...
+ adcx %r14,%r12
+ mulx 3*8($aptr),%r13,%r14
+ .byte 0x67,0x67
+ mov $mi,%rdx
+ adcx %rax,%r13
+ adcx $zero,%r14 # cf=0
+ lea 4*8($aptr),$aptr
+ lea 4*8($tptr),$tptr
+
+ adox %r15,%r10
+ mulx 0*16($nptr),%rax,%r15
+ adcx %rax,%r10
+ adox %r15,%r11
+ mulx 1*16($nptr),%rax,%r15
+ adcx %rax,%r11
+ adox %r15,%r12
+ mulx 2*16($nptr),%rax,%r15
+ mov %r10,-5*8($tptr)
+ adcx %rax,%r12
+ mov %r11,-4*8($tptr)
+ adox %r15,%r13
+ mulx 3*16($nptr),%rax,%r15
+ mov $bi,%rdx
+ mov %r12,-3*8($tptr)
+ adcx %rax,%r13
+ adox $zero,%r15
+ lea 4*16($nptr),$nptr
+ mov %r13,-2*8($tptr)
+
+ dec $bptr # of=0, pass cf
+ jnz .Lmulx4x_1st
+
+ mov 8(%rsp),$num # load -num
+ movq %xmm0,%rdx # bp[1]
+ adc $zero,%r15 # modulo-scheduled
+ lea ($aptr,$num),$aptr # rewind $aptr
+ add %r15,%r14
+ mov 8+8(%rsp),$bptr # re-load &b[i]
+ adc $zero,$zero # top-most carry
+ mov %r14,-1*8($tptr)
+ jmp .Lmulx4x_outer
+
+.align 32
+.Lmulx4x_outer:
+ mov $zero,($tptr) # save top-most carry
+ lea 4*8($tptr,$num),$tptr # rewind $tptr
+ mulx 0*8($aptr),$mi,%r11 # a[0]*b[i]
+ xor $zero,$zero # cf=0, of=0
+ mov %rdx,$bi
+ mulx 1*8($aptr),%r14,%r12 # a[1]*b[i]
+ adox -4*8($tptr),$mi # +t[0]
+ adcx %r14,%r11
+ mulx 2*8($aptr),%r15,%r13 # ...
+ adox -3*8($tptr),%r11
+ adcx %r15,%r12
+ mulx 3*8($aptr),%rdx,%r14
+ adox -2*8($tptr),%r12
+ adcx %rdx,%r13
+ lea ($nptr,$num,2),$nptr # rewind $nptr
+ lea 4*8($aptr),$aptr
+ adox -1*8($tptr),%r13
+ adcx $zero,%r14
+ adox $zero,%r14
+
+ .byte 0x67
+ mov $mi,%r15
+ imulq 32+8(%rsp),$mi # "t[0]"*n0
+
+ movq `0*$STRIDE/4-96`($bptr),%xmm0
+ .byte 0x67,0x67
+ mov $mi,%rdx
+ movq `1*$STRIDE/4-96`($bptr),%xmm1
+ .byte 0x67
+ pand %xmm4,%xmm0
+ movq `2*$STRIDE/4-96`($bptr),%xmm2
+ .byte 0x67
+ pand %xmm5,%xmm1
+ movq `3*$STRIDE/4-96`($bptr),%xmm3
+ add \$$STRIDE,$bptr # next &b[i]
+ .byte 0x67
+ pand %xmm6,%xmm2
+ por %xmm1,%xmm0
+ pand %xmm7,%xmm3
+ xor $zero,$zero # cf=0, of=0
+ mov $bptr,8+8(%rsp) # off-load &b[i]
+
+ mulx 0*16($nptr),%rax,%r10
+ adcx %rax,%r15 # discarded
+ adox %r11,%r10
+ mulx 1*16($nptr),%rax,%r11
+ adcx %rax,%r10
+ adox %r12,%r11
+ mulx 2*16($nptr),%rax,%r12
+ adcx %rax,%r11
+ adox %r13,%r12
+ mulx 3*16($nptr),%rax,%r15
+ mov $bi,%rdx
+ por %xmm2,%xmm0
+ mov 24+8(%rsp),$bptr # counter value
+ mov %r10,-8*4($tptr)
+ por %xmm3,%xmm0
+ adcx %rax,%r12
+ mov %r11,-8*3($tptr)
+ adox $zero,%r15 # of=0
+ mov %r12,-8*2($tptr)
+ lea 4*16($nptr),$nptr
+ jmp .Lmulx4x_inner
+
+.align 32
+.Lmulx4x_inner:
+ mulx 0*8($aptr),%r10,%rax # a[4]*b[i]
+ adcx $zero,%r15 # cf=0, modulo-scheduled
+ adox %r14,%r10
+ mulx 1*8($aptr),%r11,%r14 # a[5]*b[i]
+ adcx 0*8($tptr),%r10
+ adox %rax,%r11
+ mulx 2*8($aptr),%r12,%rax # ...
+ adcx 1*8($tptr),%r11
+ adox %r14,%r12
+ mulx 3*8($aptr),%r13,%r14
+ mov $mi,%rdx
+ adcx 2*8($tptr),%r12
+ adox %rax,%r13
+ adcx 3*8($tptr),%r13
+ adox $zero,%r14 # of=0
+ lea 4*8($aptr),$aptr
+ lea 4*8($tptr),$tptr
+ adcx $zero,%r14 # cf=0
+
+ adox %r15,%r10
+ mulx 0*16($nptr),%rax,%r15
+ adcx %rax,%r10
+ adox %r15,%r11
+ mulx 1*16($nptr),%rax,%r15
+ adcx %rax,%r11
+ adox %r15,%r12
+ mulx 2*16($nptr),%rax,%r15
+ mov %r10,-5*8($tptr)
+ adcx %rax,%r12
+ adox %r15,%r13
+ mov %r11,-4*8($tptr)
+ mulx 3*16($nptr),%rax,%r15
+ mov $bi,%rdx
+ lea 4*16($nptr),$nptr
+ mov %r12,-3*8($tptr)
+ adcx %rax,%r13
+ adox $zero,%r15
+ mov %r13,-2*8($tptr)
+
+ dec $bptr # of=0, pass cf
+ jnz .Lmulx4x_inner
+
+ mov 0+8(%rsp),$num # load -num
+ movq %xmm0,%rdx # bp[i+1]
+ adc $zero,%r15 # modulo-scheduled
+ sub 0*8($tptr),$bptr # pull top-most carry to %cf
+ mov 8+8(%rsp),$bptr # re-load &b[i]
+ mov 16+8(%rsp),%r10
+ adc %r15,%r14
+ lea ($aptr,$num),$aptr # rewind $aptr
+ adc $zero,$zero # top-most carry
+ mov %r14,-1*8($tptr)
+
+ cmp %r10,$bptr
+ jb .Lmulx4x_outer
+
+ mov -16($nptr),%r10
+ xor %r15,%r15
+ sub %r14,%r10 # compare top-most words
+ adc %r15,%r15
+ or %r15,$zero
+ xor \$1,$zero
+ lea ($tptr,$num),%rdi # rewind $tptr
+ lea ($nptr,$num,2),$nptr # rewind $nptr
+ .byte 0x67,0x67
+ sar \$3+2,$num # cf=0
+ lea ($nptr,$zero,8),%rbp
+ mov 56+8(%rsp),%rdx # restore rp
+ mov $num,%rcx
+ jmp .Lsqrx4x_sub # common post-condition
+.size mulx4x_internal,.-mulx4x_internal
+___
+} {
+######################################################################
+# void bn_power5(
+my $rptr="%rdi"; # BN_ULONG *rptr,
+my $aptr="%rsi"; # const BN_ULONG *aptr,
+my $bptr="%rdx"; # const void *table,
+my $nptr="%rcx"; # const BN_ULONG *nptr,
+my $n0 ="%r8"; # const BN_ULONG *n0);
+my $num ="%r9"; # int num, has to be divisible by 8
+ # int pwr);
+
+my ($i,$j,$tptr)=("%rbp","%rcx",$rptr);
+my @A0=("%r10","%r11");
+my @A1=("%r12","%r13");
+my ($a0,$a1,$ai)=("%r14","%r15","%rbx");
+
+$code.=<<___;
+.type bn_powerx5,\@function,6
+.align 32
+bn_powerx5:
+.Lpowerx5_enter:
+ .byte 0x67
+ mov %rsp,%rax
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+___
+$code.=<<___ if ($win64);
+ lea -0x28(%rsp),%rsp
+ movaps %xmm6,(%rsp)
+ movaps %xmm7,0x10(%rsp)
+___
+$code.=<<___;
+ .byte 0x67
+ mov ${num}d,%r10d
+ shl \$3,${num}d # convert $num to bytes
+ shl \$3+2,%r10d # 4*$num
+ neg $num
+ mov ($n0),$n0 # *n0
+
+ ##############################################################
+ # ensure that stack frame doesn't alias with $aptr+4*$num
+ # modulo 4096, which covers ret[num], am[num] and n[2*num]
+ # (see bn_exp.c). this is done to allow memory disambiguation
+ # logic do its magic.
+ #
+ lea -64(%rsp,$num,2),%r11
+ sub $aptr,%r11
+ and \$4095,%r11
+ cmp %r11,%r10
+ jb .Lpwrx_sp_alt
+ sub %r11,%rsp # align with $aptr
+ lea -64(%rsp,$num,2),%rsp # alloca(frame+2*$num)
+ jmp .Lpwrx_sp_done
+
+.align 32
+.Lpwrx_sp_alt:
+ lea 4096-64(,$num,2),%r10 # 4096-frame-2*$num
+ lea -64(%rsp,$num,2),%rsp # alloca(frame+2*$num)
+ sub %r10,%r11
+ mov \$0,%r10
+ cmovc %r10,%r11
+ sub %r11,%rsp
+.Lpwrx_sp_done:
+ and \$-64,%rsp
+ mov $num,%r10
+ neg $num
+
+ ##############################################################
+ # Stack layout
+ #
+ # +0 saved $num, used in reduction section
+ # +8 &t[2*$num], used in reduction section
+ # +16 intermediate carry bit
+ # +24 top-most carry bit, used in reduction section
+ # +32 saved *n0
+ # +40 saved %rsp
+ # +48 t[2*$num]
+ #
+ pxor %xmm0,%xmm0
+ movq $rptr,%xmm1 # save $rptr
+ movq $nptr,%xmm2 # save $nptr
+ movq %r10, %xmm3 # -$num
+ movq $bptr,%xmm4
+ mov $n0, 32(%rsp)
+ mov %rax, 40(%rsp) # save original %rsp
+.Lpowerx5_body:
+
+ call __bn_sqrx8x_internal
+ call __bn_sqrx8x_internal
+ call __bn_sqrx8x_internal
+ call __bn_sqrx8x_internal
+ call __bn_sqrx8x_internal
+
+ mov %r10,$num # -num
+ mov $aptr,$rptr
+ movq %xmm2,$nptr
+ movq %xmm4,$bptr
+ mov 40(%rsp),%rax
+
+ call mulx4x_internal
+
+ mov 40(%rsp),%rsi # restore %rsp
+ mov \$1,%rax
+___
+$code.=<<___ if ($win64);
+ movaps -88(%rsi),%xmm6
+ movaps -72(%rsi),%xmm7
+___
+$code.=<<___;
+ mov -48(%rsi),%r15
+ mov -40(%rsi),%r14
+ mov -32(%rsi),%r13
+ mov -24(%rsi),%r12
+ mov -16(%rsi),%rbp
+ mov -8(%rsi),%rbx
+ lea (%rsi),%rsp
+.Lpowerx5_epilogue:
+ ret
+.size bn_powerx5,.-bn_powerx5
+
+.globl bn_sqrx8x_internal
+.hidden bn_sqrx8x_internal
+.type bn_sqrx8x_internal,\@abi-omnipotent
+.align 32
+bn_sqrx8x_internal:
+__bn_sqrx8x_internal:
+ ##################################################################
+ # Squaring part:
+ #
+ # a) multiply-n-add everything but a[i]*a[i];
+ # b) shift result of a) by 1 to the left and accumulate
+ # a[i]*a[i] products;
+ #
+ ##################################################################
+ # a[7]a[7]a[6]a[6]a[5]a[5]a[4]a[4]a[3]a[3]a[2]a[2]a[1]a[1]a[0]a[0]
+ # a[1]a[0]
+ # a[2]a[0]
+ # a[3]a[0]
+ # a[2]a[1]
+ # a[3]a[1]
+ # a[3]a[2]
+ #
+ # a[4]a[0]
+ # a[5]a[0]
+ # a[6]a[0]
+ # a[7]a[0]
+ # a[4]a[1]
+ # a[5]a[1]
+ # a[6]a[1]
+ # a[7]a[1]
+ # a[4]a[2]
+ # a[5]a[2]
+ # a[6]a[2]
+ # a[7]a[2]
+ # a[4]a[3]
+ # a[5]a[3]
+ # a[6]a[3]
+ # a[7]a[3]
+ #
+ # a[5]a[4]
+ # a[6]a[4]
+ # a[7]a[4]
+ # a[6]a[5]
+ # a[7]a[5]
+ # a[7]a[6]
+ # a[7]a[7]a[6]a[6]a[5]a[5]a[4]a[4]a[3]a[3]a[2]a[2]a[1]a[1]a[0]a[0]
+___
+{
+my ($zero,$carry)=("%rbp","%rcx");
+my $aaptr=$zero;
+$code.=<<___;
+ lea 48+8(%rsp),$tptr
+ lea ($aptr,$num),$aaptr
+ mov $num,0+8(%rsp) # save $num
+ mov $aaptr,8+8(%rsp) # save end of $aptr
+ jmp .Lsqr8x_zero_start
+
+.align 32
+.byte 0x66,0x66,0x66,0x2e,0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00
+.Lsqrx8x_zero:
+ .byte 0x3e
+ movdqa %xmm0,0*8($tptr)
+ movdqa %xmm0,2*8($tptr)
+ movdqa %xmm0,4*8($tptr)
+ movdqa %xmm0,6*8($tptr)
+.Lsqr8x_zero_start: # aligned at 32
+ movdqa %xmm0,8*8($tptr)
+ movdqa %xmm0,10*8($tptr)
+ movdqa %xmm0,12*8($tptr)
+ movdqa %xmm0,14*8($tptr)
+ lea 16*8($tptr),$tptr
+ sub \$64,$num
+ jnz .Lsqrx8x_zero
+
+ mov 0*8($aptr),%rdx # a[0], modulo-scheduled
+ #xor %r9,%r9 # t[1], ex-$num, zero already
+ xor %r10,%r10
+ xor %r11,%r11
+ xor %r12,%r12
+ xor %r13,%r13
+ xor %r14,%r14
+ xor %r15,%r15
+ lea 48+8(%rsp),$tptr
+ xor $zero,$zero # cf=0, cf=0
+ jmp .Lsqrx8x_outer_loop
+
+.align 32
+.Lsqrx8x_outer_loop:
+ mulx 1*8($aptr),%r8,%rax # a[1]*a[0]
+ adcx %r9,%r8 # a[1]*a[0]+=t[1]
+ adox %rax,%r10
+ mulx 2*8($aptr),%r9,%rax # a[2]*a[0]
+ adcx %r10,%r9
+ adox %rax,%r11
+ .byte 0xc4,0xe2,0xab,0xf6,0x86,0x18,0x00,0x00,0x00 # mulx 3*8($aptr),%r10,%rax # ...
+ adcx %r11,%r10
+ adox %rax,%r12
+ .byte 0xc4,0xe2,0xa3,0xf6,0x86,0x20,0x00,0x00,0x00 # mulx 4*8($aptr),%r11,%rax
+ adcx %r12,%r11
+ adox %rax,%r13
+ mulx 5*8($aptr),%r12,%rax
+ adcx %r13,%r12
+ adox %rax,%r14
+ mulx 6*8($aptr),%r13,%rax
+ adcx %r14,%r13
+ adox %r15,%rax
+ mulx 7*8($aptr),%r14,%r15
+ mov 1*8($aptr),%rdx # a[1]
+ adcx %rax,%r14
+ adox $zero,%r15
+ adc 8*8($tptr),%r15
+ mov %r8,1*8($tptr) # t[1]
+ mov %r9,2*8($tptr) # t[2]
+ sbb $carry,$carry # mov %cf,$carry
+ xor $zero,$zero # cf=0, of=0
+
+
+ mulx 2*8($aptr),%r8,%rbx # a[2]*a[1]
+ mulx 3*8($aptr),%r9,%rax # a[3]*a[1]
+ adcx %r10,%r8
+ adox %rbx,%r9
+ mulx 4*8($aptr),%r10,%rbx # ...
+ adcx %r11,%r9
+ adox %rax,%r10
+ .byte 0xc4,0xe2,0xa3,0xf6,0x86,0x28,0x00,0x00,0x00 # mulx 5*8($aptr),%r11,%rax
+ adcx %r12,%r10
+ adox %rbx,%r11
+ .byte 0xc4,0xe2,0x9b,0xf6,0x9e,0x30,0x00,0x00,0x00 # mulx 6*8($aptr),%r12,%rbx
+ adcx %r13,%r11
+ adox %r14,%r12
+ .byte 0xc4,0x62,0x93,0xf6,0xb6,0x38,0x00,0x00,0x00 # mulx 7*8($aptr),%r13,%r14
+ mov 2*8($aptr),%rdx # a[2]
+ adcx %rax,%r12
+ adox %rbx,%r13
+ adcx %r15,%r13
+ adox $zero,%r14 # of=0
+ adcx $zero,%r14 # cf=0
+
+ mov %r8,3*8($tptr) # t[3]
+ mov %r9,4*8($tptr) # t[4]
+
+ mulx 3*8($aptr),%r8,%rbx # a[3]*a[2]
+ mulx 4*8($aptr),%r9,%rax # a[4]*a[2]
+ adcx %r10,%r8
+ adox %rbx,%r9
+ mulx 5*8($aptr),%r10,%rbx # ...
+ adcx %r11,%r9
+ adox %rax,%r10
+ .byte 0xc4,0xe2,0xa3,0xf6,0x86,0x30,0x00,0x00,0x00 # mulx 6*8($aptr),%r11,%rax
+ adcx %r12,%r10
+ adox %r13,%r11
+ .byte 0xc4,0x62,0x9b,0xf6,0xae,0x38,0x00,0x00,0x00 # mulx 7*8($aptr),%r12,%r13
+ .byte 0x3e
+ mov 3*8($aptr),%rdx # a[3]
+ adcx %rbx,%r11
+ adox %rax,%r12
+ adcx %r14,%r12
+ mov %r8,5*8($tptr) # t[5]
+ mov %r9,6*8($tptr) # t[6]
+ mulx 4*8($aptr),%r8,%rax # a[4]*a[3]
+ adox $zero,%r13 # of=0
+ adcx $zero,%r13 # cf=0
+
+ mulx 5*8($aptr),%r9,%rbx # a[5]*a[3]
+ adcx %r10,%r8
+ adox %rax,%r9
+ mulx 6*8($aptr),%r10,%rax # ...
+ adcx %r11,%r9
+ adox %r12,%r10
+ mulx 7*8($aptr),%r11,%r12
+ mov 4*8($aptr),%rdx # a[4]
+ mov 5*8($aptr),%r14 # a[5]
+ adcx %rbx,%r10
+ adox %rax,%r11
+ mov 6*8($aptr),%r15 # a[6]
+ adcx %r13,%r11
+ adox $zero,%r12 # of=0
+ adcx $zero,%r12 # cf=0
+
+ mov %r8,7*8($tptr) # t[7]
+ mov %r9,8*8($tptr) # t[8]
+
+ mulx %r14,%r9,%rax # a[5]*a[4]
+ mov 7*8($aptr),%r8 # a[7]
+ adcx %r10,%r9
+ mulx %r15,%r10,%rbx # a[6]*a[4]
+ adox %rax,%r10
+ adcx %r11,%r10
+ mulx %r8,%r11,%rax # a[7]*a[4]
+ mov %r14,%rdx # a[5]
+ adox %rbx,%r11
+ adcx %r12,%r11
+ #adox $zero,%rax # of=0
+ adcx $zero,%rax # cf=0
+
+ mulx %r15,%r14,%rbx # a[6]*a[5]
+ mulx %r8,%r12,%r13 # a[7]*a[5]
+ mov %r15,%rdx # a[6]
+ lea 8*8($aptr),$aptr
+ adcx %r14,%r11
+ adox %rbx,%r12
+ adcx %rax,%r12
+ adox $zero,%r13
+
+ .byte 0x67,0x67
+ mulx %r8,%r8,%r14 # a[7]*a[6]
+ adcx %r8,%r13
+ adcx $zero,%r14
+
+ cmp 8+8(%rsp),$aptr
+ je .Lsqrx8x_outer_break
+
+ neg $carry # mov $carry,%cf
+ mov \$-8,%rcx
+ mov $zero,%r15
+ mov 8*8($tptr),%r8
+ adcx 9*8($tptr),%r9 # +=t[9]
+ adcx 10*8($tptr),%r10 # ...
+ adcx 11*8($tptr),%r11
+ adc 12*8($tptr),%r12
+ adc 13*8($tptr),%r13
+ adc 14*8($tptr),%r14
+ adc 15*8($tptr),%r15
+ lea ($aptr),$aaptr
+ lea 2*64($tptr),$tptr
+ sbb %rax,%rax # mov %cf,$carry
+
+ mov -64($aptr),%rdx # a[0]
+ mov %rax,16+8(%rsp) # offload $carry
+ mov $tptr,24+8(%rsp)
+
+ #lea 8*8($tptr),$tptr # see 2*8*8($tptr) above
+ xor %eax,%eax # cf=0, of=0
+ jmp .Lsqrx8x_loop
+
+.align 32
+.Lsqrx8x_loop:
+ mov %r8,%rbx
+ mulx 0*8($aaptr),%rax,%r8 # a[8]*a[i]
+ adcx %rax,%rbx # +=t[8]
+ adox %r9,%r8
+
+ mulx 1*8($aaptr),%rax,%r9 # ...
+ adcx %rax,%r8
+ adox %r10,%r9
+
+ mulx 2*8($aaptr),%rax,%r10
+ adcx %rax,%r9
+ adox %r11,%r10
+
+ mulx 3*8($aaptr),%rax,%r11
+ adcx %rax,%r10
+ adox %r12,%r11
+
+ .byte 0xc4,0x62,0xfb,0xf6,0xa5,0x20,0x00,0x00,0x00 # mulx 4*8($aaptr),%rax,%r12
+ adcx %rax,%r11
+ adox %r13,%r12
+
+ mulx 5*8($aaptr),%rax,%r13
+ adcx %rax,%r12
+ adox %r14,%r13
+
+ mulx 6*8($aaptr),%rax,%r14
+ mov %rbx,($tptr,%rcx,8) # store t[8+i]
+ mov \$0,%ebx
+ adcx %rax,%r13
+ adox %r15,%r14
+
+ .byte 0xc4,0x62,0xfb,0xf6,0xbd,0x38,0x00,0x00,0x00 # mulx 7*8($aaptr),%rax,%r15
+ mov 8($aptr,%rcx,8),%rdx # a[i]
+ adcx %rax,%r14
+ adox %rbx,%r15 # %rbx is 0, of=0
+ adcx %rbx,%r15 # cf=0
+
+ .byte 0x67
+ inc %rcx # of=0
+ jnz .Lsqrx8x_loop
+
+ lea 8*8($aaptr),$aaptr
+ mov \$-8,%rcx
+ cmp 8+8(%rsp),$aaptr # done?
+ je .Lsqrx8x_break
+
+ sub 16+8(%rsp),%rbx # mov 16(%rsp),%cf
+ .byte 0x66
+ mov -64($aptr),%rdx
+ adcx 0*8($tptr),%r8
+ adcx 1*8($tptr),%r9
+ adc 2*8($tptr),%r10
+ adc 3*8($tptr),%r11
+ adc 4*8($tptr),%r12
+ adc 5*8($tptr),%r13
+ adc 6*8($tptr),%r14
+ adc 7*8($tptr),%r15
+ lea 8*8($tptr),$tptr
+ .byte 0x67
+ sbb %rax,%rax # mov %cf,%rax
+ xor %ebx,%ebx # cf=0, of=0
+ mov %rax,16+8(%rsp) # offload carry
+ jmp .Lsqrx8x_loop
+
+.align 32
+.Lsqrx8x_break:
+ sub 16+8(%rsp),%r8 # consume last carry
+ mov 24+8(%rsp),$carry # initial $tptr, borrow $carry
+ mov 0*8($aptr),%rdx # a[8], modulo-scheduled
+ xor %ebp,%ebp # xor $zero,$zero
+ mov %r8,0*8($tptr)
+ cmp $carry,$tptr # cf=0, of=0
+ je .Lsqrx8x_outer_loop
+
+ mov %r9,1*8($tptr)
+ mov 1*8($carry),%r9
+ mov %r10,2*8($tptr)
+ mov 2*8($carry),%r10
+ mov %r11,3*8($tptr)
+ mov 3*8($carry),%r11
+ mov %r12,4*8($tptr)
+ mov 4*8($carry),%r12
+ mov %r13,5*8($tptr)
+ mov 5*8($carry),%r13
+ mov %r14,6*8($tptr)
+ mov 6*8($carry),%r14
+ mov %r15,7*8($tptr)
+ mov 7*8($carry),%r15
+ mov $carry,$tptr
+ jmp .Lsqrx8x_outer_loop
+
+.align 32
+.Lsqrx8x_outer_break:
+ mov %r9,9*8($tptr) # t[9]
+ movq %xmm3,%rcx # -$num
+ mov %r10,10*8($tptr) # ...
+ mov %r11,11*8($tptr)
+ mov %r12,12*8($tptr)
+ mov %r13,13*8($tptr)
+ mov %r14,14*8($tptr)
+___
+} {
+my $i="%rcx";
+$code.=<<___;
+ lea 48+8(%rsp),$tptr
+ mov ($aptr,$i),%rdx # a[0]
+
+ mov 8($tptr),$A0[1] # t[1]
+ xor $A0[0],$A0[0] # t[0], of=0, cf=0
+ mov 0+8(%rsp),$num # restore $num
+ adox $A0[1],$A0[1]
+ mov 16($tptr),$A1[0] # t[2] # prefetch
+ mov 24($tptr),$A1[1] # t[3] # prefetch
+ #jmp .Lsqrx4x_shift_n_add # happens to be aligned
+
+.align 32
+.Lsqrx4x_shift_n_add:
+ mulx %rdx,%rax,%rbx
+ adox $A1[0],$A1[0]
+ adcx $A0[0],%rax
+ .byte 0x48,0x8b,0x94,0x0e,0x08,0x00,0x00,0x00 # mov 8($aptr,$i),%rdx # a[i+1] # prefetch
+ .byte 0x4c,0x8b,0x97,0x20,0x00,0x00,0x00 # mov 32($tptr),$A0[0] # t[2*i+4] # prefetch
+ adox $A1[1],$A1[1]
+ adcx $A0[1],%rbx
+ mov 40($tptr),$A0[1] # t[2*i+4+1] # prefetch
+ mov %rax,0($tptr)
+ mov %rbx,8($tptr)
+
+ mulx %rdx,%rax,%rbx
+ adox $A0[0],$A0[0]
+ adcx $A1[0],%rax
+ mov 16($aptr,$i),%rdx # a[i+2] # prefetch
+ mov 48($tptr),$A1[0] # t[2*i+6] # prefetch
+ adox $A0[1],$A0[1]
+ adcx $A1[1],%rbx
+ mov 56($tptr),$A1[1] # t[2*i+6+1] # prefetch
+ mov %rax,16($tptr)
+ mov %rbx,24($tptr)
+
+ mulx %rdx,%rax,%rbx
+ adox $A1[0],$A1[0]
+ adcx $A0[0],%rax
+ mov 24($aptr,$i),%rdx # a[i+3] # prefetch
+ lea 32($i),$i
+ mov 64($tptr),$A0[0] # t[2*i+8] # prefetch
+ adox $A1[1],$A1[1]
+ adcx $A0[1],%rbx
+ mov 72($tptr),$A0[1] # t[2*i+8+1] # prefetch
+ mov %rax,32($tptr)
+ mov %rbx,40($tptr)
+
+ mulx %rdx,%rax,%rbx
+ adox $A0[0],$A0[0]
+ adcx $A1[0],%rax
+ jrcxz .Lsqrx4x_shift_n_add_break
+ .byte 0x48,0x8b,0x94,0x0e,0x00,0x00,0x00,0x00 # mov 0($aptr,$i),%rdx # a[i+4] # prefetch
+ adox $A0[1],$A0[1]
+ adcx $A1[1],%rbx
+ mov 80($tptr),$A1[0] # t[2*i+10] # prefetch
+ mov 88($tptr),$A1[1] # t[2*i+10+1] # prefetch
+ mov %rax,48($tptr)
+ mov %rbx,56($tptr)
+ lea 64($tptr),$tptr
+ nop
+ jmp .Lsqrx4x_shift_n_add
+
+.align 32
+.Lsqrx4x_shift_n_add_break:
+ adcx $A1[1],%rbx
+ mov %rax,48($tptr)
+ mov %rbx,56($tptr)
+ lea 64($tptr),$tptr # end of t[] buffer
+___
+}
+######################################################################
+# Montgomery reduction part, "word-by-word" algorithm.
+#
+# This new path is inspired by multiple submissions from Intel, by
+# Shay Gueron, Vlad Krasnov, Erdinc Ozturk, James Guilford,
+# Vinodh Gopal...
+{
+my ($nptr,$carry,$m0)=("%rbp","%rsi","%rdx");
+
+$code.=<<___;
+ movq %xmm2,$nptr
+sqrx8x_reduction:
+ xor %eax,%eax # initial top-most carry bit
+ mov 32+8(%rsp),%rbx # n0
+ mov 48+8(%rsp),%rdx # "%r8", 8*0($tptr)
+ lea -128($nptr,$num,2),%rcx # end of n[]
+ #lea 48+8(%rsp,$num,2),$tptr # end of t[] buffer
+ mov %rcx, 0+8(%rsp) # save end of n[]
+ mov $tptr,8+8(%rsp) # save end of t[]
+
+ lea 48+8(%rsp),$tptr # initial t[] window
+ jmp .Lsqrx8x_reduction_loop
+
+.align 32
+.Lsqrx8x_reduction_loop:
+ mov 8*1($tptr),%r9
+ mov 8*2($tptr),%r10
+ mov 8*3($tptr),%r11
+ mov 8*4($tptr),%r12
+ mov %rdx,%r8
+ imulq %rbx,%rdx # n0*a[i]
+ mov 8*5($tptr),%r13
+ mov 8*6($tptr),%r14
+ mov 8*7($tptr),%r15
+ mov %rax,24+8(%rsp) # store top-most carry bit
+
+ lea 8*8($tptr),$tptr
+ xor $carry,$carry # cf=0,of=0
+ mov \$-8,%rcx
+ jmp .Lsqrx8x_reduce
+
+.align 32
+.Lsqrx8x_reduce:
+ mov %r8, %rbx
+ mulx 16*0($nptr),%rax,%r8 # n[0]
+ adcx %rbx,%rax # discarded
+ adox %r9,%r8
+
+ mulx 16*1($nptr),%rbx,%r9 # n[1]
+ adcx %rbx,%r8
+ adox %r10,%r9
+
+ mulx 16*2($nptr),%rbx,%r10
+ adcx %rbx,%r9
+ adox %r11,%r10
+
+ mulx 16*3($nptr),%rbx,%r11
+ adcx %rbx,%r10
+ adox %r12,%r11
+
+ .byte 0xc4,0x62,0xe3,0xf6,0xa5,0x40,0x00,0x00,0x00 # mulx 16*4($nptr),%rbx,%r12
+ mov %rdx,%rax
+ mov %r8,%rdx
+ adcx %rbx,%r11
+ adox %r13,%r12
+
+ mulx 32+8(%rsp),%rbx,%rdx # %rdx discarded
+ mov %rax,%rdx
+ mov %rax,64+48+8(%rsp,%rcx,8) # put aside n0*a[i]
+
+ mulx 16*5($nptr),%rax,%r13
+ adcx %rax,%r12
+ adox %r14,%r13
+
+ mulx 16*6($nptr),%rax,%r14
+ adcx %rax,%r13
+ adox %r15,%r14
+
+ mulx 16*7($nptr),%rax,%r15
+ mov %rbx,%rdx
+ adcx %rax,%r14
+ adox $carry,%r15 # $carry is 0
+ adcx $carry,%r15 # cf=0
+
+ .byte 0x67,0x67,0x67
+ inc %rcx # of=0
+ jnz .Lsqrx8x_reduce
+
+ mov $carry,%rax # xor %rax,%rax
+ cmp 0+8(%rsp),$nptr # end of n[]?
+ jae .Lsqrx8x_no_tail
+
+ mov 48+8(%rsp),%rdx # pull n0*a[0]
+ add 8*0($tptr),%r8
+ lea 16*8($nptr),$nptr
+ mov \$-8,%rcx
+ adcx 8*1($tptr),%r9
+ adcx 8*2($tptr),%r10
+ adc 8*3($tptr),%r11
+ adc 8*4($tptr),%r12
+ adc 8*5($tptr),%r13
+ adc 8*6($tptr),%r14
+ adc 8*7($tptr),%r15
+ lea 8*8($tptr),$tptr
+ sbb %rax,%rax # top carry
+
+ xor $carry,$carry # of=0, cf=0
+ mov %rax,16+8(%rsp)
+ jmp .Lsqrx8x_tail
+
+.align 32
+.Lsqrx8x_tail:
+ mov %r8,%rbx
+ mulx 16*0($nptr),%rax,%r8
+ adcx %rax,%rbx
+ adox %r9,%r8
+
+ mulx 16*1($nptr),%rax,%r9
+ adcx %rax,%r8
+ adox %r10,%r9
+
+ mulx 16*2($nptr),%rax,%r10
+ adcx %rax,%r9
+ adox %r11,%r10
+
+ mulx 16*3($nptr),%rax,%r11
+ adcx %rax,%r10
+ adox %r12,%r11
+
+ .byte 0xc4,0x62,0xfb,0xf6,0xa5,0x40,0x00,0x00,0x00 # mulx 16*4($nptr),%rax,%r12
+ adcx %rax,%r11
+ adox %r13,%r12
+
+ mulx 16*5($nptr),%rax,%r13
+ adcx %rax,%r12
+ adox %r14,%r13
+
+ mulx 16*6($nptr),%rax,%r14
+ adcx %rax,%r13
+ adox %r15,%r14
+
+ mulx 16*7($nptr),%rax,%r15
+ mov 72+48+8(%rsp,%rcx,8),%rdx # pull n0*a[i]
+ adcx %rax,%r14
+ adox $carry,%r15
+ mov %rbx,($tptr,%rcx,8) # save result
+ mov %r8,%rbx
+ adcx $carry,%r15 # cf=0
+
+ inc %rcx # of=0
+ jnz .Lsqrx8x_tail
+
+ cmp 0+8(%rsp),$nptr # end of n[]?
+ jae .Lsqrx8x_tail_done # break out of loop
+
+ sub 16+8(%rsp),$carry # mov 16(%rsp),%cf
+ mov 48+8(%rsp),%rdx # pull n0*a[0]
+ lea 16*8($nptr),$nptr
+ adc 8*0($tptr),%r8
+ adc 8*1($tptr),%r9
+ adc 8*2($tptr),%r10
+ adc 8*3($tptr),%r11
+ adc 8*4($tptr),%r12
+ adc 8*5($tptr),%r13
+ adc 8*6($tptr),%r14
+ adc 8*7($tptr),%r15
+ lea 8*8($tptr),$tptr
+ sbb %rax,%rax
+ sub \$8,%rcx # mov \$-8,%rcx
+
+ xor $carry,$carry # of=0, cf=0
+ mov %rax,16+8(%rsp)
+ jmp .Lsqrx8x_tail
+
+.align 32
+.Lsqrx8x_tail_done:
+ add 24+8(%rsp),%r8 # can this overflow?
+ mov $carry,%rax # xor %rax,%rax
+
+ sub 16+8(%rsp),$carry # mov 16(%rsp),%cf
+.Lsqrx8x_no_tail: # %cf is 0 if jumped here
+ adc 8*0($tptr),%r8
+ movq %xmm3,%rcx
+ adc 8*1($tptr),%r9
+ mov 16*7($nptr),$carry
+ movq %xmm2,$nptr # restore $nptr
+ adc 8*2($tptr),%r10
+ adc 8*3($tptr),%r11
+ adc 8*4($tptr),%r12
+ adc 8*5($tptr),%r13
+ adc 8*6($tptr),%r14
+ adc 8*7($tptr),%r15
+ adc %rax,%rax # top-most carry
+
+ mov 32+8(%rsp),%rbx # n0
+ mov 8*8($tptr,%rcx),%rdx # modulo-scheduled "%r8"
+
+ mov %r8,8*0($tptr) # store top 512 bits
+ lea 8*8($tptr),%r8 # borrow %r8
+ mov %r9,8*1($tptr)
+ mov %r10,8*2($tptr)
+ mov %r11,8*3($tptr)
+ mov %r12,8*4($tptr)
+ mov %r13,8*5($tptr)
+ mov %r14,8*6($tptr)
+ mov %r15,8*7($tptr)
+
+ lea 8*8($tptr,%rcx),$tptr # start of current t[] window
+ cmp 8+8(%rsp),%r8 # end of t[]?
+ jb .Lsqrx8x_reduction_loop
+___
+}
+##############################################################
+# Post-condition, 4x unrolled
+#
+{
+my ($rptr,$nptr)=("%rdx","%rbp");
+my @ri=map("%r$_",(10..13));
+my @ni=map("%r$_",(14..15));
+$code.=<<___;
+ xor %rbx,%rbx
+ sub %r15,%rsi # compare top-most words
+ adc %rbx,%rbx
+ mov %rcx,%r10 # -$num
+ .byte 0x67
+ or %rbx,%rax
+ .byte 0x67
+ mov %rcx,%r9 # -$num
+ xor \$1,%rax
+ sar \$3+2,%rcx # cf=0
+ #lea 48+8(%rsp,%r9),$tptr
+ lea ($nptr,%rax,8),$nptr
+ movq %xmm1,$rptr # restore $rptr
+ movq %xmm1,$aptr # prepare for back-to-back call
+ jmp .Lsqrx4x_sub
+
+.align 32
+.Lsqrx4x_sub:
+ .byte 0x66
+ mov 8*0($tptr),%r12
+ mov 8*1($tptr),%r13
+ sbb 16*0($nptr),%r12
+ mov 8*2($tptr),%r14
+ sbb 16*1($nptr),%r13
+ mov 8*3($tptr),%r15
+ lea 8*4($tptr),$tptr
+ sbb 16*2($nptr),%r14
+ mov %r12,8*0($rptr)
+ sbb 16*3($nptr),%r15
+ lea 16*4($nptr),$nptr
+ mov %r13,8*1($rptr)
+ mov %r14,8*2($rptr)
+ mov %r15,8*3($rptr)
+ lea 8*4($rptr),$rptr
+
+ inc %rcx
+ jnz .Lsqrx4x_sub
+___
+}
+$code.=<<___;
+ neg %r9 # restore $num
+
+ ret
+.size bn_sqrx8x_internal,.-bn_sqrx8x_internal
+___
+}}}
+{
+my ($inp,$num,$tbl,$idx)=$win64?("%rcx","%edx","%r8", "%r9d") : # Win64 order
+ ("%rdi","%esi","%rdx","%ecx"); # Unix order
+my $out=$inp;
+my $STRIDE=2**5*8;
+my $N=$STRIDE/4;
+
+$code.=<<___;
+.globl bn_scatter5
+.type bn_scatter5,\@abi-omnipotent
+.align 16
+bn_scatter5:
+ cmp \$0, $num
+ jz .Lscatter_epilogue
+ lea ($tbl,$idx,8),$tbl
+.Lscatter:
+ mov ($inp),%rax
+ lea 8($inp),$inp
+ mov %rax,($tbl)
+ lea 32*8($tbl),$tbl
+ sub \$1,$num
+ jnz .Lscatter
+.Lscatter_epilogue:
+ ret
+.size bn_scatter5,.-bn_scatter5
+
+.globl bn_gather5
+.type bn_gather5,\@abi-omnipotent
+.align 16
+bn_gather5:
+___
+$code.=<<___ if ($win64);
+.LSEH_begin_bn_gather5:
+ # I can't trust assembler to use specific encoding:-(
+ .byte 0x48,0x83,0xec,0x28 #sub \$0x28,%rsp
+ .byte 0x0f,0x29,0x34,0x24 #movaps %xmm6,(%rsp)
+ .byte 0x0f,0x29,0x7c,0x24,0x10 #movdqa %xmm7,0x10(%rsp)
+___
+$code.=<<___;
+ mov $idx,%r11d
+ shr \$`log($N/8)/log(2)`,$idx
+ and \$`$N/8-1`,%r11
+ not $idx
+ lea .Lmagic_masks(%rip),%rax
+ and \$`2**5/($N/8)-1`,$idx # 5 is "window size"
+ lea 128($tbl,%r11,8),$tbl # pointer within 1st cache line
+ movq 0(%rax,$idx,8),%xmm4 # set of masks denoting which
+ movq 8(%rax,$idx,8),%xmm5 # cache line contains element
+ movq 16(%rax,$idx,8),%xmm6 # denoted by 7th argument
+ movq 24(%rax,$idx,8),%xmm7
+ jmp .Lgather
+.align 16
+.Lgather:
+ movq `0*$STRIDE/4-128`($tbl),%xmm0
+ movq `1*$STRIDE/4-128`($tbl),%xmm1
+ pand %xmm4,%xmm0
+ movq `2*$STRIDE/4-128`($tbl),%xmm2
+ pand %xmm5,%xmm1
+ movq `3*$STRIDE/4-128`($tbl),%xmm3
+ pand %xmm6,%xmm2
+ por %xmm1,%xmm0
+ pand %xmm7,%xmm3
+ .byte 0x67,0x67
+ por %xmm2,%xmm0
+ lea $STRIDE($tbl),$tbl
+ por %xmm3,%xmm0
+
+ movq %xmm0,($out) # m0=bp[0]
+ lea 8($out),$out
+ sub \$1,$num
+ jnz .Lgather
+___
+$code.=<<___ if ($win64);
+ movaps (%rsp),%xmm6
+ movaps 0x10(%rsp),%xmm7
+ lea 0x28(%rsp),%rsp
+___
+$code.=<<___;
+ ret
+.LSEH_end_bn_gather5:
+.size bn_gather5,.-bn_gather5
+___
+}
+$code.=<<___;
+.align 64
+.Lmagic_masks:
+ .long 0,0, 0,0, 0,0, -1,-1
+ .long 0,0, 0,0, 0,0, 0,0
+.asciz "Montgomery Multiplication with scatter/gather for x86_64, CRYPTOGAMS by <appro\@openssl.org>"
+___
+
+# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame,
+# CONTEXT *context,DISPATCHER_CONTEXT *disp)
+if ($win64) {
+$rec="%rcx";
+$frame="%rdx";
+$context="%r8";
+$disp="%r9";
+
+$code.=<<___;
+.extern __imp_RtlVirtualUnwind
+.type mul_handler,\@abi-omnipotent
+.align 16
+mul_handler:
+ push %rsi
+ push %rdi
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+ pushfq
+ sub \$64,%rsp
+
+ mov 120($context),%rax # pull context->Rax
+ mov 248($context),%rbx # pull context->Rip
+
+ mov 8($disp),%rsi # disp->ImageBase
+ mov 56($disp),%r11 # disp->HandlerData
+
+ mov 0(%r11),%r10d # HandlerData[0]
+ lea (%rsi,%r10),%r10 # end of prologue label
+ cmp %r10,%rbx # context->Rip<end of prologue label
+ jb .Lcommon_seh_tail
+
+ mov 152($context),%rax # pull context->Rsp
+
+ mov 4(%r11),%r10d # HandlerData[1]
+ lea (%rsi,%r10),%r10 # epilogue label
+ cmp %r10,%rbx # context->Rip>=epilogue label
+ jae .Lcommon_seh_tail
+
+ lea .Lmul_epilogue(%rip),%r10
+ cmp %r10,%rbx
+ jb .Lbody_40
+
+ mov 192($context),%r10 # pull $num
+ mov 8(%rax,%r10,8),%rax # pull saved stack pointer
+ jmp .Lbody_proceed
+
+.Lbody_40:
+ mov 40(%rax),%rax # pull saved stack pointer
+.Lbody_proceed:
+
+ movaps -88(%rax),%xmm0
+ movaps -72(%rax),%xmm1
+
+ mov -8(%rax),%rbx
+ mov -16(%rax),%rbp
+ mov -24(%rax),%r12
+ mov -32(%rax),%r13
+ mov -40(%rax),%r14
+ mov -48(%rax),%r15
+ mov %rbx,144($context) # restore context->Rbx
+ mov %rbp,160($context) # restore context->Rbp
+ mov %r12,216($context) # restore context->R12
+ mov %r13,224($context) # restore context->R13
+ mov %r14,232($context) # restore context->R14
+ mov %r15,240($context) # restore context->R15
+ movups %xmm0,512($context) # restore context->Xmm6
+ movups %xmm1,528($context) # restore context->Xmm7
+
+.Lcommon_seh_tail:
+ mov 8(%rax),%rdi
+ mov 16(%rax),%rsi
+ mov %rax,152($context) # restore context->Rsp
+ mov %rsi,168($context) # restore context->Rsi
+ mov %rdi,176($context) # restore context->Rdi
+
+ mov 40($disp),%rdi # disp->ContextRecord
+ mov $context,%rsi # context
+ mov \$154,%ecx # sizeof(CONTEXT)
+ .long 0xa548f3fc # cld; rep movsq
+
+ mov $disp,%rsi
+ xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER
+ mov 8(%rsi),%rdx # arg2, disp->ImageBase
+ mov 0(%rsi),%r8 # arg3, disp->ControlPc
+ mov 16(%rsi),%r9 # arg4, disp->FunctionEntry
+ mov 40(%rsi),%r10 # disp->ContextRecord
+ lea 56(%rsi),%r11 # &disp->HandlerData
+ lea 24(%rsi),%r12 # &disp->EstablisherFrame
+ mov %r10,32(%rsp) # arg5
+ mov %r11,40(%rsp) # arg6
+ mov %r12,48(%rsp) # arg7
+ mov %rcx,56(%rsp) # arg8, (NULL)
+ call *__imp_RtlVirtualUnwind(%rip)
+
+ mov \$1,%eax # ExceptionContinueSearch
+ add \$64,%rsp
+ popfq
+ pop %r15
+ pop %r14
+ pop %r13
+ pop %r12
+ pop %rbp
+ pop %rbx
+ pop %rdi
+ pop %rsi
+ ret
+.size mul_handler,.-mul_handler
+
+.section .pdata
+.align 4
+ .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_power5
+ .rva .LSEH_end_bn_power5
+ .rva .LSEH_info_bn_power5
+
+ .rva .LSEH_begin_bn_from_mont8x
+ .rva .LSEH_end_bn_from_mont8x
+ .rva .LSEH_info_bn_from_mont8x
+___
+$code.=<<___ if ($addx);
+ .rva .LSEH_begin_bn_mulx4x_mont_gather5
+ .rva .LSEH_end_bn_mulx4x_mont_gather5
+ .rva .LSEH_info_bn_mulx4x_mont_gather5
+
+ .rva .LSEH_begin_bn_powerx5
+ .rva .LSEH_end_bn_powerx5
+ .rva .LSEH_info_bn_powerx5
+___
+$code.=<<___;
+ .rva .LSEH_begin_bn_gather5
+ .rva .LSEH_end_bn_gather5
+ .rva .LSEH_info_bn_gather5
+
+.section .xdata
+.align 8
+.LSEH_info_bn_mul_mont_gather5:
+ .byte 9,0,0,0
+ .rva mul_handler
+ .rva .Lmul_body,.Lmul_epilogue # HandlerData[]
+.align 8
+.LSEH_info_bn_mul4x_mont_gather5:
+ .byte 9,0,0,0
+ .rva mul_handler
+ .rva .Lmul4x_body,.Lmul4x_epilogue # HandlerData[]
+.align 8
+.LSEH_info_bn_power5:
+ .byte 9,0,0,0
+ .rva mul_handler
+ .rva .Lpower5_body,.Lpower5_epilogue # HandlerData[]
+.align 8
+.LSEH_info_bn_from_mont8x:
+ .byte 9,0,0,0
+ .rva mul_handler
+ .rva .Lfrom_body,.Lfrom_epilogue # HandlerData[]
+___
+$code.=<<___ if ($addx);
+.align 8
+.LSEH_info_bn_mulx4x_mont_gather5:
+ .byte 9,0,0,0
+ .rva mul_handler
+ .rva .Lmulx4x_body,.Lmulx4x_epilogue # HandlerData[]
+.align 8
+.LSEH_info_bn_powerx5:
+ .byte 9,0,0,0
+ .rva mul_handler
+ .rva .Lpowerx5_body,.Lpowerx5_epilogue # HandlerData[]
+___
+$code.=<<___;
+.align 8
+.LSEH_info_bn_gather5:
+ .byte 0x01,0x0d,0x05,0x00
+ .byte 0x0d,0x78,0x01,0x00 #movaps 0x10(rsp),xmm7
+ .byte 0x08,0x68,0x00,0x00 #movaps (rsp),xmm6
+ .byte 0x04,0x42,0x00,0x00 #sub rsp,0x28
+.align 8
+___
+}
+
+$code =~ s/\`([^\`]*)\`/eval($1)/gem;
+
+print $code;
+close STDOUT;
diff --git a/src/crypto/bn/bn.c b/src/crypto/bn/bn.c
new file mode 100644
index 0000000..368c4f1
--- /dev/null
+++ b/src/crypto/bn/bn.c
@@ -0,0 +1,338 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/bn.h>
+
+#include <limits.h>
+#include <string.h>
+
+#include <openssl/err.h>
+#include <openssl/mem.h>
+
+#include "internal.h"
+
+
+BIGNUM *BN_new(void) {
+ BIGNUM *bn = OPENSSL_malloc(sizeof(BIGNUM));
+
+ if (bn == NULL) {
+ OPENSSL_PUT_ERROR(BN, BN_new, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ memset(bn, 0, sizeof(BIGNUM));
+ bn->flags = BN_FLG_MALLOCED;
+
+ return bn;
+}
+
+void BN_init(BIGNUM *bn) {
+ memset(bn, 0, sizeof(BIGNUM));
+}
+
+void BN_free(BIGNUM *bn) {
+ if (bn == NULL) {
+ return;
+ }
+
+ if (bn->d != NULL && (bn->flags & BN_FLG_STATIC_DATA) == 0) {
+ OPENSSL_free(bn->d);
+ }
+
+ if (bn->flags & BN_FLG_MALLOCED) {
+ OPENSSL_free(bn);
+ } else {
+ bn->d = NULL;
+ }
+}
+
+void BN_clear_free(BIGNUM *bn) {
+ char should_free;
+
+ if (bn == NULL) {
+ return;
+ }
+
+ if (bn->d != NULL) {
+ OPENSSL_cleanse(bn->d, bn->dmax * sizeof(bn->d[0]));
+ if ((bn->flags & BN_FLG_STATIC_DATA) == 0) {
+ OPENSSL_free(bn->d);
+ }
+ }
+
+ should_free = (bn->flags & BN_FLG_MALLOCED) != 0;
+ OPENSSL_cleanse(bn, sizeof(BIGNUM));
+ if (should_free) {
+ OPENSSL_free(bn);
+ }
+}
+
+BIGNUM *BN_dup(const BIGNUM *src) {
+ BIGNUM *copy;
+
+ if (src == NULL) {
+ return NULL;
+ }
+
+ copy = BN_new();
+ if (copy == NULL) {
+ return NULL;
+ }
+
+ if (!BN_copy(copy, src)) {
+ BN_free(copy);
+ return NULL;
+ }
+
+ return copy;
+}
+
+BIGNUM *BN_copy(BIGNUM *dest, const BIGNUM *src) {
+ if (src == dest) {
+ return dest;
+ }
+
+ if (bn_wexpand(dest, src->top) == NULL) {
+ return NULL;
+ }
+
+ memcpy(dest->d, src->d, sizeof(src->d[0]) * src->top);
+
+ dest->top = src->top;
+ dest->neg = src->neg;
+ return dest;
+}
+
+void BN_clear(BIGNUM *bn) {
+ if (bn->d != NULL) {
+ memset(bn->d, 0, bn->dmax * sizeof(bn->d[0]));
+ }
+
+ bn->top = 0;
+ bn->neg = 0;
+}
+
+const BIGNUM *BN_value_one(void) {
+ static const BN_ULONG data_one = 1;
+ static const BIGNUM const_one = {(BN_ULONG *)&data_one, 1, 1, 0,
+ BN_FLG_STATIC_DATA};
+
+ return &const_one;
+}
+
+void BN_with_flags(BIGNUM *out, const BIGNUM *in, int flags) {
+ memcpy(out, in, sizeof(BIGNUM));
+ out->flags &= ~BN_FLG_MALLOCED;
+ out->flags |= BN_FLG_STATIC_DATA | flags;
+}
+
+/* BN_num_bits_word returns the minimum number of bits needed to represent the
+ * value in |l|. */
+unsigned BN_num_bits_word(BN_ULONG l) {
+ static const unsigned char bits[256] = {
+ 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8};
+
+#if defined(OPENSSL_64_BIT)
+ if (l & 0xffffffff00000000L) {
+ if (l & 0xffff000000000000L) {
+ if (l & 0xff00000000000000L) {
+ return (bits[(int)(l >> 56)] + 56);
+ } else
+ return (bits[(int)(l >> 48)] + 48);
+ } else {
+ if (l & 0x0000ff0000000000L) {
+ return (bits[(int)(l >> 40)] + 40);
+ } else
+ return (bits[(int)(l >> 32)] + 32);
+ }
+ } else
+#endif
+ {
+ if (l & 0xffff0000L) {
+ if (l & 0xff000000L) {
+ return (bits[(int)(l >> 24L)] + 24);
+ } else {
+ return (bits[(int)(l >> 16L)] + 16);
+ }
+ } else {
+ if (l & 0xff00L) {
+ return (bits[(int)(l >> 8)] + 8);
+ } else {
+ return (bits[(int)(l)]);
+ }
+ }
+ }
+}
+
+unsigned BN_num_bits(const BIGNUM *bn) {
+ const int max = bn->top - 1;
+
+ if (BN_is_zero(bn)) {
+ return 0;
+ }
+
+ return max*BN_BITS2 + BN_num_bits_word(bn->d[max]);
+}
+
+unsigned BN_num_bytes(const BIGNUM *bn) {
+ return (BN_num_bits(bn) + 7) / 8;
+}
+
+void BN_zero(BIGNUM *bn) {
+ bn->top = bn->neg = 0;
+}
+
+int BN_one(BIGNUM *bn) {
+ return BN_set_word(bn, 1);
+}
+
+int BN_set_word(BIGNUM *bn, BN_ULONG value) {
+ if (value == 0) {
+ BN_zero(bn);
+ return 1;
+ }
+
+ if (bn_wexpand(bn, 1) == NULL) {
+ return 0;
+ }
+
+ bn->neg = 0;
+ bn->d[0] = value;
+ bn->top = 1;
+ return 1;
+}
+
+int BN_is_negative(const BIGNUM *bn) {
+ return bn->neg != 0;
+}
+
+void BN_set_negative(BIGNUM *bn, int sign) {
+ if (sign && !BN_is_zero(bn)) {
+ bn->neg = 1;
+ } else {
+ bn->neg = 0;
+ }
+}
+
+BIGNUM *bn_wexpand(BIGNUM *bn, unsigned words) {
+ BN_ULONG *a;
+
+ if (words <= (unsigned) bn->dmax) {
+ return bn;
+ }
+
+ if (words > (INT_MAX / (4 * BN_BITS2))) {
+ OPENSSL_PUT_ERROR(BN, bn_wexpand, BN_R_BIGNUM_TOO_LONG);
+ return NULL;
+ }
+
+ if (bn->flags & BN_FLG_STATIC_DATA) {
+ OPENSSL_PUT_ERROR(BN, bn_wexpand, BN_R_EXPAND_ON_STATIC_BIGNUM_DATA);
+ return NULL;
+ }
+
+ a = (BN_ULONG *)OPENSSL_malloc(sizeof(BN_ULONG) * words);
+ if (a == NULL) {
+ OPENSSL_PUT_ERROR(BN, bn_wexpand, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ memcpy(a, bn->d, sizeof(BN_ULONG) * bn->top);
+
+ if (bn->d) {
+ OPENSSL_free(bn->d);
+ }
+ bn->d = a;
+ bn->dmax = words;
+
+ return bn;
+}
+
+BIGNUM *bn_expand(BIGNUM *bn, unsigned bits) {
+ return bn_wexpand(bn, (bits+BN_BITS2-1)/BN_BITS2);
+}
+
+void bn_correct_top(BIGNUM *bn) {
+ BN_ULONG *ftl;
+ int tmp_top = bn->top;
+
+ if (tmp_top > 0) {
+ for (ftl = &(bn->d[tmp_top - 1]); tmp_top > 0; tmp_top--) {
+ if (*(ftl--)) {
+ break;
+ }
+ }
+ bn->top = tmp_top;
+ }
+}
+
+int BN_get_flags(const BIGNUM *bn, int flags) {
+ return bn->flags & flags;
+}
+
+void BN_set_flags(BIGNUM *bn, int flags) {
+ bn->flags |= flags;
+}
diff --git a/src/crypto/bn/bn_error.c b/src/crypto/bn/bn_error.c
new file mode 100644
index 0000000..b522c2a
--- /dev/null
+++ b/src/crypto/bn/bn_error.c
@@ -0,0 +1,63 @@
+/* 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 <openssl/err.h>
+
+#include <openssl/bn.h>
+
+const ERR_STRING_DATA BN_error_string_data[] = {
+ {ERR_PACK(ERR_LIB_BN, BN_F_BN_CTX_get, 0), "BN_CTX_get"},
+ {ERR_PACK(ERR_LIB_BN, BN_F_BN_CTX_new, 0), "BN_CTX_new"},
+ {ERR_PACK(ERR_LIB_BN, BN_F_BN_CTX_start, 0), "BN_CTX_start"},
+ {ERR_PACK(ERR_LIB_BN, BN_F_BN_bn2dec, 0), "BN_bn2dec"},
+ {ERR_PACK(ERR_LIB_BN, BN_F_BN_bn2hex, 0), "BN_bn2hex"},
+ {ERR_PACK(ERR_LIB_BN, BN_F_BN_div, 0), "BN_div"},
+ {ERR_PACK(ERR_LIB_BN, BN_F_BN_div_recp, 0), "BN_div_recp"},
+ {ERR_PACK(ERR_LIB_BN, BN_F_BN_exp, 0), "BN_exp"},
+ {ERR_PACK(ERR_LIB_BN, BN_F_BN_generate_dsa_nonce, 0), "BN_generate_dsa_nonce"},
+ {ERR_PACK(ERR_LIB_BN, BN_F_BN_generate_prime_ex, 0), "BN_generate_prime_ex"},
+ {ERR_PACK(ERR_LIB_BN, BN_F_BN_mod_exp2_mont, 0), "BN_mod_exp2_mont"},
+ {ERR_PACK(ERR_LIB_BN, BN_F_BN_mod_exp_mont, 0), "BN_mod_exp_mont"},
+ {ERR_PACK(ERR_LIB_BN, BN_F_BN_mod_exp_mont_consttime, 0), "BN_mod_exp_mont_consttime"},
+ {ERR_PACK(ERR_LIB_BN, BN_F_BN_mod_exp_mont_word, 0), "BN_mod_exp_mont_word"},
+ {ERR_PACK(ERR_LIB_BN, BN_F_BN_mod_inverse, 0), "BN_mod_inverse"},
+ {ERR_PACK(ERR_LIB_BN, BN_F_BN_mod_inverse_no_branch, 0), "BN_mod_inverse_no_branch"},
+ {ERR_PACK(ERR_LIB_BN, BN_F_BN_mod_lshift_quick, 0), "BN_mod_lshift_quick"},
+ {ERR_PACK(ERR_LIB_BN, BN_F_BN_mod_sqrt, 0), "BN_mod_sqrt"},
+ {ERR_PACK(ERR_LIB_BN, BN_F_BN_new, 0), "BN_new"},
+ {ERR_PACK(ERR_LIB_BN, BN_F_BN_rand, 0), "BN_rand"},
+ {ERR_PACK(ERR_LIB_BN, BN_F_BN_rand_range, 0), "BN_rand_range"},
+ {ERR_PACK(ERR_LIB_BN, BN_F_BN_sqrt, 0), "BN_sqrt"},
+ {ERR_PACK(ERR_LIB_BN, BN_F_BN_usub, 0), "BN_usub"},
+ {ERR_PACK(ERR_LIB_BN, BN_F_bn_wexpand, 0), "bn_wexpand"},
+ {ERR_PACK(ERR_LIB_BN, BN_F_mod_exp_recp, 0), "mod_exp_recp"},
+ {ERR_PACK(ERR_LIB_BN, 0, BN_R_ARG2_LT_ARG3), "ARG2_LT_ARG3"},
+ {ERR_PACK(ERR_LIB_BN, 0, BN_R_BAD_RECIPROCAL), "BAD_RECIPROCAL"},
+ {ERR_PACK(ERR_LIB_BN, 0, BN_R_BIGNUM_TOO_LONG), "BIGNUM_TOO_LONG"},
+ {ERR_PACK(ERR_LIB_BN, 0, BN_R_BITS_TOO_SMALL), "BITS_TOO_SMALL"},
+ {ERR_PACK(ERR_LIB_BN, 0, BN_R_CALLED_WITH_EVEN_MODULUS), "CALLED_WITH_EVEN_MODULUS"},
+ {ERR_PACK(ERR_LIB_BN, 0, BN_R_DIV_BY_ZERO), "DIV_BY_ZERO"},
+ {ERR_PACK(ERR_LIB_BN, 0, BN_R_EXPAND_ON_STATIC_BIGNUM_DATA), "EXPAND_ON_STATIC_BIGNUM_DATA"},
+ {ERR_PACK(ERR_LIB_BN, 0, BN_R_INPUT_NOT_REDUCED), "INPUT_NOT_REDUCED"},
+ {ERR_PACK(ERR_LIB_BN, 0, BN_R_INVALID_RANGE), "INVALID_RANGE"},
+ {ERR_PACK(ERR_LIB_BN, 0, BN_R_NEGATIVE_NUMBER), "NEGATIVE_NUMBER"},
+ {ERR_PACK(ERR_LIB_BN, 0, BN_R_NOT_A_SQUARE), "NOT_A_SQUARE"},
+ {ERR_PACK(ERR_LIB_BN, 0, BN_R_NOT_INITIALIZED), "NOT_INITIALIZED"},
+ {ERR_PACK(ERR_LIB_BN, 0, BN_R_NO_INVERSE), "NO_INVERSE"},
+ {ERR_PACK(ERR_LIB_BN, 0, BN_R_PRIVATE_KEY_TOO_LARGE), "PRIVATE_KEY_TOO_LARGE"},
+ {ERR_PACK(ERR_LIB_BN, 0, BN_R_P_IS_NOT_PRIME), "P_IS_NOT_PRIME"},
+ {ERR_PACK(ERR_LIB_BN, 0, BN_R_TOO_MANY_ITERATIONS), "TOO_MANY_ITERATIONS"},
+ {ERR_PACK(ERR_LIB_BN, 0, BN_R_TOO_MANY_TEMPORARY_VARIABLES), "TOO_MANY_TEMPORARY_VARIABLES"},
+ {0, NULL},
+};
diff --git a/src/crypto/bn/bn_test.c b/src/crypto/bn/bn_test.c
new file mode 100644
index 0000000..e342ed8
--- /dev/null
+++ b/src/crypto/bn/bn_test.c
@@ -0,0 +1,1471 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <stdio.h>
+#include <string.h>
+
+#include <openssl/bio.h>
+#include <openssl/bn.h>
+#include <openssl/crypto.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+
+#include "internal.h"
+
+
+static const int num0 = 100; /* number of tests */
+static const int num1 = 50; /* additional tests for some functions */
+static const int num2 = 5; /* number of tests for slow functions */
+
+int test_add(BIO *bp);
+int test_sub(BIO *bp);
+int test_lshift1(BIO *bp);
+int test_lshift(BIO *bp, BN_CTX *ctx, BIGNUM *a_);
+int test_rshift1(BIO *bp);
+int test_rshift(BIO *bp, BN_CTX *ctx);
+int test_sqr(BIO *bp, BN_CTX *ctx);
+int test_mul(BIO *bp);
+int test_div(BIO *bp, BN_CTX *ctx);
+int rand_neg(void);
+
+int test_div_word(BIO *bp);
+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_exp(BIO *bp, BN_CTX *ctx);
+int test_mod_sqrt(BIO *bp, BN_CTX *ctx);
+static int test_exp_mod_zero(void);
+int test_small_prime(BIO *bp,BN_CTX *ctx);
+int test_mod_exp_mont5(BIO *bp, BN_CTX *ctx);
+int test_sqrt(BIO *bp, BN_CTX *ctx);
+int test_bn2bin_padded(BIO *bp, BN_CTX *ctx);
+#if 0
+int test_gf2m_add(BIO *bp);
+int test_gf2m_mod(BIO *bp);
+int test_gf2m_mod_mul(BIO *bp, BN_CTX *ctx);
+int test_gf2m_mod_sqr(BIO *bp, BN_CTX *ctx);
+int test_gf2m_mod_inv(BIO *bp, BN_CTX *ctx);
+int test_gf2m_mod_div(BIO *bp, BN_CTX *ctx);
+int test_gf2m_mod_exp(BIO *bp, BN_CTX *ctx);
+int test_gf2m_mod_sqrt(BIO *bp, BN_CTX *ctx);
+int test_gf2m_mod_solve_quad(BIO *bp, BN_CTX *ctx);
+#endif
+static int results = 0;
+
+static unsigned char lst[] =
+ "\xC6\x4F\x43\x04\x2A\xEA\xCA\x6E\x58\x36\x80\x5B\xE8\xC9"
+ "\x9B\x04\x5D\x48\x36\xC2\xFD\x16\xC9\x64\xF0";
+
+static void ERR_print_errors_fp(FILE *out) {
+}
+
+static void message(BIO *out, char *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 = NULL;
+ char *outfile = NULL;
+
+ CRYPTO_library_init();
+
+ 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++;
+ }
+
+
+ ctx = BN_CTX_new();
+ if (ctx == NULL)
+ return 1;
+
+ out = BIO_new(BIO_s_file());
+ if (out == NULL) {
+ return 1;
+ }
+
+ if (outfile == NULL) {
+ BIO_set_fp(out, stdout, BIO_NOCLOSE);
+ } else {
+ if (!BIO_write_filename(out, outfile)) {
+ perror(outfile);
+ return 1;
+ }
+ }
+
+ if (!results)
+ BIO_puts(out, "obase=16\nibase=16\n");
+
+ message(out, "BN_add");
+ if (!test_add(out))
+ goto err;
+ (void)BIO_flush(out);
+
+ message(out, "BN_sub");
+ if (!test_sub(out))
+ goto err;
+ (void)BIO_flush(out);
+
+ message(out, "BN_lshift1");
+ if (!test_lshift1(out))
+ goto err;
+ (void)BIO_flush(out);
+
+ message(out, "BN_lshift (fixed)");
+ if (!test_lshift(out, ctx, BN_bin2bn(lst, sizeof(lst) - 1, NULL)))
+ goto err;
+ (void)BIO_flush(out);
+
+ message(out, "BN_lshift");
+ if (!test_lshift(out, ctx, NULL))
+ goto err;
+ (void)BIO_flush(out);
+
+ message(out, "BN_rshift1");
+ if (!test_rshift1(out))
+ 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))
+ 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))
+ 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) ||
+ !test_mod_exp_mont5(out, ctx)) {
+ goto err;
+ }
+ (void)BIO_flush(out);
+
+ message(out, "BN_exp");
+ if (!test_exp(out, ctx) ||
+ !test_exp_mod_zero()) {
+ goto err;
+ }
+ (void)BIO_flush(out);
+
+ message(out, "BN_mod_sqrt");
+ if (!test_mod_sqrt(out, ctx))
+ goto err;
+ (void)BIO_flush(out);
+
+ message(out, "Small prime generation");
+ if (!test_small_prime(out, ctx))
+ goto err;
+ (void)BIO_flush(out);
+
+ message(out, "BN_sqrt");
+ if (!test_sqrt(out, ctx))
+ goto err;
+ (void)BIO_flush(out);
+
+ message(out, "BN_bn2bin_padded");
+ if (!test_bn2bin_padded(out, ctx))
+ goto err;
+ (void)BIO_flush(out);
+
+ BN_CTX_free(ctx);
+ BIO_free(out);
+
+ printf("PASS\n");
+ return 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);
+
+ return 1;
+}
+
+int test_add(BIO *bp) {
+ BIGNUM a, b, c;
+ int i;
+
+ BN_init(&a);
+ BN_init(&b);
+ BN_init(&c);
+
+ BN_rand(&a, 512, 0, 0);
+ for (i = 0; i < num0; i++) {
+ BN_rand(&b, 450 + i, 0, 0);
+ a.neg = rand_neg();
+ b.neg = rand_neg();
+ BN_add(&c, &a, &b);
+ if (bp != NULL) {
+ if (!results) {
+ BN_print(bp, &a);
+ BIO_puts(bp, " + ");
+ BN_print(bp, &b);
+ BIO_puts(bp, " - ");
+ }
+ BN_print(bp, &c);
+ BIO_puts(bp, "\n");
+ }
+ a.neg = !a.neg;
+ b.neg = !b.neg;
+ BN_add(&c, &c, &b);
+ BN_add(&c, &c, &a);
+ if (!BN_is_zero(&c)) {
+ fprintf(stderr, "Add test failed!\n");
+ return 0;
+ }
+ }
+ BN_free(&a);
+ BN_free(&b);
+ BN_free(&c);
+ return (1);
+}
+
+int test_sub(BIO *bp) {
+ BIGNUM a, b, c;
+ int i;
+
+ BN_init(&a);
+ BN_init(&b);
+ BN_init(&c);
+
+ for (i = 0; i < num0 + num1; i++) {
+ if (i < num1) {
+ BN_rand(&a, 512, 0, 0);
+ BN_copy(&b, &a);
+ if (BN_set_bit(&a, i) == 0)
+ return (0);
+ BN_add_word(&b, i);
+ } else {
+ BN_rand(&b, 400 + i - num1, 0, 0);
+ a.neg = rand_neg();
+ b.neg = rand_neg();
+ }
+ BN_sub(&c, &a, &b);
+ if (bp != NULL) {
+ if (!results) {
+ BN_print(bp, &a);
+ BIO_puts(bp, " - ");
+ BN_print(bp, &b);
+ BIO_puts(bp, " - ");
+ }
+ BN_print(bp, &c);
+ BIO_puts(bp, "\n");
+ }
+ BN_add(&c, &c, &b);
+ BN_sub(&c, &c, &a);
+ if (!BN_is_zero(&c)) {
+ fprintf(stderr, "Subtract test failed!\n");
+ return 0;
+ }
+ }
+ BN_free(&a);
+ BN_free(&b);
+ BN_free(&c);
+ return (1);
+}
+
+int test_div(BIO *bp, BN_CTX *ctx) {
+ BIGNUM a, b, c, d, e;
+ int i;
+
+ BN_init(&a);
+ BN_init(&b);
+ BN_init(&c);
+ BN_init(&d);
+ BN_init(&e);
+
+ for (i = 0; i < num0 + num1; i++) {
+ if (i < num1) {
+ BN_rand(&a, 400, 0, 0);
+ BN_copy(&b, &a);
+ BN_lshift(&a, &a, i);
+ BN_add_word(&a, i);
+ } else
+ BN_rand(&b, 50 + 3 * (i - num1), 0, 0);
+ a.neg = rand_neg();
+ b.neg = rand_neg();
+ BN_div(&d, &c, &a, &b, ctx);
+ if (bp != NULL) {
+ if (!results) {
+ BN_print(bp, &a);
+ BIO_puts(bp, " / ");
+ BN_print(bp, &b);
+ BIO_puts(bp, " - ");
+ }
+ BN_print(bp, &d);
+ BIO_puts(bp, "\n");
+
+ if (!results) {
+ BN_print(bp, &a);
+ BIO_puts(bp, " % ");
+ BN_print(bp, &b);
+ BIO_puts(bp, " - ");
+ }
+ BN_print(bp, &c);
+ BIO_puts(bp, "\n");
+ }
+ BN_mul(&e, &d, &b, ctx);
+ BN_add(&d, &e, &c);
+ BN_sub(&d, &d, &a);
+ if (!BN_is_zero(&d)) {
+ fprintf(stderr, "Division test failed!\n");
+ return 0;
+ }
+ }
+ BN_free(&a);
+ BN_free(&b);
+ BN_free(&c);
+ BN_free(&d);
+ BN_free(&e);
+ return (1);
+}
+
+int test_lshift1(BIO *bp) {
+ BIGNUM *a, *b, *c;
+ int i;
+
+ a = BN_new();
+ b = BN_new();
+ c = BN_new();
+
+ BN_rand(a, 200, 0, 0); /**/
+ a->neg = rand_neg();
+ for (i = 0; i < num0; i++) {
+ BN_lshift1(b, a);
+ if (bp != NULL) {
+ if (!results) {
+ BN_print(bp, a);
+ BIO_puts(bp, " * 2");
+ BIO_puts(bp, " - ");
+ }
+ BN_print(bp, b);
+ BIO_puts(bp, "\n");
+ }
+ BN_add(c, a, a);
+ BN_sub(a, b, c);
+ if (!BN_is_zero(a)) {
+ fprintf(stderr, "Left shift one test failed!\n");
+ return 0;
+ }
+
+ BN_copy(a, b);
+ }
+ BN_free(a);
+ BN_free(b);
+ BN_free(c);
+ return (1);
+}
+
+int test_rshift(BIO *bp, BN_CTX *ctx) {
+ BIGNUM *a, *b, *c, *d, *e;
+ int i;
+
+ a = BN_new();
+ b = BN_new();
+ c = BN_new();
+ d = BN_new();
+ e = BN_new();
+ BN_one(c);
+
+ BN_rand(a, 200, 0, 0); /**/
+ a->neg = rand_neg();
+ for (i = 0; i < num0; i++) {
+ BN_rshift(b, a, i + 1);
+ BN_add(c, c, c);
+ if (bp != NULL) {
+ if (!results) {
+ BN_print(bp, a);
+ BIO_puts(bp, " / ");
+ BN_print(bp, c);
+ BIO_puts(bp, " - ");
+ }
+ BN_print(bp, b);
+ BIO_puts(bp, "\n");
+ }
+ BN_div(d, e, a, c, ctx);
+ BN_sub(d, d, b);
+ if (!BN_is_zero(d)) {
+ fprintf(stderr, "Right shift test failed!\n");
+ return 0;
+ }
+ }
+ BN_free(a);
+ BN_free(b);
+ BN_free(c);
+ BN_free(d);
+ BN_free(e);
+ return (1);
+}
+
+int test_rshift1(BIO *bp) {
+ BIGNUM *a, *b, *c;
+ int i;
+
+ a = BN_new();
+ b = BN_new();
+ c = BN_new();
+
+ BN_rand(a, 200, 0, 0); /**/
+ a->neg = rand_neg();
+ for (i = 0; i < num0; i++) {
+ BN_rshift1(b, a);
+ if (bp != NULL) {
+ if (!results) {
+ BN_print(bp, a);
+ BIO_puts(bp, " / 2");
+ BIO_puts(bp, " - ");
+ }
+ BN_print(bp, b);
+ BIO_puts(bp, "\n");
+ }
+ BN_sub(c, a, b);
+ BN_sub(c, c, b);
+ if (!BN_is_zero(c) && !BN_abs_is_word(c, 1)) {
+ fprintf(stderr, "Right shift one test failed!\n");
+ return 0;
+ }
+ BN_copy(a, b);
+ }
+ BN_free(a);
+ BN_free(b);
+ BN_free(c);
+ return (1);
+}
+
+int test_lshift(BIO *bp, BN_CTX *ctx, BIGNUM *a_) {
+ BIGNUM *a, *b, *c, *d;
+ int i;
+
+ b = BN_new();
+ c = BN_new();
+ d = BN_new();
+ BN_one(c);
+
+ if (a_)
+ a = a_;
+ else {
+ a = BN_new();
+ BN_rand(a, 200, 0, 0); /**/
+ a->neg = rand_neg();
+ }
+ for (i = 0; i < num0; i++) {
+ BN_lshift(b, a, i + 1);
+ BN_add(c, c, c);
+ if (bp != NULL) {
+ if (!results) {
+ BN_print(bp, a);
+ BIO_puts(bp, " * ");
+ BN_print(bp, c);
+ BIO_puts(bp, " - ");
+ }
+ BN_print(bp, b);
+ BIO_puts(bp, "\n");
+ }
+ BN_mul(d, a, c, ctx);
+ BN_sub(d, d, b);
+ if (!BN_is_zero(d)) {
+ fprintf(stderr, "Left shift test failed!\n");
+ fprintf(stderr, "a=");
+ BN_print_fp(stderr, a);
+ fprintf(stderr, "\nb=");
+ BN_print_fp(stderr, b);
+ fprintf(stderr, "\nc=");
+ BN_print_fp(stderr, c);
+ fprintf(stderr, "\nd=");
+ BN_print_fp(stderr, d);
+ fprintf(stderr, "\n");
+ return 0;
+ }
+ }
+ BN_free(a);
+ BN_free(b);
+ BN_free(c);
+ BN_free(d);
+ return (1);
+}
+
+int test_mul(BIO *bp) {
+ BIGNUM a, b, c, d, e;
+ int i;
+ BN_CTX *ctx;
+
+ ctx = BN_CTX_new();
+ if (ctx == NULL)
+ abort();
+
+ BN_init(&a);
+ BN_init(&b);
+ BN_init(&c);
+ BN_init(&d);
+ BN_init(&e);
+
+ for (i = 0; i < num0 + num1; i++) {
+ if (i <= num1) {
+ BN_rand(&a, 100, 0, 0);
+ BN_rand(&b, 100, 0, 0);
+ } else
+ BN_rand(&b, i - num1, 0, 0);
+ a.neg = rand_neg();
+ b.neg = rand_neg();
+ BN_mul(&c, &a, &b, ctx);
+ if (bp != NULL) {
+ if (!results) {
+ BN_print(bp, &a);
+ BIO_puts(bp, " * ");
+ BN_print(bp, &b);
+ BIO_puts(bp, " - ");
+ }
+ BN_print(bp, &c);
+ BIO_puts(bp, "\n");
+ }
+ BN_div(&d, &e, &c, &a, ctx);
+ BN_sub(&d, &d, &b);
+ if (!BN_is_zero(&d) || !BN_is_zero(&e)) {
+ fprintf(stderr, "Multiplication test failed!\n");
+ return 0;
+ }
+ }
+ BN_free(&a);
+ BN_free(&b);
+ BN_free(&c);
+ BN_free(&d);
+ BN_free(&e);
+ BN_CTX_free(ctx);
+ return (1);
+}
+
+int test_sqr(BIO *bp, BN_CTX *ctx) {
+ BIGNUM *a, *c, *d, *e;
+ int i, ret = 0;
+
+ a = BN_new();
+ c = BN_new();
+ d = BN_new();
+ e = BN_new();
+ if (a == NULL || c == NULL || d == NULL || e == NULL) {
+ goto err;
+ }
+
+ for (i = 0; i < num0; i++) {
+ BN_rand(a, 40 + i * 10, 0, 0);
+ a->neg = rand_neg();
+ BN_sqr(c, a, ctx);
+ if (bp != NULL) {
+ if (!results) {
+ BN_print(bp, a);
+ BIO_puts(bp, " * ");
+ BN_print(bp, a);
+ BIO_puts(bp, " - ");
+ }
+ BN_print(bp, c);
+ BIO_puts(bp, "\n");
+ }
+ BN_div(d, e, c, a, ctx);
+ 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. */
+ BN_hex2bn(&a,
+ "80000000000000008000000000000001FFFFFFFFFFFFFFFE0000000000000000");
+ BN_sqr(c, a, ctx);
+ if (bp != NULL) {
+ if (!results) {
+ BN_print(bp, a);
+ BIO_puts(bp, " * ");
+ BN_print(bp, a);
+ BIO_puts(bp, " - ");
+ }
+ BN_print(bp, c);
+ BIO_puts(bp, "\n");
+ }
+ 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. */
+ BN_hex2bn(&a,
+ "80000000000000000000000080000001FFFFFFFE000000000000000000000000");
+ BN_sqr(c, a, ctx);
+ if (bp != NULL) {
+ if (!results) {
+ BN_print(bp, a);
+ BIO_puts(bp, " * ");
+ BN_print(bp, a);
+ BIO_puts(bp, " - ");
+ }
+ BN_print(bp, c);
+ BIO_puts(bp, "\n");
+ }
+ 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:
+ if (a != NULL) {
+ BN_free(a);
+ }
+ if (c != NULL) {
+ BN_free(c);
+ }
+ if (d != NULL) {
+ BN_free(d);
+ }
+ if (e != NULL) {
+ BN_free(e);
+ }
+ 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]);
+}
+
+static void print_word(BIO *bp, BN_ULONG w) {
+ BIO_printf(bp, BN_HEX_FMT1, w);
+}
+
+int test_div_word(BIO *bp) {
+ BIGNUM a, b;
+ BN_ULONG r, s;
+ int i;
+
+ BN_init(&a);
+ BN_init(&b);
+
+ for (i = 0; i < num0; i++) {
+ do {
+ BN_rand(&a, 512, -1, 0);
+ BN_rand(&b, BN_BITS2, -1, 0);
+ s = b.d[0];
+ } while (!s);
+
+ BN_copy(&b, &a);
+ r = BN_div_word(&b, s);
+
+ if (bp != NULL) {
+ if (!results) {
+ BN_print(bp, &a);
+ BIO_puts(bp, " / ");
+ print_word(bp, s);
+ BIO_puts(bp, " - ");
+ }
+ BN_print(bp, &b);
+ BIO_puts(bp, "\n");
+
+ if (!results) {
+ BN_print(bp, &a);
+ BIO_puts(bp, " % ");
+ print_word(bp, s);
+ BIO_puts(bp, " - ");
+ }
+ print_word(bp, r);
+ BIO_puts(bp, "\n");
+ }
+ BN_mul_word(&b, s);
+ BN_add_word(&b, r);
+ BN_sub(&b, &a, &b);
+ if (!BN_is_zero(&b)) {
+ fprintf(stderr, "Division (word) test failed!\n");
+ return 0;
+ }
+ }
+ BN_free(&a);
+ BN_free(&b);
+ return (1);
+}
+
+int test_mont(BIO *bp, BN_CTX *ctx) {
+ BIGNUM a, b, c, d, A, B;
+ BIGNUM n;
+ int i;
+ BN_MONT_CTX *mont;
+
+ BN_init(&a);
+ BN_init(&b);
+ BN_init(&c);
+ BN_init(&d);
+ BN_init(&A);
+ BN_init(&B);
+ BN_init(&n);
+
+ mont = BN_MONT_CTX_new();
+ if (mont == NULL)
+ return 0;
+
+ BN_rand(&a, 100, 0, 0); /**/
+ BN_rand(&b, 100, 0, 0); /**/
+ for (i = 0; i < num2; i++) {
+ int bits = (200 * (i + 1)) / num2;
+
+ if (bits == 0)
+ continue;
+ BN_rand(&n, bits, 0, 1);
+ BN_MONT_CTX_set(mont, &n, ctx);
+
+ BN_nnmod(&a, &a, &n, ctx);
+ BN_nnmod(&b, &b, &n, ctx);
+
+ BN_to_montgomery(&A, &a, mont, ctx);
+ BN_to_montgomery(&B, &b, mont, ctx);
+
+ BN_mod_mul_montgomery(&c, &A, &B, mont, ctx); /**/
+ BN_from_montgomery(&A, &c, mont, ctx); /**/
+ if (bp != NULL) {
+ if (!results) {
+#ifdef undef
+ fprintf(stderr, "%d * %d %% %d\n", BN_num_bits(&a), BN_num_bits(&b),
+ BN_num_bits(mont->N));
+#endif
+ BN_print(bp, &a);
+ BIO_puts(bp, " * ");
+ BN_print(bp, &b);
+ BIO_puts(bp, " % ");
+ BN_print(bp, &(mont->N));
+ BIO_puts(bp, " - ");
+ }
+ BN_print(bp, &A);
+ BIO_puts(bp, "\n");
+ }
+ BN_mod_mul(&d, &a, &b, &n, ctx);
+ BN_sub(&d, &d, &A);
+ if (!BN_is_zero(&d)) {
+ fprintf(stderr, "Montgomery multiplication test failed!\n");
+ return 0;
+ }
+ }
+ BN_MONT_CTX_free(mont);
+ BN_free(&a);
+ BN_free(&b);
+ BN_free(&c);
+ BN_free(&d);
+ BN_free(&A);
+ BN_free(&B);
+ BN_free(&n);
+ return (1);
+}
+
+int test_mod(BIO *bp, BN_CTX *ctx) {
+ BIGNUM *a, *b, *c, *d, *e;
+ int i;
+
+ a = BN_new();
+ b = BN_new();
+ c = BN_new();
+ d = BN_new();
+ e = BN_new();
+
+ BN_rand(a, 1024, 0, 0); /**/
+ for (i = 0; i < num0; i++) {
+ BN_rand(b, 450 + i * 10, 0, 0); /**/
+ a->neg = rand_neg();
+ b->neg = rand_neg();
+ BN_mod(c, a, b, ctx); /**/
+ if (bp != NULL) {
+ if (!results) {
+ BN_print(bp, a);
+ BIO_puts(bp, " % ");
+ BN_print(bp, b);
+ BIO_puts(bp, " - ");
+ }
+ BN_print(bp, c);
+ BIO_puts(bp, "\n");
+ }
+ BN_div(d, e, a, b, ctx);
+ BN_sub(e, e, c);
+ if (!BN_is_zero(e)) {
+ fprintf(stderr, "Modulo test failed!\n");
+ return 0;
+ }
+ }
+ BN_free(a);
+ BN_free(b);
+ BN_free(c);
+ BN_free(d);
+ BN_free(e);
+ return (1);
+}
+
+int test_mod_mul(BIO *bp, BN_CTX *ctx) {
+ BIGNUM *a, *b, *c, *d, *e;
+ int i, j;
+
+ a = BN_new();
+ b = BN_new();
+ c = BN_new();
+ d = BN_new();
+ e = BN_new();
+
+ for (j = 0; j < 3; j++) {
+ BN_rand(c, 1024, 0, 0); /**/
+ for (i = 0; i < num0; i++) {
+ BN_rand(a, 475 + i * 10, 0, 0); /**/
+ BN_rand(b, 425 + i * 11, 0, 0); /**/
+ a->neg = rand_neg();
+ b->neg = 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));
+ abort();
+ }
+ if (bp != NULL) {
+ if (!results) {
+ BN_print(bp, a);
+ BIO_puts(bp, " * ");
+ BN_print(bp, b);
+ BIO_puts(bp, " % ");
+ BN_print(bp, c);
+ if ((a->neg ^ b->neg) && !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, " + ");
+ BN_print(bp, c);
+ }
+ BIO_puts(bp, " - ");
+ }
+ BN_print(bp, e);
+ BIO_puts(bp, "\n");
+ }
+ BN_mul(d, a, b, ctx);
+ BN_sub(d, d, e);
+ BN_div(a, b, d, c, ctx);
+ if (!BN_is_zero(b)) {
+ fprintf(stderr, "Modulo multiply test failed!\n");
+ ERR_print_errors_fp(stderr);
+ return 0;
+ }
+ }
+ }
+ BN_free(a);
+ BN_free(b);
+ BN_free(c);
+ BN_free(d);
+ BN_free(e);
+ return (1);
+}
+
+int test_mod_exp(BIO *bp, BN_CTX *ctx) {
+ BIGNUM *a, *b, *c, *d, *e;
+ int i;
+
+ a = BN_new();
+ b = BN_new();
+ c = BN_new();
+ d = BN_new();
+ e = BN_new();
+
+ BN_rand(c, 30, 0, 1); /* must be odd for montgomery */
+ for (i = 0; i < num2; i++) {
+ BN_rand(a, 20 + i * 5, 0, 0); /**/
+ BN_rand(b, 2 + i, 0, 0); /**/
+
+ if (!BN_mod_exp(d, a, b, c, ctx))
+ return (0);
+
+ if (bp != NULL) {
+ if (!results) {
+ BN_print(bp, a);
+ BIO_puts(bp, " ^ ");
+ BN_print(bp, b);
+ BIO_puts(bp, " % ");
+ BN_print(bp, c);
+ BIO_puts(bp, " - ");
+ }
+ BN_print(bp, d);
+ BIO_puts(bp, "\n");
+ }
+ BN_exp(e, a, b, ctx);
+ BN_sub(e, e, d);
+ BN_div(a, b, e, c, ctx);
+ if (!BN_is_zero(b)) {
+ fprintf(stderr, "Modulo exponentiation test failed!\n");
+ return 0;
+ }
+ }
+ BN_free(a);
+ BN_free(b);
+ BN_free(c);
+ BN_free(d);
+ BN_free(e);
+ return (1);
+}
+
+int test_mod_exp_mont_consttime(BIO *bp, BN_CTX *ctx) {
+ BIGNUM *a, *b, *c, *d, *e;
+ int i;
+
+ a = BN_new();
+ b = BN_new();
+ c = BN_new();
+ d = BN_new();
+ e = BN_new();
+
+ BN_rand(c, 30, 0, 1); /* must be odd for montgomery */
+ for (i = 0; i < num2; i++) {
+ BN_rand(a, 20 + i * 5, 0, 0); /**/
+ BN_rand(b, 2 + i, 0, 0); /**/
+
+ if (!BN_mod_exp_mont_consttime(d, a, b, c, ctx, NULL))
+ return (00);
+
+ if (bp != NULL) {
+ if (!results) {
+ BN_print(bp, a);
+ BIO_puts(bp, " ^ ");
+ BN_print(bp, b);
+ BIO_puts(bp, " % ");
+ BN_print(bp, c);
+ BIO_puts(bp, " - ");
+ }
+ BN_print(bp, d);
+ BIO_puts(bp, "\n");
+ }
+ BN_exp(e, a, b, ctx);
+ BN_sub(e, e, d);
+ BN_div(a, b, e, c, ctx);
+ if (!BN_is_zero(b)) {
+ fprintf(stderr, "Modulo exponentiation test failed!\n");
+ return 0;
+ }
+ }
+ BN_free(a);
+ BN_free(b);
+ BN_free(c);
+ BN_free(d);
+ BN_free(e);
+ return (1);
+}
+
+/* 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;
+
+ BN_MONT_CTX *mont;
+
+ a = BN_new();
+ p = BN_new();
+ m = BN_new();
+ d = BN_new();
+ e = BN_new();
+
+ mont = BN_MONT_CTX_new();
+
+ BN_rand(m, 1024, 0, 1); /* must be odd for montgomery */
+ /* Zero exponent */
+ BN_rand(a, 1024, 0, 0);
+ BN_zero(p);
+ if (!BN_mod_exp_mont_consttime(d, a, p, m, ctx, NULL))
+ return 0;
+ if (!BN_is_one(d)) {
+ fprintf(stderr, "Modular exponentiation test failed!\n");
+ return 0;
+ }
+ /* Zero input */
+ BN_rand(p, 1024, 0, 0);
+ BN_zero(a);
+ if (!BN_mod_exp_mont_consttime(d, a, p, m, ctx, NULL))
+ return 0;
+ if (!BN_is_zero(d)) {
+ fprintf(stderr, "Modular exponentiation test failed!\n");
+ return 0;
+ }
+ /* 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.
+ */
+ BN_one(a);
+ BN_MONT_CTX_set(mont, m, ctx);
+ if (!BN_from_montgomery(e, a, mont, ctx) ||
+ !BN_mod_exp_mont_consttime(d, e, p, m, ctx, NULL) ||
+ !BN_mod_exp(a, e, p, m, ctx)) {
+ return 0;
+ }
+ if (BN_cmp(a, d) != 0) {
+ fprintf(stderr, "Modular exponentiation test failed!\n");
+ return 0;
+ }
+ /* Finally, some regular test vectors. */
+ BN_rand(e, 1024, 0, 0);
+ if (!BN_mod_exp_mont_consttime(d, e, p, m, ctx, NULL))
+ return 0;
+ if (!BN_mod_exp(a, e, p, m, ctx))
+ return 0;
+ if (BN_cmp(a, d) != 0) {
+ fprintf(stderr, "Modular exponentiation test failed!\n");
+ return 0;
+ }
+
+ BN_MONT_CTX_free(mont);
+ BN_free(a);
+ BN_free(p);
+ BN_free(m);
+ BN_free(d);
+ BN_free(e);
+ return (1);
+}
+
+int test_exp(BIO *bp, BN_CTX *ctx) {
+ BIGNUM *a, *b, *d, *e, *one;
+ int i;
+
+ a = BN_new();
+ b = BN_new();
+ d = BN_new();
+ e = BN_new();
+ one = BN_new();
+ BN_one(one);
+
+ for (i = 0; i < num2; i++) {
+ BN_rand(a, 20 + i * 5, 0, 0); /**/
+ BN_rand(b, 2 + i, 0, 0); /**/
+
+ if (BN_exp(d, a, b, ctx) <= 0)
+ return (0);
+
+ if (bp != NULL) {
+ if (!results) {
+ BN_print(bp, a);
+ BIO_puts(bp, " ^ ");
+ BN_print(bp, b);
+ BIO_puts(bp, " - ");
+ }
+ BN_print(bp, d);
+ BIO_puts(bp, "\n");
+ }
+ BN_one(e);
+ for (; !BN_is_zero(b); BN_sub(b, b, one))
+ BN_mul(e, e, a, ctx);
+ BN_sub(e, e, d);
+ if (!BN_is_zero(e)) {
+ fprintf(stderr, "Exponentiation test failed!\n");
+ return 0;
+ }
+ }
+ BN_free(a);
+ BN_free(b);
+ BN_free(d);
+ BN_free(e);
+ BN_free(one);
+ return (1);
+}
+
+/* test_exp_mod_zero tests that x**0 mod 1 == 0. */
+static int test_exp_mod_zero(void) {
+ BIGNUM a, p, m;
+ BIGNUM r;
+ BN_CTX *ctx = BN_CTX_new();
+ int ret = 0;
+
+ BN_init(&m);
+ BN_one(&m);
+
+ BN_init(&a);
+ BN_one(&a);
+
+ BN_init(&p);
+ BN_zero(&p);
+
+ BN_init(&r);
+ BN_mod_exp(&r, &a, &p, &m, ctx);
+ BN_CTX_free(ctx);
+
+ if (BN_is_zero(&r)) {
+ ret = 1;
+ } else {
+ printf("1**0 mod 1 = ");
+ BN_print_fp(stdout, &r);
+ printf(", should be 0\n");
+ }
+
+ BN_free(&r);
+ BN_free(&a);
+ BN_free(&p);
+ BN_free(&m);
+
+ 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, stdout);
+ fflush(stdout);
+ return 1;
+}
+
+int test_mod_sqrt(BIO *bp, BN_CTX *ctx) {
+ BN_GENCB cb;
+ BIGNUM *a, *p, *r;
+ int i, j;
+ int ret = 0;
+
+ a = BN_new();
+ p = BN_new();
+ r = BN_new();
+ if (a == NULL || p == NULL || r == 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', stdout);
+ }
+ p->neg = 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_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_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 = ");
+ BN_print_fp(stderr, a);
+ fprintf(stderr, ", r = ");
+ BN_print_fp(stderr, r);
+ fprintf(stderr, ", p = ");
+ BN_print_fp(stderr, p);
+ fprintf(stderr, "\n");
+ goto err;
+ }
+
+ putc('.', stdout);
+ fflush(stdout);
+ }
+
+ putc('\n', stdout);
+ fflush(stderr);
+ }
+ ret = 1;
+err:
+ if (a != NULL)
+ BN_free(a);
+ if (p != NULL)
+ BN_free(p);
+ if (r != NULL)
+ BN_free(r);
+ return ret;
+}
+
+int test_small_prime(BIO *bp, BN_CTX *ctx) {
+ static const int bits = 10;
+ int ret = 0;
+ BIGNUM r;
+
+ BN_init(&r);
+ if (!BN_generate_prime_ex(&r, bits, 0, NULL, NULL, NULL)) {
+ goto err;
+ }
+ if (BN_num_bits(&r) != bits) {
+ BIO_printf(bp, "Expected %d bit prime, got %d bit number\n", bits,
+ BN_num_bits(&r));
+ goto err;
+ }
+
+ ret = 1;
+
+err:
+ BN_free(&r);
+ return ret;
+}
+
+int test_sqrt(BIO *bp, BN_CTX *ctx) {
+ BIGNUM *n = BN_new(), *nn = BN_new(), *sqrt = BN_new();
+ unsigned i;
+
+ /* Test some random squares. */
+ for (i = 0; i < 100; i++) {
+ if (!BN_rand(n, 1024 /* bit length */, -1 /* no modification of top bits */,
+ 0 /* don't modify bottom bit */) ||
+ !BN_mul(nn, n, n, ctx) ||
+ !BN_sqrt(sqrt, nn, ctx)) {
+ BIO_print_errors_fp(stderr);
+ return 0;
+ }
+ if (BN_cmp(n, sqrt) != 0) {
+ fprintf(stderr, "Bad result from BN_sqrt.\n");
+ return 0;
+ }
+ }
+
+ /* Test some non-squares */
+ for (i = 0; i < 100; i++) {
+ if (!BN_rand(n, 1024 /* bit length */, -1 /* no modification of top bits */,
+ 0 /* don't modify bottom bit */) ||
+ !BN_mul(nn, n, n, ctx) ||
+ !BN_add(nn, nn, BN_value_one())) {
+ BIO_print_errors_fp(stderr);
+ return 0;
+ }
+
+ if (BN_sqrt(sqrt, nn, ctx)) {
+ char *nn_str = BN_bn2dec(nn);
+ fprintf(stderr, "BIO_sqrt didn't fail on a non-square: %s\n", nn_str);
+ OPENSSL_free(nn_str);
+ }
+ }
+
+ BN_free(n);
+ BN_free(sqrt);
+ BN_free(nn);
+
+ return 1;
+}
+
+int test_bn2bin_padded(BIO *bp, BN_CTX *ctx) {
+ BIGNUM *n = BN_new();
+ uint8_t zeros[256], out[256], reference[128];
+ size_t bytes;
+
+ memset(zeros, 0, sizeof(zeros));
+
+ /* Test edge case at 0. */
+ if (!BN_bn2bin_padded(NULL, 0, n)) {
+ fprintf(stderr,
+ "BN_bn2bin_padded failed to encode 0 in an empty buffer.\n");
+ return 0;
+ }
+ memset(out, -1, sizeof(out));
+ if (!BN_bn2bin_padded(out, sizeof(out), n)) {
+ fprintf(stderr,
+ "BN_bn2bin_padded failed to encode 0 in a non-empty buffer.\n");
+ return 0;
+ }
+ if (memcmp(zeros, out, sizeof(out))) {
+ fprintf(stderr, "BN_bn2bin_padded did not zero buffer.\n");
+ return 0;
+ }
+
+ /* Test a random numbers at various byte lengths. */
+ for (bytes = 128 - 7; bytes <= 128; bytes++) {
+ if (!BN_rand(n, bytes * 8, 0 /* make sure top bit is 1 */,
+ 0 /* don't modify bottom bit */)) {
+ BIO_print_errors_fp(stderr);
+ return 0;
+ }
+ if (BN_num_bytes(n) != bytes || BN_bn2bin(n, reference) != bytes) {
+ fprintf(stderr, "Bad result from BN_rand; bytes.\n");
+ return 0;
+ }
+ /* Empty buffer should fail. */
+ if (BN_bn2bin_padded(NULL, 0, n)) {
+ fprintf(stderr,
+ "BN_bn2bin_padded incorrectly succeeded on empty buffer.\n");
+ return 0;
+ }
+ /* One byte short should fail. */
+ if (BN_bn2bin_padded(out, bytes - 1, n)) {
+ fprintf(stderr, "BN_bn2bin_padded incorrectly succeeded on short.\n");
+ return 0;
+ }
+ /* Exactly right size should encode. */
+ if (!BN_bn2bin_padded(out, bytes, n) ||
+ memcmp(out, reference, bytes) != 0) {
+ fprintf(stderr, "BN_bn2bin_padded gave a bad result.\n");
+ return 0;
+ }
+ /* Pad up one byte extra. */
+ if (!BN_bn2bin_padded(out, bytes + 1, n) ||
+ memcmp(out + 1, reference, bytes) || memcmp(out, zeros, 1)) {
+ fprintf(stderr, "BN_bn2bin_padded gave a bad result.\n");
+ return 0;
+ }
+ /* Pad up to 256. */
+ if (!BN_bn2bin_padded(out, sizeof(out), n) ||
+ memcmp(out + sizeof(out) - bytes, reference, bytes) ||
+ memcmp(out, zeros, sizeof(out) - bytes)) {
+ fprintf(stderr, "BN_bn2bin_padded gave a bad result.\n");
+ return 0;
+ }
+ }
+
+ BN_free(n);
+
+ return 1;
+}
diff --git a/src/crypto/bn/cmp.c b/src/crypto/bn/cmp.c
new file mode 100644
index 0000000..fce7233
--- /dev/null
+++ b/src/crypto/bn/cmp.c
@@ -0,0 +1,200 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/bn.h>
+
+#include "internal.h"
+
+
+int BN_ucmp(const BIGNUM *a, const BIGNUM *b) {
+ int i;
+ BN_ULONG t1, t2, *ap, *bp;
+
+ i = a->top - b->top;
+ if (i != 0) {
+ return i;
+ }
+
+ ap = a->d;
+ bp = b->d;
+ for (i = a->top - 1; i >= 0; i--) {
+ t1 = ap[i];
+ t2 = bp[i];
+ if (t1 != t2) {
+ return (t1 > t2) ? 1 : -1;
+ }
+ }
+
+ return 0;
+}
+
+int BN_cmp(const BIGNUM *a, const BIGNUM *b) {
+ int i;
+ int gt, lt;
+ BN_ULONG t1, t2;
+
+ if ((a == NULL) || (b == NULL)) {
+ if (a != NULL) {
+ return -1;
+ } else if (b != NULL) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+
+ if (a->neg != b->neg) {
+ if (a->neg) {
+ return -1;
+ }
+ return 1;
+ }
+ if (a->neg == 0) {
+ gt = 1;
+ lt = -1;
+ } else {
+ gt = -1;
+ lt = 1;
+ }
+
+ if (a->top > b->top) {
+ return gt;
+ }
+ if (a->top < b->top) {
+ return lt;
+ }
+
+ for (i = a->top - 1; i >= 0; i--) {
+ t1 = a->d[i];
+ t2 = b->d[i];
+ if (t1 > t2) {
+ return gt;
+ } if (t1 < t2) {
+ return lt;
+ }
+ }
+
+ return 0;
+}
+
+int bn_cmp_words(const BN_ULONG *a, const BN_ULONG *b, int n) {
+ int i;
+ BN_ULONG aa, bb;
+
+ aa = a[n - 1];
+ bb = b[n - 1];
+ if (aa != bb) {
+ return (aa > bb) ? 1 : -1;
+ }
+
+ for (i = n - 2; i >= 0; i--) {
+ aa = a[i];
+ bb = b[i];
+ if (aa != bb) {
+ return (aa > bb) ? 1 : -1;
+ }
+ }
+ return 0;
+}
+
+int bn_cmp_part_words(const BN_ULONG *a, const BN_ULONG *b, int cl, int dl) {
+ int n, i;
+ n = cl - 1;
+
+ if (dl < 0) {
+ for (i = dl; i < 0; i++) {
+ if (b[n - i] != 0) {
+ return -1; /* a < b */
+ }
+ }
+ }
+ if (dl > 0) {
+ for (i = dl; i > 0; i--) {
+ if (a[n + i] != 0) {
+ return 1; /* a > b */
+ }
+ }
+ }
+
+ return bn_cmp_words(a, b, cl);
+}
+
+int BN_abs_is_word(const BIGNUM *bn, BN_ULONG w) {
+ switch (bn->top) {
+ case 1:
+ return bn->d[0] == w;
+ case 0:
+ return w == 0;
+ default:
+ return 0;
+ }
+}
+
+int BN_is_zero(const BIGNUM *bn) {
+ return bn->top == 0;
+}
+
+int BN_is_one(const BIGNUM *bn) {
+ return bn->neg == 0 && BN_abs_is_word(bn, 1);
+}
+
+int BN_is_word(const BIGNUM *bn, BN_ULONG w) {
+ return BN_abs_is_word(bn, w) && (w == 0 || bn->neg == 0);
+}
+
+int BN_is_odd(const BIGNUM *bn) {
+ return bn->top > 0 && (bn->d[0] & 1) == 1;
+}
diff --git a/src/crypto/bn/convert.c b/src/crypto/bn/convert.c
new file mode 100644
index 0000000..f764eed
--- /dev/null
+++ b/src/crypto/bn/convert.c
@@ -0,0 +1,504 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/bn.h>
+
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <openssl/bio.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+
+#include "internal.h"
+
+BIGNUM *BN_bin2bn(const uint8_t *in, size_t len, BIGNUM *ret) {
+ unsigned num_words, m;
+ BN_ULONG word = 0;
+ BIGNUM *bn = NULL;
+
+ if (ret == NULL) {
+ ret = bn = BN_new();
+ }
+
+ if (ret == NULL) {
+ return NULL;
+ }
+
+ if (len == 0) {
+ ret->top = 0;
+ return ret;
+ }
+
+ num_words = ((len - 1) / BN_BYTES) + 1;
+ m = (len - 1) % BN_BYTES;
+ if (bn_wexpand(ret, num_words) == NULL) {
+ if (bn) {
+ BN_free(bn);
+ }
+ return NULL;
+ }
+
+ ret->top = num_words;
+ ret->neg = 0;
+
+ while (len--) {
+ word = (word << 8) | *(in++);
+ if (m-- == 0) {
+ ret->d[--num_words] = word;
+ word = 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;
+}
+
+size_t BN_bn2bin(const BIGNUM *in, uint8_t *out) {
+ size_t n, i;
+ BN_ULONG l;
+
+ n = i = BN_num_bytes(in);
+ while (i--) {
+ l = in->d[i / BN_BYTES];
+ *(out++) = (unsigned char)(l >> (8 * (i % BN_BYTES))) & 0xff;
+ }
+ return n;
+}
+
+/* constant_time_select_ulong returns |x| if |v| is 1 and |y| if |v| is 0. Its
+ * behavior is undefined if |v| takes any other value. */
+static BN_ULONG constant_time_select_ulong(int v, BN_ULONG x, BN_ULONG y) {
+ BN_ULONG mask = v;
+ mask--;
+
+ return (~mask & x) | (mask & y);
+}
+
+/* constant_time_le_size_t returns 1 if |x| <= |y| and 0 otherwise. |x| and |y|
+ * must not have their MSBs set. */
+static int constant_time_le_size_t(size_t x, size_t y) {
+ return ((x - y - 1) >> (sizeof(size_t) * 8 - 1)) & 1;
+}
+
+/* read_word_padded returns the |i|'th word of |in|, if it is not out of
+ * bounds. Otherwise, it returns 0. It does so without branches on the size of
+ * |in|, however it necessarily does not have the same memory access pattern. If
+ * the access would be out of bounds, it reads the last word of |in|. |in| must
+ * not be zero. */
+static BN_ULONG read_word_padded(const BIGNUM *in, size_t i) {
+ /* Read |in->d[i]| if valid. Otherwise, read the last word. */
+ BN_ULONG l = in->d[constant_time_select_ulong(
+ constant_time_le_size_t(in->dmax, i), in->dmax - 1, i)];
+
+ /* Clamp to zero if above |d->top|. */
+ return constant_time_select_ulong(constant_time_le_size_t(in->top, i), 0, l);
+}
+
+int BN_bn2bin_padded(uint8_t *out, size_t len, const BIGNUM *in) {
+ size_t i;
+ BN_ULONG l;
+
+ /* Special case for |in| = 0. Just branch as the probability is negligible. */
+ if (BN_is_zero(in)) {
+ memset(out, 0, len);
+ return 1;
+ }
+
+ /* Check if the integer is too big. This case can exit early in non-constant
+ * time. */
+ if ((size_t)in->top > (len + (BN_BYTES - 1)) / BN_BYTES) {
+ return 0;
+ }
+ if ((len % BN_BYTES) != 0) {
+ l = read_word_padded(in, len / BN_BYTES);
+ if (l >> (8 * (len % BN_BYTES)) != 0) {
+ return 0;
+ }
+ }
+
+ /* Write the bytes out one by one. Serialization is done without branching on
+ * the bits of |in| or on |in->top|, but if the routine would otherwise read
+ * out of bounds, the memory access pattern can't be fixed. However, for an
+ * RSA key of size a multiple of the word size, the probability of BN_BYTES
+ * leading zero octets is low.
+ *
+ * See Falko Stenzke, "Manger's Attack revisited", ICICS 2010. */
+ i = len;
+ while (i--) {
+ l = read_word_padded(in, i / BN_BYTES);
+ *(out++) = (uint8_t)(l >> (8 * (i % BN_BYTES))) & 0xff;
+ }
+ return 1;
+}
+
+static const char hextable[] = "0123456789abcdef";
+
+char *BN_bn2hex(const BIGNUM *bn) {
+ int i, j, v, z = 0;
+ char *buf;
+ char *p;
+
+ buf = (char *)OPENSSL_malloc(bn->top * BN_BYTES * 2 + 2);
+ if (buf == NULL) {
+ OPENSSL_PUT_ERROR(BN, BN_bn2hex, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ p = buf;
+ if (bn->neg) {
+ *(p++) = '-';
+ }
+
+ if (BN_is_zero(bn)) {
+ *(p++) = '0';
+ }
+
+ for (i = bn->top - 1; i >= 0; i--) {
+ for (j = BN_BITS2 - 8; j >= 0; j -= 8) {
+ /* strip leading zeros */
+ v = ((int)(bn->d[i] >> (long)j)) & 0xff;
+ if (z || v != 0) {
+ *(p++) = hextable[v >> 4];
+ *(p++) = hextable[v & 0x0f];
+ z = 1;
+ }
+ }
+ }
+ *p = '\0';
+
+ return buf;
+}
+
+/* decode_hex decodes |i| bytes of hex data from |in| and updates |bn|. */
+static void decode_hex(BIGNUM *bn, const char *in, int i) {
+ int h, m, j, k, c;
+ BN_ULONG l=0;
+
+ j = i; /* least significant 'hex' */
+ h = 0;
+ while (j > 0) {
+ m = ((BN_BYTES * 2) <= j) ? (BN_BYTES * 2) : j;
+ l = 0;
+ for (;;) {
+ c = in[j - m];
+ if ((c >= '0') && (c <= '9')) {
+ k = c - '0';
+ } else if ((c >= 'a') && (c <= 'f')) {
+ k = c - 'a' + 10;
+ } else if ((c >= 'A') && (c <= 'F')) {
+ k = c - 'A' + 10;
+ } else {
+ k = 0; /* paranoia */
+ }
+
+ l = (l << 4) | k;
+
+ if (--m <= 0) {
+ bn->d[h++] = l;
+ break;
+ }
+ }
+
+ j -= (BN_BYTES * 2);
+ }
+
+ bn->top = h;
+}
+
+/* decode_dec decodes |i| bytes of decimal data from |in| and updates |bn|. */
+static void decode_dec(BIGNUM *bn, const char *in, int i) {
+ int j;
+ BN_ULONG l = 0;
+
+ j = BN_DEC_NUM - (i % BN_DEC_NUM);
+ if (j == BN_DEC_NUM) {
+ j = 0;
+ }
+ l = 0;
+ while (*in) {
+ l *= 10;
+ l += *in - '0';
+ in++;
+ if (++j == BN_DEC_NUM) {
+ BN_mul_word(bn, BN_DEC_CONV);
+ BN_add_word(bn, l);
+ l = 0;
+ j = 0;
+ }
+ }
+}
+
+typedef void (*decode_func) (BIGNUM *bn, const char *in, int i);
+typedef int (*char_test_func) (int c);
+
+static int bn_x2bn(BIGNUM **outp, const char *in, decode_func decode, char_test_func want_char) {
+ BIGNUM *ret = NULL;
+ int neg = 0, i;
+ int num;
+
+ if (in == NULL || *in == 0) {
+ return 0;
+ }
+
+ if (*in == '-') {
+ neg = 1;
+ in++;
+ }
+
+ for (i = 0; want_char((unsigned char)in[i]); i++) {}
+
+ num = i + neg;
+ if (outp == NULL) {
+ return num;
+ }
+
+ /* in is the start of the hex digits, and it is 'i' long */
+ if (*outp == NULL) {
+ ret = BN_new();
+ if (ret == NULL) {
+ return 0;
+ }
+ } else {
+ ret = *outp;
+ BN_zero(ret);
+ }
+ ret->neg = neg;
+
+ /* i is the number of hex digests; */
+ if (bn_expand(ret, i * 4) == NULL) {
+ goto err;
+ }
+
+ decode(ret, in, i);
+
+ bn_correct_top(ret);
+
+ *outp = ret;
+ return num;
+
+err:
+ if (*outp == NULL) {
+ BN_free(ret);
+ }
+
+ return 0;
+}
+
+int BN_hex2bn(BIGNUM **outp, const char *in) {
+ return bn_x2bn(outp, in, decode_hex, isxdigit);
+}
+
+char *BN_bn2dec(const BIGNUM *a) {
+ int i = 0, num, ok = 0;
+ char *buf = NULL;
+ char *p;
+ BIGNUM *t = NULL;
+ BN_ULONG *bn_data = NULL, *lp;
+
+ /* get an upper bound for the length of the decimal integer
+ * num <= (BN_num_bits(a) + 1) * log(2)
+ * <= 3 * BN_num_bits(a) * 0.1001 + log(2) + 1 (rounding error)
+ * <= BN_num_bits(a)/10 + BN_num_bits/1000 + 1 + 1
+ */
+ i = BN_num_bits(a) * 3;
+ num = i / 10 + i / 1000 + 1 + 1;
+ bn_data =
+ (BN_ULONG *)OPENSSL_malloc((num / BN_DEC_NUM + 1) * sizeof(BN_ULONG));
+ buf = (char *)OPENSSL_malloc(num + 3);
+ if ((buf == NULL) || (bn_data == NULL)) {
+ OPENSSL_PUT_ERROR(BN, BN_bn2dec, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ t = BN_dup(a);
+ if (t == NULL) {
+ goto err;
+ }
+
+#define BUF_REMAIN (num + 3 - (size_t)(p - buf))
+ p = buf;
+ lp = bn_data;
+ if (BN_is_zero(t)) {
+ *(p++) = '0';
+ *(p++) = '\0';
+ } else {
+ if (BN_is_negative(t)) {
+ *p++ = '-';
+ }
+
+ while (!BN_is_zero(t)) {
+ *lp = BN_div_word(t, BN_DEC_CONV);
+ lp++;
+ }
+ lp--;
+ /* We now have a series of blocks, BN_DEC_NUM chars
+ * in length, where the last one needs truncation.
+ * The blocks need to be reversed in order. */
+ BIO_snprintf(p, BUF_REMAIN, BN_DEC_FMT1, *lp);
+ while (*p) {
+ p++;
+ }
+ while (lp != bn_data) {
+ lp--;
+ BIO_snprintf(p, BUF_REMAIN, BN_DEC_FMT2, *lp);
+ while (*p) {
+ p++;
+ }
+ }
+ }
+ ok = 1;
+
+err:
+ if (bn_data != NULL) {
+ OPENSSL_free(bn_data);
+ }
+ if (t != NULL) {
+ BN_free(t);
+ }
+ if (!ok && buf) {
+ OPENSSL_free(buf);
+ buf = NULL;
+ }
+
+ return buf;
+}
+
+int BN_dec2bn(BIGNUM **outp, const char *in) {
+ return bn_x2bn(outp, in, decode_dec, isdigit);
+}
+
+int BN_asc2bn(BIGNUM **outp, const char *in) {
+ const char *const orig_in = in;
+ if (*in == '-') {
+ in++;
+ }
+
+ if (in[0] == '0' && (in[1] == 'X' || in[1] == 'x')) {
+ if (!BN_hex2bn(outp, in+2)) {
+ return 0;
+ }
+ } else {
+ if (!BN_dec2bn(outp, in)) {
+ return 0;
+ }
+ }
+
+ if (*orig_in == '-') {
+ (*outp)->neg = 1;
+ }
+
+ return 1;
+}
+
+int BN_print(BIO *bp, const BIGNUM *a) {
+ int i, j, v, z = 0;
+ int ret = 0;
+
+ if (a->neg && BIO_write(bp, "-", 1) != 1) {
+ goto end;
+ }
+
+ if (BN_is_zero(a) && BIO_write(bp, "0", 1) != 1) {
+ goto end;
+ }
+
+ for (i = a->top - 1; i >= 0; i--) {
+ for (j = BN_BITS2 - 4; j >= 0; j -= 4) {
+ /* strip leading zeros */
+ v = ((int)(a->d[i] >> (long)j)) & 0x0f;
+ if (z || v != 0) {
+ if (BIO_write(bp, &hextable[v], 1) != 1) {
+ goto end;
+ }
+ z = 1;
+ }
+ }
+ }
+ ret = 1;
+
+end:
+ return ret;
+}
+
+int BN_print_fp(FILE *fp, const BIGNUM *a) {
+ BIO *b;
+ int ret;
+
+ b = BIO_new(BIO_s_file());
+ if (b == NULL) {
+ return 0;
+ }
+ BIO_set_fp(b, fp, BIO_NOCLOSE);
+ ret = BN_print(b, a);
+ BIO_free(b);
+
+ return ret;
+}
+
+BN_ULONG BN_get_word(const BIGNUM *bn) {
+ switch (bn->top) {
+ case 0:
+ return 0;
+ case 1:
+ return bn->d[0];
+ default:
+ return BN_MASK2;
+ }
+}
diff --git a/src/crypto/bn/ctx.c b/src/crypto/bn/ctx.c
new file mode 100644
index 0000000..e54007b
--- /dev/null
+++ b/src/crypto/bn/ctx.c
@@ -0,0 +1,315 @@
+/* Written by Ulf Moeller for the OpenSSL project. */
+/* ====================================================================
+ * Copyright (c) 1998-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.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com). */
+
+
+#include <openssl/bn.h>
+
+#include <string.h>
+
+#include <openssl/err.h>
+#include <openssl/mem.h>
+
+
+/* How many bignums are in each "pool item"; */
+#define BN_CTX_POOL_SIZE 16
+/* The stack frame info is resizing, set a first-time expansion size; */
+#define BN_CTX_START_FRAMES 32
+
+/* A bundle of bignums that can be linked with other bundles */
+typedef struct bignum_pool_item {
+ /* The bignum values */
+ BIGNUM vals[BN_CTX_POOL_SIZE];
+ /* Linked-list admin */
+ struct bignum_pool_item *prev, *next;
+} BN_POOL_ITEM;
+
+
+typedef struct bignum_pool {
+ /* Linked-list admin */
+ BN_POOL_ITEM *head, *current, *tail;
+ /* Stack depth and allocation size */
+ unsigned used, size;
+} BN_POOL;
+
+static void BN_POOL_init(BN_POOL *);
+static void BN_POOL_finish(BN_POOL *);
+static BIGNUM *BN_POOL_get(BN_POOL *);
+static void BN_POOL_release(BN_POOL *, unsigned int);
+
+/************/
+/* BN_STACK */
+/************/
+
+/* A wrapper to manage the "stack frames" */
+typedef struct bignum_ctx_stack {
+ /* Array of indexes into the bignum stack */
+ unsigned int *indexes;
+ /* Number of stack frames, and the size of the allocated array */
+ unsigned int depth, size;
+} BN_STACK;
+
+static void BN_STACK_init(BN_STACK *);
+static void BN_STACK_finish(BN_STACK *);
+static int BN_STACK_push(BN_STACK *, unsigned int);
+static unsigned int BN_STACK_pop(BN_STACK *);
+
+/**********/
+/* BN_CTX */
+/**********/
+
+/* The opaque BN_CTX type */
+struct bignum_ctx {
+ /* The bignum bundles */
+ BN_POOL pool;
+ /* The "stack frames", if you will */
+ BN_STACK stack;
+ /* The number of bignums currently assigned */
+ unsigned int used;
+ /* Depth of stack overflow */
+ int err_stack;
+ /* Block "gets" until an "end" (compatibility behaviour) */
+ int too_many;
+};
+
+BN_CTX *BN_CTX_new(void) {
+ BN_CTX *ret = OPENSSL_malloc(sizeof(BN_CTX));
+ if (!ret) {
+ OPENSSL_PUT_ERROR(BN, BN_CTX_new, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ /* Initialise the structure */
+ BN_POOL_init(&ret->pool);
+ BN_STACK_init(&ret->stack);
+ ret->used = 0;
+ ret->err_stack = 0;
+ ret->too_many = 0;
+ return ret;
+}
+
+void BN_CTX_free(BN_CTX *ctx) {
+ if (ctx == NULL) {
+ return;
+ }
+
+ BN_STACK_finish(&ctx->stack);
+ BN_POOL_finish(&ctx->pool);
+ OPENSSL_free(ctx);
+}
+
+void BN_CTX_start(BN_CTX *ctx) {
+ /* If we're already overflowing ... */
+ if (ctx->err_stack || ctx->too_many) {
+ ctx->err_stack++;
+ } else if (!BN_STACK_push(&ctx->stack, ctx->used)) {
+ /* (Try to) get a new frame pointer */
+ OPENSSL_PUT_ERROR(BN, BN_CTX_start, BN_R_TOO_MANY_TEMPORARY_VARIABLES);
+ ctx->err_stack++;
+ }
+}
+
+BIGNUM *BN_CTX_get(BN_CTX *ctx) {
+ BIGNUM *ret;
+ if (ctx->err_stack || ctx->too_many) {
+ return NULL;
+ }
+
+ ret = BN_POOL_get(&ctx->pool);
+ if (ret == NULL) {
+ /* Setting too_many prevents repeated "get" attempts from
+ * cluttering the error stack. */
+ ctx->too_many = 1;
+ OPENSSL_PUT_ERROR(BN, BN_CTX_get, BN_R_TOO_MANY_TEMPORARY_VARIABLES);
+ return NULL;
+ }
+
+ /* OK, make sure the returned bignum is "zero" */
+ BN_zero(ret);
+ ctx->used++;
+ return ret;
+}
+
+void BN_CTX_end(BN_CTX *ctx) {
+ if (ctx->err_stack) {
+ ctx->err_stack--;
+ } else {
+ unsigned int fp = BN_STACK_pop(&ctx->stack);
+ /* Does this stack frame have anything to release? */
+ if (fp < ctx->used) {
+ BN_POOL_release(&ctx->pool, ctx->used - fp);
+ }
+
+ ctx->used = fp;
+ /* Unjam "too_many" in case "get" had failed */
+ ctx->too_many = 0;
+ }
+}
+
+/************/
+/* BN_STACK */
+/************/
+
+static void BN_STACK_init(BN_STACK *st) {
+ st->indexes = NULL;
+ st->depth = st->size = 0;
+}
+
+static void BN_STACK_finish(BN_STACK *st) {
+ if (st->size)
+ OPENSSL_free(st->indexes);
+}
+
+static int BN_STACK_push(BN_STACK *st, unsigned int idx) {
+ if (st->depth == st->size)
+ /* Need to expand */
+ {
+ unsigned int newsize =
+ (st->size ? (st->size * 3 / 2) : BN_CTX_START_FRAMES);
+ unsigned int *newitems = OPENSSL_malloc(newsize * sizeof(unsigned int));
+ if (!newitems) {
+ return 0;
+ }
+ if (st->depth) {
+ memcpy(newitems, st->indexes, st->depth * sizeof(unsigned int));
+ }
+ if (st->size) {
+ OPENSSL_free(st->indexes);
+ }
+ st->indexes = newitems;
+ st->size = newsize;
+ }
+
+ st->indexes[(st->depth)++] = idx;
+ return 1;
+}
+
+static unsigned int BN_STACK_pop(BN_STACK *st) {
+ return st->indexes[--(st->depth)];
+}
+
+static void BN_POOL_init(BN_POOL *p) {
+ p->head = p->current = p->tail = NULL;
+ p->used = p->size = 0;
+}
+
+static void BN_POOL_finish(BN_POOL *p) {
+ while (p->head) {
+ unsigned int loop = 0;
+ BIGNUM *bn = p->head->vals;
+ while (loop++ < BN_CTX_POOL_SIZE) {
+ if (bn->d) {
+ BN_clear_free(bn);
+ }
+ bn++;
+ }
+
+ p->current = p->head->next;
+ OPENSSL_free(p->head);
+ p->head = p->current;
+ }
+}
+
+static BIGNUM *BN_POOL_get(BN_POOL *p) {
+ if (p->used == p->size) {
+ BIGNUM *bn;
+ unsigned int loop = 0;
+ BN_POOL_ITEM *item = OPENSSL_malloc(sizeof(BN_POOL_ITEM));
+ if (!item) {
+ return NULL;
+ }
+
+ /* Initialise the structure */
+ bn = item->vals;
+ while (loop++ < BN_CTX_POOL_SIZE) {
+ BN_init(bn++);
+ }
+
+ item->prev = p->tail;
+ item->next = NULL;
+ /* Link it in */
+ if (!p->head) {
+ p->head = p->current = p->tail = item;
+ } else {
+ p->tail->next = item;
+ p->tail = item;
+ p->current = item;
+ }
+
+ p->size += BN_CTX_POOL_SIZE;
+ p->used++;
+ /* Return the first bignum from the new pool */
+ return item->vals;
+ }
+
+ if (!p->used) {
+ p->current = p->head;
+ } else if ((p->used % BN_CTX_POOL_SIZE) == 0) {
+ p->current = p->current->next;
+ }
+
+ return p->current->vals + ((p->used++) % BN_CTX_POOL_SIZE);
+}
+
+static void BN_POOL_release(BN_POOL *p, unsigned int num) {
+ unsigned int offset = (p->used - 1) % BN_CTX_POOL_SIZE;
+ p->used -= num;
+
+ while (num--) {
+ if (!offset) {
+ offset = BN_CTX_POOL_SIZE - 1;
+ p->current = p->current->prev;
+ } else {
+ offset--;
+ }
+ }
+}
diff --git a/src/crypto/bn/div.c b/src/crypto/bn/div.c
new file mode 100644
index 0000000..d65957a
--- /dev/null
+++ b/src/crypto/bn/div.c
@@ -0,0 +1,620 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/bn.h>
+
+#include <limits.h>
+#include <openssl/err.h>
+
+#include "internal.h"
+
+
+#define asm __asm__
+
+#if !defined(OPENSSL_NO_ASM)
+# if defined(__GNUC__) && __GNUC__>=2
+# if defined(OPENSSL_X86)
+ /*
+ * There were two reasons for implementing this template:
+ * - GNU C generates a call to a function (__udivdi3 to be exact)
+ * in reply to ((((BN_ULLONG)n0)<<BN_BITS2)|n1)/d0 (I fail to
+ * understand why...);
+ * - divl doesn't only calculate quotient, but also leaves
+ * remainder in %edx which we can definitely use here:-)
+ *
+ * <appro@fy.chalmers.se>
+ */
+#undef div_asm
+# define div_asm(n0,n1,d0) \
+ ({ asm volatile ( \
+ "divl %4" \
+ : "=a"(q), "=d"(rem) \
+ : "a"(n1), "d"(n0), "g"(d0) \
+ : "cc"); \
+ q; \
+ })
+# define REMAINDER_IS_ALREADY_CALCULATED
+# elif defined(OPENSSL_X86_64)
+ /*
+ * Same story here, but it's 128-bit by 64-bit division. Wow!
+ * <appro@fy.chalmers.se>
+ */
+# undef div_asm
+# define div_asm(n0,n1,d0) \
+ ({ asm volatile ( \
+ "divq %4" \
+ : "=a"(q), "=d"(rem) \
+ : "a"(n1), "d"(n0), "g"(d0) \
+ : "cc"); \
+ q; \
+ })
+# define REMAINDER_IS_ALREADY_CALCULATED
+# endif /* __<cpu> */
+# endif /* __GNUC__ */
+#endif /* OPENSSL_NO_ASM */
+
+/* BN_div computes dv := num / divisor, rounding towards
+ * zero, and sets up rm such that dv*divisor + rm = num holds.
+ * Thus:
+ * dv->neg == num->neg ^ divisor->neg (unless the result is zero)
+ * rm->neg == num->neg (unless the remainder is zero)
+ * If 'dv' or 'rm' is NULL, the respective value is not returned. */
+int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor,
+ BN_CTX *ctx) {
+ int norm_shift, i, loop;
+ BIGNUM *tmp, wnum, *snum, *sdiv, *res;
+ BN_ULONG *resp, *wnump;
+ BN_ULONG d0, d1;
+ int num_n, div_n;
+ int no_branch = 0;
+
+ /* Invalid zero-padding would have particularly bad consequences
+ * so don't just rely on bn_check_top() here */
+ if ((num->top > 0 && num->d[num->top - 1] == 0) ||
+ (divisor->top > 0 && divisor->d[divisor->top - 1] == 0)) {
+ OPENSSL_PUT_ERROR(BN, BN_div, BN_R_NOT_INITIALIZED);
+ return 0;
+ }
+
+ if ((num->flags & BN_FLG_CONSTTIME) != 0 ||
+ (divisor->flags & BN_FLG_CONSTTIME) != 0) {
+ no_branch = 1;
+ }
+
+ if (BN_is_zero(divisor)) {
+ OPENSSL_PUT_ERROR(BN, BN_div, BN_R_DIV_BY_ZERO);
+ return 0;
+ }
+
+ if (!no_branch && BN_ucmp(num, divisor) < 0) {
+ if (rm != NULL) {
+ if (BN_copy(rm, num) == NULL) {
+ return 0;
+ }
+ }
+ if (dv != NULL) {
+ BN_zero(dv);
+ }
+ return 1;
+ }
+
+ BN_CTX_start(ctx);
+ tmp = BN_CTX_get(ctx);
+ snum = BN_CTX_get(ctx);
+ sdiv = BN_CTX_get(ctx);
+ if (dv == NULL) {
+ res = BN_CTX_get(ctx);
+ } else {
+ res = dv;
+ }
+ if (sdiv == NULL || res == NULL || tmp == NULL || snum == 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, num, 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) == NULL) {
+ 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) == NULL) {
+ goto err;
+ }
+ snum->d[snum->top] = 0;
+ snum->top++;
+ }
+ }
+
+ div_n = sdiv->top;
+ num_n = snum->top;
+ loop = num_n - div_n;
+ /* Lets 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 */
+
+ /* 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' */
+ res->neg = (num->neg ^ divisor->neg);
+ if (!bn_wexpand(res, (loop + 1))) {
+ goto err;
+ }
+ res->top = loop - no_branch;
+ 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 */
+ BN_ULONG n0, n1, rem = 0;
+
+ n0 = wnump[0];
+ n1 = wnump[-1];
+ if (n0 == d0) {
+ q = BN_MASK2;
+ } else {
+ /* n0 < d0 */
+#ifdef BN_LLONG
+ BN_ULLONG t2;
+
+#if defined(BN_LLONG) && !defined(div_asm)
+ q = (BN_ULONG)(((((BN_ULLONG)n0) << BN_BITS2) | n1) / d0);
+#else
+ q = div_asm(n0, n1, d0);
+#endif
+
+#ifndef REMAINDER_IS_ALREADY_CALCULATED
+ /* rem doesn't have to be BN_ULLONG. The least we know it's less that d0,
+ * isn't it? */
+ rem = (n1 - q * d0) & BN_MASK2;
+#endif
+
+ t2 = (BN_ULLONG)d1 * q;
+
+ for (;;) {
+ if (t2 <= ((((BN_ULLONG)rem) << BN_BITS2) | wnump[-2]))
+ break;
+ q--;
+ rem += d0;
+ if (rem < d0)
+ break; /* don't let rem overflow */
+ t2 -= d1;
+ }
+#else /* !BN_LLONG */
+ BN_ULONG t2l, t2h;
+
+#if defined(div_asm)
+ q = div_asm(n0, n1, d0);
+#else
+ q = bn_div_words(n0, n1, d0);
+#endif
+
+#ifndef REMAINDER_IS_ALREADY_CALCULATED
+ rem = (n1 - q * d0) & BN_MASK2;
+#endif
+
+#if defined(BN_UMULT_LOHI)
+ BN_UMULT_LOHI(t2l, t2h, d1, q);
+#elif defined(BN_UMULT_HIGH)
+ t2l = d1 * q;
+ t2h = BN_UMULT_HIGH(d1, q);
+#else
+ {
+ BN_ULONG ql, qh;
+ t2l = LBITS(d1);
+ t2h = HBITS(d1);
+ ql = LBITS(q);
+ qh = HBITS(q);
+ mul64(t2l, t2h, ql, qh); /* t2=(BN_ULLONG)d1*q; */
+ }
+#endif
+
+ for (;;) {
+ if ((t2h < rem) || ((t2h == rem) && (t2l <= wnump[-2])))
+ break;
+ q--;
+ rem += d0;
+ if (rem < d0)
+ break; /* don't let rem overflow */
+ if (t2l < d1)
+ t2h--;
+ t2l -= d1;
+ }
+#endif /* !BN_LLONG */
+ }
+
+ l0 = bn_mul_words(tmp->d, sdiv->d, div_n, q);
+ tmp->d[div_n] = l0;
+ wnum.d--;
+ /* ingore 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 (rm != NULL) {
+ /* Keep a copy of the neg flag in num because if rm==num
+ * BN_rshift() will overwrite it.
+ */
+ int neg = num->neg;
+ BN_rshift(rm, snum, norm_shift);
+ if (!BN_is_zero(rm)) {
+ rm->neg = neg;
+ }
+ }
+ if (no_branch) {
+ bn_correct_top(res);
+ }
+ BN_CTX_end(ctx);
+ return 1;
+
+err:
+ BN_CTX_end(ctx);
+ return 0;
+}
+
+int BN_nnmod(BIGNUM *r, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx) {
+ if (!(BN_mod(r, m, d, ctx))) {
+ return 0;
+ }
+ if (!r->neg) {
+ return 1;
+ }
+
+ /* now -|d| < r < 0, so we have to set r := r + |d|. */
+ return (d->neg ? BN_sub : BN_add)(r, r, d);
+}
+
+int BN_mod_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m,
+ BN_CTX *ctx) {
+ if (!BN_add(r, a, b)) {
+ return 0;
+ }
+ return BN_nnmod(r, r, m, ctx);
+}
+
+int BN_mod_add_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+ const BIGNUM *m) {
+ if (!BN_uadd(r, a, b)) {
+ return 0;
+ }
+ if (BN_ucmp(r, m) >= 0) {
+ return BN_usub(r, r, m);
+ }
+ return 1;
+}
+
+int BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m,
+ BN_CTX *ctx) {
+ if (!BN_sub(r, a, b)) {
+ return 0;
+ }
+ return BN_nnmod(r, r, m, ctx);
+}
+
+/* BN_mod_sub variant that may be used if both a and b are non-negative
+ * and less than m */
+int BN_mod_sub_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+ const BIGNUM *m) {
+ if (!BN_sub(r, a, b)) {
+ return 0;
+ }
+ if (r->neg) {
+ return BN_add(r, r, m);
+ }
+ return 1;
+}
+
+int BN_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m,
+ BN_CTX *ctx) {
+ BIGNUM *t;
+ int ret = 0;
+
+ BN_CTX_start(ctx);
+ t = BN_CTX_get(ctx);
+ if (t == NULL) {
+ goto err;
+ }
+
+ if (a == b) {
+ if (!BN_sqr(t, a, ctx)) {
+ goto err;
+ }
+ } else {
+ if (!BN_mul(t, a, b, ctx)) {
+ goto err;
+ }
+ }
+
+ if (!BN_nnmod(r, t, m, ctx)) {
+ goto err;
+ }
+
+ ret = 1;
+
+err:
+ BN_CTX_end(ctx);
+ return ret;
+}
+
+int BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx) {
+ if (!BN_sqr(r, a, ctx)) {
+ return 0;
+ }
+
+ /* r->neg == 0, thus we don't need BN_nnmod */
+ return BN_mod(r, r, m, ctx);
+}
+
+int BN_mod_lshift(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m,
+ BN_CTX *ctx) {
+ BIGNUM *abs_m = NULL;
+ int ret;
+
+ if (!BN_nnmod(r, a, m, ctx)) {
+ return 0;
+ }
+
+ if (m->neg) {
+ abs_m = BN_dup(m);
+ if (abs_m == NULL) {
+ return 0;
+ }
+ abs_m->neg = 0;
+ }
+
+ ret = BN_mod_lshift_quick(r, r, n, (abs_m ? abs_m : m));
+
+ if (abs_m) {
+ BN_free(abs_m);
+ }
+ return ret;
+}
+
+int BN_mod_lshift_quick(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m) {
+ if (r != a) {
+ if (BN_copy(r, a) == NULL) {
+ return 0;
+ }
+ }
+
+ while (n > 0) {
+ int max_shift;
+
+ /* 0 < r < m */
+ max_shift = BN_num_bits(m) - BN_num_bits(r);
+ /* max_shift >= 0 */
+
+ if (max_shift < 0) {
+ OPENSSL_PUT_ERROR(BN, BN_mod_lshift_quick, BN_R_INPUT_NOT_REDUCED);
+ return 0;
+ }
+
+ if (max_shift > n) {
+ max_shift = n;
+ }
+
+ if (max_shift) {
+ if (!BN_lshift(r, r, max_shift)) {
+ return 0;
+ }
+ n -= max_shift;
+ } else {
+ if (!BN_lshift1(r, r)) {
+ return 0;
+ }
+ --n;
+ }
+
+ /* BN_num_bits(r) <= BN_num_bits(m) */
+ if (BN_cmp(r, m) >= 0) {
+ if (!BN_sub(r, r, m)) {
+ return 0;
+ }
+ }
+ }
+
+ return 1;
+}
+
+int BN_mod_lshift1(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx) {
+ if (!BN_lshift1(r, a)) {
+ return 0;
+ }
+
+ return BN_nnmod(r, r, m, ctx);
+}
+
+int BN_mod_lshift1_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *m) {
+ if (!BN_lshift1(r, a)) {
+ return 0;
+ }
+ if (BN_cmp(r, m) >= 0) {
+ return BN_sub(r, r, m);
+ }
+
+ return 1;
+}
+
+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];
+ d = bn_div_words(ret, l, w);
+ ret = (l - ((d * w) & BN_MASK2)) & BN_MASK2;
+ a->d[i] = d;
+ }
+
+ if ((a->top > 0) && (a->d[a->top - 1] == 0)) {
+ a->top--;
+ }
+
+ ret >>= j;
+ return ret;
+}
+
+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;
+ }
+
+ 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;
+}
diff --git a/src/crypto/bn/exponentiation.c b/src/crypto/bn/exponentiation.c
new file mode 100644
index 0000000..53f3e9c
--- /dev/null
+++ b/src/crypto/bn/exponentiation.c
@@ -0,0 +1,1535 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/bn.h>
+
+#include <assert.h>
+#include <string.h>
+
+#include <openssl/cpu.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+
+#include "internal.h"
+
+
+#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64)
+#define OPENSSL_BN_ASM_MONT5
+#define RSAZ_ENABLED
+
+#include "rsaz_exp.h"
+#endif
+
+int BN_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) {
+ int i, bits, ret = 0;
+ BIGNUM *v, *rr;
+
+ if ((p->flags & BN_FLG_CONSTTIME) != 0) {
+ /* BN_FLG_CONSTTIME only supported by BN_mod_exp_mont() */
+ OPENSSL_PUT_ERROR(BN, BN_exp, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return 0;
+ }
+
+ BN_CTX_start(ctx);
+ if (r == a || r == p) {
+ rr = BN_CTX_get(ctx);
+ } else {
+ rr = r;
+ }
+
+ v = BN_CTX_get(ctx);
+ if (rr == NULL || v == NULL) {
+ goto err;
+ }
+
+ if (BN_copy(v, a) == NULL) {
+ goto err;
+ }
+ bits = BN_num_bits(p);
+
+ if (BN_is_odd(p)) {
+ if (BN_copy(rr, a) == NULL) {
+ goto err;
+ }
+ } else {
+ if (!BN_one(rr)) {
+ goto err;
+ }
+ }
+
+ for (i = 1; i < bits; i++) {
+ if (!BN_sqr(v, v, ctx)) {
+ goto err;
+ }
+ if (BN_is_bit_set(p, i)) {
+ if (!BN_mul(rr, rr, v, ctx)) {
+ goto err;
+ }
+ }
+ }
+ ret = 1;
+
+err:
+ if (r != rr) {
+ BN_copy(r, rr);
+ }
+ BN_CTX_end(ctx);
+ return ret;
+}
+
+/* maximum precomputation table size for *variable* sliding windows */
+#define TABLE_SIZE 32
+
+typedef struct bn_recp_ctx_st {
+ BIGNUM N; /* the divisor */
+ BIGNUM Nr; /* the reciprocal */
+ int num_bits;
+ int shift;
+ int flags;
+} BN_RECP_CTX;
+
+static void BN_RECP_CTX_init(BN_RECP_CTX *recp) {
+ BN_init(&recp->N);
+ BN_init(&recp->Nr);
+ recp->num_bits = 0;
+ recp->flags = 0;
+}
+
+static void BN_RECP_CTX_free(BN_RECP_CTX *recp) {
+ if (recp == NULL) {
+ return;
+ }
+
+ BN_free(&recp->N);
+ BN_free(&recp->Nr);
+}
+
+static 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;
+}
+
+/* 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 */
+static int BN_reciprocal(BIGNUM *r, const BIGNUM *m, int len, BN_CTX *ctx) {
+ int ret = -1;
+ BIGNUM *t;
+
+ BN_CTX_start(ctx);
+ t = BN_CTX_get(ctx);
+ if (t == NULL) {
+ goto err;
+ }
+
+ if (!BN_set_bit(t, len)) {
+ goto err;
+ }
+
+ if (!BN_div(r, NULL, t, m, ctx)) {
+ goto err;
+ }
+
+ ret = len;
+
+err:
+ BN_CTX_end(ctx);
+ return ret;
+}
+
+static 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)) {
+ 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;
+
+ j = 0;
+ while (BN_ucmp(r, &(recp->N)) >= 0) {
+ if (j++ > 2) {
+ OPENSSL_PUT_ERROR(BN, BN_div_recp, BN_R_BAD_RECIPROCAL);
+ goto err;
+ }
+ if (!BN_usub(r, r, &(recp->N))) {
+ goto err;
+ }
+ if (!BN_add_word(d, 1)) {
+ goto err;
+ }
+ }
+
+ r->neg = BN_is_zero(r) ? 0 : m->neg;
+ d->neg = m->neg ^ recp->N.neg;
+ ret = 1;
+
+err:
+ BN_CTX_end(ctx);
+ return ret;
+}
+
+static 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);
+ a = BN_CTX_get(ctx);
+ if (a == 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;
+}
+
+/* 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)
+
+static int mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx) {
+ int i, j, bits, ret = 0, wstart, window;
+ 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() */
+ OPENSSL_PUT_ERROR(BN, mod_exp_recp, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return 0;
+ }
+
+ bits = BN_num_bits(p);
+
+ if (bits == 0) {
+ ret = BN_one(r);
+ return ret;
+ }
+
+ BN_CTX_start(ctx);
+ aa = BN_CTX_get(ctx);
+ val[0] = BN_CTX_get(ctx);
+ if (!aa || !val[0]) {
+ goto err;
+ }
+
+ BN_RECP_CTX_init(&recp);
+ 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. */
+ wstart = bits - 1; /* The top bit of the window */
+
+ if (!BN_one(r)) {
+ goto err;
+ }
+
+ for (;;) {
+ int wvalue; /* The 'value' of the window */
+ int wend; /* The bottom bit of the window */
+
+ 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 */
+ 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;
+ start = 0;
+ if (wstart < 0) {
+ break;
+ }
+ }
+ ret = 1;
+
+err:
+ BN_CTX_end(ctx);
+ BN_RECP_CTX_free(&recp);
+ return ret;
+}
+
+int BN_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m,
+ BN_CTX *ctx) {
+ /* 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 && BN_get_flags(p, BN_FLG_CONSTTIME) == 0) {
+ BN_ULONG A = a->d[0];
+ return BN_mod_exp_mont_word(r, A, p, m, ctx, NULL);
+ }
+
+ return BN_mod_exp_mont(r, a, p, m, ctx, NULL);
+ }
+
+ return mod_exp_recp(r, a, p, m, ctx);
+}
+
+int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont) {
+ int i, j, bits, ret = 0, wstart, window;
+ 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 (BN_get_flags(p, BN_FLG_CONSTTIME) != 0) {
+ return BN_mod_exp_mont_consttime(rr, a, p, m, ctx, in_mont);
+ }
+
+ if (!BN_is_odd(m)) {
+ OPENSSL_PUT_ERROR(BN, BN_mod_exp_mont, BN_R_CALLED_WITH_EVEN_MODULUS);
+ return 0;
+ }
+ bits = BN_num_bits(p);
+ if (bits == 0) {
+ ret = BN_one(rr);
+ return ret;
+ }
+
+ BN_CTX_start(ctx);
+ d = BN_CTX_get(ctx);
+ r = BN_CTX_get(ctx);
+ val[0] = BN_CTX_get(ctx);
+ if (!d || !r || !val[0]) {
+ goto err;
+ }
+
+ /* If this is not done, things will break in the montgomery part */
+
+ if (in_mont != NULL) {
+ mont = in_mont;
+ } else {
+ mont = BN_MONT_CTX_new();
+ if (mont == NULL) {
+ goto err;
+ }
+ if (!BN_MONT_CTX_set(mont, m, ctx)) {
+ goto err;
+ }
+ }
+
+ if (a->neg || BN_ucmp(a, m) >= 0) {
+ if (!BN_nnmod(val[0], a, m, ctx)) {
+ goto err;
+ }
+ aa = val[0];
+ } else {
+ aa = a;
+ }
+
+ 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. */
+ wstart = bits - 1; /* The top bit of the window */
+
+ j = m->top; /* borrow j */
+ if (m->d[j - 1] & (((BN_ULONG)1) << (BN_BITS2 - 1))) {
+ if (bn_wexpand(r, j) == NULL)
+ goto err;
+ /* 2^(top*BN_BITS2) - m */
+ r->d[0] = (0 - m->d[0]) & BN_MASK2;
+ for (i = 1; i < j; i++)
+ r->d[i] = (~m->d[i]) & BN_MASK2;
+ r->top = j;
+ /* Upper words will be zero if the corresponding words of 'm'
+ * were 0xfff[...], so decrement r->top accordingly. */
+ bn_correct_top(r);
+ } else if (!BN_to_montgomery(r, BN_value_one(), mont, ctx)) {
+ goto err;
+ }
+
+ for (;;) {
+ int wvalue; /* The 'value' of the window */
+ int wend; /* The bottom bit of the window */
+
+ 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 */
+ 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;
+ 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;
+}
+
+/* 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 copy_to_prebuf(const BIGNUM *b, int top, unsigned char *buf, int idx,
+ int width) {
+ size_t i, j;
+
+ if (top > b->top) {
+ top = b->top; /* this works because 'buf' is explicitly zeroed */
+ }
+ for (i = 0, j = idx; i < top * sizeof b->d[0]; i++, j += width) {
+ buf[j] = ((unsigned char *)b->d)[i];
+ }
+
+ return 1;
+}
+
+static int copy_from_prebuf(BIGNUM *b, int top, unsigned char *buf, int idx,
+ int width) {
+ size_t i, j;
+
+ if (bn_wexpand(b, top) == NULL) {
+ return 0;
+ }
+
+ for (i = 0, j = idx; i < top * sizeof b->d[0]; i++, j += width) {
+ ((unsigned char *)b->d)[i] = buf[j];
+ }
+
+ b->top = top;
+ bn_correct_top(b);
+ return 1;
+}
+
+/* BN_mod_exp_mont_conttime 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
+
+/* 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;
+
+ top = m->top;
+
+ if (!(m->d[0] & 1)) {
+ OPENSSL_PUT_ERROR(BN, BN_mod_exp_mont_consttime,
+ BN_R_CALLED_WITH_EVEN_MODULUS);
+ return 0;
+ }
+ bits = BN_num_bits(p);
+ if (bits == 0) {
+ 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;
+ }
+
+#ifdef RSAZ_ENABLED
+ /* If the size of the operands allow it, perform the optimized
+ * RSAZ exponentiation. For further information see
+ * crypto/bn/rsaz_exp.c and accompanying assembly modules. */
+ if ((16 == a->top) && (16 == p->top) && (BN_num_bits(m) == 1024) &&
+ rsaz_avx2_eligible()) {
+ if (NULL == bn_wexpand(rr, 16))
+ goto err;
+ RSAZ_1024_mod_exp_avx2(rr->d, a->d, p->d, m->d, mont->RR.d, mont->n0[0]);
+ rr->top = 16;
+ rr->neg = 0;
+ bn_correct_top(rr);
+ ret = 1;
+ goto err;
+ } else if ((8 == a->top) && (8 == p->top) && (BN_num_bits(m) == 512)) {
+ if (NULL == bn_wexpand(rr, 8))
+ goto err;
+ RSAZ_512_mod_exp(rr->d, a->d, p->d, m->d, mont->n0[0], mont->RR.d);
+ rr->top = 8;
+ rr->neg = 0;
+ bn_correct_top(rr);
+ ret = 1;
+ goto err;
+ }
+#endif
+
+ /* 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 >= 5) {
+ window = 5; /* ~5% improvement for RSA2048 sign, and even for RSA4096 */
+ if ((top & 7) == 0)
+ powerbufLen += 2 * top * sizeof(m->d[0]);
+ }
+#endif
+ (void)0;
+
+ /* 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));
+#ifdef alloca
+ if (powerbufLen < 3072)
+ powerbufFree = alloca(powerbufLen + MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH);
+ else
+#endif
+ if ((powerbufFree = (unsigned char *)OPENSSL_malloc(
+ powerbufLen + MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH)) == NULL)
+ goto err;
+
+ powerbuf = MOD_EXP_CTIME_ALIGN(powerbufFree);
+ memset(powerbuf, 0, powerbufLen);
+
+#ifdef alloca
+ if (powerbufLen < 3072)
+ powerbufFree = NULL;
+#endif
+
+ /* 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 */
+/* by Shay Gueron's suggestion */
+ if (m->d[top - 1] & (((BN_ULONG)1) << (BN_BITS2 - 1))) {
+ /* 2^(top*BN_BITS2) - m */
+ tmp.d[0] = (0 - m->d[0]) & BN_MASK2;
+ for (i = 1; i < top; i++)
+ tmp.d[i] = (~m->d[i]) & BN_MASK2;
+ tmp.top = top;
+ } else if (!BN_to_montgomery(&tmp, BN_value_one(), mont, ctx))
+ goto err;
+
+ /* prepare a^1 in Montgomery domain */
+ if (a->neg || BN_ucmp(a, m) >= 0) {
+ if (!BN_mod(&am, a, m, ctx))
+ goto err;
+ if (!BN_to_montgomery(&am, &am, mont, ctx))
+ goto err;
+ } else if (!BN_to_montgomery(&am, a, 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);
+ void bn_power5(BN_ULONG * rp, const BN_ULONG * ap, const void * table,
+ const BN_ULONG * np, const BN_ULONG * n0, int num,
+ int power);
+ int bn_from_montgomery(BN_ULONG * rp, const BN_ULONG * ap,
+ const BN_ULONG * not_used, const BN_ULONG * np,
+ const BN_ULONG * n0, int num);
+
+ BN_ULONG *np = mont->N.d, *n0 = mont->n0, *np2;
+
+ /* 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;
+
+ if (top & 7)
+ np2 = np;
+ else
+ for (np2 = am.d + top, i = 0; i < top; i++)
+ np2[2 * i] = np[i];
+
+ 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);
+
+ /* 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, np2, 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, np2, 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, np2, n0, top, i - 1);
+ bn_scatter5(tmp.d, top, powerbuf, i);
+ }
+
+ 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);
+
+ /* At this point |bits| is 4 mod 5 and at least -1. (|bits| is the first bit
+ * that has not been read yet.) */
+ assert(bits >= -1 && (bits == -1 || bits % 5 == 4));
+
+ /* Scan the exponent one window at a time starting from the most
+ * significant bits.
+ */
+ if (top & 7) {
+ 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);
+ }
+ } else {
+ const uint8_t *p_bytes = (const uint8_t *)p->d;
+ int max_bits = p->top * BN_BITS2;
+ assert(bits < max_bits);
+ /* |p = 0| has been handled as a special case, so |max_bits| is at least
+ * one word. */
+ assert(max_bits >= 64);
+
+ /* If the first bit to be read lands in the last byte, unroll the first
+ * iteration to avoid reading past the bounds of |p->d|. (After the first
+ * iteration, we are guaranteed to be past the last byte.) Note |bits|
+ * here is the top bit, inclusive. */
+ if (bits - 4 >= max_bits - 8) {
+ /* Read five bits from |bits-4| through |bits|, inclusive. */
+ wvalue = p_bytes[p->top * BN_BYTES - 1];
+ wvalue >>= (bits - 4) & 7;
+ wvalue &= 0x1f;
+ bits -= 5;
+ bn_power5(tmp.d, tmp.d, powerbuf, np2, n0, top, wvalue);
+ }
+ while (bits >= 0) {
+ /* Read five bits from |bits-4| through |bits|, inclusive. */
+ int first_bit = bits - 4;
+ wvalue = *(const uint16_t *) (p_bytes + (first_bit >> 3));
+ wvalue >>= first_bit & 7;
+ wvalue &= 0x1f;
+ bits -= 5;
+ bn_power5(tmp.d, tmp.d, powerbuf, np2, n0, top, wvalue);
+ }
+ }
+
+ ret = bn_from_montgomery(tmp.d, tmp.d, NULL, np2, n0, top);
+ tmp.top = top;
+ bn_correct_top(&tmp);
+ if (ret) {
+ if (!BN_copy(rr, &tmp))
+ ret = 0;
+ goto err; /* non-zero ret means it's not error */
+ }
+ } else
+#endif
+ {
+ if (!copy_to_prebuf(&tmp, top, powerbuf, 0, numPowers))
+ goto err;
+ if (!copy_to_prebuf(&am, top, powerbuf, 1, numPowers))
+ 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 (!copy_to_prebuf(&tmp, top, powerbuf, 2, numPowers))
+ 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 (!copy_to_prebuf(&tmp, top, powerbuf, i, numPowers))
+ goto err;
+ }
+ }
+
+ bits--;
+ for (wvalue = 0, i = bits % window; i >= 0; i--, bits--)
+ wvalue = (wvalue << 1) + BN_is_bit_set(p, bits);
+ if (!copy_from_prebuf(&tmp, top, powerbuf, wvalue, numPowers))
+ 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 (!copy_from_prebuf(&am, top, powerbuf, wvalue, numPowers))
+ 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);
+ if (powerbuf != NULL) {
+ OPENSSL_cleanse(powerbuf, powerbufLen);
+ if (powerbufFree)
+ OPENSSL_free(powerbufFree);
+ }
+ BN_CTX_end(ctx);
+ return (ret);
+}
+
+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(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() */
+ OPENSSL_PUT_ERROR(BN, BN_mod_exp_mont_word,
+ ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return 0;
+ }
+
+ if (!BN_is_odd(m)) {
+ OPENSSL_PUT_ERROR(BN, BN_mod_exp_mont_word, 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_is_one(m)) {
+ 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);
+ d = BN_CTX_get(ctx);
+ r = BN_CTX_get(ctx);
+ t = BN_CTX_get(ctx);
+ if (d == NULL || r == NULL || t == 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;
+}
+
+#define TABLE_SIZE 32
+
+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 (!(m->d[0] & 1)) {
+ OPENSSL_PUT_ERROR(BN, BN_mod_exp2_mont, 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);
+ d = BN_CTX_get(ctx);
+ r = BN_CTX_get(ctx);
+ val1[0] = BN_CTX_get(ctx);
+ val2[0] = BN_CTX_get(ctx);
+ if (!d || !r || !val1[0] || !val2[0]) {
+ goto err;
+ }
+
+ if (in_mont != NULL) {
+ mont = in_mont;
+ } else {
+ mont = BN_MONT_CTX_new();
+ if (mont == 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 (a1->neg || BN_ucmp(a1, m) >= 0) {
+ if (!BN_mod(val1[0], a1, m, ctx)) {
+ goto err;
+ }
+ a_mod_m = val1[0];
+ } else {
+ a_mod_m = a1;
+ }
+
+ 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 (a2->neg || BN_ucmp(a2, m) >= 0) {
+ if (!BN_mod(val2[0], a2, m, ctx)) {
+ goto err;
+ }
+ a_mod_m = val2[0];
+ } else {
+ a_mod_m = a2;
+ }
+
+ 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 && 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 && 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;
+}
diff --git a/src/crypto/bn/gcd.c b/src/crypto/bn/gcd.c
new file mode 100644
index 0000000..2dce296
--- /dev/null
+++ b/src/crypto/bn/gcd.c
@@ -0,0 +1,704 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/bn.h>
+
+#include <openssl/err.h>
+
+#include "internal.h"
+
+static BIGNUM *euclid(BIGNUM *a, BIGNUM *b) {
+ BIGNUM *t;
+ int shifts = 0;
+
+ /* 0 <= b <= a */
+ while (!BN_is_zero(b)) {
+ /* 0 < b <= a */
+
+ if (BN_is_odd(a)) {
+ if (BN_is_odd(b)) {
+ if (!BN_sub(a, a, b)) {
+ goto err;
+ }
+ if (!BN_rshift1(a, a)) {
+ goto err;
+ }
+ if (BN_cmp(a, b) < 0) {
+ t = a;
+ a = b;
+ b = t;
+ }
+ } else {
+ /* a odd - b even */
+ if (!BN_rshift1(b, b)) {
+ goto err;
+ }
+ if (BN_cmp(a, b) < 0) {
+ t = a;
+ a = b;
+ b = t;
+ }
+ }
+ } else {
+ /* a is even */
+ if (BN_is_odd(b)) {
+ if (!BN_rshift1(a, a)) {
+ goto err;
+ }
+ if (BN_cmp(a, b) < 0) {
+ t = a;
+ a = b;
+ b = t;
+ }
+ } else {
+ /* a even - b even */
+ if (!BN_rshift1(a, a)) {
+ goto err;
+ }
+ if (!BN_rshift1(b, b)) {
+ goto err;
+ }
+ shifts++;
+ }
+ }
+ /* 0 <= b <= a */
+ }
+
+ 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);
+ a = BN_CTX_get(ctx);
+ b = BN_CTX_get(ctx);
+
+ if (a == NULL || b == NULL) {
+ goto err;
+ }
+ if (BN_copy(a, in_a) == NULL) {
+ goto err;
+ }
+ if (BN_copy(b, in_b) == NULL) {
+ 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) == NULL) {
+ goto err;
+ }
+ ret = 1;
+
+err:
+ BN_CTX_end(ctx);
+ return ret;
+}
+
+/* solves ax == 1 (mod n) */
+static BIGNUM *BN_mod_inverse_no_branch(BIGNUM *out, const BIGNUM *a,
+ const BIGNUM *n, BN_CTX *ctx);
+
+BIGNUM *BN_mod_inverse(BIGNUM *out, const BIGNUM *a, const BIGNUM *n,
+ BN_CTX *ctx) {
+ BIGNUM *A, *B, *X, *Y, *M, *D, *T, *R = NULL;
+ BIGNUM *ret = NULL;
+ int sign;
+
+ if ((a->flags & BN_FLG_CONSTTIME) != 0 ||
+ (n->flags & BN_FLG_CONSTTIME) != 0) {
+ return BN_mod_inverse_no_branch(out, a, n, ctx);
+ }
+
+ BN_CTX_start(ctx);
+ A = BN_CTX_get(ctx);
+ B = BN_CTX_get(ctx);
+ X = BN_CTX_get(ctx);
+ D = BN_CTX_get(ctx);
+ M = BN_CTX_get(ctx);
+ Y = BN_CTX_get(ctx);
+ T = BN_CTX_get(ctx);
+ if (T == NULL) {
+ goto err;
+ }
+
+ if (out == NULL) {
+ R = BN_new();
+ } else {
+ R = out;
+ }
+ if (R == NULL) {
+ goto err;
+ }
+
+ BN_one(X);
+ BN_zero(Y);
+ if (BN_copy(B, a) == NULL) {
+ goto err;
+ }
+ if (BN_copy(A, n) == NULL) {
+ 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
+ * sytems, 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(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)) {
+ /* Y*a == 1 (mod |n|) */
+ if (!Y->neg && BN_ucmp(Y, n) < 0) {
+ if (!BN_copy(R, Y)) {
+ goto err;
+ }
+ } else {
+ if (!BN_nnmod(R, Y, n, ctx)) {
+ goto err;
+ }
+ }
+ } else {
+ OPENSSL_PUT_ERROR(BN, BN_mod_inverse, BN_R_NO_INVERSE);
+ goto err;
+ }
+ ret = R;
+
+err:
+ if (ret == NULL && out == NULL) {
+ BN_free(R);
+ }
+ BN_CTX_end(ctx);
+ return ret;
+}
+
+/* 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 *out, 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_CTX_start(ctx);
+ A = BN_CTX_get(ctx);
+ B = BN_CTX_get(ctx);
+ X = BN_CTX_get(ctx);
+ D = BN_CTX_get(ctx);
+ M = BN_CTX_get(ctx);
+ Y = BN_CTX_get(ctx);
+ T = BN_CTX_get(ctx);
+ if (T == NULL) {
+ goto err;
+ }
+
+ if (out == NULL) {
+ R = BN_new();
+ } else {
+ R = out;
+ }
+ if (R == NULL) {
+ goto err;
+ }
+
+ BN_one(X);
+ BN_zero(Y);
+ if (BN_copy(B, a) == NULL) {
+ goto err;
+ }
+ if (BN_copy(A, n) == NULL) {
+ 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_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_with_flags(pA, A, BN_FLG_CONSTTIME);
+
+ /* (D, M) := (A/B, A%B) ... */
+ if (!BN_div(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)) {
+ /* Y*a == 1 (mod |n|) */
+ if (!Y->neg && BN_ucmp(Y, n) < 0) {
+ if (!BN_copy(R, Y)) {
+ goto err;
+ }
+ } else {
+ if (!BN_nnmod(R, Y, n, ctx)) {
+ goto err;
+ }
+ }
+ } else {
+ OPENSSL_PUT_ERROR(BN, BN_mod_inverse_no_branch, BN_R_NO_INVERSE);
+ goto err;
+ }
+ ret = R;
+
+err:
+ if (ret == NULL && out == NULL) {
+ BN_free(R);
+ }
+
+ BN_CTX_end(ctx);
+ return ret;
+}
diff --git a/src/crypto/bn/generic.c b/src/crypto/bn/generic.c
new file mode 100644
index 0000000..224a47c
--- /dev/null
+++ b/src/crypto/bn/generic.c
@@ -0,0 +1,1120 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/bn.h>
+
+#include <assert.h>
+
+#include "internal.h"
+
+
+/* Generic implementations of most operations are needed for:
+ * - Configurations without inline assembly.
+ * - Architectures other than x86 or x86_64.
+ * - Windows x84_64; x86_64-gcc.c does not build on MSVC. */
+#if defined(OPENSSL_NO_ASM) || \
+ (!defined(OPENSSL_X86_64) && !defined(OPENSSL_X86)) || \
+ (defined(OPENSSL_X86_64) && defined(OPENSSL_WINDOWS))
+
+#if defined(OPENSSL_WINDOWS)
+#define alloca _alloca
+#else
+#include <alloca.h>
+#endif
+
+#ifdef BN_LLONG
+#define mul_add(r, a, w, c) \
+ { \
+ BN_ULLONG t; \
+ t = (BN_ULLONG)w * (a) + (r) + (c); \
+ (r) = Lw(t); \
+ (c) = Hw(t); \
+ }
+
+#define mul(r, a, w, c) \
+ { \
+ BN_ULLONG t; \
+ t = (BN_ULLONG)w * (a) + (c); \
+ (r) = Lw(t); \
+ (c) = Hw(t); \
+ }
+
+#define sqr(r0, r1, a) \
+ { \
+ BN_ULLONG t; \
+ t = (BN_ULLONG)(a) * (a); \
+ (r0) = Lw(t); \
+ (r1) = Hw(t); \
+ }
+
+#elif defined(BN_UMULT_LOHI)
+#define mul_add(r, a, w, c) \
+ { \
+ BN_ULONG high, low, ret, tmp = (a); \
+ ret = (r); \
+ BN_UMULT_LOHI(low, high, w, tmp); \
+ ret += (c); \
+ (c) = (ret < (c)) ? 1 : 0; \
+ (c) += high; \
+ ret += low; \
+ (c) += (ret < low) ? 1 : 0; \
+ (r) = ret; \
+ }
+
+#define mul(r, a, w, c) \
+ { \
+ BN_ULONG high, low, ret, ta = (a); \
+ BN_UMULT_LOHI(low, high, w, ta); \
+ ret = low + (c); \
+ (c) = high; \
+ (c) += (ret < low) ? 1 : 0; \
+ (r) = ret; \
+ }
+
+#define sqr(r0, r1, a) \
+ { \
+ BN_ULONG tmp = (a); \
+ BN_UMULT_LOHI(r0, r1, tmp, tmp); \
+ }
+
+#else
+
+/*************************************************************
+ * No long long type
+ */
+
+#define LBITS(a) ((a) & BN_MASK2l)
+#define HBITS(a) (((a) >> BN_BITS4) & BN_MASK2l)
+#define L2HBITS(a) (((a) << BN_BITS4) & BN_MASK2)
+
+#define LLBITS(a) ((a) & BN_MASKl)
+#define LHBITS(a) (((a) >> BN_BITS2) & BN_MASKl)
+#define LL2HBITS(a) ((BN_ULLONG)((a) & BN_MASKl) << BN_BITS2)
+
+#define mul64(l, h, bl, bh) \
+ { \
+ BN_ULONG m, m1, lt, ht; \
+ \
+ lt = l; \
+ ht = h; \
+ m = (bh) * (lt); \
+ lt = (bl) * (lt); \
+ m1 = (bl) * (ht); \
+ ht = (bh) * (ht); \
+ m = (m + m1) & BN_MASK2; \
+ if (m < m1) \
+ ht += L2HBITS((BN_ULONG)1); \
+ ht += HBITS(m); \
+ m1 = L2HBITS(m); \
+ lt = (lt + m1) & BN_MASK2; \
+ if (lt < m1) \
+ ht++; \
+ (l) = lt; \
+ (h) = ht; \
+ }
+
+#define sqr64(lo, ho, in) \
+ { \
+ BN_ULONG l, h, m; \
+ \
+ h = (in); \
+ l = LBITS(h); \
+ h = HBITS(h); \
+ m = (l) * (h); \
+ l *= l; \
+ h *= h; \
+ h += (m & BN_MASK2h1) >> (BN_BITS4 - 1); \
+ m = (m & BN_MASK2l) << (BN_BITS4 + 1); \
+ l = (l + m) & BN_MASK2; \
+ if (l < m) \
+ h++; \
+ (lo) = l; \
+ (ho) = h; \
+ }
+
+#define mul_add(r, a, bl, bh, c) \
+ { \
+ BN_ULONG l, h; \
+ \
+ h = (a); \
+ l = LBITS(h); \
+ h = HBITS(h); \
+ mul64(l, h, (bl), (bh)); \
+ \
+ /* non-multiply part */ \
+ l = (l + (c)) & BN_MASK2; \
+ if (l < (c)) \
+ h++; \
+ (c) = (r); \
+ l = (l + (c)) & BN_MASK2; \
+ if (l < (c)) \
+ h++; \
+ (c) = h & BN_MASK2; \
+ (r) = l; \
+ }
+
+#define mul(r, a, bl, bh, c) \
+ { \
+ BN_ULONG l, h; \
+ \
+ h = (a); \
+ l = LBITS(h); \
+ h = HBITS(h); \
+ mul64(l, h, (bl), (bh)); \
+ \
+ /* non-multiply part */ \
+ l += (c); \
+ if ((l & BN_MASK2) < (c)) \
+ h++; \
+ (c) = h & BN_MASK2; \
+ (r) = l & BN_MASK2; \
+ }
+#endif /* !BN_LLONG */
+
+#if defined(BN_LLONG) || defined(BN_UMULT_HIGH)
+
+BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num,
+ BN_ULONG w) {
+ BN_ULONG c1 = 0;
+
+ assert(num >= 0);
+ if (num <= 0) {
+ return c1;
+ }
+
+ while (num & ~3) {
+ mul_add(rp[0], ap[0], w, c1);
+ mul_add(rp[1], ap[1], w, c1);
+ mul_add(rp[2], ap[2], w, c1);
+ mul_add(rp[3], ap[3], w, c1);
+ ap += 4;
+ rp += 4;
+ num -= 4;
+ }
+
+ while (num) {
+ mul_add(rp[0], ap[0], w, c1);
+ ap++;
+ rp++;
+ num--;
+ }
+
+ return c1;
+}
+
+BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w) {
+ BN_ULONG c1 = 0;
+
+ assert(num >= 0);
+ if (num <= 0) {
+ return c1;
+ }
+
+ while (num & ~3) {
+ mul(rp[0], ap[0], w, c1);
+ mul(rp[1], ap[1], w, c1);
+ mul(rp[2], ap[2], w, c1);
+ mul(rp[3], ap[3], w, c1);
+ ap += 4;
+ rp += 4;
+ num -= 4;
+ }
+ while (num) {
+ mul(rp[0], ap[0], w, c1);
+ ap++;
+ rp++;
+ num--;
+ }
+ return c1;
+}
+
+void bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, int n) {
+ assert(n >= 0);
+ if (n <= 0) {
+ return;
+ }
+
+ while (n & ~3) {
+ sqr(r[0], r[1], a[0]);
+ sqr(r[2], r[3], a[1]);
+ sqr(r[4], r[5], a[2]);
+ sqr(r[6], r[7], a[3]);
+ a += 4;
+ r += 8;
+ n -= 4;
+ }
+ while (n) {
+ sqr(r[0], r[1], a[0]);
+ a++;
+ r += 2;
+ n--;
+ }
+}
+
+#else /* !(defined(BN_LLONG) || defined(BN_UMULT_HIGH)) */
+
+BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num,
+ BN_ULONG w) {
+ BN_ULONG c = 0;
+ BN_ULONG bl, bh;
+
+ assert(num >= 0);
+ if (num <= 0) {
+ return (BN_ULONG)0;
+ }
+
+ bl = LBITS(w);
+ bh = HBITS(w);
+
+ while (num & ~3) {
+ mul_add(rp[0], ap[0], bl, bh, c);
+ mul_add(rp[1], ap[1], bl, bh, c);
+ mul_add(rp[2], ap[2], bl, bh, c);
+ mul_add(rp[3], ap[3], bl, bh, c);
+ ap += 4;
+ rp += 4;
+ num -= 4;
+ }
+ while (num) {
+ mul_add(rp[0], ap[0], bl, bh, c);
+ ap++;
+ rp++;
+ num--;
+ }
+ return c;
+}
+
+BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w) {
+ BN_ULONG carry = 0;
+ BN_ULONG bl, bh;
+
+ assert(num >= 0);
+ if (num <= 0) {
+ return (BN_ULONG)0;
+ }
+
+ bl = LBITS(w);
+ bh = HBITS(w);
+
+ while (num & ~3) {
+ mul(rp[0], ap[0], bl, bh, carry);
+ mul(rp[1], ap[1], bl, bh, carry);
+ mul(rp[2], ap[2], bl, bh, carry);
+ mul(rp[3], ap[3], bl, bh, carry);
+ ap += 4;
+ rp += 4;
+ num -= 4;
+ }
+ while (num) {
+ mul(rp[0], ap[0], bl, bh, carry);
+ ap++;
+ rp++;
+ num--;
+ }
+ return carry;
+}
+
+void bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, int n) {
+ assert(n >= 0);
+ if (n <= 0) {
+ return;
+ }
+
+ while (n & ~3) {
+ sqr64(r[0], r[1], a[0]);
+ sqr64(r[2], r[3], a[1]);
+ sqr64(r[4], r[5], a[2]);
+ sqr64(r[6], r[7], a[3]);
+ a += 4;
+ r += 8;
+ n -= 4;
+ }
+ while (n) {
+ sqr64(r[0], r[1], a[0]);
+ a++;
+ r += 2;
+ n--;
+ }
+}
+
+#endif /* !(defined(BN_LLONG) || defined(BN_UMULT_HIGH)) */
+
+#if defined(BN_LLONG)
+
+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. */
+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) */
+
+#ifdef BN_LLONG
+BN_ULONG bn_add_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
+ int n) {
+ BN_ULLONG ll = 0;
+
+ assert(n >= 0);
+ if (n <= 0) {
+ return (BN_ULONG)0;
+ }
+
+ while (n & ~3) {
+ ll += (BN_ULLONG)a[0] + b[0];
+ r[0] = (BN_ULONG)ll & BN_MASK2;
+ ll >>= BN_BITS2;
+ ll += (BN_ULLONG)a[1] + b[1];
+ r[1] = (BN_ULONG)ll & BN_MASK2;
+ ll >>= BN_BITS2;
+ ll += (BN_ULLONG)a[2] + b[2];
+ r[2] = (BN_ULONG)ll & BN_MASK2;
+ ll >>= BN_BITS2;
+ ll += (BN_ULLONG)a[3] + b[3];
+ r[3] = (BN_ULONG)ll & BN_MASK2;
+ ll >>= BN_BITS2;
+ a += 4;
+ b += 4;
+ r += 4;
+ n -= 4;
+ }
+ while (n) {
+ ll += (BN_ULLONG)a[0] + b[0];
+ r[0] = (BN_ULONG)ll & BN_MASK2;
+ ll >>= BN_BITS2;
+ a++;
+ b++;
+ r++;
+ n--;
+ }
+ return (BN_ULONG)ll;
+}
+
+#else /* !BN_LLONG */
+
+BN_ULONG bn_add_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
+ int n) {
+ BN_ULONG c, l, t;
+
+ assert(n >= 0);
+ if (n <= 0) {
+ return (BN_ULONG)0;
+ }
+
+ c = 0;
+ while (n & ~3) {
+ t = a[0];
+ t = (t + c) & BN_MASK2;
+ c = (t < c);
+ l = (t + b[0]) & BN_MASK2;
+ c += (l < t);
+ r[0] = l;
+ t = a[1];
+ t = (t + c) & BN_MASK2;
+ c = (t < c);
+ l = (t + b[1]) & BN_MASK2;
+ c += (l < t);
+ r[1] = l;
+ t = a[2];
+ t = (t + c) & BN_MASK2;
+ c = (t < c);
+ l = (t + b[2]) & BN_MASK2;
+ c += (l < t);
+ r[2] = l;
+ t = a[3];
+ t = (t + c) & BN_MASK2;
+ c = (t < c);
+ l = (t + b[3]) & BN_MASK2;
+ c += (l < t);
+ r[3] = l;
+ a += 4;
+ b += 4;
+ r += 4;
+ n -= 4;
+ }
+ while (n) {
+ t = a[0];
+ t = (t + c) & BN_MASK2;
+ c = (t < c);
+ l = (t + b[0]) & BN_MASK2;
+ c += (l < t);
+ r[0] = l;
+ a++;
+ b++;
+ r++;
+ n--;
+ }
+ return (BN_ULONG)c;
+}
+
+#endif /* !BN_LLONG */
+
+BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
+ int n) {
+ BN_ULONG t1, t2;
+ int c = 0;
+
+ assert(n >= 0);
+ if (n <= 0) {
+ return (BN_ULONG)0;
+ }
+
+ while (n & ~3) {
+ t1 = a[0];
+ t2 = b[0];
+ r[0] = (t1 - t2 - c) & BN_MASK2;
+ if (t1 != t2)
+ c = (t1 < t2);
+ t1 = a[1];
+ t2 = b[1];
+ r[1] = (t1 - t2 - c) & BN_MASK2;
+ if (t1 != t2)
+ c = (t1 < t2);
+ t1 = a[2];
+ t2 = b[2];
+ r[2] = (t1 - t2 - c) & BN_MASK2;
+ if (t1 != t2)
+ c = (t1 < t2);
+ t1 = a[3];
+ t2 = b[3];
+ r[3] = (t1 - t2 - c) & BN_MASK2;
+ if (t1 != t2)
+ c = (t1 < t2);
+ a += 4;
+ b += 4;
+ r += 4;
+ n -= 4;
+ }
+ while (n) {
+ t1 = a[0];
+ t2 = b[0];
+ r[0] = (t1 - t2 - c) & BN_MASK2;
+ if (t1 != t2)
+ c = (t1 < t2);
+ a++;
+ b++;
+ r++;
+ n--;
+ }
+ return c;
+}
+
+/* mul_add_c(a,b,c0,c1,c2) -- c+=a*b for three word number c=(c2,c1,c0) */
+/* mul_add_c2(a,b,c0,c1,c2) -- c+=2*a*b for three word number c=(c2,c1,c0) */
+/* sqr_add_c(a,i,c0,c1,c2) -- c+=a[i]^2 for three word number c=(c2,c1,c0) */
+/* sqr_add_c2(a,i,c0,c1,c2) -- c+=2*a[i]*a[j] for three word number c=(c2,c1,c0) */
+
+#ifdef BN_LLONG
+
+/* Keep in mind that additions to multiplication result can not overflow,
+ * because its high half cannot be all-ones. */
+#define mul_add_c(a, b, c0, c1, c2) \
+ do { \
+ BN_ULONG hi; \
+ BN_ULLONG t = (BN_ULLONG)(a) * (b); \
+ t += c0; /* no carry */ \
+ c0 = (BN_ULONG)Lw(t); \
+ hi = (BN_ULONG)Hw(t); \
+ c1 = (c1 + hi) & BN_MASK2; \
+ if (c1 < hi) \
+ c2++; \
+ } while (0)
+
+#define mul_add_c2(a, b, c0, c1, c2) \
+ do { \
+ BN_ULONG hi; \
+ BN_ULLONG t = (BN_ULLONG)(a) * (b); \
+ BN_ULLONG tt = t + c0; /* no carry */ \
+ c0 = (BN_ULONG)Lw(tt); \
+ hi = (BN_ULONG)Hw(tt); \
+ c1 = (c1 + hi) & BN_MASK2; \
+ if (c1 < hi) \
+ c2++; \
+ t += c0; /* no carry */ \
+ c0 = (BN_ULONG)Lw(t); \
+ hi = (BN_ULONG)Hw(t); \
+ c1 = (c1 + hi) & BN_MASK2; \
+ if (c1 < hi) \
+ c2++; \
+ } while (0)
+
+#define sqr_add_c(a, i, c0, c1, c2) \
+ do { \
+ BN_ULONG hi; \
+ BN_ULLONG t = (BN_ULLONG)a[i] * a[i]; \
+ t += c0; /* no carry */ \
+ c0 = (BN_ULONG)Lw(t); \
+ hi = (BN_ULONG)Hw(t); \
+ c1 = (c1 + hi) & BN_MASK2; \
+ if (c1 < hi) \
+ c2++; \
+ } while (0)
+
+#define sqr_add_c2(a, i, j, c0, c1, c2) mul_add_c2((a)[i], (a)[j], c0, c1, c2)
+
+#elif defined(BN_UMULT_LOHI)
+
+/* Keep in mind that additions to hi can not overflow, because the high word of
+ * a multiplication result cannot be all-ones. */
+#define mul_add_c(a, b, c0, c1, c2) \
+ do { \
+ BN_ULONG ta = (a), tb = (b); \
+ BN_ULONG lo, hi; \
+ BN_UMULT_LOHI(lo, hi, ta, tb); \
+ c0 += lo; \
+ hi += (c0 < lo) ? 1 : 0; \
+ c1 += hi; \
+ c2 += (c1 < hi) ? 1 : 0; \
+ } while (0)
+
+#define mul_add_c2(a, b, c0, c1, c2) \
+ do { \
+ BN_ULONG ta = (a), tb = (b); \
+ BN_ULONG lo, hi, tt; \
+ BN_UMULT_LOHI(lo, hi, ta, tb); \
+ c0 += lo; \
+ tt = hi + ((c0 < lo) ? 1 : 0); \
+ c1 += tt; \
+ c2 += (c1 < tt) ? 1 : 0; \
+ c0 += lo; \
+ hi += (c0 < lo) ? 1 : 0; \
+ c1 += hi; \
+ c2 += (c1 < hi) ? 1 : 0; \
+ } while (0)
+
+#define sqr_add_c(a, i, c0, c1, c2) \
+ do { \
+ BN_ULONG ta = (a)[i]; \
+ BN_ULONG lo, hi; \
+ BN_UMULT_LOHI(lo, hi, ta, ta); \
+ c0 += lo; \
+ hi += (c0 < lo) ? 1 : 0; \
+ c1 += hi; \
+ c2 += (c1 < hi) ? 1 : 0; \
+ } while (0)
+
+#define sqr_add_c2(a, i, j, c0, c1, c2) mul_add_c2((a)[i], (a)[j], c0, c1, c2)
+
+#else /* !BN_LLONG */
+
+/* Keep in mind that additions to hi can not overflow, because
+ * the high word of a multiplication result cannot be all-ones. */
+
+#define mul_add_c(a, b, c0, c1, c2) \
+ do { \
+ BN_ULONG lo = LBITS(a), hi = HBITS(a); \
+ BN_ULONG bl = LBITS(b), bh = HBITS(b); \
+ mul64(lo, hi, bl, bh); \
+ c0 = (c0 + lo) & BN_MASK2; \
+ if (c0 < lo) \
+ hi++; \
+ c1 = (c1 + hi) & BN_MASK2; \
+ if (c1 < hi) \
+ c2++; \
+ } while (0)
+
+#define mul_add_c2(a, b, c0, c1, c2) \
+ do { \
+ BN_ULONG tt; \
+ BN_ULONG lo = LBITS(a), hi = HBITS(a); \
+ BN_ULONG bl = LBITS(b), bh = HBITS(b); \
+ mul64(lo, hi, bl, bh); \
+ tt = hi; \
+ c0 = (c0 + lo) & BN_MASK2; \
+ if (c0 < lo) \
+ tt++; \
+ c1 = (c1 + tt) & BN_MASK2; \
+ if (c1 < tt) \
+ c2++; \
+ c0 = (c0 + lo) & BN_MASK2; \
+ if (c0 < lo) \
+ hi++; \
+ c1 = (c1 + hi) & BN_MASK2; \
+ if (c1 < hi) \
+ c2++; \
+ } while (0)
+
+#define sqr_add_c(a, i, c0, c1, c2) \
+ do { \
+ BN_ULONG lo, hi; \
+ sqr64(lo, hi, (a)[i]); \
+ c0 = (c0 + lo) & BN_MASK2; \
+ if (c0 < lo) \
+ hi++; \
+ c1 = (c1 + hi) & BN_MASK2; \
+ if (c1 < hi) \
+ c2++; \
+ } while (0)
+
+#define sqr_add_c2(a, i, j, c0, c1, c2) mul_add_c2((a)[i], (a)[j], c0, c1, c2)
+#endif /* !BN_LLONG */
+
+void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) {
+ BN_ULONG c1, c2, c3;
+
+ c1 = 0;
+ c2 = 0;
+ c3 = 0;
+ mul_add_c(a[0], b[0], c1, c2, c3);
+ r[0] = c1;
+ c1 = 0;
+ mul_add_c(a[0], b[1], c2, c3, c1);
+ mul_add_c(a[1], b[0], c2, c3, c1);
+ r[1] = c2;
+ c2 = 0;
+ mul_add_c(a[2], b[0], c3, c1, c2);
+ mul_add_c(a[1], b[1], c3, c1, c2);
+ mul_add_c(a[0], b[2], c3, c1, c2);
+ r[2] = c3;
+ c3 = 0;
+ mul_add_c(a[0], b[3], c1, c2, c3);
+ mul_add_c(a[1], b[2], c1, c2, c3);
+ mul_add_c(a[2], b[1], c1, c2, c3);
+ mul_add_c(a[3], b[0], c1, c2, c3);
+ r[3] = c1;
+ c1 = 0;
+ mul_add_c(a[4], b[0], c2, c3, c1);
+ mul_add_c(a[3], b[1], c2, c3, c1);
+ mul_add_c(a[2], b[2], c2, c3, c1);
+ mul_add_c(a[1], b[3], c2, c3, c1);
+ mul_add_c(a[0], b[4], c2, c3, c1);
+ r[4] = c2;
+ c2 = 0;
+ mul_add_c(a[0], b[5], c3, c1, c2);
+ mul_add_c(a[1], b[4], c3, c1, c2);
+ mul_add_c(a[2], b[3], c3, c1, c2);
+ mul_add_c(a[3], b[2], c3, c1, c2);
+ mul_add_c(a[4], b[1], c3, c1, c2);
+ mul_add_c(a[5], b[0], c3, c1, c2);
+ r[5] = c3;
+ c3 = 0;
+ mul_add_c(a[6], b[0], c1, c2, c3);
+ mul_add_c(a[5], b[1], c1, c2, c3);
+ mul_add_c(a[4], b[2], c1, c2, c3);
+ mul_add_c(a[3], b[3], c1, c2, c3);
+ mul_add_c(a[2], b[4], c1, c2, c3);
+ mul_add_c(a[1], b[5], c1, c2, c3);
+ mul_add_c(a[0], b[6], c1, c2, c3);
+ r[6] = c1;
+ c1 = 0;
+ mul_add_c(a[0], b[7], c2, c3, c1);
+ mul_add_c(a[1], b[6], c2, c3, c1);
+ mul_add_c(a[2], b[5], c2, c3, c1);
+ mul_add_c(a[3], b[4], c2, c3, c1);
+ mul_add_c(a[4], b[3], c2, c3, c1);
+ mul_add_c(a[5], b[2], c2, c3, c1);
+ mul_add_c(a[6], b[1], c2, c3, c1);
+ mul_add_c(a[7], b[0], c2, c3, c1);
+ r[7] = c2;
+ c2 = 0;
+ mul_add_c(a[7], b[1], c3, c1, c2);
+ mul_add_c(a[6], b[2], c3, c1, c2);
+ mul_add_c(a[5], b[3], c3, c1, c2);
+ mul_add_c(a[4], b[4], c3, c1, c2);
+ mul_add_c(a[3], b[5], c3, c1, c2);
+ mul_add_c(a[2], b[6], c3, c1, c2);
+ mul_add_c(a[1], b[7], c3, c1, c2);
+ r[8] = c3;
+ c3 = 0;
+ mul_add_c(a[2], b[7], c1, c2, c3);
+ mul_add_c(a[3], b[6], c1, c2, c3);
+ mul_add_c(a[4], b[5], c1, c2, c3);
+ mul_add_c(a[5], b[4], c1, c2, c3);
+ mul_add_c(a[6], b[3], c1, c2, c3);
+ mul_add_c(a[7], b[2], c1, c2, c3);
+ r[9] = c1;
+ c1 = 0;
+ mul_add_c(a[7], b[3], c2, c3, c1);
+ mul_add_c(a[6], b[4], c2, c3, c1);
+ mul_add_c(a[5], b[5], c2, c3, c1);
+ mul_add_c(a[4], b[6], c2, c3, c1);
+ mul_add_c(a[3], b[7], c2, c3, c1);
+ r[10] = c2;
+ c2 = 0;
+ mul_add_c(a[4], b[7], c3, c1, c2);
+ mul_add_c(a[5], b[6], c3, c1, c2);
+ mul_add_c(a[6], b[5], c3, c1, c2);
+ mul_add_c(a[7], b[4], c3, c1, c2);
+ r[11] = c3;
+ c3 = 0;
+ mul_add_c(a[7], b[5], c1, c2, c3);
+ mul_add_c(a[6], b[6], c1, c2, c3);
+ mul_add_c(a[5], b[7], c1, c2, c3);
+ r[12] = c1;
+ c1 = 0;
+ mul_add_c(a[6], b[7], c2, c3, c1);
+ mul_add_c(a[7], b[6], c2, c3, c1);
+ r[13] = c2;
+ c2 = 0;
+ mul_add_c(a[7], b[7], c3, c1, c2);
+ r[14] = c3;
+ r[15] = c1;
+}
+
+void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) {
+ BN_ULONG c1, c2, c3;
+
+ c1 = 0;
+ c2 = 0;
+ c3 = 0;
+ mul_add_c(a[0], b[0], c1, c2, c3);
+ r[0] = c1;
+ c1 = 0;
+ mul_add_c(a[0], b[1], c2, c3, c1);
+ mul_add_c(a[1], b[0], c2, c3, c1);
+ r[1] = c2;
+ c2 = 0;
+ mul_add_c(a[2], b[0], c3, c1, c2);
+ mul_add_c(a[1], b[1], c3, c1, c2);
+ mul_add_c(a[0], b[2], c3, c1, c2);
+ r[2] = c3;
+ c3 = 0;
+ mul_add_c(a[0], b[3], c1, c2, c3);
+ mul_add_c(a[1], b[2], c1, c2, c3);
+ mul_add_c(a[2], b[1], c1, c2, c3);
+ mul_add_c(a[3], b[0], c1, c2, c3);
+ r[3] = c1;
+ c1 = 0;
+ mul_add_c(a[3], b[1], c2, c3, c1);
+ mul_add_c(a[2], b[2], c2, c3, c1);
+ mul_add_c(a[1], b[3], c2, c3, c1);
+ r[4] = c2;
+ c2 = 0;
+ mul_add_c(a[2], b[3], c3, c1, c2);
+ mul_add_c(a[3], b[2], c3, c1, c2);
+ r[5] = c3;
+ c3 = 0;
+ mul_add_c(a[3], b[3], c1, c2, c3);
+ r[6] = c1;
+ r[7] = c2;
+}
+
+void bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a) {
+ BN_ULONG c1, c2, c3;
+
+ c1 = 0;
+ c2 = 0;
+ c3 = 0;
+ sqr_add_c(a, 0, c1, c2, c3);
+ r[0] = c1;
+ c1 = 0;
+ sqr_add_c2(a, 1, 0, c2, c3, c1);
+ r[1] = c2;
+ c2 = 0;
+ sqr_add_c(a, 1, c3, c1, c2);
+ sqr_add_c2(a, 2, 0, c3, c1, c2);
+ r[2] = c3;
+ c3 = 0;
+ sqr_add_c2(a, 3, 0, c1, c2, c3);
+ sqr_add_c2(a, 2, 1, c1, c2, c3);
+ r[3] = c1;
+ c1 = 0;
+ sqr_add_c(a, 2, c2, c3, c1);
+ sqr_add_c2(a, 3, 1, c2, c3, c1);
+ sqr_add_c2(a, 4, 0, c2, c3, c1);
+ r[4] = c2;
+ c2 = 0;
+ sqr_add_c2(a, 5, 0, c3, c1, c2);
+ sqr_add_c2(a, 4, 1, c3, c1, c2);
+ sqr_add_c2(a, 3, 2, c3, c1, c2);
+ r[5] = c3;
+ c3 = 0;
+ sqr_add_c(a, 3, c1, c2, c3);
+ sqr_add_c2(a, 4, 2, c1, c2, c3);
+ sqr_add_c2(a, 5, 1, c1, c2, c3);
+ sqr_add_c2(a, 6, 0, c1, c2, c3);
+ r[6] = c1;
+ c1 = 0;
+ sqr_add_c2(a, 7, 0, c2, c3, c1);
+ sqr_add_c2(a, 6, 1, c2, c3, c1);
+ sqr_add_c2(a, 5, 2, c2, c3, c1);
+ sqr_add_c2(a, 4, 3, c2, c3, c1);
+ r[7] = c2;
+ c2 = 0;
+ sqr_add_c(a, 4, c3, c1, c2);
+ sqr_add_c2(a, 5, 3, c3, c1, c2);
+ sqr_add_c2(a, 6, 2, c3, c1, c2);
+ sqr_add_c2(a, 7, 1, c3, c1, c2);
+ r[8] = c3;
+ c3 = 0;
+ sqr_add_c2(a, 7, 2, c1, c2, c3);
+ sqr_add_c2(a, 6, 3, c1, c2, c3);
+ sqr_add_c2(a, 5, 4, c1, c2, c3);
+ r[9] = c1;
+ c1 = 0;
+ sqr_add_c(a, 5, c2, c3, c1);
+ sqr_add_c2(a, 6, 4, c2, c3, c1);
+ sqr_add_c2(a, 7, 3, c2, c3, c1);
+ r[10] = c2;
+ c2 = 0;
+ sqr_add_c2(a, 7, 4, c3, c1, c2);
+ sqr_add_c2(a, 6, 5, c3, c1, c2);
+ r[11] = c3;
+ c3 = 0;
+ sqr_add_c(a, 6, c1, c2, c3);
+ sqr_add_c2(a, 7, 5, c1, c2, c3);
+ r[12] = c1;
+ c1 = 0;
+ sqr_add_c2(a, 7, 6, c2, c3, c1);
+ r[13] = c2;
+ c2 = 0;
+ sqr_add_c(a, 7, c3, c1, c2);
+ r[14] = c3;
+ r[15] = c1;
+}
+
+void bn_sqr_comba4(BN_ULONG *r, const BN_ULONG *a) {
+ BN_ULONG c1, c2, c3;
+
+ c1 = 0;
+ c2 = 0;
+ c3 = 0;
+ sqr_add_c(a, 0, c1, c2, c3);
+ r[0] = c1;
+ c1 = 0;
+ sqr_add_c2(a, 1, 0, c2, c3, c1);
+ r[1] = c2;
+ c2 = 0;
+ sqr_add_c(a, 1, c3, c1, c2);
+ sqr_add_c2(a, 2, 0, c3, c1, c2);
+ r[2] = c3;
+ c3 = 0;
+ sqr_add_c2(a, 3, 0, c1, c2, c3);
+ sqr_add_c2(a, 2, 1, c1, c2, c3);
+ r[3] = c1;
+ c1 = 0;
+ sqr_add_c(a, 2, c2, c3, c1);
+ sqr_add_c2(a, 3, 1, c2, c3, c1);
+ r[4] = c2;
+ c2 = 0;
+ sqr_add_c2(a, 3, 2, c3, c1, c2);
+ r[5] = c3;
+ c3 = 0;
+ sqr_add_c(a, 3, c1, c2, c3);
+ r[6] = c1;
+ r[7] = c2;
+}
+
+#if defined(OPENSSL_NO_ASM) || (!defined(OPENSSL_ARM) && !defined(OPENSSL_X86_64))
+/* This is essentially reference implementation, which may or may not
+ * result in performance improvement. E.g. on IA-32 this routine was
+ * observed to give 40% faster rsa1024 private key operations and 10%
+ * faster rsa4096 ones, while on AMD64 it improves rsa1024 sign only
+ * by 10% and *worsens* rsa4096 sign by 15%. Once again, it's a
+ * reference implementation, one to be used as starting point for
+ * platform-specific assembler. Mentioned numbers apply to compiler
+ * generated code compiled with and without -DOPENSSL_BN_ASM_MONT and
+ * can vary not only from platform to platform, but even for compiler
+ * versions. Assembler vs. assembler improvement coefficients can
+ * [and are known to] differ and are to be documented elsewhere. */
+int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
+ const BN_ULONG *np, const BN_ULONG *n0p, int num) {
+ BN_ULONG c0, c1, ml, *tp, n0;
+#ifdef mul64
+ BN_ULONG mh;
+#endif
+ volatile BN_ULONG *vp;
+ int i = 0, j;
+
+#if 0 /* template for platform-specific implementation */
+ if (ap==bp) return bn_sqr_mont(rp,ap,np,n0p,num);
+#endif
+ vp = tp = alloca((num + 2) * sizeof(BN_ULONG));
+
+ n0 = *n0p;
+
+ c0 = 0;
+ ml = bp[0];
+#ifdef mul64
+ mh = HBITS(ml);
+ ml = LBITS(ml);
+ for (j = 0; j < num; ++j)
+ mul(tp[j], ap[j], ml, mh, c0);
+#else
+ for (j = 0; j < num; ++j)
+ mul(tp[j], ap[j], ml, c0);
+#endif
+
+ tp[num] = c0;
+ tp[num + 1] = 0;
+ goto enter;
+
+ for (i = 0; i < num; i++) {
+ c0 = 0;
+ ml = bp[i];
+#ifdef mul64
+ mh = HBITS(ml);
+ ml = LBITS(ml);
+ for (j = 0; j < num; ++j)
+ mul_add(tp[j], ap[j], ml, mh, c0);
+#else
+ for (j = 0; j < num; ++j)
+ mul_add(tp[j], ap[j], ml, c0);
+#endif
+ c1 = (tp[num] + c0) & BN_MASK2;
+ tp[num] = c1;
+ tp[num + 1] = (c1 < c0 ? 1 : 0);
+ enter:
+ c1 = tp[0];
+ ml = (c1 * n0) & BN_MASK2;
+ c0 = 0;
+#ifdef mul64
+ mh = HBITS(ml);
+ ml = LBITS(ml);
+ mul_add(c1, np[0], ml, mh, c0);
+#else
+ mul_add(c1, ml, np[0], c0);
+#endif
+ for (j = 1; j < num; j++) {
+ c1 = tp[j];
+#ifdef mul64
+ mul_add(c1, np[j], ml, mh, c0);
+#else
+ mul_add(c1, ml, np[j], c0);
+#endif
+ tp[j - 1] = c1 & BN_MASK2;
+ }
+ c1 = (tp[num] + c0) & BN_MASK2;
+ tp[num - 1] = c1;
+ tp[num] = tp[num + 1] + (c1 < c0 ? 1 : 0);
+ }
+
+ if (tp[num] != 0 || tp[num - 1] >= np[num - 1]) {
+ c0 = bn_sub_words(rp, tp, np, num);
+ if (tp[num] != 0 || c0 == 0) {
+ for (i = 0; i < num + 2; i++)
+ vp[i] = 0;
+ return 1;
+ }
+ }
+ for (i = 0; i < num; i++)
+ rp[i] = tp[i], vp[i] = 0;
+ vp[num] = 0;
+ vp[num + 1] = 0;
+ return 1;
+}
+#endif
+
+#endif
diff --git a/src/crypto/bn/internal.h b/src/crypto/bn/internal.h
new file mode 100644
index 0000000..d421cf3
--- /dev/null
+++ b/src/crypto/bn/internal.h
@@ -0,0 +1,297 @@
+/* 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 OPENSSL_HEADER_BN_INTERNAL_H
+#define OPENSSL_HEADER_BN_INTERNAL_H
+
+#include <openssl/base.h>
+
+#include <inttypes.h>
+
+#if defined(OPENSSL_X86_64) && defined(_MSC_VER) && _MSC_VER >= 1400
+#include <intrin.h>
+#pragma intrinsic(__umulh, _umul128)
+#endif
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/* bn_expand acts the same as |BN_wexpand|, but takes a number of bits rather
+ * than a number of words. */
+BIGNUM *bn_expand(BIGNUM *bn, unsigned bits);
+
+#if defined(OPENSSL_64_BIT)
+
+#if !defined(_MSC_VER)
+/* MSVC doesn't support two-word integers on 64-bit. */
+#define BN_LLONG __int128_t
+#define BN_ULLONG __uint128_t
+#endif
+
+#define BN_BITS 128
+#define BN_BITS2 64
+#define BN_BYTES 8
+#define BN_BITS4 32
+#define BN_MASK (0xffffffffffffffffffffffffffffffffLL)
+#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 "%" PRIu64
+#define BN_DEC_FMT2 "%019" PRIu64
+#define BN_DEC_NUM 19
+#define BN_HEX_FMT1 "%" PRIx64
+
+#elif defined(OPENSSL_32_BIT)
+
+#define BN_LLONG int64_t
+#define BN_ULLONG uint64_t
+#define BN_MASK (0xffffffffffffffffLL)
+#define BN_BITS 64
+#define BN_BITS2 32
+#define BN_BYTES 4
+#define BN_BITS4 16
+#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 "%" PRIu32
+#define BN_DEC_FMT2 "%09" PRIu32
+#define BN_DEC_NUM 9
+#define BN_HEX_FMT1 "%" PRIx32
+
+#else
+#error "Must define either OPENSSL_32_BIT or OPENSSL_64_BIT"
+#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 */
+
+#if defined(BN_LLONG)
+#define Lw(t) (((BN_ULONG)(t))&BN_MASK2)
+#define Hw(t) (((BN_ULONG)((t)>>BN_BITS2))&BN_MASK2)
+#endif
+
+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);
+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);
+
+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_comba8(BN_ULONG *r, const BN_ULONG *a);
+void bn_sqr_comba4(BN_ULONG *r, const BN_ULONG *a);
+
+/* bn_cmp_words returns a value less than, equal to or greater than zero if
+ * the, length |n|, array |a| is less than, equal to or greater than |b|. */
+int bn_cmp_words(const BN_ULONG *a, const BN_ULONG *b, int n);
+
+/* bn_cmp_words returns a value less than, equal to or greater than zero if the
+ * array |a| is less than, equal to or greater than |b|. The arrays can be of
+ * different lengths: |cl| gives the minimum of the two lengths and |dl| gives
+ * the length of |a| minus the length of |b|. */
+int bn_cmp_part_words(const BN_ULONG *a, const BN_ULONG *b, int cl, int dl);
+
+int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
+ const BN_ULONG *np, const BN_ULONG *n0, int num);
+
+#if !defined(BN_LLONG)
+
+#define LBITS(a) ((a) & BN_MASK2l)
+#define HBITS(a) (((a) >> BN_BITS4) & BN_MASK2l)
+#define L2HBITS(a) (((a) << BN_BITS4) & BN_MASK2)
+
+#define LLBITS(a) ((a) & BN_MASKl)
+#define LHBITS(a) (((a) >> BN_BITS2) & BN_MASKl)
+#define LL2HBITS(a) ((BN_ULLONG)((a) & BN_MASKl) << BN_BITS2)
+
+#define mul64(l, h, bl, bh) \
+ { \
+ BN_ULONG m, m1, lt, ht; \
+ \
+ lt = l; \
+ ht = h; \
+ m = (bh) * (lt); \
+ lt = (bl) * (lt); \
+ m1 = (bl) * (ht); \
+ ht = (bh) * (ht); \
+ m = (m + m1) & BN_MASK2; \
+ if (m < m1) \
+ ht += L2HBITS((BN_ULONG)1); \
+ ht += HBITS(m); \
+ m1 = L2HBITS(m); \
+ lt = (lt + m1) & BN_MASK2; \
+ if (lt < m1) \
+ ht++; \
+ (l) = lt; \
+ (h) = ht; \
+ }
+
+#endif /* !defined(BN_LLONG) */
+
+#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64)
+# if defined(__GNUC__) && __GNUC__ >= 2
+# define BN_UMULT_HIGH(a,b) ({ \
+ register BN_ULONG ret,discard; \
+ __asm__ ("mulq %3" \
+ : "=a"(discard),"=d"(ret) \
+ : "a"(a), "g"(b) \
+ : "cc"); \
+ ret; })
+# define BN_UMULT_LOHI(low,high,a,b) \
+ __asm__ ("mulq %3" \
+ : "=a"(low),"=d"(high) \
+ : "a"(a),"g"(b) \
+ : "cc");
+# elif defined(_MSC_VER) && _MSC_VER >= 1400
+# define BN_UMULT_HIGH(a, b) __umulh((a), (b))
+# define BN_UMULT_LOHI(low, high, a, b) ((low) = _umul128((a), (b), &(high)))
+# endif
+#elif !defined(OPENSSL_NO_ASM) && defined(OPENSSL_AARCH64)
+# if defined(__GNUC__) && __GNUC__>=2
+# define BN_UMULT_HIGH(a,b) ({ \
+ register BN_ULONG ret; \
+ __asm__ ("umulh %0,%1,%2" \
+ : "=r"(ret) \
+ : "r"(a), "r"(b)); \
+ ret; })
+# endif
+#endif
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_BN_INTERNAL_H */
diff --git a/src/crypto/bn/kronecker.c b/src/crypto/bn/kronecker.c
new file mode 100644
index 0000000..23ef79a
--- /dev/null
+++ b/src/crypto/bn/kronecker.c
@@ -0,0 +1,175 @@
+/* ====================================================================
+ * 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 <openssl/bn.h>
+
+#include "internal.h"
+
+
+/* least significant word */
+#define BN_lsw(n) (((n)->top == 0) ? (BN_ULONG) 0 : (n)->d[0])
+
+/* Returns -2 for errors because both -1 and 0 are valid results. */
+int BN_kronecker(const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) {
+ int i;
+ int ret = -2;
+ BIGNUM *A, *B, *tmp;
+ /* In 'tab', only odd-indexed entries are relevant:
+ * For any odd BIGNUM n,
+ * tab[BN_lsw(n) & 7]
+ * is $(-1)^{(n^2-1)/8}$ (using TeX notation).
+ * Note that the sign of n does not matter. */
+ static const int tab[8] = {0, 1, 0, -1, 0, -1, 0, 1};
+
+ BN_CTX_start(ctx);
+ A = BN_CTX_get(ctx);
+ B = BN_CTX_get(ctx);
+ if (B == NULL) {
+ goto end;
+ }
+
+ if (!BN_copy(A, a) ||
+ !BN_copy(B, b)) {
+ goto end;
+ }
+
+ /* Kronecker symbol, imlemented according to Henri Cohen,
+ * "A Course in Computational Algebraic Number Theory"
+ * (algorithm 1.4.10). */
+
+ /* Cohen's step 1: */
+
+ if (BN_is_zero(B)) {
+ ret = BN_abs_is_word(A, 1);
+ goto end;
+ }
+
+ /* Cohen's step 2: */
+
+ if (!BN_is_odd(A) && !BN_is_odd(B)) {
+ ret = 0;
+ goto end;
+ }
+
+ /* now B is non-zero */
+ i = 0;
+ while (!BN_is_bit_set(B, i)) {
+ i++;
+ }
+ if (!BN_rshift(B, B, i)) {
+ goto end;
+ }
+ if (i & 1) {
+ /* i is odd */
+ /* (thus B was even, thus A must be odd!) */
+
+ /* set 'ret' to $(-1)^{(A^2-1)/8}$ */
+ ret = tab[BN_lsw(A) & 7];
+ } else {
+ /* i is even */
+ ret = 1;
+ }
+
+ if (B->neg) {
+ B->neg = 0;
+ if (A->neg) {
+ ret = -ret;
+ }
+ }
+
+ /* now B is positive and odd, so what remains to be done is to compute the
+ * Jacobi symbol (A/B) and multiply it by 'ret' */
+
+ while (1) {
+ /* Cohen's step 3: */
+
+ /* B is positive and odd */
+ if (BN_is_zero(A)) {
+ ret = BN_is_one(B) ? ret : 0;
+ goto end;
+ }
+
+ /* now A is non-zero */
+ i = 0;
+ while (!BN_is_bit_set(A, i)) {
+ i++;
+ }
+ if (!BN_rshift(A, A, i)) {
+ goto end;
+ }
+ if (i & 1) {
+ /* i is odd */
+ /* multiply 'ret' by $(-1)^{(B^2-1)/8}$ */
+ ret = ret * tab[BN_lsw(B) & 7];
+ }
+
+ /* Cohen's step 4: */
+ /* multiply 'ret' by $(-1)^{(A-1)(B-1)/4}$ */
+ if ((A->neg ? ~BN_lsw(A) : BN_lsw(A)) & BN_lsw(B) & 2) {
+ ret = -ret;
+ }
+
+ /* (A, B) := (B mod |A|, |A|) */
+ if (!BN_nnmod(B, B, A, ctx)) {
+ ret = -2;
+ goto end;
+ }
+ tmp = A;
+ A = B;
+ B = tmp;
+ tmp->neg = 0;
+ }
+
+end:
+ BN_CTX_end(ctx);
+ return ret;
+}
diff --git a/src/crypto/bn/montgomery.c b/src/crypto/bn/montgomery.c
new file mode 100644
index 0000000..65e177c
--- /dev/null
+++ b/src/crypto/bn/montgomery.c
@@ -0,0 +1,571 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/bn.h>
+
+#include <string.h>
+
+#include <openssl/mem.h>
+#include <openssl/thread.h>
+
+#include "internal.h"
+
+
+#if !defined(OPENSSL_NO_ASM) && \
+ (defined(OPENSSL_X86) || defined(OPENSSL_X86_64))
+#define OPENSSL_BN_ASM_MONT
+#endif
+
+BN_MONT_CTX *BN_MONT_CTX_new(void) {
+ BN_MONT_CTX *ret = OPENSSL_malloc(sizeof(BN_MONT_CTX));
+
+ if (ret == NULL) {
+ return NULL;
+ }
+
+ BN_MONT_CTX_init(ret);
+ ret->flags = BN_FLG_MALLOCED;
+ return ret;
+}
+
+void BN_MONT_CTX_init(BN_MONT_CTX *mont) {
+ memset(mont, 0, sizeof(BN_MONT_CTX));
+ BN_init(&mont->RR);
+ BN_init(&mont->N);
+ BN_init(&mont->Ni);
+}
+
+void BN_MONT_CTX_free(BN_MONT_CTX *mont) {
+ if (mont == NULL) {
+ return;
+ }
+
+ BN_free(&mont->RR);
+ BN_free(&mont->N);
+ BN_free(&mont->Ni);
+ if (mont->flags & BN_FLG_MALLOCED) {
+ OPENSSL_free(mont);
+ }
+}
+
+BN_MONT_CTX *BN_MONT_CTX_copy(BN_MONT_CTX *to, BN_MONT_CTX *from) {
+ if (to == from) {
+ return to;
+ }
+
+ if (!BN_copy(&to->RR, &from->RR) ||
+ !BN_copy(&to->N, &from->N) ||
+ !BN_copy(&to->Ni, &from->Ni)) {
+ return NULL;
+ }
+ to->ri = from->ri;
+ to->n0[0] = from->n0[0];
+ to->n0[1] = from->n0[1];
+ return to;
+}
+
+int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx) {
+ int ret = 0;
+ BIGNUM *Ri, *R;
+ BIGNUM tmod;
+ BN_ULONG buf[2];
+
+ BN_CTX_start(ctx);
+ Ri = BN_CTX_get(ctx);
+ if (Ri == NULL) {
+ goto err;
+ }
+ R = &mont->RR; /* grab RR as a temp */
+ if (!BN_copy(&mont->N, mod)) {
+ goto err; /* Set N */
+ }
+ mont->N.neg = 0;
+
+ BN_init(&tmod);
+ tmod.d = buf;
+ tmod.dmax = 2;
+ tmod.neg = 0;
+
+ mont->ri = (BN_num_bits(mod) + (BN_BITS2 - 1)) / BN_BITS2 * BN_BITS2;
+
+#if defined(OPENSSL_BN_ASM_MONT) && (BN_BITS2 <= 32)
+ /* Only certain BN_BITS2<=32 platforms actually make use of
+ * n0[1], and we could use the #else case (with a shorter R
+ * value) for the others. However, currently only the assembler
+ * files do know which is which. */
+
+ BN_zero(R);
+ if (!BN_set_bit(R, 2 * BN_BITS2)) {
+ goto err;
+ }
+
+ tmod.top = 0;
+ if ((buf[0] = mod->d[0])) {
+ tmod.top = 1;
+ }
+ if ((buf[1] = mod->top > 1 ? mod->d[1] : 0)) {
+ tmod.top = 2;
+ }
+
+ if (BN_mod_inverse(Ri, R, &tmod, ctx) == NULL) {
+ goto err;
+ }
+ if (!BN_lshift(Ri, Ri, 2 * BN_BITS2)) {
+ goto err; /* R*Ri */
+ }
+ if (!BN_is_zero(Ri)) {
+ if (!BN_sub_word(Ri, 1)) {
+ goto err;
+ }
+ } else {
+ /* if N mod word size == 1 */
+ if (bn_expand(Ri, (int)sizeof(BN_ULONG) * 2) == NULL) {
+ goto err;
+ }
+ /* Ri-- (mod double word size) */
+ Ri->neg = 0;
+ Ri->d[0] = BN_MASK2;
+ Ri->d[1] = BN_MASK2;
+ Ri->top = 2;
+ }
+
+ if (!BN_div(Ri, NULL, Ri, &tmod, ctx)) {
+ goto err;
+ }
+ /* Ni = (R*Ri-1)/N,
+ * keep only couple of least significant words: */
+ mont->n0[0] = (Ri->top > 0) ? Ri->d[0] : 0;
+ mont->n0[1] = (Ri->top > 1) ? Ri->d[1] : 0;
+#else
+ BN_zero(R);
+ if (!BN_set_bit(R, BN_BITS2)) {
+ goto err; /* R */
+ }
+
+ buf[0] = mod->d[0]; /* tmod = N mod word size */
+ buf[1] = 0;
+ tmod.top = buf[0] != 0 ? 1 : 0;
+ /* Ri = R^-1 mod N*/
+ if (BN_mod_inverse(Ri, R, &tmod, ctx) == NULL) {
+ goto err;
+ }
+ if (!BN_lshift(Ri, Ri, BN_BITS2)) {
+ goto err; /* R*Ri */
+ }
+ if (!BN_is_zero(Ri)) {
+ if (!BN_sub_word(Ri, 1)) {
+ goto err;
+ }
+ } else {
+ /* if N mod word size == 1 */
+ if (!BN_set_word(Ri, BN_MASK2)) {
+ goto err; /* Ri-- (mod word size) */
+ }
+ }
+ if (!BN_div(Ri, NULL, Ri, &tmod, ctx)) {
+ goto err;
+ }
+ /* Ni = (R*Ri-1)/N,
+ * keep only least significant word: */
+ mont->n0[0] = (Ri->top > 0) ? Ri->d[0] : 0;
+ mont->n0[1] = 0;
+#endif
+
+ /* setup RR for conversions */
+ BN_zero(&(mont->RR));
+ if (!BN_set_bit(&(mont->RR), mont->ri * 2)) {
+ goto err;
+ }
+ if (!BN_mod(&(mont->RR), &(mont->RR), &(mont->N), ctx)) {
+ goto err;
+ }
+
+ ret = 1;
+
+err:
+ BN_CTX_end(ctx);
+ return ret;
+}
+
+BN_MONT_CTX *BN_MONT_CTX_set_locked(BN_MONT_CTX **pmont, int lock,
+ const BIGNUM *mod, BN_CTX *ctx) {
+ BN_MONT_CTX *ret;
+
+ CRYPTO_r_lock(lock);
+ ret = *pmont;
+ CRYPTO_r_unlock(lock);
+ if (ret) {
+ return ret;
+ }
+
+ /* We don't want to serialise globally while doing our lazy-init math in
+ * BN_MONT_CTX_set. That punishes threads that are doing independent
+ * things. Instead, punish the case where more than one thread tries to
+ * lazy-init the same 'pmont', by having each do the lazy-init math work
+ * independently and only use the one from the thread that wins the race
+ * (the losers throw away the work they've done). */
+ ret = BN_MONT_CTX_new();
+ if (!ret) {
+ return NULL;
+ }
+ if (!BN_MONT_CTX_set(ret, mod, ctx)) {
+ BN_MONT_CTX_free(ret);
+ return NULL;
+ }
+
+ /* The locked compare-and-set, after the local work is done. */
+ CRYPTO_w_lock(lock);
+ if (*pmont) {
+ BN_MONT_CTX_free(ret);
+ ret = *pmont;
+ } else {
+ *pmont = ret;
+ }
+
+ CRYPTO_w_unlock(lock);
+
+ return ret;
+}
+
+int BN_to_montgomery(BIGNUM *ret, const BIGNUM *a, const BN_MONT_CTX *mont,
+ BN_CTX *ctx) {
+ return BN_mod_mul_montgomery(ret, a, &mont->RR, mont, ctx);
+}
+
+#if 0
+static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r,
+ const BN_MONT_CTX *mont) {
+ const BIGNUM *n;
+ BN_ULONG *ap, *np, *rp, n0, v, carry;
+ int nl, max, i;
+
+ n = &mont->N;
+ nl = n->top;
+ if (nl == 0) {
+ ret->top = 0;
+ return 1;
+ }
+
+ max = (2 * nl); /* carry is stored separately */
+ if (bn_wexpand(r, max) == NULL) {
+ return 0;
+ }
+
+ r->neg ^= n->neg;
+ np = n->d;
+ rp = r->d;
+
+ /* clear the top words of T */
+ if (max > r->top) {
+ memset(&rp[r->top], 0, (max - r->top) * sizeof(BN_ULONG));
+ }
+
+ r->top = max;
+ n0 = mont->n0[0];
+
+ for (carry = 0, i = 0; i < nl; i++, rp++) {
+ v = bn_mul_add_words(rp, np, nl, (rp[0] * n0) & BN_MASK2);
+ v = (v + carry + rp[nl]) & BN_MASK2;
+ carry |= (v != rp[nl]);
+ carry &= (v <= rp[nl]);
+ rp[nl] = v;
+ }
+
+ if (bn_wexpand(ret, nl) == NULL) {
+ return 0;
+ }
+ ret->top = nl;
+ ret->neg = r->neg;
+
+ rp = ret->d;
+ ap = &(r->d[nl]);
+
+ {
+ BN_ULONG *nrp;
+ size_t m;
+
+ v = bn_sub_words(rp, ap, np, nl) - carry;
+ /* if subtraction result is real, then trick unconditional memcpy below to
+ * perform in-place "refresh" instead of actual copy. */
+ m = (0 - (size_t)v);
+ nrp = (BN_ULONG *)(((intptr_t)rp & ~m) | ((intptr_t)ap & m));
+
+ for (i = 0, nl -= 4; i < nl; i += 4) {
+ BN_ULONG t1, t2, t3, t4;
+
+ t1 = nrp[i + 0];
+ t2 = nrp[i + 1];
+ t3 = nrp[i + 2];
+ ap[i + 0] = 0;
+ t4 = nrp[i + 3];
+ ap[i + 1] = 0;
+ rp[i + 0] = t1;
+ ap[i + 2] = 0;
+ rp[i + 1] = t2;
+ ap[i + 3] = 0;
+ rp[i + 2] = t3;
+ rp[i + 3] = t4;
+ }
+
+ for (nl += 4; i < nl; i++) {
+ rp[i] = nrp[i], ap[i] = 0;
+ }
+ }
+
+ bn_correct_top(r);
+ bn_correct_top(ret);
+
+ return 1;
+}
+#endif
+
+#define PTR_SIZE_INT size_t
+
+static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, const BN_MONT_CTX *mont)
+ {
+ BIGNUM *n;
+ BN_ULONG *ap,*np,*rp,n0,v,carry;
+ int nl,max,i;
+
+ n= (BIGNUM*) &(mont->N);
+ nl=n->top;
+ if (nl == 0) { ret->top=0; return(1); }
+
+ max=(2*nl); /* carry is stored separately */
+ if (bn_wexpand(r,max) == NULL) return(0);
+
+ r->neg^=n->neg;
+ np=n->d;
+ rp=r->d;
+
+ /* clear the top words of T */
+#if 1
+ for (i=r->top; i<max; i++) /* memset? XXX */
+ rp[i]=0;
+#else
+ memset(&(rp[r->top]),0,(max-r->top)*sizeof(BN_ULONG));
+#endif
+
+ r->top=max;
+ n0=mont->n0[0];
+
+ for (carry=0, i=0; i<nl; i++, rp++)
+ {
+ v=bn_mul_add_words(rp,np,nl,(rp[0]*n0)&BN_MASK2);
+ v = (v+carry+rp[nl])&BN_MASK2;
+ carry |= (v != rp[nl]);
+ carry &= (v <= rp[nl]);
+ rp[nl]=v;
+ }
+
+ if (bn_wexpand(ret,nl) == NULL) return(0);
+ ret->top=nl;
+ ret->neg=r->neg;
+
+ rp=ret->d;
+ ap=&(r->d[nl]);
+
+ {
+ BN_ULONG *nrp;
+ size_t m;
+
+ v=bn_sub_words(rp,ap,np,nl)-carry;
+ /* if subtraction result is real, then
+ * trick unconditional memcpy below to perform in-place
+ * "refresh" instead of actual copy. */
+ m=(0-(size_t)v);
+ nrp=(BN_ULONG *)(((PTR_SIZE_INT)rp&~m)|((PTR_SIZE_INT)ap&m));
+
+ for (i=0,nl-=4; i<nl; i+=4)
+ {
+ BN_ULONG t1,t2,t3,t4;
+
+ t1=nrp[i+0];
+ t2=nrp[i+1];
+ t3=nrp[i+2]; ap[i+0]=0;
+ t4=nrp[i+3]; ap[i+1]=0;
+ rp[i+0]=t1; ap[i+2]=0;
+ rp[i+1]=t2; ap[i+3]=0;
+ rp[i+2]=t3;
+ rp[i+3]=t4;
+ }
+ for (nl+=4; i<nl; i++)
+ rp[i]=nrp[i], ap[i]=0;
+ }
+ bn_correct_top(r);
+ bn_correct_top(ret);
+
+ return(1);
+ }
+
+int BN_from_montgomery(BIGNUM *ret, const BIGNUM *a, const BN_MONT_CTX *mont,
+ BN_CTX *ctx) {
+ int retn = 0;
+ BIGNUM *t;
+
+ BN_CTX_start(ctx);
+ t = BN_CTX_get(ctx);
+ if (t == NULL) {
+ return 0;
+ }
+
+ if (BN_copy(t, a))
+ retn = BN_from_montgomery_word(ret, t, mont);
+ BN_CTX_end(ctx);
+
+ return retn;
+}
+
+int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+ const BN_MONT_CTX *mont, BN_CTX *ctx) {
+ BIGNUM *tmp;
+ int ret = 0;
+
+#if defined(OPENSSL_BN_ASM_MONT)
+ int num = mont->N.top;
+
+ if (num > 1 && a->top == num && b->top == num) {
+ if (bn_wexpand(r, num) == NULL) {
+ return 0;
+ }
+ if (bn_mul_mont(r->d, a->d, b->d, mont->N.d, mont->n0, num)) {
+ r->neg = a->neg ^ b->neg;
+ r->top = num;
+ bn_correct_top(r);
+ return 1;
+ }
+ }
+#endif
+
+ BN_CTX_start(ctx);
+ tmp = BN_CTX_get(ctx);
+ if (tmp == 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_from_montgomery_word(r, tmp, mont)) {
+ goto err;
+ }
+
+ ret = 1;
+
+err:
+ BN_CTX_end(ctx);
+ return ret;
+}
diff --git a/src/crypto/bn/mul.c b/src/crypto/bn/mul.c
new file mode 100644
index 0000000..80c6288
--- /dev/null
+++ b/src/crypto/bn/mul.c
@@ -0,0 +1,886 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/bn.h>
+
+#include <assert.h>
+#include <string.h>
+
+#include "internal.h"
+
+
+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;
+ }
+}
+
+void bn_mul_low_normal(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n) {
+ bn_mul_words(r, a, n, b[0]);
+
+ for (;;) {
+ if (--n <= 0) {
+ return;
+ }
+ bn_mul_add_words(&(r[1]), a, n, b[1]);
+ if (--n <= 0) {
+ return;
+ }
+ bn_mul_add_words(&(r[2]), a, n, b[2]);
+ if (--n <= 0) {
+ return;
+ }
+ bn_mul_add_words(&(r[3]), a, n, b[3]);
+ if (--n <= 0) {
+ return;
+ }
+ bn_mul_add_words(&(r[4]), a, n, b[4]);
+ r += 4;
+ b += 4;
+ }
+}
+
+#if !defined(OPENSSL_X86) || defined(OPENSSL_NO_ASM)
+/* Here follows specialised variants of bn_add_words() and bn_sub_words(). They
+ * have the property performing operations on arrays of different sizes. The
+ * sizes of those arrays is expressed through cl, which is the common length (
+ * basicall, min(len(a),len(b)) ), and dl, which is the delta between the two
+ * lengths, calculated as len(a)-len(b). All lengths are the number of
+ * BN_ULONGs... For the operations that require a result array as parameter,
+ * it must have the length cl+abs(dl). These functions should probably end up
+ * in bn_asm.c as soon as there are assembler counterparts for the systems that
+ * use assembler files. */
+
+static BN_ULONG bn_sub_part_words(BN_ULONG *r, const BN_ULONG *a,
+ const BN_ULONG *b, int cl, int dl) {
+ BN_ULONG c, t;
+
+ assert(cl >= 0);
+ c = bn_sub_words(r, a, b, cl);
+
+ if (dl == 0)
+ return c;
+
+ r += cl;
+ a += cl;
+ b += cl;
+
+ if (dl < 0) {
+ for (;;) {
+ t = b[0];
+ r[0] = (0 - t - c) & BN_MASK2;
+ if (t != 0) {
+ c = 1;
+ }
+ if (++dl >= 0) {
+ break;
+ }
+
+ t = b[1];
+ r[1] = (0 - t - c) & BN_MASK2;
+ if (t != 0) {
+ c = 1;
+ }
+ if (++dl >= 0) {
+ break;
+ }
+
+ t = b[2];
+ r[2] = (0 - t - c) & BN_MASK2;
+ if (t != 0) {
+ c = 1;
+ }
+ if (++dl >= 0) {
+ break;
+ }
+
+ t = b[3];
+ r[3] = (0 - t - c) & BN_MASK2;
+ if (t != 0) {
+ c = 1;
+ }
+ if (++dl >= 0) {
+ break;
+ }
+
+ b += 4;
+ r += 4;
+ }
+ } else {
+ int save_dl = dl;
+ while (c) {
+ t = a[0];
+ r[0] = (t - c) & BN_MASK2;
+ if (t != 0) {
+ c = 0;
+ }
+ if (--dl <= 0) {
+ break;
+ }
+
+ t = a[1];
+ r[1] = (t - c) & BN_MASK2;
+ if (t != 0) {
+ c = 0;
+ }
+ if (--dl <= 0) {
+ break;
+ }
+
+ t = a[2];
+ r[2] = (t - c) & BN_MASK2;
+ if (t != 0) {
+ c = 0;
+ }
+ if (--dl <= 0) {
+ break;
+ }
+
+ t = a[3];
+ r[3] = (t - c) & BN_MASK2;
+ if (t != 0) {
+ c = 0;
+ }
+ if (--dl <= 0) {
+ break;
+ }
+
+ save_dl = dl;
+ a += 4;
+ r += 4;
+ }
+ if (dl > 0) {
+ if (save_dl > dl) {
+ switch (save_dl - dl) {
+ case 1:
+ r[1] = a[1];
+ if (--dl <= 0) {
+ break;
+ }
+ case 2:
+ r[2] = a[2];
+ if (--dl <= 0) {
+ break;
+ }
+ case 3:
+ r[3] = a[3];
+ if (--dl <= 0) {
+ break;
+ }
+ }
+ a += 4;
+ r += 4;
+ }
+ }
+
+ if (dl > 0) {
+ for (;;) {
+ r[0] = a[0];
+ if (--dl <= 0) {
+ break;
+ }
+ r[1] = a[1];
+ if (--dl <= 0) {
+ break;
+ }
+ r[2] = a[2];
+ if (--dl <= 0) {
+ break;
+ }
+ r[3] = a[3];
+ if (--dl <= 0) {
+ break;
+ }
+
+ a += 4;
+ r += 4;
+ }
+ }
+ }
+
+ return c;
+}
+#else
+/* On other platforms the function is defined in asm. */
+BN_ULONG bn_sub_part_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
+ int cl, int dl);
+#endif
+
+/* Karatsuba recursive multiplication algorithm
+ * (cf. Knuth, The Art of Computer Programming, Vol. 2) */
+
+/* r is 2*n2 words in size,
+ * a and b are both n2 words in size.
+ * n2 must be a power of 2.
+ * We multiply and return the result.
+ * t must be 2*n2 words in size
+ * We calculate
+ * a[0]*b[0]
+ * a[0]*b[0]+a[1]*b[1]+(a[0]-a[1])*(b[1]-b[0])
+ * a[1]*b[1]
+ */
+/* dnX may not be positive, but n2/2+dnX has to be */
+static void bn_mul_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2,
+ int dna, int dnb, BN_ULONG *t) {
+ int n = n2 / 2, c1, c2;
+ int tna = n + dna, tnb = n + dnb;
+ unsigned int neg, zero;
+ BN_ULONG ln, lo, *p;
+
+ /* Only call bn_mul_comba 8 if n2 == 8 and the
+ * two arrays are complete [steve]
+ */
+ if (n2 == 8 && dna == 0 && dnb == 0) {
+ bn_mul_comba8(r, a, b);
+ return;
+ }
+
+ /* Else do normal multiply */
+ if (n2 < BN_MUL_RECURSIVE_SIZE_NORMAL) {
+ bn_mul_normal(r, a, n2 + dna, b, n2 + dnb);
+ if ((dna + dnb) < 0)
+ memset(&r[2 * n2 + dna + dnb], 0, sizeof(BN_ULONG) * -(dna + dnb));
+ return;
+ }
+
+ /* r=(a[0]-a[1])*(b[1]-b[0]) */
+ c1 = bn_cmp_part_words(a, &(a[n]), tna, n - tna);
+ c2 = bn_cmp_part_words(&(b[n]), b, tnb, tnb - n);
+ zero = neg = 0;
+ switch (c1 * 3 + c2) {
+ case -4:
+ bn_sub_part_words(t, &(a[n]), a, tna, tna - n); /* - */
+ bn_sub_part_words(&(t[n]), b, &(b[n]), tnb, n - tnb); /* - */
+ break;
+ case -3:
+ zero = 1;
+ break;
+ case -2:
+ bn_sub_part_words(t, &(a[n]), a, tna, tna - n); /* - */
+ bn_sub_part_words(&(t[n]), &(b[n]), b, tnb, tnb - n); /* + */
+ neg = 1;
+ break;
+ case -1:
+ case 0:
+ case 1:
+ zero = 1;
+ break;
+ case 2:
+ bn_sub_part_words(t, a, &(a[n]), tna, n - tna); /* + */
+ bn_sub_part_words(&(t[n]), b, &(b[n]), tnb, n - tnb); /* - */
+ neg = 1;
+ break;
+ case 3:
+ zero = 1;
+ break;
+ case 4:
+ bn_sub_part_words(t, a, &(a[n]), tna, n - tna);
+ bn_sub_part_words(&(t[n]), &(b[n]), b, tnb, tnb - n);
+ break;
+ }
+
+ if (n == 4 && dna == 0 && dnb == 0) {
+ /* XXX: bn_mul_comba4 could take extra args to do this well */
+ if (!zero) {
+ bn_mul_comba4(&(t[n2]), t, &(t[n]));
+ } else {
+ memset(&(t[n2]), 0, 8 * sizeof(BN_ULONG));
+ }
+
+ bn_mul_comba4(r, a, b);
+ bn_mul_comba4(&(r[n2]), &(a[n]), &(b[n]));
+ } else if (n == 8 && dna == 0 && dnb == 0) {
+ /* XXX: bn_mul_comba8 could take extra args to do this well */
+ if (!zero) {
+ bn_mul_comba8(&(t[n2]), t, &(t[n]));
+ } else {
+ memset(&(t[n2]), 0, 16 * sizeof(BN_ULONG));
+ }
+
+ bn_mul_comba8(r, a, b);
+ bn_mul_comba8(&(r[n2]), &(a[n]), &(b[n]));
+ } else {
+ p = &(t[n2 * 2]);
+ if (!zero) {
+ bn_mul_recursive(&(t[n2]), t, &(t[n]), n, 0, 0, p);
+ } else {
+ memset(&(t[n2]), 0, n2 * sizeof(BN_ULONG));
+ }
+ bn_mul_recursive(r, a, b, n, 0, 0, p);
+ bn_mul_recursive(&(r[n2]), &(a[n]), &(b[n]), n, dna, dnb, p);
+ }
+
+ /* t[32] holds (a[0]-a[1])*(b[1]-b[0]), c1 is the sign
+ * r[10] holds (a[0]*b[0])
+ * r[32] holds (b[1]*b[1]) */
+
+ c1 = (int)(bn_add_words(t, r, &(r[n2]), n2));
+
+ if (neg) {
+ /* if t[32] is negative */
+ c1 -= (int)(bn_sub_words(&(t[n2]), t, &(t[n2]), n2));
+ } else {
+ /* Might have a carry */
+ c1 += (int)(bn_add_words(&(t[n2]), &(t[n2]), t, n2));
+ }
+
+ /* t[32] holds (a[0]-a[1])*(b[1]-b[0])+(a[0]*b[0])+(a[1]*b[1])
+ * r[10] holds (a[0]*b[0])
+ * r[32] holds (b[1]*b[1])
+ * c1 holds the carry bits */
+ c1 += (int)(bn_add_words(&(r[n]), &(r[n]), &(t[n2]), n2));
+ if (c1) {
+ p = &(r[n + n2]);
+ lo = *p;
+ ln = (lo + c1) & BN_MASK2;
+ *p = ln;
+
+ /* The overflow will stop before we over write
+ * words we should not overwrite */
+ if (ln < (BN_ULONG)c1) {
+ do {
+ p++;
+ lo = *p;
+ ln = (lo + 1) & BN_MASK2;
+ *p = ln;
+ } while (ln == 0);
+ }
+ }
+}
+
+/* n+tn is the word length
+ * t needs to be n*4 is size, as does r */
+/* tnX may not be negative but less than n */
+static void bn_mul_part_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n,
+ int tna, int tnb, BN_ULONG *t) {
+ int i, j, n2 = n * 2;
+ int c1, c2, neg;
+ BN_ULONG ln, lo, *p;
+
+ if (n < 8) {
+ bn_mul_normal(r, a, n + tna, b, n + tnb);
+ return;
+ }
+
+ /* r=(a[0]-a[1])*(b[1]-b[0]) */
+ c1 = bn_cmp_part_words(a, &(a[n]), tna, n - tna);
+ c2 = bn_cmp_part_words(&(b[n]), b, tnb, tnb - n);
+ neg = 0;
+ switch (c1 * 3 + c2) {
+ case -4:
+ bn_sub_part_words(t, &(a[n]), a, tna, tna - n); /* - */
+ bn_sub_part_words(&(t[n]), b, &(b[n]), tnb, n - tnb); /* - */
+ break;
+ case -3:
+ /* break; */
+ case -2:
+ bn_sub_part_words(t, &(a[n]), a, tna, tna - n); /* - */
+ bn_sub_part_words(&(t[n]), &(b[n]), b, tnb, tnb - n); /* + */
+ neg = 1;
+ break;
+ case -1:
+ case 0:
+ case 1:
+ /* break; */
+ case 2:
+ bn_sub_part_words(t, a, &(a[n]), tna, n - tna); /* + */
+ bn_sub_part_words(&(t[n]), b, &(b[n]), tnb, n - tnb); /* - */
+ neg = 1;
+ break;
+ case 3:
+ /* break; */
+ case 4:
+ bn_sub_part_words(t, a, &(a[n]), tna, n - tna);
+ bn_sub_part_words(&(t[n]), &(b[n]), b, tnb, tnb - n);
+ break;
+ }
+
+ if (n == 8) {
+ bn_mul_comba8(&(t[n2]), t, &(t[n]));
+ bn_mul_comba8(r, a, b);
+ bn_mul_normal(&(r[n2]), &(a[n]), tna, &(b[n]), tnb);
+ memset(&(r[n2 + tna + tnb]), 0, sizeof(BN_ULONG) * (n2 - tna - tnb));
+ } else {
+ p = &(t[n2 * 2]);
+ bn_mul_recursive(&(t[n2]), t, &(t[n]), n, 0, 0, p);
+ bn_mul_recursive(r, a, b, n, 0, 0, p);
+ i = n / 2;
+ /* If there is only a bottom half to the number,
+ * just do it */
+ if (tna > tnb) {
+ j = tna - i;
+ } else {
+ j = tnb - i;
+ }
+
+ if (j == 0) {
+ bn_mul_recursive(&(r[n2]), &(a[n]), &(b[n]), i, tna - i, tnb - i, p);
+ memset(&(r[n2 + i * 2]), 0, sizeof(BN_ULONG) * (n2 - i * 2));
+ } else if (j > 0) {
+ /* eg, n == 16, i == 8 and tn == 11 */
+ bn_mul_part_recursive(&(r[n2]), &(a[n]), &(b[n]), i, tna - i, tnb - i, p);
+ memset(&(r[n2 + tna + tnb]), 0, sizeof(BN_ULONG) * (n2 - tna - tnb));
+ } else {
+ /* (j < 0) eg, n == 16, i == 8 and tn == 5 */
+ memset(&(r[n2]), 0, sizeof(BN_ULONG) * n2);
+ if (tna < BN_MUL_RECURSIVE_SIZE_NORMAL &&
+ tnb < BN_MUL_RECURSIVE_SIZE_NORMAL) {
+ bn_mul_normal(&(r[n2]), &(a[n]), tna, &(b[n]), tnb);
+ } else {
+ for (;;) {
+ i /= 2;
+ /* these simplified conditions work
+ * exclusively because difference
+ * between tna and tnb is 1 or 0 */
+ if (i < tna || i < tnb) {
+ bn_mul_part_recursive(&(r[n2]), &(a[n]), &(b[n]), i, tna - i,
+ tnb - i, p);
+ break;
+ } else if (i == tna || i == tnb) {
+ bn_mul_recursive(&(r[n2]), &(a[n]), &(b[n]), i, tna - i, tnb - i,
+ p);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ /* t[32] holds (a[0]-a[1])*(b[1]-b[0]), c1 is the sign
+ * r[10] holds (a[0]*b[0])
+ * r[32] holds (b[1]*b[1])
+ */
+
+ c1 = (int)(bn_add_words(t, r, &(r[n2]), n2));
+
+ if (neg) {
+ /* if t[32] is negative */
+ c1 -= (int)(bn_sub_words(&(t[n2]), t, &(t[n2]), n2));
+ } else {
+ /* Might have a carry */
+ c1 += (int)(bn_add_words(&(t[n2]), &(t[n2]), t, n2));
+ }
+
+ /* t[32] holds (a[0]-a[1])*(b[1]-b[0])+(a[0]*b[0])+(a[1]*b[1])
+ * r[10] holds (a[0]*b[0])
+ * r[32] holds (b[1]*b[1])
+ * c1 holds the carry bits */
+ c1 += (int)(bn_add_words(&(r[n]), &(r[n]), &(t[n2]), n2));
+ if (c1) {
+ p = &(r[n + n2]);
+ lo = *p;
+ ln = (lo + c1) & BN_MASK2;
+ *p = ln;
+
+ /* The overflow will stop before we over write
+ * words we should not overwrite */
+ if (ln < (BN_ULONG)c1) {
+ do {
+ p++;
+ lo = *p;
+ ln = (lo + 1) & BN_MASK2;
+ *p = ln;
+ } while (ln == 0);
+ }
+ }
+}
+
+int BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) {
+ int ret = 0;
+ int top, al, bl;
+ BIGNUM *rr;
+ int i;
+ BIGNUM *t = NULL;
+ int j = 0, k;
+
+ al = a->top;
+ bl = b->top;
+
+ if ((al == 0) || (bl == 0)) {
+ BN_zero(r);
+ return 1;
+ }
+ top = al + bl;
+
+ BN_CTX_start(ctx);
+ if ((r == a) || (r == b)) {
+ if ((rr = BN_CTX_get(ctx)) == NULL) {
+ goto err;
+ }
+ } else {
+ rr = r;
+ }
+ rr->neg = a->neg ^ b->neg;
+
+ i = al - bl;
+ if (i == 0) {
+ if (al == 8) {
+ if (bn_wexpand(rr, 16) == NULL) {
+ goto err;
+ }
+ rr->top = 16;
+ bn_mul_comba8(rr->d, a->d, b->d);
+ goto end;
+ }
+ }
+
+ if ((al >= BN_MULL_SIZE_NORMAL) && (bl >= BN_MULL_SIZE_NORMAL)) {
+ if (i >= -1 && i <= 1) {
+ /* Find out the power of two lower or equal
+ to the longest of the two numbers */
+ if (i >= 0) {
+ j = BN_num_bits_word((BN_ULONG)al);
+ }
+ if (i == -1) {
+ j = BN_num_bits_word((BN_ULONG)bl);
+ }
+ j = 1 << (j - 1);
+ assert(j <= al || j <= bl);
+ k = j + j;
+ t = BN_CTX_get(ctx);
+ if (t == NULL) {
+ goto err;
+ }
+ if (al > j || bl > j) {
+ if (bn_wexpand(t, k * 4) == NULL) {
+ goto err;
+ }
+ if (bn_wexpand(rr, k * 4) == NULL) {
+ goto err;
+ }
+ bn_mul_part_recursive(rr->d, a->d, b->d, j, al - j, bl - j, t->d);
+ } else {
+ /* al <= j || bl <= j */
+ if (bn_wexpand(t, k * 2) == NULL) {
+ goto err;
+ }
+ if (bn_wexpand(rr, k * 2) == NULL) {
+ goto err;
+ }
+ bn_mul_recursive(rr->d, a->d, b->d, j, al - j, bl - j, t->d);
+ }
+ rr->top = top;
+ goto end;
+ }
+ }
+
+ if (bn_wexpand(rr, top) == NULL) {
+ goto err;
+ }
+ rr->top = top;
+ bn_mul_normal(rr->d, a->d, al, b->d, bl);
+
+end:
+ bn_correct_top(rr);
+ if (r != rr) {
+ BN_copy(r, rr);
+ }
+ ret = 1;
+
+err:
+ BN_CTX_end(ctx);
+ return ret;
+}
+
+/* tmp must have 2*n words */
+static void bn_sqr_normal(BN_ULONG *r, const BN_ULONG *a, int n, BN_ULONG *tmp) {
+ int i, j, max;
+ const BN_ULONG *ap;
+ BN_ULONG *rp;
+
+ max = n * 2;
+ ap = a;
+ rp = r;
+ rp[0] = rp[max - 1] = 0;
+ rp++;
+ j = n;
+
+ if (--j > 0) {
+ ap++;
+ rp[j] = bn_mul_words(rp, ap, j, ap[-1]);
+ rp += 2;
+ }
+
+ for (i = n - 2; i > 0; i--) {
+ j--;
+ ap++;
+ rp[j] = bn_mul_add_words(rp, ap, j, ap[-1]);
+ rp += 2;
+ }
+
+ bn_add_words(r, r, r, max);
+
+ /* There will not be a carry */
+
+ bn_sqr_words(tmp, a, n);
+
+ bn_add_words(r, r, tmp, max);
+}
+
+/* r is 2*n words in size,
+ * a and b are both n words in size. (There's not actually a 'b' here ...)
+ * n must be a power of 2.
+ * We multiply and return the result.
+ * t must be 2*n words in size
+ * We calculate
+ * a[0]*b[0]
+ * a[0]*b[0]+a[1]*b[1]+(a[0]-a[1])*(b[1]-b[0])
+ * a[1]*b[1]
+ */
+static void bn_sqr_recursive(BN_ULONG *r, const BN_ULONG *a, int n2, BN_ULONG *t) {
+ int n = n2 / 2;
+ int zero, c1;
+ BN_ULONG ln, lo, *p;
+
+ if (n2 == 4) {
+ bn_sqr_comba4(r, a);
+ return;
+ } else if (n2 == 8) {
+ bn_sqr_comba8(r, a);
+ return;
+ }
+ if (n2 < BN_SQR_RECURSIVE_SIZE_NORMAL) {
+ bn_sqr_normal(r, a, n2, t);
+ return;
+ }
+ /* r=(a[0]-a[1])*(a[1]-a[0]) */
+ c1 = bn_cmp_words(a, &(a[n]), n);
+ zero = 0;
+ if (c1 > 0) {
+ bn_sub_words(t, a, &(a[n]), n);
+ } else if (c1 < 0) {
+ bn_sub_words(t, &(a[n]), a, n);
+ } else {
+ zero = 1;
+ }
+
+ /* The result will always be negative unless it is zero */
+ p = &(t[n2 * 2]);
+
+ if (!zero) {
+ bn_sqr_recursive(&(t[n2]), t, n, p);
+ } else {
+ memset(&(t[n2]), 0, n2 * sizeof(BN_ULONG));
+ }
+ bn_sqr_recursive(r, a, n, p);
+ bn_sqr_recursive(&(r[n2]), &(a[n]), n, p);
+
+ /* t[32] holds (a[0]-a[1])*(a[1]-a[0]), it is negative or zero
+ * r[10] holds (a[0]*b[0])
+ * r[32] holds (b[1]*b[1]) */
+
+ c1 = (int)(bn_add_words(t, r, &(r[n2]), n2));
+
+ /* t[32] is negative */
+ c1 -= (int)(bn_sub_words(&(t[n2]), t, &(t[n2]), n2));
+
+ /* t[32] holds (a[0]-a[1])*(a[1]-a[0])+(a[0]*a[0])+(a[1]*a[1])
+ * r[10] holds (a[0]*a[0])
+ * r[32] holds (a[1]*a[1])
+ * c1 holds the carry bits */
+ c1 += (int)(bn_add_words(&(r[n]), &(r[n]), &(t[n2]), n2));
+ if (c1) {
+ p = &(r[n + n2]);
+ lo = *p;
+ ln = (lo + c1) & BN_MASK2;
+ *p = ln;
+
+ /* The overflow will stop before we over write
+ * words we should not overwrite */
+ if (ln < (BN_ULONG)c1) {
+ do {
+ p++;
+ lo = *p;
+ ln = (lo + 1) & BN_MASK2;
+ *p = ln;
+ } while (ln == 0);
+ }
+ }
+}
+
+int BN_mul_word(BIGNUM *bn, BN_ULONG w) {
+ BN_ULONG ll;
+
+ w &= BN_MASK2;
+ if (!bn->top) {
+ return 1;
+ }
+
+ if (w == 0) {
+ BN_zero(bn);
+ return 1;
+ }
+
+ ll = bn_mul_words(bn->d, bn->d, bn->top, w);
+ if (ll) {
+ if (bn_wexpand(bn, bn->top + 1) == NULL) {
+ return 0;
+ }
+ bn->d[bn->top++] = ll;
+ }
+
+ return 1;
+}
+
+int BN_sqr(BIGNUM *r, const BIGNUM *a, BN_CTX *ctx) {
+ int max, al;
+ int ret = 0;
+ BIGNUM *tmp, *rr;
+
+ al = a->top;
+ if (al <= 0) {
+ r->top = 0;
+ r->neg = 0;
+ return 1;
+ }
+
+ BN_CTX_start(ctx);
+ rr = (a != r) ? r : BN_CTX_get(ctx);
+ tmp = BN_CTX_get(ctx);
+ if (!rr || !tmp) {
+ goto err;
+ }
+
+ max = 2 * al; /* Non-zero (from above) */
+ if (bn_wexpand(rr, max) == NULL) {
+ goto err;
+ }
+
+ if (al == 4) {
+ bn_sqr_comba4(rr->d, a->d);
+ } else if (al == 8) {
+ bn_sqr_comba8(rr->d, a->d);
+ } else {
+ if (al < BN_SQR_RECURSIVE_SIZE_NORMAL) {
+ BN_ULONG t[BN_SQR_RECURSIVE_SIZE_NORMAL * 2];
+ bn_sqr_normal(rr->d, a->d, al, t);
+ } else {
+ int j, k;
+
+ j = BN_num_bits_word((BN_ULONG)al);
+ j = 1 << (j - 1);
+ k = j + j;
+ if (al == j) {
+ if (bn_wexpand(tmp, k * 2) == NULL) {
+ goto err;
+ }
+ bn_sqr_recursive(rr->d, a->d, al, tmp->d);
+ } else {
+ if (bn_wexpand(tmp, max) == NULL) {
+ goto err;
+ }
+ bn_sqr_normal(rr->d, a->d, al, tmp->d);
+ }
+ }
+ }
+
+ rr->neg = 0;
+ /* If the most-significant half of the top word of 'a' is zero, then
+ * the square of 'a' will max-1 words. */
+ if (a->d[al - 1] == (a->d[al - 1] & BN_MASK2l)) {
+ rr->top = max - 1;
+ } else {
+ rr->top = max;
+ }
+
+ if (rr != r) {
+ BN_copy(r, rr);
+ }
+ ret = 1;
+
+err:
+ BN_CTX_end(ctx);
+ return ret;
+}
diff --git a/src/crypto/bn/prime.c b/src/crypto/bn/prime.c
new file mode 100644
index 0000000..fc9a3d5
--- /dev/null
+++ b/src/crypto/bn/prime.c
@@ -0,0 +1,838 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/bn.h>
+
+#include <openssl/err.h>
+#include <openssl/mem.h>
+
+#include "internal.h"
+
+/* number of Miller-Rabin iterations for an error rate of less than 2^-80
+ * for random 'b'-bit input, b >= 100 (taken from table 4.4 in the Handbook
+ * of Applied Cryptography [Menezes, van Oorschot, Vanstone; CRC Press 1996];
+ * original paper: Damgaard, Landrock, Pomerance: Average case error estimates
+ * for the strong probable prime test. -- Math. Comp. 61 (1993) 177-194) */
+#define BN_prime_checks_for_size(b) ((b) >= 1300 ? 2 : \
+ (b) >= 850 ? 3 : \
+ (b) >= 650 ? 4 : \
+ (b) >= 550 ? 5 : \
+ (b) >= 450 ? 6 : \
+ (b) >= 400 ? 7 : \
+ (b) >= 350 ? 8 : \
+ (b) >= 300 ? 9 : \
+ (b) >= 250 ? 12 : \
+ (b) >= 200 ? 15 : \
+ (b) >= 150 ? 18 : \
+ /* b >= 100 */ 27)
+
+/* 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. */
+
+/* NUMPRIMES is the number of primes that fit into a uint16_t. */
+#define NUMPRIMES 2048
+
+/* primes contains all the primes that fit into a uint16_t. */
+static 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,
+};
+
+static int witness(BIGNUM *w, const BIGNUM *a, const BIGNUM *a1,
+ const BIGNUM *a1_odd, int k, BN_CTX *ctx, BN_MONT_CTX *mont);
+static int probable_prime(BIGNUM *rnd, int bits);
+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);
+
+void BN_GENCB_set(BN_GENCB *callback,
+ int (*f)(int event, int n, struct bn_gencb_st *),
+ void *arg) {
+ callback->callback = f;
+ callback->arg = arg;
+}
+
+int BN_GENCB_call(BN_GENCB *callback, int event, int n) {
+ if (!callback) {
+ return 1;
+ }
+
+ return callback->callback(event, n, callback);
+}
+
+int BN_generate_prime_ex(BIGNUM *ret, int bits, int safe, const BIGNUM *add,
+ const BIGNUM *rem, BN_GENCB *cb) {
+ BIGNUM *t;
+ int found = 0;
+ int i, j, c1 = 0;
+ BN_CTX *ctx;
+ int checks = BN_prime_checks_for_size(bits);
+
+ if (bits < 2) {
+ /* There are no prime numbers this small. */
+ OPENSSL_PUT_ERROR(BN, BN_generate_prime_ex, BN_R_BITS_TOO_SMALL);
+ return 0;
+ } else if (bits == 2 && safe) {
+ /* The smallest safe prime (7) is three bits. */
+ OPENSSL_PUT_ERROR(BN, BN_generate_prime_ex, BN_R_BITS_TOO_SMALL);
+ return 0;
+ }
+
+ ctx = BN_CTX_new();
+ if (ctx == NULL) {
+ goto err;
+ }
+ BN_CTX_start(ctx);
+ t = BN_CTX_get(ctx);
+ if (!t) {
+ 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, BN_GENCB_GENERATED, c1++)) {
+ /* aborted */
+ goto err;
+ }
+
+ if (!safe) {
+ i = BN_is_prime_fasttest_ex(ret, checks, ctx, 0, cb);
+ if (i == -1) {
+ goto err;
+ } else if (i == 0) {
+ goto loop;
+ }
+ } else {
+ /* for "safe prime" generation, check that (p-1)/2 is prime. Since a prime
+ * is odd, We just need to divide by 2 */
+ if (!BN_rshift1(t, ret)) {
+ goto err;
+ }
+
+ for (i = 0; i < checks; i++) {
+ j = BN_is_prime_fasttest_ex(ret, 1, ctx, 0, NULL);
+ if (j == -1) {
+ goto err;
+ } else if (j == 0) {
+ goto loop;
+ }
+
+ j = BN_is_prime_fasttest_ex(t, 1, ctx, 0, NULL);
+ if (j == -1) {
+ goto err;
+ } else if (j == 0) {
+ goto loop;
+ }
+
+ if (!BN_GENCB_call(cb, i, c1 - 1)) {
+ goto err;
+ }
+ /* We have a safe prime test pass */
+ }
+ }
+
+ /* we have a prime :-) */
+ found = 1;
+
+err:
+ if (ctx != NULL) {
+ BN_CTX_end(ctx);
+ BN_CTX_free(ctx);
+ }
+
+ return found;
+}
+
+int BN_primality_test(int *is_probably_prime, const BIGNUM *candidate,
+ int checks, BN_CTX *ctx, int do_trial_division,
+ BN_GENCB *cb) {
+ switch (BN_is_prime_fasttest_ex(candidate, checks, ctx, do_trial_division, cb)) {
+ case 1:
+ *is_probably_prime = 1;
+ return 1;
+ case 0:
+ *is_probably_prime = 0;
+ return 1;
+ default:
+ *is_probably_prime = 0;
+ return 0;
+ }
+}
+
+int BN_is_prime_ex(const BIGNUM *candidate, int checks, BN_CTX *ctx, BN_GENCB *cb) {
+ return BN_is_prime_fasttest_ex(candidate, checks, ctx, 0, cb);
+}
+
+int BN_is_prime_fasttest_ex(const BIGNUM *a, int checks, BN_CTX *ctx_passed,
+ int do_trial_division, BN_GENCB *cb) {
+ int i, j, ret = -1;
+ int k;
+ BN_CTX *ctx = NULL;
+ BIGNUM *A1, *A1_odd, *check; /* taken from ctx */
+ BN_MONT_CTX *mont = NULL;
+ const BIGNUM *A = NULL;
+
+ if (BN_cmp(a, BN_value_one()) <= 0) {
+ return 0;
+ }
+
+ if (checks == BN_prime_checks) {
+ checks = BN_prime_checks_for_size(BN_num_bits(a));
+ }
+
+ /* first look for small factors */
+ if (!BN_is_odd(a)) {
+ /* a is even => a is prime if and only if a == 2 */
+ return BN_is_word(a, 2);
+ }
+
+ if (do_trial_division) {
+ for (i = 1; i < NUMPRIMES; i++) {
+ if (BN_mod_word(a, primes[i]) == 0) {
+ return 0;
+ }
+ }
+
+ if (!BN_GENCB_call(cb, 1, -1)) {
+ goto err;
+ }
+ }
+
+ if (ctx_passed != NULL) {
+ ctx = ctx_passed;
+ } else if ((ctx = BN_CTX_new()) == NULL) {
+ goto err;
+ }
+ BN_CTX_start(ctx);
+
+ /* A := abs(a) */
+ if (a->neg) {
+ BIGNUM *t;
+ if ((t = BN_CTX_get(ctx)) == NULL) {
+ goto err;
+ }
+ BN_copy(t, a);
+ t->neg = 0;
+ A = t;
+ } else {
+ A = a;
+ }
+
+ A1 = BN_CTX_get(ctx);
+ A1_odd = BN_CTX_get(ctx);
+ check = BN_CTX_get(ctx);
+ if (check == NULL) {
+ goto err;
+ }
+
+ /* compute A1 := A - 1 */
+ if (!BN_copy(A1, A)) {
+ goto err;
+ }
+ if (!BN_sub_word(A1, 1)) {
+ goto err;
+ }
+ if (BN_is_zero(A1)) {
+ ret = 0;
+ goto err;
+ }
+
+ /* write A1 as A1_odd * 2^k */
+ k = 1;
+ while (!BN_is_bit_set(A1, k)) {
+ k++;
+ }
+ if (!BN_rshift(A1_odd, A1, k)) {
+ goto err;
+ }
+
+ /* Montgomery setup for computations mod A */
+ mont = BN_MONT_CTX_new();
+ if (mont == NULL) {
+ goto err;
+ }
+ if (!BN_MONT_CTX_set(mont, A, ctx)) {
+ goto err;
+ }
+
+ for (i = 0; i < checks; i++) {
+ if (!BN_pseudo_rand_range(check, A1)) {
+ goto err;
+ }
+ if (!BN_add_word(check, 1)) {
+ goto err;
+ }
+ /* now 1 <= check < A */
+
+ j = witness(check, A, A1, A1_odd, k, ctx, mont);
+ if (j == -1) {
+ goto err;
+ }
+ if (j) {
+ ret = 0;
+ goto err;
+ }
+ if (!BN_GENCB_call(cb, 1, i)) {
+ goto err;
+ }
+ }
+ ret = 1;
+
+err:
+ if (ctx != NULL) {
+ BN_CTX_end(ctx);
+ if (ctx_passed == NULL) {
+ BN_CTX_free(ctx);
+ }
+ }
+ if (mont != NULL) {
+ BN_MONT_CTX_free(mont);
+ }
+
+ return ret;
+}
+
+static int witness(BIGNUM *w, const BIGNUM *a, const BIGNUM *a1,
+ const BIGNUM *a1_odd, int k, BN_CTX *ctx,
+ BN_MONT_CTX *mont) {
+ if (!BN_mod_exp_mont(w, w, a1_odd, a, ctx, mont)) { /* w := w^a1_odd mod a */
+ return -1;
+ }
+ if (BN_is_one(w)) {
+ return 0; /* probably prime */
+ }
+ if (BN_cmp(w, a1) == 0) {
+ return 0; /* w == -1 (mod a), 'a' is probably prime */
+ }
+
+ while (--k) {
+ if (!BN_mod_mul(w, w, w, a, ctx)) { /* w := w^2 mod a */
+ return -1;
+ }
+
+ if (BN_is_one(w)) {
+ return 1; /* 'a' is composite, otherwise a previous 'w' would
+ * have been == -1 (mod 'a') */
+ }
+
+ if (BN_cmp(w, a1) == 0) {
+ return 0; /* w == -1 (mod a), 'a' is probably prime */
+ }
+ }
+
+ /* If we get here, 'w' is the (a-1)/2-th power of the original 'w',
+ * and it is neither -1 nor +1 -- so 'a' cannot be prime */
+ return 1;
+}
+
+static BN_ULONG get_word(const BIGNUM *bn) {
+ if (bn->top == 1) {
+ return bn->d[0];
+ }
+ return 0;
+}
+
+static int probable_prime(BIGNUM *rnd, int bits) {
+ int i;
+ uint16_t mods[NUMPRIMES];
+ BN_ULONG delta;
+ BN_ULONG maxdelta = BN_MASK2 - primes[NUMPRIMES - 1];
+ char is_single_word = bits <= BN_BITS2;
+
+again:
+ if (!BN_rand(rnd, bits, 1, 1)) {
+ return 0;
+ }
+
+ /* we now have a random number 'rnd' to test. */
+ for (i = 1; i < NUMPRIMES; i++) {
+ mods[i] = (uint16_t)BN_mod_word(rnd, (BN_ULONG)primes[i]);
+ }
+ /* If bits is so small that it fits into a single word then we
+ * additionally don't want to exceed that many bits. */
+ if (is_single_word) {
+ BN_ULONG size_limit = (((BN_ULONG)1) << bits) - get_word(rnd) - 1;
+ if (size_limit < maxdelta) {
+ maxdelta = size_limit;
+ }
+ }
+ delta = 0;
+
+loop:
+ if (is_single_word) {
+ BN_ULONG rnd_word = get_word(rnd);
+
+ /* In the case that the candidate prime is a single word then
+ * we check that:
+ * 1) It's greater than primes[i] because we shouldn't reject
+ * 3 as being a prime number because it's a multiple of
+ * three.
+ * 2) That it's not a multiple of a known prime. We don't
+ * check that rnd-1 is also coprime to all the known
+ * primes because there aren't many small primes where
+ * that's true. */
+ for (i = 1; i < NUMPRIMES && primes[i] < rnd_word; i++) {
+ if ((mods[i] + delta) % primes[i] == 0) {
+ delta += 2;
+ if (delta > maxdelta)
+ goto again;
+ goto loop;
+ }
+ }
+ } else {
+ 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;
+ }
+ if (BN_num_bits(rnd) != bits) {
+ goto again;
+ }
+
+ 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(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 */
+ if (BN_mod_word(rnd, (BN_ULONG)primes[i]) <= 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);
+ t1 = BN_CTX_get(ctx);
+ q = BN_CTX_get(ctx);
+ qadd = BN_CTX_get(ctx);
+ if (qadd == 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(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) */
+ if ((BN_mod_word(p, (BN_ULONG)primes[i]) == 0) ||
+ (BN_mod_word(q, (BN_ULONG)primes[i]) == 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/src/crypto/bn/random.c b/src/crypto/bn/random.c
new file mode 100644
index 0000000..285bf26
--- /dev/null
+++ b/src/crypto/bn/random.c
@@ -0,0 +1,328 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/bn.h>
+
+#include <string.h>
+
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/rand.h>
+#include <openssl/sha.h>
+
+int BN_rand(BIGNUM *rnd, int bits, int top, int bottom) {
+ uint8_t *buf = NULL;
+ int ret = 0, bit, bytes, mask;
+
+ if (rnd == NULL) {
+ return 0;
+ }
+
+ if (bits == 0) {
+ BN_zero(rnd);
+ return 1;
+ }
+
+ bytes = (bits + 7) / 8;
+ bit = (bits - 1) % 8;
+ mask = 0xff << (bit + 1);
+
+ buf = OPENSSL_malloc(bytes);
+ if (buf == NULL) {
+ OPENSSL_PUT_ERROR(BN, BN_rand, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ /* Make a random number and set the top and bottom bits. */
+ if (!RAND_bytes(buf, bytes)) {
+ goto err;
+ }
+
+ if (top != -1) {
+ if (top) {
+ if (bit == 0) {
+ buf[0] = 1;
+ buf[1] |= 0x80;
+ } else {
+ buf[0] |= (3 << (bit - 1));
+ }
+ } else {
+ buf[0] |= (1 << bit);
+ }
+ }
+
+ buf[0] &= ~mask;
+
+ /* set bottom bit if requested */
+ if (bottom) {
+ buf[bytes - 1] |= 1;
+ }
+
+ if (!BN_bin2bn(buf, bytes, rnd)) {
+ goto err;
+ }
+
+ ret = 1;
+
+err:
+ if (buf != NULL) {
+ OPENSSL_cleanse(buf, bytes);
+ OPENSSL_free(buf);
+ }
+ return (ret);
+}
+
+int BN_pseudo_rand(BIGNUM *rnd, int bits, int top, int bottom) {
+ return BN_rand(rnd, bits, top, bottom);
+}
+
+int BN_rand_range(BIGNUM *r, const BIGNUM *range) {
+ unsigned n;
+ unsigned count = 100;
+
+ if (range->neg || BN_is_zero(range)) {
+ OPENSSL_PUT_ERROR(BN, BN_rand_range, 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 /* don't set most significant bits */,
+ 0 /* don't set least significant bits */)) {
+ return 0;
+ }
+
+ /* If r < 3*range, use r := r MOD range (which is either r, r - range, or
+ * r - 2*range). Otherwise, iterate again. 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) {
+ OPENSSL_PUT_ERROR(BN, BN_rand_range, 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) {
+ OPENSSL_PUT_ERROR(BN, BN_rand_range, BN_R_TOO_MANY_ITERATIONS);
+ return 0;
+ }
+ } while (BN_cmp(r, range) >= 0);
+ }
+
+ return 1;
+}
+
+int BN_pseudo_rand_range(BIGNUM *r, const BIGNUM *range) {
+ return BN_rand_range(r, range);
+}
+
+int BN_generate_dsa_nonce(BIGNUM *out, const BIGNUM *range, const BIGNUM *priv,
+ const uint8_t *message, size_t message_len,
+ BN_CTX *ctx) {
+ SHA512_CTX sha;
+ /* We use 512 bits of random data per iteration to
+ * ensure that we have at least |range| bits of randomness. */
+ uint8_t random_bytes[64];
+ uint8_t digest[SHA512_DIGEST_LENGTH];
+ size_t done, todo, attempt;
+ const unsigned num_k_bytes = BN_num_bytes(range);
+ const unsigned bits_to_mask = (8 - (BN_num_bits(range) % 8)) % 8;
+ uint8_t private_bytes[96];
+ uint8_t *k_bytes = NULL;
+ int ret = 0;
+
+ if (out == NULL) {
+ return 0;
+ }
+
+ if (BN_is_zero(range)) {
+ OPENSSL_PUT_ERROR(BN, BN_generate_dsa_nonce, BN_R_DIV_BY_ZERO);
+ goto err;
+ }
+
+ k_bytes = OPENSSL_malloc(num_k_bytes);
+ if (!k_bytes) {
+ OPENSSL_PUT_ERROR(BN, BN_generate_dsa_nonce, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ /* We copy |priv| into a local buffer to avoid furthur exposing its
+ * length. */
+ todo = sizeof(priv->d[0]) * priv->top;
+ if (todo > sizeof(private_bytes)) {
+ /* No reasonable DSA or ECDSA key should have a private key
+ * this large and we don't handle this case in order to avoid
+ * leaking the length of the private key. */
+ OPENSSL_PUT_ERROR(BN, BN_generate_dsa_nonce, BN_R_PRIVATE_KEY_TOO_LARGE);
+ goto err;
+ }
+ memcpy(private_bytes, priv->d, todo);
+ memset(private_bytes + todo, 0, sizeof(private_bytes) - todo);
+
+ for (attempt = 0;; attempt++) {
+ for (done = 0; done < num_k_bytes;) {
+ if (!RAND_bytes(random_bytes, sizeof(random_bytes))) {
+ goto err;
+ }
+ SHA512_Init(&sha);
+ SHA512_Update(&sha, &attempt, sizeof(attempt));
+ SHA512_Update(&sha, &done, sizeof(done));
+ SHA512_Update(&sha, private_bytes, sizeof(private_bytes));
+ SHA512_Update(&sha, message, message_len);
+ SHA512_Update(&sha, random_bytes, sizeof(random_bytes));
+ SHA512_Final(digest, &sha);
+
+ todo = num_k_bytes - done;
+ if (todo > SHA512_DIGEST_LENGTH) {
+ todo = SHA512_DIGEST_LENGTH;
+ }
+ memcpy(k_bytes + done, digest, todo);
+ done += todo;
+ }
+
+ k_bytes[0] &= 0xff >> bits_to_mask;
+
+ if (!BN_bin2bn(k_bytes, num_k_bytes, out)) {
+ goto err;
+ }
+ if (BN_cmp(out, range) < 0) {
+ break;
+ }
+ }
+
+ ret = 1;
+
+err:
+ if (k_bytes) {
+ OPENSSL_free(k_bytes);
+ }
+ return ret;
+}
diff --git a/src/crypto/bn/rsaz_exp.c b/src/crypto/bn/rsaz_exp.c
new file mode 100644
index 0000000..c802752
--- /dev/null
+++ b/src/crypto/bn/rsaz_exp.c
@@ -0,0 +1,326 @@
+/*****************************************************************************
+* *
+* Copyright (c) 2012, Intel Corporation *
+* *
+* All rights reserved. *
+* *
+* Redistribution and use in source and binary forms, with or without *
+* modification, are permitted provided that the following conditions are *
+* met: *
+* *
+* * Redistributions of source code must retain the above copyright *
+* notice, this list of conditions and the following disclaimer. *
+* *
+* * Redistributions in binary form must reproduce the above copyright *
+* notice, this list of conditions and the following disclaimer in the *
+* documentation and/or other materials provided with the *
+* distribution. *
+* *
+* * Neither the name of the Intel Corporation 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 INTEL CORPORATION ""AS IS"" AND ANY *
+* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE *
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR *
+* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR *
+* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
+* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
+* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
+* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
+* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
+* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
+* *
+******************************************************************************
+* Developers and authors: *
+* Shay Gueron (1, 2), and Vlad Krasnov (1) *
+* (1) Intel Corporation, Israel Development Center, Haifa, Israel *
+* (2) University of Haifa, Israel *
+*****************************************************************************/
+
+#include <openssl/base.h>
+
+#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64)
+
+#include "rsaz_exp.h"
+
+#include <openssl/mem.h>
+
+/*
+ * See crypto/bn/asm/rsaz-avx2.pl for further details.
+ */
+void rsaz_1024_norm2red_avx2(void *red,const void *norm);
+void rsaz_1024_mul_avx2(void *ret,const void *a,const void *b,const void *n,BN_ULONG k);
+void rsaz_1024_sqr_avx2(void *ret,const void *a,const void *n,BN_ULONG k,int cnt);
+void rsaz_1024_scatter5_avx2(void *tbl,const void *val,int i);
+void rsaz_1024_gather5_avx2(void *val,const void *tbl,int i);
+void rsaz_1024_red2norm_avx2(void *norm,const void *red);
+
+#if defined(__GNUC__)
+# define ALIGN64 __attribute__((aligned(64)))
+#elif defined(_MSC_VER)
+# define ALIGN64 __declspec(align(64))
+#elif defined(__SUNPRO_C)
+# define ALIGN64
+# pragma align 64(one,two80)
+#else
+# define ALIGN64 /* not fatal, might hurt performance a little */
+#endif
+
+ALIGN64 static const BN_ULONG one[40] =
+ {1,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+ALIGN64 static const BN_ULONG two80[40] =
+ {0,0,1<<22,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+
+void RSAZ_1024_mod_exp_avx2(BN_ULONG result_norm[16],
+ const BN_ULONG base_norm[16], const BN_ULONG exponent[16],
+ const BN_ULONG m_norm[16], const BN_ULONG RR[16], BN_ULONG k0)
+{
+ unsigned char storage[320*3+32*9*16+64]; /* 5.5KB */
+ unsigned char *p_str = storage + (64-((size_t)storage%64));
+ unsigned char *a_inv, *m, *result,
+ *table_s = p_str+320*3,
+ *R2 = table_s; /* borrow */
+ int index;
+ int wvalue;
+
+ if ((((size_t)p_str&4095)+320)>>12) {
+ result = p_str;
+ a_inv = p_str + 320;
+ m = p_str + 320*2; /* should not cross page */
+ } else {
+ m = p_str; /* should not cross page */
+ result = p_str + 320;
+ a_inv = p_str + 320*2;
+ }
+
+ rsaz_1024_norm2red_avx2(m, m_norm);
+ rsaz_1024_norm2red_avx2(a_inv, base_norm);
+ rsaz_1024_norm2red_avx2(R2, RR);
+
+ rsaz_1024_mul_avx2(R2, R2, R2, m, k0);
+ rsaz_1024_mul_avx2(R2, R2, two80, m, k0);
+
+ /* table[0] = 1 */
+ rsaz_1024_mul_avx2(result, R2, one, m, k0);
+ /* table[1] = a_inv^1 */
+ rsaz_1024_mul_avx2(a_inv, a_inv, R2, m, k0);
+
+ rsaz_1024_scatter5_avx2(table_s,result,0);
+ rsaz_1024_scatter5_avx2(table_s,a_inv,1);
+
+ /* table[2] = a_inv^2 */
+ rsaz_1024_sqr_avx2(result, a_inv, m, k0, 1);
+ rsaz_1024_scatter5_avx2(table_s,result,2);
+#if 0
+ /* this is almost 2x smaller and less than 1% slower */
+ for (index=3; index<32; index++) {
+ rsaz_1024_mul_avx2(result, result, a_inv, m, k0);
+ rsaz_1024_scatter5_avx2(table_s,result,index);
+ }
+#else
+ /* table[4] = a_inv^4 */
+ rsaz_1024_sqr_avx2(result, result, m, k0, 1);
+ rsaz_1024_scatter5_avx2(table_s,result,4);
+ /* table[8] = a_inv^8 */
+ rsaz_1024_sqr_avx2(result, result, m, k0, 1);
+ rsaz_1024_scatter5_avx2(table_s,result,8);
+ /* table[16] = a_inv^16 */
+ rsaz_1024_sqr_avx2(result, result, m, k0, 1);
+ rsaz_1024_scatter5_avx2(table_s,result,16);
+ /* table[17] = a_inv^17 */
+ rsaz_1024_mul_avx2(result, result, a_inv, m, k0);
+ rsaz_1024_scatter5_avx2(table_s,result,17);
+
+ /* table[3] */
+ rsaz_1024_gather5_avx2(result,table_s,2);
+ rsaz_1024_mul_avx2(result,result,a_inv,m,k0);
+ rsaz_1024_scatter5_avx2(table_s,result,3);
+ /* table[6] */
+ rsaz_1024_sqr_avx2(result, result, m, k0, 1);
+ rsaz_1024_scatter5_avx2(table_s,result,6);
+ /* table[12] */
+ rsaz_1024_sqr_avx2(result, result, m, k0, 1);
+ rsaz_1024_scatter5_avx2(table_s,result,12);
+ /* table[24] */
+ rsaz_1024_sqr_avx2(result, result, m, k0, 1);
+ rsaz_1024_scatter5_avx2(table_s,result,24);
+ /* table[25] */
+ rsaz_1024_mul_avx2(result, result, a_inv, m, k0);
+ rsaz_1024_scatter5_avx2(table_s,result,25);
+
+ /* table[5] */
+ rsaz_1024_gather5_avx2(result,table_s,4);
+ rsaz_1024_mul_avx2(result,result,a_inv,m,k0);
+ rsaz_1024_scatter5_avx2(table_s,result,5);
+ /* table[10] */
+ rsaz_1024_sqr_avx2(result, result, m, k0, 1);
+ rsaz_1024_scatter5_avx2(table_s,result,10);
+ /* table[20] */
+ rsaz_1024_sqr_avx2(result, result, m, k0, 1);
+ rsaz_1024_scatter5_avx2(table_s,result,20);
+ /* table[21] */
+ rsaz_1024_mul_avx2(result, result, a_inv, m, k0);
+ rsaz_1024_scatter5_avx2(table_s,result,21);
+
+ /* table[7] */
+ rsaz_1024_gather5_avx2(result,table_s,6);
+ rsaz_1024_mul_avx2(result,result,a_inv,m,k0);
+ rsaz_1024_scatter5_avx2(table_s,result,7);
+ /* table[14] */
+ rsaz_1024_sqr_avx2(result, result, m, k0, 1);
+ rsaz_1024_scatter5_avx2(table_s,result,14);
+ /* table[28] */
+ rsaz_1024_sqr_avx2(result, result, m, k0, 1);
+ rsaz_1024_scatter5_avx2(table_s,result,28);
+ /* table[29] */
+ rsaz_1024_mul_avx2(result, result, a_inv, m, k0);
+ rsaz_1024_scatter5_avx2(table_s,result,29);
+
+ /* table[9] */
+ rsaz_1024_gather5_avx2(result,table_s,8);
+ rsaz_1024_mul_avx2(result,result,a_inv,m,k0);
+ rsaz_1024_scatter5_avx2(table_s,result,9);
+ /* table[18] */
+ rsaz_1024_sqr_avx2(result, result, m, k0, 1);
+ rsaz_1024_scatter5_avx2(table_s,result,18);
+ /* table[19] */
+ rsaz_1024_mul_avx2(result, result, a_inv, m, k0);
+ rsaz_1024_scatter5_avx2(table_s,result,19);
+
+ /* table[11] */
+ rsaz_1024_gather5_avx2(result,table_s,10);
+ rsaz_1024_mul_avx2(result,result,a_inv,m,k0);
+ rsaz_1024_scatter5_avx2(table_s,result,11);
+ /* table[22] */
+ rsaz_1024_sqr_avx2(result, result, m, k0, 1);
+ rsaz_1024_scatter5_avx2(table_s,result,22);
+ /* table[23] */
+ rsaz_1024_mul_avx2(result, result, a_inv, m, k0);
+ rsaz_1024_scatter5_avx2(table_s,result,23);
+
+ /* table[13] */
+ rsaz_1024_gather5_avx2(result,table_s,12);
+ rsaz_1024_mul_avx2(result,result,a_inv,m,k0);
+ rsaz_1024_scatter5_avx2(table_s,result,13);
+ /* table[26] */
+ rsaz_1024_sqr_avx2(result, result, m, k0, 1);
+ rsaz_1024_scatter5_avx2(table_s,result,26);
+ /* table[27] */
+ rsaz_1024_mul_avx2(result, result, a_inv, m, k0);
+ rsaz_1024_scatter5_avx2(table_s,result,27);
+
+ /* table[15] */
+ rsaz_1024_gather5_avx2(result,table_s,14);
+ rsaz_1024_mul_avx2(result,result,a_inv,m,k0);
+ rsaz_1024_scatter5_avx2(table_s,result,15);
+ /* table[30] */
+ rsaz_1024_sqr_avx2(result, result, m, k0, 1);
+ rsaz_1024_scatter5_avx2(table_s,result,30);
+ /* table[31] */
+ rsaz_1024_mul_avx2(result, result, a_inv, m, k0);
+ rsaz_1024_scatter5_avx2(table_s,result,31);
+#endif
+
+ /* load first window */
+ p_str = (unsigned char*)exponent;
+ wvalue = p_str[127] >> 3;
+ rsaz_1024_gather5_avx2(result,table_s,wvalue);
+
+ index = 1014;
+
+ while(index > -1) { /* loop for the remaining 127 windows */
+
+ rsaz_1024_sqr_avx2(result, result, m, k0, 5);
+
+ wvalue = *((unsigned short*)&p_str[index/8]);
+ wvalue = (wvalue>> (index%8)) & 31;
+ index-=5;
+
+ rsaz_1024_gather5_avx2(a_inv,table_s,wvalue); /* borrow a_inv */
+ rsaz_1024_mul_avx2(result, result, a_inv, m, k0);
+ }
+
+ /* square four times */
+ rsaz_1024_sqr_avx2(result, result, m, k0, 4);
+
+ wvalue = p_str[0] & 15;
+
+ rsaz_1024_gather5_avx2(a_inv,table_s,wvalue); /* borrow a_inv */
+ rsaz_1024_mul_avx2(result, result, a_inv, m, k0);
+
+ /* from Montgomery */
+ rsaz_1024_mul_avx2(result, result, one, m, k0);
+
+ rsaz_1024_red2norm_avx2(result_norm, result);
+
+ OPENSSL_cleanse(storage,sizeof(storage));
+}
+
+/*
+ * See crypto/bn/rsaz-x86_64.pl for further details.
+ */
+void rsaz_512_mul(void *ret,const void *a,const void *b,const void *n,BN_ULONG k);
+void rsaz_512_mul_scatter4(void *ret,const void *a,const void *n,BN_ULONG k,const void *tbl,unsigned int power);
+void rsaz_512_mul_gather4(void *ret,const void *a,const void *tbl,const void *n,BN_ULONG k,unsigned int power);
+void rsaz_512_mul_by_one(void *ret,const void *a,const void *n,BN_ULONG k);
+void rsaz_512_sqr(void *ret,const void *a,const void *n,BN_ULONG k,int cnt);
+void rsaz_512_scatter4(void *tbl, const BN_ULONG *val, int power);
+void rsaz_512_gather4(BN_ULONG *val, const void *tbl, int power);
+
+void RSAZ_512_mod_exp(BN_ULONG result[8],
+ const BN_ULONG base[8], const BN_ULONG exponent[8],
+ const BN_ULONG m[8], BN_ULONG k0, const BN_ULONG RR[8])
+{
+ unsigned char storage[16*8*8+64*2+64]; /* 1.2KB */
+ unsigned char *table = storage + (64-((size_t)storage%64));
+ BN_ULONG *a_inv = (BN_ULONG *)(table+16*8*8),
+ *temp = (BN_ULONG *)(table+16*8*8+8*8);
+ unsigned char *p_str = (unsigned char*)exponent;
+ int index;
+ unsigned int wvalue;
+
+ /* table[0] = 1_inv */
+ temp[0] = 0-m[0]; temp[1] = ~m[1];
+ temp[2] = ~m[2]; temp[3] = ~m[3];
+ temp[4] = ~m[4]; temp[5] = ~m[5];
+ temp[6] = ~m[6]; temp[7] = ~m[7];
+ rsaz_512_scatter4(table, temp, 0);
+
+ /* table [1] = a_inv^1 */
+ rsaz_512_mul(a_inv, base, RR, m, k0);
+ rsaz_512_scatter4(table, a_inv, 1);
+
+ /* table [2] = a_inv^2 */
+ rsaz_512_sqr(temp, a_inv, m, k0, 1);
+ rsaz_512_scatter4(table, temp, 2);
+
+ for (index=3; index<16; index++)
+ rsaz_512_mul_scatter4(temp, a_inv, m, k0, table, index);
+
+ /* load first window */
+ wvalue = p_str[63];
+
+ rsaz_512_gather4(temp, table, wvalue>>4);
+ rsaz_512_sqr(temp, temp, m, k0, 4);
+ rsaz_512_mul_gather4(temp, temp, table, m, k0, wvalue&0xf);
+
+ for (index=62; index>=0; index--) {
+ wvalue = p_str[index];
+
+ rsaz_512_sqr(temp, temp, m, k0, 4);
+ rsaz_512_mul_gather4(temp, temp, table, m, k0, wvalue>>4);
+
+ rsaz_512_sqr(temp, temp, m, k0, 4);
+ rsaz_512_mul_gather4(temp, temp, table, m, k0, wvalue&0x0f);
+ }
+
+ /* from Montgomery */
+ rsaz_512_mul_by_one(result, temp, m, k0);
+
+ OPENSSL_cleanse(storage,sizeof(storage));
+}
+
+#endif /* OPENSSL_X86_64 */
diff --git a/src/crypto/bn/rsaz_exp.h b/src/crypto/bn/rsaz_exp.h
new file mode 100644
index 0000000..0bb6b0c
--- /dev/null
+++ b/src/crypto/bn/rsaz_exp.h
@@ -0,0 +1,44 @@
+/******************************************************************************
+* Copyright(c) 2012, Intel Corp.
+* Developers and authors:
+* Shay Gueron (1, 2), and Vlad Krasnov (1)
+* (1) Intel Corporation, Israel Development Center, Haifa, Israel
+* (2) University of Haifa, Israel
+******************************************************************************
+* LICENSE:
+* This submission to OpenSSL is to be made available under the OpenSSL
+* license, and only to the OpenSSL project, in order to allow integration
+* into the publicly distributed code.
+* The use of this code, or portions of this code, or concepts embedded in
+* this code, or modification of this code and/or algorithm(s) in it, or the
+* use of this code for any other purpose than stated above, requires special
+* licensing.
+******************************************************************************
+* DISCLAIMER:
+* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS AND THE COPYRIGHT OWNERS
+* ``AS IS''. ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS OR THE COPYRIGHT
+* OWNERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (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 RSAZ_EXP_H
+#define RSAZ_EXP_H
+
+#include <openssl/bn.h>
+
+void RSAZ_1024_mod_exp_avx2(BN_ULONG result[16],
+ const BN_ULONG base_norm[16], const BN_ULONG exponent[16],
+ const BN_ULONG m_norm[16], const BN_ULONG RR[16], BN_ULONG k0);
+int rsaz_avx2_eligible(void);
+
+void RSAZ_512_mod_exp(BN_ULONG result[8],
+ const BN_ULONG base_norm[8], const BN_ULONG exponent[8],
+ const BN_ULONG m_norm[8], BN_ULONG k0, const BN_ULONG RR[8]);
+#endif
diff --git a/src/crypto/bn/shift.c b/src/crypto/bn/shift.c
new file mode 100644
index 0000000..1e3b7c3
--- /dev/null
+++ b/src/crypto/bn/shift.c
@@ -0,0 +1,287 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/bn.h>
+
+#include <string.h>
+
+#include "internal.h"
+
+
+int BN_lshift(BIGNUM *r, const BIGNUM *a, int n) {
+ int i, nw, lb, rb;
+ BN_ULONG *t, *f;
+ BN_ULONG l;
+
+ r->neg = a->neg;
+ nw = n / BN_BITS2;
+ if (bn_wexpand(r, a->top + nw + 1) == NULL) {
+ return 0;
+ }
+ lb = n % BN_BITS2;
+ rb = BN_BITS2 - lb;
+ f = a->d;
+ t = r->d;
+ t[a->top + nw] = 0;
+ if (lb == 0) {
+ for (i = a->top - 1; i >= 0; i--) {
+ t[nw + i] = f[i];
+ }
+ } else {
+ for (i = a->top - 1; i >= 0; i--) {
+ l = f[i];
+ t[nw + i + 1] |= (l >> rb) & BN_MASK2;
+ t[nw + i] = (l << lb) & BN_MASK2;
+ }
+ }
+ memset(t, 0, nw * sizeof(t[0]));
+ r->top = a->top + nw + 1;
+ bn_correct_top(r);
+
+ return 1;
+}
+
+int BN_lshift1(BIGNUM *r, const BIGNUM *a) {
+ BN_ULONG *ap, *rp, t, c;
+ int i;
+
+ if (r != a) {
+ r->neg = a->neg;
+ if (bn_wexpand(r, a->top + 1) == NULL) {
+ return 0;
+ }
+ r->top = a->top;
+ } else {
+ if (bn_wexpand(r, a->top + 1) == NULL) {
+ return 0;
+ }
+ }
+ ap = a->d;
+ rp = r->d;
+ c = 0;
+ for (i = 0; i < a->top; i++) {
+ t = *(ap++);
+ *(rp++) = ((t << 1) | c) & BN_MASK2;
+ c = (t & BN_TBIT) ? 1 : 0;
+ }
+ if (c) {
+ *rp = 1;
+ r->top++;
+ }
+
+ return 1;
+}
+
+int BN_rshift(BIGNUM *r, const BIGNUM *a, int n) {
+ int i, j, nw, lb, rb;
+ BN_ULONG *t, *f;
+ BN_ULONG l, tmp;
+
+ nw = n / BN_BITS2;
+ rb = n % BN_BITS2;
+ lb = BN_BITS2 - rb;
+ if (nw >= a->top || a->top == 0) {
+ BN_zero(r);
+ return 1;
+ }
+ i = (BN_num_bits(a) - n + (BN_BITS2 - 1)) / BN_BITS2;
+ if (r != a) {
+ r->neg = a->neg;
+ if (bn_wexpand(r, i) == NULL) {
+ return 0;
+ }
+ } else {
+ if (n == 0) {
+ return 1; /* or the copying loop will go berserk */
+ }
+ }
+
+ f = &(a->d[nw]);
+ t = r->d;
+ j = a->top - nw;
+ r->top = i;
+
+ if (rb == 0) {
+ for (i = j; i != 0; i--) {
+ *(t++) = *(f++);
+ }
+ } else {
+ l = *(f++);
+ for (i = j - 1; i != 0; i--) {
+ tmp = (l >> rb) & BN_MASK2;
+ l = *(f++);
+ *(t++) = (tmp | (l << lb)) & BN_MASK2;
+ }
+ if ((l = (l >> rb) & BN_MASK2)) {
+ *(t) = l;
+ }
+ }
+
+ return 1;
+}
+
+int BN_rshift1(BIGNUM *r, const BIGNUM *a) {
+ BN_ULONG *ap, *rp, t, c;
+ int i, j;
+
+ if (BN_is_zero(a)) {
+ BN_zero(r);
+ return 1;
+ }
+ i = a->top;
+ ap = a->d;
+ j = i - (ap[i - 1] == 1);
+ if (a != r) {
+ if (bn_wexpand(r, j) == NULL) {
+ return 0;
+ }
+ r->neg = a->neg;
+ }
+ rp = r->d;
+ t = ap[--i];
+ c = (t & 1) ? BN_TBIT : 0;
+ if (t >>= 1) {
+ rp[i] = t;
+ }
+ while (i > 0) {
+ t = ap[--i];
+ rp[i] = ((t >> 1) & BN_MASK2) | c;
+ c = (t & 1) ? BN_TBIT : 0;
+ }
+ r->top = j;
+
+ return 1;
+}
+
+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) == NULL) {
+ 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;
+}
+
+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;
+}
+
+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 (a->d[i]>>j)&1;
+}
+
+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;
+}
diff --git a/src/crypto/bn/sqrt.c b/src/crypto/bn/sqrt.c
new file mode 100644
index 0000000..07041f9
--- /dev/null
+++ b/src/crypto/bn/sqrt.c
@@ -0,0 +1,505 @@
+/* Written by Lenka Fibikova <fibikova@exp-math.uni-essen.de>
+ * and Bodo Moeller 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). */
+
+#include <openssl/bn.h>
+
+#include <openssl/err.h>
+
+
+/* Returns 'ret' such that
+ * ret^2 == a (mod p),
+ * using the Tonelli/Shanks algorithm (cf. Henri Cohen, "A Course
+ * in Algebraic Computational Number Theory", algorithm 1.5.1).
+ * 'p' must be prime! */
+BIGNUM *BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) {
+ BIGNUM *ret = in;
+ int err = 1;
+ int r;
+ BIGNUM *A, *b, *q, *t, *x, *y;
+ int e, i, j;
+
+ if (!BN_is_odd(p) || BN_abs_is_word(p, 1)) {
+ if (BN_abs_is_word(p, 2)) {
+ if (ret == NULL) {
+ ret = BN_new();
+ }
+ if (ret == NULL) {
+ goto end;
+ }
+ if (!BN_set_word(ret, BN_is_bit_set(a, 0))) {
+ if (ret != in) {
+ BN_free(ret);
+ }
+ return NULL;
+ }
+ return ret;
+ }
+
+ OPENSSL_PUT_ERROR(BN, BN_mod_sqrt, BN_R_P_IS_NOT_PRIME);
+ return (NULL);
+ }
+
+ if (BN_is_zero(a) || BN_is_one(a)) {
+ if (ret == NULL) {
+ ret = BN_new();
+ }
+ if (ret == NULL) {
+ goto end;
+ }
+ if (!BN_set_word(ret, BN_is_one(a))) {
+ if (ret != in) {
+ BN_free(ret);
+ }
+ return NULL;
+ }
+ return ret;
+ }
+
+ BN_CTX_start(ctx);
+ A = BN_CTX_get(ctx);
+ b = BN_CTX_get(ctx);
+ q = BN_CTX_get(ctx);
+ t = BN_CTX_get(ctx);
+ x = BN_CTX_get(ctx);
+ y = BN_CTX_get(ctx);
+ if (y == NULL) {
+ goto end;
+ }
+
+ if (ret == NULL) {
+ ret = BN_new();
+ }
+ if (ret == NULL) {
+ goto end;
+ }
+
+ /* A = a mod p */
+ if (!BN_nnmod(A, a, p, ctx)) {
+ goto end;
+ }
+
+ /* now write |p| - 1 as 2^e*q where q is odd */
+ e = 1;
+ while (!BN_is_bit_set(p, e)) {
+ e++;
+ }
+ /* we'll set q later (if needed) */
+
+ if (e == 1) {
+ /* The easy case: (|p|-1)/2 is odd, so 2 has an inverse
+ * modulo (|p|-1)/2, and square roots can be computed
+ * directly by modular exponentiation.
+ * We have
+ * 2 * (|p|+1)/4 == 1 (mod (|p|-1)/2),
+ * so we can use exponent (|p|+1)/4, i.e. (|p|-3)/4 + 1.
+ */
+ if (!BN_rshift(q, p, 2)) {
+ goto end;
+ }
+ q->neg = 0;
+ if (!BN_add_word(q, 1) ||
+ !BN_mod_exp(ret, A, q, p, ctx)) {
+ goto end;
+ }
+ err = 0;
+ goto vrfy;
+ }
+
+ if (e == 2) {
+ /* |p| == 5 (mod 8)
+ *
+ * In this case 2 is always a non-square since
+ * Legendre(2,p) = (-1)^((p^2-1)/8) for any odd prime.
+ * So if a really is a square, then 2*a is a non-square.
+ * Thus for
+ * b := (2*a)^((|p|-5)/8),
+ * i := (2*a)*b^2
+ * we have
+ * i^2 = (2*a)^((1 + (|p|-5)/4)*2)
+ * = (2*a)^((p-1)/2)
+ * = -1;
+ * so if we set
+ * x := a*b*(i-1),
+ * then
+ * x^2 = a^2 * b^2 * (i^2 - 2*i + 1)
+ * = a^2 * b^2 * (-2*i)
+ * = a*(-i)*(2*a*b^2)
+ * = a*(-i)*i
+ * = a.
+ *
+ * (This is due to A.O.L. Atkin,
+ * <URL:
+ *http://listserv.nodak.edu/scripts/wa.exe?A2=ind9211&L=nmbrthry&O=T&P=562>,
+ * November 1992.)
+ */
+
+ /* t := 2*a */
+ if (!BN_mod_lshift1_quick(t, A, p)) {
+ goto end;
+ }
+
+ /* b := (2*a)^((|p|-5)/8) */
+ if (!BN_rshift(q, p, 3)) {
+ goto end;
+ }
+ q->neg = 0;
+ if (!BN_mod_exp(b, t, q, p, ctx)) {
+ goto end;
+ }
+
+ /* y := b^2 */
+ if (!BN_mod_sqr(y, b, p, ctx)) {
+ goto end;
+ }
+
+ /* t := (2*a)*b^2 - 1*/
+ if (!BN_mod_mul(t, t, y, p, ctx) ||
+ !BN_sub_word(t, 1)) {
+ goto end;
+ }
+
+ /* x = a*b*t */
+ if (!BN_mod_mul(x, A, b, p, ctx) ||
+ !BN_mod_mul(x, x, t, p, ctx)) {
+ goto end;
+ }
+
+ if (!BN_copy(ret, x)) {
+ goto end;
+ }
+ err = 0;
+ goto vrfy;
+ }
+
+ /* e > 2, so we really have to use the Tonelli/Shanks algorithm.
+ * First, find some y that is not a square. */
+ if (!BN_copy(q, p)) {
+ goto end; /* use 'q' as temp */
+ }
+ q->neg = 0;
+ i = 2;
+ do {
+ /* For efficiency, try small numbers first;
+ * if this fails, try random numbers.
+ */
+ if (i < 22) {
+ if (!BN_set_word(y, i)) {
+ goto end;
+ }
+ } else {
+ if (!BN_pseudo_rand(y, BN_num_bits(p), 0, 0)) {
+ goto end;
+ }
+ if (BN_ucmp(y, p) >= 0) {
+ if (!(p->neg ? BN_add : BN_sub)(y, y, p)) {
+ goto end;
+ }
+ }
+ /* now 0 <= y < |p| */
+ if (BN_is_zero(y)) {
+ if (!BN_set_word(y, i)) {
+ goto end;
+ }
+ }
+ }
+
+ r = BN_kronecker(y, q, ctx); /* here 'q' is |p| */
+ if (r < -1) {
+ goto end;
+ }
+ if (r == 0) {
+ /* m divides p */
+ OPENSSL_PUT_ERROR(BN, BN_mod_sqrt, BN_R_P_IS_NOT_PRIME);
+ goto end;
+ }
+ } while (r == 1 && ++i < 82);
+
+ if (r != -1) {
+ /* Many rounds and still no non-square -- this is more likely
+ * a bug than just bad luck.
+ * Even if p is not prime, we should have found some y
+ * such that r == -1.
+ */
+ OPENSSL_PUT_ERROR(BN, BN_mod_sqrt, BN_R_TOO_MANY_ITERATIONS);
+ goto end;
+ }
+
+ /* Here's our actual 'q': */
+ if (!BN_rshift(q, q, e)) {
+ goto end;
+ }
+
+ /* Now that we have some non-square, we can find an element
+ * of order 2^e by computing its q'th power. */
+ if (!BN_mod_exp(y, y, q, p, ctx)) {
+ goto end;
+ }
+ if (BN_is_one(y)) {
+ OPENSSL_PUT_ERROR(BN, BN_mod_sqrt, BN_R_P_IS_NOT_PRIME);
+ goto end;
+ }
+
+ /* Now we know that (if p is indeed prime) there is an integer
+ * k, 0 <= k < 2^e, such that
+ *
+ * a^q * y^k == 1 (mod p).
+ *
+ * As a^q is a square and y is not, k must be even.
+ * q+1 is even, too, so there is an element
+ *
+ * X := a^((q+1)/2) * y^(k/2),
+ *
+ * and it satisfies
+ *
+ * X^2 = a^q * a * y^k
+ * = a,
+ *
+ * so it is the square root that we are looking for.
+ */
+
+ /* t := (q-1)/2 (note that q is odd) */
+ if (!BN_rshift1(t, q)) {
+ goto end;
+ }
+
+ /* x := a^((q-1)/2) */
+ if (BN_is_zero(t)) /* special case: p = 2^e + 1 */
+ {
+ if (!BN_nnmod(t, A, p, ctx)) {
+ goto end;
+ }
+ if (BN_is_zero(t)) {
+ /* special case: a == 0 (mod p) */
+ BN_zero(ret);
+ err = 0;
+ goto end;
+ } else if (!BN_one(x)) {
+ goto end;
+ }
+ } else {
+ if (!BN_mod_exp(x, A, t, p, ctx)) {
+ goto end;
+ }
+ if (BN_is_zero(x)) {
+ /* special case: a == 0 (mod p) */
+ BN_zero(ret);
+ err = 0;
+ goto end;
+ }
+ }
+
+ /* b := a*x^2 (= a^q) */
+ if (!BN_mod_sqr(b, x, p, ctx) ||
+ !BN_mod_mul(b, b, A, p, ctx)) {
+ goto end;
+ }
+
+ /* x := a*x (= a^((q+1)/2)) */
+ if (!BN_mod_mul(x, x, A, p, ctx)) {
+ goto end;
+ }
+
+ while (1) {
+ /* Now b is a^q * y^k for some even k (0 <= k < 2^E
+ * where E refers to the original value of e, which we
+ * don't keep in a variable), and x is a^((q+1)/2) * y^(k/2).
+ *
+ * We have a*b = x^2,
+ * y^2^(e-1) = -1,
+ * b^2^(e-1) = 1.
+ */
+
+ if (BN_is_one(b)) {
+ if (!BN_copy(ret, x)) {
+ goto end;
+ }
+ err = 0;
+ goto vrfy;
+ }
+
+
+ /* find smallest i such that b^(2^i) = 1 */
+ i = 1;
+ if (!BN_mod_sqr(t, b, p, ctx)) {
+ goto end;
+ }
+ while (!BN_is_one(t)) {
+ i++;
+ if (i == e) {
+ OPENSSL_PUT_ERROR(BN, BN_mod_sqrt, BN_R_NOT_A_SQUARE);
+ goto end;
+ }
+ if (!BN_mod_mul(t, t, t, p, ctx)) {
+ goto end;
+ }
+ }
+
+
+ /* t := y^2^(e - i - 1) */
+ if (!BN_copy(t, y)) {
+ goto end;
+ }
+ for (j = e - i - 1; j > 0; j--) {
+ if (!BN_mod_sqr(t, t, p, ctx)) {
+ goto end;
+ }
+ }
+ if (!BN_mod_mul(y, t, t, p, ctx) ||
+ !BN_mod_mul(x, x, t, p, ctx) ||
+ !BN_mod_mul(b, b, y, p, ctx)) {
+ goto end;
+ }
+ e = i;
+ }
+
+vrfy:
+ if (!err) {
+ /* verify the result -- the input might have been not a square
+ * (test added in 0.9.8) */
+
+ if (!BN_mod_sqr(x, ret, p, ctx)) {
+ err = 1;
+ }
+
+ if (!err && 0 != BN_cmp(x, A)) {
+ OPENSSL_PUT_ERROR(BN, BN_mod_sqrt, BN_R_NOT_A_SQUARE);
+ err = 1;
+ }
+ }
+
+end:
+ if (err) {
+ if (ret != NULL && ret != in) {
+ BN_clear_free(ret);
+ }
+ ret = NULL;
+ }
+ BN_CTX_end(ctx);
+ return ret;
+}
+
+int BN_sqrt(BIGNUM *out_sqrt, const BIGNUM *in, BN_CTX *ctx) {
+ BIGNUM *estimate, *tmp, *delta, *last_delta, *tmp2;
+ int ok = 0, last_delta_valid = 0;
+
+ if (in->neg) {
+ OPENSSL_PUT_ERROR(BN, BN_sqrt, BN_R_NEGATIVE_NUMBER);
+ return 0;
+ }
+ if (BN_is_zero(in)) {
+ BN_zero(out_sqrt);
+ return 1;
+ }
+
+ BN_CTX_start(ctx);
+ if (out_sqrt == in) {
+ estimate = BN_CTX_get(ctx);
+ } else {
+ estimate = out_sqrt;
+ }
+ tmp = BN_CTX_get(ctx);
+ last_delta = BN_CTX_get(ctx);
+ delta = BN_CTX_get(ctx);
+ if (estimate == NULL || tmp == NULL || last_delta == NULL || delta == NULL) {
+ OPENSSL_PUT_ERROR(BN, BN_sqrt, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ /* We estimate that the square root of an n-bit number is 2^{n/2}. */
+ BN_lshift(estimate, BN_value_one(), BN_num_bits(in)/2);
+
+ /* This is Newton's method for finding a root of the equation |estimate|^2 -
+ * |in| = 0. */
+ for (;;) {
+ /* |estimate| = 1/2 * (|estimate| + |in|/|estimate|) */
+ if (!BN_div(tmp, NULL, in, estimate, ctx) ||
+ !BN_add(tmp, tmp, estimate) ||
+ !BN_rshift1(estimate, tmp) ||
+ /* |tmp| = |estimate|^2 */
+ !BN_sqr(tmp, estimate, ctx) ||
+ /* |delta| = |in| - |tmp| */
+ !BN_sub(delta, in, tmp)) {
+ OPENSSL_PUT_ERROR(BN, BN_sqrt, ERR_R_BN_LIB);
+ goto err;
+ }
+
+ delta->neg = 0;
+ /* The difference between |in| and |estimate| squared is required to always
+ * decrease. This ensures that the loop always terminates, but I don't have
+ * a proof that it always finds the square root for a given square. */
+ if (last_delta_valid && BN_cmp(delta, last_delta) >= 0) {
+ break;
+ }
+
+ last_delta_valid = 1;
+
+ tmp2 = last_delta;
+ last_delta = delta;
+ delta = tmp2;
+ }
+
+ if (BN_cmp(tmp, in) != 0) {
+ OPENSSL_PUT_ERROR(BN, BN_sqrt, BN_R_NOT_A_SQUARE);
+ goto err;
+ }
+
+ ok = 1;
+
+err:
+ if (ok && out_sqrt == in) {
+ BN_copy(out_sqrt, estimate);
+ }
+ BN_CTX_end(ctx);
+ return ok;
+}
diff --git a/src/crypto/buf/CMakeLists.txt b/src/crypto/buf/CMakeLists.txt
new file mode 100644
index 0000000..dabf8d1
--- /dev/null
+++ b/src/crypto/buf/CMakeLists.txt
@@ -0,0 +1,10 @@
+include_directories(. .. ../../include)
+
+add_library(
+ buf
+
+ OBJECT
+
+ buf.c
+ buf_error.c
+)
diff --git a/src/crypto/buf/buf.c b/src/crypto/buf/buf.c
new file mode 100644
index 0000000..5769e77
--- /dev/null
+++ b/src/crypto/buf/buf.c
@@ -0,0 +1,235 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/buf.h>
+
+#include <string.h>
+
+#include <openssl/mem.h>
+#include <openssl/err.h>
+
+
+BUF_MEM *BUF_MEM_new(void) {
+ BUF_MEM *ret;
+
+ ret = OPENSSL_malloc(sizeof(BUF_MEM));
+ if (ret == NULL) {
+ OPENSSL_PUT_ERROR(BUF, BUF_MEM_new, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ memset(ret, 0, sizeof(BUF_MEM));
+ return ret;
+}
+
+void BUF_MEM_free(BUF_MEM *buf) {
+ if (buf == NULL) {
+ return;
+ }
+
+ if (buf->data != NULL) {
+ OPENSSL_cleanse(buf->data, buf->max);
+ OPENSSL_free(buf->data);
+ }
+
+ OPENSSL_free(buf);
+}
+
+static size_t buf_mem_grow(BUF_MEM *buf, size_t len, char clean) {
+ char *new_buf;
+ size_t n, alloc_size;
+
+ if (buf->length >= len) {
+ buf->length = len;
+ return len;
+ }
+ if (buf->max >= len) {
+ memset(&buf->data[buf->length], 0, len - buf->length);
+ buf->length = len;
+ return len;
+ }
+
+ n = len + 3;
+ if (n < len) {
+ /* overflow */
+ OPENSSL_PUT_ERROR(BUF, buf_mem_grow, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ n = n / 3;
+ alloc_size = n * 4;
+ if (alloc_size / 4 != n) {
+ /* overflow */
+ OPENSSL_PUT_ERROR(BUF, buf_mem_grow, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ if (buf->data == NULL) {
+ new_buf = OPENSSL_malloc(alloc_size);
+ } else {
+ if (clean) {
+ new_buf = OPENSSL_realloc_clean(buf->data, buf->max, alloc_size);
+ } else {
+ new_buf = OPENSSL_realloc(buf->data, alloc_size);
+ }
+ }
+
+ if (new_buf == NULL) {
+ OPENSSL_PUT_ERROR(BUF, buf_mem_grow, ERR_R_MALLOC_FAILURE);
+ len = 0;
+ } else {
+ buf->data = new_buf;
+ buf->max = alloc_size;
+ memset(&buf->data[buf->length], 0, len - buf->length);
+ buf->length = len;
+ }
+
+ return len;
+}
+
+size_t BUF_MEM_grow(BUF_MEM *buf, size_t len) {
+ return buf_mem_grow(buf, len, 0 /* don't clear old buffer contents. */);
+}
+
+size_t BUF_MEM_grow_clean(BUF_MEM *buf, size_t len) {
+ return buf_mem_grow(buf, len, 1 /* clear old buffer contents. */);
+}
+
+char *BUF_strdup(const char *buf) {
+ if (buf == NULL) {
+ return NULL;
+ }
+
+ return BUF_strndup(buf, strlen(buf));
+}
+
+size_t BUF_strnlen(const char *str, size_t max_len) {
+ size_t i;
+
+ for (i = 0; i < max_len; i++) {
+ if (str[i] == 0) {
+ break;
+ }
+ }
+
+ return i;
+}
+
+char *BUF_strndup(const char *buf, size_t size) {
+ char *ret;
+ size_t alloc_size;
+
+ if (buf == NULL) {
+ return NULL;
+ }
+
+ size = BUF_strnlen(buf, size);
+
+ alloc_size = size + 1;
+ if (alloc_size < size) {
+ /* overflow */
+ OPENSSL_PUT_ERROR(BUF, BUF_strndup, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ ret = OPENSSL_malloc(alloc_size);
+ if (ret == NULL) {
+ OPENSSL_PUT_ERROR(BUF, BUF_strndup, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ memcpy(ret, buf, size);
+ ret[size] = '\0';
+ return ret;
+}
+
+size_t BUF_strlcpy(char *dst, const char *src, size_t dst_size) {
+ size_t l = 0;
+
+ for (; dst_size > 1 && *src; dst_size--) {
+ *dst++ = *src++;
+ l++;
+ }
+
+ if (dst_size) {
+ *dst = 0;
+ }
+
+ return l + strlen(src);
+}
+
+size_t BUF_strlcat(char *dst, const char *src, size_t dst_size) {
+ size_t l = 0;
+ for (; dst_size > 0 && *dst; dst_size--, dst++) {
+ l++;
+ }
+ return l + BUF_strlcpy(dst, src, dst_size);
+}
+
+void *BUF_memdup(const void *data, size_t dst_size) {
+ void *ret;
+
+ if (data == NULL) {
+ return NULL;
+ }
+
+ ret = OPENSSL_malloc(dst_size);
+ if (ret == NULL) {
+ OPENSSL_PUT_ERROR(BUF, BUF_memdup, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ memcpy(ret, data, dst_size);
+ return ret;
+}
diff --git a/src/crypto/buf/buf_error.c b/src/crypto/buf/buf_error.c
new file mode 100644
index 0000000..fac6011
--- /dev/null
+++ b/src/crypto/buf/buf_error.c
@@ -0,0 +1,25 @@
+/* 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 <openssl/err.h>
+
+#include <openssl/buf.h>
+
+const ERR_STRING_DATA BUF_error_string_data[] = {
+ {ERR_PACK(ERR_LIB_BUF, BUF_F_BUF_MEM_new, 0), "BUF_MEM_new"},
+ {ERR_PACK(ERR_LIB_BUF, BUF_F_BUF_memdup, 0), "BUF_memdup"},
+ {ERR_PACK(ERR_LIB_BUF, BUF_F_BUF_strndup, 0), "BUF_strndup"},
+ {ERR_PACK(ERR_LIB_BUF, BUF_F_buf_mem_grow, 0), "buf_mem_grow"},
+ {0, NULL},
+};
diff --git a/src/crypto/bytestring/CMakeLists.txt b/src/crypto/bytestring/CMakeLists.txt
new file mode 100644
index 0000000..8d6be7b
--- /dev/null
+++ b/src/crypto/bytestring/CMakeLists.txt
@@ -0,0 +1,19 @@
+include_directories(. .. ../../include)
+
+add_library(
+ bytestring
+
+ OBJECT
+
+ ber.c
+ cbs.c
+ cbb.c
+)
+
+add_executable(
+ bytestring_test
+
+ bytestring_test.c
+)
+
+target_link_libraries(bytestring_test crypto)
diff --git a/src/crypto/bytestring/ber.c b/src/crypto/bytestring/ber.c
new file mode 100644
index 0000000..2729fa1
--- /dev/null
+++ b/src/crypto/bytestring/ber.c
@@ -0,0 +1,219 @@
+/* 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 <openssl/bytestring.h>
+
+#include <string.h>
+
+#include "internal.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 kMaxDepth = 2048;
+
+/* cbs_find_ber walks an ASN.1 structure in |orig_in| and sets |*ber_found|
+ * depending on whether an indefinite length element was found. The value of
+ * |in| is not changed. It returns one on success (i.e. |*ber_found| was set)
+ * and zero on error. */
+static int cbs_find_ber(CBS *orig_in, char *ber_found, unsigned depth) {
+ CBS in;
+
+ if (depth > kMaxDepth) {
+ return 0;
+ }
+
+ CBS_init(&in, CBS_data(orig_in), CBS_len(orig_in));
+ *ber_found = 0;
+
+ while (CBS_len(&in) > 0) {
+ CBS contents;
+ unsigned tag;
+ size_t header_len;
+
+ if (!CBS_get_any_asn1_element(&in, &contents, &tag, &header_len)) {
+ return 0;
+ }
+ if (CBS_len(&contents) == header_len &&
+ header_len > 0 &&
+ CBS_data(&contents)[header_len-1] == 0x80) {
+ *ber_found = 1;
+ return 1;
+ }
+ if (tag & CBS_ASN1_CONSTRUCTED) {
+ if (!CBS_skip(&contents, header_len) ||
+ !cbs_find_ber(&contents, ber_found, depth + 1)) {
+ return 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 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_get_any_asn1_element|, indicate an "end of contents" (EOC) value. */
+static char is_eoc(size_t header_len, CBS *contents) {
+ return header_len == 2 && CBS_len(contents) == 2 &&
+ memcmp(CBS_data(contents), "\x00\x00", 2) == 0;
+}
+
+/* cbs_convert_ber reads BER data from |in| and writes 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_ber(CBS *in, CBB *out, char squash_header,
+ char looking_for_eoc, unsigned depth) {
+ if (depth > kMaxDepth) {
+ return 0;
+ }
+
+ while (CBS_len(in) > 0) {
+ CBS contents;
+ unsigned tag;
+ size_t header_len;
+ CBB *out_contents, out_contents_storage;
+
+ if (!CBS_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 BER
+ * 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 inner_tag;
+ size_t inner_header_len;
+
+ CBS_init(&in_copy, CBS_data(in), CBS_len(in));
+ if (!CBS_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 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_ber(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_ber(&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_ber_to_der(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_ber(in, &conversion_needed, 0)) {
+ return 0;
+ }
+
+ if (!conversion_needed) {
+ *out = NULL;
+ *out_len = 0;
+ return 1;
+ }
+
+ CBB_init(&cbb, CBS_len(in));
+ if (!cbs_convert_ber(in, &cbb, 0, 0, 0)) {
+ CBB_cleanup(&cbb);
+ return 0;
+ }
+
+ return CBB_finish(&cbb, out, out_len);
+}
diff --git a/src/crypto/bytestring/bytestring_test.c b/src/crypto/bytestring/bytestring_test.c
new file mode 100644
index 0000000..cd0155e
--- /dev/null
+++ b/src/crypto/bytestring/bytestring_test.c
@@ -0,0 +1,655 @@
+/* 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <openssl/crypto.h>
+#include <openssl/bytestring.h>
+
+#include "internal.h"
+#include "../internal.h"
+
+
+static int test_skip(void) {
+ static const uint8_t kData[] = {1, 2, 3};
+ CBS data;
+
+ CBS_init(&data, kData, sizeof(kData));
+ return CBS_len(&data) == 3 &&
+ CBS_skip(&data, 1) &&
+ CBS_len(&data) == 2 &&
+ CBS_skip(&data, 2) &&
+ CBS_len(&data) == 0 &&
+ !CBS_skip(&data, 1);
+}
+
+static int test_get_u(void) {
+ static const uint8_t kData[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+ uint8_t u8;
+ uint16_t u16;
+ uint32_t u32;
+ CBS data;
+
+ CBS_init(&data, kData, sizeof(kData));
+ return CBS_get_u8(&data, &u8) &&
+ u8 == 1 &&
+ CBS_get_u16(&data, &u16) &&
+ u16 == 0x203 &&
+ CBS_get_u24(&data, &u32) &&
+ u32 == 0x40506 &&
+ CBS_get_u32(&data, &u32) &&
+ u32 == 0x708090a &&
+ !CBS_get_u8(&data, &u8);
+}
+
+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));
+ return CBS_get_u8_length_prefixed(&data, &prefixed) &&
+ CBS_len(&prefixed) == 1 &&
+ CBS_get_u8(&prefixed, &u8) &&
+ u8 == 2 &&
+ CBS_get_u16_length_prefixed(&data, &prefixed) &&
+ CBS_len(&prefixed) == 2 &&
+ CBS_get_u16(&prefixed, &u16) &&
+ u16 == 0x304 &&
+ CBS_get_u24_length_prefixed(&data, &prefixed) &&
+ CBS_len(&prefixed) == 3 &&
+ CBS_get_u24(&prefixed, &u32) &&
+ u32 == 0x30201;
+}
+
+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));
+ if (CBS_get_u8_length_prefixed(&data, &prefixed)) {
+ return 0;
+ }
+
+ CBS_init(&data, kData2, sizeof(kData2));
+ if (CBS_get_u16_length_prefixed(&data, &prefixed)) {
+ return 0;
+ }
+
+ CBS_init(&data, kData3, sizeof(kData3));
+ if (CBS_get_u24_length_prefixed(&data, &prefixed)) {
+ return 0;
+ }
+
+ 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[] = {0x30, 0x82, 0, 1, 1};
+ 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));
+ if (CBS_peek_asn1_tag(&data, 0x1) ||
+ !CBS_peek_asn1_tag(&data, 0x30)) {
+ return 0;
+ }
+ if (!CBS_get_asn1(&data, &contents, 0x30) ||
+ CBS_len(&contents) != 2 ||
+ memcmp(CBS_data(&contents), "\x01\x02", 2) != 0) {
+ return 0;
+ }
+
+ CBS_init(&data, kData2, sizeof(kData2));
+ /* data is truncated */
+ if (CBS_get_asn1(&data, &contents, 0x30)) {
+ return 0;
+ }
+
+ CBS_init(&data, kData3, sizeof(kData3));
+ /* zero byte length of length */
+ if (CBS_get_asn1(&data, &contents, 0x30)) {
+ return 0;
+ }
+
+ CBS_init(&data, kData4, sizeof(kData4));
+ /* long form mistakenly used. */
+ if (CBS_get_asn1(&data, &contents, 0x30)) {
+ return 0;
+ }
+
+ CBS_init(&data, kData5, sizeof(kData5));
+ /* length takes too many bytes. */
+ if (CBS_get_asn1(&data, &contents, 0x30)) {
+ return 0;
+ }
+
+ CBS_init(&data, kData1, sizeof(kData1));
+ /* wrong tag. */
+ if (CBS_get_asn1(&data, &contents, 0x31)) {
+ return 0;
+ }
+
+ CBS_init(&data, NULL, 0);
+ /* peek at empty data. */
+ if (CBS_peek_asn1_tag(&data, 0x30)) {
+ return 0;
+ }
+
+ CBS_init(&data, NULL, 0);
+ /* optional elements at empty data. */
+ if (!CBS_get_optional_asn1(&data, &contents, &present, 0xa0) ||
+ present ||
+ !CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa0) ||
+ present ||
+ CBS_len(&contents) != 0 ||
+ !CBS_get_optional_asn1_octet_string(&data, &contents, NULL, 0xa0) ||
+ CBS_len(&contents) != 0 ||
+ !CBS_get_optional_asn1_uint64(&data, &value, 0xa0, 42) ||
+ value != 42) {
+ return 0;
+ }
+
+ CBS_init(&data, kData6, sizeof(kData6));
+ /* optional element. */
+ if (!CBS_get_optional_asn1(&data, &contents, &present, 0xa0) ||
+ present ||
+ !CBS_get_optional_asn1(&data, &contents, &present, 0xa1) ||
+ !present ||
+ CBS_len(&contents) != 3 ||
+ memcmp(CBS_data(&contents), "\x04\x01\x01", 3) != 0) {
+ return 0;
+ }
+
+ CBS_init(&data, kData6, sizeof(kData6));
+ /* optional octet string. */
+ if (!CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa0) ||
+ present ||
+ CBS_len(&contents) != 0 ||
+ !CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa1) ||
+ !present ||
+ CBS_len(&contents) != 1 ||
+ CBS_data(&contents)[0] != 1) {
+ return 0;
+ }
+
+ CBS_init(&data, kData7, sizeof(kData7));
+ /* invalid optional octet string. */
+ if (CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa1)) {
+ return 0;
+ }
+
+ CBS_init(&data, kData8, sizeof(kData8));
+ /* optional octet string. */
+ if (!CBS_get_optional_asn1_uint64(&data, &value, 0xa0, 42) ||
+ value != 42 ||
+ !CBS_get_optional_asn1_uint64(&data, &value, 0xa1, 42) ||
+ value != 1) {
+ return 0;
+ }
+
+ CBS_init(&data, kData9, sizeof(kData9));
+ /* invalid optional integer. */
+ if (CBS_get_optional_asn1_uint64(&data, &value, 0xa1, 42)) {
+ return 0;
+ }
+
+ 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;
+ if (!CBS_get_optional_asn1_bool(&data, &val, 0x0a, 0) ||
+ val != 0) {
+ return 0;
+ }
+
+ CBS_init(&data, kTrue, sizeof(kTrue));
+ val = 2;
+ if (!CBS_get_optional_asn1_bool(&data, &val, 0x0a, 0) ||
+ val != 1) {
+ return 0;
+ }
+
+ CBS_init(&data, kFalse, sizeof(kFalse));
+ val = 2;
+ if (!CBS_get_optional_asn1_bool(&data, &val, 0x0a, 1) ||
+ val != 0) {
+ return 0;
+ }
+
+ CBS_init(&data, kInvalid, sizeof(kInvalid));
+ if (CBS_get_optional_asn1_bool(&data, &val, 0x0a, 1)) {
+ return 0;
+ }
+
+ return 1;
+}
+
+static int test_cbb_basic(void) {
+ static const uint8_t kExpected[] = {1, 2, 3, 4, 5, 6, 7, 8};
+ uint8_t *buf;
+ size_t buf_len;
+ int ok;
+ CBB cbb;
+
+ if (!CBB_init(&cbb, 100)) {
+ return 0;
+ }
+ CBB_cleanup(&cbb);
+
+ if (!CBB_init(&cbb, 0) ||
+ !CBB_add_u8(&cbb, 1) ||
+ !CBB_add_u16(&cbb, 0x203) ||
+ !CBB_add_u24(&cbb, 0x40506) ||
+ !CBB_add_bytes(&cbb, (const uint8_t*) "\x07\x08", 2) ||
+ !CBB_finish(&cbb, &buf, &buf_len)) {
+ return 0;
+ }
+
+ ok = buf_len == sizeof(kExpected) && memcmp(buf, kExpected, buf_len) == 0;
+ free(buf);
+ return ok;
+}
+
+static int test_cbb_fixed(void) {
+ CBB cbb;
+ uint8_t buf[1];
+ uint8_t *out_buf;
+ size_t out_size;
+
+ if (!CBB_init_fixed(&cbb, NULL, 0) ||
+ CBB_add_u8(&cbb, 1) ||
+ !CBB_finish(&cbb, &out_buf, &out_size) ||
+ out_buf != NULL ||
+ out_size != 0) {
+ return 0;
+ }
+
+ if (!CBB_init_fixed(&cbb, buf, 1) ||
+ !CBB_add_u8(&cbb, 1) ||
+ CBB_add_u8(&cbb, 2) ||
+ !CBB_finish(&cbb, &out_buf, &out_size) ||
+ out_buf != buf ||
+ out_size != 1 ||
+ buf[0] != 1) {
+ return 0;
+ }
+
+ return 1;
+}
+
+static int test_cbb_finish_child(void) {
+ CBB cbb, child;
+ uint8_t *out_buf;
+ size_t out_size;
+
+ if (!CBB_init(&cbb, 16) ||
+ !CBB_add_u8_length_prefixed(&cbb, &child) ||
+ CBB_finish(&child, &out_buf, &out_size) ||
+ !CBB_finish(&cbb, &out_buf, &out_size) ||
+ out_size != 1 ||
+ out_buf[0] != 0) {
+ return 0;
+ }
+
+ free(out_buf);
+ return 1;
+}
+
+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};
+ uint8_t *buf;
+ size_t buf_len;
+ CBB cbb, contents, inner_contents, inner_inner_contents;
+ int ok;
+
+ if (!CBB_init(&cbb, 0) ||
+ !CBB_add_u8_length_prefixed(&cbb, &contents) ||
+ !CBB_add_u8_length_prefixed(&cbb, &contents) ||
+ !CBB_add_u8(&contents, 1) ||
+ !CBB_add_u16_length_prefixed(&cbb, &contents) ||
+ !CBB_add_u16(&contents, 0x203) ||
+ !CBB_add_u24_length_prefixed(&cbb, &contents) ||
+ !CBB_add_u24(&contents, 0x40506) ||
+ !CBB_add_u8_length_prefixed(&cbb, &contents) ||
+ !CBB_add_u8_length_prefixed(&contents, &inner_contents) ||
+ !CBB_add_u8(&inner_contents, 1) ||
+ !CBB_add_u16_length_prefixed(&inner_contents, &inner_inner_contents) ||
+ !CBB_add_u8(&inner_inner_contents, 2) ||
+ !CBB_finish(&cbb, &buf, &buf_len)) {
+ return 0;
+ }
+
+ ok = buf_len == sizeof(kExpected) && memcmp(buf, kExpected, buf_len) == 0;
+ free(buf);
+ return ok;
+}
+
+static int test_cbb_misuse(void) {
+ CBB cbb, child, contents;
+ uint8_t *buf;
+ size_t buf_len;
+
+ if (!CBB_init(&cbb, 0) ||
+ !CBB_add_u8_length_prefixed(&cbb, &child) ||
+ !CBB_add_u8(&child, 1) ||
+ !CBB_add_u8(&cbb, 2)) {
+ return 0;
+ }
+
+ /* Since we wrote to |cbb|, |child| is now invalid and attempts to write to
+ * it should fail. */
+ if (CBB_add_u8(&child, 1) ||
+ CBB_add_u16(&child, 1) ||
+ CBB_add_u24(&child, 1) ||
+ CBB_add_u8_length_prefixed(&child, &contents) ||
+ CBB_add_u16_length_prefixed(&child, &contents) ||
+ CBB_add_asn1(&child, &contents, 1) ||
+ CBB_add_bytes(&child, (const uint8_t*) "a", 1)) {
+ fprintf(stderr, "CBB operation on invalid CBB did not fail.\n");
+ return 0;
+ }
+
+ if (!CBB_finish(&cbb, &buf, &buf_len) ||
+ buf_len != 3 ||
+ memcmp(buf, "\x01\x01\x02", 3) != 0) {
+ return 0;
+ }
+
+ free(buf);
+
+ return 1;
+}
+
+static int test_cbb_asn1(void) {
+ static const uint8_t kExpected[] = {0x30, 3, 1, 2, 3};
+ uint8_t *buf, *test_data;
+ size_t buf_len;
+ CBB cbb, contents, inner_contents;
+
+ if (!CBB_init(&cbb, 0) ||
+ !CBB_add_asn1(&cbb, &contents, 0x30) ||
+ !CBB_add_bytes(&contents, (const uint8_t*) "\x01\x02\x03", 3) ||
+ !CBB_finish(&cbb, &buf, &buf_len)) {
+ return 0;
+ }
+
+ if (buf_len != sizeof(kExpected) || memcmp(buf, kExpected, buf_len) != 0) {
+ return 0;
+ }
+ free(buf);
+
+ test_data = malloc(100000);
+ memset(test_data, 0x42, 100000);
+
+ if (!CBB_init(&cbb, 0) ||
+ !CBB_add_asn1(&cbb, &contents, 0x30) ||
+ !CBB_add_bytes(&contents, test_data, 130) ||
+ !CBB_finish(&cbb, &buf, &buf_len)) {
+ return 0;
+ }
+
+ if (buf_len != 3 + 130 ||
+ memcmp(buf, "\x30\x81\x82", 3) != 0 ||
+ memcmp(buf + 3, test_data, 130) != 0) {
+ return 0;
+ }
+ free(buf);
+
+ if (!CBB_init(&cbb, 0) ||
+ !CBB_add_asn1(&cbb, &contents, 0x30) ||
+ !CBB_add_bytes(&contents, test_data, 1000) ||
+ !CBB_finish(&cbb, &buf, &buf_len)) {
+ return 0;
+ }
+
+ if (buf_len != 4 + 1000 ||
+ memcmp(buf, "\x30\x82\x03\xe8", 4) != 0 ||
+ memcmp(buf + 4, test_data, 1000)) {
+ return 0;
+ }
+ free(buf);
+
+ if (!CBB_init(&cbb, 0) ||
+ !CBB_add_asn1(&cbb, &contents, 0x30) ||
+ !CBB_add_asn1(&contents, &inner_contents, 0x30) ||
+ !CBB_add_bytes(&inner_contents, test_data, 100000) ||
+ !CBB_finish(&cbb, &buf, &buf_len)) {
+ return 0;
+ }
+
+ if (buf_len != 5 + 5 + 100000 ||
+ memcmp(buf, "\x30\x83\x01\x86\xa5\x30\x83\x01\x86\xa0", 10) != 0 ||
+ memcmp(buf + 10, test_data, 100000)) {
+ return 0;
+ }
+ free(buf);
+
+ free(test_data);
+ return 1;
+}
+
+static int do_ber_convert(const char *name,
+ const uint8_t *der_expected, size_t der_len,
+ const uint8_t *ber, size_t ber_len) {
+ CBS in;
+ uint8_t *out;
+ size_t out_len;
+
+ CBS_init(&in, ber, ber_len);
+ if (!CBS_asn1_ber_to_der(&in, &out, &out_len)) {
+ fprintf(stderr, "%s: CBS_asn1_ber_to_der failed.\n", name);
+ return 0;
+ }
+
+ if (out == NULL) {
+ if (ber_len != der_len ||
+ memcmp(der_expected, ber, ber_len) != 0) {
+ fprintf(stderr, "%s: incorrect unconverted result.\n", name);
+ return 0;
+ }
+
+ return 1;
+ }
+
+ if (out_len != der_len ||
+ memcmp(out, der_expected, der_len) != 0) {
+ fprintf(stderr, "%s: incorrect converted result.\n", name);
+ return 0;
+ }
+
+ free(out);
+ return 1;
+}
+
+static int test_ber_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,
+ };
+
+ return do_ber_convert("kSimpleBER", kSimpleBER, sizeof(kSimpleBER),
+ kSimpleBER, sizeof(kSimpleBER)) &&
+ do_ber_convert("kIndefBER", kIndefDER, sizeof(kIndefDER), kIndefBER,
+ sizeof(kIndefBER)) &&
+ do_ber_convert("kOctetStringBER", kOctetStringDER,
+ sizeof(kOctetStringDER), kOctetStringBER,
+ sizeof(kOctetStringBER)) &&
+ do_ber_convert("kNSSBER", kNSSDER, sizeof(kNSSDER), kNSSBER,
+ sizeof(kNSSBER));
+}
+
+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},
+};
+
+static int test_asn1_uint64(void) {
+ size_t i;
+
+ for (i = 0; i < sizeof(kAsn1Uint64Tests) / sizeof(kAsn1Uint64Tests[0]); i++) {
+ const ASN1_UINT64_TEST *test = &kAsn1Uint64Tests[i];
+ CBS cbs;
+ uint64_t value;
+ CBB cbb;
+ uint8_t *out;
+ size_t len;
+
+ CBS_init(&cbs, (const uint8_t *)test->encoding, test->encoding_len);
+ if (!CBS_get_asn1_uint64(&cbs, &value) ||
+ CBS_len(&cbs) != 0 ||
+ value != test->value) {
+ return 0;
+ }
+
+ if (!CBB_init(&cbb, 0)) {
+ return 0;
+ }
+ if (!CBB_add_asn1_uint64(&cbb, test->value) ||
+ !CBB_finish(&cbb, &out, &len)) {
+ CBB_cleanup(&cbb);
+ return 0;
+ }
+ if (len != test->encoding_len || memcmp(out, test->encoding, len) != 0) {
+ free(out);
+ return 0;
+ }
+ free(out);
+ }
+
+ 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);
+ if (CBS_get_asn1_uint64(&cbs, &value)) {
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+int main(void) {
+ CRYPTO_library_init();
+
+ if (!test_skip() ||
+ !test_get_u() ||
+ !test_get_prefixed() ||
+ !test_get_prefixed_bad() ||
+ !test_get_asn1() ||
+ !test_cbb_basic() ||
+ !test_cbb_fixed() ||
+ !test_cbb_finish_child() ||
+ !test_cbb_misuse() ||
+ !test_cbb_prefixed() ||
+ !test_cbb_asn1() ||
+ !test_ber_convert() ||
+ !test_asn1_uint64() ||
+ !test_get_optional_asn1_bool()) {
+ return 1;
+ }
+
+ printf("PASS\n");
+ return 0;
+}
diff --git a/src/crypto/bytestring/cbb.c b/src/crypto/bytestring/cbb.c
new file mode 100644
index 0000000..4428836
--- /dev/null
+++ b/src/crypto/bytestring/cbb.c
@@ -0,0 +1,375 @@
+/* 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 <openssl/bytestring.h>
+
+#include <assert.h>
+#include <string.h>
+
+#include <openssl/mem.h>
+
+
+static int cbb_init(CBB *cbb, uint8_t *buf, size_t cap) {
+ struct cbb_buffer_st *base;
+
+ base = OPENSSL_malloc(sizeof(struct cbb_buffer_st));
+ if (base == NULL) {
+ OPENSSL_free(buf);
+ return 0;
+ }
+
+ base->buf = buf;
+ base->len = 0;
+ base->cap = cap;
+ base->can_resize = 1;
+
+ memset(cbb, 0, sizeof(CBB));
+ cbb->base = base;
+ cbb->is_top_level = 1;
+ return 1;
+}
+
+int CBB_init(CBB *cbb, size_t initial_capacity) {
+ uint8_t *buf;
+
+ buf = OPENSSL_malloc(initial_capacity);
+ if (initial_capacity > 0 && buf == NULL) {
+ return 0;
+ }
+
+ return cbb_init(cbb, buf, initial_capacity);
+}
+
+int CBB_init_fixed(CBB *cbb, uint8_t *buf, size_t len) {
+ 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->buf && cbb->base->can_resize) {
+ OPENSSL_free(cbb->base->buf);
+ }
+ OPENSSL_free(cbb->base);
+ }
+ cbb->base = 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 = OPENSSL_realloc(base->buf, newcap);
+ 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_buffer_add_u(struct cbb_buffer_st *base, uint32_t v,
+ size_t len_len) {
+ uint8_t *buf;
+ size_t i;
+
+ if (len_len == 0) {
+ return 1;
+ }
+ if (!cbb_buffer_add(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 = 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 assume that we'll only need a single byte for the length.
+ * If that turned out to be incorrect, we have to move the contents along
+ * in order to make space. */
+ size_t len_len;
+ uint8_t initial_length_byte;
+
+ assert (cbb->pending_len_len == 1);
+
+ if (len > 0xfffffffe) {
+ /* Too large. */
+ return 0;
+ } else if (len > 0xffffff) {
+ len_len = 5;
+ initial_length_byte = 0x80 | 4;
+ } else if (len > 0xffff) {
+ len_len = 4;
+ initial_length_byte = 0x80 | 3;
+ } else if (len > 0xff) {
+ len_len = 3;
+ initial_length_byte = 0x80 | 2;
+ } else if (len > 0x7f) {
+ len_len = 2;
+ initial_length_byte = 0x80 | 1;
+ } else {
+ len_len = 1;
+ initial_length_byte = len;
+ len = 0;
+ }
+
+ if (len_len != 1) {
+ /* We need to move the contents along in order to make space. */
+ 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;
+}
+
+
+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, uint8_t tag) {
+ if (!CBB_flush(cbb) ||
+ !CBB_add_u8(cbb, tag)) {
+ return 0;
+ }
+
+ 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;
+ }
+ return 1;
+}
+
+int CBB_add_u8(CBB *cbb, uint8_t value) {
+ if (!CBB_flush(cbb)) {
+ return 0;
+ }
+
+ return cbb_buffer_add_u(cbb->base, value, 1);
+}
+
+int CBB_add_u16(CBB *cbb, uint16_t value) {
+ if (!CBB_flush(cbb)) {
+ return 0;
+ }
+
+ return cbb_buffer_add_u(cbb->base, value, 2);
+}
+
+int CBB_add_u24(CBB *cbb, uint32_t value) {
+ if (!CBB_flush(cbb)) {
+ return 0;
+ }
+
+ return cbb_buffer_add_u(cbb->base, value, 3);
+}
+
+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;
+ 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/src/crypto/bytestring/cbs.c b/src/crypto/bytestring/cbs.c
new file mode 100644
index 0000000..b417716
--- /dev/null
+++ b/src/crypto/bytestring/cbs.c
@@ -0,0 +1,388 @@
+/* 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 <openssl/buf.h>
+#include <openssl/mem.h>
+#include <openssl/bytestring.h>
+
+#include <assert.h>
+#include <string.h>
+
+#include "internal.h"
+
+
+void CBS_init(CBS *cbs, const uint8_t *data, size_t len) {
+ cbs->data = data;
+ cbs->len = 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;
+}
+
+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) {
+ if (*out_ptr != NULL) {
+ OPENSSL_free(*out_ptr);
+ *out_ptr = NULL;
+ }
+ *out_len = 0;
+
+ if (cbs->len == 0) {
+ return 1;
+ }
+ *out_ptr = BUF_memdup(cbs->data, cbs->len);
+ if (*out_ptr == NULL) {
+ return 0;
+ }
+ *out_len = cbs->len;
+ return 1;
+}
+
+int CBS_strdup(const CBS *cbs, char **out_ptr) {
+ if (*out_ptr != NULL) {
+ OPENSSL_free(*out_ptr);
+ }
+ *out_ptr = BUF_strndup((const char*)cbs->data, cbs->len);
+ return (*out_ptr != NULL);
+}
+
+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 CRYPTO_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 (!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_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);
+}
+
+int CBS_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
+ size_t *out_header_len) {
+ uint8_t tag, length_byte;
+ CBS header = *cbs;
+ CBS throwaway;
+
+ if (out == NULL) {
+ out = &throwaway;
+ }
+
+ if (!CBS_get_u8(&header, &tag) ||
+ !CBS_get_u8(&header, &length_byte)) {
+ return 0;
+ }
+
+ if ((tag & 0x1f) == 0x1f) {
+ /* Long form tags are not supported. */
+ return 0;
+ }
+
+ if (out_tag != NULL) {
+ *out_tag = tag;
+ }
+
+ size_t len;
+ 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;
+
+ if ((tag & CBS_ASN1_CONSTRUCTED) != 0 && num_bytes == 0) {
+ /* indefinite length */
+ *out_header_len = 2;
+ return CBS_get_bytes(cbs, out, 2);
+ }
+
+ if (num_bytes == 0 || num_bytes > 4) {
+ return 0;
+ }
+ if (!cbs_get_u(&header, &len32, num_bytes)) {
+ return 0;
+ }
+ if (len32 < 128) {
+ /* Length should have used short-form encoding. */
+ 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 tag_value,
+ int skip_header) {
+ size_t header_len;
+ unsigned tag;
+ CBS throwaway;
+
+ if (out == NULL) {
+ out = &throwaway;
+ }
+
+ if (!CBS_get_any_asn1_element(cbs, out, &tag, &header_len) ||
+ tag != tag_value ||
+ (header_len > 0 &&
+ /* This ensures that the tag is either zero length or
+ * indefinite-length. */
+ CBS_len(out) == header_len &&
+ CBS_data(out)[header_len - 1] == 0x80)) {
+ return 0;
+ }
+
+ if (skip_header && !CBS_skip(out, header_len)) {
+ assert(0);
+ return 0;
+ }
+
+ return 1;
+}
+
+int CBS_get_asn1(CBS *cbs, CBS *out, unsigned tag_value) {
+ return cbs_get_asn1(cbs, out, tag_value, 1 /* skip header */);
+}
+
+int CBS_get_asn1_element(CBS *cbs, CBS *out, unsigned tag_value) {
+ return cbs_get_asn1(cbs, out, tag_value, 0 /* include header */);
+}
+
+int CBS_peek_asn1_tag(const CBS *cbs, unsigned tag_value) {
+ if (CBS_len(cbs) < 1) {
+ return 0;
+ }
+ return CBS_data(cbs)[0] == tag_value;
+}
+
+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 octet. */
+ return 0;
+ }
+
+ if ((data[0] & 0x80) != 0) {
+ /* negative number */
+ 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 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 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 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 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/src/crypto/bytestring/internal.h b/src/crypto/bytestring/internal.h
new file mode 100644
index 0000000..b4ea7e5
--- /dev/null
+++ b/src/crypto/bytestring/internal.h
@@ -0,0 +1,46 @@
+/* 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_INTERNAL_H
+#define OPENSSL_HEADER_BYTESTRING_INTERNAL_H
+
+#include <openssl/base.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* CBS_asn1_ber_to_der reads an ASN.1 structure from |in|. If it finds
+ * indefinite-length elements then it attempts to convert the BER 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.
+ *
+ * A sufficiently complex ASN.1 structure will break this function because it's
+ * not possible to generically convert BER to DER without knowledge of the
+ * structure itself. However, this sufficies to handle the PKCS#7 and #12 output
+ * from NSS.
+ *
+ * It returns one on success and zero otherwise. */
+OPENSSL_EXPORT int CBS_asn1_ber_to_der(CBS *in, uint8_t **out, size_t *out_len);
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_BYTESTRING_INTERNAL_H */
diff --git a/src/crypto/chacha/CMakeLists.txt b/src/crypto/chacha/CMakeLists.txt
new file mode 100644
index 0000000..6c3f87e
--- /dev/null
+++ b/src/crypto/chacha/CMakeLists.txt
@@ -0,0 +1,20 @@
+include_directories(. .. ../../include)
+
+if (${ARCH} STREQUAL "arm")
+ set(
+ CHACHA_ARCH_SOURCES
+
+ chacha_vec_arm.S
+ )
+endif()
+
+add_library(
+ chacha
+
+ OBJECT
+
+ chacha_generic.c
+ chacha_vec.c
+
+ ${CHACHA_ARCH_SOURCES}
+)
diff --git a/src/crypto/chacha/chacha_generic.c b/src/crypto/chacha/chacha_generic.c
new file mode 100644
index 0000000..31cf4f0
--- /dev/null
+++ b/src/crypto/chacha/chacha_generic.c
@@ -0,0 +1,143 @@
+/* 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. */
+
+/* Adapted from the public domain, estream code by D. Bernstein. */
+
+#include <openssl/chacha.h>
+
+#include <string.h>
+
+#include <openssl/cpu.h>
+
+
+#if defined(OPENSSL_WINDOWS) || (!defined(OPENSSL_X86_64) && !defined(OPENSSL_X86)) || !defined(__SSE2__)
+
+/* sigma contains the ChaCha constants, which happen to be an ASCII string. */
+static const uint8_t sigma[16] = { 'e', 'x', 'p', 'a', 'n', 'd', ' ', '3',
+ '2', '-', 'b', 'y', 't', 'e', ' ', 'k' };
+
+#define ROTATE(v, n) (((v) << (n)) | ((v) >> (32 - (n))))
+#define XOR(v, w) ((v) ^ (w))
+#define PLUS(x, y) ((x) + (y))
+#define PLUSONE(v) (PLUS((v), 1))
+
+#define U32TO8_LITTLE(p, v) \
+ { \
+ (p)[0] = (v >> 0) & 0xff; \
+ (p)[1] = (v >> 8) & 0xff; \
+ (p)[2] = (v >> 16) & 0xff; \
+ (p)[3] = (v >> 24) & 0xff; \
+ }
+
+#define U8TO32_LITTLE(p) \
+ (((uint32_t)((p)[0])) | ((uint32_t)((p)[1]) << 8) | \
+ ((uint32_t)((p)[2]) << 16) | ((uint32_t)((p)[3]) << 24))
+
+/* QUARTERROUND updates a, b, c, d with a ChaCha "quarter" round. */
+#define QUARTERROUND(a,b,c,d) \
+ x[a] = PLUS(x[a],x[b]); x[d] = ROTATE(XOR(x[d],x[a]),16); \
+ x[c] = PLUS(x[c],x[d]); x[b] = ROTATE(XOR(x[b],x[c]),12); \
+ x[a] = PLUS(x[a],x[b]); x[d] = ROTATE(XOR(x[d],x[a]), 8); \
+ x[c] = PLUS(x[c],x[d]); x[b] = ROTATE(XOR(x[b],x[c]), 7);
+
+#if defined(OPENSSL_ARM) && !defined(OPENSSL_NO_ASM)
+/* Defined in chacha_vec.c */
+void CRYPTO_chacha_20_neon(uint8_t *out, const uint8_t *in, size_t in_len,
+ const uint8_t key[32], const uint8_t nonce[8],
+ size_t counter);
+#endif
+
+/* chacha_core performs 20 rounds of ChaCha on the input words in
+ * |input| and writes the 64 output bytes to |output|. */
+static void chacha_core(uint8_t output[64], const uint32_t input[16]) {
+ uint32_t x[16];
+ int i;
+
+ memcpy(x, input, sizeof(uint32_t) * 16);
+ for (i = 20; i > 0; i -= 2) {
+ QUARTERROUND(0, 4, 8, 12)
+ QUARTERROUND(1, 5, 9, 13)
+ QUARTERROUND(2, 6, 10, 14)
+ QUARTERROUND(3, 7, 11, 15)
+ QUARTERROUND(0, 5, 10, 15)
+ QUARTERROUND(1, 6, 11, 12)
+ QUARTERROUND(2, 7, 8, 13)
+ QUARTERROUND(3, 4, 9, 14)
+ }
+
+ for (i = 0; i < 16; ++i) {
+ x[i] = PLUS(x[i], input[i]);
+ }
+ for (i = 0; i < 16; ++i) {
+ U32TO8_LITTLE(output + 4 * i, x[i]);
+ }
+}
+
+void CRYPTO_chacha_20(uint8_t *out, const uint8_t *in, size_t in_len,
+ const uint8_t key[32], const uint8_t nonce[8],
+ size_t counter) {
+ uint32_t input[16];
+ uint8_t buf[64];
+ size_t todo, i;
+
+#if defined(OPENSSL_ARM) && !defined(OPENSSL_NO_ASM)
+ if (CRYPTO_is_NEON_capable()) {
+ CRYPTO_chacha_20_neon(out, in, in_len, key, nonce, counter);
+ return;
+ }
+#endif
+
+ input[0] = U8TO32_LITTLE(sigma + 0);
+ input[1] = U8TO32_LITTLE(sigma + 4);
+ input[2] = U8TO32_LITTLE(sigma + 8);
+ input[3] = U8TO32_LITTLE(sigma + 12);
+
+ input[4] = U8TO32_LITTLE(key + 0);
+ input[5] = U8TO32_LITTLE(key + 4);
+ input[6] = U8TO32_LITTLE(key + 8);
+ input[7] = U8TO32_LITTLE(key + 12);
+
+ input[8] = U8TO32_LITTLE(key + 16);
+ input[9] = U8TO32_LITTLE(key + 20);
+ input[10] = U8TO32_LITTLE(key + 24);
+ input[11] = U8TO32_LITTLE(key + 28);
+
+ input[12] = counter;
+ input[13] = ((uint64_t)counter) >> 32;
+ input[14] = U8TO32_LITTLE(nonce + 0);
+ input[15] = U8TO32_LITTLE(nonce + 4);
+
+ while (in_len > 0) {
+ todo = sizeof(buf);
+ if (in_len < todo) {
+ todo = in_len;
+ }
+
+ chacha_core(buf, input);
+ for (i = 0; i < todo; i++) {
+ out[i] = in[i] ^ buf[i];
+ }
+
+ out += todo;
+ in += todo;
+ in_len -= todo;
+
+ input[12]++;
+ if (input[12] == 0) {
+ input[13]++;
+ }
+ }
+}
+
+#endif /* OPENSSL_WINDOWS || !OPENSSL_X86_64 && !OPENSSL_X86 || !__SSE2__ */
diff --git a/src/crypto/chacha/chacha_vec.c b/src/crypto/chacha/chacha_vec.c
new file mode 100644
index 0000000..88830bc
--- /dev/null
+++ b/src/crypto/chacha/chacha_vec.c
@@ -0,0 +1,340 @@
+/* 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. */
+
+/* ====================================================================
+ *
+ * When updating this file, also update chacha_vec_arm.S
+ *
+ * ==================================================================== */
+
+
+/* This implementation is by Ted Krovetz and was submitted to SUPERCOP and
+ * marked as public domain. It was been altered to allow for non-aligned inputs
+ * and to allow the block counter to be passed in specifically. */
+
+#include <openssl/chacha.h>
+
+#if defined(ASM_GEN) || \
+ !defined(OPENSSL_WINDOWS) && \
+ (defined(OPENSSL_X86_64) || defined(OPENSSL_X86)) && defined(__SSE2__)
+
+#define CHACHA_RNDS 20 /* 8 (high speed), 20 (conservative), 12 (middle) */
+
+/* Architecture-neutral way to specify 16-byte vector of ints */
+typedef unsigned vec __attribute__((vector_size(16)));
+
+/* This implementation is designed for Neon, SSE and AltiVec machines. The
+ * following specify how to do certain vector operations efficiently on
+ * each architecture, using intrinsics.
+ * This implementation supports parallel processing of multiple blocks,
+ * including potentially using general-purpose registers. */
+#if __ARM_NEON__
+#include <arm_neon.h>
+#define GPR_TOO 1
+#define VBPI 2
+#define ONE (vec) vsetq_lane_u32(1, vdupq_n_u32(0), 0)
+#define LOAD_ALIGNED(m) (vec)(*((vec *)(m)))
+#define LOAD(m) ({ \
+ memcpy(alignment_buffer, m, 16); \
+ LOAD_ALIGNED(alignment_buffer); \
+ })
+#define STORE(m, r) ({ \
+ (*((vec *)(alignment_buffer))) = (r); \
+ memcpy(m, alignment_buffer, 16); \
+ })
+#define ROTV1(x) (vec) vextq_u32((uint32x4_t)x, (uint32x4_t)x, 1)
+#define ROTV2(x) (vec) vextq_u32((uint32x4_t)x, (uint32x4_t)x, 2)
+#define ROTV3(x) (vec) vextq_u32((uint32x4_t)x, (uint32x4_t)x, 3)
+#define ROTW16(x) (vec) vrev32q_u16((uint16x8_t)x)
+#if __clang__
+#define ROTW7(x) (x << ((vec) {7, 7, 7, 7})) ^ (x >> ((vec) {25, 25, 25, 25}))
+#define ROTW8(x) (x << ((vec) {8, 8, 8, 8})) ^ (x >> ((vec) {24, 24, 24, 24}))
+#define ROTW12(x) \
+ (x << ((vec) {12, 12, 12, 12})) ^ (x >> ((vec) {20, 20, 20, 20}))
+#else
+#define ROTW7(x) \
+ (vec) vsriq_n_u32(vshlq_n_u32((uint32x4_t)x, 7), (uint32x4_t)x, 25)
+#define ROTW8(x) \
+ (vec) vsriq_n_u32(vshlq_n_u32((uint32x4_t)x, 8), (uint32x4_t)x, 24)
+#define ROTW12(x) \
+ (vec) vsriq_n_u32(vshlq_n_u32((uint32x4_t)x, 12), (uint32x4_t)x, 20)
+#endif
+#elif __SSE2__
+#include <emmintrin.h>
+#define GPR_TOO 0
+#if __clang__
+#define VBPI 4
+#else
+#define VBPI 3
+#endif
+#define ONE (vec) _mm_set_epi32(0, 0, 0, 1)
+#define LOAD(m) (vec) _mm_loadu_si128((__m128i *)(m))
+#define LOAD_ALIGNED(m) (vec) _mm_load_si128((__m128i *)(m))
+#define STORE(m, r) _mm_storeu_si128((__m128i *)(m), (__m128i)(r))
+#define ROTV1(x) (vec) _mm_shuffle_epi32((__m128i)x, _MM_SHUFFLE(0, 3, 2, 1))
+#define ROTV2(x) (vec) _mm_shuffle_epi32((__m128i)x, _MM_SHUFFLE(1, 0, 3, 2))
+#define ROTV3(x) (vec) _mm_shuffle_epi32((__m128i)x, _MM_SHUFFLE(2, 1, 0, 3))
+#define ROTW7(x) \
+ (vec)(_mm_slli_epi32((__m128i)x, 7) ^ _mm_srli_epi32((__m128i)x, 25))
+#define ROTW12(x) \
+ (vec)(_mm_slli_epi32((__m128i)x, 12) ^ _mm_srli_epi32((__m128i)x, 20))
+#if __SSSE3__
+#include <tmmintrin.h>
+#define ROTW8(x) \
+ (vec) _mm_shuffle_epi8((__m128i)x, _mm_set_epi8(14, 13, 12, 15, 10, 9, 8, \
+ 11, 6, 5, 4, 7, 2, 1, 0, 3))
+#define ROTW16(x) \
+ (vec) _mm_shuffle_epi8((__m128i)x, _mm_set_epi8(13, 12, 15, 14, 9, 8, 11, \
+ 10, 5, 4, 7, 6, 1, 0, 3, 2))
+#else
+#define ROTW8(x) \
+ (vec)(_mm_slli_epi32((__m128i)x, 8) ^ _mm_srli_epi32((__m128i)x, 24))
+#define ROTW16(x) \
+ (vec)(_mm_slli_epi32((__m128i)x, 16) ^ _mm_srli_epi32((__m128i)x, 16))
+#endif
+#else
+#error-- Implementation supports only machines with neon or SSE2
+#endif
+
+#ifndef REVV_BE
+#define REVV_BE(x) (x)
+#endif
+
+#ifndef REVW_BE
+#define REVW_BE(x) (x)
+#endif
+
+#define BPI (VBPI + GPR_TOO) /* Blocks computed per loop iteration */
+
+#define DQROUND_VECTORS(a,b,c,d) \
+ a += b; d ^= a; d = ROTW16(d); \
+ c += d; b ^= c; b = ROTW12(b); \
+ a += b; d ^= a; d = ROTW8(d); \
+ c += d; b ^= c; b = ROTW7(b); \
+ b = ROTV1(b); c = ROTV2(c); d = ROTV3(d); \
+ a += b; d ^= a; d = ROTW16(d); \
+ c += d; b ^= c; b = ROTW12(b); \
+ a += b; d ^= a; d = ROTW8(d); \
+ c += d; b ^= c; b = ROTW7(b); \
+ b = ROTV3(b); c = ROTV2(c); d = ROTV1(d);
+
+#define QROUND_WORDS(a,b,c,d) \
+ a = a+b; d ^= a; d = d<<16 | d>>16; \
+ c = c+d; b ^= c; b = b<<12 | b>>20; \
+ a = a+b; d ^= a; d = d<< 8 | d>>24; \
+ c = c+d; b ^= c; b = b<< 7 | b>>25;
+
+#define WRITE_XOR(in, op, d, v0, v1, v2, v3) \
+ STORE(op + d + 0, LOAD(in + d + 0) ^ REVV_BE(v0)); \
+ STORE(op + d + 4, LOAD(in + d + 4) ^ REVV_BE(v1)); \
+ STORE(op + d + 8, LOAD(in + d + 8) ^ REVV_BE(v2)); \
+ STORE(op + d +12, LOAD(in + d +12) ^ REVV_BE(v3));
+
+#if __ARM_NEON__
+/* For ARM, we can't depend on NEON support, so this function is compiled with
+ * a different name, along with the generic code, and can be enabled at
+ * run-time. */
+void CRYPTO_chacha_20_neon(
+#else
+void CRYPTO_chacha_20(
+#endif
+ uint8_t *out,
+ const uint8_t *in,
+ size_t inlen,
+ const uint8_t key[32],
+ const uint8_t nonce[8],
+ size_t counter)
+ {
+ unsigned iters, i, *op=(unsigned *)out, *ip=(unsigned *)in, *kp;
+#if defined(__ARM_NEON__)
+ unsigned *np;
+ uint8_t alignment_buffer[16] __attribute__((aligned(16)));
+#endif
+ vec s0, s1, s2, s3;
+#if !defined(__ARM_NEON__) && !defined(__SSE2__)
+ __attribute__ ((aligned (16))) unsigned key[8], nonce[4];
+#endif
+ __attribute__ ((aligned (16))) unsigned chacha_const[] =
+ {0x61707865,0x3320646E,0x79622D32,0x6B206574};
+#if defined(__ARM_NEON__) || defined(__SSE2__)
+ kp = (unsigned *)key;
+#else
+ ((vec *)key)[0] = REVV_BE(((vec *)key)[0]);
+ ((vec *)key)[1] = REVV_BE(((vec *)key)[1]);
+ nonce[0] = REVW_BE(((unsigned *)nonce)[0]);
+ nonce[1] = REVW_BE(((unsigned *)nonce)[1]);
+ nonce[2] = REVW_BE(((unsigned *)nonce)[2]);
+ nonce[3] = REVW_BE(((unsigned *)nonce)[3]);
+ kp = (unsigned *)key;
+ np = (unsigned *)nonce;
+#endif
+#if defined(__ARM_NEON__)
+ np = (unsigned*) nonce;
+#endif
+ s0 = LOAD_ALIGNED(chacha_const);
+ s1 = LOAD_ALIGNED(&((vec*)kp)[0]);
+ s2 = LOAD_ALIGNED(&((vec*)kp)[1]);
+ s3 = (vec){
+ counter & 0xffffffff,
+#if __ARM_NEON__ || defined(OPENSSL_X86)
+ 0, /* can't right-shift 32 bits on a 32-bit system. */
+#else
+ counter >> 32,
+#endif
+ ((uint32_t*)nonce)[0],
+ ((uint32_t*)nonce)[1]
+ };
+
+ for (iters = 0; iters < inlen/(BPI*64); iters++)
+ {
+#if GPR_TOO
+ register unsigned x0, x1, x2, x3, x4, x5, x6, x7, x8,
+ x9, x10, x11, x12, x13, x14, x15;
+#endif
+#if VBPI > 2
+ vec v8,v9,v10,v11;
+#endif
+#if VBPI > 3
+ vec v12,v13,v14,v15;
+#endif
+
+ vec v0,v1,v2,v3,v4,v5,v6,v7;
+ v4 = v0 = s0; v5 = v1 = s1; v6 = v2 = s2; v3 = s3;
+ v7 = v3 + ONE;
+#if VBPI > 2
+ v8 = v4; v9 = v5; v10 = v6;
+ v11 = v7 + ONE;
+#endif
+#if VBPI > 3
+ v12 = v8; v13 = v9; v14 = v10;
+ v15 = v11 + ONE;
+#endif
+#if GPR_TOO
+ x0 = chacha_const[0]; x1 = chacha_const[1];
+ x2 = chacha_const[2]; x3 = chacha_const[3];
+ x4 = kp[0]; x5 = kp[1]; x6 = kp[2]; x7 = kp[3];
+ x8 = kp[4]; x9 = kp[5]; x10 = kp[6]; x11 = kp[7];
+ x12 = counter+BPI*iters+(BPI-1); x13 = 0;
+ x14 = np[0]; x15 = np[1];
+#endif
+ for (i = CHACHA_RNDS/2; i; i--)
+ {
+ DQROUND_VECTORS(v0,v1,v2,v3)
+ DQROUND_VECTORS(v4,v5,v6,v7)
+#if VBPI > 2
+ DQROUND_VECTORS(v8,v9,v10,v11)
+#endif
+#if VBPI > 3
+ DQROUND_VECTORS(v12,v13,v14,v15)
+#endif
+#if GPR_TOO
+ QROUND_WORDS( x0, x4, x8,x12)
+ QROUND_WORDS( x1, x5, x9,x13)
+ QROUND_WORDS( x2, x6,x10,x14)
+ QROUND_WORDS( x3, x7,x11,x15)
+ QROUND_WORDS( x0, x5,x10,x15)
+ QROUND_WORDS( x1, x6,x11,x12)
+ QROUND_WORDS( x2, x7, x8,x13)
+ QROUND_WORDS( x3, x4, x9,x14)
+#endif
+ }
+
+ WRITE_XOR(ip, op, 0, v0+s0, v1+s1, v2+s2, v3+s3)
+ s3 += ONE;
+ WRITE_XOR(ip, op, 16, v4+s0, v5+s1, v6+s2, v7+s3)
+ s3 += ONE;
+#if VBPI > 2
+ WRITE_XOR(ip, op, 32, v8+s0, v9+s1, v10+s2, v11+s3)
+ s3 += ONE;
+#endif
+#if VBPI > 3
+ WRITE_XOR(ip, op, 48, v12+s0, v13+s1, v14+s2, v15+s3)
+ s3 += ONE;
+#endif
+ ip += VBPI*16;
+ op += VBPI*16;
+#if GPR_TOO
+ op[0] = REVW_BE(REVW_BE(ip[0]) ^ (x0 + chacha_const[0]));
+ op[1] = REVW_BE(REVW_BE(ip[1]) ^ (x1 + chacha_const[1]));
+ op[2] = REVW_BE(REVW_BE(ip[2]) ^ (x2 + chacha_const[2]));
+ op[3] = REVW_BE(REVW_BE(ip[3]) ^ (x3 + chacha_const[3]));
+ op[4] = REVW_BE(REVW_BE(ip[4]) ^ (x4 + kp[0]));
+ op[5] = REVW_BE(REVW_BE(ip[5]) ^ (x5 + kp[1]));
+ op[6] = REVW_BE(REVW_BE(ip[6]) ^ (x6 + kp[2]));
+ op[7] = REVW_BE(REVW_BE(ip[7]) ^ (x7 + kp[3]));
+ op[8] = REVW_BE(REVW_BE(ip[8]) ^ (x8 + kp[4]));
+ op[9] = REVW_BE(REVW_BE(ip[9]) ^ (x9 + kp[5]));
+ op[10] = REVW_BE(REVW_BE(ip[10]) ^ (x10 + kp[6]));
+ op[11] = REVW_BE(REVW_BE(ip[11]) ^ (x11 + kp[7]));
+ op[12] = REVW_BE(REVW_BE(ip[12]) ^ (x12 + counter+BPI*iters+(BPI-1)));
+ op[13] = REVW_BE(REVW_BE(ip[13]) ^ (x13));
+ op[14] = REVW_BE(REVW_BE(ip[14]) ^ (x14 + np[0]));
+ op[15] = REVW_BE(REVW_BE(ip[15]) ^ (x15 + np[1]));
+ s3 += ONE;
+ ip += 16;
+ op += 16;
+#endif
+ }
+
+ for (iters = inlen%(BPI*64)/64; iters != 0; iters--)
+ {
+ vec v0 = s0, v1 = s1, v2 = s2, v3 = s3;
+ for (i = CHACHA_RNDS/2; i; i--)
+ {
+ DQROUND_VECTORS(v0,v1,v2,v3);
+ }
+ WRITE_XOR(ip, op, 0, v0+s0, v1+s1, v2+s2, v3+s3)
+ s3 += ONE;
+ ip += 16;
+ op += 16;
+ }
+
+ inlen = inlen % 64;
+ if (inlen)
+ {
+ __attribute__ ((aligned (16))) vec buf[4];
+ vec v0,v1,v2,v3;
+ v0 = s0; v1 = s1; v2 = s2; v3 = s3;
+ for (i = CHACHA_RNDS/2; i; i--)
+ {
+ DQROUND_VECTORS(v0,v1,v2,v3);
+ }
+
+ if (inlen >= 16)
+ {
+ STORE(op + 0, LOAD(ip + 0) ^ REVV_BE(v0 + s0));
+ if (inlen >= 32)
+ {
+ STORE(op + 4, LOAD(ip + 4) ^ REVV_BE(v1 + s1));
+ if (inlen >= 48)
+ {
+ STORE(op + 8, LOAD(ip + 8) ^
+ REVV_BE(v2 + s2));
+ buf[3] = REVV_BE(v3 + s3);
+ }
+ else
+ buf[2] = REVV_BE(v2 + s2);
+ }
+ else
+ buf[1] = REVV_BE(v1 + s1);
+ }
+ else
+ buf[0] = REVV_BE(v0 + s0);
+
+ for (i=inlen & ~15; i<inlen; i++)
+ ((char *)op)[i] = ((char *)ip)[i] ^ ((char *)buf)[i];
+ }
+ }
+
+#endif /* ASM_GEN || !OPENSSL_WINDOWS && (OPENSSL_X86_64 || OPENSSL_X86) && SSE2 */
diff --git a/src/crypto/chacha/chacha_vec_arm.S b/src/crypto/chacha/chacha_vec_arm.S
new file mode 100644
index 0000000..15d4556
--- /dev/null
+++ b/src/crypto/chacha/chacha_vec_arm.S
@@ -0,0 +1,1426 @@
+# 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.
+
+# This file contains a pre-compiled version of chacha_vec.c for ARM. This is
+# needed to support switching on NEON code at runtime. If the whole of OpenSSL
+# were to be compiled with the needed flags to build chacha_vec.c, then it
+# wouldn't be possible to run on non-NEON systems.
+#
+# This file was generated by chacha_vec_arm_generate.go using the following
+# compiler command:
+#
+# /opt/gcc-linaro-4.9-2014.11-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc -O3 -mcpu=cortex-a8 -mfpu=neon -fpic -DASM_GEN -I ../../include -S chacha_vec.c -o -
+
+#if !defined(OPENSSL_NO_ASM)
+
+ .syntax unified
+ .cpu cortex-a8
+ .eabi_attribute 27, 3
+
+# EABI attribute 28 sets whether VFP register arguments were used to build this
+# file. If object files are inconsistent on this point, the linker will refuse
+# to link them. Thus we report whatever the compiler expects since we don't use
+# VFP arguments.
+
+#if defined(__ARM_PCS_VFP)
+ .eabi_attribute 28, 1
+#else
+ .eabi_attribute 28, 0
+#endif
+
+ .fpu neon
+ .eabi_attribute 20, 1
+ .eabi_attribute 21, 1
+ .eabi_attribute 23, 3
+ .eabi_attribute 24, 1
+ .eabi_attribute 25, 1
+ .eabi_attribute 26, 2
+ .eabi_attribute 30, 2
+ .eabi_attribute 34, 1
+ .eabi_attribute 18, 4
+ .thumb
+ .file "chacha_vec.c"
+ .text
+ .align 2
+ .global CRYPTO_chacha_20_neon
+ .hidden CRYPTO_chacha_20_neon
+ .thumb
+ .thumb_func
+ .type CRYPTO_chacha_20_neon, %function
+CRYPTO_chacha_20_neon:
+ @ args = 8, pretend = 0, frame = 128
+ @ frame_needed = 1, uses_anonymous_args = 0
+ push {r4, r5, r6, r7, r8, r9, r10, fp, lr}
+ mov r4, r2
+ vpush.64 {d8, d9, d10, d11, d12, d13, d14, d15}
+ movw r8, #43691
+ movt r8, 43690
+ mov ip, r3
+ umull r8, r9, r4, r8
+ sub sp, sp, #132
+ add r7, sp, #0
+ sub sp, sp, #112
+ mov fp, r0
+ mov r10, r1
+ str r2, [r7, #8]
+ add r4, sp, #15
+ ldr r2, .L92+16
+ bic r4, r4, #15
+ ldr r5, [r7, #232]
+ add lr, r4, #64
+.LPIC16:
+ add r2, pc
+ str r0, [r7, #60]
+ str r1, [r7, #12]
+ str r3, [r7, #44]
+ ldmia r2, {r0, r1, r2, r3}
+ ldr r6, [r5]
+ str r4, [r7, #72]
+ ldr r5, [r5, #4]
+ ldr r4, [r7, #236]
+ str r6, [r7, #120]
+ str r5, [r7, #124]
+ str r4, [r7, #112]
+ stmia lr, {r0, r1, r2, r3}
+ movs r3, #0
+ ldr r0, [r7, #72]
+ str r3, [r7, #116]
+ lsrs r3, r9, #7
+ vldr d22, [r7, #112]
+ vldr d23, [r7, #120]
+ vldr d24, [r0, #64]
+ vldr d25, [r0, #72]
+ vld1.64 {d26-d27}, [ip:64]
+ vldr d28, [ip, #16]
+ vldr d29, [ip, #24]
+ beq .L26
+ ldr r1, [r0, #64]
+ lsls r2, r3, #8
+ sub r3, r2, r3, lsl #6
+ str r3, [r7, #4]
+ ldr r2, [r0, #72]
+ str r1, [r7, #40]
+ mov r1, r3
+ ldr r3, [r0, #68]
+ vldr d0, .L92
+ vldr d1, .L92+8
+ str r2, [r7, #32]
+ adds r2, r4, #2
+ str r3, [r7, #36]
+ ldr r3, [r0, #76]
+ str r2, [r7, #48]
+ mov r2, r0
+ mov r0, fp
+ str r10, [r7, #64]
+ str r3, [r7, #28]
+ adds r3, r0, r1
+ mov r1, r6
+ str r3, [r7, #16]
+ add r3, r2, #80
+ mov r2, r5
+ str r3, [r7, #68]
+.L4:
+ ldr r0, [r7, #44]
+ add r8, r7, #28
+ str r2, [r7, #108]
+ vadd.i32 q3, q11, q0
+ ldmia r8, {r8, r9, r10, fp}
+ vmov q8, q14 @ v4si
+ ldr r3, [r0]
+ vmov q1, q13 @ v4si
+ vmov q9, q12 @ v4si
+ vmov q2, q11 @ v4si
+ str r3, [r7, #52]
+ mov r3, r0
+ ldr r5, [r3, #8]
+ vmov q15, q14 @ v4si
+ ldr lr, [r3, #20]
+ vmov q5, q13 @ v4si
+ ldr r6, [r3, #12]
+ vmov q10, q12 @ v4si
+ str r5, [r7, #92]
+ mov r5, r3
+ ldr r4, [r5, #28]
+ movs r5, #10
+ ldr ip, [r3, #16]
+ ldr r3, [r3, #24]
+ str r4, [r7, #104]
+ ldr r4, [r7, #48]
+ str r3, [r7, #100]
+ mov r3, r1
+ str r6, [r7, #56]
+ str r4, [r7, #96]
+ str r8, [r7, #80]
+ mov r8, r10
+ ldr r0, [r0, #4]
+ mov r10, r9
+ ldr r1, [r7, #92]
+ ldr r2, [r7, #56]
+ ldr r9, [r7, #100]
+ ldr r4, [r7, #52]
+ str lr, [r7, #88]
+ mov lr, r3
+ str r5, [r7, #76]
+ movs r5, #0
+ str r5, [r7, #84]
+ b .L93
+.L94:
+ .align 3
+.L92:
+ .word 1
+ .word 0
+ .word 0
+ .word 0
+ .word .LANCHOR0-(.LPIC16+4)
+.L93:
+.L3:
+ vadd.i32 q9, q9, q1
+ add r3, r8, r0
+ vadd.i32 q10, q10, q5
+ add r5, fp, r4
+ veor q3, q3, q9
+ mov r6, r3
+ veor q2, q2, q10
+ ldr r3, [r7, #80]
+ str r5, [r7, #100]
+ add r10, r10, r1
+ vrev32.16 q3, q3
+ eor lr, lr, r10
+ vadd.i32 q8, q8, q3
+ vrev32.16 q2, q2
+ vadd.i32 q15, q15, q2
+ mov fp, r3
+ ldr r3, [r7, #96]
+ veor q4, q8, q1
+ str r6, [r7, #96]
+ veor q6, q15, q5
+ eors r3, r3, r5
+ mov r5, r6
+ ldr r6, [r7, #84]
+ vshl.i32 q1, q4, #12
+ vshl.i32 q5, q6, #12
+ add fp, fp, r2
+ eors r6, r6, r5
+ ror r3, r3, #16
+ vsri.32 q1, q4, #20
+ ror lr, lr, #16
+ mov r5, r6
+ ldr r6, [r7, #108]
+ vsri.32 q5, q6, #20
+ str r3, [r7, #108]
+ eor r6, r6, fp
+ ror r5, r5, #16
+ vadd.i32 q9, q9, q1
+ add r9, r9, lr
+ ror r3, r6, #16
+ ldr r6, [r7, #108]
+ vadd.i32 q10, q10, q5
+ str r3, [r7, #92]
+ veor q4, q9, q3
+ add ip, ip, r6
+ ldr r6, [r7, #88]
+ veor q6, q10, q2
+ eor r4, ip, r4
+ eor r1, r9, r1
+ vshl.i32 q3, q4, #8
+ mov r8, r6
+ ldr r6, [r7, #104]
+ vshl.i32 q2, q6, #8
+ ror r4, r4, #20
+ add r6, r6, r3
+ vsri.32 q3, q4, #24
+ str r6, [r7, #88]
+ eors r2, r2, r6
+ ldr r6, [r7, #100]
+ vsri.32 q2, q6, #24
+ add r8, r8, r5
+ ror r2, r2, #20
+ adds r6, r4, r6
+ vadd.i32 q4, q8, q3
+ eor r0, r8, r0
+ vadd.i32 q15, q15, q2
+ mov r3, r6
+ ldr r6, [r7, #96]
+ veor q6, q4, q1
+ ror r0, r0, #20
+ str r3, [r7, #96]
+ veor q5, q15, q5
+ adds r6, r0, r6
+ str r6, [r7, #104]
+ mov r6, r3
+ ldr r3, [r7, #108]
+ vshl.i32 q8, q6, #7
+ add fp, fp, r2
+ eors r3, r3, r6
+ ldr r6, [r7, #104]
+ vshl.i32 q1, q5, #7
+ ror r1, r1, #20
+ eors r5, r5, r6
+ vsri.32 q8, q6, #25
+ ldr r6, [r7, #92]
+ ror r3, r3, #24
+ ror r5, r5, #24
+ vsri.32 q1, q5, #25
+ str r5, [r7, #100]
+ eor r6, fp, r6
+ ldr r5, [r7, #100]
+ add r10, r10, r1
+ add ip, r3, ip
+ vext.32 q8, q8, q8, #1
+ str ip, [r7, #108]
+ add ip, r5, r8
+ ldr r5, [r7, #88]
+ eor lr, r10, lr
+ ror r6, r6, #24
+ vext.32 q1, q1, q1, #1
+ add r8, r6, r5
+ vadd.i32 q9, q9, q8
+ ldr r5, [r7, #108]
+ vext.32 q3, q3, q3, #3
+ vadd.i32 q10, q10, q1
+ ror lr, lr, #24
+ eor r0, ip, r0
+ vext.32 q2, q2, q2, #3
+ add r9, r9, lr
+ eors r4, r4, r5
+ veor q3, q9, q3
+ ldr r5, [r7, #96]
+ eor r1, r9, r1
+ ror r0, r0, #25
+ veor q2, q10, q2
+ adds r5, r0, r5
+ vext.32 q4, q4, q4, #2
+ str r5, [r7, #96]
+ ldr r5, [r7, #104]
+ ror r1, r1, #25
+ vrev32.16 q3, q3
+ eor r2, r8, r2
+ vext.32 q15, q15, q15, #2
+ adds r5, r1, r5
+ vadd.i32 q4, q4, q3
+ ror r4, r4, #25
+ vrev32.16 q2, q2
+ str r5, [r7, #84]
+ vadd.i32 q15, q15, q2
+ eors r3, r3, r5
+ ldr r5, [r7, #96]
+ add fp, fp, r4
+ veor q8, q4, q8
+ ror r2, r2, #25
+ veor q1, q15, q1
+ eor lr, fp, lr
+ eors r6, r6, r5
+ ror r3, r3, #16
+ ldr r5, [r7, #100]
+ add r10, r10, r2
+ str r3, [r7, #104]
+ ror lr, lr, #16
+ ldr r3, [r7, #104]
+ eor r5, r10, r5
+ vshl.i32 q5, q8, #12
+ add ip, lr, ip
+ vshl.i32 q6, q1, #12
+ str ip, [r7, #88]
+ add ip, r3, r8
+ str ip, [r7, #100]
+ ldr r3, [r7, #108]
+ ror r5, r5, #16
+ vsri.32 q5, q8, #20
+ ror r6, r6, #16
+ add ip, r5, r3
+ ldr r3, [r7, #88]
+ vsri.32 q6, q1, #20
+ add r9, r9, r6
+ eor r2, ip, r2
+ eors r4, r4, r3
+ ldr r3, [r7, #100]
+ eor r0, r9, r0
+ vadd.i32 q9, q9, q5
+ ror r4, r4, #20
+ eors r1, r1, r3
+ vadd.i32 q10, q10, q6
+ ror r3, r2, #20
+ str r3, [r7, #92]
+ ldr r3, [r7, #96]
+ veor q3, q9, q3
+ ror r0, r0, #20
+ add r8, r4, fp
+ veor q2, q10, q2
+ add fp, r0, r3
+ ldr r3, [r7, #84]
+ ror r1, r1, #20
+ mov r2, r8
+ vshl.i32 q8, q3, #8
+ str r8, [r7, #80]
+ add r8, r1, r3
+ ldr r3, [r7, #92]
+ vmov q1, q6 @ v4si
+ vshl.i32 q6, q2, #8
+ eor r6, fp, r6
+ add r10, r10, r3
+ ldr r3, [r7, #104]
+ vsri.32 q8, q3, #24
+ eor lr, r2, lr
+ eor r3, r8, r3
+ ror r2, r6, #24
+ vsri.32 q6, q2, #24
+ eor r5, r10, r5
+ str r2, [r7, #108]
+ ror r2, r3, #24
+ ldr r3, [r7, #88]
+ vmov q3, q8 @ v4si
+ vadd.i32 q15, q15, q6
+ ror lr, lr, #24
+ vadd.i32 q8, q4, q8
+ ror r6, r5, #24
+ add r5, lr, r3
+ ldr r3, [r7, #108]
+ veor q4, q8, q5
+ add ip, ip, r6
+ vmov q2, q6 @ v4si
+ add r9, r9, r3
+ veor q6, q15, q1
+ ldr r3, [r7, #100]
+ vshl.i32 q1, q4, #7
+ str r2, [r7, #96]
+ add r3, r3, r2
+ str r3, [r7, #104]
+ vshl.i32 q5, q6, #7
+ eors r1, r1, r3
+ ldr r3, [r7, #92]
+ vsri.32 q1, q4, #25
+ eors r4, r4, r5
+ eor r0, r9, r0
+ eor r2, ip, r3
+ vsri.32 q5, q6, #25
+ ldr r3, [r7, #76]
+ ror r4, r4, #25
+ str r6, [r7, #84]
+ ror r0, r0, #25
+ subs r3, r3, #1
+ str r5, [r7, #88]
+ ror r1, r1, #25
+ ror r2, r2, #25
+ vext.32 q15, q15, q15, #2
+ str r3, [r7, #76]
+ vext.32 q2, q2, q2, #1
+ vext.32 q8, q8, q8, #2
+ vext.32 q3, q3, q3, #1
+ vext.32 q5, q5, q5, #3
+ vext.32 q1, q1, q1, #3
+ bne .L3
+ ldr r3, [r7, #68]
+ vadd.i32 q4, q12, q10
+ str r9, [r7, #100]
+ mov r9, r10
+ mov r10, r8
+ ldr r8, [r7, #80]
+ str lr, [r7, #80]
+ mov lr, r5
+ ldr r5, [r7, #40]
+ vadd.i32 q5, q13, q5
+ ldr r6, [r7, #64]
+ vadd.i32 q15, q14, q15
+ add fp, fp, r5
+ ldr r5, [r7, #36]
+ str r4, [r7, #52]
+ vadd.i32 q7, q14, q8
+ ldr r4, [r7, #96]
+ add r5, r10, r5
+ str r3, [r7, #96]
+ vadd.i32 q2, q11, q2
+ ldr r3, [r6, #12] @ unaligned
+ vadd.i32 q6, q12, q9
+ str r0, [r7, #76]
+ vadd.i32 q1, q13, q1
+ ldr r0, [r6] @ unaligned
+ vadd.i32 q11, q11, q0
+ str r1, [r7, #92]
+ str r2, [r7, #56]
+ vadd.i32 q3, q11, q3
+ ldr r1, [r6, #4] @ unaligned
+ vadd.i32 q11, q11, q0
+ ldr r2, [r6, #8] @ unaligned
+ str r5, [r7, #88]
+ vadd.i32 q11, q11, q0
+ ldr r5, [r7, #96]
+ ldr r10, [r7, #68]
+ stmia r5!, {r0, r1, r2, r3}
+ mov r5, r10
+ ldr r2, [r7, #72]
+ ldr r1, [r7, #32]
+ ldr r3, [r7, #48]
+ vldr d20, [r2, #80]
+ vldr d21, [r2, #88]
+ add r9, r9, r1
+ veor q10, q10, q4
+ ldr r1, [r7, #28]
+ add r0, r8, r1
+ str r0, [r7, #24]
+ vstr d20, [r2, #80]
+ vstr d21, [r2, #88]
+ adds r0, r4, r3
+ str r0, [r7, #20]
+ ldmia r5!, {r0, r1, r2, r3}
+ mov r5, r10
+ ldr r4, [r7, #60]
+ str r0, [r4] @ unaligned
+ mov r4, r10
+ ldr r0, [r7, #60]
+ str r1, [r0, #4] @ unaligned
+ mov r8, r0
+ str r2, [r0, #8] @ unaligned
+ str r3, [r0, #12] @ unaligned
+ ldr r0, [r6, #16]! @ unaligned
+ ldr r1, [r6, #4] @ unaligned
+ ldr r2, [r6, #8] @ unaligned
+ ldr r3, [r6, #12] @ unaligned
+ ldr r6, [r7, #64]
+ stmia r5!, {r0, r1, r2, r3}
+ mov r5, r10
+ ldr r3, [r7, #72]
+ vldr d20, [r3, #80]
+ vldr d21, [r3, #88]
+ veor q10, q10, q5
+ vstr d20, [r3, #80]
+ vstr d21, [r3, #88]
+ ldmia r4!, {r0, r1, r2, r3}
+ mov r4, r8
+ str r0, [r8, #16] @ unaligned
+ str r1, [r8, #20] @ unaligned
+ str r2, [r8, #24] @ unaligned
+ str r3, [r8, #28] @ unaligned
+ ldr r0, [r6, #32]! @ unaligned
+ ldr r1, [r6, #4] @ unaligned
+ ldr r2, [r6, #8] @ unaligned
+ ldr r3, [r6, #12] @ unaligned
+ ldr r6, [r7, #64]
+ stmia r5!, {r0, r1, r2, r3}
+ mov r5, r10
+ ldr r0, [r7, #72]
+ vldr d16, [r0, #80]
+ vldr d17, [r0, #88]
+ veor q15, q8, q15
+ vstr d30, [r0, #80]
+ vstr d31, [r0, #88]
+ ldmia r10!, {r0, r1, r2, r3}
+ mov r10, r5
+ str r0, [r4, #32] @ unaligned
+ str r1, [r4, #36] @ unaligned
+ str r2, [r4, #40] @ unaligned
+ str r3, [r4, #44] @ unaligned
+ ldr r0, [r6, #48]! @ unaligned
+ ldr r1, [r6, #4] @ unaligned
+ ldr r2, [r6, #8] @ unaligned
+ ldr r3, [r6, #12] @ unaligned
+ ldr r6, [r7, #64]
+ stmia r5!, {r0, r1, r2, r3}
+ mov r5, r10
+ ldr r2, [r7, #72]
+ vldr d18, [r2, #80]
+ vldr d19, [r2, #88]
+ veor q9, q9, q2
+ vstr d18, [r2, #80]
+ vstr d19, [r2, #88]
+ ldmia r10!, {r0, r1, r2, r3}
+ mov r10, r5
+ str r0, [r4, #48] @ unaligned
+ str r1, [r4, #52] @ unaligned
+ str r2, [r4, #56] @ unaligned
+ str r3, [r4, #60] @ unaligned
+ ldr r0, [r6, #64]! @ unaligned
+ ldr r1, [r6, #4] @ unaligned
+ ldr r2, [r6, #8] @ unaligned
+ ldr r3, [r6, #12] @ unaligned
+ ldr r6, [r7, #64]
+ stmia r5!, {r0, r1, r2, r3}
+ mov r5, r10
+ ldr r2, [r7, #72]
+ vldr d18, [r2, #80]
+ vldr d19, [r2, #88]
+ veor q9, q9, q6
+ vstr d18, [r2, #80]
+ vstr d19, [r2, #88]
+ ldmia r10!, {r0, r1, r2, r3}
+ mov r10, r5
+ str r0, [r4, #64] @ unaligned
+ str r1, [r4, #68] @ unaligned
+ str r2, [r4, #72] @ unaligned
+ str r3, [r4, #76] @ unaligned
+ ldr r0, [r6, #80]! @ unaligned
+ ldr r1, [r6, #4] @ unaligned
+ ldr r2, [r6, #8] @ unaligned
+ ldr r3, [r6, #12] @ unaligned
+ ldr r6, [r7, #64]
+ stmia r5!, {r0, r1, r2, r3}
+ mov r5, r10
+ ldr r2, [r7, #72]
+ vldr d18, [r2, #80]
+ vldr d19, [r2, #88]
+ veor q1, q9, q1
+ vstr d2, [r2, #80]
+ vstr d3, [r2, #88]
+ ldmia r10!, {r0, r1, r2, r3}
+ mov r10, r5
+ str r0, [r4, #80] @ unaligned
+ str r1, [r4, #84] @ unaligned
+ str r2, [r4, #88] @ unaligned
+ str r3, [r4, #92] @ unaligned
+ ldr r0, [r6, #96]! @ unaligned
+ ldr r1, [r6, #4] @ unaligned
+ ldr r2, [r6, #8] @ unaligned
+ ldr r3, [r6, #12] @ unaligned
+ ldr r6, [r7, #64]
+ stmia r5!, {r0, r1, r2, r3}
+ mov r5, r10
+ ldr r3, [r7, #72]
+ vldr d16, [r3, #80]
+ vldr d17, [r3, #88]
+ veor q8, q8, q7
+ vstr d16, [r3, #80]
+ vstr d17, [r3, #88]
+ ldmia r10!, {r0, r1, r2, r3}
+ mov r10, r5
+ str r0, [r4, #96] @ unaligned
+ str r1, [r4, #100] @ unaligned
+ str r2, [r4, #104] @ unaligned
+ str r3, [r4, #108] @ unaligned
+ ldr r0, [r6, #112]! @ unaligned
+ ldr r1, [r6, #4] @ unaligned
+ ldr r2, [r6, #8] @ unaligned
+ ldr r3, [r6, #12] @ unaligned
+ stmia r5!, {r0, r1, r2, r3}
+ mov r5, r10
+ ldr r0, [r7, #72]
+ ldr r6, [r7, #44]
+ vldr d16, [r0, #80]
+ vldr d17, [r0, #88]
+ veor q8, q8, q3
+ vstr d16, [r0, #80]
+ vstr d17, [r0, #88]
+ ldmia r5!, {r0, r1, r2, r3}
+ mov r5, r4
+ mov r8, r5
+ str r1, [r4, #116] @ unaligned
+ ldr r1, [r7, #64]
+ str r0, [r4, #112] @ unaligned
+ mov r0, r5
+ str r2, [r4, #120] @ unaligned
+ str r3, [r4, #124] @ unaligned
+ ldr r3, [r1, #128]
+ ldr r2, [r7, #88]
+ eor r3, fp, r3
+ str r3, [r4, #128]
+ ldr r3, [r1, #132]
+ mov r4, r1
+ mov r1, r5
+ eors r2, r2, r3
+ str r2, [r8, #132]
+ ldr r3, [r4, #136]
+ ldr r2, [r7, #24]
+ eor r3, r9, r3
+ str r3, [r5, #136]
+ ldr r3, [r4, #140]
+ eors r3, r3, r2
+ str r3, [r5, #140]
+ mov r5, r4
+ ldr r3, [r6]
+ ldr r2, [r4, #144]
+ ldr r4, [r7, #52]
+ add r4, r4, r3
+ eors r2, r2, r4
+ mov r4, r1
+ str r2, [r1, #144]
+ ldr r1, [r7, #76]
+ ldr r2, [r6, #4]
+ ldr r3, [r5, #148]
+ mov r8, r1
+ add r8, r8, r2
+ mov r2, r8
+ eors r3, r3, r2
+ str r3, [r0, #148]
+ mov r0, r4
+ ldr r2, [r6, #8]
+ ldr r1, [r7, #92]
+ ldr r3, [r5, #152]
+ mov r8, r1
+ add r8, r8, r2
+ ldr r1, [r7, #56]
+ mov r2, r8
+ eors r3, r3, r2
+ str r3, [r4, #152]
+ mov r8, r6
+ ldr r2, [r6, #12]
+ mov r4, r5
+ ldr r3, [r5, #156]
+ add r1, r1, r2
+ eors r3, r3, r1
+ str r3, [r0, #156]
+ ldr r2, [r6, #16]
+ mov r1, r0
+ ldr r3, [r5, #160]
+ add ip, ip, r2
+ eor r3, ip, r3
+ str r3, [r0, #160]
+ ldr r2, [r6, #20]
+ mov ip, r0
+ ldr r3, [r5, #164]
+ add lr, lr, r2
+ ldr r2, [r7, #100]
+ eor r3, lr, r3
+ str r3, [r1, #164]
+ ldr r6, [r6, #24]
+ ldr r3, [r4, #168]
+ add r2, r2, r6
+ eors r3, r3, r2
+ ldr r2, [r7, #104]
+ str r3, [r0, #168]
+ ldr r5, [r8, #28]
+ ldr r3, [r4, #172]
+ add r2, r2, r5
+ mov r5, r4
+ eors r3, r3, r2
+ mov r2, r0
+ str r3, [r0, #172]
+ ldr r3, [r7, #48]
+ ldr r4, [r4, #176]
+ ldr r0, [r7, #20]
+ adds r1, r3, #3
+ ldr r3, [r7, #84]
+ eors r4, r4, r0
+ str r4, [r2, #176]
+ ldr r0, [r5, #180]
+ mov r4, r2
+ str r1, [r7, #48]
+ eors r3, r3, r0
+ mov r0, r3
+ ldr r3, [r7, #232]
+ str r0, [r2, #180]
+ ldr r1, [r3]
+ ldr r3, [r5, #184]
+ ldr r2, [r7, #80]
+ add r2, r2, r1
+ mov r1, r5
+ eors r3, r3, r2
+ str r3, [ip, #184]
+ ldr r3, [r7, #232]
+ adds r1, r1, #192
+ str r1, [r7, #64]
+ ldr r1, [r7, #108]
+ ldr r2, [r3, #4]
+ ldr r3, [r5, #188]
+ add r1, r1, r2
+ mov r2, r1
+ eors r2, r2, r3
+ str r2, [ip, #188]
+ mov r3, r4
+ ldr r2, [r7, #16]
+ adds r3, r3, #192
+ str r3, [r7, #60]
+ cmp r2, r3
+ beq .L85
+ ldr r3, [r7, #232]
+ ldmia r3, {r1, r2}
+ b .L4
+.L85:
+ ldr r3, [r7, #12]
+ ldr r2, [r7, #4]
+ add r3, r3, r2
+ str r3, [r7, #12]
+.L2:
+ ldr r1, [r7, #8]
+ movw r2, #43691
+ movt r2, 43690
+ umull r2, r3, r1, r2
+ lsr fp, r3, #7
+ lsl r3, fp, #8
+ sub fp, r3, fp, lsl #6
+ rsb fp, fp, r1
+ lsrs fp, fp, #6
+ beq .L6
+ ldr r6, [r7, #72]
+ ldr r5, [r7, #12]
+ ldr r4, [r7, #16]
+ mov r3, r6
+ adds r3, r3, #80
+ vldr d30, .L95
+ vldr d31, .L95+8
+ mov lr, r3
+ str fp, [r7, #104]
+ str fp, [r7, #108]
+.L8:
+ vmov q2, q11 @ v4si
+ movs r3, #10
+ vmov q8, q14 @ v4si
+ vmov q9, q13 @ v4si
+ vmov q10, q12 @ v4si
+.L7:
+ vadd.i32 q10, q10, q9
+ subs r3, r3, #1
+ veor q3, q2, q10
+ vrev32.16 q3, q3
+ vadd.i32 q8, q8, q3
+ veor q9, q8, q9
+ vshl.i32 q2, q9, #12
+ vsri.32 q2, q9, #20
+ vadd.i32 q10, q10, q2
+ veor q3, q10, q3
+ vshl.i32 q9, q3, #8
+ vsri.32 q9, q3, #24
+ vadd.i32 q8, q8, q9
+ vext.32 q9, q9, q9, #3
+ veor q2, q8, q2
+ vext.32 q8, q8, q8, #2
+ vshl.i32 q3, q2, #7
+ vsri.32 q3, q2, #25
+ vext.32 q3, q3, q3, #1
+ vadd.i32 q10, q10, q3
+ veor q9, q10, q9
+ vrev32.16 q9, q9
+ vadd.i32 q8, q8, q9
+ veor q3, q8, q3
+ vshl.i32 q2, q3, #12
+ vsri.32 q2, q3, #20
+ vadd.i32 q10, q10, q2
+ vmov q3, q2 @ v4si
+ veor q9, q10, q9
+ vshl.i32 q2, q9, #8
+ vsri.32 q2, q9, #24
+ vadd.i32 q8, q8, q2
+ vext.32 q2, q2, q2, #1
+ veor q3, q8, q3
+ vext.32 q8, q8, q8, #2
+ vshl.i32 q9, q3, #7
+ vsri.32 q9, q3, #25
+ vext.32 q9, q9, q9, #3
+ bne .L7
+ ldr r0, [r5] @ unaligned
+ vadd.i32 q1, q12, q10
+ ldr r1, [r5, #4] @ unaligned
+ mov ip, lr
+ ldr r2, [r5, #8] @ unaligned
+ mov r9, lr
+ ldr r3, [r5, #12] @ unaligned
+ mov r10, r5
+ vadd.i32 q9, q13, q9
+ mov r8, lr
+ vadd.i32 q8, q14, q8
+ stmia ip!, {r0, r1, r2, r3}
+ mov ip, lr
+ vldr d20, [r6, #80]
+ vldr d21, [r6, #88]
+ vadd.i32 q3, q11, q2
+ veor q10, q10, q1
+ vadd.i32 q11, q11, q15
+ vstr d20, [r6, #80]
+ vstr d21, [r6, #88]
+ ldmia r9!, {r0, r1, r2, r3}
+ mov r9, r5
+ str r0, [r4] @ unaligned
+ str r1, [r4, #4] @ unaligned
+ str r2, [r4, #8] @ unaligned
+ str r3, [r4, #12] @ unaligned
+ ldr r0, [r10, #16]! @ unaligned
+ ldr r1, [r10, #4] @ unaligned
+ ldr r2, [r10, #8] @ unaligned
+ ldr r3, [r10, #12] @ unaligned
+ add r10, r4, #48
+ adds r4, r4, #64
+ stmia r8!, {r0, r1, r2, r3}
+ mov r8, lr
+ vldr d20, [r6, #80]
+ vldr d21, [r6, #88]
+ veor q10, q10, q9
+ vstr d20, [r6, #80]
+ vstr d21, [r6, #88]
+ ldmia ip!, {r0, r1, r2, r3}
+ mov ip, lr
+ str r0, [r4, #-48] @ unaligned
+ str r1, [r4, #-44] @ unaligned
+ str r2, [r4, #-40] @ unaligned
+ str r3, [r4, #-36] @ unaligned
+ ldr r0, [r9, #32]! @ unaligned
+ ldr r1, [r9, #4] @ unaligned
+ ldr r2, [r9, #8] @ unaligned
+ ldr r3, [r9, #12] @ unaligned
+ mov r9, r5
+ adds r5, r5, #64
+ stmia r8!, {r0, r1, r2, r3}
+ mov r8, lr
+ vldr d18, [r6, #80]
+ vldr d19, [r6, #88]
+ veor q9, q9, q8
+ vstr d18, [r6, #80]
+ vstr d19, [r6, #88]
+ ldmia ip!, {r0, r1, r2, r3}
+ mov ip, lr
+ str r0, [r4, #-32] @ unaligned
+ str r1, [r4, #-28] @ unaligned
+ str r2, [r4, #-24] @ unaligned
+ str r3, [r4, #-20] @ unaligned
+ ldr r0, [r9, #48]! @ unaligned
+ ldr r1, [r9, #4] @ unaligned
+ ldr r2, [r9, #8] @ unaligned
+ ldr r3, [r9, #12] @ unaligned
+ stmia r8!, {r0, r1, r2, r3}
+ vldr d16, [r6, #80]
+ vldr d17, [r6, #88]
+ veor q8, q8, q3
+ vstr d16, [r6, #80]
+ vstr d17, [r6, #88]
+ ldmia ip!, {r0, r1, r2, r3}
+ str r0, [r4, #-16] @ unaligned
+ str r1, [r4, #-12] @ unaligned
+ str r3, [r10, #12] @ unaligned
+ ldr r3, [r7, #108]
+ str r2, [r10, #8] @ unaligned
+ cmp r3, #1
+ beq .L88
+ movs r3, #1
+ str r3, [r7, #108]
+ b .L8
+.L96:
+ .align 3
+.L95:
+ .word 1
+ .word 0
+ .word 0
+ .word 0
+.L88:
+ ldr fp, [r7, #104]
+ ldr r3, [r7, #12]
+ lsl fp, fp, #6
+ add r3, r3, fp
+ str r3, [r7, #12]
+ ldr r3, [r7, #16]
+ add r3, r3, fp
+ str r3, [r7, #16]
+.L6:
+ ldr r3, [r7, #8]
+ ands r9, r3, #63
+ beq .L1
+ vmov q3, q11 @ v4si
+ movs r3, #10
+ vmov q8, q14 @ v4si
+ mov r5, r9
+ vmov q15, q13 @ v4si
+ vmov q10, q12 @ v4si
+.L10:
+ vadd.i32 q10, q10, q15
+ subs r3, r3, #1
+ veor q9, q3, q10
+ vrev32.16 q9, q9
+ vadd.i32 q8, q8, q9
+ veor q15, q8, q15
+ vshl.i32 q3, q15, #12
+ vsri.32 q3, q15, #20
+ vadd.i32 q10, q10, q3
+ veor q15, q10, q9
+ vshl.i32 q9, q15, #8
+ vsri.32 q9, q15, #24
+ vadd.i32 q8, q8, q9
+ vext.32 q9, q9, q9, #3
+ veor q3, q8, q3
+ vext.32 q8, q8, q8, #2
+ vshl.i32 q15, q3, #7
+ vsri.32 q15, q3, #25
+ vext.32 q15, q15, q15, #1
+ vadd.i32 q10, q10, q15
+ veor q9, q10, q9
+ vrev32.16 q9, q9
+ vadd.i32 q8, q8, q9
+ veor q15, q8, q15
+ vshl.i32 q3, q15, #12
+ vsri.32 q3, q15, #20
+ vadd.i32 q10, q10, q3
+ vmov q15, q3 @ v4si
+ veor q9, q10, q9
+ vshl.i32 q3, q9, #8
+ vsri.32 q3, q9, #24
+ vadd.i32 q8, q8, q3
+ vext.32 q3, q3, q3, #1
+ veor q9, q8, q15
+ vext.32 q8, q8, q8, #2
+ vshl.i32 q15, q9, #7
+ vsri.32 q15, q9, #25
+ vext.32 q15, q15, q15, #3
+ bne .L10
+ cmp r5, #15
+ mov r9, r5
+ bhi .L89
+ vadd.i32 q12, q12, q10
+ ldr r3, [r7, #72]
+ vst1.64 {d24-d25}, [r3:128]
+.L14:
+ ldr r3, [r7, #8]
+ and r2, r3, #48
+ cmp r9, r2
+ bls .L1
+ ldr r6, [r7, #16]
+ add r3, r2, #16
+ ldr r1, [r7, #12]
+ rsb ip, r2, r9
+ adds r0, r1, r2
+ mov r4, r6
+ add r1, r1, r3
+ add r4, r4, r2
+ add r3, r3, r6
+ cmp r0, r3
+ it cc
+ cmpcc r4, r1
+ ite cs
+ movcs r3, #1
+ movcc r3, #0
+ cmp ip, #18
+ ite ls
+ movls r3, #0
+ andhi r3, r3, #1
+ cmp r3, #0
+ beq .L16
+ and r1, r0, #7
+ mov r3, r2
+ negs r1, r1
+ and r1, r1, #15
+ cmp r1, ip
+ it cs
+ movcs r1, ip
+ cmp r1, #0
+ beq .L17
+ ldr r5, [r7, #72]
+ cmp r1, #1
+ ldrb r0, [r0] @ zero_extendqisi2
+ add r3, r2, #1
+ ldrb lr, [r5, r2] @ zero_extendqisi2
+ mov r6, r5
+ eor r0, lr, r0
+ strb r0, [r4]
+ beq .L17
+ ldr r0, [r7, #12]
+ cmp r1, #2
+ ldrb r4, [r5, r3] @ zero_extendqisi2
+ ldr r5, [r7, #16]
+ ldrb r0, [r0, r3] @ zero_extendqisi2
+ eor r0, r0, r4
+ strb r0, [r5, r3]
+ add r3, r2, #2
+ beq .L17
+ ldr r0, [r7, #12]
+ cmp r1, #3
+ ldrb r4, [r6, r3] @ zero_extendqisi2
+ ldrb r0, [r0, r3] @ zero_extendqisi2
+ eor r0, r0, r4
+ strb r0, [r5, r3]
+ add r3, r2, #3
+ beq .L17
+ ldr r0, [r7, #12]
+ cmp r1, #4
+ ldrb r4, [r6, r3] @ zero_extendqisi2
+ ldrb r0, [r0, r3] @ zero_extendqisi2
+ eor r0, r0, r4
+ strb r0, [r5, r3]
+ add r3, r2, #4
+ beq .L17
+ ldr r0, [r7, #12]
+ cmp r1, #5
+ ldrb r4, [r6, r3] @ zero_extendqisi2
+ ldrb r0, [r0, r3] @ zero_extendqisi2
+ eor r0, r0, r4
+ strb r0, [r5, r3]
+ add r3, r2, #5
+ beq .L17
+ ldr r0, [r7, #12]
+ cmp r1, #6
+ ldrb r4, [r6, r3] @ zero_extendqisi2
+ ldrb r0, [r0, r3] @ zero_extendqisi2
+ eor r0, r0, r4
+ strb r0, [r5, r3]
+ add r3, r2, #6
+ beq .L17
+ ldr r0, [r7, #12]
+ cmp r1, #7
+ ldrb r4, [r6, r3] @ zero_extendqisi2
+ ldrb r0, [r0, r3] @ zero_extendqisi2
+ eor r0, r0, r4
+ strb r0, [r5, r3]
+ add r3, r2, #7
+ beq .L17
+ ldr r0, [r7, #12]
+ cmp r1, #8
+ ldrb r4, [r6, r3] @ zero_extendqisi2
+ ldrb r0, [r0, r3] @ zero_extendqisi2
+ eor r0, r0, r4
+ strb r0, [r5, r3]
+ add r3, r2, #8
+ beq .L17
+ ldr r0, [r7, #12]
+ cmp r1, #9
+ ldrb r4, [r6, r3] @ zero_extendqisi2
+ ldrb r0, [r0, r3] @ zero_extendqisi2
+ eor r0, r0, r4
+ strb r0, [r5, r3]
+ add r3, r2, #9
+ beq .L17
+ ldr r0, [r7, #12]
+ cmp r1, #10
+ ldrb r4, [r6, r3] @ zero_extendqisi2
+ ldrb r0, [r0, r3] @ zero_extendqisi2
+ eor r0, r0, r4
+ strb r0, [r5, r3]
+ add r3, r2, #10
+ beq .L17
+ ldr r0, [r7, #12]
+ cmp r1, #11
+ ldrb r4, [r6, r3] @ zero_extendqisi2
+ ldrb r0, [r0, r3] @ zero_extendqisi2
+ eor r0, r0, r4
+ strb r0, [r5, r3]
+ add r3, r2, #11
+ beq .L17
+ ldr r0, [r7, #12]
+ cmp r1, #12
+ ldrb r4, [r6, r3] @ zero_extendqisi2
+ ldrb r0, [r0, r3] @ zero_extendqisi2
+ eor r0, r0, r4
+ strb r0, [r5, r3]
+ add r3, r2, #12
+ beq .L17
+ ldr r0, [r7, #12]
+ cmp r1, #13
+ ldrb r4, [r6, r3] @ zero_extendqisi2
+ ldrb r0, [r0, r3] @ zero_extendqisi2
+ eor r0, r0, r4
+ strb r0, [r5, r3]
+ add r3, r2, #13
+ beq .L17
+ ldr r0, [r7, #12]
+ cmp r1, #15
+ ldrb r4, [r6, r3] @ zero_extendqisi2
+ ldrb r0, [r0, r3] @ zero_extendqisi2
+ eor r0, r0, r4
+ strb r0, [r5, r3]
+ add r3, r2, #14
+ bne .L17
+ ldr r0, [r7, #12]
+ ldrb r4, [r6, r3] @ zero_extendqisi2
+ ldrb r0, [r0, r3] @ zero_extendqisi2
+ eors r0, r0, r4
+ strb r0, [r5, r3]
+ add r3, r2, #15
+.L17:
+ rsb r4, r1, ip
+ add r0, ip, #-1
+ sub r6, r4, #16
+ subs r0, r0, r1
+ cmp r0, #14
+ lsr r6, r6, #4
+ add r6, r6, #1
+ lsl lr, r6, #4
+ bls .L19
+ add r2, r2, r1
+ ldr r1, [r7, #12]
+ ldr r5, [r7, #16]
+ cmp r6, #1
+ add r0, r1, r2
+ ldr r1, [r7, #72]
+ add r1, r1, r2
+ vld1.64 {d18-d19}, [r0:64]
+ add r2, r2, r5
+ vld1.8 {q8}, [r1]
+ veor q8, q8, q9
+ vst1.8 {q8}, [r2]
+ beq .L20
+ add r8, r1, #16
+ add ip, r2, #16
+ vldr d18, [r0, #16]
+ vldr d19, [r0, #24]
+ cmp r6, #2
+ vld1.8 {q8}, [r8]
+ veor q8, q8, q9
+ vst1.8 {q8}, [ip]
+ beq .L20
+ add r8, r1, #32
+ add ip, r2, #32
+ vldr d18, [r0, #32]
+ vldr d19, [r0, #40]
+ cmp r6, #3
+ vld1.8 {q8}, [r8]
+ veor q8, q8, q9
+ vst1.8 {q8}, [ip]
+ beq .L20
+ adds r1, r1, #48
+ adds r2, r2, #48
+ vldr d18, [r0, #48]
+ vldr d19, [r0, #56]
+ vld1.8 {q8}, [r1]
+ veor q8, q8, q9
+ vst1.8 {q8}, [r2]
+.L20:
+ cmp lr, r4
+ add r3, r3, lr
+ beq .L1
+.L19:
+ ldr r4, [r7, #72]
+ adds r2, r3, #1
+ ldr r1, [r7, #12]
+ cmp r2, r9
+ ldr r5, [r7, #16]
+ ldrb r0, [r4, r3] @ zero_extendqisi2
+ ldrb r1, [r1, r3] @ zero_extendqisi2
+ eor r1, r1, r0
+ strb r1, [r5, r3]
+ bcs .L1
+ ldr r0, [r7, #12]
+ adds r1, r3, #2
+ mov r6, r4
+ cmp r9, r1
+ ldrb r4, [r4, r2] @ zero_extendqisi2
+ ldrb r0, [r0, r2] @ zero_extendqisi2
+ eor r0, r0, r4
+ strb r0, [r5, r2]
+ bls .L1
+ ldr r0, [r7, #12]
+ adds r2, r3, #3
+ ldrb r4, [r6, r1] @ zero_extendqisi2
+ cmp r9, r2
+ ldrb r0, [r0, r1] @ zero_extendqisi2
+ eor r0, r0, r4
+ strb r0, [r5, r1]
+ bls .L1
+ ldr r0, [r7, #12]
+ adds r1, r3, #4
+ ldrb r4, [r6, r2] @ zero_extendqisi2
+ cmp r9, r1
+ ldrb r0, [r0, r2] @ zero_extendqisi2
+ eor r0, r0, r4
+ strb r0, [r5, r2]
+ bls .L1
+ ldr r0, [r7, #12]
+ adds r2, r3, #5
+ ldrb r4, [r6, r1] @ zero_extendqisi2
+ cmp r9, r2
+ ldrb r0, [r0, r1] @ zero_extendqisi2
+ eor r0, r0, r4
+ strb r0, [r5, r1]
+ bls .L1
+ ldr r0, [r7, #12]
+ adds r1, r3, #6
+ ldrb r4, [r6, r2] @ zero_extendqisi2
+ cmp r9, r1
+ ldrb r0, [r0, r2] @ zero_extendqisi2
+ eor r0, r0, r4
+ strb r0, [r5, r2]
+ bls .L1
+ ldr r0, [r7, #12]
+ adds r2, r3, #7
+ ldrb r4, [r6, r1] @ zero_extendqisi2
+ cmp r9, r2
+ ldrb r0, [r0, r1] @ zero_extendqisi2
+ eor r0, r0, r4
+ strb r0, [r5, r1]
+ bls .L1
+ ldr r0, [r7, #12]
+ add r1, r3, #8
+ ldrb r4, [r6, r2] @ zero_extendqisi2
+ cmp r9, r1
+ ldrb r0, [r0, r2] @ zero_extendqisi2
+ eor r0, r0, r4
+ strb r0, [r5, r2]
+ bls .L1
+ ldr r0, [r7, #12]
+ add r2, r3, #9
+ ldrb r4, [r6, r1] @ zero_extendqisi2
+ cmp r9, r2
+ ldrb r0, [r0, r1] @ zero_extendqisi2
+ eor r0, r0, r4
+ strb r0, [r5, r1]
+ bls .L1
+ ldr r0, [r7, #12]
+ add r1, r3, #10
+ ldrb r4, [r6, r2] @ zero_extendqisi2
+ cmp r9, r1
+ ldrb r0, [r0, r2] @ zero_extendqisi2
+ eor r0, r0, r4
+ strb r0, [r5, r2]
+ bls .L1
+ ldr r0, [r7, #12]
+ add r2, r3, #11
+ ldrb r4, [r6, r1] @ zero_extendqisi2
+ cmp r9, r2
+ ldrb r0, [r0, r1] @ zero_extendqisi2
+ eor r0, r0, r4
+ strb r0, [r5, r1]
+ bls .L1
+ ldr r0, [r7, #12]
+ add r1, r3, #12
+ ldrb r4, [r6, r2] @ zero_extendqisi2
+ cmp r9, r1
+ ldrb r0, [r0, r2] @ zero_extendqisi2
+ eor r0, r0, r4
+ strb r0, [r5, r2]
+ bls .L1
+ ldr r0, [r7, #12]
+ add r2, r3, #13
+ ldrb r4, [r6, r1] @ zero_extendqisi2
+ cmp r9, r2
+ ldrb r0, [r0, r1] @ zero_extendqisi2
+ eor r0, r0, r4
+ strb r0, [r5, r1]
+ bls .L1
+ ldr r1, [r7, #12]
+ adds r3, r3, #14
+ ldrb r0, [r6, r2] @ zero_extendqisi2
+ cmp r9, r3
+ ldrb r1, [r1, r2] @ zero_extendqisi2
+ eor r1, r1, r0
+ strb r1, [r5, r2]
+ bls .L1
+ ldr r2, [r7, #72]
+ ldrb r1, [r2, r3] @ zero_extendqisi2
+ ldr r2, [r7, #12]
+ ldrb r2, [r2, r3] @ zero_extendqisi2
+ eors r2, r2, r1
+ ldr r1, [r7, #16]
+ strb r2, [r1, r3]
+.L1:
+ adds r7, r7, #132
+ mov sp, r7
+ @ sp needed
+ vldm sp!, {d8-d15}
+ pop {r4, r5, r6, r7, r8, r9, r10, fp, pc}
+.L89:
+ ldr r4, [r7, #12]
+ vadd.i32 q12, q12, q10
+ ldr r5, [r7, #72]
+ cmp r9, #31
+ ldr r0, [r4] @ unaligned
+ add r6, r5, #80
+ ldr r1, [r4, #4] @ unaligned
+ ldr r2, [r4, #8] @ unaligned
+ mov r5, r6
+ ldr r3, [r4, #12] @ unaligned
+ mov r4, r6
+ str r6, [r7, #68]
+ stmia r6!, {r0, r1, r2, r3}
+ ldr r2, [r7, #72]
+ ldr r6, [r7, #16]
+ vldr d18, [r2, #80]
+ vldr d19, [r2, #88]
+ veor q9, q9, q12
+ vstr d18, [r2, #80]
+ vstr d19, [r2, #88]
+ ldmia r4!, {r0, r1, r2, r3}
+ str r1, [r6, #4] @ unaligned
+ mov r1, r6
+ str r0, [r6] @ unaligned
+ str r2, [r6, #8] @ unaligned
+ str r3, [r6, #12] @ unaligned
+ bhi .L90
+ vadd.i32 q13, q13, q15
+ ldr r3, [r7, #72]
+ vstr d26, [r3, #16]
+ vstr d27, [r3, #24]
+ b .L14
+.L16:
+ subs r3, r2, #1
+ ldr r2, [r7, #12]
+ add r2, r2, r9
+ mov r5, r2
+ ldr r2, [r7, #72]
+ add r2, r2, r3
+ mov r3, r2
+.L24:
+ ldrb r1, [r0], #1 @ zero_extendqisi2
+ ldrb r2, [r3, #1]! @ zero_extendqisi2
+ cmp r0, r5
+ eor r2, r2, r1
+ strb r2, [r4], #1
+ bne .L24
+ adds r7, r7, #132
+ mov sp, r7
+ @ sp needed
+ vldm sp!, {d8-d15}
+ pop {r4, r5, r6, r7, r8, r9, r10, fp, pc}
+.L26:
+ str fp, [r7, #16]
+ b .L2
+.L90:
+ ldr r3, [r7, #12]
+ add lr, r1, #16
+ mov r4, r5
+ mov r6, r5
+ mov r5, r1
+ vadd.i32 q13, q13, q15
+ ldr r0, [r3, #16]! @ unaligned
+ cmp r9, #47
+ ldr r1, [r3, #4] @ unaligned
+ ldr r2, [r3, #8] @ unaligned
+ ldr r3, [r3, #12] @ unaligned
+ stmia r6!, {r0, r1, r2, r3}
+ ldr r2, [r7, #72]
+ vldr d18, [r2, #80]
+ vldr d19, [r2, #88]
+ veor q13, q9, q13
+ vstr d26, [r2, #80]
+ vstr d27, [r2, #88]
+ ldmia r4!, {r0, r1, r2, r3}
+ str r0, [r5, #16] @ unaligned
+ str r1, [lr, #4] @ unaligned
+ str r2, [lr, #8] @ unaligned
+ str r3, [lr, #12] @ unaligned
+ bhi .L91
+ vadd.i32 q8, q14, q8
+ ldr r3, [r7, #72]
+ vstr d16, [r3, #32]
+ vstr d17, [r3, #40]
+ b .L14
+.L91:
+ ldr r3, [r7, #12]
+ add lr, r5, #32
+ ldr r4, [r7, #68]
+ vadd.i32 q8, q14, q8
+ ldr r5, [r7, #72]
+ vadd.i32 q11, q11, q3
+ ldr r0, [r3, #32]! @ unaligned
+ mov r6, r4
+ vstr d22, [r5, #48]
+ vstr d23, [r5, #56]
+ ldr r1, [r3, #4] @ unaligned
+ ldr r2, [r3, #8] @ unaligned
+ ldr r3, [r3, #12] @ unaligned
+ stmia r4!, {r0, r1, r2, r3}
+ vldr d18, [r5, #80]
+ vldr d19, [r5, #88]
+ veor q9, q9, q8
+ ldr r4, [r7, #16]
+ vstr d18, [r5, #80]
+ vstr d19, [r5, #88]
+ ldmia r6!, {r0, r1, r2, r3}
+ str r0, [r4, #32] @ unaligned
+ str r1, [lr, #4] @ unaligned
+ str r2, [lr, #8] @ unaligned
+ str r3, [lr, #12] @ unaligned
+ b .L14
+ .size CRYPTO_chacha_20_neon, .-CRYPTO_chacha_20_neon
+ .section .rodata
+ .align 2
+.LANCHOR0 = . + 0
+.LC0:
+ .word 1634760805
+ .word 857760878
+ .word 2036477234
+ .word 1797285236
+ .ident "GCC: (Linaro GCC 2014.11) 4.9.3 20141031 (prerelease)"
+ .section .note.GNU-stack,"",%progbits
+
+#endif /* !OPENSSL_NO_ASM */
diff --git a/src/crypto/cipher/CMakeLists.txt b/src/crypto/cipher/CMakeLists.txt
new file mode 100644
index 0000000..bb62b72
--- /dev/null
+++ b/src/crypto/cipher/CMakeLists.txt
@@ -0,0 +1,38 @@
+include_directories(. .. ../../include)
+
+add_library(
+ cipher
+
+ OBJECT
+
+ cipher.c
+ cipher_error.c
+ derive_key.c
+ aead.c
+
+ e_null.c
+ e_rc2.c
+ e_rc4.c
+ e_des.c
+ e_aes.c
+ e_chacha20poly1305.c
+
+ tls_cbc.c
+ e_tls.c
+ e_ssl3.c
+)
+
+add_executable(
+ cipher_test
+
+ cipher_test.c
+)
+
+add_executable(
+ aead_test
+
+ aead_test.c
+)
+
+target_link_libraries(cipher_test crypto)
+target_link_libraries(aead_test crypto)
diff --git a/src/crypto/cipher/aead.c b/src/crypto/cipher/aead.c
new file mode 100644
index 0000000..263e398
--- /dev/null
+++ b/src/crypto/cipher/aead.c
@@ -0,0 +1,119 @@
+/* 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 <openssl/aead.h>
+
+#include <string.h>
+
+#include <openssl/cipher.h>
+#include <openssl/err.h>
+
+#include "internal.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 uint8_t *key, size_t key_len, size_t tag_len,
+ ENGINE *impl) {
+ ctx->aead = aead;
+ if (key_len != aead->key_len) {
+ OPENSSL_PUT_ERROR(CIPHER, EVP_AEAD_CTX_init, CIPHER_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;
+}
+
+/* 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 uint8_t *in, size_t in_len, const uint8_t *out) {
+ if (out <= in) {
+ return 1;
+ } else if (in + in_len <= out) {
+ return 1;
+ }
+ return 0;
+}
+
+int EVP_AEAD_CTX_seal(const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len,
+ size_t max_out_len, const uint8_t *nonce,
+ size_t nonce_len, const uint8_t *in, size_t in_len,
+ const uint8_t *ad, size_t ad_len) {
+ size_t possible_out_len = in_len + ctx->aead->overhead;
+
+ if (possible_out_len < in_len /* overflow */) {
+ OPENSSL_PUT_ERROR(CIPHER, EVP_AEAD_CTX_seal, CIPHER_R_TOO_LARGE);
+ goto error;
+ }
+
+ if (!check_alias(in, in_len, out)) {
+ OPENSSL_PUT_ERROR(CIPHER, EVP_AEAD_CTX_seal, CIPHER_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, uint8_t *out, size_t *out_len,
+ size_t max_out_len, const uint8_t *nonce,
+ size_t nonce_len, const uint8_t *in, size_t in_len,
+ const uint8_t *ad, size_t ad_len) {
+ if (!check_alias(in, in_len, out)) {
+ OPENSSL_PUT_ERROR(CIPHER, EVP_AEAD_CTX_open, CIPHER_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/src/crypto/cipher/aead_test.c b/src/crypto/cipher/aead_test.c
new file mode 100644
index 0000000..310c90c
--- /dev/null
+++ b/src/crypto/cipher/aead_test.c
@@ -0,0 +1,387 @@
+/* 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 <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <openssl/aead.h>
+#include <openssl/bio.h>
+#include <openssl/crypto.h>
+#include <openssl/err.h>
+
+/* 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 or EOF indicates the end of
+ * the test case.
+ *
+ * For example, here's a valid test case:
+ *
+ * KEY: 5a19f3173586b4c42f8412f4d5a786531b3231753e9e00998aec12fda8df10e4
+ * NONCE: 978105dfce667bf4
+ * IN: 6a4583908d
+ * AD: b654574932
+ * CT: 5294265a60
+ * TAG: 1d45758621762e061368e68868e2f929
+ */
+
+#define BUF_MAX 512
+
+/* These are the different types of line that are found in the input file. */
+enum {
+ KEY = 0, /* 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. */
+ NO_SEAL, /* non-zero length if seal(IN) is not expected to be CT+TAG,
+ however open(CT+TAG) should still be IN. */
+ FAILS, /* non-zero length if open(CT+TAG) is expected to fail. */
+ NUM_TYPES,
+};
+
+static const char NAMES[8][NUM_TYPES] = {
+ "KEY", "NONCE", "IN", "AD", "CT", "TAG", "NO_SEAL", "FAILS",
+};
+
+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 run_test_case(const EVP_AEAD *aead,
+ uint8_t bufs[NUM_TYPES][BUF_MAX],
+ const unsigned int lengths[NUM_TYPES],
+ unsigned int line_no) {
+ EVP_AEAD_CTX ctx;
+ size_t ciphertext_len, plaintext_len;
+ uint8_t out[BUF_MAX + EVP_AEAD_MAX_OVERHEAD + 1];
+ /* Note: When calling |EVP_AEAD_CTX_open|, the "stateful" AEADs require
+ * |max_out| be at least |in_len| despite the final output always being
+ * smaller by at least tag length. */
+ uint8_t out2[sizeof(out)];
+
+ 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);
+ return 0;
+ }
+
+ if (!lengths[NO_SEAL]) {
+ if (!EVP_AEAD_CTX_seal(&ctx, out, &ciphertext_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);
+ return 0;
+ }
+
+ if (ciphertext_len != lengths[CT] + lengths[TAG]) {
+ fprintf(stderr, "Bad output length on line %u: %u vs %u\n", line_no,
+ (unsigned)ciphertext_len, (unsigned)(lengths[CT] + lengths[TAG]));
+ return 0;
+ }
+
+ if (memcmp(out, bufs[CT], lengths[CT]) != 0) {
+ fprintf(stderr, "Bad output on line %u\n", line_no);
+ return 0;
+ }
+
+ if (memcmp(out + lengths[CT], bufs[TAG], lengths[TAG]) != 0) {
+ fprintf(stderr, "Bad tag on line %u\n", line_no);
+ return 0;
+ }
+ } else {
+ memcpy(out, bufs[CT], lengths[CT]);
+ memcpy(out + lengths[CT], bufs[TAG], lengths[TAG]);
+ ciphertext_len = lengths[CT] + lengths[TAG];
+ }
+
+ /* The "stateful" AEADs for implementing pre-AEAD cipher suites need to be
+ * reset after each operation. */
+ EVP_AEAD_CTX_cleanup(&ctx);
+ 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);
+ return 0;
+ }
+
+ int ret = EVP_AEAD_CTX_open(&ctx, out2, &plaintext_len, sizeof(out2),
+ bufs[NONCE], lengths[NONCE], out, ciphertext_len,
+ bufs[AD], lengths[AD]);
+ if (lengths[FAILS]) {
+ if (ret) {
+ fprintf(stderr, "Decrypted bad data on line %u\n", line_no);
+ return 0;
+ }
+ ERR_clear_error();
+ } else {
+ if (!ret) {
+ fprintf(stderr, "Failed to decrypt on line %u\n", line_no);
+ return 0;
+ }
+
+ if (plaintext_len != lengths[IN]) {
+ fprintf(stderr, "Bad decrypt on line %u: %u\n", line_no,
+ (unsigned)ciphertext_len);
+ return 0;
+ }
+
+ /* The "stateful" AEADs for implementing pre-AEAD cipher suites need to be
+ * reset after each operation. */
+ EVP_AEAD_CTX_cleanup(&ctx);
+ 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);
+ return 0;
+ }
+
+ /* Garbage at the end isn't ignored. */
+ out[ciphertext_len] = 0;
+ if (EVP_AEAD_CTX_open(&ctx, out2, &plaintext_len, sizeof(out2),
+ bufs[NONCE], lengths[NONCE], out, ciphertext_len + 1,
+ bufs[AD], lengths[AD])) {
+ fprintf(stderr, "Decrypted bad data on line %u\n", line_no);
+ return 0;
+ }
+ ERR_clear_error();
+
+ /* The "stateful" AEADs for implementing pre-AEAD cipher suites need to be
+ * reset after each operation. */
+ EVP_AEAD_CTX_cleanup(&ctx);
+ 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);
+ return 0;
+ }
+
+ /* Verify integrity is checked. */
+ out[0] ^= 0x80;
+ if (EVP_AEAD_CTX_open(&ctx, out2, &plaintext_len, sizeof(out2), bufs[NONCE],
+ lengths[NONCE], out, ciphertext_len, bufs[AD],
+ lengths[AD])) {
+ fprintf(stderr, "Decrypted bad data on line %u\n", line_no);
+ return 0;
+ }
+ ERR_clear_error();
+ }
+
+ EVP_AEAD_CTX_cleanup(&ctx);
+ return 1;
+}
+
+int main(int argc, char **argv) {
+ FILE *f;
+ const EVP_AEAD *aead = NULL;
+ unsigned int line_no = 0, num_tests = 0, j;
+
+ unsigned char bufs[NUM_TYPES][BUF_MAX];
+ unsigned int lengths[NUM_TYPES];
+
+ CRYPTO_library_init();
+ ERR_load_crypto_strings();
+
+ if (argc != 3) {
+ fprintf(stderr, "%s <aead> <test file.txt>\n", argv[0]);
+ return 1;
+ }
+
+ if (strcmp(argv[1], "aes-128-gcm") == 0) {
+ aead = EVP_aead_aes_128_gcm();
+ } else if (strcmp(argv[1], "aes-256-gcm") == 0) {
+ aead = EVP_aead_aes_256_gcm();
+ } else if (strcmp(argv[1], "chacha20-poly1305") == 0) {
+ aead = EVP_aead_chacha20_poly1305();
+ } else if (strcmp(argv[1], "rc4-md5-tls") == 0) {
+ aead = EVP_aead_rc4_md5_tls();
+ } else if (strcmp(argv[1], "rc4-sha1-tls") == 0) {
+ aead = EVP_aead_rc4_sha1_tls();
+ } else if (strcmp(argv[1], "aes-128-cbc-sha1-tls") == 0) {
+ aead = EVP_aead_aes_128_cbc_sha1_tls();
+ } else if (strcmp(argv[1], "aes-128-cbc-sha1-tls-implicit-iv") == 0) {
+ aead = EVP_aead_aes_128_cbc_sha1_tls_implicit_iv();
+ } else if (strcmp(argv[1], "aes-128-cbc-sha256-tls") == 0) {
+ aead = EVP_aead_aes_128_cbc_sha256_tls();
+ } else if (strcmp(argv[1], "aes-256-cbc-sha1-tls") == 0) {
+ aead = EVP_aead_aes_256_cbc_sha1_tls();
+ } else if (strcmp(argv[1], "aes-256-cbc-sha1-tls-implicit-iv") == 0) {
+ aead = EVP_aead_aes_256_cbc_sha1_tls_implicit_iv();
+ } else if (strcmp(argv[1], "aes-256-cbc-sha256-tls") == 0) {
+ aead = EVP_aead_aes_256_cbc_sha256_tls();
+ } else if (strcmp(argv[1], "aes-256-cbc-sha384-tls") == 0) {
+ aead = EVP_aead_aes_256_cbc_sha384_tls();
+ } else if (strcmp(argv[1], "des-ede3-cbc-sha1-tls") == 0) {
+ aead = EVP_aead_des_ede3_cbc_sha1_tls();
+ } else if (strcmp(argv[1], "des-ede3-cbc-sha1-tls-implicit-iv") == 0) {
+ aead = EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv();
+ } else if (strcmp(argv[1], "rc4-md5-ssl3") == 0) {
+ aead = EVP_aead_rc4_md5_ssl3();
+ } else if (strcmp(argv[1], "rc4-sha1-ssl3") == 0) {
+ aead = EVP_aead_rc4_sha1_ssl3();
+ } else if (strcmp(argv[1], "aes-128-cbc-sha1-ssl3") == 0) {
+ aead = EVP_aead_aes_128_cbc_sha1_ssl3();
+ } else if (strcmp(argv[1], "aes-256-cbc-sha1-ssl3") == 0) {
+ aead = EVP_aead_aes_256_cbc_sha1_ssl3();
+ } else if (strcmp(argv[1], "des-ede3-cbc-sha1-ssl3") == 0) {
+ aead = EVP_aead_des_ede3_cbc_sha1_ssl3();
+ } else if (strcmp(argv[1], "aes-128-key-wrap") == 0) {
+ aead = EVP_aead_aes_128_key_wrap();
+ } else if (strcmp(argv[1], "aes-256-key-wrap") == 0) {
+ aead = EVP_aead_aes_256_key_wrap();
+ } else {
+ fprintf(stderr, "Unknown AEAD: %s\n", argv[1]);
+ return 2;
+ }
+
+ f = fopen(argv[2], "r");
+ if (f == 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)) {
+ line[0] = 0;
+ }
+
+ 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) {
+ if (!run_test_case(aead, bufs, lengths, line_no)) {
+ BIO_print_errors_fp(stderr);
+ return 4;
+ }
+
+ for (j = 0; j < NUM_TYPES; j++) {
+ lengths[j] = 0;
+ }
+
+ num_tests++;
+ }
+
+ if (line[0] == 0) {
+ break;
+ }
+ 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];
+ }
+
+ if (buf == NULL) {
+ fprintf(stderr, "Unknown line type on line %u\n", line_no);
+ return 3;
+ }
+
+ j = 0;
+ for (; 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/src/crypto/cipher/cipher.c b/src/crypto/cipher/cipher.c
new file mode 100644
index 0000000..4bb4196
--- /dev/null
+++ b/src/crypto/cipher/cipher.c
@@ -0,0 +1,654 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/cipher.h>
+
+#include <assert.h>
+#include <string.h>
+
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+
+#include "internal.h"
+
+
+const EVP_CIPHER *EVP_get_cipherbynid(int nid) {
+ switch (nid) {
+ case NID_des_ede3_cbc:
+ return EVP_des_ede3_cbc();
+ case NID_des_ede_cbc:
+ return EVP_des_cbc();
+ case NID_aes_128_cbc:
+ return EVP_aes_128_cbc();
+ case NID_aes_256_cbc:
+ return EVP_aes_256_cbc();
+ default:
+ return NULL;
+ }
+}
+
+void EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *ctx) {
+ memset(ctx, 0, sizeof(EVP_CIPHER_CTX));
+}
+
+EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void) {
+ EVP_CIPHER_CTX *ctx = OPENSSL_malloc(sizeof(EVP_CIPHER_CTX));
+ if (ctx) {
+ EVP_CIPHER_CTX_init(ctx);
+ }
+ return ctx;
+}
+
+int EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *c) {
+ if (c->cipher != NULL && c->cipher->cleanup && !c->cipher->cleanup(c)) {
+ return 0;
+ }
+
+ if (c->cipher_data) {
+ OPENSSL_cleanse(c->cipher_data, c->cipher->ctx_size);
+ OPENSSL_free(c->cipher_data);
+ }
+
+ memset(c, 0, sizeof(EVP_CIPHER_CTX));
+ return 1;
+}
+
+void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx) {
+ if (ctx) {
+ EVP_CIPHER_CTX_cleanup(ctx);
+ OPENSSL_free(ctx);
+ }
+}
+
+int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in) {
+ if (in == NULL || in->cipher == NULL) {
+ OPENSSL_PUT_ERROR(CIPHER, EVP_CIPHER_CTX_copy, CIPHER_R_INPUT_NOT_INITIALIZED);
+ return 0;
+ }
+
+ EVP_CIPHER_CTX_cleanup(out);
+ memcpy(out, in, sizeof(EVP_CIPHER_CTX));
+
+ if (in->cipher_data && in->cipher->ctx_size) {
+ out->cipher_data = OPENSSL_malloc(in->cipher->ctx_size);
+ if (!out->cipher_data) {
+ OPENSSL_PUT_ERROR(CIPHER, EVP_CIPHER_CTX_copy, 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) {
+ return in->cipher->ctrl((EVP_CIPHER_CTX *)in, EVP_CTRL_COPY, 0, out);
+ }
+
+ return 1;
+}
+
+int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
+ ENGINE *engine, const uint8_t *key, const uint8_t *iv,
+ int enc) {
+ if (enc == -1) {
+ enc = ctx->encrypt;
+ } else {
+ if (enc) {
+ enc = 1;
+ }
+ ctx->encrypt = enc;
+ }
+
+ if (cipher) {
+ /* Ensure a context left 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) {
+ EVP_CIPHER_CTX_cleanup(ctx);
+ /* Restore encrypt and flags */
+ ctx->encrypt = enc;
+ }
+
+ ctx->cipher = cipher;
+ if (ctx->cipher->ctx_size) {
+ ctx->cipher_data = OPENSSL_malloc(ctx->cipher->ctx_size);
+ if (!ctx->cipher_data) {
+ OPENSSL_PUT_ERROR(CIPHER, EVP_CipherInit_ex, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ } else {
+ ctx->cipher_data = NULL;
+ }
+
+ ctx->key_len = cipher->key_len;
+ ctx->flags = 0;
+
+ if (ctx->cipher->flags & EVP_CIPH_CTRL_INIT) {
+ if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_INIT, 0, NULL)) {
+ OPENSSL_PUT_ERROR(CIPHER, EVP_CipherInit_ex, CIPHER_R_INITIALIZATION_ERROR);
+ return 0;
+ }
+ }
+ } else if (!ctx->cipher) {
+ OPENSSL_PUT_ERROR(CIPHER, EVP_CipherInit_ex, CIPHER_R_NO_CIPHER_SET);
+ return 0;
+ }
+
+ /* we assume block size is a power of 2 in *cryptUpdate */
+ assert(ctx->cipher->block_size == 1 || ctx->cipher->block_size == 8 ||
+ ctx->cipher->block_size == 16);
+
+ 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:
+ assert(EVP_CIPHER_CTX_iv_length(ctx) <= sizeof(ctx->iv));
+ if (iv) {
+ memcpy(ctx->oiv, iv, EVP_CIPHER_CTX_iv_length(ctx));
+ }
+ memcpy(ctx->iv, ctx->oiv, EVP_CIPHER_CTX_iv_length(ctx));
+ 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;
+ }
+ }
+
+ 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_EncryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
+ ENGINE *impl, const uint8_t *key, const uint8_t *iv) {
+ return EVP_CipherInit_ex(ctx, cipher, impl, key, iv, 1);
+}
+
+int EVP_DecryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
+ ENGINE *impl, const uint8_t *key, const uint8_t *iv) {
+ return EVP_CipherInit_ex(ctx, cipher, impl, key, iv, 0);
+}
+
+int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, uint8_t *out, int *out_len,
+ const uint8_t *in, int in_len) {
+ int i, j, bl;
+
+ if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) {
+ i = ctx->cipher->cipher(ctx, out, in, in_len);
+ if (i < 0) {
+ return 0;
+ } else {
+ *out_len = i;
+ }
+ return 1;
+ }
+
+ if (in_len <= 0) {
+ *out_len = 0;
+ return in_len == 0;
+ }
+
+ if (ctx->buf_len == 0 && (in_len & ctx->block_mask) == 0) {
+ if (ctx->cipher->cipher(ctx, out, in, in_len)) {
+ *out_len = in_len;
+ return 1;
+ } else {
+ *out_len = 0;
+ return 0;
+ }
+ }
+
+ i = ctx->buf_len;
+ bl = ctx->cipher->block_size;
+ assert(bl <= (int)sizeof(ctx->buf));
+ if (i != 0) {
+ if (i + in_len < bl) {
+ memcpy(&ctx->buf[i], in, in_len);
+ ctx->buf_len += in_len;
+ *out_len = 0;
+ return 1;
+ } else {
+ j = bl - i;
+ memcpy(&ctx->buf[i], in, j);
+ if (!ctx->cipher->cipher(ctx, out, ctx->buf, bl)) {
+ return 0;
+ }
+ in_len -= j;
+ in += j;
+ out += bl;
+ *out_len = bl;
+ }
+ } else {
+ *out_len = 0;
+ }
+
+ i = in_len & ctx->block_mask;
+ in_len -= i;
+ if (in_len > 0) {
+ if (!ctx->cipher->cipher(ctx, out, in, in_len)) {
+ return 0;
+ }
+ *out_len += in_len;
+ }
+
+ if (i != 0) {
+ memcpy(ctx->buf, &in[in_len], i);
+ }
+ ctx->buf_len = i;
+ return 1;
+}
+
+int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, uint8_t *out, int *out_len) {
+ int n, ret;
+ unsigned int i, b, bl;
+
+ if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) {
+ ret = ctx->cipher->cipher(ctx, out, NULL, 0);
+ if (ret < 0) {
+ return 0;
+ } else {
+ *out_len = ret;
+ }
+ return 1;
+ }
+
+ b = ctx->cipher->block_size;
+ assert(b <= sizeof(ctx->buf));
+ if (b == 1) {
+ *out_len = 0;
+ return 1;
+ }
+
+ bl = ctx->buf_len;
+ if (ctx->flags & EVP_CIPH_NO_PADDING) {
+ if (bl) {
+ OPENSSL_PUT_ERROR(CIPHER, EVP_EncryptFinal_ex,
+ CIPHER_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH);
+ return 0;
+ }
+ *out_len = 0;
+ return 1;
+ }
+
+ n = b - bl;
+ for (i = bl; i < b; i++) {
+ ctx->buf[i] = n;
+ }
+ ret = ctx->cipher->cipher(ctx, out, ctx->buf, b);
+
+ if (ret) {
+ *out_len = b;
+ }
+
+ return ret;
+}
+
+int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, uint8_t *out, int *out_len,
+ const uint8_t *in, int in_len) {
+ int fix_len;
+ unsigned int b;
+
+ if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) {
+ int r = ctx->cipher->cipher(ctx, out, in, in_len);
+ if (r < 0) {
+ *out_len = 0;
+ return 0;
+ } else {
+ *out_len = r;
+ }
+ return 1;
+ }
+
+ if (in_len <= 0) {
+ *out_len = 0;
+ return in_len == 0;
+ }
+
+ if (ctx->flags & EVP_CIPH_NO_PADDING) {
+ return EVP_EncryptUpdate(ctx, out, out_len, in, in_len);
+ }
+
+ b = ctx->cipher->block_size;
+ assert(b <= sizeof(ctx->final));
+
+ if (ctx->final_used) {
+ memcpy(out, ctx->final, b);
+ out += b;
+ fix_len = 1;
+ } else {
+ fix_len = 0;
+ }
+
+ if (!EVP_EncryptUpdate(ctx, out, out_len, in, in_len)) {
+ 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) {
+ *out_len -= b;
+ ctx->final_used = 1;
+ memcpy(ctx->final, &out[*out_len], b);
+ } else {
+ ctx->final_used = 0;
+ }
+
+ if (fix_len) {
+ *out_len += b;
+ }
+
+ return 1;
+}
+
+int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *out_len) {
+ int i, n;
+ unsigned int b;
+ *out_len = 0;
+
+ if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) {
+ i = ctx->cipher->cipher(ctx, out, NULL, 0);
+ if (i < 0) {
+ return 0;
+ } else {
+ *out_len = i;
+ }
+ return 1;
+ }
+
+ b = ctx->cipher->block_size;
+ if (ctx->flags & EVP_CIPH_NO_PADDING) {
+ if (ctx->buf_len) {
+ OPENSSL_PUT_ERROR(CIPHER, EVP_DecryptFinal_ex,
+ CIPHER_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH);
+ return 0;
+ }
+ *out_len = 0;
+ return 1;
+ }
+
+ if (b > 1) {
+ if (ctx->buf_len || !ctx->final_used) {
+ OPENSSL_PUT_ERROR(CIPHER, EVP_DecryptFinal_ex,
+ CIPHER_R_WRONG_FINAL_BLOCK_LENGTH);
+ return 0;
+ }
+ assert(b <= sizeof(ctx->final));
+
+ /* The following assumes that the ciphertext has been authenticated.
+ * Otherwise it provides a padding oracle. */
+ n = ctx->final[b - 1];
+ if (n == 0 || n > (int)b) {
+ OPENSSL_PUT_ERROR(CIPHER, EVP_DecryptFinal_ex, CIPHER_R_BAD_DECRYPT);
+ return 0;
+ }
+
+ for (i = 0; i < n; i++) {
+ if (ctx->final[--b] != n) {
+ OPENSSL_PUT_ERROR(CIPHER, EVP_DecryptFinal_ex, CIPHER_R_BAD_DECRYPT);
+ return 0;
+ }
+ }
+
+ n = ctx->cipher->block_size - n;
+ for (i = 0; i < n; i++) {
+ out[i] = ctx->final[i];
+ }
+ *out_len = n;
+ } else {
+ *out_len = 0;
+ }
+
+ return 1;
+}
+
+int EVP_Cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
+ size_t in_len) {
+ return ctx->cipher->cipher(ctx, out, in, in_len);
+}
+
+int EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, uint8_t *out, int *out_len,
+ const uint8_t *in, int in_len) {
+ if (ctx->encrypt) {
+ return EVP_EncryptUpdate(ctx, out, out_len, in, in_len);
+ } else {
+ return EVP_DecryptUpdate(ctx, out, out_len, in, in_len);
+ }
+}
+
+int EVP_CipherFinal_ex(EVP_CIPHER_CTX *ctx, uint8_t *out, int *out_len) {
+ if (ctx->encrypt) {
+ return EVP_EncryptFinal_ex(ctx, out, out_len);
+ } else {
+ return EVP_DecryptFinal_ex(ctx, out, out_len);
+ }
+}
+
+const EVP_CIPHER *EVP_CIPHER_CTX_cipher(const EVP_CIPHER_CTX *ctx) {
+ return ctx->cipher;
+}
+
+int EVP_CIPHER_CTX_nid(const EVP_CIPHER_CTX *ctx) {
+ return ctx->cipher->nid;
+}
+
+unsigned EVP_CIPHER_CTX_block_size(const EVP_CIPHER_CTX *ctx) {
+ return ctx->cipher->block_size;
+}
+
+unsigned EVP_CIPHER_CTX_key_length(const EVP_CIPHER_CTX *ctx) {
+ return ctx->key_len;
+}
+
+unsigned EVP_CIPHER_CTX_iv_length(const EVP_CIPHER_CTX *ctx) {
+ return ctx->cipher->iv_len;
+}
+
+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;
+}
+
+uint32_t EVP_CIPHER_CTX_flags(const EVP_CIPHER_CTX *ctx) {
+ return ctx->cipher->flags & ~EVP_CIPH_MODE_MASK;
+}
+
+uint32_t EVP_CIPHER_CTX_mode(const EVP_CIPHER_CTX *ctx) {
+ return ctx->cipher->flags & EVP_CIPH_MODE_MASK;
+}
+
+int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int command, int arg, void *ptr) {
+ int ret;
+ if (!ctx->cipher) {
+ OPENSSL_PUT_ERROR(CIPHER, EVP_CIPHER_CTX_ctrl, CIPHER_R_NO_CIPHER_SET);
+ return 0;
+ }
+
+ if (!ctx->cipher->ctrl) {
+ OPENSSL_PUT_ERROR(CIPHER, EVP_CIPHER_CTX_ctrl, CIPHER_R_CTRL_NOT_IMPLEMENTED);
+ return 0;
+ }
+
+ ret = ctx->cipher->ctrl(ctx, command, arg, ptr);
+ if (ret == -1) {
+ OPENSSL_PUT_ERROR(CIPHER, EVP_CIPHER_CTX_ctrl,
+ CIPHER_R_CTRL_OPERATION_NOT_IMPLEMENTED);
+ return 0;
+ }
+
+ return ret;
+}
+
+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_set_key_length(EVP_CIPHER_CTX *c, unsigned key_len) {
+ if (c->key_len == key_len) {
+ return 1;
+ }
+
+ if (key_len == 0 || !(c->cipher->flags & EVP_CIPH_VARIABLE_LENGTH)) {
+ OPENSSL_PUT_ERROR(CIPHER, EVP_CIPHER_CTX_set_key_length,
+ CIPHER_R_INVALID_KEY_LENGTH);
+ return 0;
+ }
+
+ c->key_len = key_len;
+ return 1;
+}
+
+int EVP_CIPHER_nid(const EVP_CIPHER *cipher) { return cipher->nid; }
+
+const char *EVP_CIPHER_name(const EVP_CIPHER *cipher) {
+ return OBJ_nid2sn(cipher->nid);
+}
+
+unsigned EVP_CIPHER_block_size(const EVP_CIPHER *cipher) {
+ return cipher->block_size;
+}
+
+unsigned EVP_CIPHER_key_length(const EVP_CIPHER *cipher) {
+ return cipher->key_len;
+}
+
+unsigned EVP_CIPHER_iv_length(const EVP_CIPHER *cipher) {
+ return cipher->iv_len;
+}
+
+uint32_t EVP_CIPHER_flags(const EVP_CIPHER *cipher) {
+ return cipher->flags & ~EVP_CIPH_MODE_MASK;
+}
+
+uint32_t EVP_CIPHER_mode(const EVP_CIPHER *cipher) {
+ return cipher->flags & EVP_CIPH_MODE_MASK;
+}
+
+int EVP_CipherInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
+ const uint8_t *key, const uint8_t *iv, int enc) {
+ if (cipher) {
+ EVP_CIPHER_CTX_init(ctx);
+ }
+ return EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, enc);
+}
+
+int EVP_EncryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
+ const uint8_t *key, const uint8_t *iv) {
+ return EVP_CipherInit(ctx, cipher, key, iv, 1);
+}
+
+int EVP_DecryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
+ const uint8_t *key, const uint8_t *iv) {
+ return EVP_CipherInit(ctx, cipher, key, iv, 0);
+}
+
+int EVP_add_cipher_alias(const char *a, const char *b) {
+ return 1;
+}
+
+const EVP_CIPHER *EVP_get_cipherbyname(const char *name) {
+ if (OPENSSL_strcasecmp(name, "rc4") == 0) {
+ return EVP_rc4();
+ } else if (OPENSSL_strcasecmp(name, "des-cbc") == 0) {
+ return EVP_des_cbc();
+ } else if (OPENSSL_strcasecmp(name, "3des-cbc") == 0 ||
+ OPENSSL_strcasecmp(name, "3des") == 0) {
+ return EVP_des_ede3_cbc();
+ } else if (OPENSSL_strcasecmp(name, "aes-128-cbc") == 0) {
+ return EVP_aes_128_cbc();
+ } else if (OPENSSL_strcasecmp(name, "aes-256-cbc") == 0) {
+ return EVP_aes_256_cbc();
+ } else if (OPENSSL_strcasecmp(name, "aes-128-ctr") == 0) {
+ return EVP_aes_128_ctr();
+ } else if (OPENSSL_strcasecmp(name, "aes-256-ctr") == 0) {
+ return EVP_aes_256_ctr();
+ } else if (OPENSSL_strcasecmp(name, "aes-128-ecb") == 0) {
+ return EVP_aes_128_ecb();
+ } else if (OPENSSL_strcasecmp(name, "aes-256-ecb") == 0) {
+ return EVP_aes_256_ecb();
+ }
+
+ return NULL;
+}
diff --git a/src/crypto/cipher/cipher_error.c b/src/crypto/cipher/cipher_error.c
new file mode 100644
index 0000000..95230f6
--- /dev/null
+++ b/src/crypto/cipher/cipher_error.c
@@ -0,0 +1,78 @@
+/* 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 <openssl/err.h>
+
+#include <openssl/cipher.h>
+
+const ERR_STRING_DATA CIPHER_error_string_data[] = {
+ {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_EVP_AEAD_CTX_init, 0), "EVP_AEAD_CTX_init"},
+ {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_EVP_AEAD_CTX_open, 0), "EVP_AEAD_CTX_open"},
+ {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_EVP_AEAD_CTX_seal, 0), "EVP_AEAD_CTX_seal"},
+ {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_EVP_CIPHER_CTX_copy, 0), "EVP_CIPHER_CTX_copy"},
+ {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_EVP_CIPHER_CTX_ctrl, 0), "EVP_CIPHER_CTX_ctrl"},
+ {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_EVP_CIPHER_CTX_set_key_length, 0), "EVP_CIPHER_CTX_set_key_length"},
+ {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_EVP_CipherInit_ex, 0), "EVP_CipherInit_ex"},
+ {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_EVP_DecryptFinal_ex, 0), "EVP_DecryptFinal_ex"},
+ {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_EVP_EncryptFinal_ex, 0), "EVP_EncryptFinal_ex"},
+ {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_aead_aes_gcm_init, 0), "aead_aes_gcm_init"},
+ {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_aead_aes_gcm_open, 0), "aead_aes_gcm_open"},
+ {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_aead_aes_gcm_seal, 0), "aead_aes_gcm_seal"},
+ {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_aead_aes_key_wrap_init, 0), "aead_aes_key_wrap_init"},
+ {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_aead_aes_key_wrap_open, 0), "aead_aes_key_wrap_open"},
+ {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_aead_aes_key_wrap_seal, 0), "aead_aes_key_wrap_seal"},
+ {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_aead_chacha20_poly1305_init, 0), "aead_chacha20_poly1305_init"},
+ {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_aead_chacha20_poly1305_open, 0), "aead_chacha20_poly1305_open"},
+ {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_aead_chacha20_poly1305_seal, 0), "aead_chacha20_poly1305_seal"},
+ {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_aead_rc4_md5_tls_init, 0), "aead_rc4_md5_tls_init"},
+ {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_aead_rc4_md5_tls_open, 0), "aead_rc4_md5_tls_open"},
+ {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_aead_rc4_md5_tls_seal, 0), "aead_rc4_md5_tls_seal"},
+ {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_aead_ssl3_ensure_cipher_init, 0), "aead_ssl3_ensure_cipher_init"},
+ {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_aead_ssl3_init, 0), "aead_ssl3_init"},
+ {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_aead_ssl3_open, 0), "aead_ssl3_open"},
+ {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_aead_ssl3_seal, 0), "aead_ssl3_seal"},
+ {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_aead_tls_ensure_cipher_init, 0), "aead_tls_ensure_cipher_init"},
+ {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_aead_tls_init, 0), "aead_tls_init"},
+ {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_aead_tls_open, 0), "aead_tls_open"},
+ {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_aead_tls_seal, 0), "aead_tls_seal"},
+ {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_aes_init_key, 0), "aes_init_key"},
+ {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_aesni_init_key, 0), "aesni_init_key"},
+ {ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_AES_KEY_SETUP_FAILED), "AES_KEY_SETUP_FAILED"},
+ {ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_BAD_DECRYPT), "BAD_DECRYPT"},
+ {ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_BAD_KEY_LENGTH), "BAD_KEY_LENGTH"},
+ {ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_BUFFER_TOO_SMALL), "BUFFER_TOO_SMALL"},
+ {ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_CTRL_NOT_IMPLEMENTED), "CTRL_NOT_IMPLEMENTED"},
+ {ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_CTRL_OPERATION_NOT_IMPLEMENTED), "CTRL_OPERATION_NOT_IMPLEMENTED"},
+ {ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH), "DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH"},
+ {ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_INITIALIZATION_ERROR), "INITIALIZATION_ERROR"},
+ {ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_INPUT_NOT_INITIALIZED), "INPUT_NOT_INITIALIZED"},
+ {ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_INVALID_AD), "INVALID_AD"},
+ {ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_INVALID_AD_SIZE), "INVALID_AD_SIZE"},
+ {ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_INVALID_KEY_LENGTH), "INVALID_KEY_LENGTH"},
+ {ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_INVALID_NONCE_SIZE), "INVALID_NONCE_SIZE"},
+ {ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_INVALID_OPERATION), "INVALID_OPERATION"},
+ {ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_IV_TOO_LARGE), "IV_TOO_LARGE"},
+ {ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_NO_CIPHER_SET), "NO_CIPHER_SET"},
+ {ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_OUTPUT_ALIASES_INPUT), "OUTPUT_ALIASES_INPUT"},
+ {ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_TAG_TOO_LARGE), "TAG_TOO_LARGE"},
+ {ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_TOO_LARGE), "TOO_LARGE"},
+ {ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_UNSUPPORTED_AD_SIZE), "UNSUPPORTED_AD_SIZE"},
+ {ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_UNSUPPORTED_INPUT_SIZE), "UNSUPPORTED_INPUT_SIZE"},
+ {ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_UNSUPPORTED_KEY_SIZE), "UNSUPPORTED_KEY_SIZE"},
+ {ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_UNSUPPORTED_NONCE_SIZE), "UNSUPPORTED_NONCE_SIZE"},
+ {ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_UNSUPPORTED_TAG_SIZE), "UNSUPPORTED_TAG_SIZE"},
+ {ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_WRAP_MODE_NOT_ALLOWED), "WRAP_MODE_NOT_ALLOWED"},
+ {ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_WRONG_FINAL_BLOCK_LENGTH), "WRONG_FINAL_BLOCK_LENGTH"},
+ {0, NULL},
+};
diff --git a/src/crypto/cipher/cipher_test.c b/src/crypto/cipher/cipher_test.c
new file mode 100644
index 0000000..2b04ad5
--- /dev/null
+++ b/src/crypto/cipher/cipher_test.c
@@ -0,0 +1,413 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <stdio.h>
+#include <string.h>
+
+#include <openssl/bio.h>
+#include <openssl/cipher.h>
+#include <openssl/crypto.h>
+#include <openssl/err.h>
+
+
+static void hexdump(FILE *f, const char *title, const uint8_t *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(uint8_t *s) {
+ uint8_t *d;
+
+ for (d = s; *s; s += 2, ++d) {
+ unsigned int n;
+
+ if (!s[1]) {
+ fprintf(stderr, "Odd number of hex digits!");
+ exit(4);
+ }
+ sscanf((char *)s, "%2x", &n);
+ *d = (uint8_t)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[(uint8_t)(*delim)] = 1;
+ delim++;
+ }
+
+ while (!isdelim[(uint8_t)(**string)]) {
+ (*string)++;
+ }
+
+ if (**string) {
+ **string = 0;
+ (*string)++;
+ }
+
+ return token;
+}
+
+static uint8_t *ustrsep(char **p, const char *sep) {
+ return (uint8_t *)sstrsep(p, sep);
+}
+
+static void test1(const EVP_CIPHER *c, const uint8_t *key, int kn,
+ const uint8_t *iv, int in, const uint8_t *plaintext, int pn,
+ const uint8_t *ciphertext, int cn, const uint8_t *aad, int an,
+ const uint8_t *tag, int tn, int encdec) {
+ EVP_CIPHER_CTX ctx;
+ uint8_t out[4096];
+ int outl, outl2, mode;
+
+ 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 (an) {
+ hexdump(stdout, "AAD", aad, an);
+ }
+ if (tn) {
+ hexdump(stdout, "Tag", tag, tn);
+ }
+ mode = EVP_CIPHER_mode(c);
+ 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));
+ exit(5);
+ }
+ EVP_CIPHER_CTX_init(&ctx);
+ if (encdec != 0) {
+ if (mode == EVP_CIPH_GCM_MODE) {
+ if (!EVP_EncryptInit_ex(&ctx, c, NULL, NULL, NULL)) {
+ fprintf(stderr, "EncryptInit failed\n");
+ BIO_print_errors_fp(stderr);
+ exit(10);
+ }
+ if (!EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_IVLEN, in, NULL)) {
+ fprintf(stderr, "IV length set failed\n");
+ BIO_print_errors_fp(stderr);
+ exit(11);
+ }
+ if (!EVP_EncryptInit_ex(&ctx, NULL, NULL, key, iv)) {
+ fprintf(stderr, "Key/IV set failed\n");
+ BIO_print_errors_fp(stderr);
+ exit(12);
+ }
+ if (an && !EVP_EncryptUpdate(&ctx, NULL, &outl, aad, an)) {
+ fprintf(stderr, "AAD set failed\n");
+ BIO_print_errors_fp(stderr);
+ exit(13);
+ }
+ } else if (!EVP_EncryptInit_ex(&ctx, c, NULL, key, iv)) {
+ fprintf(stderr, "EncryptInit failed\n");
+ BIO_print_errors_fp(stderr);
+ exit(10);
+ }
+ EVP_CIPHER_CTX_set_padding(&ctx, 0);
+
+ if (!EVP_EncryptUpdate(&ctx, out, &outl, plaintext, pn)) {
+ fprintf(stderr, "Encrypt failed\n");
+ BIO_print_errors_fp(stderr);
+ exit(6);
+ }
+ if (!EVP_EncryptFinal_ex(&ctx, out + outl, &outl2)) {
+ fprintf(stderr, "EncryptFinal failed\n");
+ BIO_print_errors_fp(stderr);
+ exit(7);
+ }
+
+ if (outl + outl2 != cn) {
+ fprintf(stderr, "Ciphertext length mismatch got %d expected %d\n",
+ outl + outl2, cn);
+ exit(8);
+ }
+
+ if (memcmp(out, ciphertext, cn)) {
+ fprintf(stderr, "Ciphertext mismatch\n");
+ hexdump(stderr, "Got", out, cn);
+ hexdump(stderr, "Expected", ciphertext, cn);
+ exit(9);
+ }
+ if (mode == EVP_CIPH_GCM_MODE) {
+ uint8_t rtag[16];
+ /* Note: EVP_CTRL_CCM_GET_TAG has same value as
+ * EVP_CTRL_GCM_GET_TAG
+ */
+ if (!EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_GET_TAG, tn, rtag)) {
+ fprintf(stderr, "Get tag failed\n");
+ BIO_print_errors_fp(stderr);
+ exit(14);
+ }
+ if (memcmp(rtag, tag, tn)) {
+ fprintf(stderr, "Tag mismatch\n");
+ hexdump(stderr, "Got", rtag, tn);
+ hexdump(stderr, "Expected", tag, tn);
+ exit(9);
+ }
+ }
+ }
+
+ if (encdec <= 0) {
+ if (mode == EVP_CIPH_GCM_MODE) {
+ if (!EVP_DecryptInit_ex(&ctx, c, NULL, NULL, NULL)) {
+ fprintf(stderr, "EncryptInit failed\n");
+ BIO_print_errors_fp(stderr);
+ exit(10);
+ }
+ if (!EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_IVLEN, in, NULL)) {
+ fprintf(stderr, "IV length set failed\n");
+ BIO_print_errors_fp(stderr);
+ exit(11);
+ }
+ if (!EVP_DecryptInit_ex(&ctx, NULL, NULL, key, iv)) {
+ fprintf(stderr, "Key/IV set failed\n");
+ BIO_print_errors_fp(stderr);
+ exit(12);
+ }
+ if (!EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_TAG, tn, (void *)tag)) {
+ fprintf(stderr, "Set tag failed\n");
+ BIO_print_errors_fp(stderr);
+ exit(14);
+ }
+ if (an && !EVP_DecryptUpdate(&ctx, NULL, &outl, aad, an)) {
+ fprintf(stderr, "AAD set failed\n");
+ BIO_print_errors_fp(stderr);
+ exit(13);
+ }
+ } else if (!EVP_DecryptInit_ex(&ctx, c, NULL, key, iv)) {
+ fprintf(stderr, "DecryptInit failed\n");
+ BIO_print_errors_fp(stderr);
+ exit(11);
+ }
+ EVP_CIPHER_CTX_set_padding(&ctx, 0);
+
+ if (!EVP_DecryptUpdate(&ctx, out, &outl, ciphertext, cn)) {
+ fprintf(stderr, "Decrypt failed\n");
+ BIO_print_errors_fp(stderr);
+ exit(6);
+ }
+ outl2 = 0;
+ if (!EVP_DecryptFinal_ex(&ctx, out + outl, &outl2)) {
+ fprintf(stderr, "DecryptFinal failed\n");
+ BIO_print_errors_fp(stderr);
+ exit(7);
+ }
+
+ if (outl + outl2 != pn) {
+ fprintf(stderr, "Plaintext length mismatch got %d expected %d\n",
+ outl + outl2, pn);
+ exit(8);
+ }
+
+ if (memcmp(out, plaintext, pn)) {
+ fprintf(stderr, "Plaintext mismatch\n");
+ hexdump(stderr, "Got", out, pn);
+ hexdump(stderr, "Expected", plaintext, pn);
+ exit(9);
+ }
+ }
+
+ EVP_CIPHER_CTX_cleanup(&ctx);
+
+ printf("\n");
+}
+
+static int test_cipher(const char *cipher, const uint8_t *key, int kn,
+ const uint8_t *iv, int in, const uint8_t *plaintext,
+ int pn, const uint8_t *ciphertext, int cn,
+ const uint8_t *aad, int an, const uint8_t *tag, int tn,
+ int encdec) {
+ const EVP_CIPHER *c;
+
+ if (strcmp(cipher, "DES-CBC") == 0) {
+ c = EVP_des_cbc();
+ } else if (strcmp(cipher, "DES-EDE3-CBC") == 0) {
+ c = EVP_des_ede3_cbc();
+ } else if (strcmp(cipher, "RC4") == 0) {
+ c = EVP_rc4();
+ } else if (strcmp(cipher, "AES-128-ECB") == 0) {
+ c = EVP_aes_128_ecb();
+ } else if (strcmp(cipher, "AES-256-ECB") == 0) {
+ c = EVP_aes_256_ecb();
+ } else if (strcmp(cipher, "AES-128-CBC") == 0) {
+ c = EVP_aes_128_cbc();
+ } else if (strcmp(cipher, "AES-128-GCM") == 0) {
+ c = EVP_aes_128_gcm();
+ } else if (strcmp(cipher, "AES-256-CBC") == 0) {
+ c = EVP_aes_256_cbc();
+ } else if (strcmp(cipher, "AES-128-CTR") == 0) {
+ c = EVP_aes_128_ctr();
+ } else if (strcmp(cipher, "AES-256-CTR") == 0) {
+ c = EVP_aes_256_ctr();
+ } else if (strcmp(cipher, "AES-256-GCM") == 0) {
+ c = EVP_aes_256_gcm();
+ } else {
+ fprintf(stderr, "Unknown cipher type %s\n", cipher);
+ return 0;
+ }
+
+ test1(c, key, kn, iv, in, plaintext, pn, ciphertext, cn, aad, an, tag, tn,
+ encdec);
+
+ return 1;
+}
+
+int main(int argc, char **argv) {
+ const char *input_file;
+ FILE *f;
+
+ CRYPTO_library_init();
+
+ if (argc != 2) {
+ fprintf(stderr, "%s <test file>\n", argv[0]);
+ return 1;
+ }
+
+ input_file = argv[1];
+
+ f = fopen(input_file, "r");
+ if (!f) {
+ perror(input_file);
+ return 2;
+ }
+
+ ERR_load_crypto_strings();
+
+ for (;;) {
+ char line[4096];
+ char *p;
+ char *cipher;
+ uint8_t *iv, *key, *plaintext, *ciphertext, *aad, *tag;
+ int encdec;
+ int kn, in, pn, cn;
+ int an = 0;
+ int tn = 0;
+
+ 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') {
+ encdec = -1;
+ p[-1] = '\0';
+ tag = aad = NULL;
+ an = tn = 0;
+ } else {
+ aad = ustrsep(&p, ":");
+ tag = ustrsep(&p, ":");
+ if (tag == NULL) {
+ p = (char *)aad;
+ tag = aad = NULL;
+ an = tn = 0;
+ }
+ if (p[-1] == '\n') {
+ encdec = -1;
+ p[-1] = '\0';
+ } else
+ encdec = atoi(sstrsep(&p, "\n"));
+ }
+
+ kn = convert(key);
+ in = convert(iv);
+ pn = convert(plaintext);
+ cn = convert(ciphertext);
+ if (aad) {
+ an = convert(aad);
+ tn = convert(tag);
+ }
+
+ if (!test_cipher(cipher, key, kn, iv, in, plaintext, pn, ciphertext, cn,
+ aad, an, tag, tn, encdec)) {
+ return 3;
+ }
+ }
+ fclose(f);
+
+ printf("PASS\n");
+ return 0;
+}
diff --git a/src/crypto/cipher/derive_key.c b/src/crypto/cipher/derive_key.c
new file mode 100644
index 0000000..9e1634a
--- /dev/null
+++ b/src/crypto/cipher/derive_key.c
@@ -0,0 +1,154 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/cipher.h>
+
+#include <assert.h>
+
+#include <openssl/digest.h>
+#include <openssl/mem.h>
+
+#include "internal.h"
+
+
+#define PKCS5_SALT_LEN 8
+
+int EVP_BytesToKey(const EVP_CIPHER *type, const EVP_MD *md,
+ const uint8_t *salt, const uint8_t *data, size_t data_len,
+ unsigned count, uint8_t *key, uint8_t *iv) {
+ EVP_MD_CTX c;
+ uint8_t md_buf[EVP_MAX_MD_SIZE];
+ unsigned niv, nkey, addmd = 0;
+ unsigned mds = 0, i;
+ int rv = 0;
+
+ nkey = type->key_len;
+ niv = type->iv_len;
+
+ assert(nkey <= EVP_MAX_KEY_LENGTH);
+ assert(niv <= EVP_MAX_IV_LENGTH);
+
+ if (data == NULL) {
+ return nkey;
+ }
+
+ EVP_MD_CTX_init(&c);
+ for (;;) {
+ if (!EVP_DigestInit_ex(&c, md, NULL)) {
+ return 0;
+ }
+ if (addmd++) {
+ if (!EVP_DigestUpdate(&c, md_buf, mds)) {
+ goto err;
+ }
+ }
+ if (!EVP_DigestUpdate(&c, data, data_len)) {
+ goto err;
+ }
+ if (salt != NULL) {
+ if (!EVP_DigestUpdate(&c, salt, PKCS5_SALT_LEN)) {
+ goto err;
+ }
+ }
+ if (!EVP_DigestFinal_ex(&c, md_buf, &mds)) {
+ goto err;
+ }
+
+ for (i = 1; i < count; i++) {
+ if (!EVP_DigestInit_ex(&c, md, NULL) ||
+ !EVP_DigestUpdate(&c, md_buf, mds) ||
+ !EVP_DigestFinal_ex(&c, md_buf, &mds)) {
+ goto err;
+ }
+ }
+
+ i = 0;
+ if (nkey) {
+ for (;;) {
+ if (nkey == 0 || i == mds) {
+ break;
+ }
+ if (key != NULL) {
+ *(key++) = md_buf[i];
+ }
+ nkey--;
+ i++;
+ }
+ }
+
+ if (niv && i != mds) {
+ for (;;) {
+ if (niv == 0 || 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);
+ OPENSSL_cleanse(md_buf, EVP_MAX_MD_SIZE);
+ return rv;
+}
diff --git a/src/crypto/cipher/e_aes.c b/src/crypto/cipher/e_aes.c
new file mode 100644
index 0000000..f92bb8e
--- /dev/null
+++ b/src/crypto/cipher/e_aes.c
@@ -0,0 +1,1364 @@
+/* ====================================================================
+ * 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 <string.h>
+
+#include <openssl/aead.h>
+#include <openssl/aes.h>
+#include <openssl/cipher.h>
+#include <openssl/cpu.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/modes.h>
+#include <openssl/obj.h>
+#include <openssl/rand.h>
+
+#include "internal.h"
+#include "../modes/internal.h"
+
+#if defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)
+#include "../arm_arch.h"
+#endif
+
+
+typedef struct {
+ union {
+ double align;
+ AES_KEY ks;
+ } ks;
+ block128_f block;
+ union {
+ cbc128_f cbc;
+ ctr128_f ctr;
+ } stream;
+} EVP_AES_KEY;
+
+typedef struct {
+ union {
+ double align;
+ AES_KEY ks;
+ } 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;
+ uint8_t *iv; /* Temporary IV store */
+ int ivlen; /* IV length */
+ int taglen;
+ int iv_gen; /* It is OK to generate IVs */
+ ctr128_f ctr;
+} EVP_AES_GCM_CTX;
+
+#if !defined(OPENSSL_NO_ASM) && \
+ (defined(OPENSSL_X86_64) || defined(OPENSSL_X86))
+#define VPAES
+extern unsigned int OPENSSL_ia32cap_P[];
+
+static char vpaes_capable(void) {
+ return (OPENSSL_ia32cap_P[1] & (1 << (41 - 32))) != 0;
+}
+
+#if defined(OPENSSL_X86_64)
+#define BSAES
+static char bsaes_capable(void) {
+ return vpaes_capable();
+}
+#endif
+
+#elif !defined(OPENSSL_NO_ASM) && \
+ (defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64))
+#include "../arm_arch.h"
+
+#if defined(OPENSSL_ARM) && __ARM_ARCH__ >= 7
+#define BSAES
+static char bsaes_capable(void) {
+ return CRYPTO_is_NEON_capable();
+}
+#endif
+
+#define HWAES
+static char hwaes_capable(void) {
+ return (OPENSSL_armcap_P & ARMV8_AES) != 0;
+}
+
+int aes_v8_set_encrypt_key(const uint8_t *user_key, const int bits,
+ AES_KEY *key);
+int aes_v8_set_decrypt_key(const uint8_t *user_key, const int bits,
+ AES_KEY *key);
+void aes_v8_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key);
+void aes_v8_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key);
+void aes_v8_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t length,
+ const AES_KEY *key, uint8_t *ivec, const int enc);
+void aes_v8_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out, size_t len,
+ const AES_KEY *key, const uint8_t ivec[16]);
+
+#endif /* OPENSSL_ARM */
+
+#if defined(BSAES)
+/* On platforms where BSAES gets defined (just above), then these functions are
+ * provided by asm. */
+void bsaes_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t length,
+ const AES_KEY *key, uint8_t ivec[16], int enc);
+void bsaes_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out, size_t len,
+ const AES_KEY *key, const uint8_t ivec[16]);
+#else
+static char bsaes_capable(void) {
+ return 0;
+}
+
+/* On other platforms, bsaes_capable() will always return false and so the
+ * following will never be called. */
+void bsaes_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t length,
+ const AES_KEY *key, uint8_t ivec[16], int enc) {
+ abort();
+}
+
+void bsaes_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out, size_t len,
+ const AES_KEY *key, const uint8_t ivec[16]) {
+ abort();
+}
+#endif
+
+#if defined(VPAES)
+/* On platforms where VPAES gets defined (just above), then these functions are
+ * provided by asm. */
+int vpaes_set_encrypt_key(const uint8_t *userKey, int bits, AES_KEY *key);
+int vpaes_set_decrypt_key(const uint8_t *userKey, int bits, AES_KEY *key);
+
+void vpaes_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key);
+void vpaes_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key);
+
+void vpaes_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t length,
+ const AES_KEY *key, uint8_t *ivec, int enc);
+#else
+static char vpaes_capable(void) {
+ return 0;
+}
+
+/* On other platforms, vpaes_capable() will always return false and so the
+ * following will never be called. */
+int vpaes_set_encrypt_key(const uint8_t *userKey, int bits, AES_KEY *key) {
+ abort();
+}
+int vpaes_set_decrypt_key(const uint8_t *userKey, int bits, AES_KEY *key) {
+ abort();
+}
+void vpaes_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) {
+ abort();
+}
+void vpaes_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) {
+ abort();
+}
+void vpaes_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t length,
+ const AES_KEY *key, uint8_t *ivec, int enc) {
+ abort();
+}
+#endif
+
+#if !defined(HWAES)
+/* If HWAES isn't defined then we provide dummy functions for each of the hwaes
+ * functions. */
+int hwaes_capable(void) {
+ return 0;
+}
+
+int aes_v8_set_encrypt_key(const uint8_t *user_key, int bits,
+ AES_KEY *key) {
+ abort();
+}
+
+int aes_v8_set_decrypt_key(const uint8_t *user_key, int bits, AES_KEY *key) {
+ abort();
+}
+
+void aes_v8_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) {
+ abort();
+}
+
+void aes_v8_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) {
+ abort();
+}
+
+void aes_v8_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t length,
+ const AES_KEY *key, uint8_t *ivec, int enc) {
+ abort();
+}
+
+void aes_v8_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out, size_t len,
+ const AES_KEY *key, const uint8_t ivec[16]) {
+ abort();
+}
+#endif
+
+#if !defined(OPENSSL_NO_ASM) && \
+ (defined(OPENSSL_X86_64) || defined(OPENSSL_X86))
+int aesni_set_encrypt_key(const uint8_t *userKey, int bits, AES_KEY *key);
+int aesni_set_decrypt_key(const uint8_t *userKey, int bits, AES_KEY *key);
+
+void aesni_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key);
+void aesni_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key);
+
+void aesni_ecb_encrypt(const uint8_t *in, uint8_t *out, size_t length,
+ const AES_KEY *key, int enc);
+void aesni_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t length,
+ const AES_KEY *key, uint8_t *ivec, int enc);
+
+void aesni_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out, size_t blocks,
+ const void *key, const uint8_t *ivec);
+
+#if defined(OPENSSL_X86_64)
+size_t aesni_gcm_encrypt(const uint8_t *in, uint8_t *out, size_t len,
+ const void *key, uint8_t ivec[16], uint64_t *Xi);
+#define AES_gcm_encrypt aesni_gcm_encrypt
+size_t aesni_gcm_decrypt(const uint8_t *in, uint8_t *out, size_t len,
+ const void *key, uint8_t ivec[16], uint64_t *Xi);
+#define AES_gcm_decrypt aesni_gcm_decrypt
+void gcm_ghash_avx(uint64_t Xi[2], const u128 Htable[16], const uint8_t *in,
+ size_t len);
+#define AES_GCM_ASM(gctx) \
+ (gctx->ctr == aesni_ctr32_encrypt_blocks && gctx->gcm.ghash == gcm_ghash_avx)
+#endif /* OPENSSL_X86_64 */
+
+#else
+
+/* On other platforms, aesni_capable() will always return false and so the
+ * following will never be called. */
+void aesni_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) {
+ abort();
+}
+int aesni_set_encrypt_key(const uint8_t *userKey, int bits, AES_KEY *key) {
+ abort();
+}
+void aesni_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out, size_t blocks,
+ const void *key, const uint8_t *ivec) {
+ abort();
+}
+
+#endif
+
+static int aes_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key,
+ const uint8_t *iv, int enc) {
+ int ret, mode;
+ EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
+
+ mode = ctx->cipher->flags & EVP_CIPH_MODE_MASK;
+ if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE) && !enc) {
+ if (hwaes_capable()) {
+ ret = aes_v8_set_decrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
+ dat->block = (block128_f)aes_v8_decrypt;
+ dat->stream.cbc = NULL;
+ if (mode == EVP_CIPH_CBC_MODE) {
+ dat->stream.cbc = (cbc128_f)aes_v8_cbc_encrypt;
+ }
+ } else if (bsaes_capable() && mode == EVP_CIPH_CBC_MODE) {
+ ret = AES_set_decrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
+ dat->block = (block128_f)AES_decrypt;
+ dat->stream.cbc = (cbc128_f)bsaes_cbc_encrypt;
+ } else if (vpaes_capable()) {
+ ret = vpaes_set_decrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
+ dat->block = (block128_f)vpaes_decrypt;
+ dat->stream.cbc =
+ mode == EVP_CIPH_CBC_MODE ? (cbc128_f)vpaes_cbc_encrypt : NULL;
+ } else {
+ ret = AES_set_decrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
+ dat->block = (block128_f)AES_decrypt;
+ dat->stream.cbc =
+ mode == EVP_CIPH_CBC_MODE ? (cbc128_f)AES_cbc_encrypt : NULL;
+ }
+ } else if (hwaes_capable()) {
+ ret = aes_v8_set_encrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
+ dat->block = (block128_f)aes_v8_encrypt;
+ dat->stream.cbc = NULL;
+ if (mode == EVP_CIPH_CBC_MODE) {
+ dat->stream.cbc = (cbc128_f)aes_v8_cbc_encrypt;
+ } else if (mode == EVP_CIPH_CTR_MODE) {
+ dat->stream.ctr = (ctr128_f)aes_v8_ctr32_encrypt_blocks;
+ }
+ } else if (bsaes_capable() && mode == EVP_CIPH_CTR_MODE) {
+ ret = AES_set_encrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
+ dat->block = (block128_f)AES_encrypt;
+ dat->stream.ctr = (ctr128_f)bsaes_ctr32_encrypt_blocks;
+ } else if (vpaes_capable()) {
+ ret = vpaes_set_encrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
+ dat->block = (block128_f)vpaes_encrypt;
+ dat->stream.cbc =
+ mode == EVP_CIPH_CBC_MODE ? (cbc128_f)vpaes_cbc_encrypt : NULL;
+ } else {
+ ret = AES_set_encrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
+ dat->block = (block128_f)AES_encrypt;
+ dat->stream.cbc =
+ mode == EVP_CIPH_CBC_MODE ? (cbc128_f)AES_cbc_encrypt : NULL;
+ }
+
+ if (ret < 0) {
+ OPENSSL_PUT_ERROR(CIPHER, aes_init_key, CIPHER_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_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;
+}
+
+static ctr128_f aes_gcm_set_key(AES_KEY *aes_key, GCM128_CONTEXT *gcm_ctx,
+ const uint8_t *key, size_t key_len) {
+ if (hwaes_capable()) {
+ aes_v8_set_encrypt_key(key, key_len * 8, aes_key);
+ CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)aes_v8_encrypt);
+ return (ctr128_f)aes_v8_ctr32_encrypt_blocks;
+ }
+
+ 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;
+ }
+
+ 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;
+ }
+
+ AES_set_encrypt_key(key, key_len * 8, aes_key);
+ CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)AES_encrypt);
+ return NULL;
+}
+
+static int aes_gcm_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key,
+ const uint8_t *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.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;
+}
+
+static int aes_gcm_cleanup(EVP_CIPHER_CTX *c) {
+ EVP_AES_GCM_CTX *gctx = c->cipher_data;
+ OPENSSL_cleanse(&gctx->gcm, sizeof(gctx->gcm));
+ if (gctx->iv != c->iv) {
+ OPENSSL_free(gctx->iv);
+ }
+ return 1;
+}
+
+/* increment counter (64-bit int) by 1 */
+static void ctr64_inc(uint8_t *counter) {
+ int n = 8;
+ uint8_t 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;
+ gctx->ivlen = c->cipher->iv_len;
+ gctx->iv = c->iv;
+ gctx->taglen = -1;
+ gctx->iv_gen = 0;
+ return 1;
+
+ case EVP_CTRL_GCM_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) {
+ OPENSSL_free(gctx->iv);
+ }
+ gctx->iv = OPENSSL_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 && !RAND_bytes(gctx->iv + arg, gctx->ivlen - arg)) {
+ return 0;
+ }
+ 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_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 {
+ gctx_out->iv = OPENSSL_malloc(gctx->ivlen);
+ if (!gctx_out->iv) {
+ return 0;
+ }
+ memcpy(gctx_out->iv, gctx->iv, gctx->ivlen);
+ }
+ return 1;
+ }
+
+ default:
+ return -1;
+ }
+}
+
+static int aes_gcm_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *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->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) {
+ size_t bulk = 0;
+#if defined(AES_GCM_ASM)
+ if (len >= 32 && AES_GCM_ASM(gctx)) {
+ size_t res = (16 - gctx->gcm.mres) % 16;
+
+ if (!CRYPTO_gcm128_encrypt(&gctx->gcm, in, out, res)) {
+ return -1;
+ }
+
+ bulk = AES_gcm_encrypt(in + res, out + res, len - res, gctx->gcm.key,
+ gctx->gcm.Yi.c, gctx->gcm.Xi.u);
+ gctx->gcm.len.u[1] += bulk;
+ bulk += res;
+ }
+#endif
+ if (!CRYPTO_gcm128_encrypt_ctr32(&gctx->gcm, in + bulk, out + bulk,
+ len - bulk, gctx->ctr)) {
+ return -1;
+ }
+ } else {
+ size_t bulk = 0;
+ if (!CRYPTO_gcm128_encrypt(&gctx->gcm, in + bulk, out + bulk,
+ len - bulk)) {
+ return -1;
+ }
+ }
+ } else {
+ if (gctx->ctr) {
+ size_t bulk = 0;
+#if defined(AES_GCM_ASM)
+ if (len >= 16 && AES_GCM_ASM(gctx)) {
+ size_t res = (16 - gctx->gcm.mres) % 16;
+
+ if (!CRYPTO_gcm128_decrypt(&gctx->gcm, in, out, res)) {
+ return -1;
+ }
+
+ bulk = AES_gcm_decrypt(in + res, out + res, len - res, gctx->gcm.key,
+ gctx->gcm.Yi.c, gctx->gcm.Xi.u);
+ gctx->gcm.len.u[1] += bulk;
+ bulk += res;
+ }
+#endif
+ if (!CRYPTO_gcm128_decrypt_ctr32(&gctx->gcm, in + bulk, out + bulk,
+ len - bulk, gctx->ctr)) {
+ return -1;
+ }
+ } else {
+ size_t bulk = 0;
+ if (!CRYPTO_gcm128_decrypt(&gctx->gcm, in + bulk, out + bulk,
+ len - bulk)) {
+ return -1;
+ }
+ }
+ }
+ return len;
+ } else {
+ if (!ctx->encrypt) {
+ if (gctx->taglen < 0 ||
+ !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;
+ }
+}
+
+static const EVP_CIPHER aes_128_cbc = {
+ NID_aes_128_cbc, 16 /* block_size */, 16 /* key_size */,
+ 16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_CBC_MODE,
+ NULL /* app_data */, aes_init_key, aes_cbc_cipher,
+ NULL /* cleanup */, NULL /* ctrl */};
+
+static const EVP_CIPHER aes_128_ctr = {
+ NID_aes_128_ctr, 1 /* block_size */, 16 /* key_size */,
+ 16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_CTR_MODE,
+ NULL /* app_data */, aes_init_key, aes_ctr_cipher,
+ NULL /* cleanup */, NULL /* ctrl */};
+
+static const EVP_CIPHER aes_128_ecb = {
+ NID_aes_128_ecb, 16 /* block_size */, 16 /* key_size */,
+ 0 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_ECB_MODE,
+ NULL /* app_data */, aes_init_key, aes_ecb_cipher,
+ NULL /* cleanup */, NULL /* ctrl */};
+
+static const EVP_CIPHER aes_128_gcm = {
+ NID_aes_128_gcm, 1 /* block_size */, 16 /* key_size */, 12 /* iv_len */,
+ sizeof(EVP_AES_GCM_CTX),
+ EVP_CIPH_GCM_MODE | EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER |
+ EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT |
+ EVP_CIPH_FLAG_AEAD_CIPHER,
+ NULL /* app_data */, aes_gcm_init_key, aes_gcm_cipher, aes_gcm_cleanup,
+ aes_gcm_ctrl};
+
+
+static const EVP_CIPHER aes_256_cbc = {
+ NID_aes_128_cbc, 16 /* block_size */, 32 /* key_size */,
+ 16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_CBC_MODE,
+ NULL /* app_data */, aes_init_key, aes_cbc_cipher,
+ NULL /* cleanup */, NULL /* ctrl */};
+
+static const EVP_CIPHER aes_256_ctr = {
+ NID_aes_128_ctr, 1 /* block_size */, 32 /* key_size */,
+ 16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_CTR_MODE,
+ NULL /* app_data */, aes_init_key, aes_ctr_cipher,
+ NULL /* cleanup */, NULL /* ctrl */};
+
+static const EVP_CIPHER aes_256_ecb = {
+ NID_aes_128_ecb, 16 /* block_size */, 32 /* key_size */,
+ 0 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_ECB_MODE,
+ NULL /* app_data */, aes_init_key, aes_ecb_cipher,
+ NULL /* cleanup */, NULL /* ctrl */};
+
+static const EVP_CIPHER aes_256_gcm = {
+ NID_aes_128_gcm, 1 /* block_size */, 32 /* key_size */, 12 /* iv_len */,
+ sizeof(EVP_AES_GCM_CTX),
+ EVP_CIPH_GCM_MODE | EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER |
+ EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT |
+ EVP_CIPH_FLAG_AEAD_CIPHER,
+ NULL /* app_data */, aes_gcm_init_key, aes_gcm_cipher, aes_gcm_cleanup,
+ aes_gcm_ctrl};
+
+#if !defined(OPENSSL_NO_ASM) && \
+ (defined(OPENSSL_X86_64) || defined(OPENSSL_X86))
+
+/* AES-NI section. */
+
+static char aesni_capable(void) {
+ return (OPENSSL_ia32cap_P[1] & (1 << (57 - 32))) != 0;
+}
+
+static int aesni_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key,
+ const uint8_t *iv, int enc) {
+ int ret, mode;
+ EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
+
+ mode = ctx->cipher->flags & EVP_CIPH_MODE_MASK;
+ 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) {
+ OPENSSL_PUT_ERROR(CIPHER, aesni_init_key, CIPHER_R_AES_KEY_SETUP_FAILED);
+ return 0;
+ }
+
+ return 1;
+}
+
+static int aesni_cbc_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out,
+ const uint8_t *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, uint8_t *out,
+ const uint8_t *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 uint8_t *key,
+ const uint8_t *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.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 const EVP_CIPHER aesni_128_cbc = {
+ NID_aes_128_cbc, 16 /* block_size */, 16 /* key_size */,
+ 16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_CBC_MODE,
+ NULL /* app_data */, aesni_init_key, aesni_cbc_cipher,
+ NULL /* cleanup */, NULL /* ctrl */};
+
+static const EVP_CIPHER aesni_128_ctr = {
+ NID_aes_128_ctr, 1 /* block_size */, 16 /* key_size */,
+ 16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_CTR_MODE,
+ NULL /* app_data */, aesni_init_key, aes_ctr_cipher,
+ NULL /* cleanup */, NULL /* ctrl */};
+
+static const EVP_CIPHER aesni_128_ecb = {
+ NID_aes_128_ecb, 16 /* block_size */, 16 /* key_size */,
+ 0 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_ECB_MODE,
+ NULL /* app_data */, aesni_init_key, aesni_ecb_cipher,
+ NULL /* cleanup */, NULL /* ctrl */};
+
+static const EVP_CIPHER aesni_128_gcm = {
+ NID_aes_128_gcm, 1 /* block_size */, 16 /* key_size */, 12 /* iv_len */,
+ sizeof(EVP_AES_GCM_CTX),
+ EVP_CIPH_GCM_MODE | EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER |
+ EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT |
+ EVP_CIPH_FLAG_AEAD_CIPHER,
+ NULL /* app_data */, aesni_gcm_init_key, aes_gcm_cipher, aes_gcm_cleanup,
+ aes_gcm_ctrl};
+
+
+static const EVP_CIPHER aesni_256_cbc = {
+ NID_aes_128_cbc, 16 /* block_size */, 32 /* key_size */,
+ 16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_CBC_MODE,
+ NULL /* app_data */, aesni_init_key, aesni_cbc_cipher,
+ NULL /* cleanup */, NULL /* ctrl */};
+
+static const EVP_CIPHER aesni_256_ctr = {
+ NID_aes_128_ctr, 1 /* block_size */, 32 /* key_size */,
+ 16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_CTR_MODE,
+ NULL /* app_data */, aesni_init_key, aes_ctr_cipher,
+ NULL /* cleanup */, NULL /* ctrl */};
+
+static const EVP_CIPHER aesni_256_ecb = {
+ NID_aes_128_ecb, 16 /* block_size */, 32 /* key_size */,
+ 0 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_ECB_MODE,
+ NULL /* app_data */, aesni_init_key, aesni_ecb_cipher,
+ NULL /* cleanup */, NULL /* ctrl */};
+
+static const EVP_CIPHER aesni_256_gcm = {
+ NID_aes_256_gcm, 1 /* block_size */, 32 /* key_size */, 12 /* iv_len */,
+ sizeof(EVP_AES_GCM_CTX),
+ EVP_CIPH_GCM_MODE | EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER |
+ EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT | EVP_CIPH_CUSTOM_COPY |
+ EVP_CIPH_FLAG_AEAD_CIPHER,
+ NULL /* app_data */, aesni_gcm_init_key, aes_gcm_cipher, aes_gcm_cleanup,
+ aes_gcm_ctrl};
+
+#define EVP_CIPHER_FUNCTION(keybits, mode) \
+ const EVP_CIPHER *EVP_aes_##keybits##_##mode(void) { \
+ if (aesni_capable()) { \
+ return &aesni_##keybits##_##mode; \
+ } else { \
+ return &aes_##keybits##_##mode; \
+ } \
+ }
+
+#else /* ^^^ OPENSSL_X86_64 || OPENSSL_X86 */
+
+static char aesni_capable(void) {
+ return 0;
+}
+
+#define EVP_CIPHER_FUNCTION(keybits, mode) \
+ const EVP_CIPHER *EVP_aes_##keybits##_##mode(void) { \
+ return &aes_##keybits##_##mode; \
+ }
+
+#endif
+
+EVP_CIPHER_FUNCTION(128, cbc)
+EVP_CIPHER_FUNCTION(128, ctr)
+EVP_CIPHER_FUNCTION(128, ecb)
+EVP_CIPHER_FUNCTION(128, gcm)
+
+EVP_CIPHER_FUNCTION(256, cbc)
+EVP_CIPHER_FUNCTION(256, ctr)
+EVP_CIPHER_FUNCTION(256, ecb)
+EVP_CIPHER_FUNCTION(256, gcm)
+
+
+#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;
+ uint8_t tag_len;
+};
+
+static int aead_aes_gcm_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
+ size_t key_len, size_t tag_len) {
+ struct aead_aes_gcm_ctx *gcm_ctx;
+ const size_t key_bits = key_len * 8;
+
+ if (key_bits != 128 && key_bits != 256) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_aes_gcm_init, CIPHER_R_BAD_KEY_LENGTH);
+ return 0; /* EVP_AEAD_CTX_init should catch this. */
+ }
+
+ 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) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_aes_gcm_init, CIPHER_R_TAG_TOO_LARGE);
+ return 0;
+ }
+
+ gcm_ctx = OPENSSL_malloc(sizeof(struct aead_aes_gcm_ctx));
+ if (gcm_ctx == NULL) {
+ return 0;
+ }
+
+ if (aesni_capable()) {
+ aesni_set_encrypt_key(key, key_len * 8, &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 {
+ 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;
+ OPENSSL_cleanse(gcm_ctx, sizeof(struct aead_aes_gcm_ctx));
+ OPENSSL_free(gcm_ctx);
+}
+
+static int aead_aes_gcm_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
+ size_t *out_len, size_t max_out_len,
+ const uint8_t *nonce, size_t nonce_len,
+ const uint8_t *in, size_t in_len,
+ const uint8_t *ad, size_t ad_len) {
+ size_t bulk = 0;
+ const struct aead_aes_gcm_ctx *gcm_ctx = ctx->aead_state;
+ GCM128_CONTEXT gcm;
+
+ if (in_len + gcm_ctx->tag_len < in_len) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_aes_gcm_seal, CIPHER_R_TOO_LARGE);
+ return 0;
+ }
+
+ if (max_out_len < in_len + gcm_ctx->tag_len) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_aes_gcm_seal, CIPHER_R_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ memcpy(&gcm, &gcm_ctx->gcm, sizeof(gcm));
+ 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, uint8_t *out,
+ size_t *out_len, size_t max_out_len,
+ const uint8_t *nonce, size_t nonce_len,
+ const uint8_t *in, size_t in_len,
+ const uint8_t *ad, size_t ad_len) {
+ size_t bulk = 0;
+ const struct aead_aes_gcm_ctx *gcm_ctx = ctx->aead_state;
+ uint8_t tag[EVP_AEAD_AES_GCM_TAG_LEN];
+ size_t plaintext_len;
+ GCM128_CONTEXT gcm;
+
+ if (in_len < gcm_ctx->tag_len) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_aes_gcm_open, CIPHER_R_BAD_DECRYPT);
+ return 0;
+ }
+
+ plaintext_len = in_len - gcm_ctx->tag_len;
+
+ if (max_out_len < plaintext_len) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_aes_gcm_open, CIPHER_R_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ memcpy(&gcm, &gcm_ctx->gcm, sizeof(gcm));
+ 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 (CRYPTO_memcmp(tag, in + plaintext_len, gcm_ctx->tag_len) != 0) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_aes_gcm_open, CIPHER_R_BAD_DECRYPT);
+ return 0;
+ }
+
+ *out_len = plaintext_len;
+ return 1;
+}
+
+static const EVP_AEAD aead_aes_128_gcm = {
+ 16, /* key len */
+ 12, /* nonce len */
+ EVP_AEAD_AES_GCM_TAG_LEN, /* overhead */
+ EVP_AEAD_AES_GCM_TAG_LEN, /* max tag length */
+ aead_aes_gcm_init, aead_aes_gcm_cleanup,
+ aead_aes_gcm_seal, aead_aes_gcm_open,
+};
+
+static const EVP_AEAD aead_aes_256_gcm = {
+ 32, /* key len */
+ 12, /* nonce len */
+ EVP_AEAD_AES_GCM_TAG_LEN, /* overhead */
+ EVP_AEAD_AES_GCM_TAG_LEN, /* max tag length */
+ aead_aes_gcm_init, aead_aes_gcm_cleanup,
+ aead_aes_gcm_seal, 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; }
+
+
+/* AES Key Wrap is specified in
+ * http://csrc.nist.gov/groups/ST/toolkit/documents/kms/key-wrap.pdf
+ * or https://tools.ietf.org/html/rfc3394 */
+
+struct aead_aes_key_wrap_ctx {
+ uint8_t key[32];
+ unsigned key_bits;
+};
+
+static int aead_aes_key_wrap_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
+ size_t key_len, size_t tag_len) {
+ struct aead_aes_key_wrap_ctx *kw_ctx;
+ const size_t key_bits = key_len * 8;
+
+ if (key_bits != 128 && key_bits != 256) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_aes_key_wrap_init, CIPHER_R_BAD_KEY_LENGTH);
+ return 0; /* EVP_AEAD_CTX_init should catch this. */
+ }
+
+ if (tag_len == EVP_AEAD_DEFAULT_TAG_LENGTH) {
+ tag_len = 8;
+ }
+
+ if (tag_len != 8) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_aes_key_wrap_init,
+ CIPHER_R_UNSUPPORTED_TAG_SIZE);
+ return 0;
+ }
+
+ kw_ctx = OPENSSL_malloc(sizeof(struct aead_aes_key_wrap_ctx));
+ if (kw_ctx == NULL) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_aes_key_wrap_init, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ memcpy(kw_ctx->key, key, key_len);
+ kw_ctx->key_bits = key_bits;
+
+ ctx->aead_state = kw_ctx;
+ return 1;
+}
+
+static void aead_aes_key_wrap_cleanup(EVP_AEAD_CTX *ctx) {
+ struct aead_aes_key_wrap_ctx *kw_ctx = ctx->aead_state;
+ OPENSSL_cleanse(kw_ctx, sizeof(struct aead_aes_key_wrap_ctx));
+ OPENSSL_free(kw_ctx);
+}
+
+/* kDefaultAESKeyWrapNonce is the default nonce value given in 2.2.3.1. */
+static const uint8_t kDefaultAESKeyWrapNonce[8] = {0xa6, 0xa6, 0xa6, 0xa6,
+ 0xa6, 0xa6, 0xa6, 0xa6};
+
+
+static int aead_aes_key_wrap_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
+ size_t *out_len, size_t max_out_len,
+ const uint8_t *nonce, size_t nonce_len,
+ const uint8_t *in, size_t in_len,
+ const uint8_t *ad, size_t ad_len) {
+ const struct aead_aes_key_wrap_ctx *kw_ctx = ctx->aead_state;
+ union {
+ double align;
+ AES_KEY ks;
+ } ks;
+ /* Variables in this function match up with the variables in the second half
+ * of section 2.2.1. */
+ unsigned i, j, n;
+ uint8_t A[AES_BLOCK_SIZE];
+
+ if (ad_len != 0) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_aes_key_wrap_seal,
+ CIPHER_R_UNSUPPORTED_AD_SIZE);
+ return 0;
+ }
+
+ if (nonce_len == 0) {
+ nonce = kDefaultAESKeyWrapNonce;
+ nonce_len = sizeof(kDefaultAESKeyWrapNonce);
+ }
+
+ if (nonce_len != 8) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_aes_key_wrap_seal,
+ CIPHER_R_UNSUPPORTED_NONCE_SIZE);
+ return 0;
+ }
+
+ if (in_len % 8 != 0) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_aes_key_wrap_seal,
+ CIPHER_R_UNSUPPORTED_INPUT_SIZE);
+ return 0;
+ }
+
+ /* The code below only handles a 32-bit |t| thus 6*|n| must be less than
+ * 2^32, where |n| is |in_len| / 8. So in_len < 4/3 * 2^32 and we
+ * conservatively cap it to 2^32-16 to stop 32-bit platforms complaining that
+ * a comparison is always true. */
+ if (in_len > 0xfffffff0) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_aes_key_wrap_seal, CIPHER_R_TOO_LARGE);
+ return 0;
+ }
+
+ n = in_len / 8;
+
+ if (n < 2) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_aes_key_wrap_seal,
+ CIPHER_R_UNSUPPORTED_INPUT_SIZE);
+ return 0;
+ }
+
+ if (in_len + 8 < in_len) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_aes_key_wrap_seal, CIPHER_R_TOO_LARGE);
+ return 0;
+ }
+
+ if (max_out_len < in_len + 8) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_aes_key_wrap_seal,
+ CIPHER_R_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ if (AES_set_encrypt_key(kw_ctx->key, kw_ctx->key_bits, &ks.ks) < 0) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_aes_key_wrap_seal,
+ CIPHER_R_AES_KEY_SETUP_FAILED);
+ return 0;
+ }
+
+ memmove(out + 8, in, in_len);
+ memcpy(A, nonce, 8);
+
+ for (j = 0; j < 6; j++) {
+ for (i = 1; i <= n; i++) {
+ uint32_t t;
+
+ memcpy(A + 8, out + 8 * i, 8);
+ AES_encrypt(A, A, &ks.ks);
+ t = n * j + i;
+ A[7] ^= t & 0xff;
+ A[6] ^= (t >> 8) & 0xff;
+ A[5] ^= (t >> 16) & 0xff;
+ A[4] ^= (t >> 24) & 0xff;
+ memcpy(out + 8 * i, A + 8, 8);
+ }
+ }
+
+ memcpy(out, A, 8);
+ *out_len = in_len + 8;
+ return 1;
+}
+
+static int aead_aes_key_wrap_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
+ size_t *out_len, size_t max_out_len,
+ const uint8_t *nonce, size_t nonce_len,
+ const uint8_t *in, size_t in_len,
+ const uint8_t *ad, size_t ad_len) {
+ const struct aead_aes_key_wrap_ctx *kw_ctx = ctx->aead_state;
+ union {
+ double align;
+ AES_KEY ks;
+ } ks;
+ /* Variables in this function match up with the variables in the second half
+ * of section 2.2.1. */
+ unsigned i, j, n;
+ uint8_t A[AES_BLOCK_SIZE];
+
+ if (ad_len != 0) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_aes_key_wrap_open,
+ CIPHER_R_UNSUPPORTED_AD_SIZE);
+ return 0;
+ }
+
+ if (nonce_len == 0) {
+ nonce = kDefaultAESKeyWrapNonce;
+ nonce_len = sizeof(kDefaultAESKeyWrapNonce);
+ }
+
+ if (nonce_len != 8) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_aes_key_wrap_open,
+ CIPHER_R_UNSUPPORTED_NONCE_SIZE);
+ return 0;
+ }
+
+ if (in_len % 8 != 0) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_aes_key_wrap_open,
+ CIPHER_R_UNSUPPORTED_INPUT_SIZE);
+ return 0;
+ }
+
+ /* The code below only handles a 32-bit |t| thus 6*|n| must be less than
+ * 2^32, where |n| is |in_len| / 8. So in_len < 4/3 * 2^32 and we
+ * conservatively cap it to 2^32-8 to stop 32-bit platforms complaining that
+ * a comparison is always true. */
+ if (in_len > 0xfffffff8) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_aes_key_wrap_open, CIPHER_R_TOO_LARGE);
+ return 0;
+ }
+
+ if (in_len < 24) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_aes_gcm_open, CIPHER_R_BAD_DECRYPT);
+ return 0;
+ }
+
+ n = (in_len / 8) - 1;
+
+ if (max_out_len < in_len - 8) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_aes_key_wrap_open,
+ CIPHER_R_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ if (AES_set_decrypt_key(kw_ctx->key, kw_ctx->key_bits, &ks.ks) < 0) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_aes_key_wrap_open,
+ CIPHER_R_AES_KEY_SETUP_FAILED);
+ return 0;
+ }
+
+ memcpy(A, in, 8);
+ memmove(out, in + 8, in_len - 8);
+
+ for (j = 5; j < 6; j--) {
+ for (i = n; i > 0; i--) {
+ uint32_t t;
+
+ t = n * j + i;
+ A[7] ^= t & 0xff;
+ A[6] ^= (t >> 8) & 0xff;
+ A[5] ^= (t >> 16) & 0xff;
+ A[4] ^= (t >> 24) & 0xff;
+ memcpy(A + 8, out + 8 * (i - 1), 8);
+ AES_decrypt(A, A, &ks.ks);
+ memcpy(out + 8 * (i - 1), A + 8, 8);
+ }
+ }
+
+ if (CRYPTO_memcmp(A, nonce, 8) != 0) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_aes_gcm_open, CIPHER_R_BAD_DECRYPT);
+ return 0;
+ }
+
+ *out_len = in_len - 8;
+ return 1;
+}
+
+static const EVP_AEAD aead_aes_128_key_wrap = {
+ 16, /* key len */
+ 8, /* nonce len */
+ 8, /* overhead */
+ 8, /* max tag length */
+ aead_aes_key_wrap_init, aead_aes_key_wrap_cleanup,
+ aead_aes_key_wrap_seal, aead_aes_key_wrap_open,
+};
+
+static const EVP_AEAD aead_aes_256_key_wrap = {
+ 32, /* key len */
+ 8, /* nonce len */
+ 8, /* overhead */
+ 8, /* max tag length */
+ aead_aes_key_wrap_init, aead_aes_key_wrap_cleanup,
+ aead_aes_key_wrap_seal, aead_aes_key_wrap_open,
+};
+
+const EVP_AEAD *EVP_aead_aes_128_key_wrap(void) { return &aead_aes_128_key_wrap; }
+
+const EVP_AEAD *EVP_aead_aes_256_key_wrap(void) { return &aead_aes_256_key_wrap; }
+
+int EVP_has_aes_hardware(void) {
+#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64)
+ return aesni_capable() && crypto_gcm_clmul_enabled();
+#elif defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)
+ return hwaes_capable() && (OPENSSL_armcap_P & ARMV8_PMULL);
+#else
+ return 0;
+#endif
+}
diff --git a/src/crypto/cipher/e_chacha20poly1305.c b/src/crypto/cipher/e_chacha20poly1305.c
new file mode 100644
index 0000000..1cdcbca
--- /dev/null
+++ b/src/crypto/cipher/e_chacha20poly1305.c
@@ -0,0 +1,218 @@
+/* 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 <openssl/aead.h>
+
+#include <string.h>
+
+#include <openssl/chacha.h>
+#include <openssl/cipher.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/poly1305.h>
+
+#include "internal.h"
+
+
+#define POLY1305_TAG_LEN 16
+#define CHACHA20_NONCE_LEN 8
+
+struct aead_chacha20_poly1305_ctx {
+ unsigned char key[32];
+ unsigned char tag_len;
+};
+
+static int aead_chacha20_poly1305_init(EVP_AEAD_CTX *ctx, const uint8_t *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) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_chacha20_poly1305_init, CIPHER_R_TOO_LARGE);
+ return 0;
+ }
+
+ if (key_len != sizeof(c20_ctx->key)) {
+ return 0; /* internal error - EVP_AEAD_CTX_init should catch this. */
+ }
+
+ c20_ctx = OPENSSL_malloc(sizeof(struct aead_chacha20_poly1305_ctx));
+ if (c20_ctx == NULL) {
+ return 0;
+ }
+
+ memcpy(c20_ctx->key, 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;
+ OPENSSL_cleanse(c20_ctx->key, sizeof(c20_ctx->key));
+ OPENSSL_free(c20_ctx);
+}
+
+static void poly1305_update_with_length(poly1305_state *poly1305,
+ const uint8_t *data, size_t data_len) {
+ size_t j = data_len;
+ uint8_t length_bytes[8];
+ unsigned i;
+
+ for (i = 0; i < sizeof(length_bytes); i++) {
+ length_bytes[i] = j;
+ j >>= 8;
+ }
+
+ CRYPTO_poly1305_update(poly1305, data, data_len);
+ CRYPTO_poly1305_update(poly1305, length_bytes, sizeof(length_bytes));
+}
+
+#if defined(__arm__)
+#define ALIGNED __attribute__((aligned(16)))
+#else
+#define ALIGNED
+#endif
+
+static int aead_chacha20_poly1305_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
+ size_t *out_len, size_t max_out_len,
+ const uint8_t *nonce, size_t nonce_len,
+ const uint8_t *in, size_t in_len,
+ const uint8_t *ad, size_t ad_len) {
+ const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state;
+ uint8_t poly1305_key[32] ALIGNED;
+ poly1305_state poly1305;
+ const uint64_t in_len_64 = in_len;
+
+ /* The underlying ChaCha implementation may not overflow the block
+ * counter into the second counter word. Therefore we disallow
+ * individual operations that work on more than 256GB at a time.
+ * |in_len_64| is needed because, on 32-bit platforms, size_t is only
+ * 32-bits and this produces a warning because it's always false.
+ * Casting to uint64_t inside the conditional is not sufficient to stop
+ * the warning. */
+ if (in_len_64 >= (1ull << 32) * 64 - 64) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_chacha20_poly1305_seal, CIPHER_R_TOO_LARGE);
+ return 0;
+ }
+
+ if (in_len + c20_ctx->tag_len < in_len) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_chacha20_poly1305_seal, CIPHER_R_TOO_LARGE);
+ return 0;
+ }
+
+ if (max_out_len < in_len + c20_ctx->tag_len) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_chacha20_poly1305_seal,
+ CIPHER_R_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ if (nonce_len != CHACHA20_NONCE_LEN) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_chacha20_poly1305_seal, CIPHER_R_IV_TOO_LARGE);
+ return 0;
+ }
+
+ memset(poly1305_key, 0, sizeof(poly1305_key));
+ CRYPTO_chacha_20(poly1305_key, poly1305_key, sizeof(poly1305_key),
+ c20_ctx->key, nonce, 0);
+
+ CRYPTO_poly1305_init(&poly1305, poly1305_key);
+ poly1305_update_with_length(&poly1305, ad, ad_len);
+ CRYPTO_chacha_20(out, in, in_len, c20_ctx->key, nonce, 1);
+ poly1305_update_with_length(&poly1305, out, in_len);
+
+ uint8_t tag[POLY1305_TAG_LEN] ALIGNED;
+ CRYPTO_poly1305_finish(&poly1305, tag);
+ memcpy(out + in_len, tag, c20_ctx->tag_len);
+ *out_len = in_len + c20_ctx->tag_len;
+ return 1;
+}
+
+static int aead_chacha20_poly1305_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
+ size_t *out_len, size_t max_out_len,
+ const uint8_t *nonce, size_t nonce_len,
+ const uint8_t *in, size_t in_len,
+ const uint8_t *ad, size_t ad_len) {
+ const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state;
+ uint8_t mac[POLY1305_TAG_LEN];
+ uint8_t poly1305_key[32] ALIGNED;
+ size_t plaintext_len;
+ poly1305_state poly1305;
+ const uint64_t in_len_64 = in_len;
+
+ if (in_len < c20_ctx->tag_len) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_chacha20_poly1305_open, CIPHER_R_BAD_DECRYPT);
+ return 0;
+ }
+
+ /* The underlying ChaCha implementation may not overflow the block
+ * counter into the second counter word. Therefore we disallow
+ * individual operations that work on more than 256GB at a time.
+ * |in_len_64| is needed because, on 32-bit platforms, size_t is only
+ * 32-bits and this produces a warning because it's always false.
+ * Casting to uint64_t inside the conditional is not sufficient to stop
+ * the warning. */
+ if (in_len_64 >= (1ull << 32) * 64 - 64) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_chacha20_poly1305_open, CIPHER_R_TOO_LARGE);
+ return 0;
+ }
+
+ if (nonce_len != CHACHA20_NONCE_LEN) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_chacha20_poly1305_open, CIPHER_R_IV_TOO_LARGE);
+ return 0;
+ }
+
+ plaintext_len = in_len - c20_ctx->tag_len;
+
+ if (max_out_len < plaintext_len) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_chacha20_poly1305_open,
+ CIPHER_R_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ memset(poly1305_key, 0, sizeof(poly1305_key));
+ CRYPTO_chacha_20(poly1305_key, poly1305_key, sizeof(poly1305_key),
+ c20_ctx->key, nonce, 0);
+
+ CRYPTO_poly1305_init(&poly1305, poly1305_key);
+ poly1305_update_with_length(&poly1305, ad, ad_len);
+ poly1305_update_with_length(&poly1305, in, plaintext_len);
+ CRYPTO_poly1305_finish(&poly1305, mac);
+
+ if (CRYPTO_memcmp(mac, in + plaintext_len, c20_ctx->tag_len) != 0) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_chacha20_poly1305_open, CIPHER_R_BAD_DECRYPT);
+ return 0;
+ }
+
+ CRYPTO_chacha_20(out, in, plaintext_len, c20_ctx->key, nonce, 1);
+ *out_len = plaintext_len;
+ return 1;
+}
+
+static const EVP_AEAD aead_chacha20_poly1305 = {
+ 32, /* key len */
+ CHACHA20_NONCE_LEN, /* nonce len */
+ POLY1305_TAG_LEN, /* overhead */
+ POLY1305_TAG_LEN, /* max tag length */
+ aead_chacha20_poly1305_init, aead_chacha20_poly1305_cleanup,
+ aead_chacha20_poly1305_seal, aead_chacha20_poly1305_open,
+};
+
+const EVP_AEAD *EVP_aead_chacha20_poly1305(void) {
+ return &aead_chacha20_poly1305;
+}
diff --git a/src/crypto/cipher/e_des.c b/src/crypto/cipher/e_des.c
new file mode 100644
index 0000000..d4b04f4
--- /dev/null
+++ b/src/crypto/cipher/e_des.c
@@ -0,0 +1,157 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/cipher.h>
+#include <openssl/des.h>
+#include <openssl/obj.h>
+
+#include "internal.h"
+
+
+#define EVP_MAXCHUNK (1<<30)
+
+typedef struct {
+ union {
+ double align;
+ DES_key_schedule ks;
+ } ks;
+} EVP_DES_KEY;
+
+static int des_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key,
+ const uint8_t *iv, int enc) {
+ DES_cblock *deskey = (DES_cblock *)key;
+ EVP_DES_KEY *dat = (EVP_DES_KEY *)ctx->cipher_data;
+
+ DES_set_key(deskey, &dat->ks.ks);
+ return 1;
+}
+
+static int des_cbc_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
+ size_t in_len) {
+ EVP_DES_KEY *dat = (EVP_DES_KEY *)ctx->cipher_data;
+
+ while (in_len >= EVP_MAXCHUNK) {
+ DES_ncbc_encrypt(in, out, EVP_MAXCHUNK, &dat->ks.ks, (DES_cblock *)ctx->iv,
+ ctx->encrypt);
+ in_len -= EVP_MAXCHUNK;
+ in += EVP_MAXCHUNK;
+ out += EVP_MAXCHUNK;
+ }
+
+ if (in_len) {
+ DES_ncbc_encrypt(in, out, (long)in_len, &dat->ks.ks,
+ (DES_cblock *)ctx->iv, ctx->encrypt);
+ }
+
+ return 1;
+}
+
+static const EVP_CIPHER des_cbc = {
+ NID_des_cbc, 8 /* block_size */, 8 /* key_size */,
+ 8 /* iv_len */, sizeof(EVP_DES_KEY), EVP_CIPH_CBC_MODE,
+ NULL /* app_data */, des_init_key, des_cbc_cipher,
+ NULL /* cleanup */, NULL /* ctrl */, };
+
+const EVP_CIPHER *EVP_des_cbc(void) { return &des_cbc; }
+
+
+typedef struct {
+ union {
+ double align;
+ DES_key_schedule ks[3];
+ } ks;
+} DES_EDE_KEY;
+
+
+static int des_ede3_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key,
+ const uint8_t *iv, int enc) {
+ DES_cblock *deskey = (DES_cblock *)key;
+ DES_EDE_KEY *dat = (DES_EDE_KEY*) ctx->cipher_data;
+
+ DES_set_key(&deskey[0], &dat->ks.ks[0]);
+ DES_set_key(&deskey[1], &dat->ks.ks[1]);
+ DES_set_key(&deskey[2], &dat->ks.ks[2]);
+
+ return 1;
+}
+
+static int des_ede3_cbc_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out,
+ const uint8_t *in, size_t in_len) {
+ DES_EDE_KEY *dat = (DES_EDE_KEY*) ctx->cipher_data;
+
+ while (in_len >= EVP_MAXCHUNK) {
+ DES_ede3_cbc_encrypt(in, out, EVP_MAXCHUNK, &dat->ks.ks[0], &dat->ks.ks[1],
+ &dat->ks.ks[2], (DES_cblock *)ctx->iv, ctx->encrypt);
+ in_len -= EVP_MAXCHUNK;
+ in += EVP_MAXCHUNK;
+ out += EVP_MAXCHUNK;
+ }
+
+ if (in_len) {
+ DES_ede3_cbc_encrypt(in, out, in_len, &dat->ks.ks[0], &dat->ks.ks[1],
+ &dat->ks.ks[2], (DES_cblock *)ctx->iv, ctx->encrypt);
+ }
+
+ return 1;
+}
+
+static const EVP_CIPHER des3_cbc = {
+ NID_des_cbc, 8 /* block_size */, 24 /* key_size */,
+ 8 /* iv_len */, sizeof(DES_EDE_KEY), EVP_CIPH_CBC_MODE,
+ NULL /* app_data */, des_ede3_init_key, des_ede3_cbc_cipher,
+ NULL /* cleanup */, NULL /* ctrl */, };
+
+const EVP_CIPHER *EVP_des_ede3_cbc(void) { return &des3_cbc; }
diff --git a/src/crypto/cipher/e_null.c b/src/crypto/cipher/e_null.c
new file mode 100644
index 0000000..cfe1d1b
--- /dev/null
+++ b/src/crypto/cipher/e_null.c
@@ -0,0 +1,85 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/cipher.h>
+
+#include <string.h>
+
+#include <openssl/obj.h>
+
+#include "internal.h"
+
+
+static int null_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key,
+ const uint8_t *iv, int enc) {
+ return 1;
+}
+
+static int null_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out,
+ const uint8_t *in, size_t in_len) {
+ if (in != out) {
+ memcpy(out, in, in_len);
+ }
+ return 1;
+}
+
+static const EVP_CIPHER n_cipher = {
+ NID_undef, 1 /* block size */, 0 /* key_len */, 0 /* iv_len */,
+ 0 /* ctx_size */, 0 /* flags */, NULL /* app_data */, null_init_key,
+ null_cipher, NULL /* cleanup */, NULL /* ctrl */,
+};
+
+const EVP_CIPHER *EVP_enc_null(void) { return &n_cipher; }
diff --git a/src/crypto/cipher/e_rc2.c b/src/crypto/cipher/e_rc2.c
new file mode 100644
index 0000000..c90ab93
--- /dev/null
+++ b/src/crypto/cipher/e_rc2.c
@@ -0,0 +1,420 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/cipher.h>
+#include <openssl/obj.h>
+
+#include "internal.h"
+
+
+#define c2l(c, l) \
+ (l = ((uint32_t)(*((c)++))), l |= ((uint32_t)(*((c)++))) << 8L, \
+ l |= ((uint32_t)(*((c)++))) << 16L, \
+ l |= ((uint32_t)(*((c)++))) << 24L)
+
+#define c2ln(c, l1, l2, n) \
+ { \
+ c += n; \
+ l1 = l2 = 0; \
+ switch (n) { \
+ case 8: \
+ l2 = ((uint32_t)(*(--(c)))) << 24L; \
+ case 7: \
+ l2 |= ((uint32_t)(*(--(c)))) << 16L; \
+ case 6: \
+ l2 |= ((uint32_t)(*(--(c)))) << 8L; \
+ case 5: \
+ l2 |= ((uint32_t)(*(--(c)))); \
+ case 4: \
+ l1 = ((uint32_t)(*(--(c)))) << 24L; \
+ case 3: \
+ l1 |= ((uint32_t)(*(--(c)))) << 16L; \
+ case 2: \
+ l1 |= ((uint32_t)(*(--(c)))) << 8L; \
+ case 1: \
+ l1 |= ((uint32_t)(*(--(c)))); \
+ } \
+ }
+
+#define l2c(l, c) \
+ (*((c)++) = (uint8_t)(((l)) & 0xff), \
+ *((c)++) = (uint8_t)(((l) >> 8L) & 0xff), \
+ *((c)++) = (uint8_t)(((l) >> 16L) & 0xff), \
+ *((c)++) = (uint8_t)(((l) >> 24L) & 0xff))
+
+#define l2cn(l1, l2, c, n) \
+ { \
+ c += n; \
+ switch (n) { \
+ case 8: \
+ *(--(c)) = (uint8_t)(((l2) >> 24L) & 0xff); \
+ case 7: \
+ *(--(c)) = (uint8_t)(((l2) >> 16L) & 0xff); \
+ case 6: \
+ *(--(c)) = (uint8_t)(((l2) >> 8L) & 0xff); \
+ case 5: \
+ *(--(c)) = (uint8_t)(((l2)) & 0xff); \
+ case 4: \
+ *(--(c)) = (uint8_t)(((l1) >> 24L) & 0xff); \
+ case 3: \
+ *(--(c)) = (uint8_t)(((l1) >> 16L) & 0xff); \
+ case 2: \
+ *(--(c)) = (uint8_t)(((l1) >> 8L) & 0xff); \
+ case 1: \
+ *(--(c)) = (uint8_t)(((l1)) & 0xff); \
+ } \
+ }
+
+typedef struct rc2_key_st { uint16_t data[64]; } RC2_KEY;
+
+static void RC2_encrypt(uint32_t *d, RC2_KEY *key) {
+ int i, n;
+ uint16_t *p0, *p1;
+ uint16_t x0, x1, x2, x3, t;
+ uint32_t l;
+
+ l = d[0];
+ x0 = (uint16_t)l & 0xffff;
+ x1 = (uint16_t)(l >> 16L);
+ l = d[1];
+ x2 = (uint16_t)l & 0xffff;
+ x3 = (uint16_t)(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] = (uint32_t)(x0 & 0xffff) | ((uint32_t)(x1 & 0xffff) << 16L);
+ d[1] = (uint32_t)(x2 & 0xffff) | ((uint32_t)(x3 & 0xffff) << 16L);
+}
+
+static void RC2_decrypt(uint32_t *d, RC2_KEY *key) {
+ int i, n;
+ uint16_t *p0, *p1;
+ uint16_t x0, x1, x2, x3, t;
+ uint32_t l;
+
+ l = d[0];
+ x0 = (uint16_t)l & 0xffff;
+ x1 = (uint16_t)(l >> 16L);
+ l = d[1];
+ x2 = (uint16_t)l & 0xffff;
+ x3 = (uint16_t)(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] = (uint32_t)(x0 & 0xffff) | ((uint32_t)(x1 & 0xffff) << 16L);
+ d[1] = (uint32_t)(x2 & 0xffff) | ((uint32_t)(x3 & 0xffff) << 16L);
+}
+
+static void RC2_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t length,
+ RC2_KEY *ks, uint8_t *iv, int encrypt) {
+ uint32_t tin0, tin1;
+ uint32_t tout0, tout1, xor0, xor1;
+ long l = length;
+ uint32_t 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);
+ }
+ tin[0] = tin[1] = 0;
+}
+
+static const uint8_t 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,
+};
+
+static void RC2_set_key(RC2_KEY *key, int len, const uint8_t *data, int bits) {
+ int i, j;
+ uint8_t *k;
+ uint16_t *ki;
+ unsigned int c, d;
+
+ k = (uint8_t *)&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 uint16_t's */
+ ki = &(key->data[63]);
+ for (i = 127; i >= 0; i -= 2) {
+ *(ki--) = ((k[i] << 8) | k[i - 1]) & 0xffff;
+ }
+}
+
+typedef struct {
+ int key_bits; /* effective key bits */
+ RC2_KEY ks; /* key schedule */
+} EVP_RC2_KEY;
+
+static int rc2_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key,
+ const uint8_t *iv, int enc) {
+ EVP_RC2_KEY *rc2_key = (EVP_RC2_KEY *)ctx->cipher_data;
+ RC2_set_key(&rc2_key->ks, EVP_CIPHER_CTX_key_length(ctx), key,
+ rc2_key->key_bits);
+ return 1;
+}
+
+static int rc2_cbc_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
+ size_t inl) {
+ EVP_RC2_KEY *key = (EVP_RC2_KEY *)ctx->cipher_data;
+ static const size_t kChunkSize = 0x10000;
+
+ while (inl >= kChunkSize) {
+ RC2_cbc_encrypt(in, out, kChunkSize, &key->ks, ctx->iv, ctx->encrypt);
+ inl -= kChunkSize;
+ in += kChunkSize;
+ out += kChunkSize;
+ }
+ if (inl) {
+ RC2_cbc_encrypt(in, out, inl, &key->ks, ctx->iv, ctx->encrypt);
+ }
+ return 1;
+}
+
+static int rc2_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr) {
+ EVP_RC2_KEY *key = (EVP_RC2_KEY *)ctx->cipher_data;
+
+ switch (type) {
+ case EVP_CTRL_INIT:
+ key->key_bits = EVP_CIPHER_CTX_key_length(ctx) * 8;
+ return 1;
+
+ default:
+ return -1;
+ }
+}
+
+static const EVP_CIPHER rc2_40_cbc_cipher = {
+ NID_rc2_40_cbc,
+ 8 /* block size */,
+ 5 /* 40 bit */,
+ 8 /* iv len */,
+ sizeof(EVP_RC2_KEY),
+ EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CTRL_INIT,
+ NULL /* app_data */,
+ rc2_init_key,
+ rc2_cbc_cipher,
+ NULL,
+ rc2_ctrl,
+};
+
+const EVP_CIPHER *EVP_rc2_40_cbc(void) {
+ return &rc2_40_cbc_cipher;
+}
diff --git a/src/crypto/cipher/e_rc4.c b/src/crypto/cipher/e_rc4.c
new file mode 100644
index 0000000..04ddcb6
--- /dev/null
+++ b/src/crypto/cipher/e_rc4.c
@@ -0,0 +1,384 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/aead.h>
+
+#include <assert.h>
+#include <string.h>
+
+#include <openssl/cipher.h>
+#include <openssl/cpu.h>
+#include <openssl/err.h>
+#include <openssl/md5.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/rc4.h>
+
+#include "internal.h"
+
+
+static int rc4_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key,
+ const uint8_t *iv, int enc) {
+ RC4_KEY *rc4key = (RC4_KEY *)ctx->cipher_data;
+
+ RC4_set_key(rc4key, EVP_CIPHER_CTX_key_length(ctx), key);
+ return 1;
+}
+
+static int rc4_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
+ size_t in_len) {
+ RC4_KEY *rc4key = (RC4_KEY *)ctx->cipher_data;
+
+ RC4(rc4key, in_len, in, out);
+ return 1;
+}
+
+static const EVP_CIPHER rc4 = {
+ NID_rc4, 1 /* block_size */, 16 /* key_size */,
+ 0 /* iv_len */, sizeof(RC4_KEY), EVP_CIPH_VARIABLE_LENGTH,
+ NULL /* app_data */, rc4_init_key, rc4_cipher,
+ NULL /* cleanup */, NULL /* ctrl */, };
+
+const EVP_CIPHER *EVP_rc4(void) { return &rc4; }
+
+
+struct aead_rc4_md5_tls_ctx {
+ RC4_KEY rc4;
+ MD5_CTX head, tail, md;
+ size_t payload_length;
+ unsigned char tag_len;
+};
+
+
+static int
+aead_rc4_md5_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len,
+ size_t tag_len) {
+ struct aead_rc4_md5_tls_ctx *rc4_ctx;
+ size_t i;
+ uint8_t hmac_key[MD5_CBLOCK];
+
+ if (tag_len == EVP_AEAD_DEFAULT_TAG_LENGTH) {
+ tag_len = MD5_DIGEST_LENGTH;
+ }
+
+ if (tag_len > MD5_DIGEST_LENGTH) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_rc4_md5_tls_init, CIPHER_R_TOO_LARGE);
+ return 0;
+ }
+
+ /* The keys consists of |MD5_DIGEST_LENGTH| bytes of HMAC(MD5) key followed
+ * by some number of bytes of RC4 key. */
+ if (key_len <= MD5_DIGEST_LENGTH) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_rc4_md5_tls_init, CIPHER_R_BAD_KEY_LENGTH);
+ return 0;
+ }
+
+ rc4_ctx = OPENSSL_malloc(sizeof(struct aead_rc4_md5_tls_ctx));
+ if (rc4_ctx == NULL) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_rc4_md5_tls_init, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ memset(rc4_ctx, 0, sizeof(struct aead_rc4_md5_tls_ctx));
+
+ RC4_set_key(&rc4_ctx->rc4, key_len - MD5_DIGEST_LENGTH,
+ key + MD5_DIGEST_LENGTH);
+
+ memset(hmac_key, 0, sizeof(hmac_key));
+ memcpy(hmac_key, key, MD5_DIGEST_LENGTH);
+ for (i = 0; i < sizeof(hmac_key); i++) {
+ hmac_key[i] ^= 0x36;
+ }
+ MD5_Init(&rc4_ctx->head);
+ MD5_Update(&rc4_ctx->head, hmac_key, sizeof(hmac_key));
+ for (i = 0; i < sizeof(hmac_key); i++) {
+ hmac_key[i] ^= 0x36 ^ 0x5c;
+ }
+ MD5_Init(&rc4_ctx->tail);
+ MD5_Update(&rc4_ctx->tail, hmac_key, sizeof(hmac_key));
+
+ rc4_ctx->tag_len = tag_len;
+ ctx->aead_state = rc4_ctx;
+
+ return 1;
+}
+
+static void aead_rc4_md5_tls_cleanup(EVP_AEAD_CTX *ctx) {
+ struct aead_rc4_md5_tls_ctx *rc4_ctx = ctx->aead_state;
+ OPENSSL_cleanse(rc4_ctx, sizeof(struct aead_rc4_md5_tls_ctx));
+ OPENSSL_free(rc4_ctx);
+}
+
+#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64)
+#define STITCHED_CALL
+
+/* rc4_md5_enc is defined in rc4_md5-x86_64.pl */
+void rc4_md5_enc(RC4_KEY *key, const void *in0, void *out, MD5_CTX *ctx,
+ const void *inp, size_t blocks);
+#endif
+
+static int aead_rc4_md5_tls_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
+ size_t *out_len, size_t max_out_len,
+ const uint8_t *nonce, size_t nonce_len,
+ const uint8_t *in, size_t in_len,
+ const uint8_t *ad, size_t ad_len) {
+ struct aead_rc4_md5_tls_ctx *rc4_ctx = ctx->aead_state;
+ MD5_CTX md;
+#if defined(STITCHED_CALL)
+ size_t rc4_off, md5_off, blocks;
+#else
+ const size_t rc4_off = 0;
+ const size_t md5_off = 0;
+#endif
+ uint8_t digest[MD5_DIGEST_LENGTH];
+
+ if (in_len + rc4_ctx->tag_len < in_len) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_rc4_md5_tls_seal, CIPHER_R_TOO_LARGE);
+ return 0;
+ }
+
+ if (nonce_len != 0) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_rc4_md5_tls_seal, CIPHER_R_IV_TOO_LARGE);
+ return 0;
+ }
+
+ if (max_out_len < in_len + rc4_ctx->tag_len) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_rc4_md5_tls_seal, CIPHER_R_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ if (nonce_len != 0) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_rc4_md5_tls_seal, CIPHER_R_TOO_LARGE);
+ return 0;
+ }
+
+ memcpy(&md, &rc4_ctx->head, sizeof(MD5_CTX));
+ /* The MAC's payload begins with the additional data. See
+ * https://tools.ietf.org/html/rfc5246#section-6.2.3.1 */
+ MD5_Update(&md, ad, ad_len);
+
+ /* To allow for CBC mode which changes cipher length, |ad| doesn't include the
+ * length for legacy ciphers. */
+ uint8_t ad_extra[2];
+ ad_extra[0] = (uint8_t)(in_len >> 8);
+ ad_extra[1] = (uint8_t)(in_len & 0xff);
+ MD5_Update(&md, ad_extra, sizeof(ad_extra));
+
+#if defined(STITCHED_CALL)
+ /* 32 is $MOD from rc4_md5-x86_64.pl. */
+ rc4_off = 32 - 1 - (rc4_ctx->rc4.x & (32 - 1));
+ md5_off = MD5_CBLOCK - md.num;
+ /* Ensure RC4 is behind MD5. */
+ if (rc4_off > md5_off) {
+ md5_off += MD5_CBLOCK;
+ }
+ assert(md5_off >= rc4_off);
+
+ if (in_len > md5_off && (blocks = (in_len - md5_off) / MD5_CBLOCK) &&
+ (OPENSSL_ia32cap_P[0] & (1 << 20)) == 0) {
+ /* Process the initial portions of the plaintext normally. */
+ MD5_Update(&md, in, md5_off);
+ RC4(&rc4_ctx->rc4, rc4_off, in, out);
+
+ /* Process the next |blocks| blocks of plaintext with stitched routines. */
+ rc4_md5_enc(&rc4_ctx->rc4, in + rc4_off, out + rc4_off, &md, in + md5_off,
+ blocks);
+ blocks *= MD5_CBLOCK;
+ rc4_off += blocks;
+ md5_off += blocks;
+ md.Nh += blocks >> 29;
+ md.Nl += blocks <<= 3;
+ if (md.Nl < (unsigned int)blocks) {
+ md.Nh++;
+ }
+ } else {
+ rc4_off = 0;
+ md5_off = 0;
+ }
+#endif
+ /* Finish computing the MAC. */
+ MD5_Update(&md, in + md5_off, in_len - md5_off);
+ MD5_Final(digest, &md);
+
+ memcpy(&md, &rc4_ctx->tail, sizeof(MD5_CTX));
+ MD5_Update(&md, digest, sizeof(digest));
+ if (rc4_ctx->tag_len == MD5_DIGEST_LENGTH) {
+ MD5_Final(out + in_len, &md);
+ } else {
+ MD5_Final(digest, &md);
+ memcpy(out + in_len, digest, rc4_ctx->tag_len);
+ }
+
+ /* Encrypt the remainder of the plaintext and the MAC. */
+ RC4(&rc4_ctx->rc4, in_len - rc4_off, in + rc4_off, out + rc4_off);
+ RC4(&rc4_ctx->rc4, MD5_DIGEST_LENGTH, out + in_len, out + in_len);
+
+ *out_len = in_len + rc4_ctx->tag_len;
+ return 1;
+}
+
+static int aead_rc4_md5_tls_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
+ size_t *out_len, size_t max_out_len,
+ const uint8_t *nonce, size_t nonce_len,
+ const uint8_t *in, size_t in_len,
+ const uint8_t *ad, size_t ad_len) {
+ struct aead_rc4_md5_tls_ctx *rc4_ctx = ctx->aead_state;
+ MD5_CTX md;
+ size_t plaintext_len;
+#if defined(STITCHED_CALL)
+ unsigned int l;
+ size_t rc4_off, md5_off, blocks;
+ extern unsigned int OPENSSL_ia32cap_P[];
+#else
+ const size_t rc4_off = 0;
+ const size_t md5_off = 0;
+#endif
+ uint8_t digest[MD5_DIGEST_LENGTH];
+
+ if (in_len < rc4_ctx->tag_len) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_rc4_md5_tls_open, CIPHER_R_BAD_DECRYPT);
+ return 0;
+ }
+
+ plaintext_len = in_len - rc4_ctx->tag_len;
+
+ if (nonce_len != 0) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_rc4_md5_tls_open, CIPHER_R_TOO_LARGE);
+ return 0;
+ }
+
+ if (max_out_len < plaintext_len) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_rc4_md5_tls_open, CIPHER_R_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ memcpy(&md, &rc4_ctx->head, sizeof(MD5_CTX));
+ /* The MAC's payload begins with the additional data. See
+ * https://tools.ietf.org/html/rfc5246#section-6.2.3.1 */
+ MD5_Update(&md, ad, ad_len);
+
+ /* To allow for CBC mode which changes cipher length, |ad| doesn't include the
+ * length for legacy ciphers. */
+ uint8_t ad_extra[2];
+ ad_extra[0] = (uint8_t)(plaintext_len >> 8);
+ ad_extra[1] = (uint8_t)(plaintext_len & 0xff);
+ MD5_Update(&md, ad_extra, sizeof(ad_extra));
+
+#if defined(STITCHED_CALL)
+ rc4_off = 32 - 1 - (rc4_ctx->rc4.x & (32 - 1));
+ md5_off = MD5_CBLOCK - md.num;
+ /* Ensure MD5 is a full block behind RC4 so it has plaintext to operate on in
+ * both normal and stitched routines. */
+ if (md5_off > rc4_off) {
+ rc4_off += 2 * MD5_CBLOCK;
+ } else {
+ rc4_off += MD5_CBLOCK;
+ }
+
+ if (in_len > rc4_off && (blocks = (in_len - rc4_off) / MD5_CBLOCK) &&
+ (OPENSSL_ia32cap_P[0] & (1 << 20)) == 0) {
+ /* Decrypt the initial portion of the ciphertext and digest the plaintext
+ * normally. */
+ RC4(&rc4_ctx->rc4, rc4_off, in, out);
+ MD5_Update(&md, out, md5_off);
+
+ /* Decrypt and digest the next |blocks| blocks of ciphertext with the
+ * stitched routines. */
+ rc4_md5_enc(&rc4_ctx->rc4, in + rc4_off, out + rc4_off, &md, out + md5_off,
+ blocks);
+ blocks *= MD5_CBLOCK;
+ rc4_off += blocks;
+ md5_off += blocks;
+ l = (md.Nl + (blocks << 3)) & 0xffffffffU;
+ if (l < md.Nl) {
+ md.Nh++;
+ }
+ md.Nl = l;
+ md.Nh += blocks >> 29;
+ } else {
+ md5_off = 0;
+ rc4_off = 0;
+ }
+#endif
+
+ /* Process the remainder of the input. */
+ RC4(&rc4_ctx->rc4, in_len - rc4_off, in + rc4_off, out + rc4_off);
+ MD5_Update(&md, out + md5_off, plaintext_len - md5_off);
+ MD5_Final(digest, &md);
+
+ /* Calculate HMAC and verify it */
+ memcpy(&md, &rc4_ctx->tail, sizeof(MD5_CTX));
+ MD5_Update(&md, digest, MD5_DIGEST_LENGTH);
+ MD5_Final(digest, &md);
+
+ if (CRYPTO_memcmp(out + plaintext_len, digest, rc4_ctx->tag_len)) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_rc4_md5_tls_open, CIPHER_R_BAD_DECRYPT);
+ return 0;
+ }
+
+ *out_len = plaintext_len;
+ return 1;
+}
+
+static const EVP_AEAD aead_rc4_md5_tls = {
+ 16 + MD5_DIGEST_LENGTH, /* key len (RC4 + MD5) */
+ 0, /* nonce len */
+ MD5_DIGEST_LENGTH, /* overhead */
+ MD5_DIGEST_LENGTH, /* max tag length */
+ aead_rc4_md5_tls_init, aead_rc4_md5_tls_cleanup,
+ aead_rc4_md5_tls_seal, aead_rc4_md5_tls_open,
+};
+
+const EVP_AEAD *EVP_aead_rc4_md5_tls(void) { return &aead_rc4_md5_tls; }
diff --git a/src/crypto/cipher/e_ssl3.c b/src/crypto/cipher/e_ssl3.c
new file mode 100644
index 0000000..d9dec68
--- /dev/null
+++ b/src/crypto/cipher/e_ssl3.c
@@ -0,0 +1,437 @@
+/* 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 <assert.h>
+#include <limits.h>
+#include <string.h>
+
+#include <openssl/aead.h>
+#include <openssl/cipher.h>
+#include <openssl/err.h>
+#include <openssl/hmac.h>
+#include <openssl/md5.h>
+#include <openssl/mem.h>
+#include <openssl/sha.h>
+
+#include "internal.h"
+
+
+typedef struct {
+ EVP_CIPHER_CTX cipher_ctx;
+ EVP_MD_CTX md_ctx;
+ /* enc_key is the portion of the key used for the stream or block cipher. It
+ * is retained separately to allow the EVP_CIPHER_CTX to be initialized once
+ * the direction is known. */
+ uint8_t enc_key[EVP_MAX_KEY_LENGTH];
+ uint8_t enc_key_len;
+ /* iv is the portion of the key used for the fixed IV. It is retained
+ * separately to allow the EVP_CIPHER_CTX to be initialized once the direction
+ * is known. */
+ uint8_t iv[EVP_MAX_IV_LENGTH];
+ uint8_t iv_len;
+ char initialized;
+} AEAD_SSL3_CTX;
+
+static int ssl3_mac(AEAD_SSL3_CTX *ssl3_ctx, uint8_t *out, unsigned *out_len,
+ const uint8_t *ad, size_t ad_len, const uint8_t *in,
+ size_t in_len) {
+ size_t md_size = EVP_MD_CTX_size(&ssl3_ctx->md_ctx);
+ size_t pad_len = (md_size == 20) ? 40 : 48;
+
+ /* To allow for CBC mode which changes cipher length, |ad| doesn't include the
+ * length for legacy ciphers. */
+ uint8_t ad_extra[2];
+ ad_extra[0] = (uint8_t)(in_len >> 8);
+ ad_extra[1] = (uint8_t)(in_len & 0xff);
+
+ EVP_MD_CTX md_ctx;
+ EVP_MD_CTX_init(&md_ctx);
+
+ uint8_t pad[48];
+ uint8_t tmp[EVP_MAX_MD_SIZE];
+ memset(pad, 0x36, pad_len);
+ if (!EVP_MD_CTX_copy_ex(&md_ctx, &ssl3_ctx->md_ctx) ||
+ !EVP_DigestUpdate(&md_ctx, pad, pad_len) ||
+ !EVP_DigestUpdate(&md_ctx, ad, ad_len) ||
+ !EVP_DigestUpdate(&md_ctx, ad_extra, sizeof(ad_extra)) ||
+ !EVP_DigestUpdate(&md_ctx, in, in_len) ||
+ !EVP_DigestFinal_ex(&md_ctx, tmp, NULL)) {
+ EVP_MD_CTX_cleanup(&md_ctx);
+ return 0;
+ }
+
+ memset(pad, 0x5c, pad_len);
+ if (!EVP_MD_CTX_copy_ex(&md_ctx, &ssl3_ctx->md_ctx) ||
+ !EVP_DigestUpdate(&md_ctx, pad, pad_len) ||
+ !EVP_DigestUpdate(&md_ctx, tmp, md_size) ||
+ !EVP_DigestFinal_ex(&md_ctx, out, out_len)) {
+ EVP_MD_CTX_cleanup(&md_ctx);
+ return 0;
+ }
+ EVP_MD_CTX_cleanup(&md_ctx);
+ return 1;
+}
+
+static void aead_ssl3_cleanup(EVP_AEAD_CTX *ctx) {
+ AEAD_SSL3_CTX *ssl3_ctx = (AEAD_SSL3_CTX *)ctx->aead_state;
+ EVP_CIPHER_CTX_cleanup(&ssl3_ctx->cipher_ctx);
+ EVP_MD_CTX_cleanup(&ssl3_ctx->md_ctx);
+ OPENSSL_cleanse(&ssl3_ctx->enc_key, sizeof(ssl3_ctx->enc_key));
+ OPENSSL_cleanse(&ssl3_ctx->iv, sizeof(ssl3_ctx->iv));
+ OPENSSL_free(ssl3_ctx);
+ ctx->aead_state = NULL;
+}
+
+static int aead_ssl3_init(EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len,
+ size_t tag_len, const EVP_CIPHER *cipher,
+ const EVP_MD *md) {
+ if (tag_len != EVP_AEAD_DEFAULT_TAG_LENGTH &&
+ tag_len != EVP_MD_size(md)) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_ssl3_init, CIPHER_R_UNSUPPORTED_TAG_SIZE);
+ return 0;
+ }
+
+ if (key_len != EVP_AEAD_key_length(ctx->aead)) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_ssl3_init, CIPHER_R_BAD_KEY_LENGTH);
+ return 0;
+ }
+
+ size_t mac_key_len = EVP_MD_size(md);
+ size_t enc_key_len = EVP_CIPHER_key_length(cipher);
+ size_t iv_len = EVP_CIPHER_iv_length(cipher);
+ assert(mac_key_len + enc_key_len + iv_len == key_len);
+ assert(mac_key_len < 256);
+ assert(enc_key_len < 256);
+ assert(iv_len < 256);
+ /* Although EVP_rc4() is a variable-length cipher, the default key size is
+ * correct for SSL3. */
+
+ AEAD_SSL3_CTX *ssl3_ctx = OPENSSL_malloc(sizeof(AEAD_SSL3_CTX));
+ if (ssl3_ctx == NULL) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_ssl3_init, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ EVP_CIPHER_CTX_init(&ssl3_ctx->cipher_ctx);
+ EVP_MD_CTX_init(&ssl3_ctx->md_ctx);
+ memcpy(ssl3_ctx->enc_key, &key[mac_key_len], enc_key_len);
+ ssl3_ctx->enc_key_len = (uint8_t)enc_key_len;
+ memcpy(ssl3_ctx->iv, &key[mac_key_len + enc_key_len], iv_len);
+ ssl3_ctx->iv_len = (uint8_t)iv_len;
+ ssl3_ctx->initialized = 0;
+
+ ctx->aead_state = ssl3_ctx;
+ if (!EVP_CipherInit_ex(&ssl3_ctx->cipher_ctx, cipher, NULL, NULL, NULL, 0) ||
+ !EVP_DigestInit_ex(&ssl3_ctx->md_ctx, md, NULL) ||
+ !EVP_DigestUpdate(&ssl3_ctx->md_ctx, key, mac_key_len)) {
+ aead_ssl3_cleanup(ctx);
+ return 0;
+ }
+ EVP_CIPHER_CTX_set_padding(&ssl3_ctx->cipher_ctx, 0);
+
+ return 1;
+}
+
+/* aead_ssl3_ensure_cipher_init initializes |ssl3_ctx| for encryption (or
+ * decryption, if |encrypt| is zero). If it has already been initialized, it
+ * ensures the direction matches and fails otherwise. It returns one on success
+ * and zero on failure.
+ *
+ * Note that, unlike normal AEADs, legacy SSL3 AEADs may not be used concurrently
+ * due to this (and bulk-cipher-internal) statefulness. */
+static int aead_ssl3_ensure_cipher_init(AEAD_SSL3_CTX *ssl3_ctx, int encrypt) {
+ if (!ssl3_ctx->initialized) {
+ /* Finish initializing the EVP_CIPHER_CTX now that the direction is
+ * known. */
+ if (!EVP_CipherInit_ex(&ssl3_ctx->cipher_ctx, NULL, NULL, ssl3_ctx->enc_key,
+ ssl3_ctx->iv, encrypt)) {
+ return 0;
+ }
+ ssl3_ctx->initialized = 1;
+ } else if (ssl3_ctx->cipher_ctx.encrypt != encrypt) {
+ /* Unlike a normal AEAD, using an SSL3 AEAD once freezes the direction. */
+ OPENSSL_PUT_ERROR(CIPHER, aead_ssl3_ensure_cipher_init,
+ CIPHER_R_INVALID_OPERATION);
+ return 0;
+ }
+ return 1;
+}
+
+static int aead_ssl3_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
+ size_t *out_len, size_t max_out_len,
+ const uint8_t *nonce, size_t nonce_len,
+ const uint8_t *in, size_t in_len,
+ const uint8_t *ad, size_t ad_len) {
+ AEAD_SSL3_CTX *ssl3_ctx = (AEAD_SSL3_CTX *)ctx->aead_state;
+ size_t total = 0;
+
+ if (in_len + EVP_AEAD_max_overhead(ctx->aead) < in_len ||
+ in_len > INT_MAX) {
+ /* EVP_CIPHER takes int as input. */
+ OPENSSL_PUT_ERROR(CIPHER, aead_ssl3_seal, CIPHER_R_TOO_LARGE);
+ return 0;
+ }
+
+ if (max_out_len < in_len + EVP_AEAD_max_overhead(ctx->aead)) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_ssl3_seal, CIPHER_R_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ if (nonce_len != 0) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_ssl3_seal, CIPHER_R_IV_TOO_LARGE);
+ return 0;
+ }
+
+ if (ad_len != 11 - 2 /* length bytes */) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_ssl3_seal, CIPHER_R_INVALID_AD_SIZE);
+ return 0;
+ }
+
+ if (!aead_ssl3_ensure_cipher_init(ssl3_ctx, 1)) {
+ return 0;
+ }
+
+ /* Compute the MAC. This must be first in case the operation is being done
+ * in-place. */
+ uint8_t mac[EVP_MAX_MD_SIZE];
+ unsigned mac_len;
+ if (!ssl3_mac(ssl3_ctx, mac, &mac_len, ad, ad_len, in, in_len)) {
+ return 0;
+ }
+
+ /* Encrypt the input. */
+ int len;
+ if (!EVP_EncryptUpdate(&ssl3_ctx->cipher_ctx, out, &len, in,
+ (int)in_len)) {
+ return 0;
+ }
+ total = len;
+
+ /* Feed the MAC into the cipher. */
+ if (!EVP_EncryptUpdate(&ssl3_ctx->cipher_ctx, out + total, &len, mac,
+ (int)mac_len)) {
+ return 0;
+ }
+ total += len;
+
+ unsigned block_size = EVP_CIPHER_CTX_block_size(&ssl3_ctx->cipher_ctx);
+ if (block_size > 1) {
+ assert(block_size <= 256);
+ assert(EVP_CIPHER_CTX_mode(&ssl3_ctx->cipher_ctx) == EVP_CIPH_CBC_MODE);
+
+ /* Compute padding and feed that into the cipher. */
+ uint8_t padding[256];
+ unsigned padding_len = block_size - ((in_len + mac_len) % block_size);
+ memset(padding, 0, padding_len - 1);
+ padding[padding_len - 1] = padding_len - 1;
+ if (!EVP_EncryptUpdate(&ssl3_ctx->cipher_ctx, out + total, &len, padding,
+ (int)padding_len)) {
+ return 0;
+ }
+ total += len;
+ }
+
+ if (!EVP_EncryptFinal_ex(&ssl3_ctx->cipher_ctx, out + total, &len)) {
+ return 0;
+ }
+ total += len;
+
+ *out_len = total;
+ return 1;
+}
+
+static int aead_ssl3_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
+ size_t *out_len, size_t max_out_len,
+ const uint8_t *nonce, size_t nonce_len,
+ const uint8_t *in, size_t in_len,
+ const uint8_t *ad, size_t ad_len) {
+ AEAD_SSL3_CTX *ssl3_ctx = (AEAD_SSL3_CTX *)ctx->aead_state;
+
+ size_t mac_len = EVP_MD_CTX_size(&ssl3_ctx->md_ctx);
+ if (in_len < mac_len) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_ssl3_open, CIPHER_R_BAD_DECRYPT);
+ return 0;
+ }
+
+ if (max_out_len < in_len) {
+ /* This requires that the caller provide space for the MAC, even though it
+ * will always be removed on return. */
+ OPENSSL_PUT_ERROR(CIPHER, aead_ssl3_open, CIPHER_R_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ if (nonce_len != 0) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_ssl3_open, CIPHER_R_TOO_LARGE);
+ return 0;
+ }
+
+ if (ad_len != 11 - 2 /* length bytes */) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_ssl3_open, CIPHER_R_INVALID_AD_SIZE);
+ return 0;
+ }
+
+ if (in_len > INT_MAX) {
+ /* EVP_CIPHER takes int as input. */
+ OPENSSL_PUT_ERROR(CIPHER, aead_ssl3_open, CIPHER_R_TOO_LARGE);
+ return 0;
+ }
+
+ if (!aead_ssl3_ensure_cipher_init(ssl3_ctx, 0)) {
+ return 0;
+ }
+
+ /* Decrypt to get the plaintext + MAC + padding. */
+ size_t total = 0;
+ int len;
+ if (!EVP_DecryptUpdate(&ssl3_ctx->cipher_ctx, out, &len, in, (int)in_len)) {
+ return 0;
+ }
+ total += len;
+ if (!EVP_DecryptFinal_ex(&ssl3_ctx->cipher_ctx, out + total, &len)) {
+ return 0;
+ }
+ total += len;
+ assert(total == in_len);
+
+ /* Remove CBC padding and MAC. This would normally be timing-sensitive, but SSLv3 CBC
+ * ciphers are already broken. Support will be removed eventually.
+ * https://www.openssl.org/~bodo/ssl-poodle.pdf */
+ unsigned data_len;
+ if (EVP_CIPHER_CTX_mode(&ssl3_ctx->cipher_ctx) == EVP_CIPH_CBC_MODE) {
+ unsigned padding_length = out[total - 1];
+ if (total < padding_length + 1 + mac_len) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_ssl3_open, CIPHER_R_BAD_DECRYPT);
+ return 0;
+ }
+ /* The padding must be minimal. */
+ if (padding_length + 1 > EVP_CIPHER_CTX_block_size(&ssl3_ctx->cipher_ctx)) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_ssl3_open, CIPHER_R_BAD_DECRYPT);
+ return 0;
+ }
+ data_len = total - padding_length - 1 - mac_len;
+ } else {
+ data_len = total - mac_len;
+ }
+
+ /* Compute the MAC and compare against the one in the record. */
+ uint8_t mac[EVP_MAX_MD_SIZE];
+ if (!ssl3_mac(ssl3_ctx, mac, NULL, ad, ad_len, out, data_len)) {
+ return 0;
+ }
+ if (CRYPTO_memcmp(&out[data_len], mac, mac_len) != 0) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_ssl3_open, CIPHER_R_BAD_DECRYPT);
+ return 0;
+ }
+
+ *out_len = data_len;
+ return 1;
+}
+
+static int aead_rc4_md5_ssl3_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
+ size_t key_len, size_t tag_len) {
+ return aead_ssl3_init(ctx, key, key_len, tag_len, EVP_rc4(), EVP_md5());
+}
+
+static int aead_rc4_sha1_ssl3_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
+ size_t key_len, size_t tag_len) {
+ return aead_ssl3_init(ctx, key, key_len, tag_len, EVP_rc4(), EVP_sha1());
+}
+
+static int aead_aes_128_cbc_sha1_ssl3_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
+ size_t key_len, size_t tag_len) {
+ return aead_ssl3_init(ctx, key, key_len, tag_len, EVP_aes_128_cbc(),
+ EVP_sha1());
+}
+
+static int aead_aes_256_cbc_sha1_ssl3_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
+ size_t key_len, size_t tag_len) {
+ return aead_ssl3_init(ctx, key, key_len, tag_len, EVP_aes_256_cbc(),
+ EVP_sha1());
+}
+static int aead_des_ede3_cbc_sha1_ssl3_init(EVP_AEAD_CTX *ctx,
+ const uint8_t *key, size_t key_len,
+ size_t tag_len) {
+ return aead_ssl3_init(ctx, key, key_len, tag_len, EVP_des_ede3_cbc(),
+ EVP_sha1());
+}
+
+static const EVP_AEAD aead_rc4_md5_ssl3 = {
+ MD5_DIGEST_LENGTH + 16, /* key len (MD5 + RC4) */
+ 0, /* nonce len */
+ MD5_DIGEST_LENGTH, /* overhead */
+ MD5_DIGEST_LENGTH, /* max tag length */
+ aead_rc4_md5_ssl3_init,
+ aead_ssl3_cleanup,
+ aead_ssl3_seal,
+ aead_ssl3_open,
+};
+
+static const EVP_AEAD aead_rc4_sha1_ssl3 = {
+ SHA_DIGEST_LENGTH + 16, /* key len (SHA1 + RC4) */
+ 0, /* nonce len */
+ SHA_DIGEST_LENGTH, /* overhead */
+ SHA_DIGEST_LENGTH, /* max tag length */
+ aead_rc4_sha1_ssl3_init,
+ aead_ssl3_cleanup,
+ aead_ssl3_seal,
+ aead_ssl3_open,
+};
+
+static const EVP_AEAD aead_aes_128_cbc_sha1_ssl3 = {
+ SHA_DIGEST_LENGTH + 16 + 16, /* key len (SHA1 + AES128 + IV) */
+ 0, /* nonce len */
+ 16 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */
+ SHA_DIGEST_LENGTH, /* max tag length */
+ aead_aes_128_cbc_sha1_ssl3_init,
+ aead_ssl3_cleanup,
+ aead_ssl3_seal,
+ aead_ssl3_open,
+};
+
+static const EVP_AEAD aead_aes_256_cbc_sha1_ssl3 = {
+ SHA_DIGEST_LENGTH + 32 + 16, /* key len (SHA1 + AES256 + IV) */
+ 0, /* nonce len */
+ 16 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */
+ SHA_DIGEST_LENGTH, /* max tag length */
+ aead_aes_256_cbc_sha1_ssl3_init,
+ aead_ssl3_cleanup,
+ aead_ssl3_seal,
+ aead_ssl3_open,
+};
+
+static const EVP_AEAD aead_des_ede3_cbc_sha1_ssl3 = {
+ SHA_DIGEST_LENGTH + 24 + 8, /* key len (SHA1 + 3DES + IV) */
+ 0, /* nonce len */
+ 8 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */
+ SHA_DIGEST_LENGTH, /* max tag length */
+ aead_des_ede3_cbc_sha1_ssl3_init,
+ aead_ssl3_cleanup,
+ aead_ssl3_seal,
+ aead_ssl3_open,
+};
+
+const EVP_AEAD *EVP_aead_rc4_md5_ssl3(void) { return &aead_rc4_md5_ssl3; }
+
+const EVP_AEAD *EVP_aead_rc4_sha1_ssl3(void) { return &aead_rc4_sha1_ssl3; }
+
+const EVP_AEAD *EVP_aead_aes_128_cbc_sha1_ssl3(void) {
+ return &aead_aes_128_cbc_sha1_ssl3;
+}
+
+const EVP_AEAD *EVP_aead_aes_256_cbc_sha1_ssl3(void) {
+ return &aead_aes_256_cbc_sha1_ssl3;
+}
+
+const EVP_AEAD *EVP_aead_des_ede3_cbc_sha1_ssl3(void) {
+ return &aead_des_ede3_cbc_sha1_ssl3;
+}
diff --git a/src/crypto/cipher/e_tls.c b/src/crypto/cipher/e_tls.c
new file mode 100644
index 0000000..8ac1aae
--- /dev/null
+++ b/src/crypto/cipher/e_tls.c
@@ -0,0 +1,611 @@
+/* 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 <assert.h>
+#include <limits.h>
+#include <string.h>
+
+#include <openssl/aead.h>
+#include <openssl/cipher.h>
+#include <openssl/err.h>
+#include <openssl/hmac.h>
+#include <openssl/mem.h>
+#include <openssl/sha.h>
+
+#include "../crypto/internal.h"
+#include "internal.h"
+
+
+typedef struct {
+ EVP_CIPHER_CTX cipher_ctx;
+ HMAC_CTX hmac_ctx;
+ /* mac_key is the portion of the key used for the MAC. It is retained
+ * separately for the constant-time CBC code. */
+ uint8_t mac_key[EVP_MAX_MD_SIZE];
+ uint8_t mac_key_len;
+ /* enc_key is the portion of the key used for the stream or block
+ * cipher. It is retained separately to allow the EVP_CIPHER_CTX to be
+ * initialized once the direction is known. */
+ uint8_t enc_key[EVP_MAX_KEY_LENGTH];
+ uint8_t enc_key_len;
+ /* iv is the portion of the key used for the fixed IV. It is retained
+ * separately to allow the EVP_CIPHER_CTX to be initialized once the direction
+ * is known. */
+ uint8_t iv[EVP_MAX_IV_LENGTH];
+ uint8_t iv_len;
+ /* implicit_iv is one iff this is a pre-TLS-1.1 CBC cipher without an explicit
+ * IV. */
+ char implicit_iv;
+ char initialized;
+} AEAD_TLS_CTX;
+
+
+static void aead_tls_cleanup(EVP_AEAD_CTX *ctx) {
+ AEAD_TLS_CTX *tls_ctx = (AEAD_TLS_CTX *)ctx->aead_state;
+ EVP_CIPHER_CTX_cleanup(&tls_ctx->cipher_ctx);
+ HMAC_CTX_cleanup(&tls_ctx->hmac_ctx);
+ OPENSSL_cleanse(&tls_ctx->mac_key, sizeof(tls_ctx->mac_key));
+ OPENSSL_cleanse(&tls_ctx->enc_key, sizeof(tls_ctx->enc_key));
+ OPENSSL_cleanse(&tls_ctx->iv, sizeof(tls_ctx->iv));
+ OPENSSL_free(tls_ctx);
+ ctx->aead_state = NULL;
+}
+
+static int aead_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len,
+ size_t tag_len, const EVP_CIPHER *cipher,
+ const EVP_MD *md, char implicit_iv) {
+ if (tag_len != EVP_AEAD_DEFAULT_TAG_LENGTH &&
+ tag_len != EVP_MD_size(md)) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_tls_init, CIPHER_R_UNSUPPORTED_TAG_SIZE);
+ return 0;
+ }
+
+ if (key_len != EVP_AEAD_key_length(ctx->aead)) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_tls_init, CIPHER_R_BAD_KEY_LENGTH);
+ return 0;
+ }
+
+ size_t mac_key_len = EVP_MD_size(md);
+ size_t enc_key_len = EVP_CIPHER_key_length(cipher);
+ size_t iv_len = implicit_iv ? EVP_CIPHER_iv_length(cipher) : 0;
+ assert(mac_key_len + enc_key_len + iv_len == key_len);
+ assert(mac_key_len < 256);
+ assert(enc_key_len < 256);
+ assert(iv_len < 256);
+ /* Although EVP_rc4() is a variable-length cipher, the default key size is
+ * correct for TLS. */
+
+ AEAD_TLS_CTX *tls_ctx = OPENSSL_malloc(sizeof(AEAD_TLS_CTX));
+ if (tls_ctx == NULL) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_tls_init, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ EVP_CIPHER_CTX_init(&tls_ctx->cipher_ctx);
+ HMAC_CTX_init(&tls_ctx->hmac_ctx);
+ memcpy(tls_ctx->mac_key, key, mac_key_len);
+ tls_ctx->mac_key_len = (uint8_t)mac_key_len;
+ memcpy(tls_ctx->enc_key, &key[mac_key_len], enc_key_len);
+ tls_ctx->enc_key_len = (uint8_t)enc_key_len;
+ memcpy(tls_ctx->iv, &key[mac_key_len + enc_key_len], iv_len);
+ tls_ctx->iv_len = (uint8_t)iv_len;
+ tls_ctx->implicit_iv = implicit_iv;
+ tls_ctx->initialized = 0;
+
+ ctx->aead_state = tls_ctx;
+ if (!EVP_CipherInit_ex(&tls_ctx->cipher_ctx, cipher, NULL, NULL, NULL, 0) ||
+ !HMAC_Init_ex(&tls_ctx->hmac_ctx, key, mac_key_len, md, NULL)) {
+ aead_tls_cleanup(ctx);
+ return 0;
+ }
+ EVP_CIPHER_CTX_set_padding(&tls_ctx->cipher_ctx, 0);
+
+ return 1;
+}
+
+/* aead_tls_ensure_cipher_init initializes |tls_ctx| for encryption (or
+ * decryption, if |encrypt| is zero). If it has already been initialized, it
+ * ensures the direction matches and fails otherwise. It returns one on success
+ * and zero on failure.
+ *
+ * Note that, unlike normal AEADs, legacy TLS AEADs may not be used concurrently
+ * due to this (and bulk-cipher-internal) statefulness. */
+static int aead_tls_ensure_cipher_init(AEAD_TLS_CTX *tls_ctx, int encrypt) {
+ if (!tls_ctx->initialized) {
+ /* Finish initializing the EVP_CIPHER_CTX now that the direction is
+ * known. */
+ if (!EVP_CipherInit_ex(&tls_ctx->cipher_ctx, NULL, NULL, tls_ctx->enc_key,
+ tls_ctx->implicit_iv ? tls_ctx->iv : NULL,
+ encrypt)) {
+ return 0;
+ }
+ tls_ctx->initialized = 1;
+ } else if (tls_ctx->cipher_ctx.encrypt != encrypt) {
+ /* Unlike a normal AEAD, using a TLS AEAD once freezes the direction. */
+ OPENSSL_PUT_ERROR(CIPHER, aead_tls_ensure_cipher_init,
+ CIPHER_R_INVALID_OPERATION);
+ return 0;
+ }
+ return 1;
+}
+
+static int aead_tls_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
+ size_t *out_len, size_t max_out_len,
+ const uint8_t *nonce, size_t nonce_len,
+ const uint8_t *in, size_t in_len,
+ const uint8_t *ad, size_t ad_len) {
+ AEAD_TLS_CTX *tls_ctx = (AEAD_TLS_CTX *)ctx->aead_state;
+ size_t total = 0;
+
+ if (in_len + EVP_AEAD_max_overhead(ctx->aead) < in_len ||
+ in_len > INT_MAX) {
+ /* EVP_CIPHER takes int as input. */
+ OPENSSL_PUT_ERROR(CIPHER, aead_tls_seal, CIPHER_R_TOO_LARGE);
+ return 0;
+ }
+
+ if (max_out_len < in_len + EVP_AEAD_max_overhead(ctx->aead)) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_tls_seal, CIPHER_R_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ if (nonce_len != EVP_AEAD_nonce_length(ctx->aead)) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_tls_seal, CIPHER_R_INVALID_NONCE_SIZE);
+ return 0;
+ }
+
+ if (ad_len != 13 - 2 /* length bytes */) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_tls_seal, CIPHER_R_INVALID_AD_SIZE);
+ return 0;
+ }
+
+ if (!aead_tls_ensure_cipher_init(tls_ctx, 1)) {
+ return 0;
+ }
+
+ /* To allow for CBC mode which changes cipher length, |ad| doesn't include the
+ * length for legacy ciphers. */
+ uint8_t ad_extra[2];
+ ad_extra[0] = (uint8_t)(in_len >> 8);
+ ad_extra[1] = (uint8_t)(in_len & 0xff);
+
+ /* Compute the MAC. This must be first in case the operation is being done
+ * in-place. */
+ uint8_t mac[EVP_MAX_MD_SIZE];
+ unsigned mac_len;
+ HMAC_CTX hmac_ctx;
+ HMAC_CTX_init(&hmac_ctx);
+ if (!HMAC_CTX_copy_ex(&hmac_ctx, &tls_ctx->hmac_ctx) ||
+ !HMAC_Update(&hmac_ctx, ad, ad_len) ||
+ !HMAC_Update(&hmac_ctx, ad_extra, sizeof(ad_extra)) ||
+ !HMAC_Update(&hmac_ctx, in, in_len) ||
+ !HMAC_Final(&hmac_ctx, mac, &mac_len)) {
+ HMAC_CTX_cleanup(&hmac_ctx);
+ return 0;
+ }
+ HMAC_CTX_cleanup(&hmac_ctx);
+
+ /* Configure the explicit IV. */
+ if (EVP_CIPHER_CTX_mode(&tls_ctx->cipher_ctx) == EVP_CIPH_CBC_MODE &&
+ !tls_ctx->implicit_iv &&
+ !EVP_EncryptInit_ex(&tls_ctx->cipher_ctx, NULL, NULL, NULL, nonce)) {
+ return 0;
+ }
+
+ /* Encrypt the input. */
+ int len;
+ if (!EVP_EncryptUpdate(&tls_ctx->cipher_ctx, out, &len, in,
+ (int)in_len)) {
+ return 0;
+ }
+ total = len;
+
+ /* Feed the MAC into the cipher. */
+ if (!EVP_EncryptUpdate(&tls_ctx->cipher_ctx, out + total, &len, mac,
+ (int)mac_len)) {
+ return 0;
+ }
+ total += len;
+
+ unsigned block_size = EVP_CIPHER_CTX_block_size(&tls_ctx->cipher_ctx);
+ if (block_size > 1) {
+ assert(block_size <= 256);
+ assert(EVP_CIPHER_CTX_mode(&tls_ctx->cipher_ctx) == EVP_CIPH_CBC_MODE);
+
+ /* Compute padding and feed that into the cipher. */
+ uint8_t padding[256];
+ unsigned padding_len = block_size - ((in_len + mac_len) % block_size);
+ memset(padding, padding_len - 1, padding_len);
+ if (!EVP_EncryptUpdate(&tls_ctx->cipher_ctx, out + total, &len, padding,
+ (int)padding_len)) {
+ return 0;
+ }
+ total += len;
+ }
+
+ if (!EVP_EncryptFinal_ex(&tls_ctx->cipher_ctx, out + total, &len)) {
+ return 0;
+ }
+ total += len;
+
+ *out_len = total;
+ return 1;
+}
+
+static int aead_tls_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
+ size_t *out_len, size_t max_out_len,
+ const uint8_t *nonce, size_t nonce_len,
+ const uint8_t *in, size_t in_len,
+ const uint8_t *ad, size_t ad_len) {
+ AEAD_TLS_CTX *tls_ctx = (AEAD_TLS_CTX *)ctx->aead_state;
+
+ if (in_len < HMAC_size(&tls_ctx->hmac_ctx)) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_tls_open, CIPHER_R_BAD_DECRYPT);
+ return 0;
+ }
+
+ if (max_out_len < in_len) {
+ /* This requires that the caller provide space for the MAC, even though it
+ * will always be removed on return. */
+ OPENSSL_PUT_ERROR(CIPHER, aead_tls_open, CIPHER_R_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ if (nonce_len != EVP_AEAD_nonce_length(ctx->aead)) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_tls_open, CIPHER_R_INVALID_NONCE_SIZE);
+ return 0;
+ }
+
+ if (ad_len != 13 - 2 /* length bytes */) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_tls_open, CIPHER_R_INVALID_AD_SIZE);
+ return 0;
+ }
+
+ if (in_len > INT_MAX) {
+ /* EVP_CIPHER takes int as input. */
+ OPENSSL_PUT_ERROR(CIPHER, aead_tls_open, CIPHER_R_TOO_LARGE);
+ return 0;
+ }
+
+ if (!aead_tls_ensure_cipher_init(tls_ctx, 0)) {
+ return 0;
+ }
+
+ /* Configure the explicit IV. */
+ if (EVP_CIPHER_CTX_mode(&tls_ctx->cipher_ctx) == EVP_CIPH_CBC_MODE &&
+ !tls_ctx->implicit_iv &&
+ !EVP_DecryptInit_ex(&tls_ctx->cipher_ctx, NULL, NULL, NULL, nonce)) {
+ return 0;
+ }
+
+ /* Decrypt to get the plaintext + MAC + padding. */
+ size_t total = 0;
+ int len;
+ if (!EVP_DecryptUpdate(&tls_ctx->cipher_ctx, out, &len, in, (int)in_len)) {
+ return 0;
+ }
+ total += len;
+ if (!EVP_DecryptFinal_ex(&tls_ctx->cipher_ctx, out + total, &len)) {
+ return 0;
+ }
+ total += len;
+ assert(total == in_len);
+
+ /* Remove CBC padding. Code from here on is timing-sensitive with respect to
+ * |padding_ok| and |data_plus_mac_len| for CBC ciphers. */
+ int padding_ok;
+ unsigned data_plus_mac_len, data_len;
+ if (EVP_CIPHER_CTX_mode(&tls_ctx->cipher_ctx) == EVP_CIPH_CBC_MODE) {
+ padding_ok = EVP_tls_cbc_remove_padding(
+ &data_plus_mac_len, out, total,
+ EVP_CIPHER_CTX_block_size(&tls_ctx->cipher_ctx),
+ (unsigned)HMAC_size(&tls_ctx->hmac_ctx));
+ /* Publicly invalid. This can be rejected in non-constant time. */
+ if (padding_ok == 0) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_tls_open, CIPHER_R_BAD_DECRYPT);
+ return 0;
+ }
+ } else {
+ padding_ok = 1;
+ data_plus_mac_len = total;
+ /* |data_plus_mac_len| = |total| = |in_len| at this point. |in_len| has
+ * already been checked against the MAC size at the top of the function. */
+ assert(data_plus_mac_len >= HMAC_size(&tls_ctx->hmac_ctx));
+ }
+ data_len = data_plus_mac_len - HMAC_size(&tls_ctx->hmac_ctx);
+
+ /* At this point, |padding_ok| is 1 or -1. If 1, the padding is valid and the
+ * first |data_plus_mac_size| bytes after |out| are the plaintext and
+ * MAC. Either way, |data_plus_mac_size| is large enough to extract a MAC. */
+
+ /* To allow for CBC mode which changes cipher length, |ad| doesn't include the
+ * length for legacy ciphers. */
+ uint8_t ad_fixed[13];
+ memcpy(ad_fixed, ad, 11);
+ ad_fixed[11] = (uint8_t)(data_len >> 8);
+ ad_fixed[12] = (uint8_t)(data_len & 0xff);
+ ad_len += 2;
+
+ /* Compute the MAC and extract the one in the record. */
+ uint8_t mac[EVP_MAX_MD_SIZE];
+ size_t mac_len;
+ uint8_t record_mac_tmp[EVP_MAX_MD_SIZE];
+ uint8_t *record_mac;
+ if (EVP_CIPHER_CTX_mode(&tls_ctx->cipher_ctx) == EVP_CIPH_CBC_MODE &&
+ EVP_tls_cbc_record_digest_supported(tls_ctx->hmac_ctx.md)) {
+ if (!EVP_tls_cbc_digest_record(tls_ctx->hmac_ctx.md, mac, &mac_len,
+ ad_fixed, out, data_plus_mac_len, total,
+ tls_ctx->mac_key, tls_ctx->mac_key_len)) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_tls_open, CIPHER_R_BAD_DECRYPT);
+ return 0;
+ }
+ assert(mac_len == HMAC_size(&tls_ctx->hmac_ctx));
+
+ record_mac = record_mac_tmp;
+ EVP_tls_cbc_copy_mac(record_mac, mac_len, out, data_plus_mac_len, total);
+ } else {
+ /* We should support the constant-time path for all CBC-mode ciphers
+ * implemented. */
+ assert(EVP_CIPHER_CTX_mode(&tls_ctx->cipher_ctx) != EVP_CIPH_CBC_MODE);
+
+ HMAC_CTX hmac_ctx;
+ HMAC_CTX_init(&hmac_ctx);
+ unsigned mac_len_u;
+ if (!HMAC_CTX_copy_ex(&hmac_ctx, &tls_ctx->hmac_ctx) ||
+ !HMAC_Update(&hmac_ctx, ad_fixed, ad_len) ||
+ !HMAC_Update(&hmac_ctx, out, data_len) ||
+ !HMAC_Final(&hmac_ctx, mac, &mac_len_u)) {
+ HMAC_CTX_cleanup(&hmac_ctx);
+ return 0;
+ }
+ mac_len = mac_len_u;
+ HMAC_CTX_cleanup(&hmac_ctx);
+
+ assert(mac_len == HMAC_size(&tls_ctx->hmac_ctx));
+ record_mac = &out[data_len];
+ }
+
+ /* Perform the MAC check and the padding check in constant-time. It should be
+ * safe to simply perform the padding check first, but it would not be under a
+ * different choice of MAC location on padding failure. See
+ * EVP_tls_cbc_remove_padding. */
+ unsigned good = constant_time_eq_int(CRYPTO_memcmp(record_mac, mac, mac_len),
+ 0);
+ good &= constant_time_eq_int(padding_ok, 1);
+ if (!good) {
+ OPENSSL_PUT_ERROR(CIPHER, aead_tls_open, CIPHER_R_BAD_DECRYPT);
+ return 0;
+ }
+
+ /* End of timing-sensitive code. */
+
+ *out_len = data_len;
+ return 1;
+}
+
+static int aead_rc4_sha1_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
+ size_t key_len, size_t tag_len) {
+ return aead_tls_init(ctx, key, key_len, tag_len, EVP_rc4(), EVP_sha1(), 0);
+}
+
+static int aead_aes_128_cbc_sha1_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
+ size_t key_len, size_t tag_len) {
+ return aead_tls_init(ctx, key, key_len, tag_len, EVP_aes_128_cbc(),
+ EVP_sha1(), 0);
+}
+
+static int aead_aes_128_cbc_sha1_tls_implicit_iv_init(EVP_AEAD_CTX *ctx,
+ const uint8_t *key,
+ size_t key_len,
+ size_t tag_len) {
+ return aead_tls_init(ctx, key, key_len, tag_len, EVP_aes_128_cbc(),
+ EVP_sha1(), 1);
+}
+
+static int aead_aes_128_cbc_sha256_tls_init(EVP_AEAD_CTX *ctx,
+ const uint8_t *key, size_t key_len,
+ size_t tag_len) {
+ return aead_tls_init(ctx, key, key_len, tag_len, EVP_aes_128_cbc(),
+ EVP_sha256(), 0);
+}
+
+static int aead_aes_256_cbc_sha1_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
+ size_t key_len, size_t tag_len) {
+ return aead_tls_init(ctx, key, key_len, tag_len, EVP_aes_256_cbc(),
+ EVP_sha1(), 0);
+}
+
+static int aead_aes_256_cbc_sha1_tls_implicit_iv_init(EVP_AEAD_CTX *ctx,
+ const uint8_t *key,
+ size_t key_len,
+ size_t tag_len) {
+ return aead_tls_init(ctx, key, key_len, tag_len, EVP_aes_256_cbc(),
+ EVP_sha1(), 1);
+}
+
+static int aead_aes_256_cbc_sha256_tls_init(EVP_AEAD_CTX *ctx,
+ const uint8_t *key, size_t key_len,
+ size_t tag_len) {
+ return aead_tls_init(ctx, key, key_len, tag_len, EVP_aes_256_cbc(),
+ EVP_sha256(), 0);
+}
+
+static int aead_aes_256_cbc_sha384_tls_init(EVP_AEAD_CTX *ctx,
+ const uint8_t *key, size_t key_len,
+ size_t tag_len) {
+ return aead_tls_init(ctx, key, key_len, tag_len, EVP_aes_256_cbc(),
+ EVP_sha384(), 0);
+}
+
+static int aead_des_ede3_cbc_sha1_tls_init(EVP_AEAD_CTX *ctx,
+ const uint8_t *key, size_t key_len,
+ size_t tag_len) {
+ return aead_tls_init(ctx, key, key_len, tag_len, EVP_des_ede3_cbc(),
+ EVP_sha1(), 0);
+}
+
+static int aead_des_ede3_cbc_sha1_tls_implicit_iv_init(EVP_AEAD_CTX *ctx,
+ const uint8_t *key,
+ size_t key_len,
+ size_t tag_len) {
+ return aead_tls_init(ctx, key, key_len, tag_len, EVP_des_ede3_cbc(),
+ EVP_sha1(), 1);
+}
+
+static const EVP_AEAD aead_rc4_sha1_tls = {
+ SHA_DIGEST_LENGTH + 16, /* key len (SHA1 + RC4) */
+ 0, /* nonce len */
+ SHA_DIGEST_LENGTH, /* overhead */
+ SHA_DIGEST_LENGTH, /* max tag length */
+ aead_rc4_sha1_tls_init,
+ aead_tls_cleanup,
+ aead_tls_seal,
+ aead_tls_open,
+};
+
+static const EVP_AEAD aead_aes_128_cbc_sha1_tls = {
+ SHA_DIGEST_LENGTH + 16, /* key len (SHA1 + AES128) */
+ 16, /* nonce len (IV) */
+ 16 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */
+ SHA_DIGEST_LENGTH, /* max tag length */
+ aead_aes_128_cbc_sha1_tls_init,
+ aead_tls_cleanup,
+ aead_tls_seal,
+ aead_tls_open,
+};
+
+static const EVP_AEAD aead_aes_128_cbc_sha1_tls_implicit_iv = {
+ SHA_DIGEST_LENGTH + 16 + 16, /* key len (SHA1 + AES128 + IV) */
+ 0, /* nonce len */
+ 16 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */
+ SHA_DIGEST_LENGTH, /* max tag length */
+ aead_aes_128_cbc_sha1_tls_implicit_iv_init,
+ aead_tls_cleanup,
+ aead_tls_seal,
+ aead_tls_open,
+};
+
+static const EVP_AEAD aead_aes_128_cbc_sha256_tls = {
+ SHA256_DIGEST_LENGTH + 16, /* key len (SHA256 + AES128) */
+ 16, /* nonce len (IV) */
+ 16 + SHA256_DIGEST_LENGTH, /* overhead (padding + SHA256) */
+ SHA_DIGEST_LENGTH, /* max tag length */
+ aead_aes_128_cbc_sha256_tls_init,
+ aead_tls_cleanup,
+ aead_tls_seal,
+ aead_tls_open,
+};
+
+static const EVP_AEAD aead_aes_256_cbc_sha1_tls = {
+ SHA_DIGEST_LENGTH + 32, /* key len (SHA1 + AES256) */
+ 16, /* nonce len (IV) */
+ 16 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */
+ SHA_DIGEST_LENGTH, /* max tag length */
+ aead_aes_256_cbc_sha1_tls_init,
+ aead_tls_cleanup,
+ aead_tls_seal,
+ aead_tls_open,
+};
+
+static const EVP_AEAD aead_aes_256_cbc_sha1_tls_implicit_iv = {
+ SHA_DIGEST_LENGTH + 32 + 16, /* key len (SHA1 + AES256 + IV) */
+ 0, /* nonce len */
+ 16 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */
+ SHA_DIGEST_LENGTH, /* max tag length */
+ aead_aes_256_cbc_sha1_tls_implicit_iv_init,
+ aead_tls_cleanup,
+ aead_tls_seal,
+ aead_tls_open,
+};
+
+static const EVP_AEAD aead_aes_256_cbc_sha256_tls = {
+ SHA256_DIGEST_LENGTH + 32, /* key len (SHA256 + AES256) */
+ 16, /* nonce len (IV) */
+ 16 + SHA256_DIGEST_LENGTH, /* overhead (padding + SHA256) */
+ SHA_DIGEST_LENGTH, /* max tag length */
+ aead_aes_256_cbc_sha256_tls_init,
+ aead_tls_cleanup,
+ aead_tls_seal,
+ aead_tls_open,
+};
+
+static const EVP_AEAD aead_aes_256_cbc_sha384_tls = {
+ SHA384_DIGEST_LENGTH + 32, /* key len (SHA384 + AES256) */
+ 16, /* nonce len (IV) */
+ 16 + SHA384_DIGEST_LENGTH, /* overhead (padding + SHA384) */
+ SHA_DIGEST_LENGTH, /* max tag length */
+ aead_aes_256_cbc_sha384_tls_init,
+ aead_tls_cleanup,
+ aead_tls_seal,
+ aead_tls_open,
+};
+
+static const EVP_AEAD aead_des_ede3_cbc_sha1_tls = {
+ SHA_DIGEST_LENGTH + 24, /* key len (SHA1 + 3DES) */
+ 8, /* nonce len (IV) */
+ 8 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */
+ SHA_DIGEST_LENGTH, /* max tag length */
+ aead_des_ede3_cbc_sha1_tls_init,
+ aead_tls_cleanup,
+ aead_tls_seal,
+ aead_tls_open,
+};
+
+static const EVP_AEAD aead_des_ede3_cbc_sha1_tls_implicit_iv = {
+ SHA_DIGEST_LENGTH + 24 + 8, /* key len (SHA1 + 3DES + IV) */
+ 0, /* nonce len */
+ 8 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */
+ SHA_DIGEST_LENGTH, /* max tag length */
+ aead_des_ede3_cbc_sha1_tls_implicit_iv_init,
+ aead_tls_cleanup,
+ aead_tls_seal,
+ aead_tls_open,
+};
+
+const EVP_AEAD *EVP_aead_rc4_sha1_tls(void) { return &aead_rc4_sha1_tls; }
+
+const EVP_AEAD *EVP_aead_aes_128_cbc_sha1_tls(void) {
+ return &aead_aes_128_cbc_sha1_tls;
+}
+
+const EVP_AEAD *EVP_aead_aes_128_cbc_sha1_tls_implicit_iv(void) {
+ return &aead_aes_128_cbc_sha1_tls_implicit_iv;
+}
+
+const EVP_AEAD *EVP_aead_aes_128_cbc_sha256_tls(void) {
+ return &aead_aes_128_cbc_sha256_tls;
+}
+
+const EVP_AEAD *EVP_aead_aes_256_cbc_sha1_tls(void) {
+ return &aead_aes_256_cbc_sha1_tls;
+}
+
+const EVP_AEAD *EVP_aead_aes_256_cbc_sha1_tls_implicit_iv(void) {
+ return &aead_aes_256_cbc_sha1_tls_implicit_iv;
+}
+
+const EVP_AEAD *EVP_aead_aes_256_cbc_sha256_tls(void) {
+ return &aead_aes_256_cbc_sha256_tls;
+}
+
+const EVP_AEAD *EVP_aead_aes_256_cbc_sha384_tls(void) {
+ return &aead_aes_256_cbc_sha384_tls;
+}
+
+const EVP_AEAD *EVP_aead_des_ede3_cbc_sha1_tls(void) {
+ return &aead_des_ede3_cbc_sha1_tls;
+}
+
+const EVP_AEAD *EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv(void) {
+ return &aead_des_ede3_cbc_sha1_tls_implicit_iv;
+}
diff --git a/src/crypto/cipher/internal.h b/src/crypto/cipher/internal.h
new file mode 100644
index 0000000..2b8fb05
--- /dev/null
+++ b/src/crypto/cipher/internal.h
@@ -0,0 +1,193 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 OPENSSL_HEADER_CIPHER_INTERNAL_H
+#define OPENSSL_HEADER_CIPHER_INTERNAL_H
+
+#include <openssl/base.h>
+
+#include <openssl/asn1t.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+struct evp_cipher_st {
+ /* type contains a NID identifing the cipher. (For example, NID_rc4.) */
+ int nid;
+
+ /* block_size contains the block size, in bytes, of the cipher, or 1 for a
+ * stream cipher. */
+ unsigned block_size;
+
+ /* key_len contains the key size, in bytes, for the cipher. If the cipher
+ * takes a variable key size then this contains the default size. */
+ unsigned key_len;
+
+ /* iv_len contains the IV size, in bytes, or zero if inapplicable. */
+ unsigned iv_len;
+
+ /* ctx_size contains the size, in bytes, of the per-key context for this
+ * cipher. */
+ unsigned ctx_size;
+
+ /* flags contains the OR of a number of flags. See |EVP_CIPH_*|. */
+ uint32_t flags;
+
+ /* app_data is a pointer to opaque, user data. */
+ void *app_data;
+
+ int (*init)(EVP_CIPHER_CTX *ctx, const uint8_t *key, const uint8_t *iv,
+ int enc);
+
+ int (*cipher)(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
+ size_t inl);
+
+ int (*cleanup)(EVP_CIPHER_CTX *);
+
+ int (*ctrl)(EVP_CIPHER_CTX *, int type, int arg, void *ptr);
+};
+
+/* EVP_CIPH_MODE_MASK contains the bits of |flags| that represent the mode. */
+#define EVP_CIPH_MODE_MASK 0x3f
+
+
+struct evp_aead_ctx_st;
+
+/* EVP_AEAD represents a specific AEAD algorithm. */
+struct evp_aead_st {
+ uint8_t key_len;
+ uint8_t nonce_len;
+ uint8_t overhead;
+ uint8_t max_tag_len;
+
+ int (*init)(struct evp_aead_ctx_st *, const uint8_t *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, uint8_t *out,
+ size_t *out_len, size_t max_out_len, const uint8_t *nonce,
+ size_t nonce_len, const uint8_t *in, size_t in_len,
+ const uint8_t *ad, size_t ad_len);
+
+ int (*open)(const struct evp_aead_ctx_st *ctx, uint8_t *out,
+ size_t *out_len, size_t max_out_len, const uint8_t *nonce,
+ size_t nonce_len, const uint8_t *in, size_t in_len,
+ const uint8_t *ad, size_t ad_len);
+};
+
+
+/* EVP_tls_cbc_get_padding determines the padding from the decrypted, TLS, CBC
+ * record in |in|. This decrypted record should not include any "decrypted"
+ * explicit IV. It sets |*out_len| to the length with the padding removed or
+ * |in_len| if invalid.
+ *
+ * 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 EVP_tls_cbc_remove_padding(unsigned *out_len,
+ const uint8_t *in, unsigned in_len,
+ unsigned block_size, unsigned mac_size);
+
+/* EVP_tls_cbc_copy_mac copies |md_size| bytes from the end of the first
+ * |in_len| bytes of |in| to |out| in constant time (independent of the concrete
+ * value of |in_len|, which may vary within a 256-byte window). |in| must point
+ * to a buffer of |orig_len| bytes.
+ *
+ * On entry:
+ * orig_len >= in_len >= md_size
+ * md_size <= EVP_MAX_MD_SIZE */
+void EVP_tls_cbc_copy_mac(uint8_t *out, unsigned md_size,
+ const uint8_t *in, unsigned in_len,
+ unsigned orig_len);
+
+/* EVP_tls_cbc_record_digest_supported returns 1 iff |md| is a hash function
+ * which EVP_tls_cbc_digest_record supports. */
+int EVP_tls_cbc_record_digest_supported(const EVP_MD *md);
+
+/* EVP_tls_cbc_digest_record computes the MAC of a decrypted, padded TLS
+ * record.
+ *
+ * md: the hash function used in the HMAC.
+ * EVP_tls_cbc_record_digest_supported must return true for this hash.
+ * md_out: the digest output. At most EVP_MAX_MD_SIZE bytes will be written.
+ * md_out_size: the number of output bytes is written here.
+ * header: the 13-byte, TLS record header.
+ * data: the record data itself
+ * 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 EVP_tls_cbc_digest_record(const EVP_MD *md, uint8_t *md_out,
+ size_t *md_out_size, const uint8_t header[13],
+ const uint8_t *data, size_t data_plus_mac_size,
+ size_t data_plus_mac_plus_padding_size,
+ const uint8_t *mac_secret,
+ unsigned mac_secret_length);
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_CIPHER_INTERNAL_H */
diff --git a/src/crypto/cipher/test/aes_128_cbc_sha1_ssl3_tests.txt b/src/crypto/cipher/test/aes_128_cbc_sha1_ssl3_tests.txt
new file mode 100644
index 0000000..5bc08f0
--- /dev/null
+++ b/src/crypto/cipher/test/aes_128_cbc_sha1_ssl3_tests.txt
@@ -0,0 +1,840 @@
+# Generated by
+# go run make_legacy_aead_tests.go -cipher aes128 -mac sha1 -ssl3
+#
+# Note: aead_test's input format splits the ciphertext and tag positions of the sealed
+# input. But these legacy AEADs are MAC-then-encrypt and may include padding, so this
+# split isn't meaningful. The unencrypted MAC is included in the 'DIGEST' tag above
+# each test case.
+
+# Test with non-minimal padding.
+# DIGEST: 4a7464217ea94d95668d31736693ae851eb0e39a
+KEY: 171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6
+NONCE:
+IN: 936a91d0b5
+AD: d2c0267218cb7090c6
+CT: b7b9920735d05707f3640947f30968fd28b859368f54f0640312ac25
+TAG: 0fd5c300f0bc1e4c696b6b18c7049fba428940f5
+NO_SEAL: 01
+FAILS: 01
+
+# Test with bad padding values.
+# DIGEST: 4a7464217ea94d95668d31736693ae851eb0e39a
+KEY: 171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6
+NONCE:
+IN: 936a91d0b5
+AD: d2c0267218cb7090c6
+CT: b7b9920735d05707f3640947
+TAG: f30968fda5d36eed80b2be5e31b53279d1ffabe8
+NO_SEAL: 01
+
+# Test with no padding.
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b
+TAG: 158cf6c3158503d5e540f784482988db925b4405
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 095a8f557f75cba8e2452ddf97c053904b48827f
+KEY: 18cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1
+NONCE:
+IN:
+AD: 936a91d0b5d2c02672
+CT: 7d9d5462c4f740b310431406
+TAG: f80161cadcb4d8776b38956269abd09f42858567
+
+# DIGEST: 4a7464217ea94d95668d31736693ae851eb0e39a
+KEY: 171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6
+NONCE:
+IN: 936a91d0b5
+AD: d2c0267218cb7090c6
+CT: b7b9920735d05707f3640947
+TAG: f30968fd253aaf0edf8053b0b9c0ca0b9b2739b1
+
+# DIGEST: f1efd4c11318f4558eb4a50d5a5b9b1e540f6dfc
+KEY: b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c30
+NONCE:
+IN: 936a91d0b5d2c0267218
+AD: cb7090c6171386d641
+CT: f0a8aea40ca2ba9a2145f873
+TAG: ed1b4b52ef82d4a2e5f414512abaa3a18f9779e8
+
+# DIGEST: 995341bee01fb91132d1af8394401144a35bd965
+KEY: e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c617
+AD: 1386d641b87797b684
+CT: 91d9ee5d0e6bbd3f13c762435f5a2c73d2bc9886e18625607eff26db
+TAG: 158e790822f17df79706cd13570834650b13efff
+
+# DIGEST: 73dc06657c34ffcc71e6662ec0a52aa7168c22e0
+KEY: 3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d7
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b8
+AD: 7797b684e0fb56f97c
+CT: 22942bc47874d585696e300e22001886f7de6fc6e1c0e57442d758bb
+TAG: 21fc808643d71f74063eed34636ade5b64d14b3f
+
+# DIGEST: 6a5e3024f92e29f8f3e294f87fb25572c0390dd1
+KEY: 2993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0
+AD: fb56f97c3961d8afa2
+CT: f85d7039aff0b22339c6702939871d20d8804be733efe4fd4637d06e
+TAG: d8197577d9b68012507e3864811e709d004b0df2
+
+# DIGEST: 6f192a6acc2fed00007506adeb1dd454e2e92809
+KEY: b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c39
+AD: 61d8afa22993a340b9
+CT: c7a6e129afa18060afc5ec3cc8c8d7cc0bdddad58186347060619084ff87425764abb4e56e9f85447700d241
+TAG: 781a85c4190d01bb9f1820397fe4215fba47b81d
+
+# DIGEST: 7faa4d4ec92841e45297553097f2ac2ca53d2592
+KEY: 1df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa229
+AD: 93a340b9b3c589c748
+CT: d1e4fdf3e846eea505a2bb7145030858c57ccb15ce9e6ec7877d7d7da83d7fae2ce095eb0e796270a8b9a94d
+TAG: 0b54393279e2881ddbc465f75250162512b56ee2
+
+# DIGEST: d6cf3a4fe57328e885cb10cc7088e0562c7f91b3
+KEY: a23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0c
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3
+AD: c589c7481df3f4183a
+CT: b486a616710a6e368fdafa8b43d425fcc8a9fa75131777592430af12463231fa472de20408f14db3e7cf1f15
+TAG: a06fff2a1d74ad6ca7b12fad7f7bbc7d0e51bb1e
+
+# DIGEST: a2ba1bff3a6dc3ffa8c405fb8f69c41ce7c1a1f5
+KEY: d88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be9937
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481d
+AD: f3f4183aa23fd8d7ef
+CT: 37e4da118fed51f937b7a8a8cb85d3d19537e44fef418028ca61e4d4540eea883bf8bc413743ec6a0cf0802bc94a84d7fded4b04a469c48218ba4442
+TAG: 2bcb3cbc3f1bf6c1cb62d9ea688b7845a9cfb9c2
+
+# DIGEST: e2825275a794df011a9dd0c6061de3a9eb2efd48
+KEY: 8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa2
+AD: 3fd8d7efd88503f78b
+CT: 65f79b105f63cefb347951e445f1b85347a7829396a0c81d3c1cf62471bfb7684d7aa5b88ba3a7001df506bdbcb0f18975293b45f4f90cbaff2ae7c7
+TAG: 99743f9f45b5e5fc73a8f1868552d8a4c42ab36c
+
+# DIGEST: ab656533e45e90a45a508392ce59ab9bbcac27c2
+KEY: 2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd8
+AD: 8503f78b8ed1c8e9ba
+CT: 8ae03461319d0b57ab69559037e155b10f48f3ec9d8d3839d8835eede6aac57918b5f1b08ef51a55acdd1f6e67c8828cf9064e8632ad49e99f381d02
+TAG: 09c4edf5933cb4fa117f268ec54f487c492dca37
+
+# DIGEST: 0614460f6ee128d42ae79b1dda518a0f0e4d0d16
+KEY: 0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8e
+AD: d1c8e9ba2fd6773e0d
+CT: 5dd7c1f3d9bd475e50d28d166ba8b28ef7657a71467dfd75a49e286d06adabcf1e145a080fe198e2bf146fd69b252f2e3087a5ca55195fc0e36861ae34d960fb6a6d19809a5de444db1b06db
+TAG: 948c6f127429a01b45ea4c1cca37e0491845978b
+
+# DIGEST: 629525ee366d420f18c6a88fa3a8cfecaa1331f9
+KEY: e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a1
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2f
+AD: d6773e0d0c302a5f47
+CT: d8b2abc3b5f2b5a239ba8f7dabe6a8e3edb4848ea6bd1acb861b34f1e88558ef4fbfa897908a3d4b5d5f31d90faa3a158927f4d47078b4f8d9287d3d54e1ffaad064c7eb12b230537b02e93c
+TAG: 795488f7fe52ac5ac50569ca8abadb9fc9bf3db9
+
+# DIGEST: 79b26abc71e1670444167ecf48e093d505678371
+KEY: 91d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a729
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c
+AD: 302a5f47e037446f58
+CT: 3eceac2e338b4dfd9f4840d77db69ed23ee286b522cd4a324b04b1865cc772914c8d84abbf0db1a3a2d15401759b18d6fb3b7020cca1e31d136fb97b26bc772b7425ce8f731534cff2c871be
+TAG: 5a61ecb4eb45c25a2c5868a624b266d385bf2c1c
+
+# DIGEST: 6cd5a6f762364b9814deb6e1cfba1eae5b0f31d3
+KEY: ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e0
+AD: 37446f5891d77df660
+CT: e3af374fb6f33c64fc2e4cc1e1b635bbe890f02359b6adb2a747beda433e003e30e1803f2169ff6abc81ff8095601cdff7aebae5fd8fc012387a70dd7db18e7e3cc172fa74b37fec00a3e384
+TAG: a0f0e8ef7856f3af00a1d9388370056b55b313ea
+
+# DIGEST: 2d3f449046b625672e740920da76e6cb0b297236
+KEY: be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891
+AD: d77df660ed82933f62
+CT: c7de96bb45663dfe6da2a64ffc9ddfa7c3dc63077079bd4bc2ce52fea89924a75664782a5026fb5a099ec460eb9c6d7c3d5ea383092c8f4c67a70fc499a7689bd3c0ac2b8c18256e4919e6f6bfe53144d32c731d087a809a682f653b
+TAG: 8f171526509126898bb88b1eed92578d9072948f
+
+# DIGEST: f321845e9752dd4bbc414648274459099c9e5574
+KEY: 6965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed
+AD: 82933f62be8dc55b43
+CT: 8780167385b8856be346b71b042332368067d5d9420b3793fe94bc1ba92991756523c7a8e0114af8fa7296ffef8fae01796b47edea43bdcaa8832a08e823c45c1ccfaf1190cc7fc73a67decbdf407c72d4cbd2d387e0c058a146cc62
+TAG: 4f813cb42d0e24d9aba48105a44ddc4027d8a9e8
+
+# DIGEST: da9868a42a40dc263e0a0fe4247ee859569d7f63
+KEY: 7e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2ea
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be
+AD: 8dc55b436965aabe47
+CT: 889ed4c7bd5455821c5b95a67a277a197140816784e820ad8e126b3d3f0ddaca73e3eede78c1c1d3ff5c2a98c0cadd644393b7e3c2273aea2be1c6fd20374b71edbed5658237d819b5e4e206698c8cc88319eb3cb12ea91bdbd4c838
+TAG: 0b44f1023ce340fc1d7a5e84e58aa9dfc2163e87
+
+# DIGEST: a17d268f79216e57050079ed4a85ce137f83cf5e
+KEY: 99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae021
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b4369
+AD: 65aabe477e0cdd46be
+CT: 182dc2f9f412f305a8fa4813e8c8eb7a41f9708efb516fe3feaa6ae94c89b4437cbdba7c738fb97ef9739ed94d988bd60af5359194d2b5f8a48e3f5482c3be294ae65ce803e21acdee157d436188980b9151b640bd810acf2f9fbe2e23e617b965d9b9078044dc9c2d737ac3
+TAG: c49e204d05998b2da40a08faf351ffa15a2a5af3
+
+# DIGEST: 44ba8d9c06c6788865a1dd76287a443eb0c22aa0
+KEY: 7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0c
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e
+AD: 0cdd46be99371eb8da
+CT: a850ddac6117f7b13e15c17621fc7c99f2276ed7337cde87ada287814150f8b3f3e8ba7108a1237fa6a9ddcebb07c234660ec93b8279bb4614be85c5973603568e885f5f8ea102d0621b5ba77fc58af4285c15996d6868c520f3e09ec5b6a4685266d61ed0318558a7f76c6d
+TAG: 7a459f4f5ac36d0490f9b6e96b60b2d93d0efe97
+
+# DIGEST: 5b0d95d9ca1dc4d0ccd940d38881b8864757c9d2
+KEY: fd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+AD: 371eb8da7dac997dea
+CT: f90604401a507574dcfe5d7c5e0c36c5fa65d9a8f0a25daaa9fe5c50ffb3758f52c9c883c2f85d879f26845a130044d395b58497979cf24a9e18ee1f27d1eac4d0cd994a6338c5755c74419111b2bebed645c3d8b8071a7b5304eab2c33777ede3c27758074699755a3ddff4
+TAG: edcdf269db62839ffdda253539a85ffaa23fcb5c
+
+# DIGEST: 310801f266e960f886f9a02cc9e8adaead89dd29
+KEY: de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f2
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7d
+AD: ac997deafd64b1fc65
+CT: 0f0483dd1e9ef91f215f7f9817b7f82e0b96c0d3b2996b2a1d878d0be3a70c07a4bbbba3721e646405a8a7f44347557d482d7899044af37f6df054070eb4debf7471072af1e4c98dfb3c192e956b2931967d7fdf200b464be1ff1955a658bf8615cec296c37f0989faa0d3a2fa61f38bed8a5afaa1d9ffffe3ce1015
+TAG: ffa160fa18b790e5cb64b76e4f391106f88d8d8b
+
+# DIGEST: f6998ed9b090ceb8422100ff91e5e2671a49d980
+KEY: 41a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d03
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd
+AD: 64b1fc65de39f4f035
+CT: ccecdb03830e84c5267a5b6f68dc909cafe94a1c872602961e8467b4b2723af537d79d723fc4e8f0397fe169186c23f50cf9e78af3156f507bfd38181dffcc05695583863d8a167df062cd16aeec0cc548a7b5e16b148ced8bc2a60a33a583779fef6d7160e0f6c31a03b8a0f1ed8e18415cd0f22ee9c68405a1d063
+TAG: 91f8228c58dc15dbe2a86142ca235ab05976c57c
+
+# DIGEST: af2873f1a7fcd4930f1c8a554ff271c5ee9185ce
+KEY: a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de
+AD: 39f4f03541a11be112
+CT: a06030a844e38f9e049bcf318b10e1cd2db6b60a2611cf9788f0c1fb31a366d2038b3a1692865b926196594850807895523a851a993b77e49c911f840f28aaa42b4f427eead4e2a578d57b101bb4795aedcffc58212e0eaecadf503e3b208eeb72d53072caa44677d6667a0d22639db7eaab14e537cf748462d0b651
+TAG: be85179e50a3c46d6f33a6923261baa2f7b8094b
+
+# DIGEST: c4eaa1d6c4d2d5a8d2f4d96890bd0299f1d699d8
+KEY: 4ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541
+AD: a11be112a72933c7b5
+CT: d0076d9cc2f829a33a0b1972f6c0d8c67718a7593975798e0667135db3ce31b4d9bea98710909313a4a2af88bae720963ee738f26bde44b54dd5820992569e5d2eea000baf5de9e0f76dc8e0b93244a8474beb7e922a5f30a5b5977611594af25ed35aab12a61de68f215d73173fd38f8c81e0b79a01bdc9e9182df9aeb1561aab1044da40826e6a14df0453
+TAG: 407670db42b64956d19b967a07744000f8497421
+
+# DIGEST: e9bb0964e1cb09fde5e8f852937c4d8e1605b714
+KEY: 905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a7
+AD: 2933c7b54ed4fad0be
+CT: 688cd509094cd4bbc4084ae78885afbd16845ca8cd47077450408a85c8f3da0025623f3365a65f04d281ba5397fa74b6f90e01cf138e01ee22280fb3a7d4da5c1a3b0e0507bd46636984a0b91e11492ea47136b32c2f364cdfff19625878ba42a4fa736bb277740e58e4aef1566167157411426cd2803709478bb2bf9bc0ae5c9faa227455727126ea3e9c69
+TAG: 311574cfc72a0ac74c97e0bb5e427d04370421eb
+
+# DIGEST: 659746de28fff60cf3bcaa07eb7a95c5b7d3200a
+KEY: 5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a74
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54e
+AD: d4fad0be905d41203f
+CT: 90c83b333d6aa133026223c4966a43fb67f666db06d95f45cff479a626698bc2a73c64066e904ef04800aa8151adec851a51293b7bab1ce22d3e86cd3ba3924d8c0a1253f9714b7c1add9fba2be58b243e6f7ff4f0cf9ae6d4ccd2d4edbbc54d09abb8b9e3f0b269a2cf424a213f0dde7a716f71798f1e96af75a9990279df6fdae208635849a14b4f1191c7
+TAG: bb9f94b6bb709f64a48e4e6c67a09f3abd141256
+
+# DIGEST: 170202dac332954785ff6f866f165ca62510d9bb
+KEY: b2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be90
+AD: 5d41203f5dce998f8f
+CT: 2e844cc46c1eb905c90fa857be56d4bf947ffe31238ecd92f62c3fdbb1df4c65b14acce9aedbcf6e0d6b0099023fb89084d0658af9d148c00798ba511cfe93ca2604109939a2ed5c8be6a6557f270c14ec9dcf1953014c5324bddbd19c5de88cdfd90c17b06161dc3faac0b551ea15fb282d8aa7cf37601360ba2b8a31f9f17573d43733050f46bb5c8550cf0b03a5843b50d501008db5cca395c2f8
+TAG: 5e6cefc019a4f3b8ec93016be7424d6d4a521733
+
+# DIGEST: 767d4f588b55b2593cfbdc46acc6064616f75c2a
+KEY: e02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b144476
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5d
+AD: ce998f8fb2eaad409a
+CT: 0a24641339c4667401990cc343e88c724f0973e555243627d3c207427860b5b4ecfd0ca62166228bb4c489bc843d14391302dccc41d52ab5a94ce2747f8266b38115b8fb6a290e2375beb61a8465f766334738b2a951cd2c6dfae290873a59a7da14cfd29cb6227c26502269962b657c0f50b79537546ef1f472b6737b6c56998dc94cdda0f7ce1572bcb21bf13f8dfb83fb419b741e842d675bb277
+TAG: 24d14b2d10e14d5e1ad246e841ab1ffb450fb8af
+
+# DIGEST: 27937a84ae455678a2f3c73b523d600135e6dcdf
+KEY: ae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2
+AD: eaad409ae02116417d
+CT: 8e587c5840ac0cbaf4d3c7b761f5c28c7f7643b82d6c2a9c3161692b815a912b2760865316c1632352822070ad23308530a25a3b6122d4b418692a33598c29165698c2d1febb3bbbd0808dd23aa8abb1d0da0c87fe08de7e08f1646798149dcfb6921a038974d656929bc3bcf70dafac2269ec0871d5b9868830f317cbb8246c1d9329b5ca3a5add5c7308dcb7c4c32812024670693eacf64680a4d7
+TAG: 72c154e585b4d70361baa3c19ec0350cc825892d
+
+# DIGEST: b1c534558a6ecb0ea225369be47ddfe669190d41
+KEY: 9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae0
+AD: 2116417dae0cef457b
+CT: 766ded347e52114c6f858c41a14f40865b13742dcafdfe7fe8863e6244d12ef42e6ef941149d0dbbef968a64e6a9b5312a68ad7d8cd26237d78654180272b67ee8bcfd11ffb6a07eee9e9420370f9a3db54a4d4e8613f00f1db63239dbf9127b1611edaeb6477b4978ebe754e0899fef68d398d70672da44290abac0dbc5bc2cd957e8bc85a3888e8055fb3f2edd2562f3d5eabcc00983e673b2ae4d
+TAG: 1b62a81c3d4fdfb001eae20339af92a75e0da11f
+
+# DIGEST: 774dbbcae39eaf44fc300eb00977f4e56e4dc0d6
+KEY: b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3a
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae
+AD: 0cef457b9e5e16dcc5
+CT: d3f3616ccf281682a7dba30092564afcf74dcf12ab69486ac7131890b4ccb9d6995a8f829f6a53660637f9d7dd7ccd5ab552dcdcd9cda27bbdaede240b55c1ada451855b95dfdd8fd876c432ff76efebac1e7201aee7fd3f2bb58104d45ac9d99a8d4e75ba90c3e2deb60f396e375c253796b0d4ce6e896e9b4e59fe7e8bda1133f2ba4783d915867b1d6e35f083b2bc0fbba220a3f9ea5fa78be507768e895a3e5430228a240724caae8f15
+TAG: 0e3488b19cc6f2c12b6e61bd3a7608e2b80391f3
+
+# DIGEST: 5c6b13d8f7e9f764136921bf62cf406b9dcc8615
+KEY: 0d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b18
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e
+AD: 5e16dcc5b6f25607f0
+CT: 41d5edf93095449590cc702feda28c76f9741406b3c56786ec0581d552e7180e3e5ba0816b5a18356fdbbb3b3fa8e4c8b9bae97687ba6106eb8de6598d38020b81ae1c8828f3ba7b5606fee312d8d9a0fd7fa320dc207a0ea5f69a3b323ccc4ceb0423a0c54f1a3b7aadf8559b0ca838925cea554c2f1396831d3025eb9192a0bacffd5317cd51b2a39859d584fb6ed8361d9f6ce1b2eebc6e49f017195453213b47727a664843ec42e0be6b
+TAG: bc31d69a72cba34c097cfa730e4f3b73354536c7
+
+# DIGEST: b72799f51e711da0ea2528a5125a994e33078898
+KEY: b09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6
+AD: f25607f00d033fb95f
+CT: 37540a55755a9895e547e06bd2d0965edf678924925b055a72e6c122923ff83c387b0868239bea740a4e0c430c8cc3d95c7d7ed9386284686855609854f987aefd01a304f03950b5cd12374736851a2058dd854a875b253408ff097d8f742eb56d3a7ec85228a250e890670615809b36cb0383b3ea52b4c05a6d229d637dba73c6b33721d1a5861be9f209e2700f17e1a040549b4a81425cc99023d004f1b9ecea75cd3ff38f8d20a333f321
+TAG: b93a7e0d0816db07cf4139599233325d0f8d78be
+
+# DIGEST: c2c932a2159da6861262e601fe835e4feb139fc6
+KEY: 172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d
+AD: 033fb95fb09e4d00d6
+CT: 4fb36cf192f45d7c858d792f8272a7a804cf1f11f66da95e125d15e1a7c1906a9e16f2616362db28abab333f08e06b52921075036b183b98dd3abeccf6629e94d5391e1bb0ded50e1d49ec2d9e2c08ce24282522bfbc246292b0eb1a6e13b86578d238e97de105c9768ead8d420dd49b64f7c5d12f25759fe5e6a9c284f4e66b0f8154f0919c36d5dd0fbbde50b01e78d57cfc09947066838679a433c62936f6bf8d35e3da4c43ad7cd352aa11c07d012ab097228d1bf243cb06d62f
+TAG: ba90ed5623c4d8107ac20ebc202b9637fe155813
+
+# DIGEST: 25b40da26cc2da8afe980d0287004507d92a426d
+KEY: b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb0
+AD: 9e4d00d6172e780ab8
+CT: bf748eb6bde598154952e5d806bc09dd015e0ae9809dd3390e1625a5811283d7551e730888bda40b166ca025fb4975c4fdad3a8947f50736c1e9a6c44aa927bc67f423cd0a817358254e4b7671ba216e61ae8acc961f53e738018b52573969f05d14c3c3c6f14b18f432f01298dfc981e8b6e67214e96d882517c27bc98ac00f19c81238384774e0787b541984de83ee57162a1350ea6387b43a39bc994e8d9d911d684ff60561d618363f18adf47247986c1905dcf0b3096200de85
+TAG: e50adbfd46aac83c6411ae3c2b2a52525133f522
+
+# DIGEST: 2b6449832e28e0f08469119a61c6119ecaf747be
+KEY: 7a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d617
+AD: 2e780ab8b700433a95
+CT: b7bdc09d52c63e35f3b770c1fa574693699bbc52308d0ab251cc295c1bdc60a9d9e85317037ec3cba2814502d5bae26308bcbb1f740fd344021a41b7cb01c8ba8e3ce3304c25d56a6086d7ca6c87e3c02d166d821f16aa07af7dabb0a422c62c7cd1db4d929cb6c0257fb9919ac016d1fd7dd69b444028312714c998caf234b989892406510ce40ca2c0b0a7a00b1ac2e6dba05f3ec5ad9daad89ae3ae4edd17204dbe9c3ae2d3eda07fa8a683acbee694b5da283e092abc684c3e1f
+TAG: a3e7d974c449372aafdef2b9ca879df8b55ef89c
+
+# DIGEST: 4e2f1dae39e30675c6b32f427ca47ce502a02191
+KEY: 0f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249c
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b7
+AD: 00433a957a741c9eb8
+CT: f6373678f3268213ac98576dcaa25d90a8711c01360c42eccd4e0c4a25cfe0656e82e47fc3ff9e6c007d6751ac82ebafdf70f3859b9470dc56f8a191059b21301f005dc4ad600ee8e1b5592f43f15e73c21c93dfbe76ec12b3f9142464f570089d9f85dd65df2a0092cf5ada2a34657748d6cfb8985ec96a23899b1dfefc0b726272194ae7ac2b16a8ab5b1e14ddf598066a3b4e31f5701e33119f0a5e11d19f4935815a6b6d0767ea98d7b7336f2e6b9411eb6fa94dba3fa7bca18bedb43cec0bc4cdd9fe0c81bdb7f626c3
+TAG: 58c299dfe095e4043dd88ff8eee50ba9a4632779
+
+# DIGEST: 4b779331c327101cda11bbea17702561aa8a410d
+KEY: 44769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a
+AD: 741c9eb80f2b021b14
+CT: ad41dfbad76ad8377906e900dfcb0a3eda073fda5b3a873733624657da5e9fe4508b030270d7383a2cf1d5b6970c35bd330aef18219ecfe9e3bb919b2cffea524f9a7c753f1f2533687d92481430c893a42ab2ea3d2b7bb55f8f17a42434fd6aeb4322b4967038836789241aed4cfc046c542a01b2cc36e2e8a134b8e7d6ade6de03b3553acbba4af9be7a929d7f90977251d6a4e32d9fa8af9856b3398739efc3a1eaaf836dc6930e3f33aa187ad84d824d681be019c5d97ddfeaf2cafbd4e42f9797260e2a135eb00fb868
+TAG: 7694582794ab50da1b2178b7dd95d3bafec01ded
+
+# DIGEST: 708364fadfaaf52792bc2fe5bdaabcf986af7aa9
+KEY: cfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f
+AD: 2b021b1444769da00f
+CT: b091341790c5e5de9a9fc4b8c64bc9cc715772f8e6f1ac1a1b11684bad8098d024cb5418048801cb346e8fb8a48fec71c66e4d537bf7b7ed9e1123bfabb375c29179684ef9c2eabc5cecf65b0311651960b150651908460193becfd50bd18ee57f98db537105e7387aae92b7f41144c1ad6cc12be844f8e592a225138eaca3486f3db95872944fe0e692da3b9df4395aa49f8cd5f8807ba5bb20b316a33c05a190dcb3f49192fe6b1a0394fffa2439d160876e92f6390ce0ee85e7f1d4f5dfde789bf5bb677cade2f138d094
+TAG: ca086d853a64020af3b69b6bcd6ffd9425c67c1a
+
+# DIGEST: 335c241743268f08b03aa63abf9642360d22a112
+KEY: b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e7
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444
+AD: 769da00fcfab0f5f93
+CT: c0bdff9e90f0b5bb77539901d778c506cabb1f589c446154226e5cdc1bc123b3aefb12c9df23a1da0a9652e85b4b009103e39dc7312530b7ea98bcd7a60000b9eb9dbadd992f299d297d4918e84a1dc7dfcac337e82a4d718ab924e93dc22d5f57f6cf70bea55a2fd63827cda07d5ab9a85d5c2bb2ba4d3aac391d268fc3eee30574656761239a4434d05fb280310d377278ddf813656608c894d9e54ca3927b0e32ed01bd61eca0cd7b7578cdfc197a1ea5a037b2cad21845abb91699350349cd72515dc9fc00484208d330db3bc4b5cef547e9a9a0c2784d55d8e6
+TAG: 26c803e03963518fbe921ed3648a848fd7485168
+
+# DIGEST: ae61ce3c2b1475f8afdfb1be68addaaeb6489356
+KEY: 5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025c
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcf
+AD: ab0f5f93b511060c9c
+CT: 4befd25f071ff621a072685e6569932405baa183e28849b056c564496cd966d8ce4b10fcaaf673f238a8d4519b9bd557dd1ad252c0bcfe158502b5fbb2a0815fb98d5480c28ffd52a717d6380750d5b015e0e02087989a2e79bffcc6866c7b1977d53adad2ed4100141c6f6673b25f17f7cc0432d852b3d65918fe8ced7a87414837c0618255ff02fc616fdfb507df8cbc8298063857b450dbe35e77045af2e91f54af1da77cde9b2a55fa901bd82c8df6cc2a6c5a15ff157ce013f6a035fc2c7983bc31fa37b0e07bdc7e22c357c6ea4f3dd4cfac8c3a5dc97abed9
+TAG: 9ada5ed5751c07293bb68eb6633b16c2b129138a
+
+# DIGEST: dc6621d897775dba7bacf8b7f82bac003e984b00
+KEY: 1b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d29
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b5
+AD: 11060c9c5f3aacefe6
+CT: 00b35be27f55c837a5b872b61b44832da05eb41a78dbd7d58892ef1b4f09ac96f5728810c5c04100aba6ca84b7fd30de4ba7710a606153f98691707bad0e1a810b8bd49545766055237d94094d701af245285aed50976af790a719b9fc84546636bd53ed519318fcdccbbe57473edd6830218472f56813fbb0a3ff204a5e4c7b929208753cf784f87a48adfbe1d117bb7b8e5da54ed4dfc5cade94078592f3d57463329494408ed38f4e01fd1550ecf547b2ab04bc6dffabd3cb118f02e6a3ee10b0ebd1c70457d9b8a1bd448abf7f040c72491548dada57f680f498
+TAG: ad689d9c1018cf8f871d9f32044c7a063fad1ba8
+
+# DIGEST: d2e6d3eeb6b5565d9a407fb96c74b8b3be42e64e
+KEY: 3939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f
+AD: 3aacefe61b184ad246
+CT: 54e43d3b42420bbe8471975ba2b7daa8979824cb28f519828a0e14c38929af839f703ba6fe3d519260475a3dba7737a3129844111739b75812ab257377eb9ce32ba43909e6247a31ff2c96715f5e2fb95b533dd2e2c1434aaff5bf1edd8086fdb2a565aae5accf05c88d8f29e31c70931c52f911dae835ca0772d78b76272c8ad3f5752daa25ac1afb869a8edd572f0864210fb0d7956d2669685a5a58b2c8e9414ccb9ddfd99ab91df6691b56fe81629b38df6d3ef8fb6e19c9b2054dbc5a1296a0f07bf3e2e95a23a9e9eb8de3c732dec0a23a0bbf780c68722b367bd513a64f3479520625ed8c76f46b26
+TAG: b4d965802e9faed7a6e9c027fa14ac9ecad17be2
+
+# DIGEST: 238d50a0695b1f255d5b3944c623876919f9cc6f
+KEY: e97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be5
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b
+AD: 184ad2463939ed518c
+CT: ed34a3841c9afb1fe87c3accb423db53b4d0cac02fa98b282d1aef34f7870fccb9bd13501d7997be3504c58c0efce356a90623e75eb38e61aa87e36e6caea0255e6d49275264a0fce9eb96909ec669ae0fea49a6e9a906aa979af08b8fee384b1acfd7b209f2821c4416cec91b93bbaeb4c1a027fc3bb27861b97e5de853ad7ada10c3cc14fce4545d895e37584e95c72675f7c9814c73369dc9ad574b7f81c514e2305ccc95066b793df943971e30d6472797740678594b71389a1a22ea9e15a0ac4b75e59e94b9cb994bbd1b04fd938561284025d64fe2169312dc4706dc3d9bf9f98b88bd1affd86c1697
+TAG: 90e72fac11b217eb57f992112c1e97dbd040b51f
+
+# DIGEST: 562090fcf982854158b6068786792d26d2af3cb4
+KEY: 3d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af1
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad24639
+AD: 39ed518ce97c3fdd29
+CT: a95a94ccb2aacd93f91403b637162a7353d6c2d68d68d74a5a53afe10a093a1971a4ec84afa1d3db7c28f7ec9a521eca0b91a9802ba754ed782bc8ff89cc21564ee8b86c0de4873710f3a7a03eed0e12c6beaceb1b2dda1ec9a1b999487410aaa8dfe2c3234fd6d5dd8d6bdbfdcd5c766d3687d0b1049188cf7ebe212d201c13799a7bcdac060a5ddbe3a9f9d4c5eaeb6b067547b6cb5675f9118fba865c87188f6b530044e5d0d9278261f53df2c7ba028074abed9959830317ced6f2a4d2d13c6dc9668c1aef0737881d0fcb0df8794e65fc65c9896d2366e6506fecae7ad383b7de72e77ee734778db5bb
+TAG: d962f7609fa5deca9450fb029e83172d3f45736f
+
+# DIGEST: 0c2eff5f73e4ec6371200ea4e3ed600ca22116cf
+KEY: fdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e10
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce9
+AD: 7c3fdd293d72afc09f
+CT: 605b3d1a86af6271020d5fb07275a837c16808a7f764a31ac872d85310a473e4520a6fc58f0bde468d9e916c087603260eee24f29a6d07eb294aeb4b42924b05cd003c3b6e88b000e851de33ddaa0fdbfec7648d23b797e893fd6b8478a1afc9cc18f42b229aafd5f52e0b244e5f18c65c88fb18009e32f64e93b85bd0ff735c62781a159e6abcdd96147940ec1605b26b1acebc4bc33986ba9696fb9d6c5fe9b1122095b2982f45e6bfa30804d977e9d4a89041ef918afae83daa2f70e7d7777873b41e0f80ba3d55e24499261af10f1e0b17801ad82305a6b29b8e02413f36803bf4ff71c09db4ec2981ca
+TAG: 8ebd9da270b677f95d8cf6683b67a44f53ed0f75
+
+# DIGEST: 7e81f0c3bb2f9c2073120134be9d0b1d0521989a
+KEY: 249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e8
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d
+AD: 72afc09ffdd4f41963
+CT: 60e655a80816b8ba9dcae0757f8f4ab01084748cd772bbf3c12b8b690c92b90b6a31372cebfe4b4aa961febb94942d80eced62b60e5cce3b2525231db333fb464af259ab5b1f3470d3bfa56cf68b8b859c168d8bc08917db3712da5b2a6a4e5f69f1565c967af6e6f58765ee1b410d4cdd5137489047d18cfef1b103e5021b68b7413bdfe7c698e5deb453aa62de38df9f401bebe6c466ab2451912078d2f0271c792b666f3297f6eb414fd267f61d2c1a3cb89e5e28a41a61388563a38bcb1a3412c0b770831147a1d93c0544fba45116622758e30718c3af24175ae1334dcdbe68b2b2c59fbfcfe14b1f930c56fcfa7ea933ed12b8bc7e9a23c165
+TAG: 693b0737d6467d92031b471582c3c2f60c7e815d
+
+# DIGEST: 28a454911a3ce17c0248d2f535f4073b6b092f6e
+KEY: 2e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffd
+AD: d4f41963249cd299b9
+CT: 8afe66ac7b8e1729bfb8b3263421ce64485ddb0afccc30d48934e126cf48ede99412917710eda1f62f32f2cff868abbecdcbb6861ac5a95e8f43aab4abb62dbdd2d045b3cf1c3b6f5cde94e4a55dbeb3971cc2dd96479c8c4ad3eb3a523b66410200848e8e76d2b43fc654deda360b97746904dfa48897756118678cf0b7e7547b879ec70c120d8d44e268f83d7af4adfecb6890ec6aea24e2154f51078b821057ad5081d1ac107ec3bc474e59817bd00495e148545605e41e06cf1e1527091412c130d412b083b3912d3bd0a8597b317054d0e40ff330d37ea61968261fa97b8f54893e7f61b0726ddc62ff7519305c8bd053013d3a1ac32acfdb40
+TAG: e25247f8710102ca8c344160ac034e5c75e341f6
+
+# DIGEST: 179d0ff2661ea9bbc7a42df1b3368bd48c176a91
+KEY: c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a02
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f4196324
+AD: 9cd299b92e55ca24d8
+CT: 1ad1da12e4162e0865531e146c3c7c740068d820abb2dd3c9814614acf8cc2e250fc3586acfc96eefa1a37c5d87902ce6a4ac195f6a6f966b59bfcdbaea6f98b794287f9c8da3185eee6d6a27dd65f0404ab35238e29a70723a9c893caa348617a2ace66d23427898f75f0e52ac3dbb44a32f517320c82c845a976964c3fbfc8cf674e9a2ec4a81a32d8abc5c4474785c317723b6a2eddde810a7fbacb9a452e5e933613fec9c72b46be999e0572ddfbc600b59adc009b84617fb862bd0c170e369737d4d321cbd8942f5728147a40521baf6c70faf17d8a1b51b99938b325f1f2fe74d5e0bc7697cc6d7716e3cdeabcf0d01a208ffc9a735a2ecba4
+TAG: 65414b6ca6e64048d30168e6c62603338448b8ec
+
+# DIGEST: 35f3568ac38767bbb0464106b32622a101523d0f
+KEY: c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e
+AD: 55ca24d8c078c49f78
+CT: 0ac4f333b7aea61acacaadaae5fe3498598a54b3d2e5733493097cea25414b4da594075bda7d1792378090e27982f123299bfe05bbb6aa8568bdd52e11d94ec59d377ba0980b926ed03d5cfd521357f5125cdb44b3bff564fba3997c886ab0c6625395a10ffbf1baa01b93a8c297fe2d0f70ee361195ecab4a846b0a56014c003da3d4aaccc60d72ffbcab085efa19139ccb613c45d2bba0c2fbe85a980b9f5b285fd27179390d2a99e3bf09c1932753c274b1e22c6554e24e647116a2c75986d2723a5643b20be78311ffba6568c905a5ad51881e83fd886dd269503d7c5c2f2e061312f46f961248d10d23e3ffb288c43da634203cbde6c253bf9aa49865f9545dfb09724a1a090740b183
+TAG: 6e45dcd6fd9e94c4b022b52421dccf0c783b0aab
+
+# DIGEST: 720ba4f4eaf71a85873c01a80fcbcea419d22ce5
+KEY: 025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a7
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c0
+AD: 78c49f78c7e713710a
+CT: 306e3f7c91d47fa6a3de3d332df7574e5821d5db45a82b54f511c0e5f474fdf0f7cb3fe630497b6c2e3f829a2bf64eb75edb64ca8d799880991132119723f0d99f7b67763b70170b82cf539aeeb130c1dcf31eabf0f0f23f6e758cda367f178ba0e8912f6f33fab716f1c11b1cc5b196e316fcca2fa669886a1ee14fbf7e8f0aa74ee9da7d7f69f646fc880e888b219c8e40a0e07f7dc02ffbd877671a6b6deac1bdb58ab312fbe0cbf597b583ed58c4858a696ffa544e9353f2742c950d682d544713df70d6da303ac80a6de1fbea21811468d715659677366f3cafeae487a1e8a4b7bfb2a14068ecab067714ad5c054baeff16d367af6612ef57577f8f72ceb534beaaab24762a922af8b4
+TAG: 4879befe22c40574f58af91626859dbaeb3b7df9
+
+# DIGEST: e531dc2be28c8985a08dc53ed098457cca032116
+KEY: 1d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b38
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7
+AD: e713710a025cb8b9d7
+CT: b32e08b56e5b06463ca2fa7e91549ce7e59ef0787043cffa87fa2b7a064a88cef7e324c829f89aff1bd700720cf271957bddc392ce04306c93cfa9e00e178f067bf689c34e23d0c5b65ede2ad00f1302d1b357bb8142516c6ded22563bbb89dd4678cb9166823286c6ff22e41cca350718e2ce77881e1b15139b3e66a3ad0b400c5a41efef51437416ff81c25ce20fb6979a1e696f6794296049420497757d56af9ed00bac106932f4a70331f9238df963e3c4704a92aa8126428f464c9665a1f8005c7ac66468de208c46526ab0e075bf141022fb304a85e382b19d08972d6729362976d337416f639aad1912c3326a79e9cbf5159a50b5358af208c346ea2f9410d36d609c3f2fe83407ab
+TAG: 0a61630a7ca92c58159c4a1c6368bc6064f084d8
+
+# DIGEST: 87828be40716e1acb0ce876660045cef3bbbda49
+KEY: e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a02
+AD: 5cb8b9d71d2989ab33
+CT: 58305048a89a282ec8bf637b4ae237fb9058dd3a717e740df06270cebd047b316edce730d8459c51f9e497e625b101617172a3a779d6a0d2e749a8fb5dc214403855219c7ac2a23023dddf4350127e17fe0fc8f7b1a542813c1282d5b9a794390d3fc7bf55758e1fccab70be4189a7d10edf46166744a64532fe59ca99c48301cfeb7ae4442ae1a4c44e82204daf9f3feaed9268ee15a7f08bc174de7cddfb1fba817cba3f33174aefe46473f829d18eac6488afecf461ea9f48173e9e17967bf4c0d7a69e6fc2dd6c3e2f112e71e09f4f69669a5d9fd94691ced1fdc5a99e47f0d7a63d264acad33c997891b7e29e80e66fe7cc9d0813864803b0b912949d15a8e751601d48f62668aa62ea4501d7501ee11650542f8c95135fd2a2
+TAG: 9aad03073b5f9e16b0819fc1bee06981d7df4e97
+
+# DIGEST: c413683815bcbf3858fbb654590434d5b9f1eaae
+KEY: 3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d
+AD: 2989ab33e978c4451e
+CT: 5f186db973bda7fe447606fe3416985e7ff19af8a7d35870c8c5484eaee4377af9143ee54edb9de9fe4a7599ae151b41213139e71dc40865386a28d74ce6d1dbaf9e69b63cb93f4233a63d2e598c12192f56bfa1e2cb547971b725a21c031b27e2083fd0e75f3a6bd63920965ce19ed8e8e20a1cc0c692a3b93a869b0adcfb4f106b106051177b7b5dbdf89f7ec7a43414e80d6f5efe836c722b43f70f23593abd716a3f773f6b73bb2306981e83021e4a1e501f46d1bac175306eac26b9af21b94b6ca2ea4866e7d9e9e73d54f90c7107951b275ca2bb123471223d62f34221915b1f2be0ad1a7ee88553ad753ab102604727df8ff859ccef1de1d5233f0aa9274b924090fa05fd2df999784fe2ec9a2ca0dc982db2b50bcd4aac25
+TAG: d9a786dfba3cea0b888df28e5a99376a96f166fa
+
+# DIGEST: e55813b42aa337183d3c091b9f88f8e37832692a
+KEY: 2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e9
+AD: 78c4451e3be585a29a
+CT: 25e850730513fbb44ead76fd93f55ff6bfcff1acee2ccf9976211a91980b684151cc4aeb75d6355d3aa7d4946820781a8bcb58fb31f1d7c90845ef3a25cd7be562c5219b110bd658fc1c537ebac8241585e21a6419508983fd7739d5f26a113c9ea66139819ecf4f1fd63a163995ce066d9ad470049574091be85c41b8e96f7ab01159089c47ec90be1f656e5269af258c4dae3e5f95b0789ed23b617efe319494a678ee26e118e67c350e47807fb957c68441eca8fc0f709016c9120f82bf0fd83b0376d2db086998e0ce994454a9b89fbcfc2ceb17c8810b113b1ba1211871b528c0279aa0a09aafdc3bb69f7d37e21d762dd38cab926b3b782da291fbc6d9108ea1e50c1dd92ffae215b270219748b9380f25f20f81a4be8671bd
+TAG: 469fdee372ff7df774f681fe92d685ea70ee220f
+
+# DIGEST: 013c5a98871203f5494bc2d6927d15ace1e719ea
+KEY: 1e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3b
+AD: e585a29a2af12feef7
+CT: dc8e8fe548a6402c45ccf78f6e839f61521a0c2aca5f3c352393d9b077a72a08826f47a170a28ebf098052424b76229278ad6510d3242d2370864a716e0a763d8f1dbc28955a997031a7f36f0f546af1b50cf1e74853a9cc95b1d35753caf4e71944ee0d7822e3a45225666437bc634f673f40fec822b447d631f3e49eacf0085d54d6f289f37793f9400e37ae3155fb5a8763e91612746c44b112924a34f3ac4d96f11afe2fa132214c7483698884c6814635ba2647f7f4bae78b9a0b3b291448a3c6ec9e644ae011ea9d22e66f9e3fede1be4b1edcc77ef7d76146b1746c5b5b940e4378a16cb269b910fe06d580704f5908c2475c42f8bca3684e7ce22376c7fff7ff481595c3ffa912e567289e99616625d89be4993b3a2dd5a1ee67d673de806371d8e3830d4c980f83
+TAG: 817fb21f9513cb10afa68ffccb25d85974c2d64b
+
+# DIGEST: 7f9e8085dff06dec7a2250bcc60532aedf162762
+KEY: e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a4172
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2a
+AD: f12feef71e1063b0b4
+CT: 8cc3fb65529ac15824db72dbf63c2f26627579a62019d4b136f8599aa6661f19eaea69b4a5b2a3fb48d69fd4d14c4237e31d1d4e28fe4e7c57d2c1f68c418bfe65686b5fd091e80e9eb88ca2399749e531730ba59fdcdd46cd203b6b7e997a16d0d461b2bddda388d5467eced67ebe132c80e2ff85293cfcec59c67e03c6606c986ae55e0d74678e382985d9fed8ffff01e72031051e91778a9b27db9a6819a6b2adb717985c40078ba3de1cb0409186412adda2754580c05c080ee7ead1c18e3cb578f5e70d572cd2699016fe64189666295bf78c09bff6d87c7f7a96c49272519d8766eedacdb7bb3ee39c2097fe9bbf7a15a4fed737dc0bc76a8ebe67663c38828faf5a1e88b461d8f4178ab9e6af65f8127bb0b116e68db61931ce1351e7b166f171bf79c8bc80bae4b6
+TAG: e88f15450a7cbd7f889e989c6b7edea5fa8ec727
+
+# DIGEST: 0254594a43b8c9b638cb456593750b3f8f9ada22
+KEY: 04bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e
+AD: 1063b0b4e6e8992003
+CT: 154d22b4a4e10199334fca00b50abc2eb4ceb36e3f6d672c68c285d1336ac9d94af9f7c0b642150f1066f15a4fa2a11379108c746510e1b3ab7089dbfc7d0704f6e1aaf07f9877a04fa13e241ece9382c2964e00ae2d16cec7aa97d9c5462d28c07ead215a0e57fcc0fc62c1a2a0020198ac5373f7454e8712d08811e10c7117d17d3ac028fb88675f9fb7585dd5fd4a17cb163c1f1a7550ddd9058967a8b70e6f9b049aa195a4caca88cf0eb585778b1a3d28686486c7f640e74d41dab92ae3e8f0b11c4085bcc928d658cff333cfb786b890a4f4d072d8adb2a7423670b20fedc088fd44ff5954f641179b577ec4567aa60fb836c8b6bad381a3437028f4d31afda51a56cf047812d78bb3cdbb440448ecd0bd8e7a8e409bb992f139cce33e8d9896b8d8cafc9f6e084313
+TAG: 0a7752e00e329f2062de42b275c5d215565a0dcc
+
+# DIGEST: 15059d32a3357610e64a48c19dec95d256455404
+KEY: 2a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6
+AD: e899200304bd350813
+CT: 76800b5422d1c8b76798998ce256b4e36e6b516eac77a664044c34b81f6b6733939d54cab7d104a31d14b7d0ecd87af242a3fc80cd24b86427a6d74c45cdadea04fd9a59369952e0d83e668c6b65cfb8b06c8579d95b424340e89b2c5ed6e8f41b3d59e19be86117e8b53f8757991ca8291309d17431a51296d06e9eb19c2a718c6a69c53558795d00989df9a5bdb6bc8844358b6d1d8fda0dcd648a46e6cf2c13aef90540fcbe3bc0673b41d8ddc11e2bb74c3b17a077c6d62ab7f2224aaa81271aa0ccdf997b32304ef04d0c454c227083c999f9ea14cc6c1cc440ae1ee083e1fe6e8ee07d7e7bdd0a354d6b348e0952a09bcc8a251eef9075e18ddb5db47c80890552a416722f82db26425961816149c4d091db9e749b0453b05bce02520ec585f730498ebbc32246acd90032436021675996d1a45d5d2900299b
+TAG: 4bb90cc5e0337e922cea6cd8bfd6841125e13a19
+
+# DIGEST: df289e1d102b25ad07e98f430cdd24eef513f8d4
+KEY: c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a0
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304
+AD: bd3508132a027d1ff4
+CT: e3ee0b719f73bccab6fc848298457fddee3ccb2ea8996fa82a3f8d5e0b9eb7facad873a47c572edfce0bc537a3f1ac4cf91eb748a5856ecb419dc16e1fe9c6e28e39afa1be7ef2b579b7e477fccf61e51a942d0cec83a8229991204107dbed7267b52ee160285099e6a709372823d467ce651cdf6425178d1bc3c76c99d3932eb458745b63a2faaf87efbc338da19342d202ad4ee05e038138823144ff993bb3dde55ff0fa86d039ba7145c45336eff7ca66ef984e86cef017a9e941399dc1c8a050c17049bb0bccc1c029fb860fc68798fe2e3a27224f48728ddbd25dde87f74d63b28ec02e77bd78b22695762b91f4e79cdab886871393a5ad2ad27f3a7b07dc57b4b9168086c9d785849ed8b4307e551dd14c4bfb367869ab1526e9a32bfd0a071abb2edd065a6afafc12f0a2196952f79a77dbd90b461572f548
+TAG: 1ef251477dab7c9f852589681385942ac3d00dc9
+
+# DIGEST: 3faf5b20ff66fd6583a2b62901c1ccd798c0e9eb
+KEY: 57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab6997
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a
+AD: 027d1ff4c047b3ef4f
+CT: fa6e8219de9fd33ec48f71106a0bc5299d3147b5a3205f584ae899405c8d99d544fa5104bde77c1a17f57877e81ba030707936664fdc95b1855a3303fc272001c89f9881b6e01ab7e1f788937d31a94ad005f1fade8ab5c198f5d0229a2c83b793501c96a6565d75532afe9cf50129492f6b1357d4a212b718c70ee756d530fd1f0ffbd43e41188ee565d963b90d427cca1a0473aaa382f1a72a0687522aa086219209e3881183b2cf7991b53adce8f04c56e0e7736f4584c5b08da023d94cfe5b124472ddd150091eea988ba4f026a8e7e05d0b3ff0aeeb3b443f4136b783802e8645664ca2795fc6de05783a60b24b7fe2adcbe26262aa27279376b1199600fb1bfb32b8a9f1fb03b44f8968a063f98728418ec097ffe1e75e9da32b48afe2487c48a6e1a911da4b1dd70e826fc3fcce610c12fd24ec0b6b4db75d
+TAG: d27196f54b33dc60e7a92ca82fb3faedb0641994
+
+# DIGEST: 2a1f12db7c66ef374e510b2fee81431a4902fd8d
+KEY: 4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c0
+AD: 47b3ef4f57a74706de
+CT: 803d8d67bfe35a42adf45278c408e6a76f2227192b24a6dff6c7d01de04ac2d2571e3979db68080faa58b0c6fdbbea6b9eb6e55ecf56c040739ff4d788e1dcbc01b53808c0fbbf063da5502f15cc3953faaf039cfcf16ef08c97df88212ef25f5e66e6faf1f66feb5b533a3627a59a14b1e4655056672a8212b5bd89f832c40a4b5c67bae2d19025648ecbc97da85996d52f5aa652c2ab0d8f6b96898f87f34ea090b311d1c3e519fb513f989f9338b54e7ef5bccd076e4f16c17516ead02c75d108d2e7c3bbc6187592ab2b2dbbc8c4797bc65950fb67be129dc86f9f6fbea8f78109b05a113b5b318848ad5b1e2a91b76263c275a4b6026e89f06ef7fefc1b105e6dad0823461af8be8d6e7abaa911f98aaf61357093189eff0fab83832367ec42a6742ce7c6b0f516bc4d5c9bde79da59fe0f1be3565e48e5b274
+TAG: 2a97166f515983dd839a6f3bb6a0d92702a6520b
+
+# DIGEST: 524f8d38ff527d6ba89c51265f6a55211a443a04
+KEY: f164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57
+AD: a74706de4b381c692e
+CT: c712fd90ed4cdc005e86c2787e247e358d72847974137a0764992010db9420563a3fbfd7dcc1193f80b5a07ce846a6dbe6c43315eacef7fe26f414ece76b711e92425ceafaa408ab834235f325a54465a2105a82f0a36970b6512330567fa4d408c47aea6ca694ef66f6c5406773990463c79dfeec84da60a56c8e142aaf5a36a8fe6cac983fc8b7ffb289a77b979fdb4cb33d1370e2c80f623471160cb10c6cfec048de7c138d2b0ec74fdd14123b6c35edabcc7234a70cd63d5d571ee3a3e8db71c67be5a466455ecd1b40e90415c0128f7211817cb40d40d746b5e02d95346e8855e3313ceed8064c778a1cc671b3f655c45a21995888318be9ce3ca712c6299ecee3c972ce8e972b26e69f91ae98aa251d9cc047f7be5a7cf4442ff3c3842de17fdfab8b714b49b9d86e7940299a7381c8344e3c2ab116912758d398b14d0bd7fc8b827e03373eeab446
+TAG: f9e802d10ae6a6646240821bb59b154b0e0b44be
+
+# DIGEST: b50c58268b989fac3ad8f6d25a401211ddc5cef4
+KEY: b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870d
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b
+AD: 381c692ef164101b89
+CT: e44230b5eb0d9d7f9893d444866694911cb7ba6e4bd4133f9b2ddfae8e1e9a968e130c5c606c2102ca8ab58751060aa1209ae64cf9595d0cc993667f14d88a2f33a071bf7c81487d0d5fe5a4c24adb662079a3d1bc542cc8a996e6e43a767e23579d50caedea812400fd64a6968f37021f8b082d269af1c3c152b22a54730f3c2408813b39af7b8f6ed29d0df502900f3f7b7fae51ceca9bfdba2c651cd413d7e288632c739d045e253a2893e517352e69ce40da3a9493d3ba8478833d7b7b0d62e6503ffa83154163f0089173b381e4d38575fe9ee745a060eb1fd923387b6180ccb1d1f73f4b2d9f07ad597423442789cebd984d3e466d391389da356476ebd15c3f8cd6eb149bd1f3e266cf02688f923094352ba0870fba92dec5769707c04ae089884e3796da437c964980d4ce97a88f87ebfad4388b3276576f16e20877d5e25e7c022de687eb88e719
+TAG: 8afb9aaa778428724803d0200fd2c2aa5e56a737
+
+# DIGEST: 7337152aba55f41574aac9d678dedcf895a1fd7c
+KEY: f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bd
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef1
+AD: 64101b89b476f72b27
+CT: 26a204d8d3a7d792195e9d29788789c4c5813f73a3f72a39a8ab0584aa7654ded987429bd3e7aa49dea71e5ee220ce4a82b04108965b5f64c749133e8b1c5544e46d1ffb2b8f11fdb760546d1d53ebb6d6ef9444805a388b19dd032408d564cf37c7f54495a83576f555e0fa4fb9ff1d285c0ece6f5bea86e50f40e2804337f1c4d1236f6447c8100764c12c458571f0950b1a516070a106f94148f9df78ef1d1550fad379185fb025553a2632be51af3d41498d431b69717f64f99bf3ed9420b1903a43eadfbf27af1e7d9a91e8799ee36b19d61c77d4939a6b60d6239cba57329d480c4815089bbbac2bbaba566f72b8dbab821e5ca41c5305366ad6818261042952703683360c740f719909239118e108b7ca9804a1c05248479b7d25bbd94ad5eededadd302d11d7bfeed257bd3f842e63649e6a038f5c8352b9330410c58ec1dfa8c6e1b5241832aac6
+TAG: 841bc5f387bfbb0821df47f87c7cc2819e7c6479
+
+# DIGEST: 6578de87f977f4cd4c5d6dd6f6f99daa338ceef4
+KEY: 67cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb105
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b4
+AD: 76f72b27f06f520c92
+CT: 79c9e7f23613ad4f5a4481634c0be510c6399c7ff4d840286b3239f8d6b819caa0c4e7b3768e4e91db4d9d6a191debac42f5f80d84c7857947f8a38dfd16f73b107cac3e128e501daa710824df1a4c56b5796630fbb5445cba50d676e192c47f2d9becb1de53c4ad0de8fab0ea04737f9a43b9636cdc75cb2327c5866d2058fe905e48ccb1996e4ceba984a077bbbe717039d8cb85c6c7ffe51d2301b527dab0ef517fa26035aaa8797710b7c614f56a0d2d342c29e482845e5829a75db3331ddff5e7f5a6b5778e129c05dc0a49a7409d68fac05c2977069ef951fd4f337455c5ff94dbb225ceaeaa51de287095b8760a81cc037ca3f13bcf31cb5d66a812abf4b3063391f0139086e4761567e0cdfee7c94758be99b023fa2351a88a050c5b9ab057129a5eccda057a60971cc8d5809becca6dc6eb500ca622281972c77746384343025bbba46c0471d812f5e5802d95a34cab0f45e2ae5c2a4991
+TAG: f5c55a3f956a8e64e5d3eddd0cac64c7c7192633
+
+# DIGEST: 38dda49f961e8d18556e2f4cc30812a7e17d827a
+KEY: 41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a1
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f0
+AD: 6f520c9267cf71408a
+CT: b9a705ae374d3307c38dbe85075b03fd87684950b301553906633f02b82494149b0ba8b85992ebe95d4ca941851ff043ac8de57c4f7214029b862b870a9058fe41fb26ab7d8cf09a03330516d4364c7b47a3ecc37b341be35ed862c839cba7ecd9f629aa78ea2d6f139c050abbafc46e3ee0a61643f83ff9eaf261217764d5e4182c2c7435cc74a2d880a9d9c94397855b05270f27147cfbe976edae6a5c98579e34bdf987efce69ce87d498c280556e8cf46ea0803449b38659ccafb449dc7302412535ef31d4727b9ca780b50060a1c72d5c71b5ff4aeb9e0f4c3fcdf2e5f020e96ba88d61f6f5fc29acaa130c3897b0fce71b67daba9510aa737ea8f039c2effcd1f6742bf1d807a37d556e22e16d6759a456a5fb80f1cd259e0c40aade69291e4dc1a1281f91817662e56a6e8a30f6008d2db2ecd648e8983de55a61c25a673134e3fd27d17c367362759169cfd62b614b2289805ead2c54051f
+TAG: 6c8ae48d7b6b04ce4d2b4d6e1f46ba739f2d0499
+
+# DIGEST: 9a4462e5c302d0657a599d31a78f3581e4b1684b
+KEY: 877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095d
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267
+AD: cf71408a41729bacb5
+CT: 7e3cccab056aeacc8baacb254b7363b1b8f29b89616ff1e085d9549a3b7c4ed3c08b5ff539a656f0b6a08af40359dee39011cddaea181aab7ff8bf02040db0fd37cf78e1bb1fcbf2ad7db294b1a52534ad088b6466c15fdca345f500581982c8c8d6468c4f65a5d03dc8ae337279605b883140b1c6c5c996c7b70b6c56efa01d8690e1aba0f5f2311bef4b9ad10eb41aef328064bc80a4e1a934dd08039e989fa8db790629109bc86b7e9124e39a160d3b4c89c14fb94ac44fd3fa07ee6de892c022eb36e486342192f1b4ae79661f3eab3ff565a455c3df19192828d9f15fd5cbef0e45afc2a9d46efefe037534e82fb015da8db17da9ab80d40e3f1544a40b83cf8767e1882e5520ef46f73b7a7d0e1574e0d176e2335ee6b8d4b9d75712f51259c5fa9f260b2d8ffc3b307c592252f97524b4a80bb388531b1aa8c7359b805c04d42924bbc4225720ed67c1776d969cb920aa221821f9527a4cdf
+TAG: 2e2f6b4cff873227806611c39e755d6f4507cd3d
+
+# DIGEST: c96066fba6ca75beaddcbf7b6bf1b43b2a7b6353
+KEY: fa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41
+AD: 729bacb5877e72cdfc
+CT: b55e0f831a669d23feb4e6bdb8ab31374cc15f40f3687e7f0ac46e5e2326204ae0a6c3fcffac2dd19655cbfd9b8c61f07857d59c7cead206bd572fd16801fe0db5ac9f6253eb1e74ffd8c628572fd831aa19e3a231be4f8b1a03405832046c2135113a7ddb93fd850cde55be920e977eace1e3dc9d850c0766084ffef0e5328d10e621b5dc3a1845546ada5e1b230722bb167fbf6639f26de5908d08a02ce5aed467d342bc784226df88844f4c888d0f1b1952d54304d987661f4e05c77cb064055551e2e50f48c36e16edd9406fc35da6b7decad304405ba7549882e960a87d72631aed385cab4454bf59cee68352db32e19bcf4912160a500c27da10ec5760aad09bd109c528f67f67dbcf9de8814f940329ea7bf50e1a47ca7bc9a2e62f229f00952360dd4709a6543d49ce92f4427f00a94c7c8def47b633af2bff6954e7550728b0498deaa007ad865e4320ae07ad22fd61653101bc28161ecc5e9e00f0f37ece30523a61246bff0932
+TAG: 10fc0abb7b0b62a9fec2232f804365f467e5563f
+
+# DIGEST: 0cd3dccc73f4bbfcc3c62b4638bcca5a633a2b37
+KEY: 07a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d50
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb587
+AD: 7e72cdfcfa76aed067
+CT: e3a075fa77212e9872278a3feeb1b4f9be63d2a3425f3572a205ad8f9241eb15421a53cfd667bd97100178882832b6c4c0ab87d277bfb2e1ca355516787427fdf34b05b88008aa0a7539c8055941af184e70bc596f7d9a09a3671241f8684dbf076fd38f16fb8d209f43bab026562a74d49cb8b02c0ce252b16957fd09e8fd979fdf00e0d4ff0921f36d87c7f011b214ce6938168933d9038ebb5e06d78fce4409e8e1ce6bdfd0cc836552ae524b0f02938fcdb6e43c373f5e0b60f9678ee788ba6c453377942de41730e83191c0db43b3779d1381a31fc5bccdadb04aaf2970f281d5c5953faba0e8a7ccbb5f9b7cb59bc252d1c09c2ab0f72740c82ebca6e4fbdeeb0a395d9261fd3a33ccc90b35b6b58a77b8d6cd67dbd09bd256268aa57122bd1606267da63e0a4c2f5237716d8b705d0e259d2b3ee4469d97e05f44891dba51f6c8583fbfeed8de18389afba0f7448ee132978632e3a66933ade488ea8c0ba864e0a9e21d18caedfe14
+TAG: d5fecc7a9200f91211c4b111840076f5b76b2900
+
+# DIGEST: 61f7a437ed58c4d0c66997aeed34757d4f36926f
+KEY: 699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa
+AD: 76aed06707a07c3dab
+CT: 6319f0bebd865b4cb2dc2f5a4260831fe1c1dbec9881ae34dd981ced02c024a599b934f3605e49799080ff83c0a463517be7ec06bf3f85ff42e9283208dbe38090d735c59a879ee558833a9f1cbf51d39718d74d09bfda726bad568c06792c44c9108f8b7ac7602dd3f6cc0369a0a4c13e88f6e2f3be45c6e7f38da0c08f6b6d74187f4f3c422b58b12116ede6c8ab6781f3fe5388bb98fb1ccaa0c7482d5b2455f9910a47e39371795c037e22f5ab113e9e160518d2a8cd406af416bb59de06e062d340f32d0eb2b10673bda6e151c09e5c2011b39d7f850b972d4db419973268fe7bbbe8898c43c09bcf75bd8dbccffbb9b13c032084f0f0ff57ceac4f8e92a588862c271bf1df0fad32ca8f6552a11317c683accba791afe33c13b5ac2513a0b51fc484f1dac9b6971fe7077f484bd9669d92d6e0f0acb2f005722800590951bad06fad379af6b36ab18aa5cc2dd50d02c57fa7ffbf54497faf041b123c695ee831bc039761cf33e8e10d
+TAG: 32dfc35deb4fe29345ea8a3a55bfc78a55b0c95d
+
+# DIGEST: 9b062a7f63d081bc4fbb8cf13db57ffdb7d113bc
+KEY: 2eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707
+AD: a07c3dab699719fe88
+CT: 128223f1076a84eba1348c8d2b2d7c01a760817c24e89f27a262474add983297dea63ad25139f2607bf194a8d44cd6a542486a81c35bbfca64ee3181230684c33daa5f1e7e32e3cb441225a1fa40d2baa75151324f1237fd8af7216ed9e8c1e93a0eb1c1f08ca71c69fd5792c6eac47a13f2faefe615b6f89dae0a1eb830248c83d6426c8638877cd44753e40ce05ee149afbb98b0cfa97ecdce28eecf0a22a90388b0496d6fb8c7aea5ee951e8c8926323bf2ce35c3cd9ffa75dfae779615951dc037784037d51c342d8a9916ac5f0d61fb1d44367b14a06de96bc820ba07b4a2f2b7057b889cc174d5a50744670d1b4d06536b81c804e44e26dc816345df9da27a1602137ba223ef693d7e3b27de924088f7c871ce4d1795f45bf0b2592d4f8c264a50df66ed1d761fcac9e4920b73085bd3b25a93f39b2f6b64a4e5a81a8f7ccb4d5adacfa28e9a046b62306dce758b03177b126977bc178a59bf0d974a0114464c0c1ee8ce042414886b8dbff0d714fb5097c16c208b4fe6d99f
+TAG: eb1062b39b2bfed2dce3aae0aa8344ec7f88c39e
+
+# DIGEST: ee4812a7dc3e037844fd9c35770734168c4ce2ce
+KEY: ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab69
+AD: 9719fe882eee2fee55
+CT: 942972c32cc84a252ce6188065ea54e7f607b3042b98d8ae9fe723a01fa60995eb2da39844ac491750df99510dd46d5d9d212de3d507be8e5f8ad196117fa1ed8224e3cea3630a08955fef38a94b9aa402d5c4a88702d72bee078ab8d5a9e4ac5be9b741fb0e9bad9293e1fa4e5f78bf8839abda0393ef14d0ce299cb913dcd2cd3407cfa816bde8ba892d20699cc2e52d52a0c90eef4f106cb93df5910423c5aec6d02ea502c85445771eb7b3c2a196fc729b1108e6596e502de1ec94a5481dfd78272586a3b30a28e759514de18f883eb657072483c49f3a4189c0ef5e4b7d442a66bf8f2c49753a3072094e3edd8ea99642a3a4b477e36c3fc7075931c8abe234d30ed9e54d971ab4d8c1331a157817f3222db9bcedea9040d937d454de48a854623ad459721aac92e71f27f5c816d236822f4afd01b1cfff9e7b58ac33a8c4586bf6ca4a9ae4cddf73f42c5b9baecb5b4b50db930144a32c6a47fbd3044258b8e770b3089ff8dbb5b8376181872b3b1f11fe16dc475016b3a51c
+TAG: e69e3b95e1e41659c9ba74e4af26eb2489763771
+
+# DIGEST: 4209b9f203b29926176f7d54ae89ce7e903009cf
+KEY: 870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882e
+AD: ee2fee55ed8b11534c
+CT: f8f1c7527108ea4c0d6a7df691008cb6b9afb3cb3a059e68f291118d1f648ea03ce9694bbaf8bc74758253ed94fbc8e0b0c3942af881ea659a0a8ab72f8db73e76d817752779390b2ae398edcb88f115090bd226d1ffe0f691163e54c59b6d7a513183184304c2e2c1da41226062a1a07dcd1bbbec218a8a41c77f11f93c367fa1f1de8ae88c843f65015613b54f7e9ab76c409045ec301525b40393c956bf93ed409457e332e1719d1d8d5e921e7ec1507174c78a65ea33eec1bf8b569cd6a963dda00aa9769f851eb669474d9cc562e4f47ed0650eb07b3d6eaec76b9dc2b5475b737b27f65c6bd2b22f3abc04b4c5f7329c407c897986f59b55148cf89e94be3b608f55374b404e4f24547a74457595cd39b4636ec19e3b21ff45b4787322ec175407ec64bc8dfd817a086b746f7f35085f2b4fc961ca7a8861c5d05b13df7eaa208e45284aae89a47583847f3d157337bd4c9a27c5d5a4baf251d9067beb5d64f677edd31001493a55e3af990b9e5efe53e3efc14d2c7ef037b9
+TAG: 7898f79743cc6849ad7a062464196d8cdadddd62
+
+# DIGEST: ef5c6927cf43e0994fe5d8e87aeee052b6828289
+KEY: 14bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee585777
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed
+AD: 8b11534c870dc695b8
+CT: ccf04e624b835dd92156603e3b69810c38f25f63a09025b8ee7fa83538ebdf8fcf77de4f7d42030f8f1f0f86306092bb4d820d31a3204b182dc67af9ea900cd10d4a336a8089c7270b3fdbf9af1227ca0e0df6fedd7e49568f952c0b3948c96e2b80b9874a2511d2284b8533ff3ea02aaafa5b485cc0c932242e1b5e0733d1de3e1d42b797fc734d6f8f5d2dfa61c770723f85701656cf21c096c982c7408cddfbffea583e641b7cdd962fa3a0b6d21203548d4c4bc6b7d216d152e3a4aeb3e14b41eca61187becd9592004ff3129e400ee08ef2dc24c3f9e2e335582274cedfc957e64c17b59179126147760bb03f9f0f5ad741adb96850f3eb4ff687edbce048c1c1f30fd7a1f487c99ac407858e3974462baf435591b8d5757ef3ad60a208d7e9d3ec1fa6f60e668d3e2b6a801e42463e16ec9c5c3b70b03e22f2b8fd9d83bc3d51a3c45424f169e22c4d50f2e8012fdd6911933dd182edcd916a18ffc9de98bb69bd7400287590a944ac0d8c7565751ec8709fda693033e6ddc9d2e91440af8fc4fa60e00d13eff7851c
+TAG: 4037095661e0abde170cfa05e1f4d4ac9db34b94
+
+# DIGEST: f239c330cddd57a5e88e777c848cd66e508bbac0
+KEY: b1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b5
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c87
+AD: 0dc695b814bdf1a87b
+CT: 49c21170700ee18f3361ccb378ee5f2882494ded0fb841b2e5b6eb496247cefeca919920d50d51e837186372183cc4c20b7cda4c7efc05aa3d2ae4db38dd91856cc7125879348faa22cd4f9f2c9772b0f0ab44b6084ddeda17f7125c12a11caeb1dc1295af3c652fb9942d4f72a8f5ee5d9d45b1389ac8e54a7cdde5937fa6108bcab1905f5a0a22898f9884961bf2cc146a417f931dc3ea91a9e59905d94816ca1b43f6b9762357e1a4ba972e8b4129f93cd50d0cca773b97830f7d180585e3e547bb7a28ec65b7604cba0638cde0fec588481c01ca223732200a96f50260584995731a2ec0cab84b7dde25c088f29f17b7106e30f60ce18d979d1371914fea038afa4a4c7ae1200acb7dced53bff9a10083b4c5f47e0ae51637bb610092014e1279b6388c422d53a21635d171e46463dc033f7a56c7a73766ce8ab24295995e66b5ab966711294355f5028c12ec777c449ff2affe39a00bc038b2f2603b461e6416387da9f860c42e8644532cd2deaea9fd5ce637117819fd8a679f8787048cf86b84f7b8024dd69693bd1
+TAG: cf222f1b5c2f697a51ab2bd51b514cdcf7e486c7
+
+# DIGEST: 7384b8e3650297f0e51d9a8f76de34eaa4bc9fcd
+KEY: a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814
+AD: bdf1a87bb1052c6755
+CT: a0ffd519afcbe9b82a13cab3dab68f94a29edb808186510d76b6d39529eaaef3aa5a609370abf26af8f312bc6508c3bdde15e1493790f081eae48482cf667e42fc88a58b97772a05eab5dca063fda2beabe878c00558591bd7edc62aca4260ead112a6b0f2fbc971ba74867279e6b806986475be83bc9a3bfccc93948334f78088d82fc43562e4149539c503f0b81f4f09af31400101670d5eea77ac41f6321b13f999b10797e0c87ce64ea0ae30949097ae9ad16c3467e6cd7cd020fac6d175735eab6397803fd4afac03be5aea1ed4db1f0a1d17db9f9ac5bd6deaf2d3e1eca9f61e3878c84f933b9c90937b0e3c0ba5f5fd138ea21f80d69c2675f1764295171a4a40b330b5caca13ca4f0e1627dffb6c829d378f4ec8828ac316343d777ca0504faafa9d604157cdbd37a439865ee701b34b2699e48a6d8a697b931989d925704123659b083c221541f8df159b472abb6fd054a151656f522348cacaafe7e088733baa4c4baa6ffe4b52b0b0be9a39b3f141ede7455c9f509ed7dcf5b95cc5fb4bc5fc918a76b24dc44d
+TAG: 7beca38c905411e47c28807e52a67603bcd3fd43
+
+# DIGEST: dab0914dde7a8845203fb78f9b0af41ce550adf8
+KEY: 095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1
+AD: 052c6755a7a116bfc9
+CT: a34b32667725ca007a6d17ee2884aa65002018a80050b6947c4b25d989205a1cbffaa44f4605347d3e49ceb4252b2c01fe37795350671266d571d813af732cdac9c91cfe462c7efa64150194b6e646b792e7dbde75fe4ae2275ce22957484b9c063f5a9c05877d32b809b8550240c0c68b9715032595fdcb354459cf0fcb3ebd863d93afc1d3371857091da669d235fde1060f81f62740812edfa67c5ed5a16d0d39b5318b88a000a8653c8bde809f18cfb9295d79c5a3a5d8431887e36bc67371744bacff3da434c16383acc99e7a79713641f58329ecf7f7f82682facdd44dc603a57bc4e2b8ba762fe3c9acf99eb36c0573bbed96b8ee90654b8dff7a0175f30b043fc5112341e38bbd7d38cb2677dcbd1616502e5bc8a194d1eee74e7d0f46d49fbb613f5b03370fdded59ee658f44aaa0b9428b9d75bc8168924b58ab0cee0ab0491c42b70036de73441008c962315f81a19915123da47f774e530803f9b2f3bc01aab752fcf566adb133d3e12c536a09df14bebc4d12aa62871d1cb35c2842e089e8357659b63c29fa
+TAG: ff397394b96c420778054db3b9288c80200a843c
+
+# DIGEST: b139e0011fe2e768284091a4f838f86fea1e4a7a
+KEY: d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf78
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7
+AD: a116bfc9095da49db3
+CT: 738c00b73914a5aef2d755f650917418ba836583ff2acd6844f68e26cf90b18b2c63308020bef9b4b82b6cb1744510bdbda4491853f56d841b5457d50ec175691bb3dd9f2d209cf956edc949c65a624996c9cfdd31b6301dd7d7aef584497117662ae87aeb21866d02607d36d8f1ccc67b5f04581a7daa36f86f3aa469c06be6a2718d3f366dd4bb25c8917b3e225e0eaa2a06208a975b4fa1de731062cd3cb1d26773f256338eb3b815091a7f575a146e2ffd7c539be1b5e08d6e62543325f19d078dfe32dd03ec6b1ec1e6fa5534dc5dfb1b19880a4bc7a932d1e1341970a878cd095502d69402eacd321451f587c627811d0f3cd282d0a58de10a645c11266bc87a89d554325afc3a0d406bf458c4a74a24e10be233a2cce31568ccaa1ab33b3a707e68c38403a4cc1887a5304be4c87aa3cb694f6d8bed8b6261cbb98bbe86ae71a17cef2c23503589c9bbc4d90fb163680aa0ede951d4d2b003aa2ad6f0723ac9820e5b84e3754cc06a7b5ae8ceb38740044be456b2b41442de186a2e51d4ac9dfddcb00f480f8f55f268741c5fc90a977f412c2e79e8d8d0d0
+TAG: b2101592f196dcbb2053ddf16bdb149f77056551
+
+# DIGEST: b338ffac4bbf3a2e41fd1b3b6d9d224d4263b547
+KEY: 5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc909
+AD: 5da49db3d71f4b975c
+CT: 917ccae5a4490cb239366ba41e15f1e1f31eb70a30002ad8312f24aa1f261ce4e6685891d3c71eb97ffd9fd26efa2e9d0976f5d2433806a03065464ad01c2791042f2f516be040644aa1507f8ab025c79511253cd82697cc32c319c4d85b701cf18550222403dc417aae5564ce35e42594534818342a46035a3005471d986e212de8e751cc926a15e58f26d991564922a410f491620781642f07a40ae1259162bcd954a05e69b3b0de1b543e510957cd1ca34958f810177d713c1a4a7d2a033f0b10c2bd3bc161e75566a46877a77d9c8a1e8714048438efbc2bf030928d53c5864593400f0c926e6931b9277dda4e8de45abed0df2fe0fe9ee0d932c13b7bfab02568eae46a68a4d3e9edc479a26686c839b1b5fc1d04e82580eeaf4818267cc15ef419fedc26d83f8c7f43a7a25af6cbf1ed3a2cc5d607e0ed89b092ff7f8b840a6dd98320640c824cf4a88af6b5d66efba3e0d166aeca3a1e27ddea006473a47e3559c8d15f09228c85edd16fb62f462d5d4a9527fd1038cb498aa9951bf53f5faed1c22ceb2485f19c0c98441f7398ee523a67c1fd929bcc38ab
+TAG: e3d945ebe0ab943403c42145667715e44781193f
+
+# DIGEST: c9dc1fbf134470bd3ac0d9855918516e5b8d8778
+KEY: 22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6d
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d7
+AD: 1f4b975c5d503f478b
+CT: 17a9508234ec1c8f49210531da64cea6fa25f599dd8546e8eb23f45f056c60cc44309a9a7372b0f01395ba0c74cba680204d81515885cc0168ad44e07e76ff2f110c71eaf79f04b0f21a5385e2ba8d0ae5e2ecdea8b34d45c15fab0157069cfd273c62a749c6b0b5958a4e3695ce6f6e4781583a8b6a8e21bdd84fc90307e0b40c546bde6be01ad9af4c5b26f06f206fb262778349c20478e41cd0e426abc2fdeec5c3ee9eca534fdeacd7989463896478673258b3e77458d4609967b7b395c2be6a2e6715d92ad299cc36ebf23f2c1e78f7d568571b29b6f1198aa96ab10063fea3562ce8dc6efe1d940630b7c5ab5504776d41da740407df7439de25b3ffc03f988fbd6263ee63d7727b8aea8b01ac60f7470bacb7e997bbe625f1a4f05b790bfaeae6803c8a399becb9bae37821b9d266c706326cc19d06dfd47b4498b536ce0e521087d61e212ee07931ed4eaff00445eb3d38f9953b7938e0c0c4626f4eda3e329c22593235a1f52ee24cd5ac8b3b442b59e1f21332ddcc81eadc6969eabe9be90ec54192f87cbb500092af496ddcafaa961d543ff56c42daf0
+TAG: 6f34019aaf45018f9fc89d88a2b540bd68c21e18
+
+# DIGEST: a551ad393bcdeb8c1bb1a4a70e367b069ec549c7
+KEY: e6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d
+AD: 503f478b22dc8253be
+CT: e56d450c090f228798e8614ec86041b3d6a064c8da667a9c81ff7def573082e051d09807f92cf74ec5c193cda867b4f369d712374e8403b42aae4a42e06885ad3e2ac81f5e768cc320f8cbd420256f7d603afec7554bfda909ab7c7ea80d4517bffa5f21dd616bde564066e2ced03837586ab364eca65b04a083823af15243564f00737697050604c28842f1e4545fa5a28ee86cfbb8b8adfa24ebcfa04028d3a0b9a42601a2358d83a6135f07647921fece532b7fc6bf13b6f3c8bbb6afb5fed1d65ef501a6584f31cab0251046993754f5a8aa63fed71b9060c0794d04820c3fc6b35ffe321da325fc66f320195c94cc1554f0c1f87e293c2afa4810734ece8d71678690e984dac197c60053fcff2ee752c749ae8b7d77bff8e37fc9a44c86cb4c4e0503813406aa206dfd85856f1402369aabaa19c7ded53af990bd62be4bf6b7617042274223cd4d96de406dc35c5757bb0b66c2f8de0cb77abc0e2a9840830e2c19fda54b1e66ee75e7f13072f5f9b16e75b76d829bbc38325c5fc3fa4d97887539ff935268a92cfb0176844eba3e2a88357ac1550c672300c6644a54f1851aedaa1a5e025da1186450
+TAG: b46c0ea8a53b669bd45c0f85f85942992227610b
+
+# DIGEST: 45b1d26c62717ec46530a565c9e11c18206bab29
+KEY: 307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22
+AD: dc8253bee6fd1b174c
+CT: f1eedcdfbfcc756cda733cdb5abb1d5c65fc83e3493ad57cdaeac2d0bc2019003af3df605d8ad531ddc332391fcb89c18e40054c70522719717565e739d04e301d03653b4c24359d4750acb34adf65cb69e541d12b7b4f9e3ead269f813b1ead7f478a0c715905422647437416f2acc1cf08293562b1d25ed8ede56c76698a12acdff235ae3229eb4398bf9fc4fdc0a9bec6a2b414df01575b71a6ac0132d0d41f21e2e54bcd20b62dd4dc1d49cf08d62696e97789ab47d399a73020e72b630b5f6df6bd145e3b7ecd1327acfb02d054176bdcce4f4a6d2148f47e3d0c7920e89f5cf6c2430dc3d83c5a66029c6623ff8da0acee26fb0260e932220e97e33aad185ed958f7521fc1759a52c21518bab27c6983d8d552ff6b8f763e335e7b174b44ffdad689c688b2f8698ee99cc11fd80d8ec61cf55260f7d4c2d1de9b714d3f4807a23e7a2c76c6f0da094b8f8ec58f65ff2b36bea220dbf3f9de860ab3c920366c9b3dda95de87b25b071a4f7ce4e1b7c2f8336b0b529c26cd3133b0b27e86b771200d1b32f1add46637c3e0fada0d95c21bd68be7353ed6ca164efad44314cf933eaaa39e10e35ed1b516
+TAG: cd7c0e0048dde3773b27696a37cdd282414025cd
+
+# DIGEST: aa7cb8f1b995ca51405931f1d021ef30a5b0eb3d
+KEY: abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41d
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6
+AD: fd1b174c307f01be95
+CT: ea3065eff1aabc0f0109b530efbce516fb8cd620c0a00dd68755215b59786badb0639e81a5b42b72c63dffd53f3ee32aa3d25d4892c432f2c8cbe0adf614535698ac030557ff820705b06143098f070d5c35eb8b9f04a0f7cd7591708495ec355f194d12e1609a0217d574950797f14f539f0b7f8ea436f723a01e5f876c19e589a021904b6f76521a9481339d10cfdbcafb02d3f6dd7a9a05600f76a1163e14227ce99f11abdee90c22e529bbee7d529c5836196b5a30849c5b77790bb33e352b716473013e85bdd13a6fd191a19281b133cc0c43e758b710c314bdba5ad1e9e1634089e2968a2bab1a2341e95295f3c6665bca1ab6807e56741e9055f9ac63daba7b0843283bfb7fbf3a5556be03dd48324eefa4791d28f5e9817cf366dc1334946c1daa6be561634d321ad2e1b9fd0b12e7c22757b52d3939b425ca6b7daa7813cc4ba15f5dcfb3947870be86d777f80aae58145c5d1e93e29e9a857dafa7808eeccdda2fe45c0639db30da5a6f62563ddab3cca6286a2588f91cbb40e07dc460a495cec7a5dbbfc23dec43ac6a754c6ffb4f9785fd4d405aa8de3460ea01e306e221478cddbd42851bff
+TAG: da466e51bce176e5f1ac15125651126f24400e0a
+
+# DIGEST: bdbd450e5d302436cffcae83ca3a444c0253a85c
+KEY: 57772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f9823
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c30
+AD: 7f01be95abaa9bee58
+CT: f656eca05d6825e75936e7ab5b6cf591e15e0c7f8b930713242119afc813032f448a9260afbfce9e153337013709b90b642835a458be2a634cb8bea24add0b3ef14f18061893d8332bf341f8336d9a32d67e5be51a37595b5b3e3235fcd53edd8297415c0307a76de6cfe8f771736bbea29d2e359cdc433f08d8f2fc1bffe6da9f93965c527284d95e5b4b1ee4ecb3155cbf04098279185f5c8c4b8b257b0903a732f725f656d7a1ed83a9b8b4424e9569d9f10376cd9f8ef6314190031a4d84895de0c1b95421b875aab2e9b105578a674cda20656229e1467a8a77feef112ab60f0f0ae97e06529701da1f35c92729e39294fb0a020bac4312ca618183652c1aedcb5606d57cde32510d2b056b4dc1f8f36d5fd7156eb1b9cd46a1ba6ffe630a9b1bc0bb4eccd252ef5eeaa1fac39e26d0f404901ad02bedf6e058b3fcf053085318bbf5cfb358ff8b89739db2032ddd255893b3ba1d86a2b7877e72eb73fe41d1e526f6c1d5fe4cb4c0978e8503325ab0b516cd418a185f21dcddd3a788ff5cd9cbbf4834b1d15544d933437e27c807124d6ff069a7a5436c3cc90c2c9a3cfcfe40785cc11c900f76a00d99eb9d0d2fd07587eb01c9739bdbcfef
+TAG: a20435b01d8be195bd3dedc3e8b6396e54c95f31
+
+# DIGEST: af3f40d07667dc7e32a1fa664c6f5503c3e2c8f1
+KEY: a4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a5
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95ab
+AD: aa9bee5857772305da
+CT: ea8673a09898576733b3c3adacdd7e1f6f78b33df73c93543c531279172edc2011fd36c7cbf37645ca5e02f08bbbc23e63eea341374b7321afd810376c8086d8dd4a62101e113c3b5961d7e9bf140731963aa62f41526436e1c90dc838e83472882cbd7bfc33ac02298e5d8c2371ecdd2e50570c5a3171a3ad96d9b680bc59cc7f98ad96d51a4174138d0f6d11e46fe271d78755a809d91fd30380e600a4bf89e69660dba2fb38dfd600bd77317f25da06cb099b29186facb68dc2c8609b6f7bae3fa2ce89c3005010593d5014652994655233958716384e0b1da5845a6a84baa3aef8378178964cca583fed12edf52ad6a6937a64b726cceecb2362b7d9d60b1e7bc685c8160e6c18b37875e3fee39993050ff004aff75ec2f42944fae732430ffab1bbf084275fbabb94c1d2eb49403b929f232dadf3d8381de29939d6bee7c0f002427841abbc458b8e9bcf05c303a6ea9e96c5b36839fa67bda668d1e22191f7ea654d16ee23d4bedcd5fcd3adb4944e154f1d1c581714ff839c3dea726f6489ca6c5855ced7fa2ed5164bb343de912eaec324c0a50df3924d430a54b7ab036debeeb11dbf005fbb40c35f7d1beeff336ba0847ddc012d843d23
+TAG: 56016fba57c07ea9a88288c7fb8cba8f03572491
+
+# DIGEST: c6830aca35b85932f7c5df33907ca59bcc489a85
+KEY: 05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f31
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857
+AD: 772305daa4b550d75f
+CT: e5c217213bffb311cf3d91dc4b3f7ee13a0196ac2fed97597522b732f4d46b33bfc47f63eb397efd387ff17922fa40d0e2caacb1caab186e4f4d52e7084fa4a5f1070a268548029e467ffdd5aaa31f3bcc6fce90a072584f36a2dcc2a8f452a31eccb6c6c032a74d6be58cbd585251f955bc7ccfaf4811923a811d656a942c33c02f8993234a75bd84d4d7752675fe917d4d75d53e1e1912db353a40cad7fdb6ca978288be5de67adc4231510b2d7876dfb52b3a4538f8270845bab57f0215dc66f89190087d9cce65ea69841236a364c78e0bb9248aa1d8bbfb2cbc2fd7579e3507fd33f33e608ef895fb49b65b5507e338fb4152645c036a208ddf3342b6606ac221b0f475b24b3f2705da4f7517bbcac0bf330f7c87559a276ebbc6743e9d1be245fb89e9e411a94a71b13e1f5678dc5e139db351a1de5774b082b2ce3c94ce25dc89c06c88ad558453e221c52c1618e9e4500c1d02f0f1b3bd6e38b602d3e3a19bbddc6f129e7927063ac39f7d792262386d8031cf58d29f0bfe5619d24c7ff225628c89def92c309502b744b67526ac7234e63bdc8059bea89070301dcb8f6cb5841e71d2c65f4ac17a1091d4050f0d452bf423fe3d7ecdbc34
+TAG: 5533b1648b6a83163ca00e1ca9a5da7827f70c58
+
+# DIGEST: ccbdb85e0a5bae6416136d8d64ef0fc8ef3bd52c
+KEY: fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6e
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4
+AD: b550d75f05d8089850
+CT: b798be3ad9f7dde8652c009af2e1856653d23ab304aa268f16072cba20acfe52bf29ed47b979db0683e5ad0e8b0016614926f0ddb21e94ebb4806814a5742eaf2a19891d043c07ca01e082944ec69e518428fe476818d533dd169ead2bde9b887ffa182d06dbadea375c2e935fc88ce601e83664de9234173dc27e734da972ca4fb77990b82510f50b9716ea077b096b6e3233bab2636a1193009baaa1514eb71c251647b7d6cfc02987c5c10239ba348128f13a221db9e4db79a4e5ee1cc25d95b17f416a70f4bc74e8b8ca05923d7d4b7be109b4c7dfdc7a07cdfb8db6121b3ff5edad457fd5bc23c7093094ce349e11f4e4fa9962e0ad6be7a388cf6dfd3ecf1248267968f852047ed322bc818d170ecd468913358b631e194e8c257868704f7a59abeb348b661b72bfabc41507b8fe3661a40ef9e92aa6220b16ca4c6718f79077e83c637181c4f2c4628fb5112ae332f61a83725dd8c9f81b981fc3a30b7af22e6aaaf7cf4799ba4d5a5a7b654528f505903ea324d0e06e1d0c46fca011b8febae6d2f49b69bbb87d3ad7b5269fb14455c8897891db909417db4619bc13df1fa043ea9bce2352bed5fb2464b6f9e8c8e1f0117e00b66cb105f75926b4ecc375b3cf33760ce81c9ca626
+TAG: d021f15665c1c544ea83771b73338087704f5027
+
+# DIGEST: 9bc71f6083d602ea43a5be27534283d8953578aa
+KEY: bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799e
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05
+AD: d8089850fea3711265
+CT: 822928b9b6dac27693dec121706ab0f5f60d6891afcecc0cb4c32d9e13d5c4792d16b005d3b86fc271a086aa18735d6b33edaa6c74054eee6d28911a11481d5d266134145a83c9af2a0c4b0d1c29584afa5e9383a34bdb81ee43b06351a08d806b4bf93e9bc35e1ae917d268bd76f99dcbaa9261dbe800b7bfc21aa91f25ef3545aa2e7fc1dcb246a898d3b68a29d1ce279b9d5424b090a04e727fa2c7e07bd18df63b2700a84b3bfe78f2be2ec550d0790338fa2baed3c0f9299bfe3755785a28e8537e59d7d0de086a693dc20c344f35a6b909c8abc99ed1440d75393b7a5630b788b46653ee98d800ee6a695de91cd993d19600a50114898ef275f0e3a2f08d72fd9197e858ac65c6a2cbdac648ade97002e960c15856735318d5deafc31a8418463ff32c999ae62cf5c1b7f5f48e5671cb356738fff751657ba3346a63e6525aad4375d3517e9db09815e386da08a4dc7e29c1f3faa17ca86e166cec6ce8ae33c291f09df418606a8767c6dd28ebe2919dfad2e010877c327d057db6e31a65b411bb2263786a83ff5c7bbb8d5b405d62947ac8fea97a9a51852d9adab006638e0673e97d794e9f407b80805cd3faa0f1e3ed6be0c4cc485aa5834ecc478b288ee3611ede19a5ca40583f
+TAG: b13b137b80a6efc73b4d2747990eb1a453eedc29
+
+# DIGEST: c39bd34f093d3b18f254e8a94d2afd8f70eb4d75
+KEY: 0bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fe
+AD: a3711265bf78261046
+CT: 6c2493fc8bf1226539fde9a58ad9167069a8e79cb9a536e1b4f69ed6869805736326216009681a9b21819aaa868bdebfe4a8bb464b58f3e3956213a269850ee6290395d94cdee1add5eb89705be26ae39fc84c2998eabc0eae41e08233f644c61ab84ad8d07253ad19c33ae45de76b2eebd5dd1994db355c26eee5ba6f326954e8e6805c6d90f60ea6a826ed43c7ce7d932541b2005e994b0890a43e4cbff30d522bb75ac8329ddfd663f43ae9bd338f6b8b36327802804ef124dd9126085b377d57429320d9d635a6fc19757789d36fa75c6b135c5a90ee42069659f017455800e3a585d514d0b61431b0fe55a789de8835525b2d18a7efc468c0b6d9c4ead9ea3cf98ceb06be198ad5bd5fb7d741cf2b7cccf11f885d4cfd91f88ef1b677ff08d34412d5d10b27e66afe549724a8a210e85bf5504ad9aa6d97bfa930f406f3b2e3f04101503970aa816843411307b9a2c2a686773221f54235a5884c5986ec7d0ac6fcf49ca3e0f5e678f1fc410df48e7349d69672348d26f65fd5b3a3dc257684b64a025c175bb5c4c7a7434e3a3e91527189c335fa54505efbb7665ff105c9649407d52633d74e8a404827371e37aac91bff5dc3a3624bd0fc5b5027cdf908df802bda6ecf00ed7dc8f5
+TAG: c0d79cb6719b11e491e4f564fdefcbd0cac134a9
+
+# DIGEST: 630e1d99053b3cb7dc8c5c78dcb39fa7b0b53e74
+KEY: 2e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e93
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf
+AD: 782610460bfd24ba02
+CT: 65312debfd2840f9cb5499c1d50efbeeddf8403e0e2bed3652ae1eef633da8f7e7206a3eb053745183828d887815a1df5556e024ba29f5c5ee073b9d7c92bc3d23ccae04da293d106d041329682e1ffc726a856d397a3df9df19900513e048c17fcfa79c09cc183613badf96dfbf60c86c273a4e2955f0cce8a0798ad123f8b97350af4ec03f385d30cffa4f1da7d1c7c2eadbe1f074bc1d2bb9bafa2a3cb01666f0ba08dfad720c27f6a1b25cec4f77abaea1ec2099a019173172bf5e3eb99856c909b76494d46e5731292b7a7d6b0d5bbca8f31280fb9cfc46a2587224b97e7bbad29c5629a627026b39cd58a9a8befaa123cc90150e330ea2a638c4d03eab62f857818c92c133eb96468e97305087f30ea440fc12f5bcff58e1ecdc175b43e3145691513552fbd77dfd8ab31947e33e2b09511b2837429f60fafd480167e572c4846811b444af97b71e8b4fed1ecc15c9b3b6ad537d0ea421eac4334357f2f60bc0d74f6f3c2a8077a37a12cd0ab19a48a86dcc0c1d44cba8458bcb0b00ce405b9a95c1a9735c3bd119abd12bf93859049b73ede8b549fe96e8c623da61eef972abd88cb62968c478fdb51dc1b64a68c20035902e179be9815fe4f22adc00d9c1d10da7d3ea89bec7177b6bafbc33dc04dad6232f8622376e193b
+TAG: 32ec71fbccad98563adf24107208eed3f6b178d7
+
+# DIGEST: 083d60536c78fbe909d2b35cd5b891be34f2a60a
+KEY: c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a694
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460b
+AD: fd24ba022e6da12dd4
+CT: 9b29da1fa8eadf575a8460c16d4cf12c5e427accdf0dd30cfaa7afa28990ae731bad393e7dee5f5a415c9f7ee97ebbd51d92f422bafaacb601ffb1b7aaf6badf6ebb5efa691e6682c8d6275ccee2f307aa241ec93a42f4e78e09fd42bfc60e479a8608058f893f0835325ea1fbb6f9621230c8f06e2beaf8ef2403e80fcfc79f9037a7d6654aa1d28a6b6199807daff0a790879dd18b828314388d99cd51a7dd0d130a2805e84ad2f98b0dd46b805e127d2cf6f84d2b0a163dcaa254802cec2f843cac216a95780ad04558c3d3a6fd4ebc4eef7261591c01c7e68d56bd1a81aa5e9898c1093fda42ffc9aadeeb9e6010186afd8ef196fd44865bf4ed5d67ac5293300c6795c8e7c9d607e22b1ae0a0463b4c8b633bb3727e3259fc25398cd8ce4dbd64a02fb47123b1bf46e3b5d00e36fc128dac05e279312b5ff2966ee1e2969881510f64539c2c04495c68208bf3ca12e9e8c5edd6be6eb6ecd2fedbd3e980ecc5ceae99d46924ebeb0dc90b9f7efe0a75f12c52e18d68dd46f031b79bb9f6cccf0493e069b6d4e14a59e29f8b507cb1892c7973bf0ffcd0112f9312c97c9eb8f561da4430a7b0e72b9f8d940374f66b8f8e322f5db0c4848538e3b2b59d21cf598499826e6db079a6f66a30bb23b3b5c122e21a22209b6cf81ac5
+TAG: 567b8a4583d9df8c4942d29058d80e13f908397c
+
+# DIGEST: ba36e689ce5c9e3dbeba5ed1cb00b265c7b30d79
+KEY: 0974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d72227
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e
+AD: 6da12dd4c27f437248
+CT: a93aa7823d34f8b035d7bed4528aacf556446ce80a1fdce5e9f64dba84727a3fadafac1b2f6a88a913882e5765bc481ae13aadba33efd7bfeadec03559d2072ead19a96a1dd7ef1e04d982a5c6307da72270ca0cb9da56c439314b4b0d37aad7d14d8d034dfc0919bfacdb62d619baf501ed1ef8283438d5da788f85e001ab834e15b64d3b90c959fb3f1af52478d30182c49618a8b99aec4e12fb660c7662f327cfdc55b23ebc213d02388e7d94b8019b240ce6f842225010cdbc95f98a6fd81d074a7a492c9cf35540ed43b3959c798b84b7ebe951eec1b2814f4660577f7e11403bf6c21a67c27603d3dd8cb9b93c4d83b0ad6914411874bf2936289747b204f214b3d5a8c80917115bc6b59580b8449b8fdd5d2fd466ee87b326c50617fd07a5c2fb13d3abb9b30a52c3c0dde9b4a9d4fa47072467b0c338a9ea4ad4c5ccd199a8d4b52b1a10352697a3a24192957454cc5d9482c02138c5d83b9bce9df2a42fac1a52bf3edb9d29408a9e3e855096acf97176361675abb3a2fd307193792cec150a7ebd5d1f58326693d85e54039048bcc2d426afefae8c62c564241dec4fc7df196d23e414b2ce29d6391035abff70532504416272b0eb0e349d9b533624ef27b31fecb90fe504c454b413299eb3a6f06e9820a5f6bacf2bde
+TAG: 2be33e5191afe50dbf95105c830b97baea623927
+
+# DIGEST: 2f9b29467c1e54888b4d4db41fe3a943887e305e
+KEY: c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a82526
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c2
+AD: 7f4372480974454879
+CT: 813e34d511852d0ecc7654e61c29d27e7255e00bcd26203fee7871f87e225495512ab5b4928e09106c123885c32f9f4d8c49fd8e6924056641f19c561c1690e71e31b16f9f077b590572ba8179a7193487da47f2650f6fe79bae11b3ad5d8a7b20ac3cd1865d42752c4e7f9db8541853875790ba51f95d2bef2e8e7a1cededc9682c2a821922a908ccdeda441f031212952bd888a1654b585a84365fae1d451d432fc69cede6a8a122a0ef6c0e44a2cdef42b5e39dd1c3ff698c6e0f1504f351d40f84a8b40b9cbfbbab8aa9ee2b33e954ac8ca096b73ac9123e124826a5405db2c004d4af645e7e92bee41370937660983f36314cb1f24c645e6b043aed1e2aeec6c762684c62a3aeff1dd3a1a5704741174944b60234839ed11a365eaa04f208d13f2522d9f574e77c61f0ba69a4c67892b88c661981d27c56aa02ebede387756c9a5bb137000134eeba255a3e482d631f1d7cf11b9d5b2e675a27000fc425bb76b0c33432560ae67f4b2bd85d3ab43081c1202ed532d1d8d5f72083ed835a60c72ed5cdc76370e3bbfc119a5755a1ffb02843cb6613d606ec3fdc0c1c538e6c4ac8efdc7d4fca2c4dc437f2b5932b9d1799ebf672d5357f11c6ae8fde8872b2c157894d2c0c631492a047ef6b37b300b81ef74aa66f08210850bd
+TAG: 48134151ddf62842a1ed42dfe36251be3c2272b3
+
+# DIGEST: 070f23e02cb53f55b0127fd3fddbab83e5682275
+KEY: 98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e97704531
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f43724809
+AD: 74454879c41de9ac9f
+CT: a6973cdda2077c619562f707d67b195a87b856408e55246f4c50256359b510ae9e7ac578f85d993901d87d92d845909adf6df42bc33e2c9cabc020987415347b3f2e43db4596debf6576f7d5aed7c536996fb1cc0da14294386e5a077f92fe4a51148a5d823065f834c196cbd8f35cfc513d4ca44da13a387a768519128e3c5af0d2184268080772553844d87589498ed0be54977140f849bad5aff53dcddfc87f63eea5d047bfe3a40c668dfd856cd2768c3d1ce390df698b0ba44ae9396d220bd9499105beb06480573175d9e2f776efc05917371ac4e6146cd9447e389187f8321bc06b04b7ecc76e2def2e27574d5eda1f5308a06578e1ef1163e8383469d5ba121bfeebb3bf1f14cc1a8453e0d3a0fecc87b5dc308028a3c3cff0458409e957c56559801028ea26e7600723db06acd3213955193402f64bbfd7114f3a0a4f2992ec6efb54768093620b8a759786d984f0500d0fb339e3d5d11eb15752a79f5af18915bb0be7f7974e4b526c3b6b16263ea90d2062da7fdc64bbcdf8eaabf01235b43faa0dfdf55316495768b3ad8ac8b64577c64a72fc758cb174abfdf4bbe79792516ba0a22b862edb81bb92b2a2844cf48e19648e959dae0b1a0de913fba70d3aee74e050da8218663c44520ae86a63a777a1e980add28a86522b86eedf8982c601f51be7459b2602
+TAG: 1f138c414bd8f4655dc34f3d856ac6723dcae8a2
+
+# DIGEST: a09f0450fec556fbb3a1f869c9780c3d12547311
+KEY: 79a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c9b66262c
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c4
+AD: 1de9ac9f98233b5a73
+CT: da8ecd3f75f4def35959d74a96174bf5b2557f8ee76748e256980fa49ff0229bd76b4d8f28af0a42276b0eb75ab2c25d6d692a2d2e9bae6442eb58c557a9064e2750a282cde738a0fc8f9d75a176bb9ac5eb30edd7b299d8e2d50de750c97394c6013ba6b855c270860474c18b7fb268c2adc20cc8adc5b3126c5922aa1deb220d33ca9f4b27df8914e073222184872ef90222e05fb206d6cddd72f7ef5c04d192904acf15c261a1d1ce1054bfdceddb06829dea04c64bd87a37ac7c6094e41e464d4b0019839b5f14081ce2488e018292036f1d92e1bb6a2c5ef2c5b70cb97b056ddc7619c1ede30fbefcdfc75ad790bcbd4fa00e9bed812895c03405f7886f20a0599994e210d18433cc52d54d02e34e2d80f3c260b943f30325ba2cac7f0131514ea71f7158bd9de54cc5865a20fecd89d60ad377d3bf2b2181a637fb53a79e648223553c1bc77b513379b0a0f50c25284eaabbb45e8247923b72e99f99f7adb65d2096e8ae18d4178285e03f9c720b39215016d023b6a9ad39dc10cf32f69ffaafedbd20a63324fd587ccb1b2cca0c454f9d239cc953b695e2cac454476f2f52ce94be35a3d47585161eda1b85a5bf089e85a0fd789daefb9ebd0a6ac3b2187134873be399c505cc443cdb5a59cd228e73be207a6da57286fe7adb3379f44c06b4910d1a56aa3fd35042
+TAG: 738858b4b65a39a92e20c6b13c88d5b0ea28fa80
+
+# DIGEST: 32559b69ebdbf4f1fe7c6e5ada9a4117836eaf4e
+KEY: 0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c9b66262c0f0368fe9d
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98
+AD: 233b5a7379a561792c
+CT: cf3f4de53bfba97b3576fc56739eb98dfb728e2d0b4944fad81cf2b7217d38b87b043bdadb58ad2bb0c1aaf373a0512222026b7601044dba3515c2c3609ff905233dab916dda38e90cff749d70649503409dc8768eb40954f8dc7f39d482242d911f22f0b2e26204b36dece5e871a92c4025c0038c9371a53934a8296286d5ae10cfa6ea54b00da5e54b18cb4c22af94aaf00fdf0fc8e0a3170036996885688d9fa09556e519c3bbbfaaaaa2fa9c79d8a3471bd651b68c64e8f1400384ca35853a04015228c5e5ea76b8355215614deeb4cfe103b7d24777620063d90065fb48c0c81a0deeddf15785363405a9a378fe07fcf0eaf030c52f5a9ebba80b6ca7457fd34cc133fa4b30d4eb31b4a4e40479f002b5a878fcc90999a03164b19cfa58a2aed8354ba6f8b325f80f8eb9598bff11f47e7688d46137d0ece20b9bb3a4b7a16f0ebb767aaece5e85075676c96cdf52f7ca01a1b37b40bcf97ce2b432eda27fa4f0af86b3a14a5560aba1377f680f14cc9ab9571b81e977a85c5ca8ae0be4a8668432f53ff45b74fed7c0d8528a74b67e0a83ad655f6bcf0324ee94b45addec81d628155690f4403a40522618b1d143193b13f5214d463690036b83eea81063e9dab96ae76d3b18470ccc5d6762349089dde6ef5f445a7d3a5b9e16ded53390a2208bfd31e412e1fd32fc
+TAG: d46e1ed22fe3fa4077ca274b9cae824eadf9fd2d
+
+# DIGEST: bcdc01526c7b0248abf3a41ac893bb72adf422eb
+KEY: 8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c9b66262c0f0368fe9d0cb746bbd5
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379
+AD: a561792c0f3116430e
+CT: 2b48e2e4aa61ca10c9175cb004b0c9e56e17652a7de545221ac10fd1763e4e41169b161452c937d33b6ee6feb52b5db56d8a1168118c7bd1a70f4395a091a96048fa8473737fed577015a0de9016bded4f09d1a2e53b482c5ff13ef2566b19c8a3526b7aca7f59d0e89b3bc2d6e417fa8613f2dfd3fb6ab20b5917533a0cf18f8e1bebc9264708085daa7f89b244d82c9e45021ab1908d971a847cb965b61f95b8813f27f671734e0f527db0bc3532ad7c052da83b8086ebb5479390e419d6ffc43cf7dd7d66545bd35a215956f4fde6e3515508ca2d5d229b3dffeb0fa62cb3edbbbab98b62872927a804a07a441bf17080931791b890229d1d8edc6bd34bd3f491744ea04620b805107c50532f1ed4db7b8e45d9a1325a02212b6bc7747e007d1565cc646523df015af4842e82bcfab0f229683c508f08f0f0a6bd0249123008b89d9c665c91da8fd538337a4413173aa21039cb35022fb9f8e1d12ccfc736a0e78ce98f426f8eeb42a2a92391c5ce70ee5a571939ea139dbab5dc90c75219a963ed1c40f4f7cc9d53056d8f52094ddef9e633ea154a7ca544066c58c992a1215fb97e2ee09993ea5cbabbe0ce1653039ea084a754ea98f5dcc157a51c8e3b3d15cd52c8618383ac70440c670f1772cde101e7305e4b2e88c0a7d34995f6b0c05949c67b5a21473d481275eca8ade9734ec349483bfd2add27a8ea
+TAG: 0ed527bdfd4a8536b00007464eaca59a1633ac63
+
diff --git a/src/crypto/cipher/test/aes_128_cbc_sha1_tls_implicit_iv_tests.txt b/src/crypto/cipher/test/aes_128_cbc_sha1_tls_implicit_iv_tests.txt
new file mode 100644
index 0000000..477f1eb
--- /dev/null
+++ b/src/crypto/cipher/test/aes_128_cbc_sha1_tls_implicit_iv_tests.txt
@@ -0,0 +1,840 @@
+# Generated by
+# go run make_legacy_aead_tests.go -cipher aes128 -mac sha1 -implicit-iv
+#
+# Note: aead_test's input format splits the ciphertext and tag positions of the sealed
+# input. But these legacy AEADs are MAC-then-encrypt and may include padding, so this
+# split isn't meaningful. The unencrypted MAC is included in the 'DIGEST' tag above
+# each test case.
+
+# Test with non-minimal padding.
+# DIGEST: 7f3a0e20bde700d3c5596909282e5c3e764c99e7
+KEY: 86d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e
+NONCE:
+IN: 936a91d0b5
+AD: d2c0267218cb7090c61713
+CT: c6281c1cd562c1935946013b946a2342f00e08a2a3e0f0bf6c98426d
+TAG: ce5d0ff98773f9560831e8ef348f50b35a2fbbf2
+NO_SEAL: 01
+
+# Test with bad padding values.
+# DIGEST: 7f3a0e20bde700d3c5596909282e5c3e764c99e7
+KEY: 86d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e
+NONCE:
+IN: 936a91d0b5
+AD: d2c0267218cb7090c61713
+CT: c6281c1cd562c1935946013b
+TAG: 946a234257dce6ada126887baada8ee4e2b9f5ee
+NO_SEAL: 01
+FAILS: 01
+
+# Test with no padding.
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312
+TAG: ead153f0c9488b88357e81187178465d2416ca97
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: f0f82752a691ef5866413f2b2e5c1d0ebb41ccc8
+KEY: 7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9
+NONCE:
+IN:
+AD: 936a91d0b5d2c0267218cb
+CT: 3573ea7b63ce69f8201934d1
+TAG: 32287532f62cf9e3f76e29a7d32db4e5d02a8ddb
+
+# DIGEST: 7f3a0e20bde700d3c5596909282e5c3e764c99e7
+KEY: 86d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e
+NONCE:
+IN: 936a91d0b5
+AD: d2c0267218cb7090c61713
+CT: c6281c1cd562c1935946013b
+TAG: 946a234250ed67575910144f24abf6bb500ae865
+
+# DIGEST: 5b32faa93c18842b5cb7b075270438756d5f7dd2
+KEY: 97b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f
+NONCE:
+IN: 936a91d0b5d2c0267218
+AD: cb7090c6171386d641b877
+CT: e22001f66a70505db0e606fd
+TAG: ab054baa17e7012c3090a39ba2562febc61c54e9
+
+# DIGEST: 995a0f9b029aba3e0a3205364628bb76baccbf45
+KEY: 56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c617
+AD: 1386d641b87797b684e0fb
+CT: ecaa1fb673a01178c9cbb07f97da65089b3d6183eaa3bb100bcf1271
+TAG: c050c7c8e7ed21c7b3d340c6b95dce75eeacf9cf
+
+# DIGEST: 023d08d5e5af3e0b016103c7c3cfd1d02577888e
+KEY: d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df6
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b8
+AD: 7797b684e0fb56f97c3961
+CT: 92528284fcbe4afcfdee31cfa766b130a569f80e2da876ef0ff47db0
+TAG: ee913ea056cdfa866567ffaf89f68fc1596e5160
+
+# DIGEST: ad4b11a43bb47aec3e91209f98f99839dfa1d6f6
+KEY: a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0
+AD: fb56f97c3961d8afa22993
+CT: bfe23f8be496b3bc8f7ce56d98bd68d1fa5d34db969fed05095d0024
+TAG: 0221a5d84e7b9f7500c5c250d1df78d4026652c9
+
+# DIGEST: 580641286aa43bcef85be190e1967f627713bc64
+KEY: 89c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c39
+AD: 61d8afa22993a340b9b3c5
+CT: a405ea4fd52a1d4c062e1f39f8074fef3990ecb68913525d2d780461df8c91d9b3da0aa66462756bd7108feb
+TAG: e9c52c19a46b7ae12022c55465cce0e6ae5032bb
+
+# DIGEST: abb06965675631a07f380e80a05cff36c2d42ecb
+KEY: f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa229
+AD: 93a340b9b3c589c7481df3
+CT: 1d85149d836f2eb30de4e81629b6db810080dfba5ff8fe1ebce0e21d9841d8526bd843ea675cddc01dbea77e
+TAG: 1ec4419ec20d3f08f9bd5046d31f2bc608e19e41
+
+# DIGEST: c6a1ebefd827cde32df1d38379ee4bb6a7f81267
+KEY: d8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3
+AD: c589c7481df3f4183aa23f
+CT: 7ac2b8a728aec2d83c9efe446bd4bc61d4e195d0bc84a2bfb8fade2cdc0d8eb890dedae85da0f608cc1bcb82
+TAG: 461c0f62ed6555a18f173399da6fab6943f13d55
+
+# DIGEST: 77fcb5875838a28d24c4b6bd0916ebd827968073
+KEY: 03f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481d
+AD: f3f4183aa23fd8d7efd885
+CT: fba1a6e2f66b4f9e45d281a15de9acc0ab1d9bdf910eb1d7f666dc0f9920f57602beb84189085fe9032db35a353fa554389af4aff3dea1e20c4b6209
+TAG: c615c926659cd38d7d86073c080002572f222ef8
+
+# DIGEST: ff3c91da880d2942bbc51adafaebcf4c6fd50603
+KEY: c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997d
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa2
+AD: 3fd8d7efd88503f78b8ed1
+CT: 727c00d1375f9360f59bce3279a2058d47b580669a3725c4f655f9ad081f6e7517ac0feaa7f6b283381d4e42ca33d77a1cacca3526bab09a860948a9
+TAG: 28b686839c5990e0e2392ee4c1368a92c07b66b5
+
+# DIGEST: 8c439bfcfb896bd106f94676b5626f2bc624c313
+KEY: 773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd8
+AD: 8503f78b8ed1c8e9ba2fd6
+CT: 7af81e2a26192870b683f696c80b2cb7a212b68a5a85f9af5775f9582a9a99f50945b4e81c21185a315cc328e5345cf309c70c230fb769823807599a
+TAG: c74b90be48c48661e615ef7884fa97dcdf27aeb9
+
+# DIGEST: 35d9dfb89c1883210f03050da3166b6d13f5b8db
+KEY: 2a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8e
+AD: d1c8e9ba2fd6773e0d0c30
+CT: 98c01c277a1bd3e1edefb31f39c80968a9e94c40b702e7f0b69a39a9b9ea78aedcbba89b266f5a11e8cbcb64e5ff2d0adbbc10416110d9f7f9f1c5fdf3b49e183d08ce4fa72d2d78f4bf69bd
+TAG: 2bada16d212ff285cf763468fe2104a38e095f7e
+
+# DIGEST: a07054c760cc66fc704edf950201005031f3faac
+KEY: 446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be1
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2f
+AD: d6773e0d0c302a5f47e037
+CT: 2e7e6cd84e03e35d8977c9e1d4ce6784c4db3a87fa1b82e6f781e284e0d3914eb56acdde0374eed6283cc10e1f329821fefbf888dfc8fb42fa574cb64df6d88d2d80503493bfa3c2cd3817bb
+TAG: 145fc5794bb7519429bfa85ae1382e165e104a4b
+
+# DIGEST: 63efe7af502231420ed5aecce9a28446b257828d
+KEY: 7df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c
+AD: 302a5f47e037446f5891d7
+CT: b2e315ef97a1b89b4625715c61946446fe1bf27aa60e65d0ad9849f71ec53ccbee951d3628efe2795949f88795b354df0ec68b21cd699cdd0f92f31f3d6013a4c1116165b4f54e9eb0387d91
+TAG: 21ea239be370b7c0547ded846c811f422a71e61d
+
+# DIGEST: e8e41988fad6c8b44c56544964cfe0a347b35b1e
+KEY: 933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e0
+AD: 37446f5891d77df660ed82
+CT: 8795d6c225aa78fccaaff86101641081f4a440969633ca8d7830ffb14f629fa34dc4c15e8ff20a8940c7a484ee94503372e658615eb3fc07c2d2c399ae9ad7a77d684512d0ca273f77fcfe53
+TAG: 4574a93d31c1c0bb43d3d482057e0d8b51a679a6
+
+# DIGEST: 172f4992e692a88f49628e5d3937959be01aed2e
+KEY: c55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d4120
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891
+AD: d77df660ed82933f62be8d
+CT: f2f3a3d985eb38c406bb0db0d141188c680656db8a4484abad2c8973267e14458e2be7cb52f06ee2a0f68eaced13db714296319b2b3557454f5e9cb47e8943ea3e66f7bd25c5757375be7bdd65fef53b2c441fd3259628cab417df36
+TAG: 374ededb564b3918239bd5e284ce22d0372f4ae0
+
+# DIGEST: a35fc7d25f90dd9cbd35910d5532aca8aba88b29
+KEY: aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed
+AD: 82933f62be8dc55b436965
+CT: cea9c7528706d506d75cf085c8475c081ee8c6145ca11610b73eb3e103a706faa66062f8edc10abaa7c3edb3fcaf43c202c4812e768fececaa04564414f45816fa5c0df5b7518ea3859be75c4567565358293e923232de5af0908060
+TAG: 4ec6b6fc6692337793c264f2b4f5f88570cd6e22
+
+# DIGEST: 4abaa8453e8cfdefd918571a961d8351754ad5b4
+KEY: dd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad40
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be
+AD: 8dc55b436965aabe477e0c
+CT: 03065bb245ba12ab90903bc081198fdfe45d7d3c6fa3b1f76bde831917376ec2a5b2ac2cf629de6bd3f23025b678ea9cc3bd7801f5510b58432a8bc17999304fec4de7ab9ac22d75897cac67ed57e30d4745588b36695dd005c59287
+TAG: 7bfb0998bc70cd20d6c1dd51a73b031eb1aa567f
+
+# DIGEST: b51001b6ff9d27bccf3103a4961280e0a1406257
+KEY: 1eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae0211641
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b4369
+AD: 65aabe477e0cdd46be9937
+CT: 8d7999ec7a80e528bd6a8d2a9724930c93ee5cbb0c888d9b7c79d2449e638c03f3143f1927a1b261d66ff55bdeb7ff6616da99a2155f465d7c91f54963e7cbda7b61529381204ba43c9681260799ce66fec9b0e9882fc0ab474fd9134adb66e9012cda52183ec3e658c42f81
+TAG: 9dd9862193c5b312ba42f288553e8f1af858d6a2
+
+# DIGEST: ad2b43eee27e6267d8c5c1c3d558a07dcd6b1f5f
+KEY: 997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef45
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e
+AD: 0cdd46be99371eb8da7dac
+CT: ad918e7428ca106cf043d6626772cd45ce998f32fea28c3253fd58f0fcc191bb4cd250b5dc6a7b352bb2aaa66601e280576fa60ad8c3aa58742462955fd7f33ddbbb5036128617c1fc3bfdf83100dfdd069042ad1887c2821afbcf822756226c69779d88edae83839ae4bcbc
+TAG: f7da661a2c2ee207e4eb4716dab8e0e11e4ae1f9
+
+# DIGEST: 7b17b7cb19107af8fc4671420e461060e2ef3e61
+KEY: b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dc
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+AD: 371eb8da7dac997deafd64
+CT: 5e654ee6344f96fa117a2e1f9cdc08bfaca9c83b1c4d61891e49077c8ae7a8aa604e1b19995b32872087e04a59ed367e42f0ad3998cc2112035b33104164403a948ecf73c516f74adaa57688cee9417456f996847e0c637120478f7d88288b5403f0697c4834e4ea7f363ea1
+TAG: d1325e86d712a133cb4e4ed7b75715b2589f764a
+
+# DIGEST: a27799fc2e00e7abec4c5939451a834c4606cf7a
+KEY: f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7d
+AD: ac997deafd64b1fc65de39
+CT: eded0eef58434338153caefd914cb98ff516157445bfbd25c3c5cbcc0ad68ed1bf049ac292da027acab0310ef08d66040341721524982165cfe7f6dc495f7f5f36cc410470e3b42045b718f580713dac8074b0e76a0345d11c94a9800bb5e5eef1cb8d9ba5818799cd1ef69c4ed1d7459df78edeb89e01ea8d685b57
+TAG: 80b94ac3cde906a204fc3bdf00e36d5dd00e464b
+
+# DIGEST: 7c52593d1d37b0dc380297231c6cb7b64e04c493
+KEY: 1be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb9
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd
+AD: 64b1fc65de39f4f03541a1
+CT: b463f7f24871b617a1001d2f73f9eb8fe39b5fe0b382d420af876defd68a893add2eb6cac45e56d669f4ac67a943a3b32daf0932072bd701f9291b5020bfa9133d2875d8f6ee78ce8c49d45b80329831799f1eee8c712683300e49c57dc8c1ad0b07465184483d669b04c183976289e3ad60702e8b0999a7792a9cfe
+TAG: 5148a8733167317f341a861b3455bc33df9fcee1
+
+# DIGEST: ac6871d354eac507556770d8b6bf10b5240273ed
+KEY: 33c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de
+AD: 39f4f03541a11be112a729
+CT: 413d2c3fbc77845409ad66cc13432824ae4ae109379a9617e8b93d4f9b17fe0d0450476c3f98c229bf35e86fa792dceb4b3864761dd442c294e43b1cafe1fe086cd1ca5e1572fe2b3753c20a74b663b536f6e686d9765bafb10566f2b5cf02ee24e3dc69cb2be9392c991848b840418835603bdd83b2cf0f5df25036
+TAG: 8694b1d3b13be94fcce671a810bd1283cffc0ef2
+
+# DIGEST: 4f498d0aa9205160827626ef80c163275eca1f78
+KEY: fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780a
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541
+AD: a11be112a72933c7b54ed4
+CT: f72c519566632f89513f3f278407845ff8096a5b63929f0ea6009c3cae0dbd853662c4017ee5729eab92f2c475f0a45533de67d4b941d4b16c1964986d8f4a16cc12f02c28442ddf5790f321b3942cb65964587f3fe55ab28064c52ce3d3598d3431788ed2c26fe1b196abfd35afa0f7c8206a6bc71d61cc4e1a086c4cf8c75274342950e4893ca3b0e9fe95
+TAG: fa51343cc9c204e3fdb1d9b5af26119fc874e52c
+
+# DIGEST: f0901e8b8083c39222fc940384eb73cb96b22892
+KEY: 41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a7
+AD: 2933c7b54ed4fad0be905d
+CT: 71fd9ada130acec7deffa6a53eab506bb5fc80ed7e98e656a5282cd88cdf9c253a87832ac42dae0e8a476011b11cd5c075c74b0f29c1c966983f3fa69e00df1ea93fad4942bde475e7ee08ea2c5f6676145c3dfb8d07521133468ce6e573b789a71e59d622587f8fb76e93af95b0c47e15938206774398e50a7e7550e2718270cc1f2b2e70be7be2df4442f0
+TAG: a82a8dd4cf89df1e3103a1b3dac4d3b1fb973e18
+
+# DIGEST: 7af193cdcc8d7f17b55447a81eef3dfdf345bba8
+KEY: 998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9e
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54e
+AD: d4fad0be905d41203f5dce
+CT: da1b99574d59c3998b39dc057d093134c9bb4d0f9a38758e95273694e405b55d8047bf119dbf29c346ea5318a13c8eac769230c085cc2b67e57800279fd47aee9f2ba8e572bebb9f231e954430bfa53bd193ed74b4dc59d6c6e3687451c95d996c86283f10bccde027b90be52f6e20032ae1d83aea8adf183010f4fb90b9ecb96b6d79fcb98f36632079d35e
+TAG: 9dc29a1579727361d74d6db3e9d619394310261b
+
+# DIGEST: 4ecf44faa266de0904b093653c4d623a543d12d8
+KEY: ad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be90
+AD: 5d41203f5dce998f8fb2ea
+CT: 5e1086339724c5489cee84cd57e1b188bf83390f0d264e495c92040a1e56a616d5e2aaa3a240592f65ef0e1bc65ca5e18fef30362fa7b38749328ab2cd7d43c5a37931597d975101e59d089f03a3d99d928cf50db01b3f5e789d4b8b4addbca347f68dc94c17944bbc17bc0ed7495a800c6faa9c87a152e792a11ea7f0b551ab2d5377d780e8506747b67ba783db1f7ff26becd07a35f4fc178567cd
+TAG: ad3eea5bc8aa12011332730a3d2adb24766de087
+
+# DIGEST: 92a938017497e0762115325c40b5f7c138d5c6f6
+KEY: 16417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da0
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5d
+AD: ce998f8fb2eaad409ae021
+CT: 5fb310ed46bd64cf198dc4b2a2e03a1cab6615e1d50179dd050cd538851669ab1ed4aea1970ace6463b5a910bf5be01e8d8196d6d0833a50a330531f61d962a4fa1767e958e38b4897514b08114e9c1ddceb19aea5d5ee079c3aaa8017e9ab7ceb03514f7d393ed60ba6fb88f7cf8bd93949426083afc9205052394680a7c04fa80c2f12484dd44047d80117e54cbe9105a5e895128dd29e99c4d955
+TAG: da935ac0c6d5cafc8c9c2139f848d68e93e7b168
+
+# DIGEST: 6b126413a7bac1069cbb5b338c158463a242d607
+KEY: ef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2
+AD: eaad409ae02116417dae0c
+CT: 553c974dbb652bbd9a573ce72b9df30ec0c01cd04c8c706d7121983d8e8ce23436bdc2e3bb2134af220dc1d70eb68ca340c3e4791755e5b7101a04de9f8c455c81c617577e2c23c08eeb3b23bc959e4870e0d64cbec4c1d276d31f7ad19190f0677d0dc0494a8053476591dc5c87cba04248cf5c7c2e17131af7dd5b794347045ca4fa7b30723d29b22c509ed91e95fc456cd87c5e2b6e3e53472204
+TAG: 1d09e80e11a72ddf9beaa27c8cd8832bc082bf79
+
+# DIGEST: c72d214b42ed66ae0822fa9f3bda306c7d58cf80
+KEY: 16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae0
+AD: 2116417dae0cef457b9e5e
+CT: 8f269f0114fa47b84784dc3ef9a084d9d65e8bb10c345a9a9d13100860f2e713208c5c4886b40989cc165605f5719d5a8e76e146e6a5ec822a1fbd6b237bd0f02d41ae5f26032c202d5fce97ac0317c28d80b91343131ab3db438962b2e52bc14cbc286b50c1e4c9170e516461e24bf920c470ff7e2442f755aad133cf6b3e20e05669f5d86bd39a04cadc29b2c37dbeb89f0ff7192f497b3e157c4a
+TAG: 930cb7a078b1f1312a1baf186c8ecbd3cf1eb7a4
+
+# DIGEST: 9faaa58dd34a192550c3519f8c0aeb2ff48dd388
+KEY: 5607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacef
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae
+AD: 0cef457b9e5e16dcc5b6f2
+CT: 9e3b93e29ee6c0825e0150fd63a887227470d524fc52d652db43730c0c4dcc0f0c2f6dc2d26568a61336082ad638d91c4a3e149e0680321151771f52eab69a579b908db93d7a83d57c360f99de2b4ef1ee6fe905e17f02893df19073b2afd26da1729775ea4c6adac3bf7b50f2b7a8c3b8fe09ec371fe597d74cd15a32ba97adf813508ecab5aa303ecb9c20464a7914ab38255930448f990b058c89626024ae066ecd13619b0291c37297f3
+TAG: fb23b5521faebef99b281cbfdd79037dd351b7d9
+
+# DIGEST: dd5e6be3644dcc888cc50c0b2ad0d55eb0407fdc
+KEY: 3fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e
+AD: 5e16dcc5b6f25607f00d03
+CT: a042853b92cc97b68982df3502800fe9ea7d8e7962002b7d8fca0ace62a7e4b24162624be865ca5010943f469b5793eb4fcc877c83b94c176f67f074704240e4c3fe3dcb1dc4f0f963b7550f280ae18f1b0bf2c727da8ac286386d852a71bd1a0b8cb2b39b3ca29b5570d212cd43ef0dbf480aebb6e246f300663a3e084e15affd00e44b11e4bb0afb7ba73ab6a37208fe63667d24a94f45a78f1bbfff37c5975a382e173347b11ccfb0ef7b
+TAG: 639c107760b90f4e21dee961b3a59f8ae6133f6c
+
+# DIGEST: 1b8b627e1020d71318511d4c2078eed315ee0b04
+KEY: 4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed51
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6
+AD: f25607f00d033fb95fb09e
+CT: 712d1d5251c85943d3da1cf4ede4e648c64177447cb04d34c4417fb4b89676f3a59501b9da58d94c355f1c94b3470bded1c34c49b555238d3522e074f5c60cb0990b04d953fab40ac8c4589d16f7006de59a929b761cee5e4e43a708b53c4db32c49407697a65dea4d3b279fc0bc343f35621cdc097635affb7dcf17f12858cc20629461c88967b4a508703355421304d55ba1d4f07ac5e0d58b8dd76608c5441a0b7f8ae992750e2a0085c2
+TAG: 837b93fa27d7e8954a0e790c8e8a2f06a0a36c1a
+
+# DIGEST: b7370237d402dbf76f1a431cdfbb37f41ef2ad4e
+KEY: 780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d
+AD: 033fb95fb09e4d00d6172e
+CT: afc5e2e40692708b77a11005f8e5f8a81bfb418a9b1868ba8ce95d8c0d8a42872a980d8df4ee62e3b7cc1ea14f5681b21624f670c9cc38c39e02db42a79fca20527e8fbd84a5b54c08dcc3b18ecf34f651a51b922f634204d2699aa41e0db44525c9d0702eb7f31004876c2b34b60eaa9ec7d5a81e4878ebbb53fa7b113899e705e3366ee578cd6d3f2828bc32e3ea7c303bb94862fe340c9ab91a8c0b8d64471fd49107935802d48eae18a6a1d77f71cbf93daf609a91b0957ab733
+TAG: dd5bb4c15c4f4f87b676e66c6b9ce50f57b18657
+
+# DIGEST: 0ad0e709e40cb2fd662020d420d97ae50a14adc2
+KEY: 433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc0
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb0
+AD: 9e4d00d6172e780ab8b700
+CT: a56be93b1bce1546c8e2ce1c44fc0a2551a82f8bdb89d6caed27589981add67b4c8f1c068d00c73b8821f42bc6268a4366ffa87c5eb122829d58423ed30015ffd10b2c4f4120d600bea00069eb909470a7c8cb95fa74b668ff756a2715635fb6603c27bfd9ab0e47ff19dc637bfb7294b5df8fbdb80adf6c7f1ac20b7a833c90619544e9df8f4b6c46846ec67dddf08896cd7d2aba20422fd2ebc287458b5b16825a2c938f7378a8711500f7968e2a46a4b4cd4682e4509cc79cbf86
+TAG: 265618c60124dae5b83273f274b2c021ba1f664f
+
+# DIGEST: 5f9967a8fba7184dd97dc7d5da22ea785e0ffbbf
+KEY: 1c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f419
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d617
+AD: 2e780ab8b700433a957a74
+CT: 42c4a44d5c32c5506e5e1aa6b5d02294a7a3f83e0b69b86b3bad5fa159bbbff88b1c691f19a94b9c09351e4c2da5106b4a98583250bf76156ba41605a78595410ef30fd5eaf6d7000ca24d2e3327d9fcd69ac842f31c7a5ec7798c917ce4eb0d1219b90092aa680c73baa42c4d930b3bcf3052d88d216ad7b52caddaae916600c6a31c9a4654ce4eb528c355d99a3349035b37b9df8f2dd07699631c54c6604815bdd16d9c06fe27f29864f7dc6d340d1c6d834d21e1dc79d4c716b8
+TAG: e8a35426e7b86baf32f17a3db30ea0bc012a83a5
+
+# DIGEST: b5aedaae523d9d396ad1d9bb175bf4c7c0b03eb5
+KEY: 021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b7
+AD: 00433a957a741c9eb80f2b
+CT: 29f67431802cb52308b51065f1592c6def60f3f503bd12deeaea4916ff8dc310fe84ac7da36cad4c96cf115862b2796d90a95f8f23edb3f495d72b0f71552975e37e4105dd70c87a3273e46d62e23db8a2504aeea3451ee6505b0fb0d236232861dc006320e36d9828e27d3a0fc607c74bbbcf9c94363ab49efb6e904b741d2f6c93c2e55ab9e41157d9342e234077770288efc77eb95b335529975636309836349d5d18fa7ec643e972ed0e9911f21eb04279ea8bb0b04e9b9e8cdf2c4f3a039e0c32148a50a93e0eb29d9a
+TAG: 093eac58013a426de1390c66b8d4a8a52688a3dd
+
+# DIGEST: 52bf12f5594b0cdefcf977c07626e8748cec5425
+KEY: 9da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a
+AD: 741c9eb80f2b021b144476
+CT: 170a91c57848e7fd097f96da09530676f65ec1e0e31cf9f8de86bb5aba87a311d37188abd1ad16fc4f6d8201b9dcf3aaf895fab0154c301464b9c9d1a082d0fd3ba717086f2d5d1b5b2e71eab58a861b53dc5c3c45b0dedd334e308648c9185200d4e0ea2e5f26bcb0bc6964d63aa548de958549aa2d68b455e46f2ffe6f9f3e8b59e18b23672600f1f44247600b43131e7530b2859fd7b8fa5620dc8da0b428f5a1e78015afefa79b504e35e1148fbc58b982179002125748c76b3d283bf493cfbc32872dc1afd006674d15
+TAG: 455a1ec8e67c5a7af2b979ad23c6ac7b5ab3a8ea
+
+# DIGEST: 900a1792a921b6a253c47013c9eaf01fc5c880c2
+KEY: 0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f
+AD: 2b021b1444769da00fcfab
+CT: 919a222be8cb73e456dd156c699448211b709e63886967b73a1eddff4a6ae575498823bff9d8a8966c22f8077aef5befe70492175e31daa749fbb0431c1880a8595475a48a299f082ce7f57b2f0a24b8cb8442041bc93e01e44253085685a056157ef6f75331566ab98e1598108ee47833b2f12764ab1ab7b5fee647e95599f2daae053cac2c02413930f81eeaf94ce3dde5f543cb219ac32eb20bc0d43ee92586b3886af60736fa45400d4bc848219d06e8063bfe739bd44fe96564d0437ac12ba99c5f02bb3be4f8d5f712
+TAG: d66f899357f64957f10b00a48e605137a8c830e0
+
+# DIGEST: 88d7ec35d88ff113703702955e931e802fb0d8b8
+KEY: 060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e71371
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444
+AD: 769da00fcfab0f5f93b511
+CT: 58006dd9eb2ea343d8bf40076a71c209375b5ed356073b946dab0617bc456391fdc21a93801557bb40699eebdf57693107f73ab0d777060569d6a300eba25c9dce54c621a25991b43ea18b9266c0b4e2571d9870ce9ce2e705e0a5b7da6424a579c3a890b9ea99c83d909b033c59ab2e0d9d48df70a04535a84738fb355ad579fad6e48803f5ef13c082f83f7f8f1f603a91b33f159c5157f8feef6d9f679c0992f726f05892a12bf6b7c2d97764e640e0174ce82857630da3ca7e032ec999e528fa63004b49c35661202ffd334e3e1e266a92ede447a0b876b77df4
+TAG: 8dc2fd4adc9331186eff899f8dd1acea003b8316
+
+# DIGEST: 8d8493b55d9b74892e77d3b730588c087ca9b1e8
+KEY: acefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcf
+AD: ab0f5f93b511060c9c5f3a
+CT: cabca6bfebb503df1a2b2cfb11c23394f1ee57edbcd0c8acf4546dfe383d7b71134bcbde9dcbce5bc4300964de3c9c0d48de13153a69101643c48842bb0efefe9e928fac973e69817a7fc35722e22fb21819107424db4836d24b429e8eef3b861099d58aef6bbc23896f862fe41ca72a34d9f41b8bc4daf96f8c7b4e01c3abf5ae4a7839785fb7bbcf50a93a9d621770797c68483602c30e2c8b91acca0f6dc08346c851e1d5f3da4eba9327ecdc56ba52b7377ada217b595e760935ab5c681e813454b037dd6ff31f67fc29fe84663535c6a259161d6b16a7d85d6f
+TAG: f59f90ae7624b9fdbaa9cdc72f22396e98b4331a
+
+# DIGEST: 4cd92ac16a807d2ff180df75c47d848749c7ef46
+KEY: 4ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b5
+AD: 11060c9c5f3aacefe61b18
+CT: c5d01436be8f519a54eb38637bbe20c56e6bcaec1e9557578cc1ff66658b83ce117092f33c40084eaea1db6ce043b35cd2a55f109db71567ab7039daebd2a363246b48ef0daff133d51b21020270f165056ec0ad3ef67f3d4525d14c50730ccd3d0990abd52319010f3afcf2d312054f6be80adb71ef96cff4377a35c63949caddcd52dc2a8604567e7894367e38db843060f8a34d6c6bef60a0ef47c31955229d7edeacaebeacdb45ad147b1d8874846c333a1136ec0992f9847465b07899e7d144555a8a35f65c25c7ee092de14d499968d7503f106a11cb958d9c
+TAG: ac452c9d89f0af8ae0ef497b74631fbac1944863
+
+# DIGEST: 64ee218c0c96ca8e2d2e50cd809d61ee109baca6
+KEY: ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c445
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f
+AD: 3aacefe61b184ad2463939
+CT: 37a3f88b2b27dad02c71c257d17331e7650f71a4632fa6dcd651c96dac0acd00106494e7aa6d7667a8c034b621608f5edcc4ac37fed8a5d150552e365eadeaa665e605c158e86462417c5c161bb4d4d1797718866368ab4518d7bb109a55ed2e73d02d9b94ddc624f869881d8d4762e733d44dc04498823ac137ec7ec7ea85281c24dc9f63ac2acedb9c46627f825977c58c61fc930b511098df24807d7a5a84634e10a4726a7f8c668f5cd07898821958ef074ba4397631be00269b95967538f4766584ddc1479b4bb104ee2448ce7186ff501b46184206660cc091ab5011ff99cdc39a37f6478b1cd82ca1
+TAG: ececa23afb81adc0b576d49f83b454a39c15c8eb
+
+# DIGEST: eef8eae201ae4e5af32ee74bc724e13ae5ed3978
+KEY: 3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a2
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b
+AD: 184ad2463939ed518ce97c
+CT: 1112903cc97cc872c44f156068c58992f1aca2a0a8f1b8a08e744ac1dd0efad9321556c77e9c64fd6a36041ebeb980c0ff064aba672e4eac6cbef78235325c412d80ba0bfd76b740623e457e0e600f375e47809c56c1b7f2f5359d08fabf5cc6beda669a495813aa0e8368f386fb9d7ae42f64a52c047e0230e045d9ff1752315af9f6c4348d7e685b3f3e2daef06e41a6997ed11b3fa0f2b15f074b1362c3096d010671a8abbce7bb5c729fb6babac9e685a1d64ffff97c17b33396d2fe2a920082445fe75c8d924ee2f5935dcfef6e9a88372e2c03be6a4447153e96d81f7bb34d9f9b3ebc9678fcded522
+TAG: b32214b890415a87105aa401c188808ae0a106c9
+
+# DIGEST: 2fe67a81b41b094a708ae515e28bcbde3bed724c
+KEY: afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12fee
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad24639
+AD: 39ed518ce97c3fdd293d72
+CT: 9fae07a37501e2382d004a399d8cd95a9cb9a4b6dc038ed7bcca0c85073acdffcc66a84bfd302c48a4eed40a679d5658c8eeb76772cf93584a8decb8969cbe7bac022b18fb86c7bc26f0974ae4e03e36c22bb7b3e02d182e25cfd52ef7bc890fe0f5935847f8652d42965757105e88b327e19308c88cfcac46a47478ca7a0643da97478b127f4dc45f61537394fd4d049d59e8361ccee4ac86cbb4e14050ac07dcda7495f1a1d34095a9f7d697cb6b88eb9a6421c7ab338ab4d0d5b2bb61e11ddeda49e75bf6d0bf0d12fed98d50d65d33e029cf341f0f7a58e85bd0568b7cc3db803ec5e9d0cecc027d5017
+TAG: b820cfcf74d78664b23fc2aaeb20bc8d73499954
+
+# DIGEST: 33d10d6cb5dc80751d0f8e370925d7c86cda331c
+KEY: f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce9
+AD: 7c3fdd293d72afc09ffdd4
+CT: 1817463656d30d6648bc628a45e20e231a4ff8dba4eab244abcb198580499c696b41cf256352023975a62e66d5359f9bf656cf098819a5491f1a113a06fe4d56ab4629665b93a017369a1e2d22f817a66120197e20aa92f174b5ce4e158a272b51acf766858864fc5c90c1ebe9bf79b61f327eb12a106a38662bb2317db8113c3301f00dfc54bdd79ba7126f448cd9f3eaac475bb62eeff16fe2de45af646929f797f69163864884279eb35ec9ad6137a694d2c72a2cd2fbd25cce1ee90b73b9c7e592af463057737a1db4da41b479abed76d3b601292544be8ecafdc43a48129ecf1d94dd9d59183385cb0f
+TAG: 58d011c758b6b59622c5f26faef2f7e2a97aa82a
+
+# DIGEST: a29f128842a48debb60699ae0df0da9a9b5e5dad
+KEY: d299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e89920
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d
+AD: 72afc09ffdd4f41963249c
+CT: e68230ce6101c64176f56a57c34ee54ab6e95b7aa28d3e3d262fae71ea66e5f1699e31b3f9cc1337d2ac193b5b6df4d1d10fb86b77c120faa9f67ad6d9cf98c49e1ee572eb8ef497611e6b5f84ff42dc3a2461a326424ed0e2c5978ab4175cbc15dc4cae9eefa24ddff8d055abd113f0fefc3af7405b153ea1fce067062a751c306cf0eec477d4b9a068d5032c410de991497b6c166233036841b9c1f6313fdd216200007089734d096189f4c6cf0a0e5cdd2328d8514d319d5644003201124ca71df0bebc8c61595a54a6a85f9a88565a0f7b517b20488da57827caba252efdc6766cf860f89c21128ec572c2a5e44c8b92c00f8d4306201a1fac67
+TAG: 97931b4600a3993e9c11e01b7fb92f01c20a213a
+
+# DIGEST: b5048d1efa7564966b6cf1579cfb4ad8e9460660
+KEY: ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffd
+AD: d4f41963249cd299b92e55
+CT: 7ffa8c3f882de672b6548e722bdf64671ec122187bd811240e0c8a62f7ece34743f3e8286cecc99ad2637f960134d80230f4b358422576025bf2d2e25cb0b2be8c93fe8ecb1a2a84367d075b03d2eec5c8ea3bc306727733918762088ecb995b61720cd294bfbea261cce90ba5ad6f5b011bfb2767f4388f1c2fc5bcdc9faf1517b734aaccd780328a0cd3c3e8a82c279231ada466f5789b0795e56c9b14073b9900046c7cdb02edb55c96aadb8d703f0f6d739d0788447fc8c47ae9ebf40f38355476bbad9aa239373a6fd38d0d4f39590d70cb1068729ed8e685fb905685dd549e333c670fe07abb04e7af6b6855ef574913c06c595df508852081
+TAG: 48d4c51412885c34bf197e3eece02ad0c969ece7
+
+# DIGEST: b6e68f5f0dfd8ceab56ebb657728c9bc5129fdf4
+KEY: c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f4196324
+AD: 9cd299b92e55ca24d8c078
+CT: 0638cf64bebd174c40cb462a85d7c6ea529619e2a7338e829f91227e5586e88e11bbf62addf813475e1bc024b60a2f8ad72541d3345898b1833f28db4d9e2754807c3b2888e01584590f879ffeffc2cd66973c65c3712f7a7704ece102a5b67e4d7414fb53ad9c16e4aa8d4f310ed787dd8c23b008f0a9667b84ab7e429ad7d2173421c8ac06abb1e4da82493a01a6872ef6cb603ac754d96ec48cc15ee9c127e321523aa02508595edae2ae4bdd453ee8b6326d05166704e1d358d7efe22c24a40be281cbacfc97383c4a0ef9f2aa45e0b31b06b8b5ff75bbff51b6c77880093bbf113135bb7c251c7123bca5e35e311b55fd7ddc84e507039cfa81
+TAG: 12d34c21d32010e1815b550a05b971cd6153f281
+
+# DIGEST: 853bc7b9fbd640cc0654fa5533ae302e398bab35
+KEY: 13710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e
+AD: 55ca24d8c078c49f78c7e7
+CT: 20e84bf92ccc563048b5d130c8c2260974171942a26977e1b1716c1e73007433710609261743a0320598c80712c1c50a3e8afc047a5481ee38840486001ef9c7ee14c42e4b41cc6238bbc2c00f5f1ec121f5df881a12e98ecc46987a93fa2ab6c76279850fd2097f7312e699d10556c4899ba330ddbe52ccce814fd575842153698cfbd9602df8d0ba4765c6483de83232d9705ca82a866b78b1c782b13330b8637c0de7a0ac028c7da0a5510373d56a48e8bd1e59d269fb69ba7a73b1bd485859346d060677ca386c04f6d07b295950fa3ee91cd38928e29a38128b8ed73007182ae3870630b385ff6f212413260d083c61f1e537b6d1057f3972553938adedc275bc6faa902aefccdf13f0
+TAG: 825ebfc57f0daefcbd118e10e1d324056723a87e
+
+# DIGEST: 286a92c480192206a2153df1b6d0eb26e6507da3
+KEY: b8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c0
+AD: 78c49f78c7e713710a025c
+CT: 6da237176c778f67e98f09fcdc96ab9a54a9ece12c2e6de1223dc1a22c74902352c33dfc993b398728b8a62206a656ed0ac1d49cdacb22b9eb1ae70e9b7f511333054dbc26a26f837ed0213ba98820c31104dcfa60c6892a98bfa0a41fc220e81c219d3ab9312ddc534f314d35056901d04d485b3caec47b746445270e2276e02e8f1adc54547ec9efb1ad44354b25b5c09c58cd9480a68e758e87739888129e337419d9638482cba7259f5b150891818b58b24fbdf6211c7c5976cbac2e10dca06d425247005385996a9649240d680811a5ee4229d0984c11291f86b1e75a066263d3a738da0c98ba24054da15f6f11f5c8aadf24b547016f336beee210877b25e987ea0dd1abc087078d0d
+TAG: 7e93d9d86375891b928bf21763a87e31b345b49f
+
+# DIGEST: c2acb0c126af5282abe14058066631fd0c658571
+KEY: 89ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c69
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7
+AD: e713710a025cb8b9d71d29
+CT: 70e4d06f468de2780565a300966e410ee3e0ebbdd6d29b8921a047fdfff86da5f4fa2981c1d7a4013c480b8ece1fad84ea27ff0b87bee1bdb88a661954d078bb65bb6a2aa1ed5b00519bb0c56069774dde08b06bdf83335ea9c8702abb9098015707b00122eff2f8e5108e4fd6cd719131f919591d0c5198c1d975c4f038ac273cd6f9ab2f8136b48429efa57c6ef1a239a693086025bf6db218c2c26bf0ff823dbc08944f06c7be29278baaf5039e544a54de7208e0392bb5d9972f3c3a7e69532b5d4322c71ea4af6fa2167996145538735b3581250c1fde20c03b14d01c101a0a04e79f6c6a6390f10cdbb3fa3e3fbb03a64132bf82e965039f0231d69ae71ac20ce11bfbae7229a90faf
+TAG: e3412c5b67009dc185a9b38d00e26e9cd299e550
+
+# DIGEST: 500e5f2a56bfafb2d93e26224c9c2df562589f23
+KEY: c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a02
+AD: 5cb8b9d71d2989ab33e978
+CT: f0d7b956c586c029980ff8a78a79df78d14328a608b47cdb8ca3670f4bdca883033f8372b6267218b07dc5b9aa5b8104a1c8c3fab4d6f3d39c2fe8d7c997889a8deb970edef03204852873f1f9f07e41754996f57fec4d72cc438c7adf58a9e888aecc2bf6d7d240431c1481e7a0c9bd27743700141b7be5206a027165f9ae82cf1f3aaee97dde5ce850e34bc714ad67c617c6640905b1c067a214a160df4e787b48cbebe465cfeee405c8611c7d376ce913bc3a5c0e996e4cc252a89a48ff09a18cce553dd5ea3ec9b7d8417abdadaaeea44ff233ebb45fb6385fc2c4d9be76cf2ab7f803cae25fbcfa68bc05cedb14492111696884995046b5959389081690e7e4ec9c1af09a482e74283246327ac73e153a515cf974176c011180
+TAG: 0c5f76ce31a1d08772b950754a82e6c5b7d5dbe6
+
+# DIGEST: cfa6a42a2cc0ddf1c7b20031c95e331696bb9ece
+KEY: 85a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d
+AD: 2989ab33e978c4451e3be5
+CT: ac2c01cbae12fa7572615a755522dc5c0aa6d7782167e4459e5dcbc6a5c2cd8164890d2715a61e4e80cc13a35c48b537f441ad1bb63e2d3eb2cfba711fa3ea878cf0b4961ea3a016fe0a918f7683be5a243f02ba3e651950f15d4df7b7f144a57feb3d6bd50707731e273a2b78d7733be4be6bbddd4aede0ff29ec67d280f159210ac1ec62500a8f0a2c17a6d05114eede2ef4b393c4728d3045e48bd381d616ad13d7672083b55aeb1f6bf0a043bdf37712cafc7d57d23b1fc96371bd111cf0facf75d45e28f45cefc76ae50a5a90c00915fd348d5dd2110174ba52b67c6158c1ab541ee57cd7e29155e6a18bba141eb6b5ecbb2f22f68e37a695a2e37aeea8e2f66209d9664227344facface4d99f2ecb03f39f33e804488bf9293
+TAG: f087647a39f5b594115586268ac92bcd688e1580
+
+# DIGEST: 2d1b27948de83e32a0fa5be7040d896824ac1fe9
+KEY: 2feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e9
+AD: 78c4451e3be585a29a2af1
+CT: e750bf0d24339dff581342ad50a30cd209bb3a4ff8435fa17428c504aadb7520804eb83698f54c13532655c032b83f824cfabc9513faeb6bc63641e9c76c019964699ab8bb31bc22c0a1acbebcb76a095cac94afa630030e036a48cd49ebe0af001604bd753234e706b48183f2bf93028267ba8622cd661910a6e147c8af31364f3aee50b14a40cc6a8a0227615c4cc6a139cb2a33374145841cb58c44e0dbe5487294ff9e3691d89666eca0c3edf6b9b026abe508f1718a86a7ec35c2719265fc1424e445335d81afaf02650f4dc41d752dcc2c272a006be8e98bd80250c66a616ad87897f7e5b9a8a00f54e942914e2339fb2e08359b3f78f8b9c8927a5fbb0a810c4fd826db8e0167d535816e4b2d6d4d199b96ba1c3718a564e0
+TAG: fd21d17bd5530d73dec0bae15222bb76a8903d15
+
+# DIGEST: d35ac8b9ece76d43f1497ac8681c5077398bf2ac
+KEY: 63b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf7140
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3b
+AD: e585a29a2af12feef71e10
+CT: b1def7ba0c05f8acf42e15cb052fafd63c2febcf277cc6aae7065d606b502852696a6081d096de91a8673e3a96ebcc2b0120ad68a2b1a85457dfd38e187ae42e8279c3e2b57b1f7d69e11a51d1b8d7165c6e74d84fc1df402ae551134939e5a17e28d5f415a491c12b3c70d473c370542d7794103d7d639d9dcdcd5f67ff7a2420d2d38a433ec767efd5e5d9aa64ce3570e116b50b2514ec29a7afd8a831ce30342c2cc79066eb1373e4d44fe432271dab68bf1fe2a6a1c45a4060943825bbebf790a2298bc9dbe4891320d3325a309041b411a629346b12e3e929bfd1fe5eff9068713e6171a89a2cc54085a2224792ddb9a7ffceb5431d1b8fdb7d7de82c7db78d7f80260333cbae973c7f3ced0752e792546f2e65fbed672ec987172308ddb2e01ff8f34d767efcf93b5d
+TAG: 989b11b610e5852a480286b0bfab442e52548f4b
+
+# DIGEST: a3b33fa67f5c471a60a63dea915333550bf3af04
+KEY: 99200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bac
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2a
+AD: f12feef71e1063b0b4e6e8
+CT: 046bd6d55b37dc68cd7cffe008316544ff781e42afe4200864178ae7d666ca3f83f25ee4ab1f2847e132d762225b87ea77dc30bde8f3ed156251f9366573cc759bb5bfd129e3c3f799832ba8b489ac3616c3dcbd30ee75459ce15e7885da51ca277ddffe5756b22781cfc00ad7eb1283a4ddbacf5f2921b155b4646335069c03f62cc01d75ee33b40a20f46e2a8e9fb1b3b02bb7d7cc56913cf9159f12e2df6b166d1d2a064807ff296f774216fb4b1a31f3b1da9d9dd6cc76f6d365a6fcf6e7424694b88bfdd8af1237cba450a7ad1bc8bc7ec3335eff5edf0c95f8f0ef051406513c910fee9b51326b4e17cee5446ed7477aa9399c4af75ee25b56154b30f410c47db1cf9ffe8740e52501d4295bd3abbf75b88691d50488b07f38abc8a6bab104a701c8a1a2a018242105
+TAG: 9347df07b84f8055901ed051dddf5737bf24143e
+
+# DIGEST: fc45f684acf19a1dcbf767f671396e793430d7fc
+KEY: 3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cd
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e
+AD: 1063b0b4e6e899200304bd
+CT: 818d8cfb3cadad479e68b2ff3f8fc79e098ac47e2bd838fe955af0a66afe07b216f744f3d1192bbaded6127387742f8d45bcf43341a3f2bc9be47fd9ec413ab0e2afae4b34ddbdf97988a3a3af1b578095502f79189dde995b234daf811380fb12c60b0910ae663c195fb5a834e7575487f1c4453ae20c97b622bceb018623a107a26a9663a62b0ef0ea12e3d2cf37b4ef2770c977c06a17bd6fac29483f6c56d2c4b755e38fbace64b1ee521ca994b86d2b1f9610b7c46d1b65a490b56f4518de3fbc9337699a5c2c91818b8df531149f6fbc0860d5ab93abc5df22465aaf6207f28eae0792ceac9ceea56672262960bc6d821d0ca831ac1ce81dc1771f1ee8577fb3ed0b72a93b80e62fd3ce2afaf7668a0c4c08c99014fb254381e02979d69b2ef411f67d3da7489dd0cc
+TAG: 26b2ddcfaa1f7ceac677cbb88bf0839b9838047c
+
+# DIGEST: bea3f11679bacd98ddd996236dd603d319aafc6a
+KEY: 7d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed0
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6
+AD: e899200304bd3508132a02
+CT: 35ad27b44bee4b205fb9224755d1d79d5798db15916050287c9ec894e706331a290d0e32c08b5f417e1cfa07a1d176a7830e5aaf3cdedec5ddf4143cffb045f55cf7b901ce3de905ecb0a4541db8161082cc12b0872d3818e793a379fdb9131b3d521ca7d787360f830ce7dba5f79cd204dfff53ace458842153c3b0489ff04fb09b9f2a4ced538c64caaaa09713000ab48f0ca6b283d5a59a7d1845ef228261ac41d1a71a134d28bfdbb92b6cfa18258702e33f9be85f2848fe0f052ea8133468b70aa86de44adb5f31d2415bf852dde608f1e6673334416e8b17b3010dd53d95f9a5322e025a9b259f9cae0158f8864d98a8297e2a3140ea4ec962ae8c904f7a5108eea7583f13d977008d685aca7e8fa7cbe80645aa1a016e557a6234c5c96171c017b8f4ef1a2b9a66bce7cb365011df84ce4c1bb1ad99a47ddf
+TAG: c2dced82907168cfcb15347115231c288f5de339
+
+# DIGEST: b0ccc9b5ae13a7f8a01100af61a34be7ef6ccf6d
+KEY: b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3d
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304
+AD: bd3508132a027d1ff4c047
+CT: f454347ba4e2b6254e66b97f8ac519c2e263ff43c65869553ba693bbb54a96c042228493f97292e1f5798e73c86ad8f4c521e0c4f199902e534388c9d5d2d2c54fd992a3e073381e0cb2fad75331979c76690c8d8c1bf3e966f7bb8f5dccdbede2f628618eba828c8336e2914931613e12f7ca9e0b674390bc6128f9e18f3491f98a073013d1fd78dcb4f0ae4eabc054f8935563353c4b6bb44c3bb99f76568acac0df85200987c67441d75b48312e98847301b3db282058a31f74197cbd4d1ffa6eb69bf67e9cce44512d35b9f141231424dae335797bbb16c16571fb607908324ab86d8034341e341f3a4646a2636ab5326bbf1a63445007fe8fe4d5279396c1a36d04bf97bdaa5978d9c4e598cebcd80a1a2f0045f1d0ae626f92d09f999bdcdbd889de2e4cdee882b757911fbc8421312c1d345e3526356c9cf7
+TAG: e7bdc63b30d2adc79c33b0cc32143d2894b48fed
+
+# DIGEST: e2b953c833076a52442a7afab46150176c47b730
+KEY: 4706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a
+AD: 027d1ff4c047b3ef4f57a7
+CT: d8a6fd43a147414840554083c11d5fbe0b12d2298af893294f4273df0492f5d8bcefe2c811587e124d26f8cd7c737b2f848b2b25945d4f031db45794ee24b81103d172c0d0e457059eb972371f275a0c03737ad02b4f8526b32a39c460931f05914ab3c2a16a48405bc662693cd08e2d79cf722b9d57b998f318f25dc267395c195d83b32c87c8812b65b6db999d64560d8967cd0ba99445b1601aa03b290cb6803a8e6b0196bc9ba6dca507fad6e4041666735747f08f0bd56f1f5097193f373ec062750dd462d1d6e987999f7d0f06fc1d0144f98fd163cd0b0aa64f2edf9e29afb05ea1f1d055f740e162cb14466e01ba68ba9fc942a60128e2b6d58ca12ec2a905747c3035f7579a1eb8abeaff88413b52624f6372fd5f2664ba69e71b100178b88e365ebd0489c48bda8a4a490df66bb167de1fe77e14318d46
+TAG: c2bc8d71ede61ce63bf623a1f2822d78b8a7e70e
+
+# DIGEST: 8e84935ed1bb79dd38ae38924952e1105101533b
+KEY: 1c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c0
+AD: 47b3ef4f57a74706de4b38
+CT: c2c1f17e309846fffa55e6fe4137029fb8506ccd4b238523812d61096c4a533737c22ef0f940f720d26563d2c7c90a48c3b4ecbcbbd9a641242a68b466f4eae6f663ddf27555b0b492419847bf333f815b7467ac4ee70ab683d37c1f966ee8d40d34c181ed1298d2084b634d4eb49466b21f39909317cda6a900925b32641184c4165cd3b6596806b6482c02353802e5ca12c72f111b0e0f7edb9c373124b5640e06d3163d4516a233db3183f67afeb3cd33db49998eea63648c69f441357f092b5dd5e5c3b69254640ae313b71e741c00cb9bc4944b1bae449fef8a32c08ecd316723a286d25598280a1ae189f4a321cf443135cab43f4721663848ac1373208a28d3640e16e792bad274b2d98b182455e56d27211e97b94e6ecd95bb33cdf8c42f04b5c4536ee4838c1610e90f312bb5b0a1de5825a261b5d08967
+TAG: 070bda84ec98b059629d10d0d0849495d1a8e0a5
+
+# DIGEST: 99ec6b669dbedbe99548117f37189e669fc5d8a2
+KEY: 101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b1153
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57
+AD: a74706de4b381c692ef164
+CT: 352e3b5b2a8a9552e0159017fd9ff4c169869ff3d1d900711d29889c4f1365b1e3d15c7162be4a1dcaa6b7209b9ea600916345cab1f2c1c79200826f180e1f7c92af192b92168c4f73ebf2a671577c5b995a26eb24b125ee24a47f78c94b48f69883b1ee5dd5c9e53835640066ecb26c631fbd18c41a67e59ede2d824e7d7f6d1ddcb14fcccc85a4faa5d46f91d03d543ff87989e8d1b3b2fd87415edc709abdaa7baa5e2a78c394302a630ee14e908fa8dddfe0c3b1830ddd036ad5e65e4d3490321dd450c01bb566427240882b07c0691f2f37c346845da3a8b50e291d5bf9b5572e72b7a031ef71f744acd6a3ed9ea32ada739184b6268954af35c6c293e64c83573e95b166e76ba981ee6f1723fe3865e0f17b28d72a869cc0cdf9c21ff97a11ccb6fb08baa5093f7acb55cd5c534389e1564b187a6bfb9cbf98044d718a99b9c8254967607e0bdbdd2c
+TAG: ee977c194e315505fd3dbf288be63c3fc871917a
+
+# DIGEST: b55f018cb06f74f0a9f76e65a23c1744ce7535e0
+KEY: f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b
+AD: 381c692ef164101b89b476
+CT: a95aae1040d61a7b44194c20233270ac94156ad0d735c30356beba1adcfa9abe3bb55cdd41a4f1a27446afd5221a3abca45d7b867a999d9cc1d89f19cc32907083e72c43f5e39f6b5d5682923914f4cae6fa0ecbc02c9d7c289c39a9a159b714c9e0eccc143b13fc5632ff079d4216b331617d2dc62ce9fa5da2b1c59f413d211022c79ac5550b0c7ae525e0af3d364138353f4ff208215393f5667359b2f97b5852959c6e4ffae26fdb93c1b15720e53206f2721c58c8a7241806c80163796ba087a073eaaf1cd3f433fa24518d0989607339c2d0df01ce1fba94f755ca5c43243f16035506bc7e69b21eb8d2970f35dd282fdda64736c92229254aa6b74e3dd929ae1cf9607950407b01c5fa0e9990488f5d07fbaef1062f51acfd745aa3bf27cfbba630aaf19d02aba5a55b95a6949ddb8669ae8b0f13453a905a43fb6f1fa97fe1c514820beea65a549f
+TAG: 03ea186313e6d0eae129bbdd8cd40f3ec88f3f63
+
+# DIGEST: ac3202e483c67fbcdd751950e1497feb3ebacf52
+KEY: 520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a8
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef1
+AD: 64101b89b476f72b27f06f
+CT: 458997cfcd9de1ef0222884a21e1af8773fc492139b15eeb31c48e5c32c918036618f4969d34c063cf759906a92956fa066d0045e8acb813081a55cef1fecb34178063b4cf6489b35374db4cb422b2f88b28fdba361550f087bf686ae0f7ebf4e5ac6ab0e4351d7682dbf825a79bc9a8ece0f5679517d33593d1fb9d1927e6f944a02cd2561da59f01634f4328423c7a4e1d1d57debbfca349e5fa1fd4735a87cfa8737ca4cc447d3249d6e1ab998f4efd62bb50bc079399ba250eb24cc43cbf3bdb30e1c5a4d6b3f679b742f39f123e75646c4a42dddc3714042fe0651e1efb0078a636d712bfe51208f8ed2ad86759726942a9026e5e158c8f42333601e9fd54457183a7253543f6372b57fef6dc9db5a655f37b265fbfad0693c0504038e36883d61e83ef9faff4a795fb21787949793ae00774cd86b8df51fc5492efd7800c223374e59adb59bbb69ad1
+TAG: 8f00aa5cfdd05b3586477d882fab3bcf49a0d900
+
+# DIGEST: db82ae5d79573da2bd7215485a92063861879c3c
+KEY: 71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c67
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b4
+AD: 76f72b27f06f520c9267cf
+CT: 8ee287bb4179d54a23ac238a457da5317d6f73129f16a288d5d08ce503395ec9354a9babe85135aac28e00fa66e16867a09e9c6c2366d73d74b80544b85ae48ade77800fc82a3ea14a7d645f0cfb19ce2281d2de096ddeb822d838123806908c161b0372771d9281f4471fca2f2fe6d4d33bd6de70b21bb66728f15948a34c756664019369efadeae8d84a777a30d79aefe978f6803c56ec8a2138bc294787a1083cb5aa0835585acd7239a85dc8b556fa78f64f45973e97061591f756069ed4314a2275e3a540417d87a2709b0d22a02c2d6f7a34976290bb83cfb64a3e90503879fc26fca103cf64f925a9c87848c736b349145d86351855216440eea3f6454e4ba4d7316662b04b4ddd0dd66bc99598f8824d062ba29916799859e38fe17fce17c83b83a7b4e90e6b112197724005a70f5440fdbcb6a2b6fe3bcd660dd7078bbbe6b1d00ac7782edbe62ae0ef6294689a1c2d12a0367c1961cd21
+TAG: cfdfda24a5dbec4eaa3d68bebe6b12bcaefb1ea1
+
+# DIGEST: 902d703861f9872e7b6482f854709a214aa98731
+KEY: 9bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bf
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f0
+AD: 6f520c9267cf71408a4172
+CT: be32e45e2b86ca112fdd67aece84c9a4ffe6f773b616aab51eaf3d5d9bee1622f377630d65b496169d5c724e303fcf652fb8275a6b6857768a067a77710ecefdf85666ce3c35d7f0b7394035f220e1d944e823bd2c43c722cd7a9839efcaf23142320d4fee27e0d5e4499e249b3b662f7cb24b48686d533f55707c7f09e70eec383bf1c022bbed0379d0892342914230ac0194fb067959abcb1b7eaacc4783ec10d9ff1ef334ffcebb468008e8f0fac1fe342ef71718731577ae555bf0786d2cbfd2a3c8d7043887a720e514373d248452ad24eb639b35564d5e0638ea4d6a560a4e6073a45d02c0f42087e430cc52d0536587696f694d05a73b8f61056fea619234673ebee12c82eba2a51e0ed0006cc4884a20da9cb4db5bd262513250f48ae4f86bba13fd659db46b38d155532f0c0c54e7a6768c169b9bb420ae0ff504ab632f25759896fe57e32775b65583d6c32941a5294ff47a3c8ffc5ba8
+TAG: a5beed898ccb282d69807358004d87728afbd3aa
+
+# DIGEST: 4becd26b9b5c7bf831523f44cb72c8e50ff8033e
+KEY: 72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49d
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267
+AD: cf71408a41729bacb5877e
+CT: 596949b6d943048a68d9c5e6f6b6b91836c497c3c160337f4b1a3ed44d0db20d00774ee636262481fd61e81d5717feec56bd1b2ab077d205b4c8ac78bf225da9cdf72bc1665330a87a31774e282b676cb1dfb857f32e56806c1d6049594136de222041d5316df307bee6031ee1de0251dbcce0c3fc6f121c0f5cd84579b65055ba71a429acca3938dd0df53647a4a4dcb4321a86bd8f96cca38814937d6262324e1cb76286858cf3c62e9272e1b3473eb7c75a60859142ffe27daf062d0e05b643657a3cc30a0df09c101079547005e22e8cf833e3f0a7c4609e3c80924a2e1e4f61c329b9baf20fcdd8662b6dbd02a4941c3e68247bd00aad3ec3c7d925cce788a05b2518e248d68337e7f9b1c8335fd8f7d0c0ec4454709495fdcf191086d83b71707f97bbb3dcb88a0dc572930ff27c0cd9b93ac1a962e54e726af68a2f1ff4e15cebb06a28c61c5492a08b3bb73f0f7f747968dc6653ace1085c
+TAG: f56fd0172170fe14b89e755f8ae4dd3a89d561ff
+
+# DIGEST: bcf4785d0e3b34c55cb2505b559fdbd525deaac6
+KEY: aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b97
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41
+AD: 729bacb5877e72cdfcfa76
+CT: 4cef7dd855fcf77232ddf499ce5ea322ab0fc48715fb2dece1c954fafe396791c8dcf4ced2f3ae865f6e062d193509b264858dea3d05a13b62e9c958971040bab31fca1b748e05fca1967a5aaeb0efaa7cb2367149e0c5493d710f2862eaf2030a7ebc2566ed4995879cf27a58beada2a97255f1dc09e2bc102bfc47fca7503f39d04311ee546a01d3854574f389b013425ba1c2142b9a8654fd6bb28be2c4a5f6a923b23867b4c9e00463db4a1c774c101e08c911501853791ed3604eefb2057df9e6a522ad108677ba0929132f86357a91873d46d0d78d1e7278e9fe9e29e6c988b07cfef195953435f5a2004a05f0ada6f75cf6a63297b66a0c1cb574d7c87e99bae61a614e4ed5c50271d9f1e8d3c85393a4d219fdb3bbeb43bddca914eba85e041bce2b7a4b211c628aee1161e93fd13e1320c2e444b15bd7027bb40269e15712e1908f03f52658b85786b3378c4d3bacab39d956576fb8940481b10fff63bea1b1f0cdaf656dd5588b
+TAG: 81a4019ca07ecc27430d947686fe19fa9b5d3272
+
+# DIGEST: 13bff121568d7c32b2546132cb4ad490cea9303d
+KEY: 7c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f47
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb587
+AD: 7e72cdfcfa76aed06707a0
+CT: 1a8d2a54eb61c49085190bfe8dd6c6423c6a6c2b147343f07746cf45c004e7ccd780cf0bf41d7f070590d1b649be4df0e9fe7df3919727f78966bcb5991a92016a9090c7976ea55a0ba039b416e61067ea414d87161ad03592ddee51d40d2bfcf53873c4c92d869af7614ae780814aa4aa12a2967cb8bacbe5d40542e4e8c619435c0daeb3b01c55a3eef62c633df798e2e9d7ae350a9a1e5aed3ddc64039f968cf9d918ec57cebd4a69b195c8bb8082fc8af05e5b577e886b7b258fdd7b60503742eec8f861ca6d8f7cfc5262afb97aed6205765e9d236a790680183fa10d302a92a2ccbf8ca3153882c829c1f70a449748a6e08f302acf9f8cbcafbc2d04fdbcb57b581e04d8c15120aff497aab1e8d3b4b2f30d9156a213c08692c1dc2273e6a9c835a962311e9a8855820600688d10e00861abbd63a43b1a5476d9f00c304e74cb254291c51a8d8967656efcba8b54e53453fff0dcb44fb53317611d2ac8bf15a00315ed24d43f861040
+TAG: 3e7df1268a84c4c1b604e54b410323097fa2dfe7
+
+# DIGEST: e0ec91f0baa3c5fd0c50f135517909e26c204af3
+KEY: 19fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa
+AD: 76aed06707a07c3dab6997
+CT: f76b9306112d329d3300d7961db8e83a93de9a1de25a25505b428e14479e142012e4d140bd327cebc7eb5f45681d863beeee2161e0eda1d55f20429fcfeb104010d3db857a7edd43453f0889d8a54f97eb406cf4d0d57e8e86562c55ed0ed4ca292f77ad1362ac5e154b768926aae31f9e2b7f67cb4d6663fc44aa9249604d01a767b7bd32d2124644b7da4c08a5dfbb17ea57c0b7b757cd2719030371112da299f73159f436e39bd3e18319724ea2b89cb82ac19be902d1df0b0555d5c4a375c2df99585defa395d860be8ce4693220da4bac58584e35f4f46de3de7d8538f11c20f04ccdc9daf42abe19f6a4347308ea00bb764e9f44fffb3bf7f7cb0b8d790301dd47c3d823346a01c68287ca3a4641290c51749ea2d56d87fb6abb533283e7f67684069085c16a9be4b38f7fad01c5f8ecfbd4a2ed75f79f86868bdeb7bd4f964c19984c3d4db3f54c25906ef9f11ca9c2852a4c1279d96e07880be6aa2e1bb5df14a2d8812aacf9ff71
+TAG: 29a4ef26ea7f17cc78c25903cca527d06af831a6
+
+# DIGEST: ee7d6f651db434a281b5cc57c2c418db731c65df
+KEY: 2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b17
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707
+AD: a07c3dab699719fe882eee
+CT: 76f61331693fb10e859759bfcf1d105cf9609cb381e016502aaadd2db381a27ae8065064ac38f329b79861d6968ee1e1ccc8bff41bd8c38e82c91e813caaf1db5d8cd420d67e58db6a8b6b8b65566f8dd374490d28f0d33ea88bdeaa1fcddb4ce77fd96c72e5e646c5e5291db6a376a87b0f54c5e39b38f26f367807396ea8b11a6fac2546bf5d574a59b48c61b7749778cdeb52acdd54baf61f19802ef03a322501031c40930e9160df61a6946f6782dbe6b917c2138194a111e0501b775db1a66e5c1a5df5c42f58058b9868ec525f8f45403ba27f1f8a8ae9728b2ea140a00c822cf434e41b3105fdd6af4c2162376bda1d3bd5938ff9b486a11ae53c243cd4e97c0f632ea07099c1a23bea9b4571294ab518250a3570c1ca7fa01e11e1e245b15e8c266f9f03142d0d16cfac8dfa4888368082c6ec86e652c8f1afcd32dcc95b3e2cdbca6f19887b124a3c205fee32595bfc933dae224e2df5652c772ab6941a470386e14224b565639abd8a71e85da5d5e89fc0f7b0aa6f1a67
+TAG: 61354c3d7be6e00f6db3c79b69d91cf8bbb13c5f
+
+# DIGEST: 810e1f01bfcf6bc13ebae7861454ac133b2d6cd2
+KEY: 11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab69
+AD: 9719fe882eee2fee55ed8b
+CT: c76fd203ffada1af37acc360b1d26ab9364882831ee2f6ee68332165d863704db18ef1d5921b8134ba1a9a16d4da0d47670b2f5fde4d1194d8b8a62ba57f7e628cb144d605b7ad561ec0c66e3e7cb8d782723758e0dc2afc57c399d440433eb911b6dc3873adda54e62719c0e345f083e88797321232960c2c406776b371a64bfa82c96a49f07223c3cc8470aab3a7cdabf43c06349f0cac94a61e2503280d869b92ce7f88e281caf490e9edcbfffe7a7528669d5ded607e7b51681b06003ff061bacec4bff3a4c43ac3855142de282584e76eee9d2af0a543c7783fef1af169540e712b5d373823f1c31d1985f3edd2685edbae95b9b095d82ce7d77a79f406e5b44e7784c2d647feba197a9cc44271938ccb5a11e962d188d80d1aed890499f569d14772010ed7078518a196fbf2110bc5bd0397ddaeac981a00865ae4255f60b4660b67a828d855344e5dd0db5df6587cd8f8a60fc652c4626a9bac41bf28f6095ec6953e7d2873ca3ff14c068d25958580513d3a7f34ec7d3ff7
+TAG: d085062ebfd5b6829f69086235eea68eb2195e08
+
+# DIGEST: 881551d50a849b7e81f0cc0d722f631e32a4c97f
+KEY: c695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882e
+AD: ee2fee55ed8b11534c870d
+CT: c5a11b6948d9ac5fb184b7df3ff5260b03d6e6c1cf5830a1bc378de13e91f8bab09c96aefa60948ee51035bd24f3dcc0982a385372b2d30aed79b321717cf50973971483ccdf8121b5117c8930043dd229af9fe9b84fe817cbaeb1fc306fffc61e7e5965ea8367e42f91ebdb969b74300b1329e0b41bd94f6d5c53acfa55d088daeed3777c42d01ec2e53955c428a15e48856d6fa774788b1dd591d45397f89b6718885e02b4635f48078f823d2ce914e122bffc007d894f3a50aa399aef33b8255e4b1f84ea591f1898489516ad6a3f4a62275578fd9aba2203ae079f60743961426c5245ae672d01bf294ccb5ad36da0a0462db05a88aaf16670d03179a6ccf06b5e872d743e57c924d2a2bac38abe0ad23b44ef0a15839c095ab7467a5d10efb16bd183b5766bc51eb9c7ca8ca1e2bb94a1b54f8e80b37b7393bb207d7fd79c01b09943145dc5d603247ea08866f3b8e419e9f04e55f610e0c4491a281af0f15e11a863ee747aec65f65da5ee7b31fdfa8a120ee4d29988e65757
+TAG: 069fa6ca1e062a9163d4fcebea3e7220258682f8
+
+# DIGEST: d525f72dbdbf54db80ddeb9c2a84aca41451353e
+KEY: f1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed
+AD: 8b11534c870dc695b814bd
+CT: cc02b0c77ad10d25b9c16911516db68583194f48650131ccf55d29c35ec9d2de2b3d3ea2ee9937b6a87212779560b4ad9cd49b84304128329587e5d3abb71402d5eb0411f2704816409b2ca24f9fb3f2a4cb03e9e74ba1345a60bf6577159c8fe82b7747621311eaba3e43bfbc688edb7de11603cfd13ace7ddb6974e3dbd2b20e86e4e35e006ff87c06ea69a6e6b8cf2e02a7ba0210e4d10a474a06ad9d75559c0b9966811f94d5c209eb74e185de3bd1cf4d675de9abe7b2f11b907fbab8c128fd1fbeec0697ce9d2ad66e600068037a6a89ffa19b3c66d146655acf93028693a3bf0c86fb704927a9b10ced07f0b6cbac917f873a2e97cabc8b6e1b428d4ea4453a42d582e42e5586b7ced5c187085b1113ae5aa699b5951c3aff18bc1fa6d4c18e075c53ce657af855c4522a0c3d866bb7b0592ee3e04676b433b5f1097bc1cfd119c3b9f5af2fb69ce8200a8188dd4ef0d880258bb60ff2e9a276e7f1fb89372d835c32cb577fad96731b0891d9a23bfc4fa1bde25e187dc96c5007ee0a1a26c37857e867ec5c207581
+TAG: fdc1cb334fe2cc8adb94874c2566875c90d87ed9
+
+# DIGEST: b25882426b4730205533cfccc0da1de1f6f2c459
+KEY: 2c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d7
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c87
+AD: 0dc695b814bdf1a87bb105
+CT: 152a8f32525deb44c4fac83d46a32177d6f70edb8b7f5469ed5af0aada4b68d0c95c6e86293e40c25fbdf15570aeb42f3d1f055fd855b3115dabaaa765c5844e9578d8ee9f63c8cb21b181b556b8b687ef856e0cf059adf1d51064b7390eb95b32e2ea25308b4a04921d55240f64a5767fabbe3207dabd28b5f442597e75f3c6a1c6a26f0b44c316b0834f47f8445abf978509fdbf7cc65bcacd655c4eae698e6cc605a811c56a4ce31f38b2d0114bbf32eb591ad08e9f64434fd535bc9b73470879eba47eae13487edf13423b898e00efde2ff3f93576eb6f8e6d9131df10998ceae836310d4000a5905ede4db0c24b15c83d3476944f19eb7a4e6a493583f13486e5cc1604e01c9f6b47d728cb5dcd40d581db1ccc263ceb23375402395898dc26eb6947600a006294e28bcd1a70a2d89c1d1fc5ca5e6e28c16bc26a1fed1d8ec85b0daf7d4a2574c8d6bdcdc9fc4cfc37b79281e1470eae42846b223e303e004afa0d0f811c81f1da124c92c3d123284fd2199b645b6c7a86742d3ed2d5de900590d1b96aa2cc86a542ec
+TAG: 54cc7524500c7997bf02fd492b08c0262e2e95b0
+
+# DIGEST: 939442486c730c2cbd8df213d81310e50534f06c
+KEY: 16bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d80898
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814
+AD: bdf1a87bb1052c6755a7a1
+CT: 4d05fe0669ff88fb0fb4c053661c7fcbb79942de55c9c83648990903dc2af904086a05e683f71263d3f471a5c5f60cfaad78f79acd972c85f25ecf41f033b7fd8ca5fb13f011ef27bcb27bc10ed9f0ca233f533eae78e95f7dee6dafb592c66209bc946b745ff843544182b110540cc33615814a779b92ef8e69394d046d773086a29b3c7d70eb18d580915aff1490681e78efea704f81e2410617d2d92d2c62dfd78d8626b67b1800695bcb979bd6dac36bd4ad12073eeb0a4bce6026d02f92862392e3ef81653b6b28efca81754e99112e66f12593766e9153864fc7d6ffb46c0c95744d3a96ec069c27760ab353db33492f195d49147b6b166f09e7b0799ae329b30b60318ea4adb91fb338fc82bffaf47674b5d6e0847b317290b6ee46b43ffd5548c2c2c36a04971d6490019ec83f174ca095d5a983ddd5877927e5d6cfa62992327afe6e44e072a18a122de78569170e20d36b63f17049cdd01da3fcc50e4915e6b1aafbdeb0e5da30368552ce66a0bdd318deb534eaebb441111579c273338cfd9f55e0479da82b12
+TAG: a047d37ec97cab3d5f09a0dfd19632841cf1eac3
+
+# DIGEST: a7b522c0de411517839342925e8acf703ea12e8c
+KEY: a49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea37112
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1
+AD: 052c6755a7a116bfc9095d
+CT: e0015fea482acfd931875e6af31a81f2dc31103849db0354c7775ddbff6dd3baeab029bd6863b5a3e0bb4b3c5109bdc1d289df63a2b6a577e3c7af1000a16faa2a4acda887f7563ef227a214ec4343840058f94833f9ccda64ebf7e14358bdcf1224aa7e79153d4c128c13e23b5c41e76047e069070e522d62367a3dffe2418e1d2ea71f84f1c032568a8ba19040b1e06d0302fbe1b95298f7f16b75211f4c45d0015e049677874681b309f9115b33812e57ee411c43f8bdff6455368985b2c3b455c762761828e0a952cb2f51500317f95968eb275f52f66c80fcd1d454e2bd2b7c51bfb0e84cd5f8f1d2ee848d6cef1c2b382f73aea027a71dbfae5711a6a6b60d67747115bf138c7e88bbd5eeed3720ae5d9a3cd03a18ac7ad05ba0aa850814060964a6f324181c26257522e7e9db8848f4a26c13eac3f71132d82620d4d7bdd7a6b13edaff628a41a05de3a24ecede59960223e1a296bf1d22e268632f4e1cc4044a7548531efc9c8dd7488fcdafdc3ff6c0d7f664f537471695875f9da4f90a642d0134bb4659c79f97
+TAG: 03ebaf5b98044e677ba5ce1e5155cafb39a4ad6a
+
+# DIGEST: f61096694be30b85b6571dfc8b5bfc4d364bd225
+KEY: 4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7
+AD: a116bfc9095da49db3d71f
+CT: ce8e2a194f41ff1b79391f55bd476fa95060f706df76ef47dabf84b2c8c5c2390e2b6e95d299cfc316f0ba7df1ed7dda7ebcff09fb1928a341361132200bfdc5ff36bf6260980569edfacbed09160c009405b412373e8102709e0107cf4292efc32c6d7991df26bf862e36bac504341916b6b2378bb82500e0f1a323d6e668acef8cd24b609c66225d4745afd2ae547793206d0e76cddcb9dbb22854508d7e16a7419a63a1d6fe6c2eb353dc7802562b83adede2fcfb02ffb63080d4113a0f011659a1c243c3ae834e726f2d4ee202e82d174cd2df26c35e157ff3cefbdcedf98dc438ea8add64cb88cb0ded1c8873673947e5698cfce17c2c20f8570241a855b7ffd0800626e4fa17ef59708b7968676076b42e4816a276dd0a0cf7b7eb0624aa4fa8c2a05e11742bd1a29cb3a4cf3a319f8c66874d2fcc7018bb32fc8e51ef20e410197c3a0173e22bee6307b732be8d610c1ea994895c20f45181b40de55c04bc70e971821d5c852802fec021db47d2d7b8a3f91f8b21b2abb3b7e89e6e181cae3baa1bd5077b749316f78fc44c8c08f6b56fa105e8d5c3d5a52f
+TAG: 4e3a66874f74cdc4f9cf304deb02040eeac9e72f
+
+# DIGEST: acd9a5179a0ec782a63bc824188d838776bc1b81
+KEY: 3f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc909
+AD: 5da49db3d71f4b975c5d50
+CT: 8a610f075d994055451e514414628e2c30d72d5567cfb3d2592ffb1f4a85d553f85563a0352381df79ada451e8d6ffb6939edb73f57919abdbf37da41a3db4bab0406a73c6f61b84581c824d72652c36062130edd4673d0cb22c009fc67dbd9eef0365a67473e2672d522a3753b33ba2ece80974fd9550b667e8c942afd6a22924100b89abf9901053d5568197e9a11c85183f45385c2f3b887d78b04971e091a5d2b20dea01b60e61ef687c708fbeae417c99522e23dcc37ac2a23b785a6bbdfd41937f0e40e5835587c72118ea97f57c539451ba7bafb844b8cf3426ad973d8ddbae7a3eeedc6f5dc77ae6e05a752592e0d2ed0bdd92770952b0c11af898180767ccde0081dcf8ff748c02206ede73dc32bbef560e507962808fe7e6f3c130460d975757b6dfd2449fed5838bf4e3140bdc83688b156c22cb32f1b41aae2e53c66c06b81e85fa17b45763507f3fc9dafe4f0d8b2d71d4b4e645ac5047162988e3bb342142112294155dc646646c4bd9bbcae5238b0d8ab782fd7e4ffb383a4fc48523b8d28258d3b42e5e02ff3120d025e5b90978a7c839811873d
+TAG: 4b04e948b26a3acc920035433831086563526a6d
+
+# DIGEST: 152118d780c866c5eed3a08d2d9960cdc5acaabf
+KEY: 8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12d
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d7
+AD: 1f4b975c5d503f478b22dc
+CT: 6ee0912f8730e5e8fe419530addabe3c51e95d2261b032755287969f8834e473226e4e9113c586759fb812908a64c3ee020f4d15010b903b4c5e721cfb208eebb3e58707914f9048b9d89d53dd80d53dad740394a943db83bff6d27980ec681c7b9ffa80bc6464c71c0c807a7c8e445fd94edf77270e79080cd597ea69dc69617b9edf3d088785a47fe0b67188a2a058205a166e3bf8f61246509adc0d1d833f1a96f09970aced95a110946e68cb56ac439a2a850f97be36fbb4857c470f431ee6be051c9eb7148261e52889a789b14ac5d6009d925674ac8f22b46edd8786ba24ef920aa599efddf948a62496dcee2d453697e320610bbb3cfa7e657cab4548b92d0f40c7c927761fd6ab1cd50b9bd941768e7147515dfb3ed5a7e34440a75a6f9119e7bd0cc411ba3181adf38252230b73823daefa3295b71e2e967ecaf7916c1049f3235fc0249ffd7ce42563c910756eaded217d56e188738792f03938901caa6b23a5b1261033fad3e9743ded57121945f2f1086e567de844ff71f88920ff3925bc28055f4e9fb3b6eff0adb7d94c3e45c2842b4cdc6168a6c9
+TAG: db0a3a86abd5bfd20bd9cc96063d04791e407c80
+
+# DIGEST: ca91b15125e07b81debf75ff84e7eed4da5808a0
+KEY: 1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d
+AD: 503f478b22dc8253bee6fd
+CT: f39aee42285906c6ac413a75c9c35aa8990cfcc1404672886cf6b2c26013396c95213823f09d2f5ac5ee06b500caa7abc0bf72d1f00ab37a12daee95a9a867e570d6659dce22f8b4bf6e98964349cd96ad2c2adc7261c00732729d4e4fb1b70ca745ed300a8b75622296bd4fe6b2ffe5428b42bb1f5ad709a868a5fa4571a6dc6ad44c3cbf292c961bd18dc23d0aff520a344f3c964bdbd07add2af0bca8355a3f71e4a11779b8f0ee7c9ba514ba10a7663ff30c347f96902f86d77deebf0cc8b384382e509b2114c0fa9931c3c28d737a7f46945cf9609c7cd4143f0c62e5510aa5cbfea578a5e8f6fa2e4235b13ee4cf2c90666ba7225b042ed15b84124d53b14395574960586810e2cb6b03d65817fe6ccfcfdb98b35e94b0fa076783b60296f6bad6ba20e12dc508e1f6ea9e4fc9a50e233650d997ffb17792fd8803c7515955da482e62e18051311fcac5b6915d814ec2182593ef4b7a6f7d4cc3b8b65470a7f16180d54164ab0bbdced684dcc5f7a1f061e755d801364097d052234430062640edfd0a122e20877d551be7a92128c1ece727fdc237d37af2ce223e5d9ab881694f96395be0c06430ab
+TAG: 88f233b90e833d3fceeccb3b8371b62868e99647
+
+# DIGEST: 93d06638fe1e836ecdf5d30db3e4fd0660d9d701
+KEY: 01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f43724809744548
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22
+AD: dc8253bee6fd1b174c307f
+CT: 8693a4385e2082f13e0a89dec1e8df98242e30d84d9b0a1fe5905201846bbf34ba9e04afd3fc9ff4ada361cbae026a0862f7bdbfbca6c895ef0977852fc79821942bfeb89e8a51a46e99726ccd7d2477b683cbd9350fb9ea0378a543b70699df0bd9f1d29262dc6a9a116d8eb62f3fa7237f0e098e713ecea3af72d9daa702cd961de566f2ddf91de0e5a5d1bbfc0fb508b6b81c27190f4f1f05a8554ec96dd63cb2adbb10fb7e6662422130ebbe7fe36cd53bfd9cc7e21d1777c9347c79834f46406e409472fb747d20ad0ea516bdafa838adfa031e0d10415a55da4a46102cb72338922724554c5f5a632ef40827337695295c3bafebc537fa88d1f648d5c459bfa24e4956bab52084f8c0cfed8db6ed3d4dfe8f21268d5aea323d16f10ed304ba909d816ff848c1bf643f0b3926e23a39ee79acea462d7ceb91786536814213be4eb44e85d540af000069ff0c7b533d7f614093ec4b327555e1e3f311fd38138fb47c509341142578dc69b03161f9beed51708f7c7e14314f48a8f10a958179b189d27ecd1c9d80aca2d5c87d68f3b785a070e6922fc7b332bb9574c515d0e940c01a8ee8037916b472d5
+TAG: 67f5ab24e993e303144cfb49b62486bcff710dd0
+
+# DIGEST: a12c8aa71387379d0e43afa0321979e018d56547
+KEY: 9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6
+AD: fd1b174c307f01be95abaa
+CT: 0895c823437435ba580b89e28d667821b5bfad60bd76bca45bf922c31cc889f51abdf9b47aea2b4f2c5459f38e8e5e35d0ac624bef8dd3a96a06f3491ae629a05d15df535e1f2f1dbddd22fde0ff631fc298fd4f79a67879f4367f4e5a372df8b881b32d88057357ca1b5fbcbc7efdcef7e143d4e1ca35fda0bc19fc6da65f08fea0a381c4e93d5cc7c7198959cfead892f8a167631326da0905bd348faf7b7df25b621d7b7988a7b062ca6ff4c7ce931a901f2d509aa42e9bce1f20e68024b991520c43ee2d8689ed7e1a4f14f53b05566dcb9487787243f11beb5dda2c78b145b47fd4c13d6589d42c7e504c55d73f1bdbe5fb4a500a57001373fe772c2211dcac1eed0004634ab851f2e58b0234e1aa6d0d50c45695fa8cf24b1b35f2ede35406927e8101395910e865a3c44d81076bb246c15715bf21e3bc8a0f1ba0221755a17d5e4d72aab1a227818a7009fc4d4695a69a28a328c60903595236de7470a7af21bb0748ab7936f29cc5b0198d222c69800e0229e041fad4393bc16f28025403f209e0d266271f232ffdf89808715d51128514ec1936c7c924d58fd7521597fa44126d12b11d4a54fba9
+TAG: cce3639ceb31a80a5ae5ec4ea7160421c604a532
+
+# DIGEST: 8a524c3ce814e3059b4c7a6ac748783ce1385c68
+KEY: 2305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c30
+AD: 7f01be95abaa9bee585777
+CT: eab2468c2d5343dfcb43ff97e68caf92f032066f92d1f918ab524c3c89deefe814444bb6c24dec9dc20d59a401443905c653bf42ab7a67d041bffbc6940b5fe55afa5e15e748e779f6023b797b2b1cd929277bf6b8a415f93566fde4a773e4828aa0704caf46321d48332da01c7cb8b6b295ea13d9a9855a9c9499b5ba38370b6bfa982e3538302fa4ebfad9cd5324fed77c8e70437818ae275b68fc029d2caabaddce7dc50df388fa986a985e2df6d0450c9a00e16005734c7966fb7bbd7312957da2263fbd88a2016134aa45ece2ac93b47151acb0e38ec653ab23cd6003104c2ad254ec98f64a7a27a0d7c58f35e548ab6a291ee927190e7812c7a71a71d765943fe4fe9cc22a987917a4c35d28e25c8d2e0354f17a0ded0e61dc6609e8ddafc512306e71d0e8bf2cb3a04221b6d1721da96836e8f155ee0c3461a1d58403f8fe7ef13e5babcf9fd9d33c59a1aae25b082fce0f3c5299df0b83714ae9196dd809b750e9832702207fdcefc011f4107cf8424aa29552d3307d0e4c14db84751c086275400b5d3fe6eca4f5499de1290d34894c45187e2dc33086ff93feb97081d300931323297a8f1b93b41d973c165d9a8c85f4ab226939b775c4
+TAG: 8cc1565fd1cd6117c864bc0a9b7ec5369e66cf35
+
+# DIGEST: c31dae836928083019ab6902865d9f14c88fe27b
+KEY: 50d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a56179
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95ab
+AD: aa9bee5857772305daa4b5
+CT: b2a0474f96d94bf836f29da058d80da84d60b11126b3a9f8f6975def0fd2b2ea22f1c3ebfe8b9421155c364d38f24ef5e4e4440edd34113008e29179fd6637d6a0b2cb3b6d50a7cc3c4fecf56166b5a4a59eda1fee7ced7541e203fa9e07b2d43e136ffa3ef17eb0a59c9d333f38a4e7da8c5416f537c56cb30ea671674a7af92d966ba6d2d320c04791514815bcb6da500b469527b0eb66e825d81bebae70c376493846c41ae85c94318750a499f30f02e18eb4a722c47e80c08cc7b5f28bd7e9fc7ce71c38feb46aba20539716bd224d26e482b352fa1bc54a987d990b330f55c3eff7364247cc1d4b73dfab96fb8fe21a6f61a7de4bcd27806915bfe89e6708e2c00249bb847cde5056a468f94d6383a0ccab628ab96ef47b5a7b5e645f35af3159318bd913368bf276bd15a6c0981462ab7bbdc39246c98699c8b8369781277a58bc2a322f31077dc71a2feabfd900fb5ff851d07a2dd4b72a26c8e2a1a9787b83c13c4eebf0168828dab4636e7f419b72e7fdf482a9821d7785e18d110a5555aabea1762be06ed15a3ec1a42480bfe53cdf03eb1ec0fa75e5b2aaabe7a63beefcc4d059c4402952c97a8857b89542c84f525a996312ec2a0781
+TAG: 2cadb094771cf21fcea2209be5a6a6bdd550ec61
+
+# DIGEST: 4b2db052fc8a09f7a0c26afc66dbcd8ae5c9bf62
+KEY: 089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f311643
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857
+AD: 772305daa4b550d75f05d8
+CT: b5791488db7390a80622777e45f78e9154bb13e4da959bbfb824460bbda64f776864b921d07968201bbd570a5fce10d6c10777bd237130821c0df9a0248b604b9f814429a2c435b3154a2f05cb237a271a2f949c9e82f8d110524a48531cfdedf07fcc08c88d3a90c6852c0d91fb4c847dc6c69fdc4ce1c684763892b09159de9ae8b57720da5a949c7e46b5e34739820fac62d472dc50a3ccde3c64fd47d398c07372b0a37ddb026dbd8c27d698716f12aeecb4b1dd3ef3411ee6b71d519caf74cccd225c2d445c469503611efb27e3bf9f27d74fa796a07c8acbb8f6d8d567c51891a0daefa7b7e948d3292ff927825a08769492ed47e2f0f54dc2cde68486019e7ee93cdcc39305dfb388156ca44d1e22a16083168ff74a647424afb0c8ae7e589a68bf372b49ea9aaf0e58690cfbf8d014c3682588a1eac2ca6663138b35c7a76b7c099a2e4ea0ee4965ea3ee375ec279ccdff3d38a342b0130f2c962fe3b0b54185fa7dfcc59a783913557afd00f5f9ed55c3958eb5d1899ae70f3057e05662881f369d9816b2e86c8cc6c40dd6537335728443e2cbbce66ab22e86335c7800b170cef707364a93472c035542489ea8681d3647d2d6dba0df4e
+TAG: abb18212526497bad9f0f8f25ec9c1976f82bfc1
+
+# DIGEST: 881926d37fae9095362fff56efadd9fa3c455ebd
+KEY: 711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4
+AD: b550d75f05d8089850fea3
+CT: 33e5dbddc7a3d14f78529c8b97fcff71b6d4e93354361f17bf9243c5cb1fe26577d8b2dfb5205f72def5923198e294294a612bc2064380fd2e7367a84afc10b7db41a12d38754205937444a08dc11bbde5565a8e103eb305f85540405966d6f3760096c0b54bce8414dc539c91da221943ce0327516a5e8f4aedc7997a64a7bad0f315dfe9b8472f934c67efd104eacb2c3ed3c1efd8949d66033e297cc655732b781399f215463a8c053ba05b65680166d7d5791b39e4e88c82a982bfd85061bdcfd4b52864a0e9efba5451b5aaa9a1bb3d59f2cf9214c994afdd87c2ae389d095e380bc33d66f802f635595da58e2ce0e1fed44032c940e6c1ead3c1b33d820cd8a754b8592a2f16ccf7751a82c36da56b5e6b5ba588d33068ce3e7f4e9de1fc87612b55c44b61fbcf6507e660e3ae5f56fc3cd751f505a854636cb87067ced759c1136325b58cad2a2558565cc7aa006c9dd88155003d5dc1922177bb61142da62844956fd9d4b60fbac403d5a92b122e8f63ff4ce6fae70fd824322d8607fa59c6b0b2134d8165214d41deba7d28f99e7fb19e75c4358cade4b5d478aaefd957cb8698598857f65c382148add2d90c6cbe34c1f330f611b7e8b265f936b75a9e3c18e6fbf320eb09bbfe
+TAG: b26cc01704e704e1f22c60cd5bc5ef1b4256f89a
+
+# DIGEST: 92d143942e6ef5b44ad7a4b8e71c22f1ecaafffb
+KEY: 2610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05
+AD: d8089850fea3711265bf78
+CT: 93314bd06e0f9511f8577aed88d71c6990fdfe4ea3564450cdec06392e1759dd356827fdf82ebe96ecad77f2da1ef961e601d93237ff515e46b00dbe0b0329e17bcd2a386ad9942f678f5f2942b73a39e5a7de74fb6f22911c697babac2b3a29ae9534dcf2a262227066574bf830850d0993baced9a839c80159d7d91724665e06e22268106e9eb4c99ffc7b2529be6ce06308e064e69cb712a473b25e6f84f6ed1fc72075245ed6db6fc64eb5da492fb8fa4b15dd4424dd2858e1d201044dd147b08adb4a76b63c3fe2f4c0ee49dbf0ebb1b7651be3f28edb38418b162fa0f8dddab8557e55e32b63e2e8fd401d3dcf0454ddf995a77980dd131fc48f1299a246680983d4667eb1429e55779da5c8c0e34fcd79024894577d24886a1efecc6ffc1daa6ca1c9ad7c7bb4b707f8cfd767085496145b2f65b6e755359150da8f2d5c751dede44dd061fe40ad76a5dcb509b593779cb6c8536490079394536a25442aa1a12a0d9b75d5cecafb9ebca23eed3489ab975b9442ce706511037271bd022d4bb69d75ad93683764d40b0135c85740348ad6142e5ec18888304375cb25be53d0b86bf2782c8e626b7b20b2cb2907334e95037f298271e6cb3456fc322c384d94789413ce734326aa07cf
+TAG: 608624f01bf72a6f7817b28198605cf6b6378e6d
+
+# DIGEST: 7fcec4927096421498e91df912cfe43b2e971d4a
+KEY: 24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1d
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fe
+AD: a3711265bf782610460bfd
+CT: ef33a63fb8fc5b6a4424fa6644ee0c833a6db43d65f67729378d77ab88f73416f6a63c2419bb6ffdd2378fd5280aa0bc6fd34bfaf7687f9697d0038a0e509c5826daea0c2a3dc41352f437cfdbba7012a470f42878fb127794b49476cc5f9d5f1ee34299e155d394947b2e277eb9c22b1eda29a2c538a174b7dcbe55a8af0614bd54e5ecb54d59f6393b30300354f9d1655c49d2ace998a02211e242088115421ae2c89e2fc91f5c3e63a78c24cf3f228e421d8148131efbb83df5350bcb54aa4f543c8789a12c08f2bf1dcbcfc1d4bdf2ae48a657b9ad7deaf4f82adedc92ab630a649da8416d9a1f4e4788fca2f8abd79b8e3119cf5a8157589f8cb59c9b1e0b53af9ffb6ddc69de771ece7a22d2536d3df661fa94a278276a0829cbc08c8ac613b0aae3f1396d4bcae75ba0481015f389313084e0fa7e3c51421f85bfc2335e98810813cc474a3c7954e3f9bf740ad4cb0bd7cb77363fabd3f7f2464058a3bd72c864c9e58b23108d9ef91f633ba7d5dbfd397a9a9034cff23f88b5c014b83641166948bc1769d3ce1fdc196c385867f398c06ed5d1887411fee29079b1e7b4256002ea34003ef00fae7cf24353d72385f5070d0f7306cb4efe1934571f46fa4ed0c1d00d946fc6e19a4f
+TAG: faf8a22622036eb3548c75b2c4616d216e9ed282
+
+# DIGEST: c1c6273ce723df9f2033c7150d466c011bb457da
+KEY: a12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf
+AD: 782610460bfd24ba022e6d
+CT: 8308b83db00f58f91f79a25ff76d277e13cac5a76e00c65a8a4b6ba7c2a189ea487f023c456f5d7e456a7a5ba18fe7af240b71a82898b640269c1402866f4fd25cc41ffd9f883b1c81fc4255c3425fddda7367a9a1ac231e8a5f694b41a7d22cf9312d2372dbc6d4e50d26a902fb2764ae1da84acf5f488fd29364b52ab6c5d4945268d5746a2f06406a9fc8eaff98dd509fb421a76b1231b5703f366127352d516f5416634b7905728c45dc3ee68bec892fb58d6cf713f33f7b09e44c7ae4b8954c6c7ac7cb156e57612d5f153b22fe0b6a8e1733e122d48698adee8705d8d3258f266facfda74c6dabedc2a4c31ddc59c08d367d929479c526a6effcaee8576b3d4d9fbc0b008a8c4192d6363b6f0a9b79e21f91d2e65d9817fe193ae62e1c81cb84de7b09203f07e0af073a9324ee4ea580b125a8e380a04ea48051d7cfaaf67145cb93d7a3a2985f723909552b9870f5144b5961f0ce965058ea3e27d9a79a5dcf75027ad15b17a3fa6e18259d134eaacd1d601bb75ab05e50b27c97c81b037e05ef5a1c83a74d08d853d4aecb7c8fb29ce49f1ede3cf5d9e1fc95402601f560b28f55fae01644a68b664f1c1cbcd1851707cdb3b191fab5e0899b75c4d5d3f1511b7d7ed09adc946900dfec7c40918a7fa5043fff860e582301
+TAG: fa6eee459cc5f7e681c7746c9fdbd86a475f3abc
+
+# DIGEST: 11424a64d5ce78fd71b30a8070aea071d873afea
+KEY: 4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460b
+AD: fd24ba022e6da12dd4c27f
+CT: 9dc9d73836a8b568e40e805a7508f7259ece28a4f4b83f1994ca9078d14b785091226ade8921562912fc16ddaceb1958eb92e6688f5eeae81285508168680e648a42908309be71c92dbd21d23d6e80ad62d6cf3fea415e7f46892e01e4b3eda4bc3e17acb7e65fa1d003ea9b6791f9923411680ae6e1d012c3b383e46ab698f0d572523d8ab87ed28ffc00b5c7a2d1ff6055509c3c2d67c0576289b65e73fb47dfa48b56f9b5b42f934e32123f09072f0e409d2a98e7f78901a02b7e1713c72e125e69dbc15c99b27510a89645871cc07257827e3058168990e4866e16afbf5de7547f3f6f3de7c497616e8212a11440ddf641c8de62e0a96b4220edd22b475a175a73cb7e8d9f66633e23c53e7e78c33fe54dcc9fb20fa6400400fe893cd770f668b6e763db9dd8881f0206a8f2769f1d53224a60c15b65210a12de00d159820e8dac8df1ac34388137508743c18390bd625c848916639f035df39daeb48ff13890ec8dc3f8b0dc64c57ca6e0f6b397e5c7d8aec2b5853ecf3dfeb5468589a92d7c1050fc07d3787e3c367249716c514fa63ebb6788d6875d2167c396109ae7ec6ff4684ee7f7b6f5c2e9688bc23676d3d0e6d11da1aa2c977d7741242381de004c320259a6e7a6cc7ad22cc44bcb27bdc41f70e4bfc77ff9f73b2f
+TAG: a6ca7e5060ecf484c8cfa6d75edf76d37375443b
+
+# DIGEST: 6b7295febce7fba8d79d1e7ab8fdfc452191e2ba
+KEY: 454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e
+AD: 6da12dd4c27f4372480974
+CT: 02972895ffc3e4cf8325f5ca5b26ee8a4301df3c45fc2f43412b827ff9e8314c70dff0ffd3c1dbdffac98a4407e9179557f8df243b0d07f1b672aba943ee38eb677f20985dd542164dadecee488f0657ca790f54d26741a1fe6f246d04c46781f0ebc0122e1c33a35c73065757e98177694d736db9388b4cf48850ecc62cfca7dc94184ef8efb0b1ad9987d76d571f2a1a36981aa1baa978f7b91a65c6c25d006d8a3df86e2727903404922f480dab3a5d5996b07422f3b1a2da3192f41fc34cbebec64144d4db00757f62fd0eccd592bdcb7d9cba618797b1063a6398f4e4cd8886ecb2edd1d75fc011f37cf9a0c4ebe401efdb64cd2d7807766fd40e3b3d0aecfa0d49d6747a409ac2036f3ad6f0dad8e6dcccdf7dec4048ecbb0fb7882dfe603e66a5d7973b29b956d1332f040ed405d97193053e52732aa677994a02cf10e3d4081e6bd1ebb1f3d3b95125aac94fa6637797f6db5674c1d588a30ab4739f8738a299ef60fc5eff5c7e7244eacee4dbe9a66ba60c85567c64c86a7bb11e211d2f30bb45f037f7bfc95f0bf9a87a65de21a04f1955f887c04029bfb0ce689f6a46e84c5f8076dd9806c3035810f674b417379ecd5b4372698f7b2dfb61a30dca69555e49d6f6ec3f44e7dfd6ca533b6dc2341aa63b9a1e1d8f8f11
+TAG: 83ced733218bf5c9dcf17b3adb519cfc8771b1b9
+
+# DIGEST: 1dadffba439570155af2509a548764a93042d23a
+KEY: e9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e97
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c2
+AD: 7f4372480974454879c41d
+CT: 0f3f2b8e85620a4829deb7ce60af43acc0da265bbe6c61939a327ce4a93212cc525edb28a369d54f8e116d81f136d555be33ebfb87eded221fec99f4a38b4fa3ccf58e15e46cd8ab535cc6f62af5d3f38cda649dcc3051a038406430e2b2c088e4b6c5812237d1ac113b0a47364db16632390253b3aa6f3d90f155ba771251ea35a52df0a0969d4f182699aeed419f631c0a22a48959bffa701569743177867e0b9cca18e243d77452f311ccce9c63211d6121a8f97aacebed9784accffb8e6e173141b3dc512a3414bc3a652cd8f0e2faf8fac59e3eca6e613d8466c27c21ffd772c6b18b4c19edcec6f4fdf2005050ccb466737a9ac629229b42effb9019d370af0f7944f7d2f5ba8505db265b373e051376bbcca7f9ee6ccad1f5651b24a516b213d6e90e6b01fde4d673972084d90f44c6002f65dc5acb49ec625ebd1ddf8b9884bfbc6e012ed0214c14af86717d61514927440fad1c1bcdab86b57bb93dd922f51f557e32b6501d99a0a4fc810f0cbb74a4fbdcabd9bdae42214f3a690d5e343498a022acc34cf12c0bee4ac19c193b7537b0400a26940a5bfbc5e1fc3a4b7591adfa9bbd5072cfc6b77e132da8aaf41d9a71b2e5da61c0b26a6eafe2e9245d98540d24286f7478c73b28c351fbefedb46c7a2dba1a07d005bc
+TAG: 3abfebfdc7b862b965ef5919df45ac6578d775ad
+
+# DIGEST: e654b4c78e1c0061eea2996fc126c9bfd41eb6d9
+KEY: 3b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c9b
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f43724809
+AD: 74454879c41de9ac9f9823
+CT: 04183b22cc3b9d14e40a7ea1b69be68bb2347bfef9ff9a1ddef915f42255b89d5f0cfee79eb0594d56a20fc9a1cdd263deb0242f169eabcdeeffbb64a00d8df58c058794d36cae1ed22a078baa51d10bcc28ae25990a29f400cdc725b479ba7c67f2b7da61fc25d3f063e72130eebe852fe696152c221dfec1056d5c67bcb7e38d9eb45693aede0b0047ef7b064ff1fcd0f4573fc70194a22582054f76ceb2792e2606d07099af20f76535aea63446200c49bdd188e26f784192d131f2494238b610f6f600d89f69b54c1e72c1167b9f41065888b9410c6ca631e9f0b82a72dbc02cb94b0e8aac9cb673a2ea93d53b0f382959c0df460eb00d947ce1cd6c41991f52420046314204318e364d5f8bd6d3d265cde880aff7cc16342a24f2204ec33fa00f3b7ea3ff74c6bde45a3224764bca6f8998529dc59b9a50c1db15263bdb8285f4a4360c1decdc7f2613036bd059705aa5bd651167cec76a3aed48ed5eadec9d558f87865bd1e95da7894792d84a7be856c7892ce585daa6cdc498ecc9ba39f6504144bfeeb4e098087858d008ba23a295a11a3eb13b38c9d86758fb62f133c69973a61a904844352365f007e229fb3c1450e74d5961457b5719268b4a23663de7680115e84b0dc6b118537fc0d9904eda1d9034db6794c51d798c579b344702f446158e33bc30825d98
+TAG: 8a3ed847cb93cd89e4412a8ca0e83fdd53406897
+
+# DIGEST: 654b8591c7f0506261713e9ce7a6fd24a6b9357e
+KEY: 61792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c9b66262c0f03
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c4
+AD: 1de9ac9f98233b5a7379a5
+CT: 81f1e6124dcc3ad1c6aff527c8d9be440b276cb9a78af0eb13c2656ad2c53aaa06b0bffb486100fcbe2ddd944826d6a4d0c749e4a4e646aa404b1a5c4bdf2c37c4ea58d5ceb59aa212e93adc34374a10fa1e5c0e6d1c927e4abe18f00f7caeaac7fd49fae791e04c725d2804aa73fc3bbeb636dcba401ec7f07781ea5103e4802fe94208ef07b78e7a04ea1340f135736a69da887f2886743787cbe6e4c036d04843bf617def845b2d287acc741a707eadc2bbd811ca7987a09bf3b883655de05b07783454e53d55ce7a604e4c5934f846dab6e8b9677e5de5376d38d8c4d0cb3b4dffb9cd423ee61beb74b622d2672dfa22bcca5b0e72806ae48d83a4d683a644f5049199f004256e903bf6a4a24997ecbea4d9feb8048400cd583f3ec860165acda29ec81e3cb8c735328ba0c2ee9a972d9367d5c09c029a003c0cfd0617b1659f5ec9aecd37a3307bff5a19d08d7df6061e5f5d442e76fd3aab4a249802a6e445b53276166bbc358648c0c46f56e85c717b7fd73d5ca7dd6e58ddc9dbe22698c54b9bb02a245629c761a0735db0813ea97d6d13a9e72531f69b0ed623a156dc99786cbc6099a8e11b2fbed401a8a2fcccd6235584176bbaaee17261a66457c714b12890dffd152482a72abfd70fff4fce8903712567a1022b3d4488a3f2beafd9cf574bb5cf6348163210
+TAG: be611c95e090cbde73fe628076bd1e5eed337f18
+
+# DIGEST: 1eaad32c8d0cefaa5e2c503bb2185a73e6387fac
+KEY: 16430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c9b66262c0f0368fe9d0cb7
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98
+AD: 233b5a7379a561792c0f31
+CT: 1bb52d1264ea749417b516884fa9a25fbccd4a07103bc00213614c9a61700c8fe401c438c3be664bec96b81b6b68b808e76d1af01bbef8cf65488abec789e973364be139800ebcc4c3e117271162c249ccbbbb8f6a1fefa4b7e578b8b344519364082f4afecdb3a1fcc267fb1e0b77d42b574cabf7bb3a339bf4b6f90c652b844fe78e3f3e927252cf33b68720caff6146d046211547682ba9c13a8a88438b920598c3a687cd6b67a96c589b4b827e09d644cd188e78d40a793aa0121a6c8e16ff9f86821388a995b17ec16c5d2ea2e28bf549ebc7218096f420946e296fa620d9a9241aca33674013550a054e6b7c543c5828ef38ae8457b5e9a4a2a52f1fee6004f62bb5018aa6f7853e4e5112c34b93fe12e347125c1c3a2b5e007d5a9e026ab13c196636feebcd0470a9864d50c71b4e29e6d71b678c7223f5ea34d52b17b2bfba5f31d228a203dcc1be74d2baaa6c718df27a8d1938a6a0552a305870cd6607118fd525877189d9deed6f1bd14079a19fca57d98cc2db5b792dd6431564e625f00622e384935085a0e012424d11ad122b9fee40ab5c5ada1f12f9500192d07e16ebf31e4d7ccfc983cad113c547fba55716f7c92f9f633beacf853ef53dfc3c8f8eefa2ea767cf9b338666781080e1692413909c95e492d801673bbc5cf9ef941c68981835e91b61389
+TAG: fe1b9dc1f8202b7fe5f12f6db61746a2264d5c52
+
+# DIGEST: 862c0517b3658e9b9cd27db608d49e24e9b4667d
+KEY: a058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c9b66262c0f0368fe9d0cb746bbd55813
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379
+AD: a561792c0f3116430e8b6e
+CT: 1a969ac3a7a86368c76919cc844ae3f26eb0698717b84b8ada3fbc1615b8cfe2c3e845f9b37f145ad495531c9340bedf965ce24194abf9986c2d6a5e0b7a62f984a276e47b1f51ea1ec45497972cbe00e8699c623c2f4009cdb3b32f8b9ba235512785c0f8dc46590ddbb05bd630febe7d0e6cc2f96f143c66aaae1d5d0c3bcfcc148f43e999ffce6d49dd4bcfa2b095c883659d4cf7f0940dcb1ec38807283621516d0f1b375e0266eaf3853e0bc74aa6767da3961b65792ea4e58644488fa9995ca60f89a1c533547fd764b9cc5ffca134725754be270768848e4ba0ae54d5363a5f66fa71a52107625c9eb3fface5ab5710f87b4b516415b4de3e3b59c56d2f33c6a9aa295b909da9b0d19956b790a4f082607fc59d2225651a6767471bc513b81a3c0218d134d38ec301d3fd8065cd3cd9c2fded778eff193ea0b7bcbd2ad856a931404501da9eb7226014c28371862a9eecdcc58ed8ef86da91f8e58f49c7f99377387b9676f5ae9f05eb0212e6b7bd706653f3f70abbb8ae26fc4f994821b986e866bfe64881418374886ef549cd17c883b3f1386ce4494ed85467d48f827fc28daa252829bec2a36e6c241456ebb45fb264ea29e1a3e379f1b3dc746c0d012ebc9e38a54429fdb6008fcf2ab518260ddec20a4b8db972e8e0e0e2781429513062d7b9756e277529750f90988e85f86a65c047f1867e8d942c
+TAG: 6e4a1975a52c59682e79407f73a9d493fa97b0b0
+
diff --git a/src/crypto/cipher/test/aes_128_cbc_sha1_tls_tests.txt b/src/crypto/cipher/test/aes_128_cbc_sha1_tls_tests.txt
new file mode 100644
index 0000000..2b34b7b
--- /dev/null
+++ b/src/crypto/cipher/test/aes_128_cbc_sha1_tls_tests.txt
@@ -0,0 +1,840 @@
+# Generated by
+# go run make_legacy_aead_tests.go -cipher aes128 -mac sha1
+#
+# Note: aead_test's input format splits the ciphertext and tag positions of the sealed
+# input. But these legacy AEADs are MAC-then-encrypt and may include padding, so this
+# split isn't meaningful. The unencrypted MAC is included in the 'DIGEST' tag above
+# each test case.
+
+# Test with non-minimal padding.
+# DIGEST: 7f3a0e20bde700d3c5596909282e5c3e764c99e7
+KEY: 86d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8
+NONCE: d7efd88503f78b8ed1c8e9ba2fd6773e
+IN: 936a91d0b5
+AD: d2c0267218cb7090c61713
+CT: c6281c1cd562c1935946013b946a2342f00e08a2a3e0f0bf6c98426d
+TAG: ce5d0ff98773f9560831e8ef348f50b35a2fbbf2
+NO_SEAL: 01
+
+# Test with bad padding values.
+# DIGEST: 7f3a0e20bde700d3c5596909282e5c3e764c99e7
+KEY: 86d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8
+NONCE: d7efd88503f78b8ed1c8e9ba2fd6773e
+IN: 936a91d0b5
+AD: d2c0267218cb7090c61713
+CT: c6281c1cd562c1935946013b
+TAG: 946a234257dce6ada126887baada8ee4e2b9f5ee
+NO_SEAL: 01
+FAILS: 01
+
+# Test with no padding.
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312
+TAG: ead153f0c9488b88357e81187178465d2416ca97
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: f0f82752a691ef5866413f2b2e5c1d0ebb41ccc8
+KEY: 7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4
+NONCE: 183aa23fd8d7efd88503f78b8ed1c8e9
+IN:
+AD: 936a91d0b5d2c0267218cb
+CT: 3573ea7b63ce69f8201934d1
+TAG: 32287532f62cf9e3f76e29a7d32db4e5d02a8ddb
+
+# DIGEST: 7f3a0e20bde700d3c5596909282e5c3e764c99e7
+KEY: 86d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8
+NONCE: d7efd88503f78b8ed1c8e9ba2fd6773e
+IN: 936a91d0b5
+AD: d2c0267218cb7090c61713
+CT: c6281c1cd562c1935946013b
+TAG: 946a234250ed67575910144f24abf6bb500ae865
+
+# DIGEST: 5b32faa93c18842b5cb7b075270438756d5f7dd2
+KEY: 97b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503
+NONCE: f78b8ed1c8e9ba2fd6773e0d0c302a5f
+IN: 936a91d0b5d2c0267218
+AD: cb7090c6171386d641b877
+CT: e22001f66a70505db0e606fd
+TAG: ab054baa17e7012c3090a39ba2562febc61c54e9
+
+# DIGEST: 995a0f9b029aba3e0a3205364628bb76baccbf45
+KEY: 56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8
+NONCE: e9ba2fd6773e0d0c302a5f47e037446f
+IN: 936a91d0b5d2c0267218cb7090c617
+AD: 1386d641b87797b684e0fb
+CT: ecaa1fb673a01178c9cbb07f97da65089b3d6183eaa3bb100bcf1271
+TAG: c050c7c8e7ed21c7b3d340c6b95dce75eeacf9cf
+
+# DIGEST: 023d08d5e5af3e0b016103c7c3cfd1d02577888e
+KEY: d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd677
+NONCE: 3e0d0c302a5f47e037446f5891d77df6
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b8
+AD: 7797b684e0fb56f97c3961
+CT: 92528284fcbe4afcfdee31cfa766b130a569f80e2da876ef0ff47db0
+TAG: ee913ea056cdfa866567ffaf89f68fc1596e5160
+
+# DIGEST: ad4b11a43bb47aec3e91209f98f99839dfa1d6f6
+KEY: a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a
+NONCE: 5f47e037446f5891d77df660ed82933f
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0
+AD: fb56f97c3961d8afa22993
+CT: bfe23f8be496b3bc8f7ce56d98bd68d1fa5d34db969fed05095d0024
+TAG: 0221a5d84e7b9f7500c5c250d1df78d4026652c9
+
+# DIGEST: 580641286aa43bcef85be190e1967f627713bc64
+KEY: 89c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e03744
+NONCE: 6f5891d77df660ed82933f62be8dc55b
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c39
+AD: 61d8afa22993a340b9b3c5
+CT: a405ea4fd52a1d4c062e1f39f8074fef3990ecb68913525d2d780461df8c91d9b3da0aa66462756bd7108feb
+TAG: e9c52c19a46b7ae12022c55465cce0e6ae5032bb
+
+# DIGEST: abb06965675631a07f380e80a05cff36c2d42ecb
+KEY: f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77d
+NONCE: f660ed82933f62be8dc55b436965aabe
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa229
+AD: 93a340b9b3c589c7481df3
+CT: 1d85149d836f2eb30de4e81629b6db810080dfba5ff8fe1ebce0e21d9841d8526bd843ea675cddc01dbea77e
+TAG: 1ec4419ec20d3f08f9bd5046d31f2bc608e19e41
+
+# DIGEST: c6a1ebefd827cde32df1d38379ee4bb6a7f81267
+KEY: d8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed8293
+NONCE: 3f62be8dc55b436965aabe477e0cdd46
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3
+AD: c589c7481df3f4183aa23f
+CT: 7ac2b8a728aec2d83c9efe446bd4bc61d4e195d0bc84a2bfb8fade2cdc0d8eb890dedae85da0f608cc1bcb82
+TAG: 461c0f62ed6555a18f173399da6fab6943f13d55
+
+# DIGEST: 77fcb5875838a28d24c4b6bd0916ebd827968073
+KEY: 03f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc5
+NONCE: 5b436965aabe477e0cdd46be99371eb8
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481d
+AD: f3f4183aa23fd8d7efd885
+CT: fba1a6e2f66b4f9e45d281a15de9acc0ab1d9bdf910eb1d7f666dc0f9920f57602beb84189085fe9032db35a353fa554389af4aff3dea1e20c4b6209
+TAG: c615c926659cd38d7d86073c080002572f222ef8
+
+# DIGEST: ff3c91da880d2942bbc51adafaebcf4c6fd50603
+KEY: c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aa
+NONCE: be477e0cdd46be99371eb8da7dac997d
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa2
+AD: 3fd8d7efd88503f78b8ed1
+CT: 727c00d1375f9360f59bce3279a2058d47b580669a3725c4f655f9ad081f6e7517ac0feaa7f6b283381d4e42ca33d77a1cacca3526bab09a860948a9
+TAG: 28b686839c5990e0e2392ee4c1368a92c07b66b5
+
+# DIGEST: 8c439bfcfb896bd106f94676b5626f2bc624c313
+KEY: 773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd
+NONCE: 46be99371eb8da7dac997deafd64b1fc
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd8
+AD: 8503f78b8ed1c8e9ba2fd6
+CT: 7af81e2a26192870b683f696c80b2cb7a212b68a5a85f9af5775f9582a9a99f50945b4e81c21185a315cc328e5345cf309c70c230fb769823807599a
+TAG: c74b90be48c48661e615ef7884fa97dcdf27aeb9
+
+# DIGEST: 35d9dfb89c1883210f03050da3166b6d13f5b8db
+KEY: 2a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8e
+AD: d1c8e9ba2fd6773e0d0c30
+CT: 98c01c277a1bd3e1edefb31f39c80968a9e94c40b702e7f0b69a39a9b9ea78aedcbba89b266f5a11e8cbcb64e5ff2d0adbbc10416110d9f7f9f1c5fdf3b49e183d08ce4fa72d2d78f4bf69bd
+TAG: 2bada16d212ff285cf763468fe2104a38e095f7e
+
+# DIGEST: a07054c760cc66fc704edf950201005031f3faac
+KEY: 446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac99
+NONCE: 7deafd64b1fc65de39f4f03541a11be1
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2f
+AD: d6773e0d0c302a5f47e037
+CT: 2e7e6cd84e03e35d8977c9e1d4ce6784c4db3a87fa1b82e6f781e284e0d3914eb56acdde0374eed6283cc10e1f329821fefbf888dfc8fb42fa574cb64df6d88d2d80503493bfa3c2cd3817bb
+TAG: 145fc5794bb7519429bfa85ae1382e165e104a4b
+
+# DIGEST: 63efe7af502231420ed5aecce9a28446b257828d
+KEY: 7df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1
+NONCE: fc65de39f4f03541a11be112a72933c7
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c
+AD: 302a5f47e037446f5891d7
+CT: b2e315ef97a1b89b4625715c61946446fe1bf27aa60e65d0ad9849f71ec53ccbee951d3628efe2795949f88795b354df0ec68b21cd699cdd0f92f31f3d6013a4c1116165b4f54e9eb0387d91
+TAG: 21ea239be370b7c0547ded846c811f422a71e61d
+
+# DIGEST: e8e41988fad6c8b44c56544964cfe0a347b35b1e
+KEY: 933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4
+NONCE: f03541a11be112a72933c7b54ed4fad0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e0
+AD: 37446f5891d77df660ed82
+CT: 8795d6c225aa78fccaaff86101641081f4a440969633ca8d7830ffb14f629fa34dc4c15e8ff20a8940c7a484ee94503372e658615eb3fc07c2d2c399ae9ad7a77d684512d0ca273f77fcfe53
+TAG: 4574a93d31c1c0bb43d3d482057e0d8b51a679a6
+
+# DIGEST: 172f4992e692a88f49628e5d3937959be01aed2e
+KEY: c55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11b
+NONCE: e112a72933c7b54ed4fad0be905d4120
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891
+AD: d77df660ed82933f62be8d
+CT: f2f3a3d985eb38c406bb0db0d141188c680656db8a4484abad2c8973267e14458e2be7cb52f06ee2a0f68eaced13db714296319b2b3557454f5e9cb47e8943ea3e66f7bd25c5757375be7bdd65fef53b2c441fd3259628cab417df36
+TAG: 374ededb564b3918239bd5e284ce22d0372f4ae0
+
+# DIGEST: a35fc7d25f90dd9cbd35910d5532aca8aba88b29
+KEY: aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933
+NONCE: c7b54ed4fad0be905d41203f5dce998f
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed
+AD: 82933f62be8dc55b436965
+CT: cea9c7528706d506d75cf085c8475c081ee8c6145ca11610b73eb3e103a706faa66062f8edc10abaa7c3edb3fcaf43c202c4812e768fececaa04564414f45816fa5c0df5b7518ea3859be75c4567565358293e923232de5af0908060
+TAG: 4ec6b6fc6692337793c264f2b4f5f88570cd6e22
+
+# DIGEST: 4abaa8453e8cfdefd918571a961d8351754ad5b4
+KEY: dd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fa
+NONCE: d0be905d41203f5dce998f8fb2eaad40
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be
+AD: 8dc55b436965aabe477e0c
+CT: 03065bb245ba12ab90903bc081198fdfe45d7d3c6fa3b1f76bde831917376ec2a5b2ac2cf629de6bd3f23025b678ea9cc3bd7801f5510b58432a8bc17999304fec4de7ab9ac22d75897cac67ed57e30d4745588b36695dd005c59287
+TAG: 7bfb0998bc70cd20d6c1dd51a73b031eb1aa567f
+
+# DIGEST: b51001b6ff9d27bccf3103a4961280e0a1406257
+KEY: 1eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41
+NONCE: 203f5dce998f8fb2eaad409ae0211641
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b4369
+AD: 65aabe477e0cdd46be9937
+CT: 8d7999ec7a80e528bd6a8d2a9724930c93ee5cbb0c888d9b7c79d2449e638c03f3143f1927a1b261d66ff55bdeb7ff6616da99a2155f465d7c91f54963e7cbda7b61529381204ba43c9681260799ce66fec9b0e9882fc0ab474fd9134adb66e9012cda52183ec3e658c42f81
+TAG: 9dd9862193c5b312ba42f288553e8f1af858d6a2
+
+# DIGEST: ad2b43eee27e6267d8c5c1c3d558a07dcd6b1f5f
+KEY: 997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce99
+NONCE: 8f8fb2eaad409ae02116417dae0cef45
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e
+AD: 0cdd46be99371eb8da7dac
+CT: ad918e7428ca106cf043d6626772cd45ce998f32fea28c3253fd58f0fcc191bb4cd250b5dc6a7b352bb2aaa66601e280576fa60ad8c3aa58742462955fd7f33ddbbb5036128617c1fc3bfdf83100dfdd069042ad1887c2821afbcf822756226c69779d88edae83839ae4bcbc
+TAG: f7da661a2c2ee207e4eb4716dab8e0e11e4ae1f9
+
+# DIGEST: 7b17b7cb19107af8fc4671420e461060e2ef3e61
+KEY: b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad
+NONCE: 409ae02116417dae0cef457b9e5e16dc
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+AD: 371eb8da7dac997deafd64
+CT: 5e654ee6344f96fa117a2e1f9cdc08bfaca9c83b1c4d61891e49077c8ae7a8aa604e1b19995b32872087e04a59ed367e42f0ad3998cc2112035b33104164403a948ecf73c516f74adaa57688cee9417456f996847e0c637120478f7d88288b5403f0697c4834e4ea7f363ea1
+TAG: d1325e86d712a133cb4e4ed7b75715b2589f764a
+
+# DIGEST: a27799fc2e00e7abec4c5939451a834c4606cf7a
+KEY: f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116
+NONCE: 417dae0cef457b9e5e16dcc5b6f25607
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7d
+AD: ac997deafd64b1fc65de39
+CT: eded0eef58434338153caefd914cb98ff516157445bfbd25c3c5cbcc0ad68ed1bf049ac292da027acab0310ef08d66040341721524982165cfe7f6dc495f7f5f36cc410470e3b42045b718f580713dac8074b0e76a0345d11c94a9800bb5e5eef1cb8d9ba5818799cd1ef69c4ed1d7459df78edeb89e01ea8d685b57
+TAG: 80b94ac3cde906a204fc3bdf00e36d5dd00e464b
+
+# DIGEST: 7c52593d1d37b0dc380297231c6cb7b64e04c493
+KEY: 1be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef
+NONCE: 457b9e5e16dcc5b6f25607f00d033fb9
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd
+AD: 64b1fc65de39f4f03541a1
+CT: b463f7f24871b617a1001d2f73f9eb8fe39b5fe0b382d420af876defd68a893add2eb6cac45e56d669f4ac67a943a3b32daf0932072bd701f9291b5020bfa9133d2875d8f6ee78ce8c49d45b80329831799f1eee8c712683300e49c57dc8c1ad0b07465184483d669b04c183976289e3ad60702e8b0999a7792a9cfe
+TAG: 5148a8733167317f341a861b3455bc33df9fcee1
+
+# DIGEST: ac6871d354eac507556770d8b6bf10b5240273ed
+KEY: 33c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16
+NONCE: dcc5b6f25607f00d033fb95fb09e4d00
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de
+AD: 39f4f03541a11be112a729
+CT: 413d2c3fbc77845409ad66cc13432824ae4ae109379a9617e8b93d4f9b17fe0d0450476c3f98c229bf35e86fa792dceb4b3864761dd442c294e43b1cafe1fe086cd1ca5e1572fe2b3753c20a74b663b536f6e686d9765bafb10566f2b5cf02ee24e3dc69cb2be9392c991848b840418835603bdd83b2cf0f5df25036
+TAG: 8694b1d3b13be94fcce671a810bd1283cffc0ef2
+
+# DIGEST: 4f498d0aa9205160827626ef80c163275eca1f78
+KEY: fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f256
+NONCE: 07f00d033fb95fb09e4d00d6172e780a
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541
+AD: a11be112a72933c7b54ed4
+CT: f72c519566632f89513f3f278407845ff8096a5b63929f0ea6009c3cae0dbd853662c4017ee5729eab92f2c475f0a45533de67d4b941d4b16c1964986d8f4a16cc12f02c28442ddf5790f321b3942cb65964587f3fe55ab28064c52ce3d3598d3431788ed2c26fe1b196abfd35afa0f7c8206a6bc71d61cc4e1a086c4cf8c75274342950e4893ca3b0e9fe95
+TAG: fa51343cc9c204e3fdb1d9b5af26119fc874e52c
+
+# DIGEST: f0901e8b8083c39222fc940384eb73cb96b22892
+KEY: 41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033f
+NONCE: b95fb09e4d00d6172e780ab8b700433a
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a7
+AD: 2933c7b54ed4fad0be905d
+CT: 71fd9ada130acec7deffa6a53eab506bb5fc80ed7e98e656a5282cd88cdf9c253a87832ac42dae0e8a476011b11cd5c075c74b0f29c1c966983f3fa69e00df1ea93fad4942bde475e7ee08ea2c5f6676145c3dfb8d07521133468ce6e573b789a71e59d622587f8fb76e93af95b0c47e15938206774398e50a7e7550e2718270cc1f2b2e70be7be2df4442f0
+TAG: a82a8dd4cf89df1e3103a1b3dac4d3b1fb973e18
+
+# DIGEST: 7af193cdcc8d7f17b55447a81eef3dfdf345bba8
+KEY: 998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d
+NONCE: 00d6172e780ab8b700433a957a741c9e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54e
+AD: d4fad0be905d41203f5dce
+CT: da1b99574d59c3998b39dc057d093134c9bb4d0f9a38758e95273694e405b55d8047bf119dbf29c346ea5318a13c8eac769230c085cc2b67e57800279fd47aee9f2ba8e572bebb9f231e954430bfa53bd193ed74b4dc59d6c6e3687451c95d996c86283f10bccde027b90be52f6e20032ae1d83aea8adf183010f4fb90b9ecb96b6d79fcb98f36632079d35e
+TAG: 9dc29a1579727361d74d6db3e9d619394310261b
+
+# DIGEST: 4ecf44faa266de0904b093653c4d623a543d12d8
+KEY: ad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e78
+NONCE: 0ab8b700433a957a741c9eb80f2b021b
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be90
+AD: 5d41203f5dce998f8fb2ea
+CT: 5e1086339724c5489cee84cd57e1b188bf83390f0d264e495c92040a1e56a616d5e2aaa3a240592f65ef0e1bc65ca5e18fef30362fa7b38749328ab2cd7d43c5a37931597d975101e59d089f03a3d99d928cf50db01b3f5e789d4b8b4addbca347f68dc94c17944bbc17bc0ed7495a800c6faa9c87a152e792a11ea7f0b551ab2d5377d780e8506747b67ba783db1f7ff26becd07a35f4fc178567cd
+TAG: ad3eea5bc8aa12011332730a3d2adb24766de087
+
+# DIGEST: 92a938017497e0762115325c40b5f7c138d5c6f6
+KEY: 16417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b70043
+NONCE: 3a957a741c9eb80f2b021b1444769da0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5d
+AD: ce998f8fb2eaad409ae021
+CT: 5fb310ed46bd64cf198dc4b2a2e03a1cab6615e1d50179dd050cd538851669ab1ed4aea1970ace6463b5a910bf5be01e8d8196d6d0833a50a330531f61d962a4fa1767e958e38b4897514b08114e9c1ddceb19aea5d5ee079c3aaa8017e9ab7ceb03514f7d393ed60ba6fb88f7cf8bd93949426083afc9205052394680a7c04fa80c2f12484dd44047d80117e54cbe9105a5e895128dd29e99c4d955
+TAG: da935ac0c6d5cafc8c9c2139f848d68e93e7b168
+
+# DIGEST: 6b126413a7bac1069cbb5b338c158463a242d607
+KEY: ef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c
+NONCE: 9eb80f2b021b1444769da00fcfab0f5f
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2
+AD: eaad409ae02116417dae0c
+CT: 553c974dbb652bbd9a573ce72b9df30ec0c01cd04c8c706d7121983d8e8ce23436bdc2e3bb2134af220dc1d70eb68ca340c3e4791755e5b7101a04de9f8c455c81c617577e2c23c08eeb3b23bc959e4870e0d64cbec4c1d276d31f7ad19190f0677d0dc0494a8053476591dc5c87cba04248cf5c7c2e17131af7dd5b794347045ca4fa7b30723d29b22c509ed91e95fc456cd87c5e2b6e3e53472204
+TAG: 1d09e80e11a72ddf9beaa27c8cd8832bc082bf79
+
+# DIGEST: c72d214b42ed66ae0822fa9f3bda306c7d58cf80
+KEY: 16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b02
+NONCE: 1b1444769da00fcfab0f5f93b511060c
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae0
+AD: 2116417dae0cef457b9e5e
+CT: 8f269f0114fa47b84784dc3ef9a084d9d65e8bb10c345a9a9d13100860f2e713208c5c4886b40989cc165605f5719d5a8e76e146e6a5ec822a1fbd6b237bd0f02d41ae5f26032c202d5fce97ac0317c28d80b91343131ab3db438962b2e52bc14cbc286b50c1e4c9170e516461e24bf920c470ff7e2442f755aad133cf6b3e20e05669f5d86bd39a04cadc29b2c37dbeb89f0ff7192f497b3e157c4a
+TAG: 930cb7a078b1f1312a1baf186c8ecbd3cf1eb7a4
+
+# DIGEST: 9faaa58dd34a192550c3519f8c0aeb2ff48dd388
+KEY: 5607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769d
+NONCE: a00fcfab0f5f93b511060c9c5f3aacef
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae
+AD: 0cef457b9e5e16dcc5b6f2
+CT: 9e3b93e29ee6c0825e0150fd63a887227470d524fc52d652db43730c0c4dcc0f0c2f6dc2d26568a61336082ad638d91c4a3e149e0680321151771f52eab69a579b908db93d7a83d57c360f99de2b4ef1ee6fe905e17f02893df19073b2afd26da1729775ea4c6adac3bf7b50f2b7a8c3b8fe09ec371fe597d74cd15a32ba97adf813508ecab5aa303ecb9c20464a7914ab38255930448f990b058c89626024ae066ecd13619b0291c37297f3
+TAG: fb23b5521faebef99b281cbfdd79037dd351b7d9
+
+# DIGEST: dd5e6be3644dcc888cc50c0b2ad0d55eb0407fdc
+KEY: 3fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f
+NONCE: 5f93b511060c9c5f3aacefe61b184ad2
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e
+AD: 5e16dcc5b6f25607f00d03
+CT: a042853b92cc97b68982df3502800fe9ea7d8e7962002b7d8fca0ace62a7e4b24162624be865ca5010943f469b5793eb4fcc877c83b94c176f67f074704240e4c3fe3dcb1dc4f0f963b7550f280ae18f1b0bf2c727da8ac286386d852a71bd1a0b8cb2b39b3ca29b5570d212cd43ef0dbf480aebb6e246f300663a3e084e15affd00e44b11e4bb0afb7ba73ab6a37208fe63667d24a94f45a78f1bbfff37c5975a382e173347b11ccfb0ef7b
+TAG: 639c107760b90f4e21dee961b3a59f8ae6133f6c
+
+# DIGEST: 1b8b627e1020d71318511d4c2078eed315ee0b04
+KEY: 4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b51106
+NONCE: 0c9c5f3aacefe61b184ad2463939ed51
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6
+AD: f25607f00d033fb95fb09e
+CT: 712d1d5251c85943d3da1cf4ede4e648c64177447cb04d34c4417fb4b89676f3a59501b9da58d94c355f1c94b3470bded1c34c49b555238d3522e074f5c60cb0990b04d953fab40ac8c4589d16f7006de59a929b761cee5e4e43a708b53c4db32c49407697a65dea4d3b279fc0bc343f35621cdc097635affb7dcf17f12858cc20629461c88967b4a508703355421304d55ba1d4f07ac5e0d58b8dd76608c5441a0b7f8ae992750e2a0085c2
+TAG: 837b93fa27d7e8954a0e790c8e8a2f06a0a36c1a
+
+# DIGEST: b7370237d402dbf76f1a431cdfbb37f41ef2ad4e
+KEY: 780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aac
+NONCE: efe61b184ad2463939ed518ce97c3fdd
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d
+AD: 033fb95fb09e4d00d6172e
+CT: afc5e2e40692708b77a11005f8e5f8a81bfb418a9b1868ba8ce95d8c0d8a42872a980d8df4ee62e3b7cc1ea14f5681b21624f670c9cc38c39e02db42a79fca20527e8fbd84a5b54c08dcc3b18ecf34f651a51b922f634204d2699aa41e0db44525c9d0702eb7f31004876c2b34b60eaa9ec7d5a81e4878ebbb53fa7b113899e705e3366ee578cd6d3f2828bc32e3ea7c303bb94862fe340c9ab91a8c0b8d64471fd49107935802d48eae18a6a1d77f71cbf93daf609a91b0957ab733
+TAG: dd5bb4c15c4f4f87b676e66c6b9ce50f57b18657
+
+# DIGEST: 0ad0e709e40cb2fd662020d420d97ae50a14adc2
+KEY: 433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184a
+NONCE: d2463939ed518ce97c3fdd293d72afc0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb0
+AD: 9e4d00d6172e780ab8b700
+CT: a56be93b1bce1546c8e2ce1c44fc0a2551a82f8bdb89d6caed27589981add67b4c8f1c068d00c73b8821f42bc6268a4366ffa87c5eb122829d58423ed30015ffd10b2c4f4120d600bea00069eb909470a7c8cb95fa74b668ff756a2715635fb6603c27bfd9ab0e47ff19dc637bfb7294b5df8fbdb80adf6c7f1ac20b7a833c90619544e9df8f4b6c46846ec67dddf08896cd7d2aba20422fd2ebc287458b5b16825a2c938f7378a8711500f7968e2a46a4b4cd4682e4509cc79cbf86
+TAG: 265618c60124dae5b83273f274b2c021ba1f664f
+
+# DIGEST: 5f9967a8fba7184dd97dc7d5da22ea785e0ffbbf
+KEY: 1c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed
+NONCE: 518ce97c3fdd293d72afc09ffdd4f419
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d617
+AD: 2e780ab8b700433a957a74
+CT: 42c4a44d5c32c5506e5e1aa6b5d02294a7a3f83e0b69b86b3bad5fa159bbbff88b1c691f19a94b9c09351e4c2da5106b4a98583250bf76156ba41605a78595410ef30fd5eaf6d7000ca24d2e3327d9fcd69ac842f31c7a5ec7798c917ce4eb0d1219b90092aa680c73baa42c4d930b3bcf3052d88d216ad7b52caddaae916600c6a31c9a4654ce4eb528c355d99a3349035b37b9df8f2dd07699631c54c6604815bdd16d9c06fe27f29864f7dc6d340d1c6d834d21e1dc79d4c716b8
+TAG: e8a35426e7b86baf32f17a3db30ea0bc012a83a5
+
+# DIGEST: b5aedaae523d9d396ad1d9bb175bf4c7c0b03eb5
+KEY: 021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3f
+NONCE: dd293d72afc09ffdd4f41963249cd299
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b7
+AD: 00433a957a741c9eb80f2b
+CT: 29f67431802cb52308b51065f1592c6def60f3f503bd12deeaea4916ff8dc310fe84ac7da36cad4c96cf115862b2796d90a95f8f23edb3f495d72b0f71552975e37e4105dd70c87a3273e46d62e23db8a2504aeea3451ee6505b0fb0d236232861dc006320e36d9828e27d3a0fc607c74bbbcf9c94363ab49efb6e904b741d2f6c93c2e55ab9e41157d9342e234077770288efc77eb95b335529975636309836349d5d18fa7ec643e972ed0e9911f21eb04279ea8bb0b04e9b9e8cdf2c4f3a039e0c32148a50a93e0eb29d9a
+TAG: 093eac58013a426de1390c66b8d4a8a52688a3dd
+
+# DIGEST: 52bf12f5594b0cdefcf977c07626e8748cec5425
+KEY: 9da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72af
+NONCE: c09ffdd4f41963249cd299b92e55ca24
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a
+AD: 741c9eb80f2b021b144476
+CT: 170a91c57848e7fd097f96da09530676f65ec1e0e31cf9f8de86bb5aba87a311d37188abd1ad16fc4f6d8201b9dcf3aaf895fab0154c301464b9c9d1a082d0fd3ba717086f2d5d1b5b2e71eab58a861b53dc5c3c45b0dedd334e308648c9185200d4e0ea2e5f26bcb0bc6964d63aa548de958549aa2d68b455e46f2ffe6f9f3e8b59e18b23672600f1f44247600b43131e7530b2859fd7b8fa5620dc8da0b428f5a1e78015afefa79b504e35e1148fbc58b982179002125748c76b3d283bf493cfbc32872dc1afd006674d15
+TAG: 455a1ec8e67c5a7af2b979ad23c6ac7b5ab3a8ea
+
+# DIGEST: 900a1792a921b6a253c47013c9eaf01fc5c880c2
+KEY: 0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f4
+NONCE: 1963249cd299b92e55ca24d8c078c49f
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f
+AD: 2b021b1444769da00fcfab
+CT: 919a222be8cb73e456dd156c699448211b709e63886967b73a1eddff4a6ae575498823bff9d8a8966c22f8077aef5befe70492175e31daa749fbb0431c1880a8595475a48a299f082ce7f57b2f0a24b8cb8442041bc93e01e44253085685a056157ef6f75331566ab98e1598108ee47833b2f12764ab1ab7b5fee647e95599f2daae053cac2c02413930f81eeaf94ce3dde5f543cb219ac32eb20bc0d43ee92586b3886af60736fa45400d4bc848219d06e8063bfe739bd44fe96564d0437ac12ba99c5f02bb3be4f8d5f712
+TAG: d66f899357f64957f10b00a48e605137a8c830e0
+
+# DIGEST: 88d7ec35d88ff113703702955e931e802fb0d8b8
+KEY: 060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd2
+NONCE: 99b92e55ca24d8c078c49f78c7e71371
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444
+AD: 769da00fcfab0f5f93b511
+CT: 58006dd9eb2ea343d8bf40076a71c209375b5ed356073b946dab0617bc456391fdc21a93801557bb40699eebdf57693107f73ab0d777060569d6a300eba25c9dce54c621a25991b43ea18b9266c0b4e2571d9870ce9ce2e705e0a5b7da6424a579c3a890b9ea99c83d909b033c59ab2e0d9d48df70a04535a84738fb355ad579fad6e48803f5ef13c082f83f7f8f1f603a91b33f159c5157f8feef6d9f679c0992f726f05892a12bf6b7c2d97764e640e0174ce82857630da3ca7e032ec999e528fa63004b49c35661202ffd334e3e1e266a92ede447a0b876b77df4
+TAG: 8dc2fd4adc9331186eff899f8dd1acea003b8316
+
+# DIGEST: 8d8493b55d9b74892e77d3b730588c087ca9b1e8
+KEY: acefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca
+NONCE: 24d8c078c49f78c7e713710a025cb8b9
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcf
+AD: ab0f5f93b511060c9c5f3a
+CT: cabca6bfebb503df1a2b2cfb11c23394f1ee57edbcd0c8acf4546dfe383d7b71134bcbde9dcbce5bc4300964de3c9c0d48de13153a69101643c48842bb0efefe9e928fac973e69817a7fc35722e22fb21819107424db4836d24b429e8eef3b861099d58aef6bbc23896f862fe41ca72a34d9f41b8bc4daf96f8c7b4e01c3abf5ae4a7839785fb7bbcf50a93a9d621770797c68483602c30e2c8b91acca0f6dc08346c851e1d5f3da4eba9327ecdc56ba52b7377ada217b595e760935ab5c681e813454b037dd6ff31f67fc29fe84663535c6a259161d6b16a7d85d6f
+TAG: f59f90ae7624b9fdbaa9cdc72f22396e98b4331a
+
+# DIGEST: 4cd92ac16a807d2ff180df75c47d848749c7ef46
+KEY: 4ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c4
+NONCE: 9f78c7e713710a025cb8b9d71d2989ab
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b5
+AD: 11060c9c5f3aacefe61b18
+CT: c5d01436be8f519a54eb38637bbe20c56e6bcaec1e9557578cc1ff66658b83ce117092f33c40084eaea1db6ce043b35cd2a55f109db71567ab7039daebd2a363246b48ef0daff133d51b21020270f165056ec0ad3ef67f3d4525d14c50730ccd3d0990abd52319010f3afcf2d312054f6be80adb71ef96cff4377a35c63949caddcd52dc2a8604567e7894367e38db843060f8a34d6c6bef60a0ef47c31955229d7edeacaebeacdb45ad147b1d8874846c333a1136ec0992f9847465b07899e7d144555a8a35f65c25c7ee092de14d499968d7503f106a11cb958d9c
+TAG: ac452c9d89f0af8ae0ef497b74631fbac1944863
+
+# DIGEST: 64ee218c0c96ca8e2d2e50cd809d61ee109baca6
+KEY: ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713
+NONCE: 710a025cb8b9d71d2989ab33e978c445
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f
+AD: 3aacefe61b184ad2463939
+CT: 37a3f88b2b27dad02c71c257d17331e7650f71a4632fa6dcd651c96dac0acd00106494e7aa6d7667a8c034b621608f5edcc4ac37fed8a5d150552e365eadeaa665e605c158e86462417c5c161bb4d4d1797718866368ab4518d7bb109a55ed2e73d02d9b94ddc624f869881d8d4762e733d44dc04498823ac137ec7ec7ea85281c24dc9f63ac2acedb9c46627f825977c58c61fc930b511098df24807d7a5a84634e10a4726a7f8c668f5cd07898821958ef074ba4397631be00269b95967538f4766584ddc1479b4bb104ee2448ce7186ff501b46184206660cc091ab5011ff99cdc39a37f6478b1cd82ca1
+TAG: ececa23afb81adc0b576d49f83b454a39c15c8eb
+
+# DIGEST: eef8eae201ae4e5af32ee74bc724e13ae5ed3978
+KEY: 3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8
+NONCE: b9d71d2989ab33e978c4451e3be585a2
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b
+AD: 184ad2463939ed518ce97c
+CT: 1112903cc97cc872c44f156068c58992f1aca2a0a8f1b8a08e744ac1dd0efad9321556c77e9c64fd6a36041ebeb980c0ff064aba672e4eac6cbef78235325c412d80ba0bfd76b740623e457e0e600f375e47809c56c1b7f2f5359d08fabf5cc6beda669a495813aa0e8368f386fb9d7ae42f64a52c047e0230e045d9ff1752315af9f6c4348d7e685b3f3e2daef06e41a6997ed11b3fa0f2b15f074b1362c3096d010671a8abbce7bb5c729fb6babac9e685a1d64ffff97c17b33396d2fe2a920082445fe75c8d924ee2f5935dcfef6e9a88372e2c03be6a4447153e96d81f7bb34d9f9b3ebc9678fcded522
+TAG: b32214b890415a87105aa401c188808ae0a106c9
+
+# DIGEST: 2fe67a81b41b094a708ae515e28bcbde3bed724c
+KEY: afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989
+NONCE: ab33e978c4451e3be585a29a2af12fee
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad24639
+AD: 39ed518ce97c3fdd293d72
+CT: 9fae07a37501e2382d004a399d8cd95a9cb9a4b6dc038ed7bcca0c85073acdffcc66a84bfd302c48a4eed40a679d5658c8eeb76772cf93584a8decb8969cbe7bac022b18fb86c7bc26f0974ae4e03e36c22bb7b3e02d182e25cfd52ef7bc890fe0f5935847f8652d42965757105e88b327e19308c88cfcac46a47478ca7a0643da97478b127f4dc45f61537394fd4d049d59e8361ccee4ac86cbb4e14050ac07dcda7495f1a1d34095a9f7d697cb6b88eb9a6421c7ab338ab4d0d5b2bb61e11ddeda49e75bf6d0bf0d12fed98d50d65d33e029cf341f0f7a58e85bd0568b7cc3db803ec5e9d0cecc027d5017
+TAG: b820cfcf74d78664b23fc2aaeb20bc8d73499954
+
+# DIGEST: 33d10d6cb5dc80751d0f8e370925d7c86cda331c
+KEY: f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4
+NONCE: 451e3be585a29a2af12feef71e1063b0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce9
+AD: 7c3fdd293d72afc09ffdd4
+CT: 1817463656d30d6648bc628a45e20e231a4ff8dba4eab244abcb198580499c696b41cf256352023975a62e66d5359f9bf656cf098819a5491f1a113a06fe4d56ab4629665b93a017369a1e2d22f817a66120197e20aa92f174b5ce4e158a272b51acf766858864fc5c90c1ebe9bf79b61f327eb12a106a38662bb2317db8113c3301f00dfc54bdd79ba7126f448cd9f3eaac475bb62eeff16fe2de45af646929f797f69163864884279eb35ec9ad6137a694d2c72a2cd2fbd25cce1ee90b73b9c7e592af463057737a1db4da41b479abed76d3b601292544be8ecafdc43a48129ecf1d94dd9d59183385cb0f
+TAG: 58d011c758b6b59622c5f26faef2f7e2a97aa82a
+
+# DIGEST: a29f128842a48debb60699ae0df0da9a9b5e5dad
+KEY: d299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585
+NONCE: a29a2af12feef71e1063b0b4e6e89920
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d
+AD: 72afc09ffdd4f41963249c
+CT: e68230ce6101c64176f56a57c34ee54ab6e95b7aa28d3e3d262fae71ea66e5f1699e31b3f9cc1337d2ac193b5b6df4d1d10fb86b77c120faa9f67ad6d9cf98c49e1ee572eb8ef497611e6b5f84ff42dc3a2461a326424ed0e2c5978ab4175cbc15dc4cae9eefa24ddff8d055abd113f0fefc3af7405b153ea1fce067062a751c306cf0eec477d4b9a068d5032c410de991497b6c166233036841b9c1f6313fdd216200007089734d096189f4c6cf0a0e5cdd2328d8514d319d5644003201124ca71df0bebc8c61595a54a6a85f9a88565a0f7b517b20488da57827caba252efdc6766cf860f89c21128ec572c2a5e44c8b92c00f8d4306201a1fac67
+TAG: 97931b4600a3993e9c11e01b7fb92f01c20a213a
+
+# DIGEST: b5048d1efa7564966b6cf1579cfb4ad8e9460660
+KEY: ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12f
+NONCE: eef71e1063b0b4e6e899200304bd3508
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffd
+AD: d4f41963249cd299b92e55
+CT: 7ffa8c3f882de672b6548e722bdf64671ec122187bd811240e0c8a62f7ece34743f3e8286cecc99ad2637f960134d80230f4b358422576025bf2d2e25cb0b2be8c93fe8ecb1a2a84367d075b03d2eec5c8ea3bc306727733918762088ecb995b61720cd294bfbea261cce90ba5ad6f5b011bfb2767f4388f1c2fc5bcdc9faf1517b734aaccd780328a0cd3c3e8a82c279231ada466f5789b0795e56c9b14073b9900046c7cdb02edb55c96aadb8d703f0f6d739d0788447fc8c47ae9ebf40f38355476bbad9aa239373a6fd38d0d4f39590d70cb1068729ed8e685fb905685dd549e333c670fe07abb04e7af6b6855ef574913c06c595df508852081
+TAG: 48d4c51412885c34bf197e3eece02ad0c969ece7
+
+# DIGEST: b6e68f5f0dfd8ceab56ebb657728c9bc5129fdf4
+KEY: c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063
+NONCE: b0b4e6e899200304bd3508132a027d1f
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f4196324
+AD: 9cd299b92e55ca24d8c078
+CT: 0638cf64bebd174c40cb462a85d7c6ea529619e2a7338e829f91227e5586e88e11bbf62addf813475e1bc024b60a2f8ad72541d3345898b1833f28db4d9e2754807c3b2888e01584590f879ffeffc2cd66973c65c3712f7a7704ece102a5b67e4d7414fb53ad9c16e4aa8d4f310ed787dd8c23b008f0a9667b84ab7e429ad7d2173421c8ac06abb1e4da82493a01a6872ef6cb603ac754d96ec48cc15ee9c127e321523aa02508595edae2ae4bdd453ee8b6326d05166704e1d358d7efe22c24a40be281cbacfc97383c4a0ef9f2aa45e0b31b06b8b5ff75bbff51b6c77880093bbf113135bb7c251c7123bca5e35e311b55fd7ddc84e507039cfa81
+TAG: 12d34c21d32010e1815b550a05b971cd6153f281
+
+# DIGEST: 853bc7b9fbd640cc0654fa5533ae302e398bab35
+KEY: 13710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899
+NONCE: 200304bd3508132a027d1ff4c047b3ef
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e
+AD: 55ca24d8c078c49f78c7e7
+CT: 20e84bf92ccc563048b5d130c8c2260974171942a26977e1b1716c1e73007433710609261743a0320598c80712c1c50a3e8afc047a5481ee38840486001ef9c7ee14c42e4b41cc6238bbc2c00f5f1ec121f5df881a12e98ecc46987a93fa2ab6c76279850fd2097f7312e699d10556c4899ba330ddbe52ccce814fd575842153698cfbd9602df8d0ba4765c6483de83232d9705ca82a866b78b1c782b13330b8637c0de7a0ac028c7da0a5510373d56a48e8bd1e59d269fb69ba7a73b1bd485859346d060677ca386c04f6d07b295950fa3ee91cd38928e29a38128b8ed73007182ae3870630b385ff6f212413260d083c61f1e537b6d1057f3972553938adedc275bc6faa902aefccdf13f0
+TAG: 825ebfc57f0daefcbd118e10e1d324056723a87e
+
+# DIGEST: 286a92c480192206a2153df1b6d0eb26e6507da3
+KEY: b8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd35
+NONCE: 08132a027d1ff4c047b3ef4f57a74706
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c0
+AD: 78c49f78c7e713710a025c
+CT: 6da237176c778f67e98f09fcdc96ab9a54a9ece12c2e6de1223dc1a22c74902352c33dfc993b398728b8a62206a656ed0ac1d49cdacb22b9eb1ae70e9b7f511333054dbc26a26f837ed0213ba98820c31104dcfa60c6892a98bfa0a41fc220e81c219d3ab9312ddc534f314d35056901d04d485b3caec47b746445270e2276e02e8f1adc54547ec9efb1ad44354b25b5c09c58cd9480a68e758e87739888129e337419d9638482cba7259f5b150891818b58b24fbdf6211c7c5976cbac2e10dca06d425247005385996a9649240d680811a5ee4229d0984c11291f86b1e75a066263d3a738da0c98ba24054da15f6f11f5c8aadf24b547016f336beee210877b25e987ea0dd1abc087078d0d
+TAG: 7e93d9d86375891b928bf21763a87e31b345b49f
+
+# DIGEST: c2acb0c126af5282abe14058066631fd0c658571
+KEY: 89ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d
+NONCE: 1ff4c047b3ef4f57a74706de4b381c69
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7
+AD: e713710a025cb8b9d71d29
+CT: 70e4d06f468de2780565a300966e410ee3e0ebbdd6d29b8921a047fdfff86da5f4fa2981c1d7a4013c480b8ece1fad84ea27ff0b87bee1bdb88a661954d078bb65bb6a2aa1ed5b00519bb0c56069774dde08b06bdf83335ea9c8702abb9098015707b00122eff2f8e5108e4fd6cd719131f919591d0c5198c1d975c4f038ac273cd6f9ab2f8136b48429efa57c6ef1a239a693086025bf6db218c2c26bf0ff823dbc08944f06c7be29278baaf5039e544a54de7208e0392bb5d9972f3c3a7e69532b5d4322c71ea4af6fa2167996145538735b3581250c1fde20c03b14d01c101a0a04e79f6c6a6390f10cdbb3fa3e3fbb03a64132bf82e965039f0231d69ae71ac20ce11bfbae7229a90faf
+TAG: e3412c5b67009dc185a9b38d00e26e9cd299e550
+
+# DIGEST: 500e5f2a56bfafb2d93e26224c9c2df562589f23
+KEY: c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3
+NONCE: ef4f57a74706de4b381c692ef164101b
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a02
+AD: 5cb8b9d71d2989ab33e978
+CT: f0d7b956c586c029980ff8a78a79df78d14328a608b47cdb8ca3670f4bdca883033f8372b6267218b07dc5b9aa5b8104a1c8c3fab4d6f3d39c2fe8d7c997889a8deb970edef03204852873f1f9f07e41754996f57fec4d72cc438c7adf58a9e888aecc2bf6d7d240431c1481e7a0c9bd27743700141b7be5206a027165f9ae82cf1f3aaee97dde5ce850e34bc714ad67c617c6640905b1c067a214a160df4e787b48cbebe465cfeee405c8611c7d376ce913bc3a5c0e996e4cc252a89a48ff09a18cce553dd5ea3ec9b7d8417abdadaaeea44ff233ebb45fb6385fc2c4d9be76cf2ab7f803cae25fbcfa68bc05cedb14492111696884995046b5959389081690e7e4ec9c1af09a482e74283246327ac73e153a515cf974176c011180
+TAG: 0c5f76ce31a1d08772b950754a82e6c5b7d5dbe6
+
+# DIGEST: cfa6a42a2cc0ddf1c7b20031c95e331696bb9ece
+KEY: 85a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a747
+NONCE: 06de4b381c692ef164101b89b476f72b
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d
+AD: 2989ab33e978c4451e3be5
+CT: ac2c01cbae12fa7572615a755522dc5c0aa6d7782167e4459e5dcbc6a5c2cd8164890d2715a61e4e80cc13a35c48b537f441ad1bb63e2d3eb2cfba711fa3ea878cf0b4961ea3a016fe0a918f7683be5a243f02ba3e651950f15d4df7b7f144a57feb3d6bd50707731e273a2b78d7733be4be6bbddd4aede0ff29ec67d280f159210ac1ec62500a8f0a2c17a6d05114eede2ef4b393c4728d3045e48bd381d616ad13d7672083b55aeb1f6bf0a043bdf37712cafc7d57d23b1fc96371bd111cf0facf75d45e28f45cefc76ae50a5a90c00915fd348d5dd2110174ba52b67c6158c1ab541ee57cd7e29155e6a18bba141eb6b5ecbb2f22f68e37a695a2e37aeea8e2f66209d9664227344facface4d99f2ecb03f39f33e804488bf9293
+TAG: f087647a39f5b594115586268ac92bcd688e1580
+
+# DIGEST: 2d1b27948de83e32a0fa5be7040d896824ac1fe9
+KEY: 2feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c
+NONCE: 692ef164101b89b476f72b27f06f520c
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e9
+AD: 78c4451e3be585a29a2af1
+CT: e750bf0d24339dff581342ad50a30cd209bb3a4ff8435fa17428c504aadb7520804eb83698f54c13532655c032b83f824cfabc9513faeb6bc63641e9c76c019964699ab8bb31bc22c0a1acbebcb76a095cac94afa630030e036a48cd49ebe0af001604bd753234e706b48183f2bf93028267ba8622cd661910a6e147c8af31364f3aee50b14a40cc6a8a0227615c4cc6a139cb2a33374145841cb58c44e0dbe5487294ff9e3691d89666eca0c3edf6b9b026abe508f1718a86a7ec35c2719265fc1424e445335d81afaf02650f4dc41d752dcc2c272a006be8e98bd80250c66a616ad87897f7e5b9a8a00f54e942914e2339fb2e08359b3f78f8b9c8927a5fbb0a810c4fd826db8e0167d535816e4b2d6d4d199b96ba1c3718a564e0
+TAG: fd21d17bd5530d73dec0bae15222bb76a8903d15
+
+# DIGEST: d35ac8b9ece76d43f1497ac8681c5077398bf2ac
+KEY: 63b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef16410
+NONCE: 1b89b476f72b27f06f520c9267cf7140
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3b
+AD: e585a29a2af12feef71e10
+CT: b1def7ba0c05f8acf42e15cb052fafd63c2febcf277cc6aae7065d606b502852696a6081d096de91a8673e3a96ebcc2b0120ad68a2b1a85457dfd38e187ae42e8279c3e2b57b1f7d69e11a51d1b8d7165c6e74d84fc1df402ae551134939e5a17e28d5f415a491c12b3c70d473c370542d7794103d7d639d9dcdcd5f67ff7a2420d2d38a433ec767efd5e5d9aa64ce3570e116b50b2514ec29a7afd8a831ce30342c2cc79066eb1373e4d44fe432271dab68bf1fe2a6a1c45a4060943825bbebf790a2298bc9dbe4891320d3325a309041b411a629346b12e3e929bfd1fe5eff9068713e6171a89a2cc54085a2224792ddb9a7ffceb5431d1b8fdb7d7de82c7db78d7f80260333cbae973c7f3ced0752e792546f2e65fbed672ec987172308ddb2e01ff8f34d767efcf93b5d
+TAG: 989b11b610e5852a480286b0bfab442e52548f4b
+
+# DIGEST: a3b33fa67f5c471a60a63dea915333550bf3af04
+KEY: 99200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f7
+NONCE: 2b27f06f520c9267cf71408a41729bac
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2a
+AD: f12feef71e1063b0b4e6e8
+CT: 046bd6d55b37dc68cd7cffe008316544ff781e42afe4200864178ae7d666ca3f83f25ee4ab1f2847e132d762225b87ea77dc30bde8f3ed156251f9366573cc759bb5bfd129e3c3f799832ba8b489ac3616c3dcbd30ee75459ce15e7885da51ca277ddffe5756b22781cfc00ad7eb1283a4ddbacf5f2921b155b4646335069c03f62cc01d75ee33b40a20f46e2a8e9fb1b3b02bb7d7cc56913cf9159f12e2df6b166d1d2a064807ff296f774216fb4b1a31f3b1da9d9dd6cc76f6d365a6fcf6e7424694b88bfdd8af1237cba450a7ad1bc8bc7ec3335eff5edf0c95f8f0ef051406513c910fee9b51326b4e17cee5446ed7477aa9399c4af75ee25b56154b30f410c47db1cf9ffe8740e52501d4295bd3abbf75b88691d50488b07f38abc8a6bab104a701c8a1a2a018242105
+TAG: 9347df07b84f8055901ed051dddf5737bf24143e
+
+# DIGEST: fc45f684acf19a1dcbf767f671396e793430d7fc
+KEY: 3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f52
+NONCE: 0c9267cf71408a41729bacb5877e72cd
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e
+AD: 1063b0b4e6e899200304bd
+CT: 818d8cfb3cadad479e68b2ff3f8fc79e098ac47e2bd838fe955af0a66afe07b216f744f3d1192bbaded6127387742f8d45bcf43341a3f2bc9be47fd9ec413ab0e2afae4b34ddbdf97988a3a3af1b578095502f79189dde995b234daf811380fb12c60b0910ae663c195fb5a834e7575487f1c4453ae20c97b622bceb018623a107a26a9663a62b0ef0ea12e3d2cf37b4ef2770c977c06a17bd6fac29483f6c56d2c4b755e38fbace64b1ee521ca994b86d2b1f9610b7c46d1b65a490b56f4518de3fbc9337699a5c2c91818b8df531149f6fbc0860d5ab93abc5df22465aaf6207f28eae0792ceac9ceea56672262960bc6d821d0ca831ac1ce81dc1771f1ee8577fb3ed0b72a93b80e62fd3ce2afaf7668a0c4c08c99014fb254381e02979d69b2ef411f67d3da7489dd0cc
+TAG: 26b2ddcfaa1f7ceac677cbb88bf0839b9838047c
+
+# DIGEST: bea3f11679bacd98ddd996236dd603d319aafc6a
+KEY: 7d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71
+NONCE: 408a41729bacb5877e72cdfcfa76aed0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6
+AD: e899200304bd3508132a02
+CT: 35ad27b44bee4b205fb9224755d1d79d5798db15916050287c9ec894e706331a290d0e32c08b5f417e1cfa07a1d176a7830e5aaf3cdedec5ddf4143cffb045f55cf7b901ce3de905ecb0a4541db8161082cc12b0872d3818e793a379fdb9131b3d521ca7d787360f830ce7dba5f79cd204dfff53ace458842153c3b0489ff04fb09b9f2a4ced538c64caaaa09713000ab48f0ca6b283d5a59a7d1845ef228261ac41d1a71a134d28bfdbb92b6cfa18258702e33f9be85f2848fe0f052ea8133468b70aa86de44adb5f31d2415bf852dde608f1e6673334416e8b17b3010dd53d95f9a5322e025a9b259f9cae0158f8864d98a8297e2a3140ea4ec962ae8c904f7a5108eea7583f13d977008d685aca7e8fa7cbe80645aa1a016e557a6234c5c96171c017b8f4ef1a2b9a66bce7cb365011df84ce4c1bb1ad99a47ddf
+TAG: c2dced82907168cfcb15347115231c288f5de339
+
+# DIGEST: b0ccc9b5ae13a7f8a01100af61a34be7ef6ccf6d
+KEY: b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729b
+NONCE: acb5877e72cdfcfa76aed06707a07c3d
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304
+AD: bd3508132a027d1ff4c047
+CT: f454347ba4e2b6254e66b97f8ac519c2e263ff43c65869553ba693bbb54a96c042228493f97292e1f5798e73c86ad8f4c521e0c4f199902e534388c9d5d2d2c54fd992a3e073381e0cb2fad75331979c76690c8d8c1bf3e966f7bb8f5dccdbede2f628618eba828c8336e2914931613e12f7ca9e0b674390bc6128f9e18f3491f98a073013d1fd78dcb4f0ae4eabc054f8935563353c4b6bb44c3bb99f76568acac0df85200987c67441d75b48312e98847301b3db282058a31f74197cbd4d1ffa6eb69bf67e9cce44512d35b9f141231424dae335797bbb16c16571fb607908324ab86d8034341e341f3a4646a2636ab5326bbf1a63445007fe8fe4d5279396c1a36d04bf97bdaa5978d9c4e598cebcd80a1a2f0045f1d0ae626f92d09f999bdcdbd889de2e4cdee882b757911fbc8421312c1d345e3526356c9cf7
+TAG: e7bdc63b30d2adc79c33b0cc32143d2894b48fed
+
+# DIGEST: e2b953c833076a52442a7afab46150176c47b730
+KEY: 4706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72
+NONCE: cdfcfa76aed06707a07c3dab699719fe
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a
+AD: 027d1ff4c047b3ef4f57a7
+CT: d8a6fd43a147414840554083c11d5fbe0b12d2298af893294f4273df0492f5d8bcefe2c811587e124d26f8cd7c737b2f848b2b25945d4f031db45794ee24b81103d172c0d0e457059eb972371f275a0c03737ad02b4f8526b32a39c460931f05914ab3c2a16a48405bc662693cd08e2d79cf722b9d57b998f318f25dc267395c195d83b32c87c8812b65b6db999d64560d8967cd0ba99445b1601aa03b290cb6803a8e6b0196bc9ba6dca507fad6e4041666735747f08f0bd56f1f5097193f373ec062750dd462d1d6e987999f7d0f06fc1d0144f98fd163cd0b0aa64f2edf9e29afb05ea1f1d055f740e162cb14466e01ba68ba9fc942a60128e2b6d58ca12ec2a905747c3035f7579a1eb8abeaff88413b52624f6372fd5f2664ba69e71b100178b88e365ebd0489c48bda8a4a490df66bb167de1fe77e14318d46
+TAG: c2bc8d71ede61ce63bf623a1f2822d78b8a7e70e
+
+# DIGEST: 8e84935ed1bb79dd38ae38924952e1105101533b
+KEY: 1c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76ae
+NONCE: d06707a07c3dab699719fe882eee2fee
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c0
+AD: 47b3ef4f57a74706de4b38
+CT: c2c1f17e309846fffa55e6fe4137029fb8506ccd4b238523812d61096c4a533737c22ef0f940f720d26563d2c7c90a48c3b4ecbcbbd9a641242a68b466f4eae6f663ddf27555b0b492419847bf333f815b7467ac4ee70ab683d37c1f966ee8d40d34c181ed1298d2084b634d4eb49466b21f39909317cda6a900925b32641184c4165cd3b6596806b6482c02353802e5ca12c72f111b0e0f7edb9c373124b5640e06d3163d4516a233db3183f67afeb3cd33db49998eea63648c69f441357f092b5dd5e5c3b69254640ae313b71e741c00cb9bc4944b1bae449fef8a32c08ecd316723a286d25598280a1ae189f4a321cf443135cab43f4721663848ac1373208a28d3640e16e792bad274b2d98b182455e56d27211e97b94e6ecd95bb33cdf8c42f04b5c4536ee4838c1610e90f312bb5b0a1de5825a261b5d08967
+TAG: 070bda84ec98b059629d10d0d0849495d1a8e0a5
+
+# DIGEST: 99ec6b669dbedbe99548117f37189e669fc5d8a2
+KEY: 101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c
+NONCE: 3dab699719fe882eee2fee55ed8b1153
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57
+AD: a74706de4b381c692ef164
+CT: 352e3b5b2a8a9552e0159017fd9ff4c169869ff3d1d900711d29889c4f1365b1e3d15c7162be4a1dcaa6b7209b9ea600916345cab1f2c1c79200826f180e1f7c92af192b92168c4f73ebf2a671577c5b995a26eb24b125ee24a47f78c94b48f69883b1ee5dd5c9e53835640066ecb26c631fbd18c41a67e59ede2d824e7d7f6d1ddcb14fcccc85a4faa5d46f91d03d543ff87989e8d1b3b2fd87415edc709abdaa7baa5e2a78c394302a630ee14e908fa8dddfe0c3b1830ddd036ad5e65e4d3490321dd450c01bb566427240882b07c0691f2f37c346845da3a8b50e291d5bf9b5572e72b7a031ef71f744acd6a3ed9ea32ada739184b6268954af35c6c293e64c83573e95b166e76ba981ee6f1723fe3865e0f17b28d72a869cc0cdf9c21ff97a11ccb6fb08baa5093f7acb55cd5c534389e1564b187a6bfb9cbf98044d718a99b9c8254967607e0bdbdd2c
+TAG: ee977c194e315505fd3dbf288be63c3fc871917a
+
+# DIGEST: b55f018cb06f74f0a9f76e65a23c1744ce7535e0
+KEY: f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719
+NONCE: fe882eee2fee55ed8b11534c870dc695
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b
+AD: 381c692ef164101b89b476
+CT: a95aae1040d61a7b44194c20233270ac94156ad0d735c30356beba1adcfa9abe3bb55cdd41a4f1a27446afd5221a3abca45d7b867a999d9cc1d89f19cc32907083e72c43f5e39f6b5d5682923914f4cae6fa0ecbc02c9d7c289c39a9a159b714c9e0eccc143b13fc5632ff079d4216b331617d2dc62ce9fa5da2b1c59f413d211022c79ac5550b0c7ae525e0af3d364138353f4ff208215393f5667359b2f97b5852959c6e4ffae26fdb93c1b15720e53206f2721c58c8a7241806c80163796ba087a073eaaf1cd3f433fa24518d0989607339c2d0df01ce1fba94f755ca5c43243f16035506bc7e69b21eb8d2970f35dd282fdda64736c92229254aa6b74e3dd929ae1cf9607950407b01c5fa0e9990488f5d07fbaef1062f51acfd745aa3bf27cfbba630aaf19d02aba5a55b95a6949ddb8669ae8b0f13453a905a43fb6f1fa97fe1c514820beea65a549f
+TAG: 03ea186313e6d0eae129bbdd8cd40f3ec88f3f63
+
+# DIGEST: ac3202e483c67fbcdd751950e1497feb3ebacf52
+KEY: 520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2f
+NONCE: ee55ed8b11534c870dc695b814bdf1a8
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef1
+AD: 64101b89b476f72b27f06f
+CT: 458997cfcd9de1ef0222884a21e1af8773fc492139b15eeb31c48e5c32c918036618f4969d34c063cf759906a92956fa066d0045e8acb813081a55cef1fecb34178063b4cf6489b35374db4cb422b2f88b28fdba361550f087bf686ae0f7ebf4e5ac6ab0e4351d7682dbf825a79bc9a8ece0f5679517d33593d1fb9d1927e6f944a02cd2561da59f01634f4328423c7a4e1d1d57debbfca349e5fa1fd4735a87cfa8737ca4cc447d3249d6e1ab998f4efd62bb50bc079399ba250eb24cc43cbf3bdb30e1c5a4d6b3f679b742f39f123e75646c4a42dddc3714042fe0651e1efb0078a636d712bfe51208f8ed2ad86759726942a9026e5e158c8f42333601e9fd54457183a7253543f6372b57fef6dc9db5a655f37b265fbfad0693c0504038e36883d61e83ef9faff4a795fb21787949793ae00774cd86b8df51fc5492efd7800c223374e59adb59bbb69ad1
+TAG: 8f00aa5cfdd05b3586477d882fab3bcf49a0d900
+
+# DIGEST: db82ae5d79573da2bd7215485a92063861879c3c
+KEY: 71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11
+NONCE: 534c870dc695b814bdf1a87bb1052c67
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b4
+AD: 76f72b27f06f520c9267cf
+CT: 8ee287bb4179d54a23ac238a457da5317d6f73129f16a288d5d08ce503395ec9354a9babe85135aac28e00fa66e16867a09e9c6c2366d73d74b80544b85ae48ade77800fc82a3ea14a7d645f0cfb19ce2281d2de096ddeb822d838123806908c161b0372771d9281f4471fca2f2fe6d4d33bd6de70b21bb66728f15948a34c756664019369efadeae8d84a777a30d79aefe978f6803c56ec8a2138bc294787a1083cb5aa0835585acd7239a85dc8b556fa78f64f45973e97061591f756069ed4314a2275e3a540417d87a2709b0d22a02c2d6f7a34976290bb83cfb64a3e90503879fc26fca103cf64f925a9c87848c736b349145d86351855216440eea3f6454e4ba4d7316662b04b4ddd0dd66bc99598f8824d062ba29916799859e38fe17fce17c83b83a7b4e90e6b112197724005a70f5440fdbcb6a2b6fe3bcd660dd7078bbbe6b1d00ac7782edbe62ae0ef6294689a1c2d12a0367c1961cd21
+TAG: cfdfda24a5dbec4eaa3d68bebe6b12bcaefb1ea1
+
+# DIGEST: 902d703861f9872e7b6482f854709a214aa98731
+KEY: 9bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc6
+NONCE: 95b814bdf1a87bb1052c6755a7a116bf
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f0
+AD: 6f520c9267cf71408a4172
+CT: be32e45e2b86ca112fdd67aece84c9a4ffe6f773b616aab51eaf3d5d9bee1622f377630d65b496169d5c724e303fcf652fb8275a6b6857768a067a77710ecefdf85666ce3c35d7f0b7394035f220e1d944e823bd2c43c722cd7a9839efcaf23142320d4fee27e0d5e4499e249b3b662f7cb24b48686d533f55707c7f09e70eec383bf1c022bbed0379d0892342914230ac0194fb067959abcb1b7eaacc4783ec10d9ff1ef334ffcebb468008e8f0fac1fe342ef71718731577ae555bf0786d2cbfd2a3c8d7043887a720e514373d248452ad24eb639b35564d5e0638ea4d6a560a4e6073a45d02c0f42087e430cc52d0536587696f694d05a73b8f61056fea619234673ebee12c82eba2a51e0ed0006cc4884a20da9cb4db5bd262513250f48ae4f86bba13fd659db46b38d155532f0c0c54e7a6768c169b9bb420ae0ff504ab632f25759896fe57e32775b65583d6c32941a5294ff47a3c8ffc5ba8
+TAG: a5beed898ccb282d69807358004d87728afbd3aa
+
+# DIGEST: 4becd26b9b5c7bf831523f44cb72c8e50ff8033e
+KEY: 72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1
+NONCE: a87bb1052c6755a7a116bfc9095da49d
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267
+AD: cf71408a41729bacb5877e
+CT: 596949b6d943048a68d9c5e6f6b6b91836c497c3c160337f4b1a3ed44d0db20d00774ee636262481fd61e81d5717feec56bd1b2ab077d205b4c8ac78bf225da9cdf72bc1665330a87a31774e282b676cb1dfb857f32e56806c1d6049594136de222041d5316df307bee6031ee1de0251dbcce0c3fc6f121c0f5cd84579b65055ba71a429acca3938dd0df53647a4a4dcb4321a86bd8f96cca38814937d6262324e1cb76286858cf3c62e9272e1b3473eb7c75a60859142ffe27daf062d0e05b643657a3cc30a0df09c101079547005e22e8cf833e3f0a7c4609e3c80924a2e1e4f61c329b9baf20fcdd8662b6dbd02a4941c3e68247bd00aad3ec3c7d925cce788a05b2518e248d68337e7f9b1c8335fd8f7d0c0ec4454709495fdcf191086d83b71707f97bbb3dcb88a0dc572930ff27c0cd9b93ac1a962e54e726af68a2f1ff4e15cebb06a28c61c5492a08b3bb73f0f7f747968dc6653ace1085c
+TAG: f56fd0172170fe14b89e755f8ae4dd3a89d561ff
+
+# DIGEST: bcf4785d0e3b34c55cb2505b559fdbd525deaac6
+KEY: aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c
+NONCE: 6755a7a116bfc9095da49db3d71f4b97
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41
+AD: 729bacb5877e72cdfcfa76
+CT: 4cef7dd855fcf77232ddf499ce5ea322ab0fc48715fb2dece1c954fafe396791c8dcf4ced2f3ae865f6e062d193509b264858dea3d05a13b62e9c958971040bab31fca1b748e05fca1967a5aaeb0efaa7cb2367149e0c5493d710f2862eaf2030a7ebc2566ed4995879cf27a58beada2a97255f1dc09e2bc102bfc47fca7503f39d04311ee546a01d3854574f389b013425ba1c2142b9a8654fd6bb28be2c4a5f6a923b23867b4c9e00463db4a1c774c101e08c911501853791ed3604eefb2057df9e6a522ad108677ba0929132f86357a91873d46d0d78d1e7278e9fe9e29e6c988b07cfef195953435f5a2004a05f0ada6f75cf6a63297b66a0c1cb574d7c87e99bae61a614e4ed5c50271d9f1e8d3c85393a4d219fdb3bbeb43bddca914eba85e041bce2b7a4b211c628aee1161e93fd13e1320c2e444b15bd7027bb40269e15712e1908f03f52658b85786b3378c4d3bacab39d956576fb8940481b10fff63bea1b1f0cdaf656dd5588b
+TAG: 81a4019ca07ecc27430d947686fe19fa9b5d3272
+
+# DIGEST: 13bff121568d7c32b2546132cb4ad490cea9303d
+KEY: 7c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116
+NONCE: bfc9095da49db3d71f4b975c5d503f47
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb587
+AD: 7e72cdfcfa76aed06707a0
+CT: 1a8d2a54eb61c49085190bfe8dd6c6423c6a6c2b147343f07746cf45c004e7ccd780cf0bf41d7f070590d1b649be4df0e9fe7df3919727f78966bcb5991a92016a9090c7976ea55a0ba039b416e61067ea414d87161ad03592ddee51d40d2bfcf53873c4c92d869af7614ae780814aa4aa12a2967cb8bacbe5d40542e4e8c619435c0daeb3b01c55a3eef62c633df798e2e9d7ae350a9a1e5aed3ddc64039f968cf9d918ec57cebd4a69b195c8bb8082fc8af05e5b577e886b7b258fdd7b60503742eec8f861ca6d8f7cfc5262afb97aed6205765e9d236a790680183fa10d302a92a2ccbf8ca3153882c829c1f70a449748a6e08f302acf9f8cbcafbc2d04fdbcb57b581e04d8c15120aff497aab1e8d3b4b2f30d9156a213c08692c1dc2273e6a9c835a962311e9a8855820600688d10e00861abbd63a43b1a5476d9f00c304e74cb254291c51a8d8967656efcba8b54e53453fff0dcb44fb53317611d2ac8bf15a00315ed24d43f861040
+TAG: 3e7df1268a84c4c1b604e54b410323097fa2dfe7
+
+# DIGEST: e0ec91f0baa3c5fd0c50f135517909e26c204af3
+KEY: 19fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da4
+NONCE: 9db3d71f4b975c5d503f478b22dc8253
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa
+AD: 76aed06707a07c3dab6997
+CT: f76b9306112d329d3300d7961db8e83a93de9a1de25a25505b428e14479e142012e4d140bd327cebc7eb5f45681d863beeee2161e0eda1d55f20429fcfeb104010d3db857a7edd43453f0889d8a54f97eb406cf4d0d57e8e86562c55ed0ed4ca292f77ad1362ac5e154b768926aae31f9e2b7f67cb4d6663fc44aa9249604d01a767b7bd32d2124644b7da4c08a5dfbb17ea57c0b7b757cd2719030371112da299f73159f436e39bd3e18319724ea2b89cb82ac19be902d1df0b0555d5c4a375c2df99585defa395d860be8ce4693220da4bac58584e35f4f46de3de7d8538f11c20f04ccdc9daf42abe19f6a4347308ea00bb764e9f44fffb3bf7f7cb0b8d790301dd47c3d823346a01c68287ca3a4641290c51749ea2d56d87fb6abb533283e7f67684069085c16a9be4b38f7fad01c5f8ecfbd4a2ed75f79f86868bdeb7bd4f964c19984c3d4db3f54c25906ef9f11ca9c2852a4c1279d96e07880be6aa2e1bb5df14a2d8812aacf9ff71
+TAG: 29a4ef26ea7f17cc78c25903cca527d06af831a6
+
+# DIGEST: ee7d6f651db434a281b5cc57c2c418db731c65df
+KEY: 2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b
+NONCE: 975c5d503f478b22dc8253bee6fd1b17
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707
+AD: a07c3dab699719fe882eee
+CT: 76f61331693fb10e859759bfcf1d105cf9609cb381e016502aaadd2db381a27ae8065064ac38f329b79861d6968ee1e1ccc8bff41bd8c38e82c91e813caaf1db5d8cd420d67e58db6a8b6b8b65566f8dd374490d28f0d33ea88bdeaa1fcddb4ce77fd96c72e5e646c5e5291db6a376a87b0f54c5e39b38f26f367807396ea8b11a6fac2546bf5d574a59b48c61b7749778cdeb52acdd54baf61f19802ef03a322501031c40930e9160df61a6946f6782dbe6b917c2138194a111e0501b775db1a66e5c1a5df5c42f58058b9868ec525f8f45403ba27f1f8a8ae9728b2ea140a00c822cf434e41b3105fdd6af4c2162376bda1d3bd5938ff9b486a11ae53c243cd4e97c0f632ea07099c1a23bea9b4571294ab518250a3570c1ca7fa01e11e1e245b15e8c266f9f03142d0d16cfac8dfa4888368082c6ec86e652c8f1afcd32dcc95b3e2cdbca6f19887b124a3c205fee32595bfc933dae224e2df5652c772ab6941a470386e14224b565639abd8a71e85da5d5e89fc0f7b0aa6f1a67
+TAG: 61354c3d7be6e00f6db3c79b69d91cf8bbb13c5f
+
+# DIGEST: 810e1f01bfcf6bc13ebae7861454ac133b2d6cd2
+KEY: 11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f
+NONCE: 478b22dc8253bee6fd1b174c307f01be
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab69
+AD: 9719fe882eee2fee55ed8b
+CT: c76fd203ffada1af37acc360b1d26ab9364882831ee2f6ee68332165d863704db18ef1d5921b8134ba1a9a16d4da0d47670b2f5fde4d1194d8b8a62ba57f7e628cb144d605b7ad561ec0c66e3e7cb8d782723758e0dc2afc57c399d440433eb911b6dc3873adda54e62719c0e345f083e88797321232960c2c406776b371a64bfa82c96a49f07223c3cc8470aab3a7cdabf43c06349f0cac94a61e2503280d869b92ce7f88e281caf490e9edcbfffe7a7528669d5ded607e7b51681b06003ff061bacec4bff3a4c43ac3855142de282584e76eee9d2af0a543c7783fef1af169540e712b5d373823f1c31d1985f3edd2685edbae95b9b095d82ce7d77a79f406e5b44e7784c2d647feba197a9cc44271938ccb5a11e962d188d80d1aed890499f569d14772010ed7078518a196fbf2110bc5bd0397ddaeac981a00865ae4255f60b4660b67a828d855344e5dd0db5df6587cd8f8a60fc652c4626a9bac41bf28f6095ec6953e7d2873ca3ff14c068d25958580513d3a7f34ec7d3ff7
+TAG: d085062ebfd5b6829f69086235eea68eb2195e08
+
+# DIGEST: 881551d50a849b7e81f0cc0d722f631e32a4c97f
+KEY: c695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc82
+NONCE: 53bee6fd1b174c307f01be95abaa9bee
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882e
+AD: ee2fee55ed8b11534c870d
+CT: c5a11b6948d9ac5fb184b7df3ff5260b03d6e6c1cf5830a1bc378de13e91f8bab09c96aefa60948ee51035bd24f3dcc0982a385372b2d30aed79b321717cf50973971483ccdf8121b5117c8930043dd229af9fe9b84fe817cbaeb1fc306fffc61e7e5965ea8367e42f91ebdb969b74300b1329e0b41bd94f6d5c53acfa55d088daeed3777c42d01ec2e53955c428a15e48856d6fa774788b1dd591d45397f89b6718885e02b4635f48078f823d2ce914e122bffc007d894f3a50aa399aef33b8255e4b1f84ea591f1898489516ad6a3f4a62275578fd9aba2203ae079f60743961426c5245ae672d01bf294ccb5ad36da0a0462db05a88aaf16670d03179a6ccf06b5e872d743e57c924d2a2bac38abe0ad23b44ef0a15839c095ab7467a5d10efb16bd183b5766bc51eb9c7ca8ca1e2bb94a1b54f8e80b37b7393bb207d7fd79c01b09943145dc5d603247ea08866f3b8e419e9f04e55f610e0c4491a281af0f15e11a863ee747aec65f65da5ee7b31fdfa8a120ee4d29988e65757
+TAG: 069fa6ca1e062a9163d4fcebea3e7220258682f8
+
+# DIGEST: d525f72dbdbf54db80ddeb9c2a84aca41451353e
+KEY: f1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b
+NONCE: 174c307f01be95abaa9bee5857772305
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed
+AD: 8b11534c870dc695b814bd
+CT: cc02b0c77ad10d25b9c16911516db68583194f48650131ccf55d29c35ec9d2de2b3d3ea2ee9937b6a87212779560b4ad9cd49b84304128329587e5d3abb71402d5eb0411f2704816409b2ca24f9fb3f2a4cb03e9e74ba1345a60bf6577159c8fe82b7747621311eaba3e43bfbc688edb7de11603cfd13ace7ddb6974e3dbd2b20e86e4e35e006ff87c06ea69a6e6b8cf2e02a7ba0210e4d10a474a06ad9d75559c0b9966811f94d5c209eb74e185de3bd1cf4d675de9abe7b2f11b907fbab8c128fd1fbeec0697ce9d2ad66e600068037a6a89ffa19b3c66d146655acf93028693a3bf0c86fb704927a9b10ced07f0b6cbac917f873a2e97cabc8b6e1b428d4ea4453a42d582e42e5586b7ced5c187085b1113ae5aa699b5951c3aff18bc1fa6d4c18e075c53ce657af855c4522a0c3d866bb7b0592ee3e04676b433b5f1097bc1cfd119c3b9f5af2fb69ce8200a8188dd4ef0d880258bb60ff2e9a276e7f1fb89372d835c32cb577fad96731b0891d9a23bfc4fa1bde25e187dc96c5007ee0a1a26c37857e867ec5c207581
+TAG: fdc1cb334fe2cc8adb94874c2566875c90d87ed9
+
+# DIGEST: b25882426b4730205533cfccc0da1de1f6f2c459
+KEY: 2c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01
+NONCE: be95abaa9bee5857772305daa4b550d7
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c87
+AD: 0dc695b814bdf1a87bb105
+CT: 152a8f32525deb44c4fac83d46a32177d6f70edb8b7f5469ed5af0aada4b68d0c95c6e86293e40c25fbdf15570aeb42f3d1f055fd855b3115dabaaa765c5844e9578d8ee9f63c8cb21b181b556b8b687ef856e0cf059adf1d51064b7390eb95b32e2ea25308b4a04921d55240f64a5767fabbe3207dabd28b5f442597e75f3c6a1c6a26f0b44c316b0834f47f8445abf978509fdbf7cc65bcacd655c4eae698e6cc605a811c56a4ce31f38b2d0114bbf32eb591ad08e9f64434fd535bc9b73470879eba47eae13487edf13423b898e00efde2ff3f93576eb6f8e6d9131df10998ceae836310d4000a5905ede4db0c24b15c83d3476944f19eb7a4e6a493583f13486e5cc1604e01c9f6b47d728cb5dcd40d581db1ccc263ceb23375402395898dc26eb6947600a006294e28bcd1a70a2d89c1d1fc5ca5e6e28c16bc26a1fed1d8ec85b0daf7d4a2574c8d6bdcdc9fc4cfc37b79281e1470eae42846b223e303e004afa0d0f811c81f1da124c92c3d123284fd2199b645b6c7a86742d3ed2d5de900590d1b96aa2cc86a542ec
+TAG: 54cc7524500c7997bf02fd492b08c0262e2e95b0
+
+# DIGEST: 939442486c730c2cbd8df213d81310e50534f06c
+KEY: 16bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9b
+NONCE: ee5857772305daa4b550d75f05d80898
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814
+AD: bdf1a87bb1052c6755a7a1
+CT: 4d05fe0669ff88fb0fb4c053661c7fcbb79942de55c9c83648990903dc2af904086a05e683f71263d3f471a5c5f60cfaad78f79acd972c85f25ecf41f033b7fd8ca5fb13f011ef27bcb27bc10ed9f0ca233f533eae78e95f7dee6dafb592c66209bc946b745ff843544182b110540cc33615814a779b92ef8e69394d046d773086a29b3c7d70eb18d580915aff1490681e78efea704f81e2410617d2d92d2c62dfd78d8626b67b1800695bcb979bd6dac36bd4ad12073eeb0a4bce6026d02f92862392e3ef81653b6b28efca81754e99112e66f12593766e9153864fc7d6ffb46c0c95744d3a96ec069c27760ab353db33492f195d49147b6b166f09e7b0799ae329b30b60318ea4adb91fb338fc82bffaf47674b5d6e0847b317290b6ee46b43ffd5548c2c2c36a04971d6490019ec83f174ca095d5a983ddd5877927e5d6cfa62992327afe6e44e072a18a122de78569170e20d36b63f17049cdd01da3fcc50e4915e6b1aafbdeb0e5da30368552ce66a0bdd318deb534eaebb441111579c273338cfd9f55e0479da82b12
+TAG: a047d37ec97cab3d5f09a0dfd19632841cf1eac3
+
+# DIGEST: a7b522c0de411517839342925e8acf703ea12e8c
+KEY: a49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee58577723
+NONCE: 05daa4b550d75f05d8089850fea37112
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1
+AD: 052c6755a7a116bfc9095d
+CT: e0015fea482acfd931875e6af31a81f2dc31103849db0354c7775ddbff6dd3baeab029bd6863b5a3e0bb4b3c5109bdc1d289df63a2b6a577e3c7af1000a16faa2a4acda887f7563ef227a214ec4343840058f94833f9ccda64ebf7e14358bdcf1224aa7e79153d4c128c13e23b5c41e76047e069070e522d62367a3dffe2418e1d2ea71f84f1c032568a8ba19040b1e06d0302fbe1b95298f7f16b75211f4c45d0015e049677874681b309f9115b33812e57ee411c43f8bdff6455368985b2c3b455c762761828e0a952cb2f51500317f95968eb275f52f66c80fcd1d454e2bd2b7c51bfb0e84cd5f8f1d2ee848d6cef1c2b382f73aea027a71dbfae5711a6a6b60d67747115bf138c7e88bbd5eeed3720ae5d9a3cd03a18ac7ad05ba0aa850814060964a6f324181c26257522e7e9db8848f4a26c13eac3f71132d82620d4d7bdd7a6b13edaff628a41a05de3a24ecede59960223e1a296bf1d22e268632f4e1cc4044a7548531efc9c8dd7488fcdafdc3ff6c0d7f664f537471695875f9da4f90a642d0134bb4659c79f97
+TAG: 03ebaf5b98044e677ba5ce1e5155cafb39a4ad6a
+
+# DIGEST: f61096694be30b85b6571dfc8b5bfc4d364bd225
+KEY: 4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550
+NONCE: d75f05d8089850fea3711265bf782610
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7
+AD: a116bfc9095da49db3d71f
+CT: ce8e2a194f41ff1b79391f55bd476fa95060f706df76ef47dabf84b2c8c5c2390e2b6e95d299cfc316f0ba7df1ed7dda7ebcff09fb1928a341361132200bfdc5ff36bf6260980569edfacbed09160c009405b412373e8102709e0107cf4292efc32c6d7991df26bf862e36bac504341916b6b2378bb82500e0f1a323d6e668acef8cd24b609c66225d4745afd2ae547793206d0e76cddcb9dbb22854508d7e16a7419a63a1d6fe6c2eb353dc7802562b83adede2fcfb02ffb63080d4113a0f011659a1c243c3ae834e726f2d4ee202e82d174cd2df26c35e157ff3cefbdcedf98dc438ea8add64cb88cb0ded1c8873673947e5698cfce17c2c20f8570241a855b7ffd0800626e4fa17ef59708b7968676076b42e4816a276dd0a0cf7b7eb0624aa4fa8c2a05e11742bd1a29cb3a4cf3a319f8c66874d2fcc7018bb32fc8e51ef20e410197c3a0173e22bee6307b732be8d610c1ea994895c20f45181b40de55c04bc70e971821d5c852802fec021db47d2d7b8a3f91f8b21b2abb3b7e89e6e181cae3baa1bd5077b749316f78fc44c8c08f6b56fa105e8d5c3d5a52f
+TAG: 4e3a66874f74cdc4f9cf304deb02040eeac9e72f
+
+# DIGEST: acd9a5179a0ec782a63bc824188d838776bc1b81
+KEY: 3f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d808
+NONCE: 9850fea3711265bf782610460bfd24ba
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc909
+AD: 5da49db3d71f4b975c5d50
+CT: 8a610f075d994055451e514414628e2c30d72d5567cfb3d2592ffb1f4a85d553f85563a0352381df79ada451e8d6ffb6939edb73f57919abdbf37da41a3db4bab0406a73c6f61b84581c824d72652c36062130edd4673d0cb22c009fc67dbd9eef0365a67473e2672d522a3753b33ba2ece80974fd9550b667e8c942afd6a22924100b89abf9901053d5568197e9a11c85183f45385c2f3b887d78b04971e091a5d2b20dea01b60e61ef687c708fbeae417c99522e23dcc37ac2a23b785a6bbdfd41937f0e40e5835587c72118ea97f57c539451ba7bafb844b8cf3426ad973d8ddbae7a3eeedc6f5dc77ae6e05a752592e0d2ed0bdd92770952b0c11af898180767ccde0081dcf8ff748c02206ede73dc32bbef560e507962808fe7e6f3c130460d975757b6dfd2449fed5838bf4e3140bdc83688b156c22cb32f1b41aae2e53c66c06b81e85fa17b45763507f3fc9dafe4f0d8b2d71d4b4e645ac5047162988e3bb342142112294155dc646646c4bd9bbcae5238b0d8ab782fd7e4ffb383a4fc48523b8d28258d3b42e5e02ff3120d025e5b90978a7c839811873d
+TAG: 4b04e948b26a3acc920035433831086563526a6d
+
+# DIGEST: 152118d780c866c5eed3a08d2d9960cdc5acaabf
+KEY: 8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea371
+NONCE: 1265bf782610460bfd24ba022e6da12d
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d7
+AD: 1f4b975c5d503f478b22dc
+CT: 6ee0912f8730e5e8fe419530addabe3c51e95d2261b032755287969f8834e473226e4e9113c586759fb812908a64c3ee020f4d15010b903b4c5e721cfb208eebb3e58707914f9048b9d89d53dd80d53dad740394a943db83bff6d27980ec681c7b9ffa80bc6464c71c0c807a7c8e445fd94edf77270e79080cd597ea69dc69617b9edf3d088785a47fe0b67188a2a058205a166e3bf8f61246509adc0d1d833f1a96f09970aced95a110946e68cb56ac439a2a850f97be36fbb4857c470f431ee6be051c9eb7148261e52889a789b14ac5d6009d925674ac8f22b46edd8786ba24ef920aa599efddf948a62496dcee2d453697e320610bbb3cfa7e657cab4548b92d0f40c7c927761fd6ab1cd50b9bd941768e7147515dfb3ed5a7e34440a75a6f9119e7bd0cc411ba3181adf38252230b73823daefa3295b71e2e967ecaf7916c1049f3235fc0249ffd7ce42563c910756eaded217d56e188738792f03938901caa6b23a5b1261033fad3e9743ded57121945f2f1086e567de844ff71f88920ff3925bc28055f4e9fb3b6eff0adb7d94c3e45c2842b4cdc6168a6c9
+TAG: db0a3a86abd5bfd20bd9cc96063d04791e407c80
+
+# DIGEST: ca91b15125e07b81debf75ff84e7eed4da5808a0
+KEY: 1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf7826
+NONCE: 10460bfd24ba022e6da12dd4c27f4372
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d
+AD: 503f478b22dc8253bee6fd
+CT: f39aee42285906c6ac413a75c9c35aa8990cfcc1404672886cf6b2c26013396c95213823f09d2f5ac5ee06b500caa7abc0bf72d1f00ab37a12daee95a9a867e570d6659dce22f8b4bf6e98964349cd96ad2c2adc7261c00732729d4e4fb1b70ca745ed300a8b75622296bd4fe6b2ffe5428b42bb1f5ad709a868a5fa4571a6dc6ad44c3cbf292c961bd18dc23d0aff520a344f3c964bdbd07add2af0bca8355a3f71e4a11779b8f0ee7c9ba514ba10a7663ff30c347f96902f86d77deebf0cc8b384382e509b2114c0fa9931c3c28d737a7f46945cf9609c7cd4143f0c62e5510aa5cbfea578a5e8f6fa2e4235b13ee4cf2c90666ba7225b042ed15b84124d53b14395574960586810e2cb6b03d65817fe6ccfcfdb98b35e94b0fa076783b60296f6bad6ba20e12dc508e1f6ea9e4fc9a50e233650d997ffb17792fd8803c7515955da482e62e18051311fcac5b6915d814ec2182593ef4b7a6f7d4cc3b8b65470a7f16180d54164ab0bbdced684dcc5f7a1f061e755d801364097d052234430062640edfd0a122e20877d551be7a92128c1ece727fdc237d37af2ce223e5d9ab881694f96395be0c06430ab
+TAG: 88f233b90e833d3fceeccb3b8371b62868e99647
+
+# DIGEST: 93d06638fe1e836ecdf5d30db3e4fd0660d9d701
+KEY: 01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24
+NONCE: ba022e6da12dd4c27f43724809744548
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22
+AD: dc8253bee6fd1b174c307f
+CT: 8693a4385e2082f13e0a89dec1e8df98242e30d84d9b0a1fe5905201846bbf34ba9e04afd3fc9ff4ada361cbae026a0862f7bdbfbca6c895ef0977852fc79821942bfeb89e8a51a46e99726ccd7d2477b683cbd9350fb9ea0378a543b70699df0bd9f1d29262dc6a9a116d8eb62f3fa7237f0e098e713ecea3af72d9daa702cd961de566f2ddf91de0e5a5d1bbfc0fb508b6b81c27190f4f1f05a8554ec96dd63cb2adbb10fb7e6662422130ebbe7fe36cd53bfd9cc7e21d1777c9347c79834f46406e409472fb747d20ad0ea516bdafa838adfa031e0d10415a55da4a46102cb72338922724554c5f5a632ef40827337695295c3bafebc537fa88d1f648d5c459bfa24e4956bab52084f8c0cfed8db6ed3d4dfe8f21268d5aea323d16f10ed304ba909d816ff848c1bf643f0b3926e23a39ee79acea462d7ceb91786536814213be4eb44e85d540af000069ff0c7b533d7f614093ec4b327555e1e3f311fd38138fb47c509341142578dc69b03161f9beed51708f7c7e14314f48a8f10a958179b189d27ecd1c9d80aca2d5c87d68f3b785a070e6922fc7b332bb9574c515d0e940c01a8ee8037916b472d5
+TAG: 67f5ab24e993e303144cfb49b62486bcff710dd0
+
+# DIGEST: a12c8aa71387379d0e43afa0321979e018d56547
+KEY: 9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da1
+NONCE: 2dd4c27f4372480974454879c41de9ac
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6
+AD: fd1b174c307f01be95abaa
+CT: 0895c823437435ba580b89e28d667821b5bfad60bd76bca45bf922c31cc889f51abdf9b47aea2b4f2c5459f38e8e5e35d0ac624bef8dd3a96a06f3491ae629a05d15df535e1f2f1dbddd22fde0ff631fc298fd4f79a67879f4367f4e5a372df8b881b32d88057357ca1b5fbcbc7efdcef7e143d4e1ca35fda0bc19fc6da65f08fea0a381c4e93d5cc7c7198959cfead892f8a167631326da0905bd348faf7b7df25b621d7b7988a7b062ca6ff4c7ce931a901f2d509aa42e9bce1f20e68024b991520c43ee2d8689ed7e1a4f14f53b05566dcb9487787243f11beb5dda2c78b145b47fd4c13d6589d42c7e504c55d73f1bdbe5fb4a500a57001373fe772c2211dcac1eed0004634ab851f2e58b0234e1aa6d0d50c45695fa8cf24b1b35f2ede35406927e8101395910e865a3c44d81076bb246c15715bf21e3bc8a0f1ba0221755a17d5e4d72aab1a227818a7009fc4d4695a69a28a328c60903595236de7470a7af21bb0748ab7936f29cc5b0198d222c69800e0229e041fad4393bc16f28025403f209e0d266271f232ffdf89808715d51128514ec1936c7c924d58fd7521597fa44126d12b11d4a54fba9
+TAG: cce3639ceb31a80a5ae5ec4ea7160421c604a532
+
+# DIGEST: 8a524c3ce814e3059b4c7a6ac748783ce1385c68
+KEY: 2305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f43
+NONCE: 72480974454879c41de9ac9f98233b5a
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c30
+AD: 7f01be95abaa9bee585777
+CT: eab2468c2d5343dfcb43ff97e68caf92f032066f92d1f918ab524c3c89deefe814444bb6c24dec9dc20d59a401443905c653bf42ab7a67d041bffbc6940b5fe55afa5e15e748e779f6023b797b2b1cd929277bf6b8a415f93566fde4a773e4828aa0704caf46321d48332da01c7cb8b6b295ea13d9a9855a9c9499b5ba38370b6bfa982e3538302fa4ebfad9cd5324fed77c8e70437818ae275b68fc029d2caabaddce7dc50df388fa986a985e2df6d0450c9a00e16005734c7966fb7bbd7312957da2263fbd88a2016134aa45ece2ac93b47151acb0e38ec653ab23cd6003104c2ad254ec98f64a7a27a0d7c58f35e548ab6a291ee927190e7812c7a71a71d765943fe4fe9cc22a987917a4c35d28e25c8d2e0354f17a0ded0e61dc6609e8ddafc512306e71d0e8bf2cb3a04221b6d1721da96836e8f155ee0c3461a1d58403f8fe7ef13e5babcf9fd9d33c59a1aae25b082fce0f3c5299df0b83714ae9196dd809b750e9832702207fdcefc011f4107cf8424aa29552d3307d0e4c14db84751c086275400b5d3fe6eca4f5499de1290d34894c45187e2dc33086ff93feb97081d300931323297a8f1b93b41d973c165d9a8c85f4ab226939b775c4
+TAG: 8cc1565fd1cd6117c864bc0a9b7ec5369e66cf35
+
+# DIGEST: c31dae836928083019ab6902865d9f14c88fe27b
+KEY: 50d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f437248097445
+NONCE: 4879c41de9ac9f98233b5a7379a56179
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95ab
+AD: aa9bee5857772305daa4b5
+CT: b2a0474f96d94bf836f29da058d80da84d60b11126b3a9f8f6975def0fd2b2ea22f1c3ebfe8b9421155c364d38f24ef5e4e4440edd34113008e29179fd6637d6a0b2cb3b6d50a7cc3c4fecf56166b5a4a59eda1fee7ced7541e203fa9e07b2d43e136ffa3ef17eb0a59c9d333f38a4e7da8c5416f537c56cb30ea671674a7af92d966ba6d2d320c04791514815bcb6da500b469527b0eb66e825d81bebae70c376493846c41ae85c94318750a499f30f02e18eb4a722c47e80c08cc7b5f28bd7e9fc7ce71c38feb46aba20539716bd224d26e482b352fa1bc54a987d990b330f55c3eff7364247cc1d4b73dfab96fb8fe21a6f61a7de4bcd27806915bfe89e6708e2c00249bb847cde5056a468f94d6383a0ccab628ab96ef47b5a7b5e645f35af3159318bd913368bf276bd15a6c0981462ab7bbdc39246c98699c8b8369781277a58bc2a322f31077dc71a2feabfd900fb5ff851d07a2dd4b72a26c8e2a1a9787b83c13c4eebf0168828dab4636e7f419b72e7fdf482a9821d7785e18d110a5555aabea1762be06ed15a3ec1a42480bfe53cdf03eb1ec0fa75e5b2aaabe7a63beefcc4d059c4402952c97a8857b89542c84f525a996312ec2a0781
+TAG: 2cadb094771cf21fcea2209be5a6a6bdd550ec61
+
+# DIGEST: 4b2db052fc8a09f7a0c26afc66dbcd8ae5c9bf62
+KEY: 089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9
+NONCE: ac9f98233b5a7379a561792c0f311643
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857
+AD: 772305daa4b550d75f05d8
+CT: b5791488db7390a80622777e45f78e9154bb13e4da959bbfb824460bbda64f776864b921d07968201bbd570a5fce10d6c10777bd237130821c0df9a0248b604b9f814429a2c435b3154a2f05cb237a271a2f949c9e82f8d110524a48531cfdedf07fcc08c88d3a90c6852c0d91fb4c847dc6c69fdc4ce1c684763892b09159de9ae8b57720da5a949c7e46b5e34739820fac62d472dc50a3ccde3c64fd47d398c07372b0a37ddb026dbd8c27d698716f12aeecb4b1dd3ef3411ee6b71d519caf74cccd225c2d445c469503611efb27e3bf9f27d74fa796a07c8acbb8f6d8d567c51891a0daefa7b7e948d3292ff927825a08769492ed47e2f0f54dc2cde68486019e7ee93cdcc39305dfb388156ca44d1e22a16083168ff74a647424afb0c8ae7e589a68bf372b49ea9aaf0e58690cfbf8d014c3682588a1eac2ca6663138b35c7a76b7c099a2e4ea0ee4965ea3ee375ec279ccdff3d38a342b0130f2c962fe3b0b54185fa7dfcc59a783913557afd00f5f9ed55c3958eb5d1899ae70f3057e05662881f369d9816b2e86c8cc6c40dd6537335728443e2cbbce66ab22e86335c7800b170cef707364a93472c035542489ea8681d3647d2d6dba0df4e
+TAG: abb18212526497bad9f0f8f25ec9c1976f82bfc1
+
+# DIGEST: 881926d37fae9095362fff56efadd9fa3c455ebd
+KEY: 711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b
+NONCE: 5a7379a561792c0f3116430e8b6ea058
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4
+AD: b550d75f05d8089850fea3
+CT: 33e5dbddc7a3d14f78529c8b97fcff71b6d4e93354361f17bf9243c5cb1fe26577d8b2dfb5205f72def5923198e294294a612bc2064380fd2e7367a84afc10b7db41a12d38754205937444a08dc11bbde5565a8e103eb305f85540405966d6f3760096c0b54bce8414dc539c91da221943ce0327516a5e8f4aedc7997a64a7bad0f315dfe9b8472f934c67efd104eacb2c3ed3c1efd8949d66033e297cc655732b781399f215463a8c053ba05b65680166d7d5791b39e4e88c82a982bfd85061bdcfd4b52864a0e9efba5451b5aaa9a1bb3d59f2cf9214c994afdd87c2ae389d095e380bc33d66f802f635595da58e2ce0e1fed44032c940e6c1ead3c1b33d820cd8a754b8592a2f16ccf7751a82c36da56b5e6b5ba588d33068ce3e7f4e9de1fc87612b55c44b61fbcf6507e660e3ae5f56fc3cd751f505a854636cb87067ced759c1136325b58cad2a2558565cc7aa006c9dd88155003d5dc1922177bb61142da62844956fd9d4b60fbac403d5a92b122e8f63ff4ce6fae70fd824322d8607fa59c6b0b2134d8165214d41deba7d28f99e7fb19e75c4358cade4b5d478aaefd957cb8698598857f65c382148add2d90c6cbe34c1f330f611b7e8b265f936b75a9e3c18e6fbf320eb09bbfe
+TAG: b26cc01704e704e1f22c60cd5bc5ef1b4256f89a
+
+# DIGEST: 92d143942e6ef5b44ad7a4b8e71c22f1ecaafffb
+KEY: 2610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561
+NONCE: 792c0f3116430e8b6ea058c4799eea80
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05
+AD: d8089850fea3711265bf78
+CT: 93314bd06e0f9511f8577aed88d71c6990fdfe4ea3564450cdec06392e1759dd356827fdf82ebe96ecad77f2da1ef961e601d93237ff515e46b00dbe0b0329e17bcd2a386ad9942f678f5f2942b73a39e5a7de74fb6f22911c697babac2b3a29ae9534dcf2a262227066574bf830850d0993baced9a839c80159d7d91724665e06e22268106e9eb4c99ffc7b2529be6ce06308e064e69cb712a473b25e6f84f6ed1fc72075245ed6db6fc64eb5da492fb8fa4b15dd4424dd2858e1d201044dd147b08adb4a76b63c3fe2f4c0ee49dbf0ebb1b7651be3f28edb38418b162fa0f8dddab8557e55e32b63e2e8fd401d3dcf0454ddf995a77980dd131fc48f1299a246680983d4667eb1429e55779da5c8c0e34fcd79024894577d24886a1efecc6ffc1daa6ca1c9ad7c7bb4b707f8cfd767085496145b2f65b6e755359150da8f2d5c751dede44dd061fe40ad76a5dcb509b593779cb6c8536490079394536a25442aa1a12a0d9b75d5cecafb9ebca23eed3489ab975b9442ce706511037271bd022d4bb69d75ad93683764d40b0135c85740348ad6142e5ec18888304375cb25be53d0b86bf2782c8e626b7b20b2cb2907334e95037f298271e6cb3456fc322c384d94789413ce734326aa07cf
+TAG: 608624f01bf72a6f7817b28198605cf6b6378e6d
+
+# DIGEST: 7fcec4927096421498e91df912cfe43b2e971d4a
+KEY: 24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116
+NONCE: 430e8b6ea058c4799eea80abde04ee1d
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fe
+AD: a3711265bf782610460bfd
+CT: ef33a63fb8fc5b6a4424fa6644ee0c833a6db43d65f67729378d77ab88f73416f6a63c2419bb6ffdd2378fd5280aa0bc6fd34bfaf7687f9697d0038a0e509c5826daea0c2a3dc41352f437cfdbba7012a470f42878fb127794b49476cc5f9d5f1ee34299e155d394947b2e277eb9c22b1eda29a2c538a174b7dcbe55a8af0614bd54e5ecb54d59f6393b30300354f9d1655c49d2ace998a02211e242088115421ae2c89e2fc91f5c3e63a78c24cf3f228e421d8148131efbb83df5350bcb54aa4f543c8789a12c08f2bf1dcbcfc1d4bdf2ae48a657b9ad7deaf4f82adedc92ab630a649da8416d9a1f4e4788fca2f8abd79b8e3119cf5a8157589f8cb59c9b1e0b53af9ffb6ddc69de771ece7a22d2536d3df661fa94a278276a0829cbc08c8ac613b0aae3f1396d4bcae75ba0481015f389313084e0fa7e3c51421f85bfc2335e98810813cc474a3c7954e3f9bf740ad4cb0bd7cb77363fabd3f7f2464058a3bd72c864c9e58b23108d9ef91f633ba7d5dbfd397a9a9034cff23f88b5c014b83641166948bc1769d3ce1fdc196c385867f398c06ed5d1887411fee29079b1e7b4256002ea34003ef00fae7cf24353d72385f5070d0f7306cb4efe1934571f46fa4ed0c1d00d946fc6e19a4f
+TAG: faf8a22622036eb3548c75b2c4616d216e9ed282
+
+# DIGEST: c1c6273ce723df9f2033c7150d466c011bb457da
+KEY: a12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea0
+NONCE: 58c4799eea80abde04ee1de13e937af8
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf
+AD: 782610460bfd24ba022e6d
+CT: 8308b83db00f58f91f79a25ff76d277e13cac5a76e00c65a8a4b6ba7c2a189ea487f023c456f5d7e456a7a5ba18fe7af240b71a82898b640269c1402866f4fd25cc41ffd9f883b1c81fc4255c3425fddda7367a9a1ac231e8a5f694b41a7d22cf9312d2372dbc6d4e50d26a902fb2764ae1da84acf5f488fd29364b52ab6c5d4945268d5746a2f06406a9fc8eaff98dd509fb421a76b1231b5703f366127352d516f5416634b7905728c45dc3ee68bec892fb58d6cf713f33f7b09e44c7ae4b8954c6c7ac7cb156e57612d5f153b22fe0b6a8e1733e122d48698adee8705d8d3258f266facfda74c6dabedc2a4c31ddc59c08d367d929479c526a6effcaee8576b3d4d9fbc0b008a8c4192d6363b6f0a9b79e21f91d2e65d9817fe193ae62e1c81cb84de7b09203f07e0af073a9324ee4ea580b125a8e380a04ea48051d7cfaaf67145cb93d7a3a2985f723909552b9870f5144b5961f0ce965058ea3e27d9a79a5dcf75027ad15b17a3fa6e18259d134eaacd1d601bb75ab05e50b27c97c81b037e05ef5a1c83a74d08d853d4aecb7c8fb29ce49f1ede3cf5d9e1fc95402601f560b28f55fae01644a68b664f1c1cbcd1851707cdb3b191fab5e0899b75c4d5d3f1511b7d7ed09adc946900dfec7c40918a7fa5043fff860e582301
+TAG: fa6eee459cc5f7e681c7746c9fdbd86a475f3abc
+
+# DIGEST: 11424a64d5ce78fd71b30a8070aea071d873afea
+KEY: 4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea
+NONCE: 80abde04ee1de13e937af8f1a6944f44
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460b
+AD: fd24ba022e6da12dd4c27f
+CT: 9dc9d73836a8b568e40e805a7508f7259ece28a4f4b83f1994ca9078d14b785091226ade8921562912fc16ddaceb1958eb92e6688f5eeae81285508168680e648a42908309be71c92dbd21d23d6e80ad62d6cf3fea415e7f46892e01e4b3eda4bc3e17acb7e65fa1d003ea9b6791f9923411680ae6e1d012c3b383e46ab698f0d572523d8ab87ed28ffc00b5c7a2d1ff6055509c3c2d67c0576289b65e73fb47dfa48b56f9b5b42f934e32123f09072f0e409d2a98e7f78901a02b7e1713c72e125e69dbc15c99b27510a89645871cc07257827e3058168990e4866e16afbf5de7547f3f6f3de7c497616e8212a11440ddf641c8de62e0a96b4220edd22b475a175a73cb7e8d9f66633e23c53e7e78c33fe54dcc9fb20fa6400400fe893cd770f668b6e763db9dd8881f0206a8f2769f1d53224a60c15b65210a12de00d159820e8dac8df1ac34388137508743c18390bd625c848916639f035df39daeb48ff13890ec8dc3f8b0dc64c57ca6e0f6b397e5c7d8aec2b5853ecf3dfeb5468589a92d7c1050fc07d3787e3c367249716c514fa63ebb6788d6875d2167c396109ae7ec6ff4684ee7f7b6f5c2e9688bc23676d3d0e6d11da1aa2c977d7741242381de004c320259a6e7a6cc7ad22cc44bcb27bdc41f70e4bfc77ff9f73b2f
+TAG: a6ca7e5060ecf484c8cfa6d75edf76d37375443b
+
+# DIGEST: 6b7295febce7fba8d79d1e7ab8fdfc452191e2ba
+KEY: 454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee
+NONCE: 1de13e937af8f1a6944f44d722271233
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e
+AD: 6da12dd4c27f4372480974
+CT: 02972895ffc3e4cf8325f5ca5b26ee8a4301df3c45fc2f43412b827ff9e8314c70dff0ffd3c1dbdffac98a4407e9179557f8df243b0d07f1b672aba943ee38eb677f20985dd542164dadecee488f0657ca790f54d26741a1fe6f246d04c46781f0ebc0122e1c33a35c73065757e98177694d736db9388b4cf48850ecc62cfca7dc94184ef8efb0b1ad9987d76d571f2a1a36981aa1baa978f7b91a65c6c25d006d8a3df86e2727903404922f480dab3a5d5996b07422f3b1a2da3192f41fc34cbebec64144d4db00757f62fd0eccd592bdcb7d9cba618797b1063a6398f4e4cd8886ecb2edd1d75fc011f37cf9a0c4ebe401efdb64cd2d7807766fd40e3b3d0aecfa0d49d6747a409ac2036f3ad6f0dad8e6dcccdf7dec4048ecbb0fb7882dfe603e66a5d7973b29b956d1332f040ed405d97193053e52732aa677994a02cf10e3d4081e6bd1ebb1f3d3b95125aac94fa6637797f6db5674c1d588a30ab4739f8738a299ef60fc5eff5c7e7244eacee4dbe9a66ba60c85567c64c86a7bb11e211d2f30bb45f037f7bfc95f0bf9a87a65de21a04f1955f887c04029bfb0ce689f6a46e84c5f8076dd9806c3035810f674b417379ecd5b4372698f7b2dfb61a30dca69555e49d6f6ec3f44e7dfd6ca533b6dc2341aa63b9a1e1d8f8f11
+TAG: 83ced733218bf5c9dcf17b3adb519cfc8771b1b9
+
+# DIGEST: 1dadffba439570155af2509a548764a93042d23a
+KEY: e9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937a
+NONCE: f8f1a6944f44d722271233a825264e97
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c2
+AD: 7f4372480974454879c41d
+CT: 0f3f2b8e85620a4829deb7ce60af43acc0da265bbe6c61939a327ce4a93212cc525edb28a369d54f8e116d81f136d555be33ebfb87eded221fec99f4a38b4fa3ccf58e15e46cd8ab535cc6f62af5d3f38cda649dcc3051a038406430e2b2c088e4b6c5812237d1ac113b0a47364db16632390253b3aa6f3d90f155ba771251ea35a52df0a0969d4f182699aeed419f631c0a22a48959bffa701569743177867e0b9cca18e243d77452f311ccce9c63211d6121a8f97aacebed9784accffb8e6e173141b3dc512a3414bc3a652cd8f0e2faf8fac59e3eca6e613d8466c27c21ffd772c6b18b4c19edcec6f4fdf2005050ccb466737a9ac629229b42effb9019d370af0f7944f7d2f5ba8505db265b373e051376bbcca7f9ee6ccad1f5651b24a516b213d6e90e6b01fde4d673972084d90f44c6002f65dc5acb49ec625ebd1ddf8b9884bfbc6e012ed0214c14af86717d61514927440fad1c1bcdab86b57bb93dd922f51f557e32b6501d99a0a4fc810f0cbb74a4fbdcabd9bdae42214f3a690d5e343498a022acc34cf12c0bee4ac19c193b7537b0400a26940a5bfbc5e1fc3a4b7591adfa9bbd5072cfc6b77e132da8aaf41d9a71b2e5da61c0b26a6eafe2e9245d98540d24286f7478c73b28c351fbefedb46c7a2dba1a07d005bc
+TAG: 3abfebfdc7b862b965ef5919df45ac6578d775ad
+
+# DIGEST: e654b4c78e1c0061eea2996fc126c9bfd41eb6d9
+KEY: 3b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f
+NONCE: 44d722271233a825264e977045318c9b
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f43724809
+AD: 74454879c41de9ac9f9823
+CT: 04183b22cc3b9d14e40a7ea1b69be68bb2347bfef9ff9a1ddef915f42255b89d5f0cfee79eb0594d56a20fc9a1cdd263deb0242f169eabcdeeffbb64a00d8df58c058794d36cae1ed22a078baa51d10bcc28ae25990a29f400cdc725b479ba7c67f2b7da61fc25d3f063e72130eebe852fe696152c221dfec1056d5c67bcb7e38d9eb45693aede0b0047ef7b064ff1fcd0f4573fc70194a22582054f76ceb2792e2606d07099af20f76535aea63446200c49bdd188e26f784192d131f2494238b610f6f600d89f69b54c1e72c1167b9f41065888b9410c6ca631e9f0b82a72dbc02cb94b0e8aac9cb673a2ea93d53b0f382959c0df460eb00d947ce1cd6c41991f52420046314204318e364d5f8bd6d3d265cde880aff7cc16342a24f2204ec33fa00f3b7ea3ff74c6bde45a3224764bca6f8998529dc59b9a50c1db15263bdb8285f4a4360c1decdc7f2613036bd059705aa5bd651167cec76a3aed48ed5eadec9d558f87865bd1e95da7894792d84a7be856c7892ce585daa6cdc498ecc9ba39f6504144bfeeb4e098087858d008ba23a295a11a3eb13b38c9d86758fb62f133c69973a61a904844352365f007e229fb3c1450e74d5961457b5719268b4a23663de7680115e84b0dc6b118537fc0d9904eda1d9034db6794c51d798c579b344702f446158e33bc30825d98
+TAG: 8a3ed847cb93cd89e4412a8ca0e83fdd53406897
+
+# DIGEST: 654b8591c7f0506261713e9ce7a6fd24a6b9357e
+KEY: 61792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d7222712
+NONCE: 33a825264e977045318c9b66262c0f03
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c4
+AD: 1de9ac9f98233b5a7379a5
+CT: 81f1e6124dcc3ad1c6aff527c8d9be440b276cb9a78af0eb13c2656ad2c53aaa06b0bffb486100fcbe2ddd944826d6a4d0c749e4a4e646aa404b1a5c4bdf2c37c4ea58d5ceb59aa212e93adc34374a10fa1e5c0e6d1c927e4abe18f00f7caeaac7fd49fae791e04c725d2804aa73fc3bbeb636dcba401ec7f07781ea5103e4802fe94208ef07b78e7a04ea1340f135736a69da887f2886743787cbe6e4c036d04843bf617def845b2d287acc741a707eadc2bbd811ca7987a09bf3b883655de05b07783454e53d55ce7a604e4c5934f846dab6e8b9677e5de5376d38d8c4d0cb3b4dffb9cd423ee61beb74b622d2672dfa22bcca5b0e72806ae48d83a4d683a644f5049199f004256e903bf6a4a24997ecbea4d9feb8048400cd583f3ec860165acda29ec81e3cb8c735328ba0c2ee9a972d9367d5c09c029a003c0cfd0617b1659f5ec9aecd37a3307bff5a19d08d7df6061e5f5d442e76fd3aab4a249802a6e445b53276166bbc358648c0c46f56e85c717b7fd73d5ca7dd6e58ddc9dbe22698c54b9bb02a245629c761a0735db0813ea97d6d13a9e72531f69b0ed623a156dc99786cbc6099a8e11b2fbed401a8a2fcccd6235584176bbaaee17261a66457c714b12890dffd152482a72abfd70fff4fce8903712567a1022b3d4488a3f2beafd9cf574bb5cf6348163210
+TAG: be611c95e090cbde73fe628076bd1e5eed337f18
+
+# DIGEST: 1eaad32c8d0cefaa5e2c503bb2185a73e6387fac
+KEY: 16430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e
+NONCE: 977045318c9b66262c0f0368fe9d0cb7
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98
+AD: 233b5a7379a561792c0f31
+CT: 1bb52d1264ea749417b516884fa9a25fbccd4a07103bc00213614c9a61700c8fe401c438c3be664bec96b81b6b68b808e76d1af01bbef8cf65488abec789e973364be139800ebcc4c3e117271162c249ccbbbb8f6a1fefa4b7e578b8b344519364082f4afecdb3a1fcc267fb1e0b77d42b574cabf7bb3a339bf4b6f90c652b844fe78e3f3e927252cf33b68720caff6146d046211547682ba9c13a8a88438b920598c3a687cd6b67a96c589b4b827e09d644cd188e78d40a793aa0121a6c8e16ff9f86821388a995b17ec16c5d2ea2e28bf549ebc7218096f420946e296fa620d9a9241aca33674013550a054e6b7c543c5828ef38ae8457b5e9a4a2a52f1fee6004f62bb5018aa6f7853e4e5112c34b93fe12e347125c1c3a2b5e007d5a9e026ab13c196636feebcd0470a9864d50c71b4e29e6d71b678c7223f5ea34d52b17b2bfba5f31d228a203dcc1be74d2baaa6c718df27a8d1938a6a0552a305870cd6607118fd525877189d9deed6f1bd14079a19fca57d98cc2db5b792dd6431564e625f00622e384935085a0e012424d11ad122b9fee40ab5c5ada1f12f9500192d07e16ebf31e4d7ccfc983cad113c547fba55716f7c92f9f633beacf853ef53dfc3c8f8eefa2ea767cf9b338666781080e1692413909c95e492d801673bbc5cf9ef941c68981835e91b61389
+TAG: fe1b9dc1f8202b7fe5f12f6db61746a2264d5c52
+
+# DIGEST: 862c0517b3658e9b9cd27db608d49e24e9b4667d
+KEY: a058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c
+NONCE: 9b66262c0f0368fe9d0cb746bbd55813
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379
+AD: a561792c0f3116430e8b6e
+CT: 1a969ac3a7a86368c76919cc844ae3f26eb0698717b84b8ada3fbc1615b8cfe2c3e845f9b37f145ad495531c9340bedf965ce24194abf9986c2d6a5e0b7a62f984a276e47b1f51ea1ec45497972cbe00e8699c623c2f4009cdb3b32f8b9ba235512785c0f8dc46590ddbb05bd630febe7d0e6cc2f96f143c66aaae1d5d0c3bcfcc148f43e999ffce6d49dd4bcfa2b095c883659d4cf7f0940dcb1ec38807283621516d0f1b375e0266eaf3853e0bc74aa6767da3961b65792ea4e58644488fa9995ca60f89a1c533547fd764b9cc5ffca134725754be270768848e4ba0ae54d5363a5f66fa71a52107625c9eb3fface5ab5710f87b4b516415b4de3e3b59c56d2f33c6a9aa295b909da9b0d19956b790a4f082607fc59d2225651a6767471bc513b81a3c0218d134d38ec301d3fd8065cd3cd9c2fded778eff193ea0b7bcbd2ad856a931404501da9eb7226014c28371862a9eecdcc58ed8ef86da91f8e58f49c7f99377387b9676f5ae9f05eb0212e6b7bd706653f3f70abbb8ae26fc4f994821b986e866bfe64881418374886ef549cd17c883b3f1386ce4494ed85467d48f827fc28daa252829bec2a36e6c241456ebb45fb264ea29e1a3e379f1b3dc746c0d012ebc9e38a54429fdb6008fcf2ab518260ddec20a4b8db972e8e0e0e2781429513062d7b9756e277529750f90988e85f86a65c047f1867e8d942c
+TAG: 6e4a1975a52c59682e79407f73a9d493fa97b0b0
+
diff --git a/src/crypto/cipher/test/aes_128_cbc_sha256_tls_tests.txt b/src/crypto/cipher/test/aes_128_cbc_sha256_tls_tests.txt
new file mode 100644
index 0000000..c6419fa
--- /dev/null
+++ b/src/crypto/cipher/test/aes_128_cbc_sha256_tls_tests.txt
@@ -0,0 +1,840 @@
+# Generated by
+# go run make_legacy_aead_tests.go -cipher aes128 -mac sha256
+#
+# Note: aead_test's input format splits the ciphertext and tag positions of the sealed
+# input. But these legacy AEADs are MAC-then-encrypt and may include padding, so this
+# split isn't meaningful. The unencrypted MAC is included in the 'DIGEST' tag above
+# each test case.
+
+# Test with non-minimal padding.
+# DIGEST: 9c95dd31953799bae5073105f0694f1a0e48afce9277fe009ff26b28ca9ce072
+KEY: 86d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba
+NONCE: 2fd6773e0d0c302a5f47e037446f5891
+IN: 936a91d0b5
+AD: d2c0267218cb7090c61713
+CT: d25f286de17a05e3727d1399c895b02464357998b11b7f98525ac704f9cd130a
+TAG: ced325c6691591a3f137a8cf4d6332b007edc59c516e3641b9c0e02fe218521e
+NO_SEAL: 01
+
+# Test with bad padding values.
+# DIGEST: 9c95dd31953799bae5073105f0694f1a0e48afce9277fe009ff26b28ca9ce072
+KEY: 86d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba
+NONCE: 2fd6773e0d0c302a5f47e037446f5891
+IN: 936a91d0b5
+AD: d2c0267218cb7090c61713
+CT: d25f286de17a05e3727d1399c895b024
+TAG: 64357998b11b7f98525ac704f9cd130a810efebe69fd479ccc46f0cd15a2ba47
+NO_SEAL: 01
+FAILS: 01
+
+# Test with no padding.
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271
+TAG: 713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: f1402641d69b3d67d63e5bd137ba006c70582fc0ac760c7cc005f22b69aead4b
+KEY: 7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b
+NONCE: 8ed1c8e9ba2fd6773e0d0c302a5f47e0
+IN:
+AD: 936a91d0b5d2c0267218cb
+CT: e9b4584cc1b8a6142b2b8bb0cf850ee7
+TAG: 3311934d01bcf0c9573076e070282e4db9c117eaa597452536b7c30ef66445c8
+
+# DIGEST: 9c95dd31953799bae5073105f0694f1a0e48afce9277fe009ff26b28ca9ce072
+KEY: 86d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba
+NONCE: 2fd6773e0d0c302a5f47e037446f5891
+IN: 936a91d0b5
+AD: d2c0267218cb7090c61713
+CT: d25f286de17a05e3727d1399c895b024
+TAG: 64357998b11b7f98525ac704f9cd130ad014a582418fb07fa2cd6c2825693bd1
+
+# DIGEST: d5014c1cef6e20aa0f2346723fecc3c089ed5a38a61721469ad6f2c738845737
+KEY: 97b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d
+NONCE: 0c302a5f47e037446f5891d77df660ed
+IN: 936a91d0b5d2c0267218
+AD: cb7090c6171386d641b877
+CT: 703e2478ac53047f51c8299103fcfc7d
+TAG: 4782d02da5ac5f122def2935098403dc2bf2f4d32ea88c0568be0ae1d5f70f44
+
+# DIGEST: 846ce86aae8dd9b29bfb827aa33463c0080092891e59f97f05bead38577545c1
+KEY: 56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47
+NONCE: e037446f5891d77df660ed82933f62be
+IN: 936a91d0b5d2c0267218cb7090c617
+AD: 1386d641b87797b684e0fb
+CT: 939a53d77132969416e3bd18a7e661b4
+TAG: 4215defb2498d8ce35f3798936caf062e3832ce05e814265d81e0fbe2caae7e6
+
+# DIGEST: bdad1a60322dbfcd8c7a9311c700e878058572e0a0248b45ce98ce72177998e2
+KEY: d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f58
+NONCE: 91d77df660ed82933f62be8dc55b4369
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b8
+AD: 7797b684e0fb56f97c3961
+CT: 3a2a6badd8471b9a518b0b9106158349c64b3112640cee24836649f99e271839
+TAG: 2b23e9c088cd44093cb21127bf1e88bd24922e28d86c18c282ab73226bcbfc3b
+
+# DIGEST: 34413890ca23481acb1093a11d520da2ab99acf2ddc6dd22666f73bf23306212
+KEY: a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660
+NONCE: ed82933f62be8dc55b436965aabe477e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0
+AD: fb56f97c3961d8afa22993
+CT: f415dacd0fdecfda387f1c37360774cf825d6d2d53c5180636de483be093e06d
+TAG: 38d58d46b40e1f2361e7f3183e3ea55a03d232b3dc207c4c0d9d0af838a40932
+
+# DIGEST: 52e557635a7ae12be6c29ec1f8804b62c724d6754d243d8b9ddbc5741563dbe5
+KEY: 89c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62
+NONCE: be8dc55b436965aabe477e0cdd46be99
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c39
+AD: 61d8afa22993a340b9b3c5
+CT: cd8df431309589084bfa5bcce99cbe08d2065994585cd9982fde73d78e4b5cf5
+TAG: 8f68d2dfc17a48b00bae6081b96337a6981b05dcb96f937fe3fb723b55f033d7
+
+# DIGEST: 62ddad70b167a0485a88fbc1c14436bc42625704e155f887135c6ef5ad30cba6
+KEY: f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b43
+NONCE: 6965aabe477e0cdd46be99371eb8da7d
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa229
+AD: 93a340b9b3c589c7481df3
+CT: fe1456e765847fc96db17cb52acc2c8885c83eac2ca459dcdbc278e8f2bc69efe348cfc8869346249101228a0cbb7c2f
+TAG: af25895eea8c00cf5c71e5f7fae3f24d8bc7d27877c3e5ea667cc3a3909c4010
+
+# DIGEST: 6f8dd29852fef7f18075cbcc49fdd6c06310c9460cdf7704f32dc2262fe7cb0c
+KEY: d8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371eb8da7dac997deafd
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3
+AD: c589c7481df3f4183aa23f
+CT: a0407cc2b34e19502c284eb41935ebadbd0d2e6cf98098096ddca55b6df4a606321f064b371afe510a2ccbfcda8e9685
+TAG: 243d0a399ebaebcb9f9ac52b3735c92d73d930d89aefc0ff43263f7f051aab15
+
+# DIGEST: af9b961f54d0814cace0da7ed911b096d8ac66c29aad2f658ecc6304fcf9bf33
+KEY: 03f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be
+NONCE: 99371eb8da7dac997deafd64b1fc65de
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481d
+AD: f3f4183aa23fd8d7efd885
+CT: 1e99957fe2fe1d8a53532c2a206a413d1b35463aa0643984e6ad026f40705e0e235adda7e1c5cf0a5e1a264275fe7635
+TAG: 41cf3a3f642c783f5f479a2f0ceed4da9c95e1514e20becda99d649692928cd9
+
+# DIGEST: ffe42c0313980b92fcee160f5ccdc42911faf4497e194d283fc9c81c240879fa
+KEY: c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da
+NONCE: 7dac997deafd64b1fc65de39f4f03541
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa2
+AD: 3fd8d7efd88503f78b8ed1
+CT: 4198b84b3ca140be437c934f11d722d7585325fbb6b23977846bc233f89b16cfe29740edef9151052430bfc8feabe200cc3f6a6d217402d3cbd23a785e4f816d
+TAG: c9b5d41d7d643662d6a13ef24054ebbe0808c692fef6c6b1b7d8b6ac597a8a26
+
+# DIGEST: 4571c737be7acec8e83a42f0db55ffb2644bdeebb5677e5c179a5274cef7d8d9
+KEY: 773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997dea
+NONCE: fd64b1fc65de39f4f03541a11be112a7
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd8
+AD: 8503f78b8ed1c8e9ba2fd6
+CT: 82aba2e22933737ef55346865375b574f24066eabe39fb800ec790df3ad05f85a760332e8a1d45e7b0c2d969ac5689505bf1790829237ca889aa9de016267f30
+TAG: 567cc74f67efc1e7a3ef8421a1fa1ead95f84ea61bfab239dc7a8d187792b79b
+
+# DIGEST: fc6e1f5821a18027b80b574b621170ecef9abc558e743eaadafc0421ff28e2a0
+KEY: 2a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65
+NONCE: de39f4f03541a11be112a72933c7b54e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8e
+AD: d1c8e9ba2fd6773e0d0c30
+CT: 8a9f0d731d72929136ed9e6993cbb28013b336540f602c7203e6a38391dc07c8c3ce5b4ca62df582dea366c4b0b5aaab14eab92425310c5a12171bf2f5c9655b
+TAG: ef75d8cad215c6ea9a92692d73f489e475402d46ffb41f93cef5722210dc3511
+
+# DIGEST: bb57bd76fe5f29b96ee3f2d62d8f3c4d1c8c986c0991382834046dc907fe1ea7
+KEY: 446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f035
+NONCE: 41a11be112a72933c7b54ed4fad0be90
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2f
+AD: d6773e0d0c302a5f47e037
+CT: f2e78e183884c99ad7f199a02d87a1026c832b9a953919a98c2487bd0d724be407994fcce9e19b5a69f15ceef5d3b95c79d5fffede18a143cdfade5c0f80254c9924e9ae181761a00bf1d1af920bdde0
+TAG: 0d9e1ef046fd7f5b8af753a3c9da8fc18b48ce50804a7c0d0f6f6da2b1c91589
+
+# DIGEST: 23f13497afad98ac65bd2a1642935ff7185a839a672fd94b18279ff92202a3b7
+KEY: 7df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112
+NONCE: a72933c7b54ed4fad0be905d41203f5d
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c
+AD: 302a5f47e037446f5891d7
+CT: b2fe392acc286bdc73cac1aee34ecb3a3e3ae2ccdb065618e3c4a17f2b2668a2c11108b0bf8a8ffe20800a698e73c9b6ed4b0da61bf6fc22c33c75439445061ebc8b6fccb4ec738a07f02a376df62855
+TAG: 5d3755a9a76ca66cb12c6899bd77f49aff7a966f3ffdd00a1b038cfb832289dc
+
+# DIGEST: 4fb8d7ccd762998c343aef821e49cf91783d15669105b725eb1123ddc16ea445
+KEY: 933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b5
+NONCE: 4ed4fad0be905d41203f5dce998f8fb2
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e0
+AD: 37446f5891d77df660ed82
+CT: df01c1a140da0e422919c0d34b231fa3cd767766fb35f8d78d715c44b9003e42cca112fa1543d74ac05e00da9b5740c03b5c4d1e558ceb8629adf3adb1771e6e8cfde8edcdcd8de584ef28520d6becaa
+TAG: 190f3c1fbf6165ff2c4e7b62b8281cc4f640f2d2376b8e5ec08faf0d1bc36239
+
+# DIGEST: 11a40304bc276c51e2e7d8e3fa16f905bf050f3861586be68ca4257b1e6cc566
+KEY: c55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be
+NONCE: 905d41203f5dce998f8fb2eaad409ae0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891
+AD: d77df660ed82933f62be8d
+CT: 5d9af50991ea21f041a766d8d9036073eeb0ac083b8069619ee50c64c661bad73a9e2ca7f8b49ad9df79e47b49ca3c8ea9dc254854f116a49959c91481ba96463521bfdb74902a4b454d2c6af72d130119c6ef896aa751a22b3504609e8f4497
+TAG: a4987ec3469fa6578e271d77e8d15a2e28acd03321ceae7991ed9c90fd7370e8
+
+# DIGEST: 8b4c76888085f1030618cca2b0ef708b79b68fbe879c266adab2211c35baebae
+KEY: aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f
+NONCE: 5dce998f8fb2eaad409ae02116417dae
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed
+AD: 82933f62be8dc55b436965
+CT: 1944f256989b6acd7dc7c334d10ce71d9f2980cdb6adb03784061096955a3e10efe7cbf1c0aa1caab97cdeee4d08a8ff34d68e1b53a0df58e79a4c1d5d9b7eadb2430c0b8049b6c43a848fbc5e5feaf18e45691b7c7d89642640d19b0427d5d9
+TAG: 48adada9000755d3703a092201740a807a7f2c2fd7288c5a4732f290e5673ab2
+
+# DIGEST: 20f01a20150588ee1067e30a2ab84904a34ac56cb9e327756a700b1af24c6200
+KEY: dd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8f
+NONCE: b2eaad409ae02116417dae0cef457b9e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be
+AD: 8dc55b436965aabe477e0c
+CT: c107710a85a49250f3a4401fdf07a44f96560ca5e71d6021075b7b6e3ff8fd6f36c652f186dc82c8a21a8a743dcc007e6710214320cb5c5e788f8c5b020e4d0d89ec2fb780c9ea915966b9f9b1e2cb0f48800ab75f986e8d2c524e7360dc7f66
+TAG: 30f04c8f1d2f7839ea3f2389d40b2a0ba27647157f2f65259e7dad06bca4ccf4
+
+# DIGEST: 9ee27167f084f493a4e6e5b80c1cd07babdac057ed98dc28cea1f107ebc68787
+KEY: 1eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409a
+NONCE: e02116417dae0cef457b9e5e16dcc5b6
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b4369
+AD: 65aabe477e0cdd46be9937
+CT: 54a2f87f11c6597b3013a0de46b61a8fcc28ab021465178138cdd76ef01c2701b3a48ca4d3cc885173bdeb33b7b27f9064d2f09ec187d0c9c482522fb29bb421595589aa69ec2ca4155f503bdb8f0f8d79a5870e0d0be26ac239c56803ea8179
+TAG: 75b116a955bd24273dd59c90130d59ddaab77f2534a19dac3243014118208897
+
+# DIGEST: e59c699ea2887f6c829b7a0e895c45710aef6911fa3c930de3da61fc988e955b
+KEY: 997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417d
+NONCE: ae0cef457b9e5e16dcc5b6f25607f00d
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e
+AD: 0cdd46be99371eb8da7dac
+CT: bcdda7eecf3331f4e7605cfd33789ab585318bbd35047755402372403a4df125e7f5bdf857e49a3f74cb8e824576a226c1942fa86de07bbf564cfb384d8420a367963020613dd2f6bd4f371ca1b53532a7015dfdabd07497367aea8db9298141229325ef13440914c85b7e154828290e
+TAG: 09ac244fe4cae2f9f3019ce37d2b34c8701093a5b30e6bbe16e0626aa9d973d4
+
+# DIGEST: a1c40dc7a17b3ef6c9170eeaa9500014ef9ada833615b6d40af3fb2e14d7ddb7
+KEY: b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b
+NONCE: 9e5e16dcc5b6f25607f00d033fb95fb0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+AD: 371eb8da7dac997deafd64
+CT: 985481677ae867b2427182edf3de86d7b9956a4970b107ca7e01e90ee7cb02c6b9a46212e1b8ce67e7aca5e2d96272c2f412b5f16a7c1d00fe597f1390c3a686724c4846c78ae66b26ded18adb40f0d74c33a68032b97d440104cb7acc755ad759ef9b371d04e4394a02dc6b8ba61937
+TAG: d3e551c3207759d54de21b85ecd47c2cfec46e4cb8e045326cf6a37366124af6
+
+# DIGEST: 09ec84331099e1d602d0998d99c199a6037255a5a4d96bb3af54cfba357bbbf1
+KEY: f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5
+NONCE: b6f25607f00d033fb95fb09e4d00d617
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7d
+AD: ac997deafd64b1fc65de39
+CT: 8c5849a917c328d68cdf4fc279b29efb0c3c1921621276ca19206c9941a5789b0aba7283e743f94a6e4142f7febc9ad35df30daffeaa5cd0cffe0fa2e4cd5ceb687def585b2634774a01a3f00ce2ca9951fb910b4386bd0d61d1e292b2b225ac68617962b28bee0d40f195ff45a57efa
+TAG: 8ddd692c0285de19d483dc17b89babd27ec8177a51b25f4beda6d2e59a739b48
+
+# DIGEST: 640ba3888e6cc260a6022fb69dbe5c5267dc8604aa92216e11888394fe59d292
+KEY: 1be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f0
+NONCE: 0d033fb95fb09e4d00d6172e780ab8b7
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd
+AD: 64b1fc65de39f4f03541a1
+CT: 0e87c57c18fdc439c968a9dab086c88271be6dd00843879ae1563e4ed03d69f9fa09a29c1bf99b1c859323eb8452acb2f808f051669bb5e097e23b947369b5a0577157995d729a75ae7a65e293acace3124a8aec53328439e5f2103fc3a236728682fc129a5b0e203bd730303fdd2396270e000f83d6bddf9d40d259dbaa002a
+TAG: cac91b5e7623fdde5257b305581f673257c7c065aca535d48810e07610ae6277
+
+# DIGEST: cf85268a8412f6a450d7c8d48a2e744b508b00017da678e76cac09902ca6b0ad
+KEY: 33c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95f
+NONCE: b09e4d00d6172e780ab8b700433a957a
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de
+AD: 39f4f03541a11be112a729
+CT: d9832e63c2bc9936f33f10fbdb262711e715fb09ca209b46106c77e03b1bf7b062eebbb99185c684e9bfbceb083b5e459bceea895ce3fb7ec4eee3a5375c15066196b3cf24fc7b89a756184abb59ac80bc73116cd277e7ad4d9d02a9a9541cb4c71a644973b959b9405c9b109dc367c96ccf4c49a8cb942c9945a3c66ab56d5b
+TAG: a42914d0da1221752f381bb8929cdcfcc57158adc8c0f78ce7756103c3e9050a
+
+# DIGEST: 338800a96a5cf6db2ec5d06de2a53d0fb1b94918f1f8d5c0f222640d4c1bb96d
+KEY: fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6
+NONCE: 172e780ab8b700433a957a741c9eb80f
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541
+AD: a11be112a72933c7b54ed4
+CT: 088728abe87e0abc8f5991ed5b43811f4134b159111b0fe9a173122864baf70c5a904e46404399ad705084830860d7e78bf85bb166576117af665dd709ed380aa5de72a9d5819177fff5ca3b536f40f6518a21ccc50dc1cdd1a3d4dc89128de2ec6a6c64cdb50df0e11b55769dbc1e3cc18c9e57c06f5ee705590654bd092370
+TAG: b96f4351ecdf553259224c8b6e90e656e032ca56532eca0984c973a62098d431
+
+# DIGEST: c7923cf359e113a2e3403b71f1fba1977f9ceaf3b62ddf94f1c55eaf1f8eff15
+KEY: 41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8
+NONCE: b700433a957a741c9eb80f2b021b1444
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a7
+AD: 2933c7b54ed4fad0be905d
+CT: 34cac94d50dbc2556ba30c7535dd7f49495a8173f65c5cacc2cef1afd3ec14608635d9ca3cad6d7adc54294d5a48f5c3cbd43e222248e076066970f607d592f77fd2128345151211e9e75e51edc3f3e30923371942d0d62114786ec422308a78936edde5489305a2e7c1f4155623d34ed562c9f7c2086c3cc058a13cd54d82e08af88157f82bf75bad85860d44a51719
+TAG: b147ca39772889eae1caf10031cfcc456ab2fb69f58daaf8ca15a90727e6f30a
+
+# DIGEST: e31e88c9d9b8447db592d1b7752a0d9b21dbb2dcadc7cb82b70bef32a45e8c61
+KEY: 998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a95
+NONCE: 7a741c9eb80f2b021b1444769da00fcf
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54e
+AD: d4fad0be905d41203f5dce
+CT: ecb939c0a6eb19d5a502117dd393e30b37cba90dc001f03834a97dd13990b1b9bcae061b40cf333c620775adceae996b7663979370ff5ea7ad67d78f14256f7872d5b8d55888223cfd5e5d78b058b9865b1677ff74c9d6aaa0d3714bd8317066f971fa6e9462b732303b5cfe0dc274e00bbbc1ecc32079353d71fa1164a5a54962654c23ee9a98faa9825dd52975e404
+TAG: cdf55d6d85c2b5a2c676b8d1717c93d6d6261a8c1b98554b114ce981b0a05313
+
+# DIGEST: de34f10db0a4f6017ca3c515fcd8b6089bf276f1ee8bf60d0f1c3e6b0198c9d8
+KEY: ad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb8
+NONCE: 0f2b021b1444769da00fcfab0f5f93b5
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be90
+AD: 5d41203f5dce998f8fb2ea
+CT: d4e627247d7599a53c593c5cc7a63532cc3c83612d6795f92355d6555e067ddc430a0270b0b6b8069042ed951e7eaa3ae921c3c8808f0778e739dc83a316976e1f94ed76a53909877ee55bfa7076bd9cca9781ccd9611867cb415b86959f2ac11ce1ef94383ffea322d80d819568f69f2eb8bffef7d35df4910107daead743b6f21ca5f84fff6bc5b0758d10dfe086eb
+TAG: 9edfd6de65dcf756726abe121c1b76e8ba3ee0c0830961aea07d008bcefa353f
+
+# DIGEST: 0d9f746ab15a35cbed48acffb98f7743ab8ecf16760146434e465e570eeea779
+KEY: 16417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b14
+NONCE: 44769da00fcfab0f5f93b511060c9c5f
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5d
+AD: ce998f8fb2eaad409ae021
+CT: 2b979c9ce7461eed6ce82398b813e6c5028ec42fbfbb7c081d5892938d078fe922f4a6fb18d139541a845d0051ee9e59b9011eb7272e5515235f1b7e7413ce4253a339492d1ad2e8c2ff3747667b7e7d5730c388adcc18b4c0225fdd8192a87c68ffec8897f3058014cf2289b1036dd8be07379dc4164252049f0fccb748f05de0015e669eb5018b1069cf7e525fecf7b7691614baba040fa2859a1098ed12ab
+TAG: 4086162c9c039ef159240779380172c2de6603c2d0bf707826929df79b9ffee6
+
+# DIGEST: fa967c5729ef3be5f912bbaac5d3f6ef60dcbd99a9040d0a6f7b248209c0ccec
+KEY: ef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00f
+NONCE: cfab0f5f93b511060c9c5f3aacefe61b
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2
+AD: eaad409ae02116417dae0c
+CT: 9917a6bfe055cb6a373ed325174fe4eca1a37ed06a449e08ae37526eb4c4119736491170a197700181aad32cf63798327a9edeed564906021e3cf6e261d65dd023ccfa9763e42adcad987e950fdef763b083bf15e1124e6a9d880e30f39a052c81bb75bcb1dc2a4412264f03dbf10c37d27379022186a9e77af35a90a92179ca2684f5d90e741392b644f67fa4a763075d830b97021d4f24d60bcc914bda84a5
+TAG: 212fac98900fb504dff019235bf4a7a7c601fab80bed95b6e0628a043f7b0b6b
+
+# DIGEST: 34d46d9f6bb42722965c5d7d9033d8656525135588528906b7fdb3ecb5637f5c
+KEY: 16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93
+NONCE: b511060c9c5f3aacefe61b184ad24639
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae0
+AD: 2116417dae0cef457b9e5e
+CT: 6fc75baa13923dfa1c6fcfc65014c28d99c868d37b12ef306089c2b66eabecdc86a22fe3b6e3aadd3117135404336b8067cd901e2d71f54becf6c8bd4a8067e4cc4f1f262d49651601f565530672282d5bcd023bf2c6dcb045b71802ef728fd57f6f80577f4bd1d08f8b8239ebd8998cb13556ebc19297e919a58c218b7a3a283b2063c14c0e3173e0b04f53a0f04bf327298b0918a8cb2df68c28598b72be26
+TAG: aae5e11fa233954b795ec4391f745e64b53f40bc70c329bef1c4e1434c0b6627
+
+# DIGEST: 6a34de797c2867beb60921713584376c6d8d65afe3e45b7a1923719e8d44aa5f
+KEY: 5607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c
+NONCE: 5f3aacefe61b184ad2463939ed518ce9
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae
+AD: 0cef457b9e5e16dcc5b6f2
+CT: 2057c4380d6659e98051f50ede462febaed30368c9d4dfb3a6056fa37492c8d0d4e709834097fb3482218750b9df644d8360488930125729d63384d95aba68b233a9abc9ca77b069982c56f638c112c1c1c0ffc32c653bbf95d5c674dd6baed516c044dce6cea1d53c15c61334c981fb7a2dd1ff101ef0e9e68d63b302102f6f44e20a38a8fd0a198f288b98036c9999963530a0bfa3f5195249fdcc373580da42309839981a64071d3849018316e18d
+TAG: 5719a34c33128b09a6927c35e971c0054ac9c02820334d21309f8f7272d072cf
+
+# DIGEST: eccdb07aa24652caf23f2a83a58abe1e7992f9a3fbea97eddc8390b905978a07
+KEY: 3fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe6
+NONCE: 1b184ad2463939ed518ce97c3fdd293d
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e
+AD: 5e16dcc5b6f25607f00d03
+CT: b0e6d23fd3d04604aba739c2ed0726d1afa2d3903ba984fa29f588870721f00db1a4ec4c54d967a4d1ff6f2aad1f62033fb174674599b3aa668edcd1f3a585b6d4e50cb23453ffb1fb75e52a49a11cae5d85214f3ee337b4dd2fd8091a6d3706f1f3ee3dfaa304d678225b122d2553f3276dc01af5e0791a5383e794fde62c3ffb2e446372e9dc9a9673e472c1b9346e5fb677496abec859a046a402f8100045e3bd65fbddba50eaa3cd2f283b54fe6c
+TAG: 8c408057f9d4fb86fa70c6c1421189aae2710ffa2423bb59df752b04cecab8ac
+
+# DIGEST: de04f9f52b4f38fb3d9601082d9e846e67591724717066c7d9374b6725fb582e
+KEY: 4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad246
+NONCE: 3939ed518ce97c3fdd293d72afc09ffd
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6
+AD: f25607f00d033fb95fb09e
+CT: 121b70c62cfb1f2d818db063773173d3cbe2d11f45add0cd8b646c6d5c39ce730bbd777ff6eb8d0d7649a80f400da14a31bfaad449a13fbe3936ccb9898aa78bb5eb03ec38eed2d002ade035765e0dd7e34a4b04d1fa2a6c1594c21fe83d768bc711b4431f355ee97ed523f710e41cae21b270d5dc9134151a79e8afee04ba2396043ab9b013def38e48ff81b0865c4b9969c43b7db4df9850e9f01821a1f173c6aed3fd7d05c87b39689a51751163f3
+TAG: 5db727a0d57d5b888eeb40a545c30b8d617a62ae60f67c6cb6a98434e88a98c1
+
+# DIGEST: 4a2f51903111f8f9f1cd0e10e3aaf21e95d7bd8f91d4117fe6e228acc1c36d64
+KEY: 780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518c
+NONCE: e97c3fdd293d72afc09ffdd4f4196324
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d
+AD: 033fb95fb09e4d00d6172e
+CT: 4007d706893e327677bbd38f69d927d3a3eba3f8eb4fb59e1037d1dea20faa616161915c5bcc927c8d9b06c8bb095dba7c950cb284134b0b11b67b18880cac02f57a45b67f03dc202ad51d2a2301f0f835cccf88b70687ea3600dfa3c8d5fe606ba1ad2f346454061d8642c68aed3078fd7fa0ae3a76a269fe6710ac1d7a5a2d03a2a5832008cb6d139d16b7ebcca9c78cd5de1f25d759845e9d3e86bd8960736363f20913d1709f77620f23b1c1ecc7
+TAG: 77edff039d8287c72e6a4d2a88f231905f066bc9d5554fca5132ade630db27cc
+
+# DIGEST: 20d8d5bf7826924dd212445d7cfe80d03657d2a75757de48313f3d0de3f61eb9
+KEY: 433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd29
+NONCE: 3d72afc09ffdd4f41963249cd299b92e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb0
+AD: 9e4d00d6172e780ab8b700
+CT: c1362678baa1f710599115bbd7be79c1b6bfb4c2ff8eed0c0256daeba0117d359bfe04d82cfdfa51fee7b376bb3d84dd5f31848bd7901534828a36b1498ce852da03f833d75bbd3546c7de50c55b370c14c5dc21b889dbb551dc593dab9bd1f94e5de2174adad296e4150ab59dbb7bc8f126c16f5b388c1da6d3e037c6fed10cf8ffd9ab60148aedac9719d45aafd65c5ad79a685184ad483061477971264ab52d9a042a3e8d824662c364e98c5dacd2ddb785fc1b03936ce456c0188bdf77e3
+TAG: 5f0c20b67725822e1c8bb0bfc426848c3e0ed39fcfc7ff9fa7fb24c2d9eab3a9
+
+# DIGEST: f676940c12fbd43c81b05378d938ac7945b83754a0d88f67bd47aab9daeb26e6
+KEY: 1c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09f
+NONCE: fdd4f41963249cd299b92e55ca24d8c0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d617
+AD: 2e780ab8b700433a957a74
+CT: 902fb925c844ed25c0203d5c0e30f8135f41e1308b09233fb0c1b913f7895a8e81242e15a9e5e5ba31625de65c150b27c55e6903073f2633bd214b82afd6d36c327cccfdd33284487b771dc61ae73a66389af3b85e8cb72d27738a65e3e8526d76f30e5572aaa4cbdde2cdce25616f17e6c55908436f85c58c38d11a4e3e01ef9e6c1f51a2a53bf9bbcbec2317da9df09c387a8999deaa30739467b731cbbafd6d651e0a1598aba7e5275c9e5b6980aa98b9dc5fad509b478acb6185e7fd31d3
+TAG: 362d3ab40e1b92401d18f8c442c27b3918e8c61d79a3ccfcd61a2f2d047d004d
+
+# DIGEST: 69662ae4064ad473606c2d36c5a71dfced4a0a4ab4dca27dbcbd5d3757685920
+KEY: 021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963
+NONCE: 249cd299b92e55ca24d8c078c49f78c7
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b7
+AD: 00433a957a741c9eb80f2b
+CT: 3c7088a48a12d491d63b579f387985431aec724602dcdf094975d233f4e2c9aaebeda00deb2e5ab08a663e6e40247404e040f262d6224fdc2d1c42eaa00424ce36dd9be610eea1db9301f54be20e95b2aa67007c760b78497417cd8299fd21a2e4dcc393d703a1cd4b7e0a26df78062b77d1db7e15f0ce7111c598b6b7e6c75503e111377fbc8f62e7a46dbac714940b92810d4f5827bfbeda845e65ab892d66932957af1ea5f17106666710be952ad1e5b330fd7d269edacb5bc5a3d838f304
+TAG: c95853f40da8ae0a20812fadf6739417b67e21bd850382d1bdbcb3f8cb8044d0
+
+# DIGEST: 1c22e20d5ea9a85a8e75c7a1a54c691ef19721be71ea3aa4c22d34a8ef6d8e50
+KEY: 9da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b9
+NONCE: 2e55ca24d8c078c49f78c7e713710a02
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a
+AD: 741c9eb80f2b021b144476
+CT: 70293178482fc64094c8968427315ea1f97de2b9f4addaca582996b463b8dd8fd827c71a0522768011ae5837b2ee3805b901187903db7e7a03452e66b2cc5f4430fa76ee0b6aa47208d1d0876785209245b2687bd71cbc6c283996ca629483a35575f13e1cd102d7dfb3cde8fa64c3290f343182e01fd6d33fd9375cb0fe6a16af270dd08fa86869c40d5c77cb2a6e8bdbee8d94763652f7d98274ac94faf50bea3a84e80a869fec51a9099827d2732a6e3cc91a1cf6e446dcd45cc41690bf86f4a01437ad43bae2c7c9d7f3fb6eda4d
+TAG: b712b1d0fcb03c065b1cafa72b27af4583654ee8a9c1ccbd45a176ca94923994
+
+# DIGEST: 26ca5ff6124bac99bfbcd7110aeb05a5d2fb3766722e743a6a71600c4f691aa2
+KEY: 0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8
+NONCE: c078c49f78c7e713710a025cb8b9d71d
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f
+AD: 2b021b1444769da00fcfab
+CT: 3c1b9fe2f41518444a71d1fb79927fb1edda77254666bdfdf2e1fc620405338ccbd40b05d513de22550163407738ddf22be2832cda50469f6bfd6f2a8ba4168ffb409c190c55dd3e929578e7ea4a9ff8c94186d484872b42c7ad7138a00a2f32cd11c57e2910c1726f8d0bf82dc59e0b529b4d9dbb56b4bc813cc259b3fd0138e6ac7f5ab6b4d49a918f7b773c6ff48e5e1be5d559d07983e7242dc3bd1314efe2e37e27ddb8fe728edca88b54b56b541981171516debd2c9e4736d61976f7b7f9f3f59b642c6604cc7a58d13e74a7db
+TAG: 7e5e937febce43f63f9a327b1aabdb103333c291cad5a643ff1a9e69c7b064ae
+
+# DIGEST: bb93727ee7c2a4c128150ef9c32f637cc28c95f76b345f87b9d749dd9cea56cb
+KEY: 060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78
+NONCE: c7e713710a025cb8b9d71d2989ab33e9
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444
+AD: 769da00fcfab0f5f93b511
+CT: 16ab9a87a7adc98c92c2dbbbca3df3f9e65dd5960081e34e18d0f6c804adb7eea8480ec884e1541788ff90f5434b3a39e63c816d01883f44cd615866e7b44e3fab62c29b1c05c70734d9593ba312a37fd5c08f4a888417fd18182ed70c3f527b5fc41aa1ffb667457fcf5940596c9ae6417ca920b7ee65f81e643cf7c4aa02f1a5552948b21130aecc5e22bed10f47aee5afeecc8cca238a34b96e6cf292317671d78054a873900658ff538033e1ae3c5b2d96b5e373531932d3b9e68fe31d179505ba59c637222267e6832dba7bff13
+TAG: 881af4ea93fc761d110174a6a4884bccf2a805a236339f90f92c7f392202bba3
+
+# DIGEST: 8ae8a1099506d47bed30e442e2b0806148dd7e981e23fe9847de6fd79b5feed0
+KEY: acefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a
+NONCE: 025cb8b9d71d2989ab33e978c4451e3b
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcf
+AD: ab0f5f93b511060c9c5f3a
+CT: 4b757d3fceac7fdd82d2108ded21aa750d26851b40c1f1c8b40583a387f6c852439119c77fbbf7b9825fa7035d9e2acb739dc150315edae36223ae0e3db716a6995073318bf81a34611c536f647066c2d987d9dba9b618d1083a3132c5f91bcd059c50b5b62cc900a53cca70657648b3caee972a33527c393da330e6b82170fbf5188f670f42ade0fc0e8cf349c7bba78deb27161b624e83c7de77750e222116c15b8cfa7a34b92b824d1376c10649f9c6bca4ee78ebed2780085d6c8d2fae6f76fc6b00a7585a2deac94f90f6e70a135895d2f466361a9ba5bfe86e8f16875c
+TAG: 3c93308ed2e3dc292d365e12723c36dc2fbea1e37469c9e649eba14f671e9767
+
+# DIGEST: b06c18cd7f4c807056854690c911e4deffddc44b59950560ef03d85696e245e4
+KEY: 4ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d7
+NONCE: 1d2989ab33e978c4451e3be585a29a2a
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b5
+AD: 11060c9c5f3aacefe61b18
+CT: 7d774b3f93c47cef7854903b8d82495c5500c099d0a00bf35e0048e9967f70b3554ce610f4363e17f4485e3317dcd21d55e66e5f9ae9fa7e8fe404ca70d56ac707e1c8a75baa3d1a92e9a887354c699e4e8cb05f8db65e4dc563131e2b0796afca8f808390358bccebee2714e93ca6598ee1d5f8164d6b39f238526bffc4aa508a876dd0407e4a7bf0c577ec27272a8d7d021e3369a77f791ef308311095dd1742dd611713e4af00d52755491dc9394799aabdbb9b10d1fd52749370acb97d34b9176429e28e4605e19e47d41a66bccb16b316e0ba35b72af4ff212a72f4cc63
+TAG: 2803250ea1a7e8e3401eec5f99abc722fae5b6045cf08ff8179efdfd3bac1a70
+
+# DIGEST: 644dde7a2550d59806eb3ea4306cb5f780a53450fbdcbe2ce736c3c96899b653
+KEY: ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33
+NONCE: e978c4451e3be585a29a2af12feef71e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f
+AD: 3aacefe61b184ad2463939
+CT: e570e5defb28ec61b702684feacff304f8f1061741c32dd43e4992d95a6c145a1866b74c3e63dd43fe1b38e37ee67d84b13224f627b63f00e8371e2b0151a4d7348739a2ef23051033e71206f8517c47ed768c7a6ece627ee931bc0e0d0f82593052e07764a7f6f5457435a427f19b8a83fcd79649984342bcc1d6ee51d948ae87ab9a8d79eab314ee7e3777c3a5dd1e46bf96cc8a00d9e135ba5dfcb016573fad0816a80c2016254dc61c7a510f0b9d3032d0f69aaf508348a1b27f59499e259f2701f3d500c9b80cbdbcf321b19b6b3fb0d8a7f9b12f5f0f045b12f3f64a9d
+TAG: 9177750442804a9fd89a9f43da3c18a1f8d0018ae2cf4e68f150acc5d535f385
+
+# DIGEST: 6fdc37d5ed4a054bbc386444f96a13f554744434e60237c1d823a171fe282485
+KEY: 3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e
+NONCE: 3be585a29a2af12feef71e1063b0b4e6
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b
+AD: 184ad2463939ed518ce97c
+CT: 30738b48fdaa1d2dd4f0f95c030d11c33b9f1133a326cf117b65906b9de6df16163be7cb9a4f8362da21863e108006c2f91750fc016e02c23d8983cd8f5144f40fd8fa53146b1c1a0bef9cd786385d36a4f59ced271aaa392bb1343b04de23c40babeea0c9916163dfcc591b4f37f575757dd60088a7a58e5fea94169140b4bf6a4818197e64107abcf18eed250d64bdaee0d5ae7540646f5c6f770bef6ba30f1ff202a619fcda61daeee1f0ae1cff7f6fece6795a2b131c2a36af4aac0e28ddff094eb5463de3221a0eb499178e42cf2d454a23b463f0879750f50911911e05995cf1c0b418634b94cbab41aa8d2c6a
+TAG: a5015e85a0b49afc05fc649bfb2cb72eb58523d5bc0e91039bf76719d4def92a
+
+# DIGEST: eafe150c9d5813a48cfc8d3b72c11bbf490429ce58522cf5eb1b6a0350d3cf0d
+KEY: afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a
+NONCE: 2af12feef71e1063b0b4e6e899200304
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad24639
+AD: 39ed518ce97c3fdd293d72
+CT: 7c1a90c25bf8fb71fac4798c2366794ded293fe75b35451855ee6ee125a8257c4fd75363ede703985ce25c72c34b0abbcdb3bb08314ed23d716c2ebc814cb5bb406f22f774c7a7e9db283b6395f0b88c5db03bce527c653da7e9547a30ef35d9c4e8202ac7fe265e8dd339cab5041e894db686e9b552c31ef8a3a4345d6b8ad37f80472375b67d43b49566b4c3c19f50256b2699fd48d53ce7d954f4909033cd8d22e0f3c7330352841c8a26c4628c6f7a50ec01181a6cf3d3745b5a6261ae01ce59076d12c168d33b5fba0bea97bd442915d3d7ec588e5b86cb1304ecc044f9c910bb2405e00c972b500bfd9b277639
+TAG: 156f914bd27144e81c9609cd5cfccf3e4939b856dfbfc9f9f2fc82efc450f4ca
+
+# DIGEST: 188098edeb12f571910ca64d0db7d6da26c090dbf1f532c4120e4821ef333638
+KEY: f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef7
+NONCE: 1e1063b0b4e6e899200304bd3508132a
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce9
+AD: 7c3fdd293d72afc09ffdd4
+CT: 17fd4257ead2b35364fafea9272870ce17a7981fd0b35798521a9e20abc5fb06999ede5aa2859c879ab61d57e128cc4832cb176b7b73f008a3f3d4d08e9562fafaf91ebce17d48ff0628aa95521b32099818a900b3c431d4fb5e98df2d717d7a72737948657a61f1905617c9a040b2100b8ee77745856e6a9ace03203038adb61755816b16037eaca4093ee160ddedfc2415b9dc49672a6181acaa4e0c6c675b49e3e4eb2562bf6414b9c635f5301676a37ee7fdc0649ebef0a48c51cc01d46423f6d748ae425dc67fa5dbfd8b738baba74b614dfe827c25037281fe8769587fc5a5516a6b25919430f02d9591bd0433
+TAG: c56528edf96a07205a8f74adc80deebb2f5b7afcbf46ef54122a5aed89e2a56e
+
+# DIGEST: 1ec354373ad0e5f22fe70619f5d925266cd3021a03e5cd2efcaf907f5419bc1c
+KEY: d299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4
+NONCE: e6e899200304bd3508132a027d1ff4c0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d
+AD: 72afc09ffdd4f41963249c
+CT: 653e0d070a1b55ddbebcdb13d480156ebe1cfda1e48d5c5e46450e9b31b39f357960d0024a4c383b824dea00a92f6bcfaf12b56a657b31923da0db5561280883c0b3e1cbb125bc12f16e18b9c3f08749590b8285488a577771159f712668cf5833f36b19a34e715566f64d62ccfb199a5e5d6b29a2570535ac36f11b47864a9bf51168ae248e38054edcb6dd18073598d16a9658e60843d29eaaee1a2cb864882c94b9b2f618ee68e9d5f3fd15dbfee4dbdc465de7e2cf17b43257c0bcb5c1cf001a6a3b0eb0e19395f8e9b6f8a0b1e503c40a2a2811d1786e00e71a5dce6b0c35a062dd4f219de919de9548ed1f10802b49ca0bc19e30f98686baa5b06bd82e
+TAG: d1dd5956f1099a83b68a1d53a64bc30dc2d84b33a6c98bd920aa60f6da0c5889
+
+# DIGEST: 03311a02867c702d778f6d1760930e8b8c05f168bfa8fc391937517a91487570
+KEY: ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e8992003
+NONCE: 04bd3508132a027d1ff4c047b3ef4f57
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffd
+AD: d4f41963249cd299b92e55
+CT: 5e37957981c1ebf1b5bfd31e09b1a983bf8f847782ee44125773fc1098ee0f9f6759a3b8f500c9a4f0ea2886fd62f237615631c82cc379a0b4d1f6adf8d552324bc5be7dcb98d62d771c3cfd84a2fa108b35c014a584cd1768c9a0922b3a7f5c1df7190b2caceedcfaf86ead5cb43e55eeff47bf22dbc79a7ccdc0d436ec1dd8e60a45ecffb9374f5412bc614e373f7eddf49be981a7c9d21bf506ab80031a230f825455083b37abadbe26e419483ac6a0c9e3513507f1610590f36d8a317093882b05403a1afd5b610009d2b6df5a484b7c373f05f09a5e995222872e258fc9a1b5ccf92b4d3cc16b8de887bfcbbc1f346761a8bb1f14cb7b03f896de6c43a5
+TAG: d53a33f44b37a32e48dd0e8628044db684cddaaaa4c47577b63761200cd2a7f8
+
+# DIGEST: 4d915f47f60df1497b0421c003d413bfd327ca8ea84c7b985fc125b2e5e17b97
+KEY: c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd350813
+NONCE: 2a027d1ff4c047b3ef4f57a74706de4b
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f4196324
+AD: 9cd299b92e55ca24d8c078
+CT: 1684af27544e73f6a92158091d12eae3c49ad65f636e3f7456f65ffb521e2f579377ad5d02b709693ad183ecb3e4de881510f47c7453eeb1237b38defa7e6e41498a863d8275b1d90c360530a74ccdb637ba7abd58bc60e733f6a8091b7973d5d6c48246e74e325d4e7a0a6fa2a58ebea5ecf7d032a1291b9ed0841544cf7dd2d569946e919db91b51094003393357e6c0931e8dd315fc5831bdbe2cdb1117e80d073a6e0b620d895e5f463e011c182333543c1af95d63597cf0e0ab5519b6316f13a645b761be858b93a2ea3fde8942baa8b64e4765d222077451340236a98b17cc0ec7b1f83ec8b6bc4a7a61a2ed747db901d7f9ed8593422274be1ae800fe
+TAG: 695eddb15c9a4363da26127bb5f9cc231a0d0f17a873ac214cb9f19b43ecbd57
+
+# DIGEST: 51f679720151684cf2065746e1643487bca49ea8cdf3b1b3629e840dd209c0f8
+KEY: 13710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4
+NONCE: c047b3ef4f57a74706de4b381c692ef1
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e
+AD: 55ca24d8c078c49f78c7e7
+CT: bfae8a240f987282df9cf2524019d5f2667128a73d4d1b69397d12e5ce57d9136bb628c25f9e185fdcd2b4ae0e5a563cf172aaa6c1213bc7a0cf13eba1b204ff93447cb7b6ea42576e11de5dfbfd0faba0eb75989aef2efdeaf4b9934bcf54709e88e94fc581155646948ed687d62ab9834eca831ae913932fac1512a6a48c1fffda29ada1d640cffcaf5f135ebaef3fd6794359778e3cd07e45a80fefa6675116e7ec46073c008be98736066761a71fb8380918d3512ec4e9855db003ed771b8a798a4fc43b8f505fd31a7638555fd10f00911466b2b9bfbc6d579a0173d46fec87a210a9134d3ca9590e32f5f904c4be0e5e506fec16a7e5ca708c2e7e421a
+TAG: 19199e7c636c712145bb5af526e1c830ac87afb336422de2762135c812843f88
+
+# DIGEST: 216debd294dc4f2c3d2e6d287bedd91f1e9b041f6ad98880c26a5a1d4a40d836
+KEY: b8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f
+NONCE: 57a74706de4b381c692ef164101b89b4
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c0
+AD: 78c49f78c7e713710a025c
+CT: d49aa7dcad59adddfc5645e3b66ebbd8570ea2992949dbad48d45f4043d64600fe0681ec3f7cf5c261275e1d414cd6666948827299429b62f45c3025ae8fa0b7cec282492dbab9b70bbc44b15d4d30017ff9a6421297916e06b52e53a98ceab9e28c58049f1d0571c9b32babb2ae071f39cc7f2fe2aacece5fcff43376da5b3fb63c6d5926d1f3ce7863e98c8d4a454ae70bc3b5b46e035f940c087946b9acc83e7287e23204c2ad89b8ab8942bd57c4328622863d88cfe1f21bfac2c3810457397e3a52b76549051606a913998c4680792e08e52e6e105dd76abc5e413b4f7621b5dfe271f6d27ca565042aec5914bef4caad7bf85ea4f4d2338987f9734cf3f253e43f768fb69e9ec251a6f0f91eef
+TAG: 37e86e9cbc38c6a4fc0280ba941fcea5441d26d86c2b590f3e4563c371136c01
+
+# DIGEST: 366ac0d2917699493300e9677177d16020fcd86748b9d8fe8f99e259e45ec6b5
+KEY: 89ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de
+NONCE: 4b381c692ef164101b89b476f72b27f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7
+AD: e713710a025cb8b9d71d29
+CT: 3047ea080d3a25dfa957f260280c0da9bfd9742a2c707d026d4c93f34ee147949aac3d2e24b899304a2244f773eb78e9b17a937896f5a018b7515d226394965140c67578b235d45601fdfc95dce3288289fdfd592b3269691defadcf6e9a702cd3536c79e92ccd623de57d1a859a7a08d3cd56aeeb06127a3b608f8e6b4958d49acfc19b3b989c4c724178c63093df85ae3d41345dbefb43518386954721e5eb4a4879ea8de61453703258542bb1b8302c15549ada6865d60164d9ec36d911b8e29080fdcbcf92ee9e5aa6d395fd83771c38aa24455acf9e92a3bc842cdb6b3def5190e39509000244d9b5b5ddce4da237c0145458fff953163b262b56b37b441c2c76f9b447118ecc5716c86973188b
+TAG: 538ddb219981f9423c075bb52b86d2e77c2ec2e93bc10fab5ace72ca342bc887
+
+# DIGEST: 8062bb5c43539c2e5f94d0ebe3387fba85f65733836e4f6dd724cfd319dabfe7
+KEY: c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692e
+NONCE: f164101b89b476f72b27f06f520c9267
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a02
+AD: 5cb8b9d71d2989ab33e978
+CT: 1521c9c57edf6586c1232fe8b5626dfff9a9550bd7f2a2f1afe52255f0d0d76cc6b9ae4ab81d4cdd6dae1265ae3268406c1bfd7807e5ea28808b9b1baf482868a0e8984f7a2dceeb23da9cbdae485d4b5bc8cb5ddee7f65a0f7af2125c8fd9add309a85d8279d30df886736e0d09afddf5fe0bc491a5097d4ec6167476b5f11e854905b576b087dd0d8c4038f4c78cc9d4fdbeb2bd3c47645ad4ca69f3f8caeb3397fa3855215631c25a60b2de6ae388a56fe1700ef7aa8e9a7abffa8300aeeba60443421efde4069a533ecb857a461b3f3654d65c2f5aaf67a42437e252d566218207f7162fa432eee57c26052cf6124394a8d80c4796349af44b32c6666914f2f22b418b9c198b7d342b91e534059d
+TAG: e40387228066436c72d0c32a9e681934a45d2a529445a8c140ee29498bf22d43
+
+# DIGEST: 2cf5d2fc7233c5723012a8c475e430be11cdccedef906f5b5e5509d6197943d0
+KEY: 85a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89
+NONCE: b476f72b27f06f520c9267cf71408a41
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d
+AD: 2989ab33e978c4451e3be5
+CT: 50e79738ebc625bb60b0dda5bde4ea60131410e69ea276bb3781c93bba0d6230ef5e877111fb3f477dfef7afe70b1f352bc7e7ecfbb016c6bb4b761b31757e00453a92699faf16f4bb73a63331c87e6bb4d2cdc675ee7ecbe694bfbe16139f2ccb5391544cf3fd638cd4d2dd9c77ed1800af8c5bc4603259d58461a4bf29feb2439191798abe2092ea9a4921b61e5d9bcaedf1b0070f0b6c2c44646dbe79724522c43d4526be023ecc50635ba2b55fca592a366c57c7317edfba0c00d99b2f1ed4de1cea408c0184763d2165cc0c805a157662e9f29abd187d82645d0c2378b85d2ab110971181f9c519e07a0976e9de075b845d439ec235743cb0b19cd5b64ffc749b9c18a1aeedc663e22c4c924db0a5d627e00f0fed4da63f49cead212370
+TAG: c38b9b4dbf10631b680a3fb54029a86f155041304ad79d31b9e626f9e247dcdc
+
+# DIGEST: 5a7f0f0cbd9fe9e1541460a3a2b442a7fd1316c92475250ebad04166f8f39c7d
+KEY: 2feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27
+NONCE: f06f520c9267cf71408a41729bacb587
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e9
+AD: 78c4451e3be585a29a2af1
+CT: 220cdb8dd4e53e98a034b9b068936986dc54d13f709d9efeb7835c9d3a0b3c2f53714a05be28c51f6611ef4684722e659aa83bf373a23d073a858bd358d919c9048f3145477af7860c60d477df2837f2782627780abde90714f036be0ef843403da249ac585f6da8fc30a9443b2f601c499616515b0b0b160b1433ec90e9837b21955c4a47028f91e0c5877ffdb9c67c350596fe9a72d6fc2a9345375ca089f2e9a48ab3db7e379ab9ecf9a7ebf45c26782e4f03225022f2f1f780db9809b4a2df377a1a22db995f5eecd67dd247ea715918bba0e050e6aa32258ac03d4a26b3a30122cacf29f2ebe0fac9ff727627a7db41209e223f1365186c71b03acafecaaf364b9dbe0bb554efddae13b6f8a1952a187a33f638a39a39d67be9b3076782
+TAG: c84aee84113475412bb3f06a9124d5e77cf3f82c65e7edd806a217de3dc62809
+
+# DIGEST: c09500fb251738f53a35271795a0790b649976d6225c8174ca45040317fd6fab
+KEY: 63b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c92
+NONCE: 67cf71408a41729bacb5877e72cdfcfa
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3b
+AD: e585a29a2af12feef71e10
+CT: f354ea373bf58d2a0b0609872d67697b22a7f0ff746624190240a9203d2137f3f04c335809c22c44fd25859f0fa5403003675770fba3b658c7f819352144d61a3def9b2c0cd93d02878843a8a959e108da445d96df2e8c8a03d9381e7d34e78c7b7530ac82b89e952ff8d6cdff234232b5c84d2f7818c29adc6e1a52a1eb3178aaf5e158c836209bec55a3619ae2aaa43ec0c2bb8cce32a121d1ed135d74f9c825a1456e5e60b749048ff3bd525a7c413386050c6cb5668b5b382999bf2b61632b30312a07ae3c2b09d6879ea286ae74170a8f6b3438acdceec0446cc3d71ed1114e7cabec85815236850e641738085990499e930a435f243f9a4cd3096efafd419553455de2a18330942ea5da367d61ab0745889166b3b0f700a4af78513e7f
+TAG: f0627329d14ecf4290c0ef8bec98d5166840455dcec8970528c7e31102962e62
+
+# DIGEST: 779c4c8a35a8127be0a3af015697dd111f9617234f30f19dfddad1f22d36ad8f
+KEY: 99200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a
+NONCE: 41729bacb5877e72cdfcfa76aed06707
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2a
+AD: f12feef71e1063b0b4e6e8
+CT: d8bfc14fed369d5a6f61ea9ca1018ed05c996195a2f5f2b3ff8266c159aafb670aefdf84d2742e6a684da23812f94d6a509aad2ae6ca30778c45736fce6a79fe9255c38fa371e8aa0ee0f49236867f0252ae23a48f540270b67ef44cf576775833ebd7a3a511f0058921527b70589d41c27bd21fc22be9e3b84376d64c06536bd52ba5459206d500481cb72b9d5cc9c8dccc9992361713417d714ee7396614d85cf7f76ed29657e3a74ab28c30cf81e08e077d8e2a3714c8d0153528b0fe369042179d95ecce2095232903c65d4aced84a185c19d16d08ccc6abf13b612d045a1fcc4a22f1a446e48b0a9c67724dfc4e0fb659f1b952b90da0e20c9682e9318eb43efd847c0359430b5bc83e3f8f164a287fb0404662ff8b150a7a41f00396d58ec50c4a91acfeee5e0ba80fc55c3099
+TAG: ab7e7dcfb87c2b9bfe03270f8cf28d9a85dc914e31e36cedd0f20c02e9253f7f
+
+# DIGEST: 17cf5ceb6bb8a7738247709043777aa7880c7a583ce22f19cbcb61aa4e76c6b5
+KEY: 3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5
+NONCE: 877e72cdfcfa76aed06707a07c3dab69
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e
+AD: 1063b0b4e6e899200304bd
+CT: 5002c26268b8db10ce40552f8c5458a2abb7299c283dcaef9013a8065eb22ef089c21dc2e943cd2c74157d8ff891ad125d47bcbb7f5604d4945311fb2d488122b29c047654985de66336046095f376bf6ebe1a1bc754b18accfa44538913869a3c5f140d2a24f677dc372e960985b9aef09eed90bd20cfc8f57ab72a94399e2b98f46d1e5385033c0499618c7fc0b5cef6b3d0247cb13b2199921cbefe90caee031c22c35e64d47e39d07d2caa71d39870ce25e8be9e3d681acf2e554b9be66b8e8154b15af80cfce8999cb8c86b1edef500186c6ce5b333e5969ad8cab8876db442a90ca0dd037d64ef938234ca0df906de02554e8ac03649b7ae5bd2a8bcea103315f9f8478b3612a51a9ba9968a3e3aac6ec14cbfff88b80c46cab578f053a87ee0ede5c806cf9134ab6bdbd21dde
+TAG: fe5c438932a6adea96ee75b1c8fc6e394914ac376056ed9943b7a5433787f80b
+
+# DIGEST: b96b7307ee0a74e8372393bac2c64b606678e21ae96fe6ea0c356e8ece1e6fc4
+KEY: 7d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfc
+NONCE: fa76aed06707a07c3dab699719fe882e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6
+AD: e899200304bd3508132a02
+CT: 0f2cb2f5172556aa08d85a0ff55d2d6c80a4e5279e6cba6dcfa8cde66e280a57f19ee11f0ad17a59373267fe5e04e0ab73342e986d525cff8c47b5aed3d15393a7918ac3dcad5b6fe57d26d14d06041677e474a27bec7ec6ae1be69a098fdf95b9f286f15dc2013303dbce67985342c8f6ec989a8cfbfc5e1c37cd3fa1f204887c17885bf20349cefe6f46cf35148105cf65fdd3cea0d87ba871b7eeeac738d6f2cfb9b6e3dea4c28365e018cc7c1f6f88d1519aaec6d3ccfc0d691f6b1eef4d1ce73363fd1c5a21829e74f91536f69a9fe58612c45034957622e83ce1be885b9fc22fba858d81023ada19bf88d5ed6c89b48e392e420dc93448d2797a2b46906a05c0101797f74adbbd0a64382f67ffb0d0f7fca179343e71f4a3ac138708505b8e022f12748dae87427b61e36da15b
+TAG: 6b06cb00841bb3d131d2186b0f21d4792e7d4325d0f3350aab3568910ac9d8b7
+
+# DIGEST: 095708068d51ea787faa3318a9dcf624cd00f3fd32e0ec09d2390ae46783a0de
+KEY: b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed067
+NONCE: 07a07c3dab699719fe882eee2fee55ed
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304
+AD: bd3508132a027d1ff4c047
+CT: a7daf8b197cc2cfa5a43ccc5001a443192d23722a51b59187f200326bd29f988a746b6e25000097f2b4c0b26d51ee736e0c6306a4da5392a58f95e814e7069b981c72cd7c0b4a092f921eed2c578aebf0e969f764d74bbc393a4ee49fbace743dab29f53c099cd80c95931dc9aac11b245501d4240b1a6f6dcbc284f70525731245fec013a8af977621b89e5de5b7e6c686d6f7800c599a3c64cb92a1d8e64d2fc00f42eab0040c0e35ba5f75ff3dad680f26ecbb745de2385e8cc59576cadf40ac75a761aa611c70b305490e17e3b06e0854fe137c2cc539c5d4e2f933bc524f3e79982dbe79dbd09122fb2d5a7697b9fb3caec0ac0557c07361a0ba5005787422d7375b3a210de599116d97ce96698376d98d538e5519daaa276fb7c876d162ef1ac2bc25c09736c364c83208a28140e9bf71ee7a92eefab03174ba7bda8dd
+TAG: 22d0783cc7bf26cc7652c057f5b3db7dfcc0507ec7d4a3eb1d14fffe773bf52e
+
+# DIGEST: 5f270c4adbbd1c7910b64cb075903ac41a2df8c9270cf9cb77b7c9999a4ed94b
+KEY: 4706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab
+NONCE: 699719fe882eee2fee55ed8b11534c87
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a
+AD: 027d1ff4c047b3ef4f57a7
+CT: 4b75a1cbea0c660f89637de8e2ef1c093d29036d0552956741ddb7d7a2a967d4e8814d1c6fd65e390f4052c68ee0786e27e59fbc1486014c2e99de8745ab442e4d0b48fd811bb8e0c160433d5dd29a9ef63cbaa08e6608e0e6c67205e8459476f78d610f67860de94624c63e70ea7fc7cb96ec5fc84e2d2ea540ff00166947d800cc969db37231a355bd62098bf59c93679b89905876adfda923c0a9bdb5f5f226ab8732bf5bd4ed780155327ed1509e1c250000b1b8f7f1b9497f2aa131a5d721b9d1a51605622a2a3b3a3884806f3ba679557b3720394eb3ba9c7be4ceb7d84a537eb51e2d3e73fa266f644ccfc91dae04a5c396ee88260d1fc559f6ed3fbfe6f3398d271d278a561d9753aa177a84a65dc6b1735a837308d73d8f66ab69c831dd463f39f3a6fe025fdd62a6ce5097f386908990cc1bc48ca8419c12efbd34
+TAG: 82610f5ce79f810f3bee67afce72e17b2a392e5e866a1de13dfaa6a3c5b0bdf1
+
+# DIGEST: b9cf43847a4ada30333644f3f70f1bb376bd9dd3f62d887e1c568e027dc9a850
+KEY: 1c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe88
+NONCE: 2eee2fee55ed8b11534c870dc695b814
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c0
+AD: 47b3ef4f57a74706de4b38
+CT: 1e96060f35983824c1ca554518abcbe0ac9f4ca5b100eb4554cfba18c6d7f98fcfaf05cdad43763224d135ea243e890b063dce6c3a46b0519516263791e4e55f7a8b81a36043d73373c8490c03d2c8d24943d24d40a6b504c5da3e99d23ddd767c46dbbf79bbce67ad06e470b69c0960f1b24b32cabc01e182ade6323909129d444ed311e5828a1fc157c7936fa2ab3b5953e332201f001e7436089fb18aa1ad1c2f1f27d4f457e1c75538b5850a23e9e6ec6e3af8108afccf0b55c6981fd5fe535cf3e6d605dc41c3c8d25f130d4d69ee19e9323f7719579b7f20062a9f87a7d9c8ffc58282aec58beaa761a02d5501f913b8fe8d8252b031c79a962e343c33104088a23700844bc7d4cf424c48aded06564de13ec4a9c56e80b9f5d9f8e69cdc8099295c97cddd9ede4cf778cf9223eabb7b170cacb006d041bc15daadffcf
+TAG: 3832ad48d8ee2e798336e6ad5ae32d475608873bd64787146d6459c3d80fc2ca
+
+# DIGEST: fdb5d6bf2dfbc87415f4ab038def33249486f36e8b73ef8f41b8b6ed483222dd
+KEY: 101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55
+NONCE: ed8b11534c870dc695b814bdf1a87bb1
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57
+AD: a74706de4b381c692ef164
+CT: ee58a0617fbb1606aea5301069bc938fc81f094e25cf38e780bac0c44b52b76d30cabd1713ddd212fce606e32fb265a8b1869195fef9ce9cc01f1255bfcde59829265f4910402dfbb4bf1a6beda9ff94f6786746cc5958118a7d6f5a9987bab98a9634ad0c160ca2d51b4e015f5326033431013b1a82a94afa15058c5b1e95dc597a4dab3686abda9c79461b4526f75f829ce5d2c514288dba339a8df969296398efa38c9ba3d1a93e3acdbe111274bb654fbfefa29b2ad7940b1a00c3701957ae3312572424cce5f4e7d0e9ce98ff5b6efdb6774dcac18d25cbd68ee337eb6d52605ec80350e105ddd4407b65c7992ab233cc2556de9978db7609e8631f2cdbe6ee143d4d482b9e991c4c1753d16397ad3fab7d339ed69dee0aef01b9ccc9b0c1a99cadee095a405e67729bff12e9a45fc4406582a12705dd83af918aaae6af34b8aa0eea74722293b7e42c08a629d2
+TAG: f3fa2c7a0ae134a6f0e7b1e3bf342d73bc3366e7790a2d422fc3af0b53dc2bb2
+
+# DIGEST: 4b01d6fb213b1664440939ee33e8c5d2234c67ce23a0a398997b14fef5418961
+KEY: f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c
+NONCE: 870dc695b814bdf1a87bb1052c6755a7
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b
+AD: 381c692ef164101b89b476
+CT: 4c54ab4b4a1fae625316fee27e03c31704c9211fe32419e6a6db157cdd8450c7720981bab227f3ab376dd7504dc2506c2b20771cccc9ce1ec71a7691b6dd05af30631bd3022a5608f0d031baff73258ef25914d87d9fb89ea29550d18aaab69a14729ea131ccf979801a6bfb31017d25f3ec0d052b33d340d3ade59a6d3e234c05bd232e297b95f8bd57388a378e66bcfdbdd10a425c9abc92590fc298fff3f4c23df80597d6771f226f52e5c8c55deb6f5f80b2ad6ec4c5b1d61ba8cb91779cf117fd5f859f63b28b22a95a26723f38d534c8285896bdf992d15b95fb6253785ad777f069b00625f97da055a828a5b5bd0b8faf6084f2366a80684e8db427c90b46cd027b6a882a68e8abf96598391735b6ce324ac29569a02af06dacc983b22f0914e098ed714e434ba3f0087f6cbdfaef5fce5adea93f346abd7b01f5007627de8f6d1090b9dda39751f7b1523018
+TAG: 96eb8d6b902063253487cfc6b8416e5040fea881aae069e8be909902ec0f8999
+
+# DIGEST: 0009f882f7e8af026f9de7a79f59f654252f154d073b36bb640d9bd070ac8f03
+KEY: 520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b8
+NONCE: 14bdf1a87bb1052c6755a7a116bfc909
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef1
+AD: 64101b89b476f72b27f06f
+CT: ef1b94d0eb89ebba603b82a788afd4b0c26f219337e1058e1dd843dc6be6cf575006f4b5763d43f501b7cb72ff36e46185b6446cc3c79456b752c0ba7c85a27994951e222e630b015a95ca33d4cf998bb5c928a642d717a90a6cce6de0898b2579bedfaaeebb10db3ebbd4cdc99fd0636bce97043b81a86447785292ac1ad17a93829a24eff6558f8f40c68810ccdb3c2b9af1d3d41951edb77afed4db9268f6b2e2ad794e6bb757d3ceb24bbe4783fcc5d18c7ee4a5d78ecb7173751ef2fd070ce0cd71fa8b2090ff82794acd68ebb98cece31d86502b75d7fbcd33264289b66ccb4f9974af84d3e3ff97378dd86de062b7fc73a27a4a54e443d0850b026a0c89ba9169058748b0ca3786d072c45778497dee64f9be58842147b0fb0dc7e326b9645395a0a3344ad7784a9c22393f9bd2edc60607eb8fde43a9a5759c718d84f9d7250fdab459eea1404bbd17d56bad
+TAG: 055039138a1563b3e59a0e8eb8062ef48736ad597126b4f9a001e605cdba9353
+
+# DIGEST: d46a7bd4a3a5ae655563611d004ed51ce2eba538b78c30b4cd4a0c1d82e3bee5
+KEY: 71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87b
+NONCE: b1052c6755a7a116bfc9095da49db3d7
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b4
+AD: 76f72b27f06f520c9267cf
+CT: 89b6396c1ed681495f33274d436d7b2e76d4acec24018929717f6c1613c00b12f3c78405a8c329aba33f5854100db498ce9a15a0fee40ed0fae2bdeaa0a272272da3977f7c97935e08e27f6b5ff3761401702321029159c254edb23dec0b2a9851acab6131265b0e86da5b0f789519e8780adc531112159269f99d073f81f9d947625f2ac60b8b65f896bf0c9eea00114693b44a88b89e3d2a96d20ce2b47ccaf56527569dd9bf746a39d4ba38412dd1187cc0053926004216cb8cf90b11faa52cf4d77010cd5577a0e586692b91513ceb2dd25dfca0a7ca87fdd948aaf7c4d27c0882b055440eca0623093a880286a2a622aabd55aa60984b6fe5ecb096f9d0dccfcb07f14b354559151e830a56d0d0818d5d98e772e49bc1c337f445cd6cd1c0d840bf3cc045f9368c310ebb104cc0680f8325a83bbcf3c6428f7ce408a6def505143e3c22752c5ef47623c9df3d2c
+TAG: 49ef0ec1103ba7bef24948873dde9e6c63bddc45b37aa93a2d55309db785d6df
+
+# DIGEST: f25dbcd1903d7e56eda6b3f29a4c673e9564c7275b22ad278b9ff23c98499ad9
+KEY: 9bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755
+NONCE: a7a116bfc9095da49db3d71f4b975c5d
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f0
+AD: 6f520c9267cf71408a4172
+CT: 3bcd449e3b5abf0f7810d6de4ed80d9cf593f6e7648927049e6b62e1f06576455454c3469e4cfd15be7b640209e1211e66469edf0da1112857824dc7c881d42464c2bff491a4db8e55bb60f8bc6abc6453859d4b23ed978c677d32ac4c118d898c121044cede1847c264716999cac4d3179732ea7b75f4d403d7f56507dd91074033bdcdb95c70da57ba8f87f9986aee6a2616aab1e1e07ec4b195c80161ee1a539e50eec064586974be81c2b4b49483f72e867737faa2f90a1e2332fb7d69f92d7c3aa4a45f2971c2175f126c1bd0458b5e380b246f2f567e254cc45d80cdc974dcf08ecd58426056d09d4aefec1b1dc0cf7e9521dfb2b4ff98bc3a9334315ad5c6eb81515e329b22480f2a9cb6cbfbe857a8a1eda8ddd4fc7eab9cac8821a67cffd16ba4acca1182887e375e012438062ddae6746959af3465bce163f87b45da0ea41fa70b62543ae4c10e535dc456bbc1041c93671fec88055abf1b3d626c
+TAG: 6de91d0083a26e66de60b15fc20471e71639748403768bcc7a673115672bcd14
+
+# DIGEST: cc3ca713a3d8ab5a06b5ecb827842cdfca5631740841a1dca516e643b88275c4
+KEY: 72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9
+NONCE: 095da49db3d71f4b975c5d503f478b22
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267
+AD: cf71408a41729bacb5877e
+CT: 56f0ed5d72c78eb673a9dc74e3a07e38e0a129a37d314fd389755437bbfee77add0aef7253d2a8a62a0dd37896b36aa145f80060503ea05e79d71d997d1d1f02f9bf8ce1bfc1b37c18614a7513d341ab2a32195840c57adac846ee46da06fda985b8423c564619bea72482ce7b617e156c221a98748851996bb7d270acd49d0aac70b3bc5ac96b6a0825cf032be8253db2a6524b074f332c0a6f7c0a69109cd61984638005331f3c18cb814e9e1c8d6f3ad72bde4fcbb56288a06f528815b0edfca67c243188dbc62367a9a151628797f2987dda36bff45f676521b83927e9ca6c94554c45779718787b20fa10b20239223a4b61488f542bb6dda3aa6596d4bb1ffd2f48dbf1ec6af83d12c2b2a99996b9c9d61a71b0172024d4ed9c02c7787e23ebb4633da6b0b551803823efa3e416287b07a29a17777bff7831e7840bbbf8a8ae5a20a5edf1609ddcbaafb79bd3deffc85920368b14cae5aa51d11dd47bf8
+TAG: a3cab635c536a0da4751b61fa192f9cef30216e37c277c182a4cde2cb7f6af24
+
+# DIGEST: 2efa7638ced4eaa3cf8c0958b383f52fcd3f088bdad351f534022d5855a7c2b2
+KEY: aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3
+NONCE: d71f4b975c5d503f478b22dc8253bee6
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41
+AD: 729bacb5877e72cdfcfa76
+CT: 5974f57246c01f8fc36807ce0934507b36ea66918224a386cda9b3526047c184da3c68ac400a2ea3f88e481deb591b61ce4c727ca1c62cbf7008ccc69df0da0c12642716c636f03c3b1cbec0bdeda5b7d1190b011fce07ca94d80eb17ddbf97b91191fa020cdd53a5c4bfb7380cb00875ae4f7c1f2e8cb49d0c45360d11bdcd07d14367542ca9884f4c276f75aa24667c83e31a62842526d4f6209c5eee8e0cb74f09440a3f31b010149c5c2dc9f136f172b054c7d9cce3ab5e259e366669bd3d059453c906423a1053f8c5323d53b77831e16d2c9b12c8605e16a8666acdf6776179476d56f50b48eab35c2f30868bebe6c638bb8fbad47484814d6767daf5af3a8142728f96899d2aa27171fc881d520f705f7f8bc70eff7ea14cfffcfa599f4d8e67b7922c58d040db8fceedcde04483a6a25e5721f72b15eea35039d0da49ac5b2061c38321f3b11d2f57bada5417d75e421912acdad6b515b63d23935c7
+TAG: 8fa2f1b17aa784141271370968b1d1bc768dfd78ffbbb310cb487e654ccc4743
+
+# DIGEST: 21551f1aa2a795b508708c2601585cd3175588f9a422dcdde2f23441304602c6
+KEY: 7c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c
+NONCE: 5d503f478b22dc8253bee6fd1b174c30
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb587
+AD: 7e72cdfcfa76aed06707a0
+CT: af118cdf54334cbbd848874ec93799e9790fea4b8f0823d353dbe0e1bb6ed582ca27807523ee2e2aa442c511f542df073883db7140242be5ed993ff02fb1c6eac37fb6bfa657d946e2ad81a2cac58aba20b40a71860c6749f6a9b82a531bac5b9eef442ce306c7f12b2cc9b445e9b7f1ec0b43c3e9102f95ab344a1e19c3bd6df047784065a4d7862fd77aefa616eb900b210f413f269bd66f2d542c31828e23b4b6a31d53c4bfe394b3a8dafeb04f72c03b547d5fcd41ad2ad3515239b1289996f0ba0b67cb9ea07bd8dfb1588f8dad9ca384f5ab8e8cfda3650392f6443ef2f2075fbc8ce97e72d54dc4f986a12a792a20e6b48db655236111c15a56876f636d1238337b5e6aa22736200087f533927a68c8f6ead0a92d058a99eb316cf91808ae5e1c7538919f72e048946ce9ead9aca7523635c8935683e0396630401ff670766e45f6963bcf0ac944beca23bfff92b3bd712578e26bd9f2d81456f0c3b638ab665cdfe1d46b9e42c21ed6ae55ea
+TAG: 2d50c34ec27ca8f299f1289ae63017592b6255a658fab68b8951ddcc24021a04
+
+# DIGEST: 37f283859e4bea7af5e11b877f34e06e20fd6b27cb847257df50c9e1a003e4fa
+KEY: 19fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b
+NONCE: 22dc8253bee6fd1b174c307f01be95ab
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa
+AD: 76aed06707a07c3dab6997
+CT: 869c011bd439d023d4fed918373dde28d548829027a7f758043e64d86dbf438693db526434c690a00318f752beb28557a9562973db2512e526c60c5aef46faacd2df324c69b3a43bd62a83d1680c7357865c687c867dc3f10b05a691f2075279293450fcd67979a3edc4c50d48d330a089487809ceca8ce79ad0d5ea53ac740a3e5973e9ce2e7391e6e1b563b41f0c0c76d472ea80be1503e454ae5770b7128b05ed554b381ad5e4befd2d97fcabe82b83b3d62b62ceaf7e856141d73bf14f9d2e8b19ab1b50e5e91601838ae508d30f3ab3b4a9cc893cb17b35a41e337867c94217dba34234e77ac28b24622a4fc6a4332a91f0a461c33653301c7556fc2650dfecebafa6b6598ba6bd2b8bfa90b934b57285f7e9f8be228649829103260cea7f6d68f97b839b6471a9da3c32163da92328ece7bc1ca4b7c1cabcfdfaf272714a16bbb4733b0f8f6f2d87ab8e3cd8ee708920d66cf721640795ce65bc15898e0f5871dbbd940825165bd930e34e62e1
+TAG: 6e55635e08d69e398d4edff20172fa345f3f98a40d50ba63be8bd0434a7fe986
+
+# DIGEST: 586951e00b7512419812973a96112da62fda6f2e20eb626bf24b1b036b9055fd
+KEY: 2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253be
+NONCE: e6fd1b174c307f01be95abaa9bee5857
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707
+AD: a07c3dab699719fe882eee
+CT: 61820a238ed9ba6c408057511e95bfa9ad33e81be5219d9031265b258d91553d72be5ca490962b87f2d90cb77f8edd152257b4e2df3d8788f752256c5eceb25fda798fe9aad0c926bfe2795e35c9b5706afc0fa9fc5a9178672170e802ab35534fd6addda50828c08477ec39b1acc88a587aebab18cd4de8a6cddf89a44371557d5eec70d14aa69d29f94679856e05fa6dd0d8326fc73f3fdf7bf895e588f6f487e1ec4655e3e9d5534ef572d5e23a618f6a97e6fba5a8d7001279ea62a4370390a974c06c4c89a0b654d33987f5db250d6ab6848b20e6db60cf72a83c6f8da630beb4c6aaf7052b76f55c5ee2c94bbfa12263e12ef461266ef14dde6b129a7092808d069c0656e3ac5ea54654fce4d9784322f1c51845b151f22bea5399ababcb4615c04ba4962c7f18629a4eff5e7f5aefebc13be98834c9f904339c89634e0821b67df29e2cb99f01bbbd0d869436d8598334462b7d32c6819c6f155ffda29ba5703cbc4c0d1e6575f57bd9e82d80
+TAG: aa2b8f488b9df4ab0c41f52f5046c6fac1f8bc0a6129f2a14f7fcf26eba6aa51
+
+# DIGEST: 8580235e581735ea2a79cd995457451b448919d39cb40914b7a100d090f5502e
+KEY: 11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c
+NONCE: 307f01be95abaa9bee5857772305daa4
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab69
+AD: 9719fe882eee2fee55ed8b
+CT: 4718d7af5b1392d6bab2f1ba11bc86d1e1f8cc33a7cebc244282d85de9270567506a4bd0e0ac92061cc3d58a68a2fe55e32a5bf4c2323d114a3e4a27969a2f18b54b1b8890e2300584239dd17870da3d72fd7418fb340cd07b323d2de6ac4edb1235b161f5418e839e8973d1d13106d90bf0210b5a06f8096033687a2069780ed63a77ceeaee39ae5bb1d95a504e2fa398c245be136544865354a94c0931f9fd80653f5e5db7bab8d687a2d7878653466c2a46e124802ab69acf07947f1e0082792c0e4ac3ea371638fd18155b7ad5dfcd55b962fa8db2c9be013cadf7e1103f4f5c2398ee22171833f7c48513625331107cf35933fd37079cb7a531d87808452641bed0a232546ba304726ed825c2ba7e53cb4c5dfa8884d9836a9ebfa94c0ad470ac6d95fbde38d744cd7639edbb6b82c3c090d5dee31c9eb8666213a6c43fd628e751bdeaea7496ae966a628644f2899bdc57de9790b4a35334b72cf42211ab73692508a9a16ca97434d28bb91f6f712006d68625233dfc39c1dca528279d
+TAG: 1b0474b104b5095fdf81cca5f962acc3952a8651e51ef455aae0752f9007dc0f
+
+# DIGEST: 4d1e0e78f6347b8ddb4e9812cf4d68920ee35a2d978cc68bb75d2c3f334829ce
+KEY: c695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95
+NONCE: abaa9bee5857772305daa4b550d75f05
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882e
+AD: ee2fee55ed8b11534c870d
+CT: 246989bf9e23da08a285706a95a0ca32119c13db5b041e0304d1c51968293dcbe5f90b6e101d37f16930e8d409cc40ad0f549b549a31eb5e81a47dcf2676cf576a645f4df9c787da5a909dd5baeeab5ec65d16c812c876e4c61af73abe1f42b57cb80ae31611a53d133a6554756762c8e336ef72bb0e0cac5d7c68acb6454fd44b536f182b5e1c81d81f1a8c0c3b25af6a2aed4ef735eeb467b72e8b457e2b91fa77012949b984d568026debeab487d460c06c369978a4bcf37e721b60da34c0924ba8b840e6908b168dd69470bb46b75fc542a3297a252162748e35943dac0f0e6fce1d9f7cc5c03cd4963e7298f390d1d4923a0a79e0d2f8570491de5cc2b8688007674b4f5bfd7d136f432b8e0877cbf65ad41ad80950fe3426ed226efbdc853bcc6411ef07fd502dbbce5eb759cd6df0a2fe1db66f9663d64a554fc2f7185e432551cf047fd19d9122e7153bb6f01e97e817ef2a1fa2b37e5712bb6dd7950a41e349a111be7a5012f8f50f46844aa1ee0f24c1369448f7e08a8960b1ef64
+TAG: 8f49f26447273a56d30315f3bcbc9f280e952de5bd5ed928a9e2c4fabbda367f
+
+# DIGEST: a86fb2801104bd81851682d1541b44183f740d2fb6e3811eb614f0e3750802f9
+KEY: f1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee58
+NONCE: 57772305daa4b550d75f05d8089850fe
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed
+AD: 8b11534c870dc695b814bd
+CT: 3f85d49d203f8fdc18636f0ea67f03ab1da561207a8409eebef6002f10dd0cd05d1af105e75500e68614a76b08989c333d5d5d706a318f816dd36722e31183e48a61e36139b1f04023132a0e720cd586d7b9395c6638d824804d87ff5ec728500818bdd58b5d991e37163eeb9231b0310e11230bd52da012a7baa27560162347766765bca5bd2ee22cfa62551bed9ae93f43fec0650c60ca09f6528afbc886a1e1cf50b087e6c6137498ae8b60246852471559f1e33002bdbdb756344f0a6a816f669af0c22c61e6eb7a07bf0e84e6aee7d54c62c6580387d4af038ffb8527b651a67093dce6e92c2c7168d0da868715b0544beec36eb91632290cd3258931dbba267fec08f9e074eaa69db1b5ebdcebdfb1537489e838de843d3efe7be10f27e9524654a97b3cad3fbc1c2cf9db747451fda6fab89def52e27b5d40e538f89692d548d3c24bb59e2ff862c69507c4a476bc45ec319c84d8355712724d8e00c0ccfaf520eaeb9894c894e6cbbced67820bbd2a0ec0a3b70fc6f5f346a4767a50
+TAG: 4e53991dda80e0a3b66720ba6e9d9d9271b56e0217d66f4b17bc2c76de321a7d
+
+# DIGEST: d92a6b7991149d98e5e23a68619b06a3f076321a9c1918b4f5ec6c0878636cce
+KEY: 2c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305da
+NONCE: a4b550d75f05d8089850fea3711265bf
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c87
+AD: 0dc695b814bdf1a87bb105
+CT: decf7ecadd3753f18629a14f3409ec1cbff5e07e82680670ccd27315ea7d0b02e3b890b7e8d7849b73345940976efa42d6fee9335f55d52e7ee0da15cc455043498409b07c773f1c34ff956c023f53751945dae69069f4d930ba2426e055946b7876bf262528e24704e7d5364d950733e3a98b54d4f66e76165019dc0842bb374034a7f45a0597d46bf1167affd5a5f085bceed27edaf3364e4f010af08ddf6d68432c766d5227468970947f4a50911973f09ec1aea71d718745b091ee484f1f34f13199982b4a0f178155946d89284f40dfe45413862f49512466d71fddf75e8668b077856a782184f05c14a6328194979966e57fdb2f0a262bf9d9e65aa38249271ebedaf9f6c9d2c57007385b5539903dd0f1df1898211f24745d2021453d66faed65e5ed37a4ef3362872ca8d62c50bcdb44fd8f08ace50199791c3261b4b49ae902a6b4c292e33480d4ccf472a590c92e54dc51d56c457e6105103394c6e404aec4b9ceaa2051346f3adda2b620d17ee6133356aaa197b418025b41db6a69b2526b500c980849fb6ad117b2b4fa
+TAG: 52681f3b5b0a5a19baefcaf17d404b595fcc8628df13579fc7e69e343910f732
+
+# DIGEST: e6922faa85d6075991d02e503c1573c65bb97e4ff4a967f1f4ec2e8771d059b2
+KEY: 16bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f
+NONCE: 05d8089850fea3711265bf782610460b
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814
+AD: bdf1a87bb1052c6755a7a1
+CT: dd089a8a2f6f2e43f9c1caadb3fce5d679259fda2164416ab5e1a71eaea70ce83d1b6dbeeddc0b7cc9537218e62ddc223ace1f90ed28528cb0c3a611a5d7810a06171259ec5a65485420a2acb707047f872cbdbf35f7435823679c96d3a50ad04a6c432e73a31c183cb4fbae1d31b1a27e8607e2c12536e804ec6dad1668cca6fba18d57afd481e9c0a434ef01dc80664bf68483477991ebeb9f121a0687a371df2a649593e8249f7ad1a4bf10be8317e3d84362ac6c4ee6b95215dfa40111f5c1609346359ecd452ab1cce3745f316d685d666542f3b08aa6db029f202bb57db68ff405ead385e44acdf7bb663bcc47b6082dc836156006585cda9d78d9030204dad22c9f16937c99ff35f59dc4ac50aac853b0d9c682d3e2f25dd1a4ef1e12f6fdf92479704a3aafe6cbe5d3a23a91a6c03e0d019a1d909a74d50551b59691764d6d8edf448f5720747828ecba57acb854238a007ffcec03ac902b14e73a98a974a353b63438c4187432b7cc37819230a2290ad3f419ee3db4e56cf89b99207cdce4ab7823d4e4c65d7572fe20102e
+TAG: b95406da360486831736da873470698916772d723b5df29b69e3fb561bab9692
+
+# DIGEST: 41edbb0ebc4f450655eb5a394e9d7b3bbf76bf761a69a1fe0096149595e8f108
+KEY: a49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850
+NONCE: fea3711265bf782610460bfd24ba022e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1
+AD: 052c6755a7a116bfc9095d
+CT: 51bfc8342ec0c6a9b42ba6dda5bb0d137a55b647aa6997a85baf698fa18b63104fcee88ff18c6582555e4b29a1c2416e21820a259267b559d73b64ec8feaba0f042040ec8f55980ce8ead636e49b2715c680c9d7a4bb4824fca77aabedfd50119fa11cd9c458fb1e3ecd9ce685ccf5f1d6984df409e0dd33a63cf40c8dd514c8095543a1e725ef20dba3d7c79e6812f093eb8c0c0e08f8981771dcf992c0b77dbfdabc944947e986bec4d8ffd1601980a3e814590fdbd2e4a3fdcbacec76ce50bab1be70d661229b4e5d2d2d6b52f833e9bc67edff98cd6dc50065c439916c60adb73366c6422bdcbdeaf16aa8b4cd0e98ec2b6747b8db8af9d1c046eb5be3d037e3a57c3a19e1e497870b9393a8bf9281a1cd2a8e8bbef12e4287faa869d9b724f47b8348ab5be58583b9b365883ae7d3314f190dd431f17f82e38c7fd5661a04ea8d540bdb4d98a4e237ee563c6c2e0e2190abf6743238d13c9525d24e93aab2c157d3202b775551d178b708d7f8f8974ed0fa8fdad71902bb6f0e3ab511d74c628a3bc3eabdcb7db8736ffdb52044
+TAG: d57a132dae800f43ab885aeaa77c91a0e5b131a6ca77674fe90619467919491c
+
+# DIGEST: 95d5f8dec296bdc99a258ebf22984ae9a317b909f128f0c954eb6a2e2cf4abdb
+KEY: 4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265
+NONCE: bf782610460bfd24ba022e6da12dd4c2
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7
+AD: a116bfc9095da49db3d71f
+CT: 5252da63ccc0428d083b44c764ca93e95e966b7ccbf08e3ccced4ccc62f6a79c27714fc3d029d6551704d11281ae1533d576b0154d493f6fa5a85a3cdaa3a0aa433afd836d037c8d54828f4bf82b07012fdf8b1f764b3b64723f2867d33004da014bafabf8d0d7b033cf39b8e1980e8f4149ff431bcd800cc5c5c95f24fa305a33d944e1b63b20933f5509beffa6ccc772107b691b9192fd4f130d5c053061931f6dd352fe86793de84abb7b71afef3310fb6b326de39ce02d8a486656dc87c9df45b88c44a57a9a73b8f022360ee753f8fba24d46d839385e9f42060c8ac1b637f0e03891351599778eb69ee5795f815685e8b0f7780951b99fd885b3dd4b161532c28b947d9ad927c842571e699c9830e69e7d94baebd5f4357de29ea281695e94f094ba38188a077e3f8954b5c9c96d8619a4d29934ddf65702d163469aaaeebab76a9595704454aa2900895c7ec0ed10e3be5ad6e12f65d35255d960d7a3a4ec2ba2524983ca88c19d2ef26bcecd1f2a4e35451be6173d39ac8aeff57b0d3564166af79a572f683231ae2c3e3c2ed137d967d1416af4c185209d1f389b1d
+TAG: f9495a0c970bdf53474cd21da1c1690df46fc5f0257eafb7c53c614204dc7c0b
+
+# DIGEST: 1593e69acc71d6f25a85caeed987c73d9b86e132ec163fbcfca267eea32dee44
+KEY: 3f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf78261046
+NONCE: 0bfd24ba022e6da12dd4c27f43724809
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc909
+AD: 5da49db3d71f4b975c5d50
+CT: 356df193cd9ed5320a8d1467336d95adc76958ebbb773ae361c821e479cb24e536b508597473d5157e00f4a8415c577b65ec19316aea8a599b6ad9895cf7feabf61b7335b4aeb410cad40a230dfa75ee9ae3cd2c985b8d1d7334d7a74c03afb1d4276b84635d3841818657e0c353a4d9ec48266ee465f66c513d70b38c02e822e91054b556824025eb02e8aca19d62e971dbec19b968ff699f9ddb8d816a5a1a69aae17a97246be1939e197bab17a321f6c924992cc9abe6d4559f51017e1c8fbe3288ecb1d60286c4bdd5bdfd33ca8fc4b9b47b0edd9142d6ae3195bef14b5add88fc541adfd53781ce6b9e94f4628ac69075212142f99563805d65e2c9c660e4e6bdbe566d8655b611af5d0a58d5445ac6fbf04377e24febae3f7882e27c340ffd05298a9c159fc1819d4b7ccefb78a8cc62a66fe616780155feeea4f0dd6ee590d40ad051f0d8682c7c3321a5096d64b2c2631c868b4de0de4470e2657024132cfffe4fc9ba8b71bb21691a1368072d8c0406943a269c18f5d5adeec448e2beee885adccfc9bf0584ccdd7c155cf062473727ff199f4b53c3e902d3d9ff5a
+TAG: 858354db2adaba8440cfc7cf924ca6a93fcf5243c99b76c656823514b0807c04
+
+# DIGEST: 540ffa937f22712c877648c744b15846f3bed2a73b41aa1f2080f3cebeda089f
+KEY: 8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba02
+NONCE: 2e6da12dd4c27f4372480974454879c4
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d7
+AD: 1f4b975c5d503f478b22dc
+CT: 5b0967effdf0d8e9e642e6ea489ae4dff843f4086c18e31888542f69f9a37ab257ae682343a1e1172343274d656ca0c6714c7a41f1a60177d27cb9a6e5e0e2786232ed761af93de4033dc7569b27de20dfbe84deea2a352717c94a6ece101b9730a1cbe2c17f6ade46375ac3692db56daf7eb7719b349f0f9bb00243d8323e23e22e9f740e611d0a25196450c38d1d6562bf9b2e60db82c5c6fc5f2a54a42b5a4f6695559bf873cb2ef3cc389b02785dfd3113ba954f27fc0ab115183107caa496cab195de2d24a3996ce9ba754e9df4d71e398595617b60c058c6463433a71b6b1745e326daa7a8b5524bfd23bcd9ef1e1c48381fac64755fa9baf64d3e3cde4f8c309c4e00c2ed711dd3fc33fe432c0f117bb70b295a0d05b57e4707f6a1708b9bd3daffa09497e91c5b22009c5717e5f79ac57d234899de4525bb6795adec9b7bdec38d6d62a0c90a2cbbd1e07f582577b6c1f4391aaf84ad55168a12be57f95f0e3b07b13c99e8ab3a5d182e86594a0acd4558f8d0dc795f160c7359974b6ea4821d4cda5d08b9d78910fc572fe0ac27e32a9609e49df66bbafc8c68fa39
+TAG: 24c8df384fd41b79625d5c206017cc3dcbb9a1f7cd67cf38f005373d258248ed
+
+# DIGEST: 03f6fded63d608230f8fa271ee0433ef627e47a84608ac20bcde586dfd6fea2c
+KEY: 1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4
+NONCE: c27f4372480974454879c41de9ac9f98
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d
+AD: 503f478b22dc8253bee6fd
+CT: cfdb3f96a86bbaa4ee5c7fc2a1dc5f31dd318efc8516dfcd7d943d4cc413c1370e1c7f5989ea26e4b540b0603d6be14362a5aa01447f87182859e8388824bb94cabb139ddce4c1782c65c32fa023773d7f48ba3ac7fd6d5436a148d77d8b69ec6d6ae66c7ac7237bb9ce73c8377994b960fc33e9e3a2f412e3009b6d919d7c1ef0d03d460c8571183785eba5fc8641b39859f133a18564e887df982150f36d970e153c3a7dc5a8d73d16920d1fe973836a7fb31001ccaac1198037ed6956caedd18a2b1c0af676eddd4dafb9480e18ed186d7d18817918c6e89f890a2c96b96180e4e233d616c010c167d996bc6b26eaf1531195d0b3e2e5a32ac21a348527c062ab280b94f49faea3698dc73dd03d1282eae5956979a1b69a3e326fc743b23ca5540d50a75065089d05b8a4d9b2f34f171abf84cb81a856e6e89599ce793fc1c0514da783ddb5a3b6c26acf1b248c2831b2da789a6c5cdd8ec7a159fa172668578f7514a2f4e315a46bef0f66d43246c9f725eec654d3fd9521440e22d2d22abbb94c162d77c85da69912cb1c62679f55dce5eb3bac3b5f1f2543dc68f5fb9f
+TAG: 4364ca8c2449799b3fd98300e404908f71d910e20c0804cd6857d6f8aadc6f83
+
+# DIGEST: 9c71648f64c8ff1988dc25488cf958444dd430503dd9c13e62297cb32822917d
+KEY: 01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f437248
+NONCE: 0974454879c41de9ac9f98233b5a7379
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22
+AD: dc8253bee6fd1b174c307f
+CT: ae0bcaa9524e7031f2e96c099ddcb3fb88fcc4e9b6ae3494d75d7189a6de91b5a3555899d83d27f669c6adc7f05dbd208743846c26f298206f2de72beb93bd84d56c6f9fc611d4e3635d3382cfa0b9453d03ced98c7ead57b349007f79e24eda400beb5d652e55f83ce17e79ac5a9b79063befb737d212d56fd9ef633dc7bb66cb9c4dfd92f46e453ce158ab4a426f93f2d853bb5a9ebec2b3640097b8d472d663d2b3a3308221e16bc6e8e681933d03aac0216188e0ee7c4c08fa098848f2018e7dc20c32c1a219396ca2209bd8581138c87f7fb2751cddfe1f4fcfc1fffe00bf9ea32edfed9852478d5bac5bedcc722833c3b3245c387b6fb863c86e3b571e8ded09e203b3dd9612980bc97905bc093443a02c12abb2be29ff5ba4b6b940110d9fa57117f64e0753c8a15c1a6d479142d372920a9d780e860f50a89df7c3822ec7114944a24341b7e9ff4b2a97f0ae26d23ad4a7600d2243a7bebf5ad860b30aa83e71ff817eceffec437d29d1f9842465b7945504167c988bb60906032541fa52421f86c97d32e726d13c92c09ae1d88ae91e80928b23a2638215cba642535d04662749e956fc86d0e38d43c030b0
+TAG: 7725b4a6b859525fbae44f1e5587c296606fa9342b95c7ded6324d3b617367e4
+
+# DIGEST: 72604fac954211a22c7f16e8ad09175985a5232f341c816e11e203de02061d2e
+KEY: 9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879
+NONCE: c41de9ac9f98233b5a7379a561792c0f
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6
+AD: fd1b174c307f01be95abaa
+CT: 3e6e666cfd39de318102e3f98e534f4deb2164574a56f97a5788c936bc5aace45c916fc73fb831aced2e82704231ef551d32ea8e10ca6240042838a06641745ec0addb8ba877f92eef92f88c7c91173314c6cd2420b7a4d8467d01aa0beb3c1be9a236154b007b7d151ce935ce2b636d98c1b11c1aafa16690f6abd5d86854a0756b454f339c7c90b30703faceee875c629a1ca64848c2ac75e31f27441813a859e2226741fd0de5c225d1c56c7ee9582326236f019ff27060735387bcc3c40dfaabf14a9fbe545e8f6de6001b9ddccdcee18916cd9987c51277839046f278df337d566c8563abed284452508056503476979b5f6046c91e22907f74ad0a555d9fc9787017e5dcd2c5e362e41736db3db6408dab82346d2e0455e87d797bcb4d64ef10082043b30fc29494cd3ca867c1dcfdbcfa63083d9d3c55c8785641fc4e73f94173fa424be73eabf54b94734ce8c39ee0a98c26827794f7a4e31ae3b1954ba686b41cc685ab7262e5ed238e392aec646e8a4506ab916f1f08a9c7e54659b4e15be81f564a2ce541d57357c5e33ea903b64748ee3872ccacd235cc4b18680d6ddac246515ddead35fa361a53aeb1
+TAG: 499d77ad1e5d6876f650413a4355985b3fd637102a51dcbbdc621690aaedb071
+
+# DIGEST: 7fe6e8386faec373ac58fbb0849aa7b9e96d3de86a25764656756970c7e6f5a4
+KEY: 2305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f
+NONCE: 98233b5a7379a561792c0f3116430e8b
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c30
+AD: 7f01be95abaa9bee585777
+CT: 269f4a0b75351768ac2a5d7ea660fb9533f1640fae57c019f6c257dac6c2bd34e30205949896eea53e6e10bb6d4706ded408450289ba469ac5344a582310b19e3ad2e64dc846abeeca1504ba38c25bc75125b41979655dba49b6d63cc5891292fd2fe5cac2b32936a14b9318f22c3d235f072acb5ba4df29757bcb0c1afbdc025816ce08da637407507ac456bd567e818df78a9e2810095270a7ac1c917ca987645cab447505010a4d9e387d25bd8155167f1eabc3fd1a95c35138aee4cdec540e17f6d29f1308196efbe1d691160a97c85d90b55eb1456dc1d5bb12af21ca934b92d78b00b9a192a4458375427650d745db9ec03ad89354e332cfc742fc01073476d2f6a657f1e3c7d5cdd918958a3a13c772e6cb47b00eb2d1045006b6496f711a539f2e4fb1a38a6b5f652da5df879a6c2b7cb460a2197751b85a3aa994e1640b0fe45651d86180f1cf7138ddae9129032d937c7ce1b8cda731df0d4a606d1573a58839ada0072a695935855d7889f6f7c33ca80a781940c787b5138647a4e19f52e759a414d8e3a9dc200bcc543a1f724953035762c6ec34e31d353587259b056d769c3c1f6473555fce3b7e9269
+TAG: 07c605d90226d9461851c8e61e5d5946fd91e3ff2b12713f19cc46f478fc0071
+
+# DIGEST: 70f26aae705f690b027bbce00098725716b6be9596fc76d97161047489cfb34a
+KEY: 50d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a73
+NONCE: 79a561792c0f3116430e8b6ea058c479
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95ab
+AD: aa9bee5857772305daa4b5
+CT: 8093c46513c2e0ab6b03f9c15d469a1fbe1efd61bca2b1a4027feaba40db937394c8a22cd81be669cb0f7b26c357c05b7c526d64eb0c70c074bce7f377a3012d3180fb10b76774ff4738085e1e27fb238996b4b990e5afcbb292273554e1663b96ed1dee25971a2cb0386ea796305a73b0371a1e75819d394618e128ff88452c1c3f3c40ae8784b67b57b27bb26cfa19c8ba74d2af1f413af6ad8b6f69709869407893cb9ed77ff6c244aab3e3663b088b929ca1efb9c8c92234b491c3591ea1cb00275261d18da9787b122f9aab8afa3d8f3fd00b99be700fcb8230839608363b14b240e426587172325cfb465795e17f267d26e7b2c8b079c59fe634238dd5b015d3a77c667f6e1ca65d4824bccc4b7ac2ef1b7a9f10effc1d2648654619f9a7497ac1b207850522675cd26b355ed221fce517fcf8a9b359b55fe73593721f2ae33da8603afe0f06f5dfb98edd4aa75cdd1799d1bc1f42e684cbd506d35a943505a5a022463007782daa1bc096881190513069b8fbec13818b934cbe1747009ca54cd90b267c511f6916ec871e0e05d62fdb9510880fd2071bde06d02de75d71c94403d5a8e1716db31c37e710ef906d3e8b41d095d93b747b86821efd4011
+TAG: 4ecde695a58f4535e8a5abb70315d2108d1903f6e1d7f77036f887930eea2f36
+
+# DIGEST: 5ce6145c80fd4e7f63dc4dfdc7c12359075b4468193169af8e7f31b8f8116a5a
+KEY: 089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c
+NONCE: 0f3116430e8b6ea058c4799eea80abde
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857
+AD: 772305daa4b550d75f05d8
+CT: 23546f8344d1b089a5557cea08c601eec43202175d5593726d6a7a03f84304c5f733a6f464e359bbf78de964647f1af4dfa3007e6c3c9378fc5cd26269cb46c5769ad51dd0dc46e14ebd286cd56011afed614b2f68720f700532d8feb858d3d231d3bd8f65a935e2e827cb0e5d167c7170f46f07e92ab9ad330fde73e20a7010d01f860feec662a81efcb79be4b22e156fd51cd2753ab4fff96f9fb537e1d05a0dd67117e01bfd23a52cd957a423a793524c779ddaf2f587bb059801214948716d18c20b088daffb95213e5bf4406a5823faac672c7b0900d8658fb782f3286bccfc3a0799338f92b7f4b31baaa8c66e57a427647cb163377b3569f852d315b34703eeab88c0295c6d1ab83b4c089e8e6d9c542117b00fe29010fc6bfad2a3d1cf160e198ce5eb8cb8d4d93903825e5c8e7d111aecd0d346c4611d7d9e52c3a74a743e1165efa1b859ac7a5146927508006f255c916444dfe721a2449e10d228157f33385f1e6cc0220963f4d37e3ba760eb7df2e006a82fa0c324062e67cb6a31bf9b66b925c3a30b84ea12ab6c7edae88c9f8e900d6abe3a55c119423fc68f465aeb124b635f9cb3ab648972789fe44b3851879ef30cc2f702a5410f7ffaa8
+TAG: 2dbcf20f40baaedafb13f516aacb329f84eb5572124c3c3baf4152be37238e29
+
+# DIGEST: 7f4b3991adbbf881a1a3de1d8e814d39e6c0d751ebab74984d41727ce9fa639d
+KEY: 711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e
+NONCE: 8b6ea058c4799eea80abde04ee1de13e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4
+AD: b550d75f05d8089850fea3
+CT: fdc0067f429184461c3d0fd9fd9d72efb5a216aba82adfe278fade3267cc6fc1fd4f5335287f3e67abf5018d237f7d7e5809d58133ba14f856469029ce598cbf80915d2d034a05de73d36db652701d8175855736bdc7591596c678f63be7f46f69194329f977ab75bbe9f9c026ba09404e1bf10c807290528c11227f6c57ced1b87c5e8b4674941dd16a697bd53aececd99ecb45bead5f6e456c3893809d08dbcfa530cfed2ec9cd550258df3240a775fa5bfd96619e3147dac748ca716ef6d0f036a3bb7f1cc5c3c291f6ea63093a5c266f7772aeee5e36eb3dbf03309be80e3d0f730e7e3ec44ce964fa106b7d1178b5dd783b257460e4bcc4d0f0982f57a565215b5c9a73bae5110dd62b75201435f6eafbb208f400c52d64031c9cb2b7b225bd29e6ef63c6b079887a1ca7cfad6db424379b6dab5b947aa61ca95ae441ba2787780906a67f1677484b809c8f93fc01d525a7f7d14c374b4c592eaed8673145b2aa0ec1fe598d969980f48cb46ec786bb4e20ee7a06ae40a2df12d7a4a5745ef689fb74aa22922ed67da82fc7d1cc6514656d878cc0b7b0f61e6ecc695d5ab71f1164004e3dcc67d856432579b11a4ab54c475035389a5891c8acd34c47c5
+TAG: eb412c25cc8df477086e79be473d74f332427577ddccf3f0d61caf057806e942
+
+# DIGEST: 07b2f90bd1fdcc17e3971eddfc2032df2dc44c74cfd6f8544a3072f821cdfdec
+KEY: 2610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4
+NONCE: 799eea80abde04ee1de13e937af8f1a6
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05
+AD: d8089850fea3711265bf78
+CT: 013e974044b859fc3eb06483c39f6c7b3ba378ec82d1caf2b35a1141f11955be00cf61d06f9c2e7d76f2867ca259ba718fc5e8b276974adf1f4c120c7d79c22e2d71b843cf160947cb90f6fff24b93ece22d3d2dde830c05e53c47d092e9dccf4077bfc9069336967b396d98c4e704f27c4064307e239590889df5077c609386719d9b126bf7b77e730c5458dac3a7db8d5a63f2e2e923880880e4eb120adcc144bed7527c25d83e9792d039e8a155df8f178174b9964307e5c6b48b93b923eb3e6301fad2946e4f474713910d45d17a0b1d7f3cdeada091caf89a386817ec633f706062e1ef07077da59a84bfcfd427436d1ab19a02465f9f4a56042624ce15364d96298c5ce91b2b186a44e4e362bb4673d1769ea21a3e0671a62763c1f5d85f4651da103d0ce951ea8092d8880bba06eab21fa111298b78aa3beba14a5e0cd2d97066d15d576033cbe09a6b177f68d14ea1e5f1ddd766dceaf590cb81933284e72f0e3b8819804b6ebcd4718ff3e686eb51cab786e0b62307d903f6dd7cea013b963838c1cdf162c72b4083aaa82aa7b0a8c47d159a7d784230ecb7e5aa2d20a5b77895ed6d431f95ef72910a2bb8c67d89c225cc1405f6e1fc203ab15b0e67490dfe5a53c39c9c21e9110674de59
+TAG: e3af82811586f3fcb4e74f4c6cbd454f1c6c17ea1235444ab3e1bce9028e28c1
+
+# DIGEST: 7092477b3a0860955b93738d9cb5e798ecea0719141d53afd0ddf57b3a6deba7
+KEY: 24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80ab
+NONCE: de04ee1de13e937af8f1a6944f44d722
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fe
+AD: a3711265bf782610460bfd
+CT: 9efe324cdca3a40c0f117de411ef935bdcea4d01c0250385e295cf1b45102e7771155883117cb07aab26f76d36972ac8048a65ed20c1a692b16a5b04962e41d8804a7a637f6b1160daea5c02daaeb335419a42669403f2819ec461cc66e6e8c75f74380a4d5d7eaedfefdd20cf51c99ad5cfbe0026a6c2e595c31fe1a40afd9a7f90d1e8b9be614dff90d32569526d59445990f2f50bd5c3a265a57884de17ab692c2f1a2e9dbe471766f5249bd287a1b396272bf3e6aa3cde5529cf2c44073fbd01066e80b408eca770187257b261d460fd6721bf7136d3af64336e553c91e047c5a64827238977691d366404f9076bae49c1646682698110be2e1f4938916394f9f8e53837939ef7250f5801cefe8114f00a3ee24e9f7ac0b1d0523463f3b14eb84b81f10906f70bdf381beccc85a6e01a0dc718ed8d26ebe1a26e171a2131ad5fc96ad7592649f771756f9e83145287b1ad71b8642478c54565e0fd5e9b78b1b5bb3473b7c8dc8d1d414afc6dd53b2152b479495c60bf01011e05ad6f0797621b0ea168055710912e4bfb88410ee5940f133cb72d4b3f875c1b3c3bd6db6bdbb24bca332729b1e778c1a70e5214b3bd7d8983f0ecb260b8fe205fb90eb5b75bbbfe27bcc7919d7253d0453484ad3e
+TAG: 41e29791295f4d2b913be55f2334e9c0c1e33e582a5c3dcc85b15a26c3e424fd
+
+# DIGEST: 1a48204e7b3e43ccb4aa1d8d8b8a655183c3881f7c3acf851e689884b2773f43
+KEY: a12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de1
+NONCE: 3e937af8f1a6944f44d722271233a825
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf
+AD: 782610460bfd24ba022e6d
+CT: f3809d379d1ecdc532090e994f337045c1151e72bd48688a7204bd68e2d70ca0fd13440e2d278a27ff900235155deda4638acf3981f3e474fc2cde7d1a7a676a2f733db9d18c69c895b71932771920fea07bc2e99076dd3682f1dacfb34fc885028c1e835816c51cf5b890226a794d240164fd17c605cac9c1192e4cc91efde20ef8100192027da79b82f06906f8e661803b1d00b6b9eaf16e6c6ed568a2f4e2955609d6b930288d6fd54ef8c95cc0c2eae599cd5a61d4e8e35b17e0c9fec1dfd00049049d137ce7474bd4d15e2f43e3ee595898d73318c5e1935be3f9bc5882b7470e785121cd812f285e4d1bafae79554b48fa9a2d237ba75aebc80f151a13142eb6c1d92d6aa6eac19b2d0bda9373d643fe35c9a4e03aca32aba5ef86d02e29f8c390cfda66c5fcec5643b253e3be8273d0b9dbe76ea63d66b8949403d2e8fbbb475e65945dc96d670aaa0a6b2a3f98431bf8b35ff393b34a3da3cf26087687e94a303b60e99542264c917fc33880cb17273a1259420b6047ceb7d451b86a829d455dd1e218e95ee114854afe0a4bceefc54a74a344636ef85adee18f535da5186507c741138572a3ae44cc589c06608a41b2ad09d4ef6699f7475d2324665a6c425db6bf92383996f6544c5c6337
+TAG: df79279058b3ca40a233eb724cf5f2642baf6388e44210d8842345afdae3b344
+
+# DIGEST: 1c5da35ac0ca01e3557c4cc38b9b48c5c90a8796a5636b7d8f8f339f17bb68a1
+KEY: 4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1
+NONCE: a6944f44d722271233a825264e977045
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460b
+AD: fd24ba022e6da12dd4c27f
+CT: 1400f0dfc66fe7ed8b25fa42be824fd2dbf22863fb4a4d1d424108b800eb717006cf072b9ebc4a2a729c82c7bd256fe28de3d9780228ebfef0cd5723e83161761be08dd7639af45c47af78289a026e66acc3a187bf91a6de89142cffb2c142e22cb61b63487889b72a9d048094a0dfca87c885650d25df5f6ae7275a000b329e748b6a959ab5894299cd70a1d0293f38fc160726ab55f65f20056e7530916bbd5e22294fa1da0c30e6d66192f9dd2001eae3c637e1aa7f34898cff9aff01dcfc80943d3554cefafe5b78bd74e87620b2eb2f37d227c4244273bf424c355f73acbbf99f90d827690a3f32b1c33e26733d8be4d4abe7b225e664951c38948be6a99d7d2c5daaf7ca8c291d38b340ade74a9f48fb1018d0732457368f07e28eb01e14e40c3c2e96a59a8e9723c668f3263b2b192c295885a95d82c5d6ef3f5d95b292f80f161d00a4284d23b2fabd461a29ab174345865c691d42ef52d423d0ff18b449990a670ba7b009aa21929f1c3acae763575eb19ca098972717eb89f6013b812af543b2102f27aefab25471fce3b82591c1ad4b9749c669c24c3e1e20b0a8164ddafd257db481525bebad48c7d1fb1e8b0464bc0b2dee2e65b0b0340610a9fe0a1c46cd70ac11138d88329f5b27beb07c24c0c792a720ec46fb8d41835566
+TAG: 721ed98e1ac88c508700999900b4c3facaae0c127c7c71d848e0605a6abc0565
+
+# DIGEST: 0593db8c39c4b86087be7188cbf3daa8bb7793b8c4eb3240aabfd91ffa2819c9
+KEY: 454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d7
+NONCE: 22271233a825264e977045318c9b6626
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e
+AD: 6da12dd4c27f4372480974
+CT: ae43709afdcd59dddd8bebd8165407fc491ce15f998a475b1379d5307a1220c953d2661e0ce5df287f2964e54dadc743ad889ea40f047f2d60e129beaedf2ab5ad6a63db081cb45a960c279a0a53463faebec43634b6831ebded1a8eecf8c7f5c7a0c2a6944f74455a5dcd33151b79bec1a6c7ab6eb8d6f4ab18d0354e96f738fc8b16c2b76e7d2ec26e79afc103adcbb051b947a14c56867dedc7541d183ecf981941bfef006e11b9a5a0b14ddff16fa013cac13853f080940bde87cb1be873719f3cc84570af43f889c5ed77ba44eaca27dd442c4e81511dc4787d503b0b8b5b6b0020e6d5e5f02a8200c97ecf5280bbb84209bc11f073950dd4e12dc07ad632e288a6eee0d7878527123eed7008491cb7283bbcdc382aa0ddfa1b3e714b43bcc602ef2aea22b605a9c848e250b0588f20a78cfd0e5092233049c190f6b8f43cff6ce5376137e6935f3b594ed1d8f0535f0760bd42e723d4ca62bd0a10dfe4d42c761ed724ad7f0db5fdf2f5c0d7e4e845fc03f18a8bde4a4183ca3be2352106097de87479c1649c19fd027e686a352faa1f9fe49fe7351e823207e1434c2fe52985c211a92b894a711d65417b13aab893b07b81f443d76a6cb6bfe953cfb58c6be86ea63a31b80a3bacaa133c9e8d3945df15490a84b94ae7f681c0d72181
+TAG: b2133f10f57c1723dbda9a2dfe11cb18471d3428d34fdf74c4cf950ee561d49f
+
+# DIGEST: ff2a290f638f41038a81fe1e1e9bf3835c0423886d264bc60adbdfc38e7441f1
+KEY: e9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a8
+NONCE: 25264e977045318c9b66262c0f0368fe
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c2
+AD: 7f4372480974454879c41d
+CT: c8f99ac7db9777b8a9b8431a319f01d23796a74bd7a121331e9aa82cf2ad552d6aab13df48fb9b1e885b9f33807c028c932d58b37056b35be5f97f9ad980c45c33f5a762e3f98aaf0982ca71e034243e366bb0f57a8a087015cf8c358fee76ac34afb72ea824627643a814c852047e7a783de5d1d7bb07262cf63628bde815f317571c302345886f1ad3f3f0cbe5506a3c72a906869cbe3f1e515b03a5270487e2506b8ff737e586396cfeaf40b16364f508c62a94233a211f7da0e3633d12f918a40be750833c273bfb33725e2f2a6d0336dc58eed7e728f727c0818a38ab508a11f095fee48d5724045a665ad7ac8d0f6003da4836d2fbbfa29b8480b84a5af0b21e254a66552409b561e4ce519430e04e4d6d17e5c893bc5ca1dca4a3abef2313f675a7b446a6ff6777d74d058e7ed589093a0f72afbd4813895262cbdcdf81b32daf383c903d279c9489a0185add3f1d21a010fa6b2fea40188eb8ac688202d8618d6f120126861a8a30a2e76e30d3e03a3f4ed2b85e51c3f2d81f2f07ba533c31a9e735bd91d28ab10ca50a437ea9dac44dd43b597ae9fc7d733affa818a1126f2ce87747321812fcb825429feeb2b65da87b5e95c4ee1007dac8f9c0d5f0ed0acb98cc49fd0f9de237f402e6d6489a2322f3c2a06182c0da8792fb14ee
+TAG: 3f24a0ecbdbc0c0e34b872e6788074fe02e96fa1bfea7c6177f0bd3dee1b9260
+
+# DIGEST: 989e0d1b57528f06473357bb0001d552849b928083a8bd2a4642e72be7dd71d6
+KEY: 3b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e9770
+NONCE: 45318c9b66262c0f0368fe9d0cb746bb
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f43724809
+AD: 74454879c41de9ac9f9823
+CT: b9f5615ac46aa1758c87d6dd0411ebcd6cf01d6daf4ea466afb04388430293a432c64d0364069e31bc5a168a63f11eab3d1770c4bb88e0d365cf497a92f7ed53090f831dc882c60580abb0b13385c1da23c72877c8724ec14a6a119d77364857504817dc265f0debe9b642cb4362c9705d6eee5b267c2eb778380b2f63823f08db8f91e726198b1edf6752010909c275790b2e1919bbb8e1b41bbaf311c705fb3f94225860176d59eead8d452f685c9bea0d429d8e9f1217ec67401546c63251ebc9452647035c86bb8e25d24bb1311eed6f0845419a51ce724e7972fbbc79b2012e1bdcaa73188ee07f3e091da441d8414c3ef2525d135c9c159943479d6bb1f9aca82d07666dd31e92434d3f6b5f324b524f86819f4429a241504eabea71c201ac679cebb9726cea5551a3fb2def39dda488b5489ec0f379df4e1e5c6874e18a38480a2bf0b27ec3e19927c993e7330015f00cf406eaf2e82fff913446e6ea2264eb5fb61b7731a342b47e1aad9635805d1e9dc16c025692aedb2848551b96e36a79a92b09a48b245443fc095a3818b90c336dc5415608c6426c3f8d272e0e6fa17c79815b4a320d517165989cdca04bd6fffcc0b43ca5ca7fe3ffc2799c9fdf239e03abe8b017fe9b3014798d863fe5d962b99eed729ce49961d2b47e52990a41d2b5959ceeb5bf05d0d94f2638bc
+TAG: 1445aaa40aa8882c398d70538019f649923d9fc3819de3b57ed7350b3aa79d27
+
+# DIGEST: a6924d514c1b926c930a9da2091f42787d1e8111ae5ce12a0292e9d25d906c8e
+KEY: 61792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c9b66
+NONCE: 262c0f0368fe9d0cb746bbd55813e8d4
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c4
+AD: 1de9ac9f98233b5a7379a5
+CT: 96cddee7340f4819d74c71e37ed02ac3b758e1a4c408215a25548c09c609bf692eb4b51be684adee72aef0d9bb2e16520d226d48f8cbcfae8d0f9251b9614ab6959aa3a3dc40fb67ae88c7a87172dbb189d011835c15fd941475a124cca458e34f191ab429d31b71013ef1465ec8e007983e19efb1a64bd789faa4d4b37a20487deb74d945411013628fa81a963ad291b1eb3fc1a323d12779ddc6c3dfafc1e4c315c9fd4974d9256dd720a3a42e3748217b403de15e901cf10842e8e6a3bfb8fd31b9210e99e636f0be57c337c0b443fdb835b81bc59960c69383e2f97acfec738b802932d46853682dca66e7af9bf22f7e78a5bc07e6bd1a1a8f1f204716250777f02f17b105df80b4d8799c17166dc5527eaa07e74bcb84190425cc36add64d024bebcafd19b500b0bc9d86bfa93e7ced0a1599e5238bc71dcd9d1ef860828dd5efdeaad84a29084ad39d3dcca12c01dae84aeb9b1ab6b9935a9043c0a16f0d6e6a88264f94ddd50ae59113300f91e6bcdecbe27215f38b96b83e88b50641203b3137b3c2b1ccbf75d07d82819681e98482213a7df1a818a1096924cb48e0f39a5b1c0553e583e12f24c50f925e50acd6d7531c513bde5bf01695d964ff066b92b7315e58a198717304ef00e8997bb0a5f445f6b12bbf7c97c8a3f1ef1a82b79a37f5435990b8ff5d5407478e1525
+TAG: 8d98ff597a753d8d8660a2cd17ddf6cdea23e7f3c3650e3ee575f5a44b1ff609
+
+# DIGEST: eac0a728eea929714da1c2a7934747811313b16a918363bd291d7eeeb8082047
+KEY: 16430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c9b66262c0f0368
+NONCE: fe9d0cb746bbd55813e8d454817c212d
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98
+AD: 233b5a7379a561792c0f31
+CT: 1f926befd80280b903f2b8959a46e6f2da227f140195ce17390463511569051a9ef00c1996998a80c5c27d3dbadd366183e29f8d6be4185423269af17eb4bcf8c9d91c2552c83994cd775d466709eb0f91df2b48545725d9d0334a4339be75760e082e39f0bd5bfe8c8e2dc356447597f29ac51c485f79a9a5d264471dd04955c487d9ba1b872326b5bbf69ad9b015fe24a62abdb12afb4c9015580d51614c8bf0c7bd1dc8df177273b15cb59a7c5f587f932fdce46dd7fec970d4f99cec8d6587d2ddb820747bbeeb46bd07c81e62e49e6df4c6f14dca91483bf3e80baa2ac4f66726fa457b05b8db7742f528171978023e0d556413196c3db1091d13793ee6616ab5132458f2f707e14f4485e7fca7aa88a5f43236a725b490aeaf292e0775c7521469ca3e0ae2bbbcfdf13ec86bd6638589a01b2fec8c62f234a9a55107dee748eba6211b87327ef55ab9c069d9e0a8df2ee4faffb37d2e2fdb274b0ed499ae817e86383cb5f45d0c3f46f74ea83dce54cccfd0c9d55349a81adb1c33829bd29f1f58b3fbbd7bff830a5f960ed67150f6cba6580caaea26cbabe8fe4e8f32eeb3488b326881405e78f2256274bed9894a2ab41e4ece9abd10405053933a1c69233f66b77b0dc4304e7d68837d946db94e1cbb6e79e22768510ef5ab5ee614a440d58ebba3f7c2e03e4eee336d194a
+TAG: 1f28fce12f91f6227400d0013e698269fb4a6c667dfb9ebb7c38451c4d1ba102
+
+# DIGEST: 8ad5314b867b5272f447c02f6666e53ceb37d99aaf1ee5833e3827cd1725b5b7
+KEY: a058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c9b66262c0f0368fe9d0cb746
+NONCE: bbd55813e8d454817c212d3a0063be26
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379
+AD: a561792c0f3116430e8b6e
+CT: 3c1c7cbc76badee6777d21e6ef008ae177761f8f43960cbf5f6af4699c94cb8507b462773c1f55f63f4541fee6d142f92c6e882be6f0551a57999a377effa8b2dd5c2590374967e13bb72156ca7b15a90280f2e04577f575430da443f057cea0fcf0df5e57b394ea3116c08fa03cdf8612825740503c564814ec85e80650352e6c52c985aa7da565058d649d58e45770e9547d4f56e80d4ad918e13d2a6d3d550dde254e425aff625187b3f7b8ce8ab5c9f911aa89aea9b780542a3808218a5fa8d0877dcee10ffa468ae69d8d48c2ea2ba9800add97e83b8a0732ae06c329c8d558209075f64d7ccbb4d641e30a14a8ecdb2e755c5199f677eeb588e298d367fc085479ba456d49738c1b4e270d0c88f54321f28e2d77fd893de8e4b779b1c87c6cd1a033c21cae25816371e07a85d4c2f7f7c3dd04786a03363e87c80fe24e827f2a81808ee789e62605078b6edb1c86eefd58c0c2af065e3a36c45aaac32cf1f4b8f883e38be670e83497352d563fbbad646c592cb958fbcee54a2a28e89a45a53e8651096ec94ea5e255fd92b1ec869ca58aed2f4e3af06092363b1708cd55db9145c7272b787290db021743178d6678532d5082874991070da8ffcd2d6797ad408a05461d9915d222512b2d2828f902d8cca06cb1d889f93a7745611aa92e5dee8359eb7cf633bcb652fce1e01c
+TAG: c27aeb0141e91ef264cbbd39131fe8c3cf02a00f542f86d6619d86375f855f7e
+
diff --git a/src/crypto/cipher/test/aes_128_gcm_tests.txt b/src/crypto/cipher/test/aes_128_gcm_tests.txt
new file mode 100644
index 0000000..5f7ad35
--- /dev/null
+++ b/src/crypto/cipher/test/aes_128_gcm_tests.txt
@@ -0,0 +1,420 @@
+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
+
diff --git a/src/crypto/cipher/test/aes_128_key_wrap_tests.txt b/src/crypto/cipher/test/aes_128_key_wrap_tests.txt
new file mode 100644
index 0000000..561ec90
--- /dev/null
+++ b/src/crypto/cipher/test/aes_128_key_wrap_tests.txt
@@ -0,0 +1,9 @@
+# These test vectors have been taken from
+# http://csrc.nist.gov/groups/ST/toolkit/documents/kms/key-wrap.pdf
+
+KEY: 000102030405060708090A0B0C0D0E0F
+NONCE:
+IN: 00112233445566778899AABBCCDDEEFF
+AD:
+CT: 1FA68B0A8112B447AEF34BD8FB5A7B82
+TAG: 9D3E862371D2CFE5
diff --git a/src/crypto/cipher/test/aes_256_cbc_sha1_ssl3_tests.txt b/src/crypto/cipher/test/aes_256_cbc_sha1_ssl3_tests.txt
new file mode 100644
index 0000000..a644168
--- /dev/null
+++ b/src/crypto/cipher/test/aes_256_cbc_sha1_ssl3_tests.txt
@@ -0,0 +1,840 @@
+# Generated by
+# go run make_legacy_aead_tests.go -cipher aes256 -mac sha1 -ssl3
+#
+# Note: aead_test's input format splits the ciphertext and tag positions of the sealed
+# input. But these legacy AEADs are MAC-then-encrypt and may include padding, so this
+# split isn't meaningful. The unencrypted MAC is included in the 'DIGEST' tag above
+# each test case.
+
+# Test with non-minimal padding.
+# DIGEST: 4a7464217ea94d95668d31736693ae851eb0e39a
+KEY: 171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77d
+NONCE:
+IN: 936a91d0b5
+AD: d2c0267218cb7090c6
+CT: c38859c09150f4c2dcbd409a6ff0d4d748ec14027a3a88c8117b119c
+TAG: 2fbbebe4693c8fa8e966cac88a81834c0d8ff6ff
+NO_SEAL: 01
+FAILS: 01
+
+# Test with bad padding values.
+# DIGEST: 4a7464217ea94d95668d31736693ae851eb0e39a
+KEY: 171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77d
+NONCE:
+IN: 936a91d0b5
+AD: d2c0267218cb7090c6
+CT: c38859c09150f4c2dcbd409a
+TAG: 6ff0d4d77699ab8772483a69168bd80c869b5f30
+NO_SEAL: 01
+
+# Test with no padding.
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c4
+TAG: 25ab146e770a444418e57b6ab4bbcb78b2f1140c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 095a8f557f75cba8e2452ddf97c053904b48827f
+KEY: 18cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e03744
+NONCE:
+IN:
+AD: 936a91d0b5d2c02672
+CT: f0f0bdffdd657edfb0a67683
+TAG: de74526ff023548d1f03b78cf28be8a0e3c83523
+
+# DIGEST: 4a7464217ea94d95668d31736693ae851eb0e39a
+KEY: 171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77d
+NONCE:
+IN: 936a91d0b5
+AD: d2c0267218cb7090c6
+CT: c38859c09150f4c2dcbd409a
+TAG: 6ff0d4d7e8e993099edbe911646ebed3f6d87edf
+
+# DIGEST: f1efd4c11318f4558eb4a50d5a5b9b1e540f6dfc
+KEY: b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed8293
+NONCE:
+IN: 936a91d0b5d2c0267218
+AD: cb7090c6171386d641
+CT: c115f1a248d83231feca6ffc
+TAG: 5cd326750f8f8187179b60f166e92d542483c0b7
+
+# DIGEST: 995341bee01fb91132d1af8394401144a35bd965
+KEY: e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc5
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c617
+AD: 1386d641b87797b684
+CT: 8631130ef1a5b83efe184f1ee509e3c4303ad9b3e4713c7dd6b4fce8
+TAG: eac3adde92cde2047ca81c172cd08d1dba079452
+
+# DIGEST: 73dc06657c34ffcc71e6662ec0a52aa7168c22e0
+KEY: 3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aa
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b8
+AD: 7797b684e0fb56f97c
+CT: 2b1d137dd25f4a56ba01c8f593f02570020636b77007113b3ccd87d2
+TAG: 1292e5d674c0a1ea04a5dc7c9bd1aed245311ac4
+
+# DIGEST: 6a5e3024f92e29f8f3e294f87fb25572c0390dd1
+KEY: 2993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0
+AD: fb56f97c3961d8afa2
+CT: 4757880b2deee616ee76b399b5daa8847d4ba61b4d8e48a17116a809
+TAG: ba43123adea3041010b265b1c8719473aaebe3b3
+
+# DIGEST: 6f192a6acc2fed00007506adeb1dd454e2e92809
+KEY: b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c39
+AD: 61d8afa22993a340b9
+CT: a64c22f959677dd500a8ce52b3b43ace3fe4d49550accd6de18d02fff1d28d292a3fe514d44cd38873098e98
+TAG: 7ae5c5112e2eb827f1a59b85e249fff2f7de54c7
+
+# DIGEST: 7faa4d4ec92841e45297553097f2ac2ca53d2592
+KEY: 1df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac99
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa229
+AD: 93a340b9b3c589c748
+CT: da502c1268d382682c692d05a27e9a2fd87823c47c1fadc0fcbaa7ebc5ec33182fa7108468bd9ecb858b4756
+TAG: 64641e24c80cdf664d37c1a2a1155cb95b5ed714
+
+# DIGEST: d6cf3a4fe57328e885cb10cc7088e0562c7f91b3
+KEY: a23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3
+AD: c589c7481df3f4183a
+CT: 08ab0e7477cd533684f773e3f2df2c02e41e9a2de22b398fe1bf170a52778b9aa8f29439e8328b7ebc54e755
+TAG: 48b29ca7ef7b15d6a4d40ab43d52ace1c3f1e97e
+
+# DIGEST: a2ba1bff3a6dc3ffa8c405fb8f69c41ce7c1a1f5
+KEY: d88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481d
+AD: f3f4183aa23fd8d7ef
+CT: 2c0c4953cb8b272100002493ab55612e80a9a395495a89c31fc1b927d17a058d980dba7cdbb96012eb300ec57f13bac6bbac27b0fcb5c8bc0c43d3d9
+TAG: f7a6ef251e2f86c56a7620a353faea7527a50bf7
+
+# DIGEST: e2825275a794df011a9dd0c6061de3a9eb2efd48
+KEY: 8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11b
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa2
+AD: 3fd8d7efd88503f78b
+CT: 9da9a98c18acb8585d11615ff6fc6847f67f5c123868be7f59b834af799bd322841bd2745c83d93b880ce4982de88d8a1db49ccfb3a87a774f30b159
+TAG: a804b6ec173b19c696e67802cd2ce4eddba2f686
+
+# DIGEST: ab656533e45e90a45a508392ce59ab9bbcac27c2
+KEY: 2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd8
+AD: 8503f78b8ed1c8e9ba
+CT: aa10f163502c489d9d4e51893fcdeb21d28e682d37f202f4a606eb8bf7543cfcde20c758f58e64f93bebc2d8c2fc8408ab882be84ef65cd2e1467b1a
+TAG: e696bc221bd1412abab6b61e5efa7f96e234f407
+
+# DIGEST: 0614460f6ee128d42ae79b1dda518a0f0e4d0d16
+KEY: 0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fa
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8e
+AD: d1c8e9ba2fd6773e0d
+CT: 1d76d74a882c23d4a9c2f025d99239bc51c2756c038302bafc74cbeb85d79602a5d2cc80f0e81fa2869ce3f0de2612ca60c7a2e46993b3cbe5d9dc63a30ca51820b3b4c3ab43812a163d27c9
+TAG: c1540f2d60ada9b3e0dfba2acb213b53d99b8393
+
+# DIGEST: 629525ee366d420f18c6a88fa3a8cfecaa1331f9
+KEY: e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2f
+AD: d6773e0d0c302a5f47
+CT: 8c486099ddb7e81637f3e7c80af6b1212a140f56ae463ebcdc4bf6637994b9a5fa363f5f2013e426d3b86867beec506dee1d833909ea8005656b3e809c2b3c3985d6d7dea1f7f9471f17b9d1
+TAG: ee7d73716c491cf321f68a2e6008facf99fb31a9
+
+# DIGEST: 79b26abc71e1670444167ecf48e093d505678371
+KEY: 91d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce99
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c
+AD: 302a5f47e037446f58
+CT: 87bf1af7e4987cdab35bfe32adc6b1be286751426cf926217f2c699bc095bde7b6ff3d6cc96b79328ab776547c2cb756d9de8c1245d21619a51dba8364ef69143a9e7a0d4c7fc792362f2c47
+TAG: f90ca9d6dae35d906d4fa112a5e7c7e4da861b5e
+
+# DIGEST: 6cd5a6f762364b9814deb6e1cfba1eae5b0f31d3
+KEY: ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e0
+AD: 37446f5891d77df660
+CT: 33ac574b7962d03b7816c0199a7f661a485832b9023867a749fc4bfe8ff0485571744f801139afd8215863b23e2d68ee7a254c60d8029e0f1ee10a1b947a4984df605829260ac2db2c216a22
+TAG: abf02fc3c1444a138ed55217c7b16fbd7809d79a
+
+# DIGEST: 2d3f449046b625672e740920da76e6cb0b297236
+KEY: be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891
+AD: d77df660ed82933f62
+CT: 4d754c684658bcc89208bcd75f24dc8e18b70a28b8a2201535e60ab755fb20e1ddfa98742d257eadd02d96c6a65f880d058312311efdf67f9a106beff9f5ace09965962e11aa37cc75d6e73936c18f796f51b8a86772bbd5e395111f
+TAG: dc06ed623189291e7aa947a3b625128e871662c7
+
+# DIGEST: f321845e9752dd4bbc414648274459099c9e5574
+KEY: 6965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed
+AD: 82933f62be8dc55b43
+CT: 9b51ba0eebf72bbcd7a1b8452a49f30bf2d96bf0cde4d9e5efe7f1903eb4e09f53aec649c5a8ad7e7fc6c28a0dcf4bd3556f4377bbf8b3f9c79dffa5978692559f732c109a7a02390746f5975d5a0aac8c84c047ab87167a1669c5ba
+TAG: 03e0e79805d2ac8e6d141a50044facb483e050ec
+
+# DIGEST: da9868a42a40dc263e0a0fe4247ee859569d7f63
+KEY: 7e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be
+AD: 8dc55b436965aabe47
+CT: eded2db8c302b3b5b5b0c0d556f8d34408fdb2af75d38231049b5f91e02a4086e6ffcfabcba5e3ec68173dfde382a41523d3c8ea1f7944351baad1588516c548125b1005d3375b03a4ff4bb19937068e9ce780436943d161baa219ec
+TAG: bb3d73a5238767af07748b696b4f06086e157da2
+
+# DIGEST: a17d268f79216e57050079ed4a85ce137f83cf5e
+KEY: 99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f256
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b4369
+AD: 65aabe477e0cdd46be
+CT: fe6540372ad1c40ec1dd644e935c480b9e34aed05a7f21e2e37dd46db52ebc5352cbc3be2aa289cc2e9712aa7d393f4454c9fa3a4acc30db41ada1257693d3469b0a1d5680dc8dbfea8cbb4768161f828cbca92abb73d24780fbcfaa65f505a372c73315375069abd35f6cbb
+TAG: 2195dbf5751581624be7f7434859f67f211a9ca4
+
+# DIGEST: 44ba8d9c06c6788865a1dd76287a443eb0c22aa0
+KEY: 7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e
+AD: 0cdd46be99371eb8da
+CT: ee9fa11a7d6f965e7d65d8f48810754770b9d237ba0111978b97e24f223817d0c6ce4dbde85c4e0979bea607a36c66f908c25384184fc334d8d985b78c2e9872d82c4cb1aad49d7dc21d6484b80f9192bd724ca57cdced2fdf142283126721c17127c31a384cc05446f5cf8e
+TAG: 8eb96b334b35968f92de7892dc5a86662262beee
+
+# DIGEST: 5b0d95d9ca1dc4d0ccd940d38881b8864757c9d2
+KEY: fd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+AD: 371eb8da7dac997dea
+CT: 90712d5e3edeed5000c62ce80212d41773a393792a3a8fc62a1cfbff38b3555aadd88f0e36f93c8a12897d7779972b3e42978cdf85da7a3ba2e4b261f0a0cf4e1edaf259849e87133a9c057e5d3e693a2a181eff1f5d6f84e0679c625ad9a0f7a13ceb503d62c1fa7494b8c8
+TAG: e766c78f90df099bbaf385f2a428dcfa697e032a
+
+# DIGEST: 310801f266e960f886f9a02cc9e8adaead89dd29
+KEY: de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e78
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7d
+AD: ac997deafd64b1fc65
+CT: e59fdb3d1413cd6a1098b5daf1662c698076996e2581e11a286e5acd6f29d41ff9d04da8308ce7f5defc52be0b4d1ee96d8e5f4eddbdd5fa9894e7d1b0a1bed483b7e7549e1c10cf5b8ebd1e7f1177972ff061cdecdad8d97bb0308b19bbc2c8e3359853830d6cd1e41a850527891a1e2e8c512d9b86a2df2036d99b
+TAG: d956f1b2d6ff38b2d1e05db60a4b8ef8987e40e8
+
+# DIGEST: f6998ed9b090ceb8422100ff91e5e2671a49d980
+KEY: 41a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b70043
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd
+AD: 64b1fc65de39f4f035
+CT: 8a1448acbd769e42bfdf00ddd801153db3202daf5ba7997890f5f42a183d3a66faf66d899c7099fa99bbcf5b62b6adcb6ee87fafdd0275a8f625f3f959b0ea9acca88070aa9c61141787435cd60f63e262a80b6aaf931ba554ade7e0fb46b03a318347f1ca84e9fa1786d721b6c222b13d5d36322f70c5e087b05666
+TAG: b1ab11873443a2a1c75dc8579a3e0b8753e7b9eb
+
+# DIGEST: af2873f1a7fcd4930f1c8a554ff271c5ee9185ce
+KEY: a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de
+AD: 39f4f03541a11be112
+CT: 10ee64784345c076e3f9aaeacc87cd51d6ee0b0facc9f40b4e6a1b4bec669ac3c5252c948b0c0a4d8e798248e6b10ee247e51c81793c2be91aa8c9666e0d8774439ea159e4745014bdd2e9f379ba461a7e638cab9ba2aba1498397044edd3f271e2b4dbb5990c383167c9191ceeaa82324a339abf8f81c7908a429bb
+TAG: 449d611eb4c37625048b5aa2445e14b3c2ac0e4d
+
+# DIGEST: c4eaa1d6c4d2d5a8d2f4d96890bd0299f1d699d8
+KEY: 4ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b02
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541
+AD: a11be112a72933c7b5
+CT: 9c61bfbbd3e8395be166b30a56b3e192748ba3bbbdc334dc3720206ac10c90dd777aa4957695bddaea0b7e554951c94f2f74a2bb7547ac20a7e357fe249614204401144fef61394c140553d5566c18ded15e0fa50fd5836cb725d277fa46210eb588a96d7baec9e2c947fee1b85cbe65ec6b81c709ffbaf595f17a0fe5edc3b61a279f08460ed6854ffd1fde
+TAG: 25ba01b037df54df3dd9cad8f68d008c4287aa3e
+
+# DIGEST: e9bb0964e1cb09fde5e8f852937c4d8e1605b714
+KEY: 905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769d
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a7
+AD: 2933c7b54ed4fad0be
+CT: 997bd62c118718ee23b9d75f5ad15bea914cace8858ccf9534ffc79a626768802f7e86930243b3dae80d38782a6a61429cf0278d37bdb60a0ce3ea74163ab77eb299285efafa2895fac6d7f2ea65b35e579e07a7a6395e2488db288c415b402a913d727cbf3df623ae4a205d9867c5962ea0c9749b791dc33a0e6e635983bb65d29913e213ca6ab308f86c8e
+TAG: c4ec5258fad44a8aee2259a27f0e9a82cb602121
+
+# DIGEST: 659746de28fff60cf3bcaa07eb7a95c5b7d3200a
+KEY: 5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54e
+AD: d4fad0be905d41203f
+CT: 368ce97b3b9c28678363cbcee49ac8474b6a12ff63d783060a8cb33ad951edd059260c4927d5bc2ce252b4deabfd902ec1025a8847bd6fa57324d1d8cdad0f23aacd338c8162f77024291f106dd73b1dba3746e7a8dc3c3132c6edf1367aa576046a7d537df7827059b25e469dbb6aec7a62207bacc22c93a6704eb2cba7ae26843bcf55d829cb54ac853833
+TAG: 8872357a6e7d99bc6aa361bf314e5ac48e91eb8c
+
+# DIGEST: 170202dac332954785ff6f866f165ca62510d9bb
+KEY: b2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b51106
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be90
+AD: 5d41203f5dce998f8f
+CT: a7a27ff44599a6263753294a057c527552f4659590b97b9135c74da778a88607d0781df713f4e0d72d044f0c2c7daab6fdcbf162cd700d236999e29c25be1c599b5b5941c774432494b848f6d862da9f95d28d132c7333a4ab436d5488466ff8304415494bac0a922c8aadf885ac23db5e65f05767aea7da7721255b9c5c853387c33e51236579e1c220479ba41bd71ac3c697ffb3a6b30e90e484f8
+TAG: 787d8440ab9ecd38e99984ad00b1fac217b5e60d
+
+# DIGEST: 767d4f588b55b2593cfbdc46acc6064616f75c2a
+KEY: e02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aac
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5d
+AD: ce998f8fb2eaad409a
+CT: 26084337bbba564153818959e07afc3b13632b7f5fc304979d073460eef46f853152b9059990e582b700e8cef904670514026d4a62c34f77ad6f614a9a48a0abc3be830ec88eb9cdcb98d441e70f1c0d389bb9e9e7517cbba7b2fdf43e115aa556429e5a91a925dd9d4b1af3c9ea8df004bb33ad11584a1d51cd4b31e4f94d9ff69708c27da44c0d4622b3d602ae0a05972bee246b778aad1831dae3
+TAG: eb7a77e59ed7de5b09ad3296b251fdff3b9042e7
+
+# DIGEST: 27937a84ae455678a2f3c73b523d600135e6dcdf
+KEY: ae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184a
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2
+AD: eaad409ae02116417d
+CT: 3210ec37a258006ad6ad1e65906abd6f74810eec72d7ab162703aaf18d3275d4272a1124d4da1be565e29eb1673c5151762bde617fb2279ab77c8a376670622c5ab068ed36719969baaca7d42ca0d781dda79230d7af3e05cf913f39e5b4e93e99e5cbec9988d7179b621a13c78f0f9b64173bc7163cc2268a5f0f390b9a1f188c5ff5b73e325819e2be58af313ed5c626d755101e12a5cf1e36c0cd
+TAG: fdf23a507c6955359d5019c2f482967209548f1e
+
+# DIGEST: b1c534558a6ecb0ea225369be47ddfe669190d41
+KEY: 9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae0
+AD: 2116417dae0cef457b
+CT: e51ceb1ee67c681952d48022d3ade08d04bbd85f2b609e37bb52b2a0a43206aae01e249c2c7b30ecfd28f78add255b02691a15c660d28fc76eda5ea7971c8b11ca995b338251124a12e7ce550a5e692ce2b0248b6982823a22305c7a928cadb23cb9f14c10d3c006757abd0257361b447b8c3407bf7730c6b6d28afd10f1bbf828029f6aa972c24aacad252a64ce86bcc6b5db9dfe214fa7e6ee332f
+TAG: ac35ae8fe91ed70afa5f74f676faf14eb6020038
+
+# DIGEST: 774dbbcae39eaf44fc300eb00977f4e56e4dc0d6
+KEY: b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae
+AD: 0cef457b9e5e16dcc5
+CT: 77b4e444d271670653f04d99105b36886383a2853163a47615b431eb3347fcb7e013392376ca0c7bd2ba68e9b3e9e8513c783df10c1e71650c952c31821db41a509b7163f509f1445ec13f31090fcf566b69f6f1c5330ab588eea6f229025409c4b749edc4e22e1f4612a9dd9df978e685e30d6c27a8f50d7063c73be06ba9e8897d13031380f070abe014f7249c3862e92241c4317659b3bfa24ab2b14c5e1cf5f0ba6d292c78d84609f9df
+TAG: d3f7baa32742efa2321cfbbf5dc9a68229f4bb9c
+
+# DIGEST: 5c6b13d8f7e9f764136921bf62cf406b9dcc8615
+KEY: 0d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72af
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e
+AD: 5e16dcc5b6f25607f0
+CT: f48adc232363a0490e75ff78e4071f299eb70eccefe5e2b93a5e223e2521a266d9b5f9f2d6ee01c1aee3e4b85e71551c8d22535406146d9561eee1ab3b3ddf46cb55cbe4f38d309da8c71a508892f19a86940101e191d0b2fedda544b64f5baff9829554be885553500f09d707357c4cbbc7fe96ecd36a699645d5257f71ce7d99ff6e8d1cab03e91e03f8921862cd0912853433c8af5b173ef777ccf55349b3e922fadfffd5f6ae475801b8
+TAG: 75de1de5c12e11add4bbce9eb7ca8bcad23c9019
+
+# DIGEST: b72799f51e711da0ea2528a5125a994e33078898
+KEY: b09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f4
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6
+AD: f25607f00d033fb95f
+CT: f4cbe7ed67750574ab0716367351b71575476b76987a082de8c92e79861d945779aff8e89905bf3c9ba0bad99b8710fdba8298510063b646b4e1dda6ab11890e6cb30350d110c46f954f3bde6738828d339c6380b5008ae314ff09ba49dfaffce583400765a52af8970ca0e542b963219c0cf6c0d627b68df25ae47e1d81df1d6b9b23c54daeea7b49cfa0a42486c48f7966261b0fe16b1b116b379d6e64eb774424edd9b0157bc44cfd1b53
+TAG: ba0589f7e6aa5e142cdcb9791ded0370689e672c
+
+# DIGEST: c2c932a2159da6861262e601fe835e4feb139fc6
+KEY: 172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd2
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d
+AD: 033fb95fb09e4d00d6
+CT: a96cd704bd0516225a1ebaa7b4624e0e368aa56c0f75307802a3dabc6ec6c767a9d00769d74b48f7f93a3d5c53822e2dc8eee7df367345adbcd0516092af64ee9977e0cbffd3d2c631afff977bb14909d3859c6abb2a48c14960f1c99da2c6efe025201a7e50c994f214e67c66d995ca58ea0ceff350c9c3d6ad5276e56804d63ea4b80073cae3cff6b8f236faa26f934734ba5990c826fe2b49af193a2d487f297c396731b266c20de6849d9775d5727b358c3e607df1471e9f556a
+TAG: efceda90dda065645df2f44f97bbbf12cc7f3ef6
+
+# DIGEST: 25b40da26cc2da8afe980d0287004507d92a426d
+KEY: b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb0
+AD: 9e4d00d6172e780ab8
+CT: d2b2a4db33fcfae2c6ec8cce4e5856333aa8fe628b522ff9e407f279e64c091634057036ba811354b902f72f039a509a585aea1a5b403ca70cc2860d64c487adeecd0002817cafa85e73b259f5cdfb8f2563cc767b8f32b2bbed0c4eac259f351cb81548918cb8d8bf7450bfadd0fdd0d0b880f23256a80eecfcdd9855b0b9a0f5c820bee13c40c002909d811e428ddcf28cf80ac1e7f4f258fb811c4394f708eb6d269a3f09ccb7eaef32fda306b007e9e3eda3b06c3d25f522732b
+TAG: 2feccc6fd3f1422159627c6ed15b5491cc6bc675
+
+# DIGEST: 2b6449832e28e0f08469119a61c6119ecaf747be
+KEY: 7a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c4
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d617
+AD: 2e780ab8b700433a95
+CT: 92f2af21175b4820901ab086fd9abbf8ac6bbdda20a1d4dba5217fb6f325940bb90fb6755b09ebcb54283f03795eb74f19efdd758caf83c22c8d2f9e69593a255fb96646d3b7593b3e4682ac2132e0568d01b516ef3af057faacf4fc90b9ed42728a91f28fe91610c275906a1b6bda159562f3e23c4658e40e0d3a3b6e955ae014eb538a818808f062a67e6f301e0145b4294626e754b83bc95ab107d29eb0a56bc7858710e1bd5ab68b59219610f1d41c4341f675a1db128c81a25a
+TAG: dcd3f3568c669002e897aef8a594c19f66a19a2f
+
+# DIGEST: 4e2f1dae39e30675c6b32f427ca47ce502a02191
+KEY: 0f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b7
+AD: 00433a957a741c9eb8
+CT: 43daaafd62f3733ee7805bf8cd9a7189eb1343eff0ce3f2cc2aaec323899f676aacb0a22bc44317eb9cd1fc8ff6d98c19d4b00ddab897d600de8c07d9993fa221ccec98977addf87f03fb7883cdd704bf788a5e9ff04775d3272987afd072cce7ffde5739754d7fb6b449e1d45523cecdb039e8596b7cb22467750ff04722deebfa0ded35c23ec5ec46f40fe43eeebb96ffe0090006dc0d631098103ee773598de70237b3ba2c0e8ecb52a3ca7a494f9805190ef0c7187f4d8d369de7c83e142e424cdada41fdebe493808d7
+TAG: 2b18ccdfe7df7e65cc77b6f961201c318b5bf89e
+
+# DIGEST: 4b779331c327101cda11bbea17702561aa8a410d
+KEY: 44769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a
+AD: 741c9eb80f2b021b14
+CT: 8de1f281a40131d37e88a68372e39f5c89e74df53a9cdc6d9802878667985ed45a6f200e8207a53c4c95ed03e245adef990153e52a7079bc94a8b7d6127a0f03b94ad68227a79ed6d1d642bd8dba6f5a8614a41bdb0256222fc02bede6bc1c9caad38d4d27bcdbb0e49b2dbaebd1ec589f56b5523c9df3519be8ff4808836a228b46fcf021f4a248ae5b05c8f2016f7cb8cbe88ce2971d52c782b6357940f37df373ecb3e050e070a3cb5c02acab38e2f4b41385f9e9c19df93c4520a9dbfcaa5ae72f52a38cff805313cf9a
+TAG: 97751e929fc014f5c589e9a60ef388e2d4486433
+
+# DIGEST: 708364fadfaaf52792bc2fe5bdaabcf986af7aa9
+KEY: cfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f
+AD: 2b021b1444769da00f
+CT: 06f47b618e70d204b9a2081eb0b48fa8e006088d69ab34c7f6632e23c0c4fe4033728dc89c88903531f6315950b637475d553d0b35f369c7d4df7d1558fcff67583b983f6cd858dc2eb958bfb2ebd3a2632da37ead5ceea92b8b49faa175a9192054e27eebe05fa871d07cedea8023a8794f71cbcccd82f3e25911b95b432af1e60803704175599b2e7b53918c0670dc08d3b220bfe007df18972a09cda4d55eed67d55d66141ef243528c7e87c2e641cba18f332b7abded77669d7692ef84ea31f95b35a11d49b86d8a6e99
+TAG: 0713d6c5cbebb5cd2f2fb7cf6eb897254cfbbab0
+
+# DIGEST: 335c241743268f08b03aa63abf9642360d22a112
+KEY: b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444
+AD: 769da00fcfab0f5f93
+CT: ad3cc5a9c59067452fd219bcf53d99d6d82866fda051b69ba1d83e6e671b6de596aad44b6f22f1dd898a1e8e40e74d8f018e07c9e9e73912a94d9078392447a6a4d0c52808933983b1e668b39790bd65926e039cd54bff207ec74af8ef77ad33a897fd3677d5442876365cf1f28d88b6525a00c5c81d0125560fc6f1ec3ff1d15949ef1c1e828ed4e4ff00f27e61ce0c9cb9e9fd4c45cdbb642ed4ae73077b5fb1085c04150b50a36199f0d5e3a00bf16ebc5228cfaaeb3e0eb5c552b502eb8b4f1050b11a3e9ab81692545cec206ed8ba4badff3844e69467613ebd
+TAG: da3c119557eb9e3980e3652328c523477ac251bc
+
+# DIGEST: ae61ce3c2b1475f8afdfb1be68addaaeb6489356
+KEY: 5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcf
+AD: ab0f5f93b511060c9c
+CT: e4d1bb73127386320be2b84f9ca0aa40b95fd7f81892942fcb954257a7b9b8886f1253f0db712af44c1db5655042e552a26e7e9b5cf46bbbb4540826d05f21e3f9a3c336ad2d19bba71ed71a8985fa4de946ab419a56f9d15d18c9a31437efbd8d3a3e091649ff9ab1a7f9a10f15a1deced2af148b42fcb1b2eb9019bc40b3b4102579527087d427c62777960aa8653326523c26388753883f406b7db999856a01a7e9f3242b3ba50d4434a6ef4f8b46d34ff8d94369f217b73c62c53f2aa4b3a20c5550749ac8e231046b358b4c6d9196e210a1d14029a187a0c5f6
+TAG: 7dc2b9549831cc6d40f445e331944c7bd435db5a
+
+# DIGEST: dc6621d897775dba7bacf8b7f82bac003e984b00
+KEY: 1b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b5
+AD: 11060c9c5f3aacefe6
+CT: 560f3a3feeefd071458aec326be08d3672129e77d60f4686200e5449ce2593a2a8d01b981d16388f2eef742bea8d5f0cccbb9a1bbffe53220c763dc6e384e87e76dc5c31296d18cc9510ec00cf5c7dec2d40aec17f7c1ac55e5ff919a5957f8bd56dda58e1d0d6b2af3878a714ddc891109166655de5253a4213bfc3caca4c69204b27f46d19b0dbc2df066559a894ea31b066fe6035012f4d8002dcac151bb4e48404bafd6121fc1a2d62a85d13850b221a9ee2773a87a1b01fa7662265a694f0a1c9b8397f12dd23e61f770280080051d5077f0906964e9888c981
+TAG: 14f9635793af9fed9140314b0ef14ebbf5bade39
+
+# DIGEST: d2e6d3eeb6b5565d9a407fb96c74b8b3be42e64e
+KEY: 3939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f
+AD: 3aacefe61b184ad246
+CT: 1cb08ffca3e3e9af65d527b96e75dde23a3674df40ec4866dd55ea60d023c8119b7e4b4d4c72ac3a26907d25a549d77762bb5673d52e296d6a894d68e87dc4eb63d5eb6d262a206891baa2c1c4bccf9e8958c5ee374c2b503d3db7cd91ba30d0aa1c3d13068ee09299dc1816717071fecf98f7a6f2ce7ca458c80e0d9e430c8d90b96667d60cc3973091619a75c56b7535d73b72bad57b7ae670aa2e7793a8299dcbfcb7a4b0dc22dadd37ef3562b0f2c0c41aa68dc26d14cf8552683c362f906aea3613b920716459e086c56cbc7e888d9dba744e807bd1370959911c8f9390dba82fc48915766cd9bbb2c5
+TAG: db72501e90a8f1dc6a52e73a047bdf3ab548ccf2
+
+# DIGEST: 238d50a0695b1f255d5b3944c623876919f9cc6f
+KEY: e97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b
+AD: 184ad2463939ed518c
+CT: c2a2d4990449ded87c4992bdd79e0fa70ec3be505db46c1e17673caaecd6b24b36b2acecf0dec640832a2de1e3d9dcac02f5ccda46decd8d19eb038a6bac782760721cc9b90e7037238b55132f1c3f94ebd67cdfee66c0b08962dd69f71285c5a76173d85ce830c04008dab0ad2b5d4d00ab2ac093579d7763f8b64863198cc3eb899861f73a2368d1e2d6a709f29db09403080606ba78cfbb9ca6d282f6f1b6066e92d3ec8d7c66977194120c0cb393c543086144619ed854fd65db3bb17b5f86a7d396e13cf48dd67df52bca570dab759fce1b2237ed9f0a8c1c53fa3cde4f492928050742c9a32abbcf19
+TAG: e64c0d9baa2878c8458ab1f8a8700d6debd2df1b
+
+# DIGEST: 562090fcf982854158b6068786792d26d2af3cb4
+KEY: 3d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd35
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad24639
+AD: 39ed518ce97c3fdd29
+CT: 47779ce727a9319dc4da77d809cf8b79f3e3658f7ba3679e96411f7c201f3638bb6a10c70f79d21ea99bf709150a7a556f2684bc3b67bb716dbdba980cdb37f2317809b2fc7f034a76eea0d217959cefdce844b826611ada73c2dd12630206077bfb5da1112a92cd8fa5b6f768422f288c1de123710dec8f3e95f88c63a2224e35e8406fb06ac93cabfee0dc27208b7bcdd785c18023c81159223c6b9a2e5980388460b67bc38183d5953248b8886139d7b2865b9c5255197458c8155c1641969ebdac9f5ae511108b0bd541eee3211159d30f1e8ab451563678d3de24748ba0cc648f5c96afa9c3ad32436c
+TAG: 301135d24542dba3192d514650bcd27366fe5ef6
+
+# DIGEST: 0c2eff5f73e4ec6371200ea4e3ed600ca22116cf
+KEY: fdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce9
+AD: 7c3fdd293d72afc09f
+CT: bf5f4271222a6b8f88aff52aba803e69cbc1faaac7cce89f7d2fa6287556835990ce1d81c706ab63ba3758f8699ccba1a00a89c4e454c4e61dd1447fe635ad75c5b56637e82fccf5a635c5e4746807b3baf9d2ae7a495b75788de46c58648eff4c6a5aa95ca1c86a26706a1fb258a801b35e152ee3c0eb1cdc9053cd9dd97b360a8fb4369899605101f46e13e3b8f7c2e92c721703e5f234f85d9a51bc748d34512eab57a38befb3caa27fcdcbeb76e7f70d3d5b70d1e0db56cb5492b27b5ed36e612b9a9060929d0ba93f2d6bb4b8acdbd7219395fbb14f10bb8ba04ed8bafeea055754a1c412e4b6819013
+TAG: 178238d3b2f52380b87ccb05ffd189a89cac726a
+
+# DIGEST: 7e81f0c3bb2f9c2073120134be9d0b1d0521989a
+KEY: 249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d
+AD: 72afc09ffdd4f41963
+CT: ef1d5106820950033607cb01ed020cf464b1752c60719958611f95569a665d388560bd7214f85ce9a257efb83518744ca9525ab3aa5262f1f1eb4d3ee753cbe6b4531f9a2b97fc482d22279dc42372401d38388d1798a47753cab483132c30d43a093a9abd285bdc35106079c1ccf7c1fc356d3cdef55f28a43b949ba30b8b14c5602d82f005c15db8e216ee027089884e5512ea6c75b46ab3806739f389f998a76c7c752ee6ccbdf02646bc4d4af5407c91e826b2859b6fd6f14376fcf42b4973d6106b1ca04c4c944fa91ed3198000d6141363c1fb1db6a6630701c233a6cd56f6479925bc02dabd7ed778806b3685debc637b71d1022c0971f331
+TAG: e005b1be8937cf34667c0e6a90b763974f9f809e
+
+# DIGEST: 28a454911a3ce17c0248d2f535f4073b6b092f6e
+KEY: 2e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a747
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffd
+AD: d4f41963249cd299b9
+CT: dc3ec8109d10797f038763f228f2b09ec5f5ab9e575c3e965135aae0327a709d39947aadaa1a7d3be9c73ef1c3c2ff740fe4c294fce8a28deef09a100bd079ece1a82c96cc679428686b439fb3bf4392fc2155b4f4f4aa510eaad21ffe8898d2bf8d7e47120203d7efcb163163b89ca9ff7db4555d248caa91c1ef64b3376e5d95f5eee2123e0f932b0f4f22c67e81689466aaecea9e8a167d3f17509ea2c5827100b3e8b0db42150958595aa7e48df36906fc510c36bf3ae1d47d5991501fa6f07587a3db0d8bf92ef614486e62d4c0b6d47f2db2c27be7122c63cdc06f46bc69ef9090d2c43783d0128e174e58ac71607d0b2ade8cfc7f568ed7eb
+TAG: 32d0284a7696624e7a79a0f3165f80fe207d45c5
+
+# DIGEST: 179d0ff2661ea9bbc7a42df1b3368bd48c176a91
+KEY: c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f4196324
+AD: 9cd299b92e55ca24d8
+CT: 7bb7bdec9f7a88752fac855f095aa4861045f35d39bd7183785931cba565bcded1146323c13bf4d8f19fd365fd41f83e91f9ce1a295cf3eb1b00ff4d99522496af0a633d2db59a0c65e2586c82df31917ab7d59b888926c94cf262c97d0a157e5db083de3a9f6ebce2c675e079c95d64d09b926c4d2838fccaaab418f22ffe00f26afecf9f6ecc8cfb777b9356d9e04ae7400ea0640cb447ae19d54e9f617fc700720a8a705492d69b2de7593e55a6ef5ea5f6aab63b6e49f5a5d63d0bd6a07f1e63b2cd6bc07017d663027cc029f5d916e75935ed45dbd9c8b352ad36f94d6b11dafea430c8409d46a427cd16653d2c5c43aecba23bdd93ce732897
+TAG: 3e94d057f3e0f0aa2ae835f6227aeacf75cea641
+
+# DIGEST: 35f3568ac38767bbb0464106b32622a101523d0f
+KEY: c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef16410
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e
+AD: 55ca24d8c078c49f78
+CT: 0ab3deb7e70e17a62eb723138ab79ff735fa1afb15ffdfa40e0ac94c961da191a19b3f0e91d12304bcf80aa651e6d8b3ff2602ac79227450a6e321ff24fbcc6c0b19261c557da187acfd00d3da83a2210b9331bb9fb2585fcb9641745322ab8c1cc0f1def713af660b94a388b5719e38dc3610ba6ed09e675cd350d637536193bf94d95a8e14c92024417a3ffbab61c03aca0e8e2973876eb3e2b2a9daf5608bbbeece9900b86f0f2a47e6d0af95f06be0037721cdb2c94cc1f7ca37afab618fda75378eaf63ffb41f472c0f6a1c5a5767081aea7b5435feddcc27324a13d45a6c12861753dc7be75c6c962ccfa061ca3e2ba72a8f7a572ea27e84d9bd045a791bf083fa8f45be1617852e00
+TAG: 7ccd8f44f0a5f140d2a5b994d381836db18a9551
+
+# DIGEST: 720ba4f4eaf71a85873c01a80fcbcea419d22ce5
+KEY: 025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f7
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c0
+AD: 78c49f78c7e713710a
+CT: 5beea8abccb14c5f200e93dd25742477cd3c63368a50060a73667011e0db1939bf17ae2ab7c8cc31a03b075d694c357737eb79aeb6433956b1f91cd99a6be1664ea93b88cd8d9a3672aaab7046051d91fcc4b1e1794dcba499f1c05adae879c1f2a9631ae97303f5acbd4601debfa5e31f9df46f99026b8c2bb7f669847624abe75de43c77d8c628097771271930ff2b9b5d846bdab2d12e6f7a90bd07f4ef4fa87932cc038be88e1556c0dcf35d659c165d4ac3c19f3eb1036f954a02320ba7ec600129cc2725677b598d95c5468b3d7743286f05c9f1821af752d1e2ad61290cdb25950e9fdfdb61edd74527d95cf96716dc1826e3ed1f1ba451f725792e653ad4df20202d4e1064dad10f
+TAG: 8d763a1a8079cf71fa31ee81c2cf29cefb4792c2
+
+# DIGEST: e531dc2be28c8985a08dc53ed098457cca032116
+KEY: 1d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f52
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7
+AD: e713710a025cb8b9d7
+CT: e7f4549699e18497448d0e730dbdd2b1c6055fccf9fef5442ad0e6d67a92fb7dda31422f52b2b2c8b0ee0ae0d532ebaab9d4c2f81e7579e24cdc4142aa50c5ff041f6b76985461775017a9169183ded52fa0ecc5392e95dd61f7d6ba2103f75ead01673f2388ba8d4257666aa3f73559ec2078beede99e963b7003ab9c041ed6a97b50947cfaef864269e84a33a598f81c7dc27191962c8936403f198e9012f19bb8b57868c11aa5ff89c312e7224d7b170c74ec38c5c1e6bce87426129313658fc3ad88de0a12d2012c92e9ffb25ba5faa9ff8456cadc94346aeea7d8d115a50e3de7bd92cc3f45c73bce249d1318ed4c64a1743a189d8cf9a9d3cb0d7cb64d230608efe6a674e0314d5b83
+TAG: 8cfb2cf5e2829248542000a6e7a11863f40198f7
+
+# DIGEST: 87828be40716e1acb0ce876660045cef3bbbda49
+KEY: e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a02
+AD: 5cb8b9d71d2989ab33
+CT: 8a0c0690a36109d3e1647d0cfeb9561bae8c54fe971bccd634a33ddc02590fa3332cc74b2ebec342844c1e89a2589af6a72c118b9052ae12b11788342ee169c2e0c51189e8ca8dba3faf6d1d97ccf929e7ffb05e218c36eab2b4943d29a00224dd6ad98e6092967c5dffef62aba7008478bdf97f2a762c9251aeedb01e57eac36a7322b967b5bca4bd6b8bd54e234a0aeac200ace65afbb4708b3509873b7ea7946d8586d5db3ed1eee98650eeabf51467dc139dbc7ebe0e7706171cc8b840d5c328c66fd570540f874eb43fa864c137339449cffca080670b60dc885543e95503e24ad384c2664dc824bc09823c9418bce39715e6aad665aeba78588a382b0f24b52387efae6380663ecc7522efcef2d2ae170a2177f3d653489f4a
+TAG: 1c2987f3a0864070414be1e53d1dd43187d2a15e
+
+# DIGEST: c413683815bcbf3858fbb654590434d5b9f1eaae
+KEY: 3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729b
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d
+AD: 2989ab33e978c4451e
+CT: 059daac7128bfdaf3391a02322a1032a52057d6cdc30a2a83ff6e2cf5cf7c06611a5d25af94232c15d7462a89e556654e4fcb14cafb8df79aefca9e632bd25321e7ef7b91545cb67b5cedfb5a075f8c28430368d0f18113772db67a8b0b11f41192716be6ae0a7f2102be589b95e3d379110fae8384fa3f98a9314deae55e8b158d953508f0f81853385cb8eeefabfdda6f95a351b42002c7768c5e48fb276b3390af75c94c4ea14648235d9066e4812c6dbc50c2d739f27eb94a76d9a1fa4178657a7bdb616cbfa86f2a83ed1567d2d5d947f27a02192a94704d61785cc2fe3c6c5d575e98153f6c0ec0976c9e367e51ffe4d6c02a6c13f66be873ed77a9d15f7ca7ce4ffdfb9d7b56ecf2d59078391fa0e4f24066861a1a5fd6702
+TAG: 291a3e7e1cb71c0915268760f2b4dc6c66ee76d5
+
+# DIGEST: e55813b42aa337183d3c091b9f88f8e37832692a
+KEY: 2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e9
+AD: 78c4451e3be585a29a
+CT: 83a51fdf1e0a256ee3c01fdec162c5008bd4192c2b526dbb4163b593afcd7413166994c6195202488e537296ee818d0cf6a5a8e47a0925e1e51004bc1a2b4607ef26c9237404f69255756e244a0cb06f1a1ad00a6e5d261d507cffea930b3a393fdf0e52e56199ef9e23a09bdf8c6fb441df2772a5c3e6905097b1ee0ad5bd54bcbd6eb7a2674a2ce63af37a96992e5fb353dfffce5a17a8cce059c16537fac26fc9a681b6e2929d6e717098040900b988827c219aeaff1388049e07c030d80315b15104fed0ccd37c46e271c1e4e04829f931eeeca824ff4ed1f747d7c57498588bec7e87c8ff8d67b7580e2062caff3f9d8e93b482cd6e3c01f60d02570871542f3132e462e4fbd27a60fc59a7a7cc97179ba7df2aca3ff6bee51e
+TAG: 0f8e4e26f9bc679ea57cabe6825b641707dbc257
+
+# DIGEST: 013c5a98871203f5494bc2d6927d15ace1e719ea
+KEY: 1e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76ae
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3b
+AD: e585a29a2af12feef7
+CT: 2d50ca52c8f44d507dba0b611cfe7c249d0df7b92404fa74456f79cb32bdbfdb7f5c5a6d505087ba180079f38d27bb4cf2b070d60d8d22d224203480d254dcd60e837b8dbfd51c1550e722ff2fdfbb589f84f259349df71eb8af4b69839b23f2380deee9e01aefc4de8ed96f9a9c371127c5b6ec2045f37912d50fb9d389ebc89d9239ce6f029fc5c7eaaadbdc6336a8f56aadadd9606a3726f10ff17b03a1f3ea05e5dcd06e9e4a1ec0d8dca837158b875f646bf36ce9b142e9621819519002bcddc1a0efa76e94c63af2b928bdd4f8b1e6f90842c4b744468de6b8beb3417fae3d87553169fe1667d2b353bd30ff0f9b8ba05dbf177bff699c1905bc20c61540da0bfab6b6387f981a6108e98d3f10b5f61dc2faffad3ed3daefaf409346ad45e8b841749643b219dc43cc
+TAG: d183b5691f9bf0459f75fcada9f99e178c63894a
+
+# DIGEST: 7f9e8085dff06dec7a2250bcc60532aedf162762
+KEY: e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2a
+AD: f12feef71e1063b0b4
+CT: 0207ba7e4e575a6b442e7c0822473cbb2a243f2ffb701a4060f989298a9a75922fc801ad4170608a0461e721f1092d2197d8b7509b3a818f219b2e9aaab3f267e88ecc4b25e26f423a44b140d09bb0d082785dceb2b00bc7b28b5edb6de8e51f5e8d0ebf82928d24b02f1cbd302c87daa1fe115c30e8f7c1b12322a44493f1f2b1ec626463aa838f86ae65994fc3a2def1d1f75aa68c2d873c218d1c312b2f0e66c2db0e7770966db07451b49319307347032a8c86d01282f95d19832bd57bcaac0c566e8d7108902cbff432031b050a909fd8164ea85dbc916228f17ca50df79ce92673fd74b8b0deeda3261fb0ab8574747189162a692ac09e796a655f83583b46b63dfa1eb3e448243bfcab53c2d4672228e445c9b9f2e5a88783aec4f4f56710bf69ea9a3f7334a441fa
+TAG: 26b00777825b2e63fc052705f41ba9a956e50426
+
+# DIGEST: 0254594a43b8c9b638cb456593750b3f8f9ada22
+KEY: 04bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e
+AD: 1063b0b4e6e8992003
+CT: b0d3bc02cae47ee3aa38465fa9bec9015334c2b6c84bb5c06a0d273094655c449164e22c374937b29ee21c21dc4efb3b3bcdcc31ddb08eea4b9f69704ce32aefcf08fb3039da9636964079e15002855f4ba8757e536b2dc83d4fa81d0cfdc173a61c6c5dc7591b09e64000d105a934c7d9738e7a09a9cbd6f6661eb90155d1ea7a3de606c6e0767c64bc714cf7ba35dd618ba823ce6d89b80d555bd6861eea22a926ce39d4d3e88e0f141a40f65361a30d8c72a0c6e56056a32961f7dd4d54eb6673ec2c6ef90fca76c5817f021eaec43b0598ee952a52d7d79c0f345c42a4394ed82e3bb706d9636c246ab6adf04922e4bb350dd225664cf136d383ce2abca36b3f6a7cb512f82d2fd5a838151c33a47e104033d74540a23144ad73d1608c45662cc4c5958e45d59b088e0d
+TAG: b076149b3d407e76180bf18cb3293a57adacd5d3
+
+# DIGEST: 15059d32a3357610e64a48c19dec95d256455404
+KEY: 2a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6
+AD: e899200304bd350813
+CT: 7702d1d52c644f0ba13e433448710ff25d3cfbe67c93247156cb8a7506551b3c7176ee639b4123440ba6647dfa6ac4f539c619fc2a0c60bff8085d04ad0ad809907253068c3ba12b54d8e17ca20006044e7c86d3541f9f03de3c6684ff57b2fd47eeb88c8a5597b4303c248c502bc73da18bdfcde09a108ced804cd3020e6e4407117052bc3d971edb348d203df7fa3634e3c1ec1dffaebe5810a9121bd74e71f27ead339abf7f437cf00a9366ee70e78499639f484e44dc86b4efcb640a64c417048449e20b837d0a7e9329ecc82c0f1ecd29b13ec252d91ee1e0c3367ee0cc304c0a736d91048dfee0619691d39a916fa1acb87fa9513bf4de17cf844dfd1f5d6310afa07d654a70908355b2dfcf5e911cc5e941647ecf2c612462d691639f39cd8665824d6cc2f63349bc9fc2e67ed66d6c979a666e5a4dafa13f
+TAG: 0ed9131d173057251f74bcf13948f72782e91ad9
+
+# DIGEST: df289e1d102b25ad07e98f430cdd24eef513f8d4
+KEY: c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304
+AD: bd3508132a027d1ff4
+CT: 8879c6ae66d6d1c0dc4ebfd79bacc10bf2084dd379195aac9356263681e5820a834c2d1f97f2471be4e381bc832ac47fed2d487365716c47a6b7746560ff155e90fad5dbf779540f2a952bd779f09e73191e29e3d053a35cb2f0816dff86a80fc4964059c5fd6982d2d6713bab09d0ccfa50db5cbe264b5b1903d2c0e7a300f3adfa46d88bd85fb1c7c6493b99439aec1dd948ec55f9884ccd9db1219afc094fd003d05f0a0368889afe88d450de70ab803b281dfd94d8a39999d0a8c4b5dd5d5eb0fc763818cfd489e75663a97c35755f33af1bab261d27fdf280a9b0d569609de1da440ba3bd1ebf0c8bd3bbc748303754a8ab42a3277594af4416f073a7e5edd1638593e9ccd97bf2961f408a8f2d39510010ac0f8710ef97588b056d6d003c70ed7833170a9ae8735728f2f00a26dd345be9e17240e085a36ee9
+TAG: c1e66ce0973aa867186aa0728a651fd345b5cf45
+
+# DIGEST: 3faf5b20ff66fd6583a2b62901c1ccd798c0e9eb
+KEY: 57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc6
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a
+AD: 027d1ff4c047b3ef4f
+CT: caf92c526ca2f6df21d1f72cc6e2f0d538a7550aa6bae2f3f26b31d4b9d60748c3138784df673d78feb662c33c9b6cb2f53040a64d7b94851eacc0bc688f4863a77425f21060fd948b9f76d3cad6f5560fe7c8612234d72453dbe4cb3017639c90bf3d7bd249e1bac830cf3eeba58a55a24aa1f150640e8f369e365d3f534d113607659405f2b5b34eb9c5b324752b40d2fb7b06d75008fc94554c9bc5b5a7fe6d06934b488e82587b8173bac173110e4823107533e66c3bba0dfeb5bcf89a6abfa7e5ccfb31f7b75cbd461d57baf37c65bf530ffc47c7a1e214263436b55ef9291548516abb3747a37f1447e8a2a6bc5d14490d25efd196fb4453ddef5ceab17b5035beb528750f529a30a593c48c820384182d2a22b0b84f704ee4fb0d70df89f0eadbddd97233af94a72f6cec219cda8c7782a6588021bf5ee35b
+TAG: 219e8e7323563879824fd497ab431d82effc5887
+
+# DIGEST: 2a1f12db7c66ef374e510b2fee81431a4902fd8d
+KEY: 4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c0
+AD: 47b3ef4f57a74706de
+CT: 41b726de79e3f6c4c752c1b9acdad102527540bb6300a8bdc438c6116705fdf7669c951c997ddbcd7f97e9467425a6d2ced02b18dea62ce491d6aebed24f92b06412c419a7b69abf964ac82382a60375a9abbad905936de5053d6439404a46efe12bad7ba50162bb195f83c6cbf4c0c6065bd47a50d4a46999e74f4645ea68e5f7c1fdcbde253298b55f66c2766196a1218f86a8ffa849efaf616bc66637b87af68ec420708aa081052e7c4608ef8bb740bc8255ea23473ca58c914f8180aff5a217b401e155d9bfbc362c5e3a3fe49f9a49f847cb8489be7950399644cf53c1f52b7357de1aa4ee24a8fe4e942a35a15e8e7cd228880bbe6cbec83f64efec4085e1f5211b15f503369407d3024941de3e9f89c819f64e077c92789b9cedd7766d0177b0671dd26157e6b66df801b24735b09e7c6952f100fe4eb55e
+TAG: 0ab84b5baf8f163cf3c814ace4386a126a2e6c99
+
+# DIGEST: 524f8d38ff527d6ba89c51265f6a55211a443a04
+KEY: f164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57
+AD: a74706de4b381c692e
+CT: 8508187fa18f9f1e202027290ace1355dba08d4af8e4afb74d52a7e0aa2005f5815006990468f5982cf5bc97141b783d3713ee8ae335c8ed63d3cfcceb4d433b4cad0aabad5a7b3387c52af24e48bfaf4cf0a6511c0e52c2c985a1be41186976838acbe49ed9f9ee157f8480997a448b0fb4786ef69e3a8bf660d12df28968ce6cb04196225c6a2d14f69d8668a0567bee5e6b1dcadc9ab65742b4561332e68206e78d100724719b4c47e2febe647129b7c896bd92ff0a3787acff249006b856c78d71b860402e0fceb1013c92de542b02abbd4392b86c10438c87bd056ee57d074b57c3d4491959db47d622bd958be19ed4aeb8db0f656d2fcd9bd489b6340a32384167bb35f16b11882878ddd05484afb0dc46f6e89f35674943c3d4a1b3b82240c10036418bacbf74afa4195052534d64ab256547f3534a1604d5d3c752eda856228996b1b4e0a8f8d86d
+TAG: 5ebfd4858c63377e0391984fa84e37a580a7ac14
+
+# DIGEST: b50c58268b989fac3ad8f6d25a401211ddc5cef4
+KEY: b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b
+AD: 381c692ef164101b89
+CT: 10dfd18c8af7dd4c5d11e7570d4715730c8a63d7e270763129f251360a076942d5b1c64f953495a2e3cae2015347c02f7abf2055b0816022c0c281339022788ef520233919e89e417a58846eefc727885509a1e921c27889b3cd9867edf342ae11565a2811d594fd84e95fc3205c8604f1643d2adc3fd3f7080857d1d9ce0f24eb1a72287e97cece89bad62e4a7012115874d04aebce6a89a193922b7611e3d0a05ef6c9197ee7affa2f4be7c62012148251034013398536bdc0041c62a7d5c304d2f033e88b1fb593449abcf722ceedfc3e1823875adcfcbdd705096f856fc61e705537686e1ca298c281d8c3f4bbe1842fd26b8c21116a2061437e9772a7f70a3fa62e5f1027e13c102970e9998d03ada32b0e91bdf8b5f9b7b4aa6fa69b6687597e2cbf280a26b04aa4c15e143dcb3f7a223b6772dfa1a09e166ca02252027549cd9f2d548d75b6ec7692
+TAG: 048e4a0de1f44677091562efc32398b6e06596b0
+
+# DIGEST: 7337152aba55f41574aac9d678dedcf895a1fd7c
+KEY: f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da4
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef1
+AD: 64101b89b476f72b27
+CT: 4e22afb3b591e9a83871c8549747ce7a0093158b36a830f8d67354c13731d8f8d55ce6205cd65c87a91f61fcc601d941eb594710dfe181e4df12253cbfea685fb89ddc9d54d980596825060cf2bf50c4fa712119ad816673c33d51aca814acbd5173b9908b1f1e1c6985597b54d8e996b9e2f15bfb3a01fb521e31bd6d5d7405f1af3f2a805d2416349c6c6a8ad7b0b5adcccb65fb342ceb12e0f2d384c729567ced9fb2e7fa6f5c6155f5dd02c45e5a482b8f3b96c2a602cf3060d026f1ea1d7653667ab46a5b9ffaa685dd5dd736047cd9a77f11182e2327b1caa6e82109b71d2c8b974ed200416c676a374282c60dd7bf7f07f9202908ae5827bc061fcad2e85f795a0d1a8bedf8ed288b61c308e458dad4129ad7d2f08c95ab143df22f90810bce4fd8ecdfa154a64c8331ec0ea3ce452bcc9410cc9037b037eb522f16e793c28900077ccebdc53934e2
+TAG: 22a77e3b7c53c56122b36b729db0e55a7102a621
+
+# DIGEST: 6578de87f977f4cd4c5d6dd6f6f99daa338ceef4
+KEY: 67cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b4
+AD: 76f72b27f06f520c92
+CT: df2b10cbabc4176218c6b9c6f108c1bb25807fefbdfde2ecba5ccd2361cf63db84035427017766b44bfdf329953adb786e6653d5d220408d6bcb4461b204768eb0d8e7f56eaa2ac707182972a65597a4534183972b48d5190d61a497609026825f7d02bdeeb1d9421d13c217e3c17faa9bfc3ad587600f934ac8b508be37589416a51f5703c9244178b3102ae59d5f7b5d574ddaed1b3fd1ad7c47939d9c1ee08bbbbce47288eafe3b508743211c79b75db22873c1eac4b9c61d5684d94d3aa4c11b01cb43fecf4fa06e0945767519d7e7a89526c4c821d24678baa7ce6ede7f2e8b4c9bc70706be730148d159c1d6158f27d7511ba66e1310e1bc74faa5b60f12fbf9b539cc25734a9ac0762204b57f565fb35dd6e96fb84b1b7934fffc01e5afbca911ccac4953b1e63c596fb9268ff11676571df4084236b327e802f8855466089850d0ea9e96873f774796dcba106d6268916078a9062421a616
+TAG: 8de4c38791b5c4fbcb6cf996696d97e7dd218337
+
+# DIGEST: 38dda49f961e8d18556e2f4cc30812a7e17d827a
+KEY: 41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f0
+AD: 6f520c9267cf71408a
+CT: 52b3ab3912ef6e742a285968809db8eca231dcce87daeee16c7ed2557167b8df32b194e17218e03f8a4fa53aceda990b2b76c3ca4b527d89affd2fa47a19a876196296cafa94b72a0b85b7fe2f9b49d6c43e1c4862c703bb7b8433b2db76dd9ca6eac8a7bd7e994db7521b7c1c628a728387f042fda0be75de1f783a957ec75aaaec6b3db998ca8f238ed636633f87d0ee73dd8a3d4889ec61006e10d5412d9501b8a25fc4ea73f8a08883850bd573ffcbfef595f6baccce2e343718fa71fe72db06f5022f05b2bc06eb92ff836af3426c313d1813b849690e983c90e2d3f502f4cf7003b85af82b844d1058874d2d48986bf90c781adbb404b79b644d298988077f192d25df9697a4b9577b6b56a72fd079adada11b719b7063f72858f4a993ee3d89bf92f36f4ee23194181d393783405fa6c87448753b7b3ff387777d8757ca65932b24b494398a9bca45fb578b63d81d3d1f191d565e63f2a1e7
+TAG: 0ce4a2f392b64d7981a20bdb7cbea3317ab719d8
+
+# DIGEST: 9a4462e5c302d0657a599d31a78f3581e4b1684b
+KEY: 877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc82
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267
+AD: cf71408a41729bacb5
+CT: ed1c1e41992c0784cb35b220c4c1acd1985a6b96c2084f2dd6a8ea7409d39cb0f983ec2aae41e72ee9ef204a1401d4478ca5f2b068c9c5327ca260b2587d44ad53bd6d830340411da14bedd9ddb161df5ffcea3cd1c51e98c16512b657a9dd38f1ad9bad415c6f7d29c059507531594c44145d560f6fc9e11ba2f44efbb0309f9fe15df97bf1f5599d71707a45afb8a366bae722597a6087ec82357ce748db0ba87812e2ae60b12a1db5c36c1eb041dc9910335d44f35b209129394524ac043ec759fa1e9d46a31b4cb3e248817bb2e636bfbcf946e1c61b81288d571f693ccc02967bc7a1f21b7b75a0aa3858f732149c6c97697b1fb37f8e41ce99aeec3b0b31f8e1b2f6d612c52f6764f63dfee41699c26d54fbe15001a80b026de35025031043821b79900c08eaec35112ff48f36116fa847c40ec9fe98e92d11954d35e8538c3b57cdb8c2dcb9d1c96011147c743abd3550b69c6e40359de012
+TAG: 976cf00a1ace82de693c002cba9df69d29ea8467
+
+# DIGEST: c96066fba6ca75beaddcbf7b6bf1b43b2a7b6353
+KEY: fa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41
+AD: 729bacb5877e72cdfc
+CT: c97f9422501111b5e8d41a02331c741db0f170ab55371933ca372c3b1c77c15abe3771fabfd2f3f4bb8f163aff56e5e04307cd6361903b037d5a555a518dfc7bc7819348db0a05c6079c6650b7f8560a971d07bbf9dc9c3034450937735807145e8abea960da5435a4b7bd69204f97ac4f3eee248939d3c1f890585c408158d9ca3b5c1fc59d75de526892967c09730b23d89623b6219b6646e503de4d088170928973d78b54d742363c6313e793c557a6717d16fc7f73f144f8687420637b2624ba3a23955e1342930a6c350b095101b9b3598bfd1d8331cd0b0b44443835456ec42b29adb89efa9b64f6498df3c8850d6165f5d74b5796ae4ca8bd29fd7cf30e9a3970700d741f6b9f00548bd1e997c89d2fd0a16075fbbc5deac2661fe25d9704f4e27237b86124feb77490f005cf0e5a1b706812b91667b4c025d733d2290e8f704e6098650a8cc720bd4217e20ea8649ded31317a540f070d15493219f401653dfd2afb2309c0e4d06a
+TAG: 2dadfbb06299fc25fdfea99655051c8bba078921
+
+# DIGEST: 0cd3dccc73f4bbfcc3c62b4638bcca5a633a2b37
+KEY: 07a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb587
+AD: 7e72cdfcfa76aed067
+CT: 3f144ecae12b64b1754688f0eac019e5803454c5b79f94c679495f2f2e26b6376949d2b9f8d322ef2a04d4c514e17d8cb9afde3961a434acc21e09a022d83381aa25e4592779433402f772a175f5d685982ca4e908134ad9a13916e125f33dfd10be9922f739f038107297e72708a19dc2452c7a2a64293aa8ae508072d99f4c83ec9a1c2df5f48e4fae6d27edeca1892444aadadbf83c669a86b1defb2be7322e659f3478b38ad82525e4b412127661b676f798cc4c0c21522948d9db6e51d31cf11a495b4c38159d4939952c313dbca903b9b87524d7bcc7fdbf19126e926a6afd970a53c6542ca38986d90967853c502cf7b8adf0f77b38bc004b563025fa1c0e9c4e17e97a8f37daa112d03e35fa3526bc136f178897776bc35b6fd6194d8c661978da5b50bced6811ffadde94bef268d97162cafedbb237d2eda805b43b18e8a356aba96c9d7beecfbe4a8d35e37fc88acaf4bb851e06fe75d9b1f3505f4fb0ea0fb806f5ecb135d445
+TAG: 42bef68540720e81d7abcbb337641c74716ad11f
+
+# DIGEST: 61f7a437ed58c4d0c66997aeed34757d4f36926f
+KEY: 699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9b
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa
+AD: 76aed06707a07c3dab
+CT: 9169e6bab5e2c9bb2efbafa95242efc4e42dc6905000653b98c179ec663578417c9c2149b9868709a7bc550bd7831939ac540c6510fe15661b09192c0814a22f03ac79190a0889b1aa5d165c927149c86b9ac0abb32cc50d33736edcd31da2ba1e4f60fcf35e8d088df63cb003898ba843aa99e410cdb1b8abdcc3dc3fec2bd3752ae5ab0a2b858c3e451fc62b95dd8b46ed0cdaab69608376fd711d0eb7e017d11528f353fd37965e26d905ee161637dcfca5cabef495d3b074f5be708e074008324792a0d901cfee936dd165ef18799ed7db508898370574255a95e190f428b1fab0693f400a47811e4acf0319c76581146e48912be4cc8c8e496c2df2fe634a8e18f99eaf1ba5fcd21c810bf8c9ab28dc5dc59da6685603ad3c14281075948268b452ae0187ad6bbbaa8f8d275c227ce6921c4b0c5a837e36ee17ee5d2460213495a2995a8872cc6b3c621dd338bb4c375448a74bbc7eee4d6a3b4ce26caab655fccc39324799cc4078a3
+TAG: 3107faa6e1a05d54646e5b83b2ab91fc61000327
+
+# DIGEST: 9b062a7f63d081bc4fbb8cf13db57ffdb7d113bc
+KEY: 2eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee58577723
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707
+AD: a07c3dab699719fe88
+CT: acd60034dadbeb0b29f9e43f33df5e650e474d48ff007a6ebbd7f86d8bdf8177b81e3c31347fa78cf1216fcab0952f00a189dac9164c58639aff79c9138519a84100af1911dad011f01e8b9e49496a51e11b7e211efa64df95eebcdcc3ad152ae5066e2b80a31f456357290d07b637df0566e4dcfc672bb60fc30725c7940f397e3d486d044ea41df0626355a36913f6f6d4b68ff7e7f35926eca8f0f0eabe6baf4480ecac852078c4609e3e92f942bd63bb4438c4d370dc0cb7d4e40228273fcfc96c08e39a3fe7b765ef18753b6c1c07afffb902c788ad058e31440480f1dc2def700caeb66d980fba5eb72d14cd7b385e91712cc719f0b6654b250a823848b0ff42646ba211816f8c71958a50c090db514fee0a4ffd706a3b95ec71112e272fb8832e34fae9b2d3f82c94c6f808f708a3c7e1c5d8d5929d9e44b0a7bfccb1a1c198d42b9e30986b581c1bb185a1225389df109ff1687345d7b4be9f6d5addd6608c87071968415a12c97933079be4482362ba3c9acb80924ec02f
+TAG: 359a4ce7b8d5ee784081002b31717662b6bed9cc
+
+# DIGEST: ee4812a7dc3e037844fd9c35770734168c4ce2ce
+KEY: ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab69
+AD: 9719fe882eee2fee55
+CT: 96514bbba87db4dba9b5ddec2139efbb5887b65fad1212133f6da03ce1a71b77987fbfe4c4447455f956aedae52a6241a88a4fdede9fb0e1bad955cc96abf5b1b34caddb470a1e094ac62152a5685c57877319aa3775fee4db3e2d179bcb3cb86f58c0e0e4f4e38d03782ee926a399c3332e9bd136b45929fc6a00e12035754d135809bd6705602a2162a29f87ae13ed832a2140255a23bbb68bfe71c99e8cd25251a04fe87f30937f763cb5d6973a90495c906b0ed74581ea0e8c1cfa6ab5d977407d74a0c3c7c131d276d802bb993497079788c9f6a3525cb18a2d65fdcf757c0062d5c19fd0cf184ef0806008cd1ae87fadfa04d7b5a95c5e2716139b82b25aede042caa76ca315e17c4c4e58ce793e3725ec5a40dcc65e102d21eba7b85074f0c496e28a63274de40407dc2ffcf6da8a7187a8370c9826698402521ca3bc9fb20bcddaf728182dea0a728d48a03056636844ff12cbec4eec7792c62a37ef9c020f3cb69608d92520900bef2f6abe55e917d0ce12d1b2f2a41097
+TAG: 589b01897b76019e4d23180af96ca5463df8a7b4
+
+# DIGEST: 4209b9f203b29926176f7d54ae89ce7e903009cf
+KEY: 870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d808
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882e
+AD: ee2fee55ed8b11534c
+CT: a97d4be4873411771d0c3c86bb4a4610649a74d05b1e10db57af6b45d273823462258a9df3b133e46bb134dee4ce97bec666f1c21e029a55b5d40bb34faed140a7e932b0a4b3c9ceb9028221076dd8a9e4e7d18c3c90f19fef440a9304be5fb9c55b241dbdfdfe728808fe06ded668984b9a574c47cf8a3224e2935182502261f1d21455938b39b75dbbc2399b0a105c1dda39e05a262ef27fe4f47343ffe9010c9abf69a8351a7d7c4b30a312a20ad5bf55b5606180b2a12cf5fa1a0b78140adc2db254942849c01d567196063ecb79c9d7ace4331e40e57df620b751cd098fa8c875ae83edd30c40ab9852f98a8cf6afbf60e8adefefb538045117f5e362605305776b748382d048d84cea0e04eb9615f5c26f75c725cdc8f7034ee1d0ae6cc6e08862fe9826945586d5e99f96b79c545e6e7e0579f594199ed16198703de56deac61735d8410534721a32c734856ca66e260d3499838419e4859e8133f9deae819d4dfd561daac4f45d0471e71ab863bc1c1a832c412e3fd936ea
+TAG: 0ceb6cd190cd9844dbd8a860dc5b33e29ea2d248
+
+# DIGEST: ef5c6927cf43e0994fe5d8e87aeee052b6828289
+KEY: 14bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea371
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed
+AD: 8b11534c870dc695b8
+CT: 5d4c72fb3d29791d044da718b25de9934e6b297dd9e33d0f5cb0be6a9193cfe7d850350bd26f6ef889b2295a9f9a82bc7fa139b4201c6ac59c45bff394dfa707178f4ef94ae3739a0f1ef6e385702966102d231fd27a41493318cd51418e90d322439e4ff58feb1f9b45b233eee8eed28738158bca9d53b579184ef5d5687b2a419dc1cef68d4b4f7a782e979f7c4ef2f97f801da6b5aa9d1c0bc0736f50cd3ed4dece7573d895b67a2f2d6fb004806778f6e9c6bb14df1deb8e931dba87287980b3290c84bd7b55aa7daabef5037e583bc5932dfe526a55a128095dee020a5cd99fa3af69ce674a71dab3b4c282e904b8d6eb6f4cacf3026ccaeef0e260381129527e1968fb9c8b728d342100e2d500ecc4d1060a6b32e6730d695fb8aba898d0c64a1fc4a0f39bf64cacaa9265eb2520082f0f8d0c967c4a5113762096bc6a553fa68d2f9778b08807c5e99cad5acc5b14cd6963399b05520e8ecd7b50a1fe448051450960f74ad4b9aec57605e0c1cd78253bee7c6a7339b1aa22440fa165e7e44760eab4aac87688b8b0
+TAG: c84500647c5be225d31d3e03787039311d629b77
+
+# DIGEST: f239c330cddd57a5e88e777c848cd66e508bbac0
+KEY: b1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf7826
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c87
+AD: 0dc695b814bdf1a87b
+CT: 083deb38197f9b8378269fe2c20a28aad6218aa3805d4d1722a6ba7a447710f71244e38d0c33c195949e6171e9c1fb53a522296a2c27562d35896d5948b886f7d5f6ef95a4b27a16a6b524ceb60acf96e1896f76144972b07a763243b5cbbd74599d2a2b64fe9e0e5cf1826f07f8273de31cf819c890d8c1d6ada8f1562d1bd0327671ee4271e1ccf765de3eba46caaf48394265233e3460486f60a3f56926d6807566a712acaa03b04f4623a4abbe0a31c3bd109d58e96cad275d9dadf7790aa1e4be7014be6eb9bced40feed4a3232a179f672aa1c162156a31beb5602527db08883e4bd39c8ec32715a826e957b1f8575a3e5840e373ec45b2aa2ccfb81b2a17a0f23d3114d6c7301c964c7120e722e013140d002a2991920d19f2fe5d25ed265190569b4c3e197e49d19a43dc9f126da52f46ee2b9ec75dbaaa6f594474531b7228ca66be6c820c9b7d42c390b68cde3ce98e886c91fb77a0d10716641d073127c00172078004578965243127e8dfc67f1590dffd2f2455e3854e5f18cfeae2d0a2b6c24de67c02a0dc6
+TAG: 5593c57a3ab3abf2d9824b9df0f4778e99dd1520
+
+# DIGEST: 7384b8e3650297f0e51d9a8f76de34eaa4bc9fcd
+KEY: a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814
+AD: bdf1a87bb1052c6755
+CT: 27d1f2bd2e21f99e75ea4b99877cde2d22c34b2ef059aac79802efa77504e3dbe6883ae4d5e41f0616784d3188add7d06d45d26fdea979be4ea5ae687c81e250c6fc6f8fe1076bd37ec50768889652d7c604b026c41eb97d884cef82cd4c80e93675fcc0a059ce3e0cfc61bf18e84233fed0521a136a4080316b4c9176849732e8e48d61a17d7bd614a4c86e0ba9cd2672d0ece285dd86a532a403cea4b431bb821653b97defcb2076f278f5abf8110239b5319d8b9a6abddbe96228dc16dd512d06c8bf5abdeb2554827952f5b98e93fdd7d49b9a3686e093e8cacc2fe5e283bda680500b48854bc185c703e79969d3181d922f02f2ed0b651646b1c6126849047a3b9f79c624a33e3f8ef68038929252345e1ff1c693b96325c04a897dbc09d363c9eeb63037772808c1911343cca530eb11c69ce39860f82e9b676493499b7f6191bdffe780a770b79aa1a74f0a49fa37f15a24f585869327d24fe599470091965715871d1368fcfc71fb6ccacb1f50cda71213944a9a250f63f3a169e986c7e8c9e573e93edec03d4448
+TAG: 4e16b89dcc8c298594e247eaf8d5bb1e2d26b428
+
+# DIGEST: dab0914dde7a8845203fb78f9b0af41ce550adf8
+KEY: 095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da1
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1
+AD: 052c6755a7a116bfc9
+CT: e2ea2cac5a4cfdd8631ee6309ff2119e4625d73ffb6e48e8d694c55b7d636fdf3bfca7b100dc78eecfec200fcf58d06314399ae4e646e73f7605fac3c63733c2a5045d4cf83ffcf68603e63f8c646793be1ca25676ecb384810c2cc13ca8007cbe723ceee6f392eb831f9c4c541e21ea993876636326947677ac5b89804f30df4a27d07631c880d3f03776a1b7f24114d0ca4b7d9964757e02066f62ecc4a61922318fd71182de1a56b2202e92c00b8885666f385e07657ad6b92201f7492e8aaf14e741c6f38d7f799d4ad9acf129df2bc634373b5973f1bd257a316cad58a0f17eb03549e5f706ddfa8926f0f20a2c0fa0f81ff4e608b4c968c79305e58e34b528fc1605cedb88f6b733c7544ae95d38f99969f150f189556e5618e525f43437e666be027fc6ac8ecb261043d669eb94ee553e275fd64095f6df62d5789b90aab649d3f7f7167b414fd1e748dc80ab9b0f69bd1abf1b6eb6e737755910e68256f13bcac73f6e950fc26d7b4f58a5cd3105053e6031b88ded4645f95ab03ce2eeb886e4e5d52d7b414cdf73
+TAG: 0b82e6a4515e1c8f061d5978181d07a4bcc49d49
+
+# DIGEST: b139e0011fe2e768284091a4f838f86fea1e4a7a
+KEY: d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f43
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7
+AD: a116bfc9095da49db3
+CT: 58b87fe042cb0c4c869213616b87685eb2eb8ccf80eaf00e68747c919892e7d8bc38d9aa485d9f3822f4da3e2ca327124b0ed52c2f7378a08e0bd787fb7a336439b401c8500b1d70f32d6632a21e411b1160cf967c4178b25e1d479eeb0c455a666d9ea7a7efe210c0978f72eb11990df5fa4153d93baa9bad94641a170f954cea1d2d4cb1ce7e96f9ee793ff25d4d43d008b6d5cf133f61512eaff05fb14be90739e9619796c6d3831deaa7fa2506fa3170f9a4e4a106714744e8196dac22a31e6c9c3a2aa8d6da4d568a61e54e3028a4e59c8c492583314e90479ad88c49ca6394a0ecc3dadf40d5ff0a28cc29eae4a495f180837120dc7e6bbe45abac52b90e8ad0899f40332a07e646888de5a8ea55db87ff1876fd6b7c8ef50f69e1b40029632b9c58d4006fb26c8ba1abf64708009ef67820f670e60db618df3efd9f40e7faee7f859a113d5e9ea7181bf68a26d180bc394856ce57217f4f1d620f3e5b7c9e1220ea726f407aa4a0ec242cb6bae6e180b7d4322fdf49bf27eab946692b51e873e7b9b76e53de4991ad062df286ff874419f1864dd71aabb834
+TAG: 47da95508c164ecf4f985b7fe0ae148b556b41e7
+
+# DIGEST: b338ffac4bbf3a2e41fd1b3b6d9d224d4263b547
+KEY: 5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f437248097445
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc909
+AD: 5da49db3d71f4b975c
+CT: c69587a3af9209656e7c8592fbc8a79fffec4dbec3682bfaa5bbab1e9977bb081fac7a73c840de583e97decbbf5a6752576223c4b08958a71e0f981e1f27b1fc4b96cd1e7fd2df2303d6af831ea7ce2b6674d693c74917d04198fc96257f192b9c08cf208251a62e8a66cf99d2e8283dfdb5212095bc16cd88dd00005bc34be680737e64e6d1089e8edf85393fbaaad1c28369ad366ade7baac9a971c00f39d9eb84467410025b98fea49413adbd48196cb9512dd1c806e18570d1f6cc2c2914472f48cdf5993fcf7d6df6cfbd372fb71982304763a0603124104419cca2ccc303774951e9d1a4f41e608623904c4aac898ff3bed9d353279e15a032a04a7bbf4dddb0764728ac457bb4b1d243d8ac0dc73a9c2420029288b97029fd7fe59725d0f6313d81539b7c11558c94947264b4c00a974dd62191b59453731360338be011e381ae6d46a92785147c17ad1dd725221176782ec699620570e35cb348b36d974e6e45f7ea49889094f31756cdbc0fd238fd247e5d2c51bf6fe727285356345677147aac72b1f45477f41bee8f692206db9f563263751d3cf739a2
+TAG: f7a77c476cc78dff1c23f98b8c57b6d276019acb
+
+# DIGEST: c9dc1fbf134470bd3ac0d9855918516e5b8d8778
+KEY: 22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d7
+AD: 1f4b975c5d503f478b
+CT: bbb6bab0cbe78c3d1066c7095262110fc14c479e44411d469c83e852abe3fd3bbbbfb3456306735b0f469ef93f9d792d7f4a4f3062978f9bc838d664583167da462152f25266bfa520dda945fe7562bfdc2a78191d3c55195f1492af8f31703c171375ff2b2221e9efc6251b346e6a0ea9c10772926a5bb1bc4004f8fdea3e7baca834646803b5177a5c4b6f7822a92a4e4d28c6db9c0932b5c2d019aa1059c376e675f452a6ba35eb7e3517e20dc8ef44996229ba1d69846442ed4f2c5bf9cfb555fb73bd29912d6e5afea45b502a0a5f4de7d90a2922bd80d968fcd39f699590354636de8cac1c49258550d46fbd8298d6cf34dd859f9f2bf6b3ea20aee0e60dbe7f9b7b06d5e6993ca977416e6d450029a5232e4d7349d2707673fae01730810c7a2f5f77d5af3d69f20cb6fd1746d5afe4c1542dcd9a0876960178838aa6cf2edc0e17f87a21634d7efa0f208ef3ef5e6dce8f8b16f46f7e379b1f1eac4b0d789fa4ce9c6484519fd907935c8a250e226e4b330a4a109697dbcc79d4520729640f59a7d0e40a22b9652e2b34480994fc73f54f70c20c4f4f0117
+TAG: 25210947153971efdbcc388f14d616d80403b774
+
+# DIGEST: a551ad393bcdeb8c1bb1a4a70e367b069ec549c7
+KEY: e6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d
+AD: 503f478b22dc8253be
+CT: 92a056b861f4177ea827a5fe32c15ecc05ee1243de09975aeb00d5b32ce60666ad858be3ba1deca076199b702003cdf64a4e40d7b3950e5f7f4601366f906eb03a550c2d811221a8a6b2e768ab8d1e576c49b11301ae55939dc7d2aa030936922458e2ec07721cd122a5706a39f0021dc348424ecbe92af1bbf383db837958848ee5655c6a443b3a29a5366ab3b6ab9cf3add4c65cbf39250273a079345611bae3b1096f841f6e027277df046c122d29e1e5b9b882b36bdd0f2ce051dd889b73abf0c454e22e5476f918d357a6091ba3299294c6c2ace938793a56c14072b9166e388644deee327982b773c823636ab0d962881e4805d778cdb6c6034966d4489e86af4399b8076702d6035edf5c38ab4e80e73429460b7631cd212993cce12778f137c97abedba19f38b713870f8d7f63315af67607100a78f704dd0bc44a3a404fd70ca604b6a22b5407f7349281eae5380b698c9e20a3878bd23c9cf35f77e43c529baf21cfd10e3b60fdb06d52a34581bca607573de309d182f080e273d896f9879438773f16b050a414744f59d42478b1033e2eb263a5b7f0bcf3feb8870f45c780292d4d2836c4a927
+TAG: 270975712dd2568fc7c5f6218bc620df04a749fe
+
+# DIGEST: 45b1d26c62717ec46530a565c9e11c18206bab29
+KEY: 307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22
+AD: dc8253bee6fd1b174c
+CT: f8c9831657e40d019c0d05b8f79185eb0e75d27098fc1aa99c66ebff5c97969a378e448fdf30d6f38a792d104228129e4d87e70e85a7ad0a973851c5eeb4a2ede2f35796a2ce6a056f2e8cde884cd0cb4d9f5f7ee1c2ce932d3a597029596af97b07b14b844f4084a7de41106cb77e9d24fb2e4bc647d59c3c47cea97215b08b258ccfa92a30d3cb099b5e5cd6f3fb58de0dca4058e60de309ae9eeab026662eb670db60d6d7de664204e3d7102443182309f4f40321cc1d115995511f16c4c9c2e08486ad616e387739176ec2c7a69435a61f654f27516667785bfa75ce5393896824928e9b69ddc0955c055644d3a704b8dc14650ab1fe01c38c6ff925d07457d72f4a435e36dbeba36ac5cfb19c47af263aaf52912eb77243ec0017b58940efbfadce7cabe38fcb06347f7da1cae9bb03f091984625192375e9c0e3b51ff64c34096de9e3f26fcc02c5a9d023fb5e5d81baadba649cf93699af5131ac44f5f0e08cd1efe577aa7febfe7893667ba892d7a9ed93af763fef4c06cee67d42010c17e0b934841158a8d888cbc94082da6c632eab6f3fc1a4559d26daf7245a67f4af0e34e9b0529e04dbd1bc
+TAG: cafb6999818eee13e04283bf16a4d2e81becfdbe
+
+# DIGEST: aa7cb8f1b995ca51405931f1d021ef30a5b0eb3d
+KEY: abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6
+AD: fd1b174c307f01be95
+CT: bc607a6306096ce9e70e6bbca7a22d39ad642c58fea6b3f3681dbb24da8279244badf409292187125c7dae096687e19fbe139a5f0f751bed53b960cd39e8918b072680bc3fff249ef9ae5045640bd7f038855f3e4786ba66919cca8dd38dbe8d3f2ab2778d44af12c6bdf4434add471d1e93168df1b7b6e310d9cc727b1f68e186a34498fdedc3b1ecd0de9e79b59b6ca3d5adaa3c75a2b8bb2a892a214aaa37fb321f71d006a1bff1f4d2fd33dcc500d14221ca590b8308aff3c5abb149e137acef7d822ee3442d9740dcc9843a81c542918611cacdf0f80f297c1d4a74aeb9528109b80e23858eb942b507736b5c94942558ac79cd266fd2dd746d2592ce9a043537588d692009d9b417e002fa18689c6ca1a5437745f83ffb925e387ae3552fceb8ef347f1797d37f049986fa07b4b2a4a8bdd043f91fc863c5dc8734463e5761051ef4e038a874b6c8cbded85a399c27eeffb2fb79aab5d3ecda4ff316db38dd05f23a6c6353f12e38bfbc2d415b7633e778600516ff1785a876c300bd3db01ceb5efe28cdfdb94239b3ee543e84532ec96e22aee767a977ef74547e476b818fe2c9425a2bcb5e3592e8
+TAG: a8351776f03d49bf373b6227157f58ef5630cfef
+
+# DIGEST: bdbd450e5d302436cffcae83ca3a444c0253a85c
+KEY: 57772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea0
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c30
+AD: 7f01be95abaa9bee58
+CT: 546f158f89157e304802d3b194f4679d887fa5e7b9380fd8a529fa7c101c3ff237c819fb254a75a385bf8e22c4c5129a920c1b0297c6fe06cce701c36ec8dfec315f54b9a1a9c438b39b4f302b921546bbcea00d9bdc1ed7d74e71eeb3f763b41d6f0a640395faf59d61c7b99570004004a5a0e5c97b28cf350cf79e9948c91c1cbb8cf81baef18bffd1cdbe22e82c5c60432003fd7a72da57a2b93f37b9456fab6511ba1c09b6627466cbba48405190d1199fae0eae624903b0c828dfa85341ece889301ee3c38624c4bf6eb19100326761e2dd001eb95791b31ca1fa9d1547d91ef5637b53a0e8461cd3d3515abf9c8afcdd076200cf65bef73903f5565504723b41811d2b49460e08bb401af8969ace8ade353c78fc7a483416b1a7c0c2b06ae1f9cef65a3b7e7db9fffc50bdcce947fae8790dc531bd556fdf447cff672255a5f2316425537c1d6623e7b5239fa87e5e6e4ab781ca21184340c59d9996a22ffe312f3560caf6de5ce18d8d6abb1ed5e4b25e51deee7cc64d389cd8d0dd611d3d7fec39159f7d4c07ba7accfadb8a0134630d2d3b8fadc4fc1b7e74ba00e9c31c5d665c45c7f73fa18c9994590d769f93e5cf3fef535068062040
+TAG: 5958171116b990ab4984e60ba3375bad82202439
+
+# DIGEST: af3f40d07667dc7e32a1fa664c6f5503c3e2c8f1
+KEY: a4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95ab
+AD: aa9bee5857772305da
+CT: d63e48dba3eb1d466e836e4e0098739655a4a78557aa3bd8e57be6f9625844c2c42941178d96ea3c1e86faf93299fc8b9b40aa9542b84542370883939cd81266576da98855962d002fa6598fe7bc5c6f5804280b64672d6b7a3a06c4c76afbf62fece44fe375620ada56eae3e4c40b2ee8cb1b4d085e2d7cc9f836e55dda114f5a2dd21df88ebea6ea0a97d65ef014dcf79279571546ade3fba652f6969ae21c692a1f65b5544f7338d3adf420093e519ebe4b11fe589fb8cc952fd267d65b64829c0cec40fd1b44a0ebc8b5b9356b97672248c45c6f357e8c4d493f44395af88d3f905d96040cfa227e301438043f8874d9e4bbf0349fd784157d13c9f3c96d371b9901b550a7376e446bad5435cb885101e950d340c62e1b4b8cf179a7c0f7c407e41f51bab8265f6e5ecc56a921669c9d4e1d13999b442cc40c777b990cccf51b65cc65d72c2cf2e242a34325d8639a4c8a533a3e4e3130fa33346f13c807b21e5fa15121d025f17e0c773d936cd5c294c96292c2f1c40d80940277176cf5667f15fbf593927b1cc0519cf77d227ff21624b8be4d10fd8fb1aff93a3a97fecc194170f3e397d8295c3bee39b48ac92b15c85af958023fb57a5fe2
+TAG: 0ffa77947bb23bc8a6cccba5a5592465dbb214e9
+
+# DIGEST: c6830aca35b85932f7c5df33907ca59bcc489a85
+KEY: 05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857
+AD: 772305daa4b550d75f
+CT: 761dcb055f9c8420fc734bc8ed9db220299e342e205ae568bad20d8d2936f76a5ab824e43f29cc60568e80e4fda30bb0bd02a2ddfa188c609102aee343dd4c5916877b982e11637f6a2bc719b48b6fd3f54e26210b2ee307ba31eaa15f1ba29e17ca2cab38f219de9559de06de87ecf0dc490e0f7910ca70c588abad351c39491546ff9e49ef1626fbce474ba66690c57d4b856dc2e298ffa02b807d81dec4f13f0aa29f8708b5fe5762de65204276dec4f7e22bfb6771cb1b29919162a4c469cc4f179ea31eec7088a0b546e66daa7798afa655696b486f7ad23c2816fa7b468e9974f1b33d559e8c84eb2a1574a0a20f2a1c084b95b4c8de8d73e104058fc8a434dd2094bd7bf3a4e59d44747c1e7aa9b18747b1c44ac1ec5367e974ee62f5197e0d67cf65ac4505ef465adfd76b858cca29ce86ee1997ca6b12b6468e3b1cc9e651c5cb7272c18781007888a28e9def8e92fb3df84c1858b3f1300e645fd7ce835d41eccd07efe87bd22df4f7f1205a28fda90913586dd79b847bdfef187e0f3c43d6ff51329fa9cd53b536da7eb233cee64cc8975e7ec43415a8032457b4c6b5d23494cc698c74bff88b7684773542a0977fc011f05d36af855a
+TAG: 92b91f4933516e7ddf95aef4629594da2b0f0387
+
+# DIGEST: ccbdb85e0a5bae6416136d8d64ef0fc8ef3bd52c
+KEY: fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937a
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4
+AD: b550d75f05d8089850
+CT: 12048f02ca2ef39e4f29e114aa976b6947f28fc51c0d428baec2e180f4a8bcf24d28c954f3f43070ba235576f322231b2cff04e890e916d43eab6cfd9ac0503eab292d5b51bce8e6da431d23bfdcc47841bee19affbe2d8ad7df33a3f6e3f07dfcd00f77f542cfb6f5434967d1ba10ad4b82fd332ae3c973acc2ebe3b905a04806a500ccbfac27c9e73f382a211052115b5a850ecbc797a9c07bc29c3965452f8ebb8500f30312c03ca0028aadb92bd7481e8017ffe05947f3677eb15d17f4441e3ca9f108f54bf60162a55777f98bfe9fda5ca80cb8c3e1bba672fb6e4789042c0f33e3c74a6c05936e3c483496ad901e021cb2f3196ad8d079309c75f27068d3c3c623d56e86154b55634205e580b51323e2de1a73a868b7b055ee616fd2fec4dc7a7920f6178cfe254134e013fb559a02600913c9d2137a2f87964e9bf081c34cc0a71b7afe1a72cf8b21784ddaa7e838325a40f036d20d18de6f6961311854082a099e9be0d543521d4989bf6d386a71091bcd8639e1140be65729d7662b069b0918a1d824dc3152776db07186a3f4168c4210747e3ea54d1dbcd14e4a85f37510c405bb9be210d2efb2a53af490da9a229fc275f5549c61c6635abfea4143deb9409af6e8afc5608d1e
+TAG: 0682570499a4e2f697eb93fc9675ed36b713b8b1
+
+# DIGEST: 9bc71f6083d602ea43a5be27534283d8953578aa
+KEY: bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05
+AD: d8089850fea3711265
+CT: 97c08f8a306208ddc424cd17ee5d596f635b225aab285e7ff5c18227b520c22946ecf7d4d449db30817b89876ced2f3e490e7417c7c4d7b6d13de1583ad02d492829c83a7ff09a35989a21816b3a68492fb179d6281bc2572c37b6a615b3b117bce255a43610171efeaaccc99228dc940a439e9e20773d257ce232095b7a02ade7290dbb95cb48445db7056d5d30f5de69ffcbe2e65bc38c70776c37f0439d4b16b39008a293f2fb9b3dda7b2160aa78b7a16e55c901107f92984b528039844198826ee1709f495b34bf6fe5af4eaca12940f065d3059892c824dcc3950c1e012e82c0b3e19d4d7ddc6404ae3d474f28cbbd50ca02ba17e711094db7ca776c248a96722d7ff94bb208c6c02e05d6dca8170080b5cd07e0f9d303d92c0b6cd1c509d728399be71725393e7ab8aacc206487b0c7290f8418cd2eb529d4a3dd095c367efecc8135c465b427f6fe35d3d00da4d87ecf19001ba8373906aea88cc3414dcf4aff273f283846c39d908ee52536523c078b353fe6d94ebdc16aafd7ad4101bdbcfa1ae8a4066a5aaf1e1ff7a9d068fa3246cf545fe64f80647da52d912a9e64525db3d9093d6fe948062c8f741e07d0336e135c20ad3981c6ea4f14afdf9f930e50c8feb13bd4e7d705
+TAG: 9b2e2dd8f940e25c43bdc446c1c6234e3aee4ee8
+
+# DIGEST: c39bd34f093d3b18f254e8a94d2afd8f70eb4d75
+KEY: 0bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d7222712
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fe
+AD: a3711265bf78261046
+CT: 2382a3e4d43619e1596ef90c5b79fb198e4eb178c3ce524b812ccefd8e758427f5854eec76f3b408b1247d6be5fe0b1d6dc5bd061b2a7494b6d40c0fadcf555811de17999d5fb561a542f1269d44b6eb3b7b101b3e746a741b55fc434999bec21fb30fb7d4dd4b75b61e889976cd64b76fea5834a038bad5eac4d8c5bd476a64cfbc08095e36544520aa52b18b25ffc9652eb3523f87e12b82570a590be4c43b124719b50dd14030370f90e9c6e7f55ceefa2f135a98206fd5c7906f75d135639152130fab38a6c2a7edd9bf21a4847da2968e886eb450b5e8f00afd94a21268353ae170220835efa524dae65ae9e6172f32adaf21c3ea29280e6e01c4f380dde9c6d8fac5cd158a95edeb84abeae89c8748c484fc4a58e42003d50bacc1f55094385b17f7a5a1acee5f2ea1e737b832891f1ff344ab2b9b9531e68c5487fbab69772e4abc0d149ea1007fdfdd3cb201d3f2e5753098faca3b0bf1432a9ff55a988222343be6cb131af249fed51e92c24b168bb44acd283354060f28fbfb807036ca11229af09b1d325964cbac93f8a0c674324d81a4dadebc08f6deb368b58bd33413c5a2596aaf69656bf4a6524a2ae17a1e21f52bbddea5acd3b133f4d84e0393d92b7362b234abde7c30
+TAG: a4f9da4208933a9a391a6187af1951995ecc18aa
+
+# DIGEST: 630e1d99053b3cb7dc8c5c78dcb39fa7b0b53e74
+KEY: 2e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf
+AD: 782610460bfd24ba02
+CT: e3658fce6b8bb64c0fbe21eca4027dfaae745275bc257d5c99feb998abd4a6e9521ca1ffba8d54c2d909cb2f2561046d79cdf42a1b8bd086bba23f942c0bc5d56f74f4a9a72f25a4f470f431b64dcd78673836fb238439a21fc1338f09a8e813b08e168f70fd24d880aa304f3dee3184b963c4925766b8aaa44289573943a0c066f208c302ef1536bf125a2b139722581d36d34e904f6d7c5dc354218e1532a0918ac115d0b5fed7cfee50c6430540b64e618cda52f44ea26e7d62c01d6ef12205fffd5a4ed40a5f4581a57394b4e429deda25a96e7d38ecd27f9cbd596701c2e1f42aadcacd4d7cb7ed9713111765ce50476c8888875ed0ccc29edb3f6521a1b1708030d24caabd7725420c5691c642261f43694900b2b357449d43b19309d5e8fbe6a084ff202850cd48aca018cc3e3ed42114c1e3dfcd687be51f27e68cf397273c19209825570d1fbc3444f6ab20bfffe25760e736a3062e8fe0354cfb248a7a48a4f191792abf3c895d8b6b9c934a8c2a499e49d858100159027a067cf0bce2c9de65e4570b4f21761989f8f5af25de362ec3ab61f3544c5381f55e1e2f0cf529397144a5e064dcfb1b3262734eb7184e176f16524bd4fb53e91ff0553753f5c7375539b6fef45cd20bfc3bd476250cdceae7bc798268d9dec1
+TAG: af8dec713022951f306f59041759667b34a5f7c3
+
+# DIGEST: 083d60536c78fbe909d2b35cd5b891be34f2a60a
+KEY: c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460b
+AD: fd24ba022e6da12dd4
+CT: 5452596a11cab5e8247db758ea029b27fd2a413d4ea5c7e7e9b7f4e72b3fb93eb4cae4f26f4c443feb029473ff8f229100ecfd6c397bfd6cc4ea775fa2b12f2422383ca4abc4118417c9fa64335fbf0354e152f2245e83cc111475d56a0a2c816ec3f920ca96c446644a44193d744b4ad95f1dd3c1485db8ba50eb8463902019e0e47852dcc2b5367280e1724c357f911f691299ebe68f321d269b5ee5f3ffed5ef4493e125539f85b299f4ec037767a3d68d8c010e9c7a2d0b2d7e3b05c9ee1fd8216698e7e7e79954c1c433a49647d1d3162ec0faee67fda9b027ff5800ab72522036a9cce5e6e42b8a0b8e59d4b3ccb6d2b327e41f8be742196829138214109abb0a34af0f4e91712be0ba6aca8742cca08f0b3117e7be7a91925a4600d7cc69e58583aa61574fef12215f4b4c46e075f62dbcd0f69f6fd655857ed104d921642988a015ecc083a64227dd80ce0b7e9ce080f814542d4243c82c4760b2626ad327a5be9dda7df5daa3c5936924d49514c9a6e3d12d8f31ef0801c0ff34d6188630ced37e4ac3de3d986f20415bc87f6ad86c4046995da036b3a223d0aa16e2e78aa4a809ddb47fc92ad21a76cc358167b152a92f66e89eb967c35fdc129ae309e4c5d6d8cb8f96a5f9272593fd1f2e2871367b1bcf057c83c5474
+TAG: 7b48a800b0c78cb0026c5f1f1ef85b3564785775
+
+# DIGEST: ba36e689ce5c9e3dbeba5ed1cb00b265c7b30d79
+KEY: 0974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c9b66262c0f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e
+AD: 6da12dd4c27f437248
+CT: 41e1a02a53b81e3d916b0f7ab52fdf917459dd672a60f366a46112cb26007fb5b2b38f3ca9dc32c116d9c73119061a5c9b1cc421bc63359439dfa4a02891711f858b8206e1b02731b8fd7b40921ebf02c4cc9349978b3c1589c1c81217d19556c33b9f1d45e6afe2f8aa753d13393bd3556f60b71e58a57bec31c828bd3d2c20b148eae0ebedbc7654a080d0aae0766ad0be0b08906ebeb2dc68670815ee91aa0f2ad302d0e28662cd84d83031917f85296fd706028b0c11d41efd8814f22b8c665181b905d1a690394fbfd3317a077b10637e4dce89d85aa54643053d04a0c179aae0498d91130fd1aef5af0f5e12c7fc02bbc6f425995437c24cc59f45f005647f7035e494ae1bb4aad4372f62794bc33bce0b58459a8c32b0986405c2697dfec246e2d74bca42535f424be5d9404b7998695405987f5de3df233ace70be7722e4e36097b1f6f0aa58e6dbb211f4f820e81a697082671bc717259511e2e790b56001fb1d9c1451a729a9d435ee9d4ff2d57225f28c48c20a5ca984597ea5b221e4fdb83f9c7eb3a7fdc16c1fb6851380afd0c2c20c4c555f60c7563a42c4287cf9e62f93508a8d9eb3d21491b4dec3ea042e8a3a9453cb8a6c6d0b74661b0ef667aec6e11799c635932c6fbb31f87d01e6fc66828a8e8fc61cf5bf
+TAG: 178fc270ae283bf1914e5de1cf1c1b82fa896d27
+
+# DIGEST: 2f9b29467c1e54888b4d4db41fe3a943887e305e
+KEY: c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c9b66262c0f0368fe9d0c
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c2
+AD: 7f4372480974454879
+CT: 54b7b878731dee0ed7e52959582a4ac1c0c112ccc1c92b12f3e5bcf9391161aa48badac21a27051a423f7ce8d346486b347b2ceec45ceda308183bce1add943c6d85031327d5e27fd9cbe28bb7b18ffef443b778858fb60359540aaf62e74e750115a8dba069817d0c324ea6a3a23475997ed851e9a299afc2bf0ac7f653dc5362e846efe9392a720b24b64fa9d446321fd0ef2d54e39737dea22cf94764743522cb67cf21ed9a8ca698dac845fd37fe1beaa3732de61faef354df0e04f8e8ec0fd60e86fab12965e95b8e0b82dd3bd35991c74314cc34c13a9ccfe627520b3a9ed9266bce8bf4b340607e8b0b7d2d2548690ada448d5203963d363f425fcd0fc681f0eec748273127f8f0e366ca10e7f024f82dcc763e587c053a05f49a09c9962617aad3fa6f600ab4081f19de809b431453ea6236afecb5688a5b1a3ac3bc205341a80666c602ade7298969cfb322ef26e154d16b88700ffbea28185f9aa1c109fb0357071e3d8c5655c304095660779c3731ca4f5ff53d577490db2e44a03a8283dcca422eabee388f2f2b2d53d774c0928d5b6e7191aeded5fd2c24ee9c92e5cea9af6b20818b7033464d8cb199513af1b582c36ccef51a1093da9123d7aee836f37f3bda6a6457f0d9bdef8d2dc6212753f182d75c6a9d4fa6
+TAG: 1047dcd2893003c5abbe59e6838305107ee46052
+
+# DIGEST: 070f23e02cb53f55b0127fd3fddbab83e5682275
+KEY: 98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c9b66262c0f0368fe9d0cb746bbd558
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f43724809
+AD: 74454879c41de9ac9f
+CT: 7b61fdc182df0b0f3e1ef36e99bafb954b295ab39b2aa67f0cbfa848dbbc6ddea6e762e103216e814340b92a539deb7f8aed37a258c993381635b0d00e9fa912abcab37e135e0d88befe38d172c9331376cd541e279dfbed6b7a04fee4f8a4cb9f9f4cafef5d1da9ec104c8eb1eef2fbf79fcac547bcdb6589c03323bf95af0c5e3b3f297467bd40d1c2b11ad38ed396460945ab9cdbf807367fbdc0257519aadb8dc6cb46cc9fe2fc09782a475ecd870e6325f8c42abab69be453aee523c2fcd729b4cece57d82b72c4b4a3d4715f73e1612a894527c1e214f0ff0cba5bcdc5ce830bb1db12f70159d90db8b454b8a19f7d2d14137f64a11ec93886be20dd58af01c6649010158c88fd5b3e19d492977e0ec991832142f5f78361acb243b9419b7a928261cef944f9fa8f00c8bb76ef7b9ce257738da2331cd4504eaf0dc0f61ad2027654c0cbd590f99210243eec65a776faebac13e96f00a03837cceef450fb997c39b1aa680645b8a8bf31afcc05e07ccf0f39fa45d779ccca69dce520cb15717ef4dfad98fc5bf2776a4635edceceb71e99f0278ad0dad826c5dc8b186873de60030c9336d41e877394b3c5a3d8af97927e62351d3ff8879cd8f0bba12993d61b3c1542d275896ad0d841fdc86f1a86e80960be9216eefdc1eb93e3844b9da671229732bd10f61e1d5a
+TAG: 2a1fc9670df5fdf20e9cbf479f9f9e7fdebebc16
+
+# DIGEST: a09f0450fec556fbb3a1f869c9780c3d12547311
+KEY: 79a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c9b66262c0f0368fe9d0cb746bbd55813e8d45481
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c4
+AD: 1de9ac9f98233b5a73
+CT: 4a8618bb21c8b2a26a50d5efde0f4adfef21664419951e96c0ce5b3776c693d49a2cde406ffb23f212c293a60f1884c8be12c902bc24fb52cdbe41e225d3782f62cf2d9d5ad31ff210ab35d07a5fe395b168f575aee5a75b405f7b15dde886f39e34cc038f4bf075764dd9a1ae448e16e64c6538d36f621c10763482961d99ecc1476898d26bfade04cd796ca59b4c6ce92ddecc91109a0bb37b0fc0b08daad10d8c6bc86eb22f3a354d943dfb4d8f3c3805ecb39c645eaac13ecfed6457e254b1bcd2f589d2032e7221a7e179445c5fc063fe1d08e828b03abbfe92ffb95eb442a30f7a469f89f3515455dc647324679bf4df189b8624861a2a17c021ed11ceecbe1a247133d8739b88b93280b2c9279fc967675539f61e1163fb2b64e9eac8219f2ea1faad49a1c77c8246c41c62bac5fe6554fe6d3c6b4e46ab3c305244dbd1e8975bf73dbf8039ad6db23c356bd9865dca873076cdd8b3f6baf659613305dbbc2d04560f2fef872da55e1994d7fbb14320e51b7711354e7edbb9e7709766fadf0c6c44ffadbad87609eccc2b70d4cee87db79efd515de9065d69c24e7b40782d7548e789ebb7c6946989224a3701e02e28e355724f140198aea804fb2dbee5f0507ef3579b5c0acdbdeff7d16c667205bb0677b9e5bb33234d481aef7bba0e491d142b6b75ac4687bc4e
+TAG: 93d80b0efb1d74b9e869f280b487e386280be7d8
+
+# DIGEST: 32559b69ebdbf4f1fe7c6e5ada9a4117836eaf4e
+KEY: 0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c9b66262c0f0368fe9d0cb746bbd55813e8d454817c212d3a00
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98
+AD: 233b5a7379a561792c
+CT: 40867ea63f638c79bb33c4defbf8e35be3a632c60b1bce1eb70f4ecb80c0ec31dfc873bfec82ef82fe170e30cc2ebe3b1dbe341d5b49781a00f2e2b2cf1a5cdada3409c341b141b6ce3c7ea4a6d92c98bc3288297c0cdf11975337b6f03be152bb7917387a3b2b50de49d501e57a06c78e04167d9ed058a6770699e43797ab4b1e51e3c5e622f237ae9e1f99def71a67466db2d957e1ac80b856813337d0969dc3b788c68973fd2b58792a5bb570b8d113fe88763c58d17951c345f5c13fcade97e3c0124c5be3e979f64796746b5667950ac0f0fd43c1930e9e1e90d3598d8c15daa463aa42a46995b21c9d2046814a8a0cf2583a0f21c87755bc340c0270692909b6969d2cabaed1e801bcacfa3218ca1043f5e94fb2935ec55ea7b43f5e47fb9267cf887c2a81d023987ab41b26d4d00e8cdfff7aa486298a97fdaa939e0b0b5a880ccbae8ca68b3f0fa9c6914fa702e87e412b6b5e3e673dfcba087c5f98fe203973b98561aeca0fa33856cfd16cc37cd0f1373575b6badc2163f565e8ce2765cbfe9264076388f431161b652e9fa5547529b9e6c3c7e848d97d9253005609654975c17d1d5fc600c803d8108b9ecfcadd354bdfb96edc46607d41556c44c1d5c981dd38e2b7e72b00f7eb4e52462c0323522794b3791ddbb272547b038362623d5dc4312960c60c67e5
+TAG: b3e5650300957899dd1a39ae3d5e725736729b8d
+
+# DIGEST: bcdc01526c7b0248abf3a41ac893bb72adf422eb
+KEY: 8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c9b66262c0f0368fe9d0cb746bbd55813e8d454817c212d3a0063be26e063
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379
+AD: a561792c0f3116430e
+CT: 02c169fa50f4bbbe70f9fa2193ad1e2abe20477b7f0bc3a966819d04b65892d1159154c703219632c7a3c9ad3129de230c3d3cc3e88517712531583dfd6b7f57ddfffe8b7eb4d0ac81ed3be7fc80f6d71d82a322f890e071dd210d1726bc1cc1f6abd78d044b65036dd7cfb728589fbffe26b7b954578ac0036c5e9f7eacbff13ab98201f1e894f57304bce324ff5bc61f5850f1048f30f302086a5804f366bf58ce61d949465ba2ba7d31cc3ac7f5952356ab3de8e7844a6f2c197b67e32ecc2b8480f8e81af75e6d1019e11f7ee0b9338de462871910783faff9eaa1f0fbca258f6872a7ca2dd708b1c059d41e4cdcd7fa1eb616f817b53bb3d4f6820fa87ae44c65bc5dd74e0e922bf4ff540221424568bfe74feb139e1af8a540a5e8431532f7332ef924af01922070da6c14f3ae784a18790368a1f1a0e4295fa6ce0a686641de77fa91a615dce62a0eda98c9ef252eff58280243bace254db39b09025491dfb8ffccfd8f7396caab122446f74f6847016b390f0163ff1b30786e8883607d74c3fef78cf63be2c0acf04830be0f8afc9412f08a6d5d8e9c985d8d6571e4d69f037940625a91f6ad518c5b5d956b1a4e7f4b7a300babd8ebb190cb170b51991119d8d33cac92872936e9b563d4c58274af6da172cfc41c5bb527d77010a3803573f69e3030ee5b1095e01f47cad2120e30faa448cccfdd408ebc
+TAG: 30a902f3ddb7c666d3a62de3c641db01ff0100a1
+
diff --git a/src/crypto/cipher/test/aes_256_cbc_sha1_tls_implicit_iv_tests.txt b/src/crypto/cipher/test/aes_256_cbc_sha1_tls_implicit_iv_tests.txt
new file mode 100644
index 0000000..06ce309
--- /dev/null
+++ b/src/crypto/cipher/test/aes_256_cbc_sha1_tls_implicit_iv_tests.txt
@@ -0,0 +1,840 @@
+# Generated by
+# go run make_legacy_aead_tests.go -cipher aes256 -mac sha1 -implicit-iv
+#
+# Note: aead_test's input format splits the ciphertext and tag positions of the sealed
+# input. But these legacy AEADs are MAC-then-encrypt and may include padding, so this
+# split isn't meaningful. The unencrypted MAC is included in the 'DIGEST' tag above
+# each test case.
+
+# Test with non-minimal padding.
+# DIGEST: 7f3a0e20bde700d3c5596909282e5c3e764c99e7
+KEY: 86d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660
+NONCE:
+IN: 936a91d0b5
+AD: d2c0267218cb7090c61713
+CT: d88861dcbb181ebd603365ed262b8f2faf5b86ab90a8930bfc0c55cb
+TAG: 9f1c88defe20893b2d5eb8ee6809c2452f302315
+NO_SEAL: 01
+
+# Test with bad padding values.
+# DIGEST: 7f3a0e20bde700d3c5596909282e5c3e764c99e7
+KEY: 86d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660
+NONCE:
+IN: 936a91d0b5
+AD: d2c0267218cb7090c61713
+CT: d88861dcbb181ebd603365ed
+TAG: 262b8f2f50b02faefb172ea4c7478e6f7477abf5
+NO_SEAL: 01
+FAILS: 01
+
+# Test with no padding.
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07
+TAG: ec90d128ef465f4a3645fd0b2601fbe2b0bceae2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: f0f82752a691ef5866413f2b2e5c1d0ebb41ccc8
+KEY: 7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f58
+NONCE:
+IN:
+AD: 936a91d0b5d2c0267218cb
+CT: 612c50f907cda81e17437e36
+TAG: ab70f776ab74437f9d6eeb87fe373f855e71d302
+
+# DIGEST: 7f3a0e20bde700d3c5596909282e5c3e764c99e7
+KEY: 86d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660
+NONCE:
+IN: 936a91d0b5
+AD: d2c0267218cb7090c61713
+CT: d88861dcbb181ebd603365ed
+TAG: 262b8f2fcce52ffe745fc1c7ce881f2ed93c7fbc
+
+# DIGEST: 5b32faa93c18842b5cb7b075270438756d5f7dd2
+KEY: 97b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62
+NONCE:
+IN: 936a91d0b5d2c0267218
+AD: cb7090c6171386d641b877
+CT: b5a44ff124b35147c8832b7b
+TAG: 08bd2f5f31a10eed64200b62f72b9c71a06a14e4
+
+# DIGEST: 995a0f9b029aba3e0a3205364628bb76baccbf45
+KEY: 56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b43
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c617
+AD: 1386d641b87797b684e0fb
+CT: d128b6056a11e9007634f1993def8750f83702d0ab0ab723a9a2df9f
+TAG: 967942ead5a3160aae2e81d44dfb06745fc5df2d
+
+# DIGEST: 023d08d5e5af3e0b016103c7c3cfd1d02577888e
+KEY: d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b8
+AD: 7797b684e0fb56f97c3961
+CT: 6433705ba5fa7475ad4360e9ea95dd1c94f42a409014ab838a265f38
+TAG: 7c92b586e69347343f5bc2835cd925ee0f1ce9ae
+
+# DIGEST: ad4b11a43bb47aec3e91209f98f99839dfa1d6f6
+KEY: a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0
+AD: fb56f97c3961d8afa22993
+CT: a511cb41a1a4ccfcc8bb2f3f1ceabb5894dde04c784521f037c2884d
+TAG: 9a51b8b056fd7993b5a7021f08aa891b8fe758d2
+
+# DIGEST: 580641286aa43bcef85be190e1967f627713bc64
+KEY: 89c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c39
+AD: 61d8afa22993a340b9b3c5
+CT: 4058092e17118a2a5642a6748128b9f3a1b4f6066df062f50ca8b2f33f27d8ee6402919ed7265c3eaec7bff4
+TAG: 1e228c5adee4da5f5e011c451ae6b1898c37fd73
+
+# DIGEST: abb06965675631a07f380e80a05cff36c2d42ecb
+KEY: f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997dea
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa229
+AD: 93a340b9b3c589c7481df3
+CT: 0d661570231e6395ef7d3622744d4bdb042eba415057c7a1d0b69d5a3b45d823ddf46c14b0ed290b203cb992
+TAG: 2d5d2039ede69ce09d1486f4f69ba47edbd879aa
+
+# DIGEST: c6a1ebefd827cde32df1d38379ee4bb6a7f81267
+KEY: d8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3
+AD: c589c7481df3f4183aa23f
+CT: 9b2135cddb9bde3de8bde3bd28443dad97160f9082871f54335b9adf2e8d38dd4e2664d6617e60c90df1f5f1
+TAG: 1b950ac39f86f765edfd995d3e35aa2b2a17c404
+
+# DIGEST: 77fcb5875838a28d24c4b6bd0916ebd827968073
+KEY: 03f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f035
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481d
+AD: f3f4183aa23fd8d7efd885
+CT: f5ce2c99afbf0b4f95b9fbb637284a3ae9bfe40459cdbdb1422508e4e1bcd0439cb43db5666c809858a02019d50401522e4a17b9aca15cf4cc4d120e
+TAG: dbdf6873c9bfc6b220de50eb22429b3b6b56ba0d
+
+# DIGEST: ff3c91da880d2942bbc51adafaebcf4c6fd50603
+KEY: c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa2
+AD: 3fd8d7efd88503f78b8ed1
+CT: 1584991deb24d7302857918d975ac183244358a337f532aed39d5430a24b880892e81f81e8ba4333339344c6d648315c13b93441876c3ba67ae9e6e1
+TAG: 160029ddf23401042a0701286776a79e1f18764f
+
+# DIGEST: 8c439bfcfb896bd106f94676b5626f2bc624c313
+KEY: 773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b5
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd8
+AD: 8503f78b8ed1c8e9ba2fd6
+CT: 20ec6093b5cffc6112d7e81f6a7c15cabfc0198ea72c6150996d2d67b786053d008f39a9f72dd1d7677a0b8eab398d2e6158e06b868d9d61753aec98
+TAG: 125d0570de85c4bac646a252e5e25825b0dc9b7f
+
+# DIGEST: 35d9dfb89c1883210f03050da3166b6d13f5b8db
+KEY: 2a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8e
+AD: d1c8e9ba2fd6773e0d0c30
+CT: 0478014ecd403576d3744dedaf875ad6edb95e02f8a8adcc8eeef2f7046be074ac72dd4657fd1beb285797cff933dae4dce573639a3d4453878aae0af7ebbb45698398e402ca1a2f2d20f7e5
+TAG: 62f533f9335a2243381353c18612c344310058c2
+
+# DIGEST: a07054c760cc66fc704edf950201005031f3faac
+KEY: 446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2f
+AD: d6773e0d0c302a5f47e037
+CT: a1e92776d0ffcfed03d1be956169f606733755d5a7011620c7ced6a825d8e59627e75692a41a1f2a86e62fc6052873b5458616414584e36bad698cf4c44909e0a26e0b32528feac2d7f69abb
+TAG: 480efc7a17e891603a7f3838fc28e487ca9ee348
+
+# DIGEST: 63efe7af502231420ed5aecce9a28446b257828d
+KEY: 7df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c
+AD: 302a5f47e037446f5891d7
+CT: 2f25b5a3b01af5411466c8aa5d8ece037434d5e12b62306f2732cb063d0dcdfc2725e67118a242a5576d470fcaf9be6d811bf2789cc66f5561d0542438b5432fe713187a879fd80e1f4edc21
+TAG: 37f430d3b33404c96f691117b9365042a6bc9f17
+
+# DIGEST: e8e41988fad6c8b44c56544964cfe0a347b35b1e
+KEY: 933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409a
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e0
+AD: 37446f5891d77df660ed82
+CT: b1cf0005c93547664e09031d923c4ef9ad663a808189cd8aaa68fbada340d8bb13330499131ef3788cd91e9527702a2388802fdd2e91998a53ffbb466bb7e362d06677edd673cae71418a67c
+TAG: ad9732821248c5e5b7c9b5b6a440ab891ec922e1
+
+# DIGEST: 172f4992e692a88f49628e5d3937959be01aed2e
+KEY: c55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417d
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891
+AD: d77df660ed82933f62be8d
+CT: f1ab85a35a17541efb4f906e7fc85e64efec6ab40d59d3da920c4ec09797c3ad47820e9d934e51e3f4d097c4a555575939bfaeb8cfea062b64816a160d6e4d1ff02a5fded435ab9aa2daf22fa7d676fa14684ce099f4f0e11e785320
+TAG: debb89c7c8f7d31a0a32333f58ad58f9ec389761
+
+# DIGEST: a35fc7d25f90dd9cbd35910d5532aca8aba88b29
+KEY: aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed
+AD: 82933f62be8dc55b436965
+CT: 1ddce9b3f674dfc1b94a6cb34418e6b75c93f14941a6dbe028ed59667404b93afead95ec50b9393a8e0e5f469fc1cbc5136f4dc54f3a005af6c88cf70ff39487cdc730dc131538279704a67492f5241faf00aa8c46d4307434911577
+TAG: 5a6db0a9323a8851bfb81e3f7981229d7a9d0360
+
+# DIGEST: 4abaa8453e8cfdefd918571a961d8351754ad5b4
+KEY: dd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be
+AD: 8dc55b436965aabe477e0c
+CT: bf13550fa32201ffc699cbf22de17ca268652f8ba2693dde72b626d01855eea7c21f0afae3fa03dc757491e8efb9091a4c100f8dccfd15a9b4dd94e4fe1f5e90cec62768d0a91e132acb1fbec1052878706359cab3445d38b1a78737
+TAG: 0bba8adc9c7ecac4a0d87033de3ece8478ecb0be
+
+# DIGEST: b51001b6ff9d27bccf3103a4961280e0a1406257
+KEY: 1eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f0
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b4369
+AD: 65aabe477e0cdd46be9937
+CT: 4772e647d03817c0f9deb39ff4f4f27fb0fed33e0630eb453883c707336f0e74ef206e92e31fb2935a466105dbdfd42c180ef63cf5cdd3c281337895e399df6078c22762eba5d84b8845ea00bd88bf5e4f0da518cae42502e8531b14d979bda6a89cb7f4f54501b3fc90129f
+TAG: 28198a9c52b7864a4a25ea34472f22eaf51209f3
+
+# DIGEST: ad2b43eee27e6267d8c5c1c3d558a07dcd6b1f5f
+KEY: 997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e
+AD: 0cdd46be99371eb8da7dac
+CT: 67466a0bda0815f726cd09d159e06088b2530b73775a8c18eab2d09ed7bd12b743b0a10345cb3126dc14d8f5c503b65a45467ef9b56ec7c5b24e5548e734d3f0fc90fd9c8019fc782882ea6e72f4df5fc6e8105e79d12fc588c9137c758995666f480dcf24b828c3e6018287
+TAG: 3556d7aa83282257dc21e5f34c1e5599e7c76aeb
+
+# DIGEST: 7b17b7cb19107af8fc4671420e461060e2ef3e61
+KEY: b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+AD: 371eb8da7dac997deafd64
+CT: b1025c9eb02f72e5526ef641778aebe786c2f85961997f1eaa090a33caae3a9df34da7088352a2df7a61eaaa026dadbcd604f5baa3a0de4fcbb3812816408d61384984141d9c78f47e725e99cea9d52f73cdd5e2c3961b035589db1d2283476006a1e10a992d4997623f4415
+TAG: 54acad8bcd9bdaab4641e1e01fa569c9a0e5e61b
+
+# DIGEST: a27799fc2e00e7abec4c5939451a834c4606cf7a
+KEY: f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7d
+AD: ac997deafd64b1fc65de39
+CT: 9b6a8359acfc5d15067e2e6d812727d768f44b3edf4272f57fb54db41d95153fb03d7a7b3371e91c4be80326f4d70a8f2ac1e867ad3772901c513895e694214d6c0fa1f431aeb016ccc93faacb4950082f0cf00d3a5879c9a4f3fdb281e911b40d6d0a84b05f4ce32f85b1657d75a3c72b69369cbf0d435790c97438
+TAG: a38109f3988e0faa64c5fa9481a847527f01c85c
+
+# DIGEST: 7c52593d1d37b0dc380297231c6cb7b64e04c493
+KEY: 1be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a95
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd
+AD: 64b1fc65de39f4f03541a1
+CT: 8cacbae377d038fe27b37fdb253f3b136aa38660743dc6b4778ab16940a9710c8f08970164316e26c3b603140f2f43f62a88d021426b841baec29fb11a3d8735d0b8c14d133a825e1044be5523932ebd65b34433c083c2d77af313a240b1eeb52391728dcd04852fdcbf9b6f89502dddc317c485c893ad99aff613e6
+TAG: f95cf9c6c1c976c30585e3a7b8bdb5d1991861a3
+
+# DIGEST: ac6871d354eac507556770d8b6bf10b5240273ed
+KEY: 33c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb8
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de
+AD: 39f4f03541a11be112a729
+CT: 9807d89925c67a45c8ba18cfdb817f5bbc21e58c10f7dc8c15b70acd97e8b97e0393d5948d51a65f6f092590b38c845164e6d2b49288bd0f73c4f4b551b362470638f51422dcfdaaff5e8aaf80ff715f3f597fb9385ca18355b8e98d1de17a303d019f7d4b9a3acd07d257c049fc16134c53e1350cfb8c287cd3491b
+TAG: 8e157876e1b7a1a09b5b61969f6ad7ff8d1c80b5
+
+# DIGEST: 4f498d0aa9205160827626ef80c163275eca1f78
+KEY: fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b14
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541
+AD: a11be112a72933c7b54ed4
+CT: 9b01cfa97c72b5ae8befd0d357283a52f6b8c5d9292d28f61373334280f815d6b69f878936738cebaf6fc84d20baf51868eb4d2ae08d64e724beea1887a76316acc955a00b5d1230fb120bf7d51f74fdc5f332521c59406bbd3161987c6ec49ad946a6a51755796de19830631daf69c78a847d2e515d409a7b77ffe75ee785184106419b8c7f38061f49cfe3
+TAG: a265e9d442fb3917d21f7ccfe3230c101816885a
+
+# DIGEST: f0901e8b8083c39222fc940384eb73cb96b22892
+KEY: 41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a7
+AD: 2933c7b54ed4fad0be905d
+CT: 452c39f1ed638a315dd21cfbfa383115d3345ae07f9968f2c30e47a05891ceacdc0f3b4669c929765f51f69c0db940b6ed5d0266894292e57d04c2fbb3b1fe2bc3acb98f87974341ed985a151f82673c237d101161ec73bdfa6144198a83a6e7ce8866b5fbb7bfdaa908dfc2fb15b917f5fc167bad7a91872bd9fa3744f28b2df449014989cbbe0c48237408
+TAG: 396bc6821c4d65f383e11c7a741a9e66fd6cb76f
+
+# DIGEST: 7af193cdcc8d7f17b55447a81eef3dfdf345bba8
+KEY: 998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54e
+AD: d4fad0be905d41203f5dce
+CT: e4879e4b80eac7bf4b235ee71db7af4a9b68cd4151d92ec1d33476595c714d4c6d97810f5c88c7ce2f45b181cb0a20b1969c88039248f7fce86f7f9458f51b726faf05610b76cef8afd0855a658feea188abdd705a3de0a655ce2e9a54617d8b646853210dc47dcb094c1db4c198cb1bc4796830bd6f806b6f08fb86188279614fc90365a40a1943d26e1890
+TAG: 11cffba98abb9a9104cb1cb16c76d349e4d9d598
+
+# DIGEST: 4ecf44faa266de0904b093653c4d623a543d12d8
+KEY: ad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be90
+AD: 5d41203f5dce998f8fb2ea
+CT: 2c1a333439801d1d17c151f7ce56725581484bd90b2847c9f9eb3935f37efc7bcf398b46339386254a865b9e555f8980362a6057a0a1011d719136a09e2856d8a978b5c67d8da48811bb6f4f25441325529b9eaf3e3f0102871a191880ed5ad0b42be1bab94dbe64eb4efed91c2c8fa0eab4789179120f2a0dc172fc99829160e6c6db8ecb8792ae0ebd893e32b5493783befed569b17c99f7bc7087
+TAG: 6497e62b8cfe7425b179f8090146be6903480323
+
+# DIGEST: 92a938017497e0762115325c40b5f7c138d5c6f6
+KEY: 16417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe6
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5d
+AD: ce998f8fb2eaad409ae021
+CT: af71d8d9603b26c45f5f6fbf5b88d0ee7e2abce004c012faeaff1c0f6779dc54c387976a14174ce5b4407840591e92e1538b76f958286a98a37007afe80ba99a11d00cd81c39b6abc2567e70f87c439490f642a1cd0691941c0eafebe99656459805d0bdd36bb30effd1e2d7931a6d0aeaae860489eb05f9f9f9fd11ebbe8ca751bd21c11087ed4b9edd0ecc2006ea1ccdb53f7311c8a71982409227
+TAG: d759ed87bbd8111a082e5a1cd5986e27b52bb59a
+
+# DIGEST: 6b126413a7bac1069cbb5b338c158463a242d607
+KEY: ef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad246
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2
+AD: eaad409ae02116417dae0c
+CT: 4cff025015d0aadad5fc178ff562305391c3db629b5f376287ea83ac43b2ca20b72d9deb700250430d36714cfba995d16d4ecf2d7317ad7cec870fb335f01335ce75d39c0f0cecc33e658485732d18681b753ee4ec01df14284d619ae5329c5ddb662fdd987979601a37a53a67e273da3224339f047d62392bf868052c7fbbc95885f1e69991bc31c344c2d9cf00ffdf9f4b573abe0420317e91bf46
+TAG: 8f06477a7f7b7f79f241d40d7c0c9616732e3852
+
+# DIGEST: c72d214b42ed66ae0822fa9f3bda306c7d58cf80
+KEY: 16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518c
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae0
+AD: 2116417dae0cef457b9e5e
+CT: 16de4a070472c578ae448e3c3303ca7bb0910961995193c23d7e6a8ab32b6b6bb84202369705d43962903b0d7f1b2fe7d963e558fad39f38f4d4a017701710badae74235ba0b3b6f8c846115fa8f36cbbd6b41efe933d51c4f3d7e89924aa6848947d8c57f6c950eae443025f614302863e8415312e8a727840126f37b299a26d28c2c7686160c1ee27e3bbde0c4346f050f9c906257d31663f6b2ef
+TAG: bd25d25882abe288e646d725e9313052a86cff31
+
+# DIGEST: 9faaa58dd34a192550c3519f8c0aeb2ff48dd388
+KEY: 5607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd29
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae
+AD: 0cef457b9e5e16dcc5b6f2
+CT: a6fda8e3bc0c1a2cc69ac359d338159b984f31ed1e1f8747bcd7ba473c3d0aa7f0f577d8115e74bc71e077ad5c320f3250a0fd21ff531e09f746f39377e4ad02f34843b5467ed61c839ca899e2b0cfc5e37c5889b934c4ddf9b862ee4f5c9bfa0db31dcfe6622e81a7caeb65a96d5059d6b58f9f440ef473be63192420a6f75372c97af21d679e17165696d8825223db470b1eaf65326fd8029fd5ce582f8de285e68a7fc4c5167ba1a9b2ad
+TAG: c8fdf133a5b50b8cc9cff5f76364d28419f23809
+
+# DIGEST: dd5e6be3644dcc888cc50c0b2ad0d55eb0407fdc
+KEY: 3fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e
+AD: 5e16dcc5b6f25607f00d03
+CT: 61239a68ef268c69afa1f73aec32aceae19915a59fb977f948fce8352f16cd782fee60f9fdcf7b98357b7220a727081344285deb0a4f866e12a9c77791b5cf506fe35fe1d153e928138952c64a4091fe9d337d7b760960261476e338cb18c0c057ca756aafbf62f2c38e5a5faa398e5c5a043f33fc7ca61a633e78b22c007fb7ed84d873e285fdd551d8eb16f1db1b337f94b0b7aa231d6c2f0f6cb4c10ea84061e157f0973c46f6e72a28bc
+TAG: 2adc9f39ce32a6940d20cc7f14ed61b753a698c7
+
+# DIGEST: 1b8b627e1020d71318511d4c2078eed315ee0b04
+KEY: 4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6
+AD: f25607f00d033fb95fb09e
+CT: cca8cf31431023c84ea568ff31658dade25623d4454eb7eed13678718ed549a081c75e3e0b7266e8240f6d446caa99560b87a37e3644e00a3d37d435b1f41e8c511f1e24c6b96413b3ae74acad54ff315075a86687264ef232aa20f37cdde1ffa50777a3607a690a0421189135f4821692ff1d37fb5f0422d680fa1cf31439a4c730e49aa1bf86d3867c97f82b7441b7c28cbb9fc7783c80771af42afcd9ebcb65c1b425b2a71387b0c303a6
+TAG: 1d8f007af408c027b36f3fff31371e3cf3602269
+
+# DIGEST: b7370237d402dbf76f1a431cdfbb37f41ef2ad4e
+KEY: 780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b9
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d
+AD: 033fb95fb09e4d00d6172e
+CT: 59408639c245d3fe4c2a12537254fc2eb3b89e79c7354e02e74935b1102a81cf02b86865abaef81adb2db4f336fbe6aa4c97957469031cafdaba403098a9dbb819d196393d6e8f0f98eeb23ae9f796ceca48eba87742a02ff361bef722abbe4db873ada8f30e88fc1ddce192dd169fee88064833167bb6f94c1888b417371a08e5394904214836843ba20bd3368039b34ae3d1d69c50c4f95d8fe4969771ab36c4f48d4731406121c7bc68e94986a085469aef7c0b46952a8b412efa
+TAG: 83bd26345c3a7c70d7bd313acddbf5bccec83512
+
+# DIGEST: 0ad0e709e40cb2fd662020d420d97ae50a14adc2
+KEY: 433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb0
+AD: 9e4d00d6172e780ab8b700
+CT: 0634d0090fc059f4d83c4ac6b479943d77f183d521b6560fd2776bdb85f29a20ac02b5561ffa60cbeb55ab8ebfad9586696f46a497486e20719a4c1623a4bf025cd3dfdb89d9bef336804c23ef29377aeb5265ebf72e71866636d90e05bcde9e2eb4ea7fe2483e93dfb81cede20053ab7983024c39e7988a1f246a4823191d864c4935b21694a6b4d38339ab2b98569b2a457b86c0cead36a17995a7b6fccffa1dfd81e4ee355157b52961dba19f5a9b3c6d17496c6b2da15d262e21
+TAG: 70b1ec053b80c6fc9d64d9efbb5083723dd9fba8
+
+# DIGEST: 5f9967a8fba7184dd97dc7d5da22ea785e0ffbbf
+KEY: 1c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d617
+AD: 2e780ab8b700433a957a74
+CT: 1700287ee100f35488f3a37e8fc87e70f30d219b6435d0f386aaf38b9e38fa6ce677045559c806f1f7b6c73aca9f89ad3766cb1a55acce81ad15a7aef46d3c58051be7d673c42b8b3f2384444b27179cccd85d4dda0a96d711bcea982c30a38875a35554dfbd2d7572c45ed621dce8b56c885604b0744f6e6fab919a008c57480438198f6e0e5971b981dfd3cc34f9379a4eafbcd402f45804d4950c71ccc7ea1ab93fb9605f7fa0925ecb3121c02a889f125825bc0f86f76b377890
+TAG: bf4db639a8685ec081c4fc772db93766a3519452
+
+# DIGEST: b5aedaae523d9d396ad1d9bb175bf4c7c0b03eb5
+KEY: 021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b7
+AD: 00433a957a741c9eb80f2b
+CT: e45b2bf546a38abd03aa17933c50624f8fc36af8b541757d26cec56f3a9d578aff93663bd2240a28377ae1c182eaafb63197721de1aef7934b9f394f91137bbd7cbf5e7fb2f5c15ae86d508079fa46055820e9fc43eec6e5c5274aea27307139a2a7ce83d2d15b438d0cffca73277a7c4f5906662b7a5c1b4afca2a66d1766ecda6eb94bc07153ec322d624900a626317d9faf2bad47d97ddac27d305811f29ccc96a206a87d18ed24f806c8b088fd2c9ba8a9f42221166c9664d5b06d5211df205e58f2289aea30b85102e9
+TAG: c14771c0c1bdbb9e7d74567963e06b76e7417ccf
+
+# DIGEST: 52bf12f5594b0cdefcf977c07626e8748cec5425
+KEY: 9da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d7
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a
+AD: 741c9eb80f2b021b144476
+CT: d9d6339ecdef69eac635f0149f8702bcbd815ebb9687b510581be5dc32aa8733bef01a4fa3254e6318858ace9b89d0ea5f7c9838922796dab27701908431d7c80ab7084cef14ee53f1953e7aec43416c2f569558429cfcf1b5de4a9a1102024fb7b1e8e03158ae85616773b5f32b17701f4d9bb1895b87cd2d52f66d3d230dfdb0b057e1235c314a3829679b69af629890fa40afef0eee6387db68fabe2d83cd0ce16d892c4b883d06437ce7a80d5934084db6d10a9e0f84ae335b3ee9839896520321b86f9e82a3e2bf4d7c
+TAG: 3ad60aaac815cc77d8dadeae51793e4e2ccda92c
+
+# DIGEST: 900a1792a921b6a253c47013c9eaf01fc5c880c2
+KEY: 0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f
+AD: 2b021b1444769da00fcfab
+CT: 07e235433bf3603cdd0ee3553690ca664a457f7d1a5ee2d38db92583c517c909d33d417ffb76c6150c8b364fba7970eebb346765fefe6da1f0bf9fbb2a3ecf14fdf50c24f1ec316a408f6aebfa7f74098a887ded5c433294ff2cdeb987586d437c6abfa5b7b9b82bb85b88edee401f4e6ef72c9b10f2078c5d2a62f64b475c805ae5571123739877e98d4aa2c3a1a50de0add4802ea931136b2dd4c466fd49f7ac2518d472aeb68d80031aafe6df887b0fddf4cb2774603edb6776d65cd71235c1a6205dcabdcf980ac98244
+TAG: 6fb9e3e72ecd491bd5e91f519be70ac102a58f14
+
+# DIGEST: 88d7ec35d88ff113703702955e931e802fb0d8b8
+KEY: 060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444
+AD: 769da00fcfab0f5f93b511
+CT: 11fad6dcca311530333337acfd187547325442755679f1a91edc21a46773084a17f3d1dc85e2db913133847e2f9cbf257d81c1b74860014d020b0c8d6bda7551a752287899d555dae082983f5e23319cf01bcc904e32d448fd049615cb5422e8ad667f9eb2d80c9cca9d28e22a0f4c67344e16eb68a38c4108f0843a8e7b3aec5848394d858910f9075a5772a435183dacbe0a7d63bf2216450cb5623b226a9d8ee088cb8613427a7bdf6ab543e54e7e9f84cdbb788e38d6322381184026188a23fb31bc486ef029d371fcd49198ccc62cea48e937052c96f140736a
+TAG: e97ffad80eefa8b65807da8334869b4ff5a3ca9d
+
+# DIGEST: 8d8493b55d9b74892e77d3b730588c087ca9b1e8
+KEY: acefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcf
+AD: ab0f5f93b511060c9c5f3a
+CT: 6094755624849041a40890612831d14eac35e35583e377c7b5c9be17d26cfe8d3bbe9a868fb43f976db00db7ee82f434c745ed6040a2aaecb66c769dd37784886bbbc893880969e58645f35d7cc76ba362a4bd6d4b763bec9d8ae452a825767598473fe8ac556a2e547df30ee3f82a08427c50e228527fa4585e773f370dff0cd950160d7a03176469da4f48b86a14c58d80664f1b9ec2ffab19da19b6cbd5e03692bca9879ed620417e73aa0991171f92d8c1845b09b59c7a74801729fe409ec60075b56ac14c8444631bf2b24ce7d5111ab514a161776105f2c772
+TAG: b8fc8c0bafdee27cf54f3cde1db77b71f8028e56
+
+# DIGEST: 4cd92ac16a807d2ff180df75c47d848749c7ef46
+KEY: 4ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef7
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b5
+AD: 11060c9c5f3aacefe61b18
+CT: e2e6df43b4151995a2fbaba9cd974285d815e05dc641f562a88af180e5f1d3ab6ef8e7326866d039c8225f13d436082b026c787e2a0becb2bdae522674bb3f723f4a4a9cbd87cdbea9e66bef5a1d2d98dc61f2a039f0fedeec4cd31ab179d23f03661d00df3d2d91213b086aca1079d1c545604ceb1e9122b5e738bf1bc264c7c6863434c0baf604b5038dc97d2fb95701908553c68d30ac1a96a14d507a4ccf1c8fe86d3e584f926475a5c8f849327dc55ddae4a77ed01dcc45d7c25a5825d4a9cd1e98982b04ba58373a5c4378c112102b7696515f969f195ea5fe
+TAG: 4a5e942b980894262797ac0e7d3d629c1fe6f43c
+
+# DIGEST: 64ee218c0c96ca8e2d2e50cd809d61ee109baca6
+KEY: ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f
+AD: 3aacefe61b184ad2463939
+CT: af965562788e82423000adc0baf6cd49b082e5c12923b53927ab1dafcdd4c9581c73cd339918647bf718923fe669df07e55acb3206e9ae3b7cf1a2cfd7eb98d36eedba65227f02ce86d223d6348ebabf31dcd990ffe91ff1011f3ed91e1e41aa5f6d127c7607160279e035de9aa36cfea0266a1b9a958edd736568bfd52b62ec7bf034439cbe41653c2ba5321d599a40f6230c2fbb594a7dadfbed46e23834ac938d6344407219685c7e666bd135ab30c3b1c71ccb73d12dc313bfba75514106beb10b740800e32c52557eddfd4a1883e64a5909aa1bd2a0e090c44bba7ad8065b3ffd7d3530ed9ed841ee57
+TAG: d1f11016e5b036a76568e145bd2f35f96bd46084
+
+# DIGEST: eef8eae201ae4e5af32ee74bc724e13ae5ed3978
+KEY: 3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e8992003
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b
+AD: 184ad2463939ed518ce97c
+CT: 7ee4c521cf1d5807fa3e5841a5af354731ede548f8624427441475b9c1263d609d88fc53bddabee16983298d5cd7cf304d6c899cb219c842a608e30b5e6119b9ab93fcea65a9620e8bc33be5cc4ea04877eb4605472db6f2b87484991c3cfabb750f7ae7d903f6971f337eeab06fe66183d1253d63d3b3a2c1b5505f307653393dcb62101a401ed3653fe40b551af91cf90948097e4c0c445ca5cb77650e69a1aca5eef48228c37c15f6ecb562d01eda955279dfc07d681caca072257a969be5b9be811035ceeb32fcbe9a1bcbe732cb09b52c92bd467b97dc2ad08beaa009393ef3b2b7cdc226b6e5d39977
+TAG: 983c088708ec1e7b6d3efd09e83de01ec62e7711
+
+# DIGEST: 2fe67a81b41b094a708ae515e28bcbde3bed724c
+KEY: afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd350813
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad24639
+AD: 39ed518ce97c3fdd293d72
+CT: 1e9eda4b2015b166f708941dc7de6057cfe4fa04cf1d98a01de87b35a4950f763f58edf8ffcba9a9fb1091fc8cc2d3bde47ee32d8b41e020dfedf2a10c2c99ae9afbc65875b22ae18369cd8253b4de489d859d3066506588a3fbafe2c77454ab71cc8b7f94c8e906121276b57e22391c55de57db0e36c4b3d9d098f872c7052b72b519d7db739852b68f7c00c86b849e80fef5da6cd39b1f2a255d73cf1ea204f3a7ba3000d1ed37d43e810e19b369b4a4beaa2b22efc7dcf3b63b3d744f1b58a23c21beb691eabce5f7f5e995ad89e5fb4e5c41936365905fd4811edd8c5afaff6acdf11ebbc65d5cba608a
+TAG: bcce2f776c27b0cb639941762719bde29d5e627b
+
+# DIGEST: 33d10d6cb5dc80751d0f8e370925d7c86cda331c
+KEY: f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce9
+AD: 7c3fdd293d72afc09ffdd4
+CT: f1f61cfa95db64f8120073bb3ed7f0adab10a000930a0bd61e245f653e78343baf543424748d98fe2f6eecfa6bd4a3fbdcbe7b5d8f610de7e893ac00f22ff8eb9d22fe778196da6491bc4b1933b6b6f8684fb1721fe0f51e4b495c8a6a7554cc08a6f17974594af4f0b93c9038bcff1d24a63f353816760f787a95755ef4f0212ed5c984cd4b42c2e580228b5aa186673136a23f81780a620bdd0564131d333ca6bb4752b6469e076c1dc385d4620f3218b9b10287be69e0ab2d09dcac916ef3a8607a0583195943111ebe90090eb3b990bdc156fab7f6c9488b93c346bf9db81234487616f429ebc06caff1
+TAG: 7eec03b5c9b14a8411dd628fc61487869113428b
+
+# DIGEST: a29f128842a48debb60699ae0df0da9a9b5e5dad
+KEY: d299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d
+AD: 72afc09ffdd4f41963249c
+CT: dbb201b0cef7005084819a642c3e1fc54cf70b4c510b96689f988b598942a153756c67519f0174477a233da3b1323981cce6c65216493ea82c149c909d1cb64b6151239e88cf25cb540037d2459bb812425a7514aa56f03741ade539fe2f92c7b58168d963aa5a558db8403e67eb1b81f63d667fb44903b1cc2749eb387d08bb50982f85afb55c3e4ad5d11cb10355aa534fd0ff35c9bae1cbfbf25b7e28f2f91d201cc462e02e6b9bd4d9ebb8fbf84543f2ae5aa140ef7c030a95f320bc0a78189f6f3c37c1bb28c443793ed9faae5b130ad311338136b47a273dac03d17b7d054ac5ff4700d62f6f883b0f0377bd34dd75aeb27cd961ca249d1f50
+TAG: be8a2bd269ee80af4a8022b486cf5ac0d4a62ad2
+
+# DIGEST: b5048d1efa7564966b6cf1579cfb4ad8e9460660
+KEY: ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffd
+AD: d4f41963249cd299b92e55
+CT: 201dfc8d35187b836614651daf466fc1cefa69a36653dbe231bbb727f192645a2ad5ed66274a99dc78d749ef0f15aff2ad75758f8604d4b396e5054ad41874d9e97c5dfe427f1e54aa3643b21b4af2cd9afd0894587ada0eab10bad12d94eeec00457ba93c32741b6b465c5c68f4f06df5e004d22b9a51477fc1a515b8d29ebb5f924b60e10f839dc2467fe2fa134960c4e65ab1883a83c7ba74bcb648c961fc4204b3c1a56c58d4c62b9487b975dd656f5aaa9bc114aa1738874faf5cfb04fc74469e17e5a378595b00483836ccaa73171581a860d90bcab101ff0dcaa94120f1da585fb78141e9bdae90cf75b5387c2bec2b478eb0b7c328e979e9
+TAG: 45eabefd3e8b18f2471050fc363e0cb42a8d8ad4
+
+# DIGEST: b6e68f5f0dfd8ceab56ebb657728c9bc5129fdf4
+KEY: c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692e
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f4196324
+AD: 9cd299b92e55ca24d8c078
+CT: a3d7370aa37af8c9f088e3fa794a6bb8d2afcebba68010a40253208882123922be16fc8911d95e169f144603c0b5435bed90f30502e6645b62ae6a66dfed3ac2a03271c954c511fc803ea2d7c862d3b9770e22656d91f1003e971039bd0adc9dc462e8aa2d8061998c7efa989e5ea8c43408ab8431f28b0990dde190a7d30c99cf305d95886c27a0512745f7b3c6e50561b6ffddd638a1065b1f2cfc8282382339ad18fa1a9aa9e67a9e30f179a7d5bf9e88afd9d1e1f8eb3de79fed1498428fae303cdce80d22d42e45f934b78a2da5fec0c7baaa5ca26dd541ab69c557db6f3df7588ee2b7ef36f8d0f37bd4dc973e9258a181082fc4c7052acef5
+TAG: 8875a82de3400e2a5a825e0921e40c16166a7b8d
+
+# DIGEST: 853bc7b9fbd640cc0654fa5533ae302e398bab35
+KEY: 13710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e
+AD: 55ca24d8c078c49f78c7e7
+CT: 5b324c466f073e7dfe295ffb7c59353a83298e3610488ca81be17db495e1b448594cd2320405c976988b594e21b38f840f5138665ae027fa544f3caf02f3d0b71d81c8778667019396ade470e5176bd7edb64f8a099e557405e3feaf2ef76dd9a312bc75fcab8b5759440e157c3323f305a3de9eb4b18bd3c9eaaae634607d6741811f6b3e422b033bf03d9fd40f5ca08f715c7d62ff18cd592587a5c2fccf131f605d74b38fe707ee006d22dfc82c425e84104c43811de2acbaef2653375c00514e5fd6e28fc9c5a8baed280e87e315709cecb8b30a83687572f30996bf75f6355d9013a21aca70f655bc97dddc6393dd17a64761e7e0813501402edcee7ba39f7857a38f47658991617203
+TAG: adda70005a81731792f3f2071d10d5fe032f75fe
+
+# DIGEST: 286a92c480192206a2153df1b6d0eb26e6507da3
+KEY: b8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c0
+AD: 78c49f78c7e713710a025c
+CT: 5b6753a8f7bcfc2b7d50abf211a52e3538ba28d09a7b3c21892abc08784ef72ca70880881251825379c461cc0f0c6bdcaa9a5bb50362bd77b9eee6ace3bba1d2898152c50c5d257913bf8e84f40f6cf155f6c6fa0943a891b87927035542191cf042dc9718e33c8319e9842c1f0458e2a41078ce3274721b8ac0c4d3f5968ce296906add8df796ea335ae33671d4af2197187bd7e9625043431731d3b0665a6106e6a0b0f68f1eaf53c829d8a7fefe76bd1e6a2c79796cb35dad232ea7d4922ba51e411c27e0294ce6cff050998404ba41194c545dd6302859172303baf22ea316a5c620632f09adf3e7d6869f9539cb26eddeb7455c6c180023ebaa67663e8370a9bf871d613e4b490960ab
+TAG: 0aebbbc0aefa10421ec7a6aced5ced076c4029aa
+
+# DIGEST: c2acb0c126af5282abe14058066631fd0c658571
+KEY: 89ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c92
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7
+AD: e713710a025cb8b9d71d29
+CT: 17bfa592a3eb59bf20a51235012db934d58582964e94ea19b0b751a68c0176624b5d3947c2980b252926ff5330b31f11e1d900c67923fa466e7d3cc618d330248b7aa82836ca492b344d87ddaa93b5c9f77d3bceb13881c49217f9de2c40a5a9c63dbc7adcb0f3e814bcf4ebc09c29824dd93a03177221896ffa89f4f58ed476590baf335eb5f9acffd84f7d7163982ecee9922eed48a64c537be384091f3c9879c02e175a7761cf1908bdcc7c3297a2b489a005e55c6a325431e1d37b3743518a82634df26f10721d1d979e12015e3efdb1dee1a03cae7b0dab97d5e3b23d25ce49581f9a2e5b1147c5767baff32668e28f3c8ca1f4ce72ab626086a682a4457f46fd9d842680baaebeb1e5
+TAG: d9417734d0993739b038cf04ffae40c9b088296f
+
+# DIGEST: 500e5f2a56bfafb2d93e26224c9c2df562589f23
+KEY: c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a02
+AD: 5cb8b9d71d2989ab33e978
+CT: 9ec67887b8555ce427fcd9b07aa9b78a64f4f602dede7eabcfb2e7204f8afeff070c10fe7065c6912e93deba117852cf5472c5a2aad1439b6f3911bfe2709b631dff0226fdc4c21b9955548d1c01db24c1cbd28b69d05bcb38a31ee04748b1d9e00b232e2929f5f6b6a7b7c85c924f53fbd9fe51124413178b813c34fba81cb34b54dc692379203ce94ff4d8829995791011cef817735bd698fe3818646dc77ee3e6eafcd08eae893a93d7702f4c437baad48d3585d25d293cea23c168ae67ae55e3ec32f6f775ab54c816ef0da9ed9d0ba0e947a6e7b34fa733cbca7520593c5f271083a5fa9d6e53182f21b8bdc920b6d831d02ab594177826d46058cebd21a6bfa8896b6ea7f7b9eee48cc47b8f82e82f4d1064d8dd0f8cf2e730
+TAG: bb566ff02c84955fd7ee1cc474b02c8786e8a750
+
+# DIGEST: cfa6a42a2cc0ddf1c7b20031c95e331696bb9ece
+KEY: 85a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d
+AD: 2989ab33e978c4451e3be5
+CT: 668c1a9dd22292157afaa8c6f38d5d4531ebc8c2d4ab39e4f1652041f503c135ac6765ff18f34452c641424ba17e4411f5bea80e256fe6e938a7b6a72f5c096d70a3f6849158b5c6233001b5512515b64ea1279fcbc40c5fdc9699acd75eb7c7e229454364ffb27a2cfb7199440fccf8cf62ad5d0cf267634615c487ee6512353377862720a12568beffeac495e50f76c1b6d8505151dff66506094827c1d695d2f8b56cd1cac01e01f41616c68cc1afcfbbbcd48c340bed083194389a746da3e50230868107de9defd2ee0c05e1f983ff00769f90a4912f971eadeb69a78ee3379e5ba6921b31f38a419b590e838f2a7fa6c5411f268c8b7e1326fec2d0ac7c4b5f4b236aec8e64bc1963555ebdb0abe3ce092fa1af42021509fc14
+TAG: ef8fa8130ca204d56364242c3e91e27017cb4de8
+
+# DIGEST: 2d1b27948de83e32a0fa5be7040d896824ac1fe9
+KEY: 2feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfc
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e9
+AD: 78c4451e3be585a29a2af1
+CT: cb8dbf2719d8db2dc0af1209a5c6b93d561a4882e78451a69466db8bcef8fad8c92e2a20a9063fd2c2c344d98446ccfd6ab0cc62d0007ffe979cfadbec818c8762418fe66a68cf913b6249b34337ca86403e7d42526827a699a8ef6c1dacc7b147a74c53caf5f7bcfd3a380f891c820d7e3173b892b8c56d961dcac9d9870a22a23b727f5e2eefa7a7135efaf3b9a4d6e2b1b91e9b7cc2e91d1d85b16d16515bab9ac09fc4ea93e52d25dc9464a7d2fa940e00f049b083846db5316a6e4a00d7434abe037430bff82406c918bc8106ff9805072676a078d532a94a98a0934531f6c3a959597236705d29ee308dd6a335969030a6df0dee568f0f24d66797a44a53beb03ab6c44f56e02419ff338543ae3d988a0ad55eae2f7a6998f9
+TAG: 068601ecdaff981100567f0b01db1ab86878c774
+
+# DIGEST: d35ac8b9ece76d43f1497ac8681c5077398bf2ac
+KEY: 63b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed067
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3b
+AD: e585a29a2af12feef71e10
+CT: 5e90767a79addcaab93fa583fb7fc9ceffc9afb0eab0a6f19943899a00c0f7bef8b84af3fe46527fd957e6e8edc7c45c7a22836e76d211e00f99eb9335306904ac452eb60fa59c7e05c2479288206103da8fd4f42cc2b6172ae43b3c9714fc068209855bad8fdb91c52ed209dfc7c6d68903ea06b363c24b5c18b1cb9171083dec402b7633ab13147dc8281453789d0fcce00979c9508a409e59449c69dc2b6c806d4cef36857dce1f135c44b83fe16e70ae8ad6a8a1f9ce0f29b631b483583efe097bb35035d6a0092157a298917a2b5e78d19e3cf1c9ec937e987a06d927621affc6228b1e2e151c7a1fe53fec3789a93f54b32f50ae962f99d612244903e808c31bce799e30c59584061c87cd9f88206e47a58293f02e235f5f3626c36f7b5c921d5159a545d8def2f9b8
+TAG: 7845e501529bd28ae60e0fe514b361856bfdb41f
+
+# DIGEST: a3b33fa67f5c471a60a63dea915333550bf3af04
+KEY: 99200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2a
+AD: f12feef71e1063b0b4e6e8
+CT: b513e57bb4723eaa7598d5861312f1992a33ec9459be6da060a2440753c617f335311bd6c12fdc2a4f8ae0ed4c45a0ccd2567da4fe963b28fb4955beff3a95cc61e73d81f0e5e5594d86d2f82cb3067180eba126107efba2d82d1440b29a6b7a8e0d86041d6454916f6eb4b8076f3a822bd6b4ed5c070858dd49e386d8fea517c4b1bd54c34638a52de8499f7faf6c4086c2087dd6764bb402ffbd4a9b24c0b52f6a5c6efa43abcb268308a95942df217de92dfce2bb04a076e69daef23bf6e8b32f6f7f037008c344b560c48058a879e06f100d8c047182fe8738fa52691134d015d4e2fb636aa8a9f0d8eac688bb9c245f0b72e9b9f0bd9d3a027742e61c47f1b041789223e83bda7a0fb324d9a50c6c11acbce94a6f4068f5b7bf096eaf90fc99d2c9a12de93b47d26b7b
+TAG: ab3bf9c34632bea89d15770d39da5b1b8cc14090
+
+# DIGEST: fc45f684acf19a1dcbf767f671396e793430d7fc
+KEY: 3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe88
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e
+AD: 1063b0b4e6e899200304bd
+CT: 2994b3f3dc13a23bfc3f05641fabb045df724e5b49f70d92475f6c6f52ef91c7ae49efa48909f1f23bead9b64b6210eae1b063bfb022cf600a6f8b9730fb176e8949143d8a1e031c5f6f67c3d5859453ea581f5a3a63b319c4790cdd7a95b2f977c6a8038cbebba57a5de33beca201a1f8e6f5e726237749bd83743c15c8c353ab1b66ef26ad7556c4e61685868b01dd2004ce7805041ee0c14b4ec15fbababceecc2614ecd07ced80e73a511c4c3e6aa2e6bc544544d9a10111a8cf6e3f07bbc2a416a4dfe0d6a1b9434ac1bfb5e6d0e835a6ed11b84085a0059cd06b4228a120ea877f4d11163c256eb17c81d363f4fac4f0b9dca0ac76a576af94afc6d4b153fc35ed6e2533ae0abe5f2f2a760862026c38dba487bed1ce960e7f9922bb8a207a71b1660354ff649c56fe
+TAG: 3e54ebd4ea6d8d1571b9040b24e36542cb642586
+
+# DIGEST: bea3f11679bacd98ddd996236dd603d319aafc6a
+KEY: 7d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6
+AD: e899200304bd3508132a02
+CT: 1aa80c050cd84224fe254cd0439bbb498357b27ae04433b191299e2edb7978c48e7e792d7329a7f1145ee98b64bb71817d9d359cc2dff64f32c3b2b6c29a27f0a8e58711f5ca3281a974c18b805fd40e690f6b78d8614eff3315e9b551f4b56eea59ccbe499dfe3fd295ab1324803c8a9439afad859fab31e9c4eb3b21b65f00a4be1079fd8ac05c6b39d0fa40344d65ae0d2ce7c1e323f49b44f2cc463b4b665918a292f37400fc5ce08085859d5baac0dbfa0d9dd6441cd53ba945639e30b3d3256b31fc8cfaa93bff9d01d4787665f0a8c523a1ebba2aa1634be6b0201fca3ebccc34f82568e405d79191af02867640181a6236290e856c308ee4bc27e71c192beeba9fa9af92db8b62f9f0fe06c6b7350b8b76470b76e5108207c254980a42002c6cf3229a80b76db23871486d4eb1a667975d8ae3e43cc6ce3b
+TAG: b6a3881d8f65719785a1f22be059f0288373a3c5
+
+# DIGEST: b0ccc9b5ae13a7f8a01100af61a34be7ef6ccf6d
+KEY: b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304
+AD: bd3508132a027d1ff4c047
+CT: 69a1ce037f1c63441c1fde91a64e42f6ccfc14cac57b9b2e03500c54e33983b396adbd280bd43c3817658957b711b0debf39f8227d3ff940c4aa4e8c83f1176d36ecbfd07693632d8fda21b725f1cf494f61db8ba3f061dbea75d520e86d86ece1c2315e5e8113ba2c35466503a7e934a15af5fe42f25b7dd65d8b6aed1599798a93e1edd4ebbd1ba54d61694e6aa1007b79d6e1a96c89bd92953db0b6182adbc8434ec97d9d182013cea371a823664b2b1014b077a5f9d06bd78a4de3d605e9e76f2197b81abc37392f4a2397d95c3f7f41dd4d45937764fcb21175472053245ab74b02a891d0c3d5a3901c6f5b6e9488437ce247d20c1eccbca08a2cc6c244c3750b38cb63dcffb7110762cc13478aa05380b1ecd0ed52b4239887bf2d29006d30b03a81047f548052ce7d750b576816951d6b493ed900ada74fb7
+TAG: e2e8ee15e405ee4524a56ea0353be028ab76e314
+
+# DIGEST: e2b953c833076a52442a7afab46150176c47b730
+KEY: 4706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b8
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a
+AD: 027d1ff4c047b3ef4f57a7
+CT: 3f6560d1f67ff9c0bfa2862bdc10d3453bc552e0827707568d873ce98b2afd207392769903ee020eeaa590224bd1acb39312c1ec91abda16f5ab085b2bb9fa0d17385435232d1956dc5b6956af441ce23e7515ad9e433f0508c43bbed5a1911bb0f8f9f80134fe9df2fc402b3ab0310848b26579bd31f4b499ff26afa8e9808760dbe7347d16325d0a2b4da30f8c92e098b2ac0ccd3e11ec1cb85bf54aa6a48069d913eaac9da5f7e4a36fb05818c0a855050a17604d3550d8d41d50e27439cf485e2863a5dee94b2fa90b089b9d77bc08ba9937c57f455113f5fb34a161b831291ee6036da4e4c53682884ef1e95e07fce8e9437aca523824275f27ff00485fba9965f9163e5231aa98989402eee3b9ef4358876bd49a14bed20c51091666833cbe124897de0077d175140fafc97d7187790c808486534204395d04
+TAG: 752769f5175e1c7b79a4c13ea15960f31b2ca063
+
+# DIGEST: 8e84935ed1bb79dd38ae38924952e1105101533b
+KEY: 1c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87b
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c0
+AD: 47b3ef4f57a74706de4b38
+CT: 40402e4ddc2cdb109bd50353f857056355e117f96e0c3fdfd9efd316cddda82f346e2089a841518db9bdccfdacf58477242b53ac2bf04e27be7d619a12ec0ac68381c49f19ea8c076fa7568335b59e6c67e314b7e3a10f524c7b4db0c73b556457ddf5c725f7294543ed585b0198e6086af11d0d83fc4e06d968465e63bc726ab3cec1ddd3918036b89aedd03e538677236696bc86d20e688e5b49b6b49d6dd8999405d29023db71d0c3b993a3c35708d35767081139a16f8e9ab01789fac4dedc5439e49f5d2f774908a834732b194ae9a8c7a0ed1e068014e4f9b6c0905a0446eacdaafa662dde1f2f1cea2bfc9e02d4b349116d6b171985c5650742c0efb73702a7a7c95f7b235feceaf11c315e48e1988450ec1d20933257ce8ed8cc0a5649956a4a9c8d888d5b47024cfb3f44f5cd4689a8d89928f4219c7eaf
+TAG: a5d70a49d544e1eb9c5ddc48f570c8105431fb11
+
+# DIGEST: 99ec6b669dbedbe99548117f37189e669fc5d8a2
+KEY: 101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57
+AD: a74706de4b381c692ef164
+CT: 82edfb0827b4b520ebd3ae16420b67d9ec946f3a2e78392ad480c67b0beee6128d4fea93e0f3b4d88d54a9c78e6cbcc24e4276715f68f57a8efa119459ffb661c0ff938673fe64ba1e727264d79225591454329ad9dd5c415d2bfbb0d1719a322f511bb3363ef9f750aa912b2516495f5d59205b93a253dd750379b394c309cdf5c9497ad595adbb45bcb548fba27768ddef32add986aeff87fa56c703f93330991678b9fedf033580cdf33ae8e8a2c5ed43c2be82e64c4995f83c39dde700a6bb0b31a7afd2fd14f426b05e7f835c23fafc2f31d2b1cfa0d9326c9486b587e686432c910fe4ce4a85306e66a1b8fe3051866297bfae1c81d1679833cd92b7f592870a01c0efbb059c8d77becfed21f1a922458ddc2263ff452d67deb7a4968fbd6591a14cf3636441a3187c3beeef11550dcfcee08d476480a4751f1a176a85318ad23260371d3a122c1d61
+TAG: 4a3d4afa61fa8bfed2e59531a20a808b890cd704
+
+# DIGEST: b55f018cb06f74f0a9f76e65a23c1744ce7535e0
+KEY: f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b
+AD: 381c692ef164101b89b476
+CT: ff6f54385718a06bdf33dc752a0e8f4c04fcb8b7e1260cf4d20a5f30d00e9a705f742ae3f35a3502eb34c2ed97174e2c9f99d7c0c09c3831fa1622824183e25de78cbcea451b781b125511edc39b5b64462b22d2784de4300582a17d682c114e7618aeec5ccb06f9209e4713cdf5e4665edac182c1d5b6f9862a52f73c42ec444f7078a6a8ec40df331a7855bc88e39df2bdacb0f7a13d5d3c4f2ed40fb527040ab8d67b18c2a7debedb5ed3c25050ca00667a0f3130d77caefb61661eaaf35b7799d04959c17c1c2dd4f2d726e988121c75057d1c51ce73f1303f615b3d6c5daa92dc135cdda0cbf4361a5b82682897facf1e5b12dba96ef9918b8f0be60317c27224d0f3a446adc64ec9a6a10e0830677354c71601f8410453caa1d4a0627e065373b763dea62fd77c58db4f56d8ac17d1671c6c67d325e43b41b73eb1ab22034567ac9388e16c84699033
+TAG: dde423f11983c02baf3030999fb735453705d7e6
+
+# DIGEST: ac3202e483c67fbcdd751950e1497feb3ebacf52
+KEY: 520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef1
+AD: 64101b89b476f72b27f06f
+CT: c178edf2c7815791a8c0c56b78abc211ce5932347f418721f70c2b9516391e7a1be5e74928a33a2fb97336a6154bd2f9a61acca355493cf87276c3f9e20153c2ab1dbd345bce4a89d4ae84e3c1a0e83a224f35de85aad0ddd33a17e8b595d09e15ebb548a7c1832b1d24ef2fcbbd17b3652a76daf467bf82db36d298fca3347427af1985935722fbbe92846bdf33872abb28b0124654199384a3e9a43f7a135c22a4413bd737c64c97b5c1c4b335d7769e59d1a73731a81f32198c921dfd7878d7cfecfad0dee1023203fca3640532418540fc5a0d2da5e730e581436f925d2229e2bc765b2966f7b8b5769e0ae1e9e5a91f4c6261f8aedf82e2939957e577b420ab9d2874c0f38ef05778acb4491baa3e3b188ae5cb99580d0aad081abd6d2a97cb169025f873a250c8f868382c34fba5b1c26d5cd72babd96adb34f34f06fce41989d833193665e8db9168
+TAG: c8a33dae3945586a81e002b693774acbaa4687e9
+
+# DIGEST: db82ae5d79573da2bd7215485a92063861879c3c
+KEY: 71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b4
+AD: 76f72b27f06f520c9267cf
+CT: 5581b26c1fc6a6f99e27dfd69561b5d7ef77264dddf1ed64233eea8ad24318e9c9d6736fc4a2d45e914460d1b0d0b4645bd41beb1af9d4a154c2eb18a8d61057b91574a93bc512f7155c0e8556a7ab47c0155352cd72c18ce341009ff561451cba430008767aeeeb1749964adc493c5e2e8dd2e33bc96a2dcc796fc06393c59f9069d18dfd7166198e646f3acc788d7506a67701a81a0fc20c755fe765475b3507b3a1f7678d63242c38def38d27e0c69eb2f553eac45c265e62da45c7a6189d0082cf595093bb7aba0dbf739f43db945010a35eaf081ce0cea82f0128b4875873fa2eb0a3d518a3a4988f956cb58ecaed2498a82eea504e768490b4d456bce978c33e661b8fbe8b86eaf8b153ec41546da349acb2d6b47afec6a40ddc53a007ed83645a7b1c3d896491a8363faaf16b1377c447f6484a958783d9b89db04fddf4523a88b633505ead3d2c83cafe488fc927792746225a69ae5f5c13
+TAG: 8ae9857dc11cd3de0c4df9ffaec27c79c089f14c
+
+# DIGEST: 902d703861f9872e7b6482f854709a214aa98731
+KEY: 9bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f0
+AD: 6f520c9267cf71408a4172
+CT: ff38097f8cddba5cbf30283a6425180a2e4b3053a70c542e1dc907c2f68c3c3f644efd9f4814b790bcf4f2622c519787e0e4007be88a23491f40cdc4329d2448e100c8e81184a63b61734b532d3cd24ca24b8cd38d2b156d14ae2652fb9ff8c8f8b96d80da36300556a13200d4384c77b1ab836939bda18d1fbbfb737d5399cc84a6173f70a228c10b416fa5f8d6b545c76980fd53aa9ecd5b581e196be64dc5276f5482575a50ec3df626917a1fdc05761fa2249ff0f60432c3d3a90d231c725b00403693250e53585bcfa4b1074a16bad498c39859efbba2103e9f4b0c10e98afbe4db55d8790d1529b04a26ad9bdea77b8a9dfdbcd4cae4e43313440e9d419603849946f13c75af11aa299456c52da29615dad2f3196fd8d914a0ae4ad57fa831685e55e25f7e27e3842fb117f19566f42826bb952a992c46b67fd629ba7090d2b86e73f1610e8d5abb94381729dbdfc273b8abf2e2dc47e2e565
+TAG: e23d09cde2677d2633246a8a8710829a46a61f82
+
+# DIGEST: 4becd26b9b5c7bf831523f44cb72c8e50ff8033e
+KEY: 72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253be
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267
+AD: cf71408a41729bacb5877e
+CT: 13e3582ab6a27298a624cc2de13536c7d83312b06f1e5b1d6e1e3fc1f3097abe800d8f8e746d1ece7468f4064ba2e0f8b92ac1fb950d7036a4a1eaa5c4b313c86682fde18b27d2c3d6f0f5c33f51655a221a0b58519c9eb146bf457ac4d37ea1b9622e432d079ecb2ad1271189e04f95c495a04d920ce73b89ff33278fcb437c419dc923dbf868805853b9c654ebe098d43e43b3aad663a4ef5616c9aa45907d66bb045c001444946862298247be2c4c413ea85a21a10f2ca89111821d09d49237ce6cf098ca2040f90a0d0afdf84901122bb2f37afd23d9d8aee11908916fefb280fd3c3090f72a7edbf1d5233daa16527baf30dab254b53b2a1dc08c71d8077d08035019c22d106a4814c430216ef30ada2a4758ed5cac0c6f320a96b92b7f34110f23412b6e9c1d040faf9e60a5617bde2e352d213aa872372faf35be9313b17c650d5956cbdcbde7eea1c301b7fd20097c1abd634db93b7b2676
+TAG: e6f6ef404acc4e20bb12dbff739097e2c344f025
+
+# DIGEST: bcf4785d0e3b34c55cb2505b559fdbd525deaac6
+KEY: aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41
+AD: 729bacb5877e72cdfcfa76
+CT: 62b2eb7cedade84b4b268ea7366f2809639dfb45c756ed0a682d1b78d560dc917705dc89c959342ddadad2335803e9eb76d1cc04ac1f447784aba2ecc6a47efb907c797be11e457e89e79e112318e9151f1853acbab93eee4a7411ae368ba2d536f77ac07ccf97e34b7acfd624fa1dc8fd1f6a9f39d588efbc1f7fee396e16d7eba0b10d6c92b8fd28beda4c7adac95953d602ef078f0b287333d0440df73152d621b85a423b312db7ede56754b077d517427f3e18c6d8b490cdae116296d7132a49cfea37b095210ca289f949c9091288bee92cc500b37034cdd1135df8d14f21b5047def31a0ec016a7fcab66f448c1b34e44b224ef0756c9b2c5364b5c9a7a93dc340a3347ff3697346dbf43fab5241839f23a5573c92c6ae0353e4171322b2e37b1a035b72fb669093fc8644930415e58d4801ac1a88276cac841ff2191a11e38f0f7cead1c8d5fa5907d267d43d17befab34b238babe532813ecb04dd1315b0c55ffcd3ecff337999ef
+TAG: b5bba763b080b734afd22ab19610bd94f3666a02
+
+# DIGEST: 13bff121568d7c32b2546132cb4ad490cea9303d
+KEY: 7c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb587
+AD: 7e72cdfcfa76aed06707a0
+CT: b4fd9142a06b01664843ad5ecf6eb9238ce5f15647cb032bad047a40a5101292154c83703a693d6bdb60ed8b206db9a6c9b9c94e7d00977707e9ba0e155f078607cc5934748be3335e08f827bc03eabcbbabc0de929c298f631fcfda502e64825669d6c0e1abb2eed919f17f5f310ef9a648a2ab2a0e5a5448049f58a9aa867b7d60fdb0e56d2706921fc5e579e8920f8f4053c8463f02b881046486df2932b285b52e001ac5d1af243d7621fe8158f3b269a0a14ca26ad17ef47503836a971386b9849f1ae9e2b5362dedadf855a4c2c71290976e67137139635230de31b592810cf64a0222ec3210d96fce256f9d8a77b1cd232bbc0ef2c0e9e41c9b881eb5e272e6c2cbcb2e71de30c9427edd9c43d00fe057867b00fa79e8f2535ccb9b3e09ad5f8f470f391b3e48ac53ba0c6cd16cb554dfd349a0866701e1d204bb08c9701569701bbe7229a35ad544d9171d0387e51d41c4e0757b9cfacdb7fd7d74f9942dad9a098945127fd30658
+TAG: 919f8bd22660f31bd5a59264c38ddc524781faa7
+
+# DIGEST: e0ec91f0baa3c5fd0c50f135517909e26c204af3
+KEY: 19fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee58
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa
+AD: 76aed06707a07c3dab6997
+CT: 7c96052a47ffc1c76a26d7dc4138a30fb77b7039eec9fce4197253e8f175292d9bebfb3178db218ad2c43c40fcbe54ca6e7e3fab9ab1bf3f52711ffd8bd0114507c5d4351abf3482069474ffbeefa2b690376f93ed25b9b90f423eb4f3f8ef9f6919d6486139c923f0b2651a1d4cfefb60bd21294151e22859146724c1379d8fab03d5d4a3e350ae3934675a13fe1105fcbc68ed7733c0a878cace42cfd00b862331f5fbe0ebc70bc8a801f30b7ceed2709885539b5138ea1b6ac119f6bdcdab33f7230761fd49abaa35381f65a0638e1f0615eba574864b61423d0b598e5b32f187a56b06f0557e60925e52c9db2adc33b799c91f794fbb2ebc6da439fa168eea33cb32c2dad741aa359fd61ce70cbce2af0ef4befcec109ae2ccb3da544024c8008dc7c4521ab8f02a34f1ffc13ee9e278cae85571c50d5dd0be78e372d400878aad3f758cc90b126b9bb12a171c8e3c1dbb980000614f86d3d9c51a86fe5fec84e5be2b935f4e35e1d33b
+TAG: 8a9a6443370da2f41974b6e9cff2e8aef727c058
+
+# DIGEST: ee7d6f651db434a281b5cc57c2c418db731c65df
+KEY: 2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305da
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707
+AD: a07c3dab699719fe882eee
+CT: 0cb133985f6f80ef985c6883c5b2d15ce54521d97b1369c52f63b7d8c395ff12d668aa9ce030f8cbe213a4ed790c9c61c1fbe635531c2b0ff7eaff6500a8000367fb8e2bace831c64428a1ab84beaf2585f8afa5780c9a7b071f50d3a4d1f45d62bd1244e4ddbe3cc7f80dd9bd4df7115da0a8c4c4d93bb44cf1ec59b78f1b5b53fffb3c7c2982effce5a5b01ddfcacdfb77c33241787fd90147b8c2cca45540aed10516ef902aeba6f20f4956fd65a31a61628419257f3a37d96846771764c5f6bfcd5c9321b1167f01182ef71d744f4776f6c2e836df401b5d7fe34709f224100f865bc55a976ebf5d59a779bb8d2ba67c8e486f8b8c8d1d21529b57f24f17973af9e67b938f16881c584d139a07ed0676dac6d7fb13a5d7e7f093cca854e632722ba063932c6314bcb2a7a45fc9c46930cf3623a0acb8459b0a1325f0cb9c1497709ae88bbfa898f23b48fc693ee2abd52344ca1acb7073ebf5e46a61d14aaa3efef2c346a5e58dacc950738bbab724710b1a3dfe54de4cdf33c6
+TAG: f720f0fe436c4ce0ee45131b18271ec1d4572f3b
+
+# DIGEST: 810e1f01bfcf6bc13ebae7861454ac133b2d6cd2
+KEY: 11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab69
+AD: 9719fe882eee2fee55ed8b
+CT: b09c56b0c2ecf23b997316e7266c4b255cc9d9520ebd7da9b03cd49ed66fc489d6ad3912b9a17e30f118412d0e6b8bd14fad9c27a1ad1def4f374661e9e2016c8806e29bdd8ba54dfd69d3d1c27c8c7751a8fcaf73b0a569c5986f99b9ca118b6154c159e3e6274856f3ca96dc5d1a753eedffabd28e53f0f9e3ccbc7a9bc831427c8450ad1d0fc6c74080a4d2b3fcf589963b4d2620a5398883eb87ae315229a81b48f84ca0a097d6d7f335e004c5abf9bdf79f5fa62da078fdfc42edc38e893ebb20f63bdecfcfaacb4e126423064bfa21bbfa9f958cf86f1676791f73101f66ce94fadf1a309a36c7a480de0cfdd9ceea83b05772d66e35cbdb462bb6ef32f10e0d8ce5287ba87a2b862e4ecf36ea4028ac4dcbf90e479b136d91405355637fc80491030df93f3d4b532cf8a4c9ea5b024249d9df673e12e3b24e206d5cd519e80d2fbd4b5086b909791d532bd40a38389888beacf6f993c4e35fa42052eb12bfe8cec4a037c0679b94eb56849d8b539792aeb7a9cb472810efdd
+TAG: 09c411f7819307f2767d8a7aa3debd6c6c3d2022
+
+# DIGEST: 881551d50a849b7e81f0cc0d722f631e32a4c97f
+KEY: c695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882e
+AD: ee2fee55ed8b11534c870d
+CT: d89378b07f1281cb54b8e040812aaeb76d54cbf82c62a3c2f999b60733c69ffe98d3984a9f6bd31ac4f2845fd5e5152d5ac0bb4e5a1859c4b9600a5521338104dc7597319ddee899d7f4c4623ec1096372a5731052285cfb34061b76d22a455afeb414ebd19f122aadd4f30db6cb4e0d9c854473d615cd00a3c0b246357ab81941d55e146c367bf5c0068e77cd72a93236e9e469c41d956cedf31f4125efce99ca10cedcf1242017327c421b6ddb269977ac3e8648ef8ddf49f498b61b58f4a6d56e39ceba57d084243c5f1a1e9a1e0825a9858f096bee4d2dd7733858f888a7343567f16cf2fe7e53f39c85f4cbf71452b7778ba4a5bf577ab2b4e81f565adb512aa2f1890530b9c268527b54921124dc9c96c283e313e858dd52e73c9568acd8b24b15eb5cf674d8773ba443bf7f2dc34fc6c10fe62d747677a935c86d8858cefd5ee285d42ce37ace889314366f7c15732f3387de622e77d880272188ebe2792ab5b0a0e2ea9cad77a75720c0c7419fbeddb96f8b5a5681d5548f
+TAG: ca83f417dd775486cfb10376d5c081adc53101fb
+
+# DIGEST: d525f72dbdbf54db80ddeb9c2a84aca41451353e
+KEY: f1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed
+AD: 8b11534c870dc695b814bd
+CT: 1f035ff517ae79d4a7e4000dcaf9846a719a227ef18a1608f4bfe3ba2a59fccd09b1e79d7609d15b91eaa8365156e10b02b494a9ccee828875207f366ec8f2b49a88498e3663f25b0afb91f0b7fa229938105e64cc825db5a42d6d1bf9c29481f55b3ad5ed9d69d7aa54d3f27adc368216e2e9ff6dd5681ffbd04614099b9ac810ee94fb25f586e6ebeb85344c457febb886c3b9226432fa6d08af644c52fbb7e5aa389b2e3bd0f8a115975532d981011f01394aecb5f2c4c59a8e5b53aa77f45ab84f42d5f5afa00e099d87ef2b06b1f53c7538f4de3d9e3dab78a864510ffd7b232fd88d9650e34c43b5190166ce7b9729f2299649d8ca219908ab5a62fe2f45213093a2382dc5471b5740b1f9e310aecf5f915b0ba289f3005b65fc11124fed3bd0039ff81cada478cedbc29a26f8d56d56f173110345b6acc8e541ef653f44a4a1557731629a185965fc993988c6650b9d7ee93821e494b3298f29a974eaf7733ba7d1739cfcd13bb0e5a604ef9793ff6d360a2b1d75c47742ad868755f840e65c06a23048c0e11d3b3d
+TAG: 385478ec67d36f57baeb80487aaca72b36701d35
+
+# DIGEST: b25882426b4730205533cfccc0da1de1f6f2c459
+KEY: 2c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf78261046
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c87
+AD: 0dc695b814bdf1a87bb105
+CT: 43c1a8d1dcbee77b084c945d6975c01d865a8b09fb8f77268e718aef91a7b31d6624c522ba0d16ae5d28e079c7381607f1c98fd103c3affe57c86ad24a2c7ac7c10fc9fa1fb2be2725a26fa0b1cdc9078ab8ef0b3bd177ac31c1fc24edb27f035e26c9c9c464cd6b2298103c369d4e0eb9612c9422eaf3983f00c36ee8f14e3705f846c885cd7e553b0c12da16ef7f8bcb360a4199cfb11d95c2dbd40a9a1135aedf3293578a70edf7be64f837f2e11a21c1d81e510c8c1e1d1c9a331a3320b2092781c3e8b1b81dbf24aa611391fc57fd6930e1e52a56af6e42dc78dfa5b488993eb1f351ad472d4630997fb389c53d277ec6453f49f9955fee16f51f1b9b5c088a98015781bda2541d81e6d400908bef8fa9d27fc908ff461d4138045de008634f6d4e1b6264917243a7c41b3780c61b173f06c00c632cd91fdb327d643cbc2e0705be8d98d21bd3ad0d969436bcddbfff63209fdafb69d8c1817181073fc876fa15cfeeb9ffc6527f70fc75b332c58893ff140ca078054a6ed2e1ebd951cc47768739d3d0e0305419c8f5
+TAG: a2642099b5bda0af0a76e713291582fb6659111a
+
+# DIGEST: 939442486c730c2cbd8df213d81310e50534f06c
+KEY: 16bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba02
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814
+AD: bdf1a87bb1052c6755a7a1
+CT: bd6e242fa4cfce283653422c815b981f8d5f6fdb48925d737c8c46f4bb093b1c4f79c06eb1f91fa32820a8e1d5b6ff8ebbce6d7f8398688051556c4a32e7029d23909bb2e70b79daa938b2c9ee8cb07a421a216ed65eeba98badb326094765445a106aa71f8e418ecbe8a1698e7992bf5c1c5f91b8b3c0798a93b9bc7079f9cbc3ae94734335cfb84a92ed8049f06bfb16cb6287b6aff57eaae417e4fa722a7f80d7e9c18ce6e06d857c21d28ff7004f3bd51a8d8070a0640289abb78ea910ebc47452946a955e1ba78bc5ef20db60b2c8856eaf8ed30d858ea934f87e7d57d928a4b837704e4b0c268a9436fd7660f639ff6976f44947b482efee01234c361f37548004a5829d8749860790c913eb2187358a78b6b007e2a9405d0b57f3a6127c22219f1cb224f783206ba3433b75f53d34216676281568548912f7a6699dd48ba96271319fc6aab8669a2b966860ab4768125d485c503d6587ce6665872dc8eb4d78c0e13e6ca0895aa6ff58778f613810df2316b83ae03eebfac35c1a0b150219fa9b61fb3371c8e08491
+TAG: b0d4098e114ac495776366824becf23a977bb28e
+
+# DIGEST: a7b522c0de411517839342925e8acf703ea12e8c
+KEY: a49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1
+AD: 052c6755a7a116bfc9095d
+CT: cdf5b3d98e77a6f8e8db93f661d0ff4c237b90f6d4e64426534cfbd7092fa3126428e24f761fb85f21bfaae503cdb49b9971b32743ae48542ea7f580652413f6482cee491ca039f141ad0d2b26ccf7ef2cf86aed6320bc65b20c394f82a379e20d2a4994465faa5c2b1dae7cf5fb9a22f2c0a345de68cd152825e5438ece2fa478a3c60ebe56f33cd552a9f1e7c1e1826cbda6c982a63384a94bb347c5fcc632fffd609e069f3a2499b90ea612a36c39ee39e2acbd065b4fad0ce20a99b95c3bb54184806bbb0b18f9be5d9a3caca6c153bef090f26969d42f99b50cea64319aae436aabc204ea882049d831e8a5f9ee802b47cebdb48c2357ddc4e3b60f12fcfc13dffa75419bd36280735854529e703dbf6b99f41c00b74f6f33521c6314d3d21822434112758fe5929a06aee886ceaf2e2f59b313dca996bfbad3b971c70b5681e747deaa9cd0f7a2b1c020174fcd3b78cf39acd23e4aadee49f095f3fbd0f6f503f82f5c36e75b64853debbdb0ffa571e33507436fd3571a4cd408023d94f698446abf319357a1aab5c7
+TAG: ff57e9ad2942ab503b0bafcafe2d1b865e7f95f4
+
+# DIGEST: f61096694be30b85b6571dfc8b5bfc4d364bd225
+KEY: 4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f437248
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7
+AD: a116bfc9095da49db3d71f
+CT: 498ee9a108fcbb8953eb07b37295f3be910090ee8d7867779fafb057830eb374b68e177e62416f9b34c6354ee6ba8e90aaefd02b5c0777f35b175e25b00dc9f2bfbccf16fb9d4e30e1382ac1a51e2ac08121173efdc5ece35d0be23c071dc621b1d35d4d926309a11580f7526f8596903a326669e5ef12faa11cd9175e97bf3194cd9e1d8c7d01fe01b8a1c88ffce9b14be053674f5bf7b4987091cdffe12aa53d641d2b78a852969d8ae45eef5a964f0b617a5acc98d71c414157d036eb14f4f33d4fce801c4ace2df271259a105a72b37c38bc858c2aae401858d32e1a110d5de3043740860a08603d652a8d387b443f2f72e28a07a8ee901277345a47444c00ac2b1506804da67ecd92bd672b29c6037d0d056eed647904fa8dae86cc43616c8a69477723b0ed13331b3f620facad9e10824bf15efa7d6cffa935f26eebdf2719ede194a6029d76f474364f95f049393841e43dd43ede3849e57cb84ae4c8e06ed374ea4f58dd171161460fcd3a5fef4e71fdf650eb2fc65bb2120fb434390d887111f407a5558ca3fe54cf92bbe6c069ae942b34f41ff9727e0c
+TAG: 3bfaecc79c3270db8b7971e68f6912a8a84d0306
+
+# DIGEST: acd9a5179a0ec782a63bc824188d838776bc1b81
+KEY: 3f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc909
+AD: 5da49db3d71f4b975c5d50
+CT: f433eec0a92a6c87af7f65b9a33447409036fea98c409835e252aeecd3ce4225cd67b9b8c63228ab3e8c03157da29e40b94db66a23447adc2b6e7ab15c0d35917ee74d2230854a33781b4a8e953aa499e69610af56f29716013769756ce7a3a89ba6cba1eeecac208d86f736fd3c7de2a69870a24c300b01fa5c1d00a6908d74ae21209fa52ea94cf5f834059aae61ca242b6ac170513ffeb0ea4745abf0da3e9f4e58b7111b58d26cff5b5a2488cbe443a58a28da10bb507a041d9e2fb6724917b4a5f30bd3d103cc2ad134a840ad764d7e9ad882a4dbf82534f64aff19a189cc8e59596996d57e3d51cd7b4bd7b27a54055fd08c48186ca8086a2eff30155cd500db3077c5666348d61ee60490f187f397c893fa1f994db993cb64ea15078493a7f9994a90c1a6524e8dcc34ec6dd30782b9d2102d20e85e88efb48e929fd8ed901335d2a2f0f278affba985f8fbc01e7866342921221a8f9bb13babe23aa19ae46c236ef8858c3759ab19982b90905e12ba64a8af0defa71d94e7c786f4f38d973e476aba6517b8330ac6d782d69df184316a9bacdb8148cf0ea4
+TAG: 26387a216709732e2ceb4c847031abc90e6fcd06
+
+# DIGEST: 152118d780c866c5eed3a08d2d9960cdc5acaabf
+KEY: 8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d7
+AD: 1f4b975c5d503f478b22dc
+CT: fdbbda3b59b58b69fda1bd7f3f2e09789f0673170a0fdf7b8a560d758c53073440bb046c8ed52feb841f590a35575d2dbe42ed5d2c740e05d3b2c29e48761f5bc112e7323d9f4b44a70a74d41d0a76c8fa042a99208c8ec4462a91043c919fba39a67cf2dcb38e0c9646198a7065592825964e56b88e8b44feb5df2d1bc105e25932b13ffbdacca52835fb818f756341c936f58ffc8d5e68a7fc95f63566a7e85b70f0f6b9c37b33821d3f9321c021aa6cd3cf71fbc0edd49ab7a69be749d9875d0e0e060de3bb8b204011819ddcb1795f5c0bee7ade3d7352ed9d94338df47bf0fff00e1f7d519920a0344e8109def37dbfb100ef6310da54c3c7f77132e97298e48201146a16dfeb54265c0d97a6decc4f2861b7a7e678ef171f52d3fb64aada6dc1be57c9077227b75759df8a25d493c67fee9a25bef1e06c600572fe2562aa0b400eba69e35c52d970b4b0cd283d51b7906dd4df3844864af2500c9af5250d4be1eb01d4bb6129b80b0d5079696a9143b54e51c0bd4de47d3016d8a546f16387d9c5f4416c77b906e89fa29145dc38f7158b47769c94d0d18619
+TAG: 6de1ebebd88940bfde4d0e79036abd346c8001ca
+
+# DIGEST: ca91b15125e07b81debf75ff84e7eed4da5808a0
+KEY: 1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a73
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d
+AD: 503f478b22dc8253bee6fd
+CT: b1786f6ec328c919403049ec715cd835c45428b455456b7b968a11799addf79315bc7f80b64b7eee0e20bc464a0e02d144795b2609d2807c389eecff7c5494830075fff7d94332855d5c7620a142b70d8f5d377fe1a75b590b588969e7e55a76980f599db245d4bf6efb0aa0f10288865d9084ecb9b029c9736433b4d44825deddacbef88bae53f6c404a6dc3ddaa07a98dca1a437ea589830b6ea19c40f380f5a520cdedcdac965c7a203af7abe0f72409c17b1292fad665ce55c5c071dd0e2ec67f5d809d0222f5fb0b0f7d6356f4f3056324bc122b6be09ce53ad09033aa5df02c3d215e579b595729f6f999d81fb7c7c1843562e8d324c6c66df00f28418f78be63cfd8d1705294fb477e7c4e2171dde57083ce322b2b66f0fe9bc38f3ad9659a1ab27ba9c4e1aa139da8ee910a3b2aac66b116af8bf816fee3a6338008cadd97d5ac82211c968ac8c97683967b11e146860e703a59c8cf2468cabb92a7c86a825ee1f231f5c227aea3bb292acfbc5a8a73c29a69be3e50135a82ca0a3612d134fbb8c86bb58ba6ec91f8fcab306095a588b19f07525e5fb51462e41c8c0c00b037f80e00ad40f93781a
+TAG: 71182ecd62747c589ccc2319e1a3534a426cb75f
+
+# DIGEST: 93d06638fe1e836ecdf5d30db3e4fd0660d9d701
+KEY: 01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22
+AD: dc8253bee6fd1b174c307f
+CT: f402036b6e4f5fe96520115aadff36491e42f7d0836599ab08d497b78715a153edbc02eb8a8af6525d018f9f4bb6b0d061be80a69441e632a22979fe26cb0e6947c462da97b28ea69e35de6b1a0508b17f862206881608b471455b7409aa6593f291cee81b0df85ac915f44a5fd48221e0ec2f4bbb0f0ec4287e70d7f4e54a2b87cc73f11b9a6d1386a2719f3533b867335b5a26279cb51bba6c66ebdb03f7ad0932cb0465204775b74999c7cf6fb80f9b697732678313467b483855e4a7fe432ad048bb3bcb4f4d845eb4e503282185678d3117b13171869a4605f7c0e332e951bbdf796d51da6f93b043b93527371a5a5dcde3a21424c8625f3a5aee72505fd3e753152955d96232b07a2c619d29524411c0658f7653ae32320682e61959998f23972437a24f99132e2cc2cab1029783504520625789fe0fcdcdc3e7fe745928b5fcb79f83d8294d3e61e219f1b19caef5bc0c218fa166b05b77158e45738c8817ba578007a1d4f70e702615b7a3880847a21191b571587941a10a5a704a27edcdfbbdf4fe4ffdd9971ccfdea0649ffcaf0cd9f2e58b0eea8c29deaf10013f16a1d5407de8538d3574b8f6
+TAG: 15aa7aac3a0499b39e77b2e6d44a052380a5c8f2
+
+# DIGEST: a12c8aa71387379d0e43afa0321979e018d56547
+KEY: 9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6
+AD: fd1b174c307f01be95abaa
+CT: e12c1e2c88a2c08a0c84a95cf3596ddea16a74f4c24f1a62aefb90fa7b9e7e0c7cba1823e8ab41db069779f51f03ae5aa382f08415cadef6b0f525ef78b98a6d04c28f6a2d7f6798daaad01d3f3846532fc6d2130516769f35db6fd288a27911575cd7cbff19fc4e2e674763c929efb375b5649b693bf4be0c229ad2f6fac552a4a9c49ef2dfeaab9df1468e4827c0e68f562b1833a5b053e2b72fae7231c3110a417fa3d65334112be45c762174dbcf73957d5a07e2db167c388e93b85e8ee674f48e6a5e2e2250b438bce981c8a9f48dc7e980249d9ac7d1a2fb1c439aac9c90582807d2ad0d2b8b566631f472104e167bfab2939896453b67680be0a70e699d0c168357bd3f16e0d745ef9f1546e4f72725bd212290235927004d109942954bef8a0bccb328f063ae0342f4b4d102cee4d9ba1eafe9287ef189d1865747a55a65eaf25b203ddf37f06e63ca4e0dda3a1ad4ac1b1e8526020e2b94dfdb0f66ac7832706002f2851971d14e57d62e8e21c0d82a537a313499072d63f373c393c03af278503b6d831ecdfe5d3ec7c09a6d6788c56daa8504011f21e649a59304c51a8cc4f2cf45bfb9f0c142
+TAG: ebc6600443f9694846e6f8a626b9aaf6585791ee
+
+# DIGEST: 8a524c3ce814e3059b4c7a6ac748783ce1385c68
+KEY: 2305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c30
+AD: 7f01be95abaa9bee585777
+CT: a1bc4e51912193d23fe189ae2fb121b8a8f03b054927816400674246ba1c0608992e4faa9bf3342e4aa349fd4bec034267b2a2202c3792da2b14288c024a50b672ef53439313e52ccbf490911c9718aa0d19555a00490f4fd1f9c28f4096958c439153eb58692a6da902d39693ae5e0d0eb70e9ca87eb79af26c7a1c456220bf31c91ae30d96bfd5b87592e57820b9ce8a1c425e4b5d7b6df443e436dea5090939d4d9a50ca822624e757cc1c73c94d9a3aae18e8a73f5f043df6e0fe4ae05487a4af94a54192ba2136a1daccf844cbe455dcfe0d28b3d1ea002ad38dbda9b5de0b665549163e7bb259b6a7ec39dd497b2aa0223b69c2655db5714273fd36f1f567b9ebcfa3e5ee5c036e8abb6e572acd492eaa61ea1f82757ca0e300b97ccc5d2022bcff0557ab9d78ac7e4cf740cb2864d6ef2e130a0a81ee126b1ca2787127f4fab3e4b551c7699bde44d18cebf3f7c466f8edb04e88c2d6ea8971313ec9f6c2d1592bc2002e6eb8c5e90f12aaf2c0b2a3cbe88117217665dcf6c037e1bfd58a3fea924e4acf6cdcd5563d45942a8623b5124a33ce6c59f1f0c27b1d61f4379c4a844d3c68362050b6ad15c0bb0ed565fea5e69b21aa5476d391f
+TAG: db71512300dc7d825bc25b966f5df0900b024a4b
+
+# DIGEST: c31dae836928083019ab6902865d9f14c88fe27b
+KEY: 50d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80ab
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95ab
+AD: aa9bee5857772305daa4b5
+CT: 56dc7c2bbe23c6e4d7b91187e19c851d2a29fa715d0bc0eb902a58369adecf325f37d2b000d4cb06b0a764484117bd49ac9915c0b1e9b885f3331106bd70c3558973681c5cfbfd6ef9619c5c8a0ef96d24294aa27321786d9ebc8349f53ec3532918328d5c4e343c65ea07ecfe6ed8bc06f9783cad2440fd1474fe6ae29779ea961956aa052d64a6618c9e36468677fae3f9698d1ca3de0a79b154cf19776cb4b1b6b597178c3aeed245649c5d3a4a029c84b22f1d5ffdac07e9625bf6fc4431a67c52d598b9330cdf41d4ba0ebcc91c74bed2c16373b99aacefc56ccfada070cd7e1d1f60b35a891d69a71d9ec65f8c68f81965d9cdd9218b4b47e632f72a98e5efd08a222929358021b653954418881dd766a52176bf32c3ef7ee6b8dd8c2063f44d5e5d18fcb03163231bc3b46e04552c673d7b605499e5248e52eddc6db41ac678cfab283d471718a8878de334b740ef87448117289c985ddda0da61ec1aab4ca037d82ae417556030d39b195ca5c67973feda88672bb9b333c32a7e762d4d804d3af2686ae0e6435a0a61e02a18818e5470da9fc18993398ee043abb2d9835fed80843e02b1b6ede114cc0461f1161d4ad55e5ec06b2142381c
+TAG: eed7e1f348b06f08e09a128b274cb695e5a1f717
+
+# DIGEST: 4b2db052fc8a09f7a0c26afc66dbcd8ae5c9bf62
+KEY: 089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de1
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857
+AD: 772305daa4b550d75f05d8
+CT: fe77092f381d9eb10c17443b47b4a73733f213b0a94b2b3e9487635fdfa0314e0233f2dc43ac2356c32d1efecfbda315a414a0deab24b076883413ed464b185319b8f0edff6c8b65d8e607ec5132403e527ae8bd78b7ebf29ddd61f0980c0c59f5fde07f52c1dfcb2597d5d8e4276fcd19b6d1a923f1c3365be14b2d89a1b3cb45dd668d410f4fae178bd3295c81c01ecfc72a5a43197100bd1ff4eced052366994c83c45c6244dcc9681645c26fb52ac731912d68b4467c98f3f773882a230c3e21429a16bb67c0f6ceefa6599a76c47d769fd8328d8e5002998ed7cfc7adb4a301d0ba67c3eb71aa82bcfc4a0cc65cc3b6324b383e9f9d1e0c097f996785affe7f4b6241c19769c19330d716ba315750e2edd6ee66b336dcd6d336eb7b5d1c4640689a0707917de3cdf7bb5b149691ef5875e18a42adb447b8c618cfc7e6d836bf072878be2ebd0b9d3f02e6ba4137ef7bb1ec9be8b56913001358957145c117ec61424d012527aca33ed2437a4def56b1b417f09daef026ed8e3972f2ade1b2c7e4c7c9020c79f61d8720161b86c27a27910834b6cb32112d0a26b230c3fbe31dc80118d35bf210cb3be323461b648157e0d420adc0e48390dc57
+TAG: 9fa1e1023a9c77c0e772a7c7f67608637fe0bfdf
+
+# DIGEST: 881926d37fae9095362fff56efadd9fa3c455ebd
+KEY: 711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4
+AD: b550d75f05d8089850fea3
+CT: 2cd78a1d5e00cf2b8d4eef9ba6d4809a2d729e9bac3c5649f0529fda45971423bda7b65a091c1c96c2ed818c6f2f8eb521da64073a4c6df9c2ce3e154435107476178f55e5ab65b4ea8d52f4030d3dbefb020cb33d29d76518325c7bad7c0ed926cff0650ea851eeda22482b5af03a8c4144f49ccaf9352f7ef9eaac42031dfa9adb694b0ec0452165ed44a6bce29fb4f1f7c32113538d0a874e08610194a5017d974e2ec6b1b9e82ebc46fd63f496c24eb032b9b996e3d79fa884909867dd21a290e6b4c0f25301312cdb8c71942562044532fb268cf350b05c62c68f6aeb5ebb9830f85e4eae5eacc7189968b6223e33537735e6f56b06ea4bd67183711fc3859f0e598d4b793ea7f073ce6d8023b0f509edc82a215a19dbba80bb036485c9a458ab2358ae6ca8d46ebd6eb83eaaec1177564f68aa67bfa40b17263222e22622a200fcea120173bc7eb97d980c7a8f6b3ce91973ba23c1aed6935ec1e36be8d4d385611ed0acad0121d7d850bd90ebcd76b369c772c8cefc9348387789e9eb47b0ee707660955b7da4c738a3777c018a90238ffb7b10ce5ee0d7b717d33aeb136f203662c70e6977f1dc757038fab0a6323fbd456f1f1af1d92f5a7a314148a6f2d4567218c5ab7cafaf53
+TAG: f1fa988620039a434fad9ef360b228e5dfc66c36
+
+# DIGEST: 92d143942e6ef5b44ad7a4b8e71c22f1ecaafffb
+KEY: 2610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d7
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05
+AD: d8089850fea3711265bf78
+CT: 47c359b12a231308471fcd0df2af5247f18ce9561f1fec792ed27997f6c7a7ea9fd77fb857dc8cbc7a4f741dc245baa7993a6112b15c444f099f79b53df80050946a2d07c0e70bfb83d8a05c6b1880e3fdbee50e9eaba819d516aaddce6908340cbcb46d30cb12cbb68c8b8ab72f72df3b2b2f2e38798a2df4c3788b4a9968931d3c15658922bfa9eebc78dc59f218b426f5b0c71d8b66a82a07d9f8654b679c874d5af333cf454147b478c2503403b75431f8de1f2861803012cf3b686deac373b6224431dc5381ff00e54f6923c99384366922e84bc2e866a04fd1b044c66dc2a9ce1ad3c435bb94f6a1a0bc70ef8bd89b8f2ca46f6048a43fd77a2e73eadd5a2243971b4639a6baa4e8cd571b2cb2cc7b9635d660470444aeb3e898a1a2b7afc3cb7bd9c1c8cf3edc792a8892db4ded7388cc88a269d5b22b73cc1f0e02df7ba4acee4712b4a69580aab8db133313cb4014d094480ecd5d3a6019fc3eaac315e70682bb8a952853cc6b1c3001a67fd0e8abb838f8443c241cd8a209ff605cf1fce4eeaa66479543ebbf7ff2829670116fe30c533dd79cd3104dea4628442628c5826e9fd8e670d1e631b5eb28083f18db3b64493cb979091d4ad3d1ce6a5d496ec976048bb998c8d2ebc7
+TAG: 4353d819718eeceb0a50799e3a4743a0f964b7a6
+
+# DIGEST: 7fcec4927096421498e91df912cfe43b2e971d4a
+KEY: 24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a8
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fe
+AD: a3711265bf782610460bfd
+CT: 4d282f5b19d4d42dae2a0a066761ce1dd2baa3dc0cf8713de4a0575a01cf652034ccb126382e92e067b6ab5b8074f0908d1cdf18cb9b20433ddba7cf65b88568ad45b5719b0db5e2c6600054b6bf6bfb0f53418da9f0e8abc97ae45acb588a14d6ba9459c751cf6495e6a8356bb974229ba7287ccd8e08e12aea474140417f46b8c89b569a46f7bb6e28ba26b29ba6995966851d65c137aca29a06ae93878a5ef77bbf3ee4bf36ed4c15ad5f64193b2f631ceae958575fb1c504b37df2ba8f78de83fa2d678fa4eff18e81ce6f56298d66ef401683c3bbc5ec1860933a1bae605399e29826e0df26d650d57b9d84d370bb853b3d491483d348ab8a66b00f126607a1c87413306e3e06670c97e75f72d7772310b09991bcacbb2a120e5dfff5e11cf3ac94481fe3d484b509ec71f2b8f4566b46abe231bd6c02b09ac25ca1aa15678789508f93cdf309881ac081f416e99e6b143c7fdfc5bd1e8bfb75c47eb89c83f8fac5ac86e26574c99f8325cf7ab05986d0d241400349a59153d10ec7516396b500e7b2dc24c05817e38b30f7cdc25f603a82506475a047ec6cd73747df51928e6d210c261f8a148ad576c9e76e2aa4d128d7c8127dfda4d74c85cc2df80a55f5d3f4f1d9c787dddd0fd3
+TAG: 6cb89c50675552d0ffcb0d90c72602b703d409ca
+
+# DIGEST: c1c6273ce723df9f2033c7150d466c011bb457da
+KEY: a12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e9770
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf
+AD: 782610460bfd24ba022e6d
+CT: 43ad95cab27e9e2366235309ee4a84c7642025f5c0f2944b6802d83eeb8a9c46a346c33a1eadea00f95cc78f4d4073edb81a6a2b18ae40d8d54ac2474d3fa966c51bc0878c176ed39f63b73bd1df5d17bdb4e3e9bc978bc9e47133531d823d0004afd9c7b3874aeb205431f9475b6442f8d8424f01f3119fa5e063723d54584fe23f181509dda41e0347341001a38323fd7d36870ba6e4717eb1920ceed81a40160b441e9c627fc08b16bbf85397e8232895d0d44422c682208b7c34c542c0693482545e9f5e0981d84d10756ad895573ecee79a5eeb180208a05fb38d4ba309449b92db287deb0fbd07882996dc6ded4ce145e4ac883e570af5be1a0ef0f046cb847f8bebe45754a97f1e6b976eafebb46fd1885b94e5eea20e89a9134fb2c3f632f67e5539fa915d4b90af3338d0007eca44ace0d6e7bdd918e7fe3354af3da8be1528e792ca2f163b2ef0edea2301159e7a0ec20a57c1c3de1f0273fc6c33efcef75131b77cf740b7c9803e20c8097605b3b0754bc60e93dbd05de690237b4cd16f3bfbc36173f9ca8b66489ac203b32fc2c9a9c3f34307699af08e8c03e253c95277fe8b734158b1ebd943ce6397ef4285e4acc43b1217241697a0e8d3b7df22330033997469d1cbaa6e5586ba9fd4abed5f115e5d073ef2e4e3
+TAG: 1cd567258b44f27d8a450615c954b90268a3a4d2
+
+# DIGEST: 11424a64d5ce78fd71b30a8070aea071d873afea
+KEY: 4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c9b66
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460b
+AD: fd24ba022e6da12dd4c27f
+CT: 49c8529d90530d74ec84089b8936fcf772bbd205dc1cb2fd7d623a9f995b61d20b7bed5e432bf8f283dff639855e81196099ae224900cce32e751de9d8be60350a22f8c5871095fe6ea0899a193711cf6309fdbc89f68bcec9941cb4d6ed121e9cf2d362b1396f353152d783ca897e81276bbd02f2423cfb6ae0172ece1ae9b9ab8c352144e145305daa975634fb1db85d4318433f01cb150f5a1bfa9c233d05ffcac991a4e217339a015a4441da79e06977e0ef3d5dea040cee1611dff24f4ee0fc75b6ab57c1158c2306c873ddb9cf93005c12de1202f0c2d056faf51f34b0e544fcf16276d55ac7bb71a02fe33723069b76235d6796b759235df1c67a1cf86c3fafaa11bbc704fe27fa92524f8629cb80e197bb0e4e2a7920afcf9f11f6caf2fa7529411375a5e19e030072e7e65e185f042b5df62b91f1b0355a71aea9354fe629dc0c163e72d98d5c4fe8e90fe7f16a7b45c98ced5e715a3ddbb465f956973d38da213e2c106385bd2990f0a9f94043908f183fb2b638e372419ddabe64317fecbb02875276284900072d58ddf3607832616fd6f60c14f4b44d758bf2c99fbbd5df8a632b97cec0d7e8ed570d7949929f19fa3655808b97e38942435b6817b9b50b2dbaf1ed01355dfe3ba0766417218d8f3c97c6c71f6eda61
+TAG: 9167fffc2ffcabdf64082f265b31052c240d03d0
+
+# DIGEST: 6b7295febce7fba8d79d1e7ab8fdfc452191e2ba
+KEY: 454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c9b66262c0f0368
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e
+AD: 6da12dd4c27f4372480974
+CT: 1fe976a4efa5debb0d17032940d4d95335d66d02bf4f57be78ccdc3e8a81eab2f7dbef2db83d0442238598c2976cd693dbdfc2ff936062f2e99bc7c0036052f8ddb2c86dfb181166e04a01e0c1764b35e408be6f2013f668a6ff07bd27092370186e7b2180e36e9fb9f3ec90a36539d0f181f0b5b8c5991bb4ce9ce09815597559f61ce460ba2b236f9955b75c114af0869627a49a2de946072d8dde11f20c1afcdd5c979c28a4102b9ca4e6e0cf709673768fc1f4dbb90f3447be2384dbce69b12108a6b35b5389e2c79e4e398c5b9f0c1b665049ba76e7249f4ac2d9c36c647dbf30021da94cbf3eabd07f1954fcdc7d7798041edeb5a909e7b27f149cf8d9cc6df30c064df1c5dd4e8af6adfc9d9e4124bcb19d1a5ee8162a9d645d77184cd92bacd8f89fefef2125259fdc9cf8a0a2310dc631f1c96b681428819a73dca987fe74e6c6c5ccb8db201b3493e3f13f9d5d2a3bea0cd2675ca8f6945eaca741eee15774527cacb9a8169e5e3250cf318de6f8d7f0f3ab777b110c12413a97df8d446ca06e6330234498d58b93a4ad75e7c782f9eedaec1988d314a06366afd4de3b061ca49855c22f12f0d38ccf19f97b0825402429709d74e75c3602e573249fde601f393c945d281d380aa7008148be4ebc041f86979446710048
+TAG: 41aa89ee180786907e87dc87a8d552e1dae5f9a6
+
+# DIGEST: 1dadffba439570155af2509a548764a93042d23a
+KEY: e9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c9b66262c0f0368fe9d0cb746
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c2
+AD: 7f4372480974454879c41d
+CT: fcbf4939de59426da2002fcb8e3a4d07604a168e9ffb5f13afcfbdc45325e3ecf0659ea736f9dbf61cec1dbed1024eff9e3bcb721c28d004549fd84e2cdeae36dc5e5abba4f0102835740bb877858814fa38290344addefb47ae583171a510719d9aa18c8f8a5e01396fecf1a982e162edf1047f56e8e4a839c5560473f389a4c7ea8fd5e03c7f2d31ccbc094f04e2a510aa57fe30f37cda765ddcd2bec89ab3f1f5f2ca423c68664c3303520c71439230116409dd84b4a26c1a102e521253ccd455793b0d883b1569b5013653b1c606143fcba7252a70d2a2026b989d1f67fdd594d2b33bde1bf7ee9bcb6c013ea8886e0ec1341039b8d8fbb4d865754a62d0e2a1151c917368e93fed0cb29e2d63ae176cbd95991db0a2864b27b6cf5782093bbe0ae117c7b2931f678bcb07aaae3d955b61e7ebbab8e84442295700cebf1a8f7d846fe788baa0660608bcbfa59c4bc9e5d163654aea99635f9bb63b8074478fc97b4981f5e5d35430b1e18332370dc5f4e94616b0270112dc446335d10a169e8a6923765647607ba9ad65c6f6f008cdf041af2e136b398bd1d1f67044f8360d9c1e90012e594a353d8e45aefac62173fd1b03ee5e4aa6961d83cbf1096dfa02f36ef62ceea5bf88f95301464d0046cc8ae3bfa611caa0c63d0785
+TAG: 0f8608529bdc90c222092bfab0239a3b07b9cb1f
+
+# DIGEST: e654b4c78e1c0061eea2996fc126c9bfd41eb6d9
+KEY: 3b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c9b66262c0f0368fe9d0cb746bbd55813e8
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f43724809
+AD: 74454879c41de9ac9f9823
+CT: 3a35e98cfbeeabc993af7e952b148ceb87a110d851bf2d036e5eed8482b39b881b3180dc50ce782a8cbe2c586863c5d038fc4f37d4a96ce8732abb984ae90bbccb86f7766e9712e43d3ec40fdd7a1c88cfbf14743908c78dd4c19d449db7557e0c30127d35a49503d8dce6c9a9e6f07e1c86d7e365162ec05a8b4ed301645f8274999a6c5beafc5b27dd68608aeb2efdd9cb00c6236bb143e7d91709a3fea0e865330680a854d47ae3b6067002a01aec6bdab9e60c19ca66cc39d4a44ada1e21720bd5bd87cdfb31b8a9bfac77feeafc9f8e92c4131d73a3cfb64efae2e8d14fed99c2bc88f63f88079d30b78df18ac03db855338986c0fd1614dc6afaea71130290bf52270999f3392128bc48fb0a6d6425c383b637f4c293e177f479f6a2d6323ed545bbd564f743850a121da96256a8daf163fd80835558b21e0286cf008e7cd87bab94222fd7faa395ee2ba19aa3abf5d000e7514a35357941b97e4ef433c30972e995b0991c862cefdf79712cbd3655ceb43e1e5f5b0d3f5e275bfad98a667d997333d704e4d70acc488b6829d18d1263b841307d592f760a66761e800b4676d64546a1d8630d97218a7c5f555d4a90cf58eee4bd1e1fc0e15f8f64d336edf9ca00183169f237a924e7efd5a339f3cc1bb90b4c513bb9969ecdc9beb5c5b24af9f27ebc204aace6315a
+TAG: 197550907bf6079b848eb1dca1a96192ee7c8107
+
+# DIGEST: 654b8591c7f0506261713e9ce7a6fd24a6b9357e
+KEY: 61792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c9b66262c0f0368fe9d0cb746bbd55813e8d454817c21
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c4
+AD: 1de9ac9f98233b5a7379a5
+CT: 7e1b59c791aeef6577c7ac69f8624352b7c2c7d1c8b14a7a0daf8240cc9d71ff1298eebf18ab6d469e1a327bbc3bb539df445ddcf7dccacb54f0a4ce6cf18bec20101bcd62bb2b30d8426a1e3ba949dcb69767aab5b8d2228267d784bde55bf887403188cd39453d32d50428bb9846212e4bbd3843161dc830646ba6e251ffad5d1b382101c7a3c87163867391fe44a58639e8a29fbd34cce657d321d004f842e0efa9d4cf03f557bf07a1201ac36258a4810dc101c427e19bb79f0800f27732094ee1dbab2abfc061fd4a1e84b2d36e560a38465cd4c8bc04bc27ffe90f1ce5999fc78d9432ed98c8dac4047a61547b6205bebe2191782ca63e50bb29c9bea553f5de0e9051cef35e3122c00e0d3a2468ecb2a898225c5f65fae573b17a15e013655a2ddc62adfe61ce5a7e352539c6d27c9726d2ca5492ee25b6d8233e32383100d131abce97b33dfe18a415156917ead8fe854c53bde97c0202e782679ac46f05afe1b9ad6b41bcb65bc8a80682ea8092bba0c47a9a03d08004a11756d9274ff83d5d468475c8a4a56f81cd1367040a3f75fd998b5fb3380cf8c1630fdb948fa2d0930fa5b009abc755f4bf70a59847969500d43e2db40ee517c9a6826e8e3746b3d40f9a6e7b35362550cabfa601a887bfabfd28476b3d7eb8917d66bbe9d21bfebb5a22e74d37769a86
+TAG: 785c57bb760e8a28de7a7ca3207fef4e80c284b4
+
+# DIGEST: 1eaad32c8d0cefaa5e2c503bb2185a73e6387fac
+KEY: 16430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c9b66262c0f0368fe9d0cb746bbd55813e8d454817c212d3a0063be
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98
+AD: 233b5a7379a561792c0f31
+CT: 26234359615c88fbbf5fddd43d4832a57bda2037e2177b264309e2e50c28efc28c5ed5cbf6dea046a14caa64d499352ecba0eb2d4bd376c6b1e14048033e21b9ec63f500a70c53be60099d9c9e46ea8f250d3d20c834c3c0638a9245377fe2b76b74ea14bca6b4bdc7e8d86ca59f397fe72b8c4cbb8edc3dca7f9f234529034fe5f1441210a8ad9b4694fe013f7e4a906fc400a27279f2a1a31700750e2209f6296ed808c893a42214b46f765c9d01cee46df18b02d5493c3a1da3a6258e89e47934ade4da2fa9eef7f5b1887a60585684b1c5c2ac60d94a62d79694b063444fa36674ecde12095e9203d281da3118d058f547ede5e4b67a11ab55c1b42fe01a94a601ba031c5b0b4088563344cc28d640bf2e7c81a259211b130bb9ba9ad93090c0e11cc939b99046fe7f25132672c3714f9973513af628f21942da6b459a60e31fe1bb9bf4f6259d8c9fa07d796a264f94d64122d186a0220d9f44b040396c9c187d5ad1d806ca613a4d0f5038a8b77177f39361f9107bea7700ba835dcd38cb48a6c5af0bfbb07b7a2543f1c661f1dec06acadf8860fa2220c67bbc9c97c44cb7cc58831563153149713ca2db85af46932a8de891da1d4662e52ed5b7c1c15d5557a0930c7177c2046b50aaf14874512cd9ed62efabe5704573a4f44a4ddf71202a6ea8c7068422998eb6
+TAG: 0165231c67e88b0abd1d7c1c3dcab1b7006d4d3f
+
+# DIGEST: 862c0517b3658e9b9cd27db608d49e24e9b4667d
+KEY: a058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c9b66262c0f0368fe9d0cb746bbd55813e8d454817c212d3a0063be26e0636617
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379
+AD: a561792c0f3116430e8b6e
+CT: 6f2cea3b4aa1b3ae78d31e47c0c1e03df944352b9bd5483cfc09577aab2095a0a7e977e9c1c6451625d85d162c1653423609f141aac93123b2a0bd093c5bcdd9a49b27ace4dbe6acb486446f437c27e619a0f69405afc83240f087feb029fdf8f3f25a8a262b4a3efc4bc80512a96a45cca61d46e42132abd34c2821e7ff588c742062c01eacf9d1689f11648ebe326a91fe79275b5b1fb2af4d1440ff4a9ad35381daf2a2c0aa928216351c5b89ea33bf225d34efd7ec2c81c5af325b138a5f4ac50c5aca196d1b32ce8352431a8f08cb3b59d2f8de5c850e2a06d00c1d7f7027b4aa6757eb0c9fd3035063669a5ff8db2402818c88a7137ee309ef2735dd575e43b7508c81306dc50da65aa2276dbcd98537636ef06d1736f14e2babbc39457dc8d101d22e5516d652151c2092812814e9f73dd6cc805e670ca36e62799b42bc07fa1d93b9332c43a4b759e53ae138fd2b2b419b21a332ea304fb7db57e860509855b2a540cc909aff57e1433f295e8052c7609a88170feb7623cee8ee651ae1dca4b1afa427e2e43569d5b7f2ea688d2e2afb33f1dc0666c4b0df8aee281cbcbf5e964beb3851f7b929e5a4e06766746f22d4fa1a32913c0f449b4da8aac6294348f711d4d75bca509516668944d2a162a53a31229528e54e4bfbe13cef013efcd6687e890d292e42119529c92c76c80a678b6cd735a2d01acc18
+TAG: dbd90bc3997f57efc2c5c78c22fe4dd13f06fb91
+
diff --git a/src/crypto/cipher/test/aes_256_cbc_sha1_tls_tests.txt b/src/crypto/cipher/test/aes_256_cbc_sha1_tls_tests.txt
new file mode 100644
index 0000000..9cbeb39
--- /dev/null
+++ b/src/crypto/cipher/test/aes_256_cbc_sha1_tls_tests.txt
@@ -0,0 +1,840 @@
+# Generated by
+# go run make_legacy_aead_tests.go -cipher aes256 -mac sha1
+#
+# Note: aead_test's input format splits the ciphertext and tag positions of the sealed
+# input. But these legacy AEADs are MAC-then-encrypt and may include padding, so this
+# split isn't meaningful. The unencrypted MAC is included in the 'DIGEST' tag above
+# each test case.
+
+# Test with non-minimal padding.
+# DIGEST: 7f3a0e20bde700d3c5596909282e5c3e764c99e7
+KEY: 86d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e
+NONCE: 0d0c302a5f47e037446f5891d77df660
+IN: 936a91d0b5
+AD: d2c0267218cb7090c61713
+CT: d88861dcbb181ebd603365ed262b8f2faf5b86ab90a8930bfc0c55cb
+TAG: 9f1c88defe20893b2d5eb8ee6809c2452f302315
+NO_SEAL: 01
+
+# Test with bad padding values.
+# DIGEST: 7f3a0e20bde700d3c5596909282e5c3e764c99e7
+KEY: 86d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e
+NONCE: 0d0c302a5f47e037446f5891d77df660
+IN: 936a91d0b5
+AD: d2c0267218cb7090c61713
+CT: d88861dcbb181ebd603365ed
+TAG: 262b8f2f50b02faefb172ea4c7478e6f7477abf5
+NO_SEAL: 01
+FAILS: 01
+
+# Test with no padding.
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07
+TAG: ec90d128ef465f4a3645fd0b2601fbe2b0bceae2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: f0f82752a691ef5866413f2b2e5c1d0ebb41ccc8
+KEY: 7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9
+NONCE: ba2fd6773e0d0c302a5f47e037446f58
+IN:
+AD: 936a91d0b5d2c0267218cb
+CT: 612c50f907cda81e17437e36
+TAG: ab70f776ab74437f9d6eeb87fe373f855e71d302
+
+# DIGEST: 7f3a0e20bde700d3c5596909282e5c3e764c99e7
+KEY: 86d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e
+NONCE: 0d0c302a5f47e037446f5891d77df660
+IN: 936a91d0b5
+AD: d2c0267218cb7090c61713
+CT: d88861dcbb181ebd603365ed
+TAG: 262b8f2fcce52ffe745fc1c7ce881f2ed93c7fbc
+
+# DIGEST: 5b32faa93c18842b5cb7b075270438756d5f7dd2
+KEY: 97b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f
+NONCE: 47e037446f5891d77df660ed82933f62
+IN: 936a91d0b5d2c0267218
+AD: cb7090c6171386d641b877
+CT: b5a44ff124b35147c8832b7b
+TAG: 08bd2f5f31a10eed64200b62f72b9c71a06a14e4
+
+# DIGEST: 995a0f9b029aba3e0a3205364628bb76baccbf45
+KEY: 56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f
+NONCE: 5891d77df660ed82933f62be8dc55b43
+IN: 936a91d0b5d2c0267218cb7090c617
+AD: 1386d641b87797b684e0fb
+CT: d128b6056a11e9007634f1993def8750f83702d0ab0ab723a9a2df9f
+TAG: 967942ead5a3160aae2e81d44dfb06745fc5df2d
+
+# DIGEST: 023d08d5e5af3e0b016103c7c3cfd1d02577888e
+KEY: d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df6
+NONCE: 60ed82933f62be8dc55b436965aabe47
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b8
+AD: 7797b684e0fb56f97c3961
+CT: 6433705ba5fa7475ad4360e9ea95dd1c94f42a409014ab838a265f38
+TAG: 7c92b586e69347343f5bc2835cd925ee0f1ce9ae
+
+# DIGEST: ad4b11a43bb47aec3e91209f98f99839dfa1d6f6
+KEY: a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f
+NONCE: 62be8dc55b436965aabe477e0cdd46be
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0
+AD: fb56f97c3961d8afa22993
+CT: a511cb41a1a4ccfcc8bb2f3f1ceabb5894dde04c784521f037c2884d
+TAG: 9a51b8b056fd7993b5a7021f08aa891b8fe758d2
+
+# DIGEST: 580641286aa43bcef85be190e1967f627713bc64
+KEY: 89c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b
+NONCE: 436965aabe477e0cdd46be99371eb8da
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c39
+AD: 61d8afa22993a340b9b3c5
+CT: 4058092e17118a2a5642a6748128b9f3a1b4f6066df062f50ca8b2f33f27d8ee6402919ed7265c3eaec7bff4
+TAG: 1e228c5adee4da5f5e011c451ae6b1898c37fd73
+
+# DIGEST: abb06965675631a07f380e80a05cff36c2d42ecb
+KEY: f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe
+NONCE: 477e0cdd46be99371eb8da7dac997dea
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa229
+AD: 93a340b9b3c589c7481df3
+CT: 0d661570231e6395ef7d3622744d4bdb042eba415057c7a1d0b69d5a3b45d823ddf46c14b0ed290b203cb992
+TAG: 2d5d2039ede69ce09d1486f4f69ba47edbd879aa
+
+# DIGEST: c6a1ebefd827cde32df1d38379ee4bb6a7f81267
+KEY: d8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46
+NONCE: be99371eb8da7dac997deafd64b1fc65
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3
+AD: c589c7481df3f4183aa23f
+CT: 9b2135cddb9bde3de8bde3bd28443dad97160f9082871f54335b9adf2e8d38dd4e2664d6617e60c90df1f5f1
+TAG: 1b950ac39f86f765edfd995d3e35aa2b2a17c404
+
+# DIGEST: 77fcb5875838a28d24c4b6bd0916ebd827968073
+KEY: 03f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8
+NONCE: da7dac997deafd64b1fc65de39f4f035
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481d
+AD: f3f4183aa23fd8d7efd885
+CT: f5ce2c99afbf0b4f95b9fbb637284a3ae9bfe40459cdbdb1422508e4e1bcd0439cb43db5666c809858a02019d50401522e4a17b9aca15cf4cc4d120e
+TAG: dbdf6873c9bfc6b220de50eb22429b3b6b56ba0d
+
+# DIGEST: ff3c91da880d2942bbc51adafaebcf4c6fd50603
+KEY: c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997d
+NONCE: eafd64b1fc65de39f4f03541a11be112
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa2
+AD: 3fd8d7efd88503f78b8ed1
+CT: 1584991deb24d7302857918d975ac183244358a337f532aed39d5430a24b880892e81f81e8ba4333339344c6d648315c13b93441876c3ba67ae9e6e1
+TAG: 160029ddf23401042a0701286776a79e1f18764f
+
+# DIGEST: 8c439bfcfb896bd106f94676b5626f2bc624c313
+KEY: 773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc
+NONCE: 65de39f4f03541a11be112a72933c7b5
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd8
+AD: 8503f78b8ed1c8e9ba2fd6
+CT: 20ec6093b5cffc6112d7e81f6a7c15cabfc0198ea72c6150996d2d67b786053d008f39a9f72dd1d7677a0b8eab398d2e6158e06b868d9d61753aec98
+TAG: 125d0570de85c4bac646a252e5e25825b0dc9b7f
+
+# DIGEST: 35d9dfb89c1883210f03050da3166b6d13f5b8db
+KEY: 2a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 3541a11be112a72933c7b54ed4fad0be
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8e
+AD: d1c8e9ba2fd6773e0d0c30
+CT: 0478014ecd403576d3744dedaf875ad6edb95e02f8a8adcc8eeef2f7046be074ac72dd4657fd1beb285797cff933dae4dce573639a3d4453878aae0af7ebbb45698398e402ca1a2f2d20f7e5
+TAG: 62f533f9335a2243381353c18612c344310058c2
+
+# DIGEST: a07054c760cc66fc704edf950201005031f3faac
+KEY: 446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be1
+NONCE: 12a72933c7b54ed4fad0be905d41203f
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2f
+AD: d6773e0d0c302a5f47e037
+CT: a1e92776d0ffcfed03d1be956169f606733755d5a7011620c7ced6a825d8e59627e75692a41a1f2a86e62fc6052873b5458616414584e36bad698cf4c44909e0a26e0b32528feac2d7f69abb
+TAG: 480efc7a17e891603a7f3838fc28e487ca9ee348
+
+# DIGEST: 63efe7af502231420ed5aecce9a28446b257828d
+KEY: 7df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7
+NONCE: b54ed4fad0be905d41203f5dce998f8f
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c
+AD: 302a5f47e037446f5891d7
+CT: 2f25b5a3b01af5411466c8aa5d8ece037434d5e12b62306f2732cb063d0dcdfc2725e67118a242a5576d470fcaf9be6d811bf2789cc66f5561d0542438b5432fe713187a879fd80e1f4edc21
+TAG: 37f430d3b33404c96f691117b9365042a6bc9f17
+
+# DIGEST: e8e41988fad6c8b44c56544964cfe0a347b35b1e
+KEY: 933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0
+NONCE: be905d41203f5dce998f8fb2eaad409a
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e0
+AD: 37446f5891d77df660ed82
+CT: b1cf0005c93547664e09031d923c4ef9ad663a808189cd8aaa68fbada340d8bb13330499131ef3788cd91e9527702a2388802fdd2e91998a53ffbb466bb7e362d06677edd673cae71418a67c
+TAG: ad9732821248c5e5b7c9b5b6a440ab891ec922e1
+
+# DIGEST: 172f4992e692a88f49628e5d3937959be01aed2e
+KEY: c55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d4120
+NONCE: 3f5dce998f8fb2eaad409ae02116417d
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891
+AD: d77df660ed82933f62be8d
+CT: f1ab85a35a17541efb4f906e7fc85e64efec6ab40d59d3da920c4ec09797c3ad47820e9d934e51e3f4d097c4a555575939bfaeb8cfea062b64816a160d6e4d1ff02a5fded435ab9aa2daf22fa7d676fa14684ce099f4f0e11e785320
+TAG: debb89c7c8f7d31a0a32333f58ad58f9ec389761
+
+# DIGEST: a35fc7d25f90dd9cbd35910d5532aca8aba88b29
+KEY: aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f
+NONCE: 8fb2eaad409ae02116417dae0cef457b
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed
+AD: 82933f62be8dc55b436965
+CT: 1ddce9b3f674dfc1b94a6cb34418e6b75c93f14941a6dbe028ed59667404b93afead95ec50b9393a8e0e5f469fc1cbc5136f4dc54f3a005af6c88cf70ff39487cdc730dc131538279704a67492f5241faf00aa8c46d4307434911577
+TAG: 5a6db0a9323a8851bfb81e3f7981229d7a9d0360
+
+# DIGEST: 4abaa8453e8cfdefd918571a961d8351754ad5b4
+KEY: dd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad40
+NONCE: 9ae02116417dae0cef457b9e5e16dcc5
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be
+AD: 8dc55b436965aabe477e0c
+CT: bf13550fa32201ffc699cbf22de17ca268652f8ba2693dde72b626d01855eea7c21f0afae3fa03dc757491e8efb9091a4c100f8dccfd15a9b4dd94e4fe1f5e90cec62768d0a91e132acb1fbec1052878706359cab3445d38b1a78737
+TAG: 0bba8adc9c7ecac4a0d87033de3ece8478ecb0be
+
+# DIGEST: b51001b6ff9d27bccf3103a4961280e0a1406257
+KEY: 1eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae0211641
+NONCE: 7dae0cef457b9e5e16dcc5b6f25607f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b4369
+AD: 65aabe477e0cdd46be9937
+CT: 4772e647d03817c0f9deb39ff4f4f27fb0fed33e0630eb453883c707336f0e74ef206e92e31fb2935a466105dbdfd42c180ef63cf5cdd3c281337895e399df6078c22762eba5d84b8845ea00bd88bf5e4f0da518cae42502e8531b14d979bda6a89cb7f4f54501b3fc90129f
+TAG: 28198a9c52b7864a4a25ea34472f22eaf51209f3
+
+# DIGEST: ad2b43eee27e6267d8c5c1c3d558a07dcd6b1f5f
+KEY: 997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef45
+NONCE: 7b9e5e16dcc5b6f25607f00d033fb95f
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e
+AD: 0cdd46be99371eb8da7dac
+CT: 67466a0bda0815f726cd09d159e06088b2530b73775a8c18eab2d09ed7bd12b743b0a10345cb3126dc14d8f5c503b65a45467ef9b56ec7c5b24e5548e734d3f0fc90fd9c8019fc782882ea6e72f4df5fc6e8105e79d12fc588c9137c758995666f480dcf24b828c3e6018287
+TAG: 3556d7aa83282257dc21e5f34c1e5599e7c76aeb
+
+# DIGEST: 7b17b7cb19107af8fc4671420e461060e2ef3e61
+KEY: b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dc
+NONCE: c5b6f25607f00d033fb95fb09e4d00d6
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+AD: 371eb8da7dac997deafd64
+CT: b1025c9eb02f72e5526ef641778aebe786c2f85961997f1eaa090a33caae3a9df34da7088352a2df7a61eaaa026dadbcd604f5baa3a0de4fcbb3812816408d61384984141d9c78f47e725e99cea9d52f73cdd5e2c3961b035589db1d2283476006a1e10a992d4997623f4415
+TAG: 54acad8bcd9bdaab4641e1e01fa569c9a0e5e61b
+
+# DIGEST: a27799fc2e00e7abec4c5939451a834c4606cf7a
+KEY: f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607
+NONCE: f00d033fb95fb09e4d00d6172e780ab8
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7d
+AD: ac997deafd64b1fc65de39
+CT: 9b6a8359acfc5d15067e2e6d812727d768f44b3edf4272f57fb54db41d95153fb03d7a7b3371e91c4be80326f4d70a8f2ac1e867ad3772901c513895e694214d6c0fa1f431aeb016ccc93faacb4950082f0cf00d3a5879c9a4f3fdb281e911b40d6d0a84b05f4ce32f85b1657d75a3c72b69369cbf0d435790c97438
+TAG: a38109f3988e0faa64c5fa9481a847527f01c85c
+
+# DIGEST: 7c52593d1d37b0dc380297231c6cb7b64e04c493
+KEY: 1be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb9
+NONCE: 5fb09e4d00d6172e780ab8b700433a95
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd
+AD: 64b1fc65de39f4f03541a1
+CT: 8cacbae377d038fe27b37fdb253f3b136aa38660743dc6b4778ab16940a9710c8f08970164316e26c3b603140f2f43f62a88d021426b841baec29fb11a3d8735d0b8c14d133a825e1044be5523932ebd65b34433c083c2d77af313a240b1eeb52391728dcd04852fdcbf9b6f89502dddc317c485c893ad99aff613e6
+TAG: f95cf9c6c1c976c30585e3a7b8bdb5d1991861a3
+
+# DIGEST: ac6871d354eac507556770d8b6bf10b5240273ed
+KEY: 33c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00
+NONCE: d6172e780ab8b700433a957a741c9eb8
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de
+AD: 39f4f03541a11be112a729
+CT: 9807d89925c67a45c8ba18cfdb817f5bbc21e58c10f7dc8c15b70acd97e8b97e0393d5948d51a65f6f092590b38c845164e6d2b49288bd0f73c4f4b551b362470638f51422dcfdaaff5e8aaf80ff715f3f597fb9385ca18355b8e98d1de17a303d019f7d4b9a3acd07d257c049fc16134c53e1350cfb8c287cd3491b
+TAG: 8e157876e1b7a1a09b5b61969f6ad7ff8d1c80b5
+
+# DIGEST: 4f498d0aa9205160827626ef80c163275eca1f78
+KEY: fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780a
+NONCE: b8b700433a957a741c9eb80f2b021b14
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541
+AD: a11be112a72933c7b54ed4
+CT: 9b01cfa97c72b5ae8befd0d357283a52f6b8c5d9292d28f61373334280f815d6b69f878936738cebaf6fc84d20baf51868eb4d2ae08d64e724beea1887a76316acc955a00b5d1230fb120bf7d51f74fdc5f332521c59406bbd3161987c6ec49ad946a6a51755796de19830631daf69c78a847d2e515d409a7b77ffe75ee785184106419b8c7f38061f49cfe3
+TAG: a265e9d442fb3917d21f7ccfe3230c101816885a
+
+# DIGEST: f0901e8b8083c39222fc940384eb73cb96b22892
+KEY: 41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a
+NONCE: 957a741c9eb80f2b021b1444769da00f
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a7
+AD: 2933c7b54ed4fad0be905d
+CT: 452c39f1ed638a315dd21cfbfa383115d3345ae07f9968f2c30e47a05891ceacdc0f3b4669c929765f51f69c0db940b6ed5d0266894292e57d04c2fbb3b1fe2bc3acb98f87974341ed985a151f82673c237d101161ec73bdfa6144198a83a6e7ce8866b5fbb7bfdaa908dfc2fb15b917f5fc167bad7a91872bd9fa3744f28b2df449014989cbbe0c48237408
+TAG: 396bc6821c4d65f383e11c7a741a9e66fd6cb76f
+
+# DIGEST: 7af193cdcc8d7f17b55447a81eef3dfdf345bba8
+KEY: 998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9e
+NONCE: b80f2b021b1444769da00fcfab0f5f93
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54e
+AD: d4fad0be905d41203f5dce
+CT: e4879e4b80eac7bf4b235ee71db7af4a9b68cd4151d92ec1d33476595c714d4c6d97810f5c88c7ce2f45b181cb0a20b1969c88039248f7fce86f7f9458f51b726faf05610b76cef8afd0855a658feea188abdd705a3de0a655ce2e9a54617d8b646853210dc47dcb094c1db4c198cb1bc4796830bd6f806b6f08fb86188279614fc90365a40a1943d26e1890
+TAG: 11cffba98abb9a9104cb1cb16c76d349e4d9d598
+
+# DIGEST: 4ecf44faa266de0904b093653c4d623a543d12d8
+KEY: ad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b
+NONCE: 1444769da00fcfab0f5f93b511060c9c
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be90
+AD: 5d41203f5dce998f8fb2ea
+CT: 2c1a333439801d1d17c151f7ce56725581484bd90b2847c9f9eb3935f37efc7bcf398b46339386254a865b9e555f8980362a6057a0a1011d719136a09e2856d8a978b5c67d8da48811bb6f4f25441325529b9eaf3e3f0102871a191880ed5ad0b42be1bab94dbe64eb4efed91c2c8fa0eab4789179120f2a0dc172fc99829160e6c6db8ecb8792ae0ebd893e32b5493783befed569b17c99f7bc7087
+TAG: 6497e62b8cfe7425b179f8090146be6903480323
+
+# DIGEST: 92a938017497e0762115325c40b5f7c138d5c6f6
+KEY: 16417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da0
+NONCE: 0fcfab0f5f93b511060c9c5f3aacefe6
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5d
+AD: ce998f8fb2eaad409ae021
+CT: af71d8d9603b26c45f5f6fbf5b88d0ee7e2abce004c012faeaff1c0f6779dc54c387976a14174ce5b4407840591e92e1538b76f958286a98a37007afe80ba99a11d00cd81c39b6abc2567e70f87c439490f642a1cd0691941c0eafebe99656459805d0bdd36bb30effd1e2d7931a6d0aeaae860489eb05f9f9f9fd11ebbe8ca751bd21c11087ed4b9edd0ecc2006ea1ccdb53f7311c8a71982409227
+TAG: d759ed87bbd8111a082e5a1cd5986e27b52bb59a
+
+# DIGEST: 6b126413a7bac1069cbb5b338c158463a242d607
+KEY: ef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f
+NONCE: 93b511060c9c5f3aacefe61b184ad246
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2
+AD: eaad409ae02116417dae0c
+CT: 4cff025015d0aadad5fc178ff562305391c3db629b5f376287ea83ac43b2ca20b72d9deb700250430d36714cfba995d16d4ecf2d7317ad7cec870fb335f01335ce75d39c0f0cecc33e658485732d18681b753ee4ec01df14284d619ae5329c5ddb662fdd987979601a37a53a67e273da3224339f047d62392bf868052c7fbbc95885f1e69991bc31c344c2d9cf00ffdf9f4b573abe0420317e91bf46
+TAG: 8f06477a7f7b7f79f241d40d7c0c9616732e3852
+
+# DIGEST: c72d214b42ed66ae0822fa9f3bda306c7d58cf80
+KEY: 16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c
+NONCE: 9c5f3aacefe61b184ad2463939ed518c
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae0
+AD: 2116417dae0cef457b9e5e
+CT: 16de4a070472c578ae448e3c3303ca7bb0910961995193c23d7e6a8ab32b6b6bb84202369705d43962903b0d7f1b2fe7d963e558fad39f38f4d4a017701710badae74235ba0b3b6f8c846115fa8f36cbbd6b41efe933d51c4f3d7e89924aa6848947d8c57f6c950eae443025f614302863e8415312e8a727840126f37b299a26d28c2c7686160c1ee27e3bbde0c4346f050f9c906257d31663f6b2ef
+TAG: bd25d25882abe288e646d725e9313052a86cff31
+
+# DIGEST: 9faaa58dd34a192550c3519f8c0aeb2ff48dd388
+KEY: 5607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacef
+NONCE: e61b184ad2463939ed518ce97c3fdd29
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae
+AD: 0cef457b9e5e16dcc5b6f2
+CT: a6fda8e3bc0c1a2cc69ac359d338159b984f31ed1e1f8747bcd7ba473c3d0aa7f0f577d8115e74bc71e077ad5c320f3250a0fd21ff531e09f746f39377e4ad02f34843b5467ed61c839ca899e2b0cfc5e37c5889b934c4ddf9b862ee4f5c9bfa0db31dcfe6622e81a7caeb65a96d5059d6b58f9f440ef473be63192420a6f75372c97af21d679e17165696d8825223db470b1eaf65326fd8029fd5ce582f8de285e68a7fc4c5167ba1a9b2ad
+TAG: c8fdf133a5b50b8cc9cff5f76364d28419f23809
+
+# DIGEST: dd5e6be3644dcc888cc50c0b2ad0d55eb0407fdc
+KEY: 3fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2
+NONCE: 463939ed518ce97c3fdd293d72afc09f
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e
+AD: 5e16dcc5b6f25607f00d03
+CT: 61239a68ef268c69afa1f73aec32aceae19915a59fb977f948fce8352f16cd782fee60f9fdcf7b98357b7220a727081344285deb0a4f866e12a9c77791b5cf506fe35fe1d153e928138952c64a4091fe9d337d7b760960261476e338cb18c0c057ca756aafbf62f2c38e5a5faa398e5c5a043f33fc7ca61a633e78b22c007fb7ed84d873e285fdd551d8eb16f1db1b337f94b0b7aa231d6c2f0f6cb4c10ea84061e157f0973c46f6e72a28bc
+TAG: 2adc9f39ce32a6940d20cc7f14ed61b753a698c7
+
+# DIGEST: 1b8b627e1020d71318511d4c2078eed315ee0b04
+KEY: 4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed51
+NONCE: 8ce97c3fdd293d72afc09ffdd4f41963
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6
+AD: f25607f00d033fb95fb09e
+CT: cca8cf31431023c84ea568ff31658dade25623d4454eb7eed13678718ed549a081c75e3e0b7266e8240f6d446caa99560b87a37e3644e00a3d37d435b1f41e8c511f1e24c6b96413b3ae74acad54ff315075a86687264ef232aa20f37cdde1ffa50777a3607a690a0421189135f4821692ff1d37fb5f0422d680fa1cf31439a4c730e49aa1bf86d3867c97f82b7441b7c28cbb9fc7783c80771af42afcd9ebcb65c1b425b2a71387b0c303a6
+TAG: 1d8f007af408c027b36f3fff31371e3cf3602269
+
+# DIGEST: b7370237d402dbf76f1a431cdfbb37f41ef2ad4e
+KEY: 780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd
+NONCE: 293d72afc09ffdd4f41963249cd299b9
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d
+AD: 033fb95fb09e4d00d6172e
+CT: 59408639c245d3fe4c2a12537254fc2eb3b89e79c7354e02e74935b1102a81cf02b86865abaef81adb2db4f336fbe6aa4c97957469031cafdaba403098a9dbb819d196393d6e8f0f98eeb23ae9f796ceca48eba87742a02ff361bef722abbe4db873ada8f30e88fc1ddce192dd169fee88064833167bb6f94c1888b417371a08e5394904214836843ba20bd3368039b34ae3d1d69c50c4f95d8fe4969771ab36c4f48d4731406121c7bc68e94986a085469aef7c0b46952a8b412efa
+TAG: 83bd26345c3a7c70d7bd313acddbf5bccec83512
+
+# DIGEST: 0ad0e709e40cb2fd662020d420d97ae50a14adc2
+KEY: 433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc0
+NONCE: 9ffdd4f41963249cd299b92e55ca24d8
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb0
+AD: 9e4d00d6172e780ab8b700
+CT: 0634d0090fc059f4d83c4ac6b479943d77f183d521b6560fd2776bdb85f29a20ac02b5561ffa60cbeb55ab8ebfad9586696f46a497486e20719a4c1623a4bf025cd3dfdb89d9bef336804c23ef29377aeb5265ebf72e71866636d90e05bcde9e2eb4ea7fe2483e93dfb81cede20053ab7983024c39e7988a1f246a4823191d864c4935b21694a6b4d38339ab2b98569b2a457b86c0cead36a17995a7b6fccffa1dfd81e4ee355157b52961dba19f5a9b3c6d17496c6b2da15d262e21
+TAG: 70b1ec053b80c6fc9d64d9efbb5083723dd9fba8
+
+# DIGEST: 5f9967a8fba7184dd97dc7d5da22ea785e0ffbbf
+KEY: 1c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f419
+NONCE: 63249cd299b92e55ca24d8c078c49f78
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d617
+AD: 2e780ab8b700433a957a74
+CT: 1700287ee100f35488f3a37e8fc87e70f30d219b6435d0f386aaf38b9e38fa6ce677045559c806f1f7b6c73aca9f89ad3766cb1a55acce81ad15a7aef46d3c58051be7d673c42b8b3f2384444b27179cccd85d4dda0a96d711bcea982c30a38875a35554dfbd2d7572c45ed621dce8b56c885604b0744f6e6fab919a008c57480438198f6e0e5971b981dfd3cc34f9379a4eafbcd402f45804d4950c71ccc7ea1ab93fb9605f7fa0925ecb3121c02a889f125825bc0f86f76b377890
+TAG: bf4db639a8685ec081c4fc772db93766a3519452
+
+# DIGEST: b5aedaae523d9d396ad1d9bb175bf4c7c0b03eb5
+KEY: 021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299
+NONCE: b92e55ca24d8c078c49f78c7e713710a
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b7
+AD: 00433a957a741c9eb80f2b
+CT: e45b2bf546a38abd03aa17933c50624f8fc36af8b541757d26cec56f3a9d578aff93663bd2240a28377ae1c182eaafb63197721de1aef7934b9f394f91137bbd7cbf5e7fb2f5c15ae86d508079fa46055820e9fc43eec6e5c5274aea27307139a2a7ce83d2d15b438d0cffca73277a7c4f5906662b7a5c1b4afca2a66d1766ecda6eb94bc07153ec322d624900a626317d9faf2bad47d97ddac27d305811f29ccc96a206a87d18ed24f806c8b088fd2c9ba8a9f42221166c9664d5b06d5211df205e58f2289aea30b85102e9
+TAG: c14771c0c1bdbb9e7d74567963e06b76e7417ccf
+
+# DIGEST: 52bf12f5594b0cdefcf977c07626e8748cec5425
+KEY: 9da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24
+NONCE: d8c078c49f78c7e713710a025cb8b9d7
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a
+AD: 741c9eb80f2b021b144476
+CT: d9d6339ecdef69eac635f0149f8702bcbd815ebb9687b510581be5dc32aa8733bef01a4fa3254e6318858ace9b89d0ea5f7c9838922796dab27701908431d7c80ab7084cef14ee53f1953e7aec43416c2f569558429cfcf1b5de4a9a1102024fb7b1e8e03158ae85616773b5f32b17701f4d9bb1895b87cd2d52f66d3d230dfdb0b057e1235c314a3829679b69af629890fa40afef0eee6387db68fabe2d83cd0ce16d892c4b883d06437ce7a80d5934084db6d10a9e0f84ae335b3ee9839896520321b86f9e82a3e2bf4d7c
+TAG: 3ad60aaac815cc77d8dadeae51793e4e2ccda92c
+
+# DIGEST: 900a1792a921b6a253c47013c9eaf01fc5c880c2
+KEY: 0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f
+NONCE: 78c7e713710a025cb8b9d71d2989ab33
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f
+AD: 2b021b1444769da00fcfab
+CT: 07e235433bf3603cdd0ee3553690ca664a457f7d1a5ee2d38db92583c517c909d33d417ffb76c6150c8b364fba7970eebb346765fefe6da1f0bf9fbb2a3ecf14fdf50c24f1ec316a408f6aebfa7f74098a887ded5c433294ff2cdeb987586d437c6abfa5b7b9b82bb85b88edee401f4e6ef72c9b10f2078c5d2a62f64b475c805ae5571123739877e98d4aa2c3a1a50de0add4802ea931136b2dd4c466fd49f7ac2518d472aeb68d80031aafe6df887b0fddf4cb2774603edb6776d65cd71235c1a6205dcabdcf980ac98244
+TAG: 6fb9e3e72ecd491bd5e91f519be70ac102a58f14
+
+# DIGEST: 88d7ec35d88ff113703702955e931e802fb0d8b8
+KEY: 060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e71371
+NONCE: 0a025cb8b9d71d2989ab33e978c4451e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444
+AD: 769da00fcfab0f5f93b511
+CT: 11fad6dcca311530333337acfd187547325442755679f1a91edc21a46773084a17f3d1dc85e2db913133847e2f9cbf257d81c1b74860014d020b0c8d6bda7551a752287899d555dae082983f5e23319cf01bcc904e32d448fd049615cb5422e8ad667f9eb2d80c9cca9d28e22a0f4c67344e16eb68a38c4108f0843a8e7b3aec5848394d858910f9075a5772a435183dacbe0a7d63bf2216450cb5623b226a9d8ee088cb8613427a7bdf6ab543e54e7e9f84cdbb788e38d6322381184026188a23fb31bc486ef029d371fcd49198ccc62cea48e937052c96f140736a
+TAG: e97ffad80eefa8b65807da8334869b4ff5a3ca9d
+
+# DIGEST: 8d8493b55d9b74892e77d3b730588c087ca9b1e8
+KEY: acefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9
+NONCE: d71d2989ab33e978c4451e3be585a29a
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcf
+AD: ab0f5f93b511060c9c5f3a
+CT: 6094755624849041a40890612831d14eac35e35583e377c7b5c9be17d26cfe8d3bbe9a868fb43f976db00db7ee82f434c745ed6040a2aaecb66c769dd37784886bbbc893880969e58645f35d7cc76ba362a4bd6d4b763bec9d8ae452a825767598473fe8ac556a2e547df30ee3f82a08427c50e228527fa4585e773f370dff0cd950160d7a03176469da4f48b86a14c58d80664f1b9ec2ffab19da19b6cbd5e03692bca9879ed620417e73aa0991171f92d8c1845b09b59c7a74801729fe409ec60075b56ac14c8444631bf2b24ce7d5111ab514a161776105f2c772
+TAG: b8fc8c0bafdee27cf54f3cde1db77b71f8028e56
+
+# DIGEST: 4cd92ac16a807d2ff180df75c47d848749c7ef46
+KEY: 4ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab
+NONCE: 33e978c4451e3be585a29a2af12feef7
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b5
+AD: 11060c9c5f3aacefe61b18
+CT: e2e6df43b4151995a2fbaba9cd974285d815e05dc641f562a88af180e5f1d3ab6ef8e7326866d039c8225f13d436082b026c787e2a0becb2bdae522674bb3f723f4a4a9cbd87cdbea9e66bef5a1d2d98dc61f2a039f0fedeec4cd31ab179d23f03661d00df3d2d91213b086aca1079d1c545604ceb1e9122b5e738bf1bc264c7c6863434c0baf604b5038dc97d2fb95701908553c68d30ac1a96a14d507a4ccf1c8fe86d3e584f926475a5c8f849327dc55ddae4a77ed01dcc45d7c25a5825d4a9cd1e98982b04ba58373a5c4378c112102b7696515f969f195ea5fe
+TAG: 4a5e942b980894262797ac0e7d3d629c1fe6f43c
+
+# DIGEST: 64ee218c0c96ca8e2d2e50cd809d61ee109baca6
+KEY: ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c445
+NONCE: 1e3be585a29a2af12feef71e1063b0b4
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f
+AD: 3aacefe61b184ad2463939
+CT: af965562788e82423000adc0baf6cd49b082e5c12923b53927ab1dafcdd4c9581c73cd339918647bf718923fe669df07e55acb3206e9ae3b7cf1a2cfd7eb98d36eedba65227f02ce86d223d6348ebabf31dcd990ffe91ff1011f3ed91e1e41aa5f6d127c7607160279e035de9aa36cfea0266a1b9a958edd736568bfd52b62ec7bf034439cbe41653c2ba5321d599a40f6230c2fbb594a7dadfbed46e23834ac938d6344407219685c7e666bd135ab30c3b1c71ccb73d12dc313bfba75514106beb10b740800e32c52557eddfd4a1883e64a5909aa1bd2a0e090c44bba7ad8065b3ffd7d3530ed9ed841ee57
+TAG: d1f11016e5b036a76568e145bd2f35f96bd46084
+
+# DIGEST: eef8eae201ae4e5af32ee74bc724e13ae5ed3978
+KEY: 3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a2
+NONCE: 9a2af12feef71e1063b0b4e6e8992003
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b
+AD: 184ad2463939ed518ce97c
+CT: 7ee4c521cf1d5807fa3e5841a5af354731ede548f8624427441475b9c1263d609d88fc53bddabee16983298d5cd7cf304d6c899cb219c842a608e30b5e6119b9ab93fcea65a9620e8bc33be5cc4ea04877eb4605472db6f2b87484991c3cfabb750f7ae7d903f6971f337eeab06fe66183d1253d63d3b3a2c1b5505f307653393dcb62101a401ed3653fe40b551af91cf90948097e4c0c445ca5cb77650e69a1aca5eef48228c37c15f6ecb562d01eda955279dfc07d681caca072257a969be5b9be811035ceeb32fcbe9a1bcbe732cb09b52c92bd467b97dc2ad08beaa009393ef3b2b7cdc226b6e5d39977
+TAG: 983c088708ec1e7b6d3efd09e83de01ec62e7711
+
+# DIGEST: 2fe67a81b41b094a708ae515e28bcbde3bed724c
+KEY: afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12fee
+NONCE: f71e1063b0b4e6e899200304bd350813
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad24639
+AD: 39ed518ce97c3fdd293d72
+CT: 1e9eda4b2015b166f708941dc7de6057cfe4fa04cf1d98a01de87b35a4950f763f58edf8ffcba9a9fb1091fc8cc2d3bde47ee32d8b41e020dfedf2a10c2c99ae9afbc65875b22ae18369cd8253b4de489d859d3066506588a3fbafe2c77454ab71cc8b7f94c8e906121276b57e22391c55de57db0e36c4b3d9d098f872c7052b72b519d7db739852b68f7c00c86b849e80fef5da6cd39b1f2a255d73cf1ea204f3a7ba3000d1ed37d43e810e19b369b4a4beaa2b22efc7dcf3b63b3d744f1b58a23c21beb691eabce5f7f5e995ad89e5fb4e5c41936365905fd4811edd8c5afaff6acdf11ebbc65d5cba608a
+TAG: bcce2f776c27b0cb639941762719bde29d5e627b
+
+# DIGEST: 33d10d6cb5dc80751d0f8e370925d7c86cda331c
+KEY: f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0
+NONCE: b4e6e899200304bd3508132a027d1ff4
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce9
+AD: 7c3fdd293d72afc09ffdd4
+CT: f1f61cfa95db64f8120073bb3ed7f0adab10a000930a0bd61e245f653e78343baf543424748d98fe2f6eecfa6bd4a3fbdcbe7b5d8f610de7e893ac00f22ff8eb9d22fe778196da6491bc4b1933b6b6f8684fb1721fe0f51e4b495c8a6a7554cc08a6f17974594af4f0b93c9038bcff1d24a63f353816760f787a95755ef4f0212ed5c984cd4b42c2e580228b5aa186673136a23f81780a620bdd0564131d333ca6bb4752b6469e076c1dc385d4620f3218b9b10287be69e0ab2d09dcac916ef3a8607a0583195943111ebe90090eb3b990bdc156fab7f6c9488b93c346bf9db81234487616f429ebc06caff1
+TAG: 7eec03b5c9b14a8411dd628fc61487869113428b
+
+# DIGEST: a29f128842a48debb60699ae0df0da9a9b5e5dad
+KEY: d299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e89920
+NONCE: 0304bd3508132a027d1ff4c047b3ef4f
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d
+AD: 72afc09ffdd4f41963249c
+CT: dbb201b0cef7005084819a642c3e1fc54cf70b4c510b96689f988b598942a153756c67519f0174477a233da3b1323981cce6c65216493ea82c149c909d1cb64b6151239e88cf25cb540037d2459bb812425a7514aa56f03741ade539fe2f92c7b58168d963aa5a558db8403e67eb1b81f63d667fb44903b1cc2749eb387d08bb50982f85afb55c3e4ad5d11cb10355aa534fd0ff35c9bae1cbfbf25b7e28f2f91d201cc462e02e6b9bd4d9ebb8fbf84543f2ae5aa140ef7c030a95f320bc0a78189f6f3c37c1bb28c443793ed9faae5b130ad311338136b47a273dac03d17b7d054ac5ff4700d62f6f883b0f0377bd34dd75aeb27cd961ca249d1f50
+TAG: be8a2bd269ee80af4a8022b486cf5ac0d4a62ad2
+
+# DIGEST: b5048d1efa7564966b6cf1579cfb4ad8e9460660
+KEY: ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508
+NONCE: 132a027d1ff4c047b3ef4f57a74706de
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffd
+AD: d4f41963249cd299b92e55
+CT: 201dfc8d35187b836614651daf466fc1cefa69a36653dbe231bbb727f192645a2ad5ed66274a99dc78d749ef0f15aff2ad75758f8604d4b396e5054ad41874d9e97c5dfe427f1e54aa3643b21b4af2cd9afd0894587ada0eab10bad12d94eeec00457ba93c32741b6b465c5c68f4f06df5e004d22b9a51477fc1a515b8d29ebb5f924b60e10f839dc2467fe2fa134960c4e65ab1883a83c7ba74bcb648c961fc4204b3c1a56c58d4c62b9487b975dd656f5aaa9bc114aa1738874faf5cfb04fc74469e17e5a378595b00483836ccaa73171581a860d90bcab101ff0dcaa94120f1da585fb78141e9bdae90cf75b5387c2bec2b478eb0b7c328e979e9
+TAG: 45eabefd3e8b18f2471050fc363e0cb42a8d8ad4
+
+# DIGEST: b6e68f5f0dfd8ceab56ebb657728c9bc5129fdf4
+KEY: c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1f
+NONCE: f4c047b3ef4f57a74706de4b381c692e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f4196324
+AD: 9cd299b92e55ca24d8c078
+CT: a3d7370aa37af8c9f088e3fa794a6bb8d2afcebba68010a40253208882123922be16fc8911d95e169f144603c0b5435bed90f30502e6645b62ae6a66dfed3ac2a03271c954c511fc803ea2d7c862d3b9770e22656d91f1003e971039bd0adc9dc462e8aa2d8061998c7efa989e5ea8c43408ab8431f28b0990dde190a7d30c99cf305d95886c27a0512745f7b3c6e50561b6ffddd638a1065b1f2cfc8282382339ad18fa1a9aa9e67a9e30f179a7d5bf9e88afd9d1e1f8eb3de79fed1498428fae303cdce80d22d42e45f934b78a2da5fec0c7baaa5ca26dd541ab69c557db6f3df7588ee2b7ef36f8d0f37bd4dc973e9258a181082fc4c7052acef5
+TAG: 8875a82de3400e2a5a825e0921e40c16166a7b8d
+
+# DIGEST: 853bc7b9fbd640cc0654fa5533ae302e398bab35
+KEY: 13710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef
+NONCE: 4f57a74706de4b381c692ef164101b89
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e
+AD: 55ca24d8c078c49f78c7e7
+CT: 5b324c466f073e7dfe295ffb7c59353a83298e3610488ca81be17db495e1b448594cd2320405c976988b594e21b38f840f5138665ae027fa544f3caf02f3d0b71d81c8778667019396ade470e5176bd7edb64f8a099e557405e3feaf2ef76dd9a312bc75fcab8b5759440e157c3323f305a3de9eb4b18bd3c9eaaae634607d6741811f6b3e422b033bf03d9fd40f5ca08f715c7d62ff18cd592587a5c2fccf131f605d74b38fe707ee006d22dfc82c425e84104c43811de2acbaef2653375c00514e5fd6e28fc9c5a8baed280e87e315709cecb8b30a83687572f30996bf75f6355d9013a21aca70f655bc97dddc6393dd17a64761e7e0813501402edcee7ba39f7857a38f47658991617203
+TAG: adda70005a81731792f3f2071d10d5fe032f75fe
+
+# DIGEST: 286a92c480192206a2153df1b6d0eb26e6507da3
+KEY: b8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706
+NONCE: de4b381c692ef164101b89b476f72b27
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c0
+AD: 78c49f78c7e713710a025c
+CT: 5b6753a8f7bcfc2b7d50abf211a52e3538ba28d09a7b3c21892abc08784ef72ca70880881251825379c461cc0f0c6bdcaa9a5bb50362bd77b9eee6ace3bba1d2898152c50c5d257913bf8e84f40f6cf155f6c6fa0943a891b87927035542191cf042dc9718e33c8319e9842c1f0458e2a41078ce3274721b8ac0c4d3f5968ce296906add8df796ea335ae33671d4af2197187bd7e9625043431731d3b0665a6106e6a0b0f68f1eaf53c829d8a7fefe76bd1e6a2c79796cb35dad232ea7d4922ba51e411c27e0294ce6cff050998404ba41194c545dd6302859172303baf22ea316a5c620632f09adf3e7d6869f9539cb26eddeb7455c6c180023ebaa67663e8370a9bf871d613e4b490960ab
+TAG: 0aebbbc0aefa10421ec7a6aced5ced076c4029aa
+
+# DIGEST: c2acb0c126af5282abe14058066631fd0c658571
+KEY: 89ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c69
+NONCE: 2ef164101b89b476f72b27f06f520c92
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7
+AD: e713710a025cb8b9d71d29
+CT: 17bfa592a3eb59bf20a51235012db934d58582964e94ea19b0b751a68c0176624b5d3947c2980b252926ff5330b31f11e1d900c67923fa466e7d3cc618d330248b7aa82836ca492b344d87ddaa93b5c9f77d3bceb13881c49217f9de2c40a5a9c63dbc7adcb0f3e814bcf4ebc09c29824dd93a03177221896ffa89f4f58ed476590baf335eb5f9acffd84f7d7163982ecee9922eed48a64c537be384091f3c9879c02e175a7761cf1908bdcc7c3297a2b489a005e55c6a325431e1d37b3743518a82634df26f10721d1d979e12015e3efdb1dee1a03cae7b0dab97d5e3b23d25ce49581f9a2e5b1147c5767baff32668e28f3c8ca1f4ce72ab626086a682a4457f46fd9d842680baaebeb1e5
+TAG: d9417734d0993739b038cf04ffae40c9b088296f
+
+# DIGEST: 500e5f2a56bfafb2d93e26224c9c2df562589f23
+KEY: c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b
+NONCE: 89b476f72b27f06f520c9267cf71408a
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a02
+AD: 5cb8b9d71d2989ab33e978
+CT: 9ec67887b8555ce427fcd9b07aa9b78a64f4f602dede7eabcfb2e7204f8afeff070c10fe7065c6912e93deba117852cf5472c5a2aad1439b6f3911bfe2709b631dff0226fdc4c21b9955548d1c01db24c1cbd28b69d05bcb38a31ee04748b1d9e00b232e2929f5f6b6a7b7c85c924f53fbd9fe51124413178b813c34fba81cb34b54dc692379203ce94ff4d8829995791011cef817735bd698fe3818646dc77ee3e6eafcd08eae893a93d7702f4c437baad48d3585d25d293cea23c168ae67ae55e3ec32f6f775ab54c816ef0da9ed9d0ba0e947a6e7b34fa733cbca7520593c5f271083a5fa9d6e53182f21b8bdc920b6d831d02ab594177826d46058cebd21a6bfa8896b6ea7f7b9eee48cc47b8f82e82f4d1064d8dd0f8cf2e730
+TAG: bb566ff02c84955fd7ee1cc474b02c8786e8a750
+
+# DIGEST: cfa6a42a2cc0ddf1c7b20031c95e331696bb9ece
+KEY: 85a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b
+NONCE: 27f06f520c9267cf71408a41729bacb5
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d
+AD: 2989ab33e978c4451e3be5
+CT: 668c1a9dd22292157afaa8c6f38d5d4531ebc8c2d4ab39e4f1652041f503c135ac6765ff18f34452c641424ba17e4411f5bea80e256fe6e938a7b6a72f5c096d70a3f6849158b5c6233001b5512515b64ea1279fcbc40c5fdc9699acd75eb7c7e229454364ffb27a2cfb7199440fccf8cf62ad5d0cf267634615c487ee6512353377862720a12568beffeac495e50f76c1b6d8505151dff66506094827c1d695d2f8b56cd1cac01e01f41616c68cc1afcfbbbcd48c340bed083194389a746da3e50230868107de9defd2ee0c05e1f983ff00769f90a4912f971eadeb69a78ee3379e5ba6921b31f38a419b590e838f2a7fa6c5411f268c8b7e1326fec2d0ac7c4b5f4b236aec8e64bc1963555ebdb0abe3ce092fa1af42021509fc14
+TAG: ef8fa8130ca204d56364242c3e91e27017cb4de8
+
+# DIGEST: 2d1b27948de83e32a0fa5be7040d896824ac1fe9
+KEY: 2feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c
+NONCE: 9267cf71408a41729bacb5877e72cdfc
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e9
+AD: 78c4451e3be585a29a2af1
+CT: cb8dbf2719d8db2dc0af1209a5c6b93d561a4882e78451a69466db8bcef8fad8c92e2a20a9063fd2c2c344d98446ccfd6ab0cc62d0007ffe979cfadbec818c8762418fe66a68cf913b6249b34337ca86403e7d42526827a699a8ef6c1dacc7b147a74c53caf5f7bcfd3a380f891c820d7e3173b892b8c56d961dcac9d9870a22a23b727f5e2eefa7a7135efaf3b9a4d6e2b1b91e9b7cc2e91d1d85b16d16515bab9ac09fc4ea93e52d25dc9464a7d2fa940e00f049b083846db5316a6e4a00d7434abe037430bff82406c918bc8106ff9805072676a078d532a94a98a0934531f6c3a959597236705d29ee308dd6a335969030a6df0dee568f0f24d66797a44a53beb03ab6c44f56e02419ff338543ae3d988a0ad55eae2f7a6998f9
+TAG: 068601ecdaff981100567f0b01db1ab86878c774
+
+# DIGEST: d35ac8b9ece76d43f1497ac8681c5077398bf2ac
+KEY: 63b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf7140
+NONCE: 8a41729bacb5877e72cdfcfa76aed067
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3b
+AD: e585a29a2af12feef71e10
+CT: 5e90767a79addcaab93fa583fb7fc9ceffc9afb0eab0a6f19943899a00c0f7bef8b84af3fe46527fd957e6e8edc7c45c7a22836e76d211e00f99eb9335306904ac452eb60fa59c7e05c2479288206103da8fd4f42cc2b6172ae43b3c9714fc068209855bad8fdb91c52ed209dfc7c6d68903ea06b363c24b5c18b1cb9171083dec402b7633ab13147dc8281453789d0fcce00979c9508a409e59449c69dc2b6c806d4cef36857dce1f135c44b83fe16e70ae8ad6a8a1f9ce0f29b631b483583efe097bb35035d6a0092157a298917a2b5e78d19e3cf1c9ec937e987a06d927621affc6228b1e2e151c7a1fe53fec3789a93f54b32f50ae962f99d612244903e808c31bce799e30c59584061c87cd9f88206e47a58293f02e235f5f3626c36f7b5c921d5159a545d8def2f9b8
+TAG: 7845e501529bd28ae60e0fe514b361856bfdb41f
+
+# DIGEST: a3b33fa67f5c471a60a63dea915333550bf3af04
+KEY: 99200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bac
+NONCE: b5877e72cdfcfa76aed06707a07c3dab
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2a
+AD: f12feef71e1063b0b4e6e8
+CT: b513e57bb4723eaa7598d5861312f1992a33ec9459be6da060a2440753c617f335311bd6c12fdc2a4f8ae0ed4c45a0ccd2567da4fe963b28fb4955beff3a95cc61e73d81f0e5e5594d86d2f82cb3067180eba126107efba2d82d1440b29a6b7a8e0d86041d6454916f6eb4b8076f3a822bd6b4ed5c070858dd49e386d8fea517c4b1bd54c34638a52de8499f7faf6c4086c2087dd6764bb402ffbd4a9b24c0b52f6a5c6efa43abcb268308a95942df217de92dfce2bb04a076e69daef23bf6e8b32f6f7f037008c344b560c48058a879e06f100d8c047182fe8738fa52691134d015d4e2fb636aa8a9f0d8eac688bb9c245f0b72e9b9f0bd9d3a027742e61c47f1b041789223e83bda7a0fb324d9a50c6c11acbce94a6f4068f5b7bf096eaf90fc99d2c9a12de93b47d26b7b
+TAG: ab3bf9c34632bea89d15770d39da5b1b8cc14090
+
+# DIGEST: fc45f684acf19a1dcbf767f671396e793430d7fc
+KEY: 3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cd
+NONCE: fcfa76aed06707a07c3dab699719fe88
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e
+AD: 1063b0b4e6e899200304bd
+CT: 2994b3f3dc13a23bfc3f05641fabb045df724e5b49f70d92475f6c6f52ef91c7ae49efa48909f1f23bead9b64b6210eae1b063bfb022cf600a6f8b9730fb176e8949143d8a1e031c5f6f67c3d5859453ea581f5a3a63b319c4790cdd7a95b2f977c6a8038cbebba57a5de33beca201a1f8e6f5e726237749bd83743c15c8c353ab1b66ef26ad7556c4e61685868b01dd2004ce7805041ee0c14b4ec15fbababceecc2614ecd07ced80e73a511c4c3e6aa2e6bc544544d9a10111a8cf6e3f07bbc2a416a4dfe0d6a1b9434ac1bfb5e6d0e835a6ed11b84085a0059cd06b4228a120ea877f4d11163c256eb17c81d363f4fac4f0b9dca0ac76a576af94afc6d4b153fc35ed6e2533ae0abe5f2f2a760862026c38dba487bed1ce960e7f9922bb8a207a71b1660354ff649c56fe
+TAG: 3e54ebd4ea6d8d1571b9040b24e36542cb642586
+
+# DIGEST: bea3f11679bacd98ddd996236dd603d319aafc6a
+KEY: 7d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed0
+NONCE: 6707a07c3dab699719fe882eee2fee55
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6
+AD: e899200304bd3508132a02
+CT: 1aa80c050cd84224fe254cd0439bbb498357b27ae04433b191299e2edb7978c48e7e792d7329a7f1145ee98b64bb71817d9d359cc2dff64f32c3b2b6c29a27f0a8e58711f5ca3281a974c18b805fd40e690f6b78d8614eff3315e9b551f4b56eea59ccbe499dfe3fd295ab1324803c8a9439afad859fab31e9c4eb3b21b65f00a4be1079fd8ac05c6b39d0fa40344d65ae0d2ce7c1e323f49b44f2cc463b4b665918a292f37400fc5ce08085859d5baac0dbfa0d9dd6441cd53ba945639e30b3d3256b31fc8cfaa93bff9d01d4787665f0a8c523a1ebba2aa1634be6b0201fca3ebccc34f82568e405d79191af02867640181a6236290e856c308ee4bc27e71c192beeba9fa9af92db8b62f9f0fe06c6b7350b8b76470b76e5108207c254980a42002c6cf3229a80b76db23871486d4eb1a667975d8ae3e43cc6ce3b
+TAG: b6a3881d8f65719785a1f22be059f0288373a3c5
+
+# DIGEST: b0ccc9b5ae13a7f8a01100af61a34be7ef6ccf6d
+KEY: b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3d
+NONCE: ab699719fe882eee2fee55ed8b11534c
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304
+AD: bd3508132a027d1ff4c047
+CT: 69a1ce037f1c63441c1fde91a64e42f6ccfc14cac57b9b2e03500c54e33983b396adbd280bd43c3817658957b711b0debf39f8227d3ff940c4aa4e8c83f1176d36ecbfd07693632d8fda21b725f1cf494f61db8ba3f061dbea75d520e86d86ece1c2315e5e8113ba2c35466503a7e934a15af5fe42f25b7dd65d8b6aed1599798a93e1edd4ebbd1ba54d61694e6aa1007b79d6e1a96c89bd92953db0b6182adbc8434ec97d9d182013cea371a823664b2b1014b077a5f9d06bd78a4de3d605e9e76f2197b81abc37392f4a2397d95c3f7f41dd4d45937764fcb21175472053245ab74b02a891d0c3d5a3901c6f5b6e9488437ce247d20c1eccbca08a2cc6c244c3750b38cb63dcffb7110762cc13478aa05380b1ecd0ed52b4239887bf2d29006d30b03a81047f548052ce7d750b576816951d6b493ed900ada74fb7
+TAG: e2e8ee15e405ee4524a56ea0353be028ab76e314
+
+# DIGEST: e2b953c833076a52442a7afab46150176c47b730
+KEY: 4706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe
+NONCE: 882eee2fee55ed8b11534c870dc695b8
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a
+AD: 027d1ff4c047b3ef4f57a7
+CT: 3f6560d1f67ff9c0bfa2862bdc10d3453bc552e0827707568d873ce98b2afd207392769903ee020eeaa590224bd1acb39312c1ec91abda16f5ab085b2bb9fa0d17385435232d1956dc5b6956af441ce23e7515ad9e433f0508c43bbed5a1911bb0f8f9f80134fe9df2fc402b3ab0310848b26579bd31f4b499ff26afa8e9808760dbe7347d16325d0a2b4da30f8c92e098b2ac0ccd3e11ec1cb85bf54aa6a48069d913eaac9da5f7e4a36fb05818c0a855050a17604d3550d8d41d50e27439cf485e2863a5dee94b2fa90b089b9d77bc08ba9937c57f455113f5fb34a161b831291ee6036da4e4c53682884ef1e95e07fce8e9437aca523824275f27ff00485fba9965f9163e5231aa98989402eee3b9ef4358876bd49a14bed20c51091666833cbe124897de0077d175140fafc97d7187790c808486534204395d04
+TAG: 752769f5175e1c7b79a4c13ea15960f31b2ca063
+
+# DIGEST: 8e84935ed1bb79dd38ae38924952e1105101533b
+KEY: 1c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee
+NONCE: 55ed8b11534c870dc695b814bdf1a87b
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c0
+AD: 47b3ef4f57a74706de4b38
+CT: 40402e4ddc2cdb109bd50353f857056355e117f96e0c3fdfd9efd316cddda82f346e2089a841518db9bdccfdacf58477242b53ac2bf04e27be7d619a12ec0ac68381c49f19ea8c076fa7568335b59e6c67e314b7e3a10f524c7b4db0c73b556457ddf5c725f7294543ed585b0198e6086af11d0d83fc4e06d968465e63bc726ab3cec1ddd3918036b89aedd03e538677236696bc86d20e688e5b49b6b49d6dd8999405d29023db71d0c3b993a3c35708d35767081139a16f8e9ab01789fac4dedc5439e49f5d2f774908a834732b194ae9a8c7a0ed1e068014e4f9b6c0905a0446eacdaafa662dde1f2f1cea2bfc9e02d4b349116d6b171985c5650742c0efb73702a7a7c95f7b235feceaf11c315e48e1988450ec1d20933257ce8ed8cc0a5649956a4a9c8d888d5b47024cfb3f44f5cd4689a8d89928f4219c7eaf
+TAG: a5d70a49d544e1eb9c5ddc48f570c8105431fb11
+
+# DIGEST: 99ec6b669dbedbe99548117f37189e669fc5d8a2
+KEY: 101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b1153
+NONCE: 4c870dc695b814bdf1a87bb1052c6755
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57
+AD: a74706de4b381c692ef164
+CT: 82edfb0827b4b520ebd3ae16420b67d9ec946f3a2e78392ad480c67b0beee6128d4fea93e0f3b4d88d54a9c78e6cbcc24e4276715f68f57a8efa119459ffb661c0ff938673fe64ba1e727264d79225591454329ad9dd5c415d2bfbb0d1719a322f511bb3363ef9f750aa912b2516495f5d59205b93a253dd750379b394c309cdf5c9497ad595adbb45bcb548fba27768ddef32add986aeff87fa56c703f93330991678b9fedf033580cdf33ae8e8a2c5ed43c2be82e64c4995f83c39dde700a6bb0b31a7afd2fd14f426b05e7f835c23fafc2f31d2b1cfa0d9326c9486b587e686432c910fe4ce4a85306e66a1b8fe3051866297bfae1c81d1679833cd92b7f592870a01c0efbb059c8d77becfed21f1a922458ddc2263ff452d67deb7a4968fbd6591a14cf3636441a3187c3beeef11550dcfcee08d476480a4751f1a176a85318ad23260371d3a122c1d61
+TAG: 4a3d4afa61fa8bfed2e59531a20a808b890cd704
+
+# DIGEST: b55f018cb06f74f0a9f76e65a23c1744ce7535e0
+KEY: f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695
+NONCE: b814bdf1a87bb1052c6755a7a116bfc9
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b
+AD: 381c692ef164101b89b476
+CT: ff6f54385718a06bdf33dc752a0e8f4c04fcb8b7e1260cf4d20a5f30d00e9a705f742ae3f35a3502eb34c2ed97174e2c9f99d7c0c09c3831fa1622824183e25de78cbcea451b781b125511edc39b5b64462b22d2784de4300582a17d682c114e7618aeec5ccb06f9209e4713cdf5e4665edac182c1d5b6f9862a52f73c42ec444f7078a6a8ec40df331a7855bc88e39df2bdacb0f7a13d5d3c4f2ed40fb527040ab8d67b18c2a7debedb5ed3c25050ca00667a0f3130d77caefb61661eaaf35b7799d04959c17c1c2dd4f2d726e988121c75057d1c51ce73f1303f615b3d6c5daa92dc135cdda0cbf4361a5b82682897facf1e5b12dba96ef9918b8f0be60317c27224d0f3a446adc64ec9a6a10e0830677354c71601f8410453caa1d4a0627e065373b763dea62fd77c58db4f56d8ac17d1671c6c67d325e43b41b73eb1ab22034567ac9388e16c84699033
+TAG: dde423f11983c02baf3030999fb735453705d7e6
+
+# DIGEST: ac3202e483c67fbcdd751950e1497feb3ebacf52
+KEY: 520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a8
+NONCE: 7bb1052c6755a7a116bfc9095da49db3
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef1
+AD: 64101b89b476f72b27f06f
+CT: c178edf2c7815791a8c0c56b78abc211ce5932347f418721f70c2b9516391e7a1be5e74928a33a2fb97336a6154bd2f9a61acca355493cf87276c3f9e20153c2ab1dbd345bce4a89d4ae84e3c1a0e83a224f35de85aad0ddd33a17e8b595d09e15ebb548a7c1832b1d24ef2fcbbd17b3652a76daf467bf82db36d298fca3347427af1985935722fbbe92846bdf33872abb28b0124654199384a3e9a43f7a135c22a4413bd737c64c97b5c1c4b335d7769e59d1a73731a81f32198c921dfd7878d7cfecfad0dee1023203fca3640532418540fc5a0d2da5e730e581436f925d2229e2bc765b2966f7b8b5769e0ae1e9e5a91f4c6261f8aedf82e2939957e577b420ab9d2874c0f38ef05778acb4491baa3e3b188ae5cb99580d0aad081abd6d2a97cb169025f873a250c8f868382c34fba5b1c26d5cd72babd96adb34f34f06fce41989d833193665e8db9168
+TAG: c8a33dae3945586a81e002b693774acbaa4687e9
+
+# DIGEST: db82ae5d79573da2bd7215485a92063861879c3c
+KEY: 71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c67
+NONCE: 55a7a116bfc9095da49db3d71f4b975c
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b4
+AD: 76f72b27f06f520c9267cf
+CT: 5581b26c1fc6a6f99e27dfd69561b5d7ef77264dddf1ed64233eea8ad24318e9c9d6736fc4a2d45e914460d1b0d0b4645bd41beb1af9d4a154c2eb18a8d61057b91574a93bc512f7155c0e8556a7ab47c0155352cd72c18ce341009ff561451cba430008767aeeeb1749964adc493c5e2e8dd2e33bc96a2dcc796fc06393c59f9069d18dfd7166198e646f3acc788d7506a67701a81a0fc20c755fe765475b3507b3a1f7678d63242c38def38d27e0c69eb2f553eac45c265e62da45c7a6189d0082cf595093bb7aba0dbf739f43db945010a35eaf081ce0cea82f0128b4875873fa2eb0a3d518a3a4988f956cb58ecaed2498a82eea504e768490b4d456bce978c33e661b8fbe8b86eaf8b153ec41546da349acb2d6b47afec6a40ddc53a007ed83645a7b1c3d896491a8363faaf16b1377c447f6484a958783d9b89db04fddf4523a88b633505ead3d2c83cafe488fc927792746225a69ae5f5c13
+TAG: 8ae9857dc11cd3de0c4df9ffaec27c79c089f14c
+
+# DIGEST: 902d703861f9872e7b6482f854709a214aa98731
+KEY: 9bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bf
+NONCE: c9095da49db3d71f4b975c5d503f478b
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f0
+AD: 6f520c9267cf71408a4172
+CT: ff38097f8cddba5cbf30283a6425180a2e4b3053a70c542e1dc907c2f68c3c3f644efd9f4814b790bcf4f2622c519787e0e4007be88a23491f40cdc4329d2448e100c8e81184a63b61734b532d3cd24ca24b8cd38d2b156d14ae2652fb9ff8c8f8b96d80da36300556a13200d4384c77b1ab836939bda18d1fbbfb737d5399cc84a6173f70a228c10b416fa5f8d6b545c76980fd53aa9ecd5b581e196be64dc5276f5482575a50ec3df626917a1fdc05761fa2249ff0f60432c3d3a90d231c725b00403693250e53585bcfa4b1074a16bad498c39859efbba2103e9f4b0c10e98afbe4db55d8790d1529b04a26ad9bdea77b8a9dfdbcd4cae4e43313440e9d419603849946f13c75af11aa299456c52da29615dad2f3196fd8d914a0ae4ad57fa831685e55e25f7e27e3842fb117f19566f42826bb952a992c46b67fd629ba7090d2b86e73f1610e8d5abb94381729dbdfc273b8abf2e2dc47e2e565
+TAG: e23d09cde2677d2633246a8a8710829a46a61f82
+
+# DIGEST: 4becd26b9b5c7bf831523f44cb72c8e50ff8033e
+KEY: 72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49d
+NONCE: b3d71f4b975c5d503f478b22dc8253be
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267
+AD: cf71408a41729bacb5877e
+CT: 13e3582ab6a27298a624cc2de13536c7d83312b06f1e5b1d6e1e3fc1f3097abe800d8f8e746d1ece7468f4064ba2e0f8b92ac1fb950d7036a4a1eaa5c4b313c86682fde18b27d2c3d6f0f5c33f51655a221a0b58519c9eb146bf457ac4d37ea1b9622e432d079ecb2ad1271189e04f95c495a04d920ce73b89ff33278fcb437c419dc923dbf868805853b9c654ebe098d43e43b3aad663a4ef5616c9aa45907d66bb045c001444946862298247be2c4c413ea85a21a10f2ca89111821d09d49237ce6cf098ca2040f90a0d0afdf84901122bb2f37afd23d9d8aee11908916fefb280fd3c3090f72a7edbf1d5233daa16527baf30dab254b53b2a1dc08c71d8077d08035019c22d106a4814c430216ef30ada2a4758ed5cac0c6f320a96b92b7f34110f23412b6e9c1d040faf9e60a5617bde2e352d213aa872372faf35be9313b17c650d5956cbdcbde7eea1c301b7fd20097c1abd634db93b7b2676
+TAG: e6f6ef404acc4e20bb12dbff739097e2c344f025
+
+# DIGEST: bcf4785d0e3b34c55cb2505b559fdbd525deaac6
+KEY: aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b97
+NONCE: 5c5d503f478b22dc8253bee6fd1b174c
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41
+AD: 729bacb5877e72cdfcfa76
+CT: 62b2eb7cedade84b4b268ea7366f2809639dfb45c756ed0a682d1b78d560dc917705dc89c959342ddadad2335803e9eb76d1cc04ac1f447784aba2ecc6a47efb907c797be11e457e89e79e112318e9151f1853acbab93eee4a7411ae368ba2d536f77ac07ccf97e34b7acfd624fa1dc8fd1f6a9f39d588efbc1f7fee396e16d7eba0b10d6c92b8fd28beda4c7adac95953d602ef078f0b287333d0440df73152d621b85a423b312db7ede56754b077d517427f3e18c6d8b490cdae116296d7132a49cfea37b095210ca289f949c9091288bee92cc500b37034cdd1135df8d14f21b5047def31a0ec016a7fcab66f448c1b34e44b224ef0756c9b2c5364b5c9a7a93dc340a3347ff3697346dbf43fab5241839f23a5573c92c6ae0353e4171322b2e37b1a035b72fb669093fc8644930415e58d4801ac1a88276cac841ff2191a11e38f0f7cead1c8d5fa5907d267d43d17befab34b238babe532813ecb04dd1315b0c55ffcd3ecff337999ef
+TAG: b5bba763b080b734afd22ab19610bd94f3666a02
+
+# DIGEST: 13bff121568d7c32b2546132cb4ad490cea9303d
+KEY: 7c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f47
+NONCE: 8b22dc8253bee6fd1b174c307f01be95
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb587
+AD: 7e72cdfcfa76aed06707a0
+CT: b4fd9142a06b01664843ad5ecf6eb9238ce5f15647cb032bad047a40a5101292154c83703a693d6bdb60ed8b206db9a6c9b9c94e7d00977707e9ba0e155f078607cc5934748be3335e08f827bc03eabcbbabc0de929c298f631fcfda502e64825669d6c0e1abb2eed919f17f5f310ef9a648a2ab2a0e5a5448049f58a9aa867b7d60fdb0e56d2706921fc5e579e8920f8f4053c8463f02b881046486df2932b285b52e001ac5d1af243d7621fe8158f3b269a0a14ca26ad17ef47503836a971386b9849f1ae9e2b5362dedadf855a4c2c71290976e67137139635230de31b592810cf64a0222ec3210d96fce256f9d8a77b1cd232bbc0ef2c0e9e41c9b881eb5e272e6c2cbcb2e71de30c9427edd9c43d00fe057867b00fa79e8f2535ccb9b3e09ad5f8f470f391b3e48ac53ba0c6cd16cb554dfd349a0866701e1d204bb08c9701569701bbe7229a35ad544d9171d0387e51d41c4e0757b9cfacdb7fd7d74f9942dad9a098945127fd30658
+TAG: 919f8bd22660f31bd5a59264c38ddc524781faa7
+
+# DIGEST: e0ec91f0baa3c5fd0c50f135517909e26c204af3
+KEY: 19fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253
+NONCE: bee6fd1b174c307f01be95abaa9bee58
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa
+AD: 76aed06707a07c3dab6997
+CT: 7c96052a47ffc1c76a26d7dc4138a30fb77b7039eec9fce4197253e8f175292d9bebfb3178db218ad2c43c40fcbe54ca6e7e3fab9ab1bf3f52711ffd8bd0114507c5d4351abf3482069474ffbeefa2b690376f93ed25b9b90f423eb4f3f8ef9f6919d6486139c923f0b2651a1d4cfefb60bd21294151e22859146724c1379d8fab03d5d4a3e350ae3934675a13fe1105fcbc68ed7733c0a878cace42cfd00b862331f5fbe0ebc70bc8a801f30b7ceed2709885539b5138ea1b6ac119f6bdcdab33f7230761fd49abaa35381f65a0638e1f0615eba574864b61423d0b598e5b32f187a56b06f0557e60925e52c9db2adc33b799c91f794fbb2ebc6da439fa168eea33cb32c2dad741aa359fd61ce70cbce2af0ef4befcec109ae2ccb3da544024c8008dc7c4521ab8f02a34f1ffc13ee9e278cae85571c50d5dd0be78e372d400878aad3f758cc90b126b9bb12a171c8e3c1dbb980000614f86d3d9c51a86fe5fec84e5be2b935f4e35e1d33b
+TAG: 8a9a6443370da2f41974b6e9cff2e8aef727c058
+
+# DIGEST: ee7d6f651db434a281b5cc57c2c418db731c65df
+KEY: 2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b17
+NONCE: 4c307f01be95abaa9bee5857772305da
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707
+AD: a07c3dab699719fe882eee
+CT: 0cb133985f6f80ef985c6883c5b2d15ce54521d97b1369c52f63b7d8c395ff12d668aa9ce030f8cbe213a4ed790c9c61c1fbe635531c2b0ff7eaff6500a8000367fb8e2bace831c64428a1ab84beaf2585f8afa5780c9a7b071f50d3a4d1f45d62bd1244e4ddbe3cc7f80dd9bd4df7115da0a8c4c4d93bb44cf1ec59b78f1b5b53fffb3c7c2982effce5a5b01ddfcacdfb77c33241787fd90147b8c2cca45540aed10516ef902aeba6f20f4956fd65a31a61628419257f3a37d96846771764c5f6bfcd5c9321b1167f01182ef71d744f4776f6c2e836df401b5d7fe34709f224100f865bc55a976ebf5d59a779bb8d2ba67c8e486f8b8c8d1d21529b57f24f17973af9e67b938f16881c584d139a07ed0676dac6d7fb13a5d7e7f093cca854e632722ba063932c6314bcb2a7a45fc9c46930cf3623a0acb8459b0a1325f0cb9c1497709ae88bbfa898f23b48fc693ee2abd52344ca1acb7073ebf5e46a61d14aaa3efef2c346a5e58dacc950738bbab724710b1a3dfe54de4cdf33c6
+TAG: f720f0fe436c4ce0ee45131b18271ec1d4572f3b
+
+# DIGEST: 810e1f01bfcf6bc13ebae7861454ac133b2d6cd2
+KEY: 11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be
+NONCE: 95abaa9bee5857772305daa4b550d75f
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab69
+AD: 9719fe882eee2fee55ed8b
+CT: b09c56b0c2ecf23b997316e7266c4b255cc9d9520ebd7da9b03cd49ed66fc489d6ad3912b9a17e30f118412d0e6b8bd14fad9c27a1ad1def4f374661e9e2016c8806e29bdd8ba54dfd69d3d1c27c8c7751a8fcaf73b0a569c5986f99b9ca118b6154c159e3e6274856f3ca96dc5d1a753eedffabd28e53f0f9e3ccbc7a9bc831427c8450ad1d0fc6c74080a4d2b3fcf589963b4d2620a5398883eb87ae315229a81b48f84ca0a097d6d7f335e004c5abf9bdf79f5fa62da078fdfc42edc38e893ebb20f63bdecfcfaacb4e126423064bfa21bbfa9f958cf86f1676791f73101f66ce94fadf1a309a36c7a480de0cfdd9ceea83b05772d66e35cbdb462bb6ef32f10e0d8ce5287ba87a2b862e4ecf36ea4028ac4dcbf90e479b136d91405355637fc80491030df93f3d4b532cf8a4c9ea5b024249d9df673e12e3b24e206d5cd519e80d2fbd4b5086b909791d532bd40a38389888beacf6f993c4e35fa42052eb12bfe8cec4a037c0679b94eb56849d8b539792aeb7a9cb472810efdd
+TAG: 09c411f7819307f2767d8a7aa3debd6c6c3d2022
+
+# DIGEST: 881551d50a849b7e81f0cc0d722f631e32a4c97f
+KEY: c695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee
+NONCE: 5857772305daa4b550d75f05d8089850
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882e
+AD: ee2fee55ed8b11534c870d
+CT: d89378b07f1281cb54b8e040812aaeb76d54cbf82c62a3c2f999b60733c69ffe98d3984a9f6bd31ac4f2845fd5e5152d5ac0bb4e5a1859c4b9600a5521338104dc7597319ddee899d7f4c4623ec1096372a5731052285cfb34061b76d22a455afeb414ebd19f122aadd4f30db6cb4e0d9c854473d615cd00a3c0b246357ab81941d55e146c367bf5c0068e77cd72a93236e9e469c41d956cedf31f4125efce99ca10cedcf1242017327c421b6ddb269977ac3e8648ef8ddf49f498b61b58f4a6d56e39ceba57d084243c5f1a1e9a1e0825a9858f096bee4d2dd7733858f888a7343567f16cf2fe7e53f39c85f4cbf71452b7778ba4a5bf577ab2b4e81f565adb512aa2f1890530b9c268527b54921124dc9c96c283e313e858dd52e73c9568acd8b24b15eb5cf674d8773ba443bf7f2dc34fc6c10fe62d747677a935c86d8858cefd5ee285d42ce37ace889314366f7c15732f3387de622e77d880272188ebe2792ab5b0a0e2ea9cad77a75720c0c7419fbeddb96f8b5a5681d5548f
+TAG: ca83f417dd775486cfb10376d5c081adc53101fb
+
+# DIGEST: d525f72dbdbf54db80ddeb9c2a84aca41451353e
+KEY: f1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305
+NONCE: daa4b550d75f05d8089850fea3711265
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed
+AD: 8b11534c870dc695b814bd
+CT: 1f035ff517ae79d4a7e4000dcaf9846a719a227ef18a1608f4bfe3ba2a59fccd09b1e79d7609d15b91eaa8365156e10b02b494a9ccee828875207f366ec8f2b49a88498e3663f25b0afb91f0b7fa229938105e64cc825db5a42d6d1bf9c29481f55b3ad5ed9d69d7aa54d3f27adc368216e2e9ff6dd5681ffbd04614099b9ac810ee94fb25f586e6ebeb85344c457febb886c3b9226432fa6d08af644c52fbb7e5aa389b2e3bd0f8a115975532d981011f01394aecb5f2c4c59a8e5b53aa77f45ab84f42d5f5afa00e099d87ef2b06b1f53c7538f4de3d9e3dab78a864510ffd7b232fd88d9650e34c43b5190166ce7b9729f2299649d8ca219908ab5a62fe2f45213093a2382dc5471b5740b1f9e310aecf5f915b0ba289f3005b65fc11124fed3bd0039ff81cada478cedbc29a26f8d56d56f173110345b6acc8e541ef653f44a4a1557731629a185965fc993988c6650b9d7ee93821e494b3298f29a974eaf7733ba7d1739cfcd13bb0e5a604ef9793ff6d360a2b1d75c47742ad868755f840e65c06a23048c0e11d3b3d
+TAG: 385478ec67d36f57baeb80487aaca72b36701d35
+
+# DIGEST: b25882426b4730205533cfccc0da1de1f6f2c459
+KEY: 2c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d7
+NONCE: 5f05d8089850fea3711265bf78261046
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c87
+AD: 0dc695b814bdf1a87bb105
+CT: 43c1a8d1dcbee77b084c945d6975c01d865a8b09fb8f77268e718aef91a7b31d6624c522ba0d16ae5d28e079c7381607f1c98fd103c3affe57c86ad24a2c7ac7c10fc9fa1fb2be2725a26fa0b1cdc9078ab8ef0b3bd177ac31c1fc24edb27f035e26c9c9c464cd6b2298103c369d4e0eb9612c9422eaf3983f00c36ee8f14e3705f846c885cd7e553b0c12da16ef7f8bcb360a4199cfb11d95c2dbd40a9a1135aedf3293578a70edf7be64f837f2e11a21c1d81e510c8c1e1d1c9a331a3320b2092781c3e8b1b81dbf24aa611391fc57fd6930e1e52a56af6e42dc78dfa5b488993eb1f351ad472d4630997fb389c53d277ec6453f49f9955fee16f51f1b9b5c088a98015781bda2541d81e6d400908bef8fa9d27fc908ff461d4138045de008634f6d4e1b6264917243a7c41b3780c61b173f06c00c632cd91fdb327d643cbc2e0705be8d98d21bd3ad0d969436bcddbfff63209fdafb69d8c1817181073fc876fa15cfeeb9ffc6527f70fc75b332c58893ff140ca078054a6ed2e1ebd951cc47768739d3d0e0305419c8f5
+TAG: a2642099b5bda0af0a76e713291582fb6659111a
+
+# DIGEST: 939442486c730c2cbd8df213d81310e50534f06c
+KEY: 16bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d80898
+NONCE: 50fea3711265bf782610460bfd24ba02
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814
+AD: bdf1a87bb1052c6755a7a1
+CT: bd6e242fa4cfce283653422c815b981f8d5f6fdb48925d737c8c46f4bb093b1c4f79c06eb1f91fa32820a8e1d5b6ff8ebbce6d7f8398688051556c4a32e7029d23909bb2e70b79daa938b2c9ee8cb07a421a216ed65eeba98badb326094765445a106aa71f8e418ecbe8a1698e7992bf5c1c5f91b8b3c0798a93b9bc7079f9cbc3ae94734335cfb84a92ed8049f06bfb16cb6287b6aff57eaae417e4fa722a7f80d7e9c18ce6e06d857c21d28ff7004f3bd51a8d8070a0640289abb78ea910ebc47452946a955e1ba78bc5ef20db60b2c8856eaf8ed30d858ea934f87e7d57d928a4b837704e4b0c268a9436fd7660f639ff6976f44947b482efee01234c361f37548004a5829d8749860790c913eb2187358a78b6b007e2a9405d0b57f3a6127c22219f1cb224f783206ba3433b75f53d34216676281568548912f7a6699dd48ba96271319fc6aab8669a2b966860ab4768125d485c503d6587ce6665872dc8eb4d78c0e13e6ca0895aa6ff58778f613810df2316b83ae03eebfac35c1a0b150219fa9b61fb3371c8e08491
+TAG: b0d4098e114ac495776366824becf23a977bb28e
+
+# DIGEST: a7b522c0de411517839342925e8acf703ea12e8c
+KEY: a49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea37112
+NONCE: 65bf782610460bfd24ba022e6da12dd4
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1
+AD: 052c6755a7a116bfc9095d
+CT: cdf5b3d98e77a6f8e8db93f661d0ff4c237b90f6d4e64426534cfbd7092fa3126428e24f761fb85f21bfaae503cdb49b9971b32743ae48542ea7f580652413f6482cee491ca039f141ad0d2b26ccf7ef2cf86aed6320bc65b20c394f82a379e20d2a4994465faa5c2b1dae7cf5fb9a22f2c0a345de68cd152825e5438ece2fa478a3c60ebe56f33cd552a9f1e7c1e1826cbda6c982a63384a94bb347c5fcc632fffd609e069f3a2499b90ea612a36c39ee39e2acbd065b4fad0ce20a99b95c3bb54184806bbb0b18f9be5d9a3caca6c153bef090f26969d42f99b50cea64319aae436aabc204ea882049d831e8a5f9ee802b47cebdb48c2357ddc4e3b60f12fcfc13dffa75419bd36280735854529e703dbf6b99f41c00b74f6f33521c6314d3d21822434112758fe5929a06aee886ceaf2e2f59b313dca996bfbad3b971c70b5681e747deaa9cd0f7a2b1c020174fcd3b78cf39acd23e4aadee49f095f3fbd0f6f503f82f5c36e75b64853debbdb0ffa571e33507436fd3571a4cd408023d94f698446abf319357a1aab5c7
+TAG: ff57e9ad2942ab503b0bafcafe2d1b865e7f95f4
+
+# DIGEST: f61096694be30b85b6571dfc8b5bfc4d364bd225
+KEY: 4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610
+NONCE: 460bfd24ba022e6da12dd4c27f437248
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7
+AD: a116bfc9095da49db3d71f
+CT: 498ee9a108fcbb8953eb07b37295f3be910090ee8d7867779fafb057830eb374b68e177e62416f9b34c6354ee6ba8e90aaefd02b5c0777f35b175e25b00dc9f2bfbccf16fb9d4e30e1382ac1a51e2ac08121173efdc5ece35d0be23c071dc621b1d35d4d926309a11580f7526f8596903a326669e5ef12faa11cd9175e97bf3194cd9e1d8c7d01fe01b8a1c88ffce9b14be053674f5bf7b4987091cdffe12aa53d641d2b78a852969d8ae45eef5a964f0b617a5acc98d71c414157d036eb14f4f33d4fce801c4ace2df271259a105a72b37c38bc858c2aae401858d32e1a110d5de3043740860a08603d652a8d387b443f2f72e28a07a8ee901277345a47444c00ac2b1506804da67ecd92bd672b29c6037d0d056eed647904fa8dae86cc43616c8a69477723b0ed13331b3f620facad9e10824bf15efa7d6cffa935f26eebdf2719ede194a6029d76f474364f95f049393841e43dd43ede3849e57cb84ae4c8e06ed374ea4f58dd171161460fcd3a5fef4e71fdf650eb2fc65bb2120fb434390d887111f407a5558ca3fe54cf92bbe6c069ae942b34f41ff9727e0c
+TAG: 3bfaecc79c3270db8b7971e68f6912a8a84d0306
+
+# DIGEST: acd9a5179a0ec782a63bc824188d838776bc1b81
+KEY: 3f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba
+NONCE: 022e6da12dd4c27f4372480974454879
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc909
+AD: 5da49db3d71f4b975c5d50
+CT: f433eec0a92a6c87af7f65b9a33447409036fea98c409835e252aeecd3ce4225cd67b9b8c63228ab3e8c03157da29e40b94db66a23447adc2b6e7ab15c0d35917ee74d2230854a33781b4a8e953aa499e69610af56f29716013769756ce7a3a89ba6cba1eeecac208d86f736fd3c7de2a69870a24c300b01fa5c1d00a6908d74ae21209fa52ea94cf5f834059aae61ca242b6ac170513ffeb0ea4745abf0da3e9f4e58b7111b58d26cff5b5a2488cbe443a58a28da10bb507a041d9e2fb6724917b4a5f30bd3d103cc2ad134a840ad764d7e9ad882a4dbf82534f64aff19a189cc8e59596996d57e3d51cd7b4bd7b27a54055fd08c48186ca8086a2eff30155cd500db3077c5666348d61ee60490f187f397c893fa1f994db993cb64ea15078493a7f9994a90c1a6524e8dcc34ec6dd30782b9d2102d20e85e88efb48e929fd8ed901335d2a2f0f278affba985f8fbc01e7866342921221a8f9bb13babe23aa19ae46c236ef8858c3759ab19982b90905e12ba64a8af0defa71d94e7c786f4f38d973e476aba6517b8330ac6d782d69df184316a9bacdb8148cf0ea4
+TAG: 26387a216709732e2ceb4c847031abc90e6fcd06
+
+# DIGEST: 152118d780c866c5eed3a08d2d9960cdc5acaabf
+KEY: 8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12d
+NONCE: d4c27f4372480974454879c41de9ac9f
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d7
+AD: 1f4b975c5d503f478b22dc
+CT: fdbbda3b59b58b69fda1bd7f3f2e09789f0673170a0fdf7b8a560d758c53073440bb046c8ed52feb841f590a35575d2dbe42ed5d2c740e05d3b2c29e48761f5bc112e7323d9f4b44a70a74d41d0a76c8fa042a99208c8ec4462a91043c919fba39a67cf2dcb38e0c9646198a7065592825964e56b88e8b44feb5df2d1bc105e25932b13ffbdacca52835fb818f756341c936f58ffc8d5e68a7fc95f63566a7e85b70f0f6b9c37b33821d3f9321c021aa6cd3cf71fbc0edd49ab7a69be749d9875d0e0e060de3bb8b204011819ddcb1795f5c0bee7ade3d7352ed9d94338df47bf0fff00e1f7d519920a0344e8109def37dbfb100ef6310da54c3c7f77132e97298e48201146a16dfeb54265c0d97a6decc4f2861b7a7e678ef171f52d3fb64aada6dc1be57c9077227b75759df8a25d493c67fee9a25bef1e06c600572fe2562aa0b400eba69e35c52d970b4b0cd283d51b7906dd4df3844864af2500c9af5250d4be1eb01d4bb6129b80b0d5079696a9143b54e51c0bd4de47d3016d8a546f16387d9c5f4416c77b906e89fa29145dc38f7158b47769c94d0d18619
+TAG: 6de1ebebd88940bfde4d0e79036abd346c8001ca
+
+# DIGEST: ca91b15125e07b81debf75ff84e7eed4da5808a0
+KEY: 1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372
+NONCE: 480974454879c41de9ac9f98233b5a73
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d
+AD: 503f478b22dc8253bee6fd
+CT: b1786f6ec328c919403049ec715cd835c45428b455456b7b968a11799addf79315bc7f80b64b7eee0e20bc464a0e02d144795b2609d2807c389eecff7c5494830075fff7d94332855d5c7620a142b70d8f5d377fe1a75b590b588969e7e55a76980f599db245d4bf6efb0aa0f10288865d9084ecb9b029c9736433b4d44825deddacbef88bae53f6c404a6dc3ddaa07a98dca1a437ea589830b6ea19c40f380f5a520cdedcdac965c7a203af7abe0f72409c17b1292fad665ce55c5c071dd0e2ec67f5d809d0222f5fb0b0f7d6356f4f3056324bc122b6be09ce53ad09033aa5df02c3d215e579b595729f6f999d81fb7c7c1843562e8d324c6c66df00f28418f78be63cfd8d1705294fb477e7c4e2171dde57083ce322b2b66f0fe9bc38f3ad9659a1ab27ba9c4e1aa139da8ee910a3b2aac66b116af8bf816fee3a6338008cadd97d5ac82211c968ac8c97683967b11e146860e703a59c8cf2468cabb92a7c86a825ee1f231f5c227aea3bb292acfbc5a8a73c29a69be3e50135a82ca0a3612d134fbb8c86bb58ba6ec91f8fcab306095a588b19f07525e5fb51462e41c8c0c00b037f80e00ad40f93781a
+TAG: 71182ecd62747c589ccc2319e1a3534a426cb75f
+
+# DIGEST: 93d06638fe1e836ecdf5d30db3e4fd0660d9d701
+KEY: 01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f43724809744548
+NONCE: 79c41de9ac9f98233b5a7379a561792c
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22
+AD: dc8253bee6fd1b174c307f
+CT: f402036b6e4f5fe96520115aadff36491e42f7d0836599ab08d497b78715a153edbc02eb8a8af6525d018f9f4bb6b0d061be80a69441e632a22979fe26cb0e6947c462da97b28ea69e35de6b1a0508b17f862206881608b471455b7409aa6593f291cee81b0df85ac915f44a5fd48221e0ec2f4bbb0f0ec4287e70d7f4e54a2b87cc73f11b9a6d1386a2719f3533b867335b5a26279cb51bba6c66ebdb03f7ad0932cb0465204775b74999c7cf6fb80f9b697732678313467b483855e4a7fe432ad048bb3bcb4f4d845eb4e503282185678d3117b13171869a4605f7c0e332e951bbdf796d51da6f93b043b93527371a5a5dcde3a21424c8625f3a5aee72505fd3e753152955d96232b07a2c619d29524411c0658f7653ae32320682e61959998f23972437a24f99132e2cc2cab1029783504520625789fe0fcdcdc3e7fe745928b5fcb79f83d8294d3e61e219f1b19caef5bc0c218fa166b05b77158e45738c8817ba578007a1d4f70e702615b7a3880847a21191b571587941a10a5a704a27edcdfbbdf4fe4ffdd9971ccfdea0649ffcaf0cd9f2e58b0eea8c29deaf10013f16a1d5407de8538d3574b8f6
+TAG: 15aa7aac3a0499b39e77b2e6d44a052380a5c8f2
+
+# DIGEST: a12c8aa71387379d0e43afa0321979e018d56547
+KEY: 9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac
+NONCE: 9f98233b5a7379a561792c0f3116430e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6
+AD: fd1b174c307f01be95abaa
+CT: e12c1e2c88a2c08a0c84a95cf3596ddea16a74f4c24f1a62aefb90fa7b9e7e0c7cba1823e8ab41db069779f51f03ae5aa382f08415cadef6b0f525ef78b98a6d04c28f6a2d7f6798daaad01d3f3846532fc6d2130516769f35db6fd288a27911575cd7cbff19fc4e2e674763c929efb375b5649b693bf4be0c229ad2f6fac552a4a9c49ef2dfeaab9df1468e4827c0e68f562b1833a5b053e2b72fae7231c3110a417fa3d65334112be45c762174dbcf73957d5a07e2db167c388e93b85e8ee674f48e6a5e2e2250b438bce981c8a9f48dc7e980249d9ac7d1a2fb1c439aac9c90582807d2ad0d2b8b566631f472104e167bfab2939896453b67680be0a70e699d0c168357bd3f16e0d745ef9f1546e4f72725bd212290235927004d109942954bef8a0bccb328f063ae0342f4b4d102cee4d9ba1eafe9287ef189d1865747a55a65eaf25b203ddf37f06e63ca4e0dda3a1ad4ac1b1e8526020e2b94dfdb0f66ac7832706002f2851971d14e57d62e8e21c0d82a537a313499072d63f373c393c03af278503b6d831ecdfe5d3ec7c09a6d6788c56daa8504011f21e649a59304c51a8cc4f2cf45bfb9f0c142
+TAG: ebc6600443f9694846e6f8a626b9aaf6585791ee
+
+# DIGEST: 8a524c3ce814e3059b4c7a6ac748783ce1385c68
+KEY: 2305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a
+NONCE: 7379a561792c0f3116430e8b6ea058c4
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c30
+AD: 7f01be95abaa9bee585777
+CT: a1bc4e51912193d23fe189ae2fb121b8a8f03b054927816400674246ba1c0608992e4faa9bf3342e4aa349fd4bec034267b2a2202c3792da2b14288c024a50b672ef53439313e52ccbf490911c9718aa0d19555a00490f4fd1f9c28f4096958c439153eb58692a6da902d39693ae5e0d0eb70e9ca87eb79af26c7a1c456220bf31c91ae30d96bfd5b87592e57820b9ce8a1c425e4b5d7b6df443e436dea5090939d4d9a50ca822624e757cc1c73c94d9a3aae18e8a73f5f043df6e0fe4ae05487a4af94a54192ba2136a1daccf844cbe455dcfe0d28b3d1ea002ad38dbda9b5de0b665549163e7bb259b6a7ec39dd497b2aa0223b69c2655db5714273fd36f1f567b9ebcfa3e5ee5c036e8abb6e572acd492eaa61ea1f82757ca0e300b97ccc5d2022bcff0557ab9d78ac7e4cf740cb2864d6ef2e130a0a81ee126b1ca2787127f4fab3e4b551c7699bde44d18cebf3f7c466f8edb04e88c2d6ea8971313ec9f6c2d1592bc2002e6eb8c5e90f12aaf2c0b2a3cbe88117217665dcf6c037e1bfd58a3fea924e4acf6cdcd5563d45942a8623b5124a33ce6c59f1f0c27b1d61f4379c4a844d3c68362050b6ad15c0bb0ed565fea5e69b21aa5476d391f
+TAG: db71512300dc7d825bc25b966f5df0900b024a4b
+
+# DIGEST: c31dae836928083019ab6902865d9f14c88fe27b
+KEY: 50d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a56179
+NONCE: 2c0f3116430e8b6ea058c4799eea80ab
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95ab
+AD: aa9bee5857772305daa4b5
+CT: 56dc7c2bbe23c6e4d7b91187e19c851d2a29fa715d0bc0eb902a58369adecf325f37d2b000d4cb06b0a764484117bd49ac9915c0b1e9b885f3331106bd70c3558973681c5cfbfd6ef9619c5c8a0ef96d24294aa27321786d9ebc8349f53ec3532918328d5c4e343c65ea07ecfe6ed8bc06f9783cad2440fd1474fe6ae29779ea961956aa052d64a6618c9e36468677fae3f9698d1ca3de0a79b154cf19776cb4b1b6b597178c3aeed245649c5d3a4a029c84b22f1d5ffdac07e9625bf6fc4431a67c52d598b9330cdf41d4ba0ebcc91c74bed2c16373b99aacefc56ccfada070cd7e1d1f60b35a891d69a71d9ec65f8c68f81965d9cdd9218b4b47e632f72a98e5efd08a222929358021b653954418881dd766a52176bf32c3ef7ee6b8dd8c2063f44d5e5d18fcb03163231bc3b46e04552c673d7b605499e5248e52eddc6db41ac678cfab283d471718a8878de334b740ef87448117289c985ddda0da61ec1aab4ca037d82ae417556030d39b195ca5c67973feda88672bb9b333c32a7e762d4d804d3af2686ae0e6435a0a61e02a18818e5470da9fc18993398ee043abb2d9835fed80843e02b1b6ede114cc0461f1161d4ad55e5ec06b2142381c
+TAG: eed7e1f348b06f08e09a128b274cb695e5a1f717
+
+# DIGEST: 4b2db052fc8a09f7a0c26afc66dbcd8ae5c9bf62
+KEY: 089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f311643
+NONCE: 0e8b6ea058c4799eea80abde04ee1de1
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857
+AD: 772305daa4b550d75f05d8
+CT: fe77092f381d9eb10c17443b47b4a73733f213b0a94b2b3e9487635fdfa0314e0233f2dc43ac2356c32d1efecfbda315a414a0deab24b076883413ed464b185319b8f0edff6c8b65d8e607ec5132403e527ae8bd78b7ebf29ddd61f0980c0c59f5fde07f52c1dfcb2597d5d8e4276fcd19b6d1a923f1c3365be14b2d89a1b3cb45dd668d410f4fae178bd3295c81c01ecfc72a5a43197100bd1ff4eced052366994c83c45c6244dcc9681645c26fb52ac731912d68b4467c98f3f773882a230c3e21429a16bb67c0f6ceefa6599a76c47d769fd8328d8e5002998ed7cfc7adb4a301d0ba67c3eb71aa82bcfc4a0cc65cc3b6324b383e9f9d1e0c097f996785affe7f4b6241c19769c19330d716ba315750e2edd6ee66b336dcd6d336eb7b5d1c4640689a0707917de3cdf7bb5b149691ef5875e18a42adb447b8c618cfc7e6d836bf072878be2ebd0b9d3f02e6ba4137ef7bb1ec9be8b56913001358957145c117ec61424d012527aca33ed2437a4def56b1b417f09daef026ed8e3972f2ade1b2c7e4c7c9020c79f61d8720161b86c27a27910834b6cb32112d0a26b230c3fbe31dc80118d35bf210cb3be323461b648157e0d420adc0e48390dc57
+TAG: 9fa1e1023a9c77c0e772a7c7f67608637fe0bfdf
+
+# DIGEST: 881926d37fae9095362fff56efadd9fa3c455ebd
+KEY: 711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058
+NONCE: c4799eea80abde04ee1de13e937af8f1
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4
+AD: b550d75f05d8089850fea3
+CT: 2cd78a1d5e00cf2b8d4eef9ba6d4809a2d729e9bac3c5649f0529fda45971423bda7b65a091c1c96c2ed818c6f2f8eb521da64073a4c6df9c2ce3e154435107476178f55e5ab65b4ea8d52f4030d3dbefb020cb33d29d76518325c7bad7c0ed926cff0650ea851eeda22482b5af03a8c4144f49ccaf9352f7ef9eaac42031dfa9adb694b0ec0452165ed44a6bce29fb4f1f7c32113538d0a874e08610194a5017d974e2ec6b1b9e82ebc46fd63f496c24eb032b9b996e3d79fa884909867dd21a290e6b4c0f25301312cdb8c71942562044532fb268cf350b05c62c68f6aeb5ebb9830f85e4eae5eacc7189968b6223e33537735e6f56b06ea4bd67183711fc3859f0e598d4b793ea7f073ce6d8023b0f509edc82a215a19dbba80bb036485c9a458ab2358ae6ca8d46ebd6eb83eaaec1177564f68aa67bfa40b17263222e22622a200fcea120173bc7eb97d980c7a8f6b3ce91973ba23c1aed6935ec1e36be8d4d385611ed0acad0121d7d850bd90ebcd76b369c772c8cefc9348387789e9eb47b0ee707660955b7da4c738a3777c018a90238ffb7b10ce5ee0d7b717d33aeb136f203662c70e6977f1dc757038fab0a6323fbd456f1f1af1d92f5a7a314148a6f2d4567218c5ab7cafaf53
+TAG: f1fa988620039a434fad9ef360b228e5dfc66c36
+
+# DIGEST: 92d143942e6ef5b44ad7a4b8e71c22f1ecaafffb
+KEY: 2610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80
+NONCE: abde04ee1de13e937af8f1a6944f44d7
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05
+AD: d8089850fea3711265bf78
+CT: 47c359b12a231308471fcd0df2af5247f18ce9561f1fec792ed27997f6c7a7ea9fd77fb857dc8cbc7a4f741dc245baa7993a6112b15c444f099f79b53df80050946a2d07c0e70bfb83d8a05c6b1880e3fdbee50e9eaba819d516aaddce6908340cbcb46d30cb12cbb68c8b8ab72f72df3b2b2f2e38798a2df4c3788b4a9968931d3c15658922bfa9eebc78dc59f218b426f5b0c71d8b66a82a07d9f8654b679c874d5af333cf454147b478c2503403b75431f8de1f2861803012cf3b686deac373b6224431dc5381ff00e54f6923c99384366922e84bc2e866a04fd1b044c66dc2a9ce1ad3c435bb94f6a1a0bc70ef8bd89b8f2ca46f6048a43fd77a2e73eadd5a2243971b4639a6baa4e8cd571b2cb2cc7b9635d660470444aeb3e898a1a2b7afc3cb7bd9c1c8cf3edc792a8892db4ded7388cc88a269d5b22b73cc1f0e02df7ba4acee4712b4a69580aab8db133313cb4014d094480ecd5d3a6019fc3eaac315e70682bb8a952853cc6b1c3001a67fd0e8abb838f8443c241cd8a209ff605cf1fce4eeaa66479543ebbf7ff2829670116fe30c533dd79cd3104dea4628442628c5826e9fd8e670d1e631b5eb28083f18db3b64493cb979091d4ad3d1ce6a5d496ec976048bb998c8d2ebc7
+TAG: 4353d819718eeceb0a50799e3a4743a0f964b7a6
+
+# DIGEST: 7fcec4927096421498e91df912cfe43b2e971d4a
+KEY: 24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1d
+NONCE: e13e937af8f1a6944f44d722271233a8
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fe
+AD: a3711265bf782610460bfd
+CT: 4d282f5b19d4d42dae2a0a066761ce1dd2baa3dc0cf8713de4a0575a01cf652034ccb126382e92e067b6ab5b8074f0908d1cdf18cb9b20433ddba7cf65b88568ad45b5719b0db5e2c6600054b6bf6bfb0f53418da9f0e8abc97ae45acb588a14d6ba9459c751cf6495e6a8356bb974229ba7287ccd8e08e12aea474140417f46b8c89b569a46f7bb6e28ba26b29ba6995966851d65c137aca29a06ae93878a5ef77bbf3ee4bf36ed4c15ad5f64193b2f631ceae958575fb1c504b37df2ba8f78de83fa2d678fa4eff18e81ce6f56298d66ef401683c3bbc5ec1860933a1bae605399e29826e0df26d650d57b9d84d370bb853b3d491483d348ab8a66b00f126607a1c87413306e3e06670c97e75f72d7772310b09991bcacbb2a120e5dfff5e11cf3ac94481fe3d484b509ec71f2b8f4566b46abe231bd6c02b09ac25ca1aa15678789508f93cdf309881ac081f416e99e6b143c7fdfc5bd1e8bfb75c47eb89c83f8fac5ac86e26574c99f8325cf7ab05986d0d241400349a59153d10ec7516396b500e7b2dc24c05817e38b30f7cdc25f603a82506475a047ec6cd73747df51928e6d210c261f8a148ad576c9e76e2aa4d128d7c8127dfda4d74c85cc2df80a55f5d3f4f1d9c787dddd0fd3
+TAG: 6cb89c50675552d0ffcb0d90c72602b703d409ca
+
+# DIGEST: c1c6273ce723df9f2033c7150d466c011bb457da
+KEY: a12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8
+NONCE: f1a6944f44d722271233a825264e9770
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf
+AD: 782610460bfd24ba022e6d
+CT: 43ad95cab27e9e2366235309ee4a84c7642025f5c0f2944b6802d83eeb8a9c46a346c33a1eadea00f95cc78f4d4073edb81a6a2b18ae40d8d54ac2474d3fa966c51bc0878c176ed39f63b73bd1df5d17bdb4e3e9bc978bc9e47133531d823d0004afd9c7b3874aeb205431f9475b6442f8d8424f01f3119fa5e063723d54584fe23f181509dda41e0347341001a38323fd7d36870ba6e4717eb1920ceed81a40160b441e9c627fc08b16bbf85397e8232895d0d44422c682208b7c34c542c0693482545e9f5e0981d84d10756ad895573ecee79a5eeb180208a05fb38d4ba309449b92db287deb0fbd07882996dc6ded4ce145e4ac883e570af5be1a0ef0f046cb847f8bebe45754a97f1e6b976eafebb46fd1885b94e5eea20e89a9134fb2c3f632f67e5539fa915d4b90af3338d0007eca44ace0d6e7bdd918e7fe3354af3da8be1528e792ca2f163b2ef0edea2301159e7a0ec20a57c1c3de1f0273fc6c33efcef75131b77cf740b7c9803e20c8097605b3b0754bc60e93dbd05de690237b4cd16f3bfbc36173f9ca8b66489ac203b32fc2c9a9c3f34307699af08e8c03e253c95277fe8b734158b1ebd943ce6397ef4285e4acc43b1217241697a0e8d3b7df22330033997469d1cbaa6e5586ba9fd4abed5f115e5d073ef2e4e3
+TAG: 1cd567258b44f27d8a450615c954b90268a3a4d2
+
+# DIGEST: 11424a64d5ce78fd71b30a8070aea071d873afea
+KEY: 4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44
+NONCE: d722271233a825264e977045318c9b66
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460b
+AD: fd24ba022e6da12dd4c27f
+CT: 49c8529d90530d74ec84089b8936fcf772bbd205dc1cb2fd7d623a9f995b61d20b7bed5e432bf8f283dff639855e81196099ae224900cce32e751de9d8be60350a22f8c5871095fe6ea0899a193711cf6309fdbc89f68bcec9941cb4d6ed121e9cf2d362b1396f353152d783ca897e81276bbd02f2423cfb6ae0172ece1ae9b9ab8c352144e145305daa975634fb1db85d4318433f01cb150f5a1bfa9c233d05ffcac991a4e217339a015a4441da79e06977e0ef3d5dea040cee1611dff24f4ee0fc75b6ab57c1158c2306c873ddb9cf93005c12de1202f0c2d056faf51f34b0e544fcf16276d55ac7bb71a02fe33723069b76235d6796b759235df1c67a1cf86c3fafaa11bbc704fe27fa92524f8629cb80e197bb0e4e2a7920afcf9f11f6caf2fa7529411375a5e19e030072e7e65e185f042b5df62b91f1b0355a71aea9354fe629dc0c163e72d98d5c4fe8e90fe7f16a7b45c98ced5e715a3ddbb465f956973d38da213e2c106385bd2990f0a9f94043908f183fb2b638e372419ddabe64317fecbb02875276284900072d58ddf3607832616fd6f60c14f4b44d758bf2c99fbbd5df8a632b97cec0d7e8ed570d7949929f19fa3655808b97e38942435b6817b9b50b2dbaf1ed01355dfe3ba0766417218d8f3c97c6c71f6eda61
+TAG: 9167fffc2ffcabdf64082f265b31052c240d03d0
+
+# DIGEST: 6b7295febce7fba8d79d1e7ab8fdfc452191e2ba
+KEY: 454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233
+NONCE: a825264e977045318c9b66262c0f0368
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e
+AD: 6da12dd4c27f4372480974
+CT: 1fe976a4efa5debb0d17032940d4d95335d66d02bf4f57be78ccdc3e8a81eab2f7dbef2db83d0442238598c2976cd693dbdfc2ff936062f2e99bc7c0036052f8ddb2c86dfb181166e04a01e0c1764b35e408be6f2013f668a6ff07bd27092370186e7b2180e36e9fb9f3ec90a36539d0f181f0b5b8c5991bb4ce9ce09815597559f61ce460ba2b236f9955b75c114af0869627a49a2de946072d8dde11f20c1afcdd5c979c28a4102b9ca4e6e0cf709673768fc1f4dbb90f3447be2384dbce69b12108a6b35b5389e2c79e4e398c5b9f0c1b665049ba76e7249f4ac2d9c36c647dbf30021da94cbf3eabd07f1954fcdc7d7798041edeb5a909e7b27f149cf8d9cc6df30c064df1c5dd4e8af6adfc9d9e4124bcb19d1a5ee8162a9d645d77184cd92bacd8f89fefef2125259fdc9cf8a0a2310dc631f1c96b681428819a73dca987fe74e6c6c5ccb8db201b3493e3f13f9d5d2a3bea0cd2675ca8f6945eaca741eee15774527cacb9a8169e5e3250cf318de6f8d7f0f3ab777b110c12413a97df8d446ca06e6330234498d58b93a4ad75e7c782f9eedaec1988d314a06366afd4de3b061ca49855c22f12f0d38ccf19f97b0825402429709d74e75c3602e573249fde601f393c945d281d380aa7008148be4ebc041f86979446710048
+TAG: 41aa89ee180786907e87dc87a8d552e1dae5f9a6
+
+# DIGEST: 1dadffba439570155af2509a548764a93042d23a
+KEY: e9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e97
+NONCE: 7045318c9b66262c0f0368fe9d0cb746
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c2
+AD: 7f4372480974454879c41d
+CT: fcbf4939de59426da2002fcb8e3a4d07604a168e9ffb5f13afcfbdc45325e3ecf0659ea736f9dbf61cec1dbed1024eff9e3bcb721c28d004549fd84e2cdeae36dc5e5abba4f0102835740bb877858814fa38290344addefb47ae583171a510719d9aa18c8f8a5e01396fecf1a982e162edf1047f56e8e4a839c5560473f389a4c7ea8fd5e03c7f2d31ccbc094f04e2a510aa57fe30f37cda765ddcd2bec89ab3f1f5f2ca423c68664c3303520c71439230116409dd84b4a26c1a102e521253ccd455793b0d883b1569b5013653b1c606143fcba7252a70d2a2026b989d1f67fdd594d2b33bde1bf7ee9bcb6c013ea8886e0ec1341039b8d8fbb4d865754a62d0e2a1151c917368e93fed0cb29e2d63ae176cbd95991db0a2864b27b6cf5782093bbe0ae117c7b2931f678bcb07aaae3d955b61e7ebbab8e84442295700cebf1a8f7d846fe788baa0660608bcbfa59c4bc9e5d163654aea99635f9bb63b8074478fc97b4981f5e5d35430b1e18332370dc5f4e94616b0270112dc446335d10a169e8a6923765647607ba9ad65c6f6f008cdf041af2e136b398bd1d1f67044f8360d9c1e90012e594a353d8e45aefac62173fd1b03ee5e4aa6961d83cbf1096dfa02f36ef62ceea5bf88f95301464d0046cc8ae3bfa611caa0c63d0785
+TAG: 0f8608529bdc90c222092bfab0239a3b07b9cb1f
+
+# DIGEST: e654b4c78e1c0061eea2996fc126c9bfd41eb6d9
+KEY: 3b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c9b
+NONCE: 66262c0f0368fe9d0cb746bbd55813e8
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f43724809
+AD: 74454879c41de9ac9f9823
+CT: 3a35e98cfbeeabc993af7e952b148ceb87a110d851bf2d036e5eed8482b39b881b3180dc50ce782a8cbe2c586863c5d038fc4f37d4a96ce8732abb984ae90bbccb86f7766e9712e43d3ec40fdd7a1c88cfbf14743908c78dd4c19d449db7557e0c30127d35a49503d8dce6c9a9e6f07e1c86d7e365162ec05a8b4ed301645f8274999a6c5beafc5b27dd68608aeb2efdd9cb00c6236bb143e7d91709a3fea0e865330680a854d47ae3b6067002a01aec6bdab9e60c19ca66cc39d4a44ada1e21720bd5bd87cdfb31b8a9bfac77feeafc9f8e92c4131d73a3cfb64efae2e8d14fed99c2bc88f63f88079d30b78df18ac03db855338986c0fd1614dc6afaea71130290bf52270999f3392128bc48fb0a6d6425c383b637f4c293e177f479f6a2d6323ed545bbd564f743850a121da96256a8daf163fd80835558b21e0286cf008e7cd87bab94222fd7faa395ee2ba19aa3abf5d000e7514a35357941b97e4ef433c30972e995b0991c862cefdf79712cbd3655ceb43e1e5f5b0d3f5e275bfad98a667d997333d704e4d70acc488b6829d18d1263b841307d592f760a66761e800b4676d64546a1d8630d97218a7c5f555d4a90cf58eee4bd1e1fc0e15f8f64d336edf9ca00183169f237a924e7efd5a339f3cc1bb90b4c513bb9969ecdc9beb5c5b24af9f27ebc204aace6315a
+TAG: 197550907bf6079b848eb1dca1a96192ee7c8107
+
+# DIGEST: 654b8591c7f0506261713e9ce7a6fd24a6b9357e
+KEY: 61792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c9b66262c0f03
+NONCE: 68fe9d0cb746bbd55813e8d454817c21
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c4
+AD: 1de9ac9f98233b5a7379a5
+CT: 7e1b59c791aeef6577c7ac69f8624352b7c2c7d1c8b14a7a0daf8240cc9d71ff1298eebf18ab6d469e1a327bbc3bb539df445ddcf7dccacb54f0a4ce6cf18bec20101bcd62bb2b30d8426a1e3ba949dcb69767aab5b8d2228267d784bde55bf887403188cd39453d32d50428bb9846212e4bbd3843161dc830646ba6e251ffad5d1b382101c7a3c87163867391fe44a58639e8a29fbd34cce657d321d004f842e0efa9d4cf03f557bf07a1201ac36258a4810dc101c427e19bb79f0800f27732094ee1dbab2abfc061fd4a1e84b2d36e560a38465cd4c8bc04bc27ffe90f1ce5999fc78d9432ed98c8dac4047a61547b6205bebe2191782ca63e50bb29c9bea553f5de0e9051cef35e3122c00e0d3a2468ecb2a898225c5f65fae573b17a15e013655a2ddc62adfe61ce5a7e352539c6d27c9726d2ca5492ee25b6d8233e32383100d131abce97b33dfe18a415156917ead8fe854c53bde97c0202e782679ac46f05afe1b9ad6b41bcb65bc8a80682ea8092bba0c47a9a03d08004a11756d9274ff83d5d468475c8a4a56f81cd1367040a3f75fd998b5fb3380cf8c1630fdb948fa2d0930fa5b009abc755f4bf70a59847969500d43e2db40ee517c9a6826e8e3746b3d40f9a6e7b35362550cabfa601a887bfabfd28476b3d7eb8917d66bbe9d21bfebb5a22e74d37769a86
+TAG: 785c57bb760e8a28de7a7ca3207fef4e80c284b4
+
+# DIGEST: 1eaad32c8d0cefaa5e2c503bb2185a73e6387fac
+KEY: 16430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c9b66262c0f0368fe9d0cb7
+NONCE: 46bbd55813e8d454817c212d3a0063be
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98
+AD: 233b5a7379a561792c0f31
+CT: 26234359615c88fbbf5fddd43d4832a57bda2037e2177b264309e2e50c28efc28c5ed5cbf6dea046a14caa64d499352ecba0eb2d4bd376c6b1e14048033e21b9ec63f500a70c53be60099d9c9e46ea8f250d3d20c834c3c0638a9245377fe2b76b74ea14bca6b4bdc7e8d86ca59f397fe72b8c4cbb8edc3dca7f9f234529034fe5f1441210a8ad9b4694fe013f7e4a906fc400a27279f2a1a31700750e2209f6296ed808c893a42214b46f765c9d01cee46df18b02d5493c3a1da3a6258e89e47934ade4da2fa9eef7f5b1887a60585684b1c5c2ac60d94a62d79694b063444fa36674ecde12095e9203d281da3118d058f547ede5e4b67a11ab55c1b42fe01a94a601ba031c5b0b4088563344cc28d640bf2e7c81a259211b130bb9ba9ad93090c0e11cc939b99046fe7f25132672c3714f9973513af628f21942da6b459a60e31fe1bb9bf4f6259d8c9fa07d796a264f94d64122d186a0220d9f44b040396c9c187d5ad1d806ca613a4d0f5038a8b77177f39361f9107bea7700ba835dcd38cb48a6c5af0bfbb07b7a2543f1c661f1dec06acadf8860fa2220c67bbc9c97c44cb7cc58831563153149713ca2db85af46932a8de891da1d4662e52ed5b7c1c15d5557a0930c7177c2046b50aaf14874512cd9ed62efabe5704573a4f44a4ddf71202a6ea8c7068422998eb6
+TAG: 0165231c67e88b0abd1d7c1c3dcab1b7006d4d3f
+
+# DIGEST: 862c0517b3658e9b9cd27db608d49e24e9b4667d
+KEY: a058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c9b66262c0f0368fe9d0cb746bbd55813
+NONCE: e8d454817c212d3a0063be26e0636617
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379
+AD: a561792c0f3116430e8b6e
+CT: 6f2cea3b4aa1b3ae78d31e47c0c1e03df944352b9bd5483cfc09577aab2095a0a7e977e9c1c6451625d85d162c1653423609f141aac93123b2a0bd093c5bcdd9a49b27ace4dbe6acb486446f437c27e619a0f69405afc83240f087feb029fdf8f3f25a8a262b4a3efc4bc80512a96a45cca61d46e42132abd34c2821e7ff588c742062c01eacf9d1689f11648ebe326a91fe79275b5b1fb2af4d1440ff4a9ad35381daf2a2c0aa928216351c5b89ea33bf225d34efd7ec2c81c5af325b138a5f4ac50c5aca196d1b32ce8352431a8f08cb3b59d2f8de5c850e2a06d00c1d7f7027b4aa6757eb0c9fd3035063669a5ff8db2402818c88a7137ee309ef2735dd575e43b7508c81306dc50da65aa2276dbcd98537636ef06d1736f14e2babbc39457dc8d101d22e5516d652151c2092812814e9f73dd6cc805e670ca36e62799b42bc07fa1d93b9332c43a4b759e53ae138fd2b2b419b21a332ea304fb7db57e860509855b2a540cc909aff57e1433f295e8052c7609a88170feb7623cee8ee651ae1dca4b1afa427e2e43569d5b7f2ea688d2e2afb33f1dc0666c4b0df8aee281cbcbf5e964beb3851f7b929e5a4e06766746f22d4fa1a32913c0f449b4da8aac6294348f711d4d75bca509516668944d2a162a53a31229528e54e4bfbe13cef013efcd6687e890d292e42119529c92c76c80a678b6cd735a2d01acc18
+TAG: dbd90bc3997f57efc2c5c78c22fe4dd13f06fb91
+
diff --git a/src/crypto/cipher/test/aes_256_cbc_sha256_tls_tests.txt b/src/crypto/cipher/test/aes_256_cbc_sha256_tls_tests.txt
new file mode 100644
index 0000000..c614276
--- /dev/null
+++ b/src/crypto/cipher/test/aes_256_cbc_sha256_tls_tests.txt
@@ -0,0 +1,840 @@
+# Generated by
+# go run make_legacy_aead_tests.go -cipher aes256 -mac sha256
+#
+# Note: aead_test's input format splits the ciphertext and tag positions of the sealed
+# input. But these legacy AEADs are MAC-then-encrypt and may include padding, so this
+# split isn't meaningful. The unencrypted MAC is included in the 'DIGEST' tag above
+# each test case.
+
+# Test with non-minimal padding.
+# DIGEST: 9c95dd31953799bae5073105f0694f1a0e48afce9277fe009ff26b28ca9ce072
+KEY: 86d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891
+NONCE: d77df660ed82933f62be8dc55b436965
+IN: 936a91d0b5
+AD: d2c0267218cb7090c61713
+CT: 5485a389637bd49a1ea251ed03f3478129a62964bc26d5d16c69be13c2e657f1
+TAG: 0e971352bae57fd40d369aa902d9e8d365c498a4f4829af1a7e0da1bbd913e36
+NO_SEAL: 01
+
+# Test with bad padding values.
+# DIGEST: 9c95dd31953799bae5073105f0694f1a0e48afce9277fe009ff26b28ca9ce072
+KEY: 86d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891
+NONCE: d77df660ed82933f62be8dc55b436965
+IN: 936a91d0b5
+AD: d2c0267218cb7090c61713
+CT: 5485a389637bd49a1ea251ed03f34781
+TAG: 29a62964bc26d5d16c69be13c2e657f1b36726df0f322286f368847fecaa5977
+NO_SEAL: 01
+FAILS: 01
+
+# Test with no padding.
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1
+TAG: bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: f1402641d69b3d67d63e5bd137ba006c70582fc0ac760c7cc005f22b69aead4b
+KEY: 7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e0
+NONCE: 37446f5891d77df660ed82933f62be8d
+IN:
+AD: 936a91d0b5d2c0267218cb
+CT: 0eb7d45bd2681bd217ca2e8cdf793095
+TAG: 1689d861bb4b601bae3aa27f3857bca97bfbc9873b8a69d2cbc6d22958af4e85
+
+# DIGEST: 9c95dd31953799bae5073105f0694f1a0e48afce9277fe009ff26b28ca9ce072
+KEY: 86d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891
+NONCE: d77df660ed82933f62be8dc55b436965
+IN: 936a91d0b5
+AD: d2c0267218cb7090c61713
+CT: 5485a389637bd49a1ea251ed03f34781
+TAG: 29a62964bc26d5d16c69be13c2e657f1d99cba89146195471f4914c30cd60eb8
+
+# DIGEST: d5014c1cef6e20aa0f2346723fecc3c089ed5a38a61721469ad6f2c738845737
+KEY: 97b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed
+NONCE: 82933f62be8dc55b436965aabe477e0c
+IN: 936a91d0b5d2c0267218
+AD: cb7090c6171386d641b877
+CT: 556dc063bddf5bb1392be048976bf3d3
+TAG: 5fd82370529b9b6a34f0d8382e57f2609754d5bc9ec1fd73af244ab34899daec
+
+# DIGEST: 846ce86aae8dd9b29bfb827aa33463c0080092891e59f97f05bead38577545c1
+KEY: 56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be
+NONCE: 8dc55b436965aabe477e0cdd46be9937
+IN: 936a91d0b5d2c0267218cb7090c617
+AD: 1386d641b87797b684e0fb
+CT: eef9a599a1e885d9f5ff222076d05964
+TAG: 60030f2073c50856d5b4763995df236d954a0cf2102b63d54caaf83eaaabfdf3
+
+# DIGEST: bdad1a60322dbfcd8c7a9311c700e878058572e0a0248b45ce98ce72177998e2
+KEY: d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b4369
+NONCE: 65aabe477e0cdd46be99371eb8da7dac
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b8
+AD: 7797b684e0fb56f97c3961
+CT: acf51b12c9cc5e0a6ab378380717d247237d3f6cfc99c99f0bfa700e7d25c702
+TAG: 2fa7006e3060f63e1ada09228aa7a88c57e1108f2d94d4466db1ec3af5772bbb
+
+# DIGEST: 34413890ca23481acb1093a11d520da2ab99acf2ddc6dd22666f73bf23306212
+KEY: a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e
+NONCE: 0cdd46be99371eb8da7dac997deafd64
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0
+AD: fb56f97c3961d8afa22993
+CT: 48ff34bcd2d4f4f7dfa1b8231ebba74bd88762932b36053d54df57ea7797777d
+TAG: eb28eacde2d19c8721fd371002d81dcdeb25eda808a3b33bc643cfba1c691735
+
+# DIGEST: 52e557635a7ae12be6c29ec1f8804b62c724d6754d243d8b9ddbc5741563dbe5
+KEY: 89c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 371eb8da7dac997deafd64b1fc65de39
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c39
+AD: 61d8afa22993a340b9b3c5
+CT: c24738f07b81998c80b1c66a0d4e9c4c20fd286de243b919da845cd1adcad776
+TAG: 379f49dc461d72197df2224a29dfe9f4c70e78801ab86aa334d42a557a65f4df
+
+# DIGEST: 62ddad70b167a0485a88fbc1c14436bc42625704e155f887135c6ef5ad30cba6
+KEY: f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7d
+NONCE: ac997deafd64b1fc65de39f4f03541a1
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa229
+AD: 93a340b9b3c589c7481df3
+CT: a0c008c5088bcb14ae509d22f73c849b934f2eb59860c86cf50198894c2caca28bd66182475896dcbf78ba4cb1d6fd9a
+TAG: e8366a31f80c1215a0748cfa50190d2a5c8be1d14b5fdc9f691a7d5fb260f6d2
+
+# DIGEST: 6f8dd29852fef7f18075cbcc49fdd6c06310c9460cdf7704f32dc2262fe7cb0c
+KEY: d8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd
+NONCE: 64b1fc65de39f4f03541a11be112a729
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3
+AD: c589c7481df3f4183aa23f
+CT: 644cde42a1f695b87d0bca5a6b890e8e9817daadb1441a37d754b36c51fc1ba5822d3b3ca0f3a6dec10d01a7dd729ccc
+TAG: 39f99299186b101db9c495892d53d530fb0db1aec611ecf6efac5c8191d577b1
+
+# DIGEST: af9b961f54d0814cace0da7ed911b096d8ac66c29aad2f658ecc6304fcf9bf33
+KEY: 03f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de
+NONCE: 39f4f03541a11be112a72933c7b54ed4
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481d
+AD: f3f4183aa23fd8d7efd885
+CT: 1d5cd7a3c91c525c3077feb16852406796e3944bb97a00e4f78170f4dca23164bafc1edd7046864673fa3f67a9edc840
+TAG: 99db8b5d9f9460a82f63ec0d7ef6feceb686e7ebeba738fec5090486308474c4
+
+# DIGEST: ffe42c0313980b92fcee160f5ccdc42911faf4497e194d283fc9c81c240879fa
+KEY: c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541
+NONCE: a11be112a72933c7b54ed4fad0be905d
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa2
+AD: 3fd8d7efd88503f78b8ed1
+CT: 2b8738c7dbf8f657ee8d3ea676a2a899ac46741ecd7a3a4d0416bdb14e93d390570db44f0065cee4658390116c3d6616ead81e108d3885ccbf7fa0a3ac90741c
+TAG: f396f196f01ba77fb84833fc8d112d63ceb6d7e92ffab5ce8091d8b533e22aa8
+
+# DIGEST: 4571c737be7acec8e83a42f0db55ffb2644bdeebb5677e5c179a5274cef7d8d9
+KEY: 773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a7
+NONCE: 2933c7b54ed4fad0be905d41203f5dce
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd8
+AD: 8503f78b8ed1c8e9ba2fd6
+CT: b51ab2f8c4ba3e8638d454ea72da5e3cb15336c347c442b8e1ade85c5cbd0dde790dc707d60d452d5b88d72e718f13cde462eafde82b774306bc4856db52cf7b
+TAG: f3feefbbd09818e851cfd0145fbc07b47eed3cd546d03847a92a3b0b26c80b46
+
+# DIGEST: fc6e1f5821a18027b80b574b621170ecef9abc558e743eaadafc0421ff28e2a0
+KEY: 2a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54e
+NONCE: d4fad0be905d41203f5dce998f8fb2ea
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8e
+AD: d1c8e9ba2fd6773e0d0c30
+CT: 9b9bb61ca4d5aab8d0342d2b174e8f39b8e21db0fb7146025fb298016df3bab4363bb47f5b1fa038587df98851d09d47135e349d227c6cbdf66a045673e8b6a4
+TAG: c138aaa56bcf85f928d583ce7afdffa54c236e2a4720940502dfeb6dc1993dd8
+
+# DIGEST: bb57bd76fe5f29b96ee3f2d62d8f3c4d1c8c986c0991382834046dc907fe1ea7
+KEY: 446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be90
+NONCE: 5d41203f5dce998f8fb2eaad409ae021
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2f
+AD: d6773e0d0c302a5f47e037
+CT: 1d50f3eb1cd76d8e08a9f386db0cdc3eddfc694e8502ccae47ab431c2935fc461254b80386c87690b01c22f38ea9bd118d2e0ed316ac249437a3e9c30f6c1f76364b376f558ddf76137f0690dd8eb887
+TAG: 20c506760c182e4cbb2fddb2f64e269b95f70292f7a24af00d975583a8a5fa21
+
+# DIGEST: 23f13497afad98ac65bd2a1642935ff7185a839a672fd94b18279ff92202a3b7
+KEY: 7df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5d
+NONCE: ce998f8fb2eaad409ae02116417dae0c
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c
+AD: 302a5f47e037446f5891d7
+CT: 16e3c681ba1ece3bdbfb1da491f877e806ddac5f1ae96bc406bd195c9d48bcd4a9b700a8ced21d824bfb99eb057e401c3529818725b51e96c576e8009bfe486610501aa3068c52e952e88946079d0e7e
+TAG: 443f24f113c0c13ee17438fb7c302d82bb11de71c29af66da468e17d56359b60
+
+# DIGEST: 4fb8d7ccd762998c343aef821e49cf91783d15669105b725eb1123ddc16ea445
+KEY: 933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2
+NONCE: eaad409ae02116417dae0cef457b9e5e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e0
+AD: 37446f5891d77df660ed82
+CT: 95b9375058667abde693e7e3a598dd4c326ae4db29f54667c54453e6191c52f86d2fb4fe324e9a02b94f094f1dc272b1e6ad85529206a511468879d31ab9e74f44d9f388b72cd2461fb67f7d5b0073be
+TAG: 50f1aa588d60ff430da154c9793c3064d885b31d4f7565de764af964c2e2037e
+
+# DIGEST: 11a40304bc276c51e2e7d8e3fa16f905bf050f3861586be68ca4257b1e6cc566
+KEY: c55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae0
+NONCE: 2116417dae0cef457b9e5e16dcc5b6f2
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891
+AD: d77df660ed82933f62be8d
+CT: b4d33c5131701c960eda4c50fc0a918acbe28cd47fbcaa328c6a9eb08e3c36b697928c6981992ab155c30984c6b8e9340cb00decef7086f589ed2d730cfafd5ccfb95373b8c55044fa1c95927d02278a713f2e3e88f54fa870bb429940553f8a
+TAG: 55526f219f062dadacd69284718a21914e35eac8d9078a5569725548b2032d27
+
+# DIGEST: 8b4c76888085f1030618cca2b0ef708b79b68fbe879c266adab2211c35baebae
+KEY: aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae
+NONCE: 0cef457b9e5e16dcc5b6f25607f00d03
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed
+AD: 82933f62be8dc55b436965
+CT: 4307f039e09bbc51fa0477941e321dec14e5f562d3a5ba25d71c3c8afa23f44e1ca619d130890b7476e5227442c27995cd292ed9d0a649773b752b3bc7abf171244624bc55784adc9282f1776789fdbcc5c043dadf10d9216fcf6eb71ad30348
+TAG: d591c025c364715c73d46bdd26f04cecfe347e0cbc1255ec655313aa271da4b7
+
+# DIGEST: 20f01a20150588ee1067e30a2ab84904a34ac56cb9e327756a700b1af24c6200
+KEY: dd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e
+NONCE: 5e16dcc5b6f25607f00d033fb95fb09e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be
+AD: 8dc55b436965aabe477e0c
+CT: 2ec0aab31fbb036bd2af5ce39025ee2d5591fd525a199f2233384f52a8746f4fb547843c92d1e4c9fa92bc268174d4a59134142f14e8e1e277f1f1844c64f76dcd20f3b73dfec8e9fc59a639616fe4076fabc5d3fc116a8db5b258aa84e06a34
+TAG: 424ee932af39466c3309363d93e3af6ae4409f8ea5b82ca9e4f40a472095f30e
+
+# DIGEST: 9ee27167f084f493a4e6e5b80c1cd07babdac057ed98dc28cea1f107ebc68787
+KEY: 1eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6
+NONCE: f25607f00d033fb95fb09e4d00d6172e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b4369
+AD: 65aabe477e0cdd46be9937
+CT: 60d4a0ba2caff08ac046349b511017a7c5f5537eff0bda94bf838d50c14d59426424e4a8f531103773aa0eb9d242a9e6f2ba5002ef04aef8144c8a88f05788fa5fa1ab1cb5cad84da0d31b280ff8a55cbd75f2327f726d6dcbcebbbf49001226
+TAG: ce951279729891effbc740a3e38a8eec7aa06c2bcf9eea0dcdfe8b1100d3e61b
+
+# DIGEST: e59c699ea2887f6c829b7a0e895c45710aef6911fa3c930de3da61fc988e955b
+KEY: 997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d
+NONCE: 033fb95fb09e4d00d6172e780ab8b700
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e
+AD: 0cdd46be99371eb8da7dac
+CT: ad0dff8adc54b5f02f428915bfa9f7277e4743e72e1789dcf552b91cda03bf52c757a9cca0655550c944fd264d287bc97d15dab3b986ed34637f45ffc1eb71b764cf5d5c1444033975829f1e59cb65ce40d787adc630e1f3155b2dc32733a754360ec1e16a74ea2b3f209b6f81b27fc5
+TAG: 8b28585c7b378a9b11b346aa0f155a4977d3b749d9af7af0f6c3cdad6168e92e
+
+# DIGEST: a1c40dc7a17b3ef6c9170eeaa9500014ef9ada833615b6d40af3fb2e14d7ddb7
+KEY: b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb0
+NONCE: 9e4d00d6172e780ab8b700433a957a74
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+AD: 371eb8da7dac997deafd64
+CT: 85da88e13f3ca14fc4440ffca7bc837818daf1dc52a4c505583edd070c7cbcdb4642d8ee1ca687037b08e1737a2f49039621823222f9f02deef2c340289af5184a86af8429747ef2f7d98d6aec2af060fc8e6895c2182bd1c479fc6a2e7ecc03eb4b03204db79e18b5bfb333acf9be1b
+TAG: b3abd081f67f54bb1a198e007b1152a0fb9230cbbc3e8396a1ff6763d65ac105
+
+# DIGEST: 09ec84331099e1d602d0998d99c199a6037255a5a4d96bb3af54cfba357bbbf1
+KEY: f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d617
+NONCE: 2e780ab8b700433a957a741c9eb80f2b
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7d
+AD: ac997deafd64b1fc65de39
+CT: 26d675c591f287b26eb35f87231624e454c4aca1f25491b74a252e971c48ca523b353b4f6c0106c1b3b40182eddbaf7ba47263790c3b22d23b09458d48868bb18b2fb01bdfa965f7c1b211fe02f9b78959b71e872ee05ff3baf548a85797270f456c24459e019d00f06b8a73aaf111cb
+TAG: 33f42c68fed775b06e02f9dcb709d626730d6a7d8c11dd74d811e4bc43ece4e9
+
+# DIGEST: 640ba3888e6cc260a6022fb69dbe5c5267dc8604aa92216e11888394fe59d292
+KEY: 1be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b7
+NONCE: 00433a957a741c9eb80f2b021b144476
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd
+AD: 64b1fc65de39f4f03541a1
+CT: 8d5b92c78a48ca6049da6a036735ca23b99f9c3cfb97122312e5bf0279d094cfca0b976e24f6b65d81f85eff669da35486809cbfdfd1fd615a5347947156148e6b71a11f7bec611e7c29e19f6f62f94bd7f8b89e54b6945dcc1a7e380e51456a31f1d511bb92443deab5987c3bba2663e446407acf0a75baf749f03853423ce4
+TAG: 0ae4561a255e37361b6c1d7112ece841dd30b1aa0ed2c91de1de853a13b5fa5d
+
+# DIGEST: cf85268a8412f6a450d7c8d48a2e744b508b00017da678e76cac09902ca6b0ad
+KEY: 33c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a
+NONCE: 741c9eb80f2b021b1444769da00fcfab
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de
+AD: 39f4f03541a11be112a729
+CT: 1425f735d28f545c7ab1627588b21089cfd0641b2746bae57d36f0286c43e9f9476f47da0ed156600455ac14c65c5f2999e8aac4d99f69a0deaf7ea1653dde591fe26139e30f64ba29d0b11c7853938d86d801e721ce7ec81be6fa8b5f281d31b14fe3388a028319f0fb12ab50438a3ecc32ee959cb5d39303ba0e494d4f1f60
+TAG: 2f3554bf4888706d6f686c9e04a1189d629b5b4d9d02d9d7b9cdc80bce848be0
+
+# DIGEST: 338800a96a5cf6db2ec5d06de2a53d0fb1b94918f1f8d5c0f222640d4c1bb96d
+KEY: fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f
+NONCE: 2b021b1444769da00fcfab0f5f93b511
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541
+AD: a11be112a72933c7b54ed4
+CT: 9b5f06ef7caa30028667c9d88efe9069c214d2244ab9b30443691c7298ba292241099693d831c5bc50dcf8a7eb983df8bd7d91497d8e6892e3c6ed49aae987bc5f047ea53b3a44960b469142662b1d0aa726b99170cf0c0edbbd2223efa7fd3c97afeeb9c50ca0a8074d2d339e8b4ebc0def814188cd87dee400b23ba1c512d1
+TAG: 9b8c661985b1bddf12672f3ce85664c9d96a5800824c9be33dc556fed4537c52
+
+# DIGEST: c7923cf359e113a2e3403b71f1fba1977f9ceaf3b62ddf94f1c55eaf1f8eff15
+KEY: 41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444
+NONCE: 769da00fcfab0f5f93b511060c9c5f3a
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a7
+AD: 2933c7b54ed4fad0be905d
+CT: d95064ea523f0600f9a0a9e5e46836e93632675e22df016aad2fa2499d4e8d25b2782d337760aaf3869ff96e3ddd0131acfd12b08aea5ba118754f5abed868e5adb19f7e785731c9fa79a6d5203b1d402495a4c123c0de5aaaa635ebc1773b444228df3f90ab15661b5bbdd920c1706da1ee1cc44a8d4811fa190cc820a26818b112fd76c07eb29e6987d84f528f8e51
+TAG: f44511e9ce61ae99c5b3574f20f08f8fe6379dcec516be3d1afea828764c54d5
+
+# DIGEST: e31e88c9d9b8447db592d1b7752a0d9b21dbb2dcadc7cb82b70bef32a45e8c61
+KEY: 998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcf
+NONCE: ab0f5f93b511060c9c5f3aacefe61b18
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54e
+AD: d4fad0be905d41203f5dce
+CT: 7a6bfab5564bbd7bc79f8313f25356e65fbfd003cfd17ad186f5c8789641224e42f06b505759d5182223f13b8d492990d72454448e27cd15dfcf98e5990cae2342b41770aa30eca29d5f44f3f45b23e1373914bb5791fc977e3d5d5d262616eb95dc4b7b7435bcbd27e957c004c7f205b2168b6300d7bb43625126dee9c0b226d58f1a05e020c5a162595facc8a28537
+TAG: 3f906feee719a71339736c674256182007ce2ec7a11b24f1cd77460b1de9ac87
+
+# DIGEST: de34f10db0a4f6017ca3c515fcd8b6089bf276f1ee8bf60d0f1c3e6b0198c9d8
+KEY: ad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b5
+NONCE: 11060c9c5f3aacefe61b184ad2463939
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be90
+AD: 5d41203f5dce998f8fb2ea
+CT: 9bf25d7e1bffbce914bd368f0d12e779409baf163d276582b6143a8118fc4b1f2ebbd65d63d53e3adaa296d71eac7d9a84fec35498f5825399dd307f3c949947b7efbdeaccd66c18f4c5a8781a19ebac26f5b50fd6353b5c27c49f323b756713cb9e2be4754491e21b428e3dd5f47bb7fbc25a5fc8bf1ee397566f3fc3c9256e3b996676f3f28181969a32d79bccabe5
+TAG: c0f295620e441bb9d7277a734ae3e8b0ec8b96a75668a56bac120b67534ca407
+
+# DIGEST: 0d9f746ab15a35cbed48acffb98f7743ab8ecf16760146434e465e570eeea779
+KEY: 16417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f
+NONCE: 3aacefe61b184ad2463939ed518ce97c
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5d
+AD: ce998f8fb2eaad409ae021
+CT: a8b0f34da40f7b7f9669e5eee8148fbee9d53a83583043dabd4c11cb01fb74c044ed01878f8a28d49f8a45530f9d4fb7918bbef7eecfb86f1573605e68e87d0ba1b1bc554d863a11f8439d9623ae316285e9440fae8c50c92175ad7d83ac5c0e4cf9856f5857920e981799f0e25669e61a4487febcd0ae165f9117d9ec797250b24d7619c092fdffa5fe4c8ed2db94d6962857f34b0bbc86c198267c10ad4d4a
+TAG: e9204c3b2b3da7f80f0e1cd383dcfd4d2f69e2306a7f9ce490c66f9f13c32cc7
+
+# DIGEST: fa967c5729ef3be5f912bbaac5d3f6ef60dcbd99a9040d0a6f7b248209c0ccec
+KEY: ef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b
+NONCE: 184ad2463939ed518ce97c3fdd293d72
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2
+AD: eaad409ae02116417dae0c
+CT: 0f480ed31ef27cb2f1d317cde4541ab855c9f5ff474cbfae88156a9d44b557a1febac105a4b2f70c468431e316d3a72bd51e6044b0e619cb8aa255fb5802ff9f026593b0576c3bbafc0ce1c0721e9e2bdd6cbab1d298f5c48f78e92806eaab2dd7c5975e1adba426c720f20e1cf06615cf54d75abb82be5729797cefabf4204752e41a0650564c89284246d5b10d650f8aebf01d82a671407cc890f298a75b52
+TAG: 01afbdb68d73d23750ad06f8356becfa56feeff0e974b7899d248b0ce83ce515
+
+# DIGEST: 34d46d9f6bb42722965c5d7d9033d8656525135588528906b7fdb3ecb5637f5c
+KEY: 16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad24639
+NONCE: 39ed518ce97c3fdd293d72afc09ffdd4
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae0
+AD: 2116417dae0cef457b9e5e
+CT: 1545bc0aca055503fba91292148a0707f2f6e32c9fa51a432bfd630d7c7d82992e2c5364dddfbb313df2e82b36a05aeb1565607a44217d3a70b425d045e6eba799ff1f2b081108f9895cac6cc1c390b9bbbef4a946ffa535e96267b7f87bd0bca11c519aec7a80d0586ae5d0475ee0ca537e74cdfdb4d9f96a3ff8d23b24cc1a8644d8ff85e5662977b28b5e624cd47d2fb0cb3e4c791ad6a1c503ad06fc50a2
+TAG: eba8428e4708eb10c1db67bd6b0a7218264c697c76a93aa477cfb80264fced2f
+
+# DIGEST: 6a34de797c2867beb60921713584376c6d8d65afe3e45b7a1923719e8d44aa5f
+KEY: 5607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce9
+NONCE: 7c3fdd293d72afc09ffdd4f41963249c
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae
+AD: 0cef457b9e5e16dcc5b6f2
+CT: 9d76c5eda9a39813031f2ddec6073c8d04d3473b356aeabfb929358785f83f156701dc6925c88ecfa5e3b71d1e1f0f8cc8fb1f68f703a3e1e51b8955cc6e35f750c0919807194b29e74bddd969213dcf80854f7bbd51a63ca907742a7875514118408059c72ce19b55910e944fbc8f85b9cae740b3ff347c040424e399b6e179c0a4ec05bf50c6604eadc08b83424b90cc2d8f0432de714096793dd6687d4d2a2dc1bcc7bb59ba988de324e0917878d7
+TAG: 725f8f89ce71030aac347347dbbad2a15a52a9ee1b418188793a6ea381186d4b
+
+# DIGEST: eccdb07aa24652caf23f2a83a58abe1e7992f9a3fbea97eddc8390b905978a07
+KEY: 3fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d
+NONCE: 72afc09ffdd4f41963249cd299b92e55
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e
+AD: 5e16dcc5b6f25607f00d03
+CT: 482a42ef22e3693f0f624099b5f1f46ffeb4580a2a55a8028b6be4d20bdfaba1ff9f8be16ca78dc45e782602094295f3716d48434b0a7b5244bee2485b909d3743919761a0a5b221d6c6bf505e999df856cf1c8f17e7f76ff525c2fa3907575395a86c3185d15331dc2f19f78cc2a3d3049f6d8e212318179ca38d8af1eb0c387eae090e92e9bfdb2ef6f43ee39a9130a761777f43e396951f9eae810abc37bb804f596782177702b26b8058d1986969
+TAG: 6cb6e288e7862d234bfebf6e49a8a309ad3d824b1b3dc54315500bbaedacecec
+
+# DIGEST: de04f9f52b4f38fb3d9601082d9e846e67591724717066c7d9374b6725fb582e
+KEY: 4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffd
+NONCE: d4f41963249cd299b92e55ca24d8c078
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6
+AD: f25607f00d033fb95fb09e
+CT: 332d3d299fd057c6e147f7464eadaf930f3abef1a31f5a5da964698bea10501fd2803ac0eb4f56ed8f53774b218af52b9dd4d69469627b91c31e54cde91a90f6730b772a27219593a2fea44929e7a5e6700801dc293930362f285194f24789cddf37dec7a8f493cdeb8289ad76e646738c04fab0fe19828d44bc8baf8b6b8adc7dacdf837e0ed1aff5b88d6c5d80af2c6b69949834421341deebfeeeabf5f5908eb20d18d969e394826b17adf4b0cf20
+TAG: c4d171181570fa5239e205289043bbd317256ac76c3122da2c26b9f53aefc94a
+
+# DIGEST: 4a2f51903111f8f9f1cd0e10e3aaf21e95d7bd8f91d4117fe6e228acc1c36d64
+KEY: 780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f4196324
+NONCE: 9cd299b92e55ca24d8c078c49f78c7e7
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d
+AD: 033fb95fb09e4d00d6172e
+CT: 7b6eae83ad48f5dae6e7cd46e90295b2793cfdb0476e49b67d2cbd9325fc39b3ef6d56557ab04e6003bc698e16793903bd6a33e1689957ff6146ba9ab375fb39addd9a37a6894504049d536d7b8cd4ca4f415fc271f25b538eedf03bcf652f921c4c8356d914d0ac60957a7ddc83246d44384d3aec33d6853398af001f368119f3dc2a31603c1a2f1dec97fa28a293e7a63119011dfad5aa4b1c0fbf0d4982655d21b0d9a224ebabe061c730a0a0d614
+TAG: 6a7b7985c931fb57e1102da39c24db6e2bfd939d47d0dca645f5df971ac072f8
+
+# DIGEST: 20d8d5bf7826924dd212445d7cfe80d03657d2a75757de48313f3d0de3f61eb9
+KEY: 433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e
+NONCE: 55ca24d8c078c49f78c7e713710a025c
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb0
+AD: 9e4d00d6172e780ab8b700
+CT: e3f070e55ba60e79d1ed0e882b9b78b0b2c10b775f597f03de3e81feeab2261b02e781c397ea715e2b6d240a38ffd21e892023538056d5edcdd1a547e0beece57e82f2dba5ef79131095cad656ad3150ec391b65abe64951638d78dac16d718c6fd6d0909bf06f45254e6a877eb22cad05fbaeb26b93c4fb3545b292bc09854b439f1e3170fc6f0e01cf0cac2b40e448aaebde610d38ba6cd053d8b8a04d3dcbd7d373917787d38cd1cab85ac835d00ace59cab9128190064185c1596bf191bb
+TAG: 03d6d5984148042e599241a156177850d56a1099c261b98492d12aa88a31d72d
+
+# DIGEST: f676940c12fbd43c81b05378d938ac7945b83754a0d88f67bd47aab9daeb26e6
+KEY: 1c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c0
+NONCE: 78c49f78c7e713710a025cb8b9d71d29
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d617
+AD: 2e780ab8b700433a957a74
+CT: c4410d0a8005ef22d607a2ab6a679395df14297bee469686e5803fc20b77e0b91865189d1758e9ebc6439ca8646e6c7c77488c5c40daca8c6e9df246b90d5de2ae09470dfa2008bdbcfecbd0b20c1fc6a35bc86c030b9f0303882c0c579c3bb124a61a665c815d2f9eef72aac75e9ed959f926a3432bccf6f175b6e282c49e5562c505687f44a4501ce79a4b5469c8579d8ad79e3454ca05b03b290b3615e2dac8710675280226b40d3547dd2fece835c45e9f5d73adbfd38a366747da343d4e
+TAG: 7ed2477ee8638f85f488cfb811aa01f74e16909596c67a94949012c93c77234a
+
+# DIGEST: 69662ae4064ad473606c2d36c5a71dfced4a0a4ab4dca27dbcbd5d3757685920
+KEY: 021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7
+NONCE: e713710a025cb8b9d71d2989ab33e978
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b7
+AD: 00433a957a741c9eb80f2b
+CT: 3eda4bd7d31ebb23dd1ec602ceede5e948b652ff386bfec7abff2b50b5913b238a29c8948d40389b1059008b3d5d0caa970362356c943bb25a5239edc4c23369afa76553842f295cdb4431e6d67da97d55431597fb84bc6b28a6dc7927dff1deaf25c4dec139ceb858642ec2b140fa2b3c6417f11b08cc3fde11120ec1e1591a33428ab0ca128bc57b2363ea771264c337010cddc04ac969137f2634e6fd7993362c72ec6a23de9f5c9f18e12d2212ead6e9f24eda998f593a16f5bae1913d9e
+TAG: 73488ca2c3c371fcdca5d380d96282b6d18aad9c59a143704db80335a0ffb886
+
+# DIGEST: 1c22e20d5ea9a85a8e75c7a1a54c691ef19721be71ea3aa4c22d34a8ef6d8e50
+KEY: 9da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a02
+NONCE: 5cb8b9d71d2989ab33e978c4451e3be5
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a
+AD: 741c9eb80f2b021b144476
+CT: 66116d47c60b86d93d47940996a3be79d7bbc01d813395e8a865c246548bc042cf8716869a418a1eafe0d46de099e4dfb82cff750ad3f2098b14b8b05e419fa972d9fb5885447aaf85a4859f423417f8b3c3adbca559e43eeba2b59d91f4bbb82ba18c9b0f4179e42abdac6c9cf4af89bb42444b6eeabe962aabbcf049086f450067b7d3a51344232d4f0b998a4728240ac155b2fec71744867c930d48e13644088323e7ac3de44fa2cfb409971f72ceeba19dd72bed753b3afe8fb9ea9ad156f62843b00c40aed369841c7a6490813b
+TAG: a2896bd1fb89869d7c83a23a366fb9afd940a01007b1edb37e59c585b055a723
+
+# DIGEST: 26ca5ff6124bac99bfbcd7110aeb05a5d2fb3766722e743a6a71600c4f691aa2
+KEY: 0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d
+NONCE: 2989ab33e978c4451e3be585a29a2af1
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f
+AD: 2b021b1444769da00fcfab
+CT: 6f44a030061b3670dda9ee13d729b0b6ee46a412de08a3c814059c2607b1b2a6d7e38c875cfa07c94b95d64c8ac084eafb438a8f76cb3d91650439ed389ab9e475b7a8e39a5c82c4f820df8bbc2a9b7bb5d3eba50aa76000fa6fa9e0deab4206218dac88d72a5fff0bc96c4705b2811caed58d513326b61d5dc20e0777ef9362267dfd0bf9252531431868a5fd302300cf9fad09cbfbf7ee5c92890afb1340daa074e54124f7e660928de3adaa8714d535034465d2065eb28609958495a67bc74e2e3a22638138be4f9de315b35d8f26
+TAG: 3bd63155cefcde1d2f4880851fdfadae6d4dcc1f8573eaadb9e1028731537a66
+
+# DIGEST: bb93727ee7c2a4c128150ef9c32f637cc28c95f76b345f87b9d749dd9cea56cb
+KEY: 060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e9
+NONCE: 78c4451e3be585a29a2af12feef71e10
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444
+AD: 769da00fcfab0f5f93b511
+CT: bcdab648fde1d70c2cd09540f682ce557f8a13b86306d4c4d03eebb004d626df788adb3f7bc338908eba9e5f6059b2f6a0025833da3a444394d6711bde309f6368616f7042fb52b32e67694f89523e4554968dc6da72e0b414d3e74d3fb1b8cc109b0ddd09528bc39ced260226e6ec81284367e2006da60c1eac6de9f6fbce2e540f8eb98a02c72d78e5b370c051f2c942dbb320f48d301d03f91963c5b8a4c3a6db35d7e15ec0dd3c064c4bc3f5a663cc41d494a0f1a362befe464c49a0d4c3b685895a81adf925f89e44a5c53074db
+TAG: a3ad6f2fc226891b4d6840c7d6495c81192e0e785132c81e2280263cf756bc38
+
+# DIGEST: 8ae8a1099506d47bed30e442e2b0806148dd7e981e23fe9847de6fd79b5feed0
+KEY: acefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3b
+NONCE: e585a29a2af12feef71e1063b0b4e6e8
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcf
+AD: ab0f5f93b511060c9c5f3a
+CT: 513583922cbd08942d938dfc82ac174f8c94205ff61fc29715fdd77265355520469354c80d8cf3b2f99c4fdea8cff972515c9e207cccf3f6fe43e4d8ccd51ff821ff3a95ae7cbaed326b34f2abef9c17bcf99ca91d6eac6d96b4655bd6dfa8f5d660eaeba74d141851f9c5dcfd2f9fab8ea813f4a902a3c49cfb6fea3ad9be516a3250d9b59aeb7d9e988a45c499a41d10827e09ad49549ae7fce78877da2ff3e11b7a9a893786028006be1206eac4eb2c869444dc46e932b334415b0927f6b4289c7bd7758232c42460eafb339dad4f31a4c62296804ef2aff9569faed2001c
+TAG: 17a5139a08b772fcae09eb80df7f1c5d6ff6a565dff4cfe8bae66d420387027d
+
+# DIGEST: b06c18cd7f4c807056854690c911e4deffddc44b59950560ef03d85696e245e4
+KEY: 4ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2a
+NONCE: f12feef71e1063b0b4e6e899200304bd
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b5
+AD: 11060c9c5f3aacefe61b18
+CT: fcc697a58e647e77524ebe7499db0f8e145236bd359b5b9dbab1f674c5e341031045356bb810b6f873a565299b96b85025fe1e031aca2b6637a2ddbbda4b702155eaafb4c63360ac35dd1329805f336ba03389cb7dafb8a40cf210138caa0a882665e5bcf393636e57b3ee8415f801c15299295d12ca97271aa220a8858b9f53e9662da4e72c83f1edee225d73d242de465b8b3c53fe2e52ec96e8142ad6f1197dc5ad365f07c62ae7eaa2066e4eb9f1e0332876488d4876f193a2e20a2be86a48fedb8694ed9d18702e33fba9ff373be166aa8f4a62745715f18aa01aaad13a
+TAG: 2c3c99e46bf2f6fccf00a4f2878ef2a0ca698e9c7bb2bfa8bb1dea04d4ee9157
+
+# DIGEST: 644dde7a2550d59806eb3ea4306cb5f780a53450fbdcbe2ce736c3c96899b653
+KEY: ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e
+NONCE: 1063b0b4e6e899200304bd3508132a02
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f
+AD: 3aacefe61b184ad2463939
+CT: 39fecb3773d15fc0e0b1cf13a867d13adcb899ff2718cab650eb1ea7da933cf2965270dd50129c3f4f84e291655506b805c401e7a41bfc44814592eebed176578e0db763b340aca798ec9b8319dfb8fc196970a4d2bf2c4e6e9bda41f73bd90dedb4dd2da23543ef21b7d9f7d1e987fd3b8c07832282bd08348d3de252bbe1b307ec5e95f32ccbd113aae58440ec08edb7efa432b2331633181abe4b545cccef8bc6282ef1e4eb546db9e090dad5be6e63bb2370d35e424aaa2abaa5b3a9d294ea39e51a5c5c2e88ecfc153138b4b1ff7ed7ea196d0fb443fb21ed32bf9a88e4
+TAG: f712ae23eee846029f20b5b73a3f985e677e2ef96468475ad6fa47d29ec99103
+
+# DIGEST: 6fdc37d5ed4a054bbc386444f96a13f554744434e60237c1d823a171fe282485
+KEY: 3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6
+NONCE: e899200304bd3508132a027d1ff4c047
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b
+AD: 184ad2463939ed518ce97c
+CT: f0774adeee7cc3bdce404b88769fa47a0f1c016c754726d7ff0e6b8dee2e9544b0888328f6d05fcbc96bcae2d222d12a4f401d60cd309d162337f1ec872a846432fc6c6b1047a9ae5dcead76d347c9eaa50a6f715ace8ed26fc9746043d771b5ea46e2db2331b0d3133f30af7fcf85c24f8889951e6019c8e6b5bcd7b35b788209a1d1f1ba6318a851c56875a074e88e15838cabbbd1333859417098ed428149996be26532404fa848db64e7f0b2915f53335c0d6bedcc25a2a2fdd59163528d62fc136ae0d7048646f081c7435b8f1b4c11b365c8d8f225bc60745f67ea0e8720e857893d4a8b6525c733e9f1390dbe
+TAG: 08510fb69ef365431daf95d0b3bd0a86759ecbe81c71c7b55130c93e97d913ed
+
+# DIGEST: eafe150c9d5813a48cfc8d3b72c11bbf490429ce58522cf5eb1b6a0350d3cf0d
+KEY: afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304
+NONCE: bd3508132a027d1ff4c047b3ef4f57a7
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad24639
+AD: 39ed518ce97c3fdd293d72
+CT: 9de5756d2e157625198e3b71d837b7f8b29144efac902416a9833a2bd97638825b1a56e76a34199e9ba5b217a440cd24f156cb3f868fd9f54431ed96c83953bd545d452db35a7a49a471437a91b90aa710de7c79c4a742c1ba514296cdf84c84f0d29f4c2f98a21cdf1ac319de88b7b78f8f0d147a7a349e28a4e4f438743c15a1a622b6dab9d4d70dcd6de9d782f2f7bcccdf1969ead45797bf09abfab621448e380b96b14811f8cc271463a2b45548e5fef4da2c5281ce317f80b15a1dfd735ed578c43fce54d73ca984603229f10b906a3c79788521df2ebe6896b1891a4f01507e8b872d3ba5a17975af09b6a773
+TAG: c83a689f0b3a400bbd71f06470b177ffc1c1240fc96e53cacbba09dc8357f444
+
+# DIGEST: 188098edeb12f571910ca64d0db7d6da26c090dbf1f532c4120e4821ef333638
+KEY: f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a
+NONCE: 027d1ff4c047b3ef4f57a74706de4b38
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce9
+AD: 7c3fdd293d72afc09ffdd4
+CT: 24e39955ae8b8c321a42a999a416b8304ae2b5c9f8f1d7050df6f93973a8181a782c12764a1c1c6a1cf425e770a38809e6601c37d4cdaa37d0a8e8cde896b4907dbe458ad81d30d0a3513d45f6ef4a227df6e3cd07b0d68375bb2134bd33ecf6092aac48e4dc985d5630087d458fdd77e1c00e7993e866e75951a45d70316381333d6ee9fd81e6fc66735d8021aec38118bd9a750bcdb996b2e3085b3630ed4c60007bd3f71c5f9d9b0089208e3f699f647da6b2b27e1c041e1137a1e817c5785d63ee5ba217618c6510a2ff39747dc0702b9ee1fecc994833f2452cec47512ebf6029b84463a715d853c1d800e649c3
+TAG: ab1d10e7c5365167d850f567039226331310843bd90afafdb3d5384ba6101f7e
+
+# DIGEST: 1ec354373ad0e5f22fe70619f5d925266cd3021a03e5cd2efcaf907f5419bc1c
+KEY: d299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c0
+NONCE: 47b3ef4f57a74706de4b381c692ef164
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d
+AD: 72afc09ffdd4f41963249c
+CT: b211a3e5e34c000f7f53409cfe4b06d85f636aef0d343be530f63dd1926bfa582281400bdb397e97ac4cd668f18f8945c962c1e9caa21fa7f304d02867aa6400aae4e0da990457a622a8d6b57464628dd81dabeaca617a7a4a419ba515f97573c5862b8d609ad5909596d41c3d2a440ce0d65b25b5c63e5d3a566b6f785c3dd0bf7fe814411470070612b291c9a81472afe061a333f48119077f18bf7533077a8026f2fbdd224fe5dc8812cd8b190bffdcf0a541b0bf0e37c9e468b3d48f1eacfaec57e62cee157788ded9a843d85322b4cf230d941b101bb27eb845002e0c90d626c555807d9fc68413169567f69a00cb42cfdaec498d204ba5ff6d38ada903
+TAG: 2b28870ba51f1c0d18ffce743203e73fadc93c6e2dcb747ba5919dd31e6c61d5
+
+# DIGEST: 03311a02867c702d778f6d1760930e8b8c05f168bfa8fc391937517a91487570
+KEY: ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57
+NONCE: a74706de4b381c692ef164101b89b476
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffd
+AD: d4f41963249cd299b92e55
+CT: 8aa6f51ba4d59abe6bbc72a67d0ac0324538b8cc19e92c93f9acedf9502b65dc3c9aa910b08f99feacd5e01ef38c112a1316d27adee0d11362b0f16b24b40f5d9792a60d1c5f1cadc8a4d382aa0e602b1f14e615b1e0078dde3f29caad420b8eddce7ce28b9a324e573488fd39755817c7b0e65525f0f0172b46d6cd89cb1d22d2c88657d65acf12043190d081599b2a17eab4a4746cea17972ea4874afd1976593e619957a38a50e66e7111fae07c21339665db18d4f21bcf63419cb74b3a1ffc93684930dc3d14a2d10970da74296ecf4b7aeb953c6bcb0f4ac2b35501aaa79c54fe48680264a19cf1eb38f1ec8817775161b2a83b47f16e5f5664c121e546
+TAG: 3d4290900839ded9d9429556f7353936a0596b44fdd003aa84f43466fddfbf57
+
+# DIGEST: 4d915f47f60df1497b0421c003d413bfd327ca8ea84c7b985fc125b2e5e17b97
+KEY: c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b
+NONCE: 381c692ef164101b89b476f72b27f06f
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f4196324
+AD: 9cd299b92e55ca24d8c078
+CT: 427644bf78c00d2a5e9e7a39354ad661a00c454ac3c1753f2c39989e7f3d4d8d32ea9f79dae440dd1aa43ea188ae86d11fbc1cf675da4773fc8f880c6ea7a5fc676a371f8b1dae466fd22a9414a2e10c524db4238406e3af2eb15f575715915aaf40aec9c264b29efb543c05a30f6f959bb8ac4d5d2384a453e3c1359eddde8f19618c71924e40a24acf33998a46baad26fb7682c6d87dba83ca3701b6bb5d4e05df6576f8627111a04f670797444acc8114bca9a2cdb600eb7ae8483c460228f7225dd5600bb6a709cb475bb9273c3b1ff29d17f87e8459a586c919c7bd85c23dacd591977b8047bdd4893bb845076edb53673ba2aebd1ee2795aba0091e0c1
+TAG: 8d8f2e9e5e5946d940bbc9810e50d37f463d330489cfdf39a8a39331749e46cd
+
+# DIGEST: 51f679720151684cf2065746e1643487bca49ea8cdf3b1b3629e840dd209c0f8
+KEY: 13710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef1
+NONCE: 64101b89b476f72b27f06f520c9267cf
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e
+AD: 55ca24d8c078c49f78c7e7
+CT: 7108b98dd275e9c981cd2711f84ab7d21cc8d21136dbb9e4f6325443dc3fea5531d3404718bb42794622e79c99cf046e200e367071cf6c250f68426de30ea014a5fe67364114674be01ac315cda0b6a10f88713412cce26286b3dfbd64ab628f78ee26417b405eeaf7d665cb533c29abb8d845dbc74530f7f348235c5dac90ac2d0f2ad25ef7b5f09e20bcddf05376b9d064213f0a66a288f2aaa93481887a4d753e098fcf0a7d1cb5fcfef3fb917e78cd31e5fb0c2edfaae71f96f03fa28085a7d5e9d697f659a2782904db103104d46d822b8a3d2c6c45ccc313a1c7597b51e933e9ba828b133c5a7332d462a681f4bf57f4e6c8a559f16eeb7a79aa5ba0a5
+TAG: 381c40b63c7f0bcb1065c3d612942e93fe55ee43192293daf2fb108b144ccd7d
+
+# DIGEST: 216debd294dc4f2c3d2e6d287bedd91f1e9b041f6ad98880c26a5a1d4a40d836
+KEY: b8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b4
+NONCE: 76f72b27f06f520c9267cf71408a4172
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c0
+AD: 78c49f78c7e713710a025c
+CT: be553ac472d481cea232ac78ef2f5e4174271fec6e457ff80b5049b7764c4027f2bd4f8f690481b493a41211a61d491346b7a6a31a6e78a166282b90c2e2e52da302305910aa7b0ed92fbd79433c7d63852a0fe1587a3dae548ea8f2d4fb57d4eca9141c6161b2113d82316f0ab3e41f39f9ba074681bfbece412c6633f31bc4c08de4ca41430a9ab5a8e8096f4af746383125ab4d6aef987e63228cd35565f202dd2e0e442802244f9a7a99093009aac32efcff16c3427954d72a368be22930aae8bea36670be5ec423d7571895f171f35d78605525252011ca320553617cd05f0fa2966bbf28125a971ecd0669f1a01df7b580bd70d4fcc6407f7736b7ce18c1516e0296aa120b385ea0a6ed3256cf
+TAG: 23199aa9a0520c0060ed6178c14bd4012d35964444ce26217b5bafd742a8dcbe
+
+# DIGEST: 366ac0d2917699493300e9677177d16020fcd86748b9d8fe8f99e259e45ec6b5
+KEY: 89ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f0
+NONCE: 6f520c9267cf71408a41729bacb5877e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7
+AD: e713710a025cb8b9d71d29
+CT: 5490ceea3a82f0fc643d71a80c9cb1f38ccd31686e4ef9203ab025de0a7c20bf07c3d56b0eca4188f8bf72e01a34e7f522f845dcb487f4adb8a8a3eb377a8e114279c292655b054c4a7e2befd73bff3f5c5ebfd57a50460be7470ac52adca57bd1be9674563edabfcf1f4b3e33c437f05f337b79ed83ca859d2d5de30903d782c93c077d7e253b9776edbc0fbcf52080585b1f0835dfa24bb2d9bc34b0db2fdbb6c4c866a5ca5c881e6213bb3eb5f848c51f1b68252ae15fd7c7a627da44039decacd5112684b778c3af18f11d2afe3881a3402f0bc66b6321a87875817c900b46063ae3d2f58c55f5b05d6f36801740766d5c97f60dbb1aa59eb0f3a10784ce2e7a029b0657f446c046373dfa222a2a
+TAG: f9fc0c2e9d3320a1df42edf63bbe88460b2cb11cfe31015334d87ded8ad53575
+
+# DIGEST: 8062bb5c43539c2e5f94d0ebe3387fba85f65733836e4f6dd724cfd319dabfe7
+KEY: c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267
+NONCE: cf71408a41729bacb5877e72cdfcfa76
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a02
+AD: 5cb8b9d71d2989ab33e978
+CT: 2b5dbf3819f539f3e2fe94074f6b2af0ba46bd7019177efddfcddd36f5aa23a03906e41f7e13975f53e9fb3d3fcd167a8f4ff5590f6f96dba53e68aac97ec1acdae0bf80d00ca899a20e6b8d37ae120556c7fc9f4d1791a05b6fdf352f0c30760c6f3b283248b987c07f40307b1e9e301c55163797e242619dd68232dc3cdd582f29f2c0f94b9817bd0d39d26ee142607a643e8e74b9e2010da2f7ff91d710e265d6c04010be465d32648472e59fe02326e51e9ec893ae766c4c36adcdc479c02eb96b00a60a17ee50605397146b30d1824e06e8d4bd8ff514730e52e6655c81ad3535d328723aea81ac8b1390857f1d8041159def516ef97321c9f15a211ed729c8fba4ccf3280d435cb0249f53d362
+TAG: d9ae75b8d6b358c79f4c2bcaaab38b73b05442b6f5b6f4641f81a6269eb1d038
+
+# DIGEST: 2cf5d2fc7233c5723012a8c475e430be11cdccedef906f5b5e5509d6197943d0
+KEY: 85a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41
+NONCE: 729bacb5877e72cdfcfa76aed06707a0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d
+AD: 2989ab33e978c4451e3be5
+CT: bf3bae12c3bb5b3a5ef1f6ea6eaef7d17bbe4d93e6b103730ab816b3663040943f6d453c5b702f8fcfcf92dcf6d73597cde9ca8047240d3b60153af853dc1966d97851da7568b962f7812fc5de4e7d325eadca6f0ab958301c844e2b616e7a040f27c829813704c33437d1eb602f24e8b9d021a7e3354d4a53e7f6c7088023f392a1be9339fbcd2f9e9fc565b30a4b2446f559381406dcfab665f230babe8addaba0b7ed9b23161291da46ce3a14cedfd0f20bc4934749de2911cd108f00edc5bbd527c72376dcf1f2e343144a544cbac017188a11048ed5b796cae5aa863b3961308d5b63946bf75fe409d92f2e772fa12ddfcb9eb983570b67d5c596fa28a057d989150dedf138b36c858bbfd3ac3db3ae08914933f5513ac5a18968c0286a
+TAG: 0cbfed0829aef9786d2a1fb2a8297698c097ab8dcf04497bdc01ee909ffb12e4
+
+# DIGEST: 5a7f0f0cbd9fe9e1541460a3a2b442a7fd1316c92475250ebad04166f8f39c7d
+KEY: 2feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb587
+NONCE: 7e72cdfcfa76aed06707a07c3dab6997
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e9
+AD: 78c4451e3be585a29a2af1
+CT: 33df05db55e943a6f2eb56a27d4b417eb6223faf4a91d67c6814a43b037f75563ffc5f818d65306b2c93219167bfcc788c6dfa7e5877238445efd87a5ff3d569b14ed685486b22d394e23ccdce5b8a291ecd98dbdc1c687c367039c60be9dd01da1d997a39cde650915dcd5c657bd7789f289e6cc3c8a0db64bdc1fb9be8bd8f9882038111a65d2775e59d904008593bd546e641db5bd04a927f11663ef3f36383900e66fb4053034b555d41b6cced65e913d38ac7665eae534610a1ccba89ac8fbc85a2494b6579952c38333c69d1881ed08b0050a137533a88153ee439d9ba8ab92f48363667f55a14baade59275a2452994994205518e8e23fc4336baff5473bb07313060923802eca037633cdd7a2789c31dff343d2bc22b5e0671865c98
+TAG: 9df583b0dbf5c5b16842e39156c630f37762c6aa134070400623aef24ee2111e
+
+# DIGEST: c09500fb251738f53a35271795a0790b649976d6225c8174ca45040317fd6fab
+KEY: 63b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa
+NONCE: 76aed06707a07c3dab699719fe882eee
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3b
+AD: e585a29a2af12feef71e10
+CT: 7c56a9c19c88e838ca8e416fc2b128bb630626c9e41b00ddae7fc0ea6bb302b2ed10e7c8230d13e649f604efab7cf7cabf4b6e7dad911f8f73b0f36cb0cdb6eba1748905dd9a3eaae1615506d21a76bfc9eafe1c0bb35a9d7461081c98468fefc143885395edc07000ac131bfdd633c18201fbed99f867fa55de732f65e124cbbb4138eb0898e28772fc1119a5aeaf2b4e6746473b794ec60a963cf549240a5991faeaf82c0c841ddd0e11c2a4357b689bb9ad1866b116afce119ddb7c5f95751f6ec731677445d03cd82229f959c0ed8541b2a3a29ba736e20241feb0090d2b300412f0385ea306b3200f855ae510d6ef9232279c922d33194df17dd2789af2baf38284979942d3b8e5299363ebb87a409d316e05e67f1551c7d027b5bfde7d
+TAG: 3da5c931576ad969c8b9522f5edf5b1d9f54c97b2631afd3a94ef41105c06f68
+
+# DIGEST: 779c4c8a35a8127be0a3af015697dd111f9617234f30f19dfddad1f22d36ad8f
+KEY: 99200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707
+NONCE: a07c3dab699719fe882eee2fee55ed8b
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2a
+AD: f12feef71e1063b0b4e6e8
+CT: d7db44607e1399e2f20bcb99c2eba9242b6bb90f3eb955d95ee1a10342ef6e10286f7f2fe48c4f6f24da28adcd3be51063abdfa8145d3f1592e149efd3c37c222169d205814ef194bab2f120b4af5a4d46568c74074039c0e4c734ab65fb74e79f1670c29e3d5891195f1e5b45aec92f9d4fc5c635dcc2fbf4df1c3a7fb01bcf56ac1e5f950550898f13246bd399c245d4e85f9329fde63fafa7c102944d934fa83f9d7d99c3ca3136ec67cef72a762cded77106ddbe62c45b68b25cc2a4cd6be394e0fc451fd0be17f22464a396f3b58c9152a908a62f52a3ab7394db9d9604333e698ea46adc4425acbaeb2fa6a3ce536163d39440c77798507320fdf19465a8fd7b30776ba9459374fca2d0bab5c50f24e6ba0bfeb978cdd1c7615b307e86261d95065a1792746f5fa1d08c41bc63
+TAG: ee90927eb0692ba0479c0dd5365fc74befc7c861aa24ff5add2dd7051ee2569a
+
+# DIGEST: 17cf5ceb6bb8a7738247709043777aa7880c7a583ce22f19cbcb61aa4e76c6b5
+KEY: 3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab69
+NONCE: 9719fe882eee2fee55ed8b11534c870d
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e
+AD: 1063b0b4e6e899200304bd
+CT: fb507acf490b6970ed308e33d4e7e0978db00c73af82bf78641a61bddb0dcb66a27f9f9017d9686c1bc2c303b9c6916a18a72df70bd57e886507193da1f1d6e38ce91582bcabe398bb48c2222eab5a559773b4b9b3f739c8a8a64d97037004aec5d1511f009c917871aeb3d5edb73863320a7904b800d5da7c611f5a5f48831ad694ea335cce05a72e526d1b516785603e488e5481da37c3bdf972ebffe667538d678da3e36f14874f2bc27a3b4b60b54c5727fdc2bf7aff9359d5b20d01c536222e832aea7cba8cac52cbb351d0d761712f8fcd675d58c6a364587563c7d94a62d032220acb6cf45cded21e81a3ffa26d2f9deb246890ff5c278007af43a13cf0ba8fb68fe5c2c543923d65f2938b3bd1577379fa1d8d5c84122f480d00115e95d1e3b212c0a15cd7502daf9c357420
+TAG: 8d851d0c7b79b3b4451fb7e050ce90927cfe40aff5e06e53bef197534d3da5de
+
+# DIGEST: b96b7307ee0a74e8372393bac2c64b606678e21ae96fe6ea0c356e8ece1e6fc4
+KEY: 7d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882e
+NONCE: ee2fee55ed8b11534c870dc695b814bd
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6
+AD: e899200304bd3508132a02
+CT: b90a2c5745a09b83660e1e7109b216058ece05e002d8fe68c8b1b3d0fea3c4e630ca41ac4a10b57fb89ba5e6a37c46c7f791a3ceec3a4bf9bb312f7008ad4b67387ecb2093668233e3f3884a1b1aaafd85159a5d625b1468f7fbe255bf02f3b7194f3d8fc32a813aad2d3e23cac7c4a7854c64c70d4f64f710267281ea4bd4473dddb4c96e57a2c685a7538e956f0ef51111b5c306d539bce4d97fa13550bc41b5b16a94989dfaf6025bb3c597947c1b34e0b4b05c842e74feb0d69aab7ceb7d1d3b378a2a2dae451a74ba82ac0f85a62e78688209de93ba856b21d35c01cbcf5c9d2c4a6632ba22599a101ac6ebf5a2faa8d2c2304a673ced7a9694b5fc0dfcb573dd2b1e815c43ff7c6fd94263005cc8155f7f24da8891d76ec73a3e857a16fef9230aee65699aa8664aed703815b9
+TAG: e0eacea939ac275a55f9d87ec044428dc9a328ffda0985bd421df803317c218b
+
+# DIGEST: 095708068d51ea787faa3318a9dcf624cd00f3fd32e0ec09d2390ae46783a0de
+KEY: b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed
+NONCE: 8b11534c870dc695b814bdf1a87bb105
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304
+AD: bd3508132a027d1ff4c047
+CT: 072dc4ae216213f3bfe304ced557c74f32b14e198f8417204655a2227cf019b1a66d4da455fb7ac53e37c0b0e418242a9f10e50982ddfc9e6305cf209bb6ad4ff8e96f3868679f3d1a28c75c1867002efccffe8bd63dae073b4717d9b6862e32043ca7781a007c5c42739de3a3da6d2650536037c916820c9c63ab6e54b274bbbf48e5ac39ed0c3cbca892c0c66c881a81977218178a29faff4083e4f554e122d62fdf9f2dd7d96af4c5a71cce931267e902057b29bbabe69129e51062f54122ca2090ed6e57c41c8c26e2548103aa3a0e956fed6556a196fac9ea60d18c0ea3ef8896960d4312c77073714269bc42e50457788b455a56b0b490b6a57f9d5ec9c190cb637c09557b30c020c36462fcfa53a575ab411e851301d2ab8dc47ac2bfea74b3d6973db29d84d6f07c8ad793541a7ff47e2fd0b44ae5cc3dbd903ed48c
+TAG: 88cb76554f3e54ee272669cf1f844b47c2ac3154031405ee57c04d3c042f4370
+
+# DIGEST: 5f270c4adbbd1c7910b64cb075903ac41a2df8c9270cf9cb77b7c9999a4ed94b
+KEY: 4706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c87
+NONCE: 0dc695b814bdf1a87bb1052c6755a7a1
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a
+AD: 027d1ff4c047b3ef4f57a7
+CT: 34852acb2fb8e5dd364ea55e56d270e7955cf9eda08a63e5cb0659954d5d6066707e35907e3f79719b614e9c8e41415066a1438b583648e87add78d683ff3ecce1a5351cac3b9c8fb1a259f9e2de0fe2c5a7c1afdf9d584b5af2a277a3b0a40b2cf1ee30c5f0e13a402856f731aca7396126235f5aca0bc686e55fed14437e5addb6b4ef985b090f1f2e144d384a9aeef3c89fb290bb49361565c361ad1d017987ea5eeb19e02d3dd3e04fc48c023aefc31ae7d1232546c75001a901951983ed423ac5aac06c70bb15bd62c3ce599fcc6fac9068248c29cfdb21edb739872ecc0d2624415af1ad923a19d93f49da0f3f595a2579f072cdd36d98f25a21ff3d7c8be43a54b2baa926a385c128b5e5a6ceae3c48c43e727196f5026b830f80d5b6db08877666ccd56b6d5fabac4537552c0edd6014cfbdb026d9395ec4d5e45e5b
+TAG: 73a311eca47680fc70a40305eec05def6cf44ff7e0bbc38400891eb3cba320be
+
+# DIGEST: b9cf43847a4ada30333644f3f70f1bb376bd9dd3f62d887e1c568e027dc9a850
+KEY: 1c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814
+NONCE: bdf1a87bb1052c6755a7a116bfc9095d
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c0
+AD: 47b3ef4f57a74706de4b38
+CT: 33866f4095afb9df351945bb466e541be8f05b7e9074ded9147e3dfeef7737c1e2569574d2d9693d7be8e2930578ecbd31d12118c0005b9f27f341d5637ea098e98a09357c8128a8b460d8d9e2f14b413eefa6a14a685b116371ae3a45888b372497d82bf6a38d0cbb657b5aa43b3017fabecf4a33e70bd2a94682ed7149122d828c4f7c5ed41454a35fc5aafaca2a5a46783ca824db3bd8566654ed891b57d1621c72e622e0bca362cde56ff26ef5c226223b4d86285a95fab71722b645c815e6322cf7874e7ace05dbadf792632a3e079aa193c3d3eb24c58ecbd5818d5a79b7f956712fe103ba31e1e39a6c31a3efb2a72d8907c52e446ed2b5a4085f7bf40f7c5e0d31e24ec572d4c604561055e6e5b48d23e4d594968e32ec931b5272941c0a6786b0f11158dce72f6cc69e600af87de5631253eedc3b05dda23d97490b
+TAG: 74dc7a9e817640b5a6f8a63ddd41299fa879736cfc84a6452665d31ae69d1615
+
+# DIGEST: fdb5d6bf2dfbc87415f4ab038def33249486f36e8b73ef8f41b8b6ed483222dd
+KEY: 101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1
+NONCE: 052c6755a7a116bfc9095da49db3d71f
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57
+AD: a74706de4b381c692ef164
+CT: 3021e304c1a4f73309baa78c2dfc389b5efaee2fddd1e915edfeba17b244b481df325c3ca455b1255e5ddb73bfc3775c2619466943828616f772b4329ad432472e707932e5dcccb0f75f998dc95de7cf7121113807db92c3ef072f5bc569d05bc87f5b0db1710d140c0601a22cf0d88ecaa6e6377a6dcf62760d4b5817d004ce1c9f161a7a14cb3156aee08e93a9ea16c601284744918b39daa3228cc20385e9375d3807501d29758fe51668b746029ff5ec5aa5b1626533e7a50b9ce80bc2264ffea78c5fd066a1b0822471e3afb374e070cd6c91084c65cd88e446c5e3ef58ffc3d2a323586a038949582ff5d416bd0dc8f21b84645886172e6adc9dd30942e6e3e10afcfd549bc1c44cc2dd8c3c01e94d6c586641f808b3a947fb7070660c4149f6fa54c08c732079fa6c299b03bd1940d6afb70cd72d631d3811be3b8920c230d5e362250d3c3547eff9efacb3d3
+TAG: c5f15c5ba209e158167f74f57d616780d7a16a2742139bc3a4da81e26d620afe
+
+# DIGEST: 4b01d6fb213b1664440939ee33e8c5d2234c67ce23a0a398997b14fef5418961
+KEY: f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7
+NONCE: a116bfc9095da49db3d71f4b975c5d50
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b
+AD: 381c692ef164101b89b476
+CT: 59fa1e8ae8260aa38b2104f14633e0c46ed9af3d1ad70c1d251e0ecd81810d03aa34f0064f8c9002d06cea1feebfcdb7e65d58207046e290edd363913fb6b8c9d24dbfc406457b794ae86c905b1b13b32bc30eafd4914c93113ae251cc05ecde3693804de90063ebf3641096b0d4f4f2092144cdaba47646a34b5e8eef1b48e3fa57257514148ae1f88f19f495972701a053a14b65d6db3c0d9b1c9673cdcb234501248341e3581f2d9d543c25c3707915b9297e4b618ff4c1db4986ca6c635b0b4f45331aa1f157159fce7822469d6147c7b59f244bfc5aff1b337aecd91136fff686f8ef7ed7ec5e3cd41194f2cf2ef4abaa9296ee99b349080f140acc991b596fa3a7147aee0d37ac5b3aff5383b4c93a0ee6ea8352923b97e5ecc24faba8ef3498641eed9521df8042786b4bc1d4d5b4ab17fb3b680eb432a5fb72ca1c5fa0b2839bf426a036673ecfdc67111c89
+TAG: cef248915758d364e69d2105c5db95078a47ccbb938fc6677e6a3dfd79bf49be
+
+# DIGEST: 0009f882f7e8af026f9de7a79f59f654252f154d073b36bb640d9bd070ac8f03
+KEY: 520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc909
+NONCE: 5da49db3d71f4b975c5d503f478b22dc
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef1
+AD: 64101b89b476f72b27f06f
+CT: 2396a6bd6d6927612b4e6a56e7d461c2c89e7bf3d384088102f4498c572db10fe0a825b5a868d6bc46a209a1560e6ebf81d96651bc57ce3490839a60fa1b0480a85b18827100468c63018e6e98d305a18602060ca5ac02cbb0ecd8a8135651b8134bc2b5ca994b9d1e5ab82c6511be8f9425601b12d99c8183522506ea2279ecda206f66bdfb0d054c0029d013f2e5334c119b7d81022c27a34dd7e3bf6f48811d03d01c81be1cfde80eb87a65f6bfe73ffa7518432dac1747a6a35f3cd7cde558a9d893f33bf7aac67b4c5ef47c45cd7b04366260a2574f5e39abf8b064d18eae8e74c1e1cf0505c52797bc227776668eb9936bf27adf2b133bcb56ace91b5db59d95138bf62a5b8b4d311921b9e5eec5adde04912a4696e5933944985cfddbe268ec87ecf784fb61102c4033e367d670c316dfa94fae8d6eac35643b638283d7d88ff43a14cf46082e3c75a0dc22f5
+TAG: 3d19bc99a363c38df13e15f677f422fe0322b76f7475b25ca79f44202dcd59e8
+
+# DIGEST: d46a7bd4a3a5ae655563611d004ed51ce2eba538b78c30b4cd4a0c1d82e3bee5
+KEY: 71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d7
+NONCE: 1f4b975c5d503f478b22dc8253bee6fd
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b4
+AD: 76f72b27f06f520c9267cf
+CT: 2b8899785acc6cd7bd978600b9fbb94c4a5026179a1fe22d9049622ecdf84213efdb4dc5fb830fd3d506b92e224ce62ef13d7a364b0ae8fda7cf916433d692a2a4ded2806d34eae12c78395a3751cbbbbb52e9e9931a6bd3c9e2b8290c02c72bd86257e48ad605a90110d4f46d77f5e8c15baeaaaad42ff4b855720b8ca5d328e4f9c4143742f77c6064d59f6cec33b5c6703f9a7372bf0fc783fb24abd7cbeba3ed6529436755bd6eb512c3d19679ea331ec6153ce799960e5a50d844a37c919b7b62537c6ac91a9f77d9885e7a4a66a82f3824f17d756424f9e2e870cadc95b8af446f4a70f249d228bf6ee760a03637edd3c648ddbbd2576153d8b708b64ff79fa4105c3cd6ef3406cdb0ff325cb60a0c4ebf3660c401e52a40174e4d1423903eac108cb970c53feab7107104d27f2f07fb3767fbc3250afff3fd9ffb15385d59ee88db624d0addb9ac5928ff6b57
+TAG: fb3e67ab3dc2df840e3cba09f699f9ac81c6ebcf568ee0f7c50be63211c29e22
+
+# DIGEST: f25dbcd1903d7e56eda6b3f29a4c673e9564c7275b22ad278b9ff23c98499ad9
+KEY: 9bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d
+NONCE: 503f478b22dc8253bee6fd1b174c307f
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f0
+AD: 6f520c9267cf71408a4172
+CT: febb0c12feeeb3e01489bd80c9d169f8eb95f607e6644744ad595fa5b4e1f9b2e09103083abc4d2a772963642cb066078e0d29d05618ea458bcff714c6d03a80dd792e8ff809779d8ad224b13291d5a341cd4fab7f2aef3317b387661b7a60cb006bb5e88e99e3436ca0c7de680e487697648cc38d2248d2de768314568304c96a819e28ee0227472062fe2a56f1cfd3d622ec28ea3afe5f22812dbd82358b30badafccf030b12d5ad43e56e74b52f8777c296d41a1f340c6982d1480c85d8b47096d4d993d5de49433e3aa6274a5101d98f53067ab1d4bce43d823798c9c279205425376a92800cc0d5a1fdc6d22bb79c2f65284bd6a4bb0cc515a165f5a280393b09b16e6ad1c51810d5cdce2c7bdc918181ff0502eedfdb978d6baf91c8afa80d4dadb4271eca6ebdc2f9b2c3c2ca32079a4f225972bfbfa658a944c4b0a997f66f16d0d66b55476d9bbb5047b653d03f38fd8d07ec9646c82ce242b38759
+TAG: 5cd52878a7a0fa1c6760e1744482802345a726e1ed975bce5308fcc28bee6637
+
+# DIGEST: cc3ca713a3d8ab5a06b5ecb827842cdfca5631740841a1dca516e643b88275c4
+KEY: 72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22
+NONCE: dc8253bee6fd1b174c307f01be95abaa
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267
+AD: cf71408a41729bacb5877e
+CT: f00593c6930e7028b5f3b94b30574cb12a39163834b4acbfa291731c91e22a60084694bc850ef6d179b7195553a9e33f5d36db482c393ad91d3f2618b3a43c8660bab015594825580a1f3536156de6292f89865c9266ea31e429f98f5633fe6f94142873cce67ac4c46ad389fa324209039f881cee43768b55821f248752a0859962bf422a4838bbbf00487ebc75e51afaf63a8753245d6a5cec01c45d84db786e349ac469d27079863db0655e88bc533dd198924af95b0114a0fd9d877f5896b3c4455611f75c71a00ff9bbe65e4919426615bc5ee6e434c21c66655a465bf4fa64cf50be1f5a4c6b77cc73acd9937f04d7dd3085ee9d3a2fc23caf5a2984817311ce4e4cb2c2fba00425b864c5155679f17e8b70b27ec0014a571a2102bc6702f55e798541499faf18e12b918cff6218b38c09e0c7e84b56d43a32ac848f13f2f01766a54b8417526ace32792ffac71935f58093e1f1506f92ff2ce0533336
+TAG: b368505d0b96524636f65aea8c9cda66df6928e444a71ecb822955a437a5339c
+
+# DIGEST: 2efa7638ced4eaa3cf8c0958b383f52fcd3f088bdad351f534022d5855a7c2b2
+KEY: aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6
+NONCE: fd1b174c307f01be95abaa9bee585777
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41
+AD: 729bacb5877e72cdfcfa76
+CT: d7bc5ba21d53d21bc55f5d2ab4a6cd01c2a81e4c3ef0e95dc774092582a188807c94a93741def8d71cfd3e6162d674c4b41980e5fe753ccbd6c16e6bbab80f9e569efcd7c1ad4c7d3a6e89d47b8d70c77cb4b0dbc500602128c0bcb34c2a2840a20d704956d91c60098f2e30d7002d7000c009820908749f517b55307555b330480dbe067e3763fbf147accf9b1fb1cdda14686e2e272fc68e0ddffdcbde75fdb3df4ea2df1adab4e21b26042b741e011a219913bb741a5bc8ad6b1fc32003bf279cbe44eceb5d3d3e275fb54f23d0b2fc2c456fb717ca401daf930cfa04358113aacacaaef51f39b913adde7b88384b8a8f0f7f520f8ef29218845b290c178ce759805e3a46fa4fbbf282af97392624560b5c783b046e5523bc5eeaf40401757628d8381124c14b74e7f08087399be7bb4732bd4bb4717b1c4cccb90a9917b459fdf7a36515fe80c2b94b46ec15502af7b1d9387c088cdad4935fe90e571f08
+TAG: 5b2896567564aa969c4a3d788511703a946c54957908754ec73071278c3758bf
+
+# DIGEST: 21551f1aa2a795b508708c2601585cd3175588f9a422dcdde2f23441304602c6
+KEY: 7c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c30
+NONCE: 7f01be95abaa9bee5857772305daa4b5
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb587
+AD: 7e72cdfcfa76aed06707a0
+CT: 72a7294ae080555a722ed9f77dc9109afcf16ad29e7909656aaf8cafb52d636ce339b6ccbbc1e105fa83eb165431013d58cdf5a0e37bae5256e45433794aa4f56d577590a212dad57990bef55ca7bd06dd192a4947812a856add84a7b10364608e0640c96600d98bb945f9af8cdafe84f5b3197e94e48ca494093b4105999fc881d083333df9696c356fc58f5ef9ab1f66ceb69ebef7e3650fa43266d8664c3367a980e4f4c2c6cf925aa71ed0ee14d8c260a1df9cf3d58ddaad5881c7ef0a02bb19ef05772c3d21572ab0c05780e533ac48bfd199fa0727cd36991a57d00f77d58d53aeac81118e7b7d677912f0ae54196ae1063c96106e578de29d6b59758011b1c636e5479e24b3604b165104a6209e666b3c13130e47246698e400f5311120b72d54f2b49494b5475572771e7b8c3e7d071aaf3b80dd71c92e168e0f28ba20db868489c30ba87047dff5deb9ca1a10273aa1678bc7628de0221789df4a6fe0f2ef7c52e23b8275d4bb9e01de6ead
+TAG: b1dcc74efaeaa3b239de4b913956e94d923819ad0590eed41889c7fd24b0c224
+
+# DIGEST: 37f283859e4bea7af5e11b877f34e06e20fd6b27cb847257df50c9e1a003e4fa
+KEY: 19fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95ab
+NONCE: aa9bee5857772305daa4b550d75f05d8
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa
+AD: 76aed06707a07c3dab6997
+CT: 02f61373fe80472ae5673e2a1ea0359b04a030d1c00d032c087fc9b2893a8a629696f260043c66df8fac460c088afa265fd5a43c1eb20b048bca97b3da168eb2d54e955c2e2261c3ea5a872e13de87626fc94d10f4d55914ad308e1dd15a2ac27bfe4551b0bae5043a6cdfdc53dffeae88ae67436327bd5b1d49ef9d32feb83308d2a77527adcdc398f05e354b3d0e08f5b08739c21541c342aefcf6e1bdc5819271669b18e1bec25d474f277bbaba48243adaddda569b035dc5bcffa65a40aa90d264369b5d91af66e8485c66681205a16464c9f034d088046cc955c62b35d0b0c68a978e09956cb9d69e66ee32795c66dad1e8431d3d669e55816c9eb6ce49624ea7913f13c42a4498f16c21cf0d279c37b83b390eaab7afb88b46711ac3ca920d233836defa9b89e4a6831f668e45410c00736f2bbf8c25fb35190e11e006d7a4f32fffccb5c0d1cc084de720d774b7405ed338ae81e02ac3f92e8218ca859c54268839f76ca2844a7ffe5ac9783f
+TAG: dd4d2498885e6b1d3cff04a44c01c7a797737cfd6f9da34b9362af9be085590d
+
+# DIGEST: 586951e00b7512419812973a96112da62fda6f2e20eb626bf24b1b036b9055fd
+KEY: 2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857
+NONCE: 772305daa4b550d75f05d8089850fea3
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707
+AD: a07c3dab699719fe882eee
+CT: 787b7beb0ff6c1d04f62c98c7c80b96c5a888c63796cf59c3b904ac062abd94511d5c08aee5c5e9c7e2c73fda66261427e54fbe4a385a5441fe629e383c2a6c851505748de89e4cffbf39f92f12423e73844190f5cb2cc7b300f46bd7cdd70a7080489f4be9538987e542d606811b6ff9b795228263919f4b23d60d3505f5ce5cd94dcda032940e840ac7c54d5ffa0d4c6b6a79b0a0da867c87e005ceb38062c1856077aa671282d6d01ae9611896a023bf8d8fdc898265c6ca03d9f1531203bb2e37a72c84a41199b99bb797645db30ad80658917dec81e4cc0b7e93c6f7d3e2d46de98ed1174f28df6980ba38f917dd33d7dd46c5bcd3213598f440beaa460717d1a4947cc56d9782dfb8f43bd0bbb63a7dc45101c61f5d5112fe7d62cea0ac4f06aee7e44cc5b2128f4f169b62943d15eb46b156d6de7f49edc97c0266b547f3d8cb19673d2a46245d3d47e984d799ccaad62609351331a1d80540d6776778868e3a9416131018cd517f51ae4c86b
+TAG: 07eb4ca7ba7bdff88d1db639aa0ba1bbfa651377a07d2dbd0bc336dc9cdc75f3
+
+# DIGEST: 8580235e581735ea2a79cd995457451b448919d39cb40914b7a100d090f5502e
+KEY: 11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4
+NONCE: b550d75f05d8089850fea3711265bf78
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab69
+AD: 9719fe882eee2fee55ed8b
+CT: c501cbe69a2cd49c88e390d51b87dcdf955d189b94cad4a46170cc76a5c91c4008834b321d530d610c63bd5e8a87f8175c125b533182fc0c9eaed95ad1942bc7ea5f2510f05be1ac98f84541465448819029bd7cf808fc87e56223e444b81866816d6424d86243ec362473ef764089ca42603448477c5b3750fbf675847ac059a0a60ff728ba31ac430eebcf5e6637c44546f97883aa30cedd50871f33bbea5bdbff2dd6121a905f1f19d139418b49adc14e9c9fbf811ac77b8c8d3d43e4799b432000fd97d715ad75ee8fc6e973c3503fe4399fa2063e4fa060ac99eab6373b635024cdab836f2b9b9db16209ef3d23565297eaa9bc168da1fe53d827d7da82a378aeb11160eea625892afacf2c06720c9f89139cec0e51660e6355ca51988caf19e59bad9148d6ed1215b59bac010080fc92df475c101969366e92cf06978abf2494223d78f929969055d56cdc35a2c788d7a51e79b48a6655ffc5866a04eb4d30c65306496d90eefefa7ade0125a4464a9f5a683d3a89dd8de4aa4a2b5481
+TAG: 97be41b0f5485fade9fea09e73f55d6bd083deb0e5958cc8d6a27f618723079b
+
+# DIGEST: 4d1e0e78f6347b8ddb4e9812cf4d68920ee35a2d978cc68bb75d2c3f334829ce
+KEY: c695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05
+NONCE: d8089850fea3711265bf782610460bfd
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882e
+AD: ee2fee55ed8b11534c870d
+CT: d8099ba11e3823257af38fb3b0a6a6d673631dcd6388052cb4d8ef1b85a9af621252fbcaafc55c666a97b8da77e567056f77c927d73311b07cd5f4b8560cf747728ca403fc5c88366b55bbfca1c8f68997a40467dae71dee975364af96cd2547f6daf626287c3f78d16bae7dbe38a226e4e78c500885b880bed34deb37ebcebf6bd99a078cd2af79de622f3af9e0f80667c60c05fb19eafc1e2999830d640945825c68cb4492ecfef72af50ab52ecd2849356956d5e4cb7a9ecdebea360f9e0b8bcd91b355e9664ad25592e1efdf76ba0bafefa58eb30be235e79b9ebf4df3501b46d0bf71c95721fbd2c746bc46d6e8f8cae28530fd295d78d7ecd7914a835dba3d36a25ff0b708f139d3dc2377d4b8dca7ad96260eaca1d6982963554bd26bae8de6d132e5c6080d4a4c3b19d8d213e5f35e0bf8bd497d95c3124d5d55a78e7fe1cfb9b9d6b4f12e251616a883815e8a4bfe0a9f18ba4f7c9111d0b80690438e3b50fb7302abb398e25818125c36fb5a69cf343e40dcea898f4a27e072f96b
+TAG: ec9e0143550f1581bafd84d3c6f55aefdcc801b4eb547bf10a94362e39997cfb
+
+# DIGEST: a86fb2801104bd81851682d1541b44183f740d2fb6e3811eb614f0e3750802f9
+KEY: f1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fe
+NONCE: a3711265bf782610460bfd24ba022e6d
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed
+AD: 8b11534c870dc695b814bd
+CT: ed79a061602d4de1511819ff5cb96b969d2ef7f6b86d9892802cfab081127a5ca9cdeca32e8ae6aca7f2bfc285f5c5c02aceecc348dd361b4c35dd90e3dcf10c673cf18ad9c46474ab3a913f95c9d1cd5161684b4ccf48fa2035f177fc78432b762b0b0a36a4eb034a24e689014a97c5dcf5e78245f466788d8de698a0f468f368693d7355f5ee8e071f7a282492696702cef613d8fe146a92d0f89f9859212edd76a4bdf22e5e946b8957f49177edf27df30f05fd2658949becbc0793feb26015154fed875ad854debd0edc48d7dd3cdd1cca4b2263cd57c8dd25347aeaaac1d22dfaa69134d8d1f5458e47f7dfc8774dcfb92f3493a500444110e8fb78a7e4825a1617b970765105116d363d5cc7f6fe9547e1e5b3a2e86e6e7853f8b1929c772605c451dabe2d6c4594639cf8ca991d12c26e15299a2fdfd843179ddd0e0949061ab4559ccbfc241d7c197c0a6ddce2a273461a1536bbf1636b8cc967c0cec2fc8d573366b83de64a634d26650c351d7bdebfef778dd3b4352d1d69485e67
+TAG: cf29592b2c7a260a89a9928f2740ed4a1372736c7c02051523cf74998b9df58c
+
+# DIGEST: d92a6b7991149d98e5e23a68619b06a3f076321a9c1918b4f5ec6c0878636cce
+KEY: 2c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf
+NONCE: 782610460bfd24ba022e6da12dd4c27f
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c87
+AD: 0dc695b814bdf1a87bb105
+CT: 05a8296a8a551c9f66d81d684a0b033d4f7bb77ca9e098d43dd4ae9729cf01b6b29b648ea354a9db71b3f79bf712693bb0b61d8c2a24219419effe600c09350c479d28aefa333cc8f4a63b0a9d0582869ab8b5e7d2bfe4d63b450791a23cb794977e4b25bed039f5e59c9cbb34d6ffa71da565aca1db598019f268456bcff9e4787086af7ee344b9e7a37024b074a8726500e8dde6342ba778cc02787b64673b5151e1519ac1beb8f2ce1cb90f4414088584168aefd8bdca48c14a0d8c915571cf269446fd439ad3bd3e63e009dc1e9e15ebef518976d5374d374e282fcaaddb9ccf57dc0c6473990f7eee08f7a2a7a4023109826d3ff0ad0626a261040a2eead19524b9f3817730c01a1d369ae7b759c7f8a891906152acbd7b3da18a373cca4aec55d0ae062dd3d0fad5c8ce3e572e2f3a993033f3f2b23a2e957abd3505ff90c1196f123a4a534b8a56780a554b3906e221e185d5c8418a732956232982c7f616a4586222d2d8cf59f8e89c43fc425d2f4e8ef0ac39d7571b95eb4dc832f71a389879e4a968b53bb170ee5e07564d
+TAG: 5064288c18e97af2563d11eb6a44105c85b6f9a31c11919ef02749ede759a705
+
+# DIGEST: e6922faa85d6075991d02e503c1573c65bb97e4ff4a967f1f4ec2e8771d059b2
+KEY: 16bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460b
+NONCE: fd24ba022e6da12dd4c27f4372480974
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814
+AD: bdf1a87bb1052c6755a7a1
+CT: 3e21065905ed1059d4da5cefc3739c9e8aac8571f2aa09613674c8e44f98535bcf590fb08e338f122d978f5ee6bdf83ba3eceedd52f494c2d2b108977b25e751cc4c85759b4fbe87e71cbbda138d1949cefc1a351148db731e8684271434dbed7609e64985998505b84cd0c9548df09d92f2d532c6a11a5e71d71807ddacb9f003bfa78c2a8b848f9ef77ee50f1e4be33ef22aecab2a463911c0a8636340287fb79e51abcb14764bc6f4cca469d387422fb4e35ba98381e28a639cc1c56e24a5bac1a81bc7a518b5c151bfda0afa4fabc5baa8b47c901119f087def7c85e924c1145c50d6eb566a6d39f3044d528044414ae4751a1ef59bf7e16c6d1e73fa2d424896721ce36131373ac43fe87f3a6140225ad19481e9b24f05ebf1b33d81f99684343069b50388ba3b7ab463227048829cc974c94e99cebfbf679afd0d40c649040628263be7dc781118a0eede687277311d08200eb968cc385540e981d7597b3557542255dab4de02f3a34e46729fa93c9273282b678aeba9dfc6ab7056875092def2b9675cb212a83ab670d6d8fac
+TAG: 9ecbe4e86c0953c5337793ca8e5ac6b8656f4229eedfca483644251c34936f54
+
+# DIGEST: 41edbb0ebc4f450655eb5a394e9d7b3bbf76bf761a69a1fe0096149595e8f108
+KEY: a49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e
+NONCE: 6da12dd4c27f4372480974454879c41d
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1
+AD: 052c6755a7a116bfc9095d
+CT: abc72086582f0391534a2ed49d138f7244ce9827fd11af1a9cd0a0f2961312f9453802a1485fcb4a5b8d2f1093f7c7fb40d22978ffa446e210d5cf4e56f5ba3b8e2da4216f939cd679e0b60fb1b4bd958cb3b12a707a8ae9922d9b6b2d535e3db301cc23a244444d21c4623d9aa188bb3320ee7a65cb473ca77e81bda0809d4481ec866e05cdb21e4bfdf75af119bf2a265ac13ce7740e74cdac2d7882994c7b3634e3431cc1924a256b9be3a1555acf77395b0781d4223a4d6e63cd7d9aeec7422e3f306f7ea2561d6e4d9d4052a0ebeeab89662a0fc0c19d3a5c58fd88ed2af461354eb20e89caba0851f4e870375d9a362e5b05152fb456c1e2cbd93b701e55ef8c80dc90c72ae873d3a3601aac3e2ee72e1ffff7f360265d6c0fd2f95d82fdb955a187e7e7e7bf383e3dc96bf1823a3ef088545f28135b4d3508e8b9391670c15fae03a94aace5729ebfa406aa5b4d01cc987b1425b7bf515364bbf2ae16d0b31c155f1e337dfd24eb31e2fecd4654eea67ea21cd83b73097b150921dd7587cd0316de99985323f81dcf9f1df646
+TAG: d3d1f6ff46ec7e5892bf45eb795c22ac6bd0d4d81b418491b28b4db86cdd0320
+
+# DIGEST: 95d5f8dec296bdc99a258ebf22984ae9a317b909f128f0c954eb6a2e2cf4abdb
+KEY: 4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c2
+NONCE: 7f4372480974454879c41de9ac9f9823
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7
+AD: a116bfc9095da49db3d71f
+CT: d3115348ee3716a712d242f5d2f81a58a90a583fc64ca3a6b41567ee15aabba947a1656a6d3eed7662a1c005ac2d072616cb6044e45fb56e95f80d6edfff27d1145f077f1583e49e5faf63c374a2bc9808dd50330daaaf5956a2302dbafae641c5607663bfc2cc9aa28d77317cee8d62dde6736c5bd6edbbc2a05f5919ee120ada909968ff446375756897b6c60e89ba2a20df2a75ae527035f910a0d3e94e995875ef5572229aefe769d08ed192d29b12c757e07a34b379acd7c7dfa30f44b00fcd962c98db03ece1bc6ed9e9d6d776a670f8a95ac385f3e9cd5a4152f90f06bc909ab2ca00915287ae2d24d6027e1c5ea8d67694685cbe04f9fe116a50ed9ac8b2e159741bf91cb31a572a46ec71e7e28bab67625b42fd66d346bf83200c7c10b3b0bcef834cb9e2d7886d9a81643a35e08320a51b02890ff44ef4bfd0f89708fc9988074db2150b0bbd0127e6df3f87ac3880b199df28ee8a26f293ce4d568d340aa6ea5c214a602347b1b7f42eef57fcf48e91c3e7069757d17adbff8c46b4f7783c5f74a321984819c703d3e3b6c727ae87bbbd0934204f109fac725690
+TAG: aaa5d7d5db7bd35b965540b1d4058025f2e84fbfe89f432858cece365981e2f8
+
+# DIGEST: 1593e69acc71d6f25a85caeed987c73d9b86e132ec163fbcfca267eea32dee44
+KEY: 3f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f43724809
+NONCE: 74454879c41de9ac9f98233b5a7379a5
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc909
+AD: 5da49db3d71f4b975c5d50
+CT: 07fa4208b12b11a5c469bb547702fc5d9a335721719fa9b76d268e3d8e793e976d26889e67b2e3b124113dae350017038774ef4513e746e51a8a07a96f5288bd8b64e8f697173d484a9037e3b2ed54fb27cf30b93da0d3ea19a5015d6386fe1c33b5c3ddcf17ce15ea21ee55d429cbf359a85ca92a8fd44b23b58898800b80663d2971075487650d7384897b5332278e2437426fdc8f496fc452073445546e5644522ba421511d13a5e600f2acf4c4a1d4cabcd9b3e476be2f85250ae100b7dd856fb6a40b89977d4f3ff88afc6b9cb5043dcb2f8dbe410ee4437e113c8c37735e51a269c3cbb8b7097d5713e1c3618687207b401e3e804e43e35c43158033451e5c072408d184e374ab64d5867a26d6b18bab9567eaecdf237c2850a536ddf34d118202f35bb10c64f74ff70070babc5a838f752b35a702ab30d3d494c611a22d2135f76714309c9124955dde20b7586d97b11537ea90bd6bcf60e81d82596bf4e3e91fdbc32e568f6350d70bc7b06a90266aec00d90b8577fa6ee36b7ef45dc6442cb76830ac57f36e62c88ea7ed1e46e08fa82e3fe5d3331d299eb07cc67e
+TAG: 09f01f78af7b8cdd8093fd4e6aaab65d5eff39c5c0f23857da464252f42ea081
+
+# DIGEST: 540ffa937f22712c877648c744b15846f3bed2a73b41aa1f2080f3cebeda089f
+KEY: 8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c4
+NONCE: 1de9ac9f98233b5a7379a561792c0f31
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d7
+AD: 1f4b975c5d503f478b22dc
+CT: c06bc8b56ff3fede979d7a12a6fa874a94d111d5192dbc81cb48fa05836a0abe8a12035c181cbaf0e7f7848a0d38539c8cdeb9c9d0b4b310d6a98d747c6425397029a576f952f158bb5704c4b422c36127794d49928bc38e7ae54975046d37c94885f06f3ec35f5b9391173330922988ad61b96a9fc6bff85128ddb0951e431e45c34b8b5692c0ec238c7b1995e030e77f1343d26a91a8ca879267a1147ba6591efcff138107f89b95ab5d892e77c318eaf08403f4e41c41d6961a49477a0a80a4a888e9ab63ea1c06cb2a251277be8b90c43b978f351878b71306fa367ee1c6519a9eb63682590a7fe0fb459a7c74794f714b49e0e3cea4c85623a43de766bf0b6ec930d31d44f14d778b6a9bfa5af1fd50fb8681afde36aeb1bfebedba8020bff6475204a6213200491cbc6bece64bed3cdc00ef2bff260529f275fb7a689b08c3da978162f7dd5c7cb31803e79a51e3e79179c2d12570ce3633e7ab0a93c10a8eca72c758ff2614792bfe3ace9bb8b8d21b07d5f574e8e53e7875eb13b1d64cda9426890628b27ca6777536bdb323f8d79c8c40e901d84aff34567c6a51e9
+TAG: e89c9bf6f140d43ba7c9d7cb6f442d056fe273ff7d50f7a98a79d55911ffb9bb
+
+# DIGEST: 03f6fded63d608230f8fa271ee0433ef627e47a84608ac20bcde586dfd6fea2c
+KEY: 1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98
+NONCE: 233b5a7379a561792c0f3116430e8b6e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d
+AD: 503f478b22dc8253bee6fd
+CT: 03116a16f1021bc78f8c009ec74e2c2767cb1620e065fe789065d67edcea532ed06429f9e51901d260b1065c585c112f51f8866415136672de5b12e34a68185cd633d07cef101732805b747d06525d9c7fd15b89ae93a639aa1b35c5880cd21cd66003e6d791667e4a182955b979397013327e10bd71b7e460fcf06de28e82ac025552b41047ce86b455873deb75e9589bda80f4e59243311df20887b494e0dcca010144f2e37d0ab6f5ed3d9c8505a5896972f2d402fe75923754c884d20433ce2dac1835490711d29d4ef9477e5feff2e8765c2feaf85d93f11eaa0b91178255f1c5a440efdbd91581bb9f49bcdb6e72e2ab1a596e56dc189a1d5553f731ad410961d8b3c50390b36d9f30f165fe69a7f9a1f32f5fe9170b547d0f535d946c04af655fd97e8cc4f74c0a297e8f81bdf8bfc9e4c7e0a87aa3c3f58de14b70b6356358dcdaa1f80108fc75a7fdd6dac4ce154af2360a24af04e460b025338c75ed1206db8e1531badc5abaf4c2a4a828e11fc0a58a1b064dc8a06ae5a1513cd40ea94e97dc7d0727500674a913d6c8fed5031def1cf7b8d65d2114b475c08a7f
+TAG: 6ebc10ecfa508c47bf8fdc63944407ba7076cbd9031866d09f68df73f71819ab
+
+# DIGEST: 9c71648f64c8ff1988dc25488cf958444dd430503dd9c13e62297cb32822917d
+KEY: 01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379
+NONCE: a561792c0f3116430e8b6ea058c4799e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22
+AD: dc8253bee6fd1b174c307f
+CT: b53d295076816381b8998800fc201ae1297a3c52c420408480f5459e59d1aa691c56ea7183c67a933ffbdb0eee1862ab02d91a76ac674d649a311e1d4987bb4cf92c414b4c15f4db93d9c1fb3f63ee69436ced61bb8387283cb1ebfb63c778c6cf40cbf4094ca336748f3f74af0b4b8a0cc2187f9150d9c62ff5ed9a6acef6a3e915c978c3880b3601fce0d66dda7b26ca55eaa8094bf60c6b1f87959e3b796edceb47d3c9f53f3da58a121b298a6b244c330318fef82633cad0326b90440910ea950d0b13736c2b9b1878d4fd197e87f51075e15835e5d50b5a0faf8718e8ef3a6baf33f20dcf06691726fa4653c2a9009b0f8da0e86f23f5b286516fb6ef6e5dd9ec5af9fdd723f951a12d209d2af0c8c5ef8f897ddcac1aab7283964e9d57867375422c5e19ccec090657643de4b1c3afdd4a993584253084ef13dbf910908d5f07c1a43f7dbf122025733396182cea3a980ff7d89a3b85a6c9fa1099319f451bba84c6f4cc21b46baf166e06867c11eceea38375a976824eac06ac08dfdc9fb0d56ba1b4c8bbfcad19048b120908a5412a0c4f5f973897cb55e65624c22725c9bead1931aa9fe7d5907619f12d83
+TAG: b5e9851c3484b82a707c89494bea21b6c789c27b715e2ef5c92615e13c433085
+
+# DIGEST: 72604fac954211a22c7f16e8ad09175985a5232f341c816e11e203de02061d2e
+KEY: 9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f
+NONCE: 3116430e8b6ea058c4799eea80abde04
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6
+AD: fd1b174c307f01be95abaa
+CT: 04c8cdcff929f67ba666f02be7da3631013d907e03e4b0eb7f0808065a50f103e8e6700e5b53dbb0b761f3d6ab40b4bd8ad2f33849ed72988b01ddb393e199b98958e47f1e7b1f58972aa2e0a26215fe630f7e0f72410bd65c3dfb8575c971576f87bbb6a473043cc48fc262c91e225f52d15f8685e8345b3aeeeb1a11ff7d40324eaaeece2cd65c936da01bcb438fa0b39bf7fd3cfc7f279d6a6b4a47c40fd557888d21b16dc5a8a74963cc50e805c8013b95a84a637962f4208dd002643417dd9327291183aa96e54bdeaa142a659b04795bb9ee067da62a4ffea9b0a02f538cc404c1914a0e3e28e9838fd51c99d00a585618965d76ecf3ba522e5af64979849b8c0ae2ffb59e06f3263133fdae97fada7fe53e4a6949a5d1c3339b53ba46dc5c5883f918a69411b091e94f7e917b498386579e5e2278bb84abc2c93746d3f76e674754b1e3afe9a7c792cc24d0ab2b7d764f6a85a606b8cbefa2fa53bd38c724de18b34ea7551c59d320ce7c071cc814683e59171679922619e12cb381d1f67961c8d3f1f3caf1c9a003d3f560e200dee9b20b506cb796ef691847b946cf6ebb75edf639d9dbf42772aebf82b872
+TAG: ccf6aee4516b05512d48a1a29f64058a290fca008ae7c24d25d64ff9d944bbb5
+
+# DIGEST: 7fe6e8386faec373ac58fbb0849aa7b9e96d3de86a25764656756970c7e6f5a4
+KEY: 2305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b
+NONCE: 6ea058c4799eea80abde04ee1de13e93
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c30
+AD: 7f01be95abaa9bee585777
+CT: 0d844c44a75fa7296d9a550874ccb1d91b2392507e8ac8598622f586714b06356c2cdf8209eb436b2c40011bae2d7df0fc9f49b41f31a5e19b2852a8b74b068fceeb29a81402ea67ffce13642910a47c4940fc850d35528e12857981202820685f28b5c09df99eba28229b40530a5bd7ed5619c1df49e17a9956d907bbb705a1ceca957ff2bc1dfbde1fffe688f8ac4b399585442ea139749858db2dae385322ccc9bc9a876ed5d8d4bbfb7bf1fd05f4256215cbeabdc3aa3dfd634e5478934850d84f923e539cd2b04812388c20a39a9d2b6bb29531912daeb3009640ac74aae854baca7a2dcb58c167e85d5d49cbd495f6859e459dcfd2f0f45ee8b8f6d1e459820f8f85d31fb8b986794dfb71f2c82100037d35c042c11ccdb3306db789c0ee7bc42fd1f18edb38633327a4d77280fce1ecab059c162fe8b1910562ceb6ad53b62ca03be94c9d482afe497304438e1a27260f0d6f5ade83f4a2b642b10ce267ecd2b9a559028926efc66b2968351acaa408bdf7e24439eb134274f6ba9f945307b7268b494733e8f57d0613645f8d209a5998df281ae0954da6a4144e1c92420478d7dfa0c3440f5abe0f4debf7fb
+TAG: 5043c4bad6b2b11e88393b61dd75dcfd39fa12b6a5f686a9d35c262204273408
+
+# DIGEST: 70f26aae705f690b027bbce00098725716b6be9596fc76d97161047489cfb34a
+KEY: 50d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c479
+NONCE: 9eea80abde04ee1de13e937af8f1a694
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95ab
+AD: aa9bee5857772305daa4b5
+CT: 6d0c5a7dfb05eebe49efade0a2e117cf62a22d0e2ecd0a75e24fb0ae3efd9672df384a771f07261fd479caca14be7befed70eca35c91daf8d36064fff39cc5a2b4fdf5afc3ffe12ec5d6a48883246d9e889add1ef911deb019cb3271e6dfbd255aa0ce506f9bada14e84dad53852476c758b55aef463f8973d314f7deabcffd157a990f0c416e8c03f77d69ad2d78cc13931ebbb4de6a2999d3d836e1177f6dabeaa243f5e363b36d9ad9e4c4e8804799af07a3d6c7de521770df813e96171fe503cf17a09d781b686f32ccd23f3908ca5e854a01c5a4bcd1bbb939edbe486c4875b43f7f21cef737f8202bc7c1452280297805249a1e84337ed8010274e7f4aa09ae09ba5034228aaf20a50e00b0346ea8a6c5d4409681140fadb0baebaf7eb7945019469ab2e9e3f3fc89b3b9108aac707db499d7035311070f7312550a91fe59b9f908c2118de909550a48061f5ed8d1f107f21a80bb2b78590de9c8e350c398122a595a1f11bd4d5439693faf723ae42ed8b0a12cb646c55b6c4e7fc6ec781d2c980ec8b8f313725eb8a7c1bb1484dc1651b6bc5cb287d40062e65f1529be77d09dcfdfe982c459a401156f60dad7c8a2da09bbb7a3067f360b88158fa0e
+TAG: 53f44417b46826d6d7d9cad57ef1adb8d3a37b780cdfc05fe97f00c6415c3820
+
+# DIGEST: 5ce6145c80fd4e7f63dc4dfdc7c12359075b4468193169af8e7f31b8f8116a5a
+KEY: 089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde
+NONCE: 04ee1de13e937af8f1a6944f44d72227
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857
+AD: 772305daa4b550d75f05d8
+CT: 1791b8271b1642fb6bc3d6633b0545236db2104db16a5075564ce219c7aeba4b9e27f81798d34e7d0a66ff26d00f684a70d3fe735163b2e1a6e46e7f5d38608bbb8d16185802f3a7899d62012a73ed6f52a4efd62f6dca83290bb9028634106ddc14e4f392fee05b6c21260a2b5458d5730028ee45ef1424262f455abd1db5318f1e9d34c9578fb06060fa5265a3c0df51ead53bfd248af72ad9bda1508a7965fa3f08ea8527702e5ed0d235cde9de33fb7dd5ad25c1faa52a37414813294daa2e579aabe221078e0e7095c2fc8dac6e5716d928c5a1401fb6e2ec561ef2a2f54e8bf48b6f0e712e2963fa557416d1770aec0e16e493b16bd27b219455a4f6bf7f152816c95d3e8a85b8fa20bbacff91015773362802122827413ee8cef69de068010f9561c89e210f465643d29f41e27d2395c6300ecec2d2f6c655eea54d9a79a1c4cee92234dd982468ea6db37fd32334ff8779017b7ed4b490ae9cde1c00511bc4d022b21aaa16d557d075413d9a5ae43c2456daca9e58f8d78f15c457b5f12e9151f91008bc0982d69d95ab5c6f9ec7fee224757d2d8392c9d55bda6f79e0dd9bb1e4c27d47ed30d4f548084c7ee6ae256fe7508cdf751afd718fcf3d0b
+TAG: ca33cf2863245a7f9c04f6974fee1ea7e7969b68f35828484f1ac0d8399778c0
+
+# DIGEST: 7f4b3991adbbf881a1a3de1d8e814d39e6c0d751ebab74984d41727ce9fa639d
+KEY: 711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e
+NONCE: 937af8f1a6944f44d722271233a82526
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4
+AD: b550d75f05d8089850fea3
+CT: ee470a80d06cf9fd7b71aa1718f3cd96c5ee3290f58c85426b07e0affddc4f84d84fa44428b65e8cb05a3ce7a386dcd4a932b6d512f5643b94c90d50069e02dc27b41502f6729097ecf755fbd1e62b2cadbb6f389c56837e1e6f318258e6cc208688daf914adde6618425f404ef89e9af6679776ea5d3bb30404c20535e4dbb950b25adeff758a1ca56910853edf9a8dd185c44ca681eaabf4a4bae09caa31ea5fc1964821872a1a6ce23480a0ff4c1e8ed3f71a963bda8f64d0d179dc54bc944560d4749f66e95ee54df9ac3be25de9899fc76db8bb54c5bc66052a591298dd27d7b13ed1d88dfd2e0aca05a102c5696a88d17997d138515a70211e25aa0025383e7228ae051bfc89f68863fb223dc666efe883e5de499e30cb4081e77ab05bf0db4093cb2d6ca5a6cac540126d822de4f515016df3af59f1ae011b4aef307841dda06adbb6111630088dbfafe2bbfd1a6506f876fb84463e5c9935281c7c0439a0c26131cee27fb725dbf533fc6dba38b25486303f43f44c42f07bbae698bc56b429283e5edf1b2c08c2f2fa2bd6ddf23de914baa3a2b5392f72edab83c479d7222a1ac836feec63b68a79db9374c2412b594b3f34b23f0c74fd987ac33f22
+TAG: 13de97495934a5e2a22a764da40827bfbc94a9509b965ec9ec6ce014101d9bf2
+
+# DIGEST: 07b2f90bd1fdcc17e3971eddfc2032df2dc44c74cfd6f8544a3072f821cdfdec
+KEY: 2610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6
+NONCE: 944f44d722271233a825264e97704531
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05
+AD: d8089850fea3711265bf78
+CT: 2e88761cd4ad93a5703ed946f30c9250b1af5529e7e7cb156d4c8ae00685e76f382955adf1f05ec381f42d92802be22455f6d083dcd2fe980b42259312854828749bf2b09ab416db35b97421a63dbf6cf482f910d7e520f0391777efd4d321a4f668b203dcd8636376e1aeb26d88d7a4ce3e211d5e70e1cb0359af89484df57f6071aba6c68c52cc95d1a7c92f07c48a84d236910d46d3db4347850322c5c660651ed0a6438dddd89a7b8806f74eeb096bb44346bc5b976a66dd5b7ef0dd62d22abc5ee82935c8575ab52d3d8de4edf3dd8a52e66611987f7f6d44447e6b981d9fcb8e15dafc15f9c04e4f7a064fd7288e51241f6092afab113127cd59465a9c5108f233cd44e7c5a604d7b57dca86854f97956d54a79bbe23eecca01c28eb6cfe2a1532eca03f56e1ee32afc9cfaac142463a0307244dd2530fd98882cc6be9f13ad2ed7b5f2eb81c7904dc8d164094569bd2f6676de58612b72eec7c032769973c603b42083c77cf7c78c7422ff628da3927c78484901e33489406208df2b26d4f67ffede0b04cb92c4073d0ecce60ae3e77c4575a147b7294038dcbd8b27999b113287aaa3cab9237057199fca8d664b7866e379a3787144281d3ed989839a8019c7f4b3c0e17e8453133562f248b
+TAG: b84bc42c5dc6b27a02992f1d33924bc461f4696854aca6b9b3146ee00ef0ada3
+
+# DIGEST: 7092477b3a0860955b93738d9cb5e798ecea0719141d53afd0ddf57b3a6deba7
+KEY: 24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722
+NONCE: 271233a825264e977045318c9b66262c
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fe
+AD: a3711265bf782610460bfd
+CT: 749f7f3e44b1f0cc6af9448154f68fb22eae324ae6d0fbb231c2a8e1a55e55b6431e8fda02c7d452c866a2c8d0ced9d2c6897b5448d3102092c1692594641d4f3a91cadda9b406ce3978a395b2161713e01b3adf5a64145295804d36b674fca9e11528cf895bf1ff50f64d67e84626227cd69f7e4cde2d7af3589560c1867ea8119c5c4d5dbb6071f4d3125a2bd57f5601cb4d662e8fcba84d0c1e7687608978abf605368528cd44d561ad9b82f21ee9ad2319e87be9c00ebf69a9c235f4c676d0ed3fa219f529588c6e4573d5b9a9c627fc59e487eff880b427ce5811d27dbb9316634bcc6f80e24e88288db03f2ba38196b225aec1bff191e4ceb9ba7f91edc1f04bf3c2016c2a32d92fdd4112c05494bcb79911331879ac0035e10ae8a53e3b4dffdf22a51274e329562e1a33773d0e30ccac67e518ef903776a0cf510fc1c644a98f4e562880164840d6a7fc8b91e0038e861304522d830a384ee5038fd2a6d14dbc53d9c6a76aa2738c60dbeffe0d530bd14f669da3bed3a172a38acab7300c107b5717a77b8f8361066ef092a85b55bdb7ebdb2cd55928a9f59880f91731e25fe97923bc5e571351c70ff0ab787424ca2d669772c32cc3d17186d0169497bca1bde695d41ead0e4a01be6c88e2
+TAG: d21986bd2e1deb8c0225bd55a4b0ea5ad54751c534cf5cd373b1f02492ef2723
+
+# DIGEST: 1a48204e7b3e43ccb4aa1d8d8b8a655183c3881f7c3acf851e689884b2773f43
+KEY: a12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825
+NONCE: 264e977045318c9b66262c0f0368fe9d
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf
+AD: 782610460bfd24ba022e6d
+CT: d1dafdcef817b6de6bf74d1e8c8fa5cceaf2bba62aef2225d3b6a7ba6c143341f33e4fd50157bfbcdc1ffdaeb557f5788de931bb99364a6305623e296f0dba41be16f880f0423206b067477f1f29b72e3d145227f2b62aad7d59384d9297d6f9aa8f528ef0e7a868b303c85155eecdfad47e7b58e296a9ccd2e9dbf67695a4d006657f05b8f269d5973851c93f2cc901e34e0a4ad730d6ff52f85d7654dea1af73503c6e3cc5c4eb7f393735914834630e2eb0ab09ab01db7de4c89dbc67d50fdb0bf1af90f7f61afd383adb79e2c417feebefd8e6c7892a43a924fa30c108ffcea550cdc34bcd9f4cf47d1fa0109125e258dd6f560737251244bfe9bab7d4745655179c4494b3a5485ba655b0ca497d51e06158cc3ac875f1d98e708a9347af0fe45025f2bdda3a8dfeb3e8559eb523dd0ff9d0625dda03d76b595e0beb54fb66b38f20810ce3ab983357172807059598114499209be5a6b0802270cf02fcb4931e30e9c94c944885a4ca605621f76d6be63d3303e07cb49da08ac696dbee44c7cfa022d8a056d1848bbb14f7df86de883030dc160cb6e6cc8634459fa15ba62ee289af7c02776a5e22970f95f77bc8a8bb15040aec3602da9ee6c309e59d31c2eaa05919dbefae4272a290aa235276
+TAG: 350d204a9c61ee079f64b210caee89c502a861a8882342b4df0f98b92b9b04b7
+
+# DIGEST: 1c5da35ac0ca01e3557c4cc38b9b48c5c90a8796a5636b7d8f8f339f17bb68a1
+KEY: 4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045
+NONCE: 318c9b66262c0f0368fe9d0cb746bbd5
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460b
+AD: fd24ba022e6da12dd4c27f
+CT: ba7d2738b5dabd283b847d69313bab76f5e35c561cc1431bce28a3e025de2a41922681f06427d97d6e3ea8d6cf28341de217ce62588d2cde3ad4f79371514df90dee87d4f7e066850ff47f91b7a8e37d357be20db7f9a84866febb87b8db828930e4fb4f9107dad1956279fe1a102da6f1112f2a039544bb94dff607e50b1af2c2c7584f251b4f5561eb7dcc66e15ea1e3cce15b0472c2f252685b520d7e78a848d8aef0afae6973092155bbe3dc296d6d4c77eec2049e1438a800c852bfd192d1fccf34b3c7c36c821cadd6c2f0edc0b19f206213e5a1f3b7de53ce54d255db18ab75e649bc0405d852f3312bb03d71c1c76e2695aef44ab4bf153a27d88c19173edcc2dd471f33610b906159375d490131c8b6ef8a07229fe2642e23c19a5a442889c4c2a4a6cfabf6fc92eef75e1fe7ab5c573be927135a88e80ee7310952b58f1341aec79efff06dc18e2fdda9c6cc6d1b0014c443e12c1733195a9563fe3e34caa2e10534392bd777671eecb0fa87ef21925603c9820b5238ed8b07f4a6d7399777b7f9b7a307eb31760dd130680416fc0545f2e1e120a9548c09da0cbf0122bb6a2ce9cd96c9c35e4dd2c255e5c20811b1c40129cf88286bc3cee36f83d57c7a8817c3d6f5ce2e24e98f562beecdefee098f19a170c208b6cc3f0638d0
+TAG: efb40c192eda9160b8b997a4c6e9b4eeb3fa1241c6687fd7f261c4d55e2940f5
+
+# DIGEST: 0593db8c39c4b86087be7188cbf3daa8bb7793b8c4eb3240aabfd91ffa2819c9
+KEY: 454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c9b6626
+NONCE: 2c0f0368fe9d0cb746bbd55813e8d454
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e
+AD: 6da12dd4c27f4372480974
+CT: fd5ba0ff0ebed4617a78938def5cd911ca92712c5b2c941830b99408a94cccb90c90130ed901c94d9477780d0c000f6af9ebfd71566199a51ffd3420b72d0f3404b5c79729a468797639a48f1b8318d531531696b2aaec489306c070d6fa6bc1f00d0956a4b995db24049c6ead0065f28f570a857bf2a78fd8ead6784ec7c2182db92da136a38c6bf0489cc342fc6ddcd1be1f96fc040923078faa8e259572472b9353cd2a8ea88ffd99fb6173de97e45479fd93b6830b92775a7d831dc0070f7292b44a8242df02e2f1a0d3d9415209052f14f6a6c0d3e1773e6900c8e4d18e6ee0785d651f465fc629e4228cf0c56bad63a74f1f4146f1e411996199ecc7058ef56eeb9e04803bf6751bb544f79a9414a4e23ec1ad6fc998a64ceb4d6649946980be065aa274434c1244045bf6494c38d41c2527e7bcfefd97b56e02a88714517ce9e8bc09bd95bcfce333d8365af3ae81a7f925a18af9dfc3d66a3de394fb3126d596edbd85e17d9de30e70adc2049df16d73b7ec3a5034cc6e3a909e08dbc863d69cecff8035f49cce01fe284e5f52245f1ef8bb27f46939372c5d4f7cb5089b3bedf3eb7940442994081f6413716e831362acc732e8f0ad1670251a664ce3db8a32f87a172e77df3ad3722b56d0a40da18139a6f64196334f9a8a0ec088
+TAG: 19927d2ba1e0796124f4d752f084f1c58725b45930fd2d873c4126c8c9019d95
+
+# DIGEST: ff2a290f638f41038a81fe1e1e9bf3835c0423886d264bc60adbdfc38e7441f1
+KEY: e9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c9b66262c0f0368fe
+NONCE: 9d0cb746bbd55813e8d454817c212d3a
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c2
+AD: 7f4372480974454879c41d
+CT: aca825e4559f40de2808ef65930926da912bfe99aec6688bfe17727cf5518ecf004cd88dd52a9a8657924068c7651c64378b763909e06cd3c60fe97c75ea15ec3dcc043588f17ca9cc59b7e85f7fa3bb10bdf28437e9bdc37207c79789033cc97a37bc9fbf31d7084b59a2b47918a9dd331bcb3431cb8a76de859ebced78927ef0d1871674312671dd99aa03a68df7fd62b0d6e3bb96434ddad5361670b38004e1e70e85b4a67912f93f69996c571e0deab051b1ffad32e16b7a5f93092d3f11b32df90de0405eedbcc122f97066e8455e1ac186c37634478e2a1d9ce9b3f17209bfe611ac69efd50ee698f9749d095d36edbe03e7ba5e28dc69a44cbc06bf3e3841400f3ca60bf8032e0d4d09b6d68156ade78a488932a6f44af7394b148e0f5420594ed37eab06f53e1cb266fdd16ce53ad4b012e341f99cfc78d25dec223b30f78b672ccceb034f3f5e0168f5a6287e7d6880ce00f3fb968fc3f101697a126d9e1b39d03bb064bf52ddde36acc2be4e6d753dfa767230f942dcdbed8fe360a9d3e2120459c24274f64761ddeb7934632d900ac60e5f78bbc31c94606173cddf966f86c45d51b69b9bff5fbbf8a7a94baf284713876be230a959347dcc4e1da5a326a78c9c28af0dba48877d0ea0cdcec88cae74ece4ffaa89a9abb6640954
+TAG: 263403c1e8aa601023bc08e4e56e0876908ff7c7ba5c5effeadee6b98fe24dde
+
+# DIGEST: 989e0d1b57528f06473357bb0001d552849b928083a8bd2a4642e72be7dd71d6
+KEY: 3b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c9b66262c0f0368fe9d0cb746bb
+NONCE: d55813e8d454817c212d3a0063be26e0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f43724809
+AD: 74454879c41de9ac9f9823
+CT: 8d0aa9d329e5b0dada9bf8d38ee8a980f7dce1ddc16eb9efd3d41006b2df5d3daba48f09736f75d8abce242dd2911cf80b233530e8d70905e26984b9e392063117f20e92c0cf0f3a7a50c8ee839fd18549ba2db16f724dd3d03a2b8e79877c8b4a213150338e0b1a4e57042886f3982579362fdf5204416bb0edbb8be587a4a2c4ca64ae03cb7306785d2eec45eabee789321ef52b8aadd397aee9acb996da928f5fd2e6f44118a50f0bf044a316f954c45e2b6c17120e873c15cb80eb44d2565609e08644b561219f0c343e1d0b01904db4c69a03a4c00479ccd4f8696579aa601fddc12dc61bc72a40e084df39621e0726b1dab7894c68b4182f3b0ff8c4e0d46bec9744d95e27646904ebfbfa7a8b58de71fece8908a14ddb9157aec0c97327f760519594cf8d0720040e7e27c570dba60febd7e3f289e1f583e721d67ff0d8d5b31e3a51ab68a008abc80febade9cc2023b35a7b001bd5196d9785789b8dc1ffa1fc69c6c10f0eb3eef9e764c1e1a40d26310c567ea8d98cbdd29dbec0df6bcb7b222d4b86941270bebbb0be0535eb15903afb3c5148372e1e616c16f300a6698c983e5eb8fd42dd6816007afe1f42f0d86cdd2ce4cdf0c0ee2fee29ce6cc326f91686e670050ee76b5f6897639d5d30df19e4aa15ae3d0b73d6bad3e870ad95c5e3840e677351b30d88f11a43bd
+TAG: 8e30261054a605d54ad1777b82804210c251870d9a6cce9b3dc5b21a7b7b3f77
+
+# DIGEST: a6924d514c1b926c930a9da2091f42787d1e8111ae5ce12a0292e9d25d906c8e
+KEY: 61792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c9b66262c0f0368fe9d0cb746bbd55813e8d4
+NONCE: 54817c212d3a0063be26e0636617781e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c4
+AD: 1de9ac9f98233b5a7379a5
+CT: f1848c2b876ebd13f307d4a98d2834e994bc7b884b767aaab9e59ea5893a8dfd82d05c3fa9a0a59b8720c29c5ebb01293a30372c05dab5eb3c3d2427915289ab212a882128f584e62e201d10df90bce4202e48511fe41c8f1cf03dd2a843016802b489a10b3b3b0282a684b2162ddb2f9dbb23d0ebdc6820dc87263547eb00a8e54dc9193f3e1c2fdfce901fb36c982865c76b6a49cc2d6132a825c645be6ecc30af67d1b5738f69a4b8e6299440a3c396dcdf70d36079239f5a4f9a7ee28e4765a009324a9091472091864e7773708c1d0610d521a8634e1a6c1505ce79cf8c012caf3d6578782fc374c52dd6b78a5c7fee68ab99872ec8dd4b55858bd48df1ef39d2ef8c6fda201371a41d086946ce3d8daf107cdb5a5aceed9530b40e27a274a31de3688e0bb2fa89b6b3dc8bc5bc146d4fe0b7e565556cb9be1575e7661c43d4f385d571439fd3400841b96723277edea50154b6ae2b93f9040e4c5613690f690f3330fe06b293386de70d3c313985eda63f7f2ea35053b53d9bf8de93703bc5a43930e44a0ea6ac82a102f957ff13a19f42a328e9b5b586433d421b520c55fb6e2f9eaef264931679866a88731d716eb513236b44661b3d186d7273320a6fef5140ec5e6ff32da365ff9d393143a3e4f7e62b9a065313738d437b550cd1694c1b99005ffebc8724d29794a04cd2
+TAG: 157479f16efc49829ad7b25b7a97b0e216c4092711d833e82d4152bbe1965398
+
+# DIGEST: eac0a728eea929714da1c2a7934747811313b16a918363bd291d7eeeb8082047
+KEY: 16430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c9b66262c0f0368fe9d0cb746bbd55813e8d454817c212d
+NONCE: 3a0063be26e0636617781e8591a6c6a1
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98
+AD: 233b5a7379a561792c0f31
+CT: 9ce57bbeec62f4bb724c36bc2fc4da15d2f371e09f9de5cd436f99f39ba84a07959c002ec82006a69f5624333abf264dc93ab263d4202e8a078890927212f68fcbc2850dd569498db53b7a8e24921fa186b1575e6150b1785cc649aa6728ad08a57e6eb1aa1eb95635fee0ed3a689b3131c939e4de3aa8ff479784b10fae712c9d94708a8a4095acae2ac4ffe2685a3d1b654aa3a879683c54df1aaf42ae496d911789707c2b7598e418a8bb4b3ce767fa7d9f970691b010b529d770cc3fb9e5dfb840a9c815e09f47a5f8178e91af1ff10c1112c0e7f70cb9d31391dd7e7002a80774d101e18407d514bb28d5cf7db5a7c694c1cca10b447689ecc00aebde49652f8d8d65368a2f2e8039a06d7660c7f0743cb5e3144e3301509c003e803ca47587afc081b58799952cd17a53a891c6530797e288ff8543955c3011ec924024f7e2a1dd539285075783ddd478d4d06e7c20bb2037a5e9ffdfb5359d85a066f0d23aaf762996d97c15f7e42659395b7130945b62f6ed8c31996ecef0c5ce098c0530fed5a012540a3c4f5b1aa821a5c2a3e25c07d61d95de4d124d64cfeedbc8d1925a1d75a01e9e870005156786181e7c606ba058e29374a45f066cdf3f5b4acb607e6e5cc56c95931438f4f8973b7124cc176ed66b83d398b7c7507cfee916818a34c4627560f525a087f23cb98be6
+TAG: 8f9ce0a655e72b55443984e2db06b61f29cbca726534113013f257f403766ddd
+
+# DIGEST: 8ad5314b867b5272f447c02f6666e53ceb37d99aaf1ee5833e3827cd1725b5b7
+KEY: a058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c9b66262c0f0368fe9d0cb746bbd55813e8d454817c212d3a0063be26
+NONCE: e0636617781e8591a6c6a196868dee0c
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379
+AD: a561792c0f3116430e8b6e
+CT: 02c37207bdef46b95ac29c1f55c4068c5ac406490ed3843c9d507fc562a05bd2e8f6dfa6446b927ee18944d2e6e87521332e0e4d01ec2e1927e89c367e465579b0b7a9b37e32b57d0389e1d313ea25223f4b2d93fda46c87ad9c5fdc180c031df2c43cc53458322ba003c3502cc4eb19ac388e75f2eed8e2d071a678fb9d23a187644ac6e7e1ba36af68225950fda501a403bcb8d54619f4bff98e5b10d68dd74ee86944974d1142b87fec029d34a2e7c35c02b14b17c396f60a07f6a9676430a7745a90a223243bef3fe7ff6b555c40c93aee082f0285837a3abe8afe704b80862f59884e1fb71d3e7906dd33e951d93b6827c787d6c8666d0a56520f9d1bd78620ad0d806d03ce996e5b84e019877a320508ecb30088a09abe023a92b0956ea61020370f8df95c78ab2d136e18877892e7ed1da39a40550f561ba041b5c35bb82631dff76e8f5c4d3cdd2c8b3dd3d49874219ffdd6c9441190d71e2bb52af177a0961c120a68c81bdacc4766d7c0cef8bcaf2cae6906571d3bdc5c332a2bc81528a1529d0158af7e78fea2023f3b69134f54490a7a27cf1a6239e99fddd09d01f11f6d3e11a9a67d4233d9e4f6f26c3e065096276b59904006353edaf40efdf9bb77112c5952ad0bfc8cce42a2e4348b41530dfa12bb993fc19f40766f843d3428f60be569faeafead6a412187b320
+TAG: 07b01b5ebc9c9b6aa3ca1db3b26e6e3df8db6b41f774220ec075286a7e894dbe
+
diff --git a/src/crypto/cipher/test/aes_256_cbc_sha384_tls_tests.txt b/src/crypto/cipher/test/aes_256_cbc_sha384_tls_tests.txt
new file mode 100644
index 0000000..9f38bb0
--- /dev/null
+++ b/src/crypto/cipher/test/aes_256_cbc_sha384_tls_tests.txt
@@ -0,0 +1,840 @@
+# Generated by
+# go run make_legacy_aead_tests.go -cipher aes256 -mac sha384
+#
+# Note: aead_test's input format splits the ciphertext and tag positions of the sealed
+# input. But these legacy AEADs are MAC-then-encrypt and may include padding, so this
+# split isn't meaningful. The unencrypted MAC is included in the 'DIGEST' tag above
+# each test case.
+
+# Test with non-minimal padding.
+# DIGEST: 2e661c639db0b3d4e89d27c55e03361e12fab46ed2e8c795f131ead30d185257790e87bcaf3af7fa0399583386f12648
+KEY: 86d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965
+NONCE: aabe477e0cdd46be99371eb8da7dac99
+IN: 936a91d0b5
+AD: d2c0267218cb7090c61713
+CT: f6f8de8547cadb667c8c823a2ff44444bdc80dc7de80e5faffb40880dcf4d20f
+TAG: 706109ef1d8fb6bed697545eeb0060e7f680d30dd70e8ecd3135b7e01e895983de56fb0889a4ab0856040dba57e94dcb
+NO_SEAL: 01
+
+# Test with bad padding values.
+# DIGEST: 2e661c639db0b3d4e89d27c55e03361e12fab46ed2e8c795f131ead30d185257790e87bcaf3af7fa0399583386f12648
+KEY: 86d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965
+NONCE: aabe477e0cdd46be99371eb8da7dac99
+IN: 936a91d0b5
+AD: d2c0267218cb7090c61713
+CT: f6f8de8547cadb667c8c823a2ff44444
+TAG: bdc80dc7de80e5faffb40880dcf4d20f706109ef1d8fb6bed697545eeb0060e77a4c251b2e25daddee81248b6d121fa2
+NO_SEAL: 01
+FAILS: 01
+
+# Test with no padding.
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb4
+TAG: 8b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 2e6894abd3cfac4d4020094d02c6db6450cb7367b405443de9b5f2ab444b281848ef5da3aed9ebfc054ae89af094ddd6
+KEY: 7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN:
+AD: 936a91d0b5d2c0267218cb
+CT: e07fc15e5084da35f900e19d1ab465f1
+TAG: 26377a5cfd21b371f35b306ffd88cebaa7267ae1e2c3e62211515f30ecb95e7fe761b7f32805d48d35241b1d9b9a93e9
+
+# DIGEST: 2e661c639db0b3d4e89d27c55e03361e12fab46ed2e8c795f131ead30d185257790e87bcaf3af7fa0399583386f12648
+KEY: 86d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965
+NONCE: aabe477e0cdd46be99371eb8da7dac99
+IN: 936a91d0b5
+AD: d2c0267218cb7090c61713
+CT: f6f8de8547cadb667c8c823a2ff44444
+TAG: bdc80dc7de80e5faffb40880dcf4d20f706109ef1d8fb6bed697545eeb0060e7cb0235c73088a4372494ef1ede2fa37e
+
+# DIGEST: 092a3b893bafcf87b7b3b2ec7908a1efee91c236300f1928de92310d85367f42dc69d5f76daf928b61fbd54175533fce
+KEY: 97b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0c
+NONCE: dd46be99371eb8da7dac997deafd64b1
+IN: 936a91d0b5d2c0267218
+AD: cb7090c6171386d641b877
+CT: d68e00dda368621cf582bbb17cc62f6f
+TAG: 149cd5f73f501c206107166a9726c58a0a18d1783fdb36dcff34b2923a8ac10d579872c25c4543fc6fa3375be31447bf
+
+# DIGEST: 36c1006d8e570a433eb4515f74150638e3e5c1be4d453e5d5369c9446e624a435b1f361338b18d12dceaaaac967fab59
+KEY: 56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be9937
+NONCE: 1eb8da7dac997deafd64b1fc65de39f4
+IN: 936a91d0b5d2c0267218cb7090c617
+AD: 1386d641b87797b684e0fb
+CT: 56b4fe5ccf5ca048b668a1365ef3a6c1
+TAG: 972ef78e87301787e84101d562791d350554781e3ead0c8546ec7155b824a7a8d523dd723a2ba7ef9334d94a14682fa9
+
+# DIGEST: 724b8f16b1df651c74c7c73853f6011019704beb631f7c4751f80a5d78846f16726175a5efeaf83cb43090953a20a456
+KEY: d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac
+NONCE: 997deafd64b1fc65de39f4f03541a11b
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b8
+AD: 7797b684e0fb56f97c3961
+CT: 9da9a98c18acb8585d11615ff6fc6847d59901984d480cbf18ce0130187463f8
+TAG: de01ef34ce36f20e8f352fa165c1afcefb9be6ea181356d45d3881c55a7de88b74351892d27252a30110a4b11d3d994c
+
+# DIGEST: eede1c2c5abc64d35974d1be71f5571767153cfef11febb6f46651c96086226cec242ae16ce801b2c3344da32e14c466
+KEY: a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64
+NONCE: b1fc65de39f4f03541a11be112a72933
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0
+AD: fb56f97c3961d8afa22993
+CT: aa10f163502c489d9d4e51893fcdeb213182b10f5741b5df08ea79a1098ef810
+TAG: 05ee2c763f2370c6a93ccb063f1bdf9ccf35b9db56878c9259e63de9a3b5e99f73f026cf640ce02a70d4de77242317ce
+
+# DIGEST: 602445ee16815bd5392ffb3739fae82de0d336c2da1ea38076c0300742c200065ab4a3a9a4a64c3274f141fc41246724
+KEY: 89c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: f4f03541a11be112a72933c7b54ed4fa
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c39
+AD: 61d8afa22993a340b9b3c5
+CT: 1d76d74a882c23d4a9c2f025d99239bc6382457eeee577bcff70289da0b40638
+TAG: 4628866a25a9b09faca5d6ab13382433a0776fb58c2c2a82bdf47fbc3faceeae341616c49e2ea2eb2a46c23916f78a33
+
+# DIGEST: 3529da9f9caa827d9e1f8d3586ae1186529a5e00a3bf1b38f09489ffdd866665bab48e5f19d0f2aa748644ba1d53dbe5
+KEY: f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a1
+NONCE: 1be112a72933c7b54ed4fad0be905d41
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa229
+AD: 93a340b9b3c589c7481df3
+CT: 8c486099ddb7e81637f3e7c80af6b1212a140f56ae463ebcdc4bf6637994b9a5a7e87e5ce92927759b7465f8200bd112
+TAG: 4e77df3d100c811d87b821d6d237579d17f8c362b8db61254f65b14ab785c4c4fc993e3f7717a699eb6c5ad9282c7f53
+
+# DIGEST: bddcf50b5ead03c14d5feb8cf3017f3b0e258cd7f4bde1be196a5fc09855dd29d7c6eb11f6df8ff3ba473bbbd69a8ae7
+KEY: d8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a729
+NONCE: 33c7b54ed4fad0be905d41203f5dce99
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3
+AD: c589c7481df3f4183aa23f
+CT: 87bf1af7e4987cdab35bfe32adc6b1be286751426cf926217f2c699bc095bde786263b6b35941d4767f63f7d2458ec01
+TAG: abaf22bfd3d5505beefac1cbb6eee4519189f0bbbfe0f2725b072057e5e7269538b1c172423b7ccc7001e42897c85ad6
+
+# DIGEST: 6565952b26fba864a3e99b6d81a2ede01c38946598db1a961ad8e50b935be288bb37cb096c6e7c9f5f9015ca7705955a
+KEY: 03f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4
+NONCE: fad0be905d41203f5dce998f8fb2eaad
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481d
+AD: f3f4183aa23fd8d7efd885
+CT: 33ac574b7962d03b7816c0199a7f661a485832b9023867a749fc4bfe8ff04855ac66ecca8ae54c2c256d4efe5d116bf7
+TAG: 21858382c16802cda3a2b0db0638f4e3f2afd4cdba1b03c9edcaca3ad0386854b3a92f5526333f86d4f857737b42a752
+
+# DIGEST: 2d19661c55d455c6513f7b0cabf60a402ae67e747af58c45bac1c01d0e10a085b2977ad0abd58d510f62191aa4b4d66e
+KEY: c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d
+NONCE: 41203f5dce998f8fb2eaad409ae02116
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa2
+AD: 3fd8d7efd88503f78b8ed1
+CT: 4d754c684658bcc89208bcd75f24dc8e18b70a28b8a2201535e60ab755fb20e1ddfa98742d257eadd02d96c6a65f880db80453bdb1edd2983e1c802d8e5ed8f3
+TAG: 8ac85b9ca5e7d67db2ea075d59fc395a4779fdf4833d23c827d6b9f523f1bcb1f2343a7c4d77077d1e2b6dd7f70a98b8
+
+# DIGEST: 8dce8d23600bf08b71b5464d66cf287d688c91871d3b91759e1eaaef61f60807524d56db5dc08caff97f545048c5d460
+KEY: 773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce
+NONCE: 998f8fb2eaad409ae02116417dae0cef
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd8
+AD: 8503f78b8ed1c8e9ba2fd6
+CT: 9b51ba0eebf72bbcd7a1b8452a49f30bf2d96bf0cde4d9e5efe7f1903eb4e09f53aec649c5a8ad7e7fc6c28a0dcf4bd386ffc00ba6ef93b558a113009bbec2e5
+TAG: fa96245ef45d6fb921021c825d4c4241898294222f83f383c67967dd2b5ff374902a0ebf5812cc217e34120f0808ef98
+
+# DIGEST: aa1173284085dd18a864d455c478a0808ffa5a51e9a3db362f3b7f8109ed2b47e8111bbb9cf56475f70c5d8e5bcfa423
+KEY: 2a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2ea
+NONCE: ad409ae02116417dae0cef457b9e5e16
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8e
+AD: d1c8e9ba2fd6773e0d0c30
+CT: eded2db8c302b3b5b5b0c0d556f8d34408fdb2af75d38231049b5f91e02a4086e6ffcfabcba5e3ec68173dfde382a41533dc6baef8e3b080c6588f6142285d1e
+TAG: 73c1c1742e869f057bbd107ff6db52ac806447f99bac975fe26f4d5e52615921fd774649ef9dbaf15f3ac36625dcfa2b
+
+# DIGEST: 00a674085cc7557439f1cc93ce5b8197c24e5418aa78a94942e5bac44fd8ed76bf4337c4c7f5aaaa0a26abf8892ab859
+KEY: 446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae021
+NONCE: 16417dae0cef457b9e5e16dcc5b6f256
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2f
+AD: d6773e0d0c302a5f47e037
+CT: fe6540372ad1c40ec1dd644e935c480b9e34aed05a7f21e2e37dd46db52ebc5352cbc3be2aa289cc2e9712aa7d393f4454c9fa3a4acc30db41ada1257693d346cef433d997bb724f8c2f7377cc1343cc
+TAG: dbeef907a443bcd4651ea570db81b17e79c3b2348398b4e207f9ecdd0cf291f025ca2a4a7d6be9014912c45087572ba6
+
+# DIGEST: 152198832facaa26bdcc0ed689326da3b034c2eb9bc98b19071a7069a0d5b9cf9d2ffbc923ae89b624ec8c28b2774ca4
+KEY: 7df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0c
+NONCE: ef457b9e5e16dcc5b6f25607f00d033f
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c
+AD: 302a5f47e037446f5891d7
+CT: ee9fa11a7d6f965e7d65d8f48810754770b9d237ba0111978b97e24f223817d0c6ce4dbde85c4e0979bea607a36c66f908c25384184fc334d8d985b78c2e9872012bb8b0cbc01f773da5c198619b9dcd
+TAG: 93bed62403e6ddfa8cb92403b68720cd50df9a37a501f0ce06c68cb8a1ea08c1f33820f9d80d490b5a15c99e471f5ed5
+
+# DIGEST: 50a58f35a44d0768ad0398b3b64d6e6d30a04ad203d3e2c215be5b92ed72677147afb1ad12af6084e4210dc28d52491d
+KEY: 933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e
+NONCE: 16dcc5b6f25607f00d033fb95fb09e4d
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e0
+AD: 37446f5891d77df660ed82
+CT: 90712d5e3edeed5000c62ce80212d41773a393792a3a8fc62a1cfbff38b3555aadd88f0e36f93c8a12897d7779972b3e42978cdf85da7a3ba2e4b261f0a0cf4e05603cdbc04095b2a6ff21518f0ae74a
+TAG: 20c1bb6f0e3dd7d8682828145162219c47fec48a78cbadfaebd4b6188ecb4cd80a13614e9c9b7406732c775c58f27b8a
+
+# DIGEST: 40d2122714f6fcbfa15931e2443f2dedf8252679669e312c6dbab6ee751c91bd5306d9662bec797acde7ded03b2c1cbd
+KEY: c55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f2
+NONCE: 5607f00d033fb95fb09e4d00d6172e78
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891
+AD: d77df660ed82933f62be8d
+CT: e59fdb3d1413cd6a1098b5daf1662c698076996e2581e11a286e5acd6f29d41ff9d04da8308ce7f5defc52be0b4d1ee96d8e5f4eddbdd5fa9894e7d1b0a1bed483b7e7549e1c10cf5b8ebd1e7f1177970cb1ad2d4aefe88126e3b0bf35de4db8
+TAG: 872f628852be37a1b4286cdfe937e78126f468edae5d64f31bfde5becebf4ece2f5e424bc06f42898af9788f714ef582
+
+# DIGEST: 28c82ca9530a157f21987e088143e7e69f28e36d8a55e0cd51fe71b23059eaede970e9af88313a9bec28a8a7be640720
+KEY: aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d03
+NONCE: 3fb95fb09e4d00d6172e780ab8b70043
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed
+AD: 82933f62be8dc55b436965
+CT: 8a1448acbd769e42bfdf00ddd801153db3202daf5ba7997890f5f42a183d3a66faf66d899c7099fa99bbcf5b62b6adcb6ee87fafdd0275a8f625f3f959b0ea9acca88070aa9c61141787435cd60f63e2af3a6879002e74373ae31da657180cb0
+TAG: 164a5e06f18e56bf1a9f407b8cafe021ab9fe037b9a3944b0de4947d6beec26b6050318b38e01fbe192aaa329e87e98a
+
+# DIGEST: 727805e6e690197085180c7542a13734c51d5094ce1151d07c9822bb87824db4dbcfaf1d3a82ab01aaaad212246251b9
+KEY: dd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e
+NONCE: 4d00d6172e780ab8b700433a957a741c
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be
+AD: 8dc55b436965aabe477e0c
+CT: 10ee64784345c076e3f9aaeacc87cd51d6ee0b0facc9f40b4e6a1b4bec669ac3c5252c948b0c0a4d8e798248e6b10ee247e51c81793c2be91aa8c9666e0d8774439ea159e4745014bdd2e9f379ba461aa21a551f5da619fda09770a8bcca234c
+TAG: 0287336785ea986534891414bc9b72015a8c11d9add3cfac3f33f0fee6aeaf6d281187a34c6a8a893603182fb61583b9
+
+# DIGEST: a892f4fa9f433250e57547e5185cc0869d4fd336aa7e1112a29c47795db1bb4fd1b6566efe76006be971eed5977eaa46
+KEY: 1eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e
+NONCE: 780ab8b700433a957a741c9eb80f2b02
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b4369
+AD: 65aabe477e0cdd46be9937
+CT: 9c61bfbbd3e8395be166b30a56b3e192748ba3bbbdc334dc3720206ac10c90dd777aa4957695bddaea0b7e554951c94f2f74a2bb7547ac20a7e357fe249614204401144fef61394c140553d5566c18de81fc52a5481f284fdac02528a32970eb
+TAG: 0fe5ad054fa80b5a33ced5c6b9d870363d50438ebafde87e43f7a5238af61827b1c8432f6dabacbad4dc8ba4c8e6b8ac
+
+# DIGEST: b02aa6365f90da9c0088a2a88aabb9537a471a8124fb9b94ef84b3c5a72d2c884cd82669037d7265fc376fd97c6e7c2d
+KEY: 997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700
+NONCE: 433a957a741c9eb80f2b021b1444769d
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e
+AD: 0cdd46be99371eb8da7dac
+CT: 997bd62c118718ee23b9d75f5ad15bea914cace8858ccf9534ffc79a626768802f7e86930243b3dae80d38782a6a61429cf0278d37bdb60a0ce3ea74163ab77eb299285efafa2895fac6d7f2ea65b35e579e07a7a6395e2488db288c415b402a2006ad6b49a7dda0ffdb3d235db98180
+TAG: 26692ba1297393841d79cf2ebbe97a2db3c9c7908c7fe177f82942142a4b32bd958d5f0001a9a4437329afae6d96cf51
+
+# DIGEST: a96f9b4eab55a7fe69cb820841d5002209ebc9fef382e07b1f552b29a972273c6594f5320c80d5d7be9a68c2fa3ec941
+KEY: b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a74
+NONCE: 1c9eb80f2b021b1444769da00fcfab0f
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+AD: 371eb8da7dac997deafd64
+CT: 368ce97b3b9c28678363cbcee49ac8474b6a12ff63d783060a8cb33ad951edd059260c4927d5bc2ce252b4deabfd902ec1025a8847bd6fa57324d1d8cdad0f23aacd338c8162f77024291f106dd73b1dba3746e7a8dc3c3132c6edf1367aa57677f205ba47ba4fde712666d3032daa79
+TAG: 46089c4d2eef7ae5634f00ff88aa400b160e17a593946bb97e2b6214262c28034b1d72c245029e8a96ff76730bee6608
+
+# DIGEST: 03d8f617ad8dec610ec4b0a7d8f87ea436bebfca15a6890d7a2796c2b8ccd7708be719711f72aa620aef65286c87d3cf
+KEY: f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b
+NONCE: 021b1444769da00fcfab0f5f93b51106
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7d
+AD: ac997deafd64b1fc65de39
+CT: a7a27ff44599a6263753294a057c527552f4659590b97b9135c74da778a88607d0781df713f4e0d72d044f0c2c7daab6fdcbf162cd700d236999e29c25be1c599b5b5941c774432494b848f6d862da9f95d28d132c7333a4ab436d5488466ff8bd7436f2246165743a8bbfc1ed4cd7c1
+TAG: 653851c2977d8a09609131f192f60560a73bdfafe24efe29ef851702aa673cb242f47fd516ec07eebd46969096d463ea
+
+# DIGEST: bfd2138a5e4adcddc3973fec3232ff0c6313375e74235e067f934b1a8c5e1c20625c7141b19d48b858093a3655020d84
+KEY: 1be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b144476
+NONCE: 9da00fcfab0f5f93b511060c9c5f3aac
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd
+AD: 64b1fc65de39f4f03541a1
+CT: 26084337bbba564153818959e07afc3b13632b7f5fc304979d073460eef46f853152b9059990e582b700e8cef904670514026d4a62c34f77ad6f614a9a48a0abc3be830ec88eb9cdcb98d441e70f1c0d389bb9e9e7517cbba7b2fdf43e115aa556429e5a91a925dd9d4b1af3c9ea8df09401cf054093e407837e8396a6a27ec5
+TAG: 2344c4e128bef713234425a47bb4a6785ef99a776844e8e6057da4341aba629ca58c7ba57adf1b133fcc4861397c5689
+
+# DIGEST: b43b53518e1a7ff3f5bcb64c5494d3e8ffbc433c37acfea1ef7f218028e424aa45359e02c4e5b99c5f0cb41d926d0fc4
+KEY: 33c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab
+NONCE: 0f5f93b511060c9c5f3aacefe61b184a
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de
+AD: 39f4f03541a11be112a729
+CT: 3210ec37a258006ad6ad1e65906abd6f74810eec72d7ab162703aaf18d3275d4272a1124d4da1be565e29eb1673c5151762bde617fb2279ab77c8a376670622c5ab068ed36719969baaca7d42ca0d781dda79230d7af3e05cf913f39e5b4e93e99e5cbec9988d7179b621a13c78f0f9b806bd327a953d9753abf97d7345a0056
+TAG: 58030cb4a119d4218a1a3c9d0cd6ce0d376ecc50f18adf4da6384e6b92e6f8eab1af0f61678ff882d388e422faa93012
+
+# DIGEST: 2215160f6bc9e5f2507dbc4eade16c5b0fd333c504b2b8eef1ae8cc76419b72826baa82c03ba29b3b7d17a2d7d509b66
+KEY: fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511
+NONCE: 060c9c5f3aacefe61b184ad2463939ed
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541
+AD: a11be112a72933c7b54ed4
+CT: e51ceb1ee67c681952d48022d3ade08d04bbd85f2b609e37bb52b2a0a43206aae01e249c2c7b30ecfd28f78add255b02691a15c660d28fc76eda5ea7971c8b11ca995b338251124a12e7ce550a5e692ce2b0248b6982823a22305c7a928cadb23cb9f14c10d3c006757abd0257361b44f4823280987701c1f11f60df27bf1200
+TAG: e1b8167076b76934e2950bc661fbc3929a5fd75219a93209711478f827ece871ea523d396d1fd5e92c9e904eb0a2bb30
+
+# DIGEST: 2f2f9bc024a04218f1863efcd195fb4576836915ee658a38d3da7db7ba2e535e452b309b381ca5105040017b0a4d0b12
+KEY: 41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3a
+NONCE: acefe61b184ad2463939ed518ce97c3f
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a7
+AD: 2933c7b54ed4fad0be905d
+CT: 77b4e444d271670653f04d99105b36886383a2853163a47615b431eb3347fcb7e013392376ca0c7bd2ba68e9b3e9e8513c783df10c1e71650c952c31821db41a509b7163f509f1445ec13f31090fcf566b69f6f1c5330ab588eea6f229025409c4b749edc4e22e1f4612a9dd9df978e685e30d6c27a8f50d7063c73be06ba9e85fc8a15c86236a1519eb952f87295688
+TAG: ae78628bcaf9984c97193aa897609ba6666c3d50c39f7b20d7cd92a672018369ba7973806b46dc616eab89194c6aacf5
+
+# DIGEST: 20a22396a997be31e1bfc48c6599519cc1362918f955976a90e0c9303a61e95c80af563819337001c9da724f05c1cba3
+KEY: 998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b18
+NONCE: 4ad2463939ed518ce97c3fdd293d72af
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54e
+AD: d4fad0be905d41203f5dce
+CT: f48adc232363a0490e75ff78e4071f299eb70eccefe5e2b93a5e223e2521a266d9b5f9f2d6ee01c1aee3e4b85e71551c8d22535406146d9561eee1ab3b3ddf46cb55cbe4f38d309da8c71a508892f19a86940101e191d0b2fedda544b64f5baff9829554be885553500f09d707357c4cbbc7fe96ecd36a699645d5257f71ce7d0f1defe3a0db65dd2d4910cd800c9837
+TAG: 702ff168bc6fcd623f65ba01cdc6424545e12e9936d87979a83200472ab1e18c463c746d44333288d557815f9b0c3e7e
+
+# DIGEST: 95f818eb95b73edf2473f9c8ba94a6db66c085bf46bd9fa44a70705148e60e30688f65818126a70dfd4f3c26d2a20a5e
+KEY: ad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939
+NONCE: ed518ce97c3fdd293d72afc09ffdd4f4
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be90
+AD: 5d41203f5dce998f8fb2ea
+CT: f4cbe7ed67750574ab0716367351b71575476b76987a082de8c92e79861d945779aff8e89905bf3c9ba0bad99b8710fdba8298510063b646b4e1dda6ab11890e6cb30350d110c46f954f3bde6738828d339c6380b5008ae314ff09ba49dfaffce583400765a52af8970ca0e542b963219c0cf6c0d627b68df25ae47e1d81df1d26d670410d41a87b9a8e67900c9a3e5b
+TAG: beb14b0645b8990d824180606057e1953ee69b74091ff3da651879021d1b830090236d41dda89fd4bc21978c0c7b439a
+
+# DIGEST: 84efe380cd5143cc075e7c1c75d3ecfeea9ed121f1d23c950fe4a27fa0d63c1a4450fc58680421f0e582a82b87f323a9
+KEY: 16417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c
+NONCE: 3fdd293d72afc09ffdd4f41963249cd2
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5d
+AD: ce998f8fb2eaad409ae021
+CT: a96cd704bd0516225a1ebaa7b4624e0e368aa56c0f75307802a3dabc6ec6c767a9d00769d74b48f7f93a3d5c53822e2dc8eee7df367345adbcd0516092af64ee9977e0cbffd3d2c631afff977bb14909d3859c6abb2a48c14960f1c99da2c6efe025201a7e50c994f214e67c66d995ca58ea0ceff350c9c3d6ad5276e56804d63ea4b80073cae3cff6b8f236faa26f93b448f4a2097c0523e667812b8497fa17
+TAG: 5c56d4c4f100bef8296fcd25c0b9709dacd538aa89216fbc9587df7a0d321d0c46adc3383c59841cb13258270418ac1b
+
+# DIGEST: 7142482659914e898847dda0bf181e0736f21fd345aa7fd52e3c84598d0379f68812d4c13b7ece54dac2170ba12896d4
+KEY: ef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72
+NONCE: afc09ffdd4f41963249cd299b92e55ca
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2
+AD: eaad409ae02116417dae0c
+CT: d2b2a4db33fcfae2c6ec8cce4e5856333aa8fe628b522ff9e407f279e64c091634057036ba811354b902f72f039a509a585aea1a5b403ca70cc2860d64c487adeecd0002817cafa85e73b259f5cdfb8f2563cc767b8f32b2bbed0c4eac259f351cb81548918cb8d8bf7450bfadd0fdd0d0b880f23256a80eecfcdd9855b0b9a0f5c820bee13c40c002909d811e428ddc15496ec34c425f7b3613097061c75caa
+TAG: c1e2dc213bf62c382aca74c3e4d488189623a7e933779eaa3e7301ef6e8cd95b5e1b74dc74a00d34f44f6d1ab26acef7
+
+# DIGEST: 8ba8bc38fad5d199b53a50c10ce551026216a5a2242cf234d54cd7641ada792e4c95598585e08be84b9d9ef6c27a518a
+KEY: 16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4
+NONCE: f41963249cd299b92e55ca24d8c078c4
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae0
+AD: 2116417dae0cef457b9e5e
+CT: 92f2af21175b4820901ab086fd9abbf8ac6bbdda20a1d4dba5217fb6f325940bb90fb6755b09ebcb54283f03795eb74f19efdd758caf83c22c8d2f9e69593a255fb96646d3b7593b3e4682ac2132e0568d01b516ef3af057faacf4fc90b9ed42728a91f28fe91610c275906a1b6bda159562f3e23c4658e40e0d3a3b6e955ae014eb538a818808f062a67e6f301e01458d069f3e5a12f7fcf169b77d037696f5
+TAG: 178a99714516c4d96347b1c2339a5d9c760542eb68ac315b2d86e61a37b9f3bfe562d34cb3a5ab3f55632e33c1ac2739
+
+# DIGEST: 00a1663e50a85a86aea024b2befa6fcb0024b9a4ea13ba4601498cf643508fb6b0a42b42f0d943db4a9bcfdb7cc5f9f8
+KEY: 5607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249c
+NONCE: d299b92e55ca24d8c078c49f78c7e713
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae
+AD: 0cef457b9e5e16dcc5b6f2
+CT: 43daaafd62f3733ee7805bf8cd9a7189eb1343eff0ce3f2cc2aaec323899f676aacb0a22bc44317eb9cd1fc8ff6d98c19d4b00ddab897d600de8c07d9993fa221ccec98977addf87f03fb7883cdd704bf788a5e9ff04775d3272987afd072cce7ffde5739754d7fb6b449e1d45523cecdb039e8596b7cb22467750ff04722deebfa0ded35c23ec5ec46f40fe43eeebb96ffe0090006dc0d631098103ee773598af969ba66dc318012d2e492ac637df12
+TAG: 00a94d598dd7bd774e055c427ab60fad7bc33ae5501af416b0f47b49bc33644f10d18a2b3fa846133ad589fd0ceb1ef6
+
+# DIGEST: a01fb73d01170adac67ef90c6b6ccc87e453df811c42f66405621e0997ce6a25def0328d6f52de24754a6bd4415d6c1f
+KEY: 3fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55
+NONCE: ca24d8c078c49f78c7e713710a025cb8
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e
+AD: 5e16dcc5b6f25607f00d03
+CT: 8de1f281a40131d37e88a68372e39f5c89e74df53a9cdc6d9802878667985ed45a6f200e8207a53c4c95ed03e245adef990153e52a7079bc94a8b7d6127a0f03b94ad68227a79ed6d1d642bd8dba6f5a8614a41bdb0256222fc02bede6bc1c9caad38d4d27bcdbb0e49b2dbaebd1ec589f56b5523c9df3519be8ff4808836a228b46fcf021f4a248ae5b05c8f2016f7cb8cbe88ce2971d52c782b6357940f37d9ceb93c11ac3a6f0b72750c79a50d793
+TAG: 88f4893efce52add5f877e27020095d0227e0819721eaaafec768eb044ad71e6bf2dc8c36e4c9e80618965f366f81c9b
+
+# DIGEST: 738648c6f3306223c77ae918c138182d983425dbf3af16c2d4839ebf67cb2f2729207dfcabf1f7124a53ac06cd312bc8
+KEY: 4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078
+NONCE: c49f78c7e713710a025cb8b9d71d2989
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6
+AD: f25607f00d033fb95fb09e
+CT: 06f47b618e70d204b9a2081eb0b48fa8e006088d69ab34c7f6632e23c0c4fe4033728dc89c88903531f6315950b637475d553d0b35f369c7d4df7d1558fcff67583b983f6cd858dc2eb958bfb2ebd3a2632da37ead5ceea92b8b49faa175a9192054e27eebe05fa871d07cedea8023a8794f71cbcccd82f3e25911b95b432af1e60803704175599b2e7b53918c0670dc08d3b220bfe007df18972a09cda4d55e4c1f5043ccfec22386c96c538523fd3e
+TAG: d203386688981c4c085d444ac58edde930f5f1cae0ab26e2038cc4547a2b64a7c99eea8425970d8acfdf61aefa53374c
+
+# DIGEST: 9c7178600888bd363e7a2dce613caede33d56168d6c95b9eb6733ac17a700884b02b79380a1f847b85f1078c99da67f8
+KEY: 780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e7
+NONCE: 13710a025cb8b9d71d2989ab33e978c4
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d
+AD: 033fb95fb09e4d00d6172e
+CT: ad3cc5a9c59067452fd219bcf53d99d6d82866fda051b69ba1d83e6e671b6de596aad44b6f22f1dd898a1e8e40e74d8f018e07c9e9e73912a94d9078392447a6a4d0c52808933983b1e668b39790bd65926e039cd54bff207ec74af8ef77ad33a897fd3677d5442876365cf1f28d88b6525a00c5c81d0125560fc6f1ec3ff1d15949ef1c1e828ed4e4ff00f27e61ce0c9cb9e9fd4c45cdbb642ed4ae73077b5f05ebc7c8e83f6722a6646acd5d51665a
+TAG: 077356a8e26258c388d85e08441646c5ae94049d31c6cc41aa21d988801a199c6023769beea150498e0585fb985adb86
+
+# DIGEST: a5a1b1c2f26458848aabac95b548513d2b2a30c3c3859a2fb179fd383928bbff7da581cac851c73f1b5b74c04ba38d2e
+KEY: 433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025c
+NONCE: b8b9d71d2989ab33e978c4451e3be585
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb0
+AD: 9e4d00d6172e780ab8b700
+CT: e4d1bb73127386320be2b84f9ca0aa40b95fd7f81892942fcb954257a7b9b8886f1253f0db712af44c1db5655042e552a26e7e9b5cf46bbbb4540826d05f21e3f9a3c336ad2d19bba71ed71a8985fa4de946ab419a56f9d15d18c9a31437efbd8d3a3e091649ff9ab1a7f9a10f15a1deced2af148b42fcb1b2eb9019bc40b3b4102579527087d427c62777960aa8653326523c26388753883f406b7db999856a01a7e9f3242b3ba50d4434a6ef4f8b46cf47891ea878bd46dd6ea897af2b8958
+TAG: 367297c52e0cb71e0c57ce61d69a50381f9f0a985b317799fc1f932cf13a71a69e048bbcf577504ec6ebd006ff32d150
+
+# DIGEST: 8fc6e3e5e3dd055d2bdebea6a389e81a0be2daf3536b2a4d3ac80621bbdcc683363875b928a6d6b1e9821689d7c66be7
+KEY: 1c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d29
+NONCE: 89ab33e978c4451e3be585a29a2af12f
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d617
+AD: 2e780ab8b700433a957a74
+CT: 560f3a3feeefd071458aec326be08d3672129e77d60f4686200e5449ce2593a2a8d01b981d16388f2eef742bea8d5f0cccbb9a1bbffe53220c763dc6e384e87e76dc5c31296d18cc9510ec00cf5c7dec2d40aec17f7c1ac55e5ff919a5957f8bd56dda58e1d0d6b2af3878a714ddc891109166655de5253a4213bfc3caca4c69204b27f46d19b0dbc2df066559a894ea31b066fe6035012f4d8002dcac151bb4e48404bafd6121fc1a2d62a85d13850bd6cd018a8854e122bdcf4af80a60832b
+TAG: 1a4292a51d81c07a837d7fe0966552cbba4578b0444c7bbd3480aa8d72bbeb0242429121690e02b543e608075dcd8f4d
+
+# DIGEST: 168cf3eaf275a6d7d7ba7b64fd7bdd80e09d8f8c24c224ab8ea02db5583871d7456c1aad5ff3aa4224598fb4711da687
+KEY: 021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978
+NONCE: c4451e3be585a29a2af12feef71e1063
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b7
+AD: 00433a957a741c9eb80f2b
+CT: 1cb08ffca3e3e9af65d527b96e75dde23a3674df40ec4866dd55ea60d023c8119b7e4b4d4c72ac3a26907d25a549d77762bb5673d52e296d6a894d68e87dc4eb63d5eb6d262a206891baa2c1c4bccf9e8958c5ee374c2b503d3db7cd91ba30d0aa1c3d13068ee09299dc1816717071fecf98f7a6f2ce7ca458c80e0d9e430c8d90b96667d60cc3973091619a75c56b7535d73b72bad57b7ae670aa2e7793a8299dcbfcb7a4b0dc22dadd37ef3562b0f2eee3d7c0df9bfdeb0e88cf52f1f23961
+TAG: 15e4cb367a9062acfd0333ab16928099b54620c8f13306d8848990c28e0ec47d1ad934e66ba7e646bb0df5d1813bdfd8
+
+# DIGEST: be00e794065f55199340f72074234026dd824f3ea47da9ccc308c3ae8f32e02d207810d42934fb8cc1f6a52fbe9e0c93
+KEY: 9da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be5
+NONCE: 85a29a2af12feef71e1063b0b4e6e899
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a
+AD: 741c9eb80f2b021b144476
+CT: c2a2d4990449ded87c4992bdd79e0fa70ec3be505db46c1e17673caaecd6b24b36b2acecf0dec640832a2de1e3d9dcac02f5ccda46decd8d19eb038a6bac782760721cc9b90e7037238b55132f1c3f94ebd67cdfee66c0b08962dd69f71285c5a76173d85ce830c04008dab0ad2b5d4d00ab2ac093579d7763f8b64863198cc3eb899861f73a2368d1e2d6a709f29db09403080606ba78cfbb9ca6d282f6f1b6066e92d3ec8d7c66977194120c0cb393c543086144619ed854fd65db3bb17b5fb71faa853f598fa33571b781ccf726cd
+TAG: 6e27a74ea5fb8936840a58b1e5b88e947124af9ce0a73697522d2b6f9c49e45b4b7f8de504eb42fdc0499789ca6b181b
+
+# DIGEST: d269fa4bada377118b68689289e45c46233a1e42ff00d1aaf2104943958fc881182292b99bcd5ffef9cf06311ddc937f
+KEY: 0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af1
+NONCE: 2feef71e1063b0b4e6e899200304bd35
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f
+AD: 2b021b1444769da00fcfab
+CT: 47779ce727a9319dc4da77d809cf8b79f3e3658f7ba3679e96411f7c201f3638bb6a10c70f79d21ea99bf709150a7a556f2684bc3b67bb716dbdba980cdb37f2317809b2fc7f034a76eea0d217959cefdce844b826611ada73c2dd12630206077bfb5da1112a92cd8fa5b6f768422f288c1de123710dec8f3e95f88c63a2224e35e8406fb06ac93cabfee0dc27208b7bcdd785c18023c81159223c6b9a2e5980388460b67bc38183d5953248b8886139d7b2865b9c5255197458c8155c164196d715f9d7ba59dfb63315fc4dd3a2539a
+TAG: 80f88f5f9db6ad651171908ee1fdf43dc2773672ea5502dbdd678808d9e25176b9490039ccbfc27c6c705d9cb335d758
+
+# DIGEST: 83f1d674eb2a353ef320f53cc7ce581816f5d86a04d4a02038e3bbf9c8c38ebf0724c18720e38fc524999ab2c408053b
+KEY: 060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e10
+NONCE: 63b0b4e6e899200304bd3508132a027d
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444
+AD: 769da00fcfab0f5f93b511
+CT: bf5f4271222a6b8f88aff52aba803e69cbc1faaac7cce89f7d2fa6287556835990ce1d81c706ab63ba3758f8699ccba1a00a89c4e454c4e61dd1447fe635ad75c5b56637e82fccf5a635c5e4746807b3baf9d2ae7a495b75788de46c58648eff4c6a5aa95ca1c86a26706a1fb258a801b35e152ee3c0eb1cdc9053cd9dd97b360a8fb4369899605101f46e13e3b8f7c2e92c721703e5f234f85d9a51bc748d34512eab57a38befb3caa27fcdcbeb76e7f70d3d5b70d1e0db56cb5492b27b5ed343215ada6cdcbee1e37ba4c70a116922
+TAG: e1783ddb0da896c7704c3186db3f47389601a786d4227b886b7371f144305953ededba504420a68c6bacf1dd3bb98634
+
+# DIGEST: 6a1add8d6e893eb14c0169f01df796242fdae6d5cbee28997b4a634cb49e6cd4f2c333d211bb0ee623bf136d96d49a8a
+KEY: acefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e8
+NONCE: 99200304bd3508132a027d1ff4c047b3
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcf
+AD: ab0f5f93b511060c9c5f3a
+CT: ef1d5106820950033607cb01ed020cf464b1752c60719958611f95569a665d388560bd7214f85ce9a257efb83518744ca9525ab3aa5262f1f1eb4d3ee753cbe6b4531f9a2b97fc482d22279dc42372401d38388d1798a47753cab483132c30d43a093a9abd285bdc35106079c1ccf7c1fc356d3cdef55f28a43b949ba30b8b14c5602d82f005c15db8e216ee027089884e5512ea6c75b46ab3806739f389f998a76c7c752ee6ccbdf02646bc4d4af5407c91e826b2859b6fd6f14376fcf42b4973d6106b1ca04c4c944fa91ed3198000c45c9ae5496c47e324a3220a9a1f3aa8
+TAG: f692bfe1314d3b41f4357ed43a29e1b3942f3c5898afd01cb8f1eb200ad6219cb47245656258b63c6ace5f2261c96c47
+
+# DIGEST: e1dffd50cba85a03f6be0e1e56270ed742d0d280597396f247c2166c5fad4e464773e231c38ca1600a9e5d30f68a3d79
+KEY: 4ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd
+NONCE: 3508132a027d1ff4c047b3ef4f57a747
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b5
+AD: 11060c9c5f3aacefe61b18
+CT: dc3ec8109d10797f038763f228f2b09ec5f5ab9e575c3e965135aae0327a709d39947aadaa1a7d3be9c73ef1c3c2ff740fe4c294fce8a28deef09a100bd079ece1a82c96cc679428686b439fb3bf4392fc2155b4f4f4aa510eaad21ffe8898d2bf8d7e47120203d7efcb163163b89ca9ff7db4555d248caa91c1ef64b3376e5d95f5eee2123e0f932b0f4f22c67e81689466aaecea9e8a167d3f17509ea2c5827100b3e8b0db42150958595aa7e48df36906fc510c36bf3ae1d47d5991501fa6f07587a3db0d8bf92ef614486e62d4c077be06e86d58c6cfe83737ac79a9e9b7
+TAG: a2d8676b91a4dd699014b4192619d63ba58dc09d2d6201d67e8c087b88bb89ff4061de7f298ca019e6a0441491d9990f
+
+# DIGEST: c8af2065af39797ff13c758f8981117e988450d5fdd669efdcdfe0a3f394822a55d77f7a4c18b638bb93eff902cbb495
+KEY: ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a02
+NONCE: 7d1ff4c047b3ef4f57a74706de4b381c
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f
+AD: 3aacefe61b184ad2463939
+CT: 7bb7bdec9f7a88752fac855f095aa4861045f35d39bd7183785931cba565bcded1146323c13bf4d8f19fd365fd41f83e91f9ce1a295cf3eb1b00ff4d99522496af0a633d2db59a0c65e2586c82df31917ab7d59b888926c94cf262c97d0a157e5db083de3a9f6ebce2c675e079c95d64d09b926c4d2838fccaaab418f22ffe00f26afecf9f6ecc8cfb777b9356d9e04ae7400ea0640cb447ae19d54e9f617fc700720a8a705492d69b2de7593e55a6ef5ea5f6aab63b6e49f5a5d63d0bd6a07f1e63b2cd6bc07017d663027cc029f5d9093c5d2a218f3835dd0668c0d7e52109
+TAG: 36894e65f63b0872db53e0921b1e49b183bd496c559836b57a5c2a1a9615f2709a234e86a41f2fe44f513eacdac15057
+
+# DIGEST: 50c5b2f25940bfa114d61268aa1822c89e18d1b2615a9609620658127d9ecee6d0e5b4b535bed85ec48792def2e7d0f3
+KEY: 3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047
+NONCE: b3ef4f57a74706de4b381c692ef16410
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b
+AD: 184ad2463939ed518ce97c
+CT: 0ab3deb7e70e17a62eb723138ab79ff735fa1afb15ffdfa40e0ac94c961da191a19b3f0e91d12304bcf80aa651e6d8b3ff2602ac79227450a6e321ff24fbcc6c0b19261c557da187acfd00d3da83a2210b9331bb9fb2585fcb9641745322ab8c1cc0f1def713af660b94a388b5719e38dc3610ba6ed09e675cd350d637536193bf94d95a8e14c92024417a3ffbab61c03aca0e8e2973876eb3e2b2a9daf5608bbbeece9900b86f0f2a47e6d0af95f06be0037721cdb2c94cc1f7ca37afab618fda75378eaf63ffb41f472c0f6a1c5a5767081aea7b5435feddcc27324a13d45a444a9f6a3b31895c735d1a130191c1e9
+TAG: 9d6e18d13fa0a2d15f58030b319a616e7afdef095fa69df558ee151ba2ba34b1cc47aaebe1d62b016434dfe300caa9e9
+
+# DIGEST: 2dd9a9d8ed4cd002fd9220f00d63f452a64081f1d58a6bb6638d43d8796fd8650e270266e68a1b633150186b9eb4d2c5
+KEY: afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a7
+NONCE: 4706de4b381c692ef164101b89b476f7
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad24639
+AD: 39ed518ce97c3fdd293d72
+CT: 5beea8abccb14c5f200e93dd25742477cd3c63368a50060a73667011e0db1939bf17ae2ab7c8cc31a03b075d694c357737eb79aeb6433956b1f91cd99a6be1664ea93b88cd8d9a3672aaab7046051d91fcc4b1e1794dcba499f1c05adae879c1f2a9631ae97303f5acbd4601debfa5e31f9df46f99026b8c2bb7f669847624abe75de43c77d8c628097771271930ff2b9b5d846bdab2d12e6f7a90bd07f4ef4fa87932cc038be88e1556c0dcf35d659c165d4ac3c19f3eb1036f954a02320ba7ec600129cc2725677b598d95c5468b3d7743286f05c9f1821af752d1e2ad61296b9c98883fdb4875f0d09ef33f50b122
+TAG: 8efceca9dfac02a2571e0cf62fa6486e72790f3cb7aae134f8248067229f755b40b669e66b71b48cb45604441625c5ab
+
+# DIGEST: 08d139d6d4903a9ea414e1a1c1c0aa2a4aba3bd64bf798740168a81fc6d30ef05dac1298578eb7987f46f73aaba2e9e8
+KEY: f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b38
+NONCE: 1c692ef164101b89b476f72b27f06f52
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce9
+AD: 7c3fdd293d72afc09ffdd4
+CT: e7f4549699e18497448d0e730dbdd2b1c6055fccf9fef5442ad0e6d67a92fb7dda31422f52b2b2c8b0ee0ae0d532ebaab9d4c2f81e7579e24cdc4142aa50c5ff041f6b76985461775017a9169183ded52fa0ecc5392e95dd61f7d6ba2103f75ead01673f2388ba8d4257666aa3f73559ec2078beede99e963b7003ab9c041ed6a97b50947cfaef864269e84a33a598f81c7dc27191962c8936403f198e9012f19bb8b57868c11aa5ff89c312e7224d7b170c74ec38c5c1e6bce87426129313658fc3ad88de0a12d2012c92e9ffb25ba5faa9ff8456cadc94346aeea7d8d115a509e4095d5446dd23cc1a8487d179698e
+TAG: 4fc94468c28721069fd8b709881a47a1857d66cc73d936390acc630b8f65db2c35fb2e5534971637bd908f857cfa5659
+
+# DIGEST: c2384737c5a6bebcf80d5407502a9f63f99ba051d327344e7499d74a6595d8a62acc024817557b34d564fe29dbc07f16
+KEY: d299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164
+NONCE: 101b89b476f72b27f06f520c9267cf71
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d
+AD: 72afc09ffdd4f41963249c
+CT: 8a0c0690a36109d3e1647d0cfeb9561bae8c54fe971bccd634a33ddc02590fa3332cc74b2ebec342844c1e89a2589af6a72c118b9052ae12b11788342ee169c2e0c51189e8ca8dba3faf6d1d97ccf929e7ffb05e218c36eab2b4943d29a00224dd6ad98e6092967c5dffef62aba7008478bdf97f2a762c9251aeedb01e57eac36a7322b967b5bca4bd6b8bd54e234a0aeac200ace65afbb4708b3509873b7ea7946d8586d5db3ed1eee98650eeabf51467dc139dbc7ebe0e7706171cc8b840d5c328c66fd570540f874eb43fa864c137339449cffca080670b60dc885543e95503e24ad384c2664dc824bc09823c94184741bdc3afebbadebfc288a860dc9ab9
+TAG: 77a0c2a186248702375fed2ae79fd68fb379d02de457bd21bc5dc432670b8aa477e406788635696690158dfab2040e07
+
+# DIGEST: 884a8cad7697f63e916069f5188980399132025f7c5c8b944cffa52a0ade0a2348da300e9daea089f71e77847c3aee24
+KEY: ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476
+NONCE: f72b27f06f520c9267cf71408a41729b
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffd
+AD: d4f41963249cd299b92e55
+CT: 059daac7128bfdaf3391a02322a1032a52057d6cdc30a2a83ff6e2cf5cf7c06611a5d25af94232c15d7462a89e556654e4fcb14cafb8df79aefca9e632bd25321e7ef7b91545cb67b5cedfb5a075f8c28430368d0f18113772db67a8b0b11f41192716be6ae0a7f2102be589b95e3d379110fae8384fa3f98a9314deae55e8b158d953508f0f81853385cb8eeefabfdda6f95a351b42002c7768c5e48fb276b3390af75c94c4ea14648235d9066e4812c6dbc50c2d739f27eb94a76d9a1fa4178657a7bdb616cbfa86f2a83ed1567d2d5d947f27a02192a94704d61785cc2fe3c6c5d575e98153f6c0ec0976c9e367e5ccb7634ef6abf1b48d01a89c8c31aa0b
+TAG: 8e09dd0c6b1aca804d0660338871d4eee9218b7803d901d20e2328866574467840f7882a365bf6a280615c9d55af07e5
+
+# DIGEST: 2b30758d1c221bc3eda5719a0edc2d227b1203ad321d73fa29bc282fd34e0688758eafed68532e9793eaecb530aa24bb
+KEY: c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f
+NONCE: 520c9267cf71408a41729bacb5877e72
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f4196324
+AD: 9cd299b92e55ca24d8c078
+CT: 83a51fdf1e0a256ee3c01fdec162c5008bd4192c2b526dbb4163b593afcd7413166994c6195202488e537296ee818d0cf6a5a8e47a0925e1e51004bc1a2b4607ef26c9237404f69255756e244a0cb06f1a1ad00a6e5d261d507cffea930b3a393fdf0e52e56199ef9e23a09bdf8c6fb441df2772a5c3e6905097b1ee0ad5bd54bcbd6eb7a2674a2ce63af37a96992e5fb353dfffce5a17a8cce059c16537fac26fc9a681b6e2929d6e717098040900b988827c219aeaff1388049e07c030d80315b15104fed0ccd37c46e271c1e4e04829f931eeeca824ff4ed1f747d7c57498588bec7e87c8ff8d67b7580e2062caffac2e1369cfd9a97d951df6b97da98764
+TAG: 31b2b774a0521232f2df93628ba6826f32434e71aa1ee7945a85ea5f835f209e7833b64ee8d68fe301fe0ee72e6d9929
+
+# DIGEST: e6dceb11d53d89194b5e2eb0e609be023b6b1881d0008e8c9e6d794d8d9a95479ab7e088729e7797119e31bfcfba6e43
+KEY: 13710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf
+NONCE: 71408a41729bacb5877e72cdfcfa76ae
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e
+AD: 55ca24d8c078c49f78c7e7
+CT: 2d50ca52c8f44d507dba0b611cfe7c249d0df7b92404fa74456f79cb32bdbfdb7f5c5a6d505087ba180079f38d27bb4cf2b070d60d8d22d224203480d254dcd60e837b8dbfd51c1550e722ff2fdfbb589f84f259349df71eb8af4b69839b23f2380deee9e01aefc4de8ed96f9a9c371127c5b6ec2045f37912d50fb9d389ebc89d9239ce6f029fc5c7eaaadbdc6336a8f56aadadd9606a3726f10ff17b03a1f3ea05e5dcd06e9e4a1ec0d8dca837158b875f646bf36ce9b142e9621819519002bcddc1a0efa76e94c63af2b928bdd4f8b1e6f90842c4b744468de6b8beb3417fae3d87553169fe1667d2b353bd30ff0f31f4eefa68ef41b4d76c64da86d7a124
+TAG: 44c2606b9ab3f19a8f6d780582246b16df090fb6f214ac0d7f48fb1329ee1cdec5d274d3a8dd54a9f1f7340d255654d3
+
+# DIGEST: 199b417495922276221b3c279f61d5d6e33d59927265d36ebf0cc78e458388d5c98bef7808dbd51595c02692e3cc3087
+KEY: b8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a4172
+NONCE: 9bacb5877e72cdfcfa76aed06707a07c
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c0
+AD: 78c49f78c7e713710a025c
+CT: 0207ba7e4e575a6b442e7c0822473cbb2a243f2ffb701a4060f989298a9a75922fc801ad4170608a0461e721f1092d2197d8b7509b3a818f219b2e9aaab3f267e88ecc4b25e26f423a44b140d09bb0d082785dceb2b00bc7b28b5edb6de8e51f5e8d0ebf82928d24b02f1cbd302c87daa1fe115c30e8f7c1b12322a44493f1f2b1ec626463aa838f86ae65994fc3a2def1d1f75aa68c2d873c218d1c312b2f0e66c2db0e7770966db07451b49319307347032a8c86d01282f95d19832bd57bcaac0c566e8d7108902cbff432031b050a909fd8164ea85dbc916228f17ca50df79ce92673fd74b8b0deeda3261fb0ab8574747189162a692ac09e796a655f8358d5c0f9939b20a121af39c01db09b4dd7
+TAG: 264fa21243ad6ca5715ba718ac90ab3f4c2a320b09c79ab551dceb7037ce08e2c5aeb75371d0f6287123bdf70b02d26c
+
+# DIGEST: e4f46e5cae47136c80c8a60bf56767373748ebfda287a8b879801993ab4a5246f40ccbe2e884c7e27a2426eff89fffdc
+KEY: 89ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e
+NONCE: 72cdfcfa76aed06707a07c3dab699719
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7
+AD: e713710a025cb8b9d71d29
+CT: b0d3bc02cae47ee3aa38465fa9bec9015334c2b6c84bb5c06a0d273094655c449164e22c374937b29ee21c21dc4efb3b3bcdcc31ddb08eea4b9f69704ce32aefcf08fb3039da9636964079e15002855f4ba8757e536b2dc83d4fa81d0cfdc173a61c6c5dc7591b09e64000d105a934c7d9738e7a09a9cbd6f6661eb90155d1ea7a3de606c6e0767c64bc714cf7ba35dd618ba823ce6d89b80d555bd6861eea22a926ce39d4d3e88e0f141a40f65361a30d8c72a0c6e56056a32961f7dd4d54eb6673ec2c6ef90fca76c5817f021eaec43b0598ee952a52d7d79c0f345c42a4394ed82e3bb706d9636c246ab6adf04922e4bb350dd225664cf136d383ce2abca3a375081f9ae1c1e2c0c03d14234315bd
+TAG: 3c1054c17942f62266a7626a4b3b29c78dc184582aeca024e7c783928b31c47fb7bbd058960be756a28690fcc64382d1
+
+# DIGEST: a9ab89e536b200a81aed2163f60661188fa59c897afd82de19f6592ad0048057e945aaf7281ac6693e3d55f3c202f327
+KEY: c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76
+NONCE: aed06707a07c3dab699719fe882eee2f
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a02
+AD: 5cb8b9d71d2989ab33e978
+CT: 7702d1d52c644f0ba13e433448710ff25d3cfbe67c93247156cb8a7506551b3c7176ee639b4123440ba6647dfa6ac4f539c619fc2a0c60bff8085d04ad0ad809907253068c3ba12b54d8e17ca20006044e7c86d3541f9f03de3c6684ff57b2fd47eeb88c8a5597b4303c248c502bc73da18bdfcde09a108ced804cd3020e6e4407117052bc3d971edb348d203df7fa3634e3c1ec1dffaebe5810a9121bd74e71f27ead339abf7f437cf00a9366ee70e78499639f484e44dc86b4efcb640a64c417048449e20b837d0a7e9329ecc82c0f1ecd29b13ec252d91ee1e0c3367ee0cc304c0a736d91048dfee0619691d39a916fa1acb87fa9513bf4de17cf844dfd1f430eb59d2951be2e818ca139a9730c3c
+TAG: 6eff1b0d8a4ceaef0a0dab7894838585e235e612ca586a5ec90e8471c42f22108525083c6926e6e7d09b8091f8672ba6
+
+# DIGEST: 21e69e0c67364acda97b977e5c6480b74e4d6a486564daf031078571f52cb2eff8516e6c5c16186a7efa7280dd22f910
+KEY: 85a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a0
+NONCE: 7c3dab699719fe882eee2fee55ed8b11
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d
+AD: 2989ab33e978c4451e3be5
+CT: 8879c6ae66d6d1c0dc4ebfd79bacc10bf2084dd379195aac9356263681e5820a834c2d1f97f2471be4e381bc832ac47fed2d487365716c47a6b7746560ff155e90fad5dbf779540f2a952bd779f09e73191e29e3d053a35cb2f0816dff86a80fc4964059c5fd6982d2d6713bab09d0ccfa50db5cbe264b5b1903d2c0e7a300f3adfa46d88bd85fb1c7c6493b99439aec1dd948ec55f9884ccd9db1219afc094fd003d05f0a0368889afe88d450de70ab803b281dfd94d8a39999d0a8c4b5dd5d5eb0fc763818cfd489e75663a97c35755f33af1bab261d27fdf280a9b0d569609de1da440ba3bd1ebf0c8bd3bbc748303754a8ab42a3277594af4416f073a7e5edd1638593e9ccd97bf2961f408a8f2d6ea4644b67b6ecca16ef02e85e03111f
+TAG: 1adfb34793904d23a570922b96defeb6a704328e40ce688b18ae7669d9635a38d43453afdcc063d6d0a59a94a3a631f5
+
+# DIGEST: 6a10a0d487172a3e826da1ce857df74274a0a94e0d8331d7fb2ba5086bdce03d8b290e09e5255918560ac233f5e4e9dd
+KEY: 2feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab6997
+NONCE: 19fe882eee2fee55ed8b11534c870dc6
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e9
+AD: 78c4451e3be585a29a2af1
+CT: caf92c526ca2f6df21d1f72cc6e2f0d538a7550aa6bae2f3f26b31d4b9d60748c3138784df673d78feb662c33c9b6cb2f53040a64d7b94851eacc0bc688f4863a77425f21060fd948b9f76d3cad6f5560fe7c8612234d72453dbe4cb3017639c90bf3d7bd249e1bac830cf3eeba58a55a24aa1f150640e8f369e365d3f534d113607659405f2b5b34eb9c5b324752b40d2fb7b06d75008fc94554c9bc5b5a7fe6d06934b488e82587b8173bac173110e4823107533e66c3bba0dfeb5bcf89a6abfa7e5ccfb31f7b75cbd461d57baf37c65bf530ffc47c7a1e214263436b55ef9291548516abb3747a37f1447e8a2a6bc5d14490d25efd196fb4453ddef5ceab17b5035beb528750f529a30a593c48c8280632cd693299ad28c9edd687bbfad62
+TAG: ca742e70061c7591e2368e0c9aa38c912be053cf2ad02f221d6d206b3b702748d446411c2b28a29ea8c569b264f0a87a
+
+# DIGEST: 77ffcbd25c7f2d4503c939d96a5dce72df506fdbcd4ba4df81b94803e91b320f8e56543894d67b2f77822f858b39bf6a
+KEY: 63b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee
+NONCE: 2fee55ed8b11534c870dc695b814bdf1
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3b
+AD: e585a29a2af12feef71e10
+CT: 41b726de79e3f6c4c752c1b9acdad102527540bb6300a8bdc438c6116705fdf7669c951c997ddbcd7f97e9467425a6d2ced02b18dea62ce491d6aebed24f92b06412c419a7b69abf964ac82382a60375a9abbad905936de5053d6439404a46efe12bad7ba50162bb195f83c6cbf4c0c6065bd47a50d4a46999e74f4645ea68e5f7c1fdcbde253298b55f66c2766196a1218f86a8ffa849efaf616bc66637b87af68ec420708aa081052e7c4608ef8bb740bc8255ea23473ca58c914f8180aff5a217b401e155d9bfbc362c5e3a3fe49f9a49f847cb8489be7950399644cf53c1f52b7357de1aa4ee24a8fe4e942a35a15e8e7cd228880bbe6cbec83f64efec4085e1f5211b15f503369407d3024941de5270e2f036a655af6d3ae88404d35236
+TAG: dd0208ab9a66fb6c5f87eb7410f6300fedc3bdc9c3c189bf70304ad33f0c3358de3da4fa9d2702f387c4ae0d454e7760
+
+# DIGEST: 32457abe3890cae95de6b49e49630615b10a555e6dcc9d78135848b910cc1778468d8a314fe1156a8b7a18aab2321622
+KEY: 99200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b
+NONCE: 11534c870dc695b814bdf1a87bb1052c
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2a
+AD: f12feef71e1063b0b4e6e8
+CT: 8508187fa18f9f1e202027290ace1355dba08d4af8e4afb74d52a7e0aa2005f5815006990468f5982cf5bc97141b783d3713ee8ae335c8ed63d3cfcceb4d433b4cad0aabad5a7b3387c52af24e48bfaf4cf0a6511c0e52c2c985a1be41186976838acbe49ed9f9ee157f8480997a448b0fb4786ef69e3a8bf660d12df28968ce6cb04196225c6a2d14f69d8668a0567bee5e6b1dcadc9ab65742b4561332e68206e78d100724719b4c47e2febe647129b7c896bd92ff0a3787acff249006b856c78d71b860402e0fceb1013c92de542b02abbd4392b86c10438c87bd056ee57d074b57c3d4491959db47d622bd958be19ed4aeb8db0f656d2fcd9bd489b6340a32384167bb35f16b11882878ddd05484afb0dc46f6e89f35674943c3d4a1b3b8be459e7f554cabd88a49680b70c89071
+TAG: 619a13abdcdef2105a87912cb516423e92905a954388217d88f9b287db9da091b2771d7d31815d3031980aa3e6060c17
+
+# DIGEST: 7566814f71ab50996d4be639d21fea8536913960b35e2827df5720add45d97ba24ace53b74b9415cfa8eb70130404663
+KEY: 3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870d
+NONCE: c695b814bdf1a87bb1052c6755a7a116
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e
+AD: 1063b0b4e6e899200304bd
+CT: 10dfd18c8af7dd4c5d11e7570d4715730c8a63d7e270763129f251360a076942d5b1c64f953495a2e3cae2015347c02f7abf2055b0816022c0c281339022788ef520233919e89e417a58846eefc727885509a1e921c27889b3cd9867edf342ae11565a2811d594fd84e95fc3205c8604f1643d2adc3fd3f7080857d1d9ce0f24eb1a72287e97cece89bad62e4a7012115874d04aebce6a89a193922b7611e3d0a05ef6c9197ee7affa2f4be7c62012148251034013398536bdc0041c62a7d5c304d2f033e88b1fb593449abcf722ceedfc3e1823875adcfcbdd705096f856fc61e705537686e1ca298c281d8c3f4bbe1842fd26b8c21116a2061437e9772a7f70a3fa62e5f1027e13c102970e9998d03ada32b0e91bdf8b5f9b7b4aa6fa69b66fd5e34e9d9d34ee0068ae65d76cc0fc5
+TAG: db2def285650d7644938b33a44c75aa6c54223c83bd6abdf443e4d512af9da78ed9d1ddc88536bcafcb0f3e7e36e6ffa
+
+# DIGEST: abe8d2c3e126a09b7884999082289ace9fdac6af11ea2d3bb57a5ae33ef91d4e8e65ff0d35e038bf324992066881c495
+KEY: 7d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bd
+NONCE: f1a87bb1052c6755a7a116bfc9095da4
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6
+AD: e899200304bd3508132a02
+CT: 4e22afb3b591e9a83871c8549747ce7a0093158b36a830f8d67354c13731d8f8d55ce6205cd65c87a91f61fcc601d941eb594710dfe181e4df12253cbfea685fb89ddc9d54d980596825060cf2bf50c4fa712119ad816673c33d51aca814acbd5173b9908b1f1e1c6985597b54d8e996b9e2f15bfb3a01fb521e31bd6d5d7405f1af3f2a805d2416349c6c6a8ad7b0b5adcccb65fb342ceb12e0f2d384c729567ced9fb2e7fa6f5c6155f5dd02c45e5a482b8f3b96c2a602cf3060d026f1ea1d7653667ab46a5b9ffaa685dd5dd736047cd9a77f11182e2327b1caa6e82109b71d2c8b974ed200416c676a374282c60dd7bf7f07f9202908ae5827bc061fcad2e85f795a0d1a8bedf8ed288b61c308e458dad4129ad7d2f08c95ab143df22f905c5b8c717f96e6bd220956607d2090ad
+TAG: 8a3b1d156a50fde730ea786d674cc0542b0ce8c547f94f651518f4f54570366dea56d9f6b4ff27815fff6496c551873c
+
+# DIGEST: 70db0154799937204e038d0bc765da2d5e1e9f266abd47df62103ea4fffdd9ed80e95d281bfd7537fb3423fa3332cc8a
+KEY: b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb105
+NONCE: 2c6755a7a116bfc9095da49db3d71f4b
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304
+AD: bd3508132a027d1ff4c047
+CT: df2b10cbabc4176218c6b9c6f108c1bb25807fefbdfde2ecba5ccd2361cf63db84035427017766b44bfdf329953adb786e6653d5d220408d6bcb4461b204768eb0d8e7f56eaa2ac707182972a65597a4534183972b48d5190d61a497609026825f7d02bdeeb1d9421d13c217e3c17faa9bfc3ad587600f934ac8b508be37589416a51f5703c9244178b3102ae59d5f7b5d574ddaed1b3fd1ad7c47939d9c1ee08bbbbce47288eafe3b508743211c79b75db22873c1eac4b9c61d5684d94d3aa4c11b01cb43fecf4fa06e0945767519d7e7a89526c4c821d24678baa7ce6ede7f2e8b4c9bc70706be730148d159c1d6158f27d7511ba66e1310e1bc74faa5b60f12fbf9b539cc25734a9ac0762204b57f565fb35dd6e96fb84b1b7934fffc01e5afbca911ccac4953b1e63c596fb9268f87f5de6a07a9e9f12ff8668c5b0c07a7
+TAG: 78e3e77e872a030049ed772441f7103b8787136b6358868632fcb041f22b4dcbda8d945feb06e54fa28ff35ca5142057
+
+# DIGEST: 42589001ce998459e1e0625b178110b12aa71f15dc1f15059ed9379f662dcb801d7789ca5917d477c828573310a63799
+KEY: 4706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a1
+NONCE: 16bfc9095da49db3d71f4b975c5d503f
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a
+AD: 027d1ff4c047b3ef4f57a7
+CT: 52b3ab3912ef6e742a285968809db8eca231dcce87daeee16c7ed2557167b8df32b194e17218e03f8a4fa53aceda990b2b76c3ca4b527d89affd2fa47a19a876196296cafa94b72a0b85b7fe2f9b49d6c43e1c4862c703bb7b8433b2db76dd9ca6eac8a7bd7e994db7521b7c1c628a728387f042fda0be75de1f783a957ec75aaaec6b3db998ca8f238ed636633f87d0ee73dd8a3d4889ec61006e10d5412d9501b8a25fc4ea73f8a08883850bd573ffcbfef595f6baccce2e343718fa71fe72db06f5022f05b2bc06eb92ff836af3426c313d1813b849690e983c90e2d3f502f4cf7003b85af82b844d1058874d2d48986bf90c781adbb404b79b644d298988077f192d25df9697a4b9577b6b56a72fd079adada11b719b7063f72858f4a993ee3d89bf92f36f4ee23194181d3937837c2004681ea0abdf2a4384863d1a9b0e
+TAG: 8cea7a80cac6b53a9e973b41ea92b560175252994f4a14a89cdccc51898550a42b74d41e9f6b716d3a287cf112b8b552
+
+# DIGEST: 7101809487e8b4bb3015a0de401077a2c5d2a96dd70a97eb3ce8d9864723b6c87d9f0d2468209c6adeed2a05a0645742
+KEY: 1c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095d
+NONCE: a49db3d71f4b975c5d503f478b22dc82
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c0
+AD: 47b3ef4f57a74706de4b38
+CT: ed1c1e41992c0784cb35b220c4c1acd1985a6b96c2084f2dd6a8ea7409d39cb0f983ec2aae41e72ee9ef204a1401d4478ca5f2b068c9c5327ca260b2587d44ad53bd6d830340411da14bedd9ddb161df5ffcea3cd1c51e98c16512b657a9dd38f1ad9bad415c6f7d29c059507531594c44145d560f6fc9e11ba2f44efbb0309f9fe15df97bf1f5599d71707a45afb8a366bae722597a6087ec82357ce748db0ba87812e2ae60b12a1db5c36c1eb041dc9910335d44f35b209129394524ac043ec759fa1e9d46a31b4cb3e248817bb2e636bfbcf946e1c61b81288d571f693ccc02967bc7a1f21b7b75a0aa3858f732149c6c97697b1fb37f8e41ce99aeec3b0b31f8e1b2f6d612c52f6764f63dfee41699c26d54fbe15001a80b026de35025031043821b79900c08eaec35112ff48f364915dd83d7406321e4e2fac6b0b4e6d9
+TAG: 8fb0da23eb53eecc1b59b2d6a9a3eb5feb368128ded76c717e2c5325a8d0ec43734c1f5c4bde8c253b880e5340355d24
+
+# DIGEST: 5eedd2cb6641072f2e8234f811431cbc589b06c89a6e0f6f90c63de9ee682200445a8a13522f8d75be41bff67efd4516
+KEY: 101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f
+NONCE: 4b975c5d503f478b22dc8253bee6fd1b
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57
+AD: a74706de4b381c692ef164
+CT: c97f9422501111b5e8d41a02331c741db0f170ab55371933ca372c3b1c77c15abe3771fabfd2f3f4bb8f163aff56e5e04307cd6361903b037d5a555a518dfc7bc7819348db0a05c6079c6650b7f8560a971d07bbf9dc9c3034450937735807145e8abea960da5435a4b7bd69204f97ac4f3eee248939d3c1f890585c408158d9ca3b5c1fc59d75de526892967c09730b23d89623b6219b6646e503de4d088170928973d78b54d742363c6313e793c557a6717d16fc7f73f144f8687420637b2624ba3a23955e1342930a6c350b095101b9b3598bfd1d8331cd0b0b44443835456ec42b29adb89efa9b64f6498df3c8850d6165f5d74b5796ae4ca8bd29fd7cf30e9a3970700d741f6b9f00548bd1e997c89d2fd0a16075fbbc5deac2661fe25d9704f4e27237b86124feb77490f005cf0e5a1b706812b91667b4c025d733d22938ef19f73492e5a7db0dc7e2b22ff46f
+TAG: 395a711cfcaa794d309683f08a4ae98ff9244ec6acd70a36ef94b12994f9bc86bb6d63594caa630ab37043dbd4c03925
+
+# DIGEST: 414511b251fbd9c63bbeb1f072db83380710d470fd5e3deee7fb5161bf6c45b6a1122753ec0acbe8c1ecabb17c653a5f
+KEY: f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d50
+NONCE: 3f478b22dc8253bee6fd1b174c307f01
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b
+AD: 381c692ef164101b89b476
+CT: 3f144ecae12b64b1754688f0eac019e5803454c5b79f94c679495f2f2e26b6376949d2b9f8d322ef2a04d4c514e17d8cb9afde3961a434acc21e09a022d83381aa25e4592779433402f772a175f5d685982ca4e908134ad9a13916e125f33dfd10be9922f739f038107297e72708a19dc2452c7a2a64293aa8ae508072d99f4c83ec9a1c2df5f48e4fae6d27edeca1892444aadadbf83c669a86b1defb2be7322e659f3478b38ad82525e4b412127661b676f798cc4c0c21522948d9db6e51d31cf11a495b4c38159d4939952c313dbca903b9b87524d7bcc7fdbf19126e926a6afd970a53c6542ca38986d90967853c502cf7b8adf0f77b38bc004b563025fa1c0e9c4e17e97a8f37daa112d03e35fa3526bc136f178897776bc35b6fd6194d8c661978da5b50bced6811ffadde94bef268d97162cafedbb237d2eda805b43b9c67ae8e337b7f7502136abaab2606a9
+TAG: 4f57c0a8ab8887eaca71e741149243c8a30482750a0f0ee666c0dfb18250030ffb073685643b1a3773f3a5250f551059
+
+# DIGEST: 308351560f4d9b6ed2c0002023b33ac6b8161a6467c9072015ed7010cec8534bf143a7b37b145464fd3565235e6ee765
+KEY: 520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc
+NONCE: 8253bee6fd1b174c307f01be95abaa9b
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef1
+AD: 64101b89b476f72b27f06f
+CT: 9169e6bab5e2c9bb2efbafa95242efc4e42dc6905000653b98c179ec663578417c9c2149b9868709a7bc550bd7831939ac540c6510fe15661b09192c0814a22f03ac79190a0889b1aa5d165c927149c86b9ac0abb32cc50d33736edcd31da2ba1e4f60fcf35e8d088df63cb003898ba843aa99e410cdb1b8abdcc3dc3fec2bd3752ae5ab0a2b858c3e451fc62b95dd8b46ed0cdaab69608376fd711d0eb7e017d11528f353fd37965e26d905ee161637dcfca5cabef495d3b074f5be708e074008324792a0d901cfee936dd165ef18799ed7db508898370574255a95e190f428b1fab0693f400a47811e4acf0319c76581146e48912be4cc8c8e496c2df2fe634a8e18f99eaf1ba5fcd21c810bf8c9ab28dc5dc59da6685603ad3c14281075948268b452ae0187ad6bbbaa8f8d275c227ce6921c4b0c5a837e36ee17ee5d24604dacd788526e4623652c7fd44b2d5419
+TAG: 05b9a5cf0c66a4b79dea8b3aa3b5847cfb11fad03ad9312a6508bcd7aed9b7099bb5b69aad936c3f95717e60d332a390
+
+# DIGEST: 3b27033919f9b4ab68c8c22766a430e1aa70d214a7232678f57265f9ed00811203fcb67d9b928556eab731f39483236d
+KEY: 71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd
+NONCE: 1b174c307f01be95abaa9bee58577723
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b4
+AD: 76f72b27f06f520c9267cf
+CT: acd60034dadbeb0b29f9e43f33df5e650e474d48ff007a6ebbd7f86d8bdf8177b81e3c31347fa78cf1216fcab0952f00a189dac9164c58639aff79c9138519a84100af1911dad011f01e8b9e49496a51e11b7e211efa64df95eebcdcc3ad152ae5066e2b80a31f456357290d07b637df0566e4dcfc672bb60fc30725c7940f397e3d486d044ea41df0626355a36913f6f6d4b68ff7e7f35926eca8f0f0eabe6baf4480ecac852078c4609e3e92f942bd63bb4438c4d370dc0cb7d4e40228273fcfc96c08e39a3fe7b765ef18753b6c1c07afffb902c788ad058e31440480f1dc2def700caeb66d980fba5eb72d14cd7b385e91712cc719f0b6654b250a823848b0ff42646ba211816f8c71958a50c090db514fee0a4ffd706a3b95ec71112e272fb8832e34fae9b2d3f82c94c6f808f708a3c7e1c5d8d5929d9e44b0a7bfccb11344b54221014aae48665051921f47cb
+TAG: 54bfd04c0ce7348b3fdeb2ce5fe24576c8b3fd6aa6268bdf26a8c40d0c8df91ede050ea9efca7cc1c39ef2fe997c7dcf
+
+# DIGEST: d5b97828b1780b3c93f4bbbd93fc216c75dc360e803416baf980da6eaa8ffa71b0aded29e346f3e7adb7334708c912a7
+KEY: 9bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f
+NONCE: 01be95abaa9bee5857772305daa4b550
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f0
+AD: 6f520c9267cf71408a4172
+CT: 96514bbba87db4dba9b5ddec2139efbb5887b65fad1212133f6da03ce1a71b77987fbfe4c4447455f956aedae52a6241a88a4fdede9fb0e1bad955cc96abf5b1b34caddb470a1e094ac62152a5685c57877319aa3775fee4db3e2d179bcb3cb86f58c0e0e4f4e38d03782ee926a399c3332e9bd136b45929fc6a00e12035754d135809bd6705602a2162a29f87ae13ed832a2140255a23bbb68bfe71c99e8cd25251a04fe87f30937f763cb5d6973a90495c906b0ed74581ea0e8c1cfa6ab5d977407d74a0c3c7c131d276d802bb993497079788c9f6a3525cb18a2d65fdcf757c0062d5c19fd0cf184ef0806008cd1ae87fadfa04d7b5a95c5e2716139b82b25aede042caa76ca315e17c4c4e58ce793e3725ec5a40dcc65e102d21eba7b85074f0c496e28a63274de40407dc2ffcf6da8a7187a8370c9826698402521ca3bc9fb20bcddaf728182dea0a728d48a0305bff03e0673d0f8df42067afa10207fb
+TAG: 7822e8e3c20272ab4b9b5b23bda585589b82ec3096785b06c246c84a722d3a266d4df5e23a85719e3bd232a5144d31cb
+
+# DIGEST: 308d3740a6cbc4565bd19d58f561b1f6fba0c31ce8d323bac8c337b8a6d2db6c03dce8a06a13aa1cf2163e29d61f78f6
+KEY: 72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa
+NONCE: 9bee5857772305daa4b550d75f05d808
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267
+AD: cf71408a41729bacb5877e
+CT: a97d4be4873411771d0c3c86bb4a4610649a74d05b1e10db57af6b45d273823462258a9df3b133e46bb134dee4ce97bec666f1c21e029a55b5d40bb34faed140a7e932b0a4b3c9ceb9028221076dd8a9e4e7d18c3c90f19fef440a9304be5fb9c55b241dbdfdfe728808fe06ded668984b9a574c47cf8a3224e2935182502261f1d21455938b39b75dbbc2399b0a105c1dda39e05a262ef27fe4f47343ffe9010c9abf69a8351a7d7c4b30a312a20ad5bf55b5606180b2a12cf5fa1a0b78140adc2db254942849c01d567196063ecb79c9d7ace4331e40e57df620b751cd098fa8c875ae83edd30c40ab9852f98a8cf6afbf60e8adefefb538045117f5e362605305776b748382d048d84cea0e04eb9615f5c26f75c725cdc8f7034ee1d0ae6cc6e08862fe9826945586d5e99f96b79c545e6e7e0579f594199ed16198703de56deac61735d8410534721a32c734856ca5901c5df411a38301b56cb1c6897264
+TAG: e3c5f1db9687bdd32ba9410ef031a99d0854fc4c65959858e3085b6666895b7902e421d18f40dc1ed45f26801ca96c8f
+
+# DIGEST: e5a6b0b09b5b6f4a150bea968150cf2d61401a463f37ad6bb9369496287ac5cce1be57680c8b730be44a0a0cb5875ae6
+KEY: aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee585777
+NONCE: 2305daa4b550d75f05d8089850fea371
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41
+AD: 729bacb5877e72cdfcfa76
+CT: 5d4c72fb3d29791d044da718b25de9934e6b297dd9e33d0f5cb0be6a9193cfe7d850350bd26f6ef889b2295a9f9a82bc7fa139b4201c6ac59c45bff394dfa707178f4ef94ae3739a0f1ef6e385702966102d231fd27a41493318cd51418e90d322439e4ff58feb1f9b45b233eee8eed28738158bca9d53b579184ef5d5687b2a419dc1cef68d4b4f7a782e979f7c4ef2f97f801da6b5aa9d1c0bc0736f50cd3ed4dece7573d895b67a2f2d6fb004806778f6e9c6bb14df1deb8e931dba87287980b3290c84bd7b55aa7daabef5037e583bc5932dfe526a55a128095dee020a5cd99fa3af69ce674a71dab3b4c282e904b8d6eb6f4cacf3026ccaeef0e260381129527e1968fb9c8b728d342100e2d500ecc4d1060a6b32e6730d695fb8aba898d0c64a1fc4a0f39bf64cacaa9265eb2520082f0f8d0c967c4a5113762096bc6a553fa68d2f9778b08807c5e99cad5acce06f45da78c2b9d20a0d4cca6bf7235c
+TAG: 41f514a1d6c62ce2cbfaef46633382dbee960fdb457b52ca54927f6c4d7df66af610458e4b4e0aba0aaf12daa7077e13
+
+# DIGEST: c7f7e52449d4ad8fe48fdd88412657d4b67c9fe9818d7c6549a568b46b89faa3271eb482fa10c024d567f5a7215bc71f
+KEY: 7c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b5
+NONCE: 50d75f05d8089850fea3711265bf7826
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb587
+AD: 7e72cdfcfa76aed06707a0
+CT: 083deb38197f9b8378269fe2c20a28aad6218aa3805d4d1722a6ba7a447710f71244e38d0c33c195949e6171e9c1fb53a522296a2c27562d35896d5948b886f7d5f6ef95a4b27a16a6b524ceb60acf96e1896f76144972b07a763243b5cbbd74599d2a2b64fe9e0e5cf1826f07f8273de31cf819c890d8c1d6ada8f1562d1bd0327671ee4271e1ccf765de3eba46caaf48394265233e3460486f60a3f56926d6807566a712acaa03b04f4623a4abbe0a31c3bd109d58e96cad275d9dadf7790aa1e4be7014be6eb9bced40feed4a3232a179f672aa1c162156a31beb5602527db08883e4bd39c8ec32715a826e957b1f8575a3e5840e373ec45b2aa2ccfb81b2a17a0f23d3114d6c7301c964c7120e722e013140d002a2991920d19f2fe5d25ed265190569b4c3e197e49d19a43dc9f126da52f46ee2b9ec75dbaaa6f594474531b7228ca66be6c820c9b7d42c390b68cde3ce98e886c91fb77a0d10716641d055915b739203f4194dc269a5c67cd547
+TAG: 9b4bbdd474ea4aa51a454d9d64344aec1b6c25366cc8041ea195654753a133082bad1ad0b1f0a276159a6d255af2a3f5
+
+# DIGEST: 80faab70b19291363016e2cbaf46f6025332b4d94540cfa83ea749f93fd7962fdb827a63875b8bc78fa1d19bc3e1845d
+KEY: 19fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8
+NONCE: 089850fea3711265bf782610460bfd24
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa
+AD: 76aed06707a07c3dab6997
+CT: 27d1f2bd2e21f99e75ea4b99877cde2d22c34b2ef059aac79802efa77504e3dbe6883ae4d5e41f0616784d3188add7d06d45d26fdea979be4ea5ae687c81e250c6fc6f8fe1076bd37ec50768889652d7c604b026c41eb97d884cef82cd4c80e93675fcc0a059ce3e0cfc61bf18e84233fed0521a136a4080316b4c9176849732e8e48d61a17d7bd614a4c86e0ba9cd2672d0ece285dd86a532a403cea4b431bb821653b97defcb2076f278f5abf8110239b5319d8b9a6abddbe96228dc16dd512d06c8bf5abdeb2554827952f5b98e93fdd7d49b9a3686e093e8cacc2fe5e283bda680500b48854bc185c703e79969d3181d922f02f2ed0b651646b1c6126849047a3b9f79c624a33e3f8ef68038929252345e1ff1c693b96325c04a897dbc09d363c9eeb63037772808c1911343cca530eb11c69ce39860f82e9b676493499b7f6191bdffe780a770b79aa1a74f0a49fa37f15a24f585869327d24fe59947007bb8486e2246463ebeebc360b3fa4bbb
+TAG: 04b5dd2464a598454ce71270f38385f3c6955268ad62d00c29f5ba5141ecb62dcc60fa593b45fc8ca51ebf1c34429182
+
+# DIGEST: 9084fb9279ff420a90ec2f0e2787db3d8bd4cf700796fca06205d258bd8539f6ba83f34a18fe20387f1890f263bc6295
+KEY: 2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3
+NONCE: 711265bf782610460bfd24ba022e6da1
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707
+AD: a07c3dab699719fe882eee
+CT: e2ea2cac5a4cfdd8631ee6309ff2119e4625d73ffb6e48e8d694c55b7d636fdf3bfca7b100dc78eecfec200fcf58d06314399ae4e646e73f7605fac3c63733c2a5045d4cf83ffcf68603e63f8c646793be1ca25676ecb384810c2cc13ca8007cbe723ceee6f392eb831f9c4c541e21ea993876636326947677ac5b89804f30df4a27d07631c880d3f03776a1b7f24114d0ca4b7d9964757e02066f62ecc4a61922318fd71182de1a56b2202e92c00b8885666f385e07657ad6b92201f7492e8aaf14e741c6f38d7f799d4ad9acf129df2bc634373b5973f1bd257a316cad58a0f17eb03549e5f706ddfa8926f0f20a2c0fa0f81ff4e608b4c968c79305e58e34b528fc1605cedb88f6b733c7544ae95d38f99969f150f189556e5618e525f43437e666be027fc6ac8ecb261043d669eb94ee553e275fd64095f6df62d5789b90aab649d3f7f7167b414fd1e748dc80ab9b0f69bd1abf1b6eb6e737755910e6828a3f9e6a8896f721f1ab1f4c8ff01a40
+TAG: 296d7d9a5118774fcdf5e56b4a7522439851172cbd4a6ec989dac8a66b68e81770c68dc09a805729e3bfda3f3dbff8e1
+
+# DIGEST: 91141fb4499f30fc60e3332541b77ae9d444f2b0108f1cbba1e97a7a610c4c222d169b59752ad3e07ea102bbab306fa3
+KEY: 11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf78
+NONCE: 2610460bfd24ba022e6da12dd4c27f43
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab69
+AD: 9719fe882eee2fee55ed8b
+CT: 58b87fe042cb0c4c869213616b87685eb2eb8ccf80eaf00e68747c919892e7d8bc38d9aa485d9f3822f4da3e2ca327124b0ed52c2f7378a08e0bd787fb7a336439b401c8500b1d70f32d6632a21e411b1160cf967c4178b25e1d479eeb0c455a666d9ea7a7efe210c0978f72eb11990df5fa4153d93baa9bad94641a170f954cea1d2d4cb1ce7e96f9ee793ff25d4d43d008b6d5cf133f61512eaff05fb14be90739e9619796c6d3831deaa7fa2506fa3170f9a4e4a106714744e8196dac22a31e6c9c3a2aa8d6da4d568a61e54e3028a4e59c8c492583314e90479ad88c49ca6394a0ecc3dadf40d5ff0a28cc29eae4a495f180837120dc7e6bbe45abac52b90e8ad0899f40332a07e646888de5a8ea55db87ff1876fd6b7c8ef50f69e1b40029632b9c58d4006fb26c8ba1abf64708009ef67820f670e60db618df3efd9f40e7faee7f859a113d5e9ea7181bf68a26d180bc394856ce57217f4f1d620f3e5b7c9e1220ea726f407aa4a0ec242cb6bac279299450de59389107a4d09df9070c
+TAG: e852a33879a772b23f364737bf548234d2d053e7eb9b1cdf451145dbeb59f734e1f44598e515b476a7d89c83a2286882
+
+# DIGEST: b6fc6a9b1051e686e3cd4a59a4fa38236ec2b78525006908315cf3b1723effbde5ee3918ec19e4a6f265a6da7fdd670a
+KEY: c695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd
+NONCE: 24ba022e6da12dd4c27f437248097445
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882e
+AD: ee2fee55ed8b11534c870d
+CT: c69587a3af9209656e7c8592fbc8a79fffec4dbec3682bfaa5bbab1e9977bb081fac7a73c840de583e97decbbf5a6752576223c4b08958a71e0f981e1f27b1fc4b96cd1e7fd2df2303d6af831ea7ce2b6674d693c74917d04198fc96257f192b9c08cf208251a62e8a66cf99d2e8283dfdb5212095bc16cd88dd00005bc34be680737e64e6d1089e8edf85393fbaaad1c28369ad366ade7baac9a971c00f39d9eb84467410025b98fea49413adbd48196cb9512dd1c806e18570d1f6cc2c2914472f48cdf5993fcf7d6df6cfbd372fb71982304763a0603124104419cca2ccc303774951e9d1a4f41e608623904c4aac898ff3bed9d353279e15a032a04a7bbf4dddb0764728ac457bb4b1d243d8ac0dc73a9c2420029288b97029fd7fe59725d0f6313d81539b7c11558c94947264b4c00a974dd62191b59453731360338be011e381ae6d46a92785147c17ad1dd725221176782ec699620570e35cb348b36d974e6e45f7ea49889094f31756cdbc0fc153748c7d0157b94b90571eb31c7a4b
+TAG: 91d61664b0b11974622fd2c42e17cc28772e16aea82e0ea802d53d9088ad0825ad90fd3409b9b424c3f474750df648b1
+
+# DIGEST: 3eabfc90f8b8cf95f67f221483d4c8c702ef8d75dc264aa289369499e0d2c19b8a61758991de904f7a76a2a8f265b37d
+KEY: f1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6d
+NONCE: a12dd4c27f4372480974454879c41de9
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed
+AD: 8b11534c870dc695b814bd
+CT: bbb6bab0cbe78c3d1066c7095262110fc14c479e44411d469c83e852abe3fd3bbbbfb3456306735b0f469ef93f9d792d7f4a4f3062978f9bc838d664583167da462152f25266bfa520dda945fe7562bfdc2a78191d3c55195f1492af8f31703c171375ff2b2221e9efc6251b346e6a0ea9c10772926a5bb1bc4004f8fdea3e7baca834646803b5177a5c4b6f7822a92a4e4d28c6db9c0932b5c2d019aa1059c376e675f452a6ba35eb7e3517e20dc8ef44996229ba1d69846442ed4f2c5bf9cfb555fb73bd29912d6e5afea45b502a0a5f4de7d90a2922bd80d968fcd39f699590354636de8cac1c49258550d46fbd8298d6cf34dd859f9f2bf6b3ea20aee0e60dbe7f9b7b06d5e6993ca977416e6d450029a5232e4d7349d2707673fae01730810c7a2f5f77d5af3d69f20cb6fd1746d5afe4c1542dcd9a0876960178838aa6cf2edc0e17f87a21634d7efa0f208ef3ef5e6dce8f8b16f46f7e379b1f1eac4b0d789fa4ce9c6484519fd907935c8a252e6081c88532e366777b33f22e361af3
+TAG: af55de50c9f1e3f46c2f1c8afbf3d0c1c414cb149c31f2c43161429b6833b7d0cbf3550309acdcc34a06d75e93dd5583
+
+# DIGEST: 6d539b0f07810da9ebd1089b9c674b2e11d2c4091c107e123351ee1da4eeea4fda44e890e27ef0599721b6c6ce972c40
+KEY: 2c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f
+NONCE: 4372480974454879c41de9ac9f98233b
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c87
+AD: 0dc695b814bdf1a87bb105
+CT: 92a056b861f4177ea827a5fe32c15ecc05ee1243de09975aeb00d5b32ce60666ad858be3ba1deca076199b702003cdf64a4e40d7b3950e5f7f4601366f906eb03a550c2d811221a8a6b2e768ab8d1e576c49b11301ae55939dc7d2aa030936922458e2ec07721cd122a5706a39f0021dc348424ecbe92af1bbf383db837958848ee5655c6a443b3a29a5366ab3b6ab9cf3add4c65cbf39250273a079345611bae3b1096f841f6e027277df046c122d29e1e5b9b882b36bdd0f2ce051dd889b73abf0c454e22e5476f918d357a6091ba3299294c6c2ace938793a56c14072b9166e388644deee327982b773c823636ab0d962881e4805d778cdb6c6034966d4489e86af4399b8076702d6035edf5c38ab4e80e73429460b7631cd212993cce12778f137c97abedba19f38b713870f8d7f63315af67607100a78f704dd0bc44a3a404fd70ca604b6a22b5407f7349281eae5380b698c9e20a3878bd23c9cf35f77e43c529baf21cfd10e3b60fdb06d52a34581bca607573de309d182f080e273d8042933e40d32679fc3746e1c4f3b1fb3
+TAG: d14982292a5ea193cc07d35496c470633bc8fdfcca2e2aa8ab2ba5988780fb27332e5e8479fecd40c2d15282996d296d
+
+# DIGEST: dd422549c5c1351edfa2c98526bf4e2f3f2d6e4267b8e56e3f5a330f13b5df1e2fa2734820384d262c9e3399f41e1fd0
+KEY: 16bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974
+NONCE: 454879c41de9ac9f98233b5a7379a561
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814
+AD: bdf1a87bb1052c6755a7a1
+CT: f8c9831657e40d019c0d05b8f79185eb0e75d27098fc1aa99c66ebff5c97969a378e448fdf30d6f38a792d104228129e4d87e70e85a7ad0a973851c5eeb4a2ede2f35796a2ce6a056f2e8cde884cd0cb4d9f5f7ee1c2ce932d3a597029596af97b07b14b844f4084a7de41106cb77e9d24fb2e4bc647d59c3c47cea97215b08b258ccfa92a30d3cb099b5e5cd6f3fb58de0dca4058e60de309ae9eeab026662eb670db60d6d7de664204e3d7102443182309f4f40321cc1d115995511f16c4c9c2e08486ad616e387739176ec2c7a69435a61f654f27516667785bfa75ce5393896824928e9b69ddc0955c055644d3a704b8dc14650ab1fe01c38c6ff925d07457d72f4a435e36dbeba36ac5cfb19c47af263aaf52912eb77243ec0017b58940efbfadce7cabe38fcb06347f7da1cae9bb03f091984625192375e9c0e3b51ff64c34096de9e3f26fcc02c5a9d023fb5e5d81baadba649cf93699af5131ac44f5f0e08cd1efe577aa7febfe7893667ba892d7a9ed93af763fef4c06cee67d42010831ec05a9113b23a82363ecfe211e24
+TAG: 551fa61429aea3511ccf3f54d108d67aabe71ddd1b0de65957dcbbc7664137155abd4ab894692bc72c49bf3fa814f887
+
+# DIGEST: 9ebe84a97ad57518fb27ea5bbed5c8f576d23454ccf47898e502f4f821468644e84642da310b26f2e57f43615b630f0c
+KEY: a49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41d
+NONCE: e9ac9f98233b5a7379a561792c0f3116
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1
+AD: 052c6755a7a116bfc9095d
+CT: bc607a6306096ce9e70e6bbca7a22d39ad642c58fea6b3f3681dbb24da8279244badf409292187125c7dae096687e19fbe139a5f0f751bed53b960cd39e8918b072680bc3fff249ef9ae5045640bd7f038855f3e4786ba66919cca8dd38dbe8d3f2ab2778d44af12c6bdf4434add471d1e93168df1b7b6e310d9cc727b1f68e186a34498fdedc3b1ecd0de9e79b59b6ca3d5adaa3c75a2b8bb2a892a214aaa37fb321f71d006a1bff1f4d2fd33dcc500d14221ca590b8308aff3c5abb149e137acef7d822ee3442d9740dcc9843a81c542918611cacdf0f80f297c1d4a74aeb9528109b80e23858eb942b507736b5c94942558ac79cd266fd2dd746d2592ce9a043537588d692009d9b417e002fa18689c6ca1a5437745f83ffb925e387ae3552fceb8ef347f1797d37f049986fa07b4b2a4a8bdd043f91fc863c5dc8734463e5761051ef4e038a874b6c8cbded85a399c27eeffb2fb79aab5d3ecda4ff316db38dd05f23a6c6353f12e38bfbc2d415b7633e778600516ff1785a876c300bd3dd0e24e391c5fe3555c13787389eefdf9
+TAG: 7fcfeaa03e5cb5ac9fa8e97100ab1875375d4e0af21cc6b8158a1cd9d6b3935c296459079dd6b13e36b91c2746cec09e
+
+# DIGEST: 81c678d515fb390669db3e58aee272f0f21522c216e0bb9aa7beb23b15810978ef65f53f329c89b8880737e0b0a07562
+KEY: 4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f9823
+NONCE: 3b5a7379a561792c0f3116430e8b6ea0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7
+AD: a116bfc9095da49db3d71f
+CT: 546f158f89157e304802d3b194f4679d887fa5e7b9380fd8a529fa7c101c3ff237c819fb254a75a385bf8e22c4c5129a920c1b0297c6fe06cce701c36ec8dfec315f54b9a1a9c438b39b4f302b921546bbcea00d9bdc1ed7d74e71eeb3f763b41d6f0a640395faf59d61c7b99570004004a5a0e5c97b28cf350cf79e9948c91c1cbb8cf81baef18bffd1cdbe22e82c5c60432003fd7a72da57a2b93f37b9456fab6511ba1c09b6627466cbba48405190d1199fae0eae624903b0c828dfa85341ece889301ee3c38624c4bf6eb19100326761e2dd001eb95791b31ca1fa9d1547d91ef5637b53a0e8461cd3d3515abf9c8afcdd076200cf65bef73903f5565504723b41811d2b49460e08bb401af8969ace8ade353c78fc7a483416b1a7c0c2b06ae1f9cef65a3b7e7db9fffc50bdcce947fae8790dc531bd556fdf447cff672255a5f2316425537c1d6623e7b5239fa87e5e6e4ab781ca21184340c59d9996a22ffe312f3560caf6de5ce18d8d6abb1ed5e4b25e51deee7cc64d389cd8d0dd611d3d7fec39159f7d4c07ba7accfadb8aa39a02d710f27627726917adc9f9da33
+TAG: 87e66f41627b9143258247fa65d04ab856719c940c24044519c194d93d5e3dca95ef96d0e2d783c73784bcf1d64d9aea
+
+# DIGEST: 4194e0c78eb5d9c746f20fb3ff404cab7b61113511843dda287ac5ce30d58959f440fa2e954484c812bf679b250a149d
+KEY: 3f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a5
+NONCE: 61792c0f3116430e8b6ea058c4799eea
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc909
+AD: 5da49db3d71f4b975c5d50
+CT: d63e48dba3eb1d466e836e4e0098739655a4a78557aa3bd8e57be6f9625844c2c42941178d96ea3c1e86faf93299fc8b9b40aa9542b84542370883939cd81266576da98855962d002fa6598fe7bc5c6f5804280b64672d6b7a3a06c4c76afbf62fece44fe375620ada56eae3e4c40b2ee8cb1b4d085e2d7cc9f836e55dda114f5a2dd21df88ebea6ea0a97d65ef014dcf79279571546ade3fba652f6969ae21c692a1f65b5544f7338d3adf420093e519ebe4b11fe589fb8cc952fd267d65b64829c0cec40fd1b44a0ebc8b5b9356b97672248c45c6f357e8c4d493f44395af88d3f905d96040cfa227e301438043f8874d9e4bbf0349fd784157d13c9f3c96d371b9901b550a7376e446bad5435cb885101e950d340c62e1b4b8cf179a7c0f7c407e41f51bab8265f6e5ecc56a921669c9d4e1d13999b442cc40c777b990cccf51b65cc65d72c2cf2e242a34325d8639a4c8a533a3e4e3130fa33346f13c807b21e5fa15121d025f17e0c773d936cd5c294c96292c2f1c40d80940277176cf5667f15fbf593927b1cc0519cf77d227ff42b366a65d1f8ffd42c477fa93dc913
+TAG: ae6065487e4399b2c7d7ea5665227fe3456293ac48c4196c2fe449e828da3a3d8050e27a0e199bd31eee451fdf2f8e5a
+
+# DIGEST: 116de9a066c42ea9935ade043f992e32d73497aec57311610c9eb57376028873632b7a19ea6da6e4878670e6fede516a
+KEY: 8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f31
+NONCE: 16430e8b6ea058c4799eea80abde04ee
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d7
+AD: 1f4b975c5d503f478b22dc
+CT: 761dcb055f9c8420fc734bc8ed9db220299e342e205ae568bad20d8d2936f76a5ab824e43f29cc60568e80e4fda30bb0bd02a2ddfa188c609102aee343dd4c5916877b982e11637f6a2bc719b48b6fd3f54e26210b2ee307ba31eaa15f1ba29e17ca2cab38f219de9559de06de87ecf0dc490e0f7910ca70c588abad351c39491546ff9e49ef1626fbce474ba66690c57d4b856dc2e298ffa02b807d81dec4f13f0aa29f8708b5fe5762de65204276dec4f7e22bfb6771cb1b29919162a4c469cc4f179ea31eec7088a0b546e66daa7798afa655696b486f7ad23c2816fa7b468e9974f1b33d559e8c84eb2a1574a0a20f2a1c084b95b4c8de8d73e104058fc8a434dd2094bd7bf3a4e59d44747c1e7aa9b18747b1c44ac1ec5367e974ee62f5197e0d67cf65ac4505ef465adfd76b858cca29ce86ee1997ca6b12b6468e3b1cc9e651c5cb7272c18781007888a28e9def8e92fb3df84c1858b3f1300e645fd7ce835d41eccd07efe87bd22df4f7f1205a28fda90913586dd79b847bdfef187e0f3c43d6ff51329fa9cd53b536da7eb260b4c4d83c4ba6e7c027ef2d91503b25
+TAG: b7912efb46b759238c73bd65eb4a85633593fc3564a12ff5ae01434692cb3856b626d0015e1e8fea8890071c31cf3660
+
+# DIGEST: a40f5c2f49f4af435f55a093c04ca74147f541866497e7c1ad47c08c5e52a3d60e53d4c69697766d5428cb398666f53a
+KEY: 1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6e
+NONCE: a058c4799eea80abde04ee1de13e937a
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d
+AD: 503f478b22dc8253bee6fd
+CT: 12048f02ca2ef39e4f29e114aa976b6947f28fc51c0d428baec2e180f4a8bcf24d28c954f3f43070ba235576f322231b2cff04e890e916d43eab6cfd9ac0503eab292d5b51bce8e6da431d23bfdcc47841bee19affbe2d8ad7df33a3f6e3f07dfcd00f77f542cfb6f5434967d1ba10ad4b82fd332ae3c973acc2ebe3b905a04806a500ccbfac27c9e73f382a211052115b5a850ecbc797a9c07bc29c3965452f8ebb8500f30312c03ca0028aadb92bd7481e8017ffe05947f3677eb15d17f4441e3ca9f108f54bf60162a55777f98bfe9fda5ca80cb8c3e1bba672fb6e4789042c0f33e3c74a6c05936e3c483496ad901e021cb2f3196ad8d079309c75f27068d3c3c623d56e86154b55634205e580b51323e2de1a73a868b7b055ee616fd2fec4dc7a7920f6178cfe254134e013fb559a02600913c9d2137a2f87964e9bf081c34cc0a71b7afe1a72cf8b21784ddaa7e838325a40f036d20d18de6f6961311854082a099e9be0d543521d4989bf6d386a71091bcd8639e1140be65729d7662b069b0918a1d824dc3152776db07186a3eda12b84b3d68adb134c317682e2bddf
+TAG: 21da030d00f13372d4531f5a09621e7afa9f75330bc9d3d0c580226038e64e2f538b247c100bf690a3f54a4e80795bff
+
+# DIGEST: 361a2336703ec10751387a202d0f3fabee5463eb2e2c5da58cc951dec4d49759d01c48b2cd960f34273edb96b03a64e3
+KEY: 01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799e
+NONCE: ea80abde04ee1de13e937af8f1a6944f
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22
+AD: dc8253bee6fd1b174c307f
+CT: 97c08f8a306208ddc424cd17ee5d596f635b225aab285e7ff5c18227b520c22946ecf7d4d449db30817b89876ced2f3e490e7417c7c4d7b6d13de1583ad02d492829c83a7ff09a35989a21816b3a68492fb179d6281bc2572c37b6a615b3b117bce255a43610171efeaaccc99228dc940a439e9e20773d257ce232095b7a02ade7290dbb95cb48445db7056d5d30f5de69ffcbe2e65bc38c70776c37f0439d4b16b39008a293f2fb9b3dda7b2160aa78b7a16e55c901107f92984b528039844198826ee1709f495b34bf6fe5af4eaca12940f065d3059892c824dcc3950c1e012e82c0b3e19d4d7ddc6404ae3d474f28cbbd50ca02ba17e711094db7ca776c248a96722d7ff94bb208c6c02e05d6dca8170080b5cd07e0f9d303d92c0b6cd1c509d728399be71725393e7ab8aacc206487b0c7290f8418cd2eb529d4a3dd095c367efecc8135c465b427f6fe35d3d00da4d87ecf19001ba8373906aea88cc3414dcf4aff273f283846c39d908ee52536523c078b353fe6d94ebdc16aafd7ad4101bdbcfa1ae8a4066a5aaf1e1ff7a9d068fa3246cf545fe64f80647da52d912aa047558c8fe985fb24521584aafb9af1
+TAG: 696498a8983cb12042c7e62066190260ea884ddca0fb508617af19f5b7bdae9f6c1c61ed671acb558bff169bcbdfe2df
+
+# DIGEST: 2838590aa01ba8edd646d23ef0ad30f66d007c01d96d3582abf6cb2ab113098c1a4a7174e941624f988ed4ae13e766be
+KEY: 9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04
+NONCE: ee1de13e937af8f1a6944f44d7222712
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6
+AD: fd1b174c307f01be95abaa
+CT: 2382a3e4d43619e1596ef90c5b79fb198e4eb178c3ce524b812ccefd8e758427f5854eec76f3b408b1247d6be5fe0b1d6dc5bd061b2a7494b6d40c0fadcf555811de17999d5fb561a542f1269d44b6eb3b7b101b3e746a741b55fc434999bec21fb30fb7d4dd4b75b61e889976cd64b76fea5834a038bad5eac4d8c5bd476a64cfbc08095e36544520aa52b18b25ffc9652eb3523f87e12b82570a590be4c43b124719b50dd14030370f90e9c6e7f55ceefa2f135a98206fd5c7906f75d135639152130fab38a6c2a7edd9bf21a4847da2968e886eb450b5e8f00afd94a21268353ae170220835efa524dae65ae9e6172f32adaf21c3ea29280e6e01c4f380dde9c6d8fac5cd158a95edeb84abeae89c8748c484fc4a58e42003d50bacc1f55094385b17f7a5a1acee5f2ea1e737b832891f1ff344ab2b9b9531e68c5487fbab69772e4abc0d149ea1007fdfdd3cb201d3f2e5753098faca3b0bf1432a9ff55a988222343be6cb131af249fed51e92c24b168bb44acd283354060f28fbfb807036ca11229af09b1d325964cbac93f8a0c674324d81a4dadebc08f6deb368b58bca1cf44f8530a0ff1294c5857da01171
+TAG: 55393b8abccef057bb1ef1a63eb0f578fa310eac799e6b4c920bf8faff10a6570b549d8df1ae98d9cd5fe476b2955c9e
+
+# DIGEST: 1f513f7652c3fe253ce6dfa6bb57fe5a8cccc1be9ca204f05c6ab3a2d4a872d451341a2e0f036f3c96c26fd1355ab00b
+KEY: 2305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e93
+NONCE: 7af8f1a6944f44d722271233a825264e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c30
+AD: 7f01be95abaa9bee585777
+CT: e3658fce6b8bb64c0fbe21eca4027dfaae745275bc257d5c99feb998abd4a6e9521ca1ffba8d54c2d909cb2f2561046d79cdf42a1b8bd086bba23f942c0bc5d56f74f4a9a72f25a4f470f431b64dcd78673836fb238439a21fc1338f09a8e813b08e168f70fd24d880aa304f3dee3184b963c4925766b8aaa44289573943a0c066f208c302ef1536bf125a2b139722581d36d34e904f6d7c5dc354218e1532a0918ac115d0b5fed7cfee50c6430540b64e618cda52f44ea26e7d62c01d6ef12205fffd5a4ed40a5f4581a57394b4e429deda25a96e7d38ecd27f9cbd596701c2e1f42aadcacd4d7cb7ed9713111765ce50476c8888875ed0ccc29edb3f6521a1b1708030d24caabd7725420c5691c642261f43694900b2b357449d43b19309d5e8fbe6a084ff202850cd48aca018cc3e3ed42114c1e3dfcd687be51f27e68cf397273c19209825570d1fbc3444f6ab20bfffe25760e736a3062e8fe0354cfb248a7a48a4f191792abf3c895d8b6b9c934a8c2a499e49d858100159027a067cf0bce2c9de65e4570b4f21761989f8f5af25de362ec3ab61f3544c5381f55e1e2f035c6578cdd74aa6cb9efaf2fc8aaa02
+TAG: d12cb962ff192529283802d266abd9dac7fb7181613ca83ae1dce08d8bfadc02709a572b120ad7abb950f1cceb36d302
+
+# DIGEST: 3a678e3f139009f5af682510ab2afbfbbb7e682887819ee767ec1ff4b58cb242fd13d47addecac33770b99597a622309
+KEY: 50d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a694
+NONCE: 4f44d722271233a825264e977045318c
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95ab
+AD: aa9bee5857772305daa4b5
+CT: 5452596a11cab5e8247db758ea029b27fd2a413d4ea5c7e7e9b7f4e72b3fb93eb4cae4f26f4c443feb029473ff8f229100ecfd6c397bfd6cc4ea775fa2b12f2422383ca4abc4118417c9fa64335fbf0354e152f2245e83cc111475d56a0a2c816ec3f920ca96c446644a44193d744b4ad95f1dd3c1485db8ba50eb8463902019e0e47852dcc2b5367280e1724c357f911f691299ebe68f321d269b5ee5f3ffed5ef4493e125539f85b299f4ec037767a3d68d8c010e9c7a2d0b2d7e3b05c9ee1fd8216698e7e7e79954c1c433a49647d1d3162ec0faee67fda9b027ff5800ab72522036a9cce5e6e42b8a0b8e59d4b3ccb6d2b327e41f8be742196829138214109abb0a34af0f4e91712be0ba6aca8742cca08f0b3117e7be7a91925a4600d7cc69e58583aa61574fef12215f4b4c46e075f62dbcd0f69f6fd655857ed104d921642988a015ecc083a64227dd80ce0b7e9ce080f814542d4243c82c4760b2626ad327a5be9dda7df5daa3c5936924d49514c9a6e3d12d8f31ef0801c0ff34d6188630ced37e4ac3de3d986f20415bc87f6ad86c4046995da036b3a223d0aa16e2e78aa4a809ddb47fc92ad21a76cc35863c54927e0340b2439cef6ec3510d090
+TAG: 8cb7fe4a069b59feaea406eefb2174263985ade17c0e53b33a88011b3986abb5572cd64af432b5d7d621e2f850d77961
+
+# DIGEST: 09ef4355d6f2c34c9088fbfd0b60031e787cc02b79cc63ab05fb244e299b1f1ff136c7ea87f4e76b88ceb30aba40d590
+KEY: 089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d72227
+NONCE: 1233a825264e977045318c9b66262c0f
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857
+AD: 772305daa4b550d75f05d8
+CT: 41e1a02a53b81e3d916b0f7ab52fdf917459dd672a60f366a46112cb26007fb5b2b38f3ca9dc32c116d9c73119061a5c9b1cc421bc63359439dfa4a02891711f858b8206e1b02731b8fd7b40921ebf02c4cc9349978b3c1589c1c81217d19556c33b9f1d45e6afe2f8aa753d13393bd3556f60b71e58a57bec31c828bd3d2c20b148eae0ebedbc7654a080d0aae0766ad0be0b08906ebeb2dc68670815ee91aa0f2ad302d0e28662cd84d83031917f85296fd706028b0c11d41efd8814f22b8c665181b905d1a690394fbfd3317a077b10637e4dce89d85aa54643053d04a0c179aae0498d91130fd1aef5af0f5e12c7fc02bbc6f425995437c24cc59f45f005647f7035e494ae1bb4aad4372f62794bc33bce0b58459a8c32b0986405c2697dfec246e2d74bca42535f424be5d9404b7998695405987f5de3df233ace70be7722e4e36097b1f6f0aa58e6dbb211f4f820e81a697082671bc717259511e2e790b56001fb1d9c1451a729a9d435ee9d4ff2d57225f28c48c20a5ca984597ea5b221e4fdb83f9c7eb3a7fdc16c1fb6851380afd0c2c20c4c555f60c7563a42c4287cf9e62f93508a8d9eb3d21491b4dec3d7d9c8ffdf9f12ee9bca1432f98a5f64
+TAG: c8d6c3e2906ba82d30b780e034afb9645b94c03db9f53c0184d4a19570976d1dac7320c1b65ff304b8444cd019baf76c
+
+# DIGEST: 5a371ae3ceb096ca0a5587e34feb41b60f4aa0bf5a5a6a7076fed1c08d1553bbcbe0d8f90bd57b6d200c793e8cfe3f2c
+KEY: 711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a82526
+NONCE: 4e977045318c9b66262c0f0368fe9d0c
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4
+AD: b550d75f05d8089850fea3
+CT: 54b7b878731dee0ed7e52959582a4ac1c0c112ccc1c92b12f3e5bcf9391161aa48badac21a27051a423f7ce8d346486b347b2ceec45ceda308183bce1add943c6d85031327d5e27fd9cbe28bb7b18ffef443b778858fb60359540aaf62e74e750115a8dba069817d0c324ea6a3a23475997ed851e9a299afc2bf0ac7f653dc5362e846efe9392a720b24b64fa9d446321fd0ef2d54e39737dea22cf94764743522cb67cf21ed9a8ca698dac845fd37fe1beaa3732de61faef354df0e04f8e8ec0fd60e86fab12965e95b8e0b82dd3bd35991c74314cc34c13a9ccfe627520b3a9ed9266bce8bf4b340607e8b0b7d2d2548690ada448d5203963d363f425fcd0fc681f0eec748273127f8f0e366ca10e7f024f82dcc763e587c053a05f49a09c9962617aad3fa6f600ab4081f19de809b431453ea6236afecb5688a5b1a3ac3bc205341a80666c602ade7298969cfb322ef26e154d16b88700ffbea28185f9aa1c109fb0357071e3d8c5655c304095660779c3731ca4f5ff53d577490db2e44a03a8283dcca422eabee388f2f2b2d53d774c0928d5b6e7191aeded5fd2c24ee9c92e5cea9af6b20818b7033464d8cb1996dacef6705c1140035f9747ec97c7fbb
+TAG: 98cb03e5b692229f898a58acb9af158c9ae8cfa43e80996aca95ec911e27203ed65b0ecb213589182b3aa5f064c03f2c
+
+# DIGEST: 0164320db5153924ee78e0257385f556ef41292e47e4a8debf9b94e6f823c777fccb26a85a9a60bbc1f42dc946fec80f
+KEY: 2610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e97704531
+NONCE: 8c9b66262c0f0368fe9d0cb746bbd558
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05
+AD: d8089850fea3711265bf78
+CT: 7b61fdc182df0b0f3e1ef36e99bafb954b295ab39b2aa67f0cbfa848dbbc6ddea6e762e103216e814340b92a539deb7f8aed37a258c993381635b0d00e9fa912abcab37e135e0d88befe38d172c9331376cd541e279dfbed6b7a04fee4f8a4cb9f9f4cafef5d1da9ec104c8eb1eef2fbf79fcac547bcdb6589c03323bf95af0c5e3b3f297467bd40d1c2b11ad38ed396460945ab9cdbf807367fbdc0257519aadb8dc6cb46cc9fe2fc09782a475ecd870e6325f8c42abab69be453aee523c2fcd729b4cece57d82b72c4b4a3d4715f73e1612a894527c1e214f0ff0cba5bcdc5ce830bb1db12f70159d90db8b454b8a19f7d2d14137f64a11ec93886be20dd58af01c6649010158c88fd5b3e19d492977e0ec991832142f5f78361acb243b9419b7a928261cef944f9fa8f00c8bb76ef7b9ce257738da2331cd4504eaf0dc0f61ad2027654c0cbd590f99210243eec65a776faebac13e96f00a03837cceef450fb997c39b1aa680645b8a8bf31afcc05e07ccf0f39fa45d779ccca69dce520cb15717ef4dfad98fc5bf2776a4635edceceb71e99f0278ad0dad826c5dc8b186873de60030c9336d41e877394b3c5a3d8af97927e62351d3ff8879cd8f0bba12991ee5ac0d07237eaa1ad4dce90f7573b
+TAG: cda72a7b5bb39fd7994d1a8c8d9b5bdad80df85a71cf4ee5575e8a10f9d4c9b291e3e2b37fc2364fc1a33837ebd987fb
+
+# DIGEST: d1cb7f5f3b3586c4f413d5d64dbfd58fc798bf0f27b4f97d218cbbb6f0e5d7b2a67599962f5e555e459df7cba95f6cfb
+KEY: 24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c9b66262c
+NONCE: 0f0368fe9d0cb746bbd55813e8d45481
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fe
+AD: a3711265bf782610460bfd
+CT: 4a8618bb21c8b2a26a50d5efde0f4adfef21664419951e96c0ce5b3776c693d49a2cde406ffb23f212c293a60f1884c8be12c902bc24fb52cdbe41e225d3782f62cf2d9d5ad31ff210ab35d07a5fe395b168f575aee5a75b405f7b15dde886f39e34cc038f4bf075764dd9a1ae448e16e64c6538d36f621c10763482961d99ecc1476898d26bfade04cd796ca59b4c6ce92ddecc91109a0bb37b0fc0b08daad10d8c6bc86eb22f3a354d943dfb4d8f3c3805ecb39c645eaac13ecfed6457e254b1bcd2f589d2032e7221a7e179445c5fc063fe1d08e828b03abbfe92ffb95eb442a30f7a469f89f3515455dc647324679bf4df189b8624861a2a17c021ed11ceecbe1a247133d8739b88b93280b2c9279fc967675539f61e1163fb2b64e9eac8219f2ea1faad49a1c77c8246c41c62bac5fe6554fe6d3c6b4e46ab3c305244dbd1e8975bf73dbf8039ad6db23c356bd9865dca873076cdd8b3f6baf659613305dbbc2d04560f2fef872da55e1994d7fbb14320e51b7711354e7edbb9e7709766fadf0c6c44ffadbad87609eccc2b70d4cee87db79efd515de9065d69c24e7b40782d7548e789ebb7c6946989224a3701e02e28e355724f140198aea804fb2dbe18ec2c94dbdcbac61059673695caa6a2
+TAG: 8440ee18b2b8ee075322c43e6d6b97ba201d3cfc5dfb45981ce52fd98a125f70cc9a917a63f88a2babc65d14700030e5
+
+# DIGEST: c9177f83c2d365922afb8d98ac37575e7a4f392ac084573ee6838237cb1b6895fc0cd8ba9a14703fb0dabc13269a8cbf
+KEY: a12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c9b66262c0f0368fe9d
+NONCE: 0cb746bbd55813e8d454817c212d3a00
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf
+AD: 782610460bfd24ba022e6d
+CT: 40867ea63f638c79bb33c4defbf8e35be3a632c60b1bce1eb70f4ecb80c0ec31dfc873bfec82ef82fe170e30cc2ebe3b1dbe341d5b49781a00f2e2b2cf1a5cdada3409c341b141b6ce3c7ea4a6d92c98bc3288297c0cdf11975337b6f03be152bb7917387a3b2b50de49d501e57a06c78e04167d9ed058a6770699e43797ab4b1e51e3c5e622f237ae9e1f99def71a67466db2d957e1ac80b856813337d0969dc3b788c68973fd2b58792a5bb570b8d113fe88763c58d17951c345f5c13fcade97e3c0124c5be3e979f64796746b5667950ac0f0fd43c1930e9e1e90d3598d8c15daa463aa42a46995b21c9d2046814a8a0cf2583a0f21c87755bc340c0270692909b6969d2cabaed1e801bcacfa3218ca1043f5e94fb2935ec55ea7b43f5e47fb9267cf887c2a81d023987ab41b26d4d00e8cdfff7aa486298a97fdaa939e0b0b5a880ccbae8ca68b3f0fa9c6914fa702e87e412b6b5e3e673dfcba087c5f98fe203973b98561aeca0fa33856cfd16cc37cd0f1373575b6badc2163f565e8ce2765cbfe9264076388f431161b652e9fa5547529b9e6c3c7e848d97d9253005609654975c17d1d5fc600c803d8108b9ecfcadd354bdfb96edc46607d41556c442c33b1bf8adeee269d661539af43b61e
+TAG: 6ce735b1dd6ee407e0f77d045b4fa5887f8eb95c9651c595ec20236c17701c389178e6ecaadc27f09bc0967fdaa51ac9
+
+# DIGEST: 0cc8dec69ce877aee11ef0245ed7bbc1f18230562b69b280a4f9e460839eab2de6f1d380df5002e7dc50feabc589d46d
+KEY: 4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c9b66262c0f0368fe9d0cb746bbd5
+NONCE: 5813e8d454817c212d3a0063be26e063
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460b
+AD: fd24ba022e6da12dd4c27f
+CT: 02c169fa50f4bbbe70f9fa2193ad1e2abe20477b7f0bc3a966819d04b65892d1159154c703219632c7a3c9ad3129de230c3d3cc3e88517712531583dfd6b7f57ddfffe8b7eb4d0ac81ed3be7fc80f6d71d82a322f890e071dd210d1726bc1cc1f6abd78d044b65036dd7cfb728589fbffe26b7b954578ac0036c5e9f7eacbff13ab98201f1e894f57304bce324ff5bc61f5850f1048f30f302086a5804f366bf58ce61d949465ba2ba7d31cc3ac7f5952356ab3de8e7844a6f2c197b67e32ecc2b8480f8e81af75e6d1019e11f7ee0b9338de462871910783faff9eaa1f0fbca258f6872a7ca2dd708b1c059d41e4cdcd7fa1eb616f817b53bb3d4f6820fa87ae44c65bc5dd74e0e922bf4ff540221424568bfe74feb139e1af8a540a5e8431532f7332ef924af01922070da6c14f3ae784a18790368a1f1a0e4295fa6ce0a686641de77fa91a615dce62a0eda98c9ef252eff58280243bace254db39b09025491dfb8ffccfd8f7396caab122446f74f6847016b390f0163ff1b30786e8883607d74c3fef78cf63be2c0acf04830be0f8afc9412f08a6d5d8e9c985d8d6571e4d69f037940625a91f6ad518c5b5d956b1a4e7f4b7a300babd8ebb190cb170b51991119d8d33cac92872936e9b563d4c58d840cfe6d6cc6e1fd7f96d82102f4a3
+TAG: 004494119c163d2e324b8ce041418646d6a188291698e310362baa3e3ba5feaefba7f26407a16c8424859d4aaa5df5f7
+
+# DIGEST: ee57c943aac622c923e0c2f6b1040eb536856c0eaf8d4db78514164fc7c57411061241a2c78c1af4f1bd429f09a052fb
+KEY: 454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c9b66262c0f0368fe9d0cb746bbd55813e8d454
+NONCE: 817c212d3a0063be26e0636617781e85
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e
+AD: 6da12dd4c27f4372480974
+CT: 2b54aa2f9adcb4109a34cccdb246b73eb2f97df4da95bf9ddd0b85c53382b957cd344514455c2de03173cdd5441f783d1a0673ece4654282e3cb90a79acd53ce4f9da316f2958b01b791e70d9a9379fe87db63ea95710be3b89f4411366971650680a5e46133b3258491c2c68c6abfd53b3aff803ec0b2ca2f3dc1168f8a8deab7bcab3ac5afc7df939259d50236b241699f4cd3e8fb9d84e5e8e178ad1e39fd5b37addb846eae3baba35d7266e3720d5cb4498b0affbe24fea46e254462227d16ba181248aff05e1415cc4ee81b51756be206ef3ecdc4a709b591375a2758137514fed5d954d9d661a0fba7f1238b06ed32515afbefcc296c467371b1df69dd34eb4c1a25feb20f9c77052eb02d2fbd90b3fc81256e30d1fc54c731b4987f089857bd6674428e01d7a2247aac43fc1ee55def21faf3c7cee4cad9c9205288b5d4b52cce55889fb3800ab7efd9a9c8dcf13199c687d70e306c364fcfc67b8decd24033dff056be0c7454b8c991aecf380da7b12c1332c7b63f32716089168e548bb92168307b97081a4b46fd56d85505f1dba460b83fbf0ef8155668fc62f1938a5a2e2c1989d5ff58435e3a3c8202ff4e5209e6d04f0a00e6a283bbbec8ae88fd7b52f3e7ea0df93e0f0c80fade89b9d521fe8a761a617fc459c1b23f56070c
+TAG: 0b8526a621c052774153225a30ec6d9cd1541be00c3c0f190892da6ae4ea368c2c5a3723f0b59b89ec27f4d4ed4d1a00
+
+# DIGEST: 80dc411121ed974cb7c835fa89f4118eabfcf42e5bc720b82b57dd6f9d0e82dbe1cc7f9940c24989ebf16d6cdc56018b
+KEY: e9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c9b66262c0f0368fe9d0cb746bbd55813e8d454817c212d3a
+NONCE: 0063be26e0636617781e8591a6c6a196
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c2
+AD: 7f4372480974454879c41d
+CT: 2b71c8e3167dc7f9af0b0262a21fb3a0c96e4d718746e696727ea6ad66f7025da2068763234fc0145f4bfd1fd72823a561765b7deb09d94e450a7900d9bbc043fc357b4b0b7a3c58c9296ddf24cdb1e512f21c7a985149ecd8ced6c37b8e978478e375493c6d4d8a6370200364bd475bf3ea057c027f0fdc943eb995437420672ac97605c32646aef8a041b24c7161c8d9442630e4969f03ff0496f76df605d074de57c2fcd0148b3775e17f33a732b6b98ddc859aeffee95be88d82394e1f1afefdc8495c24dabf73b8c6c6cbcac255bc72269778bade183be2fba30b7689ed9517fa5defaf515826ee20144f870efff3d78d34c66c61a87f1b0d9376fc0da7bd0cfdcb7393d36d1c4bfa21840cd06aa097655ae5aa2902c6ffed0cb1065d24664e5cc28188bb72f0a056a6ab451e6a6eb030533a9111c3744a4845807c7282e85a24daa3a06943e8bf0471328025995fa15ec0164810405bee5175211bce9fe27d321e4536dd3d6e15469ff370d1c400f29bae50441c085ce78f91fcab367c15a0b9e3b01f741b067709e684d607154875f34f4bdf03fb29ead4687310349b1501b3afeea224bbb95a26c25622e40e244214af2bbf3907905ecd88f46c89a5061f27b19adbc6c788fbc9ccaf9fa6ffb101c4dc2c06efb3cab8f004126d789d
+TAG: 9b5d62a77353e22bdd46652a8619c7b3001789a7ef746fe37afaf8a509c1662da515b4a8c4e8292e1e07e977ded352f9
+
+# DIGEST: 9e5fa1cdd02e7db7705cfe6107db39192c778c1ec2f6c58116e4159394858791effea9245bf0ddb0c6982cf91df5d9b2
+KEY: 3b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c9b66262c0f0368fe9d0cb746bbd55813e8d454817c212d3a0063be26e0
+NONCE: 636617781e8591a6c6a196868dee0c1c
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f43724809
+AD: 74454879c41de9ac9f9823
+CT: f29d253023b7c21c9ba097e4110101081b3d6af8d9d3b785c4c3a0e47a152cf7eecb33b5717e7f0a7d78c447aab987a70bc9c972f6b7cb4f43e8ca5001870cd306df554c70b3c327215634ad992c6d5b33f759a22123b4e376132656f9913b3b87bcac24fad0f123dfbf546ee71292c282c1c4bb21b6f4d6a56dda5d8968da822c2f6e45e7cb9284bb6f84eb64fa50d418104e966f488828cbd6f312f05c188b68b8aa824d7df75b4a2edfff1d67c0c6fe708dcae42ce7f1e11164e5ada8babfdb81f3ec54a8735ecac4afa54360b2fe766c7a7a1a4e037d77e5d4e5017399282ed1fcb8cb1b234f9565261449b32edbdbf01208cf573512cbd8155af6e00c4ffa98e2f4dd3acbecc132f92226db83fdc28f6532b143a8c25625b759a50b27aeef92bf840b77aba3103aef102b4750c752ca422ff6654ede8341306fb7a1d4251e753bf19d26a8637287634c2ca6baca7d3fe0edf5fc913808976006391f9f16657958374e2e0715b28e1bb1446845674c88c24f369969de33fad62118e24be11f8db058b27aa15bdde4e3ff803ba4a264eada9d69f3157551b4f2a728f223dd986708c9f9763fc2d02101a40a0648b1c211f48c0d720645fd18beb6137b2a7cd0ff20a445e99d66a872c3714e52a553d2e66ae3033778ed2837b3dc540b50b70e2608bc3483bf8e9db8a2abbe288655
+TAG: e130f0459c4dfde80d3ca84b598695e2e678735157258dc238b6457f5e464473352e019cb4bac880e72332581d5aca03
+
+# DIGEST: 703473db66fec69eb1310c49e13b6a10777d97c5239fdd4a32449f2b5c32bdf1d08dddeaedc0251cc0bfb87da2030de6
+KEY: 61792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c9b66262c0f0368fe9d0cb746bbd55813e8d454817c212d3a0063be26e0636617781e
+NONCE: 8591a6c6a196868dee0c1c0781065055
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c4
+AD: 1de9ac9f98233b5a7379a5
+CT: 74683b4d9443a715d1783e37f9f33d37c8c7d47d628204abaa590cf604ff88070045f76f8027875c1ad708b601200fc8f181757f8270a2d146b22a388c015de42b2b271d754ef89b6e4c3ab1244ad81d9978bb9f43bb0fd99ed601ea0c14ed1127bda4b0960c500663bc4f34ee9d1ff105f857934fb04793a22208a51f13905410538ee56df3111e6a55776582a6c927b95c2b6e3c1a91355fbba474046a26a6480138be5dcee13215edb98ee28b75ce567ccf5de3d8767078d1f9f755cbd0d19911cfa6b2a6fa97636c9984f2e4b86276a860e49ed2a1ce47fa5572d80b384c37c091698778a52c6e1c87ac73f26443803ba2945f8ebf35f3ab9f2f0136869f6acae5eea4ebacc674679a2c58858452ae86e064242183cff9306a3874925af99fbc4b919cd5f949c692a83786d9d4063a10598acfe0fedc863330b45a4a2d9eaee3a2ed8fdcc848feb6008f14f88e6e110c9f2491a83f6e216ac034dc1319d63739df19b5607001195ed45feb35dbb47ea38cba7a5051db17119631a40cc99f7f956e4b9adf05ff111faad50e5ca78167ba37dda6019e3786b042aa57d328f639e12b782743d0f94a45a4ecabb72fce616c416ee77d8031542a4e59638696c71640e09717fe9ee248097c27c86fee64806624d9540990410dac0cbd06330568bbcc303d1070a48c36b93a775550a2cb
+TAG: b4789c75916cdf2df8a1ad1095e327f46e91a05b4ca26e01fe51a51af3a5d73f2b653e76eef70a3ca290b1482f3279c7
+
+# DIGEST: e96830967214251621bbf449099c3333ce8b37d4417d13943955d1d56ce43fab845de9e38405f6cc4fba07b8f238f80c
+KEY: 16430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c9b66262c0f0368fe9d0cb746bbd55813e8d454817c212d3a0063be26e0636617781e8591a6c6a1
+NONCE: 96868dee0c1c07810650555861d449dd
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98
+AD: 233b5a7379a561792c0f31
+CT: 57878ab87bdc04e3c96214d485d14caa3f65c7d0b7ce5a03b7ab53ee501e21b91d227423dcb5a8f4629c01561bb17ba56d433ae648f2886ec087b9f6a2beff3a079ee25809a12534bfb65e94e0c2f7ff74497db708219840266102371609564e7dbc476bcd1d00866bef78a7f96843478760c2ae7338f789e73a2bb8b1a3e604b6c38cc0134bcfda72da30c5de221390099396709ced02a0312e6f86d29852878a6cb1fcf966d62b72d2099bd22007dcb1d42a8903bd70b5ca5610a8a4112837474963d1e6ce105b8c58e548e553b60ab5e1bbb9f1df31f4518b40bc6d69078a62013bbd78c9786881c4c53a75a710787d15a9ff0a4f0bd355cabc7df781702fbe124232331e0d0260f9810190245e346ab086ee986c7c9c0c84a1d531fa6900aaefd0a8b9b9c0e0372751f6d23cfe9f98294fa114da2f52409bd6ed73069f0dabbc7571ec10161cf07f1fa60c2901a05fefb88632e3e88b62a799b80ad6ed506c3442f064712dbebe893ff034620c0fce4a2d89b3a101c6652cdd46cf98073f7de3e1c3efa8211a9ec8ef7273ed0e1333eda03b8a3c57381175dc7495ca799b419f72169534dc8995fb0f63d396f5c5bbfd86f9e1822fe8590b24ccb11f7b66ff5c515bc7e9654238dfdaa70bdd6b7236954914dd332886ef2840c5aaace8c39968ad277303d78cbe2f7e02b3d7d2f5
+TAG: af4901d32845aa5d64289a40ca03a2235c8801c7d4adb18a8c3a4e84af83c2842e973483d5cff6a1a6050aff512cc7b9
+
+# DIGEST: 5e69338cb47e83dc76efcd3d20ebb4a9c9e8288b709c554a39f344dfdc691b58fe2234ec740167f6976d1e9f2775cca6
+KEY: a058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c9b66262c0f0368fe9d0cb746bbd55813e8d454817c212d3a0063be26e0636617781e8591a6c6a196868dee0c
+NONCE: 1c07810650555861d449dd43726a4e03
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379
+AD: a561792c0f3116430e8b6e
+CT: 7082642b0cc17e3ef8cadb87d81d3e973dd92e18a45e72833b34e6c4a2d24a77a1048b96e6c19a82732eb355438d577ef8e33ac646d374d99ad15c633bfccbea5e31ca27aff9e1e9b335708bbd62e3ceb7db34178a9111fc2a395957fde085b7c17645d7a473326919e7c24206a332ed8db0ac372aba510c72f1e3d480197b6811fe9bdaaad328bea365a8e732911be04a7e4bf8adb9f7d2d2e2b436287b5a5eee1dc11f43b7e12d83f83c1d928d1ace7c625abdb704745c4e2d5575aa4f0eface8bddb22c9db6aa9a32f5fe879b8210ee78c09c0be83e039ca7d64bef8dadf89bb966966e0306fc138a57d6a3f208e987c643d80b2bdb8a71eaf8b2e8ca33eadd49e422c99dafe511fbdcbfaa39aa6170d57d1107f9ccc80caee2bf0b3d3928628694e3d42b49d69c02c13685a2175493771fcf93704b95b621b491f4cd3231c1736a5abcc41d0b20722c21b23c4631a0e13134c36be19bd8a8ddcac189518facf810688cf69b28d9548621357ad635b40c253a1af855b896395db2e5ffa2f1388b3860dd5997ab42e329c6beb926db93899a7daec7b408a86f848d7db34374fcfac9fe8a875622947fa067954b47946dff7d042bbde8e64fe5e3bf894bd632a80c63581c26935abf19a944989568511983c6e3839a0f4f5c521671da973f756da87e146a3db56314254d95172f1964
+TAG: 0c5cc64d87084321fc1707667d2c39e6186e9690aa90bc2ba26007fbac8878ac9f769b29375119c5d6cac500eba86cab
+
diff --git a/src/crypto/cipher/test/aes_256_gcm_tests.txt b/src/crypto/cipher/test/aes_256_gcm_tests.txt
new file mode 100644
index 0000000..021c275
--- /dev/null
+++ b/src/crypto/cipher/test/aes_256_gcm_tests.txt
@@ -0,0 +1,420 @@
+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
+
diff --git a/src/crypto/cipher/test/aes_256_key_wrap_tests.txt b/src/crypto/cipher/test/aes_256_key_wrap_tests.txt
new file mode 100644
index 0000000..92d3a04
--- /dev/null
+++ b/src/crypto/cipher/test/aes_256_key_wrap_tests.txt
@@ -0,0 +1,23 @@
+# These test vectors have been taken from
+# http://csrc.nist.gov/groups/ST/toolkit/documents/kms/key-wrap.pdf
+
+KEY: 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F
+NONCE:
+IN: 00112233445566778899AABBCCDDEEFF
+AD:
+CT: 64E8C3F9CE0F5BA263E9777905818A2A
+TAG: 93C8191E7D6E8AE7
+
+KEY: 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F
+NONCE:
+IN: 00112233445566778899AABBCCDDEEFF0001020304050607
+AD:
+CT: A8F9BC1612C68B3FF6E6F4FBE30E71E4769C8B80A32CB895
+TAG: 8CD5D17D6B254DA1
+
+KEY: 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F
+NONCE:
+IN: 00112233445566778899AABBCCDDEEFF000102030405060708090A0B0C0D0E0F
+AD:
+CT: 28C9F404C4B810F4CBCCB35CFB87F8263F5786E2D80ED326CBC7F0E71A99F43B
+TAG: FB988B9B7A02DD21
diff --git a/src/crypto/cipher/test/chacha20_poly1305_tests.txt b/src/crypto/cipher/test/chacha20_poly1305_tests.txt
new file mode 100644
index 0000000..b7f1cc6
--- /dev/null
+++ b/src/crypto/cipher/test/chacha20_poly1305_tests.txt
@@ -0,0 +1,524 @@
+KEY: 9a97f65b9b4c721b960a672145fca8d4e32e67f9111ea979ce9c4826806aeee6
+NONCE: 3de9c0da2bd7f91e
+IN:
+AD:
+CT:
+TAG: 5a6e21f4ba6dbee57380e79e79c30def
+
+KEY: bcb2639bf989c6251b29bf38d39a9bdce7c55f4b2ac12a39c8a37b5d0a5cc2b5
+NONCE: 1e8b4c510f5ca083
+IN: 8c8419bc27
+AD: 34ab88c265
+CT: 1a7c2f33f5
+TAG: 2875c659d0f2808de3a40027feff91a4
+
+KEY: 4290bcb154173531f314af57f3be3b5006da371ece272afa1b5dbdd1100a1007
+NONCE: cd7cf67be39c794a
+IN: 86d09974840bded2a5ca
+AD: 87e229d4500845a079c0
+CT: e3e446f7ede9a19b62a4
+TAG: 677dabf4e3d24b876bb284753896e1d6
+
+KEY: 422a5355b56dcf2b436aa8152858106a88d9ba23cdfe087b5e74e817a52388b3
+NONCE: 1d12d6d91848f2ea
+IN: 537a645387f22d6f6dbbea568d3feb
+AD: bef267c99aec8af56bc238612bfea6
+CT: 281a366705c5a24b94e56146681e44
+TAG: 38f2b8ee3be44abba3c010d9cab6e042
+
+KEY: ec7b864a078c3d05d970b6ea3ba6d33d6bb73dfa64c622a4727a96ede876f685
+NONCE: 2bca0e59e39508d3
+IN: b76733895c871edd728a45ed1a21f15a9597d49d
+AD: cc1243ea54272db602fb0853c8e7027c56338b6c
+CT: 1fb9b2958fce47a5cada9d895fbb0c00d3569858
+TAG: 042ad5042c89ebc1aad57d3fb703d314
+
+KEY: 2c4c0fdb611df2d4d5e7898c6af0022795364adb8749155e2c68776a090e7d5c
+NONCE: 13ce7382734c4a71
+IN: 0dc6ff21a346e1337dd0db81d8f7d9f6fd1864418b98aadcdb
+AD: 0115edcb176ab8bfa947d1f7c3a86a845d310bf6706c59a8f9
+CT: dad65e4244a1a17ce59d88b00af4f7434bd7830ffdd4c5558f
+TAG: ac1437b45d8eacf9c0fe547c84fb82a2
+
+KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865
+NONCE: 5d9856060c54ab06
+IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e
+AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51
+CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36
+TAG: 6dd98710d8a889dceea0d0a936f98617
+
+KEY: a8b9766f404dea8cf7d7dfaf5822f53df9ccd092e332a57f007b301b507d5e14
+NONCE: c7f2f7a233104a2d
+IN: 4d6faeaee39179a7c892faae3719656cc614c7e6ecd8fcb570a3b82c4dace969090338
+AD: c6d83b6a56408a356e68d0494d4eff150530b09551d008373d6dee2b8d6b5619d67fdb
+CT: a15443f083316eef627a371f4c9ac654d0dd75255d8a303125e9f51af4233ff4ceb7fe
+TAG: 52504e880f6792a60708cc6db72eae42
+
+KEY: 5e8d0e5f1467f7a750c55144d0c670f7d91075f386795b230c9bf1c04ba250bc
+NONCE: 88049f44ba61b88f
+IN: 51a1eebcc348e0582196a0bce16ed1f8ac2e91c3e8a690e04a9f4b5cf63313d7ad08d1efbff85c89
+AD: 5d09bf0be90026f9fc51f73418d6d864b6d197ea030b3de072bd2c2f5cab5860a342abbd29dba9dc
+CT: 35aa4bd4537aa611fd7578fc227df50ebcb00c692a1cf6f02e50ed9270bd93af3bc68f4c75b96638
+TAG: ccea1cbbc83944cc66df4dbf6fb7fc46
+
+KEY: 21a9f07ec891d488805e9b92bb1b2286f3f0410c323b07fee1dc6f7379e22e48
+NONCE: 066215be6567377a
+IN: c1b0affaf2b8d7ef51cca9aacf7969f92f928c2e3cc7db2e15f47ee1f65023910d09f209d007b7436ee898133d
+AD: dfdfdf4d3a68b47ad0d48828dc17b2585da9c81c3a8d71d826b5fa8020fee002397e91fc9658e9d61d728b93eb
+CT: 8ff4ceb600e7d45696d02467f8e30df0d33864a040a41ffb9e4c2da09b92e88b6f6b850e9f7258d827b9aaf346
+TAG: 4eeddc99784011f0758ba5ebfba61827
+
+KEY: 54c93db9aa0e00d10b45041c7a7e41ee9f90ab78ae4c1bba18d673c3b370abde
+NONCE: 3f2d44e7b352360f
+IN: 1241e7d6fbe5eef5d8af9c2fb8b516e0f1dd49aa4ebe5491205194fe5aea3704efaf30d392f44cc99e0925b84460d4873344
+AD: f1d1b08dd6fe96c46578c1d1ad38881840b10cb5eae41e5f05fe5287223fa72242aea48cb374a80be937b541f9381efa66bb
+CT: 027b86865b80b4c4da823a7d3dbcf5845bf57d58ee334eb357e82369cc628979e2947830d9d4817efd3d0bc4779f0b388943
+TAG: 4303fa0174ac2b9916bf89c593baee37
+
+KEY: 808e0e73e9bcd274d4c6f65df2fe957822a602f039d4752616ba29a28926ef4a
+NONCE: 1b9cd73d2fc3cb8e
+IN: 3436c7b5be2394af7e88320c82326a6db37887ff9de41961c7d654dd22dd1f7d40444d48f5c663b86ff41f3e15b5c8ca1337f97635858f
+AD: d57cfbe5f2538044282e53b2f0bb4e86ea2233041fb36adb8338ded092148f8c2e894ef8766a7ec2dd02c6ac5dbab0c3703c5e9119e37c
+CT: 9b950b3caf7d25eaf5fca6fa3fe12ed077d80dcd5579851233c766bb8bb613ec91d925a939bb52fb88d5eda803cfe2a8cda2e055b962fd
+TAG: 6bf5b718f5bbe1395a5fdfcbbef752f5
+
+KEY: 4adfe1a26c5636536cd7cb72aa5bded0b1aa64487ad0e4078f311e8782768e97
+NONCE: d69e54badec11560
+IN: 19b3f9411ce875fcb684cbdc07938c4c1347e164f9640d37b22f975b4b9a373c4302ae0e7dfdeba1e0d00ced446e338f4c5bc01b4becef5115825276
+AD: bda1b0f6c2f4eb8121dcbd2eebd91a03ae1d6e0523b9b6f34b6f16ceca0d086654fb0552bfd5c8e1887730e1449ea02d7f647ae835bc2dab4bbc65b9
+CT: ea765a829d961e08bacaed801237ef4067df38ad3737b7c6de4db587a102a86fc4abbaabea0ee97c95ca7f571c7bab6f38cbae60cd6e6a4ce3c7a320
+TAG: b425cdf10cd0123a7e64b347c6b4b1f0
+
+KEY: eb3db86c14b7cc2e494345d0dfb4841bbd3aa1e2bc640cca0c6c405520685639
+NONCE: 88b54b28d6da8c81
+IN: f75c0a357271430b1ecff07a307b6c29325c6e66935046704a19845e629f87a9e3b8aa6c1df55dd426a487d533bb333e46f0d3418464ac1bef059231f8e87e6284
+AD: 34b08bb0df821c573dcb56f5b8b4a9920465067f3b5bf3e3254ea1da1a7fc9847fd38bdfe6b30927945263a91fa288c7cf1bee0fddb0fadf5948c5d83eb4623575
+CT: 146ec84f5dc1c9fe9de3307a9182dbaa75965bf85f5e64563e68d039a5b659aa8863b89228edb93ff3d8c3323ab0d03300476aa4aca206d4626a6b269b2078912d
+TAG: 0058a8dff32c29935c62210c359bd281
+
+KEY: dd5b49b5953e04d926d664da3b65ebcffbbf06abbe93a3819dfc1abbecbaab13
+NONCE: c5c8009459b9e31a
+IN: f21f6706a4dc33a361362c214defd56d353bcb29811e5819ab3c5c2c13950c7aa0000b9d1fe69bb46454514dcce88a4a5eda097c281b81e51d6a4dba47c80326ba6cea8e2bab
+AD: fe6f4cbb00794adea59e9de8b03c7fdf482e46f6c47a35f96997669c735ed5e729a49416b42468777e6a8d7aa173c18b8177418ded600124a98cbb65489f9c24a04f1e7127ce
+CT: 911ead61b2aa81d00c5eff53aeea3ab713709ed571765890d558fb59d3993b45f598a39e5eff4be844c4d4bd1ef9622e60412b21140007d54dcf31b2c0e3e98cf33a00fd27f0
+TAG: d38d672665e2c8c4a07954b10ecff7d9
+
+KEY: 3b319e40148a67dc0bb19271d9272b327bc5eee087173d3d134ad56c8c7dc020
+NONCE: ce5cf6fef84d0010
+IN: 27b5627b17a2de31ad00fc2ecb347da0a399bb75cc6eadd4d6ee02de8fbd6a2168d4763ba9368ba982e97a2db8126df0343cdad06d2bc7d7e12eec731d130f8b8745c1954bfd1d717b4ea2
+AD: a026b6638f2939ec9cc28d935fb7113157f3b5b7e26c12f8f25b36412b0cd560b7f11b62788a76bd171342e2ae858bcecb8266ff8482bbaed593afe818b9829e05e8e2b281ae7799580142
+CT: 368fb69892447b75778f1c5236e1e9d5d89255c3d68d565a5bba4f524d6ad27de13087f301e2ef4c08f5e2c6128b1d3e26de845c4ac4869e4c8bd8858ad0d26dec3b5d61a9e3666a3911ba
+TAG: 2e70564c3999c448d92cc6df29d095c4
+
+KEY: 43bf97407a82d0f684bb85342380d66b85fcc81c3e22f1c0d972cd5bfdf407f4
+NONCE: 8b6ba494c540fba4
+IN: 4b4c7e292a357f56fdf567c32fc0f33608110d7ce5c69112987d7b5a0bd46d8627a721b0aed070b54ea9726084188c518cba829f3920365afc9382c6a5eb0dd332b84612366735be2479b63c9efc7ff5
+AD: 1e0acf4070e8d6758b60d81b6d289a4ecdc30e3de4f9090c13691d5b93d5bbcef984f90956de53c5cf44be6c70440661fa58e65dec2734ff51d6d03f57bddda1f47807247e3194e2f7ddd5f3cafd250f
+CT: d0076c88ad4bc12d77eb8ae8d9b5bf3a2c5888a8d4c15297b38ece5d64f673191dc81547240a0cbe066c9c563f5c3424809971b5a07dcc70b107305561ce85aecb0b0ea0e8b4ff4d1e4f84836955a945
+TAG: 75c9347425b459af6d99b17345c61ff7
+
+KEY: 12fc0bc94104ed8150bde1e56856ce3c57cd1cf633954d22552140e1f4e7c65d
+NONCE: d3875d1b6c808353
+IN: 24592082d6e73eb65c409b26ceae032e57f6877514947fc45eb007b8a6034494dde5563ac586ea081dc12fa6cda32266be858e4748be40bb20f71320711bf84c3f0e2783a63ad6e25a63b44c373a99af845cdf452c
+AD: b8be08463e84a909d071f5ff87213391b7da889dc56fd2f1e3cf86a0a03e2c8eaa2f539bf73f90f5298c26f27ef4a673a12784833acb4d0861562142c974ee37b09ae7708a19f14d1ad8c402bd1ecf5ea280fab280
+CT: 9d9ae6328711fb897a88462d20b8aa1b278134cdf7b23e1f1c809fa408b68a7bfc2be61a790008edaa98823381f45ae65f71042689d88acfa5f63332f0fba737c4772c972eba266640056452903d6522cefd3f264e
+TAG: e9c982d4ade7397bcfaa1e4c5a6cd578
+
+KEY: 7b6300f7dc21c9fddeaa71f439d53b553a7bf3e69ff515b5cb6495d652a0f99c
+NONCE: 40b32e3fdc646453
+IN: 572f60d98c8becc8ba80dd6b8d2d0f7b7bbfd7e4abc235f374abd44d9035c7650a79d1dd545fa2f6fb0b5eba271779913e5c5eb450528e4128909a96d11a652bf3f7ae9d0d17adbf612ec9ca32e73ef6e87d7f4e21fe3412ce14
+AD: 9ff377545a35cf1bfb77c734ad900c703aee6c3174fdb3736664863036a3a9d09163c2992f093e2408911b8751f001e493decc41e4eeeed04f698b6daed48452a7e1a74ec3b4f3dcf2151ca249fa568aa084c8428a41f20be5fd
+CT: 229da76844426639e2fd3ef253a195e0a93f08452ba37219b6773f103134f3f87b1345f9b4bf8cfc11277c311780a2b6e19a363b6ac2efe6c4cc54a39b144e29c94b9ebbde6fd094c30f59d1b770ebf9fcad2a5c695dc003bf51
+TAG: b72acab50131a29558d56ae7b9d48e4e
+
+KEY: 4aeb62f024e187606ee7cc9f5865c391c43df1963f459c87ba00e44bb163a866
+NONCE: 9559bd08718b75af
+IN: c5d586ceece6f41812c969bcf1e727fe6ff8d1ae8c8c52367c612caa7cdf50e0662f5dffc5ea7d3cc39400dfe3dc1897905f6490fd7747b5f5f9842739c67d07ce7c339a5b3997a7fb4cd0d8e4817ff8916b251c11ef919167f858e41504b9
+AD: 51f5b503b73a5de8b96534c2a3f2d859ece0bd063ea6dfa486a7eec99f6c020983f7148cccb86202cf9685cc1cc266930f04e536ad8bc26094252baa4606d883bd2aeed6b430152202e9b6cc797ff24fc365315ed67391374c1357c9a845f2
+CT: 252ea42b6e5740306816974a4fe67b66e793ebe0914778ef485d55288eb6c9c45fa34ac853dc7a39252520514c3cb34c72b973b14b32bc257687d398f36f64cc2a668faffa7305ab240171343b5f9f49b6c2197e4fbe187b10540d7cdcfa37
+TAG: 711ff33ef8d2b067a1b85c64f32f1814
+
+KEY: 9a19e72f005cae1ae78b8e350d7aabe59fc8845999e8c52fad545b942c225eaf
+NONCE: d9dae2ea8d2ffc31
+IN: 2110378d856ded07eb2be8e8f43308e0c75bc8a3fcc7b1773b0725b7de49f6a166c4528e64120bdf7c9776615d3ce6feeb03de964a7b919206a77392f80437faceb6745845cafc166e1c13b68e70ca2a1d00c71737b8fcbbbd50902565c32159e05fcd23
+AD: 1cd73b72c4e103afbefd7c777e0480f3f5e68c60b85bd2e71ef5caebb175d7fc6535d39f38f92c24f2eb0fe97d878ed3d5967c0bb4394a5d41f7d34cda6e1523d3848f049cde554a7d31e1afeab5d3e6150f85858335cbd28c8a7f87d528058df50eea06
+CT: 5f009fbce4ec8e4ca9d8d42258b1a3e4e920b2fbad33d5e9f07557d9595e841025193b521ba440110dd83958e8ee30219d952b418e98a6c624894aa248aedc0678f2d263e7bfaf54ca379fef6c5d2f7ac422ea4b4369408b82d6225a7a2cf9a9f46fd4ef
+TAG: aa0a5fa7d3cf717a4704a59973b1cd15
+
+KEY: ba1d0b3329ecc009f1da0fab4c854b00ad944870fdca561838e38bad364da507
+NONCE: 8a81c92b37221f2f
+IN: 6289944ffa3ccea4bf25cd601b271f64e6deb0eba77d65efb4d69ca93e01996e4727168b6f74f3ccf17bd44715f23ceb8fc030c0e035e77f53263db025021fd2d04b87a1b54b12229c5e860481452a80a125cb0693a2ba1b47e28ee7cbaf9e683c178232c7f6d34f97
+AD: e57883961b8d041d9b9eeaddcfd61fa9f59213f66571fadffffdd1498b9b014f1ef2e7e56c3044d7f9fa7a1403a1169e86430a2a782137093f5456e142aad03a5f7a66d38009dd01b7fc02c9cf61642dedaf7cc8d46066c281ee17780674c3a36eae66c58d2d765075
+CT: 9c44d9135db0dbf81c862c1f69bec55a279794cdd29a58e61909aa29ec4c120c9c5a508d856b9e56138095714a4bb58402a1ad06774cf4ecdf2273839c0007cb88b5444b25c76f6d2424281101d043fc6369ebb3b2ff63cdb0f11a6ea1b8a7dafc80cdaef2813fa661
+TAG: 65c746f659bcbdcd054e768c57c848c9
+
+KEY: 0cf8c73a6cffc1b8b2f5d320da1d859d314374e4a9468db7fd42c8d270b7613a
+NONCE: 3c4c6f0281841aff
+IN: 4434728d234603c916e2faa06b25d83bad3348990ecde2344368d1a7af1309bd04251bb2e0b72044948f8dea33cce2618283b6af742073a9586b26c1089335fe735141e099785a1235810a3a67ff309e2f0ce68220ba0077ad1a5dc1a4aef898a3b9ff8f5ad7fe60149bd0bd6d83
+AD: a38d09a4f1c9241623c639b7688d8d35345ea5824080c9d74e4352919db63c74d318f19e1cbb9b14eebd7c74b0ad0119247651911f3551583e749ea50ff648858dcaaa789b7419d9e93a5bf6c8167188dbac2f36804380db325201982b8b06597efeb7684546b272642941591e92
+CT: bdfbfea261b1f4c134445321db9e6e40476e2dd2f4e4dbe86e31d6a116d25830762e065b07b11a3799aab93a94b4f98c31c0faeb77ec52c02048e9579257e67f5a6bae9bc65210c25b37fc16ee93bda88fd5f30a533e470b6188c6ce5739fa3e90f77120b490fc1027964f277f40
+TAG: 4993ee9582f58eabdb26b98c4d56a244
+
+KEY: 69f4e5788d486a75adf9207df1bd262dd2fe3dd3a0236420390d16e2a3040466
+NONCE: 6255bf5c71bb27d1
+IN: c15048ca2941ef9600e767a5045aa98ac615225b805a9fbda3ac6301cd5a66aef611400fa3bc04838ead9924d382bef8251a47f1e487d2f3ca4bccd3476a6ca7f13e94fd639a259ef23cc2f8b8d248a471d30ac9219631c3e6985100dc45e0b59b8fc62046309165ddb6f092da3a4f067c8a44
+AD: 0c83039504c8464b49d63b7f944802f0d39c85e9f3745e250f10119fa2c960490f75ae4dced8503b156d072a69f20400e9494ab2fa58446c255d82ff0be4b7e43046580bc1cf34060c6f076c72ea455c3687381a3b908e152b10c95c7b94155b0b4b303b7764a8a27d1db0a885f1040d5dbcc3
+CT: f0bb2b73d94f2a7cef70fe77e054f206998eacf2b86c05c4fa3f40f2b8cebf034fe17bcbee4dea821f51c18c0aa85b160f8508bd1dc455cc7f49668b1fb25557cdae147bf2399e07fcacaca18eccded741e026ef25365a6b0f44a6b3dd975ee6bb580f5fccd040b73c18b0fbf8f63199ba10fe
+TAG: 4236a8750f0cafee3c4a06a577a85cb3
+
+KEY: ad7b9409147a896648a2a2fe2128f79022a70d96dc482730cd85c70db492b638
+NONCE: a28a6dedf3f2b01a
+IN: 791d293ff0a3b8510b4d494b30f50b38a01638bf130e58c7601904f12cb8900871e8cf3d50abd4d34fda122c76dfee5b7f82cd6e8590647535c915ae08714e427da52f80aef09f40040036034ca52718ea68313c534e7a045cd51745ec52f2e1b59463db07de7ca401c6f6453841d247f370341b2dbc1212
+AD: 9a6defddb9b8d5c24a26dd8096f5b8c3af7a89e1f7d886f560fabbe64f14db838d6eb9d6879f4f0b769fe1f9eebf67fcd47b6f9ceb4840b2dba7587e98dc5cae186ef2a0f8601060e8058d9dda812d91387c583da701d2ba3347f285c5d44385a2b0bf07150cbc95e7fcfa8ae07132849a023c98817c03d2
+CT: c2f109d6d94f77a7289c8a2ab33bc6a98d976554721b0c726cbf4121069473e62ba36e7090e02414f3edc25c5d83ac80b49ad528cda1e3ad815b5a8c8ae9ad0753de725319df236983abd3f69ab4465d9b806c075b1896d40bdba72d73ba84c4a530896eb94ffccf5fb67eb59119e66a1861872218f928cf
+TAG: e48dc0153d5b0f7edb76fc97a0224987
+
+KEY: 48470da98228c9b53f58747673504f74ca1737d7d4bb6dbf7c0cba6ca42f80b9
+NONCE: 56fb4923a97e9320
+IN: bc6626d651e2b237f22ee51608ddcffeba5f31c26df72f443f701f2b085d6f34f806e29673584cb21522179edb62a82427d946acabce065b88b2878e9eb87ed1004e55ef58f51ec46375ac542c5782725ff013136cb506fcf99496e13fcd224b8a74a971cc8ddb8b393ccc6ac910bd1906ea9f2ed8a5d066dc639c20cd
+AD: df8ab634d3dca14e2e091b15ecc78f91e229a1a13cba5edd6526d182525ec575aa45bc70fb6193ffcd59bad3c347159099c4f139c323c30a230753d070018786b2e59b758dd4a97d1a88e8f672092bef780b451fd66ba7431cbb5660ea7816cdf26e19a6ebb9aadc3088e6923f29f53f877a6758068f79a6f2a182b4bf
+CT: a62e313ecf258cc9087cbb94fcc12643eb722d255c3f98c39f130e10058a375f0809662442c7b18044feb1602d89be40facae8e89ca967015f0b7f8c2e4e4a3855dbb46a066e49abf9cef67e6036400c8ff46b241fc99ba1974ba3ba6ea20dc52ec6753f6fc7697adbccd02b0bbea1df8352629b03b43cc3d632576787
+TAG: 675287f8143b9b976e50a80f8531bd39
+
+KEY: b62fb85c1decd0faf242ce662140ad1b82975e99a3fa01666cac2385ab91da54
+NONCE: 2f4a5ca096a4faf8
+IN: 03b14f13c0065e4a4421de62ab1d842bffb80f3da30bf47d115c09857f5bdd5756fd7c9ac3d9af1c9fb94f2640f7f4386cfba74db468e5288dbe4dd78bfe4f69e41480ca6138e8beacc6eaa3374157c713cfa900c07dd836eaecc8827fa3e70e052ae09e8473e2ae1a10b1bb669ef60a8dd957f6553daa8114918e17371f2ac327bd
+AD: cfe3b7ab7550b0e8e2e8235fa0dcef95647ce6814abd3dc3f5a3bd7d6d282504660c34ad8341e4d11402c7d46c83a494d7ddb105e1002979023e0e3dc2978c9ae53e10eb8567e7a02b60e51e945c7040d832ca900d132b4205a35034fed939a1b7965183c25654931a9b744401c4649c945710b0d9733b87451348b32ba81de30ea7
+CT: 8965db3d3ae4fb483208f147276e7d81b71a86e7202ffc9b1eaade009bc016838dc09ca4bcf30887b2f4243fbd652cd90ebed1ceef8151ff17ea70518d03b0f2a24960aa7de9b30fa65c2e2d57360061aae6d9376e984e9fcd5e5dd0911a4bc8deca832ffb76f252bd7da523076593ba6b174f7d9fb0377e066ecbb6638036241e86
+TAG: 3d0fc53e9058c2be32aa0850e0fab5a6
+
+KEY: de9c657258774d4ebc09d109a0fc79d66493ae578797cac4eb8830a6a4b547e0
+NONCE: b5e35fe3398efa34
+IN: 4d68fb683aa4f4c7a16ba1114fc0b1b8d8898610fa2763e435ded8771b3651078bef73d4dfd14e76a34cd5eb9ef4db4ead4da9e83f4ce50fe059977b2d17d687c29335a04d87389d211f8215449749969f7652dc1935a0f9a94538dc81dc9a39af63446a6517609076987920547d0098a9c6766cf5e704883ea32feaea1889b1554b5eb0ce5ecc
+AD: 436ea5a5fee8293b93e4e8488116c94d3269c19f1d5050def23d280515457b931bbed64a542b317cc5023d648330a4b7adca14dd6f3783207b94f86ccaa0a0ac39b7db00ac87a99e3cd8a764ed9c75da8454479636ab2b29e770b166a5b75cacc425c919bf1ce9ac34afe6b4425c3d9fd2e48bc81e7d15516d60e592bfcc2ebefb660f0995f2b5
+CT: 97a97b8f0f5420845ae8d57567f9bba693d30e6db916fad0b971f553ad7d993f806f27ab8b458d8046062ced4778c004b4f958a4436141637c6039963308dea2f54008b7feab79650295ed41bf9e65e1a2d75ab1c7b2a70ebb9e9f38d07a9a672d3e95ea78afe9ac02f2566b48b0251aef6eeeca8bd15bd8d43b559426aa9d15d960ee35cb3edf
+TAG: e55dbb21851e8a5b365f86d02518331c
+
+KEY: 6885bd333c336c7672db8ebdf24c1a1b605c5a4ae279f0f698162f47e6c73401
+NONCE: f0c4a213a6168aab
+IN: fa905a2bfa5b5bad767239fb070a7bc0b303d1503ecd2b429418cc8feba843e5444ed89022fdb379c3b155a0f9ceab2979000a0f60292a631771f2fde4ef065aa746426609082969530a9c70ad145308c30ba389ea122fd766081511a031ce3a0bd9f9f583c7000b333b79ac004fbde6ec3eb2d905977ff95dcff77858e3c424fe8932a6a12139e6ec8d5e98
+AD: 8ded368f919efb522bb6a9ad009e02ffbc6a16536e34d95cdb34f1153d7cb7b0f3c2b13dd05cedae27cfe68ec3aca8047e0930a29c9d0770c1b83c234dcb0385deae7ae85da73a5f8de3dfb28612a001f4e552c4f67ae0e2ec53853289b7017a58591fd6f70b0e954876bb2f7ec33001e298856a64bb16181017ba924648c09fc63c62eff262c80d614679bd
+CT: 0cb3d6c31e0f4029eca5524f951244df042fc637c4162511fea512a52d3f7581af097eb642e79e48666cb1086edbd38c4777c535a20945fabc23e7c9277e2b960aac46865f1026eb6da82759108b9baece5da930ccfc1052b1656b0eadaa120ed0c45ad04b24ae8cdb22ceab76c5f180b46a392ab45b1b99c612546e6b947f4d5c06ad5abee92ff96345ad43
+TAG: d3b541ac446c84626daf800c0172eec6
+
+KEY: fbc978abb1240a6937ccc16735b8d6ed5411cdbc1897214165a174e16f4e699b
+NONCE: 7968379a8ce88117
+IN: 1a8196cd4a1389ec916ef8b7da5078a2afa8e9f1081223fa72f6524ac0a1a8019e44a09563a953615587429295052cc904b89f778ef446ed341430d7d8f747cf2db4308478524639f44457253ae5a4451c7efca8ae0b6c5c051aaa781e9c505489b381a6dcba87b157edc7f820a8fbaf2a52e484dc121f33d9d8b9ac59d4901d6ed8996ed4f62d9d4d82274c449cd74efa
+AD: 3913cd01299b8a4e507f067d887d7e9a6ded16dd9f9bb3115c5779aa14239fd33ee9f25756d45262dc3011069356425b5c81a4729594e17c9747119f81463e85625d5603d05e00f568b0c800bb181eb717be8d7a93166a504ce1bc817e15530c5bd2b3df1d4222245ea78a38bc10f66c5cf68d661503131f11af885c8a910b6dce70bc3a7448dfae00595beb707fe054d3
+CT: d152bcb4c24c3711b0fad28548dc4db605bbc89237cdbea7dbf956b8855d1161a0781f27bd56d798141e2ace339955efb98fe05d9b44cd011e645106bf47726183958cb6df34ce5766695f60bc70b6fe0fabb9afa009a8ef043dbf75f861881368fa07726625448fe608d578cdc48277f2dc53eaaf1bdc075269a42f9302a57cad387a82c6969608acacda20e1cac4596c
+TAG: 945dca73cf2f007ae243991c4fbe0479
+
+KEY: 77d1a857fbadfe01aba7974eea2dfb3dc7bf41de73686aece403993e5016c714
+NONCE: fdd913a321c40eb0
+IN: db8915bfe651e2ecb3ce0b27d99a6bfa7a7c507cfcb2987293018636c365a459c6a138b4428be538413db15bda69e697cbb92b154b7f4d2cbb07965225aa6865d7dcd1ba2c17c484b00b1986fed63e889f25a4966dc3ed4273f1577768f665362d7d3e824484f0dded7f82b8be8797ad951719719365e45abbf76324bc7d657799d4d4f4bb1dba67d96ab1c88519a5bee704f7214814
+AD: 3cb2c06c20cb0832bbacebfc205d77393ca1816346ea2681de4d3ab1fadb774ad273e4713290454496f5281ebc65e04cfe84ed37cd0aedc4bbe3decbd8d79d04a4e434876650e0d64309e336bfb10e924066a64acb92260b2dbd96735d03af03909aa6a80a6e89fda81037257aec21fe9be7e91a64e88e0a58fa38ecba4c4c4cffb61958f3c486cbb0b1d0b0014a2d1d3df248eec1ca
+CT: acb825e6023b44b03b2efc265603e887954e8612b2ee134bdcb61501cfb9492952bf67be597c3a005b09af74d9e421a576d2c65e98104780feab838d8cb1bd135452ea39dc8907a4c1a6a9161805e4fa3e16989e6a418a7eea2582bf895da967028eab7c95d846a6de4b9980785814cf00484baa2f6de609912fff689bce6e854261ffe866bd8e63274605c7c5ad677bd7897ade543e
+TAG: 938478a41a3223a2199f9276d116210f
+
+KEY: b7e9b90dc02b5cd6df5df7283ef293ed4dc07513d9e67331b606f4d42dec7d29
+NONCE: a6c191f6d1818f8e
+IN: 2ada0e3c7ca6db1f780ce8c79472af4e8e951ddc828e0d6e8a67df520638ff5f14a2f95a5e5931749ae2c4e9946ae4d5eb5de42fb5b77d2236e2e2bd817df51be40b1b8a6c21015a7c79fe06dba4a08b34013dfa02747b5f03930268404c455dc54a74d9c6e35485e10026da573cb41cd50b64cfafe4cfcdf3c9684ef877e45d84e22bd5e15fa6c8fd5be921366ff0dc6fe2df45f7252972c9b303
+AD: 0f4269ed5ef0bfff7be39946a4e86e8bf79f84b70cd0b14fecb7be3c071316ce86de3d99d6871e0ba5667d9d7bba7dcaba10cb2a36668b6c3e2fb6c102938b75008bb9c213ebf9b85b5e91a802df0d31d7f11d764b2289f6225212694ab6b7c0e3ff36e84245d9f4f43fc5f98e654dea7ba9bd918658879c5bb4a1642af0d83113e3cf935d3c0d5208318f66f654eb17d8c28a602543e77ad3e815
+CT: 22586fe7338e99cdaad9f85bd724ba4cfe6249b8a71399f9a3707b5c4323b8d96679568dfc8d230aefb453df596e13eb3e8a439249bd64bc93a58f95089a62b94f6562b821c83d91f56c55147381e9de4beb4ae81bd6fe7caef7e7e9a2078f2fba8f3e70d4910da9accc92b8e81a61b0fefbece4bd89443e66e8ddda8e47a66a62f17fd0e7d0a4852ce1a4d43d72a0b5e8914bbec698f060f2b092
+TAG: c082470297da8c5f682a169d28bc0239
+
+KEY: 6b2cb2678d1102f2fbbd028794a79f14585c223d405e1ae904c0361e9b241e99
+NONCE: 7b3ae31f8f938251
+IN: b3cb745930e05f3ab8c926c0a343a6eb14809fd21b8390a6fcc58adb5579e5432021765b2d249a0ecf6ba678634c4f53f71495865f031ee97aa159f9ead3a3fcb823ee5238bdf12706a9c6137d236e2e7110ce650c321e41daf0afd62bab2a8fe55d7018de49a14efe6d83a15b2f256d595e998d25309f23633360f5745c50c4e5af8ccc9a8a2cb47064105a023e919c7795d2dc331d3f2afb8c42e5c0bcc26d
+AD: 1c32fd3df22b3e440e2a3c7a7624990194cb16a5f74af36f87fd6ca7d410ce9064316a2d091945deef7d9b35ceec8396069307caced2b80afd7d53ec479c35cedf2dfd4c95c3dd8400f71ad34028c6e4f8681d93d0774064ba38f3fb9b0c1dfa1f5f0c7d20676a5911d999fb6a1d41367a8e99d852bf3d3b7b3f4c233249ed1ca135389a674ff48232ded3f6800a97b6d409c40e6cd70d09bf9d2ad25d9b9485
+CT: ef70c7de98ab1d4ad817024a970be463443640eb0cd7ff234bdd00e653074a77a1d5749e698bd526dc709f82df06f4c0e64046b3dc5f3c7044aef53aebb807d32239d0652dd990362c44ec25bf5aeae641e27bf716e0c4a1c9fbd37bbf602bb0d0c35b0638be20dd5d5891d446137e842f92c0ee075c68225e4dbacb63cc6fb32442b4bcda5e62cb500a4df2741a4059034d2ccb71b0b8b0112bf1c4ca6eec74
+TAG: 393ae233848034248c191ac0e36b6123
+
+KEY: 4dbc80a402c9fceaa755e1105dc49ef6489016776883e06fcf3aed93bf7f6af7
+NONCE: 2358ae0ce3fb8e9f
+IN: 197c06403eb896d2fa6465e4d64426d24cc7476aa1ae4127cd2bd8a48ce2c99c16b1cbf3064856e84073b6cf12e7406698ef3dd1240c026cbd1ab04ee603e1e6e735c9b7551fd0d355202b4f64b482dd4a7c7d82c4fe2eb494d0d5e17788982d704c1356c41a94655530deda23118cba281d0f717e149fbeb2c59b22d0c0574c1a2e640afad1a6ceb92e1bf1dde71752a1c991e9a5517fe98688a16b073dbf6884cfde61ac
+AD: cf6ce7b899fb700a90d2a5466d54d31358ecf0562e02b330a27ba0138006b342b7ed6349d73c4c5c6d29bde75a25089b11dac5b27adea7e7640ca1a7ceb050e3aae84a47e11640a6e485bd54ae9fdb547edc7313d24a0328429fcffd8b18f39880edd616447344ebeec9eadb2dcb1fa7e67179e7f913c194ebd8f5a58aea73b0c5d1133561245b6d9c5cfd8bb0c25b38ffb37db5e2de5cdded6b57355e9d215cb095b8731f
+CT: aa87f9a83048b6919c8f2b050315db4e2adae4a9c2ca0109b81961b520e63299dcb028cec0b9d3249a945ee67dd029b40f361245c740f004f8cf0d2214fcfa65e6124a3e74b78aa94345c46fdc158d34823ed249ee550431eaae9218367321cdd6e6a477650469bb3cc137a8f48d9cf27934b16703608b383d2145659922fb83bb2e7ee2ef938a90f2ff846a4a949129b1fb74dde55c5ae013c2f285de84f7dac7d1662f23
+TAG: 06b4318ac7f65d556f781428a0514ffe
+
+KEY: 9e4a62016dae4b3223fed1d01d0787e31d30694f79e8142224fe4c4735248a83
+NONCE: 263a2fc06a2872e7
+IN: 5a46946601f93a0cee5993c69575e599cc24f51aafa2d7c28d816a5b9b4decda2e59c111075fb60a903d701ad2680bb14aeda14af2ae9c07a759d8388b30446f28b85f0a05cd150050bd2e715ff550ebbd24da3ebb1eac15aba23d448659de34be962ab3ab31cb1758db76c468b5bb8ce44b06c4e4db9bd2f0615b1e727f053f6b4ffb6358d248f022bcad6ca973044bed23d3920906a89a9a9c5d8024ec67d7f061f64529a955ce16b3
+AD: 4cd65f68f9f88c0516231f2a425c8f8a287de47d409d5ecde3ad151e906b3839fb01bb91a456f20ea9d394d4b06604ab1f9009ef29019af7968d965d1643161ab33a5354cda2fdc9f1d21ec9cb71c325c65964a14f9b26eb16560beb9792075a1597394000fd5f331bd8b7d20d88e5f89cf8d0b33e4e78e4904bb59c9c8d5d31ac86b893e4a0667af1be85fdb77f7ec3e2594a68048d20c2fb9422f5879078772ee26a1c560cbcbb2113
+CT: e944bb2ab06d138ad633c16ce82706ecf0ef5d119be1f3460c9ce101d9c4e04ef1677707fca40d1f8ca181e07273707b06624d6d7063c3b7b0bb0151b757b3e5237fb8004c161233d8bc7e5f28ea1c18da1874b3d54c5ad6ff0835eed35c8853704585cf83996e5e7cec68180af414e04f08134d3b0384ebdf0393c9310b55d8698fe10cb362defc0995e9a13b48b42cff61ffd9fe4c3c8c6dab355713b88f6e98a02e7231a0c6644ec4
+TAG: 27de0d4ca7648f6396d5419a7b1243b7
+
+KEY: 18ca3ea3e8baeed1b341189297d33cef7f4e0a2fab40ec3b6bb67385d0969cfe
+NONCE: b6aef34c75818e7c
+IN: ef6d1bb4094782f602fcf41561cba4970679661c63befe35ff2ca7ad1a280bf6b1e7f153fa848edfeffe25153f540b71253e8baba9aeb719a02752cda60ea5938aab339eead5aabf81b19b0fc5c1ed556be6ad8970ea43c303d3046205b12c419dea71c4245cfedd0a31b0f4150b5a9fe80052790188529ab32f5e61d8ccde5973ed30bdf290cbfbd5f073c0c6a020eac0332fced17a9a08cef6f9217bd6bef68c1505d6eed40953e15508d87f08fc
+AD: f40f03beaa023db6311bad9b4d5d0d66a58d978e0bcbbf78acebde1f4eb9a284095628955a0b15afc454152f962ec3ea2b9a3b089b99658e68ede4dee5acd56672025eb7323bcbc6ba5d91c94310f18c918e3914bbbf869e1b8721476f9def31b9d32c471a54132481aa89f6c735ab193369496d8dbeb49b130d85fbff3f9cb7dccea4c1da7a2846eef5e6929d9009a9149e39c6c8ec150c9ab49a09c18c4749a0a9fcba77057cdea6efd4d142256c
+CT: c531633c0c98230dcf059c1081d1d69c96bab71c3143ae60f9fc2b9cd18762314496ab6e90bf6796252cb9f667a1f08da47fc2b0eecda813228cae00d4c0d71f5e01b6ce762fa636efffe55d0e89fdc89ba42521cc019ab9d408fcd79c14914e8bbf0ea44d8a1d35743ad628327e432fdcfeb0b6679ddca8c92b998473732abd55dba54eefff83c78488eee5f92b145a74b6866531476fc46279d4fde24d049c1ce2b42358ff3ab2ba3a8866e547af
+TAG: a0a5242759a6d9b1aa5baf9a4ef895a2
+
+KEY: 95fdd2d3d4296069055b6b79e5d1387628254a7be647baafdf99dd8af354d817
+NONCE: cd7ed9e70f608613
+IN: 0248284acffa4b2c46636bdf8cc70028dd151a6d8e7a5a5bc2d39acc1020e736885031b252bfe9f96490921f41d1e174bf1ac03707bc2ae5088a1208a7c664583835e8bb93c787b96dea9fc4b884930c57799e7b7a6649c61340376d042b9f5faee8956c70a63cf1cff4fc2c7cb8535c10214e73cec6b79669d824f23ff8c8a2ca1c05974dd6189cfee484d0906df487b6bd85671ce2b23825052e44b84803e2839a96391abc25945cb867b527cdd9b373fbfb83
+AD: 24a45a3a0076a5bcfd5afe1c54f7b77496117d29f4c0909f1e6940b81dde3abacb71ec71f0f4db8a7e540bd4c2c60faee21dd3ce72963855be1b0ce54fb20ad82dbc45be20cd6c171e2bebb79e65e7d01567ad0eeb869883e4e814c93688607a12b3b732c1703b09566c308d29ce676a5c762a85700639b70d82aaef408cf98821a372c6a0614a73ba9918a7951ea8b2bb77cd9896d26988086d8586d72edc92af2042ff5e5f1429a22f61065e03cfcd7edc2a93
+CT: 40c6318d9e383e107cdd3e1c8951562193c3ef64ee442432a63e2edefc78f32ab07772aeac172cb67ecf4d21f8b448423527bbeb9d8ddd0b46bdb27f74096ceb24e41963b4cdca176676a75bdbe3abc270b349ac0c6cbd9c3a5cd5bce20202fc5cc0c1bdd4fd25e121e0a24bd7bbeb9b19b1912467bf5338ee2ce88aa383c082b42cc399c9654ca325f35523e81438beb3f8926be79c378822d7c8f785614408a5f7cac49e4543188725643e6c1a70b46d0ec400
+TAG: 5801e84192c7267f66b0e04607a39a3e
+
+KEY: 6ae1102f84ed4dc114bb9d63f4dc78d7dbb1ab63f1659dd95f47940a7b7a811f
+NONCE: c965d578ba91d227
+IN: b82a8a9209618f1f5be9c2c32aba3dc45b4947007b14c851cd694456b303ad59a465662803006705673d6c3e29f1d3510dfc0405463c03414e0e07e359f1f1816c68b2434a19d3eee0464873e23c43f3ab60a3f606a0e5be81e3ab4aa27fb7707a57b949f00d6cd3a11ae4827d4889dd455a0b6d39e99012fd40db23fb50e79e11f8a6451669beb2fbd913effd49ad1b43926311f6e13a6e7a09cf4bebb1c0bf63ce59cd5a08e4b8d8dbf9d002e8a3d9e80c7995bb0b485280
+AD: dfd4ac3e80b2904623ff79ea8ee87862268939decf5306c07a175b6b9da0eb13ac209b4d164755929e03240a0fe26599f136fb2afdffd12bb20354aa1d20e5799839abb68ae46d50c8974e13e361d87ef550fe6d82e8b5b172cf5cd08482efdef793ede3530d24667faf3a1e96348867c2942641f4c036981b83f50236b8e8a10b83ebf6909aad0076302f1083f72de4cf4a1a3183fe6ec6bfe2e73e2af8e1e8c9d85079083fd179ccc2ee9ff002f213dbd7333053a46c5e43
+CT: a9aeb8f0a2b3ca141ac71a808dcc0c9798ac117c5d2bd09b3cfe622693a9f8ca62e841b58bddb2042f888e3099b53638b88dfc930b7a6ee4272d77e4b1d7e442bab6afbde96ab0b432f0092d9ca50eef42f63c60c09e7b8de019b32ebe4030c37b8183cc1e3b913b0ce4ee4d744398fa03f9af1c070bed8cdafd65b3a84140cb4deadc70184de757332ce3780af84353f540755227e886a8d7ad980f3dd6fd68263d82e93f883381dec888bc9f4f48349aa2b4c342cb9f48c6
+TAG: f26b3af8a45c416291ce66330733b2f8
+
+KEY: 405bb7b94715b875df068655f00513cb1ae23ffaac977ce273e57d3f83b43663
+NONCE: 5c6da1259451119a
+IN: f9f143c0c52c94b4ba7b0608b144156a49e7b5d27c97315743d171911e3645ab7957c80924e3c6b9c22ab7a1cac4b7e9c0de84e49fd5e4a2d1ab51d764fc5670318688ec942f7ab34c331dce8f90fea6972e07f0dadec29d8eb3b7b6521ddd678a6527a962f4d8af78c077e27f7a0b2ef7eabd19e92b7f8c1e8fb166d4763ce9c40c888cf49aa9cdfc3e997c8fe1cce3fe802441bbd698de269ff316f31c196e62d12c6bb5cd93fb3c79ca6369f8c1ac9102daf818975ea7f513bb38576a
+AD: 6fe6446505677bf08b385e2f6d83ef70e1547712208d9cebc010cba8c16ea4ece058d73c72273eed650afdc9f954f35aa1bdf90f1118b1173368acbc8d38d93ebf85bd30d6dc6d1b90913790c3efa55f34d31531f70c958759b2ba6f956c6fcdd289b58cb4c26e9515bf550f0fd71ab8527f062c9505cbb16e8e037d34de1756bef02a133dbf4a9c00ac03befc3fb7f137af04e12595ce9560f98b612480fcdba3b8be01db56ebec40f9deae532c3b0370b5c23a2a6b02a4de69efa8900c
+CT: 1a4b073881922c6366680cc9c2a127b26f264148651b29abb0c388cf6c9b1865dba5a991e1f8309efbdb91bce44b278772c58fd41273526c33fec84beb53d1689b9da8483f71be6db73a73417069bb4cd3f195236e8d0a00d124eed3a6b6f89415b19a27fbe35774f6a1a6ee4bd4350b252b975f0db2d2eea82f4836350850d6290901e726e8af13644e2d98bc1d569c20800521e6affe976bd407049a2e6d9dd23f88d52e651391ecd2fc45b864310824aaadfa203762a77c1d64562dae
+TAG: 0060026d3efc120f11c0739959ae0066
+
+KEY: 8c602bd94c630cd00c7a9c508067a5a9f133d12f06d9f6fe2a7b68dce4786d8a
+NONCE: 760de0f7b7cb67e2
+IN: c3ff559cf1d6ba6c0cc793ca09a0ba573a28359386a6ec93e1bacd8e630209e0b477a20aedec3c9cbf513ee6a1e3887112218d6155b9875f7e6c4bbba2c31972e905d19f529f4f0f9502996199f94f8728ba8d6424bb15f87fcacd88bb42c63fcc513759712bd0172b1e87c9da122f1993ffb7efd3a5c34b240dd3db89dddea36dbeb2836d9f8648f8e7cd428c0f948097af753b35f9876059e7702027bb00dc69071206e785f48fcbf81b39cc0343974ac70784a2e60c0df93b40379bea4ad8cac625
+AD: 9e14907c3a8e96c2636db1f3d78eb1f673d6ef043cbbb349467f1fe29bf60f23d5d5d1c3b133a8ad72065d822347541c13d1574baf737eb3cc3382fb479e6d5193b9c8e7d2444c66971ef099dc7f37f6cd97b9f7959d46e2cf25e8a5b3111b4d9e2ef906d905f0ee2d17587f7082d7c8e9a51509bde03d3d64338e1838d71700f1b4fcb100b5e0402969da462f26f974b4f9e766121f8fd54be99fc10beb9a606e13fbb1f960062815d19e67f80093360324013095719273c65542b0e31b1a2a3d928f
+CT: 2794e6e133f6892f23837fff60cf7c28ee9942f8982ef8089db117903d0143293fdf12ea1cc014bcd8806fb83c19570eed7af522db0de489bbc87133a13434518bcfb9cda4d9f6d832a69209657a447abf8afd816ae15f313c7ea95ec4bc694efc2386cdd8d915dc475e8fadf3421fbb0319a3c0b3b6dfa80ca3bb22c7aab07fe14a3fea5f0aee17ab1302338eeac010a04e505e20096a95f3347dc2b4510f62d6a4c1fae6b36939503a6ac22780a62d72f2fc3849d4ef21267fffdef23196d88fbb9b
+TAG: 457cce6e075ffdb180765ab2e105c707
+
+KEY: bd68ff5eb296c71cfe6bc903c14907f7726bcb1331f0c75f7801cd1b7948f3a1
+NONCE: 65a748004b352ba6
+IN: 52bf78c00f6e5dca2fc60e2e9a52e827df97808e9cf727773860cafc89f4b64178a19b30b46ed813fe00c8f09b25a6a1b6e350d5b005122934a59bfbd5e6e0c635c84a5226c3f2f7dcf951560f18ac220453d583015fdb2e446c69c6e6fdecf2e595e04fab1b0c506e3c6bd5e4414a35f15021e97f447aa334f54a8f1ef942dec6273511b5668b696fca97188ff15ed84b2f46145cce031c1a7f00bd88bb83d90797edc46161b3fda7a2299173496d73b812139556e8b4eb318078b9eb2ae5046e83b79dd3d45950
+AD: 5557b08a5010cbc9f46bb140c2505f68684eb24889324bff44b27234fd7a95a99cfb4ff90a8f9982085b725f78ac42eca6ce7f3314e457dc41f404008681a9d29ba765660de2e05bb679d65b81f5e797d8417b94eb9aabbd0576b5c57f86eae25f6050a7918e4c8021a85b47f7a83b4c8446898441c5cc4e0229776ef3e809cb085d71f3c75ec03378730cb066150f07e60f96aec983c0e7e72bf6bf87ae42228dfda195f97855fcdf4e6d1c4479d978abcfa276d16ed60ecbfbfc664041335ce65a40a2ca3424df
+CT: a5c8cf42287d4760fca755e2111817b981c47e85b0047de270ec301ca5f7b3679f4749210892b6ea6568f3a6a4344734a0efc0120ffedecf212d55cbcbb67815ac964875af45f735b70092a8f8435f52fc01b981ae971d486026fb69a9c3927acfe1f2eab0340ae95f8dbee41b2548e400805ece191db5fd1f0804053f1dbfaf7f8d6fded3874cb92d99a2729d3faaa60522060cf0b8101b463b3eb35b380fcddb6406c027d73fe701a5090c8dd531c203ce979e26b9ced3431e2b726a7244a20d9377bd62951bf5
+TAG: 4579fa1fdb4c674cc3cd232b8da52a97
+
+KEY: 934fd043c32d16a88fad01c3506469b077cb79d258b5664fa55ad8521afdcaa2
+NONCE: c7091f6afbbeb360
+IN: 2bdd1fc4f011ef97ea52ec643819941c7e0fb39023c2f3c7683804a0ddee14a5d1784a5246966d533b3538edc7d8742d27061c3cab88df0318ab242102de3a54d03632eeb871b72c7e8f8065b49f4a91e95e15f3f46b29fd76b8fcea0d23570c5530e3bbb8a6aafa9ae32c1b3eac653c5ed5fdb2da5a986075808f6385870c85b1913e26042a9d8e78f5bc2ea6de5a64f8aeafa22adcffc7f6932d543c29bb3a04614783f948680e433a71573568d2ce984d249fb4fc06a9f358c76aa3e64a357f4eae924c1356bd5baccf7e0f
+AD: f737dd85638eb324dd3891219c5eef7c2dd053cfd055d447a411eba304a4b27dce981d112c4540590933c153d603022c91ebd2b4a58069d27e6ca17a462ef822ca41bffa80b43a68b1b564644cb3c5a7f0fddf7a13a30ff24437fddd8ef93c6f6f205d054f81890d982bd4d4ece0b1563677e843fe48c1f54e9a57ed4da66061482712e710a401073be5080d5b8b96525bffa67de5af31d50385fbbf1a87c21bf0e0a1fdff69ec32c7b7103e0b8ee6c844245e0fc84b9f89fcce62966cea68e2871d3b82e8df424c76309fc88d
+CT: dd13fbf22c8d18354d774bcd18f7eb814e9b528e9e424abc4e3f2463195e8018576565d16ab48845d11c9277f2865ebb4dc412fd5b27078f8325eadf971e6944c66542e34d9dda971e2aba70dbd3e94a1e638d521477a027776b52acf90520ca229ebc760b73128879475d1cbe1f70fc598b549cd92d8a9ac6833e500c138c56474db84cb3d70b7aa4f293a4c2b4d818b0ff9fd85918dc590a12a8c0e375c4d98b7fc87596547eb960676aad5559834588f00f251a9d53f95c47af4df3c4299175d5211779c148cfc988a5e9d9
+TAG: 476616ea15190c1093fdc4a087643cae
+
+KEY: f9f6eb9ad736a8f66e7459fef5ec2890188dc26baf34a95f6f0384e79f5c6559
+NONCE: 7858dfc084fe4b0f
+IN: a644ca6e7cc076e87eb2929fd257693fce0f6fb64fd632f7f07c648ebd03696c8e262e6a810d7b7c4e5eef8c65b5323c99dbba50a70b4a9e5c2a9e7315973cd67f35d8052ce9a85a206416dd3031929f4f929b13d0a5fb10cb73c65f6c0ace019da146b51c5274a099f44e3669d26add6f2ff081e886f3cf952fe0dbbe6b0534c23e307574bd35fbd657f5fcbd5dc19fb382a1dc0a2dc8285a0350f71554e4c601497749e35567dd4a273cddc9a48ce53a5f1d297fd8baf8d1b9feb35d9151114345abada4d90db947bb9a743c175f5653d1
+AD: 2048d1c2ddfb5ec385b201832c7a993f229ba72ec16d6ebf723ef0c5032b9966209a9e8a63151b40412e96b82f86728ea6588c7e8e11ac71cc8eabab8c4b54de866658d9c5011def61fb3dbe4e630158a45ea41a2ed55ebd1efb1abeda7637de6fa5fd2f151c6d2f385bf6cd002ca8b4a2896e0d65944ee913e3c784669dd201b1985ef3577f7f123a5f9bcffa176c8f557c4f729133cac518642f27d9b22ca9b97faaafe5b669a10b79ace4a7d5727df146c77ce681357d69f9c2d65b4401bd73cd113387e3b3a05d897adad7a24c485e7b
+CT: 4146faffd7313f5d9f625370d20413cc62ab65f4acfa3c7ee1125b937dd7a39f638fc46c8ed004fb525698de5d8620ec153435571817c3de257b0d0e648ebb92940c86a98262d54e764f28cbdd4f7d9bea970291f2110414f62064d7229c6332236c507b3dac742e651d85a2a22fb243c0cc7cc2d016e5bea38f33f9a9ce048944a5fe8b078d71d23168e12dfe5a0f0b829771edc7073fb96032b7be471337a37aca0cf7c0cdd543eed686cd34934717fd79a3f18492eef72f9f450b880aa7e2e1b65e3b04c22e72301338b43aa32ceec2e6
+TAG: 10ffaf2be316676da02d7473a9df87b9
+
+KEY: 29b19636cdd32507fd98ec4ee26caab1a917646fb8f05b0dc01728a9f4a127f0
+NONCE: 06699d245916686d
+IN: 5fdf913aceab1d6dbaf7d9a29352fa8a3eb22718043a79cffa2fe8c35c820aec7c07644b8785dcf7a433b4189abb257fb12b06fae0662641011a069873c3e3c5ccc78e7358184a62c2005c44b8a92254958eb5ff460d73cd80284d6daba22c3faba046c5426fe8b7cacec64b235a8f8d3e2641e5bc378830594bcfb27c177aea745951ee5780a63705727ef42c4ad3abf556d88e3830f3db6b09e93edd09485cbf907f79de61f8dc5cb5fb7665ffa0ef53cb48702f6a81d8ad421cef20c1dbdf402b8fafed56a5361b2f93f914a2380fdd0557faf1f4de
+AD: 39116c49cc13adb065b92cb7635f73d5f6bf6b5ccbf72a3f65a5df6bd4a661105015358d9e69f42e98aed795e8161282bc113058b7ef3b9e23fcd8eeab34a392e03f4d6329c112cb968385ec52a7afc98bb8695785af6b27b700973cc952630b7247ce226b4fbb99b8a486370bf6345d4516c52c64e33f407c4f2d1ba90545c88732d98bbd97972ac5e94c694624a9b3782b0099824651cb7567914d25b3e13181a791dbcd40e76e836b3350d310a52151bf835d3c357c9871482c2928e8404c6e533406d4d6fa8f63366f2c4ed828141f1ff00f01a536
+CT: 01e237220b619054a1f3670928fe67d40484b5af40fbd04d032500aac5acaa3b4584dd99a58c390627636a50de5d744f76a56a33205f9e3b00e16162eb47ff3333e1e208ca200f1a5338a86e17bd92dd2d16af8bb022a7dc05b923d019e05247f1a0d0b4bfcfce58dd6d83830705707676d55739abee89fcd5cb94b8fde006a5da02df64b00a467f45970b5ca440f22319b9735a55d454b9fba0588fef0c59d3d83823eba6e0601a96e10233826c5adeea6b2a51d386a07a9e047ad405b23d4c3d89f30c31e3199f0c8f927bfac43ceea1f969de0a8c0f
+TAG: 092f9f3c5d4f2570c9946c87967f4579
+
+KEY: bae06b9b5456707551c7b0e207aae02a19b4848ad8ca4ce40705bf8c856a6e52
+NONCE: 9c27065c3ef2d522
+IN: 50cdd88137ff428a88e87b5845be4924f6387537bb5c0b654c80107ab5698db75b2e131848e7aec156d31aed0766d31c379fece4095d38264c6d5945974d25f729c3b0ba11ea853e9cebdb6f03bb670fce08adff74d0a8f02d633fb34e0fb7337a8e66e1c12084d914fb6173b8105684db822752c6751a372bb16690284d661b8b8bc6a6dfbddf45ebc2219596f9f2f878c118df69030de38b4d99dde43b9b9e20a3dab691645dd518342f49b06a0fe0a397adf261e99f07af5b0b3798b1022ba0939c42a54d3b93641cffa3c2e174bce9ab7ad7e7c7924308d1a77a
+AD: 5d5590db1bd316eb7a0e30e4c7a6dfdbef9d3287fdb8d824389599c3c2ee262b2192eb5b9708e66e22dbc7eca83fa1a995da3ce64c86fe5aa08b826d476dc439497e2d12e2702c63c8d27aa7f09fedee816dc8bffe1351d53271a34d4292b613b7efcedb7e3cf3e6ad389eef12471e9e20e38e7ae22a323abbadfe8f2e84271bffb1819feb4f77b82843cb8757cfae293631bc6d39669107e7015c85d7343ffa6fc1bbe6f5ab4de30cd752a281e03061ea89de2a3f5e90e20da22fd6e8525c100738667f42212b2cf45fcb23bbb54b21c117484b22c6e514685314df
+CT: 66b7f69ac49fab4e5975aeb6fa9287d8eac02ac312c4de78f77f59da16cbcf87274e66801c4b862c33ea79cdc76528862bb2956c06db8b8acfac4794ebf39e35ac03cc73a4351a4ff762f681a48d6f25cad36e2814c9b5c40b9ae92509e58429106847789454d376836936bebc7a80e6c66e7aa52936d6b361378a41f849ad4e48f9ee2d3e92217a908fa8eb35736ac8ada7d32ae05391f2d807be3512543c36138a5fe660dd4cd4cd184bb43b6ba6bc0bae634e2fa9669304cd510ed5103f630068ff76d3375738de60a381842b421477e25a490cdd6894b2704125
+TAG: c9998a677dfb0e91924aec9de0afd585
+
+KEY: 2cb374cb048c168f2e43597f028d9e73cade1b458284ffc260d4fc6b9011c414
+NONCE: 9fb909169bc9f4e9
+IN: 39eb929482784b463546f5d84f80510f2019923d465b99d194246d68c7ae343f91971d8f7059cebb86aa5dd099289aa648248b8c5ca04e66ac5e9bf06776e3883495397618a0227f035666806e636836b47d3d2d255a49db79866cf00d9ddabda259c4f968a1e01e651c7811cebbee2ee71803ea1d9d23487eb221f2d9555756800aba5e6abbefd6fb72b3151cc99ced599cd86df2a9b1ce94f89f347eeb124d9e7f0d9cc48d3dedd819e6d3dbac57ecee199547b266116a2035c9acc4c8ca3271ac74952372897c4a5f2cb84e2d81817fec9d6774f6d8a5b2021684132db4fca3
+AD: 0c7bd4f3a30ee944ccf9489181e6911684dcffad4593a9b65a67dfc80718c69b35897d01281016b7731e12c15cad8482e79458e08a755622e3f3f22a23ef6c8487a36ad1771ba06c641f06f85de0db3776cc6df06ad8fe3b4d60d58508de943083f17cbb9dc0d390ac94d8429e8c6fcfe063f424fbde0f62f6a7f91a626d195dc498a6e69bd93109c4e9ba13e7330aba456d710a4b0cc279d4045660406e26d61dff70d4a33c4f1052869f9248024e7a0f85f1effb32f6f7ccb1f860f3ef04e8f7b29096e6bcf9d4b3e0ce703e9bf228fdf515c2ff9cbabd16987be0f9babd3d8a
+CT: 91ddadb86b7ebef798ddaa59da51d71316fcf6c9678143178227d778750dc9827fc6cc21e605c505023e6db25849df7fb6fc1ca4d223aa215f8c85b724643c83bf8218815a9f9e2952384e0ca6a80a3760b39daf91a3c6154c4728c2371fd181fa3764753d0b0c23808a82cd8f0497246e3a0f17f8906a07c725d2891ce968a9d432c2b102d85c05510b28e715bb60d0403a77490e7f18be81218bc4f39287b9bb09f50227dd2f55e4fb70c4438da8ba3c8ffbced87d90155913faa9979fc57e6cbeddfaba3d3ab4163c0eebc7d94279c27d3ed56338893dba542eaefba30f8c3b
+TAG: 728e60f8124effbac234f70da925881c
+
+KEY: f0f16b6f12b3840bbd1c4a6a0811eef237f1521b45de9986daec9f28fca6485c
+NONCE: 7ac93e754e290323
+IN: 0530556424d823f90a7f1c524c4baa706aad2807e289e9479301e3e7a71f2a5e14e6232ea785f339c669af2e6d25f1d5a261096a548d23864945c3a589b67b09b0304a784d61b42b2419139485242e0d51fcbe9e8fed996d214de8717e6a71f8987ccad65eb92e66707034a5ae38e6486e26eb4374c565aad5df949dab209f7f7bcd8eb6fc52761a26cfe5d01fd349e59f4042e6dbe6b232f9301b971dee121d8aa1e62d40f043a42f3aa859d867eb809b1ced5ae1ec62cacf94a69fafd0631a8b5dfd66d855900fb295eec90ae5fcbf77beae267a79d24081bb322d8c4e0630fed252541b36
+AD: 13bfcc17b810099cda31ca53a1323db9b07633ceb2088a42263a4cbd6a4d47978776005c9a20203319c3a3ae434e9a26fb541047dc9df38dc36c095267272e203d0b24d119a70a7e96041b6d82b7c4d5570e1e4a1cf2f6e44ae63fe005a1f5b900778c482f7bd89e2e02305e35b8f61b7bb2c78a13aebfce0145d1c5aa0bf1d10d23616d5a3a446de550302f56f81dc56fe4f3700f14242688d9b92d8a427979b403c8de8c493a2cde510eaf6b285e6675b173aa0314a386b635c7577d5aff0d868a0cb3f73c8d2005f8c7c9dab5a060ef80102c9d4a4af988838afe87aff04c0689e8c3c7f9
+CT: 2c14c3931e98e84507c4c165c2ed47ad4a178f0e216cd7ac2453bbbf9f85dd06bd8ef54a9ff1fd3dd8e0cafb635d8f2de861a0db5b14d03f17aaea8c89b3010797c71c13a0e666899d7ff6e53c4f08be8ddb3e37688b5afa088079b6c7519b833e16560073e699530302028a3496e05edddec01a23a4c7983956250e8d9e616f7b940856955cde81c1efabf6b7b92f153d03f4cd17e7f7d2907670cfc84d45c1d7936775a3fce47968504278ffaecacea0871b227f250e2979516f6fa310fec0d8df1af7872e5a534e82870aa05f43ef0a455846b93ce938064fa33e92de262e4156dae56775
+TAG: d95d73bf9aeb71eba9042396f3725424
+
+KEY: 3792943c0396f1840496917ce8ad89608385007e796febeea3805f3f4cbeccf7
+NONCE: 23b2f9068b2c4c85
+IN: be6b67eb943ee7b5c785cd882f653e73a8f75b4a41a2a7c56ae5a10f729caf39948fe48ad0e51240e2e7aa43193c7ec6ce7f4909fc94c9f99e38e6a0ad7e98eb29c5c2e61c99e9cbe890f154185cec213a74725d23c1a4e4d0cb9b1a36b78c87e5eee20d2aa29aae80d4759eb0c51c5dc3a95bdbbf7e14eb434419a6c88a954ac03d0c98739f4211b8732acd71c297f578b8cb64ccac45f7235ddc7f2a3f5f997525c1ed39dc550126cdf9cedaf55425489085e91b170be6205a5a395f2dd4084a3e8dbc4fd8b13252f7effae067b571cb94a1e54aba45b1b9841308db0cc75b03cfce4ddafe89ce20f2d1
+AD: 7eb6d7b7bbaaa3c202a4f0f1de2263767169eb4a64853240d48c0f8d5d31b08d5baf42977614a57aad99426cde76d242cb37d2956d8c77dc4fd62a3abf30e8ac6cd58c8ef35e67497022960138c57787818892460f3bfc16e37ff388b1edc6ce2bc53c22717edc7a03d4c78b0dbbe9121c7fd8a3e3993b87a4fe389bff13bdae3b349de0b6db561602c53f746022aeb4483c723b67825042f4af20b7dd1e6031cf54215266295c524ac8e1370424c5c5e607fb3e23e97c8eebe64656775edf616422a8b974e1acf13ab45c9a367a7dd9b2d62f48bbc05819b65eccb813ca813f57b22ee4c280dbb5a9d8d5
+CT: 0b316ab2bcf5359900fa4082d5d253b49ad94b70e3fab544f98bd111cbcef6766cf953deec08cae1f489fe12f7acc0032db8a6b0c0eee0c206ea5fb973feaebf90f690e840094db5e13fdd7157ba127368c995b426529435a1bcdd1f14ce9125b8a0e4c96b6ec09e3c36a180adf81941c002d19c19d53c2009be803b987504606b7d43bdee5e0b32ff23c466b6cccfcd0d4e88fd1332e73712b5ab725c1a383e584f34f80daff29d285ae5e43cf1d0cc7a828e75c25daced3a581a93d7a50f313b33f38dddfaa23cd5b9914797db820ee2400d52bf5fa982277fe9b5881ac42981633b3957b0e935051828
+TAG: 01973ee2e81cef22751a6a8831d752ef
+
+KEY: fe4be6054773f634356ac328591fbc6f833b0d1beeb38dd5b6feb7481b4489d4
+NONCE: 0b3f16f898a5a7d5
+IN: 76ced1ade6d1ef4069afddb32e7432d4ff2fd06685121f7b16464e7a72d365744f547d2ccf53486310e38b42d8bacaf711e54c5458d2d68c4dbcc8de31ab6732f4430e88a64565f5b287640775aaa2af1cc461d3e415bb275c6246b1b58517aa72667eae291a2982eda175d1b22c5a58e6fec2b3743d55712f201ca24ba5c0ae8c25724871b2ec2fb914a8da5a52670ab9b43a83b8568ce74db5c634061cb80530c8070c38b8f48c33ba136cb9f2158ee7eda8b65f2192fc94d1291f182f101795b7190c74b319d2d3e02a97c824d9c9471a83797e4936310b207e3a1e0bcf75f7c3e3ee48a747641cdc4377f2d55082
+AD: 834cd775cbefe4b33a3ca53a00c06a3c4a666983e4115a029f15729460daa45d1505e95172d3695625a186b28b8be173a925af04665f209267b3c5123e8be13da447ee1ae856bb0925f35aaa76e04a7bca8460f76c2024de2149f38a8cfba81694b854885d72568105571b6b213a0bc188a44cc7fe13153cbf261401b238cf12a95e23cb56f240114f16e2f1e3a514615aab4449c0c49e4d900b0e17d1a8dabb53d43dca32fa052d576b73dd9b40856b515d6d7efc2a5c17e0ebcb17bd59dc86f22ce909301a2652f134e82ef0e4519487ed12d51536024f2ae8f75d937c42d003076e5dea8de0c684cda1f34253d8fc
+CT: f8defb6fe95dfec499b909996a1f75a198a90e4d6c6464d00a357a555311c42fe92dbbc4b79c935e4f0b1a95e44fdbc1380bebabca28db4dd0d2870daaafc38ef27908c3509e945714801cc51f1a07b2430c74fa64f2a7c2f7fd1551d258c9c3be020873fc1bf19f33ab6c660911dcf2317195d0efee82d20ec26d22611f9cf86c51a64e28b3a1f344500018e0855c88dae3c07acaeaa10b60388484dce93e16e6e1a6e69e899806648a92568c8780e9f4baacd98cbb353ac2f908e775d92303cfab843f15be0e0c322a958802fb1a60fcc7631f151f4c2b8cb965d2d296acef250275a2fecc0cea803ce7c058b12dd2
+TAG: ade515091930dd7861b27f78a87ef60c
+
+KEY: a288b11ce5382ec724ce4ab2d7efa8e777e91ebd04367935e15f9dac483e9596
+NONCE: 874144dbf648b325
+IN: 4c9195280a79a509919af4947e9e07231695fd7c5088539f23936ce88770ce07d9ad3ae4a463b3a57d0634d3a77ceaadf347a334682b04be8e58b8e86fb94a1f93255132b8cdb0df86f5bea354eea4e8315fea83e3fdf6e58aa9f26e93caa08e5e2551a94bd916a51fed29ec16f66800cda6a0aa24ec308bf5fb885afba272685de27c1edcdd3668048ef07b06e90d464a8aa28664903cac45e154e8e1e39c257e1ff506b9d95cef4f300bb73b899e7828602c3c1d290b8cf55ee5fd72ecce9e6efc9293aebf674a70e2a7673e75629c12950622dff71d3ec0992e57776c788c6927d30b4e24b749191c3ce8017f0ada6276e43720
+AD: 04abe8588c8c8c39a182092e5e7840442bd1c1149da102c4ee412bd8b82baa5087ef7291b5cd077c177c42770b0023e0e462b06e7553f191bcb0315a34918dcdbffe2b99c3e011b4220cc1775debcc0db55fa60df9b52234f3d3fa9606508badc26f30b47cdb4f1c0f4708d417b6853e66c2f1f67f6200daf760ceb64ffc43db27f057ad3ee973e31d7e5d5deb050315c1c687980c0c148ee1a492d47acfcd6132334176c11258c89b19ba02e6acc55d852f87b6a2169ed34a6147caa60906ac8c0813c0f05522af7b7f0faddb4bc297405e28ecf5a0f6aac6258422d29cfe250d61402840f3c27d0ce39b3e2d5f1e520541d2965e
+CT: 0afce770a12f15d67ac104ba0640aab95922390607473cbda71321156a5559906be933fb0980da56f27e89796eaa1054f5aacf1668d9f273cc69071b9e8e22af6a205a6a88f7ad918e22f616bddbb07c78913c7e056e769e6fcf91c7600c2740212e3a176e4110cac9e361a59a773457064d2dc652dd115d04f1c3756c0e1d39f6737a16b4508663e310934c49c58058b3c7b9af7bb2334c8a163608c42499658986927cda365e2aead3ac29de16e47e954383ea566f8fb245a4e5a934c767bb3bf7e0eb8a477fd0e1f61bcb238462a0d19c5cea9293ca58ade76829413216a7882cd2846323046694f78cd8b0347792ebb75abdc1
+TAG: 973e58b1b8adb176a6f1e5c963bfdc5c
+
+KEY: 65b63ed53750c88c508c44881ae59e6fff69c66288f3c14cfec503391262cafc
+NONCE: 7f5e560a1de434ba
+IN: 845ef27b6615fb699d37971db6b597930a7ef1e6f90054791eb04ddfe7252b5f88fd60eba5af469bc09661c0987a496fa540621afeec51bebda786826800943d977039dee76235248112ff8b743f25ed5f3cb0d3307f5e118d84fdbb9c3f5531bc177fb84549c994ea4496c65e5249da987dd755d46dc1788f582410266a10f291c1474f732183a2a39afe603771bb9c423fe3e8906f2be44a0c9a7c3f0ceb09d1d0f92d942383a875c0567c7869f045e56dd1a4d6e90c58d44fe0c5760bb4fd01de55439db52b56831e5a26a47de14249453a4f8e7da3cb3282c6622916197ebfaad85dd65c61e7d2d3ba626276366746f396394c1bf75f51ce
+AD: 51a3588398808e1d6a98505c6e5601ae2a2766f1f28f8f69d1ccbcad18038c157b41525be58ae4527a073748b7a04809e52a5df0c7988417607738e63d7ead47db795a346b04e740186e73ccad79f725b58ee22dc6e30d1f0a218eda1791e2229b253d4ab2b963a43e12318c8b0785c20fca3abcf220c08745d9f9602f0ece544a05736d76b12d249699c9e3e99f3f13cf4e5dc13a04125c949a5b30d034b23cb364c8781964bc6c30e5e5ca9673d517ef5f35965d8a8cf1be017e343df97b6bee37b30638b154286d1f36d2f9a0eaa23cc484eac5a05b15d9efc537d989dbc8b3106c0dc1a56e97e6aec2eff54a82cf7ae9df2af46b4c860f83
+CT: 027b14197b4012256b133b78ddc94e72fb4d724fefa4ae329f5a5fa3fa784fe6d7e1e805e3f7a75557de64de506d38237b467fa577efb59e7cfe2356bed6655c5aa4e238dcfeb75c16549a0917268768a96acb5e20546a1fb7e3a7cff887f49f2cd7a135f72a98a779150f3207bf733e88861fd79eadbf77fa3bfe97bfe8b6a991cb3bcc2cde8287f7e89384846561934b0f3e05e0646e0e1907770df67a7594161a4d0763faa6fa844080932159999d528ee0558710058ce16f97d13ac9fd9bf5044191188bbfb598d0fafbdf790b61ce0781ecc04218a30ded45efd498cc9ba03562ed2b4a993ee98876b3ab7a9bc07829f1c4ca6ead98c06b
+TAG: e4d18a701b8308697b5e79141ed783c1
+
+KEY: 4986fd62d6cb86b2eaf219174bec681bebcdef86c8be291f27d3e5dc69e2feba
+NONCE: d08d486620ed2e84
+IN: 3a22ad5de387db4fdd5d62a1b728c23a8dddc50b1e89f54f6198b90499f9da3122ebeb38ebf5fdfe30309734f79aff01e3de1e196b35bffa33bae451f31f74b8aec03763f9e0861a34fe5db0b40c76e57c7fc582bfa19c94ee25b5e168270f379bf9f8a0a18bed05de256f8f0dd7c23ba2ff1c7f721409462f04cc611ad9bd4c3c9acf30742acfb9518a6375cbb15d65a1bc6993ea434894f93d4f6e05996ebc1bd56579296309a2c6b8fde95072168b5fd31927c4c0abaa056bcd16221d5f220be47591f43255013a262dce439817f534830ba82155347e5fe3101f8011b89365a6568214ed0661914e8cb3431d6c8f2347dfc1209a3eca4aaf0a111f47fe
+AD: 7dd3f656a03c001b45ca0680bc3ac9d68c6e96b591d3c69eb8c65e489009d845cb331c98b82e627e06d5bf01e74c573df268c2386f12628c019951d42f55991ff20d72a7b2c45f41d0be7af428c92f324aaab8df70d900301cdf09a3d93eb711c919d34a86fff9cb078322ee2e0ad48dbdf3b7884f0f2dc5c36262c59bcfd75ac6200f59c6fcd0ce10ff5005fef5df8f0432377dfbfc1db8f559e27e1aeef3380ea3864867d36a25a18654779a751586cad3b8a46b90864ee697b08605673b8d2123433c020a21c4db243dde2420c12fd4d54a2704a0c8c376454a1b5e80fd6db89aabd56d9b421f29649e474824dfa56cb5c673c504d10be52b53751709fe
+CT: c40180afd53001663ff4834110f56e6b0f178cd3c0e7f7de5d0089ee41d8403ffb98e84922706544a344d7e2625b12cf66b9c966f9f57d7b94e3e4b34e6f0aaed1763ce012782e2f5e1682e6c343fc7961fedddd0919d0b910e9923c17e36406979b256b85aec24ee352f03b48c1302eab419c83dccc5372cc059e9de596224fa70098eb32fc9579e97917b923914fa2efc30ab29b457bf14e45583b3771486bdc0876f3ea6e1a646746c4f8c5cb2641a1557c8473e6ea67d4811a67485ae9a678ff3a2408ca845c3b51957e189eef47dfc1d46bde4b9d754d7df13f828ddadb06e4ebddb5f0dafbdb28de4c5e6078926f20cdf9e97ecd58e309e640f74f06
+TAG: fd5e29332832a14a31a9ce2ca8568498
+
+KEY: 7d28a60810e43d3dfa32e97c07957ec069fc80cc6a50061830aa29b3aa777dfc
+NONCE: 47738ac8f10f2c3a
+IN: b50278ae0f0fa2f918bb9a5ed3a0797c328e452974d33cbf26a1e213aa20c03d0d89490869754abf84dbbe231d7bccdced77d53fd4527356d8e02b681fc89a535ae87308bf7fbc26197a5ea85bdb3aa033b8da5cd197ea6d72f96f63b03f4ecc7adedf399a5043776cdb32c08f30b77f34df85f8adb8e02649a04b020b03e17d445ca63e4ed73ae432c481392e031eba2f9d2f7f981d1e50917822bd6ff71c239d33444ada3523a59dfbce5457eadec1ab926c9e6c5299c7521e3f204b96901a712504fcc782e8cea80ba12a7f7e71cec3d0871899b6ca059061da037715f7d13fed01c9cade1e687b4fbb1f4ac4b040db3b43800f112fb900e4f772d61b921cbce4da6f
+AD: 324292813b7df15bc070cc5d8a4bf74ead036430be63abc43304cf653959a24a91c7de5a671c50fa8a87e21bb82b069999aadfb6895d8bda4c3083d17b8ca55b9ab1511ed8c4b39d8c28c11a22ef90c08a983e3fe2d988df9e02b16a20b24f39ddb28429625f511db08298c4dc321f6c268fc836a6191df6232f51c463a397a8d8b33374abe94e62c0f5c322387e1fc4a1c1980a04a1a3c2c31b32f183a11c3268c6dca521149dc16af120a78be6627210e8ddbc44472bc24d66ce3681c7579b3d9a425212a704a4f5105cb80f0d18ee860953d10b59c114826779bbc368d7a0eece9f223e47cd8e5fd453607d101d9d9c2bd9a658d6520b87d7b4263f6d845a524a36e4
+CT: 2c217e969c04740a1acfa30117eb5b32dc573df3354f4cc3bf8f696ff905f1e640f3b2c250473b376622e0c9bda13b94640521be1ef0fc660b4c10dbe2bfc093030753e04f6aaecf813b43b61f960455974b8bb8a9b461d1e8fd3802315e863c00448f24dd38deb90e135493274eb14ccbde15c50dcad734ed815a806be6622492a84cd062e3ba567b909a205a1d0d2bedd40169697d261c7b6c2e0b1f069853fd470e8f364a142c386c439a6dbe192ded5a3d0fbf73799f588c59e58c60249d980ddcf0d9693631cd9b3f972509c3a77123d38d9e267ecad06e1208e3f1c0a69fbca7c3bb1a48fda19493d0f8f48398820057b94120f3ef97d87e9e8a1b301a2534c68f
+TAG: 1fdd2dcd935f55822bf7231a516ca841
+
+KEY: a76e9b916f5a67b78a5949651c8c3a9741a1bc3c41cdf85fd2c8f3e9a0616098
+NONCE: 0808da8292dc14e0
+IN: 9c149eeb09345c3c22462b03e49eb4dba6bc98b269b1086d752bcd8eea53b8977b238a04a994baf915591686baab90b79a3bf7d9adb2c6c2e31acd3e72f0813fb745aa5fb2e3da408f78001c9c09bd26a1a2646011b6120aaa2bbacc4a16c39fb5257b9b2ea2ad8bf70bcc9855cf11841116c2767310cf3cd49d1aa44cd505f079761e064d5bc7cea4a7173b086882a77d3fc179efc86fc4db8a373491d2ed81eabc63c950e832db17d09f474d4ec46bde47830caf26fabaa0372b81fccc449c0e19ccd630caf693a7b43bb1c408a54e03f50c44280a05ad89fb6e8f01d8ac278edf556e5d86ceb4b614fb2ef133819c6e1ff6abb86c54a135256204b5cd400b93624d3932e7c2b046
+AD: 6aeb7031e4a2e23eea93f05fdc562aa2bf43b8998bea7344377aaddc60fbdb7bcb1491d379ed0cb613ee757cfb66490db61bb431d2fad34b38ddd55bc5b22aa6c4773b9992f34b878c5663f6e8cdb5f80a17f4d312bf342492e48d1ce4c6d754076a634fece61500acf8168d47381af4faf980c6cac2bfd5da8c09b6edb0f543bf0fe02643e38d73fa37d8ae87fb66193f22e57faf4393c007d48c8631a685d520578f8f89db684fb371ea02f3a58b1e2168f0216321139472e0d03b6d90ba8aab65402e1c1ac4f9172a60e27e3d997b9b05e2f672120d6c87bcafa6d4c9b4cf8ba8a82932d92840368fc53dc5b48526103dcab5f1531038aabe89171327ac559b98a3cf4ea70bf051
+CT: 9c3faab9261a63cea9477b3269007283995b06ba77ef83d9e693f7e4ee9855550eef94855be39a7a435b6a3584b202973777c7b2482376ba47b49311947a64983b60236756ee4455d4cfada8c36af8eb06b06ba2f6b79ffb1185c89f2b2a831cfaa3855fc1841d8910908be5078352011168a67d36372d851a3217cabf593ea462dcd325cf9a4f67e85418fd5c924e9b92ab026cbee4e7ab1067066cb5949dfc699a68fe539e1abb13cec33904e5207e6963d24f5a0b770613b8b00014e791bfff88f9c25ca126127a2f8d1d1e9794efd28dce98b53e228073faae8d5047530d502184fc341321c3f55fcbf41187fc31262c325b97f519959b6a29b36c71f76f60196bb1457b77c8bb
+TAG: b45df119043d29008fcef36a169ef886
+
+KEY: 98cd2477a7a072c69f375b88d09ed9d7b9c3df3f87e36ce621726f76e3b41a1d
+NONCE: 77d185aaf715aa48
+IN: 42b31eefdacab0f03ef6060156000c8195adb0976cabbe1a42bfcc09f85659c60b98638401f2d2e2facfb9a97a62926bb0cecaf3af0180a01bfb6e576babf7fc43331937a92abd30cddfa3e450f895e9dd914dea3fafd759c136d685310ebce28ac0613ccdbf30115946c9634b67510b77d0e37f07714b2ddac9d7095b8d4bd887c132c4a9127eb01c8dedb4c39c87b98a741316656f9a8d5a5b0c0ac84789aa2347a5f99ca5ad55cd1bcf98f703eb4b00badb8a8555f38b3b368db8ba7ceea94e8b219f51edce75d84166b5602156ed5962a93a51db73c59d87e906179d7a74a2a2a69d8ad99f323225c87e475d3f771b4a203a2e2b03b458401044649fa6536dfab24d7037807dcbf6518e6578
+AD: f5bb1496052a4361dddf72a288e36953a3d815d6876c013f1d6ba839e127f721b052b1f7d8ca20c7dc0386a7d459ebd7eb9fc8cb08941e6ca9ddb980f3115f65bc1928a414d441ae71dcb879d5bfe0cde0562bc37f8fde0d5291ad405c92fcbb860c43b55ac0fe663b54b3d0616aca13a5c82b7b5d34125a05c2acb5530141030e6f2aa0c8322b2c8fa307e7518918e550e9f48921c6168f094d8758e16b9f815fd0458095c4143f0922adb1840d0e685636825a9c90ee90ee537f4b8dceecbc4287c82dc9a00d7e51671e37ea284ee3ca501b1b2596459d3f592f70186f41125739e342c9f6be9241973b1414dfe5fb8cba1af82e679278cfcf95420df0c5364af4d7e72ad57d5c871fcbc35462
+CT: 7a3bf3e3ad5ae3ab71fb1f7121c3d8fb511099484b50af7ca128ee0337ed4b828dc4cde0b88dc1e8089101fa82c9beb3eb48fdcf0f5b16da441f5a3fce9a590022af95a94aed6a3e71e505f60f303c78c356f274ea85a55354078530664ecda32c80e77dc20974b3b38f4825b8fbee8c3970769a2f42c5181608a8d7d76ef4d093961b665ee42b9708fcafe2c82d3a307173e2a25ad2528c3bf83352b9265e45b70722d7cf8c9b80826d21335234ee3db69d0d37871c83222365900c96c17a7e9f5742d0bfe383be24d0d44590d4b0f29f7abe0c65daaffb968b3f2657b1eb300534eacb52ec7a6b6f9f57a50a91b1799f491361cf613c934b7f520dc4eeeb40ffc45e10be0a95e76f366d4eac14
+TAG: f613b65226afb64c614fe60d9c71ed74
+
+KEY: 2f0f4631ab1c1bcf8f3ad0559c818d50e0af7d8cd63faa357f2069f30881d9cb
+NONCE: 7d0ced2fdb1c9173
+IN: 6516ba1d29357144eebfa486d21decf223da3aa76ec29bbfcbe7f1eeaf4a847710e5080177f7e5a7c8b4752c219b1cc70aef4db861ba67d0fa6222d9f4a1dc756a0ba44e62906f9374a960c16198866d867854d88f528a60e212eb91645787e75685b2e215c0a41990abc344a77236ec0186ba63a664592938cc5a8ac1d3eb99c95ce00e19fbe249263083d85b052d48bfdffc01585dc57bb2a2c6c4a819604c1ec0548c6f0f78dc05e4418b36277dc07233c7532f9c289d6aed0cc6bc7df4fd0a536c497b982e2dad2c30d2db1c6545a845c5dfa83a4ac49ef06fc9c919079d3e299e31b5c3be370814ae5022ae469d3ee55246a41bd0dc4e64351cc38c3c09af0a1aee3b388a6892deff0df3f93cd92d722b
+AD: 1ccfa1ececc8de1e200d0ecc19dcf67b7c96bea3a282c2bccba61035db5c14776387b8b8f58e5757deb0129d4e5e315f64df354a5985d2e47ebbbeafe0c914f7cf1d63dd0311ace19e69a8b6ff0ab25cc8df0408d22132205e89e5eb679268d82b2913e64e3f885bbf4a6d379b760b94590e3140dd7275ab4713cb56d0b716e2718f11316640cb394802862d39e77a46d0c065af3caf7dec14e887039d8aa8c3d3a8ac1ee06026f49d00b2f59d971b54735e95a51f199389a93a4fc24ebaba1f7a2eef7412f61febf79084fbf481afc6fb6b204084e5ef5df71f30506459dea074f11fc055cd2a8c0fc922c4811a849984352a56a15659b7d07a4cc90b88623638ea00c4c8bc13884df2237b359f2877aa41d6
+CT: e580093789ba17ffb46672dc326f09278aca08598d3e5458eaa53e6ed45d5c71a396e35b5ea3fe7b7c0496a734d24f1c75420694be2ff095d5172fd3407794e4b99fd7c374fbe8d1564a048614d3f355bfb5866de1a53e1a51f9f5e8312253cfd82f36efaa1898c850ca0d975ad1e8b0d9597a5a9e6516fe2a3c92efb7495557a8afc3da15b0d3e2ba58f612519836946cf2d15b898320d16a026c8c00a1be2e35f0ebe68f28d91c6c45d24c3f3c157cb132fa659b7794df883d90741fa2d2afcc4f27858e13ecd41b154a35d24947ae7361170060c107d8ecacb393ea67104b60457278a392fdf1794bab97d3b02b71a4eb015eaa38a4b4c944c2bc7cd5e329da4a1ab2937a6af81a6caa5fce752331fdefd4
+TAG: 0fd7419c54bc84265ed310a3411a3f2e
+
+KEY: a48b9b6df475e566aba7671fbd76772cb0eff0b12499967978ce3e25fac92feb
+NONCE: 2ccbf0d6c40cb302
+IN: 09da1cacd001dce4f7573a065a4406fe0da04ab367a2d87780a2762e168957a88d3fa78f0a4b6978d449026e5a801d32884b6e14fdaaaf864214f928ebc03dead081fee96683ebb032362d5088c4c2a3b1e242f055f2604919f4dd551db777a258cf9da6d95a2bde249247812b9efc7985cf08707620808524d6dd3079b0b63bf0f71ea5de834ccb8b7c6a97125fd6ca49148e866d3134bbf1d8a6b714e9a80fe549c8bfefe342f41be2ba2300e0028f78cefab65274632dfdbe70bf7d655ec4036df561f2d4fc4d56a482bbe2f9f2ae279b3aa216b39afee75e53602de319484db89a51e844f38c361634e474f8f1f01c340f3f3594860d671346449c6d08ee38de22d246309bc7e4a252a29c86aa6d94b5b4fa58904c70
+AD: 1c2503d5aa1aad193f0da12874074ea0432bb76a61cd43a3017061514da0759846a0f3ae3a49fdb0b6d29f713de665beacb6568f2694112ca380d13f3c1698316866a7a7f87f1d7503a92176ab84fc08977b46ba664508a858e7525753c45511b3d2f407d5e993c6ede77f13d12975707e5195704970a89f71fc30828049f92f944f3aa93d6a5297e678e08952919beb7eac5919df1919cab3c3da6aa696a1eeab6371f310f7e81143e7d240b0213ae554524b52000306160dd4877bf13ba0f13bbe867da7c7d707f31335eef4cd942938ac890a0829ec66bd30ae01a2188a6e5ea0f17cd7dc875e17f03c0ab5dd18e36db8a1fc1f72859ee046b62368f168b3bea2234e0432c07b7d8e1b9277f21e692c513b9e816e6860
+CT: 7d35cfe4be56bd6e0e09dedcd01735b915bc1891a4d1f6a541abc4bcd0ebe89dcb8e365e5813742e8ec65777b6159422fada747da99394252baf8a046fc1b60ad79755f545f4448627b7acaf403000894f5641e78d3f946dfca29ec617f0660dcd6e8d8827e67e1022a245c595d86e60fbd176bf721b171bbe5ecaf4ae671b9f3dd3920146e6ad431bd8fc431820e19454b6ca209723d80fdbee187fca9c937c979206ae97be55f6ba7366a5608770a11d537396485eb0a66586385f4d4cf3905d1fc90831c3e136d5d513fa22be285193142994a3ed477145bacdcbdd791e8b3b88b0d4f1d18b27382550a818c4fd8884bf36f677c6c3ff5677406e510911e696af75e5b3f859bef699bdd16e6215fdb98d874025eada50
+TAG: 2aabff35611b3e0013f6ae0df130799b
+
+KEY: 923d4b086b9e43b986f7b65e4cea6113a3d8aabefa89323c5e4d5b6f158bb7e0
+NONCE: a0f73297b87f5deb
+IN: 21435e8d5c8edf0684f58c2cba4070c10b4801adf46b6c4d322eb3990a38a9ad338ad704b9df6597f3e68d66cd5b56290c8466db2231e56d6bcb9c44e1bd081f42ca2a894dad369df2bd0d2c63d6c881732d6ea22bb22b5bc9a62eaffa1b094d0845f6b966d2cb095e7b3b8bcbc15e707449d35c8df4aea30c3b7243e977fffd59c80f1c5c9af4bb5a54b9c786fbbe8d21b2b906a87a786caed841a34a3e0cc0ac3209d83c58afba19edd63622dd261532d2cfb0b49d527d8eaa0887a087f5129d897f665264b229f860363d71a88b7d49c8dc6360182b357b0662391bb41337f46010ac32b9fada2d60a2efcb99365d3b27b7ac396900d1c821d0df8b86cc9cc1f2673259a33efea610bf8e1d00d7e9db2afea21da8f58c55f799999d
+AD: c853a8b39c0dc597d562f123cd221e4104b65423a062a4f4ba890ba344feb84290f61817e23330c365f58c3583ce08360d3c1171982ead5496d525ac878f23a57480a6ee39d4e65afd6268245bb982a2545fa1195427cdbbcd404cdad5198f55cce2a5a028fae435f71b15921d066e8d43766c32b2f2c3f57c0674e129607dcd3703eca529414adaee79d81fed432153cceb6f3fc53404810d8ec878f7d94be5d379d0e0e1aa9bc404b4b5d396038a9d76a5ce53c9f3759b8e50fb331858ca58cee81bfc3ee58baef5d19c402a3dc8b36370ec1ace5a4aa2527fb94b4f933a4ab8ccaaf6a5af5a779eae5667c2a24ab027e781c8d4f30c377aa5885a2fdaf6507d18cd824a847c35368b4ea984d2c3c3824a5b8ba3042e1852504a21a3
+CT: f2e21052eebbb86a4f5e803360855d8632aa727dca6f5e79dd74d7aff106e442001928d113005b030f8446f8eff2ee951db663978abe43090dd5ad2c51ba97a0ecf988c607d95e486d02524f690fa3c28d5c48c1f75c1f555e7b43fe7e46f2ca2b9fdb408ec4ba18b6cdde2af673183cb7b1a3c23ae77eddd4cac75e1ea14743fc571f8d31ce2e96787524cd48aadaa474181c096a032184574ddc25a6e0ac8441c212bc36298708e33c963ae931e6c6241d1affeef7b6ef759495df44b6ab647447693cf703569e69aa72f1def9a342b8978c1edea9703a421ca75b92cac4de14b88c693200022b8a2ed22b1c4678b99f4d695e080dd1196d7168e14f0d0f8ff880d742e97b9f6d00af1f7118e10b77c5ef3ea6c52f84a20fd6ea46dc
+TAG: fa8ee13400fb3f63b899df582f2fec45
+
+KEY: df73adab2768559ea983cce85453fe81d79be3b3c57f202b31b94d6635cf2e4b
+NONCE: e7a87e6bf6b5a354
+IN: 0032a37abf661faa18c587fd2aa88885c061deeba81105dd221969bed5d59c7204b09b1a8c4c8de3b9f748c7fc70626ebeaca060233a57b102221b1bf0f3d9fdaaad3d2b1439c24d08f9c67f49f3c47128f92ee530abf4c4f4573bc60ae4b38109f55bca3ca9e1ba9f9fd6e34ba0d174892977a53356e1f5c88c614fe3ff3b3dd0818e7a2285412e3b37444bbe8a80942efcfd03958809a6966cda9430b2f0c9e552f4bced6e19eb3e85fc5758bd7b588297ccbed37ed94c3adc8c08ea8b058462aac9d57a939ec711bc4ecfec944d2b653b7cfc7b02a65d7057c9fdadd51b9da8cc4a3c68dae9da8b9c5319c1a2baa3d6c891c5ac4a39461484b5a01abc64df447ada24c04a4363e605eaccf339a9aa515e724206206da6d22bbd2f52e64cd7c895
+AD: f833e5ab4f8bc89167f80f576b1d6b22cdd0e30721f5f735799746cf645b6eff531d4c7b03584f3dfcb73cbd35ac42736216dc7f0de098a4f42c61ceb4b227ee288e47d697a0a76afc762f084e8fdbf9351c28340c324771c109a469341ab10ca10483ed2af5e878d7d3dc2bced2f72da3d1a25852b103ee9878e8158eb4309c1ce528f3a178ace153b6d3ae0af0d577cb3cb1540489e80427f792217ad8a09b84f027fca7ceb651b4264e98e94b4cb8a37b133390897233e8ba9103628d05b9609e8552c4a4b11e3f2fa8d56af36957390e88cba44656be3edace798cf8cdf7771bac338a256bc3cba6df97728f222f423ca7c6d149c9372d66163a98f79a234b00d4b75fb2ec860dcc2d1998105e4b9c01d68f079f3e0aa21cc534047fc7b858f8
+CT: b842eadfdf431c135bd6581d3eccae54e2267d8890036aa33dfe2d2d9715c44625441210a3a0d666d708d30588fe851ec36e10d8fa3584ed77b095149494b7c54379d62c8935e1d2b9a8f47e4759ad0b3437fdf2cc2fb6c5ea25ad10e0bdc9dc5b0517fc237eb783cc461c46665e2b1d1a5b8008dbf409ea2a63fea0276de23a32c99d92a498807a0f95e208fc6262321a78aafaf0cc3f833fff37bd4efa66f6023a25cdc6702cee3912799563d908a5183c9956a06aa71085d855dc7c809ed6e2889592b361ab3ab39060f8e419152187a794a19c2a1128882201900ea2cd597860674bf78d9720643df8701676718fd201baed4935a88e50558daf86edd08a9ab227ac7afae55c974b68de8dacad4a4d79b13ed6dfe74017a4cb9148e033436fb6
+TAG: 184095b7a8190abec08bb72d19eeb103
+
+KEY: 55a4be2448b464c2ea52a2f2664ed6aba865c14ea1fea77f4689331fd105c8d4
+NONCE: db37c0a405b4626d
+IN: d266e66272e5d3462081b004cb42429c8b9741e9f678153754d726f6f9aa513464763c5e793b482fe512fece97585f1426120d4cefb3d0a8cc0a8db4bde93fc72c78f44d4fecca14650c660d3e285b327e7cdd813063e7e867b8a2d059a41bab70432b7f857199894da90dca3fe5272bae1ec694a1a07b60b05df275784d4975637e4673109f3ba846dfd1a048b202ed8e89973be608b91ee4743b1e759900f1443038951fe6189e806638985f3c16338c3c60695df58e621154d79bb973859c4558e9dca90470f77c73f004443ad5db0717abbe43266f90e57397b83ac34d1fef2e897e2483d5bcdcb627abd64b0d1aef525835f25e76d6e9158232cdde6dce970b59f58de8a98e653be32fb58edabbcefa5065d73afdf1c9c4fbf50c1022bd22bfcb98e4b422
+AD: fd6a3fdd879f8880843eac20ae01c1b9dc3487d270a806572088ef2ddc1f1e0de495e71d4813bf5c501ad31e5d791c4b5b3a0a71b63fdddcc8de4b056064ef467989ecccc5d0160d403bf3a025d4892b3b1de3e062bc3581d4410f273338311eb4637529e4a680a6e4a5e26e308630a5b6d49ead6d543f8f2bf9050aa94ce091318721e1d8b96e279f34b9759b65037bec4bf6ccda6929705aeeeebe49e327e4d7a916620c9faf3765120658af34c53fbb97ec07657b3f088fcbdc401aa7949ddeda34d885018c2c23f4f0bb8218bf0d4fc90643658b4d8834f4a8c08e590c2a790995baa9e77627c342d283e454f84fcc05be15e9627a2d9be340c9d72f222bbdfc47905f56616cd9f936d49e4732f319f020513340fb8b22828db251b102b6b137c9533936d6
+CT: bd11ed07b7b4b30eeaf25d6a41a549cca0a5aee71f990ac566a37265d7af2ce3c03703427ee0b2755c2bdfc29f9d826aec6ee4ad28af48079ac23db16580b97424f3a4e35cc23625d39f95699d9ff5143e9a2bc26fcfee4f125f5aa2d968ccfc2faaf9db3c28850f6757f735cbc50c94c498bcde4f23bffafa8dd5f70d1a011e35eb26e905d4e68848fedebeb197be595c085ba33f11ba8398258445051751888e9bba111f800f31b37c447074ca6dce6d54b4dfad6cee5138643d4f6ac045e8047248924e88ea4294c7878bc22c9b41924ce301f22693c33733107bf1ba85e34806c5e4366ea66fc52a5f89dd9bf213239158b3d4d2600dde696c61d76c398b9bf10de9118e812e891c8f3355c0ecc6405f79bc32a58905e37888a1d8395fbedc3ac54eca569f
+TAG: f7d3b58a34a86e99267e5db206f17bbe
+
+KEY: 3304e4917ad7777b86c26a636292c9cc4c10d32003c49e07209eb0ef8505031a
+NONCE: 4d572d116fbd8c4d
+IN: 2f242c2ba33790ecef862b0e077ff8b15eb9d10cf2ff621ed65902494431dcbd
+AD: e699bbf250cdd93d229d0740e433897e2d19132e2b722df8b69bb6a7c2cf3b93
+CT: fb81e30436e437c7f686f86b1b65c73549a9d09db810d320785c3634934150b3
+TAG: 8b
+
+KEY: ed6057bb163f1609ff28b938122f495e3d5ae4ec3dbd7456c9b5c82e28e952dc
+NONCE: e6ff6852f3a3afde
+IN: 3c50edc967eb0b3b2355f6400e0a036e796c8b7d72c5e583a86e820d53e76c43
+AD: 2441db55148e14e9e241d68296eb60d529408f0534143089671bce546db96d88
+CT: 6ecabccee31519374d4bed11296e7483d1cb759bea3f4446a96bda8b4ca6d7ac
+TAG: 355f
+
+KEY: 73568183c1f9725af30e0f2067606ce802c3fe3ab5cff8d02b3db8c35176ee0d
+NONCE: 0bc9e19321b3d00a
+IN: ec2590af5ccd226a32ff750c1b029c11e3dd76c469a5579da9418e4c3fdc0d41
+AD: df30160ae0cbf2cf8992221bd62dffe691dd602afa784ca691479e957af3acf1
+CT: 9e8d8ac30626f8b831448d6976933aa5bb8c6dbc794e1f4b7eeb0e4a59342c07
+TAG: 9fd36a
+
+KEY: 273bcb3f8c067da4ec3418799ad40e7e4aee74ad7e629499d646df4a7e585025
+NONCE: f60be3eb894b4030
+IN: 697498ba964d5ef401da4d94844fab1efc635e7157d0831a325bb5a4cf1fbd34
+AD: 9129715deab14f02c76ba8172571b1fa9d50365cd795bfccdfc28e7e7b4f66fc
+CT: bd4cd5af83be1c13933302675d9fcaf1c4cacdf269f6ff441d1ea2211c54e7ed
+TAG: 7ab12a37
+
+KEY: ad39610c2e6a6d0961207390e076e972c2edadca885c92965fa648b2ce34fdbf
+NONCE: a90db690bba83b78
+IN: 31c49e3cd3d80a82e6b90316dfb94b38b8a23042519bf40c8181fec873c99002
+AD: ddbd7d821d18d44c66295abf245b227b5cf4366811b7b34c07679600abdbfc29
+CT: 94628fc303a0546edd51e966f2bd87968f37800c607d5e5a91f727fc1fec406f
+TAG: c22ec4e4c8
+
+KEY: 29984954060ba06ece1bcfc0e50195f4632c6df48da1e02ae6c14f7065668971
+NONCE: cce53a25aeeaf747
+IN: b9b87433a9894f3c9ca8212623d62369a565a2edcddd276e07d611eda3597426
+AD: 19fa9aa59697559d8b46d9cd49c3b763c0b73b26b9e334a3eeac2c86fdbaca8d
+CT: b68c83397770c36f073710882fa86d43b0e54e8efef0ff75075604d0d7ec4e1b
+TAG: 40d4ab752f3d
+
+KEY: 5c3b838b84100b2a818c0842e9fe19a7c50cf5f3ea73364c816ef588e500ff3f
+NONCE: fdf6b0229e4bcc2a
+IN: 2ba91904c143be99297b39f52856904af41705c176c8c6554b6bc89bddffbcc1
+AD: 3539d9dd821f004f4ced1637071f4be6abd7fe98f017f0a8ce3f49dc8d496f46
+CT: ff9d6d924e737a1df8c2bd3047e40ab401f903aa0e5b51acb991bac38ac2cc4d
+TAG: 1bcaa415a6a3c7
+
+KEY: 6d65e627cab6d5eb1a088b25bd6c3a8a004a7a19cccae909d62fed3559c812f7
+NONCE: 7ff00a8798b792de
+IN: 6848ee4ac820291a2e1dc3baad97f1ad8b7160dfeaa1bc83b2700ae42b5a366b
+AD: d2437b1306bf0ea211449fac863ca0d1074d84caee9009c5d54b9e9bdc8de6b1
+CT: 2da0abe2a71e1c0b1ab309c160a8cebe45c6e16170aa5561806484ba2b5b9a9a
+TAG: 566003e1f78d2a90
+
+KEY: 63401046a96efbc8c6483a2c396b2a593d3fae0db565525b85999fae13a46b6a
+NONCE: 051393d775e635ee
+IN: 2b4b6477580382aae782f8b5772c0948a444d8d95caacd85c0856c7e4393fe09
+AD: 3d84d2e70e9c062d1f511eb685a9a90c8d5fa50eadf8455c7148666b3e7155e0
+CT: 880c1123e54fd8ffb3c293720dd174913572e619ef46504cdaa64fc451b0ec1c
+TAG: 339274339c88d50ac0
+
+KEY: 291fccfce0782f1787d62d4b9293d2ada4c04d37a8288ba9ba9aae0d31aad204
+NONCE: 7450bbd62e4aba7b
+IN: adc251e793181e5d4c4bd983b853eb13f2096ccb340996b6eca4cd2157efcec7
+AD: 4c598f6deedc8c1d97da33654763495cca3517430eec4edb006b10c95e031ae6
+CT: 28bda22e4922cd8ff6739cd8a6bdafce036d9c61a145a65ca1b86f6d4d3206a1
+TAG: d98fd43fe7ac74d4b016
+
+KEY: fa3a9674d4a0eb36b2f7547c956443d09e6b4e4acfc9deda838eb7ebdb999a8d
+NONCE: 0a2572592c3bbbf6
+IN: ae27f70fda9f5a5be0f704a27f0b8a9c04ce83d3c2e0d7ec152da25f473b0c8a
+AD: 6ee8705a9a3655d198497ad410da02005872ecbe397824851b80f4050bfdd311
+CT: f356cbd88e4e2aff62d91e3f914032085388955bbba995fde013758b8702e38f
+TAG: 00324c76fecd3f50e1e3b8
+
+KEY: 471ec87b992b104d369748d96856b5f66149cb45ca05c17f29d24eb9526fe6db
+NONCE: 23a2df9ed0b47439
+IN: 2b9452bca0f48e5519ec3d0736597608df6ad9ce799eba913cff71573d79c092
+AD: a56722ddfaee5f1b64398c225ee8bcdcfde5c2127101c363bfac52bc409c1082
+CT: 7bbc464aac5dd29c25262fe0b116c176d827c2cc8dd63428393b0a9110f3c194
+TAG: 2e87f4a6663a62e47c7e197f
+
+KEY: a29d1cfd4ccdc18803fbca9500f4bb29ce99cfcbf8acc41b8208dae4b7ee5d64
+NONCE: 634f99e88e237ef0
+IN: 09ee5982c5743f396d0c29c13e3fbb8fb89f61705da05466291e010effd51a5c
+AD: 564dddfcc3227b413244f1105b610f192decf15c4cfa067f4d7fcd6bd7af11b8
+CT: 32916b67a6f32733623344c98c49773f3e721dc2ded105fb245799525bc9c84c
+TAG: ff463c07e7ef831321d3fd775f
+
+KEY: 08ba23616d911188f91da063278bef1237dcbf17f52585e53c2c4b6cf3ac9f0d
+NONCE: 989ae593eddd3874
+IN: 749152c9478944c8271c0c11e07bc1c569eec01493e65b3b94842a1bf5d721f8
+AD: a12d1a45b7c9b91ab08751a70b753714052ad24e0b2619fe8c3be303c65f2dbc
+CT: 34c40538ee1d22ddf8ac290dd7d423dfc622b5cf8f3412a5343e277822aea713
+TAG: 014c7c678e0949e88071d1fe3531
+
+KEY: c2ba8bed8634156afc6bfe3754c91744d4131de39d059f3a866399f916553b5c
+NONCE: 80fbf7b433a4cd9c
+IN: 419be6623e7964f9f26068dd969e4a139617e67c5ffb269b3013c433fe771c77
+AD: 3937592db78a61ff469691b6800792019bc2b3d42512f23c1b1a66a8274495cb
+CT: 9d5bd1c7e766763eb00684c038043111d8c6390a8d6e17a15ef97c02ab16f09c
+TAG: a64d0eeb4a01481ec0cee8c1c357e3
diff --git a/src/crypto/cipher/test/cipher_test.txt b/src/crypto/cipher/test/cipher_test.txt
new file mode 100644
index 0000000..b250df3
--- /dev/null
+++ b/src/crypto/cipher/test/cipher_test.txt
@@ -0,0 +1,81 @@
+# 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
+
+# DES EDE3 CBC tests (from destest)
+DES-EDE3-CBC:0123456789abcdeff1e0d3c2b5a49786fedcba9876543210:fedcba9876543210:37363534333231204E6F77206973207468652074696D6520666F722000000000:3FE301C962AC01D02213763C1CBD4CDC799657C064ECF5D41C673812CFDE9675
+
+# AES 128 ECB tests (from FIPS-197 test vectors, encrypt)
+AES-128-ECB:000102030405060708090A0B0C0D0E0F::00112233445566778899AABBCCDDEEFF:69C4E0D86A7B0430D8CDB78070B4C55A:1
+
+# AES 256 ECB tests (from FIPS-197 test vectors, encrypt)
+AES-256-ECB:000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F::00112233445566778899AABBCCDDEEFF:8EA2B7CA516745BFEAFC49904B496089:1
+
+# AES 128 CBC tests (from NIST test vectors, decrypt)
+
+# 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-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-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
+
+# 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-256-CTR:776BEFF2851DB06F4C8A0542C8696F6C6A81AF1EEC96B4D37FC1D689E6C1C104:00000060DB5672C97AA8F0B200000001:53696E676C6520626C6F636B206D7367:145AD01DBF824EC7560863DC71E3E0C0:1
+AES-256-CTR:F6D66D6BD52D59BB0796365879EFF886C66DD51A5B6A99744B50590C87A23884:00FAAC24C1585EF15A43D87500000001:000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F:F05E231B3894612C49EE000B804EB2A9B8306B508F839D6A5530831D9344AF1C:1
+AES-256-CTR:FF7A617CE69148E4F1726E2F43581DE2AA62D9F805532EDFF1EED687FB54153D:001CC5B751A51D70A1C1114800000001:000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20212223:EB6C52821D0BBBF7CE7594462ACA4FAAB407DF866569FD07F48CC0B583D6071F1EC0E6B8:1
+
+# AES GCM test vectors from http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-spec.pdf
+AES-128-GCM:00000000000000000000000000000000:000000000000000000000000::::58e2fccefa7e3061367f1d57a4e7455a
+AES-128-GCM:00000000000000000000000000000000:000000000000000000000000:00000000000000000000000000000000:0388dace60b6a392f328c2b971b2fe78::ab6e47d42cec13bdf53a67b21257bddf
+AES-128-GCM:feffe9928665731c6d6a8f9467308308:cafebabefacedbaddecaf888:d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255:42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091473f5985::4d5c2af327cd64a62cf35abd2ba6fab4
+AES-128-GCM:feffe9928665731c6d6a8f9467308308:cafebabefacedbaddecaf888:d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39:42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091:feedfacedeadbeeffeedfacedeadbeefabaddad2:5bc94fbc3221a5db94fae95ae7121a47
+AES-128-GCM:feffe9928665731c6d6a8f9467308308:cafebabefacedbad:d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39:61353b4c2806934a777ff51fa22a4755699b2a714fcdc6f83766e5f97b6c742373806900e49f24b22b097544d4896b424989b5e1ebac0f07c23f4598:feedfacedeadbeeffeedfacedeadbeefabaddad2:3612d2e79e3b0785561be14aaca2fccb
+AES-128-GCM:feffe9928665731c6d6a8f9467308308:9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b:d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39:8ce24998625615b603a033aca13fb894be9112a5c3a211a8ba262a3cca7e2ca701e4a9a4fba43c90ccdcb281d48c7c6fd62875d2aca417034c34aee5:feedfacedeadbeeffeedfacedeadbeefabaddad2:619cc5aefffe0bfa462af43c1699d050
+AES-256-GCM:0000000000000000000000000000000000000000000000000000000000000000:000000000000000000000000::::530f8afbc74536b9a963b4f1c4cb738b
+AES-256-GCM:0000000000000000000000000000000000000000000000000000000000000000:000000000000000000000000:00000000000000000000000000000000:cea7403d4d606b6e074ec5d3baf39d18::d0d1c8a799996bf0265b98b5d48ab919
+AES-256-GCM:feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308:cafebabefacedbaddecaf888:d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255:522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad::b094dac5d93471bdec1a502270e3cc6c
+AES-256-GCM:feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308:cafebabefacedbaddecaf888:d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39:522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662:feedfacedeadbeeffeedfacedeadbeefabaddad2:76fc6ece0f4e1768cddf8853bb2d551b
+AES-256-GCM:feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308:cafebabefacedbad:d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39:c3762df1ca787d32ae47c13bf19844cbaf1ae14d0b976afac52ff7d79bba9de0feb582d33934a4f0954cc2363bc73f7862ac430e64abe499f47c9b1f:feedfacedeadbeeffeedfacedeadbeefabaddad2:3a337dbf46a792c45e454913fe2ea8f2
+AES-256-GCM:feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308:9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b:d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39:5a8def2f0c9e53f1f75d7853659e2a20eeb2b22aafde6419a058ab4f6f746bf40fc0c3b780f244452da3ebf1c5d82cdea2418997200ef82e44ae7e3f:feedfacedeadbeeffeedfacedeadbeefabaddad2:a44a8266ee1c8eb0c8b5d4cf5ae9f19a
+# local add-ons, primarily streaming ghash tests
+# 128 bytes aad
+AES-128-GCM:00000000000000000000000000000000:000000000000000000000000:::d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad:5fea793a2d6f974d37e68e0cb8ff9492
+# 48 bytes plaintext
+AES-128-GCM:00000000000000000000000000000000:000000000000000000000000:000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:0388dace60b6a392f328c2b971b2fe78f795aaab494b5923f7fd89ff948bc1e0200211214e7394da2089b6acd093abe0::9dd0a376b08e40eb00c35f29f9ea61a4
+# 80 bytes plaintext
+AES-128-GCM:00000000000000000000000000000000:000000000000000000000000:0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:0388dace60b6a392f328c2b971b2fe78f795aaab494b5923f7fd89ff948bc1e0200211214e7394da2089b6acd093abe0c94da219118e297d7b7ebcbcc9c388f28ade7d85a8ee35616f7124a9d5270291::98885a3a22bd4742fe7b72172193b163
+# 128 bytes plaintext
+AES-128-GCM:00000000000000000000000000000000:000000000000000000000000:0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:0388dace60b6a392f328c2b971b2fe78f795aaab494b5923f7fd89ff948bc1e0200211214e7394da2089b6acd093abe0c94da219118e297d7b7ebcbcc9c388f28ade7d85a8ee35616f7124a9d527029195b84d1b96c690ff2f2de30bf2ec89e00253786e126504f0dab90c48a30321de3345e6b0461e7c9e6c6b7afedde83f40::cac45f60e31efd3b5a43b98a22ce1aa1
+# 192 bytes plaintext, iv is chosen so that initial counter LSB is 0xFF
+AES-128-GCM:00000000000000000000000000000000:ffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:56b3373ca9ef6e4a2b64fe1e9a17b61425f10d47a75a5fce13efc6bc784af24f4141bdd48cf7c770887afd573cca5418a9aeffcd7c5ceddfc6a78397b9a85b499da558257267caab2ad0b23ca476a53cb17fb41c4b8b475cb4f3f7165094c229c9e8c4dc0a2a5ff1903e501511221376a1cdb8364c5061a20cae74bc4acd76ceb0abc9fd3217ef9f8c90be402ddf6d8697f4f880dff15bfb7a6b28241ec8fe183c2d59e3f9dfff653c7126f0acb9e64211f42bae12af462b1070bef1ab5e3606::566f8ef683078bfdeeffa869d751a017
+# 80 bytes plaintext, submitted by Intel
+AES-128-GCM:843ffcf5d2b72694d19ed01d01249412:dbcca32ebf9b804617c3aa9e:000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f:6268c6fa2a80b2d137467f092f657ac04d89be2beaa623d61b5a868c8f03ff95d3dcee23ad2f1ab3a6c80eaf4b140eb05de3457f0fbc111a6b43d0763aa422a3013cf1dc37fe417d1fbfc449b75d4cc5:00000000000000000000000000000000101112131415161718191a1b1c1d1e1f:3b629ccfbc1119b7319e1dce2cd6fd6d
+
diff --git a/src/crypto/cipher/test/des_ede3_cbc_sha1_ssl3_tests.txt b/src/crypto/cipher/test/des_ede3_cbc_sha1_ssl3_tests.txt
new file mode 100644
index 0000000..2b57c8d
--- /dev/null
+++ b/src/crypto/cipher/test/des_ede3_cbc_sha1_ssl3_tests.txt
@@ -0,0 +1,840 @@
+# Generated by
+# go run make_legacy_aead_tests.go -cipher 3des -mac sha1 -ssl3
+#
+# Note: aead_test's input format splits the ciphertext and tag positions of the sealed
+# input. But these legacy AEADs are MAC-then-encrypt and may include padding, so this
+# split isn't meaningful. The unencrypted MAC is included in the 'DIGEST' tag above
+# each test case.
+
+# Test with non-minimal padding.
+# DIGEST: 4a7464217ea94d95668d31736693ae851eb0e39a
+KEY: 171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6
+NONCE:
+IN: 936a91d0b5
+AD: d2c0267218cb7090c6
+CT: 267abdc1b983e49bc0b906878f32d6a4c8181e7d
+TAG: 5acf3fc5024062031c33e0801c44319a66c01882
+NO_SEAL: 01
+FAILS: 01
+
+# Test with bad padding values.
+# DIGEST: 4a7464217ea94d95668d31736693ae851eb0e39a
+KEY: 171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6
+NONCE:
+IN: 936a91d0b5
+AD: d2c0267218cb7090c6
+CT: 267abdc1b983e49bc0b90687
+TAG: 8f32d6a4c8181e7d5acf3fc5a3bf9078433cc5a8
+NO_SEAL: 01
+
+# Test with no padding.
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11
+TAG: 997c66a777945bb051934aa50dc6b8e3e58cd0b6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 095a8f557f75cba8e2452ddf97c053904b48827f
+KEY: 18cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1
+NONCE:
+IN:
+AD: 936a91d0b5d2c02672
+CT: 77e3ff59
+TAG: f948dbcb8582c2cde43b466a54a956898f56a752
+
+# DIGEST: 4a7464217ea94d95668d31736693ae851eb0e39a
+KEY: 171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6
+NONCE:
+IN: 936a91d0b5
+AD: d2c0267218cb7090c6
+CT: 267abdc1b983e49bc0b90687
+TAG: 8f32d6a4c8181e7d5acf3fc58f1d717a09fc1797
+
+# DIGEST: f1efd4c11318f4558eb4a50d5a5b9b1e540f6dfc
+KEY: b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c30
+NONCE:
+IN: 936a91d0b5d2c0267218
+AD: cb7090c6171386d641
+CT: 7a4dbf7807b4be968093c640
+TAG: ebf8cb38dbdbe56024a1c22f7ed023120f598ace
+
+# DIGEST: 995341bee01fb91132d1af8394401144a35bd965
+KEY: e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c617
+AD: 1386d641b87797b684
+CT: e70f93c6900d96a1d47c719eeac751e2ff383cd9
+TAG: 915d9901dff460051565eee5e79b932fc47bbcad
+
+# DIGEST: 73dc06657c34ffcc71e6662ec0a52aa7168c22e0
+KEY: 3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d7
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b8
+AD: 7797b684e0fb56f97c
+CT: 52632646daba40c88bec2d3958bc5f46141bdc1ea788b81efc7a608a
+TAG: 68c1e272babbccc02f31dba07a8431f0e258d07a
+
+# DIGEST: 6a5e3024f92e29f8f3e294f87fb25572c0390dd1
+KEY: 2993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0
+AD: fb56f97c3961d8afa2
+CT: 526fa1466e35d3bca354a7e290042a327c239a79264bc5559844ddff
+TAG: d30a03e7d7bfb58784c46a96857cd240641ebe96
+
+# DIGEST: 6f192a6acc2fed00007506adeb1dd454e2e92809
+KEY: b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c39
+AD: 61d8afa22993a340b9
+CT: bcefa25e0ab10cbf1e6a779c6be6ae031668ab15a3295e2eb8bfbc09947c0e1ec05ea2f6
+TAG: 48341a914b69041eada343af7725b0226c786ab9
+
+# DIGEST: 7faa4d4ec92841e45297553097f2ac2ca53d2592
+KEY: 1df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa229
+AD: 93a340b9b3c589c748
+CT: c70b3ebf0546758b8eff783142ac8e22cf95dce71ee949ff70e95c67df68e29fe15c70d8
+TAG: 9e7545b4f24d70c888cfabd3ec45c4675d52e3f9
+
+# DIGEST: d6cf3a4fe57328e885cb10cc7088e0562c7f91b3
+KEY: a23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0c
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3
+AD: c589c7481df3f4183a
+CT: 2f558e9d61062e01c873fed6c11b6fbe2be751b6f90d3852f812f3efcd04e5265df631931aa5c74e0974bf8f
+TAG: f66d57040b4a0475ff373a8b63ed3c5cf313a955
+
+# DIGEST: a2ba1bff3a6dc3ffa8c405fb8f69c41ce7c1a1f5
+KEY: d88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be9937
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481d
+AD: f3f4183aa23fd8d7ef
+CT: 2ca3253fe692823d686d9f30ca78a6d1fca204b6b71a47395f2bc6966067f9f540ba84cb5504198e821a7e5ce3e70e44f9ee1f9a
+TAG: a197e66b8c40b802241a157057df14d4de1bfd72
+
+# DIGEST: e2825275a794df011a9dd0c6061de3a9eb2efd48
+KEY: 8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa2
+AD: 3fd8d7efd88503f78b
+CT: f0f4fe175b2a51041ed5c73c0b05893b0b9e5cfdd1cec279be6d57c27e74afbac5c7f933b3f7648cc6969365dd5010ae5b63c940
+TAG: 5d64505b78ea53c24d2a9a5ab120f9a62ba2914a
+
+# DIGEST: ab656533e45e90a45a508392ce59ab9bbcac27c2
+KEY: 2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd8
+AD: 8503f78b8ed1c8e9ba
+CT: d068faefabad8e9a5cfdcad7e24295d6a3ceb8006903957d4207b3d49fb8dc3ffa11989daabeb45fa1c03218b668cfb78020ac6f8f5081316944b374
+TAG: 4fbd3895a9044c385aa4186a3a0176fc7b9fc69b
+
+# DIGEST: 0614460f6ee128d42ae79b1dda518a0f0e4d0d16
+KEY: 0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8e
+AD: d1c8e9ba2fd6773e0d
+CT: 99be2113bf150035f4be2993996f0b09ecdbe310529e7ee7be8d1906b38e9b16a653a738651f12b25d54917443a35dabcefd04f32313a0a3e10f201d25bbead7f2ff6db2
+TAG: 974a3317ab352f92e19b15b1b6a106c4f9cec9dc
+
+# DIGEST: 629525ee366d420f18c6a88fa3a8cfecaa1331f9
+KEY: e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a1
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2f
+AD: d6773e0d0c302a5f47
+CT: 3296137ede477266ed6a9442f4eafd4fc62d7ec7d0e99f0fc7787c016ae84a4f967011b7837ad6c1f0bc9dd51b529e9926192a1c603c2ed39e689a5a11573c3f277b0c80
+TAG: 862cb82d0d4902a4288b5b25c83b6c2e5936d86c
+
+# DIGEST: 79b26abc71e1670444167ecf48e093d505678371
+KEY: 91d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a729
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c
+AD: 302a5f47e037446f58
+CT: 719d9de3bc86d08510354817d0fb94340ab1ddeefdb95a1cf460f7c9b185837b5320dd862b4c319619a0b18dc75f1762cf7c9bed63713c31e39a6f7069563441b93ba76b8510b686c3489a69
+TAG: 8021bb9df11cf8b9b07ad4f4c4ce06e8e73ea4a6
+
+# DIGEST: 6cd5a6f762364b9814deb6e1cfba1eae5b0f31d3
+KEY: ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e0
+AD: 37446f5891d77df660
+CT: eeb6afcfd2626da1230067ed9938f7df35e99d2ba1c91d0e91c3db53034a3dd2ce3352b06e3d1b9e8415ef4ced9b2257eb05bc86db8204a8bd943bde51423a09459fecd528faccb6e333fdde
+TAG: 2269b91988386e0e448212b3c6db2a58931011a7
+
+# DIGEST: 2d3f449046b625672e740920da76e6cb0b297236
+KEY: be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891
+AD: d77df660ed82933f62
+CT: 894d8fc70288c7b8a5d12e63ed6e6e8c74b8d9837720762ccc519a42e024ee05e8f770180e5213a7c7ceac56cab05834d49847aa1432fcfad8286e092feddd421b33212e41716b3d337aadb5c561944395478852
+TAG: cd8802361679fc257b650eadf4181b2cb5f5c27a
+
+# DIGEST: f321845e9752dd4bbc414648274459099c9e5574
+KEY: 6965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed
+AD: 82933f62be8dc55b43
+CT: 8b397fb4fa218359120058dbd145f4bd99def7e5e0a88249783128801b3828909ea19d9f5fb0f3e15ebd624fc32525796ccf9ec01b1da3acc6dec2a9306c57db4eeeeef4830575fd8166c13c23664d4d1bcfb7411f088ceeedb63764
+TAG: 3c41693bab784c1269dbbed43bae55d4bdbb9208
+
+# DIGEST: da9868a42a40dc263e0a0fe4247ee859569d7f63
+KEY: 7e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2ea
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be
+AD: 8dc55b436965aabe47
+CT: f64f633af5421e2b8d343b52642ee5448527831821d39220eace1ee48eef879efe49679f13a9c7594f16511427d3b5eacc8ccdc597d72ad37f5ae1a9bda42cd690ded3eba9a6fe3bf1f36f480805351df8daf2d92fb90d18e06817cc
+TAG: f276fddc28b1ae41c9022998aa5327c5fca1512b
+
+# DIGEST: a17d268f79216e57050079ed4a85ce137f83cf5e
+KEY: 99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae021
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b4369
+AD: 65aabe477e0cdd46be
+CT: 7c5e36678f3fc8465f7770d619712f4fdf45922b20db9aa521e721ca35a02446f1f06ce15971afecb695e3e780f4972821f9fa044564fd8675f1626c5b5f8a24da4493917526ad72b631acd16b13ec9aae03ee7b5034919290f246147e3f2d82cb65ae99
+TAG: f2e458f17b44de16f6c49953d5db231677013acf
+
+# DIGEST: 44ba8d9c06c6788865a1dd76287a443eb0c22aa0
+KEY: 7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0c
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e
+AD: 0cdd46be99371eb8da
+CT: a6e967aa8bfe23d4237d593e6cb2e279174b57acd9037fd150cb3a00a5524256756602c8541f6eae44e2b97245f0f63894afc812ebbf87f77be763320d0effe9974df583519582f72b57845bf20bb2f82ad5dc59b7d695a424001d0b9a1194b92ef752cb5415a925ad70a1eb
+TAG: 7a0a73803ae02d78be28ee02fd1307f7e3653cff
+
+# DIGEST: 5b0d95d9ca1dc4d0ccd940d38881b8864757c9d2
+KEY: fd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+AD: 371eb8da7dac997dea
+CT: e21464474404e9d0d653d2e5214e332ee7691e12bed8f91627208c67da34033887369def4de497f2b7d39c0b0c9101bf25e7aa405a165ce0ad00f7bf311e19f6a45fdf5e13f6ea9b6007a5ebc584e0e68dba642f1d6427a6cf6f84147dfb3f3d924993202daf87dc85d43120
+TAG: 94cd6558662a7300187d5ee7f5b9b73f83f60799
+
+# DIGEST: 310801f266e960f886f9a02cc9e8adaead89dd29
+KEY: de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f2
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7d
+AD: ac997deafd64b1fc65
+CT: 3de7bd95f32d7bd6e263993e48d69eb4cd90f2995e437f1112707f96ece932b1aa317ac0b4abf88a8a90581b9118ceddb576c74c960d5e734eb157b90abdc61b90d485314ffe145a5603bc661bd9a09f4dde518b762ab6de54187baed5f23d6d27f528f66d080a1b670a3094fe8c2d880b1b1aa6
+TAG: 83612c900a85c7a5ccd62119e71906fff0c99dbf
+
+# DIGEST: f6998ed9b090ceb8422100ff91e5e2671a49d980
+KEY: 41a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d03
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd
+AD: 64b1fc65de39f4f035
+CT: 29cd7e2276dc4170c3f73666ab4e87527758ec7324c9956629128cc2291d73e1894eddbdc234f9fdc70cd31cb4d76438e9e0f9f43c1788fada093c829aae078fbfb287609ee81e2e3b6e607245228842e001345c1624c4e40ee09042c7074cec076e2efe2dc58932dee704728ce57dda95df2061
+TAG: e0ad444be0abde69245406247c8907a87ec7c338
+
+# DIGEST: af2873f1a7fcd4930f1c8a554ff271c5ee9185ce
+KEY: a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de
+AD: 39f4f03541a11be112
+CT: 3e94752703e605b1e18ade7f560525381b41b75c871add14d3190286f19267b75f44135e3c1cac10fd59c29c136b9f105dc503721e831f10bba87ac8ed1844892e1b0e4895a778b7f1be7f5cb76a04358ee28471c1b55f28e571e297d6b6eeb4634fd3c7593dceb363211a890fb44f61538f3ec147d046e8fe91353d
+TAG: a710a8099050407c3b74ab99e6e99b22d1e199bc
+
+# DIGEST: c4eaa1d6c4d2d5a8d2f4d96890bd0299f1d699d8
+KEY: 4ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541
+AD: a11be112a72933c7b5
+CT: d426f1f4e5e9f77c9ce41b9e3078d1138d28428a0c81cace18a5c10c83ec1d9e6ded56404f7cebab2aec5f8c0849246c28c08ecc495202ba4e640117be1489c0c4e8c9b1dfd014e801423c3142c567e06d41378b18741b0e1f73c1663297da3a2391cdae02640328d528b03d536b8ab97d019e8e68fdc599efada7deae196898f350a645
+TAG: d5007c866199f399c4c79d2203efb4e3a3aa2f12
+
+# DIGEST: e9bb0964e1cb09fde5e8f852937c4d8e1605b714
+KEY: 905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a7
+AD: 2933c7b54ed4fad0be
+CT: cafdd119e14240dc6e9b6e88db8ebb69beac90e0e5c03c46481dae13c8ad8660ae620d1a5515a0f83022977f2786c4b0ca7a560942b542cd2fae1416ffaf74ed6cd0b61a1d3353fa684c6d098fa56c34f46da4ccbf17eb23644e1af99f35c0415812876e69cf584edeb5dbe23e8c5a912714d4c3dba0b153feaf1f12d62bd6d284258d60
+TAG: ef2e489eeb25553669ad5b6829f4ac9eccd1d04c
+
+# DIGEST: 659746de28fff60cf3bcaa07eb7a95c5b7d3200a
+KEY: 5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a74
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54e
+AD: d4fad0be905d41203f
+CT: 1fe9b98944ab7ed6bb3a0e6c82aed6ce9b2ee46fcf2862e1f2cd7bb241291e9653aaa1f0f69a2ad7bec55449569661de65674fa8324e0672c802bc026a07d339d69c88dfb679f78a9cda1a9de3e6d15f80cdbbd3d95d5d7b35275292a71b53b1b6051827477ea7258d1d87297ce0e9b378a61b626a8380c63fa736af14782ea7660e66c021a5df77c2a10ed0
+TAG: ca7536afb8103ad562ffe515b9457189bc61defe
+
+# DIGEST: 170202dac332954785ff6f866f165ca62510d9bb
+KEY: b2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be90
+AD: 5d41203f5dce998f8f
+CT: 50da8d3c28a1a69a55150924d561482411c88a7451954d57b9bd78af3e0f155239369885cd00cf3109106087fe6ea20c1d021f5cdab1ac5d6c468b569981a2fe098670676d253e574af321c58aa4eb809f6aff4c07716f09b1a84e9bd06599ea76ae1ab6b879c0d77e026ec181f16d90584e5525f3d3369a573fc5926cf76be995dfb27233d4a2394c9bc8695a6bcfb6efc3b16d
+TAG: 404e3cb0cab88a6287dd52a4c847459c4025d3e9
+
+# DIGEST: 767d4f588b55b2593cfbdc46acc6064616f75c2a
+KEY: e02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b144476
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5d
+AD: ce998f8fb2eaad409a
+CT: 9ea48a66fd32adfc4c7cc31d28802b3867064404462752703d10e2041808e47851220b6fa877b72cce9cdfc9be819c034d4669995610f9796e0113fa548a6a9a359f9558950c5803e1c04a16fb6a1d130d550132617a5a9e7e19379e872286eb54984b5b306b51af0690762a7f073f13dd9c286866cc5d92c3877d0a31a547dbba0b101dc1602201a6e52332b53cc33417d25cf1
+TAG: 3f489636991abd14b6c01849c102ea8b1b7776ee
+
+# DIGEST: 27937a84ae455678a2f3c73b523d600135e6dcdf
+KEY: ae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2
+AD: eaad409ae02116417d
+CT: 6bcfafe6e33fa147c3e6316d8a3befc5f6ae131ecd5af45adf9d13783ea024b9eef6966ff04e08f2e48799e279f716aaba59dd58f6dde28920143b46f61704c0128c6ef8f2134af1228dc8725b0bc5f00faff23bdcc3813a599128f81114cb65826d2df9b39bcd1f084f28bd5a11b7ec247d5baafc419e6134000813ad29318006ccb066147e8f9187aa57465e01a83887bc453c9f1623fa35462b05
+TAG: cf22c931e1965446421fa490781f5b71f148c9ef
+
+# DIGEST: b1c534558a6ecb0ea225369be47ddfe669190d41
+KEY: 9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae0
+AD: 2116417dae0cef457b
+CT: 27dd6b1d84e3046715115ac2c867b35f09925fc5887a1dea3eb5dfa35903adca50b8b941abb7e2001321ba832029520d854aec718598cac026210e6e28f3575d9aa513ee67b10b8e681c8e6b996f0d77bdd13b3903bea150dacf557c2bb5685be9309ee5a98aa902988eee5896ce7419a840e2309938a54ff2ac0a2c188bd2cca4b50fa70aa4adbf3277fd4d7cd7476b54ef77341feb00c6be713930
+TAG: deb0c0883493a56353ae1b6c74f18336495a515b
+
+# DIGEST: 774dbbcae39eaf44fc300eb00977f4e56e4dc0d6
+KEY: b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3a
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae
+AD: 0cef457b9e5e16dcc5
+CT: 040fcf5053d0377687fcd7efaacf8c2e5eb2b23086a0e5c3137a481f42277ee5126e9930b24f1f4c82e0f9c25b7a470c60c7964941f994a58c0c4e1024800d5cd8996122f6f614a45dd1a86b37007ff0e25fa8c6d74245ac4621e776c25051ef218bda7005dc355285106e93bf068a9baa5a6e81af29b7c8d629bb758b7502eacdfc40e73e24fdc95666dc9a1bbd912115c8048a1735148079fc445a0dd00a6fb77fb3fa
+TAG: bf4a12eb75dfe8c2b8d65d87d9900ac22ae9e7f4
+
+# DIGEST: 5c6b13d8f7e9f764136921bf62cf406b9dcc8615
+KEY: 0d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b18
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e
+AD: 5e16dcc5b6f25607f0
+CT: a644db1ea4cea0d0543b6cd86171f30c46931322e0974b13f2fcf1e16846887aaeb6367f05f117e67aaf205c67e779e92c1f01608c23acc372e8de544381c3a04e71554fd5670d1cfeaea9b2b61f56b29f0df6e290cf6ec5e89463f1b6204b9744a32081d094bfca98c833121458958f89996a40f01f6412cda9651f2df92996b6084d470edb3aa8fa2d93b2bdc148b3019bee0239b91f21f4ce2041739f1e3093be8441697d8fc597d56e59
+TAG: 2b402a0e215013db6984d8f941fbcbb15e8b802a
+
+# DIGEST: b72799f51e711da0ea2528a5125a994e33078898
+KEY: b09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6
+AD: f25607f00d033fb95f
+CT: 95b1aeb1f50b3500029170370c24f870c76105592077ea9a3c7eb1219caffa624079b76fb88c5725efb0a0a8f7040c84e4f305bb2edf0fcfa6dd6a44ac47a8a47144d6e58ebac08c72bf62f3d59abc02036a05cc51269b77b061eece24e98880292e3b022c436f227833cf2162537730be51da7f73ddb14ddb5a534fa66eb375c7bbae288f514377783fa4a9a68c0345756ff0294f3e185ceb53880bbdd85c845c4378be9ee8ccb967f1d530
+TAG: e7840e73bb0686b06fda51c92408f5a709a1ea8d
+
+# DIGEST: c2c932a2159da6861262e601fe835e4feb139fc6
+KEY: 172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d
+AD: 033fb95fb09e4d00d6
+CT: 4e656329b2a0bb6fe47dfaab34ab0126f640a9c07a3f4c8e444aec99944264b9057ab556dd6f943494b49a13bf8bfe7cff16ec560cf81f1b0124bb6d4c3adb2e52127f52dbbcff31123eb666cc742a0ca6e9bdf2f7222651f03ac35da01ff384a1b0982933f4ed0aee39d3695157add38320ab24282c809d17f1f434cebcf8347440ba3af410933363b286c8bea7b12a0ef09001c6553d7fa0097c8baff655caee36842f500a592d039ed12bcdefba3486ca1456
+TAG: 5f9a6834f9355d04b7c302257edb88bbed3c133e
+
+# DIGEST: 25b40da26cc2da8afe980d0287004507d92a426d
+KEY: b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb0
+AD: 9e4d00d6172e780ab8
+CT: 296fee34a103ad45ca1179a70c1e24f943f9ede806c746d7561918f0bff681633d11ae80dc0fd2f3141d81039218b2d4e242c780faf345578461cd286e8f4f1117f59c9db8c00f92630650eb39a8e858c9f8df313a9bae6bdc1814468a0d8ca5d980e557d14b1df52533b18687d6c02fe0ab62053698912ba8c29797a42abf1fca282cba2ecf3f4fdf0e0b7fda983f88d2a120fcbb13dd423b550d63a3892b6c229db0a73a6a32ae0822f235fbfe07e97c2885f7eb99720569f93ac2
+TAG: bf96b55300ff9a6b9b356d116e4d6c89161361c8
+
+# DIGEST: 2b6449832e28e0f08469119a61c6119ecaf747be
+KEY: 7a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d617
+AD: 2e780ab8b700433a95
+CT: f078d80206e1263974df88b766bf358c46c1c30ddd6c96d99d72bc193d67cbcbebb7a4861c046c94827639e34282e8bffcbb08565fc1abab4c4d5a166d213dfd0ee7af94488ad70c7376ba71bd9c4c72a119d64e664b4965a005faeb93696ac2cfd168b1e99e82ebad066492622dce7803cedaad26a5fbd125ec8c1bc2120501d0931e8fe9fc53d01b2c29b47b951093388d69cdf35ffc386e851b1950394d7fb6a70e853df1b46dfcd793860bb09cbc37dde34b6f666610a391afe2
+TAG: 21231248c7de1a85407a62390b2ee4e25c0598a4
+
+# DIGEST: 4e2f1dae39e30675c6b32f427ca47ce502a02191
+KEY: 0f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249c
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b7
+AD: 00433a957a741c9eb8
+CT: fa6d75da1fc0f8576aea655b00d70b59033d7a062dd2192b1b77c370a35dd9416946aeebf5fc88a06c5d962ef085f06af56d38b282750d9cf565e9567adbc0c1620d6ebf0c0996563718b8c5a27d6c8bf58bc5f9d8a69cb8743324dcd1610c6d4770dd90efe96db7f8a6eba1a086306fd89f8368f414cd94d275e9c9ee14fe1756ee41145e26971cc17931a12d51bb5a6f5e3b7ec8906ce8a8658b8c7bad2818c6ae8aa550982b02e609551291e324fcac781960cf884b5c8dd6f30ebe6e5645be2cbbff
+TAG: eaf26782ccdbbf53892c1523c606066b45d7a393
+
+# DIGEST: 4b779331c327101cda11bbea17702561aa8a410d
+KEY: 44769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a
+AD: 741c9eb80f2b021b14
+CT: d84660eb57038fbf6023f1ea46f29bfe463d722966ab02d8ac4847a7f41b1ec5716cec350fdd9fe908f01db56bc44d62f0d1599167a0a229e901bd0ea1bacff182fff5e78ca5074b974ae0d6654bd0b5acc930276a372f40bccef66bcbe516d7fbf7317d035bf6728c39b3d7451e84394abe84907d876d791fbdfb3df2edd21ba24c112e3df0abb562203d1a78c469f33cbf30a0daa03142efba5f617eba3a8e1de9f623b161fb6268dccaeff2f9ef210dfe4be82d205cf6929f819368c17f8f0c7f31de
+TAG: 70b8dc7f5070942e1c42f3380849b27a3845f2bc
+
+# DIGEST: 708364fadfaaf52792bc2fe5bdaabcf986af7aa9
+KEY: cfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f
+AD: 2b021b1444769da00f
+CT: 5653b6672ede3a17eeaa6f075adb7f22610cea7f5f4a2fc38430de8466dbfd4871222c2a24c8817af13dc6b82ed44ded4a757455f642df83e5f9b593859ce7f4f11d81c60264dcf3c40d4f8c66286d480e2832f0e0dd8e885ebc77c0ea05797a434a1fb97ba30ad2924930f2c2ca204141c1b90c363d33c9eb003b120c4262e76120305fd29d3059eec4aad7a30b9d4df7517703669965bd21b3d182f575aeaf873d7d927bbd00015c4af7d884d69187d5f93dfcc417c4b16d6aa64c2c2adff7305928cf603bd45faa524c60
+TAG: 8dd82f2c6b333cd0b23819e31399a50800b3df81
+
+# DIGEST: 335c241743268f08b03aa63abf9642360d22a112
+KEY: b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e7
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444
+AD: 769da00fcfab0f5f93
+CT: 10c64b9a78b8e4897d3f8a8b9f7eb88a24e9afb892eb730d830a860d4d6c8c5a1f10ccd7767021a18200a100794bce8382a4937bdf59d6344a4fda104365a89d748e2e7a0f4ca41256a4a1f0b1dc872a4c7941c104bce160ca17e34fa1d82c39f005f9e4777870d1272d27055019cf09e921a1d3d9a034e056ec4ac62bfcb80d8ca0418647aa8a72a3ebd02fa4d5b2aa9963a7fd0af2c9e7d2ed0c9773b79686cad03da4a7644fa76eeede1ba97122f2a5f3bbc10cabd205402f745c06489ba0a673be2b11d1843bcf1b96226d653d3447b2ba2c
+TAG: a258907d24c57bbf2b66fca54bfe5b5bc184013d
+
+# DIGEST: ae61ce3c2b1475f8afdfb1be68addaaeb6489356
+KEY: 5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025c
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcf
+AD: ab0f5f93b511060c9c
+CT: fabc3275c597dd00bcff5ad86a707b1faa95af38785da98ef2976fcb8807e5ae9cef41f65b286727b60b6a8681cd7bb81be8577b35b745ddff5d9a44e5f4affe53c61d8c7d5ec24c9ccc5e3c057d840d08e8407e202ec39458d192fef397a3422e968e446b05be58a9ed71cdd1eceeaadf16d8a90ff397a22ddd20206ae11462044336fa30e109d1a3a483fe379fcc07536ab32f56a81e4be456c1d9f7e305b6ad5a90daa6cd2c15f8377f94d08852bc69d0370575606bce8f97ae372c4f33056d190668a143f0f2fb1079a7fcb0baa63b788184
+TAG: 2369ef569ca5168601acc8fd592e1ca3b9bcd4f5
+
+# DIGEST: dc6621d897775dba7bacf8b7f82bac003e984b00
+KEY: 1b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d29
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b5
+AD: 11060c9c5f3aacefe6
+CT: d8650a5806a479f00b0e903aee156d8cb9e01462aab7b1fb98bbce1d7bd6d197c58e94b952f7bfe87e020096cee18963705841fd42bf74a1bc250e280165c6719ab341dff9cf22fa51be884b97518377a6f9835687cfd4c126a2d4037bf7aa015179b5711a0d1375464f99aebbbb35f3b92b81066c8ab32b54c838bcb4a212918e5944717fe84d1304e1eb174eae04f5f66f28b2055cf722a0c87da46048f5aeab3a5a4c29a3dde34aedaf0fc93fa553325f0698be6d7c735b9a44c98f6ed01c3df161f9987108b4b9cda8bf132fd07f7e8af152d8cc0b6bfae3193f
+TAG: 64b9882cc8adddb00d99f17a12b62eaae695629d
+
+# DIGEST: d2e6d3eeb6b5565d9a407fb96c74b8b3be42e64e
+KEY: 3939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f
+AD: 3aacefe61b184ad246
+CT: b7edae6c7aad16192c3dbb2d9f0813ae81a3fb9f1703a58cc85a5ef9f20439bb6e6377adad49002e03829c2afa320e552d543581b05243b5769c5c5211690650a8f050fbdc29da9daf0b56d3546e0b12ff5c7921978ea212a4f715f81ad546d3cae297d550335131f4ec5dcce627955056dc2d5efe5d355ba5245d61de59923b3dc099bf4f5095686d4dd666e4f1d9c4ee6a29cae485730a9c69fb3f1033e72fe5cf18c6a2b74eb7c22b1706a13c2b054900773f23dba77cbdaa2a47730bded8a07f24edd0f78d68b58e8769b33fecfcf191c34c8a1d2bcc6db63d1615f4a10fab0bf392
+TAG: 00aa855ff0bc80a14859f67aa0ba3d51677ac8ff
+
+# DIGEST: 238d50a0695b1f255d5b3944c623876919f9cc6f
+KEY: e97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be5
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b
+AD: 184ad2463939ed518c
+CT: 80bf5c9e9d8e7091d9a7ee8b0cf12ade92e5983b86ea90c84447eb6aa494a5cd5c00fb07207978ac8ec7b8959b7126435cbf2f59f2ce319b99c53d507876a7e6761dcb90d64295fb8100e7b61005a39640e90c966f8b8f6aa5cadc4fc4b63fabc363e4c8d07789b1b476ac00c18d37538a7e17e71c355ee6c4a3805a8e8ade743832fd6603047effd0e80927bf28f2e0ccae11bd16e8b6b6d9c542de16804b0426f8fafe9ebabee2f80cbc595b7937429ed119016131b832d0651e979b6f74ec9334c3f0db85b8557da3398fc8aaab8593d972d2c235a6094cf172f0fb79ec71e54e605e
+TAG: eeea51eaf0ea7523bdc92368ffa0fd6595ce1245
+
+# DIGEST: 562090fcf982854158b6068786792d26d2af3cb4
+KEY: 3d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af1
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad24639
+AD: 39ed518ce97c3fdd29
+CT: f6096606ffdf8d3e00c5e0b71c1eee74e3ead824c59ba76102afdc193ca5aca324eba95b8130539b2ef96bf4fd90200b87536fb105ceabcab4bf28424c1b7cc3d1dbdb49c47001c4ec8e1d54ddd8d6058bd74e5d6ba24f9118fea10960dca00a46f7012ec588be50f9a8c7c68eacbe2f05b5eff0d17c626764d757379ea5d477ac2312117b37b4304581b8f5bed4d2242c31a4b99561113ea97b625d2141933c6f0f23a5278d09ed06f071811d130aebdd331f2f7e8fc21da7e2b4b92922db7a69fcb8d77c5abf212e150429d009d48190b37eb8b360a1d14fbe6cc9c94a7593d8fc0c8f739bd86c6c06894f
+TAG: 5211bd514bcd6638a8edb54c0988b310d8a023a2
+
+# DIGEST: 0c2eff5f73e4ec6371200ea4e3ed600ca22116cf
+KEY: fdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e10
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce9
+AD: 7c3fdd293d72afc09f
+CT: 8507378795ae3d113afa4c9c129970347ae67382c1491971a4fae44783b3a6613f826e819998e494310b0c8fe66b6f8b71a397ae2f838880559837c0b6de1a405864b4b69e3d1c7d75e292df1a3c901fc34c446d4c33ce3b72c227aa5b3a7b6a3fd775040211fd94a5f8185fce0cf207442627970b648cf5edbb769eb9f7bbbfa5df0bf97ee89be3a5939241d9bd5175a470e6ff41a12c63c8f8dc016f54c639cddb0dd1b377241ad2fbe97cc155247d43bc8a91a60a5a4d856e0785fb74944bdd28ed0d24a11404571bc420c1f650992dfb9f47e0c4f82472392d76b91a8e20c2572cc06a1573729e1e74b1
+TAG: 43290d6a76a289c34f2a5c82aeb29505d43f19c2
+
+# DIGEST: 7e81f0c3bb2f9c2073120134be9d0b1d0521989a
+KEY: 249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e8
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d
+AD: 72afc09ffdd4f41963
+CT: 6cbadbdd1962e0a61e913c506a6c301e662657113766037c480606d596e3483e8b6afc3b0995f4a1609eddcf49302440eafd7161c2bdfbcbdc0b6e7d209e98aa2d06495ed6168aeefbc77eb69b2c54a4e7f8585ca48eef8aa416ecc40acc3c120d03760168cffd22cfb4ca56691e70e6dcadd18c401055d82c8828c6ede0c948e7a05b6bcd5348135c1ef0bc7b21c2ae65985270c6819ad6b3734ba871af242108acf1eca56e6f545bfc5b303c61995c7bb5761ef08875eac22068d1e2837ab29a7ae16cbe61eff1030124e87cf06c65624630eb32f5942f1728858a27ec52ac5015b1e54de02702ab9b536e337bda73254de276
+TAG: 499207f96bd58f954d41d4bbec7491ecec342d91
+
+# DIGEST: 28a454911a3ce17c0248d2f535f4073b6b092f6e
+KEY: 2e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffd
+AD: d4f41963249cd299b9
+CT: a24a966e15e5bfbb87d7bac8de0e7f27afbbb44b4b69e42a492556041f2b428a18cb87083b9fe23e15df7de3933561710785f192b2960ee505872efa24e19abb65838bcfecf2385f09d1f7e6e5499315768a1e080be35085613525ef484f0e6aa36ef91b92544f0419e51691ebbbaca34071e5a14fdc4c148f3219cea516b2c4afd6a2e331178cc68161482f2b04094ec83d36c0196450d925091782ce28349beb5b0c41013a265fdd3029c540c55163bec6f57ddc24ca2f368753a34955e54aa8e4a1ecd18111644c89933f8351987b28baf6cc40d003976622bb04f75f5f4dc3303898a6e8bbacdc178bb925a12e08eb2d97b7809ef9a66114e0ff
+TAG: ec0b5e14333b7fb4f8752995e720702a487ebc39
+
+# DIGEST: 179d0ff2661ea9bbc7a42df1b3368bd48c176a91
+KEY: c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a02
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f4196324
+AD: 9cd299b92e55ca24d8
+CT: 3314c0b14827911014523d510deee85d85d7de5d9741ae4dd739d9a28b2fdc05968c580ada74e19814b62fee6d0e79d868627f9a8c89b18f5f23935573809b42b6167146d0f25ff7a23a35a5af3f70678b3a4a00dfd05ddc529092a110dc6cbe1176fcd92c4dec24fd8e635b97633a5c6272db46aff9864b8aa215ad7bab2a8677a9580c27db71579d9f43e09846d9fc6fc21e6430d8ee1f5f274388a30633020d7a6af1e5aab27d8c3dbb5201bf2a5ce39a122e5935bd7c158ea9fc070d29b1201bc10f5e9459cc354de7d4695bbd5a3b3bbf6c5f8f52a45d2f8c5817759427f915ad3a8cfe3252ac5a65eb21adab60c47d37c478c39a7e312d2ef9
+TAG: 954f8961c085751c4a9df38c66b89dabfacdcc1c
+
+# DIGEST: 35f3568ac38767bbb0464106b32622a101523d0f
+KEY: c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e
+AD: 55ca24d8c078c49f78
+CT: f738159c0cf73f64f2e7e4cffac4a016275d7929d4077c1b2d92e637d4eb4f8c9c05bd4ea0f30ecd5482d142cdfeee688593c1c2eabf5520d2db8d788b6c3f79bb97c324d5517ca6ef8095e36e4459bae7bd4ad1cee0a46d08908966ad53f5a701fd372ce9e5c01a722dd0d620504780de685355c2cc8b2ca18cece0b00f371c83c05296e06302f1e5e221712a40c105e3977854d913996914a1ea173fb15cbca95db36f91e3b607f85e6ee197c757a5007cd98fc78ca5455e0f1ecbc221b9021981c176603ea3b7a93cedb820b3f0a865b96c7c48e2ae56e16a611ca99e47635efe56b251ee27fc98dfc8c1dc6d81fab1e429c655c84a118e1a071e9a09858605a145f6
+TAG: a11d586af8634baea1259f94bd7d6abf11d04136
+
+# DIGEST: 720ba4f4eaf71a85873c01a80fcbcea419d22ce5
+KEY: 025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a7
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c0
+AD: 78c49f78c7e713710a
+CT: 6d358b297ec762961ec90c8b272fd991daf819c86822251a191ed7e8bf5199596dc70e2d09d2903505eaeb1eb562ae47d6c65ffab673975ad88b45505f959c62bc2884653797a9f5e22fa709f5e2e8f26e393d1c58babd7f2d0374e164b8dc231557f4302b08b4b0c3f3d070043ed393a3c6825aeeb277f11873e0332bdf81410cde0adf4044a4b02193c8e3e45af4145d465c02c358c54190af19102730b00a45aeab88d4b756fbede6fdd4235b22dc385cf8fc382475abd8516beab06dd60e26769b622f5f6942af330547c425ccf1a69d8bad2ac539fc33f19f55edf4aab8be6d62c707f1f114fb5cd56525730750958653db884e442206c6a2f6160bc3d4c6f5663fba67fec68e897e9e
+TAG: 4789102706b7b9a012934624bec8ea108b169b83
+
+# DIGEST: e531dc2be28c8985a08dc53ed098457cca032116
+KEY: 1d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b38
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7
+AD: e713710a025cb8b9d7
+CT: b5b1097d7130a96d52036a2a10c765370af34a4190da745e09811211984b0aa194ab24933c33625d7bdb8e40c9bf5cbd887427e24851a8ba826296a41ea3456135f372a4132571596330cbca7523cd38401bf89f9560f0f504528ff5d82befd9695bd2c8a1c1669f78ac8ac5952fcb7aeed3f9d9196c7dc72eacd297c3c185bde0a86899e9c8a2fa5820e9293a665e725f8e4f7e2bbd41253ffeda0951c440f4d17c2584529be84bf2d072324151e54e1ab3a5b0a70cfa57d2932f96143fd69fcc357a915d42b60f19340ee467c63d095cfba77a11f4406d6d3dcb56131e2a9e1950135dcd34023efae1ff103122b0def2b85cbd0feb720fb93f598c50bafa23e983d11d4aab5e9961e8fbc8
+TAG: 3ea9c92de8fea6f7df016e3fae66fa9c87127e5a
+
+# DIGEST: 87828be40716e1acb0ce876660045cef3bbbda49
+KEY: e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a02
+AD: 5cb8b9d71d2989ab33
+CT: 5ee0b608631363abc207018c9e2689bc955793b0d9d372fb834c294a4c2f7f91865e7905080c994c98d1c58ef4285219048cc896c65aa5f980df10c5bacc1a13f22c925dd130018d166a0f47bcc44667ba4be67482c617843fc156983c1e2e76ba8ac70b68643a0f8102c51749a00a3344b38664eb53eaaa8b83e4c92f2c15d3c9cf399c2ec66d8ad7ddafff01a6cba81331733564dbc569cba8e9b76069f5b97dbc6dab71aa79c30635b21c0e7057b0ee9d44035486220269b6249a9c085ca3aa09085246a52a785c95067fcc3187460788d742162c75d99dee94f1222156e1ef02f6376ee0ae344ab88dcc518abe34846dd54b16ace38fca9908c977d7a797f4105656a20c4dd7cffea8f56e001786324d1434
+TAG: a52bee1e2d73762c749a945760a175aa1d175d81
+
+# DIGEST: c413683815bcbf3858fbb654590434d5b9f1eaae
+KEY: 3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d
+AD: 2989ab33e978c4451e
+CT: 1cb1ae3fd2e63eb6676beb8e595903e8d5ff1380ba16173f104225dc578a90498c7a5a6780d8492a35d253cc8f9428f4c2b278558c0467535a191fba740385e404e95d18dd0ac88789cae93a09d54f20f8e7460c4cd257707286a54154a783b651c55486a3d1b43a195f57ebc22668028015aa77eaa95cfa648ba95ae894d456536e40f9f523fbae30b77afac2d1abaf40cda26d2b5939b8cffc3b78b489a43760f6ad0a16aa33a0d70457ba2c00d73eb9e6443eefacb1661f495c1e9a929003e364b17ae06c2c1db6f9a1a61d4559e3e6232d4a06470334df16cd94aed2cb1aab2c6d6b45186b0b2f4770e4379cea1dc41c13260e603f15e9b43fc51af8f8539a08e3e0311dee44278198d5fa880f1a126687e6
+TAG: 63c53fd057ee38f2a98820ca30db3b06dac5b6f2
+
+# DIGEST: e55813b42aa337183d3c091b9f88f8e37832692a
+KEY: 2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e9
+AD: 78c4451e3be585a29a
+CT: 243bc4ecdce83a0a3968cb4c2fb1cdac8867edcd64ef8213eeff93ec9eccbb53c86578e6a024a1b2cdb0b111d0c24e3b3b8ba98dfe3331dc3558c5c130f09031f4f67a7c14fc2aeeb89e15bb5c681d8b22e12bfd287eca17661df24ec94dd802c4ae451c293a51097cd48da2550eec9aa27b48d4d0af9d20b3a185421985fd48b2d3fd50b3bbd0bc4a9ce3b04bbbb96c2593168f9d5e1bd31a66f3da8adcf6675e6f3d95c38c2739fe61f216e673cf2ca4c22bd0a4270baa7882872bffbd967d8bb1d0d2cb8942dec08acfcfcb3acb88334c3afb247313198df8d71d705b171c86c265cc64df6e1d9edef2b4ada2019097640ed223fd0ccf41972fd2f8c5071fc27e55d5dfa6e8cf44a44111886708126443be75c455916a4123731d
+TAG: 61a43e4df0da06aba22a45a3e6499a58d5a336d8
+
+# DIGEST: 013c5a98871203f5494bc2d6927d15ace1e719ea
+KEY: 1e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3b
+AD: e585a29a2af12feef7
+CT: 0082c3ae567977360d72182ecf79dc9b03c61ce425b10bc31e0e931125c53fc14c5a12f21c75c45581908c2c4f216fc8686477c3b86a8d4cfb870e0d9a5db491e9cc902709b5323f970605ee9f5b81bae1a8af76f3e4a92b025e386072296eaa6c03ca13c565dc628113a47405533854ae0c7f31ffa3e161c767bd6246825653f42f90b97751316920f1a97044cbc2ef40bae40fb7f3999a68e5975a457e7af13cbbf78800ffafb3f44192039f57eca106d654ab86dfd4ce802f8d09e293b56e5cd18cfef447ecece4c7b5b5ac86f79b1e88e523028617ee05da58a5cec297cef92288c1de6e1d4418150a7acca9fe78a54210d729253057c7152b393348695379f5495f1a5e34262814cfc2d405eafb059b45f5c7f2a5433992ef8a414ca86c483d0cc5
+TAG: 9a0a0d67185b871f26d0dd277465ce273d91b596
+
+# DIGEST: 7f9e8085dff06dec7a2250bcc60532aedf162762
+KEY: e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a4172
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2a
+AD: f12feef71e1063b0b4
+CT: f4464c006e0cf9a248c77494f127b46f859154fe1b64cc85a38e7d54df62d1dd7419c7e7338f362c3179a4fdad151a9ba2dbd2d450e4c356ec108288f250d586667b899b8bbbf788ba1471af766544bf4ce9ae17e3a045974966120eb2a99ff0ae5e9b3558ffc1977f7f950897ec69c0aca5a92ad3920c708b5a0528a32e74254dfb3f7279b66b7878f96aaef7ede01efffcf55f79e36f63269436916d0fedf969294889e0483bb232132663dbadc8d5d91ff4bdb91fac40cb2e129402dfeccdfbfcdb5e985e83617bb869e81e61ab62ed0ad5821b5be32dd0af0eb7971cd7bf235ff5349ffb62dd18c11914e951cace6e0597d4862386a960d8d69faa9497870d51fbdea193d91fc0ea679a803d5e8111798896fea7b305b8e8fe3f69c986ffd4e8d888
+TAG: 43f754a619b5e741b663d54fd98ec05db397b339
+
+# DIGEST: 0254594a43b8c9b638cb456593750b3f8f9ada22
+KEY: 04bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e
+AD: 1063b0b4e6e8992003
+CT: 72b7c3199ffab4ac855778ba85b369bde732698528495800481af15b455c07c38ab9be576850c5aaaa80c5869714a06e45d4ffeec24abf56e73ed87c76080b0fbb6a12df21ce3a592eb8271392ac52a72d4f023af3960dcf3319c05694f93666637208c292e08a9faf63cfc5d516e404efbe48463e104b3535045859a8f46215b244533702b1290d98010c24a9b2879f221b5c2cc3ea0327197a37378fa1a1d868f6cea0cf2d71ff9ae0c62ca119761813e4cf834047c8690883490c3171e1ee49278decc5dbe6f8614fd2a6c908aa1387b7459c199f1f5a7b23e29490d56ca982d0c5f8100a893db4bc18de5ae9efcb6a28f21fef30b15150fe39b2c3e9e4800233f6aa950a8261f5cffdc380861502ba418532703df8d1a45fdba5cccf0a78adbef63b8ff45e0e5bc9f57a
+TAG: dfc67f784776b3e8619acfd3aacd31ec543e057c
+
+# DIGEST: 15059d32a3357610e64a48c19dec95d256455404
+KEY: 2a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6
+AD: e899200304bd350813
+CT: bfa1572da96f220292971d4db1d2da04d8d06af3cf424f3bd362822c00cf403f276a390d1aede75240d5c71ab97123351133f23fedf608651bf109d0cae3746cd6cfad0c7b3b0d97bd49e739a9a347f1c5e317c6d6b0f8f6d72eb725454693e4b720e05bcf27bad1c55e579c5f2b0f69c73728ce193cceda471150c94f8bf590f490303dbe50835dd4a491e9e62dc0dbc9e105450e40341a29a7ba2721792975fbee90db9ead07872f66c3d1508e8780efad680d5d9478752b3bd6cbd9317b0d77e83f04a5bf7bdedcb68ad02a29f2e471d4a5f80caa9709669745de77a890c556c6591daf429abd457b20c0422bc5847c551d7eceeebae04893654e21840e197ad9ca30170ae5a996b6e7627051afea55f61982a48459abe0b6db2a2738e0056a555bcb30fd6d47e31527c92e01d60eee3e1725
+TAG: 3552925f6f504fa9b4ecedd02274a5f854d39b57
+
+# DIGEST: df289e1d102b25ad07e98f430cdd24eef513f8d4
+KEY: c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a0
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304
+AD: bd3508132a027d1ff4
+CT: be652946fdcec9999bd86f46657f8085df52e650aed368f5eb5175f65519b6aad645e81a4acce3e0beb1fd310aff96aca84fccee0dd087e44135074f53883d34314205925ede081568ec0b2b670918857b27153e789ec45e612faeb31fc3ac9cde15bd1374659f76043ebbed999827ea9ca6a90ef654558fa6dfc15eec62d9163e33b62a2dd0aa7479235edd67e23a449e676e120a9b41ae8b28e93dc0dd9c6683a01773dfdc3760227ce2951b6159b7eb16a1143bd6c890966f2d37b726e35ed0dfb7f67872e1bb7929f781a71591615eca65bb22e9d3fa83d9de5ef0b122db03cdddd98d3ca1d0559c0a462fa06448a45cdbe9fa5030f931de153d1a9e635a7e513d40c0990ff650a2fae326fc07a3b31e02447725e44b86ee299cac88681ea571d74363cf049f1116f42bcd8f0914d72ecb47
+TAG: 4f6cf7daee58ae08dcfb8c6450b5e893e4fa3790
+
+# DIGEST: 3faf5b20ff66fd6583a2b62901c1ccd798c0e9eb
+KEY: 57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab6997
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a
+AD: 027d1ff4c047b3ef4f
+CT: b9ff84b48c521b729b3dd1394f27d0ddf738f56cbf720ab03d2f0875bc9a0530480f4e170b9ed73aa789748a6152d0d228b816e432720a40dbed8bfce957a3d671feaebab8e6a9831bdc602d0942bbb08bd9ff1f69fc2b561c4684375e8f804af86769a23c4456d7890ca0ba9752d948296dec4708ae87ccbcfeea0746dfcc37d68c82db8951bcc4e37a8145a87b57576afda822c8bdea68f69440e97119bd7b55d700f8d377c572cea6c94954158f83bb04caeffb98ca1d52b075a8d5e07a6ae5f6e84cf9f6589c3a0880c23ca9850950e688adf8372c973cf5e98e6ef5790e9ab7d75ca45bc9237e3058eb9bf35ce29487e87a722aeb0ebce675d5252ed8aab3c7f7cca0ff2376d54153e44dfcc81d63a7ac938d10c901c1b576782f888b12cb079debf677ca4ab61fcbb49004eecf97464d9a1cdb404edf761330
+TAG: 630ac90ec5de49b642d23b829c855cf3d5832156
+
+# DIGEST: 2a1f12db7c66ef374e510b2fee81431a4902fd8d
+KEY: 4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c0
+AD: 47b3ef4f57a74706de
+CT: 636bbf7e5001376e9e86c75671299369b40c2136e995d537c22dcf9d1ae384837f7ca1ff59da32b25aa6a25025669aa1de1aba1fab22ebbc2937f4d36f2e5adc0e91ff8111f2ad012dcae75b22b28ae554d25ff0327b6fb4b7b974834c5d5a354d8c5b33fb535e2be18081328f5d769c14ae82baee972ed4fc7e042bca4a1ab3c9ac423276f64a29d1e4b369b61bcbad64bce5107ba2cc207e6136ff4ef613d21638b80343a673979653381427989a484d6bfc0bac7fc178e423663d4b0ff9ffec818f59592d59bdebc0b34124a4402c014a84703cd4b273d384994790b2e584d952822a8b0aa8c05c7094b2fceb3463294edd70cd1ab20ecdacbe30c56af493753ef431d0d76d9adfde01c108dd329c397f8a92797b438a6924ba30300f7136659d19c5d4be248a7128bdd7156adb7376ad2bc60a0f6ac584abec4f
+TAG: 87689533563c8992a50d934e6cf5cd8e34796b01
+
+# DIGEST: 524f8d38ff527d6ba89c51265f6a55211a443a04
+KEY: f164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57
+AD: a74706de4b381c692e
+CT: a09408a321d5bb788f14ea077b9e8ef3136d6469fe9afa8f0f268149b64f4866c99131fc2d802141d01a481ae7d16685e71b85b7f45d39cf789514f2ffe46950ca49b1ac141a4d944668a646ea95ee03347af00aa0f5e8f130e8cf37d4d307c5a5c302d513f676c3fe3b4d2d90069232931b510230ad4debef036fd791b9867aa52ded3b6c42ecca747608526d448f3c63990181f9c982d755cf82a1f539d54f594baf52d4105f4892b207102815d48ce439b605d5ea53638ecd85be3078f36ca7e14db7435b70f81718c4a83dba356a23ac71667bc8e73dad35560849d164526f6c7792c61a349e15473007372a50fe2c3119075467f3c0e4978ccfbe9244f195020cdc3f3c76ae9387cc5483d0dceab475db90dcdf4b306d29af66c3ab64a6a1097488f1b1b2eeb26ff6084b091d2af0bc09dd598bde25aad9d91bcd8f1a0265773a05
+TAG: 519ef430cc0a0e6fbc05df92dde22b709df66736
+
+# DIGEST: b50c58268b989fac3ad8f6d25a401211ddc5cef4
+KEY: b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870d
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b
+AD: 381c692ef164101b89
+CT: 235986207bfb514729ae4cc42abd4947b4a5d16f9d6d48e6966a319f460e6f6df154989622aea2d8adfe16e9c59e17c3dd4b34440a5fe799303a496b23a998695e67ea0d68668a5a2d536c37bc2b3454de37aed00f9e6ab14ba6cb76b493441f21afd95cbb7121570e60cb98ce04cffe2ddec4e52188f0f64802c36fd0472c323978609dae080948cd1b22fa5befdbd4bdf49575e08e15e72a6bda1e0858939ff867ef82356f71ca56c8277323a2b5043263a6de48ed1cf176721672678eca4c6ed1026ecbecfb04bb087202eed21e1a194b64ed24a18ade61330fa1fe62c18f2f46aef6d930a62249b8598e541b3a0f22008252e45b70d9d675d8e2c784fa52194012223340276297b810fadcff80aeff2768f86a11ecefda0844c3e7c1524be2a3644cc3a9213956081a1d84e8fd61f517d89c60db955363bfe82c5a97560b1760a1d9807e081c6b6ce1e5
+TAG: 382494d9f0da029fc894bc75b27a625bc89b9e06
+
+# DIGEST: 7337152aba55f41574aac9d678dedcf895a1fd7c
+KEY: f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bd
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef1
+AD: 64101b89b476f72b27
+CT: 08bc1958297f8830991245cd79aea8bbb7e6c3b7cb498a357c1fa07648933a38fa34c95131c328cd218cd6f90a90ee505b47b9a6062a321f99052d691addaebdd2ecc3d607b80aa1201b1c0f66fde9a452b73c469317367cdd52c9b99ecf3d7b6e920eb47766610dc69604f8713028ff0a70ff772d1142e98b77f6bc0aa7ecbf2cadd0094520d7a3696a5c57fc2275f144dcbbb98b54b618acb1a921db1a5763aea1e9c79b7fe60283be06ff8d6690cb3bb3dcd786c75b97c3d06bc06bbab31b3aebc1fd682b4e046520096ed4570a3b70b8ce9c5e777513f7e8bc553ab0e7a7773f32b5b3ff365d848565f2418666c34517212bce58252f485ba6883a14e2d14470c617a53184aac89e93aa13e6b3d78f4097c655e46c6f203f34c9e27e02b2e1ed16b1e7f8fe900a980299a4509d534b104d22ee4170fe0ce2e5db4ee7fa27faf2f0da8abaed585d619776
+TAG: 493bf5c6933c6af0dbf90b877f7e87569acaacf5
+
+# DIGEST: 6578de87f977f4cd4c5d6dd6f6f99daa338ceef4
+KEY: 67cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb105
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b4
+AD: 76f72b27f06f520c92
+CT: 374ba8b0ba565d2409eec5ab30cd2c679903b8403dfd1d9d8b1af9add406025fea1eb954312115345a6163f22ac70902b64ab3341d7922d72b40064cfae3931ad3b9abf69fe5c61c3eb5dc61110e30d0e72df60d1c03c46d1ed4f71d8719cd5704014c1f5630bd6701508aee600aefc3e84a324bcb7064ecf44856bfb2a4aa0bec92b791bf57aecf2ef2e7ad38ea74e7b5141d5141ec70925b93f9bde405eaca242ac7f1ce2089eb411d33fc20be18637e9bb3e2afcb5623a12535b7cb1eeb68def867128bf2b7aa3401bd7e1e101e7bedd9caf25a118e054de7564fffbfb23914c19fc3e57ba9515acb79120a730a1b104e062ee05bc611f7ac25add7c93c636e33f63d8fbb9337e04c1655dda60b0ba2664d72774bbe088abb64cda73b0ab246877b44f2b8c19f19d57cc7b8a474c5269bbfc46616549adb330568d49d7d229c465801ac0dfa9879e35dab9edf3bd1a94aa664
+TAG: d29a84c29e0e3cfff64cb471c6db07bbc5b5d0e0
+
+# DIGEST: 38dda49f961e8d18556e2f4cc30812a7e17d827a
+KEY: 41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a1
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f0
+AD: 6f520c9267cf71408a
+CT: b5308ab1dbab773b72c3d7aefadbf5910d53aca7a5b269590d3c27d319ca593742c46ee810ad8594bfdbffc6db2e2dd2193620b9bb9b3beaac52925bd9800425154ffbd57cc72fd4c45f00e2e927e8bda6ca7bfccdcf5e27fe7aeec60566a86fe3bb70a44e5a0e18d9e18abac92ade6d8e8c4210d5ddff7d63531b75b94c99564aeb176133ecb9d644a94d8e7dccc94834507e4b5140e614837bba3419ee89457b422382bae67751660b364373e5d9d2a506868cec3e8057bc247c1f89743bd9341ea711ba40ade6e0bfe5559967ccd1f4f978678a7495de82ae99b6916174633bbb63009fd807bfde74f71b2ede385101c7becbd601e36e1d8d687ffa508464e8c24a0b120f44950db1b977ce361400498320461716a2fa603afa567ff1168a57b69d7b62b2f5c2e71f1282553f0090f91dccaecd9ffcf92fda7cbdc2ac3caee6f7ad0db6afde81b960fa94d15695aa1ec0696fb161b7baf7deb502
+TAG: ffec2e8693380d6f3600f894b0b40ccac0d011d0
+
+# DIGEST: 9a4462e5c302d0657a599d31a78f3581e4b1684b
+KEY: 877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095d
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267
+AD: cf71408a41729bacb5
+CT: 7cfe483947fa6ddac1a38de10982a0c355e4de8fc734432b923e50475323f4085af3528575b2dc3672b57c6a1dfd0242e8a95e67c5d23f4fbe296b50fd13e9b13acdea7e87c53c055bb5332c9b5c49166841ea4ccdf922b808d471646b517e19385cde50fd38dc940d28a9e214a8a861d12a43bfea01e52cf0d092f7fa41796ce08435f7d86df75f82485945cff688083d16c4b814540bb74445cad44bfeb4cc0e07101155555d21942aa7ded8fa9fd217643706c15c064bed82219be62ed9b67db528f69e7404444a7a2c168beccbdbafe4e5f60fe2071ae50ab653524230cedaeb53bdba836f65a62f330ff3cec4d9a545d39ef731fca880d0000ec19d08228597b8eb27ddd5ee390fb03fc6768f7ad86fb2f53337f5ca94f19238c62cb6cec098dc7d5471e3d045e6bf3df535321c532f4d47169c6c5ff3942e88ac78d36b222c821d2444b8eaa7a296d624e141770e9de7adba010823a7babcb1
+TAG: 4fa4936478f17e1ae7a94474967e1421e1187315
+
+# DIGEST: c96066fba6ca75beaddcbf7b6bf1b43b2a7b6353
+KEY: fa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41
+AD: 729bacb5877e72cdfc
+CT: f3b53a2bdeb743753d727e5868f58f24435bf5d9a4268aa8c1a05b81f64ffe695ad11225885eb4147290932b7f64bd9feb08ac20f33aa33de06e6a362de8d255ff97b1ace17f96caac614a12f03929b7a6ef30faca7340f91391cbea911084fafa90844146817b5d57d98d231270ba9c4a26dd3db0023269f7d592eae74ac75fbf15c2602f938596f84b4cd685fd336b1d3e89f2a0bf9ff118af03cb625bd8848c8e02d9e0abf671c3c9a2d4b794d4b8c75b21561ef1ea388bbcac1543e3028e78aaf9f9dcef04bb05beace5a5a74dcad40ca9ef58ace62ed4a4690c0ac38ec5f283a7cdc713c93353a9195a300cdf5abc98e316186c0abb5ecc0475f3c136adef8a6aafca015efbb6e8f661d9282345b94c37d8bea811a908ac78dce8a4642372257829ff715e337f8c3e147babe590205f5c9c8d075e5e51de7d4a99f895ca1d768f9cecaf9e7cb468f4f143d20c3f5816b777230b05d90c34b1c2aba4f7e70bbb24a3
+TAG: 57255cb85634135fc5da614fd4dcb1553d59ef4e
+
+# DIGEST: 0cd3dccc73f4bbfcc3c62b4638bcca5a633a2b37
+KEY: 07a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d50
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb587
+AD: 7e72cdfcfa76aed067
+CT: b992198f130a502723f02c5b3dc8b5cf5f7c71f4056d4a44700e5d497c39b51dc9b8b552b3685084b46060078c7355c1900a136056374db001fbf8cbf37f24273aa3b9e45a26bb9622b8b455e82fbd84b6e3da451603c7948ba48b138520d48bbcee408b33a0e5a8b2c38554cb095221bc3fa2b74b956db02a68dd5c6e493c928b4f15895ed6a0c5ed4b9968ac320559a9b7d7c76a37125f37c6dbc3878fbaa82cc26ad255d62c06dc264f8ce151446e29f3e8c4d5a7f85387dcd84e4d06b48aeccac58f951366947c8f3a1791c8f7fdec5e82924574c44ee1ff75f54e9a4bde480ec81fbd205de1fa5d5432e66a350a8c086bcaebe5516b5b2460d8c3321cb0e1254bb0aca6303ab1114a1b97de44e890e3d4cb7aec2745f5b9826844949d925ccb30475f9fa6e0fd84506108879d586a410f02260bca9f472f3f8642cb53923d4b321195f09815a514099b53e40f68591ac6518732620eea108eebbbd6eea943209af2
+TAG: e36f04934697cef2750dbe4075d1bd42b6a09490
+
+# DIGEST: 61f7a437ed58c4d0c66997aeed34757d4f36926f
+KEY: 699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa
+AD: 76aed06707a07c3dab
+CT: a61c69a5adc8d790c82a9f9767983df075f8b9f762dcbf9a009508378127f3f60a7f1cf84889ffd9c0c4c797d50dcc0f840a97aa2da9e2a682453a90750eff9f06b38c2bf4dc97827fba6ee494578ea7345dd306e5109b5d3274662d219d0158617089cf557c18c6f1581519c7401b0fe6f469c5536767baef2ef7892f05b21d3456934336efef306b54163f53f4b64fb8ea378cf5167143e7fcae4a9341ef0865fe20ea6cb9f7c8d22f434a7f9d4d34237edd8591c3f3aaf7377a0334216aa085a2d97e769ce404f04503a92b40b15ec2b44ace69783061d5e63c56a63a563ba8df8e2bf3163ee0aa34237b6a5eb3d2fca88abda82b5d6fe6e188732333183ff1dad6b34e9a5f7350e9023d138019c38d31640cb47ac1e90101ac0ae3954cd5194cee5ff0f702629526f6620b5ea754cbec01e6e126eba2855c12c5c92f782ea0243da8a6f311ebee99eeaf9001c59a7dcb1b3d26b94fb0ab22b74bcd79ac88b569dbf49257f49e3c2f0b45
+TAG: 58b508dd7d2941ae7f6aac753711df9673ea6e36
+
+# DIGEST: 9b062a7f63d081bc4fbb8cf13db57ffdb7d113bc
+KEY: 2eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707
+AD: a07c3dab699719fe88
+CT: 3cda4ce1026369ccc236631484c3a330eae6beab6e2117c8ab851a1e73800c1d0192af73e8cc19a61c6fd4716e07708d1a69d884a9c5b35b3a2834c82c3d687658ac59b15024415319a009ea285e0fc6ed65d87618d8249031ddce20b154cab11adf802398ddfa24e02c4807ff146cd77ee8c463931022b27c174a6f9d5e51d77b86ed991ab12f4af29e6b55aafd22a08c1db081f7538a35f14a166686d99abc3fe805e1520a67989494d9e214405cabb90e9e2e8ffaf1d3787017e4abb3b229904bc1ecfe9a102ec9ea1588bec36236806759bb088fadd74e16fb82f164801f272d6f77a32236657d0bbe4924ed0430fc81419e81172c29ee702ab40b83c24ab5593cd582df0a061a0b359878ba9a32011d471dc068430d66e8e61c0b3d6c7a07e48996e0d2ba08f9ca6606d140925e89e2b4b6073817d075ea89f940d7ace55d41d2570d399a2a812c8b5fbc526bdd66a7a325616f7bb572a29da88ddbe53ca4b338dc2c4a2fee777a72331bfa055edbca5127
+TAG: ad2d9d5fbf7162f1be5d9bd1bc0a8b5007fc6abf
+
+# DIGEST: ee4812a7dc3e037844fd9c35770734168c4ce2ce
+KEY: ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab69
+AD: 9719fe882eee2fee55
+CT: c58ee8259ec0e52f2af6f61b94240a0b7439ad87d2dcdd10c19236657d0018040f1e6267d5ed4780395bd76926bc77afc9c0c4cc0d4da0b93f5094a31c57dc27d81012e9bd1017d61b9d008138bd6e698ed473daf89bf47d62b91cf0060585375f6f2ba41ef614af99735136e2b6f86e54ca519c5b84db3bf9da5c7f3c2235952610a4b39e0dd812aded5dbbb0d0cf4b22670ca71f7908308ec94c392c66e24bef7eacabca88d7710c9ab6a5db128ef092f261fb6fb8182c1ecc176ac8dff76215913bb21dfc686ad7afff75274e5287bcab353cb4423fec64fbeb6ba30641e5dc83148164299e5e8c9ce0021862927a932ef04a9e7fac444a7cb67a230f85285a3f09f598abe9daf5a03bc6c357893fd8e0c8d6ae99896547014562017b17bf9888372b207b678287a70e859bd3ecc330b099fc69bb8f66287612e3ceae3c6578dc58bf14195aec1db18fabf1b21a75f2c2f03c40ce04b577784887054f8cb73ee9da8253864610c61f64446329e71d16bf261f
+TAG: 216694aff1265b773948a2f0faf7902323b6a8ad
+
+# DIGEST: 4209b9f203b29926176f7d54ae89ce7e903009cf
+KEY: 870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882e
+AD: ee2fee55ed8b11534c
+CT: c0bab3d8fe209c8c99bf5a38157b072fcddb2cd57cd49c5efd6c78755314e39f64cd0df5420fecba167c4a5bdca4c86221a067fb1dfc0b34b3c3b03feb0b4dbdc2df114f9e6b1e3cde5e7d7e549702f54b9df62103ffd8888bc2269e74ec33dc640aa685edd118c11bfc531dc179fdc46ee646c6f4983efca4a8a2b5a0e7932186671c24e66a5551620da232537134c94871b5211e4f3e1ae9f782648ac957f6b04042d266cbd04ae439f63816d8e5c72b34c4162422c527e8d531e22bacf36e00ca9f0a61770834fc62a9b5e4394d5625df991f3967c3cb3eea99e0f6ba68b916e95ae874bf32f5149113c9b281e6127b993885eded80076120818c73a98f48c7cd021e786a9df574aa6d5be508bf4f6daf65f2c8a2ad328cf32bb54e27a46dbbbb1004bf0ad28232358db4b47c8bc1d3e21916a5a2b2f72fa4aaafcee80a72078bf716f51c5251c7396e3c125838b86511cecff53a03a3fb427ceb5b010b36637929cf67054e00deb76ebeea22068535d2a6a0c730a7569eefa475
+TAG: 0137ca83e772e1bba4e3af347f36ab0c096d427b
+
+# DIGEST: ef5c6927cf43e0994fe5d8e87aeee052b6828289
+KEY: 14bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee585777
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed
+AD: 8b11534c870dc695b8
+CT: 79133fb4985b7734dbac71c64333b5ad2e69d065a3badaad9cedeffe07920d760f5604a396912a0a1a6d7e8a509d0c42cd212a049a5c448a34bc5aa294f7e3a0e0bb56e846e75a2db0c187c861d3a8ad17dd2404d343928bbd6d827f8cdad3767f70838a7d1e76d44df50a2b0a7f134f4819342815b02ba58e4a4594c431c79108e61d29154c35dba566d2de54a603be4b364a645ee4a1449615ede291abf33f880f25665609cfe320ae5014fc79846e7e7c443bc2f191fb5361ddb9cb67d46b03a9fdac83de8813a5752d28836c406eabbc88526101d17fb2b5f855693873be0063c5c7dee428af7b5485404e935f3d00f05f93398f3c8b7355871ca53546d4dfee58074ffe88850dc853e5a419544bbafe4c4cb7bcca3c64f64ff8a4c7310194a466db56e0103e1220deffa94a1066e12efebe95e9d714dd67326c7fdf13c037729a01a6f9592f80df903d491d1f74eea0d3d2d37f1fd62f48e3d66e1387f19dd483b3becc9eb59d28c7d94a7299b49be610aedcc0148d2b249d204f30fdf4c4db7ab5
+TAG: 28732fbbd5f620762d1e9ff909a0db0edfed2942
+
+# DIGEST: f239c330cddd57a5e88e777c848cd66e508bbac0
+KEY: b1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b5
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c87
+AD: 0dc695b814bdf1a87b
+CT: 1c3df688201b358f1575d78926242bbb1aa04c8493e4c2384c23278b235c613fae4a42a23790d370da77b45e968363f7b22112544fecec9cb95c26e3fce51a8ec38366be2efc3ff32232655a6b3dbc823e1a7c09bc1db2ecd0ff97662043254abf466451a0a888ae598aa119406051eb7303d0131956e14083607a54c6e3f76a1e8f7681372c05f0643959d54a3f90985ddca5329e83d8412096b33343382ce2b8913b2d6977e770ca6b3113af39f0fd10ce9a48c39681f79dc0904959ab1d18631195630981d6a34cf641f08dc0b17f614442c31574e2141596efc9a75a5c7ed2931b5b5af5fe5e1f15a2ca413a591feb1b9ba6e2b5c2bb3476ca664944b8723fcdfe24dc4dafa4504927c4ceeba3001df138b644fb544f46d8188d14e34e46fe76a27811bb0df1ec343ea31e89bac8741f817b48c286509f224e730b00eb534d71ffa6f126cdab4ee535fb0f09d22bc9bea407b1ca51fb4da6f510d311b99bc124cbfb78b158092493d51c1f2bf13d732623a498e6c9d2d49d64a4955ff2e502d79657
+TAG: c431e2f3e5f4e4b87ecf51fd7d2112a1575b187b
+
+# DIGEST: 7384b8e3650297f0e51d9a8f76de34eaa4bc9fcd
+KEY: a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814
+AD: bdf1a87bb1052c6755
+CT: d70a4956fd8baadad811a1b94b27da0a2dbfb88def2f26a2b908460241485e9da431c37eb8a75a3151de74e7ab684026c1a9684b2119d9315261abdce630f1ff5f6e61a5577fc606fa0f5db177e4701d81b615ad6cdcfb9f6df9eed85a42f583744b8ed645f4726a9bb6182ba2695dc1118a8a454255caa6fa8f098f3dfc21a925f2787f5dbbc53a3802271926b6ea734b41b8887a28b60ac24bade50995744fbb149ce0f49cc99a0f9d853b77bc820d9693833bb7b2632945822b0222f1d79e08aa3375f14c2f17ae66b0062b59bae357a58061ff2a3f7ace35503d7e59e627e2a18f6c5046e1a06259a52753ca23141a2bb191af7bcec4b735a63b911eb82cea9eb7e904e2157f1cf0c603a764f6db853cb2b15a548042749ddac410bd95839c43effee3b7bb954a46100e16175193ddb84ce065de0e66cf10ddf923a50e71311d6bc9d22c1264166a8eaf3fd41ccaceef444ddd384985fd3236060dbf79d60c57f0e268b8f1ae6eb54624164c34cd129da78cd6af50a8833f172a87409d4a10473b93e112c5fc9e938623
+TAG: 348be9bd8c6169837a34984244276f59c8d57950
+
+# DIGEST: dab0914dde7a8845203fb78f9b0af41ce550adf8
+KEY: 095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1
+AD: 052c6755a7a116bfc9
+CT: b9cf4130b44e5dbceb363772edd47c563f124fa7b8cf25858f3de1587da1548e4f07e3e50c5019c0db8c599f02e1cac5a39c8b2376aa507de0a440f6f51f5898d963a273500660d90e011e2136a91f7c0f89005cfa8aab371aac5aa9b449f0b958aee68b0af202b252fca4cccedf5c2aea3d963324103a3cf2707d438e42cfa65aaf209bf9d7c15c0809b6c6c9ec08f30eef30a2093319c33caff1921c91cd88b3868a3369b4f1416cc78e5b54eadc96878536b4e6fa0dac43c02e0dbdd0db07840cf36e9d630c2803c86dd464e8ea0f1a18395d6eceffdc2191c64e25cc1a1e7d3dd0dc7a06589215abac5b00385f30cd3e74fa21e9ee9ce48c867fbbf37e880f20b8329fe2712785f92d19c66e3cb344c4326562bff91f2b5105f12924bc0ae4386f2648f30234bdf242611343360115d071ac1b568e8d368c2bd0b125f3ab28e432c601fe1e64281185929310d315072f53f16311644c35ebe8f6b2d0bce13d249b532fe60a716acc87cff2b144584d3725569730c1f51875a29b2c0b25aec3751e536d32a2376538c62a
+TAG: fded702501b0750a49d5224ec3cff6d194ca3879
+
+# DIGEST: b139e0011fe2e768284091a4f838f86fea1e4a7a
+KEY: d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf78
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7
+AD: a116bfc9095da49db3
+CT: 8f652f044f5027cef5558a29f1efc954259e64dc61aaf414c9266f6dc26c6c91fa215fc2e118a5645f0232873e2eefba7785b6703bcd179d194d7e8bb0a8b882efaab0c7e6b5b7738bbddf560ea066655ad054ac13d7845f2d7d9bb8a3a9a0a496d07fd1500c4868cf6f24fdc046e5552b66e1fcc0500581016ae93046a279f6c515223e9acdbcaca910d133857d3056f44d02906debf5a5995dfb37bdbb44698b9ec42cbfb501ba50e8413584b35b28ec73dbc24e7baa66cd7e17132b78613a162c728f41ae77be3c215b93d389e761a7b696221383aad22cb7bc09683446f1a2063d112b1eeaeb95abd95756f2c9eccab74c74f292e02efecf09b9415dd509451ce8578cc240a8d4e7ca947806c1f81d14b45094e7f85875008a95809b4e630c74df104853829024101cbb65840a5372a7f8c09887fc8520af064803da79c013f20e7872a188aacab2fbf26143dc587e047b520b3744ece1051aaece1c5ba17846eb2cdcb9d4678d1ac45487da89b26e85dfb373cb9eb47cdf4f5be045aeefd7663318a34489fde6a13405ce6548bb21c2b837
+TAG: 8211669a61ac9f4fef81ea6001c975d03fa85713
+
+# DIGEST: b338ffac4bbf3a2e41fd1b3b6d9d224d4263b547
+KEY: 5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc909
+AD: 5da49db3d71f4b975c
+CT: 1b937f25477580dd855280f6434cfd4a1475dde36ca8fbd6af37d5bf1d39b55dbaa3b65e8ccdead85cd478eb61cc375b508d83c498d4ca5d561d371284400939758685d1940b53202ae6285210e52f946e1baf0983236b970367b70030bd9f29299b43a500d1900cfe3abc127cda8343e5afb36ca607c7f6a7d16ef63a5b3a90aa849d2e3f63ee64ac82fe4e975904b37c9d27b19eaa8ffd17a4069c283566a490ef1aa99877a410a2820091f327caa46c82b1745f313d70ea194b85fb29ee7305940821b11d47cc1603dfd7aafd62d33ec8477c0a72cd48fc458d481e77f052806c2c875b6bba0d4e70a18e708c443f173d44764a1deed251b15b4f2ced3527d814910e41dee7089dad1310e7e774de21fedd9083dc5ff6c90d00494263b60f9d84a47682ba35ba2d33c34bd7357fc8df02b966916d8b1d8f683b5b3afd4399d7083e37e923dba5a0abd893b0571ca2d1f363ad6f5c49db51d66b59dac95b54f8fa946b0b27fefba7b00fcdc31dd9bc6925be4d08916a4030ae98f05bd130d164e9025e319ed6a69c7b61908e91649ffea14c1cbff390b187ba6c1e
+TAG: a81b0282a09ba18c11dc3a2534c76d75bbcc2e3a
+
+# DIGEST: c9dc1fbf134470bd3ac0d9855918516e5b8d8778
+KEY: 22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6d
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d7
+AD: 1f4b975c5d503f478b
+CT: d1a6cf55ef88054ed00d7a39fe04546601efb0e63d14aed811fc2bc6b60f9af84c84d65c17ceabd70d2fd3a185d1eb34e87be13face12949a7665254e599dc92534624dcf8aee009f41f2f6788adb929c6c410bdb25a69be633b9435d74d88026aa421377bdc367f46a9101d18d13a617893dd2f4910e538820208c074041744414685b1ec1252be32df9259fd71d7e16067425bea4e371d24644a4491e7c976df48dd1baaafd7215d285f622a9a5b0fef0bb54cdef19b085b09b1f7ee6bad2ec745b98fda92a72447a08f345920b92b85cb9c8783804e86f4cf3bdd7d8d0374838e4670fb58ed22787aaaae846fadb74862d556f65d0ef4e2488a249e7c01333c03b8f37412f1af1481e67b1051cf18ab98ab412727a68407c0babe308ab782a690230bd6f3d26087dbc6c8d92883be22959c18974fdd04d21abb205dadd669218e14b14c12b44bf399625c8c3e71038bee6b889506ea0204e68578fbaa2c2c04deefe296ddf42d403106c0a43c87345268bbcbdae39529850e9cf0b3cb56a01c46241f4c460af8c4a3d95937d46419375ec438af07cf81cae4d7b6
+TAG: a1b5e31456676f283538bbe2a22c9604bba67cdf
+
+# DIGEST: a551ad393bcdeb8c1bb1a4a70e367b069ec549c7
+KEY: e6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d
+AD: 503f478b22dc8253be
+CT: 37ac83517e61aeacd22a330f014d5e67554623f4f00aec72dc67ef9258f92fce2beddac3032e1d9f9cacb0d3d127894c7c8f60ab7a0b8be0fadba5765f2c61a74e89e7753e8c15d5e7f961907d78961d01b2942e5874aa0d760cc2e2a96b3362438116ae4b989a51d3cb6bbe24c10c2fdc1285cc68aa52bad29289420fd4bf8e33488272a9f37baf48c1545931cddd491d5db4b73e9eab72b6d6c9c8510782b89e4cc7b310173abc9b39ea4391890416a24a1d8b66b69707d0312315b1c028a026d507e94e3bd38d7808dda9b2d62624865b64c5c5c85484ebb0ffe434718e3a959761dc98fc5c66de380f05e51e6482ebb0682ef52f7439dc7c92f824e7fd18228c9a425eec702bbda519754e65ead7fda4ae74f9acc5fcf2e469b34c0d5b9cc318b3ed421129dc2e3565be1b2359da1950dae2f093c993eb1a8e52ba2594e5d3a2864f90cffc75f773ca7e36c8d9270d756b33d6c9a91652987f0b380a3ce1fe84336ee6d205fb990ae3e787601cd66df9c89683af5c4d4901689a08f16886c339fd824def4a6a8d4b62f62bbaf5275d02f66093d57a9b5c8d873b8a95bce2335611af
+TAG: 513caf30a93e98f7c2b3a88ffa6d59434827e54b
+
+# DIGEST: 45b1d26c62717ec46530a565c9e11c18206bab29
+KEY: 307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22
+AD: dc8253bee6fd1b174c
+CT: 4647f634034fffbc324a1398cf93e91c50a201477178a2f8a4b36151efda92a4927db04a6e0f988f6d45ed3b3f6ea30b4cdf3fe79aaa4b7bbe49e7f95c15baf766d4817b1d48ac2677b2fac1b769a6bfc612a61c427d7509e663be00f2dd0849f1766b963be59bd3022fc1d68976ed372d2f81da626d5970cb7427442d7d94c447dd6e65da2d670e5ebf9daf13af886622c9920bdb7a6b0f6cbc8ef71c237d727d3105d813ee7449671c50f5094f794b521b5ca2538f2ae915bd08a56a6b03d2d0b3e82c6c7b4bd692eac3f83777feb1891e470f1a7b00e07083c3c40638a8709ec0989f28b5cdc719d5ac28983f2d6f8395ab41eac4a7b6c6f17d43c9f83eee6ddcddf13af3fbebb7b53e2717a441849fc2aabc4144d07667a7f6a81412064df823654ff9ca771435551c38a2e73f9b1a092b710484b4f6fa549aa119d65dac90fb30e0f87a1ead1f069b80419809e1758a791826f1b27a64c09a4403bc235dc3e4b74111fd692bfb0cd866e56dc5fa2c361fb3b01157d5ce9ce4bc0a5c8201a69b458b8b5b963ff115933334f51c38ffeba8aac4a782aeaa8f4f0be9c739cb1622f37f5ace749af984b530
+TAG: 3602b73ab2005b886cae6d8d0efac96702e064c2
+
+# DIGEST: aa7cb8f1b995ca51405931f1d021ef30a5b0eb3d
+KEY: abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41d
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6
+AD: fd1b174c307f01be95
+CT: 0404983a958a093e52cb897cf82e2e570a2554e3aaf111fd5b126e2ecf4b27bd58f6c76f2e4a80bcd4d25044a1f5e011bc2e63f34d41714ca321335760fe45e2d3c454eee81bec506062bbe5f41684e1baf9e442647f13bdcf2f0b3b89f76495b32232542ce32e563a2acc6267cf7c08af52cdcbaf340460386de8df583e370379809ce754c95eaba1e06db323303dd159a1895641701bf5f93a761b43ffd80d81c72cc58007a8a4e2ed4a6b308c99258e7898bf7af3dba4f1b570f6d0ede6e20cc49e42ee048d80d6c826de7e128b5ebe1729d839d63d108892184b21dced7d048312bea646ca21f1eb769b5b1bb6a80792b76ba6fd26c7dcbb5c23b8ea56cb838a178e14b78f6d51289d8b9483aba410575b0878d3ed066d0a16cef8d40eb656c4e68135672053c32100864ffea4652d6ac10d5a98187101cd8b673aabdf5df60c610918a008437aa150e52476635a2dd4c217196814e4bb556ce204d1ccd9b108334a435d48de5ee6f49ed009d37b5361910b2dc8292d014597d7b3b34721576365e7343967b23549dcf289e3a4eb9e93325d3e78623c5800775dfa1976463c4ae73c5ff6644229920f7a
+TAG: 73de781c870e696a0ca83402a8002fc7c97f745c
+
+# DIGEST: bdbd450e5d302436cffcae83ca3a444c0253a85c
+KEY: 57772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f9823
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c30
+AD: 7f01be95abaa9bee58
+CT: 28b701a0faf2fbf9567df15795b626ef7d67eb1495d28df4847f628b1dafff2312c7fec7f753f77a88d5d1ba331b9b37dd52658d795a7a8bb66240ccc98973395b4b741457dfb89f18f7a406ab94dcdb9145620602333063bc505bf7a02b86f2254191cc8fc3ad3f17262539a071fc381e12c6a0d0ca0ef339d8bbadf8a5a6e9ad9cc5cfca547c509b163ab074d9832de01f5163dea589bb29217a0bdd520e81ba18534f479e2a83ff5d9ea1d8f6bb8caf92fef5137130ab2d6088a344560bcb887ed6b9f062248071ee2b251b05ab085935ce863e9cad2f30343677b00da0325a02fa97181bc77bac9cfd245817ae6f23eaba98d6de31e2cbc621301d21c6c48de6a7a63197195df0f70182aba9ecafc857cf64c28373ed4767b6cf53f39df66e66d382d89b4d3e647d194396bfd4cb7322623287554545108f9262e08b827abd2c0a4962d08a13254e200bade516d9ffd31ffa5468acf36c03b2fd84aacf9a8f4253fb452d1409d7aad41d52294f4d9f36b3bccd8e7c497c6a42f5511ccc176374e7268ff37404e941ee4388042a9c3049694e06f14c688ea9221e203c11fe168c6267ce5e1a5f83826ca71e751820d992a7ce
+TAG: fa53fc37eda9c6092f63ce45991bc7d4ab0eb258
+
+# DIGEST: af3f40d07667dc7e32a1fa664c6f5503c3e2c8f1
+KEY: a4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a5
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95ab
+AD: aa9bee5857772305da
+CT: 2ff85611ef32c679e79e8a9b98ce51c6cc7a8c0bfadc2724e96fee4a24decd0302578976fee5f941081734db490f900eb9823746b6490d429f9bf31ccc5f13377f6cb0c141f895e8e2b1cbe61a42de1ce4cdbe1bf3c4fde31edd8413474f6e50b8f0d983cfa05b58020af3095db841d05fb33959cf745e9ed90ce2626f7dcf238d910030ed78744eaddafc4f1b394721efe3f3880e2b288dabf1e21e37d38eae308a5c2290a9742f77ca4d0c143292b96a8470c82c84949ab5428ae8b35cc544ddf6f674dec140f1c4dd3b046278500fc63df066112120ba103068dccb9f451d7241fb38bda51b5284fa208426ef63f38faeefbbf74b950e6a417b03ba16b48069f7cfb522df48f2d39bc105f75081f5373e77054d69170f2391238594b7c9920223de55b4f25c33aa8207e85cf6f3d33acf4a10078afe905fb0d67222a42e109e3998b6de33f25abb52cbba6d544d63365fa05fdad5dd38bb7c727ef03fb0f43f57374df1ed64fdcc033354dd9fbae444748afb173ae44ae0a046bb5283db4e79a9ded7717d963ea237eedacfd9589080e4d55ec53c32271988f12be580dacba67bd3926ce4d16dd28e1d5d6881a0beb95f43ab
+TAG: b76516d8c0808b4db1bec37d7af70637cb64f474
+
+# DIGEST: c6830aca35b85932f7c5df33907ca59bcc489a85
+KEY: 05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f31
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857
+AD: 772305daa4b550d75f
+CT: b5ebb7bb1179c4972ac79a1a8de3e57605a5e4c5c7e999777718e99744e8a529d7527b86a9b224378494ddec09d5caa06ba1d202b70d9d53319decfd8365f21b5829354fb9b06d57f8e9508521b057e96c82d21cdaad9b0af78317213e397f679fe344696efa61e30e904fd6014489c9b129e8b1e6c1a705b139830e6a55e638b39da886d2dca168ba760203ebbdd4477dcaa67f0d69d903bacf135b61c77e128e1ebc93b1c225a58f42d8e0b762e9a342cfe070f01c2727ca0089f0cde69c75c36ab90847cc634a2d9a8a241e491a3128a1d5f4ce4c3ea5af7eb85fb8d23f1100c1b9068714ea1a54f4bac67a362744e04a87c5e8d3d752aaab778cf98b164a7d7045790d833755d4b29819786b8f8ae06218357ee70889adbad358aab0e6aba1913b6e55e6b3fa578557b5f7d86554e4215e21da28800263ae04e9a3b2066e3cb0b42b1aa16a63fb81a92f24f59ff5fcc7677cb93c2a46ea22541169f598a31ca696c96a5acf5a703c00419a3d6e644a6f4ac6141754986fcf9010abd375c3fea8f107196a5b666b42486e5736f35eea345c0e6d8244782245f9a70f26c07ca3b34bec07079ebeda416a7c9c9cc2f786eda3b2bed14d11e15ac258
+TAG: 89880be09a636f07c6c1d882314bfd42cf8371bc
+
+# DIGEST: ccbdb85e0a5bae6416136d8d64ef0fc8ef3bd52c
+KEY: fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6e
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4
+AD: b550d75f05d8089850
+CT: 8c2bddb47fa7091e81be5d74877d87184980523eb4d64bdf472da0cf0d32ed1053785e39b2a80810986a47f3c25ec4937aa21180f4e74ed36282e1a416b6d427318afd3f35509fdd9298917cce03073b4f3575d8ce0db9a851db44ea3e6aa0e1131553345cf51fed918e443b3ba4dd0847dd78306b31818723d8e20dc2d6fc42ab86110d0cd83dbed91e1f298bc0f5e05d63fc482e18d7963e3c6307b82cc3631a8dd7035e8bff22206f3c83a38457b27acf4749a4bf084933111d4b49b73a96d3da4753e01daf1c1a1104fffaea23cc04543a301714f57aacd26e1b744f90163eb7d0538d11485406c7278b174c6b6673f5a3883ef8cea4c757b64852a36eb95b11a2749fffd88b180af280595f6dee9fb88fad85f17a8936858d4d725267c82f74832d1342c575b582e8ad1181c9f6b793fb472e0bb3efcedf7bf7cebf02b511403a29b7c4c876a7ae361a662e3ac8b0ee680e283e2952b6195f1251804bcf48dc2521507ac5c7605ee3057096daeb1d420295b2db80739f7ca0ad6d29d81874c8642e4fc9879de2c5f575d08ad81f0f83959919061d9431bcc7ceecc1eb4907437b4849a02b13fd487e01fb3a3d79c0a3c7129964b148213f8813854b2a66dd81cbde
+TAG: 577ddb6434e1ed8455470001527a4183858116e6
+
+# DIGEST: 9bc71f6083d602ea43a5be27534283d8953578aa
+KEY: bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799e
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05
+AD: d8089850fea3711265
+CT: dc09bcd3238a4d70331bc666ca9b6d4de7d07baacbae73287b256cf26ac45eed45438d30003f7a19af46c493a1cb33b92e0e76dac7a70fae1a93379c529bc2771e2048769632854ad5a9e1b0fbec30c95de2a3b9ab8cfe406cbb2f9fcf80327c290758719c3f7d417c61097e770573bc09349c4b8cc87f35dff18a8838063a5a5e937b1e050021ffa5fa1437a85f4031c890b9ad41b4b8b1baf07035610624ed8397cda94e87b525860608544a91a27e0aaf49e5118677e8195bf02d33ed8ae550285383e271aeb435a735af6ff4aa051dd7b45c7feea79e5ed291a94ef39bef3885458e1a6111829742c6e1fd27300c402896730b65b59231d661e8507f490fc6fcd6a62592f33b9c963f95b50c7a98b6e9ae9b44f08176472ef817eee8c593d31cd625968d3ead3cd8b916985a3ae0facffffd05ed87bdc3fec7fe110d61534a179eb6a610c9bab65cc23f9abb02ea2cbd4852733f8689c96e454b458b3a5ad188c35141902dcacc600dc5daee602c9afea317865061eddb03fd3ac3a9aab26d27b54352844950aca7c6d38cd2782a43b8e879a269b5db48f60a4c9f57fa1631ff81f465577bf6a7b7edbae75968bdfd3fe1ce2c50604e15a2044cb7992fad89a37e5b
+TAG: 46c0a8a87eb399fb9fadc9e313e9073707b9e9a1
+
+# DIGEST: c39bd34f093d3b18f254e8a94d2afd8f70eb4d75
+KEY: 0bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fe
+AD: a3711265bf78261046
+CT: c4cc994ae03c798c47b7bfcd7a96f64d50adab27beda58940bea9bc1ecc0900061651f1aa7f19000ecd5e36ec4da3c66f6748841bf841e0d777b3cf4963bd938e813fb23ba5fba744e6f63d10ed7a76c08e3d2f5c14735443e8df8341406977ff22ff82654ea441235235c900fe04eb6e3dfff65c3d17bd725e41677d7fc8b13098a7e90b4a4597dc1031078a27d02b9f74480a738d7d056cb0607fbd1f1cc9bc90fbc32d18df8ddd29fecd71ddfd9ccb56c96e99c679811dcba63958880825e7b5397d77e3b0f3edc6ebabc2ba0876cb1f200f2a5070a61dad3ada6f85735a6b277ff1112bf7ae1043981856d4eae0de28426f4a625a7780ec1ae237d130950ae8861639a2c89433bdbaabe8d055a8d6380205743d1489c98484743273c1ff9c469917577d013fc9293902667b01e9c69aef3e5320011fe28bed4b2b90ac3fad38da7fe513aa0fa8be56ed672867adadd74dbbd78e6a408c125607a8260ada650b61b788ab739c1395e4c13fd6675fd6218b1b35f21476f56ce0673fc943b58a5eec32d94b7019fa1aabccaebbcb5814607aac96a58c242888969d2c2cf80858c2a6a86eb120eff1f7d42d904565ffed8d7a2e1822018c398dcd5c7ff75170e6d974360f7b689a6abca99ca
+TAG: bf4baafb8c1f74a9622d423b0ff9eefbb25c1f34
+
+# DIGEST: 630e1d99053b3cb7dc8c5c78dcb39fa7b0b53e74
+KEY: 2e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e93
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf
+AD: 782610460bfd24ba02
+CT: 6f8d2c39efeb7eda5b5e5c63969165c0c39cfa9d00528931f7108f26a59f2c2ec3582014b225e82ebd176e140446e73495bdd90871ccf5ad416c28aa95cd3399d433ae099ab0f945d3c4d1578cc3bb84c63a93233915680aa2477e7801e9333972a4fc61bfd51006c4b10423e7535529ba236c1304aa2b3f0a3b02e7fe26089b9bd32a213b71a888eb83edf074d497145f4da9fecefcd80c87e0e400e5360df5bb73047a34a67f594e3994361960a9fc89030e4f5dfb37a9294da54e7e1f31edc38eb5d31cc7450b1a39bd8ce60ee651181bd42ac28894e5069d861bd62cd18a0d380d24f0a1b786e0306ab59c6ebd3148cfd1e9e45161e49984563c1917376f9131a02452ed792d1a68ed1b34fb51f051a29e559b8728f1ecc0e5d68de2d92fd5fe20c4d4840544e91dff2850549ae844d49f333f735ca89c5bf111fbdadae996413b532bcf743074a09f2f7b70fb9d463236d61338f034a9f185c09a11cadc34212bdec5fd16f5294302cb464d9b365b5c7ef9534023d9b9a69856c861e672deae4c77b1a2226a6e4269636cd25772cfe1ffb915a88f6cdcb79819934eb65621d8a6b60ff03606301481c05d703fba6e5aeee78ac6ff5567097d4e367dd30c2b24ff71927c1ad7606db719d9f4ab4e5080a5e0
+TAG: 66138ad334451538343e81a214ceb3be27e737cd
+
+# DIGEST: 083d60536c78fbe909d2b35cd5b891be34f2a60a
+KEY: c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a694
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460b
+AD: fd24ba022e6da12dd4
+CT: e56c98e73ac4038310322a56de7b3700a3a81a6adf92c8e5e339b1486a72ccfa4324f710ce5583b940bcab1bd364b30cb42a47ce8df7f188f3c6b26b9b3babfc314d80ee43f368a7a1abb4c1b0fee2a133ee269bc1cc8ef59640f8a01781dd6ffe5f0d39256e42505b9cebfcb3287096561c4b6a3803c6ff8957397c24ec8f51191538506f8d73ddc741c2533853624b3d06efff61ef3d738430dea182981e5134037466fe5048e2c3b3c1871516cfccc08863061badfdf3cddb56810004b2f3d801c69b935c11595b142200dac0a26a09cab2abebc21a37811cdb09d0da0c82218e3dea77bd92f4ca22c4bf6aa0b81a6d0ef48d34f0e6e9e548a96868cf2fc993c0fca590cc6f805703a7b7499b8ccbf0d1eaca2625fea63523bf38ae3af6466719f0a0ef3f2d2c058a8ac0b9be5d045da44c16faa55c8ee9a49ee33107a8b46b37bc154256d2ca67e208a47809204956e52515183f44d6fa827de73bfc29918536d7f922f5c0ba442bc80071548cad3a9b63cd8b6761f6be828cf2a46c779abc0e1aed0ec8a89c94a4cea1a92de49827c0ee561230d2773f0740230e8b54f97fa347d6a0baf299a4ff218a4ebb9fa31af690e5f64dbad4ab4f3ee4bbb12037baa262fcabc475713e305010665b8608d81618cf
+TAG: be0d055693ea4aae1b43166595464c779e974c8a
+
+# DIGEST: ba36e689ce5c9e3dbeba5ed1cb00b265c7b30d79
+KEY: 0974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d72227
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e
+AD: 6da12dd4c27f437248
+CT: 634b20cec2ef572ed3b8cb2f4e71caa311ac4ccf21b980479d5fb936012c2077bc92f0ff04631796e7cf504e38638787f10d03a5c17f2cf07b71379ab7bca0e51c31e7bd78e22b66fb7006328db1cfcf7c39822d9ab88d2fa2c3ae4a22ac611c6703fa5dfbdb4f3432d8d195e000f7adc2763fe861b3e0df2f21fdc58d4e7e80c476138f47d7bbd83606914dc43f0182f3d707c37befe92e78faf34f9f9fa116b9a176f18ff772837e8c3e25d46ede452fefd626c53aabfac9d0c8adc45190920a0df316f4229227831a30a660ab19815a10c02b5be0d09390f686aee296b0a0814f3b8f4eb1acd3a1bc92e6f1b5ca5742c0ba9b6e964ef6785fdfd632053370c6afe5a8239755b491e5aa268f26537136aa183f8904f8127590ec1ec841fe27ca5a791fcfa18118d0d15fadd3aeb0765a2c07a4a14bcd2aa3c08b2a601fcaf76e6fa748a9797c75a18a898c8e42a4793c237197c4db829568d5ed096c2bb2dfa0af999f336da6e286f3626201abbc8decb693d725d6f15c919b5c29491d99805c20cb996c0a4c08c1520f51b5405d853dfe60da206c46f02602cbf53b2feefb6386f8a0ed446b2db6649386a39bd179fb78ee99954adc094f0ada882506c5bd35b9aa0ef67b6db8a459d04d3c4718a33d856ee732048c6a9f11bbdc
+TAG: 9d9a5e7adaa5baa55b8cd3364d66bb073ad12586
+
+# DIGEST: 2f9b29467c1e54888b4d4db41fe3a943887e305e
+KEY: c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a82526
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c2
+AD: 7f4372480974454879
+CT: d9c24e38cce64bc0c3c42dfed478d1399c8661f63bd459cf420ef22ed06970bd44bf09cda84b1d920ff51d5a2e9a968e66ae8aa9a10d7b5e0b4483bac02644cdf255362fd9b806dbf1c25212cf1283bfef7e15e3cc29a5ff98edcf16747067aa928e360cca30b4bbb57b48e8259f9160d3d6ffe44f4a9579f02ece6d5f7ee3ad45a36292bc7eee581b5b4cc038ebb19cda4f339d34fe51b2d59459d54d42d840108fc1d7c271b8d9e7e342507c8117f54b79e723a408a0e6a387ed5933a61cc8665814e5eb8ddadde020c7e6d77bcda15e7a332c07f903aa207181715b2e7e60e522727f12343e7db9cc5eab156342d49c0fd05e02981b2852b61dd311afdf696535839b86b2eb6776b7b117d249a2adc1a4a4260f3e42a0b7cff6f17a3465087f0870bd5c678662e5fd509aa2a53cd49a99ad18d7f35b9d68307cd2a6a146c1dfee5428ea3fe0b0ae02ecbf5819576d0094ae0e80773c4ebf7a27d6a74a703ba98c4681a648dd20a7ef8540432db9a3b186d3cefebdcf4557ca70087fe4412f9a14f84ad3e5ec6668692be195a7db3c9deefb89fdd3972c07a4274c075cbdd2d92ca62b409dd2bd095e5d59590f7376359aea46f69e06dd77629c0c90a9d18b3605f2fac518e2d448550e371ca88f3943eb63a3a2c93043ecb0d1fd
+TAG: 5473022e135093d1b4dd56529a341b3894da36e7
+
+# DIGEST: 070f23e02cb53f55b0127fd3fddbab83e5682275
+KEY: 98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e97704531
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f43724809
+AD: 74454879c41de9ac9f
+CT: 6e115446599543bce17fa824852055880348dd98bc8241db1d62a76e599d4b9f3c2ea4f27c1e928ff84b480ad3d8bbeeec758366fb3ebb3e8e8f15906e219e768bcd285268b6347596f31240e345464c7316836a28753f6ad0e22c68ee74c41a3af8ceaf29f3a28fd1eb847602386cf37b57fbd8e52f90415a084800f05cd7a1e0040f69a06ffbdb82c5beaf66f69a17830f94dba00e4a574db348f9f0125ba656da5821b19a7294cd57ef4ea3a2435866554b705c0518445a156240151520e4f61ce4ea7f57af81a5a32056f9ab44102dd70735cf9875d12191dcea96ae8d5319a19cf291b1487f8281e61c634e7b46c2c28400cb437187a0de78c025cde3a7be6c5dea6927d404176c2dd79329929aeeae88a03298041eb728dbb18b5d0086d73813f48fe7eab4248efc38df06dda783a1d9d9ae8fe5fcd50f2173405b4fd35911ae775085c04a0c0b296a10b4ac3f1407ee613ed627567fbfa47dda3e6b151d4fe736f9ee0f1a3148178b483e74d251a5a050caa9df0a6a5d9740653bc5f6b269426ba9ed391eb475fcf0b5b773bfaef15c6c634d2ad22b314b20bf7ee767e9a0abeba61e909ee90c1e433d834610bbbc3cba4989777e0511f8a08bab823c2544c5ee7b1c57992a40c3829fb8bc43e7d102e4d14ef990451f835eb5255c143e52fd15
+TAG: c88ae6b348c5097fbf9aa9185a3c141e9ce6e541
+
+# DIGEST: a09f0450fec556fbb3a1f869c9780c3d12547311
+KEY: 79a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c9b66262c
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c4
+AD: 1de9ac9f98233b5a73
+CT: 7512a3cae0bfc465c4d9ea0456ea81065b0903d57498f148b5b183c25b0cfcdf005d331c01c14df2990220940bda53515fd055ce885d197b0eb7c66daf15c1d60ac88ba4f8d0f38df81041a1be3a54e500b5e24ba3818361f2594322b12f3fadb67be436b590a30209619bf8e288b86e24ed702a4c351dd441f048568521c6c1c77f97b1e12317bc83a2469c244be18b2962ebd250ea520609fb3ad24ff562a65ab01eb6ffafeee625090c9d2196afd8666c260117280d369a083892cd8efae9e986c925e02108f013a332f4a8bedc7ebdfae2ad2669b694ed7f1870dcb08e69cce507648665498bd572df38b691ebba62726db33f13f84d831669d3a825f10da1d557a40bee0de82546dfc28e30b6a1042d7d9874799f62596a827f7f9675977946e829ef7bdea5e7aa3c0b386c50dbe73fbf8e28c21e935045ad6d8125af3905550b8780e1147bf54db77c2de58cff48601e9f720ee686443c22691fb8bd6ce6769626e7152b551c3c1df01c7f8b41d383c782a1c9fe4d370c49e1df71de1b62a7626dd485502476473c5e32a9fc420e6693ce80152613e37b73041834d0900f5258a5181801f41384e2a73b5d61e2cd442073ee1ef22a366f67f3eb655cd6d5891aaf7192e651eb5ccc0fea3c12f2f0255a62d1709cf785f524e0339911dbe33c342f0c88c400d376ca7e
+TAG: be9b117006329af96d21c9cdb240de73731b1d6c
+
+# DIGEST: 32559b69ebdbf4f1fe7c6e5ada9a4117836eaf4e
+KEY: 0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c9b66262c0f0368fe9d
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98
+AD: 233b5a7379a561792c
+CT: 0cb288e69981e771486fa83463c402cf6dccfe4b913ac4cba832933d3596c67d7b5ae39a123dc3ccb12942b78d2229841996ebcf3bcf508ab909d714eacdfb6d635a8a925ce15e7c8b13b4c821937114eadfc23e240ca06a001a118cd9b9894616f1eec3a2bedeb88c3bd0fc9548c42c9b7a9ca710f94fd9d638b7adcd758c9fe27afa89106f81653f0722f41bf9560296bd0492d8e084e83474e77632c11a89fc3960cd75e3d0e704cec1c4f53caf468f49364ade315f83a836d54f259d3dbbcdc9a9adae1181261b0ac5aa3a6e7e3d7e78f2cec0afa64185d548ce45ef620dec97ca51dde09052789e896e07859468bcc0dd5b007bdb73942677241360c2ecb4d75700fb1de196a6dbfa778200605de9ee0a8683fc6e89f19ba852db7359cc7d42803fec50b5d123b73c6383aeeff387544122fa64ed7b15d23cb43bba9a9ca8e58a2e28f555d970f7c83fe396d4c2c207fba13512bc60868361369896778744e41a82e874b2f51277c6a5b1d3e5052c87cf58b05425b396fde61fd92b480a6fb5b3052183c880a9fa04dcd2082753bb748125695f6df801d9bd4803fc3d5e76599db0b91bf76c9f4186f76a4f919df7376bf314814b28012483717d357da61492940ab3bbfd0091d19899bacc5bd0fba72ea4005a55dd99f0e9be91256b93239aadf66c4d803e5d320c36
+TAG: b6205a04ba2c348c86ac1c5dd66881e3bb6b369a
+
+# DIGEST: bcdc01526c7b0248abf3a41ac893bb72adf422eb
+KEY: 8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c9b66262c0f0368fe9d0cb746bbd5
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379
+AD: a561792c0f3116430e
+CT: efb869db3a0ba8e9c1d4a0ef6404bcc10eaf089340ae938e87f1d17d3b7e3ff65c4ff6972c6f404e6d71b5dcb90fee0c9baffdf26de5a4c01220321babcaae4ed55f8766d70c14b58abd1826b90a121e5b9d13d8a41101ed5b8a3b73a4c6cfec8ff46946c5414bb5ba70b615d19be6181e52e0ed6d1ac9cf4bbbb29d67a213a7cf07af21743f0e107ae580a924c43b9a8120373619de0b8996d675d90a1aa9d17aabe9a85997372d4d2b1a1ef6055fe3339fcdc8256fb2f085898d83b609dfa6ad79b3ba260892563a00a1b1f5af69b94cd500449f20abda617250cdd7615cec3f1d75d4a66ca7c9ac8822e945c7ce30be6e6d0897c2faba38141c4aa4684f0cf890ce4c57660a166e32c6e0b7fe9981eff7a9025f9318e142c9fc71a7b52f3646e7ba41fe8c9a20d0b25c8b6f3827bc067d6f6962ad4faac0aecffe54a1f37d20ba08b7bc648551fcb93cbedc728bebee5189c80e715d3b8df3e5a891b0fc555921e2af871b01356c2c049361df495691b9383fc1f2ba55f023e8d1f4649ada0de9bb02764890f2f1efe9e11f131abdc35f1aec108aa532eb54060a77777384476a994aa156d452ce2a6f2eb92b3bbe63f84dbc5385bfcb3331b4f4df3b8bb2d94b22029090bd9c0b6dd41084beeebad804f133b3317d5529b237adf8cf463da32dba799c255ca3f157dbb1dc4588bfa1bb6571
+TAG: ea7450159ea6b00ec46d57c3117ba4b6879008fe
+
diff --git a/src/crypto/cipher/test/des_ede3_cbc_sha1_tls_implicit_iv_tests.txt b/src/crypto/cipher/test/des_ede3_cbc_sha1_tls_implicit_iv_tests.txt
new file mode 100644
index 0000000..ef97ddf
--- /dev/null
+++ b/src/crypto/cipher/test/des_ede3_cbc_sha1_tls_implicit_iv_tests.txt
@@ -0,0 +1,840 @@
+# Generated by
+# go run make_legacy_aead_tests.go -cipher 3des -mac sha1 -implicit-iv
+#
+# Note: aead_test's input format splits the ciphertext and tag positions of the sealed
+# input. But these legacy AEADs are MAC-then-encrypt and may include padding, so this
+# split isn't meaningful. The unencrypted MAC is included in the 'DIGEST' tag above
+# each test case.
+
+# Test with non-minimal padding.
+# DIGEST: 7f3a0e20bde700d3c5596909282e5c3e764c99e7
+KEY: 86d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e
+NONCE:
+IN: 936a91d0b5
+AD: d2c0267218cb7090c61713
+CT: 144c98ca1f4a40ffe530b338e5173a8e62c8530b
+TAG: 0c14b15046d12f2ca3158ad71effd0f46b29b3ae
+NO_SEAL: 01
+
+# Test with bad padding values.
+# DIGEST: 7f3a0e20bde700d3c5596909282e5c3e764c99e7
+KEY: 86d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e
+NONCE:
+IN: 936a91d0b5
+AD: d2c0267218cb7090c61713
+CT: 144c98ca1f4a40ffe530b338
+TAG: e5173a8e62c8530b0c14b15088f70f550ab57e02
+NO_SEAL: 01
+FAILS: 01
+
+# Test with no padding.
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f
+TAG: 3ebd1b0bee840e8a6e992421c62de5a8fda3a82f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: f0f82752a691ef5866413f2b2e5c1d0ebb41ccc8
+KEY: 7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9
+NONCE:
+IN:
+AD: 936a91d0b5d2c0267218cb
+CT: 76416b81
+TAG: 2ddb5b2cb015f5b11fb960cd166c5159b6fd430d
+
+# DIGEST: 7f3a0e20bde700d3c5596909282e5c3e764c99e7
+KEY: 86d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e
+NONCE:
+IN: 936a91d0b5
+AD: d2c0267218cb7090c61713
+CT: 144c98ca1f4a40ffe530b338
+TAG: e5173a8e62c8530b0c14b1504666f5a5cf6b3a5d
+
+# DIGEST: 5b32faa93c18842b5cb7b075270438756d5f7dd2
+KEY: 97b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f
+NONCE:
+IN: 936a91d0b5d2c0267218
+AD: cb7090c6171386d641b877
+CT: 6c5290706a6c9c4ae519349f
+TAG: 87e4aadd457cc7115f854462b6797e3836bdee34
+
+# DIGEST: 995a0f9b029aba3e0a3205364628bb76baccbf45
+KEY: 56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c617
+AD: 1386d641b87797b684e0fb
+CT: 68c399c86abcb34bac8b6f4c8c5ccd5e7f5ad7ea
+TAG: a5e3a1b66f75d0725697822203b423868c636bb7
+
+# DIGEST: 023d08d5e5af3e0b016103c7c3cfd1d02577888e
+KEY: d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df6
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b8
+AD: 7797b684e0fb56f97c3961
+CT: f30bd82745f9136badb1e6957b7229751351e557802b8dbcccd5fafa
+TAG: 640fd302b568db96ffebe60962d923c5bec73197
+
+# DIGEST: ad4b11a43bb47aec3e91209f98f99839dfa1d6f6
+KEY: a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0
+AD: fb56f97c3961d8afa22993
+CT: 630d9ab3da5334512f84d4a3fa8244df0f51498917d19af8ca6a43ee
+TAG: f417e0695663cee81a0537c1bcade379cbebb75e
+
+# DIGEST: 580641286aa43bcef85be190e1967f627713bc64
+KEY: 89c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c39
+AD: 61d8afa22993a340b9b3c5
+CT: 81ec9cb470c5b72a2e3e86b53b94e20516bd821d68706452f03ba1e953790e4e9dc4b7f8
+TAG: a095c625d96bc03688f985eaed80f85ef647ccf7
+
+# DIGEST: abb06965675631a07f380e80a05cff36c2d42ecb
+KEY: f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa229
+AD: 93a340b9b3c589c7481df3
+CT: 7595dae5e0e62100c9b72c60c8aa4059c1ef7265547feb2ae537686e8f8acbc915d367a7
+TAG: 32ab1bcabac6a7fe8f37dfa48d7186f19427690c
+
+# DIGEST: c6a1ebefd827cde32df1d38379ee4bb6a7f81267
+KEY: d8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3
+AD: c589c7481df3f4183aa23f
+CT: e4b7e1ade1e8af85dab54d781969a9f06c22f044d115e64fecd4eb0e222b3d39988a0d5c2816643d4007ce91
+TAG: 0f713edac5403cc736197c8f9af9e538fb7a6d89
+
+# DIGEST: 77fcb5875838a28d24c4b6bd0916ebd827968073
+KEY: 03f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481d
+AD: f3f4183aa23fd8d7efd885
+CT: 418453b6063331fdcf123f5462411fe0551c0f2ca9bf070bcdf95c35177954d700487dc811e98759ff04f0116961bcdd438d1dc8
+TAG: c4d3547bc89478d711ae7e671d6b48e7a512fbd5
+
+# DIGEST: ff3c91da880d2942bbc51adafaebcf4c6fd50603
+KEY: c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997d
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa2
+AD: 3fd8d7efd88503f78b8ed1
+CT: 2b4f3b7db35b6608ca790d8b05b405749f78859ff7b1ee4e588648f7afbc345a04d550c0a03753f4222ba1f967a2faeb3f37a994
+TAG: 679fb99370455efab942fcddc691db0d392c7eaf
+
+# DIGEST: 8c439bfcfb896bd106f94676b5626f2bc624c313
+KEY: 773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd8
+AD: 8503f78b8ed1c8e9ba2fd6
+CT: bf4a8b5df0754ce3000649b523fce0cf44db67966281a8c3b300ae433949e5351de6869545a8136a226b192e0d78bbaa81e3e6b7a010d5e0e2e2af23
+TAG: 105209280dfed70a87e67baa508408106b096575
+
+# DIGEST: 35d9dfb89c1883210f03050da3166b6d13f5b8db
+KEY: 2a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8e
+AD: d1c8e9ba2fd6773e0d0c30
+CT: f0bf72c441d1c94878f3ce10b10c540ad9933089de01b8ab82022d64d0b7a7665d0a485bce781ba9a9f6a53c2eb31d732f2233b94224bb6b541e3b94f4366882a9db4b67
+TAG: 668ec1f6254ff1c294fa40ed27260c848636ae96
+
+# DIGEST: a07054c760cc66fc704edf950201005031f3faac
+KEY: 446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be1
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2f
+AD: d6773e0d0c302a5f47e037
+CT: d7059edbabb5cfc2cd5c459abd74e136790aad50d988c6c9271428597617db171b89ab171a68b14f9d417bb81f9f7d2e2045aa47c0b5d166c8b2622bd914c4e752e3d17e
+TAG: 303776640b3ab712f6068c449dd7a7b2c4ed366c
+
+# DIGEST: 63efe7af502231420ed5aecce9a28446b257828d
+KEY: 7df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c
+AD: 302a5f47e037446f5891d7
+CT: b81f6e678c5a08244a5f578970d64f96f50ad5b5724a9287ee7b293308db34e03456f1745f79c594ecc480fb2a9412bd685e6c0df028eda06aaa15c90afa4ec01736450e3eb863b849636c21
+TAG: 2d353918c6e3044d298da2684c08f1271ba4b4b0
+
+# DIGEST: e8e41988fad6c8b44c56544964cfe0a347b35b1e
+KEY: 933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e0
+AD: 37446f5891d77df660ed82
+CT: a799c4a6590a4c48735d1da9746e5441cb11b664daada5d4d68d3a0110c4ad8d5e96d7331d5f7a0d1df9af5da4208065b6bf31affdfcd4944e8ed55b0ba7b7911be1a9052fbd93d5fbe2926a
+TAG: 6e5ced88748f87682759b5547234cae85f78e4a7
+
+# DIGEST: 172f4992e692a88f49628e5d3937959be01aed2e
+KEY: c55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d4120
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891
+AD: d77df660ed82933f62be8d
+CT: 7923c66ac88a9d3a2c9d9e714d491372caea0658b4e5692a7df8da934dce8525d0974848545ce89a44a735eedb22f18b5b8f1455c0aeedea9cb8f5c0bb51addd065a83c4e825ff3993ff58cf0af7577b06b8d517
+TAG: 26fe8d46fce9a59b084c3924d2bcf053291e7a38
+
+# DIGEST: a35fc7d25f90dd9cbd35910d5532aca8aba88b29
+KEY: aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed
+AD: 82933f62be8dc55b436965
+CT: 5e91bdcdc26c9100265ed7c6f029a1aa46ea6807340a161cdd07d21bf6bf7181eee02d939fd95aaf343eac9f629e01a665dbb40392e95da6d00839e3f9b412229bc48d9b289b8e91fb2705a0d3ab85aafb130e3e8d6c57ffa542b745
+TAG: e2313b7c92ca3350ded6fbc5e7824c50e3888c0e
+
+# DIGEST: 4abaa8453e8cfdefd918571a961d8351754ad5b4
+KEY: dd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad40
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be
+AD: 8dc55b436965aabe477e0c
+CT: 2de7b7a26fa9d1b0d301f9bfcc0772b0a683ad5a1392bc38f495fd88a44a648cb4136d63ccbfc994f5147cdd88a40d813ad4cf7c95db148871433d23f296f2c0edf698329c760b76f4c5eaf2a5b620c482494de0128c9e5d2237efe9
+TAG: 5b7e557cc8c83b35c5df397489694ee739154c84
+
+# DIGEST: b51001b6ff9d27bccf3103a4961280e0a1406257
+KEY: 1eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae0211641
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b4369
+AD: 65aabe477e0cdd46be9937
+CT: bc181d050d6e79cd5d66a1410338e4031378d60a217bfbdaed1404453cf8a680b9200f746ddb6106a8a407aad8204a7e3b5ce8b8f34d1bc69b84fa538745bf599674c6ab008435897a765e5072449a7c79c4fbd11f0883548a88244f5b1dd7aaf4ba13e0
+TAG: df9d9f0ea057ac04f64b48a9018ade3b086aacad
+
+# DIGEST: ad2b43eee27e6267d8c5c1c3d558a07dcd6b1f5f
+KEY: 997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef45
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e
+AD: 0cdd46be99371eb8da7dac
+CT: 7ed8d60c67875030c8a20cbb5f71e22d1e5c3f93852a5bf953ae67cbb3a4d3c0b69bd9b43cf807b32dac4833e502fb377d67d2575a62e9f6dcc12c4df05c71802cfa5b6b3104d9526941bf1b48bd5e65710e15862b6c0dacc1decf5aa1980fce6cf99e0a82dfffccefd195e0
+TAG: b64ed804149472b11158cc396b77e8d080cd7205
+
+# DIGEST: 7b17b7cb19107af8fc4671420e461060e2ef3e61
+KEY: b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dc
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+AD: 371eb8da7dac997deafd64
+CT: 245180810407934bb7ef6fbda3f64abd712a3959d0fa2502464c159ed70fab64a10f360f22dbaaeaf44d4bc926c1028675cd1c3a94ea951b1561c8cc449f0940c6766b67ec21f8c039f826afa423e7960bb4e2f7e71f8f660ab2bb24e2f3bdda5c070a3529d78b1cb7502ba1
+TAG: aa764ed0da7a939f1aee2b6f173e03cdef71f25f
+
+# DIGEST: a27799fc2e00e7abec4c5939451a834c4606cf7a
+KEY: f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7d
+AD: ac997deafd64b1fc65de39
+CT: 4fc30349e938933fbe87c1b071bb54ea2837c2bbc4ad4a59291fe5e190d25aeba4a14adf7a8968f87be1d68d3251259bf66b5413b4b4354e2f2e0574a3055b4c70e736ea139159599ba7f7c9028671c1bc4af858bf7a691429571743ec154f0a7cced1f23b748cc93cbefc234dd8dcb51409755c
+TAG: 687cfe32d594a0351affd831264ada7fdf8e83a5
+
+# DIGEST: 7c52593d1d37b0dc380297231c6cb7b64e04c493
+KEY: 1be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb9
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd
+AD: 64b1fc65de39f4f03541a1
+CT: 4b735990123f86b6d35d5c64faf77b21b07ccd281649d3f70353b0515698c843c2fbc2ba7ea0700112990ca0c7c638be7f1f0e6f4a531ddfff6db4638c2f38df750ffd5ef23976fd56d79f1d882f6a5db8c107e6a76c2f74c3b72b14127504befe98541418987222f4620738e7ae67feba4480f1
+TAG: 5e0eebab83ce6db242365b528d681102cfa7f000
+
+# DIGEST: ac6871d354eac507556770d8b6bf10b5240273ed
+KEY: 33c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de
+AD: 39f4f03541a11be112a729
+CT: d93d6d42642cb56dd5a1e3b8d5913ef595a8d71fe4683afab5f8f6e3f1f87d08af1efa5257e2427a9e34041dde5deaaf6f0f808debb26b0f4f32860669879324369aadc41982a2abaea1c1c04146144d028b40be77e4f07ab6d5903f6d88aa7716748c3b158e5b2b387b0116a8a8ab1fa852c210b5cef20d5ec2d60d
+TAG: 0ace1a7de20afd27c436d4785eaec425d8f22fc8
+
+# DIGEST: 4f498d0aa9205160827626ef80c163275eca1f78
+KEY: fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780a
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541
+AD: a11be112a72933c7b54ed4
+CT: ed719f396a0c720c91486127e58916f010692f6018646fda04b0321e70f3d5736ee3827743f541857fc2bb3c41497f03563540655a7ac43f69e62d876a31ebc3c14e24a432814aa4a448c44ac4b02624494f703bb171f6878236bbdf27be2f9fb651cd855564976b0e875e4ccfb42930422db234008ef6a25723c944f8e17447e2588894
+TAG: 570bcd7913bb8141042b7dbcf8714d68d6539db7
+
+# DIGEST: f0901e8b8083c39222fc940384eb73cb96b22892
+KEY: 41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a7
+AD: 2933c7b54ed4fad0be905d
+CT: 10be314ab0ffd93775ec945717d140b07d15e46e8f057f93e76615048981899200f4411833cf63fad000ebf63673171104d08ded699f25dcbe747545447e558610f08ab78c09025ee0ccb3fb0661677c76d58695eea7e137a2d846e583466568dcfaab2b7f42d92835342872aaae2f2ec44d2f0e63bf68fdf2709492e9e79b38f04805ba
+TAG: cd4e2eb1ffd0c0e5ac8805cf4b84b7ab18ba3f6f
+
+# DIGEST: 7af193cdcc8d7f17b55447a81eef3dfdf345bba8
+KEY: 998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9e
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54e
+AD: d4fad0be905d41203f5dce
+CT: 6afc6a8dd1544dc4e77dc7621ec0b0c56f27bba0784e917e95b484d64dcf926cd68dd020fbfc356c78ebd7a1af77126f430d0b2477b965eaa7c964e888f47370d3bafa933f35ddbda9f13bc1155599ae31d552eee3058f63f63a3632e4f1c83873c785f45f7cbf46f3e7f7a9f36fbc623c168eb921b916f64f99fbe60892395fb66bf809c02da0f16d60e4ad
+TAG: 555cddb946338c9157220cae40f2ca7dd9ceb85b
+
+# DIGEST: 4ecf44faa266de0904b093653c4d623a543d12d8
+KEY: ad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be90
+AD: 5d41203f5dce998f8fb2ea
+CT: db772e357f5f21e09490a69975168af1f31f5310b5c95d5fc0b099975525e8d8c397537d43e986adf5a961f3d2fe4bfb5a4febe487efa71a9d8b14831c627601d7f991ff6530591309ff66becc03cac76403a4eccf4615941cf909c7b9e693bfa7108829749961e54ce04f91ff2067b8b8a3cef940f50f140b32f23316b87ec8bc4799b5bf6fe332093a2e37f66c1960584c8565
+TAG: 48d415b8b4843cf7454c1b47646aa291c20b8dd3
+
+# DIGEST: 92a938017497e0762115325c40b5f7c138d5c6f6
+KEY: 16417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da0
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5d
+AD: ce998f8fb2eaad409ae021
+CT: 583717ade9efc6127768397fc4042d88c3a86ee8e749090a0c8a5b66aa1f5260644d51306f601b6728bff56ea2331edf811d9e8ea7b697952c42af9503106c6c6e99818ac0868414d431bb9ca0988b41455f8fd8a3bc96febb0e2e630ffa9537aaec863eba926e0942c97b21700c6c091d7edad3d6dde06698978920648c2a2352af648374fde214d6d970e701fc04db2a124f49
+TAG: cabb2cd56341a73d1d7e0edbd38f9949ab24c162
+
+# DIGEST: 6b126413a7bac1069cbb5b338c158463a242d607
+KEY: ef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2
+AD: eaad409ae02116417dae0c
+CT: f806ec43738373a70f9b7757a9780cf133c46e02e7f82c0b64cf0c1ddbfbfaa4975ee8bab96ccd9270f6255fe8005a79bd8f80dcd59daec2975ad7302b5a2c2c8bf772231ba0ceff4b670b7b0aee0ebd8d14e216428d9fd1c43432aba3f4cf61771c3927290a280e43c409837df078857d442bcfedd2ebee19f96fc0c23829f5763c786f189341f38f44246820887ed0cf18a992dffa18111ff5f794
+TAG: 9aff5f9f4d4ff14565af4d150200379747746a01
+
+# DIGEST: c72d214b42ed66ae0822fa9f3bda306c7d58cf80
+KEY: 16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae0
+AD: 2116417dae0cef457b9e5e
+CT: 1b56543b2b50cb60e4a65bbe46474205dacb06c4bce58ab4bff5d9af5a9a4f07570f678fe3f1744f49fd79a0870ea2da2b85208dc679cafca49dada177ee8516bb7f2711065f8b1d66051901835377bba41f0c86b4c382c01aeb1343d26896e9600d7102c170c7235f0d5206840f96dc59762e742e9c39ae14dd75962d8d26fd382a2c9093520fabf7559fd78b664ce0989c40c480c4b230149ab513
+TAG: 790ff151c28ffeac434d030ad485670706a659fd
+
+# DIGEST: 9faaa58dd34a192550c3519f8c0aeb2ff48dd388
+KEY: 5607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacef
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae
+AD: 0cef457b9e5e16dcc5b6f2
+CT: 07b122adbd77b909995f3867d9fa2e8af2f2028aa07397f7d6f27d6ffd998a3c8c1da14cd1f8e8c43b92cc7308643d9de917c5f139faca9f484fc9173e09367d1935c5859457c35f11d0c5545c61f42db8649cff5872ad5e0860c3c78dc1054511d03b8ae346c0a2d6775367e2b3ca47da414b2f3d8b8d9ea4baca74901b3034ae1e92aafcac58027fab8db2de72334c7daec5c6c712c6315943fb8a03406f1a4ef00b08
+TAG: 5176ab1ca9d038887995cd7ee8fc5f68d6e42161
+
+# DIGEST: dd5e6be3644dcc888cc50c0b2ad0d55eb0407fdc
+KEY: 3fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e
+AD: 5e16dcc5b6f25607f00d03
+CT: c4d9dc14b3c2bf23ba6b0e9113cf165ac1028a34834afee7f3984de1c12ce56d54cd648a65bedf3a7c549c85333862b6a82fb838beeaa1dad68486c602af60c19f734ea1e9af5ba68570ed16313c9c03eb392157d8d745ad82741d8a090d287ba39041ac0467cdfa53714d8c6fa59db12ed4e1a175d9162a51dc35efa454adaf91e5474c7cf0d7aca04e75f7c8640ba7e306a089159e51b0eeb66b90c6e30c57e96f600275e15cf0d3ee9f59
+TAG: 435b6826d9febed2eff89ac6076b8b6a55767765
+
+# DIGEST: 1b8b627e1020d71318511d4c2078eed315ee0b04
+KEY: 4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed51
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6
+AD: f25607f00d033fb95fb09e
+CT: 2261fa7efcf858f8525939b1b1d5c3bd5cd0e8a6e0ad4194f61378cd61dd8fd63b01ce93aba89e2209eb7ffb50b1de5a36012f8d59b5b30152198d2fcd4b8192db32bfb21a74d02fb3202cb232cd7d713904b3bfcc6551288fea26486abbc501952bdec0a18f73060f708b8c76715120ba4babb84e03b30909b8c1490694cb8a0e2c6314ce66b174c70ad3ac5f45bb57d66d56ddc5e9f8fd4b5ce9dcfe97ebae0e14c826bd8fe451e5022aaf
+TAG: c1facc93e6120c9863f4c2b1dd5e3a702e0aabd0
+
+# DIGEST: b7370237d402dbf76f1a431cdfbb37f41ef2ad4e
+KEY: 780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d
+AD: 033fb95fb09e4d00d6172e
+CT: 454dd554c546774980035b134088f5cedd92840cdf2b02f4081c377abaa3908a6ecbedd24ae0c1d4c77811cde6f30ecde59fb15c5c15a0f4279f5891123cc285e8e9313f72189397354c3cb08bc1f7ec58e4b2a1376faeb2b14f2ee30f6d464b15fba2eda657e915e6157b8dc6611839b6044df0a60ed4d728443736f001f452749f8a4a088968434b4a01fd952364e71ec97190ce63fbf54b588cf3a3b8c36fb2e4b6329be0f0f966225754c9b4223a3074804b
+TAG: e8e840127ff0d3c91c8d853d529fd05c2bb86da7
+
+# DIGEST: 0ad0e709e40cb2fd662020d420d97ae50a14adc2
+KEY: 433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc0
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb0
+AD: 9e4d00d6172e780ab8b700
+CT: 03f55636209cd9af55c373972b3affbaeeed9fbb71a0a7c44674beb657eb89b20dd93116bcc042f8bfb640921f56d1fdc52121cb05f51cafeeb7e3a409005230bf117ecbb9f45092f70e6ee714799a7dc0efe6fcd2c16668d40e69ea18c6905b33b368c3ff69a51afd881dfff6546f6fe795dd40f87ea722fb33c7eb687a5f6833f74783c115cca091978dc51c7f947f0028a2c6256a0c848695dd21346c2fdc451963e4f441181dade8650f30fc6b9cf45ec3e58bf5f2e78ab1719a
+TAG: f7808bbb1f62629ced0b9cd9916fbde790b10c65
+
+# DIGEST: 5f9967a8fba7184dd97dc7d5da22ea785e0ffbbf
+KEY: 1c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f419
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d617
+AD: 2e780ab8b700433a957a74
+CT: 30cc1719932801b83d65fddade4e734a6280d8928f18669907dd495e5120f782bde269e83df0643bef695e4b3bc701b35fd9074984c91d61cc31c35720055b5f78b22a95d421e5672ece2a4f57c5e5a9d0b22fbad70d437eee0d68cffe0ddf53344bc2ae326072160a00d5f554692bfbc1ba91f72a128976c4bf0de672e9b2355425a3a23dbd193cad4ab4c0c845c577e2b316170c7f048910ced9628f994a17a938e961f61710812f630e2e0e36d0e37b768fe6477bf4e58942323b
+TAG: d9bc1c06b67c3b2b9c042f0c3ba53841b8e09ffa
+
+# DIGEST: b5aedaae523d9d396ad1d9bb175bf4c7c0b03eb5
+KEY: 021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b7
+AD: 00433a957a741c9eb80f2b
+CT: cc4350ab7a89fb51e185843732f69653b1fef9fad05206d2f7422e2a9c661af9b2d80f309495ba09055a4aa2f6f0e1da38b5fec74e0c4ca3e3385347a7eb2fe794327266280448401e5f8fa2bdd6026a5e1375f92e23a778cd5db095396cad1e73135d7d7fee85010fa183264c24b70b79c9949bc39a1c8cfd0a2ba0948a6c68c815c5ccfc7a85e0bbc24cbe025e952dfababb1683fe915b7f0ee86ac23982d678df4c8e57903798341bd5865a6d8d3a3f04c95245a7e65b4dadad572b5af30c9980b43b
+TAG: a3b175b2c9d19b04ba53546f4256c9a131f62dd9
+
+# DIGEST: 52bf12f5594b0cdefcf977c07626e8748cec5425
+KEY: 9da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a
+AD: 741c9eb80f2b021b144476
+CT: 4ea765fb274bbb65405076c33d3df1557f29586ae00d86d954dd3ee1feee0789f18a3714396a5ac1e2cdfbd3fd3b4c33241c63d94f91ca43dd207b4b12a9ec5b09fe279904cb066cc2e4992dbe626e80779d0896b86cdd280405642ab1efd34a0ac611836b1b325cdbf6c1dfc405cf75b33071b4a6634c705cb887b868dca4a85acc07f39db0f289c0f834c4c007893d49a40ce25fde425527cffe31aef94f145335f30be40da9e002dee2d97f5e3aa6724b806ae7683e3bb67329726ee5dd66a51d18ba
+TAG: 5848c6daa10670d1de89c8b71fb6eaa9d639998f
+
+# DIGEST: 900a1792a921b6a253c47013c9eaf01fc5c880c2
+KEY: 0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f
+AD: 2b021b1444769da00fcfab
+CT: 34e8f6de67c17c6beb8db6d2c57a1df7bba6799de0541a44b3a305948a292cc3c8d0e007af88b44e3c4055c638718e9d2056ca76ff704438d946a19498eb35c442ef5e84a4bb5c7a5f4e9b95e1e851cd917a09077212f937e6437a52cc8793cb58dd8accb4ac84ba5add02f625b02ee114f4afb59b587fd464dd1e1e8c1fb6019625877c054c580a1a23b2b9ff597283d6768297e1d02b71f7f6a733e1c27d32b78dc7a7ab1b94c907ded7b0265e2b55cafe07b6719426e89ce00499a6cddafe476588aea55bd0f484073e20
+TAG: deb039be12bcccd8af19da94148942b076b0f5fc
+
+# DIGEST: 88d7ec35d88ff113703702955e931e802fb0d8b8
+KEY: 060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e71371
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444
+AD: 769da00fcfab0f5f93b511
+CT: f9c86839afa85f6a0ad9872059d9643dd5ebd05ac90e885c600a25c1346a82fcd6367ea6a9dc6643778e6923443af1809c9351e1ba0b8559dfede7394344872d6d3632e0fd0ba4b8c03d844c71560c8c72cc309f3c115f8870e9538b21166e4037978a1b00cda5477788a93387c8a1cefe2d5f760227223f3df5d8b4e313d413f197a2a3f6ea8b1ece39cc8b2fdb27badd6edccda3bab02cd939fcbd7ba67d5128c89bf0e872a3c034880e1728c164ddb98f1861bf06db075978159eb2ea34ee524e3795e3b8a3e8c774c07f937f9e451527b4a1
+TAG: 313d2683d78674e4bd8cba35acd381cc0a8239ec
+
+# DIGEST: 8d8493b55d9b74892e77d3b730588c087ca9b1e8
+KEY: acefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcf
+AD: ab0f5f93b511060c9c5f3a
+CT: a34ad0347668ea658b79c19b83084980c020c41dacd30d9ef865de6adfe812e111055799ace3cb04b570df0e767a5dda0e558b908d296854bb02ba4790c661bb1f84d3730181ec0ad5b32ce2baafffcfac0e3b50e885864ebd5c3ec4ae1aae6774e476700cb3c0a2e9af218bda34fc2db1612490305f4dc590fc61d3aead676e85c16439b1d991f8249349b310cfcc7bf5625a61da9f4deb506c43503a6d49c03e536c6bebd70c44e72cde63218aec74245fe8d20e92a4c67e64b82306ed5736fe110510f8ef7d068039c4b0b9fa27679354271b
+TAG: fa6ee1d1846b2facab3daa94fa50610b15850fb3
+
+# DIGEST: 4cd92ac16a807d2ff180df75c47d848749c7ef46
+KEY: 4ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b5
+AD: 11060c9c5f3aacefe61b18
+CT: 6419d65313bbd047c755b374ab46155499c53eccf14d3f4c9885c871d738a6ea9f15f63099045e7f81af5de13e161caf54d19a45f8693a0c1f2da28764f47bcc214744659eb49698eaccfb4d6a1f52e1daef9e8845460ff2c5cfd702f72c6667358607613cadc6e94b0b9ce5afbbf2bd18b5698c4f8932b8825dc6f4cb0dc89957d514b3439d8c760816a4d39e78abbf36cc19bd9fea6727d49458250df7c587966926feefb89578781aac92ba271b5f14116e4a9ae9f858dd7d6068dc9161e88f48082a6af6ec8f0570dad665ca02a56fc96dc1e021973bc97c4ab0
+TAG: a853e815d864a6c9ef3aa1f3cd4add104790e679
+
+# DIGEST: 64ee218c0c96ca8e2d2e50cd809d61ee109baca6
+KEY: ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c445
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f
+AD: 3aacefe61b184ad2463939
+CT: 069ae98037205c7044bf0afa3692125971755288c3beb1ffc4cb471bd4dc20d5ae838bcc20098905e19a1fae620cab84322db0946e57840f9dd1ff5911f0763125f2943ccbcf3b7e3130fc363b1ce073d472a22ecbe58b51497b8f069ea7ba59d0a5b186f7710ab3c781fc62e635b65abd24c71835777ff979a5575f7d36075332912ccda68c5252b9cd45b2fcff84081ba2e136e2454dd58123714183439aa78e1fb2b2cd4d956ac832dd7cf5fb05ddaa0fb9c39b44c4128a27468ae727e96bd6e792731fb38d847aadd03512b12faf9ab09bf4b8403314f3c21584bddcca5bd676989e
+TAG: 46ff903a15778aa34273a903ff37a3a18c64db6a
+
+# DIGEST: eef8eae201ae4e5af32ee74bc724e13ae5ed3978
+KEY: 3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a2
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b
+AD: 184ad2463939ed518ce97c
+CT: 434eb612539fd15014568a6b1eb7ae957a8e5256325d6b235be52792e63be39b88d5ccdc61d22017a73d54b2586b3c7ba42377c51275d0300999b359a4242085256611ca8f84a9d373de8010187086d1098af5c6c70b14f371f851c463556a680c26683206e806d00dfec8a95bd99727bb9c9122b3863c2fc49e00181eeff08a0c3a8fb7d14772df0a949d2b040a399e051dc0b767c85906c978df93d4d9acaf70d414a56454d5513ef1ea5ddf98276f333c9418d52274904872dbc92dfcf6b477a211740279744a0a6f88c73c59a4d09a44c8381fb8ff2efc5ee55f7a7628ee5db13f2d
+TAG: be3991f1c4832db5c08ca9fdf358611f410cb85d
+
+# DIGEST: 2fe67a81b41b094a708ae515e28bcbde3bed724c
+KEY: afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12fee
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad24639
+AD: 39ed518ce97c3fdd293d72
+CT: 34ed75b8e5eb648e16de93a0a3d678c456e2b3aadc994a8dbe7f27041fb86ef6ff8f01d50402756edbd403699dafe73e8aa4b82cbfa558a96dcb9b2cedd0c370ccd06939c97371d61d04d85a903cc9fd3115fd31b6a8d3502ed7a3838b3f0c96b01964c97087eeb67e44c9a5577c52354e497708f832854f14095469515e5426d1a4b3e16251d63cb6dbca6f817c0d2b577e29adbb1e644e3ef5a836386e768f3d37bfeec1973ff2c1302eba5b682b57e85156749e260b908a7a96e7a1c111220721a119ac7a8d6edacb4a46749a2e5e230bfc6a881adca1d62acc915b2b131661146e2b902ed46c69b9af20
+TAG: a1aaa47705eafd9737dc8433130d5236e5b91adc
+
+# DIGEST: 33d10d6cb5dc80751d0f8e370925d7c86cda331c
+KEY: f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce9
+AD: 7c3fdd293d72afc09ffdd4
+CT: 662d0187be8d1d337523445b502c3335fa20f095c3e1e7efa0c6b6433c1d4f9b9fe84caa3c887ff84cdf789026fc4a39982880532e3e8cc37b14df298a12be384794f8c52eb8e4b6960e33e826949594477f0c9fb1e2249df4f83f19879d952725c06eaac526c14ee00828c171a0d57df06504a7ebfd64ef69a49b9d4ba5b68cf6d257933a317c48da3157a88bcbb7a3109deb3d734cbb2562003ae7e8887303acebe18bec9c4dc981472565ba0855d1d81ef3f63efac52f082a012bc98f8ecabed9a19b734cd4886c809dbd9f8c71f890d420d0ae490cb6b850e137dbd5701018f0af1fd952949083b1a1e7
+TAG: 8be90b2249b6070bd8b68806643fa6b94bf047a5
+
+# DIGEST: a29f128842a48debb60699ae0df0da9a9b5e5dad
+KEY: d299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e89920
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d
+AD: 72afc09ffdd4f41963249c
+CT: ad8879f5c6ee8149ce55b0d308d04ad638ea5a1ddb77e9dd8c84b94c852fe35222414fef1027b58a97add291eac103debbbfe939df09ce27d8a7685ed95f9b485d8eb4f413c20273db7f4248aea56ef48ca362cc0181e011500b61a146e16893e5f56b8856fe1f2bb32b3a06cc6344240efebd8961d3198d096e4180de6942ef98ff4cdefb91cd12f1d2bc16bb5906a29174354797e6791db461bd7cd24ca79ee90974fc04081ceae85222cf11aac40932e5cae151be81f0719b312225ad0b35475e5e39210310088c4987567ba3b4bf258f3afedebf8f76d1f4f5910035da683cb4cc1b257e8e0251f73e90f4a02543f858cd38
+TAG: 0296cf58edf6f189bb5dc7591c33e7cf123aee82
+
+# DIGEST: b5048d1efa7564966b6cf1579cfb4ad8e9460660
+KEY: ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffd
+AD: d4f41963249cd299b92e55
+CT: d010afb06d69e17b6e2916a6b9e7fd5eddf91f4fdf411af9f745b7346df6912f86fd0f032fd2182e2063efdd2d481052aac1a623f8ee0c4e8f5c8ea97de8a65404ed3da338076b6a527462c15f296e886bd6d9604f4ead7339ca71a5a392a31a4053b15754a11980bc61906ea934a35ea7dc8ee7a4a6be9526e3494284e15ae79c1c4abeace3f5d110b6553fa3e1aa6a61a109bc9f308dcee32b4a68c56fe9a08f78cc6e606ce15f53b340c3d52e08362dc55b3d00419538e9ac5cb0fd87bbbbc2016186ca7f1ff9288a9e374795a8bbd578b26b809fa4f9fcf8928d96f75609c12769be2f5c8dda26d08473c275b33a0fb9247c2397bbc9d734673c
+TAG: 41f8cbf79ddd4e4549bd4a3c897c293031feeac0
+
+# DIGEST: b6e68f5f0dfd8ceab56ebb657728c9bc5129fdf4
+KEY: c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f4196324
+AD: 9cd299b92e55ca24d8c078
+CT: 02759c0f5538db2f15af1fdcfb06ffef16d86e12e7c52d060a91c2b98e4c301300618f86209b179b1ef79a3543e18776522b96107818dcd51e4fd207dd4ad99748225af36a342f6ba23081ae3217eee6686f66694727ccd94a5a7f5661b68a0ecde3c06208905b431ee81ae5d5e3bd0138c4f205f450960f8e54d2027b9b14ee5e5ae302311208aedd474aaa476b0c490734ebcd5a949251e2b3ecbafbaa75c4b02910895ec5a34ded91a796ccdbd8b8e79b6cadf73b356b8c19ac19c09a99b498d739f909da39b86344255a34678f3ec869ce703e4088f8253620c93327d8bd44f436bcbcf89817b19b0114a4396619ce226592afe596307b1e3e44
+TAG: 559a8ce3236cccb72f8d826254f4183ded50f8af
+
+# DIGEST: 853bc7b9fbd640cc0654fa5533ae302e398bab35
+KEY: 13710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e
+AD: 55ca24d8c078c49f78c7e7
+CT: c7ffbe299dc13468c02e7ccdf4131565bc71c552defa99b2c72fe3f3a472f97fba7ba99586e2c6fd195c4abb8e5111588cdda4dd1f18cc6d1dcea60483178e1e406e5f19f6c94691d41b0b11e13e34075c1495c87a15a00d393446ef9c3f3aaad35addaa87ce0e1ee3398262598ec44157fe81f247c302e0db13b8802c7a8afaf1a3189043ca22e76010ad8184c62ea1700a513359d160f48f6204ce303ee343f0c7d8c4ace5961d0601d4280123caf622e4463cfdc2bb392aea1c99cadd2b5d103e4f3fa32e12335dee9df20d4146c927ad3411e4c5fb1933428de395703d961cd9121a99deef6d1f9cf15fc3f2ee3e37d16fdfc1fd0aad421244b31f309ab0d5374f46
+TAG: a2d94e2645ef68ade510d2b078b1b92959b8197f
+
+# DIGEST: 286a92c480192206a2153df1b6d0eb26e6507da3
+KEY: b8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c0
+AD: 78c49f78c7e713710a025c
+CT: 3cc00a29f84d453f22814b53acb5841579656dbc4ba4d97370e1c941cb7c176a55fac6c0d465816eb323c0516a0f16b7870feb863f38df1fc218fa7a17ea4c8c8143f83be7597638a7b475ab31c59bce238bbe731c339d9116054b689920c4081c2ce28f4a1909cdb944e0c2f8bb8cc918c2fd75590a147658491f33237e2f86aa598c0757511739055b8e2dae8a98abf3b86c069042dab3c727f2f9a1ce7ce56b3bab7709861152abf2196eeeff3142b959f6a925336a67fce2d7983648f7df46843a6718d7504d0076a3cea75a6a464d59abf00afa42ec9513b53991fa35c4cdb3b302a0fb1968d4d1bb54ac0df034de5b506e6ddfc800610c7654470eb119c02ab4dd6e5bb623cfe1ebf0
+TAG: e29902672aa6b6b90570d8eea222e5e933515704
+
+# DIGEST: c2acb0c126af5282abe14058066631fd0c658571
+KEY: 89ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c69
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7
+AD: e713710a025cb8b9d71d29
+CT: 1d7982e3a2cb25c3c901714a1dec6e4adb2b4da2a8b92a6171ac22fd52d9c7f2bc1b37fccc72a1056f02beb556d77f4ec5195c15fbc1c0e35dc1ff57d2aca31dcf7f5fb655adb535a14c210255d80948c1df76d6b18713a0c2ec26151bbc0edd40a64908bb502010e1cad69d13af3875e2edfda77cf58de3c04f48308fcdfd6843a76157a2c339bfcb511e5f56b511c4fd71915b1a994acc657e2d430bb590bf407f00131dd06e6d67161703738ba5f6c1456926e82ab29a79fb081786ea14f6c089b27bf1d31d956f25fe2255ea962c2c0ded796aabeda4c557173cc0b40b432f9ae4ba8baeb5f5f5ceb7345ac2d750c27859b97dbf9918b6d6fd19fce9f89a709e7ddf4c2038be992bb402
+TAG: e239f703fef0a6bb390173093fddd8baa283f9ed
+
+# DIGEST: 500e5f2a56bfafb2d93e26224c9c2df562589f23
+KEY: c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a02
+AD: 5cb8b9d71d2989ab33e978
+CT: caf02bbfbe730d0adee907f73f3c6d302df10a6495d2c1c97b5cb0ae984fede2efeebaec895f2164a5895d085e7c696dec9a6929e3ee4dbd94f7ed8e9befbd6563d591faf5057c020cf27e22a6127838038016af79ad02b2f04024954e1b86281bcdc26f05e2b1f328837069172609962faa4956aa6155a5426584e7290e203c93fc1749dfe42a5c33510750386768a62fee6eeb7d9af751d3c23541f33761c8accf40652e7e747487f854594573debbb06e50bb7e46ad1aa7572042f1ac4b2c2c087c571edd4ef74a31f2b21f481bb46926600d6501ef13d24c09eba31bae0df9d5d431c752e454c417937a087ca9e549002f3bb7ce858ff0757b522127b26d1d96fc166a2683e7cc41426bd80c46648649f552
+TAG: c8093b5e426868c9e3d0aa6bcfd738fe1ce59da5
+
+# DIGEST: cfa6a42a2cc0ddf1c7b20031c95e331696bb9ece
+KEY: 85a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d
+AD: 2989ab33e978c4451e3be5
+CT: 8b4ea8b6549d734f4676313476bb0c6ca8787cf6d3cba5d0720148e04411db8bc205f61287fc509dd149f4221a0529d7dd10cd60bd0f861d1114482bddf2542725d44f663049840531cd70ad43df4fa6758ef6cdaa4c5c472b7b458092dbfd4086129dfb6f17d1000a36eea4aaee651cafb2e597ad019cd9c37abf1d177a4da2215504c29504de35086143c352be087e98373310bec397d1f5db44722be75d3f4251fc7b95acec2b67ce6e0975be1fe0771dd30a4723d39c2f5faac04fa2ac6051c93ceb4fbdb316d8c95f306ac653080327725d765df4776327b4d04dab6e9f1f296a8263cf8542ca453e95b6ae694029a02b42964d88ef7edc10420a4e78fd0f370d72c3e5e9e187487700889669bcfe94a213
+TAG: 435cc125c99f6d4ffdc147da46a1370e3f79d1c9
+
+# DIGEST: 2d1b27948de83e32a0fa5be7040d896824ac1fe9
+KEY: 2feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e9
+AD: 78c4451e3be585a29a2af1
+CT: b761bf917019eed719105c33f9dfb47ded79f85b3f96bcf0b2a25c624055d65a0bd30d14077808636dca1181f14169f60bfacc14e54ec103d617324c87b890e36f33d9a37d9a7e706b9a28728dd3a157886e17eed711bfc30a109925b9d74018cb7cc21e231741f9b332cc54ddc2e89d777e97fc04158a731a178fc5a55f5e9a0cdaf672b5c31388684042558916a5d0c929afb486c893c2a36960c436d04e923554934998a5c177e743edbdddc70394e78925b7539e939c90008553acb791701584eaf2485bb8ba19a949309018b0c9b5e345c4fba9816766ad710ed0db8c304e72c448f0adb4cc70c43e1138ce417b0f6f380a6740452f8f809da0d200458a08d8daf6aa073cb4d9a5187cf2036a4060caff14707fa966f02f510a
+TAG: 894c622329fa96bdc1624027e00a76cc89f7098b
+
+# DIGEST: d35ac8b9ece76d43f1497ac8681c5077398bf2ac
+KEY: 63b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf7140
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3b
+AD: e585a29a2af12feef71e10
+CT: a0aafcc6a85c5270e19bded5ada3ce9e6884e94c40ed70ce85680c2655e68912e711404cd577b7f3df76ba1cf7a92f89ab0e4adaf9a0eb25068abf3c9608199e4ea0b2bf5d9d2454fe1e058005837679ecbd3e1fbb880ab33fec110f9b55157ce057afb96dc8b864c60dc5d1b39e6052a3db6aa8c4bc6a726fa8ba20fa1a1774903a5b1d3222236ce00e9cc8e0ee7a5091f91dc8413f562f741f1c7809e48f2020819119a77be04211b5f3570a0e2b1d40f11e23064dd38ea1a2e4edd802c71b907f828bfc9fb51366d0790c508e4dfa455c72a669399fac3503cac1ea4b048a70405bbc3ca13b90d706eacf065e880976247884b45ba112cc71f6f610cbad33b5a89efa51db8451247bc7f80c39acbd3cf97fada7d063a8ef45f20efd78bf48373cbff7
+TAG: 82ebfb084377ee47c5d7897414f633045775e1b7
+
+# DIGEST: a3b33fa67f5c471a60a63dea915333550bf3af04
+KEY: 99200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bac
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2a
+AD: f12feef71e1063b0b4e6e8
+CT: 02408ff8a844fd105df2983bbe68dd7ebd45e9b0073ce6b23189e98f466acc9f693a01b404516c628d2741d5b37466a33a05975976902e2464f75201053b92aaf5bbab595b70e86e7087dabb8787d772dcb1cd6e8db502f59168fa26d806eb6342d3ec05b1906cecd68da45878f5d8b4946f5a7258d37ad3db0a3a27c22eeceead70b3514a9e33fb0f854e330c0dab9f7d2d97facff30a7d2e4971c06b05cbae135c8f159d12fffec70b8a5ddbfec23735cdc4142d733eaa0c3fa577d19a7ae08685e2edc332e06fb334a9ca07efae1089486525406a6f7b3777f1692e4fef8ea48d1a4018d4c262e72543a3506fa879346c0b25909e20f531acf35c53eff8376b8168d22d0c84853d66fb123fa849db9388b4780764cdf44bf88027ccede3816aadd850
+TAG: ac07e5fee69389005fb0397c9bf105edccd3eec5
+
+# DIGEST: fc45f684acf19a1dcbf767f671396e793430d7fc
+KEY: 3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cd
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e
+AD: 1063b0b4e6e899200304bd
+CT: ea9a7f46e1abcd5228f7ddc3343aff2cb98c500d4ca0440f9d88cbe5c008165d65c9263b7e62ebf405acabc33a784c95398eae8779d5896d69b6954651517758db7cbb0a7916872fc5f33a7bc3f840a40188fa9a77af02e49b7e68f84e71c39025b4d6e4fba2b619fe1f84976c2df2d71f77d3629bf475f6b8823a0c4d89fe87b723ce2461f990249c32dcac08757e3f595adf6a6312c5c78f8db3c00f6d154cc453a8d037fdc9f8eb874ea278090d5d4db2562cc11e01846a77ee05d2f9d6c3774ce0fd3c29ca17f464d5d27f0474f5da8900c6a8677b5c065f2ee3c251d4343d84002404ee7af254a0475dfbd136874f81d0a71b6fec585e437756a000f30edda7b392954a34f59381a3da471c8b9716388ee2eba972b721ae9e3e235ae7671fed245b1f6c4931f3daf573
+TAG: ed5e9603d036ab0b1767979068c7fa3879c363e7
+
+# DIGEST: bea3f11679bacd98ddd996236dd603d319aafc6a
+KEY: 7d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed0
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6
+AD: e899200304bd3508132a02
+CT: ed8d7304d9aedbfdd669c8c11dc881b706e45a3430659081f7fb24732d1d3b96b5b2a011f2d44df44814a6215fbf5678efc410f5ecca4b787aacd2f1244d890f48d748659c7ff25e8ba5f487c85308b331f92cb7394be079f6bc2762aa07328c2002351a1c9b3b34c04dbe276468e375ac50e5b5130575d40f051e698361d3fc85f0eaebfcd3517a461dbff1b2ca6d2e932bccf36b9a490df8f0305d27e5063516d3849c062fbf1fe374902242b64860b6cd71dafca08a8fb4fd4984c25c736b6f1cf8d5d862e9e12399f756dfd68d42f8f7791d2bc89cea27bdd0d3c73c7e3acacb6fbf77872a703daa63c20f23674a410209d96ef52e6e9dca0683bacfd49cc98cd6ccbab221cc1aa0bf195d507c7bb678f960ffdca7d18ec178f4ab1c21b7221248960727694751c0c33fb43baa4a714f4f87
+TAG: 3a56ed03df7f802921cacb13af8f0fcfeb552460
+
+# DIGEST: b0ccc9b5ae13a7f8a01100af61a34be7ef6ccf6d
+KEY: b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3d
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304
+AD: bd3508132a027d1ff4c047
+CT: a27f7a6f40bf2bacbd743882a2719834c88d28d9035215ba6b8877a6619dade8af89eb10d0daecbd38dffb5ed92888483bf547207d22a4e5896f8b9b104b272621c0515061f9a62beda4e92d14a5ef515149fac74b5c5fa0bf56e5dba3298513360bcb27e36357cbc02c5725a2614e5bd320db4256e3626fc66808d077e8b8b0eef256df46a5cf9ec8826ccb64d5e19d211e2bb0ea67761bf0faf2f7b2184e5d7c4f9ddcdcb050018523e799da45fa1219dc87773fcd8945c78a8336a6748b5053fcb9cfa5bbbf32d0a99f7b6483582d05766f7a712250499143a6a979a86f1f791d61bd840fc3b85f8ce65cdb78cfe3bb0c987dec4ea8ba7b684632e1a60a7b1245ebbb4f81f7ed773ed8cc79d47acb0e48d2bf853450812560d581665a2f6c1ba974457c91f7f312b9eed9633096fcc2c7f47d
+TAG: e115bc1a3bcf9d5100232470709a8ffac5c46d71
+
+# DIGEST: e2b953c833076a52442a7afab46150176c47b730
+KEY: 4706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a
+AD: 027d1ff4c047b3ef4f57a7
+CT: 78aa80f37f893c1dc21f20d518ae59d165eae38cfb3166aff256dddd657fbf8f478d623d1ff87fea241c2ec531f05449c77c3d9eaac53846193afadea6ac9ec104a1dd47b460575c61c42685f33c91ce3dc317e91bcb5fbdf17b5a777bd9cec373bc64618806cc5c1bfffd06f4f9c136a8d1aaeae5366317ba917a4a549c8b2980b4d44510b593e88f21fac625a1aca325a8ed79915b51388b2565e530c99610b1074daf3e4c8642f2c4623fd717fd1c84e772c25c99367960dac5d67f960faefaa305358ead95919c12116913e9ffa397132944091a27a148195f3befe9e507716086027b927326a9a706f38a260fa8a2d194ba50fc64d788ac647b756b78f33739319cfec7716fcf98e049249d5b3c47e1d9b6824bd7001d3e824b141e7d472c5e0eac99930b3b0f80b8688ab469bf2961e3d284f96e4720fc04bf
+TAG: 2aebc63532a4e6b2820e548d63f52642c16e7bab
+
+# DIGEST: 8e84935ed1bb79dd38ae38924952e1105101533b
+KEY: 1c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c0
+AD: 47b3ef4f57a74706de4b38
+CT: 9beea2482ed4e87f301b5c360af4a181050cc895f96af12a7fd9d696d845e4e9c39c95d716db5e96741dd888a2c9bcca7213222a136037fb3fcbc54ae922206a3256f7871cb99f5a43732cbb0adf4d2a76555e6a4e5168c6759b61d402a6432cd3373396b3dca9f5e1b282e99e94ebb51857a8355af238d42b3c84bad7c8b48faeb081f648c8067144334a712af278559123c5bef34d8a40f11d239684bb7961698aad69b6bb2d0d93681b647ccf17fcd3bac2ffea4f818833a6e3b0a3f4ca23f6c8f43b9adf8052b75c6ffa61ff449b1fe20da621953fb3cc62a3a6a51136bc02720aa74b0e9fea462f7dfb3bf5ecbf014bea5498c375e07e6fd473a0f96e06d31cd6ce8a0bef0dbf4feed11be7ffcc162fcadf1b52070db736192f51935f895b2c0347fad7000e5465ebc9a975b482db313df596443c5cd2e94ad7
+TAG: 16bf10e9c9f277f9f85e5a465512bd3822aced49
+
+# DIGEST: 99ec6b669dbedbe99548117f37189e669fc5d8a2
+KEY: 101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b1153
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57
+AD: a74706de4b381c692ef164
+CT: 85640a969f9287cb5cb08444124807b42aab51e2b2ab0c9dd8b66d40c1888f2bbd2cdde501bddccdba759887eaa74dd7e04b2e63f352412c39b3c41085eb1f8e085d7f43b4277b257557557024275da5ebd9b9448ebca8d21b22a8a62901fba946a4d640787b6325fbf1b482ec5a9a493f9816c292c18ef4191a7f646ef897aeee62d65f4e14e83444dc42089d1851bb92b8cf2e7885cafc570729751986fcfadd45be98e2fe6a4bfd31d7f99b9f625eb949ffd0102d2828f427e9311af63f0b2c734ba0fb3a2e61484e902288a528568e6c9c22a74d02967b3f6dad74d83870ee68fb9b3165fb613d12c2e98db15e23f2b5b0ae223387a369ca590a12ec20f81804edd1eebffb1deffca6b83240d53068812d8b6de4b5a8b6c215e320b2f73ef68c4e031104d4caef1a25c125a58373a737eaa1387527f5b1b6afbe36203f5bfe9c2a8e
+TAG: ca36ffe7fedaaa28c661b2750759715ab4aae9db
+
+# DIGEST: b55f018cb06f74f0a9f76e65a23c1744ce7535e0
+KEY: f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b
+AD: 381c692ef164101b89b476
+CT: dd8857dcdc3f407b615e38dab8c9805b5e1eec446d43ebd98dcde611cf7e73c8ce0d3c94b882b089566f0adfefe5d12ef9a79e6914c084935374ee72fdb565bc05bbf4c5185963081e332dd691c39eaf677838a7c4736eb55ac741faaf5d84edaef5f319c3a42f4a3c4e152e7d7bc1d01f9b30c2bec803bca56277963d8b3cafa482f089a67ce2a378275d2c5d2572b8368bf684cd75bc21af2bccc2ae3f3d5a8250f19632eb77dbf8a0007604c2aa432e2e775dd835290ca499a649c9c0e40858ce278db056c4263b11dd2b842ea015537d28497714661db4f6fe94a80d8414f5f651b8a752fe93357fcfe7fd60d7c843834468c9a41372064735f8a58242a32596cce9db4f9daf89c80d5ab4f8e2a4b4025f1fdc8f6e8e13f42bf94daf4e86a8dce092954cc9f049660470d884c03fcb09cb5db4dc1822ff9d7f18f4d9ae5d691f64f041c0bcb64f200bc4
+TAG: 165afd8a78f51c0fd9b3b8217409cdc7e43798bd
+
+# DIGEST: ac3202e483c67fbcdd751950e1497feb3ebacf52
+KEY: 520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a8
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef1
+AD: 64101b89b476f72b27f06f
+CT: b993d988c55b57cb5be8ab951b5a5054323f1ad55a6bff6252f466201f773473edf0a2b33bc2362f8ce01d99975f5d17c42b11c81ec1c06451ed74ce3ca5239eb0c756b09dc605b9f8bd9fe038687a99c9d645f50df1c78cd627591edba6601b54c84c859dbafa21321ef4abc122daeb3e87cc0ba3c9849b5d62e0385b9f5d404996548ebd02fac8eb55730f02cc843fd6e1b99a1b2f4fd0980d1c466a9be94adc1ee4afd9179dd745b5cf3edb7e343a5facd2033bf8daa8b039098f041b51d3d15439590ac686282df2d214546627b4fdcf9aa24932dd01f5b01d10a8cdf50527b401e17d8bba0163beea29f425761d8007190e7b195a64af1324c2053dbea5763ed6e4933a178982d49a9d4cb4867e1efe619dd1de29a2e1342f04adad88c627946884d97351d1c67ee3f927001b5f35e595ef40138798d613e07ae5d145565dac034de15c347149caaf99
+TAG: dff0c37999c6737db145fab4a31a029bba1bd98a
+
+# DIGEST: db82ae5d79573da2bd7215485a92063861879c3c
+KEY: 71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c67
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b4
+AD: 76f72b27f06f520c9267cf
+CT: 1f7e488dcf405e8d8a6475718354005133e6801cb39959a371eda0cc70981f886c982c85d69c1bcd9e6e8c2f03c63dca22ba22d951e1cf9fd5f54bbc8f4336b80072f8548106970fbe4a00e97317a59c9725d00eaff09ae38761b1f01941fdab07d95e3adbff674c1a9db46026bfa09ec648239d4e883f96ffc80890c06070dc9ff7cc31ca850e8619045abef74c0978b1fa585fcff5d00ea8168f1af17d18063d8dac5beb8dd8b7ce23cd2574cca2c31bd2412806ed1b82f1d4b7ba7072e52e15ae4f20a9cb4aca53a212d853401bd09a63f40408805515941cfa3173402663de0495dcebe93ceb9154b3ed57c015d4d1591070bad10194f88355b988a22dbf1cc4bbe39ff3567b5dfad7c806a7354f0e978fab21c3a8af7ebf1f99f56500f65586a0f6b0c45b6917ea51c5145575679295af5f171d8247cace787cec9a7e9d9985e483723f4b103ddfbb11f6e4dcb9482c341a
+TAG: 61df47dd4d561c27ed65be50f936e846465ad99e
+
+# DIGEST: 902d703861f9872e7b6482f854709a214aa98731
+KEY: 9bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bf
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f0
+AD: 6f520c9267cf71408a4172
+CT: 9835391a91a08d675db2ee1cdef9bec9fef0520e918b3555858a9d39f4b0aaf88de033e902a1d025cf6e4e3a2bf9484730bc2daeac2d08d8ef198c8f0e4cc99f65741543c4a4579cdcc44fe5f20b64d6f3d68cc77c3d9fe150916c1cf8364c513fadf3e2f3b958604c9ed1fa41ceceddc8b4840a9098c7cb89bad01e4eea5539697a17940abcb2952dcc60a60582a96d5f8450859e42bddbf32dbd41007f8ad87c579722aa20a39a804d61d6bc7ad5cbfccfe2a9e8365658212944213ae9e7e7a764078d0c871d31f758dda7ff012cfd55a2971c997019bc24d37010e7db7159d4a88deed965509981ea447369e09dc437ccdbddc0f76b5827aca8fb7d6d159cec2b6b57eed832aaf508953cd58aa104245b6487a716a0db466ade98085394289ef445afd6dd10fb7fa6bf0747e4c11f482a552c9edcde9ea68d65db558c6e38a3747684a0bb5622211b7b860b743ddf670adee58ca4dd4166c290f2
+TAG: 91b47e596f06d0263cc60f14bf4c16811e6a0ac4
+
+# DIGEST: 4becd26b9b5c7bf831523f44cb72c8e50ff8033e
+KEY: 72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49d
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267
+AD: cf71408a41729bacb5877e
+CT: cf28f31b6370e2d3b7e7d1e7a61591099edd311277d440026c41a81172f2fe78595dce07b9853b879de6730790bde8dc13c283dd0d007a26aa587ed9fdd55cf28d60671ef85e6b4731aac6e31b64e0e31b63e51f4d90ec9ada97d80c9ed185d460ab581167a5927157a637fa57e11300be1ed2b0a8f36c886a59f2fd8911213b889ed2d111670ac138421533a71f6f9e165da6b4fc1cef541db35d26cac57306d12a09a603af22f8abfb3700ffe4201b444a7de75f0178eb38fdb6e9265bfced71cbb75fa8c588caa899b45f1ef6f74378edc9f7d9ab33ad5ec441b5a81696d6640fe2bdb302e6df3f0c6b3aa274eaf15100d8b3e5a8587f01511a9374072387de282e11695565ae9dd5039e433be5833fe10645645d5eb645ca5615160dabcd8302801e61861907422b5946ae518f8c5428f7ec2ccc3e1dc29cc1f319e9e1a2de3659feb4862b835615c20b3316a9eb867a3a3be67bd316b9c7d25c
+TAG: 8512d6d7f4b995072e9245f31df90c9806e57a0c
+
+# DIGEST: bcf4785d0e3b34c55cb2505b559fdbd525deaac6
+KEY: aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b97
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41
+AD: 729bacb5877e72cdfcfa76
+CT: 9e0544a68ddd604d2199108e4bec3fd17e0635d3cc44cfe31e81716e90053dab65e3a2e65324b85e07aac633e57ed3747757e8a6aa898f1c917ed2ffd4bf46cecc2cfdda6d187165f6d6fca1b2ec8947e11e3b78c067e69f519218c1c1defc7fe1634b83df70397753df9057487bcbbd09802c969feaa2adc4257338944441d78cba4bd8c601c92b8d44c950b12a565d2b07165ed4706207d2ccacba3d851cdcd4c02d5d3110e7a8e61ae8cc1c0162be31df5f4e9a2e7e88cb1ee6b51edf758f3630a9122fcbbb8979477e19d12e8ef500589fbcd9a3d57fa11103a69e4813bd426d54772c2c3a94234d9e030916aae54ff48082f2c1957663021dfe335225701d062676c28233e5405bd5dd5d78a49d33de19dae786b627f32c1ed8099c0d2900af6ff7034dedcb31dc32fe16aa6daa8e763e336c675c393dcb575821d1968148301ad88fff913bbcd38726cc20fab0e4ec9a168b4fbb86368a0ec4e8346c4fb5826a93
+TAG: fa7edcb8541048dbfb1e7ed670050d37286a5af5
+
+# DIGEST: 13bff121568d7c32b2546132cb4ad490cea9303d
+KEY: 7c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f47
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb587
+AD: 7e72cdfcfa76aed06707a0
+CT: a125f7708271f724413c30a2cfb47a0ce5ab26a1179bdf71aba612fb45d9d08e3f004501070ed0992dcde59c3f247a4c0ac88926b705ec95929337f83f75f03d3f8275b8cc86945ce07354043303101cad7d4492fc7e79ab084057908f36623f7bf504d88e40f586c27f38a28bdcef6d3f6c82f55094ccb3a390c8f847435bd512657e1b79ccb472411ff9eacf5b7959f5d8fdcb0342909c3997b54a391bee7ac17d6023d2749a2bfc03279f354c24c7e2bbad69d3a5db33dbb594facb70ab0f25668aef076dbcc38729255539b0a71c3258307aecca0fef8481d2119baa4da7b9425cc9554365720ab8cc989a3856040ab6c3076d5b17a5a5525360b11b5164f40ae45a14150086cd0d9d7d62438ec4603f1cb0d37868322ece5f8b662c2db2c01d2cfdcecaeb192941c4d552d0e720f8894a6b5fa9c3945994c2dc1b5c3e3aecdc891837d32d56d668fe0825459f346b55f8749fab08e33d917bdfd49c44418b2e2df6
+TAG: 7b3d73202448992d2e60fa805ae91da335e6b221
+
+# DIGEST: e0ec91f0baa3c5fd0c50f135517909e26c204af3
+KEY: 19fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa
+AD: 76aed06707a07c3dab6997
+CT: 4620522fa922ad1c109fdd7e72bbed6af5cbb500e7ad342153318569f9b9c64679e62a95323783dd8ff8554b9d7e1bf8639987f0ddc36024b678257d8d85867a0c7099c4df600b5d82fa1a29b02ac60169fdd49352545c1802ce02cad363341e779feb7bfb7b6efb9bb72e9cd3bad5f661e10146eda469c1c5a44287668827f6ce4177a7d30dd57eda8b64c60e299237eef7637e9a9715298f9d2cbf6fec1a4964f54624189f56453a532030f59727276c628864a6ab4742d4f0fa830a73485b1d308f3aada4f29c4ce65d1b695a0044db415473a733f822c8814aec498d8783d84c4da17b9b13f18ed9721a381ee29b29a5320ebaeb0b72a3bc756a7511560a63a80f93a2ee051689c36278a64579d60f50087a55e9ab79a7a2f2a5a49ee31835205bf540474b893311cc0d10e57ee7b3d5db12adc35c37d7951eb2b5a8831d8ac860a25f22c4469bc5da7be22dec424187561493a6b0aaba687e01a5a9be8ec31492d6a263eeb529bae15b
+TAG: 6a196d99256fab0dfaa692394d20f5c5f5aef052
+
+# DIGEST: ee7d6f651db434a281b5cc57c2c418db731c65df
+KEY: 2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b17
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707
+AD: a07c3dab699719fe882eee
+CT: 5f9a0ce63065aac2eb142de993023141755e120551f9b0f82eee280d9f6c8294a99f6015cfa2824a58b2e072f5a5e0cf624a6d10be31ccb78408fc4de6dbbeda4271d913a8a0d94c0da522473442cebb2c17d39e776dafc9c339b8f03b5821b0e6358a60e8707a220bf94ead4cc613159857174ffbece4702c1fd6ea6a815764311917c9fcf8c457fd6f79d6885084ec126172e629a68914ffe68f035093e0f1b5dd1718d221207930e380195faa5b3df86e21ba4db7e3f60ae3da641b557c843f2433a295c0490ad05744d3c51ec7271d548fab1f13c050adad0ff21606cad85d5730c7ae12b0f9b846929a1691916ac20ecdf7382f6f83ce1d16f69703bd9d60054d5fc226c7264959e0a07989bc5cf683ee0f9c3eaa5d071e52e5f4e477e1bc625af537af1a9d131dd6202e57646c051ceb235c6b6ce9d164ed1d63ea079f024322b2c1c666a36328420f5cd664a7f26bfb3f8940ea1e36daf466f94a710ed21fd31c6309015421e380106bee468da857e39b
+TAG: a6dc72fe43395d1061d596d4f71968c6ddc01064
+
+# DIGEST: 810e1f01bfcf6bc13ebae7861454ac133b2d6cd2
+KEY: 11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab69
+AD: 9719fe882eee2fee55ed8b
+CT: 048e188527cd839f4fc4d7ee6f21ac06c1a9fba38050b6d8fd45b958696e447efe78466a0f34e5d4c9fded7dcd42316ef86f66962e54b2c8495d67a098f4e568942a6401bee5a44d4ed5bb4e6ae9dffa4fdeb618f9d3fa333ddeeac248750e20a1646d51c226fa5ef63cc6d13199f81973efd3f2ba55f9317623f317da33e16687ce9ab95f532af3fd10b62ffd181c60f3cc622578d8c17fcaa820ef67345de78ccede187b6f0c66119433f0264994007b0d48087a15c49fe4e88a88800a75702b4c0d1ed17cab715205ba7ba4bc387a2eeed7ef0b4358f1d2d52f7874ba17e71fed166443e38aa9b4d99bfb2af39e485d10d75d5320e15897addfbdeb731943778afe1ab3c9d5528c84c9d9ddb58c7ac4b4c5c183321853ca84299ea8123885ca3ffc3947ab681b5359ea83f30a16358607b329dfa016cc7b5ee73d005738ff314835d9a4442fed0d0e7b8e4b165f35d7e5b78b8d743c8f3e6e0fb351acd07ebc3a012e12a2eabcc94b0ff9c5cb8d7500790fa5
+TAG: 3c76dc6105cda6576ddbdf2efc62ce97030f1ed1
+
+# DIGEST: 881551d50a849b7e81f0cc0d722f631e32a4c97f
+KEY: c695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882e
+AD: ee2fee55ed8b11534c870d
+CT: 1f60e24ba352c5b6655e78292b84baedce9a3e9c26c6eae21c4a0f3e6d6c9a989cd0cefa8bf3fef1a4b3c26452f9add15c08dde77dfb30784a3a919c55901f4e1cae8236b4fa04ca4b64d0f10c6beeb289fce85dc964cb69f46668cd9d422e78e93c749fa46d25dc4c6ffe09b427b303ff7694ea08d667902a1544d60f55f9843d4077d938cdfb31a07af8bd8db28dd004132ff5fdf6917a787f12360171dbfed0c1544f4b4e1aa6f9da799047ffd2626bd8da9619588c957f0dbec346bc2a29e1e50b52642859f66486cc5235d268f3b75a81c81efa50b83f74513891c76b889183611808220b8434d1c25c201425238a396a4f126b9367e3e4174f0e4b6bf665c6f2fc75e50f306687b87517662293abe1c6b921886a5a86b8d898dfcc9d4504ecf80294e4b5137f6229abb764a9227ab564d788d7c3966c220f36880ab316f7b2cb5b670a4178b9800909dfba1004a07aa35e6b604622623cf3cbdddd23ba0d4cd6cd0b1b87fc929e8a505a4e7e3f07345bf3bccda2af56a8f080
+TAG: 43dff4a9fdfeb97629c25e784a32eb49e59b8461
+
+# DIGEST: d525f72dbdbf54db80ddeb9c2a84aca41451353e
+KEY: f1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed
+AD: 8b11534c870dc695b814bd
+CT: 96bd8678ac174f2113b58ddc2409f55e233849a591f7c29b8e98926d4d5c59ca6ed22a695404246d65b4bf173d5c17f3287b21bcce3d29a30636d6f2279590f512bbb3a61c49b5b883fe0abb0bdf9a056448c90120741bf588a1e92978f5d5a3f6faadbd21583804de9017144ef0db3209400d12838434981adf2baa3213f63e62d75ca551818efafb37f158b0cc9fbb0214a556b0318ca981054c18b4d73709b6fdb6a48f162a2a0aab9d908b3c7ba2d13ff53ae64faac740193ed1f97bb5a13b41e0fe8201410cb888eb765ceac5bb20858eff5ba890a449938839a74e8b79b67828e1a0ff2353039e71538d9a5918ff8bdf47fbc0ec361c4b1baa8cf17fd6260953c61a920f5cb6a672d36ffe61612ff6130cfdfe41e6b78abc659c4f857f64f3c64a00e507ff21e3fc61015ef915363f45666167b058c822819e8a526316348c872838cca368c4ae38173fdff66e83c4e1bcd63d355dddbc9e63a506738e85e97b44a47db81a4d7e5468aac3fb4305e8f0e35fb76fbb89229268a50eb74dfd63858c
+TAG: bdeac9af53dece2c1c0de2ff4d5d5cf5105e3f54
+
+# DIGEST: b25882426b4730205533cfccc0da1de1f6f2c459
+KEY: 2c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d7
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c87
+AD: 0dc695b814bdf1a87bb105
+CT: 579c28d0e7fce65a25ef22ca8ee1e50b7728904b7977819c8a8e80084fc77fa15e4f1cbba0480dedfa6671434c58b52b4086979db38ca7eac8a5d47b5806e8f2ae41975ae2eb7ad0e00a3e55de98e16e3c9fc86ab28608e5f264db3a961d876fc673d43b7b411b3e06bf552114d5c0a4112e0781d61458ca15ac549dcdb8c88bbd15fad5b5c704c5e7b4f55f7d0f67eb72a099413bbc909f04085d266cc0a9d3f15d2fdee96892259dc34b43cf2a0f5dfe244fc5a6f840020b3cdd0859e9b4f552e460aae3e80f30e5c1f33599af834a343621b86e8b79ca09e7df8fbc307fa16fe93d81348454f26fbc0658bc19f132c41661244973bbe6fcfd00a43a0b7ea4b2633edcc281aef855a2dca4fb4799697f93f3b300e97cc2ea6a0a2e6350ddd7b93267c3e82b76200ac7ed7a51f24dc761a9741b7c579789ff79835501d45ea74b1aa8a9ae526deeeeb34b6f3684b303569fce5115068fcc38efe942e95232c594b1a8ff70010da995eb20dd56120411e96fa127588077ad202e4813d323ea0736c94e47
+TAG: affd879a5c946a7640fbb4e2d472e081b8e706c5
+
+# DIGEST: 939442486c730c2cbd8df213d81310e50534f06c
+KEY: 16bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d80898
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814
+AD: bdf1a87bb1052c6755a7a1
+CT: ed81399356ccf3a7813536e8c7daa4fb9fb23a3461ffa23c4feac92057fefa6a9d6c35c25b8e1e19ad8cfa541ae30964f9bd19d111f40571bd63246d736015670fa35e8c79bfbe03f19e102ab2dbe890bcc0c2ee152c30f99c209129729e265a9f497d40bb206c130f9aff0d0700c7cb71512b5e2dedd62cd1d6a3549907861a91015479c0c68b49bdcfdaa711bb11d1e09fe61e11a02d50189b6ddbcd4fdbe5feb19b0435a35003814243001e597fb02a2bc0f70f967674c9a141ccfcbd2a3d91f1794925e2c485d5589dc9ee94601f570817dad04ab75ebfa21339bb41b451213ae1b71011ad79737b44ec859c3b2fec5e344cfbc77f16ff1314232697a95e3a7a47e3880c7636c9fade3d79640fa4eb71fa2faabe5ed9ea92743cdce899ce62d92cf086608fe9fa8ded1b0e63d905c160e5b3d492c59cb67e8951e869274d14dc78f5fd549d19fb39a27befb6eb777efbe5e8a263de2e5ac9dfdaa0e44dedf32f15e899c60dbae56177b0134a7d311d0334cd4adbe2fc3e94376546ff8379e220749e2ecaeecc9d7ab54a
+TAG: 7966f9795c627d5e808e4a73b204c3c655204177
+
+# DIGEST: a7b522c0de411517839342925e8acf703ea12e8c
+KEY: a49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea37112
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1
+AD: 052c6755a7a116bfc9095d
+CT: c842affd0db9acb0b1fa690c58195e0bd26c86a645607c0ca204858f40430e217bf7cadbe07592c3c7684edbaa46f4702523f12710b76de4c0464207744947a92012e6638c65b2e9dd8376140da2dc1edefeaf03b1c69c8d28ec8fdf2c780b11d53483f60f436e8cdcdacbc94797e084f5c1d76b5941b209c5b8f56ae6855ea0570fa221fd16dc386cf3fea08b17af147bdb86c026de070359a5f1e0042492ea67596981b34a4b318ad9d174ad10729ffb9664b46dffe80c90dbcbaf7da29194fe701c297a9082e00bcbe0d7167e7b4fdd778eb59fd53071ff15878b4c5871a69415f697d383a218236ebaa3b9e1453e7531021b8dce4f9ce2df6dc676b27643e02d39d7dcf79b71d57fb7b9d2ea5eb010cd35bc3a8961a1cd2b1112d390d40346ff01d2bf801bbe25992732024896dfd164c140cd3d8f112a5c40b548e498e6cfd050ffa2d67fa588b264b9f073f91aeb468c9d1c1a794affc85067dcdd756448a21044b337ae8d661f59eaa2f4a15ed7cf8775ff761ec9c0e2e0f8083558c46a04d42d90f1e773821c36ac
+TAG: a401b46e4fe944b49ffe8e4a2132c7f00225ee9e
+
+# DIGEST: f61096694be30b85b6571dfc8b5bfc4d364bd225
+KEY: 4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7
+AD: a116bfc9095da49db3d71f
+CT: d86fbc79797d8ab9e1b7a9ef560b59afeb48ca8068956f7235297566b72b6d747a4cd2e0cf6ce78e59bdfb48c2508d7e8051fec253edfa33c3d124097a5af2f2beb25a3572401ba1498a22dcf30f2c91d31a5268aab6cf57a1b08caca948d1ef2d55e4a9350d539a620ecad97995952d7f99db82390f7cb0e596c59032da58f06de0d52b3848bf01c5b5bdc9688a90330e1b7995bd5156a775d886ca5fac3de1697c47c7076f73fd8232500c97d245565375fd2a2f398aba9519b66a7b880ad760ac822255146895a5e7854e98467ef8f20f12a1615767c7ba7f109641950cacdf22e49fc4277542960954a6de3a3d0e81c3ea98773ef28d4f2f93fa0b36189dacc3693358f2244f98f22d29d3d5233af3e46c4eb528fa74186542cda75291f9af3eb95f8a5ba622252f541af9ebccda76ac7fa8088be72379f6767551b4245f562dcdb4b0f1ec08c214966e6d8c4de5763a8f54d74b67a7edc83f1d4c81c7d5d9f7a114979b32b35393bec2c9bfb8ad180c6172144833fb9e9f07bc18dc7fb205625da03a5224acd4d6ec248b529295b1452740
+TAG: 3e32fd273ff4a18251e8c6da2bb025e8b8544dcc
+
+# DIGEST: acd9a5179a0ec782a63bc824188d838776bc1b81
+KEY: 3f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc909
+AD: 5da49db3d71f4b975c5d50
+CT: 2c03706f44019d51a43dd345ee21522bc48f76ea4de5bd65e16787cb3bc024d1fd6600bcdc2ea94dbfb9b939b28216cf9a52825f767a5617c2849f999423b2a4e6117b51ca2bae722975ac503263525759fe6ba7ea20277010137de25ec258d370a6d3e7e160238f07863b30bc38e9cf6ebe31d3c5dbd3b975046c48cb9b3b1c8756e3e396993ba7f49d15661485e640e09084219162654dbc9cceec6cc13153809f60aef7b56ded6640f3962738a1996ee0716a0143c1b8dcda8384b994f415c1bcc21b299d0e50a3867e9333eb8db49bd0d98439ea4afa8dafc0a3d7a4a6dc1054c2cce005d0a758aa2e6c951c8836e90ac6264a894299421bff8d654830c0c1f96fe2469b17c76f55d88f31f228b466a2ed6baac506159d80843ef75347b303cf194b9b737a13ecd07eab0365aea581dfd6bcdcb8a65788452d12d8bb63619ae949c872aa8fa9048012792b1a1ccc6c0b21e9f5865864aa1ab770a5fb8ae34d7fe28586aa624b1ba1e22d087745a943b73636ea3e14aaa081bcecf845fb328338a1a5cb2c63ed09d004ae806a49620b58d68e1438ae5eceac184d
+TAG: a3eeb77b2aaaa01216a7719aac6a597f7e36d81d
+
+# DIGEST: 152118d780c866c5eed3a08d2d9960cdc5acaabf
+KEY: 8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12d
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d7
+AD: 1f4b975c5d503f478b22dc
+CT: 6905a38b7101d66c121399c45c25fd2927a302c719d2c07bf516c076e5bc6dc15ced29b1a8e7b7ae98bd76078d09f6521ebbb9d7db384cb8eeba2f157979a35828cf7a5018dd03d38961d570a0a6e5662ee60f6be865c2cdbd6044d87b481b23e19637d05eba817430e1a9e9c06acc49ac1c6a0a9ed3fc0b26159143c134acb1f3084fd0c729271727548d84a20df2bb9391bc3abd008d391f33a5b015ae34613a1bf1f266ebbb4a06a0ea234c8b89dab2d8a32900f1775c94ece7c03c3b120355f62c8a8f368bf23ddb9ab8ae316350dfe709ddf24d499082d4c61084063ae1609c1aeb19de2becd8a54ccf3d4c6af8b81c062b2fc20f1dc61bae6b8d6bdf7449594f146f5a29c7a45c334e3cdbbd59286d06b3b9bcfe4aeeb97089cd0ddf46824440118e7064da58cb7a30d60d3ac2733818c157320ffa8bd93295ba7499fb7ba3892d23d6994ba0d0049111fb7be0477a8b3fa0360e4f461049b023ad16a2997120a8c9721eb6a2ac1589bee7a326d869764faade0547893a44eacba6e7ca3410c3cc29dcf5c164ff17b62e6e4481ea400a30c5f9232b923987c5
+TAG: 42aeeaba0d6782f4494e30c6d33547fadc0be100
+
+# DIGEST: ca91b15125e07b81debf75ff84e7eed4da5808a0
+KEY: 1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d
+AD: 503f478b22dc8253bee6fd
+CT: 1ecaa428115b590cf1e175c4f8bf7b42d036550f620b8b594518526193fd5f24cb763fafec99ab08ba81a89ac592e04e8b8ee7f18469bcfd19e2ec65c60203ab2c031abc272af778d2bfa5098444b989102349e2bed405e4eda8d1c7e92d71bde05d85ae42b7566ac6959dabc73346fcdbc9417c937c828ef8cd2e98407cff92c32f288059aacea152d4d458fc5bff26e342b5e40c51c1293c9179d43287f1939e1e4a4d1dae80a8025eb2a4b4dd797d578a19202a7454687379307089b8a4987a59b67204770e2e59e45b9dde82b53c7cf6191ddb0e3351bf43fc972de128b8a615c541d3828612da0381375f171c9f341dedbae3ebd62a58f031a68fbb6526ea1811842acf9dba06bec164e77a4ba9dd4cef9a939b3228f41c8124a5079a046ebfb0b8e0a6aca18875c4363a46f54377ea2012002d0289d82500061791bfced04f39c01b348e33795dff170cccd462c6425c492633154740bffb4bfcb5649a96af54fefc76073b39622fdd38d00080b440a07bdfc199ca727fead42f927560380b944b4e21dbe64b4ad4542a1f1fd8168541d2bc094ef215b83d2015256c2ff451c9ea
+TAG: 1b44a1372c1928b835131fec54635aec481f8442
+
+# DIGEST: 93d06638fe1e836ecdf5d30db3e4fd0660d9d701
+KEY: 01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f43724809744548
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22
+AD: dc8253bee6fd1b174c307f
+CT: a32714b057f0a6976c38b30a283e2d3b24406288add659f11900a39378291dbf71c1b9656b8f4815ce297848ab25c492ab4539c4ac70c21a3065ad49b5d7a80a1f757c084cc84e7d3f6132b85dd8f450f050b9cb63eee49cd8e4af716f21119173e53ce84786de262e5b0d1595dd2f901347bec4c00be909b004139ce0aeb502f1485f5e6b179953ad96af5d73eb280400ebfd3bf9435c4fd9c43f8af0447e70c9d9a05c8bb90fc2ebe2954462a7a5fe3a0d0ca91f65bcd570d24cbbd82b2d23169c6abb64efe138a1d3f206cde8606c73a303c34a77d2019e8354ee75bb3d4faebe204064c481fc58709cc6e9742b62f4ed6cc02081e767b8c5ca1f81ef8510ed2d6814a14ae5b2fe0fd69cb132a0147db024e34ef526664b67f47ec97eeaa42a0b2033213ae2c8b4eb9afa86ba4c6957a20a02c5c5678f46c0695c7923ca3bfa281dedbd3ccfab513b742410e0e9d4eb6c32dbce9a566aab928252c883d2f1269a81264b28f09a264b63212f832e256ba146e8e194d4d35218628fea3c225cb396a3ed5a549dd50eb0779eb7d5bad23c2870ee1641b655d791940e62cefc0c5a75b2f48671f568265d2307
+TAG: 027f5fdc0b7249b7f6d5291d7eb020effd5d6d25
+
+# DIGEST: a12c8aa71387379d0e43afa0321979e018d56547
+KEY: 9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6
+AD: fd1b174c307f01be95abaa
+CT: ad53040b1f2d39edd352ffa3f7c2bee725c7c5a95a5c3a9a3b189f45298e763ef830b91c562a567f16f4f8950e88419c9c6d17bf96dab4d9a52dfd142543495e9cdfcb48945044263e3d47706644149e1f133a259e0ae01b8f36921a6555cfb3017e957fdb3531f26cf37f64484fd02d13c749014ecb134a4cd3f0e3580661b44eaf9a9694ceb1d5f12055483715ff7df94226226e2baf1b835661705303ec2a49cb305ab9935c755e6dce98b7088617017c69fb4383b6e8a0b89dfde0a798dc90f8d286758c21fb7546e47a6c489db61fa01aa9aea7316598e7e536f29d852ef09ab538c1db4f9164552b5a744d0f75a48d556a83475ebda7c6e04b28826b7f08547a2b4d85b8d986f81d68f6588bc62b639febed7329b994e2c244e9c37f35dc7abaf805c9a698220c463a29ce0191008ad39abd133c59d4e699fd79b5a1b8edb0c448b8c2170d2401673659e1808cf67d44b0561517d0ae1d84c7da3172747d5e61bf5b50430d55dcd5df3f7257dff64fbbcdcc2af84edb04ea0ffe7ba23c20dee69bd1754d294df1ed3a2be638b2256989a75cd56394242eec3c33555a1f6dff4b81d0380ad02e46da0a
+TAG: 818e204a564339b5b9dbbfee647a9c4c56bca1b4
+
+# DIGEST: 8a524c3ce814e3059b4c7a6ac748783ce1385c68
+KEY: 2305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c30
+AD: 7f01be95abaa9bee585777
+CT: adfb293df114fd3899f27e1f8ff585467b2e99c50dc3fd4b0e1c9cee420541e5c2a9bda905434711f5a6ffb0c0d22dac841021a2962bcb189c2b4e14dce830d34204adbbac032779140050fbd8f531f9c67eac989994c966b0cdeb2c2cd018b0ebcf1dcba1311a978508b48fec30e1619b54030f8b2f104c5c98df5752bd5c5eaf3f957ff74178d43bdd4e1ef73ccf5f411c7a35a34691fc76b195884e4b5a861ffec3e4d4c0f39dd8144983dac4f651ac42de781376194ab1fb1feffcefd82ef941e87ff6f3645c8b86e6b78ba90748cec8eced5f2160f04d8137816b65903d0631855b8961b679956f07111e3f911e4ce55fd709c9c0028791a80faf75d5f13f38e7dc398d25a6e60388c87fc5faedd6d823924b61e3dad0d95974c955e34d0650f9abf8567f3602b62851936af67984339b8070c1c86ed87f433571d5e8c2eee93c4974c72e698da4a786053235f2fbe9d93fe51decfb1282efed58eb0de91156d06946bd7f1d06b3a0481132984c1ed68d407214340fe83efb9ae6330934a66829d5410bf7b40dd3bebc398bb7be276742d7dc0b51b62c444ca1482045c79e36869b23a86a15cfd79a2e47bf9367f9679657
+TAG: ab2492511c8fc94d8e2d3624b8c922ad2ec4ce2d
+
+# DIGEST: c31dae836928083019ab6902865d9f14c88fe27b
+KEY: 50d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a56179
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95ab
+AD: aa9bee5857772305daa4b5
+CT: ae447789e7f899988d7156b6fc9472468af03c00dc6ca394524d88a47a67ada94e9e851c12b9d3066426a1ab23b9cf21b8c193f66304426e32d539073de6e08cb9c5fa2923913cedc176af8225a238f5c3bf697347e7c13a33f11891ee741446ec5b972686f9e3eff25f749642781aa323d85bb952d31249e72aa7b0f3cd45165ed0572a7dc415996dedd4776e626459487a68d8fbcba8566ea893630535e10d0b5346617a310e582c4bb78d7761f41062553054425b99075bc7bf604a22d6e87c84602ae8d44b5b1067f7c1b0584d80b3d2be7054bfaf3be923677528f61c892e741c2468347ec41ef27f672117bd588462eccdccb3395e31d20fbf2267244705b4907ed85022b767374d4ad05779e1b8dc5c6196bcac0b482c0964e4c406c29e3ba3888b60551e7a27e17034012a891b8b540d0ed3bf82709eeadffb58accd08ea02afc1d6a5bcfae160dec16899a0ca7b7977d9a93869657cb7d58b6302cbc664400430c550a5a5e62865abcc50447d2cfc4200e5300d81b1c5c7a8b1e526c4fb96c2b8ef59c2bf6cba5dc88f47dad6d4bdf02add12c108c659de1951177c06129e5c5af6089aedc51aa3e6ad954f5760c36b
+TAG: b99c3f8d2786ddad9968674dd638bf3fa91eade0
+
+# DIGEST: 4b2db052fc8a09f7a0c26afc66dbcd8ae5c9bf62
+KEY: 089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f311643
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857
+AD: 772305daa4b550d75f05d8
+CT: 9cb162540153657eae0a8fdef64af0d94f20b838ec1fe250294f8919d49d70441fad4f7f5613aadd13e5bf0da947cb23a1bae181fe70da12e53fc9050ea773bb62718ff9841382035c4e0bbf77ecb0df7297b5e2325058efea121e78998b66877357e554018ac5c3011c971376cd50ce9b43bfb2d851e316a111b209fa389fb56abb674a1b07392d2eaf1352e2da821ed02261d5188514bbfb1b74f48b1ce9986f8f0acd8e16654881e28a4b9631f52e316aefff2a5f53352659335b603025d86c58fc18c4025a474f87bd6afc069c5b317d48d840c6d374c2cda4e66502cea13605b007f415e9b51d13630f01c604952f4af68bdc4a8fac43a8c0dccfd22ece5e99bd7f0322195c0066c5b8b6651d36a631851d9caeb963813fb218d291b1d1d703cfb47ab0bc949b2a245d22cbca57945cc357e1271de83b8f4b84766e98f1726c57a0682e78d7c4f2df89072917e634fddc5f5844161bef816b40945477f1200d57eb2a48938d9ea8894eb10c18675848335c9067e92ba3aa28038c18c8d5b1a0338a0206243d568ad8e403d2132ded8ab5364392ac6f712b157f31a17193eaf89a90c36617010472d0ca6bc01eb025fe877e5aa3abe3f97753e6
+TAG: 5be6679684115c921a3741e79448f5c773574164
+
+# DIGEST: 881926d37fae9095362fff56efadd9fa3c455ebd
+KEY: 711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4
+AD: b550d75f05d8089850fea3
+CT: a47a7370a3536722c28135e6721b731acd648eff5e3438a9b7587e63566cb6c47408c3afa71daea9e90a2af1c4ce231d0d51106ae1258793c79ef355c827350a01b32b9c77aa2e4815d409f6a40755ee5421a48643d39bd8d584cd10368586420229061a201cd804eed227b039d14fbeeaf3b768f1380c6cdd1d6c819c8c065bcb0e43b448e757dda123452e4351f0553257580494999c7d9355d6f1a8965b429e8322cdeb215430d524dda10f1b85c2cd7dc3088a93cf4c6fb922f13bb569fbdf4ebb9ad392771058ed8a2e41fc0e276c76182c36c35a0235306cb70f9bf40c57ab1b8e74398584eca10b05713fd1c0c580f1eff62fc54a8e7d7339ddbeb1513605d6da5c6c2bcb025ffcb00eb92e709d4461800597e58d2684083e7d1b16c6a45654674677bd785b5f0e2daa9d282f94db4283f9a1648ef65dc38b238c7a58122bb4dcf4be769ff0fb7dbc412e62fcd875334390f22f82533eccda89593b52eca8eef8ee6b1edcf9c91b8bd2258007540028f86699e8ff451563c6adc62ade020ff7de6a0a58a5e1511aadb91a56eec10dec230bc05fa1ba9b7d3b394507fa1eb221397399a625da14f82f744468c75cb7b9995cb6b39d2a043cae7e0a393df38f5898
+TAG: a1948eecb32734d870cb49e3f755b695718b8715
+
+# DIGEST: 92d143942e6ef5b44ad7a4b8e71c22f1ecaafffb
+KEY: 2610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05
+AD: d8089850fea3711265bf78
+CT: 79e6fb673b8e28503d4195e41bf9128add6080cf49b2c899a8faa6b12237eaf7bd1d7c24b457857896479e3fcdec2bcfa342e77b9046eb9a7b338d803cc3320fffbbc5a57cd5d46c5c1689bcc323eda5a6368e1bfffebcf4bd330f87e82886112a9fedd396dc221ddbe9685c31eca34783e12cd7d6fd323a7d5c6c0b9dcd9ed8d44f157552c72fb7eb4f733865a80064f5b456c4c57c00163103205e6391996ec34d33c7fb5f015a9a6577eb2668406dbc794b8f174821d27b17f8b6be398eac7b60afe0091a4e108dab59c93c910bc9ff33a4f26632e6375287d63216793daf8ffdc91f24c47c526b3e555fc86e5033add22a7245cc034a4309ca95af93fb618004073dd5eba2eee79ff318a3823e3e1469ce57eb4c26c981bd2f2db7888ed23c965d154f1576acb4da3d14189d9ae1d86ccd48b4c34e543a88918c6468d563f170c32b394d6f28fe0a10204deea94d023abfd1960a997a3a1f2cf73692135a917765f73316ad5b643a980c8c25db0666f53fa09ebd35e8c2977fd65606756c433edc1b4c873e4a7fda943f991d31fa10fac66a6952ac0a84e03e9e01341517e6615cccc746c21c221d29627351645dc0ffd19fd7113702a9dbab25429aac3249c9bd28
+TAG: ce8d5a357f97b8b1efef74441256eeac568d8b29
+
+# DIGEST: 7fcec4927096421498e91df912cfe43b2e971d4a
+KEY: 24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1d
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fe
+AD: a3711265bf782610460bfd
+CT: 8289205f7b42867e84796a5cfa5c21216202eab11e889530f145d25617278284b4dae14c33eb4ac40a685c2c8292a83770d20eac9fbfe8c2c2e4937ce7b82215399c3a6605f005513a8dc3866a9c5e1a98379b07155a49767e51cc3ba8ff8c254553f1e35b7d894717deb92db7a3ed8e3ed28f9d9306780e05414a0944198fbb97504ad59c0f7177af273382a58e6039378c60fc25416d7241cc4fd23c83af29143be0747797276d4e3fbb36df003a98089fa81114e865461cd1afa098005f881d5bc51acc1775cca6d0ba773c7c0c2062bb46000190f9f0ebb90fa575b14bdbb9cca733b679070a7b8315e11976c72ccf82dbac94d75e51fd935445248a7838c9176ee6b2730893f7c9938a073049f71cfe86440713653f9492423a5c68e7ee65610718bf8d7a0dd3447cd7c7dc2827c6d1b32f7f4541477ad51a64195a5dcb2215073f719e53b90b9dff91d092f47668ab6440206b1a8d87e474fbae41228cfc43d6405205bc5198bb7e24b7beac464ca038cfd7e855d6b26ad0c76b95ecff0661833083965934c7d8d26b47e0daad1f153cce07363f531ea4b37edb5f049f88a4f8e9394f65e9e37770ff388adc6f3c4cc5b394fe37d316955426e87c807711abfc1991adc5185ca35728
+TAG: 366760f0493e3723d9b6d839dd3242cff0268151
+
+# DIGEST: c1c6273ce723df9f2033c7150d466c011bb457da
+KEY: a12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf
+AD: 782610460bfd24ba022e6d
+CT: efa5fc01608bd42df1a0118169da12c6ce53ed259fe37dcaf562c178557bd4a116bbd3579b382738ddf0114d90e26f7d8b5f4043a7d6e157750dce5fe0878079cc8cbc86982da0b33b5e8af5033dc71d68c71d7f34c93ca5af160845cd8597b90c693bd5ed700c4710b7ccb8ae314f926dca32bc3ab8df6d305140d7404830d31c485edd546138c8d5e675f0019876dc36d40a10142fc209ff8a3c2b9be85651135ae0db636967993c253e869d6aef6f3ed29be3d8cb976390ff6286a56b59a628f2ac7a68406e096070dd446f71f60c4612fe01997d89ff29b55bb6809d22159ff039474b51600443baa82742282008440484bbd16c0ff92339e577781b5d84201fa313c33eba1d47e21f264370b32aeaa20a06dabb7a6e4a98b34b9c1d8cb171dbdcc9632cbdf7c2665e547ade3e4cd78f996d243e3d4548102ff340f50a7c23caac880070a1fbac1d3f1bb571ccdae2ba85ce4f28a7f1c1923ac45a53a885361a3cb4c7408334eb0696745645c912d32b9ebb735af698bde327c547c4e5e534b79349c7faa325999900ddaa25712e0c139071e6a82600d04a0787f5990dd28d4d65c140d6c8651794999e368d62b62c337454fe74622104eeadfa098d5a3c424aa87f37bb74664dedcb91e965b761a1e900cc
+TAG: 27d9c3f63fb8f31a80817178460c3267198c9e49
+
+# DIGEST: 11424a64d5ce78fd71b30a8070aea071d873afea
+KEY: 4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460b
+AD: fd24ba022e6da12dd4c27f
+CT: 31db5824d6e3df47be0d38d8ae50105cfd5bb43e2f62a7997c28e4d4be40b09d48f020d9035e4595f2896370ac62eaab2e1d6bbd26fe94a21d7e5c09c81cde56d501ca2b6799594007eb0ade5c580e818c58a6323fee0c46c20162261cb5b3ca54c227053692a38c26452992b2c6f1b28a0e46220a10d45183cac1de4c49ba2c4a77945ec4b33ba939468cff3b4894086e797870225109b7bf7cb1a7ca9572a39e50bf2a65c97a18364bd026b435089d5cad842a41cf386abff179fdecb260628e332aed11db3f14f9f5b7bcc096ae4460b29797a10a6e44b184315e5b9fb3df6dcddd7d0d0b5d8d185402f1a2691738d5b368f9951ae2668f3306c44118f495d6e777ee7e8d3e5f86360e8a460a613a7f3a36638e754e8b0130673daeca1a67c6c812b9a66e5c07eabcd03a8384fdcea6055c31a1ba3cc4f9673da321c48d8b8007848328e6f026d8252988e50690f96995071863c1d493f326040dba4826b9e734e440d378cf82880f96a95ce7c54d7e59a18bb7fd2a997a68892fba5a05040ef03b86b53f0b3710326d1e2094a26dcaaa17e55671c941735030e074788a102bc930f9dcdbcb29cca4fb20d309f1c38e132f9bd2b55a9955797a870965c73102785340c871dc51ed8994903edca258de6537e3
+TAG: d360c293324f0f7cdfaffe9642aae9f7bc42060e
+
+# DIGEST: 6b7295febce7fba8d79d1e7ab8fdfc452191e2ba
+KEY: 454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e
+AD: 6da12dd4c27f4372480974
+CT: a1d0537c3bddc7459a37268608d30ee8e15377c922a4300d7e7f00084cb45a9ab7cfc7f89dfb68f3cf7defd102012361782e977e22c12ac1d91d1e093a21ab26bd171b426af9af7b2dec9d1f2dcf78f19748b39e9b0736e24b44dabf677296db10dc28cd37751d020e1780e5fb00142e972baffc546b9b55bd0067e22ffee4f10312a590394a296cf6fba3456b3c0a64b662d232f185a41762bbad664f977328bba56b62f489d33821d4d604265c388b5ea852968db95ab844c7cb9498bd28d4b055760f83fa94f2a35492a4dd03a1fe9f0c2947fedd44b96948447054e2da7fd3b9d95bfcd0cfe3d1c909e84c9f87ba2a50c33d588592ff3c7c7b56442d52683e222f2610b740a2187159b05f2b15afbba7a97ef2dcb30813b89393706011397f4aa3c537e91fab098ecbf3a87c2185b9001ff1a78e104fbeac85bea4ad609bf1571d83969934d483794944c2e6bea9d778d2deac2d6344106c1dc30d56251faaab3f4dda43a2ed8c3345d9773e4fa4effc5edc3a68cc423b539ed63e8b0605b58aa881906e38b38f02a4df3708e9de4333056c96a02ad6d235636da61fedc631f705e771af9f522109a4d3b34d684b3b175d28a389ea574215131aa68016ea9cf3664b0baa6491f85d3a4370f73967e4c23637fd1d131597a4dd30
+TAG: 57b4a44498ea09294f2df51a5e81adcb3318ccd5
+
+# DIGEST: 1dadffba439570155af2509a548764a93042d23a
+KEY: e9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e97
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c2
+AD: 7f4372480974454879c41d
+CT: 98c951eccacf8dcba5b819312f0ed234ea1cc06abee5f70888558000c2857de7411feffdf379c187d327943c63ab697675557a62c68c13f48d3970531225d5fb6c1434a126cfd6ba80b8f6dda08b3e3629ed12f7bbb45f45148f8544f0a8eb70c849260916eb62baa1bd850e082ad69ca5817594e8f26f63a1909ff03f5696b7a52f146af246c0c6485ea5826c89471c04fd6c373e9d0fef06f4a7b01400962ebfa4ef4166dc895619864accfef9a4be874111cb333518b33a3a2565d032a2434931a16e000d01e35317338ddbc48317517367603697a225d81fc63fcc7d4b8463bbd24910b4972375a995e13baa148b644993b9a7bd706ae64da00f898599957e406c1ab15fd44b6e85b41d47ffaec8136a5dadab324cb0ce95c738a1f8d246af90d98a68b8ab7003d74aa29591b58ca7b2dc38f21f4cfbc04f2e239728e1350b0f074293a13970b264bee368ff98c6960a805346c19702983d3ddfb6306f24cc7f8224e553b0668180787e48ca8e5d851f84df71d5ce6fd7815d39d7e3941b8e0562af98e6e244216bf418d7ca2d9e29ecd3997573b2c4d92aea1a5a82f2272af1218b379ca40a28cc7ce09ad60028a5a6aac6ce145cc3936f89a5d34ba54aeec8d99f84ebf7367fa5fdc12def2294fd3fa3299ba1a59aacc0d7f6
+TAG: 5b77267d53b2dfc87a936ae08ef7a3f630176553
+
+# DIGEST: e654b4c78e1c0061eea2996fc126c9bfd41eb6d9
+KEY: 3b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c9b
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f43724809
+AD: 74454879c41de9ac9f9823
+CT: 5a1c2b7a8d5bc74901521e1300567f30e2b7755f004ddcfd8fe64f471cbaec4bc6d445ea931bafe6ad78034d0ac1d3916f1e0405c2f2aa4b193c2cd599d34b86029840ad379b136aea5c2a74ea70e22e8c8d1e017a2f7d47f8ebac7b85087075c28d6d2846e357ce031abe09e03629a32cef0b205d631f36ec9a1c9c4e90a80900e01688c7298b99be65f204ebaf312364bfdf57d9e16b0142e879a47b9ae0e96fc62e90883624ee2dc110f3a83ab341f4558f360df399170bbae57cb2eb377a87aaed9755e8057d76609d447a33a8255450504b71439fc0d03e0fffb775019ebf921325b42ef56e1b454b5c87ba5daa1f0d0920e860eea43c913d417cd9e9b6676759a4e2c71b0180b432fe2aab4e4fcffb51b4198ffbedbfcdb4dd4e105847f5a5832e85744f34bf3b9929ffeb177ceb4c5e68585a3ff8fda6569921b3d093a2f1d77e710f78245eacd471af88da8ff8f268293845a9a8550ef34e2bbff9d6cf55b18987c71eb98803bac42b0e6c062015fafb754c6a75f927cac4a8adfcfa8ee05a3f115f1f90d734f78180aec2aa621fa7908d350b0cd8550895cf4b5c3cc75eb95fa574f9a91c1f5efa61f054bedd9267f10a08a21b19e63754de10a1bb0c4ffd8c5c08558882a2f98f1175920a71b981affffde44ae1c9281eee161c4c28f32436
+TAG: 32b13692a2f175644a0e192d8102dd9e2affc5c1
+
+# DIGEST: 654b8591c7f0506261713e9ce7a6fd24a6b9357e
+KEY: 61792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c9b66262c0f03
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c4
+AD: 1de9ac9f98233b5a7379a5
+CT: 62d0c56ae3e695bafc3cfa3c2d8b9d17ac8ff3b84ccac28d568c1ac84e1574ea06f31605caf86d4e809e39e9c275eed4a8f27eb00dc78e1c10dae719519d949dbc22e00d8644bc3806e54e6531864ae4cb5694002e2a3d7146b39b0b38acadbf1651401805f6394831c608b0478d496cc939b24aa3d3e6d445faceb798a69ae1308a593244645e242829f64f7945d0af8af0eeb6d391c69c2d5bf7b00e42092b36c23362bdd627af43ca7336d88cc36e95ede07b83afb54c8758678d19e0ea7956d8f26776b0f4b6b637c1152853651b6c130f436ffa2d4fd0c344e7583c5e56d6262f43767a1011d8398311dd6e3d7f9ea89d3eb3f6a1a9cb98905c0761fc5be1d83005fb9ca039b877c30b402743bdf0109ee5de42eef860be676a399a206c08dca8e757f059f7d9611137039b9053430e7d6406abcbf7aed645110aae84f758fcf0d225738cc7c90ace5d83eb9fe65d1e65efa4f6c9d808060cb0f72605e3d7c70e0d13d84689aa1e44aa4dcb152f230d456eb6cf520898bb249262d30c64fde02d6894f72ddff201e4bc41c5fc1f394f2620f764d40098292b04aee45e26812f3abf9a020b5215beb7938e2c121e809ab825d22a2d560bb9bde47572ecb891dd49b38f41af9649dfbdc83ab9bceb444bacdfca2fcbefd623364d4e255e2c0f3164ad9242174887a9a11a
+TAG: 8ac5d1d13e83f8502a3cb0310bbf46b24ff42e3d
+
+# DIGEST: 1eaad32c8d0cefaa5e2c503bb2185a73e6387fac
+KEY: 16430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c9b66262c0f0368fe9d0cb7
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98
+AD: 233b5a7379a561792c0f31
+CT: cc269c9aed42c9ba90c768710fa03985372a219f391327e438b1593af29aaf2b66cf8fd60f137d8ce8438a7bcbf7c1c7010c06636f191802daa26fe12ac1c1458baefb2a51fc7361b2d98311c2eaa27e046fffbb76fc855ac01a1321672658e394043367e89478a789d662c88e91642af53824097326d991abd62d1ab818452fc152aa1bd05032027fbb691886d9269937f7f57e214a2186a191b2249ba6fe79b69a94623d85ef0db6b5c2363627ea15a614e6ee42ce0a26a90faaa3ec45451c69c7d472d98b0376a95503b16c6f17eeeb42e0ad5c8775584819aa01309e6071e6b9494da6ddcf992ec6bfc81e0031d74353afa042abfe62fae02792bb6dcae82694cb651689e4039208bf677c90ed6245606cae81732d9d32043e5435f8c40cb76b55a03593dda1271aaccdbc24f18c9a881c77e1dca0e62bfdd36208ee94370b166d66203dfb90c8602dfb48159410840c669c47e7514bf91ef603834bc213173458a87909979b3b77aaa77262e1a634fcb40241818f544f9d207e91ca1f46f77c5c4f606398938f764080dda0978c6b76ce76830a15098870e72b5c9f4975b495d2c5d969688b555773601ad8c857ca8c38565674539fa71a8acadac5415b563f55811b0c010ca1e6793ad08e6c830a0ec2b385402fb8af3b6f0ea0b70b458667953207e4d44f1959ecd2
+TAG: bdb2e683ff8bc7d20482e698ce2b608032094cc2
+
+# DIGEST: 862c0517b3658e9b9cd27db608d49e24e9b4667d
+KEY: a058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c9b66262c0f0368fe9d0cb746bbd55813
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379
+AD: a561792c0f3116430e8b6e
+CT: def7eba4397065d05a7a1b742179c1d8eff65e7e4ac18bec49ed020a95497a58af4ce62679a36b77f95f72913c2a58184ea0c3b59b60784bdf63893a2a84f76ab2b6324a218361316971ebb1e2850b6c7baaf9130715580626bf298f60d862cc4b9c4f353a9e4c7536fd697ece9407eb8ad434c97e325cebd5aa0cf4a5342724f2950c8623aa3a5322f2e06a6b1d71a57b22a2f85ed1acacbeba192cb29ced37983e4231bb930c07f7266728c54e8fa9a0b7195975095fd714440e07d63aa87778061a361b4d44f0241a504089b738cdf3a6323b7a709d39637a2c61677c1f034214a4da6471a89425a5cc6040f37261b9a8e55589b2c24a01b4379dfe00ce758e9e617b6d15abcf0974be46d151c5d26e69c50d3fe68d1854b788d6a43e72a00b1602bb9e7557c4c298b99cccaa17fd950123d672978cd359e115eceb88480d59f5496a920949e09d0590283280d78df0ee068c475706701034b5b8686c60e2c4c4d4bafb2dd25c86293d472d195186f3fbaaaa000cf678295143aa290b011ec35e1eb2dcc6ad12593a934b60af7b570bc59569df2e99bf618aaa60e533265e2bfcfe3e01dd1620cd7d6df8b70726b5fa1191b0cdbe627f714744b2bf2abaddf800cc091ce5ee447f2a61ad36094743182ebbe236745bbeb27a946c8d8dba54dd3597fc4328bb3fa5f43371b531bbbcb4795a55
+TAG: 1fa0b1d147e2c8f70c31f20a60228963076b32bb
+
diff --git a/src/crypto/cipher/test/des_ede3_cbc_sha1_tls_tests.txt b/src/crypto/cipher/test/des_ede3_cbc_sha1_tls_tests.txt
new file mode 100644
index 0000000..19fd026
--- /dev/null
+++ b/src/crypto/cipher/test/des_ede3_cbc_sha1_tls_tests.txt
@@ -0,0 +1,840 @@
+# Generated by
+# go run make_legacy_aead_tests.go -cipher 3des -mac sha1
+#
+# Note: aead_test's input format splits the ciphertext and tag positions of the sealed
+# input. But these legacy AEADs are MAC-then-encrypt and may include padding, so this
+# split isn't meaningful. The unencrypted MAC is included in the 'DIGEST' tag above
+# each test case.
+
+# Test with non-minimal padding.
+# DIGEST: 7f3a0e20bde700d3c5596909282e5c3e764c99e7
+KEY: 86d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8e
+NONCE: d1c8e9ba2fd6773e
+IN: 936a91d0b5
+AD: d2c0267218cb7090c61713
+CT: 144c98ca1f4a40ffe530b338e5173a8e62c8530b
+TAG: 0c14b15046d12f2ca3158ad71effd0f46b29b3ae
+NO_SEAL: 01
+
+# Test with bad padding values.
+# DIGEST: 7f3a0e20bde700d3c5596909282e5c3e764c99e7
+KEY: 86d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8e
+NONCE: d1c8e9ba2fd6773e
+IN: 936a91d0b5
+AD: d2c0267218cb7090c61713
+CT: 144c98ca1f4a40ffe530b338
+TAG: e5173a8e62c8530b0c14b15088f70f550ab57e02
+NO_SEAL: 01
+FAILS: 01
+
+# Test with no padding.
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f
+TAG: 3ebd1b0bee840e8a6e992421c62de5a8fda3a82f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: f0f82752a691ef5866413f2b2e5c1d0ebb41ccc8
+KEY: 7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd8
+NONCE: 8503f78b8ed1c8e9
+IN:
+AD: 936a91d0b5d2c0267218cb
+CT: 76416b81
+TAG: 2ddb5b2cb015f5b11fb960cd166c5159b6fd430d
+
+# DIGEST: 7f3a0e20bde700d3c5596909282e5c3e764c99e7
+KEY: 86d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8e
+NONCE: d1c8e9ba2fd6773e
+IN: 936a91d0b5
+AD: d2c0267218cb7090c61713
+CT: 144c98ca1f4a40ffe530b338
+TAG: e5173a8e62c8530b0c14b1504666f5a5cf6b3a5d
+
+# DIGEST: 5b32faa93c18842b5cb7b075270438756d5f7dd2
+KEY: 97b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2f
+NONCE: d6773e0d0c302a5f
+IN: 936a91d0b5d2c0267218
+AD: cb7090c6171386d641b877
+CT: 6c5290706a6c9c4ae519349f
+TAG: 87e4aadd457cc7115f854462b6797e3836bdee34
+
+# DIGEST: 995a0f9b029aba3e0a3205364628bb76baccbf45
+KEY: 56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c
+NONCE: 302a5f47e037446f
+IN: 936a91d0b5d2c0267218cb7090c617
+AD: 1386d641b87797b684e0fb
+CT: 68c399c86abcb34bac8b6f4c8c5ccd5e7f5ad7ea
+TAG: a5e3a1b66f75d0725697822203b423868c636bb7
+
+# DIGEST: 023d08d5e5af3e0b016103c7c3cfd1d02577888e
+KEY: d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e0
+NONCE: 37446f5891d77df6
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b8
+AD: 7797b684e0fb56f97c3961
+CT: f30bd82745f9136badb1e6957b7229751351e557802b8dbcccd5fafa
+TAG: 640fd302b568db96ffebe60962d923c5bec73197
+
+# DIGEST: ad4b11a43bb47aec3e91209f98f99839dfa1d6f6
+KEY: a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891
+NONCE: d77df660ed82933f
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0
+AD: fb56f97c3961d8afa22993
+CT: 630d9ab3da5334512f84d4a3fa8244df0f51498917d19af8ca6a43ee
+TAG: f417e0695663cee81a0537c1bcade379cbebb75e
+
+# DIGEST: 580641286aa43bcef85be190e1967f627713bc64
+KEY: 89c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed
+NONCE: 82933f62be8dc55b
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c39
+AD: 61d8afa22993a340b9b3c5
+CT: 81ec9cb470c5b72a2e3e86b53b94e20516bd821d68706452f03ba1e953790e4e9dc4b7f8
+TAG: a095c625d96bc03688f985eaed80f85ef647ccf7
+
+# DIGEST: abb06965675631a07f380e80a05cff36c2d42ecb
+KEY: f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be
+NONCE: 8dc55b436965aabe
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa229
+AD: 93a340b9b3c589c7481df3
+CT: 7595dae5e0e62100c9b72c60c8aa4059c1ef7265547feb2ae537686e8f8acbc915d367a7
+TAG: 32ab1bcabac6a7fe8f37dfa48d7186f19427690c
+
+# DIGEST: c6a1ebefd827cde32df1d38379ee4bb6a7f81267
+KEY: d8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b4369
+NONCE: 65aabe477e0cdd46
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3
+AD: c589c7481df3f4183aa23f
+CT: e4b7e1ade1e8af85dab54d781969a9f06c22f044d115e64fecd4eb0e222b3d39988a0d5c2816643d4007ce91
+TAG: 0f713edac5403cc736197c8f9af9e538fb7a6d89
+
+# DIGEST: 77fcb5875838a28d24c4b6bd0916ebd827968073
+KEY: 03f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e
+NONCE: 0cdd46be99371eb8
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481d
+AD: f3f4183aa23fd8d7efd885
+CT: 418453b6063331fdcf123f5462411fe0551c0f2ca9bf070bcdf95c35177954d700487dc811e98759ff04f0116961bcdd438d1dc8
+TAG: c4d3547bc89478d711ae7e671d6b48e7a512fbd5
+
+# DIGEST: ff3c91da880d2942bbc51adafaebcf4c6fd50603
+KEY: c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 371eb8da7dac997d
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa2
+AD: 3fd8d7efd88503f78b8ed1
+CT: 2b4f3b7db35b6608ca790d8b05b405749f78859ff7b1ee4e588648f7afbc345a04d550c0a03753f4222ba1f967a2faeb3f37a994
+TAG: 679fb99370455efab942fcddc691db0d392c7eaf
+
+# DIGEST: 8c439bfcfb896bd106f94676b5626f2bc624c313
+KEY: 773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7d
+NONCE: ac997deafd64b1fc
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd8
+AD: 8503f78b8ed1c8e9ba2fd6
+CT: bf4a8b5df0754ce3000649b523fce0cf44db67966281a8c3b300ae433949e5351de6869545a8136a226b192e0d78bbaa81e3e6b7a010d5e0e2e2af23
+TAG: 105209280dfed70a87e67baa508408106b096575
+
+# DIGEST: 35d9dfb89c1883210f03050da3166b6d13f5b8db
+KEY: 2a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd
+NONCE: 64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8e
+AD: d1c8e9ba2fd6773e0d0c30
+CT: f0bf72c441d1c94878f3ce10b10c540ad9933089de01b8ab82022d64d0b7a7665d0a485bce781ba9a9f6a53c2eb31d732f2233b94224bb6b541e3b94f4366882a9db4b67
+TAG: 668ec1f6254ff1c294fa40ed27260c848636ae96
+
+# DIGEST: a07054c760cc66fc704edf950201005031f3faac
+KEY: 446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de
+NONCE: 39f4f03541a11be1
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2f
+AD: d6773e0d0c302a5f47e037
+CT: d7059edbabb5cfc2cd5c459abd74e136790aad50d988c6c9271428597617db171b89ab171a68b14f9d417bb81f9f7d2e2045aa47c0b5d166c8b2622bd914c4e752e3d17e
+TAG: 303776640b3ab712f6068c449dd7a7b2c4ed366c
+
+# DIGEST: 63efe7af502231420ed5aecce9a28446b257828d
+KEY: 7df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541
+NONCE: a11be112a72933c7
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c
+AD: 302a5f47e037446f5891d7
+CT: b81f6e678c5a08244a5f578970d64f96f50ad5b5724a9287ee7b293308db34e03456f1745f79c594ecc480fb2a9412bd685e6c0df028eda06aaa15c90afa4ec01736450e3eb863b849636c21
+TAG: 2d353918c6e3044d298da2684c08f1271ba4b4b0
+
+# DIGEST: e8e41988fad6c8b44c56544964cfe0a347b35b1e
+KEY: 933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a7
+NONCE: 2933c7b54ed4fad0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e0
+AD: 37446f5891d77df660ed82
+CT: a799c4a6590a4c48735d1da9746e5441cb11b664daada5d4d68d3a0110c4ad8d5e96d7331d5f7a0d1df9af5da4208065b6bf31affdfcd4944e8ed55b0ba7b7911be1a9052fbd93d5fbe2926a
+TAG: 6e5ced88748f87682759b5547234cae85f78e4a7
+
+# DIGEST: 172f4992e692a88f49628e5d3937959be01aed2e
+KEY: c55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54e
+NONCE: d4fad0be905d4120
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891
+AD: d77df660ed82933f62be8d
+CT: 7923c66ac88a9d3a2c9d9e714d491372caea0658b4e5692a7df8da934dce8525d0974848545ce89a44a735eedb22f18b5b8f1455c0aeedea9cb8f5c0bb51addd065a83c4e825ff3993ff58cf0af7577b06b8d517
+TAG: 26fe8d46fce9a59b084c3924d2bcf053291e7a38
+
+# DIGEST: a35fc7d25f90dd9cbd35910d5532aca8aba88b29
+KEY: aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be90
+NONCE: 5d41203f5dce998f
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed
+AD: 82933f62be8dc55b436965
+CT: 5e91bdcdc26c9100265ed7c6f029a1aa46ea6807340a161cdd07d21bf6bf7181eee02d939fd95aaf343eac9f629e01a665dbb40392e95da6d00839e3f9b412229bc48d9b289b8e91fb2705a0d3ab85aafb130e3e8d6c57ffa542b745
+TAG: e2313b7c92ca3350ded6fbc5e7824c50e3888c0e
+
+# DIGEST: 4abaa8453e8cfdefd918571a961d8351754ad5b4
+KEY: dd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5d
+NONCE: ce998f8fb2eaad40
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be
+AD: 8dc55b436965aabe477e0c
+CT: 2de7b7a26fa9d1b0d301f9bfcc0772b0a683ad5a1392bc38f495fd88a44a648cb4136d63ccbfc994f5147cdd88a40d813ad4cf7c95db148871433d23f296f2c0edf698329c760b76f4c5eaf2a5b620c482494de0128c9e5d2237efe9
+TAG: 5b7e557cc8c83b35c5df397489694ee739154c84
+
+# DIGEST: b51001b6ff9d27bccf3103a4961280e0a1406257
+KEY: 1eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2
+NONCE: eaad409ae0211641
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b4369
+AD: 65aabe477e0cdd46be9937
+CT: bc181d050d6e79cd5d66a1410338e4031378d60a217bfbdaed1404453cf8a680b9200f746ddb6106a8a407aad8204a7e3b5ce8b8f34d1bc69b84fa538745bf599674c6ab008435897a765e5072449a7c79c4fbd11f0883548a88244f5b1dd7aaf4ba13e0
+TAG: df9d9f0ea057ac04f64b48a9018ade3b086aacad
+
+# DIGEST: ad2b43eee27e6267d8c5c1c3d558a07dcd6b1f5f
+KEY: 997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae0
+NONCE: 2116417dae0cef45
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e
+AD: 0cdd46be99371eb8da7dac
+CT: 7ed8d60c67875030c8a20cbb5f71e22d1e5c3f93852a5bf953ae67cbb3a4d3c0b69bd9b43cf807b32dac4833e502fb377d67d2575a62e9f6dcc12c4df05c71802cfa5b6b3104d9526941bf1b48bd5e65710e15862b6c0dacc1decf5aa1980fce6cf99e0a82dfffccefd195e0
+TAG: b64ed804149472b11158cc396b77e8d080cd7205
+
+# DIGEST: 7b17b7cb19107af8fc4671420e461060e2ef3e61
+KEY: b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae
+NONCE: 0cef457b9e5e16dc
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+AD: 371eb8da7dac997deafd64
+CT: 245180810407934bb7ef6fbda3f64abd712a3959d0fa2502464c159ed70fab64a10f360f22dbaaeaf44d4bc926c1028675cd1c3a94ea951b1561c8cc449f0940c6766b67ec21f8c039f826afa423e7960bb4e2f7e71f8f660ab2bb24e2f3bdda5c070a3529d78b1cb7502ba1
+TAG: aa764ed0da7a939f1aee2b6f173e03cdef71f25f
+
+# DIGEST: a27799fc2e00e7abec4c5939451a834c4606cf7a
+KEY: f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e
+NONCE: 5e16dcc5b6f25607
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7d
+AD: ac997deafd64b1fc65de39
+CT: 4fc30349e938933fbe87c1b071bb54ea2837c2bbc4ad4a59291fe5e190d25aeba4a14adf7a8968f87be1d68d3251259bf66b5413b4b4354e2f2e0574a3055b4c70e736ea139159599ba7f7c9028671c1bc4af858bf7a691429571743ec154f0a7cced1f23b748cc93cbefc234dd8dcb51409755c
+TAG: 687cfe32d594a0351affd831264ada7fdf8e83a5
+
+# DIGEST: 7c52593d1d37b0dc380297231c6cb7b64e04c493
+KEY: 1be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6
+NONCE: f25607f00d033fb9
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd
+AD: 64b1fc65de39f4f03541a1
+CT: 4b735990123f86b6d35d5c64faf77b21b07ccd281649d3f70353b0515698c843c2fbc2ba7ea0700112990ca0c7c638be7f1f0e6f4a531ddfff6db4638c2f38df750ffd5ef23976fd56d79f1d882f6a5db8c107e6a76c2f74c3b72b14127504befe98541418987222f4620738e7ae67feba4480f1
+TAG: 5e0eebab83ce6db242365b528d681102cfa7f000
+
+# DIGEST: ac6871d354eac507556770d8b6bf10b5240273ed
+KEY: 33c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d
+NONCE: 033fb95fb09e4d00
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de
+AD: 39f4f03541a11be112a729
+CT: d93d6d42642cb56dd5a1e3b8d5913ef595a8d71fe4683afab5f8f6e3f1f87d08af1efa5257e2427a9e34041dde5deaaf6f0f808debb26b0f4f32860669879324369aadc41982a2abaea1c1c04146144d028b40be77e4f07ab6d5903f6d88aa7716748c3b158e5b2b387b0116a8a8ab1fa852c210b5cef20d5ec2d60d
+TAG: 0ace1a7de20afd27c436d4785eaec425d8f22fc8
+
+# DIGEST: 4f498d0aa9205160827626ef80c163275eca1f78
+KEY: fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb0
+NONCE: 9e4d00d6172e780a
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541
+AD: a11be112a72933c7b54ed4
+CT: ed719f396a0c720c91486127e58916f010692f6018646fda04b0321e70f3d5736ee3827743f541857fc2bb3c41497f03563540655a7ac43f69e62d876a31ebc3c14e24a432814aa4a448c44ac4b02624494f703bb171f6878236bbdf27be2f9fb651cd855564976b0e875e4ccfb42930422db234008ef6a25723c944f8e17447e2588894
+TAG: 570bcd7913bb8141042b7dbcf8714d68d6539db7
+
+# DIGEST: f0901e8b8083c39222fc940384eb73cb96b22892
+KEY: 41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d617
+NONCE: 2e780ab8b700433a
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a7
+AD: 2933c7b54ed4fad0be905d
+CT: 10be314ab0ffd93775ec945717d140b07d15e46e8f057f93e76615048981899200f4411833cf63fad000ebf63673171104d08ded699f25dcbe747545447e558610f08ab78c09025ee0ccb3fb0661677c76d58695eea7e137a2d846e583466568dcfaab2b7f42d92835342872aaae2f2ec44d2f0e63bf68fdf2709492e9e79b38f04805ba
+TAG: cd4e2eb1ffd0c0e5ac8805cf4b84b7ab18ba3f6f
+
+# DIGEST: 7af193cdcc8d7f17b55447a81eef3dfdf345bba8
+KEY: 998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b7
+NONCE: 00433a957a741c9e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54e
+AD: d4fad0be905d41203f5dce
+CT: 6afc6a8dd1544dc4e77dc7621ec0b0c56f27bba0784e917e95b484d64dcf926cd68dd020fbfc356c78ebd7a1af77126f430d0b2477b965eaa7c964e888f47370d3bafa933f35ddbda9f13bc1155599ae31d552eee3058f63f63a3632e4f1c83873c785f45f7cbf46f3e7f7a9f36fbc623c168eb921b916f64f99fbe60892395fb66bf809c02da0f16d60e4ad
+TAG: 555cddb946338c9157220cae40f2ca7dd9ceb85b
+
+# DIGEST: 4ecf44faa266de0904b093653c4d623a543d12d8
+KEY: ad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a
+NONCE: 741c9eb80f2b021b
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be90
+AD: 5d41203f5dce998f8fb2ea
+CT: db772e357f5f21e09490a69975168af1f31f5310b5c95d5fc0b099975525e8d8c397537d43e986adf5a961f3d2fe4bfb5a4febe487efa71a9d8b14831c627601d7f991ff6530591309ff66becc03cac76403a4eccf4615941cf909c7b9e693bfa7108829749961e54ce04f91ff2067b8b8a3cef940f50f140b32f23316b87ec8bc4799b5bf6fe332093a2e37f66c1960584c8565
+TAG: 48d415b8b4843cf7454c1b47646aa291c20b8dd3
+
+# DIGEST: 92a938017497e0762115325c40b5f7c138d5c6f6
+KEY: 16417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f
+NONCE: 2b021b1444769da0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5d
+AD: ce998f8fb2eaad409ae021
+CT: 583717ade9efc6127768397fc4042d88c3a86ee8e749090a0c8a5b66aa1f5260644d51306f601b6728bff56ea2331edf811d9e8ea7b697952c42af9503106c6c6e99818ac0868414d431bb9ca0988b41455f8fd8a3bc96febb0e2e630ffa9537aaec863eba926e0942c97b21700c6c091d7edad3d6dde06698978920648c2a2352af648374fde214d6d970e701fc04db2a124f49
+TAG: cabb2cd56341a73d1d7e0edbd38f9949ab24c162
+
+# DIGEST: 6b126413a7bac1069cbb5b338c158463a242d607
+KEY: ef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444
+NONCE: 769da00fcfab0f5f
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2
+AD: eaad409ae02116417dae0c
+CT: f806ec43738373a70f9b7757a9780cf133c46e02e7f82c0b64cf0c1ddbfbfaa4975ee8bab96ccd9270f6255fe8005a79bd8f80dcd59daec2975ad7302b5a2c2c8bf772231ba0ceff4b670b7b0aee0ebd8d14e216428d9fd1c43432aba3f4cf61771c3927290a280e43c409837df078857d442bcfedd2ebee19f96fc0c23829f5763c786f189341f38f44246820887ed0cf18a992dffa18111ff5f794
+TAG: 9aff5f9f4d4ff14565af4d150200379747746a01
+
+# DIGEST: c72d214b42ed66ae0822fa9f3bda306c7d58cf80
+KEY: 16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcf
+NONCE: ab0f5f93b511060c
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae0
+AD: 2116417dae0cef457b9e5e
+CT: 1b56543b2b50cb60e4a65bbe46474205dacb06c4bce58ab4bff5d9af5a9a4f07570f678fe3f1744f49fd79a0870ea2da2b85208dc679cafca49dada177ee8516bb7f2711065f8b1d66051901835377bba41f0c86b4c382c01aeb1343d26896e9600d7102c170c7235f0d5206840f96dc59762e742e9c39ae14dd75962d8d26fd382a2c9093520fabf7559fd78b664ce0989c40c480c4b230149ab513
+TAG: 790ff151c28ffeac434d030ad485670706a659fd
+
+# DIGEST: 9faaa58dd34a192550c3519f8c0aeb2ff48dd388
+KEY: 5607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b5
+NONCE: 11060c9c5f3aacef
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae
+AD: 0cef457b9e5e16dcc5b6f2
+CT: 07b122adbd77b909995f3867d9fa2e8af2f2028aa07397f7d6f27d6ffd998a3c8c1da14cd1f8e8c43b92cc7308643d9de917c5f139faca9f484fc9173e09367d1935c5859457c35f11d0c5545c61f42db8649cff5872ad5e0860c3c78dc1054511d03b8ae346c0a2d6775367e2b3ca47da414b2f3d8b8d9ea4baca74901b3034ae1e92aafcac58027fab8db2de72334c7daec5c6c712c6315943fb8a03406f1a4ef00b08
+TAG: 5176ab1ca9d038887995cd7ee8fc5f68d6e42161
+
+# DIGEST: dd5e6be3644dcc888cc50c0b2ad0d55eb0407fdc
+KEY: 3fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f
+NONCE: 3aacefe61b184ad2
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e
+AD: 5e16dcc5b6f25607f00d03
+CT: c4d9dc14b3c2bf23ba6b0e9113cf165ac1028a34834afee7f3984de1c12ce56d54cd648a65bedf3a7c549c85333862b6a82fb838beeaa1dad68486c602af60c19f734ea1e9af5ba68570ed16313c9c03eb392157d8d745ad82741d8a090d287ba39041ac0467cdfa53714d8c6fa59db12ed4e1a175d9162a51dc35efa454adaf91e5474c7cf0d7aca04e75f7c8640ba7e306a089159e51b0eeb66b90c6e30c57e96f600275e15cf0d3ee9f59
+TAG: 435b6826d9febed2eff89ac6076b8b6a55767765
+
+# DIGEST: 1b8b627e1020d71318511d4c2078eed315ee0b04
+KEY: 4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b
+NONCE: 184ad2463939ed51
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6
+AD: f25607f00d033fb95fb09e
+CT: 2261fa7efcf858f8525939b1b1d5c3bd5cd0e8a6e0ad4194f61378cd61dd8fd63b01ce93aba89e2209eb7ffb50b1de5a36012f8d59b5b30152198d2fcd4b8192db32bfb21a74d02fb3202cb232cd7d713904b3bfcc6551288fea26486abbc501952bdec0a18f73060f708b8c76715120ba4babb84e03b30909b8c1490694cb8a0e2c6314ce66b174c70ad3ac5f45bb57d66d56ddc5e9f8fd4b5ce9dcfe97ebae0e14c826bd8fe451e5022aaf
+TAG: c1facc93e6120c9863f4c2b1dd5e3a702e0aabd0
+
+# DIGEST: b7370237d402dbf76f1a431cdfbb37f41ef2ad4e
+KEY: 780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad24639
+NONCE: 39ed518ce97c3fdd
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d
+AD: 033fb95fb09e4d00d6172e
+CT: 454dd554c546774980035b134088f5cedd92840cdf2b02f4081c377abaa3908a6ecbedd24ae0c1d4c77811cde6f30ecde59fb15c5c15a0f4279f5891123cc285e8e9313f72189397354c3cb08bc1f7ec58e4b2a1376faeb2b14f2ee30f6d464b15fba2eda657e915e6157b8dc6611839b6044df0a60ed4d728443736f001f452749f8a4a088968434b4a01fd952364e71ec97190ce63fbf54b588cf3a3b8c36fb2e4b6329be0f0f966225754c9b4223a3074804b
+TAG: e8e840127ff0d3c91c8d853d529fd05c2bb86da7
+
+# DIGEST: 0ad0e709e40cb2fd662020d420d97ae50a14adc2
+KEY: 433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce9
+NONCE: 7c3fdd293d72afc0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb0
+AD: 9e4d00d6172e780ab8b700
+CT: 03f55636209cd9af55c373972b3affbaeeed9fbb71a0a7c44674beb657eb89b20dd93116bcc042f8bfb640921f56d1fdc52121cb05f51cafeeb7e3a409005230bf117ecbb9f45092f70e6ee714799a7dc0efe6fcd2c16668d40e69ea18c6905b33b368c3ff69a51afd881dfff6546f6fe795dd40f87ea722fb33c7eb687a5f6833f74783c115cca091978dc51c7f947f0028a2c6256a0c848695dd21346c2fdc451963e4f441181dade8650f30fc6b9cf45ec3e58bf5f2e78ab1719a
+TAG: f7808bbb1f62629ced0b9cd9916fbde790b10c65
+
+# DIGEST: 5f9967a8fba7184dd97dc7d5da22ea785e0ffbbf
+KEY: 1c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d
+NONCE: 72afc09ffdd4f419
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d617
+AD: 2e780ab8b700433a957a74
+CT: 30cc1719932801b83d65fddade4e734a6280d8928f18669907dd495e5120f782bde269e83df0643bef695e4b3bc701b35fd9074984c91d61cc31c35720055b5f78b22a95d421e5672ece2a4f57c5e5a9d0b22fbad70d437eee0d68cffe0ddf53344bc2ae326072160a00d5f554692bfbc1ba91f72a128976c4bf0de672e9b2355425a3a23dbd193cad4ab4c0c845c577e2b316170c7f048910ced9628f994a17a938e961f61710812f630e2e0e36d0e37b768fe6477bf4e58942323b
+TAG: d9bc1c06b67c3b2b9c042f0c3ba53841b8e09ffa
+
+# DIGEST: b5aedaae523d9d396ad1d9bb175bf4c7c0b03eb5
+KEY: 021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffd
+NONCE: d4f41963249cd299
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b7
+AD: 00433a957a741c9eb80f2b
+CT: cc4350ab7a89fb51e185843732f69653b1fef9fad05206d2f7422e2a9c661af9b2d80f309495ba09055a4aa2f6f0e1da38b5fec74e0c4ca3e3385347a7eb2fe794327266280448401e5f8fa2bdd6026a5e1375f92e23a778cd5db095396cad1e73135d7d7fee85010fa183264c24b70b79c9949bc39a1c8cfd0a2ba0948a6c68c815c5ccfc7a85e0bbc24cbe025e952dfababb1683fe915b7f0ee86ac23982d678df4c8e57903798341bd5865a6d8d3a3f04c95245a7e65b4dadad572b5af30c9980b43b
+TAG: a3b175b2c9d19b04ba53546f4256c9a131f62dd9
+
+# DIGEST: 52bf12f5594b0cdefcf977c07626e8748cec5425
+KEY: 9da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f4196324
+NONCE: 9cd299b92e55ca24
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a
+AD: 741c9eb80f2b021b144476
+CT: 4ea765fb274bbb65405076c33d3df1557f29586ae00d86d954dd3ee1feee0789f18a3714396a5ac1e2cdfbd3fd3b4c33241c63d94f91ca43dd207b4b12a9ec5b09fe279904cb066cc2e4992dbe626e80779d0896b86cdd280405642ab1efd34a0ac611836b1b325cdbf6c1dfc405cf75b33071b4a6634c705cb887b868dca4a85acc07f39db0f289c0f834c4c007893d49a40ce25fde425527cffe31aef94f145335f30be40da9e002dee2d97f5e3aa6724b806ae7683e3bb67329726ee5dd66a51d18ba
+TAG: 5848c6daa10670d1de89c8b71fb6eaa9d639998f
+
+# DIGEST: 900a1792a921b6a253c47013c9eaf01fc5c880c2
+KEY: 0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e
+NONCE: 55ca24d8c078c49f
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f
+AD: 2b021b1444769da00fcfab
+CT: 34e8f6de67c17c6beb8db6d2c57a1df7bba6799de0541a44b3a305948a292cc3c8d0e007af88b44e3c4055c638718e9d2056ca76ff704438d946a19498eb35c442ef5e84a4bb5c7a5f4e9b95e1e851cd917a09077212f937e6437a52cc8793cb58dd8accb4ac84ba5add02f625b02ee114f4afb59b587fd464dd1e1e8c1fb6019625877c054c580a1a23b2b9ff597283d6768297e1d02b71f7f6a733e1c27d32b78dc7a7ab1b94c907ded7b0265e2b55cafe07b6719426e89ce00499a6cddafe476588aea55bd0f484073e20
+TAG: deb039be12bcccd8af19da94148942b076b0f5fc
+
+# DIGEST: 88d7ec35d88ff113703702955e931e802fb0d8b8
+KEY: 060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c0
+NONCE: 78c49f78c7e71371
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444
+AD: 769da00fcfab0f5f93b511
+CT: f9c86839afa85f6a0ad9872059d9643dd5ebd05ac90e885c600a25c1346a82fcd6367ea6a9dc6643778e6923443af1809c9351e1ba0b8559dfede7394344872d6d3632e0fd0ba4b8c03d844c71560c8c72cc309f3c115f8870e9538b21166e4037978a1b00cda5477788a93387c8a1cefe2d5f760227223f3df5d8b4e313d413f197a2a3f6ea8b1ece39cc8b2fdb27badd6edccda3bab02cd939fcbd7ba67d5128c89bf0e872a3c034880e1728c164ddb98f1861bf06db075978159eb2ea34ee524e3795e3b8a3e8c774c07f937f9e451527b4a1
+TAG: 313d2683d78674e4bd8cba35acd381cc0a8239ec
+
+# DIGEST: 8d8493b55d9b74892e77d3b730588c087ca9b1e8
+KEY: acefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7
+NONCE: e713710a025cb8b9
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcf
+AD: ab0f5f93b511060c9c5f3a
+CT: a34ad0347668ea658b79c19b83084980c020c41dacd30d9ef865de6adfe812e111055799ace3cb04b570df0e767a5dda0e558b908d296854bb02ba4790c661bb1f84d3730181ec0ad5b32ce2baafffcfac0e3b50e885864ebd5c3ec4ae1aae6774e476700cb3c0a2e9af218bda34fc2db1612490305f4dc590fc61d3aead676e85c16439b1d991f8249349b310cfcc7bf5625a61da9f4deb506c43503a6d49c03e536c6bebd70c44e72cde63218aec74245fe8d20e92a4c67e64b82306ed5736fe110510f8ef7d068039c4b0b9fa27679354271b
+TAG: fa6ee1d1846b2facab3daa94fa50610b15850fb3
+
+# DIGEST: 4cd92ac16a807d2ff180df75c47d848749c7ef46
+KEY: 4ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a02
+NONCE: 5cb8b9d71d2989ab
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b5
+AD: 11060c9c5f3aacefe61b18
+CT: 6419d65313bbd047c755b374ab46155499c53eccf14d3f4c9885c871d738a6ea9f15f63099045e7f81af5de13e161caf54d19a45f8693a0c1f2da28764f47bcc214744659eb49698eaccfb4d6a1f52e1daef9e8845460ff2c5cfd702f72c6667358607613cadc6e94b0b9ce5afbbf2bd18b5698c4f8932b8825dc6f4cb0dc89957d514b3439d8c760816a4d39e78abbf36cc19bd9fea6727d49458250df7c587966926feefb89578781aac92ba271b5f14116e4a9ae9f858dd7d6068dc9161e88f48082a6af6ec8f0570dad665ca02a56fc96dc1e021973bc97c4ab0
+TAG: a853e815d864a6c9ef3aa1f3cd4add104790e679
+
+# DIGEST: 64ee218c0c96ca8e2d2e50cd809d61ee109baca6
+KEY: ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d
+NONCE: 2989ab33e978c445
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f
+AD: 3aacefe61b184ad2463939
+CT: 069ae98037205c7044bf0afa3692125971755288c3beb1ffc4cb471bd4dc20d5ae838bcc20098905e19a1fae620cab84322db0946e57840f9dd1ff5911f0763125f2943ccbcf3b7e3130fc363b1ce073d472a22ecbe58b51497b8f069ea7ba59d0a5b186f7710ab3c781fc62e635b65abd24c71835777ff979a5575f7d36075332912ccda68c5252b9cd45b2fcff84081ba2e136e2454dd58123714183439aa78e1fb2b2cd4d956ac832dd7cf5fb05ddaa0fb9c39b44c4128a27468ae727e96bd6e792731fb38d847aadd03512b12faf9ab09bf4b8403314f3c21584bddcca5bd676989e
+TAG: 46ff903a15778aa34273a903ff37a3a18c64db6a
+
+# DIGEST: eef8eae201ae4e5af32ee74bc724e13ae5ed3978
+KEY: 3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e9
+NONCE: 78c4451e3be585a2
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b
+AD: 184ad2463939ed518ce97c
+CT: 434eb612539fd15014568a6b1eb7ae957a8e5256325d6b235be52792e63be39b88d5ccdc61d22017a73d54b2586b3c7ba42377c51275d0300999b359a4242085256611ca8f84a9d373de8010187086d1098af5c6c70b14f371f851c463556a680c26683206e806d00dfec8a95bd99727bb9c9122b3863c2fc49e00181eeff08a0c3a8fb7d14772df0a949d2b040a399e051dc0b767c85906c978df93d4d9acaf70d414a56454d5513ef1ea5ddf98276f333c9418d52274904872dbc92dfcf6b477a211740279744a0a6f88c73c59a4d09a44c8381fb8ff2efc5ee55f7a7628ee5db13f2d
+TAG: be3991f1c4832db5c08ca9fdf358611f410cb85d
+
+# DIGEST: 2fe67a81b41b094a708ae515e28bcbde3bed724c
+KEY: afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3b
+NONCE: e585a29a2af12fee
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad24639
+AD: 39ed518ce97c3fdd293d72
+CT: 34ed75b8e5eb648e16de93a0a3d678c456e2b3aadc994a8dbe7f27041fb86ef6ff8f01d50402756edbd403699dafe73e8aa4b82cbfa558a96dcb9b2cedd0c370ccd06939c97371d61d04d85a903cc9fd3115fd31b6a8d3502ed7a3838b3f0c96b01964c97087eeb67e44c9a5577c52354e497708f832854f14095469515e5426d1a4b3e16251d63cb6dbca6f817c0d2b577e29adbb1e644e3ef5a836386e768f3d37bfeec1973ff2c1302eba5b682b57e85156749e260b908a7a96e7a1c111220721a119ac7a8d6edacb4a46749a2e5e230bfc6a881adca1d62acc915b2b131661146e2b902ed46c69b9af20
+TAG: a1aaa47705eafd9737dc8433130d5236e5b91adc
+
+# DIGEST: 33d10d6cb5dc80751d0f8e370925d7c86cda331c
+KEY: f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2a
+NONCE: f12feef71e1063b0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce9
+AD: 7c3fdd293d72afc09ffdd4
+CT: 662d0187be8d1d337523445b502c3335fa20f095c3e1e7efa0c6b6433c1d4f9b9fe84caa3c887ff84cdf789026fc4a39982880532e3e8cc37b14df298a12be384794f8c52eb8e4b6960e33e826949594477f0c9fb1e2249df4f83f19879d952725c06eaac526c14ee00828c171a0d57df06504a7ebfd64ef69a49b9d4ba5b68cf6d257933a317c48da3157a88bcbb7a3109deb3d734cbb2562003ae7e8887303acebe18bec9c4dc981472565ba0855d1d81ef3f63efac52f082a012bc98f8ecabed9a19b734cd4886c809dbd9f8c71f890d420d0ae490cb6b850e137dbd5701018f0af1fd952949083b1a1e7
+TAG: 8be90b2249b6070bd8b68806643fa6b94bf047a5
+
+# DIGEST: a29f128842a48debb60699ae0df0da9a9b5e5dad
+KEY: d299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e
+NONCE: 1063b0b4e6e89920
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d
+AD: 72afc09ffdd4f41963249c
+CT: ad8879f5c6ee8149ce55b0d308d04ad638ea5a1ddb77e9dd8c84b94c852fe35222414fef1027b58a97add291eac103debbbfe939df09ce27d8a7685ed95f9b485d8eb4f413c20273db7f4248aea56ef48ca362cc0181e011500b61a146e16893e5f56b8856fe1f2bb32b3a06cc6344240efebd8961d3198d096e4180de6942ef98ff4cdefb91cd12f1d2bc16bb5906a29174354797e6791db461bd7cd24ca79ee90974fc04081ceae85222cf11aac40932e5cae151be81f0719b312225ad0b35475e5e39210310088c4987567ba3b4bf258f3afedebf8f76d1f4f5910035da683cb4cc1b257e8e0251f73e90f4a02543f858cd38
+TAG: 0296cf58edf6f189bb5dc7591c33e7cf123aee82
+
+# DIGEST: b5048d1efa7564966b6cf1579cfb4ad8e9460660
+KEY: ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6
+NONCE: e899200304bd3508
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffd
+AD: d4f41963249cd299b92e55
+CT: d010afb06d69e17b6e2916a6b9e7fd5eddf91f4fdf411af9f745b7346df6912f86fd0f032fd2182e2063efdd2d481052aac1a623f8ee0c4e8f5c8ea97de8a65404ed3da338076b6a527462c15f296e886bd6d9604f4ead7339ca71a5a392a31a4053b15754a11980bc61906ea934a35ea7dc8ee7a4a6be9526e3494284e15ae79c1c4abeace3f5d110b6553fa3e1aa6a61a109bc9f308dcee32b4a68c56fe9a08f78cc6e606ce15f53b340c3d52e08362dc55b3d00419538e9ac5cb0fd87bbbbc2016186ca7f1ff9288a9e374795a8bbd578b26b809fa4f9fcf8928d96f75609c12769be2f5c8dda26d08473c275b33a0fb9247c2397bbc9d734673c
+TAG: 41f8cbf79ddd4e4549bd4a3c897c293031feeac0
+
+# DIGEST: b6e68f5f0dfd8ceab56ebb657728c9bc5129fdf4
+KEY: c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304
+NONCE: bd3508132a027d1f
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f4196324
+AD: 9cd299b92e55ca24d8c078
+CT: 02759c0f5538db2f15af1fdcfb06ffef16d86e12e7c52d060a91c2b98e4c301300618f86209b179b1ef79a3543e18776522b96107818dcd51e4fd207dd4ad99748225af36a342f6ba23081ae3217eee6686f66694727ccd94a5a7f5661b68a0ecde3c06208905b431ee81ae5d5e3bd0138c4f205f450960f8e54d2027b9b14ee5e5ae302311208aedd474aaa476b0c490734ebcd5a949251e2b3ecbafbaa75c4b02910895ec5a34ded91a796ccdbd8b8e79b6cadf73b356b8c19ac19c09a99b498d739f909da39b86344255a34678f3ec869ce703e4088f8253620c93327d8bd44f436bcbcf89817b19b0114a4396619ce226592afe596307b1e3e44
+TAG: 559a8ce3236cccb72f8d826254f4183ded50f8af
+
+# DIGEST: 853bc7b9fbd640cc0654fa5533ae302e398bab35
+KEY: 13710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a
+NONCE: 027d1ff4c047b3ef
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e
+AD: 55ca24d8c078c49f78c7e7
+CT: c7ffbe299dc13468c02e7ccdf4131565bc71c552defa99b2c72fe3f3a472f97fba7ba99586e2c6fd195c4abb8e5111588cdda4dd1f18cc6d1dcea60483178e1e406e5f19f6c94691d41b0b11e13e34075c1495c87a15a00d393446ef9c3f3aaad35addaa87ce0e1ee3398262598ec44157fe81f247c302e0db13b8802c7a8afaf1a3189043ca22e76010ad8184c62ea1700a513359d160f48f6204ce303ee343f0c7d8c4ace5961d0601d4280123caf622e4463cfdc2bb392aea1c99cadd2b5d103e4f3fa32e12335dee9df20d4146c927ad3411e4c5fb1933428de395703d961cd9121a99deef6d1f9cf15fc3f2ee3e37d16fdfc1fd0aad421244b31f309ab0d5374f46
+TAG: a2d94e2645ef68ade510d2b078b1b92959b8197f
+
+# DIGEST: 286a92c480192206a2153df1b6d0eb26e6507da3
+KEY: b8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c0
+NONCE: 47b3ef4f57a74706
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c0
+AD: 78c49f78c7e713710a025c
+CT: 3cc00a29f84d453f22814b53acb5841579656dbc4ba4d97370e1c941cb7c176a55fac6c0d465816eb323c0516a0f16b7870feb863f38df1fc218fa7a17ea4c8c8143f83be7597638a7b475ab31c59bce238bbe731c339d9116054b689920c4081c2ce28f4a1909cdb944e0c2f8bb8cc918c2fd75590a147658491f33237e2f86aa598c0757511739055b8e2dae8a98abf3b86c069042dab3c727f2f9a1ce7ce56b3bab7709861152abf2196eeeff3142b959f6a925336a67fce2d7983648f7df46843a6718d7504d0076a3cea75a6a464d59abf00afa42ec9513b53991fa35c4cdb3b302a0fb1968d4d1bb54ac0df034de5b506e6ddfc800610c7654470eb119c02ab4dd6e5bb623cfe1ebf0
+TAG: e29902672aa6b6b90570d8eea222e5e933515704
+
+# DIGEST: c2acb0c126af5282abe14058066631fd0c658571
+KEY: 89ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57
+NONCE: a74706de4b381c69
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7
+AD: e713710a025cb8b9d71d29
+CT: 1d7982e3a2cb25c3c901714a1dec6e4adb2b4da2a8b92a6171ac22fd52d9c7f2bc1b37fccc72a1056f02beb556d77f4ec5195c15fbc1c0e35dc1ff57d2aca31dcf7f5fb655adb535a14c210255d80948c1df76d6b18713a0c2ec26151bbc0edd40a64908bb502010e1cad69d13af3875e2edfda77cf58de3c04f48308fcdfd6843a76157a2c339bfcb511e5f56b511c4fd71915b1a994acc657e2d430bb590bf407f00131dd06e6d67161703738ba5f6c1456926e82ab29a79fb081786ea14f6c089b27bf1d31d956f25fe2255ea962c2c0ded796aabeda4c557173cc0b40b432f9ae4ba8baeb5f5f5ceb7345ac2d750c27859b97dbf9918b6d6fd19fce9f89a709e7ddf4c2038be992bb402
+TAG: e239f703fef0a6bb390173093fddd8baa283f9ed
+
+# DIGEST: 500e5f2a56bfafb2d93e26224c9c2df562589f23
+KEY: c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b
+NONCE: 381c692ef164101b
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a02
+AD: 5cb8b9d71d2989ab33e978
+CT: caf02bbfbe730d0adee907f73f3c6d302df10a6495d2c1c97b5cb0ae984fede2efeebaec895f2164a5895d085e7c696dec9a6929e3ee4dbd94f7ed8e9befbd6563d591faf5057c020cf27e22a6127838038016af79ad02b2f04024954e1b86281bcdc26f05e2b1f328837069172609962faa4956aa6155a5426584e7290e203c93fc1749dfe42a5c33510750386768a62fee6eeb7d9af751d3c23541f33761c8accf40652e7e747487f854594573debbb06e50bb7e46ad1aa7572042f1ac4b2c2c087c571edd4ef74a31f2b21f481bb46926600d6501ef13d24c09eba31bae0df9d5d431c752e454c417937a087ca9e549002f3bb7ce858ff0757b522127b26d1d96fc166a2683e7cc41426bd80c46648649f552
+TAG: c8093b5e426868c9e3d0aa6bcfd738fe1ce59da5
+
+# DIGEST: cfa6a42a2cc0ddf1c7b20031c95e331696bb9ece
+KEY: 85a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef1
+NONCE: 64101b89b476f72b
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d
+AD: 2989ab33e978c4451e3be5
+CT: 8b4ea8b6549d734f4676313476bb0c6ca8787cf6d3cba5d0720148e04411db8bc205f61287fc509dd149f4221a0529d7dd10cd60bd0f861d1114482bddf2542725d44f663049840531cd70ad43df4fa6758ef6cdaa4c5c472b7b458092dbfd4086129dfb6f17d1000a36eea4aaee651cafb2e597ad019cd9c37abf1d177a4da2215504c29504de35086143c352be087e98373310bec397d1f5db44722be75d3f4251fc7b95acec2b67ce6e0975be1fe0771dd30a4723d39c2f5faac04fa2ac6051c93ceb4fbdb316d8c95f306ac653080327725d765df4776327b4d04dab6e9f1f296a8263cf8542ca453e95b6ae694029a02b42964d88ef7edc10420a4e78fd0f370d72c3e5e9e187487700889669bcfe94a213
+TAG: 435cc125c99f6d4ffdc147da46a1370e3f79d1c9
+
+# DIGEST: 2d1b27948de83e32a0fa5be7040d896824ac1fe9
+KEY: 2feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b4
+NONCE: 76f72b27f06f520c
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e9
+AD: 78c4451e3be585a29a2af1
+CT: b761bf917019eed719105c33f9dfb47ded79f85b3f96bcf0b2a25c624055d65a0bd30d14077808636dca1181f14169f60bfacc14e54ec103d617324c87b890e36f33d9a37d9a7e706b9a28728dd3a157886e17eed711bfc30a109925b9d74018cb7cc21e231741f9b332cc54ddc2e89d777e97fc04158a731a178fc5a55f5e9a0cdaf672b5c31388684042558916a5d0c929afb486c893c2a36960c436d04e923554934998a5c177e743edbdddc70394e78925b7539e939c90008553acb791701584eaf2485bb8ba19a949309018b0c9b5e345c4fba9816766ad710ed0db8c304e72c448f0adb4cc70c43e1138ce417b0f6f380a6740452f8f809da0d200458a08d8daf6aa073cb4d9a5187cf2036a4060caff14707fa966f02f510a
+TAG: 894c622329fa96bdc1624027e00a76cc89f7098b
+
+# DIGEST: d35ac8b9ece76d43f1497ac8681c5077398bf2ac
+KEY: 63b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f0
+NONCE: 6f520c9267cf7140
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3b
+AD: e585a29a2af12feef71e10
+CT: a0aafcc6a85c5270e19bded5ada3ce9e6884e94c40ed70ce85680c2655e68912e711404cd577b7f3df76ba1cf7a92f89ab0e4adaf9a0eb25068abf3c9608199e4ea0b2bf5d9d2454fe1e058005837679ecbd3e1fbb880ab33fec110f9b55157ce057afb96dc8b864c60dc5d1b39e6052a3db6aa8c4bc6a726fa8ba20fa1a1774903a5b1d3222236ce00e9cc8e0ee7a5091f91dc8413f562f741f1c7809e48f2020819119a77be04211b5f3570a0e2b1d40f11e23064dd38ea1a2e4edd802c71b907f828bfc9fb51366d0790c508e4dfa455c72a669399fac3503cac1ea4b048a70405bbc3ca13b90d706eacf065e880976247884b45ba112cc71f6f610cbad33b5a89efa51db8451247bc7f80c39acbd3cf97fada7d063a8ef45f20efd78bf48373cbff7
+TAG: 82ebfb084377ee47c5d7897414f633045775e1b7
+
+# DIGEST: a3b33fa67f5c471a60a63dea915333550bf3af04
+KEY: 99200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267
+NONCE: cf71408a41729bac
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2a
+AD: f12feef71e1063b0b4e6e8
+CT: 02408ff8a844fd105df2983bbe68dd7ebd45e9b0073ce6b23189e98f466acc9f693a01b404516c628d2741d5b37466a33a05975976902e2464f75201053b92aaf5bbab595b70e86e7087dabb8787d772dcb1cd6e8db502f59168fa26d806eb6342d3ec05b1906cecd68da45878f5d8b4946f5a7258d37ad3db0a3a27c22eeceead70b3514a9e33fb0f854e330c0dab9f7d2d97facff30a7d2e4971c06b05cbae135c8f159d12fffec70b8a5ddbfec23735cdc4142d733eaa0c3fa577d19a7ae08685e2edc332e06fb334a9ca07efae1089486525406a6f7b3777f1692e4fef8ea48d1a4018d4c262e72543a3506fa879346c0b25909e20f531acf35c53eff8376b8168d22d0c84853d66fb123fa849db9388b4780764cdf44bf88027ccede3816aadd850
+TAG: ac07e5fee69389005fb0397c9bf105edccd3eec5
+
+# DIGEST: fc45f684acf19a1dcbf767f671396e793430d7fc
+KEY: 3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41
+NONCE: 729bacb5877e72cd
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e
+AD: 1063b0b4e6e899200304bd
+CT: ea9a7f46e1abcd5228f7ddc3343aff2cb98c500d4ca0440f9d88cbe5c008165d65c9263b7e62ebf405acabc33a784c95398eae8779d5896d69b6954651517758db7cbb0a7916872fc5f33a7bc3f840a40188fa9a77af02e49b7e68f84e71c39025b4d6e4fba2b619fe1f84976c2df2d71f77d3629bf475f6b8823a0c4d89fe87b723ce2461f990249c32dcac08757e3f595adf6a6312c5c78f8db3c00f6d154cc453a8d037fdc9f8eb874ea278090d5d4db2562cc11e01846a77ee05d2f9d6c3774ce0fd3c29ca17f464d5d27f0474f5da8900c6a8677b5c065f2ee3c251d4343d84002404ee7af254a0475dfbd136874f81d0a71b6fec585e437756a000f30edda7b392954a34f59381a3da471c8b9716388ee2eba972b721ae9e3e235ae7671fed245b1f6c4931f3daf573
+TAG: ed5e9603d036ab0b1767979068c7fa3879c363e7
+
+# DIGEST: bea3f11679bacd98ddd996236dd603d319aafc6a
+KEY: 7d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb587
+NONCE: 7e72cdfcfa76aed0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6
+AD: e899200304bd3508132a02
+CT: ed8d7304d9aedbfdd669c8c11dc881b706e45a3430659081f7fb24732d1d3b96b5b2a011f2d44df44814a6215fbf5678efc410f5ecca4b787aacd2f1244d890f48d748659c7ff25e8ba5f487c85308b331f92cb7394be079f6bc2762aa07328c2002351a1c9b3b34c04dbe276468e375ac50e5b5130575d40f051e698361d3fc85f0eaebfcd3517a461dbff1b2ca6d2e932bccf36b9a490df8f0305d27e5063516d3849c062fbf1fe374902242b64860b6cd71dafca08a8fb4fd4984c25c736b6f1cf8d5d862e9e12399f756dfd68d42f8f7791d2bc89cea27bdd0d3c73c7e3acacb6fbf77872a703daa63c20f23674a410209d96ef52e6e9dca0683bacfd49cc98cd6ccbab221cc1aa0bf195d507c7bb678f960ffdca7d18ec178f4ab1c21b7221248960727694751c0c33fb43baa4a714f4f87
+TAG: 3a56ed03df7f802921cacb13af8f0fcfeb552460
+
+# DIGEST: b0ccc9b5ae13a7f8a01100af61a34be7ef6ccf6d
+KEY: b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa
+NONCE: 76aed06707a07c3d
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304
+AD: bd3508132a027d1ff4c047
+CT: a27f7a6f40bf2bacbd743882a2719834c88d28d9035215ba6b8877a6619dade8af89eb10d0daecbd38dffb5ed92888483bf547207d22a4e5896f8b9b104b272621c0515061f9a62beda4e92d14a5ef515149fac74b5c5fa0bf56e5dba3298513360bcb27e36357cbc02c5725a2614e5bd320db4256e3626fc66808d077e8b8b0eef256df46a5cf9ec8826ccb64d5e19d211e2bb0ea67761bf0faf2f7b2184e5d7c4f9ddcdcb050018523e799da45fa1219dc87773fcd8945c78a8336a6748b5053fcb9cfa5bbbf32d0a99f7b6483582d05766f7a712250499143a6a979a86f1f791d61bd840fc3b85f8ce65cdb78cfe3bb0c987dec4ea8ba7b684632e1a60a7b1245ebbb4f81f7ed773ed8cc79d47acb0e48d2bf853450812560d581665a2f6c1ba974457c91f7f312b9eed9633096fcc2c7f47d
+TAG: e115bc1a3bcf9d5100232470709a8ffac5c46d71
+
+# DIGEST: e2b953c833076a52442a7afab46150176c47b730
+KEY: 4706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707
+NONCE: a07c3dab699719fe
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a
+AD: 027d1ff4c047b3ef4f57a7
+CT: 78aa80f37f893c1dc21f20d518ae59d165eae38cfb3166aff256dddd657fbf8f478d623d1ff87fea241c2ec531f05449c77c3d9eaac53846193afadea6ac9ec104a1dd47b460575c61c42685f33c91ce3dc317e91bcb5fbdf17b5a777bd9cec373bc64618806cc5c1bfffd06f4f9c136a8d1aaeae5366317ba917a4a549c8b2980b4d44510b593e88f21fac625a1aca325a8ed79915b51388b2565e530c99610b1074daf3e4c8642f2c4623fd717fd1c84e772c25c99367960dac5d67f960faefaa305358ead95919c12116913e9ffa397132944091a27a148195f3befe9e507716086027b927326a9a706f38a260fa8a2d194ba50fc64d788ac647b756b78f33739319cfec7716fcf98e049249d5b3c47e1d9b6824bd7001d3e824b141e7d472c5e0eac99930b3b0f80b8688ab469bf2961e3d284f96e4720fc04bf
+TAG: 2aebc63532a4e6b2820e548d63f52642c16e7bab
+
+# DIGEST: 8e84935ed1bb79dd38ae38924952e1105101533b
+KEY: 1c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab69
+NONCE: 9719fe882eee2fee
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c0
+AD: 47b3ef4f57a74706de4b38
+CT: 9beea2482ed4e87f301b5c360af4a181050cc895f96af12a7fd9d696d845e4e9c39c95d716db5e96741dd888a2c9bcca7213222a136037fb3fcbc54ae922206a3256f7871cb99f5a43732cbb0adf4d2a76555e6a4e5168c6759b61d402a6432cd3373396b3dca9f5e1b282e99e94ebb51857a8355af238d42b3c84bad7c8b48faeb081f648c8067144334a712af278559123c5bef34d8a40f11d239684bb7961698aad69b6bb2d0d93681b647ccf17fcd3bac2ffea4f818833a6e3b0a3f4ca23f6c8f43b9adf8052b75c6ffa61ff449b1fe20da621953fb3cc62a3a6a51136bc02720aa74b0e9fea462f7dfb3bf5ecbf014bea5498c375e07e6fd473a0f96e06d31cd6ce8a0bef0dbf4feed11be7ffcc162fcadf1b52070db736192f51935f895b2c0347fad7000e5465ebc9a975b482db313df596443c5cd2e94ad7
+TAG: 16bf10e9c9f277f9f85e5a465512bd3822aced49
+
+# DIGEST: 99ec6b669dbedbe99548117f37189e669fc5d8a2
+KEY: 101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882e
+NONCE: ee2fee55ed8b1153
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57
+AD: a74706de4b381c692ef164
+CT: 85640a969f9287cb5cb08444124807b42aab51e2b2ab0c9dd8b66d40c1888f2bbd2cdde501bddccdba759887eaa74dd7e04b2e63f352412c39b3c41085eb1f8e085d7f43b4277b257557557024275da5ebd9b9448ebca8d21b22a8a62901fba946a4d640787b6325fbf1b482ec5a9a493f9816c292c18ef4191a7f646ef897aeee62d65f4e14e83444dc42089d1851bb92b8cf2e7885cafc570729751986fcfadd45be98e2fe6a4bfd31d7f99b9f625eb949ffd0102d2828f427e9311af63f0b2c734ba0fb3a2e61484e902288a528568e6c9c22a74d02967b3f6dad74d83870ee68fb9b3165fb613d12c2e98db15e23f2b5b0ae223387a369ca590a12ec20f81804edd1eebffb1deffca6b83240d53068812d8b6de4b5a8b6c215e320b2f73ef68c4e031104d4caef1a25c125a58373a737eaa1387527f5b1b6afbe36203f5bfe9c2a8e
+TAG: ca36ffe7fedaaa28c661b2750759715ab4aae9db
+
+# DIGEST: b55f018cb06f74f0a9f76e65a23c1744ce7535e0
+KEY: f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed
+NONCE: 8b11534c870dc695
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b
+AD: 381c692ef164101b89b476
+CT: dd8857dcdc3f407b615e38dab8c9805b5e1eec446d43ebd98dcde611cf7e73c8ce0d3c94b882b089566f0adfefe5d12ef9a79e6914c084935374ee72fdb565bc05bbf4c5185963081e332dd691c39eaf677838a7c4736eb55ac741faaf5d84edaef5f319c3a42f4a3c4e152e7d7bc1d01f9b30c2bec803bca56277963d8b3cafa482f089a67ce2a378275d2c5d2572b8368bf684cd75bc21af2bccc2ae3f3d5a8250f19632eb77dbf8a0007604c2aa432e2e775dd835290ca499a649c9c0e40858ce278db056c4263b11dd2b842ea015537d28497714661db4f6fe94a80d8414f5f651b8a752fe93357fcfe7fd60d7c843834468c9a41372064735f8a58242a32596cce9db4f9daf89c80d5ab4f8e2a4b4025f1fdc8f6e8e13f42bf94daf4e86a8dce092954cc9f049660470d884c03fcb09cb5db4dc1822ff9d7f18f4d9ae5d691f64f041c0bcb64f200bc4
+TAG: 165afd8a78f51c0fd9b3b8217409cdc7e43798bd
+
+# DIGEST: ac3202e483c67fbcdd751950e1497feb3ebacf52
+KEY: 520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c87
+NONCE: 0dc695b814bdf1a8
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef1
+AD: 64101b89b476f72b27f06f
+CT: b993d988c55b57cb5be8ab951b5a5054323f1ad55a6bff6252f466201f773473edf0a2b33bc2362f8ce01d99975f5d17c42b11c81ec1c06451ed74ce3ca5239eb0c756b09dc605b9f8bd9fe038687a99c9d645f50df1c78cd627591edba6601b54c84c859dbafa21321ef4abc122daeb3e87cc0ba3c9849b5d62e0385b9f5d404996548ebd02fac8eb55730f02cc843fd6e1b99a1b2f4fd0980d1c466a9be94adc1ee4afd9179dd745b5cf3edb7e343a5facd2033bf8daa8b039098f041b51d3d15439590ac686282df2d214546627b4fdcf9aa24932dd01f5b01d10a8cdf50527b401e17d8bba0163beea29f425761d8007190e7b195a64af1324c2053dbea5763ed6e4933a178982d49a9d4cb4867e1efe619dd1de29a2e1342f04adad88c627946884d97351d1c67ee3f927001b5f35e595ef40138798d613e07ae5d145565dac034de15c347149caaf99
+TAG: dff0c37999c6737db145fab4a31a029bba1bd98a
+
+# DIGEST: db82ae5d79573da2bd7215485a92063861879c3c
+KEY: 71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814
+NONCE: bdf1a87bb1052c67
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b4
+AD: 76f72b27f06f520c9267cf
+CT: 1f7e488dcf405e8d8a6475718354005133e6801cb39959a371eda0cc70981f886c982c85d69c1bcd9e6e8c2f03c63dca22ba22d951e1cf9fd5f54bbc8f4336b80072f8548106970fbe4a00e97317a59c9725d00eaff09ae38761b1f01941fdab07d95e3adbff674c1a9db46026bfa09ec648239d4e883f96ffc80890c06070dc9ff7cc31ca850e8619045abef74c0978b1fa585fcff5d00ea8168f1af17d18063d8dac5beb8dd8b7ce23cd2574cca2c31bd2412806ed1b82f1d4b7ba7072e52e15ae4f20a9cb4aca53a212d853401bd09a63f40408805515941cfa3173402663de0495dcebe93ceb9154b3ed57c015d4d1591070bad10194f88355b988a22dbf1cc4bbe39ff3567b5dfad7c806a7354f0e978fab21c3a8af7ebf1f99f56500f65586a0f6b0c45b6917ea51c5145575679295af5f171d8247cace787cec9a7e9d9985e483723f4b103ddfbb11f6e4dcb9482c341a
+TAG: 61df47dd4d561c27ed65be50f936e846465ad99e
+
+# DIGEST: 902d703861f9872e7b6482f854709a214aa98731
+KEY: 9bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1
+NONCE: 052c6755a7a116bf
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f0
+AD: 6f520c9267cf71408a4172
+CT: 9835391a91a08d675db2ee1cdef9bec9fef0520e918b3555858a9d39f4b0aaf88de033e902a1d025cf6e4e3a2bf9484730bc2daeac2d08d8ef198c8f0e4cc99f65741543c4a4579cdcc44fe5f20b64d6f3d68cc77c3d9fe150916c1cf8364c513fadf3e2f3b958604c9ed1fa41ceceddc8b4840a9098c7cb89bad01e4eea5539697a17940abcb2952dcc60a60582a96d5f8450859e42bddbf32dbd41007f8ad87c579722aa20a39a804d61d6bc7ad5cbfccfe2a9e8365658212944213ae9e7e7a764078d0c871d31f758dda7ff012cfd55a2971c997019bc24d37010e7db7159d4a88deed965509981ea447369e09dc437ccdbddc0f76b5827aca8fb7d6d159cec2b6b57eed832aaf508953cd58aa104245b6487a716a0db466ade98085394289ef445afd6dd10fb7fa6bf0747e4c11f482a552c9edcde9ea68d65db558c6e38a3747684a0bb5622211b7b860b743ddf670adee58ca4dd4166c290f2
+TAG: 91b47e596f06d0263cc60f14bf4c16811e6a0ac4
+
+# DIGEST: 4becd26b9b5c7bf831523f44cb72c8e50ff8033e
+KEY: 72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7
+NONCE: a116bfc9095da49d
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267
+AD: cf71408a41729bacb5877e
+CT: cf28f31b6370e2d3b7e7d1e7a61591099edd311277d440026c41a81172f2fe78595dce07b9853b879de6730790bde8dc13c283dd0d007a26aa587ed9fdd55cf28d60671ef85e6b4731aac6e31b64e0e31b63e51f4d90ec9ada97d80c9ed185d460ab581167a5927157a637fa57e11300be1ed2b0a8f36c886a59f2fd8911213b889ed2d111670ac138421533a71f6f9e165da6b4fc1cef541db35d26cac57306d12a09a603af22f8abfb3700ffe4201b444a7de75f0178eb38fdb6e9265bfced71cbb75fa8c588caa899b45f1ef6f74378edc9f7d9ab33ad5ec441b5a81696d6640fe2bdb302e6df3f0c6b3aa274eaf15100d8b3e5a8587f01511a9374072387de282e11695565ae9dd5039e433be5833fe10645645d5eb645ca5615160dabcd8302801e61861907422b5946ae518f8c5428f7ec2ccc3e1dc29cc1f319e9e1a2de3659feb4862b835615c20b3316a9eb867a3a3be67bd316b9c7d25c
+TAG: 8512d6d7f4b995072e9245f31df90c9806e57a0c
+
+# DIGEST: bcf4785d0e3b34c55cb2505b559fdbd525deaac6
+KEY: aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc909
+NONCE: 5da49db3d71f4b97
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41
+AD: 729bacb5877e72cdfcfa76
+CT: 9e0544a68ddd604d2199108e4bec3fd17e0635d3cc44cfe31e81716e90053dab65e3a2e65324b85e07aac633e57ed3747757e8a6aa898f1c917ed2ffd4bf46cecc2cfdda6d187165f6d6fca1b2ec8947e11e3b78c067e69f519218c1c1defc7fe1634b83df70397753df9057487bcbbd09802c969feaa2adc4257338944441d78cba4bd8c601c92b8d44c950b12a565d2b07165ed4706207d2ccacba3d851cdcd4c02d5d3110e7a8e61ae8cc1c0162be31df5f4e9a2e7e88cb1ee6b51edf758f3630a9122fcbbb8979477e19d12e8ef500589fbcd9a3d57fa11103a69e4813bd426d54772c2c3a94234d9e030916aae54ff48082f2c1957663021dfe335225701d062676c28233e5405bd5dd5d78a49d33de19dae786b627f32c1ed8099c0d2900af6ff7034dedcb31dc32fe16aa6daa8e763e336c675c393dcb575821d1968148301ad88fff913bbcd38726cc20fab0e4ec9a168b4fbb86368a0ec4e8346c4fb5826a93
+TAG: fa7edcb8541048dbfb1e7ed670050d37286a5af5
+
+# DIGEST: 13bff121568d7c32b2546132cb4ad490cea9303d
+KEY: 7c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d7
+NONCE: 1f4b975c5d503f47
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb587
+AD: 7e72cdfcfa76aed06707a0
+CT: a125f7708271f724413c30a2cfb47a0ce5ab26a1179bdf71aba612fb45d9d08e3f004501070ed0992dcde59c3f247a4c0ac88926b705ec95929337f83f75f03d3f8275b8cc86945ce07354043303101cad7d4492fc7e79ab084057908f36623f7bf504d88e40f586c27f38a28bdcef6d3f6c82f55094ccb3a390c8f847435bd512657e1b79ccb472411ff9eacf5b7959f5d8fdcb0342909c3997b54a391bee7ac17d6023d2749a2bfc03279f354c24c7e2bbad69d3a5db33dbb594facb70ab0f25668aef076dbcc38729255539b0a71c3258307aecca0fef8481d2119baa4da7b9425cc9554365720ab8cc989a3856040ab6c3076d5b17a5a5525360b11b5164f40ae45a14150086cd0d9d7d62438ec4603f1cb0d37868322ece5f8b662c2db2c01d2cfdcecaeb192941c4d552d0e720f8894a6b5fa9c3945994c2dc1b5c3e3aecdc891837d32d56d668fe0825459f346b55f8749fab08e33d917bdfd49c44418b2e2df6
+TAG: 7b3d73202448992d2e60fa805ae91da335e6b221
+
+# DIGEST: e0ec91f0baa3c5fd0c50f135517909e26c204af3
+KEY: 19fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d
+NONCE: 503f478b22dc8253
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa
+AD: 76aed06707a07c3dab6997
+CT: 4620522fa922ad1c109fdd7e72bbed6af5cbb500e7ad342153318569f9b9c64679e62a95323783dd8ff8554b9d7e1bf8639987f0ddc36024b678257d8d85867a0c7099c4df600b5d82fa1a29b02ac60169fdd49352545c1802ce02cad363341e779feb7bfb7b6efb9bb72e9cd3bad5f661e10146eda469c1c5a44287668827f6ce4177a7d30dd57eda8b64c60e299237eef7637e9a9715298f9d2cbf6fec1a4964f54624189f56453a532030f59727276c628864a6ab4742d4f0fa830a73485b1d308f3aada4f29c4ce65d1b695a0044db415473a733f822c8814aec498d8783d84c4da17b9b13f18ed9721a381ee29b29a5320ebaeb0b72a3bc756a7511560a63a80f93a2ee051689c36278a64579d60f50087a55e9ab79a7a2f2a5a49ee31835205bf540474b893311cc0d10e57ee7b3d5db12adc35c37d7951eb2b5a8831d8ac860a25f22c4469bc5da7be22dec424187561493a6b0aaba687e01a5a9be8ec31492d6a263eeb529bae15b
+TAG: 6a196d99256fab0dfaa692394d20f5c5f5aef052
+
+# DIGEST: ee7d6f651db434a281b5cc57c2c418db731c65df
+KEY: 2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22
+NONCE: dc8253bee6fd1b17
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707
+AD: a07c3dab699719fe882eee
+CT: 5f9a0ce63065aac2eb142de993023141755e120551f9b0f82eee280d9f6c8294a99f6015cfa2824a58b2e072f5a5e0cf624a6d10be31ccb78408fc4de6dbbeda4271d913a8a0d94c0da522473442cebb2c17d39e776dafc9c339b8f03b5821b0e6358a60e8707a220bf94ead4cc613159857174ffbece4702c1fd6ea6a815764311917c9fcf8c457fd6f79d6885084ec126172e629a68914ffe68f035093e0f1b5dd1718d221207930e380195faa5b3df86e21ba4db7e3f60ae3da641b557c843f2433a295c0490ad05744d3c51ec7271d548fab1f13c050adad0ff21606cad85d5730c7ae12b0f9b846929a1691916ac20ecdf7382f6f83ce1d16f69703bd9d60054d5fc226c7264959e0a07989bc5cf683ee0f9c3eaa5d071e52e5f4e477e1bc625af537af1a9d131dd6202e57646c051ceb235c6b6ce9d164ed1d63ea079f024322b2c1c666a36328420f5cd664a7f26bfb3f8940ea1e36daf466f94a710ed21fd31c6309015421e380106bee468da857e39b
+TAG: a6dc72fe43395d1061d596d4f71968c6ddc01064
+
+# DIGEST: 810e1f01bfcf6bc13ebae7861454ac133b2d6cd2
+KEY: 11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6
+NONCE: fd1b174c307f01be
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab69
+AD: 9719fe882eee2fee55ed8b
+CT: 048e188527cd839f4fc4d7ee6f21ac06c1a9fba38050b6d8fd45b958696e447efe78466a0f34e5d4c9fded7dcd42316ef86f66962e54b2c8495d67a098f4e568942a6401bee5a44d4ed5bb4e6ae9dffa4fdeb618f9d3fa333ddeeac248750e20a1646d51c226fa5ef63cc6d13199f81973efd3f2ba55f9317623f317da33e16687ce9ab95f532af3fd10b62ffd181c60f3cc622578d8c17fcaa820ef67345de78ccede187b6f0c66119433f0264994007b0d48087a15c49fe4e88a88800a75702b4c0d1ed17cab715205ba7ba4bc387a2eeed7ef0b4358f1d2d52f7874ba17e71fed166443e38aa9b4d99bfb2af39e485d10d75d5320e15897addfbdeb731943778afe1ab3c9d5528c84c9d9ddb58c7ac4b4c5c183321853ca84299ea8123885ca3ffc3947ab681b5359ea83f30a16358607b329dfa016cc7b5ee73d005738ff314835d9a4442fed0d0e7b8e4b165f35d7e5b78b8d743c8f3e6e0fb351acd07ebc3a012e12a2eabcc94b0ff9c5cb8d7500790fa5
+TAG: 3c76dc6105cda6576ddbdf2efc62ce97030f1ed1
+
+# DIGEST: 881551d50a849b7e81f0cc0d722f631e32a4c97f
+KEY: c695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c30
+NONCE: 7f01be95abaa9bee
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882e
+AD: ee2fee55ed8b11534c870d
+CT: 1f60e24ba352c5b6655e78292b84baedce9a3e9c26c6eae21c4a0f3e6d6c9a989cd0cefa8bf3fef1a4b3c26452f9add15c08dde77dfb30784a3a919c55901f4e1cae8236b4fa04ca4b64d0f10c6beeb289fce85dc964cb69f46668cd9d422e78e93c749fa46d25dc4c6ffe09b427b303ff7694ea08d667902a1544d60f55f9843d4077d938cdfb31a07af8bd8db28dd004132ff5fdf6917a787f12360171dbfed0c1544f4b4e1aa6f9da799047ffd2626bd8da9619588c957f0dbec346bc2a29e1e50b52642859f66486cc5235d268f3b75a81c81efa50b83f74513891c76b889183611808220b8434d1c25c201425238a396a4f126b9367e3e4174f0e4b6bf665c6f2fc75e50f306687b87517662293abe1c6b921886a5a86b8d898dfcc9d4504ecf80294e4b5137f6229abb764a9227ab564d788d7c3966c220f36880ab316f7b2cb5b670a4178b9800909dfba1004a07aa35e6b604622623cf3cbdddd23ba0d4cd6cd0b1b87fc929e8a505a4e7e3f07345bf3bccda2af56a8f080
+TAG: 43dff4a9fdfeb97629c25e784a32eb49e59b8461
+
+# DIGEST: d525f72dbdbf54db80ddeb9c2a84aca41451353e
+KEY: f1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95ab
+NONCE: aa9bee5857772305
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed
+AD: 8b11534c870dc695b814bd
+CT: 96bd8678ac174f2113b58ddc2409f55e233849a591f7c29b8e98926d4d5c59ca6ed22a695404246d65b4bf173d5c17f3287b21bcce3d29a30636d6f2279590f512bbb3a61c49b5b883fe0abb0bdf9a056448c90120741bf588a1e92978f5d5a3f6faadbd21583804de9017144ef0db3209400d12838434981adf2baa3213f63e62d75ca551818efafb37f158b0cc9fbb0214a556b0318ca981054c18b4d73709b6fdb6a48f162a2a0aab9d908b3c7ba2d13ff53ae64faac740193ed1f97bb5a13b41e0fe8201410cb888eb765ceac5bb20858eff5ba890a449938839a74e8b79b67828e1a0ff2353039e71538d9a5918ff8bdf47fbc0ec361c4b1baa8cf17fd6260953c61a920f5cb6a672d36ffe61612ff6130cfdfe41e6b78abc659c4f857f64f3c64a00e507ff21e3fc61015ef915363f45666167b058c822819e8a526316348c872838cca368c4ae38173fdff66e83c4e1bcd63d355dddbc9e63a506738e85e97b44a47db81a4d7e5468aac3fb4305e8f0e35fb76fbb89229268a50eb74dfd63858c
+TAG: bdeac9af53dece2c1c0de2ff4d5d5cf5105e3f54
+
+# DIGEST: b25882426b4730205533cfccc0da1de1f6f2c459
+KEY: 2c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857
+NONCE: 772305daa4b550d7
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c87
+AD: 0dc695b814bdf1a87bb105
+CT: 579c28d0e7fce65a25ef22ca8ee1e50b7728904b7977819c8a8e80084fc77fa15e4f1cbba0480dedfa6671434c58b52b4086979db38ca7eac8a5d47b5806e8f2ae41975ae2eb7ad0e00a3e55de98e16e3c9fc86ab28608e5f264db3a961d876fc673d43b7b411b3e06bf552114d5c0a4112e0781d61458ca15ac549dcdb8c88bbd15fad5b5c704c5e7b4f55f7d0f67eb72a099413bbc909f04085d266cc0a9d3f15d2fdee96892259dc34b43cf2a0f5dfe244fc5a6f840020b3cdd0859e9b4f552e460aae3e80f30e5c1f33599af834a343621b86e8b79ca09e7df8fbc307fa16fe93d81348454f26fbc0658bc19f132c41661244973bbe6fcfd00a43a0b7ea4b2633edcc281aef855a2dca4fb4799697f93f3b300e97cc2ea6a0a2e6350ddd7b93267c3e82b76200ac7ed7a51f24dc761a9741b7c579789ff79835501d45ea74b1aa8a9ae526deeeeb34b6f3684b303569fce5115068fcc38efe942e95232c594b1a8ff70010da995eb20dd56120411e96fa127588077ad202e4813d323ea0736c94e47
+TAG: affd879a5c946a7640fbb4e2d472e081b8e706c5
+
+# DIGEST: 939442486c730c2cbd8df213d81310e50534f06c
+KEY: 16bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4
+NONCE: b550d75f05d80898
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814
+AD: bdf1a87bb1052c6755a7a1
+CT: ed81399356ccf3a7813536e8c7daa4fb9fb23a3461ffa23c4feac92057fefa6a9d6c35c25b8e1e19ad8cfa541ae30964f9bd19d111f40571bd63246d736015670fa35e8c79bfbe03f19e102ab2dbe890bcc0c2ee152c30f99c209129729e265a9f497d40bb206c130f9aff0d0700c7cb71512b5e2dedd62cd1d6a3549907861a91015479c0c68b49bdcfdaa711bb11d1e09fe61e11a02d50189b6ddbcd4fdbe5feb19b0435a35003814243001e597fb02a2bc0f70f967674c9a141ccfcbd2a3d91f1794925e2c485d5589dc9ee94601f570817dad04ab75ebfa21339bb41b451213ae1b71011ad79737b44ec859c3b2fec5e344cfbc77f16ff1314232697a95e3a7a47e3880c7636c9fade3d79640fa4eb71fa2faabe5ed9ea92743cdce899ce62d92cf086608fe9fa8ded1b0e63d905c160e5b3d492c59cb67e8951e869274d14dc78f5fd549d19fb39a27befb6eb777efbe5e8a263de2e5ac9dfdaa0e44dedf32f15e899c60dbae56177b0134a7d311d0334cd4adbe2fc3e94376546ff8379e220749e2ecaeecc9d7ab54a
+TAG: 7966f9795c627d5e808e4a73b204c3c655204177
+
+# DIGEST: a7b522c0de411517839342925e8acf703ea12e8c
+KEY: a49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05
+NONCE: d8089850fea37112
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1
+AD: 052c6755a7a116bfc9095d
+CT: c842affd0db9acb0b1fa690c58195e0bd26c86a645607c0ca204858f40430e217bf7cadbe07592c3c7684edbaa46f4702523f12710b76de4c0464207744947a92012e6638c65b2e9dd8376140da2dc1edefeaf03b1c69c8d28ec8fdf2c780b11d53483f60f436e8cdcdacbc94797e084f5c1d76b5941b209c5b8f56ae6855ea0570fa221fd16dc386cf3fea08b17af147bdb86c026de070359a5f1e0042492ea67596981b34a4b318ad9d174ad10729ffb9664b46dffe80c90dbcbaf7da29194fe701c297a9082e00bcbe0d7167e7b4fdd778eb59fd53071ff15878b4c5871a69415f697d383a218236ebaa3b9e1453e7531021b8dce4f9ce2df6dc676b27643e02d39d7dcf79b71d57fb7b9d2ea5eb010cd35bc3a8961a1cd2b1112d390d40346ff01d2bf801bbe25992732024896dfd164c140cd3d8f112a5c40b548e498e6cfd050ffa2d67fa588b264b9f073f91aeb468c9d1c1a794affc85067dcdd756448a21044b337ae8d661f59eaa2f4a15ed7cf8775ff761ec9c0e2e0f8083558c46a04d42d90f1e773821c36ac
+TAG: a401b46e4fe944b49ffe8e4a2132c7f00225ee9e
+
+# DIGEST: f61096694be30b85b6571dfc8b5bfc4d364bd225
+KEY: 4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fe
+NONCE: a3711265bf782610
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7
+AD: a116bfc9095da49db3d71f
+CT: d86fbc79797d8ab9e1b7a9ef560b59afeb48ca8068956f7235297566b72b6d747a4cd2e0cf6ce78e59bdfb48c2508d7e8051fec253edfa33c3d124097a5af2f2beb25a3572401ba1498a22dcf30f2c91d31a5268aab6cf57a1b08caca948d1ef2d55e4a9350d539a620ecad97995952d7f99db82390f7cb0e596c59032da58f06de0d52b3848bf01c5b5bdc9688a90330e1b7995bd5156a775d886ca5fac3de1697c47c7076f73fd8232500c97d245565375fd2a2f398aba9519b66a7b880ad760ac822255146895a5e7854e98467ef8f20f12a1615767c7ba7f109641950cacdf22e49fc4277542960954a6de3a3d0e81c3ea98773ef28d4f2f93fa0b36189dacc3693358f2244f98f22d29d3d5233af3e46c4eb528fa74186542cda75291f9af3eb95f8a5ba622252f541af9ebccda76ac7fa8088be72379f6767551b4245f562dcdb4b0f1ec08c214966e6d8c4de5763a8f54d74b67a7edc83f1d4c81c7d5d9f7a114979b32b35393bec2c9bfb8ad180c6172144833fb9e9f07bc18dc7fb205625da03a5224acd4d6ec248b529295b1452740
+TAG: 3e32fd273ff4a18251e8c6da2bb025e8b8544dcc
+
+# DIGEST: acd9a5179a0ec782a63bc824188d838776bc1b81
+KEY: 3f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf
+NONCE: 782610460bfd24ba
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc909
+AD: 5da49db3d71f4b975c5d50
+CT: 2c03706f44019d51a43dd345ee21522bc48f76ea4de5bd65e16787cb3bc024d1fd6600bcdc2ea94dbfb9b939b28216cf9a52825f767a5617c2849f999423b2a4e6117b51ca2bae722975ac503263525759fe6ba7ea20277010137de25ec258d370a6d3e7e160238f07863b30bc38e9cf6ebe31d3c5dbd3b975046c48cb9b3b1c8756e3e396993ba7f49d15661485e640e09084219162654dbc9cceec6cc13153809f60aef7b56ded6640f3962738a1996ee0716a0143c1b8dcda8384b994f415c1bcc21b299d0e50a3867e9333eb8db49bd0d98439ea4afa8dafc0a3d7a4a6dc1054c2cce005d0a758aa2e6c951c8836e90ac6264a894299421bff8d654830c0c1f96fe2469b17c76f55d88f31f228b466a2ed6baac506159d80843ef75347b303cf194b9b737a13ecd07eab0365aea581dfd6bcdcb8a65788452d12d8bb63619ae949c872aa8fa9048012792b1a1ccc6c0b21e9f5865864aa1ab770a5fb8ae34d7fe28586aa624b1ba1e22d087745a943b73636ea3e14aaa081bcecf845fb328338a1a5cb2c63ed09d004ae806a49620b58d68e1438ae5eceac184d
+TAG: a3eeb77b2aaaa01216a7719aac6a597f7e36d81d
+
+# DIGEST: 152118d780c866c5eed3a08d2d9960cdc5acaabf
+KEY: 8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460b
+NONCE: fd24ba022e6da12d
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d7
+AD: 1f4b975c5d503f478b22dc
+CT: 6905a38b7101d66c121399c45c25fd2927a302c719d2c07bf516c076e5bc6dc15ced29b1a8e7b7ae98bd76078d09f6521ebbb9d7db384cb8eeba2f157979a35828cf7a5018dd03d38961d570a0a6e5662ee60f6be865c2cdbd6044d87b481b23e19637d05eba817430e1a9e9c06acc49ac1c6a0a9ed3fc0b26159143c134acb1f3084fd0c729271727548d84a20df2bb9391bc3abd008d391f33a5b015ae34613a1bf1f266ebbb4a06a0ea234c8b89dab2d8a32900f1775c94ece7c03c3b120355f62c8a8f368bf23ddb9ab8ae316350dfe709ddf24d499082d4c61084063ae1609c1aeb19de2becd8a54ccf3d4c6af8b81c062b2fc20f1dc61bae6b8d6bdf7449594f146f5a29c7a45c334e3cdbbd59286d06b3b9bcfe4aeeb97089cd0ddf46824440118e7064da58cb7a30d60d3ac2733818c157320ffa8bd93295ba7499fb7ba3892d23d6994ba0d0049111fb7be0477a8b3fa0360e4f461049b023ad16a2997120a8c9721eb6a2ac1589bee7a326d869764faade0547893a44eacba6e7ca3410c3cc29dcf5c164ff17b62e6e4481ea400a30c5f9232b923987c5
+TAG: 42aeeaba0d6782f4494e30c6d33547fadc0be100
+
+# DIGEST: ca91b15125e07b81debf75ff84e7eed4da5808a0
+KEY: 1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e
+NONCE: 6da12dd4c27f4372
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d
+AD: 503f478b22dc8253bee6fd
+CT: 1ecaa428115b590cf1e175c4f8bf7b42d036550f620b8b594518526193fd5f24cb763fafec99ab08ba81a89ac592e04e8b8ee7f18469bcfd19e2ec65c60203ab2c031abc272af778d2bfa5098444b989102349e2bed405e4eda8d1c7e92d71bde05d85ae42b7566ac6959dabc73346fcdbc9417c937c828ef8cd2e98407cff92c32f288059aacea152d4d458fc5bff26e342b5e40c51c1293c9179d43287f1939e1e4a4d1dae80a8025eb2a4b4dd797d578a19202a7454687379307089b8a4987a59b67204770e2e59e45b9dde82b53c7cf6191ddb0e3351bf43fc972de128b8a615c541d3828612da0381375f171c9f341dedbae3ebd62a58f031a68fbb6526ea1811842acf9dba06bec164e77a4ba9dd4cef9a939b3228f41c8124a5079a046ebfb0b8e0a6aca18875c4363a46f54377ea2012002d0289d82500061791bfced04f39c01b348e33795dff170cccd462c6425c492633154740bffb4bfcb5649a96af54fefc76073b39622fdd38d00080b440a07bdfc199ca727fead42f927560380b944b4e21dbe64b4ad4542a1f1fd8168541d2bc094ef215b83d2015256c2ff451c9ea
+TAG: 1b44a1372c1928b835131fec54635aec481f8442
+
+# DIGEST: 93d06638fe1e836ecdf5d30db3e4fd0660d9d701
+KEY: 01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c2
+NONCE: 7f43724809744548
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22
+AD: dc8253bee6fd1b174c307f
+CT: a32714b057f0a6976c38b30a283e2d3b24406288add659f11900a39378291dbf71c1b9656b8f4815ce297848ab25c492ab4539c4ac70c21a3065ad49b5d7a80a1f757c084cc84e7d3f6132b85dd8f450f050b9cb63eee49cd8e4af716f21119173e53ce84786de262e5b0d1595dd2f901347bec4c00be909b004139ce0aeb502f1485f5e6b179953ad96af5d73eb280400ebfd3bf9435c4fd9c43f8af0447e70c9d9a05c8bb90fc2ebe2954462a7a5fe3a0d0ca91f65bcd570d24cbbd82b2d23169c6abb64efe138a1d3f206cde8606c73a303c34a77d2019e8354ee75bb3d4faebe204064c481fc58709cc6e9742b62f4ed6cc02081e767b8c5ca1f81ef8510ed2d6814a14ae5b2fe0fd69cb132a0147db024e34ef526664b67f47ec97eeaa42a0b2033213ae2c8b4eb9afa86ba4c6957a20a02c5c5678f46c0695c7923ca3bfa281dedbd3ccfab513b742410e0e9d4eb6c32dbce9a566aab928252c883d2f1269a81264b28f09a264b63212f832e256ba146e8e194d4d35218628fea3c225cb396a3ed5a549dd50eb0779eb7d5bad23c2870ee1641b655d791940e62cefc0c5a75b2f48671f568265d2307
+TAG: 027f5fdc0b7249b7f6d5291d7eb020effd5d6d25
+
+# DIGEST: a12c8aa71387379d0e43afa0321979e018d56547
+KEY: 9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f43724809
+NONCE: 74454879c41de9ac
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6
+AD: fd1b174c307f01be95abaa
+CT: ad53040b1f2d39edd352ffa3f7c2bee725c7c5a95a5c3a9a3b189f45298e763ef830b91c562a567f16f4f8950e88419c9c6d17bf96dab4d9a52dfd142543495e9cdfcb48945044263e3d47706644149e1f133a259e0ae01b8f36921a6555cfb3017e957fdb3531f26cf37f64484fd02d13c749014ecb134a4cd3f0e3580661b44eaf9a9694ceb1d5f12055483715ff7df94226226e2baf1b835661705303ec2a49cb305ab9935c755e6dce98b7088617017c69fb4383b6e8a0b89dfde0a798dc90f8d286758c21fb7546e47a6c489db61fa01aa9aea7316598e7e536f29d852ef09ab538c1db4f9164552b5a744d0f75a48d556a83475ebda7c6e04b28826b7f08547a2b4d85b8d986f81d68f6588bc62b639febed7329b994e2c244e9c37f35dc7abaf805c9a698220c463a29ce0191008ad39abd133c59d4e699fd79b5a1b8edb0c448b8c2170d2401673659e1808cf67d44b0561517d0ae1d84c7da3172747d5e61bf5b50430d55dcd5df3f7257dff64fbbcdcc2af84edb04ea0ffe7ba23c20dee69bd1754d294df1ed3a2be638b2256989a75cd56394242eec3c33555a1f6dff4b81d0380ad02e46da0a
+TAG: 818e204a564339b5b9dbbfee647a9c4c56bca1b4
+
+# DIGEST: 8a524c3ce814e3059b4c7a6ac748783ce1385c68
+KEY: 2305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c4
+NONCE: 1de9ac9f98233b5a
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c30
+AD: 7f01be95abaa9bee585777
+CT: adfb293df114fd3899f27e1f8ff585467b2e99c50dc3fd4b0e1c9cee420541e5c2a9bda905434711f5a6ffb0c0d22dac841021a2962bcb189c2b4e14dce830d34204adbbac032779140050fbd8f531f9c67eac989994c966b0cdeb2c2cd018b0ebcf1dcba1311a978508b48fec30e1619b54030f8b2f104c5c98df5752bd5c5eaf3f957ff74178d43bdd4e1ef73ccf5f411c7a35a34691fc76b195884e4b5a861ffec3e4d4c0f39dd8144983dac4f651ac42de781376194ab1fb1feffcefd82ef941e87ff6f3645c8b86e6b78ba90748cec8eced5f2160f04d8137816b65903d0631855b8961b679956f07111e3f911e4ce55fd709c9c0028791a80faf75d5f13f38e7dc398d25a6e60388c87fc5faedd6d823924b61e3dad0d95974c955e34d0650f9abf8567f3602b62851936af67984339b8070c1c86ed87f433571d5e8c2eee93c4974c72e698da4a786053235f2fbe9d93fe51decfb1282efed58eb0de91156d06946bd7f1d06b3a0481132984c1ed68d407214340fe83efb9ae6330934a66829d5410bf7b40dd3bebc398bb7be276742d7dc0b51b62c444ca1482045c79e36869b23a86a15cfd79a2e47bf9367f9679657
+TAG: ab2492511c8fc94d8e2d3624b8c922ad2ec4ce2d
+
+# DIGEST: c31dae836928083019ab6902865d9f14c88fe27b
+KEY: 50d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98
+NONCE: 233b5a7379a56179
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95ab
+AD: aa9bee5857772305daa4b5
+CT: ae447789e7f899988d7156b6fc9472468af03c00dc6ca394524d88a47a67ada94e9e851c12b9d3066426a1ab23b9cf21b8c193f66304426e32d539073de6e08cb9c5fa2923913cedc176af8225a238f5c3bf697347e7c13a33f11891ee741446ec5b972686f9e3eff25f749642781aa323d85bb952d31249e72aa7b0f3cd45165ed0572a7dc415996dedd4776e626459487a68d8fbcba8566ea893630535e10d0b5346617a310e582c4bb78d7761f41062553054425b99075bc7bf604a22d6e87c84602ae8d44b5b1067f7c1b0584d80b3d2be7054bfaf3be923677528f61c892e741c2468347ec41ef27f672117bd588462eccdccb3395e31d20fbf2267244705b4907ed85022b767374d4ad05779e1b8dc5c6196bcac0b482c0964e4c406c29e3ba3888b60551e7a27e17034012a891b8b540d0ed3bf82709eeadffb58accd08ea02afc1d6a5bcfae160dec16899a0ca7b7977d9a93869657cb7d58b6302cbc664400430c550a5a5e62865abcc50447d2cfc4200e5300d81b1c5c7a8b1e526c4fb96c2b8ef59c2bf6cba5dc88f47dad6d4bdf02add12c108c659de1951177c06129e5c5af6089aedc51aa3e6ad954f5760c36b
+TAG: b99c3f8d2786ddad9968674dd638bf3fa91eade0
+
+# DIGEST: 4b2db052fc8a09f7a0c26afc66dbcd8ae5c9bf62
+KEY: 089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379
+NONCE: a561792c0f311643
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857
+AD: 772305daa4b550d75f05d8
+CT: 9cb162540153657eae0a8fdef64af0d94f20b838ec1fe250294f8919d49d70441fad4f7f5613aadd13e5bf0da947cb23a1bae181fe70da12e53fc9050ea773bb62718ff9841382035c4e0bbf77ecb0df7297b5e2325058efea121e78998b66877357e554018ac5c3011c971376cd50ce9b43bfb2d851e316a111b209fa389fb56abb674a1b07392d2eaf1352e2da821ed02261d5188514bbfb1b74f48b1ce9986f8f0acd8e16654881e28a4b9631f52e316aefff2a5f53352659335b603025d86c58fc18c4025a474f87bd6afc069c5b317d48d840c6d374c2cda4e66502cea13605b007f415e9b51d13630f01c604952f4af68bdc4a8fac43a8c0dccfd22ece5e99bd7f0322195c0066c5b8b6651d36a631851d9caeb963813fb218d291b1d1d703cfb47ab0bc949b2a245d22cbca57945cc357e1271de83b8f4b84766e98f1726c57a0682e78d7c4f2df89072917e634fddc5f5844161bef816b40945477f1200d57eb2a48938d9ea8894eb10c18675848335c9067e92ba3aa28038c18c8d5b1a0338a0206243d568ad8e403d2132ded8ab5364392ac6f712b157f31a17193eaf89a90c36617010472d0ca6bc01eb025fe877e5aa3abe3f97753e6
+TAG: 5be6679684115c921a3741e79448f5c773574164
+
+# DIGEST: 881926d37fae9095362fff56efadd9fa3c455ebd
+KEY: 711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f
+NONCE: 3116430e8b6ea058
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4
+AD: b550d75f05d8089850fea3
+CT: a47a7370a3536722c28135e6721b731acd648eff5e3438a9b7587e63566cb6c47408c3afa71daea9e90a2af1c4ce231d0d51106ae1258793c79ef355c827350a01b32b9c77aa2e4815d409f6a40755ee5421a48643d39bd8d584cd10368586420229061a201cd804eed227b039d14fbeeaf3b768f1380c6cdd1d6c819c8c065bcb0e43b448e757dda123452e4351f0553257580494999c7d9355d6f1a8965b429e8322cdeb215430d524dda10f1b85c2cd7dc3088a93cf4c6fb922f13bb569fbdf4ebb9ad392771058ed8a2e41fc0e276c76182c36c35a0235306cb70f9bf40c57ab1b8e74398584eca10b05713fd1c0c580f1eff62fc54a8e7d7339ddbeb1513605d6da5c6c2bcb025ffcb00eb92e709d4461800597e58d2684083e7d1b16c6a45654674677bd785b5f0e2daa9d282f94db4283f9a1648ef65dc38b238c7a58122bb4dcf4be769ff0fb7dbc412e62fcd875334390f22f82533eccda89593b52eca8eef8ee6b1edcf9c91b8bd2258007540028f86699e8ff451563c6adc62ade020ff7de6a0a58a5e1511aadb91a56eec10dec230bc05fa1ba9b7d3b394507fa1eb221397399a625da14f82f744468c75cb7b9995cb6b39d2a043cae7e0a393df38f5898
+TAG: a1948eecb32734d870cb49e3f755b695718b8715
+
+# DIGEST: 92d143942e6ef5b44ad7a4b8e71c22f1ecaafffb
+KEY: 2610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b
+NONCE: 6ea058c4799eea80
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05
+AD: d8089850fea3711265bf78
+CT: 79e6fb673b8e28503d4195e41bf9128add6080cf49b2c899a8faa6b12237eaf7bd1d7c24b457857896479e3fcdec2bcfa342e77b9046eb9a7b338d803cc3320fffbbc5a57cd5d46c5c1689bcc323eda5a6368e1bfffebcf4bd330f87e82886112a9fedd396dc221ddbe9685c31eca34783e12cd7d6fd323a7d5c6c0b9dcd9ed8d44f157552c72fb7eb4f733865a80064f5b456c4c57c00163103205e6391996ec34d33c7fb5f015a9a6577eb2668406dbc794b8f174821d27b17f8b6be398eac7b60afe0091a4e108dab59c93c910bc9ff33a4f26632e6375287d63216793daf8ffdc91f24c47c526b3e555fc86e5033add22a7245cc034a4309ca95af93fb618004073dd5eba2eee79ff318a3823e3e1469ce57eb4c26c981bd2f2db7888ed23c965d154f1576acb4da3d14189d9ae1d86ccd48b4c34e543a88918c6468d563f170c32b394d6f28fe0a10204deea94d023abfd1960a997a3a1f2cf73692135a917765f73316ad5b643a980c8c25db0666f53fa09ebd35e8c2977fd65606756c433edc1b4c873e4a7fda943f991d31fa10fac66a6952ac0a84e03e9e01341517e6615cccc746c21c221d29627351645dc0ffd19fd7113702a9dbab25429aac3249c9bd28
+TAG: ce8d5a357f97b8b1efef74441256eeac568d8b29
+
+# DIGEST: 7fcec4927096421498e91df912cfe43b2e971d4a
+KEY: 24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c479
+NONCE: 9eea80abde04ee1d
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fe
+AD: a3711265bf782610460bfd
+CT: 8289205f7b42867e84796a5cfa5c21216202eab11e889530f145d25617278284b4dae14c33eb4ac40a685c2c8292a83770d20eac9fbfe8c2c2e4937ce7b82215399c3a6605f005513a8dc3866a9c5e1a98379b07155a49767e51cc3ba8ff8c254553f1e35b7d894717deb92db7a3ed8e3ed28f9d9306780e05414a0944198fbb97504ad59c0f7177af273382a58e6039378c60fc25416d7241cc4fd23c83af29143be0747797276d4e3fbb36df003a98089fa81114e865461cd1afa098005f881d5bc51acc1775cca6d0ba773c7c0c2062bb46000190f9f0ebb90fa575b14bdbb9cca733b679070a7b8315e11976c72ccf82dbac94d75e51fd935445248a7838c9176ee6b2730893f7c9938a073049f71cfe86440713653f9492423a5c68e7ee65610718bf8d7a0dd3447cd7c7dc2827c6d1b32f7f4541477ad51a64195a5dcb2215073f719e53b90b9dff91d092f47668ab6440206b1a8d87e474fbae41228cfc43d6405205bc5198bb7e24b7beac464ca038cfd7e855d6b26ad0c76b95ecff0661833083965934c7d8d26b47e0daad1f153cce07363f531ea4b37edb5f049f88a4f8e9394f65e9e37770ff388adc6f3c4cc5b394fe37d316955426e87c807711abfc1991adc5185ca35728
+TAG: 366760f0493e3723d9b6d839dd3242cff0268151
+
+# DIGEST: c1c6273ce723df9f2033c7150d466c011bb457da
+KEY: a12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde
+NONCE: 04ee1de13e937af8
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf
+AD: 782610460bfd24ba022e6d
+CT: efa5fc01608bd42df1a0118169da12c6ce53ed259fe37dcaf562c178557bd4a116bbd3579b382738ddf0114d90e26f7d8b5f4043a7d6e157750dce5fe0878079cc8cbc86982da0b33b5e8af5033dc71d68c71d7f34c93ca5af160845cd8597b90c693bd5ed700c4710b7ccb8ae314f926dca32bc3ab8df6d305140d7404830d31c485edd546138c8d5e675f0019876dc36d40a10142fc209ff8a3c2b9be85651135ae0db636967993c253e869d6aef6f3ed29be3d8cb976390ff6286a56b59a628f2ac7a68406e096070dd446f71f60c4612fe01997d89ff29b55bb6809d22159ff039474b51600443baa82742282008440484bbd16c0ff92339e577781b5d84201fa313c33eba1d47e21f264370b32aeaa20a06dabb7a6e4a98b34b9c1d8cb171dbdcc9632cbdf7c2665e547ade3e4cd78f996d243e3d4548102ff340f50a7c23caac880070a1fbac1d3f1bb571ccdae2ba85ce4f28a7f1c1923ac45a53a885361a3cb4c7408334eb0696745645c912d32b9ebb735af698bde327c547c4e5e534b79349c7faa325999900ddaa25712e0c139071e6a82600d04a0787f5990dd28d4d65c140d6c8651794999e368d62b62c337454fe74622104eeadfa098d5a3c424aa87f37bb74664dedcb91e965b761a1e900cc
+TAG: 27d9c3f63fb8f31a80817178460c3267198c9e49
+
+# DIGEST: 11424a64d5ce78fd71b30a8070aea071d873afea
+KEY: 4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e
+NONCE: 937af8f1a6944f44
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460b
+AD: fd24ba022e6da12dd4c27f
+CT: 31db5824d6e3df47be0d38d8ae50105cfd5bb43e2f62a7997c28e4d4be40b09d48f020d9035e4595f2896370ac62eaab2e1d6bbd26fe94a21d7e5c09c81cde56d501ca2b6799594007eb0ade5c580e818c58a6323fee0c46c20162261cb5b3ca54c227053692a38c26452992b2c6f1b28a0e46220a10d45183cac1de4c49ba2c4a77945ec4b33ba939468cff3b4894086e797870225109b7bf7cb1a7ca9572a39e50bf2a65c97a18364bd026b435089d5cad842a41cf386abff179fdecb260628e332aed11db3f14f9f5b7bcc096ae4460b29797a10a6e44b184315e5b9fb3df6dcddd7d0d0b5d8d185402f1a2691738d5b368f9951ae2668f3306c44118f495d6e777ee7e8d3e5f86360e8a460a613a7f3a36638e754e8b0130673daeca1a67c6c812b9a66e5c07eabcd03a8384fdcea6055c31a1ba3cc4f9673da321c48d8b8007848328e6f026d8252988e50690f96995071863c1d493f326040dba4826b9e734e440d378cf82880f96a95ce7c54d7e59a18bb7fd2a997a68892fba5a05040ef03b86b53f0b3710326d1e2094a26dcaaa17e55671c941735030e074788a102bc930f9dcdbcb29cca4fb20d309f1c38e132f9bd2b55a9955797a870965c73102785340c871dc51ed8994903edca258de6537e3
+TAG: d360c293324f0f7cdfaffe9642aae9f7bc42060e
+
+# DIGEST: 6b7295febce7fba8d79d1e7ab8fdfc452191e2ba
+KEY: 454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6
+NONCE: 944f44d722271233
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e
+AD: 6da12dd4c27f4372480974
+CT: a1d0537c3bddc7459a37268608d30ee8e15377c922a4300d7e7f00084cb45a9ab7cfc7f89dfb68f3cf7defd102012361782e977e22c12ac1d91d1e093a21ab26bd171b426af9af7b2dec9d1f2dcf78f19748b39e9b0736e24b44dabf677296db10dc28cd37751d020e1780e5fb00142e972baffc546b9b55bd0067e22ffee4f10312a590394a296cf6fba3456b3c0a64b662d232f185a41762bbad664f977328bba56b62f489d33821d4d604265c388b5ea852968db95ab844c7cb9498bd28d4b055760f83fa94f2a35492a4dd03a1fe9f0c2947fedd44b96948447054e2da7fd3b9d95bfcd0cfe3d1c909e84c9f87ba2a50c33d588592ff3c7c7b56442d52683e222f2610b740a2187159b05f2b15afbba7a97ef2dcb30813b89393706011397f4aa3c537e91fab098ecbf3a87c2185b9001ff1a78e104fbeac85bea4ad609bf1571d83969934d483794944c2e6bea9d778d2deac2d6344106c1dc30d56251faaab3f4dda43a2ed8c3345d9773e4fa4effc5edc3a68cc423b539ed63e8b0605b58aa881906e38b38f02a4df3708e9de4333056c96a02ad6d235636da61fedc631f705e771af9f522109a4d3b34d684b3b175d28a389ea574215131aa68016ea9cf3664b0baa6491f85d3a4370f73967e4c23637fd1d131597a4dd30
+TAG: 57b4a44498ea09294f2df51a5e81adcb3318ccd5
+
+# DIGEST: 1dadffba439570155af2509a548764a93042d23a
+KEY: e9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722
+NONCE: 271233a825264e97
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c2
+AD: 7f4372480974454879c41d
+CT: 98c951eccacf8dcba5b819312f0ed234ea1cc06abee5f70888558000c2857de7411feffdf379c187d327943c63ab697675557a62c68c13f48d3970531225d5fb6c1434a126cfd6ba80b8f6dda08b3e3629ed12f7bbb45f45148f8544f0a8eb70c849260916eb62baa1bd850e082ad69ca5817594e8f26f63a1909ff03f5696b7a52f146af246c0c6485ea5826c89471c04fd6c373e9d0fef06f4a7b01400962ebfa4ef4166dc895619864accfef9a4be874111cb333518b33a3a2565d032a2434931a16e000d01e35317338ddbc48317517367603697a225d81fc63fcc7d4b8463bbd24910b4972375a995e13baa148b644993b9a7bd706ae64da00f898599957e406c1ab15fd44b6e85b41d47ffaec8136a5dadab324cb0ce95c738a1f8d246af90d98a68b8ab7003d74aa29591b58ca7b2dc38f21f4cfbc04f2e239728e1350b0f074293a13970b264bee368ff98c6960a805346c19702983d3ddfb6306f24cc7f8224e553b0668180787e48ca8e5d851f84df71d5ce6fd7815d39d7e3941b8e0562af98e6e244216bf418d7ca2d9e29ecd3997573b2c4d92aea1a5a82f2272af1218b379ca40a28cc7ce09ad60028a5a6aac6ce145cc3936f89a5d34ba54aeec8d99f84ebf7367fa5fdc12def2294fd3fa3299ba1a59aacc0d7f6
+TAG: 5b77267d53b2dfc87a936ae08ef7a3f630176553
+
+# DIGEST: e654b4c78e1c0061eea2996fc126c9bfd41eb6d9
+KEY: 3b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825
+NONCE: 264e977045318c9b
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f43724809
+AD: 74454879c41de9ac9f9823
+CT: 5a1c2b7a8d5bc74901521e1300567f30e2b7755f004ddcfd8fe64f471cbaec4bc6d445ea931bafe6ad78034d0ac1d3916f1e0405c2f2aa4b193c2cd599d34b86029840ad379b136aea5c2a74ea70e22e8c8d1e017a2f7d47f8ebac7b85087075c28d6d2846e357ce031abe09e03629a32cef0b205d631f36ec9a1c9c4e90a80900e01688c7298b99be65f204ebaf312364bfdf57d9e16b0142e879a47b9ae0e96fc62e90883624ee2dc110f3a83ab341f4558f360df399170bbae57cb2eb377a87aaed9755e8057d76609d447a33a8255450504b71439fc0d03e0fffb775019ebf921325b42ef56e1b454b5c87ba5daa1f0d0920e860eea43c913d417cd9e9b6676759a4e2c71b0180b432fe2aab4e4fcffb51b4198ffbedbfcdb4dd4e105847f5a5832e85744f34bf3b9929ffeb177ceb4c5e68585a3ff8fda6569921b3d093a2f1d77e710f78245eacd471af88da8ff8f268293845a9a8550ef34e2bbff9d6cf55b18987c71eb98803bac42b0e6c062015fafb754c6a75f927cac4a8adfcfa8ee05a3f115f1f90d734f78180aec2aa621fa7908d350b0cd8550895cf4b5c3cc75eb95fa574f9a91c1f5efa61f054bedd9267f10a08a21b19e63754de10a1bb0c4ffd8c5c08558882a2f98f1175920a71b981affffde44ae1c9281eee161c4c28f32436
+TAG: 32b13692a2f175644a0e192d8102dd9e2affc5c1
+
+# DIGEST: 654b8591c7f0506261713e9ce7a6fd24a6b9357e
+KEY: 61792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045
+NONCE: 318c9b66262c0f03
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c4
+AD: 1de9ac9f98233b5a7379a5
+CT: 62d0c56ae3e695bafc3cfa3c2d8b9d17ac8ff3b84ccac28d568c1ac84e1574ea06f31605caf86d4e809e39e9c275eed4a8f27eb00dc78e1c10dae719519d949dbc22e00d8644bc3806e54e6531864ae4cb5694002e2a3d7146b39b0b38acadbf1651401805f6394831c608b0478d496cc939b24aa3d3e6d445faceb798a69ae1308a593244645e242829f64f7945d0af8af0eeb6d391c69c2d5bf7b00e42092b36c23362bdd627af43ca7336d88cc36e95ede07b83afb54c8758678d19e0ea7956d8f26776b0f4b6b637c1152853651b6c130f436ffa2d4fd0c344e7583c5e56d6262f43767a1011d8398311dd6e3d7f9ea89d3eb3f6a1a9cb98905c0761fc5be1d83005fb9ca039b877c30b402743bdf0109ee5de42eef860be676a399a206c08dca8e757f059f7d9611137039b9053430e7d6406abcbf7aed645110aae84f758fcf0d225738cc7c90ace5d83eb9fe65d1e65efa4f6c9d808060cb0f72605e3d7c70e0d13d84689aa1e44aa4dcb152f230d456eb6cf520898bb249262d30c64fde02d6894f72ddff201e4bc41c5fc1f394f2620f764d40098292b04aee45e26812f3abf9a020b5215beb7938e2c121e809ab825d22a2d560bb9bde47572ecb891dd49b38f41af9649dfbdc83ab9bceb444bacdfca2fcbefd623364d4e255e2c0f3164ad9242174887a9a11a
+TAG: 8ac5d1d13e83f8502a3cb0310bbf46b24ff42e3d
+
+# DIGEST: 1eaad32c8d0cefaa5e2c503bb2185a73e6387fac
+KEY: 16430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c9b6626
+NONCE: 2c0f0368fe9d0cb7
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98
+AD: 233b5a7379a561792c0f31
+CT: cc269c9aed42c9ba90c768710fa03985372a219f391327e438b1593af29aaf2b66cf8fd60f137d8ce8438a7bcbf7c1c7010c06636f191802daa26fe12ac1c1458baefb2a51fc7361b2d98311c2eaa27e046fffbb76fc855ac01a1321672658e394043367e89478a789d662c88e91642af53824097326d991abd62d1ab818452fc152aa1bd05032027fbb691886d9269937f7f57e214a2186a191b2249ba6fe79b69a94623d85ef0db6b5c2363627ea15a614e6ee42ce0a26a90faaa3ec45451c69c7d472d98b0376a95503b16c6f17eeeb42e0ad5c8775584819aa01309e6071e6b9494da6ddcf992ec6bfc81e0031d74353afa042abfe62fae02792bb6dcae82694cb651689e4039208bf677c90ed6245606cae81732d9d32043e5435f8c40cb76b55a03593dda1271aaccdbc24f18c9a881c77e1dca0e62bfdd36208ee94370b166d66203dfb90c8602dfb48159410840c669c47e7514bf91ef603834bc213173458a87909979b3b77aaa77262e1a634fcb40241818f544f9d207e91ca1f46f77c5c4f606398938f764080dda0978c6b76ce76830a15098870e72b5c9f4975b495d2c5d969688b555773601ad8c857ca8c38565674539fa71a8acadac5415b563f55811b0c010ca1e6793ad08e6c830a0ec2b385402fb8af3b6f0ea0b70b458667953207e4d44f1959ecd2
+TAG: bdb2e683ff8bc7d20482e698ce2b608032094cc2
+
+# DIGEST: 862c0517b3658e9b9cd27db608d49e24e9b4667d
+KEY: a058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c9b66262c0f0368fe
+NONCE: 9d0cb746bbd55813
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379
+AD: a561792c0f3116430e8b6e
+CT: def7eba4397065d05a7a1b742179c1d8eff65e7e4ac18bec49ed020a95497a58af4ce62679a36b77f95f72913c2a58184ea0c3b59b60784bdf63893a2a84f76ab2b6324a218361316971ebb1e2850b6c7baaf9130715580626bf298f60d862cc4b9c4f353a9e4c7536fd697ece9407eb8ad434c97e325cebd5aa0cf4a5342724f2950c8623aa3a5322f2e06a6b1d71a57b22a2f85ed1acacbeba192cb29ced37983e4231bb930c07f7266728c54e8fa9a0b7195975095fd714440e07d63aa87778061a361b4d44f0241a504089b738cdf3a6323b7a709d39637a2c61677c1f034214a4da6471a89425a5cc6040f37261b9a8e55589b2c24a01b4379dfe00ce758e9e617b6d15abcf0974be46d151c5d26e69c50d3fe68d1854b788d6a43e72a00b1602bb9e7557c4c298b99cccaa17fd950123d672978cd359e115eceb88480d59f5496a920949e09d0590283280d78df0ee068c475706701034b5b8686c60e2c4c4d4bafb2dd25c86293d472d195186f3fbaaaa000cf678295143aa290b011ec35e1eb2dcc6ad12593a934b60af7b570bc59569df2e99bf618aaa60e533265e2bfcfe3e01dd1620cd7d6df8b70726b5fa1191b0cdbe627f714744b2bf2abaddf800cc091ce5ee447f2a61ad36094743182ebbe236745bbeb27a946c8d8dba54dd3597fc4328bb3fa5f43371b531bbbcb4795a55
+TAG: 1fa0b1d147e2c8f70c31f20a60228963076b32bb
+
diff --git a/src/crypto/cipher/test/make_all_legacy_aead_tests.sh b/src/crypto/cipher/test/make_all_legacy_aead_tests.sh
new file mode 100755
index 0000000..12f8853
--- /dev/null
+++ b/src/crypto/cipher/test/make_all_legacy_aead_tests.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+set -xe
+
+go run make_legacy_aead_tests.go -cipher rc4 -mac md5 > rc4_md5_tls_tests.txt
+go run make_legacy_aead_tests.go -cipher rc4 -mac sha1 > rc4_sha1_tls_tests.txt
+
+go run make_legacy_aead_tests.go -cipher aes128 -mac sha1 > aes_128_cbc_sha1_tls_tests.txt
+go run make_legacy_aead_tests.go -cipher aes128 -mac sha1 -implicit-iv > aes_128_cbc_sha1_tls_implicit_iv_tests.txt
+go run make_legacy_aead_tests.go -cipher aes128 -mac sha256 > aes_128_cbc_sha256_tls_tests.txt
+
+go run make_legacy_aead_tests.go -cipher aes256 -mac sha1 > aes_256_cbc_sha1_tls_tests.txt
+go run make_legacy_aead_tests.go -cipher aes256 -mac sha1 -implicit-iv > aes_256_cbc_sha1_tls_implicit_iv_tests.txt
+go run make_legacy_aead_tests.go -cipher aes256 -mac sha256 > aes_256_cbc_sha256_tls_tests.txt
+go run make_legacy_aead_tests.go -cipher aes256 -mac sha384 > aes_256_cbc_sha384_tls_tests.txt
+
+go run make_legacy_aead_tests.go -cipher 3des -mac sha1 > des_ede3_cbc_sha1_tls_tests.txt
+go run make_legacy_aead_tests.go -cipher 3des -mac sha1 -implicit-iv > des_ede3_cbc_sha1_tls_implicit_iv_tests.txt
+
+go run make_legacy_aead_tests.go -cipher rc4 -mac md5 -ssl3 > rc4_md5_ssl3_tests.txt
+go run make_legacy_aead_tests.go -cipher rc4 -mac sha1 -ssl3 > rc4_sha1_ssl3_tests.txt
+go run make_legacy_aead_tests.go -cipher aes128 -mac sha1 -ssl3 > aes_128_cbc_sha1_ssl3_tests.txt
+go run make_legacy_aead_tests.go -cipher aes256 -mac sha1 -ssl3 > aes_256_cbc_sha1_ssl3_tests.txt
+go run make_legacy_aead_tests.go -cipher 3des -mac sha1 -ssl3 > des_ede3_cbc_sha1_ssl3_tests.txt
diff --git a/src/crypto/cipher/test/make_legacy_aead_tests.go b/src/crypto/cipher/test/make_legacy_aead_tests.go
new file mode 100644
index 0000000..40b8a01
--- /dev/null
+++ b/src/crypto/cipher/test/make_legacy_aead_tests.go
@@ -0,0 +1,357 @@
+package main
+
+import (
+ "crypto"
+ "crypto/aes"
+ "crypto/cipher"
+ "crypto/des"
+ "crypto/hmac"
+ _ "crypto/md5"
+ "crypto/rc4"
+ _ "crypto/sha1"
+ _ "crypto/sha256"
+ _ "crypto/sha512"
+ "encoding/hex"
+ "flag"
+ "fmt"
+ "os"
+)
+
+var bulkCipher *string = flag.String("cipher", "", "The bulk cipher to use")
+var mac *string = flag.String("mac", "", "The hash function to use in the MAC")
+var implicitIV *bool = flag.Bool("implicit-iv", false, "If true, generate tests for a cipher using a pre-TLS-1.0 implicit IV")
+var ssl3 *bool = flag.Bool("ssl3", false, "If true, use the SSLv3 MAC and padding rather than TLS")
+
+// rc4Stream produces a deterministic stream of pseudorandom bytes. This is to
+// make this script idempotent.
+type rc4Stream struct {
+ cipher *rc4.Cipher
+}
+
+func newRc4Stream(seed string) (*rc4Stream, error) {
+ cipher, err := rc4.NewCipher([]byte(seed))
+ if err != nil {
+ return nil, err
+ }
+ return &rc4Stream{cipher}, nil
+}
+
+func (rs *rc4Stream) fillBytes(p []byte) {
+ for i := range p {
+ p[i] = 0
+ }
+ rs.cipher.XORKeyStream(p, p)
+}
+
+func getHash(name string) (crypto.Hash, bool) {
+ switch name {
+ case "md5":
+ return crypto.MD5, true
+ case "sha1":
+ return crypto.SHA1, true
+ case "sha256":
+ return crypto.SHA256, true
+ case "sha384":
+ return crypto.SHA384, true
+ default:
+ return 0, false
+ }
+}
+
+func getKeySize(name string) int {
+ switch name {
+ case "rc4":
+ return 16
+ case "aes128":
+ return 16
+ case "aes256":
+ return 32
+ case "3des":
+ return 24
+ default:
+ return 0
+ }
+}
+
+func newBlockCipher(name string, key []byte) (cipher.Block, error) {
+ switch name {
+ case "aes128":
+ return aes.NewCipher(key)
+ case "aes256":
+ return aes.NewCipher(key)
+ case "3des":
+ return des.NewTripleDESCipher(key)
+ default:
+ return nil, fmt.Errorf("unknown cipher '%s'", name)
+ }
+}
+
+var ssl30Pad1 = [48]byte{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36}
+
+var ssl30Pad2 = [48]byte{0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c}
+
+func ssl30MAC(hash crypto.Hash, key, input, ad []byte) []byte {
+ padLength := 48
+ if hash.Size() == 20 {
+ padLength = 40
+ }
+
+ h := hash.New()
+ h.Write(key)
+ h.Write(ssl30Pad1[:padLength])
+ h.Write(ad)
+ h.Write(input)
+ digestBuf := h.Sum(nil)
+
+ h.Reset()
+ h.Write(key)
+ h.Write(ssl30Pad2[:padLength])
+ h.Write(digestBuf)
+ return h.Sum(digestBuf[:0])
+}
+
+type testCase struct {
+ digest []byte
+ key []byte
+ nonce []byte
+ input []byte
+ ad []byte
+ ciphertext []byte
+ tag []byte
+ noSeal bool
+ fails bool
+}
+
+// options adds additional options for a test.
+type options struct {
+ // extraPadding causes an extra block of padding to be added.
+ extraPadding bool
+ // wrongPadding causes one of the padding bytes to be wrong.
+ wrongPadding bool
+ // noPadding causes padding is to be omitted. The plaintext + MAC must
+ // be a multiple of the block size.
+ noPadding bool
+}
+
+func makeTestCase(length int, options options) (*testCase, error) {
+ rand, err := newRc4Stream("input stream")
+ if err != nil {
+ return nil, err
+ }
+
+ input := make([]byte, length)
+ rand.fillBytes(input)
+
+ var adFull []byte
+ if *ssl3 {
+ adFull = make([]byte, 11)
+ } else {
+ adFull = make([]byte, 13)
+ }
+ ad := adFull[:len(adFull)-2]
+ rand.fillBytes(ad)
+ adFull[len(adFull)-2] = uint8(length >> 8)
+ adFull[len(adFull)-1] = uint8(length & 0xff)
+
+ hash, ok := getHash(*mac)
+ if !ok {
+ return nil, fmt.Errorf("unknown hash function '%s'", *mac)
+ }
+
+ macKey := make([]byte, hash.Size())
+ rand.fillBytes(macKey)
+
+ var digest []byte
+ if *ssl3 {
+ if hash != crypto.SHA1 && hash != crypto.MD5 {
+ return nil, fmt.Errorf("invalid hash for SSLv3: '%s'", *mac)
+ }
+ digest = ssl30MAC(hash, macKey, input, adFull)
+ } else {
+ h := hmac.New(hash.New, macKey)
+ h.Write(adFull)
+ h.Write(input)
+ digest = h.Sum(nil)
+ }
+
+ size := getKeySize(*bulkCipher)
+ if size == 0 {
+ return nil, fmt.Errorf("unknown cipher '%s'", *bulkCipher)
+ }
+ encKey := make([]byte, size)
+ rand.fillBytes(encKey)
+
+ var fixedIV []byte
+ var nonce []byte
+ var sealed []byte
+ var noSeal, fails bool
+ if *bulkCipher == "rc4" {
+ if *implicitIV {
+ return nil, fmt.Errorf("implicit IV enabled on a stream cipher")
+ }
+
+ stream, err := rc4.NewCipher(encKey)
+ if err != nil {
+ return nil, err
+ }
+
+ sealed = make([]byte, 0, len(input)+len(digest))
+ sealed = append(sealed, input...)
+ sealed = append(sealed, digest...)
+ stream.XORKeyStream(sealed, sealed)
+ } else {
+ block, err := newBlockCipher(*bulkCipher, encKey)
+ if err != nil {
+ return nil, err
+ }
+
+ iv := make([]byte, block.BlockSize())
+ rand.fillBytes(iv)
+ if *implicitIV || *ssl3 {
+ fixedIV = iv
+ } else {
+ nonce = iv
+ }
+
+ cbc := cipher.NewCBCEncrypter(block, iv)
+
+ sealed = make([]byte, 0, len(input)+len(digest)+cbc.BlockSize())
+ sealed = append(sealed, input...)
+ sealed = append(sealed, digest...)
+ paddingLen := cbc.BlockSize() - (len(sealed) % cbc.BlockSize())
+ if options.noPadding {
+ if paddingLen != cbc.BlockSize() {
+ return nil, fmt.Errorf("invalid length for noPadding")
+ }
+ noSeal = true
+ fails = true
+ } else {
+ if options.extraPadding {
+ paddingLen += cbc.BlockSize()
+ noSeal = true
+ if *ssl3 {
+ // SSLv3 padding must be minimal.
+ fails = true
+ }
+ }
+ if *ssl3 {
+ sealed = append(sealed, make([]byte, paddingLen-1)...)
+ sealed = append(sealed, byte(paddingLen-1))
+ } else {
+ pad := make([]byte, paddingLen)
+ for i := range pad {
+ pad[i] = byte(paddingLen - 1)
+ }
+ sealed = append(sealed, pad...)
+ }
+ if options.wrongPadding && paddingLen > 1 {
+ sealed[len(sealed)-2]++
+ noSeal = true
+ if !*ssl3 {
+ // TLS specifies the all the padding bytes.
+ fails = true
+ }
+ }
+ }
+ cbc.CryptBlocks(sealed, sealed)
+ }
+
+ key := make([]byte, 0, len(macKey)+len(encKey)+len(fixedIV))
+ key = append(key, macKey...)
+ key = append(key, encKey...)
+ key = append(key, fixedIV...)
+ t := &testCase{
+ digest: digest,
+ key: key,
+ nonce: nonce,
+ input: input,
+ ad: ad,
+ ciphertext: sealed[:len(sealed)-hash.Size()],
+ tag: sealed[len(sealed)-hash.Size():],
+ noSeal: noSeal,
+ fails: fails,
+ }
+ return t, nil
+}
+
+func printTestCase(t *testCase) {
+ fmt.Printf("# DIGEST: %s\n", hex.EncodeToString(t.digest))
+ fmt.Printf("KEY: %s\n", hex.EncodeToString(t.key))
+ fmt.Printf("NONCE: %s\n", hex.EncodeToString(t.nonce))
+ fmt.Printf("IN: %s\n", hex.EncodeToString(t.input))
+ fmt.Printf("AD: %s\n", hex.EncodeToString(t.ad))
+ fmt.Printf("CT: %s\n", hex.EncodeToString(t.ciphertext))
+ fmt.Printf("TAG: %s\n", hex.EncodeToString(t.tag))
+ if t.noSeal {
+ fmt.Printf("NO_SEAL: 01\n")
+ }
+ if t.fails {
+ fmt.Printf("FAILS: 01\n")
+ }
+}
+
+func main() {
+ flag.Parse()
+
+ commandLine := fmt.Sprintf("go run make_legacy_aead_tests.go -cipher %s -mac %s", *bulkCipher, *mac)
+ if *implicitIV {
+ commandLine += " -implicit-iv"
+ }
+ if *ssl3 {
+ commandLine += " -ssl3"
+ }
+ fmt.Printf("# Generated by\n")
+ fmt.Printf("# %s\n", commandLine)
+ fmt.Printf("#\n")
+ fmt.Printf("# Note: aead_test's input format splits the ciphertext and tag positions of the sealed\n")
+ fmt.Printf("# input. But these legacy AEADs are MAC-then-encrypt and may include padding, so this\n")
+ fmt.Printf("# split isn't meaningful. The unencrypted MAC is included in the 'DIGEST' tag above\n")
+ fmt.Printf("# each test case.\n")
+ fmt.Printf("\n")
+
+ // For CBC-mode ciphers, emit tests for padding flexibility.
+ if *bulkCipher != "rc4" {
+ fmt.Printf("# Test with non-minimal padding.\n")
+ t, err := makeTestCase(5, options{extraPadding: true})
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "%s\n", err)
+ os.Exit(1)
+ }
+ printTestCase(t)
+ fmt.Printf("\n")
+
+ fmt.Printf("# Test with bad padding values.\n")
+ t, err = makeTestCase(5, options{wrongPadding: true})
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "%s\n", err)
+ os.Exit(1)
+ }
+ printTestCase(t)
+ fmt.Printf("\n")
+
+ fmt.Printf("# Test with no padding.\n")
+ hash, ok := getHash(*mac)
+ if !ok {
+ panic("unknown hash")
+ }
+ t, err = makeTestCase(64-hash.Size(), options{noPadding: true})
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "%s\n", err)
+ os.Exit(1)
+ }
+ printTestCase(t)
+ fmt.Printf("\n")
+ }
+
+ // Generate long enough of input to cover a non-zero num_starting_blocks
+ // value in the constant-time CBC logic.
+ for l := 0; l < 500; l += 5 {
+ t, err := makeTestCase(l, options{})
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "%s\n", err)
+ os.Exit(1)
+ }
+ printTestCase(t)
+ fmt.Printf("\n")
+ }
+}
diff --git a/src/crypto/cipher/test/rc4_md5_ssl3_tests.txt b/src/crypto/cipher/test/rc4_md5_ssl3_tests.txt
new file mode 100644
index 0000000..329569a
--- /dev/null
+++ b/src/crypto/cipher/test/rc4_md5_ssl3_tests.txt
@@ -0,0 +1,808 @@
+# Generated by
+# go run make_legacy_aead_tests.go -cipher rc4 -mac md5 -ssl3
+#
+# Note: aead_test's input format splits the ciphertext and tag positions of the sealed
+# input. But these legacy AEADs are MAC-then-encrypt and may include padding, so this
+# split isn't meaningful. The unencrypted MAC is included in the 'DIGEST' tag above
+# each test case.
+
+# DIGEST: 426e94f7c3d22cdfa51d7ead530d93d7
+KEY: 18cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c5
+NONCE:
+IN:
+AD: 936a91d0b5d2c02672
+CT:
+TAG: 05846be413003a0eb64a245a28775d8f
+
+# DIGEST: a7bdf0184f0c1374fc84aaaccf0d8309
+KEY: 171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3
+NONCE:
+IN: 936a91d0b5
+AD: d2c0267218cb7090c6
+CT: 2593351dfe
+TAG: 863de43649bf546a1bd0ff1125b8e350
+
+# DIGEST: 1b3c97629ae3b60a1116b48bc7366361
+KEY: b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23f
+NONCE:
+IN: 936a91d0b5d2c0267218
+AD: cb7090c6171386d641
+CT: 51e5dff21e15c9c107b2
+TAG: 503b5f8096b7b5f95f94caa4bd64f05a
+
+# DIGEST: 506e7defec74b711d424bfedc1a9d9f7
+KEY: e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd885
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c617
+AD: 1386d641b87797b684
+CT: e1b2d8a4bc5a63d9305d8f5aa266cf
+TAG: 5723497026a15e318b5417b7a3300a47
+
+# DIGEST: c2668e1af0461bb975611ee291d951de
+KEY: 3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b8
+AD: 7797b684e0fb56f97c
+CT: 22de3dcf23720f48512ec7e47a6dbb71daeb6f81
+TAG: e7d301f88b1400714b59eb3a1f81eab1
+
+# DIGEST: bd92ee8df8f0d9bc61f917fa8c60b435
+KEY: 2993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0
+AD: fb56f97c3961d8afa2
+CT: 48b521762a7555332bc0d4074a63c2381db05a9c2406c1351c
+TAG: 5255a7661e8f1e2c1764daa0b47eec0f
+
+# DIGEST: 842173c8929556ff8b2ac55fe427f5e7
+KEY: b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c30
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c39
+AD: 61d8afa22993a340b9
+CT: 4bccbd6af7761500dc4113802632ebe1dad33581177b03b51fb095e4fd05
+TAG: 333c9a1413a6d2ce961a5f3447f5d0a1
+
+# DIGEST: 6823af156b7baae6f74ddfc4f0d911cf
+KEY: 1df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa229
+AD: 93a340b9b3c589c748
+CT: d5437e9a3618f0d4a3c4bcc6393c603be961ec485bae84b4d0baf0f50419e7d35224b1
+TAG: 5982a70a52b2d960ca4c118aeb73bc4e
+
+# DIGEST: 39ddff59a03ce56ccb306bf69c687d16
+KEY: a23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d7
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3
+AD: c589c7481df3f4183a
+CT: d9774257767cf640e68e706cfa861bfd00f992df627d1ab8557433d98c6ff11d92c74d634340c193
+TAG: 1313f466a4acf36eecd52bfb76535072
+
+# DIGEST: b735db1f1bde92e0b5655d14a378ef28
+KEY: d88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481d
+AD: f3f4183aa23fd8d7ef
+CT: 4fea0cb8faec38c3cf3b3562ee80273f65f18a42fbb43e38804bae51a3fbb16074cc4ea40464a950a9106c5ad4
+TAG: c2da66e07900cf676356fb011c1a7476
+
+# DIGEST: 6d89920b67eecc3e93b7cbf90e37d872
+KEY: 8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa2
+AD: 3fd8d7efd88503f78b
+CT: 6e658a27ffd7aeb5906dc743361b19f62aea56f41b043c82b2a2caf1eb75e8f28dc73ddb7d72d4d333e9e57e5f9b746d2167
+TAG: f2ee67308d0f5677a079387c90f30dae
+
+# DIGEST: 274d4d9ee741be5e72cea431cf75c7ab
+KEY: 2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd8
+AD: 8503f78b8ed1c8e9ba
+CT: 835cb09e59158c13c28ad651482d75c39cbe91cf8d224fce0413770d56191f74bbbec9641588408fe69791a3cba4bb1d54b6d605595ab9
+TAG: 4e721990c5ff5c878405d1a1d6699581
+
+# DIGEST: 5e63a64af3e67492f7e4fd2237f2ab67
+KEY: 0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0c
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8e
+AD: d1c8e9ba2fd6773e0d
+CT: 62905dc07cd5df22402b2eb148f4ad3a740612f647fc8c03ea6a9f28c7913734317c609d97eabdd133840845a67dba69b2732f05ac562fbaacde227e
+TAG: a19603ad15f278fd377fb5ff358efeca
+
+# DIGEST: 2fca578631a06e8cafa565fd09c30e09
+KEY: e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be9937
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2f
+AD: d6773e0d0c302a5f47
+CT: 70d3805fba2f613b689edf9a61f03888240085734701035bced726440ae0d9955193849ca6133ce8c3c22a54337617376f8d4d3bc09f4910130ecdefb8abb366ca
+TAG: beb41bfe3e73105e706ca7169206c585
+
+# DIGEST: aa192f3b031cb9a30af41b8fa3f4e369
+KEY: 91d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c
+AD: 302a5f47e037446f58
+CT: b1317208f660f563bd62f005ee65796d293a2eeb2e59f7705c997a491d01b23e39fe266b3f6450a3ee6a1a17dded8259334f7aaf1efceb7e2b53eabd371aa4ab86a008cbecc2
+TAG: bc77d0ac024768b105d4be4bc343f40e
+
+# DIGEST: 393c853840160ddd9e7cbb51e3377f57
+KEY: ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e0
+AD: 37446f5891d77df660
+CT: 1d99057efaf87afb2a5be17f3b5226d4fb76db90dd274af26ad858360701ee8119d1e927ec1c93ecfc81b70bcdc54f74361300593d53145acc58a65e8f1c5d8db80828abdfa25e107e4ecd
+TAG: a86e86c0457e2ad6f567408e6b12f53f
+
+# DIGEST: d02f0f475895a6643bf54f91026671dc
+KEY: be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891
+AD: d77df660ed82933f62
+CT: 2d0c0b403b1320346deb4fe08c3c8c6b0a2087aa12b21df1f5fa06ae3113589b329107c852cd436e4a5a160a1f8745e8fdba76e9cd66d09dd21ec5135899eea5b218a7ac6992e03582d0eab07da34cd0
+TAG: 861cc010424b3168d94cd5e0c413b661
+
+# DIGEST: c99f7c9d68495a74eaf7b380cf8ebb5d
+KEY: 6965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a1
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed
+AD: 82933f62be8dc55b43
+CT: a994e7600252b8fbef23be6c01eb38234c10a49b963dc0b1a13b7213579b7254ee4954de0044d31127dd6bb49c89072b1baf049db9a987b742a9e042ffe5425e280b546a7e1842b689fd0fbf418ff7d18672f49f92
+TAG: 3f08b1086962d1eac317bddee31c1b34
+
+# DIGEST: 184dcb254997993937d338a762208d0f
+KEY: 7e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a729
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be
+AD: 8dc55b436965aabe47
+CT: d558213621e14f40231438002d0dc5b1e96bce531a1c118e478b59001210ff8478e54ed24032328858c0e6e2204566c4e98e0a90a7ca2f856b67e50e01b0d6ebcf4cab4494d394cd642a98fefa1343a6a5e88b1f778ad94be2fd
+TAG: 43804328531f04ade72e44c9bf657eff
+
+# DIGEST: 5edc848f24cad2efa22f6fdda710b027
+KEY: 99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b4369
+AD: 65aabe477e0cdd46be
+CT: c1ed7d7615c5575817fa2b5353c1ed6e16b4c18fa57789b88030d9ec80447037729f82f7c5fc34d90c93969607348df0754c5549a9fea1cb94ad9f63cd5cd063d60a3af47e1ebd80c3dda604a30bb099f27557ae918961262a57999086296a
+TAG: 2a098f3f6669360001a661ab3be820d6
+
+# DIGEST: d24e0f5685b3b90ca1669656dcbad20b
+KEY: 7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e
+AD: 0cdd46be99371eb8da
+CT: e4a22be70ba7642ed6f02f1b76ec2143c161b03fe406e19f043e23a6be3a575c11721824c7c796ca3cf96b835830ea369b83b05a751e481b77446751e3fe0cdb27eb9682ed8cd71e48f8699e743be7e70cc80deacde5c9381a59c7aa908d417192a3dd12
+TAG: 32c89817f1ee09295c9d7108e606ec70
+
+# DIGEST: fea6f3c6b5b442c42392aef4b8327654
+KEY: fd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+AD: 371eb8da7dac997dea
+CT: a27d73f11b119fd94ef071131585a759f82a5028c2c56bb31baffe9746281636ae0f691e411ed8954a959ee7a6ab49cc5581a58ee4d734d9a013758bec7ca07c5763eb95eaa577e05dcd5d7cf361821f5ad118566c7ca5b8f3d05fff984f8875cffad97df5f5a64f43
+TAG: c783535f032ad4c2905fbc44fc9d05ef
+
+# DIGEST: fb6e2c79ce3f425b011f1a1291c68b84
+KEY: de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2ea
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7d
+AD: ac997deafd64b1fc65
+CT: 3c4ae6b1a39df8586882981e6998eba21a339e0f7208acd91364c09ce26593d320f27c290e4fce80b790900b2e50f848130ed76411def57687c5047326925596e248bb62c7bf8179f6cad60e70b484a0b83529ed7b2c62c03a9c101b26508c7cc95d85e783728dc6c9e5609910ec
+TAG: b364e72448df5e15fb56469665cfc331
+
+# DIGEST: c2afdc008657b539a6611ea992bbc482
+KEY: 41a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae021
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd
+AD: 64b1fc65de39f4f035
+CT: 022fb12a967311e357f7f9634e1ad598d94d4bae2d70daa6136b6be1c06cc4c5f2af7a02903992393a63c2f037b4534cbd720e75501930b081145e9fea8e640941df62fd5f36dc15195c2b55172c052779d9400d30936478b346450fb947f66cd0de9bf0fa832bdb9ad2fe5b3e5724b2acf644
+TAG: 49736dd0605e62bf24043d5c96057d48
+
+# DIGEST: 6f8e417699313a90b5aded715dcaa643
+KEY: a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0c
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de
+AD: 39f4f03541a11be112
+CT: 85eb73b69ad10ed561d27cf2cc28154fa02a2b366ae40a206674b7c5e539cc05cdf19dca5a5db49154b1805b75661cc78be9d5dde3eaedc9fec040b24c05703beb8457b43f3e808459257fe98273f13b9c5127f5c211e43d7e84201104231df4091ec9d2bfc1ba3b68422593215d834433fa48af743811b1
+TAG: 2f81076852caa12dbb640037fa468d8f
+
+# DIGEST: 8aceb91b52859608724b4a48b922d43e
+KEY: 4ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541
+AD: a11be112a72933c7b5
+CT: 4b7276030a7874c9a0ff4c581605eb8c73c70d0eeaba862ba50568d193b5c04c739df087b3e1f797d0afac61a19603ed3506d25ea30d8c1275827ae383efc0e1e14c96263dbddabd48bf73269b4057791cb162885ea1b26f755c040337d79113021c2b920537f35361fdd3c44619dcf73bbd0a8b4d57235d6bd8f1d249
+TAG: 0407850fc0180fae942efa19393a8798
+
+# DIGEST: fad9e8eb1af2dbcdacfa0b8717c23924
+KEY: 905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f2
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a7
+AD: 2933c7b54ed4fad0be
+CT: 57e0ececf205a7ded9c530952bff2329cbb54d2ae077e741078f2734d516217567864b500fc66987f4382f45c31091bf2146a2a28b6f7327edec01b5261d9f0ba216c32ec1f8131998c6d06e411f1b77912bb4d5a6eaca54fc02b143da2ed6f0d5c85bc205dc2807e981ff98e08f12e45879aa4bbd16377ef4fb9e6b7e1759e64ccc
+TAG: f1f60690a3c488f146d36641928cec5f
+
+# DIGEST: 92ea0c97694e315909b540f2a6c6371c
+KEY: 5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d03
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54e
+AD: d4fad0be905d41203f
+CT: ac58dc34b2abc4a6905ac7c4a788835e00f335e8c5c88ecce9e1b18a9fda971e1319440935913cf171074595b77d064c558fbee528996413436441dedc503fa251c83e4c5428a30f52b098f4ed355c8d598cd5d5fdfc2fa4802d9212f07bb1a147c9d1442865df7774b9fed2d50deea09667b920968af475c7aaa0ceafa9eebdf3e22efbe24be8
+TAG: dc1c2b005b805744a09da9dd508355b4
+
+# DIGEST: 3077366019f1e67eb8eec875922863ef
+KEY: b2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be90
+AD: 5d41203f5dce998f8f
+CT: 5c998d85a3c0eb59f5ac78756cf3b2db5c20bf0657d0339e66c5a6e204e72fac3fd21690915445fb55fb7405685efc47ea98154004d6a3373dcc1014d8f59b3d711ac32f4056fe4b9a1259c62bd9a5291c282b7e8e6abc5cff0f414f782149a92ba8717ea9fb9d5cd6d6347f4ab7d06de15afbab9cc7c524783e22619b61afc217f83bb6911b1b055c12ae1c
+TAG: 1fa679f8407f206bad94fddc1d629ec2
+
+# DIGEST: 5252d79fb797526525742fa0368f13d1
+KEY: e02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5d
+AD: ce998f8fb2eaad409a
+CT: 02707c7e05411a77bfadcca90c8994191ec79edbada45b95ff0add0f1cea0d0f35e7e208a493d80ef2c2c114a563e87329429ff36608fc0a0e1115a44b47d47c5e5095b2c0662c523814954c57d4ac5038c362b574e1b35543b5a04335ac4a5e6054a2f541688fa54b6e0d3da3a1e22c22b3b9baaa523e5ff08236219f37aba267ade84f6af352319f3c5304b1dff09a96
+TAG: 7b1bf69149efc480b0b5ec2d74063bb2
+
+# DIGEST: 404ec1474e5cc319401cb6917841930d
+KEY: ae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2
+AD: eaad409ae02116417d
+CT: 6757d23ea24d7c45cb11705a98dd9f24be0b9d1c3120bc140d8c216ba831aaceeb9bc5f102e420a4e141706f812d793059259bcc2882d7155452e93ff4cc8e1b006b0523024de24988681f14f8b7c4399c586d72c5a1124c4b5b4e7583d04c9bd82b2b04ddf1b81caa2e8392b5d06d58be3b21ab7001cf8de02915ff3e83cfa8bec1dd0ef8141147de698c3c35f98f81cbc314a203ea
+TAG: 3e61331729f00c9201d4120813fd5017
+
+# DIGEST: 3bda811f1a0bde14458d547ba2c7928b
+KEY: 9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a74
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae0
+AD: 2116417dae0cef457b
+CT: 6b08b8a7e877438ac9af36ecfb1a577c59c6697d5949b527f00e3cbcefc01983f8ca58c93489e903bc2fb2df14470848440dfa7a58d3ec24abced8d729be4f414b3645d99241fb8b26eded8ba4c4e78909d85a5b4af4af02ada1f6a483262fe57ca2fb8459d52175dd32df021b56aa7eb6c5fb3117723b75a16812c3a1713f5d82b894c800137be6afe1dcf3ddaed439997ec308870ce3bbded570
+TAG: fa52ae48b96197cf3d01284155e5ff51
+
+# DIGEST: 23adf4ac47183c50429f7f288d1f2e72
+KEY: b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae
+AD: 0cef457b9e5e16dcc5
+CT: 6e5de1b6e56f82df47dfbe44dfcbe79fff2b160ca96b867662660e0ab675f8af700c62bfb81b8a71b723bfa76b0d6b0e31e2bc2ac3e84ea5d18048d6004a72df6d79f097960891651cae15bf750053d87c4bbb39948089bc3687088af8329bd5a308f2e19411a5ce326f0411f89d883ed3e01f1885910940a1371059e7ea8552d8f379e0563d2a8de0a5197d33b33335fa27ab5d1c00dba8640701af250b3c4b
+TAG: 2299b6be430023a1e1264bfac3480da7
+
+# DIGEST: b9e89fdbac6bc398838ff244071b8a9e
+KEY: 0d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b144476
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e
+AD: 5e16dcc5b6f25607f0
+CT: 7eda958efdfec21f278c9f0fb915e173a97aa37cc266c6ccbcd0000be5d0879815635464c04a688bc46b1d8f99d018112a899a718a8f941c1ccdd1ebdd0df8349bbe543c620c7f649cc4af84b459810c7361f19995d4e8dfa253523a2d55ece9f7996a610b38b4e0fbef9afea548f7174fef8a50b2b5923d11106ee588a0e696bc811c98acdd9b3aa896cdcc9a5b96e3977971f6decdb1af8dfc9437427bdce62640d87226
+TAG: 50e24daa826873b682c0d8158a3f970c
+
+# DIGEST: 014ed695a644f2b8e9a45b9d38ed202f
+KEY: b09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6
+AD: f25607f00d033fb95f
+CT: feeccf5b760db1668de88fdb368caaa443fbae3c6064d0cf681cd785f79f06c3ebb20b429ddd68e0a1dbac2b76dae39d8c84f078fe8177020b406eedf19d4fd89bbda2247a298f4914d3fb2c856d4ef57c76e9fc4a0b6ae69dc13d5fda02468b71337c5d508adcba33c9f586049dbf4fc743776ac6dd3169feba07afd70e9e03d2f10da49b79882691b45f0531781a80b5bf4b8120803336fedcf6d53a7c0ecddab8dbd140d325906f11
+TAG: dbed8077c0ad861018f2f6f57dd7da6e
+
+# DIGEST: e5d8d3b66ac9c11de3e3ab6d0f88e17d
+KEY: 172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d
+AD: 033fb95fb09e4d00d6
+CT: e10dd7b0e0c7fc02e7df875921ed537437fe5723fbed68e24b96d84e6475d7558f773b6d765016b7b8e57368567ce4fa9de9a4923d13d30217b4202721fa7c8c2650ff5a3edae11f112797a2ccf10afc07c94c01783ece6a509efbd64d220f22c0454c219a1b120efeb68ae96e251d9a4a7fd4a51af10e96e9ea6b3e190dc06be571992ece0c9c727b949870a8331cc72985f6fae694511ead3ad7ddd3a7f36a3502d3f56581cb0eec53f6a9ed2356
+TAG: c3b4b0c50c4cbcd133a995f5eea4cb7e
+
+# DIGEST: 4ce3eefb916480816f66176f39ca1f83
+KEY: b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3a
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb0
+AD: 9e4d00d6172e780ab8
+CT: 1bb00f63b102b576f7dfc114de44219be1ab8bcf2ed1b9133bcb8711f9d0aa88eb4c8540d2c9b653b740d55783d7cbc05f9cd8bde224fa4a601cdeeddf193536f625ca9f7292d974f9cd2db5e018c075f3f66ff0d649f13d60499727c6836b16d340fa9e0ff0699b26920be3c273172bbfa8ba8b55de378299e14d8dfa7f5acecb8edc907a93840264ec6c535c180bceac0761dd16bee00badb777530f8b8ccfde928a1e4eb73aed4fdfdea8e026ff0518e2b7f5
+TAG: a1f60746e414f0a2e6c6ae5794453a22
+
+# DIGEST: 3a9a63597a0f95983a9cfda265eac176
+KEY: 7a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b18
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d617
+AD: 2e780ab8b700433a95
+CT: 72a283919ae3d279d7594683dc7680ae93298ab3ca887bca22c6db5def3570c270fc47f973873192b410d695d547d9909b65cec57f68528db8d1a1a05aeaa29f5d1e923e4f7132391ab3939be05d2cda1118f58ec556e57956e096b7c11bfb7b39ad1238cab04afbf789208245837aa2d709ca1f0cfbb3c805bef5e3562ee9b5ad18b8705e3a8a477ab06d4368f3e43d70920659a0cc761dbbcf5fda59f07f699b7016f97bbfc72e40a62b7d3341204be4491209d981248f49
+TAG: da7670699256f86330480ed45f1e171b
+
+# DIGEST: 4c4516dbad34a518693559604d55d34b
+KEY: 0f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b7
+AD: 00433a957a741c9eb8
+CT: a898b0660d1f528b18d544b5e5f95d1a20e9298efd0441dbfe599a537e00b129a46fb19f7ad0b297653aeb401759b58ce61b8e32632825e96bf0e8a66cb95ab2f49afc5707416369b47fca12336f7f212dc25cb6da620ef5d63b8b69678d2d2f3e5bdf887a29c6adc77bab3f0331f5aaccc2b7355c72e2387f2708f4be00376146b8c7e690e34d4a05aacd9bc4392b273f86e2953300eb9eedf855d25030c8004f04aa111954c093dfad15e63becee6a44ec679b69658c674ecdbcbf5aac
+TAG: 42e267ac23fd1f20b53a4c4be206bce3
+
+# DIGEST: 2db68c551c43ebd1b18da8518f4abe7e
+KEY: 44769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a
+AD: 741c9eb80f2b021b14
+CT: 78ccd36c0cea3981ba2b7a9413d7f96a137862ada5b03a28661e0824e5a425fd9d34a861969f84be8d9d59e356e0fb5fe42de6528b43103c65f7ae893b21f1a68328eee0c5dbbeded165621f96f59eaa6c20eee20b5a49586867e1e019fe146917b3bbc29d8627e33c409c9eaad1e4fae0c5bec59d946daa4cae02db5eae991de078771f005b82c74692273af45a18df344c6b9637308c83d4be35c67e3c22d83f6dfefc238cf0b6e1ee04de4ae02f8ac92139d31b2f2211e6513a9704e5d9c3c4873e
+TAG: e0271c7e00c771b0f93c08af17cc0808
+
+# DIGEST: 113aef22861952d452c541d5c230765b
+KEY: cfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f
+AD: 2b021b1444769da00f
+CT: 87516a2d342a6d11ed739731b8e965a8acf9cf7b1e0dcc535b7b354e4ef208511f1c999f03546e24d0252c8063c722459b878605f596b1ee7bd0395963ce43282355a7564cf28479959d587f48f34d2c5705a6b14401da25bbab15d3db8d074473cd6ff55299333c6be6d832ea71ef1738d449fa835ce589cb179495d36bc537d841d6ec4421bb4743c404bca6a6a5631a977cc6fc85c0a8b7dc710971be01298a2f554fb3d3db4e764a55075da446ad0247c4a9292ff6b52526227a6c7360dd4f42190592d14719
+TAG: fa9e556c2d930286faf2d68226b34176
+
+# DIGEST: dd36b5a92d416e3d2dc4c15407556748
+KEY: b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444
+AD: 769da00fcfab0f5f93
+CT: 0fe4c705744b0d3c2603148393f33cea2a2603fd018496fa8a4527bd4037c17103ed2601ce721d5289b317658d21809fdedeaf5c1dcbfa758a19befa03ab930158b252c5d3a8eba82bda3f6655029e0dcfa4ce20da1e4e9a7d3a90af67a0fd96654982e4e75e009b94dc7dddcac2a766cb380e40026b0ae7bf25c5acc943b486c4abec847c12068a26e467b5de96860e82a4f1393bf16f1f24db7fef420c327f8af4140e3b273c12d6391dd273feccbee1ca0ade55b84961e57dfe6f33407db86c240c16a866c16d289a93afaf
+TAG: 4f14190e07bed1a0e3bc236948b025e6
+
+# DIGEST: 3d94d12c5dc8424a058de2a998ba7a6a
+KEY: 5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249c
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcf
+AD: ab0f5f93b511060c9c
+CT: 116a50e2eb4d1562c49d484597a53f68ed17200aa036dd8926728cdd25156f94e94c0207f97e37b1f3f8d3a57c3d92f3c6d056bcf63b25eea79fe4e35a40bc566070dd0dc3cd3fb017e0354160146f46716c5d8242ae6c60a7e89ac0a8f5e3ee278e4e10f3f2d19c4c1682d7b810ec8a8e7e7e2bf9a11604ef294f8571a7d8998be0afe8326397dcba7d68284366dc2b82fc47ebe9abfe33a5af263fb54a96c8d0b8609098110af9702c3be43c0a58951fbd56170d59a1c04cb02861b12c30f087508d4f37690c3fe60c0e2f76ca53808765
+TAG: 52df5d8f215f382225368a29ff204701
+
+# DIGEST: 1dfe99b6df485647f7d88e08cf56163d
+KEY: 1b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b5
+AD: 11060c9c5f3aacefe6
+CT: bb514ace66239002b23fd0643673d9e5f601a021d9cc444dbec91c11e9e79a4a71b84d2b514b98ecf62c8164df84d0fc10b9149c3ca88c1575287121608ef7b8f94681384f705e9c5fb59604378791ac2d8057bd9ee3175ace3355c0cc77440db0e31d7d5f88567e887ce5b115815ad7321c025e6d176c4f7bba4686e223053eca2417a78ac81f2a67b522593b72060a7c0339597b06a6505c19c00cfad5dd76ceda73a46eeeec6fa7218acd9479ea032147ac4f59079943dc31212b6ca8bce30f66d2ae28106825bc6c4c1a5df272e279d9f8adad9652
+TAG: 371ce3d96af1fa0514b0b0ae7cd1ad40
+
+# DIGEST: 501f8a4a621c5fa25f3d835b00526ff6
+KEY: 3939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f
+AD: 3aacefe61b184ad246
+CT: fa6b8e1532c01196bb220bd64f4f9b66a69f50377cffa4733673028acc5bd4ddfa195f9a0b37a61b67d0a24ec30cafac97203df5c7e5d8dc3271cc97242a4c8030b7100667c135a54a53f5cd4af9340c0726850dec7f1a6d48851777b2dd6992e1b2502837dd84c996b1ac41f0cbd2c69d8fb6c6a3550d9cb3f3b6a8e1809733c97f7c1bda88c691420b956b5c81a59bc5bba327b35c302ad3d2d7d6223fba9a5b176af7f904b6a8f300104006bb3c9a9ad9912740643da61c022508ce243171e314394d958fd2c012b70b965b82114c6c0fa879e661a3c5ee24161b
+TAG: 75af38ed899b1456ee12924925e8152a
+
+# DIGEST: ac835d341bfe7039645ca14c05d29b3b
+KEY: e97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e7
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b
+AD: 184ad2463939ed518c
+CT: 66cc280967790c374494a45d93a5119d8368598402f98dcf2288cb988d1e62641728d3380cbfdddb5400aed37322ac8a2ca4018a3e708f7b54cc39b2a0c50cc5ff2da5efa31f1908f417d966eedac8ebee9a6ebc30039aaa3526f8364f68d97ab0ab917035a933cc75cb856efd7ec5a9d2eef4e73f1ee39f185bdfb01aaefedbab39a1e57fcc90cc18ea721d62f7273dedd0feb2ec72556a2a8412ae446dd1bca94848779db9ab8ee4ffdf663a6469327c8434ff1612303dde92c9e1c78d64d99555b3b5cf6adea1e170f17fc8d369f59c4b4babcb3ae3b4820c7a4a41905e3945
+TAG: 84a43ae2f0537f0ae458f8a84eb51fff
+
+# DIGEST: 4bcc5b6312a793e6874c8ceabd086182
+KEY: 3d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025c
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad24639
+AD: 39ed518ce97c3fdd29
+CT: 487e47b1486bc32e33aef14bf56fdf578a33be5e09849198ed2f91a7c6905917106434ee1bd7b5c95c266ae371c075aba5f5aae9c5a7ae3e39e3a25a1cda682db4295e473be862de1ebf9db7244e3139eec37e6e4e4231de7dce06e5253ebb429bd4b22fc7cc98bc897caad630adbee281081e772dfd29f69cae620d89c2cb0f78a2b1980f8d83d9c47b8f43ef9a73775ff8188cbc7abdb1759383f53158897aec10ff1c98ce469fe67551345b10d7307e1b1b6a5481034b0c6b2e1d541ed1647b9a217d3790d237ca37cf47c4d96b0abbcc78670795f9d6c57a059efb1d0edbfae33490b33b
+TAG: cf4324536fa10c0510bfa6a26b6190f2
+
+# DIGEST: 80b0cf21fcb7ed153a787592150af7cd
+KEY: fdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d29
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce9
+AD: 7c3fdd293d72afc09f
+CT: 9fead102515d95f86e178070c162f71189e7ad1dde31dad503c33a5e7c702918abe2b9d2dce5886aff412ca2a6f027d719edbf837949906d80e5545f29ace27a2804a149577e03d0181971bb7bfd64d82d4da1c9073a617fe7c265ba3e4fac3d1bcb96b5930f46b609ed7abd001bd80d6993976af60873436c2db169861db6aee7de0d59454461ce5dc90299a3a80a6eb0f27fbf6d071941d95c7fd962ccfbd8c60f0c0227ad3650458ed794f42160edca41cb805b7c83eb626b8ae625615657bdc240234b613fe8551a93080b17e3854bb98c166661616137e507fb293fbca437174b366f4f1fefca7448
+TAG: 38146f2b814ff4cd6d9833a7e792a611
+
+# DIGEST: 23bfd9d6c946dcf8d47e6ba743c3781b
+KEY: 249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d
+AD: 72afc09ffdd4f41963
+CT: 0b03085e0f32b9d882b46bb9b5245a44cebe9647a0f06a5d7fb48b5b6af8c875b1cd524a66f4b08df03e32c612ba82ce609a3fb97c256c312088acd5c635d44c52319254a88889f2ade388200107cf42330824552ef0784a8a4578462b383bae5a77dac532a0b169dcda545c8af78627e12cbedadf2039626787066a1f7cf420cfd8e68abc9bb6ae5aa7d86a10cccf96d64b0ce6178c87de22b214a041ba5d5c9fd947d65e4d1d1b5b2eb23fc48367286a179782b3fe148101f3c844c5b95ca3fc7f0b8d0d36e06b1cfe9735ea43055ce1568a8b1aadfe9ad775bee4eaf34321e4b6d164f0dd70c7888d8187f25763f1
+TAG: 77da84c5c44516fed499667df0368553
+
+# DIGEST: e9fbf8746d61a8f52f259ed2e38aba0c
+KEY: 2e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be5
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffd
+AD: d4f41963249cd299b9
+CT: efa252251de3aa0c11c023d881d9728ec8715722661ec3e531596d4c1609dfab2684b4ed484f290a83b4a2d6763f597c6ccb6237f4c1a96e78ca4cfb2f5fec2a4e7741aa32fbe935672792a14aa1b07a8f9d32b94af0679654e2fa05d36dd31b37c65f4158a5e389f96672fe896fca21dc5df5a8abe1a43d49003dbc060e65e3c7ca5ff79489f3e7d2ecf86788a6655a369e517eb1109aae205e6e8ddb6ade98ca7aef3934d6254a3be8a221e635b16e96d33298bf0340998c7e0fcc0c3664f4306fa0d20244186f4fae97b97e2d6aa3787b91c597da21659b64cf962bdbfe858151547186f30fbcbff3a694a5d11d1bd99d76e376
+TAG: a4a83bbc54016275b2b65aaa1a544b05
+
+# DIGEST: 8c09a0bd0fbeee7211c138c837bb1f09
+KEY: c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af1
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f4196324
+AD: 9cd299b92e55ca24d8
+CT: 07419c48687a9de15a007d5521253b76bca15be276bd7cb0c56ecb74b30f17b9d697bb189a3bbc82f0f944b84239fcc177fb64c41c42789082192457bba0460acc58263f2912b2c6935cd67336ec8ff501aef40cd35e6f4f66ded303824580615347bdd8d4511303ae5f47b20c932c0ea2270de1f33822eb7e7bfb733375c3869ae092ddbfe792d205b91ee79e2142a210c8fd00a4b25b1de796bad9fb686e3335339c56e4925bf04490cef35fa000dc6a78815e8a58b02800483b9264e3a12b88cf8a57864b164573d732a2de1cd2094b6c8d8c9db0f7a3a3854db93bec6410b9c743a4c312de36218efa1db0da76579be3d83a93bc68d11af2
+TAG: df8b9c147798aedd893fb07badda3af5
+
+# DIGEST: 737fc724a7ee589b475d3a46333b6528
+KEY: c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e10
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e
+AD: 55ca24d8c078c49f78
+CT: 167408f770548d8c8b471c0c04033359d67f36176ccb701d859c7b80ce24bde453c93eee3908801b967a9dbd6e8646600cb97ec519cfef8a2eb2522f440f4cc3eb4d0a4f6a00af6053482bba54f4a7ddef2eb35f585ec46381750969ae131146b789b87fa429d1a2492ac40495c8efa9818c2cc33a79e75793b3b4b94ba491a7bafe6361b48b224725e9cf8c551f0277524600048969f19521bc3b9181f3ef4cda0849e5ba72cf7d28cb8bfdceaca11aecdf1f3595ebd443bdf6b357ea4b58790af3a280d2b19d4cfd1e216e35dbf0a9c7f455dfc0b64da16f655795a594501fe02ad96c1c4f4856a16305cf5cb0432d4e7be0a9ca3682089ca1e09a7531ba
+TAG: 43a3e7f67b609aa4516173aeb2690848
+
+# DIGEST: 642be488fac458617b8590f7281e9dc8
+KEY: 025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e8
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c0
+AD: 78c49f78c7e713710a
+CT: 22b6404c5cf46935f582ec36056a58e5c6aceecec038962f61305f2247c0e20aaf59f5a9cff44bc20ae2d3a49fccce618911609ebd01686740da90fce75eb01bb08dea952a4b19e18b3e124c9a10bb4a190f2b6c469787b1d8a5cc32e11ae99f26d238888a0a6ffe8f605ab63ff8304c8f2467dca93fe840370a0898febb3dfeada3c91086b4705a97c60b30d96ddc2d9cbc17a132ad28db7d0e936f53346242c1e8101b8adb9bfb177785d9b6d547b411c01f3cf0d387af911b82fce97d248d72a092c994df7d93024b9c346c9e8525b0f9719a64a7b0aa258a976c69bdc7a3fc630200dee58170e640b2b28d6e75f79aedebaea4d7aff2e4bfaf9e2e2f057e711af60d
+TAG: fea411cfdce04491a361893b86286c1b
+
+# DIGEST: 1c7c31cd062040c8db4f188c45170e3c
+KEY: 1d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7
+AD: e713710a025cb8b9d7
+CT: 0e8fd3257650c5a9255224a494cee1c709f3f7a2aa467da6308f735ec4a07cba9cf25d49a78ad6219c197bc1deee3cf188230248172b0a33fee5e7d0d7d20dd010fb1fffbf723554d3ed8c9d630feae088ba4af2b58755d3380be95120060e1b6a69dc795540e0880566f149085bc6326176684d563dcdc87ab29a8d73ea7959dc2d10a089f160a6a3f9067cf669c79021317434e3f599b668b153b6a3f448ba6f391e4e089f7223903a4b974d655d2f9b5ca5f8d6d4fb84061510105e9bfca0d1aba01403d2acbd027446c46c787c767efb408fd646c8db0381c38748e6ca0966e725e08f207edff25fea6ef469f2ac7c08ba21ec8a796f205e0c4ef8eec3bb71b9152c48bebf3bd0
+TAG: 43ee003b1fd38dc56e23bd81a515eedc
+
+# DIGEST: e1e6201d23f24095643c6977d56205a3
+KEY: e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a02
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a02
+AD: 5cb8b9d71d2989ab33
+CT: 1908c9f4b0038e568f15e46af6ccbd5d798dbb08c1275c7f757df28a403e147f1a90cd69a3462e7f4a1681922478720f62508f7259f75948431cdbd8ec73dafbe666688ad18302dd17ea7fb41e0aaf5043aeaf041aaac4c389ce4a4ffeae208bfb08f525d05f4dc0376651e999cab33c0106dd21fd75532ebd64ac942a6375f74a559543b981fd20c8f71085b38ece0d39b79bd8115cc5fa52bf4a074e1c72885573a6aed0fbf85fb1367dab0cb4e9f61c97674bca43633ac0f7cadaa6ea5a06700750c103df4164467f6e3a4677aff0e68da74fbe37c1d6fc8b97b5f19b195a6f782865ef6000017b4b29b1002d144ebf1cc07a96c6cbf339601d9d2a7f524671639191f7e81ceff4e8420fe68a
+TAG: 01ecadfc181fb3bb47d4d5b907054f16
+
+# DIGEST: 57210154c6292e0847d231ad76eb6168
+KEY: 3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d
+AD: 2989ab33e978c4451e
+CT: e0da199b8bbaba1e440abcd66e03d85e8d5bf78375507af506ba5015877c01d0f19115341ebfa1f69fd05c5d999aff0979c101d82651b90925cb4b929f51d33fb1756d6ea16e445910a09ee8ad261042becf5e54d56bbcca2bf071445826dcf539374da414628ff4e39177d5cde20f1dd0e38db05ba1503820ed6cbfc663835634b902434b8eb650ba9056fbdcbb441a071234bef49f58ca7ae621075a773e0b7d92447a98d629c8d8ff092d7feec70ba50cf61bb55c1755f9f975e7b16f1abb12939ce0f1f75060421cb16a5b6201f86339ccb8bcea1c88bca929d0f5f9d5433b12cc07de858981ce34e94e1b71802b558b82148facc5e03d337fbfbbd63a01a3a349a38f3aa35d6232edeeeba90e107d972b
+TAG: 48374614d65c500cc3c5e2784be89c05
+
+# DIGEST: 6f6d56cca5d872205a57571fc564cf72
+KEY: 2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a7
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e9
+AD: 78c4451e3be585a29a
+CT: a1304672e5950c3c4805bd1556a87debd1da675b727d0e3ea29ab7cbddd523d20a0bdfb39edb2ea7da3d82ce489defe5516ea8e08b627944ddc648f77eca01c1b9b6e848c60dbbacc6bfc16ad82aaca568d646407be98710fd8d16785c4845acfb9e583493b8cbb170ebba677a160099954aa496aa9cbe5dcffca907096b9b57da293eb86622b4b6656241fd47e486ab541b9dd4035ced25a5e3c40c781b4b2a9702f96d567d116ab0b26777d01772a0f86bb4393fe09fb7251bf0e722fe27de3a31e4b8bde14bcdbef78d0c0611f7f8fd992d6699603d0fe267577e559ac4fd533b53a4de901b7dce10ddd4b672f46c8e9e7b461453a7572e20baa7f48be990aca2616917da40571b6037d056ab955f811d5250e5aaabea
+TAG: 9e783043a55aa2f2252436d1474bab8d
+
+# DIGEST: ac37709ba1b8654c0765c9bd4ab92c3f
+KEY: 1e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b38
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3b
+AD: e585a29a2af12feef7
+CT: 3cca2772b518cd7418a047eea4df2a4f98447658301d64c0c83cb7a2dc2b83cabe50f52aaee0db53d97a65c61eb0976a0172ee9d2cd3cac94d83dc3e302d9ad6a55170e3bc0bc32da50beb7f3502d464ce763008c10dd80edffa49207bbb0949874f5082da43591f78017b1f522b8683c02b1b62c738033e8ae2d9854d271e667275cc52dd40cc4b13b8a51249421c361acc7ab1c802e6cb3ef1e1a41344d75721a886c43fd2b81ed688172bdf393a83d986f5026fd296a3a789417904aea5c796df1bf7c7ba61409639aa0c244d2150c94469f7bab5ee15c93fdbb78dda98023ca752209cfe91c5748358d5c882139c6087d6e2a4cd5fca929a6f28d69896eccc60e4ea191db090c25b3a283085ae2950e79a5721ea9f42fa7696984e
+TAG: c29132dbf866d880af4bf0301f936369
+
+# DIGEST: 4c53d119a5f99d33bbde7e15e076f5f4
+KEY: e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2a
+AD: f12feef71e1063b0b4
+CT: 9ce6bb2a8165fc84815d512cb79b5e6bf95eed0033d982af640b1a48c3a6c898e5c11b016f08f824acba3da4cf9b4775a47d0ae4e53f7fe0bdfa6adf0240882cda625a387823e20dadd940b8d9e84456ced027f7844e3ac9c72f150eb5a422793128827b88843c76101bd0c8319ce6cb760e4205b5833b34f643de024a7872c4a76574d19adeaad0555c4e39416b4d1ce15c9bb26235ed8e705a1ba13052ac366094abbb0c441e508a26c1ccc276cf6c43738b786572ac43782a9493ad47fa82639dc9337553e73ae0587ab01b6f5e928dae0a1ae4393b780b8277cfd5cc9f358bf69ac21f4367a2a3711e2361927b7b25469e65e8e2c29250c2239ef358e2fb41e90a556d7f81c22086fbc2e16e23fad45c0781b9464fc39de6ce3821f3c64dec57
+TAG: 70f696d5c28e546c2df1ab518414bafa
+
+# DIGEST: 33c72019b806d647531a2df1517d13ad
+KEY: 04bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e
+AD: 1063b0b4e6e8992003
+CT: b2b6753787cb50b8209ffd5529da02b64594159264f69ce7ca0b2e5f42d9eb6795e95c3e6baf57a3b7f5f7c260a428b0d47b3a4fe2d5323e1d2554014ee79b2867d6f954e1dd11b6b8b0d8d9a6088a313672f6e5c0699c8b9dd013cad4530a37fdcf7a813d3a71b7bb87ce2bdc3e6fce237e26e0899eeae031d808a6bf37cd4ab88466e20dc9081484c1938829626893367888adf5fe7ea66e6a46457a0d6980a2bd96b2dd2c8386620c93ad6a30e904bd11c3515651ec78346fdb6c4a3d61ad696741d55da980027668c016f5a9f0c991a1d57dd37900e51502f42b1f3d7eb865fb3836a644ca0ff6de2d147d89146d710cc7eb01c025950261db300b49e7607ff8a0d6c5bbb245f82b684ea1e678f20ece4e05eb2fafddd8bd71edde6f3289d36354550340e9
+TAG: 1e2fe20c38aa8a9f9226b0b8d41d8102
+
+# DIGEST: 32f25db0edef93b50a9104b5fbebe0e6
+KEY: 2a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6
+AD: e899200304bd350813
+CT: 9fed83de5dda9e0679e98790bcc6226976dac10414751299af304c91e40c91bd239991e02a3ad6d3b14c84d32ea2c39def6f8820050c3fe9a21bf4e82d58086330361d5423c3203815d5208dc0f8d3e774e8875a70fe3c4ef09341f9963c078844a67ef69bbf66bfe939da4ac57f9d5f53b06a5c9d4d3defb306966f15be2a6d431dc521a5994070546cdc35d552a5e9f582110c39f79d77fb4b1ced4fcf243fcf79c55cef9fb0c3a0a66cb36dc822a68f6b0fbaeac859acdda1c9744e690c7248f93358c989265a3b45718bb654c08f1267c57a7014927fc29032041143d102861226ede06f705c19da6d2baa142996380b46c0aca0e9f103bed84c04e3f56cf2f6f983672f8daaf4222513cddd2a2064829f71a5163150a5e40d38acf7a3db30b4da0f3efdb835c43d10f3
+TAG: 7881e996e03efe69d69d6c3da908a4c6
+
+# DIGEST: 2a36a608b469ed2cfcd987016e487b06
+KEY: c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304
+AD: bd3508132a027d1ff4
+CT: aedd430e100b7355b832d0b9db0bfa7a541527654f19f5cde4689787f3c705596bd61b5406df8c78dc833270543a4000866dd9896e22879cfcba25e7aec57492c2ca2f6dac77eb3facf66ae1bf12b65671f97e4a6c7064509699bec7adbce0e0e3f6175539fd35a9963aedca5756af0daacdc604a6e9e4d3f7f537ae8f42ec5d42168225741f309d3b0d8e912d77207be843799ca2d80cccdf68963ed0941241d6e306aa4b682c27302d054fffac44889f04e851c772697e3ae7f06305c92c229905d6b8dd9d7b46287dcaa0a32ebed120dbf58ec533ec4bd6c360eff8ead7b6dc38e53c3d4c7582e0b71415c5fcbfe170beb7259ceaf09ae450cafbe7609921c46cc2e44368f6026be8cc0aae797dbd8766712e5b5da85f83ee55c715883cdb9c508a3eb36453ff51571e8d7a63a71091
+TAG: 044b46de9c993cdc81788fba305f9eaa
+
+# DIGEST: 16f650bcfc7127fcabbdff3f344a0c0d
+KEY: 57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a4172
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a
+AD: 027d1ff4c047b3ef4f
+CT: 3f27ddce45f3b828b3a212053c97da0f14face2f622d440a99596f900f519c59d95b5161a9f98648a58356634bcea4f3295af03cc4e947ed63b676a3e9c148851fe96d805b65552225a9570ee56e60d22fd8f39f39070bf7f6d666fb538fed96b255d022413b8252c414a17ebe49b6e01e8afec0cded8942f52ea7ce814aeb5bed9e883799e3951e809a92c3280b24036bb08f72201e41f1c0e6080f10d3b71e26e29e0209e18769475a2a52bca05a66735d8e49bd96f7e2507dd33bd597e24449aab01496cc924850ae4b6958bbd4e4db3810933585016910cc9f290487626acd19c33ae70c7eed3477790959ac8117cec940490b586258a59bc389a4e03772e821d84a36579057f1d9648ba4529d7ce35b4a189c69ada0e152f32bf9e0a197d651ab805831322ec52c56bf7d6fabdb6a758ad1956d
+TAG: 163b19ed66856084833dc222f2c3c925
+
+# DIGEST: c792c5b1c4fbb54909c5a4d205194c57
+KEY: 4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c0
+AD: 47b3ef4f57a74706de
+CT: cdc1da3548980c176fcc489d4bae72ea36db636caf6e6201c2eb8af5968d6aa2bc8863450514caf27112c9ed4c08148c75b6b258d4c0dcb55b6358305fbe15ff6ec435947ec1f567fa8f680d0f75a31a7b4a96013b6b0ceef3a5ce95a7799e50434f3d702ad886313ff3e8b9445efe59372e10d8911ce6f0d2e0c1cb3de3340912def094a55c0970d48fcfd728d6ba66ab1b38018cb56507b0c3e462921043ba15069e9553ec04db8e8a329f09d52508328496d8d30d0f82eb85fa8cc7d63119eaa3f17107a05834c3903e2f61804a7d89542231868d943f1d73502badf240d3de7cd400950469a62a242406ec125cfd92805243ce434194a104e8788f4a1410c93bdd68762b0720f9b0ed3bbf559c720cbaf66dc90fa26a4f1c86edf4d23e573908fd2f8b465cb4e30fd19af5755c5376e60876d17a31251583f6
+TAG: 62e47276e4b8c8ab74ef98b6e6253462
+
+# DIGEST: 08f2d340d16d63548c1d29e52ee8cc09
+KEY: f164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57
+AD: a74706de4b381c692e
+CT: de4706e5eafa9f448642f34fc322388b4d6f69cdd0ce20a87655e6e6343f0fa830e9517628571f218cd9cb06a5501577901ba940be24884170f789da2b38ba7f9cb8d42372b445297f47d34e759d4bfa2fc843fc52059c1ca170da3f00a9c241ee87eec4c95d52591d373fdb73f96ec4a86df3afc4c6705b8aa92cf287a94ebab80168a5b5c0a96766b709ad7da2b365c78ac6c99d44c76127a86ed4d3dabef7e3a744adb7368913cb0b4cb626735ff5e9eab51d285d5aa72c78c3ef45a5359d51177b4c009f071a50e53584c450a0aaf8de3b65fc915c797feb48c0c533152a9d93cf3a60d99e5bc02bb7e2b461b92500cc2632ba60ef2c31d2aed8654302063fc2cde4706d9988a9539c28ac1195c0d30b1c9c132e797fc1caf19e62bc3f9b4ea25a0b1cae86caa6477f808d1e9ac648bd44971268d9a9e534b6719606ff3f
+TAG: fa8e48c16ed080eebb362665a9e807d7
+
+# DIGEST: 71ac80721f38fd7d54a644765bd1f48a
+KEY: b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a0
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b
+AD: 381c692ef164101b89
+CT: b68f2908c386fe241571edb4766ff64ddddef9ae511740ba949b8adcee91c5468d4b87eb27cf639ea43fb56668a732a6bce74cfb2645dbed1c5f39016b82e9f471bddeddaf60f5cc11ad66d56b586466f88eececf17477cd86fe71603e20c486615d4ec960da3860a2db4d2a33c815b5cd4db00d666d1e2a59a09a139a5f94f9d152b658d0b7c3dd67f799fc0e907489d70d293ea16294740c9efedbeb33f0b2f821f2ffb5777bd888eef29463c625482b733539cc0d0691de6b59daa9720998f04ac6477f80db62479d92f2970b4bca34aca11d0ea1dde560b0609c50460ed0e3c9ce9bd0dd893d84c47345b0704cdef9832fe720b0c054dcf9a0a6a33b6d69d3fc4b398d71c2d4dac4e480a73df21c9235aaf82a5c5985abec1a008795f24894bb326048b91b0184e1a02cc8e23358949f860ba425daba75d5494e096972a10312a36dfe
+TAG: aaef46b0180e51cbc0d9b73145601c67
+
+# DIGEST: 3f37e16dda400dcce23bf4e476f6a97c
+KEY: f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab6997
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef1
+AD: 64101b89b476f72b27
+CT: dd955f6ce7c833fbfd6859ab34e563dd685520b4ca4a2b21ce0f462e44738a5090d26b5e71e450015f5b0e08902f2513b9306d33bbd4b25a9b5a00e66935e8ba6a1cbd01fab93846163170f07297485cbee2a4fd1cbb99cd864fc281f9e35626d9f936e57b8376225b656ae7280e2efbf1b01085e5f94c22733ed5db9dc061efeea59fbde8bb764fbb6230ef6133208b3128c1a402bf385113ce9a1288d4791cae37833270af8e83ee5d70adfdfbac1033c4642750d67091d4bb4c222771bf66215273ecf68767aeb5d8d7fddeab6d73140aee4ceced826ee05f55b5279ec647d4691c4719b49d1d7f8afa4e7acdf888ef3ad9846b21e2a4705cea9f3c7038b91872373f7db2310fbfab4707d067977d79233e8c8d6a8eb113003907397f6d4602675eaf5065be12ddf486b20cdb014bb07e7b390d41fa699086c7d3edbd6e1cbf2e705fbcf099bbdffc
+TAG: 3ab8f56f918b102691e8193a51d58683
+
+# DIGEST: 658412ac7dd60a93ccbe73c9d88e0ecf
+KEY: 67cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b4
+AD: 76f72b27f06f520c92
+CT: 25b8ac08fd2ea4e9cf3dbd84245f007e32024c8b257e1274abb9dd144a6ec3999514c07a389152c603efd9e2bf8d742c5c523d15047135f0b0677ae9c14fb2bd60a7757cfc6818291c72e5479aebbd7133ec2f0e31c39e9405ee6aa1b60835db9f9221768dd4446fdcacbefc6a2696f87afe8ed0cf5b09825a07570edc2f7b3a1fc1342704b62590347145977d0837003a5d9c19fa2888eb0ab211d7dfaad32fed7cb51e4ac9f029e650e863ca165f4cce99c8b28df78ae73d22c7e4d0d6fc75f2ece50d8893f3a73bc92fa69e5c9576eb13f34da976e1d44f9fa1814224c20e057e9c57ae5fefcd5366ba8176ad4d468a4131541c9b8a3b20f2207dadbcca8cbf4872c99a11c4ed949d0f05d90087050d01182a94364a845b5a23ab3efaa51589cbb158df534299d12af5654002f1dd92a19e6958c40bd7e2a00cb213c75050fdc017190d17c7b077bcfba80f6014
+TAG: a4f7c2bd8805e03b38679d1fb86810b0
+
+# DIGEST: d58f377d8ad6c3f53f39f38c0b2b0685
+KEY: 41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f0
+AD: 6f520c9267cf71408a
+CT: bdccd6103753ee7dffa21d7254291239015da3532076b11bc8ddfdf94408feec7b92cb135ccb8da8bbcf1a1937d942d9d9f9acb009ba63e3bfc957e518d3ae36bf839c073d9883549cc7c826b91066155f798a30d1fe2fc5f8904af160e359dbba7de774e3ec468d6924b3774b3ab753bf2363ccbfb01416d7f918f16b4195853c19647027b617250766d730fc3e50d0b3710e965c829d5366809d91c1fe35ecd35c17110744b842ba6ef81b2db7e9bd992ce8909da1ee57d54abe64bb50d6265611655ac5fcc574180072afebe0a60da3fdee42af02552499d8592acafd8ab0fe63a0235d297b01fb4bdeb9fd94ad52ffe1e1e51fa6564b4c6f082f0819f2da718d6bab23ba710ed16fed50d8366ed950758ce04ad8b927e07cc4f24fe03ae21676d6d29a9f70daa29bb163d9f4926683447ec19f58fb81204312a3554d017478a10c618e1da3316288fe084d70eb7496d0696e
+TAG: a2b7ba032f834f83c7bedd1659ebfc85
+
+# DIGEST: dfd840fe0d59eb9b05884455fc8f2644
+KEY: 877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870d
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267
+AD: cf71408a41729bacb5
+CT: 34afbe79f3d6c66af1401d9ee8206716888d447afe33ec0dcd672a10fd2b85d7226653268172d35e4ef236ab3026e95e96063825e4e3751bc05dad84ecd9991912ffc95b6000baf02882629c144dfe38cecb8280f93b571dfd182b9ccd0fb2bc6cae64aecd8d9a2469fa710ebb400296e3202ab1290957edbadac45cf5cd37c86ab7f76df262ce4f2e0b8a8a16c9e7f220055ee6ec108f43e3e908f4ccd1f783a452910afae90c14ee3173a0c8252a2007a192a431a7d38d981d16c88ba6b1db2aace490acd7e63ef4f8795b6b0f449d44865ed2fd243f3f55e7ec1c5233686db081a44ca428ccd96238a33324d62f0aff7c45d954ea778176b68123afc18ef32a76d77f5267e54d6ba06472ef82864011a022a9da2c567ca32c5ea3718a93d2fe747351a452edfe610e552d0bb949861e6c615f34d1b5642833bd94b4dd1e38385dff917f8868565ca5446d6b09a2641b6dcc145bdee50b7c
+TAG: 48d515f164f18b80a3fc7890381452b4
+
+# DIGEST: 026c86d0f2cf51fafddc6623fa7acfb2
+KEY: fa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bd
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41
+AD: 729bacb5877e72cdfc
+CT: 6bcd3e1875adf1a8e5e1273c7e887347b7aed9b028efb64e7863ce92b0fc21a8e150fcc5f35863279be9e3455eeb3812dc2453ddac241b9dad1cb419e38a62e7ce48363c01d05f85cdeae37a4dd4e7baf32a8f8ee14822f0e4ed7e8c54f6dc93aa281cb63a54f6bf7e54c3d59e29d6d4cc838c663cf9e260e1063b080ba4b68581e022f32fcfafd6f85d16ed52ace3bbd8d946215e325104ca73c53dcede023c0c56a86741e02624ae6f1cae6bc7e40409a2043e629c5bcbc07fcf5f68fd720f51e80f1fd69c2602bfc7e6714b2b1f268744acdc52920987a9db30c9fce1ad47e9490a304fdd7aee4caae1f4eb2a68a2d7b481df7c5065a96d321d5eb4eeff673cedff0d31ca9052130991a57fcb471cc463718f8aaba373ce2335f51696191828a98b9abe27fe9700bc41939a49b7a478f88f488baa19cb4c33a212fd6b30fd9c227f0577aba83b67b0fd0257f60c07bfde1cd71cec6d24be3125896e8c
+TAG: 164b98e0627ce973fc196ed1ddd97c50
+
+# DIGEST: 85b63faf53d1a1caaea723f2d0f4d9b0
+KEY: 07a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb105
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb587
+AD: 7e72cdfcfa76aed067
+CT: cdbb9d06cb5973d699ef8418b113f9c5bbeafc427b287ec3a475fd64eccf233a678dfb850b157e18e95309967eedc381637569ce5cdc68c0b89c4dc352840c55511cf8a4291838680a10e9f1aace56a6be46856f0d43b9961c2d5acef06586b72c0cc05f1902caa846a94e9206ad6ea203c56b56f70b487cd68232e78a762720032ccb98954b32aceb26f3d4a8487a20eb4fa47b67f7887d3a7c79f87143aa14900a4579fb2fb28868621172aced46a3aebacc77c2964d0c227a3f4b9151250bbba35c0961e8f025b00b055749ea5914706ece5573f96fdcff359d2124663f859d69a5f63a4ffd853a8aa7d2e728a618c7b86d0b9f770cdd084913f7228249d09d885a7375fa36cc1157188ae9eded71f0ceb2b414bfff03ce20fa57d939fc922461e265d98563d2d345edd785335da838dca068d7cbbf40ec5881eee6a9bb560b5989ed35d6136c3b8c891f6c19e5ecf0af1b49425f48eb7a7c631adbee3733f33009
+TAG: d33fd21c1dc33ee95ed519c091271f0c
+
+# DIGEST: f5f396b0a28d97d9c5f9880475d2b313
+KEY: 699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a1
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa
+AD: 76aed06707a07c3dab
+CT: 69cffa7ec4f11dfdf2cfef639774701c542ca22d52ab53555382b42678c4ede8dbf1e8c376de99c4f75e426dcbef76b96c29698308d80239bd60c804adf846bee81cddc48f8f004f05145c4cddcb00cce08ba90bb0342f733fc661b6497d082898c49c359bf67dba8f1634ac16ea7c1de60bac806c2eb36ab4a25d47c9f66a3da1608e562b0c1030d0174f79a211ad442aa50f12e91071f7b1ecb7db05d13c4acd9037b62dc0d7c0a9753302be298c7d8b71fe9952c60d88d5a46474c69e4f75000bf871fd4c2bc4dee09fb917b06526a599a53a616f3134b64cd0dc0b52dc8d7d1d6a4f7bc703b18e710fe4cc8ca7013abc1426b8061c23dc595ab94f5acd0ead423daa1245dc6febd5d4b569fe55c211bdf4bc28bd803a4b6cddfae3fb2603704276334d3e5ebe3480d1a44e5abc40935d2b0c6a985bd7f42ea35e99abf943de78779b766a59b40f1621c31b9d927234837d77c934559f7f5c5eb862395540a275a969b1cf20b3
+TAG: cd28598489165f20a382a4edf219e12b
+
+# DIGEST: eda1d27c78e3cf18826d72aaa9d3360f
+KEY: 2eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095d
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707
+AD: a07c3dab699719fe88
+CT: 44917b7da50b0d57ac61aa582ef21912243eec101da9773e0c82a279c2d778d42583684e1f9bbc2bb7d58b2c64d4226e11dafb002f80335b930924e3cb3baffeb55af42d9ac4b7a8838bb7e64587a90d6c263511e5d139b8d1ed0ea08ece969bf581eac03eb34bd2302c606708bc1522e7e728790a6083315a08290323658a85562437a61dba7fbe473568fb601021c9ce82c6d5f5260a2d3e2705c59b048d3a269f1bcc348931e11c3c05f43b5b5a91a07b32647fc7b5849697333f5c1609a9ecede15703657ef83ea7cc9cc8074399ec1c4744fdb29c298458db34b283a8285b513c29275506d866150ac39e69ef08b56207f69b4c963690416ee2920e441e4001cfcb820d27b67e246dbdebb642bcdbe1a060360f06c2cd8e98cf496920a252fd895fd8d6e316eaa2081d65e2eb01bb44facf8c76c4bda543c1d3587b40e077a4da20c364d402262fd729de7c11afbf44846f0372b012ef376eb6a5ac0cf0b8ed4695d22ab53a6f48b0441a
+TAG: 0427e13275e8c1436eca3da08984a503
+
+# DIGEST: 4b1448f2ee1aa8511c3e24274530637d
+KEY: ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab69
+AD: 9719fe882eee2fee55
+CT: 4e585ce43cc157dbeba9c21455712dd9ef50f9fc4c9567d8ced08f1fa8a1712fc839d2331e658c88d30de97ef6225bb6f9c0eaa71e35bb10de9b73c3666948a328bd1da06a62ade92f29f336f9affcf481dc0b0a246671aea223c2b937b93f2ffbb0ea1f17bebbb6a6964c54894aa7f2671ce4eda1b361ebd64d7268cb8994f683877e24765487821907b3e88544de6094e732ce01fb226eaa1f74aba6f8471135dd944a9a6fc22f2a957712735060ac0aadf1cf469fc9a4fe1306d9c22d671c1c7e42c0a3dbe2016b3b535869f5ec438e644bbd3f08c4f35de10d72314717328a6e60fdecb604fff90ebbfc3a6118641ee71b2beaea672532f75f0fad6a0d14dbd75f9e0038f39c91eb55c9a3b022e910cd8ad002b83499727b7f9eaef2a7214176b856171ea9757fc54dbf3ae455d1f7ddff2003981c56e1d9c53b4ef3617ba103b77bbec226833a55fbeaa587b4cc1b2abe70023262fb73bcd3b97fc762d39e1cffc225c190d7eb8497c6016ee88f6479
+TAG: 1907b80efe6d13c65dab5694dda97cfc
+
+# DIGEST: 2483a9a1fb3c7b3b399ef062a7b3b7ea
+KEY: 870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d50
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882e
+AD: ee2fee55ed8b11534c
+CT: ab9da4a38f81737ff05edc442ad046f6324ab9f6ef0b70702438e7e2b4e8e9c893c8b7af8a49fe54c3d8dae8b3983b5c625dc101de20e3e1d33efddcb9932f2d88769bf950fc26850fd41be4c13f6092ddd3e611992baa4bd526ef66f44c80daea8e3eda5d1d9f680b0403419be5e30424749714e9792f3c7a434a94cddee59e8680510eb5f78684fb35913d5592a4721b649f2ec0bd7383bd0366fc07ee3c823a2e21fb116444f0ffc63e9a83be3fc07a7ddc371ed532d7f35fc58b2abe0042290544d5f0f4a07a3accf1fede69c10917eb626c63756338e9fd498659868b021b02d223101a02a8ad05ce734426cf6a12a7e1ed5d469dc8a6b88aca88a725e35267a246828234c4dcc0fa7b62b61bfe7526babedd6af7f4c877f74c7abed25eb88fcdc1ff1eaaae5738b2ea03928f304696683398cccbcacabec855c6e1cf18a42fe4511da75dab80a364755fde1966d9b9002f335fd5aec82f1461a9d61f2138c31f7c5513c7ea16cd008f6f81f7da273c5287f18eba
+TAG: 878e67f8fbc86d4b7f721a68398a3103
+
+# DIGEST: 35a6ea4f54f8cc735b35c8f71c48d325
+KEY: 14bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed
+AD: 8b11534c870dc695b8
+CT: 30999422519fbb295b92b377e03294feb061eb57cd97156cd81518fc66f75b4662df89ad3b99fa0afb3a26b1f40d1ef1b591a4892ea10ddcfdb985a84e19affbb3a4c61f06e473ead4cd193426ae632d4ae2c419eafef1ec43b7780feb6bc0e6e17b6fa91c7eeee967648cafdfda6afbca6b6822e71dd563ebdf6b6f6d49f98d9748320692466865fdbfc2bd9f047feaf213bfac7bcd4502300539133353df343253034712cc236c74bbf0bcccc8abbe7cf44e445de4dd24be54bdb251764c36632f1446339e58904a26929085db0182b43beadbaf3c7086d9831ae59789953f59428fc399490c101378c952dd6ac24c3de1e1ebd6c284cd367388f39d208a2b5196b3fc737c588abf770260dabf9dbdbd36670d07dff4540ce2e67bb9173a8d9a038daf1b59705a4f5d5ff51510646ce283047671bb7fc18ebb6013ee1b47741a31ce49302da399ff0e28eef4d5b325f67f8809f0ac19279372cde0f8bcf9141f2bc0ee9ce892e5427d31a016be7878fdda80fde1ce691df23cc52b
+TAG: 40910f0ad89adf7cd1e624a1325545ce
+
+# DIGEST: a351ccd3cea941c35f1fa776f09e43da
+KEY: b1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c87
+AD: 0dc695b814bdf1a87b
+CT: 81d6805a8d4764e52521cf995311fd2979146862e9effdbc3311c127be3b311b6bc325b494b1db8a5474f3bdd2b5bfab0e5fee38868af4f1410a8bcdee3aa752306d72059c35eca63e19ff817bf6e4cb6d5b716194b34203e84407ee27e7d42fafeafb9260273f92b7636b5cce9c454f524205b642e83640483cf9cc9f47e78857c18465fa2f576cfd95541cce0f2752328f44c3a9f257dabb8d3a66eadeaff668f302265920febb8f0775bf5a3133c9d47b92fad347bc26ee582b671865dc8ca59f3a4e8200da3278ee58b95e5774d2303607da64ca32c31035002281474da87d3c9885eb8c61a1296231ea1d3f0cb4fd91c723f374373d2efb8ae23f3e8054c4da9ba517d8d2657093e5cf3c8c43c6ce41e0047118428f4af04c6cfbf9224e8dcc429431e045b05aa5f8b12639f2595e48c2585d9d1d1a602ced3102fc3b744d83ed9ca5cf0b28db7743d3f47362245f996e57d29328321cd84a73687ed700cc202ea52c64bdf6775344b1f1a9257d7319cb6785fa593b042d4453ea17d2cee2
+TAG: 2d21e78705f349ce058a412408becfd4
+
+# DIGEST: e52e4a1db3ffc409a9af5b65882789d8
+KEY: a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814
+AD: bdf1a87bb1052c6755
+CT: 53a86af84ebde5059dec18b9867755ab994e897b9512655c489ec2ef4291df74bfd63ecc880c694b0124ffda1f96e51bfb06df2e527d071509e2ae5c51d75b89139eacac9e61a614e2b4033633df5a998a38f146cb8d1d6b69421d024a4dec07f84b9da531e6c23ee5d8bb62b1829cd851471acb971adf23595ef041b682f1085b799adf3dfc0f2795a774ee135fe6db065e0dd642e39642af71e312637ac993bf94d9900f2dffa7a54e51407eba3617667aaa602e1c61621f0dbd4cd1a27a73395d02b5849304bb023a7f4b02bc0675a985c1f2aec2cde3bc226f73634b972f2fa6d1e21523a05a53c7aae524246831397968a5ad634664c5fec0a57c8ee51a2a3e123cab0aa8169cc7d51b2f3e4ee1bd6454930c660cd7df41090243cf542b0f49ad85030d950d6ccf27f8d8e9de6d172cbdebfbac59ae86309adb5b54ab5e25231e6d1526b9db7992d4e82f1366ef2be0c0c4126545e51666c11a6682b227087d1cda373da408d8fd00ac3f099538f9e15357e6d100fb6ec2e5668192190e48f835746a5f
+TAG: dde4bfa752ae99b2c8de2d813b6d65da
+
+# DIGEST: 7a624215d180b523862d2b0c9d9ce0bc
+KEY: 095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1
+AD: 052c6755a7a116bfc9
+CT: 513e03d3bf6c4e3676d295a69d1d09bdb1f5fdf067d02c87eaa2caa2de9e1edd2fb594f0bdcb40eb31779d9699a6ed7e406e2fcbc672297ea75d4cd90fa7481bcec936ed44c6832c28a4f57813fea389db096200cef14e60277495799a45083a65b1baf60595ce7b671208c15795598ee7aea2961c42896eabc76551158407b4696640003ab5e13f9fa3502fe5361c131ef20b12168bada932e10bbe9bbd0c2e78dabdc8c7427f006412dc526a72cbe7afb90c844429e0364dd698824b8260221719b1a8c13edd4aeffa7a482c76e23e3fd06073e9acbad2e1cf55d7280adc73d211efa5dfeee2b8b8e42d717d19ed96faf603a9c4c3c36b63b1f56a5369a9c017e8735415b79c6eda27da311ebffe0b1729e2e040f2b185bf6bc99efce660545d72b63c2a192f462540e8b8c54db85df4cbfc70e5cfcdc1123224d5b6a4b7fcaf9b5bdd567336f8906eaab4c566047c76b7930e838bf0d590f256d9c57fb07d7d850d020b10bb3d5aa52e1a1e64152f272025655eb2ac7b54b3b08bb8c56b7c7308532bf5f8e6dfb5309c
+TAG: 13182fa2d35344b231aa43eefb25ea67
+
+# DIGEST: b894330fad8850d3a33918ca2ed73090
+KEY: d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee585777
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7
+AD: a116bfc9095da49db3
+CT: afd9a2313252e9a333c3d5c1c2825294d09787ce728bfcd08c46726bfdf190863d2d6f0f0bef6a112de2a31c7a76c876feadbfb55c2da3ae056943f8d7385373bda6bc2f34c6dc4b32839d53d0948d2e250cb4a9c7ff38ca5cf6c23b4c2af5b9fcfcfe95f6ebeb8c37439c0aa6ec8b3c3588ea0a69c256283ec42b0e7f3cff7f8aa94b7651c539bd0a2ffe3ab4501075187b1b604d460d8b061d1ec052c04ba14afd8c05be9559b5d12ffb400330f9adf5550a0332a3de83396b1048591245af112c691365bc62c8d339477e34af6ea36b63ec4936bc9328bacb60b054b9bc711b6c7ee2ce405bd3761c79b79b7dca9dd46f13341b7087b58abf465e016bdce12d746a66daf9d52c4a18f0ab2eff69adac3970a42cb44670c5df3c12e1f60bcb14b94a7f72cd7491aabc670d37e2152b078cf6db76435bd2927471c3e88fb1680c9e7d55003dee904def37e492b423d0000c4ab4adc3844183a12326c298fc8fa2b3605d5a6549c392a84eaf7760ca5d7648bbf5549ece14571655967639f9e9e9166eb95a6eb16ce7913524bfa1524e
+TAG: a26398461026c59af3201a767e89e65b
+
+# DIGEST: 92b916267f27859c14cbb07dcd9c05a9
+KEY: 5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b5
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc909
+AD: 5da49db3d71f4b975c
+CT: 38634ca794878081ecf598b272e06d83fe17a3defac2bf8302cd9e6d9ab33eb47befc1ffdf5ca33d607585b54bc9786b8ed1e1414158edb7e120e6567e20bdd30ae6b3a9db076324e4aacb6b0762d4939479b0e79817315c243e987021416593f75ac58c4f65f7910ed07148f1884bd196a5b4e7ffd0f078c753aa0a89b501cd7ef8157243413c54201d5e1f232da8b3ab9fe1480e97f2034cf3a5e8c57e760d99eaafab9b5c2574f079d94e9b77a60a47406e956f995a3fddfbf11eae8aa3584d76bc9bf497d6962791f9e0c9ebe9178317489e1664f3465c66a21bd4fa1d55e683f76bd01b5ec3427d9b52b071b4d7f5324a4f74fbb3f99a20a9844c6c9c5e442740deda2acbb379d323661cb9930331ca47d4d7a0f6abd9e577736cb455ebda5efad8e65a4cbdc4a6e1cef26952670874ef887beaf085cd494a6ebf566555b42eb720321bad0e011fea0a0da6f2356c6bdc5b84c92e62b4bbb7d4e48de3bf6c665dcb4dd07ba6cf4e5acd5c0293719357da9219a1809bf839dfde87e893e520ba0ea8edc172b91b8e606c7584845131db13c3db
+TAG: 71bae6db6429cdfb67022b967f283aa5
+
+# DIGEST: 4465e341e0ebe2ea59175751f9bc0be8
+KEY: 22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d7
+AD: 1f4b975c5d503f478b
+CT: d69442c7e022f4d2c69854e07ed099b6dce18432b1cb232a3d7c9b0a5188864d848c17bde687aa35198085029eec6bfc8abd0e86cee73347c6f6f0fc090f462c4a617f839d047ab31da668f69df66ca38a586fc893d74967f23bdf0c96c0abf8006744c71690e361ace444bbe01ee443588d0d9bbb5aef7566b5ea0b27fe1a4ba2d6c545737ce0968062bf4dfc2de6f498a0b55b2d5bf9e86405ef307eab013540355030e4e7f85fc9d59f90a94894b68d61bcbc5defcaf6bd39368cd5924474bb7f20df0045764d2639b5c0cbef916dcb49d4958af758c0c36b76fe58289929cd83538779f65f1a7aa7486e0d1ceab396a34d6ce7c7d4194f7f1ab8f7a6aa295570e118dc3db999c4b76c9a3222fbbf9855de1ef5a61e8517f74634947e120b55b2a7d2c562b24d92023f6a5d14545d778adbf3b85ac969270b578cdce574a57e86efef202bc89f041122a4c429cff087733ad3d04327e62477f937e6ae13912328782d5ee248fd486fbd4f03d6548fca41dc8a2e543e86aa1d75cf39b0a02a55ab3bce92ea4e7278bfd021756b19e5bcd54da002f7a3a5f0d3
+TAG: ba423b074120d15bcfc99d8a7920db23
+
+# DIGEST: 16b14d50d657a4dcb5f745e2de66b2cd
+KEY: e6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d
+AD: 503f478b22dc8253be
+CT: fad86b42e107ec8d0bdbc63561fd1d83ef5ff9943f044b1ec1c1ce554043f7a763fbb68fd910fe53beadc4d570ec7e671abea1a99be3b368a77df28664c9e8c143b28f8753324c89261055409070f6940693ea1d3708c6465219064135cb85d79bca4317e159fbc5b624c2fcbed3f339de5a6bd4fa2b927481b3b852db57d9fb7bc205384faf53fb604a9b5cdeaab3df48998c61ad280a58f10e9ca9cda1976e461e8d1b9b0ab5f32078c00132ff68cc20435b441163dfdd3c8041208e4d11e0ef0652eaaae4d4fb8ec5662ea60eb78e188b9dd1165382a5226c2d070a3cfb94cb6765730de2715b298d92c6c95a5ba8b9082634287266b90c7498ab30b9516f9edc35ad89ad55c4c62e60e4751aadb61373c12de1cce4ffc12311e0b33209e138c411f959b8522c221171acce55802633544dded45bf783a50911008f199db1cf3fe65581eca4379187ecf14432338725bb6123ad4664f5d9f91337e1d0a8a2b3562fa83ec0bf949453e714228455bef0efa8f5d7c1a652c49167634b1990dc1126efcbb8bce1c3650a69112ef5774f5e46f3bf69b1edfab4035df916fc69
+TAG: 41ca785151f835b99bda574eb5448068
+
+# DIGEST: 9b69e954dcd34c3a5251ee13e4c8179e
+KEY: 307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf78
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22
+AD: dc8253bee6fd1b174c
+CT: cbc02c5923d5f56eee4010969f486bc4538f38185159a23d751e339f90565b2e8f6ea977c2acc892e05159e772bb2d8a6da0e0ea2e8d314fc85d4e4cb63e3710ad827a0a260d5b4eaec0dbbef254480a97e2008975af36de1ca301d69d6a360325380a68565e9a8701530506ee759656e5cba2cac1ecd5182c2b70950b9afdad6cf0888fcf7e6f519434efc31ba87bbf138fa6f6883fb764214740f4356c15ef907960ca8901304739ae30681c7e3d91dcccabf22a2bad5b33f1ace436a3e423ebcf69f9d7f61e0bbdf125e6be29a85a0c18c6c6da1c448d71588e18ca180fa697ac56eb6e24d3cb4d3d35367fbf800dacc305048fad71e4376aa0416bf7647e24b707f4e65b40555577256a277a882b9a5d64f27e1e56426236ef951650d082a5b8c04c6ab3818a02d39c0e9a1b78da109284c941d42e5d7350ff89da8d83e7e61536648f4afcc84a895f50234ffa9c3262848bacef0161021b06756d8c2e13fd55602e92d3a3bc79f9a7d3bbca56885826da10063f2a14b3f04a3ea3228575416f77e3797951070e01b20199e4067c01021ec6cd2c86a6986da094b9a0377a4bc8b1ad
+TAG: 8a271ca3c9fde6a6152d4f624c7c49fa
+
+# DIGEST: 5d9d41fee2178bd7f431f60b30771912
+KEY: abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6
+AD: fd1b174c307f01be95
+CT: 4de1b987a419e38d54fbc93d7abf0dba4a9b6961eba02fa37035d3a2c29ae1edd8c92d19cfb4efdd99fcc164db9049001dfccd13617faaef9617ff2f3dd2cd567546f7f63820bb330350d88a8bb6d7758e1050f53bc4c0c9f570b02193c1a41ae9290d3a61aa67e6c1a300ad48f0ac42e408726c453b79509ff08aa46fc6ccc0648485c6a1b70c92c759149bbce74778e7ce5b1f9ad3eb524b95730d088c284b616c0be8b44f27730711bbf8f710c38fe21100c303453d2708e6152ed08d99d971d4d20ba1468db0bc05ccc56202746dbc249bcc76e83ec31c7623984f0cbdf58521f798966bd3c2d8f8b5f9423a6c8d1aad475934739b7f44ced5aec0e70e4a581cbcd84bca5106bbff1fda80dd4e8c7671609d95d4b10b92d84d0fd01a5e7ada7aa2b2c8d71ff33a0971b3404add5bf0e0ab5abef373db2fc3408ec63c6f462c7bce3861ccfb32e37c4dc413ccfd9c44e3184ac3307097feb9accb7e39a46e047dbad88928f876417da4bb436cfa434088fa5aa13563cd7cba0ed36cdc97cff0e262dc400d472fa2e2f01f12589a551574b3362840e46faed9a120abcec01e275c013494d8f112e2
+TAG: a9ac5e4d19c1e72d0b8e712886ae71b4
+
+# DIGEST: df2b853313aeb7796dd6b91b45710b2e
+KEY: 57772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6d
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c30
+AD: 7f01be95abaa9bee58
+CT: 0b9025f707950937ebc0d835836bd33ee943fdf1bd77125f065f2e2ce96c23643c8a7b48d6832cd07c0aa42c820a50bda0495a7ccebfdb37ad5a95b3d438fb1ef1450e7a6d7159f0c020b45d2fa361cb1b19915404181b098cb2aecf06b62425939fad6b4e0137844c5bf5c4d1f912eb47acd6d4afe6dac1937397056fcc82b4cb4da13bba3d81905733d85996f3881f3fc9a56cc112b5357b6857eb474188ede98c16e6786a1739232b0b9cd7fc7d255138f15bea73f257ca7284835e26c0e97a814720500ac2079eb92d35bf409d408cce330d892f54a21f208848521f728fc77fe2845ce0d51cc991a5b017a399edddcf530c5f9b5025cd66e1274dcdd27d57ef72d6b82585dcc2d9e4537854814c5d009f99710df74a60ab9615f6ed0c5690d488899b12c969bd121da9f67f9a973830867ad088ad2c5d90ebce3c7296072efbe4d6145bd7fd93b3751befd8322c5a8a0f69ceb9c2c33825434e4aebaa5040bef331fdd05909ba09d6f5d199bd88b11c3ee9c12b3c7b252c9726c3b611b93e78da1d4336a05795acd2f928a77ef424ca64021d4802cb9b42d3f639c61def102e76be7efa75972dac3698b73d
+TAG: 2e052714cb1b6d77009074fc7ed23810
+
+# DIGEST: 539203e4c1494bf84e16a2bc953ee485
+KEY: a4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95ab
+AD: aa9bee5857772305da
+CT: 708d7501d07b03e65484bdaff1b0992a3b547685be63ce0b187fc5e359337cb4de113a667f1cb933aaf2e4da0cc91436fd42acfa99a381aa1a8eac87f470ad8e52be9cdd624e46bb1eb04079f5ee38b7d35aa8f4e1f57254c2dda1741e4ae79963ca691f01333e9c25ec9b78485c474ee08dae1523d3f5114ff0413b8d295393b656238fea984b4419f6a8b1185089b8c6a611b2d477d10c4d856504db1dbf1535f269e9bf02f6ff3ee4717a4a903439bb697133a7dd1e49830ba8cd1297e7958e508fd62c1db3c9491d47d21d9471f0edfced7d7626395c48276bbdcea2366593fad2e985623559da742691475c39f8374ceed2748252780e58f80fcfa55e8eeb2fdd1ab9f5fe0b54d56039a901fefb263a4dcf56921b229541315ad25128089c6d42b3b9aefed0d88006b240273d969e6871e2d37d3c1cfe879fe29804732bd0dce6ab8422cce5f52d5342430d79baa81601b90dd904baf1e95111d55801778e163f9d6826904d4068bc8565480658a6767ea2374b383bd7f4acc52874b39e51cbcd1bbef41465e7522cad1f2ac0b322bd91134e0572608f4aeb281604ffdd51247966f719ef0b22d4f423c64da79848a398
+TAG: 9aa7ada3a0949b97e114ba529a806105
+
+# DIGEST: 7abdbff8fe6003f19eeaaedc5dd97cdd
+KEY: 05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857
+AD: 772305daa4b550d75f
+CT: 269e3f3d008c4b37746f57e166082197bbe6f848bbe9e6731ddc73ec999da162bd6772931b8a1b5f8aab3cb5e9e341b2184a1ac848dfb98bb62ac6313a50e98091a8b830e81a614e5010b22c85ce96d717cc80a137455e274e2e432d57e89719df4aac62a3e72ed40c9ebc30b048493174af5563459779a4d9ca18fb7338066f876c901c88bc111a88b2749c96d073565c5b06344eef2deba1730dc9b8cf0e2dd6379a95b49e3595466d6fec8e902eb3caa5eb6040fc739e3f1ab9ee962119299e2d4db637d97203ae0bdfe677d5bd016e3107a77ac95adb760dcb1e954f2ac959ca0708a879e341ab4f5c08ee4fefe55c73eb08358476c352846fb40c01facb589a0e825939abe1751442f4ee49ac6034ed22933f412dd971c2625faf15563fc79d8ce522e4255a890d339d849a1ed9f989e1c627252e4694911be9a11a7c7f2dba4f8a18e8daae6d27e420cb4e1354d996078530eca3cda25fc33dbca151829086037bd3dbf44b56f79e279ca18887d35f64c97c3bfe55b6c41ea2d3af2867fc52a82d258de031dd17227bf260addbce2c2311df31b1b57ec213288460d8d70c19054e7e847eb7f23c174b28eb01264ae17ed69012af59
+TAG: 954dd539b5e5b82da2f991ecad2a1d85
+
+# DIGEST: b5ba41f3768b7212013eac67a613e17a
+KEY: fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41d
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4
+AD: b550d75f05d8089850
+CT: 73bbefc2c66981c17b1db7033972c697a69a0281413f60ae001274b7dbc4d615653e394a8efcbc4100e98a6aba7629fc05f0cd033eaf75156e1267f7cbd163e016c92cb5ad8933f7d3fc91693ea82e4532ed4229a9eb506f543765d704cdbc86cf149d99c3eb92b3c35e5c5e67b632b467415a8d6bdce7eeb5cba287cebb04e9c007a6dfe4032b1c6236a6f1369ea492cc3e321080869656b4d088c9a3db6072cf1242222cc5152743c3bd86aa2e2cd9aa47b079b2ccfe091dfb72dd85d50dea46b0492db7d51012137ce2f7ac960f6a32e87f19138622a7bd7a278195834084d386c9522cf72252f612bfd7241c8331ba9fea380e648c4981692713120594afbd1a4fe46c151ecc557ea9fa05941bdfb8de8d6e8738d32783d0563a7629cfc1a2ac8fc40e2637413aa96a36f863c9e6d02cbe8e92020c3bcc15ff4e05fc312a54c8b297dc07b2d95b33cbe5d727dd0fb45a91a171d5e6b1e867132abd417d84243ebec01211a236ca3ca5936d7fb6a2cc2e2d33ca2ab11a04c23685aba49e65dce7b0e5caa5e66e85987dab4081c9b6174643ce31851bcfc57c6cc9d20abe5a1527028356ee5372cec94a8990147291d800c20a0dbdb718748a86666c
+TAG: 7f0ecbf514cf0af99185b15b23284c1a
+
+# DIGEST: d0267fe533b8d89563e8d7046121b9c2
+KEY: bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f9823
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05
+AD: d8089850fea3711265
+CT: b595bd4d603d6c22819ce1bbc96e5db951b3326a07e46a85b36d2deffd7badad310d2611360027ced4739400e6a7aeba9bc3b4ff1232f1cb2946bc8962c5a1b139db8f9e75166f00249245bc5628b593feed578150a449904e9c640cd2f6a8c96ffb5a6b6d018d18dad48693f165411411ecfdc9d6d91ffd95c9e65c31c22e1107d657c385b1a1fad0ddf404151960162e2dbc379db8c2d7ec9191a78e4bd278a11499b4f61d094d633287bb6698d91da4acdeaa098179e2a33228d56a5fc012e252660252cc5b60a6418e2a39303cfb675d7684f48fe0724927d1b51abecdfc2cd38b2e210eacb3ad9d712a7dca0970e3bfab0ce2be1afec30a88d2a5e45e56428b9acdbeb5b20c8a657c30c8bcd5e97db74a00e8c3e616c37ccb84ab1367e935c4f1891c75b9d657c3a57bf7c2a9e3bcb0933e652934c8d9c4de1bcb772721dcc3850042ad52358376929cd33e288cd6e03bd6db1a80a0fe4b8c2be46f5cb54c9c64af86e2e50e5aea327af276002d8ca4473da13a6a2caec0edca89d06a256f2625b5bcd52b280b68ed17f5fe72fad3cb3771df5fc64f19eb3a44462a36fc3dc2b8956909eb9400035b3cca0c5ecf7cabd66c2e2ea1a65563f8749a29ba0c213c
+TAG: 85bb6da24a0b79726458da81751bc0ee
+
+# DIGEST: 1df657796024b3f5303ea6b7c93f75cf
+KEY: 0bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a5
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fe
+AD: a3711265bf78261046
+CT: 501c36a4048690953e838daa3b21ed3bc99ec6db3c3034f6572b3f19b6ed2ecf3af1f93649ec362592c9537b34907aa8e053236f8c06c7ce9f258203976b81bfc12723807fe3558ad12b74ad3e29585e05486836e537c9b369c54c387e970b514399769d59cbd6f1d43e3420087ad70ac145273d6373b0d013b05cd704e0df4b15da5be3ff51fea41c1f207e3dae111264bd949c7c5650d7b5e07e735c064f9157ce0ca74967103d646888b65f12871d56483238f1006a43dbe3c7f4a0ca1295f7846ba1e6136349d753fd61cb44510149a8b986f530c5a3326e1b6e6b50ff07a3f32738ba93c70a309f47f05793a8f96ffd7f1d18d6ef1811489ef7e37c9fe9b55a9427ff6e3efc420b7012676e649935e85cb3702cf4780a1260eeeb188469ff0631a7d632fa9c25cc23c8d05c440483aefe3692b439114de65b33412ad503b91c75683e5611b2e14b196ff601ad4eca50b49dcf7922d7cc8af687a9239b372d9a85347c225a5bfa03675aeb479fec43a65be1193edefbf767cbb07043914d203867b249907da10c1714b5bdd54b016c9e07e1aa69568681671244de4ee423dc36d80b9195d70b1d7801f75374743c909a3ed9a5f6d2613a4fe55c7fddceb1436d1fbff360aa
+TAG: 9dbf8881204d58c1ee7ce48f1f802d94
+
+# DIGEST: 34af4afa9bc312dfce81a335f10effdc
+KEY: 2e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f31
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf
+AD: 782610460bfd24ba02
+CT: 790c4275fe98628f10b22ba14be7cbb9c12da9237d2a000ffa08048a86602b41966078a3128fcc17dc42ca08880c196229353c69cb1c4a5e999cf73ba05f7d2a5cb830c5110554e9b4c878bdc89ec803c588adfa7403d5227c681496618d6e84116eba323bd88a7b63ef37e426659fda576d26e5ded2c76035af3272d0e54178f340f9247f0fe9f63e30ac1d85b7b03635c01975a90dba95de74d40c3e8a6436450830b830132dbaa5405d391802336f9eb55f1fc00831df6eb9f3b5b79cee5a6fa05f79c2ba7a9667dbd3973c5307c524c4e39c9aafdb7c43322719506314782d461d1b66a57eece5c4c537c18ad579f568f741bb907999156d1958a72b56320bf123f7e1e2fc871fe0aec12e3bd8acbe4aaa19b54ebc6be3f332d4dd2490e54643db9baefe498b2b0f6ce27d3e9dfae7a5ccfcf7bb8058efa42ae2d6e6cf973777d6175e8bacb0494ecd72e880bb000b9445aff09ba6fd842df9c612b596df46f9cb1f83526e3c768d8578655886cf44df89c3e279bbf30d713504c948c8a0f5cc22b38f251ce0136f871f45ad11b519ab298203e1df07df2bd12e98b28d3c5b37d823768eebea444d50f99af18106e421f7221abd6dff05787d94030fe2a7a4bf80c3a544d89439474312
+TAG: de69a2de94edc0b8d6ed8c808845e0e3
+
+# DIGEST: e62b14eaadc8c64f883ca44ee9650e21
+KEY: c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6e
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460b
+AD: fd24ba022e6da12dd4
+CT: a21c3d02b781230bfea4f226e7f5771b2204d12ba69aa73de505f1372cd673837bb27e98503bd342c3d9cfc02de3a3aadf067edc719b03a1e819b7a383fa0a088bc0bf29ac68f81f0f22695902200b6767ccd20e4fe34fa67542e3272575f0c49cdbaf7b34db4deddcf25053d4f61f716f01707afe3f2e04e330563322daaa00fb2384f083be7bead9e354fd15d721f32e4a1fa103c41462f1c24298602f9b81e794ad59717a5e3e1a61a2b6cd7e134efe45632b08ba98ceb5001734d6fe1f4254660dcf2f0c648dd66cb948d093e20bd94a735fd2653806b86ffb3b415fe30a09ebd1e10593dbb1b1eddc64ff30671290e7ef01b980317b8fddfaa38daf1b5ce3c19a749557c7dd2c770684022ef8e839653dcf6ca442ef6907875c6b948dd229b038d8e107d64c3666e5efe2169bdf30e9d453fc59bc4981c887c5675da0698a5e8be0c1ea153f8e073597b4784ec0df791926ff9db525649c5fe7d38493c9103bb00a09dd46b226a471719c7d9e5b2c8ef28b33d6a2eea37939aab607c663afece3f0713213d665791c9df3566d5ffae58b438f1eb498f38cd01311c546a6ba6b5ec4a6d0ddbdbcbb10b988ce6d29b037906a2d9dca0e2d2c530864e6f525dd714ef0ada397c4b620f71603e04a48af
+TAG: d79c4a13834a9d31864a9abba3c3bd15
+
+# DIGEST: dae9f48f286ce7b3355bc3a645157647
+KEY: 0974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799e
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e
+AD: 6da12dd4c27f437248
+CT: 01012e24c420ccef50d9764bbd08f08f615eaf7760928af57330908f95036804eeb747b442cdb78bda535479c21fc034ef4688deea1605a147b19b8ec90be0a11aef2a03bf4d2883cf5884c4882892810bc56c324572bb03404c54f810daae9705659a4d3aa4dd34d41093950a0b9fe3c6067573d9d85b4a601dd423f7dc0e56186dc3d88f258596e52eb3b029343901979d403cee76a4bfb10f54fcaec418e030991d8216480e5b335d3ea061ef93ac5fdd38b35ebd109043761344a21c7acbb03c9046e20eadb86ca539263703481eb109e7682b241066b18ff22ff6c35fea7731aa26fb3d6634620d9ba0ec06624cf5f534713146a34fe8ab6479470a66e017a60d946fb588f7ecbafb754f159a6a2e597446b3ce231bbe2cf7dccffd9429157abe4643e29db8d654f5022abdc1f723a55e75aba3a10f83f4220f453aa6cacd6d019002f576c91964b8ff7ec1d474983d0a9cf6591c9502eb2f7cbafd754bf13b0f48e8687c00d7a4faa339160f27a5d8193596e44b99393ce9aac93f302fec64e0f7fdcbb7cc319da71fdfd294c929a64fc7b4e248d8e601af93fc511db891a43d0fb6ca8a4eb9f7224de8f98551f294bd9e464e734ea468326c44bf82831ea0810b27b0b8268fbeb974b3599744652f2a607928
+TAG: cf211e739999c0a884a201d24e1defae
+
+# DIGEST: de6f2d0a9b2e678bdde49c463719942a
+KEY: c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c2
+AD: 7f4372480974454879
+CT: 48e2287435bfbe67587ab7d4a101e217a565040663659fc0d73a952dd6fd9c29ec29263960d84c1c0295c4ee2149eff2ec60a17871741b0419fb612288d6e6db6bb5abe321006878b8802ae62e19c5f0abfd81582539aa06e14af05f9015e60cc906c2716665400b87f6995c77ad1f4394b16e4e5f4ecf1e7a69928c18d786c94d6169ad6846ff8de1fd0bff2332bebc0b23de70bdd2b0e4b305f4dc3a85b34571ae351d7bbf394a2e51196c3073515d57ad14341653f1cbe54c50862586d8e0e1824f9bd9f38a5d51dd1ac7470d06b4283739906d4aa431870ea38e003f7a0d9ede50064694d761b4ac908179f3b244958ac05f1981b5cda5c7f67f18bc87f3bd09e1eb5bdcd9f74c4ad8d4b2b166f6039e40c144562b6d90298ab797af1220f5aa48c2baea819b30c2cae54311b2c8b44cd163c034023411af6133ef2cd14d5448b08ee6cdf60661a19d3114aa4fab03df07d0ee30dabf36940d6ed2171705e0f7d2064a01ef56e69d6a135f0c13e94c9c57391b5e862e687aabb82ebb2551160fb90aa142edbff48938e288bcf9f32e47dec4e89d6c1aeeefdd4737dbab412ae3407aa47c76847021824739c385723068e68c443c8a8b51d37f1085b3f599d1e7aa6b7070db8d2e907cbccf2326c377365347f2ea010552bcf7
+TAG: 13a03ce033c494c9ba60a66aa3c07ed8
+
+# DIGEST: db6eddb69a41cd0d4ca9679040a199c4
+KEY: 98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e93
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f43724809
+AD: 74454879c41de9ac9f
+CT: fcdb2d0070295ace472381de9ad1fedad4c21f6f9bd6549111b080a0ee78901e977b7d4d4c5153359e6a3201a2fa8f9ecfec1abe4a7826f6260cd107d7b4d74f5904472881e25ed8faa85d8db5d36e83c59387c2efe711a7f247747b5fbfe6c9c779f63b632b78cf6a4a55f19e62dce27676d3aadde0536deced39dc4cc3b360eab3851d99bbeed9b28b88e39484a27c7fbd37d6523ee0e50903ca89beb8fbcc6f73368ed4790696bfeeae81ab5a3a5294390c6bfd1d576f3896ad923db0fafc50fe5b23a6324a0a1881d2581381ff8aaadcda315a9aced39fe9c4782936b33553a897c3cd599b26903e114ac8cd8334c2e98542864b94e8d1711bb505797498770e8be9ef4ca0d7a94e53d62825459dedb5abe4acaa9a44192076daaf9b9773f99f7502c8ed38f0e675f41c685b85db681fc5994a206fe8454be3e3590785b07b9ad074cc164e9675fdfdc5c57d825ca2d9b2fc1c9f7e4af8b2716d21b8666c198c6175482d44946b83507c5ee5f41a0b438c55c185f7b0ce85e2ea01ed0f20cd4000dbe9755b4e59b36624751141c86b44e196f9522e7c0f0ba892787ce5735ae82e5c6d151fb8c431b5b5a4b1aab959cc8c55b21ad60dfbc4936156ff3ca97995ef221f987c240e7e6bc62201cfbb55c7e70693e854002ac991a3928522b6
+TAG: 552d84f30344bbc5017b510637fb2f18
+
+# DIGEST: e4e06593a0603f3860c86d1fbe2aa43a
+KEY: 79a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a694
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c4
+AD: 1de9ac9f98233b5a73
+CT: 8006a4fdcd449f2b7da0ac9bacd94ad887e5a10542d36a7886c4bd81fad228ac66f95a0a66c2415003b7d2fdcd08c2c2f201358b31266b046ecb7d1d253963d0e790270fdd89e57212268eee2626cd33cfda90776b86992ef182151aa130f3c437602d1fb908c396e31a7acebc479f2d4b45c318e1373a7b8f65a759d6bc3d7781e73eb430eba1f3e5598273a3ffb805314f176dee7352163fb172d0eff516316d345e6dc4a7d0be7d035b9feec2a419b3fc90dff8c801e9784a270b86f863759e5f06e4a8d5934474d10a0d16224a374a6555882cb0834ab84c1e1f1853b3514afa2e6ffb4add6d0a32660f6e305c921ddc2aad880462ade745f30a87b0ccfe5c15197a833cc517396875b1a3e8ecaa7cd745b1c53d3b2be00258adca82c158b32714175449a9b6aea7c6f9136348a738834e7788a2acd94b21bafc903bef5f71efe0f116002e377c92a8800880dafa613d7ca3e7479ea5cc1f3e76b87d9567ce81cb48c41bd4874c3cbd0394345a9a993a9056aedec499cde39a31e6270dcbbbdeb325cd2179f471b29ac4054a37a0e0c51e3ad25f91fe1718eb1b2b9f1d19763d08a2be6114e6ea50e75887a6c2d18a8ccfa5de41a6da15c921afe368c39dd6bc411128cf9aeff7d48125126f2d8d12864ca260f655fd5953be5c3de63b2def94a177f3
+TAG: b69f65870400bb2326b9dd8749dec331
+
+# DIGEST: a7a194379c1d265d2b77990f70c46ac7
+KEY: 0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d72227
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98
+AD: 233b5a7379a561792c
+CT: 8f46a3c72904cdf63c692fa0e2ac3b0282251606b720ac79232365b3a817ab00b8efab53e93d712fb1c4f7f60bd023669d50d4008ab8aa42291d972f5b5d39a4fdf859d12efc9d0c4ec3550f4743794b12c2c3dfe9ce3a1aa1e5960b4212b26d572aea1cf458f6ac193e34d6508f655971ad32c5d249d56d48573ce52c0e066c245e71ce0a6bd84b2fed90c84f8253baff77cb3cac8a2c785c4271d4b080a342af297bb3ecd54c03f45564c6d84af9b4b315a99fc75814b198942eaa4890ee10e67efdf2aa1e9608d5553bef569a085a767dea732324edc485c5e3c9f412902116695d7b74262d93e1469f5721e1f5ff9113fe7653103ec6d16891e0841616641aef5bc1e3d2fed2cf74179fcf488a9833c1e886bbf224fc6bf059707ae1030f51bdfce71843cdbbe0b53c773ac12db44af5d5acc62508db1bb4f6753c018c32004178dd418fc6ef0d5255deb4b4999dd94b59cd11c9843da7f76cbbfcd4b9c7b99283305432bc3bf9473032efe923bc265ab130ba3733872ddbf402d8e295a8ee09ef689dc41f46df40d941227f1614a6d2895b2e7e01052516ff67d9ea17bf864a08f9df3fd035da8046599b2819b40d5b290584bbbfe138bdfd52c043cee630b7cfb4fbdda4a9b38b54b76cee95c6c9029a0466216894b4d8627104a22b6d95bcdd96e9bd904634b6
+TAG: 828e852f1d956f6e53daa6a78b016932
+
+# DIGEST: 024206042fa9f1c70cb75952ed076e53
+KEY: 8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a82526
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379
+AD: a561792c0f3116430e
+CT: bd7f7811be613d6c6dc47be7c208c381b084443b78e124338c514532a96e329519d6553d51bae587cafd4f3b1acae6d20a34172b46fc2cffad3b979f16b6e4c1ecfee56b085eba9eb4a33ed2a9a02515e8d3700346a0d0c5f4dc4a3a1a3784d58fdd207726aab66126b23c725562e4ae44d3677c8577ba2a83f48faa28151929f7c33ef22ee42e4cfa9a27abd3fe8a27d8376f68233744c4c04aad2169976b9eed261ec82ed131033b4268e498a4a35bdcb757e0ec92715397d1804c7789f3870a84de4d3a9a92875f5624bd6cd7ba55e24dcb01044b5409ceac99f254697fac04c1a1bdd1682119653a0bd693f2bc00372d044da72308dcff6ac360bad8c048a6eb5b52515598970b2e48ed25105b751ab6fc084a239a561513f3cb5e56d75301160b56ae1da7ede989f6a08d30b77f5516764f8b9f7128d55d7726095fbb441d3da8aafa0842e283762d0f5ebbc0d6aee45e9df7fd41b63431adb16f6c5325e376c26e536f848c2a01251111e022e5adfc88d1ad977c67e9abac0d3749cfcf1d0e6b61c7be0432c5ce56187c48c84c8b3ddb71bf373e6ce818b579e13eae2987cf407cbc844c4ac176d3bde3851446908eb61969154f8d058e645dfc05ce4cc6722062e5ec1a790952f504fde390a438c8aa19eb25566ac9313f44aa2de4e438926583ef9592e55abd39149e226a
+TAG: d711bed86f6fd7adce31ae3879c36093
+
diff --git a/src/crypto/cipher/test/rc4_md5_tls_tests.txt b/src/crypto/cipher/test/rc4_md5_tls_tests.txt
new file mode 100644
index 0000000..26a2824
--- /dev/null
+++ b/src/crypto/cipher/test/rc4_md5_tls_tests.txt
@@ -0,0 +1,808 @@
+# Generated by
+# go run make_legacy_aead_tests.go -cipher rc4 -mac md5
+#
+# Note: aead_test's input format splits the ciphertext and tag positions of the sealed
+# input. But these legacy AEADs are MAC-then-encrypt and may include padding, so this
+# split isn't meaningful. The unencrypted MAC is included in the 'DIGEST' tag above
+# each test case.
+
+# DIGEST: c881255084e0f1a659712ab2e82d5b37
+KEY: 7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7
+NONCE:
+IN:
+AD: 936a91d0b5d2c0267218cb
+CT:
+TAG: 117ed9d774a7e0a103b3b44b92c5fcbb
+
+# DIGEST: e1bc6efc59bcc11ba263459176decf67
+KEY: 86d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f418
+NONCE:
+IN: 936a91d0b5
+AD: d2c0267218cb7090c61713
+CT: 0d937a13df
+TAG: 5db90b62cec3d5595fba8daa1031969e
+
+# DIGEST: 923c031c891fd8fbcad833524727cfe8
+KEY: 97b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7
+NONCE:
+IN: 936a91d0b5d2c0267218
+AD: cb7090c6171386d641b877
+CT: 06f8afaa7e40a1b8b939
+TAG: 689671bec189ad4d4d8f953e21aad538
+
+# DIGEST: 1578901a05412789af66de2fb376476b
+KEY: 56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f7
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c617
+AD: 1386d641b87797b684e0fb
+CT: b52360ca180a83cb0a431967b760df
+TAG: 5d0ccb30a6c3fe4f576e8787c6009912
+
+# DIGEST: 97520ecf77d226d7993e3e063f0d870e
+KEY: d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b8
+AD: 7797b684e0fb56f97c3961
+CT: 942a728b2c1d93ba16f09b4feddcbb22852605e0
+TAG: 0d7a7542e69787501b6cf9a4befad516
+
+# DIGEST: 31204840e4d9d7fd65f77c44393c0133
+KEY: a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0
+AD: fb56f97c3961d8afa22993
+CT: aa054be3aa6ef1f88a1b5acffccdfd71a37c8272feeb8d6e30
+TAG: 04d7407aa53d3a29be5d3d0de321331a
+
+# DIGEST: 91344b9a4ee429eea6177a09060c7553
+KEY: 89c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c39
+AD: 61d8afa22993a340b9b3c5
+CT: 36ed08ac78f36243b070eb6bc795990509bdb894cd32b0f23bac425c1ac6
+TAG: 7fb1ca79203d5376424cd888017d1d49
+
+# DIGEST: 1c49c045e7a9aaf5b7189a8eaa5d204c
+KEY: f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa229
+AD: 93a340b9b3c589c7481df3
+CT: 8a30756248324405b50c158821ff2b8c0507c0892c5f7f7bce7cc22ea88654b3595615
+TAG: 41349883fec502362155d75e5990e46d
+
+# DIGEST: a973b16287ea82511d9ccd1fbf5facad
+KEY: d8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df6
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3
+AD: c589c7481df3f4183aa23f
+CT: 550a94ccedaea25649df6d1ed3be681cddab569d49ee8607684c5ae99edb671711910d6cdb28420f
+TAG: a535f655fab88529ede7b07433853b63
+
+# DIGEST: 94a0f3b460e5fb5ff96907d8f42be0f0
+KEY: 03f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481d
+AD: f3f4183aa23fd8d7efd885
+CT: 00802d26b7cea1aa8bb7714ccea2d4fd0d9f5c792128eb80a358821113c455b364966b616ffc901ddaefb14ee9
+TAG: 04721a25d6f8bfe7107595d883ef64bb
+
+# DIGEST: 2f3c28d24f433ded58cea125f64c427c
+KEY: c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa2
+AD: 3fd8d7efd88503f78b8ed1
+CT: ca6a68b922f07e746d14403fcd4dadce0b24cfd9515ab41a623b57d0820d78998b446dc31d97ca1b47f2c2616394d245998e
+TAG: 4d87d13ad88796e1d566e2371b6e3ee2
+
+# DIGEST: 0984364e7d640e8f8cec231240851d14
+KEY: 773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd8
+AD: 8503f78b8ed1c8e9ba2fd6
+CT: 671bddabb2cd1dc74a075fc76e2ffd49472d575e80850cf497fadcfba5694d76121eee0a849b1ec2f101cc4056cb448efdd85eb36df353
+TAG: 465c0c7667586c0925489ba09cc7fb7b
+
+# DIGEST: e36590350b24e2d10cf69e9c56a51497
+KEY: 2a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8e
+AD: d1c8e9ba2fd6773e0d0c30
+CT: 42bc538d9a88cc277b0835afefa82d170d161fcd04212125c8d6d8d15f8c69e08669f9b3b29f526df59ed023faa32f0cadc9bfb2e5a78be318385c99
+TAG: cdbaaeeb162cda49bcd0a43fb16738b5
+
+# DIGEST: 0812b6041cd64a720b59143b1c796475
+KEY: 446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2f
+AD: d6773e0d0c302a5f47e037
+CT: 2a4bd55394612fc929ce1e5096ff495a73ababbb3e1f4f6e61293fb8d1b1b1350b2bcfd99bb7a34a340faee87fc79834c099c2c765dc6548c0d55ec85483e4a21f
+TAG: 1caf411949af0d5f58d63e2b0b9eefeb
+
+# DIGEST: 45105e6cfe50e6f19f4d69028a13c501
+KEY: 7df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997d
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c
+AD: 302a5f47e037446f5891d7
+CT: 4dcb418b40c6a1e4117419907646b2901aa1168c17666d954d2bf9b6915dc16c9fde7ea9372dc3169a66a44aa8d01672956a82043e74253b1f42fe9123a2f4cc7776c5d4f38f
+TAG: f8ced6476bfc8e0cadf0f4085612b616
+
+# DIGEST: 39a4171290f03c5d9c3af26d710cbd4f
+KEY: 933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e0
+AD: 37446f5891d77df660ed82
+CT: 06b513c1123d12c19911f3a6e41ce4a1ddfd58b017b6bbe2f1cbc5898e272cf39c0d19900cec6bd14475e0a27aaddea6ce1da3a34333f0e07ac134c9a6001da5474936a35330a862b60440
+TAG: b7d83d712aef8486ebc39d07b03001c4
+
+# DIGEST: 39cdf1512b10e8283c255f78254af3fe
+KEY: c55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891
+AD: d77df660ed82933f62be8d
+CT: 662533ab59e17ea202bf74a7f465b6a3f7c3b89c21f91916e3d0543066d676ef31b97184eede519d6ac5300046b8d3a89e47928aa3b348cd6097ea2bf6e7c87ade499b084f908eb822ed06f574f19673
+TAG: ce07ac0ba6808cfd68f2a5c7f7485b2f
+
+# DIGEST: 6a5dfcb98da598e243b85c0146c3d9f1
+KEY: aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be1
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed
+AD: 82933f62be8dc55b436965
+CT: 958bde313ef29f25b0a771a907be16993fd00f6f7161377e9296a85d4f1675d6959afd14cbbcf20a4ba0ddff2a8a2259cbb14bd0f5ceb2079b81ead41574d86eb0bc82d2cf4eae8e3238c7451682b17c4a4577fe15
+TAG: 207c12bfd69288206bee7aa70d022e87
+
+# DIGEST: 4d08a93e37bc6970c32f90107dccdb58
+KEY: dd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be
+AD: 8dc55b436965aabe477e0c
+CT: d844cdb9d93c02399bb61ffb280a9146b79b9faa03c7acfe7abd7ba99496e40bc2f34b8547a549ba264ee9767d67c9c94809ed9354b53d26438515ce039082a097310cebd832b30072d98e29beba3cff02bf43494017b98ff216
+TAG: a627fb233fc8cb3c0d0a3d46257dbb41
+
+# DIGEST: 070ed30ad273236ef1199928261c2db1
+KEY: 1eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b4369
+AD: 65aabe477e0cdd46be9937
+CT: 86cf00c8dc9af8d231ca9186aab46f96b6ae0fe311302546b66411baf9a688da106a5d3d332360252174d694461cfc3ee771117fd825c63e8c791d0b3988340f3d87f47219ec0c56fe1cfee6aae4cc938c8658963dbea6ed2138ea050b3ddc
+TAG: 66d99a289d5f809aecf5ca2990d39fd1
+
+# DIGEST: fe0e658cd29c28d6156a83076c559093
+KEY: 997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d4120
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e
+AD: 0cdd46be99371eb8da7dac
+CT: c4d7b8599da07fb144dac7bbea62f8b4a7668be305604ed8eb17617ab1f88fc61d8b2d9b0024fb0f7e21cdb09e65a266da7cc7c3d4e56f7c8ebeed3ba962bbf24289cfb17411ebad274ccf2891114995c02d3c6b47f993a9569dedf26346e9192180edbb
+TAG: d6bc2491a7e8e50a7a1bd991e83c5044
+
+# DIGEST: 79afdb81989e28e11f59a5ee381674c2
+KEY: b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+AD: 371eb8da7dac997deafd64
+CT: a480e47f24600c16f181fb217581eebfebc38c5be494e707407b3cb4c88424726a43225f2f8c98c54c886753c851d42d64d7f9c68c28d2ae34bd853603944e98f944f353352e9084897d8e64867cd54790dafa93db2e108d9301388e4c24d929efdce020bf0782f2f9
+TAG: 71d359da0e121aaffe0621017a931db0
+
+# DIGEST: 9c6487750d3b409d80625a11b8be3bcc
+KEY: f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad40
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7d
+AD: ac997deafd64b1fc65de39
+CT: 11fb2fd41f0ab4ddde1cd9b9b24821483c5ce33922fb883acf240f1f964ebef5364193763c1daafdc495bfa11445a3f32ba0c5fd409ea23ed99b02db460ce37c61a5c9a9e3c8165eba3f0183b1645d65816ca1da55f0bccb7ab9333a59650119be40b0e5245c3a751f2f82a07d9e
+TAG: 59ca22b8a22a2c5c8c46f262b863bf98
+
+# DIGEST: e939eed2d601b8398f93bc64bd346fe6
+KEY: 1be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae0211641
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd
+AD: 64b1fc65de39f4f03541a1
+CT: 89eb6968532a4a4a9aaaadc6532e2894f233b414bb7178f42c0276824f04a045822324892fe345d3c97b83b281107074906950d8a085b7adcad611417568da0ca7a759c868a6d76c0d77df2005aa3b8ee239d411744df96d9053fa97c847b198c594ba84ed94553a8b640a4094cd05c30dc714
+TAG: 89e1cc53dc3666fa17b9f90f3491be93
+
+# DIGEST: a3c81ede6b6a0ca240d924abc57fdb48
+KEY: 33c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef45
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de
+AD: 39f4f03541a11be112a729
+CT: 4949bc8e8e50849e4e475b91510d2ae45684c4c9f6a500de6cf8c0ebf0750e03ea371bc942f3d3ca28073701f6b0fe6df6654c4083a9b885580a6b9c2074994ab2bee5f9f8c0e0d2e26e84d2cdfee51396706aa8c70c7fe5e1859a4a99a0fc113f67a0203fb96b55ab19af91d89f325e1e4b3d2fd42162dd
+TAG: 50f1dac70c1f6ceff709da6a9fcdf1b1
+
+# DIGEST: 3851887695c9f64a3b97ee8c33005485
+KEY: fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dc
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541
+AD: a11be112a72933c7b54ed4
+CT: e7240af13d68162ff7fc0c25fc0f1cf785ade49bd39f49c1c222e7ba44b3a4e379a92caff00daa0e0d2d668e9aed5a80951fe4207089dda7188ac052176e790f2a7df0853558df8221f346f53a8f06227d70387fc5b6e42815e9b2de851c5013eed5d6e031cdbe73d43abad20fd573cd108d8494a8b17806aa19b56f7d
+TAG: 8211d9fd9f47675218f42fa69e0d8dc0
+
+# DIGEST: b623cc1e5e2115b94b7f47dabcc31735
+KEY: 41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a7
+AD: 2933c7b54ed4fad0be905d
+CT: e2b6a06df1fc7178e88e01aa009dab626c7a8e46778405ce2790681d26ab8f8fd69d2894639e6d4a7fd3ee2b2149ab4e5a254059f830c8b4d32a69453babe706924e706a8b12ac3d56317fde62b60d3694846f50e09737503c34c960df10d43a0d624f2ef0ea3e7423d2ec1e7c5974434093f53943468dcdaa29a7cd6e8c706b1ad5
+TAG: 6ad8e00edc98ac0d69e6e16aef1e6783
+
+# DIGEST: 4a59cec9f8626ae914c5a94a27f5de3d
+KEY: 998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb9
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54e
+AD: d4fad0be905d41203f5dce
+CT: 3dd231facfc7c84e8c95bd2a937cb2fbcebc4978a3de06c5b00218301b01d5b398499bb7b48ebfddf76517539adfe5e84e278994db2ce3d86ea0818d8c50e19f2a2990e8a2f4059036286ff72772d15fe762e79e0621175561483beb29644a403b3df3c14b883e454f10debc6655c69287482a40377563ad0765fa9e4da061bd365a7eea29cfa5
+TAG: b1d00f1e703d0088bbe07d23d86b2c3d
+
+# DIGEST: ec5c15d3292d8c1df0784c36bce45163
+KEY: ad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be90
+AD: 5d41203f5dce998f8fb2ea
+CT: edcd1007678e8aabdb6faa3bd8308488f765aa3b304931dcbc44d3ac67cb88854ad72206c0c98e57fc7d10d5c6f7858442978492d000a31f145fb26ce2d4b9d55f2663047e618b6d0cf0657e8ff3b4859d6b0eda600def393f5d61ade0658ed0c7060ee01a1b895a90cb66c13896ea835cb2a64d1bc4b0a580b4c5d153b6cfd78a005cd8e0d440efd1085dc2
+TAG: 79ac4fb117472ca2503d56a86706e730
+
+# DIGEST: 349ed7114f2b4112ef858eddeac2db91
+KEY: 16417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780a
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5d
+AD: ce998f8fb2eaad409ae021
+CT: ccef052add7ceca004b35aca8771cd96e94672e53bd0440cf0d28461aed73707e77983a3fd06404cfe4245c2e50701a81ba739bee051640a41d4365b8f85bc3c2acad087023a26affb19e320bccd3cfbe699925c2469d30b5b9f022fe24530baa2f60134291a25f3e49804dba23cfdf9143457cd4e92013fb052cfc3bb3c6539fec14f160c7d71559ba6427f86a28df509
+TAG: e547d7e814bcc9dcfc9bdd3163c6b6b8
+
+# DIGEST: c58bf920dfa2158876cc83afaaa6932f
+KEY: ef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2
+AD: eaad409ae02116417dae0c
+CT: 14222b0b8172d5f0cc1a77f86f645cf576ef788208d5ed00723504ae5390556821c2ec474b4a693ec9001dd86fa2c26b4a332a4dc76da9c5ade0a4178b8567e4e464cd42a3c2ccaba4422a98773099843a4a47a19d929a4ae96d624fc090027cddb90f150796a4587f2b741f0b86c74d6417c144679996677e8579d6fb015d4067ef66d8ff09c9144a35af79a08da8cf08909aa68897
+TAG: 0daeffcb4b3a84137cf7b975d26bc024
+
+# DIGEST: 0248862f0735e29caa6cd6da11560ae8
+KEY: 16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9e
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae0
+AD: 2116417dae0cef457b9e5e
+CT: 26e00daa0e6e9086cca053c90e176b3a4374771b657a7a56aa3c40a810bb8722a2b0ea45fccc78c13428e8ef6f915bf4c10bc92ea4cb2485c98819d00588bccd503bad4ca147ea7930bcf8cfa852371efb46184edec6f651a8701df8c98ec785d6bb9eaa71b66f4589a1fd5d0a85194b18796fe0ceca856b0225f735aa9713308c31424fb9f5a2447aaeddbe7441cce17b1df8d98958b7e2810a3b
+TAG: df15278d770f4d1a4c5e48b6c195b476
+
+# DIGEST: 6c619bd671699123ca99baa4916261a6
+KEY: 5607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae
+AD: 0cef457b9e5e16dcc5b6f2
+CT: e8441767ac75ff93e0c0380b37edda310f98164085ef1ca02c8b901d03bf3ee439f6974a4a0e8dbf6fc48e262b3092fe48aa80f0984976b1151d53d8a900d72858853db6dd85ab2f87b0aab7f479e571f6688a1e2ea489203f29b9852cb64832761cb834a7c7b2e728faaf96282689b8f1431acbbf79e280141aaeb00c5ed5448cc9ce6a4dba7a6719a18236b5f357c7a03e55b28371ae830fc45a291d3f5ffd
+TAG: 97cd2547d69142a2b0bc0c5ba03bc202
+
+# DIGEST: 38adb3334cddc37d1907abfdf00a7ea3
+KEY: 3fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da0
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e
+AD: 5e16dcc5b6f25607f00d03
+CT: 1488ffd99f7eb677fbe3c88076473b76790968b7fff3ffa7d62caa8c3d91bd7577ffa00bfb4b3e5227bcd56f5d63fff133aaa9c4b16a0122f9a6ad322811b5acd251e66b8c0279921a25ed944e2d2767f4f5e5a42cda1c4985e655d57dbbdbfd17eb275cafdb8696d0c9db89f5167e866aea1b5c7aa70a1a9703d8098ce246c841f36165dfd54f0b910d1d60fedce500e75367d95bb9039e2047355c21118abbf84fcef924
+TAG: 09ee3924170ed1f7c3509bb0f1ba078c
+
+# DIGEST: c48077c3bb077f089100c8f40cf071e4
+KEY: 4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6
+AD: f25607f00d033fb95fb09e
+CT: 6a6bfc3a6b9db5d0f174b9e57549d8d1769899ab1f6536fe3c603af64de4f4d747f87550a96a508855e5df3253d0000f22e321bc55efa7af25dfcef9de702c192e47cf8f3bbade2217adb593a4f3dba66f3281eaa77c2b8b6e2ab43740f19f14512963f9ec31130e78326bdd5dbeab3af04e255d22b774b82c864f7c0a4e4e0ace0384419071710473ae4c7b9d071f7e9168a0a3e6ad51730ca679fbff2d652e9795aebd71b6ebd32ce0
+TAG: 435d1c6df44fb99d57a25671d4d09b11
+
+# DIGEST: 9fbe01afa60a2107ed82643fead3d8d0
+KEY: 780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d
+AD: 033fb95fb09e4d00d6172e
+CT: 3a5706fdc8ed4805ab824161ccd51b59319350ca7c2c00b2cefc574de2a5c3f7be5762d4d837af0ee9efb9fa1c6227a1dd232900032d7f2a09658912df403e4546ff45f20e76e0c774e3aae6c3292cbce65529d451a7069f036a1b500331437b4399445056392797807ffd89867222536f8f0949542edc1219944faf78af3f068a0c4791096f33d1e66e4f067520a21fb77359b194b7a3dc894c9b5174737f394788bc4216c134aac6941467185a05
+TAG: c35c3642ad41abdcfb73a51280095f75
+
+# DIGEST: ef32a4f8c3e5520e52f3c802f8ad3701
+KEY: 433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacef
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb0
+AD: 9e4d00d6172e780ab8b700
+CT: f9d5ded5389ce96eae5adaeca4c35caccc187a1cd662bb454e82656f600f44f82155a69288ea6925d39ec26f065127736c952dda8e9c13fde73a1c10465b1780a16466cf277ff8862f7216751da2cc0effd853ba201e619ce83fe64d08b63a73f4fb040b7f52990b0133ef02f9db4bcb7f05e31e22dbacf7a7baee9b5400fec5ba9355cdcd876ddbe9c2599bd647a0f528300bd78834e7d3460dc1067fab7e04e1ab903ac78ba36dfd480c4f73aff1b6d2b8ceee
+TAG: fd54b7e5091b277efe5106e735927a7e
+
+# DIGEST: ead895f7821c38ea7b9f7f4d312447ed
+KEY: 1c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d617
+AD: 2e780ab8b700433a957a74
+CT: c0b8a6bf492f1f2acd22131c003cd86dedbb1be12bf9603fc03adb3ebbd23ff0145afb864a4ad95ed0d3c34a30449eeb1c877abc516de0a9f70094b07ed8978c34686959b50b29918bf593269e960ef42b9d6e4dcae05773439e6cec210d2f9152fb0ee52dfed56e660d7e87c8d47ef673378197777c2d79ece9949ae89896d659368231ab310c2092dbfc1dcbe183380471a01c13c07766dcca93f36e40aac6bd0cfa8a43636f32946deade797afef3b5c2063dc5da8fa2c1
+TAG: 66d5575db7d2e8d10e74138c77e7c1f4
+
+# DIGEST: 292bb2ae5f49dbc20efa5fb626870933
+KEY: 021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed51
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b7
+AD: 00433a957a741c9eb80f2b
+CT: ca0322ec1fb06356879ac0b90cab48d3ceb9a7d97b361db8fd001c69ed9845bbee656542cf3c5d1491c555ee3f05322dbe62e5a3490131d19289150245db71480c50038bccae48a3e6a220cdb4de508c185ae845f6fd1a654554ec49f0b4c70c32a1e0f600920f1496b71b0d57d26ca10b01d033351d79e53117d9208c3c9078ee7880b006f8c4595739ab1abffc45391176bf2b21696a56d20ab4ad23570488563c7a030db690f1f0fa2838663a4a4aa249c2a841e2c867088be1996799
+TAG: 6aa00271869c23ed636b2a91b4692e42
+
+# DIGEST: 6e3475400d823789c3d6a07156fe3a72
+KEY: 9da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a
+AD: 741c9eb80f2b021b144476
+CT: 13f77fa81d702b8e69b2e7bda40c425c962f3d3336ebc730685bfd11676628ecff52b339cdf074277b8def6d212076c9dc4f0ca08845c984270fa51dfd64420690461bb334456eacdbff3c7dbf564ab6479fbec6315800f67f4b50afc9924c0f662c354ea75a0ec1ccaf5d75778974a739dfd94d4ecc5bdd5390cfc2fb5dab18edf2cc7873bb046655f2605e2cd0a0a51b1c3a65aba43c7ea94d147100715c2611bfad854e86d084b79c0e4dd7f75ff9db0c4010615ff615cc9643eed2af89a3a45c8f
+TAG: a521939d20fcbddd1e8dd0d01009fe2d
+
+# DIGEST: 060d2f03ce54ba0af18f2371fbcb252b
+KEY: 0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc0
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f
+AD: 2b021b1444769da00fcfab
+CT: d303d8a5b165a4b316a6da94e8deb5b9cc8226b0695301423ab5ec868e1cd91af247550591fee72a0b07c2a8a34a1a5108d82b088aee2da8a22d3b4122178546a221f50a88f60eb28c070d0b8a355cbd7b7538a64ace31d4cd5a202460f5550ea3cfdf8ee6e58d09830da378cf9fc03c884ec9a72f969e4cd616a9519e76351bc465cbe40ab4c36b9b9857d1e849c6c4fb25c54e466276164f98d8ee27c9bae8966f7449adc8b34fde978ed3431f604597d96efe976b804c93ee06a618909638239c2637e78097e5
+TAG: 046fc6699e7e1baec230a254137da537
+
+# DIGEST: 9445f97d8d4e9f1299f03f9b495b46a9
+KEY: 060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f419
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444
+AD: 769da00fcfab0f5f93b511
+CT: d690ca4467e757a6efe9dd152fdd17db2d14f40466278ac5c6297e3b6f846050ecdbc56a2dec572de24db1f14c0a189e586d36d89173313859adbad6af6a049d5a6ad0b744a167e065767f6e20168b2d71c89ebaae08bd959ab31af1d5cc69cc40f330a0e8e41452de54a48532cd97120a0f10103ae036d10accaa4793a6ce2507b88a97e194c2c1b47850de60c0cbf5b56a04fe9f5fcbc2607770af9ba3b35c983247502993d7a1dab275e75d00e19fb420728f7de040bf9cb6a1dc8a9816ade7a98c4e5f7337b48639c9fb9d
+TAG: 13375da440b06089667d093a06528a5b
+
+# DIGEST: 71272ad29dc9b9b5eebff317e216a951
+KEY: acefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcf
+AD: ab0f5f93b511060c9c5f3a
+CT: 44f63d519806997b360731071ba43b308a4ae13f99956e807925b04d996aca984aadf8dc4bf7fc43e8d57874587853efff2855b20a5dbb8244dfbabced742c984064ba3e3b71946eab1680d74c3c61d2eaf9d2bb91207d6a7642668eb4e32b40ae3ac268b370b85204c6f0231a249cc4844f51aeb0ee469fde6b4cf9125b4af380fa9dc38f6cfccc6c5cf7172616539f794c9d116b7897973c202dfdb67c73b25e8fc092d1cf1da6ba2e3cb611d6a924b0ef073badf62d3cc11a76f75813d9cc403dde6b6b9f9fa275baa360d45c4aef2a60
+TAG: b07139311dfc7ba40c4e215823b69d0d
+
+# DIGEST: f4953fac03f0f9f2149c7c632c30a75e
+KEY: 4ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b5
+AD: 11060c9c5f3aacefe61b18
+CT: 0875a5163df500749e1d718fe9d5cd8c1a12162a3e71bd48abe3d79b0b1c521f7b41bc4c41ff4e5f70f29ade666be85a9467174e8a92d43b82e747e2c03415a87a7937a414fcfcb2829a5d755a756b3b84993e06e710156a7bf2ffb272c2652d831c1364d8d96b99944c0180ca337a95d3297f044748f6c955645cd5e961968139bb2f218486f3b600e7fe22922984fa25f4c6c604c734552285ef8a32df4ba257026d8d4c994a0b903eb9885b8b6bca0c1354f0dea5323a8b064ddf8edd3e8eda41a4afe47180781c37430dbcee634dcc253e06ad0e92
+TAG: a08d0eef96f0ac624536581d6244d7ce
+
+# DIGEST: 94bf58bf8ddd100bf3c8915ce172cf2b
+KEY: ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f
+AD: 3aacefe61b184ad2463939
+CT: 6b311960e7513f9faeddc8f9ccdc969255595790e5dead365320f84c1219a4af74917f818c69fff6f91e1b1ac612a70cf4a67478a8fa16b8113cae8511e2daa50534cc90d6da2e2220863f1cf2e1ab540c8f898d1a596af09359184a04926364988567e3691e4dcc319e249e2c32cc030a60aa2178cc495ef8f18a31bdb5ddc7dc75c1d070d40fdfb85b61af41b6b65abdfe8ed4c9c883a9f1e42f74839b635a01e92f644af28ed4cfff385a8ffcfc71c458675a558a1375356140c0abb20adf577f7ffa07d322d172ad175365bfcad5a769a0a752763b069277ceef
+TAG: c293157dcc4d380c86f51703f8c918a4
+
+# DIGEST: 5f97b2a1f54987466fc533e0affc380c
+KEY: 3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e71371
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b
+AD: 184ad2463939ed518ce97c
+CT: 4c93fe1917866c88b8db07086e942e0f734e2eb043f140c7894708f08a677e6b2f47499214ae65a1e76d473d2b4295e6e1fdd5795f00a60e17e1d2e733a798726f47dac4ab301b11990a39fd18a0def0916752538eb5df17da9d834a4ed367747d9d97c33270734b39c31ee51cee92f8c4ee14597a4e1ac0ef367931bb5ae4956fa6bd1412aab69b54f0ccea0b8e735ed60bee4f5e4e93a8803cdf9e19c56e340256923704b6b5816865578e5bef1f0531b012af93288ee649146243205771586ac16faec5af4934c2aa7bdbff3a08856b011b56d2febc4b967ca317f181ea218b
+TAG: 5c54c7ac4501e0f90b605a80723b6efa
+
+# DIGEST: 00cdf989b87c8882b1667c29c9c17b31
+KEY: afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad24639
+AD: 39ed518ce97c3fdd293d72
+CT: 235bbcf2e0c2383f6417e7fa668fd0e535d1e4522929a239367e4e5c5dabaf3d2aaad00f7f43f8412e2c7c6404a3fc4df3a0aae8592d2922c4386cc9740ffe849eb919c43fb1dface523fa5ddae3b8d8f6f8685c1601b9450e0c1e10acffce1287ddb342355ef9ec56efbd6f61858ce811da932b1052d15c531b466afe4f4164ccf5bc1f651b8de07620472bd882c8cea78f0fc65872a26291e6954e11a76ac0f410a97cd28c6133894bcfb09325b239fc0e23ad14725da4548f0de3e473c0d4dba7daab98e8114b0fd3d20ba0ae8e9789dbfa0ba956d5d7a173e8f0d0d8bc8bf6106831fa78
+TAG: 03769fd54a3093afb3f67d4a41a67a23
+
+# DIGEST: 3f1a4c94e27706d322a7516b327338b0
+KEY: f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce9
+AD: 7c3fdd293d72afc09ffdd4
+CT: a6b57f220baf8d8df8603dd925250b9ea06e1d01b0d3ae94eaea6e15db770061f63f7aa099c93012414f456bcf1e6ffe02bcd3129a713490071bdbba861cf9a73f9e4f1ad2e7f5836eb9c2703fa7a33589b2f699de73a0026fbe6468205bd8d3fe2dbd6de79672e7f07219351038ce12fc3d7edeb84651f56c1d1fb2a886b10d9c0008399443ad7def6f19754fbd71624d97aebbc3ae88038569d67c9e31597a33c8fb448a1619b0504fd1b06545ef93d7ede5a3819616e7611540355cfca12c98d9cea5b0979240ac24f901fea0500ffbf5fe5b8a9aea88ab88a9a9d2f82327ef88c12016dffeefd61cc5
+TAG: 60c0e6fa8730e6ec53224cd5a45b220e
+
+# DIGEST: e2010b79883f042a87640fd21222c9c1
+KEY: d299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c445
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d
+AD: 72afc09ffdd4f41963249c
+CT: 0fa4a993458f526143c2b22dd78163aa2d0edda724bb8340ce382fba3a810aeae3f79d97bd726f1279f81f0d43842699890dfcd8036d5c90c0ff70cf237abfe56e2d623bd8ed5c1e3e676de728d0f5d997e24c6eb13e90be67074aaa59924f42c6c700448dc9475a2f791349f1383d26687b242764ac0b850c250aeefadd0886a5e638b44db97e4c71a602e0e6e6ce411c79bf7b6ff7c6902a571f18b2f1718856beede0326ce573f0846167f3e3e8f51bc6d613d990c0ef00a8b6357dec0d46d3616ef8160e7964b25eb4c62c6ca75f81526b41f298265937a2a340810011c5b3157fd417daa36ce394d85910cd08a8
+TAG: ce1dbfcf7ffdca361c26d7b4e9d24f3b
+
+# DIGEST: df20c534f7431f87d8e9338f4e3db67a
+KEY: ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a2
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffd
+AD: d4f41963249cd299b92e55
+CT: bf267a0a42c3a885e5164c14b50d7931801ad8a551a1c4c123bb568857dd7212b5d83c20e90ad1c2d3419261f86c11ec5d1b29e90d6bcc421d53f3f11815759c0c8cae5516dffcf82e152cdb98d984600b721b00c4d98ae41b966e7eb21ce3862f24d980745e2a4489b5eeba0b9e05cec076d1016a4b96ba7e1850d6a92fc63feb9e22a0d8e8ab3a58ff23a0146b18dd9100a1a888f8129086c3ab1744f2be38014498368b70e6e32565947353f3df24d2b16b9b89a2d7c25ed861cdedc1247cd1ffb3c285937e2cbca34521b3d550a1747e0bda19e8d7d661458fce4a5ba9c933833c7b784ce8a4fd042d7570493a4521c1791bf8
+TAG: 76c8cca275f2a28c771965574c1b5a77
+
+# DIGEST: f45b6ffab0dfe7902aaecf0ea33bb831
+KEY: c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12fee
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f4196324
+AD: 9cd299b92e55ca24d8c078
+CT: c2ee4814a9011455acae6d09fac7c070f85b93537031dee21a84f7dfca4c0944770832b0bad986c7adfeff01ee87443290a6b1259e4f75123a31f2fb434ce513fbeb16f55935de36614c2bed16130a15e8ab7333658efd2b35230c1993e15da675e158fe814000cb0276298a492944b8b18761a57e70d32e00122dccdfceacdd1105238620fa12efadf5b29aaedc0d63170f86fbf73ded508e538d769270f92ce3f63a0707199709dbc3b341162e94b62373b0ebd3141af017f36865a9d5679a2d43217359db155c343a303a1db0e8c474066023559a5aaee8159d6b21040ecf72a07174ce16792d6dcc59b5ba846e6680cddde32ddfe2348fa1
+TAG: 56dec4941ab6bd602b2b0d00320aeee1
+
+# DIGEST: 193a29b7078ca1e6adf3019c6adfc919
+KEY: 13710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e
+AD: 55ca24d8c078c49f78c7e7
+CT: dd5ea738801b27f7c8af9bfc1749580ec36186f8c84d576355b5118febfa34829c93c08132701fcce8d4d7dcc3f20053baeb732418af132aea0c6b23d8d63e7302b969d909d2b03289278228ce7095192d0263298cdcab83ed49bb89d2bb71f9bd705224411bc28e24140e204b27fe9c00b44018ff42537a94521872ba4fb3b3c0c72304b88c0964aea91c145e68477c8dcb2c8efe8fdfdd7014e0e3c743b884da00deb8ba5cbc6fb49774e386325c8c2ce02b0ca00586c4e0c721b652ec579a14e18230dfca22b38244457580c923a6f02b2427ccc511842a38aae92eda616839157de5fa90a694ccaa3e2c592ef1534f71f66cded862a423511b3ab9aed0
+TAG: e95feb17ef3de46163615e1e27eb83d9
+
+# DIGEST: 354b5f9bc9ec7a622e1615b9276cc9b5
+KEY: b8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e89920
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c0
+AD: 78c49f78c7e713710a025c
+CT: 5f3b4233452e0a54e418a4549ee3f561f2cf89135ff234067a7ba193113f9b059859bcdac782bfc6c22b14344e11d845cb367efc513f3201858f3f350e28f18972bb25f8a1d05f3fb80257e19b5dade29734e747dd674129c9add36b0e5785094e7fab5d0cd5c87c191b03dc44e2583c4279650352bb6734cb25ffbb3e1a366560aa0576f4b6dee50e5f8073c0a5b177583c0a1c04946dda024829cceb8335d754bbd64183e28b67dbf882788e7be8cbfbdf80e29630643ddd1b8f51304e0dd05ce045526cfc3bc71070e0994f55260e947b4fbb2c0046097d41df9ecf603d4eaf731e81acbdbe4ef529006f210653861feb5e4023ef5cdfe648665c9365a9fe0e76ed1d
+TAG: fcd801777cd76bfdfbaa32b87cbed954
+
+# DIGEST: b96789ad37e04beaa93bf5ffa86fab7a
+KEY: 89ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7
+AD: e713710a025cb8b9d71d29
+CT: 39450296b89e1802b61767c6e72bf5bfe70f89d56b9e879cbf5854f4a2d7d263b21d231726aa3cdab3ad5a2e57e4b99b98e04153224c4cc7f47eac87b5414333613e2b91ab7bfccdd7658ad2f8cd9c806241a029a752e811bdf78f760ffeb69046afbefe2655563e60041d57bfa747105e8e37c2dd26eb1454797eaaf6a94fe3f5c10f9126a75f0ff0da8e689892c723bdadadc1e96abd921a9c4ac1ec71b5e24b833a44d69bd3e6fe6f8b74bac2d31faa51f6ec26fbe4eeae855d8afa0a1142a7b94be1155e602350eaa37fffa7ec70e6809ce0aff298a2ed57712e605202693bd65a408252f5ab15b457f2514b13d30bcd5a8965c53eb0b31dbc9469f465c0f7b28baf765e52bad2
+TAG: acc8473f464b94b35c40cb0029b7d225
+
+# DIGEST: 4bac3f2c8e06db31e888e86fdb0e9109
+KEY: c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a02
+AD: 5cb8b9d71d2989ab33e978
+CT: f79d7ec76ee4aef607dc89cef7ca620a6eabaccec78182dcc4e0649bdc917856e2c4747045900d40ea88a6b4a711c46b205d7bf82f2b3b47bd1d7886d14d77b27b1e3cdffd9bb4f1840498fc4a44fe2bbe9a7a07e10af037e07bfde75429e5c6b0a0789ab54c0f36f7be55612b7f144a054b1c63f4352ac61afd274acaa9c0de3be721a3e8f791756f624bae656b9671cac5aedda12e29069c9aebd0215c214f0efc4dfdb70a6b6ce3e55c6e9777399833594f15af9da45f96bbcb51b1bb6770fac0953d8d28db9ccb69db7474b110eb66d3a223c4e00fefc6abcda02cbf782f1fb4e49de6f6904ad2247e2e0ca98d14f9cbee03a818207c617f240eabbd489712c8e81598e6ab4f7cf8e11ac7ad
+TAG: ee072123f03d4bd4c5d2a795ed0bfa1c
+
+# DIGEST: 21c8985b6544843da17ddbc929dc8635
+KEY: 85a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d
+AD: 2989ab33e978c4451e3be5
+CT: a1f0b82e614b48e9161590be5ea456cb1a7f359fcee65baa3c4722db30a6f71695b2655d068961c0e7d85bfe9f7debea517a1e1f6ca29f92c8459ec690c1c8f2d2418f7580af3c1ea9ae4bec66385647fa5b5bd086da66a9922ad5f748684616a561c14cccf6cf84617c310e7efb265fb821ac40bc8f4207bf1659f03572298b4831348b25449e28dabe3c7bc03efbf4aa46a5c89250d1b998510956f2aedb8884af966392cb1d93aea023d437f0eda920f737dd9b0eefb322b796ea518bc5ce1623a8ed6b7583c775f67576a5af84be4af8d407f3bd2c7e1daab23aad10c3cb2d687dd357be60f1a5b10842495a589181ceddd8dfa830fb0e32b4ed0f4c5719cec8d2e448461d04d787bc0991c8d6b540c492
+TAG: 5c88b7fd810b7abbd5778822ab1ec00b
+
+# DIGEST: 84e1ca3e134c38a2c55ca250c5d4e712
+KEY: 2feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e9
+AD: 78c4451e3be585a29a2af1
+CT: e136fc48bbd599988a05651edb20b3a8c6ee5a0a867704fc0556beb424c5cea45ba88d7786d88ee42e1a53fbfdb3c6fd93f5d3f3fd3f63b38020d05c20e734c3b5381d5206d11f0cd1e1d34242889285eeba189f03d3e61a891fdfc86a2c064f074b894379690f37af0f4c0f057b2dbe1ee7a1587c933a9f162cbed45bde8226343ac96556ace1d8291c21a09c4dec032b0475505a6e5c93aa2295d332783cab15bae1172eea1d87a0617c950524f08c7b4d262a6ef90b76d25e82a88c29306c04db034c3d490886eb5f32572a004ee3e2d9cc060da61ccd8e5abd4d66b928a85ef8377550577c68d688fb4ad5a2cf55351e970d1921d237eeb591e63fc5eb91991570e0f9ef0589aadfd3a7d2e8a8155dcadf900daa4470
+TAG: 0502ebe6f59008fb5ee04b01c7a3363f
+
+# DIGEST: 5093568ec95e8396c164aa3030fcae39
+KEY: 63b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c69
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3b
+AD: e585a29a2af12feef71e10
+CT: 459f9d14cd8f13b022eebc4f8c4d285e572614284cd9c1d7d027e5454bcbb02fc3f442359cc92b50d896fbac5190ac447434517be69f8a0e208754aeaf84edcdb3650e6f468603085d9388ac83e2763bd816fa4f854ba6c8aeea93542de8976dde2478ff3645bd8404d9e65f4cb7f85c036f6198c61446d9bc3300387110e503c08a97d469142286a37a9800c5602c41b56e3f6240c5b93b2d73f61a6e922c102afbe4e3935910c5c2b077e2d3a995de6459b2e949adafaabc8abdd48a6d186c60247db4943e2ef9c190d15510c5e8a45f2e49ec9a4f1a215b536adfd76fc269c8130ec63af4d47c9f6cfa03e4b1247b3c4af4da652be0347aa7dc870285b57addc01259d2e8e6ec63a23e578ed421f3b28b71a01470c1641db18b9ab1
+TAG: d399cbef21bf65decca41c3f8119b316
+
+# DIGEST: 246725d6fb787ad7c0173b080b35b378
+KEY: 99200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2a
+AD: f12feef71e1063b0b4e6e8
+CT: a2fd3237069fdbcda3be5f0e85896c727073a84cd9e89ac8334943356ca6d24cf4201987bc79e019531bd3ffdf480324e793d2fdee56a4750e6ad5efd19926f9e27ad42718d07635217c7ce1694e9fc46fe01c9524846115a6c1d388fbfc452b1a39b58cc790be461965e805fe365a4be4daeaff319d4ee29c193a530a3b32ad8088c443fb0a13883f6b701dc23121e2a4eddc039811e672232f23b1e43b5b45142797db8abbba3ec3e8c5ffdbac7ebe7c08d75a101d306475cd4313b5d984acceb37f1cbdfff8eccd1657d8dbde90b3fa81787ab4f1aafee1bc8915144632abe207e40e21dec830c623b3f6eee9dfe9cd2b20c94896631bb13942d91f379ff1e3ae5e25b7d675dfefb03b9381bf38597e0dbc49bafb7e89e49141f8f745bbd9aa14
+TAG: 0e5e9961ae44d700a04fce952e85afcd
+
+# DIGEST: d4de2d03937bcffe13fddfd19515bacf
+KEY: 3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e
+AD: 1063b0b4e6e899200304bd
+CT: a679a86894007d51968a6888cfb5de5f6bc2bb7b08cd4efe96fe3461ca2c25017a41301265afa33576e26afdda11123eccb52a3d6a23a8ad1e801884b904e7ce355a021e67db52646d8101e8aee43c4268fd6bddc4510c5f609006c29108f77e0b4ae86eafefa12297bb755c53f1da2dab8daae08dc835de9af62bcd86f5a5efabd951352bd192a79128286bd3c565d37d7bf6ec661b47f881273c79cf6d842e1d0ce8aa28e1802204a56ef2e96ed2ce222cebc15ebd55a7347d8daf5207c0252fbf996c02b4df8f8aa2df4b61ac99f4e5e8761a2af3aeaf4dcc5d13a3fcce9d879cf26052e2956245693577e3461aa6d1bfc8ef75215e654a54871fbc8820095ca359cb69dc1ac787ba3d970602b99c2b0930d83a2bd9454bbfbd284b247627478f4be0d37415
+TAG: 949d1a29247bcd1db77841efb6f99f95
+
+# DIGEST: e05e927c56f95359635700a1da271149
+KEY: 7d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6
+AD: e899200304bd3508132a02
+CT: d16283ead5f35b89f9858a70377cdcdf6294e940af92cea417ce4e5068dfad75ae6df2ed06c9f8f0cedb6f1157b91f4fa4f642de980ac313c6ddeb67d8ebac67d6bb19cde1e4ca8a61d67154d2fdf09b81547dda42286c95b30106c2ac650c0f34a81ac13ec1b0cd861fa57475b594746047576eec5d761d195dfc3efa6af36d0bb78e7aa9601bc5ecdf7b1649ab28c780d5783addc3fb9f0f431cfb02be8f17dd4d723ceaeb9f7255d50371623bade2281ea7ffe38f54caeaaac690021750011a467ef1149149d3833a3f01d685a44c4a887a971d4cc7603442ddd71d853ac6b0d2f123a84e9cbc1af1584b83fed2dea21129480bb28aca6da05e0ab34b6b9264c541bf19fbff5c8e27058e5dee9740c5b2a37536c3c21e892d169422ccbaf7678155127f73e9568ce8e2ec
+TAG: 4fb29de227ab7186aaa3c85d04f66b8f
+
+# DIGEST: ae1092c2239a594a279f35e189cb7eb6
+KEY: b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf7140
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304
+AD: bd3508132a027d1ff4c047
+CT: 3f680d90bdc1c9f6d2f059a095c1e65a301f9d2797a5f8b9ae00d5e4336ac04563eecefe3b0f11c3686d2aa6210dd26dc5ad293c259f27879b3c50eea7e28d3a1256678927cd3e2547d4071cba797337908c8ca7c63c6939a859f00ea931c17ef0933a86cdd5b314293dab83c704bf7af282b9ea2d3f01d07e4b4826309d4bfc5b38136bc361dcee664d60a696aa6ec5faf85c464093bb68a559538583977bb8b1c25fd1f3bfab680b15858892cd7b9b728c5a531fb9f87da8d5d9914f481e2d7ef41c340498e732abadb41ec3633082ca9af06021ba6b85fb20ae6bf6cdc31dac12c86c2d594fd58047cabe0f2907efc48023c12a56722fdd27bc8922dfb503d83accdd4439c638a845933f8a0957bf1f1c4a5ed40f42019756c2937148624282185dc2543bafc2d15a36c0d7f5aeae21
+TAG: 516bfe38c7198500cef83c6c7f9f7492
+
+# DIGEST: 9ece0c0e545ae7387fdd4fb638cf1c97
+KEY: 4706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bac
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a
+AD: 027d1ff4c047b3ef4f57a7
+CT: 4b19ac559a3197b7dec47def0d9f3b9c3056a4686c1eff225b6fbc86ce98e26d40bdd899794d70c43f96a9ea7f01b5fa41fd23cdb0310d86567e90086f84ba87a14158e974edd46350cdd2e8509f1a7de45402ef3948e779ff8455c411b060d9215a0ee4c2d3a7dfadb68abc228382d3a9902dff2c42a80ceeb29a9e2a116e2532d9d926659aa1be2abedab32b7832af8cbe890b352b60615a1613a30f63634c1a7b0954d5c5293705543d7cde4071f07dda1ec304aa97038012cdfc42e387ab1897b1163bc7dfcc81d1dbedcc4f2d76956414d288738d09a4aad3cd419fdc076db2b43835a6aaf48108aadbbd7b3bb1fac080bace769bea9bb410a08a1ec9bc54f4d905fa12b5e4407ead0ab18d939e7fc89ef3b8ce8a631fc7dec90c1501e5a2867a0f02841255cccfcf036001415b3f2a68bb76cc
+TAG: b7495b69aff721937e53b67e79fe9903
+
+# DIGEST: 36c515cb7b0a278e07c0a7ed582091ee
+KEY: 1c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cd
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c0
+AD: 47b3ef4f57a74706de4b38
+CT: f73d7dfe80a222047884d5a239db14910f3adb64eabd0c0dfcaaae8f36205d62bc9f187f6bd6d3a1264ac874621a1bd1bfdf64cd921cee7e5267ca285b885d89181ee6efb49ab72b5d8bbaebd4355ec1113979e0af50c8232b73bec6c9d7bf07b357a23278934c548353c4fbb10f18da7f2c98798b6e6a33ce111265eb12b43062f2cd32e9907da455bbae284bd50e4f825c5a9443bc568e463bf705896c2f810946248a196173379ed69d2dd725e3ff36c2555fb135fa91bb81eb3ba21f2c283481acf0b42195e8987842cd8a78236772a50c2dbeb20a5cf668c07445eca42f88b1194d65892c9a681a6992df5cea766249b9a81ac476282bc1e91cf79d20a201316073b944f1cdee02b34881af4f0ead3e40aefa82d4ceb43ca0db5fb862e6aa7af4e7c1bc99d637b8fda3db52d959a35b49ada10addfd70f4a5
+TAG: ce97f86f02b0b1afe560706bb2210d3b
+
+# DIGEST: dd3a8764b876462d81cbebf4ad39c062
+KEY: 101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed0
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57
+AD: a74706de4b381c692ef164
+CT: eb33a04c1729ade767e620bcfcdb1a2d0fa2a6b61b9cf904acc7fa71d77fca4e7356d5b3b9807ee6649e50fc806190e400e928c15efc1df7bce97a18329ef9ac8cf95bdce146213a2633a8991afedd50cbfc54e449477b413713b82afe6a6ca48eaf72e2b59bca771c29c6b637787cd39acf67775e83a140da427b6ad424f52d7fa880fc0232ad5c6ce3506f25b130b7d62b524c25162bc876ef639b211eda8100ba1297e9491aa98081551a1c97f8a12a9bd3763c6a5c25b62fabcb9bbf826faab0799a4513fdcab7fe97f66ce42240b24017a848711c21d2989d2ce5ec122e280b4e5f3f0199fe31f0df1e4bf5b142b82a34baddec8103c7ab5a448087c5196e3873c8544b3500c12a090d55c4001f79be432ef727df68cb784cdd5a2aef15708e016e50328c988d483758f418b300b0848272f4e1ba272ff6241fe9cdb237
+TAG: a47c8af974512cfa3b6c6fd236a87cd2
+
+# DIGEST: eba2de7ecd86ff37ff4d61f3e1e3d72f
+KEY: f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3d
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b
+AD: 381c692ef164101b89b476
+CT: 0d2192253fc05f72d4d62247cc195ea9b458c843cdb9a1393599ddef07140a5fa81a2856a95e7a3ae730ef6c5a45723be1d0414a2fcf3e3eba5474ad4777c811a6123ac31f554b7bace41fb459063bb9e6b9bfb2e7e4547adbc2505ac639d88d90d40774773ea3fad2278299bd15fedc8df67a6ac12d9fe41d352668f6a8bb61690f4729cb9ca062dc95efdf50672a9cc223b4511ceefb9a2bad8aed8695aa3b917df075f779367a3e810eb2f3ad2c6acc863e1cfb920e3ebedaa36b369c0842a01cfed8eefa5c0c346d2ee29ac87ec69e19e3a7a04082de9544e2613abb3e8396ab1d45ef968b3b046b0e40f6643558f8442fe99db6772da2e4bbdc7e56ee0d510bb8cf073d2f3b17138aac1bc615d6c3d6ef73973b8f3cde408ff39972dda05cb00715191b2cb3eef6b65b9e65d2895625d917aa93f4f5b036971946bfdc97b0b382c982
+TAG: 4a6226f65e03e00a10af75ef1bf60931
+
+# DIGEST: 80bd1368959e19759220940500549997
+KEY: 520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef1
+AD: 64101b89b476f72b27f06f
+CT: 6abe2dfbde9951d744772997056157f7b2e8e3a6b25f071533dda8d0b27359fc47f342b50a472393ce6e5ae9d2121cfc5ba5d3da6df14732b5de01f8ebdc879c2e771d246d63b73d294ce60e770828948cb079fcd99e60b7746bd4b7e0fb168e53923e75f4d4c34efd8ed885aecb530a179efb52b14894df0a2cead731504d7a38b746b1e4e7d67dd8cbfbb07efcd7dfdd172af5c211939d2cd9216cf43443236348a66dabe1a513900244e35f5d7547ebafcfbda780f14da527b960aa6b60ba966c1ca5001fab69d03bd0c041aa99983261d9096f5e0544374966ae118dc7992d2c31fe010f5a62cc8634ed367f662f68a5def3e63215ac265457821c037c1096e786d15d53f182744ea5257a772cee1874d9d51c496780545a862ab00936665c95f4aed673c617ae73604037dbecc968abdf51ab4bc27d26d902ffc540b256f0ba22a260ba979d42e7
+TAG: e1b4e1c6bbf04bd458426f3876d22097
+
+# DIGEST: a0b9f45ca992ed9b963ad071bf5a663b
+KEY: 71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b4
+AD: 76f72b27f06f520c9267cf
+CT: 194c831a05be6d418493dda7aaa6a9d07372a5963af2a984ee3cd737e59e112c64f4d9718e853ae175ba99ae410c494aa6f42c8ef119651fe43bb7f996e1b49c0172b698d353e8733009647030761506ea07d1f3fad5762f78c17e77a4917b88889f5f0df0e6357a794c88395500eba9a2c0a0bdeeafc7d21e002555c8c8fbdb6938da2c4b7c86dbb670dd00d652ef0c85858133f6705b4176e8402a15fc89b178d52a23250ed20e0846554462bbcbabaf2353245fa790c1f2af272a3942d8c1af05d1a51d8fb8c5fa0382431843290fcc57b2a18c680ddf477b1b1ab33dcde5b7bbb590394c53d385ca7ded3577d6194579a2119230b32508426e410a1d25c226822e0df8b7e0863a17626e9a5635803e6944833a4f7ad2beccf62e867246f9369611b82c73a0ef86b7a8251784c062126dce9fa18349a64e3dd0cf0991ae4f03ff6147ffe0ac2eb165c9793ac02d
+TAG: f3ea0d8e769fd49101a4154059a283e3
+
+# DIGEST: a5930aa76a853a73f5dd763a2572f0a2
+KEY: 9bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b1153
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f0
+AD: 6f520c9267cf71408a4172
+CT: 1c5bc7800a13f2468acad45aaa810fe4da2a81439138ae78e6a5388dca296bc5225b53b94c2281b853f7f43bfe20b3190e98a7249af1031bb82895964bda30be1778468ad6d368f89753f19eac5e0c664c4ceef98d256067252f0c673af00cbfbfde412a363f72cb6e46aac0f18d757d5fa1ecf39501535c533a445eb94aee4445ad7515935b7768472ac850baff6a5e4014e1a8207dcb099b9f2f7b0b49fc9d535eecf088493f0dccccc0ed5048f6cc1344c7f2e0fc753b4fc060192ec4a32c92e883ac3c685fb1bd1b988388543f55f645e6d7771163bd1ac6b56eaee7f98326e39ae81bb85a709ccdcd1aac47d1c00b0a390872b410a9ddf5721fe7020120d557a4e1691eb9a15a1d77a3d79690b9054dd728f0720242b22b6447d4858785b4f90c82205cca3b478186aa4bcfa85bb6cba4938ab4201c67a5e7bf38ac2cee50d7bbd4cb79e3c878e89b980b50e5bdfc10d865
+TAG: e6a8da9c91074fb0324ff09d2b48d81e
+
+# DIGEST: 315afd11af4c2e349f72fa47a311f7a1
+KEY: 72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267
+AD: cf71408a41729bacb5877e
+CT: f7d2481624397f43bb5c981d9a820e2d3fb6bf30736f609fdfbf2740567b6affa3e27afbde7029951d73de2a72ac9f62ed30998aa5ef6bd6c29a8c969e4758b9dcc57b8fe35a0395fc693132a03facd2b331bd0f206d6c589505063fc6af0904420f3c95bdedcfa18a876d69aec2b2fa80deee6f7ad75ebdd32b998a5ea384cd2c34c1b9dafe221bbe1265f1e5c18562daf53622bdbcd392adfa4abb7be550d25e7c3a0d3e018739297ca63f301b511c05295a664a022ff165059a1c3b076f4fe432c848c567d75d939b129d4ff8fa4d556c07c9804ea9d43c1e84ac83943d661db620509b054e9b6d0a93d224f517afe457d5de28fec444e1d7f0cd22325f810eb7e1d4150398a4fb6af454c0cdcf8eb0ad9e69003f61c67c607765cca1605dedbf6269a7a7002e11c34082377c3f9cad2f00c8db5e7b4b5bbc0c63dc9350070388c4a5adbfcdde52a72005315f253c265540cfdb8486130b
+TAG: 6aea228edb0f4372bf903098693b24f8
+
+# DIGEST: d483a58882a065609a9d5450370d7777
+KEY: aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a8
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41
+AD: 729bacb5877e72cdfcfa76
+CT: 3de34ecd09f2aae12e97d600a345a04f319a680d6428d5571c308608ef71355ef9ca2a05c26e053f2b8beb66ba1184ef0d231f9fd6d110632c85d5d1044b60479a2d565eb103753cefefb76492444757dc0edd889eb75802eb596b79b9b52f208949195af45c58070821d38a6895723645b2d3647c99ddcdac610a3c9b6a625ecc4a3ee62671583978a4a6620e6a7b7346593cf5226b242d13a0a41febc01de7cf86c5c2ed73700be6f4e9c088b1c0b3552085bdde8e8046ad3fa0f9e489affe4a7aa598208a5c31772968b5a7303990335bd5d2dccc73825a1e3538e8604adad49b1a56292b8f603b28341969b59d562449d7fb44115975bb935b3773a813be249942c296b6e7af8bfd523df72d584d5c595267dc9dbee88955fee403ea1b3ba4513f2c2459f8999df5ddaf250dba7dec60436a25d654b773bab6f29909d99b8116eb3c84b86334273332c6df2b4b046bc9bef04bcd28f7e70620fc578c
+TAG: ae4d17e81b38d7c428518df347624951
+
+# DIGEST: b1baa9d812ae3a18f6d8d136e37e87cc
+KEY: 7c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c67
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb587
+AD: 7e72cdfcfa76aed06707a0
+CT: 7225717afb77db2d64ea87c29e94dd5fe18c1e025aee5ea854374eb38c4e43eafdd25316ca8b9a1dcde09c7e466a3239e38802d6b8f9eb2705fef5e087ced360c21cfc0d829d7fcc30a1aa39db54709fdab4ea1316c27b089c408ac38cc25f46e12bedcaaf9a41401c960e50ff33c7a4495f8a7302fe162f9dca1e84d1e1072da54b208d809954adea892597cdd2317564ed916a5ef610fd7de114dd1908d85a296b930c1c214750ce1054f7efabf9322ed3bff62da0cf1ab7ab1e298e2bbd114497a9c28fa69eb56cd1da070b1ba0baf8fe2f8c17840b0ba0ca835f41461bd3d1ff24ccab828d95bec0ca78753f4e52de047cf9401e0bc6082fdb5241ed48ed8c128037d83b48eab5a62f744510c204fd9bd1c79c68599414ce4d8a47bfccbd8916994df710b67d76ead650ce9079a5e8f2eee07bfcd7788f50fcee862b449c0b4b14722be305bf4a6aa87b7f22c0ec57614ed8675fe13987967abc3c8a7457435076
+TAG: cf99dd535f78aa458de539eb64b6041b
+
+# DIGEST: 68c0be56c31757f80c17a0532ed15886
+KEY: 19fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bf
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa
+AD: 76aed06707a07c3dab6997
+CT: 4f7449235ca434029ccd8af844ee893341b9128005cba959dfc49aad362580fe45eaea25ecd5fc979118358a845acace1ed0bd4c22cbe87bd02db947059d90c8993f2db02a23b3a8508fe7d9b63cc4adcce8b6a2d11b2da2f50a70112824dcd574c4a7f3f1a5d59f1858aaefc1eab938cbb730049fada7d04d212e32aa5bd64879ce460aea7f50da89a68e6708c32a1ef919078d3078f97c726e5516dc6d261cedc1fc3ee622cc57c4d23fe13e2cd862a57d662e29bb47f7a7d2d3fc58221809614dcb222cda362741e19304212df3ebb4eee2979f97e4f1442c36373b65a894a7711015886dd9475f86101775b46510132c2c6a5127b1cc8375c0baa31832a3ae292c5f39f86f5c07fd49e8c84e5b4d6d92a513c39e290a1d61ec38f6342a2c504aba4202aa776ff145a23fc324c3d2ddbd75261c3a1ec205b87f9559c2fb55a79a17ef8be69d81ad67668794e70d032fdbbd131524911d7e680fc873fa0627240ca02e539aa63d
+TAG: 9984fe499f6a098eee40c020eb8ed388
+
+# DIGEST: 50adef6da405084eefe2918284d8a2d7
+KEY: 2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49d
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707
+AD: a07c3dab699719fe882eee
+CT: 0ae257c9c7173aac789aa20057588a6cdaefd34ef91f9e50f2c8040de3b8d8aea82317bf6bb4f4cdebb4d9340e5ba99a598d520f23660eeaa7b946dd6d2597b40d665117514a0a68309f976e2355892a38e061438ec9a67e2ea938e38b7e58658dccb67296bd8073f8cd885b6ce363ac62282586dc78a2a53a0e218c1039f028973831c1bd11d384a34cbc051a07fc0a1786b7e92c99308b063a61ad07716377b5da64e516bfb412dc138718d3c255a04ec3d307b9f2ba90fe30b51a7506c48e0c25481d8e41da097bea7c97c41308d486c7936c4571ff539c09f09172817a92a0b1dff415c9eec36a6e8309c18e50c2d232d9d257f48cccceef0768cb1403a2cbf93b50a7a75fdb2de73df640c9471c646b6494062abb198f31793cd1b60f5893fc662b9350c8f74404023306d1cb4205f6a4bd131d39a29cb605269836526fad6e465e11f7c7921bcfb44996bcee249ed4fc2fef8ac7e8cca4f15a5b1b8f5f29c281de89a438897f2a890e9a
+TAG: d2e2b9bbe88d10e89bc8d8aca69d56db
+
+# DIGEST: e0e99653835661c7becbd9ba0c48107c
+KEY: 11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b97
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab69
+AD: 9719fe882eee2fee55ed8b
+CT: 3010e2287e92a1a526eae166a6b09341cdd17e0c96b017c534dabd4e197a7c7ebce5217819bcb253e62c6873ef97aad7e6eddd92ce5ff41346b92671af2a8d76ae0442b47ec241dc20c38f1d0e34c556eb820ed17ab67196cdc9c6b226b151a729ca0d7acf3263973761ad32dc1a81cd8c942626f4d4ba67e3ea73041ee107896bd62e714f147176802b013054f0ac8eb7daf750eebbb585b4fedc67972977a22364028c445ddb6441a2378f8f17c307742615f9b6489591d8ca2325c699d38e4dec8c7aa65eea7bab6d720802729b3dcf7a3c3ea48e4e57620d51fbf34e73df0df27158a815177195f08d02f0ae65485b9713a3b313cf7b042085ea7c3064d4e5d307efa1dafd83e05ce672cc8bbcb59a196d967eea3674d272827c210f8efb3377d627d1393d7478fa6a240dea0eea7e251cf2624cb6a679ecf6f5009a91b8b97f868f60b40c5afc36edf970682a15c9d8460aa669fd9931edd9d4752cf7d6446efbba62da525be96039ed9c24bfe283c4
+TAG: 50667fdc0f53c729370589abbbd7bb16
+
+# DIGEST: d48b900f00c5ee1a629c2a0d3d778c0c
+KEY: c695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f47
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882e
+AD: ee2fee55ed8b11534c870d
+CT: 20e3e0f8f68b311c8a8c97338cb819d8283ecd8f7f7f743bdf66d8f2b7e9bde6de26f2c6277932cd444b69b2e3b2dac804a30d10777d52d70136a8177d4712b271b5c736b123b5912bba0ac479a31b8b50fdda2ca0b79c1b95b7e7bbd7f3f87401499fac1db5854def863c53a88923a135303897f23679a46e954f24bea2ae06f7a51cc5a7bce74715abacd29de4523e3dae5c8477b8ccc65dac351d289efd8813e454981686e1572b2d86119cf3c91f04234c7af6d4ceaab3a74e79021c2d2c6918343e05f624b938f12e0330586cecc4084969a9b02cd74181634a21dbb8192492ada41740d4f20078a3c6e378d2143ba97945c714edb72e758c0fd1a157cdc0e5f35a0435c055916360e6231e84f1cd08c4d9683053c6f29269cb3fb46bbc2136dceb4d98305f856a46103c764545ef40847e9c12e417c987f2eea838dbf6ea75043144ade176b5b3b896f8b8e6cbafc218bd326604b180da71471867c352fd1f414f63c8de94e103bc1166a78d82a207cee234b93a
+TAG: 2fb9bc483ed2925eddc2cf1a541390bd
+
+# DIGEST: abb7c6092e4f729be74a8c66291a73c3
+KEY: f1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed
+AD: 8b11534c870dc695b814bd
+CT: 6b19aa9bc626b77e79f44b1315002722a9a8486ea24c060de42d1b929c04a1832cf62970834cfff3ea251d234896cf164ce850d4da613c01e5a00fdc364bc3eb07fd20d7dd9f48f48bdb171504c7f9fa593f9d559be02c913a8aa8703433e024f6cf6116e056b529a32d2bd8c7800cdfe69279da869c5aa1acea7ad7f90605d0cf6eca2d2a8b5c14fe249d7ebd51e87fd7884ee88291bd0ed8987b8acf19d35cc73e3946d56a52ca40552b33f50fb5fcdf1b0f167830e5bbea3b75742ddf0a3d615d258ce30743ea4bae4e4aad54dd197acd69cdcd992f15eed07767b473ea814f602bf43009174d8b56d430346e9eb27ebb1b62f3f442cf61b4370668f6f751a722b894e0431280261d2965bb52073fc22464ed6656f7100282decd12c116c731b54f020ef3a8acdc1a3d01b2d2e40451b515d0cb6505fe8a1e82feb109728a7c2ad6c422fbc9f1aec572fb0ab451694e0d521e2b3450db76446de4955c6e4d20a6854710b37a2e3a68e6a8f2cf43187414c105222a9a81887134d9
+TAG: 2808cb399950b4982c73a643999e3650
+
+# DIGEST: 8ded156a3f7c636a322f664810431782
+KEY: 2c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b17
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c87
+AD: 0dc695b814bdf1a87bb105
+CT: 09a18c4010560393b7dde422fb4437adcd75286d03838886b527650a29943c7d40c9f07efc53fb350191626feb8f6e2cfd37e1acc95b39b06d7458acb0d28b31894fe4b69a7c0beac050c4341a2e95106c41ff079164be6aef79b5ef8056d129f49085658a917ee9be071ebf3af499e6f7958092a3390be36c4495c73303f40582b92d3913c36a38d5f13892e7de420969647cffecdef25b99cab3ac8a2061ca1ea9373728ed1f9f6437db8482b9b6436f5f8c23f69b367de29e83edcbe246b0506c87881bfe09a22aa4fb525d6c115b7f9a171569494394775f80aad34aed1d8dd7d06a0cf64f1a40c91b006185c7d3944a7a4f33dd57a22fa25e077b7fe3b760ba3f5601892488a07ff07f57286438a5cec0db30945bb93ddb17f550c34a8b61466bfff81800b962ab1b36ec856bb6e9222c317420e217d76cfa0308a0dd8340631f7ea020ec796ab49e6897d9381e3aad1dfb54b55e4ed1892d36f3b46fff4400231619ae1d4bcbf59ef44309eb2e08732960ee6dd0cc9c8f122214a0ed8eef
+TAG: def243ec5a6a1b19bc054b1ff73d450a
+
+# DIGEST: 476f4c73eff8ef9dc0cb5a98ad24fac0
+KEY: 16bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814
+AD: bdf1a87bb1052c6755a7a1
+CT: 3c491ee5eb64f423375d864e1b7467ea216cde75a87a9a2876e275de3e50e1f53a412ff0a3168ccf1b36b96c5ce3f9dd52037941ec435f83eca175ebc80bb9496bec3b5239853a4ada2397fd9bb38299c7ba43f410310685bb95650272578a96b6e79be51cb8aaf1854f1a5522c830b9e3c13eed3c6da05e1447e856e3606113398a571d131efb9e86f3036919232a65dfc109c175239fe0f8f0c8b6f8766edbd1eb1204bc999ee45cf241b8f54d1f2e6e7f10ce8f8d4234146f42ac2537795b55254ce7775a66e79080bcd746d846a9aae61edb42595ab0cce3b89520b7a621118f4271c804bff9e97285856e153c21ed6c3a87b5bb1b25bef13cae57d657a51595669e36fc650a578a2431c761d477d659496a99890dc9c1af5ade6f5ea53587868df0a9e9de538472acf44baacb22ad2a6c61df427de3cb5cff939a1333d3745ca58a60b7a4002f38d4002fc60ed6f46c00620192b7af86921e66b585907e94bd02f0fdfc009d942b875dada16c20a142ee9284930d8ee5de0cf6c6a29153e89bb38caef5
+TAG: 3d2dc3732f579d8b8b13954acbc085aa
+
+# DIGEST: ee209d295d7f9be542fe42c2df64af23
+KEY: a49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1
+AD: 052c6755a7a116bfc9095d
+CT: e4675723aa350dc1a687aa917e6783558cc44914038fb94b8632b7c6dbe65b415eea890a95c94113291c93eb00a335db45b06ae6cbd9774aeb1f9ec2c4a81bcd12807274081239b2702dcfc939f8bdbe15e9fb84106a70137572a941ee0cdde004779351f619c841bf74abc57ad38e9297896bf32368520004008cbef2b046afeb1ee3918208907d5605eda0991e289ba3cac2fff5fc4afbe11e8cf62a53be0a9789e87165e856c4a9a3276d560dbe108b9346fe549c80890d05673b26576aa7309441a2eb0527a24e79de926ea5dafd55a2707bfa1f98ea32862d2763298450117eeccc0566b9abd88fe8e6cc687aa26e3962a242fee58b2d09aa4f7e9e04c77f330eafe3c9da765bc373ef1bf81eb033c235a3181cd4fddb811796b8a6fd45455c80ed4059609cc6d29f5a012ebcc321d80550abf577fe797433e82a8bba1d7e5a5fdc02c6a6aba9f91e713452dea5f5996d211cfbf6bd271497b915fa0996f0773783ab790d889966aa5ee878e2c3b046a8f8b75e0240d97039b64dff59cc3b5c32ae9146a3235b06cc
+TAG: d326b0325b79b6b48e698664b5e80174
+
+# DIGEST: edc76d971fd21d71ef1a5cebb4ae9ad2
+KEY: 4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7
+AD: a116bfc9095da49db3d71f
+CT: db50a51a5d6b71e57175e1611e6f808aa0d6b4edd19ecb7a7e1ebfd1e9532255885a4e81d94ce19c7a0168611305ef0acfaaba9bb5d0d1968ad09e9de3b2d3115a716a9b9250e49a75fdac55f51257bfeef4308108ac90b79b47374b7cb392171be9f6519ca0e7c83de0af351727501915f8baa117c811b1d74de65be00bd77185b083fad42de80acc31bf1c6b5b0b63e38169af7ea33faccd0de72ce1db117135bdf814acb4e9f15d25325f8dd00bd31e2387ccfafbb35951871c77875f22abd4caa01cd23edde2196191c5f04c41723c5a098638d17ad470522405f11457989fd367906d3cbb48894507cd353a8063c579ebfb115f9dbe0efbdb44eb8b6e8441eb8b5578986dc9277f28c36f1de32d990b29171db34a7749227d242e35b44909ab3cbf6ca78503968e8ee94eae6d47ee9c816a9fd479e12b6467b8eccba6d29aab1ee8df8155d60682a10589728401b9d51a70205b1d3b71f7cf7273921c4a3997e279180b0bc55d3bc73836cf995c126a42d76eaaa4b22d2daacd4821171d64905fabde6aad322d78b3ed09fd6f4f
+TAG: 65d126603707ec327bfba6fab9c4db49
+
+# DIGEST: 5b721a3d03aaf095d1cf78db00485987
+KEY: 3f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d7
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc909
+AD: 5da49db3d71f4b975c5d50
+CT: 1406ce3dc7845267d8445864db73229ca135f07fb4f5638a523b759e8fbc0066b3b6dd9cfab8818d0286a394c69b681b0f254637968b159cedda768841e66f83901ae8fabfc437df490213c5300b4afd6aa1e5c6b1e4abfc09c813bac1be874d07cabbfd5afdfaa12bfe49d2a57ea39441f318aa15a8f75e7a9fd2d4f9506fcbadb2b0252881e07b3c5a7143811d449473b83d975dabc76034427eb1ed078c7262d9e3429cb985db0bb160d5521658fb90c27194c8a763b0e9b3888d55f818c881624bb33ca7724041b3a6f5dd07480570ab1648633f770a6c3f47235d8c1b195b8e96e2fe4a714ed50a47b497e931492d1de3e467d2e1aac15ffca1ee7b0430e7e006452389fdb7ef605533fd411e0385da74ed14418ad85297b8fff50309326f3132eaf69da33ba88f34aad1c7c4692ce3fbe96268432a8efc4455c3614a1955db30dc29ff4c98257be16621d9da209211764e81b8724fec777a8073a7590a119cb1b7b5c14cd5e037597b14ead415299cd74e1274d6cca8d9de5dd3ca8687310db8eafb084e35c6e7a037c39017fab0c21379aa
+TAG: 8eccfc25e4921cc0eaae3fa31090482b
+
+# DIGEST: 5c230f3abc8c28493462086a8a988b25
+KEY: 8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d80898
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d7
+AD: 1f4b975c5d503f478b22dc
+CT: c0ad4239b406ac1dc560887de06d6ae3e4fe987e8aaf443c676d38af0745f4ca88625cb69233af7311836c55b8570dc4a2a9f1169e31857e095848560a04b1a7b4c61bd3e3db137a1f82f966dec88656d5b389bf3f0b50be88797e58df6f01e9d9481e70809e8f46a85cd85add45c9305398e5aabecef48defad6f2cccb5c21313b14a3e63107bac9b4243ea125d5d836260680b07adb55158d38362f1356a5699bcbb88b256f3fd0a66f56c47a6d2df819cb70d0e0541c30c3305d8952813dd3fff8b6cb6bb40f2e7234f400949676aff8cf2e739e7cdf5dc67fd2427421a7a4fb03564efa7e52e5ddaf796ace63caad1c78a9f3e20b1136f0cf8d91bad0397d5f40df198903e60dd83c301aa40af1070dcce46d53a357e94e2ae6c4036819e19506a80cb3611e9a21a4741e81f5be4ff49ca39e3040487bbc506133317d950de4e63e3e3efe4466e144c0faed616281f63e65d9f161c25baef639b4d9e41aa6293c627d8228bd246e467a2ae01451acf4134f5739f0331a06ba8de782fe7108a4028e14c909853954b74ba7eb15e08185d564fb90ce105c349
+TAG: f605cc66de00f490bcda9e3bcbf5683b
+
+# DIGEST: d001d4aed1501085c3016f25dc21e03d
+KEY: 1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea37112
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d
+AD: 503f478b22dc8253bee6fd
+CT: 6ba5329a5e4c1046465f82d79e7f52383709be8f495acac7c2fcbfa27f58c59be0c972e035b7ef2bf6ebbc2e040ef2a89d883f5470a6388090c4713bcf366da0cc1e733dac332dbbb4c230e127ec8354980b568a4f8154eddde1bfc1eeb475d13c211569eb4ee25a7dbbc8b433bc007490bd9b3eb003382dfd4bac4a0779e7bb6525f643af6ace411c9054293f8f37ecb7e3fed821d4a4bb34240b8781f0dd78aace6b9861e794e8b9ed17c5ff24b976514dd09ca54a78262dc99dfbdac0e7b93743054fa4a49220d82dc4b4319284c216bca05bfe2e1abfa44e0f8ad94e6250f22b7caf17fb0ad5617cb9b754b28f151197f68ae3a514a738bdb3f4ad6876723a9fd92be504e36bc1581f7e388b4ed98ab01af79d7d1746d437eaf16d7e9bb0d8556ecf9e7f94ed2f769d7821cf01ed8b23da3b2fcbbc27e644748bbdb1c8bdfd35c89176a11a73cc205ec7fb7ccde0ca450120a20ce1c0d4d80d35e88bd435608a9400683f97909b0b9c8439b731ab1daddcc17f6f19e1e57938acca374616d5ef23d3504b9e94c7aa89957669ee3e5710b239facbae874fa63f75ff9b04
+TAG: 0d460ffb50fcd449c699c58151fff8e4
+
+# DIGEST: e48e5f6e6f73c0625e79057e18f2ed29
+KEY: 01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22
+AD: dc8253bee6fd1b174c307f
+CT: c50ce9a6ba84423a28c6390115bd9767c1202ee4b3c6851fab1007b0f23d07f016bab18a8efebe0f09c0796b0725add60ee521823fda248b809eb317e40149374d95e9aea5cbde33ecea576e91a650e4be741f13fca2cd45cbfc967ece9ba219d5e4695d57032417165f2d29b67a9fbf6bddc0389c9c649a4de23b361cee86c3c86daf507b5a012ce2171cf94ef1019507265c0cc35d06acd936a5dd05a16a8ae8fd5a73939f68634347d35d4b6ad2b508a48e871cb51b583e8e628a24d68b63dd4a50fd9b907a67247109627faead59cdf0eaf3610bd74d7b45bc801b8e9e3780911b5017846035b5a54061f98a10b91cee3ceeb301503913ffdd4b0cba1e3f7f406ec30a7e7207adb27f3b0ec80605ff65ecddc01239838deec3d0abde5b36d743ffd5973b21e467e940fe3ee3b887230708f61d1e4417fcf756af1a9fb469d91ef360c8a1c2861481f61a137b308a913c15b469d6c3ab7b71f8bf27b2fd40e9e276f07d10bfe72626965b500752cc4eef16adbeb65ad98de604c2df8d20b5b69384e69a432688ec6b9225b3f473ff7b32816d5a28f6623706c1e411f04a531ff5bb46
+TAG: 30451363e2e03ce4f9a432d28d2dd44b
+
+# DIGEST: 1910b5dc71aab1b2a978c487f5f76df5
+KEY: 9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6
+AD: fd1b174c307f01be95abaa
+CT: ebd8b1e9abcef8eedef579b2bf37174ed8b6bc46cdb8392b4668318bf7afe149a98b3d3f9015285373adab1af0551f317eea7cbb56aa27161cbb165b6385689aa7ca1481ae2dccefb5721290da2044fe8d3de8854b1cd3822617356bb84cbf8fae2a865d9e8777b6833cfae5eec85de81c1b9b72b3c092758e59c10b719734c83633c9198f6f1e1ede2455defccbbe3bc9746af7e8526599a9b5de1057956ec88f7f970018c942be60e14e09b48b9dd0fa6276950cc4a4a73c3087d6d25243e5a95ce5c5cc610897a5e21ad281cf692e3ad7a4432d61d98560cf16234fbae0b1245424fe86ca94396629ad39a9722756b24fe764584eaa337aad79e823ee367c5254cc0421e40cdb2ceff496cf20e69bee39edd2eb38dccab18a3ac312fc672c2a3d252f0bcc1d1b25c85be83233601c29b89fb6a998ac36bbf0c572c184f94b402c3f9c507848751d5fe56e33919773cbc337b272cd8d9c78f54a431a78cba31b989b1db3ad1f1214522268ea9580160b21adf01cc9650253d8d22ad6e6877b525d411c688770898fca77c91e5545caa4999c839b26eec634c886808c793e37d9ff19f3e14bb1499b
+TAG: bf0653da28fbe42053746aaba0510492
+
+# DIGEST: e5b79a4a9a785ae0a9818bd752d81130
+KEY: 2305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12d
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c30
+AD: 7f01be95abaa9bee585777
+CT: bd52047b9c992ba4b657931ce78872bae84cabcea091e32e0e011dac1c372cad88c18b0fcc117a33dc800144b7418d5be64f69b38f174f663b8d980f5d1c38e75c0ca39014a2b641cf1f0101d6d3a3ff4e6fa5fb3de8a88086104b729e1a9675487820c026835be7ff6600cd541819f9c4fef670bce214c4f105f1e4155963b13f350d55f146125b937ec144d73b01386754ad073f941a3b45a8b934a74c2f554be441ac118faaaa97174999a28b569582698039f94c2eade7486713ac0847fc21ccacf9dc99a8e846a53ff5ccb8f2fc211e735ee176b834d598dc849ac59af9228323ae33721cca53505936261ac31b71160877b1fec885e5ad68257096511b4c95894476260a10db66003ec07cf3cd9e9c2d75bfe951ae4cdab5bb7e5fe74f462eb4651fc55d243c5fe04cfa2c4742652c9c62b7966b97d7c509899b64a642a9cbbc2ef723b3d0857cda68498d970b5892f2d273d5118a8ccdb0e431d7ed0874463fcf4454aa308c91bea7b89cccf8a06edb405f3065360540da3f52ff5821b85d7fe6944b5778c99d49f2612b65467a43960168ac8bc4fff7d27f9bdc59194513a3ba39a6c9968ceea8075aa9
+TAG: 7eb4040f290c97bbbb7dfbeb9a73f2e6
+
+# DIGEST: 165cfc8f22f98aba035cbb44802b73f3
+KEY: 50d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95ab
+AD: aa9bee5857772305daa4b5
+CT: 30877f875cb8277391ce1ee6a4d6d8236597b4b6ff92f99ff6a0936f5f69ca7b4ed6e665bd0a839a9308d6b19ff0759d4ea8a3debc68a56f29320a8d5b7a72b0fbc6c3db1bf4f84bbdfd2dc9d9ff1f7b88e5ac2e4faed3910e2c828599299e43527ed75d250f2821f5e52019474e2daff474621552e504072a7c6b29076ebcd53d6b7194303e92df1f728a868f4c836ffd0eb0f05782a8f737b4f799983c6965ac8c44f0821f1be485bca48b545cc8a0f7e61bc7e987a9b183ad3dc03c41a98fc2fed643fbf8fa10938ffa37bb79175177331006b5acdca04996fa3739963991765a308ceb8ac35c46c8ac4548add3ee3ef77f42c9b49093a7907a2f2b8195c53377654fea51ad55fcf58ca6ed333674f9cc2d9bec1e509513a250b595163848eeb5df23ea8305ccc1413c9a97ef94e19d3986d584134cc985e98d398790aaefbf44e447e8707b7effd52b6af3abb6ed2d1db57e016026e962b7048e00027eaa1a11910a2f54af54170bd8ad9b17ff55302da6ab19144167531098f977e1ecf1e374a956d49595b326c9c805040e511dc5c8ce0a56f5078a7c12324aa55da1125b82c4ae433337de48f017d059039b8425eb75
+TAG: 27006fa7a39b64eabae70ccbf884b2ca
+
+# DIGEST: 4ea4edf4c7d390a9465fd5ea4ab7d4f4
+KEY: 089850fea3711265bf782610460bfd24ba022e6da12dd4c27f43724809744548
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857
+AD: 772305daa4b550d75f05d8
+CT: 90151815e2c6af6753c265657ddd9205447a49eaab8d6b258d2aea66cec6ca3c9302e73a6e08b9b63679fe0f3b026cafd03e664d6aa7e0d7171aba17e3ceb2d11c63851becdab399f71081d6fd3f5c5cdc387b77d919a5f717f352efa4ca87a753aa81693b5ff00785b7e8228acca636fcf6163157362756e46d29ffb69d9308af60452c821989c1b3b2f1eb4fd6ca7e555102a052098cae1aadb4578f45067492a6ddfb435d4b976dc223cc643c9ff86e47626837b8f48a8bce5647340aa7aecf049c510a65d957041dc3525ad2a16936194bbb2deeaa53d5147ad15ac9ad2a1ad852a92e44b067e54a1a3bb48a9ca6e249018e10361d3d76cfe6a25cbe2961e70db44dc9fc35886501ba957e8568161d09c51805e2b09dca668151b56d2cc24bac15f21ef7c81b5edc8dd683c328099e41d91d9ad09d7b9195bc7823c97379322bf9487da0b700c625dd5a2481b609885f3133ce78de3a303afac64e980c9dc15a0fb1559603f2eff1192060a9297d33811c43c59f4e0bff1e4f56d3d86298fab884d133c3743c9fa86cfe424cf4e8278ccfa0e5948dc005fcef7784ea91a91fd9dba729e5ea0f10a1c419fb9f1f764070de745c86750d
+TAG: 6cdf4165f444005b25d384167d7c5fcf
+
+# DIGEST: 838a2cdb1f507acd485870460bc595c0
+KEY: 711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4
+AD: b550d75f05d8089850fea3
+CT: 6cd01c4259d58fd4781811a67322755aa7b9c9f01f3ff7117fa0c30618b7f8cb6140502f2b850d486ec4cfa1192a4b01644438d86a4c2dc0a94968ef7da5660d7e66c9b6d4c51ffc9bc939d5564a25fa67459652fc6d0f20f43d2e97a4d11139c0817d320f6ccd92fc4ab4c986bcfd29b0b8fef0b7d3c3668b31d14a38840980fb7a078daea8b4e42a26bb4b23755cffb5c5309c62b9debbed40dc3ecb9bad09592a254b59a17bf80371d7abc1cf83a6ea44da238be638a46d6d9e369f0311f5f9ec7a63861668082c7ee390ac2d822a2555c0d09695df6c838bcc2583b868bdbec76e050c1a36a5fd3720f277e2cb5d5d067c61649ba66c316ebaf237f02aaca44be9bdefe16c51c6007755158673441654aea29f5bca6fd2b27227c9d029006036d77c8cfe8bc6dcaca259dd87e0a5982fcb631c28660f0d02515e9b702314985b504cbdbc2568ee04b8b80a2efc9121cd6c2e9b72d9e4c53a939a28280c618d428326f95e64680a299b31150dfb6b2007302d0e50ca0ad90c8094258acc8689f0b44d405bf4457ddd284aaee75b27ee7d64b55b0f0606d76d773580a3c0214981325f4ddde19fb30716f01b76197b217ae650fd7a71b337e7a34e05
+TAG: 287b728e0f1c5bfc11427720bfadf646
+
+# DIGEST: 7c4d663f385b10207fa977d19d9234f7
+KEY: 2610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05
+AD: d8089850fea3711265bf78
+CT: 9b019ddfcab4c84ad95b017a7a121320a8c1824f110e45e4fb184718a034b289542fd9799b98645c64d045b185b1fc9f48544d99ea5f3e76771556dc018353fad7b26bb7734b576c64ebe9b45fae3bfd3afd9155af81fb5e96ee1d918c84cdedb853bd0b609fef7d7276802ffe7860f5faf59cd197da7ba0795105df1f47862764daa944128fb34c473e2ebe5e296841c0c705dc2831155c591a60af6000b8abcf63dc831e9a593107d366af4053fefdfbf532c03f4ee3b710ed678b436fe07cc2561773aa8ca2a065f5624ec157806c94d0813465f5a2a2dacf50c5f47d8357b14f977221b6bd291cf4f0be3a692d0664235529f0cdda9e4cb2a09ef7af816eff499fb6dfb9f8ea20a731036de9db7ab03307f2b762ca811f36fdbd67f09e4afb4345e64ef57b72e133da61cb8eb612e327ad79864fd8bb9c37461ddff66e6d5b8bdf6980d9ac9acdf03a76089da0173a79bb50c04c2bcfca0029b398705d71a64169bd58bbf392ac72d43ec445cc3c7aec3a99126be0733b1804b79ece6c6a6230940e25443b1ebf7ebbeeb3d9c13ce3de970bfd399bb0964a5179d34e292d19039b911d421d3fd74bbdb7cf21bbf2643b4410a9fa8fe565b821a94725c8667d9c
+TAG: 4526d0a45c3aa8447603075a765b73d3
+
+# DIGEST: e52cf395415d5134e78d8a6897f91291
+KEY: 24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a56179
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fe
+AD: a3711265bf782610460bfd
+CT: cf705822d1da98141709c1edb5e4947aac4e08869870133d1bd840ff14c839ccf59e5d788af01678e3b2db0b63be17bf9b01513f8dec4a45a685a7d50b9c959d5b9df8998a1532966ed6245b394c83e849d7fd9c78168d0309ba9571405566db6bf31212b1f63b5b1412a11c6cfebfef14d35189685795bf988d3f51c79e409e3c7334d6398f76b68b363bb300c82bbbbd9ea9a9ce9e31a5c4888d7b08a98f594e073803d5ea60a95c4a7fb6a143902ffe173a2939fc6ea9cb21cbac15147a6439fc2cc06c9386f1293e2fe5efd5bae24e218d86f1b6735951ba0f672d64fa1e8dd410def77ad2a6f10f85a3048c31c4e64c588c96c2cab2060a515f3e7d68d67185c235cba8c3f257f8d37e753974f1e95c29540a847afa4786eed15c34f7db0f1c722810f4ae328916bdb076533f0b357d4b3497081c9ab68e98cf26e453479a0fd5312d2871e6cfb2f8ef375aa0a294462bb73da14949c287c0fa716be37f11ddb6f7e493aedd94718f35bcfceb68717585e0ae63d13e1d767326f54e8b2eb38b3ceeb409f020d02bde0fbbc4e06d14d2ae99ca304fa32f5653ed44939749e5f972b0fb8a6fc05cf826dd4025a808b61e9412a8b1a8f27e64de18a35893262a79a8cb0cec20
+TAG: 617310796152e91bd763bf1162849795
+
+# DIGEST: c4161bfb8895268565ed0e2563b26c96
+KEY: a12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f311643
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf
+AD: 782610460bfd24ba022e6d
+CT: 57b0c0e28fa66b9736971aef22d7d86137d548a0ac1b644aab306a2f979d8542156ad2741a384625b6ff579919eee7323da113589a2a342597d11917a9fc2fdcfea1fed6cbdeb55de2e809c1fdad26bdbfee428d361644ca21f55727101a597e664cc7211ad639f3f765f4cb51035d6a522c140fa92c92dae39dba4535b52b3562520c647fb23ca569f634f0bf430936a7348f6bb063a683eca09745de2e7c842d20cc0eb06448d2ba52b08fb54e6fac2d05a57bb7f092f616c13df49e4e54cbbf94ce7a3ddc95bc4b49327cf5d1a4fb19cbbf78faff09e19ed143029989d505a8e7832815b9ce25b44f169c7c3ec1c15afb6b74e4c0b92ee8c2d2e61d47391d0687b5a0172c382623e18d7f1071b8c529dafdeee003b4cbba129ddc8e5e785246f6917c1074f29d915af8f4728d180c18919b753a0b056fc71a15a0e09e5ab555c62c6d02214c539eba966fda05dc8dea5fb4738131df72a53b83e6ef539d75282b8ff99a761cc885afeb6d849b886ab59888933db6b91362053f9552f626dfc8c3621c25603c2c257e7c1fc17d206a3f76253f88c468e5b73dfb8b107ed6960832c9955c8bcbdd0ddcf77d0c510029bc761accc41e9b344f753fd6db881a9ac2758b6f2c6b1f5787b7aa47
+TAG: 1465528b2efccadb4dca099468029ffa
+
+# DIGEST: 5316b9140451c44cd67cd9a2c9b3b668
+KEY: 4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460b
+AD: fd24ba022e6da12dd4c27f
+CT: b874f7a7bbb22e888130456cb93c867242b0a44e4d2497116092221e9fbee54545108f25e342c8e06c2a7e8d3541088b7bf6766a92769a39a1bf37b2edf90ba1a14aacab0649c518529880379f483b99a9c98e13b4baa47e79e1df049c843d100a8635614692514effe098f38659df69543cd27504feaf436d1f04b85b4775991855da050fa21808871cd30f433d0718aa141876355be2ede583a2b4ca17332ab7beea63134e65908999ece8f4985aced7a9f3b89cbf099115f92a343d2feb2f2b39968069918c62cbec80ca760c93de92518d6f4b855906752f909b0064bbfdee8b6d5eeed10b1e58627d96a660d87339c2647ee287c3efa7c80124876bd462eb18158007a5dac108e9c5f9295bff5de87b528a8db33fd60a52f394ccbace73e4711b3552087ce1d38955abb3ebca24fa4e5541ceb4bd162583170eaa3043b2b258e7c595816313177790b7b684f480802dfab03e41fa90d25f01d746c5fba48ed62dafb61b2bad3d66d908df7963d0ed230e9f1d6c08cfd5b3707221a5f828df6b3ac28b1e48651a4d89578724cc6e66b45e47e15c2206ddda622aef8ac4b3d9d9c9708ebe1605a5174f79ccb2c1d001d12ddbf9823350d554d9135fee7de3899394dc24d12b46e779f38d59403d6cbe
+TAG: ac394c05f2af8ec027b66f5b6a64f464
+
+# DIGEST: 580e929216166bc239b3b9137b2f00b7
+KEY: 454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e
+AD: 6da12dd4c27f4372480974
+CT: 4736410243526a37d14024099da6f50e51953a2194d38399e935642e9a1c71b6e7bfb404d0678dff844aa96eb64a133ba004421da9ebb01acdb2621ec45e617bb3d5b9a27224d275023b37ad49ff53003415e97f38b01ceb149daf49124fc7c5272e12ce83b51d3b4904bc088c8c59a207a6a24e86f1cee5682d32e9b2ce821a105c91896e226d0f286205b0b8106bd31ce0d7a56cc546f294a144cba741805ea4633918c3256ff68fb76720ccde1fd3ad05aacc299ae87b6a9da1aa5706fa2d05f84fc094a470c08af578bd633faa99ef018cef78bec1bb646e7ba06acb884b3a20b94dbaf5a7290d0eef866fee38971aa2df880aa8c83e1a3967a1e7044d8e6d528eb31d9421ba227138e48db766a20364c0f5044d02916ae3b569998cb2b52e4b6765d148834900a4e96398e6266fccd038ca3ca881c91f40e4b383df67640057559e3981bf468e5ded9831f3dd2205b97296d0e7ada6ef10516225b9d53cf44967d22fd85105bbad8de666dab38314ddc89ef4ce7547e5b29176963bbe09390f642a527615573c38e4c7d4bc698cd0d94fb3ef694de8965a5fb4412de97aac0b5e8efc2158490730397756f770ff52a4eeb40f8e6e464fab9cac94026ea76b1884ec18f2195747222a52f1e62c07902240ce3e5e
+TAG: ea46512c8a7332c4d63c7d8faad019ae
+
+# DIGEST: aba7a79c9107933b5d5c01965fb21d02
+KEY: e9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1d
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c2
+AD: 7f4372480974454879c41d
+CT: 5c1937c3e5142700a00d89fc8cd56b32d91e0182dcbee99c56a268dace00490bbe5f243560719df76bc492e53b21de57d7ac8803ec00afa463e04302d8ec23c8a4b12129d6d924c0ef49302f19f24cc3e4869b40937a11a01c6198f7e710ca8bfdd142f25cda23558b639c108908aadb1f83a8402f0b5755e5e9b8650a9c6c0568ea30361fd9334935239d89b2ab242e8f83ab60f1f4c21ca86625129d892939e3f18ba7b44a3cd788c316e3eece720ff5cb077dc08bcaef31069a8c62493cb27f9706d2879cff2e06342b7b9828afc929e226c72e8f012f32d17c77aeaadbdd435e602fe9981f78550e38afd0631be5b197827740b6f9e3a71daf93d705098b2d7c5c3e8bc79274ca021504c682b868f986568039ddfade902a8e364298a46af4cda4a104badb965f5a2600a30813aa4d8c251e31a1d36803c42323083c3fae69b91bbf52687458c7cc7e15b9a066c5cd349ff45cae43a9443979a56fd88dba64f924a11deacd36b069193e3aa532c76b216a2f2a883d02fdbe82c98ecc09dbd3eff7ea6411e398d3555b9a8cc851be4dd04442595b9aaaae415167c4685953fe1c7009b099f408502f6a121f90ba6c57880c3782aab1a123bb946b9e6de6fdbaebb3c78fd326cd23ac78ec251d5fb8a1df74b47c308eead8c2ce
+TAG: 8da32407e0897e2b00aebe576619713e
+
+# DIGEST: 93866d980c6f5a13693a5d350f2d3c72
+KEY: 3b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f43724809
+AD: 74454879c41de9ac9f9823
+CT: f559d2830b720d70336ac550a13d6a686dda1087ec5b517eccbb5c8580277852b7a05f0bc90ca417c8de69ec15d0493d2e4829666102226453c84333a6240e151090228d2872c89dcd6bc805d32cdf83b03ad6b28afeb6be972b9b5844739bd9fc11e38869860ec4dc0dcaaccf5274a8aceb95c2f2b4c5c82b63a178edd2eb7d41affbe93c92ad8153a77157d742edb53926d1192b5f8dbe1e58d1974013f8bf676d52f0a096ca756d389a7ea774cd4ba16aeb33356279e706038338c7ba932054aa93bc75d9d49d0e9a62ad58a8d5b28178286fc2f205608133992259c4f140148ee2bb431e73132af3dd23b8df5406c5f4a65da38f65e5d630b193a6e4a62c86a98034cc4789e8376cd16fd9a9ee56480ef96232955fdab68a8aea07736757a7c5e28637a18f255ab044bee7ee991bf8d403ca3d7c35392d64307527b04683cfbef1e0a7cb005fcead5d8cf1f3afd2a0bf428814ae93b10d34b04158768b4b3873ba83c9e20172776f73866890d38f6f253c64c89288ddec376d01857e9698c561ab020ca33b63f843946d97824983d5999d8bb565b1517655c9ee8600e0480d95a5c7b33390b8172ee1a13e09f1e377daf86dbc220c5585a6859e798b44f61c5463d1e2cfde28a2f043d0cc8e83cebd087b6cf34e048f3f4fe902d1c7c089
+TAG: b2ff32dd9823d1f90db9078ca471d4c9
+
+# DIGEST: 15ed29142440dd8af534d2c2b33dd98c
+KEY: 61792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c4
+AD: 1de9ac9f98233b5a7379a5
+CT: 466e361159ffdd7ac6e88bcdbe85cffae4b6a813321538a317accc1a36e6924011e446557a6f47786d99ab8102386bac937ffecda7c9eff4ce567eac6939fdc77c6db11437f959beb340d58414ee1969182c978fe7c739ccb95b620a0f0b19be2d6e8dec31e79a52b527fda1a046b2cc3bacb3677385b2a8bc96e40b784944452667958393c0e78af716415e93b87d4942d0e0cfacb967c26c2b81f3857c85d5a734043581f2131d2a584139eb41b110a2c8c535d265f5ffabd52c7c3a6c291ad4fa924435e4bb6e891afc6d86365329e856d6424e0fd31afe0c469fecc6453d15b63347f3486879447c3208485fd92ae3fb71ffc2347a79df4fd8f03fa452598e48e4689aad73bb5021d98a403c17a3177051b3e189c955ce1afe96e4be38a484687c5b0b7e0b1edf38e66d54eadbd80ee56528c1c00f8e3c0dd9d6737da7ac955de557d68ad5a6c6e0d85d8fa115640a6f4a19e734abe06ecdb653b66e38acf4778f8604225a3e8a17f81e58196211a73c9ebc2548baa04bb68e7d91584e563575983b7ebcb0dd7a83e565e89f7df2fb5ca616ad3a1a4bc2a728acab951975e77c56610ba8f9edd445f74ec442d679dcd260564d2e8882313982c9a622a1a42157faf82479a866fda1c74d21482e2cf629278b6f932ae1857008fe0c9e44b542c942591a
+TAG: 188fa26c452a97f68e0f27d47625133d
+
+# DIGEST: 22a2ee718c69582499aa0ac787cca9a1
+KEY: 16430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98
+AD: 233b5a7379a561792c0f31
+CT: 67109c38272a3ea6a8940d9f7003dd7962ceb088b1f975f74f555e115a869f5a7c4844112dc652236b84faf71533af8ba01828c3a63f7aaa6fb8cc06ce68fe65f60e715c991fa2c089e52529fbb2c14c95b3a9b8461cd2ffcc3a46e54606ab86043c0b019c8539b4a1967e1223b80dfb76c3da941a0632e9255401271c2ef0caacc14c754bb067337b11496940a70b64ebd5749f37dff625bc9b1928a077d81777e24ad3b6b58bcd9ccb145c1ae566bcfa0c55e958922ed3c38037e301a83d6aaef98027de167b8fb5593e7518e7b8688e9542af9df9f92d0666823b5ff7f2d4482cd546216be57e72e8ef6bbcfe32b7d37c7d23a47ddbf7af99a0a46a5c017050234d5a5214e171a28c7c08052c4221cdce240eb0c3df9f9205f63905ab63a99233cd74b57268050f1a04569c96553e3043db88569e065ab9211259ae175dd535c2ad225d5f70de6ce4682a56d8c679ee2dc5f63ec2d305cb3a9a1e25a90b4d148e840ff270e0049642986ec8c04a09ccf54a2848374a84d1c5a1ce4af7b5f4c844947ff3e913e86fb2d668af3eeecadc36df490532b15cd0d65ae99bc23e20c58a826094be1f3acc6c1661b58211bad36d6a9a5c3c28704694e28553f85756407c5990ecc4b0842812e6e29b167d9260fc9df88a6414456e0e9d2d4f83cce1f23b3170cef4c44f883b
+TAG: 0d4ad1e138a35ebc3d530eb0d8968e80
+
+# DIGEST: a64b2e7861a3b81599e28f7927498221
+KEY: a058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e97
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379
+AD: a561792c0f3116430e8b6e
+CT: aebcdb47d8f5565894e4be47dbe8914631c5de410be171358941e7e39b9a930d1d43c8472b33101cf8edbfee477ed19f39f391032d1a2786871781bcc9f08632251579c196b3993162c7a0db8291e5b06454f45cec378d36f5b5b6c342c6bd936eb286201fedaa8129e6cf6befbdea84b01fb653b10c6d36445429fd0e29878479a911b488a03bae8b30a9eb1c933f482fd066a33a46e0c0ae1a593064c0ef568994cb3d16085e3a49731e039ea37e400667576f1a06b6954052eff50abe59ff90d172c5eff6e04ef5fd185aa7830a3d819cd4d57031dc491815ebc2e18f306988e21f8707791c3448fecac276f89c89821dfb1983ab3087095ccd42b9ab114f64d613accadaacccfca4b57afa2a3e4a21fb2b4231936ebf6746e4805c555a6c6041cef8d90c3d5f6f12fd4585fe1bc5745ad5c29a395918c9e52f0c1ec55d41e76a947871b85f4f0dd769b12f9eebbb073b2842636b944bd7414b114957c00b615311921f511295a5fb334a77cb7f8768946faa6c00e98c1dea65ec9d7aac487ef917f4cf5cf785ee7dace6bbacb7484957cad1982d7c230ad1be62c2ef3ced8c994a704063348815fb54daac5ec9cab57963e8dc29f5054cc0c1626df56fc22400029b58239147a85d171562ab8780f64d1858870ce28b6060d6104a8c26d4fd78700ae11638236bce92ecdbd7e9
+TAG: f5fd3668d52f4c82278d94e9728c45e0
+
diff --git a/src/crypto/cipher/test/rc4_sha1_ssl3_tests.txt b/src/crypto/cipher/test/rc4_sha1_ssl3_tests.txt
new file mode 100644
index 0000000..721cef9
--- /dev/null
+++ b/src/crypto/cipher/test/rc4_sha1_ssl3_tests.txt
@@ -0,0 +1,808 @@
+# Generated by
+# go run make_legacy_aead_tests.go -cipher rc4 -mac sha1 -ssl3
+#
+# Note: aead_test's input format splits the ciphertext and tag positions of the sealed
+# input. But these legacy AEADs are MAC-then-encrypt and may include padding, so this
+# split isn't meaningful. The unencrypted MAC is included in the 'DIGEST' tag above
+# each test case.
+
+# DIGEST: 095a8f557f75cba8e2452ddf97c053904b48827f
+KEY: 18cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481d
+NONCE:
+IN:
+AD: 936a91d0b5d2c02672
+CT:
+TAG: 42fbfab0ff2cf9938a29b79c5bf289aac6db2da7
+
+# DIGEST: 4a7464217ea94d95668d31736693ae851eb0e39a
+KEY: 171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa2
+NONCE:
+IN: 936a91d0b5
+AD: d2c0267218cb7090c6
+CT: ed6c876469
+TAG: 3d3149ef83ac555271dce4ce450cc31d3bb32de4
+
+# DIGEST: f1efd4c11318f4558eb4a50d5a5b9b1e540f6dfc
+KEY: b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd8
+NONCE:
+IN: 936a91d0b5d2c0267218
+AD: cb7090c6171386d641
+CT: afadafe409fde84f8901
+TAG: ec20aef4350ebea1cbcf910e74a0e0e62ab419ce
+
+# DIGEST: 995341bee01fb91132d1af8394401144a35bd965
+KEY: e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8e
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c617
+AD: 1386d641b87797b684
+CT: 8358512e9cc1143dcdd908479e4129
+TAG: d765825aa1e1f1430046369c64831742ba458a5c
+
+# DIGEST: 73dc06657c34ffcc71e6662ec0a52aa7168c22e0
+KEY: 3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b8
+AD: 7797b684e0fb56f97c
+CT: 2c53873f0e02a70437eeff275623bdcc0d0d4533
+TAG: 4a0a14ce7b5ea1305637f7691d988aae655ebe01
+
+# DIGEST: 6a5e3024f92e29f8f3e294f87fb25572c0390dd1
+KEY: 2993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0
+AD: fb56f97c3961d8afa2
+CT: 33b31a7663a04d4819138b9afc9e8bbd3e8d9651489da70383
+TAG: 3c0fd00f8a839c739a168b90d21f16671819d3b6
+
+# DIGEST: 6f192a6acc2fed00007506adeb1dd454e2e92809
+KEY: b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e0
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c39
+AD: 61d8afa22993a340b9
+CT: 67df387e73f7050286e6f7fede0ff98880d03cf0348a0b09b0f392f3f4bb
+TAG: 65a63d2f42a842cc6387c149339d8034b78eb7d8
+
+# DIGEST: 7faa4d4ec92841e45297553097f2ac2ca53d2592
+KEY: 1df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa229
+AD: 93a340b9b3c589c748
+CT: 14a1af0b3ca2bbbfe6b61d0d13352e422cbc46a616542047b9562c5edd0d20b8ef4993
+TAG: 5ba5731267366f041998a50a635b3b7062f416fa
+
+# DIGEST: d6cf3a4fe57328e885cb10cc7088e0562c7f91b3
+KEY: a23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3
+AD: c589c7481df3f4183a
+CT: b791f1701e00cf2ab51cc341c3b142194cc15a67ba1bfdc09e0e6963bbc1eee11d47170810dd7a21
+TAG: cb883e2debf80c04e09af2c6e2576398ccfdbba5
+
+# DIGEST: a2ba1bff3a6dc3ffa8c405fb8f69c41ce7c1a1f5
+KEY: d88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481d
+AD: f3f4183aa23fd8d7ef
+CT: 1240c27d9d132ebd3f6ecd644edf5c2b9385bee1099d3ecb5e33ef7a10cbac2ea8c05537180371f2378d38fa5a
+TAG: 4813fb143d05567bcc75cbbb5551fd944bdfceac
+
+# DIGEST: e2825275a794df011a9dd0c6061de3a9eb2efd48
+KEY: 8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b4369
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa2
+AD: 3fd8d7efd88503f78b
+CT: a5873808917d9b452bf13878e1c8fbe06ad063206b8b75a4754032a7d2e9e8c97571f5eee1bdae8550fecc97cb5e85ec3e70
+TAG: 4e38aaba4320b6ad874c24616414428bad95c56e
+
+# DIGEST: ab656533e45e90a45a508392ce59ab9bbcac27c2
+KEY: 2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd8
+AD: 8503f78b8ed1c8e9ba
+CT: aa5d4eb24a28527149552be0864fced97736994382efa76742c1bc1df8af3c571c27b65f01a742d8e93f14584645f66414cfc4a2a8f54d
+TAG: 980e3e5a6f8e4fc370990d813a4d1d3cb40b8c42
+
+# DIGEST: 0614460f6ee128d42ae79b1dda518a0f0e4d0d16
+KEY: 0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8e
+AD: d1c8e9ba2fd6773e0d
+CT: 963b25bc57f4ff2161ebe8e13250e1b19500eb467300cbd7d7d240a31746436c5a64ab1874f57cf9205582a364f1486b17e4420112a3a9adbf6824e6
+TAG: 9f7c325e93edde164eb3acf739b9097ad5f9b495
+
+# DIGEST: 629525ee366d420f18c6a88fa3a8cfecaa1331f9
+KEY: e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7d
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2f
+AD: d6773e0d0c302a5f47
+CT: d2f611885eef206fc73f346611e61a9c38b9f67dbecb14799ce7c2395ae6e89d1a2debb319b68ee7006c884b9b98ad3af15709b9d1b2e176b308f399f74107fcaf
+TAG: 96604f07b8ccea9a830db6845f887197bcc9a471
+
+# DIGEST: 79b26abc71e1670444167ecf48e093d505678371
+KEY: 91d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c
+AD: 302a5f47e037446f58
+CT: f526da150e339a1527a325b217f86afc12e34936aa98f487fd754b27dd2997b208bdef456ab2f8029c47dadd0e0c565043db169c632aa166551bf8475aac497578efaa493b21
+TAG: c06d88653796f1965b07d0ac8d17ba0fdd3d3483
+
+# DIGEST: 6cd5a6f762364b9814deb6e1cfba1eae5b0f31d3
+KEY: ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e0
+AD: 37446f5891d77df660
+CT: eaa157a1a45054c9496d70ea9429071763e65fec4e03808041f569affc6fa6a818a857135e80d67cec5ece259fc33535db2106b2b16f75880f39b9326d4d1419d8eb1e7b3c9b0c620830e2
+TAG: 4951455ca46f1d3c2f9b6e6fe70adffa9a77c8f8
+
+# DIGEST: 2d3f449046b625672e740920da76e6cb0b297236
+KEY: be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891
+AD: d77df660ed82933f62
+CT: 7112394937353fb4362b8d974895296c596eaffd68d4702a280273a01c0fd8218a58556d1afc8ef9baf09c2e257c4194b13335d2bd6edf5ff52c8113ab663532b987f51de94372efdf55c2eef73c6716
+TAG: 169a37f0d0fcb9ab7211adfce3e06884fa925147
+
+# DIGEST: f321845e9752dd4bbc414648274459099c9e5574
+KEY: 6965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a7
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed
+AD: 82933f62be8dc55b43
+CT: 7a38a3cec5b13fb9918f69a4ae4656ab16da1c5f23d7e89540f7eac98103d616c19da4b6c37a012dc4ae0f84292b1c1e017fef186547c618d4705be66f054acabe0ac48d6e836ce899374e3d68f49df31e11efa466
+TAG: 5cb7b3345741a8473477735b6ba91a519081a163
+
+# DIGEST: da9868a42a40dc263e0a0fe4247ee859569d7f63
+KEY: 7e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54e
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be
+AD: 8dc55b436965aabe47
+CT: d996a7ceefe76cbdf83bf2bf707067eb22579d7aee99464184e78a9eeb10c9d47b76de9621a8f728ef4f90beefec0be8a36cf2c1c679d158a484d43902b543e31920359aafd51bc47b622c01a98463ec0471c5bda7040d654f2a
+TAG: 8939720762240273631ac9dcd7a2227ec5ba1c98
+
+# DIGEST: a17d268f79216e57050079ed4a85ce137f83cf5e
+KEY: 99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be90
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b4369
+AD: 65aabe477e0cdd46be
+CT: b8058f25f9fd11c1ebdf5570d5e18cf96d768abdd979250fcb87c97f30f508ae2115f99ef088328bed753ec571a3158f4e83d50639b340af020d5d9fe9a913dccb3e9818d497470cb51e6dd696506ae350b89fc023d9fddcf2fa9860f1f703
+TAG: 1de8ddec0c43310fdb052e7884b94da86a5f3404
+
+# DIGEST: 44ba8d9c06c6788865a1dd76287a443eb0c22aa0
+KEY: 7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5d
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e
+AD: 0cdd46be99371eb8da
+CT: 90cae6bf042b86fe5a3762e829532395c884c5410b02cf4237cae91cbb460ab4e85ea3acde6b0ca76c878d950510b78d36b8fa4a7ac2b018b8be08e3145694667e966a3b4b18109a62f8c8a35fa922a52c1b14d72f23693fbe4777b435587240eba5ad52
+TAG: 7e520549bb7d8515ea5e6b9b30e4ef3337d6afdc
+
+# DIGEST: 5b0d95d9ca1dc4d0ccd940d38881b8864757c9d2
+KEY: fd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+AD: 371eb8da7dac997dea
+CT: 79c97c6bd427bcf073edbe6d522fe077ad8a7bcb44f4767f6d4d84ec057ad21f30e7abb6a600907905c57a405bdc68627a2cc2dc4a0f942c3f83bc59fe0320587b211f3831c1207949ae295a350e8166c433579b8b794b039ba60ea8194532fe742dd89555cefea263
+TAG: be903f4aa6afcdc0e05ee39e160c8723de43684a
+
+# DIGEST: 310801f266e960f886f9a02cc9e8adaead89dd29
+KEY: de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae0
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7d
+AD: ac997deafd64b1fc65
+CT: d97f0b75e910efb5a9fe90bff3d1986e7fcc4a620ad8dc9a811ce6148ea1f10a427a9280a8bc4fda4580c5a045b8df85f2da6668af09386692e1e721645890c328f718bba7a00c78b3ab9ffac115df353dc00e0e7892d736e8f152ea2ecdd80350e01161a2c14ff713066088775d
+TAG: 799ed401e99d3ab54616dc8f2e0affa8109c3e27
+
+# DIGEST: f6998ed9b090ceb8422100ff91e5e2671a49d980
+KEY: 41a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd
+AD: 64b1fc65de39f4f035
+CT: f59fcaab6e1c62614e12ccac2430bcf5ab87954b4c678940cf64f442cb4e56126fe39bf25769b5622c3da73b44e57d977e9826500a33c5f48598cf4a264381954ec94a94ff2e1b1585e07f1bde18c5062be474cbd09966d14ff8c27a56b85b489fc4240614152ddbca10dc28afe154b8c7c5b8
+TAG: a2612eb4ca3f51b7d4ea2e1c63ba0e4a133642a0
+
+# DIGEST: af2873f1a7fcd4930f1c8a554ff271c5ee9185ce
+KEY: a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de
+AD: 39f4f03541a11be112
+CT: bb149d8dfc97403a5c1be9655adb17cfd8fe9458a5f7c296fcbba583f6dead58f135138d5965c9ec489481544b8c42ad5f8fa10fc129e6f49a1fb9be75fdac724f65a489e26a5adac60e073cafff429900aab079d83e417760349970c86ab37da5547b5f3f22a3a620207b3cc9f255a79767a5e22971d8a5
+TAG: 4e97b22ac0ccca468463616230a8b54cba66eb47
+
+# DIGEST: c4eaa1d6c4d2d5a8d2f4d96890bd0299f1d699d8
+KEY: 4ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541
+AD: a11be112a72933c7b5
+CT: c2bf3eb1f2d87005fab2a16ec21c0678b66b57c28ca20d413aed6c50a26ac1af6272c80983d1e9348573af84a38de9f47cc8358df2f70d4fbda7ece428b07e8ebf94cffd6e82923bce263cbc3d6a44090894922a565a7401189677a3da7b359658bd24e20d7199a1822a527a5e916b7ec85eb5aa3b368b63108eccc4ff
+TAG: 25d775b8c7063c627e4e4b540c48d250d7029f5d
+
+# DIGEST: e9bb0964e1cb09fde5e8f852937c4d8e1605b714
+KEY: 905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a7
+AD: 2933c7b54ed4fad0be
+CT: 6457026b23b8d31afba224c866688051a8132973e4cb97e017fe4ffcbce63acc177e3f2100c33adaec1d09b96a3c6ae96c8c90df697d322f3301b01fdfc2703b59a25944b9bbd2cce2a56ab1dc120e2fb2c906a986d306636564c5eee7f7f06dc74f4b45c208018cedb9a9643d85506d2f35781fbadf3dc1dfe17ab3126a062ddf81
+TAG: 4920fc1354c9cf60ca78d39e55041b8b5e5ac58a
+
+# DIGEST: 659746de28fff60cf3bcaa07eb7a95c5b7d3200a
+KEY: 5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb0
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54e
+AD: d4fad0be905d41203f
+CT: 2cbfe55d182b1e32997a9bc15756076fce0d74074fe3d6de95465010710fb6e48f272093d989c1b382a2d1457817b905269e4158b65a824dfde9d5142849367231611eebd767b09d2edd87db86c9eec8f6e4be7f271708553faf9b8ee8b8edd8b669690e93415e78e3227922d041e4a9cbb19f2db23cc5bf5e444daa8ac99bbc238dfeee3f0eea
+TAG: f4ce57f86096bf2aa2e904666213669050e8eaf2
+
+# DIGEST: 170202dac332954785ff6f866f165ca62510d9bb
+KEY: b2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d617
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be90
+AD: 5d41203f5dce998f8f
+CT: 15ecdbdf769134ff174f8473a8fc1f8119c0a7499c7d5adf339f8a2f23c54ff2f07e8002344fc9867bd5345d83f148a8a3693a7217232a98de92b7ce2a6702893bd1ef9d3efa734d501253e8af0cd20251fbad552b4b1f59e52b4b1a138ac89d2e6027dcbd004ed8e2b23629fc5de4ae1894987fc35693a300244aee525d3ae0b68fa40f1178f82b9c08ecfd
+TAG: ec4889ddbf5879bc74cd40989dfb8b68143b7b9e
+
+# DIGEST: 767d4f588b55b2593cfbdc46acc6064616f75c2a
+KEY: e02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b7
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5d
+AD: ce998f8fb2eaad409a
+CT: e0eb36831cc90b2739671bc583b7bb0dabf12de5d45b478d4eab1ff25b158c52bfa83a79d0f1581b2a7c7628405255d678a721c6db44ce8f053eac595b3ad3d0658fd93f7775ad2f02d532e0fb9ad7498746e3e105d165b22fd776e93f2738fea93e82bc3e456488b07b683f59ded5e0b4c4e3c6382c31c215598ba1464c8d6254071a0c0faadea8c248480a5340bf0166
+TAG: f9a4cd990a3998752d06f9193521a04bea771798
+
+# DIGEST: 27937a84ae455678a2f3c73b523d600135e6dcdf
+KEY: ae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2
+AD: eaad409ae02116417d
+CT: f47fe2f0ab38d33a0be222fc035d8e0271af0945cd8d7b2075a645ce9b0e10dd32a7b35a320e904f28086300f6c63b9984064cdd3a1e945e4b09e521f8a7addc781c8c206698902e6c30e202b7045d3a2233b8981aa16ec36bc568ab4688b08e5b0402f9781b4e843b40361b79db0064e141566f6df0301a2fdab3efcb32aae0aba0bf7d1317ab061e37118f59f46377c9ea521d3e10
+TAG: 40da6a2b16aa3a61ea5c56ac229692a754342883
+
+# DIGEST: b1c534558a6ecb0ea225369be47ddfe669190d41
+KEY: 9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae0
+AD: 2116417dae0cef457b
+CT: 073434fd77c0f06a1ce257d9988a28da439c05efe00c28e89c45a5cb0606334c7a34bef33687dbb559d33cf2cc60c23cd217ce1a56ad5ac995141b5ef5d7308ebb30634e74d37bd9fb1bff082a1c718b7e811ff5c0dbee2acfa35a26899cf4749e1d4e2d7e04f795ac4c73b5f00c09e06f098725dfbeea62385deea4096d27e4f5806810742dac6c73906ad454640c574e9b63ed2d810add0f34b0
+TAG: 827ea5384c132bba74c199b40af774aecb95263a
+
+# DIGEST: 774dbbcae39eaf44fc300eb00977f4e56e4dc0d6
+KEY: b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae
+AD: 0cef457b9e5e16dcc5
+CT: 28a3dfcd210589857c4d4040ff61e2d0f50a944a9ffc7443ce5721ca5416b84c90aa4c05ecdacd746021b711ce44a256713ffdaf31e33baec23e9d88bdbba99ac83ecacdcad09f482a6ea3a6ba75f7ae65ba8e0d429bb03c4394194c51e55e66966db37d0347d0a5b7aee2e1dc23ec90775e32193a739335106074fb3ad65a6154047cbd4341933e6954f0b7d0392198bc46faf0d66c5e270d165909573646d3
+TAG: 710469ca411535dad3c7d49e507a0ea46a7e9afb
+
+# DIGEST: 5c6b13d8f7e9f764136921bf62cf406b9dcc8615
+KEY: 0d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcf
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e
+AD: 5e16dcc5b6f25607f0
+CT: 5b447b16aa964e8abe9f6087d40a746019ca109e99ec78b7166484a497d8e829faed1bfbd9c08f6acab94f86d565c5845174a4634901da38aab27151752320c6b81e71e68092d49619b4b99427823868429f00d2fcd93105a4f151011457a7c8dd82f90a3002994e131b3dec06d0e4c84b0f24f3ee5769830ab949dbb6b6cbf1df468369c1f0614bbe0593135a3d3762bedf0367bd7990104cb9c171534bc00d92750eeb25
+TAG: 51cdcd24acafbddcdcc4bcf30eff1dbf4151d2ac
+
+# DIGEST: b72799f51e711da0ea2528a5125a994e33078898
+KEY: b09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b5
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6
+AD: f25607f00d033fb95f
+CT: 18d86aa0539057971974e72a1b6f06f43e45cb7a5ac20d59cb88e3b952002ecfa4593a2787ff68a38fb386d4dd06da29cad8f5e9c7f1fab4878f2e92becc45a58b3948b7f5c0d0245f957bcfc393b07a16f9180e109e4e3e2090a7b2078e29d54c59ddd718b76cab59584864c8dc2c840e90b0a5909d230cf44cf18ebd72c70eabffa0ecc1bf6c73ddafee3f55ba13cecacba7663b08fcf5f149eb5fe359a197b495722d8b2737f48ad9
+TAG: 7089cd9d3ca5bf31ec1c3dd5d50f26c14323c3c8
+
+# DIGEST: c2c932a2159da6861262e601fe835e4feb139fc6
+KEY: 172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d
+AD: 033fb95fb09e4d00d6
+CT: 5aabc651eca00fb77235fb54818c06a7f4fd19e4bb00844b3ca3f705dd22fcace922f2ac4509af9c72ff2ed068556962f936759d56d726db65e149e7e4e362d771512ad9d3bde7388f53e69d813a8afd4e5accb77d9024b4fefd86b6a32d8c455d7edafe8f897aa08069d7345371bd46bece90dd9f82da5233a3cea5bad59a8b8859290f786223e83b57136a3de0c2da7fbc4483634ef9b0e7b026d07ad86f3184520ca49b04f38f170006a7e35805
+TAG: 4b5088aa10d6c4bde1165ae11b0b5c17bfa050a1
+
+# DIGEST: 25b40da26cc2da8afe980d0287004507d92a426d
+KEY: b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb0
+AD: 9e4d00d6172e780ab8
+CT: 68b82ca866d62315e0870a3e86dfa8357e704b0d53243cc058f31281622dc63e304032135fa43c4973f183c7d7999b496cb6ff4fdf8370ed45e82b6ff897f32b7abfe80e9193ddb74916103085e18fd6d84981714299fda6a6d8851e7af73921b02f71eae96c45497525636b6b093705db1e614b1ff594d6e28ba0a239fbb1078fe0dd76777669f780f0f4d79bd13aa3b0cd1b1da66e05112349413f03219ac50759f4186b2f20ce9831914d8d0ecd851777b7e3
+TAG: 2d963c2535e0c3ed74cf97d26a039fdddb78c1e8
+
+# DIGEST: 2b6449832e28e0f08469119a61c6119ecaf747be
+KEY: 7a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad24639
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d617
+AD: 2e780ab8b700433a95
+CT: bf0ad57d9488771a3325336c8fadb2c7d07f659408a72368385d8324c39c25d26af60252fa83ffc831934d6eb6107fba199352fb7f308abaff306b1e2e77e9b8ca8b7138a481a703e6289f1b3c1045f012749ad5692706d6f6c1a8c086062bf728a0277c79d5a14b7d36fdd2d26e7761b82a57319c93c6df34b93a216065fa5cb79273826503be96ad60f7799c02995e2227d26b5f2c93e5897a8adf4b4ead6504389a9ff18c0b42b8684b98ba7e9fed8a6a01afaed53f3d96
+TAG: 9ad5ed93f2e952f0b1462348a84e2ddf00f6d76d
+
+# DIGEST: 4e2f1dae39e30675c6b32f427ca47ce502a02191
+KEY: 0f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce9
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b7
+AD: 00433a957a741c9eb8
+CT: af7a08349525d2d24d992f3c0fe725bfe8fe896e0c7acc5ad581a7976995588745714ac772e7afc9ab916f86eb189ec68d9b2c492be6fbb7378cdb8b226d09d5e2ab7e59ef063c99c8684217928254db72050aadcfc5883acdc566fbfb69b248b4c5e5425dab7521dc30ab220751d31d1165cf81059e6ec5aeb8d0c74c712e33d895148fc120669b26ba00b00044d4d6db7177ad44a62c893826c5d654cb710d4bd3fedca0523e3f42f290babd110d9706aab3495827952e3f0836ea7aff
+TAG: da1b91d5d06e1475b86b48b439a5157e8d80c722
+
+# DIGEST: 4b779331c327101cda11bbea17702561aa8a410d
+KEY: 44769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a
+AD: 741c9eb80f2b021b14
+CT: 80a9f55c17c62102d6823fcd318277941ae57469811e2bdd5949b705960917a4bcc5915821a49a1da23cc5fbc1b047d414d0dffadfdd820ed280d92e9fa22d38e5134d1a2f8e3b5ed3a3a37219ffe0b1dc4de0d57607fdff522765a1c23c480a904bfa425379ff7383b38c8cda62ced5ebba17db593c6e69bda0a9c8b6dd72e38b4b4c98e4984082162cbd7718150ccc8edfed0486777f1dcac67bd7ea4cf3d44e40b450976378c4d04b7f36ac3410368cd4bf530c32f1900a732a71d9ff8685aa9992
+TAG: 8d78b133054797ccbfa8c04f2d98627e1bce622e
+
+# DIGEST: 708364fadfaaf52792bc2fe5bdaabcf986af7aa9
+KEY: cfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffd
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f
+AD: 2b021b1444769da00f
+CT: d9dd3e151f466b7969f73801eea0fae7cd8427c7b39587ebaa22ea80c5c40ed42fd9d189a6c7c55f9ef3129739a728c0af7e0b37f891af7cbe7ad83526b6be3dd1dc9efb30656e5298638a6baf3719f78a0b4274c9d8ecec4326055ebd33054e504c73bc0e68fde6dc64f69576a04ff87971b520d905d2df6bdc2a2eb54642c301a88d305a30d7d0d42e731aa67c06da64180f9b6206ec0c7ef7cca074ebcf22f0ec4fc1f722a425e8a08d57dcc007cdfd9164de3a5c4a99e2285327e6a0b0bc84cbd2e3549a39f4
+TAG: 06f1a5f262325ef0465342fea679747930bfdf27
+
+# DIGEST: 335c241743268f08b03aa63abf9642360d22a112
+KEY: b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f4196324
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444
+AD: 769da00fcfab0f5f93
+CT: f448369ddf6afc246731ec01667b19ecf0534392c76e7848385f51d187253ba1acd2b3ccf8cba66f2ba90e25a2b999748dbcc4a6e0575f565d38a4ca6326276a7f5dc51c6007c3491b017d7e127a31633d00ca3f01909b607d74f27dffd4c67c5860f3b18754211b5bc719f4780841d224203c3de44104b65deaae2559e6ee3d5ed6c6657be351ef2a1791d28a149af7061c4d9c7ff991f0c35b87681208d8763f6158142c7c50e50a0c516c74a00f94bfb0663f8cb85e62ad9e4748f45f2fb14f12ba58e45082b1a487655ed2
+TAG: 14427e3d291b4eb36a87c0a5b3b6e61e18ece0d7
+
+# DIGEST: ae61ce3c2b1475f8afdfb1be68addaaeb6489356
+KEY: 5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcf
+AD: ab0f5f93b511060c9c
+CT: 20c99f6edec4a13ff93b43fa6e52daff5f6b83cd295cd6bc560c70def9b8eb7ab27f17e4ebf28479a786fdac80ceb057f45737548998ebbf9bb2917da086bf29a4178c49654d73d0ca98091b4dc618a7903d7771f6bee7a81d7f63894afacabd8af32a5dbf748a51960a33c6c8ba8378e4a76054228d5a639eebd60283d9aae75c531e48c7c2518b788b3440ce72d99bb8e86a92c802d6ec00002fa0b5e7fbb7c22809362bfa7027134e7ab0f978d7b5f1ed4bca13bae97ed24a76a4216e59cc72af58d1ff27a0ba3b68548ac6d44948b42e
+TAG: 5562283769aad26a812585074b329a403444fd65
+
+# DIGEST: dc6621d897775dba7bacf8b7f82bac003e984b00
+KEY: 1b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c0
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b5
+AD: 11060c9c5f3aacefe6
+CT: 21629876afb14f4694e49898c5af7fbdaaf96c2b7871094d1f3d55d8d903d2205422e7514662d15020366c41b5422110a0f84a8d2577c79df4e664e68d79f19c71c63d2190b7b8756a8bb05cada3f7f5925a67906b6f93f3349eb1502005fd9d123e07df3f423d5e5ac97a52ddccab3fe8191a7a1896356d49eafe67c18a2fb32745a3e0f6776bcfcb51e0027812c222eb2da4451bb9f218fda14b5d078e89873b1a09866814ba4a0adf542d0a0e578e6a39d5dd783626b5d1795581f4b11b46271eae7e1c5b02fd4f21d6238ee417c75a35735358c324
+TAG: ad3eb8bde9d6af53dc3803b3f40511fce6a4be5a
+
+# DIGEST: d2e6d3eeb6b5565d9a407fb96c74b8b3be42e64e
+KEY: 3939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f
+AD: 3aacefe61b184ad246
+CT: de8061ea3b9408e5ba06c5919388b3525f9e9b11021d2554006246765a977e5bb90a9e89c4cb32b3ad2d03e47b34a36189c2aacb0dfa0746e1eab2d806eed3310887d60e12f7c8de5cd5501e6564cb0bada4e6ccbcdc16fbfce9aeff7c41c02d9ab333cc811f0295b87df0714129799a7de0ab4727a19e145fa6afac3eae1740a8f877bc3ba69f4cd212d6cb028d7aa869ee22572b65fc76bb0a64d32ccb63ad238abd6387fd4af1a9c770b460bd3cdacab4e6b98330daeab2f852a898211a13a2550ea041c1a1b9b00675616281a0275c1f9faa4ef23aac2bef19aa
+TAG: 20dc918aa66561341910b033a15505b94128b0a7
+
+# DIGEST: 238d50a0695b1f255d5b3944c623876919f9cc6f
+KEY: e97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a02
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b
+AD: 184ad2463939ed518c
+CT: aab52e8bee8a90959cc84dd9477751f0725be7adb366f321f415552458918b40a96d39c3a43ebc64fe0d6bd3efdc4ec8654a6fddec81208ab57cf3d29cb563c743cbd9e110d8151016a27e5eb86285231ee4c79c5a15fbbc2d05daa96f6b06d542e05b9fcaf164b822e10b311013ef038399e09b696a1697a14069c30d9b6db4bbdd866431d912f2b84a231ca84cdb4e7d8160268425412eac641a92afb9d47231fd802a663bc8a42031564086615388ad2794d30b4c16c6370a75e7488d00234d1da69d64a740b3f0f682e95ab99a0271a448a240d11d80c6953dfddedd2e3563
+TAG: 676d003572059bada08be97c20260f7afb1da0bb
+
+# DIGEST: 562090fcf982854158b6068786792d26d2af3cb4
+KEY: 3d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad24639
+AD: 39ed518ce97c3fdd29
+CT: 59b348edd30bfa86e0f4662ffe5351727e98a1942877a1079edb5cec4fa811a06f871f023b7249bee23b2e8708acc776c5c88b449946bc1f4d17f31f0f78598e3b2de5a667555313b9ce4494b53eb2b2938c0533c49498a8455281769c84d94fffb69f5a7061a095705f1f767b649be854168f8e058d17699b5798007f0f92e36a2aff459591b93c4d712364e7fdf32c080a212783c09ba2a6ac6b68b818e08b2c6012f7234af899dcf1958cae498ee42b6e9107bfc702b190d04fb3db4611eb9602ea88a33efab569228e7cdc883a91bc695739754ea69013e6316b75a7695835a6fd4cb6f9
+TAG: 1c78c2dff285189eb60609d74a4fe9dc951c2738
+
+# DIGEST: 0c2eff5f73e4ec6371200ea4e3ed600ca22116cf
+KEY: fdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e9
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce9
+AD: 7c3fdd293d72afc09f
+CT: 380373d3a8dd1460b75f7b809ebf51d0d1fa55c0d434fc23af1898d13539fb8abb17dfaefb892b7efc7c005738599138da7f2501d6ad4591647b655add97c2af2384a633ba6dfad3b7b1d2e072df58db461ed5e147d3b456591f0c0a344c7d3b557e074208eca098da866f42244fd18823da188cbbbb42f935d11b5d3f7d6ab0f32bd35c8a6ecb816c98e7dd00c55960ec258756c478e501688200970728340517f59c8e5ca0b77ac6e054be4647a923eff729a149732ea3e875017ba945613b5e956646105739851f67c829fe8dffb850b29ff9313e9368805b3c8ef5a6d62acfa58032351608882caeb6
+TAG: f681b209cc7fbc6b902145d750dbd08d8a07c273
+
+# DIGEST: 7e81f0c3bb2f9c2073120134be9d0b1d0521989a
+KEY: 249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3b
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d
+AD: 72afc09ffdd4f41963
+CT: d22a45b6b6dff4c4a9b362d7c1e3b21d4d3364cd65d17ff37241ee0f2d89333964da9357f5f4228df3b7778f8fc64b8c5b2ed2c7f60e1fd67cc58843e3aac3f80052ade2a901315b56260e7b18004d2cc4c730d7d7a0b128b87e2fd0e910211e3f8ecfa97488344f1bfcad735c32b52dcabb3d9fd821a329a6515b1241002e61fa1400b672d76139cc56c0660af0de5179056b52286a1237ffaddd51be34e2cbffc4307f07682b10e8fa109cc87b5ced99a97fdb633279d609bb9c11b5f96039208eca672eb7bab4c54e66db69d8e0ce558c9a0e83a53da005131a53765e771b0c1bdd0121f5c5e4aadb9edadca2329b
+TAG: da8484093b25e78f7090d8a4298404cfd5858b2b
+
+# DIGEST: 28a454911a3ce17c0248d2f535f4073b6b092f6e
+KEY: 2e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2a
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffd
+AD: d4f41963249cd299b9
+CT: 943b5845b33812ba7610e75aeaf5ea38268324cd6fac2e9275795fdaa1a6df50d6acb3dc4c9dcbf6625865859697a27fd6b1ad418e4f184f074692f6faa13e795701d33a3b8f5fe8bd6fb36e4c852fafdeee63122e0150468cb37680670f5b8b3c9a86f4eafbb106857d527708d1f20b6114ce19feba607dab8755ef7707b8bdc9e9f71e40e6c099c6790a5cc5c30b0a45c94de1743cb5da7ef11d0a180042dbfb1595d144f28e3b1f431ebad15af77b325d8944e5e61a58c6f6234a7ad2be1cf18a1e7453f6e348adf330447205b3bf8d148c63441d681bf7bae17755a3d797ac03dc81df899548ead0ea413a6a99c7ec07021312
+TAG: 2b7b6000232312ed6bfbc04983d32d46e67a1dc3
+
+# DIGEST: 179d0ff2661ea9bbc7a42df1b3368bd48c176a91
+KEY: c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f4196324
+AD: 9cd299b92e55ca24d8
+CT: 8ff112e1de1d8baac5be35dd75ed7099f5ae24ab0b01984daaf7c69c0b35b1038316adb4a6029af6363ccf4232875f2712fa9d91012a0e9b37606cb2051815697f3e020836f46cab240a27472561ef14fb0a85924802d1e991e80aacd149d8f93aba358d5024e412f7ee6b30fd67cc17dfa3e9219097768ca438b150cf83d28b25bf53795a8d519c0e43dc9ae7b732a25e6391236770897085e9e10c4278fcde2c3958b89438c0dc085fed9159f17ad74fee72d6e0c5a43818fdf2c246ba781b7a47b13cca182869a6daed98eea4e1b868b9f0f4a7a482d5066cd6165c769369b2261529bb97424e3a3a75208d5dab9bb38ca5d9eb1deef6af24
+TAG: 0e5bd44a1df7664162d7e2c696e52cbe1aa58fe6
+
+# DIGEST: 35f3568ac38767bbb0464106b32622a101523d0f
+KEY: c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e
+AD: 55ca24d8c078c49f78
+CT: d13d3a49ff50b3755d46a272e3819f68b98d4c668648301c5ab4d0fe1f477940c3318bde05090f14ca3832af2a6ca4a60221751d2555715184c8df8d67c5d17a052b8b375dbe5b63e68cbcb230fd36b0d9321d72c61377567a47d7d65064b4826bd130f949544edad567b6f12314fb7b807d9d7fe109607b40928aa798bbbba9ff19ae362ed6faaf42cd6b7df0bdb8cc0e39b650a78bdf13b378e641ba4c86f8a52d6e4cde61b337e5112f64a57b5020962689ca4c8173f17f8e8c627476d1fb3118d5be44abe7247eaa0b2fe4b1494c43231a2ae87f14271e6b956f0da89aafad9f008d0d25f174ef82b96afc4f1ada9694c033101bcc5e62e8d3f6b41450
+TAG: eeee908d29c6ec4293c0d6bc61447a21c2f21447
+
+# DIGEST: 720ba4f4eaf71a85873c01a80fcbcea419d22ce5
+KEY: 025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c0
+AD: 78c49f78c7e713710a
+CT: c6aab34bf5ff64abb221ce84bf690040486c03321d898f228b34cc3fda44e6df1486f06284fe53eafa3f9b16a0d07db924ce911381903bd941f5b1e3b7069f3648cd44d6275919493eb36a9ce960e208f7d2464275fc7ab0fcc45d4528b9487bb22326741b9ab517a7aa412cd6cd4ad5bcb217d39cce252449c9a59121cba8c714bd3f16c3228b563f3a5a588da12364cb5c1db0821763a04309e97e243fe869c836897794bb67af25c86e2546e63a28fc3b90c3af5eedb41c6785e8318ef82b429369d088e9328bfdaba0621c4247e181cb44ee5001a540ccee570e47deaa6563add91ce9bdb3fcf8e409bda66ee5b545d9b767a7913255c188a2cf038619e4d197f942
+TAG: 2b3704e284c3a0fad20b6d2654e7cc2fc6bbd951
+
+# DIGEST: e531dc2be28c8985a08dc53ed098457cca032116
+KEY: 1d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7
+AD: e713710a025cb8b9d7
+CT: d4c81d32d0dd6fd40a7892442921d27b98bdb7a6cf32101b0d062c31877074c73880d932404000e83c8f65a1a027f21409353bdef852f8acb87713f2effc0cab743831dc011e2c82826c3177af759a0027f57d1b0bb3ab487ffa4ea9763d1db5a7d41ce249ef878b54af845fc63a83497c102b87f21ec8b589864ce758f53127af36e4d006eedb9fa76da0a7c23c8056e2832dc41e73580f10f5c1b57b5bff2ca23e22c5c193014a885c36d5535b1d4e7215e5568a1c0cb4dd9f982c6c1847d0bececa0d19567d0319878d2925f88d1b965cd016707e55ab27b54532a7360d4112f472a7ccdde4892aba35e42caa523fb88aa2f5a33ba0502360ac5d52f615b3533b1e4ab6ceb66372
+TAG: 21b3c2757288507ea67239422287f67675273011
+
+# DIGEST: 87828be40716e1acb0ce876660045cef3bbbda49
+KEY: e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c0
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a02
+AD: 5cb8b9d71d2989ab33
+CT: 680f456751cca408e19342cac26668b49b89e0d8311b95309f4377bb45cdfa8c9268f9cfea547f114c7c6626a3de37fa75a80b3ca1bb1edfecc1f628432dfb459cb6a7cadce0f90e402185f28b328587c13ef3d1992eba37cb46252fb424cbea94a766a906017ff49bd0d360e30e25247b912b70b81964d1347a1de0bbdeda7a76866201ed728f369e0866a84fb9fa8956d31ee5cfeac115ea6ccc587120599ee7bccaadf5217b09d14deb6406e234bbdd9d294dd71df01db3a7762d44eacc9c0c1218398cfc68c45146a8d8d3416d55bb5628c83427d8dcd0252739247d147efcc737c725a11363b1e29acd13677dec3ff27e6406e3978db82bc11e232163d047ea0556a84cba9bf194002b5794
+TAG: 8977b63942a59e8d7f1279973c9f202e7f50d061
+
+# DIGEST: c413683815bcbf3858fbb654590434d5b9f1eaae
+KEY: 3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d
+AD: 2989ab33e978c4451e
+CT: 6aa6371c08b82ab3a11fcc3606096a2b9badd5065727b534ec484120d0e8c5604813503cd2efb737df2eaa001bd309738a2393146c7187a9e659af964bf7e386a95a2a94498c59610f0dea18e15ac8eb4af5057feb08146e17ac935b3816d7f1aa6fd48157e0773249a8d8d4c6ca8908cbf28567fad3eda42d349cbe630c865ed942abeb24b136a95341da4dc9353711e033f4dec49c0c8d41ce766df14c516704a80606f83e3907984702ef5f520f5b2f54513fc9961045e95bd925181fbe84b563223f857ed2f57c3aa2c365e09208a22bf0a66fa4acad282b960d4fc5f94364505a39d62d7b7b0b087f441463476ee09b781ca0da0c0db77c9135c07de04f3dc796360c3f40f123540c2ca083a3a2a2eb80
+TAG: 1b897a78c5444f951c2e540bb8ca62d177994c15
+
+# DIGEST: e55813b42aa337183d3c091b9f88f8e37832692a
+KEY: 2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e9
+AD: 78c4451e3be585a29a
+CT: 0fded719e9447da01727f2f0e09c5accfa6ca4a37be56c0328d615a5c3bde41e6eb09b8013d5ddb2231812ec1becf9ef7340f61a74aad14175b4f3a06b32554afeaa549940a61950e0541d9d299b4c0c6a2cd9a6d56546ddff208f466355ed5787462375dc54b32fc7a6680aca9579386e11292463adef01c3379d9099134a7e00efdfe477d7ed5dcaeaa5cc444bbfc9891bf2a192094c6496d2b25cc45858ad5124886245c3a1ecd6c515464b70ea0d739278a86a7d1b6bc369fcb29f8cc6ecd60524646fd36dad09017797f5d01f44ae00f2744d61c69f8b29f26a7b7f9f37d85c208cd89c323a80f0d99c689811e6db3365356671dc3887e016fefc8835461bab75ca3ecf52e6fa56d89dcf9338455bbb55cff1e9f10e
+TAG: 1570afb016707550615f02da6f4824048db1d802
+
+# DIGEST: 013c5a98871203f5494bc2d6927d15ace1e719ea
+KEY: 1e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef1
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3b
+AD: e585a29a2af12feef7
+CT: 7239290c44cce5a0a7b22180b5fc6fcee4b1a5b55b1c9475db16e246aa12a4e4d8ba6ca1b4c68b289f8fd18d1442b46f0f1f14c584a1128f3fe456e15dbb3eb2b15d9d11fd86e19af236b2d4e29884dd98a0b89d4f86663f672c2e3ff4e7c57caffa8b09564ceeb7557c0c0a1f97136f06c2b00b12c64fb5d13ebeb3384fabf5a9f35ee700efcddb79aab49e25e7b0e296d2b8e625a970bf1888b844c74608b703a59a57f669745ba3ee89bc5d6bbf19fb3e8acca322fd93f6cd5e0a792c29c47fcecda29c1e2842056fbd94e25a0442f2a68409bff680b76b3e9d5902189098bdfd00e982a4bb0932b272229e1d795c0fb9464db31d9a918eba62eccbbbc29aa0bf6d2d029eeaab97b1395c8f4cc92f8cbf9746e0471399421edd83ea
+TAG: 037e1fd817bede51eb47755c071f6f11d1e21f43
+
+# DIGEST: 7f9e8085dff06dec7a2250bcc60532aedf162762
+KEY: e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b4
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2a
+AD: f12feef71e1063b0b4
+CT: 921a159f066f91275f36cd54486376bf627fa8d342e9816dee093a1f9ce5fc4d866cb1ae146ccf500b558ef543682ce03178dd9c7dc019e47e189bd06d47b708ddca50fbd57cfc4b8bcba7921b66cab1ce0a5ddb8716e015e0ba1b9a47e6d0b417c6c177f56b5dcbee24a27dabc0cd97a08074655e367168f84293ab5306f310b9f13eaa976fab886017c3c94bd0bd04a8602265cfdd4aabb8539332d875aabef8abf53574b17b4dfd4f05a46d2d5755e69e09200fbd88510a8dfa9c44d1577d18e34f9b04b8969d6867c92ae0899bf94d27db85da27dba2f5ca1c8105f219daca5cafd6394f764103a319a3c3d7bcd0058effa72294ed3813b8d977e8cdb49d4e24321a8f9b68136efd2cb926363e0a7ec233e09433a26ca6451910242433928417
+TAG: 499815f05270dc4823696553f505de10b24bc475
+
+# DIGEST: 0254594a43b8c9b638cb456593750b3f8f9ada22
+KEY: 04bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f0
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e
+AD: 1063b0b4e6e8992003
+CT: 5996d5bc8057de4e7db15436983978338d8dd9b3134a029e937fb9b7ec53a87c7685c24a8de6a024af2b6413a5beed842ba376e6b2c9a6e9b1e5dd7ca3d5fc2fc914d8db008bafdb39f632f306a905d98c1be2c71ed53e6c16371fb593792546c3d91e2c067d755f659df39b1b5b8768772e2625268e653d3fe88a742f666da99eee4ef8dce23c87a7e46309d4039cb49968ec13256083b695a9352364a354150e41fb34b18be7702d72df83872d6627a18861c9854e44fa17fb6e2443c97c2ff2ee307adb5fed315a91c5060a36770467782cc5340594f4b393e74a1c848eca1b2280a2e568de697564934a6d4ef14f8d1eb844ae2f2dfe0f4ff0462483e5b0d8d21b5ec8ea2aaad58fc84e51251560d93e58076afa29f2b6f58ff8f533ca13ad84a991ab3a24
+TAG: 17480f644c4351fbed6f21a7624a15ed864db9be
+
+# DIGEST: 15059d32a3357610e64a48c19dec95d256455404
+KEY: 2a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6
+AD: e899200304bd350813
+CT: 73b136d64df2b3fa8e39c2df09322509764ac6b8e9db523ceb94dd654ccd9e1f37bfb6a6128c4da55432de0fba06a6934d162a905b9b9931fa030006f8f50ac8e64ad64d1ae09336f95f541e7114507e03ffed6b5a4c73df41787da70306a765f484987b3102db46cb3dac5aa1d3b617f4c1f2938d384a8628eafc9ec3e5313b96b6cddbb4da34bf3d7467703317c11f3662790cee0110ad6202f6a9cb6d9e155aba11292cad2fef459762efd68514fefc820fdf8016a9991a06af074fcf1bb37cd52c8d491303f1ed721f8f33d53756247f3010ad9b20aca36bea8d3b5c71d4b5202052b4c2ad0d07894afcafa84a125f9bd8c2c3805e562516076c54ffe638b12ad6c79a23ca1875c5fe53879d97927a9936d4fc42e6e20f6882ac0259f718e33edb5375897d80448bb442
+TAG: b3eb0253705c434f7d1e6c36f31347f9ec7e79a5
+
+# DIGEST: df289e1d102b25ad07e98f430cdd24eef513f8d4
+KEY: c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304
+AD: bd3508132a027d1ff4
+CT: 9634f9a5936150cd81dfb92a8eb20be560197da9f2cb0c9d80ea21b30c61ad03588d1281881d4d5b5dd98f22660ab88ab21d58fee675ea122f88464982bed5711c2e8d4d7177dbe7109fa3173bde9d58d9ad06c8809bf47bd0415ff6352be9ed579bed26496fc85a4f28ef8178aa0c9dbec3f0faefac33a8d172a6fd37b853c1da0457229c0e43d8d089ce2dae8fe944e62ef4473e6be0f0fa7d4a3fa7db7a7bff27f542dd34c7e2022b117b45be1a03f769ed1617dc5976f667a3b7529896b200f5d0346b036273b7cf22e02d49026f068d05df84625021efb49039fefbfd9010075bafea9d97ed5000e56e962c64a414347baee525e910ba6cd75222e2570266f9713ef1fa78194e89a60f32b8a176f7e01377f2327eb16c688b0645dc42ec42b2b14c9b6277fc07ef032484ee77dc10
+TAG: cbdf5f13e04d40a5cf18b3f4be7fc81af8d6239b
+
+# DIGEST: 3faf5b20ff66fd6583a2b62901c1ccd798c0e9eb
+KEY: 57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb587
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a
+AD: 027d1ff4c047b3ef4f
+CT: 5caaec626058391de248e4690345da79206ca1583b9eb07fe92e8a4ed451ec8d0fb2363000dadd05225ea0e36fb327b083c7aca517b99fd3553a604a528ac3cf474c9be6f0e2da0b184c8eba60cffaee4ee2ab23d1acb8b4d371ab3e4dd64c9d10da80a789c627645dc1dc99f7febcc82d0d594b06ccab9b2563f398cb24f5778903337c336cc1ecefae2569487c41e498246d36307f174f345314ea8c68ffe37903046308b361382212c8c617e2e7413b5a4783f6e0249fc306298d2b96c802aeff2f57eb124feaeb335352496ef159f22fe45324c2c125153051f7b956a3c39c4c4260287a93674cb32c15c66eb4053c19e6075b1065ab6d11a4fbb1188a30d48e0071d6db0c15ac523ff882a79faf419754a90330b2d87b08a94dc8b6edd42a769b19212674bc9aff4af2f9cec47c6b0f486f8e5e
+TAG: d733762bb04080e15537cc840efaa0209a07b8ac
+
+# DIGEST: 2a1f12db7c66ef374e510b2fee81431a4902fd8d
+KEY: 4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c0
+AD: 47b3ef4f57a74706de
+CT: 96e184f7d0a88b1b00c45117ead492b2407e75f83bcbc2602a9cf660371e3bed40898133b8d706a347f68375102d843b0512522501c455cffe8260e589832219cde28993ebe608459b5a3db9b8d4bc1c20b23077743fe65918972fcc9b2de1310a20e5554476cfdf34b9377769cece4428b7fc437ce113655cb92f670aaadbfe6b83574c4f57313d41a21fb2731e16a2659e440cf91177856a0ab13b7fc0664ce2706ca44f96cf17e29fd9a4754a0b0455c434c2b1095b72b5b9782a91e2437a3bf65ba3f716e6e7596ab6fd6e8980368a45edcd4c222bc03301f0a450e93a43a1d4ce5efdc36676068dcce5fefdae8a590289621855f02619e8bed0f82acfe85045d613029e5db9b07e99578f71d9f6cd1024f3e031de2540ee99c834c55bc56aa4dd95b496797e4599fe8a3c00cabfe518a9a457ca5f3258b37f
+TAG: 9b6d21c19fe123f5b8c2c6e1aa00bfc5525fdd4a
+
+# DIGEST: 524f8d38ff527d6ba89c51265f6a55211a443a04
+KEY: f164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57
+AD: a74706de4b381c692e
+CT: c35644580aec8535204a1d98f4aebc8f70dd659b9bd6810080197755062b975c269c2228d33149ff3ab1a2ffb554561fee4c06500017d0f3e3d9845fdab84bd311bb38995c04d8f801c6d7f7341695921cb0ea3947f7cdbbb4787d032c1fead5ae913bcf7c748805d0d9833bc6a73b43ef026c8a2c77f031cd9f2cb05ae5ac4cf639f93b50a8775c3adbd06f212ea14de34ac7afa93ff9b2e60f82407a8cdd49e971a1a938ac30611fcaca913a509eb6fdf8dd859e0ee3ae4178b1fe01f6a8e2285fdbcdc73f36f9fdf04eeaa98861b068abb69acffc765efe68df97206a8738f6555e0d6c94686f09598567a222b754863144daf2b14a1723103914e8f37010c86861f8f510d32c47952cb548a8977023bcfc5768fc89bc03c0bf2dba1f036f576fde363c35f0d5381998bc5e9e65d1dc5efa52b8810f96d4c1351d9e7462a4
+TAG: c93f523bcadb7db1d2fa8fecc9ea7b63a4f5e4c2
+
+# DIGEST: b50c58268b989fac3ad8f6d25a401211ddc5cef4
+KEY: b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab69
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b
+AD: 381c692ef164101b89
+CT: 19aed26d8f680371ed40554248306faeb951ccfc880a1303d394e2948e55a214b056e8db8ca57ddbf5007fba9d77c2429e64cd417b10de6478d8b9f48e79de8ad434d489bf2d18eac4933419d7c971d1304a8bc605a89238b9e440271aeb18a86d8e17523ebbacd86dc29ca4e1cfb396e8e79b717a0188d094923d90f69e2d382e57fdad06b21019c0f61c504b76546b43a4211a7a235186ff236638599efaa025a2703ad6f54f6c31fab2405a26fbbd1f2229860c76255c4f1f113c775d3df0fe37e29e617731d93b30e71cfb06fa9ba2cc143492b3758151e19304ab27be2a5775aeef539a10a51fc94d1a37a65f5d64b6b3b0fbf0ecee2061663188c288a668d66573f479b12675be7b3d563feb532afe6177431b8cc1da1b7786c2e2992809638f9f00cb6d8464786227c9fe0e957e3f549bc5aadeb185c0b9f52d8c676c893b25fd10
+TAG: 2c444107e0c938d5bca33f5e18c91a3291e6c060
+
+# DIGEST: 7337152aba55f41574aac9d678dedcf895a1fd7c
+KEY: f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882e
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef1
+AD: 64101b89b476f72b27
+CT: cc4663885845e8360fe110fedeedb93552d33ffa03f4edde71b69fab5a55835a3327e0fb1b01141bae77e9faf534c97bacb044ea9744059a1bca2c9fd5cd61ee097eae00a206af9f3fadd82c7aea17968c128548e99495da6047bb8b2059afab4bc4731f5d2c9de2ab43386def08ebf0d981721abe5b2108996bc604096a3e5e7b2030b1a63af3000ff0d5c96c7f9073e52d7a9e895e642cda8bfb692a220b699ac3cee3c557c80e1d56993aa47cf96a3494cfc27fb515f111eebe5f0bade366183477ce44e1c614dcc884cd192e2dae6e5193fd9435fb897deb2c11b76413dc33534a4dc9027a88d73c4d151251c0511726aba86905ccf135833c4c77f0bb4091921beb549fe04c1909a4f0930848c5d1cac51c44f7cdb060c0e370d2578584fe7170b95d225609648057478e362a33d7a566ee27eb71a8831bc276e685f92236d1c6129e8fb436af8c
+TAG: bc75c7995b34a15355b0b8e51fbbbe2b57e84971
+
+# DIGEST: 6578de87f977f4cd4c5d6dd6f6f99daa338ceef4
+KEY: 67cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b4
+AD: 76f72b27f06f520c92
+CT: ff3e4153e46cd056e3c73aaa60416f7eeb126e59f47b9462c27e23d2dc2e7f9f4babbddbb205620bf89cad24879308a99f16c404fce4b7351868fa3b081c6ed14e824a41ead8db109f537784724f4a25e4e7c8960a563151223dcf893e1b09bfe6e23d5408388d975b158af6961f92ffc70738822324055f502500b3855c3d4898fe2838ffba75e0bb6099f07cefa4877611a33f4f819cf13bde64e4d5dea2f780d5936a4f3b5e8abd5842b82ff9bc97c8287565a33f3038d31c4016fdd78bdd05f38b3420d6708ea93c69b5aec08461a39bf37e718c3b2dd797f847ea8d5448d82ba7f5595dc9a3036b8cda497176e2f3f952e1b37dea55ebf10ba60298c6d12c2968e9dc09df92fe75a814b61c1b20c7dda8cbbe8897f086335cbce0a5b00370312d3fd737c14e0bdf46ede18d051e82e013af5cdd45749b5c496a16247a874e7c48e0d1ebd8343072fa403ae7fa
+TAG: 1122473ff26ea7f621e3ccd8e0a7bd417794a02d
+
+# DIGEST: 38dda49f961e8d18556e2f4cc30812a7e17d827a
+KEY: 41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c87
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f0
+AD: 6f520c9267cf71408a
+CT: 3fce7f036bd0fc52bbf4d25cb7f9fd88c78a157b7cb2fa349eab415316db90c987874920e6e4fdba26e4ffe81adb0eca3bb315e2c3e20c446f18c27cc7ab7686bc59fab8e085b6de1c9310023f4a33ad867dfdf5c7271cdd1872ea76e705f712a412c4d31cc1ee6fae2a63d7c44a71b2232202ef2cb6a9496809c97fbf2621f0e39ff765a99d4ac4410f0b9c744638d602e1cecbddc5358aa2faa06c82d0dd628f7eff73e2b010262a735d885254bf1168c123931e14a8a5bc4bd817078724766fb07a6279a4b8ec3fcbae311df29b2d7a7213a4b66032db3e5206b297872954447ddd32960ec4ffe07dacf5a106ebc455f9e30a0a4150c88aaf34354a7fd0c050419e8cc6db9e12b2d4116386fe1550888779c7fbed6b1d56b23731d0fe3eae14e9b993e49e965db60577d13f6fbb03d937e0c09cd10b1b15133798717f74201116c3da2c08430bf40263b591047cf909c665dc
+TAG: 3a0efdac8ee75abdd79c3f93028fda0bdfa37078
+
+# DIGEST: 9a4462e5c302d0657a599d31a78f3581e4b1684b
+KEY: 877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267
+AD: cf71408a41729bacb5
+CT: be03b780b4698313866ea0174471b6c54dc7aaedb5b438ba944202cf763f0f1d906599d23506599a11d5de0cefd144929142a94c82af2b61f908895af4e679676a0ad9657e6739c617e1e52182386a8db0f6922e387111672c1fa0cb0fbc4b4e42a9f2ad137224e91b21895bd958e702a1665d83c807aeb15977642d18afd931f50926ab27a0436cff6b04f6c1ff93e58ed2f4d4cb6f5048fddcb5ef135c3eda8cc96a8e1aa8250411592c43e7aeccf1c814dd3f3a8fec60ec5613296fdd1edc0d9a76d4d252cb8b28cb9697204d0140d51f6eaf0fceb8db7269030abe7dd1dbb9fd4162a59c2790987c4e204931dd64c06f5041428870d8119601a21a88824d1f2e5d2c56bd34073e05ac234f64f73aac7d67c754506f62341c240e7731c506438ff836814705c6f48fbe7056b408fd083296e9157dd53c4a6065e1be27956e6494c724064e58e69833ce871199ee92c8dab57f6e3bed6137
+TAG: 8c63c41924400f386144121b91411fcdf4dfe91d
+
+# DIGEST: c96066fba6ca75beaddcbf7b6bf1b43b2a7b6353
+KEY: fa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41
+AD: 729bacb5877e72cdfc
+CT: 80153a7bef8ab89d04214ec93045cf4c471b225ea04e569f2e394b755ea7bc6378ac1cc7b9b6f407d21d82004ef7faa37624936d5efe9b5f04d3bdaf31e96afd2eee7441c09de6413ffed0323a15bb6ba02a7e9775c3e71a32553a48537ae94a8d7de4a53cf3bf1c9ac47ef9178ad480deebd7cb02977008987dfeec4a8ae0160f5e3c726ae89230027bdab41ef703831d6b85775321cbd64362e2a6590036fea8f0a86752800fd44dde7f934b7cfd8892a1e3de873cd162de316d3610f7ba522aefe82196f459572ceb000498faa8b383208add721a9450d4586745115ec11b82bd39c1b3b016de0f7307ed2cdff9fbd9e4981c1ff42d5a8b4307133a0821540bfa1c94a100f6225b0f37bce482895dc0f3254e136f5ba8dc622843516e4aacadbca070e70c775be978e72fa6f9dcf695b07b42848dec50d325f7e80679299d7a39ff07c33f95e29f4fc8a19140c3e25034521043fca8ebc8dc01f55b92
+TAG: 75b49f356afd4752dcac3abf1525625e7edf3811
+
+# DIGEST: 0cd3dccc73f4bbfcc3c62b4638bcca5a633a2b37
+KEY: 07a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb587
+AD: 7e72cdfcfa76aed067
+CT: 92b56e0f8e04cd31a8496097c3a4d188e3f7dfa36577a0896d9ea81a2f0b92eb6d55148ab375e7e9cb7398ab8f74916735159553b26ddeb3143d6ad8934b50f6fd59559e5d768092e1a1dec220ba9c0b30a76582050b5abac8bf9b576c39c9d93375b4bdc383e9145722335f5a458da78af2f94d35bcc421f695584148ca0aa63305370df473d17771eeab64db928a96d60270e73a30e8d44c3c92e261d14f4f029b1816fbedc238262179f0ea101003dc27cd9018f1e64408c5fbf6b81226a801769c23e05d85b74ec8a51e3fb58662033ca4f4900791fec90e212af7c8681b1aedeb5738e6253ba4f150f9b2d86051b4071c778f8e020efe350c1e81818e0822972a4f5e387c81f60b460f4f865b71ff29471c76da0a6245b7a0cec8e882d0c3767e12ba4c550393266f137807276f37e99ce59a8a1033b878b8960aa0d0554082a9bb2994f48385d98aeb09a28557a8138ebba93b7ecb4db4d3e0e995ed6707d6b2
+TAG: 99aa6de07804065fb4d36a3e0ec18a954cb98135
+
+# DIGEST: 61f7a437ed58c4d0c66997aeed34757d4f36926f
+KEY: 699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc909
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa
+AD: 76aed06707a07c3dab
+CT: 239b6400b1fb4c9dac96b84401c419931efdeb6af9473975979c2315a96a103a0cc5a3d89e44c5f18cd42e218af662ef0cc43a7d9fb1b24b238a28d18e4afcc7f2a87ed59de04775af7390444fff68af519416ab0727ddac1b6c46fef5085871575481382e9f244aaaafb0dd004654e0d76d3eae36db7c1480adab3fffce2bf40ec172ed00b72266bd7049b3ea0d18806b86776dc4b43e60e4ed856811ebf7ef7a51853300d80d713353938d6c05d6e79ffc2a59642a7042805fd1482917c0c1808677f977738a4436568d3ada913285be30999a9c806c74d22b1a7e65bf80cefe158d785bd86229c3ad7a8e2129262f4cfc0a86b0587d1cb5f62179de15acbddd7f984972e627554448697cec457a798e1b0f1cba6deb1c795432f5964a02618a88dea906be61d09bbef6bcabc2cded3867b08b023d77ff114b32a40748dc9417eac9cfb2eef67405a28c024bd82e2dc8fbde615c3a2caae48eae1fd72a33f0cc3956b1f6cbfff7
+TAG: 965b16a7dc6895db026b69f287f37701c21ed2be
+
+# DIGEST: 9b062a7f63d081bc4fbb8cf13db57ffdb7d113bc
+KEY: 2eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d7
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707
+AD: a07c3dab699719fe88
+CT: c9eb33f74f30722568f1fb10c74285184125a317c23502a53fb683dba4f27f1fda501aca6b5beff101711ab65301d5323a2d4f665e9609495cb3eacb0363cd7e664a9aff6a7816d01969877b18e0e114e9a03b86ea4be8f3bba0c0d207e6b052a624d0d04d6c69249d71ee6e7dbc8ae57c6d47d34ebe655da38e5b97aa19fcd2d0307d9de6a0f61c9735e71c3edf9867e1ed8684bb41b0d547a8aa9e3fe8d6dda64078df499d0ea49fcc2c212950c65ef107c12cefdd1fc1edf9d8637192ba127e7e3fbd07bc6c662d8315ca2e531e374b1363470b890c0bef830768d22548d814c92b0c5945971271d3443a72ca7e317356de9e4cec5caa2f47f2904ed1aa88c88ebc386413049f552a481a7de29afa7ea62874e7085f76a4bd716e0556ddbf2188ebc8b9d68ce388ac5efdd251c47d0bba7fe5c5d73171fd382433990fbf92ebb7a612b20c9b040f10caa5f90ad4faf3ac053dd469b43d99aeec5418d13e1d7959fa7aa01907e72a0a5eb0a8
+TAG: e921b1bb121d0a629c08755bef6fc3f1e4c5c3f5
+
+# DIGEST: ee4812a7dc3e037844fd9c35770734168c4ce2ce
+KEY: ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab69
+AD: 9719fe882eee2fee55
+CT: b420c2d484ef8284447a0d14ea73dc43c79080c4560a0ecb6937a920bae8ec975e14c58a200f933b24e472f544b0b12539caa91f8cc5450a5d9f13344008e303e6770a057737ce04d1507d320c0e82c8356041b92d21d8211dd802cd47d05a7b529832843ec03f74d58f75f2eac4e43596c1ba8e6539f7200bb1eb491e975a7dcde78088d042a6ac7731c904ed17675b7265ced940fecd4ec61e6653fc12a9766ecd167e7d33ccfd501dabfa72ddf9fd5ceaff2e81fc8d821142337efc768acff4c01c245e36161e4226444bfa42cccc586e041bb9aad429cf3a57f3ea674587ef49ae09e4845c52becedc76e79e58a00d80d0b350f89e9042a74a7a3f02d7a8e3f99f9431738416d5b761078295bf6d2be8d05a59a72f8699923fea5f61dedbb481993fe19d6deb50d39ac37cccc875d84246303a9a52770758986ffb1331b4d7aff7b8cfb3a03befc9ce156a5f5fe4d42f40e0511a5dfe8f1d6babbfe65ce85f1b1eb1f6de30acf52a8593d763f10d1871
+TAG: b052776332bb81c991f6f70e79270add7f0bf6f0
+
+# DIGEST: 4209b9f203b29926176f7d54ae89ce7e903009cf
+KEY: 870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882e
+AD: ee2fee55ed8b11534c
+CT: 6f751cb6179b55339051a1d2060f68e0d73e5d5eee4f3a6dfa5555dfcb613a8993dc473f4fbb0f5e2ccdf2041743a7a436ee8582ccecbc2e2aaa9865cb2de735513f882b826bf240f217808e5dfa9a1f88851f1c8a7e4a81235c371a0918033859eea12b41a8d46eca874d3247837be056e441a82e5eef44f550bd3e079249641a2677dd3a46939eaae2fb61cfd8bf27567b4e4391644cfea7fa04186e67b9c347bc7bb331117a81daa53821822db4f3a1acd888d9286d4898c2e3fc5b7b8b1c829c09ae7ad556509d6c284a9dc2c88fc6db5a928999d15c7720d6ad0697e2dacd643cff49eaa3b05c64ec8d7f8e6da47978dd5ac256513e2b8fe3f52625c5f77f35a64ee264d9090e1dfb8453565d8df618c242b1b48474b02ac71ab72e4ed88080a47b7a9a2f450d30ea021cba5ffdc432ffed92e01a659017c184ea9d0669aff47160af476b00a712631fed290bea7c4763c80b34ff2cf911bd3623f49b3b27e7e17e47197b93ab08e2907773c6164cf3fb90c4e16b
+TAG: f9435a042895ce53916e1e14ce1df9ced677962d
+
+# DIGEST: ef5c6927cf43e0994fe5d8e87aeee052b6828289
+KEY: 14bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed
+AD: 8b11534c870dc695b8
+CT: adf307571ca077ce893883f70f60276c36d601bf49ee23adaf81c6b84bc3bf46e9c13c921556f86075688d9fd3ed5f678442c09a6d3f81f52dbb32224d878f644046a9318de7fe5a8520735f8e71a66ecf176af38aab83a0c2c07b21b574f067544c03b9beb50e04c85df9b557d143b30bd5c75f63813b51cbfe2bf4b077c708cbe770c83ca0bea9b5b73255b04906fac466b1b07d4ac48e0b2f318e8a212b09010e262db38881ab8e82b61c4b370c4378022225e597c9b0081618c02604ea0f3c5cd0faf3da44bde5c4e916061380a95678113e8b16d66d2a416dc713fc7ed921049af96c97cd827d781f6c3e8a89447738dc77ab3b73ae1cbd2a5b6c42f9b9237b8fe0d9bf496fc20bbb3818c77153b99cbbaacdd63bae384756d83da79963c5754d28fb9cf72e45a6f5f3dd064ad23402004d6b102edbb3eb112f80983f92fcefd35c1bcc876b6d98c7650d1485aa2152add4e11999ba66e7627d216992ba23590f660ac289d96cba43e534b03433f917540fb4730290112a377b
+TAG: aa5bde606f1143263549c9ef1fe4ebfc8cb6fae6
+
+# DIGEST: f239c330cddd57a5e88e777c848cd66e508bbac0
+KEY: b1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c30
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c87
+AD: 0dc695b814bdf1a87b
+CT: 578f5fb9e465d5170e4213421298803b81153140a69c8867d143affe182970729b58af0aa00c280619b0bd9aab23c988e5ea60be4100b8b000911b96f8c7345fb590b478c95b1d7ef9deb9a770f59a433f44aa11cbb4f9d1ea2f9acc861c8e44c932af277022a2f7fa1adb333f1728c7c3219cf616ac6d90f7dee497470d5d50bedeea6771e83be2a42ac9e9c54d27ba3fc1a8f77ae6591079c945111dbd0631e80024e2dd62d2487fa6291fdbc11001d7d8fe6aafa069da4a6c084c328b7850d681fc4943bbae999ebb5950057d22fad12707df8b02d1b85ae01a4f97747a0b58c6cad19846edd76847d64f9ef8855b5679e6ed78734b53b014e7fdb04c436c64ab8dc96a380cf0e69e98dd6cb302caedd2a2922f38fee381a6ec63ef507a3c657e3f875edee806c2a801c72461174de3cae1c73daf1aedfa75543a46fa51f254b20c53bca20c79f036c2b39d8d5861aca40be01382e6eda1ccfa159c517bc4bac0507e14f16323b812ccee4f70ede598ac37bfc01a7ae9285fe90ed88bcf7124
+TAG: b40c2e6bf817514ff9bd363a6e06d648be0c261f
+
+# DIGEST: 7384b8e3650297f0e51d9a8f76de34eaa4bc9fcd
+KEY: a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95ab
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814
+AD: bdf1a87bb1052c6755
+CT: 29cbbe2cf50c291bd2f525173786d8fb20f45edbf0fb52825e415a644a6396bed1346abe0ccdf3e20f602951be4ca8e2c5fca8f6d79ec56f51d1667615e72b475b8f7cef71a97992f167808b45ad6e450a3ee25eaa976a87827a676d2534fd604b3765a9e2844af2dc276fc8bcb76c861403f822e900db914c9591a3dc1c5e05129c57aad7d3ca1e58f713eab94de4edbf418c50ec073b616e10bcf7228076598c4cc89431413a66935ea2ccf98e87b365087316e362406d02146a3a3e80d0b6c2b38b48d69530f48295ae305b7a177308e28d17b0b1f4f7fe218354c4857963abaf6eea625b44b2f764357121a2bc4d5cd7eb75d52509c48878956a1598ad4979f5b1d05a311263a306fd2ba36f3468528c150b77863c01bc8a6f8b502b4d4d75a138bb4d34445570ac7bd9ee5ad33a1a67365e0a7096f206c1d401e4dda563f61fa826f091186e2d60edef486cdae4108388c5d6d131bd82119c3710c9c017e3107b328c840e79691773a6551287ff7b7245854ce555587368e8a2ea741383a29eee1b7e34
+TAG: fc08fb09951de4a6bc3e8cd483248279650f1c45
+
+# DIGEST: dab0914dde7a8845203fb78f9b0af41ce550adf8
+KEY: 095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1
+AD: 052c6755a7a116bfc9
+CT: 2b5aa6105c526639bef306b1b4ed377c51ffe3389c70767ff4b11f5573bf128b1a1d745419c2756e7356cd1c7402969891ba10ea6b6d336222e5f6a9902dd23a0447e2dec8a24ca99abebb3d04954f6102caedf6a22dae5a2f5bf01c6b316d77524aa86245c89f6c6bebce5791dd7ce65e7239356361d09bf35c6c07eb6141abf5e8a7382a86ba32c4e1e3382f3599b4e398cfd08eb6b8dfc86fc5e6f5da1ad252ec57e4f550ab2887ab8cc7a30c06b9cb9e22180846150538b1567525f86c0363765a287962965966179be154f2406be74da366df58d4095a1f179046c02c538e30b70561ac03fcac7e1844ba1900473cdfe7b0824fd26c623cc9e87fef340adbe136dc0e06b64ed0f0f5b1ff56e094dfe3894021082b9f9b10ff46d76b0ca9829a2832e0c67e99679aff2a022bade3743dea259aaf1b964a7ea84f202986fa9ce9c1d98ff77ccdd08103ba0926fb8bf972b9861d537621136aed49b33d4cb4e574a485fbb1469c8bc97e8e23300fc970a9d9e3c81580703c12632f1221a37ab45db367ed31a56fb1945c
+TAG: fd6d4d5bd750a7631434ae3c1102db751997e965
+
+# DIGEST: b139e0011fe2e768284091a4f838f86fea1e4a7a
+KEY: d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7
+AD: a116bfc9095da49db3
+CT: 9a878b40eb8c755bf7fde51fd406d7ac496a467f36e833586f6f1f60e7fd6c52ce96ff9049055af08aeb99e28ead97d83669df6f868a62fb4193a38e65570e30c1ac39279f107c250e976f2b396fd94f0584b41ff02b6bd1075d7af8d580386398531ef5b5868153f3668966a23c72bd02d9e01af231a7ce327694ea81a6165326f098f3fd3db8b0a235db22571bc3b2511b2874797a4bd1812f79cdc7462e44d204995c65a6e0c0789cabc344132bfba06b7cb493713c184078cb64a13e9e72b91896cdb5586155173755b819389ec1e4dc853f44ddc414c3ed7516f342885d7cb40a426b1ae7a5422b6ea77fd8bcc7e921ef6862ba1ef0d8f625709017e207e874f7858a89e4e2d73bb8612fd32c5e57074a4d4dd2f3d97cbfb11913361be39bfcffbb5ec9fce19810a4357a030adfd070f4924dc82338441f61d9a9bf0fc94c1c68ff609923b6b95fe4146403c0009082296e4ed94c52f8e5481c017405dcc870223f0fd6efd3243a385b2e70771931e8bba676b1b02a215205f710e1e76cb123a9722757d22d3ad49f1625078347
+TAG: 9d47b2d5666bafaa77edee57f26a6953db96fa23
+
+# DIGEST: b338ffac4bbf3a2e41fd1b3b6d9d224d4263b547
+KEY: 5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc909
+AD: 5da49db3d71f4b975c
+CT: 05ab919931edf88f6c7d68a883f4928d31e31d6bd8e223ede06a1b05e17bca5726cc7334be24a5b8937857f4d0adfa3da7ccdecf18ea73b4b0af199f9f39ae47f8b805ad5375d50d3638faea53e1073e8c79929a3e2bf753154bd5980d347c2d12c7f3d0ceae0a6b5f7e58413cd321597873d13d440ffa5936e892cfcde8239a5108421f0f86357ee1855ede66acffea05bf8b6963d4e465acc84f3f97f74466be9109dcb7b24041f32a017fb6629fceae5f5045f7db743442d79b3a38e9b14891a80334dc80e72c94a0c534df3d8e6877a05a55c7cf0f14cdb4bcdff24ce8e76e25fad1ecfa1e6e4b39b387a1d0165bddb2224750e7d3971bbebc8d78da5f25387bf3e1dbc31c10118107cc65fe040f7d37cd778da5125c619138236d082bdfdb56f08670a20e859a48e71103e7dc417ef9d78ca7308b081a6b96120bbda291d3790f1c516f3fef5189c2ce34f6eacef331672b1dfddb6273535ea3806b470afab24f8217126df8821fd3c8248753b45cde8276242328bbdd2d16564262c874209566495d6d846b858b2baf100b596cd9fb99fc70
+TAG: 129a576af57cc5e9e26957085296cc83d8ac9789
+
+# DIGEST: c9dc1fbf134470bd3ac0d9855918516e5b8d8778
+KEY: 22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fe
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d7
+AD: 1f4b975c5d503f478b
+CT: ac26c716fe110ffe65fdf821b8afc4aa217b2dfbc40c4cfe8e014321d62145d652c55256bdfc50da8dd5e05253bcf3118eb4deb03e802c7b3c9fb2b5675829d5d58972bdc806b8dee5dd394e5dd2f2c0624d99cc5092ce9e893c0cb3c582c63f25f3eadc2feb5f3a55acd013c1ebac8992c4282ae15a72e5a2a07fed6b8272bb6b739a077290321c3acef763c290700e32ee4ebcd8739eb70251ffe2ae0bd0c8177365c67464947eb8b0863bf3d155c289f7378f6cadc3033f2a4ebd7db180f9b8855af9aead52067cf707167453eb1dd4ccec0ef9a5d6d4275417b5ad5be6fc4dbcbb66d34bd5160fd5acd98e5d0e7a89990a0bd7b920eeabeb059ccc1d7ff3480ad3190c4b54275ae2ff64e9766a7639d0403e827b234ad18dc298d2d651bf0aba550f3ad23a13420f181d997984ffb62d623c1db9fefe77ba0db48de7c17311065153aa4bde5e17865e2af2a037fc3005333cb856ecb0baf6a05aeb6ea983099e85ed8e2a5dab283d389fd5966e3025eb431a37edee0ae2e9de6573a93a78bfe973bcd135275b9ab5b698fdd40fa2bcc226b83c010caede1b
+TAG: 07987dc6133e2050817d4c9f650d2dd63820c982
+
+# DIGEST: a551ad393bcdeb8c1bb1a4a70e367b069ec549c7
+KEY: e6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d
+AD: 503f478b22dc8253be
+CT: d5a7518fc6accd03686279ccda810b8a15d6a75d6a3de1a0f7d8b2beaad418cd45a6a3aaab1f10ba101728549e64ead8d6ec865943e02013a1c49f3c1ef254c7b80a60fba71ef4d24ed89a776c066b86878ede6fcb6cc01b9fefb28581ccc5784c574f6188df057d2483358fd159497a74f8c2761545a522c2ae2fb7ac43abc655e3bce5a3e970172b3ee8e310b0055d8f263d4e4cf08c066b6305903f04d5a8a7b8d2fe0bf06e1b88b6e6d0383302cd82705437903219574f17a0f5707ec9318dfd93401f629773c79cdb7b07978e16ad7d53e4cf3b6786f85364d80c747c75e5926d06b689f124873fdc47a646b3994e2e1e63bc1f2942a7c74b4942440ed4c6bfad7f39e951b1ed739ed9f5e6332623acc3f67e1586c6dedb2471f2886a6e83263ea04b623df4ebc591b651dd030bf05c4ab4f2dbf5c0f1d120919f9233ae37d5e49f865343d9858f5dfc6d140d29da4e62f8d4317b39535b2bac1f43b6ff60db448f8b7f4f1ca69d6ffaaa8b4c1e7729aa1740509506abee3cb8d2cfdd7b3cb7c719ce83381296da1d17259f0887963202cbc806db70138880b03457f1
+TAG: bef2ba9751a26349c2b0a0ca06b900d510a77c56
+
+# DIGEST: 45b1d26c62717ec46530a565c9e11c18206bab29
+KEY: 307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460b
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22
+AD: dc8253bee6fd1b174c
+CT: b6fc258bb64e8ca059c30c0c6c3818efb8a3566058e3fc30f5bd555535568071c255d434cbcef333e02820f0b3d824d45811d575fef8a883de07016cd7b9546cccb238d42ba5e384f82b2aca128fc12ae4334cd5a74397cd9b418c711068167dbd2b51967eba5ee6bbbb3bf54aa46f49d523eb74710c993e5cbf86cb859f19e4b6b0082b9f724683fb45880f3802493d3d61f8a826ff073d635955fc73a833194afda9043b347b6294529185b3cb827b85269f7cf5a457de4170db0194a84ce96400371a98b76c7b8a65d948f0f34c803abe65df001f5fa80e0b63d237fe20bf6a1233686d16a37d6e244ea59e07c135050a2045e1c3305ad284f0d0981f683c91a64097fbc4219d9f9e415d90fd59e6fec3aa07d00fe27209658a5a446ab8982e49553ae24e70f4deaeb4ff662ec05ab7b4bca774a35e0037658f4ae2e59d8174e41592887652ad4ea44b081c08d698ce47d722ad29f834b4132ac0675a0f20decee4a4d946c06d25c1c905533be55e471182ae1f445dd2deea3637ed985e22efe4e4f9f4634a4de27e13082a9f7f4e0e0366fad88ca86c63dd9dbb33bf61968e989103
+TAG: 94f0ca862e7d8e1f764df9b738378d3fece90842
+
+# DIGEST: aa7cb8f1b995ca51405931f1d021ef30a5b0eb3d
+KEY: abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6
+AD: fd1b174c307f01be95
+CT: 9085c339ae7bb43ddc1ceaad9ba3317c1e1a6dd5e391beb5fcfccaf258c4d9c78bc8e4d4728d6b7381917e4b7aeea7759ba21f67a00e31f0b6e22a4695285a359e4a8114ff8d94163ceec0640c5f040b0a7869065d68603ee209b10632cacfc81ac6fe82138d0faa750fb04d582f06ea5ee009529b74ca203fae65e4ac47b81cf46d3d6a95f43f701ab2d80d02e31ebefb6d47a0662aecf76e3bfe501fb10261eb0b483069f7b6309fd04ed4fcda950863a3a32a2a027fa220f262029a05e2544bc490f30363a26dd9c809c10ddf48f10805922908c1d40d99a8529f153e085608920021b316533954eb3f8dba79dd4c5d1c16d32859d221c63892c9138c2e01aa44351f5d20040a61173e6f4a672a3d9fd6265fbd2ea78048379f8c1f164c2b0421dc7f248fea856e3060cb340c71d913db8eb6739fc18d0232a2ffa54edb0853e40c71761523b7929c8b7e315066a5637bd0171b4489a201e21b21e2bb8898a57317405812fa41b4f5ecfbcb4c8222edc338e056c5a85e1c55491ee9850347086b137a3517d39c16db5f7b0a5282219e5b15e8dded5d174b8e609d954e7f8c55ece0beb13f5a6652
+TAG: a80dd559dbad93f2f7e0c488e7a1b64bb50e2fcf
+
+# DIGEST: bdbd450e5d302436cffcae83ca3a444c0253a85c
+KEY: 57772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c2
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c30
+AD: 7f01be95abaa9bee58
+CT: 006a885cb2b3968ce150b4e89591cd0b5baf7056f1d82bf5fbe4f994be75e2323ba28c7ad84a146a45a9c0192daf25c113f164f4813d88879bfa21e583e2cd16ea9232be370b00f174b9d04af4877f0dd9d5695c5b65f5710165f9c9806ed08170c9a968ff24065e11297147d3575a1173e752472c31cf7e6f11888f55eade9a86e4c8d61ef0d3a4d70d9e469b0cdfcc95d66d116a093a5c7a392510643905b73eb816b981c8eb2f07eac0e61966eeed596d35f3efac268af78fdf655e981db0069a76df72af523ad88d313f8c6001dfdd6bc2417b5bf25b1e97d380e84a6b9c8716704f1fe8c0ecc79362e29a4bdcc7f97f331adaa2cddc81c9bc75fd45b9ebce682cd72cadbb8aea74553e47aa0f7fe046853bbba6aa93b797d0362ecf8061d4be3525b9b71c990cf62e8ed7364989114c1023e6443fcb22340d599f59188ee00c28ea9ae17555e44b7a001f6064ea0c3776e19b5318d0c0710e6b5be0695b86b9df2e60a640946129a83582eb0bf613c05b1b3156bb6bbf8735c9790b6906d8ed2f87b2edcce33117124464e24950b2ecb07319c4892a8d6b1be71b5ab21607b5eea8e1649d3a389a7ef0ce75
+TAG: fa6c2e0a8bc4fe87333ff0f450005063700e4a9d
+
+# DIGEST: af3f40d07667dc7e32a1fa664c6f5503c3e2c8f1
+KEY: a4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f43724809
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95ab
+AD: aa9bee5857772305da
+CT: 7ba590996ccf9cc27aa3ca835494fe22c04cfd6653c6a130fcaf6362950a592226d64d6300957701c0bc7322054ed7a5da0710646357976393997ca1d9900687e8b9687d8e0ab4b52f570e59fd24d57d5b6039efdc89b1ae1112b039f4a5326d5bf96bd4eb9f4786d29738c23a411c268bf97b51052c1df7f852ccbd5d73d132aefcd63e7fd424b229f44c273c3291379e13f55cc177cd5b9b641d888f3a8c331f753fcd10200f727f7e72e5ac983ae908a30e4f3d1f7cc7b6c4b1a5ba3829e08eacbd0b0b902a11650bdb1e66eac4aa1cf9fbbfe982c3cf1cdf6e08a1af5e40a76736b63e418ccd2c90a9d5bd9e0e6033ee3edf68f220b7b6ae78c155656b3fe80512c90b2a26a5f89dc0159a0707f2619f2f76c18c3c2d82dda661cdbe817fe2df1c4ce139016597cac1ef4e8ec30413624d4cc6e5285aed49643db2d70abfb36e97ba3fc9e88c17abe5f82d855b09b303a748d0812db5bc07bd59211f292aeb0b8ef001259b7a12cd7e409d7396ea5f620fb9054ecb506c7d548ca77a62761c92a8484870255f3feb878e6715f711b608af234235e55ba834373f5223c630a061276875f598010e0567ee72a211c32f61eb
+TAG: 6d8145aceb01e000d3463cc6fd07246076e2f1c4
+
+# DIGEST: c6830aca35b85932f7c5df33907ca59bcc489a85
+KEY: 05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c4
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857
+AD: 772305daa4b550d75f
+CT: ba7f2c4b3acc7aa855b862e9bc6a6e9e4b673e9d6c3e5c3a756e0017a68be0912dad490c7a42dd095e459e3a5696e6291ff98d412f866d1ed177ac311920b60b062b108a36c80507d4a41b20cd14a9f6a7ae142382d88e7619376e223c0ed4fdd1d9c7409a0827104a42bce85e075fdd3fccb5635b0d82abd75507ad4139ed03dc49f39ec6c7b3ce05f2fe0fff53da5d7316908061bfb3de630c40efdff3ef612a9352d527dd2f505664558f99b0a7e908738ee6fe833824a2240058edd8c2bd9e77e51a3828b6a382cadf9c5fa2b7f70aab14959d19c485e94593da45dec7362398c2396461b5d1dbf77d3e954f7e2d08dafe24dacef38500183a17ed92c8fb8e9974c21fe8b597004a087c633f42a67d7d8f0e8623d70819100f5033c392bd159afc5c39f6b81d30d8e94e9a2f13ccd5428dca2513178eab91180d2226d3293707873ef69d0163d3c8fa18e879cb0d51ae6e289ed7825cd46df859e70ac97c5ac17ceaa4da73739d97750cd000675910decb20d5941c2372d46ce69d934edecb5e26e02926ae4bb6819e4ed8aa3c307c5ade9330b36d4de79453a1b294293ca9bb7e6454c7ef31760eaa10303f52c4f9a5be9a2c83832c
+TAG: 5f836b39e8138627594b0529ea382608be0e58e1
+
+# DIGEST: ccbdb85e0a5bae6416136d8d64ef0fc8ef3bd52c
+KEY: fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4
+AD: b550d75f05d8089850
+CT: e0a855b6d3584bb5793097867ddf2fdc65d509a493675085df912b8d9d45f65dd3f18f4fbc3780ea2d134107f4685ed9f6d40dd52c76b1cb3ae5b4f74d3110f223c1db893c40df84cba33b8398742382c723c91de8f7de22138ba150c6909147a81d236a65806655881e7b77e115e589ba78f0665839668d84e9bfed25f0e3328be98a66176e9d73c5aedba453f241c4cc056e54642bfba8e3bc60165f4f2abc50b99b1985501d2cb08a735ab5cabf8d83020a12f94050518276703f0ef5c9767139bbd9f4a7ed0dbe431bc29500e715df723b0a89f9a26638fe7664f32dcdc52a3ea76ea605e01f06cc734140e2bff8bbd589b015dc043518f90c1fe4a9fc6a9e42fca91ee4efdba6bc4fee897e3a35989945378bfce25368b2acee1ac82adcdedcdacd2a9ed487914f249c8a72ccd93e2afd43c42386d7e35e2568c0c812f110c42b1c666b73bfd200534a2dc275352ff46f74c327431d834c24c82214045d7d4efa6297361fc1c2e4eb1ab3a8dfaa417c4a9f2bafb26f934bcf16cf6aa29a264d8100c8669a44692a88a26ff5705e6196bff8f80cf22a1bda8fe85b68660f10bf33c4b566d0285dd6fb03c116c1483ba7adc82b98c6d2168b1d8d85
+TAG: 8cef2e943614fdebdd3b88374925fe725a21e4e4
+
+# DIGEST: 9bc71f6083d602ea43a5be27534283d8953578aa
+KEY: bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05
+AD: d8089850fea3711265
+CT: 974e2616553cc63db47fae22b0f0c8abf9ed4074aaac7eea99edc717df468fd648f78add94df01178a742bdaceeac4e72887ae5161db5bc1fbf192b24f79942425096be91cc3dca81f139cedbbfd97d56f429830ae2e5a6a3c9f563e3e0af5204859c4db7beca03f2b1e958c81de8233b5a96e32483b63a0c0dd62b9381b2436479cdcbd67192f0e670f00b11d78adc333b5a25d165c563b6c1630e93212ef4cfd86d7cdf0ef66df65406dd0229b6281c0b0f6f622f0d99010cc5217c37dd11405788fbb6ab468df3cfef4fbd9f34b77030b1a851ebd1c0550f2aff2434985e9c0b400025ed9862e25b00d0b37e6f1180edf35169b9e0a4c29eb76eebbddd745e019665a0f59a95dd8ac9d31cff2f1e89dfbaf283a31265b881b51eb8f0d044fdcc58152487cbde662e658cd1fa7db0a5b77a2669db089a760f6c1fd22af5168c83fa088b4dd67566caa38189f7d966797c17ab8e03220f16a9f2e3fd0d445c4431bd088f2a2f611d8746705bc68e9b22718677e51e0c855965b59e2eea24b2c08a4bf553f73096a3e716ce96498af8b53e3928e1646e87b2e0eb4ade54da82919d22e5a479592321752524b556dafd165b3760cfddde22e92f578045b76c0b8bb72
+TAG: a51897e4134937cade90d95a443ff1814823c7ea
+
+# DIGEST: c39bd34f093d3b18f254e8a94d2afd8f70eb4d75
+KEY: 0bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fe
+AD: a3711265bf78261046
+CT: a71a8c31a0b21b0e3d9c498527a08781e0003ed488bd067cafc7629f3d33ebf703bd4988404d650fca6af15d3639d1e0c4c6bbc3f2b1de89615b0ad4f5b2825080ff8a65e742870e25ad5e91e7f73e4aa6df970c3752b8c83c0c7f348719ac2423b699a921687d8ee53ffdc54dfb87c37e0d52f97593407f9ba590118a6f260515807633d24b3ac2843e9dede15eca8cc42a4c2fd52f6c6651cfe27feb66b1eaa843a6c955cc302bb85a4d1cfb4de9bc9e95a978cdd0170fb7eff65cfefef919bb5ed6788b1841d7e84df1e612e98d5b20ff69e0cd33e15d41802d69169cf50b71989071101b17ce865aa810fcc2f59307b54c3eb908107549551522da4f9f3966b4060822d5df9dbd30d3520308f6a11d6b9b2c6765894c76122ac5d1aebc11e077938a577e5c315d6a88230d17e74329d8a96007982f09882837e502d2c22420878b0ebcb8116330f906d03e471606221b44717dc3c721257171375c1fa24d7d90675870fceb227e558f025c9d4afd057ce5d0b3def8131d7bd5294713211b827f5bf2f6649ed279767a2ef75a9815775e47a49cb2f7f3006da71990995436cdd5dd5791184c35f77296f5dd36b495cec211ff2663791900ac1ba25e66249bf0f41600ffd991
+TAG: 67e16c8889d79079dbfdc1085c93fbaea962af2a
+
+# DIGEST: 630e1d99053b3cb7dc8c5c78dcb39fa7b0b53e74
+KEY: 2e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf
+AD: 782610460bfd24ba02
+CT: 1d4924289812fe49f47e1830f5c883ed2dccb9dbfa24c408544cadb79311a893ed1bdbfcd3c89dad26e831935afa86c60eabc909b108b1dc35f47fcfa59bca36a877fdf8c00a37171cd727b66a717f94417135255aac047b7a424bd94e265e503446f1ce8d8a540755a283ef9cd1146073e741c8d36d5541f788f7d016b3d8a7d413b072b99adf3301394a7859f3ae3ca94ae03fe13981f0917997916c0fd7e7c24793d97ff7b25ec3588ade4487980daa0064d6e95b49513fb5a9d2b02bfb894d6f7cb3b07382348b9ffbd525553af3af9c9fdbfa3ec3b7a82a3fc290a6a262381f29f32dbbcdbcf8de8d7ad8d7329babb40d4daf2e63a87b79c37c1da0afe81dcca690076e6794ccef06a6e4fd7e6749f3ee5ff3f5a93b7d7814049a9a12f3732e5f77765552d5b0fb9b9308f0628cb22ad88af88416c3e9a09e153d8f4dad78cb5de99d20e186537d9ccc49eacaf5d8e466e9093094fae310e7fae9ede277f0051fd105ca7781707dba15fb6be3bbeea419ac82cec825785031dbc09318883d8df0e330de6193fe1b93bf322fb499ff3fbf1210a08cf435747d4646572b3d83ca5ebe5b368f2bbbb2e391f702f049ab7991de28928496772e671fa232e1db5a68dbd768d25a348d7a96d4
+TAG: f84e2ea463e5b1889b8b4028200deb97fb7af5b3
+
+# DIGEST: 083d60536c78fbe909d2b35cd5b891be34f2a60a
+KEY: c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c479
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460b
+AD: fd24ba022e6da12dd4
+CT: d6c48de6968aa867c440f9a5a1c5a4938a9cca58350c72fc5f79787b1de75cb024da9c86d920b41f4972fde0001ddd45ad4b630dafba8ee91320d462c52e8f4223aa845c5498428673fa0b63e648561622022b2cef22fdfc04bd4db2e33c536179b4ffefe97302be847487104684e3012d4294b133d317b12405e36564108037f8f5682080c6dcb1280b21ac554fc84f3f4eeb1fb88e1b9b99f443b57f6f5aa712f2bb77e5e3232dc5252e376b0be57d5a82117c022b765bf92a533d362404e9b3a54d347adbfb75012097e4dfcd00d84ea40f8490dc90c01dde5595efe64e556fdabdd4359d13d95442012b828498fff1fbc100f8ab23e6c4fa4ac38e5c2b509f1ae04ca922e76d3aab5fcc1812331618e9484b19a7b6f849cfe4fa02f8b5ed47e74f99f9d14b4911013459ad353eb3b540da6d079d937745dceb6466865be2f0815d8bc45ce9c96b1dc6d892a8f1a76d37649283f72f25a5eea83e37bcc499b1a36a3f92a85f41ee8303a9798d2e83f80e929594370c679ec47beafe6a8be3a37b26bd572686bef6341f11515fd0aba7c149e918f564ec36a85975108ce4c7eb436456d07a2d01aa28462ec771be5ab3b98bd01cf661de1321a163870bdcdcd17bb532a4923a816e9b057cedf061374a
+TAG: 658be7b2bc87f3eb23b220e9534a67a79cb1738c
+
+# DIGEST: ba36e689ce5c9e3dbeba5ed1cb00b265c7b30d79
+KEY: 0974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e
+AD: 6da12dd4c27f437248
+CT: f32043386610dafbbd6264e61982044a071a0da0fbb1f62ecf56c9e61b126948c5821a79e288b6087caec4e5275ba85a13a1b16f409e8063d6cd871a6dc08bcfe7ecc6e4348dfb93d84a78d0e470199f135bee40495a8f1133856e9c003d8eb0024261b28415f7688cbbb156c2a8ecfb6fa95c1d5938f14f07b930accc67d689aa6a26c0ac6bb1af26ddbd7a62db89c0a04e895eee446a0c628468f1e9089b0f7b3bfa7c0d1ee83321be25159bf910a17f6a71854b7bdfe75a3fbec68dc2e3d9f245dc0380a0b3500a9811b34973bcd06cde0cc7ecee4e13e3195a936b5fdba5dc5c97937846d50462808f130f2b650f422ad4a387c2ce227e3017a02ea15579a8a0ce0780d37e1f2066a23c949b308263b48c1a19d488ad044a442bbc9b93ef9df3ed4d9917ff18a7a406f4178a2e9e678aaa9eb50a25fca1fc5c8e378b4325b2c679ca21a3c6914c8a34ef4b385cfd7c8856aadf01bac7bc8028cd0498cb1d3eb530b1c850d54209fa966f2f9c6034d74245e5cdc418c1eb3d033bcb50a5e6e1e70f6f7851f4e1f318f415f0c88978d0e3804599c313cd265c5a78862646f60230e2299063d05bd5c1876ea1cea6003f4076a44bea1802d809aa46cf06ed1589a2b8895164fae541028540f58eeeeb6c576dd17ae5
+TAG: 844f42a38aa2349436a963585d1f3ceda5e292fc
+
+# DIGEST: 2f9b29467c1e54888b4d4db41fe3a943887e305e
+KEY: c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c2
+AD: 7f4372480974454879
+CT: 5cfcf1ccbcb43cc75978cf33529d2a5f19b4989627689d76cdf25566794b9350ce781fdeb5fb73f74b368d95ef63c86a389d2be3da73ad211c5367fe0e2424fd3a3ee9ccd2b41ef9c0fe3f9ddfef362d8b8bb38a5017089a84a0374e223eff98a3731f5f80b65758abcee2ec0a1ca548b005dc3f46a466c3c5baa98b74b01bdd5b7cc8931d86966460643b00ac449b546b0e8b839db61bd14c84ed0c6f903f9b2f2fd2c12465a40f4f644ac5782660b7340426721091e0d381442f22c244ba2d40908b354d073df6e9538a091f913086abd37a96c0126801160dff8f07355b9694fefb607e61047c759987f6193927db881b148c12bc85edc15ce7fd18c2a014210f7111b189119191f77f9295b9196d916f2c69da24f663758c862b7aa30cba62dafdd552d2f52b2b93abd3d286d60aff3c25ac1daf64c3442702b8b90db1a885a61daa70aca37024a18a8ad96da2ed5da3e1eb5b646ed3cb944d013dedecabdafda61e6dd3c8489281b6cae0cbb4b55e07f313e042da0a85c8cf6b36a2846ef64ad78db421d8e13f2a6f7b9a147b90365a8c3e6c45daafeef365d7bc3025607805cfe23238984dd4f39cf62c94d96294aeed613df8dd37bf9177be07fb06eb970dca0af147340c1c91f3cf4843f88a05bc623fda579ae60f2410
+TAG: 39ffe4d34319d26a148016a265e1f986af7c1c70
+
+# DIGEST: 070f23e02cb53f55b0127fd3fddbab83e5682275
+KEY: 98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f43724809
+AD: 74454879c41de9ac9f
+CT: 4f225391be3a9d473c4352a23d0030f42ac43c43d645f265404a3b53735135a5e2164a47a483be3d24a5ee51d2c0d216e7d816cf7f8fe094efbf4b4966de2395c645c70191273a57bfde17277173573af90d60fbc8b6161be2a9af5d5a99042c7f15cd00c93f6b9b79521aacfc16ee2b28f05427d23ea82cc1cf9bdc3914e3c140c926275cb339f7d5f53c8528dfc4e7bbcddf4c2c82b97f1503454bb2e18f1249bdf4f4d8d42aa07f8c9fe037f1c8ab7c0ba3dbb3c6d007ff3ac04c6fae18afdd81660f5f2aeb5975527f88063cf4838f7d8b14589982af68fa03f1b8631a7b36c7d20e24f9757071ad1acd43042af10ebbec26c755014b7aa5c5d8c90e7da1afed24a88ed1c2e1c6bbc4ed1e4ebd57d504785b0d9a651ef03b7760b6966f9029cfbd534810b31bfa5ee93b046d2c25c76e2a4c4ce4cda06c267e8662fb53aaf70cb86f551f08c06df577038144213afe38cf30878eb9f783f902e2776abe8e1e5ea1edcf193dce8521896e010cc715f8e3693e3ba1d5e6828b1f4ddbed6901c288b6ad25c8f34c030a03dd09dbde9d14c24b86a7686d8064d9ca0ec85390b70247a006501c2676a7a1eebf77111a401e0c15fc6b4aff8c4ce07c3a57326f4bf86dc553a4cb7383920e1a5ded368a310ff539945a6df6f821437781cc28057f
+TAG: c57eab12df6e5913fb17bce528343ad3641ce02f
+
+# DIGEST: a09f0450fec556fbb3a1f869c9780c3d12547311
+KEY: 79a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c4
+AD: 1de9ac9f98233b5a73
+CT: 7af1b83f0f7b4da19cec10c42cedab801abf8fa47ff79ff89fd5c0221e13a6c3f0f9e8d9102cc7a60fa3c623610fa3d1431d0fe1290ace2834df15d06826910aa9683687d199f12dd0980aef4f071d850836ff35f0e21416185fc30be28bb4bc8f51a269b3eedfb8d1b326308cfbb1a302076ca973d99427aaf1908d1d722fe30c4f1f700f05312af5d7637bc711f0581a7946303606907f72993e070024f28ff1339dc35116434e4cd03f2f240c15da8743807c26aa6058aade9c9e745ce33bbe2d062304a6637b81594a5b3266042c702342c6f157e1e0fad1262b9ad54db5ddcc00e5feba6828de39cb4b62f018a98ec52896f048a67bb6c89a8e08949b403447b96e344e852024248e13518db2a0bb3694f2821d4c50c6133032fe09143918f027f3ac0e327dbcd8b295e47167d778892040739e5f146a6ac9a33fd9c473b0ff0aeb2ac0d0b6dba6e76616cb59cb4f6ade7e49f3eb6aa5a16b5c0dd239085bdbc508abbbe9869d3a294b39bc751a00a16a8e51d2dce28f6f79e6db8a495d599c0998e28e6a4d9023d55721c5caedf347eaf3427df44af986cd2f084a493cc3663f8e198e69e6d8406e1dfb09d773538368e6b9a7d25521f093dd26899b506b3b4f3b0733767a0c8b837c775eff70d898c9a375cf4926969b71fde64650bb49904af371
+TAG: 53bc310ad159b5e75d0d2f2ecd9ad39c6c80d339
+
+# DIGEST: 32559b69ebdbf4f1fe7c6e5ada9a4117836eaf4e
+KEY: 0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98
+AD: 233b5a7379a561792c
+CT: 26f98bd16beca4414e16786a03d9c4fdcd3a12be33e3c9c65c71ac98e0cf47a8cb1c3e121be3821e79afbdb0c5751650a7aab90dd75d817628201bfec19c093977d00f5796248c6417fc81f72a2c967a6f3a8201907729997d962483a99642f7b01b5c3cea1fc3384e60224308bad9418bb1f1533451fbecb40031023628a7f1212eac41bbbf065f84af902d02938d0734d91bb2ecd638672c87f06a6a80f51cec5dd3ffd7ebf7ed134b2aad2afa6d3c3a99cf8be4072115cf56b60e664c166590f0a5623f405a4ad54f713a9da2dbdef5b6e3e4ad077f88f20272f0a33a3b74b447d7fd9a1c3fb76b302da10338f8f013804082ce50a31a092683cda694435731aa7f7085f6917a02bf1f18414539bc5c76a4a3ccf96bb385f76f4e739e1b3d7de83d6447821c4a456fb6864d2daae77481363b44cddb3e302b8ee6f508b0ac64b7b5b1dd6a1b937e4c2d0e69a6299b3ad7b1cf05b66a6ee60f4c5c097ec252dd01a0f41f2e3fda2f443b38f19926d6a66a3c270bbe39206cf734c04a69f600ef7ac92be34c337ae65ce8e23fa5784a85f051a7b54ec2231f002e5a38542490331d093f4a2a73c3f493b5626b0ea801bcea5a128c9f4da1150e55bb54f59e28d8ab07e7b2d12d4aca84f8c87594524e66e12c8e4760ac0647ff3ded86cdf75931208a0e3710acd89d14
+TAG: e0f3c733d714646b10f7500ee599efc28cd8d12a
+
+# DIGEST: bcdc01526c7b0248abf3a41ac893bb72adf422eb
+KEY: 8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379
+AD: a561792c0f3116430e
+CT: 0b3dbb6131ff771ed17b16770b0ca1bd24eb73b1a9dc26ea85e65dd02a6a5182887b58eeacc427c458fa990977fa6aa43e1739e026df75b59422f52281aa105951525f162050b530b9e1f24f61cd408858df473a7624fa2f1732b5c209d0a8973e7c95a6e9df40843a1a9d7f660636610bc84eb884990dffe7e6c5ce7e736f2af55d52c4b5a1475ad4b041a367c7c2ae2b4c9f4014ce4d16d7d0d3f28b5a7159dd7171122af72b14a520611e93e1ad6594c91626a8626bdd2bce1a85a5f314cd0d00f52aac6ea496e146b0e710952e1af5bfe61529b6c8a28f98f36445e3a74fab40f86c11f0507b9aaac6672a86fe709e155341a9f020c14ae6e68b5303dd48c6a82ddbb8937efc4e3dacba99f404b9851d3e8dfede32c2bc866ce0f1381f9448b12b4867b0ea1359f0e9daad9b79dc52eff5aa7e7d3cc383db74121520677cf4f9ac213daf5fa739b3c362cda1ecaf102646b247585b034fb10e8b650af63243f8210c559daeea3c3afb9ba153c257104ea88c0d1561adf58c717bc8bed2a11c4d6617e66315cf4c5c13a7cd6ee01347f1a7ba587e00c48bba6d58acee96429f28d29306f73d03bc540145dfbc2815658a13e3db5432fe4f451c89e3c1096f946b13ec62c5c1a3dc7537c0b320c70315070147d7f249514f2b4566681e3154bbb56e0fbb86910e7837bf6063a6e0
+TAG: 4c24b2c14225f725cdf3c966d6dc18ac9ade0ee0
+
diff --git a/src/crypto/cipher/test/rc4_sha1_tls_tests.txt b/src/crypto/cipher/test/rc4_sha1_tls_tests.txt
new file mode 100644
index 0000000..fd80f2b
--- /dev/null
+++ b/src/crypto/cipher/test/rc4_sha1_tls_tests.txt
@@ -0,0 +1,808 @@
+# Generated by
+# go run make_legacy_aead_tests.go -cipher rc4 -mac sha1
+#
+# Note: aead_test's input format splits the ciphertext and tag positions of the sealed
+# input. But these legacy AEADs are MAC-then-encrypt and may include padding, so this
+# split isn't meaningful. The unencrypted MAC is included in the 'DIGEST' tag above
+# each test case.
+
+# DIGEST: f0f82752a691ef5866413f2b2e5c1d0ebb41ccc8
+KEY: 7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4
+NONCE:
+IN:
+AD: 936a91d0b5d2c0267218cb
+CT:
+TAG: 4a25572381795f1cfd98dc51990437b4a7bad2d3
+
+# DIGEST: 7f3a0e20bde700d3c5596909282e5c3e764c99e7
+KEY: 86d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8
+NONCE:
+IN: 936a91d0b5
+AD: d2c0267218cb7090c61713
+CT: 7a81a0da3c
+TAG: 4f919beb63c93776b9b7bc50854e199a6ef44c46
+
+# DIGEST: 5b32faa93c18842b5cb7b075270438756d5f7dd2
+KEY: 97b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503
+NONCE:
+IN: 936a91d0b5d2c0267218
+AD: cb7090c6171386d641b877
+CT: b9b803f120257091144b
+TAG: 1d38f5c6bc60f8029e3c0de2bf26f75a1f043fca
+
+# DIGEST: 995a0f9b029aba3e0a3205364628bb76baccbf45
+KEY: 56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c617
+AD: 1386d641b87797b684e0fb
+CT: f9bcc75773ebeb7c04ee92e6ea5bd3
+TAG: b65aae98856e1ae9532ec51a74da99c8ed3bc305
+
+# DIGEST: 023d08d5e5af3e0b016103c7c3cfd1d02577888e
+KEY: d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd677
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b8
+AD: 7797b684e0fb56f97c3961
+CT: c287f1b6c5df7eccaa8784dd13261a80c32a498c
+TAG: c935f5958dabeceb4a7c5b938c96e8e9e092fcd6
+
+# DIGEST: ad4b11a43bb47aec3e91209f98f99839dfa1d6f6
+KEY: a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0
+AD: fb56f97c3961d8afa22993
+CT: b4ebc7ceace83ce72af3ae7bacd7aa244cef66ee260e67e19d
+TAG: 3831e1c2bfc15719a10fa549bb71b878d14b6f25
+
+# DIGEST: 580641286aa43bcef85be190e1967f627713bc64
+KEY: 89c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e03744
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c39
+AD: 61d8afa22993a340b9b3c5
+CT: 205e1cb68ac5405308020d4ffd33f8fb64feadddc41ded3f004f8d95ac1a
+TAG: 21c3f69b9e0047ece616d7514545f83e4a2b296f
+
+# DIGEST: abb06965675631a07f380e80a05cff36c2d42ecb
+KEY: f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77d
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa229
+AD: 93a340b9b3c589c7481df3
+CT: 5aa602faea775f241e8fa18773fc5ffdd33bbd948e1dbdcb3f11dfe140594e0c997aa4
+TAG: 169eaa5183d8b27ca529503deb4c53b5a0ce0d8b
+
+# DIGEST: c6a1ebefd827cde32df1d38379ee4bb6a7f81267
+KEY: d8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed8293
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3
+AD: c589c7481df3f4183aa23f
+CT: 81eaefd64602a8b482fc03a21c96c64f682d9d28206daa9af4e7f2a53f4835ce733467f38b79be66
+TAG: 6aeae471674201d6c951b519ee6119f85d6b6db9
+
+# DIGEST: 77fcb5875838a28d24c4b6bd0916ebd827968073
+KEY: 03f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc5
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481d
+AD: f3f4183aa23fd8d7efd885
+CT: 3fd49ccc28eeddd198569a5e4a00c33d09edae39f5fe4924fe5b5c248ee2b02e874934db9bc3324e6ee8982423
+TAG: e48dc9b4d7f7a8a941db23c9d958cd94bd237560
+
+# DIGEST: ff3c91da880d2942bbc51adafaebcf4c6fd50603
+KEY: c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aa
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa2
+AD: 3fd8d7efd88503f78b8ed1
+CT: bbdb54a6b0665c5e116298b84cc79436b99d968d9431f658cb56835b1e4b5e486a196c3937f1d0f51cd3ddd482e2db8361c8
+TAG: f3a15e61df207b75caf6f0d49cc6642a7dbe399e
+
+# DIGEST: 8c439bfcfb896bd106f94676b5626f2bc624c313
+KEY: 773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd8
+AD: 8503f78b8ed1c8e9ba2fd6
+CT: 8cacec10e7af223a3d90227d763a548b54f6848293815d8e7fead6fbbd6fe6fb5afd5f2e8b4fb553001c4e17378dc3b50f61b85c25a4e7
+TAG: 1480dc16dc2ee806cf1cb7c585712e8d23ca8421
+
+# DIGEST: 35d9dfb89c1883210f03050da3166b6d13f5b8db
+KEY: 2a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8e
+AD: d1c8e9ba2fd6773e0d0c30
+CT: b40d09b38f18061f9ddfa062df4e077d4cb9fa04e837cfc214a38d771c1a2385c5dc08820cd006b4da7168dab11af2c41ad67d87ba16c8f2a65a4057
+TAG: 3e6f3d1f13d37a1bcf2106a0b72484ad3b1b4cd8
+
+# DIGEST: a07054c760cc66fc704edf950201005031f3faac
+KEY: 446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac99
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2f
+AD: d6773e0d0c302a5f47e037
+CT: 07cdbc2ee6594752bcf8f66fd4a1e0e8f04a9117264787f8a4f7ad27055c78956975bc572fcdccc190ae4429b7638f0f2719026197af13699df20019251116b84c
+TAG: 773725bc58bdc2b6c10669f65731e378993212d5
+
+# DIGEST: 63efe7af502231420ed5aecce9a28446b257828d
+KEY: 7df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c
+AD: 302a5f47e037446f5891d7
+CT: 22cd54d388c7d34cde365709dc2f357c76f131c41ad36a0fac1ea6f4d30f4bf6c556ca7bd98677c245cc7a636d43827c2676ebeaff0606e7757e8419328f70b813fb7d76fd23
+TAG: 43b833799237d4006bc4a03e05117e6f449bf8cf
+
+# DIGEST: e8e41988fad6c8b44c56544964cfe0a347b35b1e
+KEY: 933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e0
+AD: 37446f5891d77df660ed82
+CT: d7e4ff3604a61c3f8a22c6a3223c18ddb5caace28aa0bdcfaee64595dce7d3d7e41d2eb150c732115aa8845cd252b57ff86ec20b651723bba7ba235837a884357f9de26643c9f273652018
+TAG: cdc49592235a3783efea4125d8fc17e2ca4beee0
+
+# DIGEST: 172f4992e692a88f49628e5d3937959be01aed2e
+KEY: c55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11b
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891
+AD: d77df660ed82933f62be8d
+CT: 1e7776c5ebe458c070344e94ba4e4fd476a00b3c9361691df365b280b6f1143fdc8e80794696c3ca1cc53152c5d1c58b4253b8c5cf4b0d2a8cb5016e7d99333321c4938257a8452a2ae5ed56aac4b6ff
+TAG: e0dd54ff80a71a27b972466826474bee791f13b9
+
+# DIGEST: a35fc7d25f90dd9cbd35910d5532aca8aba88b29
+KEY: aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed
+AD: 82933f62be8dc55b436965
+CT: 25330f9bda1ec06eba08deff82afe69247ebceae24130a7f4c900b365d064d195726feba02dac16fe3450e346ed21201fcd824bb1c4ec7f6845d48d8c6c138e912b5b30a7a1ff7640229909d6b4df939366d3ee516
+TAG: 3e71a5168d3cc7b29a96d87791c1afb2ab1cef4e
+
+# DIGEST: 4abaa8453e8cfdefd918571a961d8351754ad5b4
+KEY: dd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fa
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be
+AD: 8dc55b436965aabe477e0c
+CT: 747485302cade88f45098a5bcba428d7b9ce893f72194d2b8738d5ffa8397626a08cf9ea8542cba682cd5cdcb32022d7ab622f807fedd3fe16e852ec7f081cd3f14f364fd869e2bf556a25e0f7e205832d9c2996fa9ca8220f54
+TAG: cc65b494fca8f21cfa2aa7d1232a9f412920efc1
+
+# DIGEST: b51001b6ff9d27bccf3103a4961280e0a1406257
+KEY: 1eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b4369
+AD: 65aabe477e0cdd46be9937
+CT: 571d8eda38bee06d5217a01d64ae1b8d4a7cf03e95b66cc79e0923c6f8f14964666b63f8683cf381957dfa923c666e1a72e54123280b063d90365973184d7397ee343e24ba80ac6efc30eb9f118e6abef7cd5cc22effaf869ef2f660d26762
+TAG: e756093d90e2871ea7c208ad5b16b479bed23894
+
+# DIGEST: ad2b43eee27e6267d8c5c1c3d558a07dcd6b1f5f
+KEY: 997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce99
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e
+AD: 0cdd46be99371eb8da7dac
+CT: 89f3ea9a3a62ef92d33a9567d371233414e8102d6e9bfc8b2c1cab922290de1d3f28e0fa8c34058b73be3ea25c4846a1f2406473fac7f7207e838fe98055afa10dd1b379f50eba19f9886935d25dfcc221f9d08385c4ac19a7306363c246eecda1be94da
+TAG: af2d6a54de4a9aa05defb56dffbebc9ca1f6094d
+
+# DIGEST: 7b17b7cb19107af8fc4671420e461060e2ef3e61
+KEY: b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+AD: 371eb8da7dac997deafd64
+CT: e2c3cddae16d8113917edf7a26ad79a70c08878fa1e6df5799c062ba7f00f8d2e7fe393da949e85406ae5631ca4386f5a338b71035eab1145a545eae88e7731dcf5f1549a22dc976605253f4166615d97e330f776b4a226e6ddbc2f61b7c0908226c2d3b5a5b9de3fc
+TAG: 6894925d22dc099b341a42d40f624bd48eb0c228
+
+# DIGEST: a27799fc2e00e7abec4c5939451a834c4606cf7a
+KEY: f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7d
+AD: ac997deafd64b1fc65de39
+CT: 6cc34fabc39283fed27a10a55e1f803bebcb733a74e6cf2b20e9e48124db96d98b1a85afa02f8f83533f98ee9f50f7a8c71233c82d0835c1384b757f3f60eb89806b72f614baed813a08f7812f953ce5c71cd28ef8d2ef0d0b01444742071005fe8cd0e1fb2264acfd30c2c63620
+TAG: f51769be1a133d7a9b9dc38e1f9932bebd15ed8e
+
+# DIGEST: 7c52593d1d37b0dc380297231c6cb7b64e04c493
+KEY: 1be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd
+AD: 64b1fc65de39f4f03541a1
+CT: 63d9e6661c65dc695188835467546d4cabb554d463367ef93ee405e6b8cb8c011ead72dcbc82459ad29e599143a6956cffe752b6dd54ae1cd713f415af600ae5e0ac1d1104aad7d25f369e1c85772b1cbde454c4913604b085fdfee187484bf01efd2077913c05ea12acd1d5c0981df00d9b4d
+TAG: 4a5ba0aefdcc619d8a503695d4c8d37d9c862553
+
+# DIGEST: ac6871d354eac507556770d8b6bf10b5240273ed
+KEY: 33c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de
+AD: 39f4f03541a11be112a729
+CT: 88c4f7db02287ba3a42cc28daf6761029bb10269c7a044a3131413f086a5341171785bdd59fc8aa3d27792e41d8085e6b3ad0423c0e8e9dc00399e3bf9040d1752e43d779da4920630107c49aca16db509a1521c5ec4e8dc6d73770dbe9954fe92a5b1901cc5753d7a422db6a1f894d16bcb160b3c33a7bf
+TAG: 48547e6b59f847dafab7e038db21ecaf2c3f5400
+
+# DIGEST: 4f498d0aa9205160827626ef80c163275eca1f78
+KEY: fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f256
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541
+AD: a11be112a72933c7b54ed4
+CT: ce154bb6481d413b39e440540e5e5ba2b98d839ef6469054f9a60b33feb95acdb9a5573d6348e3f0f9eb765b005fd5625dab15a8d34c0fe8d51ec3e160ee1e71ec21b2f463add443234f0a786f0cfd60a67a8ce81a6a2ac608f70260598c636190269b5bb95ffd6f499069e9eb23153db27c0882389ae7ae4f4f85a178
+TAG: 193ce6c16238c5049df7811386f80427e49c2c75
+
+# DIGEST: f0901e8b8083c39222fc940384eb73cb96b22892
+KEY: 41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a7
+AD: 2933c7b54ed4fad0be905d
+CT: 740d1f16d5ea65f0222ee191a77b0b12b6468631d4e2283115dcbbbce2a31ee113d751c3b02197e35a0f8a208e067cc7b5d7f1859fd6fe1d1466d3ac6044fcfad074722ca08df66cdff5b26b716a724ba76e9c948ff47258ed6e80ae68689334c4205e7ee8f0aaff136b457889d0a64fa32a7f90a3c8e40d7d2060c2c0b484328a2c
+TAG: f41e458ac8ae3ea367deecad504f102365a1b82a
+
+# DIGEST: 7af193cdcc8d7f17b55447a81eef3dfdf345bba8
+KEY: 998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54e
+AD: d4fad0be905d41203f5dce
+CT: cc0b4d97e3e121915bf753affb1fba6bd629cddbd4bbafa274ff033dc9a7af54cf891a5a57b7624c440b4361efc88fe8f3d1e5d32eaeccfcd37bd51c33c99e490399fe27790c1a72d75e15b584d2c529b5ed4a6f9763895433d2230acd9fa3f7d911d6b411fba49887a5cb519cab9ba77e0e94c5f4ef69ca52e22a13273c103ed7d71703310d37
+TAG: 46b5e4512f710809f32fffccb2945cba5cf2c24d
+
+# DIGEST: 4ecf44faa266de0904b093653c4d623a543d12d8
+KEY: ad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e78
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be90
+AD: 5d41203f5dce998f8fb2ea
+CT: c7bc10d0960fa1ccca680829527650427431f4d44d22eba3346cc9e42e6f6707d0fde032ca156095289270da8ae0c2eee27d9f3533a54d2338c57689d78eacaac2349f00b240de54e29120b3e6c1c0832cc8f93eeecacae3e23a2a0732cbbccdf466b1067017890b48a5f2bf14be75f86544ddcce0e85c8a8a5b2648709f016a20ea2a8751b2fdfa8c9e73f7
+TAG: 43ccdebc5977c71f203099bef5a4c3f9b4f0d1d6
+
+# DIGEST: 92a938017497e0762115325c40b5f7c138d5c6f6
+KEY: 16417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b70043
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5d
+AD: ce998f8fb2eaad409ae021
+CT: 8fb543fefa444fd4d3a1e45f8ad7b53c3e2ba0173472726eb51beaca6b9e999d36b1c8ee9f371f171f8a30a660a7e6b56e71a1a2ad3e435eda139d3ccb423ea9eeaa43a4e410c544c400083b414c870429d5828095374e4537a498a4c0f3337147254704342b7498f617c65e334c752ac74a1fdd24673bd7475395b680ff7d98074da33deb89d2e0ea3246be69be50abc9
+TAG: 37c95a199572bc7041baf730f254e59ca3d6c81a
+
+# DIGEST: 6b126413a7bac1069cbb5b338c158463a242d607
+KEY: ef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2
+AD: eaad409ae02116417dae0c
+CT: bb11378d80cae9b1e88be6a20c1a447209fe307972c2cfcd615fd277617ee2bd75b3bfc06e792ed584abc3d220a13f91db258a8b86a2622975888170648bc511465e4844e75792cb617a850d61b913a355d7d487cc3b64dff39e8cad19bda78e3179428fd87f88575b3676e452e00a497546fc56560fe4e91ae5eb366cd9798ab583bf9f6d0237340f114dcf602284f8c5050a15c571
+TAG: 07d3bcf76f73402f7f33d098fc47bb1ed7a19645
+
+# DIGEST: c72d214b42ed66ae0822fa9f3bda306c7d58cf80
+KEY: 16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b02
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae0
+AD: 2116417dae0cef457b9e5e
+CT: 453c1a83249343b90d28b8b69bd1e63e94a01863ab0fb68fd8a63bea261088477edad3c9eda06e1d2b9b5149027fd9345d1e77079d1f95cac60eb3563ef4849dbf7012eb1617ad5bcc284dfd3fcec2927b3c07cfdf406a8109746e01fe23a2ceafb70bee955e9aa8a567e81be3c954840cedc4aca07a530cbc7a87757aac5c0e273f4ec1ecad124ae0402336c7e2b45a36be9195398e59bac0dae4
+TAG: 74594c333141277f04fcaf83687e1fa0cd753ffa
+
+# DIGEST: 9faaa58dd34a192550c3519f8c0aeb2ff48dd388
+KEY: 5607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769d
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae
+AD: 0cef457b9e5e16dcc5b6f2
+CT: a770211790010d9c8ac978027a81a1764b96acc7593a0bd8af8a9cb820e7f54176ba5737836858bfcbd72937a6f0956c58126b44ac7e15f22a5cd8ce890b07d7b6cd60e9ec897fe3d3730f4c94b5d952651f2cf69b00133167a8fe808c72587d3ac024bc8dfc238cda08fc2ccc5043f9b4265dc6092626bae91485f6c0c39598c0fe4c42e05b6985f48e00c390efb02fa30cf5ca24b04e1102d51869d05af8f0
+TAG: e35e82e27da42c6d002771274fd83bf434e3515f
+
+# DIGEST: dd5e6be3644dcc888cc50c0b2ad0d55eb0407fdc
+KEY: 3fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e
+AD: 5e16dcc5b6f25607f00d03
+CT: 88ffd8e1134afc00f36c06288548ffa40a63a5484094527d8bc390422385ccc1455b6bec72741c1de0d9c9ce3f7100114b4a6f3eeb55efb70d88dbd8976d85774099f5447c03cb8adfce723274211f6877c23d2da345cdbc6cb113fc89b1aab4cc8f3a71713acf4d6cd95d924bfee73caec80c51e99fd30e33068a9985d9ee5ba0359e3537a366d3dfd7d6f76dc770e42dcb429a503a48ae359326286b9f6bca252e23a0d4
+TAG: 10c3c2f10e79c92c0e2b5a7f68127b867309439a
+
+# DIGEST: 1b8b627e1020d71318511d4c2078eed315ee0b04
+KEY: 4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b51106
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6
+AD: f25607f00d033fb95fb09e
+CT: 005bbe3c706831c234edb017b22399e158be7cf84689a9650f2cfa6415109fe37817e2a65332846f115c6be8b6d34d9950b254b31921182d084a602850db9d93d0102acda99504fc832a2dde26406e1876c242df7d01fa54a197dee3e933aeb5006e597f198bbd81bacd91abd90dcedbc878f713c3a833b3ecf296261a71eba43b3919bfdfa0e621a0346a8ac6e9045b60481c66fec83b08d277b9966011720625dbe7a635dc407e0903
+TAG: 0bdabe2a3b1c9c1d1e486e11efa1eb07c541e22d
+
+# DIGEST: b7370237d402dbf76f1a431cdfbb37f41ef2ad4e
+KEY: 780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aac
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d
+AD: 033fb95fb09e4d00d6172e
+CT: a709eb37f13d3c77d0142da173f630f40f7d35363d4078af8e7a2d7599e6aeca8906fdbab714794b6096f039a4a123d27e229035f7e2d9877b0f06228f9fb13d3a3b0bc2370da097e34a1beef075c8656b2b0d3c9ff8ec6749ae97551a9e2ad686cbf00ccbf26463f393c74f4f942872e0888da4463fa4a6764925279d508b5cb5ea86774141ae75b54f06713d8b16f26064b9927756c421587e7b63c5a2c3343eaceb38bbf4a9daced65d0954f1b2
+TAG: 3256993e68c56e09d5c816768c0056232ce5699f
+
+# DIGEST: 0ad0e709e40cb2fd662020d420d97ae50a14adc2
+KEY: 433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184a
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb0
+AD: 9e4d00d6172e780ab8b700
+CT: b7a9ce07a6743b7ea2b09702c0b78865bdcb94b5407e0406791207885d65beee4d9cd319f02cc3649ebdf2917e009e628dcb5621adecaa0f5fcdfc3465ab4de9084eeec19e05d99f6e1f1d44ab68fc08c23d4856c53053a814c6ab59d06b99a34db9bdef3d447a705dc76168969f729b9339302c7a20286dfd55e0f9c9521bfdea22d179ae54ec9a8e9bd5a254519739b5165c817720fd80a4ede9d5b8a28ad05f7802b26dea2faf3346dddec09a3cf37bf5d54e
+TAG: 89c08dc0a31bb9762b75a6b8434bddf8f86b6def
+
+# DIGEST: 5f9967a8fba7184dd97dc7d5da22ea785e0ffbbf
+KEY: 1c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d617
+AD: 2e780ab8b700433a957a74
+CT: 1f24dd87a8fa17c78ced7190f7036b9ee09768840407787ee90bb1536a2bb51b55f7400484eaadd49b69263052986eb53786688241e0bf22f13b035bac824d3a9de4193d96ff40bc2b78f798a65e55aa0fd757687b1c665195ce7c1eba0b6f3fe3c446651eb8129f665241d1d94dbc5ba0972634ccb39a90c67a9b75acc23e640bdd2719045b9679430b05a3fa1e5d02e92110caa1d20e27ce9d4674f3bbd668de04f3747bf62b4d009f5c68f48ab0fca0d9c8f21e9d2ea773
+TAG: bde3deff0fc4f4fa7fae10062e04ddd52b5e6d1a
+
+# DIGEST: b5aedaae523d9d396ad1d9bb175bf4c7c0b03eb5
+KEY: 021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b7
+AD: 00433a957a741c9eb80f2b
+CT: 996f7e35ad967735a3f98a0032c77b9f9fbc36bfadbf4892fa77833eff98cdbfefe731522a08e9d2d5ffa8771da675c1b257b5d839e4aa8cdce6276c598cc1684b8e76f354477db5ff07ab9076dc32e1ab94a12a7a8adff47474e4186f10d57e167de8e56bd5a853cc764561ea276d12566a59994eed04f79db48524f92e1656754a2c145c5582874746dd8d14855676b3eff902d2dcadfdd79bfc84f9c6bb628d524ae818c2bb73e4101d1d0f33b65d997c68fd250571e7b52fe94dd5fa
+TAG: 03ed20e94c7fc6a0a6af3406870e65806b4e5ba3
+
+# DIGEST: 52bf12f5594b0cdefcf977c07626e8748cec5425
+KEY: 9da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72af
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a
+AD: 741c9eb80f2b021b144476
+CT: 0e066967cc5b14dabe619a6ff8aec1be75722c0ec656b9b22d3d6b0bfc861a2e3378df61038299f921681632f3a462b2bffc450f4b17906f790294f0b49cbca03d4ac9aa17bf25d97f3210d0c400067240cd2c703012ecda314864d6446582c505972eb872c362856d063ca224fd9108ce1fdb3a0570559ec802a221f4235bf5d42579089cee35cb79155f51856a4e2a12bf445183a558ce7a7325c6651b7defe486f066360f6e5c08fbaf8920c29279c86a9adb306ba4b21170d9c52e7d1d58ba5a89
+TAG: 15dd6051ac156b8b6bce69175764f5ab1b74b934
+
+# DIGEST: 900a1792a921b6a253c47013c9eaf01fc5c880c2
+KEY: 0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f4
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f
+AD: 2b021b1444769da00fcfab
+CT: 3b7a1cc6516105379e4dfd5b38f1e7481457ed388ba53e292ff3e24a6b5ce9a64a9505aab5c16d01083e30bff215375e1482ddb22bf0a7fd7bb8d62f4670cb514bf7efcdadc2a321f20d80aefc423a28942e928b7dc54ac997b960cbfc1182c9c085b36130b890d698dc49af682670ffb5faa34552ad85f7d646bee0a6937f2f3cbac3cee6ec55f0844fb7a9b66567b8e6d9df48133ca78150834f04d5b30df84591a5d26816d6c9d0e49b54403cb7bc6a7a5f2543df640ee3b1198aab9862d7b6aa51704da63cc3
+TAG: 059814e20636ac39bef8900e19e07fd6b0468309
+
+# DIGEST: 88d7ec35d88ff113703702955e931e802fb0d8b8
+KEY: 060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd2
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444
+AD: 769da00fcfab0f5f93b511
+CT: caf2c8350ecbe6b476bfbc4141c741106394965adbeaa09317502511d0512b20fdff8a160134a6987449bdea666bed33a068d4e1c75df4aa61d03f3231190a1196b27d81b37d0518326e75051f160d730ea3e957e93282cb9c351cee80c0bc842eeb8843114bf887f0747525c3adfc7020263e2bdefa56e6232de719647afeb61dee81ad76d00f59561213766d34fc4f6ae3946cf9f422aee42f9d7fa819b1f5a599824fa6bf230675dca2d95933de11ed7b8e20679faed82de39064cca50c542c269d6e94442ea3e2dd7c3299
+TAG: 52b86cf0afdc4611dac15b57334a5192e7db5f9c
+
+# DIGEST: 8d8493b55d9b74892e77d3b730588c087ca9b1e8
+KEY: acefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcf
+AD: ab0f5f93b511060c9c5f3a
+CT: 0896c2cf79cd8199adf4f91644cd96a1770d7ca3b0a92277816df280c6ec0522e04899c62758fef4f84d843c183f100506b69d0360ae054749b0b862bec23ef212dae0e8c17d2dfddf0a009ab6bf91539f1b0d0579ba8a53620b578dd6315fbc159f3249f1074a4a8a7203ed3238dc88ed8b6ac6d296edf422e2d9a2353de9671fba487129d8dd15ce39baa9c24040967a183cf61a6fd74b5f7f4852b3e3ab1e04c04692f16d0b035e0c999feab906e8600962a389e1a43136799a66d30c16e211d19582a62a941e8bf3acf80b291efee818
+TAG: 361201f6e711ac9a62f21dcabd1cf1be9f9c01a4
+
+# DIGEST: 4cd92ac16a807d2ff180df75c47d848749c7ef46
+KEY: 4ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c4
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b5
+AD: 11060c9c5f3aacefe61b18
+CT: 93f684f357e4763edb21343c7a9e17433653a1d6c2f2b5392b0a17408d3d1787cffede7d90bd4e3266c4797d90930ccd3f96077ddda39a32789eebe717e02133d44298b83bfee7f879292ab46b67cd8ecd24b25432d668a226c0f7f46ec07aef7e3fe5127610a6e5370b32fa8bf4949733ed0d920463c488684e4b76f4b015e7a7284ec8ffd52027e967dfe0fefd94345488880d5f8a606ed159b0124a6db32f34709876234fcac6b352d735522d03407cb93c2f878dfbcd543731b9a40703c23c065f5f1f39e776f32ce97fb1b4eba1e5cbc8364a5084
+TAG: b5139d51e5fd191c8ce3749401e730197cf435e6
+
+# DIGEST: 64ee218c0c96ca8e2d2e50cd809d61ee109baca6
+KEY: ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f
+AD: 3aacefe61b184ad2463939
+CT: 65ec3ab04f748c6b68ea0cedb1dced536de2f2b90103884299622ced112d15c52ee677fcf9fb364895b60546f408e4d95261a8cd9d08eefac283b62e118f2ade876a6c7864f9e9f3669b200e4a5a9bafea645302db3d8b5e280847b29ec9135a2a01ab607a694739fc47192eac87638156684c62e573da262b09db180ff8620746ea8679a33a10ab8863f89c31edf60dc5c35c14ab439bfc58ffe5731b596f87a80fa1982450428205983d9993639f34a40a08e7876f43eb8d3d2803dbb3a3dff8e92556bca311b9e6e80eda56e1f9ba9e4a8f3a7e14e3b1827d8426
+TAG: f8816855dcf65d14bc51da1771cbb76697587eca
+
+# DIGEST: eef8eae201ae4e5af32ee74bc724e13ae5ed3978
+KEY: 3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b
+AD: 184ad2463939ed518ce97c
+CT: c54f730fb867af4149390dc03d0ab5452e1bcb2c4ffd32cac435758f17ce8ac989e0b78f8018b96440e31d6de691d00e61ba3597a4a16b1bf0b5bcfd9fd03c005a4a6e3396f3f97bdbe9f5363a9a0657094da45729568334758ecccc045a33d0bdab9fea940b86079e58969234523c8a8612922ce7effac0d9a8c80835cd08bc420d9ffb166396f7438a98f2b93ce0bde77ba0666ae913ab0378df364147161f5d45709b8dacf469367fd737121908ba25f75e9877b9e1d31f6c5a766ccb39ae326822b984639367d07e46aa05ab23da9d06c2be11c789bcfdfba452453a6bd842
+TAG: 10e33999b4d7cca2ccacb6d4f114d8b5a4c9ce3a
+
+# DIGEST: 2fe67a81b41b094a708ae515e28bcbde3bed724c
+KEY: afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad24639
+AD: 39ed518ce97c3fdd293d72
+CT: 4290d591ab106835007456629b59e99bfca0ad0169f530fed727f65e6f25794ba8224a747aa5d6c94259e3cb803ce6e28d7c7ed79241fc76ed3e89d97e6344d84f437e30beb59fd6d5e1c3747b9ae83dc3d6493d46e10f8f6293f3e271268e55adaa74b7c00c5fd2d90c2e442181fa283923923f65a8a6e17172dacfc271a3cbae736b0202ce041b31647834ac1b0820d2d6ceebd800f3d6931fb5327d8141f319b07238ac9f186643b52a6cc7ad8a744f63b47fcd0f548417dd17b87423dc55d35be65a44a2525785e59e63266222bcf2695b4a04620f2452818085648aaa5526bb767af956
+TAG: 8a319ad6486ba6180e0c5cef4f0d7d81a5a401da
+
+# DIGEST: 33d10d6cb5dc80751d0f8e370925d7c86cda331c
+KEY: f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce9
+AD: 7c3fdd293d72afc09ffdd4
+CT: 9036f2648c270734fd19bc1c2fbfff99bb8321c3f125e0aca45c8315a9edc31ea1ec1ceb2b588e383f83de84a3ef9982b04a5b1640d3ee0948d93af822a478ecfb86b84abe1d91d8a134012e3aa750ee27b688aa689b818b775d99b2690d0165eb9213147618a925842f7261f336e49bb21eaf52644318296e64f864c981d4d817cda98d4bc0ac4b36f8f156ebbb162d963bceadb91cb02f300a2e34fca5dc41d80c9fe3c4afb980ec69bd00200bea8d666b430205366e0cf9649f125254a9b74b373ee11a4ce000052e4519c563636b32a1e4e65f5a68490633b4eab3ae221cf40d1f288163b9bfa3a40a
+TAG: a6b46380f845b752962b6f21f1713ef71c6c911b
+
+# DIGEST: a29f128842a48debb60699ae0df0da9a9b5e5dad
+KEY: d299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d
+AD: 72afc09ffdd4f41963249c
+CT: 677611097062667de3646779b59140faf94475426fe6a96f953facf6708433330a31aa35f95daf2539510b44a7660634233ebdb15699ddcd9c2c044c4bb2b636c356583111db64d2ce378e74558ac7fedd495b562b79f99052ea515826fdb0ea662d81e5297fce2a8695a2318c0e5b82049ba944f2ca733075fa5d985eb6634a25505acb4ba18965be92ec6366332b90607b9e1e2a30be112391b29ed0b54b61d8237b968ed070aa04a0dbc2e97c2581112e568da22a3f0f64c52267ea22f11fd8cedbfaf49e038224482f36aa6b19d872cc19ac1b90a820f1c72a1295bd551407a6cba1ad582c867bad6137d2ffb12a
+TAG: 2c229ff0bfe0bc88a7c831d99a30011ab9e7d686
+
+# DIGEST: b5048d1efa7564966b6cf1579cfb4ad8e9460660
+KEY: ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffd
+AD: d4f41963249cd299b92e55
+CT: 8a770020b63a9f2d220ccceed5562047763e86eb4047638515aed53940f46209f2ba84eae5d8f9081d4839dba2f01312f80496f8d6d4007e1656653a40c06e611b97fb4548fd9d623f926cbde44391ddd772a957c2815fe3d114ad092d535904f2a87811b8ed3a42e6667239b83e2c2f492a0eb8723e06e93bbdeed4ad5fde2e7da46d50b583a1f2dc35fac4cd40ec55f6dd38ee71051595599bb688eb3243c40da79789ea0fdbe82067cabc56fec3b812b0835aea441b9457024cf51035192c78e7cc391b565d5b837afd621c5b92a249a4dae614f09f15a87f59a35a7f67abc2e0aac6175f4f00e4d3cd9404a6655358f525053f
+TAG: 5eb88f26603397fa0c0af9806e441c219394665a
+
+# DIGEST: b6e68f5f0dfd8ceab56ebb657728c9bc5129fdf4
+KEY: c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f4196324
+AD: 9cd299b92e55ca24d8c078
+CT: e0c6e12e33364ee2a4ba0067af2c57fde404efb1753a0e47efec8eafe611cb56d8c535404bd334a48399b83f1c23931068cb3378ae1e8b435a535d1238704d8bef3d7a73f05090b88fdb028506e11b5c996d891a505ad173f1b8b761e19622420232a2a0ba983bb96c054d4f960f517e9526fcd7e67b395cd0eed2dd34e67ba69d821c6069d671dd352f089cb4bd3b604eb7868643bcfb5a065be1aa2800dde814ec5f9473fed6cf724a323326a7515f491788fe57ad08e6c3b2e207c555b6659c90925d4483f01d3ac8dc09d6da78f0e2f665c8b9bae0918578e1ec4479d4d9a4670e356a69290cea97254a91b9871e9c7996668f347a43f96a
+TAG: 8f89b656d406819c405dd8b8387a61bc3ba76c97
+
+# DIGEST: 853bc7b9fbd640cc0654fa5533ae302e398bab35
+KEY: 13710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e
+AD: 55ca24d8c078c49f78c7e7
+CT: 6a2e464c9d5b3e4053ee0deff66d8971e99d1d3cb02ed5d50c8fa5cb52f695b3a26b1dfb40ccbc881bc471958e8e68ad7a5576e1e4befd884ec6a3ca0f6510bf8db2e011ab53a8cb7d022d13755c11bc77b4c7f9f1fcadf2ff30054b72566f79316144f1fb1388848bae0637f5aa8c0e53751d9fc850cf78c280da0d65b468804fcc93c5837f00281bc40c3ce3d303d11fa2c0ceaa3a544553a9112cf5928cfbd82e96f3268e861a6ef8baf6f8e6a050f83a9e84c77f954069800e31e3aeebca1192b33f2c1fe380c1aff70a716059f12dba2ba4d780ad60c7f92f8d566625c2cc33550d92ec7e01130f887b8c78dea334c438a597df7f9bc98c0919749f97
+TAG: 6d1d94322ddab6739f34a05f10acfac396f15c2d
+
+# DIGEST: 286a92c480192206a2153df1b6d0eb26e6507da3
+KEY: b8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd35
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c0
+AD: 78c49f78c7e713710a025c
+CT: 3a57ab69b1db616a47f0dd7d0e8b9cc6ad0bffe66f32b49bc1a22970efef75f365fbadd4b6cb18dcef56e411ecb43b01e798fd233242531b89e7c393904c657fa4f665a6730ea34cc7b55355634284c95d27485a4dd71fa2e7e46d0f8b34373649b5d029b2fefdcbc19b6c4eab1b4c02ef993fbc2770368c3d53ab1bab44bd3f79cf418780fb6b158f9a9872c973ea7a4c2c75bdc6aae7924cc5c7f5f41b451fd8aa48fa88b5321ce3f65f599b50a17dbf7100bcb1faf4ba8319847119755cfed0e073d07f0f81884f816f3fec7cb75dee4005869da30b3875cc586e4525df3d9e33f3f41a66b6121d09c9bd4838e2df42e38eeee17af11e648a969f827e955d1f935e79
+TAG: b1c96886a636cec39ac6317e826fda1e8d4c0983
+
+# DIGEST: c2acb0c126af5282abe14058066631fd0c658571
+KEY: 89ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7
+AD: e713710a025cb8b9d71d29
+CT: 34c7ed85d85618f73c4af5e1b596966ad8bf5b4eb169363f5abdd788ee69a9a426cd3acd16610f2f291d3dfbfa487e56925d94043c8393c7ab0dd6105b4f0ce342d36a11be29687da84a64410d834a9c4de3367d9c5c68ba5dfad4774cfc0e54a0b8e1c666ea502b575264967115e5ce04899605745a1887f19f663cd83cdb09d43fc84c386c2714b63cf609c758188ad4f47765d5e98811ae3aa6e948d4bd79c7365370d5bd08dbb4bc56a7b779b321508d8e848a637040c44afff96b30b6ed16425a214360590ea02f32b01b710bbab9540e72d454a528980542c01b0afdcec168b6c51ee5c11cfeebf7563bcbfaeb02f95a5905d44e8a16b1c37225a56986bb1e3ca379655e8f85
+TAG: d53b9e3d13e0e5bd65683e82d22377bebd672bfc
+
+# DIGEST: 500e5f2a56bfafb2d93e26224c9c2df562589f23
+KEY: c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a02
+AD: 5cb8b9d71d2989ab33e978
+CT: 50b1b403b14560fe110cd027656bf3caa819dfc2716c55530d865e286ecccfa1af3074bac96d855eea05bcf031f20abb4237ba58dfa54adcb1060c1e736381855d225d95f2e50fe2eff0dcb5fa95cdd622cfd38ff26ca79e47c5434528cea3625268e88389339328b0480eb45b9d65e5cdefaa157530b74049edc75e21b7e25165abb7dd4dbc649be52fc685a0ee2fb5ff43850b441cbf181f7fca3702d5ae95dc0e1a620701b64a90a1202331020c547d4d4385327c05f019fd619ea0648059a7322cd25fbabbc06c17c402fa5efd9010651ef67af24e99b4bfd45971cc7a45ff415f30f61c7278c08dc3b9a4ec466b4c2769d119c6307312ed2f91edc433f73a75eba87f51d66d74b842d86976
+TAG: 35a58c0b953a4cd830903c7a72bf895118d68fa6
+
+# DIGEST: cfa6a42a2cc0ddf1c7b20031c95e331696bb9ece
+KEY: 85a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a747
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d
+AD: 2989ab33e978c4451e3be5
+CT: 6d6b66c1e66ceaa39d661c54b65d5fbca2bd1b03d9011e84a54bb60f205674e01ce1aee2aafd8073cceaf6dd5931ff4ee969f15224b328c100045ce9d964c169b14877154b202372e469df384ce3ebf777ea4fb808207566971d89f98d48605e8c510210db572fbd961e917e8d37f22617dfad556a5245756488014bc3fde63c3fa49b535f03ea5c9f7f717d29a53f9156f1f263e80382e18cc350579a1ae81a144047ad9f67f0556225c66af0fdb6908202c043b54aefbdb4bb17fe4b9fcac388e30c459e0905c9873656b3d0d79c4e836422bda6d9ba55009bbbafe6f9f8023a1a8d716d049c6c948fd9dea9900583c6f13ea5963715ea4fb6b6c0f979a2816b8046e152cd93bfd80981c24ac3d75d060da0
+TAG: 3bc2ccf3d7e14c316d6037d9505043b98ba20521
+
+# DIGEST: 2d1b27948de83e32a0fa5be7040d896824ac1fe9
+KEY: 2feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e9
+AD: 78c4451e3be585a29a2af1
+CT: 743450a5ca75c9170afde7b7dd6e56a64d945993175e929edcf2e8cae677953d9c663e96230c3ba6b507c93274d6b7ac37d96d9083f08c629a12be5b450764a34ecf4a6f84fa0cd4f63b121a8027bded2f9acd176c022e8340a98baacfa198af22f9b223887aa2eba03097e4168e1a4e3e90f25f4b90dc89429d3f5f6c853f456d8336b669a7b4e49e9b9ce63c082593aced7678b496d3fc907c3af703fdd4c0215a91f2cf16ae81fb4f045c6ff3dc856bd06dd833d4e824310400e45cd59eb6327261ee3fc694c3db79838d0232e2b9432e90ea0bde8a39a14c36d240128308ffe58471ae90f156928b6f3acffc83496304217de9093a34ddd22aa0cef94f0713151079bf41c12e43101108b55e8166460375af4dad155b
+TAG: abce5498e41fb9ad6ec25bcadffd93fe307e7a15
+
+# DIGEST: d35ac8b9ece76d43f1497ac8681c5077398bf2ac
+KEY: 63b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef16410
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3b
+AD: e585a29a2af12feef71e10
+CT: 718d77763ef30a884de7722f839c774904d9a82b4eae23412c877b69811af2129b9ab2858804f417600434709c1ee27442e56abb569eb546eb7df3df63e6a0839014a40c1773ef24e552bf96d9d85a67857a73b74996ede90121218cf221dc3d338ccbaa71102c36c1df7d4987ab27759724022d64b0891e87cb60c6ffbfd597b2112a0a24c7c9e235797b7ea636671d3523edb6714f1788c8d71e938226b7b1f2e1baec2e07d1d24895ee01f434cceaa63db35ae3c393ba78757b73b006d82fd4c78ff90795e18d6e78e24c2473a8421d7e3ad2b07057f31ce53e196f3f02d407f723dc855c72e15949c27184feccbc3bda47e4f50b7ee9f36a7e65f024cb5e0b975a493b9aedb9acfecf7ab60569c16675480dad2bdfb6107e0daeb3
+TAG: 659d537861e30a18f9f1214417e973afab90baaa
+
+# DIGEST: a3b33fa67f5c471a60a63dea915333550bf3af04
+KEY: 99200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f7
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2a
+AD: f12feef71e1063b0b4e6e8
+CT: ed8da42ea6b09c913196f5757c28f749ddd7a9e1404ae6caded36f3e093b107e01cf3b8fff8714dc2e780e6c33d0f07995d99f6eb70c8e36e08598fd0c11ad9992e5738c23a8825aafe57b3dc33a9bba2d2e7a9f563a773cd5a4888a8432902da2ea39cf3b4b1170032f78daec21e82413c55e8b0e660bb6cb5e4d23349249cc51d8620bf77936f72f7596674d1c2e1bf4faf5a2eb6055c981fa441cf8c982c50bc8c71b1339f9b1da8036fc794457fbdf6c410343135e02504be9d9e7674cdd925d0ad8f19b269af2f0d1f9e3a8c6d16df6c7d02874632fc56800659a1c82b2ff2f2a8a31ce81060864d6ffa94587fd10802dca0d4b355255dd357f04abb29cb7e351c781247fda8fcf878ea7323728b47987e3d193e1f1c08272cb569700a148b8
+TAG: b0d46e23a76083decd6cbcaae22db5657626e6ad
+
+# DIGEST: fc45f684acf19a1dcbf767f671396e793430d7fc
+KEY: 3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f52
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e
+AD: 1063b0b4e6e899200304bd
+CT: db65b42cf3242f4a7a40a335c790d85c8adb2a102fdda1939599f109c80c36403ca06cf4343dded58d1ba3b054a982414ebd2e22e3338c511227b3ee7113502aedb91befead70d9e6a3c9d0dad6b38197083d9828dddd8c6789c06ea44482d30eca889654d73bd2a20f0fb926961135058ea831d4662d677af227d404458b1b65bc328eaad4f60cb64e2ba4bd9032413be2fc5a993bdd35385b08b0077969d3949acac73b824756cfda03257cea0deb428cea88f7d63435674c16cb3da4f6a64a6ae1e98996a852e9e5815707ee6c375dd4dd7391242b9d32f144e754fc49487bd13d9b3cc1747006c24dccf344250da9a4a6d3f9b865d6c04ba17af89f47bc01aba92e266317e8433b13b759c2c9ab6f18a05a045e7c8d52632cf3f64d3f12b1adf5487fa36fd
+TAG: fccb6252f6f517e13de29c6bf7e8c32bd0cdb2b5
+
+# DIGEST: bea3f11679bacd98ddd996236dd603d319aafc6a
+KEY: 7d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6
+AD: e899200304bd3508132a02
+CT: 61b16df94f975683ecb519d3a8c2ce14b9d73a17ecf16fd46352278c34e4bd6aa0ca4199fa896de693dd866b259e244ae70e68911e94102e1d8488cb6f14acb6a35bbf3667813f3b050af05f2701bc372973111cfcffeb79e96eacd878e8e57363bb834e65e583a800431f6c29b823ca720626d2a33f6f19e936b5d1479349735e072cfdd57129bdb0d676ecf12596b3b196f169b268b747ee66222a0d452f070edd7563fdd398a0a83610117d130b01262d86162055eab3cf0afa187484669804137e84ee21d253fd6ee672ce685ff607d928c59a70c787fe0f30bc574ad30dbc88a354b7a6e828903820d60068fb3b062b054a6bb0dedb738bb7dc5a69e51a1d36d6e0eeb43c035397a44bfaf5c53b7fd90722f75c55020346ba56f73c973f4d3ef24b2d746482e4ab0620
+TAG: ce319534af63b9e965e214aba9a6ebf602c7653f
+
+# DIGEST: b0ccc9b5ae13a7f8a01100af61a34be7ef6ccf6d
+KEY: b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729b
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304
+AD: bd3508132a027d1ff4c047
+CT: 4473f6dbf2e39c927374ae7009c3aa0abaf855a2b78236afa2e033dfa40338035ca76f64960999e983dae0969ab02a6cf7e6dd0afcd5f9db596973d24e3a37f5bd6f685a06c10d2d681d7f4113e4b26f62df87b97cfa6861f7f28986c4f372c39e536ec219fbd96a0484a7c02c3895274c97b81e3330ab1a41d2046f828145468bc787e88a561840a00720a36a666181310282ff7e9c84ab39549b777f278a484d51aa92a69aebfbf3151ee89c480817f7442ab2e64f5ddf41ad36ede584babc7804c9da1b51257ab4a87613ae1edaabb9a82883dd9e4677b3e5d2c276911e23f79c1b3a300438eddddcfdf1af496caf50b4e92c37ca2f6d4968831bed614078bf53d28ef73fcf8869f23b16ecc55335dd1adf2f40a39ebe4933369b65169f13a3995e3e39348cf12fd965efe2e75fcb5e
+TAG: eeeab95ce23e78854bd1cf7338a915d7596f990d
+
+# DIGEST: e2b953c833076a52442a7afab46150176c47b730
+KEY: 4706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a
+AD: 027d1ff4c047b3ef4f57a7
+CT: 964febfd22378418945efde794a84f6b4ad1500fe0255d785a4dfb7436cd2c0431fdd7dddff43badf4de88d74107fad8e44bf605f4805d343b20d27ad3e3d46060e0e2e4642af74f249deb26b7175fd0568a47ed36b71aa363c8267bcb5321e6f0615ec2e60dab5e8e5b77e365bb53cd2df91937332e693db4ff09bf3be3900cb757466be7f76bb0e55a58adc134f51958872535b410ea87e876801c664e09cf263d4f4e99c1fccd41c0c990abcf49900859efdac3d472247f212628c704cf27fda26a89ca5e984a10335290a950e8b0489ef67fbc2d675523774a2df4c8325172b9d578a1f73ba230a22b85e154d013d0f04ee8148a7056806249342130522b735ecc17ed9fdae4b0a88a5e7f769a13b12bd6f3011c7e5671893b0698786b0f59c4e455a043eeea5582a97bbbb4d3af5c7660773fc2
+TAG: d6339db6207b064fb810591f32f23a1f1609fbe3
+
+# DIGEST: 8e84935ed1bb79dd38ae38924952e1105101533b
+KEY: 1c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76ae
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c0
+AD: 47b3ef4f57a74706de4b38
+CT: 01092dc4f294a74d082d61f47029e2015f3d43e7094c07e88d7407fbf27502e919d80d9a0389ed9cee571cd2decc43257bf58c393e492e6616b4ba0d65a8dfa04b91c8cf4f864cd7878928a4277b1fb51b730def9cf711061cea8c64ed06132e5f0a4a738d194295009eae1716a26dc7976ba139a87bbfab681d04baa7753455cb749c1cd0b4c7df77fb6e4aa124ba9338a3cfd63d4ece35e062404ffb0c0c123e7ed8732dffc8a0739b69c31b078e38bafa0593ab8a9aef485b663d302aed927be0850378cdaeb82ec8860daeb9f8845a2c77be5759331c0896e314f322d25a0d8d6e4b9d970d73db705508c64fe26215cb9bd602920b5fe1769f3ff1538528c8bd1cdeef1039d7a94e014cc568d3f495c49888c0f18ee0607e2f276e2fcaab2746a3811555a8476ada570da5ddbf15c78014efaeb55193409f2a
+TAG: a969b4a56862275eca92c3a74f225b64fb76060a
+
+# DIGEST: 99ec6b669dbedbe99548117f37189e669fc5d8a2
+KEY: 101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57
+AD: a74706de4b381c692ef164
+CT: f5fc7aba347a577477f1082edaf7c46ed81d71c06262acb5ba1e893525ae6419ad1536a1ee5e22fb60492c8265c15fb612cd65dd492432163a17d98fed2110fa160ed8cc51ec0b3c165fd19421ab5209f5b29b94dec85d5cf9c0621fb46f0602910200e32e28cf5ab5e4ed45ef913e1b4f589e8a7927275729d6f885c67e706eb37594b224f7d78aa61e046569b5e94fb1f93d6dd973651b9d4579c9f6c9ff72a96b2ac5e80491a89a884839a162e38c73bbf3edfbeb66ff2af303c0eaf51d7660e02dbcad616891651947811c4f83ef229f978118815dfcb54dd926e8ebee7938c566c9360d35f608ed64ff985aa9e85828c204ab2338b4b77020aabbc628a3b683fb00e3193c961573cde0b31c2f9daaffa8bf417a6f84c6599fc61692a3df71cd51679111b4a07c2bef3157df168b608d81ccc6aeb13c1365095044d1c99e
+TAG: 63284acc9960ca0632087c68af42958eced06a39
+
+# DIGEST: b55f018cb06f74f0a9f76e65a23c1744ce7535e0
+KEY: f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b
+AD: 381c692ef164101b89b476
+CT: b4e3965ea00f0a6cda49d5586b74e93a8ac4cce1498cfc4cfcba2570ae509b07c8600f04b05042eb7612062c56bd155ea8577dcefcaed2cb91b3a4e2230aeab8ff825639cb20eaee4c8d0cc7b3445a3e5e339ce698898e6009fbc228c37ff8833d06aaf51048a5424be4b40b82aaa61dc7ae130fa83abfe72f6341c78eb3348a9e06aaeba457e06f08f88f3dc1a419238e115f053a456cba344b7e292eeb0d7c2281f3129235f741920f24e9214c24172e19fad28dc7bc50d759ce163321ffbd3e4e6975d4be5ef6d07a33585324d215ed6740062b7fb5a03e008ccfb1c99c24f0732756c115211ce1e8ca6bf8376dfaacad1a4184da6f9944a14c723e4da5deeb202709c59cbb4132bb17f404d127e3e95292a7a2f6335a52f31aebd3685162ea9c5ebd16b45bdcef385dea9daf4fb02d0257d05f81793619689bfea1f18ea37506d4b4d6
+TAG: 1d7172f30033409663a733a01f6d9dc9d7afb7fd
+
+# DIGEST: ac3202e483c67fbcdd751950e1497feb3ebacf52
+KEY: 520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef1
+AD: 64101b89b476f72b27f06f
+CT: 12925d23d5518dfe5649c89b1b5f4a7cf0034128c714437cdfc1e7aa049425a09f11b4ef0d9a72126b0b4ac637de3a3519eb742f6134673fb521e2b556e5f6e42ac8f41f4371f55c18e318af2c48e3d92945e13eda9b1e4c6229702cee2c7539b328faa056e7f7aa5d0f1c1b7ca9abdb34709573b8359609003ea681d9814cfdc9cb1d043797f32c4bad4a36c53bca5a176f7c1a81fd94cda5992530c7675b49d27f20d16958e63723e52c43149166b2589712e3d5cf07949836e5fd471038c9acaa968673f13c00d85be51cf95360c672f88b95bdfec7869325623ed778d67d00bf41fb3f1abd681ba26e9ae18f82e58b12d80676f98a2a39f0e2f55c4ef39aec1e09b090aaeb98d024c94ae71c2c360dc358bb57ff458627eb25612ca4d4fd7c300a4a01e81c2157cd5d496c234574b556154327bd70ca81d1dfa8b13519235d3586140aecfd5157b4
+TAG: 7616b97262344239b231267986d3c3c72bfb5d28
+
+# DIGEST: db82ae5d79573da2bd7215485a92063861879c3c
+KEY: 71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b4
+AD: 76f72b27f06f520c9267cf
+CT: 281277e794af0eb7df69df600a96a5b07cf28f89ad6398c58330aaa30ece2b30014897d7aeb2a2273c06d223b8c97ac3d5d521e68a0cdaf38ff028939600b6d194fdf6ca2609e412e594497977f3a268a0ceed502f534c0d36e9b39c72a218f862454d55d184c73c2a65ab3deff2fd8ceaab9a810294d19e416a7d79a262d6f9d0f6aacff9b3f30765d35a6f0c57f6133372ba02828b71112e6586ae1efce0b5d909d9b018f17a720dcee4ed73a3953e5080598a0ea290533e71d18789fd8e5392287172230b6993abe6924a4271b003cc3c0d9cfa3c4e483896d7085749b5a07a7395fb909890fe259632a73b974f06a6d02a9b4c62f314b682ab80fffbf535374fb2b6dbca32f084eca0964d54344ebf15b489208ef54fe5b9b3b98dd4e577d868a6837d26f75b8084d77a3cceb5a91b5d3cee8abf5e30e1a30b670bfdaca8b278e8697e0a0fa806b50ae69faf10
+TAG: 07fceb24c68f8a5aaf79ad890c1727bac98a59de
+
+# DIGEST: 902d703861f9872e7b6482f854709a214aa98731
+KEY: 9bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc6
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f0
+AD: 6f520c9267cf71408a4172
+CT: 3fc7262c7b9f5a2515cd2d994a95172821c7a7d78ce103a54e10778c8f6e2e0ae4fb83cb71d6b75d1bf99ad201e3c8b5cdd14ab91a1ecbbf2570e5e37b4a77a7f7228fd0169809b3fe57bb088153a9b932c9e263931c88a173650d237ed46d0e91b859c758311ecb245d85c0447182a7159576b8227ffcd3d7198ffad4320b72e563382daa72c165866f9f76fbdb39bd2d361556b4c8172f5eb1bfe0337d4097b76b5742615954a6e1c089392c90dbc488b1bf4621e6e2d7b7e3529e27ca9260d1d53fa70d442c93c29991a8d907ab7a3564851083a57d21b89d4064861e52e8fd953f03c8cd034718a03cddccbe7b8c8eff552374ac650e988875d7b4110bbb0c37c87f2b6cb0b88cee2a494528edb5a0d9c3a8fa02000fcb5f668533eff65dddf9ab91b7f35ba6a53ef31ab08808d53a7f52b0ca5ec5e183f83cec21499171785afbebdcee06a7a95be6611344628e91ea9552
+TAG: 40f2b4c52d16bfb75db7c9e766be1571b35cbbe7
+
+# DIGEST: 4becd26b9b5c7bf831523f44cb72c8e50ff8033e
+KEY: 72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267
+AD: cf71408a41729bacb5877e
+CT: dacf6f256ac1d4b3e2f7971aa129681852898cf9a6941b1509174f85bb78dae6bd2202e6c7e422a36e16322fa3348a93ff193f2927aff6a61c265638e99ea86f02210da863068a646bcc6c0f73167ef3b9e22ac2336773ce65dd4632816f77f70e17744028e75630a756a0ad250e88a267fa572c69eb75377fc32b2b374850943adc08c05339862382e7aeef6e909ee67820b39784c9e1851c61b0a2cb66f9c40c5599169c6c1d5a008685222b3704c9a5cdee26041957bd0fe11749a2443f4c75a15d3c236ca53ee1838a7b6deea90fd3dea3b73445a70f4ecbb074ca1f9c3ea962c8a7af55a3d8eaabfa5d25c6fccdbf7068ec04052aeb15f1c4e2d577266eee16d2761231eb1f1c16bd632a26d1bfe05731161896e7b883017f488da07a8c6a9ea6b328d6db18423cb8aa20ee68a4e9b40715298a2fae3c1613d02d217d29e10a745f96d2aa60e289701d4efb22a85f3d5b688ae39ecf75
+TAG: 14df58551290cbf36433af1d5c4800a95f8059a7
+
+# DIGEST: bcf4785d0e3b34c55cb2505b559fdbd525deaac6
+KEY: aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41
+AD: 729bacb5877e72cdfcfa76
+CT: 4da071822155fd88fe886af96fba4c78220f9759d5c65b97f6bc2fac0c727004625577844286870477f36b8b07625588e2177cf568703f8b7fed2f5f2d0765b320038f450704521b842bdc69e2c9aeed028490fcc6085b6a63bc1d14111bdda123518c2bde2d145d0c965fa99538fd5e602528a46f4ea97ed4b5b5b014de7ed449af06bb1b4ca62cec5b91097747b7a5318b08d98c369ec4ddd3ccc5919b22faed23b8cce94ee1026c56fe5b6514b0e7de0054623a3e025528ca80c371c29d2bcdc0514a25085edf11f82bf12d66ba29edf4483814a3ad2689eeb39265a82a20db2002c7d39de05ba1835a13fa792d8e4c4ededb578eb734f13c66e1e54ad07de1a6de06c229a9632affd97d27eaec4492dd24426c0f26b56cb2089ac46a572df484b42cecf8c930ed8909bc6ba75edcb131dd917035248ce3ed31a33593f9636d56a0b519757f7d39496570973448b15b48c9543fab9d2a438d5bdeb15e
+TAG: 485e275d11392681f03049a38e4d3a21b5942494
+
+# DIGEST: 13bff121568d7c32b2546132cb4ad490cea9303d
+KEY: 7c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb587
+AD: 7e72cdfcfa76aed06707a0
+CT: f11e4f245836de61fba3cd50d3dab04d5dfe951045fb5d4692b20d7c64c5d4338c89355c859a7a19be779cb4edf7bb5af6f12cd9530ae438b6e3ac39a136e7604fa952aa2761c96c9422279d7cd91ba5800a82975561770e6a5fec1b4980aa24847666c838e2b20cc9b36ccf99eed7b4f179c5d5a8504a8a624f1e8d8a6a3ba8f8473900cf830ce740f8aa7714fc2e0ee1899440e3a93097248b986550e7203e173ad9a2ba4ec68902ebc2b32954290354a4b4999be077db2205c1315d9014cca579d44a162358804b7b1ad276b79d71dcf8b2ba489de860d0c015b6df096f8195a3042e37e68c0c2399e7a860476c94b534c650e15db3ffc5a706fe89673de6ecc7ae6e05fd1f85c092b02fc578bf6dbf6a394e8a005148dfe7a186616ee54d26162242d9eee14c218e7882ed6077a4977a02804885460b8023243533536b932a57b7724092191e7b4d1531b58c43e0383a0ae134fd29544d5bc33b466f167d25af69
+TAG: 027ac5addc74f1e1e372837dbef5d44d48fb14ff
+
+# DIGEST: e0ec91f0baa3c5fd0c50f135517909e26c204af3
+KEY: 19fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da4
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa
+AD: 76aed06707a07c3dab6997
+CT: 2baabe5ace1588f81b158baef541304556baac57fe7a1ced41cf27994ee77e6252c2fb7164c67350eb181acea36ba7d3a2c0e916d74de6c7204a24670b023933de10be2871aa631cb1bf51ba3e514b828ed501150165b90d32102a17b532e7579e02f83953af57fab4c884b72f375e94a95fd7fb775dd8a8c60c13c77e0f0c0e2a425f633b1f5eca906a6e9079fbe80a9838e41d89371eeb0283eaf102691df5bc25b104a35ae0727c2d4b1a342377a7e9f5f59c55da856b5b8de96be8ff20d1c7e3d87bca0646f0ff188838d38075c82fb156c8a80b8f5fc4d9dba12a8e5e0b9155f0d0619fbea43ffcd358127d10d73dd8cb84b147e13a3646c04f68631dd3cdf8eedc8f36aced5beb23d6b0ac247c272fd1d8057e1775cc2c9da988bdda7918ff4190bd4720cb90d6b26b1d5fa91a72f3bce2e7359d242cd05ff927840126aaaf4c731ecf0e17ed095ac30d49b9bed6677e13dea1021c70e074bccba68cbbeba2831cc0eeff68
+TAG: 6276304cbb4102c51393621d4f76ff3b135afb2b
+
+# DIGEST: ee7d6f651db434a281b5cc57c2c418db731c65df
+KEY: 2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707
+AD: a07c3dab699719fe882eee
+CT: d5e77afedfb02589cf443cccb4c6fd586c7aab72581af4f5966a5b05bde89bc0db6214f73ac4eda01edf99fbe7f2d09356b475fde75c5aecdd38747bc2bf4004e1a443d765e5c20be178231b3d0f2e50a646436d221e15eb1a27982190154b5abcf892424714f5b3280e4895d79ba49f4e6ee22612b8a181c08a7a7147e6af2c42194bb7e201a16f67d49dc3beb5b1d5cf731a0889ef24fc28946247f273134ff1b93d868f019667b4b01a0a37266a65590a9ad81fc40d43b126ae602280ca5d8b96441d59d3ee619e9181668efae6739ade593db6fd7f87f83f7cb4a164ec5e23400c2dbb85f8f2fb8172e67176f7e9fe66e6e31ddb5e6935058a1ec0945c2535977bfd717936d7eb46f9e3cae26e2021f6f5cfc062dbd64e0b72540802f1b56b30e61d400fa481601e83b8e0ecc8551e9e2ada8eaa278cd13b235e0cdb62992c4e7fc407b78695e18105092011dea3b2eb1f73922a5df5b74e98a2d0a5e74c44f8ce8aca4ab878abb78fac7e
+TAG: 4f54fdbcd07f1d7ae4d66dd32d084ce4c116fcaf
+
+# DIGEST: 810e1f01bfcf6bc13ebae7861454ac133b2d6cd2
+KEY: 11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab69
+AD: 9719fe882eee2fee55ed8b
+CT: f8265e8f3ab952867e0954a72231823503fe0165b9642a2b1facc2ef5c1dea8e063315eb0c6cc66234000abb030dce35273dcb1face27c68be91fab8109d64b9fd0572412d548fc57e4aec883c0222a93a604f58d8ffeda6481bf430aa487bb253f56d0811f5fdc1547ebeb9aff478f3ed0e6daeea55c0b70147748c9604c3ee738c14363f54435c92c05ac60ad92db861d250fa1e6fbde6718a94bba7eafa5ace400439c245db0f60ca52453ed9867340a9544e53fd6c9709736499afcdca771cc33139ee14386c953dff7d09b3cf79f6db3b3e862e86c564c4379c8bce7e28ab0f91f284fb66f6bf148440e3a971c9e6ec312b294eba8f681d565facb3475166a3282c7a8ab3d364f4df4ab69354f7b9248e700340659a19856b302f57808575c4e70a49ab56789172a666a41d814be589104dd67a48c9f8fa8afe98390ac23eedc82b6ed0d7e8f938d4bd30ab70f0c11aa527f5ace3a72405497d83f01a66fc9fea2f64d764dba2db8c235b491b06c183
+TAG: 88ea977a77a18aa4020c9a5461ca02e7f8d94a4a
+
+# DIGEST: 881551d50a849b7e81f0cc0d722f631e32a4c97f
+KEY: c695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc82
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882e
+AD: ee2fee55ed8b11534c870d
+CT: 89e5f9ee792b89e51663abbfc31786b7df872f3666cf0e7366c0500e6ef36a4339e71fb6b3382a32b936643e7849cc9fa1f6758cb53f7f9140d825ffc45ae3bb4a2626c9b518a77393fe3f96d7a8b3f7e2115f99b5c6da70b0cff31aa4814390242ec7fd9b1f9129a49d906ab343a402f6871f582e60514b3faab9340d961135d4c96738b38d5b62813c79169cb124818ee1c412d8768fc4d5b6088c2d61e0da33ac55165c09df47dc0ed798da978b88a324222fb4b8b60bd0cb340329538e5127c06080f0952b079c0b78d13b012d3d0307f8076b8d9ff79b94525b958212b7a2a4ca28464e02063928f26fe076e57365bc7746717efa4ed86641e0f122291e53dc32edb57afe632db70ef3fc4030c34a05b3558f745d2b4a168bf290770569eab01f4dad9ad3d9a4949eff800b7bbb7024ab5ba8772e72cf53a6e316f57491ce13d2ad63a178afa51747b513e710c2eaf94d2189a225ac770e541e7b406f109694e313be3c98668fe64074836643fa961f2beb88b6d0
+TAG: 1b809da43a0a6dd439889b6a6958dd504e94e8eb
+
+# DIGEST: d525f72dbdbf54db80ddeb9c2a84aca41451353e
+KEY: f1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed
+AD: 8b11534c870dc695b814bd
+CT: c8dbf609b350a63957dff770a6c143cec61f885fd23efce164f9de00f68cfd38a1a22569938f4aa5b34b099dd1243e6fa8fa8018641ddb4c32dd532144b939db8756a197a0a6f13507bdb3f8aba1a20eee94df74fd341cc78001eda37e4464f442b3905e1b163d5f7eaa51145fc72b10a85925136e66abb3a17e787db2aa54b666b8330a96c9e1bccebd596b4222cd42daf547fbc7c4630980457f3936e318c51f5bdd6b04bda5f733a7c57580e428d9e163240c47313815bfe20adb2f89e0646bf725d54a2e497c2a838a3f1f90bbdb2429fd2842258d363c841f4a5500e6252fbe396bed20c3c8f633f38a145422b4af4541821926b4d0d96e7743ba226f67c7a4b1a4c32c9494146be4a531b1fa0bb24f9ee44f99e4217fb61a87645b5a5efe3bceb5558391dc367354e64ff2a90eb5bd9ad925a2a4a7104bab7246644dbefdee6d93df7028429ab1ce03ac80623c502286da0ff5868b934a673dd431acd47985d3750c295c087551aad4332031b7d103d590203422a10f46a792
+TAG: 3054546598b67d893cd56d7e439b8e3c170999e4
+
+# DIGEST: b25882426b4730205533cfccc0da1de1f6f2c459
+KEY: 2c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c87
+AD: 0dc695b814bdf1a87bb105
+CT: 80b0591059c545a1e8b4692880c1425bbc08a4d159f4310504d931c02ed21d2fdc9256ac6a151dd8bf1825acb65d43b203631894539bff0bca9a74e732d08f4ea1bd44e6fedab499284fe6b20dc91b6c71517ad9f9436cacf0d6f014eaff418d64269efc62a7363091ed9b7648af113b9453bc1a66bd041ba370c4e654642abfe44099f78cf70bbcdc43ddf39bcb61b01cef9dc54e5d87fe2b95a85f3cf23f8e494a98dafa5bab420237f01b2d14ea6766ed9ae79630e77e8abf99ec62d2835338346bac866bac29adaecbfada8407a96048c5d135c90bdebad291476ed4b25bb7d8f05bfcc43468f2f8d922948faa159fe75cfe322e8936d8c536a7dfb1a040443e6bf8bf33e9dcdb0c3e87c80daeabb09aa14833c18e90a632571f714794f7a70fff7e69bc8b824243a757038ba74d79b38757639e2318fb1c99a6303a3d33de621104afd30a421865ed9712927cc17c684c0417b59b85fc3d05bc93713154e7e75111ce2b9c282e4bcce2d3c38416a6f77bf9405a71691815003dc9c555c3da
+TAG: 16074e9ebdb9bdde598d953f6a50cbea0c488567
+
+# DIGEST: 939442486c730c2cbd8df213d81310e50534f06c
+KEY: 16bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9b
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814
+AD: bdf1a87bb1052c6755a7a1
+CT: 295fedfde61b2d00b6c1d85f0ef6e34748a9d975fd4c3bcb139955054274af93dbea9a9fa3c28cdff4284b4ef20bc07e1beedc505a847abe0c9510a736b589628fac18bd5546664597b53ddd8d4a9cd7f97129e3eb618a76fe9f9386a97424c2e2193bfbcc6c10529ccb6bc16ed9109f75936760b219cffa47425a8c66c3f0312566b502278797ea1441e383cdb5618636bf1f7faea7c83d504c244553cd88fb853059e77067661c3906bd8b29aec5d066d9dcc735f590fc8362b567e8237d2c9fe9b30c9d872cfa02f4b1c7bea5afa527b29182c517484ec01f2abd89eced89518b10ae33385827357f7dbf6e28b0a7d825cce15076e1c94629f0e5f950a8fe9a8f6da65723a14071fa34237f9d99a482672e12c0c99c3af418da0fcfd9d9f8d828f6f1ada4a5918810549395097096ed521f83210292053bbec97fa3201282ce5ca509cf644749e57da9c8648519a1902272646bad4e822c94273e09b17cf8bf307c9c225cc441addf7f62e4b091fdb7e5591a0e27fbb57ee53b4eed111854e47450279db3
+TAG: 55c82c13578d0dc8863d2d0a96d26c3d6dd11f5d
+
+# DIGEST: a7b522c0de411517839342925e8acf703ea12e8c
+KEY: a49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee58577723
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1
+AD: 052c6755a7a116bfc9095d
+CT: 16c05767af25ec96be58cb10c75ea2e10b72d3e8f8243b329127b5b78dcd2aafd19faead8108dcc5ca3010b4655fdb3815b0edad5d3265338481b26848735a3b6c58f8f2ea08e3f671cb46047859bba4886d9df89adde5fde5e34272df93f86c27ee69b6f9822d502aaaf18beb153f235a620aeaefa43f7a11340f329f45b8a141cab854e31c05600b4a84fe246f5633bb2b6525fef5aa71834bea19cccca9352393e5cba73cdfc2c7a04183cac16da16a3be09d292ef9edff7a216fd708857f65be99dd696ae0ac5ba74cc33fa4b95bbfd2fad8b84202377692b4e8d2bd9901e4f5c2458cccc207cf41b2f27d91a31014e610d1fd033cd52d9706d2834c7817a78a9441f02d95f8177fc58dcfded105310c577840f49eafe0408d0d387225e8cb080daebb5677abd3b02afb699985ba434892e59e19a8baaff0356c131235499f9fb341edb12741fc574c46a1ab35501c51925e741eaea59452f5f76dd7d39ea721b341d2715f7425fd1e5f5b05e397b7ff312201a3575909143a6a22a88f3490b85e97243222020714b5
+TAG: 7129fef93fcd67556fae5414c9936256b57930d4
+
+# DIGEST: f61096694be30b85b6571dfc8b5bfc4d364bd225
+KEY: 4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7
+AD: a116bfc9095da49db3d71f
+CT: cab46036ec877a6a1797192905fe5ec3bbe5c6ad8318bcfd47b8d28c892ab2e7cea9b1b01aa78308a1868633fb77972e436860641d20e07ced22ad9c558f0a9fe3698d1ec10ff73627bf7480630f2ee9ca6e6887551b440fb36da68f84b809dd78e0b3a780727466a4deddaef43f00e4bf31adc49ae5216877c437b23f5a384353df2fdae1d9839423b1dbaeeda2d5e873f9a0a0d1a9b6f031c698bf44ff2658b788c42576efdc8cd78fb12db95a1b0e6ded6fc7838f0529849e05718e14a50fecc1f4de20233ebed7905c8ae7ac7ee8d9b6b7d9e549bd57bea0e1a68688bdaf73d497170028af527007a67f3a165dac2f0fbc54683686da7343f8deaff9b538bc9e3f50cf13851f6c5958c9b0807313aa985f3730908e00f70b9108fab8dc50e208e3e1f0d1ca9fd0c174811ff87bbc9cf1b17b072499e7861458ec8ac4d8b5654a9cc3b1082097cb1a7ee1698c30658e20dc91d07feec0fb685011cd590095f109c318394ee39a09f9f8696fec9d964053a142df939dd481407b0c984d715bf73a1a5bcaaef44fd490cbde9f970055
+TAG: 482684a4f897baee64af8632c3d6fdae9cd187f2
+
+# DIGEST: acd9a5179a0ec782a63bc824188d838776bc1b81
+KEY: 3f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d808
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc909
+AD: 5da49db3d71f4b975c5d50
+CT: c13d301ef5dd85a539af93aeea45dd6022dadb0e834c2a115c594ed6a31a1aa522c7944348f7de64bd694b994625bc08d5f3d974b6cba8060ec719d78e4ac5992668a7a0d8c911be5867dabb2df3a4d71baf9d82c878b0b5e449c8712ee300bc5bc31347d09df05e06875ddfbb6b69bd4337908c5bc8cdeb81517c91fe025ecc21c6b91a9de42ccfb946215908966aad616ff72e23770e8e24ec75592959b728133577ce0695334184ad3c0070a6a0a0cd4464db13f32a265e5b030a3c742fc2e3a65d2a3844945ff0f9b572c676b78e6bbc61b8ef6e61377209425dcf77a8ce678957632c0b344f636f339c54827a4b62b0698888539cf01898fd35cf43def6f3a6e949e8ecf4010493481fdc3dea629adf86cab60d2df0cb9592b2b1103057895cdb31dd9bfcd476c2ae9be5961f6eb664a5a533817ab12f4522fb976a0331d4d6f91ba89fc4d83270bb3be53a2094ec0aa3075ced8b7ef2afb94fb62e2c843403ccd834fd85080670a4f47e623d14b0599fc3d24e7ea459e155a27741b77126a75de4d09d713404ab352fdd936965acdc5fce80
+TAG: e140a0352368d50684c284754796f3636f398de8
+
+# DIGEST: 152118d780c866c5eed3a08d2d9960cdc5acaabf
+KEY: 8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea371
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d7
+AD: 1f4b975c5d503f478b22dc
+CT: 7bd84f18e5dca11f90d045c8c5ef6db4a5e66a6412e49393abce42b147d9d301669563c4c85526e537a54e03158d947efd9089fac862b773a79051bf50c35b26f98b0d4988295e5355ddd49ed1a2a21623e6546675516a1eb5442bc2aaea887e0ca0498346a1cc37dde8d82eaa8fcc67ba43d3bca7aa107e9d2ac70d5a526e9107dd8ca08aabbe7aa9f653db1da194b3701cc7c0d117dec905c2cb4cb02a5c9d48bcc4de6a114a17f83b2f7f926bbf3220ce3ae209caa3551ccb53339829f52a2068b161042d9b48172fdbd7be527b4cd3abf1b0e17931edcb20c55f245b3d8745bcc5a77941829561ff5e82c17ce7413bb858d87d97c9e9c362f09d5ad244417e1afee0b64c18fbecb4e4b6ea64e2ba87c1dfba250d092eaf51de94c60299c5c4a06c578c89b3cc59ae454c06902df22db0b35777b39e473e72945fe3f84182a094506c286a68fa3072ac46091d33fb5fc0d89b86b8f03dac299362665d09c95a5d21f2a5f5e8ced683d45f84a4fc1e3284d99a48fc24c6325162937e6a936f684481735aab30f6fd47cd3a712a866e13ca40fe4a1176c22205
+TAG: 42766e9cf0ec3c2535b67b7e44c309b5bbd1e553
+
+# DIGEST: ca91b15125e07b81debf75ff84e7eed4da5808a0
+KEY: 1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf7826
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d
+AD: 503f478b22dc8253bee6fd
+CT: d38a66c515a4e30c1a341c952bc8344fbcd221f2a59ac415358764d459adcbe620c76dbbbf71fe44e34d2cdb287599748e89e0a91bad4a5053bb72c23afb58eb39d468af969210146918ce17e6c399550c26213ccf964de8face807ca5011a5fb12b2c9b8db6ba11bb725ea77264fb1aec8b164f3ca3284e331f0bf2ce8ab2aff928532b3878d915bb052970559d7b540464cf493a793385f56f6149228e9573621e8c67756158d33029145fb5af82ef7fb5ce885866e578c6833d5378cd89e626879deedc60ffb910e403d5018f42840202285f846daf15f7907d6f1df0eb5a8b60f484bedf44cee6a4da6229c8ec9e11ded1f8e2d5a519adf1cfea40a838195c322f7517610beb0331e8484d20f22fa6a873fb1a520ff31357fb2fef8429ff54a9b1160232a2b2a73e8c45de6be95458f26b7a4e04efdee2b33a8e599ede760249f0261d7ce3d23528326ea55901bfe35ad1401322a9a954cfee52a376c664a5a99c03e0b9b033defa54005eaed64fccd87eb1e655448a66ff017e79320ece47105ec6e99051af737ae73241d3c1eea5c78949a3f32c351974ad273f66cd
+TAG: 24a3e638be17c2e810f8bf49a3d18b7a2d7452ea
+
+# DIGEST: 93d06638fe1e836ecdf5d30db3e4fd0660d9d701
+KEY: 01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22
+AD: dc8253bee6fd1b174c307f
+CT: 35d29afd4110acca674c73c693fe71ca34a7119b60594a8df52c24e6765ad9bd30d8b65728cb42f3227a9048677647135a385894cd057c494b6f52af8f5c099135ac8e344dbea7a152154ecee4ccddc164713b3b2d5da21108ec7f6654861b5b0dfd60865f75ac73f433eca1ab83326924fe8a9adf8fab10db48b5ccd27ad51af9cf60138683c75b9c49cbb1dc3c6be9bce77baaf927f7b8da4ae66ae6dfad02862f0ee83bf4d76c22cc3cb421bd38dabb9c42cfdf59efa757a61befb17a36c76ab07a152bc09df293b8e3b31baedc851279eaaf5a6a25f8629642c7a754139da770f54cbbb18daab5b5da916e40c1c0ca48bbe30ca4ae4fc89866a935c73110da8cf938f1ff88011bb951c0a041198d809365c46d0e06d4aaab806a46da697f2eac0887d7744d63a550c9192f1dfc2e6f3f55e9867b0e22e9550d61b9d6624f4ac2808f4381fb71d41cccd203acf24648e3f5f92d415647cfa454dbb0b5e23e6dc40926814330c6f01387435ee1f4d4a5eb95cfdf992736823dd666b35f79ad88dd317fc0bd82bc98fbb1315bb2184e00f3d1f74c751138c28a985a1eccedaea57940e1
+TAG: 9b0585dd97d9a97d592556d393f782d794c32be4
+
+# DIGEST: a12c8aa71387379d0e43afa0321979e018d56547
+KEY: 9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da1
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6
+AD: fd1b174c307f01be95abaa
+CT: bae3dfd4e46015aff8cff38c11e0342e5fbc237d241d2d328b960e3341d49af01d3c364ea92c091b3fddbcdf7cdb8110f1ff0b266e9c09c2877e2750405e15c8fd75301f590ad3a3c30b3f48d2b6d0d47bf652e59497a00c5efed6268a4d2d896516082500f191c8ea6e22ab6bd5abf6e9b053ca6b36c80e583abd9dcac3ab009284b9f2920e498984f3324110aab151a10724ec5599c6a2a40b282d20969dfc956b724655873215939751151b84af6082807f58f612ac2f331430633e09c24f381dc30b8fe3a1a3f248d10c6194ed602d7a1268a6f02d2a465e4bbd4de36b0d89ad4cc48bb341bdad7a42f31e86234c1a46984f4b5262f5e2e298cfc9e59bf79782f3b08c77c16f6652eb48a34272fa5714981503edb0929c8ea3c8e24a43fe63271ffef1891d989915ca222ca6c4ffa2df3adcb413f22c14a039a874a578108502cf7ac990774ae34f266ac3a606b14a971d82b0d3e063eff4eaf6a1ffde96794f73ecf5915c6a559471d879d4d71b6f705025b057650ec70cb1ea9d77e24e688a068efefe11db9cb5681fb5ae28616e5ceb29ef047565865847b557baeb99ca04d77c74d73bf6e0
+TAG: dc405467227388fe499925a32262985337280920
+
+# DIGEST: 8a524c3ce814e3059b4c7a6ac748783ce1385c68
+KEY: 2305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f43
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c30
+AD: 7f01be95abaa9bee585777
+CT: 675e75c4be936f4f01cb55818a5051e73c7ba82dad6b3f5c135308d69aa74476af6e45043369a7250c71fa48aab0560fece0b258f7a8546a468857a58389acb15b06c2f98fa641e9a5fb6effe75048c36a4eaec331ecd075ca3a6c3c1d254a1ba62e0556eb15a73808c4a6ff4eb94a4594dd7cfe88fa958b87ea45d5fb6c9f211e426ac075033438648faf57c513da828753a388e36ab4e4e6a9f1449d7568035ca499b7e3a7054f7c8158b186ab28aa4e6456cb31345e6c4ef34422ff3bbf46651e56a7c82520cf7e9cc354c5bd79d23d07e04dfe7a58285b196e6e7c247c318851f23b35b71af46b529c501af7cc588894d17fa1fba6f3debab63cf9e214194b10a8694453c7f6e806e6966e6b1455a7550d98c628cf8f86b1b76479fe45ab599047a9966847b5bb3b334a753204757b916b1cd755f7554898de0278505140c8afccd9a5514a8cda06c32ad50022d87f02a197acd2db289590d2c2ddcd4a0f1ba29ce1f3fb3e400e7b0cfd1dd1ff49e07e626b2e05e4e649396f92d7ce7849e5c78cfe91d27a3519dca3903228be9fb97bff4ef2cbd1c9d33bdccd94b3e9275e0086dbf2f3972da7d99a337e72
+TAG: 122b6197b4cd640a8389f52203e25a8d823fb490
+
+# DIGEST: c31dae836928083019ab6902865d9f14c88fe27b
+KEY: 50d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f437248097445
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95ab
+AD: aa9bee5857772305daa4b5
+CT: 50522331acf0b054ffc13847011df9a6a993277b66470fb312fabc84d6af6579f976b071144ab5edf17a0d3cc2c6d0a12ea5de0e7e17e1bf46492db32ff247795a51be91a06169bbcdbad98a80ab1bfe658299d8f266c147291c5e59bcc8ca72f3ea3576a94c2a58eeea2bd2c9087368dac4c7099b8fb3b1d3ae179557ada654d8ce459363e70f2a6eb51c27a93bad5d24dadd581130308b9783e85321a2c8b13e641b734850b66b842e68a3a1dfed65400816117d8ee2fd282db9563a4d3ea352eb346417e59101384744dd8357c84fa83cdd006935521a2b6fb5a2f154da6d5276cbca9a5cc55c33f155e0369982df6955092170426ff2e7edc0a7dc7c2e45d15b799643123f732511918a1595ca341c347efb0a1d5e403a7e79661f99b4d44431480697b580eebf5789daf4307cb92058291c9e05724b8026949d32e0a17b6e6a8b61e2c2ca1d0c8a43989d0bf30f7f1661bc320679a589641705132284cb24b29ab393357e6ed8d37e76ae057aa10267d7bcda84c3ac91c941d65c7e8271dbf7f0df5df8a6e8e1431c7759831c3469f9937e704ed2112889068319bdc952059c43fe714007d4e3ee21b751da5ecfed8e17
+TAG: a9d85c3a90e25a670f586c0c5eff165883fdd620
+
+# DIGEST: 4b2db052fc8a09f7a0c26afc66dbcd8ae5c9bf62
+KEY: 089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857
+AD: 772305daa4b550d75f05d8
+CT: bd1e3ae0ec8c5fc3fd73fef807ee5638c602699dc1f2fea52696533055258b673ff5e03603fa0421c0b0addbf1c37fd2210139abe9defc7751005dc20d538ebf6caa7116a9cee2137a2418b972793efdba624775ef06b8e9293969536ef03afc8c4c52579635cf11e6baf696564c085cc47040779c5c596da51f7d27946c495f3d09e95f3d8e2a9220fcd03a104a635da896e913825228653fab7a14108b6ba9281afd5cb1f0f936e978c250ac32e5a57bcd6d1e5eb32ebd0b60c14323f4c89f7a4380bb11fd71cdeab5a5d3e95b02727a5acffb79c8020415782b915011307465ec200ffa0f924a6a0c5ef1157b70139d21f451aa17819c579a12ff309ba43dbad70b3079432f5f153c5ce3b38994c113f25c3162834b6840a5076afbb54f163a28309ac641b11d9ff8aa92aba8d3ca68d9518e916a9f26a09f58a9a8862c788f638276cb7c1f267a23d50e6741688d948f72646c1b1f586439fa98109bb47c2b82aa6d6f6064310e3fb57f4f77cfac651e7882a8549f91c262de025de63e6196db82d68ec8d3d203c96098a2f7da707b57a97c46981981fd7e3c119bf4f48d62b5c236a8be8afbcd3e124f391495a0726e64462b0cc00c
+TAG: 3de5372136ff9f77b1273b64d4056e62ae51dabb
+
+# DIGEST: 881926d37fae9095362fff56efadd9fa3c455ebd
+KEY: 711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4
+AD: b550d75f05d8089850fea3
+CT: 8c750a834c7ad3b280e4a92eb17f4f7d5200b9d38f54334089c361a6bf88654046b7b4c48995f31d509f86945558287eaad74c4310c17d9aa3064a365950b3d64766f84a1daa11050a309053101392ec25e476a832ed785bf683af1febf6f58d4c50e28657c8838d59553ab006f6a9c6ec0be4c49fa01751a382b5e592291a24c4e6d71e3de9233529d79515e3d10214c274fedbefe203eceeadec92abe9923d34aebdff33ef3ba3e112caa1e60c552f7b9d1eaa0584b05a812b2ec363dd582b63fc1c08eb2f17fa96517f3c7c1306bb96fedffd01c384b54692166fb4f6f5d1ab90f67e2589ca5ccf76cf9ec2ac13e220ef8e83f8f3fa1cbd409b7df0bd1c848d9e1cb84952a560ae0a63aa0e4f8566a3cf90d7a9d5dc67d12a2f7127f824a84a5f32509bbb90b846e305c520cdc274b185794eab24a6429870eca7459d06a6b8f00b9bdf15bde4cc52a95a26ff583e7ddf5d0d7e6090eb2b41b1b6c09210ed9c998d6de660ca4babd148e7de977198f95275f0a32bc4fbd976cc37058e09b87ed46dd501bd61d492a5fa189d0e2369cc8811c3a444d38e56830fd3c50b712fd1bb17064312440b4971dbc5e9f386c0311eb537f00283d6053d0c0f32
+TAG: 35e6d1d76d51d5b3e898d88363c33fa0399bf28a
+
+# DIGEST: 92d143942e6ef5b44ad7a4b8e71c22f1ecaafffb
+KEY: 2610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05
+AD: d8089850fea3711265bf78
+CT: 5ae10feabb2c08a9487c8be5197f6b024a72434647c1ade111b2c4cca72fbb59865eda4f36b526af000a3081d5db3fa24e7c45c79f530a9db4ae533f8f6f62d1941ce180740b725947c077b81ffa70efdd5067c9d1bdd9153d55c6ccc74195622da51266ad71b5f5879597138309202bdb4da6e7e243ff2414e0cd7e3008e958fe8ccfcb381cea993ffb4615547bbb3f752ede12a0826a93350c02771bc814769c6070fe0d9e0bb70ae1b2c75cb20fd28289af44671fb2949ec72216e139c1eed55dd9f3971b4d7e177e349dd8d7fc3c8b2f0b0fd0b9146e9d35597d206219be5ef4c0fdda4b23a3c3587dcea1f89be91a5952fb024aa7df99c0f800acf58b9c0211eaed6e4c049f3ab2c29491bc3c8a662a3719b895cdf3a35b714952eb581222064f2667e578cd0e13deb1bea33fb2f4c65ad3620a1292b4d7eaf238b7269434e15a3add43393cfbb2425ec167fda249e8379283079f95fdc3ad3ea0d6a35aa0198bb1f7c55ba1b9d79ff467ed6b9b8fe56b19727616ae12d5ee8316a0849df30a5275ebd6933cb2707666b22d4950859935c47509808441caa306ca1b3f44917f1cabfa7e117d8e325527b7d0aa780821947c01a98383b1e7b61e6fc1a73b4475
+TAG: 89b1495e5916a3fc37fa6e57116c803c8237d01b
+
+# DIGEST: 7fcec4927096421498e91df912cfe43b2e971d4a
+KEY: 24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fe
+AD: a3711265bf782610460bfd
+CT: 68c46881b52106a455e0d408eefc9089b78e874e6184ab99732a9066c7c56d5c251ea64fa3e11ad64effc24ddba17a3604f91cdd77f1560733c49d07a14c270cb79c25eb89ae9119977628ec3a6f2d8771cbc7e654c8b23ea97ec3376c78d459762091642170211f06f23a6a3832d4ed0cf7da3e70f26fa99f866cedcf82b7f2f1cc25967ef0978975c38010e14854be7fbb2395307b14b1f02c3e1a4b10e90dc12933e59a7939abc7902e84f85f551aeaaa3d3b685dc81b76060b159414f8329ea4d6f1fe522f77c802646232aeca7cd1d0674410d26fa6b4694cf368f5f414e4db5cf8a03fd772ef2b2ceae57f84939b208fb49cdb718a2bf3a945f82104a958c8dd860ac9c690717666e97f689f200bfa960bc2d8ad0cbb5d57f6affbb24133bab8b20cb6bc7cdffdcf6944e030ab1bf003283bfd623d84f74a1774f9af8e102a044d5ed5e2581b881e91e18ca2f126473fe1bfcd067d3d3525478a50aa7d051d7d55de9674674c226430826d3b0c6383ca175c684279ae074aa4b6e402750c734792352565184b64fdfd6a063860aba717b746bd863ae1206d6881b14b7cac01b1959747b7cc7845808d99a1c0f2105548a726fa6f18fd5bb7a118ee4709c95dc4af9865d8
+TAG: f60291408cfa2b74d36fe999e41dcb2ae0110712
+
+# DIGEST: c1c6273ce723df9f2033c7150d466c011bb457da
+KEY: a12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea0
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf
+AD: 782610460bfd24ba022e6d
+CT: 2a2f09d464391d1f07356a3d8420d24b0194514a58c1c7913b3a926e4621d9c196079cf319570c1a7c5a4d816f822643ea9c79624b7ff3597d0f5e3e797b95f665b80aa7161f6697f71e8cbf6a436ea0f691b27b52c5fdbfa8a9fc2d17964a161a69cadfe0d3a8ee3772018bbb0a7c35bf7a5939d40f0b32c0b2e1d5414cfece1763775995c1bb4e3cce287d68a33f5a1d647473b1c4287890ce5e9c088803c3eb281163e327fa91544c24fcc62008c26384efa60cd6372fc9a33f530b2d75f2176cadaefd19cc1ab23119a9bc540772f7b1d256e6f770cb7751981b1a5b78cdfe18a6c745460d1f7ea8128de06fa45d93031dc585ead31e9c64858525b9c30ff38015ee62ba35bb3262574d9d7cdb6223815e8acc1db04130961b68fef19ae0a5eb2f3f08f62b2174873c3257370537daef8fbc47a4af0a8e125015ab9ebe077cf8fec0eb29c07565830f89f4336813e76dd0c9795c93be82d4c723119ca18ff06aacf4595b3931e158eb30c3e8956a0b8a3d1bb3456b29c9395046c1065b7295ac676dfcb8b9a81abe5a50661164032b19122d933b73425d5cbb5a08200ed31eab258a9b9c05acaac85795b78bd228ea292e9f8c14b5d08d5cc43c6147a79e42bf5c452938e5f30a00e972
+TAG: 00a1f7f9abb343d0e00c44af21c0808d2292fe0a
+
+# DIGEST: 11424a64d5ce78fd71b30a8070aea071d873afea
+KEY: 4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460b
+AD: fd24ba022e6da12dd4c27f
+CT: c07f865db109af913772076704f17a2f5e3c40c1a4353c72af3e606cc79b92f5d88ba5245a9babfde9e1ff8936a285bcdc5c81e67054c012bcd9c2b874c09e3e52960f5860f55c8264245d5c4ddd69584b7fb5bf9f79384e7017a1fc3ce1b24420f57656435fa987862deca85b0f57681e32e29fd4c6f7ff80dcbe78e2ee319ddc63e0ee680b1ccddd0fc7a26901adcd6f5f632162d672b99c09aca2e4ae63f608b2e37202c6c04515ef3f4cc6691facd70a39cd044f4115ad4fc16554a473ca994f3ce92a49021453e889508a447373cd06995f0557915009d5801144750bbb83309695726025164be2bec822936c1382fe09acabedd571b95890fd260cb907945dbd657779d35621fbae61bc7ee893708019ba13742031119ebda3e29cfe843bbe0a927b21b4a26cfb92545da5ea4beccd09b4b3eb3cb743f5956e55144da9d98acf2035cc8e9e76b7cc7ced6928d7f4a4b1f5642a3b5aa85b6042c94aa1a82111169b98a7bd3458d429b3fad0d16d6ef681df776fc0edef6c6a26d023ca504b5641325ec32baea721b0aabb9dd67c5bf822ac432676d75230e299747924be2841343ddf7275f235c013aeb5fc079adf288f4017fc40a5a8027f4dbf4e14c1822941b5561b1b78d262e34e055b88ce2b
+TAG: 045620f6e9e16322f17f29f580af6c7117157f3e
+
+# DIGEST: 6b7295febce7fba8d79d1e7ab8fdfc452191e2ba
+KEY: 454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e
+AD: 6da12dd4c27f4372480974
+CT: 537f28e6e0ff15fe2cd3e8711006bd471e69f2e465f49f4386fdff00af7c24608dbc4e4b49553c508a70e8ea9d21b8c3702016b0a36a9b2ee15e9f820f1ea16d4be04a489561db04c9dcfa10944b4fe1720a370517ab2d26bfdd8e1439d62f6595b8ce48cb64ce3495edd2be45215a348b6909bfb95c4989af058dff20a5c21a1d6c203c75b2bae4bb9a19c40098a8be1ad4c82309f1fedb312492c73a4da856c838919cf2eb58a02318bd6135554c5dc6f92439a7cf7b9ac6bab9fdb35b2e576f861963ebe43ace3c4e1c4d2ce4aff504880c5a8c2e5e9f8cff0a68139fbafbb3897bf0c4b75f9331d0935526c2d9f9b87e58d9c6ade378fb59be0f43d3caffb25f3751f2f31978a20903934a52db485d68eddca362416eac7df57be9d626c7606173befe02bebcd6d29f1b19c3a5eb0f5d1bd3eedcb8b216cd0e3ff35701291c36e190ad023409058738a5fb9d49a9ed49d1e021ced5a41b25dd765112a3890697f22b97b188ff05a7f02938f79712dc2848802d0d43af15390e77fcc4762dc8e31de811d0072c171197df4a71399aef67adaec999336254badb8ba5d3a1068eaaaa8fea82d09669cd896242294d62fb244faa54bbf50f987c7818c31b3047bbfef41afd7d00c82b8205179e527319a631466e59bd
+TAG: 0a4578985f26088be83b3627ecd37e37b1ae8bc9
+
+# DIGEST: 1dadffba439570155af2509a548764a93042d23a
+KEY: e9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937a
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c2
+AD: 7f4372480974454879c41d
+CT: 7ff3917c6a5ef9aac95b6d9a837100c7f587c5c9446051f9022fc9178b0d651bad58c884665a04e92af456ff173ea9745d8cf67eec8506b638e4dd26b3ea96e42c5992f3d94b64c0c310a0f0d60b8004ca8eeb5ead6dac3b4e8594281e3672f4d2bf9526c5645caa3d6937c43714f030432ac594391cc491c6464c128975537e8973f11d8254c8d4ff5a1591e5adea25ef60161623bfccbda8c6eed70600a532421808a1f017b8db5c09498a3cfe992046175a0c74a9485b52741d7d7cd665a0e1c73380364bc914986efe4ac1e14676b238095a22f4ff2552f2ad19f072a749bdfb81d16124f8fef856d2cc8b878805d641eac3dfb173afff38307feb4b67ba1d295464fab9dd9e45e23fc2ca49e03434c3a02424832759b1d018ef38b7ca4905974dab11f7fe2885b2ea517bfd0b22390b5e7f652bb33078bc23ace1f68045300ab713db8309dd413459d54217891cdcb350b4a3cdef008c34ccbacd338f8033d72d32a52b0ee79fcb6688d7ba76d514c35012b51cc3f4892c823189eec28195708973ff93f28b41ac282981fa20cfc930f4d13e8dbdc02feb5f3d487cf90a929fe5a29bb881a1c13c36c2dd318c5840c4d66cc89d10cb375f7c565767268a9298e7bbf479b5fecce53d6d9eb335d06fe64cc606ac39f2d8d51c
+TAG: a2cc699d78e3f6248e75a4420692f87961157d3c
+
+# DIGEST: e654b4c78e1c0061eea2996fc126c9bfd41eb6d9
+KEY: 3b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f43724809
+AD: 74454879c41de9ac9f9823
+CT: f208264960162592a3e9d56b4fc83c00269780269a93e7dadfce93f54af792c65aeef71f5db7e33f3fdec65f7a064da9826237d77a1ae03739c2a8476901f6fa4523d63dd3eb7e505408ead7fe450f0f3cb7974503603dc1d0c1c25e394349024ccc64e82bd6c6b0497da627899c61eb0accdcb776bd0516c5ef8d1c0b138f5fb59ff883df3a274cd5699cf7e400904ed7a50efaa808ff15419362b8d987caf9f57dcf542f78fdc9a8378739e1c724358264678964892d65c488cdbd1009c395d000669b26a42ec49aa91c9e73a9dc6e57fcfcee6ca1ac696975f81e45d9b2a7312ee8d5db77fa4d87f21037a949a26b8fe82655cd2078793ff30bb37db081e110615dcdfec09ebf51b98530bdf13ed457fbfb7a423019cc1056ec0ebfd5d54086f06965d98720c54e1d625db697806c44381ad35e851f4d923405173dacee2665e1f97401612f961d842276a3e8c8758f43ddafb56941dd3143de8d43c52767f598898c5182f2ab22441795719344eaa07c7145e629b31d9ab3a80ad75e2b1d23d964c32d4d9dfcd8b5909cd6e56d47b141b6da4d1292a4c438d7540659f795ccd4f7f6886ec366baa1f72a9c15fed3c0836f740416513800462903999d7e09d3bae22769c911a57b099e15a1d7d776362f25ed16ef0b3dbd2ced9632460dfb
+TAG: 1dd4b30129fda67fa16c30d192048d8305af09ab
+
+# DIGEST: 654b8591c7f0506261713e9ce7a6fd24a6b9357e
+KEY: 61792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d7222712
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c4
+AD: 1de9ac9f98233b5a7379a5
+CT: 9ed81dde78d093b3c45934a2045684bc9dd735c9898f95d70c2aa42d025ce3ff6cd55078054db439b980b94fc89f516a682c10f0f1f960f859f080378844786f59f1719ab14ae63ad047237b9aa9df84ed92bb96acab14a95516124ca465f5a1394485b7ba6eae1db874e395b89a4f6fbd72402f1f4c0514af8465a7a1e78e3d4bf68c1411227471c91b1e4ddb1c5d3394280b59fccfe1a809400248c75723832347e5d52a25c3db1e98f5b72c2c92bd02a4936db492f9f02d799f464aa1190d5caa65c28185217cd3ad072e38ec98a53c87f9ab869483075a10debcdb09025eb03b17decb80722279282be69325b1b8d9e63d0d587023e9deadb8b54e1dcd9681a78540755c70540d1bd7fadc54586d24b75d511952acc69e69ae3f1bfe34830b9306de0a26a2e045bf4670830d7f6ff254283298ccd82eef5ee773587852a3b3925b4a7b1ba55d512b0559f2a62fabbfa0169e0f3608ea457fbb9437cfe8f38f87e35b7306fb8aac50eed94b44bacb9423bfd1514a74591185f34fde204f3dd1bece5a2b9e07b533913b2b69ff6197e49686ff144b35152a1d5471b5500f439b7cae8c17ed15001a3f48a1899305a161e4b093cdd40b98d5b34f868a4b4ee2e38a939ee33226b882afd258f94a795026bfaada68681aa39c2759301812756f87e6563d17
+TAG: d8f6a119a6ac8a68deebfc6ac1a635dde51d4fd4
+
+# DIGEST: 1eaad32c8d0cefaa5e2c503bb2185a73e6387fac
+KEY: 16430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98
+AD: 233b5a7379a561792c0f31
+CT: 2248180bf6a9405dbac464126f2bbeceb4f8e0fb6ee0400be9481515936550b766e23c343c60982b7984b8de37b661705b06aad6a446834a29160f999f1c9fd22dbb01f8b28b9ae0bbc0e9939a149621ae3bd001aaa52eda0a450c1355db18324f2cf66df77f887aa8b36c550191b3458f23c17d7acb21c02c53abb7227708fc27b308486597bb07999fbf2cfed0fe4f4195d102866bcacdc2ec5c17e1b13cb506e7db53c4bf76cd027a54724752b791afe845b43c0e9109f7982a552bd6ce74851c8146ee2418787ce871d1bad80679d50d60e45d0f4a8ef5f9718a065e195986090ebb0795314d2045ee8c1c02b882887dac53d3078d7e678f1934044e7ae7860df10c928bf474b9dcd05f206f7226aec6f005c296b56910401e42a3cfb49fce993c09e156b91183f1b41cb813057eedcc07e10c62b7f695550e3c6856b2290d262f326ef9d944114b63ee5dc7ed1b83c1286e072d0a7ddb844de616e8b47cb5aa95eff840536c732dbc06e46c01f61cb8ea3e3ce1d57c6f200fb7b10b6751872a65c96c8d3679d8290f0381c22ffb30be641aeef4e28a50410826861514199259ef46294c5353a402acdc6e0969b5aaacc5657f14bfc8c0600982c3874443fc41e92ec1052fe1c790e3546f5b9b1b9e67764924959789277027aaedd127c1a9542d9a263bedf74576
+TAG: 99e98eb154afbf6cc5de5cc0074227ee2ddca81c
+
+# DIGEST: 862c0517b3658e9b9cd27db608d49e24e9b4667d
+KEY: a058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c
+NONCE:
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379
+AD: a561792c0f3116430e8b6e
+CT: 95a4e848170959bb9367293c8c6779aa4757bf58f03fa60e3e144bbb88a47dfd349db915647ea3a44fe96786543f8d09f6305f8369146b79571a9f449643c8b067896679c163e615bb64be7e459d0517e6ba420aa56e6d1faa2f936156136eb1db758fab08dbd0dd1006e8ec6407ea24b201c9244791e67ec7f2308db459f0f2f7b44078bd1a968b96a707d40a1e5a3d47cb5009222d36fcaa92bd41fad9b56b9915b42e7ab1081f0eeeeae7317d04a9e870a4033343b4dc6bf8b6d8c384d3848eefd01bf583b9a10e6bf11b92ebf1e62f3ef04c942a3ef654ceba77f3f39263a1a9cd7f2a51f1aaf01230e53370af89956615b2c370a827e56af083474ab91821dd46b6af1627d2de448942267eda09e699806be60183f208b8a83ee557ad81fe9c6d89180439423a4a1466b89bc57f19816c6c28ef0520685333d7ceebc7904d27f3fb01e25b30c00107c1e2f9477c3929354bd5bb33091555b8de268ddce72c29a80f5dd5a8d72830c072c34f95a3cfb64214233ceb304b4f96760ea762552ba0dc775ccbea2ce02ee9806daa5155287f2f741ccf700f5e5b0de7ffc6a673f00b941a2dd0f45bb8300bc8d000615db3e88381551e119296939585c810b0719d8880b0a8837bea1052a60544b3bd6c60ff8c825ff6a202d803e593873e9f7aca33aac57780f0bb71c14256512c69
+TAG: 208d87d0a27f909a4d73f03565b6442ae20bd55d
+
diff --git a/src/crypto/cipher/tls_cbc.c b/src/crypto/cipher/tls_cbc.c
new file mode 100644
index 0000000..8bca2f3
--- /dev/null
+++ b/src/crypto/cipher/tls_cbc.c
@@ -0,0 +1,495 @@
+/* ====================================================================
+ * 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 <assert.h>
+#include <string.h>
+
+#include <openssl/digest.h>
+#include <openssl/obj.h>
+#include <openssl/sha.h>
+
+#include "../internal.h"
+
+
+/* TODO(davidben): unsigned should be size_t. The various constant_time
+ * functions need to be switched to size_t. */
+
+/* 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
+
+int EVP_tls_cbc_remove_padding(unsigned *out_len,
+ const uint8_t *in, unsigned in_len,
+ unsigned block_size, unsigned mac_size) {
+ unsigned padding_length, good, to_check, i;
+ const unsigned overhead = 1 /* padding length byte */ + mac_size;
+
+ /* These lengths are all public so we can test them in non-constant time. */
+ if (overhead > in_len) {
+ return 0;
+ }
+
+ padding_length = in[in_len - 1];
+
+ good = constant_time_ge(in_len, 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 > in_len) {
+ to_check = in_len;
+ }
+
+ for (i = 0; i < to_check; i++) {
+ uint8_t mask = constant_time_ge_8(padding_length, i);
+ uint8_t b = in[in_len - 1 - i];
+ /* The final |padding_length+1| bytes should all have the value
+ * |padding_length|. Therefore the XOR should be zero. */
+ good &= ~(mask & (padding_length ^ b));
+ }
+
+ /* If any of the final |padding_length+1| bytes had the wrong value,
+ * one or more of the lower eight bits of |good| will be cleared. */
+ good = constant_time_eq(0xff, good & 0xff);
+
+ /* Always treat |padding_length| as zero on error. If, assuming block size of
+ * 16, a padding of [<15 arbitrary bytes> 15] treated |padding_length| as 16
+ * and returned -1, distinguishing good MAC and bad padding from bad MAC and
+ * bad padding would give POODLE's padding oracle. */
+ padding_length = good & (padding_length + 1);
+ *out_len = in_len - padding_length;
+
+ return constant_time_select_int(good, 1, -1);
+}
+
+/* If CBC_MAC_ROTATE_IN_PLACE is defined then EVP_tls_cbc_copy_mac 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 EVP_tls_cbc_copy_mac(uint8_t *out, unsigned md_size,
+ const uint8_t *in, unsigned in_len,
+ unsigned orig_len) {
+#if defined(CBC_MAC_ROTATE_IN_PLACE)
+ uint8_t rotated_mac_buf[64 + EVP_MAX_MD_SIZE];
+ uint8_t *rotated_mac;
+#else
+ uint8_t rotated_mac[EVP_MAX_MD_SIZE];
+#endif
+
+ /* mac_end is the index of |in| just after the end of the MAC. */
+ unsigned mac_end = in_len;
+ unsigned 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 scan_start = 0;
+ unsigned i, j;
+ unsigned div_spoiler;
+ unsigned rotate_offset;
+
+ assert(orig_len >= in_len);
+ assert(in_len >= md_size);
+ 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++) {
+ uint8_t mac_started = constant_time_ge_8(i, mac_start);
+ uint8_t mac_ended = constant_time_ge_8(i, mac_end);
+ uint8_t b = in[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 uint8_t *)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
+}
+
+/* u32toBE serialises an unsigned, 32-bit number (n) as four bytes at (p) in
+ * big-endian order. The value of p is advanced by four. */
+#define u32toBE(n, p) \
+ (*((p)++)=(uint8_t)(n>>24), \
+ *((p)++)=(uint8_t)(n>>16), \
+ *((p)++)=(uint8_t)(n>>8), \
+ *((p)++)=(uint8_t)(n))
+
+/* u64toBE serialises an unsigned, 64-bit number (n) as eight bytes at (p) in
+ * big-endian order. The value of p is advanced by eight. */
+#define u64toBE(n, p) \
+ (*((p)++)=(uint8_t)(n>>56), \
+ *((p)++)=(uint8_t)(n>>48), \
+ *((p)++)=(uint8_t)(n>>40), \
+ *((p)++)=(uint8_t)(n>>32), \
+ *((p)++)=(uint8_t)(n>>24), \
+ *((p)++)=(uint8_t)(n>>16), \
+ *((p)++)=(uint8_t)(n>>8), \
+ *((p)++)=(uint8_t)(n))
+
+/* 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_sha1_final_raw(void *ctx, uint8_t *md_out) {
+ SHA_CTX *sha1 = ctx;
+ u32toBE(sha1->h0, md_out);
+ u32toBE(sha1->h1, md_out);
+ u32toBE(sha1->h2, md_out);
+ u32toBE(sha1->h3, md_out);
+ u32toBE(sha1->h4, md_out);
+}
+#define LARGEST_DIGEST_CTX SHA_CTX
+
+static void tls1_sha256_final_raw(void *ctx, uint8_t *md_out) {
+ SHA256_CTX *sha256 = ctx;
+ unsigned i;
+
+ for (i = 0; i < 8; i++) {
+ u32toBE(sha256->h[i], md_out);
+ }
+}
+#undef LARGEST_DIGEST_CTX
+#define LARGEST_DIGEST_CTX SHA256_CTX
+
+static void tls1_sha512_final_raw(void *ctx, uint8_t *md_out) {
+ SHA512_CTX *sha512 = ctx;
+ unsigned i;
+
+ for (i = 0; i < 8; i++) {
+ u64toBE(sha512->h[i], md_out);
+ }
+}
+#undef LARGEST_DIGEST_CTX
+#define LARGEST_DIGEST_CTX SHA512_CTX
+
+int EVP_tls_cbc_record_digest_supported(const EVP_MD *md) {
+ switch (EVP_MD_type(md)) {
+ case NID_sha1:
+ case NID_sha256:
+ case NID_sha384:
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+
+int EVP_tls_cbc_digest_record(const EVP_MD *md, uint8_t *md_out,
+ size_t *md_out_size, const uint8_t header[13],
+ const uint8_t *data, size_t data_plus_mac_size,
+ size_t data_plus_mac_plus_padding_size,
+ const uint8_t *mac_secret,
+ unsigned mac_secret_length) {
+ union {
+ double align;
+ uint8_t c[sizeof(LARGEST_DIGEST_CTX)];
+ } md_state;
+ void (*md_final_raw)(void *ctx, uint8_t *md_out);
+ void (*md_transform)(void *ctx, const uint8_t *block);
+ unsigned md_size, md_block_size = 64;
+ unsigned 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 */
+ uint8_t length_bytes[MAX_HASH_BIT_COUNT_BYTES];
+ /* hmac_pad is the masked HMAC key. */
+ uint8_t hmac_pad[MAX_HASH_BLOCK_SIZE];
+ uint8_t first_block[MAX_HASH_BLOCK_SIZE];
+ uint8_t mac_out[EVP_MAX_MD_SIZE];
+ unsigned 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 md_length_size = 8;
+
+ /* This is a, hopefully redundant, check that allows us to forget about
+ * many possible overflows later in this function. */
+ assert(data_plus_mac_plus_padding_size < 1024 * 1024);
+
+ switch (EVP_MD_type(md)) {
+ case NID_sha1:
+ SHA1_Init((SHA_CTX *)md_state.c);
+ md_final_raw = tls1_sha1_final_raw;
+ md_transform =
+ (void (*)(void *ctx, const uint8_t *block))SHA1_Transform;
+ md_size = 20;
+ break;
+
+ case NID_sha256:
+ SHA256_Init((SHA256_CTX *)md_state.c);
+ md_final_raw = tls1_sha256_final_raw;
+ md_transform =
+ (void (*)(void *ctx, const uint8_t *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 uint8_t *block))SHA512_Transform;
+ md_size = 384 / 8;
+ md_block_size = 128;
+ md_length_size = 16;
+ break;
+
+ default:
+ /* EVP_tls_cbc_record_digest_supported should have been called first to
+ * check that the hash function is supported. */
+ assert(0);
+ *md_out_size = 0;
+ return 0;
+ }
+
+ assert(md_length_size <= MAX_HASH_BIT_COUNT_BYTES);
+ assert(md_block_size <= MAX_HASH_BLOCK_SIZE);
+ assert(md_size <= EVP_MAX_MD_SIZE);
+
+ static const unsigned kHeaderLength = 13;
+
+ /* kVarianceBlocks 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. */
+ static const unsigned kVarianceBlocks = 6;
+
+ /* From now on we're dealing with the MAC, which conceptually has 13
+ * bytes of `header' before the start of the data. */
+ len = data_plus_mac_plus_padding_size + kHeaderLength;
+ /* 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 |kVarianceBlocks| 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 + kHeaderLength - 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 > kVarianceBlocks) {
+ num_starting_blocks = num_blocks - kVarianceBlocks;
+ 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);
+ 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);
+
+ memset(length_bytes, 0, md_length_size - 4);
+ length_bytes[md_length_size - 4] = (uint8_t)(bits >> 24);
+ length_bytes[md_length_size - 3] = (uint8_t)(bits >> 16);
+ length_bytes[md_length_size - 2] = (uint8_t)(bits >> 8);
+ length_bytes[md_length_size - 1] = (uint8_t)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 + kVarianceBlocks;
+ i++) {
+ uint8_t block[MAX_HASH_BLOCK_SIZE];
+ uint8_t is_block_a = constant_time_eq_8(i, index_a);
+ uint8_t is_block_b = constant_time_eq_8(i, index_b);
+ for (j = 0; j < md_block_size; j++) {
+ uint8_t b = 0, is_past_c, is_past_cp1;
+ if (k < kHeaderLength) {
+ b = header[k];
+ } else if (k < data_plus_mac_plus_padding_size + kHeaderLength) {
+ b = data[k - kHeaderLength];
+ }
+ k++;
+
+ is_past_c = is_block_a & constant_time_ge_8(j, c);
+ is_past_cp1 = is_block_a & constant_time_ge_8(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 = constant_time_select_8(is_past_c, 0x80, b);
+ /* If this the 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 = constant_time_select_8(
+ is_block_b, length_bytes[j - (md_block_size - md_length_size)], b);
+ }
+ 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;
+ }
+ }
+
+ EVP_MD_CTX_init(&md_ctx);
+ if (!EVP_DigestInit_ex(&md_ctx, md, NULL /* engine */)) {
+ EVP_MD_CTX_cleanup(&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);
+ *md_out_size = md_out_size_u;
+ EVP_MD_CTX_cleanup(&md_ctx);
+
+ return 1;
+}
diff --git a/src/crypto/conf/CMakeLists.txt b/src/crypto/conf/CMakeLists.txt
new file mode 100644
index 0000000..f54d904
--- /dev/null
+++ b/src/crypto/conf/CMakeLists.txt
@@ -0,0 +1,10 @@
+include_directories(. .. ../../include)
+
+add_library(
+ conf
+
+ OBJECT
+
+ conf.c
+ conf_error.c
+)
diff --git a/src/crypto/conf/conf.c b/src/crypto/conf/conf.c
new file mode 100644
index 0000000..b8dab95
--- /dev/null
+++ b/src/crypto/conf/conf.c
@@ -0,0 +1,746 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/conf.h>
+
+#include <string.h>
+#include <ctype.h>
+
+#include <openssl/bio.h>
+#include <openssl/buf.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+
+#include "conf_def.h"
+
+
+static uint32_t conf_value_hash(const CONF_VALUE *v) {
+ return (lh_strhash(v->section) << 2) ^ lh_strhash(v->name);
+}
+
+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) {
+ return strcmp(a->name, b->name);
+ } else if (a->name == b->name) {
+ return 0;
+ } else {
+ return (a->name == NULL) ? -1 : 1;
+ }
+}
+
+CONF *NCONF_new(void) {
+ CONF *conf;
+
+ conf = OPENSSL_malloc(sizeof(CONF));
+ if (conf == NULL) {
+ return NULL;
+ }
+
+ conf->data = lh_CONF_VALUE_new(conf_value_hash, conf_value_cmp);
+ if (conf->data == NULL) {
+ OPENSSL_free(conf);
+ return NULL;
+ }
+
+ return conf;
+}
+
+static void value_free_contents(CONF_VALUE *value) {
+ if (value->section) {
+ OPENSSL_free(value->section);
+ }
+ if (value->name) {
+ OPENSSL_free(value->name);
+ if (value->value) {
+ OPENSSL_free(value->value);
+ }
+ } else {
+ if (value->value) {
+ sk_CONF_VALUE_free((STACK_OF(CONF_VALUE)*)value->value);
+ }
+ }
+}
+
+static void value_free(CONF_VALUE *value) {
+ value_free_contents(value);
+ OPENSSL_free(value);
+}
+
+void NCONF_free(CONF *conf) {
+ if (conf == NULL || conf->data == NULL) {
+ return;
+ }
+
+ lh_CONF_VALUE_doall(conf->data, value_free_contents);
+ lh_CONF_VALUE_free(conf->data);
+ OPENSSL_free(conf);
+}
+
+CONF_VALUE *NCONF_new_section(const CONF *conf, const char *section) {
+ STACK_OF(CONF_VALUE) *sk = NULL;
+ int ok = 0, i;
+ CONF_VALUE *v = NULL, *old_value;
+
+ sk = sk_CONF_VALUE_new_null();
+ v = OPENSSL_malloc(sizeof(CONF_VALUE));
+ if (sk == NULL || v == NULL) {
+ goto err;
+ }
+ i = strlen(section) + 1;
+ v->section = OPENSSL_malloc(i);
+ if (v->section == NULL) {
+ goto err;
+ }
+
+ memcpy(v->section, section, i);
+ v->section[i-1] = 0;
+ v->name = NULL;
+ v->value = (char *)sk;
+
+ if (!lh_CONF_VALUE_insert(conf->data, &old_value, v)) {
+ goto err;
+ }
+ if (old_value) {
+ value_free(old_value);
+ }
+ ok = 1;
+
+err:
+ if (!ok) {
+ if (sk != NULL) {
+ sk_CONF_VALUE_free(sk);
+ }
+ if (v != NULL) {
+ OPENSSL_free(v);
+ }
+ v = NULL;
+ }
+ return v;
+}
+
+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, *rrp, *np, *cp, v;
+ const char *p;
+ BUF_MEM *buf;
+
+ buf = BUF_MEM_new();
+ if (buf == 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) {
+ OPENSSL_PUT_ERROR(CONF, str_copy, 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 = NCONF_get_string(conf, cp, np);
+ if (rrp != NULL) {
+ *rrp = rr;
+ }
+ *rp = r;
+ if (p == NULL) {
+ OPENSSL_PUT_ERROR(CONF, str_copy, CONF_R_VARIABLE_HAS_NO_VALUE);
+ goto err;
+ }
+ BUF_MEM_grow_clean(buf, (strlen(p) + buf->length - (e - from)));
+ 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';
+ if (*pto != NULL) {
+ OPENSSL_free(*pto);
+ }
+ *pto = buf->data;
+ OPENSSL_free(buf);
+ return 1;
+
+err:
+ if (buf != NULL) {
+ BUF_MEM_free(buf);
+ }
+ return 0;
+}
+
+static CONF_VALUE *get_section(const CONF *conf, const char *section) {
+ CONF_VALUE template;
+
+ memset(&template, 0, sizeof(template));
+ template.section = (char *) section;
+ return lh_CONF_VALUE_retrieve(conf->data, &template);
+}
+
+STACK_OF(CONF_VALUE) *NCONF_get_section(const CONF *conf, const char *section) {
+ CONF_VALUE *section_value = get_section(conf, section);
+ if (section_value == NULL) {
+ return NULL;
+ }
+ return (STACK_OF(CONF_VALUE)*) section_value->value;
+}
+
+const char *NCONF_get_string(const CONF *conf, const char *section,
+ const char *name) {
+ CONF_VALUE template, *value;
+
+ memset(&template, 0, sizeof(template));
+ template.section = (char *) section;
+ template.name = (char *) name;
+ value = lh_CONF_VALUE_retrieve(conf->data, &template);
+ if (value == NULL) {
+ return NULL;
+ }
+ return value->value;
+}
+
+int add_string(const CONF *conf, CONF_VALUE *section, CONF_VALUE *value) {
+ STACK_OF(CONF_VALUE) *section_stack = (STACK_OF(CONF_VALUE)*) section->value;
+ CONF_VALUE *old_value;
+
+ value->section = section->section;
+ if (!sk_CONF_VALUE_push(section_stack, value)) {
+ return 0;
+ }
+
+ if (!lh_CONF_VALUE_insert(conf->data, &old_value, value)) {
+ return 0;
+ }
+ if (old_value != NULL) {
+ (void)sk_CONF_VALUE_delete_ptr(section_stack, old_value);
+ value_free(old_value);
+ }
+
+ return 1;
+}
+
+static char *eat_ws(CONF *conf, char *p) {
+ while (IS_WS(conf, *p) && !IS_EOF(conf, *p)) {
+ p++;
+ }
+ return p;
+}
+
+#define scan_esc(conf, p) (((IS_EOF((conf), (p)[1])) ? ((p) + 1) : ((p) + 2)))
+
+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 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 def_load_bio(CONF *conf, BIO *in, long *out_error_line) {
+ static const size_t CONFBUFSIZE = 512;
+ int bufnum = 0, i, ii;
+ BUF_MEM *buff = NULL;
+ char *s, *p, *end;
+ int again;
+ long eline = 0;
+ char btmp[DECIMAL_SIZE(eline) + 1];
+ CONF_VALUE *v = NULL, *tv;
+ CONF_VALUE *sv = NULL;
+ char *section = NULL, *buf;
+ char *start, *psection, *pname;
+
+ if ((buff = BUF_MEM_new()) == NULL) {
+ OPENSSL_PUT_ERROR(CONF, def_load_bio, ERR_R_BUF_LIB);
+ goto err;
+ }
+
+ section = (char *)OPENSSL_malloc(10);
+ if (section == NULL) {
+ OPENSSL_PUT_ERROR(CONF, def_load_bio, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ BUF_strlcpy(section, "default", 10);
+
+ sv = NCONF_new_section(conf, section);
+ if (sv == NULL) {
+ OPENSSL_PUT_ERROR(CONF, def_load_bio, CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
+ goto err;
+ }
+
+ bufnum = 0;
+ again = 0;
+ for (;;) {
+ if (!BUF_MEM_grow(buff, bufnum + CONFBUFSIZE)) {
+ OPENSSL_PUT_ERROR(CONF, def_load_bio, 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;
+ }
+ OPENSSL_PUT_ERROR(CONF, def_load_bio, CONF_R_MISSING_CLOSE_SQUARE_BRACKET);
+ goto err;
+ }
+ *end = '\0';
+ if (!str_copy(conf, NULL, &section, start))
+ goto err;
+ if ((sv = get_section(conf, section)) == NULL)
+ sv = NCONF_new_section(conf, section);
+ if (sv == NULL) {
+ OPENSSL_PUT_ERROR(CONF, def_load_bio, 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 != '=') {
+ OPENSSL_PUT_ERROR(CONF, def_load_bio, 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 = (CONF_VALUE *)OPENSSL_malloc(sizeof(CONF_VALUE)))) {
+ OPENSSL_PUT_ERROR(CONF, def_load_bio, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ if (psection == NULL)
+ psection = section;
+ v->name = (char *)OPENSSL_malloc(strlen(pname) + 1);
+ v->value = NULL;
+ if (v->name == NULL) {
+ OPENSSL_PUT_ERROR(CONF, def_load_bio, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ BUF_strlcpy(v->name, pname, strlen(pname) + 1);
+ if (!str_copy(conf, psection, &(v->value), start))
+ goto err;
+
+ if (strcmp(psection, section) != 0) {
+ if ((tv = get_section(conf, psection)) == NULL)
+ tv = NCONF_new_section(conf, psection);
+ if (tv == NULL) {
+ OPENSSL_PUT_ERROR(CONF, def_load_bio, CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
+ goto err;
+ }
+ } else
+ tv = sv;
+ if (add_string(conf, tv, v) == 0) {
+ OPENSSL_PUT_ERROR(CONF, def_load_bio, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ v = NULL;
+ }
+ }
+ if (buff != NULL)
+ BUF_MEM_free(buff);
+ if (section != NULL)
+ OPENSSL_free(section);
+ return 1;
+
+err:
+ if (buff != NULL)
+ BUF_MEM_free(buff);
+ if (section != NULL)
+ OPENSSL_free(section);
+ if (out_error_line != NULL)
+ *out_error_line = eline;
+ BIO_snprintf(btmp, sizeof btmp, "%ld", eline);
+ ERR_add_error_data(2, "line ", btmp);
+
+ if (v != NULL) {
+ if (v->name != NULL)
+ OPENSSL_free(v->name);
+ if (v->value != NULL)
+ OPENSSL_free(v->value);
+ if (v != NULL)
+ OPENSSL_free(v);
+ }
+ return 0;
+}
+
+int NCONF_load(CONF *conf, const char *filename, long *out_error_line) {
+ BIO *in = BIO_new_file(filename, "rb");
+ int ret;
+
+ if (in == NULL) {
+ OPENSSL_PUT_ERROR(CONF, NCONF_load, ERR_R_SYS_LIB);
+ return 0;
+ }
+
+ ret = def_load_bio(conf, in, out_error_line);
+ BIO_free(in);
+
+ return ret;
+}
+
+int CONF_parse_list(const char *list, char sep, int remove_whitespace,
+ int (*list_cb)(const char *elem, int len, void *usr),
+ void *arg) {
+ int ret;
+ const char *lstart, *tmpend, *p;
+
+ if (list == NULL) {
+ OPENSSL_PUT_ERROR(CONF, CONF_parse_list, CONF_R_LIST_CANNOT_BE_NULL);
+ return 0;
+ }
+
+ lstart = list;
+ for (;;) {
+ if (remove_whitespace) {
+ 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 (remove_whitespace) {
+ 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/src/crypto/conf/conf_def.h b/src/crypto/conf/conf_def.h
new file mode 100644
index 0000000..b1e6ba6
--- /dev/null
+++ b/src/crypto/conf/conf_def.h
@@ -0,0 +1,127 @@
+/* crypto/conf/conf_def.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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. */
+
+#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) CONF_type_default
+#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 const 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,
+ };
diff --git a/src/crypto/conf/conf_error.c b/src/crypto/conf/conf_error.c
new file mode 100644
index 0000000..b5dd001
--- /dev/null
+++ b/src/crypto/conf/conf_error.c
@@ -0,0 +1,31 @@
+/* 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 <openssl/err.h>
+
+#include <openssl/conf.h>
+
+const ERR_STRING_DATA CONF_error_string_data[] = {
+ {ERR_PACK(ERR_LIB_CONF, CONF_F_CONF_parse_list, 0), "CONF_parse_list"},
+ {ERR_PACK(ERR_LIB_CONF, CONF_F_NCONF_load, 0), "NCONF_load"},
+ {ERR_PACK(ERR_LIB_CONF, CONF_F_def_load_bio, 0), "def_load_bio"},
+ {ERR_PACK(ERR_LIB_CONF, CONF_F_str_copy, 0), "str_copy"},
+ {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_LIST_CANNOT_BE_NULL), "LIST_CANNOT_BE_NULL"},
+ {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_MISSING_CLOSE_SQUARE_BRACKET), "MISSING_CLOSE_SQUARE_BRACKET"},
+ {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_MISSING_EQUAL_SIGN), "MISSING_EQUAL_SIGN"},
+ {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_NO_CLOSE_BRACE), "NO_CLOSE_BRACE"},
+ {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_UNABLE_TO_CREATE_NEW_SECTION), "UNABLE_TO_CREATE_NEW_SECTION"},
+ {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_VARIABLE_HAS_NO_VALUE), "VARIABLE_HAS_NO_VALUE"},
+ {0, NULL},
+};
diff --git a/src/crypto/constant_time_test.c b/src/crypto/constant_time_test.c
new file mode 100644
index 0000000..bc127c1
--- /dev/null
+++ b/src/crypto/constant_time_test.c
@@ -0,0 +1,307 @@
+/*
+ * 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.]
+ */
+
+#include "internal.h"
+
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+static const unsigned int CONSTTIME_TRUE = (unsigned)(~0);
+static const unsigned int CONSTTIME_FALSE = 0;
+static const uint8_t CONSTTIME_TRUE_8 = 0xff;
+static const uint8_t CONSTTIME_FALSE_8 = 0;
+
+static int test_binary_op(unsigned int (*op)(unsigned int a, unsigned int b),
+ const char* op_name, unsigned int a, unsigned int b,
+ int is_true) {
+ unsigned c = op(a, b);
+ if (is_true && c != CONSTTIME_TRUE) {
+ fprintf(stderr,
+ "Test failed for %s(%du, %du): expected %du (TRUE), got %du\n",
+ op_name, a, b, CONSTTIME_TRUE, c);
+ return 1;
+ } else if (!is_true && c != CONSTTIME_FALSE) {
+ fprintf(stderr,
+ "Test failed for %s(%du, %du): expected %du (FALSE), got %du\n",
+ op_name, a, b, CONSTTIME_FALSE, c);
+ return 1;
+ }
+ return 0;
+}
+
+static int test_binary_op_8(uint8_t (*op)(unsigned int a, unsigned int b),
+ const char* op_name, unsigned int a, unsigned int b,
+ int is_true) {
+ uint8_t c = op(a, b);
+ if (is_true && c != CONSTTIME_TRUE_8) {
+ fprintf(stderr,
+ "Test failed for %s(%du, %du): expected %u (TRUE), got %u\n",
+ op_name, a, b, CONSTTIME_TRUE_8, c);
+ return 1;
+ } else if (!is_true && c != CONSTTIME_FALSE_8) {
+ fprintf(stderr,
+ "Test failed for %s(%du, %du): expected %u (FALSE), got %u\n",
+ op_name, a, b, CONSTTIME_FALSE_8, c);
+ return 1;
+ }
+ return 0;
+}
+
+static int test_is_zero(unsigned int a) {
+ unsigned int c = constant_time_is_zero(a);
+ if (a == 0 && c != CONSTTIME_TRUE) {
+ fprintf(stderr,
+ "Test failed for constant_time_is_zero(%du): expected %du (TRUE), "
+ "got %du\n",
+ a, CONSTTIME_TRUE, c);
+ return 1;
+ } else if (a != 0 && c != CONSTTIME_FALSE) {
+ fprintf(stderr,
+ "Test failed for constant_time_is_zero(%du): expected %du (FALSE), "
+ "got %du\n",
+ a, CONSTTIME_FALSE, c);
+ return 1;
+ }
+ return 0;
+}
+
+static int test_is_zero_8(unsigned int a) {
+ uint8_t c = constant_time_is_zero_8(a);
+ if (a == 0 && c != CONSTTIME_TRUE_8) {
+ fprintf(stderr,
+ "Test failed for constant_time_is_zero(%du): expected %u (TRUE), "
+ "got %u\n",
+ a, CONSTTIME_TRUE_8, c);
+ return 1;
+ } else if (a != 0 && c != CONSTTIME_FALSE) {
+ fprintf(stderr,
+ "Test failed for constant_time_is_zero(%du): expected %u (FALSE), "
+ "got %u\n",
+ a, CONSTTIME_FALSE_8, c);
+ return 1;
+ }
+ return 0;
+}
+
+static int test_select(unsigned int a, unsigned int b) {
+ unsigned int selected = constant_time_select(CONSTTIME_TRUE, a, b);
+ if (selected != a) {
+ fprintf(stderr,
+ "Test failed for constant_time_select(%du, %du,"
+ "%du): expected %du(first value), got %du\n",
+ CONSTTIME_TRUE, a, b, a, selected);
+ return 1;
+ }
+ selected = constant_time_select(CONSTTIME_FALSE, a, b);
+ if (selected != b) {
+ fprintf(stderr,
+ "Test failed for constant_time_select(%du, %du,"
+ "%du): expected %du(second value), got %du\n",
+ CONSTTIME_FALSE, a, b, b, selected);
+ return 1;
+ }
+ return 0;
+}
+
+static int test_select_8(uint8_t a, uint8_t b) {
+ uint8_t selected = constant_time_select_8(CONSTTIME_TRUE_8, a, b);
+ if (selected != a) {
+ fprintf(stderr,
+ "Test failed for constant_time_select(%u, %u,"
+ "%u): expected %u(first value), got %u\n",
+ CONSTTIME_TRUE, a, b, a, selected);
+ return 1;
+ }
+ selected = constant_time_select_8(CONSTTIME_FALSE_8, a, b);
+ if (selected != b) {
+ fprintf(stderr,
+ "Test failed for constant_time_select(%u, %u,"
+ "%u): expected %u(second value), got %u\n",
+ CONSTTIME_FALSE, a, b, b, selected);
+ return 1;
+ }
+ return 0;
+}
+
+static int test_select_int(int a, int b) {
+ int selected = constant_time_select_int(CONSTTIME_TRUE, a, b);
+ if (selected != a) {
+ fprintf(stderr,
+ "Test failed for constant_time_select(%du, %d,"
+ "%d): expected %d(first value), got %d\n",
+ CONSTTIME_TRUE, a, b, a, selected);
+ return 1;
+ }
+ selected = constant_time_select_int(CONSTTIME_FALSE, a, b);
+ if (selected != b) {
+ fprintf(stderr,
+ "Test failed for constant_time_select(%du, %d,"
+ "%d): expected %d(second value), got %d\n",
+ CONSTTIME_FALSE, a, b, b, selected);
+ return 1;
+ }
+ return 0;
+}
+
+static int test_eq_int(int a, int b) {
+ unsigned int equal = constant_time_eq_int(a, b);
+ if (a == b && equal != CONSTTIME_TRUE) {
+ fprintf(stderr,
+ "Test failed for constant_time_eq_int(%d, %d): expected %du(TRUE), "
+ "got %du\n",
+ a, b, CONSTTIME_TRUE, equal);
+ return 1;
+ } else if (a != b && equal != CONSTTIME_FALSE) {
+ fprintf(stderr,
+ "Test failed for constant_time_eq_int(%d, %d): expected "
+ "%du(FALSE), got %du\n",
+ a, b, CONSTTIME_FALSE, equal);
+ return 1;
+ }
+ return 0;
+}
+
+static int test_eq_int_8(int a, int b) {
+ uint8_t equal = constant_time_eq_int_8(a, b);
+ if (a == b && equal != CONSTTIME_TRUE_8) {
+ fprintf(stderr,
+ "Test failed for constant_time_eq_int_8(%d, %d): expected "
+ "%u(TRUE), got %u\n",
+ a, b, CONSTTIME_TRUE_8, equal);
+ return 1;
+ } else if (a != b && equal != CONSTTIME_FALSE_8) {
+ fprintf(stderr,
+ "Test failed for constant_time_eq_int_8(%d, %d): expected "
+ "%u(FALSE), got %u\n",
+ a, b, CONSTTIME_FALSE_8, equal);
+ return 1;
+ }
+ return 0;
+}
+
+static unsigned int test_values[] = {0, 1, 1024, 12345, 32000, UINT_MAX / 2 - 1,
+ UINT_MAX / 2, UINT_MAX / 2 + 1,
+ UINT_MAX - 1, UINT_MAX};
+
+static uint8_t test_values_8[] = {0, 1, 2, 20, 32, 127, 128, 129, 255};
+
+static int signed_test_values[] = {
+ 0, 1, -1, 1024, -1024, 12345, -12345,
+ 32000, -32000, INT_MAX, INT_MIN, INT_MAX - 1, INT_MIN + 1};
+
+int main(int argc, char* argv[]) {
+ unsigned int a, b, i, j;
+ int c, d;
+ uint8_t e, f;
+ int num_failed = 0, num_all = 0;
+ fprintf(stdout, "Testing constant time operations...\n");
+
+ for (i = 0; i < sizeof(test_values) / sizeof(int); ++i) {
+ a = test_values[i];
+ num_failed += test_is_zero(a);
+ num_failed += test_is_zero_8(a);
+ num_all += 2;
+ for (j = 0; j < sizeof(test_values) / sizeof(int); ++j) {
+ b = test_values[j];
+ num_failed +=
+ test_binary_op(&constant_time_lt, "constant_time_lt", a, b, a < b);
+ num_failed += test_binary_op_8(&constant_time_lt_8, "constant_time_lt_8",
+ a, b, a < b);
+ num_failed +=
+ test_binary_op(&constant_time_lt, "constant_time_lt_8", b, a, b < a);
+ num_failed += test_binary_op_8(&constant_time_lt_8, "constant_time_lt_8",
+ b, a, b < a);
+ num_failed +=
+ test_binary_op(&constant_time_ge, "constant_time_ge", a, b, a >= b);
+ num_failed += test_binary_op_8(&constant_time_ge_8, "constant_time_ge_8",
+ a, b, a >= b);
+ num_failed +=
+ test_binary_op(&constant_time_ge, "constant_time_ge", b, a, b >= a);
+ num_failed += test_binary_op_8(&constant_time_ge_8, "constant_time_ge_8",
+ b, a, b >= a);
+ num_failed +=
+ test_binary_op(&constant_time_eq, "constant_time_eq", a, b, a == b);
+ num_failed += test_binary_op_8(&constant_time_eq_8, "constant_time_eq_8",
+ a, b, a == b);
+ num_failed +=
+ test_binary_op(&constant_time_eq, "constant_time_eq", b, a, b == a);
+ num_failed += test_binary_op_8(&constant_time_eq_8, "constant_time_eq_8",
+ b, a, b == a);
+ num_failed += test_select(a, b);
+ num_all += 13;
+ }
+ }
+
+ for (i = 0; i < sizeof(signed_test_values) / sizeof(int); ++i) {
+ c = signed_test_values[i];
+ for (j = 0; j < sizeof(signed_test_values) / sizeof(int); ++j) {
+ d = signed_test_values[j];
+ num_failed += test_select_int(c, d);
+ num_failed += test_eq_int(c, d);
+ num_failed += test_eq_int_8(c, d);
+ num_all += 3;
+ }
+ }
+
+ for (i = 0; i < sizeof(test_values_8); ++i) {
+ e = test_values_8[i];
+ for (j = 0; j < sizeof(test_values_8); ++j) {
+ f = test_values_8[j];
+ num_failed += test_select_8(e, f);
+ num_all += 1;
+ }
+ }
+
+ if (!num_failed) {
+ fprintf(stdout, "ok (ran %d tests)\n", num_all);
+ fprintf(stdout, "PASS\n");
+ return EXIT_SUCCESS;
+ } else {
+ fprintf(stdout, "%d of %d tests failed!\n", num_failed, num_all);
+ return EXIT_FAILURE;
+ }
+}
diff --git a/src/crypto/cpu-arm.c b/src/crypto/cpu-arm.c
new file mode 100644
index 0000000..96392d8
--- /dev/null
+++ b/src/crypto/cpu-arm.c
@@ -0,0 +1,112 @@
+/* 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 <openssl/cpu.h>
+
+#if defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)
+
+#include <inttypes.h>
+#include <stdio.h>
+
+#include "arm_arch.h"
+
+
+/* We can't include <sys/auxv.h> because the Android SDK version against which
+ * Chromium builds is too old to have it. Instead we define all the constants
+ * that we need and have a weak pointer to getauxval. */
+
+unsigned long getauxval(unsigned long type) __attribute__((weak));
+
+static const unsigned long AT_HWCAP = 16;
+static const unsigned long AT_HWCAP2 = 26;
+
+char CRYPTO_is_NEON_capable(void) {
+ return (OPENSSL_armcap_P & ARMV7_NEON) != 0;
+}
+
+void CRYPTO_set_NEON_capable(char neon_capable) {
+ if (neon_capable) {
+ OPENSSL_armcap_P |= ARMV7_NEON;
+ } else {
+ OPENSSL_armcap_P &= ~ARMV7_NEON;
+ }
+}
+
+char CRYPTO_is_NEON_functional(void) {
+ static const uint32_t kWantFlags = ARMV7_NEON | ARMV7_NEON_FUNCTIONAL;
+ return (OPENSSL_armcap_P & kWantFlags) == kWantFlags;
+}
+
+void CRYPTO_set_NEON_functional(char neon_functional) {
+ if (neon_functional) {
+ OPENSSL_armcap_P |= ARMV7_NEON_FUNCTIONAL;
+ } else {
+ OPENSSL_armcap_P &= ~ARMV7_NEON_FUNCTIONAL;
+ }
+}
+
+void OPENSSL_cpuid_setup(void) {
+ if (getauxval == NULL) {
+ return;
+ }
+
+ unsigned long hwcap = getauxval(AT_HWCAP);
+
+#if defined(OPENSSL_ARM)
+ static const unsigned long kNEON = 1 << 12;
+ if ((hwcap & kNEON) == 0) {
+ return;
+ }
+
+ /* In 32-bit mode, the ARMv8 feature bits are in a different aux vector
+ * value. */
+ hwcap = getauxval(AT_HWCAP2);
+
+ /* See /usr/include/asm/hwcap.h on an ARM installation for the source of
+ * these values. */
+ static const unsigned long kAES = 1 << 0;
+ static const unsigned long kPMULL = 1 << 1;
+ static const unsigned long kSHA1 = 1 << 2;
+ static const unsigned long kSHA256 = 1 << 3;
+#elif defined(OPENSSL_AARCH64)
+ /* See /usr/include/asm/hwcap.h on an aarch64 installation for the source of
+ * these values. */
+ static const unsigned long kNEON = 1 << 1;
+ static const unsigned long kAES = 1 << 3;
+ static const unsigned long kPMULL = 1 << 4;
+ static const unsigned long kSHA1 = 1 << 5;
+ static const unsigned long kSHA256 = 1 << 6;
+
+ if ((hwcap & kNEON) == 0) {
+ return;
+ }
+#endif
+
+ OPENSSL_armcap_P |= ARMV7_NEON | ARMV7_NEON_FUNCTIONAL;
+
+ if (hwcap & kAES) {
+ OPENSSL_armcap_P |= ARMV8_AES;
+ }
+ if (hwcap & kPMULL) {
+ OPENSSL_armcap_P |= ARMV8_PMULL;
+ }
+ if (hwcap & kSHA1) {
+ OPENSSL_armcap_P |= ARMV8_SHA1;
+ }
+ if (hwcap & kSHA256) {
+ OPENSSL_armcap_P |= ARMV8_SHA256;
+ }
+}
+
+#endif /* defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64) */
diff --git a/src/crypto/cpu-intel.c b/src/crypto/cpu-intel.c
new file mode 100644
index 0000000..69f4570
--- /dev/null
+++ b/src/crypto/cpu-intel.c
@@ -0,0 +1,127 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#if !defined(__STDC_FORMAT_MACROS)
+#define __STDC_FORMAT_MACROS
+#endif
+
+#include <openssl/cpu.h>
+
+
+#if !defined(OPENSSL_NO_ASM) && (defined(OPENSSL_X86) || defined(OPENSSL_X86_64))
+
+#include <inttypes.h>
+#include <stdio.h>
+#include <string.h>
+
+/* OPENSSL_ia32_cpuid is defined in cpu-x86_64-asm.pl. */
+extern uint64_t OPENSSL_ia32_cpuid(uint32_t*);
+
+/* handle_cpu_env applies the value from |in| to the CPUID values in |out[0]|
+ * and |out[1]|. See the comment in |OPENSSL_cpuid_setup| about this. */
+static void handle_cpu_env(uint32_t *out, const char *in) {
+ const int invert = in[0] == '~';
+ uint64_t v;
+
+ if (!sscanf(in + invert, "%" PRIi64, &v)) {
+ return;
+ }
+
+ if (invert) {
+ out[0] &= ~v;
+ out[1] &= ~(v >> 32);
+ } else {
+ out[0] = v;
+ out[1] = v >> 32;
+ }
+}
+
+void OPENSSL_cpuid_setup(void) {
+ const char *env1, *env2;
+
+#if defined(OPENSSL_X86_64)
+ OPENSSL_ia32_cpuid(OPENSSL_ia32cap_P);
+#else
+ uint64_t vec = OPENSSL_ia32_cpuid(OPENSSL_ia32cap_P);
+ /* 1<<10 sets a reserved bit to indicate that the variable
+ * was already initialised. */
+ OPENSSL_ia32cap_P[0] = ((uint32_t)vec) | (1 << 10);
+ OPENSSL_ia32cap_P[1] = vec >> 32;
+#endif
+
+ env1 = getenv("OPENSSL_ia32cap");
+ if (env1 == NULL) {
+ return;
+ }
+
+ /* OPENSSL_ia32cap can contain zero, one or two values, separated with a ':'.
+ * Each value is a 64-bit, unsigned value which may start with "0x" to
+ * indicate a hex value. Prior to the 64-bit value, a '~' may be given.
+ *
+ * If '~' isn't present, then the value is taken as the result of the CPUID.
+ * Otherwise the value is inverted and ANDed with the probed CPUID result.
+ *
+ * The first value determines OPENSSL_ia32cap_P[0] and [1]. The second [2]
+ * and [3]. */
+
+ handle_cpu_env(&OPENSSL_ia32cap_P[0], env1);
+ env2 = strchr(env1, ':');
+ if (env2 != NULL) {
+ handle_cpu_env(&OPENSSL_ia32cap_P[2], env2 + 1);
+ }
+}
+
+#endif /* !OPENSSL_NO_ASM && (OPENSSL_X86 || OPENSSL_X86_64) */
diff --git a/src/crypto/cpu-x86-asm.pl b/src/crypto/cpu-x86-asm.pl
new file mode 100644
index 0000000..1ac7d84
--- /dev/null
+++ b/src/crypto/cpu-x86-asm.pl
@@ -0,0 +1,338 @@
+#!/usr/bin/env perl
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+push(@INC, "${dir}perlasm", "perlasm");
+require "x86asm.pl";
+
+&asm_init($ARGV[0],"crypto/cpu-x86-asm");
+
+for (@ARGV) { $sse2=1 if (/-DOPENSSL_IA32_SSE2/); }
+
+&function_begin("OPENSSL_ia32_cpuid");
+ &xor ("edx","edx");
+ &pushf ();
+ &pop ("eax");
+ &mov ("ecx","eax");
+ &xor ("eax",1<<21);
+ &push ("eax");
+ &popf ();
+ &pushf ();
+ &pop ("eax");
+ &xor ("ecx","eax");
+ &xor ("eax","eax");
+ &bt ("ecx",21);
+ &jnc (&label("nocpuid"));
+ &mov ("esi",&wparam(0));
+ &mov (&DWP(8,"esi"),"eax"); # clear 3rd word
+ &cpuid ();
+ &mov ("edi","eax"); # max value for standard query level
+
+ &xor ("eax","eax");
+ &cmp ("ebx",0x756e6547); # "Genu"
+ &setne (&LB("eax"));
+ &mov ("ebp","eax");
+ &cmp ("edx",0x49656e69); # "ineI"
+ &setne (&LB("eax"));
+ &or ("ebp","eax");
+ &cmp ("ecx",0x6c65746e); # "ntel"
+ &setne (&LB("eax"));
+ &or ("ebp","eax"); # 0 indicates Intel CPU
+ &jz (&label("intel"));
+
+ &cmp ("ebx",0x68747541); # "Auth"
+ &setne (&LB("eax"));
+ &mov ("esi","eax");
+ &cmp ("edx",0x69746E65); # "enti"
+ &setne (&LB("eax"));
+ &or ("esi","eax");
+ &cmp ("ecx",0x444D4163); # "cAMD"
+ &setne (&LB("eax"));
+ &or ("esi","eax"); # 0 indicates AMD CPU
+ &jnz (&label("intel"));
+
+ # AMD specific
+ &mov ("eax",0x80000000);
+ &cpuid ();
+ &cmp ("eax",0x80000001);
+ &jb (&label("intel"));
+ &mov ("esi","eax");
+ &mov ("eax",0x80000001);
+ &cpuid ();
+ &or ("ebp","ecx");
+ &and ("ebp",1<<11|1); # isolate XOP bit
+ &cmp ("esi",0x80000008);
+ &jb (&label("intel"));
+
+ &mov ("eax",0x80000008);
+ &cpuid ();
+ &movz ("esi",&LB("ecx")); # number of cores - 1
+ &inc ("esi"); # number of cores
+
+ &mov ("eax",1);
+ &xor ("ecx","ecx");
+ &cpuid ();
+ &bt ("edx",28);
+ &jnc (&label("generic"));
+ &shr ("ebx",16);
+ &and ("ebx",0xff);
+ &cmp ("ebx","esi");
+ &ja (&label("generic"));
+ &and ("edx",0xefffffff); # clear hyper-threading bit
+ &jmp (&label("generic"));
+
+&set_label("intel");
+ &cmp ("edi",7);
+ &jb (&label("cacheinfo"));
+
+ &mov ("esi",&wparam(0));
+ &mov ("eax",7);
+ &xor ("ecx","ecx");
+ &cpuid ();
+ &mov (&DWP(8,"esi"),"ebx");
+
+&set_label("cacheinfo");
+ &cmp ("edi",4);
+ &mov ("edi",-1);
+ &jb (&label("nocacheinfo"));
+
+ &mov ("eax",4);
+ &mov ("ecx",0); # query L1D
+ &cpuid ();
+ &mov ("edi","eax");
+ &shr ("edi",14);
+ &and ("edi",0xfff); # number of cores -1 per L1D
+
+&set_label("nocacheinfo");
+ &mov ("eax",1);
+ &xor ("ecx","ecx");
+ &cpuid ();
+ &and ("edx",0xbfefffff); # force reserved bits #20, #30 to 0
+ &cmp ("ebp",0);
+ &jne (&label("notintel"));
+ &or ("edx",1<<30); # set reserved bit#30 on Intel CPUs
+ &and (&HB("eax"),15); # familiy ID
+ &cmp (&HB("eax"),15); # P4?
+ &jne (&label("notintel"));
+ &or ("edx",1<<20); # set reserved bit#20 to engage RC4_CHAR
+&set_label("notintel");
+ &bt ("edx",28); # test hyper-threading bit
+ &jnc (&label("generic"));
+ &and ("edx",0xefffffff);
+ &cmp ("edi",0);
+ &je (&label("generic"));
+
+ &or ("edx",0x10000000);
+ &shr ("ebx",16);
+ &cmp (&LB("ebx"),1);
+ &ja (&label("generic"));
+ &and ("edx",0xefffffff); # clear hyper-threading bit if not
+
+&set_label("generic");
+ &and ("ebp",1<<11); # isolate AMD XOP flag
+ &and ("ecx",0xfffff7ff); # force 11th bit to 0
+ &mov ("esi","edx");
+ &or ("ebp","ecx"); # merge AMD XOP flag
+
+ &bt ("ecx",27); # check OSXSAVE bit
+ &jnc (&label("clear_avx"));
+ &xor ("ecx","ecx");
+ &data_byte(0x0f,0x01,0xd0); # xgetbv
+ &and ("eax",6);
+ &cmp ("eax",6);
+ &je (&label("done"));
+ &cmp ("eax",2);
+ &je (&label("clear_avx"));
+&set_label("clear_xmm");
+ &and ("ebp",0xfdfffffd); # clear AESNI and PCLMULQDQ bits
+ &and ("esi",0xfeffffff); # clear FXSR
+&set_label("clear_avx");
+ &and ("ebp",0xefffe7ff); # clear AVX, FMA and AMD XOP bits
+ &mov ("edi",&wparam(0));
+ &and (&DWP(8,"edi"),0xffffffdf); # clear AVX2
+&set_label("done");
+ &mov ("eax","esi");
+ &mov ("edx","ebp");
+&set_label("nocpuid");
+&function_end("OPENSSL_ia32_cpuid");
+
+&external_label("OPENSSL_ia32cap_P");
+
+&function_begin_B("OPENSSL_rdtsc","EXTRN\t_OPENSSL_ia32cap_P:DWORD");
+ &xor ("eax","eax");
+ &xor ("edx","edx");
+ &picmeup("ecx","OPENSSL_ia32cap_P");
+ &bt (&DWP(0,"ecx"),4);
+ &jnc (&label("notsc"));
+ &rdtsc ();
+&set_label("notsc");
+ &ret ();
+&function_end_B("OPENSSL_rdtsc");
+
+# This works in Ring 0 only [read DJGPP+MS-DOS+privileged DPMI host],
+# but it's safe to call it on any [supported] 32-bit platform...
+# Just check for [non-]zero return value...
+&function_begin_B("OPENSSL_instrument_halt","EXTRN\t_OPENSSL_ia32cap_P:DWORD");
+ &picmeup("ecx","OPENSSL_ia32cap_P");
+ &bt (&DWP(0,"ecx"),4);
+ &jnc (&label("nohalt")); # no TSC
+
+ &data_word(0x9058900e); # push %cs; pop %eax
+ &and ("eax",3);
+ &jnz (&label("nohalt")); # not enough privileges
+
+ &pushf ();
+ &pop ("eax");
+ &bt ("eax",9);
+ &jnc (&label("nohalt")); # interrupts are disabled
+
+ &rdtsc ();
+ &push ("edx");
+ &push ("eax");
+ &halt ();
+ &rdtsc ();
+
+ &sub ("eax",&DWP(0,"esp"));
+ &sbb ("edx",&DWP(4,"esp"));
+ &add ("esp",8);
+ &ret ();
+
+&set_label("nohalt");
+ &xor ("eax","eax");
+ &xor ("edx","edx");
+ &ret ();
+&function_end_B("OPENSSL_instrument_halt");
+
+# Essentially there is only one use for this function. Under DJGPP:
+#
+# #include <go32.h>
+# ...
+# i=OPENSSL_far_spin(_dos_ds,0x46c);
+# ...
+# to obtain the number of spins till closest timer interrupt.
+
+&function_begin_B("OPENSSL_far_spin");
+ &pushf ();
+ &pop ("eax");
+ &bt ("eax",9);
+ &jnc (&label("nospin")); # interrupts are disabled
+
+ &mov ("eax",&DWP(4,"esp"));
+ &mov ("ecx",&DWP(8,"esp"));
+ &data_word (0x90d88e1e); # push %ds, mov %eax,%ds
+ &xor ("eax","eax");
+ &mov ("edx",&DWP(0,"ecx"));
+ &jmp (&label("spin"));
+
+ &align (16);
+&set_label("spin");
+ &inc ("eax");
+ &cmp ("edx",&DWP(0,"ecx"));
+ &je (&label("spin"));
+
+ &data_word (0x1f909090); # pop %ds
+ &ret ();
+
+&set_label("nospin");
+ &xor ("eax","eax");
+ &xor ("edx","edx");
+ &ret ();
+&function_end_B("OPENSSL_far_spin");
+
+&function_begin_B("OPENSSL_wipe_cpu","EXTRN\t_OPENSSL_ia32cap_P:DWORD");
+ &xor ("eax","eax");
+ &xor ("edx","edx");
+ &picmeup("ecx","OPENSSL_ia32cap_P");
+ &mov ("ecx",&DWP(0,"ecx"));
+ &bt (&DWP(0,"ecx"),1);
+ &jnc (&label("no_x87"));
+ if ($sse2) {
+ &and ("ecx",1<<26|1<<24); # check SSE2 and FXSR bits
+ &cmp ("ecx",1<<26|1<<24);
+ &jne (&label("no_sse2"));
+ &pxor ("xmm0","xmm0");
+ &pxor ("xmm1","xmm1");
+ &pxor ("xmm2","xmm2");
+ &pxor ("xmm3","xmm3");
+ &pxor ("xmm4","xmm4");
+ &pxor ("xmm5","xmm5");
+ &pxor ("xmm6","xmm6");
+ &pxor ("xmm7","xmm7");
+ &set_label("no_sse2");
+ }
+ # just a bunch of fldz to zap the fp/mm bank followed by finit...
+ &data_word(0xeed9eed9,0xeed9eed9,0xeed9eed9,0xeed9eed9,0x90e3db9b);
+&set_label("no_x87");
+ &lea ("eax",&DWP(4,"esp"));
+ &ret ();
+&function_end_B("OPENSSL_wipe_cpu");
+
+&function_begin_B("OPENSSL_atomic_add");
+ &mov ("edx",&DWP(4,"esp")); # fetch the pointer, 1st arg
+ &mov ("ecx",&DWP(8,"esp")); # fetch the increment, 2nd arg
+ &push ("ebx");
+ &nop ();
+ &mov ("eax",&DWP(0,"edx"));
+&set_label("spin");
+ &lea ("ebx",&DWP(0,"eax","ecx"));
+ &nop ();
+ &data_word(0x1ab10ff0); # lock; cmpxchg %ebx,(%edx) # %eax is envolved and is always reloaded
+ &jne (&label("spin"));
+ &mov ("eax","ebx"); # OpenSSL expects the new value
+ &pop ("ebx");
+ &ret ();
+&function_end_B("OPENSSL_atomic_add");
+
+# This function can become handy under Win32 in situations when
+# we don't know which calling convention, __stdcall or __cdecl(*),
+# indirect callee is using. In C it can be deployed as
+#
+#ifdef OPENSSL_CPUID_OBJ
+# type OPENSSL_indirect_call(void *f,...);
+# ...
+# OPENSSL_indirect_call(func,[up to $max arguments]);
+#endif
+#
+# (*) it's designed to work even for __fastcall if number of
+# arguments is 1 or 2!
+&function_begin_B("OPENSSL_indirect_call");
+ {
+ my ($max,$i)=(7,); # $max has to be chosen as 4*n-1
+ # in order to preserve eventual
+ # stack alignment
+ &push ("ebp");
+ &mov ("ebp","esp");
+ &sub ("esp",$max*4);
+ &mov ("ecx",&DWP(12,"ebp"));
+ &mov (&DWP(0,"esp"),"ecx");
+ &mov ("edx",&DWP(16,"ebp"));
+ &mov (&DWP(4,"esp"),"edx");
+ for($i=2;$i<$max;$i++)
+ {
+ # Some copies will be redundant/bogus...
+ &mov ("eax",&DWP(12+$i*4,"ebp"));
+ &mov (&DWP(0+$i*4,"esp"),"eax");
+ }
+ &call_ptr (&DWP(8,"ebp"));# make the call...
+ &mov ("esp","ebp"); # ... and just restore the stack pointer
+ # without paying attention to what we called,
+ # (__cdecl *func) or (__stdcall *one).
+ &pop ("ebp");
+ &ret ();
+ }
+&function_end_B("OPENSSL_indirect_call");
+
+&function_begin_B("OPENSSL_ia32_rdrand");
+ &mov ("ecx",8);
+&set_label("loop");
+ &rdrand ("eax");
+ &jc (&label("break"));
+ &loop (&label("loop"));
+&set_label("break");
+ &cmp ("eax",0);
+ &cmove ("eax","ecx");
+ &ret ();
+&function_end_B("OPENSSL_ia32_rdrand");
+
+&hidden("OPENSSL_ia32cap_P");
+
+&asm_finish();
diff --git a/src/crypto/cpu-x86_64-asm.pl b/src/crypto/cpu-x86_64-asm.pl
new file mode 100644
index 0000000..59cfd18
--- /dev/null
+++ b/src/crypto/cpu-x86_64-asm.pl
@@ -0,0 +1,167 @@
+#!/usr/bin/env perl
+
+$flavour = shift;
+$output = shift;
+if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+
+$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
+( $xlate="${dir}perlasm/x86_64-xlate.pl" and -f $xlate) or
+die "can't locate x86_64-xlate.pl";
+
+open OUT,"| \"$^X\" $xlate $flavour $output";
+*STDOUT=*OUT;
+
+($arg1,$arg2,$arg3,$arg4)=$win64?("%rcx","%rdx","%r8", "%r9") : # Win64 order
+ ("%rdi","%rsi","%rdx","%rcx"); # Unix order
+
+print<<___;
+.text
+
+.globl OPENSSL_ia32_cpuid
+.type OPENSSL_ia32_cpuid,\@function,1
+.align 16
+OPENSSL_ia32_cpuid:
+ # On Windows, $arg1 is rcx, but that will be clobbered. So make Windows
+ # use the same register as Unix.
+ mov $arg1,%rdi
+ mov %rbx,%r8 # save %rbx
+
+ xor %eax,%eax
+ mov %eax,8(%rdi) # clear 3rd word
+ cpuid
+ mov %eax,%r11d # max value for standard query level
+
+ xor %eax,%eax
+ cmp \$0x756e6547,%ebx # "Genu"
+ setne %al
+ mov %eax,%r9d
+ cmp \$0x49656e69,%edx # "ineI"
+ setne %al
+ or %eax,%r9d
+ cmp \$0x6c65746e,%ecx # "ntel"
+ setne %al
+ or %eax,%r9d # 0 indicates Intel CPU
+ jz .Lintel
+
+ cmp \$0x68747541,%ebx # "Auth"
+ setne %al
+ mov %eax,%r10d
+ cmp \$0x69746E65,%edx # "enti"
+ setne %al
+ or %eax,%r10d
+ cmp \$0x444D4163,%ecx # "cAMD"
+ setne %al
+ or %eax,%r10d # 0 indicates AMD CPU
+ jnz .Lintel
+
+ # AMD specific
+ # See http://developer.amd.com/wordpress/media/2012/10/254811.pdf (1)
+
+ mov \$0x80000000,%eax
+ cpuid
+ # Returns "The largest CPUID extended function input value supported by
+ # the processor implementation." in EAX.
+ cmp \$0x80000001,%eax
+ jb .Lintel
+ mov %eax,%r10d
+ mov \$0x80000001,%eax
+ cpuid
+ # Returns feature bits in ECX. See page 20 of [1].
+ # TODO(fork): I think this should be a MOV.
+ or %ecx,%r9d
+ and \$0x00000801,%r9d # isolate AMD XOP bit, 1<<11
+
+ cmp \$0x80000008,%r10d
+ jb .Lintel
+
+ mov \$0x80000008,%eax
+ cpuid
+ # Returns APIC ID and number of cores in ECX. See page 27 of [1].
+ movzb %cl,%r10 # number of cores - 1
+ inc %r10 # number of cores
+
+ mov \$1,%eax
+ cpuid
+ # See page 13 of [1].
+ bt \$28,%edx # test hyper-threading bit
+ jnc .Lgeneric
+ shr \$16,%ebx # number of logical processors
+ cmp %r10b,%bl
+ ja .Lgeneric
+ and \$0xefffffff,%edx # Clear hyper-threading bit.
+ jmp .Lgeneric
+
+.Lintel:
+ cmp \$4,%r11d
+ mov \$-1,%r10d
+ jb .Lnocacheinfo
+
+ mov \$4,%eax
+ mov \$0,%ecx # query L1D
+ cpuid
+ mov %eax,%r10d
+ shr \$14,%r10d
+ and \$0xfff,%r10d # number of cores -1 per L1D
+
+ cmp \$7,%r11d
+ jb .Lnocacheinfo
+
+ mov \$7,%eax
+ xor %ecx,%ecx
+ cpuid
+ mov %ebx,8(%rdi)
+
+.Lnocacheinfo:
+ mov \$1,%eax
+ cpuid
+ # Gets feature information. See table 3-21 in the Intel manual.
+ and \$0xbfefffff,%edx # force reserved bits to 0
+ cmp \$0,%r9d
+ jne .Lnotintel
+ or \$0x40000000,%edx # set reserved bit#30 on Intel CPUs
+ and \$15,%ah
+ cmp \$15,%ah # examine Family ID
+ jne .Lnotintel
+ or \$0x00100000,%edx # set reserved bit#20 to engage RC4_CHAR
+.Lnotintel:
+ bt \$28,%edx # test hyper-threading bit
+ jnc .Lgeneric
+ and \$0xefffffff,%edx # ~(1<<28) - clear hyper-threading.
+ cmp \$0,%r10d
+ je .Lgeneric
+
+ or \$0x10000000,%edx # 1<<28
+ shr \$16,%ebx
+ cmp \$1,%bl # see if cache is shared
+ ja .Lgeneric
+ and \$0xefffffff,%edx # ~(1<<28)
+.Lgeneric:
+ and \$0x00000800,%r9d # isolate AMD XOP flag
+ and \$0xfffff7ff,%ecx
+ or %ecx,%r9d # merge AMD XOP flag
+
+ mov %edx,%r10d # %r9d:%r10d is copy of %ecx:%edx
+ bt \$27,%r9d # check OSXSAVE bit
+ jnc .Lclear_avx
+ xor %ecx,%ecx # XCR0
+ .byte 0x0f,0x01,0xd0 # xgetbv
+ and \$6,%eax # isolate XMM and YMM state support
+ cmp \$6,%eax
+ je .Ldone
+.Lclear_avx:
+ mov \$0xefffe7ff,%eax # ~(1<<28|1<<12|1<<11)
+ and %eax,%r9d # clear AVX, FMA and AMD XOP bits
+ andl \$0xffffffdf,8(%rdi) # cleax AVX2, ~(1<<5)
+.Ldone:
+ movl %r9d,4(%rdi)
+ movl %r10d,0(%rdi)
+ mov %r8,%rbx # restore %rbx
+ ret
+.size OPENSSL_ia32_cpuid,.-OPENSSL_ia32_cpuid
+
+___
+
+close STDOUT; # flush
diff --git a/src/crypto/crypto.c b/src/crypto/crypto.c
new file mode 100644
index 0000000..c463d5e
--- /dev/null
+++ b/src/crypto/crypto.c
@@ -0,0 +1,104 @@
+/* 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 <openssl/crypto.h>
+
+#include "internal.h"
+
+
+#if !defined(OPENSSL_NO_ASM) && \
+ (defined(OPENSSL_X86) || defined(OPENSSL_X86_64) || \
+ defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64))
+/* x86, x86_64 and the ARMs need to record the result of a cpuid call for the
+ * asm to work correctly, unless compiled without asm code. */
+#define NEED_CPUID
+
+#else
+
+/* Otherwise, don't emit a static initialiser. */
+
+#if !defined(BORINGSSL_NO_STATIC_INITIALIZER)
+#define BORINGSSL_NO_STATIC_INITIALIZER
+#endif
+
+#endif /* !OPENSSL_NO_ASM && (OPENSSL_X86 || OPENSSL_X86_64 ||
+ OPENSSL_ARM || OPENSSL_AARCH64) */
+
+
+/* The capability variables are defined in this file in order to work around a
+ * linker bug. When linking with a .a, if no symbols in a .o are referenced
+ * then the .o is discarded, even if it has constructor functions.
+ *
+ * This still means that any binaries that don't include some functionality
+ * that tests the capability values will still skip the constructor but, so
+ * far, the init constructor function only sets the capability variables. */
+
+#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64)
+/* This value must be explicitly initialised to zero in order to work around a
+ * bug in libtool or the linker on OS X.
+ *
+ * If not initialised then it becomes a "common symbol". When put into an
+ * archive, linking on OS X will fail to resolve common symbols. By
+ * initialising it to zero, it becomes a "data symbol", which isn't so
+ * affected. */
+uint32_t OPENSSL_ia32cap_P[4] = {0};
+#elif defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)
+
+#include "arm_arch.h"
+
+#if defined(__ARM_NEON__)
+uint32_t OPENSSL_armcap_P = ARMV7_NEON | ARMV7_NEON_FUNCTIONAL;
+#else
+uint32_t OPENSSL_armcap_P = ARMV7_NEON_FUNCTIONAL;
+#endif
+
+#endif
+
+
+#if defined(OPENSSL_WINDOWS)
+#define OPENSSL_CDECL __cdecl
+#else
+#define OPENSSL_CDECL
+#endif
+
+#if !defined(BORINGSSL_NO_STATIC_INITIALIZER)
+#if !defined(OPENSSL_WINDOWS)
+static void do_library_init(void) __attribute__ ((constructor));
+#else
+#pragma section(".CRT$XCU", read)
+static void __cdecl do_library_init(void);
+__declspec(allocate(".CRT$XCU")) void(*library_init_constructor)(void) =
+ do_library_init;
+#endif
+#endif /* !BORINGSSL_NO_STATIC_INITIALIZER */
+
+/* do_library_init is the actual initialization function. If
+ * BORINGSSL_NO_STATIC_INITIALIZER isn't defined, this is set as a static
+ * initializer. Otherwise, it is called by CRYPTO_library_init. */
+static void OPENSSL_CDECL do_library_init(void) {
+ /* WARNING: this function may only configure the capability variables. See the
+ * note above about the linker bug. */
+#if defined(NEED_CPUID)
+ OPENSSL_cpuid_setup();
+#endif
+}
+
+void CRYPTO_library_init(void) {
+ /* TODO(davidben): It would be tidier if this build knob could be replaced
+ * with an internal lazy-init mechanism that would handle things correctly
+ * in-library. */
+#if defined(BORINGSSL_NO_STATIC_INITIALIZER)
+ do_library_init();
+#endif
+}
diff --git a/src/crypto/crypto_error.c b/src/crypto/crypto_error.c
new file mode 100644
index 0000000..3e63dca
--- /dev/null
+++ b/src/crypto/crypto_error.c
@@ -0,0 +1,25 @@
+/* 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 <openssl/err.h>
+
+#include <openssl/crypto.h>
+
+const ERR_STRING_DATA CRYPTO_error_string_data[] = {
+ {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_CRYPTO_set_ex_data, 0), "CRYPTO_set_ex_data"},
+ {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_get_class, 0), "get_class"},
+ {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_get_func_pointers, 0), "get_func_pointers"},
+ {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_get_new_index, 0), "get_new_index"},
+ {0, NULL},
+};
diff --git a/src/crypto/crypto_error.h b/src/crypto/crypto_error.h
new file mode 100644
index 0000000..c0cb2bd
--- /dev/null
+++ b/src/crypto/crypto_error.h
@@ -0,0 +1,18 @@
+/* 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. */
+
+#define CRYPTO_F_CRYPTO_set_ex_data 100
+#define CRYPTO_F_get_class 101
+#define CRYPTO_F_get_new_index 102
+#define CRYPTO_F_get_func_pointers 103
diff --git a/src/crypto/des/CMakeLists.txt b/src/crypto/des/CMakeLists.txt
new file mode 100644
index 0000000..7d49ff3
--- /dev/null
+++ b/src/crypto/des/CMakeLists.txt
@@ -0,0 +1,9 @@
+include_directories(. .. ../../include)
+
+add_library(
+ des
+
+ OBJECT
+
+ des.c
+)
diff --git a/src/crypto/des/des.c b/src/crypto/des/des.c
new file mode 100644
index 0000000..6d00011
--- /dev/null
+++ b/src/crypto/des/des.c
@@ -0,0 +1,710 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/des.h>
+
+#include "internal.h"
+
+
+static const uint32_t 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, }};
+
+static const uint32_t 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, }};
+
+#define HPERM_OP(a, t, n, m) \
+ ((t) = ((((a) << (16 - (n))) ^ (a)) & (m)), \
+ (a) = (a) ^ (t) ^ (t >> (16 - (n))))
+
+void DES_set_key(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};
+ uint32_t c, d, t, s, t2;
+ const uint8_t *in;
+ uint32_t *k;
+ int i;
+
+ k = &schedule->ks->deslong[0];
+ in = key->bytes;
+
+ 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;
+ }
+}
+
+static void DES_encrypt1(uint32_t *data, const DES_key_schedule *ks, int enc) {
+ uint32_t l, r, t, u;
+ const uint32_t *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) {
+ 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 {
+ 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 */
+ }
+
+ /* 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;
+}
+
+static void DES_encrypt2(uint32_t *data, const DES_key_schedule *ks, int enc) {
+ uint32_t l, r, t, u;
+ const uint32_t *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) {
+ 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 {
+ 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 */
+ }
+ /* rotate and clear the top bits on machines with 8byte longs */
+ data[0] = ROTATE(l, 3) & 0xffffffffL;
+ data[1] = ROTATE(r, 3) & 0xffffffffL;
+}
+
+static void DES_encrypt3(uint32_t *data, const DES_key_schedule *ks1,
+ const DES_key_schedule *ks2,
+ const DES_key_schedule *ks3) {
+ uint32_t l, r;
+
+ l = data[0];
+ r = data[1];
+ IP(l, r);
+ data[0] = l;
+ data[1] = r;
+ DES_encrypt2((uint32_t *)data, ks1, DES_ENCRYPT);
+ DES_encrypt2((uint32_t *)data, ks2, DES_DECRYPT);
+ DES_encrypt2((uint32_t *)data, ks3, DES_ENCRYPT);
+ l = data[0];
+ r = data[1];
+ FP(r, l);
+ data[0] = l;
+ data[1] = r;
+}
+
+static void DES_decrypt3(uint32_t *data, const DES_key_schedule *ks1,
+ const DES_key_schedule *ks2,
+ const DES_key_schedule *ks3) {
+ uint32_t l, r;
+
+ l = data[0];
+ r = data[1];
+ IP(l, r);
+ data[0] = l;
+ data[1] = r;
+ DES_encrypt2((uint32_t *)data, ks3, DES_DECRYPT);
+ DES_encrypt2((uint32_t *)data, ks2, DES_ENCRYPT);
+ DES_encrypt2((uint32_t *)data, ks1, DES_DECRYPT);
+ l = data[0];
+ r = data[1];
+ FP(r, l);
+ data[0] = l;
+ data[1] = r;
+}
+
+void DES_ecb_encrypt(const DES_cblock *in_block, DES_cblock *out_block,
+ const DES_key_schedule *schedule, int is_encrypt) {
+ uint32_t l;
+ uint32_t ll[2];
+ const uint8_t *in = in_block->bytes;
+ uint8_t *out = out_block->bytes;
+
+ c2l(in, l);
+ ll[0] = l;
+ c2l(in, l);
+ ll[1] = l;
+ DES_encrypt1(ll, schedule, is_encrypt);
+ l = ll[0];
+ l2c(l, out);
+ l = ll[1];
+ l2c(l, out);
+ ll[0] = ll[1] = 0;
+}
+
+void DES_ncbc_encrypt(const uint8_t *in, uint8_t *out, size_t len,
+ const DES_key_schedule *schedule, DES_cblock *ivec,
+ int enc) {
+ uint32_t tin0, tin1;
+ uint32_t tout0, tout1, xor0, xor1;
+ uint32_t tin[2];
+ unsigned char *iv;
+
+ iv = ivec->bytes;
+
+ if (enc) {
+ c2l(iv, tout0);
+ c2l(iv, tout1);
+ for (; len >= 8; len -= 8) {
+ c2l(in, tin0);
+ c2l(in, tin1);
+ tin0 ^= tout0;
+ tin[0] = tin0;
+ tin1 ^= tout1;
+ tin[1] = tin1;
+ DES_encrypt1((uint32_t *)tin, schedule, DES_ENCRYPT);
+ tout0 = tin[0];
+ l2c(tout0, out);
+ tout1 = tin[1];
+ l2c(tout1, out);
+ }
+ if (len != 0) {
+ c2ln(in, tin0, tin1, len);
+ tin0 ^= tout0;
+ tin[0] = tin0;
+ tin1 ^= tout1;
+ tin[1] = tin1;
+ DES_encrypt1((uint32_t *)tin, schedule, DES_ENCRYPT);
+ tout0 = tin[0];
+ l2c(tout0, out);
+ tout1 = tin[1];
+ l2c(tout1, out);
+ }
+ iv = ivec->bytes;
+ l2c(tout0, iv);
+ l2c(tout1, iv);
+ } else {
+ c2l(iv, xor0);
+ c2l(iv, xor1);
+ for (; len >= 8; len -= 8) {
+ c2l(in, tin0);
+ tin[0] = tin0;
+ c2l(in, tin1);
+ tin[1] = tin1;
+ DES_encrypt1((uint32_t *)tin, schedule, DES_DECRYPT);
+ tout0 = tin[0] ^ xor0;
+ tout1 = tin[1] ^ xor1;
+ l2c(tout0, out);
+ l2c(tout1, out);
+ xor0 = tin0;
+ xor1 = tin1;
+ }
+ if (len != 0) {
+ c2l(in, tin0);
+ tin[0] = tin0;
+ c2l(in, tin1);
+ tin[1] = tin1;
+ DES_encrypt1((uint32_t *)tin, schedule, DES_DECRYPT);
+ tout0 = tin[0] ^ xor0;
+ tout1 = tin[1] ^ xor1;
+ l2cn(tout0, tout1, out, len);
+ xor0 = tin0;
+ xor1 = tin1;
+ }
+ iv = ivec->bytes;
+ l2c(xor0, iv);
+ l2c(xor1, iv);
+ }
+ tin[0] = tin[1] = 0;
+}
+
+void DES_ede3_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t len,
+ const DES_key_schedule *ks1,
+ const DES_key_schedule *ks2,
+ const DES_key_schedule *ks3, DES_cblock *ivec,
+ int enc) {
+ uint32_t tin0, tin1;
+ uint32_t tout0, tout1, xor0, xor1;
+ uint32_t tin[2];
+ uint8_t *iv;
+
+ iv = ivec->bytes;
+
+ if (enc) {
+ c2l(iv, tout0);
+ c2l(iv, tout1);
+ for (; len >= 8; len -= 8) {
+ c2l(in, tin0);
+ c2l(in, tin1);
+ tin0 ^= tout0;
+ tin1 ^= tout1;
+
+ tin[0] = tin0;
+ tin[1] = tin1;
+ DES_encrypt3((uint32_t *)tin, ks1, ks2, ks3);
+ tout0 = tin[0];
+ tout1 = tin[1];
+
+ l2c(tout0, out);
+ l2c(tout1, out);
+ }
+ if (len != 0) {
+ c2ln(in, tin0, tin1, len);
+ tin0 ^= tout0;
+ tin1 ^= tout1;
+
+ tin[0] = tin0;
+ tin[1] = tin1;
+ DES_encrypt3((uint32_t *)tin, ks1, ks2, ks3);
+ tout0 = tin[0];
+ tout1 = tin[1];
+
+ l2c(tout0, out);
+ l2c(tout1, out);
+ }
+ iv = ivec->bytes;
+ l2c(tout0, iv);
+ l2c(tout1, iv);
+ } else {
+ uint32_t t0, t1;
+
+ c2l(iv, xor0);
+ c2l(iv, xor1);
+ for (; len >= 8; len -= 8) {
+ c2l(in, tin0);
+ c2l(in, tin1);
+
+ t0 = tin0;
+ t1 = tin1;
+
+ tin[0] = tin0;
+ tin[1] = tin1;
+ DES_decrypt3((uint32_t *)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 (len != 0) {
+ c2l(in, tin0);
+ c2l(in, tin1);
+
+ t0 = tin0;
+ t1 = tin1;
+
+ tin[0] = tin0;
+ tin[1] = tin1;
+ DES_decrypt3((uint32_t *)tin, ks1, ks2, ks3);
+ tout0 = tin[0];
+ tout1 = tin[1];
+
+ tout0 ^= xor0;
+ tout1 ^= xor1;
+ l2cn(tout0, tout1, out, len);
+ xor0 = t0;
+ xor1 = t1;
+ }
+
+ iv = ivec->bytes;
+ l2c(xor0, iv);
+ l2c(xor1, iv);
+ }
+
+ tin[0] = tin[1] = 0;
+}
diff --git a/src/crypto/des/internal.h b/src/crypto/des/internal.h
new file mode 100644
index 0000000..d3a5cec
--- /dev/null
+++ b/src/crypto/des/internal.h
@@ -0,0 +1,229 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 OPENSSL_HEADER_DES_INTERNAL_H
+#define OPENSSL_HEADER_DES_INTERNAL_H
+
+#include <openssl/base.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+#define c2l(c, l) \
+ (l = ((uint32_t)(*((c)++))), l |= ((uint32_t)(*((c)++))) << 8L, \
+ l |= ((uint32_t)(*((c)++))) << 16L, l |= ((uint32_t)(*((c)++))) << 24L)
+
+#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 c2l */
+#define c2ln(c, l1, l2, n) \
+ { \
+ c += n; \
+ l1 = l2 = 0; \
+ switch (n) { \
+ case 8: \
+ l2 = ((uint32_t)(*(--(c)))) << 24L; \
+ case 7: \
+ l2 |= ((uint32_t)(*(--(c)))) << 16L; \
+ case 6: \
+ l2 |= ((uint32_t)(*(--(c)))) << 8L; \
+ case 5: \
+ l2 |= ((uint32_t)(*(--(c)))); \
+ case 4: \
+ l1 = ((uint32_t)(*(--(c)))) << 24L; \
+ case 3: \
+ l1 |= ((uint32_t)(*(--(c)))) << 16L; \
+ case 2: \
+ l1 |= ((uint32_t)(*(--(c)))) << 8L; \
+ case 1: \
+ l1 |= ((uint32_t)(*(--(c)))); \
+ } \
+ }
+
+/* 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); \
+ } \
+ }
+
+/* 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<<size);
+can be used to swap and move bits between words.
+
+So l = 0 1 2 3 r = 16 17 18 19
+ 4 5 6 7 20 21 22 23
+ 8 9 10 11 24 25 26 27
+ 12 13 14 15 28 29 30 31
+becomes (for size == 2 and mask == 0x3333)
+ t = 2^16 3^17 -- -- l = 0 1 16 17 r = 2 3 18 19
+ 6^20 7^21 -- -- 4 5 20 21 6 7 22 23
+ 10^24 11^25 -- -- 8 9 24 25 10 11 24 25
+ 14^28 15^29 -- -- 12 13 28 29 14 15 28 29
+
+Thanks for hints from Richard Outerbridge - he told me IP&FP
+could be done in 15 xor, 10 shifts and 5 ands.
+When I finally started to think of the problem in 2D
+I first got ~42 operations without xors. When I remembered
+how to use xors :-) I got it to its final state.
+*/
+#define PERM_OP(a, b, t, n, m) \
+ ((t) = ((((a) >> (n)) ^ (b)) & (m)), (b) ^= (t), (a) ^= ((t) << (n)))
+
+#define IP(l, r) \
+ { \
+ uint32_t 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) \
+ { \
+ uint32_t 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); \
+ }
+
+#define LOAD_DATA(R, S, u, t, E0, E1) \
+ u = R ^ s[S]; \
+ t = R ^ s[S + 1]
+
+#define D_ENCRYPT(LL, R, S) \
+ { \
+ LOAD_DATA(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]; \
+ }
+
+#define ITERATIONS 16
+#define HALF_ITERATIONS 8
+
+#if defined(_MSC_VER)
+#define ROTATE(a, n) (_lrotr(a, n))
+#elif defined(__ICC)
+#define ROTATE(a, n) (_rotr(a, n))
+#elif defined(__GNUC__) && __GNUC__ >= 2 && !defined(OPENSSL_NO_ASM) && \
+ !defined(__STRICT_ANSI__) && \
+ (defined(OPENSSL_X86) || defined(OPENSSL_X86_64))
+#define ROTATE(a, n) \
+ ({ \
+ unsigned int ret; \
+ asm("rorl %1,%0" : "=r"(ret) : "I"(n), "0"(a) : "cc"); \
+ ret; \
+ })
+#endif
+
+#ifndef ROTATE
+#define ROTATE(a, n) (((a) >> (n)) + ((a) << (32 - (n))))
+#endif
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_DES_INTERNAL_H */
diff --git a/src/crypto/dh/CMakeLists.txt b/src/crypto/dh/CMakeLists.txt
new file mode 100644
index 0000000..4e31206
--- /dev/null
+++ b/src/crypto/dh/CMakeLists.txt
@@ -0,0 +1,22 @@
+include_directories(. .. ../../include)
+
+add_library(
+ dh
+
+ OBJECT
+
+ dh.c
+ dh_impl.c
+ params.c
+ check.c
+ dh_asn1.c
+ dh_error.c
+)
+
+add_executable(
+ dh_test
+
+ dh_test.c
+)
+
+target_link_libraries(dh_test crypto)
diff --git a/src/crypto/dh/check.c b/src/crypto/dh/check.c
new file mode 100644
index 0000000..06af6f2
--- /dev/null
+++ b/src/crypto/dh/check.c
@@ -0,0 +1,180 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/dh.h>
+
+#include <openssl/bn.h>
+
+#include "internal.h"
+
+
+int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *ret) {
+ int ok = 0;
+ BIGNUM q;
+
+ *ret = 0;
+ BN_init(&q);
+ if (!BN_set_word(&q, 1)) {
+ goto err;
+ }
+
+ if (BN_cmp(pub_key, &q) <= 0) {
+ *ret |= DH_CHECK_PUBKEY_TOO_SMALL;
+ }
+ if (!BN_copy(&q, dh->p) ||
+ !BN_sub_word(&q, 1)) {
+ goto err;
+ }
+ if (BN_cmp(pub_key, &q) >= 0) {
+ *ret |= DH_CHECK_PUBKEY_TOO_LARGE;
+ }
+
+ ok = 1;
+
+err:
+ BN_free(&q);
+ return ok;
+}
+
+
+int DH_check(const DH *dh, int *ret) {
+ /* Check that p is a safe prime and if g is 2, 3 or 5, check that it is a
+ * suitable generator where:
+ * for 2, p mod 24 == 11
+ * for 3, p mod 12 == 5
+ * for 5, p mod 10 == 3 or 7
+ * should hold.
+ */
+ int ok = 0;
+ BN_CTX *ctx = NULL;
+ BN_ULONG l;
+ BIGNUM *t1 = NULL, *t2 = NULL;
+
+ *ret = 0;
+ ctx = BN_CTX_new();
+ if (ctx == NULL) {
+ goto err;
+ }
+ BN_CTX_start(ctx);
+ t1 = BN_CTX_get(ctx);
+ if (t1 == NULL) {
+ goto err;
+ }
+ t2 = BN_CTX_get(ctx);
+ if (t2 == NULL) {
+ goto err;
+ }
+
+ if (dh->q) {
+ if (BN_cmp(dh->g, BN_value_one()) <= 0) {
+ *ret |= DH_CHECK_NOT_SUITABLE_GENERATOR;
+ } else if (BN_cmp(dh->g, dh->p) >= 0) {
+ *ret |= DH_CHECK_NOT_SUITABLE_GENERATOR;
+ } else {
+ /* Check g^q == 1 mod p */
+ if (!BN_mod_exp(t1, dh->g, dh->q, dh->p, ctx)) {
+ goto err;
+ }
+ if (!BN_is_one(t1)) {
+ *ret |= DH_CHECK_NOT_SUITABLE_GENERATOR;
+ }
+ }
+ if (!BN_is_prime_ex(dh->q, BN_prime_checks, ctx, NULL)) {
+ *ret |= DH_CHECK_Q_NOT_PRIME;
+ }
+ /* Check p == 1 mod q i.e. q divides p - 1 */
+ if (!BN_div(t1, t2, dh->p, dh->q, ctx)) {
+ goto err;
+ }
+ if (!BN_is_one(t2)) {
+ *ret |= DH_CHECK_INVALID_Q_VALUE;
+ }
+ if (dh->j && BN_cmp(dh->j, t1)) {
+ *ret |= DH_CHECK_INVALID_J_VALUE;
+ }
+ } else if (BN_is_word(dh->g, DH_GENERATOR_2)) {
+ l = BN_mod_word(dh->p, 24);
+ if (l != 11) {
+ *ret |= DH_CHECK_NOT_SUITABLE_GENERATOR;
+ }
+ } else if (BN_is_word(dh->g, DH_GENERATOR_5)) {
+ l = BN_mod_word(dh->p, 10);
+ if (l != 3 && l != 7) {
+ *ret |= DH_CHECK_NOT_SUITABLE_GENERATOR;
+ }
+ } else {
+ *ret |= DH_CHECK_UNABLE_TO_CHECK_GENERATOR;
+ }
+
+ if (!BN_is_prime_ex(dh->p, BN_prime_checks, ctx, NULL)) {
+ *ret |= DH_CHECK_P_NOT_PRIME;
+ } else if (!dh->q) {
+ if (!BN_rshift1(t1, dh->p)) {
+ goto err;
+ }
+ if (!BN_is_prime_ex(t1, BN_prime_checks, ctx, NULL)) {
+ *ret |= DH_CHECK_P_NOT_SAFE_PRIME;
+ }
+ }
+ ok = 1;
+
+err:
+ if (ctx != NULL) {
+ BN_CTX_end(ctx);
+ BN_CTX_free(ctx);
+ }
+ return ok;
+}
diff --git a/src/crypto/dh/dh.c b/src/crypto/dh/dh.c
new file mode 100644
index 0000000..7a50da7
--- /dev/null
+++ b/src/crypto/dh/dh.c
@@ -0,0 +1,243 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/dh.h>
+
+#include <string.h>
+
+#include <openssl/bn.h>
+#include <openssl/buf.h>
+#include <openssl/err.h>
+#include <openssl/ex_data.h>
+#include <openssl/mem.h>
+#include <openssl/thread.h>
+
+#include "internal.h"
+
+
+extern const DH_METHOD DH_default_method;
+
+DH *DH_new(void) { return DH_new_method(NULL); }
+
+DH *DH_new_method(const ENGINE *engine) {
+ DH *dh = (DH *)OPENSSL_malloc(sizeof(DH));
+ if (dh == NULL) {
+ OPENSSL_PUT_ERROR(DH, DH_new_method, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ memset(dh, 0, sizeof(DH));
+
+ if (engine) {
+ dh->meth = ENGINE_get_DH_method(engine);
+ }
+
+ if (dh->meth == NULL) {
+ dh->meth = (DH_METHOD*) &DH_default_method;
+ }
+ METHOD_ref(dh->meth);
+
+ dh->references = 1;
+ if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_DH, dh, &dh->ex_data)) {
+ OPENSSL_free(dh);
+ return NULL;
+ }
+
+ if (dh->meth->init && !dh->meth->init(dh)) {
+ CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DH, dh, &dh->ex_data);
+ METHOD_unref(dh->meth);
+ OPENSSL_free(dh);
+ return NULL;
+ }
+
+ return dh;
+}
+
+void DH_free(DH *dh) {
+ if (dh == NULL) {
+ return;
+ }
+
+ if (CRYPTO_add(&dh->references, -1, CRYPTO_LOCK_DH) > 0) {
+ return;
+ }
+
+ if (dh->meth->finish) {
+ dh->meth->finish(dh);
+ }
+ METHOD_unref(dh->meth);
+
+ CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DH, dh, &dh->ex_data);
+
+ if (dh->method_mont_p) BN_MONT_CTX_free(dh->method_mont_p);
+ if (dh->p != NULL) BN_clear_free(dh->p);
+ if (dh->g != NULL) BN_clear_free(dh->g);
+ if (dh->q != NULL) BN_clear_free(dh->q);
+ if (dh->j != NULL) BN_clear_free(dh->j);
+ if (dh->seed) OPENSSL_free(dh->seed);
+ if (dh->counter != NULL) BN_clear_free(dh->counter);
+ if (dh->pub_key != NULL) BN_clear_free(dh->pub_key);
+ if (dh->priv_key != NULL) BN_clear_free(dh->priv_key);
+
+ OPENSSL_free(dh);
+}
+
+int DH_generate_parameters_ex(DH *dh, int prime_bits, int generator, BN_GENCB *cb) {
+ if (dh->meth->generate_parameters) {
+ return dh->meth->generate_parameters(dh, prime_bits, generator, cb);
+ }
+ return DH_default_method.generate_parameters(dh, prime_bits, generator, cb);
+}
+
+int DH_generate_key(DH *dh) {
+ if (dh->meth->generate_key) {
+ return dh->meth->generate_key(dh);
+ }
+ return DH_default_method.generate_key(dh);
+}
+
+int DH_compute_key(unsigned char *out, const BIGNUM *peers_key, DH *dh) {
+ if (dh->meth->compute_key) {
+ return dh->meth->compute_key(dh, out, peers_key);
+ }
+ return DH_default_method.compute_key(dh, out, peers_key);
+}
+
+int DH_size(const DH *dh) { return BN_num_bytes(dh->p); }
+
+int DH_up_ref(DH *r) {
+ CRYPTO_add(&r->references, 1, CRYPTO_LOCK_DH);
+ return 1;
+}
+
+static int int_dh_bn_cpy(BIGNUM **dst, const BIGNUM *src) {
+ BIGNUM *a = NULL;
+
+ if (src) {
+ a = BN_dup(src);
+ if (!a) {
+ return 0;
+ }
+ }
+
+ if (*dst) {
+ BN_free(*dst);
+ }
+ *dst = a;
+ return 1;
+}
+
+static int int_dh_param_copy(DH *to, const DH *from, int is_x942) {
+ if (is_x942 == -1) {
+ is_x942 = !!from->q;
+ }
+ if (!int_dh_bn_cpy(&to->p, from->p) ||
+ !int_dh_bn_cpy(&to->g, from->g)) {
+ return 0;
+ }
+
+ if (!is_x942) {
+ return 1;
+ }
+
+ if (!int_dh_bn_cpy(&to->q, from->q) ||
+ !int_dh_bn_cpy(&to->j, from->j)) {
+ return 0;
+ }
+
+ if (to->seed) {
+ OPENSSL_free(to->seed);
+ to->seed = NULL;
+ to->seedlen = 0;
+ }
+ if (from->seed) {
+ to->seed = BUF_memdup(from->seed, from->seedlen);
+ if (!to->seed) {
+ return 0;
+ }
+ to->seedlen = from->seedlen;
+ }
+
+ return 1;
+}
+
+DH *DHparams_dup(const DH *dh) {
+ DH *ret = DH_new();
+ if (!ret) {
+ return NULL;
+ }
+
+ if (!int_dh_param_copy(ret, dh, -1)) {
+ DH_free(ret);
+ return NULL;
+ }
+
+ return ret;
+}
+
+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);
+}
+
+int DH_set_ex_data(DH *d, int idx, void *arg) {
+ return (CRYPTO_set_ex_data(&d->ex_data, idx, arg));
+}
+
+void *DH_get_ex_data(DH *d, int idx) {
+ return (CRYPTO_get_ex_data(&d->ex_data, idx));
+}
diff --git a/src/crypto/dh/dh_asn1.c b/src/crypto/dh/dh_asn1.c
new file mode 100644
index 0000000..73cd4df
--- /dev/null
+++ b/src/crypto/dh/dh_asn1.c
@@ -0,0 +1,84 @@
+/* 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 <openssl/dh.h>
+
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+
+#include "internal.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;
+}
+
+ASN1_SEQUENCE_cb(DHparams, dh_cb) = {
+ ASN1_SIMPLE(DH, p, BIGNUM), ASN1_SIMPLE(DH, g, BIGNUM),
+ ASN1_OPT(DH, priv_length, ZLONG)} ASN1_SEQUENCE_END_cb(DH, DHparams);
+
+IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(DH, DHparams, DHparams)
diff --git a/src/crypto/dh/dh_error.c b/src/crypto/dh/dh_error.c
new file mode 100644
index 0000000..5ecc5d1
--- /dev/null
+++ b/src/crypto/dh/dh_error.c
@@ -0,0 +1,29 @@
+/* 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 <openssl/err.h>
+
+#include <openssl/dh.h>
+
+const ERR_STRING_DATA DH_error_string_data[] = {
+ {ERR_PACK(ERR_LIB_DH, DH_F_DH_new_method, 0), "DH_new_method"},
+ {ERR_PACK(ERR_LIB_DH, DH_F_compute_key, 0), "compute_key"},
+ {ERR_PACK(ERR_LIB_DH, DH_F_generate_key, 0), "generate_key"},
+ {ERR_PACK(ERR_LIB_DH, DH_F_generate_parameters, 0), "generate_parameters"},
+ {ERR_PACK(ERR_LIB_DH, 0, DH_R_BAD_GENERATOR), "BAD_GENERATOR"},
+ {ERR_PACK(ERR_LIB_DH, 0, DH_R_INVALID_PUBKEY), "INVALID_PUBKEY"},
+ {ERR_PACK(ERR_LIB_DH, 0, DH_R_MODULUS_TOO_LARGE), "MODULUS_TOO_LARGE"},
+ {ERR_PACK(ERR_LIB_DH, 0, DH_R_NO_PRIVATE_VALUE), "NO_PRIVATE_VALUE"},
+ {0, NULL},
+};
diff --git a/src/crypto/dh/dh_impl.c b/src/crypto/dh/dh_impl.c
new file mode 100644
index 0000000..9f416b7
--- /dev/null
+++ b/src/crypto/dh/dh_impl.c
@@ -0,0 +1,324 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/dh.h>
+
+#include <openssl/bn.h>
+#include <openssl/err.h>
+
+#include "internal.h"
+
+#define OPENSSL_DH_MAX_MODULUS_BITS 10000
+
+static int generate_parameters(DH *ret, int prime_bits, int generator, BN_GENCB *cb) {
+ /* We generate DH parameters as follows
+ * find a prime q which is prime_bits/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 <karn@qualcomm.com> 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.
+ */
+
+ BIGNUM *t1, *t2;
+ int g, ok = 0;
+ BN_CTX *ctx = NULL;
+
+ ctx = BN_CTX_new();
+ if (ctx == NULL) {
+ goto err;
+ }
+ BN_CTX_start(ctx);
+ t1 = BN_CTX_get(ctx);
+ t2 = BN_CTX_get(ctx);
+ if (t1 == NULL || t2 == 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) {
+ OPENSSL_PUT_ERROR(DH, generate_parameters, 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_bits, 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) {
+ OPENSSL_PUT_ERROR(DH, generate_parameters, ERR_R_BN_LIB);
+ }
+
+ if (ctx != NULL) {
+ BN_CTX_end(ctx);
+ BN_CTX_free(ctx);
+ }
+ return ok;
+}
+
+static int generate_key(DH *dh) {
+ int ok = 0;
+ int generate_new_key = 0;
+ unsigned l;
+ BN_CTX *ctx;
+ BN_MONT_CTX *mont = NULL;
+ BIGNUM *pub_key = NULL, *priv_key = NULL;
+ BIGNUM local_priv;
+
+ ctx = BN_CTX_new();
+ if (ctx == NULL) {
+ goto err;
+ }
+
+ if (dh->priv_key == NULL) {
+ priv_key = BN_new();
+ if (priv_key == NULL) {
+ goto err;
+ }
+ generate_new_key = 1;
+ } else {
+ priv_key = dh->priv_key;
+ }
+
+ if (dh->pub_key == NULL) {
+ pub_key = BN_new();
+ if (pub_key == NULL) {
+ goto err;
+ }
+ } else {
+ pub_key = dh->pub_key;
+ }
+
+ mont =
+ BN_MONT_CTX_set_locked(&dh->method_mont_p, CRYPTO_LOCK_DH, dh->p, ctx);
+ if (!mont) {
+ goto err;
+ }
+
+ if (generate_new_key) {
+ if (dh->q) {
+ do {
+ if (!BN_rand_range(priv_key, dh->q)) {
+ goto err;
+ }
+ } while (BN_is_zero(priv_key) || BN_is_one(priv_key));
+ } else {
+ /* secret exponent length */
+ DH_check_standard_parameters(dh);
+ l = dh->priv_length ? dh->priv_length : BN_num_bits(dh->p) - 1;
+ if (!BN_rand(priv_key, l, 0, 0)) {
+ goto err;
+ }
+ }
+ }
+
+ BN_with_flags(&local_priv, priv_key, BN_FLG_CONSTTIME);
+ if (!BN_mod_exp_mont(pub_key, dh->g, &local_priv, dh->p, ctx, mont)) {
+ goto err;
+ }
+
+ dh->pub_key = pub_key;
+ dh->priv_key = priv_key;
+ ok = 1;
+
+err:
+ if (ok != 1) {
+ OPENSSL_PUT_ERROR(DH, generate_key, ERR_R_BN_LIB);
+ }
+
+ if (pub_key != NULL && dh->pub_key == NULL) {
+ BN_free(pub_key);
+ }
+ if (priv_key != NULL && dh->priv_key == NULL) {
+ BN_free(priv_key);
+ }
+ BN_CTX_free(ctx);
+ return ok;
+}
+
+static int compute_key(DH *dh, unsigned char *out, const BIGNUM *pub_key) {
+ BN_CTX *ctx = NULL;
+ BN_MONT_CTX *mont = NULL;
+ BIGNUM *shared_key;
+ int ret = -1;
+ int check_result;
+ BIGNUM local_priv;
+
+ if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS) {
+ OPENSSL_PUT_ERROR(DH, compute_key, DH_R_MODULUS_TOO_LARGE);
+ goto err;
+ }
+
+ ctx = BN_CTX_new();
+ if (ctx == NULL) {
+ goto err;
+ }
+ BN_CTX_start(ctx);
+ shared_key = BN_CTX_get(ctx);
+ if (shared_key == NULL) {
+ goto err;
+ }
+
+ if (dh->priv_key == NULL) {
+ OPENSSL_PUT_ERROR(DH, compute_key, DH_R_NO_PRIVATE_VALUE);
+ goto err;
+ }
+
+ mont =
+ BN_MONT_CTX_set_locked(&dh->method_mont_p, CRYPTO_LOCK_DH, dh->p, ctx);
+ if (!mont) {
+ goto err;
+ }
+
+ if (!DH_check_pub_key(dh, pub_key, &check_result) || check_result) {
+ OPENSSL_PUT_ERROR(DH, compute_key, DH_R_INVALID_PUBKEY);
+ goto err;
+ }
+
+ BN_with_flags(&local_priv, dh->priv_key, BN_FLG_CONSTTIME);
+ if (!BN_mod_exp_mont(shared_key, pub_key, &local_priv, dh->p, ctx,
+ mont)) {
+ OPENSSL_PUT_ERROR(DH, compute_key, ERR_R_BN_LIB);
+ goto err;
+ }
+
+ ret = BN_bn2bin(shared_key, out);
+
+err:
+ if (ctx != NULL) {
+ BN_CTX_end(ctx);
+ BN_CTX_free(ctx);
+ }
+
+ return ret;
+}
+
+const struct dh_method DH_default_method = {
+ {
+ 0 /* references */,
+ 1 /* is_static */,
+ },
+ NULL /* app_data */,
+ NULL /* init */,
+ NULL /* finish */,
+ generate_parameters,
+ generate_key,
+ compute_key,
+};
diff --git a/src/crypto/dh/dh_test.c b/src/crypto/dh/dh_test.c
new file mode 100644
index 0000000..3575f34
--- /dev/null
+++ b/src/crypto/dh/dh_test.c
@@ -0,0 +1,502 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/dh.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include <openssl/bio.h>
+#include <openssl/bn.h>
+#include <openssl/crypto.h>
+#include <openssl/mem.h>
+
+#include "internal.h"
+
+
+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';
+ BIO_write(arg->arg, &c, 1);
+ (void)BIO_flush(arg->arg);
+
+ return 1;
+}
+
+static int run_rfc5114_tests(void);
+
+int main(int argc, char *argv[]) {
+ BN_GENCB _cb;
+ DH *a;
+ DH *b = NULL;
+ char buf[12];
+ unsigned char *abuf = NULL, *bbuf = NULL;
+ int i, alen, blen, aout, bout, ret = 1;
+ BIO *out;
+
+ CRYPTO_library_init();
+
+ out = BIO_new(BIO_s_file());
+ if (out == NULL) {
+ return 1;
+ }
+ BIO_set_fp(out, stdout, BIO_NOCLOSE);
+
+ BN_GENCB_set(&_cb, &cb, out);
+ if (((a = DH_new()) == NULL) ||
+ !DH_generate_parameters_ex(a, 64, DH_GENERATOR_5, &_cb)) {
+ goto err;
+ }
+
+ if (!DH_check(a, &i))
+ goto err;
+ if (i & DH_CHECK_P_NOT_PRIME)
+ BIO_puts(out, "p value is not prime\n");
+ if (i & DH_CHECK_P_NOT_SAFE_PRIME)
+ BIO_puts(out, "p value is not a safe prime\n");
+ if (i & DH_CHECK_UNABLE_TO_CHECK_GENERATOR)
+ BIO_puts(out, "unable to check the generator value\n");
+ if (i & DH_CHECK_NOT_SUITABLE_GENERATOR)
+ BIO_puts(out, "the g value is not a generator\n");
+
+ BIO_puts(out, "\np =");
+ BN_print(out, a->p);
+ BIO_puts(out, "\ng =");
+ BN_print(out, a->g);
+ BIO_puts(out, "\n");
+
+ b = DH_new();
+ if (b == NULL) {
+ goto err;
+ }
+
+ b->p = BN_dup(a->p);
+ b->g = BN_dup(a->g);
+ if (b->p == NULL || b->g == NULL) {
+ goto err;
+ }
+
+ if (!DH_generate_key(a))
+ goto err;
+ BIO_puts(out, "pri 1=");
+ BN_print(out, a->priv_key);
+ BIO_puts(out, "\npub 1=");
+ BN_print(out, a->pub_key);
+ BIO_puts(out, "\n");
+
+ if (!DH_generate_key(b))
+ goto err;
+ BIO_puts(out, "pri 2=");
+ BN_print(out, b->priv_key);
+ BIO_puts(out, "\npub 2=");
+ BN_print(out, b->pub_key);
+ BIO_puts(out, "\n");
+
+ alen = DH_size(a);
+ abuf = (unsigned char *)OPENSSL_malloc(alen);
+ aout = DH_compute_key(abuf, b->pub_key, a);
+
+ BIO_puts(out, "key1 =");
+ for (i = 0; i < aout; i++) {
+ sprintf(buf, "%02X", abuf[i]);
+ BIO_puts(out, buf);
+ }
+ BIO_puts(out, "\n");
+
+ blen = DH_size(b);
+ bbuf = (unsigned char *)OPENSSL_malloc(blen);
+ bout = DH_compute_key(bbuf, a->pub_key, b);
+
+ BIO_puts(out, "key2 =");
+ for (i = 0; i < bout; i++) {
+ sprintf(buf, "%02X", bbuf[i]);
+ BIO_puts(out, buf);
+ }
+ BIO_puts(out, "\n");
+ if ((aout < 4) || (bout != aout) || (memcmp(abuf, bbuf, aout) != 0)) {
+ fprintf(stderr, "Error in DH routines\n");
+ ret = 1;
+ } else
+ ret = 0;
+
+ if (!run_rfc5114_tests())
+ ret = 1;
+
+err:
+ BIO_print_errors_fp(stderr);
+
+ if (abuf != NULL)
+ OPENSSL_free(abuf);
+ if (bbuf != NULL)
+ OPENSSL_free(bbuf);
+ if (b != NULL)
+ DH_free(b);
+ if (a != NULL)
+ DH_free(a);
+ BIO_free(out);
+ return ret;
+}
+
+/* Test data from RFC 5114 */
+
+static const unsigned char dhtest_1024_160_xA[] = {
+ 0xB9, 0xA3, 0xB3, 0xAE, 0x8F, 0xEF, 0xC1, 0xA2, 0x93, 0x04,
+ 0x96, 0x50, 0x70, 0x86, 0xF8, 0x45, 0x5D, 0x48, 0x94, 0x3E};
+static const unsigned char dhtest_1024_160_yA[] = {
+ 0x2A, 0x85, 0x3B, 0x3D, 0x92, 0x19, 0x75, 0x01, 0xB9, 0x01, 0x5B, 0x2D,
+ 0xEB, 0x3E, 0xD8, 0x4F, 0x5E, 0x02, 0x1D, 0xCC, 0x3E, 0x52, 0xF1, 0x09,
+ 0xD3, 0x27, 0x3D, 0x2B, 0x75, 0x21, 0x28, 0x1C, 0xBA, 0xBE, 0x0E, 0x76,
+ 0xFF, 0x57, 0x27, 0xFA, 0x8A, 0xCC, 0xE2, 0x69, 0x56, 0xBA, 0x9A, 0x1F,
+ 0xCA, 0x26, 0xF2, 0x02, 0x28, 0xD8, 0x69, 0x3F, 0xEB, 0x10, 0x84, 0x1D,
+ 0x84, 0xA7, 0x36, 0x00, 0x54, 0xEC, 0xE5, 0xA7, 0xF5, 0xB7, 0xA6, 0x1A,
+ 0xD3, 0xDF, 0xB3, 0xC6, 0x0D, 0x2E, 0x43, 0x10, 0x6D, 0x87, 0x27, 0xDA,
+ 0x37, 0xDF, 0x9C, 0xCE, 0x95, 0xB4, 0x78, 0x75, 0x5D, 0x06, 0xBC, 0xEA,
+ 0x8F, 0x9D, 0x45, 0x96, 0x5F, 0x75, 0xA5, 0xF3, 0xD1, 0xDF, 0x37, 0x01,
+ 0x16, 0x5F, 0xC9, 0xE5, 0x0C, 0x42, 0x79, 0xCE, 0xB0, 0x7F, 0x98, 0x95,
+ 0x40, 0xAE, 0x96, 0xD5, 0xD8, 0x8E, 0xD7, 0x76};
+static const unsigned char dhtest_1024_160_xB[] = {
+ 0x93, 0x92, 0xC9, 0xF9, 0xEB, 0x6A, 0x7A, 0x6A, 0x90, 0x22,
+ 0xF7, 0xD8, 0x3E, 0x72, 0x23, 0xC6, 0x83, 0x5B, 0xBD, 0xDA};
+static const unsigned char dhtest_1024_160_yB[] = {
+ 0x71, 0x7A, 0x6C, 0xB0, 0x53, 0x37, 0x1F, 0xF4, 0xA3, 0xB9, 0x32, 0x94,
+ 0x1C, 0x1E, 0x56, 0x63, 0xF8, 0x61, 0xA1, 0xD6, 0xAD, 0x34, 0xAE, 0x66,
+ 0x57, 0x6D, 0xFB, 0x98, 0xF6, 0xC6, 0xCB, 0xF9, 0xDD, 0xD5, 0xA5, 0x6C,
+ 0x78, 0x33, 0xF6, 0xBC, 0xFD, 0xFF, 0x09, 0x55, 0x82, 0xAD, 0x86, 0x8E,
+ 0x44, 0x0E, 0x8D, 0x09, 0xFD, 0x76, 0x9E, 0x3C, 0xEC, 0xCD, 0xC3, 0xD3,
+ 0xB1, 0xE4, 0xCF, 0xA0, 0x57, 0x77, 0x6C, 0xAA, 0xF9, 0x73, 0x9B, 0x6A,
+ 0x9F, 0xEE, 0x8E, 0x74, 0x11, 0xF8, 0xD6, 0xDA, 0xC0, 0x9D, 0x6A, 0x4E,
+ 0xDB, 0x46, 0xCC, 0x2B, 0x5D, 0x52, 0x03, 0x09, 0x0E, 0xAE, 0x61, 0x26,
+ 0x31, 0x1E, 0x53, 0xFD, 0x2C, 0x14, 0xB5, 0x74, 0xE6, 0xA3, 0x10, 0x9A,
+ 0x3D, 0xA1, 0xBE, 0x41, 0xBD, 0xCE, 0xAA, 0x18, 0x6F, 0x5C, 0xE0, 0x67,
+ 0x16, 0xA2, 0xB6, 0xA0, 0x7B, 0x3C, 0x33, 0xFE};
+static const unsigned char dhtest_1024_160_Z[] = {
+ 0x5C, 0x80, 0x4F, 0x45, 0x4D, 0x30, 0xD9, 0xC4, 0xDF, 0x85, 0x27, 0x1F,
+ 0x93, 0x52, 0x8C, 0x91, 0xDF, 0x6B, 0x48, 0xAB, 0x5F, 0x80, 0xB3, 0xB5,
+ 0x9C, 0xAA, 0xC1, 0xB2, 0x8F, 0x8A, 0xCB, 0xA9, 0xCD, 0x3E, 0x39, 0xF3,
+ 0xCB, 0x61, 0x45, 0x25, 0xD9, 0x52, 0x1D, 0x2E, 0x64, 0x4C, 0x53, 0xB8,
+ 0x07, 0xB8, 0x10, 0xF3, 0x40, 0x06, 0x2F, 0x25, 0x7D, 0x7D, 0x6F, 0xBF,
+ 0xE8, 0xD5, 0xE8, 0xF0, 0x72, 0xE9, 0xB6, 0xE9, 0xAF, 0xDA, 0x94, 0x13,
+ 0xEA, 0xFB, 0x2E, 0x8B, 0x06, 0x99, 0xB1, 0xFB, 0x5A, 0x0C, 0xAC, 0xED,
+ 0xDE, 0xAE, 0xAD, 0x7E, 0x9C, 0xFB, 0xB3, 0x6A, 0xE2, 0xB4, 0x20, 0x83,
+ 0x5B, 0xD8, 0x3A, 0x19, 0xFB, 0x0B, 0x5E, 0x96, 0xBF, 0x8F, 0xA4, 0xD0,
+ 0x9E, 0x34, 0x55, 0x25, 0x16, 0x7E, 0xCD, 0x91, 0x55, 0x41, 0x6F, 0x46,
+ 0xF4, 0x08, 0xED, 0x31, 0xB6, 0x3C, 0x6E, 0x6D};
+static const unsigned char dhtest_2048_224_xA[] = {
+ 0x22, 0xE6, 0x26, 0x01, 0xDB, 0xFF, 0xD0, 0x67, 0x08, 0xA6,
+ 0x80, 0xF7, 0x47, 0xF3, 0x61, 0xF7, 0x6D, 0x8F, 0x4F, 0x72,
+ 0x1A, 0x05, 0x48, 0xE4, 0x83, 0x29, 0x4B, 0x0C};
+static const unsigned char dhtest_2048_224_yA[] = {
+ 0x1B, 0x3A, 0x63, 0x45, 0x1B, 0xD8, 0x86, 0xE6, 0x99, 0xE6, 0x7B, 0x49,
+ 0x4E, 0x28, 0x8B, 0xD7, 0xF8, 0xE0, 0xD3, 0x70, 0xBA, 0xDD, 0xA7, 0xA0,
+ 0xEF, 0xD2, 0xFD, 0xE7, 0xD8, 0xF6, 0x61, 0x45, 0xCC, 0x9F, 0x28, 0x04,
+ 0x19, 0x97, 0x5E, 0xB8, 0x08, 0x87, 0x7C, 0x8A, 0x4C, 0x0C, 0x8E, 0x0B,
+ 0xD4, 0x8D, 0x4A, 0x54, 0x01, 0xEB, 0x1E, 0x87, 0x76, 0xBF, 0xEE, 0xE1,
+ 0x34, 0xC0, 0x38, 0x31, 0xAC, 0x27, 0x3C, 0xD9, 0xD6, 0x35, 0xAB, 0x0C,
+ 0xE0, 0x06, 0xA4, 0x2A, 0x88, 0x7E, 0x3F, 0x52, 0xFB, 0x87, 0x66, 0xB6,
+ 0x50, 0xF3, 0x80, 0x78, 0xBC, 0x8E, 0xE8, 0x58, 0x0C, 0xEF, 0xE2, 0x43,
+ 0x96, 0x8C, 0xFC, 0x4F, 0x8D, 0xC3, 0xDB, 0x08, 0x45, 0x54, 0x17, 0x1D,
+ 0x41, 0xBF, 0x2E, 0x86, 0x1B, 0x7B, 0xB4, 0xD6, 0x9D, 0xD0, 0xE0, 0x1E,
+ 0xA3, 0x87, 0xCB, 0xAA, 0x5C, 0xA6, 0x72, 0xAF, 0xCB, 0xE8, 0xBD, 0xB9,
+ 0xD6, 0x2D, 0x4C, 0xE1, 0x5F, 0x17, 0xDD, 0x36, 0xF9, 0x1E, 0xD1, 0xEE,
+ 0xDD, 0x65, 0xCA, 0x4A, 0x06, 0x45, 0x5C, 0xB9, 0x4C, 0xD4, 0x0A, 0x52,
+ 0xEC, 0x36, 0x0E, 0x84, 0xB3, 0xC9, 0x26, 0xE2, 0x2C, 0x43, 0x80, 0xA3,
+ 0xBF, 0x30, 0x9D, 0x56, 0x84, 0x97, 0x68, 0xB7, 0xF5, 0x2C, 0xFD, 0xF6,
+ 0x55, 0xFD, 0x05, 0x3A, 0x7E, 0xF7, 0x06, 0x97, 0x9E, 0x7E, 0x58, 0x06,
+ 0xB1, 0x7D, 0xFA, 0xE5, 0x3A, 0xD2, 0xA5, 0xBC, 0x56, 0x8E, 0xBB, 0x52,
+ 0x9A, 0x7A, 0x61, 0xD6, 0x8D, 0x25, 0x6F, 0x8F, 0xC9, 0x7C, 0x07, 0x4A,
+ 0x86, 0x1D, 0x82, 0x7E, 0x2E, 0xBC, 0x8C, 0x61, 0x34, 0x55, 0x31, 0x15,
+ 0xB7, 0x0E, 0x71, 0x03, 0x92, 0x0A, 0xA1, 0x6D, 0x85, 0xE5, 0x2B, 0xCB,
+ 0xAB, 0x8D, 0x78, 0x6A, 0x68, 0x17, 0x8F, 0xA8, 0xFF, 0x7C, 0x2F, 0x5C,
+ 0x71, 0x64, 0x8D, 0x6F};
+static const unsigned char dhtest_2048_224_xB[] = {
+ 0x4F, 0xF3, 0xBC, 0x96, 0xC7, 0xFC, 0x6A, 0x6D, 0x71, 0xD3,
+ 0xB3, 0x63, 0x80, 0x0A, 0x7C, 0xDF, 0xEF, 0x6F, 0xC4, 0x1B,
+ 0x44, 0x17, 0xEA, 0x15, 0x35, 0x3B, 0x75, 0x90};
+static const unsigned char dhtest_2048_224_yB[] = {
+ 0x4D, 0xCE, 0xE9, 0x92, 0xA9, 0x76, 0x2A, 0x13, 0xF2, 0xF8, 0x38, 0x44,
+ 0xAD, 0x3D, 0x77, 0xEE, 0x0E, 0x31, 0xC9, 0x71, 0x8B, 0x3D, 0xB6, 0xC2,
+ 0x03, 0x5D, 0x39, 0x61, 0x18, 0x2C, 0x3E, 0x0B, 0xA2, 0x47, 0xEC, 0x41,
+ 0x82, 0xD7, 0x60, 0xCD, 0x48, 0xD9, 0x95, 0x99, 0x97, 0x06, 0x22, 0xA1,
+ 0x88, 0x1B, 0xBA, 0x2D, 0xC8, 0x22, 0x93, 0x9C, 0x78, 0xC3, 0x91, 0x2C,
+ 0x66, 0x61, 0xFA, 0x54, 0x38, 0xB2, 0x07, 0x66, 0x22, 0x2B, 0x75, 0xE2,
+ 0x4C, 0x2E, 0x3A, 0xD0, 0xC7, 0x28, 0x72, 0x36, 0x12, 0x95, 0x25, 0xEE,
+ 0x15, 0xB5, 0xDD, 0x79, 0x98, 0xAA, 0x04, 0xC4, 0xA9, 0x69, 0x6C, 0xAC,
+ 0xD7, 0x17, 0x20, 0x83, 0xA9, 0x7A, 0x81, 0x66, 0x4E, 0xAD, 0x2C, 0x47,
+ 0x9E, 0x44, 0x4E, 0x4C, 0x06, 0x54, 0xCC, 0x19, 0xE2, 0x8D, 0x77, 0x03,
+ 0xCE, 0xE8, 0xDA, 0xCD, 0x61, 0x26, 0xF5, 0xD6, 0x65, 0xEC, 0x52, 0xC6,
+ 0x72, 0x55, 0xDB, 0x92, 0x01, 0x4B, 0x03, 0x7E, 0xB6, 0x21, 0xA2, 0xAC,
+ 0x8E, 0x36, 0x5D, 0xE0, 0x71, 0xFF, 0xC1, 0x40, 0x0A, 0xCF, 0x07, 0x7A,
+ 0x12, 0x91, 0x3D, 0xD8, 0xDE, 0x89, 0x47, 0x34, 0x37, 0xAB, 0x7B, 0xA3,
+ 0x46, 0x74, 0x3C, 0x1B, 0x21, 0x5D, 0xD9, 0xC1, 0x21, 0x64, 0xA7, 0xE4,
+ 0x05, 0x31, 0x18, 0xD1, 0x99, 0xBE, 0xC8, 0xEF, 0x6F, 0xC5, 0x61, 0x17,
+ 0x0C, 0x84, 0xC8, 0x7D, 0x10, 0xEE, 0x9A, 0x67, 0x4A, 0x1F, 0xA8, 0xFF,
+ 0xE1, 0x3B, 0xDF, 0xBA, 0x1D, 0x44, 0xDE, 0x48, 0x94, 0x6D, 0x68, 0xDC,
+ 0x0C, 0xDD, 0x77, 0x76, 0x35, 0xA7, 0xAB, 0x5B, 0xFB, 0x1E, 0x4B, 0xB7,
+ 0xB8, 0x56, 0xF9, 0x68, 0x27, 0x73, 0x4C, 0x18, 0x41, 0x38, 0xE9, 0x15,
+ 0xD9, 0xC3, 0x00, 0x2E, 0xBC, 0xE5, 0x31, 0x20, 0x54, 0x6A, 0x7E, 0x20,
+ 0x02, 0x14, 0x2B, 0x6C};
+static const unsigned char dhtest_2048_224_Z[] = {
+ 0x34, 0xD9, 0xBD, 0xDC, 0x1B, 0x42, 0x17, 0x6C, 0x31, 0x3F, 0xEA, 0x03,
+ 0x4C, 0x21, 0x03, 0x4D, 0x07, 0x4A, 0x63, 0x13, 0xBB, 0x4E, 0xCD, 0xB3,
+ 0x70, 0x3F, 0xFF, 0x42, 0x45, 0x67, 0xA4, 0x6B, 0xDF, 0x75, 0x53, 0x0E,
+ 0xDE, 0x0A, 0x9D, 0xA5, 0x22, 0x9D, 0xE7, 0xD7, 0x67, 0x32, 0x28, 0x6C,
+ 0xBC, 0x0F, 0x91, 0xDA, 0x4C, 0x3C, 0x85, 0x2F, 0xC0, 0x99, 0xC6, 0x79,
+ 0x53, 0x1D, 0x94, 0xC7, 0x8A, 0xB0, 0x3D, 0x9D, 0xEC, 0xB0, 0xA4, 0xE4,
+ 0xCA, 0x8B, 0x2B, 0xB4, 0x59, 0x1C, 0x40, 0x21, 0xCF, 0x8C, 0xE3, 0xA2,
+ 0x0A, 0x54, 0x1D, 0x33, 0x99, 0x40, 0x17, 0xD0, 0x20, 0x0A, 0xE2, 0xC9,
+ 0x51, 0x6E, 0x2F, 0xF5, 0x14, 0x57, 0x79, 0x26, 0x9E, 0x86, 0x2B, 0x0F,
+ 0xB4, 0x74, 0xA2, 0xD5, 0x6D, 0xC3, 0x1E, 0xD5, 0x69, 0xA7, 0x70, 0x0B,
+ 0x4C, 0x4A, 0xB1, 0x6B, 0x22, 0xA4, 0x55, 0x13, 0x53, 0x1E, 0xF5, 0x23,
+ 0xD7, 0x12, 0x12, 0x07, 0x7B, 0x5A, 0x16, 0x9B, 0xDE, 0xFF, 0xAD, 0x7A,
+ 0xD9, 0x60, 0x82, 0x84, 0xC7, 0x79, 0x5B, 0x6D, 0x5A, 0x51, 0x83, 0xB8,
+ 0x70, 0x66, 0xDE, 0x17, 0xD8, 0xD6, 0x71, 0xC9, 0xEB, 0xD8, 0xEC, 0x89,
+ 0x54, 0x4D, 0x45, 0xEC, 0x06, 0x15, 0x93, 0xD4, 0x42, 0xC6, 0x2A, 0xB9,
+ 0xCE, 0x3B, 0x1C, 0xB9, 0x94, 0x3A, 0x1D, 0x23, 0xA5, 0xEA, 0x3B, 0xCF,
+ 0x21, 0xA0, 0x14, 0x71, 0xE6, 0x7E, 0x00, 0x3E, 0x7F, 0x8A, 0x69, 0xC7,
+ 0x28, 0xBE, 0x49, 0x0B, 0x2F, 0xC8, 0x8C, 0xFE, 0xB9, 0x2D, 0xB6, 0xA2,
+ 0x15, 0xE5, 0xD0, 0x3C, 0x17, 0xC4, 0x64, 0xC9, 0xAC, 0x1A, 0x46, 0xE2,
+ 0x03, 0xE1, 0x3F, 0x95, 0x29, 0x95, 0xFB, 0x03, 0xC6, 0x9D, 0x3C, 0xC4,
+ 0x7F, 0xCB, 0x51, 0x0B, 0x69, 0x98, 0xFF, 0xD3, 0xAA, 0x6D, 0xE7, 0x3C,
+ 0xF9, 0xF6, 0x38, 0x69};
+static const unsigned char dhtest_2048_256_xA[] = {
+ 0x08, 0x81, 0x38, 0x2C, 0xDB, 0x87, 0x66, 0x0C, 0x6D, 0xC1, 0x3E,
+ 0x61, 0x49, 0x38, 0xD5, 0xB9, 0xC8, 0xB2, 0xF2, 0x48, 0x58, 0x1C,
+ 0xC5, 0xE3, 0x1B, 0x35, 0x45, 0x43, 0x97, 0xFC, 0xE5, 0x0E};
+static const unsigned char dhtest_2048_256_yA[] = {
+ 0x2E, 0x93, 0x80, 0xC8, 0x32, 0x3A, 0xF9, 0x75, 0x45, 0xBC, 0x49, 0x41,
+ 0xDE, 0xB0, 0xEC, 0x37, 0x42, 0xC6, 0x2F, 0xE0, 0xEC, 0xE8, 0x24, 0xA6,
+ 0xAB, 0xDB, 0xE6, 0x6C, 0x59, 0xBE, 0xE0, 0x24, 0x29, 0x11, 0xBF, 0xB9,
+ 0x67, 0x23, 0x5C, 0xEB, 0xA3, 0x5A, 0xE1, 0x3E, 0x4E, 0xC7, 0x52, 0xBE,
+ 0x63, 0x0B, 0x92, 0xDC, 0x4B, 0xDE, 0x28, 0x47, 0xA9, 0xC6, 0x2C, 0xB8,
+ 0x15, 0x27, 0x45, 0x42, 0x1F, 0xB7, 0xEB, 0x60, 0xA6, 0x3C, 0x0F, 0xE9,
+ 0x15, 0x9F, 0xCC, 0xE7, 0x26, 0xCE, 0x7C, 0xD8, 0x52, 0x3D, 0x74, 0x50,
+ 0x66, 0x7E, 0xF8, 0x40, 0xE4, 0x91, 0x91, 0x21, 0xEB, 0x5F, 0x01, 0xC8,
+ 0xC9, 0xB0, 0xD3, 0xD6, 0x48, 0xA9, 0x3B, 0xFB, 0x75, 0x68, 0x9E, 0x82,
+ 0x44, 0xAC, 0x13, 0x4A, 0xF5, 0x44, 0x71, 0x1C, 0xE7, 0x9A, 0x02, 0xDC,
+ 0xC3, 0x42, 0x26, 0x68, 0x47, 0x80, 0xDD, 0xDC, 0xB4, 0x98, 0x59, 0x41,
+ 0x06, 0xC3, 0x7F, 0x5B, 0xC7, 0x98, 0x56, 0x48, 0x7A, 0xF5, 0xAB, 0x02,
+ 0x2A, 0x2E, 0x5E, 0x42, 0xF0, 0x98, 0x97, 0xC1, 0xA8, 0x5A, 0x11, 0xEA,
+ 0x02, 0x12, 0xAF, 0x04, 0xD9, 0xB4, 0xCE, 0xBC, 0x93, 0x7C, 0x3C, 0x1A,
+ 0x3E, 0x15, 0xA8, 0xA0, 0x34, 0x2E, 0x33, 0x76, 0x15, 0xC8, 0x4E, 0x7F,
+ 0xE3, 0xB8, 0xB9, 0xB8, 0x7F, 0xB1, 0xE7, 0x3A, 0x15, 0xAF, 0x12, 0xA3,
+ 0x0D, 0x74, 0x6E, 0x06, 0xDF, 0xC3, 0x4F, 0x29, 0x0D, 0x79, 0x7C, 0xE5,
+ 0x1A, 0xA1, 0x3A, 0xA7, 0x85, 0xBF, 0x66, 0x58, 0xAF, 0xF5, 0xE4, 0xB0,
+ 0x93, 0x00, 0x3C, 0xBE, 0xAF, 0x66, 0x5B, 0x3C, 0x2E, 0x11, 0x3A, 0x3A,
+ 0x4E, 0x90, 0x52, 0x69, 0x34, 0x1D, 0xC0, 0x71, 0x14, 0x26, 0x68, 0x5F,
+ 0x4E, 0xF3, 0x7E, 0x86, 0x8A, 0x81, 0x26, 0xFF, 0x3F, 0x22, 0x79, 0xB5,
+ 0x7C, 0xA6, 0x7E, 0x29};
+static const unsigned char dhtest_2048_256_xB[] = {
+ 0x7D, 0x62, 0xA7, 0xE3, 0xEF, 0x36, 0xDE, 0x61, 0x7B, 0x13, 0xD1,
+ 0xAF, 0xB8, 0x2C, 0x78, 0x0D, 0x83, 0xA2, 0x3B, 0xD4, 0xEE, 0x67,
+ 0x05, 0x64, 0x51, 0x21, 0xF3, 0x71, 0xF5, 0x46, 0xA5, 0x3D};
+static const unsigned char dhtest_2048_256_yB[] = {
+ 0x57, 0x5F, 0x03, 0x51, 0xBD, 0x2B, 0x1B, 0x81, 0x74, 0x48, 0xBD, 0xF8,
+ 0x7A, 0x6C, 0x36, 0x2C, 0x1E, 0x28, 0x9D, 0x39, 0x03, 0xA3, 0x0B, 0x98,
+ 0x32, 0xC5, 0x74, 0x1F, 0xA2, 0x50, 0x36, 0x3E, 0x7A, 0xCB, 0xC7, 0xF7,
+ 0x7F, 0x3D, 0xAC, 0xBC, 0x1F, 0x13, 0x1A, 0xDD, 0x8E, 0x03, 0x36, 0x7E,
+ 0xFF, 0x8F, 0xBB, 0xB3, 0xE1, 0xC5, 0x78, 0x44, 0x24, 0x80, 0x9B, 0x25,
+ 0xAF, 0xE4, 0xD2, 0x26, 0x2A, 0x1A, 0x6F, 0xD2, 0xFA, 0xB6, 0x41, 0x05,
+ 0xCA, 0x30, 0xA6, 0x74, 0xE0, 0x7F, 0x78, 0x09, 0x85, 0x20, 0x88, 0x63,
+ 0x2F, 0xC0, 0x49, 0x23, 0x37, 0x91, 0xAD, 0x4E, 0xDD, 0x08, 0x3A, 0x97,
+ 0x8B, 0x88, 0x3E, 0xE6, 0x18, 0xBC, 0x5E, 0x0D, 0xD0, 0x47, 0x41, 0x5F,
+ 0x2D, 0x95, 0xE6, 0x83, 0xCF, 0x14, 0x82, 0x6B, 0x5F, 0xBE, 0x10, 0xD3,
+ 0xCE, 0x41, 0xC6, 0xC1, 0x20, 0xC7, 0x8A, 0xB2, 0x00, 0x08, 0xC6, 0x98,
+ 0xBF, 0x7F, 0x0B, 0xCA, 0xB9, 0xD7, 0xF4, 0x07, 0xBE, 0xD0, 0xF4, 0x3A,
+ 0xFB, 0x29, 0x70, 0xF5, 0x7F, 0x8D, 0x12, 0x04, 0x39, 0x63, 0xE6, 0x6D,
+ 0xDD, 0x32, 0x0D, 0x59, 0x9A, 0xD9, 0x93, 0x6C, 0x8F, 0x44, 0x13, 0x7C,
+ 0x08, 0xB1, 0x80, 0xEC, 0x5E, 0x98, 0x5C, 0xEB, 0xE1, 0x86, 0xF3, 0xD5,
+ 0x49, 0x67, 0x7E, 0x80, 0x60, 0x73, 0x31, 0xEE, 0x17, 0xAF, 0x33, 0x80,
+ 0xA7, 0x25, 0xB0, 0x78, 0x23, 0x17, 0xD7, 0xDD, 0x43, 0xF5, 0x9D, 0x7A,
+ 0xF9, 0x56, 0x8A, 0x9B, 0xB6, 0x3A, 0x84, 0xD3, 0x65, 0xF9, 0x22, 0x44,
+ 0xED, 0x12, 0x09, 0x88, 0x21, 0x93, 0x02, 0xF4, 0x29, 0x24, 0xC7, 0xCA,
+ 0x90, 0xB8, 0x9D, 0x24, 0xF7, 0x1B, 0x0A, 0xB6, 0x97, 0x82, 0x3D, 0x7D,
+ 0xEB, 0x1A, 0xFF, 0x5B, 0x0E, 0x8E, 0x4A, 0x45, 0xD4, 0x9F, 0x7F, 0x53,
+ 0x75, 0x7E, 0x19, 0x13};
+static const unsigned char dhtest_2048_256_Z[] = {
+ 0x86, 0xC7, 0x0B, 0xF8, 0xD0, 0xBB, 0x81, 0xBB, 0x01, 0x07, 0x8A, 0x17,
+ 0x21, 0x9C, 0xB7, 0xD2, 0x72, 0x03, 0xDB, 0x2A, 0x19, 0xC8, 0x77, 0xF1,
+ 0xD1, 0xF1, 0x9F, 0xD7, 0xD7, 0x7E, 0xF2, 0x25, 0x46, 0xA6, 0x8F, 0x00,
+ 0x5A, 0xD5, 0x2D, 0xC8, 0x45, 0x53, 0xB7, 0x8F, 0xC6, 0x03, 0x30, 0xBE,
+ 0x51, 0xEA, 0x7C, 0x06, 0x72, 0xCA, 0xC1, 0x51, 0x5E, 0x4B, 0x35, 0xC0,
+ 0x47, 0xB9, 0xA5, 0x51, 0xB8, 0x8F, 0x39, 0xDC, 0x26, 0xDA, 0x14, 0xA0,
+ 0x9E, 0xF7, 0x47, 0x74, 0xD4, 0x7C, 0x76, 0x2D, 0xD1, 0x77, 0xF9, 0xED,
+ 0x5B, 0xC2, 0xF1, 0x1E, 0x52, 0xC8, 0x79, 0xBD, 0x95, 0x09, 0x85, 0x04,
+ 0xCD, 0x9E, 0xEC, 0xD8, 0xA8, 0xF9, 0xB3, 0xEF, 0xBD, 0x1F, 0x00, 0x8A,
+ 0xC5, 0x85, 0x30, 0x97, 0xD9, 0xD1, 0x83, 0x7F, 0x2B, 0x18, 0xF7, 0x7C,
+ 0xD7, 0xBE, 0x01, 0xAF, 0x80, 0xA7, 0xC7, 0xB5, 0xEA, 0x3C, 0xA5, 0x4C,
+ 0xC0, 0x2D, 0x0C, 0x11, 0x6F, 0xEE, 0x3F, 0x95, 0xBB, 0x87, 0x39, 0x93,
+ 0x85, 0x87, 0x5D, 0x7E, 0x86, 0x74, 0x7E, 0x67, 0x6E, 0x72, 0x89, 0x38,
+ 0xAC, 0xBF, 0xF7, 0x09, 0x8E, 0x05, 0xBE, 0x4D, 0xCF, 0xB2, 0x40, 0x52,
+ 0xB8, 0x3A, 0xEF, 0xFB, 0x14, 0x78, 0x3F, 0x02, 0x9A, 0xDB, 0xDE, 0x7F,
+ 0x53, 0xFA, 0xE9, 0x20, 0x84, 0x22, 0x40, 0x90, 0xE0, 0x07, 0xCE, 0xE9,
+ 0x4D, 0x4B, 0xF2, 0xBA, 0xCE, 0x9F, 0xFD, 0x4B, 0x57, 0xD2, 0xAF, 0x7C,
+ 0x72, 0x4D, 0x0C, 0xAA, 0x19, 0xBF, 0x05, 0x01, 0xF6, 0xF1, 0x7B, 0x4A,
+ 0xA1, 0x0F, 0x42, 0x5E, 0x3E, 0xA7, 0x60, 0x80, 0xB4, 0xB9, 0xD6, 0xB3,
+ 0xCE, 0xFE, 0xA1, 0x15, 0xB2, 0xCE, 0xB8, 0x78, 0x9B, 0xB8, 0xA3, 0xB0,
+ 0xEA, 0x87, 0xFE, 0xBE, 0x63, 0xB6, 0xC8, 0xF8, 0x46, 0xEC, 0x6D, 0xB0,
+ 0xC2, 0x6C, 0x5D, 0x7C};
+
+typedef struct {
+ DH *(*get_param)(const ENGINE *engine);
+ const unsigned char *xA;
+ size_t xA_len;
+ const unsigned char *yA;
+ size_t yA_len;
+ const unsigned char *xB;
+ size_t xB_len;
+ const unsigned char *yB;
+ size_t yB_len;
+ const unsigned char *Z;
+ size_t Z_len;
+} rfc5114_td;
+
+#define make_rfc5114_td(pre) \
+ { \
+ DH_get_##pre, dhtest_##pre##_xA, sizeof(dhtest_##pre##_xA), \
+ dhtest_##pre##_yA, sizeof(dhtest_##pre##_yA), dhtest_##pre##_xB, \
+ sizeof(dhtest_##pre##_xB), dhtest_##pre##_yB, \
+ sizeof(dhtest_##pre##_yB), dhtest_##pre##_Z, sizeof(dhtest_##pre##_Z) \
+ }
+
+static const rfc5114_td rfctd[] = {make_rfc5114_td(1024_160),
+ make_rfc5114_td(2048_224),
+ make_rfc5114_td(2048_256)};
+
+static int run_rfc5114_tests(void) {
+ int i;
+ DH *dhA = NULL, *dhB = NULL;
+ unsigned char *Z1 = NULL, *Z2 = NULL;
+
+ for (i = 0; i < (int)(sizeof(rfctd) / sizeof(rfc5114_td)); i++) {
+ const rfc5114_td *td = rfctd + i;
+ /* Set up DH structures setting key components */
+ dhA = td->get_param(NULL);
+ dhB = td->get_param(NULL);
+ if (!dhA || !dhB)
+ goto bad_err;
+
+ dhA->priv_key = BN_bin2bn(td->xA, td->xA_len, NULL);
+ dhA->pub_key = BN_bin2bn(td->yA, td->yA_len, NULL);
+
+ dhB->priv_key = BN_bin2bn(td->xB, td->xB_len, NULL);
+ dhB->pub_key = BN_bin2bn(td->yB, td->yB_len, NULL);
+
+ if (!dhA->priv_key || !dhA->pub_key || !dhB->priv_key || !dhB->pub_key)
+ goto bad_err;
+
+ if ((td->Z_len != (size_t)DH_size(dhA)) ||
+ (td->Z_len != (size_t)DH_size(dhB)))
+ goto err;
+
+ Z1 = OPENSSL_malloc(DH_size(dhA));
+ Z2 = OPENSSL_malloc(DH_size(dhB));
+ /* Work out shared secrets using both sides and compare
+ * with expected values.
+ */
+ if (!DH_compute_key(Z1, dhB->pub_key, dhA))
+ goto bad_err;
+ if (!DH_compute_key(Z2, dhA->pub_key, dhB))
+ goto bad_err;
+
+ if (memcmp(Z1, td->Z, td->Z_len))
+ goto err;
+ if (memcmp(Z2, td->Z, td->Z_len))
+ goto err;
+
+ printf("RFC5114 parameter test %d OK\n", i + 1);
+
+ DH_free(dhA);
+ dhA = NULL;
+ DH_free(dhB);
+ dhB = NULL;
+ OPENSSL_free(Z1);
+ Z1 = NULL;
+ OPENSSL_free(Z2);
+ Z2 = NULL;
+ }
+
+ printf("PASS\n");
+ return 1;
+
+bad_err:
+ fprintf(stderr, "Initalisation error RFC5114 set %d\n", i + 1);
+ BIO_print_errors_fp(stderr);
+
+err:
+ if (Z1 != NULL) {
+ OPENSSL_free(Z1);
+ }
+ if (Z2 != NULL) {
+ OPENSSL_free(Z2);
+ }
+ if (dhA != NULL) {
+ DH_free(dhA);
+ }
+ if (dhB != NULL) {
+ DH_free(dhB);
+ }
+
+ fprintf(stderr, "Test failed RFC5114 set %d\n", i + 1);
+ return 0;
+}
diff --git a/src/crypto/dh/internal.h b/src/crypto/dh/internal.h
new file mode 100644
index 0000000..81b9c90
--- /dev/null
+++ b/src/crypto/dh/internal.h
@@ -0,0 +1,80 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 OPENSSL_HEADER_DH_INTERNAL_H
+#define OPENSSL_HEADER_DH_INTERNAL_H
+
+#include <openssl/base.h>
+
+#include <openssl/bn.h>
+#include <openssl/ex_data.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* DH_check_standard_parameters checks if the parameters in |dh| are well
+ * known and safe. If so, it sets |dh->priv_length| to an appropriately smaller
+ * value than the default. */
+void DH_check_standard_parameters(DH *dh);
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_DH_INTERNAL_H */
diff --git a/src/crypto/dh/params.c b/src/crypto/dh/params.c
new file mode 100644
index 0000000..82d1d92
--- /dev/null
+++ b/src/crypto/dh/params.c
@@ -0,0 +1,316 @@
+/* ====================================================================
+ * 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.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com). */
+
+#include <openssl/dh.h>
+
+#include <openssl/bn.h>
+
+#include "internal.h"
+
+
+#if BN_BITS2 == 32
+#define TOBN(lo, hi) lo, hi
+#elif BN_BITS2 == 64
+#define TOBN(lo, hi) ((BN_ULONG)hi << 32 | lo)
+#else
+#error "unsupported BN_BITS2"
+#endif
+
+static const BN_ULONG dh1024_160_p[] = {
+ TOBN(0x2E4A4371, 0xDF1FB2BC), TOBN(0x6D4DA708, 0xE68CFDA7),
+ TOBN(0x365C1A65, 0x45BF37DF), TOBN(0x0DC8B4BD, 0xA151AF5F),
+ TOBN(0xF55BCCC0, 0xFAA31A4F), TOBN(0xE5644738, 0x4EFFD6FA),
+ TOBN(0x219A7372, 0x98488E9C), TOBN(0x90C4BD70, 0xACCBDD7D),
+ TOBN(0xD49B83BF, 0x24975C3C), TOBN(0xA9061123, 0x13ECB4AE),
+ TOBN(0x2EE652C0, 0x9838EF1E), TOBN(0x75A23D18, 0x6073E286),
+ TOBN(0x52D23B61, 0x9A6A9DCA), TOBN(0xFB06A3C6, 0x52C99FBC),
+ TOBN(0xAE5D54EC, 0xDE92DE5E), TOBN(0xA080E01D, 0xB10B8F96),
+};
+static const BN_ULONG dh1024_160_g[] = {
+ TOBN(0x22B3B2E5, 0x855E6EEB), TOBN(0xF97C2A24, 0x858F4DCE),
+ TOBN(0x18D08BC8, 0x2D779D59), TOBN(0x8E73AFA3, 0xD662A4D1),
+ TOBN(0x69B6A28A, 0x1DBF0A01), TOBN(0x7A091F53, 0xA6A24C08),
+ TOBN(0x63F80A76, 0x909D0D22), TOBN(0xB9A92EE1, 0xD7FBD7D3),
+ TOBN(0x9E2749F4, 0x5E91547F), TOBN(0xB01B886A, 0x160217B4),
+ TOBN(0x5504F213, 0x777E690F), TOBN(0x5C41564B, 0x266FEA1E),
+ TOBN(0x14266D31, 0xD6406CFF), TOBN(0x58AC507F, 0xF8104DD2),
+ TOBN(0xEFB99905, 0x6765A442), TOBN(0xC3FD3412, 0xA4D1CBD5),
+};
+static const BN_ULONG dh1024_160_q[] = {
+ TOBN(0x49462353, 0x64B7CB9D), TOBN(0x8ABA4E7D, 0x81A8DF27), 0xF518AA87,
+};
+
+static const BN_ULONG dh2048_224_p[] = {
+ TOBN(0x0C10E64F, 0x0AC4DFFE), TOBN(0x4E71B81C, 0xCF9DE538),
+ TOBN(0xFFA31F71, 0x7EF363E2), TOBN(0x6B8E75B9, 0xE3FB73C1),
+ TOBN(0x4BA80A29, 0xC9B53DCF), TOBN(0x16E79763, 0x23F10B0E),
+ TOBN(0x13042E9B, 0xC52172E4), TOBN(0xC928B2B9, 0xBE60E69C),
+ TOBN(0xB9E587E8, 0x80CD86A1), TOBN(0x98C641A4, 0x315D75E1),
+ TOBN(0x44328387, 0xCDF93ACC), TOBN(0xDC0A486D, 0x15987D9A),
+ TOBN(0x1FD5A074, 0x7310F712), TOBN(0xDE31EFDC, 0x278273C7),
+ TOBN(0x415D9330, 0x1602E714), TOBN(0xBC8985DB, 0x81286130),
+ TOBN(0x70918836, 0xB3BF8A31), TOBN(0xB9C49708, 0x6A00E0A0),
+ TOBN(0x8BBC27BE, 0xC6BA0B2C), TOBN(0xED34DBF6, 0xC9F98D11),
+ TOBN(0xB6C12207, 0x7AD5B7D0), TOBN(0x55B7394B, 0xD91E8FEF),
+ TOBN(0xEFDA4DF8, 0x9037C9ED), TOBN(0xAD6AC212, 0x6D3F8152),
+ TOBN(0x1274A0A6, 0x1DE6B85A), TOBN(0x309C180E, 0xEB3D688A),
+ TOBN(0x7BA1DF15, 0xAF9A3C40), TOBN(0xF95A56DB, 0xE6FA141D),
+ TOBN(0xB61D0A75, 0xB54B1597), TOBN(0x683B9FD1, 0xA20D64E5),
+ TOBN(0x9559C51F, 0xD660FAA7), TOBN(0x9123A9D0, 0xAD107E1E),
+};
+
+static const BN_ULONG dh2048_224_g[] = {
+ TOBN(0x191F2BFA, 0x84B890D3), TOBN(0x2A7065B3, 0x81BC087F),
+ TOBN(0xF6EC0179, 0x19C418E1), TOBN(0x71CFFF4C, 0x7B5A0F1C),
+ TOBN(0x9B6AA4BD, 0xEDFE72FE), TOBN(0x94B30269, 0x81E1BCFE),
+ TOBN(0x8D6C0191, 0x566AFBB4), TOBN(0x409D13CD, 0xB539CCE3),
+ TOBN(0x5F2FF381, 0x6AA21E7F), TOBN(0x770589EF, 0xD9E263E4),
+ TOBN(0xD19963DD, 0x10E183ED), TOBN(0x150B8EEB, 0xB70A8137),
+ TOBN(0x28C8F8AC, 0x051AE3D4), TOBN(0x0C1AB15B, 0xBB77A86F),
+ TOBN(0x16A330EF, 0x6E3025E3), TOBN(0xD6F83456, 0x19529A45),
+ TOBN(0x118E98D1, 0xF180EB34), TOBN(0x50717CBE, 0xB5F6C6B2),
+ TOBN(0xDA7460CD, 0x09939D54), TOBN(0x22EA1ED4, 0xE2471504),
+ TOBN(0x521BC98A, 0xB8A762D0), TOBN(0x5AC1348B, 0xF4D02727),
+ TOBN(0x1999024A, 0xC1766910), TOBN(0xA8D66AD7, 0xBE5E9001),
+ TOBN(0x620A8652, 0xC57DB17C), TOBN(0x00C29F52, 0xAB739D77),
+ TOBN(0xA70C4AFA, 0xDD921F01), TOBN(0x10B9A6F0, 0xA6824A4E),
+ TOBN(0xCFE4FFE3, 0x74866A08), TOBN(0x89998CAF, 0x6CDEBE7B),
+ TOBN(0x8FFDAC50, 0x9DF30B5C), TOBN(0x4F2D9AE3, 0xAC4032EF),
+};
+
+static const BN_ULONG dh2048_224_q[] = {
+ TOBN(0xB36371EB, 0xBF389A99), TOBN(0x4738CEBC, 0x1F80535A),
+ TOBN(0x99717710, 0xC58D93FE), 0x801C0D34,
+};
+
+static const BN_ULONG dh2048_256_p[] = {
+ TOBN(0x1E1A1597, 0xDB094AE9), TOBN(0xD7EF09CA, 0x693877FA),
+ TOBN(0x6E11715F, 0x6116D227), TOBN(0xC198AF12, 0xA4B54330),
+ TOBN(0xD7014103, 0x75F26375), TOBN(0x54E710C3, 0xC3A3960A),
+ TOBN(0xBD0BE621, 0xDED4010A), TOBN(0x89962856, 0xC0B857F6),
+ TOBN(0x71506026, 0xB3CA3F79), TOBN(0xE6B486F6, 0x1CCACB83),
+ TOBN(0x14056425, 0x67E144E5), TOBN(0xA41825D9, 0xF6A167B5),
+ TOBN(0x96524D8E, 0x3AD83477), TOBN(0x51BFA4AB, 0xF13C6D9A),
+ TOBN(0x35488A0E, 0x2D525267), TOBN(0xCAA6B790, 0xB63ACAE1),
+ TOBN(0x81B23F76, 0x4FDB70C5), TOBN(0x12307F5C, 0xBC39A0BF),
+ TOBN(0xB1E59BB8, 0xB941F54E), TOBN(0xD45F9088, 0x6C5BFC11),
+ TOBN(0x4275BF7B, 0x22E0B1EF), TOBN(0x5B4758C0, 0x91F9E672),
+ TOBN(0x6BCF67ED, 0x5A8A9D30), TOBN(0x97517ABD, 0x209E0C64),
+ TOBN(0x830E9A7C, 0x3BF4296D), TOBN(0x34096FAA, 0x16C3D911),
+ TOBN(0x61B2AA30, 0xFAF7DF45), TOBN(0xD61957D4, 0xE00DF8F1),
+ TOBN(0x435E3B00, 0x5D2CEED4), TOBN(0x660DD0F2, 0x8CEEF608),
+ TOBN(0x65195999, 0xFFBBD19C), TOBN(0xB4B6663C, 0x87A8E61D),
+};
+static const BN_ULONG dh2048_256_g[] = {
+ TOBN(0x6CC41659, 0x664B4C0F), TOBN(0xEF98C582, 0x5E2327CF),
+ TOBN(0xD4795451, 0xD647D148), TOBN(0x90F00EF8, 0x2F630784),
+ TOBN(0x1DB246C3, 0x184B523D), TOBN(0xCDC67EB6, 0xC7891428),
+ TOBN(0x0DF92B52, 0x7FD02837), TOBN(0x64E0EC37, 0xB3353BBB),
+ TOBN(0x57CD0915, 0xECD06E15), TOBN(0xDF016199, 0xB7D2BBD2),
+ TOBN(0x052588B9, 0xC8484B1E), TOBN(0x13D3FE14, 0xDB2A3B73),
+ TOBN(0xD182EA0A, 0xD052B985), TOBN(0xE83B9C80, 0xA4BD1BFF),
+ TOBN(0xFB3F2E55, 0xDFC967C1), TOBN(0x767164E1, 0xB5045AF2),
+ TOBN(0x6F2F9193, 0x1D14348F), TOBN(0x428EBC83, 0x64E67982),
+ TOBN(0x82D6ED38, 0x8AC376D2), TOBN(0xAAB8A862, 0x777DE62A),
+ TOBN(0xE9EC144B, 0xDDF463E5), TOBN(0xC77A57F2, 0x0196F931),
+ TOBN(0x41000A65, 0xA55AE313), TOBN(0xC28CBB18, 0x901228F8),
+ TOBN(0x7E8C6F62, 0xBC3773BF), TOBN(0x0C6B47B1, 0xBE3A6C1B),
+ TOBN(0xAC0BB555, 0xFF4FED4A), TOBN(0x77BE463F, 0x10DBC150),
+ TOBN(0x1A0BA125, 0x07F4793A), TOBN(0x21EF2054, 0x4CA7B18F),
+ TOBN(0x60EDBD48, 0x2E775066), TOBN(0x73134D0B, 0x3FB32C9B),
+};
+static const BN_ULONG dh2048_256_q[] = {
+ TOBN(0x64F5FBD3, 0xA308B0FE), TOBN(0x1EB3750B, 0x99B1A47D),
+ TOBN(0x40129DA2, 0xB4479976), TOBN(0xA709A097, 0x8CF83642),
+};
+
+/* dh1024_safe_prime_1 is hard-coded in Apache httpd 2.2,
+ * modules/ssl/ssl_engine_dh.c. */
+static const BN_ULONG dh1024_safe_prime_1[] = {
+ TOBN(0x24218EB3, 0xE7393E0F), TOBN(0xE2BD68B0, 0x7DE0F4D6),
+ TOBN(0x88AEAA74, 0x07DD62DB), TOBN(0x9DDD3305, 0x10EA9FCC),
+ TOBN(0x74087D15, 0xA7DBCA78), TOBN(0x78045B07, 0xDAE88600),
+ TOBN(0x1AAD3B72, 0x33168A46), TOBN(0x7BEDDCFD, 0xFF590137),
+ TOBN(0x7A635E81, 0xFE324A46), TOBN(0x420B2A29, 0x5AC179BA),
+ TOBN(0x177E16D5, 0x13B4B4D7), TOBN(0x639C72FB, 0x849F912E),
+ TOBN(0x98BCE951, 0xB88174CB), TOBN(0xA45F520B, 0x0C84D239),
+ TOBN(0x4AFD0AD5, 0x36D693D3), TOBN(0xCBBBDC19, 0xD67DE440),
+};
+
+/* dh1024_safe_prime_2 is hard-coded in nginx,
+ * src/event/ngx_event_openssl.c. */
+static const BN_ULONG dh1024_safe_prime_2[] = {
+ TOBN(0xCFE16B9B, 0x071DF045), TOBN(0x146757DA, 0x88D0F65D),
+ TOBN(0x58FAFD49, 0x4A63AB1E), TOBN(0xEF9EA027, 0x35D8CECE),
+ TOBN(0x70CC9A50, 0x25ECE662), TOBN(0x81DC2CA7, 0xF29BA5DF),
+ TOBN(0xF7D36CC8, 0x8F68B076), TOBN(0xA757E304, 0x60E91A92),
+ TOBN(0x9BE67780, 0x87A2BC04), TOBN(0xA5FDF1D2, 0xBEECA565),
+ TOBN(0x922614C5, 0x5CCBBAA8), TOBN(0xE710800C, 0x6C030276),
+ TOBN(0x0FB3504C, 0x08EED4EB), TOBN(0x68B42D4B, 0xD958A3F5),
+ TOBN(0x80E9CFDB, 0x7C43FCF5), TOBN(0xD8467490, 0xBBBC2DCA),
+};
+
+/* dh1024_safe_prime_3 is offered as a parameter by several high-traffic sites,
+ * including mozilla.org, as of Jan 2015. */
+static const BN_ULONG dh1024_safe_prime_3[] = {
+ TOBN(0x349E721B, 0x671746AE), TOBN(0xD75E93B2, 0x258A0655),
+ TOBN(0x25592EB6, 0xD425E6FB), TOBN(0xBF7CDD9A, 0x0C46AB04),
+ TOBN(0x28968680, 0x0AD0BC99), TOBN(0xD0B7EB49, 0xF53907FB),
+ TOBN(0xEBC85C1D, 0x202EABB3), TOBN(0x364D8C71, 0x3129C693),
+ TOBN(0x2D46F195, 0x53728351), TOBN(0x8C76CC85, 0xDF326DD6),
+ TOBN(0x9188E24E, 0xF898B3F9), TOBN(0x2855DFD2, 0x95EFB13C),
+ TOBN(0x7B2241FE, 0x1F5DAC48), TOBN(0x99A13D9F, 0x117B6BF7),
+ TOBN(0x3A3468C7, 0x0F97CDDA), TOBN(0x74A8297B, 0xC9BBF5F7)};
+
+/* dh1024_safe_prime_4 is hard-coded in Apache httpd 2.0,
+ * modules/ssl/ssl_engine_dh.c. */
+static const BN_ULONG dh1024_safe_prime_4[] = {
+ TOBN(0x0DD5C86B, 0x5085E21F), TOBN(0xD823C650, 0x871538DF),
+ TOBN(0x262E56A8, 0x125136F7), TOBN(0x839EB5DB, 0x974E9EF1),
+ TOBN(0x1B13A63C, 0xEA9BAD99), TOBN(0x3D76E05E, 0x6044CF02),
+ TOBN(0x1BAC9B5C, 0x611EBBBE), TOBN(0x4E5327DF, 0x3E371D79),
+ TOBN(0x061CBC05, 0x000E6EDD), TOBN(0x20129B48, 0x2F971F3C),
+ TOBN(0x3048D5A2, 0xA6EF09C4), TOBN(0xCBD523A6, 0xFA15A259),
+ TOBN(0x4A79A770, 0x2A206490), TOBN(0x51BB055E, 0x91B78182),
+ TOBN(0xBDD4798E, 0x7CF180C3), TOBN(0x495BE32C, 0xE6969D3D)};
+
+static const BN_ULONG bn_two_data[] = {2};
+
+#define STATIC_BIGNUM(x) \
+ { \
+ (BN_ULONG *) x, sizeof(x) / sizeof(BN_ULONG), \
+ sizeof(x) / sizeof(BN_ULONG), 0, BN_FLG_STATIC_DATA \
+ }
+
+struct standard_parameters {
+ BIGNUM p, q, g;
+};
+
+static const struct standard_parameters dh1024_160 = {
+ STATIC_BIGNUM(dh1024_160_p),
+ STATIC_BIGNUM(dh1024_160_q),
+ STATIC_BIGNUM(dh1024_160_g),
+};
+
+static const struct standard_parameters dh2048_224 = {
+ STATIC_BIGNUM(dh2048_224_p),
+ STATIC_BIGNUM(dh2048_224_q),
+ STATIC_BIGNUM(dh2048_224_g),
+};
+
+static const struct standard_parameters dh2048_256 = {
+ STATIC_BIGNUM(dh2048_256_p),
+ STATIC_BIGNUM(dh2048_256_q),
+ STATIC_BIGNUM(dh2048_256_g),
+};
+
+static const BIGNUM dh1024_safe_prime[] = {
+ STATIC_BIGNUM(dh1024_safe_prime_1),
+ STATIC_BIGNUM(dh1024_safe_prime_2),
+ STATIC_BIGNUM(dh1024_safe_prime_3),
+ STATIC_BIGNUM(dh1024_safe_prime_4)
+};
+
+BIGNUM bn_two = STATIC_BIGNUM(bn_two_data);
+
+static DH *get_standard_parameters(const struct standard_parameters *params,
+ const ENGINE *engine) {
+ DH *dh;
+
+ dh = DH_new_method(engine);
+ if (!dh) {
+ return NULL;
+ }
+
+ dh->p = BN_dup(&params->p);
+ dh->q = BN_dup(&params->q);
+ dh->g = BN_dup(&params->g);
+ if (!dh->p || !dh->q || !dh->g) {
+ DH_free(dh);
+ return NULL;
+ }
+
+ return dh;
+}
+
+DH *DH_get_1024_160(const ENGINE *engine) {
+ return get_standard_parameters(&dh1024_160, engine);
+}
+
+DH *DH_get_2048_224(const ENGINE *engine) {
+ return get_standard_parameters(&dh2048_224, engine);
+}
+
+DH *DH_get_2048_256(const ENGINE *engine) {
+ return get_standard_parameters(&dh2048_256, engine);
+}
+
+void DH_check_standard_parameters(DH *dh) {
+ int i;
+
+ if (dh->p == NULL ||
+ dh->g == NULL ||
+ BN_num_bytes(dh->p) != (1024 / 8) ||
+ BN_cmp(dh->g, &bn_two) != 0) {
+ return;
+ }
+
+ for (i = 0; i < sizeof(dh1024_safe_prime) / sizeof(dh1024_safe_prime[0]);
+ i++) {
+ if (BN_cmp(dh->p, &dh1024_safe_prime[i]) == 0) {
+ /* The well-known DH groups are known to have safe primes. In this case
+ * we can safely reduce the size of the private key. */
+ dh->priv_length = 161;
+ break;
+ }
+ }
+}
diff --git a/src/crypto/digest/CMakeLists.txt b/src/crypto/digest/CMakeLists.txt
new file mode 100644
index 0000000..6426399
--- /dev/null
+++ b/src/crypto/digest/CMakeLists.txt
@@ -0,0 +1,19 @@
+include_directories(. .. ../../include)
+
+add_library(
+ digest
+
+ OBJECT
+
+ digest.c
+ digests.c
+ digest_error.c
+)
+
+add_executable(
+ digest_test
+
+ digest_test.c
+)
+
+target_link_libraries(digest_test crypto)
diff --git a/src/crypto/digest/digest.c b/src/crypto/digest/digest.c
new file mode 100644
index 0000000..3897c60
--- /dev/null
+++ b/src/crypto/digest/digest.c
@@ -0,0 +1,273 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/digest.h>
+
+#include <assert.h>
+#include <string.h>
+
+#include <openssl/err.h>
+#include <openssl/obj.h>
+#include <openssl/mem.h>
+
+#include "internal.h"
+
+
+int EVP_MD_type(const EVP_MD *md) { return md->type; }
+
+const char *EVP_MD_name(const EVP_MD *md) { return OBJ_nid2sn(md->type); }
+
+uint32_t EVP_MD_flags(const EVP_MD *md) { return md->flags; }
+
+size_t EVP_MD_size(const EVP_MD *md) { return md->md_size; }
+
+size_t EVP_MD_block_size(const EVP_MD *md) { return md->block_size; }
+
+
+void EVP_MD_CTX_init(EVP_MD_CTX *ctx) { memset(ctx, 0, sizeof(EVP_MD_CTX)); }
+
+EVP_MD_CTX *EVP_MD_CTX_create(void) {
+ EVP_MD_CTX *ctx = OPENSSL_malloc(sizeof(EVP_MD_CTX));
+
+ if (ctx) {
+ EVP_MD_CTX_init(ctx);
+ }
+
+ return ctx;
+}
+
+int EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx) {
+ if (ctx->digest && ctx->digest->ctx_size && ctx->md_data) {
+ OPENSSL_cleanse(ctx->md_data, ctx->digest->ctx_size);
+ OPENSSL_free(ctx->md_data);
+ }
+
+ assert(ctx->pctx == NULL || ctx->pctx_ops != NULL);
+ if (ctx->pctx_ops) {
+ ctx->pctx_ops->free(ctx->pctx);
+ }
+
+ EVP_MD_CTX_init(ctx);
+
+ return 1;
+}
+
+void EVP_MD_CTX_destroy(EVP_MD_CTX *ctx) {
+ if (!ctx) {
+ return;
+ }
+
+ EVP_MD_CTX_cleanup(ctx);
+ OPENSSL_free(ctx);
+}
+
+int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in) {
+ uint8_t *tmp_buf = NULL;
+
+ if (in == NULL || in->digest == NULL) {
+ OPENSSL_PUT_ERROR(DIGEST, EVP_MD_CTX_copy_ex,
+ DIGEST_R_INPUT_NOT_INITIALIZED);
+ return 0;
+ }
+
+ if (out->digest == in->digest) {
+ /* |md_data| will be the correct size in this case so it's removed from
+ * |out| at this point so that |EVP_MD_CTX_cleanup| doesn't free it and
+ * then it's reused. */
+ tmp_buf = out->md_data;
+ out->md_data = NULL;
+ }
+
+ EVP_MD_CTX_cleanup(out);
+ memcpy(out, in, sizeof(EVP_MD_CTX));
+
+ if (in->md_data && in->digest->ctx_size) {
+ if (tmp_buf) {
+ out->md_data = tmp_buf;
+ } else {
+ out->md_data = OPENSSL_malloc(in->digest->ctx_size);
+ if (!out->md_data) {
+ OPENSSL_PUT_ERROR(DIGEST, EVP_MD_CTX_copy_ex, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ }
+ memcpy(out->md_data, in->md_data, in->digest->ctx_size);
+ }
+
+ assert(in->pctx == NULL || in->pctx_ops != NULL);
+ if (in->pctx && in->pctx_ops) {
+ out->pctx = in->pctx_ops->dup(in->pctx);
+ if (!out->pctx) {
+ EVP_MD_CTX_cleanup(out);
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+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_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *engine) {
+ if (ctx->digest != type) {
+ if (ctx->digest && ctx->digest->ctx_size) {
+ OPENSSL_free(ctx->md_data);
+ }
+ ctx->digest = type;
+ if (!(ctx->flags & EVP_MD_CTX_FLAG_NO_INIT) && type->ctx_size) {
+ ctx->update = type->update;
+ ctx->md_data = OPENSSL_malloc(type->ctx_size);
+ if (ctx->md_data == NULL) {
+ OPENSSL_PUT_ERROR(DIGEST, EVP_DigestInit_ex, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ }
+ }
+
+ assert(ctx->pctx == NULL || ctx->pctx_ops != NULL);
+ if (ctx->pctx_ops) {
+ if (!ctx->pctx_ops->begin_digest(ctx)) {
+ return 0;
+ }
+ }
+
+ if (ctx->flags & EVP_MD_CTX_FLAG_NO_INIT) {
+ return 1;
+ }
+
+ return ctx->digest->init(ctx);
+}
+
+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_DigestUpdate(EVP_MD_CTX *ctx, const void *data, size_t len) {
+ return ctx->update(ctx, data, len);
+}
+
+int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, uint8_t *md_out, unsigned int *size) {
+ int ret;
+
+ assert(ctx->digest->md_size <= EVP_MAX_MD_SIZE);
+ ret = ctx->digest->final(ctx, md_out);
+ if (size != NULL) {
+ *size = ctx->digest->md_size;
+ }
+ OPENSSL_cleanse(ctx->md_data, ctx->digest->ctx_size);
+
+ return ret;
+}
+
+int EVP_DigestFinal(EVP_MD_CTX *ctx, uint8_t *md, unsigned int *size) {
+ int ret = EVP_DigestFinal_ex(ctx, md, size);
+ EVP_MD_CTX_cleanup(ctx);
+ return ret;
+}
+
+int EVP_Digest(const void *data, size_t count, uint8_t *out_md,
+ unsigned int *out_size, const EVP_MD *type, ENGINE *impl) {
+ EVP_MD_CTX ctx;
+ int ret;
+
+ EVP_MD_CTX_init(&ctx);
+ ret = EVP_DigestInit_ex(&ctx, type, impl) &&
+ EVP_DigestUpdate(&ctx, data, count) &&
+ EVP_DigestFinal_ex(&ctx, out_md, out_size);
+ EVP_MD_CTX_cleanup(&ctx);
+
+ return ret;
+}
+
+
+const EVP_MD *EVP_MD_CTX_md(const EVP_MD_CTX *ctx) {
+ if (ctx == NULL) {
+ return NULL;
+ }
+ return ctx->digest;
+}
+
+unsigned EVP_MD_CTX_size(const EVP_MD_CTX *ctx) {
+ return EVP_MD_size(EVP_MD_CTX_md(ctx));
+}
+
+unsigned EVP_MD_CTX_block_size(const EVP_MD_CTX *ctx) {
+ return EVP_MD_block_size(EVP_MD_CTX_md(ctx));
+}
+
+int EVP_MD_CTX_type(const EVP_MD_CTX *ctx) {
+ return EVP_MD_type(EVP_MD_CTX_md(ctx));
+}
+
+void EVP_MD_CTX_set_flags(EVP_MD_CTX *ctx, uint32_t flags) {
+ ctx->flags |= flags;
+}
+
+void EVP_MD_CTX_clear_flags(EVP_MD_CTX *ctx, uint32_t flags) {
+ ctx->flags &= ~flags;
+}
+
+uint32_t EVP_MD_CTX_test_flags(const EVP_MD_CTX *ctx, uint32_t flags) {
+ return ctx->flags & flags;
+}
+
+int EVP_add_digest(const EVP_MD *digest) {
+ return 1;
+}
diff --git a/src/crypto/digest/digest_error.c b/src/crypto/digest/digest_error.c
new file mode 100644
index 0000000..0cc6702
--- /dev/null
+++ b/src/crypto/digest/digest_error.c
@@ -0,0 +1,24 @@
+/* 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 <openssl/err.h>
+
+#include <openssl/digest.h>
+
+const ERR_STRING_DATA DIGEST_error_string_data[] = {
+ {ERR_PACK(ERR_LIB_DIGEST, DIGEST_F_EVP_DigestInit_ex, 0), "EVP_DigestInit_ex"},
+ {ERR_PACK(ERR_LIB_DIGEST, DIGEST_F_EVP_MD_CTX_copy_ex, 0), "EVP_MD_CTX_copy_ex"},
+ {ERR_PACK(ERR_LIB_DIGEST, 0, DIGEST_R_INPUT_NOT_INITIALIZED), "INPUT_NOT_INITIALIZED"},
+ {0, NULL},
+};
diff --git a/src/crypto/digest/digest_test.c b/src/crypto/digest/digest_test.c
new file mode 100644
index 0000000..6c73e95
--- /dev/null
+++ b/src/crypto/digest/digest_test.c
@@ -0,0 +1,244 @@
+/* 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 <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <openssl/crypto.h>
+#include <openssl/digest.h>
+#include <openssl/err.h>
+#include <openssl/md4.h>
+#include <openssl/md5.h>
+#include <openssl/sha.h>
+
+
+typedef struct {
+ /* md_func is the digest to test. */
+ const EVP_MD *(*md_func)(void);
+ /* one_shot_func is the convenience one-shot version of the
+ * digest. */
+ uint8_t *(*one_shot_func)(const uint8_t *, size_t, uint8_t *);
+ /* input is a NUL-terminated string to hash. */
+ const char *input;
+ /* repeat is the number of times to repeat input. */
+ size_t repeat;
+ /* expected_hex is the expected digest in hexadecimal. */
+ const char *expected_hex;
+} TEST_VECTOR;
+
+static const TEST_VECTOR kTestVectors[] = {
+ /* MD4 tests, from RFC 1320. (crypto/md4 does not provide a
+ * one-shot MD4 function.) */
+ { &EVP_md4, NULL, "", 1, "31d6cfe0d16ae931b73c59d7e0c089c0" },
+ { &EVP_md4, NULL, "a", 1, "bde52cb31de33e46245e05fbdbd6fb24" },
+ { &EVP_md4, NULL, "abc", 1, "a448017aaf21d8525fc10ae87aa6729d" },
+ { &EVP_md4, NULL, "message digest", 1,
+ "d9130a8164549fe818874806e1c7014b" },
+ { &EVP_md4, NULL, "abcdefghijklmnopqrstuvwxyz", 1,
+ "d79e1c308aa5bbcdeea8ed63df412da9" },
+ { &EVP_md4, NULL,
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 1,
+ "043f8582f241db351ce627e153e7f0e4" },
+ { &EVP_md4, NULL, "1234567890", 8, "e33b4ddc9c38f2199c3e7b164fcc0536" },
+
+ /* MD5 tests, from RFC 1321. */
+ { &EVP_md5, &MD5, "", 1, "d41d8cd98f00b204e9800998ecf8427e" },
+ { &EVP_md5, &MD5, "a", 1, "0cc175b9c0f1b6a831c399e269772661" },
+ { &EVP_md5, &MD5, "abc", 1, "900150983cd24fb0d6963f7d28e17f72" },
+ { &EVP_md5, &MD5, "message digest", 1, "f96b697d7cb7938d525a2f31aaf161d0" },
+ { &EVP_md5, &MD5, "abcdefghijklmnopqrstuvwxyz", 1,
+ "c3fcd3d76192e4007dfb496cca67e13b" },
+ { &EVP_md5, &MD5,
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 1,
+ "d174ab98d277d9f5a5611c2c9f419d9f" },
+ { &EVP_md5, &MD5, "1234567890", 8, "57edf4a22be3c955ac49da2e2107b67a" },
+
+ /* SHA-1 tests, from RFC 3174. */
+ { &EVP_sha1, &SHA1, "abc", 1, "a9993e364706816aba3e25717850c26c9cd0d89d" },
+ { &EVP_sha1, &SHA1,
+ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 1,
+ "84983e441c3bd26ebaae4aa1f95129e5e54670f1" },
+ { &EVP_sha1, &SHA1, "a", 1000000,
+ "34aa973cd4c4daa4f61eeb2bdbad27316534016f" },
+ { &EVP_sha1, &SHA1,
+ "0123456701234567012345670123456701234567012345670123456701234567", 10,
+ "dea356a2cddd90c7a7ecedc5ebb563934f460452" },
+
+ /* SHA-224 tests, from RFC 3874. */
+ { &EVP_sha224, &SHA224, "abc", 1,
+ "23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7" },
+ { &EVP_sha224, &SHA224,
+ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 1,
+ "75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525" },
+ { &EVP_sha224, &SHA224,
+ "a", 1000000,
+ "20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67" },
+
+ /* SHA-256 tests, from NIST. */
+ { &EVP_sha256, &SHA256, "abc", 1,
+ "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" },
+ { &EVP_sha256, &SHA256,
+ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 1,
+ "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1" },
+
+ /* SHA-384 tests, from NIST. */
+ { &EVP_sha384, &SHA384, "abc", 1,
+ "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed"
+ "8086072ba1e7cc2358baeca134c825a7" },
+ { &EVP_sha384, &SHA384,
+ "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
+ "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 1,
+ "09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712"
+ "fcc7c71a557e2db966c3e9fa91746039" },
+
+ /* SHA-512 tests, from NIST. */
+ { &EVP_sha512, &SHA512, "abc", 1,
+ "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a"
+ "2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f" },
+ { &EVP_sha512, &SHA512,
+ "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
+ "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 1,
+ "8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018"
+ "501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909" },
+
+ /* MD5-SHA1 tests. */
+ { &EVP_md5_sha1, NULL, "abc", 1,
+ "900150983cd24fb0d6963f7d28e17f72a9993e364706816aba3e25717850c26c9cd0d89d" },
+};
+
+static int compare_digest(const TEST_VECTOR *test,
+ const uint8_t *digest,
+ size_t digest_len) {
+ static const char kHexTable[] = "0123456789abcdef";
+ size_t i;
+ char digest_hex[2*EVP_MAX_MD_SIZE + 1];
+
+ for (i = 0; i < digest_len; i++) {
+ digest_hex[2*i] = kHexTable[digest[i] >> 4];
+ digest_hex[2*i + 1] = kHexTable[digest[i] & 0xf];
+ }
+ digest_hex[2*digest_len] = '\0';
+
+ if (strcmp(digest_hex, test->expected_hex) != 0) {
+ fprintf(stderr, "%s(\"%s\" * %d) = %s; want %s\n",
+ EVP_MD_name(test->md_func()), test->input, (int)test->repeat,
+ digest_hex, test->expected_hex);
+ return 0;
+ }
+
+ return 1;
+}
+
+static int test_digest(const TEST_VECTOR *test) {
+ int ret = 0;
+ EVP_MD_CTX ctx;
+ size_t i;
+ uint8_t digest[EVP_MAX_MD_SIZE];
+ unsigned digest_len;
+
+ EVP_MD_CTX_init(&ctx);
+
+ /* Test the input provided. */
+ if (!EVP_DigestInit_ex(&ctx, test->md_func(), NULL)) {
+ fprintf(stderr, "EVP_DigestInit_ex failed\n");
+ goto done;
+ }
+ for (i = 0; i < test->repeat; i++) {
+ if (!EVP_DigestUpdate(&ctx, test->input, strlen(test->input))) {
+ fprintf(stderr, "EVP_DigestUpdate failed\n");
+ goto done;
+ }
+ }
+ if (!EVP_DigestFinal_ex(&ctx, digest, &digest_len)) {
+ fprintf(stderr, "EVP_DigestFinal_ex failed\n");
+ goto done;
+ }
+ if (!compare_digest(test, digest, digest_len)) {
+ goto done;
+ }
+
+ /* Test the input one character at a time. */
+ if (!EVP_DigestInit_ex(&ctx, test->md_func(), NULL)) {
+ fprintf(stderr, "EVP_DigestInit_ex failed\n");
+ goto done;
+ }
+ if (!EVP_DigestUpdate(&ctx, NULL, 0)) {
+ fprintf(stderr, "EVP_DigestUpdate failed\n");
+ goto done;
+ }
+ for (i = 0; i < test->repeat; i++) {
+ const char *p;
+ for (p = test->input; *p; p++) {
+ if (!EVP_DigestUpdate(&ctx, p, 1)) {
+ fprintf(stderr, "EVP_DigestUpdate failed\n");
+ goto done;
+ }
+ }
+ }
+ if (!EVP_DigestFinal_ex(&ctx, digest, &digest_len)) {
+ fprintf(stderr, "EVP_DigestFinal_ex failed\n");
+ goto done;
+ }
+ if (digest_len != EVP_MD_size(test->md_func())) {
+ fprintf(stderr, "EVP_MD_size output incorrect\n");
+ goto done;
+ }
+ if (!compare_digest(test, digest, digest_len)) {
+ goto done;
+ }
+
+ /* Test the one-shot function. */
+ if (test->one_shot_func && test->repeat == 1) {
+ uint8_t *out = test->one_shot_func((const uint8_t *)test->input,
+ strlen(test->input), digest);
+ if (out != digest) {
+ fprintf(stderr, "one_shot_func gave incorrect return\n");
+ goto done;
+ }
+ if (!compare_digest(test, digest, EVP_MD_size(test->md_func()))) {
+ goto done;
+ }
+
+ /* Test the deprecated static buffer variant, until it's removed. */
+ out = test->one_shot_func((const uint8_t *)test->input, strlen(test->input),
+ NULL);
+ if (!compare_digest(test, out, EVP_MD_size(test->md_func()))) {
+ goto done;
+ }
+ }
+
+ ret = 1;
+
+done:
+ EVP_MD_CTX_cleanup(&ctx);
+ return ret;
+}
+
+int main(void) {
+ size_t i;
+
+ CRYPTO_library_init();
+ ERR_load_crypto_strings();
+
+ for (i = 0; i < sizeof(kTestVectors) / sizeof(kTestVectors[0]); i++) {
+ if (!test_digest(&kTestVectors[i])) {
+ fprintf(stderr, "Test %d failed\n", (int)i);
+ return 1;
+ }
+ }
+
+ printf("PASS\n");
+ return 0;
+}
diff --git a/src/crypto/digest/digests.c b/src/crypto/digest/digests.c
new file mode 100644
index 0000000..ac00ed3
--- /dev/null
+++ b/src/crypto/digest/digests.c
@@ -0,0 +1,274 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/digest.h>
+
+#include <openssl/md4.h>
+#include <openssl/md5.h>
+#include <openssl/obj.h>
+#include <openssl/sha.h>
+
+#include "internal.h"
+
+
+static int md4_init(EVP_MD_CTX *ctx) { return MD4_Init(ctx->md_data); }
+
+static int md4_update(EVP_MD_CTX *ctx, const void *data, size_t count) {
+ return MD4_Update(ctx->md_data, data, count);
+}
+
+static int md4_final(EVP_MD_CTX *ctx, unsigned char *out) {
+ return MD4_Final(out, ctx->md_data);
+}
+
+static const EVP_MD md4_md = {
+ NID_md4, MD4_DIGEST_LENGTH, 0 /* flags */, md4_init,
+ md4_update, md4_final, 64 /* block size */, sizeof(MD4_CTX),
+};
+
+const EVP_MD *EVP_md4(void) { return &md4_md; }
+
+
+static int md5_init(EVP_MD_CTX *ctx) { return MD5_Init(ctx->md_data); }
+
+static int md5_update(EVP_MD_CTX *ctx, const void *data, size_t count) {
+ return MD5_Update(ctx->md_data, data, count);
+}
+
+static int md5_final(EVP_MD_CTX *ctx, unsigned char *out) {
+ return MD5_Final(out, ctx->md_data);
+}
+
+static const EVP_MD md5_md = {
+ NID_md5, MD5_DIGEST_LENGTH, 0 /* flags */, md5_init,
+ md5_update, md5_final, 64 /* block size */, sizeof(MD5_CTX),
+};
+
+const EVP_MD *EVP_md5(void) { return &md5_md; }
+
+
+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 = {
+ NID_sha1, SHA_DIGEST_LENGTH, 0 /* flags */, sha1_init,
+ sha1_update, sha1_final, 64 /* block size */, sizeof(SHA_CTX),
+};
+
+const EVP_MD *EVP_sha1(void) { return &sha1_md; }
+
+
+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) {
+ return SHA224_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 = {
+ NID_sha224, SHA224_DIGEST_LENGTH, 0 /* flags */,
+ sha224_init, sha224_update, sha224_final,
+ 64 /* block size */, 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 = {
+ NID_sha256, SHA256_DIGEST_LENGTH, 0 /* flags */,
+ sha256_init, sha256_update, sha256_final,
+ 64 /* block size */, sizeof(SHA256_CTX),
+};
+
+const EVP_MD *EVP_sha256(void) { return &sha256_md; }
+
+
+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) {
+ return SHA384_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 = {
+ NID_sha384, SHA384_DIGEST_LENGTH, 0 /* flags */,
+ sha384_init, sha384_update, sha384_final,
+ 128 /* block size */, 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 = {
+ NID_sha512, SHA512_DIGEST_LENGTH, 0 /* flags */,
+ sha512_init, sha512_update, sha512_final,
+ 128 /* block size */, sizeof(SHA512_CTX),
+};
+
+const EVP_MD *EVP_sha512(void) { return &sha512_md; }
+
+
+typedef struct {
+ MD5_CTX md5;
+ SHA_CTX sha1;
+} MD5_SHA1_CTX;
+
+static int md5_sha1_init(EVP_MD_CTX *md_ctx) {
+ MD5_SHA1_CTX *ctx = md_ctx->md_data;
+ return MD5_Init(&ctx->md5) && SHA1_Init(&ctx->sha1);
+}
+
+static int md5_sha1_update(EVP_MD_CTX *md_ctx, const void *data, size_t count) {
+ MD5_SHA1_CTX *ctx = md_ctx->md_data;
+ return MD5_Update(&ctx->md5, data, count) && SHA1_Update(&ctx->sha1, data, count);
+}
+
+static int md5_sha1_final(EVP_MD_CTX *md_ctx, unsigned char *out) {
+ MD5_SHA1_CTX *ctx = md_ctx->md_data;
+ if (!MD5_Final(out, &ctx->md5) ||
+ !SHA1_Final(out + MD5_DIGEST_LENGTH, &ctx->sha1)) {
+ return 0;
+ }
+ return 1;
+}
+
+static const EVP_MD md5_sha1_md = {
+ NID_md5_sha1,
+ MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH,
+ 0 /* flags */,
+ md5_sha1_init,
+ md5_sha1_update,
+ md5_sha1_final,
+ 64 /* block size */,
+ sizeof(MD5_SHA1_CTX),
+};
+
+const EVP_MD *EVP_md5_sha1(void) { return &md5_sha1_md; }
+
+
+struct nid_to_digest {
+ int nid;
+ const EVP_MD* (*md_func)(void);
+};
+
+static const struct nid_to_digest nid_to_digest_mapping[] = {
+ { NID_md5, EVP_md5 },
+ { NID_sha1, EVP_sha1 },
+ { NID_sha224, EVP_sha224 },
+ { NID_sha256, EVP_sha256 },
+ { NID_sha384, EVP_sha384 },
+ { NID_sha512, EVP_sha512 },
+ { NID_md5_sha1, EVP_md5_sha1 },
+ { NID_dsaWithSHA, EVP_sha1 },
+ { NID_dsaWithSHA1, EVP_sha1 },
+ { NID_ecdsa_with_SHA1, EVP_sha1 },
+ { NID_md5WithRSAEncryption, EVP_md5 },
+ { NID_sha1WithRSAEncryption, EVP_sha1 },
+ { NID_sha224WithRSAEncryption, EVP_sha224 },
+ { NID_sha256WithRSAEncryption, EVP_sha256 },
+ { NID_sha384WithRSAEncryption, EVP_sha384 },
+ { NID_sha512WithRSAEncryption, EVP_sha512 },
+};
+
+const EVP_MD* EVP_get_digestbynid(int nid) {
+ unsigned i;
+
+ for (i = 0; i < sizeof(nid_to_digest_mapping) / sizeof(struct nid_to_digest);
+ i++) {
+ if (nid_to_digest_mapping[i].nid == nid) {
+ return nid_to_digest_mapping[i].md_func();
+ }
+ }
+
+ return NULL;
+}
+
+const EVP_MD* EVP_get_digestbyobj(const ASN1_OBJECT *obj) {
+ return EVP_get_digestbynid(OBJ_obj2nid(obj));
+}
diff --git a/src/crypto/digest/internal.h b/src/crypto/digest/internal.h
new file mode 100644
index 0000000..94dbfaa
--- /dev/null
+++ b/src/crypto/digest/internal.h
@@ -0,0 +1,117 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 OPENSSL_HEADER_DIGEST_INTERNAL_H
+#define OPENSSL_HEADER_DIGEST_INTERNAL_H
+
+#include <openssl/base.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+struct env_md_st {
+ /* type contains a NID identifing the digest function. (For example,
+ * NID_md5.) */
+ int type;
+
+ /* md_size contains the size, in bytes, of the resulting digest. */
+ unsigned md_size;
+
+ /* flags contains the OR of |EVP_MD_FLAG_*| values. */
+ uint32_t flags;
+
+ /* init initialises the state in |ctx->md_data|. It returns one on success
+ * and zero otherwise. */
+ int (*init)(EVP_MD_CTX *ctx);
+
+ /* update hashes |len| bytes of |data| into the state in |ctx->md_data|. */
+ int (*update)(EVP_MD_CTX *ctx, const void *data, size_t count);
+
+ /* final completes the hash and writes |md_size| bytes of digest to |out|. */
+ int (*final)(EVP_MD_CTX *ctx, uint8_t *out);
+
+ /* block_size contains the hash's native block size. */
+ unsigned block_size;
+
+ /* ctx_size contains the size, in bytes, of the state of the hash function. */
+ unsigned ctx_size;
+};
+
+/* evp_md_pctx_ops contains function pointers to allow the |pctx| member of
+ * |EVP_MD_CTX| to be manipulated without breaking laying by calling EVP
+ * functions. */
+struct evp_md_pctx_ops {
+ /* free is called when an |EVP_MD_CTX| is being freed and the |pctx| also
+ * needs to be freed. */
+ void (*free) (EVP_PKEY_CTX *pctx);
+
+ /* dup is called when an |EVP_MD_CTX| is copied and so the |pctx| also needs
+ * to be copied. */
+ EVP_PKEY_CTX* (*dup) (EVP_PKEY_CTX *pctx);
+
+ /* begin_digest is called when a new digest operation is started. It returns
+ * one on success and zero otherwise. */
+ int (*begin_digest) (EVP_MD_CTX *ctx);
+};
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_DIGEST_INTERNAL */
diff --git a/src/crypto/digest/md32_common.h b/src/crypto/digest/md32_common.h
new file mode 100644
index 0000000..a4ce355
--- /dev/null
+++ b/src/crypto/digest/md32_common.h
@@ -0,0 +1,370 @@
+/* ====================================================================
+ * 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.
+ * ==================================================================== */
+
+#ifndef OPENSSL_HEADER_MD32_COMMON_H
+#define OPENSSL_HEADER_MD32_COMMON_H
+
+#include <openssl/base.h>
+
+#include <string.h>
+
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#define asm __asm__
+
+/* 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 lest 32 bit wide, if it's wider, then
+ * HASH_LONG_LOG2 *has to* be defined along
+ * 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_LONG_LOG2 MD5_LONG_LOG2
+ * #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
+ *
+ * <appro@fy.chalmers.se>
+ */
+
+#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
+
+#ifndef HASH_UPDATE
+#error "HASH_UPDATE must be defined!"
+#endif
+#ifndef HASH_TRANSFORM
+#error "HASH_TRANSFORM must be defined!"
+#endif
+#ifndef HASH_FINAL
+#error "HASH_FINAL must be defined!"
+#endif
+
+#ifndef HASH_BLOCK_DATA_ORDER
+#error "HASH_BLOCK_DATA_ORDER must be defined!"
+#endif
+
+/*
+ * Engage compiler specific rotate intrinsic function if available.
+ */
+#undef ROTATE
+# if defined(_MSC_VER)
+# define ROTATE(a,n) _lrotl(a,n)
+# elif defined(__ICC)
+# define ROTATE(a,n) _rotl(a,n)
+# elif defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM)
+ /*
+ * Some GNU C inline assembler templates. Note that these are
+ * rotates by *constant* number of bits! But that's exactly
+ * what we need here...
+ * <appro@fy.chalmers.se>
+ */
+# if defined(OPENSSL_X86) || defined(OPENSSL_X86_64)
+# define ROTATE(a,n) ({ register unsigned int ret; \
+ asm ( \
+ "roll %1,%0" \
+ : "=r"(ret) \
+ : "I"(n), "0"((unsigned int)(a)) \
+ : "cc"); \
+ ret; \
+ })
+# endif /* OPENSSL_X86 || OPENSSL_X86_64 */
+# endif /* COMPILER */
+
+#ifndef ROTATE
+#define ROTATE(a,n) (((a)<<(n))|(((a)&0xffffffff)>>(32-(n))))
+#endif
+
+#if defined(DATA_ORDER_IS_BIG_ENDIAN)
+
+#ifndef PEDANTIC
+# if defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM)
+# if defined(OPENSSL_X86) || defined(OPENSSL_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; r; })
+# elif defined(__aarch64__)
+# if defined(__BYTE_ORDER__)
+# if defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__
+# define HOST_c2l(c,l) ({ unsigned int r; \
+ asm ("rev %w0,%w1" \
+ :"=r"(r) \
+ :"r"(*((const unsigned int *)(c))));\
+ (c)+=4; (l)=r; })
+# define HOST_l2c(l,c) ({ unsigned int r; \
+ asm ("rev %w0,%w1" \
+ :"=r"(r) \
+ :"r"((unsigned int)(l)));\
+ *((unsigned int *)(c))=r; (c)+=4; r; })
+# elif defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__==__ORDER_BIG_ENDIAN__
+# define HOST_c2l(c,l) (void)((l)=*((const unsigned int *)(c)), (c)+=4)
+# define HOST_l2c(l,c) (*((unsigned int *)(c))=(l), (c)+=4, (l))
+# endif
+# endif
+# endif
+# endif
+#endif
+
+#ifndef HOST_c2l
+#define HOST_c2l(c,l) (void)(l =(((unsigned long)(*((c)++)))<<24), \
+ l|=(((unsigned long)(*((c)++)))<<16), \
+ l|=(((unsigned long)(*((c)++)))<< 8), \
+ l|=(((unsigned long)(*((c)++))) ))
+#endif
+#ifndef HOST_l2c
+#define HOST_l2c(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), \
+ l)
+#endif
+
+#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
+
+#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64)
+ /* See comment in DATA_ORDER_IS_BIG_ENDIAN section. */
+# define HOST_c2l(c,l) (void)((l)=*((const unsigned int *)(c)), (c)+=4)
+# define HOST_l2c(l,c) (*((unsigned int *)(c))=(l), (c)+=4, l)
+#endif
+
+#ifndef HOST_c2l
+#define HOST_c2l(c,l) (void)(l =(((unsigned long)(*((c)++))) ), \
+ l|=(((unsigned long)(*((c)++)))<< 8), \
+ l|=(((unsigned long)(*((c)++)))<<16), \
+ l|=(((unsigned long)(*((c)++)))<<24))
+#endif
+#ifndef HOST_l2c
+#define HOST_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), \
+ l)
+#endif
+
+#endif
+
+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 <weidai@eskimo.com> 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;
+ }
+
+
+void HASH_TRANSFORM (HASH_CTX *c, const unsigned char *data)
+ {
+ HASH_BLOCK_DATA_ORDER (c,data,1);
+ }
+
+
+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)
+ (void)HOST_l2c(c->Nh,p);
+ (void)HOST_l2c(c->Nl,p);
+#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
+ (void)HOST_l2c(c->Nl,p);
+ (void)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;
+ }
+
+#ifndef MD32_REG_T
+#define MD32_REG_T int
+#endif
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_MD32_COMMON_H */
diff --git a/src/crypto/directory.h b/src/crypto/directory.h
new file mode 100644
index 0000000..29123ea
--- /dev/null
+++ b/src/crypto/directory.h
@@ -0,0 +1,66 @@
+/* Copied from Richard Levitte's (richard@levitte.org) LP library. All
+ * symbol names have been changed, with permission from the author. */
+
+/* $LP: LPlib/source/LPdir.h,v 1.1 2004/06/14 08:56:04 _cvs_levitte Exp $ */
+/*
+ * Copyright (c) 2004, Richard Levitte <richard@levitte.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef OPENSSL_HEADER_DIRECTORY_H
+#define OPENSSL_HEADER_DIRECTORY_H
+
+#include <openssl/base.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* Directory functions abstract the O/S specific operations for opening and
+ * reading directories in the filesystem. */
+
+
+/* OPENSSL_dir_context_st is an opaque structure that represents an open
+ * directory and a position in that directory. */
+typedef struct OPENSSL_dir_context_st OPENSSL_DIR_CTX;
+
+/* OPENSSL_DIR_read reads a single filename from |ctx|. On the first call,
+ * |directory| must be given and |*ctx| must be NULL. Subsequent calls with the
+ * same |*ctx| will return subsequent file names until it returns NULL to
+ * indicate EOF. The strings returned reference a buffer internal to the
+ * |OPENSSL_DIR_CTX| and will be overridden by subsequent calls. */
+OPENSSL_EXPORT const char *OPENSSL_DIR_read(OPENSSL_DIR_CTX **ctx,
+ const char *directory);
+
+/* OPENSSL_DIR_end closes |*ctx|. It returns one on success and zero on
+ * error. */
+OPENSSL_EXPORT int OPENSSL_DIR_end(OPENSSL_DIR_CTX **ctx);
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_DIRECTORY_H */
diff --git a/src/crypto/directory_posix.c b/src/crypto/directory_posix.c
new file mode 100644
index 0000000..c16701d
--- /dev/null
+++ b/src/crypto/directory_posix.c
@@ -0,0 +1,107 @@
+/* $LP: LPlib/source/LPdir_unix.c,v 1.11 2004/09/23 22:07:22 _cvs_levitte Exp $ */
+/*
+ * Copyright (c) 2004, Richard Levitte <richard@levitte.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
+
+#if !defined(_POSIX_C_SOURCE)
+#define _POSIX_C_SOURCE 201409 /* for readdir_r */
+#endif
+
+#include "directory.h"
+
+
+#if !defined(OPENSSL_WINDOWS)
+
+#include <dirent.h>
+#include <errno.h>
+#include <string.h>
+
+#if defined(OPENSSL_PNACL)
+/* pnacl doesn't include readdir_r! So we do the best we can. */
+int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result) {
+ errno = 0;
+ *result = readdir(dirp);
+ if (*result != NULL) {
+ return 0;
+ }
+ if (errno) {
+ return 1;
+ }
+ return 0;
+}
+#endif
+
+struct OPENSSL_dir_context_st {
+ DIR *dir;
+ struct dirent dirent;
+};
+
+const char *OPENSSL_DIR_read(OPENSSL_DIR_CTX **ctx, const char *directory) {
+ struct dirent *dirent;
+
+ if (ctx == NULL || directory == NULL) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ errno = 0;
+ if (*ctx == NULL) {
+ *ctx = malloc(sizeof(OPENSSL_DIR_CTX));
+ if (*ctx == NULL) {
+ errno = ENOMEM;
+ return 0;
+ }
+ memset(*ctx, 0, sizeof(OPENSSL_DIR_CTX));
+
+ (*ctx)->dir = opendir(directory);
+ if ((*ctx)->dir == NULL) {
+ int save_errno = errno; /* Probably not needed, but I'm paranoid */
+ free(*ctx);
+ *ctx = NULL;
+ errno = save_errno;
+ return 0;
+ }
+ }
+
+ if (readdir_r((*ctx)->dir, &(*ctx)->dirent, &dirent) != 0 ||
+ dirent == NULL) {
+ return 0;
+ }
+
+ return (*ctx)->dirent.d_name;
+}
+
+int OPENSSL_DIR_end(OPENSSL_DIR_CTX **ctx) {
+ if (ctx != NULL && *ctx != NULL) {
+ int r = closedir((*ctx)->dir);
+ free(*ctx);
+ *ctx = NULL;
+ return r == 0;
+ }
+
+ errno = EINVAL;
+ return 0;
+}
+
+#endif /* !OPENSSL_WINDOWS */
diff --git a/src/crypto/directory_win.c b/src/crypto/directory_win.c
new file mode 100644
index 0000000..2e4600f
--- /dev/null
+++ b/src/crypto/directory_win.c
@@ -0,0 +1,141 @@
+/* $LP: LPlib/source/LPdir_win.c,v 1.10 2004/08/26 13:36:05 _cvs_levitte Exp $ */
+/*
+ * Copyright (c) 2004, Richard Levitte <richard@levitte.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "directory.h"
+
+
+#if defined(OPENSSL_WINDOWS)
+
+#pragma warning(push, 3)
+#include <windows.h>
+#pragma warning(pop)
+#include <errno.h>
+#include <string.h>
+#include <tchar.h>
+
+#ifndef NAME_MAX
+#define NAME_MAX 255
+#endif
+
+struct OPENSSL_dir_context_st {
+ WIN32_FIND_DATA ctx;
+ HANDLE handle;
+ char entry_name[NAME_MAX + 1];
+};
+
+const char *OPENSSL_DIR_read(OPENSSL_DIR_CTX **ctx, const char *directory) {
+ if (ctx == NULL || directory == NULL) {
+ errno = EINVAL;
+ return 0;
+ }
+
+ errno = 0;
+ if (*ctx == NULL) {
+ *ctx = malloc(sizeof(OPENSSL_DIR_CTX));
+ if (*ctx == NULL) {
+ errno = ENOMEM;
+ return 0;
+ }
+ memset(*ctx, 0, sizeof(OPENSSL_DIR_CTX));
+
+ if (sizeof(TCHAR) != sizeof(char)) {
+ TCHAR *wdir = NULL;
+ /* len_0 denotes string length *with* trailing 0 */
+ size_t index = 0, len_0 = strlen(directory) + 1;
+
+ wdir = (TCHAR *)malloc(len_0 * sizeof(TCHAR));
+ if (wdir == NULL) {
+ free(*ctx);
+ *ctx = NULL;
+ errno = ENOMEM;
+ return 0;
+ }
+
+ if (!MultiByteToWideChar(CP_ACP, 0, directory, len_0, (WCHAR *)wdir,
+ len_0)) {
+ for (index = 0; index < len_0; index++) {
+ wdir[index] = (TCHAR)directory[index];
+ }
+ }
+
+ (*ctx)->handle = FindFirstFile(wdir, &(*ctx)->ctx);
+
+ free(wdir);
+ } else {
+ (*ctx)->handle = FindFirstFile((TCHAR *)directory, &(*ctx)->ctx);
+ }
+
+ if ((*ctx)->handle == INVALID_HANDLE_VALUE) {
+ free(*ctx);
+ *ctx = NULL;
+ errno = EINVAL;
+ return 0;
+ }
+ } else {
+ if (FindNextFile((*ctx)->handle, &(*ctx)->ctx) == FALSE) {
+ return 0;
+ }
+ }
+
+ if (sizeof(TCHAR) != sizeof(char)) {
+ TCHAR *wdir = (*ctx)->ctx.cFileName;
+ size_t index, len_0 = 0;
+
+ while (wdir[len_0] && len_0 < (sizeof((*ctx)->entry_name) - 1)) {
+ len_0++;
+ }
+ len_0++;
+
+ if (!WideCharToMultiByte(CP_ACP, 0, (WCHAR *)wdir, len_0,
+ (*ctx)->entry_name, sizeof((*ctx)->entry_name),
+ NULL, 0)) {
+ for (index = 0; index < len_0; index++) {
+ (*ctx)->entry_name[index] = (char)wdir[index];
+ }
+ }
+ } else {
+ strncpy((*ctx)->entry_name, (const char *)(*ctx)->ctx.cFileName,
+ sizeof((*ctx)->entry_name) - 1);
+ }
+
+ (*ctx)->entry_name[sizeof((*ctx)->entry_name) - 1] = '\0';
+
+ return (*ctx)->entry_name;
+}
+
+int OPENSSL_DIR_end(OPENSSL_DIR_CTX **ctx) {
+ if (ctx != NULL && *ctx != NULL) {
+ FindClose((*ctx)->handle);
+ free(*ctx);
+ *ctx = NULL;
+ return 1;
+ }
+ errno = EINVAL;
+ return 0;
+}
+
+#endif /* OPENSSL_WINDOWS */
diff --git a/src/crypto/dsa/CMakeLists.txt b/src/crypto/dsa/CMakeLists.txt
new file mode 100644
index 0000000..fbc053e
--- /dev/null
+++ b/src/crypto/dsa/CMakeLists.txt
@@ -0,0 +1,20 @@
+include_directories(. .. ../../include)
+
+add_library(
+ dsa
+
+ OBJECT
+
+ dsa.c
+ dsa_impl.c
+ dsa_asn1.c
+ dsa_error.c
+)
+
+add_executable(
+ dsa_test
+
+ dsa_test.c
+)
+
+target_link_libraries(dsa_test crypto)
diff --git a/src/crypto/dsa/dsa.c b/src/crypto/dsa/dsa.c
new file mode 100644
index 0000000..8816b63
--- /dev/null
+++ b/src/crypto/dsa/dsa.c
@@ -0,0 +1,354 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <schoch@sheba.arc.nasa.gov>. */
+
+#include <openssl/dsa.h>
+
+#include <string.h>
+
+#include <openssl/asn1.h>
+#include <openssl/dh.h>
+#include <openssl/engine.h>
+#include <openssl/err.h>
+#include <openssl/ex_data.h>
+#include <openssl/mem.h>
+
+#include "internal.h"
+
+
+extern const DSA_METHOD DSA_default_method;
+
+DSA *DSA_new(void) { return DSA_new_method(NULL); }
+
+DSA *DSA_new_method(const ENGINE *engine) {
+ DSA *dsa = (DSA *)OPENSSL_malloc(sizeof(DSA));
+ if (dsa == NULL) {
+ OPENSSL_PUT_ERROR(DSA, DSA_new_method, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ memset(dsa, 0, sizeof(DSA));
+
+ if (engine) {
+ dsa->meth = ENGINE_get_DSA_method(engine);
+ }
+
+ if (dsa->meth == NULL) {
+ dsa->meth = (DSA_METHOD*) &DSA_default_method;
+ }
+ METHOD_ref(dsa->meth);
+
+ dsa->write_params = 1;
+ dsa->references = 1;
+
+ if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_DSA, dsa, &dsa->ex_data)) {
+ METHOD_unref(dsa->meth);
+ OPENSSL_free(dsa);
+ return NULL;
+ }
+
+ if (dsa->meth->init && !dsa->meth->init(dsa)) {
+ CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DSA, dsa, &dsa->ex_data);
+ METHOD_unref(dsa->meth);
+ OPENSSL_free(dsa);
+ return NULL;
+ }
+
+ return dsa;
+}
+
+void DSA_free(DSA *dsa) {
+ if (dsa == NULL) {
+ return;
+ }
+
+ if (CRYPTO_add(&dsa->references, -1, CRYPTO_LOCK_DSA) > 0) {
+ return;
+ }
+
+ if (dsa->meth->finish) {
+ dsa->meth->finish(dsa);
+ }
+ METHOD_unref(dsa->meth);
+
+ CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DSA, dsa, &dsa->ex_data);
+
+ if (dsa->p != NULL)
+ BN_clear_free(dsa->p);
+ if (dsa->q != NULL)
+ BN_clear_free(dsa->q);
+ if (dsa->g != NULL)
+ BN_clear_free(dsa->g);
+ if (dsa->pub_key != NULL)
+ BN_clear_free(dsa->pub_key);
+ if (dsa->priv_key != NULL)
+ BN_clear_free(dsa->priv_key);
+ if (dsa->kinv != NULL)
+ BN_clear_free(dsa->kinv);
+ if (dsa->r != NULL)
+ BN_clear_free(dsa->r);
+ OPENSSL_free(dsa);
+}
+
+int DSA_up_ref(DSA *dsa) {
+ CRYPTO_add(&dsa->references, 1, CRYPTO_LOCK_DSA);
+ return 1;
+}
+
+int DSA_generate_parameters_ex(DSA *dsa, unsigned bits, const uint8_t *seed_in,
+ size_t seed_len, int *out_counter,
+ unsigned long *out_h, BN_GENCB *cb) {
+ if (dsa->meth->generate_parameters) {
+ return dsa->meth->generate_parameters(dsa, bits, seed_in, seed_len,
+ out_counter, out_h, cb);
+ }
+ return DSA_default_method.generate_parameters(dsa, bits, seed_in, seed_len,
+ out_counter, out_h, cb);
+}
+
+int DSA_generate_key(DSA *dsa) {
+ if (dsa->meth->keygen) {
+ return dsa->meth->keygen(dsa);
+ }
+ return DSA_default_method.keygen(dsa);
+}
+
+DSA_SIG *DSA_SIG_new(void) {
+ DSA_SIG *sig;
+ sig = OPENSSL_malloc(sizeof(DSA_SIG));
+ if (!sig) {
+ return NULL;
+ }
+ sig->r = NULL;
+ sig->s = NULL;
+ return sig;
+}
+
+void DSA_SIG_free(DSA_SIG *sig) {
+ if (!sig) {
+ return;
+ }
+
+ if (sig->r) {
+ BN_free(sig->r);
+ }
+ if (sig->s) {
+ BN_free(sig->s);
+ }
+ OPENSSL_free(sig);
+}
+
+DSA_SIG *DSA_do_sign(const uint8_t *digest, size_t digest_len, DSA *dsa) {
+ if (dsa->meth->sign) {
+ return dsa->meth->sign(digest, digest_len, dsa);
+ }
+ return DSA_default_method.sign(digest, digest_len, dsa);
+}
+
+int DSA_do_verify(const uint8_t *digest, size_t digest_len, DSA_SIG *sig,
+ const DSA *dsa) {
+ int valid;
+ if (!DSA_do_check_signature(&valid, digest, digest_len, sig, dsa)) {
+ return -1;
+ }
+ return valid;
+}
+
+int DSA_do_check_signature(int *out_valid, const uint8_t *digest,
+ size_t digest_len, DSA_SIG *sig, const DSA *dsa) {
+ if (dsa->meth->verify) {
+ return dsa->meth->verify(out_valid, digest, digest_len, sig, dsa);
+ }
+
+ return DSA_default_method.verify(out_valid, digest, digest_len, sig, dsa);
+}
+
+int DSA_sign(int type, const uint8_t *digest, size_t digest_len,
+ uint8_t *out_sig, unsigned int *out_siglen, DSA *dsa) {
+ DSA_SIG *s;
+
+ s = DSA_do_sign(digest, digest_len, dsa);
+ if (s == NULL) {
+ *out_siglen = 0;
+ return 0;
+ }
+
+ *out_siglen = i2d_DSA_SIG(s, &out_sig);
+ DSA_SIG_free(s);
+ return 1;
+}
+
+int DSA_verify(int type, const uint8_t *digest, size_t digest_len,
+ const uint8_t *sig, size_t sig_len, const DSA *dsa) {
+ int valid;
+ if (!DSA_check_signature(&valid, digest, digest_len, sig, sig_len, dsa)) {
+ return -1;
+ }
+ return valid;
+}
+
+int DSA_check_signature(int *out_valid, const uint8_t *digest,
+ size_t digest_len, const uint8_t *sig, size_t sig_len,
+ const DSA *dsa) {
+ DSA_SIG *s = NULL;
+ int ret = 0;
+ uint8_t *der = NULL;
+
+ s = DSA_SIG_new();
+ if (s == NULL) {
+ goto err;
+ }
+
+ const uint8_t *sigp = sig;
+ if (d2i_DSA_SIG(&s, &sigp, sig_len) == NULL || sigp != sig + sig_len) {
+ goto err;
+ }
+
+ /* Ensure that the signature uses DER and doesn't have trailing garbage. */
+ int der_len = i2d_DSA_SIG(s, &der);
+ if (der_len < 0 || (size_t)der_len != sig_len || memcmp(sig, der, sig_len)) {
+ goto err;
+ }
+
+ ret = DSA_do_check_signature(out_valid, digest, digest_len, s, dsa);
+
+err:
+ if (der != NULL) {
+ OPENSSL_free(der);
+ }
+ if (s) {
+ DSA_SIG_free(s);
+ }
+ return ret;
+}
+
+int DSA_size(const DSA *dsa) {
+ int ret, i;
+ ASN1_INTEGER bs;
+ unsigned char buf[4]; /* 4 bytes looks really small.
+ However, i2d_ASN1_INTEGER() will not look
+ beyond the first byte, as long as the second
+ parameter is NULL. */
+
+ i = BN_num_bits(dsa->q);
+ bs.length = (i + 7) / 8;
+ bs.data = buf;
+ bs.type = V_ASN1_INTEGER;
+ /* If the top bit is set the asn1 encoding is 1 larger. */
+ buf[0] = 0xff;
+
+ i = i2d_ASN1_INTEGER(&bs, NULL);
+ i += i; /* r and s */
+ ret = ASN1_object_size(1, i, V_ASN1_SEQUENCE);
+ return ret;
+}
+
+int DSA_sign_setup(const DSA *dsa, BN_CTX *ctx, BIGNUM **out_kinv,
+ BIGNUM **out_r) {
+ if (dsa->meth->sign_setup) {
+ return dsa->meth->sign_setup(dsa, ctx, out_kinv, out_r, NULL, 0);
+ }
+
+ return DSA_default_method.sign_setup(dsa, ctx, out_kinv, out_r, NULL, 0);
+}
+
+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);
+}
+
+int DSA_set_ex_data(DSA *d, int idx, void *arg) {
+ return CRYPTO_set_ex_data(&d->ex_data, idx, arg);
+}
+
+void *DSA_get_ex_data(const DSA *d, int idx) {
+ return CRYPTO_get_ex_data(&d->ex_data, idx);
+}
+
+DH *DSA_dup_DH(const DSA *r) {
+ DH *ret = NULL;
+
+ if (r == NULL) {
+ goto err;
+ }
+ ret = DH_new();
+ if (ret == NULL) {
+ goto err;
+ }
+ if (r->q != NULL) {
+ ret->priv_length = BN_num_bits(r->q);
+ if ((ret->q = BN_dup(r->q)) == NULL) {
+ goto err;
+ }
+ }
+ if ((r->p != NULL && (ret->p = BN_dup(r->p)) == NULL) ||
+ (r->g != NULL && (ret->g = BN_dup(r->g)) == NULL) ||
+ (r->pub_key != NULL && (ret->pub_key = BN_dup(r->pub_key)) == NULL) ||
+ (r->priv_key != NULL && (ret->priv_key = BN_dup(r->priv_key)) == NULL)) {
+ goto err;
+ }
+
+ return ret;
+
+err:
+ if (ret != NULL) {
+ DH_free(ret);
+ }
+ return NULL;
+}
diff --git a/src/crypto/dsa/dsa_asn1.c b/src/crypto/dsa/dsa_asn1.c
new file mode 100644
index 0000000..933fba7
--- /dev/null
+++ b/src/crypto/dsa/dsa_asn1.c
@@ -0,0 +1,150 @@
+/* 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 <openssl/dsa.h>
+
+#include <string.h>
+
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+
+#include "internal.h"
+
+
+static int dsa_sig_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
+ void *exarg) {
+ if (operation != ASN1_OP_NEW_PRE) {
+ return 1;
+ }
+
+ DSA_SIG *sig;
+ sig = OPENSSL_malloc(sizeof(DSA_SIG));
+ if (!sig) {
+ OPENSSL_PUT_ERROR(DSA, dsa_sig_cb, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ memset(sig, 0, sizeof(DSA_SIG));
+ *pval = (ASN1_VALUE *)sig;
+ return 2;
+}
+
+ASN1_SEQUENCE_cb(DSA_SIG, dsa_sig_cb) = {
+ ASN1_SIMPLE(DSA_SIG, r, CBIGNUM),
+ ASN1_SIMPLE(DSA_SIG, s, CBIGNUM)} ASN1_SEQUENCE_END_cb(DSA_SIG, DSA_SIG);
+
+IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(DSA_SIG, DSA_SIG, DSA_SIG);
+
+
+static int dsa_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
+ void *exarg) {
+ switch (operation) {
+ case ASN1_OP_NEW_PRE:
+ *pval = (ASN1_VALUE *)DSA_new();
+ if (*pval) {
+ return 2;
+ }
+ return 0;
+
+ case ASN1_OP_FREE_PRE:
+ DSA_free((DSA *)*pval);
+ *pval = NULL;
+ return 2;
+
+ default:
+ return 1;
+ }
+}
+
+ASN1_SEQUENCE_cb(DSAPrivateKey, dsa_cb) = {
+ ASN1_SIMPLE(DSA, version, LONG),
+ ASN1_SIMPLE(DSA, p, BIGNUM),
+ ASN1_SIMPLE(DSA, q, BIGNUM),
+ ASN1_SIMPLE(DSA, g, BIGNUM),
+ ASN1_SIMPLE(DSA, pub_key, BIGNUM),
+ ASN1_SIMPLE(DSA, priv_key, BIGNUM)} ASN1_SEQUENCE_END_cb(DSA,
+ DSAPrivateKey);
+
+IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(DSA, DSAPrivateKey, DSAPrivateKey);
+
+ASN1_SEQUENCE_cb(DSAparams, dsa_cb) = {
+ ASN1_SIMPLE(DSA, p, BIGNUM), ASN1_SIMPLE(DSA, q, BIGNUM),
+ ASN1_SIMPLE(DSA, g, BIGNUM), } ASN1_SEQUENCE_END_cb(DSA, DSAparams);
+
+IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(DSA, DSAparams, DSAparams);
+
+
+/* DSA public key is a bit trickier... its effectively a CHOICE type decided by
+ * a field called write_params which can either write out just the public key
+ * as an INTEGER or the parameters and public key in a SEQUENCE. */
+
+ASN1_SEQUENCE(dsa_pub_internal) = {
+ ASN1_SIMPLE(DSA, pub_key, BIGNUM),
+ ASN1_SIMPLE(DSA, p, BIGNUM),
+ ASN1_SIMPLE(DSA, q, BIGNUM),
+ ASN1_SIMPLE(DSA, g, BIGNUM)
+} ASN1_SEQUENCE_END_name(DSA, dsa_pub_internal);
+
+ASN1_CHOICE_cb(DSAPublicKey, dsa_cb) = {
+ ASN1_SIMPLE(DSA, pub_key, BIGNUM),
+ ASN1_EX_COMBINE(0, 0, dsa_pub_internal)
+} ASN1_CHOICE_END_cb(DSA, DSAPublicKey, write_params);
+
+IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(DSA, DSAPublicKey, DSAPublicKey);
+
+DSA *DSAparams_dup(const DSA *dsa) {
+ return ASN1_item_dup(ASN1_ITEM_rptr(DSAparams), (DSA*) dsa);
+}
diff --git a/src/crypto/dsa/dsa_error.c b/src/crypto/dsa/dsa_error.c
new file mode 100644
index 0000000..5a83908
--- /dev/null
+++ b/src/crypto/dsa/dsa_error.c
@@ -0,0 +1,30 @@
+/* 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 <openssl/err.h>
+
+#include <openssl/dsa.h>
+
+const ERR_STRING_DATA DSA_error_string_data[] = {
+ {ERR_PACK(ERR_LIB_DSA, DSA_F_DSA_new_method, 0), "DSA_new_method"},
+ {ERR_PACK(ERR_LIB_DSA, DSA_F_dsa_sig_cb, 0), "dsa_sig_cb"},
+ {ERR_PACK(ERR_LIB_DSA, DSA_F_sign, 0), "sign"},
+ {ERR_PACK(ERR_LIB_DSA, DSA_F_sign_setup, 0), "sign_setup"},
+ {ERR_PACK(ERR_LIB_DSA, DSA_F_verify, 0), "verify"},
+ {ERR_PACK(ERR_LIB_DSA, 0, DSA_R_BAD_Q_VALUE), "BAD_Q_VALUE"},
+ {ERR_PACK(ERR_LIB_DSA, 0, DSA_R_MISSING_PARAMETERS), "MISSING_PARAMETERS"},
+ {ERR_PACK(ERR_LIB_DSA, 0, DSA_R_MODULUS_TOO_LARGE), "MODULUS_TOO_LARGE"},
+ {ERR_PACK(ERR_LIB_DSA, 0, DSA_R_NEED_NEW_SETUP_VALUES), "NEED_NEW_SETUP_VALUES"},
+ {0, NULL},
+};
diff --git a/src/crypto/dsa/dsa_impl.c b/src/crypto/dsa/dsa_impl.c
new file mode 100644
index 0000000..6719758
--- /dev/null
+++ b/src/crypto/dsa/dsa_impl.c
@@ -0,0 +1,762 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <schoch@sheba.arc.nasa.gov>. */
+
+#include <openssl/dsa.h>
+
+#include <string.h>
+
+#include <openssl/bn.h>
+#include <openssl/digest.h>
+#include <openssl/err.h>
+#include <openssl/rand.h>
+#include <openssl/sha.h>
+
+#include "internal.h"
+
+#define OPENSSL_DSA_MAX_MODULUS_BITS 10000
+
+/* Primality test according to FIPS PUB 186[-1], Appendix 2.1: 50 rounds of
+ * Rabin-Miller */
+#define DSS_prime_checks 50
+
+static int sign_setup(const DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp,
+ BIGNUM **rp, const uint8_t *digest, size_t digest_len) {
+ BN_CTX *ctx;
+ BIGNUM k, kq, *K, *kinv = NULL, *r = NULL;
+ int ret = 0;
+
+ if (!dsa->p || !dsa->q || !dsa->g) {
+ OPENSSL_PUT_ERROR(DSA, sign_setup, DSA_R_MISSING_PARAMETERS);
+ return 0;
+ }
+
+ BN_init(&k);
+ BN_init(&kq);
+
+ ctx = ctx_in;
+ if (ctx == NULL) {
+ ctx = BN_CTX_new();
+ if (ctx == NULL) {
+ goto err;
+ }
+ }
+
+ r = BN_new();
+ if (r == NULL) {
+ goto err;
+ }
+
+ /* Get random k */
+ do {
+ /* If possible, we'll include the private key and message digest in the k
+ * generation. The |digest| argument is only empty if |DSA_sign_setup| is
+ * being used. */
+ int ok;
+
+ if (digest_len > 0) {
+ ok = BN_generate_dsa_nonce(&k, dsa->q, dsa->priv_key, digest, digest_len,
+ ctx);
+ } else {
+ ok = BN_rand_range(&k, dsa->q);
+ }
+ if (!ok) {
+ goto err;
+ }
+ } while (BN_is_zero(&k));
+
+ BN_set_flags(&k, BN_FLG_CONSTTIME);
+
+ if (!BN_MONT_CTX_set_locked((BN_MONT_CTX **)&dsa->method_mont_p,
+ CRYPTO_LOCK_DSA, dsa->p, ctx)) {
+ goto err;
+ }
+
+ /* Compute r = (g^k mod p) mod q */
+ if (!BN_copy(&kq, &k))
+ goto err;
+
+ /* We do not want timing information to leak the length of k,
+ * so we compute g^k using an equivalent exponent of fixed length.
+ *
+ * (This is a kludge that we need because the BN_mod_exp_mont()
+ * does not let us specify the desired timing behaviour.) */
+
+ if (!BN_add(&kq, &kq, dsa->q))
+ goto err;
+ if (BN_num_bits(&kq) <= BN_num_bits(dsa->q)) {
+ if (!BN_add(&kq, &kq, dsa->q))
+ goto err;
+ }
+
+ K = &kq;
+
+ if (!BN_mod_exp_mont(r, dsa->g, K, dsa->p, ctx, dsa->method_mont_p)) {
+ goto err;
+ }
+ if (!BN_mod(r, r, dsa->q, ctx)) {
+ goto err;
+ }
+
+ /* Compute part of 's = inv(k) (m + xr) mod q' */
+ kinv = BN_mod_inverse(NULL, &k, dsa->q, ctx);
+ if (kinv == NULL) {
+ goto err;
+ }
+
+ if (*kinvp != NULL) {
+ BN_clear_free(*kinvp);
+ }
+ *kinvp = kinv;
+ kinv = NULL;
+ if (*rp != NULL) {
+ BN_clear_free(*rp);
+ }
+ *rp = r;
+ ret = 1;
+
+err:
+ if (!ret) {
+ OPENSSL_PUT_ERROR(DSA, sign_setup, ERR_R_BN_LIB);
+ if (r != NULL) {
+ BN_clear_free(r);
+ }
+ }
+
+ if (ctx_in == NULL) {
+ BN_CTX_free(ctx);
+ }
+ BN_clear_free(&k);
+ BN_clear_free(&kq);
+ return ret;
+}
+
+static DSA_SIG *sign(const uint8_t *digest, size_t digest_len, DSA *dsa) {
+ BIGNUM *kinv = NULL, *r = NULL, *s = NULL;
+ BIGNUM m;
+ BIGNUM xr;
+ BN_CTX *ctx = NULL;
+ int reason = ERR_R_BN_LIB;
+ DSA_SIG *ret = NULL;
+ int noredo = 0;
+
+ BN_init(&m);
+ BN_init(&xr);
+
+ if (!dsa->p || !dsa->q || !dsa->g) {
+ reason = DSA_R_MISSING_PARAMETERS;
+ goto err;
+ }
+
+ s = BN_new();
+ if (s == NULL) {
+ goto err;
+ }
+ ctx = BN_CTX_new();
+ if (ctx == 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;
+ }
+
+ if (digest_len > BN_num_bytes(dsa->q)) {
+ /* if the digest length is greater than the size of q use the
+ * BN_num_bits(dsa->q) leftmost bits of the digest, see
+ * fips 186-3, 4.2 */
+ digest_len = BN_num_bytes(dsa->q);
+ }
+
+ if (BN_bin2bn(digest, digest_len, &m) == NULL) {
+ goto err;
+ }
+
+ /* Compute s = inv(k) (m + xr) mod q */
+ if (!BN_mod_mul(&xr, dsa->priv_key, r, dsa->q, ctx)) {
+ goto err; /* s = xr */
+ }
+ if (!BN_add(s, &xr, &m)) {
+ goto err; /* s = m + xr */
+ }
+ if (BN_cmp(s, dsa->q) > 0) {
+ if (!BN_sub(s, s, dsa->q)) {
+ goto err;
+ }
+ }
+ if (!BN_mod_mul(s, s, kinv, dsa->q, ctx)) {
+ goto err;
+ }
+
+ ret = DSA_SIG_new();
+ if (ret == NULL) {
+ 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;
+ }
+ goto redo;
+ }
+ ret->r = r;
+ ret->s = s;
+
+err:
+ if (!ret) {
+ OPENSSL_PUT_ERROR(DSA, sign, reason);
+ BN_free(r);
+ BN_free(s);
+ }
+ if (ctx != NULL) {
+ BN_CTX_free(ctx);
+ }
+ BN_clear_free(&m);
+ BN_clear_free(&xr);
+ if (kinv != NULL) {
+ /* dsa->kinv is NULL now if we used it */
+ BN_clear_free(kinv);
+ }
+
+ return ret;
+}
+
+static int verify(int *out_valid, const uint8_t *dgst, size_t digest_len,
+ DSA_SIG *sig, const DSA *dsa) {
+ BN_CTX *ctx;
+ BIGNUM u1, u2, t1;
+ BN_MONT_CTX *mont = NULL;
+ int ret = 0;
+ unsigned i;
+
+ *out_valid = 0;
+
+ if (!dsa->p || !dsa->q || !dsa->g) {
+ OPENSSL_PUT_ERROR(DSA, verify, DSA_R_MISSING_PARAMETERS);
+ return 0;
+ }
+
+ i = BN_num_bits(dsa->q);
+ /* fips 186-3 allows only different sizes for q */
+ if (i != 160 && i != 224 && i != 256) {
+ OPENSSL_PUT_ERROR(DSA, verify, DSA_R_BAD_Q_VALUE);
+ return 0;
+ }
+
+ if (BN_num_bits(dsa->p) > OPENSSL_DSA_MAX_MODULUS_BITS) {
+ OPENSSL_PUT_ERROR(DSA, verify, DSA_R_MODULUS_TOO_LARGE);
+ return 0;
+ }
+
+ BN_init(&u1);
+ BN_init(&u2);
+ BN_init(&t1);
+
+ ctx = BN_CTX_new();
+ if (ctx == NULL) {
+ goto err;
+ }
+
+ if (BN_is_zero(sig->r) || BN_is_negative(sig->r) ||
+ BN_ucmp(sig->r, dsa->q) >= 0) {
+ ret = 1;
+ goto err;
+ }
+ if (BN_is_zero(sig->s) || BN_is_negative(sig->s) ||
+ BN_ucmp(sig->s, dsa->q) >= 0) {
+ ret = 1;
+ goto err;
+ }
+
+ /* Calculate W = inv(S) mod Q
+ * save W in u2 */
+ if (BN_mod_inverse(&u2, sig->s, dsa->q, ctx) == NULL) {
+ goto err;
+ }
+
+ /* save M in u1 */
+ if (digest_len > (i >> 3)) {
+ /* if the digest length is greater than the size of q use the
+ * BN_num_bits(dsa->q) leftmost bits of the digest, see
+ * fips 186-3, 4.2 */
+ digest_len = (i >> 3);
+ }
+
+ if (BN_bin2bn(dgst, digest_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;
+ }
+
+ mont = BN_MONT_CTX_set_locked((BN_MONT_CTX **)&dsa->method_mont_p,
+ CRYPTO_LOCK_DSA, dsa->p, ctx);
+ if (!mont) {
+ goto err;
+ }
+
+ if (!BN_mod_exp2_mont(&t1, dsa->g, &u1, dsa->pub_key, &u2, dsa->p, ctx, mont)) {
+ goto err;
+ }
+
+ /* BN_copy(&u1,&t1); */
+ /* let u1 = u1 mod q */
+ if (!BN_mod(&u1, &t1, dsa->q, ctx)) {
+ goto err;
+ }
+
+ /* V is now in u1. If the signature is correct, it will be
+ * equal to R. */
+ *out_valid = BN_ucmp(&u1, sig->r) == 0;
+ ret = 1;
+
+err:
+ if (ret != 1) {
+ OPENSSL_PUT_ERROR(DSA, verify, ERR_R_BN_LIB);
+ }
+ if (ctx != NULL) {
+ BN_CTX_free(ctx);
+ }
+ BN_free(&u1);
+ BN_free(&u2);
+ BN_free(&t1);
+
+ return ret;
+}
+
+static int keygen(DSA *dsa) {
+ int ok = 0;
+ BN_CTX *ctx = NULL;
+ BIGNUM *pub_key = NULL, *priv_key = NULL;
+ BIGNUM prk;
+
+ ctx = BN_CTX_new();
+ if (ctx == NULL) {
+ goto err;
+ }
+
+ priv_key = dsa->priv_key;
+ if (priv_key == NULL) {
+ priv_key = BN_new();
+ if (priv_key == NULL) {
+ goto err;
+ }
+ }
+
+ do {
+ if (!BN_rand_range(priv_key, dsa->q)) {
+ goto err;
+ }
+ } while (BN_is_zero(priv_key));
+
+ pub_key = dsa->pub_key;
+ if (pub_key == NULL) {
+ pub_key = BN_new();
+ if (pub_key == NULL) {
+ goto err;
+ }
+ }
+
+ BN_init(&prk);
+ BN_with_flags(&prk, priv_key, BN_FLG_CONSTTIME);
+
+ if (!BN_mod_exp(pub_key, dsa->g, &prk, dsa->p, ctx)) {
+ goto err;
+ }
+
+ dsa->priv_key = priv_key;
+ dsa->pub_key = pub_key;
+ ok = 1;
+
+err:
+ if (pub_key != NULL && dsa->pub_key == NULL) {
+ BN_free(pub_key);
+ }
+ if (priv_key != NULL && dsa->priv_key == NULL) {
+ BN_free(priv_key);
+ }
+ if (ctx != NULL) {
+ BN_CTX_free(ctx);
+ }
+
+ return ok;
+}
+
+static int paramgen(DSA *ret, unsigned bits, const uint8_t *seed_in,
+ size_t seed_len, 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 k, n = 0, m = 0;
+ unsigned i;
+ int counter = 0;
+ int r = 0;
+ BN_CTX *ctx = NULL;
+ unsigned int h = 2;
+ unsigned qbits, qsize;
+ const EVP_MD *evpmd;
+
+ if (bits >= 2048) {
+ qbits = 256;
+ evpmd = EVP_sha256();
+ } else {
+ qbits = 160;
+ evpmd = EVP_sha1();
+ }
+ qsize = qbits / 8;
+
+ if (qsize != SHA_DIGEST_LENGTH && qsize != SHA224_DIGEST_LENGTH &&
+ qsize != SHA256_DIGEST_LENGTH) {
+ /* invalid q size */
+ return 0;
+ }
+
+ if (bits < 512) {
+ bits = 512;
+ }
+
+ bits = (bits + 63) / 64 * 64;
+
+ /* NB: seed_len == 0 is special case: copy generated seed to
+ * seed_in if it is not NULL. */
+ if (seed_len && (seed_len < (size_t)qsize)) {
+ seed_in = NULL; /* seed buffer too small -- ignore */
+ }
+ if (seed_len > (size_t)qsize) {
+ seed_len = qsize; /* App. 2.2 of FIPS PUB 186 allows larger SEED,
+ * but our internal buffers are restricted to 160 bits*/
+ }
+ if (seed_in != NULL) {
+ memcpy(seed, seed_in, seed_len);
+ }
+
+ ctx = BN_CTX_new();
+ mont = BN_MONT_CTX_new();
+ if (ctx == NULL || mont == NULL) {
+ goto err;
+ }
+
+ BN_CTX_start(ctx);
+ r0 = BN_CTX_get(ctx);
+ g = BN_CTX_get(ctx);
+ W = BN_CTX_get(ctx);
+ q = BN_CTX_get(ctx);
+ X = BN_CTX_get(ctx);
+ c = BN_CTX_get(ctx);
+ p = BN_CTX_get(ctx);
+ test = BN_CTX_get(ctx);
+
+ if (!BN_lshift(test, BN_value_one(), bits - 1)) {
+ goto err;
+ }
+
+ for (;;) {
+ /* Find q. */
+ for (;;) {
+ int seed_is_random;
+
+ /* step 1 */
+ if (!BN_GENCB_call(cb, 0, m++)) {
+ goto err;
+ }
+
+ if (!seed_len) {
+ if (!RAND_bytes(seed, qsize)) {
+ goto err;
+ }
+ seed_is_random = 1;
+ } else {
+ seed_is_random = 0;
+ seed_len = 0; /* use random seed if 'seed_in' turns out to be bad*/
+ }
+ memcpy(buf, seed, qsize);
+ memcpy(buf2, seed, qsize);
+ /* precompute "SEED + 1" for step 7: */
+ for (i = qsize - 1; i < qsize; i--) {
+ buf[i]++;
+ if (buf[i] != 0) {
+ break;
+ }
+ }
+
+ /* step 2 */
+ if (!EVP_Digest(seed, qsize, md, NULL, evpmd, NULL) ||
+ !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) || !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 < qsize; 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) ||
+ !BN_lshift(r0, r0, (qsize << 3) * k) ||
+ !BN_add(W, W, r0)) {
+ goto err;
+ }
+ }
+
+ /* more of step 8 */
+ if (!BN_mask_bits(W, bits - 1) ||
+ !BN_copy(X, W) ||
+ !BN_add(X, X, test)) {
+ goto err;
+ }
+
+ /* step 9 */
+ if (!BN_lshift1(r0, q) ||
+ !BN_mod(c, X, r0, ctx) ||
+ !BN_sub(r0, c, BN_value_one()) ||
+ !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()) ||
+ !BN_div(r0, NULL, test, q, ctx)) {
+ goto err;
+ }
+
+ if (!BN_set_word(test, h) ||
+ !BN_MONT_CTX_set(mont, p, ctx)) {
+ goto err;
+ }
+
+ for (;;) {
+ /* g=test^r0%p */
+ if (!BN_mod_exp_mont(g, test, r0, p, ctx, mont)) {
+ goto err;
+ }
+ if (!BN_is_one(g)) {
+ break;
+ }
+ if (!BN_add(test, test, BN_value_one())) {
+ goto err;
+ }
+ h++;
+ }
+
+ if (!BN_GENCB_call(cb, 3, 1)) {
+ goto err;
+ }
+
+ ok = 1;
+
+err:
+ if (ok) {
+ if (ret->p) {
+ BN_free(ret->p);
+ }
+ if (ret->q) {
+ BN_free(ret->q);
+ }
+ if (ret->g) {
+ 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 (ctx) {
+ BN_CTX_end(ctx);
+ BN_CTX_free(ctx);
+ }
+
+ if (mont != NULL) {
+ BN_MONT_CTX_free(mont);
+ }
+
+ return ok;
+}
+
+static int finish(DSA *dsa) {
+ BN_MONT_CTX_free(dsa->method_mont_p);
+ dsa->method_mont_p = NULL;
+ return 1;
+}
+
+const struct dsa_method DSA_default_method = {
+ {
+ 0 /* references */,
+ 1 /* is_static */,
+ },
+ NULL /* app_data */,
+
+ NULL /* init */,
+ finish /* finish */,
+
+ sign,
+ sign_setup,
+ verify,
+
+ paramgen,
+ keygen,
+};
diff --git a/src/crypto/dsa/dsa_test.c b/src/crypto/dsa/dsa_test.c
new file mode 100644
index 0000000..1273638
--- /dev/null
+++ b/src/crypto/dsa/dsa_test.c
@@ -0,0 +1,338 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <schoch@sheba.arc.nasa.gov>. */
+
+#include <openssl/dsa.h>
+
+#include <string.h>
+
+#include <openssl/bio.h>
+#include <openssl/bn.h>
+#include <openssl/crypto.h>
+#include <openssl/err.h>
+
+#include "internal.h"
+
+
+static int dsa_cb(int p, int n, BN_GENCB *arg);
+
+/* The following values are taken from the updated Appendix 5 to FIPS PUB 186
+ * and also appear in Appendix 5 to FIPS PUB 186-1. */
+
+static const uint8_t seed[20] = {
+ 0xd5, 0x01, 0x4e, 0x4b, 0x60, 0xef, 0x2b, 0xa8, 0xb6, 0x21, 0x1b,
+ 0x40, 0x62, 0xba, 0x32, 0x24, 0xe0, 0x42, 0x7d, 0xd3,
+};
+
+static const uint8_t fips_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 const uint8_t fips_q[] = {
+ 0xc7, 0x73, 0x21, 0x8c, 0x73, 0x7e, 0xc8, 0xee, 0x99, 0x3b, 0x4f,
+ 0x2d, 0xed, 0x30, 0xf4, 0x8e, 0xda, 0xce, 0x91, 0x5f,
+};
+
+static const uint8_t fips_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 uint8_t fips_x[] = {
+ 0x20, 0x70, 0xb3, 0x22, 0x3d, 0xba, 0x37, 0x2f, 0xde, 0x1c, 0x0f,
+ 0xfc, 0x7b, 0x2e, 0x3b, 0x49, 0x8b, 0x26, 0x06, 0x14,
+};
+
+static const uint8_t fips_y[] = {
+ 0x19, 0x13, 0x18, 0x71, 0xd7, 0x5b, 0x16, 0x12, 0xa8, 0x19, 0xf2,
+ 0x9d, 0x78, 0xd1, 0xb0, 0xd7, 0x34, 0x6f, 0x7a, 0xa7, 0x7b, 0xb6,
+ 0x2a, 0x85, 0x9b, 0xfd, 0x6c, 0x56, 0x75, 0xda, 0x9d, 0x21, 0x2d,
+ 0x3a, 0x36, 0xef, 0x16, 0x72, 0xef, 0x66, 0x0b, 0x8c, 0x7c, 0x25,
+ 0x5c, 0xc0, 0xec, 0x74, 0x85, 0x8f, 0xba, 0x33, 0xf4, 0x4c, 0x06,
+ 0x69, 0x96, 0x30, 0xa7, 0x6b, 0x03, 0x0e, 0xe3, 0x33,
+};
+
+static const uint8_t fips_digest[] = {
+ 0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a, 0xba, 0x3e, 0x25,
+ 0x71, 0x78, 0x50, 0xc2, 0x6c, 0x9c, 0xd0, 0xd8, 0x9d,
+};
+
+/* fips_sig is a DER-encoded version of the r and s values in FIPS PUB 186-1. */
+static const uint8_t fips_sig[] = {
+ 0x30, 0x2d, 0x02, 0x15, 0x00, 0x8b, 0xac, 0x1a, 0xb6, 0x64, 0x10,
+ 0x43, 0x5c, 0xb7, 0x18, 0x1f, 0x95, 0xb1, 0x6a, 0xb9, 0x7c, 0x92,
+ 0xb3, 0x41, 0xc0, 0x02, 0x14, 0x41, 0xe2, 0x34, 0x5f, 0x1f, 0x56,
+ 0xdf, 0x24, 0x58, 0xf4, 0x26, 0xd1, 0x55, 0xb4, 0xba, 0x2d, 0xb6,
+ 0xdc, 0xd8, 0xc8,
+};
+
+/* fips_sig_negative is fips_sig with r encoded as a negative number. */
+static const uint8_t fips_sig_negative[] = {
+ 0x30, 0x2c, 0x02, 0x14, 0x8b, 0xac, 0x1a, 0xb6, 0x64, 0x10, 0x43,
+ 0x5c, 0xb7, 0x18, 0x1f, 0x95, 0xb1, 0x6a, 0xb9, 0x7c, 0x92, 0xb3,
+ 0x41, 0xc0, 0x02, 0x14, 0x41, 0xe2, 0x34, 0x5f, 0x1f, 0x56, 0xdf,
+ 0x24, 0x58, 0xf4, 0x26, 0xd1, 0x55, 0xb4, 0xba, 0x2d, 0xb6, 0xdc,
+ 0xd8, 0xc8,
+};
+
+/* fip_sig_extra is fips_sig with trailing data. */
+static const uint8_t fips_sig_extra[] = {
+ 0x30, 0x2d, 0x02, 0x15, 0x00, 0x8b, 0xac, 0x1a, 0xb6, 0x64, 0x10,
+ 0x43, 0x5c, 0xb7, 0x18, 0x1f, 0x95, 0xb1, 0x6a, 0xb9, 0x7c, 0x92,
+ 0xb3, 0x41, 0xc0, 0x02, 0x14, 0x41, 0xe2, 0x34, 0x5f, 0x1f, 0x56,
+ 0xdf, 0x24, 0x58, 0xf4, 0x26, 0xd1, 0x55, 0xb4, 0xba, 0x2d, 0xb6,
+ 0xdc, 0xd8, 0xc8, 0x00,
+};
+
+/* fips_sig_lengths is fips_sig with a non-minimally encoded length. */
+static const uint8_t fips_sig_bad_length[] = {
+ 0x30, 0x81, 0x2d, 0x02, 0x15, 0x00, 0x8b, 0xac, 0x1a, 0xb6, 0x64,
+ 0x10, 0x43, 0x5c, 0xb7, 0x18, 0x1f, 0x95, 0xb1, 0x6a, 0xb9, 0x7c,
+ 0x92, 0xb3, 0x41, 0xc0, 0x02, 0x14, 0x41, 0xe2, 0x34, 0x5f, 0x1f,
+ 0x56, 0xdf, 0x24, 0x58, 0xf4, 0x26, 0xd1, 0x55, 0xb4, 0xba, 0x2d,
+ 0xb6, 0xdc, 0xd8, 0xc8, 0x00,
+};
+
+/* fips_sig_bad_r is fips_sig with a bad r value. */
+static const uint8_t fips_sig_bad_r[] = {
+ 0x30, 0x2d, 0x02, 0x15, 0x00, 0x8c, 0xac, 0x1a, 0xb6, 0x64, 0x10,
+ 0x43, 0x5c, 0xb7, 0x18, 0x1f, 0x95, 0xb1, 0x6a, 0xb9, 0x7c, 0x92,
+ 0xb3, 0x41, 0xc0, 0x02, 0x14, 0x41, 0xe2, 0x34, 0x5f, 0x1f, 0x56,
+ 0xdf, 0x24, 0x58, 0xf4, 0x26, 0xd1, 0x55, 0xb4, 0xba, 0x2d, 0xb6,
+ 0xdc, 0xd8, 0xc8,
+};
+
+static BIO *bio_err = NULL;
+static BIO *bio_out = NULL;
+
+static DSA *get_fips_dsa(void) {
+ DSA *dsa = DSA_new();
+ if (!dsa) {
+ return NULL;
+ }
+ dsa->p = BN_bin2bn(fips_p, sizeof(fips_p), NULL);
+ dsa->q = BN_bin2bn(fips_q, sizeof(fips_q), NULL);
+ dsa->g = BN_bin2bn(fips_g, sizeof(fips_g), NULL);
+ dsa->pub_key = BN_bin2bn(fips_y, sizeof(fips_y), NULL);
+ dsa->priv_key = BN_bin2bn(fips_x, sizeof(fips_x), NULL);
+ if (dsa->p == NULL || dsa->q == NULL || dsa->g == NULL ||
+ dsa->pub_key == NULL || dsa->priv_key == NULL) {
+ DSA_free(dsa);
+ return NULL;
+ }
+ return dsa;
+}
+
+static int test_generate(void) {
+ BN_GENCB cb;
+ DSA *dsa = NULL;
+ int counter, ok = 0, i, j;
+ uint8_t buf[256];
+ unsigned long h;
+ uint8_t sig[256];
+ unsigned int siglen;
+
+ BIO_printf(bio_out, "test generation of DSA parameters\n");
+
+ BN_GENCB_set(&cb, dsa_cb, bio_out);
+ dsa = DSA_new();
+ if (dsa == NULL ||
+ !DSA_generate_parameters_ex(dsa, 512, seed, 20, &counter, &h, &cb)) {
+ goto end;
+ }
+
+ BIO_printf(bio_out, "seed\n");
+ for (i = 0; i < 20; i += 4) {
+ BIO_printf(bio_out, "%02X%02X%02X%02X ", seed[i], seed[i + 1], seed[i + 2],
+ seed[i + 3]);
+ }
+ BIO_printf(bio_out, "\ncounter=%d h=%ld\n", counter, h);
+
+ 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->q, buf);
+ j = sizeof(fips_q);
+ if (i != j || memcmp(buf, fips_q, i) != 0) {
+ BIO_printf(bio_err, "q value is wrong\n");
+ goto end;
+ }
+
+ i = BN_bn2bin(dsa->p, buf);
+ j = sizeof(fips_p);
+ if (i != j || memcmp(buf, fips_p, i) != 0) {
+ BIO_printf(bio_err, "p value is wrong\n");
+ goto end;
+ }
+
+ i = BN_bn2bin(dsa->g, buf);
+ j = sizeof(fips_g);
+ if (i != j || memcmp(buf, fips_g, i) != 0) {
+ BIO_printf(bio_err, "g value is wrong\n");
+ goto end;
+ }
+
+ DSA_generate_key(dsa);
+ DSA_sign(0, fips_digest, sizeof(fips_digest), sig, &siglen, dsa);
+ if (DSA_verify(0, fips_digest, sizeof(fips_digest), sig, siglen, dsa) == 1) {
+ ok = 1;
+ } else {
+ BIO_printf(bio_err, "verification failure\n");
+ }
+
+end:
+ if (dsa != NULL) {
+ DSA_free(dsa);
+ }
+
+ return ok;
+}
+
+static int test_verify(const uint8_t *sig, size_t sig_len, int expect) {
+ int ok = 0;
+ DSA *dsa = get_fips_dsa();
+ if (dsa == NULL) {
+ goto end;
+ }
+
+ int ret = DSA_verify(0, fips_digest, sizeof(fips_digest), sig, sig_len, dsa);
+ if (ret != expect) {
+ BIO_printf(bio_err, "DSA_verify returned %d, want %d\n", ret, expect);
+ goto end;
+ }
+ ok = 1;
+ /* Clear any errorrs from a test with expected failure. */
+ ERR_clear_error();
+
+end:
+ if (dsa != NULL) {
+ DSA_free(dsa);
+ }
+
+ return ok;
+}
+
+int main(int argc, char **argv) {
+ CRYPTO_library_init();
+
+ bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
+ bio_out = BIO_new_fp(stdout, BIO_NOCLOSE);
+
+ if (!test_generate() ||
+ !test_verify(fips_sig, sizeof(fips_sig), 1) ||
+ !test_verify(fips_sig_negative, sizeof(fips_sig_negative), -1) ||
+ !test_verify(fips_sig_extra, sizeof(fips_sig_extra), -1) ||
+ !test_verify(fips_sig_bad_length, sizeof(fips_sig_bad_length), -1) ||
+ !test_verify(fips_sig_bad_r, sizeof(fips_sig_bad_r), 0)) {
+ BIO_print_errors(bio_err);
+ BIO_free(bio_err);
+ BIO_free(bio_out);
+ return 1;
+ }
+
+ BIO_free(bio_err);
+ BIO_free(bio_out);
+ printf("PASS\n");
+ return 0;
+}
+
+static int dsa_cb(int p, int n, BN_GENCB *arg) {
+ char c = '*';
+ static int ok = 0, num = 0;
+
+ switch (p) {
+ case 0:
+ c = '.';
+ num++;
+ break;
+ case 1:
+ c = '+';
+ break;
+ case 2:
+ c = '*';
+ ok++;
+ break;
+ case 3:
+ c = '\n';
+ }
+
+ BIO_write(arg->arg, &c, 1);
+ (void)BIO_flush(arg->arg);
+
+ if (!ok && p == 0 && num > 1) {
+ BIO_printf((BIO *)arg, "error in dsatest\n");
+ return 0;
+ }
+
+ return 1;
+}
diff --git a/src/crypto/dsa/internal.h b/src/crypto/dsa/internal.h
new file mode 100644
index 0000000..ef99158
--- /dev/null
+++ b/src/crypto/dsa/internal.h
@@ -0,0 +1,78 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <schoch@sheba.arc.nasa.gov>. */
+
+#ifndef OPENSSL_HEADER_DSA_INTERNAL_H
+#define OPENSSL_HEADER_DSA_INTERNAL_H
+
+#include <openssl/base.h>
+
+#include <openssl/bn.h>
+#include <openssl/ex_data.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_DSA_INTERNAL_H */
diff --git a/src/crypto/ec/CMakeLists.txt b/src/crypto/ec/CMakeLists.txt
new file mode 100644
index 0000000..11266c6
--- /dev/null
+++ b/src/crypto/ec/CMakeLists.txt
@@ -0,0 +1,31 @@
+include_directories(. .. ../../include)
+
+add_library(
+ ec
+
+ OBJECT
+
+ ec.c
+ oct.c
+ simple.c
+ ec_montgomery.c
+ wnaf.c
+ ec_key.c
+ ec_asn1.c
+ ec_error.c
+)
+
+add_executable(
+ example_mul
+
+ example_mul.c
+)
+
+add_executable(
+ ec_test
+
+ ec_test.c
+)
+
+target_link_libraries(example_mul crypto)
+target_link_libraries(ec_test crypto)
diff --git a/src/crypto/ec/ec.c b/src/crypto/ec/ec.c
new file mode 100644
index 0000000..f9d8dc5
--- /dev/null
+++ b/src/crypto/ec/ec.c
@@ -0,0 +1,856 @@
+/* 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. */
+
+#include <openssl/ec.h>
+
+#include <string.h>
+
+#include <openssl/bn.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+
+#include "internal.h"
+
+
+static const struct curve_data P224 = {
+ "NIST P-224",
+ 28,
+ 1,
+ {/* 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 curve_data P256 = {
+ "NIST P-256",
+ 32,
+ 1,
+ {/* 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}};
+
+static const struct curve_data P384 = {
+ "NIST P-384",
+ 48,
+ 1,
+ {/* 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 curve_data P521 = {
+ "NIST P-521",
+ 66,
+ 1,
+ {/* 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}};
+
+const struct built_in_curve OPENSSL_built_in_curves[] = {
+ {NID_secp224r1, &P224, 0},
+ {NID_X9_62_prime256v1, &P256, 0},
+ {NID_secp384r1, &P384, 0},
+ {NID_secp521r1, &P521, 0},
+ {NID_undef, 0, 0},
+};
+
+EC_GROUP *ec_group_new(const EC_METHOD *meth) {
+ EC_GROUP *ret;
+
+ if (meth == NULL) {
+ OPENSSL_PUT_ERROR(EC, ec_group_new, EC_R_SLOT_FULL);
+ return NULL;
+ }
+
+ if (meth->group_init == 0) {
+ OPENSSL_PUT_ERROR(EC, ec_group_new, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return NULL;
+ }
+
+ ret = OPENSSL_malloc(sizeof(EC_GROUP));
+ if (ret == NULL) {
+ OPENSSL_PUT_ERROR(EC, ec_group_new, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ memset(ret, 0, sizeof(EC_GROUP));
+
+ ret->meth = meth;
+ BN_init(&ret->order);
+ BN_init(&ret->cofactor);
+
+ if (!meth->group_init(ret)) {
+ OPENSSL_free(ret);
+ return NULL;
+ }
+
+ return ret;
+}
+
+static EC_GROUP *ec_group_new_curve_GFp(const BIGNUM *p, const BIGNUM *a,
+ const BIGNUM *b, BN_CTX *ctx) {
+ const EC_METHOD *meth = EC_GFp_mont_method();
+ EC_GROUP *ret;
+
+ ret = ec_group_new(meth);
+ if (ret == NULL) {
+ return NULL;
+ }
+
+ if (ret->meth->group_set_curve == 0) {
+ OPENSSL_PUT_ERROR(EC, ec_group_new_curve_GFp,
+ ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return 0;
+ }
+ if (!ret->meth->group_set_curve(ret, p, a, b, ctx)) {
+ EC_GROUP_free(ret);
+ return NULL;
+ }
+ return ret;
+}
+
+static EC_GROUP *ec_group_new_from_data(const struct built_in_curve *curve) {
+ EC_GROUP *group = NULL;
+ EC_POINT *P = NULL;
+ BN_CTX *ctx = NULL;
+ BIGNUM *p = NULL, *a = NULL, *b = NULL, *x = NULL, *y = NULL, *order = NULL;
+ int ok = 0;
+ unsigned param_len;
+ const EC_METHOD *meth;
+ const struct curve_data *data;
+ const uint8_t *params;
+
+ if ((ctx = BN_CTX_new()) == NULL) {
+ OPENSSL_PUT_ERROR(EC, ec_group_new_from_data, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ data = curve->data;
+ param_len = data->param_len;
+ params = data->data;
+
+ if (!(p = BN_bin2bn(params + 0 * param_len, param_len, NULL)) ||
+ !(a = BN_bin2bn(params + 1 * param_len, param_len, NULL)) ||
+ !(b = BN_bin2bn(params + 2 * param_len, param_len, NULL))) {
+ OPENSSL_PUT_ERROR(EC, ec_group_new_from_data, ERR_R_BN_LIB);
+ goto err;
+ }
+
+ if (curve->method != 0) {
+ meth = curve->method();
+ if (((group = ec_group_new(meth)) == NULL) ||
+ (!(group->meth->group_set_curve(group, p, a, b, ctx)))) {
+ OPENSSL_PUT_ERROR(EC, ec_group_new_from_data, ERR_R_EC_LIB);
+ goto err;
+ }
+ } else {
+ if ((group = ec_group_new_curve_GFp(p, a, b, ctx)) == NULL) {
+ OPENSSL_PUT_ERROR(EC, ec_group_new_from_data, ERR_R_EC_LIB);
+ goto err;
+ }
+ }
+
+ if ((P = EC_POINT_new(group)) == NULL) {
+ OPENSSL_PUT_ERROR(EC, ec_group_new_from_data, ERR_R_EC_LIB);
+ goto err;
+ }
+
+ if (!(x = BN_bin2bn(params + 3 * param_len, param_len, NULL)) ||
+ !(y = BN_bin2bn(params + 4 * param_len, param_len, NULL))) {
+ OPENSSL_PUT_ERROR(EC, ec_group_new_from_data, ERR_R_BN_LIB);
+ goto err;
+ }
+
+ if (!EC_POINT_set_affine_coordinates_GFp(group, P, x, y, ctx)) {
+ OPENSSL_PUT_ERROR(EC, ec_group_new_from_data, ERR_R_EC_LIB);
+ goto err;
+ }
+ if (!(order = BN_bin2bn(params + 5 * param_len, param_len, NULL)) ||
+ !BN_set_word(x, (BN_ULONG)data->cofactor)) {
+ OPENSSL_PUT_ERROR(EC, ec_group_new_from_data, ERR_R_BN_LIB);
+ goto err;
+ }
+
+ group->generator = P;
+ P = NULL;
+ if (!BN_copy(&group->order, order) ||
+ !BN_set_word(&group->cofactor, (BN_ULONG)data->cofactor)) {
+ OPENSSL_PUT_ERROR(EC, ec_group_new_from_data, ERR_R_BN_LIB);
+ goto err;
+ }
+
+ ok = 1;
+
+err:
+ if (!ok) {
+ EC_GROUP_free(group);
+ group = NULL;
+ }
+ if (P)
+ EC_POINT_free(P);
+ if (ctx)
+ BN_CTX_free(ctx);
+ if (p)
+ BN_free(p);
+ if (a)
+ BN_free(a);
+ if (b)
+ BN_free(b);
+ if (order)
+ BN_free(order);
+ if (x)
+ BN_free(x);
+ if (y)
+ BN_free(y);
+ return group;
+}
+
+EC_GROUP *EC_GROUP_new_by_curve_name(int nid) {
+ unsigned i;
+ const struct built_in_curve *curve;
+ EC_GROUP *ret = NULL;
+
+ for (i = 0; OPENSSL_built_in_curves[i].nid != NID_undef; i++) {
+ curve = &OPENSSL_built_in_curves[i];
+ if (curve->nid == nid) {
+ ret = ec_group_new_from_data(curve);
+ break;
+ }
+ }
+
+ if (ret == NULL) {
+ OPENSSL_PUT_ERROR(EC, EC_GROUP_new_by_curve_name, EC_R_UNKNOWN_GROUP);
+ return NULL;
+ }
+
+ ret->curve_name = nid;
+ return ret;
+}
+
+void EC_GROUP_free(EC_GROUP *group) {
+ if (!group) {
+ return;
+ }
+
+ if (group->meth->group_finish != 0) {
+ group->meth->group_finish(group);
+ }
+
+ ec_pre_comp_free(group->pre_comp);
+
+ if (group->generator != NULL) {
+ EC_POINT_free(group->generator);
+ }
+ BN_free(&group->order);
+ BN_free(&group->cofactor);
+
+ OPENSSL_free(group);
+}
+
+int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src) {
+ if (dest->meth->group_copy == 0) {
+ OPENSSL_PUT_ERROR(EC, EC_GROUP_copy, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return 0;
+ }
+ if (dest->meth != src->meth) {
+ OPENSSL_PUT_ERROR(EC, EC_GROUP_copy, EC_R_INCOMPATIBLE_OBJECTS);
+ return 0;
+ }
+ if (dest == src) {
+ return 1;
+ }
+
+ ec_pre_comp_free(dest->pre_comp);
+ dest->pre_comp = ec_pre_comp_dup(src->pre_comp);
+
+ 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 */
+ if (dest->generator != NULL) {
+ EC_POINT_clear_free(dest->generator);
+ dest->generator = NULL;
+ }
+ }
+
+ if (!BN_copy(&dest->order, &src->order) ||
+ !BN_copy(&dest->cofactor, &src->cofactor)) {
+ return 0;
+ }
+
+ dest->curve_name = src->curve_name;
+
+ return dest->meth->group_copy(dest, src);
+}
+
+EC_GROUP *EC_GROUP_dup(const EC_GROUP *a) {
+ EC_GROUP *t = NULL;
+ int ok = 0;
+
+ if (a == NULL) {
+ return NULL;
+ }
+
+ t = ec_group_new(a->meth);
+ if (t == NULL) {
+ return NULL;
+ }
+ if (!EC_GROUP_copy(t, a)) {
+ goto err;
+ }
+
+ ok = 1;
+
+err:
+ if (!ok) {
+ if (t) {
+ EC_GROUP_free(t);
+ }
+ return NULL;
+ } else {
+ return t;
+ }
+}
+
+int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b) {
+ if (a->curve_name == NID_undef || b->curve_name == NID_undef) {
+ return 0;
+ }
+ return a->curve_name == b->curve_name;
+}
+
+const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group) {
+ return group->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);
+}
+
+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);
+}
+
+int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *out_p, BIGNUM *out_a,
+ BIGNUM *out_b, BN_CTX *ctx) {
+ if (group->meth->group_get_curve == 0) {
+ OPENSSL_PUT_ERROR(EC, EC_GROUP_get_curve_GFp,
+ ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return 0;
+ }
+ return group->meth->group_get_curve(group, out_p, out_a, out_b, ctx);
+}
+
+int EC_GROUP_get_curve_name(const EC_GROUP *group) { return group->curve_name; }
+
+int EC_GROUP_get_degree(const EC_GROUP *group) {
+ if (group->meth->group_get_degree == 0) {
+ OPENSSL_PUT_ERROR(EC, EC_GROUP_get_degree,
+ ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return 0;
+ }
+ return group->meth->group_get_degree(group);
+}
+
+int EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx) {
+ if (group->meth->mul == 0) {
+ /* use default */
+ return ec_wNAF_precompute_mult(group, ctx);
+ }
+
+ if (group->meth->precompute_mult != 0) {
+ return group->meth->precompute_mult(group, ctx);
+ }
+
+ return 1; /* nothing to do, so report success */
+}
+
+int EC_GROUP_have_precompute_mult(const EC_GROUP *group) {
+ if (group->meth->mul == 0) {
+ /* use default */
+ return ec_wNAF_have_precompute_mult(group);
+ }
+
+ if (group->meth->have_precompute_mult != 0) {
+ return group->meth->have_precompute_mult(group);
+ }
+
+ return 0; /* cannot tell whether precomputation has been performed */
+}
+
+EC_POINT *EC_POINT_new(const EC_GROUP *group) {
+ EC_POINT *ret;
+
+ if (group == NULL) {
+ OPENSSL_PUT_ERROR(EC, EC_POINT_new, ERR_R_PASSED_NULL_PARAMETER);
+ return NULL;
+ }
+ if (group->meth->point_init == 0) {
+ OPENSSL_PUT_ERROR(EC, EC_POINT_new, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return NULL;
+ }
+
+ ret = OPENSSL_malloc(sizeof *ret);
+ if (ret == NULL) {
+ OPENSSL_PUT_ERROR(EC, EC_POINT_new, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ ret->meth = group->meth;
+
+ if (!ret->meth->point_init(ret)) {
+ OPENSSL_free(ret);
+ return NULL;
+ }
+
+ return ret;
+}
+
+void EC_POINT_free(EC_POINT *point) {
+ if (!point) {
+ return;
+ }
+
+ if (point->meth->point_finish != 0) {
+ point->meth->point_finish(point);
+ }
+ OPENSSL_free(point);
+}
+
+void EC_POINT_clear_free(EC_POINT *point) {
+ if (!point) {
+ return;
+ }
+
+ if (point->meth->point_clear_finish != 0) {
+ point->meth->point_clear_finish(point);
+ } else if (point->meth->point_finish != 0) {
+ point->meth->point_finish(point);
+ }
+ OPENSSL_cleanse(point, sizeof *point);
+ OPENSSL_free(point);
+}
+
+int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src) {
+ if (dest->meth->point_copy == 0) {
+ OPENSSL_PUT_ERROR(EC, EC_POINT_copy, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return 0;
+ }
+ if (dest->meth != src->meth) {
+ OPENSSL_PUT_ERROR(EC, EC_POINT_copy, EC_R_INCOMPATIBLE_OBJECTS);
+ return 0;
+ }
+ if (dest == src) {
+ return 1;
+ }
+ return dest->meth->point_copy(dest, src);
+}
+
+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) {
+ OPENSSL_PUT_ERROR(EC, EC_POINT_dup, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ r = EC_POINT_copy(t, a);
+ if (!r) {
+ EC_POINT_free(t);
+ return NULL;
+ } else {
+ return t;
+ }
+}
+
+int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point) {
+ if (group->meth->point_set_to_infinity == 0) {
+ OPENSSL_PUT_ERROR(EC, EC_POINT_set_to_infinity,
+ ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return 0;
+ }
+ if (group->meth != point->meth) {
+ OPENSSL_PUT_ERROR(EC, EC_POINT_set_to_infinity, EC_R_INCOMPATIBLE_OBJECTS);
+ return 0;
+ }
+ return group->meth->point_set_to_infinity(group, point);
+}
+
+int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point) {
+ if (group->meth->is_at_infinity == 0) {
+ OPENSSL_PUT_ERROR(EC, EC_POINT_is_at_infinity,
+ ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return 0;
+ }
+ if (group->meth != point->meth) {
+ OPENSSL_PUT_ERROR(EC, EC_POINT_is_at_infinity, EC_R_INCOMPATIBLE_OBJECTS);
+ return 0;
+ }
+ return group->meth->is_at_infinity(group, point);
+}
+
+int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
+ BN_CTX *ctx) {
+ if (group->meth->is_on_curve == 0) {
+ OPENSSL_PUT_ERROR(EC, EC_POINT_is_on_curve,
+ ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return 0;
+ }
+ if (group->meth != point->meth) {
+ OPENSSL_PUT_ERROR(EC, EC_POINT_is_on_curve, EC_R_INCOMPATIBLE_OBJECTS);
+ return 0;
+ }
+ return group->meth->is_on_curve(group, point, ctx);
+}
+
+int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b,
+ BN_CTX *ctx) {
+ if (group->meth->point_cmp == 0) {
+ OPENSSL_PUT_ERROR(EC, EC_POINT_cmp, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return -1;
+ }
+ if ((group->meth != a->meth) || (a->meth != b->meth)) {
+ OPENSSL_PUT_ERROR(EC, EC_POINT_cmp, EC_R_INCOMPATIBLE_OBJECTS);
+ return -1;
+ }
+ return group->meth->point_cmp(group, a, b, ctx);
+}
+
+int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx) {
+ if (group->meth->make_affine == 0) {
+ OPENSSL_PUT_ERROR(EC, EC_POINT_make_affine,
+ ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return 0;
+ }
+ if (group->meth != point->meth) {
+ OPENSSL_PUT_ERROR(EC, EC_POINT_make_affine, EC_R_INCOMPATIBLE_OBJECTS);
+ return 0;
+ }
+ return group->meth->make_affine(group, point, ctx);
+}
+
+int EC_POINTs_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[],
+ BN_CTX *ctx) {
+ size_t i;
+
+ if (group->meth->points_make_affine == 0) {
+ OPENSSL_PUT_ERROR(EC, EC_POINTs_make_affine,
+ ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return 0;
+ }
+ for (i = 0; i < num; i++) {
+ if (group->meth != points[i]->meth) {
+ OPENSSL_PUT_ERROR(EC, EC_POINTs_make_affine, EC_R_INCOMPATIBLE_OBJECTS);
+ return 0;
+ }
+ }
+ return group->meth->points_make_affine(group, num, points, ctx);
+}
+
+int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group,
+ const EC_POINT *point, BIGNUM *x,
+ BIGNUM *y, BN_CTX *ctx) {
+ if (group->meth->point_get_affine_coordinates == 0) {
+ OPENSSL_PUT_ERROR(EC, EC_POINT_get_affine_coordinates_GFp,
+ ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return 0;
+ }
+ if (group->meth != point->meth) {
+ OPENSSL_PUT_ERROR(EC, EC_POINT_get_affine_coordinates_GFp,
+ EC_R_INCOMPATIBLE_OBJECTS);
+ return 0;
+ }
+ return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
+}
+
+int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
+ const BIGNUM *x, const BIGNUM *y,
+ BN_CTX *ctx) {
+ if (group->meth->point_set_affine_coordinates == 0) {
+ OPENSSL_PUT_ERROR(EC, EC_POINT_set_affine_coordinates_GFp,
+ ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return 0;
+ }
+ if (group->meth != point->meth) {
+ OPENSSL_PUT_ERROR(EC, EC_POINT_set_affine_coordinates_GFp,
+ EC_R_INCOMPATIBLE_OBJECTS);
+ return 0;
+ }
+ return group->meth->point_set_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) {
+ if (group->meth->add == 0) {
+ OPENSSL_PUT_ERROR(EC, EC_POINT_add, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return 0;
+ }
+ if ((group->meth != r->meth) || (r->meth != a->meth) ||
+ (a->meth != b->meth)) {
+ OPENSSL_PUT_ERROR(EC, EC_POINT_add, EC_R_INCOMPATIBLE_OBJECTS);
+ return 0;
+ }
+ return group->meth->add(group, r, a, b, ctx);
+}
+
+
+int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
+ BN_CTX *ctx) {
+ if (group->meth->dbl == 0) {
+ OPENSSL_PUT_ERROR(EC, EC_POINT_dbl, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return 0;
+ }
+ if ((group->meth != r->meth) || (r->meth != a->meth)) {
+ OPENSSL_PUT_ERROR(EC, EC_POINT_dbl, EC_R_INCOMPATIBLE_OBJECTS);
+ return 0;
+ }
+ return group->meth->dbl(group, r, a, ctx);
+}
+
+
+int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx) {
+ if (group->meth->invert == 0) {
+ OPENSSL_PUT_ERROR(EC, EC_POINT_invert, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return 0;
+ }
+ if (group->meth != a->meth) {
+ OPENSSL_PUT_ERROR(EC, EC_POINT_invert, EC_R_INCOMPATIBLE_OBJECTS);
+ return 0;
+ }
+ return group->meth->invert(group, a, ctx);
+}
+
+int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar,
+ const EC_POINT *point, const BIGNUM *p_scalar, BN_CTX *ctx) {
+ /* just a convenient interface to EC_POINTs_mul() */
+
+ const EC_POINT *points[1];
+ const BIGNUM *scalars[1];
+
+ points[0] = point;
+ scalars[0] = p_scalar;
+
+ return EC_POINTs_mul(group, r, g_scalar, (point != NULL && p_scalar != NULL),
+ points, scalars, ctx);
+}
+
+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) {
+ if (group->meth->mul == 0) {
+ /* use default. Warning, not constant-time. */
+ return ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
+ }
+
+ return group->meth->mul(group, r, scalar, num, points, scalars, ctx);
+}
+
+int ec_point_set_Jprojective_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
+ const BIGNUM *x, const BIGNUM *y,
+ const BIGNUM *z, BN_CTX *ctx) {
+ if (group->meth->point_set_Jprojective_coordinates_GFp == 0) {
+ OPENSSL_PUT_ERROR(EC, ec_point_set_Jprojective_coordinates_GFp,
+ ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return 0;
+ }
+ if (group->meth != point->meth) {
+ OPENSSL_PUT_ERROR(EC, ec_point_set_Jprojective_coordinates_GFp,
+ EC_R_INCOMPATIBLE_OBJECTS);
+ return 0;
+ }
+ return group->meth->point_set_Jprojective_coordinates_GFp(group, point, x, y,
+ z, ctx);
+}
diff --git a/src/crypto/ec/ec_asn1.c b/src/crypto/ec/ec_asn1.c
new file mode 100644
index 0000000..ce9b3f4
--- /dev/null
+++ b/src/crypto/ec/ec_asn1.c
@@ -0,0 +1,599 @@
+/* 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 <openssl/ec.h>
+
+#include <string.h>
+
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/bn.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+
+#include "internal.h"
+
+
+typedef struct x9_62_fieldid_st {
+ ASN1_OBJECT *fieldType;
+ union {
+ char *ptr;
+ /* NID_X9_62_prime_field */
+ ASN1_INTEGER *prime;
+ /* anything else */
+ ASN1_TYPE *other;
+ } p;
+} X9_62_FIELDID;
+
+ASN1_ADB_TEMPLATE(fieldID_def) = ASN1_SIMPLE(X9_62_FIELDID, p.other, ASN1_ANY);
+
+ASN1_ADB(X9_62_FIELDID) = {
+ ADB_ENTRY(NID_X9_62_prime_field, ASN1_SIMPLE(X9_62_FIELDID, p.prime, ASN1_INTEGER)),
+} ASN1_ADB_END(X9_62_FIELDID, 0, fieldType, 0, &fieldID_def_tt, NULL);
+
+ASN1_SEQUENCE(X9_62_FIELDID) = {
+ ASN1_SIMPLE(X9_62_FIELDID, fieldType, ASN1_OBJECT),
+ ASN1_ADB_OBJECT(X9_62_FIELDID)
+} ASN1_SEQUENCE_END(X9_62_FIELDID);
+
+typedef struct x9_62_curve_st {
+ ASN1_OCTET_STRING *a;
+ ASN1_OCTET_STRING *b;
+ ASN1_BIT_STRING *seed;
+} X9_62_CURVE;
+
+ASN1_SEQUENCE(X9_62_CURVE) = {
+ ASN1_SIMPLE(X9_62_CURVE, a, ASN1_OCTET_STRING),
+ ASN1_SIMPLE(X9_62_CURVE, b, ASN1_OCTET_STRING),
+ ASN1_OPT(X9_62_CURVE, seed, ASN1_BIT_STRING)
+} ASN1_SEQUENCE_END(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;
+
+DECLARE_ASN1_ALLOC_FUNCTIONS(ECPARAMETERS);
+
+ASN1_SEQUENCE(ECPARAMETERS) = {
+ ASN1_SIMPLE(ECPARAMETERS, version, LONG),
+ ASN1_SIMPLE(ECPARAMETERS, fieldID, X9_62_FIELDID),
+ ASN1_SIMPLE(ECPARAMETERS, curve, X9_62_CURVE),
+ ASN1_SIMPLE(ECPARAMETERS, base, ASN1_OCTET_STRING),
+ ASN1_SIMPLE(ECPARAMETERS, order, ASN1_INTEGER),
+ ASN1_OPT(ECPARAMETERS, cofactor, ASN1_INTEGER)
+} ASN1_SEQUENCE_END(ECPARAMETERS);
+
+IMPLEMENT_ASN1_ALLOC_FUNCTIONS(ECPARAMETERS);
+
+typedef struct ecpk_parameters_st {
+ int type;
+ union {
+ ASN1_OBJECT *named_curve;
+ ECPARAMETERS *parameters;
+ } value;
+} ECPKPARAMETERS;
+
+/* SEC1 ECPrivateKey */
+typedef struct ec_privatekey_st {
+ long version;
+ ASN1_OCTET_STRING *privateKey;
+ ECPKPARAMETERS *parameters;
+ ASN1_BIT_STRING *publicKey;
+} EC_PRIVATEKEY;
+
+DECLARE_ASN1_FUNCTIONS_const(ECPKPARAMETERS);
+DECLARE_ASN1_ENCODE_FUNCTIONS_const(ECPKPARAMETERS, ECPKPARAMETERS);
+
+ASN1_CHOICE(ECPKPARAMETERS) = {
+ ASN1_SIMPLE(ECPKPARAMETERS, value.named_curve, ASN1_OBJECT),
+ ASN1_SIMPLE(ECPKPARAMETERS, value.parameters, ECPARAMETERS),
+} ASN1_CHOICE_END(ECPKPARAMETERS);
+
+IMPLEMENT_ASN1_FUNCTIONS_const(ECPKPARAMETERS);
+
+DECLARE_ASN1_FUNCTIONS_const(EC_PRIVATEKEY);
+DECLARE_ASN1_ENCODE_FUNCTIONS_const(EC_PRIVATEKEY, EC_PRIVATEKEY);
+
+ASN1_SEQUENCE(EC_PRIVATEKEY) = {
+ ASN1_SIMPLE(EC_PRIVATEKEY, version, LONG),
+ ASN1_SIMPLE(EC_PRIVATEKEY, privateKey, ASN1_OCTET_STRING),
+ ASN1_EXP_OPT(EC_PRIVATEKEY, parameters, ECPKPARAMETERS, 0),
+ ASN1_EXP_OPT(EC_PRIVATEKEY, publicKey, ASN1_BIT_STRING, 1),
+} ASN1_SEQUENCE_END(EC_PRIVATEKEY);
+
+IMPLEMENT_ASN1_FUNCTIONS_const(EC_PRIVATEKEY);
+
+
+ECPKPARAMETERS *ec_asn1_group2pkparameters(const EC_GROUP *group,
+ ECPKPARAMETERS *params) {
+ int ok = 0, nid;
+ ECPKPARAMETERS *ret = params;
+
+ if (ret == NULL) {
+ ret = ECPKPARAMETERS_new();
+ if (ret == NULL) {
+ OPENSSL_PUT_ERROR(EC, ec_asn1_group2pkparameters, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ } else {
+ if (ret->value.named_curve) {
+ ASN1_OBJECT_free(ret->value.named_curve);
+ }
+ }
+
+ /* use the ASN.1 OID to describe the the elliptic curve parameters. */
+ nid = EC_GROUP_get_curve_name(group);
+ if (nid) {
+ ret->type = 0;
+ ret->value.named_curve = (ASN1_OBJECT*) OBJ_nid2obj(nid);
+ ok = ret->value.named_curve != NULL;
+ }
+
+ if (!ok) {
+ ECPKPARAMETERS_free(ret);
+ return NULL;
+ }
+
+ return ret;
+}
+
+EC_GROUP *ec_asn1_pkparameters2group(const ECPKPARAMETERS *params) {
+ EC_GROUP *ret = NULL;
+ int nid = NID_undef;
+
+ if (params == NULL) {
+ OPENSSL_PUT_ERROR(EC, ec_asn1_pkparameters2group, EC_R_MISSING_PARAMETERS);
+ return NULL;
+ }
+
+ if (params->type == 0) {
+ nid = OBJ_obj2nid(params->value.named_curve);
+ } else if (params->type == 1) {
+ /* We don't support arbitary curves so we attempt to recognise it from the
+ * group order. */
+ const ECPARAMETERS *ecparams = params->value.parameters;
+ unsigned i;
+ const struct built_in_curve *curve;
+
+ for (i = 0; OPENSSL_built_in_curves[i].nid != NID_undef; i++) {
+ curve = &OPENSSL_built_in_curves[i];
+ const unsigned param_len = curve->data->param_len;
+ if (ecparams->order->length == param_len &&
+ memcmp(ecparams->order->data, &curve->data->data[param_len * 5],
+ param_len) == 0) {
+ nid = curve->nid;
+ break;
+ }
+ }
+ }
+
+ if (nid == NID_undef) {
+ OPENSSL_PUT_ERROR(EC, ec_asn1_pkparameters2group, EC_R_NON_NAMED_CURVE);
+ return NULL;
+ }
+
+ ret = EC_GROUP_new_by_curve_name(nid);
+ if (ret == NULL) {
+ OPENSSL_PUT_ERROR(EC, ec_asn1_pkparameters2group,
+ EC_R_EC_GROUP_NEW_BY_NAME_FAILURE);
+ return NULL;
+ }
+
+ return ret;
+}
+
+static EC_GROUP *d2i_ECPKParameters(EC_GROUP **groupp, const uint8_t **inp,
+ long len) {
+ EC_GROUP *group = NULL;
+ ECPKPARAMETERS *params = NULL;
+
+ params = d2i_ECPKPARAMETERS(NULL, inp, len);
+ if (params == NULL) {
+ OPENSSL_PUT_ERROR(EC, d2i_ECPKParameters, EC_R_D2I_ECPKPARAMETERS_FAILURE);
+ ECPKPARAMETERS_free(params);
+ return NULL;
+ }
+
+ group = ec_asn1_pkparameters2group(params);
+ if (group == NULL) {
+ OPENSSL_PUT_ERROR(EC, d2i_ECPKParameters, EC_R_PKPARAMETERS2GROUP_FAILURE);
+ ECPKPARAMETERS_free(params);
+ return NULL;
+ }
+
+ if (groupp && *groupp) {
+ EC_GROUP_free(*groupp);
+ }
+ if (groupp) {
+ *groupp = group;
+ }
+
+ ECPKPARAMETERS_free(params);
+ return group;
+}
+
+static int i2d_ECPKParameters(const EC_GROUP *group, uint8_t **outp) {
+ int ret = 0;
+ ECPKPARAMETERS *tmp = ec_asn1_group2pkparameters(group, NULL);
+ if (tmp == NULL) {
+ OPENSSL_PUT_ERROR(EC, i2d_ECPKParameters, EC_R_GROUP2PKPARAMETERS_FAILURE);
+ return 0;
+ }
+ ret = i2d_ECPKPARAMETERS(tmp, outp);
+ if (ret == 0) {
+ OPENSSL_PUT_ERROR(EC, i2d_ECPKParameters, EC_R_I2D_ECPKPARAMETERS_FAILURE);
+ ECPKPARAMETERS_free(tmp);
+ return 0;
+ }
+ ECPKPARAMETERS_free(tmp);
+ return ret;
+}
+
+EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const uint8_t **in, long len) {
+ int ok = 0;
+ EC_KEY *ret = NULL;
+ EC_PRIVATEKEY *priv_key = NULL;
+
+ priv_key = EC_PRIVATEKEY_new();
+ if (priv_key == NULL) {
+ OPENSSL_PUT_ERROR(EC, d2i_ECPrivateKey, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ priv_key = d2i_EC_PRIVATEKEY(&priv_key, in, len);
+ if (priv_key == NULL) {
+ OPENSSL_PUT_ERROR(EC, d2i_ECPrivateKey, ERR_R_EC_LIB);
+ EC_PRIVATEKEY_free(priv_key);
+ return NULL;
+ }
+
+ if (a == NULL || *a == NULL) {
+ ret = EC_KEY_new();
+ if (ret == NULL) {
+ OPENSSL_PUT_ERROR(EC, d2i_ECPrivateKey, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ if (a) {
+ *a = ret;
+ }
+ } else {
+ ret = *a;
+ }
+
+ if (priv_key->parameters) {
+ if (ret->group) {
+ EC_GROUP_free(ret->group);
+ }
+ ret->group = ec_asn1_pkparameters2group(priv_key->parameters);
+ }
+
+ if (ret->group == NULL) {
+ OPENSSL_PUT_ERROR(EC, d2i_ECPrivateKey, ERR_R_EC_LIB);
+ goto err;
+ }
+
+ ret->version = priv_key->version;
+
+ if (priv_key->privateKey) {
+ ret->priv_key =
+ BN_bin2bn(M_ASN1_STRING_data(priv_key->privateKey),
+ M_ASN1_STRING_length(priv_key->privateKey), ret->priv_key);
+ if (ret->priv_key == NULL) {
+ OPENSSL_PUT_ERROR(EC, d2i_ECPrivateKey, ERR_R_BN_LIB);
+ goto err;
+ }
+ } else {
+ OPENSSL_PUT_ERROR(EC, d2i_ECPrivateKey, 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) {
+ OPENSSL_PUT_ERROR(EC, d2i_ECPrivateKey, ERR_R_EC_LIB);
+ goto err;
+ }
+
+ if (priv_key->publicKey) {
+ const uint8_t *pub_oct;
+ int pub_oct_len;
+
+ pub_oct = M_ASN1_STRING_data(priv_key->publicKey);
+ pub_oct_len = M_ASN1_STRING_length(priv_key->publicKey);
+ /* The first byte (the point conversion form) must be present. */
+ if (pub_oct_len <= 0) {
+ OPENSSL_PUT_ERROR(EC, d2i_ECPrivateKey, 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)) {
+ OPENSSL_PUT_ERROR(EC, d2i_ECPrivateKey, ERR_R_EC_LIB);
+ goto err;
+ }
+ } else {
+ if (!EC_POINT_mul(ret->group, ret->pub_key, ret->priv_key, NULL, NULL,
+ NULL)) {
+ OPENSSL_PUT_ERROR(EC, d2i_ECPrivateKey, ERR_R_EC_LIB);
+ goto err;
+ }
+ /* Remember the original private-key-only encoding. */
+ ret->enc_flag |= EC_PKEY_NO_PUBKEY;
+ }
+
+ ok = 1;
+
+err:
+ if (!ok) {
+ if (ret) {
+ EC_KEY_free(ret);
+ }
+ ret = NULL;
+ if (a) {
+ *a = ret;
+ }
+ }
+
+ if (priv_key) {
+ EC_PRIVATEKEY_free(priv_key);
+ }
+
+ return ret;
+}
+
+int i2d_ECPrivateKey(const EC_KEY *key, uint8_t **outp) {
+ int ret = 0, ok = 0;
+ uint8_t *buffer = NULL;
+ size_t buf_len = 0, tmp_len;
+ EC_PRIVATEKEY *priv_key = NULL;
+
+ if (key == NULL || key->group == NULL || key->priv_key == NULL) {
+ OPENSSL_PUT_ERROR(EC, i2d_ECPrivateKey, ERR_R_PASSED_NULL_PARAMETER);
+ goto err;
+ }
+
+ priv_key = EC_PRIVATEKEY_new();
+ if (priv_key == NULL) {
+ OPENSSL_PUT_ERROR(EC, i2d_ECPrivateKey, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ priv_key->version = key->version;
+
+ buf_len = BN_num_bytes(key->priv_key);
+ buffer = OPENSSL_malloc(buf_len);
+ if (buffer == NULL) {
+ OPENSSL_PUT_ERROR(EC, i2d_ECPrivateKey, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (!BN_bn2bin(key->priv_key, buffer)) {
+ OPENSSL_PUT_ERROR(EC, i2d_ECPrivateKey, ERR_R_BN_LIB);
+ goto err;
+ }
+
+ if (!M_ASN1_OCTET_STRING_set(priv_key->privateKey, buffer, buf_len)) {
+ OPENSSL_PUT_ERROR(EC, i2d_ECPrivateKey, ERR_R_ASN1_LIB);
+ goto err;
+ }
+
+ /* TODO(fork): replace this flexibility with key sensible default? */
+ if (!(key->enc_flag & EC_PKEY_NO_PARAMETERS)) {
+ if ((priv_key->parameters = ec_asn1_group2pkparameters(
+ key->group, priv_key->parameters)) == NULL) {
+ OPENSSL_PUT_ERROR(EC, i2d_ECPrivateKey, ERR_R_EC_LIB);
+ goto err;
+ }
+ }
+
+ /* TODO(fork): replace this flexibility with key sensible default? */
+ if (!(key->enc_flag & EC_PKEY_NO_PUBKEY) && key->pub_key != NULL) {
+ priv_key->publicKey = M_ASN1_BIT_STRING_new();
+ if (priv_key->publicKey == NULL) {
+ OPENSSL_PUT_ERROR(EC, i2d_ECPrivateKey, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ tmp_len = EC_POINT_point2oct(key->group, key->pub_key, key->conv_form, NULL,
+ 0, NULL);
+
+ if (tmp_len > buf_len) {
+ uint8_t *tmp_buffer = OPENSSL_realloc(buffer, tmp_len);
+ if (!tmp_buffer) {
+ OPENSSL_PUT_ERROR(EC, i2d_ECPrivateKey, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ buffer = tmp_buffer;
+ buf_len = tmp_len;
+ }
+
+ if (!EC_POINT_point2oct(key->group, key->pub_key, key->conv_form, buffer,
+ buf_len, NULL)) {
+ OPENSSL_PUT_ERROR(EC, i2d_ECPrivateKey, ERR_R_EC_LIB);
+ goto err;
+ }
+
+ priv_key->publicKey->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
+ priv_key->publicKey->flags |= ASN1_STRING_FLAG_BITS_LEFT;
+ if (!M_ASN1_BIT_STRING_set(priv_key->publicKey, buffer, buf_len)) {
+ OPENSSL_PUT_ERROR(EC, i2d_ECPrivateKey, ERR_R_ASN1_LIB);
+ goto err;
+ }
+ }
+
+ ret = i2d_EC_PRIVATEKEY(priv_key, outp);
+ if (ret == 0) {
+ OPENSSL_PUT_ERROR(EC, i2d_ECPrivateKey, ERR_R_EC_LIB);
+ goto err;
+ }
+ ok = 1;
+
+err:
+ if (buffer) {
+ OPENSSL_free(buffer);
+ }
+ if (priv_key) {
+ EC_PRIVATEKEY_free(priv_key);
+ }
+ return (ok ? ret : 0);
+}
+
+int i2d_ECParameters(const EC_KEY *key, uint8_t **outp) {
+ if (key == NULL) {
+ OPENSSL_PUT_ERROR(EC, i2d_ECParameters, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ return i2d_ECPKParameters(key->group, outp);
+}
+
+EC_KEY *d2i_ECParameters(EC_KEY **key, const uint8_t **inp, long len) {
+ EC_KEY *ret;
+
+ if (inp == NULL || *inp == NULL) {
+ OPENSSL_PUT_ERROR(EC, d2i_ECParameters, ERR_R_PASSED_NULL_PARAMETER);
+ return NULL;
+ }
+
+ if (key == NULL || *key == NULL) {
+ ret = EC_KEY_new();
+ if (ret == NULL) {
+ OPENSSL_PUT_ERROR(EC, d2i_ECParameters, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ if (key) {
+ *key = ret;
+ }
+ } else {
+ ret = *key;
+ }
+
+ if (!d2i_ECPKParameters(&ret->group, inp, len)) {
+ OPENSSL_PUT_ERROR(EC, d2i_ECParameters, ERR_R_EC_LIB);
+ return NULL;
+ }
+
+ return ret;
+}
+
+EC_KEY *o2i_ECPublicKey(EC_KEY **keyp, const uint8_t **inp, long len) {
+ EC_KEY *ret = NULL;
+
+ if (keyp == NULL || *keyp == NULL || (*keyp)->group == NULL) {
+ OPENSSL_PUT_ERROR(EC, o2i_ECPublicKey, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ ret = *keyp;
+ if (ret->pub_key == NULL &&
+ (ret->pub_key = EC_POINT_new(ret->group)) == NULL) {
+ OPENSSL_PUT_ERROR(EC, o2i_ECPublicKey, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ if (!EC_POINT_oct2point(ret->group, ret->pub_key, *inp, len, NULL)) {
+ OPENSSL_PUT_ERROR(EC, o2i_ECPublicKey, ERR_R_EC_LIB);
+ return 0;
+ }
+ /* save the point conversion form */
+ ret->conv_form = (point_conversion_form_t)(*inp[0] & ~0x01);
+ *inp += len;
+ return ret;
+}
+
+int i2o_ECPublicKey(const EC_KEY *key, uint8_t **outp) {
+ size_t buf_len = 0;
+ int new_buffer = 0;
+
+ if (key == NULL) {
+ OPENSSL_PUT_ERROR(EC, i2o_ECPublicKey, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ buf_len = EC_POINT_point2oct(key->group, key->pub_key, key->conv_form, NULL,
+ 0, NULL);
+
+ if (outp == NULL || buf_len == 0) {
+ /* out == NULL => just return the length of the octet string */
+ return buf_len;
+ }
+
+ if (*outp == NULL) {
+ *outp = OPENSSL_malloc(buf_len);
+ if (*outp == NULL) {
+ OPENSSL_PUT_ERROR(EC, i2o_ECPublicKey, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ new_buffer = 1;
+ }
+ if (!EC_POINT_point2oct(key->group, key->pub_key, key->conv_form, *outp,
+ buf_len, NULL)) {
+ OPENSSL_PUT_ERROR(EC, i2o_ECPublicKey, ERR_R_EC_LIB);
+ if (new_buffer) {
+ OPENSSL_free(*outp);
+ *outp = NULL;
+ }
+ return 0;
+ }
+
+ if (!new_buffer) {
+ *outp += buf_len;
+ }
+ return buf_len;
+}
diff --git a/src/crypto/ec/ec_error.c b/src/crypto/ec/ec_error.c
new file mode 100644
index 0000000..73807c7
--- /dev/null
+++ b/src/crypto/ec/ec_error.c
@@ -0,0 +1,107 @@
+/* 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 <openssl/err.h>
+
+#include <openssl/ec.h>
+
+const ERR_STRING_DATA EC_error_string_data[] = {
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_copy, 0), "EC_GROUP_copy"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_get_curve_GFp, 0), "EC_GROUP_get_curve_GFp"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_get_degree, 0), "EC_GROUP_get_degree"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_new_by_curve_name, 0), "EC_GROUP_new_by_curve_name"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_check_key, 0), "EC_KEY_check_key"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_copy, 0), "EC_KEY_copy"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_generate_key, 0), "EC_KEY_generate_key"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_new_method, 0), "EC_KEY_new_method"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_set_public_key_affine_coordinates, 0), "EC_KEY_set_public_key_affine_coordinates"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_add, 0), "EC_POINT_add"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_cmp, 0), "EC_POINT_cmp"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_copy, 0), "EC_POINT_copy"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_dbl, 0), "EC_POINT_dbl"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_dup, 0), "EC_POINT_dup"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_get_affine_coordinates_GFp, 0), "EC_POINT_get_affine_coordinates_GFp"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_invert, 0), "EC_POINT_invert"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_is_at_infinity, 0), "EC_POINT_is_at_infinity"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_is_on_curve, 0), "EC_POINT_is_on_curve"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_make_affine, 0), "EC_POINT_make_affine"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_new, 0), "EC_POINT_new"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_oct2point, 0), "EC_POINT_oct2point"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_point2oct, 0), "EC_POINT_point2oct"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_set_affine_coordinates_GFp, 0), "EC_POINT_set_affine_coordinates_GFp"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_set_compressed_coordinates_GFp, 0), "EC_POINT_set_compressed_coordinates_GFp"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_set_to_infinity, 0), "EC_POINT_set_to_infinity"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINTs_make_affine, 0), "EC_POINTs_make_affine"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_compute_wNAF, 0), "compute_wNAF"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_d2i_ECPKParameters, 0), "d2i_ECPKParameters"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_d2i_ECParameters, 0), "d2i_ECParameters"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_d2i_ECPrivateKey, 0), "d2i_ECPrivateKey"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ec_GFp_mont_field_decode, 0), "ec_GFp_mont_field_decode"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ec_GFp_mont_field_encode, 0), "ec_GFp_mont_field_encode"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ec_GFp_mont_field_mul, 0), "ec_GFp_mont_field_mul"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ec_GFp_mont_field_set_to_one, 0), "ec_GFp_mont_field_set_to_one"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ec_GFp_mont_field_sqr, 0), "ec_GFp_mont_field_sqr"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ec_GFp_mont_group_set_curve, 0), "ec_GFp_mont_group_set_curve"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ec_GFp_simple_group_check_discriminant, 0), "ec_GFp_simple_group_check_discriminant"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ec_GFp_simple_group_set_curve, 0), "ec_GFp_simple_group_set_curve"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ec_GFp_simple_make_affine, 0), "ec_GFp_simple_make_affine"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ec_GFp_simple_oct2point, 0), "ec_GFp_simple_oct2point"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ec_GFp_simple_point2oct, 0), "ec_GFp_simple_point2oct"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ec_GFp_simple_point_get_affine_coordinates, 0), "ec_GFp_simple_point_get_affine_coordinates"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ec_GFp_simple_point_set_affine_coordinates, 0), "ec_GFp_simple_point_set_affine_coordinates"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ec_GFp_simple_points_make_affine, 0), "ec_GFp_simple_points_make_affine"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ec_GFp_simple_set_compressed_coordinates, 0), "ec_GFp_simple_set_compressed_coordinates"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ec_asn1_group2pkparameters, 0), "ec_asn1_group2pkparameters"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ec_asn1_pkparameters2group, 0), "ec_asn1_pkparameters2group"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ec_group_new, 0), "ec_group_new"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ec_group_new_curve_GFp, 0), "ec_group_new_curve_GFp"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ec_group_new_from_data, 0), "ec_group_new_from_data"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ec_point_set_Jprojective_coordinates_GFp, 0), "ec_point_set_Jprojective_coordinates_GFp"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ec_pre_comp_new, 0), "ec_pre_comp_new"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ec_wNAF_mul, 0), "ec_wNAF_mul"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ec_wNAF_precompute_mult, 0), "ec_wNAF_precompute_mult"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_i2d_ECPKParameters, 0), "i2d_ECPKParameters"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_i2d_ECParameters, 0), "i2d_ECParameters"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_i2d_ECPrivateKey, 0), "i2d_ECPrivateKey"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_i2o_ECPublicKey, 0), "i2o_ECPublicKey"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_o2i_ECPublicKey, 0), "o2i_ECPublicKey"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_BUFFER_TOO_SMALL), "BUFFER_TOO_SMALL"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_COORDINATES_OUT_OF_RANGE), "COORDINATES_OUT_OF_RANGE"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_D2I_ECPKPARAMETERS_FAILURE), "D2I_ECPKPARAMETERS_FAILURE"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_EC_GROUP_NEW_BY_NAME_FAILURE), "EC_GROUP_NEW_BY_NAME_FAILURE"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_GF2M_NOT_SUPPORTED), "GF2M_NOT_SUPPORTED"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_GROUP2PKPARAMETERS_FAILURE), "GROUP2PKPARAMETERS_FAILURE"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_I2D_ECPKPARAMETERS_FAILURE), "I2D_ECPKPARAMETERS_FAILURE"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_INCOMPATIBLE_OBJECTS), "INCOMPATIBLE_OBJECTS"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_COMPRESSED_POINT), "INVALID_COMPRESSED_POINT"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_COMPRESSION_BIT), "INVALID_COMPRESSION_BIT"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_ENCODING), "INVALID_ENCODING"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_FIELD), "INVALID_FIELD"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_FORM), "INVALID_FORM"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_GROUP_ORDER), "INVALID_GROUP_ORDER"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_PRIVATE_KEY), "INVALID_PRIVATE_KEY"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_MISSING_PARAMETERS), "MISSING_PARAMETERS"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_MISSING_PRIVATE_KEY), "MISSING_PRIVATE_KEY"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_NON_NAMED_CURVE), "NON_NAMED_CURVE"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_NOT_INITIALIZED), "NOT_INITIALIZED"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_PKPARAMETERS2GROUP_FAILURE), "PKPARAMETERS2GROUP_FAILURE"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_POINT_AT_INFINITY), "POINT_AT_INFINITY"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_POINT_IS_NOT_ON_CURVE), "POINT_IS_NOT_ON_CURVE"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_SLOT_FULL), "SLOT_FULL"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_UNDEFINED_GENERATOR), "UNDEFINED_GENERATOR"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_UNKNOWN_GROUP), "UNKNOWN_GROUP"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_UNKNOWN_ORDER), "UNKNOWN_ORDER"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_WRONG_ORDER), "WRONG_ORDER"},
+ {0, NULL},
+};
diff --git a/src/crypto/ec/ec_key.c b/src/crypto/ec/ec_key.c
new file mode 100644
index 0000000..c8f0624
--- /dev/null
+++ b/src/crypto/ec/ec_key.c
@@ -0,0 +1,516 @@
+/* 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. */
+
+#include <openssl/ec_key.h>
+
+#include <string.h>
+
+#include <openssl/ec.h>
+#include <openssl/engine.h>
+#include <openssl/err.h>
+#include <openssl/ex_data.h>
+#include <openssl/mem.h>
+
+#include "internal.h"
+
+
+EC_KEY *EC_KEY_new(void) { return EC_KEY_new_method(NULL); }
+
+EC_KEY *EC_KEY_new_method(const ENGINE *engine) {
+ EC_KEY *ret = (EC_KEY *)OPENSSL_malloc(sizeof(EC_KEY));
+ if (ret == NULL) {
+ OPENSSL_PUT_ERROR(EC, EC_KEY_new_method, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ memset(ret, 0, sizeof(EC_KEY));
+
+ if (engine) {
+ ret->ecdsa_meth = ENGINE_get_ECDSA_method(engine);
+ }
+ if (ret->ecdsa_meth) {
+ METHOD_ref(ret->ecdsa_meth);
+ }
+
+ ret->version = 1;
+ ret->conv_form = POINT_CONVERSION_UNCOMPRESSED;
+ ret->references = 1;
+
+ if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_EC_KEY, ret, &ret->ex_data)) {
+ goto err1;
+ }
+
+ if (ret->ecdsa_meth && ret->ecdsa_meth->init && !ret->ecdsa_meth->init(ret)) {
+ goto err2;
+ }
+
+ return ret;
+
+err2:
+ CRYPTO_free_ex_data(CRYPTO_EX_INDEX_EC_KEY, ret, &ret->ex_data);
+err1:
+ if (ret->ecdsa_meth) {
+ METHOD_unref(ret->ecdsa_meth);
+ }
+ OPENSSL_free(ret);
+ return NULL;
+}
+
+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;
+ }
+ return ret;
+}
+
+void EC_KEY_free(EC_KEY *r) {
+ if (r == NULL) {
+ return;
+ }
+
+ if (CRYPTO_add(&r->references, -1, CRYPTO_LOCK_EC)) {
+ return;
+ }
+
+ if (r->ecdsa_meth) {
+ if (r->ecdsa_meth->finish) {
+ r->ecdsa_meth->finish(r);
+ }
+ METHOD_unref(r->ecdsa_meth);
+ }
+
+ if (r->group != NULL) {
+ EC_GROUP_free(r->group);
+ }
+ if (r->pub_key != NULL) {
+ EC_POINT_free(r->pub_key);
+ }
+ if (r->priv_key != NULL) {
+ BN_clear_free(r->priv_key);
+ }
+
+ CRYPTO_free_ex_data(CRYPTO_EX_INDEX_EC_KEY, r, &r->ex_data);
+
+ OPENSSL_cleanse((void *)r, sizeof(EC_KEY));
+ OPENSSL_free(r);
+}
+
+EC_KEY *EC_KEY_copy(EC_KEY *dest, const EC_KEY *src) {
+ if (dest == NULL || src == NULL) {
+ OPENSSL_PUT_ERROR(EC, EC_KEY_copy, ERR_R_PASSED_NULL_PARAMETER);
+ return NULL;
+ }
+ /* copy the parameters */
+ if (src->group) {
+ /* TODO(fork): duplicating the group seems wasteful. */
+ const EC_METHOD *meth = src->group->meth;
+ /* clear the old group */
+ if (dest->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) {
+ if (dest->pub_key) {
+ 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 method/extra data */
+ CRYPTO_free_ex_data(CRYPTO_EX_INDEX_EC_KEY, dest, &dest->ex_data);
+ if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_EC_KEY, &dest->ex_data,
+ &src->ex_data)) {
+ 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;
+
+ return dest;
+}
+
+EC_KEY *EC_KEY_dup(const EC_KEY *ec_key) {
+ EC_KEY *ret = EC_KEY_new();
+ if (ret == NULL) {
+ return NULL;
+ }
+ if (EC_KEY_copy(ret, ec_key) == NULL) {
+ EC_KEY_free(ret);
+ return NULL;
+ }
+ return ret;
+}
+
+int EC_KEY_up_ref(EC_KEY *r) {
+ return CRYPTO_add(&r->references, 1, CRYPTO_LOCK_EC) > 1;
+}
+
+int EC_KEY_is_opaque(const EC_KEY *key) {
+ return key->ecdsa_meth && (key->ecdsa_meth->flags & ECDSA_FLAG_OPAQUE);
+}
+
+const EC_GROUP *EC_KEY_get0_group(const EC_KEY *key) { return key->group; }
+
+int EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group) {
+ if (key->group != NULL) {
+ EC_GROUP_free(key->group);
+ }
+ /* TODO(fork): duplicating the group seems wasteful but see
+ * |EC_KEY_set_conv_form|. */
+ key->group = EC_GROUP_dup(group);
+ return (key->group == NULL) ? 0 : 1;
+}
+
+const BIGNUM *EC_KEY_get0_private_key(const EC_KEY *key) {
+ return key->priv_key;
+}
+
+int EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *priv_key) {
+ if (key->priv_key) {
+ BN_clear_free(key->priv_key);
+ }
+ key->priv_key = BN_dup(priv_key);
+ return (key->priv_key == NULL) ? 0 : 1;
+}
+
+const EC_POINT *EC_KEY_get0_public_key(const EC_KEY *key) {
+ return key->pub_key;
+}
+
+int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub_key) {
+ if (key->pub_key != NULL) {
+ EC_POINT_free(key->pub_key);
+ }
+ key->pub_key = EC_POINT_dup(pub_key, key->group);
+ return (key->pub_key == NULL) ? 0 : 1;
+}
+
+unsigned int EC_KEY_get_enc_flags(const EC_KEY *key) { return key->enc_flag; }
+
+void EC_KEY_set_enc_flags(EC_KEY *key, unsigned int flags) {
+ key->enc_flag = flags;
+}
+
+point_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *key) {
+ return key->conv_form;
+}
+
+void EC_KEY_set_conv_form(EC_KEY *key, point_conversion_form_t cform) {
+ key->conv_form = cform;
+}
+
+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);
+}
+
+int EC_KEY_check_key(const EC_KEY *eckey) {
+ int ok = 0;
+ BN_CTX *ctx = NULL;
+ const BIGNUM *order = NULL;
+ EC_POINT *point = NULL;
+
+ if (!eckey || !eckey->group || !eckey->pub_key) {
+ OPENSSL_PUT_ERROR(EC, EC_KEY_check_key, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ if (EC_POINT_is_at_infinity(eckey->group, eckey->pub_key)) {
+ OPENSSL_PUT_ERROR(EC, EC_KEY_check_key, EC_R_POINT_AT_INFINITY);
+ goto err;
+ }
+
+ ctx = BN_CTX_new();
+ point = EC_POINT_new(eckey->group);
+
+ if (ctx == NULL ||
+ point == NULL) {
+ goto err;
+ }
+
+ /* testing whether the pub_key is on the elliptic curve */
+ if (!EC_POINT_is_on_curve(eckey->group, eckey->pub_key, ctx)) {
+ OPENSSL_PUT_ERROR(EC, EC_KEY_check_key, EC_R_POINT_IS_NOT_ON_CURVE);
+ goto err;
+ }
+ /* testing whether pub_key * order is the point at infinity */
+ /* TODO(fork): can this be skipped if the cofactor is one or if we're about
+ * to check the private key, below? */
+ order = &eckey->group->order;
+ if (BN_is_zero(order)) {
+ OPENSSL_PUT_ERROR(EC, EC_KEY_check_key, EC_R_INVALID_GROUP_ORDER);
+ goto err;
+ }
+ if (!EC_POINT_mul(eckey->group, point, NULL, eckey->pub_key, order, ctx)) {
+ OPENSSL_PUT_ERROR(EC, EC_KEY_check_key, ERR_R_EC_LIB);
+ goto err;
+ }
+ if (!EC_POINT_is_at_infinity(eckey->group, point)) {
+ OPENSSL_PUT_ERROR(EC, EC_KEY_check_key, EC_R_WRONG_ORDER);
+ goto err;
+ }
+ /* in case the priv_key is present :
+ * check if generator * priv_key == pub_key
+ */
+ if (eckey->priv_key) {
+ if (BN_cmp(eckey->priv_key, order) >= 0) {
+ OPENSSL_PUT_ERROR(EC, EC_KEY_check_key, EC_R_WRONG_ORDER);
+ goto err;
+ }
+ if (!EC_POINT_mul(eckey->group, point, eckey->priv_key, NULL, NULL, ctx)) {
+ OPENSSL_PUT_ERROR(EC, EC_KEY_check_key, ERR_R_EC_LIB);
+ goto err;
+ }
+ if (EC_POINT_cmp(eckey->group, point, eckey->pub_key, ctx) != 0) {
+ OPENSSL_PUT_ERROR(EC, EC_KEY_check_key, EC_R_INVALID_PRIVATE_KEY);
+ goto err;
+ }
+ }
+ ok = 1;
+
+err:
+ if (ctx != NULL)
+ BN_CTX_free(ctx);
+ if (point != NULL)
+ EC_POINT_free(point);
+ return ok;
+}
+
+int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x,
+ BIGNUM *y) {
+ BN_CTX *ctx = NULL;
+ BIGNUM *tx, *ty;
+ EC_POINT *point = NULL;
+ int ok = 0;
+
+ if (!key || !key->group || !x || !y) {
+ OPENSSL_PUT_ERROR(EC, EC_KEY_set_public_key_affine_coordinates,
+ ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ ctx = BN_CTX_new();
+ point = EC_POINT_new(key->group);
+
+ if (ctx == NULL ||
+ point == NULL) {
+ goto err;
+ }
+
+ tx = BN_CTX_get(ctx);
+ ty = BN_CTX_get(ctx);
+
+ if (!EC_POINT_set_affine_coordinates_GFp(key->group, point, x, y, ctx) ||
+ !EC_POINT_get_affine_coordinates_GFp(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) || BN_cmp(y, ty)) {
+ OPENSSL_PUT_ERROR(EC, EC_KEY_set_public_key_affine_coordinates,
+ 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;
+ }
+
+ ok = 1;
+
+err:
+ if (ctx)
+ BN_CTX_free(ctx);
+ if (point)
+ EC_POINT_free(point);
+ return ok;
+}
+
+int EC_KEY_generate_key(EC_KEY *eckey) {
+ int ok = 0;
+ BN_CTX *ctx = NULL;
+ BIGNUM *priv_key = NULL, *order = NULL;
+ EC_POINT *pub_key = NULL;
+
+ if (!eckey || !eckey->group) {
+ OPENSSL_PUT_ERROR(EC, EC_KEY_generate_key, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ order = BN_new();
+ ctx = BN_CTX_new();
+
+ if (order == NULL ||
+ ctx == NULL) {
+ goto err;
+ }
+
+ if (eckey->priv_key == NULL) {
+ priv_key = BN_new();
+ if (priv_key == NULL) {
+ goto err;
+ }
+ } else {
+ priv_key = eckey->priv_key;
+ }
+
+ if (!EC_GROUP_get_order(eckey->group, order, ctx)) {
+ goto err;
+ }
+
+ do {
+ if (!BN_rand_range(priv_key, order)) {
+ goto err;
+ }
+ } while (BN_is_zero(priv_key));
+
+ if (eckey->pub_key == NULL) {
+ pub_key = EC_POINT_new(eckey->group);
+ if (pub_key == NULL) {
+ goto err;
+ }
+ } else {
+ pub_key = eckey->pub_key;
+ }
+
+ if (!EC_POINT_mul(eckey->group, pub_key, priv_key, NULL, NULL, ctx)) {
+ goto err;
+ }
+
+ eckey->priv_key = priv_key;
+ eckey->pub_key = pub_key;
+
+ ok = 1;
+
+err:
+ if (order)
+ BN_free(order);
+ if (pub_key != NULL && eckey->pub_key == NULL)
+ EC_POINT_free(pub_key);
+ if (priv_key != NULL && eckey->priv_key == NULL)
+ BN_free(priv_key);
+ if (ctx != NULL)
+ BN_CTX_free(ctx);
+ return ok;
+}
+
+int EC_KEY_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+ CRYPTO_EX_dup *dup_func,
+ CRYPTO_EX_free *free_func) {
+ return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_EC_KEY, argl, argp, new_func,
+ dup_func, free_func);
+}
+
+int EC_KEY_set_ex_data(EC_KEY *d, int idx, void *arg) {
+ return CRYPTO_set_ex_data(&d->ex_data, idx, arg);
+}
+
+void *EC_KEY_get_ex_data(const EC_KEY *d, int idx) {
+ return CRYPTO_get_ex_data(&d->ex_data, idx);
+}
diff --git a/src/crypto/ec/ec_montgomery.c b/src/crypto/ec/ec_montgomery.c
new file mode 100644
index 0000000..ab04556
--- /dev/null
+++ b/src/crypto/ec/ec_montgomery.c
@@ -0,0 +1,296 @@
+/* Originally written by Bodo Moeller and 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 <openssl/ec.h>
+
+#include <openssl/bn.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+
+#include "internal.h"
+
+
+const EC_METHOD *EC_GFp_mont_method(void) {
+ static const EC_METHOD ret = {EC_FLAGS_DEFAULT_OCT,
+ ec_GFp_mont_group_init,
+ ec_GFp_mont_group_finish,
+ ec_GFp_mont_group_clear_finish,
+ ec_GFp_mont_group_copy,
+ ec_GFp_mont_group_set_curve,
+ ec_GFp_simple_group_get_curve,
+ ec_GFp_simple_group_get_degree,
+ ec_GFp_simple_group_check_discriminant,
+ ec_GFp_simple_point_init,
+ ec_GFp_simple_point_finish,
+ ec_GFp_simple_point_clear_finish,
+ ec_GFp_simple_point_copy,
+ ec_GFp_simple_point_set_to_infinity,
+ ec_GFp_simple_set_Jprojective_coordinates_GFp,
+ ec_GFp_simple_get_Jprojective_coordinates_GFp,
+ ec_GFp_simple_point_set_affine_coordinates,
+ ec_GFp_simple_point_get_affine_coordinates,
+ 0,
+ 0,
+ 0,
+ ec_GFp_simple_add,
+ ec_GFp_simple_dbl,
+ ec_GFp_simple_invert,
+ ec_GFp_simple_is_at_infinity,
+ ec_GFp_simple_is_on_curve,
+ ec_GFp_simple_cmp,
+ ec_GFp_simple_make_affine,
+ ec_GFp_simple_points_make_affine,
+ 0 /* mul */,
+ 0 /* precompute_mult */,
+ 0 /* have_precompute_mult */,
+ ec_GFp_mont_field_mul,
+ ec_GFp_mont_field_sqr,
+ 0 /* field_div */,
+ ec_GFp_mont_field_encode,
+ ec_GFp_mont_field_decode,
+ ec_GFp_mont_field_set_to_one};
+
+ return &ret;
+}
+
+int ec_GFp_mont_group_init(EC_GROUP *group) {
+ int ok;
+
+ ok = ec_GFp_simple_group_init(group);
+ group->field_data1 = NULL;
+ group->field_data2 = NULL;
+ return ok;
+}
+
+void ec_GFp_mont_group_finish(EC_GROUP *group) {
+ if (group->field_data1 != NULL) {
+ BN_MONT_CTX_free(group->field_data1);
+ group->field_data1 = NULL;
+ }
+ if (group->field_data2 != NULL) {
+ BN_free(group->field_data2);
+ group->field_data2 = NULL;
+ }
+ ec_GFp_simple_group_finish(group);
+}
+
+void ec_GFp_mont_group_clear_finish(EC_GROUP *group) {
+ if (group->field_data1 != NULL) {
+ BN_MONT_CTX_free(group->field_data1);
+ group->field_data1 = NULL;
+ }
+ if (group->field_data2 != NULL) {
+ BN_clear_free(group->field_data2);
+ group->field_data2 = NULL;
+ }
+ ec_GFp_simple_group_clear_finish(group);
+}
+
+int ec_GFp_mont_group_copy(EC_GROUP *dest, const EC_GROUP *src) {
+ if (dest->field_data1 != NULL) {
+ BN_MONT_CTX_free(dest->field_data1);
+ dest->field_data1 = NULL;
+ }
+ if (dest->field_data2 != NULL) {
+ BN_clear_free(dest->field_data2);
+ dest->field_data2 = NULL;
+ }
+
+ if (!ec_GFp_simple_group_copy(dest, src))
+ return 0;
+
+ if (src->field_data1 != NULL) {
+ dest->field_data1 = BN_MONT_CTX_new();
+ if (dest->field_data1 == NULL)
+ return 0;
+ if (!BN_MONT_CTX_copy(dest->field_data1, src->field_data1))
+ goto err;
+ }
+ if (src->field_data2 != NULL) {
+ dest->field_data2 = BN_dup(src->field_data2);
+ if (dest->field_data2 == NULL)
+ goto err;
+ }
+
+ return 1;
+
+err:
+ if (dest->field_data1 != NULL) {
+ BN_MONT_CTX_free(dest->field_data1);
+ dest->field_data1 = NULL;
+ }
+ return 0;
+}
+
+int ec_GFp_mont_group_set_curve(EC_GROUP *group, const BIGNUM *p,
+ const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) {
+ BN_CTX *new_ctx = NULL;
+ BN_MONT_CTX *mont = NULL;
+ BIGNUM *one = NULL;
+ int ret = 0;
+
+ if (group->field_data1 != NULL) {
+ BN_MONT_CTX_free(group->field_data1);
+ group->field_data1 = NULL;
+ }
+ if (group->field_data2 != NULL) {
+ BN_free(group->field_data2);
+ group->field_data2 = NULL;
+ }
+
+ if (ctx == NULL) {
+ ctx = new_ctx = BN_CTX_new();
+ if (ctx == NULL)
+ return 0;
+ }
+
+ mont = BN_MONT_CTX_new();
+ if (mont == NULL)
+ goto err;
+ if (!BN_MONT_CTX_set(mont, p, ctx)) {
+ OPENSSL_PUT_ERROR(EC, ec_GFp_mont_group_set_curve, 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->field_data1 = mont;
+ mont = NULL;
+ group->field_data2 = one;
+ one = NULL;
+
+ ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx);
+
+ if (!ret) {
+ BN_MONT_CTX_free(group->field_data1);
+ group->field_data1 = NULL;
+ BN_free(group->field_data2);
+ group->field_data2 = NULL;
+ }
+
+err:
+ if (new_ctx != NULL)
+ BN_CTX_free(new_ctx);
+ if (mont != NULL)
+ BN_MONT_CTX_free(mont);
+ return ret;
+}
+
+int ec_GFp_mont_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
+ const BIGNUM *b, BN_CTX *ctx) {
+ if (group->field_data1 == NULL) {
+ OPENSSL_PUT_ERROR(EC, ec_GFp_mont_field_mul, EC_R_NOT_INITIALIZED);
+ return 0;
+ }
+
+ return BN_mod_mul_montgomery(r, a, b, group->field_data1, ctx);
+}
+
+int ec_GFp_mont_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
+ BN_CTX *ctx) {
+ if (group->field_data1 == NULL) {
+ OPENSSL_PUT_ERROR(EC, ec_GFp_mont_field_sqr, EC_R_NOT_INITIALIZED);
+ return 0;
+ }
+
+ return BN_mod_mul_montgomery(r, a, a, group->field_data1, ctx);
+}
+
+int ec_GFp_mont_field_encode(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
+ BN_CTX *ctx) {
+ if (group->field_data1 == NULL) {
+ OPENSSL_PUT_ERROR(EC, ec_GFp_mont_field_encode, EC_R_NOT_INITIALIZED);
+ return 0;
+ }
+
+ return BN_to_montgomery(r, a, (BN_MONT_CTX *)group->field_data1, ctx);
+}
+
+int ec_GFp_mont_field_decode(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
+ BN_CTX *ctx) {
+ if (group->field_data1 == NULL) {
+ OPENSSL_PUT_ERROR(EC, ec_GFp_mont_field_decode, EC_R_NOT_INITIALIZED);
+ return 0;
+ }
+
+ return BN_from_montgomery(r, a, group->field_data1, ctx);
+}
+
+int ec_GFp_mont_field_set_to_one(const EC_GROUP *group, BIGNUM *r,
+ BN_CTX *ctx) {
+ if (group->field_data2 == NULL) {
+ OPENSSL_PUT_ERROR(EC, ec_GFp_mont_field_set_to_one, EC_R_NOT_INITIALIZED);
+ return 0;
+ }
+
+ if (!BN_copy(r, group->field_data2))
+ return 0;
+ return 1;
+}
diff --git a/src/crypto/ec/ec_test.c b/src/crypto/ec/ec_test.c
new file mode 100644
index 0000000..8d53f87
--- /dev/null
+++ b/src/crypto/ec/ec_test.c
@@ -0,0 +1,124 @@
+/* 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 <stdio.h>
+#include <string.h>
+
+#include <openssl/bio.h>
+#include <openssl/crypto.h>
+#include <openssl/ec_key.h>
+#include <openssl/err.h>
+
+#include "internal.h"
+
+
+static const uint8_t kECKeyWithoutPublic[] = {
+ 0x30, 0x31, 0x02, 0x01, 0x01, 0x04, 0x20, 0xc6, 0xc1, 0xaa, 0xda, 0x15, 0xb0,
+ 0x76, 0x61, 0xf8, 0x14, 0x2c, 0x6c, 0xaf, 0x0f, 0xdb, 0x24, 0x1a, 0xff, 0x2e,
+ 0xfe, 0x46, 0xc0, 0x93, 0x8b, 0x74, 0xf2, 0xbc, 0xc5, 0x30, 0x52, 0xb0, 0x77,
+ 0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07,
+};
+
+int test_d2i_ECPrivateKey(void) {
+ int len, ret = 0;
+ uint8_t *out = NULL, *outp;
+ const uint8_t *inp;
+ EC_KEY *key = NULL;
+ BIGNUM *x = NULL, *y = NULL;
+ const EC_POINT *public;
+ char *x_hex = NULL, *y_hex = NULL;
+
+ inp = kECKeyWithoutPublic;
+ key = d2i_ECPrivateKey(NULL, &inp, sizeof(kECKeyWithoutPublic));
+
+ if (key == NULL || inp != kECKeyWithoutPublic + sizeof(kECKeyWithoutPublic)) {
+ fprintf(stderr, "Failed to parse private key.\n");
+ BIO_print_errors_fp(stderr);
+ goto out;
+ }
+
+ len = i2d_ECPrivateKey(key, NULL);
+ out = malloc(len);
+ outp = out;
+ if (len != i2d_ECPrivateKey(key, &outp)) {
+ fprintf(stderr, "Failed to serialize private key.\n");
+ BIO_print_errors_fp(stderr);
+ goto out;
+ }
+
+ if (0 != memcmp(out, kECKeyWithoutPublic, len)) {
+ fprintf(stderr, "Serialisation of key doesn't match original.\n");
+ goto out;
+ }
+
+ public = EC_KEY_get0_public_key(key);
+ if (public == NULL) {
+ fprintf(stderr, "Public key missing.\n");
+ goto out;
+ }
+
+ x = BN_new();
+ y = BN_new();
+ if (x == NULL || y == NULL) {
+ goto out;
+ }
+ if (!EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(key), public, x, y,
+ NULL)) {
+ fprintf(stderr, "Failed to get public key in affine coordinates.\n");
+ goto out;
+ }
+ x_hex = BN_bn2hex(x);
+ y_hex = BN_bn2hex(y);
+ if (0 != strcmp(x_hex, "c81561ecf2e54edefe6617db1c7a34a70744ddb261f269b83dacfcd2ade5a681") ||
+ 0 != strcmp(y_hex, "e0e2afa3f9b6abe4c698ef6495f1be49a3196c5056acb3763fe4507eec596e88")) {
+ fprintf(stderr, "Incorrect public key: %s %s\n", x_hex, y_hex);
+ goto out;
+ }
+
+ ret = 1;
+
+out:
+ if (key != NULL) {
+ EC_KEY_free(key);
+ }
+ if (out != NULL) {
+ free(out);
+ }
+ if (x != NULL) {
+ BN_free(x);
+ }
+ if (y != NULL) {
+ BN_free(y);
+ }
+ if (x_hex != NULL) {
+ OPENSSL_free(x_hex);
+ }
+ if (y_hex != NULL) {
+ OPENSSL_free(y_hex);
+ }
+ return ret;
+}
+
+int main(void) {
+ CRYPTO_library_init();
+ ERR_load_crypto_strings();
+
+ if (!test_d2i_ECPrivateKey()) {
+ fprintf(stderr, "failed\n");
+ return 1;
+ }
+
+ printf("PASS\n");
+ return 0;
+}
diff --git a/src/crypto/ec/example_mul.c b/src/crypto/ec/example_mul.c
new file mode 100644
index 0000000..ebb724f
--- /dev/null
+++ b/src/crypto/ec/example_mul.c
@@ -0,0 +1,133 @@
+/* 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. */
+
+#include <stdio.h>
+
+#include <openssl/bn.h>
+#include <openssl/crypto.h>
+#include <openssl/ec.h>
+#include <openssl/obj.h>
+
+
+int example_EC_POINT_mul(void) {
+ /* This example ensures that 10×∞ + G = G, in P-256. */
+ EC_GROUP *group = NULL;
+ EC_POINT *p = NULL, *result = NULL;
+ BIGNUM *n = NULL;
+ int ret = 0;
+ const EC_POINT *generator;
+
+ group = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1);
+ p = EC_POINT_new(group);
+ result = EC_POINT_new(group);
+ n = BN_new();
+
+ if (p == NULL ||
+ result == NULL ||
+ group == NULL ||
+ n == NULL ||
+ !EC_POINT_set_to_infinity(group, p) ||
+ !BN_set_word(n, 10)) {
+ goto err;
+ }
+
+ /* First check that 10×∞ = ∞. */
+ if (!EC_POINT_mul(group, result, NULL, p, n, NULL) ||
+ !EC_POINT_is_at_infinity(group, result)) {
+ goto err;
+ }
+
+ generator = EC_GROUP_get0_generator(group);
+
+ /* Now check that 10×∞ + G = G. */
+ if (!EC_POINT_mul(group, result, BN_value_one(), p, n, NULL) ||
+ EC_POINT_cmp(group, result, generator, NULL) != 0) {
+ goto err;
+ }
+
+ ret = 1;
+
+err:
+ BN_free(n);
+ EC_POINT_free(result);
+ EC_POINT_free(p);
+ EC_GROUP_free(group);
+
+ return ret;
+}
+
+int main(void) {
+ CRYPTO_library_init();
+
+ if (!example_EC_POINT_mul()) {
+ fprintf(stderr, "failed\n");
+ return 1;
+ }
+
+ printf("PASS\n");
+ return 0;
+}
diff --git a/src/crypto/ec/internal.h b/src/crypto/ec/internal.h
new file mode 100644
index 0000000..da116c4
--- /dev/null
+++ b/src/crypto/ec/internal.h
@@ -0,0 +1,380 @@
+/* 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 OPENSSL_HEADER_EC_INTERNAL_H
+#define OPENSSL_HEADER_EC_INTERNAL_H
+
+#include <openssl/base.h>
+
+#include <openssl/bn.h>
+#include <openssl/ex_data.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* Use default functions for poin2oct, oct2point and compressed coordinates */
+#define EC_FLAGS_DEFAULT_OCT 0x1
+
+typedef struct ec_method_st EC_METHOD;
+
+struct ec_method_st {
+ /* Various method flags */
+ int flags;
+
+ /* used by EC_GROUP_new, EC_GROUP_free, EC_GROUP_clear_free, EC_GROUP_copy: */
+ int (*group_init)(EC_GROUP *);
+ void (*group_finish)(EC_GROUP *);
+ void (*group_clear_finish)(EC_GROUP *);
+ int (*group_copy)(EC_GROUP *, const EC_GROUP *);
+
+ /* used by EC_GROUP_set_curve_GFp, EC_GROUP_get_curve_GFp, */
+ /* EC_GROUP_set_curve_GF2m, and EC_GROUP_get_curve_GF2m: */
+ 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 *);
+
+ /* used by EC_GROUP_get_degree: */
+ int (*group_get_degree)(const EC_GROUP *);
+
+ /* used by EC_GROUP_check: */
+ int (*group_check_discriminant)(const EC_GROUP *, BN_CTX *);
+
+ /* used by EC_POINT_new, EC_POINT_free, EC_POINT_clear_free, EC_POINT_copy: */
+ int (*point_init)(EC_POINT *);
+ void (*point_finish)(EC_POINT *);
+ void (*point_clear_finish)(EC_POINT *);
+ int (*point_copy)(EC_POINT *, const EC_POINT *);
+
+ /* used by EC_POINT_set_to_infinity,
+ * EC_POINT_set_Jprojective_coordinates_GFp,
+ * EC_POINT_get_Jprojective_coordinates_GFp,
+ * EC_POINT_set_affine_coordinates_GFp, ..._GF2m,
+ * EC_POINT_get_affine_coordinates_GFp, ..._GF2m,
+ * EC_POINT_set_compressed_coordinates_GFp, ..._GF2m:
+ */
+ int (*point_set_to_infinity)(const EC_GROUP *, EC_POINT *);
+ int (*point_set_Jprojective_coordinates_GFp)(const EC_GROUP *, EC_POINT *,
+ const BIGNUM *x, const BIGNUM *y,
+ const BIGNUM *z, BN_CTX *);
+ int (*point_get_Jprojective_coordinates_GFp)(const EC_GROUP *,
+ const EC_POINT *, BIGNUM *x,
+ BIGNUM *y, BIGNUM *z, BN_CTX *);
+ int (*point_set_affine_coordinates)(const EC_GROUP *, EC_POINT *,
+ const BIGNUM *x, const BIGNUM *y,
+ BN_CTX *);
+ 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 *);
+
+ /* used by EC_POINT_point2oct, EC_POINT_oct2point: */
+ 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 *);
+
+ /* used by EC_POINT_add, EC_POINT_dbl, ECP_POINT_invert: */
+ 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 *);
+
+ /* used by EC_POINT_is_at_infinity, EC_POINT_is_on_curve, EC_POINT_cmp: */
+ 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 *);
+
+ /* used by EC_POINT_make_affine, EC_POINTs_make_affine: */
+ int (*make_affine)(const EC_GROUP *, EC_POINT *, BN_CTX *);
+ int (*points_make_affine)(const EC_GROUP *, size_t num, EC_POINT * [],
+ BN_CTX *);
+
+ /* used by EC_POINTs_mul, EC_POINT_mul, EC_POINT_precompute_mult,
+ * EC_POINT_have_precompute_mult
+ * (default implementations are used if the 'mul' pointer is 0): */
+ int (*mul)(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
+ size_t num, const EC_POINT *points[], const BIGNUM *scalars[],
+ BN_CTX *);
+ int (*precompute_mult)(EC_GROUP *group, BN_CTX *);
+ int (*have_precompute_mult)(const EC_GROUP *group);
+
+
+ /* internal functions */
+
+ /* 'field_mul', 'field_sqr', and 'field_div' can be used by 'add' and 'dbl'
+ * so that the same implementations of point operations can be used with
+ * different optimized implementations 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 *);
+
+ int (*field_encode)(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
+ BN_CTX *); /* e.g. to Montgomery */
+ int (*field_decode)(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
+ BN_CTX *); /* e.g. from Montgomery */
+ int (*field_set_to_one)(const EC_GROUP *, BIGNUM *r, BN_CTX *);
+} /* EC_METHOD */;
+
+const EC_METHOD* EC_GFp_mont_method(void);
+
+struct ec_pre_comp_st;
+void ec_pre_comp_free(struct ec_pre_comp_st *pre_comp);
+void *ec_pre_comp_dup(struct ec_pre_comp_st *pre_comp);
+
+struct ec_group_st {
+ const EC_METHOD *meth;
+
+ EC_POINT *generator; /* optional */
+ BIGNUM order, cofactor;
+
+ int curve_name; /* optional NID for named curve */
+
+ struct ec_pre_comp_st *pre_comp;
+
+ /* The following members are handled by the method functions,
+ * even if they appear generic */
+
+ BIGNUM field; /* Field specification.
+ * For curves over GF(p), this is the modulus;
+ * for curves over GF(2^m), this is the
+ * irreducible polynomial defining the field. */
+
+ int poly[6]; /* Field specification for curves over GF(2^m).
+ * The irreducible f(t) is then of the form:
+ * t^poly[0] + t^poly[1] + ... + t^poly[k]
+ * where m = poly[0] > poly[1] > ... > poly[k] = 0.
+ * The array is terminated with poly[k+1]=-1.
+ * All elliptic curve irreducibles have at most 5
+ * non-zero terms. */
+
+ BIGNUM a, b; /* Curve coefficients.
+ * (Here the assumption is that BIGNUMs can be used
+ * or abused for all kinds of fields, not just GF(p).)
+ * For characteristic > 3, the curve is defined
+ * by a Weierstrass equation of the form
+ * y^2 = x^3 + a*x + b.
+ * For characteristic 2, the curve is defined by
+ * an equation of the form
+ * y^2 + x*y = x^3 + a*x^2 + b. */
+
+ int a_is_minus3; /* enable optimized point arithmetics for special case */
+
+ void *field_data1; /* method-specific (e.g., Montgomery structure) */
+ void *field_data2; /* method-specific */
+ int (*field_mod_func)(BIGNUM *, const BIGNUM *, const BIGNUM *,
+ BN_CTX *); /* method-specific */
+} /* EC_GROUP */;
+
+struct ec_point_st {
+ const EC_METHOD *meth;
+
+ /* All members except 'meth' are handled by the method functions,
+ * even if they appear generic */
+
+ BIGNUM X;
+ BIGNUM Y;
+ BIGNUM Z; /* Jacobian projective coordinates:
+ * (X, Y, Z) represents (X/Z^2, Y/Z^3) if Z != 0 */
+ int Z_is_one; /* enable optimized point arithmetics for special case */
+} /* EC_POINT */;
+
+EC_GROUP *ec_group_new(const EC_METHOD *meth);
+
+int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
+ size_t num, const EC_POINT *points[], const BIGNUM *scalars[],
+ BN_CTX *);
+int ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *);
+int ec_wNAF_have_precompute_mult(const EC_GROUP *group);
+
+/* method functions in simple.c */
+int ec_GFp_simple_group_init(EC_GROUP *);
+void ec_GFp_simple_group_finish(EC_GROUP *);
+void ec_GFp_simple_group_clear_finish(EC_GROUP *);
+int ec_GFp_simple_group_copy(EC_GROUP *, const EC_GROUP *);
+int ec_GFp_simple_group_set_curve(EC_GROUP *, const BIGNUM *p, const BIGNUM *a,
+ const BIGNUM *b, BN_CTX *);
+int ec_GFp_simple_group_get_curve(const EC_GROUP *, BIGNUM *p, BIGNUM *a,
+ BIGNUM *b, BN_CTX *);
+int ec_GFp_simple_group_get_degree(const EC_GROUP *);
+int ec_GFp_simple_group_check_discriminant(const EC_GROUP *, BN_CTX *);
+int ec_GFp_simple_point_init(EC_POINT *);
+void ec_GFp_simple_point_finish(EC_POINT *);
+void ec_GFp_simple_point_clear_finish(EC_POINT *);
+int ec_GFp_simple_point_copy(EC_POINT *, const EC_POINT *);
+int ec_GFp_simple_point_set_to_infinity(const EC_GROUP *, EC_POINT *);
+int ec_GFp_simple_set_Jprojective_coordinates_GFp(const EC_GROUP *, EC_POINT *,
+ const BIGNUM *x,
+ const BIGNUM *y,
+ const BIGNUM *z, BN_CTX *);
+int ec_GFp_simple_get_Jprojective_coordinates_GFp(const EC_GROUP *,
+ const EC_POINT *, BIGNUM *x,
+ BIGNUM *y, BIGNUM *z,
+ 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 *);
+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 *);
+
+/* method functions in montgomery.c */
+int ec_GFp_mont_group_init(EC_GROUP *);
+int ec_GFp_mont_group_set_curve(EC_GROUP *, const BIGNUM *p, const BIGNUM *a,
+ const BIGNUM *b, BN_CTX *);
+void ec_GFp_mont_group_finish(EC_GROUP *);
+void ec_GFp_mont_group_clear_finish(EC_GROUP *);
+int ec_GFp_mont_group_copy(EC_GROUP *, const EC_GROUP *);
+int ec_GFp_mont_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
+ const BIGNUM *b, BN_CTX *);
+int ec_GFp_mont_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
+ BN_CTX *);
+int ec_GFp_mont_field_encode(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
+ BN_CTX *);
+int ec_GFp_mont_field_decode(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
+ BN_CTX *);
+int ec_GFp_mont_field_set_to_one(const EC_GROUP *, BIGNUM *r, BN_CTX *);
+
+int 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);
+
+struct ec_key_st {
+ 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;
+
+ ECDSA_METHOD *ecdsa_meth;
+
+ CRYPTO_EX_DATA ex_data;
+} /* EC_KEY */;
+
+/* curve_data contains data about a built-in elliptic curve. */
+struct curve_data {
+ /* comment is a human-readable string describing the curve. */
+ const char *comment;
+ /* param_len is the number of bytes needed to store a field element. */
+ uint8_t param_len;
+ /* cofactor is the cofactor of the group (i.e. the number of elements in the
+ * group divided by the size of the main subgroup. */
+ uint8_t cofactor; /* promoted to BN_ULONG */
+ /* data points to an array of 6*|param_len| bytes which hold the field
+ * elements of the following (in big-endian order): prime, a, b, generator x,
+ * generator y, order. */
+ const uint8_t data[];
+};
+
+struct built_in_curve {
+ int nid;
+ const struct curve_data *data;
+ const EC_METHOD *(*method)(void);
+};
+
+/* OPENSSL_built_in_curves is terminated with an entry where |nid| is
+ * |NID_undef|. */
+extern const struct built_in_curve OPENSSL_built_in_curves[];
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_EC_INTERNAL_H */
diff --git a/src/crypto/ec/oct.c b/src/crypto/ec/oct.c
new file mode 100644
index 0000000..c4729ef
--- /dev/null
+++ b/src/crypto/ec/oct.c
@@ -0,0 +1,476 @@
+/* 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. */
+
+#include <openssl/ec.h>
+
+#include <openssl/bn.h>
+#include <openssl/err.h>
+
+#include "internal.h"
+
+
+static size_t ec_GFp_simple_point2oct(const EC_GROUP *group,
+ const EC_POINT *point,
+ point_conversion_form_t form,
+ uint8_t *buf, size_t len, BN_CTX *ctx) {
+ size_t ret;
+ BN_CTX *new_ctx = NULL;
+ int used_ctx = 0;
+ BIGNUM *x, *y;
+ size_t field_len, i;
+
+ if ((form != POINT_CONVERSION_COMPRESSED) &&
+ (form != POINT_CONVERSION_UNCOMPRESSED)) {
+ OPENSSL_PUT_ERROR(EC, ec_GFp_simple_point2oct, EC_R_INVALID_FORM);
+ goto err;
+ }
+
+ if (EC_POINT_is_at_infinity(group, point)) {
+ /* encodes to a single 0 octet */
+ if (buf != NULL) {
+ if (len < 1) {
+ OPENSSL_PUT_ERROR(EC, ec_GFp_simple_point2oct, 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;
+
+ /* if 'buf' is NULL, just return required length */
+ if (buf != NULL) {
+ if (len < ret) {
+ OPENSSL_PUT_ERROR(EC, ec_GFp_simple_point2oct, EC_R_BUFFER_TOO_SMALL);
+ goto err;
+ }
+
+ if (ctx == NULL) {
+ ctx = new_ctx = BN_CTX_new();
+ if (ctx == NULL) {
+ return 0;
+ }
+ }
+
+ BN_CTX_start(ctx);
+ used_ctx = 1;
+ x = BN_CTX_get(ctx);
+ y = BN_CTX_get(ctx);
+ if (y == NULL) {
+ goto err;
+ }
+
+ if (!EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx)) {
+ goto err;
+ }
+
+ if ((form == POINT_CONVERSION_COMPRESSED) &&
+ BN_is_odd(y)) {
+ buf[0] = form + 1;
+ } else {
+ buf[0] = form;
+ }
+ i = 1;
+
+ if (!BN_bn2bin_padded(buf + i, field_len, x)) {
+ OPENSSL_PUT_ERROR(EC, ec_GFp_simple_point2oct, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ i += field_len;
+
+ if (form == POINT_CONVERSION_UNCOMPRESSED) {
+ if (!BN_bn2bin_padded(buf + i, field_len, y)) {
+ OPENSSL_PUT_ERROR(EC, ec_GFp_simple_point2oct, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ i += field_len;
+ }
+
+ if (i != ret) {
+ OPENSSL_PUT_ERROR(EC, ec_GFp_simple_point2oct, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ }
+
+ if (used_ctx) {
+ BN_CTX_end(ctx);
+ }
+ if (new_ctx != NULL) {
+ BN_CTX_free(new_ctx);
+ }
+ return ret;
+
+err:
+ if (used_ctx) {
+ BN_CTX_end(ctx);
+ }
+ if (new_ctx != NULL) {
+ BN_CTX_free(new_ctx);
+ }
+ return 0;
+}
+
+
+static int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
+ const uint8_t *buf, size_t len,
+ BN_CTX *ctx) {
+ point_conversion_form_t form;
+ int y_bit;
+ BN_CTX *new_ctx = NULL;
+ BIGNUM *x, *y;
+ size_t field_len, enc_len;
+ int ret = 0;
+
+ if (len == 0) {
+ OPENSSL_PUT_ERROR(EC, ec_GFp_simple_oct2point, 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)) {
+ OPENSSL_PUT_ERROR(EC, ec_GFp_simple_oct2point, EC_R_INVALID_ENCODING);
+ return 0;
+ }
+ if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit) {
+ OPENSSL_PUT_ERROR(EC, ec_GFp_simple_oct2point, EC_R_INVALID_ENCODING);
+ return 0;
+ }
+
+ if (form == 0) {
+ if (len != 1) {
+ OPENSSL_PUT_ERROR(EC, ec_GFp_simple_oct2point, 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) {
+ OPENSSL_PUT_ERROR(EC, ec_GFp_simple_oct2point, EC_R_INVALID_ENCODING);
+ return 0;
+ }
+
+ if (ctx == NULL) {
+ ctx = new_ctx = BN_CTX_new();
+ if (ctx == NULL)
+ return 0;
+ }
+
+ BN_CTX_start(ctx);
+ x = BN_CTX_get(ctx);
+ y = BN_CTX_get(ctx);
+ if (y == NULL)
+ goto err;
+
+ if (!BN_bin2bn(buf + 1, field_len, x))
+ goto err;
+ if (BN_ucmp(x, &group->field) >= 0) {
+ OPENSSL_PUT_ERROR(EC, ec_GFp_simple_oct2point, EC_R_INVALID_ENCODING);
+ goto err;
+ }
+
+ if (form == POINT_CONVERSION_COMPRESSED) {
+ if (!EC_POINT_set_compressed_coordinates_GFp(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) {
+ OPENSSL_PUT_ERROR(EC, ec_GFp_simple_oct2point, EC_R_INVALID_ENCODING);
+ goto err;
+ }
+
+ if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx))
+ goto err;
+ }
+
+ if (!EC_POINT_is_on_curve(group, point, ctx)) /* test required by X9.62 */
+ {
+ OPENSSL_PUT_ERROR(EC, ec_GFp_simple_oct2point, EC_R_POINT_IS_NOT_ON_CURVE);
+ goto err;
+ }
+
+ ret = 1;
+
+err:
+ BN_CTX_end(ctx);
+ if (new_ctx != NULL)
+ BN_CTX_free(new_ctx);
+ return ret;
+}
+
+int EC_POINT_oct2point(const EC_GROUP *group, EC_POINT *point,
+ const uint8_t *buf, size_t len, BN_CTX *ctx) {
+ if (group->meth->oct2point == 0 &&
+ !(group->meth->flags & EC_FLAGS_DEFAULT_OCT)) {
+ OPENSSL_PUT_ERROR(EC, EC_POINT_oct2point,
+ ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return 0;
+ }
+ if (group->meth != point->meth) {
+ OPENSSL_PUT_ERROR(EC, EC_POINT_oct2point, EC_R_INCOMPATIBLE_OBJECTS);
+ return 0;
+ }
+ if (group->meth->flags & EC_FLAGS_DEFAULT_OCT) {
+ return ec_GFp_simple_oct2point(group, point, buf, len, ctx);
+ }
+
+ return group->meth->oct2point(group, point, buf, len, ctx);
+}
+
+size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *point,
+ point_conversion_form_t form, uint8_t *buf,
+ size_t len, BN_CTX *ctx) {
+ if (group->meth->point2oct == 0 &&
+ !(group->meth->flags & EC_FLAGS_DEFAULT_OCT)) {
+ OPENSSL_PUT_ERROR(EC, EC_POINT_point2oct,
+ ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return 0;
+ }
+ if (group->meth != point->meth) {
+ OPENSSL_PUT_ERROR(EC, EC_POINT_point2oct, EC_R_INCOMPATIBLE_OBJECTS);
+ return 0;
+ }
+ if (group->meth->flags & EC_FLAGS_DEFAULT_OCT) {
+ return ec_GFp_simple_point2oct(group, point, form, buf, len, ctx);
+ }
+
+ return group->meth->point2oct(group, point, form, buf, len, ctx);
+}
+
+int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group,
+ EC_POINT *point, const BIGNUM *x_,
+ int y_bit, BN_CTX *ctx) {
+ BN_CTX *new_ctx = NULL;
+ BIGNUM *tmp1, *tmp2, *x, *y;
+ int ret = 0;
+
+ ERR_clear_error();
+
+ if (ctx == NULL) {
+ ctx = new_ctx = BN_CTX_new();
+ if (ctx == NULL) {
+ return 0;
+ }
+ }
+
+ y_bit = (y_bit != 0);
+
+ BN_CTX_start(ctx);
+ tmp1 = BN_CTX_get(ctx);
+ tmp2 = BN_CTX_get(ctx);
+ x = BN_CTX_get(ctx);
+ y = BN_CTX_get(ctx);
+ if (y == 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 == 0) {
+ /* field_{sqr,mul} work on standard representation */
+ if (!group->meth->field_sqr(group, tmp2, x_, ctx) ||
+ !group->meth->field_mul(group, tmp1, tmp2, x_, ctx)) {
+ goto err;
+ }
+ } else {
+ if (!BN_mod_sqr(tmp2, x_, &group->field, ctx) ||
+ !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) ||
+ !BN_mod_add_quick(tmp2, tmp2, x, &group->field) ||
+ !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) ||
+ !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) {
+ if (!group->meth->field_decode(group, tmp2, &group->b, ctx) ||
+ !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();
+ OPENSSL_PUT_ERROR(EC, ec_GFp_simple_set_compressed_coordinates, EC_R_INVALID_COMPRESSED_POINT);
+ } else {
+ OPENSSL_PUT_ERROR(EC, ec_GFp_simple_set_compressed_coordinates, ERR_R_BN_LIB);
+ }
+ goto err;
+ }
+
+ if (y_bit != BN_is_odd(y)) {
+ if (BN_is_zero(y)) {
+ int kron;
+
+ kron = BN_kronecker(x, &group->field, ctx);
+ if (kron == -2) {
+ goto err;
+ }
+
+ if (kron == 1) {
+ OPENSSL_PUT_ERROR(EC, ec_GFp_simple_set_compressed_coordinates,
+ EC_R_INVALID_COMPRESSION_BIT);
+ } else {
+ /* BN_mod_sqrt() should have cought this error (not a square) */
+ OPENSSL_PUT_ERROR(EC, ec_GFp_simple_set_compressed_coordinates,
+ EC_R_INVALID_COMPRESSED_POINT);
+ }
+ goto err;
+ }
+ if (!BN_usub(y, &group->field, y)) {
+ goto err;
+ }
+ }
+ if (y_bit != BN_is_odd(y)) {
+ OPENSSL_PUT_ERROR(EC, ec_GFp_simple_set_compressed_coordinates,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx))
+ goto err;
+
+ ret = 1;
+
+err:
+ BN_CTX_end(ctx);
+ if (new_ctx != NULL)
+ BN_CTX_free(new_ctx);
+ return ret;
+}
+
+int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group,
+ EC_POINT *point, const BIGNUM *x,
+ int y_bit, BN_CTX *ctx) {
+ if (group->meth->point_set_compressed_coordinates == 0 &&
+ !(group->meth->flags & EC_FLAGS_DEFAULT_OCT)) {
+ OPENSSL_PUT_ERROR(EC, EC_POINT_set_compressed_coordinates_GFp,
+ ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return 0;
+ }
+ if (group->meth != point->meth) {
+ OPENSSL_PUT_ERROR(EC, EC_POINT_set_compressed_coordinates_GFp,
+ EC_R_INCOMPATIBLE_OBJECTS);
+ return 0;
+ }
+ if (group->meth->flags & EC_FLAGS_DEFAULT_OCT) {
+ return ec_GFp_simple_set_compressed_coordinates(group, point, x, y_bit,
+ ctx);
+ }
+ return group->meth->point_set_compressed_coordinates(group, point, x, y_bit,
+ ctx);
+}
diff --git a/src/crypto/ec/simple.c b/src/crypto/ec/simple.c
new file mode 100644
index 0000000..b3f96fa
--- /dev/null
+++ b/src/crypto/ec/simple.c
@@ -0,0 +1,1362 @@
+/* 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. */
+
+#include <openssl/ec.h>
+
+#include <string.h>
+
+#include <openssl/bn.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+
+#include "internal.h"
+
+
+const EC_METHOD *EC_GFp_simple_method(void) {
+ static const EC_METHOD ret = {EC_FLAGS_DEFAULT_OCT,
+ ec_GFp_simple_group_init,
+ ec_GFp_simple_group_finish,
+ ec_GFp_simple_group_clear_finish,
+ ec_GFp_simple_group_copy,
+ ec_GFp_simple_group_set_curve,
+ ec_GFp_simple_group_get_curve,
+ ec_GFp_simple_group_get_degree,
+ ec_GFp_simple_group_check_discriminant,
+ ec_GFp_simple_point_init,
+ ec_GFp_simple_point_finish,
+ ec_GFp_simple_point_clear_finish,
+ ec_GFp_simple_point_copy,
+ ec_GFp_simple_point_set_to_infinity,
+ ec_GFp_simple_set_Jprojective_coordinates_GFp,
+ ec_GFp_simple_get_Jprojective_coordinates_GFp,
+ ec_GFp_simple_point_set_affine_coordinates,
+ ec_GFp_simple_point_get_affine_coordinates,
+ 0,
+ 0,
+ 0,
+ ec_GFp_simple_add,
+ ec_GFp_simple_dbl,
+ ec_GFp_simple_invert,
+ ec_GFp_simple_is_at_infinity,
+ ec_GFp_simple_is_on_curve,
+ ec_GFp_simple_cmp,
+ ec_GFp_simple_make_affine,
+ ec_GFp_simple_points_make_affine,
+ 0 /* mul */,
+ 0 /* precompute_mult */,
+ 0 /* have_precompute_mult */,
+ ec_GFp_simple_field_mul,
+ ec_GFp_simple_field_sqr,
+ 0 /* field_div */,
+ 0 /* field_encode */,
+ 0 /* field_decode */,
+ 0 /* field_set_to_one */};
+
+ return &ret;
+}
+
+
+/* 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);
+}
+
+void ec_GFp_simple_group_clear_finish(EC_GROUP *group) {
+ BN_clear_free(&group->field);
+ BN_clear_free(&group->a);
+ BN_clear_free(&group->b);
+}
+
+int ec_GFp_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src) {
+ if (!BN_copy(&dest->field, &src->field) ||
+ !BN_copy(&dest->a, &src->a) ||
+ !BN_copy(&dest->b, &src->b)) {
+ return 0;
+ }
+
+ dest->a_is_minus3 = src->a_is_minus3;
+ return 1;
+}
+
+int ec_GFp_simple_group_set_curve(EC_GROUP *group, const BIGNUM *p,
+ const BIGNUM *a, const BIGNUM *b,
+ BN_CTX *ctx) {
+ int ret = 0;
+ BN_CTX *new_ctx = NULL;
+ BIGNUM *tmp_a;
+
+ /* p must be a prime > 3 */
+ if (BN_num_bits(p) <= 2 || !BN_is_odd(p)) {
+ OPENSSL_PUT_ERROR(EC, ec_GFp_simple_group_set_curve, EC_R_INVALID_FIELD);
+ return 0;
+ }
+
+ if (ctx == NULL) {
+ ctx = new_ctx = BN_CTX_new();
+ if (ctx == NULL)
+ return 0;
+ }
+
+ BN_CTX_start(ctx);
+ tmp_a = BN_CTX_get(ctx);
+ if (tmp_a == NULL)
+ goto err;
+
+ /* group->field */
+ if (!BN_copy(&group->field, p))
+ goto err;
+ BN_set_negative(&group->field, 0);
+
+ /* group->a */
+ if (!BN_nnmod(tmp_a, a, p, ctx))
+ goto err;
+ if (group->meth->field_encode) {
+ if (!group->meth->field_encode(group, &group->a, tmp_a, ctx))
+ goto err;
+ } else if (!BN_copy(&group->a, tmp_a))
+ goto err;
+
+ /* group->b */
+ if (!BN_nnmod(&group->b, b, p, ctx))
+ goto err;
+ if (group->meth->field_encode)
+ if (!group->meth->field_encode(group, &group->b, &group->b, ctx))
+ goto err;
+
+ /* group->a_is_minus3 */
+ if (!BN_add_word(tmp_a, 3))
+ goto err;
+ group->a_is_minus3 = (0 == BN_cmp(tmp_a, &group->field));
+
+ ret = 1;
+
+err:
+ BN_CTX_end(ctx);
+ if (new_ctx != NULL)
+ BN_CTX_free(new_ctx);
+ return ret;
+}
+
+int ec_GFp_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,
+ BIGNUM *b, BN_CTX *ctx) {
+ int ret = 0;
+ BN_CTX *new_ctx = NULL;
+
+ if (p != NULL) {
+ if (!BN_copy(p, &group->field))
+ return 0;
+ }
+
+ if (a != NULL || b != NULL) {
+ if (group->meth->field_decode) {
+ if (ctx == NULL) {
+ ctx = new_ctx = BN_CTX_new();
+ if (ctx == NULL)
+ return 0;
+ }
+ if (a != NULL) {
+ if (!group->meth->field_decode(group, a, &group->a, ctx))
+ goto err;
+ }
+ if (b != NULL) {
+ if (!group->meth->field_decode(group, b, &group->b, ctx))
+ goto err;
+ }
+ } else {
+ if (a != NULL) {
+ if (!BN_copy(a, &group->a))
+ goto err;
+ }
+ if (b != NULL) {
+ if (!BN_copy(b, &group->b))
+ goto err;
+ }
+ }
+ }
+
+ ret = 1;
+
+err:
+ if (new_ctx)
+ BN_CTX_free(new_ctx);
+ return ret;
+}
+
+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) {
+ int ret = 0;
+ BIGNUM *a, *b, *order, *tmp_1, *tmp_2;
+ const BIGNUM *p = &group->field;
+ BN_CTX *new_ctx = NULL;
+
+ if (ctx == NULL) {
+ ctx = new_ctx = BN_CTX_new();
+ if (ctx == NULL) {
+ OPENSSL_PUT_ERROR(EC, ec_GFp_simple_group_check_discriminant,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+ BN_CTX_start(ctx);
+ a = BN_CTX_get(ctx);
+ b = BN_CTX_get(ctx);
+ tmp_1 = BN_CTX_get(ctx);
+ tmp_2 = BN_CTX_get(ctx);
+ order = BN_CTX_get(ctx);
+ if (order == NULL)
+ goto err;
+
+ if (group->meth->field_decode) {
+ if (!group->meth->field_decode(group, a, &group->a, ctx))
+ goto err;
+ if (!group->meth->field_decode(group, b, &group->b, ctx))
+ goto err;
+ } else {
+ if (!BN_copy(a, &group->a))
+ goto err;
+ if (!BN_copy(b, &group->b))
+ goto err;
+ }
+
+ /* check the discriminant:
+ * y^2 = x^3 + a*x + b is an elliptic curve <=> 4*a^3 + 27*b^2 != 0 (mod p)
+ * 0 =< a, b < p */
+ if (BN_is_zero(a)) {
+ if (BN_is_zero(b))
+ goto err;
+ } else if (!BN_is_zero(b)) {
+ if (!BN_mod_sqr(tmp_1, a, p, ctx))
+ goto err;
+ if (!BN_mod_mul(tmp_2, tmp_1, a, p, ctx))
+ goto err;
+ if (!BN_lshift(tmp_1, tmp_2, 2))
+ goto err;
+ /* tmp_1 = 4*a^3 */
+
+ if (!BN_mod_sqr(tmp_2, b, p, ctx))
+ goto err;
+ if (!BN_mul_word(tmp_2, 27))
+ goto err;
+ /* tmp_2 = 27*b^2 */
+
+ if (!BN_mod_add(a, tmp_1, tmp_2, p, ctx))
+ goto err;
+ if (BN_is_zero(a))
+ goto err;
+ }
+ ret = 1;
+
+err:
+ if (ctx != NULL)
+ BN_CTX_end(ctx);
+ if (new_ctx != NULL)
+ BN_CTX_free(new_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);
+}
+
+void ec_GFp_simple_point_clear_finish(EC_POINT *point) {
+ BN_clear_free(&point->X);
+ BN_clear_free(&point->Y);
+ BN_clear_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_GFp(
+ const EC_GROUP *group, EC_POINT *point, const BIGNUM *x, const BIGNUM *y,
+ const BIGNUM *z, BN_CTX *ctx) {
+ BN_CTX *new_ctx = NULL;
+ int ret = 0;
+
+ if (ctx == NULL) {
+ ctx = new_ctx = BN_CTX_new();
+ if (ctx == NULL)
+ return 0;
+ }
+
+ if (x != NULL) {
+ if (!BN_nnmod(&point->X, x, &group->field, ctx))
+ goto err;
+ if (group->meth->field_encode) {
+ if (!group->meth->field_encode(group, &point->X, &point->X, ctx))
+ goto err;
+ }
+ }
+
+ if (y != NULL) {
+ if (!BN_nnmod(&point->Y, y, &group->field, ctx))
+ goto err;
+ if (group->meth->field_encode) {
+ if (!group->meth->field_encode(group, &point->Y, &point->Y, ctx))
+ goto err;
+ }
+ }
+
+ if (z != NULL) {
+ int Z_is_one;
+
+ if (!BN_nnmod(&point->Z, z, &group->field, ctx))
+ goto err;
+ Z_is_one = BN_is_one(&point->Z);
+ if (group->meth->field_encode) {
+ if (Z_is_one && (group->meth->field_set_to_one != 0)) {
+ if (!group->meth->field_set_to_one(group, &point->Z, ctx))
+ goto err;
+ } else {
+ if (!group->meth->field_encode(group, &point->Z, &point->Z, ctx))
+ goto err;
+ }
+ }
+ point->Z_is_one = Z_is_one;
+ }
+
+ ret = 1;
+
+err:
+ if (new_ctx != NULL)
+ BN_CTX_free(new_ctx);
+ return ret;
+}
+
+int ec_GFp_simple_get_Jprojective_coordinates_GFp(const EC_GROUP *group,
+ const EC_POINT *point,
+ BIGNUM *x, BIGNUM *y,
+ BIGNUM *z, BN_CTX *ctx) {
+ BN_CTX *new_ctx = NULL;
+ int ret = 0;
+
+ if (group->meth->field_decode != 0) {
+ if (ctx == NULL) {
+ ctx = new_ctx = BN_CTX_new();
+ if (ctx == NULL)
+ return 0;
+ }
+
+ if (x != NULL) {
+ if (!group->meth->field_decode(group, x, &point->X, ctx))
+ goto err;
+ }
+ if (y != NULL) {
+ if (!group->meth->field_decode(group, y, &point->Y, ctx))
+ goto err;
+ }
+ if (z != NULL) {
+ if (!group->meth->field_decode(group, z, &point->Z, ctx))
+ goto err;
+ }
+ } else {
+ if (x != NULL) {
+ if (!BN_copy(x, &point->X))
+ goto err;
+ }
+ if (y != NULL) {
+ if (!BN_copy(y, &point->Y))
+ goto err;
+ }
+ if (z != NULL) {
+ if (!BN_copy(z, &point->Z))
+ goto err;
+ }
+ }
+
+ ret = 1;
+
+err:
+ if (new_ctx != NULL)
+ BN_CTX_free(new_ctx);
+ 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 */
+ OPENSSL_PUT_ERROR(EC, ec_GFp_simple_point_set_affine_coordinates,
+ ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ return ec_point_set_Jprojective_coordinates_GFp(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) {
+ BN_CTX *new_ctx = NULL;
+ BIGNUM *Z, *Z_1, *Z_2, *Z_3;
+ const BIGNUM *Z_;
+ int ret = 0;
+
+ if (EC_POINT_is_at_infinity(group, point)) {
+ OPENSSL_PUT_ERROR(EC, ec_GFp_simple_point_get_affine_coordinates,
+ EC_R_POINT_AT_INFINITY);
+ return 0;
+ }
+
+ if (ctx == NULL) {
+ ctx = new_ctx = BN_CTX_new();
+ if (ctx == NULL)
+ return 0;
+ }
+
+ BN_CTX_start(ctx);
+ Z = BN_CTX_get(ctx);
+ Z_1 = BN_CTX_get(ctx);
+ Z_2 = BN_CTX_get(ctx);
+ Z_3 = BN_CTX_get(ctx);
+ if (Z_3 == NULL)
+ goto err;
+
+ /* transform (X, Y, Z) into (x, y) := (X/Z^2, Y/Z^3) */
+
+ if (group->meth->field_decode) {
+ if (!group->meth->field_decode(group, Z, &point->Z, ctx))
+ goto err;
+ Z_ = Z;
+ } else {
+ Z_ = &point->Z;
+ }
+
+ if (BN_is_one(Z_)) {
+ if (group->meth->field_decode) {
+ if (x != NULL) {
+ if (!group->meth->field_decode(group, x, &point->X, ctx))
+ goto err;
+ }
+ if (y != NULL) {
+ if (!group->meth->field_decode(group, y, &point->Y, ctx))
+ goto err;
+ }
+ } else {
+ if (x != NULL) {
+ if (!BN_copy(x, &point->X))
+ goto err;
+ }
+ if (y != NULL) {
+ if (!BN_copy(y, &point->Y))
+ goto err;
+ }
+ }
+ } else {
+ if (!BN_mod_inverse(Z_1, Z_, &group->field, ctx)) {
+ OPENSSL_PUT_ERROR(EC, ec_GFp_simple_point_get_affine_coordinates,
+ ERR_R_BN_LIB);
+ goto err;
+ }
+
+ if (group->meth->field_encode == 0) {
+ /* 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 == 0) {
+ /* 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;
+ }
+ }
+
+ ret = 1;
+
+err:
+ BN_CTX_end(ctx);
+ if (new_ctx != NULL)
+ BN_CTX_free(new_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 *);
+ const BIGNUM *p;
+ BN_CTX *new_ctx = NULL;
+ BIGNUM *n0, *n1, *n2, *n3, *n4, *n5, *n6;
+ int ret = 0;
+
+ if (a == b)
+ return EC_POINT_dbl(group, r, a, ctx);
+ if (EC_POINT_is_at_infinity(group, a))
+ return EC_POINT_copy(r, b);
+ if (EC_POINT_is_at_infinity(group, b))
+ return EC_POINT_copy(r, a);
+
+ field_mul = group->meth->field_mul;
+ field_sqr = group->meth->field_sqr;
+ p = &group->field;
+
+ if (ctx == NULL) {
+ ctx = new_ctx = BN_CTX_new();
+ if (ctx == NULL)
+ return 0;
+ }
+
+ BN_CTX_start(ctx);
+ n0 = BN_CTX_get(ctx);
+ n1 = BN_CTX_get(ctx);
+ n2 = BN_CTX_get(ctx);
+ n3 = BN_CTX_get(ctx);
+ n4 = BN_CTX_get(ctx);
+ n5 = BN_CTX_get(ctx);
+ n6 = BN_CTX_get(ctx);
+ if (n6 == 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:
+ if (ctx) /* otherwise we already called BN_CTX_end */
+ BN_CTX_end(ctx);
+ if (new_ctx != NULL)
+ BN_CTX_free(new_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;
+ BN_CTX *new_ctx = NULL;
+ BIGNUM *n0, *n1, *n2, *n3;
+ int ret = 0;
+
+ if (EC_POINT_is_at_infinity(group, a)) {
+ BN_zero(&r->Z);
+ r->Z_is_one = 0;
+ return 1;
+ }
+
+ field_mul = group->meth->field_mul;
+ field_sqr = group->meth->field_sqr;
+ p = &group->field;
+
+ if (ctx == NULL) {
+ ctx = new_ctx = BN_CTX_new();
+ if (ctx == NULL)
+ return 0;
+ }
+
+ BN_CTX_start(ctx);
+ n0 = BN_CTX_get(ctx);
+ n1 = BN_CTX_get(ctx);
+ n2 = BN_CTX_get(ctx);
+ n3 = BN_CTX_get(ctx);
+ if (n3 == 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);
+ if (new_ctx != NULL)
+ BN_CTX_free(new_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) || 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 !point->Z_is_one && 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;
+ BN_CTX *new_ctx = NULL;
+ BIGNUM *rh, *tmp, *Z4, *Z6;
+ int ret = -1;
+
+ if (EC_POINT_is_at_infinity(group, point))
+ return 1;
+
+ field_mul = group->meth->field_mul;
+ field_sqr = group->meth->field_sqr;
+ p = &group->field;
+
+ if (ctx == NULL) {
+ ctx = new_ctx = BN_CTX_new();
+ if (ctx == NULL)
+ return -1;
+ }
+
+ BN_CTX_start(ctx);
+ rh = BN_CTX_get(ctx);
+ tmp = BN_CTX_get(ctx);
+ Z4 = BN_CTX_get(ctx);
+ Z6 = BN_CTX_get(ctx);
+ if (Z6 == 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);
+ if (new_ctx != NULL)
+ BN_CTX_free(new_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 *);
+ BN_CTX *new_ctx = NULL;
+ BIGNUM *tmp1, *tmp2, *Za23, *Zb23;
+ const BIGNUM *tmp1_, *tmp2_;
+ int ret = -1;
+
+ if (EC_POINT_is_at_infinity(group, a)) {
+ return EC_POINT_is_at_infinity(group, b) ? 0 : 1;
+ }
+
+ if (EC_POINT_is_at_infinity(group, b))
+ 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;
+
+ if (ctx == NULL) {
+ ctx = new_ctx = BN_CTX_new();
+ if (ctx == NULL)
+ return -1;
+ }
+
+ BN_CTX_start(ctx);
+ tmp1 = BN_CTX_get(ctx);
+ tmp2 = BN_CTX_get(ctx);
+ Za23 = BN_CTX_get(ctx);
+ Zb23 = BN_CTX_get(ctx);
+ if (Zb23 == 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);
+ if (new_ctx != NULL)
+ BN_CTX_free(new_ctx);
+ return ret;
+}
+
+int ec_GFp_simple_make_affine(const EC_GROUP *group, EC_POINT *point,
+ BN_CTX *ctx) {
+ BN_CTX *new_ctx = NULL;
+ BIGNUM *x, *y;
+ int ret = 0;
+
+ if (point->Z_is_one || EC_POINT_is_at_infinity(group, point))
+ return 1;
+
+ if (ctx == NULL) {
+ ctx = new_ctx = BN_CTX_new();
+ if (ctx == NULL)
+ return 0;
+ }
+
+ BN_CTX_start(ctx);
+ x = BN_CTX_get(ctx);
+ y = BN_CTX_get(ctx);
+ if (y == NULL)
+ goto err;
+
+ if (!EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx))
+ goto err;
+ if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx))
+ goto err;
+ if (!point->Z_is_one) {
+ OPENSSL_PUT_ERROR(EC, ec_GFp_simple_make_affine, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ ret = 1;
+
+err:
+ BN_CTX_end(ctx);
+ if (new_ctx != NULL)
+ BN_CTX_free(new_ctx);
+ return ret;
+}
+
+int ec_GFp_simple_points_make_affine(const EC_GROUP *group, size_t num,
+ EC_POINT *points[], BN_CTX *ctx) {
+ BN_CTX *new_ctx = NULL;
+ BIGNUM *tmp, *tmp_Z;
+ BIGNUM **prod_Z = NULL;
+ size_t i;
+ int ret = 0;
+
+ if (num == 0) {
+ return 1;
+ }
+
+ if (ctx == NULL) {
+ ctx = new_ctx = BN_CTX_new();
+ if (ctx == NULL) {
+ return 0;
+ }
+ }
+
+ BN_CTX_start(ctx);
+ tmp = BN_CTX_get(ctx);
+ tmp_Z = BN_CTX_get(ctx);
+ if (tmp == NULL || tmp_Z == NULL) {
+ goto err;
+ }
+
+ prod_Z = OPENSSL_malloc(num * sizeof(prod_Z[0]));
+ if (prod_Z == NULL) {
+ goto err;
+ }
+ memset(prod_Z, 0, num * sizeof(prod_Z[0]));
+ for (i = 0; i < num; i++) {
+ prod_Z[i] = BN_new();
+ if (prod_Z[i] == NULL) {
+ goto err;
+ }
+ }
+
+ /* Set each prod_Z[i] to the product of points[0]->Z .. points[i]->Z,
+ * skipping any zero-valued inputs (pretend that they're 1). */
+
+ if (!BN_is_zero(&points[0]->Z)) {
+ if (!BN_copy(prod_Z[0], &points[0]->Z)) {
+ goto err;
+ }
+ } else {
+ if (group->meth->field_set_to_one != 0) {
+ if (!group->meth->field_set_to_one(group, prod_Z[0], ctx)) {
+ goto err;
+ }
+ } else {
+ if (!BN_one(prod_Z[0])) {
+ goto err;
+ }
+ }
+ }
+
+ for (i = 1; i < num; i++) {
+ if (!BN_is_zero(&points[i]->Z)) {
+ if (!group->meth->field_mul(group, prod_Z[i], prod_Z[i - 1],
+ &points[i]->Z, ctx)) {
+ goto err;
+ }
+ } else {
+ if (!BN_copy(prod_Z[i], prod_Z[i - 1])) {
+ goto err;
+ }
+ }
+ }
+
+ /* Now use a single explicit inversion to replace every
+ * non-zero points[i]->Z by its inverse. */
+
+ if (!BN_mod_inverse(tmp, prod_Z[num - 1], &group->field, ctx)) {
+ OPENSSL_PUT_ERROR(EC, ec_GFp_simple_points_make_affine, 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 need to multiply by the Montgomery factor twice. */
+ if (!group->meth->field_encode(group, tmp, tmp, ctx) ||
+ !group->meth->field_encode(group, tmp, tmp, ctx)) {
+ goto err;
+ }
+ }
+
+ for (i = num - 1; i > 0; --i) {
+ /* Loop invariant: tmp is the product of the inverses of
+ * points[0]->Z .. points[i]->Z (zero-valued inputs skipped). */
+ if (BN_is_zero(&points[i]->Z)) {
+ continue;
+ }
+
+ /* Set tmp_Z to the inverse of points[i]->Z (as product
+ * of Z inverses 0 .. i, Z values 0 .. i - 1). */
+ if (!group->meth->field_mul(group, tmp_Z, prod_Z[i - 1], tmp, ctx) ||
+ /* Update tmp to satisfy the loop invariant for i - 1. */
+ !group->meth->field_mul(group, tmp, tmp, &points[i]->Z, ctx) ||
+ /* Replace points[i]->Z by its inverse. */
+ !BN_copy(&points[i]->Z, tmp_Z)) {
+ goto err;
+ }
+ }
+
+ /* Replace points[0]->Z by its inverse. */
+ if (!BN_is_zero(&points[0]->Z) && !BN_copy(&points[0]->Z, tmp)) {
+ goto err;
+ }
+
+ /* Finally, fix up the X and Y coordinates for all 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, tmp, &p->Z, ctx) ||
+ !group->meth->field_mul(group, &p->X, &p->X, tmp, ctx) ||
+ !group->meth->field_mul(group, tmp, tmp, &p->Z, ctx) ||
+ !group->meth->field_mul(group, &p->Y, &p->Y, tmp, 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 (new_ctx != NULL) {
+ BN_CTX_free(new_ctx);
+ }
+ if (prod_Z != NULL) {
+ for (i = 0; i < num; i++) {
+ if (prod_Z[i] == NULL) {
+ break;
+ }
+ BN_clear_free(prod_Z[i]);
+ }
+ OPENSSL_free(prod_Z);
+ }
+
+ 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);
+}
diff --git a/src/crypto/ec/wnaf.c b/src/crypto/ec/wnaf.c
new file mode 100644
index 0000000..9016328
--- /dev/null
+++ b/src/crypto/ec/wnaf.c
@@ -0,0 +1,844 @@
+/* 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. */
+
+#include <openssl/ec.h>
+
+#include <string.h>
+
+#include <openssl/bn.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+
+#include "internal.h"
+
+
+/* This file implements the wNAF-based interleaving multi-exponentation method
+ * (<URL:http://www.informatik.tu-darmstadt.de/TI/Mitarbeiter/moeller.html#multiexp>);
+ * for multiplication with precomputation, we use wNAF splitting
+ * (<URL:http://www.informatik.tu-darmstadt.de/TI/Mitarbeiter/moeller.html#fastexp>).
+ * */
+
+/* structure for precomputed multiples of the generator */
+typedef struct ec_pre_comp_st {
+ const EC_GROUP *group; /* parent EC_GROUP object */
+ size_t blocksize; /* block size for wNAF splitting */
+ size_t numblocks; /* max. number of blocks for which we have precomputation */
+ size_t w; /* window size */
+ EC_POINT **points; /* array with pre-calculated multiples of generator:
+ * 'num' pointers to EC_POINT objects followed by a NULL */
+ size_t num; /* numblocks * 2^(w-1) */
+ int references;
+} EC_PRE_COMP;
+
+static EC_PRE_COMP *ec_pre_comp_new(const EC_GROUP *group) {
+ EC_PRE_COMP *ret = NULL;
+
+ if (!group)
+ return NULL;
+
+ ret = (EC_PRE_COMP *)OPENSSL_malloc(sizeof(EC_PRE_COMP));
+ if (!ret) {
+ OPENSSL_PUT_ERROR(EC, ec_pre_comp_new, ERR_R_MALLOC_FAILURE);
+ return ret;
+ }
+ ret->group = group;
+ ret->blocksize = 8; /* default */
+ ret->numblocks = 0;
+ ret->w = 4; /* default */
+ ret->points = NULL;
+ ret->num = 0;
+ ret->references = 1;
+ return ret;
+}
+
+void *ec_pre_comp_dup(EC_PRE_COMP *pre_comp) {
+ if (pre_comp == NULL) {
+ return NULL;
+ }
+
+ CRYPTO_add(&pre_comp->references, 1, CRYPTO_LOCK_EC_PRE_COMP);
+ return pre_comp;
+}
+
+void ec_pre_comp_free(EC_PRE_COMP *pre_comp) {
+ int i;
+
+ if (!pre_comp) {
+ return;
+ }
+
+ i = CRYPTO_add(&pre_comp->references, -1, CRYPTO_LOCK_EC_PRE_COMP);
+ if (i > 0) {
+ return;
+ }
+
+ if (pre_comp->points) {
+ EC_POINT **p;
+
+ for (p = pre_comp->points; *p != NULL; p++) {
+ EC_POINT_free(*p);
+ }
+ OPENSSL_free(pre_comp->points);
+ }
+ OPENSSL_free(pre_comp);
+}
+
+
+/* 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 = OPENSSL_malloc(1);
+ if (!r) {
+ OPENSSL_PUT_ERROR(EC, compute_wNAF, 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 */
+ {
+ OPENSSL_PUT_ERROR(EC, compute_wNAF, 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) {
+ OPENSSL_PUT_ERROR(EC, compute_wNAF, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ len = BN_num_bits(scalar);
+ r = OPENSSL_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) {
+ OPENSSL_PUT_ERROR(EC, compute_wNAF, 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)) {
+ OPENSSL_PUT_ERROR(EC, compute_wNAF, 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) {
+ OPENSSL_PUT_ERROR(EC, compute_wNAF, 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) {
+ OPENSSL_PUT_ERROR(EC, compute_wNAF, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ }
+
+ if (j > len + 1) {
+ OPENSSL_PUT_ERROR(EC, compute_wNAF, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ len = j;
+ ok = 1;
+
+err:
+ if (!ok) {
+ OPENSSL_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) {
+ BN_CTX *new_ctx = NULL;
+ const EC_POINT *generator = NULL;
+ EC_POINT *tmp = NULL;
+ size_t totalnum;
+ size_t blocksize = 0, numblocks = 0; /* for wNAF splitting */
+ size_t pre_points_per_block = 0;
+ 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 */
+ 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' */
+ const EC_PRE_COMP *pre_comp = NULL;
+ 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) {
+ OPENSSL_PUT_ERROR(EC, ec_wNAF_mul, 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) {
+ OPENSSL_PUT_ERROR(EC, ec_wNAF_mul, EC_R_INCOMPATIBLE_OBJECTS);
+ return 0;
+ }
+ }
+
+ if (ctx == NULL) {
+ ctx = new_ctx = BN_CTX_new();
+ if (ctx == NULL)
+ goto err;
+ }
+
+ if (scalar != NULL) {
+ generator = EC_GROUP_get0_generator(group);
+ if (generator == NULL) {
+ OPENSSL_PUT_ERROR(EC, ec_wNAF_mul, EC_R_UNDEFINED_GENERATOR);
+ goto err;
+ }
+
+ /* look if we can use precomputed multiples of generator */
+
+ pre_comp = group->pre_comp;
+
+ if (pre_comp && pre_comp->numblocks &&
+ (EC_POINT_cmp(group, generator, pre_comp->points[0], ctx) == 0)) {
+ blocksize = pre_comp->blocksize;
+
+ /* determine maximum number of blocks that wNAF splitting may yield
+ * (NB: maximum wNAF length is bit length plus one) */
+ numblocks = (BN_num_bits(scalar) / blocksize) + 1;
+
+ /* we cannot use more blocks than we have precomputation for */
+ if (numblocks > pre_comp->numblocks)
+ numblocks = pre_comp->numblocks;
+
+ pre_points_per_block = (size_t)1 << (pre_comp->w - 1);
+
+ /* check that pre_comp looks sane */
+ if (pre_comp->num != (pre_comp->numblocks * pre_points_per_block)) {
+ OPENSSL_PUT_ERROR(EC, ec_wNAF_mul, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ } else {
+ /* can't use precomputation */
+ pre_comp = NULL;
+ numblocks = 1;
+ num_scalar = 1; /* treat 'scalar' like 'num'-th element of 'scalars' */
+ }
+ }
+
+ totalnum = num + numblocks;
+
+ wsize = OPENSSL_malloc(totalnum * sizeof wsize[0]);
+ wNAF_len = OPENSSL_malloc(totalnum * sizeof wNAF_len[0]);
+ wNAF = OPENSSL_malloc((totalnum + 1) *
+ sizeof wNAF[0]); /* includes space for pivot */
+ val_sub = OPENSSL_malloc(totalnum * sizeof val_sub[0]);
+
+ /* Ensure wNAF is initialised in case we end up going to err. */
+ if (wNAF) {
+ wNAF[0] = NULL; /* preliminary pivot */
+ }
+
+ if (!wsize || !wNAF_len || !wNAF || !val_sub) {
+ OPENSSL_PUT_ERROR(EC, ec_wNAF_mul, 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 (pre_comp == NULL) {
+ if (num_scalar != 1) {
+ OPENSSL_PUT_ERROR(EC, ec_wNAF_mul, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ /* we have already generated a wNAF for 'scalar' */
+ } else {
+ signed char *tmp_wNAF = NULL;
+ size_t tmp_len = 0;
+
+ if (num_scalar != 0) {
+ OPENSSL_PUT_ERROR(EC, ec_wNAF_mul, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ /* use the window size for which we have precomputation */
+ wsize[num] = pre_comp->w;
+ tmp_wNAF = compute_wNAF(scalar, wsize[num], &tmp_len);
+ if (!tmp_wNAF)
+ goto err;
+
+ if (tmp_len <= max_len) {
+ /* One of the other wNAFs is at least as long
+ * as the wNAF belonging to the generator,
+ * so wNAF splitting will not buy us anything. */
+
+ numblocks = 1; /* don't use wNAF splitting */
+ totalnum = num + numblocks;
+ wNAF[num] = tmp_wNAF;
+ wNAF[num + 1] = NULL;
+ wNAF_len[num] = tmp_len;
+ /* pre_comp->points starts with the points that we need here: */
+ val_sub[num] = pre_comp->points;
+ } else {
+ /* don't include tmp_wNAF directly into wNAF array
+ * - use wNAF splitting and include the blocks */
+
+ signed char *pp;
+ EC_POINT **tmp_points;
+
+ if (tmp_len < numblocks * blocksize) {
+ /* possibly we can do with fewer blocks than estimated */
+ numblocks = (tmp_len + blocksize - 1) / blocksize;
+ if (numblocks > pre_comp->numblocks) {
+ OPENSSL_PUT_ERROR(EC, ec_wNAF_mul, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ totalnum = num + numblocks;
+ }
+
+ /* split wNAF in 'numblocks' parts */
+ pp = tmp_wNAF;
+ tmp_points = pre_comp->points;
+
+ for (i = num; i < totalnum; i++) {
+ if (i < totalnum - 1) {
+ wNAF_len[i] = blocksize;
+ if (tmp_len < blocksize) {
+ OPENSSL_PUT_ERROR(EC, ec_wNAF_mul, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ tmp_len -= blocksize;
+ } else
+ /* last block gets whatever is left
+ * (this could be more or less than 'blocksize'!) */
+ wNAF_len[i] = tmp_len;
+
+ wNAF[i + 1] = NULL;
+ wNAF[i] = OPENSSL_malloc(wNAF_len[i]);
+ if (wNAF[i] == NULL) {
+ OPENSSL_PUT_ERROR(EC, ec_wNAF_mul, ERR_R_MALLOC_FAILURE);
+ OPENSSL_free(tmp_wNAF);
+ goto err;
+ }
+ memcpy(wNAF[i], pp, wNAF_len[i]);
+ if (wNAF_len[i] > max_len)
+ max_len = wNAF_len[i];
+
+ if (*tmp_points == NULL) {
+ OPENSSL_PUT_ERROR(EC, ec_wNAF_mul, ERR_R_INTERNAL_ERROR);
+ OPENSSL_free(tmp_wNAF);
+ goto err;
+ }
+ val_sub[i] = tmp_points;
+ tmp_points += pre_points_per_block;
+ pp += blocksize;
+ }
+ OPENSSL_free(tmp_wNAF);
+ }
+ }
+ }
+
+ /* 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 = OPENSSL_malloc((num_val + 1) * sizeof val[0]);
+ if (val == NULL) {
+ OPENSSL_PUT_ERROR(EC, ec_wNAF_mul, 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)) {
+ OPENSSL_PUT_ERROR(EC, ec_wNAF_mul, 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 1 /* optional; EC_window_bits_for_scalar_size assumes we do this step */
+ if (!EC_POINTs_make_affine(group, num_val, val, ctx))
+ goto err;
+#endif
+
+ 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:
+ if (new_ctx != NULL)
+ BN_CTX_free(new_ctx);
+ if (tmp != NULL)
+ EC_POINT_free(tmp);
+ if (wsize != NULL)
+ OPENSSL_free(wsize);
+ if (wNAF_len != NULL)
+ OPENSSL_free(wNAF_len);
+ if (wNAF != NULL) {
+ signed char **w;
+
+ for (w = wNAF; *w != NULL; w++)
+ OPENSSL_free(*w);
+
+ OPENSSL_free(wNAF);
+ }
+ if (val != NULL) {
+ for (v = val; *v != NULL; v++)
+ EC_POINT_clear_free(*v);
+
+ OPENSSL_free(val);
+ }
+ if (val_sub != NULL) {
+ OPENSSL_free(val_sub);
+ }
+ return ret;
+}
+
+
+/* ec_wNAF_precompute_mult()
+ * creates an EC_PRE_COMP object with preprecomputed multiples of the generator
+ * for use with wNAF splitting as implemented in ec_wNAF_mul().
+ *
+ * 'pre_comp->points' is an array of multiples of the generator
+ * of the following form:
+ * points[0] = generator;
+ * points[1] = 3 * generator;
+ * ...
+ * points[2^(w-1)-1] = (2^(w-1)-1) * generator;
+ * points[2^(w-1)] = 2^blocksize * generator;
+ * points[2^(w-1)+1] = 3 * 2^blocksize * generator;
+ * ...
+ * points[2^(w-1)*(numblocks-1)-1] = (2^(w-1)) * 2^(blocksize*(numblocks-2)) *
+ *generator
+ * points[2^(w-1)*(numblocks-1)] = 2^(blocksize*(numblocks-1)) *
+ *generator
+ * ...
+ * points[2^(w-1)*numblocks-1] = (2^(w-1)) * 2^(blocksize*(numblocks-1)) *
+ *generator
+ * points[2^(w-1)*numblocks] = NULL
+ */
+int ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *ctx) {
+ const EC_POINT *generator;
+ EC_POINT *tmp_point = NULL, *base = NULL, **var;
+ BN_CTX *new_ctx = NULL;
+ BIGNUM *order;
+ size_t i, bits, w, pre_points_per_block, blocksize, numblocks, num;
+ EC_POINT **points = NULL;
+ EC_PRE_COMP *pre_comp;
+ int ret = 0;
+
+ /* if there is an old EC_PRE_COMP object, throw it away */
+ if (group->pre_comp) {
+ ec_pre_comp_free(group->pre_comp);
+ group->pre_comp = NULL;
+ }
+
+ if ((pre_comp = ec_pre_comp_new(group)) == NULL)
+ return 0;
+
+ generator = EC_GROUP_get0_generator(group);
+ if (generator == NULL) {
+ OPENSSL_PUT_ERROR(EC, ec_wNAF_precompute_mult, EC_R_UNDEFINED_GENERATOR);
+ goto err;
+ }
+
+ if (ctx == NULL) {
+ ctx = new_ctx = BN_CTX_new();
+ if (ctx == NULL)
+ goto err;
+ }
+
+ BN_CTX_start(ctx);
+ order = BN_CTX_get(ctx);
+ if (order == NULL)
+ goto err;
+
+ if (!EC_GROUP_get_order(group, order, ctx))
+ goto err;
+ if (BN_is_zero(order)) {
+ OPENSSL_PUT_ERROR(EC, ec_wNAF_precompute_mult, EC_R_UNKNOWN_ORDER);
+ goto err;
+ }
+
+ bits = BN_num_bits(order);
+ /* The following parameters mean we precompute (approximately)
+ * one point per bit.
+ *
+ * TBD: The combination 8, 4 is perfect for 160 bits; for other
+ * bit lengths, other parameter combinations might provide better
+ * efficiency.
+ */
+ blocksize = 8;
+ w = 4;
+ if (EC_window_bits_for_scalar_size(bits) > w) {
+ /* let's not make the window too small ... */
+ w = EC_window_bits_for_scalar_size(bits);
+ }
+
+ numblocks = (bits + blocksize - 1) /
+ blocksize; /* max. number of blocks to use for wNAF splitting */
+
+ pre_points_per_block = (size_t)1 << (w - 1);
+ num = pre_points_per_block *
+ numblocks; /* number of points to compute and store */
+
+ points = OPENSSL_malloc(sizeof(EC_POINT *) * (num + 1));
+ if (!points) {
+ OPENSSL_PUT_ERROR(EC, ec_wNAF_precompute_mult, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ var = points;
+ var[num] = NULL; /* pivot */
+ for (i = 0; i < num; i++) {
+ if ((var[i] = EC_POINT_new(group)) == NULL) {
+ OPENSSL_PUT_ERROR(EC, ec_wNAF_precompute_mult, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+
+ if (!(tmp_point = EC_POINT_new(group)) || !(base = EC_POINT_new(group))) {
+ OPENSSL_PUT_ERROR(EC, ec_wNAF_precompute_mult, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (!EC_POINT_copy(base, generator))
+ goto err;
+
+ /* do the precomputation */
+ for (i = 0; i < numblocks; i++) {
+ size_t j;
+
+ if (!EC_POINT_dbl(group, tmp_point, base, ctx))
+ goto err;
+
+ if (!EC_POINT_copy(*var++, base))
+ goto err;
+
+ for (j = 1; j < pre_points_per_block; j++, var++) {
+ /* calculate odd multiples of the current base point */
+ if (!EC_POINT_add(group, *var, tmp_point, *(var - 1), ctx))
+ goto err;
+ }
+
+ if (i < numblocks - 1) {
+ /* get the next base (multiply current one by 2^blocksize) */
+ size_t k;
+
+ if (blocksize <= 2) {
+ OPENSSL_PUT_ERROR(EC, ec_wNAF_precompute_mult, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ if (!EC_POINT_dbl(group, base, tmp_point, ctx))
+ goto err;
+ for (k = 2; k < blocksize; k++) {
+ if (!EC_POINT_dbl(group, base, base, ctx))
+ goto err;
+ }
+ }
+ }
+
+ if (!EC_POINTs_make_affine(group, num, points, ctx))
+ goto err;
+
+ pre_comp->group = group;
+ pre_comp->blocksize = blocksize;
+ pre_comp->numblocks = numblocks;
+ pre_comp->w = w;
+ pre_comp->points = points;
+ points = NULL;
+ pre_comp->num = num;
+
+ group->pre_comp = pre_comp;
+ pre_comp = NULL;
+
+ ret = 1;
+
+err:
+ if (ctx != NULL)
+ BN_CTX_end(ctx);
+ if (new_ctx != NULL)
+ BN_CTX_free(new_ctx);
+ if (pre_comp)
+ ec_pre_comp_free(pre_comp);
+ if (points) {
+ EC_POINT **p;
+
+ for (p = points; *p != NULL; p++)
+ EC_POINT_free(*p);
+ OPENSSL_free(points);
+ }
+ if (tmp_point)
+ EC_POINT_free(tmp_point);
+ if (base)
+ EC_POINT_free(base);
+ return ret;
+}
+
+
+int ec_wNAF_have_precompute_mult(const EC_GROUP *group) {
+ return group->pre_comp != NULL;
+}
diff --git a/src/crypto/ecdh/CMakeLists.txt b/src/crypto/ecdh/CMakeLists.txt
new file mode 100644
index 0000000..b312148
--- /dev/null
+++ b/src/crypto/ecdh/CMakeLists.txt
@@ -0,0 +1,10 @@
+include_directories(. .. ../../include)
+
+add_library(
+ ecdh
+
+ OBJECT
+
+ ecdh.c
+ ecdh_error.c
+)
diff --git a/src/crypto/ecdh/ecdh.c b/src/crypto/ecdh/ecdh.c
new file mode 100644
index 0000000..d4497f1
--- /dev/null
+++ b/src/crypto/ecdh/ecdh.c
@@ -0,0 +1,157 @@
+/* ====================================================================
+ * 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) 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 <openssl/ecdh.h>
+
+#include <string.h>
+
+#include <openssl/bn.h>
+#include <openssl/digest.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+
+
+int ECDH_compute_key(void *out, size_t outlen, const EC_POINT *pub_key,
+ EC_KEY *priv_key, void *(*KDF)(const void *in, size_t inlen,
+ void *out, size_t *outlen)) {
+ BN_CTX *ctx;
+ EC_POINT *tmp = NULL;
+ BIGNUM *x = NULL, *y = NULL;
+ const BIGNUM *priv;
+ const EC_GROUP *group;
+ int ret = -1;
+ size_t buflen;
+ uint8_t *buf = NULL;
+
+ if ((ctx = BN_CTX_new()) == NULL) {
+ goto err;
+ }
+ BN_CTX_start(ctx);
+ x = BN_CTX_get(ctx);
+ y = BN_CTX_get(ctx);
+
+ priv = EC_KEY_get0_private_key(priv_key);
+ if (priv == NULL) {
+ OPENSSL_PUT_ERROR(ECDH, ECDH_compute_key, ECDH_R_NO_PRIVATE_VALUE);
+ goto err;
+ }
+
+ group = EC_KEY_get0_group(priv_key);
+
+ tmp = EC_POINT_new(group);
+ if (tmp == NULL) {
+ OPENSSL_PUT_ERROR(ECDH, ECDH_compute_key, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (!EC_POINT_mul(group, tmp, NULL, pub_key, priv, ctx)) {
+ OPENSSL_PUT_ERROR(ECDH, ECDH_compute_key, ECDH_R_POINT_ARITHMETIC_FAILURE);
+ goto err;
+ }
+
+ if (!EC_POINT_get_affine_coordinates_GFp(group, tmp, x, y, ctx)) {
+ OPENSSL_PUT_ERROR(ECDH, ECDH_compute_key, ECDH_R_POINT_ARITHMETIC_FAILURE);
+ goto err;
+ }
+
+ buflen = (EC_GROUP_get_degree(group) + 7) / 8;
+ buf = OPENSSL_malloc(buflen);
+ if (buf == NULL) {
+ OPENSSL_PUT_ERROR(ECDH, ECDH_compute_key, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (!BN_bn2bin_padded(buf, buflen, x)) {
+ OPENSSL_PUT_ERROR(ECDH, ECDH_compute_key, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ if (KDF != 0) {
+ if (KDF(buf, buflen, out, &outlen) == NULL) {
+ OPENSSL_PUT_ERROR(ECDH, ECDH_compute_key, ECDH_R_KDF_FAILED);
+ goto err;
+ }
+ ret = outlen;
+ } else {
+ /* no KDF, just copy as much as we can */
+ if (outlen > buflen) {
+ outlen = buflen;
+ }
+ memcpy(out, buf, outlen);
+ ret = outlen;
+ }
+
+err:
+ if (tmp)
+ EC_POINT_free(tmp);
+ if (ctx)
+ BN_CTX_end(ctx);
+ if (ctx)
+ BN_CTX_free(ctx);
+ if (buf)
+ OPENSSL_free(buf);
+ return ret;
+}
diff --git a/src/crypto/ecdh/ecdh_error.c b/src/crypto/ecdh/ecdh_error.c
new file mode 100644
index 0000000..8ba1854
--- /dev/null
+++ b/src/crypto/ecdh/ecdh_error.c
@@ -0,0 +1,25 @@
+/* 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 <openssl/err.h>
+
+#include <openssl/ecdh.h>
+
+const ERR_STRING_DATA ECDH_error_string_data[] = {
+ {ERR_PACK(ERR_LIB_ECDH, ECDH_F_ECDH_compute_key, 0), "ECDH_compute_key"},
+ {ERR_PACK(ERR_LIB_ECDH, 0, ECDH_R_KDF_FAILED), "KDF_FAILED"},
+ {ERR_PACK(ERR_LIB_ECDH, 0, ECDH_R_NO_PRIVATE_VALUE), "NO_PRIVATE_VALUE"},
+ {ERR_PACK(ERR_LIB_ECDH, 0, ECDH_R_POINT_ARITHMETIC_FAILURE), "POINT_ARITHMETIC_FAILURE"},
+ {0, NULL},
+};
diff --git a/src/crypto/ecdsa/CMakeLists.txt b/src/crypto/ecdsa/CMakeLists.txt
new file mode 100644
index 0000000..4bddd27
--- /dev/null
+++ b/src/crypto/ecdsa/CMakeLists.txt
@@ -0,0 +1,20 @@
+include_directories(. .. ../../include)
+
+add_library(
+ ecdsa
+
+ OBJECT
+
+ ecdsa.c
+ ecdsa_asn1.c
+ ecdsa_error.c
+)
+
+
+add_executable(
+ ecdsa_test
+
+ ecdsa_test.c
+)
+
+target_link_libraries(ecdsa_test crypto)
diff --git a/src/crypto/ecdsa/ecdsa.c b/src/crypto/ecdsa/ecdsa.c
new file mode 100644
index 0000000..d389799
--- /dev/null
+++ b/src/crypto/ecdsa/ecdsa.c
@@ -0,0 +1,496 @@
+/* ====================================================================
+ * 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 <openssl/ecdsa.h>
+
+#include <string.h>
+
+#include <openssl/bn.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/thread.h>
+
+#include "../ec/internal.h"
+
+
+int ECDSA_sign(int type, const uint8_t *digest, size_t digest_len, uint8_t *sig,
+ unsigned int *sig_len, EC_KEY *eckey) {
+ if (eckey->ecdsa_meth && eckey->ecdsa_meth->sign) {
+ return eckey->ecdsa_meth->sign(digest, digest_len, sig, sig_len, eckey);
+ }
+
+ return ECDSA_sign_ex(type, digest, digest_len, sig, sig_len, NULL, NULL,
+ eckey);
+}
+
+int ECDSA_verify(int type, const uint8_t *digest, size_t digest_len,
+ const uint8_t *sig, size_t sig_len, EC_KEY *eckey) {
+ ECDSA_SIG *s;
+ int ret = 0;
+ uint8_t *der = NULL;
+
+ if (eckey->ecdsa_meth && eckey->ecdsa_meth->verify) {
+ return eckey->ecdsa_meth->verify(digest, digest_len, sig, sig_len, eckey);
+ }
+
+ s = ECDSA_SIG_new();
+ const uint8_t *sigp = sig;
+ if (s == NULL || d2i_ECDSA_SIG(&s, &sigp, sig_len) == NULL ||
+ sigp != sig + sig_len) {
+ goto err;
+ }
+
+ /* Ensure that the signature uses DER and doesn't have trailing garbage. */
+ const int der_len = i2d_ECDSA_SIG(s, &der);
+ if (der_len < 0 || (size_t) der_len != sig_len || memcmp(sig, der, sig_len)) {
+ goto err;
+ }
+
+ ret = ECDSA_do_verify(digest, digest_len, s, eckey);
+
+err:
+ if (der != NULL) {
+ OPENSSL_free(der);
+ }
+ if (s != NULL) {
+ ECDSA_SIG_free(s);
+ }
+ return ret;
+}
+
+/* digest_to_bn interprets |digest_len| bytes from |digest| as a big-endian
+ * number and sets |out| to that value. It then truncates |out| so that it's,
+ * at most, as long as |order|. It returns one on success and zero otherwise. */
+static int digest_to_bn(BIGNUM *out, const uint8_t *digest, size_t digest_len,
+ const BIGNUM *order) {
+ size_t num_bits;
+
+ num_bits = BN_num_bits(order);
+ /* Need to truncate digest if it is too long: first truncate whole
+ * bytes. */
+ if (8 * digest_len > num_bits) {
+ digest_len = (num_bits + 7) / 8;
+ }
+ if (!BN_bin2bn(digest, digest_len, out)) {
+ OPENSSL_PUT_ERROR(ECDSA, digest_to_bn, ERR_R_BN_LIB);
+ return 0;
+ }
+
+ /* If still too long truncate remaining bits with a shift */
+ if ((8 * digest_len > num_bits) &&
+ !BN_rshift(out, out, 8 - (num_bits & 0x7))) {
+ OPENSSL_PUT_ERROR(ECDSA, digest_to_bn, ERR_R_BN_LIB);
+ return 0;
+ }
+
+ return 1;
+}
+
+ECDSA_SIG *ECDSA_do_sign(const uint8_t *digest, size_t digest_len,
+ EC_KEY *key) {
+ return ECDSA_do_sign_ex(digest, digest_len, NULL, NULL, key);
+}
+
+int ECDSA_do_verify(const uint8_t *digest, size_t digest_len,
+ const ECDSA_SIG *sig, EC_KEY *eckey) {
+ int ret = 0;
+ BN_CTX *ctx;
+ BIGNUM *order, *u1, *u2, *m, *X;
+ EC_POINT *point = NULL;
+ const EC_GROUP *group;
+ const EC_POINT *pub_key;
+
+ if (eckey->ecdsa_meth && eckey->ecdsa_meth->verify) {
+ OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_verify, ECDSA_R_NOT_IMPLEMENTED);
+ return 0;
+ }
+
+ /* check input values */
+ if ((group = EC_KEY_get0_group(eckey)) == NULL ||
+ (pub_key = EC_KEY_get0_public_key(eckey)) == NULL ||
+ sig == NULL) {
+ OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_verify, ECDSA_R_MISSING_PARAMETERS);
+ return 0;
+ }
+
+ ctx = BN_CTX_new();
+ if (!ctx) {
+ OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_verify, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ BN_CTX_start(ctx);
+ order = BN_CTX_get(ctx);
+ u1 = BN_CTX_get(ctx);
+ u2 = BN_CTX_get(ctx);
+ m = BN_CTX_get(ctx);
+ X = BN_CTX_get(ctx);
+ if (!X) {
+ OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_verify, ERR_R_BN_LIB);
+ goto err;
+ }
+
+ if (!EC_GROUP_get_order(group, order, ctx)) {
+ OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_verify, ERR_R_EC_LIB);
+ goto err;
+ }
+
+ if (BN_is_zero(sig->r) || BN_is_negative(sig->r) ||
+ BN_ucmp(sig->r, order) >= 0 || BN_is_zero(sig->s) ||
+ BN_is_negative(sig->s) || BN_ucmp(sig->s, order) >= 0) {
+ OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_verify, ECDSA_R_BAD_SIGNATURE);
+ ret = 0; /* signature is invalid */
+ goto err;
+ }
+ /* calculate tmp1 = inv(S) mod order */
+ if (!BN_mod_inverse(u2, sig->s, order, ctx)) {
+ OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_verify, ERR_R_BN_LIB);
+ goto err;
+ }
+ if (!digest_to_bn(m, digest, digest_len, order)) {
+ goto err;
+ }
+ /* u1 = m * tmp mod order */
+ if (!BN_mod_mul(u1, m, u2, order, ctx)) {
+ OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_verify, ERR_R_BN_LIB);
+ goto err;
+ }
+ /* u2 = r * w mod q */
+ if (!BN_mod_mul(u2, sig->r, u2, order, ctx)) {
+ OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_verify, ERR_R_BN_LIB);
+ goto err;
+ }
+
+ point = EC_POINT_new(group);
+ if (point == NULL) {
+ OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_verify, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ if (!EC_POINT_mul(group, point, u1, pub_key, u2, ctx)) {
+ OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_verify, ERR_R_EC_LIB);
+ goto err;
+ }
+ if (!EC_POINT_get_affine_coordinates_GFp(group, point, X, NULL, ctx)) {
+ OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_verify, ERR_R_EC_LIB);
+ goto err;
+ }
+ if (!BN_nnmod(u1, X, order, ctx)) {
+ OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_verify, ERR_R_BN_LIB);
+ goto err;
+ }
+ /* if the signature is correct u1 is equal to sig->r */
+ ret = (BN_ucmp(u1, sig->r) == 0);
+
+err:
+ BN_CTX_end(ctx);
+ BN_CTX_free(ctx);
+ if (point) {
+ EC_POINT_free(point);
+ }
+ return ret;
+}
+
+static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp,
+ BIGNUM **rp, const uint8_t *digest,
+ size_t digest_len) {
+ BN_CTX *ctx = NULL;
+ BIGNUM *k = NULL, *r = NULL, *order = NULL, *X = NULL;
+ EC_POINT *tmp_point = NULL;
+ const EC_GROUP *group;
+ int ret = 0;
+
+ if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL) {
+ OPENSSL_PUT_ERROR(ECDSA, ecdsa_sign_setup, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ if (ctx_in == NULL) {
+ if ((ctx = BN_CTX_new()) == NULL) {
+ OPENSSL_PUT_ERROR(ECDSA, ecdsa_sign_setup, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ } else {
+ ctx = ctx_in;
+ }
+
+ k = BN_new(); /* this value is later returned in *kinvp */
+ r = BN_new(); /* this value is later returned in *rp */
+ order = BN_new();
+ X = BN_new();
+ if (!k || !r || !order || !X) {
+ OPENSSL_PUT_ERROR(ECDSA, ecdsa_sign_setup, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ tmp_point = EC_POINT_new(group);
+ if (tmp_point == NULL) {
+ OPENSSL_PUT_ERROR(ECDSA, ecdsa_sign_setup, ERR_R_EC_LIB);
+ goto err;
+ }
+ if (!EC_GROUP_get_order(group, order, ctx)) {
+ OPENSSL_PUT_ERROR(ECDSA, ecdsa_sign_setup, ERR_R_EC_LIB);
+ goto err;
+ }
+
+ do {
+ /* If possible, we'll include the private key and message digest in the k
+ * generation. The |digest| argument is only empty if |ECDSA_sign_setup| is
+ * being used. */
+ do {
+ int ok;
+
+ if (digest_len > 0) {
+ ok = BN_generate_dsa_nonce(k, order, EC_KEY_get0_private_key(eckey),
+ digest, digest_len, ctx);
+ } else {
+ ok = BN_rand_range(k, order);
+ }
+ if (!ok) {
+ OPENSSL_PUT_ERROR(ECDSA, ecdsa_sign_setup,
+ ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED);
+ goto err;
+ }
+ } while (BN_is_zero(k));
+
+ /* 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)) {
+ goto err;
+ }
+ if (BN_num_bits(k) <= BN_num_bits(order)) {
+ if (!BN_add(k, k, order)) {
+ goto err;
+ }
+ }
+
+ /* compute r the x-coordinate of generator * k */
+ if (!EC_POINT_mul(group, tmp_point, k, NULL, NULL, ctx)) {
+ OPENSSL_PUT_ERROR(ECDSA, ecdsa_sign_setup, ERR_R_EC_LIB);
+ goto err;
+ }
+ if (!EC_POINT_get_affine_coordinates_GFp(group, tmp_point, X, NULL, ctx)) {
+ OPENSSL_PUT_ERROR(ECDSA, ecdsa_sign_setup, ERR_R_EC_LIB);
+ goto err;
+ }
+
+ if (!BN_nnmod(r, X, order, ctx)) {
+ OPENSSL_PUT_ERROR(ECDSA, ecdsa_sign_setup, ERR_R_BN_LIB);
+ goto err;
+ }
+ } while (BN_is_zero(r));
+
+ /* compute the inverse of k */
+ if (!BN_mod_inverse(k, k, order, ctx)) {
+ OPENSSL_PUT_ERROR(ECDSA, ecdsa_sign_setup, ERR_R_BN_LIB);
+ goto err;
+ }
+ /* clear old values if necessary */
+ if (*rp != NULL) {
+ BN_clear_free(*rp);
+ }
+ if (*kinvp != NULL) {
+ BN_clear_free(*kinvp);
+ }
+
+ /* save the pre-computed values */
+ *rp = r;
+ *kinvp = k;
+ ret = 1;
+
+err:
+ if (!ret) {
+ if (k != NULL) {
+ BN_clear_free(k);
+ }
+ if (r != NULL) {
+ BN_clear_free(r);
+ }
+ }
+ if (ctx_in == NULL)
+ BN_CTX_free(ctx);
+ if (order != NULL)
+ BN_free(order);
+ if (tmp_point != NULL)
+ EC_POINT_free(tmp_point);
+ if (X)
+ BN_clear_free(X);
+ return ret;
+}
+
+int ECDSA_sign_setup(EC_KEY *eckey, BN_CTX *ctx, BIGNUM **kinv, BIGNUM **rp) {
+ return ecdsa_sign_setup(eckey, ctx, kinv, rp, NULL, 0);
+}
+
+ECDSA_SIG *ECDSA_do_sign_ex(const uint8_t *digest, size_t digest_len,
+ const BIGNUM *in_kinv, const BIGNUM *in_r,
+ EC_KEY *eckey) {
+ int ok = 0;
+ BIGNUM *kinv = NULL, *s, *m = NULL, *tmp = NULL, *order = NULL;
+ const BIGNUM *ckinv;
+ BN_CTX *ctx = NULL;
+ const EC_GROUP *group;
+ ECDSA_SIG *ret;
+ const BIGNUM *priv_key;
+
+ if (eckey->ecdsa_meth && eckey->ecdsa_meth->sign) {
+ OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_sign_ex, ECDSA_R_NOT_IMPLEMENTED);
+ return NULL;
+ }
+
+ group = EC_KEY_get0_group(eckey);
+ priv_key = EC_KEY_get0_private_key(eckey);
+
+ if (group == NULL || priv_key == NULL) {
+ OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_sign_ex, ERR_R_PASSED_NULL_PARAMETER);
+ return NULL;
+ }
+
+ ret = ECDSA_SIG_new();
+ if (!ret) {
+ OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_sign_ex, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ s = ret->s;
+
+ if ((ctx = BN_CTX_new()) == NULL || (order = BN_new()) == NULL ||
+ (tmp = BN_new()) == NULL || (m = BN_new()) == NULL) {
+ OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_sign_ex, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (!EC_GROUP_get_order(group, order, ctx)) {
+ OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_sign_ex, ERR_R_EC_LIB);
+ goto err;
+ }
+ if (!digest_to_bn(m, digest, digest_len, order)) {
+ goto err;
+ }
+ for (;;) {
+ if (in_kinv == NULL || in_r == NULL) {
+ if (!ecdsa_sign_setup(eckey, ctx, &kinv, &ret->r, digest, digest_len)) {
+ OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_sign_ex, ERR_R_ECDSA_LIB);
+ goto err;
+ }
+ ckinv = kinv;
+ } else {
+ ckinv = in_kinv;
+ if (BN_copy(ret->r, in_r) == NULL) {
+ OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_sign_ex, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+
+ if (!BN_mod_mul(tmp, priv_key, ret->r, order, ctx)) {
+ OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_sign_ex, ERR_R_BN_LIB);
+ goto err;
+ }
+ if (!BN_mod_add_quick(s, tmp, m, order)) {
+ OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_sign_ex, ERR_R_BN_LIB);
+ goto err;
+ }
+ if (!BN_mod_mul(s, s, ckinv, order, ctx)) {
+ OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_sign_ex, ERR_R_BN_LIB);
+ goto err;
+ }
+ if (BN_is_zero(s)) {
+ /* if kinv and r have been supplied by the caller
+ * don't to generate new kinv and r values */
+ if (in_kinv != NULL && in_r != NULL) {
+ OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_sign_ex, ECDSA_R_NEED_NEW_SETUP_VALUES);
+ goto err;
+ }
+ } else {
+ /* s != 0 => we have a valid signature */
+ break;
+ }
+ }
+
+ ok = 1;
+
+err:
+ if (!ok) {
+ ECDSA_SIG_free(ret);
+ ret = NULL;
+ }
+ if (ctx)
+ BN_CTX_free(ctx);
+ if (m)
+ BN_clear_free(m);
+ if (tmp)
+ BN_clear_free(tmp);
+ if (order)
+ BN_free(order);
+ if (kinv)
+ BN_clear_free(kinv);
+ return ret;
+}
+
+int ECDSA_sign_ex(int type, const uint8_t *digest, size_t digest_len,
+ uint8_t *sig, unsigned int *sig_len, const BIGNUM *kinv,
+ const BIGNUM *r, EC_KEY *eckey) {
+ ECDSA_SIG *s = NULL;
+
+ if (eckey->ecdsa_meth && eckey->ecdsa_meth->sign) {
+ OPENSSL_PUT_ERROR(ECDSA, ECDSA_sign_ex, ECDSA_R_NOT_IMPLEMENTED);
+ *sig_len = 0;
+ return 0;
+ }
+
+ s = ECDSA_do_sign_ex(digest, digest_len, kinv, r, eckey);
+ if (s == NULL) {
+ *sig_len = 0;
+ return 0;
+ }
+ *sig_len = i2d_ECDSA_SIG(s, &sig);
+ ECDSA_SIG_free(s);
+ return 1;
+}
diff --git a/src/crypto/ecdsa/ecdsa_asn1.c b/src/crypto/ecdsa/ecdsa_asn1.c
new file mode 100644
index 0000000..b3c6a87
--- /dev/null
+++ b/src/crypto/ecdsa/ecdsa_asn1.c
@@ -0,0 +1,116 @@
+/* ====================================================================
+ * 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 <openssl/ecdsa.h>
+
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/ec_key.h>
+
+#include "../ec/internal.h"
+
+
+DECLARE_ASN1_FUNCTIONS_const(ECDSA_SIG);
+DECLARE_ASN1_ENCODE_FUNCTIONS_const(ECDSA_SIG, ECDSA_SIG);
+
+ASN1_SEQUENCE(ECDSA_SIG) = {
+ ASN1_SIMPLE(ECDSA_SIG, r, CBIGNUM),
+ ASN1_SIMPLE(ECDSA_SIG, s, CBIGNUM),
+} ASN1_SEQUENCE_END(ECDSA_SIG);
+
+IMPLEMENT_ASN1_FUNCTIONS_const(ECDSA_SIG);
+
+size_t ECDSA_size(const EC_KEY *key) {
+ size_t ret, i, group_order_size;
+ ASN1_INTEGER bs;
+ BIGNUM *order = NULL;
+ unsigned char buf[4];
+ const EC_GROUP *group;
+
+ if (key->ecdsa_meth && key->ecdsa_meth->group_order_size) {
+ group_order_size = key->ecdsa_meth->group_order_size(key);
+ } else {
+ size_t num_bits;
+
+ if (key == NULL) {
+ return 0;
+ }
+ group = EC_KEY_get0_group(key);
+ if (group == NULL) {
+ return 0;
+ }
+
+ order = BN_new();
+ if (order == NULL) {
+ return 0;
+ }
+ if (!EC_GROUP_get_order(group, order, NULL)) {
+ BN_clear_free(order);
+ return 0;
+ }
+
+ num_bits = BN_num_bits(order);
+ group_order_size = (num_bits + 7) / 8;
+ }
+
+ bs.length = group_order_size;
+ bs.data = buf;
+ bs.type = V_ASN1_INTEGER;
+ /* If the top bit is set the ASN.1 encoding is 1 larger. */
+ buf[0] = 0xff;
+
+ i = i2d_ASN1_INTEGER(&bs, NULL);
+ i += i; /* r and s */
+ ret = ASN1_object_size(1, i, V_ASN1_SEQUENCE);
+ BN_clear_free(order);
+ return ret;
+}
diff --git a/src/crypto/ecdsa/ecdsa_error.c b/src/crypto/ecdsa/ecdsa_error.c
new file mode 100644
index 0000000..cbd69ce
--- /dev/null
+++ b/src/crypto/ecdsa/ecdsa_error.c
@@ -0,0 +1,32 @@
+/* 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 <openssl/err.h>
+
+#include <openssl/ecdsa.h>
+
+const ERR_STRING_DATA ECDSA_error_string_data[] = {
+ {ERR_PACK(ERR_LIB_ECDSA, ECDSA_F_ECDSA_do_sign_ex, 0), "ECDSA_do_sign_ex"},
+ {ERR_PACK(ERR_LIB_ECDSA, ECDSA_F_ECDSA_do_verify, 0), "ECDSA_do_verify"},
+ {ERR_PACK(ERR_LIB_ECDSA, ECDSA_F_ECDSA_sign_ex, 0), "ECDSA_sign_ex"},
+ {ERR_PACK(ERR_LIB_ECDSA, ECDSA_F_ECDSA_sign_setup, 0), "ECDSA_sign_setup"},
+ {ERR_PACK(ERR_LIB_ECDSA, ECDSA_F_digest_to_bn, 0), "digest_to_bn"},
+ {ERR_PACK(ERR_LIB_ECDSA, ECDSA_F_ecdsa_sign_setup, 0), "ecdsa_sign_setup"},
+ {ERR_PACK(ERR_LIB_ECDSA, 0, ECDSA_R_BAD_SIGNATURE), "BAD_SIGNATURE"},
+ {ERR_PACK(ERR_LIB_ECDSA, 0, ECDSA_R_MISSING_PARAMETERS), "MISSING_PARAMETERS"},
+ {ERR_PACK(ERR_LIB_ECDSA, 0, ECDSA_R_NEED_NEW_SETUP_VALUES), "NEED_NEW_SETUP_VALUES"},
+ {ERR_PACK(ERR_LIB_ECDSA, 0, ECDSA_R_NOT_IMPLEMENTED), "NOT_IMPLEMENTED"},
+ {ERR_PACK(ERR_LIB_ECDSA, 0, ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED), "RANDOM_NUMBER_GENERATION_FAILED"},
+ {0, NULL},
+};
diff --git a/src/crypto/ecdsa/ecdsa_test.c b/src/crypto/ecdsa/ecdsa_test.c
new file mode 100644
index 0000000..d48f9c3
--- /dev/null
+++ b/src/crypto/ecdsa/ecdsa_test.c
@@ -0,0 +1,328 @@
+/* ====================================================================
+ * 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 <openssl/ecdsa.h>
+
+#include <openssl/bio.h>
+#include <openssl/bn.h>
+#include <openssl/crypto.h>
+#include <openssl/ec.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/rand.h>
+
+
+int test_builtin(BIO *out) {
+ size_t n = 0;
+ EC_KEY *eckey = NULL, *wrong_eckey = NULL;
+ EC_GROUP *group;
+ BIGNUM *order = NULL;
+ ECDSA_SIG *ecdsa_sig = NULL;
+ unsigned char digest[20], wrong_digest[20];
+ unsigned char *signature = NULL;
+ const unsigned char *sig_ptr;
+ unsigned char *sig_ptr2;
+ unsigned char *raw_buf = NULL;
+ unsigned int sig_len, r_len, s_len, bn_len, buf_len;
+ int nid, ret = 0;
+
+ /* fill digest values with some random data */
+ if (!RAND_bytes(digest, 20) || !RAND_bytes(wrong_digest, 20)) {
+ BIO_printf(out, "ERROR: unable to get random data\n");
+ goto builtin_err;
+ }
+
+ order = BN_new();
+ if (order == NULL) {
+ goto builtin_err;
+ }
+
+ /* create and verify a ecdsa signature with every availble curve
+ * (with ) */
+ BIO_printf(out,
+ "\ntesting ECDSA_sign() and ECDSA_verify() "
+ "with some internal curves:\n");
+
+ static const int kCurveNIDs[] = {NID_secp224r1, NID_X9_62_prime256v1,
+ NID_secp384r1, NID_secp521r1, NID_undef};
+
+ /* now create and verify a signature for every curve */
+ for (n = 0; kCurveNIDs[n] != NID_undef; n++) {
+ unsigned char dirt, offset;
+
+ nid = kCurveNIDs[n];
+ /* create new ecdsa key (== EC_KEY) */
+ eckey = EC_KEY_new();
+ if (eckey == NULL) {
+ goto builtin_err;
+ }
+ group = EC_GROUP_new_by_curve_name(nid);
+ if (group == NULL) {
+ goto builtin_err;
+ }
+ if (!EC_KEY_set_group(eckey, group)) {
+ goto builtin_err;
+ }
+ EC_GROUP_free(group);
+ if (!EC_GROUP_get_order(EC_KEY_get0_group(eckey), order, NULL)) {
+ goto builtin_err;
+ }
+ if (BN_num_bits(order) < 160) {
+ /* Too small to test. */
+ EC_KEY_free(eckey);
+ eckey = NULL;
+ continue;
+ }
+
+ BIO_printf(out, "%s: ", OBJ_nid2sn(nid));
+ /* create key */
+ if (!EC_KEY_generate_key(eckey)) {
+ BIO_printf(out, " failed\n");
+ goto builtin_err;
+ }
+ /* create second key */
+ wrong_eckey = EC_KEY_new();
+ if (wrong_eckey == NULL) {
+ goto builtin_err;
+ }
+ group = EC_GROUP_new_by_curve_name(nid);
+ if (group == NULL) {
+ goto builtin_err;
+ }
+ if (EC_KEY_set_group(wrong_eckey, group) == 0) {
+ goto builtin_err;
+ }
+ EC_GROUP_free(group);
+ if (!EC_KEY_generate_key(wrong_eckey)) {
+ BIO_printf(out, " failed\n");
+ goto builtin_err;
+ }
+
+ BIO_printf(out, ".");
+ (void)BIO_flush(out);
+ /* check key */
+ if (!EC_KEY_check_key(eckey)) {
+ BIO_printf(out, " failed\n");
+ goto builtin_err;
+ }
+ BIO_printf(out, ".");
+ (void)BIO_flush(out);
+ /* create signature */
+ sig_len = ECDSA_size(eckey);
+ signature = OPENSSL_malloc(sig_len);
+ if (signature == NULL) {
+ goto builtin_err;
+ }
+ if (!ECDSA_sign(0, digest, 20, signature, &sig_len, eckey)) {
+ BIO_printf(out, " failed\n");
+ goto builtin_err;
+ }
+ BIO_printf(out, ".");
+ (void)BIO_flush(out);
+ /* verify signature */
+ if (ECDSA_verify(0, digest, 20, signature, sig_len, eckey) != 1) {
+ BIO_printf(out, " failed\n");
+ goto builtin_err;
+ }
+ BIO_printf(out, ".");
+ (void)BIO_flush(out);
+ /* verify signature with the wrong key */
+ if (ECDSA_verify(0, digest, 20, signature, sig_len, wrong_eckey) == 1) {
+ BIO_printf(out, " failed\n");
+ goto builtin_err;
+ }
+ BIO_printf(out, ".");
+ (void)BIO_flush(out);
+ /* wrong digest */
+ if (ECDSA_verify(0, wrong_digest, 20, signature, sig_len, eckey) == 1) {
+ BIO_printf(out, " failed\n");
+ goto builtin_err;
+ }
+ BIO_printf(out, ".");
+ (void)BIO_flush(out);
+ /* wrong length */
+ if (ECDSA_verify(0, digest, 20, signature, sig_len - 1, eckey) == 1) {
+ BIO_printf(out, " failed\n");
+ goto builtin_err;
+ }
+ BIO_printf(out, ".");
+ (void)BIO_flush(out);
+
+ /* 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;
+ ecdsa_sig = d2i_ECDSA_SIG(NULL, &sig_ptr, sig_len);
+ if (ecdsa_sig == NULL) {
+ BIO_printf(out, " failed\n");
+ goto builtin_err;
+ }
+
+ /* Store the two BIGNUMs in raw_buf. */
+ r_len = BN_num_bytes(ecdsa_sig->r);
+ s_len = BN_num_bytes(ecdsa_sig->s);
+ bn_len = BN_num_bytes(order);
+ if (r_len > bn_len || s_len > bn_len) {
+ BIO_printf(out, " failed\n");
+ goto builtin_err;
+ }
+ buf_len = 2 * bn_len;
+ raw_buf = OPENSSL_malloc(2 * bn_len);
+ if (raw_buf == NULL) {
+ goto builtin_err;
+ }
+ /* Pad the bignums with leading zeroes. */
+ if (!BN_bn2bin_padded(raw_buf, bn_len, ecdsa_sig->r) ||
+ !BN_bn2bin_padded(raw_buf + bn_len, bn_len, ecdsa_sig->s)) {
+ goto builtin_err;
+ }
+
+ /* 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 (BN_bin2bn(raw_buf, bn_len, ecdsa_sig->r) == NULL ||
+ BN_bin2bn(raw_buf + bn_len, bn_len, ecdsa_sig->s) == NULL) {
+ goto builtin_err;
+ }
+
+ sig_ptr2 = signature;
+ sig_len = i2d_ECDSA_SIG(ecdsa_sig, &sig_ptr2);
+ if (ECDSA_verify(0, digest, 20, signature, sig_len, eckey) == 1) {
+ BIO_printf(out, " failed\n");
+ goto builtin_err;
+ }
+ /* Sanity check: undo the modification and verify signature. */
+ raw_buf[offset] ^= dirt;
+ if (BN_bin2bn(raw_buf, bn_len, ecdsa_sig->r) == NULL ||
+ BN_bin2bn(raw_buf + bn_len, bn_len, ecdsa_sig->s) == NULL) {
+ goto builtin_err;
+ }
+
+ sig_ptr2 = signature;
+ sig_len = i2d_ECDSA_SIG(ecdsa_sig, &sig_ptr2);
+ if (ECDSA_verify(0, digest, 20, signature, sig_len, eckey) != 1) {
+ BIO_printf(out, " failed\n");
+ goto builtin_err;
+ }
+ BIO_printf(out, ".");
+ (void)BIO_flush(out);
+
+ BIO_printf(out, " ok\n");
+ /* cleanup */
+ /* clean bogus errors */
+ ERR_clear_error();
+ OPENSSL_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;
+ OPENSSL_free(raw_buf);
+ raw_buf = NULL;
+ }
+
+ ret = 1;
+builtin_err:
+ if (eckey) {
+ EC_KEY_free(eckey);
+ }
+ if (order) {
+ BN_free(order);
+ }
+ if (wrong_eckey) {
+ EC_KEY_free(wrong_eckey);
+ }
+ if (ecdsa_sig) {
+ ECDSA_SIG_free(ecdsa_sig);
+ }
+ if (signature) {
+ OPENSSL_free(signature);
+ }
+ if (raw_buf) {
+ OPENSSL_free(raw_buf);
+ }
+
+ return ret;
+}
+
+int main(void) {
+ int ret = 1;
+ BIO *out;
+
+ CRYPTO_library_init();
+ ERR_load_crypto_strings();
+
+ out = BIO_new_fp(stdout, BIO_NOCLOSE);
+
+ if (!test_builtin(out))
+ goto err;
+
+ ret = 0;
+
+err:
+ if (ret)
+ BIO_printf(out, "\nECDSA test failed\n");
+ else
+ BIO_printf(out, "\nPASS\n");
+ if (ret)
+ BIO_print_errors(out);
+
+ if (out != NULL)
+ BIO_free(out);
+
+ return ret;
+}
diff --git a/src/crypto/engine/CMakeLists.txt b/src/crypto/engine/CMakeLists.txt
new file mode 100644
index 0000000..cea6566
--- /dev/null
+++ b/src/crypto/engine/CMakeLists.txt
@@ -0,0 +1,10 @@
+include_directories(. .. ../../include)
+
+add_library(
+ engine
+
+ OBJECT
+
+ engine.c
+ engine_error.c
+)
diff --git a/src/crypto/engine/engine.c b/src/crypto/engine/engine.c
new file mode 100644
index 0000000..5b8cf1c
--- /dev/null
+++ b/src/crypto/engine/engine.c
@@ -0,0 +1,138 @@
+/* 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 <openssl/engine.h>
+
+#include <string.h>
+
+#include <openssl/dh.h>
+#include <openssl/dsa.h>
+#include <openssl/ec_key.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/rsa.h>
+#include <openssl/thread.h>
+
+
+struct engine_st {
+ DH_METHOD *dh_method;
+ DSA_METHOD *dsa_method;
+ RSA_METHOD *rsa_method;
+ ECDSA_METHOD *ecdsa_method;
+};
+
+ENGINE *ENGINE_new(void) {
+ ENGINE *engine = OPENSSL_malloc(sizeof(ENGINE));
+ if (engine == NULL) {
+ return NULL;
+ }
+
+ memset(engine, 0, sizeof(ENGINE));
+ return engine;
+}
+
+void ENGINE_free(ENGINE *engine) {
+ if (engine->dh_method != NULL) {
+ METHOD_unref(engine->dh_method);
+ }
+
+ OPENSSL_free(engine);
+}
+
+/* set_method takes a pointer to a method and its given size and sets
+ * |*out_member| to point to a copy of it. The copy is |compiled_size| bytes
+ * long and has zero padding if needed. */
+static int set_method(void **out_member, const void *method, size_t method_size,
+ size_t compiled_size) {
+ void *copy = OPENSSL_malloc(compiled_size);
+ if (copy == NULL) {
+ return 0;
+ }
+
+ memset(copy, 0, compiled_size);
+
+ if (method_size > compiled_size) {
+ method_size = compiled_size;
+ }
+ memcpy(copy, method, method_size);
+
+ METHOD_unref(*out_member);
+ *out_member = copy;
+
+ return 1;
+}
+
+int ENGINE_set_DH_method(ENGINE *engine, const DH_METHOD *method,
+ size_t method_size) {
+ return set_method((void **)&engine->dh_method, method, method_size,
+ sizeof(DH_METHOD));
+}
+
+DH_METHOD *ENGINE_get_DH_method(const ENGINE *engine) {
+ return engine->dh_method;
+}
+
+int ENGINE_set_DSA_method(ENGINE *engine, const DSA_METHOD *method,
+ size_t method_size) {
+ return set_method((void **)&engine->dsa_method, method, method_size,
+ sizeof(DSA_METHOD));
+}
+
+DSA_METHOD *ENGINE_get_DSA_method(const ENGINE *engine) {
+ return engine->dsa_method;
+}
+
+int ENGINE_set_RSA_method(ENGINE *engine, const RSA_METHOD *method,
+ size_t method_size) {
+ return set_method((void **)&engine->rsa_method, method, method_size,
+ sizeof(RSA_METHOD));
+}
+
+RSA_METHOD *ENGINE_get_RSA_method(const ENGINE *engine) {
+ return engine->rsa_method;
+}
+
+int ENGINE_set_ECDSA_method(ENGINE *engine, const ECDSA_METHOD *method,
+ size_t method_size) {
+ return set_method((void **)&engine->ecdsa_method, method, method_size,
+ sizeof(ECDSA_METHOD));
+}
+
+ECDSA_METHOD *ENGINE_get_ECDSA_method(const ENGINE *engine) {
+ return engine->ecdsa_method;
+}
+
+void METHOD_ref(void *method_in) {
+ struct openssl_method_common_st *method = method_in;
+
+ if (method->is_static) {
+ return;
+ }
+
+ CRYPTO_add(&method->references, 1, CRYPTO_LOCK_ENGINE);
+}
+
+void METHOD_unref(void *method_in) {
+ struct openssl_method_common_st *method = method_in;
+
+ if (method == NULL || method->is_static) {
+ return;
+ }
+
+ if (CRYPTO_add(&method->references, -1, CRYPTO_LOCK_ENGINE) == 0) {
+ OPENSSL_free(method);
+ }
+}
+
+OPENSSL_DECLARE_ERROR_REASON(ENGINE, OPERATION_NOT_SUPPORTED);
diff --git a/src/crypto/engine/engine_error.c b/src/crypto/engine/engine_error.c
new file mode 100644
index 0000000..9f65f70
--- /dev/null
+++ b/src/crypto/engine/engine_error.c
@@ -0,0 +1,22 @@
+/* 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 <openssl/err.h>
+
+#include <openssl/engine.h>
+
+const ERR_STRING_DATA ENGINE_error_string_data[] = {
+ {ERR_PACK(ERR_LIB_ENGINE, 0, ENGINE_R_OPERATION_NOT_SUPPORTED), "OPERATION_NOT_SUPPORTED"},
+ {0, NULL},
+};
diff --git a/src/crypto/err/CMakeLists.txt b/src/crypto/err/CMakeLists.txt
new file mode 100644
index 0000000..53dccea
--- /dev/null
+++ b/src/crypto/err/CMakeLists.txt
@@ -0,0 +1,18 @@
+include_directories(. .. ../../include)
+
+add_library(
+ err
+
+ OBJECT
+
+ err.c
+ err_impl.c
+)
+
+add_executable(
+ err_test
+
+ err_test.c
+)
+
+target_link_libraries(err_test crypto)
diff --git a/src/crypto/err/err.c b/src/crypto/err/err.c
new file mode 100644
index 0000000..ec2062e
--- /dev/null
+++ b/src/crypto/err/err.c
@@ -0,0 +1,809 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/err.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+#if defined(OPENSSL_WINDOWS)
+#pragma warning(push, 3)
+#include <Windows.h>
+#pragma warning(pop)
+#endif
+
+#include <openssl/lhash.h>
+#include <openssl/mem.h>
+#include <openssl/thread.h>
+
+
+/* err_fns contains a pointer to the current error implementation. */
+static const struct ERR_FNS_st *err_fns = NULL;
+extern const struct ERR_FNS_st openssl_err_default_impl;
+
+#define ERRFN(a) err_fns->a
+
+/* err_fns_check is an internal function that checks whether "err_fns" is set
+ * and if not, sets it to the default. */
+static void err_fns_check(void) {
+ /* In practice, this is not a race problem because loading the error strings
+ * at init time will cause this pointer to be set before the process goes
+ * multithreaded. */
+ if (err_fns) {
+ return;
+ }
+
+ CRYPTO_w_lock(CRYPTO_LOCK_ERR);
+ if (!err_fns) {
+ err_fns = &openssl_err_default_impl;
+ }
+ CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
+}
+
+/* err_clear_data frees the optional |data| member of the given error. */
+static void err_clear_data(struct err_error_st *error) {
+ if (error->data != NULL && (error->flags & ERR_FLAG_MALLOCED) != 0) {
+ OPENSSL_free(error->data);
+ }
+ error->data = NULL;
+ error->flags &= ~ERR_FLAG_MALLOCED;
+}
+
+/* err_clear clears the given queued error. */
+static void err_clear(struct err_error_st *error) {
+ err_clear_data(error);
+ memset(error, 0, sizeof(struct err_error_st));
+}
+
+/* err_get_state gets the ERR_STATE object for the current thread. */
+static ERR_STATE *err_get_state(void) {
+ err_fns_check();
+ return ERRFN(get_state)();
+}
+
+static uint32_t get_error_values(int inc, int top, const char **file, int *line,
+ const char **data, int *flags) {
+ unsigned i = 0;
+ ERR_STATE *state;
+ struct err_error_st *error;
+ uint32_t ret;
+
+ state = err_get_state();
+ if (state == NULL || state->bottom == state->top) {
+ return 0;
+ }
+
+ if (top) {
+ assert(!inc);
+ /* last error */
+ i = state->top;
+ } else {
+ i = (state->bottom + 1) % ERR_NUM_ERRORS;
+ }
+
+ error = &state->errors[i];
+ ret = error->packed;
+
+ if (file != NULL && line != NULL) {
+ if (error->file == NULL) {
+ *file = "NA";
+ *line = 0;
+ } else {
+ *file = error->file;
+ *line = error->line;
+ }
+ }
+
+ if (data != NULL) {
+ if (error->data == NULL) {
+ *data = "";
+ if (flags != NULL) {
+ *flags = 0;
+ }
+ } else {
+ *data = error->data;
+ if (flags != NULL) {
+ *flags = error->flags & ERR_FLAG_PUBLIC_MASK;
+ }
+ /* If this error is being removed, take ownership of data from
+ * the error. The semantics are such that the caller doesn't
+ * take ownership either. Instead the error system takes
+ * ownership and retains it until the next call that affects the
+ * error queue. */
+ if (inc) {
+ if (error->flags & ERR_FLAG_MALLOCED) {
+ if (state->to_free) {
+ OPENSSL_free(state->to_free);
+ }
+ state->to_free = error->data;
+ }
+ error->data = NULL;
+ error->flags = 0;
+ }
+ }
+ }
+
+ if (inc) {
+ assert(!top);
+ err_clear(error);
+ state->bottom = i;
+ }
+
+ return ret;
+}
+
+uint32_t ERR_get_error(void) {
+ return get_error_values(1, 0, NULL, NULL, NULL, NULL);
+}
+
+uint32_t ERR_get_error_line(const char **file, int *line) {
+ return get_error_values(1, 0, file, line, NULL, NULL);
+}
+
+uint32_t 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);
+}
+
+uint32_t ERR_peek_error(void) {
+ return get_error_values(0, 0, NULL, NULL, NULL, NULL);
+}
+
+uint32_t ERR_peek_error_line(const char **file, int *line) {
+ return get_error_values(0, 0, file, line, NULL, NULL);
+}
+
+uint32_t 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);
+}
+
+uint32_t ERR_peek_last_error(void) {
+ return get_error_values(0, 1, NULL, NULL, NULL, NULL);
+}
+
+uint32_t ERR_peek_last_error_line(const char **file, int *line) {
+ return get_error_values(0, 1, file, line, NULL, NULL);
+}
+
+uint32_t 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);
+}
+
+void ERR_clear_error(void) {
+ ERR_STATE *const state = err_get_state();
+ unsigned i;
+
+ if (state == NULL) {
+ return;
+ }
+
+ for (i = 0; i < ERR_NUM_ERRORS; i++) {
+ err_clear(&state->errors[i]);
+ }
+ if (state->to_free) {
+ OPENSSL_free(state->to_free);
+ state->to_free = NULL;
+ }
+
+ state->top = state->bottom = 0;
+}
+
+static void err_state_free(ERR_STATE *state) {
+ unsigned i;
+
+ for (i = 0; i < ERR_NUM_ERRORS; i++) {
+ err_clear(&state->errors[i]);
+ }
+ if (state->to_free) {
+ OPENSSL_free(state->to_free);
+ }
+ OPENSSL_free(state);
+}
+
+void ERR_remove_thread_state(const CRYPTO_THREADID *tid) {
+ CRYPTO_THREADID current;
+ ERR_STATE *state;
+
+ if (tid == NULL) {
+ CRYPTO_THREADID_current(&current);
+ tid = &current;
+ }
+
+ err_fns_check();
+ state = ERRFN(release_state)(tid);
+ if (state == NULL) {
+ return;
+ }
+
+ err_state_free(state);
+}
+
+int ERR_get_next_error_library(void) {
+ err_fns_check();
+ return ERRFN(get_next_library)();
+}
+
+void ERR_clear_system_error(void) {
+ errno = 0;
+}
+
+char *ERR_error_string(uint32_t packed_error, char *ret) {
+ static char buf[ERR_ERROR_STRING_BUF_LEN];
+
+ if (ret == NULL) {
+ /* TODO(fork): remove this. */
+ ret = buf;
+ }
+
+#if !defined(NDEBUG)
+ /* This is aimed to help catch callers who don't provide
+ * |ERR_ERROR_STRING_BUF_LEN| bytes of space. */
+ memset(ret, 0, ERR_ERROR_STRING_BUF_LEN);
+#endif
+
+ ERR_error_string_n(packed_error, ret, ERR_ERROR_STRING_BUF_LEN);
+
+ return ret;
+}
+
+void ERR_error_string_n(uint32_t packed_error, char *buf, size_t len) {
+ char lib_buf[64], func_buf[64], reason_buf[64];
+ const char *lib_str, *func_str, *reason_str;
+ unsigned lib, func, reason;
+
+ if (len == 0) {
+ return;
+ }
+
+ lib = ERR_GET_LIB(packed_error);
+ func = ERR_GET_FUNC(packed_error);
+ reason = ERR_GET_REASON(packed_error);
+
+ lib_str = ERR_lib_error_string(packed_error);
+ func_str = ERR_func_error_string(packed_error);
+ reason_str = ERR_reason_error_string(packed_error);
+
+ if (lib_str == NULL) {
+ BIO_snprintf(lib_buf, sizeof(lib_buf), "lib(%u)", lib);
+ lib_str = lib_buf;
+ }
+
+ if (func_str == NULL) {
+ BIO_snprintf(func_buf, sizeof(func_buf), "func(%u)", func);
+ func_str = func_buf;
+ }
+
+ if (reason_str == NULL) {
+ BIO_snprintf(reason_buf, sizeof(reason_buf), "reason(%u)", reason);
+ reason_str = reason_buf;
+ }
+
+ BIO_snprintf(buf, len, "error:%08" PRIx32 ":%s:%s:%s",
+ packed_error, lib_str, func_str, reason_str);
+
+ if (strlen(buf) == len - 1) {
+ /* output may be truncated; make sure we always have 5 colon-separated
+ * fields, i.e. 4 colons. */
+ static const unsigned num_colons = 4;
+ unsigned i;
+ char *s = buf;
+
+ if (len <= num_colons) {
+ /* In this situation it's not possible to ensure that the correct number
+ * of colons are included in the output. */
+ return;
+ }
+
+ for (i = 0; i < num_colons; i++) {
+ char *colon = strchr(s, ':');
+ char *last_pos = &buf[len - 1] - num_colons + i;
+
+ if (colon == NULL || colon > last_pos) {
+ /* set colon |i| at last possible position (buf[len-1] is the
+ * terminating 0). If we're setting this colon, then all whole of the
+ * rest of the string must be colons in order to have the correct
+ * number. */
+ memset(last_pos, ':', num_colons - i);
+ break;
+ }
+
+ s = colon + 1;
+ }
+ }
+}
+
+/* err_component_error_string returns the error string associated with
+ * |packed_error|, which must be of a special form matching the keys inserted
+ * into the error hash table. */
+static const char *err_component_error_string(uint32_t packed_error) {
+ ERR_STRING_DATA *p;
+
+ err_fns_check();
+ p = ERRFN(get_item)(packed_error);
+
+ if (p == NULL) {
+ return NULL;
+ }
+ return p->string;
+}
+
+const char *ERR_lib_error_string(uint32_t packed_error) {
+ return err_component_error_string(ERR_PACK(ERR_GET_LIB(packed_error), 0, 0));
+}
+
+const char *ERR_func_error_string(uint32_t packed_error) {
+ return err_component_error_string(
+ ERR_PACK(ERR_GET_LIB(packed_error), ERR_GET_FUNC(packed_error), 0));
+}
+
+const char *ERR_reason_error_string(uint32_t packed_error) {
+ const char *reason_str = err_component_error_string(
+ ERR_PACK(ERR_GET_LIB(packed_error), 0, ERR_GET_REASON(packed_error)));
+
+ if (reason_str != NULL) {
+ return reason_str;
+ }
+
+ return err_component_error_string(
+ ERR_PACK(0, 0, ERR_GET_REASON(packed_error)));
+}
+
+void ERR_print_errors_cb(ERR_print_errors_callback_t callback, void *ctx) {
+ CRYPTO_THREADID current_thread;
+ char buf[ERR_ERROR_STRING_BUF_LEN];
+ char buf2[1024];
+ unsigned long thread_hash;
+ const char *file, *data;
+ int line, flags;
+ uint32_t packed_error;
+
+ CRYPTO_THREADID_current(&current_thread);
+ thread_hash = CRYPTO_THREADID_hash(&current_thread);
+
+ for (;;) {
+ packed_error = ERR_get_error_line_data(&file, &line, &data, &flags);
+ if (packed_error == 0) {
+ break;
+ }
+
+ ERR_error_string_n(packed_error, buf, sizeof(buf));
+ BIO_snprintf(buf2, sizeof(buf2), "%lu:%s:%s:%d:%s\n", thread_hash, buf,
+ file, line, (flags & ERR_FLAG_STRING) ? data : "");
+ if (callback(buf2, strlen(buf2), ctx) <= 0) {
+ break;
+ }
+ }
+}
+
+/* err_set_error_data sets the data on the most recent error. The |flags|
+ * argument is a combination of the |ERR_FLAG_*| values. */
+static void err_set_error_data(char *data, int flags) {
+ ERR_STATE *const state = err_get_state();
+ struct err_error_st *error;
+
+ if (state == NULL || state->top == state->bottom) {
+ if (flags & ERR_FLAG_MALLOCED) {
+ OPENSSL_free(data);
+ }
+ return;
+ }
+
+ error = &state->errors[state->top];
+
+ err_clear_data(error);
+ error->data = data;
+ error->flags = flags;
+}
+
+void ERR_put_error(int library, int func, int reason, const char *file,
+ unsigned line) {
+ ERR_STATE *const state = err_get_state();
+ struct err_error_st *error;
+
+ if (state == NULL) {
+ return;
+ }
+
+ if (library == ERR_LIB_SYS && reason == 0) {
+#if defined(WIN32)
+ reason = GetLastError();
+#else
+ reason = errno;
+#endif
+ }
+
+ state->top = (state->top + 1) % ERR_NUM_ERRORS;
+ if (state->top == state->bottom) {
+ state->bottom = (state->bottom + 1) % ERR_NUM_ERRORS;
+ }
+
+ error = &state->errors[state->top];
+ err_clear(error);
+ error->file = file;
+ error->line = line;
+ error->packed = ERR_PACK(library, func, reason);
+}
+
+/* ERR_add_error_data_vdata takes a variable number of const char* pointers,
+ * concatenates them and sets the result as the data on the most recent
+ * error. */
+static void err_add_error_vdata(unsigned num, va_list args) {
+ size_t alloced, new_len, len = 0, substr_len;
+ char *buf;
+ const char *substr;
+ unsigned i;
+
+ alloced = 80;
+ buf = OPENSSL_malloc(alloced + 1);
+ if (buf == NULL) {
+ return;
+ }
+
+ for (i = 0; i < num; i++) {
+ substr = va_arg(args, const char *);
+ if (substr == NULL) {
+ continue;
+ }
+
+ substr_len = strlen(substr);
+ new_len = len + substr_len;
+ if (new_len > alloced) {
+ char *new_buf;
+
+ if (alloced + 20 + 1 < alloced) {
+ /* overflow. */
+ OPENSSL_free(buf);
+ return;
+ }
+
+ alloced = new_len + 20;
+ new_buf = OPENSSL_realloc(buf, alloced + 1);
+ if (new_buf == NULL) {
+ OPENSSL_free(buf);
+ return;
+ }
+ buf = new_buf;
+ }
+
+ memcpy(buf + len, substr, substr_len);
+ len = new_len;
+ }
+
+ buf[len] = 0;
+ err_set_error_data(buf, ERR_FLAG_MALLOCED | ERR_FLAG_STRING);
+}
+
+void ERR_add_error_data(unsigned count, ...) {
+ va_list args;
+ va_start(args, count);
+ err_add_error_vdata(count, args);
+ va_end(args);
+}
+
+void ERR_add_error_dataf(const char *format, ...) {
+ va_list ap;
+ char *buf;
+ static const unsigned buf_len = 256;
+
+ /* A fixed-size buffer is used because va_copy (which would be needed in
+ * order to call vsnprintf twice and measure the buffer) wasn't defined until
+ * C99. */
+ buf = OPENSSL_malloc(buf_len + 1);
+ if (buf == NULL) {
+ return;
+ }
+
+ va_start(ap, format);
+ BIO_vsnprintf(buf, buf_len, format, ap);
+ buf[buf_len] = 0;
+ va_end(ap);
+
+ err_set_error_data(buf, ERR_FLAG_MALLOCED | ERR_FLAG_STRING);
+}
+
+int ERR_set_mark(void) {
+ ERR_STATE *const state = err_get_state();
+
+ if (state == NULL || state->bottom == state->top) {
+ return 0;
+ }
+ state->errors[state->top].flags |= ERR_FLAG_MARK;
+ return 1;
+}
+
+int ERR_pop_to_mark(void) {
+ ERR_STATE *const state = err_get_state();
+
+ if (state == NULL) {
+ return 0;
+ }
+
+ while (state->bottom != state->top) {
+ struct err_error_st *error = &state->errors[state->top];
+
+ if ((error->flags & ERR_FLAG_MARK) != 0) {
+ error->flags &= ~ERR_FLAG_MARK;
+ return 1;
+ }
+
+ err_clear(error);
+ if (state->top == 0) {
+ state->top = ERR_NUM_ERRORS - 1;
+ } else {
+ state->top--;
+ }
+ }
+
+ return 0;
+}
+
+static const char *const kLibraryNames[ERR_NUM_LIBS] = {
+ "invalid library (0)",
+ "unknown library", /* ERR_LIB_NONE */
+ "system library", /* ERR_LIB_SYS */
+ "bignum routines", /* ERR_LIB_BN */
+ "RSA routines", /* ERR_LIB_RSA */
+ "Diffie-Hellman routines", /* ERR_LIB_DH */
+ "public key routines", /* ERR_LIB_EVP */
+ "memory buffer routines", /* ERR_LIB_BUF */
+ "object identifier routines", /* ERR_LIB_OBJ */
+ "PEM routines", /* ERR_LIB_PEM */
+ "DSA routines", /* ERR_LIB_DSA */
+ "X.509 certificate routines", /* ERR_LIB_X509 */
+ "ASN.1 encoding routines", /* ERR_LIB_ASN1 */
+ "configuration file routines", /* ERR_LIB_CONF */
+ "common libcrypto routines", /* ERR_LIB_CRYPTO */
+ "elliptic curve routines", /* ERR_LIB_EC */
+ "SSL routines", /* ERR_LIB_SSL */
+ "BIO routines", /* ERR_LIB_BIO */
+ "PKCS7 routines", /* ERR_LIB_PKCS7 */
+ "PKCS8 routines", /* ERR_LIB_PKCS8 */
+ "X509 V3 routines", /* ERR_LIB_X509V3 */
+ "random number generator", /* ERR_LIB_RAND */
+ "ENGINE routines", /* ERR_LIB_ENGINE */
+ "OCSP routines", /* ERR_LIB_OCSP */
+ "UI routines", /* ERR_LIB_UI */
+ "COMP routines", /* ERR_LIB_COMP */
+ "ECDSA routines", /* ERR_LIB_ECDSA */
+ "ECDH routines", /* ERR_LIB_ECDH */
+ "HMAC routines", /* ERR_LIB_HMAC */
+ "Digest functions", /* ERR_LIB_DIGEST */
+ "Cipher functions", /* ERR_LIB_CIPHER */
+ "User defined functions", /* ERR_LIB_USER */
+ "HKDF functions", /* ERR_LIB_HKDF */
+};
+
+#define NUM_SYS_ERRNOS 127
+
+/* kStaticErrors provides storage for ERR_STRING_DATA values that are created
+ * at init time because we assume that ERR_STRING_DATA structures aren't
+ * allocated on the heap. */
+static ERR_STRING_DATA kStaticErrors[ERR_NUM_LIBS * 2 + NUM_SYS_ERRNOS];
+
+static const ERR_STRING_DATA kGlobalErrors[] = {
+ {ERR_R_MALLOC_FAILURE, "malloc failure"},
+ {ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED, "function should not be called"},
+ {ERR_R_PASSED_NULL_PARAMETER, "passed a null parameter"},
+ {ERR_R_INTERNAL_ERROR, "internal error"},
+ {ERR_R_OVERFLOW, "overflow"},
+
+ {ERR_PACK(ERR_LIB_SYS, SYS_F_fopen, 0), "fopen"},
+ {ERR_PACK(ERR_LIB_SYS, SYS_F_fclose, 0), "fclose"},
+ {ERR_PACK(ERR_LIB_SYS, SYS_F_fread, 0), "fread"},
+ {ERR_PACK(ERR_LIB_SYS, SYS_F_fwrite, 0), "fwrite"},
+ {ERR_PACK(ERR_LIB_SYS, SYS_F_socket, 0), "socket"},
+ {ERR_PACK(ERR_LIB_SYS, SYS_F_setsockopt, 0), "setsockopt"},
+ {ERR_PACK(ERR_LIB_SYS, SYS_F_connect, 0), "connect"},
+ {ERR_PACK(ERR_LIB_SYS, SYS_F_getaddrinfo, 0), "getaddrinfo"},
+
+ {0, NULL},
+};
+
+
+extern const ERR_STRING_DATA ASN1_error_string_data[];
+extern const ERR_STRING_DATA BIO_error_string_data[];
+extern const ERR_STRING_DATA BN_error_string_data[];
+extern const ERR_STRING_DATA BUF_error_string_data[];
+extern const ERR_STRING_DATA CIPHER_error_string_data[];
+extern const ERR_STRING_DATA CONF_error_string_data[];
+extern const ERR_STRING_DATA CRYPTO_error_string_data[];
+extern const ERR_STRING_DATA DH_error_string_data[];
+extern const ERR_STRING_DATA DIGEST_error_string_data[];
+extern const ERR_STRING_DATA DSA_error_string_data[];
+extern const ERR_STRING_DATA ECDH_error_string_data[];
+extern const ERR_STRING_DATA ECDSA_error_string_data[];
+extern const ERR_STRING_DATA EC_error_string_data[];
+extern const ERR_STRING_DATA ENGINE_error_string_data[];
+extern const ERR_STRING_DATA EVP_error_string_data[];
+extern const ERR_STRING_DATA HKDF_error_string_data[];
+extern const ERR_STRING_DATA OBJ_error_string_data[];
+extern const ERR_STRING_DATA PEM_error_string_data[];
+extern const ERR_STRING_DATA PKCS8_error_string_data[];
+extern const ERR_STRING_DATA RSA_error_string_data[];
+extern const ERR_STRING_DATA X509V3_error_string_data[];
+extern const ERR_STRING_DATA X509_error_string_data[];
+
+static void err_load_strings(void) {
+ unsigned i, j = 0;
+
+ err_fns_check();
+
+ /* This loop loads strings for the libraries for the ERR_R_*_LIB
+ * reasons. */
+ for (i = ERR_LIB_NONE; i < ERR_NUM_LIBS; i++) {
+ ERR_STRING_DATA *data = &kStaticErrors[j++];
+ data->string = kLibraryNames[i];
+ data->error = ERR_PACK(i, 0, 0);
+ ERRFN(set_item)(data);
+
+ data = &kStaticErrors[j++];
+ data->string = kLibraryNames[i];
+ data->error = ERR_PACK(0, 0, i);
+ ERRFN(set_item)(data);
+ }
+
+ for (i = 1; i < 1 + NUM_SYS_ERRNOS; i++) {
+ /* The "SYS" library sets errno values as the reason for its errors.
+ * Thus we load the first |NUM_SYS_ERRNOS| errno strings as the
+ * reason strings for that library. */
+
+ ERR_STRING_DATA *data = &kStaticErrors[j++];
+ data->string = strerror(i);
+ data->error = ERR_PACK(ERR_LIB_SYS, 0, i);
+ ERRFN(set_item)(data);
+ }
+
+ ERR_load_strings(kGlobalErrors);
+
+ ERR_load_strings(ASN1_error_string_data);
+ ERR_load_strings(BIO_error_string_data);
+ ERR_load_strings(BN_error_string_data);
+ ERR_load_strings(BUF_error_string_data);
+ ERR_load_strings(CIPHER_error_string_data);
+ ERR_load_strings(CONF_error_string_data);
+ ERR_load_strings(CRYPTO_error_string_data);
+ ERR_load_strings(DH_error_string_data);
+ ERR_load_strings(DIGEST_error_string_data);
+ ERR_load_strings(DSA_error_string_data);
+ ERR_load_strings(ECDH_error_string_data);
+ ERR_load_strings(ECDSA_error_string_data);
+ ERR_load_strings(EC_error_string_data);
+ ERR_load_strings(ENGINE_error_string_data);
+ ERR_load_strings(EVP_error_string_data);
+ ERR_load_strings(HKDF_error_string_data);
+ ERR_load_strings(OBJ_error_string_data);
+ ERR_load_strings(PEM_error_string_data);
+ ERR_load_strings(PKCS8_error_string_data);
+ ERR_load_strings(RSA_error_string_data);
+ ERR_load_strings(X509V3_error_string_data);
+ ERR_load_strings(X509_error_string_data);
+}
+
+void ERR_load_strings(const ERR_STRING_DATA *str) {
+ err_fns_check();
+
+ while (str->error) {
+ ERRFN(set_item)(str);
+ str++;
+ }
+}
+
+void ERR_load_crypto_strings(void) { err_load_strings(); }
+
+void ERR_free_strings(void) {
+ err_fns_check();
+ ERRFN(shutdown)(err_state_free);
+}
+
+void ERR_load_BIO_strings(void) {}
diff --git a/src/crypto/err/err_impl.c b/src/crypto/err/err_impl.c
new file mode 100644
index 0000000..32cff35
--- /dev/null
+++ b/src/crypto/err/err_impl.c
@@ -0,0 +1,323 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/err.h>
+
+#include <assert.h>
+#include <string.h>
+
+#include <openssl/lhash.h>
+#include <openssl/mem.h>
+
+
+DEFINE_LHASH_OF(ERR_STATE);
+DEFINE_LHASH_OF(ERR_STRING_DATA);
+
+/* state_hash is a map from thread ID to ERR_STATE. It works like thread-local
+ * storage. */
+static LHASH_OF(ERR_STATE) *state_hash = NULL;
+
+/* error_hash maps from a packed error to the string for that library /
+ * function / reason. */
+static LHASH_OF(ERR_STRING_DATA) *error_hash = NULL;
+
+/* global_next_library contains the next custom library value to return. */
+static int global_next_library = ERR_NUM_LIBS;
+
+/* err_string_data_hash is an lhash hash function for ERR_STRING_DATA. */
+static uint32_t err_string_data_hash(const ERR_STRING_DATA *a) {
+ return OPENSSL_hash32(&a->error, sizeof(a->error));
+}
+
+/* err_string_data_cmp is an lhash compare function for ERR_STRING_DATA. */
+static int err_string_data_cmp(const ERR_STRING_DATA *a,
+ const ERR_STRING_DATA *b) {
+ return ((int)a->error) - ((int)b->error);
+}
+
+/* error_hash_get_write_locked returns the hash that maps from packed error to
+ * error string and creates it if need be. The caller must hold a write lock on
+ * LOCK_ERR. */
+static LHASH_OF(ERR_STRING_DATA) * error_hash_get_write_locked(void) {
+ if (!error_hash) {
+ error_hash = lh_ERR_STRING_DATA_new(err_string_data_hash, err_string_data_cmp);
+ }
+
+ return error_hash;
+}
+
+/* err_get_item returns an ERR_STRING_DATA with an |error| member that
+ * equals |packed_error|, or NULL if none can be found. */
+static ERR_STRING_DATA *err_get_item(uint32_t packed_error) {
+ ERR_STRING_DATA *ret = NULL, pattern;
+
+ pattern.error = packed_error;
+
+ CRYPTO_r_lock(CRYPTO_LOCK_ERR);
+ if (error_hash) {
+ ret = lh_ERR_STRING_DATA_retrieve(error_hash, &pattern);
+ }
+ CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
+
+ return ret;
+}
+
+/* err_set_item adds an ERR_STRING_DATA to the global hash of error strings and
+ * returns the previous entry with the same |err->error| value, if any. */
+static ERR_STRING_DATA *err_set_item(const ERR_STRING_DATA *err) {
+ ERR_STRING_DATA *old_item = NULL;
+ LHASH_OF(ERR_STRING_DATA) *hash;
+
+ CRYPTO_w_lock(CRYPTO_LOCK_ERR);
+ hash = error_hash_get_write_locked();
+ if (hash) {
+ lh_ERR_STRING_DATA_insert(hash, &old_item, (ERR_STRING_DATA*) err);
+ }
+ CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
+
+ return old_item;
+}
+
+/* err_set_item removes an item from the global hash of error strings for
+ * |packed_error| and returns the removed entry, if any. */
+static ERR_STRING_DATA *err_del_item(uint32_t packed_error) {
+ ERR_STRING_DATA *old_item = NULL, pattern;
+
+ pattern.error = packed_error;
+
+ CRYPTO_w_lock(CRYPTO_LOCK_ERR);
+ if (error_hash) {
+ old_item = lh_ERR_STRING_DATA_delete(error_hash, &pattern);
+ }
+ CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
+
+ return old_item;
+}
+
+
+/* err_state_hash is an lhash hash function for ERR_STATE. */
+static uint32_t err_state_hash(const ERR_STATE *a) {
+ return CRYPTO_THREADID_hash(&a->tid);
+}
+
+/* err_state_cmp is an lhash compare function for ERR_STATE. */
+static int err_state_cmp(const ERR_STATE *a, const ERR_STATE *b) {
+ return CRYPTO_THREADID_cmp(&a->tid, &b->tid);
+}
+
+
+static ERR_STATE *err_get_state(void) {
+ CRYPTO_THREADID tid;
+ ERR_STATE pattern, *state, *race_state;
+ int insert_result;
+ static ERR_STATE fallback;
+
+ CRYPTO_THREADID_current(&tid);
+ memset(&pattern, 0, sizeof(pattern));
+ CRYPTO_THREADID_cpy(&pattern.tid, &tid);
+
+ CRYPTO_r_lock(CRYPTO_LOCK_ERR);
+ if (state_hash == NULL) {
+ CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
+ CRYPTO_w_lock(CRYPTO_LOCK_ERR);
+ if (state_hash == NULL) {
+ state_hash = lh_ERR_STATE_new(err_state_hash, err_state_cmp);
+ }
+ CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
+ CRYPTO_r_lock(CRYPTO_LOCK_ERR);
+ }
+
+ if (state_hash == NULL) {
+ CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
+ return NULL;
+ }
+
+ state = lh_ERR_STATE_retrieve(state_hash, &pattern);
+ CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
+ if (state != NULL) {
+ return state;
+ }
+
+ state = OPENSSL_malloc(sizeof(ERR_STATE));
+ if (state == NULL) {
+ CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
+ /* The other error functions don't cope with a failure to get the error
+ * state, so we return a dummy value. */
+ return &fallback;
+ }
+
+ memset(state, 0, sizeof(ERR_STATE));
+ CRYPTO_THREADID_cpy(&state->tid, &tid);
+
+ CRYPTO_w_lock(CRYPTO_LOCK_ERR);
+ insert_result = lh_ERR_STATE_insert(state_hash, &race_state, state);
+ CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
+
+ if (!insert_result) {
+ /* Insertion failed because of malloc failure. */
+ OPENSSL_free(state);
+ return &fallback;
+ }
+
+ /* We cannot have raced with another thread to insert an ERR_STATE because no
+ * other thread should be inserting values for this thread. */
+ assert(race_state == NULL);
+
+ return state;
+}
+
+static ERR_STATE *err_release_state(const CRYPTO_THREADID *tid) {
+ ERR_STATE pattern, *state;
+
+ CRYPTO_THREADID_cpy(&pattern.tid, tid);
+
+ CRYPTO_r_lock(CRYPTO_LOCK_ERR);
+ if (state_hash == NULL) {
+ CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
+ return NULL;
+ }
+
+ state = lh_ERR_STATE_delete(state_hash, &pattern);
+ CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
+
+ return state;
+}
+
+static void err_shutdown(void (*err_state_free_cb)(ERR_STATE*)) {
+ CRYPTO_w_lock(CRYPTO_LOCK_ERR);
+ if (error_hash) {
+ lh_ERR_STRING_DATA_free(error_hash);
+ error_hash = NULL;
+ }
+ if (state_hash) {
+ lh_ERR_STATE_doall(state_hash, err_state_free_cb);
+ lh_ERR_STATE_free(state_hash);
+ state_hash = NULL;
+ }
+ CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
+}
+
+static int err_get_next_library(void) {
+ int ret;
+
+ CRYPTO_w_lock(CRYPTO_LOCK_ERR);
+ ret = global_next_library++;
+ CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
+
+ return ret;
+}
+
+const struct ERR_FNS_st openssl_err_default_impl = {
+ err_shutdown,
+ err_get_item,
+ err_set_item,
+ err_del_item,
+ err_get_state,
+ err_release_state,
+ err_get_next_library,
+};
diff --git a/src/crypto/err/err_test.c b/src/crypto/err/err_test.c
new file mode 100644
index 0000000..bf36201
--- /dev/null
+++ b/src/crypto/err/err_test.c
@@ -0,0 +1,140 @@
+/* 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 <stdio.h>
+#include <string.h>
+
+#include <openssl/crypto.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+
+
+static int test_overflow(void) {
+ unsigned i;
+
+ for (i = 0; i < ERR_NUM_ERRORS*2; i++) {
+ ERR_put_error(1, 2, i+1, "test", 1);
+ }
+
+ for (i = 0; i < ERR_NUM_ERRORS - 1; i++) {
+ uint32_t err = ERR_get_error();
+ /* Errors are returned in order they were pushed, with the least recent ones
+ * removed, up to |ERR_NUM_ERRORS - 1| errors. So the errors returned are
+ * |ERR_NUM_ERRORS + 2| through |ERR_NUM_ERRORS * 2|, inclusive. */
+ if (err == 0 || ERR_GET_REASON(err) != i + ERR_NUM_ERRORS + 2) {
+ fprintf(stderr, "ERR_get_error failed at %u\n", i);
+ return 0;
+ }
+ }
+
+ if (ERR_get_error() != 0) {
+ fprintf(stderr, "ERR_get_error more than the expected number of values.\n");
+ return 0;
+ }
+
+ return 1;
+}
+
+static int test_put_error(void) {
+ uint32_t peeked_packed_error, packed_error;
+ int peeked_line, line, peeked_flags, flags;
+ const char *peeked_file, *file, *peeked_data, *data;
+
+ if (ERR_get_error() != 0) {
+ fprintf(stderr, "ERR_get_error returned value before an error was added.\n");
+ return 0;
+ }
+
+ ERR_put_error(1, 2, 3, "test", 4);
+ ERR_add_error_data(1, "testing");
+
+ peeked_packed_error = ERR_peek_error_line_data(&peeked_file, &peeked_line,
+ &peeked_data, &peeked_flags);
+ packed_error = ERR_get_error_line_data(&file, &line, &data, &flags);
+
+ if (peeked_packed_error != packed_error ||
+ peeked_file != file ||
+ peeked_data != data ||
+ peeked_flags != flags) {
+ fprintf(stderr, "Bad peeked error data returned.\n");
+ return 0;
+ }
+
+ if (strcmp(file, "test") != 0 ||
+ line != 4 ||
+ (flags & ERR_FLAG_STRING) == 0 ||
+ ERR_GET_LIB(packed_error) != 1 ||
+ ERR_GET_FUNC(packed_error) != 2 ||
+ ERR_GET_REASON(packed_error) != 3 ||
+ strcmp(data, "testing") != 0) {
+ fprintf(stderr, "Bad error data returned.\n");
+ return 0;
+ }
+
+ return 1;
+}
+
+static int test_clear_error(void) {
+ if (ERR_get_error() != 0) {
+ fprintf(stderr, "ERR_get_error returned value before an error was added.\n");
+ return 0;
+ }
+
+ ERR_put_error(1, 2, 3, "test", 4);
+ ERR_clear_error();
+
+ if (ERR_get_error() != 0) {
+ fprintf(stderr, "Error remained after clearing.\n");
+ return 0;
+ }
+
+ return 1;
+}
+
+static int test_print(void) {
+ size_t i;
+ char buf[256];
+ uint32_t packed_error;
+
+ ERR_put_error(1, 2, 3, "test", 4);
+ ERR_add_error_data(1, "testing");
+ packed_error = ERR_get_error();
+
+ for (i = 0; i <= sizeof(buf); i++) {
+ ERR_error_string_n(packed_error, buf, i);
+ }
+
+ return 1;
+}
+
+static int test_release(void) {
+ ERR_put_error(1, 2, 3, "test", 4);
+ ERR_remove_thread_state(NULL);
+ return 1;
+}
+
+int main(void) {
+ CRYPTO_library_init();
+
+ if (!test_overflow() ||
+ !test_put_error() ||
+ !test_clear_error() ||
+ !test_print() ||
+ !test_release()) {
+ return 1;
+ }
+
+ printf("PASS\n");
+ return 0;
+}
diff --git a/src/crypto/evp/CMakeLists.txt b/src/crypto/evp/CMakeLists.txt
new file mode 100644
index 0000000..9854a18
--- /dev/null
+++ b/src/crypto/evp/CMakeLists.txt
@@ -0,0 +1,38 @@
+include_directories(. .. ../../include)
+
+add_library(
+ evp
+
+ OBJECT
+
+ algorithm.c
+ asn1.c
+ digestsign.c
+ evp.c
+ evp_ctx.c
+ evp_error.c
+ p_ec.c
+ p_ec_asn1.c
+ p_hmac.c
+ p_hmac_asn1.c
+ p_rsa.c
+ p_rsa_asn1.c
+ pbkdf.c
+ sign.c
+)
+
+
+add_executable(
+ evp_test
+
+ evp_test.c
+)
+
+add_executable(
+ pbkdf_test
+
+ pbkdf_test.c
+)
+
+target_link_libraries(evp_test crypto)
+target_link_libraries(pbkdf_test crypto)
diff --git a/src/crypto/evp/algorithm.c b/src/crypto/evp/algorithm.c
new file mode 100644
index 0000000..ea28dfa
--- /dev/null
+++ b/src/crypto/evp/algorithm.c
@@ -0,0 +1,159 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/evp.h>
+
+#include <assert.h>
+
+#include <openssl/asn1.h>
+#include <openssl/err.h>
+#include <openssl/obj.h>
+#include <openssl/x509.h>
+
+#include "internal.h"
+
+
+int EVP_DigestSignAlgorithm(EVP_MD_CTX *ctx, X509_ALGOR *algor) {
+ const EVP_MD *digest;
+ EVP_PKEY *pkey;
+ int sign_nid, paramtype;
+
+ digest = EVP_MD_CTX_md(ctx);
+ pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx);
+ if (!digest || !pkey) {
+ OPENSSL_PUT_ERROR(EVP, EVP_DigestSignAlgorithm,
+ EVP_R_CONTEXT_NOT_INITIALISED);
+ return 0;
+ }
+
+ if (pkey->ameth->digest_sign_algorithm) {
+ switch (pkey->ameth->digest_sign_algorithm(ctx, algor)) {
+ case EVP_DIGEST_SIGN_ALGORITHM_ERROR:
+ return 0;
+ case EVP_DIGEST_SIGN_ALGORITHM_SUCCESS:
+ return 1;
+ case EVP_DIGEST_SIGN_ALGORITHM_DEFAULT:
+ /* Use default behavior. */
+ break;
+ default:
+ assert(0);
+ }
+ }
+
+ /* Default behavior: look up the OID for the algorithm/hash pair and encode
+ * that. */
+ if (!OBJ_find_sigid_by_algs(&sign_nid, EVP_MD_type(digest),
+ pkey->ameth->pkey_id)) {
+ OPENSSL_PUT_ERROR(EVP, EVP_DigestSignAlgorithm,
+ EVP_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED);
+ return 0;
+ }
+
+ if (pkey->ameth->pkey_flags & ASN1_PKEY_SIGPARAM_NULL) {
+ paramtype = V_ASN1_NULL;
+ } else {
+ paramtype = V_ASN1_UNDEF;
+ }
+
+ X509_ALGOR_set0(algor, OBJ_nid2obj(sign_nid), paramtype, NULL);
+ return 1;
+}
+
+int EVP_DigestVerifyInitFromAlgorithm(EVP_MD_CTX *ctx,
+ X509_ALGOR *algor,
+ EVP_PKEY *pkey) {
+ int digest_nid, pkey_nid;
+ const EVP_PKEY_ASN1_METHOD *ameth;
+ const EVP_MD *digest;
+
+ /* Convert signature OID into digest and public key OIDs */
+ if (!OBJ_find_sigid_algs(OBJ_obj2nid(algor->algorithm), &digest_nid,
+ &pkey_nid)) {
+ OPENSSL_PUT_ERROR(EVP, EVP_DigestVerifyInitFromAlgorithm,
+ EVP_R_UNKNOWN_SIGNATURE_ALGORITHM);
+ return 0;
+ }
+
+ /* Check public key OID matches public key type */
+ ameth = EVP_PKEY_asn1_find(NULL, pkey_nid);
+ if (ameth == NULL || ameth->pkey_id != pkey->ameth->pkey_id) {
+ OPENSSL_PUT_ERROR(EVP, EVP_DigestVerifyInitFromAlgorithm,
+ EVP_R_WRONG_PUBLIC_KEY_TYPE);
+ return 0;
+ }
+
+ /* NID_undef signals that there are custom parameters to set. */
+ if (digest_nid == NID_undef) {
+ if (!pkey->ameth || !pkey->ameth->digest_verify_init_from_algorithm) {
+ OPENSSL_PUT_ERROR(EVP, EVP_DigestVerifyInitFromAlgorithm,
+ EVP_R_UNKNOWN_SIGNATURE_ALGORITHM);
+ return 0;
+ }
+
+ return pkey->ameth->digest_verify_init_from_algorithm(ctx, algor, pkey);
+ }
+
+ /* Otherwise, initialize with the digest from the OID. */
+ digest = EVP_get_digestbynid(digest_nid);
+ if (digest == NULL) {
+ OPENSSL_PUT_ERROR(EVP, EVP_DigestVerifyInitFromAlgorithm,
+ EVP_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM);
+ return 0;
+ }
+
+ return EVP_DigestVerifyInit(ctx, NULL, digest, NULL, pkey);
+}
+
diff --git a/src/crypto/evp/asn1.c b/src/crypto/evp/asn1.c
new file mode 100644
index 0000000..27ae017
--- /dev/null
+++ b/src/crypto/evp/asn1.c
@@ -0,0 +1,167 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/evp.h>
+
+#include <openssl/asn1.h>
+#include <openssl/err.h>
+#include <openssl/obj.h>
+#include <openssl/x509.h>
+
+#include "internal.h"
+
+
+EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **out, const uint8_t **inp,
+ long len) {
+ EVP_PKEY *ret;
+
+ if (out == NULL || *out == NULL) {
+ ret = EVP_PKEY_new();
+ if (ret == NULL) {
+ OPENSSL_PUT_ERROR(EVP, d2i_PrivateKey, ERR_R_EVP_LIB);
+ return NULL;
+ }
+ } else {
+ ret = *out;
+ }
+
+ if (!EVP_PKEY_set_type(ret, type)) {
+ OPENSSL_PUT_ERROR(EVP, d2i_PrivateKey, EVP_R_UNKNOWN_PUBLIC_KEY_TYPE);
+ goto err;
+ }
+
+ if (!ret->ameth->old_priv_decode ||
+ !ret->ameth->old_priv_decode(ret, inp, len)) {
+ if (ret->ameth->priv_decode) {
+ PKCS8_PRIV_KEY_INFO *p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, inp, len);
+ if (!p8) {
+ goto err;
+ }
+ EVP_PKEY_free(ret);
+ ret = EVP_PKCS82PKEY(p8);
+ PKCS8_PRIV_KEY_INFO_free(p8);
+ } else {
+ OPENSSL_PUT_ERROR(EVP, d2i_PrivateKey, ERR_R_ASN1_LIB);
+ goto err;
+ }
+ }
+
+ if (out != NULL) {
+ *out = ret;
+ }
+ return ret;
+
+err:
+ if (ret != NULL && (out == NULL || *out != ret)) {
+ EVP_PKEY_free(ret);
+ }
+ return NULL;
+}
+
+EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **out, const uint8_t **inp, long len) {
+ STACK_OF(ASN1_TYPE) *inkey;
+ const uint8_t *p;
+ int keytype;
+ p = *inp;
+
+ /* Dirty trick: read in the ASN1 data into out 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, len);
+ /* 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, inp, len);
+ EVP_PKEY *ret;
+
+ sk_ASN1_TYPE_pop_free(inkey, ASN1_TYPE_free);
+ if (!p8) {
+ OPENSSL_PUT_ERROR(EVP, d2i_AutoPrivateKey,
+ EVP_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
+ return NULL;
+ }
+ ret = EVP_PKCS82PKEY(p8);
+ PKCS8_PRIV_KEY_INFO_free(p8);
+ if (out) {
+ *out = ret;
+ }
+ return ret;
+ } else {
+ keytype = EVP_PKEY_RSA;
+ }
+
+ sk_ASN1_TYPE_pop_free(inkey, ASN1_TYPE_free);
+ return d2i_PrivateKey(keytype, out, inp, len);
+}
+
+int i2d_PublicKey(EVP_PKEY *key, uint8_t **outp) {
+ switch (key->type) {
+ case EVP_PKEY_RSA:
+ return i2d_RSAPublicKey(key->pkey.rsa, outp);
+ case EVP_PKEY_DSA:
+ return i2d_DSAPublicKey(key->pkey.dsa, outp);
+ case EVP_PKEY_EC:
+ return i2o_ECPublicKey(key->pkey.ec, outp);
+ default:
+ OPENSSL_PUT_ERROR(EVP, i2d_PublicKey, EVP_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
+ return -1;
+ }
+}
diff --git a/src/crypto/evp/digestsign.c b/src/crypto/evp/digestsign.c
new file mode 100644
index 0000000..c86b805
--- /dev/null
+++ b/src/crypto/evp/digestsign.c
@@ -0,0 +1,205 @@
+/* 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 <openssl/evp.h>
+
+#include <openssl/digest.h>
+#include <openssl/err.h>
+
+#include "internal.h"
+#include "../digest/internal.h"
+
+
+/* md_begin_digset is a callback from the |EVP_MD_CTX| code that is called when
+ * a new digest is begun. */
+static int md_begin_digest(EVP_MD_CTX *ctx) {
+ int r = EVP_PKEY_CTX_ctrl(ctx->pctx, -1, EVP_PKEY_OP_TYPE_SIG,
+ EVP_PKEY_CTRL_DIGESTINIT, 0, ctx);
+ return r > 0 || r == -2;
+}
+
+static const struct evp_md_pctx_ops md_pctx_ops = {
+ EVP_PKEY_CTX_free,
+ EVP_PKEY_CTX_dup,
+ md_begin_digest,
+};
+
+static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
+ const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey,
+ int is_verify) {
+ if (ctx->pctx == NULL) {
+ ctx->pctx = EVP_PKEY_CTX_new(pkey, e);
+ }
+ if (ctx->pctx == NULL) {
+ return 0;
+ }
+ ctx->pctx_ops = &md_pctx_ops;
+
+ if (type == NULL) {
+ type = EVP_sha1();
+ }
+
+ if (type == NULL) {
+ OPENSSL_PUT_ERROR(EVP, do_sigver_init, EVP_R_NO_DEFAULT_DIGEST);
+ return 0;
+ }
+
+ if (is_verify) {
+ 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 (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 (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 (!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_DigestSignUpdate(EVP_MD_CTX *ctx, const void *data, size_t len) {
+ return EVP_DigestUpdate(ctx, data, len);
+}
+
+int EVP_DigestVerifyUpdate(EVP_MD_CTX *ctx, const void *data, size_t len) {
+ return EVP_DigestUpdate(ctx, data, len);
+}
+
+int EVP_DigestSignFinal(EVP_MD_CTX *ctx, uint8_t *out_sig,
+ size_t *out_sig_len) {
+ int r = 0;
+ const int has_signctx = ctx->pctx->pmeth->signctx != NULL;
+
+ if (out_sig) {
+ EVP_MD_CTX tmp_ctx;
+ uint8_t md[EVP_MAX_MD_SIZE];
+ unsigned int mdlen;
+
+ EVP_MD_CTX_init(&tmp_ctx);
+ if (!EVP_MD_CTX_copy_ex(&tmp_ctx, ctx)) {
+ return 0;
+ }
+ if (has_signctx) {
+ r = tmp_ctx.pctx->pmeth->signctx(tmp_ctx.pctx, out_sig, out_sig_len, &tmp_ctx);
+ } else {
+ r = EVP_DigestFinal_ex(&tmp_ctx, md, &mdlen);
+ }
+ EVP_MD_CTX_cleanup(&tmp_ctx);
+ if (has_signctx || !r) {
+ return r;
+ }
+ return EVP_PKEY_sign(ctx->pctx, out_sig, out_sig_len, md, mdlen);
+ } else {
+ if (has_signctx) {
+ return ctx->pctx->pmeth->signctx(ctx->pctx, out_sig, out_sig_len, ctx);
+ } else {
+ size_t s = EVP_MD_size(ctx->digest);
+ return EVP_PKEY_sign(ctx->pctx, out_sig, out_sig_len, NULL, s);
+ }
+ }
+}
+
+int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const uint8_t *sig,
+ size_t sig_len) {
+ EVP_MD_CTX tmp_ctx;
+ uint8_t md[EVP_MAX_MD_SIZE];
+ int r;
+ unsigned int mdlen;
+ const int has_verifyctx = ctx->pctx->pmeth->verifyctx != NULL;
+
+ EVP_MD_CTX_init(&tmp_ctx);
+ if (!EVP_MD_CTX_copy_ex(&tmp_ctx, ctx)) {
+ return 0;
+ }
+ if (has_verifyctx) {
+ r = tmp_ctx.pctx->pmeth->verifyctx(tmp_ctx.pctx, sig, sig_len, &tmp_ctx);
+ } else {
+ r = EVP_DigestFinal_ex(&tmp_ctx, md, &mdlen);
+ }
+
+ EVP_MD_CTX_cleanup(&tmp_ctx);
+ if (has_verifyctx || !r) {
+ return r;
+ }
+ return EVP_PKEY_verify(ctx->pctx, sig, sig_len, md, mdlen);
+}
diff --git a/src/crypto/evp/evp.c b/src/crypto/evp/evp.c
new file mode 100644
index 0000000..8a1d513
--- /dev/null
+++ b/src/crypto/evp/evp.c
@@ -0,0 +1,440 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/evp.h>
+
+#include <assert.h>
+#include <string.h>
+
+#include <openssl/bio.h>
+#include <openssl/dh.h>
+#include <openssl/dsa.h>
+#include <openssl/ec.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/rsa.h>
+
+#include "internal.h"
+
+
+extern const EVP_PKEY_ASN1_METHOD ec_asn1_meth;
+extern const EVP_PKEY_ASN1_METHOD hmac_asn1_meth;
+extern const EVP_PKEY_ASN1_METHOD rsa_asn1_meth;
+
+EVP_PKEY *EVP_PKEY_new(void) {
+ EVP_PKEY *ret;
+
+ ret = OPENSSL_malloc(sizeof(EVP_PKEY));
+ if (ret == NULL) {
+ OPENSSL_PUT_ERROR(EVP, EVP_PKEY_new, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ memset(ret, 0, sizeof(EVP_PKEY));
+ ret->type = EVP_PKEY_NONE;
+ ret->references = 1;
+
+ return ret;
+}
+
+static void free_it(EVP_PKEY *pkey) {
+ if (pkey->ameth && pkey->ameth->pkey_free) {
+ pkey->ameth->pkey_free(pkey);
+ pkey->pkey.ptr = NULL;
+ pkey->type = EVP_PKEY_NONE;
+ }
+}
+
+void EVP_PKEY_free(EVP_PKEY *pkey) {
+ if (pkey == NULL) {
+ return;
+ }
+
+ if (CRYPTO_add(&pkey->references, -1, CRYPTO_LOCK_EVP_PKEY)) {
+ return;
+ }
+
+ free_it(pkey);
+ if (pkey->attributes) {
+ /* TODO(fork): layering: X509_ATTRIBUTE_free is an X.509 function. In
+ * practice this path isn't called but should be removed in the future. */
+ /*sk_X509_ATTRIBUTE_pop_free(pkey->attributes, X509_ATTRIBUTE_free);*/
+ assert(0);
+ }
+ OPENSSL_free(pkey);
+}
+
+int EVP_PKEY_is_opaque(const EVP_PKEY *pkey) {
+ if (pkey->ameth && pkey->ameth->pkey_opaque) {
+ return pkey->ameth->pkey_opaque(pkey);
+ }
+ return 0;
+}
+
+int EVP_PKEY_supports_digest(const EVP_PKEY *pkey, const EVP_MD *md) {
+ if (pkey->ameth && pkey->ameth->pkey_supports_digest) {
+ return pkey->ameth->pkey_supports_digest(pkey, md);
+ }
+ return 1;
+}
+
+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_dup(EVP_PKEY *pkey) {
+ CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY);
+ return pkey;
+}
+
+int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) {
+ if (to->type != from->type) {
+ OPENSSL_PUT_ERROR(EVP, EVP_PKEY_copy_parameters, EVP_R_DIFFERENT_KEY_TYPES);
+ goto err;
+ }
+
+ if (EVP_PKEY_missing_parameters(from)) {
+ OPENSSL_PUT_ERROR(EVP, EVP_PKEY_copy_parameters, 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_size(const EVP_PKEY *pkey) {
+ if (pkey && pkey->ameth && pkey->ameth->pkey_size) {
+ return pkey->ameth->pkey_size(pkey);
+ }
+ return 0;
+}
+
+int EVP_PKEY_bits(EVP_PKEY *pkey) {
+ if (pkey && pkey->ameth && pkey->ameth->pkey_bits) {
+ return pkey->ameth->pkey_bits(pkey);
+ }
+ return 0;
+}
+
+int EVP_PKEY_id(const EVP_PKEY *pkey) {
+ return pkey->type;
+}
+
+/* TODO(fork): remove the first argument. */
+const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find(ENGINE **pengine, int nid) {
+ switch (nid) {
+ case EVP_PKEY_RSA:
+ case EVP_PKEY_RSA2:
+ return &rsa_asn1_meth;
+ case EVP_PKEY_HMAC:
+ return &hmac_asn1_meth;
+ case EVP_PKEY_EC:
+ return &ec_asn1_meth;
+ default:
+ return NULL;
+ }
+}
+
+int EVP_PKEY_type(int nid) {
+ const EVP_PKEY_ASN1_METHOD *meth = EVP_PKEY_asn1_find(NULL, nid);
+ if (meth == NULL) {
+ return NID_undef;
+ }
+ return meth->pkey_id;
+}
+
+EVP_PKEY *EVP_PKEY_new_mac_key(int type, ENGINE *e, const uint8_t *mac_key,
+ size_t mac_key_len) {
+ EVP_PKEY_CTX *mac_ctx = NULL;
+ EVP_PKEY *ret = NULL;
+
+ mac_ctx = EVP_PKEY_CTX_new_id(type, e);
+ if (!mac_ctx) {
+ return NULL;
+ }
+
+ if (EVP_PKEY_keygen_init(mac_ctx) <= 0 ||
+ EVP_PKEY_CTX_ctrl(mac_ctx, -1, EVP_PKEY_OP_KEYGEN,
+ EVP_PKEY_CTRL_SET_MAC_KEY, mac_key_len,
+ (uint8_t *)mac_key) <= 0 ||
+ EVP_PKEY_keygen(mac_ctx, &ret) <= 0) {
+ ret = NULL;
+ goto merr;
+ }
+
+merr:
+ if (mac_ctx)
+ EVP_PKEY_CTX_free(mac_ctx);
+ return ret;
+}
+
+int EVP_PKEY_set1_RSA(EVP_PKEY *pkey, RSA *key) {
+ if (EVP_PKEY_assign_RSA(pkey, key)) {
+ RSA_up_ref(key);
+ return 1;
+ }
+ return 0;
+}
+
+int EVP_PKEY_assign_RSA(EVP_PKEY *pkey, RSA *key) {
+ return EVP_PKEY_assign(pkey, EVP_PKEY_RSA, key);
+}
+
+RSA *EVP_PKEY_get1_RSA(EVP_PKEY *pkey) {
+ if (pkey->type != EVP_PKEY_RSA) {
+ OPENSSL_PUT_ERROR(EVP, EVP_PKEY_get1_RSA, EVP_R_EXPECTING_AN_RSA_KEY);
+ return NULL;
+ }
+ RSA_up_ref(pkey->pkey.rsa);
+ return pkey->pkey.rsa;
+}
+
+int EVP_PKEY_set1_DSA(EVP_PKEY *pkey, DSA *key) {
+ if (EVP_PKEY_assign_DSA(pkey, key)) {
+ DSA_up_ref(key);
+ return 1;
+ }
+ return 0;
+}
+
+int EVP_PKEY_assign_DSA(EVP_PKEY *pkey, DSA *key) {
+ return EVP_PKEY_assign(pkey, EVP_PKEY_DSA, key);
+}
+
+DSA *EVP_PKEY_get1_DSA(EVP_PKEY *pkey) {
+ if (pkey->type != EVP_PKEY_DSA) {
+ OPENSSL_PUT_ERROR(EVP, EVP_PKEY_get1_DSA, EVP_R_EXPECTING_A_DSA_KEY);
+ return NULL;
+ }
+ DSA_up_ref(pkey->pkey.dsa);
+ return pkey->pkey.dsa;
+}
+
+int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, EC_KEY *key) {
+ if (EVP_PKEY_assign_EC_KEY(pkey, key)) {
+ EC_KEY_up_ref(key);
+ return 1;
+ }
+ return 0;
+}
+
+int EVP_PKEY_assign_EC_KEY(EVP_PKEY *pkey, EC_KEY *key) {
+ return EVP_PKEY_assign(pkey, EVP_PKEY_EC, key);
+}
+
+EC_KEY *EVP_PKEY_get1_EC_KEY(EVP_PKEY *pkey) {
+ if (pkey->type != EVP_PKEY_EC) {
+ OPENSSL_PUT_ERROR(EVP, EVP_PKEY_get1_EC_KEY, EVP_R_EXPECTING_AN_EC_KEY_KEY);
+ return NULL;
+ }
+ EC_KEY_up_ref(pkey->pkey.ec);
+ return pkey->pkey.ec;
+}
+
+int EVP_PKEY_set1_DH(EVP_PKEY *pkey, DH *key) {
+ if (EVP_PKEY_assign_DH(pkey, key)) {
+ DH_up_ref(key);
+ return 1;
+ }
+ return 0;
+}
+
+int EVP_PKEY_assign_DH(EVP_PKEY *pkey, DH *key) {
+ return EVP_PKEY_assign(pkey, EVP_PKEY_EC, key);
+}
+
+DH *EVP_PKEY_get1_DH(EVP_PKEY *pkey) {
+ if (pkey->type != EVP_PKEY_DH) {
+ OPENSSL_PUT_ERROR(EVP, EVP_PKEY_get1_DH, EVP_R_EXPECTING_A_DH_KEY);
+ return NULL;
+ }
+ DH_up_ref(pkey->pkey.dh);
+ return pkey->pkey.dh;
+}
+
+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;
+}
+
+const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find_str(ENGINE **pengine,
+ const char *name,
+ size_t len) {
+ if (len == 3 && memcmp(name, "RSA", 3) == 0) {
+ return &rsa_asn1_meth;
+ } else if (len == 4 && memcmp(name, "HMAC", 4) == 0) {
+ return &hmac_asn1_meth;
+ } if (len == 2 && memcmp(name, "EC", 2) == 0) {
+ return &ec_asn1_meth;
+ }
+ return NULL;
+}
+
+int EVP_PKEY_set_type(EVP_PKEY *pkey, int type) {
+ const EVP_PKEY_ASN1_METHOD *ameth;
+
+ if (pkey && pkey->pkey.ptr) {
+ free_it(pkey);
+ }
+
+ ameth = EVP_PKEY_asn1_find(NULL, type);
+ if (ameth == NULL) {
+ OPENSSL_PUT_ERROR(EVP, EVP_PKEY_set_type, EVP_R_UNSUPPORTED_ALGORITHM);
+ ERR_add_error_dataf("algorithm %d (%s)", type, OBJ_nid2sn(type));
+ return 0;
+ }
+
+ if (pkey) {
+ pkey->ameth = ameth;
+ pkey->type = pkey->ameth->pkey_id;
+ }
+
+ return 1;
+}
+
+
+
+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;
+}
+
+static int print_unsupported(BIO *out, const EVP_PKEY *pkey, int indent,
+ const char *kstr) {
+ BIO_indent(out, indent, 128);
+ BIO_printf(out, "%s algorithm \"%s\" unsupported\n", kstr,
+ OBJ_nid2ln(pkey->type));
+ return 1;
+}
+
+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 print_unsupported(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 print_unsupported(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 print_unsupported(out, pkey, indent, "Parameters");
+}
+
+int EVP_PKEY_CTX_set_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD *md) {
+ return EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_TYPE_SIG, EVP_PKEY_CTRL_MD, 0,
+ (void *)md);
+}
+
+int EVP_PKEY_CTX_get_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD **out_md) {
+ return EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_TYPE_SIG, EVP_PKEY_CTRL_GET_MD,
+ 0, (void *)out_md);
+}
+
+void OpenSSL_add_all_algorithms(void) {}
+
+void EVP_cleanup(void) {}
diff --git a/src/crypto/evp/evp_ctx.c b/src/crypto/evp/evp_ctx.c
new file mode 100644
index 0000000..a383725
--- /dev/null
+++ b/src/crypto/evp/evp_ctx.c
@@ -0,0 +1,512 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/evp.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+
+#include "internal.h"
+
+
+extern const EVP_PKEY_METHOD rsa_pkey_meth;
+extern const EVP_PKEY_METHOD hmac_pkey_meth;
+extern const EVP_PKEY_METHOD ec_pkey_meth;
+
+static const EVP_PKEY_METHOD *const evp_methods[] = {
+ &rsa_pkey_meth,
+ &hmac_pkey_meth,
+ &ec_pkey_meth,
+};
+
+static const EVP_PKEY_METHOD *evp_pkey_meth_find(int type) {
+ unsigned i;
+
+ for (i = 0; i < sizeof(evp_methods)/sizeof(EVP_PKEY_METHOD*); i++) {
+ if (evp_methods[i]->pkey_id == type) {
+ return evp_methods[i];
+ }
+ }
+
+ return NULL;
+}
+
+static EVP_PKEY_CTX *evp_pkey_ctx_new(EVP_PKEY *pkey, ENGINE *e, int id) {
+ EVP_PKEY_CTX *ret;
+ const EVP_PKEY_METHOD *pmeth;
+
+ if (id == -1) {
+ if (!pkey || !pkey->ameth) {
+ return NULL;
+ }
+ id = pkey->ameth->pkey_id;
+ }
+
+ pmeth = evp_pkey_meth_find(id);
+
+ if (pmeth == NULL) {
+ OPENSSL_PUT_ERROR(EVP, evp_pkey_ctx_new, EVP_R_UNSUPPORTED_ALGORITHM);
+ const char *name = OBJ_nid2sn(id);
+ ERR_add_error_dataf("algorithm %d (%s)", id, name);
+ return NULL;
+ }
+
+ ret = OPENSSL_malloc(sizeof(EVP_PKEY_CTX));
+ if (!ret) {
+ OPENSSL_PUT_ERROR(EVP, evp_pkey_ctx_new, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ memset(ret, 0, sizeof(EVP_PKEY_CTX));
+
+ ret->engine = e;
+ ret->pmeth = pmeth;
+ ret->operation = EVP_PKEY_OP_UNDEFINED;
+
+ if (pkey) {
+ ret->pkey = EVP_PKEY_dup(pkey);
+ }
+
+ if (pmeth->init) {
+ if (pmeth->init(ret) <= 0) {
+ if (pkey) {
+ EVP_PKEY_free(ret->pkey);
+ }
+ OPENSSL_free(ret);
+ return NULL;
+ }
+ }
+
+ return ret;
+}
+
+EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e) {
+ return evp_pkey_ctx_new(pkey, e, -1);
+}
+
+EVP_PKEY_CTX *EVP_PKEY_CTX_new_id(int id, ENGINE *e) {
+ return evp_pkey_ctx_new(NULL, e, id);
+}
+
+void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx) {
+ if (ctx == NULL) {
+ return;
+ }
+ if (ctx->pmeth && ctx->pmeth->cleanup) {
+ ctx->pmeth->cleanup(ctx);
+ }
+ if (ctx->pkey) {
+ EVP_PKEY_free(ctx->pkey);
+ }
+ if (ctx->peerkey) {
+ EVP_PKEY_free(ctx->peerkey);
+ }
+ OPENSSL_free(ctx);
+}
+
+EVP_PKEY_CTX *EVP_PKEY_CTX_dup(EVP_PKEY_CTX *pctx) {
+ EVP_PKEY_CTX *rctx;
+
+ if (!pctx->pmeth || !pctx->pmeth->copy) {
+ return NULL;
+ }
+
+ rctx = OPENSSL_malloc(sizeof(EVP_PKEY_CTX));
+ if (!rctx) {
+ return NULL;
+ }
+
+ memset(rctx, 0, sizeof(EVP_PKEY_CTX));
+
+ rctx->pmeth = pctx->pmeth;
+ rctx->engine = pctx->engine;
+ rctx->operation = pctx->operation;
+
+ if (pctx->pkey) {
+ rctx->pkey = EVP_PKEY_dup(pctx->pkey);
+ if (rctx->pkey == NULL) {
+ goto err;
+ }
+ }
+
+ if (pctx->peerkey) {
+ rctx->peerkey = EVP_PKEY_dup(pctx->peerkey);
+ if (rctx->peerkey == NULL) {
+ goto err;
+ }
+ }
+
+ if (pctx->pmeth->copy(rctx, pctx) > 0) {
+ return rctx;
+ }
+
+err:
+ EVP_PKEY_CTX_free(rctx);
+ OPENSSL_PUT_ERROR(EVP, EVP_PKEY_CTX_dup, ERR_LIB_EVP);
+ return NULL;
+}
+
+EVP_PKEY *EVP_PKEY_CTX_get0_pkey(EVP_PKEY_CTX *ctx) { return ctx->pkey; }
+
+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; }
+
+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) {
+ OPENSSL_PUT_ERROR(EVP, EVP_PKEY_CTX_ctrl, EVP_R_COMMAND_NOT_SUPPORTED);
+ return -2;
+ }
+ if (keytype != -1 && ctx->pmeth->pkey_id != keytype) {
+ return -1;
+ }
+
+ if (ctx->operation == EVP_PKEY_OP_UNDEFINED) {
+ OPENSSL_PUT_ERROR(EVP, EVP_PKEY_CTX_ctrl, EVP_R_NO_OPERATION_SET);
+ return -1;
+ }
+
+ if (optype != -1 && !(ctx->operation & optype)) {
+ OPENSSL_PUT_ERROR(EVP, EVP_PKEY_CTX_ctrl, EVP_R_INVALID_OPERATION);
+ return -1;
+ }
+
+ ret = ctx->pmeth->ctrl(ctx, cmd, p1, p2);
+
+ if (ret == -2) {
+ OPENSSL_PUT_ERROR(EVP, EVP_PKEY_CTX_ctrl, EVP_R_COMMAND_NOT_SUPPORTED);
+ }
+
+ return ret;
+}
+
+int EVP_PKEY_sign_init(EVP_PKEY_CTX *ctx) {
+ if (!ctx || !ctx->pmeth || !ctx->pmeth->sign) {
+ OPENSSL_PUT_ERROR(EVP, EVP_PKEY_sign_init,
+ EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ return 0;
+ }
+
+ ctx->operation = EVP_PKEY_OP_SIGN;
+ if (!ctx->pmeth->sign_init) {
+ return 1;
+ }
+
+ if (!ctx->pmeth->sign_init(ctx)) {
+ ctx->operation = EVP_PKEY_OP_UNDEFINED;
+ return 0;
+ }
+
+ return 1;
+}
+
+int EVP_PKEY_sign(EVP_PKEY_CTX *ctx, uint8_t *sig, size_t *sig_len,
+ const uint8_t *data, size_t data_len) {
+ if (!ctx || !ctx->pmeth || !ctx->pmeth->sign) {
+ OPENSSL_PUT_ERROR(EVP, EVP_PKEY_sign,
+ EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ return 0;
+ }
+ if (ctx->operation != EVP_PKEY_OP_SIGN) {
+ OPENSSL_PUT_ERROR(EVP, EVP_PKEY_sign, EVP_R_OPERATON_NOT_INITIALIZED);
+ return 0;
+ }
+ return ctx->pmeth->sign(ctx, sig, sig_len, data, data_len);
+}
+
+int EVP_PKEY_verify_init(EVP_PKEY_CTX *ctx) {
+ if (!ctx || !ctx->pmeth || !ctx->pmeth->verify) {
+ OPENSSL_PUT_ERROR(EVP, EVP_PKEY_verify_init,
+ EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ return 0;
+ }
+ ctx->operation = EVP_PKEY_OP_VERIFY;
+ if (!ctx->pmeth->verify_init) {
+ return 1;
+ }
+ if (!ctx->pmeth->verify_init(ctx)) {
+ ctx->operation = EVP_PKEY_OP_UNDEFINED;
+ return 0;
+ }
+
+ return 1;
+}
+
+int EVP_PKEY_verify(EVP_PKEY_CTX *ctx, const uint8_t *sig, size_t sig_len,
+ const uint8_t *data, size_t data_len) {
+ if (!ctx || !ctx->pmeth || !ctx->pmeth->verify) {
+ OPENSSL_PUT_ERROR(EVP, EVP_PKEY_verify,
+ EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ return 0;
+ }
+ if (ctx->operation != EVP_PKEY_OP_VERIFY) {
+ OPENSSL_PUT_ERROR(EVP, EVP_PKEY_verify, EVP_R_OPERATON_NOT_INITIALIZED);
+ return 0;
+ }
+ return ctx->pmeth->verify(ctx, sig, sig_len, data, data_len);
+}
+
+int EVP_PKEY_encrypt_init(EVP_PKEY_CTX *ctx) {
+ if (!ctx || !ctx->pmeth || !ctx->pmeth->encrypt) {
+ OPENSSL_PUT_ERROR(EVP, EVP_PKEY_encrypt_init,
+ EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ return 0;
+ }
+ ctx->operation = EVP_PKEY_OP_ENCRYPT;
+ if (!ctx->pmeth->encrypt_init) {
+ return 1;
+ }
+ if (!ctx->pmeth->encrypt_init(ctx)) {
+ ctx->operation = EVP_PKEY_OP_UNDEFINED;
+ return 0;
+ }
+ return 1;
+}
+
+int EVP_PKEY_encrypt(EVP_PKEY_CTX *ctx, uint8_t *out, size_t *outlen,
+ const uint8_t *in, size_t inlen) {
+ if (!ctx || !ctx->pmeth || !ctx->pmeth->encrypt) {
+ OPENSSL_PUT_ERROR(EVP, EVP_PKEY_encrypt,
+ EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ return 0;
+ }
+ if (ctx->operation != EVP_PKEY_OP_ENCRYPT) {
+ OPENSSL_PUT_ERROR(EVP, EVP_PKEY_encrypt, EVP_R_OPERATON_NOT_INITIALIZED);
+ return 0;
+ }
+ return ctx->pmeth->encrypt(ctx, out, outlen, in, inlen);
+}
+
+int EVP_PKEY_decrypt_init(EVP_PKEY_CTX *ctx) {
+ if (!ctx || !ctx->pmeth || !ctx->pmeth->decrypt) {
+ OPENSSL_PUT_ERROR(EVP, EVP_PKEY_decrypt_init,
+ EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ return 0;
+ }
+ ctx->operation = EVP_PKEY_OP_DECRYPT;
+ if (!ctx->pmeth->decrypt_init) {
+ return 1;
+ }
+ if (!ctx->pmeth->decrypt_init(ctx)) {
+ ctx->operation = EVP_PKEY_OP_UNDEFINED;
+ return 0;
+ }
+ return 1;
+}
+
+int EVP_PKEY_decrypt(EVP_PKEY_CTX *ctx, uint8_t *out, size_t *outlen,
+ const uint8_t *in, size_t inlen) {
+ if (!ctx || !ctx->pmeth || !ctx->pmeth->decrypt) {
+ OPENSSL_PUT_ERROR(EVP, EVP_PKEY_decrypt,
+ EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ return 0;
+ }
+ if (ctx->operation != EVP_PKEY_OP_DECRYPT) {
+ OPENSSL_PUT_ERROR(EVP, EVP_PKEY_decrypt, EVP_R_OPERATON_NOT_INITIALIZED);
+ return 0;
+ }
+ return ctx->pmeth->decrypt(ctx, out, outlen, in, inlen);
+}
+
+int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx) {
+ if (!ctx || !ctx->pmeth || !ctx->pmeth->derive) {
+ OPENSSL_PUT_ERROR(EVP, EVP_PKEY_derive_init,
+ EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ return 0;
+ }
+ ctx->operation = EVP_PKEY_OP_DERIVE;
+ if (!ctx->pmeth->derive_init) {
+ return 1;
+ }
+ if (!ctx->pmeth->derive_init(ctx)) {
+ ctx->operation = EVP_PKEY_OP_UNDEFINED;
+ return 0;
+ }
+ return 1;
+}
+
+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) {
+ OPENSSL_PUT_ERROR(EVP, EVP_PKEY_derive_set_peer,
+ EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ return 0;
+ }
+ if (ctx->operation != EVP_PKEY_OP_DERIVE &&
+ ctx->operation != EVP_PKEY_OP_ENCRYPT &&
+ ctx->operation != EVP_PKEY_OP_DECRYPT) {
+ OPENSSL_PUT_ERROR(EVP, EVP_PKEY_derive_set_peer,
+ EVP_R_OPERATON_NOT_INITIALIZED);
+ return 0;
+ }
+
+ ret = ctx->pmeth->ctrl(ctx, EVP_PKEY_CTRL_PEER_KEY, 0, peer);
+
+ if (ret <= 0) {
+ return 0;
+ }
+
+ if (ret == 2) {
+ return 1;
+ }
+
+ if (!ctx->pkey) {
+ OPENSSL_PUT_ERROR(EVP, EVP_PKEY_derive_set_peer, EVP_R_NO_KEY_SET);
+ return 0;
+ }
+
+ if (ctx->pkey->type != peer->type) {
+ OPENSSL_PUT_ERROR(EVP, EVP_PKEY_derive_set_peer, EVP_R_DIFFERENT_KEY_TYPES);
+ return 0;
+ }
+
+ /* 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)) {
+ OPENSSL_PUT_ERROR(EVP, EVP_PKEY_derive_set_peer,
+ EVP_R_DIFFERENT_PARAMETERS);
+ return 0;
+ }
+
+ if (ctx->peerkey) {
+ 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 0;
+ }
+
+ EVP_PKEY_dup(peer);
+ return 1;
+}
+
+int EVP_PKEY_derive(EVP_PKEY_CTX *ctx, uint8_t *key, size_t *out_key_len) {
+ if (!ctx || !ctx->pmeth || !ctx->pmeth->derive) {
+ OPENSSL_PUT_ERROR(EVP, EVP_PKEY_derive,
+ EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ return 0;
+ }
+ if (ctx->operation != EVP_PKEY_OP_DERIVE) {
+ OPENSSL_PUT_ERROR(EVP, EVP_PKEY_derive, EVP_R_OPERATON_NOT_INITIALIZED);
+ return 0;
+ }
+ return ctx->pmeth->derive(ctx, key, out_key_len);
+}
+
+int EVP_PKEY_keygen_init(EVP_PKEY_CTX *ctx) {
+ if (!ctx || !ctx->pmeth || !ctx->pmeth->keygen) {
+ OPENSSL_PUT_ERROR(EVP, EVP_PKEY_keygen_init,
+ EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ return 0;
+ }
+ ctx->operation = EVP_PKEY_OP_KEYGEN;
+ if (!ctx->pmeth->keygen_init) {
+ return 1;
+ }
+ if (!ctx->pmeth->keygen_init(ctx)) {
+ ctx->operation = EVP_PKEY_OP_UNDEFINED;
+ return 0;
+ }
+ return 1;
+}
+
+int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey) {
+ if (!ctx || !ctx->pmeth || !ctx->pmeth->keygen) {
+ OPENSSL_PUT_ERROR(EVP, EVP_PKEY_keygen,
+ EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ return 0;
+ }
+ if (ctx->operation != EVP_PKEY_OP_KEYGEN) {
+ OPENSSL_PUT_ERROR(EVP, EVP_PKEY_keygen, EVP_R_OPERATON_NOT_INITIALIZED);
+ return 0;
+ }
+
+ if (!ppkey) {
+ return 0;
+ }
+
+ if (!*ppkey) {
+ *ppkey = EVP_PKEY_new();
+ if (!*ppkey) {
+ OPENSSL_PUT_ERROR(EVP, EVP_PKEY_keygen, ERR_LIB_EVP);
+ return 0;
+ }
+ }
+
+ if (!ctx->pmeth->keygen(ctx, *ppkey)) {
+ EVP_PKEY_free(*ppkey);
+ *ppkey = NULL;
+ return 0;
+ }
+ return 1;
+}
diff --git a/src/crypto/evp/evp_error.c b/src/crypto/evp/evp_error.c
new file mode 100644
index 0000000..b0d311e
--- /dev/null
+++ b/src/crypto/evp/evp_error.c
@@ -0,0 +1,131 @@
+/* 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 <openssl/err.h>
+
+#include <openssl/evp.h>
+
+const ERR_STRING_DATA EVP_error_string_data[] = {
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_DigestSignAlgorithm, 0), "EVP_DigestSignAlgorithm"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_DigestVerifyInitFromAlgorithm, 0), "EVP_DigestVerifyInitFromAlgorithm"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_CTX_ctrl, 0), "EVP_PKEY_CTX_ctrl"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_CTX_dup, 0), "EVP_PKEY_CTX_dup"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_copy_parameters, 0), "EVP_PKEY_copy_parameters"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_decrypt, 0), "EVP_PKEY_decrypt"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_decrypt_init, 0), "EVP_PKEY_decrypt_init"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_derive, 0), "EVP_PKEY_derive"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_derive_init, 0), "EVP_PKEY_derive_init"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_derive_set_peer, 0), "EVP_PKEY_derive_set_peer"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_encrypt, 0), "EVP_PKEY_encrypt"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_encrypt_init, 0), "EVP_PKEY_encrypt_init"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_get1_DH, 0), "EVP_PKEY_get1_DH"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_get1_DSA, 0), "EVP_PKEY_get1_DSA"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_get1_EC_KEY, 0), "EVP_PKEY_get1_EC_KEY"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_get1_RSA, 0), "EVP_PKEY_get1_RSA"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_keygen, 0), "EVP_PKEY_keygen"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_keygen_init, 0), "EVP_PKEY_keygen_init"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_new, 0), "EVP_PKEY_new"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_set_type, 0), "EVP_PKEY_set_type"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_sign, 0), "EVP_PKEY_sign"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_sign_init, 0), "EVP_PKEY_sign_init"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_verify, 0), "EVP_PKEY_verify"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_verify_init, 0), "EVP_PKEY_verify_init"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_check_padding_md, 0), "check_padding_md"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_d2i_AutoPrivateKey, 0), "d2i_AutoPrivateKey"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_d2i_PrivateKey, 0), "d2i_PrivateKey"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_do_EC_KEY_print, 0), "do_EC_KEY_print"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_do_rsa_print, 0), "do_rsa_print"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_do_sigver_init, 0), "do_sigver_init"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_eckey_param2type, 0), "eckey_param2type"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_eckey_param_decode, 0), "eckey_param_decode"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_eckey_priv_decode, 0), "eckey_priv_decode"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_eckey_priv_encode, 0), "eckey_priv_encode"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_eckey_pub_decode, 0), "eckey_pub_decode"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_eckey_pub_encode, 0), "eckey_pub_encode"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_eckey_type2param, 0), "eckey_type2param"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_evp_pkey_ctx_new, 0), "evp_pkey_ctx_new"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_hmac_signctx, 0), "hmac_signctx"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_i2d_PublicKey, 0), "i2d_PublicKey"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_old_ec_priv_decode, 0), "old_ec_priv_decode"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_old_rsa_priv_decode, 0), "old_rsa_priv_decode"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_pkey_ec_ctrl, 0), "pkey_ec_ctrl"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_pkey_ec_derive, 0), "pkey_ec_derive"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_pkey_ec_keygen, 0), "pkey_ec_keygen"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_pkey_ec_paramgen, 0), "pkey_ec_paramgen"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_pkey_ec_sign, 0), "pkey_ec_sign"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_pkey_rsa_ctrl, 0), "pkey_rsa_ctrl"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_pkey_rsa_decrypt, 0), "pkey_rsa_decrypt"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_pkey_rsa_encrypt, 0), "pkey_rsa_encrypt"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_pkey_rsa_sign, 0), "pkey_rsa_sign"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_rsa_algor_to_md, 0), "rsa_algor_to_md"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_rsa_digest_verify_init_from_algorithm, 0), "rsa_digest_verify_init_from_algorithm"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_rsa_item_verify, 0), "rsa_item_verify"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_rsa_mgf1_to_md, 0), "rsa_mgf1_to_md"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_rsa_priv_decode, 0), "rsa_priv_decode"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_rsa_priv_encode, 0), "rsa_priv_encode"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_rsa_pss_to_ctx, 0), "rsa_pss_to_ctx"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_rsa_pub_decode, 0), "rsa_pub_decode"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_BUFFER_TOO_SMALL), "BUFFER_TOO_SMALL"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_COMMAND_NOT_SUPPORTED), "COMMAND_NOT_SUPPORTED"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_CONTEXT_NOT_INITIALISED), "CONTEXT_NOT_INITIALISED"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_DECODE_ERROR), "DECODE_ERROR"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_DIFFERENT_KEY_TYPES), "DIFFERENT_KEY_TYPES"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_DIFFERENT_PARAMETERS), "DIFFERENT_PARAMETERS"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED), "DIGEST_AND_KEY_TYPE_NOT_SUPPORTED"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_DIGEST_DOES_NOT_MATCH), "DIGEST_DOES_NOT_MATCH"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_AN_DSA_KEY), "EXPECTING_AN_DSA_KEY"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_AN_EC_KEY_KEY), "EXPECTING_AN_EC_KEY_KEY"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_AN_RSA_KEY), "EXPECTING_AN_RSA_KEY"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_A_DH_KEY), "EXPECTING_A_DH_KEY"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_A_DSA_KEY), "EXPECTING_A_DSA_KEY"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPLICIT_EC_PARAMETERS_NOT_SUPPORTED), "EXPLICIT_EC_PARAMETERS_NOT_SUPPORTED"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE), "ILLEGAL_OR_UNSUPPORTED_PADDING_MODE"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_CURVE), "INVALID_CURVE"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_DIGEST_LENGTH), "INVALID_DIGEST_LENGTH"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_DIGEST_TYPE), "INVALID_DIGEST_TYPE"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_KEYBITS), "INVALID_KEYBITS"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_MGF1_MD), "INVALID_MGF1_MD"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_OPERATION), "INVALID_OPERATION"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_PADDING_MODE), "INVALID_PADDING_MODE"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_PSS_PARAMETERS), "INVALID_PSS_PARAMETERS"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_PSS_SALTLEN), "INVALID_PSS_SALTLEN"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_SALT_LENGTH), "INVALID_SALT_LENGTH"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_TRAILER), "INVALID_TRAILER"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_KDF_PARAMETER_ERROR), "KDF_PARAMETER_ERROR"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_KEYS_NOT_SET), "KEYS_NOT_SET"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_MISSING_PARAMETERS), "MISSING_PARAMETERS"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_DEFAULT_DIGEST), "NO_DEFAULT_DIGEST"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_KEY_SET), "NO_KEY_SET"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_MDC2_SUPPORT), "NO_MDC2_SUPPORT"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_NID_FOR_CURVE), "NO_NID_FOR_CURVE"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_OPERATION_SET), "NO_OPERATION_SET"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_PARAMETERS_SET), "NO_PARAMETERS_SET"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE), "OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_OPERATON_NOT_INITIALIZED), "OPERATON_NOT_INITIALIZED"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_PEER_KEY_ERROR), "PEER_KEY_ERROR"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_SHARED_INFO_ERROR), "SHARED_INFO_ERROR"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNKNOWN_DIGEST), "UNKNOWN_DIGEST"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNKNOWN_MASK_DIGEST), "UNKNOWN_MASK_DIGEST"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM), "UNKNOWN_MESSAGE_DIGEST_ALGORITHM"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNKNOWN_PUBLIC_KEY_TYPE), "UNKNOWN_PUBLIC_KEY_TYPE"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNKNOWN_SIGNATURE_ALGORITHM), "UNKNOWN_SIGNATURE_ALGORITHM"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNSUPPORTED_ALGORITHM), "UNSUPPORTED_ALGORITHM"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNSUPPORTED_MASK_ALGORITHM), "UNSUPPORTED_MASK_ALGORITHM"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNSUPPORTED_MASK_PARAMETER), "UNSUPPORTED_MASK_PARAMETER"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNSUPPORTED_PUBLIC_KEY_TYPE), "UNSUPPORTED_PUBLIC_KEY_TYPE"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNSUPPORTED_SIGNATURE_TYPE), "UNSUPPORTED_SIGNATURE_TYPE"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_WRONG_PUBLIC_KEY_TYPE), "WRONG_PUBLIC_KEY_TYPE"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_X931_UNSUPPORTED), "X931_UNSUPPORTED"},
+ {0, NULL},
+};
diff --git a/src/crypto/evp/evp_test.c b/src/crypto/evp/evp_test.c
new file mode 100644
index 0000000..3e74cd5
--- /dev/null
+++ b/src/crypto/evp/evp_test.c
@@ -0,0 +1,639 @@
+/* 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 <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <openssl/bio.h>
+#include <openssl/bytestring.h>
+#include <openssl/crypto.h>
+#include <openssl/digest.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/rsa.h>
+#include <openssl/x509.h>
+
+
+/* kExampleRSAKeyDER is an RSA private key in ASN.1, DER format. Of course, you
+ * should never use this key anywhere but in an example. */
+static const uint8_t kExampleRSAKeyDER[] = {
+ 0x30, 0x82, 0x02, 0x5c, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, 0x00, 0xf8,
+ 0xb8, 0x6c, 0x83, 0xb4, 0xbc, 0xd9, 0xa8, 0x57, 0xc0, 0xa5, 0xb4, 0x59,
+ 0x76, 0x8c, 0x54, 0x1d, 0x79, 0xeb, 0x22, 0x52, 0x04, 0x7e, 0xd3, 0x37,
+ 0xeb, 0x41, 0xfd, 0x83, 0xf9, 0xf0, 0xa6, 0x85, 0x15, 0x34, 0x75, 0x71,
+ 0x5a, 0x84, 0xa8, 0x3c, 0xd2, 0xef, 0x5a, 0x4e, 0xd3, 0xde, 0x97, 0x8a,
+ 0xdd, 0xff, 0xbb, 0xcf, 0x0a, 0xaa, 0x86, 0x92, 0xbe, 0xb8, 0x50, 0xe4,
+ 0xcd, 0x6f, 0x80, 0x33, 0x30, 0x76, 0x13, 0x8f, 0xca, 0x7b, 0xdc, 0xec,
+ 0x5a, 0xca, 0x63, 0xc7, 0x03, 0x25, 0xef, 0xa8, 0x8a, 0x83, 0x58, 0x76,
+ 0x20, 0xfa, 0x16, 0x77, 0xd7, 0x79, 0x92, 0x63, 0x01, 0x48, 0x1a, 0xd8,
+ 0x7b, 0x67, 0xf1, 0x52, 0x55, 0x49, 0x4e, 0xd6, 0x6e, 0x4a, 0x5c, 0xd7,
+ 0x7a, 0x37, 0x36, 0x0c, 0xde, 0xdd, 0x8f, 0x44, 0xe8, 0xc2, 0xa7, 0x2c,
+ 0x2b, 0xb5, 0xaf, 0x64, 0x4b, 0x61, 0x07, 0x02, 0x03, 0x01, 0x00, 0x01,
+ 0x02, 0x81, 0x80, 0x74, 0x88, 0x64, 0x3f, 0x69, 0x45, 0x3a, 0x6d, 0xc7,
+ 0x7f, 0xb9, 0xa3, 0xc0, 0x6e, 0xec, 0xdc, 0xd4, 0x5a, 0xb5, 0x32, 0x85,
+ 0x5f, 0x19, 0xd4, 0xf8, 0xd4, 0x3f, 0x3c, 0xfa, 0xc2, 0xf6, 0x5f, 0xee,
+ 0xe6, 0xba, 0x87, 0x74, 0x2e, 0xc7, 0x0c, 0xd4, 0x42, 0xb8, 0x66, 0x85,
+ 0x9c, 0x7b, 0x24, 0x61, 0xaa, 0x16, 0x11, 0xf6, 0xb5, 0xb6, 0xa4, 0x0a,
+ 0xc9, 0x55, 0x2e, 0x81, 0xa5, 0x47, 0x61, 0xcb, 0x25, 0x8f, 0xc2, 0x15,
+ 0x7b, 0x0e, 0x7c, 0x36, 0x9f, 0x3a, 0xda, 0x58, 0x86, 0x1c, 0x5b, 0x83,
+ 0x79, 0xe6, 0x2b, 0xcc, 0xe6, 0xfa, 0x2c, 0x61, 0xf2, 0x78, 0x80, 0x1b,
+ 0xe2, 0xf3, 0x9d, 0x39, 0x2b, 0x65, 0x57, 0x91, 0x3d, 0x71, 0x99, 0x73,
+ 0xa5, 0xc2, 0x79, 0x20, 0x8c, 0x07, 0x4f, 0xe5, 0xb4, 0x60, 0x1f, 0x99,
+ 0xa2, 0xb1, 0x4f, 0x0c, 0xef, 0xbc, 0x59, 0x53, 0x00, 0x7d, 0xb1, 0x02,
+ 0x41, 0x00, 0xfc, 0x7e, 0x23, 0x65, 0x70, 0xf8, 0xce, 0xd3, 0x40, 0x41,
+ 0x80, 0x6a, 0x1d, 0x01, 0xd6, 0x01, 0xff, 0xb6, 0x1b, 0x3d, 0x3d, 0x59,
+ 0x09, 0x33, 0x79, 0xc0, 0x4f, 0xde, 0x96, 0x27, 0x4b, 0x18, 0xc6, 0xd9,
+ 0x78, 0xf1, 0xf4, 0x35, 0x46, 0xe9, 0x7c, 0x42, 0x7a, 0x5d, 0x9f, 0xef,
+ 0x54, 0xb8, 0xf7, 0x9f, 0xc4, 0x33, 0x6c, 0xf3, 0x8c, 0x32, 0x46, 0x87,
+ 0x67, 0x30, 0x7b, 0xa7, 0xac, 0xe3, 0x02, 0x41, 0x00, 0xfc, 0x2c, 0xdf,
+ 0x0c, 0x0d, 0x88, 0xf5, 0xb1, 0x92, 0xa8, 0x93, 0x47, 0x63, 0x55, 0xf5,
+ 0xca, 0x58, 0x43, 0xba, 0x1c, 0xe5, 0x9e, 0xb6, 0x95, 0x05, 0xcd, 0xb5,
+ 0x82, 0xdf, 0xeb, 0x04, 0x53, 0x9d, 0xbd, 0xc2, 0x38, 0x16, 0xb3, 0x62,
+ 0xdd, 0xa1, 0x46, 0xdb, 0x6d, 0x97, 0x93, 0x9f, 0x8a, 0xc3, 0x9b, 0x64,
+ 0x7e, 0x42, 0xe3, 0x32, 0x57, 0x19, 0x1b, 0xd5, 0x6e, 0x85, 0xfa, 0xb8,
+ 0x8d, 0x02, 0x41, 0x00, 0xbc, 0x3d, 0xde, 0x6d, 0xd6, 0x97, 0xe8, 0xba,
+ 0x9e, 0x81, 0x37, 0x17, 0xe5, 0xa0, 0x64, 0xc9, 0x00, 0xb7, 0xe7, 0xfe,
+ 0xf4, 0x29, 0xd9, 0x2e, 0x43, 0x6b, 0x19, 0x20, 0xbd, 0x99, 0x75, 0xe7,
+ 0x76, 0xf8, 0xd3, 0xae, 0xaf, 0x7e, 0xb8, 0xeb, 0x81, 0xf4, 0x9d, 0xfe,
+ 0x07, 0x2b, 0x0b, 0x63, 0x0b, 0x5a, 0x55, 0x90, 0x71, 0x7d, 0xf1, 0xdb,
+ 0xd9, 0xb1, 0x41, 0x41, 0x68, 0x2f, 0x4e, 0x39, 0x02, 0x40, 0x5a, 0x34,
+ 0x66, 0xd8, 0xf5, 0xe2, 0x7f, 0x18, 0xb5, 0x00, 0x6e, 0x26, 0x84, 0x27,
+ 0x14, 0x93, 0xfb, 0xfc, 0xc6, 0x0f, 0x5e, 0x27, 0xe6, 0xe1, 0xe9, 0xc0,
+ 0x8a, 0xe4, 0x34, 0xda, 0xe9, 0xa2, 0x4b, 0x73, 0xbc, 0x8c, 0xb9, 0xba,
+ 0x13, 0x6c, 0x7a, 0x2b, 0x51, 0x84, 0xa3, 0x4a, 0xe0, 0x30, 0x10, 0x06,
+ 0x7e, 0xed, 0x17, 0x5a, 0x14, 0x00, 0xc9, 0xef, 0x85, 0xea, 0x52, 0x2c,
+ 0xbc, 0x65, 0x02, 0x40, 0x51, 0xe3, 0xf2, 0x83, 0x19, 0x9b, 0xc4, 0x1e,
+ 0x2f, 0x50, 0x3d, 0xdf, 0x5a, 0xa2, 0x18, 0xca, 0x5f, 0x2e, 0x49, 0xaf,
+ 0x6f, 0xcc, 0xfa, 0x65, 0x77, 0x94, 0xb5, 0xa1, 0x0a, 0xa9, 0xd1, 0x8a,
+ 0x39, 0x37, 0xf4, 0x0b, 0xa0, 0xd7, 0x82, 0x27, 0x5e, 0xae, 0x17, 0x17,
+ 0xa1, 0x1e, 0x54, 0x34, 0xbf, 0x6e, 0xc4, 0x8e, 0x99, 0x5d, 0x08, 0xf1,
+ 0x2d, 0x86, 0x9d, 0xa5, 0x20, 0x1b, 0xe5, 0xdf,
+};
+
+static const uint8_t kMsg[] = {1, 2, 3, 4};
+
+static const uint8_t kSignature[] = {
+ 0xa5, 0xf0, 0x8a, 0x47, 0x5d, 0x3c, 0xb3, 0xcc, 0xa9, 0x79, 0xaf, 0x4d,
+ 0x8c, 0xae, 0x4c, 0x14, 0xef, 0xc2, 0x0b, 0x34, 0x36, 0xde, 0xf4, 0x3e,
+ 0x3d, 0xbb, 0x4a, 0x60, 0x5c, 0xc8, 0x91, 0x28, 0xda, 0xfb, 0x7e, 0x04,
+ 0x96, 0x7e, 0x63, 0x13, 0x90, 0xce, 0xb9, 0xb4, 0x62, 0x7a, 0xfd, 0x09,
+ 0x3d, 0xc7, 0x67, 0x78, 0x54, 0x04, 0xeb, 0x52, 0x62, 0x6e, 0x24, 0x67,
+ 0xb4, 0x40, 0xfc, 0x57, 0x62, 0xc6, 0xf1, 0x67, 0xc1, 0x97, 0x8f, 0x6a,
+ 0xa8, 0xae, 0x44, 0x46, 0x5e, 0xab, 0x67, 0x17, 0x53, 0x19, 0x3a, 0xda,
+ 0x5a, 0xc8, 0x16, 0x3e, 0x86, 0xd5, 0xc5, 0x71, 0x2f, 0xfc, 0x23, 0x48,
+ 0xd9, 0x0b, 0x13, 0xdd, 0x7b, 0x5a, 0x25, 0x79, 0xef, 0xa5, 0x7b, 0x04,
+ 0xed, 0x44, 0xf6, 0x18, 0x55, 0xe4, 0x0a, 0xe9, 0x57, 0x79, 0x5d, 0xd7,
+ 0x55, 0xa7, 0xab, 0x45, 0x02, 0x97, 0x60, 0x42,
+};
+
+/* kExamplePSSCert is an example self-signed certificate, signed with
+ * kExampleRSAKeyDER using RSA-PSS with default hash functions. */
+static const uint8_t kExamplePSSCert[] = {
+ 0x30, 0x82, 0x02, 0x62, 0x30, 0x82, 0x01, 0xc6, 0xa0, 0x03, 0x02, 0x01,
+ 0x02, 0x02, 0x09, 0x00, 0x8d, 0xea, 0x53, 0x24, 0xfa, 0x48, 0x87, 0xf3,
+ 0x30, 0x12, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+ 0x0a, 0x30, 0x05, 0xa2, 0x03, 0x02, 0x01, 0x6a, 0x30, 0x45, 0x31, 0x0b,
+ 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31,
+ 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x53, 0x6f,
+ 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f,
+ 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72,
+ 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20,
+ 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d, 0x31,
+ 0x34, 0x31, 0x30, 0x30, 0x39, 0x31, 0x39, 0x30, 0x39, 0x35, 0x35, 0x5a,
+ 0x17, 0x0d, 0x31, 0x35, 0x31, 0x30, 0x30, 0x39, 0x31, 0x39, 0x30, 0x39,
+ 0x35, 0x35, 0x5a, 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+ 0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
+ 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74,
+ 0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a,
+ 0x0c, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57,
+ 0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c,
+ 0x74, 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48,
+ 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00,
+ 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xf8, 0xb8, 0x6c, 0x83, 0xb4,
+ 0xbc, 0xd9, 0xa8, 0x57, 0xc0, 0xa5, 0xb4, 0x59, 0x76, 0x8c, 0x54, 0x1d,
+ 0x79, 0xeb, 0x22, 0x52, 0x04, 0x7e, 0xd3, 0x37, 0xeb, 0x41, 0xfd, 0x83,
+ 0xf9, 0xf0, 0xa6, 0x85, 0x15, 0x34, 0x75, 0x71, 0x5a, 0x84, 0xa8, 0x3c,
+ 0xd2, 0xef, 0x5a, 0x4e, 0xd3, 0xde, 0x97, 0x8a, 0xdd, 0xff, 0xbb, 0xcf,
+ 0x0a, 0xaa, 0x86, 0x92, 0xbe, 0xb8, 0x50, 0xe4, 0xcd, 0x6f, 0x80, 0x33,
+ 0x30, 0x76, 0x13, 0x8f, 0xca, 0x7b, 0xdc, 0xec, 0x5a, 0xca, 0x63, 0xc7,
+ 0x03, 0x25, 0xef, 0xa8, 0x8a, 0x83, 0x58, 0x76, 0x20, 0xfa, 0x16, 0x77,
+ 0xd7, 0x79, 0x92, 0x63, 0x01, 0x48, 0x1a, 0xd8, 0x7b, 0x67, 0xf1, 0x52,
+ 0x55, 0x49, 0x4e, 0xd6, 0x6e, 0x4a, 0x5c, 0xd7, 0x7a, 0x37, 0x36, 0x0c,
+ 0xde, 0xdd, 0x8f, 0x44, 0xe8, 0xc2, 0xa7, 0x2c, 0x2b, 0xb5, 0xaf, 0x64,
+ 0x4b, 0x61, 0x07, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x50, 0x30, 0x4e,
+ 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xd0,
+ 0x41, 0xfb, 0x89, 0x41, 0x1e, 0xa7, 0xad, 0x5a, 0xec, 0x34, 0x5d, 0x49,
+ 0x11, 0xf9, 0x55, 0x81, 0x78, 0x1f, 0x13, 0x30, 0x1f, 0x06, 0x03, 0x55,
+ 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xd0, 0x41, 0xfb, 0x89,
+ 0x41, 0x1e, 0xa7, 0xad, 0x5a, 0xec, 0x34, 0x5d, 0x49, 0x11, 0xf9, 0x55,
+ 0x81, 0x78, 0x1f, 0x13, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04,
+ 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x12, 0x06, 0x09, 0x2a, 0x86,
+ 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0a, 0x30, 0x05, 0xa2, 0x03, 0x02,
+ 0x01, 0x6a, 0x03, 0x81, 0x81, 0x00, 0x49, 0x4c, 0xb6, 0x45, 0x97, 0x20,
+ 0x35, 0xb3, 0x50, 0x64, 0x0d, 0x3f, 0xec, 0x5f, 0x95, 0xd5, 0x84, 0xcb,
+ 0x11, 0x7c, 0x03, 0xd7, 0xa6, 0xe6, 0xfa, 0x24, 0x95, 0x9f, 0x31, 0xb0,
+ 0xb5, 0xec, 0x66, 0x41, 0x51, 0x18, 0x21, 0x91, 0xbb, 0xe0, 0xaf, 0xf0,
+ 0xc5, 0xb7, 0x59, 0x41, 0xd4, 0xdb, 0xa4, 0xd2, 0x64, 0xa7, 0x54, 0x0f,
+ 0x8c, 0xf7, 0xe1, 0xd3, 0x3b, 0x1a, 0xb7, 0x0e, 0x9d, 0x9a, 0xde, 0x50,
+ 0xa1, 0x9f, 0x0a, 0xf0, 0xda, 0x34, 0x0e, 0x34, 0x7d, 0x76, 0x07, 0xfe,
+ 0x5a, 0xfb, 0xf9, 0x58, 0x9b, 0xc9, 0x50, 0x84, 0x01, 0xa0, 0x05, 0x4d,
+ 0x67, 0x42, 0x0b, 0xf8, 0xe4, 0x05, 0xcf, 0xaf, 0x8b, 0x71, 0x31, 0xf1,
+ 0x0f, 0x6e, 0xc9, 0x24, 0x27, 0x9b, 0xac, 0x04, 0xd7, 0x64, 0x0d, 0x30,
+ 0x4e, 0x11, 0x93, 0x40, 0x39, 0xbb, 0x72, 0xb2, 0xfe, 0x6b, 0xe4, 0xae,
+ 0x8c, 0x16,
+};
+
+/* kExampleRSAKeyPKCS8 is kExampleRSAKeyDER encoded in a PKCS #8
+ * PrivateKeyInfo. */
+static const uint8_t kExampleRSAKeyPKCS8[] = {
+ 0x30, 0x82, 0x02, 0x76, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82,
+ 0x02, 0x60, 0x30, 0x82, 0x02, 0x5c, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81,
+ 0x00, 0xf8, 0xb8, 0x6c, 0x83, 0xb4, 0xbc, 0xd9, 0xa8, 0x57, 0xc0, 0xa5,
+ 0xb4, 0x59, 0x76, 0x8c, 0x54, 0x1d, 0x79, 0xeb, 0x22, 0x52, 0x04, 0x7e,
+ 0xd3, 0x37, 0xeb, 0x41, 0xfd, 0x83, 0xf9, 0xf0, 0xa6, 0x85, 0x15, 0x34,
+ 0x75, 0x71, 0x5a, 0x84, 0xa8, 0x3c, 0xd2, 0xef, 0x5a, 0x4e, 0xd3, 0xde,
+ 0x97, 0x8a, 0xdd, 0xff, 0xbb, 0xcf, 0x0a, 0xaa, 0x86, 0x92, 0xbe, 0xb8,
+ 0x50, 0xe4, 0xcd, 0x6f, 0x80, 0x33, 0x30, 0x76, 0x13, 0x8f, 0xca, 0x7b,
+ 0xdc, 0xec, 0x5a, 0xca, 0x63, 0xc7, 0x03, 0x25, 0xef, 0xa8, 0x8a, 0x83,
+ 0x58, 0x76, 0x20, 0xfa, 0x16, 0x77, 0xd7, 0x79, 0x92, 0x63, 0x01, 0x48,
+ 0x1a, 0xd8, 0x7b, 0x67, 0xf1, 0x52, 0x55, 0x49, 0x4e, 0xd6, 0x6e, 0x4a,
+ 0x5c, 0xd7, 0x7a, 0x37, 0x36, 0x0c, 0xde, 0xdd, 0x8f, 0x44, 0xe8, 0xc2,
+ 0xa7, 0x2c, 0x2b, 0xb5, 0xaf, 0x64, 0x4b, 0x61, 0x07, 0x02, 0x03, 0x01,
+ 0x00, 0x01, 0x02, 0x81, 0x80, 0x74, 0x88, 0x64, 0x3f, 0x69, 0x45, 0x3a,
+ 0x6d, 0xc7, 0x7f, 0xb9, 0xa3, 0xc0, 0x6e, 0xec, 0xdc, 0xd4, 0x5a, 0xb5,
+ 0x32, 0x85, 0x5f, 0x19, 0xd4, 0xf8, 0xd4, 0x3f, 0x3c, 0xfa, 0xc2, 0xf6,
+ 0x5f, 0xee, 0xe6, 0xba, 0x87, 0x74, 0x2e, 0xc7, 0x0c, 0xd4, 0x42, 0xb8,
+ 0x66, 0x85, 0x9c, 0x7b, 0x24, 0x61, 0xaa, 0x16, 0x11, 0xf6, 0xb5, 0xb6,
+ 0xa4, 0x0a, 0xc9, 0x55, 0x2e, 0x81, 0xa5, 0x47, 0x61, 0xcb, 0x25, 0x8f,
+ 0xc2, 0x15, 0x7b, 0x0e, 0x7c, 0x36, 0x9f, 0x3a, 0xda, 0x58, 0x86, 0x1c,
+ 0x5b, 0x83, 0x79, 0xe6, 0x2b, 0xcc, 0xe6, 0xfa, 0x2c, 0x61, 0xf2, 0x78,
+ 0x80, 0x1b, 0xe2, 0xf3, 0x9d, 0x39, 0x2b, 0x65, 0x57, 0x91, 0x3d, 0x71,
+ 0x99, 0x73, 0xa5, 0xc2, 0x79, 0x20, 0x8c, 0x07, 0x4f, 0xe5, 0xb4, 0x60,
+ 0x1f, 0x99, 0xa2, 0xb1, 0x4f, 0x0c, 0xef, 0xbc, 0x59, 0x53, 0x00, 0x7d,
+ 0xb1, 0x02, 0x41, 0x00, 0xfc, 0x7e, 0x23, 0x65, 0x70, 0xf8, 0xce, 0xd3,
+ 0x40, 0x41, 0x80, 0x6a, 0x1d, 0x01, 0xd6, 0x01, 0xff, 0xb6, 0x1b, 0x3d,
+ 0x3d, 0x59, 0x09, 0x33, 0x79, 0xc0, 0x4f, 0xde, 0x96, 0x27, 0x4b, 0x18,
+ 0xc6, 0xd9, 0x78, 0xf1, 0xf4, 0x35, 0x46, 0xe9, 0x7c, 0x42, 0x7a, 0x5d,
+ 0x9f, 0xef, 0x54, 0xb8, 0xf7, 0x9f, 0xc4, 0x33, 0x6c, 0xf3, 0x8c, 0x32,
+ 0x46, 0x87, 0x67, 0x30, 0x7b, 0xa7, 0xac, 0xe3, 0x02, 0x41, 0x00, 0xfc,
+ 0x2c, 0xdf, 0x0c, 0x0d, 0x88, 0xf5, 0xb1, 0x92, 0xa8, 0x93, 0x47, 0x63,
+ 0x55, 0xf5, 0xca, 0x58, 0x43, 0xba, 0x1c, 0xe5, 0x9e, 0xb6, 0x95, 0x05,
+ 0xcd, 0xb5, 0x82, 0xdf, 0xeb, 0x04, 0x53, 0x9d, 0xbd, 0xc2, 0x38, 0x16,
+ 0xb3, 0x62, 0xdd, 0xa1, 0x46, 0xdb, 0x6d, 0x97, 0x93, 0x9f, 0x8a, 0xc3,
+ 0x9b, 0x64, 0x7e, 0x42, 0xe3, 0x32, 0x57, 0x19, 0x1b, 0xd5, 0x6e, 0x85,
+ 0xfa, 0xb8, 0x8d, 0x02, 0x41, 0x00, 0xbc, 0x3d, 0xde, 0x6d, 0xd6, 0x97,
+ 0xe8, 0xba, 0x9e, 0x81, 0x37, 0x17, 0xe5, 0xa0, 0x64, 0xc9, 0x00, 0xb7,
+ 0xe7, 0xfe, 0xf4, 0x29, 0xd9, 0x2e, 0x43, 0x6b, 0x19, 0x20, 0xbd, 0x99,
+ 0x75, 0xe7, 0x76, 0xf8, 0xd3, 0xae, 0xaf, 0x7e, 0xb8, 0xeb, 0x81, 0xf4,
+ 0x9d, 0xfe, 0x07, 0x2b, 0x0b, 0x63, 0x0b, 0x5a, 0x55, 0x90, 0x71, 0x7d,
+ 0xf1, 0xdb, 0xd9, 0xb1, 0x41, 0x41, 0x68, 0x2f, 0x4e, 0x39, 0x02, 0x40,
+ 0x5a, 0x34, 0x66, 0xd8, 0xf5, 0xe2, 0x7f, 0x18, 0xb5, 0x00, 0x6e, 0x26,
+ 0x84, 0x27, 0x14, 0x93, 0xfb, 0xfc, 0xc6, 0x0f, 0x5e, 0x27, 0xe6, 0xe1,
+ 0xe9, 0xc0, 0x8a, 0xe4, 0x34, 0xda, 0xe9, 0xa2, 0x4b, 0x73, 0xbc, 0x8c,
+ 0xb9, 0xba, 0x13, 0x6c, 0x7a, 0x2b, 0x51, 0x84, 0xa3, 0x4a, 0xe0, 0x30,
+ 0x10, 0x06, 0x7e, 0xed, 0x17, 0x5a, 0x14, 0x00, 0xc9, 0xef, 0x85, 0xea,
+ 0x52, 0x2c, 0xbc, 0x65, 0x02, 0x40, 0x51, 0xe3, 0xf2, 0x83, 0x19, 0x9b,
+ 0xc4, 0x1e, 0x2f, 0x50, 0x3d, 0xdf, 0x5a, 0xa2, 0x18, 0xca, 0x5f, 0x2e,
+ 0x49, 0xaf, 0x6f, 0xcc, 0xfa, 0x65, 0x77, 0x94, 0xb5, 0xa1, 0x0a, 0xa9,
+ 0xd1, 0x8a, 0x39, 0x37, 0xf4, 0x0b, 0xa0, 0xd7, 0x82, 0x27, 0x5e, 0xae,
+ 0x17, 0x17, 0xa1, 0x1e, 0x54, 0x34, 0xbf, 0x6e, 0xc4, 0x8e, 0x99, 0x5d,
+ 0x08, 0xf1, 0x2d, 0x86, 0x9d, 0xa5, 0x20, 0x1b, 0xe5, 0xdf,
+};
+
+/* kExampleECKeyDER is a sample EC private key encoded as an ECPrivateKey
+ * structure. */
+static const uint8_t kExampleECKeyDER[] = {
+ 0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0x07, 0x0f, 0x08, 0x72, 0x7a,
+ 0xd4, 0xa0, 0x4a, 0x9c, 0xdd, 0x59, 0xc9, 0x4d, 0x89, 0x68, 0x77, 0x08,
+ 0xb5, 0x6f, 0xc9, 0x5d, 0x30, 0x77, 0x0e, 0xe8, 0xd1, 0xc9, 0xce, 0x0a,
+ 0x8b, 0xb4, 0x6a, 0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d,
+ 0x03, 0x01, 0x07, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, 0xe6, 0x2b, 0x69,
+ 0xe2, 0xbf, 0x65, 0x9f, 0x97, 0xbe, 0x2f, 0x1e, 0x0d, 0x94, 0x8a, 0x4c,
+ 0xd5, 0x97, 0x6b, 0xb7, 0xa9, 0x1e, 0x0d, 0x46, 0xfb, 0xdd, 0xa9, 0xa9,
+ 0x1e, 0x9d, 0xdc, 0xba, 0x5a, 0x01, 0xe7, 0xd6, 0x97, 0xa8, 0x0a, 0x18,
+ 0xf9, 0xc3, 0xc4, 0xa3, 0x1e, 0x56, 0xe2, 0x7c, 0x83, 0x48, 0xdb, 0x16,
+ 0x1a, 0x1c, 0xf5, 0x1d, 0x7e, 0xf1, 0x94, 0x2d, 0x4b, 0xcf, 0x72, 0x22,
+ 0xc1,
+};
+
+/* kExampleBadECKeyDER is a sample EC private key encoded as an ECPrivateKey
+ * structure. The private key is equal to the order and will fail to import */
+static const uint8_t kExampleBadECKeyDER[] = {
+ 0x30, 0x66, 0x02, 0x01, 0x00, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48,
+ 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03,
+ 0x01, 0x07, 0x04, 0x4C, 0x30, 0x4A, 0x02, 0x01, 0x01, 0x04, 0x20, 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, 0xA1, 0x23, 0x03, 0x21, 0x00,
+ 0x00, 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
+};
+
+static EVP_PKEY *load_example_rsa_key(void) {
+ EVP_PKEY *ret = NULL;
+ const uint8_t *derp = kExampleRSAKeyDER;
+ EVP_PKEY *pkey = NULL;
+ RSA *rsa = NULL;
+
+ if (!d2i_RSAPrivateKey(&rsa, &derp, sizeof(kExampleRSAKeyDER))) {
+ return NULL;
+ }
+
+ pkey = EVP_PKEY_new();
+ if (pkey == NULL || !EVP_PKEY_set1_RSA(pkey, rsa)) {
+ goto out;
+ }
+
+ ret = pkey;
+ pkey = NULL;
+
+out:
+ if (pkey) {
+ EVP_PKEY_free(pkey);
+ }
+ if (rsa) {
+ RSA_free(rsa);
+ }
+
+ return ret;
+}
+
+static int test_EVP_DigestSignInit(void) {
+ int ret = 0;
+ EVP_PKEY *pkey = NULL;
+ uint8_t *sig = NULL;
+ size_t sig_len = 0;
+ EVP_MD_CTX md_ctx, md_ctx_verify;
+
+ EVP_MD_CTX_init(&md_ctx);
+ EVP_MD_CTX_init(&md_ctx_verify);
+
+ pkey = load_example_rsa_key();
+ if (pkey == NULL ||
+ !EVP_DigestSignInit(&md_ctx, NULL, EVP_sha256(), NULL, pkey) ||
+ !EVP_DigestSignUpdate(&md_ctx, kMsg, sizeof(kMsg))) {
+ goto out;
+ }
+ /* Determine the size of the signature. */
+ if (!EVP_DigestSignFinal(&md_ctx, NULL, &sig_len)) {
+ goto out;
+ }
+ /* Sanity check for testing. */
+ if (sig_len != EVP_PKEY_size(pkey)) {
+ fprintf(stderr, "sig_len mismatch\n");
+ goto out;
+ }
+
+ sig = malloc(sig_len);
+ if (sig == NULL || !EVP_DigestSignFinal(&md_ctx, sig, &sig_len)) {
+ goto out;
+ }
+
+ /* Ensure that the signature round-trips. */
+ if (!EVP_DigestVerifyInit(&md_ctx_verify, NULL, EVP_sha256(), NULL, pkey) ||
+ !EVP_DigestVerifyUpdate(&md_ctx_verify, kMsg, sizeof(kMsg)) ||
+ !EVP_DigestVerifyFinal(&md_ctx_verify, sig, sig_len)) {
+ goto out;
+ }
+
+ ret = 1;
+
+out:
+ if (!ret) {
+ BIO_print_errors_fp(stderr);
+ }
+
+ EVP_MD_CTX_cleanup(&md_ctx);
+ EVP_MD_CTX_cleanup(&md_ctx_verify);
+ if (pkey) {
+ EVP_PKEY_free(pkey);
+ }
+ if (sig) {
+ free(sig);
+ }
+
+ return ret;
+}
+
+static int test_EVP_DigestVerifyInit(void) {
+ int ret = 0;
+ EVP_PKEY *pkey = NULL;
+ EVP_MD_CTX md_ctx;
+
+ EVP_MD_CTX_init(&md_ctx);
+
+ pkey = load_example_rsa_key();
+ if (pkey == NULL ||
+ !EVP_DigestVerifyInit(&md_ctx, NULL, EVP_sha256(), NULL, pkey) ||
+ !EVP_DigestVerifyUpdate(&md_ctx, kMsg, sizeof(kMsg)) ||
+ !EVP_DigestVerifyFinal(&md_ctx, kSignature, sizeof(kSignature))) {
+ goto out;
+ }
+ ret = 1;
+
+out:
+ if (!ret) {
+ BIO_print_errors_fp(stderr);
+ }
+
+ EVP_MD_CTX_cleanup(&md_ctx);
+ if (pkey) {
+ EVP_PKEY_free(pkey);
+ }
+
+ return ret;
+}
+
+/* test_algorithm_roundtrip signs a message using an already-initialized
+ * |md_ctx|, sampling the AlgorithmIdentifier. It then uses |pkey| and the
+ * AlgorithmIdentifier to verify the signature. */
+static int test_algorithm_roundtrip(EVP_MD_CTX *md_ctx, EVP_PKEY *pkey) {
+ int ret = 0;
+ uint8_t *sig = NULL;
+ size_t sig_len = 0;
+ EVP_MD_CTX md_ctx_verify;
+ X509_ALGOR *algor = NULL;
+
+ EVP_MD_CTX_init(&md_ctx_verify);
+
+ if (!EVP_DigestSignUpdate(md_ctx, kMsg, sizeof(kMsg))) {
+ goto out;
+ }
+
+ /* Save the algorithm. */
+ algor = X509_ALGOR_new();
+ if (algor == NULL || !EVP_DigestSignAlgorithm(md_ctx, algor)) {
+ goto out;
+ }
+
+ /* Determine the size of the signature. */
+ if (!EVP_DigestSignFinal(md_ctx, NULL, &sig_len)) {
+ goto out;
+ }
+ /* Sanity check for testing. */
+ if (sig_len != EVP_PKEY_size(pkey)) {
+ fprintf(stderr, "sig_len mismatch\n");
+ goto out;
+ }
+
+ sig = malloc(sig_len);
+ if (sig == NULL || !EVP_DigestSignFinal(md_ctx, sig, &sig_len)) {
+ goto out;
+ }
+
+ /* Ensure that the signature round-trips. */
+ if (!EVP_DigestVerifyInitFromAlgorithm(&md_ctx_verify, algor, pkey) ||
+ !EVP_DigestVerifyUpdate(&md_ctx_verify, kMsg, sizeof(kMsg)) ||
+ !EVP_DigestVerifyFinal(&md_ctx_verify, sig, sig_len)) {
+ goto out;
+ }
+
+ ret = 1;
+
+out:
+ EVP_MD_CTX_cleanup(&md_ctx_verify);
+ if (sig) {
+ free(sig);
+ }
+ if (algor) {
+ X509_ALGOR_free(algor);
+ }
+
+ return ret;
+}
+
+static int test_EVP_DigestSignAlgorithm(void) {
+ int ret = 0;
+ EVP_PKEY *pkey = NULL;
+ EVP_MD_CTX md_ctx;
+ EVP_PKEY_CTX *pkey_ctx;
+
+ EVP_MD_CTX_init(&md_ctx);
+
+ pkey = load_example_rsa_key();
+ if (pkey == NULL) {
+ goto out;
+ }
+
+ /* Test a simple AlgorithmIdentifier. */
+ if (!EVP_DigestSignInit(&md_ctx, &pkey_ctx, EVP_sha256(), NULL, pkey) ||
+ !test_algorithm_roundtrip(&md_ctx, pkey)) {
+ fprintf(stderr, "RSA with SHA-256 failed\n");
+ goto out;
+ }
+
+ EVP_MD_CTX_cleanup(&md_ctx);
+ EVP_MD_CTX_init(&md_ctx);
+
+ /* Test RSA-PSS with custom parameters. */
+ if (!EVP_DigestSignInit(&md_ctx, &pkey_ctx, EVP_sha256(), NULL, pkey) ||
+ EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING) != 1 ||
+ EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, EVP_sha512()) != 1 ||
+ !test_algorithm_roundtrip(&md_ctx, pkey)) {
+ fprintf(stderr, "RSA-PSS failed\n");
+ goto out;
+ }
+
+ ret = 1;
+
+out:
+ if (!ret) {
+ BIO_print_errors_fp(stderr);
+ }
+
+ EVP_MD_CTX_cleanup(&md_ctx);
+ if (pkey) {
+ EVP_PKEY_free(pkey);
+ }
+
+ return ret;
+}
+
+static int test_EVP_DigestVerifyInitFromAlgorithm(void) {
+ int ret = 0;
+ CBS cert, cert_body, tbs_cert, algorithm, signature;
+ uint8_t padding;
+ X509_ALGOR *algor = NULL;
+ const uint8_t *derp;
+ EVP_PKEY *pkey = NULL;
+ EVP_MD_CTX md_ctx;
+
+ EVP_MD_CTX_init(&md_ctx);
+
+ CBS_init(&cert, kExamplePSSCert, sizeof(kExamplePSSCert));
+ if (!CBS_get_asn1(&cert, &cert_body, CBS_ASN1_SEQUENCE) ||
+ CBS_len(&cert) != 0 ||
+ !CBS_get_any_asn1_element(&cert_body, &tbs_cert, NULL, NULL) ||
+ !CBS_get_asn1_element(&cert_body, &algorithm, CBS_ASN1_SEQUENCE) ||
+ !CBS_get_asn1(&cert_body, &signature, CBS_ASN1_BITSTRING) ||
+ CBS_len(&cert_body) != 0) {
+ fprintf(stderr, "Failed to parse certificate\n");
+ goto out;
+ }
+
+ /* Signatures are BIT STRINGs, but they have are multiple of 8 bytes, so the
+ leading phase byte is just a zero. */
+ if (!CBS_get_u8(&signature, &padding) || padding != 0) {
+ fprintf(stderr, "Invalid signature padding\n");
+ goto out;
+ }
+
+ derp = CBS_data(&algorithm);
+ if (!d2i_X509_ALGOR(&algor, &derp, CBS_len(&algorithm)) ||
+ derp != CBS_data(&algorithm) + CBS_len(&algorithm)) {
+ fprintf(stderr, "Failed to parse algorithm\n");
+ }
+
+ pkey = load_example_rsa_key();
+ if (pkey == NULL ||
+ !EVP_DigestVerifyInitFromAlgorithm(&md_ctx, algor, pkey) ||
+ !EVP_DigestVerifyUpdate(&md_ctx, CBS_data(&tbs_cert),
+ CBS_len(&tbs_cert)) ||
+ !EVP_DigestVerifyFinal(&md_ctx, CBS_data(&signature),
+ CBS_len(&signature))) {
+ goto out;
+ }
+ ret = 1;
+
+out:
+ if (!ret) {
+ BIO_print_errors_fp(stderr);
+ }
+
+ EVP_MD_CTX_cleanup(&md_ctx);
+ if (pkey) {
+ EVP_PKEY_free(pkey);
+ }
+
+ return ret;
+}
+
+static int test_d2i_AutoPrivateKey(const uint8_t *input, size_t input_len,
+ int expected_id) {
+ int ret = 0;
+ const uint8_t *p;
+ EVP_PKEY *pkey = NULL;
+
+ p = input;
+ pkey = d2i_AutoPrivateKey(NULL, &p, input_len);
+ if (pkey == NULL || p != input + input_len) {
+ fprintf(stderr, "d2i_AutoPrivateKey failed\n");
+ goto done;
+ }
+
+ if (EVP_PKEY_id(pkey) != expected_id) {
+ fprintf(stderr, "Did not decode expected type\n");
+ goto done;
+ }
+
+ ret = 1;
+
+done:
+ if (!ret) {
+ BIO_print_errors_fp(stderr);
+ }
+
+ if (pkey != NULL) {
+ EVP_PKEY_free(pkey);
+ }
+ return ret;
+}
+
+/* Tests loading a bad key in PKCS8 format */
+static int test_EVP_PKCS82PKEY(void) {
+ int ret = 0;
+ const uint8_t *derp = kExampleBadECKeyDER;
+ PKCS8_PRIV_KEY_INFO *p8inf = NULL;
+ EVP_PKEY *pkey = NULL;
+
+ p8inf = d2i_PKCS8_PRIV_KEY_INFO(NULL, &derp, sizeof(kExampleBadECKeyDER));
+
+ if (!p8inf || derp != kExampleBadECKeyDER + sizeof(kExampleBadECKeyDER)) {
+ fprintf(stderr, "Failed to parse key\n");
+ goto done;
+ }
+
+ pkey = EVP_PKCS82PKEY(p8inf);
+ if (pkey) {
+ fprintf(stderr, "Imported invalid EC key\n");
+ goto done;
+ }
+
+ ret = 1;
+
+done:
+ if (p8inf != NULL) {
+ PKCS8_PRIV_KEY_INFO_free(p8inf);
+ }
+
+ if (pkey != NULL) {
+ EVP_PKEY_free(pkey);
+ }
+
+ return ret;
+}
+
+int main(void) {
+ CRYPTO_library_init();
+ ERR_load_crypto_strings();
+
+ if (!test_EVP_DigestSignInit()) {
+ fprintf(stderr, "EVP_DigestSignInit failed\n");
+ return 1;
+ }
+
+ if (!test_EVP_DigestVerifyInit()) {
+ fprintf(stderr, "EVP_DigestVerifyInit failed\n");
+ return 1;
+ }
+
+ if (!test_EVP_DigestSignAlgorithm()) {
+ fprintf(stderr, "EVP_DigestSignInit failed\n");
+ return 1;
+ }
+
+ if (!test_EVP_DigestVerifyInitFromAlgorithm()) {
+ fprintf(stderr, "EVP_DigestVerifyInitFromAlgorithm failed\n");
+ return 1;
+ }
+
+ if (!test_d2i_AutoPrivateKey(kExampleRSAKeyDER, sizeof(kExampleRSAKeyDER),
+ EVP_PKEY_RSA)) {
+ fprintf(stderr, "d2i_AutoPrivateKey(kExampleRSAKeyDER) failed\n");
+ return 1;
+ }
+
+ if (!test_d2i_AutoPrivateKey(kExampleRSAKeyPKCS8, sizeof(kExampleRSAKeyPKCS8),
+ EVP_PKEY_RSA)) {
+ fprintf(stderr, "d2i_AutoPrivateKey(kExampleRSAKeyPKCS8) failed\n");
+ return 1;
+ }
+
+ if (!test_d2i_AutoPrivateKey(kExampleECKeyDER, sizeof(kExampleECKeyDER),
+ EVP_PKEY_EC)) {
+ fprintf(stderr, "d2i_AutoPrivateKey(kExampleECKeyDER) failed\n");
+ return 1;
+ }
+
+ if (!test_EVP_PKCS82PKEY()) {
+ fprintf(stderr, "test_EVP_PKCS82PKEY failed\n");
+ return 1;
+ }
+
+ printf("PASS\n");
+ return 0;
+}
diff --git a/src/crypto/evp/internal.h b/src/crypto/evp/internal.h
new file mode 100644
index 0000000..2b0f608
--- /dev/null
+++ b/src/crypto/evp/internal.h
@@ -0,0 +1,255 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 OPENSSL_HEADER_EVP_INTERNAL_H
+#define OPENSSL_HEADER_EVP_INTERNAL_H
+
+#include <openssl/base.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* These values are flags for EVP_PKEY_ASN1_METHOD.flags. */
+
+/* ASN1_PKEY_SIGPARAM_NULL controls whether the default behavior of
+ * EVP_DigestSignAlgorithm writes an explicit NULL parameter in the
+ * AlgorithmIdentifier. */
+#define ASN1_PKEY_SIGPARAM_NULL 0x1
+
+/* evp_digest_sign_algorithm_result_t is the return value of the
+ * digest_sign_algorithm function in EVP_PKEY_ASN1_METHOD. */
+typedef enum {
+ /* EVP_DIGEST_SIGN_ALGORITHM_ERROR signals an error. */
+ EVP_DIGEST_SIGN_ALGORITHM_ERROR = 0,
+ /* EVP_DIGEST_SIGN_ALGORITHM_SUCCESS signals that the parameters were
+ * serialized in the AlgorithmIdentifier. */
+ EVP_DIGEST_SIGN_ALGORITHM_SUCCESS = 1,
+ /* EVP_DIGEST_SIGN_ALGORITHM_DEFAULT signals that the parameters are
+ * serialized using the default behavior. */
+ EVP_DIGEST_SIGN_ALGORITHM_DEFAULT = 2,
+} evp_digest_sign_algorithm_result_t;
+
+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, 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);
+
+ /* pkey_opaque returns 1 if the |pk| is opaque. Opaque keys are backed by
+ * custom implementations which do not expose key material and parameters.*/
+ int (*pkey_opaque)(const EVP_PKEY *pk);
+
+ /* pkey_supports_digest returns one if |pkey| supports digests of
+ * type |md|. This is intended for use with EVP_PKEYs backing custom
+ * implementations which can't sign all digests. If null, it is
+ * assumed that all digests are supported. */
+ int (*pkey_supports_digest)(const EVP_PKEY *pkey, const EVP_MD *md);
+
+ int (*pkey_size)(const EVP_PKEY *pk);
+ int (*pkey_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);
+
+ /* 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);
+
+ /* Converting parameters to/from AlgorithmIdentifier (X509_ALGOR). */
+ int (*digest_verify_init_from_algorithm)(EVP_MD_CTX *ctx,
+ X509_ALGOR *algor,
+ EVP_PKEY *pkey);
+ evp_digest_sign_algorithm_result_t (*digest_sign_algorithm)(
+ EVP_MD_CTX *ctx,
+ X509_ALGOR *algor);
+
+} /* EVP_PKEY_ASN1_METHOD */;
+
+
+typedef int EVP_PKEY_gen_cb(EVP_PKEY_CTX *ctx);
+
+#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_CTRL_MD 1
+#define EVP_PKEY_CTRL_GET_MD 2
+#define EVP_PKEY_CTRL_RSA_PADDING (EVP_PKEY_ALG_CTRL + 1)
+#define EVP_PKEY_CTRL_GET_RSA_PADDING (EVP_PKEY_ALG_CTRL + 2)
+#define EVP_PKEY_CTRL_RSA_PSS_SALTLEN (EVP_PKEY_ALG_CTRL + 3)
+#define EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN (EVP_PKEY_ALG_CTRL + 4)
+#define EVP_PKEY_CTRL_RSA_KEYGEN_BITS (EVP_PKEY_ALG_CTRL + 5)
+#define EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP (EVP_PKEY_ALG_CTRL + 6)
+#define EVP_PKEY_CTRL_RSA_OAEP_MD (EVP_PKEY_ALG_CTRL + 7)
+#define EVP_PKEY_CTRL_GET_RSA_OAEP_MD (EVP_PKEY_ALG_CTRL + 8)
+#define EVP_PKEY_CTRL_RSA_MGF1_MD (EVP_PKEY_ALG_CTRL + 9)
+#define EVP_PKEY_CTRL_GET_RSA_MGF1_MD (EVP_PKEY_ALG_CTRL + 10)
+#define EVP_PKEY_CTRL_RSA_OAEP_LABEL (EVP_PKEY_ALG_CTRL + 11)
+#define EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL (EVP_PKEY_ALG_CTRL + 12)
+
+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;
+ /* operation contains one of the |EVP_PKEY_OP_*| values. */
+ int operation;
+ /* Algorithm specific data */
+ void *data;
+ /* Application specific data */
+ void *app_data;
+} /* EVP_PKEY_CTX */;
+
+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 (*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);
+} /* EVP_PKEY_METHOD */;
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_EVP_INTERNAL_H */
diff --git a/src/crypto/evp/p_ec.c b/src/crypto/evp/p_ec.c
new file mode 100644
index 0000000..c274131
--- /dev/null
+++ b/src/crypto/evp/p_ec.c
@@ -0,0 +1,303 @@
+/* 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 <openssl/evp.h>
+
+#include <string.h>
+
+#include <openssl/asn1.h>
+#include <openssl/bn.h>
+#include <openssl/buf.h>
+#include <openssl/digest.h>
+#include <openssl/ec.h>
+#include <openssl/ec_key.h>
+#include <openssl/ecdh.h>
+#include <openssl/ecdsa.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+
+#include "internal.h"
+#include "../ec/internal.h"
+
+
+typedef struct {
+ /* Key and paramgen group */
+ EC_GROUP *gen_group;
+ /* message digest */
+ const EVP_MD *md;
+} EC_PKEY_CTX;
+
+
+static int pkey_ec_init(EVP_PKEY_CTX *ctx) {
+ EC_PKEY_CTX *dctx;
+ dctx = OPENSSL_malloc(sizeof(EC_PKEY_CTX));
+ if (!dctx) {
+ return 0;
+ }
+ memset(dctx, 0, sizeof(EC_PKEY_CTX));
+
+ 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;
+
+ return 1;
+}
+
+static void pkey_ec_cleanup(EVP_PKEY_CTX *ctx) {
+ EC_PKEY_CTX *dctx = ctx->data;
+ if (!dctx) {
+ return;
+ }
+
+ if (dctx->gen_group) {
+ EC_GROUP_free(dctx->gen_group);
+ }
+ OPENSSL_free(dctx);
+}
+
+static int pkey_ec_sign(EVP_PKEY_CTX *ctx, uint8_t *sig, size_t *siglen,
+ const uint8_t *tbs, size_t tbslen) {
+ int 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)) {
+ OPENSSL_PUT_ERROR(EVP, pkey_ec_sign, EVP_R_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ type = NID_sha1;
+ if (dctx->md) {
+ type = EVP_MD_type(dctx->md);
+ }
+
+ if (!ECDSA_sign(type, tbs, tbslen, sig, &sltmp, ec)) {
+ return 0;
+ }
+ *siglen = (size_t)sltmp;
+ return 1;
+}
+
+static int pkey_ec_verify(EVP_PKEY_CTX *ctx, const uint8_t *sig, size_t siglen,
+ const uint8_t *tbs, size_t tbslen) {
+ int type;
+ EC_PKEY_CTX *dctx = ctx->data;
+ EC_KEY *ec = ctx->pkey->pkey.ec;
+
+ type = NID_sha1;
+ if (dctx->md) {
+ type = EVP_MD_type(dctx->md);
+ }
+
+ return ECDSA_verify(type, tbs, tbslen, sig, siglen, ec);
+}
+
+static int pkey_ec_derive(EVP_PKEY_CTX *ctx, uint8_t *key,
+ size_t *keylen) {
+ int ret;
+ size_t outlen;
+ const EC_POINT *pubkey = NULL;
+ EC_KEY *eckey;
+
+ if (!ctx->pkey || !ctx->peerkey) {
+ OPENSSL_PUT_ERROR(EVP, pkey_ec_derive, EVP_R_KEYS_NOT_SET);
+ return 0;
+ }
+
+ eckey = 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_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) {
+ OPENSSL_PUT_ERROR(EVP, pkey_ec_ctrl, EVP_R_INVALID_CURVE);
+ return 0;
+ }
+ if (dctx->gen_group)
+ EC_GROUP_free(dctx->gen_group);
+ dctx->gen_group = group;
+ return 1;
+
+ case EVP_PKEY_CTRL_MD:
+ if (EVP_MD_type((const EVP_MD *)p2) != NID_sha1 &&
+ EVP_MD_type((const EVP_MD *)p2) != NID_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) {
+ OPENSSL_PUT_ERROR(EVP, pkey_ec_ctrl, EVP_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:
+ return 1;
+
+ default:
+ 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) {
+ OPENSSL_PUT_ERROR(EVP, pkey_ec_paramgen, EVP_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) {
+ OPENSSL_PUT_ERROR(EVP, pkey_ec_keygen, EVP_R_NO_PARAMETERS_SET);
+ return 0;
+ }
+ ec = EC_KEY_new();
+ if (!ec) {
+ return 0;
+ }
+ EVP_PKEY_assign_EC_KEY(pkey, ec);
+ if (ctx->pkey) {
+ /* Note: if error return, pkey is freed by parent routine */
+ 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(pkey->pkey.ec);
+}
+
+const EVP_PKEY_METHOD ec_pkey_meth = {
+ EVP_PKEY_EC, 0 /* flags */, pkey_ec_init,
+ pkey_ec_copy, pkey_ec_cleanup, 0 /* paramgen_init */,
+ pkey_ec_paramgen, 0 /* keygen_init */, pkey_ec_keygen,
+ 0 /* sign_init */, pkey_ec_sign, 0 /* verify_init */,
+ pkey_ec_verify, 0 /* signctx_init */, 0 /* signctx */,
+ 0 /* verifyctx_init */, 0 /* verifyctx */, 0 /* encrypt_init */,
+ 0 /* encrypt */, 0 /* decrypt_init */, 0 /* decrypt */,
+ 0 /* derive_init */, pkey_ec_derive, pkey_ec_ctrl,
+};
diff --git a/src/crypto/evp/p_ec_asn1.c b/src/crypto/evp/p_ec_asn1.c
new file mode 100644
index 0000000..48a175b
--- /dev/null
+++ b/src/crypto/evp/p_ec_asn1.c
@@ -0,0 +1,574 @@
+/* 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 <openssl/evp.h>
+
+#include <openssl/asn1t.h>
+#include <openssl/bn.h>
+#include <openssl/ec.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/x509.h>
+
+#include "internal.h"
+
+
+static int eckey_param2type(int *pptype, void **ppval, EC_KEY *ec_key) {
+ const EC_GROUP *group;
+ int nid;
+
+ if (ec_key == NULL || (group = EC_KEY_get0_group(ec_key)) == NULL) {
+ OPENSSL_PUT_ERROR(EVP, eckey_param2type, EVP_R_MISSING_PARAMETERS);
+ return 0;
+ }
+
+ nid = EC_GROUP_get_curve_name(group);
+ if (nid == NID_undef) {
+ OPENSSL_PUT_ERROR(EVP, eckey_param2type, EVP_R_NO_NID_FOR_CURVE);
+ return 0;
+ }
+
+ *ppval = (void*) OBJ_nid2obj(nid);
+ *pptype = V_ASN1_OBJECT;
+ return 1;
+}
+
+static int eckey_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey) {
+ EC_KEY *ec_key = pkey->pkey.ec;
+ void *pval = NULL;
+ int ptype;
+ uint8_t *penc = NULL, *p;
+ int penclen;
+
+ if (!eckey_param2type(&ptype, &pval, ec_key)) {
+ OPENSSL_PUT_ERROR(EVP, eckey_pub_encode, ERR_R_EC_LIB);
+ return 0;
+ }
+ penclen = i2o_ECPublicKey(ec_key, NULL);
+ if (penclen <= 0) {
+ goto err;
+ }
+ penc = OPENSSL_malloc(penclen);
+ if (!penc) {
+ goto err;
+ }
+ p = penc;
+ penclen = i2o_ECPublicKey(ec_key, &p);
+ if (penclen <= 0) {
+ goto err;
+ }
+ if (X509_PUBKEY_set0_param(pk, OBJ_nid2obj(EVP_PKEY_EC), ptype, pval, penc,
+ penclen)) {
+ return 1;
+ }
+
+err:
+ if (ptype == V_ASN1_OBJECT) {
+ ASN1_OBJECT_free(pval);
+ } else {
+ ASN1_STRING_free(pval);
+ }
+ if (penc) {
+ OPENSSL_free(penc);
+ }
+ return 0;
+}
+
+static EC_KEY *eckey_type2param(int ptype, void *pval) {
+ EC_KEY *eckey = NULL;
+
+ if (ptype == V_ASN1_SEQUENCE) {
+ ASN1_STRING *pstr = pval;
+ const uint8_t *pm = pstr->data;
+ int pmlen = pstr->length;
+
+ eckey = d2i_ECParameters(NULL, &pm, pmlen);
+ if (eckey == NULL) {
+ OPENSSL_PUT_ERROR(EVP, eckey_type2param, EVP_R_DECODE_ERROR);
+ goto err;
+ }
+ } else if (ptype == V_ASN1_OBJECT) {
+ ASN1_OBJECT *poid = pval;
+ EC_GROUP *group;
+
+ /* type == V_ASN1_OBJECT => the parameters are given
+ * by an asn1 OID */
+ eckey = EC_KEY_new();
+ if (eckey == NULL) {
+ OPENSSL_PUT_ERROR(EVP, eckey_type2param, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ group = EC_GROUP_new_by_curve_name(OBJ_obj2nid(poid));
+ if (group == NULL) {
+ goto err;
+ }
+ if (EC_KEY_set_group(eckey, group) == 0) {
+ goto err;
+ }
+ EC_GROUP_free(group);
+ } else {
+ OPENSSL_PUT_ERROR(EVP, eckey_type2param, EVP_R_DECODE_ERROR);
+ goto err;
+ }
+
+ return eckey;
+
+err:
+ if (eckey) {
+ EC_KEY_free(eckey);
+ }
+ return NULL;
+}
+
+static int eckey_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey) {
+ const uint8_t *p = NULL;
+ void *pval;
+ int ptype, pklen;
+ EC_KEY *eckey = NULL;
+ X509_ALGOR *palg;
+
+ if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey)) {
+ return 0;
+ }
+ X509_ALGOR_get0(NULL, &ptype, &pval, palg);
+
+ eckey = eckey_type2param(ptype, pval);
+ if (!eckey) {
+ OPENSSL_PUT_ERROR(EVP, eckey_pub_decode, ERR_R_EC_LIB);
+ return 0;
+ }
+
+ /* We have parameters now set public key */
+ if (!o2i_ECPublicKey(&eckey, &p, pklen)) {
+ OPENSSL_PUT_ERROR(EVP, eckey_pub_decode, EVP_R_DECODE_ERROR);
+ goto err;
+ }
+
+ EVP_PKEY_assign_EC_KEY(pkey, eckey);
+ return 1;
+
+err:
+ if (eckey)
+ EC_KEY_free(eckey);
+ return 0;
+}
+
+static int eckey_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) {
+ int r;
+ const EC_GROUP *group = EC_KEY_get0_group(b->pkey.ec);
+ const EC_POINT *pa = EC_KEY_get0_public_key(a->pkey.ec),
+ *pb = EC_KEY_get0_public_key(b->pkey.ec);
+ r = EC_POINT_cmp(group, pa, pb, NULL);
+ if (r == 0) {
+ return 1;
+ } else if (r == 1) {
+ return 0;
+ } else {
+ return -2;
+ }
+}
+
+static int eckey_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8) {
+ const uint8_t *p = NULL;
+ void *pval;
+ int ptype, pklen;
+ EC_KEY *eckey = NULL;
+ X509_ALGOR *palg;
+
+ if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8)) {
+ return 0;
+ }
+ X509_ALGOR_get0(NULL, &ptype, &pval, palg);
+
+ eckey = eckey_type2param(ptype, pval);
+
+ if (!eckey)
+ goto ecliberr;
+
+ /* We have parameters now set private key */
+ if (!d2i_ECPrivateKey(&eckey, &p, pklen)) {
+ OPENSSL_PUT_ERROR(EVP, eckey_priv_decode, EVP_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) {
+ OPENSSL_PUT_ERROR(EVP, eckey_priv_decode, ERR_R_EC_LIB);
+ goto ecliberr;
+ }
+ if (!EC_POINT_copy(pub_key, EC_GROUP_get0_generator(group))) {
+ EC_POINT_free(pub_key);
+ OPENSSL_PUT_ERROR(EVP, eckey_priv_decode, 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);
+ OPENSSL_PUT_ERROR(EVP, eckey_priv_decode, ERR_R_EC_LIB);
+ goto ecliberr;
+ }
+ if (EC_KEY_set_public_key(eckey, pub_key) == 0) {
+ EC_POINT_free(pub_key);
+ OPENSSL_PUT_ERROR(EVP, eckey_priv_decode, ERR_R_EC_LIB);
+ goto ecliberr;
+ }
+ EC_POINT_free(pub_key);
+ }
+
+ EVP_PKEY_assign_EC_KEY(pkey, eckey);
+ return 1;
+
+ecliberr:
+ OPENSSL_PUT_ERROR(EVP, eckey_priv_decode, 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 *ec_key;
+ uint8_t *ep, *p;
+ int eplen, ptype;
+ void *pval;
+ unsigned int tmp_flags, old_flags;
+
+ ec_key = pkey->pkey.ec;
+
+ if (!eckey_param2type(&ptype, &pval, ec_key)) {
+ OPENSSL_PUT_ERROR(EVP, eckey_priv_encode, EVP_R_DECODE_ERROR);
+ return 0;
+ }
+
+ /* set the private key */
+
+ /* do not include the parameters in the SEC1 private key
+ * see PKCS#11 12.11 */
+ old_flags = EC_KEY_get_enc_flags(ec_key);
+ tmp_flags = old_flags | EC_PKEY_NO_PARAMETERS;
+ EC_KEY_set_enc_flags(ec_key, tmp_flags);
+ eplen = i2d_ECPrivateKey(ec_key, NULL);
+ if (!eplen) {
+ EC_KEY_set_enc_flags(ec_key, old_flags);
+ OPENSSL_PUT_ERROR(EVP, eckey_priv_encode, ERR_R_EC_LIB);
+ return 0;
+ }
+ ep = (uint8_t *)OPENSSL_malloc(eplen);
+ if (!ep) {
+ EC_KEY_set_enc_flags(ec_key, old_flags);
+ OPENSSL_PUT_ERROR(EVP, eckey_priv_encode, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ p = ep;
+ if (!i2d_ECPrivateKey(ec_key, &p)) {
+ EC_KEY_set_enc_flags(ec_key, old_flags);
+ OPENSSL_free(ep);
+ OPENSSL_PUT_ERROR(EVP, eckey_priv_encode, ERR_R_EC_LIB);
+ return 0;
+ }
+ /* restore old encoding flags */
+ EC_KEY_set_enc_flags(ec_key, old_flags);
+
+ if (!PKCS8_pkey_set0(p8, (ASN1_OBJECT *)OBJ_nid2obj(NID_X9_62_id_ecPublicKey),
+ 0, ptype, pval, ep, eplen)) {
+ return 0;
+ }
+
+ return 1;
+}
+
+static int int_ec_size(const EVP_PKEY *pkey) {
+ return ECDSA_size(pkey->pkey.ec);
+}
+
+static int ec_bits(const EVP_PKEY *pkey) {
+ BIGNUM *order = BN_new();
+ const EC_GROUP *group;
+ int ret;
+
+ if (!order) {
+ ERR_clear_error();
+ return 0;
+ }
+ group = EC_KEY_get0_group(pkey->pkey.ec);
+ if (!EC_GROUP_get_order(group, order, NULL)) {
+ ERR_clear_error();
+ return 0;
+ }
+
+ ret = BN_num_bits(order);
+ BN_free(order);
+ return ret;
+}
+
+static int ec_missing_parameters(const EVP_PKEY *pkey) {
+ return EC_KEY_get0_group(pkey->pkey.ec) == NULL;
+}
+
+static int ec_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) {
+ EC_GROUP *group = EC_GROUP_dup(EC_KEY_get0_group(from->pkey.ec));
+ if (group == NULL ||
+ EC_KEY_set_group(to->pkey.ec, group) == 0) {
+ return 0;
+ }
+ EC_GROUP_free(group);
+ return 1;
+}
+
+static int ec_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b) {
+ const EC_GROUP *group_a = EC_KEY_get0_group(a->pkey.ec),
+ *group_b = EC_KEY_get0_group(b->pkey.ec);
+ return EC_GROUP_cmp(group_a, group_b);
+}
+
+static void int_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) {
+ uint8_t *buffer = NULL;
+ const char *ecstr;
+ size_t buf_len = 0, i;
+ int ret = 0, reason = ERR_R_BIO_LIB;
+ BIGNUM *order = NULL;
+ BN_CTX *ctx = NULL;
+ const EC_GROUP *group;
+ const EC_POINT *public_key;
+ const BIGNUM *priv_key;
+ uint8_t *pub_key_bytes = NULL;
+ size_t pub_key_bytes_len = 0;
+
+ 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) {
+ pub_key_bytes_len = EC_POINT_point2oct(
+ group, public_key, EC_KEY_get_conv_form(x), NULL, 0, ctx);
+ if (pub_key_bytes_len == 0) {
+ reason = ERR_R_MALLOC_FAILURE;
+ goto err;
+ }
+ pub_key_bytes = OPENSSL_malloc(pub_key_bytes_len);
+ if (pub_key_bytes == NULL) {
+ reason = ERR_R_MALLOC_FAILURE;
+ goto err;
+ }
+ pub_key_bytes_len =
+ EC_POINT_point2oct(group, public_key, EC_KEY_get_conv_form(x),
+ pub_key_bytes, pub_key_bytes_len, ctx);
+ if (pub_key_bytes_len == 0) {
+ reason = ERR_R_MALLOC_FAILURE;
+ goto err;
+ }
+ buf_len = pub_key_bytes_len;
+ }
+ }
+
+ if (ktype == 2) {
+ priv_key = EC_KEY_get0_private_key(x);
+ if (priv_key && (i = (size_t)BN_num_bytes(priv_key)) > buf_len)
+ buf_len = i;
+ } else
+ priv_key = NULL;
+
+ if (ktype > 0) {
+ buf_len += 10;
+ if ((buffer = OPENSSL_malloc(buf_len)) == NULL) {
+ reason = ERR_R_MALLOC_FAILURE;
+ goto err;
+ }
+ }
+ 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 ((order = BN_new()) == NULL)
+ goto err;
+ if (!EC_GROUP_get_order(group, order, NULL))
+ goto err;
+ if (BIO_printf(bp, "%s: (%d bit)\n", ecstr, BN_num_bits(order)) <= 0)
+ goto err;
+
+ if ((priv_key != NULL) && !ASN1_bn_print(bp, "priv:", priv_key, buffer, off))
+ goto err;
+ if (pub_key_bytes != NULL) {
+ BIO_hexdump(bp, pub_key_bytes, pub_key_bytes_len, off);
+ }
+ /* TODO(fork): implement */
+ /*
+ if (!ECPKParameters_print(bp, group, off))
+ goto err; */
+ ret = 1;
+
+err:
+ if (!ret)
+ OPENSSL_PUT_ERROR(EVP, do_EC_KEY_print, reason);
+ if (pub_key_bytes)
+ OPENSSL_free(pub_key_bytes);
+ if (order)
+ BN_free(order);
+ if (ctx)
+ BN_CTX_free(ctx);
+ if (buffer != NULL)
+ OPENSSL_free(buffer);
+ return ret;
+}
+
+static int eckey_param_decode(EVP_PKEY *pkey, const uint8_t **pder,
+ int derlen) {
+ EC_KEY *eckey;
+ if (!(eckey = d2i_ECParameters(NULL, pder, derlen))) {
+ OPENSSL_PUT_ERROR(EVP, eckey_param_decode, ERR_R_EC_LIB);
+ return 0;
+ }
+ EVP_PKEY_assign_EC_KEY(pkey, eckey);
+ return 1;
+}
+
+static int eckey_param_encode(const EVP_PKEY *pkey, uint8_t **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 eckey_opaque(const EVP_PKEY *pkey) {
+ return EC_KEY_is_opaque(pkey->pkey.ec);
+}
+
+static int old_ec_priv_decode(EVP_PKEY *pkey, const uint8_t **pder,
+ int derlen) {
+ EC_KEY *ec;
+ if (!(ec = d2i_ECPrivateKey(NULL, pder, derlen))) {
+ OPENSSL_PUT_ERROR(EVP, old_ec_priv_decode, EVP_R_DECODE_ERROR);
+ return 0;
+ }
+ EVP_PKEY_assign_EC_KEY(pkey, ec);
+ return 1;
+}
+
+static int old_ec_priv_encode(const EVP_PKEY *pkey, uint8_t **pder) {
+ return i2d_ECPrivateKey(pkey->pkey.ec, pder);
+}
+
+const EVP_PKEY_ASN1_METHOD ec_asn1_meth = {
+ EVP_PKEY_EC,
+ EVP_PKEY_EC,
+ 0,
+ "EC",
+ "OpenSSL EC algorithm",
+
+ eckey_pub_decode,
+ eckey_pub_encode,
+ eckey_pub_cmp,
+ eckey_pub_print,
+
+ eckey_priv_decode,
+ eckey_priv_encode,
+ eckey_priv_print,
+
+ eckey_opaque,
+ 0 /* pkey_supports_digest */,
+
+ int_ec_size,
+ ec_bits,
+
+ eckey_param_decode,
+ eckey_param_encode,
+ ec_missing_parameters,
+ ec_copy_parameters,
+ ec_cmp_parameters,
+ eckey_param_print,
+ 0,
+
+ int_ec_free,
+ old_ec_priv_decode,
+ old_ec_priv_encode
+};
diff --git a/src/crypto/evp/p_hmac.c b/src/crypto/evp/p_hmac.c
new file mode 100644
index 0000000..6d9a909
--- /dev/null
+++ b/src/crypto/evp/p_hmac.c
@@ -0,0 +1,222 @@
+/* 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 <openssl/evp.h>
+
+#include <string.h>
+
+#include <openssl/asn1.h>
+#include <openssl/err.h>
+#include <openssl/hmac.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+
+#include "internal.h"
+
+
+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;
+ hctx = OPENSSL_malloc(sizeof(HMAC_PKEY_CTX));
+ if (!hctx) {
+ return 0;
+ }
+ memset(hctx, 0, sizeof(HMAC_PKEY_CTX));
+ hctx->ktmp.type = V_ASN1_OCTET_STRING;
+ HMAC_CTX_init(&hctx->ctx);
+
+ ctx->data = hctx;
+
+ 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_ex(&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 = ctx->data;
+
+ if (hctx == NULL) {
+ return;
+ }
+
+ HMAC_CTX_cleanup(&hctx->ctx);
+ if (hctx->ktmp.data) {
+ if (hctx->ktmp.length) {
+ OPENSSL_cleanse(hctx->ktmp.data, hctx->ktmp.length);
+ }
+ OPENSSL_free(hctx->ktmp.data);
+ hctx->ktmp.data = NULL;
+ }
+ OPENSSL_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;
+ return HMAC_Update(&hctx->ctx, data, count);
+}
+
+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;
+ size_t md_size = EVP_MD_CTX_size(mctx);
+
+ if (!sig) {
+ *siglen = md_size;
+ return 1;
+ } else if (*siglen < md_size) {
+ OPENSSL_PUT_ERROR(EVP, hmac_signctx, EVP_R_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ if (!HMAC_Final(&hctx->ctx, sig, &hlen)) {
+ return 0;
+ }
+ *siglen = (size_t)hlen;
+ return 1;
+}
+
+static int pkey_hmac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) {
+ HMAC_PKEY_CTX *hctx = ctx->data;
+ ASN1_OCTET_STRING *key;
+
+ switch (type) {
+ case EVP_PKEY_CTRL_SET_MAC_KEY:
+ if ((!p2 && p1 > 0) || (p1 < -1)) {
+ return 0;
+ }
+ if (!ASN1_OCTET_STRING_set(&hctx->ktmp, p2, p1)) {
+ return 0;
+ }
+ break;
+
+ case EVP_PKEY_CTRL_MD:
+ hctx->md = p2;
+ break;
+
+ case EVP_PKEY_CTRL_DIGESTINIT:
+ key = (ASN1_OCTET_STRING *)ctx->pkey->pkey.ptr;
+ if (!HMAC_Init_ex(&hctx->ctx, key->data, key->length, hctx->md,
+ ctx->engine)) {
+ return 0;
+ }
+ break;
+
+ default:
+ return -2;
+ }
+ return 1;
+}
+
+const EVP_PKEY_METHOD hmac_pkey_meth = {
+ EVP_PKEY_HMAC, 0 /* flags */, pkey_hmac_init,
+ pkey_hmac_copy, pkey_hmac_cleanup, 0 /* paramgen_init */,
+ 0 /* paramgen */, 0 /* keygen_init */, pkey_hmac_keygen,
+ 0 /* sign_init */, 0 /* sign */, 0 /* verify_init */,
+ 0 /* verify */, hmac_signctx_init, hmac_signctx,
+ 0 /* verifyctx_init */, 0 /* verifyctx */, 0 /* encrypt_init */,
+ 0 /* encrypt */, 0 /* decrypt_init */, 0 /* decrypt */,
+ 0 /* derive_init */, 0 /* derive */, pkey_hmac_ctrl,
+ 0,
+};
diff --git a/src/crypto/evp/p_hmac_asn1.c b/src/crypto/evp/p_hmac_asn1.c
new file mode 100644
index 0000000..8aa6676
--- /dev/null
+++ b/src/crypto/evp/p_hmac_asn1.c
@@ -0,0 +1,89 @@
+/* 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 <openssl/evp.h>
+
+#include <openssl/asn1.h>
+#include <openssl/digest.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+
+#include "internal.h"
+
+
+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 = (ASN1_OCTET_STRING *)pkey->pkey.ptr;
+ if (os) {
+ if (os->data) {
+ OPENSSL_cleanse(os->data, os->length);
+ }
+ ASN1_OCTET_STRING_free(os);
+ }
+}
+
+const EVP_PKEY_ASN1_METHOD hmac_asn1_meth = {
+ EVP_PKEY_HMAC, EVP_PKEY_HMAC, 0 /* flags */,
+ "HMAC", "OpenSSL HMAC method", 0 /* pub_decode */,
+ 0 /* pub_encode */, 0 /* pub_cmp */, 0 /* pub_print */,
+ 0 /*priv_decode */, 0 /* priv_encode */, 0 /* priv_print */,
+ 0 /* pkey_opaque */, 0 /* pkey_supports_digest */,
+ hmac_size, 0 /* pkey_bits */, 0 /* param_decode */,
+ 0 /* param_encode*/, 0 /* param_missing*/, 0 /* param_copy*/,
+ 0 /* param_cmp*/, 0 /* param_print*/, 0 /* sig_print*/,
+ hmac_key_free, 0 /* old_priv_decode */,
+ 0 /* old_priv_encode */
+};
diff --git a/src/crypto/evp/p_rsa.c b/src/crypto/evp/p_rsa.c
new file mode 100644
index 0000000..31f5aaa
--- /dev/null
+++ b/src/crypto/evp/p_rsa.c
@@ -0,0 +1,598 @@
+/* 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 <openssl/evp.h>
+
+#include <string.h>
+
+#include <openssl/bn.h>
+#include <openssl/buf.h>
+#include <openssl/digest.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/rsa.h>
+
+#include "../rsa/internal.h"
+#include "internal.h"
+
+
+typedef struct {
+ /* Key gen parameters */
+ int nbits;
+ BIGNUM *pub_exp;
+ /* 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;
+ /* tbuf is a buffer which is either NULL, or is the size of the RSA modulus.
+ * It's used to store the output of RSA operations. */
+ uint8_t *tbuf;
+ /* OAEP label */
+ uint8_t *oaep_label;
+ size_t oaep_labellen;
+} RSA_PKEY_CTX;
+
+static int pkey_rsa_init(EVP_PKEY_CTX *ctx) {
+ RSA_PKEY_CTX *rctx;
+ rctx = OPENSSL_malloc(sizeof(RSA_PKEY_CTX));
+ if (!rctx) {
+ return 0;
+ }
+ memset(rctx, 0, sizeof(RSA_PKEY_CTX));
+
+ rctx->nbits = 2048;
+ rctx->pad_mode = RSA_PKCS1_PADDING;
+ rctx->saltlen = -2;
+
+ ctx->data = rctx;
+
+ 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) {
+ dctx->pub_exp = BN_dup(sctx->pub_exp);
+ if (!dctx->pub_exp) {
+ return 0;
+ }
+ }
+
+ dctx->pad_mode = sctx->pad_mode;
+ dctx->md = sctx->md;
+ dctx->mgf1md = sctx->mgf1md;
+ if (sctx->oaep_label) {
+ if (dctx->oaep_label) {
+ OPENSSL_free(dctx->oaep_label);
+ }
+ dctx->oaep_label = BUF_memdup(sctx->oaep_label, sctx->oaep_labellen);
+ if (!dctx->oaep_label) {
+ return 0;
+ }
+ dctx->oaep_labellen = sctx->oaep_labellen;
+ }
+
+ return 1;
+}
+
+static void pkey_rsa_cleanup(EVP_PKEY_CTX *ctx) {
+ RSA_PKEY_CTX *rctx = ctx->data;
+
+ if (rctx == NULL) {
+ return;
+ }
+
+ if (rctx->pub_exp) {
+ BN_free(rctx->pub_exp);
+ }
+ if (rctx->tbuf) {
+ OPENSSL_free(rctx->tbuf);
+ }
+ if (rctx->oaep_label) {
+ OPENSSL_free(rctx->oaep_label);
+ }
+ OPENSSL_free(rctx);
+}
+
+static int setup_tbuf(RSA_PKEY_CTX *ctx, EVP_PKEY_CTX *pk) {
+ if (ctx->tbuf) {
+ return 1;
+ }
+ ctx->tbuf = OPENSSL_malloc(EVP_PKEY_size(pk->pkey));
+ if (!ctx->tbuf) {
+ return 0;
+ }
+ return 1;
+}
+
+static int pkey_rsa_sign(EVP_PKEY_CTX *ctx, uint8_t *sig, size_t *siglen,
+ const uint8_t *tbs, size_t tbslen) {
+ RSA_PKEY_CTX *rctx = ctx->data;
+ RSA *rsa = ctx->pkey->pkey.rsa;
+ const size_t key_len = EVP_PKEY_size(ctx->pkey);
+
+ if (!sig) {
+ *siglen = key_len;
+ return 1;
+ }
+
+ if (*siglen < key_len) {
+ OPENSSL_PUT_ERROR(EVP, pkey_rsa_sign, EVP_R_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ if (rctx->md) {
+ unsigned int out_len;
+
+ if (tbslen != EVP_MD_size(rctx->md)) {
+ OPENSSL_PUT_ERROR(EVP, pkey_rsa_sign, EVP_R_INVALID_DIGEST_LENGTH);
+ return 0;
+ }
+
+ if (EVP_MD_type(rctx->md) == NID_mdc2) {
+ OPENSSL_PUT_ERROR(EVP, pkey_rsa_sign, EVP_R_NO_MDC2_SUPPORT);
+ return 0;
+ }
+
+ switch (rctx->pad_mode) {
+ case RSA_PKCS1_PADDING:
+ if (!RSA_sign(EVP_MD_type(rctx->md), tbs, tbslen, sig, &out_len, rsa)) {
+ return 0;
+ }
+ *siglen = out_len;
+ return 1;
+
+ case RSA_PKCS1_PSS_PADDING:
+ if (!setup_tbuf(rctx, ctx) ||
+ !RSA_padding_add_PKCS1_PSS_mgf1(rsa, rctx->tbuf, tbs, rctx->md,
+ rctx->mgf1md, rctx->saltlen) ||
+ !RSA_sign_raw(rsa, siglen, sig, *siglen, rctx->tbuf, key_len,
+ RSA_NO_PADDING)) {
+ return 0;
+ }
+ return 1;
+
+ default:
+ return 0;
+ }
+ }
+
+ return RSA_sign_raw(rsa, siglen, sig, *siglen, tbs, tbslen, rctx->pad_mode);
+}
+
+static int pkey_rsa_verify(EVP_PKEY_CTX *ctx, const uint8_t *sig,
+ size_t siglen, const uint8_t *tbs,
+ size_t tbslen) {
+ RSA_PKEY_CTX *rctx = ctx->data;
+ RSA *rsa = ctx->pkey->pkey.rsa;
+ size_t rslen;
+ const size_t key_len = EVP_PKEY_size(ctx->pkey);
+
+ if (rctx->md) {
+ switch (rctx->pad_mode) {
+ case RSA_PKCS1_PADDING:
+ return RSA_verify(EVP_MD_type(rctx->md), tbs, tbslen, sig, siglen, rsa);
+
+ case RSA_PKCS1_PSS_PADDING:
+ if (!setup_tbuf(rctx, ctx) ||
+ !RSA_verify_raw(rsa, &rslen, rctx->tbuf, key_len, sig, siglen,
+ RSA_NO_PADDING) ||
+ !RSA_verify_PKCS1_PSS_mgf1(rsa, tbs, rctx->md, rctx->mgf1md,
+ rctx->tbuf, rctx->saltlen)) {
+ return 0;
+ }
+ return 1;
+
+ default:
+ return 0;
+ }
+ }
+
+ if (!setup_tbuf(rctx, ctx) ||
+ !RSA_verify_raw(rsa, &rslen, rctx->tbuf, key_len, sig, siglen,
+ rctx->pad_mode) ||
+ rslen != tbslen ||
+ CRYPTO_memcmp(tbs, rctx->tbuf, rslen) != 0) {
+ return 0;
+ }
+
+ return 1;
+}
+
+static int pkey_rsa_encrypt(EVP_PKEY_CTX *ctx, uint8_t *out, size_t *outlen,
+ const uint8_t *in, size_t inlen) {
+ RSA_PKEY_CTX *rctx = ctx->data;
+ RSA *rsa = ctx->pkey->pkey.rsa;
+ const size_t key_len = EVP_PKEY_size(ctx->pkey);
+
+ if (!out) {
+ *outlen = key_len;
+ return 1;
+ }
+
+ if (*outlen < key_len) {
+ OPENSSL_PUT_ERROR(EVP, pkey_rsa_encrypt, EVP_R_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ if (rctx->pad_mode == RSA_PKCS1_OAEP_PADDING) {
+ if (!setup_tbuf(rctx, ctx) ||
+ !RSA_padding_add_PKCS1_OAEP_mgf1(rctx->tbuf, key_len, in, inlen,
+ rctx->oaep_label, rctx->oaep_labellen,
+ rctx->md, rctx->mgf1md) ||
+ !RSA_encrypt(rsa, outlen, out, *outlen, rctx->tbuf, key_len,
+ RSA_NO_PADDING)) {
+ return 0;
+ }
+ return 1;
+ }
+
+ return RSA_encrypt(rsa, outlen, out, *outlen, in, inlen, rctx->pad_mode);
+}
+
+static int pkey_rsa_decrypt(EVP_PKEY_CTX *ctx, uint8_t *out,
+ size_t *outlen, const uint8_t *in,
+ size_t inlen) {
+ RSA_PKEY_CTX *rctx = ctx->data;
+ RSA *rsa = ctx->pkey->pkey.rsa;
+ const size_t key_len = EVP_PKEY_size(ctx->pkey);
+
+ if (!out) {
+ *outlen = key_len;
+ return 1;
+ }
+
+ if (*outlen < key_len) {
+ OPENSSL_PUT_ERROR(EVP, pkey_rsa_decrypt, EVP_R_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ if (rctx->pad_mode == RSA_PKCS1_OAEP_PADDING) {
+ size_t plaintext_len;
+ int message_len;
+
+ if (!setup_tbuf(rctx, ctx) ||
+ !RSA_decrypt(rsa, &plaintext_len, rctx->tbuf, key_len, in, inlen,
+ RSA_NO_PADDING)) {
+ return 0;
+ }
+
+ message_len = RSA_padding_check_PKCS1_OAEP_mgf1(
+ out, key_len, rctx->tbuf, plaintext_len, rctx->oaep_label,
+ rctx->oaep_labellen, rctx->md, rctx->mgf1md);
+ if (message_len < 0) {
+ return 0;
+ }
+ *outlen = message_len;
+ return 1;
+ }
+
+ return RSA_decrypt(rsa, outlen, out, key_len, in, inlen, rctx->pad_mode);
+}
+
+static int check_padding_md(const EVP_MD *md, int padding) {
+ if (!md) {
+ return 1;
+ }
+
+ if (padding == RSA_NO_PADDING) {
+ OPENSSL_PUT_ERROR(EVP, check_padding_md, EVP_R_INVALID_PADDING_MODE);
+ return 0;
+ }
+
+ return 1;
+}
+
+static int is_known_padding(int padding_mode) {
+ switch (padding_mode) {
+ case RSA_PKCS1_PADDING:
+ case RSA_NO_PADDING:
+ case RSA_PKCS1_OAEP_PADDING:
+ case RSA_PKCS1_PSS_PADDING:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+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 (!is_known_padding(p1) || !check_padding_md(rctx->md, p1) ||
+ (p1 == RSA_PKCS1_PSS_PADDING &&
+ 0 == (ctx->operation & (EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY))) ||
+ (p1 == RSA_PKCS1_OAEP_PADDING &&
+ 0 == (ctx->operation & EVP_PKEY_OP_TYPE_CRYPT))) {
+ OPENSSL_PUT_ERROR(EVP, pkey_rsa_ctrl,
+ EVP_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE);
+ return -2;
+ }
+ if ((p1 == RSA_PKCS1_PSS_PADDING || p1 == RSA_PKCS1_OAEP_PADDING) &&
+ rctx->md == NULL) {
+ rctx->md = EVP_sha1();
+ }
+ rctx->pad_mode = p1;
+ return 1;
+
+ 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) {
+ OPENSSL_PUT_ERROR(EVP, pkey_rsa_ctrl, EVP_R_INVALID_PSS_SALTLEN);
+ return -2;
+ }
+ if (type == EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN) {
+ *(int *)p2 = rctx->saltlen;
+ } else {
+ if (p1 < -2) {
+ return -2;
+ }
+ rctx->saltlen = p1;
+ }
+ return 1;
+
+ case EVP_PKEY_CTRL_RSA_KEYGEN_BITS:
+ if (p1 < 256) {
+ OPENSSL_PUT_ERROR(EVP, pkey_rsa_ctrl, EVP_R_INVALID_KEYBITS);
+ return -2;
+ }
+ rctx->nbits = p1;
+ return 1;
+
+ case EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP:
+ if (!p2) {
+ 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) {
+ OPENSSL_PUT_ERROR(EVP, pkey_rsa_ctrl, EVP_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;
+ }
+ 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) {
+ OPENSSL_PUT_ERROR(EVP, pkey_rsa_ctrl, EVP_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 {
+ rctx->mgf1md = p2;
+ }
+ return 1;
+
+ case EVP_PKEY_CTRL_RSA_OAEP_LABEL:
+ if (rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) {
+ OPENSSL_PUT_ERROR(EVP, pkey_rsa_ctrl, EVP_R_INVALID_PADDING_MODE);
+ return -2;
+ }
+ if (rctx->oaep_label) {
+ OPENSSL_free(rctx->oaep_label);
+ }
+ if (p2 && p1 > 0) {
+ /* TODO(fork): this seems wrong. Shouldn't it take a copy of the
+ * buffer? */
+ 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) {
+ OPENSSL_PUT_ERROR(EVP, pkey_rsa_ctrl, EVP_R_INVALID_PADDING_MODE);
+ return -2;
+ }
+ *(uint8_t **)p2 = rctx->oaep_label;
+ return rctx->oaep_labellen;
+
+ case EVP_PKEY_CTRL_DIGESTINIT:
+ return 1;
+
+ default:
+ return -2;
+ }
+}
+
+static int pkey_rsa_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) {
+ RSA *rsa = NULL;
+ RSA_PKEY_CTX *rctx = ctx->data;
+
+ if (!rctx->pub_exp) {
+ rctx->pub_exp = BN_new();
+ if (!rctx->pub_exp || !BN_set_word(rctx->pub_exp, RSA_F4))
+ return 0;
+ }
+ rsa = RSA_new();
+ if (!rsa) {
+ return 0;
+ }
+
+ if (!RSA_generate_key_ex(rsa, rctx->nbits, rctx->pub_exp, NULL)) {
+ RSA_free(rsa);
+ return 0;
+ }
+
+ EVP_PKEY_assign_RSA(pkey, rsa);
+ return 1;
+}
+
+const EVP_PKEY_METHOD rsa_pkey_meth = {
+ EVP_PKEY_RSA, 0 /* flags */, pkey_rsa_init,
+ pkey_rsa_copy, pkey_rsa_cleanup, 0 /* paramgen_init */,
+ 0 /* paramgen */, 0 /* keygen_init */, pkey_rsa_keygen,
+ 0 /* sign_init */, pkey_rsa_sign, 0 /* verify_init */,
+ pkey_rsa_verify, 0 /* signctx_init */, 0 /* signctx */,
+ 0 /* verifyctx_init */, 0 /* verifyctx */, 0 /* encrypt_init */,
+ pkey_rsa_encrypt, 0 /* decrypt_init */, pkey_rsa_decrypt,
+ 0 /* derive_init */, 0 /* derive */, pkey_rsa_ctrl,
+};
+
+int EVP_PKEY_CTX_set_rsa_padding(EVP_PKEY_CTX *ctx, int padding) {
+ return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, -1, EVP_PKEY_CTRL_RSA_PADDING,
+ padding, NULL);
+}
+
+int EVP_PKEY_CTX_get_rsa_padding(EVP_PKEY_CTX *ctx, int *out_padding) {
+ return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, -1, EVP_PKEY_CTRL_GET_RSA_PADDING,
+ 0, out_padding);
+}
+
+int EVP_PKEY_CTX_set_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int salt_len) {
+ return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA,
+ (EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY),
+ EVP_PKEY_CTRL_RSA_PSS_SALTLEN, salt_len, NULL);
+}
+
+int EVP_PKEY_CTX_get_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int *out_salt_len) {
+ return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA,
+ (EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY),
+ EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN, 0, out_salt_len);
+}
+
+int EVP_PKEY_CTX_set_rsa_keygen_bits(EVP_PKEY_CTX *ctx, int bits) {
+ return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_KEYGEN,
+ EVP_PKEY_CTRL_RSA_KEYGEN_BITS, bits, NULL);
+}
+
+int EVP_PKEY_CTX_set_rsa_keygen_pubexp(EVP_PKEY_CTX *ctx, BIGNUM *e) {
+ return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_KEYGEN,
+ EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP, 0, e);
+}
+
+int EVP_PKEY_CTX_set_rsa_oaep_md(EVP_PKEY_CTX *ctx, const EVP_MD *md) {
+ return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT,
+ EVP_PKEY_CTRL_RSA_OAEP_MD, 0, (void *)md);
+}
+
+int EVP_PKEY_CTX_get_rsa_oaep_md(EVP_PKEY_CTX *ctx, const EVP_MD **out_md) {
+ return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT,
+ EVP_PKEY_CTRL_GET_RSA_OAEP_MD, 0, (void*) out_md);
+}
+
+int EVP_PKEY_CTX_set_rsa_mgf1_md(EVP_PKEY_CTX *ctx, const EVP_MD *md) {
+ return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA,
+ EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT,
+ EVP_PKEY_CTRL_RSA_MGF1_MD, 0, (void*) md);
+}
+
+int EVP_PKEY_CTX_get_rsa_mgf1_md(EVP_PKEY_CTX *ctx, const EVP_MD **out_md) {
+ return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA,
+ EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT,
+ EVP_PKEY_CTRL_GET_RSA_MGF1_MD, 0, (void*) out_md);
+}
+
+int EVP_PKEY_CTX_set0_rsa_oaep_label(EVP_PKEY_CTX *ctx, const uint8_t *label,
+ size_t label_len) {
+ int label_len_int = label_len;
+ if (((size_t) label_len_int) != label_len) {
+ return -2;
+ }
+
+ return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT,
+ EVP_PKEY_CTRL_RSA_OAEP_LABEL, label_len,
+ (void *)label);
+}
+
+int EVP_PKEY_CTX_get0_rsa_oaep_label(EVP_PKEY_CTX *ctx,
+ const uint8_t **out_label) {
+ return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT,
+ EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL, 0, (void *) out_label);
+}
diff --git a/src/crypto/evp/p_rsa_asn1.c b/src/crypto/evp/p_rsa_asn1.c
new file mode 100644
index 0000000..f478d50
--- /dev/null
+++ b/src/crypto/evp/p_rsa_asn1.c
@@ -0,0 +1,705 @@
+/* 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 <openssl/evp.h>
+
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/digest.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/rsa.h>
+#include <openssl/x509.h>
+
+#include "../rsa/internal.h"
+#include "internal.h"
+
+
+static int rsa_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey) {
+ uint8_t *encoded = NULL;
+ int len;
+ len = i2d_RSAPublicKey(pkey->pkey.rsa, &encoded);
+
+ if (len <= 0) {
+ return 0;
+ }
+
+ if (!X509_PUBKEY_set0_param(pk, OBJ_nid2obj(EVP_PKEY_RSA), V_ASN1_NULL, NULL,
+ encoded, len)) {
+ OPENSSL_free(encoded);
+ return 0;
+ }
+
+ return 1;
+}
+
+static int rsa_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey) {
+ const uint8_t *p;
+ int pklen;
+ RSA *rsa;
+
+ if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, NULL, pubkey)) {
+ return 0;
+ }
+ rsa = d2i_RSAPublicKey(NULL, &p, pklen);
+ if (rsa == NULL) {
+ OPENSSL_PUT_ERROR(EVP, rsa_pub_decode, ERR_R_RSA_LIB);
+ return 0;
+ }
+ EVP_PKEY_assign_RSA(pkey, rsa);
+ return 1;
+}
+
+static int rsa_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) {
+ return BN_cmp(b->pkey.rsa->n, a->pkey.rsa->n) == 0 &&
+ BN_cmp(b->pkey.rsa->e, a->pkey.rsa->e) == 0;
+}
+
+static int rsa_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey) {
+ uint8_t *rk = NULL;
+ int rklen;
+
+ rklen = i2d_RSAPrivateKey(pkey->pkey.rsa, &rk);
+
+ if (rklen <= 0) {
+ OPENSSL_PUT_ERROR(EVP, rsa_priv_encode, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ /* TODO(fork): const correctness in next line. */
+ if (!PKCS8_pkey_set0(p8, (ASN1_OBJECT *)OBJ_nid2obj(NID_rsaEncryption), 0,
+ V_ASN1_NULL, NULL, rk, rklen)) {
+ OPENSSL_PUT_ERROR(EVP, rsa_priv_encode, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ return 1;
+}
+
+static int rsa_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8) {
+ const uint8_t *p;
+ int pklen;
+ RSA *rsa;
+
+ if (!PKCS8_pkey_get0(NULL, &p, &pklen, NULL, p8)) {
+ OPENSSL_PUT_ERROR(EVP, rsa_priv_decode, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ rsa = d2i_RSAPrivateKey(NULL, &p, pklen);
+ if (rsa == NULL) {
+ OPENSSL_PUT_ERROR(EVP, rsa_priv_decode, ERR_R_RSA_LIB);
+ return 0;
+ }
+
+ EVP_PKEY_assign_RSA(pkey, rsa);
+ return 1;
+}
+
+static int rsa_opaque(const EVP_PKEY *pkey) {
+ return RSA_is_opaque(pkey->pkey.rsa);
+}
+
+static int rsa_supports_digest(const EVP_PKEY *pkey, const EVP_MD *md) {
+ return RSA_supports_digest(pkey->pkey.rsa, md);
+}
+
+static int 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 void int_rsa_free(EVP_PKEY *pkey) { RSA_free(pkey->pkey.rsa); }
+
+static void update_buflen(const BIGNUM *b, size_t *pbuflen) {
+ size_t i;
+
+ if (!b) {
+ return;
+ }
+
+ i = BN_num_bytes(b);
+ if (*pbuflen < i) {
+ *pbuflen = i;
+ }
+}
+
+static int do_rsa_print(BIO *out, const RSA *rsa, int off,
+ int include_private) {
+ char *str;
+ const char *s;
+ uint8_t *m = NULL;
+ int ret = 0, mod_len = 0;
+ size_t buf_len = 0;
+
+ update_buflen(rsa->n, &buf_len);
+ update_buflen(rsa->e, &buf_len);
+
+ if (include_private) {
+ update_buflen(rsa->d, &buf_len);
+ update_buflen(rsa->p, &buf_len);
+ update_buflen(rsa->q, &buf_len);
+ update_buflen(rsa->dmp1, &buf_len);
+ update_buflen(rsa->dmq1, &buf_len);
+ update_buflen(rsa->iqmp, &buf_len);
+ }
+
+ m = (uint8_t *)OPENSSL_malloc(buf_len + 10);
+ if (m == NULL) {
+ OPENSSL_PUT_ERROR(EVP, do_rsa_print, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (rsa->n != NULL) {
+ mod_len = BN_num_bits(rsa->n);
+ }
+
+ if (!BIO_indent(out, off, 128)) {
+ goto err;
+ }
+
+ if (include_private && rsa->d) {
+ if (BIO_printf(out, "Private-Key: (%d bit)\n", mod_len) <= 0) {
+ goto err;
+ }
+ str = "modulus:";
+ s = "publicExponent:";
+ } else {
+ if (BIO_printf(out, "Public-Key: (%d bit)\n", mod_len) <= 0) {
+ goto err;
+ }
+ str = "Modulus:";
+ s = "Exponent:";
+ }
+ if (!ASN1_bn_print(out, str, rsa->n, m, off) ||
+ !ASN1_bn_print(out, s, rsa->e, m, off)) {
+ goto err;
+ }
+
+ if (include_private) {
+ if (!ASN1_bn_print(out, "privateExponent:", rsa->d, m, off) ||
+ !ASN1_bn_print(out, "prime1:", rsa->p, m, off) ||
+ !ASN1_bn_print(out, "prime2:", rsa->q, m, off) ||
+ !ASN1_bn_print(out, "exponent1:", rsa->dmp1, m, off) ||
+ !ASN1_bn_print(out, "exponent2:", rsa->dmq1, m, off) ||
+ !ASN1_bn_print(out, "coefficient:", rsa->iqmp, m, off)) {
+ goto err;
+ }
+ }
+ ret = 1;
+
+err:
+ if (m != NULL) {
+ OPENSSL_free(m);
+ }
+ return ret;
+}
+
+static int rsa_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
+ ASN1_PCTX *ctx) {
+ return do_rsa_print(bp, pkey->pkey.rsa, indent, 0);
+}
+
+
+static int rsa_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
+ ASN1_PCTX *ctx) {
+ return do_rsa_print(bp, pkey->pkey.rsa, indent, 1);
+}
+
+/* Given an MGF1 Algorithm ID decode to an Algorithm Identifier */
+static X509_ALGOR *rsa_mgf1_decode(X509_ALGOR *alg) {
+ const uint8_t *p;
+ int plen;
+
+ if (alg == NULL ||
+ OBJ_obj2nid(alg->algorithm) != NID_mgf1 ||
+ alg->parameter->type != V_ASN1_SEQUENCE) {
+ return NULL;
+ }
+
+ p = alg->parameter->value.sequence->data;
+ plen = alg->parameter->value.sequence->length;
+ return d2i_X509_ALGOR(NULL, &p, plen);
+}
+
+static RSA_PSS_PARAMS *rsa_pss_decode(const X509_ALGOR *alg,
+ X509_ALGOR **pmaskHash) {
+ const uint8_t *p;
+ int plen;
+ RSA_PSS_PARAMS *pss;
+
+ *pmaskHash = NULL;
+
+ if (!alg->parameter || alg->parameter->type != V_ASN1_SEQUENCE) {
+ return NULL;
+ }
+ p = alg->parameter->value.sequence->data;
+ plen = alg->parameter->value.sequence->length;
+ pss = d2i_RSA_PSS_PARAMS(NULL, &p, plen);
+
+ if (!pss) {
+ return NULL;
+ }
+
+ *pmaskHash = rsa_mgf1_decode(pss->maskGenAlgorithm);
+
+ return pss;
+}
+
+static int rsa_pss_param_print(BIO *bp, RSA_PSS_PARAMS *pss,
+ X509_ALGOR *maskHash, int indent) {
+ int rv = 0;
+
+ if (!pss) {
+ if (BIO_puts(bp, " (INVALID PSS PARAMETERS)\n") <= 0) {
+ return 0;
+ }
+ return 1;
+ }
+
+ if (BIO_puts(bp, "\n") <= 0 ||
+ !BIO_indent(bp, indent, 128) ||
+ 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 ||
+ !BIO_indent(bp, indent, 128) ||
+ BIO_puts(bp, "Mask Algorithm: ") <= 0) {
+ goto err;
+ }
+
+ if (pss->maskGenAlgorithm) {
+ if (i2a_ASN1_OBJECT(bp, pss->maskGenAlgorithm->algorithm) <= 0 ||
+ BIO_puts(bp, " with ") <= 0) {
+ goto err;
+ }
+
+ if (maskHash) {
+ 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) ||
+ BIO_puts(bp, "Salt Length: 0x") <= 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) ||
+ 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:
+ return rv;
+}
+
+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) == NID_rsassaPss) {
+ int rv;
+ RSA_PSS_PARAMS *pss;
+ X509_ALGOR *maskHash;
+
+ pss = rsa_pss_decode(sigalg, &maskHash);
+ rv = rsa_pss_param_print(bp, pss, maskHash, indent);
+ if (pss) {
+ RSA_PSS_PARAMS_free(pss);
+ }
+ if (maskHash) {
+ X509_ALGOR_free(maskHash);
+ }
+ 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 old_rsa_priv_decode(EVP_PKEY *pkey, const unsigned char **pder,
+ int derlen) {
+ RSA *rsa = d2i_RSAPrivateKey(NULL, pder, derlen);
+ if (rsa == NULL) {
+ OPENSSL_PUT_ERROR(EVP, old_rsa_priv_decode, ERR_R_RSA_LIB);
+ return 0;
+ }
+ EVP_PKEY_assign_RSA(pkey, rsa);
+ return 1;
+}
+
+static int old_rsa_priv_encode(const EVP_PKEY *pkey, unsigned char **pder) {
+ return i2d_RSAPrivateKey(pkey->pkey.rsa, pder);
+}
+
+/* allocate and set algorithm ID from EVP_MD, default SHA1 */
+static int rsa_md_to_algor(X509_ALGOR **palg, const EVP_MD *md) {
+ if (EVP_MD_type(md) == NID_sha1) {
+ return 1;
+ }
+ *palg = X509_ALGOR_new();
+ if (!*palg) {
+ 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 (EVP_MD_type(mgf1md) == NID_sha1) {
+ return 1;
+ }
+ /* need to embed algorithm ID inside another */
+ if (!rsa_md_to_algor(&algtmp, mgf1md) ||
+ !ASN1_item_pack(algtmp, ASN1_ITEM_rptr(X509_ALGOR), &stmp)) {
+ goto err;
+ }
+ *palg = X509_ALGOR_new();
+ if (!*palg) {
+ goto err;
+ }
+ X509_ALGOR_set0(*palg, OBJ_nid2obj(NID_mgf1), V_ASN1_SEQUENCE, stmp);
+ stmp = NULL;
+
+err:
+ if (stmp)
+ ASN1_STRING_free(stmp);
+ if (algtmp)
+ X509_ALGOR_free(algtmp);
+ if (*palg)
+ return 1;
+
+ return 0;
+}
+
+/* convert algorithm ID to EVP_MD, default SHA1 */
+static const EVP_MD *rsa_algor_to_md(X509_ALGOR *alg) {
+ const EVP_MD *md;
+ if (!alg) {
+ return EVP_sha1();
+ }
+ md = EVP_get_digestbyobj(alg->algorithm);
+ if (md == NULL) {
+ OPENSSL_PUT_ERROR(EVP, rsa_algor_to_md, EVP_R_UNKNOWN_DIGEST);
+ }
+ return md;
+}
+
+/* convert MGF1 algorithm ID to EVP_MD, default SHA1 */
+static const EVP_MD *rsa_mgf1_to_md(X509_ALGOR *alg, X509_ALGOR *maskHash) {
+ const EVP_MD *md;
+ if (!alg) {
+ return EVP_sha1();
+ }
+ /* Check mask and lookup mask hash algorithm */
+ if (OBJ_obj2nid(alg->algorithm) != NID_mgf1) {
+ OPENSSL_PUT_ERROR(EVP, rsa_mgf1_to_md, EVP_R_UNSUPPORTED_MASK_ALGORITHM);
+ return NULL;
+ }
+ if (!maskHash) {
+ OPENSSL_PUT_ERROR(EVP, rsa_mgf1_to_md, EVP_R_UNSUPPORTED_MASK_PARAMETER);
+ return NULL;
+ }
+ md = EVP_get_digestbyobj(maskHash->algorithm);
+ if (md == NULL) {
+ OPENSSL_PUT_ERROR(EVP, rsa_mgf1_to_md, EVP_R_UNKNOWN_MASK_DIGEST);
+ return NULL;
+ }
+ return md;
+}
+
+/* rsa_ctx_to_pss converts EVP_PKEY_CTX in PSS mode into corresponding
+ * algorithm parameter, suitable for setting as an AlgorithmIdentifier. */
+static ASN1_STRING *rsa_ctx_to_pss(EVP_PKEY_CTX *pkctx) {
+ const EVP_MD *sigmd, *mgf1md;
+ RSA_PSS_PARAMS *pss = NULL;
+ ASN1_STRING *os = NULL;
+ EVP_PKEY *pk = EVP_PKEY_CTX_get0_pkey(pkctx);
+ int saltlen, rv = 0;
+
+ if (EVP_PKEY_CTX_get_signature_md(pkctx, &sigmd) <= 0 ||
+ EVP_PKEY_CTX_get_rsa_mgf1_md(pkctx, &mgf1md) <= 0 ||
+ !EVP_PKEY_CTX_get_rsa_pss_saltlen(pkctx, &saltlen)) {
+ goto err;
+ }
+
+ if (saltlen == -1) {
+ saltlen = EVP_MD_size(sigmd);
+ } else if (saltlen == -2) {
+ saltlen = EVP_PKEY_size(pk) - EVP_MD_size(sigmd) - 2;
+ if (((EVP_PKEY_bits(pk) - 1) & 0x7) == 0) {
+ saltlen--;
+ }
+ } else {
+ goto err;
+ }
+
+ pss = RSA_PSS_PARAMS_new();
+ if (!pss) {
+ goto err;
+ }
+
+ if (saltlen != 20) {
+ pss->saltLength = ASN1_INTEGER_new();
+ if (!pss->saltLength ||
+ !ASN1_INTEGER_set(pss->saltLength, saltlen)) {
+ goto err;
+ }
+ }
+
+ if (!rsa_md_to_algor(&pss->hashAlgorithm, sigmd) ||
+ !rsa_md_to_mgf1(&pss->maskGenAlgorithm, mgf1md)) {
+ goto err;
+ }
+
+ /* Finally create string with pss parameter encoding. */
+ if (!ASN1_item_pack(pss, ASN1_ITEM_rptr(RSA_PSS_PARAMS), &os)) {
+ goto err;
+ }
+ rv = 1;
+
+err:
+ if (pss)
+ RSA_PSS_PARAMS_free(pss);
+ if (rv)
+ return os;
+ if (os)
+ ASN1_STRING_free(os);
+ return NULL;
+}
+
+/* From PSS AlgorithmIdentifier set public key parameters. */
+static int rsa_pss_to_ctx(EVP_MD_CTX *ctx, X509_ALGOR *sigalg, EVP_PKEY *pkey) {
+ int ret = 0;
+ int saltlen;
+ const EVP_MD *mgf1md = NULL, *md = NULL;
+ RSA_PSS_PARAMS *pss;
+ X509_ALGOR *maskHash;
+ EVP_PKEY_CTX *pkctx;
+
+ /* Sanity check: make sure it is PSS */
+ if (OBJ_obj2nid(sigalg->algorithm) != NID_rsassaPss) {
+ OPENSSL_PUT_ERROR(EVP, rsa_pss_to_ctx, EVP_R_UNSUPPORTED_SIGNATURE_TYPE);
+ return 0;
+ }
+ /* Decode PSS parameters */
+ pss = rsa_pss_decode(sigalg, &maskHash);
+ if (pss == NULL) {
+ OPENSSL_PUT_ERROR(EVP, rsa_pss_to_ctx, EVP_R_INVALID_PSS_PARAMETERS);
+ goto err;
+ }
+
+ mgf1md = rsa_mgf1_to_md(pss->maskGenAlgorithm, maskHash);
+ if (!mgf1md) {
+ goto err;
+ }
+ md = rsa_algor_to_md(pss->hashAlgorithm);
+ if (!md) {
+ goto err;
+ }
+
+ saltlen = 20;
+ if (pss->saltLength) {
+ saltlen = ASN1_INTEGER_get(pss->saltLength);
+
+ /* Could perform more salt length sanity checks but the main
+ * RSA routines will trap other invalid values anyway. */
+ if (saltlen < 0) {
+ OPENSSL_PUT_ERROR(EVP, rsa_pss_to_ctx, EVP_R_INVALID_SALT_LENGTH);
+ goto err;
+ }
+ }
+
+ /* 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) {
+ OPENSSL_PUT_ERROR(EVP, rsa_pss_to_ctx, EVP_R_INVALID_TRAILER);
+ goto err;
+ }
+
+ if (!EVP_DigestVerifyInit(ctx, &pkctx, md, NULL, pkey) ||
+ EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_PSS_PADDING) <= 0 ||
+ EVP_PKEY_CTX_set_rsa_pss_saltlen(pkctx, saltlen) <= 0 ||
+ EVP_PKEY_CTX_set_rsa_mgf1_md(pkctx, mgf1md) <= 0) {
+ goto err;
+ }
+
+ ret = 1;
+
+err:
+ RSA_PSS_PARAMS_free(pss);
+ if (maskHash) {
+ X509_ALGOR_free(maskHash);
+ }
+ return ret;
+}
+
+/* Customised RSA AlgorithmIdentifier handling. This is called when a signature
+ * is encountered requiring special handling. We currently only handle PSS. */
+static int rsa_digest_verify_init_from_algorithm(EVP_MD_CTX *ctx,
+ X509_ALGOR *sigalg,
+ EVP_PKEY *pkey) {
+ /* Sanity check: make sure it is PSS */
+ if (OBJ_obj2nid(sigalg->algorithm) != NID_rsassaPss) {
+ OPENSSL_PUT_ERROR(EVP, rsa_digest_verify_init_from_algorithm,
+ EVP_R_UNSUPPORTED_SIGNATURE_TYPE);
+ return 0;
+ }
+ return rsa_pss_to_ctx(ctx, sigalg, pkey);
+}
+
+static evp_digest_sign_algorithm_result_t rsa_digest_sign_algorithm(
+ EVP_MD_CTX *ctx, X509_ALGOR *sigalg) {
+ int pad_mode;
+ EVP_PKEY_CTX *pkctx = ctx->pctx;
+ if (EVP_PKEY_CTX_get_rsa_padding(pkctx, &pad_mode) <= 0) {
+ return EVP_DIGEST_SIGN_ALGORITHM_ERROR;
+ }
+ if (pad_mode == RSA_PKCS1_PSS_PADDING) {
+ ASN1_STRING *os1 = rsa_ctx_to_pss(pkctx);
+ if (!os1) {
+ return EVP_DIGEST_SIGN_ALGORITHM_ERROR;
+ }
+ X509_ALGOR_set0(sigalg, OBJ_nid2obj(NID_rsassaPss), V_ASN1_SEQUENCE, os1);
+ return EVP_DIGEST_SIGN_ALGORITHM_SUCCESS;
+ }
+
+ /* Other padding schemes use the default behavior. */
+ return EVP_DIGEST_SIGN_ALGORITHM_DEFAULT;
+}
+
+const EVP_PKEY_ASN1_METHOD rsa_asn1_meth = {
+ EVP_PKEY_RSA,
+ EVP_PKEY_RSA,
+ ASN1_PKEY_SIGPARAM_NULL,
+
+ "RSA",
+ "OpenSSL RSA method",
+
+ rsa_pub_decode,
+ rsa_pub_encode,
+ rsa_pub_cmp,
+ rsa_pub_print,
+
+ rsa_priv_decode,
+ rsa_priv_encode,
+ rsa_priv_print,
+
+ rsa_opaque,
+ rsa_supports_digest,
+
+ int_rsa_size,
+ rsa_bits,
+
+ 0,0,0,0,0,0,
+
+ rsa_sig_print,
+ int_rsa_free,
+
+ old_rsa_priv_decode,
+ old_rsa_priv_encode,
+
+ rsa_digest_verify_init_from_algorithm,
+ rsa_digest_sign_algorithm,
+};
diff --git a/src/crypto/evp/pbkdf.c b/src/crypto/evp/pbkdf.c
new file mode 100644
index 0000000..be6ed86
--- /dev/null
+++ b/src/crypto/evp/pbkdf.c
@@ -0,0 +1,135 @@
+/* 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 <openssl/evp.h>
+
+#include <string.h>
+
+#include <openssl/hmac.h>
+
+
+int PKCS5_PBKDF2_HMAC(const char *password, size_t password_len,
+ const uint8_t *salt, size_t salt_len, unsigned iterations,
+ const EVP_MD *digest, size_t key_len, uint8_t *out_key) {
+ uint8_t digest_tmp[EVP_MAX_MD_SIZE], *p, itmp[4];
+ size_t cplen, mdlen, tkeylen, k;
+ unsigned j;
+ uint32_t i = 1;
+ HMAC_CTX hctx_tpl, hctx;
+
+ mdlen = EVP_MD_size(digest);
+ HMAC_CTX_init(&hctx_tpl);
+ p = out_key;
+ tkeylen = key_len;
+ if (!HMAC_Init_ex(&hctx_tpl, password, password_len, 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] = (uint8_t)((i >> 24) & 0xff);
+ itmp[1] = (uint8_t)((i >> 16) & 0xff);
+ itmp[2] = (uint8_t)((i >> 8) & 0xff);
+ itmp[3] = (uint8_t)(i & 0xff);
+ if (!HMAC_CTX_copy(&hctx, &hctx_tpl)) {
+ HMAC_CTX_cleanup(&hctx_tpl);
+ return 0;
+ }
+ if (!HMAC_Update(&hctx, salt, salt_len) ||
+ !HMAC_Update(&hctx, itmp, 4) ||
+ !HMAC_Final(&hctx, digest_tmp, NULL)) {
+ HMAC_CTX_cleanup(&hctx_tpl);
+ HMAC_CTX_cleanup(&hctx);
+ return 0;
+ }
+ HMAC_CTX_cleanup(&hctx);
+ memcpy(p, digest_tmp, cplen);
+ for (j = 1; j < iterations; j++) {
+ if (!HMAC_CTX_copy(&hctx, &hctx_tpl)) {
+ HMAC_CTX_cleanup(&hctx_tpl);
+ return 0;
+ }
+ if (!HMAC_Update(&hctx, digest_tmp, mdlen) ||
+ !HMAC_Final(&hctx, digest_tmp, NULL)) {
+ HMAC_CTX_cleanup(&hctx_tpl);
+ HMAC_CTX_cleanup(&hctx);
+ return 0;
+ }
+ HMAC_CTX_cleanup(&hctx);
+ for (k = 0; k < cplen; k++) {
+ p[k] ^= digest_tmp[k];
+ }
+ }
+ tkeylen -= cplen;
+ i++;
+ p += cplen;
+ }
+ HMAC_CTX_cleanup(&hctx_tpl);
+ return 1;
+}
+
+int PKCS5_PBKDF2_HMAC_SHA1(const char *password, size_t password_len,
+ const uint8_t *salt, size_t salt_len,
+ unsigned iterations, size_t key_len,
+ uint8_t *out_key) {
+ return PKCS5_PBKDF2_HMAC(password, password_len, salt, salt_len, iterations,
+ EVP_sha1(), key_len, out_key);
+}
diff --git a/src/crypto/evp/sign.c b/src/crypto/evp/sign.c
new file mode 100644
index 0000000..1faf7c6
--- /dev/null
+++ b/src/crypto/evp/sign.c
@@ -0,0 +1,151 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/evp.h>
+
+#include <openssl/digest.h>
+#include <openssl/err.h>
+
+#include "internal.h"
+
+
+int EVP_SignInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl) {
+ return EVP_DigestInit_ex(ctx, type, impl);
+}
+
+int EVP_SignInit(EVP_MD_CTX *ctx, const EVP_MD *type) {
+ return EVP_DigestInit(ctx, type);
+}
+
+int EVP_SignUpdate(EVP_MD_CTX *ctx, const void *data, size_t len) {
+ return EVP_DigestUpdate(ctx, data, len);
+}
+
+int EVP_SignFinal(const EVP_MD_CTX *ctx, uint8_t *sig,
+ unsigned int *out_sig_len, EVP_PKEY *pkey) {
+ uint8_t m[EVP_MAX_MD_SIZE];
+ unsigned int m_len;
+ int ret = 0;
+ EVP_MD_CTX tmp_ctx;
+ EVP_PKEY_CTX *pkctx = NULL;
+ size_t sig_len = EVP_PKEY_size(pkey);
+
+ *out_sig_len = 0;
+ EVP_MD_CTX_init(&tmp_ctx);
+ if (!EVP_MD_CTX_copy_ex(&tmp_ctx, ctx) ||
+ !EVP_DigestFinal_ex(&tmp_ctx, m, &m_len)) {
+ goto out;
+ }
+ EVP_MD_CTX_cleanup(&tmp_ctx);
+
+ pkctx = EVP_PKEY_CTX_new(pkey, NULL);
+ if (!pkctx || EVP_PKEY_sign_init(pkctx) <= 0 ||
+ EVP_PKEY_CTX_set_signature_md(pkctx, ctx->digest) <= 0 ||
+ EVP_PKEY_sign(pkctx, sig, &sig_len, m, m_len) <= 0) {
+ goto out;
+ }
+ *out_sig_len = sig_len;
+ ret = 1;
+
+out:
+ if (pkctx) {
+ EVP_PKEY_CTX_free(pkctx);
+ }
+
+ return ret;
+}
+
+int EVP_VerifyInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl) {
+ return EVP_DigestInit_ex(ctx, type, impl);
+}
+
+int EVP_VerifyInit(EVP_MD_CTX *ctx, const EVP_MD *type) {
+ return EVP_DigestInit(ctx, type);
+}
+
+int EVP_VerifyUpdate(EVP_MD_CTX *ctx, const void *data, size_t len) {
+ return EVP_DigestUpdate(ctx, data, len);
+}
+
+int EVP_VerifyFinal(EVP_MD_CTX *ctx, const uint8_t *sig, size_t sig_len,
+ EVP_PKEY *pkey) {
+ uint8_t m[EVP_MAX_MD_SIZE];
+ unsigned int m_len;
+ int ret = 0;
+ EVP_MD_CTX tmp_ctx;
+ EVP_PKEY_CTX *pkctx = NULL;
+
+ EVP_MD_CTX_init(&tmp_ctx);
+ if (!EVP_MD_CTX_copy_ex(&tmp_ctx, ctx) ||
+ !EVP_DigestFinal_ex(&tmp_ctx, m, &m_len)) {
+ EVP_MD_CTX_cleanup(&tmp_ctx);
+ goto out;
+ }
+ EVP_MD_CTX_cleanup(&tmp_ctx);
+
+ pkctx = EVP_PKEY_CTX_new(pkey, NULL);
+ if (!pkctx ||
+ EVP_PKEY_verify_init(pkctx) <= 0 ||
+ EVP_PKEY_CTX_set_signature_md(pkctx, ctx->digest) <= 0) {
+ goto out;
+ }
+ ret = EVP_PKEY_verify(pkctx, sig, sig_len, m, m_len);
+
+out:
+ EVP_PKEY_CTX_free(pkctx);
+ return ret;
+}
+
diff --git a/src/crypto/ex_data.c b/src/crypto/ex_data.c
new file mode 100644
index 0000000..0c2503e
--- /dev/null
+++ b/src/crypto/ex_data.c
@@ -0,0 +1,227 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/ex_data.h>
+
+#include <openssl/err.h>
+#include <openssl/thread.h>
+
+#include "crypto_error.h"
+#include "internal.h"
+
+
+/* global_impl is the implementation that we use at runtime. */
+static const CRYPTO_EX_DATA_IMPL *global_impl = NULL;
+
+/* ex_data_default_impl is a the default implementation, defined in
+ * ex_data_impl.c. */
+extern const CRYPTO_EX_DATA_IMPL ex_data_default_impl;
+
+/* get_impl returns the current ex_data implementatation. */
+static const CRYPTO_EX_DATA_IMPL *get_impl(void) {
+ const CRYPTO_EX_DATA_IMPL *impl;
+
+ CRYPTO_r_lock(CRYPTO_LOCK_EX_DATA);
+ impl = global_impl;
+ CRYPTO_r_unlock(CRYPTO_LOCK_EX_DATA);
+
+ if (impl != NULL) {
+ return impl;
+ }
+
+ CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA);
+ if (global_impl == NULL) {
+ global_impl = &ex_data_default_impl;
+ }
+ impl = global_impl;
+ CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA);
+ return impl;
+}
+
+int CRYPTO_get_ex_new_index(int class_value, long argl, void *argp,
+ CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func,
+ CRYPTO_EX_free *free_func) {
+ const CRYPTO_EX_DATA_IMPL *const impl = get_impl();
+ return impl->get_new_index(class_value, argl, argp, new_func, dup_func,
+ free_func);
+}
+
+int CRYPTO_set_ex_data(CRYPTO_EX_DATA *ad, int index, void *val) {
+ int n, i;
+
+ if (ad->sk == NULL) {
+ ad->sk = sk_void_new_null();
+ if (ad->sk == NULL) {
+ OPENSSL_PUT_ERROR(CRYPTO, CRYPTO_set_ex_data, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ }
+
+ n = sk_void_num(ad->sk);
+
+ /* Add NULL values until the stack is long enough. */
+ for (i = n; i <= index; i++) {
+ if (!sk_void_push(ad->sk, NULL)) {
+ OPENSSL_PUT_ERROR(CRYPTO, CRYPTO_set_ex_data, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ }
+
+ sk_void_set(ad->sk, index, val);
+ return 1;
+}
+
+void *CRYPTO_get_ex_data(const CRYPTO_EX_DATA *ad, int idx) {
+ if (ad->sk == NULL || idx < 0 || (size_t)idx >= sk_void_num(ad->sk)) {
+ return NULL;
+ }
+ return sk_void_value(ad->sk, idx);
+}
+
+int CRYPTO_ex_data_new_class(void) {
+ const CRYPTO_EX_DATA_IMPL *const impl = get_impl();
+ return impl->new_class();
+}
+
+int CRYPTO_new_ex_data(int class_value, void *obj, CRYPTO_EX_DATA *ad) {
+ const CRYPTO_EX_DATA_IMPL *const impl = get_impl();
+ return impl->new_ex_data(class_value, obj, ad);
+}
+
+int CRYPTO_dup_ex_data(int class_value, CRYPTO_EX_DATA *to,
+ const CRYPTO_EX_DATA *from) {
+ const CRYPTO_EX_DATA_IMPL *const impl = get_impl();
+ return impl->dup_ex_data(class_value, to, from);
+}
+
+void CRYPTO_free_ex_data(int class_value, void *obj, CRYPTO_EX_DATA *ad) {
+ const CRYPTO_EX_DATA_IMPL *const impl = get_impl();
+ impl->free_ex_data(class_value, obj, ad);
+}
+
+const CRYPTO_EX_DATA_IMPL *CRYPTO_get_ex_data_implementation(void) {
+ return get_impl();
+}
+
+int CRYPTO_set_ex_data_implementation(const CRYPTO_EX_DATA_IMPL *impl) {
+ int ret = 0;
+
+ CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA);
+ if (global_impl == NULL) {
+ ret = 1;
+ global_impl = impl;
+ }
+ CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA);
+
+ return ret;
+}
+
+void CRYPTO_cleanup_all_ex_data(void) {
+ const CRYPTO_EX_DATA_IMPL *const impl = get_impl();
+ impl->cleanup();
+}
diff --git a/src/crypto/ex_data_impl.c b/src/crypto/ex_data_impl.c
new file mode 100644
index 0000000..f55b369
--- /dev/null
+++ b/src/crypto/ex_data_impl.c
@@ -0,0 +1,401 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/ex_data.h>
+
+#include <assert.h>
+
+#include <openssl/err.h>
+#include <openssl/lhash.h>
+#include <openssl/mem.h>
+#include <openssl/stack.h>
+#include <openssl/thread.h>
+
+#include "crypto_error.h"
+#include "internal.h"
+
+typedef struct crypto_ex_data_func_st {
+ long argl; /* Arbitary long */
+ void *argp; /* Arbitary void pointer */
+ CRYPTO_EX_new *new_func;
+ CRYPTO_EX_free *free_func;
+ CRYPTO_EX_dup *dup_func;
+} CRYPTO_EX_DATA_FUNCS;
+
+typedef struct st_ex_class_item {
+ STACK_OF(CRYPTO_EX_DATA_FUNCS) *meth;
+ int class_value;
+} EX_CLASS_ITEM;
+
+static LHASH_OF(EX_CLASS_ITEM) *global_classes = NULL;
+
+static int global_next_class = 100;
+
+static int new_class(void) {
+ int ret;
+ CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA);
+ ret = global_next_class++;
+ CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA);
+
+ return ret;
+}
+
+/* class_hash is a hash function used by an LHASH of |EX_CLASS_ITEM|
+ * structures. */
+static uint32_t class_hash(const EX_CLASS_ITEM *a) {
+ return a->class_value;
+}
+
+/* class_cmp is a comparison function for an LHASH of |EX_CLASS_ITEM|
+ * structures. */
+static int class_cmp(const EX_CLASS_ITEM *a, const EX_CLASS_ITEM *b) {
+ return a->class_value - b->class_value;
+}
+
+/* data_funcs_free is a callback function from |sk_pop_free| that frees a
+ * |CRYPTO_EX_DATA_FUNCS|. */
+static void data_funcs_free(CRYPTO_EX_DATA_FUNCS *funcs) {
+ OPENSSL_free(funcs);
+}
+
+/* class_free is a callback function from lh_doall to free the EX_CLASS_ITEM
+ * structures. */
+static void class_free(EX_CLASS_ITEM *item) {
+ sk_CRYPTO_EX_DATA_FUNCS_pop_free(item->meth, data_funcs_free);
+ OPENSSL_free(item);
+}
+
+static LHASH_OF(EX_CLASS_ITEM) *get_classes(void) {
+ LHASH_OF(EX_CLASS_ITEM) *ret;
+
+ CRYPTO_r_lock(CRYPTO_LOCK_EX_DATA);
+ ret = global_classes;
+ CRYPTO_r_unlock(CRYPTO_LOCK_EX_DATA);
+
+ if (ret != NULL) {
+ return ret;
+ }
+
+ CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA);
+ if (global_classes == NULL) {
+ global_classes = lh_EX_CLASS_ITEM_new(class_hash, class_cmp);
+ }
+ ret = global_classes;
+ CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA);
+
+ return ret;
+}
+
+static void cleanup(void) {
+ LHASH_OF(EX_CLASS_ITEM) *classes = get_classes();
+
+ if (classes != NULL) {
+ lh_EX_CLASS_ITEM_doall(classes, class_free);
+ lh_EX_CLASS_ITEM_free(classes);
+ }
+
+ global_classes = NULL;
+}
+
+static EX_CLASS_ITEM *get_class(int class_value) {
+ LHASH_OF(EX_CLASS_ITEM) *const classes = get_classes();
+ EX_CLASS_ITEM template, *class_item;
+ int ok = 0;
+
+ if (classes == NULL) {
+ return NULL;
+ }
+
+ CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA);
+ template.class_value = class_value;
+ class_item = lh_EX_CLASS_ITEM_retrieve(classes, &template);
+ if (class_item != NULL) {
+ ok = 1;
+ } else {
+ class_item = OPENSSL_malloc(sizeof(EX_CLASS_ITEM));
+ if (class_item) {
+ class_item->class_value = class_value;
+ class_item->meth = sk_CRYPTO_EX_DATA_FUNCS_new_null();
+ if (class_item->meth != NULL) {
+ EX_CLASS_ITEM *old_data;
+ ok = lh_EX_CLASS_ITEM_insert(classes, &old_data, class_item);
+ assert(old_data == NULL);
+ }
+ }
+ }
+ CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA);
+
+ if (!ok) {
+ if (class_item) {
+ if (class_item->meth) {
+ sk_CRYPTO_EX_DATA_FUNCS_free(class_item->meth);
+ }
+ OPENSSL_free(class_item);
+ class_item = NULL;
+ }
+
+ OPENSSL_PUT_ERROR(CRYPTO, get_class, ERR_R_MALLOC_FAILURE);
+ }
+
+ return class_item;
+}
+
+static int get_new_index(int class_value, long argl, void *argp,
+ CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func,
+ CRYPTO_EX_free *free_func) {
+ EX_CLASS_ITEM *const item = get_class(class_value);
+ CRYPTO_EX_DATA_FUNCS *funcs;
+ int ret = -1;
+
+ if (!item) {
+ return -1;
+ }
+
+ funcs = OPENSSL_malloc(sizeof(CRYPTO_EX_DATA_FUNCS));
+ if (funcs == NULL) {
+ OPENSSL_PUT_ERROR(CRYPTO, get_new_index, ERR_R_MALLOC_FAILURE);
+ return -1;
+ }
+
+ funcs->argl = argl;
+ funcs->argp = argp;
+ funcs->new_func = new_func;
+ funcs->dup_func = dup_func;
+ funcs->free_func = free_func;
+
+ CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA);
+
+ if (!sk_CRYPTO_EX_DATA_FUNCS_push(item->meth, funcs)) {
+ OPENSSL_PUT_ERROR(CRYPTO, get_new_index, ERR_R_MALLOC_FAILURE);
+ OPENSSL_free(funcs);
+ goto err;
+ }
+
+ ret = sk_CRYPTO_EX_DATA_FUNCS_num(item->meth) - 1;
+
+err:
+ CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA);
+ return ret;
+}
+
+/* get_func_pointers takes a copy of the CRYPTO_EX_DATA_FUNCS pointers, if any,
+ * for the given class. If there are some pointers, it sets |*out| to point to
+ * a fresh stack of them. Otherwise it sets |*out| to NULL. It returns one on
+ * success or zero on error. */
+static int get_func_pointers(STACK_OF(CRYPTO_EX_DATA_FUNCS) **out,
+ int class_value) {
+ EX_CLASS_ITEM *const item = get_class(class_value);
+ size_t n;
+
+ if (!item) {
+ return 0;
+ }
+
+ *out = NULL;
+
+ /* CRYPTO_EX_DATA_FUNCS structures are static once set, so we can take a
+ * shallow copy of the list under lock and then use the structures without
+ * the lock held. */
+ CRYPTO_r_lock(CRYPTO_LOCK_EX_DATA);
+ n = sk_CRYPTO_EX_DATA_FUNCS_num(item->meth);
+ if (n > 0) {
+ *out = sk_CRYPTO_EX_DATA_FUNCS_dup(item->meth);
+ }
+ CRYPTO_r_unlock(CRYPTO_LOCK_EX_DATA);
+
+ if (n > 0 && *out == NULL) {
+ OPENSSL_PUT_ERROR(CRYPTO, get_func_pointers, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ return 1;
+}
+
+static int new_ex_data(int class_value, void *obj, CRYPTO_EX_DATA *ad) {
+ STACK_OF(CRYPTO_EX_DATA_FUNCS) *func_pointers;
+ size_t i;
+
+ ad->sk = NULL;
+
+ if (!get_func_pointers(&func_pointers, class_value)) {
+ return 0;
+ }
+
+ for (i = 0; i < sk_CRYPTO_EX_DATA_FUNCS_num(func_pointers); i++) {
+ CRYPTO_EX_DATA_FUNCS *func_pointer =
+ sk_CRYPTO_EX_DATA_FUNCS_value(func_pointers, i);
+ if (func_pointer->new_func) {
+ func_pointer->new_func(obj, NULL, ad, i, func_pointer->argl,
+ func_pointer->argp);
+ }
+ }
+
+ sk_CRYPTO_EX_DATA_FUNCS_free(func_pointers);
+
+ return 1;
+}
+
+static int dup_ex_data(int class_value, CRYPTO_EX_DATA *to,
+ const CRYPTO_EX_DATA *from) {
+ STACK_OF(CRYPTO_EX_DATA_FUNCS) *func_pointers;
+ size_t i;
+
+ if (!from->sk) {
+ /* In this case, |from| is blank, which is also the initial state of |to|,
+ * so there's nothing to do. */
+ return 1;
+ }
+
+ if (!get_func_pointers(&func_pointers, class_value)) {
+ return 0;
+ }
+
+ for (i = 0; i < sk_CRYPTO_EX_DATA_FUNCS_num(func_pointers); i++) {
+ CRYPTO_EX_DATA_FUNCS *func_pointer =
+ sk_CRYPTO_EX_DATA_FUNCS_value(func_pointers, i);
+ void *ptr = CRYPTO_get_ex_data(from, i);
+ if (func_pointer->dup_func) {
+ func_pointer->dup_func(to, from, &ptr, i, func_pointer->argl,
+ func_pointer->argp);
+ }
+ CRYPTO_set_ex_data(to, i, ptr);
+ }
+
+ sk_CRYPTO_EX_DATA_FUNCS_free(func_pointers);
+
+ return 1;
+}
+
+static void free_ex_data(int class_value, void *obj, CRYPTO_EX_DATA *ad) {
+ STACK_OF(CRYPTO_EX_DATA_FUNCS) *func_pointers;
+ size_t i;
+
+ if (!get_func_pointers(&func_pointers, class_value)) {
+ return;
+ }
+
+ for (i = 0; i < sk_CRYPTO_EX_DATA_FUNCS_num(func_pointers); i++) {
+ CRYPTO_EX_DATA_FUNCS *func_pointer =
+ sk_CRYPTO_EX_DATA_FUNCS_value(func_pointers, i);
+ if (func_pointer->free_func) {
+ void *ptr = CRYPTO_get_ex_data(ad, i);
+ func_pointer->free_func(obj, ptr, ad, i, func_pointer->argl,
+ func_pointer->argp);
+ }
+ }
+
+ sk_CRYPTO_EX_DATA_FUNCS_free(func_pointers);
+
+ if (ad->sk) {
+ sk_void_free(ad->sk);
+ ad->sk = NULL;
+ }
+}
+
+const CRYPTO_EX_DATA_IMPL ex_data_default_impl = {
+ new_class, cleanup, get_new_index, new_ex_data, dup_ex_data, free_ex_data};
diff --git a/src/crypto/header_removed.h b/src/crypto/header_removed.h
new file mode 100644
index 0000000..49ee31a
--- /dev/null
+++ b/src/crypto/header_removed.h
@@ -0,0 +1,17 @@
+/* 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. */
+
+/* This header is linked to under the names of several headers that have been
+ * removed. It's possible to put a #error in here in order to catch that an
+ * clean up older code. */
diff --git a/src/crypto/hkdf/CMakeLists.txt b/src/crypto/hkdf/CMakeLists.txt
new file mode 100644
index 0000000..9666172
--- /dev/null
+++ b/src/crypto/hkdf/CMakeLists.txt
@@ -0,0 +1,18 @@
+include_directories(. .. ../../include)
+
+add_library(
+ hkdf
+
+ OBJECT
+
+ hkdf.c
+ hkdf_error.c
+)
+
+add_executable(
+ hkdf_test
+
+ hkdf_test.c
+)
+
+target_link_libraries(hkdf_test crypto)
diff --git a/src/crypto/hkdf/hkdf.c b/src/crypto/hkdf/hkdf.c
new file mode 100644
index 0000000..bb7f5a4
--- /dev/null
+++ b/src/crypto/hkdf/hkdf.c
@@ -0,0 +1,89 @@
+/* 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 <openssl/hkdf.h>
+
+#include <assert.h>
+#include <string.h>
+
+#include <openssl/err.h>
+#include <openssl/hmac.h>
+
+
+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) {
+ /* https://tools.ietf.org/html/rfc5869#section-2.2 */
+ const size_t digest_len = EVP_MD_size(digest);
+ uint8_t prk[EVP_MAX_MD_SIZE], previous[EVP_MAX_MD_SIZE];
+ size_t n, done = 0;
+ unsigned i, prk_len;
+ int ret = 0;
+ HMAC_CTX hmac;
+
+ /* If salt is not given, HashLength zeros are used. However, HMAC does that
+ * internally already so we can ignore it.*/
+
+ /* Expand key material to desired length. */
+ n = (out_len + digest_len - 1) / digest_len;
+ if (out_len + digest_len < out_len || n > 255) {
+ OPENSSL_PUT_ERROR(HKDF, HKDF, HKDF_R_OUTPUT_TOO_LARGE);
+ return 0;
+ }
+
+ HMAC_CTX_init(&hmac);
+
+ /* Extract input keying material into pseudorandom key |prk|. */
+ if (HMAC(digest, salt, salt_len, secret, secret_len, prk, &prk_len) == NULL) {
+ goto out;
+ }
+ assert(prk_len == digest_len);
+
+ 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 (done + todo > out_len) {
+ todo = out_len - done;
+ }
+ memcpy(out_key + done, previous, todo);
+ done += todo;
+ }
+
+ ret = 1;
+
+out:
+ HMAC_CTX_cleanup(&hmac);
+ if (ret != 1) {
+ OPENSSL_PUT_ERROR(HKDF, HKDF, ERR_R_HMAC_LIB);
+ }
+ return ret;
+}
diff --git a/src/crypto/hkdf/hkdf_error.c b/src/crypto/hkdf/hkdf_error.c
new file mode 100644
index 0000000..e1928d6
--- /dev/null
+++ b/src/crypto/hkdf/hkdf_error.c
@@ -0,0 +1,23 @@
+/* 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 <openssl/err.h>
+
+#include <openssl/hkdf.h>
+
+const ERR_STRING_DATA HKDF_error_string_data[] = {
+ {ERR_PACK(ERR_LIB_HKDF, HKDF_F_HKDF, 0), "HKDF"},
+ {ERR_PACK(ERR_LIB_HKDF, 0, HKDF_R_OUTPUT_TOO_LARGE), "OUTPUT_TOO_LARGE"},
+ {0, NULL},
+};
diff --git a/src/crypto/hkdf/hkdf_test.c b/src/crypto/hkdf/hkdf_test.c
new file mode 100644
index 0000000..7467fe0
--- /dev/null
+++ b/src/crypto/hkdf/hkdf_test.c
@@ -0,0 +1,240 @@
+/* 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 <stdio.h>
+#include <string.h>
+
+#include <openssl/bio.h>
+#include <openssl/crypto.h>
+#include <openssl/digest.h>
+#include <openssl/err.h>
+#include <openssl/hkdf.h>
+
+
+typedef struct {
+ 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 size_t out_len;
+ const uint8_t out[82];
+} hkdf_test_vector_t;
+
+/* These test vectors are from RFC 5869. */
+static const hkdf_test_vector_t 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,
+ 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,
+ 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,
+ 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,
+ 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,
+ 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,
+ 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,
+ 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) {
+ uint8_t buf[82];
+ size_t i;
+
+ CRYPTO_library_init();
+ ERR_load_crypto_strings();
+
+ for (i = 0; i < sizeof(kTests) / sizeof(kTests[0]); i++) {
+ const hkdf_test_vector_t *test = &kTests[i];
+ 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");
+ BIO_print_errors_fp(stderr);
+ return 1;
+ }
+ if (memcmp(buf, test->out, test->out_len) != 0) {
+ fprintf(stderr, "%u: Resulting key material does not match test vector\n",
+ (unsigned)i);
+ return 1;
+ }
+ }
+
+ printf("PASS\n");
+ ERR_free_strings();
+ return 0;
+}
diff --git a/src/crypto/hmac/CMakeLists.txt b/src/crypto/hmac/CMakeLists.txt
new file mode 100644
index 0000000..e15c956
--- /dev/null
+++ b/src/crypto/hmac/CMakeLists.txt
@@ -0,0 +1,18 @@
+include_directories(. .. ../../include)
+
+add_library(
+ hmac
+
+ OBJECT
+
+ hmac.c
+)
+
+
+add_executable(
+ hmac_test
+
+ hmac_test.c
+)
+
+target_link_libraries(hmac_test crypto)
diff --git a/src/crypto/hmac/hmac.c b/src/crypto/hmac/hmac.c
new file mode 100644
index 0000000..f179fed
--- /dev/null
+++ b/src/crypto/hmac/hmac.c
@@ -0,0 +1,225 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/hmac.h>
+
+#include <assert.h>
+#include <string.h>
+
+#include <openssl/mem.h>
+
+
+uint8_t *HMAC(const EVP_MD *evp_md, const void *key, size_t key_len,
+ const uint8_t *data, size_t data_len, uint8_t *out,
+ unsigned int *out_len) {
+ HMAC_CTX ctx;
+ static uint8_t static_out_buffer[EVP_MAX_MD_SIZE];
+
+ /* OpenSSL has traditionally supported using a static buffer if |out| is
+ * NULL. We maintain that but don't document it. This behaviour should be
+ * considered to be deprecated. */
+ if (out == NULL) {
+ out = static_out_buffer;
+ }
+
+ HMAC_CTX_init(&ctx);
+ if (!HMAC_Init(&ctx, key, key_len, evp_md) ||
+ !HMAC_Update(&ctx, data, data_len) ||
+ !HMAC_Final(&ctx, out, out_len)) {
+ out = NULL;
+ }
+
+ HMAC_CTX_cleanup(&ctx);
+ return out;
+}
+
+void HMAC_CTX_init(HMAC_CTX *ctx) {
+ ctx->md = NULL;
+ ctx->key_length = 0;
+ EVP_MD_CTX_init(&ctx->i_ctx);
+ EVP_MD_CTX_init(&ctx->o_ctx);
+ EVP_MD_CTX_init(&ctx->md_ctx);
+}
+
+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);
+ OPENSSL_cleanse(ctx, sizeof(ctx));
+}
+
+int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, size_t key_len,
+ const EVP_MD *md, ENGINE *impl) {
+ unsigned i, reset = 0;
+ uint8_t pad[HMAC_MAX_MD_CBLOCK];
+
+ if (md != NULL) {
+ if (ctx->md == NULL && key == NULL && ctx->key_length == 0) {
+ /* TODO(eroman): Change the API instead of this hack.
+ * If a key hasn't yet been assigned to the context, then default to using
+ * an all-zero key. This is to work around callers of
+ * HMAC_Init_ex(key=NULL, key_len=0) intending to set a zero-length key.
+ * Rather than resulting in uninitialized memory reads, it will
+ * predictably use a zero key. */
+ memset(ctx->key, 0, sizeof(ctx->key));
+ }
+ reset = 1;
+ ctx->md = md;
+ } else {
+ md = ctx->md;
+ }
+
+ if (key != NULL) {
+ size_t block_size = EVP_MD_block_size(md);
+ reset = 1;
+ assert(block_size <= sizeof(ctx->key));
+ if (block_size < key_len) {
+ if (!EVP_DigestInit_ex(&ctx->md_ctx, md, impl) ||
+ !EVP_DigestUpdate(&ctx->md_ctx, key, key_len) ||
+ !EVP_DigestFinal_ex(&(ctx->md_ctx), ctx->key, &ctx->key_length)) {
+ goto err;
+ }
+ } else {
+ assert(key_len >= 0 && key_len <= sizeof(ctx->key));
+ memcpy(ctx->key, key, key_len);
+ ctx->key_length = key_len;
+ }
+ if (ctx->key_length != HMAC_MAX_MD_CBLOCK) {
+ memset(&ctx->key[ctx->key_length], 0, sizeof(ctx->key) - 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) ||
+ !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) ||
+ !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;
+}
+
+int HMAC_Update(HMAC_CTX *ctx, const uint8_t *data, size_t data_len) {
+ return EVP_DigestUpdate(&ctx->md_ctx, data, data_len);
+}
+
+int HMAC_Final(HMAC_CTX *ctx, uint8_t *out, unsigned int *out_len) {
+ unsigned int i;
+ uint8_t buf[EVP_MAX_MD_SIZE];
+
+ if (!EVP_DigestFinal_ex(&ctx->md_ctx, buf, &i) ||
+ !EVP_MD_CTX_copy_ex(&ctx->md_ctx, &ctx->o_ctx) ||
+ !EVP_DigestUpdate(&ctx->md_ctx, buf, i) ||
+ !EVP_DigestFinal_ex(&ctx->md_ctx, out, out_len)) {
+ *out_len = 0;
+ return 0;
+ }
+
+ return 1;
+}
+
+size_t HMAC_size(const HMAC_CTX *ctx) {
+ return EVP_MD_size(ctx->md);
+}
+
+int HMAC_CTX_copy_ex(HMAC_CTX *dest, const HMAC_CTX *src) {
+ if (!EVP_MD_CTX_copy_ex(&dest->i_ctx, &src->i_ctx) ||
+ !EVP_MD_CTX_copy_ex(&dest->o_ctx, &src->o_ctx) ||
+ !EVP_MD_CTX_copy_ex(&dest->md_ctx, &src->md_ctx)) {
+ return 0;
+ }
+
+ memcpy(dest->key, src->key, HMAC_MAX_MD_CBLOCK);
+ dest->key_length = src->key_length;
+ dest->md = src->md;
+ return 1;
+}
+
+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);
+}
+
+int HMAC_Init(HMAC_CTX *ctx, const void *key, int key_len, const EVP_MD *md) {
+ if (key && md) {
+ HMAC_CTX_init(ctx);
+ }
+ return HMAC_Init_ex(ctx, key, key_len, md, NULL);
+}
+
+int HMAC_CTX_copy(HMAC_CTX *dest, const HMAC_CTX *src) {
+ HMAC_CTX_init(dest);
+ return HMAC_CTX_copy_ex(dest, src);
+}
diff --git a/src/crypto/hmac/hmac_test.c b/src/crypto/hmac/hmac_test.c
new file mode 100644
index 0000000..ecc418a
--- /dev/null
+++ b/src/crypto/hmac/hmac_test.c
@@ -0,0 +1,223 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <assert.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <openssl/crypto.h>
+#include <openssl/digest.h>
+#include <openssl/hmac.h>
+
+
+struct test_st {
+ uint8_t key[16];
+ size_t key_len;
+ uint8_t data[64];
+ size_t data_len;
+ const char *hex_digest;
+};
+
+#define NUM_TESTS 4
+
+static const struct test_st kTests[NUM_TESTS] = {
+ {
+ "", 0, "More text test vectors to stuff up EBCDIC machines :-)", 54,
+ "e9139d1e6ee064ef8cf514fc7dc83e86",
+ },
+ {
+ {
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b, 0x0b,
+ },
+ 16,
+ "Hi There",
+ 8,
+ "9294727a3638bb1c13f48ef8158bfc9d",
+ },
+ {
+ "Jefe", 4, "what do ya want for nothing?", 28,
+ "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,
+ "56be34521d144c88dbb8c733f0e8b3f6",
+ },
+};
+
+static char *to_hex(const uint8_t *md, size_t md_len) {
+ size_t i;
+ static char buf[80];
+
+ for (i = 0; i < md_len; i++) {
+ sprintf(&(buf[i * 2]), "%02x", md[i]);
+ }
+ return buf;
+}
+
+int main(int argc, char *argv[]) {
+ unsigned i;
+ char *p;
+ int err = 0;
+ uint8_t out[EVP_MAX_MD_SIZE];
+ unsigned out_len;
+
+ CRYPTO_library_init();
+
+ for (i = 0; i < NUM_TESTS; i++) {
+ const struct test_st *test = &kTests[i];
+
+ /* Test using the one-shot API. */
+ if (NULL == HMAC(EVP_md5(), test->key, test->key_len, test->data,
+ test->data_len, out, &out_len)) {
+ fprintf(stderr, "%u: HMAC failed.\n", i);
+ err++;
+ continue;
+ }
+ p = to_hex(out, out_len);
+ if (strcmp(p, test->hex_digest) != 0) {
+ fprintf(stderr, "%u: got %s instead of %s\n", i, p, test->hex_digest);
+ err++;
+ }
+
+ /* Test using HMAC_CTX. */
+ HMAC_CTX ctx;
+ HMAC_CTX_init(&ctx);
+ if (!HMAC_Init_ex(&ctx, test->key, test->key_len, EVP_md5(), NULL) ||
+ !HMAC_Update(&ctx, test->data, test->data_len) ||
+ !HMAC_Final(&ctx, out, &out_len)) {
+ fprintf(stderr, "%u: HMAC failed.\n", i);
+ err++;
+ HMAC_CTX_cleanup(&ctx);
+ continue;
+ }
+ p = to_hex(out, out_len);
+ if (strcmp(p, test->hex_digest) != 0) {
+ fprintf(stderr, "%u: got %s instead of %s\n", i, p, test->hex_digest);
+ err++;
+ }
+
+ /* Test that an HMAC_CTX may be reset with the same key. */
+ if (!HMAC_Init_ex(&ctx, NULL, 0, EVP_md5(), NULL) ||
+ !HMAC_Update(&ctx, test->data, test->data_len) ||
+ !HMAC_Final(&ctx, out, &out_len)) {
+ fprintf(stderr, "%u: HMAC failed.\n", i);
+ err++;
+ HMAC_CTX_cleanup(&ctx);
+ continue;
+ }
+ p = to_hex(out, out_len);
+ if (strcmp(p, test->hex_digest) != 0) {
+ fprintf(stderr, "%u: got %s instead of %s\n", i, p, test->hex_digest);
+ err++;
+ }
+
+ HMAC_CTX_cleanup(&ctx);
+ }
+
+ /* Test that HMAC() uses the empty key when called with key = NULL. */
+ const struct test_st *test = &kTests[0];
+ assert(test->key_len == 0);
+ if (NULL == HMAC(EVP_md5(), NULL, 0, test->data, test->data_len, out,
+ &out_len)) {
+ fprintf(stderr, "HMAC failed.\n");
+ err++;
+ } else {
+ p = to_hex(out, out_len);
+ if (strcmp(p, test->hex_digest) != 0) {
+ fprintf(stderr, "got %s instead of %s\n", p, test->hex_digest);
+ err++;
+ }
+ }
+
+ /* Test that HMAC_Init, etc., uses the empty key when called initially with
+ * key = NULL. */
+ assert(test->key_len == 0);
+ HMAC_CTX ctx;
+ HMAC_CTX_init(&ctx);
+ if (!HMAC_Init_ex(&ctx, NULL, 0, EVP_md5(), NULL) ||
+ !HMAC_Update(&ctx, test->data, test->data_len) ||
+ !HMAC_Final(&ctx, out, &out_len)) {
+ fprintf(stderr, "HMAC failed.\n");
+ err++;
+ } else {
+ p = to_hex(out, out_len);
+ if (strcmp(p, test->hex_digest) != 0) {
+ fprintf(stderr, "got %s instead of %s\n", p, test->hex_digest);
+ err++;
+ }
+ }
+ HMAC_CTX_cleanup(&ctx);
+
+ if (err) {
+ return 1;
+ }
+
+ printf("PASS\n");
+ return 0;
+}
diff --git a/src/crypto/internal.h b/src/crypto/internal.h
new file mode 100644
index 0000000..4336e65
--- /dev/null
+++ b/src/crypto/internal.h
@@ -0,0 +1,302 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 OPENSSL_HEADER_CRYPTO_INTERNAL_H
+#define OPENSSL_HEADER_CRYPTO_INTERNAL_H
+
+#include <openssl/ex_data.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* st_CRYPTO_EX_DATA_IMPL contains an ex_data implementation. See the comments
+ * in ex_data.h for details of the behaviour of each of the functions. */
+struct st_CRYPTO_EX_DATA_IMPL {
+ int (*new_class)(void);
+ void (*cleanup)(void);
+
+ int (*get_new_index)(int class_value, long argl, void *argp,
+ CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func,
+ CRYPTO_EX_free *free_func);
+ int (*new_ex_data)(int class_value, void *obj, CRYPTO_EX_DATA *ad);
+ int (*dup_ex_data)(int class_value, CRYPTO_EX_DATA *to,
+ const CRYPTO_EX_DATA *from);
+ void (*free_ex_data)(int class_value, void *obj, CRYPTO_EX_DATA *ad);
+};
+
+
+#if defined(_MSC_VER)
+#define OPENSSL_U64(x) x##UI64
+#else
+
+#if defined(OPENSSL_64_BIT)
+#define OPENSSL_U64(x) x##UL
+#else
+#define OPENSSL_U64(x) x##ULL
+#endif
+
+#endif /* defined(_MSC_VER) */
+
+#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64) || defined(OPENSSL_ARM) || \
+ defined(OPENSSL_AARCH64)
+/* OPENSSL_cpuid_setup initializes OPENSSL_ia32cap_P. */
+void OPENSSL_cpuid_setup(void);
+#endif
+
+#if !defined(inline)
+#define inline __inline
+#endif
+
+
+/* Constant-time utility functions.
+ *
+ * The following 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); */
+
+/* constant_time_msb returns the given value with the MSB copied to all the
+ * other bits. */
+static inline unsigned int constant_time_msb(unsigned int a) {
+ return (unsigned int)((int)(a) >> (sizeof(int) * 8 - 1));
+}
+
+/* constant_time_lt returns 0xff..f if a < b and 0 otherwise. */
+static inline unsigned int constant_time_lt(unsigned int a, unsigned int b) {
+ /* Consider the two cases of the problem:
+ * msb(a) == msb(b): a < b iff the MSB of a - b is set.
+ * msb(a) != msb(b): a < b iff the MSB of b is set.
+ *
+ * If msb(a) == msb(b) then the following evaluates as:
+ * msb(a^((a^b)|((a-b)^a))) ==
+ * msb(a^((a-b) ^ a)) == (because msb(a^b) == 0)
+ * msb(a^a^(a-b)) == (rearranging)
+ * msb(a-b) (because ∀x. x^x == 0)
+ *
+ * Else, if msb(a) != msb(b) then the following evaluates as:
+ * msb(a^((a^b)|((a-b)^a))) ==
+ * msb(a^(🙠| ((a-b)^a))) == (because msb(a^b) == 1 and ðŸ™
+ * represents a value s.t. msb(ðŸ™) = 1)
+ * msb(a^ðŸ™) == (because ORing with 1 results in 1)
+ * msb(b)
+ *
+ *
+ * Here is an SMT-LIB verification of this formula:
+ *
+ * (define-fun lt ((a (_ BitVec 32)) (b (_ BitVec 32))) (_ BitVec 32)
+ * (bvxor a (bvor (bvxor a b) (bvxor (bvsub a b) a)))
+ * )
+ *
+ * (declare-fun a () (_ BitVec 32))
+ * (declare-fun b () (_ BitVec 32))
+ *
+ * (assert (not (= (= #x00000001 (bvlshr (lt a b) #x0000001f)) (bvult a b))))
+ * (check-sat)
+ * (get-model)
+ */
+ return constant_time_msb(a^((a^b)|((a-b)^a)));
+}
+
+/* constant_time_lt_8 acts like |constant_time_lt| but returns an 8-bit mask. */
+static inline uint8_t constant_time_lt_8(unsigned int a, unsigned int b) {
+ return (uint8_t)(constant_time_lt(a, b));
+}
+
+/* constant_time_gt returns 0xff..f if a >= b and 0 otherwise. */
+static inline unsigned int constant_time_ge(unsigned int a, unsigned int b) {
+ return ~constant_time_lt(a, b);
+}
+
+/* constant_time_ge_8 acts like |constant_time_ge| but returns an 8-bit mask. */
+static inline uint8_t constant_time_ge_8(unsigned int a, unsigned int b) {
+ return (uint8_t)(constant_time_ge(a, b));
+}
+
+/* constant_time_is_zero returns 0xff..f if a == 0 and 0 otherwise. */
+static inline unsigned int constant_time_is_zero(unsigned int a) {
+ /* Here is an SMT-LIB verification of this formula:
+ *
+ * (define-fun is_zero ((a (_ BitVec 32))) (_ BitVec 32)
+ * (bvand (bvnot a) (bvsub a #x00000001))
+ * )
+ *
+ * (declare-fun a () (_ BitVec 32))
+ *
+ * (assert (not (= (= #x00000001 (bvlshr (is_zero a) #x0000001f)) (= a #x00000000))))
+ * (check-sat)
+ * (get-model)
+ */
+ return constant_time_msb(~a & (a - 1));
+}
+
+/* constant_time_is_zero_8 acts like constant_time_is_zero but returns an 8-bit
+ * mask. */
+static inline uint8_t constant_time_is_zero_8(unsigned int a) {
+ return (uint8_t)(constant_time_is_zero(a));
+}
+
+/* constant_time_eq returns 0xff..f if a == b and 0 otherwise. */
+static inline unsigned int constant_time_eq(unsigned int a, unsigned int b) {
+ return constant_time_is_zero(a ^ b);
+}
+
+/* constant_time_eq_8 acts like |constant_time_eq| but returns an 8-bit mask. */
+static inline uint8_t constant_time_eq_8(unsigned int a, unsigned int b) {
+ return (uint8_t)(constant_time_eq(a, b));
+}
+
+/* constant_time_eq_int acts like |constant_time_eq| but works on int values. */
+static inline unsigned int constant_time_eq_int(int a, int b) {
+ return constant_time_eq((unsigned)(a), (unsigned)(b));
+}
+
+/* constant_time_eq_int_8 acts like |constant_time_eq_int| but returns an 8-bit
+ * mask. */
+static inline uint8_t constant_time_eq_int_8(int a, int b) {
+ return constant_time_eq_8((unsigned)(a), (unsigned)(b));
+}
+
+/* constant_time_select 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) {
+ return (mask & a) | (~mask & b);
+}
+
+/* constant_time_select_8 acts like |constant_time_select| but operates on
+ * 8-bit values. */
+static inline uint8_t constant_time_select_8(uint8_t mask, uint8_t a,
+ uint8_t b) {
+ return (uint8_t)(constant_time_select(mask, a, b));
+}
+
+/* constant_time_select_int acts like |constant_time_select| but operates on
+ * ints. */
+static inline int constant_time_select_int(unsigned int mask, int a, int b) {
+ return (int)(constant_time_select(mask, (unsigned)(a), (unsigned)(b)));
+}
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_CRYPTO_INTERNAL_H */
diff --git a/src/crypto/lhash/CMakeLists.txt b/src/crypto/lhash/CMakeLists.txt
new file mode 100644
index 0000000..0eaabed
--- /dev/null
+++ b/src/crypto/lhash/CMakeLists.txt
@@ -0,0 +1,17 @@
+include_directories(. .. ../../include)
+
+add_library(
+ lhash
+
+ OBJECT
+
+ lhash.c
+)
+
+add_executable(
+ lhash_test
+
+ lhash_test.c
+)
+
+target_link_libraries(lhash_test crypto)
diff --git a/src/crypto/lhash/lhash.c b/src/crypto/lhash/lhash.c
new file mode 100644
index 0000000..c282fa8
--- /dev/null
+++ b/src/crypto/lhash/lhash.c
@@ -0,0 +1,345 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/lhash.h>
+
+#include <assert.h>
+#include <limits.h>
+#include <string.h>
+
+#include <openssl/mem.h>
+
+/* kMinNumBuckets is the minimum size of the buckets array in an |_LHASH|. */
+static const size_t kMinNumBuckets = 16;
+
+/* kMaxAverageChainLength contains the maximum, average chain length. When the
+ * average chain length exceeds this value, the hash table will be resized. */
+static const size_t kMaxAverageChainLength = 2;
+static const size_t kMinAverageChainLength = 1;
+
+_LHASH *lh_new(lhash_hash_func hash, lhash_cmp_func comp) {
+ _LHASH *ret;
+
+ ret = OPENSSL_malloc(sizeof(_LHASH));
+ if (ret == NULL) {
+ return NULL;
+ }
+ memset(ret, 0, sizeof(_LHASH));
+
+ ret->num_buckets = kMinNumBuckets;
+ ret->buckets = OPENSSL_malloc(sizeof(LHASH_ITEM *) * ret->num_buckets);
+ if (ret->buckets == NULL) {
+ OPENSSL_free(ret);
+ return NULL;
+ }
+ memset(ret->buckets, 0, sizeof(LHASH_ITEM *) * ret->num_buckets);
+
+ ret->comp = comp;
+ if (ret->comp == NULL) {
+ ret->comp = (lhash_cmp_func) strcmp;
+ }
+ ret->hash = hash;
+ if (ret->hash == NULL) {
+ ret->hash = (lhash_hash_func) lh_strhash;
+ }
+
+ return ret;
+}
+
+void lh_free(_LHASH *lh) {
+ size_t i;
+ LHASH_ITEM *n, *next;
+
+ if (lh == NULL) {
+ return;
+ }
+
+ for (i = 0; i < lh->num_buckets; i++) {
+ for (n = lh->buckets[i]; n != NULL; n = next) {
+ next = n->next;
+ OPENSSL_free(n);
+ }
+ }
+
+ OPENSSL_free(lh->buckets);
+ OPENSSL_free(lh);
+}
+
+size_t lh_num_items(const _LHASH *lh) { return lh->num_items; }
+
+/* get_next_ptr_and_hash returns a pointer to the pointer that points to the
+ * item equal to |data|. In other words, it searches for an item equal to |data|
+ * and, if it's at the start of a chain, then it returns a pointer to an
+ * element of |lh->buckets|, otherwise it returns a pointer to the |next|
+ * element of the previous item in the chain. If an element equal to |data| is
+ * not found, it returns a pointer that points to a NULL pointer. If |out_hash|
+ * is not NULL, then it also puts the hash value of |data| in |*out_hash|. */
+static LHASH_ITEM **get_next_ptr_and_hash(const _LHASH *lh, uint32_t *out_hash,
+ const void *data) {
+ const uint32_t hash = lh->hash(data);
+ LHASH_ITEM *cur, **ret;
+
+ if (out_hash != NULL) {
+ *out_hash = hash;
+ }
+
+ ret = &lh->buckets[hash % lh->num_buckets];
+ for (cur = *ret; cur != NULL; cur = *ret) {
+ if (lh->comp(cur->data, data) == 0) {
+ break;
+ }
+ ret = &cur->next;
+ }
+
+ return ret;
+}
+
+void *lh_retrieve(const _LHASH *lh, const void *data) {
+ LHASH_ITEM **next_ptr;
+
+ next_ptr = get_next_ptr_and_hash(lh, NULL, data);
+
+ if (*next_ptr == NULL) {
+ return NULL;
+ }
+
+ return (*next_ptr)->data;
+}
+
+/* lh_rebucket allocates a new array of |new_num_buckets| pointers and
+ * redistributes the existing items into it before making it |lh->buckets| and
+ * freeing the old array. */
+static void lh_rebucket(_LHASH *lh, const size_t new_num_buckets) {
+ LHASH_ITEM **new_buckets, *cur, *next;
+ size_t i, alloc_size;
+
+ alloc_size = sizeof(LHASH_ITEM *) * new_num_buckets;
+ if (alloc_size / sizeof(LHASH_ITEM*) != new_num_buckets) {
+ return;
+ }
+
+ new_buckets = OPENSSL_malloc(alloc_size);
+ if (new_buckets == NULL) {
+ return;
+ }
+ memset(new_buckets, 0, alloc_size);
+
+ for (i = 0; i < lh->num_buckets; i++) {
+ for (cur = lh->buckets[i]; cur != NULL; cur = next) {
+ const size_t new_bucket = cur->hash % new_num_buckets;
+ next = cur->next;
+ cur->next = new_buckets[new_bucket];
+ new_buckets[new_bucket] = cur;
+ }
+ }
+
+ OPENSSL_free(lh->buckets);
+
+ lh->num_buckets = new_num_buckets;
+ lh->buckets = new_buckets;
+}
+
+/* lh_maybe_resize resizes the |buckets| array if needed. */
+static void lh_maybe_resize(_LHASH *lh) {
+ size_t avg_chain_length;
+
+ if (lh->callback_depth > 0) {
+ /* Don't resize the hash if we are currently iterating over it. */
+ return;
+ }
+
+ assert(lh->num_buckets >= kMinNumBuckets);
+ avg_chain_length = lh->num_items / lh->num_buckets;
+
+ if (avg_chain_length > kMaxAverageChainLength) {
+ const size_t new_num_buckets = lh->num_buckets * 2;
+
+ if (new_num_buckets > lh->num_buckets) {
+ lh_rebucket(lh, new_num_buckets);
+ }
+ } else if (avg_chain_length < kMinAverageChainLength &&
+ lh->num_buckets > kMinNumBuckets) {
+ size_t new_num_buckets = lh->num_buckets / 2;
+
+ if (new_num_buckets < kMinNumBuckets) {
+ new_num_buckets = kMinNumBuckets;
+ }
+
+ lh_rebucket(lh, new_num_buckets);
+ }
+}
+
+int lh_insert(_LHASH *lh, void **old_data, void *data) {
+ uint32_t hash;
+ LHASH_ITEM **next_ptr, *item;
+
+ *old_data = NULL;
+ next_ptr = get_next_ptr_and_hash(lh, &hash, data);
+
+
+ if (*next_ptr != NULL) {
+ /* An element equal to |data| already exists in the hash table. It will be
+ * replaced. */
+ *old_data = (*next_ptr)->data;
+ (*next_ptr)->data = data;
+ return 1;
+ }
+
+ /* An element equal to |data| doesn't exist in the hash table yet. */
+ item = OPENSSL_malloc(sizeof(LHASH_ITEM));
+ if (item == NULL) {
+ return 0;
+ }
+
+ item->data = data;
+ item->hash = hash;
+ item->next = NULL;
+ *next_ptr = item;
+ lh->num_items++;
+ lh_maybe_resize(lh);
+
+ return 1;
+}
+
+void *lh_delete(_LHASH *lh, const void *data) {
+ LHASH_ITEM **next_ptr, *item, *ret;
+
+ next_ptr = get_next_ptr_and_hash(lh, NULL, data);
+
+ if (*next_ptr == NULL) {
+ /* No such element. */
+ return NULL;
+ }
+
+ item = *next_ptr;
+ *next_ptr = item->next;
+ ret = item->data;
+ OPENSSL_free(item);
+
+ lh->num_items--;
+ lh_maybe_resize(lh);
+
+ return ret;
+}
+
+static void lh_doall_internal(_LHASH *lh, void (*no_arg_func)(void *),
+ void (*arg_func)(void *, void *), void *arg) {
+ size_t i;
+ LHASH_ITEM *cur, *next;
+
+ if (lh == NULL) {
+ return;
+ }
+
+ if (lh->callback_depth < UINT_MAX) {
+ /* |callback_depth| is a saturating counter. */
+ lh->callback_depth++;
+ }
+
+ for (i = 0; i < lh->num_buckets; i++) {
+ for (cur = lh->buckets[i]; cur != NULL; cur = next) {
+ next = cur->next;
+ if (arg_func) {
+ arg_func(cur->data, arg);
+ } else {
+ no_arg_func(cur->data);
+ }
+ }
+ }
+
+ if (lh->callback_depth < UINT_MAX) {
+ lh->callback_depth--;
+ }
+
+ /* The callback may have added or removed elements and the non-zero value of
+ * |callback_depth| will have suppressed any resizing. Thus any needed
+ * resizing is done here. */
+ lh_maybe_resize(lh);
+}
+
+void lh_doall(_LHASH *lh, void (*func)(void *)) {
+ lh_doall_internal(lh, func, NULL, NULL);
+}
+
+void lh_doall_arg(_LHASH *lh, void (*func)(void *, void *), void *arg) {
+ lh_doall_internal(lh, NULL, func, arg);
+}
+
+uint32_t lh_strhash(const char *c) {
+ /* 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 ret = 0;
+ long n;
+ unsigned long v;
+ int r;
+
+ if ((c == NULL) || (*c == '\0')) {
+ return (ret);
+ }
+
+ n = 0x100;
+ while (*c) {
+ v = n | (*c);
+ n += 0x100;
+ r = (int)((v >> 2) ^ v) & 0x0f;
+ ret = (ret << r) | (ret >> (32 - r));
+ ret &= 0xFFFFFFFFL;
+ ret ^= v * v;
+ c++;
+ }
+
+ return ((ret >> 16) ^ ret);
+}
diff --git a/src/crypto/lhash/lhash_test.c b/src/crypto/lhash/lhash_test.c
new file mode 100644
index 0000000..cf5e99b
--- /dev/null
+++ b/src/crypto/lhash/lhash_test.c
@@ -0,0 +1,196 @@
+/* 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. */
+
+#if !defined(_POSIX_C_SOURCE)
+#define _POSIX_C_SOURCE 201410L
+#endif
+
+#include <openssl/crypto.h>
+#include <openssl/lhash.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+struct dummy_lhash_node {
+ char *s;
+ struct dummy_lhash_node *next;
+};
+
+struct dummy_lhash {
+ struct dummy_lhash_node *head;
+};
+
+static void dummy_lh_free(struct dummy_lhash *lh) {
+ struct dummy_lhash_node *cur, *next;
+
+ for (cur = lh->head; cur != NULL; cur = next) {
+ next = cur->next;
+ free(cur->s);
+ free(cur);
+ }
+}
+
+static size_t dummy_lh_num_items(const struct dummy_lhash *lh) {
+ size_t count = 0;
+ struct dummy_lhash_node *cur;
+
+ for (cur = lh->head; cur != NULL; cur = cur->next) {
+ count++;
+ }
+
+ return count;
+}
+
+static char *dummy_lh_retrieve(struct dummy_lhash *lh, const char *s) {
+ struct dummy_lhash_node *cur;
+
+ for (cur = lh->head; cur != NULL; cur = cur->next) {
+ if (strcmp(cur->s, s) == 0) {
+ return cur->s;
+ }
+ }
+
+ return NULL;
+}
+
+static int dummy_lh_insert(struct dummy_lhash *lh, char **old_data, char *s) {
+ struct dummy_lhash_node *node, *cur;
+
+ for (cur = lh->head; cur != NULL; cur = cur->next) {
+ if (strcmp(cur->s, s) == 0) {
+ *old_data = cur->s;
+ cur->s = s;
+ return 1;
+ }
+ }
+
+ node = malloc(sizeof(struct dummy_lhash_node));
+ *old_data = NULL;
+ node->s = s;
+ node->next = lh->head;
+ lh->head = node;
+ return 1;
+}
+
+static char *dummy_lh_delete(struct dummy_lhash *lh, const void *s) {
+ struct dummy_lhash_node *cur, **next_ptr;
+ char *ret;
+
+ next_ptr = &lh->head;
+ for (cur = lh->head; cur != NULL; cur = cur->next) {
+ if (strcmp(cur->s, s) == 0) {
+ ret = cur->s;
+ *next_ptr = cur->next;
+ free(cur);
+ return ret;
+ }
+ next_ptr = &cur->next;
+ }
+
+ return NULL;
+}
+
+static char *rand_string(void) {
+ unsigned len = 1 + (rand() % 3);
+ char *ret = malloc(len + 1);
+ unsigned i;
+
+ for (i = 0; i < len; i++) {
+ ret[i] = '0' + (rand() & 7);
+ }
+ ret[i] = 0;
+
+ return ret;
+}
+
+int main(int argc, char **argv) {
+ _LHASH *lh;
+ struct dummy_lhash dummy_lh = {NULL};
+ unsigned i;
+
+ CRYPTO_library_init();
+
+ lh = lh_new(NULL, NULL);
+
+ for (i = 0; i < 100000; i++) {
+ unsigned action;
+ char *s, *s1, *s2;
+
+ if (dummy_lh_num_items(&dummy_lh) != lh_num_items(lh)) {
+ fprintf(stderr, "Length mismatch\n");
+ return 1;
+ }
+
+ action = rand() % 3;
+ switch (action) {
+ case 0:
+ s = rand_string();
+ s1 = (char *)lh_retrieve(lh, s);
+ s2 = dummy_lh_retrieve(&dummy_lh, s);
+ if (s1 != NULL && (s2 == NULL || strcmp(s1, s2) != 0)) {
+ fprintf(stderr, "lh_retrieve failure\n");
+ abort();
+ }
+ free(s);
+ break;
+
+ case 1:
+ s = rand_string();
+ lh_insert(lh, (void **)&s1, s);
+ dummy_lh_insert(&dummy_lh, &s2, strdup(s));
+
+ if (s1 != NULL && (s2 == NULL || strcmp(s1, s2) != 0)) {
+ fprintf(stderr, "lh_insert failure\n");
+ abort();
+ }
+
+ if (s1) {
+ free(s1);
+ }
+ if (s2) {
+ free(s2);
+ }
+ break;
+
+ case 2:
+ s = rand_string();
+ s1 = lh_delete(lh, s);
+ s2 = dummy_lh_delete(&dummy_lh, s);
+
+ if (s1 != NULL && (s2 == NULL || strcmp(s1, s2) != 0)) {
+ fprintf(stderr, "lh_insert failure\n");
+ abort();
+ }
+
+ if (s1) {
+ free(s1);
+ }
+ if (s2) {
+ free(s2);
+ }
+ free(s);
+ break;
+
+ default:
+ abort();
+ }
+ }
+
+ lh_doall(lh, free);
+ lh_free(lh);
+ dummy_lh_free(&dummy_lh);
+ printf("PASS\n");
+ return 0;
+}
diff --git a/src/crypto/lhash/make_macros.sh b/src/crypto/lhash/make_macros.sh
new file mode 100644
index 0000000..79d1e57
--- /dev/null
+++ b/src/crypto/lhash/make_macros.sh
@@ -0,0 +1,64 @@
+#!/bin/sh
+
+cat > lhash_macros.h << EOF
+/* 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. */
+
+#if !defined(IN_LHASH_H)
+#error "Don't include this file directly. Include lhash.h"
+#endif
+
+EOF
+
+output_lhash () {
+ type=$1
+
+ cat >> lhash_macros.h << EOF
+/* ${type} */
+#define lh_${type}_new(hash, comp)\\
+((LHASH_OF(${type})*) lh_new(CHECKED_CAST(lhash_hash_func, uint32_t (*) (const ${type} *), hash), CHECKED_CAST(lhash_cmp_func, int (*) (const ${type} *a, const ${type} *b), comp)))
+
+#define lh_${type}_free(lh)\\
+ lh_free(CHECKED_CAST(_LHASH*, LHASH_OF(${type})*, lh));
+
+#define lh_${type}_num_items(lh)\\
+ lh_num_items(CHECKED_CAST(_LHASH*, LHASH_OF(${type})*, lh))
+
+#define lh_${type}_retrieve(lh, data)\\
+ ((${type}*) lh_retrieve(CHECKED_CAST(_LHASH*, LHASH_OF(${type})*, lh), CHECKED_CAST(void*, ${type}*, data)))
+
+#define lh_${type}_insert(lh, old_data, data)\\
+ lh_insert(CHECKED_CAST(_LHASH*, LHASH_OF(${type})*, lh), CHECKED_CAST(void**, ${type}**, old_data), CHECKED_CAST(void*, ${type}*, data))
+
+#define lh_${type}_delete(lh, data)\\
+ ((${type}*) lh_delete(CHECKED_CAST(_LHASH*, LHASH_OF(${type})*, lh), CHECKED_CAST(void*, ${type}*, data)))
+
+#define lh_${type}_doall(lh, func)\\
+ lh_doall(CHECKED_CAST(_LHASH*, LHASH_OF(${type})*, lh), CHECKED_CAST(void (*)(void*), void (*) (${type}*), func));
+
+#define lh_${type}_doall_arg(lh, func, arg)\\
+ lh_doall_arg(CHECKED_CAST(_LHASH*, LHASH_OF(${type})*, lh), CHECKED_CAST(void (*)(void*, void*), void (*) (${type}*, void*), func), arg);
+
+
+EOF
+}
+
+lhash_types=$(cat lhash.h | grep '^ \* LHASH_OF:' | sed -e 's/.*LHASH_OF://' -e 's/ .*//')
+
+for type in $lhash_types; do
+ echo Hash of ${type}
+ output_lhash "${type}"
+done
+
+clang-format -i lhash_macros.h
diff --git a/src/crypto/md4/CMakeLists.txt b/src/crypto/md4/CMakeLists.txt
new file mode 100644
index 0000000..db7a187
--- /dev/null
+++ b/src/crypto/md4/CMakeLists.txt
@@ -0,0 +1,9 @@
+include_directories(. .. ../../include)
+
+add_library(
+ md4
+
+ OBJECT
+
+ md4.c
+)
diff --git a/src/crypto/md4/md4.c b/src/crypto/md4/md4.c
new file mode 100644
index 0000000..8fb357b
--- /dev/null
+++ b/src/crypto/md4/md4.c
@@ -0,0 +1,224 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/md4.h>
+
+#include <string.h>
+
+
+/* Implemented from RFC1186 The MD4 Message-Digest Algorithm. */
+
+int MD4_Init(MD4_CTX *md4) {
+ memset(md4, 0, sizeof(MD4_CTX));
+ md4->A = 0x67452301UL;
+ md4->B = 0xefcdab89UL;
+ md4->C = 0x98badcfeUL;
+ md4->D = 0x10325476UL;
+ return 1;
+}
+
+void md4_block_data_order (MD4_CTX *md4, const void *p, size_t num);
+
+#define DATA_ORDER_IS_LITTLE_ENDIAN
+
+#define HASH_LONG uint32_t
+#define HASH_CTX MD4_CTX
+#define HASH_CBLOCK 64
+#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; \
+ (void) HOST_l2c(ll, (s)); \
+ ll = (c)->B; \
+ (void) HOST_l2c(ll, (s)); \
+ ll = (c)->C; \
+ (void) HOST_l2c(ll, (s)); \
+ ll = (c)->D; \
+ (void) HOST_l2c(ll, (s)); \
+ } while (0)
+#define HASH_BLOCK_DATA_ORDER md4_block_data_order
+
+#include "../digest/md32_common.h"
+
+/* As pointed out by Wei Dai <weidai@eskimo.com>, 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); \
+ };
+
+void md4_block_data_order(MD4_CTX *c, const void *data_, size_t num) {
+ const uint8_t *data = data_;
+ uint32_t A, B, C, D, l;
+ uint32_t 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;
+ }
+}
diff --git a/src/crypto/md5/CMakeLists.txt b/src/crypto/md5/CMakeLists.txt
new file mode 100644
index 0000000..6c5e80f
--- /dev/null
+++ b/src/crypto/md5/CMakeLists.txt
@@ -0,0 +1,30 @@
+include_directories(. .. ../../include)
+
+if (${ARCH} STREQUAL "x86_64")
+ set(
+ MD5_ARCH_SOURCES
+
+ md5-x86_64.${ASM_EXT}
+ )
+endif()
+
+if (${ARCH} STREQUAL "x86")
+ set(
+ MD5_ARCH_SOURCES
+
+ md5-586.${ASM_EXT}
+ )
+endif()
+
+add_library(
+ md5
+
+ OBJECT
+
+ md5.c
+
+ ${MD5_ARCH_SOURCES}
+)
+
+perlasm(md5-x86_64.${ASM_EXT} asm/md5-x86_64.pl)
+perlasm(md5-586.${ASM_EXT} asm/md5-586.pl)
diff --git a/src/crypto/md5/asm/md5-586.pl b/src/crypto/md5/asm/md5-586.pl
new file mode 100644
index 0000000..6cb66bb
--- /dev/null
+++ b/src/crypto/md5/asm/md5-586.pl
@@ -0,0 +1,307 @@
+#!/usr/local/bin/perl
+
+# Normal is the
+# md5_block_x86(MD5_CTX *c, ULONG *X);
+# version, non-normal is the
+# md5_block_x86(MD5_CTX *c, ULONG *X,int blocks);
+
+$normal=0;
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+push(@INC,"${dir}","${dir}../../perlasm");
+require "x86asm.pl";
+
+&asm_init($ARGV[0],$0);
+
+$A="eax";
+$B="ebx";
+$C="ecx";
+$D="edx";
+$tmp1="edi";
+$tmp2="ebp";
+$X="esi";
+
+# What we need to load into $tmp for the next round
+%Ltmp1=("R0",&Np($C), "R1",&Np($C), "R2",&Np($C), "R3",&Np($D));
+@xo=(
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, # R0
+ 1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, # R1
+ 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2, # R2
+ 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9, # R3
+ );
+
+&md5_block("md5_block_asm_data_order");
+&asm_finish();
+
+sub Np
+ {
+ local($p)=@_;
+ local(%n)=($A,$D,$B,$A,$C,$B,$D,$C);
+ return($n{$p});
+ }
+
+sub R0
+ {
+ local($pos,$a,$b,$c,$d,$K,$ki,$s,$t)=@_;
+
+ &mov($tmp1,$C) if $pos < 0;
+ &mov($tmp2,&DWP($xo[$ki]*4,$K,"",0)) if $pos < 0; # very first one
+
+ # body proper
+
+ &comment("R0 $ki");
+ &xor($tmp1,$d); # F function - part 2
+
+ &and($tmp1,$b); # F function - part 3
+ &lea($a,&DWP($t,$a,$tmp2,1));
+
+ &xor($tmp1,$d); # F function - part 4
+
+ &add($a,$tmp1);
+ &mov($tmp1,&Np($c)) if $pos < 1; # next tmp1 for R0
+ &mov($tmp1,&Np($c)) if $pos == 1; # next tmp1 for R1
+
+ &rotl($a,$s);
+
+ &mov($tmp2,&DWP($xo[$ki+1]*4,$K,"",0)) if ($pos != 2);
+
+ &add($a,$b);
+ }
+
+sub R1
+ {
+ local($pos,$a,$b,$c,$d,$K,$ki,$s,$t)=@_;
+
+ &comment("R1 $ki");
+
+ &lea($a,&DWP($t,$a,$tmp2,1));
+
+ &xor($tmp1,$b); # G function - part 2
+ &and($tmp1,$d); # G function - part 3
+
+ &mov($tmp2,&DWP($xo[$ki+1]*4,$K,"",0)) if ($pos != 2);
+ &xor($tmp1,$c); # G function - part 4
+
+ &add($a,$tmp1);
+ &mov($tmp1,&Np($c)) if $pos < 1; # G function - part 1
+ &mov($tmp1,&Np($c)) if $pos == 1; # G function - part 1
+
+ &rotl($a,$s);
+
+ &add($a,$b);
+ }
+
+sub R2
+ {
+ local($n,$pos,$a,$b,$c,$d,$K,$ki,$s,$t)=@_;
+ # This one is different, only 3 logical operations
+
+if (($n & 1) == 0)
+ {
+ &comment("R2 $ki");
+ # make sure to do 'D' first, not 'B', else we clash with
+ # the last add from the previous round.
+
+ &xor($tmp1,$d); # H function - part 2
+
+ &xor($tmp1,$b); # H function - part 3
+ &lea($a,&DWP($t,$a,$tmp2,1));
+
+ &add($a,$tmp1);
+
+ &rotl($a,$s);
+
+ &mov($tmp2,&DWP($xo[$ki+1]*4,$K,"",0));
+ &mov($tmp1,&Np($c));
+ }
+else
+ {
+ &comment("R2 $ki");
+ # make sure to do 'D' first, not 'B', else we clash with
+ # the last add from the previous round.
+
+ &lea($a,&DWP($t,$a,$tmp2,1));
+
+ &add($b,$c); # MOVED FORWARD
+ &xor($tmp1,$d); # H function - part 2
+
+ &xor($tmp1,$b); # H function - part 3
+ &mov($tmp2,&DWP($xo[$ki+1]*4,$K,"",0)) if ($pos != 2);
+
+ &add($a,$tmp1);
+ &mov($tmp1,&Np($c)) if $pos < 1; # H function - part 1
+ &mov($tmp1,-1) if $pos == 1; # I function - part 1
+
+ &rotl($a,$s);
+
+ &add($a,$b);
+ }
+ }
+
+sub R3
+ {
+ local($pos,$a,$b,$c,$d,$K,$ki,$s,$t)=@_;
+
+ &comment("R3 $ki");
+
+ # &not($tmp1)
+ &xor($tmp1,$d) if $pos < 0; # I function - part 2
+
+ &or($tmp1,$b); # I function - part 3
+ &lea($a,&DWP($t,$a,$tmp2,1));
+
+ &xor($tmp1,$c); # I function - part 4
+ &mov($tmp2,&DWP($xo[$ki+1]*4,$K,"",0)) if $pos != 2; # load X/k value
+ &mov($tmp2,&wparam(0)) if $pos == 2;
+
+ &add($a,$tmp1);
+ &mov($tmp1,-1) if $pos < 1; # H function - part 1
+ &add($K,64) if $pos >=1 && !$normal;
+
+ &rotl($a,$s);
+
+ &xor($tmp1,&Np($d)) if $pos <= 0; # I function - part = first time
+ &mov($tmp1,&DWP( 0,$tmp2,"",0)) if $pos > 0;
+ &add($a,$b);
+ }
+
+
+sub md5_block
+ {
+ local($name)=@_;
+
+ &function_begin_B($name,"",3);
+
+ # parameter 1 is the MD5_CTX structure.
+ # A 0
+ # B 4
+ # C 8
+ # D 12
+
+ &push("esi");
+ &push("edi");
+ &mov($tmp1, &wparam(0)); # edi
+ &mov($X, &wparam(1)); # esi
+ &mov($C, &wparam(2));
+ &push("ebp");
+ &shl($C, 6);
+ &push("ebx");
+ &add($C, $X); # offset we end at
+ &sub($C, 64);
+ &mov($A, &DWP( 0,$tmp1,"",0));
+ &push($C); # Put on the TOS
+ &mov($B, &DWP( 4,$tmp1,"",0));
+ &mov($C, &DWP( 8,$tmp1,"",0));
+ &mov($D, &DWP(12,$tmp1,"",0));
+
+ &set_label("start") unless $normal;
+ &comment("");
+ &comment("R0 section");
+
+ &R0(-2,$A,$B,$C,$D,$X, 0, 7,0xd76aa478);
+ &R0( 0,$D,$A,$B,$C,$X, 1,12,0xe8c7b756);
+ &R0( 0,$C,$D,$A,$B,$X, 2,17,0x242070db);
+ &R0( 0,$B,$C,$D,$A,$X, 3,22,0xc1bdceee);
+ &R0( 0,$A,$B,$C,$D,$X, 4, 7,0xf57c0faf);
+ &R0( 0,$D,$A,$B,$C,$X, 5,12,0x4787c62a);
+ &R0( 0,$C,$D,$A,$B,$X, 6,17,0xa8304613);
+ &R0( 0,$B,$C,$D,$A,$X, 7,22,0xfd469501);
+ &R0( 0,$A,$B,$C,$D,$X, 8, 7,0x698098d8);
+ &R0( 0,$D,$A,$B,$C,$X, 9,12,0x8b44f7af);
+ &R0( 0,$C,$D,$A,$B,$X,10,17,0xffff5bb1);
+ &R0( 0,$B,$C,$D,$A,$X,11,22,0x895cd7be);
+ &R0( 0,$A,$B,$C,$D,$X,12, 7,0x6b901122);
+ &R0( 0,$D,$A,$B,$C,$X,13,12,0xfd987193);
+ &R0( 0,$C,$D,$A,$B,$X,14,17,0xa679438e);
+ &R0( 1,$B,$C,$D,$A,$X,15,22,0x49b40821);
+
+ &comment("");
+ &comment("R1 section");
+ &R1(-1,$A,$B,$C,$D,$X,16, 5,0xf61e2562);
+ &R1( 0,$D,$A,$B,$C,$X,17, 9,0xc040b340);
+ &R1( 0,$C,$D,$A,$B,$X,18,14,0x265e5a51);
+ &R1( 0,$B,$C,$D,$A,$X,19,20,0xe9b6c7aa);
+ &R1( 0,$A,$B,$C,$D,$X,20, 5,0xd62f105d);
+ &R1( 0,$D,$A,$B,$C,$X,21, 9,0x02441453);
+ &R1( 0,$C,$D,$A,$B,$X,22,14,0xd8a1e681);
+ &R1( 0,$B,$C,$D,$A,$X,23,20,0xe7d3fbc8);
+ &R1( 0,$A,$B,$C,$D,$X,24, 5,0x21e1cde6);
+ &R1( 0,$D,$A,$B,$C,$X,25, 9,0xc33707d6);
+ &R1( 0,$C,$D,$A,$B,$X,26,14,0xf4d50d87);
+ &R1( 0,$B,$C,$D,$A,$X,27,20,0x455a14ed);
+ &R1( 0,$A,$B,$C,$D,$X,28, 5,0xa9e3e905);
+ &R1( 0,$D,$A,$B,$C,$X,29, 9,0xfcefa3f8);
+ &R1( 0,$C,$D,$A,$B,$X,30,14,0x676f02d9);
+ &R1( 1,$B,$C,$D,$A,$X,31,20,0x8d2a4c8a);
+
+ &comment("");
+ &comment("R2 section");
+ &R2( 0,-1,$A,$B,$C,$D,$X,32, 4,0xfffa3942);
+ &R2( 1, 0,$D,$A,$B,$C,$X,33,11,0x8771f681);
+ &R2( 2, 0,$C,$D,$A,$B,$X,34,16,0x6d9d6122);
+ &R2( 3, 0,$B,$C,$D,$A,$X,35,23,0xfde5380c);
+ &R2( 4, 0,$A,$B,$C,$D,$X,36, 4,0xa4beea44);
+ &R2( 5, 0,$D,$A,$B,$C,$X,37,11,0x4bdecfa9);
+ &R2( 6, 0,$C,$D,$A,$B,$X,38,16,0xf6bb4b60);
+ &R2( 7, 0,$B,$C,$D,$A,$X,39,23,0xbebfbc70);
+ &R2( 8, 0,$A,$B,$C,$D,$X,40, 4,0x289b7ec6);
+ &R2( 9, 0,$D,$A,$B,$C,$X,41,11,0xeaa127fa);
+ &R2(10, 0,$C,$D,$A,$B,$X,42,16,0xd4ef3085);
+ &R2(11, 0,$B,$C,$D,$A,$X,43,23,0x04881d05);
+ &R2(12, 0,$A,$B,$C,$D,$X,44, 4,0xd9d4d039);
+ &R2(13, 0,$D,$A,$B,$C,$X,45,11,0xe6db99e5);
+ &R2(14, 0,$C,$D,$A,$B,$X,46,16,0x1fa27cf8);
+ &R2(15, 1,$B,$C,$D,$A,$X,47,23,0xc4ac5665);
+
+ &comment("");
+ &comment("R3 section");
+ &R3(-1,$A,$B,$C,$D,$X,48, 6,0xf4292244);
+ &R3( 0,$D,$A,$B,$C,$X,49,10,0x432aff97);
+ &R3( 0,$C,$D,$A,$B,$X,50,15,0xab9423a7);
+ &R3( 0,$B,$C,$D,$A,$X,51,21,0xfc93a039);
+ &R3( 0,$A,$B,$C,$D,$X,52, 6,0x655b59c3);
+ &R3( 0,$D,$A,$B,$C,$X,53,10,0x8f0ccc92);
+ &R3( 0,$C,$D,$A,$B,$X,54,15,0xffeff47d);
+ &R3( 0,$B,$C,$D,$A,$X,55,21,0x85845dd1);
+ &R3( 0,$A,$B,$C,$D,$X,56, 6,0x6fa87e4f);
+ &R3( 0,$D,$A,$B,$C,$X,57,10,0xfe2ce6e0);
+ &R3( 0,$C,$D,$A,$B,$X,58,15,0xa3014314);
+ &R3( 0,$B,$C,$D,$A,$X,59,21,0x4e0811a1);
+ &R3( 0,$A,$B,$C,$D,$X,60, 6,0xf7537e82);
+ &R3( 0,$D,$A,$B,$C,$X,61,10,0xbd3af235);
+ &R3( 0,$C,$D,$A,$B,$X,62,15,0x2ad7d2bb);
+ &R3( 2,$B,$C,$D,$A,$X,63,21,0xeb86d391);
+
+ # &mov($tmp2,&wparam(0)); # done in the last R3
+ # &mov($tmp1, &DWP( 0,$tmp2,"",0)); # done is the last R3
+
+ &add($A,$tmp1);
+ &mov($tmp1, &DWP( 4,$tmp2,"",0));
+
+ &add($B,$tmp1);
+ &mov($tmp1, &DWP( 8,$tmp2,"",0));
+
+ &add($C,$tmp1);
+ &mov($tmp1, &DWP(12,$tmp2,"",0));
+
+ &add($D,$tmp1);
+ &mov(&DWP( 0,$tmp2,"",0),$A);
+
+ &mov(&DWP( 4,$tmp2,"",0),$B);
+ &mov($tmp1,&swtmp(0)) unless $normal;
+
+ &mov(&DWP( 8,$tmp2,"",0),$C);
+ &mov(&DWP(12,$tmp2,"",0),$D);
+
+ &cmp($tmp1,$X) unless $normal; # check count
+ &jae(&label("start")) unless $normal;
+
+ &pop("eax"); # pop the temp variable off the stack
+ &pop("ebx");
+ &pop("ebp");
+ &pop("edi");
+ &pop("esi");
+ &ret();
+ &function_end_B($name);
+ }
+
diff --git a/src/crypto/md5/asm/md5-x86_64.pl b/src/crypto/md5/asm/md5-x86_64.pl
new file mode 100644
index 0000000..77a6e01
--- /dev/null
+++ b/src/crypto/md5/asm/md5-x86_64.pl
@@ -0,0 +1,370 @@
+#!/usr/bin/perl -w
+#
+# MD5 optimized for AMD64.
+#
+# Author: Marc Bevand <bevand_m (at) epita.fr>
+# Licence: I hereby disclaim the copyright on this code and place it
+# in the public domain.
+#
+
+use strict;
+
+my $code;
+
+# round1_step() does:
+# dst = x + ((dst + F(x,y,z) + X[k] + T_i) <<< s)
+# %r10d = X[k_next]
+# %r11d = z' (copy of z for the next step)
+# Each round1_step() takes about 5.3 clocks (9 instructions, 1.7 IPC)
+sub round1_step
+{
+ my ($pos, $dst, $x, $y, $z, $k_next, $T_i, $s) = @_;
+ $code .= " mov 0*4(%rsi), %r10d /* (NEXT STEP) X[0] */\n" if ($pos == -1);
+ $code .= " mov %edx, %r11d /* (NEXT STEP) z' = %edx */\n" if ($pos == -1);
+ $code .= <<EOF;
+ xor $y, %r11d /* y ^ ... */
+ lea $T_i($dst,%r10d),$dst /* Const + dst + ... */
+ and $x, %r11d /* x & ... */
+ xor $z, %r11d /* z ^ ... */
+ mov $k_next*4(%rsi),%r10d /* (NEXT STEP) X[$k_next] */
+ add %r11d, $dst /* dst += ... */
+ rol \$$s, $dst /* dst <<< s */
+ mov $y, %r11d /* (NEXT STEP) z' = $y */
+ add $x, $dst /* dst += x */
+EOF
+}
+
+# round2_step() does:
+# dst = x + ((dst + G(x,y,z) + X[k] + T_i) <<< s)
+# %r10d = X[k_next]
+# %r11d = z' (copy of z for the next step)
+# %r12d = z' (copy of z for the next step)
+# Each round2_step() takes about 5.4 clocks (11 instructions, 2.0 IPC)
+sub round2_step
+{
+ my ($pos, $dst, $x, $y, $z, $k_next, $T_i, $s) = @_;
+ $code .= " mov 1*4(%rsi), %r10d /* (NEXT STEP) X[1] */\n" if ($pos == -1);
+ $code .= " mov %edx, %r11d /* (NEXT STEP) z' = %edx */\n" if ($pos == -1);
+ $code .= " mov %edx, %r12d /* (NEXT STEP) z' = %edx */\n" if ($pos == -1);
+ $code .= <<EOF;
+ not %r11d /* not z */
+ lea $T_i($dst,%r10d),$dst /* Const + dst + ... */
+ and $x, %r12d /* x & z */
+ and $y, %r11d /* y & (not z) */
+ mov $k_next*4(%rsi),%r10d /* (NEXT STEP) X[$k_next] */
+ or %r11d, %r12d /* (y & (not z)) | (x & z) */
+ mov $y, %r11d /* (NEXT STEP) z' = $y */
+ add %r12d, $dst /* dst += ... */
+ mov $y, %r12d /* (NEXT STEP) z' = $y */
+ rol \$$s, $dst /* dst <<< s */
+ add $x, $dst /* dst += x */
+EOF
+}
+
+# round3_step() does:
+# dst = x + ((dst + H(x,y,z) + X[k] + T_i) <<< s)
+# %r10d = X[k_next]
+# %r11d = y' (copy of y for the next step)
+# Each round3_step() takes about 4.2 clocks (8 instructions, 1.9 IPC)
+sub round3_step
+{
+ my ($pos, $dst, $x, $y, $z, $k_next, $T_i, $s) = @_;
+ $code .= " mov 5*4(%rsi), %r10d /* (NEXT STEP) X[5] */\n" if ($pos == -1);
+ $code .= " mov %ecx, %r11d /* (NEXT STEP) y' = %ecx */\n" if ($pos == -1);
+ $code .= <<EOF;
+ lea $T_i($dst,%r10d),$dst /* Const + dst + ... */
+ mov $k_next*4(%rsi),%r10d /* (NEXT STEP) X[$k_next] */
+ xor $z, %r11d /* z ^ ... */
+ xor $x, %r11d /* x ^ ... */
+ add %r11d, $dst /* dst += ... */
+ rol \$$s, $dst /* dst <<< s */
+ mov $x, %r11d /* (NEXT STEP) y' = $x */
+ add $x, $dst /* dst += x */
+EOF
+}
+
+# round4_step() does:
+# dst = x + ((dst + I(x,y,z) + X[k] + T_i) <<< s)
+# %r10d = X[k_next]
+# %r11d = not z' (copy of not z for the next step)
+# Each round4_step() takes about 5.2 clocks (9 instructions, 1.7 IPC)
+sub round4_step
+{
+ my ($pos, $dst, $x, $y, $z, $k_next, $T_i, $s) = @_;
+ $code .= " mov 0*4(%rsi), %r10d /* (NEXT STEP) X[0] */\n" if ($pos == -1);
+ $code .= " mov \$0xffffffff, %r11d\n" if ($pos == -1);
+ $code .= " xor %edx, %r11d /* (NEXT STEP) not z' = not %edx*/\n"
+ if ($pos == -1);
+ $code .= <<EOF;
+ lea $T_i($dst,%r10d),$dst /* Const + dst + ... */
+ or $x, %r11d /* x | ... */
+ xor $y, %r11d /* y ^ ... */
+ add %r11d, $dst /* dst += ... */
+ mov $k_next*4(%rsi),%r10d /* (NEXT STEP) X[$k_next] */
+ mov \$0xffffffff, %r11d
+ rol \$$s, $dst /* dst <<< s */
+ xor $y, %r11d /* (NEXT STEP) not z' = not $y */
+ add $x, $dst /* dst += x */
+EOF
+}
+
+no warnings qw(uninitialized);
+my $flavour = shift;
+my $output = shift || "";
+if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+
+my $win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; my $dir=$1; my $xlate;
+( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
+( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
+die "can't locate x86_64-xlate.pl";
+
+open OUT,"| \"$^X\" $xlate $flavour $output";
+*STDOUT=*OUT;
+
+$code .= <<EOF;
+.text
+.align 16
+
+.globl md5_block_asm_data_order
+.type md5_block_asm_data_order,\@function,3
+md5_block_asm_data_order:
+ push %rbp
+ push %rbx
+ push %r12
+ push %r14
+ push %r15
+.Lprologue:
+
+ # rdi = arg #1 (ctx, MD5_CTX pointer)
+ # rsi = arg #2 (ptr, data pointer)
+ # rdx = arg #3 (nbr, number of 16-word blocks to process)
+ mov %rdi, %rbp # rbp = ctx
+ shl \$6, %rdx # rdx = nbr in bytes
+ lea (%rsi,%rdx), %rdi # rdi = end
+ mov 0*4(%rbp), %eax # eax = ctx->A
+ mov 1*4(%rbp), %ebx # ebx = ctx->B
+ mov 2*4(%rbp), %ecx # ecx = ctx->C
+ mov 3*4(%rbp), %edx # edx = ctx->D
+ # end is 'rdi'
+ # ptr is 'rsi'
+ # A is 'eax'
+ # B is 'ebx'
+ # C is 'ecx'
+ # D is 'edx'
+
+ cmp %rdi, %rsi # cmp end with ptr
+ je .Lend # jmp if ptr == end
+
+ # BEGIN of loop over 16-word blocks
+.Lloop: # save old values of A, B, C, D
+ mov %eax, %r8d
+ mov %ebx, %r9d
+ mov %ecx, %r14d
+ mov %edx, %r15d
+EOF
+round1_step(-1,'%eax','%ebx','%ecx','%edx', '1','0xd76aa478', '7');
+round1_step( 0,'%edx','%eax','%ebx','%ecx', '2','0xe8c7b756','12');
+round1_step( 0,'%ecx','%edx','%eax','%ebx', '3','0x242070db','17');
+round1_step( 0,'%ebx','%ecx','%edx','%eax', '4','0xc1bdceee','22');
+round1_step( 0,'%eax','%ebx','%ecx','%edx', '5','0xf57c0faf', '7');
+round1_step( 0,'%edx','%eax','%ebx','%ecx', '6','0x4787c62a','12');
+round1_step( 0,'%ecx','%edx','%eax','%ebx', '7','0xa8304613','17');
+round1_step( 0,'%ebx','%ecx','%edx','%eax', '8','0xfd469501','22');
+round1_step( 0,'%eax','%ebx','%ecx','%edx', '9','0x698098d8', '7');
+round1_step( 0,'%edx','%eax','%ebx','%ecx','10','0x8b44f7af','12');
+round1_step( 0,'%ecx','%edx','%eax','%ebx','11','0xffff5bb1','17');
+round1_step( 0,'%ebx','%ecx','%edx','%eax','12','0x895cd7be','22');
+round1_step( 0,'%eax','%ebx','%ecx','%edx','13','0x6b901122', '7');
+round1_step( 0,'%edx','%eax','%ebx','%ecx','14','0xfd987193','12');
+round1_step( 0,'%ecx','%edx','%eax','%ebx','15','0xa679438e','17');
+round1_step( 1,'%ebx','%ecx','%edx','%eax', '0','0x49b40821','22');
+
+round2_step(-1,'%eax','%ebx','%ecx','%edx', '6','0xf61e2562', '5');
+round2_step( 0,'%edx','%eax','%ebx','%ecx','11','0xc040b340', '9');
+round2_step( 0,'%ecx','%edx','%eax','%ebx', '0','0x265e5a51','14');
+round2_step( 0,'%ebx','%ecx','%edx','%eax', '5','0xe9b6c7aa','20');
+round2_step( 0,'%eax','%ebx','%ecx','%edx','10','0xd62f105d', '5');
+round2_step( 0,'%edx','%eax','%ebx','%ecx','15', '0x2441453', '9');
+round2_step( 0,'%ecx','%edx','%eax','%ebx', '4','0xd8a1e681','14');
+round2_step( 0,'%ebx','%ecx','%edx','%eax', '9','0xe7d3fbc8','20');
+round2_step( 0,'%eax','%ebx','%ecx','%edx','14','0x21e1cde6', '5');
+round2_step( 0,'%edx','%eax','%ebx','%ecx', '3','0xc33707d6', '9');
+round2_step( 0,'%ecx','%edx','%eax','%ebx', '8','0xf4d50d87','14');
+round2_step( 0,'%ebx','%ecx','%edx','%eax','13','0x455a14ed','20');
+round2_step( 0,'%eax','%ebx','%ecx','%edx', '2','0xa9e3e905', '5');
+round2_step( 0,'%edx','%eax','%ebx','%ecx', '7','0xfcefa3f8', '9');
+round2_step( 0,'%ecx','%edx','%eax','%ebx','12','0x676f02d9','14');
+round2_step( 1,'%ebx','%ecx','%edx','%eax', '0','0x8d2a4c8a','20');
+
+round3_step(-1,'%eax','%ebx','%ecx','%edx', '8','0xfffa3942', '4');
+round3_step( 0,'%edx','%eax','%ebx','%ecx','11','0x8771f681','11');
+round3_step( 0,'%ecx','%edx','%eax','%ebx','14','0x6d9d6122','16');
+round3_step( 0,'%ebx','%ecx','%edx','%eax', '1','0xfde5380c','23');
+round3_step( 0,'%eax','%ebx','%ecx','%edx', '4','0xa4beea44', '4');
+round3_step( 0,'%edx','%eax','%ebx','%ecx', '7','0x4bdecfa9','11');
+round3_step( 0,'%ecx','%edx','%eax','%ebx','10','0xf6bb4b60','16');
+round3_step( 0,'%ebx','%ecx','%edx','%eax','13','0xbebfbc70','23');
+round3_step( 0,'%eax','%ebx','%ecx','%edx', '0','0x289b7ec6', '4');
+round3_step( 0,'%edx','%eax','%ebx','%ecx', '3','0xeaa127fa','11');
+round3_step( 0,'%ecx','%edx','%eax','%ebx', '6','0xd4ef3085','16');
+round3_step( 0,'%ebx','%ecx','%edx','%eax', '9', '0x4881d05','23');
+round3_step( 0,'%eax','%ebx','%ecx','%edx','12','0xd9d4d039', '4');
+round3_step( 0,'%edx','%eax','%ebx','%ecx','15','0xe6db99e5','11');
+round3_step( 0,'%ecx','%edx','%eax','%ebx', '2','0x1fa27cf8','16');
+round3_step( 1,'%ebx','%ecx','%edx','%eax', '0','0xc4ac5665','23');
+
+round4_step(-1,'%eax','%ebx','%ecx','%edx', '7','0xf4292244', '6');
+round4_step( 0,'%edx','%eax','%ebx','%ecx','14','0x432aff97','10');
+round4_step( 0,'%ecx','%edx','%eax','%ebx', '5','0xab9423a7','15');
+round4_step( 0,'%ebx','%ecx','%edx','%eax','12','0xfc93a039','21');
+round4_step( 0,'%eax','%ebx','%ecx','%edx', '3','0x655b59c3', '6');
+round4_step( 0,'%edx','%eax','%ebx','%ecx','10','0x8f0ccc92','10');
+round4_step( 0,'%ecx','%edx','%eax','%ebx', '1','0xffeff47d','15');
+round4_step( 0,'%ebx','%ecx','%edx','%eax', '8','0x85845dd1','21');
+round4_step( 0,'%eax','%ebx','%ecx','%edx','15','0x6fa87e4f', '6');
+round4_step( 0,'%edx','%eax','%ebx','%ecx', '6','0xfe2ce6e0','10');
+round4_step( 0,'%ecx','%edx','%eax','%ebx','13','0xa3014314','15');
+round4_step( 0,'%ebx','%ecx','%edx','%eax', '4','0x4e0811a1','21');
+round4_step( 0,'%eax','%ebx','%ecx','%edx','11','0xf7537e82', '6');
+round4_step( 0,'%edx','%eax','%ebx','%ecx', '2','0xbd3af235','10');
+round4_step( 0,'%ecx','%edx','%eax','%ebx', '9','0x2ad7d2bb','15');
+round4_step( 1,'%ebx','%ecx','%edx','%eax', '0','0xeb86d391','21');
+$code .= <<EOF;
+ # add old values of A, B, C, D
+ add %r8d, %eax
+ add %r9d, %ebx
+ add %r14d, %ecx
+ add %r15d, %edx
+
+ # loop control
+ add \$64, %rsi # ptr += 64
+ cmp %rdi, %rsi # cmp end with ptr
+ jb .Lloop # jmp if ptr < end
+ # END of loop over 16-word blocks
+
+.Lend:
+ mov %eax, 0*4(%rbp) # ctx->A = A
+ mov %ebx, 1*4(%rbp) # ctx->B = B
+ mov %ecx, 2*4(%rbp) # ctx->C = C
+ mov %edx, 3*4(%rbp) # ctx->D = D
+
+ mov (%rsp),%r15
+ mov 8(%rsp),%r14
+ mov 16(%rsp),%r12
+ mov 24(%rsp),%rbx
+ mov 32(%rsp),%rbp
+ add \$40,%rsp
+.Lepilogue:
+ ret
+.size md5_block_asm_data_order,.-md5_block_asm_data_order
+EOF
+
+# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame,
+# CONTEXT *context,DISPATCHER_CONTEXT *disp)
+if ($win64) {
+my $rec="%rcx";
+my $frame="%rdx";
+my $context="%r8";
+my $disp="%r9";
+
+$code.=<<___;
+.extern __imp_RtlVirtualUnwind
+.type se_handler,\@abi-omnipotent
+.align 16
+se_handler:
+ push %rsi
+ push %rdi
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+ pushfq
+ sub \$64,%rsp
+
+ mov 120($context),%rax # pull context->Rax
+ mov 248($context),%rbx # pull context->Rip
+
+ lea .Lprologue(%rip),%r10
+ cmp %r10,%rbx # context->Rip<.Lprologue
+ jb .Lin_prologue
+
+ mov 152($context),%rax # pull context->Rsp
+
+ lea .Lepilogue(%rip),%r10
+ cmp %r10,%rbx # context->Rip>=.Lepilogue
+ jae .Lin_prologue
+
+ lea 40(%rax),%rax
+
+ mov -8(%rax),%rbp
+ mov -16(%rax),%rbx
+ mov -24(%rax),%r12
+ mov -32(%rax),%r14
+ mov -40(%rax),%r15
+ mov %rbx,144($context) # restore context->Rbx
+ mov %rbp,160($context) # restore context->Rbp
+ mov %r12,216($context) # restore context->R12
+ mov %r14,232($context) # restore context->R14
+ mov %r15,240($context) # restore context->R15
+
+.Lin_prologue:
+ mov 8(%rax),%rdi
+ mov 16(%rax),%rsi
+ mov %rax,152($context) # restore context->Rsp
+ mov %rsi,168($context) # restore context->Rsi
+ mov %rdi,176($context) # restore context->Rdi
+
+ mov 40($disp),%rdi # disp->ContextRecord
+ mov $context,%rsi # context
+ mov \$154,%ecx # sizeof(CONTEXT)
+ .long 0xa548f3fc # cld; rep movsq
+
+ mov $disp,%rsi
+ xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER
+ mov 8(%rsi),%rdx # arg2, disp->ImageBase
+ mov 0(%rsi),%r8 # arg3, disp->ControlPc
+ mov 16(%rsi),%r9 # arg4, disp->FunctionEntry
+ mov 40(%rsi),%r10 # disp->ContextRecord
+ lea 56(%rsi),%r11 # &disp->HandlerData
+ lea 24(%rsi),%r12 # &disp->EstablisherFrame
+ mov %r10,32(%rsp) # arg5
+ mov %r11,40(%rsp) # arg6
+ mov %r12,48(%rsp) # arg7
+ mov %rcx,56(%rsp) # arg8, (NULL)
+ call *__imp_RtlVirtualUnwind(%rip)
+
+ mov \$1,%eax # ExceptionContinueSearch
+ add \$64,%rsp
+ popfq
+ pop %r15
+ pop %r14
+ pop %r13
+ pop %r12
+ pop %rbp
+ pop %rbx
+ pop %rdi
+ pop %rsi
+ ret
+.size se_handler,.-se_handler
+
+.section .pdata
+.align 4
+ .rva .LSEH_begin_md5_block_asm_data_order
+ .rva .LSEH_end_md5_block_asm_data_order
+ .rva .LSEH_info_md5_block_asm_data_order
+
+.section .xdata
+.align 8
+.LSEH_info_md5_block_asm_data_order:
+ .byte 9,0,0,0
+ .rva se_handler
+___
+}
+
+print $code;
+
+close STDOUT;
diff --git a/src/crypto/md5/md5.c b/src/crypto/md5/md5.c
new file mode 100644
index 0000000..e20b86b
--- /dev/null
+++ b/src/crypto/md5/md5.c
@@ -0,0 +1,274 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/md5.h>
+
+#include <string.h>
+
+#include <openssl/mem.h>
+
+
+uint8_t *MD5(const uint8_t *data, size_t len, uint8_t *out) {
+ MD5_CTX ctx;
+ static uint8_t digest[MD5_DIGEST_LENGTH];
+
+ /* TODO(fork): remove this static buffer. */
+ if (out == NULL) {
+ out = digest;
+ }
+
+ MD5_Init(&ctx);
+ MD5_Update(&ctx, data, len);
+ MD5_Final(out, &ctx);
+
+ return out;
+}
+
+int MD5_Init(MD5_CTX *md5) {
+ memset(md5, 0, sizeof(MD5_CTX));
+ md5->A = 0x67452301UL;
+ md5->B = 0xefcdab89UL;
+ md5->C = 0x98badcfeUL;
+ md5->D = 0x10325476UL;
+ return 1;
+}
+
+#if !defined(OPENSSL_NO_ASM) && \
+ (defined(OPENSSL_X86_64) || defined(OPENSSL_X86))
+#define MD5_ASM
+#define md5_block_data_order md5_block_asm_data_order
+#endif
+
+
+void md5_block_data_order(MD5_CTX *md5, const void *p, size_t num);
+
+#define DATA_ORDER_IS_LITTLE_ENDIAN
+
+#define HASH_LONG uint32_t
+#define HASH_CTX MD5_CTX
+#define HASH_CBLOCK 64
+#define HASH_UPDATE MD5_Update
+#define HASH_TRANSFORM MD5_Transform
+#define HASH_FINAL MD5_Final
+#define HASH_MAKE_STRING(c, s) \
+ do { \
+ unsigned long ll; \
+ ll = (c)->A; \
+ (void) HOST_l2c(ll, (s)); \
+ ll = (c)->B; \
+ (void) HOST_l2c(ll, (s)); \
+ ll = (c)->C; \
+ (void) HOST_l2c(ll, (s)); \
+ ll = (c)->D; \
+ (void) HOST_l2c(ll, (s)); \
+ } while (0)
+#define HASH_BLOCK_DATA_ORDER md5_block_data_order
+
+#include "../digest/md32_common.h"
+
+/* As pointed out by Wei Dai <weidai@eskimo.com>, 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; };
+
+#ifndef md5_block_data_order
+#ifdef X
+#undef X
+#endif
+void md5_block_data_order(MD5_CTX *md5, const void *in_data, size_t num) {
+ const uint8_t *data = in_data;
+ uint32_t A, B, C, D, l;
+ uint32_t XX0, XX1, XX2, XX3, XX4, XX5, XX6, XX7, XX8, XX9, XX10, XX11, XX12,
+ XX13, XX14, XX15;
+#define X(i) XX##i
+
+ A = md5->A;
+ B = md5->B;
+ C = md5->C;
+ D = md5->D;
+
+ for (; num--;) {
+ HOST_c2l(data, l);
+ X(0) = l;
+ HOST_c2l(data, l);
+ X(1) = l;
+ /* Round 0 */
+ R0(A, B, C, D, X(0), 7, 0xd76aa478L);
+ HOST_c2l(data, l);
+ X(2) = l;
+ R0(D, A, B, C, X(1), 12, 0xe8c7b756L);
+ HOST_c2l(data, l);
+ X(3) = l;
+ R0(C, D, A, B, X(2), 17, 0x242070dbL);
+ HOST_c2l(data, l);
+ X(4) = l;
+ R0(B, C, D, A, X(3), 22, 0xc1bdceeeL);
+ HOST_c2l(data, l);
+ X(5) = l;
+ R0(A, B, C, D, X(4), 7, 0xf57c0fafL);
+ HOST_c2l(data, l);
+ X(6) = l;
+ R0(D, A, B, C, X(5), 12, 0x4787c62aL);
+ HOST_c2l(data, l);
+ X(7) = l;
+ R0(C, D, A, B, X(6), 17, 0xa8304613L);
+ HOST_c2l(data, l);
+ X(8) = l;
+ R0(B, C, D, A, X(7), 22, 0xfd469501L);
+ HOST_c2l(data, l);
+ X(9) = l;
+ R0(A, B, C, D, X(8), 7, 0x698098d8L);
+ HOST_c2l(data, l);
+ X(10) = l;
+ R0(D, A, B, C, X(9), 12, 0x8b44f7afL);
+ HOST_c2l(data, l);
+ X(11) = l;
+ R0(C, D, A, B, X(10), 17, 0xffff5bb1L);
+ HOST_c2l(data, l);
+ X(12) = l;
+ R0(B, C, D, A, X(11), 22, 0x895cd7beL);
+ HOST_c2l(data, l);
+ X(13) = l;
+ R0(A, B, C, D, X(12), 7, 0x6b901122L);
+ HOST_c2l(data, l);
+ X(14) = l;
+ R0(D, A, B, C, X(13), 12, 0xfd987193L);
+ HOST_c2l(data, l);
+ X(15) = l;
+ R0(C, D, A, B, X(14), 17, 0xa679438eL);
+ R0(B, C, D, A, X(15), 22, 0x49b40821L);
+ /* Round 1 */
+ R1(A, B, C, D, X(1), 5, 0xf61e2562L);
+ R1(D, A, B, C, X(6), 9, 0xc040b340L);
+ R1(C, D, A, B, X(11), 14, 0x265e5a51L);
+ R1(B, C, D, A, X(0), 20, 0xe9b6c7aaL);
+ R1(A, B, C, D, X(5), 5, 0xd62f105dL);
+ R1(D, A, B, C, X(10), 9, 0x02441453L);
+ R1(C, D, A, B, X(15), 14, 0xd8a1e681L);
+ R1(B, C, D, A, X(4), 20, 0xe7d3fbc8L);
+ R1(A, B, C, D, X(9), 5, 0x21e1cde6L);
+ R1(D, A, B, C, X(14), 9, 0xc33707d6L);
+ R1(C, D, A, B, X(3), 14, 0xf4d50d87L);
+ R1(B, C, D, A, X(8), 20, 0x455a14edL);
+ R1(A, B, C, D, X(13), 5, 0xa9e3e905L);
+ R1(D, A, B, C, X(2), 9, 0xfcefa3f8L);
+ R1(C, D, A, B, X(7), 14, 0x676f02d9L);
+ R1(B, C, D, A, X(12), 20, 0x8d2a4c8aL);
+ /* Round 2 */
+ R2(A, B, C, D, X(5), 4, 0xfffa3942L);
+ R2(D, A, B, C, X(8), 11, 0x8771f681L);
+ R2(C, D, A, B, X(11), 16, 0x6d9d6122L);
+ R2(B, C, D, A, X(14), 23, 0xfde5380cL);
+ R2(A, B, C, D, X(1), 4, 0xa4beea44L);
+ R2(D, A, B, C, X(4), 11, 0x4bdecfa9L);
+ R2(C, D, A, B, X(7), 16, 0xf6bb4b60L);
+ R2(B, C, D, A, X(10), 23, 0xbebfbc70L);
+ R2(A, B, C, D, X(13), 4, 0x289b7ec6L);
+ R2(D, A, B, C, X(0), 11, 0xeaa127faL);
+ R2(C, D, A, B, X(3), 16, 0xd4ef3085L);
+ R2(B, C, D, A, X(6), 23, 0x04881d05L);
+ R2(A, B, C, D, X(9), 4, 0xd9d4d039L);
+ R2(D, A, B, C, X(12), 11, 0xe6db99e5L);
+ R2(C, D, A, B, X(15), 16, 0x1fa27cf8L);
+ R2(B, C, D, A, X(2), 23, 0xc4ac5665L);
+ /* Round 3 */
+ R3(A, B, C, D, X(0), 6, 0xf4292244L);
+ R3(D, A, B, C, X(7), 10, 0x432aff97L);
+ R3(C, D, A, B, X(14), 15, 0xab9423a7L);
+ R3(B, C, D, A, X(5), 21, 0xfc93a039L);
+ R3(A, B, C, D, X(12), 6, 0x655b59c3L);
+ R3(D, A, B, C, X(3), 10, 0x8f0ccc92L);
+ R3(C, D, A, B, X(10), 15, 0xffeff47dL);
+ R3(B, C, D, A, X(1), 21, 0x85845dd1L);
+ R3(A, B, C, D, X(8), 6, 0x6fa87e4fL);
+ R3(D, A, B, C, X(15), 10, 0xfe2ce6e0L);
+ R3(C, D, A, B, X(6), 15, 0xa3014314L);
+ R3(B, C, D, A, X(13), 21, 0x4e0811a1L);
+ R3(A, B, C, D, X(4), 6, 0xf7537e82L);
+ R3(D, A, B, C, X(11), 10, 0xbd3af235L);
+ R3(C, D, A, B, X(2), 15, 0x2ad7d2bbL);
+ R3(B, C, D, A, X(9), 21, 0xeb86d391L);
+
+ A = md5->A += A;
+ B = md5->B += B;
+ C = md5->C += C;
+ D = md5->D += D;
+ }
+}
+#endif
diff --git a/src/crypto/mem.c b/src/crypto/mem.c
new file mode 100644
index 0000000..a8a8c08
--- /dev/null
+++ b/src/crypto/mem.c
@@ -0,0 +1,199 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#if !defined(_POSIX_C_SOURCE)
+#define _POSIX_C_SOURCE 201410L /* needed for strdup, snprintf, vprintf etc */
+#endif
+
+#include <openssl/mem.h>
+
+#include <assert.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+#if defined(OPENSSL_WINDOWS)
+#pragma warning(push, 3)
+#include <Windows.h>
+#pragma warning(pop)
+#else
+#include <strings.h>
+#endif
+
+
+void *OPENSSL_realloc_clean(void *ptr, size_t old_size, size_t new_size) {
+ void *ret = NULL;
+
+ if (ptr == NULL) {
+ return OPENSSL_malloc(new_size);
+ }
+
+ if (new_size == 0) {
+ return NULL;
+ }
+
+ /* We don't support shrinking the buffer. Note the memcpy that copies
+ * |old_size| bytes to the new buffer, below. */
+ if (new_size < old_size) {
+ return NULL;
+ }
+
+ ret = OPENSSL_malloc(new_size);
+ if (ret == NULL) {
+ return NULL;
+ }
+
+ memcpy(ret, ptr, old_size);
+ OPENSSL_cleanse(ptr, old_size);
+ OPENSSL_free(ptr);
+ return ret;
+}
+
+void OPENSSL_cleanse(void *ptr, size_t len) {
+#if defined(OPENSSL_WINDOWS)
+ SecureZeroMemory(ptr, len);
+#else
+ memset(ptr, 0, len);
+
+#if !defined(OPENSSL_NO_ASM)
+ /* As best as we can tell, this is sufficient to break any optimisations that
+ might try to eliminate "superfluous" memsets. If there's an easy way to
+ detect memset_s, it would be better to use that. */
+ __asm__ __volatile__("" : : "r"(ptr) : "memory");
+#endif
+#endif /* !OPENSSL_NO_ASM */
+}
+
+int CRYPTO_memcmp(const void *in_a, const void *in_b, size_t len) {
+ size_t i;
+ const uint8_t *a = in_a;
+ const uint8_t *b = in_b;
+ uint8_t x = 0;
+
+ for (i = 0; i < len; i++) {
+ x |= a[i] ^ b[i];
+ }
+
+ return x;
+}
+
+uint32_t OPENSSL_hash32(const void *ptr, size_t len) {
+ /* These are the FNV-1a parameters for 32 bits. */
+ static const uint32_t kPrime = 16777619u;
+ static const uint32_t kOffsetBasis = 2166136261u;
+
+ const uint8_t *in = ptr;
+ size_t i;
+ uint32_t h = kOffsetBasis;
+
+ for (i = 0; i < len; i++) {
+ h ^= in[i];
+ h *= kPrime;
+ }
+
+ return h;
+}
+
+char *OPENSSL_strdup(const char *s) { return strdup(s); }
+
+size_t OPENSSL_strnlen(const char *s, size_t len) {
+ size_t i;
+
+ for (i = 0; i < len; i++) {
+ if (s[i] == 0) {
+ return i;
+ }
+ }
+
+ return len;
+}
+
+#if defined(OPENSSL_WINDOWS)
+
+int OPENSSL_strcasecmp(const char *a, const char *b) {
+ return _stricmp(a, b);
+}
+
+int OPENSSL_strncasecmp(const char *a, const char *b, size_t n) {
+ return _strnicmp(a, b, n);
+}
+
+#else
+
+int OPENSSL_strcasecmp(const char *a, const char *b) {
+ return strcasecmp(a, b);
+}
+
+int OPENSSL_strncasecmp(const char *a, const char *b, size_t n) {
+ return strncasecmp(a, b, n);
+}
+
+#endif
+
+int BIO_snprintf(char *buf, size_t n, const char *format, ...) {
+ va_list args;
+ int ret;
+
+ va_start(args, format);
+
+ ret = BIO_vsnprintf(buf, n, format, args);
+
+ va_end(args);
+ return ret;
+}
+
+int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args) {
+ return vsnprintf(buf, n, format, args);
+}
diff --git a/src/crypto/modes/CMakeLists.txt b/src/crypto/modes/CMakeLists.txt
new file mode 100644
index 0000000..d50e97b
--- /dev/null
+++ b/src/crypto/modes/CMakeLists.txt
@@ -0,0 +1,63 @@
+include_directories(. .. ../../include)
+
+if (${ARCH} STREQUAL "x86_64")
+ set(
+ MODES_ARCH_SOURCES
+
+ aesni-gcm-x86_64.${ASM_EXT}
+ ghash-x86_64.${ASM_EXT}
+ )
+endif()
+
+if (${ARCH} STREQUAL "x86")
+ set(
+ MODES_ARCH_SOURCES
+
+ ghash-x86.${ASM_EXT}
+ )
+endif()
+
+if (${ARCH} STREQUAL "arm")
+ set(
+ MODES_ARCH_SOURCES
+
+ ghash-armv4.${ASM_EXT}
+ ghashv8-armx.${ASM_EXT}
+ )
+endif()
+
+if (${ARCH} STREQUAL "aarch64")
+ set(
+ MODES_ARCH_SOURCES
+
+ ghashv8-armx.${ASM_EXT}
+ )
+endif()
+
+add_library(
+ modes
+
+ OBJECT
+
+ cbc.c
+ ctr.c
+ ofb.c
+ cfb.c
+ gcm.c
+
+ ${MODES_ARCH_SOURCES}
+)
+
+perlasm(aesni-gcm-x86_64.${ASM_EXT} asm/aesni-gcm-x86_64.pl)
+perlasm(ghash-x86_64.${ASM_EXT} asm/ghash-x86_64.pl)
+perlasm(ghash-x86.${ASM_EXT} asm/ghash-x86.pl)
+perlasm(ghash-armv4.${ASM_EXT} asm/ghash-armv4.pl)
+perlasm(ghashv8-armx.${ASM_EXT} asm/ghashv8-armx.pl)
+
+add_executable(
+ gcm_test
+
+ gcm_test.c
+)
+
+target_link_libraries(gcm_test crypto)
diff --git a/src/crypto/modes/asm/aesni-gcm-x86_64.pl b/src/crypto/modes/asm/aesni-gcm-x86_64.pl
new file mode 100644
index 0000000..7e4e04e
--- /dev/null
+++ b/src/crypto/modes/asm/aesni-gcm-x86_64.pl
@@ -0,0 +1,1057 @@
+#!/usr/bin/env perl
+#
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+# project. The module is, however, dual licensed under OpenSSL and
+# CRYPTOGAMS licenses depending on where you obtain it. For further
+# details see http://www.openssl.org/~appro/cryptogams/.
+# ====================================================================
+#
+#
+# AES-NI-CTR+GHASH stitch.
+#
+# February 2013
+#
+# OpenSSL GCM implementation is organized in such way that its
+# performance is rather close to the sum of its streamed components,
+# in the context parallelized AES-NI CTR and modulo-scheduled
+# PCLMULQDQ-enabled GHASH. Unfortunately, as no stitch implementation
+# was observed to perform significantly better than the sum of the
+# components on contemporary CPUs, the effort was deemed impossible to
+# justify. This module is based on combination of Intel submissions,
+# [1] and [2], with MOVBE twist suggested by Ilya Albrekht and Max
+# Locktyukhin of Intel Corp. who verified that it reduces shuffles
+# pressure with notable relative improvement, achieving 1.0 cycle per
+# byte processed with 128-bit key on Haswell processor, and 0.74 -
+# on Broadwell. [Mentioned results are raw profiled measurements for
+# favourable packet size, one divisible by 96. Applications using the
+# EVP interface will observe a few percent worse performance.]
+#
+# [1] http://rt.openssl.org/Ticket/Display.html?id=2900&user=guest&pass=guest
+# [2] http://www.intel.com/content/dam/www/public/us/en/documents/software-support/enabling-high-performance-gcm.pdf
+
+$flavour = shift;
+$output = shift;
+if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+
+$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
+( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
+die "can't locate x86_64-xlate.pl";
+
+if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
+ =~ /GNU assembler version ([2-9]\.[0-9]+)/) {
+ $avx = ($1>=2.19) + ($1>=2.22);
+}
+
+if (!$avx && $win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) &&
+ `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)/) {
+ $avx = ($1>=2.09) + ($1>=2.10);
+}
+
+if (!$avx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) &&
+ `ml64 2>&1` =~ /Version ([0-9]+)\./) {
+ $avx = ($1>=10) + ($1>=11);
+}
+
+if (!$avx && `$ENV{CC} -v 2>&1` =~ /(^clang version|based on LLVM) ([3-9]\.[0-9]+)/) {
+ $avx = ($2>=3.0) + ($2>3.0);
+}
+
+open OUT,"| \"$^X\" $xlate $flavour $output";
+*STDOUT=*OUT;
+
+if ($avx>1) {{{
+
+($inp,$out,$len,$key,$ivp,$Xip)=("%rdi","%rsi","%rdx","%rcx","%r8","%r9");
+
+($Ii,$T1,$T2,$Hkey,
+ $Z0,$Z1,$Z2,$Z3,$Xi) = map("%xmm$_",(0..8));
+
+($inout0,$inout1,$inout2,$inout3,$inout4,$inout5,$rndkey) = map("%xmm$_",(9..15));
+
+($counter,$rounds,$ret,$const,$in0,$end0)=("%ebx","%ebp","%r10","%r11","%r14","%r15");
+
+$code=<<___;
+.text
+
+.type _aesni_ctr32_ghash_6x,\@abi-omnipotent
+.align 32
+_aesni_ctr32_ghash_6x:
+ vmovdqu 0x20($const),$T2 # borrow $T2, .Lone_msb
+ sub \$6,$len
+ vpxor $Z0,$Z0,$Z0 # $Z0 = 0
+ vmovdqu 0x00-0x80($key),$rndkey
+ vpaddb $T2,$T1,$inout1
+ vpaddb $T2,$inout1,$inout2
+ vpaddb $T2,$inout2,$inout3
+ vpaddb $T2,$inout3,$inout4
+ vpaddb $T2,$inout4,$inout5
+ vpxor $rndkey,$T1,$inout0
+ vmovdqu $Z0,16+8(%rsp) # "$Z3" = 0
+ jmp .Loop6x
+
+.align 32
+.Loop6x:
+ add \$`6<<24`,$counter
+ jc .Lhandle_ctr32 # discard $inout[1-5]?
+ vmovdqu 0x00-0x20($Xip),$Hkey # $Hkey^1
+ vpaddb $T2,$inout5,$T1 # next counter value
+ vpxor $rndkey,$inout1,$inout1
+ vpxor $rndkey,$inout2,$inout2
+
+.Lresume_ctr32:
+ vmovdqu $T1,($ivp) # save next counter value
+ vpclmulqdq \$0x10,$Hkey,$Z3,$Z1
+ vpxor $rndkey,$inout3,$inout3
+ vmovups 0x10-0x80($key),$T2 # borrow $T2 for $rndkey
+ vpclmulqdq \$0x01,$Hkey,$Z3,$Z2
+ xor %r12,%r12
+ cmp $in0,$end0
+
+ vaesenc $T2,$inout0,$inout0
+ vmovdqu 0x30+8(%rsp),$Ii # I[4]
+ vpxor $rndkey,$inout4,$inout4
+ vpclmulqdq \$0x00,$Hkey,$Z3,$T1
+ vaesenc $T2,$inout1,$inout1
+ vpxor $rndkey,$inout5,$inout5
+ setnc %r12b
+ vpclmulqdq \$0x11,$Hkey,$Z3,$Z3
+ vaesenc $T2,$inout2,$inout2
+ vmovdqu 0x10-0x20($Xip),$Hkey # $Hkey^2
+ neg %r12
+ vaesenc $T2,$inout3,$inout3
+ vpxor $Z1,$Z2,$Z2
+ vpclmulqdq \$0x00,$Hkey,$Ii,$Z1
+ vpxor $Z0,$Xi,$Xi # modulo-scheduled
+ vaesenc $T2,$inout4,$inout4
+ vpxor $Z1,$T1,$Z0
+ and \$0x60,%r12
+ vmovups 0x20-0x80($key),$rndkey
+ vpclmulqdq \$0x10,$Hkey,$Ii,$T1
+ vaesenc $T2,$inout5,$inout5
+
+ vpclmulqdq \$0x01,$Hkey,$Ii,$T2
+ lea ($in0,%r12),$in0
+ vaesenc $rndkey,$inout0,$inout0
+ vpxor 16+8(%rsp),$Xi,$Xi # modulo-scheduled [vpxor $Z3,$Xi,$Xi]
+ vpclmulqdq \$0x11,$Hkey,$Ii,$Hkey
+ vmovdqu 0x40+8(%rsp),$Ii # I[3]
+ vaesenc $rndkey,$inout1,$inout1
+ movbe 0x58($in0),%r13
+ vaesenc $rndkey,$inout2,$inout2
+ movbe 0x50($in0),%r12
+ vaesenc $rndkey,$inout3,$inout3
+ mov %r13,0x20+8(%rsp)
+ vaesenc $rndkey,$inout4,$inout4
+ mov %r12,0x28+8(%rsp)
+ vmovdqu 0x30-0x20($Xip),$Z1 # borrow $Z1 for $Hkey^3
+ vaesenc $rndkey,$inout5,$inout5
+
+ vmovups 0x30-0x80($key),$rndkey
+ vpxor $T1,$Z2,$Z2
+ vpclmulqdq \$0x00,$Z1,$Ii,$T1
+ vaesenc $rndkey,$inout0,$inout0
+ vpxor $T2,$Z2,$Z2
+ vpclmulqdq \$0x10,$Z1,$Ii,$T2
+ vaesenc $rndkey,$inout1,$inout1
+ vpxor $Hkey,$Z3,$Z3
+ vpclmulqdq \$0x01,$Z1,$Ii,$Hkey
+ vaesenc $rndkey,$inout2,$inout2
+ vpclmulqdq \$0x11,$Z1,$Ii,$Z1
+ vmovdqu 0x50+8(%rsp),$Ii # I[2]
+ vaesenc $rndkey,$inout3,$inout3
+ vaesenc $rndkey,$inout4,$inout4
+ vpxor $T1,$Z0,$Z0
+ vmovdqu 0x40-0x20($Xip),$T1 # borrow $T1 for $Hkey^4
+ vaesenc $rndkey,$inout5,$inout5
+
+ vmovups 0x40-0x80($key),$rndkey
+ vpxor $T2,$Z2,$Z2
+ vpclmulqdq \$0x00,$T1,$Ii,$T2
+ vaesenc $rndkey,$inout0,$inout0
+ vpxor $Hkey,$Z2,$Z2
+ vpclmulqdq \$0x10,$T1,$Ii,$Hkey
+ vaesenc $rndkey,$inout1,$inout1
+ movbe 0x48($in0),%r13
+ vpxor $Z1,$Z3,$Z3
+ vpclmulqdq \$0x01,$T1,$Ii,$Z1
+ vaesenc $rndkey,$inout2,$inout2
+ movbe 0x40($in0),%r12
+ vpclmulqdq \$0x11,$T1,$Ii,$T1
+ vmovdqu 0x60+8(%rsp),$Ii # I[1]
+ vaesenc $rndkey,$inout3,$inout3
+ mov %r13,0x30+8(%rsp)
+ vaesenc $rndkey,$inout4,$inout4
+ mov %r12,0x38+8(%rsp)
+ vpxor $T2,$Z0,$Z0
+ vmovdqu 0x60-0x20($Xip),$T2 # borrow $T2 for $Hkey^5
+ vaesenc $rndkey,$inout5,$inout5
+
+ vmovups 0x50-0x80($key),$rndkey
+ vpxor $Hkey,$Z2,$Z2
+ vpclmulqdq \$0x00,$T2,$Ii,$Hkey
+ vaesenc $rndkey,$inout0,$inout0
+ vpxor $Z1,$Z2,$Z2
+ vpclmulqdq \$0x10,$T2,$Ii,$Z1
+ vaesenc $rndkey,$inout1,$inout1
+ movbe 0x38($in0),%r13
+ vpxor $T1,$Z3,$Z3
+ vpclmulqdq \$0x01,$T2,$Ii,$T1
+ vpxor 0x70+8(%rsp),$Xi,$Xi # accumulate I[0]
+ vaesenc $rndkey,$inout2,$inout2
+ movbe 0x30($in0),%r12
+ vpclmulqdq \$0x11,$T2,$Ii,$T2
+ vaesenc $rndkey,$inout3,$inout3
+ mov %r13,0x40+8(%rsp)
+ vaesenc $rndkey,$inout4,$inout4
+ mov %r12,0x48+8(%rsp)
+ vpxor $Hkey,$Z0,$Z0
+ vmovdqu 0x70-0x20($Xip),$Hkey # $Hkey^6
+ vaesenc $rndkey,$inout5,$inout5
+
+ vmovups 0x60-0x80($key),$rndkey
+ vpxor $Z1,$Z2,$Z2
+ vpclmulqdq \$0x10,$Hkey,$Xi,$Z1
+ vaesenc $rndkey,$inout0,$inout0
+ vpxor $T1,$Z2,$Z2
+ vpclmulqdq \$0x01,$Hkey,$Xi,$T1
+ vaesenc $rndkey,$inout1,$inout1
+ movbe 0x28($in0),%r13
+ vpxor $T2,$Z3,$Z3
+ vpclmulqdq \$0x00,$Hkey,$Xi,$T2
+ vaesenc $rndkey,$inout2,$inout2
+ movbe 0x20($in0),%r12
+ vpclmulqdq \$0x11,$Hkey,$Xi,$Xi
+ vaesenc $rndkey,$inout3,$inout3
+ mov %r13,0x50+8(%rsp)
+ vaesenc $rndkey,$inout4,$inout4
+ mov %r12,0x58+8(%rsp)
+ vpxor $Z1,$Z2,$Z2
+ vaesenc $rndkey,$inout5,$inout5
+ vpxor $T1,$Z2,$Z2
+
+ vmovups 0x70-0x80($key),$rndkey
+ vpslldq \$8,$Z2,$Z1
+ vpxor $T2,$Z0,$Z0
+ vmovdqu 0x10($const),$Hkey # .Lpoly
+
+ vaesenc $rndkey,$inout0,$inout0
+ vpxor $Xi,$Z3,$Z3
+ vaesenc $rndkey,$inout1,$inout1
+ vpxor $Z1,$Z0,$Z0
+ movbe 0x18($in0),%r13
+ vaesenc $rndkey,$inout2,$inout2
+ movbe 0x10($in0),%r12
+ vpalignr \$8,$Z0,$Z0,$Ii # 1st phase
+ vpclmulqdq \$0x10,$Hkey,$Z0,$Z0
+ mov %r13,0x60+8(%rsp)
+ vaesenc $rndkey,$inout3,$inout3
+ mov %r12,0x68+8(%rsp)
+ vaesenc $rndkey,$inout4,$inout4
+ vmovups 0x80-0x80($key),$T1 # borrow $T1 for $rndkey
+ vaesenc $rndkey,$inout5,$inout5
+
+ vaesenc $T1,$inout0,$inout0
+ vmovups 0x90-0x80($key),$rndkey
+ vaesenc $T1,$inout1,$inout1
+ vpsrldq \$8,$Z2,$Z2
+ vaesenc $T1,$inout2,$inout2
+ vpxor $Z2,$Z3,$Z3
+ vaesenc $T1,$inout3,$inout3
+ vpxor $Ii,$Z0,$Z0
+ movbe 0x08($in0),%r13
+ vaesenc $T1,$inout4,$inout4
+ movbe 0x00($in0),%r12
+ vaesenc $T1,$inout5,$inout5
+ vmovups 0xa0-0x80($key),$T1
+ cmp \$11,$rounds
+ jb .Lenc_tail # 128-bit key
+
+ vaesenc $rndkey,$inout0,$inout0
+ vaesenc $rndkey,$inout1,$inout1
+ vaesenc $rndkey,$inout2,$inout2
+ vaesenc $rndkey,$inout3,$inout3
+ vaesenc $rndkey,$inout4,$inout4
+ vaesenc $rndkey,$inout5,$inout5
+
+ vaesenc $T1,$inout0,$inout0
+ vaesenc $T1,$inout1,$inout1
+ vaesenc $T1,$inout2,$inout2
+ vaesenc $T1,$inout3,$inout3
+ vaesenc $T1,$inout4,$inout4
+ vmovups 0xb0-0x80($key),$rndkey
+ vaesenc $T1,$inout5,$inout5
+ vmovups 0xc0-0x80($key),$T1
+ je .Lenc_tail # 192-bit key
+
+ vaesenc $rndkey,$inout0,$inout0
+ vaesenc $rndkey,$inout1,$inout1
+ vaesenc $rndkey,$inout2,$inout2
+ vaesenc $rndkey,$inout3,$inout3
+ vaesenc $rndkey,$inout4,$inout4
+ vaesenc $rndkey,$inout5,$inout5
+
+ vaesenc $T1,$inout0,$inout0
+ vaesenc $T1,$inout1,$inout1
+ vaesenc $T1,$inout2,$inout2
+ vaesenc $T1,$inout3,$inout3
+ vaesenc $T1,$inout4,$inout4
+ vmovups 0xd0-0x80($key),$rndkey
+ vaesenc $T1,$inout5,$inout5
+ vmovups 0xe0-0x80($key),$T1
+ jmp .Lenc_tail # 256-bit key
+
+.align 32
+.Lhandle_ctr32:
+ vmovdqu ($const),$Ii # borrow $Ii for .Lbswap_mask
+ vpshufb $Ii,$T1,$Z2 # byte-swap counter
+ vmovdqu 0x30($const),$Z1 # borrow $Z1, .Ltwo_lsb
+ vpaddd 0x40($const),$Z2,$inout1 # .Lone_lsb
+ vpaddd $Z1,$Z2,$inout2
+ vmovdqu 0x00-0x20($Xip),$Hkey # $Hkey^1
+ vpaddd $Z1,$inout1,$inout3
+ vpshufb $Ii,$inout1,$inout1
+ vpaddd $Z1,$inout2,$inout4
+ vpshufb $Ii,$inout2,$inout2
+ vpxor $rndkey,$inout1,$inout1
+ vpaddd $Z1,$inout3,$inout5
+ vpshufb $Ii,$inout3,$inout3
+ vpxor $rndkey,$inout2,$inout2
+ vpaddd $Z1,$inout4,$T1 # byte-swapped next counter value
+ vpshufb $Ii,$inout4,$inout4
+ vpshufb $Ii,$inout5,$inout5
+ vpshufb $Ii,$T1,$T1 # next counter value
+ jmp .Lresume_ctr32
+
+.align 32
+.Lenc_tail:
+ vaesenc $rndkey,$inout0,$inout0
+ vmovdqu $Z3,16+8(%rsp) # postpone vpxor $Z3,$Xi,$Xi
+ vpalignr \$8,$Z0,$Z0,$Xi # 2nd phase
+ vaesenc $rndkey,$inout1,$inout1
+ vpclmulqdq \$0x10,$Hkey,$Z0,$Z0
+ vpxor 0x00($inp),$T1,$T2
+ vaesenc $rndkey,$inout2,$inout2
+ vpxor 0x10($inp),$T1,$Ii
+ vaesenc $rndkey,$inout3,$inout3
+ vpxor 0x20($inp),$T1,$Z1
+ vaesenc $rndkey,$inout4,$inout4
+ vpxor 0x30($inp),$T1,$Z2
+ vaesenc $rndkey,$inout5,$inout5
+ vpxor 0x40($inp),$T1,$Z3
+ vpxor 0x50($inp),$T1,$Hkey
+ vmovdqu ($ivp),$T1 # load next counter value
+
+ vaesenclast $T2,$inout0,$inout0
+ vmovdqu 0x20($const),$T2 # borrow $T2, .Lone_msb
+ vaesenclast $Ii,$inout1,$inout1
+ vpaddb $T2,$T1,$Ii
+ mov %r13,0x70+8(%rsp)
+ lea 0x60($inp),$inp
+ vaesenclast $Z1,$inout2,$inout2
+ vpaddb $T2,$Ii,$Z1
+ mov %r12,0x78+8(%rsp)
+ lea 0x60($out),$out
+ vmovdqu 0x00-0x80($key),$rndkey
+ vaesenclast $Z2,$inout3,$inout3
+ vpaddb $T2,$Z1,$Z2
+ vaesenclast $Z3, $inout4,$inout4
+ vpaddb $T2,$Z2,$Z3
+ vaesenclast $Hkey,$inout5,$inout5
+ vpaddb $T2,$Z3,$Hkey
+
+ add \$0x60,$ret
+ sub \$0x6,$len
+ jc .L6x_done
+
+ vmovups $inout0,-0x60($out) # save output
+ vpxor $rndkey,$T1,$inout0
+ vmovups $inout1,-0x50($out)
+ vmovdqa $Ii,$inout1 # 0 latency
+ vmovups $inout2,-0x40($out)
+ vmovdqa $Z1,$inout2 # 0 latency
+ vmovups $inout3,-0x30($out)
+ vmovdqa $Z2,$inout3 # 0 latency
+ vmovups $inout4,-0x20($out)
+ vmovdqa $Z3,$inout4 # 0 latency
+ vmovups $inout5,-0x10($out)
+ vmovdqa $Hkey,$inout5 # 0 latency
+ vmovdqu 0x20+8(%rsp),$Z3 # I[5]
+ jmp .Loop6x
+
+.L6x_done:
+ vpxor 16+8(%rsp),$Xi,$Xi # modulo-scheduled
+ vpxor $Z0,$Xi,$Xi # modulo-scheduled
+
+ ret
+.size _aesni_ctr32_ghash_6x,.-_aesni_ctr32_ghash_6x
+___
+######################################################################
+#
+# size_t aesni_gcm_[en|de]crypt(const void *inp, void *out, size_t len,
+# const AES_KEY *key, unsigned char iv[16],
+# struct { u128 Xi,H,Htbl[9]; } *Xip);
+$code.=<<___;
+.globl aesni_gcm_decrypt
+.type aesni_gcm_decrypt,\@function,6
+.align 32
+aesni_gcm_decrypt:
+ xor $ret,$ret
+ cmp \$0x60,$len # minimal accepted length
+ jb .Lgcm_dec_abort
+
+ lea (%rsp),%rax # save stack pointer
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+___
+$code.=<<___ if ($win64);
+ lea -0xa8(%rsp),%rsp
+ movaps %xmm6,-0xd8(%rax)
+ movaps %xmm7,-0xc8(%rax)
+ movaps %xmm8,-0xb8(%rax)
+ movaps %xmm9,-0xa8(%rax)
+ movaps %xmm10,-0x98(%rax)
+ movaps %xmm11,-0x88(%rax)
+ movaps %xmm12,-0x78(%rax)
+ movaps %xmm13,-0x68(%rax)
+ movaps %xmm14,-0x58(%rax)
+ movaps %xmm15,-0x48(%rax)
+.Lgcm_dec_body:
+___
+$code.=<<___;
+ vzeroupper
+
+ vmovdqu ($ivp),$T1 # input counter value
+ add \$-128,%rsp
+ mov 12($ivp),$counter
+ lea .Lbswap_mask(%rip),$const
+ lea -0x80($key),$in0 # borrow $in0
+ mov \$0xf80,$end0 # borrow $end0
+ vmovdqu ($Xip),$Xi # load Xi
+ and \$-128,%rsp # ensure stack alignment
+ vmovdqu ($const),$Ii # borrow $Ii for .Lbswap_mask
+ lea 0x80($key),$key # size optimization
+ lea 0x20+0x20($Xip),$Xip # size optimization
+ mov 0xf0-0x80($key),$rounds
+ vpshufb $Ii,$Xi,$Xi
+
+ and $end0,$in0
+ and %rsp,$end0
+ sub $in0,$end0
+ jc .Ldec_no_key_aliasing
+ cmp \$768,$end0
+ jnc .Ldec_no_key_aliasing
+ sub $end0,%rsp # avoid aliasing with key
+.Ldec_no_key_aliasing:
+
+ vmovdqu 0x50($inp),$Z3 # I[5]
+ lea ($inp),$in0
+ vmovdqu 0x40($inp),$Z0
+ lea -0xc0($inp,$len),$end0
+ vmovdqu 0x30($inp),$Z1
+ shr \$4,$len
+ xor $ret,$ret
+ vmovdqu 0x20($inp),$Z2
+ vpshufb $Ii,$Z3,$Z3 # passed to _aesni_ctr32_ghash_6x
+ vmovdqu 0x10($inp),$T2
+ vpshufb $Ii,$Z0,$Z0
+ vmovdqu ($inp),$Hkey
+ vpshufb $Ii,$Z1,$Z1
+ vmovdqu $Z0,0x30(%rsp)
+ vpshufb $Ii,$Z2,$Z2
+ vmovdqu $Z1,0x40(%rsp)
+ vpshufb $Ii,$T2,$T2
+ vmovdqu $Z2,0x50(%rsp)
+ vpshufb $Ii,$Hkey,$Hkey
+ vmovdqu $T2,0x60(%rsp)
+ vmovdqu $Hkey,0x70(%rsp)
+
+ call _aesni_ctr32_ghash_6x
+
+ vmovups $inout0,-0x60($out) # save output
+ vmovups $inout1,-0x50($out)
+ vmovups $inout2,-0x40($out)
+ vmovups $inout3,-0x30($out)
+ vmovups $inout4,-0x20($out)
+ vmovups $inout5,-0x10($out)
+
+ vpshufb ($const),$Xi,$Xi # .Lbswap_mask
+ vmovdqu $Xi,-0x40($Xip) # output Xi
+
+ vzeroupper
+___
+$code.=<<___ if ($win64);
+ movaps -0xd8(%rax),%xmm6
+ movaps -0xd8(%rax),%xmm7
+ movaps -0xb8(%rax),%xmm8
+ movaps -0xa8(%rax),%xmm9
+ movaps -0x98(%rax),%xmm10
+ movaps -0x88(%rax),%xmm11
+ movaps -0x78(%rax),%xmm12
+ movaps -0x68(%rax),%xmm13
+ movaps -0x58(%rax),%xmm14
+ movaps -0x48(%rax),%xmm15
+___
+$code.=<<___;
+ mov -48(%rax),%r15
+ mov -40(%rax),%r14
+ mov -32(%rax),%r13
+ mov -24(%rax),%r12
+ mov -16(%rax),%rbp
+ mov -8(%rax),%rbx
+ lea (%rax),%rsp # restore %rsp
+.Lgcm_dec_abort:
+ mov $ret,%rax # return value
+ ret
+.size aesni_gcm_decrypt,.-aesni_gcm_decrypt
+___
+
+$code.=<<___;
+.type _aesni_ctr32_6x,\@abi-omnipotent
+.align 32
+_aesni_ctr32_6x:
+ vmovdqu 0x00-0x80($key),$Z0 # borrow $Z0 for $rndkey
+ vmovdqu 0x20($const),$T2 # borrow $T2, .Lone_msb
+ lea -1($rounds),%r13
+ vmovups 0x10-0x80($key),$rndkey
+ lea 0x20-0x80($key),%r12
+ vpxor $Z0,$T1,$inout0
+ add \$`6<<24`,$counter
+ jc .Lhandle_ctr32_2
+ vpaddb $T2,$T1,$inout1
+ vpaddb $T2,$inout1,$inout2
+ vpxor $Z0,$inout1,$inout1
+ vpaddb $T2,$inout2,$inout3
+ vpxor $Z0,$inout2,$inout2
+ vpaddb $T2,$inout3,$inout4
+ vpxor $Z0,$inout3,$inout3
+ vpaddb $T2,$inout4,$inout5
+ vpxor $Z0,$inout4,$inout4
+ vpaddb $T2,$inout5,$T1
+ vpxor $Z0,$inout5,$inout5
+ jmp .Loop_ctr32
+
+.align 16
+.Loop_ctr32:
+ vaesenc $rndkey,$inout0,$inout0
+ vaesenc $rndkey,$inout1,$inout1
+ vaesenc $rndkey,$inout2,$inout2
+ vaesenc $rndkey,$inout3,$inout3
+ vaesenc $rndkey,$inout4,$inout4
+ vaesenc $rndkey,$inout5,$inout5
+ vmovups (%r12),$rndkey
+ lea 0x10(%r12),%r12
+ dec %r13d
+ jnz .Loop_ctr32
+
+ vmovdqu (%r12),$Hkey # last round key
+ vaesenc $rndkey,$inout0,$inout0
+ vpxor 0x00($inp),$Hkey,$Z0
+ vaesenc $rndkey,$inout1,$inout1
+ vpxor 0x10($inp),$Hkey,$Z1
+ vaesenc $rndkey,$inout2,$inout2
+ vpxor 0x20($inp),$Hkey,$Z2
+ vaesenc $rndkey,$inout3,$inout3
+ vpxor 0x30($inp),$Hkey,$Xi
+ vaesenc $rndkey,$inout4,$inout4
+ vpxor 0x40($inp),$Hkey,$T2
+ vaesenc $rndkey,$inout5,$inout5
+ vpxor 0x50($inp),$Hkey,$Hkey
+ lea 0x60($inp),$inp
+
+ vaesenclast $Z0,$inout0,$inout0
+ vaesenclast $Z1,$inout1,$inout1
+ vaesenclast $Z2,$inout2,$inout2
+ vaesenclast $Xi,$inout3,$inout3
+ vaesenclast $T2,$inout4,$inout4
+ vaesenclast $Hkey,$inout5,$inout5
+ vmovups $inout0,0x00($out)
+ vmovups $inout1,0x10($out)
+ vmovups $inout2,0x20($out)
+ vmovups $inout3,0x30($out)
+ vmovups $inout4,0x40($out)
+ vmovups $inout5,0x50($out)
+ lea 0x60($out),$out
+
+ ret
+.align 32
+.Lhandle_ctr32_2:
+ vpshufb $Ii,$T1,$Z2 # byte-swap counter
+ vmovdqu 0x30($const),$Z1 # borrow $Z1, .Ltwo_lsb
+ vpaddd 0x40($const),$Z2,$inout1 # .Lone_lsb
+ vpaddd $Z1,$Z2,$inout2
+ vpaddd $Z1,$inout1,$inout3
+ vpshufb $Ii,$inout1,$inout1
+ vpaddd $Z1,$inout2,$inout4
+ vpshufb $Ii,$inout2,$inout2
+ vpxor $Z0,$inout1,$inout1
+ vpaddd $Z1,$inout3,$inout5
+ vpshufb $Ii,$inout3,$inout3
+ vpxor $Z0,$inout2,$inout2
+ vpaddd $Z1,$inout4,$T1 # byte-swapped next counter value
+ vpshufb $Ii,$inout4,$inout4
+ vpxor $Z0,$inout3,$inout3
+ vpshufb $Ii,$inout5,$inout5
+ vpxor $Z0,$inout4,$inout4
+ vpshufb $Ii,$T1,$T1 # next counter value
+ vpxor $Z0,$inout5,$inout5
+ jmp .Loop_ctr32
+.size _aesni_ctr32_6x,.-_aesni_ctr32_6x
+
+.globl aesni_gcm_encrypt
+.type aesni_gcm_encrypt,\@function,6
+.align 32
+aesni_gcm_encrypt:
+ xor $ret,$ret
+ cmp \$0x60*3,$len # minimal accepted length
+ jb .Lgcm_enc_abort
+
+ lea (%rsp),%rax # save stack pointer
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+___
+$code.=<<___ if ($win64);
+ lea -0xa8(%rsp),%rsp
+ movaps %xmm6,-0xd8(%rax)
+ movaps %xmm7,-0xc8(%rax)
+ movaps %xmm8,-0xb8(%rax)
+ movaps %xmm9,-0xa8(%rax)
+ movaps %xmm10,-0x98(%rax)
+ movaps %xmm11,-0x88(%rax)
+ movaps %xmm12,-0x78(%rax)
+ movaps %xmm13,-0x68(%rax)
+ movaps %xmm14,-0x58(%rax)
+ movaps %xmm15,-0x48(%rax)
+.Lgcm_enc_body:
+___
+$code.=<<___;
+ vzeroupper
+
+ vmovdqu ($ivp),$T1 # input counter value
+ add \$-128,%rsp
+ mov 12($ivp),$counter
+ lea .Lbswap_mask(%rip),$const
+ lea -0x80($key),$in0 # borrow $in0
+ mov \$0xf80,$end0 # borrow $end0
+ lea 0x80($key),$key # size optimization
+ vmovdqu ($const),$Ii # borrow $Ii for .Lbswap_mask
+ and \$-128,%rsp # ensure stack alignment
+ mov 0xf0-0x80($key),$rounds
+
+ and $end0,$in0
+ and %rsp,$end0
+ sub $in0,$end0
+ jc .Lenc_no_key_aliasing
+ cmp \$768,$end0
+ jnc .Lenc_no_key_aliasing
+ sub $end0,%rsp # avoid aliasing with key
+.Lenc_no_key_aliasing:
+
+ lea ($out),$in0
+ lea -0xc0($out,$len),$end0
+ shr \$4,$len
+
+ call _aesni_ctr32_6x
+ vpshufb $Ii,$inout0,$Xi # save bswapped output on stack
+ vpshufb $Ii,$inout1,$T2
+ vmovdqu $Xi,0x70(%rsp)
+ vpshufb $Ii,$inout2,$Z0
+ vmovdqu $T2,0x60(%rsp)
+ vpshufb $Ii,$inout3,$Z1
+ vmovdqu $Z0,0x50(%rsp)
+ vpshufb $Ii,$inout4,$Z2
+ vmovdqu $Z1,0x40(%rsp)
+ vpshufb $Ii,$inout5,$Z3 # passed to _aesni_ctr32_ghash_6x
+ vmovdqu $Z2,0x30(%rsp)
+
+ call _aesni_ctr32_6x
+
+ vmovdqu ($Xip),$Xi # load Xi
+ lea 0x20+0x20($Xip),$Xip # size optimization
+ sub \$12,$len
+ mov \$0x60*2,$ret
+ vpshufb $Ii,$Xi,$Xi
+
+ call _aesni_ctr32_ghash_6x
+ vmovdqu 0x20(%rsp),$Z3 # I[5]
+ vmovdqu ($const),$Ii # borrow $Ii for .Lbswap_mask
+ vmovdqu 0x00-0x20($Xip),$Hkey # $Hkey^1
+ vpunpckhqdq $Z3,$Z3,$T1
+ vmovdqu 0x20-0x20($Xip),$rndkey # borrow $rndkey for $HK
+ vmovups $inout0,-0x60($out) # save output
+ vpshufb $Ii,$inout0,$inout0 # but keep bswapped copy
+ vpxor $Z3,$T1,$T1
+ vmovups $inout1,-0x50($out)
+ vpshufb $Ii,$inout1,$inout1
+ vmovups $inout2,-0x40($out)
+ vpshufb $Ii,$inout2,$inout2
+ vmovups $inout3,-0x30($out)
+ vpshufb $Ii,$inout3,$inout3
+ vmovups $inout4,-0x20($out)
+ vpshufb $Ii,$inout4,$inout4
+ vmovups $inout5,-0x10($out)
+ vpshufb $Ii,$inout5,$inout5
+ vmovdqu $inout0,0x10(%rsp) # free $inout0
+___
+{ my ($HK,$T3)=($rndkey,$inout0);
+
+$code.=<<___;
+ vmovdqu 0x30(%rsp),$Z2 # I[4]
+ vmovdqu 0x10-0x20($Xip),$Ii # borrow $Ii for $Hkey^2
+ vpunpckhqdq $Z2,$Z2,$T2
+ vpclmulqdq \$0x00,$Hkey,$Z3,$Z1
+ vpxor $Z2,$T2,$T2
+ vpclmulqdq \$0x11,$Hkey,$Z3,$Z3
+ vpclmulqdq \$0x00,$HK,$T1,$T1
+
+ vmovdqu 0x40(%rsp),$T3 # I[3]
+ vpclmulqdq \$0x00,$Ii,$Z2,$Z0
+ vmovdqu 0x30-0x20($Xip),$Hkey # $Hkey^3
+ vpxor $Z1,$Z0,$Z0
+ vpunpckhqdq $T3,$T3,$Z1
+ vpclmulqdq \$0x11,$Ii,$Z2,$Z2
+ vpxor $T3,$Z1,$Z1
+ vpxor $Z3,$Z2,$Z2
+ vpclmulqdq \$0x10,$HK,$T2,$T2
+ vmovdqu 0x50-0x20($Xip),$HK
+ vpxor $T1,$T2,$T2
+
+ vmovdqu 0x50(%rsp),$T1 # I[2]
+ vpclmulqdq \$0x00,$Hkey,$T3,$Z3
+ vmovdqu 0x40-0x20($Xip),$Ii # borrow $Ii for $Hkey^4
+ vpxor $Z0,$Z3,$Z3
+ vpunpckhqdq $T1,$T1,$Z0
+ vpclmulqdq \$0x11,$Hkey,$T3,$T3
+ vpxor $T1,$Z0,$Z0
+ vpxor $Z2,$T3,$T3
+ vpclmulqdq \$0x00,$HK,$Z1,$Z1
+ vpxor $T2,$Z1,$Z1
+
+ vmovdqu 0x60(%rsp),$T2 # I[1]
+ vpclmulqdq \$0x00,$Ii,$T1,$Z2
+ vmovdqu 0x60-0x20($Xip),$Hkey # $Hkey^5
+ vpxor $Z3,$Z2,$Z2
+ vpunpckhqdq $T2,$T2,$Z3
+ vpclmulqdq \$0x11,$Ii,$T1,$T1
+ vpxor $T2,$Z3,$Z3
+ vpxor $T3,$T1,$T1
+ vpclmulqdq \$0x10,$HK,$Z0,$Z0
+ vmovdqu 0x80-0x20($Xip),$HK
+ vpxor $Z1,$Z0,$Z0
+
+ vpxor 0x70(%rsp),$Xi,$Xi # accumulate I[0]
+ vpclmulqdq \$0x00,$Hkey,$T2,$Z1
+ vmovdqu 0x70-0x20($Xip),$Ii # borrow $Ii for $Hkey^6
+ vpunpckhqdq $Xi,$Xi,$T3
+ vpxor $Z2,$Z1,$Z1
+ vpclmulqdq \$0x11,$Hkey,$T2,$T2
+ vpxor $Xi,$T3,$T3
+ vpxor $T1,$T2,$T2
+ vpclmulqdq \$0x00,$HK,$Z3,$Z3
+ vpxor $Z0,$Z3,$Z0
+
+ vpclmulqdq \$0x00,$Ii,$Xi,$Z2
+ vmovdqu 0x00-0x20($Xip),$Hkey # $Hkey^1
+ vpunpckhqdq $inout5,$inout5,$T1
+ vpclmulqdq \$0x11,$Ii,$Xi,$Xi
+ vpxor $inout5,$T1,$T1
+ vpxor $Z1,$Z2,$Z1
+ vpclmulqdq \$0x10,$HK,$T3,$T3
+ vmovdqu 0x20-0x20($Xip),$HK
+ vpxor $T2,$Xi,$Z3
+ vpxor $Z0,$T3,$Z2
+
+ vmovdqu 0x10-0x20($Xip),$Ii # borrow $Ii for $Hkey^2
+ vpxor $Z1,$Z3,$T3 # aggregated Karatsuba post-processing
+ vpclmulqdq \$0x00,$Hkey,$inout5,$Z0
+ vpxor $T3,$Z2,$Z2
+ vpunpckhqdq $inout4,$inout4,$T2
+ vpclmulqdq \$0x11,$Hkey,$inout5,$inout5
+ vpxor $inout4,$T2,$T2
+ vpslldq \$8,$Z2,$T3
+ vpclmulqdq \$0x00,$HK,$T1,$T1
+ vpxor $T3,$Z1,$Xi
+ vpsrldq \$8,$Z2,$Z2
+ vpxor $Z2,$Z3,$Z3
+
+ vpclmulqdq \$0x00,$Ii,$inout4,$Z1
+ vmovdqu 0x30-0x20($Xip),$Hkey # $Hkey^3
+ vpxor $Z0,$Z1,$Z1
+ vpunpckhqdq $inout3,$inout3,$T3
+ vpclmulqdq \$0x11,$Ii,$inout4,$inout4
+ vpxor $inout3,$T3,$T3
+ vpxor $inout5,$inout4,$inout4
+ vpalignr \$8,$Xi,$Xi,$inout5 # 1st phase
+ vpclmulqdq \$0x10,$HK,$T2,$T2
+ vmovdqu 0x50-0x20($Xip),$HK
+ vpxor $T1,$T2,$T2
+
+ vpclmulqdq \$0x00,$Hkey,$inout3,$Z0
+ vmovdqu 0x40-0x20($Xip),$Ii # borrow $Ii for $Hkey^4
+ vpxor $Z1,$Z0,$Z0
+ vpunpckhqdq $inout2,$inout2,$T1
+ vpclmulqdq \$0x11,$Hkey,$inout3,$inout3
+ vpxor $inout2,$T1,$T1
+ vpxor $inout4,$inout3,$inout3
+ vxorps 0x10(%rsp),$Z3,$Z3 # accumulate $inout0
+ vpclmulqdq \$0x00,$HK,$T3,$T3
+ vpxor $T2,$T3,$T3
+
+ vpclmulqdq \$0x10,0x10($const),$Xi,$Xi
+ vxorps $inout5,$Xi,$Xi
+
+ vpclmulqdq \$0x00,$Ii,$inout2,$Z1
+ vmovdqu 0x60-0x20($Xip),$Hkey # $Hkey^5
+ vpxor $Z0,$Z1,$Z1
+ vpunpckhqdq $inout1,$inout1,$T2
+ vpclmulqdq \$0x11,$Ii,$inout2,$inout2
+ vpxor $inout1,$T2,$T2
+ vpalignr \$8,$Xi,$Xi,$inout5 # 2nd phase
+ vpxor $inout3,$inout2,$inout2
+ vpclmulqdq \$0x10,$HK,$T1,$T1
+ vmovdqu 0x80-0x20($Xip),$HK
+ vpxor $T3,$T1,$T1
+
+ vxorps $Z3,$inout5,$inout5
+ vpclmulqdq \$0x10,0x10($const),$Xi,$Xi
+ vxorps $inout5,$Xi,$Xi
+
+ vpclmulqdq \$0x00,$Hkey,$inout1,$Z0
+ vmovdqu 0x70-0x20($Xip),$Ii # borrow $Ii for $Hkey^6
+ vpxor $Z1,$Z0,$Z0
+ vpunpckhqdq $Xi,$Xi,$T3
+ vpclmulqdq \$0x11,$Hkey,$inout1,$inout1
+ vpxor $Xi,$T3,$T3
+ vpxor $inout2,$inout1,$inout1
+ vpclmulqdq \$0x00,$HK,$T2,$T2
+ vpxor $T1,$T2,$T2
+
+ vpclmulqdq \$0x00,$Ii,$Xi,$Z1
+ vpclmulqdq \$0x11,$Ii,$Xi,$Z3
+ vpxor $Z0,$Z1,$Z1
+ vpclmulqdq \$0x10,$HK,$T3,$Z2
+ vpxor $inout1,$Z3,$Z3
+ vpxor $T2,$Z2,$Z2
+
+ vpxor $Z1,$Z3,$Z0 # aggregated Karatsuba post-processing
+ vpxor $Z0,$Z2,$Z2
+ vpslldq \$8,$Z2,$T1
+ vmovdqu 0x10($const),$Hkey # .Lpoly
+ vpsrldq \$8,$Z2,$Z2
+ vpxor $T1,$Z1,$Xi
+ vpxor $Z2,$Z3,$Z3
+
+ vpalignr \$8,$Xi,$Xi,$T2 # 1st phase
+ vpclmulqdq \$0x10,$Hkey,$Xi,$Xi
+ vpxor $T2,$Xi,$Xi
+
+ vpalignr \$8,$Xi,$Xi,$T2 # 2nd phase
+ vpclmulqdq \$0x10,$Hkey,$Xi,$Xi
+ vpxor $Z3,$T2,$T2
+ vpxor $T2,$Xi,$Xi
+___
+}
+$code.=<<___;
+ vpshufb ($const),$Xi,$Xi # .Lbswap_mask
+ vmovdqu $Xi,-0x40($Xip) # output Xi
+
+ vzeroupper
+___
+$code.=<<___ if ($win64);
+ movaps -0xd8(%rax),%xmm6
+ movaps -0xc8(%rax),%xmm7
+ movaps -0xb8(%rax),%xmm8
+ movaps -0xa8(%rax),%xmm9
+ movaps -0x98(%rax),%xmm10
+ movaps -0x88(%rax),%xmm11
+ movaps -0x78(%rax),%xmm12
+ movaps -0x68(%rax),%xmm13
+ movaps -0x58(%rax),%xmm14
+ movaps -0x48(%rax),%xmm15
+___
+$code.=<<___;
+ mov -48(%rax),%r15
+ mov -40(%rax),%r14
+ mov -32(%rax),%r13
+ mov -24(%rax),%r12
+ mov -16(%rax),%rbp
+ mov -8(%rax),%rbx
+ lea (%rax),%rsp # restore %rsp
+.Lgcm_enc_abort:
+ mov $ret,%rax # return value
+ ret
+.size aesni_gcm_encrypt,.-aesni_gcm_encrypt
+___
+
+$code.=<<___;
+.align 64
+.Lbswap_mask:
+ .byte 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0
+.Lpoly:
+ .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xc2
+.Lone_msb:
+ .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
+.Ltwo_lsb:
+ .byte 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+.Lone_lsb:
+ .byte 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+.asciz "AES-NI GCM module for x86_64, CRYPTOGAMS by <appro\@openssl.org>"
+.align 64
+___
+if ($win64) {
+$rec="%rcx";
+$frame="%rdx";
+$context="%r8";
+$disp="%r9";
+
+$code.=<<___
+.extern __imp_RtlVirtualUnwind
+.type gcm_se_handler,\@abi-omnipotent
+.align 16
+gcm_se_handler:
+ push %rsi
+ push %rdi
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+ pushfq
+ sub \$64,%rsp
+
+ mov 120($context),%rax # pull context->Rax
+ mov 248($context),%rbx # pull context->Rip
+
+ mov 8($disp),%rsi # disp->ImageBase
+ mov 56($disp),%r11 # disp->HandlerData
+
+ mov 0(%r11),%r10d # HandlerData[0]
+ lea (%rsi,%r10),%r10 # prologue label
+ cmp %r10,%rbx # context->Rip<prologue label
+ jb .Lcommon_seh_tail
+
+ mov 152($context),%rax # pull context->Rsp
+
+ mov 4(%r11),%r10d # HandlerData[1]
+ lea (%rsi,%r10),%r10 # epilogue label
+ cmp %r10,%rbx # context->Rip>=epilogue label
+ jae .Lcommon_seh_tail
+
+ mov 120($context),%rax # pull context->Rax
+
+ mov -48(%rax),%r15
+ mov -40(%rax),%r14
+ mov -32(%rax),%r13
+ mov -24(%rax),%r12
+ mov -16(%rax),%rbp
+ mov -8(%rax),%rbx
+ mov %r15,240($context)
+ mov %r14,232($context)
+ mov %r13,224($context)
+ mov %r12,216($context)
+ mov %rbp,160($context)
+ mov %rbx,144($context)
+
+ lea -0xd8(%rax),%rsi # %xmm save area
+ lea 512($context),%rdi # & context.Xmm6
+ mov \$20,%ecx # 10*sizeof(%xmm0)/sizeof(%rax)
+ .long 0xa548f3fc # cld; rep movsq
+
+.Lcommon_seh_tail:
+ mov 8(%rax),%rdi
+ mov 16(%rax),%rsi
+ mov %rax,152($context) # restore context->Rsp
+ mov %rsi,168($context) # restore context->Rsi
+ mov %rdi,176($context) # restore context->Rdi
+
+ mov 40($disp),%rdi # disp->ContextRecord
+ mov $context,%rsi # context
+ mov \$154,%ecx # sizeof(CONTEXT)
+ .long 0xa548f3fc # cld; rep movsq
+
+ mov $disp,%rsi
+ xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER
+ mov 8(%rsi),%rdx # arg2, disp->ImageBase
+ mov 0(%rsi),%r8 # arg3, disp->ControlPc
+ mov 16(%rsi),%r9 # arg4, disp->FunctionEntry
+ mov 40(%rsi),%r10 # disp->ContextRecord
+ lea 56(%rsi),%r11 # &disp->HandlerData
+ lea 24(%rsi),%r12 # &disp->EstablisherFrame
+ mov %r10,32(%rsp) # arg5
+ mov %r11,40(%rsp) # arg6
+ mov %r12,48(%rsp) # arg7
+ mov %rcx,56(%rsp) # arg8, (NULL)
+ call *__imp_RtlVirtualUnwind(%rip)
+
+ mov \$1,%eax # ExceptionContinueSearch
+ add \$64,%rsp
+ popfq
+ pop %r15
+ pop %r14
+ pop %r13
+ pop %r12
+ pop %rbp
+ pop %rbx
+ pop %rdi
+ pop %rsi
+ ret
+.size gcm_se_handler,.-gcm_se_handler
+
+.section .pdata
+.align 4
+ .rva .LSEH_begin_aesni_gcm_decrypt
+ .rva .LSEH_end_aesni_gcm_decrypt
+ .rva .LSEH_gcm_dec_info
+
+ .rva .LSEH_begin_aesni_gcm_encrypt
+ .rva .LSEH_end_aesni_gcm_encrypt
+ .rva .LSEH_gcm_enc_info
+.section .xdata
+.align 8
+.LSEH_gcm_dec_info:
+ .byte 9,0,0,0
+ .rva gcm_se_handler
+ .rva .Lgcm_dec_body,.Lgcm_dec_abort
+.LSEH_gcm_enc_info:
+ .byte 9,0,0,0
+ .rva gcm_se_handler
+ .rva .Lgcm_enc_body,.Lgcm_enc_abort
+___
+}
+}}} else {{{
+$code=<<___; # assembler is too old
+.text
+
+.globl aesni_gcm_encrypt
+.type aesni_gcm_encrypt,\@abi-omnipotent
+aesni_gcm_encrypt:
+ xor %eax,%eax
+ ret
+.size aesni_gcm_encrypt,.-aesni_gcm_encrypt
+
+.globl aesni_gcm_decrypt
+.type aesni_gcm_decrypt,\@abi-omnipotent
+aesni_gcm_decrypt:
+ xor %eax,%eax
+ ret
+.size aesni_gcm_decrypt,.-aesni_gcm_decrypt
+___
+}}}
+
+$code =~ s/\`([^\`]*)\`/eval($1)/gem;
+
+print $code;
+
+close STDOUT;
diff --git a/src/crypto/modes/asm/ghash-armv4.pl b/src/crypto/modes/asm/ghash-armv4.pl
new file mode 100644
index 0000000..b324641
--- /dev/null
+++ b/src/crypto/modes/asm/ghash-armv4.pl
@@ -0,0 +1,501 @@
+#!/usr/bin/env perl
+#
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+# project. The module is, however, dual licensed under OpenSSL and
+# CRYPTOGAMS licenses depending on where you obtain it. For further
+# details see http://www.openssl.org/~appro/cryptogams/.
+# ====================================================================
+#
+# April 2010
+#
+# The module implements "4-bit" GCM GHASH function and underlying
+# single multiplication operation in GF(2^128). "4-bit" means that it
+# uses 256 bytes per-key table [+32 bytes shared table]. There is no
+# experimental performance data available yet. The only approximation
+# that can be made at this point is based on code size. Inner loop is
+# 32 instructions long and on single-issue core should execute in <40
+# cycles. Having verified that gcc 3.4 didn't unroll corresponding
+# loop, this assembler loop body was found to be ~3x smaller than
+# compiler-generated one...
+#
+# July 2010
+#
+# Rescheduling for dual-issue pipeline resulted in 8.5% improvement on
+# Cortex A8 core and ~25 cycles per processed byte (which was observed
+# to be ~3 times faster than gcc-generated code:-)
+#
+# February 2011
+#
+# Profiler-assisted and platform-specific optimization resulted in 7%
+# improvement on Cortex A8 core and ~23.5 cycles per byte.
+#
+# March 2011
+#
+# Add NEON implementation featuring polynomial multiplication, i.e. no
+# lookup tables involved. On Cortex A8 it was measured to process one
+# byte in 15 cycles or 55% faster than integer-only code.
+#
+# April 2014
+#
+# Switch to multiplication algorithm suggested in paper referred
+# below and combine it with reduction algorithm from x86 module.
+# Performance improvement over previous version varies from 65% on
+# Snapdragon S4 to 110% on Cortex A9. In absolute terms Cortex A8
+# processes one byte in 8.45 cycles, A9 - in 10.2, Snapdragon S4 -
+# in 9.33.
+#
+# Câmara, D.; Gouvêa, C. P. L.; López, J. & Dahab, R.: Fast Software
+# Polynomial Multiplication on ARM Processors using the NEON Engine.
+#
+# http://conradoplg.cryptoland.net/files/2010/12/mocrysen13.pdf
+
+# ====================================================================
+# Note about "528B" variant. In ARM case it makes lesser sense to
+# implement it for following reasons:
+#
+# - performance improvement won't be anywhere near 50%, because 128-
+# bit shift operation is neatly fused with 128-bit xor here, and
+# "538B" variant would eliminate only 4-5 instructions out of 32
+# in the inner loop (meaning that estimated improvement is ~15%);
+# - ARM-based systems are often embedded ones and extra memory
+# consumption might be unappreciated (for so little improvement);
+#
+# Byte order [in]dependence. =========================================
+#
+# Caller is expected to maintain specific *dword* order in Htable,
+# namely with *least* significant dword of 128-bit value at *lower*
+# address. This differs completely from C code and has everything to
+# do with ldm instruction and order in which dwords are "consumed" by
+# algorithm. *Byte* order within these dwords in turn is whatever
+# *native* byte order on current platform. See gcm128.c for working
+# example...
+
+while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {}
+open STDOUT,">$output";
+
+$Xi="r0"; # argument block
+$Htbl="r1";
+$inp="r2";
+$len="r3";
+
+$Zll="r4"; # variables
+$Zlh="r5";
+$Zhl="r6";
+$Zhh="r7";
+$Tll="r8";
+$Tlh="r9";
+$Thl="r10";
+$Thh="r11";
+$nlo="r12";
+################# r13 is stack pointer
+$nhi="r14";
+################# r15 is program counter
+
+$rem_4bit=$inp; # used in gcm_gmult_4bit
+$cnt=$len;
+
+sub Zsmash() {
+ my $i=12;
+ my @args=@_;
+ for ($Zll,$Zlh,$Zhl,$Zhh) {
+ $code.=<<___;
+#if __ARM_ARCH__>=7 && defined(__ARMEL__)
+ rev $_,$_
+ str $_,[$Xi,#$i]
+#elif defined(__ARMEB__)
+ str $_,[$Xi,#$i]
+#else
+ mov $Tlh,$_,lsr#8
+ strb $_,[$Xi,#$i+3]
+ mov $Thl,$_,lsr#16
+ strb $Tlh,[$Xi,#$i+2]
+ mov $Thh,$_,lsr#24
+ strb $Thl,[$Xi,#$i+1]
+ strb $Thh,[$Xi,#$i]
+#endif
+___
+ $code.="\t".shift(@args)."\n";
+ $i-=4;
+ }
+}
+
+$code=<<___;
+#if defined(__arm__)
+#include "arm_arch.h"
+
+.syntax unified
+
+.text
+.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 $rem_4bit,pc,#8
+ sub $rem_4bit,$rem_4bit,#32 @ &rem_4bit
+ b .Lrem_4bit_got
+ nop
+.size rem_4bit_get,.-rem_4bit_get
+
+.global gcm_ghash_4bit
+.hidden gcm_ghash_4bit
+.type gcm_ghash_4bit,%function
+gcm_ghash_4bit:
+ sub r12,pc,#8
+ add $len,$inp,$len @ $len to point at the end
+ stmdb sp!,{r3-r11,lr} @ save $len/end too
+ sub r12,r12,#48 @ &rem_4bit
+
+ ldmia r12,{r4-r11} @ copy rem_4bit ...
+ stmdb sp!,{r4-r11} @ ... to stack
+
+ ldrb $nlo,[$inp,#15]
+ ldrb $nhi,[$Xi,#15]
+.Louter:
+ eor $nlo,$nlo,$nhi
+ and $nhi,$nlo,#0xf0
+ and $nlo,$nlo,#0x0f
+ mov $cnt,#14
+
+ add $Zhh,$Htbl,$nlo,lsl#4
+ ldmia $Zhh,{$Zll-$Zhh} @ load Htbl[nlo]
+ add $Thh,$Htbl,$nhi
+ ldrb $nlo,[$inp,#14]
+
+ and $nhi,$Zll,#0xf @ rem
+ ldmia $Thh,{$Tll-$Thh} @ load Htbl[nhi]
+ add $nhi,$nhi,$nhi
+ eor $Zll,$Tll,$Zll,lsr#4
+ ldrh $Tll,[sp,$nhi] @ rem_4bit[rem]
+ eor $Zll,$Zll,$Zlh,lsl#28
+ ldrb $nhi,[$Xi,#14]
+ eor $Zlh,$Tlh,$Zlh,lsr#4
+ eor $Zlh,$Zlh,$Zhl,lsl#28
+ eor $Zhl,$Thl,$Zhl,lsr#4
+ eor $Zhl,$Zhl,$Zhh,lsl#28
+ eor $Zhh,$Thh,$Zhh,lsr#4
+ eor $nlo,$nlo,$nhi
+ and $nhi,$nlo,#0xf0
+ and $nlo,$nlo,#0x0f
+ eor $Zhh,$Zhh,$Tll,lsl#16
+
+.Linner:
+ add $Thh,$Htbl,$nlo,lsl#4
+ and $nlo,$Zll,#0xf @ rem
+ subs $cnt,$cnt,#1
+ add $nlo,$nlo,$nlo
+ ldmia $Thh,{$Tll-$Thh} @ load Htbl[nlo]
+ eor $Zll,$Tll,$Zll,lsr#4
+ eor $Zll,$Zll,$Zlh,lsl#28
+ eor $Zlh,$Tlh,$Zlh,lsr#4
+ eor $Zlh,$Zlh,$Zhl,lsl#28
+ ldrh $Tll,[sp,$nlo] @ rem_4bit[rem]
+ eor $Zhl,$Thl,$Zhl,lsr#4
+ ldrbpl $nlo,[$inp,$cnt]
+ eor $Zhl,$Zhl,$Zhh,lsl#28
+ eor $Zhh,$Thh,$Zhh,lsr#4
+
+ add $Thh,$Htbl,$nhi
+ and $nhi,$Zll,#0xf @ rem
+ eor $Zhh,$Zhh,$Tll,lsl#16 @ ^= rem_4bit[rem]
+ add $nhi,$nhi,$nhi
+ ldmia $Thh,{$Tll-$Thh} @ load Htbl[nhi]
+ eor $Zll,$Tll,$Zll,lsr#4
+ ldrbpl $Tll,[$Xi,$cnt]
+ eor $Zll,$Zll,$Zlh,lsl#28
+ eor $Zlh,$Tlh,$Zlh,lsr#4
+ ldrh $Tlh,[sp,$nhi]
+ eor $Zlh,$Zlh,$Zhl,lsl#28
+ eor $Zhl,$Thl,$Zhl,lsr#4
+ eor $Zhl,$Zhl,$Zhh,lsl#28
+ eorpl $nlo,$nlo,$Tll
+ eor $Zhh,$Thh,$Zhh,lsr#4
+ andpl $nhi,$nlo,#0xf0
+ andpl $nlo,$nlo,#0x0f
+ eor $Zhh,$Zhh,$Tlh,lsl#16 @ ^= rem_4bit[rem]
+ bpl .Linner
+
+ ldr $len,[sp,#32] @ re-load $len/end
+ add $inp,$inp,#16
+ mov $nhi,$Zll
+___
+ &Zsmash("cmp\t$inp,$len","ldrbne\t$nlo,[$inp,#15]");
+$code.=<<___;
+ 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
+ bx lr @ interoperable with Thumb ISA:-)
+#endif
+.size gcm_ghash_4bit,.-gcm_ghash_4bit
+
+.global gcm_gmult_4bit
+.hidden gcm_gmult_4bit
+.type gcm_gmult_4bit,%function
+gcm_gmult_4bit:
+ stmdb sp!,{r4-r11,lr}
+ ldrb $nlo,[$Xi,#15]
+ b rem_4bit_get
+.Lrem_4bit_got:
+ and $nhi,$nlo,#0xf0
+ and $nlo,$nlo,#0x0f
+ mov $cnt,#14
+
+ add $Zhh,$Htbl,$nlo,lsl#4
+ ldmia $Zhh,{$Zll-$Zhh} @ load Htbl[nlo]
+ ldrb $nlo,[$Xi,#14]
+
+ add $Thh,$Htbl,$nhi
+ and $nhi,$Zll,#0xf @ rem
+ ldmia $Thh,{$Tll-$Thh} @ load Htbl[nhi]
+ add $nhi,$nhi,$nhi
+ eor $Zll,$Tll,$Zll,lsr#4
+ ldrh $Tll,[$rem_4bit,$nhi] @ rem_4bit[rem]
+ eor $Zll,$Zll,$Zlh,lsl#28
+ eor $Zlh,$Tlh,$Zlh,lsr#4
+ eor $Zlh,$Zlh,$Zhl,lsl#28
+ eor $Zhl,$Thl,$Zhl,lsr#4
+ eor $Zhl,$Zhl,$Zhh,lsl#28
+ eor $Zhh,$Thh,$Zhh,lsr#4
+ and $nhi,$nlo,#0xf0
+ eor $Zhh,$Zhh,$Tll,lsl#16
+ and $nlo,$nlo,#0x0f
+
+.Loop:
+ add $Thh,$Htbl,$nlo,lsl#4
+ and $nlo,$Zll,#0xf @ rem
+ subs $cnt,$cnt,#1
+ add $nlo,$nlo,$nlo
+ ldmia $Thh,{$Tll-$Thh} @ load Htbl[nlo]
+ eor $Zll,$Tll,$Zll,lsr#4
+ eor $Zll,$Zll,$Zlh,lsl#28
+ eor $Zlh,$Tlh,$Zlh,lsr#4
+ eor $Zlh,$Zlh,$Zhl,lsl#28
+ ldrh $Tll,[$rem_4bit,$nlo] @ rem_4bit[rem]
+ eor $Zhl,$Thl,$Zhl,lsr#4
+ ldrbpl $nlo,[$Xi,$cnt]
+ eor $Zhl,$Zhl,$Zhh,lsl#28
+ eor $Zhh,$Thh,$Zhh,lsr#4
+
+ add $Thh,$Htbl,$nhi
+ and $nhi,$Zll,#0xf @ rem
+ eor $Zhh,$Zhh,$Tll,lsl#16 @ ^= rem_4bit[rem]
+ add $nhi,$nhi,$nhi
+ ldmia $Thh,{$Tll-$Thh} @ load Htbl[nhi]
+ eor $Zll,$Tll,$Zll,lsr#4
+ eor $Zll,$Zll,$Zlh,lsl#28
+ eor $Zlh,$Tlh,$Zlh,lsr#4
+ ldrh $Tll,[$rem_4bit,$nhi] @ rem_4bit[rem]
+ eor $Zlh,$Zlh,$Zhl,lsl#28
+ eor $Zhl,$Thl,$Zhl,lsr#4
+ eor $Zhl,$Zhl,$Zhh,lsl#28
+ eor $Zhh,$Thh,$Zhh,lsr#4
+ andpl $nhi,$nlo,#0xf0
+ andpl $nlo,$nlo,#0x0f
+ eor $Zhh,$Zhh,$Tll,lsl#16 @ ^= rem_4bit[rem]
+ bpl .Loop
+___
+ &Zsmash();
+$code.=<<___;
+#if __ARM_ARCH__>=5
+ ldmia sp!,{r4-r11,pc}
+#else
+ ldmia sp!,{r4-r11,lr}
+ tst lr,#1
+ moveq pc,lr @ be binary compatible with V4, yet
+ bx lr @ interoperable with Thumb ISA:-)
+#endif
+.size gcm_gmult_4bit,.-gcm_gmult_4bit
+___
+{
+my ($Xl,$Xm,$Xh,$IN)=map("q$_",(0..3));
+my ($t0,$t1,$t2,$t3)=map("q$_",(8..12));
+my ($Hlo,$Hhi,$Hhl,$k48,$k32,$k16)=map("d$_",(26..31));
+
+sub clmul64x64 {
+my ($r,$a,$b)=@_;
+$code.=<<___;
+ vext.8 $t0#lo, $a, $a, #1 @ A1
+ vmull.p8 $t0, $t0#lo, $b @ F = A1*B
+ vext.8 $r#lo, $b, $b, #1 @ B1
+ vmull.p8 $r, $a, $r#lo @ E = A*B1
+ vext.8 $t1#lo, $a, $a, #2 @ A2
+ vmull.p8 $t1, $t1#lo, $b @ H = A2*B
+ vext.8 $t3#lo, $b, $b, #2 @ B2
+ vmull.p8 $t3, $a, $t3#lo @ G = A*B2
+ vext.8 $t2#lo, $a, $a, #3 @ A3
+ veor $t0, $t0, $r @ L = E + F
+ vmull.p8 $t2, $t2#lo, $b @ J = A3*B
+ vext.8 $r#lo, $b, $b, #3 @ B3
+ veor $t1, $t1, $t3 @ M = G + H
+ vmull.p8 $r, $a, $r#lo @ I = A*B3
+ veor $t0#lo, $t0#lo, $t0#hi @ t0 = (L) (P0 + P1) << 8
+ vand $t0#hi, $t0#hi, $k48
+ vext.8 $t3#lo, $b, $b, #4 @ B4
+ veor $t1#lo, $t1#lo, $t1#hi @ t1 = (M) (P2 + P3) << 16
+ vand $t1#hi, $t1#hi, $k32
+ vmull.p8 $t3, $a, $t3#lo @ K = A*B4
+ veor $t2, $t2, $r @ N = I + J
+ veor $t0#lo, $t0#lo, $t0#hi
+ veor $t1#lo, $t1#lo, $t1#hi
+ veor $t2#lo, $t2#lo, $t2#hi @ t2 = (N) (P4 + P5) << 24
+ vand $t2#hi, $t2#hi, $k16
+ vext.8 $t0, $t0, $t0, #15
+ veor $t3#lo, $t3#lo, $t3#hi @ t3 = (K) (P6 + P7) << 32
+ vmov.i64 $t3#hi, #0
+ vext.8 $t1, $t1, $t1, #14
+ veor $t2#lo, $t2#lo, $t2#hi
+ vmull.p8 $r, $a, $b @ D = A*B
+ vext.8 $t3, $t3, $t3, #12
+ vext.8 $t2, $t2, $t2, #13
+ veor $t0, $t0, $t1
+ veor $t2, $t2, $t3
+ veor $r, $r, $t0
+ veor $r, $r, $t2
+___
+}
+
+$code.=<<___;
+#if __ARM_ARCH__>=7
+.fpu neon
+
+.global gcm_init_neon
+.hidden gcm_init_neon
+.type gcm_init_neon,%function
+.align 4
+gcm_init_neon:
+ vld1.64 $IN#hi,[r1,:64]! @ load H
+ vmov.i8 $t0,#0xe1
+ vld1.64 $IN#lo,[r1,:64]
+ vshl.i64 $t0#hi,#57
+ vshr.u64 $t0#lo,#63 @ t0=0xc2....01
+ vdup.8 $t1,$IN#hi[7]
+ vshr.u64 $Hlo,$IN#lo,#63
+ vshr.s8 $t1,#7 @ broadcast carry bit
+ vshl.i64 $IN,$IN,#1
+ vand $t0,$t0,$t1
+ vorr $IN#hi,$Hlo @ H<<<=1
+ veor $IN,$IN,$t0 @ twisted H
+ vstmia r0,{$IN}
+
+ bx lr
+.size gcm_init_neon,.-gcm_init_neon
+
+.global gcm_gmult_neon
+.hidden gcm_gmult_neon
+.type gcm_gmult_neon,%function
+.align 4
+gcm_gmult_neon:
+ vld1.64 $IN#hi,[$Xi,:64]! @ load Xi
+ vld1.64 $IN#lo,[$Xi,:64]!
+ vmov.i64 $k48,#0x0000ffffffffffff
+ vldmia $Htbl,{$Hlo-$Hhi} @ load twisted H
+ vmov.i64 $k32,#0x00000000ffffffff
+#ifdef __ARMEL__
+ vrev64.8 $IN,$IN
+#endif
+ vmov.i64 $k16,#0x000000000000ffff
+ veor $Hhl,$Hlo,$Hhi @ Karatsuba pre-processing
+ mov $len,#16
+ b .Lgmult_neon
+.size gcm_gmult_neon,.-gcm_gmult_neon
+
+.global gcm_ghash_neon
+.hidden gcm_ghash_neon
+.type gcm_ghash_neon,%function
+.align 4
+gcm_ghash_neon:
+ vld1.64 $Xl#hi,[$Xi,:64]! @ load Xi
+ vld1.64 $Xl#lo,[$Xi,:64]!
+ vmov.i64 $k48,#0x0000ffffffffffff
+ vldmia $Htbl,{$Hlo-$Hhi} @ load twisted H
+ vmov.i64 $k32,#0x00000000ffffffff
+#ifdef __ARMEL__
+ vrev64.8 $Xl,$Xl
+#endif
+ vmov.i64 $k16,#0x000000000000ffff
+ veor $Hhl,$Hlo,$Hhi @ Karatsuba pre-processing
+
+.Loop_neon:
+ vld1.64 $IN#hi,[$inp]! @ load inp
+ vld1.64 $IN#lo,[$inp]!
+#ifdef __ARMEL__
+ vrev64.8 $IN,$IN
+#endif
+ veor $IN,$Xl @ inp^=Xi
+.Lgmult_neon:
+___
+ &clmul64x64 ($Xl,$Hlo,"$IN#lo"); # H.lo·Xi.lo
+$code.=<<___;
+ veor $IN#lo,$IN#lo,$IN#hi @ Karatsuba pre-processing
+___
+ &clmul64x64 ($Xm,$Hhl,"$IN#lo"); # (H.lo+H.hi)·(Xi.lo+Xi.hi)
+ &clmul64x64 ($Xh,$Hhi,"$IN#hi"); # H.hi·Xi.hi
+$code.=<<___;
+ veor $Xm,$Xm,$Xl @ Karatsuba post-processing
+ veor $Xm,$Xm,$Xh
+ veor $Xl#hi,$Xl#hi,$Xm#lo
+ veor $Xh#lo,$Xh#lo,$Xm#hi @ Xh|Xl - 256-bit result
+
+ @ equivalent of reduction_avx from ghash-x86_64.pl
+ vshl.i64 $t1,$Xl,#57 @ 1st phase
+ vshl.i64 $t2,$Xl,#62
+ veor $t2,$t2,$t1 @
+ vshl.i64 $t1,$Xl,#63
+ veor $t2, $t2, $t1 @
+ veor $Xl#hi,$Xl#hi,$t2#lo @
+ veor $Xh#lo,$Xh#lo,$t2#hi
+
+ vshr.u64 $t2,$Xl,#1 @ 2nd phase
+ veor $Xh,$Xh,$Xl
+ veor $Xl,$Xl,$t2 @
+ vshr.u64 $t2,$t2,#6
+ vshr.u64 $Xl,$Xl,#1 @
+ veor $Xl,$Xl,$Xh @
+ veor $Xl,$Xl,$t2 @
+
+ subs $len,#16
+ bne .Loop_neon
+
+#ifdef __ARMEL__
+ vrev64.8 $Xl,$Xl
+#endif
+ sub $Xi,#16
+ vst1.64 $Xl#hi,[$Xi,:64]! @ write out Xi
+ vst1.64 $Xl#lo,[$Xi,:64]
+
+ bx lr
+.size gcm_ghash_neon,.-gcm_ghash_neon
+#endif
+___
+}
+$code.=<<___;
+.asciz "GHASH for ARMv4/NEON, CRYPTOGAMS by <appro\@openssl.org>"
+.align 2
+
+#endif
+___
+
+foreach (split("\n",$code)) {
+ s/\`([^\`]*)\`/eval $1/geo;
+
+ s/\bq([0-9]+)#(lo|hi)/sprintf "d%d",2*$1+($2 eq "hi")/geo or
+ s/\bbx\s+lr\b/.word\t0xe12fff1e/go; # make it possible to compile with -march=armv4
+
+ print $_,"\n";
+}
+close STDOUT; # enforce flush
diff --git a/src/crypto/modes/asm/ghash-x86.pl b/src/crypto/modes/asm/ghash-x86.pl
new file mode 100644
index 0000000..eb6d55e
--- /dev/null
+++ b/src/crypto/modes/asm/ghash-x86.pl
@@ -0,0 +1,1393 @@
+#!/usr/bin/env perl
+#
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+# project. The module is, however, dual licensed under OpenSSL and
+# CRYPTOGAMS licenses depending on where you obtain it. For further
+# details see http://www.openssl.org/~appro/cryptogams/.
+# ====================================================================
+#
+# March, May, June 2010
+#
+# The module implements "4-bit" GCM GHASH function and underlying
+# single multiplication operation in GF(2^128). "4-bit" means that it
+# uses 256 bytes per-key table [+64/128 bytes fixed table]. It has two
+# code paths: vanilla x86 and vanilla SSE. Former will be executed on
+# 486 and Pentium, latter on all others. SSE GHASH features so called
+# "528B" variant of "4-bit" method utilizing additional 256+16 bytes
+# of per-key storage [+512 bytes shared table]. Performance results
+# are for streamed GHASH subroutine and are expressed in cycles per
+# processed byte, less is better:
+#
+# gcc 2.95.3(*) SSE assembler x86 assembler
+#
+# Pentium 105/111(**) - 50
+# PIII 68 /75 12.2 24
+# P4 125/125 17.8 84(***)
+# Opteron 66 /70 10.1 30
+# Core2 54 /67 8.4 18
+# Atom 105/105 16.8 53
+# VIA Nano 69 /71 13.0 27
+#
+# (*) gcc 3.4.x was observed to generate few percent slower code,
+# which is one of reasons why 2.95.3 results were chosen,
+# another reason is lack of 3.4.x results for older CPUs;
+# comparison with SSE results is not completely fair, because C
+# results are for vanilla "256B" implementation, while
+# assembler results are for "528B";-)
+# (**) second number is result for code compiled with -fPIC flag,
+# which is actually more relevant, because assembler code is
+# position-independent;
+# (***) see comment in non-MMX routine for further details;
+#
+# To summarize, it's >2-5 times faster than gcc-generated code. To
+# anchor it to something else SHA1 assembler processes one byte in
+# ~7 cycles on contemporary x86 cores. As for choice of MMX/SSE
+# in particular, see comment at the end of the file...
+
+# May 2010
+#
+# Add PCLMULQDQ version performing at 2.10 cycles per processed byte.
+# The question is how close is it to theoretical limit? The pclmulqdq
+# instruction latency appears to be 14 cycles and there can't be more
+# than 2 of them executing at any given time. This means that single
+# Karatsuba multiplication would take 28 cycles *plus* few cycles for
+# pre- and post-processing. Then multiplication has to be followed by
+# modulo-reduction. Given that aggregated reduction method [see
+# "Carry-less Multiplication and Its Usage for Computing the GCM Mode"
+# white paper by Intel] allows you to perform reduction only once in
+# a while we can assume that asymptotic performance can be estimated
+# as (28+Tmod/Naggr)/16, where Tmod is time to perform reduction
+# and Naggr is the aggregation factor.
+#
+# Before we proceed to this implementation let's have closer look at
+# the best-performing code suggested by Intel in their white paper.
+# By tracing inter-register dependencies Tmod is estimated as ~19
+# cycles and Naggr chosen by Intel is 4, resulting in 2.05 cycles per
+# processed byte. As implied, this is quite optimistic estimate,
+# because it does not account for Karatsuba pre- and post-processing,
+# which for a single multiplication is ~5 cycles. Unfortunately Intel
+# does not provide performance data for GHASH alone. But benchmarking
+# AES_GCM_encrypt ripped out of Fig. 15 of the white paper with aadt
+# alone resulted in 2.46 cycles per byte of out 16KB buffer. Note that
+# the result accounts even for pre-computing of degrees of the hash
+# key H, but its portion is negligible at 16KB buffer size.
+#
+# Moving on to the implementation in question. Tmod is estimated as
+# ~13 cycles and Naggr is 2, giving asymptotic performance of ...
+# 2.16. How is it possible that measured performance is better than
+# optimistic theoretical estimate? There is one thing Intel failed
+# to recognize. By serializing GHASH with CTR in same subroutine
+# former's performance is really limited to above (Tmul + Tmod/Naggr)
+# equation. But if GHASH procedure is detached, the modulo-reduction
+# can be interleaved with Naggr-1 multiplications at instruction level
+# and under ideal conditions even disappear from the equation. So that
+# optimistic theoretical estimate for this implementation is ...
+# 28/16=1.75, and not 2.16. Well, it's probably way too optimistic,
+# at least for such small Naggr. I'd argue that (28+Tproc/Naggr),
+# where Tproc is time required for Karatsuba pre- and post-processing,
+# is more realistic estimate. In this case it gives ... 1.91 cycles.
+# Or in other words, depending on how well we can interleave reduction
+# and one of the two multiplications the performance should be betwen
+# 1.91 and 2.16. As already mentioned, this implementation processes
+# one byte out of 8KB buffer in 2.10 cycles, while x86_64 counterpart
+# - in 2.02. x86_64 performance is better, because larger register
+# bank allows to interleave reduction and multiplication better.
+#
+# Does it make sense to increase Naggr? To start with it's virtually
+# impossible in 32-bit mode, because of limited register bank
+# capacity. Otherwise improvement has to be weighed agiainst slower
+# setup, as well as code size and complexity increase. As even
+# optimistic estimate doesn't promise 30% performance improvement,
+# there are currently no plans to increase Naggr.
+#
+# Special thanks to David Woodhouse <dwmw2@infradead.org> for
+# providing access to a Westmere-based system on behalf of Intel
+# Open Source Technology Centre.
+
+# January 2010
+#
+# Tweaked to optimize transitions between integer and FP operations
+# on same XMM register, PCLMULQDQ subroutine was measured to process
+# one byte in 2.07 cycles on Sandy Bridge, and in 2.12 - on Westmere.
+# The minor regression on Westmere is outweighed by ~15% improvement
+# on Sandy Bridge. Strangely enough attempt to modify 64-bit code in
+# similar manner resulted in almost 20% degradation on Sandy Bridge,
+# where original 64-bit code processes one byte in 1.95 cycles.
+
+#####################################################################
+# For reference, AMD Bulldozer processes one byte in 1.98 cycles in
+# 32-bit mode and 1.89 in 64-bit.
+
+# February 2013
+#
+# Overhaul: aggregate Karatsuba post-processing, improve ILP in
+# reduction_alg9. Resulting performance is 1.96 cycles per byte on
+# Westmere, 1.95 - on Sandy/Ivy Bridge, 1.76 - on Bulldozer.
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+push(@INC,"${dir}","${dir}../../perlasm");
+require "x86asm.pl";
+
+&asm_init($ARGV[0],"ghash-x86.pl",$x86only = $ARGV[$#ARGV] eq "386");
+
+$sse2=1;
+#for (@ARGV) { $sse2=1 if (/-DOPENSSL_IA32_SSE2/); }
+
+($Zhh,$Zhl,$Zlh,$Zll) = ("ebp","edx","ecx","ebx");
+$inp = "edi";
+$Htbl = "esi";
+
+$unroll = 0; # Affects x86 loop. Folded loop performs ~7% worse
+ # than unrolled, which has to be weighted against
+ # 2.5x x86-specific code size reduction.
+
+sub x86_loop {
+ my $off = shift;
+ my $rem = "eax";
+
+ &mov ($Zhh,&DWP(4,$Htbl,$Zll));
+ &mov ($Zhl,&DWP(0,$Htbl,$Zll));
+ &mov ($Zlh,&DWP(12,$Htbl,$Zll));
+ &mov ($Zll,&DWP(8,$Htbl,$Zll));
+ &xor ($rem,$rem); # avoid partial register stalls on PIII
+
+ # shrd practically kills P4, 2.5x deterioration, but P4 has
+ # MMX code-path to execute. shrd runs tad faster [than twice
+ # the shifts, move's and or's] on pre-MMX Pentium (as well as
+ # PIII and Core2), *but* minimizes code size, spares register
+ # and thus allows to fold the loop...
+ if (!$unroll) {
+ my $cnt = $inp;
+ &mov ($cnt,15);
+ &jmp (&label("x86_loop"));
+ &set_label("x86_loop",16);
+ for($i=1;$i<=2;$i++) {
+ &mov (&LB($rem),&LB($Zll));
+ &shrd ($Zll,$Zlh,4);
+ &and (&LB($rem),0xf);
+ &shrd ($Zlh,$Zhl,4);
+ &shrd ($Zhl,$Zhh,4);
+ &shr ($Zhh,4);
+ &xor ($Zhh,&DWP($off+16,"esp",$rem,4));
+
+ &mov (&LB($rem),&BP($off,"esp",$cnt));
+ if ($i&1) {
+ &and (&LB($rem),0xf0);
+ } else {
+ &shl (&LB($rem),4);
+ }
+
+ &xor ($Zll,&DWP(8,$Htbl,$rem));
+ &xor ($Zlh,&DWP(12,$Htbl,$rem));
+ &xor ($Zhl,&DWP(0,$Htbl,$rem));
+ &xor ($Zhh,&DWP(4,$Htbl,$rem));
+
+ if ($i&1) {
+ &dec ($cnt);
+ &js (&label("x86_break"));
+ } else {
+ &jmp (&label("x86_loop"));
+ }
+ }
+ &set_label("x86_break",16);
+ } else {
+ for($i=1;$i<32;$i++) {
+ &comment($i);
+ &mov (&LB($rem),&LB($Zll));
+ &shrd ($Zll,$Zlh,4);
+ &and (&LB($rem),0xf);
+ &shrd ($Zlh,$Zhl,4);
+ &shrd ($Zhl,$Zhh,4);
+ &shr ($Zhh,4);
+ &xor ($Zhh,&DWP($off+16,"esp",$rem,4));
+
+ if ($i&1) {
+ &mov (&LB($rem),&BP($off+15-($i>>1),"esp"));
+ &and (&LB($rem),0xf0);
+ } else {
+ &mov (&LB($rem),&BP($off+15-($i>>1),"esp"));
+ &shl (&LB($rem),4);
+ }
+
+ &xor ($Zll,&DWP(8,$Htbl,$rem));
+ &xor ($Zlh,&DWP(12,$Htbl,$rem));
+ &xor ($Zhl,&DWP(0,$Htbl,$rem));
+ &xor ($Zhh,&DWP(4,$Htbl,$rem));
+ }
+ }
+ &bswap ($Zll);
+ &bswap ($Zlh);
+ &bswap ($Zhl);
+ if (!$x86only) {
+ &bswap ($Zhh);
+ } else {
+ &mov ("eax",$Zhh);
+ &bswap ("eax");
+ &mov ($Zhh,"eax");
+ }
+}
+
+if ($unroll) {
+ &function_begin_B("_x86_gmult_4bit_inner");
+ &x86_loop(4);
+ &ret ();
+ &function_end_B("_x86_gmult_4bit_inner");
+}
+
+sub deposit_rem_4bit {
+ my $bias = shift;
+
+ &mov (&DWP($bias+0, "esp"),0x0000<<16);
+ &mov (&DWP($bias+4, "esp"),0x1C20<<16);
+ &mov (&DWP($bias+8, "esp"),0x3840<<16);
+ &mov (&DWP($bias+12,"esp"),0x2460<<16);
+ &mov (&DWP($bias+16,"esp"),0x7080<<16);
+ &mov (&DWP($bias+20,"esp"),0x6CA0<<16);
+ &mov (&DWP($bias+24,"esp"),0x48C0<<16);
+ &mov (&DWP($bias+28,"esp"),0x54E0<<16);
+ &mov (&DWP($bias+32,"esp"),0xE100<<16);
+ &mov (&DWP($bias+36,"esp"),0xFD20<<16);
+ &mov (&DWP($bias+40,"esp"),0xD940<<16);
+ &mov (&DWP($bias+44,"esp"),0xC560<<16);
+ &mov (&DWP($bias+48,"esp"),0x9180<<16);
+ &mov (&DWP($bias+52,"esp"),0x8DA0<<16);
+ &mov (&DWP($bias+56,"esp"),0xA9C0<<16);
+ &mov (&DWP($bias+60,"esp"),0xB5E0<<16);
+}
+
+$suffix = $x86only ? "" : "_x86";
+
+&function_begin("gcm_gmult_4bit".$suffix);
+ &stack_push(16+4+1); # +1 for stack alignment
+ &mov ($inp,&wparam(0)); # load Xi
+ &mov ($Htbl,&wparam(1)); # load Htable
+
+ &mov ($Zhh,&DWP(0,$inp)); # load Xi[16]
+ &mov ($Zhl,&DWP(4,$inp));
+ &mov ($Zlh,&DWP(8,$inp));
+ &mov ($Zll,&DWP(12,$inp));
+
+ &deposit_rem_4bit(16);
+
+ &mov (&DWP(0,"esp"),$Zhh); # copy Xi[16] on stack
+ &mov (&DWP(4,"esp"),$Zhl);
+ &mov (&DWP(8,"esp"),$Zlh);
+ &mov (&DWP(12,"esp"),$Zll);
+ &shr ($Zll,20);
+ &and ($Zll,0xf0);
+
+ if ($unroll) {
+ &call ("_x86_gmult_4bit_inner");
+ } else {
+ &x86_loop(0);
+ &mov ($inp,&wparam(0));
+ }
+
+ &mov (&DWP(12,$inp),$Zll);
+ &mov (&DWP(8,$inp),$Zlh);
+ &mov (&DWP(4,$inp),$Zhl);
+ &mov (&DWP(0,$inp),$Zhh);
+ &stack_pop(16+4+1);
+&function_end("gcm_gmult_4bit".$suffix);
+
+&function_begin("gcm_ghash_4bit".$suffix);
+ &stack_push(16+4+1); # +1 for 64-bit alignment
+ &mov ($Zll,&wparam(0)); # load Xi
+ &mov ($Htbl,&wparam(1)); # load Htable
+ &mov ($inp,&wparam(2)); # load in
+ &mov ("ecx",&wparam(3)); # load len
+ &add ("ecx",$inp);
+ &mov (&wparam(3),"ecx");
+
+ &mov ($Zhh,&DWP(0,$Zll)); # load Xi[16]
+ &mov ($Zhl,&DWP(4,$Zll));
+ &mov ($Zlh,&DWP(8,$Zll));
+ &mov ($Zll,&DWP(12,$Zll));
+
+ &deposit_rem_4bit(16);
+
+ &set_label("x86_outer_loop",16);
+ &xor ($Zll,&DWP(12,$inp)); # xor with input
+ &xor ($Zlh,&DWP(8,$inp));
+ &xor ($Zhl,&DWP(4,$inp));
+ &xor ($Zhh,&DWP(0,$inp));
+ &mov (&DWP(12,"esp"),$Zll); # dump it on stack
+ &mov (&DWP(8,"esp"),$Zlh);
+ &mov (&DWP(4,"esp"),$Zhl);
+ &mov (&DWP(0,"esp"),$Zhh);
+
+ &shr ($Zll,20);
+ &and ($Zll,0xf0);
+
+ if ($unroll) {
+ &call ("_x86_gmult_4bit_inner");
+ } else {
+ &x86_loop(0);
+ &mov ($inp,&wparam(2));
+ }
+ &lea ($inp,&DWP(16,$inp));
+ &cmp ($inp,&wparam(3));
+ &mov (&wparam(2),$inp) if (!$unroll);
+ &jb (&label("x86_outer_loop"));
+
+ &mov ($inp,&wparam(0)); # load Xi
+ &mov (&DWP(12,$inp),$Zll);
+ &mov (&DWP(8,$inp),$Zlh);
+ &mov (&DWP(4,$inp),$Zhl);
+ &mov (&DWP(0,$inp),$Zhh);
+ &stack_pop(16+4+1);
+&function_end("gcm_ghash_4bit".$suffix);
+
+if (!$x86only) {{{
+
+&static_label("rem_4bit");
+
+if (!$sse2) {{ # pure-MMX "May" version...
+
+$S=12; # shift factor for rem_4bit
+
+&function_begin_B("_mmx_gmult_4bit_inner");
+# MMX version performs 3.5 times better on P4 (see comment in non-MMX
+# routine for further details), 100% better on Opteron, ~70% better
+# on Core2 and PIII... In other words effort is considered to be well
+# spent... Since initial release the loop was unrolled in order to
+# "liberate" register previously used as loop counter. Instead it's
+# used to optimize critical path in 'Z.hi ^= rem_4bit[Z.lo&0xf]'.
+# The path involves move of Z.lo from MMX to integer register,
+# effective address calculation and finally merge of value to Z.hi.
+# Reference to rem_4bit is scheduled so late that I had to >>4
+# rem_4bit elements. This resulted in 20-45% procent improvement
+# on contemporary µ-archs.
+{
+ my $cnt;
+ my $rem_4bit = "eax";
+ my @rem = ($Zhh,$Zll);
+ my $nhi = $Zhl;
+ my $nlo = $Zlh;
+
+ my ($Zlo,$Zhi) = ("mm0","mm1");
+ my $tmp = "mm2";
+
+ &xor ($nlo,$nlo); # avoid partial register stalls on PIII
+ &mov ($nhi,$Zll);
+ &mov (&LB($nlo),&LB($nhi));
+ &shl (&LB($nlo),4);
+ &and ($nhi,0xf0);
+ &movq ($Zlo,&QWP(8,$Htbl,$nlo));
+ &movq ($Zhi,&QWP(0,$Htbl,$nlo));
+ &movd ($rem[0],$Zlo);
+
+ for ($cnt=28;$cnt>=-2;$cnt--) {
+ my $odd = $cnt&1;
+ my $nix = $odd ? $nlo : $nhi;
+
+ &shl (&LB($nlo),4) if ($odd);
+ &psrlq ($Zlo,4);
+ &movq ($tmp,$Zhi);
+ &psrlq ($Zhi,4);
+ &pxor ($Zlo,&QWP(8,$Htbl,$nix));
+ &mov (&LB($nlo),&BP($cnt/2,$inp)) if (!$odd && $cnt>=0);
+ &psllq ($tmp,60);
+ &and ($nhi,0xf0) if ($odd);
+ &pxor ($Zhi,&QWP(0,$rem_4bit,$rem[1],8)) if ($cnt<28);
+ &and ($rem[0],0xf);
+ &pxor ($Zhi,&QWP(0,$Htbl,$nix));
+ &mov ($nhi,$nlo) if (!$odd && $cnt>=0);
+ &movd ($rem[1],$Zlo);
+ &pxor ($Zlo,$tmp);
+
+ push (@rem,shift(@rem)); # "rotate" registers
+ }
+
+ &mov ($inp,&DWP(4,$rem_4bit,$rem[1],8)); # last rem_4bit[rem]
+
+ &psrlq ($Zlo,32); # lower part of Zlo is already there
+ &movd ($Zhl,$Zhi);
+ &psrlq ($Zhi,32);
+ &movd ($Zlh,$Zlo);
+ &movd ($Zhh,$Zhi);
+ &shl ($inp,4); # compensate for rem_4bit[i] being >>4
+
+ &bswap ($Zll);
+ &bswap ($Zhl);
+ &bswap ($Zlh);
+ &xor ($Zhh,$inp);
+ &bswap ($Zhh);
+
+ &ret ();
+}
+&function_end_B("_mmx_gmult_4bit_inner");
+
+&function_begin("gcm_gmult_4bit_mmx");
+ &mov ($inp,&wparam(0)); # load Xi
+ &mov ($Htbl,&wparam(1)); # load Htable
+
+ &call (&label("pic_point"));
+ &set_label("pic_point");
+ &blindpop("eax");
+ &lea ("eax",&DWP(&label("rem_4bit")."-".&label("pic_point"),"eax"));
+
+ &movz ($Zll,&BP(15,$inp));
+
+ &call ("_mmx_gmult_4bit_inner");
+
+ &mov ($inp,&wparam(0)); # load Xi
+ &emms ();
+ &mov (&DWP(12,$inp),$Zll);
+ &mov (&DWP(4,$inp),$Zhl);
+ &mov (&DWP(8,$inp),$Zlh);
+ &mov (&DWP(0,$inp),$Zhh);
+&function_end("gcm_gmult_4bit_mmx");
+
+# Streamed version performs 20% better on P4, 7% on Opteron,
+# 10% on Core2 and PIII...
+&function_begin("gcm_ghash_4bit_mmx");
+ &mov ($Zhh,&wparam(0)); # load Xi
+ &mov ($Htbl,&wparam(1)); # load Htable
+ &mov ($inp,&wparam(2)); # load in
+ &mov ($Zlh,&wparam(3)); # load len
+
+ &call (&label("pic_point"));
+ &set_label("pic_point");
+ &blindpop("eax");
+ &lea ("eax",&DWP(&label("rem_4bit")."-".&label("pic_point"),"eax"));
+
+ &add ($Zlh,$inp);
+ &mov (&wparam(3),$Zlh); # len to point at the end of input
+ &stack_push(4+1); # +1 for stack alignment
+
+ &mov ($Zll,&DWP(12,$Zhh)); # load Xi[16]
+ &mov ($Zhl,&DWP(4,$Zhh));
+ &mov ($Zlh,&DWP(8,$Zhh));
+ &mov ($Zhh,&DWP(0,$Zhh));
+ &jmp (&label("mmx_outer_loop"));
+
+ &set_label("mmx_outer_loop",16);
+ &xor ($Zll,&DWP(12,$inp));
+ &xor ($Zhl,&DWP(4,$inp));
+ &xor ($Zlh,&DWP(8,$inp));
+ &xor ($Zhh,&DWP(0,$inp));
+ &mov (&wparam(2),$inp);
+ &mov (&DWP(12,"esp"),$Zll);
+ &mov (&DWP(4,"esp"),$Zhl);
+ &mov (&DWP(8,"esp"),$Zlh);
+ &mov (&DWP(0,"esp"),$Zhh);
+
+ &mov ($inp,"esp");
+ &shr ($Zll,24);
+
+ &call ("_mmx_gmult_4bit_inner");
+
+ &mov ($inp,&wparam(2));
+ &lea ($inp,&DWP(16,$inp));
+ &cmp ($inp,&wparam(3));
+ &jb (&label("mmx_outer_loop"));
+
+ &mov ($inp,&wparam(0)); # load Xi
+ &emms ();
+ &mov (&DWP(12,$inp),$Zll);
+ &mov (&DWP(4,$inp),$Zhl);
+ &mov (&DWP(8,$inp),$Zlh);
+ &mov (&DWP(0,$inp),$Zhh);
+
+ &stack_pop(4+1);
+&function_end("gcm_ghash_4bit_mmx");
+
+}} else {{ # "June" MMX version...
+ # ... has slower "April" gcm_gmult_4bit_mmx with folded
+ # loop. This is done to conserve code size...
+$S=16; # shift factor for rem_4bit
+
+sub mmx_loop() {
+# MMX version performs 2.8 times better on P4 (see comment in non-MMX
+# routine for further details), 40% better on Opteron and Core2, 50%
+# better on PIII... In other words effort is considered to be well
+# spent...
+ my $inp = shift;
+ my $rem_4bit = shift;
+ my $cnt = $Zhh;
+ my $nhi = $Zhl;
+ my $nlo = $Zlh;
+ my $rem = $Zll;
+
+ my ($Zlo,$Zhi) = ("mm0","mm1");
+ my $tmp = "mm2";
+
+ &xor ($nlo,$nlo); # avoid partial register stalls on PIII
+ &mov ($nhi,$Zll);
+ &mov (&LB($nlo),&LB($nhi));
+ &mov ($cnt,14);
+ &shl (&LB($nlo),4);
+ &and ($nhi,0xf0);
+ &movq ($Zlo,&QWP(8,$Htbl,$nlo));
+ &movq ($Zhi,&QWP(0,$Htbl,$nlo));
+ &movd ($rem,$Zlo);
+ &jmp (&label("mmx_loop"));
+
+ &set_label("mmx_loop",16);
+ &psrlq ($Zlo,4);
+ &and ($rem,0xf);
+ &movq ($tmp,$Zhi);
+ &psrlq ($Zhi,4);
+ &pxor ($Zlo,&QWP(8,$Htbl,$nhi));
+ &mov (&LB($nlo),&BP(0,$inp,$cnt));
+ &psllq ($tmp,60);
+ &pxor ($Zhi,&QWP(0,$rem_4bit,$rem,8));
+ &dec ($cnt);
+ &movd ($rem,$Zlo);
+ &pxor ($Zhi,&QWP(0,$Htbl,$nhi));
+ &mov ($nhi,$nlo);
+ &pxor ($Zlo,$tmp);
+ &js (&label("mmx_break"));
+
+ &shl (&LB($nlo),4);
+ &and ($rem,0xf);
+ &psrlq ($Zlo,4);
+ &and ($nhi,0xf0);
+ &movq ($tmp,$Zhi);
+ &psrlq ($Zhi,4);
+ &pxor ($Zlo,&QWP(8,$Htbl,$nlo));
+ &psllq ($tmp,60);
+ &pxor ($Zhi,&QWP(0,$rem_4bit,$rem,8));
+ &movd ($rem,$Zlo);
+ &pxor ($Zhi,&QWP(0,$Htbl,$nlo));
+ &pxor ($Zlo,$tmp);
+ &jmp (&label("mmx_loop"));
+
+ &set_label("mmx_break",16);
+ &shl (&LB($nlo),4);
+ &and ($rem,0xf);
+ &psrlq ($Zlo,4);
+ &and ($nhi,0xf0);
+ &movq ($tmp,$Zhi);
+ &psrlq ($Zhi,4);
+ &pxor ($Zlo,&QWP(8,$Htbl,$nlo));
+ &psllq ($tmp,60);
+ &pxor ($Zhi,&QWP(0,$rem_4bit,$rem,8));
+ &movd ($rem,$Zlo);
+ &pxor ($Zhi,&QWP(0,$Htbl,$nlo));
+ &pxor ($Zlo,$tmp);
+
+ &psrlq ($Zlo,4);
+ &and ($rem,0xf);
+ &movq ($tmp,$Zhi);
+ &psrlq ($Zhi,4);
+ &pxor ($Zlo,&QWP(8,$Htbl,$nhi));
+ &psllq ($tmp,60);
+ &pxor ($Zhi,&QWP(0,$rem_4bit,$rem,8));
+ &movd ($rem,$Zlo);
+ &pxor ($Zhi,&QWP(0,$Htbl,$nhi));
+ &pxor ($Zlo,$tmp);
+
+ &psrlq ($Zlo,32); # lower part of Zlo is already there
+ &movd ($Zhl,$Zhi);
+ &psrlq ($Zhi,32);
+ &movd ($Zlh,$Zlo);
+ &movd ($Zhh,$Zhi);
+
+ &bswap ($Zll);
+ &bswap ($Zhl);
+ &bswap ($Zlh);
+ &bswap ($Zhh);
+}
+
+&function_begin("gcm_gmult_4bit_mmx");
+ &mov ($inp,&wparam(0)); # load Xi
+ &mov ($Htbl,&wparam(1)); # load Htable
+
+ &call (&label("pic_point"));
+ &set_label("pic_point");
+ &blindpop("eax");
+ &lea ("eax",&DWP(&label("rem_4bit")."-".&label("pic_point"),"eax"));
+
+ &movz ($Zll,&BP(15,$inp));
+
+ &mmx_loop($inp,"eax");
+
+ &emms ();
+ &mov (&DWP(12,$inp),$Zll);
+ &mov (&DWP(4,$inp),$Zhl);
+ &mov (&DWP(8,$inp),$Zlh);
+ &mov (&DWP(0,$inp),$Zhh);
+&function_end("gcm_gmult_4bit_mmx");
+
+######################################################################
+# Below subroutine is "528B" variant of "4-bit" GCM GHASH function
+# (see gcm128.c for details). It provides further 20-40% performance
+# improvement over above mentioned "May" version.
+
+&static_label("rem_8bit");
+
+&function_begin("gcm_ghash_4bit_mmx");
+{ my ($Zlo,$Zhi) = ("mm7","mm6");
+ my $rem_8bit = "esi";
+ my $Htbl = "ebx";
+
+ # parameter block
+ &mov ("eax",&wparam(0)); # Xi
+ &mov ("ebx",&wparam(1)); # Htable
+ &mov ("ecx",&wparam(2)); # inp
+ &mov ("edx",&wparam(3)); # len
+ &mov ("ebp","esp"); # original %esp
+ &call (&label("pic_point"));
+ &set_label ("pic_point");
+ &blindpop ($rem_8bit);
+ &lea ($rem_8bit,&DWP(&label("rem_8bit")."-".&label("pic_point"),$rem_8bit));
+
+ &sub ("esp",512+16+16); # allocate stack frame...
+ &and ("esp",-64); # ...and align it
+ &sub ("esp",16); # place for (u8)(H[]<<4)
+
+ &add ("edx","ecx"); # pointer to the end of input
+ &mov (&DWP(528+16+0,"esp"),"eax"); # save Xi
+ &mov (&DWP(528+16+8,"esp"),"edx"); # save inp+len
+ &mov (&DWP(528+16+12,"esp"),"ebp"); # save original %esp
+
+ { my @lo = ("mm0","mm1","mm2");
+ my @hi = ("mm3","mm4","mm5");
+ my @tmp = ("mm6","mm7");
+ my ($off1,$off2,$i) = (0,0,);
+
+ &add ($Htbl,128); # optimize for size
+ &lea ("edi",&DWP(16+128,"esp"));
+ &lea ("ebp",&DWP(16+256+128,"esp"));
+
+ # decompose Htable (low and high parts are kept separately),
+ # generate Htable[]>>4, (u8)(Htable[]<<4), save to stack...
+ for ($i=0;$i<18;$i++) {
+
+ &mov ("edx",&DWP(16*$i+8-128,$Htbl)) if ($i<16);
+ &movq ($lo[0],&QWP(16*$i+8-128,$Htbl)) if ($i<16);
+ &psllq ($tmp[1],60) if ($i>1);
+ &movq ($hi[0],&QWP(16*$i+0-128,$Htbl)) if ($i<16);
+ &por ($lo[2],$tmp[1]) if ($i>1);
+ &movq (&QWP($off1-128,"edi"),$lo[1]) if ($i>0 && $i<17);
+ &psrlq ($lo[1],4) if ($i>0 && $i<17);
+ &movq (&QWP($off1,"edi"),$hi[1]) if ($i>0 && $i<17);
+ &movq ($tmp[0],$hi[1]) if ($i>0 && $i<17);
+ &movq (&QWP($off2-128,"ebp"),$lo[2]) if ($i>1);
+ &psrlq ($hi[1],4) if ($i>0 && $i<17);
+ &movq (&QWP($off2,"ebp"),$hi[2]) if ($i>1);
+ &shl ("edx",4) if ($i<16);
+ &mov (&BP($i,"esp"),&LB("edx")) if ($i<16);
+
+ unshift (@lo,pop(@lo)); # "rotate" registers
+ unshift (@hi,pop(@hi));
+ unshift (@tmp,pop(@tmp));
+ $off1 += 8 if ($i>0);
+ $off2 += 8 if ($i>1);
+ }
+ }
+
+ &movq ($Zhi,&QWP(0,"eax"));
+ &mov ("ebx",&DWP(8,"eax"));
+ &mov ("edx",&DWP(12,"eax")); # load Xi
+
+&set_label("outer",16);
+ { my $nlo = "eax";
+ my $dat = "edx";
+ my @nhi = ("edi","ebp");
+ my @rem = ("ebx","ecx");
+ my @red = ("mm0","mm1","mm2");
+ my $tmp = "mm3";
+
+ &xor ($dat,&DWP(12,"ecx")); # merge input data
+ &xor ("ebx",&DWP(8,"ecx"));
+ &pxor ($Zhi,&QWP(0,"ecx"));
+ &lea ("ecx",&DWP(16,"ecx")); # inp+=16
+ #&mov (&DWP(528+12,"esp"),$dat); # save inp^Xi
+ &mov (&DWP(528+8,"esp"),"ebx");
+ &movq (&QWP(528+0,"esp"),$Zhi);
+ &mov (&DWP(528+16+4,"esp"),"ecx"); # save inp
+
+ &xor ($nlo,$nlo);
+ &rol ($dat,8);
+ &mov (&LB($nlo),&LB($dat));
+ &mov ($nhi[1],$nlo);
+ &and (&LB($nlo),0x0f);
+ &shr ($nhi[1],4);
+ &pxor ($red[0],$red[0]);
+ &rol ($dat,8); # next byte
+ &pxor ($red[1],$red[1]);
+ &pxor ($red[2],$red[2]);
+
+ # Just like in "May" verson modulo-schedule for critical path in
+ # 'Z.hi ^= rem_8bit[Z.lo&0xff^((u8)H[nhi]<<4)]<<48'. Final 'pxor'
+ # is scheduled so late that rem_8bit[] has to be shifted *right*
+ # by 16, which is why last argument to pinsrw is 2, which
+ # corresponds to <<32=<<48>>16...
+ for ($j=11,$i=0;$i<15;$i++) {
+
+ if ($i>0) {
+ &pxor ($Zlo,&QWP(16,"esp",$nlo,8)); # Z^=H[nlo]
+ &rol ($dat,8); # next byte
+ &pxor ($Zhi,&QWP(16+128,"esp",$nlo,8));
+
+ &pxor ($Zlo,$tmp);
+ &pxor ($Zhi,&QWP(16+256+128,"esp",$nhi[0],8));
+ &xor (&LB($rem[1]),&BP(0,"esp",$nhi[0])); # rem^(H[nhi]<<4)
+ } else {
+ &movq ($Zlo,&QWP(16,"esp",$nlo,8));
+ &movq ($Zhi,&QWP(16+128,"esp",$nlo,8));
+ }
+
+ &mov (&LB($nlo),&LB($dat));
+ &mov ($dat,&DWP(528+$j,"esp")) if (--$j%4==0);
+
+ &movd ($rem[0],$Zlo);
+ &movz ($rem[1],&LB($rem[1])) if ($i>0);
+ &psrlq ($Zlo,8); # Z>>=8
+
+ &movq ($tmp,$Zhi);
+ &mov ($nhi[0],$nlo);
+ &psrlq ($Zhi,8);
+
+ &pxor ($Zlo,&QWP(16+256+0,"esp",$nhi[1],8)); # Z^=H[nhi]>>4
+ &and (&LB($nlo),0x0f);
+ &psllq ($tmp,56);
+
+ &pxor ($Zhi,$red[1]) if ($i>1);
+ &shr ($nhi[0],4);
+ &pinsrw ($red[0],&WP(0,$rem_8bit,$rem[1],2),2) if ($i>0);
+
+ unshift (@red,pop(@red)); # "rotate" registers
+ unshift (@rem,pop(@rem));
+ unshift (@nhi,pop(@nhi));
+ }
+
+ &pxor ($Zlo,&QWP(16,"esp",$nlo,8)); # Z^=H[nlo]
+ &pxor ($Zhi,&QWP(16+128,"esp",$nlo,8));
+ &xor (&LB($rem[1]),&BP(0,"esp",$nhi[0])); # rem^(H[nhi]<<4)
+
+ &pxor ($Zlo,$tmp);
+ &pxor ($Zhi,&QWP(16+256+128,"esp",$nhi[0],8));
+ &movz ($rem[1],&LB($rem[1]));
+
+ &pxor ($red[2],$red[2]); # clear 2nd word
+ &psllq ($red[1],4);
+
+ &movd ($rem[0],$Zlo);
+ &psrlq ($Zlo,4); # Z>>=4
+
+ &movq ($tmp,$Zhi);
+ &psrlq ($Zhi,4);
+ &shl ($rem[0],4); # rem<<4
+
+ &pxor ($Zlo,&QWP(16,"esp",$nhi[1],8)); # Z^=H[nhi]
+ &psllq ($tmp,60);
+ &movz ($rem[0],&LB($rem[0]));
+
+ &pxor ($Zlo,$tmp);
+ &pxor ($Zhi,&QWP(16+128,"esp",$nhi[1],8));
+
+ &pinsrw ($red[0],&WP(0,$rem_8bit,$rem[1],2),2);
+ &pxor ($Zhi,$red[1]);
+
+ &movd ($dat,$Zlo);
+ &pinsrw ($red[2],&WP(0,$rem_8bit,$rem[0],2),3); # last is <<48
+
+ &psllq ($red[0],12); # correct by <<16>>4
+ &pxor ($Zhi,$red[0]);
+ &psrlq ($Zlo,32);
+ &pxor ($Zhi,$red[2]);
+
+ &mov ("ecx",&DWP(528+16+4,"esp")); # restore inp
+ &movd ("ebx",$Zlo);
+ &movq ($tmp,$Zhi); # 01234567
+ &psllw ($Zhi,8); # 1.3.5.7.
+ &psrlw ($tmp,8); # .0.2.4.6
+ &por ($Zhi,$tmp); # 10325476
+ &bswap ($dat);
+ &pshufw ($Zhi,$Zhi,0b00011011); # 76543210
+ &bswap ("ebx");
+
+ &cmp ("ecx",&DWP(528+16+8,"esp")); # are we done?
+ &jne (&label("outer"));
+ }
+
+ &mov ("eax",&DWP(528+16+0,"esp")); # restore Xi
+ &mov (&DWP(12,"eax"),"edx");
+ &mov (&DWP(8,"eax"),"ebx");
+ &movq (&QWP(0,"eax"),$Zhi);
+
+ &mov ("esp",&DWP(528+16+12,"esp")); # restore original %esp
+ &emms ();
+}
+&function_end("gcm_ghash_4bit_mmx");
+}}
+
+if ($sse2) {{
+######################################################################
+# PCLMULQDQ version.
+
+$Xip="eax";
+$Htbl="edx";
+$const="ecx";
+$inp="esi";
+$len="ebx";
+
+($Xi,$Xhi)=("xmm0","xmm1"); $Hkey="xmm2";
+($T1,$T2,$T3)=("xmm3","xmm4","xmm5");
+($Xn,$Xhn)=("xmm6","xmm7");
+
+&static_label("bswap");
+
+sub clmul64x64_T2 { # minimal "register" pressure
+my ($Xhi,$Xi,$Hkey,$HK)=@_;
+
+ &movdqa ($Xhi,$Xi); #
+ &pshufd ($T1,$Xi,0b01001110);
+ &pshufd ($T2,$Hkey,0b01001110) if (!defined($HK));
+ &pxor ($T1,$Xi); #
+ &pxor ($T2,$Hkey) if (!defined($HK));
+ $HK=$T2 if (!defined($HK));
+
+ &pclmulqdq ($Xi,$Hkey,0x00); #######
+ &pclmulqdq ($Xhi,$Hkey,0x11); #######
+ &pclmulqdq ($T1,$HK,0x00); #######
+ &xorps ($T1,$Xi); #
+ &xorps ($T1,$Xhi); #
+
+ &movdqa ($T2,$T1); #
+ &psrldq ($T1,8);
+ &pslldq ($T2,8); #
+ &pxor ($Xhi,$T1);
+ &pxor ($Xi,$T2); #
+}
+
+sub clmul64x64_T3 {
+# Even though this subroutine offers visually better ILP, it
+# was empirically found to be a tad slower than above version.
+# At least in gcm_ghash_clmul context. But it's just as well,
+# because loop modulo-scheduling is possible only thanks to
+# minimized "register" pressure...
+my ($Xhi,$Xi,$Hkey)=@_;
+
+ &movdqa ($T1,$Xi); #
+ &movdqa ($Xhi,$Xi);
+ &pclmulqdq ($Xi,$Hkey,0x00); #######
+ &pclmulqdq ($Xhi,$Hkey,0x11); #######
+ &pshufd ($T2,$T1,0b01001110); #
+ &pshufd ($T3,$Hkey,0b01001110);
+ &pxor ($T2,$T1); #
+ &pxor ($T3,$Hkey);
+ &pclmulqdq ($T2,$T3,0x00); #######
+ &pxor ($T2,$Xi); #
+ &pxor ($T2,$Xhi); #
+
+ &movdqa ($T3,$T2); #
+ &psrldq ($T2,8);
+ &pslldq ($T3,8); #
+ &pxor ($Xhi,$T2);
+ &pxor ($Xi,$T3); #
+}
+
+if (1) { # Algorithm 9 with <<1 twist.
+ # Reduction is shorter and uses only two
+ # temporary registers, which makes it better
+ # candidate for interleaving with 64x64
+ # multiplication. Pre-modulo-scheduled loop
+ # was found to be ~20% faster than Algorithm 5
+ # below. Algorithm 9 was therefore chosen for
+ # further optimization...
+
+sub reduction_alg9 { # 17/11 times faster than Intel version
+my ($Xhi,$Xi) = @_;
+
+ # 1st phase
+ &movdqa ($T2,$Xi); #
+ &movdqa ($T1,$Xi);
+ &psllq ($Xi,5);
+ &pxor ($T1,$Xi); #
+ &psllq ($Xi,1);
+ &pxor ($Xi,$T1); #
+ &psllq ($Xi,57); #
+ &movdqa ($T1,$Xi); #
+ &pslldq ($Xi,8);
+ &psrldq ($T1,8); #
+ &pxor ($Xi,$T2);
+ &pxor ($Xhi,$T1); #
+
+ # 2nd phase
+ &movdqa ($T2,$Xi);
+ &psrlq ($Xi,1);
+ &pxor ($Xhi,$T2); #
+ &pxor ($T2,$Xi);
+ &psrlq ($Xi,5);
+ &pxor ($Xi,$T2); #
+ &psrlq ($Xi,1); #
+ &pxor ($Xi,$Xhi) #
+}
+
+&function_begin_B("gcm_init_clmul");
+ &mov ($Htbl,&wparam(0));
+ &mov ($Xip,&wparam(1));
+
+ &call (&label("pic"));
+&set_label("pic");
+ &blindpop ($const);
+ &lea ($const,&DWP(&label("bswap")."-".&label("pic"),$const));
+
+ &movdqu ($Hkey,&QWP(0,$Xip));
+ &pshufd ($Hkey,$Hkey,0b01001110);# dword swap
+
+ # <<1 twist
+ &pshufd ($T2,$Hkey,0b11111111); # broadcast uppermost dword
+ &movdqa ($T1,$Hkey);
+ &psllq ($Hkey,1);
+ &pxor ($T3,$T3); #
+ &psrlq ($T1,63);
+ &pcmpgtd ($T3,$T2); # broadcast carry bit
+ &pslldq ($T1,8);
+ &por ($Hkey,$T1); # H<<=1
+
+ # magic reduction
+ &pand ($T3,&QWP(16,$const)); # 0x1c2_polynomial
+ &pxor ($Hkey,$T3); # if(carry) H^=0x1c2_polynomial
+
+ # calculate H^2
+ &movdqa ($Xi,$Hkey);
+ &clmul64x64_T2 ($Xhi,$Xi,$Hkey);
+ &reduction_alg9 ($Xhi,$Xi);
+
+ &pshufd ($T1,$Hkey,0b01001110);
+ &pshufd ($T2,$Xi,0b01001110);
+ &pxor ($T1,$Hkey); # Karatsuba pre-processing
+ &movdqu (&QWP(0,$Htbl),$Hkey); # save H
+ &pxor ($T2,$Xi); # Karatsuba pre-processing
+ &movdqu (&QWP(16,$Htbl),$Xi); # save H^2
+ &palignr ($T2,$T1,8); # low part is H.lo^H.hi
+ &movdqu (&QWP(32,$Htbl),$T2); # save Karatsuba "salt"
+
+ &ret ();
+&function_end_B("gcm_init_clmul");
+
+&function_begin_B("gcm_gmult_clmul");
+ &mov ($Xip,&wparam(0));
+ &mov ($Htbl,&wparam(1));
+
+ &call (&label("pic"));
+&set_label("pic");
+ &blindpop ($const);
+ &lea ($const,&DWP(&label("bswap")."-".&label("pic"),$const));
+
+ &movdqu ($Xi,&QWP(0,$Xip));
+ &movdqa ($T3,&QWP(0,$const));
+ &movups ($Hkey,&QWP(0,$Htbl));
+ &pshufb ($Xi,$T3);
+ &movups ($T2,&QWP(32,$Htbl));
+
+ &clmul64x64_T2 ($Xhi,$Xi,$Hkey,$T2);
+ &reduction_alg9 ($Xhi,$Xi);
+
+ &pshufb ($Xi,$T3);
+ &movdqu (&QWP(0,$Xip),$Xi);
+
+ &ret ();
+&function_end_B("gcm_gmult_clmul");
+
+&function_begin("gcm_ghash_clmul");
+ &mov ($Xip,&wparam(0));
+ &mov ($Htbl,&wparam(1));
+ &mov ($inp,&wparam(2));
+ &mov ($len,&wparam(3));
+
+ &call (&label("pic"));
+&set_label("pic");
+ &blindpop ($const);
+ &lea ($const,&DWP(&label("bswap")."-".&label("pic"),$const));
+
+ &movdqu ($Xi,&QWP(0,$Xip));
+ &movdqa ($T3,&QWP(0,$const));
+ &movdqu ($Hkey,&QWP(0,$Htbl));
+ &pshufb ($Xi,$T3);
+
+ &sub ($len,0x10);
+ &jz (&label("odd_tail"));
+
+ #######
+ # Xi+2 =[H*(Ii+1 + Xi+1)] mod P =
+ # [(H*Ii+1) + (H*Xi+1)] mod P =
+ # [(H*Ii+1) + H^2*(Ii+Xi)] mod P
+ #
+ &movdqu ($T1,&QWP(0,$inp)); # Ii
+ &movdqu ($Xn,&QWP(16,$inp)); # Ii+1
+ &pshufb ($T1,$T3);
+ &pshufb ($Xn,$T3);
+ &movdqu ($T3,&QWP(32,$Htbl));
+ &pxor ($Xi,$T1); # Ii+Xi
+
+ &pshufd ($T1,$Xn,0b01001110); # H*Ii+1
+ &movdqa ($Xhn,$Xn);
+ &pxor ($T1,$Xn); #
+ &lea ($inp,&DWP(32,$inp)); # i+=2
+
+ &pclmulqdq ($Xn,$Hkey,0x00); #######
+ &pclmulqdq ($Xhn,$Hkey,0x11); #######
+ &pclmulqdq ($T1,$T3,0x00); #######
+ &movups ($Hkey,&QWP(16,$Htbl)); # load H^2
+ &nop ();
+
+ &sub ($len,0x20);
+ &jbe (&label("even_tail"));
+ &jmp (&label("mod_loop"));
+
+&set_label("mod_loop",32);
+ &pshufd ($T2,$Xi,0b01001110); # H^2*(Ii+Xi)
+ &movdqa ($Xhi,$Xi);
+ &pxor ($T2,$Xi); #
+ &nop ();
+
+ &pclmulqdq ($Xi,$Hkey,0x00); #######
+ &pclmulqdq ($Xhi,$Hkey,0x11); #######
+ &pclmulqdq ($T2,$T3,0x10); #######
+ &movups ($Hkey,&QWP(0,$Htbl)); # load H
+
+ &xorps ($Xi,$Xn); # (H*Ii+1) + H^2*(Ii+Xi)
+ &movdqa ($T3,&QWP(0,$const));
+ &xorps ($Xhi,$Xhn);
+ &movdqu ($Xhn,&QWP(0,$inp)); # Ii
+ &pxor ($T1,$Xi); # aggregated Karatsuba post-processing
+ &movdqu ($Xn,&QWP(16,$inp)); # Ii+1
+ &pxor ($T1,$Xhi); #
+
+ &pshufb ($Xhn,$T3);
+ &pxor ($T2,$T1); #
+
+ &movdqa ($T1,$T2); #
+ &psrldq ($T2,8);
+ &pslldq ($T1,8); #
+ &pxor ($Xhi,$T2);
+ &pxor ($Xi,$T1); #
+ &pshufb ($Xn,$T3);
+ &pxor ($Xhi,$Xhn); # "Ii+Xi", consume early
+
+ &movdqa ($Xhn,$Xn); #&clmul64x64_TX ($Xhn,$Xn,$Hkey); H*Ii+1
+ &movdqa ($T2,$Xi); #&reduction_alg9($Xhi,$Xi); 1st phase
+ &movdqa ($T1,$Xi);
+ &psllq ($Xi,5);
+ &pxor ($T1,$Xi); #
+ &psllq ($Xi,1);
+ &pxor ($Xi,$T1); #
+ &pclmulqdq ($Xn,$Hkey,0x00); #######
+ &movups ($T3,&QWP(32,$Htbl));
+ &psllq ($Xi,57); #
+ &movdqa ($T1,$Xi); #
+ &pslldq ($Xi,8);
+ &psrldq ($T1,8); #
+ &pxor ($Xi,$T2);
+ &pxor ($Xhi,$T1); #
+ &pshufd ($T1,$Xhn,0b01001110);
+ &movdqa ($T2,$Xi); # 2nd phase
+ &psrlq ($Xi,1);
+ &pxor ($T1,$Xhn);
+ &pxor ($Xhi,$T2); #
+ &pclmulqdq ($Xhn,$Hkey,0x11); #######
+ &movups ($Hkey,&QWP(16,$Htbl)); # load H^2
+ &pxor ($T2,$Xi);
+ &psrlq ($Xi,5);
+ &pxor ($Xi,$T2); #
+ &psrlq ($Xi,1); #
+ &pxor ($Xi,$Xhi) #
+ &pclmulqdq ($T1,$T3,0x00); #######
+
+ &lea ($inp,&DWP(32,$inp));
+ &sub ($len,0x20);
+ &ja (&label("mod_loop"));
+
+&set_label("even_tail");
+ &pshufd ($T2,$Xi,0b01001110); # H^2*(Ii+Xi)
+ &movdqa ($Xhi,$Xi);
+ &pxor ($T2,$Xi); #
+
+ &pclmulqdq ($Xi,$Hkey,0x00); #######
+ &pclmulqdq ($Xhi,$Hkey,0x11); #######
+ &pclmulqdq ($T2,$T3,0x10); #######
+ &movdqa ($T3,&QWP(0,$const));
+
+ &xorps ($Xi,$Xn); # (H*Ii+1) + H^2*(Ii+Xi)
+ &xorps ($Xhi,$Xhn);
+ &pxor ($T1,$Xi); # aggregated Karatsuba post-processing
+ &pxor ($T1,$Xhi); #
+
+ &pxor ($T2,$T1); #
+
+ &movdqa ($T1,$T2); #
+ &psrldq ($T2,8);
+ &pslldq ($T1,8); #
+ &pxor ($Xhi,$T2);
+ &pxor ($Xi,$T1); #
+
+ &reduction_alg9 ($Xhi,$Xi);
+
+ &test ($len,$len);
+ &jnz (&label("done"));
+
+ &movups ($Hkey,&QWP(0,$Htbl)); # load H
+&set_label("odd_tail");
+ &movdqu ($T1,&QWP(0,$inp)); # Ii
+ &pshufb ($T1,$T3);
+ &pxor ($Xi,$T1); # Ii+Xi
+
+ &clmul64x64_T2 ($Xhi,$Xi,$Hkey); # H*(Ii+Xi)
+ &reduction_alg9 ($Xhi,$Xi);
+
+&set_label("done");
+ &pshufb ($Xi,$T3);
+ &movdqu (&QWP(0,$Xip),$Xi);
+&function_end("gcm_ghash_clmul");
+
+} else { # Algorith 5. Kept for reference purposes.
+
+sub reduction_alg5 { # 19/16 times faster than Intel version
+my ($Xhi,$Xi)=@_;
+
+ # <<1
+ &movdqa ($T1,$Xi); #
+ &movdqa ($T2,$Xhi);
+ &pslld ($Xi,1);
+ &pslld ($Xhi,1); #
+ &psrld ($T1,31);
+ &psrld ($T2,31); #
+ &movdqa ($T3,$T1);
+ &pslldq ($T1,4);
+ &psrldq ($T3,12); #
+ &pslldq ($T2,4);
+ &por ($Xhi,$T3); #
+ &por ($Xi,$T1);
+ &por ($Xhi,$T2); #
+
+ # 1st phase
+ &movdqa ($T1,$Xi);
+ &movdqa ($T2,$Xi);
+ &movdqa ($T3,$Xi); #
+ &pslld ($T1,31);
+ &pslld ($T2,30);
+ &pslld ($Xi,25); #
+ &pxor ($T1,$T2);
+ &pxor ($T1,$Xi); #
+ &movdqa ($T2,$T1); #
+ &pslldq ($T1,12);
+ &psrldq ($T2,4); #
+ &pxor ($T3,$T1);
+
+ # 2nd phase
+ &pxor ($Xhi,$T3); #
+ &movdqa ($Xi,$T3);
+ &movdqa ($T1,$T3);
+ &psrld ($Xi,1); #
+ &psrld ($T1,2);
+ &psrld ($T3,7); #
+ &pxor ($Xi,$T1);
+ &pxor ($Xhi,$T2);
+ &pxor ($Xi,$T3); #
+ &pxor ($Xi,$Xhi); #
+}
+
+&function_begin_B("gcm_init_clmul");
+ &mov ($Htbl,&wparam(0));
+ &mov ($Xip,&wparam(1));
+
+ &call (&label("pic"));
+&set_label("pic");
+ &blindpop ($const);
+ &lea ($const,&DWP(&label("bswap")."-".&label("pic"),$const));
+
+ &movdqu ($Hkey,&QWP(0,$Xip));
+ &pshufd ($Hkey,$Hkey,0b01001110);# dword swap
+
+ # calculate H^2
+ &movdqa ($Xi,$Hkey);
+ &clmul64x64_T3 ($Xhi,$Xi,$Hkey);
+ &reduction_alg5 ($Xhi,$Xi);
+
+ &movdqu (&QWP(0,$Htbl),$Hkey); # save H
+ &movdqu (&QWP(16,$Htbl),$Xi); # save H^2
+
+ &ret ();
+&function_end_B("gcm_init_clmul");
+
+&function_begin_B("gcm_gmult_clmul");
+ &mov ($Xip,&wparam(0));
+ &mov ($Htbl,&wparam(1));
+
+ &call (&label("pic"));
+&set_label("pic");
+ &blindpop ($const);
+ &lea ($const,&DWP(&label("bswap")."-".&label("pic"),$const));
+
+ &movdqu ($Xi,&QWP(0,$Xip));
+ &movdqa ($Xn,&QWP(0,$const));
+ &movdqu ($Hkey,&QWP(0,$Htbl));
+ &pshufb ($Xi,$Xn);
+
+ &clmul64x64_T3 ($Xhi,$Xi,$Hkey);
+ &reduction_alg5 ($Xhi,$Xi);
+
+ &pshufb ($Xi,$Xn);
+ &movdqu (&QWP(0,$Xip),$Xi);
+
+ &ret ();
+&function_end_B("gcm_gmult_clmul");
+
+&function_begin("gcm_ghash_clmul");
+ &mov ($Xip,&wparam(0));
+ &mov ($Htbl,&wparam(1));
+ &mov ($inp,&wparam(2));
+ &mov ($len,&wparam(3));
+
+ &call (&label("pic"));
+&set_label("pic");
+ &blindpop ($const);
+ &lea ($const,&DWP(&label("bswap")."-".&label("pic"),$const));
+
+ &movdqu ($Xi,&QWP(0,$Xip));
+ &movdqa ($T3,&QWP(0,$const));
+ &movdqu ($Hkey,&QWP(0,$Htbl));
+ &pshufb ($Xi,$T3);
+
+ &sub ($len,0x10);
+ &jz (&label("odd_tail"));
+
+ #######
+ # Xi+2 =[H*(Ii+1 + Xi+1)] mod P =
+ # [(H*Ii+1) + (H*Xi+1)] mod P =
+ # [(H*Ii+1) + H^2*(Ii+Xi)] mod P
+ #
+ &movdqu ($T1,&QWP(0,$inp)); # Ii
+ &movdqu ($Xn,&QWP(16,$inp)); # Ii+1
+ &pshufb ($T1,$T3);
+ &pshufb ($Xn,$T3);
+ &pxor ($Xi,$T1); # Ii+Xi
+
+ &clmul64x64_T3 ($Xhn,$Xn,$Hkey); # H*Ii+1
+ &movdqu ($Hkey,&QWP(16,$Htbl)); # load H^2
+
+ &sub ($len,0x20);
+ &lea ($inp,&DWP(32,$inp)); # i+=2
+ &jbe (&label("even_tail"));
+
+&set_label("mod_loop");
+ &clmul64x64_T3 ($Xhi,$Xi,$Hkey); # H^2*(Ii+Xi)
+ &movdqu ($Hkey,&QWP(0,$Htbl)); # load H
+
+ &pxor ($Xi,$Xn); # (H*Ii+1) + H^2*(Ii+Xi)
+ &pxor ($Xhi,$Xhn);
+
+ &reduction_alg5 ($Xhi,$Xi);
+
+ #######
+ &movdqa ($T3,&QWP(0,$const));
+ &movdqu ($T1,&QWP(0,$inp)); # Ii
+ &movdqu ($Xn,&QWP(16,$inp)); # Ii+1
+ &pshufb ($T1,$T3);
+ &pshufb ($Xn,$T3);
+ &pxor ($Xi,$T1); # Ii+Xi
+
+ &clmul64x64_T3 ($Xhn,$Xn,$Hkey); # H*Ii+1
+ &movdqu ($Hkey,&QWP(16,$Htbl)); # load H^2
+
+ &sub ($len,0x20);
+ &lea ($inp,&DWP(32,$inp));
+ &ja (&label("mod_loop"));
+
+&set_label("even_tail");
+ &clmul64x64_T3 ($Xhi,$Xi,$Hkey); # H^2*(Ii+Xi)
+
+ &pxor ($Xi,$Xn); # (H*Ii+1) + H^2*(Ii+Xi)
+ &pxor ($Xhi,$Xhn);
+
+ &reduction_alg5 ($Xhi,$Xi);
+
+ &movdqa ($T3,&QWP(0,$const));
+ &test ($len,$len);
+ &jnz (&label("done"));
+
+ &movdqu ($Hkey,&QWP(0,$Htbl)); # load H
+&set_label("odd_tail");
+ &movdqu ($T1,&QWP(0,$inp)); # Ii
+ &pshufb ($T1,$T3);
+ &pxor ($Xi,$T1); # Ii+Xi
+
+ &clmul64x64_T3 ($Xhi,$Xi,$Hkey); # H*(Ii+Xi)
+ &reduction_alg5 ($Xhi,$Xi);
+
+ &movdqa ($T3,&QWP(0,$const));
+&set_label("done");
+ &pshufb ($Xi,$T3);
+ &movdqu (&QWP(0,$Xip),$Xi);
+&function_end("gcm_ghash_clmul");
+
+}
+
+&set_label("bswap",64);
+ &data_byte(15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0);
+ &data_byte(1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xc2); # 0x1c2_polynomial
+&set_label("rem_8bit",64);
+ &data_short(0x0000,0x01C2,0x0384,0x0246,0x0708,0x06CA,0x048C,0x054E);
+ &data_short(0x0E10,0x0FD2,0x0D94,0x0C56,0x0918,0x08DA,0x0A9C,0x0B5E);
+ &data_short(0x1C20,0x1DE2,0x1FA4,0x1E66,0x1B28,0x1AEA,0x18AC,0x196E);
+ &data_short(0x1230,0x13F2,0x11B4,0x1076,0x1538,0x14FA,0x16BC,0x177E);
+ &data_short(0x3840,0x3982,0x3BC4,0x3A06,0x3F48,0x3E8A,0x3CCC,0x3D0E);
+ &data_short(0x3650,0x3792,0x35D4,0x3416,0x3158,0x309A,0x32DC,0x331E);
+ &data_short(0x2460,0x25A2,0x27E4,0x2626,0x2368,0x22AA,0x20EC,0x212E);
+ &data_short(0x2A70,0x2BB2,0x29F4,0x2836,0x2D78,0x2CBA,0x2EFC,0x2F3E);
+ &data_short(0x7080,0x7142,0x7304,0x72C6,0x7788,0x764A,0x740C,0x75CE);
+ &data_short(0x7E90,0x7F52,0x7D14,0x7CD6,0x7998,0x785A,0x7A1C,0x7BDE);
+ &data_short(0x6CA0,0x6D62,0x6F24,0x6EE6,0x6BA8,0x6A6A,0x682C,0x69EE);
+ &data_short(0x62B0,0x6372,0x6134,0x60F6,0x65B8,0x647A,0x663C,0x67FE);
+ &data_short(0x48C0,0x4902,0x4B44,0x4A86,0x4FC8,0x4E0A,0x4C4C,0x4D8E);
+ &data_short(0x46D0,0x4712,0x4554,0x4496,0x41D8,0x401A,0x425C,0x439E);
+ &data_short(0x54E0,0x5522,0x5764,0x56A6,0x53E8,0x522A,0x506C,0x51AE);
+ &data_short(0x5AF0,0x5B32,0x5974,0x58B6,0x5DF8,0x5C3A,0x5E7C,0x5FBE);
+ &data_short(0xE100,0xE0C2,0xE284,0xE346,0xE608,0xE7CA,0xE58C,0xE44E);
+ &data_short(0xEF10,0xEED2,0xEC94,0xED56,0xE818,0xE9DA,0xEB9C,0xEA5E);
+ &data_short(0xFD20,0xFCE2,0xFEA4,0xFF66,0xFA28,0xFBEA,0xF9AC,0xF86E);
+ &data_short(0xF330,0xF2F2,0xF0B4,0xF176,0xF438,0xF5FA,0xF7BC,0xF67E);
+ &data_short(0xD940,0xD882,0xDAC4,0xDB06,0xDE48,0xDF8A,0xDDCC,0xDC0E);
+ &data_short(0xD750,0xD692,0xD4D4,0xD516,0xD058,0xD19A,0xD3DC,0xD21E);
+ &data_short(0xC560,0xC4A2,0xC6E4,0xC726,0xC268,0xC3AA,0xC1EC,0xC02E);
+ &data_short(0xCB70,0xCAB2,0xC8F4,0xC936,0xCC78,0xCDBA,0xCFFC,0xCE3E);
+ &data_short(0x9180,0x9042,0x9204,0x93C6,0x9688,0x974A,0x950C,0x94CE);
+ &data_short(0x9F90,0x9E52,0x9C14,0x9DD6,0x9898,0x995A,0x9B1C,0x9ADE);
+ &data_short(0x8DA0,0x8C62,0x8E24,0x8FE6,0x8AA8,0x8B6A,0x892C,0x88EE);
+ &data_short(0x83B0,0x8272,0x8034,0x81F6,0x84B8,0x857A,0x873C,0x86FE);
+ &data_short(0xA9C0,0xA802,0xAA44,0xAB86,0xAEC8,0xAF0A,0xAD4C,0xAC8E);
+ &data_short(0xA7D0,0xA612,0xA454,0xA596,0xA0D8,0xA11A,0xA35C,0xA29E);
+ &data_short(0xB5E0,0xB422,0xB664,0xB7A6,0xB2E8,0xB32A,0xB16C,0xB0AE);
+ &data_short(0xBBF0,0xBA32,0xB874,0xB9B6,0xBCF8,0xBD3A,0xBF7C,0xBEBE);
+}} # $sse2
+
+&set_label("rem_4bit",64);
+ &data_word(0,0x0000<<$S,0,0x1C20<<$S,0,0x3840<<$S,0,0x2460<<$S);
+ &data_word(0,0x7080<<$S,0,0x6CA0<<$S,0,0x48C0<<$S,0,0x54E0<<$S);
+ &data_word(0,0xE100<<$S,0,0xFD20<<$S,0,0xD940<<$S,0,0xC560<<$S);
+ &data_word(0,0x9180<<$S,0,0x8DA0<<$S,0,0xA9C0<<$S,0,0xB5E0<<$S);
+}}} # !$x86only
+
+&asciz("GHASH for x86, CRYPTOGAMS by <appro\@openssl.org>");
+&asm_finish();
+
+# A question was risen about choice of vanilla MMX. Or rather why wasn't
+# SSE2 chosen instead? In addition to the fact that MMX runs on legacy
+# CPUs such as PIII, "4-bit" MMX version was observed to provide better
+# performance than *corresponding* SSE2 one even on contemporary CPUs.
+# SSE2 results were provided by Peter-Michael Hager. He maintains SSE2
+# implementation featuring full range of lookup-table sizes, but with
+# per-invocation lookup table setup. Latter means that table size is
+# chosen depending on how much data is to be hashed in every given call,
+# more data - larger table. Best reported result for Core2 is ~4 cycles
+# per processed byte out of 64KB block. This number accounts even for
+# 64KB table setup overhead. As discussed in gcm128.c we choose to be
+# more conservative in respect to lookup table sizes, but how do the
+# results compare? Minimalistic "256B" MMX version delivers ~11 cycles
+# on same platform. As also discussed in gcm128.c, next in line "8-bit
+# Shoup's" or "4KB" method should deliver twice the performance of
+# "256B" one, in other words not worse than ~6 cycles per byte. It
+# should be also be noted that in SSE2 case improvement can be "super-
+# linear," i.e. more than twice, mostly because >>8 maps to single
+# instruction on SSE2 register. This is unlike "4-bit" case when >>4
+# maps to same amount of instructions in both MMX and SSE2 cases.
+# Bottom line is that switch to SSE2 is considered to be justifiable
+# only in case we choose to implement "8-bit" method...
diff --git a/src/crypto/modes/asm/ghash-x86_64.pl b/src/crypto/modes/asm/ghash-x86_64.pl
new file mode 100644
index 0000000..6e656ca
--- /dev/null
+++ b/src/crypto/modes/asm/ghash-x86_64.pl
@@ -0,0 +1,1753 @@
+#!/usr/bin/env perl
+#
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+# project. The module is, however, dual licensed under OpenSSL and
+# CRYPTOGAMS licenses depending on where you obtain it. For further
+# details see http://www.openssl.org/~appro/cryptogams/.
+# ====================================================================
+#
+# March, June 2010
+#
+# The module implements "4-bit" GCM GHASH function and underlying
+# single multiplication operation in GF(2^128). "4-bit" means that
+# it uses 256 bytes per-key table [+128 bytes shared table]. GHASH
+# function features so called "528B" variant utilizing additional
+# 256+16 bytes of per-key storage [+512 bytes shared table].
+# Performance results are for this streamed GHASH subroutine and are
+# expressed in cycles per processed byte, less is better:
+#
+# gcc 3.4.x(*) assembler
+#
+# P4 28.6 14.0 +100%
+# Opteron 19.3 7.7 +150%
+# Core2 17.8 8.1(**) +120%
+# Atom 31.6 16.8 +88%
+# VIA Nano 21.8 10.1 +115%
+#
+# (*) comparison is not completely fair, because C results are
+# for vanilla "256B" implementation, while assembler results
+# are for "528B";-)
+# (**) it's mystery [to me] why Core2 result is not same as for
+# Opteron;
+
+# May 2010
+#
+# Add PCLMULQDQ version performing at 2.02 cycles per processed byte.
+# See ghash-x86.pl for background information and details about coding
+# techniques.
+#
+# Special thanks to David Woodhouse <dwmw2@infradead.org> for
+# providing access to a Westmere-based system on behalf of Intel
+# Open Source Technology Centre.
+
+# December 2012
+#
+# Overhaul: aggregate Karatsuba post-processing, improve ILP in
+# reduction_alg9, increase reduction aggregate factor to 4x. As for
+# the latter. ghash-x86.pl discusses that it makes lesser sense to
+# increase aggregate factor. Then why increase here? Critical path
+# consists of 3 independent pclmulqdq instructions, Karatsuba post-
+# processing and reduction. "On top" of this we lay down aggregated
+# multiplication operations, triplets of independent pclmulqdq's. As
+# issue rate for pclmulqdq is limited, it makes lesser sense to
+# aggregate more multiplications than it takes to perform remaining
+# non-multiplication operations. 2x is near-optimal coefficient for
+# contemporary Intel CPUs (therefore modest improvement coefficient),
+# but not for Bulldozer. Latter is because logical SIMD operations
+# are twice as slow in comparison to Intel, so that critical path is
+# longer. A CPU with higher pclmulqdq issue rate would also benefit
+# from higher aggregate factor...
+#
+# Westmere 1.78(+13%)
+# Sandy Bridge 1.80(+8%)
+# Ivy Bridge 1.80(+7%)
+# Haswell 0.55(+93%) (if system doesn't support AVX)
+# Broadwell 0.45(+110%)(if system doesn't support AVX)
+# Bulldozer 1.49(+27%)
+# Silvermont 2.88(+13%)
+
+# March 2013
+#
+# ... 8x aggregate factor AVX code path is using reduction algorithm
+# suggested by Shay Gueron[1]. Even though contemporary AVX-capable
+# CPUs such as Sandy and Ivy Bridge can execute it, the code performs
+# sub-optimally in comparison to above mentioned version. But thanks
+# to Ilya Albrekht and Max Locktyukhin of Intel Corp. we knew that
+# it performs in 0.41 cycles per byte on Haswell processor, and in
+# 0.29 on Broadwell.
+#
+# [1] http://rt.openssl.org/Ticket/Display.html?id=2900&user=guest&pass=guest
+
+$flavour = shift;
+$output = shift;
+if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+
+$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
+( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
+die "can't locate x86_64-xlate.pl";
+
+if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
+ =~ /GNU assembler version ([2-9]\.[0-9]+)/) {
+ $avx = ($1>=2.19) + ($1>=2.22);
+}
+
+if (!$avx && $win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) &&
+ `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)/) {
+ $avx = ($1>=2.09) + ($1>=2.10);
+}
+
+if (!$avx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) &&
+ `ml64 2>&1` =~ /Version ([0-9]+)\./) {
+ $avx = ($1>=10) + ($1>=11);
+}
+
+if (!$avx && `$ENV{CC} -v 2>&1` =~ /(^clang version|based on LLVM) ([3-9]\.[0-9]+)/) {
+ $avx = ($2>=3.0) + ($2>3.0);
+}
+
+open OUT,"| \"$^X\" $xlate $flavour $output";
+*STDOUT=*OUT;
+
+$do4xaggr=1;
+
+# common register layout
+$nlo="%rax";
+$nhi="%rbx";
+$Zlo="%r8";
+$Zhi="%r9";
+$tmp="%r10";
+$rem_4bit = "%r11";
+
+$Xi="%rdi";
+$Htbl="%rsi";
+
+# per-function register layout
+$cnt="%rcx";
+$rem="%rdx";
+
+sub LB() { my $r=shift; $r =~ s/%[er]([a-d])x/%\1l/ or
+ $r =~ s/%[er]([sd]i)/%\1l/ or
+ $r =~ s/%[er](bp)/%\1l/ or
+ $r =~ s/%(r[0-9]+)[d]?/%\1b/; $r; }
+
+sub AUTOLOAD() # thunk [simplified] 32-bit style perlasm
+{ my $opcode = $AUTOLOAD; $opcode =~ s/.*:://;
+ my $arg = pop;
+ $arg = "\$$arg" if ($arg*1 eq $arg);
+ $code .= "\t$opcode\t".join(',',$arg,reverse @_)."\n";
+}
+
+{ my $N;
+ sub loop() {
+ my $inp = shift;
+
+ $N++;
+$code.=<<___;
+ xor $nlo,$nlo
+ xor $nhi,$nhi
+ mov `&LB("$Zlo")`,`&LB("$nlo")`
+ mov `&LB("$Zlo")`,`&LB("$nhi")`
+ shl \$4,`&LB("$nlo")`
+ mov \$14,$cnt
+ mov 8($Htbl,$nlo),$Zlo
+ mov ($Htbl,$nlo),$Zhi
+ and \$0xf0,`&LB("$nhi")`
+ mov $Zlo,$rem
+ jmp .Loop$N
+
+.align 16
+.Loop$N:
+ shr \$4,$Zlo
+ and \$0xf,$rem
+ mov $Zhi,$tmp
+ mov ($inp,$cnt),`&LB("$nlo")`
+ shr \$4,$Zhi
+ xor 8($Htbl,$nhi),$Zlo
+ shl \$60,$tmp
+ xor ($Htbl,$nhi),$Zhi
+ mov `&LB("$nlo")`,`&LB("$nhi")`
+ xor ($rem_4bit,$rem,8),$Zhi
+ mov $Zlo,$rem
+ shl \$4,`&LB("$nlo")`
+ xor $tmp,$Zlo
+ dec $cnt
+ js .Lbreak$N
+
+ shr \$4,$Zlo
+ and \$0xf,$rem
+ mov $Zhi,$tmp
+ shr \$4,$Zhi
+ xor 8($Htbl,$nlo),$Zlo
+ shl \$60,$tmp
+ xor ($Htbl,$nlo),$Zhi
+ and \$0xf0,`&LB("$nhi")`
+ xor ($rem_4bit,$rem,8),$Zhi
+ mov $Zlo,$rem
+ xor $tmp,$Zlo
+ jmp .Loop$N
+
+.align 16
+.Lbreak$N:
+ shr \$4,$Zlo
+ and \$0xf,$rem
+ mov $Zhi,$tmp
+ shr \$4,$Zhi
+ xor 8($Htbl,$nlo),$Zlo
+ shl \$60,$tmp
+ xor ($Htbl,$nlo),$Zhi
+ and \$0xf0,`&LB("$nhi")`
+ xor ($rem_4bit,$rem,8),$Zhi
+ mov $Zlo,$rem
+ xor $tmp,$Zlo
+
+ shr \$4,$Zlo
+ and \$0xf,$rem
+ mov $Zhi,$tmp
+ shr \$4,$Zhi
+ xor 8($Htbl,$nhi),$Zlo
+ shl \$60,$tmp
+ xor ($Htbl,$nhi),$Zhi
+ xor $tmp,$Zlo
+ xor ($rem_4bit,$rem,8),$Zhi
+
+ bswap $Zlo
+ bswap $Zhi
+___
+}}
+
+$code=<<___;
+.text
+.extern OPENSSL_ia32cap_P
+
+.globl gcm_gmult_4bit
+.type gcm_gmult_4bit,\@function,2
+.align 16
+gcm_gmult_4bit:
+ push %rbx
+ push %rbp # %rbp and %r12 are pushed exclusively in
+ push %r12 # order to reuse Win64 exception handler...
+.Lgmult_prologue:
+
+ movzb 15($Xi),$Zlo
+ lea .Lrem_4bit(%rip),$rem_4bit
+___
+ &loop ($Xi);
+$code.=<<___;
+ mov $Zlo,8($Xi)
+ mov $Zhi,($Xi)
+
+ mov 16(%rsp),%rbx
+ lea 24(%rsp),%rsp
+.Lgmult_epilogue:
+ ret
+.size gcm_gmult_4bit,.-gcm_gmult_4bit
+___
+
+# per-function register layout
+$inp="%rdx";
+$len="%rcx";
+$rem_8bit=$rem_4bit;
+
+$code.=<<___;
+.globl gcm_ghash_4bit
+.type gcm_ghash_4bit,\@function,4
+.align 16
+gcm_ghash_4bit:
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+ sub \$280,%rsp
+.Lghash_prologue:
+ mov $inp,%r14 # reassign couple of args
+ mov $len,%r15
+___
+{ my $inp="%r14";
+ my $dat="%edx";
+ my $len="%r15";
+ my @nhi=("%ebx","%ecx");
+ my @rem=("%r12","%r13");
+ my $Hshr4="%rbp";
+
+ &sub ($Htbl,-128); # size optimization
+ &lea ($Hshr4,"16+128(%rsp)");
+ { my @lo =($nlo,$nhi);
+ my @hi =($Zlo,$Zhi);
+
+ &xor ($dat,$dat);
+ for ($i=0,$j=-2;$i<18;$i++,$j++) {
+ &mov ("$j(%rsp)",&LB($dat)) if ($i>1);
+ &or ($lo[0],$tmp) if ($i>1);
+ &mov (&LB($dat),&LB($lo[1])) if ($i>0 && $i<17);
+ &shr ($lo[1],4) if ($i>0 && $i<17);
+ &mov ($tmp,$hi[1]) if ($i>0 && $i<17);
+ &shr ($hi[1],4) if ($i>0 && $i<17);
+ &mov ("8*$j($Hshr4)",$hi[0]) if ($i>1);
+ &mov ($hi[0],"16*$i+0-128($Htbl)") if ($i<16);
+ &shl (&LB($dat),4) if ($i>0 && $i<17);
+ &mov ("8*$j-128($Hshr4)",$lo[0]) if ($i>1);
+ &mov ($lo[0],"16*$i+8-128($Htbl)") if ($i<16);
+ &shl ($tmp,60) if ($i>0 && $i<17);
+
+ push (@lo,shift(@lo));
+ push (@hi,shift(@hi));
+ }
+ }
+ &add ($Htbl,-128);
+ &mov ($Zlo,"8($Xi)");
+ &mov ($Zhi,"0($Xi)");
+ &add ($len,$inp); # pointer to the end of data
+ &lea ($rem_8bit,".Lrem_8bit(%rip)");
+ &jmp (".Louter_loop");
+
+$code.=".align 16\n.Louter_loop:\n";
+ &xor ($Zhi,"($inp)");
+ &mov ("%rdx","8($inp)");
+ &lea ($inp,"16($inp)");
+ &xor ("%rdx",$Zlo);
+ &mov ("($Xi)",$Zhi);
+ &mov ("8($Xi)","%rdx");
+ &shr ("%rdx",32);
+
+ &xor ($nlo,$nlo);
+ &rol ($dat,8);
+ &mov (&LB($nlo),&LB($dat));
+ &movz ($nhi[0],&LB($dat));
+ &shl (&LB($nlo),4);
+ &shr ($nhi[0],4);
+
+ for ($j=11,$i=0;$i<15;$i++) {
+ &rol ($dat,8);
+ &xor ($Zlo,"8($Htbl,$nlo)") if ($i>0);
+ &xor ($Zhi,"($Htbl,$nlo)") if ($i>0);
+ &mov ($Zlo,"8($Htbl,$nlo)") if ($i==0);
+ &mov ($Zhi,"($Htbl,$nlo)") if ($i==0);
+
+ &mov (&LB($nlo),&LB($dat));
+ &xor ($Zlo,$tmp) if ($i>0);
+ &movzw ($rem[1],"($rem_8bit,$rem[1],2)") if ($i>0);
+
+ &movz ($nhi[1],&LB($dat));
+ &shl (&LB($nlo),4);
+ &movzb ($rem[0],"(%rsp,$nhi[0])");
+
+ &shr ($nhi[1],4) if ($i<14);
+ &and ($nhi[1],0xf0) if ($i==14);
+ &shl ($rem[1],48) if ($i>0);
+ &xor ($rem[0],$Zlo);
+
+ &mov ($tmp,$Zhi);
+ &xor ($Zhi,$rem[1]) if ($i>0);
+ &shr ($Zlo,8);
+
+ &movz ($rem[0],&LB($rem[0]));
+ &mov ($dat,"$j($Xi)") if (--$j%4==0);
+ &shr ($Zhi,8);
+
+ &xor ($Zlo,"-128($Hshr4,$nhi[0],8)");
+ &shl ($tmp,56);
+ &xor ($Zhi,"($Hshr4,$nhi[0],8)");
+
+ unshift (@nhi,pop(@nhi)); # "rotate" registers
+ unshift (@rem,pop(@rem));
+ }
+ &movzw ($rem[1],"($rem_8bit,$rem[1],2)");
+ &xor ($Zlo,"8($Htbl,$nlo)");
+ &xor ($Zhi,"($Htbl,$nlo)");
+
+ &shl ($rem[1],48);
+ &xor ($Zlo,$tmp);
+
+ &xor ($Zhi,$rem[1]);
+ &movz ($rem[0],&LB($Zlo));
+ &shr ($Zlo,4);
+
+ &mov ($tmp,$Zhi);
+ &shl (&LB($rem[0]),4);
+ &shr ($Zhi,4);
+
+ &xor ($Zlo,"8($Htbl,$nhi[0])");
+ &movzw ($rem[0],"($rem_8bit,$rem[0],2)");
+ &shl ($tmp,60);
+
+ &xor ($Zhi,"($Htbl,$nhi[0])");
+ &xor ($Zlo,$tmp);
+ &shl ($rem[0],48);
+
+ &bswap ($Zlo);
+ &xor ($Zhi,$rem[0]);
+
+ &bswap ($Zhi);
+ &cmp ($inp,$len);
+ &jb (".Louter_loop");
+}
+$code.=<<___;
+ mov $Zlo,8($Xi)
+ mov $Zhi,($Xi)
+
+ lea 280(%rsp),%rsi
+ mov 0(%rsi),%r15
+ mov 8(%rsi),%r14
+ mov 16(%rsi),%r13
+ mov 24(%rsi),%r12
+ mov 32(%rsi),%rbp
+ mov 40(%rsi),%rbx
+ lea 48(%rsi),%rsp
+.Lghash_epilogue:
+ ret
+.size gcm_ghash_4bit,.-gcm_ghash_4bit
+___
+
+######################################################################
+# PCLMULQDQ version.
+
+@_4args=$win64? ("%rcx","%rdx","%r8", "%r9") : # Win64 order
+ ("%rdi","%rsi","%rdx","%rcx"); # Unix order
+
+($Xi,$Xhi)=("%xmm0","%xmm1"); $Hkey="%xmm2";
+($T1,$T2,$T3)=("%xmm3","%xmm4","%xmm5");
+
+sub clmul64x64_T2 { # minimal register pressure
+my ($Xhi,$Xi,$Hkey,$HK)=@_;
+
+if (!defined($HK)) { $HK = $T2;
+$code.=<<___;
+ movdqa $Xi,$Xhi #
+ pshufd \$0b01001110,$Xi,$T1
+ pshufd \$0b01001110,$Hkey,$T2
+ pxor $Xi,$T1 #
+ pxor $Hkey,$T2
+___
+} else {
+$code.=<<___;
+ movdqa $Xi,$Xhi #
+ pshufd \$0b01001110,$Xi,$T1
+ pxor $Xi,$T1 #
+___
+}
+$code.=<<___;
+ pclmulqdq \$0x00,$Hkey,$Xi #######
+ pclmulqdq \$0x11,$Hkey,$Xhi #######
+ pclmulqdq \$0x00,$HK,$T1 #######
+ pxor $Xi,$T1 #
+ pxor $Xhi,$T1 #
+
+ movdqa $T1,$T2 #
+ psrldq \$8,$T1
+ pslldq \$8,$T2 #
+ pxor $T1,$Xhi
+ pxor $T2,$Xi #
+___
+}
+
+sub reduction_alg9 { # 17/11 times faster than Intel version
+my ($Xhi,$Xi) = @_;
+
+$code.=<<___;
+ # 1st phase
+ movdqa $Xi,$T2 #
+ movdqa $Xi,$T1
+ psllq \$5,$Xi
+ pxor $Xi,$T1 #
+ psllq \$1,$Xi
+ pxor $T1,$Xi #
+ psllq \$57,$Xi #
+ movdqa $Xi,$T1 #
+ pslldq \$8,$Xi
+ psrldq \$8,$T1 #
+ pxor $T2,$Xi
+ pxor $T1,$Xhi #
+
+ # 2nd phase
+ movdqa $Xi,$T2
+ psrlq \$1,$Xi
+ pxor $T2,$Xhi #
+ pxor $Xi,$T2
+ psrlq \$5,$Xi
+ pxor $T2,$Xi #
+ psrlq \$1,$Xi #
+ pxor $Xhi,$Xi #
+___
+}
+
+{ my ($Htbl,$Xip)=@_4args;
+ my $HK="%xmm6";
+
+$code.=<<___;
+.globl gcm_init_clmul
+.type gcm_init_clmul,\@abi-omnipotent
+.align 16
+gcm_init_clmul:
+.L_init_clmul:
+___
+$code.=<<___ if ($win64);
+.LSEH_begin_gcm_init_clmul:
+ # I can't trust assembler to use specific encoding:-(
+ .byte 0x48,0x83,0xec,0x18 #sub $0x18,%rsp
+ .byte 0x0f,0x29,0x34,0x24 #movaps %xmm6,(%rsp)
+___
+$code.=<<___;
+ movdqu ($Xip),$Hkey
+ pshufd \$0b01001110,$Hkey,$Hkey # dword swap
+
+ # <<1 twist
+ pshufd \$0b11111111,$Hkey,$T2 # broadcast uppermost dword
+ movdqa $Hkey,$T1
+ psllq \$1,$Hkey
+ pxor $T3,$T3 #
+ psrlq \$63,$T1
+ pcmpgtd $T2,$T3 # broadcast carry bit
+ pslldq \$8,$T1
+ por $T1,$Hkey # H<<=1
+
+ # magic reduction
+ pand .L0x1c2_polynomial(%rip),$T3
+ pxor $T3,$Hkey # if(carry) H^=0x1c2_polynomial
+
+ # calculate H^2
+ pshufd \$0b01001110,$Hkey,$HK
+ movdqa $Hkey,$Xi
+ pxor $Hkey,$HK
+___
+ &clmul64x64_T2 ($Xhi,$Xi,$Hkey,$HK);
+ &reduction_alg9 ($Xhi,$Xi);
+$code.=<<___;
+ pshufd \$0b01001110,$Hkey,$T1
+ pshufd \$0b01001110,$Xi,$T2
+ pxor $Hkey,$T1 # Karatsuba pre-processing
+ movdqu $Hkey,0x00($Htbl) # save H
+ pxor $Xi,$T2 # Karatsuba pre-processing
+ movdqu $Xi,0x10($Htbl) # save H^2
+ palignr \$8,$T1,$T2 # low part is H.lo^H.hi...
+ movdqu $T2,0x20($Htbl) # save Karatsuba "salt"
+___
+if ($do4xaggr) {
+ &clmul64x64_T2 ($Xhi,$Xi,$Hkey,$HK); # H^3
+ &reduction_alg9 ($Xhi,$Xi);
+$code.=<<___;
+ movdqa $Xi,$T3
+___
+ &clmul64x64_T2 ($Xhi,$Xi,$Hkey,$HK); # H^4
+ &reduction_alg9 ($Xhi,$Xi);
+$code.=<<___;
+ pshufd \$0b01001110,$T3,$T1
+ pshufd \$0b01001110,$Xi,$T2
+ pxor $T3,$T1 # Karatsuba pre-processing
+ movdqu $T3,0x30($Htbl) # save H^3
+ pxor $Xi,$T2 # Karatsuba pre-processing
+ movdqu $Xi,0x40($Htbl) # save H^4
+ palignr \$8,$T1,$T2 # low part is H^3.lo^H^3.hi...
+ movdqu $T2,0x50($Htbl) # save Karatsuba "salt"
+___
+}
+$code.=<<___ if ($win64);
+ movaps (%rsp),%xmm6
+ lea 0x18(%rsp),%rsp
+.LSEH_end_gcm_init_clmul:
+___
+$code.=<<___;
+ ret
+.size gcm_init_clmul,.-gcm_init_clmul
+___
+}
+
+{ my ($Xip,$Htbl)=@_4args;
+
+$code.=<<___;
+.globl gcm_gmult_clmul
+.type gcm_gmult_clmul,\@abi-omnipotent
+.align 16
+gcm_gmult_clmul:
+.L_gmult_clmul:
+ movdqu ($Xip),$Xi
+ movdqa .Lbswap_mask(%rip),$T3
+ movdqu ($Htbl),$Hkey
+ movdqu 0x20($Htbl),$T2
+ pshufb $T3,$Xi
+___
+ &clmul64x64_T2 ($Xhi,$Xi,$Hkey,$T2);
+$code.=<<___ if (0 || (&reduction_alg9($Xhi,$Xi)&&0));
+ # experimental alternative. special thing about is that there
+ # no dependency between the two multiplications...
+ mov \$`0xE1<<1`,%eax
+ mov \$0xA040608020C0E000,%r10 # ((7..0)·0xE0)&0xff
+ mov \$0x07,%r11d
+ movq %rax,$T1
+ movq %r10,$T2
+ movq %r11,$T3 # borrow $T3
+ pand $Xi,$T3
+ pshufb $T3,$T2 # ($Xi&7)·0xE0
+ movq %rax,$T3
+ pclmulqdq \$0x00,$Xi,$T1 # ·(0xE1<<1)
+ pxor $Xi,$T2
+ pslldq \$15,$T2
+ paddd $T2,$T2 # <<(64+56+1)
+ pxor $T2,$Xi
+ pclmulqdq \$0x01,$T3,$Xi
+ movdqa .Lbswap_mask(%rip),$T3 # reload $T3
+ psrldq \$1,$T1
+ pxor $T1,$Xhi
+ pslldq \$7,$Xi
+ pxor $Xhi,$Xi
+___
+$code.=<<___;
+ pshufb $T3,$Xi
+ movdqu $Xi,($Xip)
+ ret
+.size gcm_gmult_clmul,.-gcm_gmult_clmul
+___
+}
+
+{ my ($Xip,$Htbl,$inp,$len)=@_4args;
+ my ($Xln,$Xmn,$Xhn,$Hkey2,$HK) = map("%xmm$_",(3..7));
+ my ($T1,$T2,$T3)=map("%xmm$_",(8..10));
+
+$code.=<<___;
+.globl gcm_ghash_clmul
+.type gcm_ghash_clmul,\@abi-omnipotent
+.align 32
+gcm_ghash_clmul:
+.L_ghash_clmul:
+___
+$code.=<<___ if ($win64);
+ lea -0x88(%rsp),%rax
+.LSEH_begin_gcm_ghash_clmul:
+ # I can't trust assembler to use specific encoding:-(
+ .byte 0x48,0x8d,0x60,0xe0 #lea -0x20(%rax),%rsp
+ .byte 0x0f,0x29,0x70,0xe0 #movaps %xmm6,-0x20(%rax)
+ .byte 0x0f,0x29,0x78,0xf0 #movaps %xmm7,-0x10(%rax)
+ .byte 0x44,0x0f,0x29,0x00 #movaps %xmm8,0(%rax)
+ .byte 0x44,0x0f,0x29,0x48,0x10 #movaps %xmm9,0x10(%rax)
+ .byte 0x44,0x0f,0x29,0x50,0x20 #movaps %xmm10,0x20(%rax)
+ .byte 0x44,0x0f,0x29,0x58,0x30 #movaps %xmm11,0x30(%rax)
+ .byte 0x44,0x0f,0x29,0x60,0x40 #movaps %xmm12,0x40(%rax)
+ .byte 0x44,0x0f,0x29,0x68,0x50 #movaps %xmm13,0x50(%rax)
+ .byte 0x44,0x0f,0x29,0x70,0x60 #movaps %xmm14,0x60(%rax)
+ .byte 0x44,0x0f,0x29,0x78,0x70 #movaps %xmm15,0x70(%rax)
+___
+$code.=<<___;
+ movdqa .Lbswap_mask(%rip),$T3
+
+ movdqu ($Xip),$Xi
+ movdqu ($Htbl),$Hkey
+ movdqu 0x20($Htbl),$HK
+ pshufb $T3,$Xi
+
+ sub \$0x10,$len
+ jz .Lodd_tail
+
+ movdqu 0x10($Htbl),$Hkey2
+___
+if ($do4xaggr) {
+my ($Xl,$Xm,$Xh,$Hkey3,$Hkey4)=map("%xmm$_",(11..15));
+
+$code.=<<___;
+ mov OPENSSL_ia32cap_P+4(%rip),%eax
+ cmp \$0x30,$len
+ jb .Lskip4x
+
+ and \$`1<<26|1<<22`,%eax # isolate MOVBE+XSAVE
+ cmp \$`1<<22`,%eax # check for MOVBE without XSAVE
+ je .Lskip4x
+
+ sub \$0x30,$len
+ mov \$0xA040608020C0E000,%rax # ((7..0)·0xE0)&0xff
+ movdqu 0x30($Htbl),$Hkey3
+ movdqu 0x40($Htbl),$Hkey4
+
+ #######
+ # Xi+4 =[(H*Ii+3) + (H^2*Ii+2) + (H^3*Ii+1) + H^4*(Ii+Xi)] mod P
+ #
+ movdqu 0x30($inp),$Xln
+ movdqu 0x20($inp),$Xl
+ pshufb $T3,$Xln
+ pshufb $T3,$Xl
+ movdqa $Xln,$Xhn
+ pshufd \$0b01001110,$Xln,$Xmn
+ pxor $Xln,$Xmn
+ pclmulqdq \$0x00,$Hkey,$Xln
+ pclmulqdq \$0x11,$Hkey,$Xhn
+ pclmulqdq \$0x00,$HK,$Xmn
+
+ movdqa $Xl,$Xh
+ pshufd \$0b01001110,$Xl,$Xm
+ pxor $Xl,$Xm
+ pclmulqdq \$0x00,$Hkey2,$Xl
+ pclmulqdq \$0x11,$Hkey2,$Xh
+ pclmulqdq \$0x10,$HK,$Xm
+ xorps $Xl,$Xln
+ xorps $Xh,$Xhn
+ movups 0x50($Htbl),$HK
+ xorps $Xm,$Xmn
+
+ movdqu 0x10($inp),$Xl
+ movdqu 0($inp),$T1
+ pshufb $T3,$Xl
+ pshufb $T3,$T1
+ movdqa $Xl,$Xh
+ pshufd \$0b01001110,$Xl,$Xm
+ pxor $T1,$Xi
+ pxor $Xl,$Xm
+ pclmulqdq \$0x00,$Hkey3,$Xl
+ movdqa $Xi,$Xhi
+ pshufd \$0b01001110,$Xi,$T1
+ pxor $Xi,$T1
+ pclmulqdq \$0x11,$Hkey3,$Xh
+ pclmulqdq \$0x00,$HK,$Xm
+ xorps $Xl,$Xln
+ xorps $Xh,$Xhn
+
+ lea 0x40($inp),$inp
+ sub \$0x40,$len
+ jc .Ltail4x
+
+ jmp .Lmod4_loop
+.align 32
+.Lmod4_loop:
+ pclmulqdq \$0x00,$Hkey4,$Xi
+ xorps $Xm,$Xmn
+ movdqu 0x30($inp),$Xl
+ pshufb $T3,$Xl
+ pclmulqdq \$0x11,$Hkey4,$Xhi
+ xorps $Xln,$Xi
+ movdqu 0x20($inp),$Xln
+ movdqa $Xl,$Xh
+ pclmulqdq \$0x10,$HK,$T1
+ pshufd \$0b01001110,$Xl,$Xm
+ xorps $Xhn,$Xhi
+ pxor $Xl,$Xm
+ pshufb $T3,$Xln
+ movups 0x20($Htbl),$HK
+ xorps $Xmn,$T1
+ pclmulqdq \$0x00,$Hkey,$Xl
+ pshufd \$0b01001110,$Xln,$Xmn
+
+ pxor $Xi,$T1 # aggregated Karatsuba post-processing
+ movdqa $Xln,$Xhn
+ pxor $Xhi,$T1 #
+ pxor $Xln,$Xmn
+ movdqa $T1,$T2 #
+ pclmulqdq \$0x11,$Hkey,$Xh
+ pslldq \$8,$T1
+ psrldq \$8,$T2 #
+ pxor $T1,$Xi
+ movdqa .L7_mask(%rip),$T1
+ pxor $T2,$Xhi #
+ movq %rax,$T2
+
+ pand $Xi,$T1 # 1st phase
+ pshufb $T1,$T2 #
+ pxor $Xi,$T2 #
+ pclmulqdq \$0x00,$HK,$Xm
+ psllq \$57,$T2 #
+ movdqa $T2,$T1 #
+ pslldq \$8,$T2
+ pclmulqdq \$0x00,$Hkey2,$Xln
+ psrldq \$8,$T1 #
+ pxor $T2,$Xi
+ pxor $T1,$Xhi #
+ movdqu 0($inp),$T1
+
+ movdqa $Xi,$T2 # 2nd phase
+ psrlq \$1,$Xi
+ pclmulqdq \$0x11,$Hkey2,$Xhn
+ xorps $Xl,$Xln
+ movdqu 0x10($inp),$Xl
+ pshufb $T3,$Xl
+ pclmulqdq \$0x10,$HK,$Xmn
+ xorps $Xh,$Xhn
+ movups 0x50($Htbl),$HK
+ pshufb $T3,$T1
+ pxor $T2,$Xhi #
+ pxor $Xi,$T2
+ psrlq \$5,$Xi
+
+ movdqa $Xl,$Xh
+ pxor $Xm,$Xmn
+ pshufd \$0b01001110,$Xl,$Xm
+ pxor $T2,$Xi #
+ pxor $T1,$Xhi
+ pxor $Xl,$Xm
+ pclmulqdq \$0x00,$Hkey3,$Xl
+ psrlq \$1,$Xi #
+ pxor $Xhi,$Xi #
+ movdqa $Xi,$Xhi
+ pclmulqdq \$0x11,$Hkey3,$Xh
+ xorps $Xl,$Xln
+ pshufd \$0b01001110,$Xi,$T1
+ pxor $Xi,$T1
+
+ pclmulqdq \$0x00,$HK,$Xm
+ xorps $Xh,$Xhn
+
+ lea 0x40($inp),$inp
+ sub \$0x40,$len
+ jnc .Lmod4_loop
+
+.Ltail4x:
+ pclmulqdq \$0x00,$Hkey4,$Xi
+ pclmulqdq \$0x11,$Hkey4,$Xhi
+ pclmulqdq \$0x10,$HK,$T1
+ xorps $Xm,$Xmn
+ xorps $Xln,$Xi
+ xorps $Xhn,$Xhi
+ pxor $Xi,$Xhi # aggregated Karatsuba post-processing
+ pxor $Xmn,$T1
+
+ pxor $Xhi,$T1 #
+ pxor $Xi,$Xhi
+
+ movdqa $T1,$T2 #
+ psrldq \$8,$T1
+ pslldq \$8,$T2 #
+ pxor $T1,$Xhi
+ pxor $T2,$Xi #
+___
+ &reduction_alg9($Xhi,$Xi);
+$code.=<<___;
+ add \$0x40,$len
+ jz .Ldone
+ movdqu 0x20($Htbl),$HK
+ sub \$0x10,$len
+ jz .Lodd_tail
+.Lskip4x:
+___
+}
+$code.=<<___;
+ #######
+ # Xi+2 =[H*(Ii+1 + Xi+1)] mod P =
+ # [(H*Ii+1) + (H*Xi+1)] mod P =
+ # [(H*Ii+1) + H^2*(Ii+Xi)] mod P
+ #
+ movdqu ($inp),$T1 # Ii
+ movdqu 16($inp),$Xln # Ii+1
+ pshufb $T3,$T1
+ pshufb $T3,$Xln
+ pxor $T1,$Xi # Ii+Xi
+
+ movdqa $Xln,$Xhn
+ pshufd \$0b01001110,$Xln,$Xmn
+ pxor $Xln,$Xmn
+ pclmulqdq \$0x00,$Hkey,$Xln
+ pclmulqdq \$0x11,$Hkey,$Xhn
+ pclmulqdq \$0x00,$HK,$Xmn
+
+ lea 32($inp),$inp # i+=2
+ nop
+ sub \$0x20,$len
+ jbe .Leven_tail
+ nop
+ jmp .Lmod_loop
+
+.align 32
+.Lmod_loop:
+ movdqa $Xi,$Xhi
+ movdqa $Xmn,$T1
+ pshufd \$0b01001110,$Xi,$Xmn #
+ pxor $Xi,$Xmn #
+
+ pclmulqdq \$0x00,$Hkey2,$Xi
+ pclmulqdq \$0x11,$Hkey2,$Xhi
+ pclmulqdq \$0x10,$HK,$Xmn
+
+ pxor $Xln,$Xi # (H*Ii+1) + H^2*(Ii+Xi)
+ pxor $Xhn,$Xhi
+ movdqu ($inp),$T2 # Ii
+ pxor $Xi,$T1 # aggregated Karatsuba post-processing
+ pshufb $T3,$T2
+ movdqu 16($inp),$Xln # Ii+1
+
+ pxor $Xhi,$T1
+ pxor $T2,$Xhi # "Ii+Xi", consume early
+ pxor $T1,$Xmn
+ pshufb $T3,$Xln
+ movdqa $Xmn,$T1 #
+ psrldq \$8,$T1
+ pslldq \$8,$Xmn #
+ pxor $T1,$Xhi
+ pxor $Xmn,$Xi #
+
+ movdqa $Xln,$Xhn #
+
+ movdqa $Xi,$T2 # 1st phase
+ movdqa $Xi,$T1
+ psllq \$5,$Xi
+ pxor $Xi,$T1 #
+ pclmulqdq \$0x00,$Hkey,$Xln #######
+ psllq \$1,$Xi
+ pxor $T1,$Xi #
+ psllq \$57,$Xi #
+ movdqa $Xi,$T1 #
+ pslldq \$8,$Xi
+ psrldq \$8,$T1 #
+ pxor $T2,$Xi
+ pshufd \$0b01001110,$Xhn,$Xmn
+ pxor $T1,$Xhi #
+ pxor $Xhn,$Xmn #
+
+ movdqa $Xi,$T2 # 2nd phase
+ psrlq \$1,$Xi
+ pclmulqdq \$0x11,$Hkey,$Xhn #######
+ pxor $T2,$Xhi #
+ pxor $Xi,$T2
+ psrlq \$5,$Xi
+ pxor $T2,$Xi #
+ lea 32($inp),$inp
+ psrlq \$1,$Xi #
+ pclmulqdq \$0x00,$HK,$Xmn #######
+ pxor $Xhi,$Xi #
+
+ sub \$0x20,$len
+ ja .Lmod_loop
+
+.Leven_tail:
+ movdqa $Xi,$Xhi
+ movdqa $Xmn,$T1
+ pshufd \$0b01001110,$Xi,$Xmn #
+ pxor $Xi,$Xmn #
+
+ pclmulqdq \$0x00,$Hkey2,$Xi
+ pclmulqdq \$0x11,$Hkey2,$Xhi
+ pclmulqdq \$0x10,$HK,$Xmn
+
+ pxor $Xln,$Xi # (H*Ii+1) + H^2*(Ii+Xi)
+ pxor $Xhn,$Xhi
+ pxor $Xi,$T1
+ pxor $Xhi,$T1
+ pxor $T1,$Xmn
+ movdqa $Xmn,$T1 #
+ psrldq \$8,$T1
+ pslldq \$8,$Xmn #
+ pxor $T1,$Xhi
+ pxor $Xmn,$Xi #
+___
+ &reduction_alg9 ($Xhi,$Xi);
+$code.=<<___;
+ test $len,$len
+ jnz .Ldone
+
+.Lodd_tail:
+ movdqu ($inp),$T1 # Ii
+ pshufb $T3,$T1
+ pxor $T1,$Xi # Ii+Xi
+___
+ &clmul64x64_T2 ($Xhi,$Xi,$Hkey,$HK); # H*(Ii+Xi)
+ &reduction_alg9 ($Xhi,$Xi);
+$code.=<<___;
+.Ldone:
+ pshufb $T3,$Xi
+ movdqu $Xi,($Xip)
+___
+$code.=<<___ if ($win64);
+ movaps (%rsp),%xmm6
+ movaps 0x10(%rsp),%xmm7
+ movaps 0x20(%rsp),%xmm8
+ movaps 0x30(%rsp),%xmm9
+ movaps 0x40(%rsp),%xmm10
+ movaps 0x50(%rsp),%xmm11
+ movaps 0x60(%rsp),%xmm12
+ movaps 0x70(%rsp),%xmm13
+ movaps 0x80(%rsp),%xmm14
+ movaps 0x90(%rsp),%xmm15
+ lea 0xa8(%rsp),%rsp
+.LSEH_end_gcm_ghash_clmul:
+___
+$code.=<<___;
+ ret
+.size gcm_ghash_clmul,.-gcm_ghash_clmul
+___
+}
+
+$code.=<<___;
+.globl gcm_init_avx
+.type gcm_init_avx,\@abi-omnipotent
+.align 32
+gcm_init_avx:
+___
+if ($avx) {
+my ($Htbl,$Xip)=@_4args;
+my $HK="%xmm6";
+
+$code.=<<___ if ($win64);
+.LSEH_begin_gcm_init_avx:
+ # I can't trust assembler to use specific encoding:-(
+ .byte 0x48,0x83,0xec,0x18 #sub $0x18,%rsp
+ .byte 0x0f,0x29,0x34,0x24 #movaps %xmm6,(%rsp)
+___
+$code.=<<___;
+ vzeroupper
+
+ vmovdqu ($Xip),$Hkey
+ vpshufd \$0b01001110,$Hkey,$Hkey # dword swap
+
+ # <<1 twist
+ vpshufd \$0b11111111,$Hkey,$T2 # broadcast uppermost dword
+ vpsrlq \$63,$Hkey,$T1
+ vpsllq \$1,$Hkey,$Hkey
+ vpxor $T3,$T3,$T3 #
+ vpcmpgtd $T2,$T3,$T3 # broadcast carry bit
+ vpslldq \$8,$T1,$T1
+ vpor $T1,$Hkey,$Hkey # H<<=1
+
+ # magic reduction
+ vpand .L0x1c2_polynomial(%rip),$T3,$T3
+ vpxor $T3,$Hkey,$Hkey # if(carry) H^=0x1c2_polynomial
+
+ vpunpckhqdq $Hkey,$Hkey,$HK
+ vmovdqa $Hkey,$Xi
+ vpxor $Hkey,$HK,$HK
+ mov \$4,%r10 # up to H^8
+ jmp .Linit_start_avx
+___
+
+sub clmul64x64_avx {
+my ($Xhi,$Xi,$Hkey,$HK)=@_;
+
+if (!defined($HK)) { $HK = $T2;
+$code.=<<___;
+ vpunpckhqdq $Xi,$Xi,$T1
+ vpunpckhqdq $Hkey,$Hkey,$T2
+ vpxor $Xi,$T1,$T1 #
+ vpxor $Hkey,$T2,$T2
+___
+} else {
+$code.=<<___;
+ vpunpckhqdq $Xi,$Xi,$T1
+ vpxor $Xi,$T1,$T1 #
+___
+}
+$code.=<<___;
+ vpclmulqdq \$0x11,$Hkey,$Xi,$Xhi #######
+ vpclmulqdq \$0x00,$Hkey,$Xi,$Xi #######
+ vpclmulqdq \$0x00,$HK,$T1,$T1 #######
+ vpxor $Xi,$Xhi,$T2 #
+ vpxor $T2,$T1,$T1 #
+
+ vpslldq \$8,$T1,$T2 #
+ vpsrldq \$8,$T1,$T1
+ vpxor $T2,$Xi,$Xi #
+ vpxor $T1,$Xhi,$Xhi
+___
+}
+
+sub reduction_avx {
+my ($Xhi,$Xi) = @_;
+
+$code.=<<___;
+ vpsllq \$57,$Xi,$T1 # 1st phase
+ vpsllq \$62,$Xi,$T2
+ vpxor $T1,$T2,$T2 #
+ vpsllq \$63,$Xi,$T1
+ vpxor $T1,$T2,$T2 #
+ vpslldq \$8,$T2,$T1 #
+ vpsrldq \$8,$T2,$T2
+ vpxor $T1,$Xi,$Xi #
+ vpxor $T2,$Xhi,$Xhi
+
+ vpsrlq \$1,$Xi,$T2 # 2nd phase
+ vpxor $Xi,$Xhi,$Xhi
+ vpxor $T2,$Xi,$Xi #
+ vpsrlq \$5,$T2,$T2
+ vpxor $T2,$Xi,$Xi #
+ vpsrlq \$1,$Xi,$Xi #
+ vpxor $Xhi,$Xi,$Xi #
+___
+}
+
+$code.=<<___;
+.align 32
+.Linit_loop_avx:
+ vpalignr \$8,$T1,$T2,$T3 # low part is H.lo^H.hi...
+ vmovdqu $T3,-0x10($Htbl) # save Karatsuba "salt"
+___
+ &clmul64x64_avx ($Xhi,$Xi,$Hkey,$HK); # calculate H^3,5,7
+ &reduction_avx ($Xhi,$Xi);
+$code.=<<___;
+.Linit_start_avx:
+ vmovdqa $Xi,$T3
+___
+ &clmul64x64_avx ($Xhi,$Xi,$Hkey,$HK); # calculate H^2,4,6,8
+ &reduction_avx ($Xhi,$Xi);
+$code.=<<___;
+ vpshufd \$0b01001110,$T3,$T1
+ vpshufd \$0b01001110,$Xi,$T2
+ vpxor $T3,$T1,$T1 # Karatsuba pre-processing
+ vmovdqu $T3,0x00($Htbl) # save H^1,3,5,7
+ vpxor $Xi,$T2,$T2 # Karatsuba pre-processing
+ vmovdqu $Xi,0x10($Htbl) # save H^2,4,6,8
+ lea 0x30($Htbl),$Htbl
+ sub \$1,%r10
+ jnz .Linit_loop_avx
+
+ vpalignr \$8,$T2,$T1,$T3 # last "salt" is flipped
+ vmovdqu $T3,-0x10($Htbl)
+
+ vzeroupper
+___
+$code.=<<___ if ($win64);
+ movaps (%rsp),%xmm6
+ lea 0x18(%rsp),%rsp
+.LSEH_end_gcm_init_avx:
+___
+$code.=<<___;
+ ret
+.size gcm_init_avx,.-gcm_init_avx
+___
+} else {
+$code.=<<___;
+ jmp .L_init_clmul
+.size gcm_init_avx,.-gcm_init_avx
+___
+}
+
+$code.=<<___;
+.globl gcm_gmult_avx
+.type gcm_gmult_avx,\@abi-omnipotent
+.align 32
+gcm_gmult_avx:
+ jmp .L_gmult_clmul
+.size gcm_gmult_avx,.-gcm_gmult_avx
+___
+
+$code.=<<___;
+.globl gcm_ghash_avx
+.type gcm_ghash_avx,\@abi-omnipotent
+.align 32
+gcm_ghash_avx:
+___
+if ($avx) {
+my ($Xip,$Htbl,$inp,$len)=@_4args;
+my ($Xlo,$Xhi,$Xmi,
+ $Zlo,$Zhi,$Zmi,
+ $Hkey,$HK,$T1,$T2,
+ $Xi,$Xo,$Tred,$bswap,$Ii,$Ij) = map("%xmm$_",(0..15));
+
+$code.=<<___ if ($win64);
+ lea -0x88(%rsp),%rax
+.LSEH_begin_gcm_ghash_avx:
+ # I can't trust assembler to use specific encoding:-(
+ .byte 0x48,0x8d,0x60,0xe0 #lea -0x20(%rax),%rsp
+ .byte 0x0f,0x29,0x70,0xe0 #movaps %xmm6,-0x20(%rax)
+ .byte 0x0f,0x29,0x78,0xf0 #movaps %xmm7,-0x10(%rax)
+ .byte 0x44,0x0f,0x29,0x00 #movaps %xmm8,0(%rax)
+ .byte 0x44,0x0f,0x29,0x48,0x10 #movaps %xmm9,0x10(%rax)
+ .byte 0x44,0x0f,0x29,0x50,0x20 #movaps %xmm10,0x20(%rax)
+ .byte 0x44,0x0f,0x29,0x58,0x30 #movaps %xmm11,0x30(%rax)
+ .byte 0x44,0x0f,0x29,0x60,0x40 #movaps %xmm12,0x40(%rax)
+ .byte 0x44,0x0f,0x29,0x68,0x50 #movaps %xmm13,0x50(%rax)
+ .byte 0x44,0x0f,0x29,0x70,0x60 #movaps %xmm14,0x60(%rax)
+ .byte 0x44,0x0f,0x29,0x78,0x70 #movaps %xmm15,0x70(%rax)
+___
+$code.=<<___;
+ vzeroupper
+
+ vmovdqu ($Xip),$Xi # load $Xi
+ lea .L0x1c2_polynomial(%rip),%r10
+ lea 0x40($Htbl),$Htbl # size optimization
+ vmovdqu .Lbswap_mask(%rip),$bswap
+ vpshufb $bswap,$Xi,$Xi
+ cmp \$0x80,$len
+ jb .Lshort_avx
+ sub \$0x80,$len
+
+ vmovdqu 0x70($inp),$Ii # I[7]
+ vmovdqu 0x00-0x40($Htbl),$Hkey # $Hkey^1
+ vpshufb $bswap,$Ii,$Ii
+ vmovdqu 0x20-0x40($Htbl),$HK
+
+ vpunpckhqdq $Ii,$Ii,$T2
+ vmovdqu 0x60($inp),$Ij # I[6]
+ vpclmulqdq \$0x00,$Hkey,$Ii,$Xlo
+ vpxor $Ii,$T2,$T2
+ vpshufb $bswap,$Ij,$Ij
+ vpclmulqdq \$0x11,$Hkey,$Ii,$Xhi
+ vmovdqu 0x10-0x40($Htbl),$Hkey # $Hkey^2
+ vpunpckhqdq $Ij,$Ij,$T1
+ vmovdqu 0x50($inp),$Ii # I[5]
+ vpclmulqdq \$0x00,$HK,$T2,$Xmi
+ vpxor $Ij,$T1,$T1
+
+ vpshufb $bswap,$Ii,$Ii
+ vpclmulqdq \$0x00,$Hkey,$Ij,$Zlo
+ vpunpckhqdq $Ii,$Ii,$T2
+ vpclmulqdq \$0x11,$Hkey,$Ij,$Zhi
+ vmovdqu 0x30-0x40($Htbl),$Hkey # $Hkey^3
+ vpxor $Ii,$T2,$T2
+ vmovdqu 0x40($inp),$Ij # I[4]
+ vpclmulqdq \$0x10,$HK,$T1,$Zmi
+ vmovdqu 0x50-0x40($Htbl),$HK
+
+ vpshufb $bswap,$Ij,$Ij
+ vpxor $Xlo,$Zlo,$Zlo
+ vpclmulqdq \$0x00,$Hkey,$Ii,$Xlo
+ vpxor $Xhi,$Zhi,$Zhi
+ vpunpckhqdq $Ij,$Ij,$T1
+ vpclmulqdq \$0x11,$Hkey,$Ii,$Xhi
+ vmovdqu 0x40-0x40($Htbl),$Hkey # $Hkey^4
+ vpxor $Xmi,$Zmi,$Zmi
+ vpclmulqdq \$0x00,$HK,$T2,$Xmi
+ vpxor $Ij,$T1,$T1
+
+ vmovdqu 0x30($inp),$Ii # I[3]
+ vpxor $Zlo,$Xlo,$Xlo
+ vpclmulqdq \$0x00,$Hkey,$Ij,$Zlo
+ vpxor $Zhi,$Xhi,$Xhi
+ vpshufb $bswap,$Ii,$Ii
+ vpclmulqdq \$0x11,$Hkey,$Ij,$Zhi
+ vmovdqu 0x60-0x40($Htbl),$Hkey # $Hkey^5
+ vpxor $Zmi,$Xmi,$Xmi
+ vpunpckhqdq $Ii,$Ii,$T2
+ vpclmulqdq \$0x10,$HK,$T1,$Zmi
+ vmovdqu 0x80-0x40($Htbl),$HK
+ vpxor $Ii,$T2,$T2
+
+ vmovdqu 0x20($inp),$Ij # I[2]
+ vpxor $Xlo,$Zlo,$Zlo
+ vpclmulqdq \$0x00,$Hkey,$Ii,$Xlo
+ vpxor $Xhi,$Zhi,$Zhi
+ vpshufb $bswap,$Ij,$Ij
+ vpclmulqdq \$0x11,$Hkey,$Ii,$Xhi
+ vmovdqu 0x70-0x40($Htbl),$Hkey # $Hkey^6
+ vpxor $Xmi,$Zmi,$Zmi
+ vpunpckhqdq $Ij,$Ij,$T1
+ vpclmulqdq \$0x00,$HK,$T2,$Xmi
+ vpxor $Ij,$T1,$T1
+
+ vmovdqu 0x10($inp),$Ii # I[1]
+ vpxor $Zlo,$Xlo,$Xlo
+ vpclmulqdq \$0x00,$Hkey,$Ij,$Zlo
+ vpxor $Zhi,$Xhi,$Xhi
+ vpshufb $bswap,$Ii,$Ii
+ vpclmulqdq \$0x11,$Hkey,$Ij,$Zhi
+ vmovdqu 0x90-0x40($Htbl),$Hkey # $Hkey^7
+ vpxor $Zmi,$Xmi,$Xmi
+ vpunpckhqdq $Ii,$Ii,$T2
+ vpclmulqdq \$0x10,$HK,$T1,$Zmi
+ vmovdqu 0xb0-0x40($Htbl),$HK
+ vpxor $Ii,$T2,$T2
+
+ vmovdqu ($inp),$Ij # I[0]
+ vpxor $Xlo,$Zlo,$Zlo
+ vpclmulqdq \$0x00,$Hkey,$Ii,$Xlo
+ vpxor $Xhi,$Zhi,$Zhi
+ vpshufb $bswap,$Ij,$Ij
+ vpclmulqdq \$0x11,$Hkey,$Ii,$Xhi
+ vmovdqu 0xa0-0x40($Htbl),$Hkey # $Hkey^8
+ vpxor $Xmi,$Zmi,$Zmi
+ vpclmulqdq \$0x10,$HK,$T2,$Xmi
+
+ lea 0x80($inp),$inp
+ cmp \$0x80,$len
+ jb .Ltail_avx
+
+ vpxor $Xi,$Ij,$Ij # accumulate $Xi
+ sub \$0x80,$len
+ jmp .Loop8x_avx
+
+.align 32
+.Loop8x_avx:
+ vpunpckhqdq $Ij,$Ij,$T1
+ vmovdqu 0x70($inp),$Ii # I[7]
+ vpxor $Xlo,$Zlo,$Zlo
+ vpxor $Ij,$T1,$T1
+ vpclmulqdq \$0x00,$Hkey,$Ij,$Xi
+ vpshufb $bswap,$Ii,$Ii
+ vpxor $Xhi,$Zhi,$Zhi
+ vpclmulqdq \$0x11,$Hkey,$Ij,$Xo
+ vmovdqu 0x00-0x40($Htbl),$Hkey # $Hkey^1
+ vpunpckhqdq $Ii,$Ii,$T2
+ vpxor $Xmi,$Zmi,$Zmi
+ vpclmulqdq \$0x00,$HK,$T1,$Tred
+ vmovdqu 0x20-0x40($Htbl),$HK
+ vpxor $Ii,$T2,$T2
+
+ vmovdqu 0x60($inp),$Ij # I[6]
+ vpclmulqdq \$0x00,$Hkey,$Ii,$Xlo
+ vpxor $Zlo,$Xi,$Xi # collect result
+ vpshufb $bswap,$Ij,$Ij
+ vpclmulqdq \$0x11,$Hkey,$Ii,$Xhi
+ vxorps $Zhi,$Xo,$Xo
+ vmovdqu 0x10-0x40($Htbl),$Hkey # $Hkey^2
+ vpunpckhqdq $Ij,$Ij,$T1
+ vpclmulqdq \$0x00,$HK, $T2,$Xmi
+ vpxor $Zmi,$Tred,$Tred
+ vxorps $Ij,$T1,$T1
+
+ vmovdqu 0x50($inp),$Ii # I[5]
+ vpxor $Xi,$Tred,$Tred # aggregated Karatsuba post-processing
+ vpclmulqdq \$0x00,$Hkey,$Ij,$Zlo
+ vpxor $Xo,$Tred,$Tred
+ vpslldq \$8,$Tred,$T2
+ vpxor $Xlo,$Zlo,$Zlo
+ vpclmulqdq \$0x11,$Hkey,$Ij,$Zhi
+ vpsrldq \$8,$Tred,$Tred
+ vpxor $T2, $Xi, $Xi
+ vmovdqu 0x30-0x40($Htbl),$Hkey # $Hkey^3
+ vpshufb $bswap,$Ii,$Ii
+ vxorps $Tred,$Xo, $Xo
+ vpxor $Xhi,$Zhi,$Zhi
+ vpunpckhqdq $Ii,$Ii,$T2
+ vpclmulqdq \$0x10,$HK, $T1,$Zmi
+ vmovdqu 0x50-0x40($Htbl),$HK
+ vpxor $Ii,$T2,$T2
+ vpxor $Xmi,$Zmi,$Zmi
+
+ vmovdqu 0x40($inp),$Ij # I[4]
+ vpalignr \$8,$Xi,$Xi,$Tred # 1st phase
+ vpclmulqdq \$0x00,$Hkey,$Ii,$Xlo
+ vpshufb $bswap,$Ij,$Ij
+ vpxor $Zlo,$Xlo,$Xlo
+ vpclmulqdq \$0x11,$Hkey,$Ii,$Xhi
+ vmovdqu 0x40-0x40($Htbl),$Hkey # $Hkey^4
+ vpunpckhqdq $Ij,$Ij,$T1
+ vpxor $Zhi,$Xhi,$Xhi
+ vpclmulqdq \$0x00,$HK, $T2,$Xmi
+ vxorps $Ij,$T1,$T1
+ vpxor $Zmi,$Xmi,$Xmi
+
+ vmovdqu 0x30($inp),$Ii # I[3]
+ vpclmulqdq \$0x10,(%r10),$Xi,$Xi
+ vpclmulqdq \$0x00,$Hkey,$Ij,$Zlo
+ vpshufb $bswap,$Ii,$Ii
+ vpxor $Xlo,$Zlo,$Zlo
+ vpclmulqdq \$0x11,$Hkey,$Ij,$Zhi
+ vmovdqu 0x60-0x40($Htbl),$Hkey # $Hkey^5
+ vpunpckhqdq $Ii,$Ii,$T2
+ vpxor $Xhi,$Zhi,$Zhi
+ vpclmulqdq \$0x10,$HK, $T1,$Zmi
+ vmovdqu 0x80-0x40($Htbl),$HK
+ vpxor $Ii,$T2,$T2
+ vpxor $Xmi,$Zmi,$Zmi
+
+ vmovdqu 0x20($inp),$Ij # I[2]
+ vpclmulqdq \$0x00,$Hkey,$Ii,$Xlo
+ vpshufb $bswap,$Ij,$Ij
+ vpxor $Zlo,$Xlo,$Xlo
+ vpclmulqdq \$0x11,$Hkey,$Ii,$Xhi
+ vmovdqu 0x70-0x40($Htbl),$Hkey # $Hkey^6
+ vpunpckhqdq $Ij,$Ij,$T1
+ vpxor $Zhi,$Xhi,$Xhi
+ vpclmulqdq \$0x00,$HK, $T2,$Xmi
+ vpxor $Ij,$T1,$T1
+ vpxor $Zmi,$Xmi,$Xmi
+ vxorps $Tred,$Xi,$Xi
+
+ vmovdqu 0x10($inp),$Ii # I[1]
+ vpalignr \$8,$Xi,$Xi,$Tred # 2nd phase
+ vpclmulqdq \$0x00,$Hkey,$Ij,$Zlo
+ vpshufb $bswap,$Ii,$Ii
+ vpxor $Xlo,$Zlo,$Zlo
+ vpclmulqdq \$0x11,$Hkey,$Ij,$Zhi
+ vmovdqu 0x90-0x40($Htbl),$Hkey # $Hkey^7
+ vpclmulqdq \$0x10,(%r10),$Xi,$Xi
+ vxorps $Xo,$Tred,$Tred
+ vpunpckhqdq $Ii,$Ii,$T2
+ vpxor $Xhi,$Zhi,$Zhi
+ vpclmulqdq \$0x10,$HK, $T1,$Zmi
+ vmovdqu 0xb0-0x40($Htbl),$HK
+ vpxor $Ii,$T2,$T2
+ vpxor $Xmi,$Zmi,$Zmi
+
+ vmovdqu ($inp),$Ij # I[0]
+ vpclmulqdq \$0x00,$Hkey,$Ii,$Xlo
+ vpshufb $bswap,$Ij,$Ij
+ vpclmulqdq \$0x11,$Hkey,$Ii,$Xhi
+ vmovdqu 0xa0-0x40($Htbl),$Hkey # $Hkey^8
+ vpxor $Tred,$Ij,$Ij
+ vpclmulqdq \$0x10,$HK, $T2,$Xmi
+ vpxor $Xi,$Ij,$Ij # accumulate $Xi
+
+ lea 0x80($inp),$inp
+ sub \$0x80,$len
+ jnc .Loop8x_avx
+
+ add \$0x80,$len
+ jmp .Ltail_no_xor_avx
+
+.align 32
+.Lshort_avx:
+ vmovdqu -0x10($inp,$len),$Ii # very last word
+ lea ($inp,$len),$inp
+ vmovdqu 0x00-0x40($Htbl),$Hkey # $Hkey^1
+ vmovdqu 0x20-0x40($Htbl),$HK
+ vpshufb $bswap,$Ii,$Ij
+
+ vmovdqa $Xlo,$Zlo # subtle way to zero $Zlo,
+ vmovdqa $Xhi,$Zhi # $Zhi and
+ vmovdqa $Xmi,$Zmi # $Zmi
+ sub \$0x10,$len
+ jz .Ltail_avx
+
+ vpunpckhqdq $Ij,$Ij,$T1
+ vpxor $Xlo,$Zlo,$Zlo
+ vpclmulqdq \$0x00,$Hkey,$Ij,$Xlo
+ vpxor $Ij,$T1,$T1
+ vmovdqu -0x20($inp),$Ii
+ vpxor $Xhi,$Zhi,$Zhi
+ vpclmulqdq \$0x11,$Hkey,$Ij,$Xhi
+ vmovdqu 0x10-0x40($Htbl),$Hkey # $Hkey^2
+ vpshufb $bswap,$Ii,$Ij
+ vpxor $Xmi,$Zmi,$Zmi
+ vpclmulqdq \$0x00,$HK,$T1,$Xmi
+ vpsrldq \$8,$HK,$HK
+ sub \$0x10,$len
+ jz .Ltail_avx
+
+ vpunpckhqdq $Ij,$Ij,$T1
+ vpxor $Xlo,$Zlo,$Zlo
+ vpclmulqdq \$0x00,$Hkey,$Ij,$Xlo
+ vpxor $Ij,$T1,$T1
+ vmovdqu -0x30($inp),$Ii
+ vpxor $Xhi,$Zhi,$Zhi
+ vpclmulqdq \$0x11,$Hkey,$Ij,$Xhi
+ vmovdqu 0x30-0x40($Htbl),$Hkey # $Hkey^3
+ vpshufb $bswap,$Ii,$Ij
+ vpxor $Xmi,$Zmi,$Zmi
+ vpclmulqdq \$0x00,$HK,$T1,$Xmi
+ vmovdqu 0x50-0x40($Htbl),$HK
+ sub \$0x10,$len
+ jz .Ltail_avx
+
+ vpunpckhqdq $Ij,$Ij,$T1
+ vpxor $Xlo,$Zlo,$Zlo
+ vpclmulqdq \$0x00,$Hkey,$Ij,$Xlo
+ vpxor $Ij,$T1,$T1
+ vmovdqu -0x40($inp),$Ii
+ vpxor $Xhi,$Zhi,$Zhi
+ vpclmulqdq \$0x11,$Hkey,$Ij,$Xhi
+ vmovdqu 0x40-0x40($Htbl),$Hkey # $Hkey^4
+ vpshufb $bswap,$Ii,$Ij
+ vpxor $Xmi,$Zmi,$Zmi
+ vpclmulqdq \$0x00,$HK,$T1,$Xmi
+ vpsrldq \$8,$HK,$HK
+ sub \$0x10,$len
+ jz .Ltail_avx
+
+ vpunpckhqdq $Ij,$Ij,$T1
+ vpxor $Xlo,$Zlo,$Zlo
+ vpclmulqdq \$0x00,$Hkey,$Ij,$Xlo
+ vpxor $Ij,$T1,$T1
+ vmovdqu -0x50($inp),$Ii
+ vpxor $Xhi,$Zhi,$Zhi
+ vpclmulqdq \$0x11,$Hkey,$Ij,$Xhi
+ vmovdqu 0x60-0x40($Htbl),$Hkey # $Hkey^5
+ vpshufb $bswap,$Ii,$Ij
+ vpxor $Xmi,$Zmi,$Zmi
+ vpclmulqdq \$0x00,$HK,$T1,$Xmi
+ vmovdqu 0x80-0x40($Htbl),$HK
+ sub \$0x10,$len
+ jz .Ltail_avx
+
+ vpunpckhqdq $Ij,$Ij,$T1
+ vpxor $Xlo,$Zlo,$Zlo
+ vpclmulqdq \$0x00,$Hkey,$Ij,$Xlo
+ vpxor $Ij,$T1,$T1
+ vmovdqu -0x60($inp),$Ii
+ vpxor $Xhi,$Zhi,$Zhi
+ vpclmulqdq \$0x11,$Hkey,$Ij,$Xhi
+ vmovdqu 0x70-0x40($Htbl),$Hkey # $Hkey^6
+ vpshufb $bswap,$Ii,$Ij
+ vpxor $Xmi,$Zmi,$Zmi
+ vpclmulqdq \$0x00,$HK,$T1,$Xmi
+ vpsrldq \$8,$HK,$HK
+ sub \$0x10,$len
+ jz .Ltail_avx
+
+ vpunpckhqdq $Ij,$Ij,$T1
+ vpxor $Xlo,$Zlo,$Zlo
+ vpclmulqdq \$0x00,$Hkey,$Ij,$Xlo
+ vpxor $Ij,$T1,$T1
+ vmovdqu -0x70($inp),$Ii
+ vpxor $Xhi,$Zhi,$Zhi
+ vpclmulqdq \$0x11,$Hkey,$Ij,$Xhi
+ vmovdqu 0x90-0x40($Htbl),$Hkey # $Hkey^7
+ vpshufb $bswap,$Ii,$Ij
+ vpxor $Xmi,$Zmi,$Zmi
+ vpclmulqdq \$0x00,$HK,$T1,$Xmi
+ vmovq 0xb8-0x40($Htbl),$HK
+ sub \$0x10,$len
+ jmp .Ltail_avx
+
+.align 32
+.Ltail_avx:
+ vpxor $Xi,$Ij,$Ij # accumulate $Xi
+.Ltail_no_xor_avx:
+ vpunpckhqdq $Ij,$Ij,$T1
+ vpxor $Xlo,$Zlo,$Zlo
+ vpclmulqdq \$0x00,$Hkey,$Ij,$Xlo
+ vpxor $Ij,$T1,$T1
+ vpxor $Xhi,$Zhi,$Zhi
+ vpclmulqdq \$0x11,$Hkey,$Ij,$Xhi
+ vpxor $Xmi,$Zmi,$Zmi
+ vpclmulqdq \$0x00,$HK,$T1,$Xmi
+
+ vmovdqu (%r10),$Tred
+
+ vpxor $Xlo,$Zlo,$Xi
+ vpxor $Xhi,$Zhi,$Xo
+ vpxor $Xmi,$Zmi,$Zmi
+
+ vpxor $Xi, $Zmi,$Zmi # aggregated Karatsuba post-processing
+ vpxor $Xo, $Zmi,$Zmi
+ vpslldq \$8, $Zmi,$T2
+ vpsrldq \$8, $Zmi,$Zmi
+ vpxor $T2, $Xi, $Xi
+ vpxor $Zmi,$Xo, $Xo
+
+ vpclmulqdq \$0x10,$Tred,$Xi,$T2 # 1st phase
+ vpalignr \$8,$Xi,$Xi,$Xi
+ vpxor $T2,$Xi,$Xi
+
+ vpclmulqdq \$0x10,$Tred,$Xi,$T2 # 2nd phase
+ vpalignr \$8,$Xi,$Xi,$Xi
+ vpxor $Xo,$Xi,$Xi
+ vpxor $T2,$Xi,$Xi
+
+ cmp \$0,$len
+ jne .Lshort_avx
+
+ vpshufb $bswap,$Xi,$Xi
+ vmovdqu $Xi,($Xip)
+ vzeroupper
+___
+$code.=<<___ if ($win64);
+ movaps (%rsp),%xmm6
+ movaps 0x10(%rsp),%xmm7
+ movaps 0x20(%rsp),%xmm8
+ movaps 0x30(%rsp),%xmm9
+ movaps 0x40(%rsp),%xmm10
+ movaps 0x50(%rsp),%xmm11
+ movaps 0x60(%rsp),%xmm12
+ movaps 0x70(%rsp),%xmm13
+ movaps 0x80(%rsp),%xmm14
+ movaps 0x90(%rsp),%xmm15
+ lea 0xa8(%rsp),%rsp
+.LSEH_end_gcm_ghash_avx:
+___
+$code.=<<___;
+ ret
+.size gcm_ghash_avx,.-gcm_ghash_avx
+___
+} else {
+$code.=<<___;
+ jmp .L_ghash_clmul
+.size gcm_ghash_avx,.-gcm_ghash_avx
+___
+}
+
+$code.=<<___;
+.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
+.L7_mask:
+ .long 7,0,7,0
+.L7_mask_poly:
+ .long 7,0,`0xE1<<1`,0
+.align 64
+.type .Lrem_4bit,\@object
+.Lrem_4bit:
+ .long 0,`0x0000<<16`,0,`0x1C20<<16`,0,`0x3840<<16`,0,`0x2460<<16`
+ .long 0,`0x7080<<16`,0,`0x6CA0<<16`,0,`0x48C0<<16`,0,`0x54E0<<16`
+ .long 0,`0xE100<<16`,0,`0xFD20<<16`,0,`0xD940<<16`,0,`0xC560<<16`
+ .long 0,`0x9180<<16`,0,`0x8DA0<<16`,0,`0xA9C0<<16`,0,`0xB5E0<<16`
+.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
+
+.asciz "GHASH for x86_64, CRYPTOGAMS by <appro\@openssl.org>"
+.align 64
+___
+
+# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame,
+# CONTEXT *context,DISPATCHER_CONTEXT *disp)
+if ($win64) {
+$rec="%rcx";
+$frame="%rdx";
+$context="%r8";
+$disp="%r9";
+
+$code.=<<___;
+.extern __imp_RtlVirtualUnwind
+.type se_handler,\@abi-omnipotent
+.align 16
+se_handler:
+ push %rsi
+ push %rdi
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+ pushfq
+ sub \$64,%rsp
+
+ mov 120($context),%rax # pull context->Rax
+ mov 248($context),%rbx # pull context->Rip
+
+ mov 8($disp),%rsi # disp->ImageBase
+ mov 56($disp),%r11 # disp->HandlerData
+
+ mov 0(%r11),%r10d # HandlerData[0]
+ lea (%rsi,%r10),%r10 # prologue label
+ cmp %r10,%rbx # context->Rip<prologue label
+ jb .Lin_prologue
+
+ mov 152($context),%rax # pull context->Rsp
+
+ mov 4(%r11),%r10d # HandlerData[1]
+ lea (%rsi,%r10),%r10 # epilogue label
+ cmp %r10,%rbx # context->Rip>=epilogue label
+ jae .Lin_prologue
+
+ lea 24(%rax),%rax # adjust "rsp"
+
+ mov -8(%rax),%rbx
+ mov -16(%rax),%rbp
+ mov -24(%rax),%r12
+ mov %rbx,144($context) # restore context->Rbx
+ mov %rbp,160($context) # restore context->Rbp
+ mov %r12,216($context) # restore context->R12
+
+.Lin_prologue:
+ mov 8(%rax),%rdi
+ mov 16(%rax),%rsi
+ mov %rax,152($context) # restore context->Rsp
+ mov %rsi,168($context) # restore context->Rsi
+ mov %rdi,176($context) # restore context->Rdi
+
+ mov 40($disp),%rdi # disp->ContextRecord
+ mov $context,%rsi # context
+ mov \$`1232/8`,%ecx # sizeof(CONTEXT)
+ .long 0xa548f3fc # cld; rep movsq
+
+ mov $disp,%rsi
+ xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER
+ mov 8(%rsi),%rdx # arg2, disp->ImageBase
+ mov 0(%rsi),%r8 # arg3, disp->ControlPc
+ mov 16(%rsi),%r9 # arg4, disp->FunctionEntry
+ mov 40(%rsi),%r10 # disp->ContextRecord
+ lea 56(%rsi),%r11 # &disp->HandlerData
+ lea 24(%rsi),%r12 # &disp->EstablisherFrame
+ mov %r10,32(%rsp) # arg5
+ mov %r11,40(%rsp) # arg6
+ mov %r12,48(%rsp) # arg7
+ mov %rcx,56(%rsp) # arg8, (NULL)
+ call *__imp_RtlVirtualUnwind(%rip)
+
+ mov \$1,%eax # ExceptionContinueSearch
+ add \$64,%rsp
+ popfq
+ pop %r15
+ pop %r14
+ pop %r13
+ pop %r12
+ pop %rbp
+ pop %rbx
+ pop %rdi
+ pop %rsi
+ ret
+.size se_handler,.-se_handler
+
+.section .pdata
+.align 4
+ .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_init_clmul
+ .rva .LSEH_end_gcm_init_clmul
+ .rva .LSEH_info_gcm_init_clmul
+
+ .rva .LSEH_begin_gcm_ghash_clmul
+ .rva .LSEH_end_gcm_ghash_clmul
+ .rva .LSEH_info_gcm_ghash_clmul
+___
+$code.=<<___ if ($avx);
+ .rva .LSEH_begin_gcm_init_avx
+ .rva .LSEH_end_gcm_init_avx
+ .rva .LSEH_info_gcm_init_clmul
+
+ .rva .LSEH_begin_gcm_ghash_avx
+ .rva .LSEH_end_gcm_ghash_avx
+ .rva .LSEH_info_gcm_ghash_clmul
+___
+$code.=<<___;
+.section .xdata
+.align 8
+.LSEH_info_gcm_gmult_4bit:
+ .byte 9,0,0,0
+ .rva se_handler
+ .rva .Lgmult_prologue,.Lgmult_epilogue # HandlerData
+.LSEH_info_gcm_ghash_4bit:
+ .byte 9,0,0,0
+ .rva se_handler
+ .rva .Lghash_prologue,.Lghash_epilogue # HandlerData
+.LSEH_info_gcm_init_clmul:
+ .byte 0x01,0x08,0x03,0x00
+ .byte 0x08,0x68,0x00,0x00 #movaps 0x00(rsp),xmm6
+ .byte 0x04,0x22,0x00,0x00 #sub rsp,0x18
+.LSEH_info_gcm_ghash_clmul:
+ .byte 0x01,0x33,0x16,0x00
+ .byte 0x33,0xf8,0x09,0x00 #movaps 0x90(rsp),xmm15
+ .byte 0x2e,0xe8,0x08,0x00 #movaps 0x80(rsp),xmm14
+ .byte 0x29,0xd8,0x07,0x00 #movaps 0x70(rsp),xmm13
+ .byte 0x24,0xc8,0x06,0x00 #movaps 0x60(rsp),xmm12
+ .byte 0x1f,0xb8,0x05,0x00 #movaps 0x50(rsp),xmm11
+ .byte 0x1a,0xa8,0x04,0x00 #movaps 0x40(rsp),xmm10
+ .byte 0x15,0x98,0x03,0x00 #movaps 0x30(rsp),xmm9
+ .byte 0x10,0x88,0x02,0x00 #movaps 0x20(rsp),xmm8
+ .byte 0x0c,0x78,0x01,0x00 #movaps 0x10(rsp),xmm7
+ .byte 0x08,0x68,0x00,0x00 #movaps 0x00(rsp),xmm6
+ .byte 0x04,0x01,0x15,0x00 #sub rsp,0xa8
+___
+}
+
+$code =~ s/\`([^\`]*)\`/eval($1)/gem;
+
+print $code;
+
+close STDOUT;
diff --git a/src/crypto/modes/asm/ghashv8-armx.pl b/src/crypto/modes/asm/ghashv8-armx.pl
new file mode 100644
index 0000000..54a1ac4
--- /dev/null
+++ b/src/crypto/modes/asm/ghashv8-armx.pl
@@ -0,0 +1,241 @@
+#!/usr/bin/env perl
+#
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+# project. The module is, however, dual licensed under OpenSSL and
+# CRYPTOGAMS licenses depending on where you obtain it. For further
+# details see http://www.openssl.org/~appro/cryptogams/.
+# ====================================================================
+#
+# GHASH for ARMv8 Crypto Extension, 64-bit polynomial multiplication.
+#
+# June 2014
+#
+# Initial version was developed in tight cooperation with Ard
+# Biesheuvel <ard.biesheuvel@linaro.org> from bits-n-pieces from
+# other assembly modules. Just like aesv8-armx.pl this module
+# supports both AArch32 and AArch64 execution modes.
+#
+# Current performance in cycles per processed byte:
+#
+# PMULL[2] 32-bit NEON(*)
+# Apple A7 1.76 5.62
+# Cortex-A53 1.45 8.39
+# Cortex-A57 2.22 7.61
+#
+# (*) presented for reference/comparison purposes;
+
+$flavour = shift;
+open STDOUT,">".shift;
+
+$Xi="x0"; # argument block
+$Htbl="x1";
+$inp="x2";
+$len="x3";
+
+$inc="x12";
+
+{
+my ($Xl,$Xm,$Xh,$IN)=map("q$_",(0..3));
+my ($t0,$t1,$t2,$t3,$H,$Hhl)=map("q$_",(8..14));
+
+$code=<<___;
+#include "arm_arch.h"
+
+.text
+___
+$code.=".arch armv8-a+crypto\n" if ($flavour =~ /64/);
+$code.=".fpu neon\n.code 32\n" if ($flavour !~ /64/);
+
+$code.=<<___;
+.global gcm_init_v8
+.type gcm_init_v8,%function
+.align 4
+gcm_init_v8:
+ vld1.64 {$t1},[x1] @ load H
+ vmov.i8 $t0,#0xe1
+ vext.8 $IN,$t1,$t1,#8
+ vshl.i64 $t0,$t0,#57
+ vshr.u64 $t2,$t0,#63
+ vext.8 $t0,$t2,$t0,#8 @ t0=0xc2....01
+ vdup.32 $t1,${t1}[1]
+ vshr.u64 $t3,$IN,#63
+ vshr.s32 $t1,$t1,#31 @ broadcast carry bit
+ vand $t3,$t3,$t0
+ vshl.i64 $IN,$IN,#1
+ vext.8 $t3,$t3,$t3,#8
+ vand $t0,$t0,$t1
+ vorr $IN,$IN,$t3 @ H<<<=1
+ veor $IN,$IN,$t0 @ twisted H
+ vst1.64 {$IN},[x0]
+
+ ret
+.size gcm_init_v8,.-gcm_init_v8
+
+.global gcm_gmult_v8
+.type gcm_gmult_v8,%function
+.align 4
+gcm_gmult_v8:
+ vld1.64 {$t1},[$Xi] @ load Xi
+ vmov.i8 $t3,#0xe1
+ vld1.64 {$H},[$Htbl] @ load twisted H
+ vshl.u64 $t3,$t3,#57
+#ifndef __ARMEB__
+ vrev64.8 $t1,$t1
+#endif
+ vext.8 $Hhl,$H,$H,#8
+ mov $len,#0
+ vext.8 $IN,$t1,$t1,#8
+ mov $inc,#0
+ veor $Hhl,$Hhl,$H @ Karatsuba pre-processing
+ mov $inp,$Xi
+ b .Lgmult_v8
+.size gcm_gmult_v8,.-gcm_gmult_v8
+
+.global gcm_ghash_v8
+.type gcm_ghash_v8,%function
+.align 4
+gcm_ghash_v8:
+ vld1.64 {$Xl},[$Xi] @ load [rotated] Xi
+ subs $len,$len,#16
+ vmov.i8 $t3,#0xe1
+ mov $inc,#16
+ vld1.64 {$H},[$Htbl] @ load twisted H
+ cclr $inc,eq
+ vext.8 $Xl,$Xl,$Xl,#8
+ vshl.u64 $t3,$t3,#57
+ vld1.64 {$t1},[$inp],$inc @ load [rotated] inp
+ vext.8 $Hhl,$H,$H,#8
+#ifndef __ARMEB__
+ vrev64.8 $Xl,$Xl
+ vrev64.8 $t1,$t1
+#endif
+ veor $Hhl,$Hhl,$H @ Karatsuba pre-processing
+ vext.8 $IN,$t1,$t1,#8
+ b .Loop_v8
+
+.align 4
+.Loop_v8:
+ vext.8 $t2,$Xl,$Xl,#8
+ veor $IN,$IN,$Xl @ inp^=Xi
+ veor $t1,$t1,$t2 @ $t1 is rotated inp^Xi
+
+.Lgmult_v8:
+ vpmull.p64 $Xl,$H,$IN @ H.lo·Xi.lo
+ veor $t1,$t1,$IN @ Karatsuba pre-processing
+ vpmull2.p64 $Xh,$H,$IN @ H.hi·Xi.hi
+ subs $len,$len,#16
+ vpmull.p64 $Xm,$Hhl,$t1 @ (H.lo+H.hi)·(Xi.lo+Xi.hi)
+ cclr $inc,eq
+
+ vext.8 $t1,$Xl,$Xh,#8 @ Karatsuba post-processing
+ veor $t2,$Xl,$Xh
+ veor $Xm,$Xm,$t1
+ vld1.64 {$t1},[$inp],$inc @ load [rotated] inp
+ veor $Xm,$Xm,$t2
+ vpmull.p64 $t2,$Xl,$t3 @ 1st phase
+
+ vmov $Xh#lo,$Xm#hi @ Xh|Xm - 256-bit result
+ vmov $Xm#hi,$Xl#lo @ Xm is rotated Xl
+#ifndef __ARMEB__
+ vrev64.8 $t1,$t1
+#endif
+ veor $Xl,$Xm,$t2
+ vext.8 $IN,$t1,$t1,#8
+
+ vext.8 $t2,$Xl,$Xl,#8 @ 2nd phase
+ vpmull.p64 $Xl,$Xl,$t3
+ veor $t2,$t2,$Xh
+ veor $Xl,$Xl,$t2
+ b.hs .Loop_v8
+
+#ifndef __ARMEB__
+ vrev64.8 $Xl,$Xl
+#endif
+ vext.8 $Xl,$Xl,$Xl,#8
+ vst1.64 {$Xl},[$Xi] @ write out Xi
+
+ ret
+.size gcm_ghash_v8,.-gcm_ghash_v8
+___
+}
+$code.=<<___;
+.asciz "GHASH for ARMv8, CRYPTOGAMS by <appro\@openssl.org>"
+.align 2
+___
+
+if ($flavour =~ /64/) { ######## 64-bit code
+ sub unvmov {
+ my $arg=shift;
+
+ $arg =~ m/q([0-9]+)#(lo|hi),\s*q([0-9]+)#(lo|hi)/o &&
+ sprintf "ins v%d.d[%d],v%d.d[%d]",$1,($2 eq "lo")?0:1,$3,($4 eq "lo")?0:1;
+ }
+ foreach(split("\n",$code)) {
+ s/cclr\s+([wx])([^,]+),\s*([a-z]+)/csel $1$2,$1zr,$1$2,$3/o or
+ s/vmov\.i8/movi/o or # fix up legacy mnemonics
+ s/vmov\s+(.*)/unvmov($1)/geo or
+ s/vext\.8/ext/o or
+ s/vshr\.s/sshr\.s/o or
+ s/vshr/ushr/o or
+ s/^(\s+)v/$1/o or # strip off v prefix
+ s/\bbx\s+lr\b/ret/o;
+
+ s/\bq([0-9]+)\b/"v".($1<8?$1:$1+8).".16b"/geo; # old->new registers
+ s/@\s/\/\//o; # old->new style commentary
+
+ # fix up remainig legacy suffixes
+ s/\.[ui]?8(\s)/$1/o;
+ s/\.[uis]?32//o and s/\.16b/\.4s/go;
+ m/\.p64/o and s/\.16b/\.1q/o; # 1st pmull argument
+ m/l\.p64/o and s/\.16b/\.1d/go; # 2nd and 3rd pmull arguments
+ s/\.[uisp]?64//o and s/\.16b/\.2d/go;
+ s/\.[42]([sd])\[([0-3])\]/\.$1\[$2\]/o;
+
+ print $_,"\n";
+ }
+} else { ######## 32-bit code
+ sub unvdup32 {
+ my $arg=shift;
+
+ $arg =~ m/q([0-9]+),\s*q([0-9]+)\[([0-3])\]/o &&
+ sprintf "vdup.32 q%d,d%d[%d]",$1,2*$2+($3>>1),$3&1;
+ }
+ sub unvpmullp64 {
+ my ($mnemonic,$arg)=@_;
+
+ if ($arg =~ m/q([0-9]+),\s*q([0-9]+),\s*q([0-9]+)/o) {
+ my $word = 0xf2a00e00|(($1&7)<<13)|(($1&8)<<19)
+ |(($2&7)<<17)|(($2&8)<<4)
+ |(($3&7)<<1) |(($3&8)<<2);
+ $word |= 0x00010001 if ($mnemonic =~ "2");
+ # since ARMv7 instructions are always encoded little-endian.
+ # correct solution is to use .inst directive, but older
+ # assemblers don't implement it:-(
+ sprintf ".byte\t0x%02x,0x%02x,0x%02x,0x%02x\t@ %s %s",
+ $word&0xff,($word>>8)&0xff,
+ ($word>>16)&0xff,($word>>24)&0xff,
+ $mnemonic,$arg;
+ }
+ }
+
+ foreach(split("\n",$code)) {
+ s/\b[wx]([0-9]+)\b/r$1/go; # new->old registers
+ s/\bv([0-9])\.[12468]+[bsd]\b/q$1/go; # new->old registers
+ s/\/\/\s?/@ /o; # new->old style commentary
+
+ # fix up remainig new-style suffixes
+ s/\],#[0-9]+/]!/o;
+
+ s/cclr\s+([^,]+),\s*([a-z]+)/mov$2 $1,#0/o or
+ s/vdup\.32\s+(.*)/unvdup32($1)/geo or
+ s/v?(pmull2?)\.p64\s+(.*)/unvpmullp64($1,$2)/geo or
+ s/\bq([0-9]+)#(lo|hi)/sprintf "d%d",2*$1+($2 eq "hi")/geo or
+ s/^(\s+)b\./$1b/o or
+ s/^(\s+)ret/$1bx\tlr/o;
+
+ print $_,"\n";
+ }
+}
+
+close STDOUT; # enforce flush
diff --git a/src/crypto/modes/cbc.c b/src/crypto/modes/cbc.c
new file mode 100644
index 0000000..a2ad26c
--- /dev/null
+++ b/src/crypto/modes/cbc.c
@@ -0,0 +1,203 @@
+/* ====================================================================
+ * 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 <openssl/modes.h>
+
+#include <assert.h>
+#include <string.h>
+
+#include "internal.h"
+
+
+#ifndef STRICT_ALIGNMENT
+# define STRICT_ALIGNMENT 0
+#endif
+
+void CRYPTO_cbc128_encrypt(const uint8_t *in, uint8_t *out, size_t len,
+ const void *key, uint8_t ivec[16],
+ block128_f block) {
+ size_t n;
+ const uint8_t *iv = ivec;
+
+ assert(in && out && key && ivec);
+
+ 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;
+ }
+ }
+
+ 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;
+ }
+
+ memcpy(ivec, iv, 16);
+}
+
+void CRYPTO_cbc128_decrypt(const uint8_t *in, uint8_t *out, size_t len,
+ const void *key, uint8_t ivec[16],
+ block128_f block) {
+ size_t n;
+ union {
+ size_t t[16 / sizeof(size_t)];
+ uint8_t c[16];
+ } tmp;
+
+ assert(in && out && key && ivec);
+
+ if (in != out) {
+ const uint8_t *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;
+ }
+ }
+ memcpy(ivec, iv, 16);
+ } else {
+ if (STRICT_ALIGNMENT &&
+ ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(size_t) != 0) {
+ uint8_t 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;
+ }
+ }
+ }
+
+ while (len) {
+ uint8_t 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;
+ }
+}
diff --git a/src/crypto/modes/cfb.c b/src/crypto/modes/cfb.c
new file mode 100644
index 0000000..738a438
--- /dev/null
+++ b/src/crypto/modes/cfb.c
@@ -0,0 +1,230 @@
+/* ====================================================================
+ * 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 <openssl/modes.h>
+
+#include <assert.h>
+#include <string.h>
+
+#include "internal.h"
+
+
+void CRYPTO_cfb128_encrypt(const uint8_t *in, uint8_t *out, size_t len,
+ const void *key, uint8_t ivec[16], int *num, int enc,
+ block128_f block) {
+ unsigned int n;
+ size_t l = 0;
+
+ assert(in && out && key && ivec && num);
+ assert((16 % sizeof(size_t)) == 0);
+
+ n = *num;
+
+ if (enc) {
+ while (n && len) {
+ *(out++) = ivec[n] ^= *(in++);
+ --len;
+ n = (n + 1) % 16;
+ }
+#if STRICT_ALIGNMENT
+ if (((size_t)in | (size_t)out | (size_t)ivec) % sizeof(size_t) != 0) {
+ while (l < len) {
+ if (n == 0) {
+ (*block)(ivec, ivec, key);
+ }
+ out[l] = ivec[n] ^= in[l];
+ ++l;
+ n = (n + 1) % 16;
+ }
+ *num = n;
+ return;
+ }
+#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;
+ } else {
+ while (n && len) {
+ uint8_t c;
+ *(out++) = ivec[n] ^ (c = *(in++));
+ ivec[n] = c;
+ --len;
+ n = (n + 1) % 16;
+ }
+ if (STRICT_ALIGNMENT && ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(size_t) != 0) {
+ 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;
+ return;
+ }
+ 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--) {
+ uint8_t c;
+ out[n] = ivec[n] ^ (c = in[n]);
+ ivec[n] = c;
+ ++n;
+ }
+ }
+ *num = n;
+ return;
+ }
+}
+
+
+/* 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 uint8_t *in, uint8_t *out, unsigned nbits,
+ const void *key, uint8_t ivec[16], int enc,
+ block128_f block) {
+ int n, rem, num;
+ uint8_t 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 uint8_t *in, uint8_t *out, size_t bits,
+ const void *key, uint8_t ivec[16], int *num,
+ int enc, block128_f block) {
+ size_t n;
+ uint8_t c[1], d[1];
+
+ assert(in && out && key && ivec && num);
+ assert(*num == 0);
+
+ 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));
+ }
+}
+
+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;
+
+ assert(in && out && key && ivec && num);
+ assert(*num == 0);
+
+ for (n = 0; n < length; ++n) {
+ cfbr_encrypt_block(&in[n], &out[n], 8, key, ivec, enc, block);
+ }
+}
+
diff --git a/src/crypto/modes/ctr.c b/src/crypto/modes/ctr.c
new file mode 100644
index 0000000..61832ba
--- /dev/null
+++ b/src/crypto/modes/ctr.c
@@ -0,0 +1,219 @@
+/* ====================================================================
+ * 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 <openssl/modes.h>
+
+#include <assert.h>
+#include <string.h>
+
+#include "internal.h"
+
+
+/* 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(uint8_t *counter) {
+ uint32_t n = 16;
+ uint8_t c;
+
+ do {
+ --n;
+ c = counter[n];
+ ++c;
+ counter[n] = c;
+ if (c) {
+ return;
+ }
+ } while (n);
+}
+
+/* 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 uint8_t *in, uint8_t *out, size_t len,
+ const void *key, uint8_t ivec[16],
+ uint8_t ecount_buf[16], unsigned int *num,
+ block128_f block) {
+ unsigned int n;
+
+ assert(in && out && key && ecount_buf && num);
+ assert(*num < 16);
+ assert((16 % sizeof(size_t)) == 0);
+
+ n = *num;
+
+ while (n && len) {
+ *(out++) = *(in++) ^ ecount_buf[n];
+ --len;
+ n = (n + 1) % 16;
+ }
+
+#if STRICT_ALIGNMENT
+ if (((size_t)in | (size_t)out | (size_t)ivec) % sizeof(size_t) != 0) {
+ size_t l = 0;
+ 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;
+ return;
+ }
+#endif
+
+ while (len >= 16) {
+ (*block)(ivec, ecount_buf, key);
+ ctr128_inc(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(ivec);
+ while (len--) {
+ out[n] = in[n] ^ ecount_buf[n];
+ ++n;
+ }
+ }
+ *num = n;
+}
+
+/* increment upper 96 bits of 128-bit counter by 1 */
+static void ctr96_inc(uint8_t *counter) {
+ uint32_t n = 12;
+ uint8_t c;
+
+ do {
+ --n;
+ c = counter[n];
+ ++c;
+ counter[n] = c;
+ if (c) {
+ return;
+ }
+ } while (n);
+}
+
+void CRYPTO_ctr128_encrypt_ctr32(const uint8_t *in, uint8_t *out,
+ size_t len, const void *key,
+ uint8_t ivec[16],
+ uint8_t ecount_buf[16],
+ unsigned int *num, ctr128_f func) {
+ unsigned int n, ctr32;
+
+ assert(in && out && key && ecount_buf && num);
+ 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 += (uint32_t)blocks;
+ if (ctr32 < blocks) {
+ blocks -= ctr32;
+ ctr32 = 0;
+ }
+ (*func)(in, out, blocks, key, ivec);
+ /* (*func) does not update ivec, caller does: */
+ PUTU32(ivec + 12, ctr32);
+ /* ... overflow was detected, propogate 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;
+}
diff --git a/src/crypto/modes/gcm.c b/src/crypto/modes/gcm.c
new file mode 100644
index 0000000..eeaeeff
--- /dev/null
+++ b/src/crypto/modes/gcm.c
@@ -0,0 +1,1245 @@
+/* ====================================================================
+ * 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 <openssl/modes.h>
+
+#include <assert.h>
+#include <string.h>
+
+#include <openssl/mem.h>
+#include <openssl/cpu.h>
+
+#include "internal.h"
+#include "../internal.h"
+
+
+#if !defined(OPENSSL_NO_ASM) && \
+ (defined(OPENSSL_X86) || defined(OPENSSL_X86_64) || \
+ defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64))
+#define GHASH_ASM
+#endif
+
+#if defined(BSWAP4) && STRICT_ALIGNMENT == 1
+/* redefine, because alignment is ensured */
+#undef GETU32
+#define GETU32(p) BSWAP4(*(const uint32_t *)(p))
+#undef PUTU32
+#define PUTU32(p, v) *(uint32_t *)(p) = BSWAP4(v)
+#endif
+
+#define PACK(s) ((size_t)(s) << (sizeof(size_t) * 8 - 16))
+#define REDUCE1BIT(V) \
+ do { \
+ if (sizeof(size_t) == 8) { \
+ uint64_t T = OPENSSL_U64(0xe100000000000000) & (0 - (V.lo & 1)); \
+ V.lo = (V.hi << 63) | (V.lo >> 1); \
+ V.hi = (V.hi >> 1) ^ T; \
+ } else { \
+ uint32_t T = 0xe1000000U & (0 - (uint32_t)(V.lo & 1)); \
+ V.lo = (V.hi << 63) | (V.lo >> 1); \
+ V.hi = (V.hi >> 1) ^ ((uint64_t)T << 32); \
+ } \
+ } while (0)
+
+
+static void gcm_init_4bit(u128 Htable[16], uint64_t H[2]) {
+ u128 V;
+
+ Htable[0].hi = 0;
+ Htable[0].lo = 0;
+ V.hi = H[0];
+ V.lo = H[1];
+
+ 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;
+
+#if defined(GHASH_ASM) && defined(OPENSSL_ARM)
+ /* ARM assembler expects specific dword order in Htable. */
+ {
+ int j;
+ const union {
+ long one;
+ char little;
+ } is_endian = {1};
+
+ if (is_endian.little) {
+ for (j = 0; j < 16; ++j) {
+ V = Htable[j];
+ Htable[j].hi = V.lo;
+ Htable[j].lo = V.hi;
+ }
+ } else {
+ 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
+}
+
+#if !defined(GHASH_ASM) || defined(OPENSSL_AARCH64)
+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(uint64_t Xi[2], const u128 Htable[16]) {
+ u128 Z;
+ int cnt = 15;
+ size_t rem, nlo, nhi;
+ const union {
+ long one;
+ char little;
+ } is_endian = {1};
+
+ nlo = ((const uint8_t *)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 (sizeof(size_t) == 8) {
+ Z.hi ^= rem_4bit[rem];
+ } else {
+ Z.hi ^= (uint64_t)rem_4bit[rem] << 32;
+ }
+
+ Z.hi ^= Htable[nhi].hi;
+ Z.lo ^= Htable[nhi].lo;
+
+ if (--cnt < 0) {
+ break;
+ }
+
+ nlo = ((const uint8_t *)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 (sizeof(size_t) == 8) {
+ Z.hi ^= rem_4bit[rem];
+ } else {
+ Z.hi ^= (uint64_t)rem_4bit[rem] << 32;
+ }
+
+ Z.hi ^= Htable[nlo].hi;
+ Z.lo ^= Htable[nlo].lo;
+ }
+
+ if (is_endian.little) {
+#ifdef BSWAP8
+ Xi[0] = BSWAP8(Z.hi);
+ Xi[1] = BSWAP8(Z.lo);
+#else
+ uint8_t *p = (uint8_t *)Xi;
+ uint32_t v;
+ v = (uint32_t)(Z.hi >> 32);
+ PUTU32(p, v);
+ v = (uint32_t)(Z.hi);
+ PUTU32(p + 4, v);
+ v = (uint32_t)(Z.lo >> 32);
+ PUTU32(p + 8, v);
+ v = (uint32_t)(Z.lo);
+ PUTU32(p + 12, v);
+#endif
+ } else {
+ Xi[0] = Z.hi;
+ Xi[1] = Z.lo;
+ }
+}
+
+/* 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(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp,
+ size_t len) {
+ u128 Z;
+ int cnt;
+ size_t rem, nlo, nhi;
+ const union {
+ long one;
+ char little;
+ } is_endian = {1};
+
+ do {
+ cnt = 15;
+ nlo = ((const uint8_t *)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 (sizeof(size_t) == 8) {
+ Z.hi ^= rem_4bit[rem];
+ } else {
+ Z.hi ^= (uint64_t)rem_4bit[rem] << 32;
+ }
+
+ Z.hi ^= Htable[nhi].hi;
+ Z.lo ^= Htable[nhi].lo;
+
+ if (--cnt < 0) {
+ break;
+ }
+
+ nlo = ((const uint8_t *)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 (sizeof(size_t) == 8) {
+ Z.hi ^= rem_4bit[rem];
+ } else {
+ Z.hi ^= (uint64_t)rem_4bit[rem] << 32;
+ }
+
+ Z.hi ^= Htable[nlo].hi;
+ Z.lo ^= Htable[nlo].lo;
+ }
+
+ if (is_endian.little) {
+#ifdef BSWAP8
+ Xi[0] = BSWAP8(Z.hi);
+ Xi[1] = BSWAP8(Z.lo);
+#else
+ uint8_t *p = (uint8_t *)Xi;
+ uint32_t v;
+ v = (uint32_t)(Z.hi >> 32);
+ PUTU32(p, v);
+ v = (uint32_t)(Z.hi);
+ PUTU32(p + 4, v);
+ v = (uint32_t)(Z.lo >> 32);
+ PUTU32(p + 8, v);
+ v = (uint32_t)(Z.lo);
+ PUTU32(p + 12, v);
+#endif
+ } else {
+ Xi[0] = Z.hi;
+ Xi[1] = Z.lo;
+ }
+ } while (inp += 16, len -= 16);
+}
+#else /* GHASH_ASM */
+void gcm_gmult_4bit(uint64_t Xi[2], const u128 Htable[16]);
+void gcm_ghash_4bit(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp,
+ size_t len);
+#endif
+
+#define GCM_MUL(ctx, Xi) gcm_gmult_4bit(ctx->Xi.u, ctx->Htable)
+#if defined(GHASH_ASM)
+#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
+
+
+#if defined(GHASH_ASM)
+#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64)
+#define GHASH_ASM_X86_OR_64
+#define GCM_FUNCREF_4BIT
+void gcm_init_clmul(u128 Htable[16], const uint64_t Xi[2]);
+void gcm_gmult_clmul(uint64_t Xi[2], const u128 Htable[16]);
+void gcm_ghash_clmul(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp,
+ size_t len);
+
+#if defined(OPENSSL_X86)
+#define gcm_init_avx gcm_init_clmul
+#define gcm_gmult_avx gcm_gmult_clmul
+#define gcm_ghash_avx gcm_ghash_clmul
+#else
+void gcm_init_avx(u128 Htable[16], const uint64_t Xi[2]);
+void gcm_gmult_avx(uint64_t Xi[2], const u128 Htable[16]);
+void gcm_ghash_avx(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp, size_t len);
+#endif
+
+#if defined(OPENSSL_X86)
+#define GHASH_ASM_X86
+void gcm_gmult_4bit_mmx(uint64_t Xi[2], const u128 Htable[16]);
+void gcm_ghash_4bit_mmx(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp,
+ size_t len);
+
+void gcm_gmult_4bit_x86(uint64_t Xi[2], const u128 Htable[16]);
+void gcm_ghash_4bit_x86(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp,
+ size_t len);
+#endif
+#elif defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)
+#include "../arm_arch.h"
+#if __ARM_ARCH__ >= 7
+#define GHASH_ASM_ARM
+#define GCM_FUNCREF_4BIT
+
+static int pmull_capable() {
+ return (OPENSSL_armcap_P & ARMV8_PMULL) != 0;
+}
+
+void gcm_init_v8(u128 Htable[16], const uint64_t Xi[2]);
+void gcm_gmult_v8(uint64_t Xi[2], const u128 Htable[16]);
+void gcm_ghash_v8(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp,
+ size_t len);
+
+#if defined(OPENSSL_ARM)
+/* 32-bit ARM also has support for doing GCM with NEON instructions. */
+static int neon_capable() {
+ return CRYPTO_is_NEON_capable();
+}
+
+void gcm_init_neon(u128 Htable[16], const uint64_t Xi[2]);
+void gcm_gmult_neon(uint64_t Xi[2], const u128 Htable[16]);
+void gcm_ghash_neon(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp,
+ size_t len);
+#else
+/* AArch64 only has the ARMv8 versions of functions. */
+static int neon_capable() {
+ return 0;
+}
+void gcm_init_neon(u128 Htable[16], const uint64_t Xi[2]) {
+ abort();
+}
+void gcm_gmult_neon(uint64_t Xi[2], const u128 Htable[16]) {
+ abort();
+}
+void gcm_ghash_neon(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp,
+ size_t len) {
+ abort();
+}
+#endif
+
+#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
+
+GCM128_CONTEXT *CRYPTO_gcm128_new(void *key, block128_f block) {
+ GCM128_CONTEXT *ret;
+
+ ret = (GCM128_CONTEXT *)OPENSSL_malloc(sizeof(GCM128_CONTEXT));
+ if (ret != NULL) {
+ CRYPTO_gcm128_init(ret, key, block);
+ }
+
+ return ret;
+}
+
+void CRYPTO_gcm128_init(GCM128_CONTEXT *ctx, void *key, block128_f block) {
+ const union {
+ long one;
+ char little;
+ } is_endian = {1};
+
+ memset(ctx, 0, sizeof(*ctx));
+ ctx->block = block;
+ ctx->key = key;
+
+ (*block)(ctx->H.c, ctx->H.c, key);
+
+ if (is_endian.little) {
+/* H is stored in host byte order */
+#ifdef BSWAP8
+ ctx->H.u[0] = BSWAP8(ctx->H.u[0]);
+ ctx->H.u[1] = BSWAP8(ctx->H.u[1]);
+#else
+ uint8_t *p = ctx->H.c;
+ uint64_t hi, lo;
+ hi = (uint64_t)GETU32(p) << 32 | GETU32(p + 4);
+ lo = (uint64_t)GETU32(p + 8) << 32 | GETU32(p + 12);
+ ctx->H.u[0] = hi;
+ ctx->H.u[1] = lo;
+#endif
+ }
+
+#if defined(GHASH_ASM_X86_OR_64)
+ if (crypto_gcm_clmul_enabled()) {
+ if (((OPENSSL_ia32cap_P[1] >> 22) & 0x41) == 0x41) { /* AVX+MOVBE */
+ gcm_init_avx(ctx->Htable, ctx->H.u);
+ ctx->gmult = gcm_gmult_avx;
+ ctx->ghash = gcm_ghash_avx;
+ } else {
+ gcm_init_clmul(ctx->Htable, ctx->H.u);
+ ctx->gmult = gcm_gmult_clmul;
+ ctx->ghash = gcm_ghash_clmul;
+ }
+ return;
+ }
+ gcm_init_4bit(ctx->Htable, ctx->H.u);
+#if defined(GHASH_ASM_X86) /* x86 only */
+ if (OPENSSL_ia32cap_P[0] & (1 << 25)) { /* check SSE bit */
+ 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 (pmull_capable()) {
+ gcm_init_v8(ctx->Htable, ctx->H.u);
+ ctx->gmult = gcm_gmult_v8;
+ ctx->ghash = gcm_ghash_v8;
+ } else if (neon_capable()) {
+ gcm_init_neon(ctx->Htable,ctx->H.u);
+ 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);
+ ctx->gmult = gcm_gmult_4bit;
+ ctx->ghash = gcm_ghash_4bit;
+#endif
+}
+
+void CRYPTO_gcm128_setiv(GCM128_CONTEXT *ctx, const uint8_t *iv, size_t len) {
+ const union {
+ long one;
+ char little;
+ } is_endian = {1};
+ unsigned int ctr;
+#ifdef GCM_FUNCREF_4BIT
+ void (*gcm_gmult_p)(uint64_t 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;
+ uint64_t 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;
+ if (is_endian.little) {
+#ifdef BSWAP8
+ ctx->Yi.u[1] ^= BSWAP8(len0);
+#else
+ ctx->Yi.c[8] ^= (uint8_t)(len0 >> 56);
+ ctx->Yi.c[9] ^= (uint8_t)(len0 >> 48);
+ ctx->Yi.c[10] ^= (uint8_t)(len0 >> 40);
+ ctx->Yi.c[11] ^= (uint8_t)(len0 >> 32);
+ ctx->Yi.c[12] ^= (uint8_t)(len0 >> 24);
+ ctx->Yi.c[13] ^= (uint8_t)(len0 >> 16);
+ ctx->Yi.c[14] ^= (uint8_t)(len0 >> 8);
+ ctx->Yi.c[15] ^= (uint8_t)(len0);
+#endif
+ } else {
+ ctx->Yi.u[1] ^= len0;
+ }
+
+ GCM_MUL(ctx, Yi);
+
+ if (is_endian.little) {
+ ctr = GETU32(ctx->Yi.c + 12);
+ } else {
+ ctr = ctx->Yi.d[3];
+ }
+ }
+
+ (*ctx->block)(ctx->Yi.c, ctx->EK0.c, ctx->key);
+ ++ctr;
+ if (is_endian.little) {
+ PUTU32(ctx->Yi.c + 12, ctr);
+ } else {
+ ctx->Yi.d[3] = ctr;
+ }
+}
+
+int CRYPTO_gcm128_aad(GCM128_CONTEXT *ctx, const uint8_t *aad, size_t len) {
+ size_t i;
+ unsigned int n;
+ uint64_t alen = ctx->len.u[0];
+#ifdef GCM_FUNCREF_4BIT
+ void (*gcm_gmult_p)(uint64_t Xi[2], const u128 Htable[16]) = ctx->gmult;
+#ifdef GHASH
+ void (*gcm_ghash_p)(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp,
+ size_t len) = ctx->ghash;
+#endif
+#endif
+
+ if (ctx->len.u[1]) {
+ return 0;
+ }
+
+ alen += len;
+ if (alen > (OPENSSL_U64(1) << 61) || (sizeof(len) == 8 && alen < len)) {
+ return 0;
+ }
+ 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 1;
+ }
+ }
+
+#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 1;
+}
+
+int CRYPTO_gcm128_encrypt(GCM128_CONTEXT *ctx, const unsigned char *in,
+ unsigned char *out, size_t len) {
+ const union {
+ long one;
+ char little;
+ } is_endian = {1};
+ unsigned int n, ctr;
+ size_t i;
+ uint64_t mlen = ctx->len.u[1];
+ block128_f block = ctx->block;
+ void *key = ctx->key;
+#ifdef GCM_FUNCREF_4BIT
+ void (*gcm_gmult_p)(uint64_t Xi[2], const u128 Htable[16]) = ctx->gmult;
+#ifdef GHASH
+ void (*gcm_ghash_p)(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp,
+ size_t len) = ctx->ghash;
+#endif
+#endif
+
+ mlen += len;
+ if (mlen > ((OPENSSL_U64(1) << 36) - 32) ||
+ (sizeof(len) == 8 && mlen < len)) {
+ return 0;
+ }
+ ctx->len.u[1] = mlen;
+
+ if (ctx->ares) {
+ /* First call to encrypt finalizes GHASH(AAD) */
+ GCM_MUL(ctx, Xi);
+ ctx->ares = 0;
+ }
+
+ if (is_endian.little) {
+ ctr = GETU32(ctx->Yi.c + 12);
+ } else {
+ ctr = 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 1;
+ }
+ }
+ if (STRICT_ALIGNMENT && ((size_t)in | (size_t)out) % sizeof(size_t) != 0) {
+ for (i = 0; i < len; ++i) {
+ if (n == 0) {
+ (*block)(ctx->Yi.c, ctx->EKi.c, key);
+ ++ctr;
+ if (is_endian.little) {
+ PUTU32(ctx->Yi.c + 12, ctr);
+ } else {
+ ctx->Yi.d[3] = 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 1;
+ }
+#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;
+ if (is_endian.little) {
+ PUTU32(ctx->Yi.c + 12, ctr);
+ } else {
+ ctx->Yi.d[3] = 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;
+ if (is_endian.little) {
+ PUTU32(ctx->Yi.c + 12, ctr);
+ } else {
+ ctx->Yi.d[3] = 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;
+ if (is_endian.little) {
+ PUTU32(ctx->Yi.c + 12, ctr);
+ } else {
+ ctx->Yi.d[3] = 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;
+ if (is_endian.little) {
+ PUTU32(ctx->Yi.c + 12, ctr);
+ } else {
+ ctx->Yi.d[3] = ctr;
+ }
+ while (len--) {
+ ctx->Xi.c[n] ^= out[n] = in[n] ^ ctx->EKi.c[n];
+ ++n;
+ }
+ }
+
+ ctx->mres = n;
+ return 1;
+}
+
+int CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx, const unsigned char *in,
+ unsigned char *out, size_t len) {
+ const union {
+ long one;
+ char little;
+ } is_endian = {1};
+ unsigned int n, ctr;
+ size_t i;
+ uint64_t mlen = ctx->len.u[1];
+ block128_f block = ctx->block;
+ void *key = ctx->key;
+#ifdef GCM_FUNCREF_4BIT
+ void (*gcm_gmult_p)(uint64_t Xi[2], const u128 Htable[16]) = ctx->gmult;
+#ifdef GHASH
+ void (*gcm_ghash_p)(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp,
+ size_t len) = ctx->ghash;
+#endif
+#endif
+
+ mlen += len;
+ if (mlen > ((OPENSSL_U64(1) << 36) - 32) ||
+ (sizeof(len) == 8 && mlen < len)) {
+ return 0;
+ }
+ ctx->len.u[1] = mlen;
+
+ if (ctx->ares) {
+ /* First call to decrypt finalizes GHASH(AAD) */
+ GCM_MUL(ctx, Xi);
+ ctx->ares = 0;
+ }
+
+ if (is_endian.little) {
+ ctr = GETU32(ctx->Yi.c + 12);
+ } else {
+ ctr = ctx->Yi.d[3];
+ }
+
+ n = ctx->mres;
+ if (n) {
+ while (n && len) {
+ uint8_t 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 1;
+ }
+ }
+ if (STRICT_ALIGNMENT && ((size_t)in | (size_t)out) % sizeof(size_t) != 0) {
+ for (i = 0; i < len; ++i) {
+ uint8_t c;
+ if (n == 0) {
+ (*block)(ctx->Yi.c, ctx->EKi.c, key);
+ ++ctr;
+ if (is_endian.little) {
+ PUTU32(ctx->Yi.c + 12, ctr);
+ } else {
+ ctx->Yi.d[3] = 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 1;
+ }
+#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;
+ if (is_endian.little) {
+ PUTU32(ctx->Yi.c + 12, ctr);
+ } else {
+ ctx->Yi.d[3] = 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;
+ if (is_endian.little) {
+ PUTU32(ctx->Yi.c + 12, ctr);
+ } else {
+ ctx->Yi.d[3] = 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;
+ if (is_endian.little) {
+ PUTU32(ctx->Yi.c + 12, ctr);
+ } else {
+ ctx->Yi.d[3] = ctr;
+ }
+ for (i = 0; i < 16 / sizeof(size_t); ++i) {
+ size_t c = in_t[i];
+ out_t[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;
+ if (is_endian.little) {
+ PUTU32(ctx->Yi.c + 12, ctr);
+ } else {
+ ctx->Yi.d[3] = ctr;
+ }
+ while (len--) {
+ uint8_t c = in[n];
+ ctx->Xi.c[n] ^= c;
+ out[n] = c ^ ctx->EKi.c[n];
+ ++n;
+ }
+ }
+
+ ctx->mres = n;
+ return 1;
+}
+
+int CRYPTO_gcm128_encrypt_ctr32(GCM128_CONTEXT *ctx, const uint8_t *in,
+ uint8_t *out, size_t len, ctr128_f stream) {
+ const union {
+ long one;
+ char little;
+ } is_endian = {1};
+ unsigned int n, ctr;
+ size_t i;
+ uint64_t mlen = ctx->len.u[1];
+ void *key = ctx->key;
+#ifdef GCM_FUNCREF_4BIT
+ void (*gcm_gmult_p)(uint64_t Xi[2], const u128 Htable[16]) = ctx->gmult;
+#ifdef GHASH
+ void (*gcm_ghash_p)(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp,
+ size_t len) = ctx->ghash;
+#endif
+#endif
+
+ mlen += len;
+ if (mlen > ((OPENSSL_U64(1) << 36) - 32) ||
+ (sizeof(len) == 8 && mlen < len)) {
+ return 0;
+ }
+ ctx->len.u[1] = mlen;
+
+ if (ctx->ares) {
+ /* First call to encrypt finalizes GHASH(AAD) */
+ GCM_MUL(ctx, Xi);
+ ctx->ares = 0;
+ }
+
+ if (is_endian.little) {
+ ctr = GETU32(ctx->Yi.c + 12);
+ } else {
+ ctr = 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 1;
+ }
+ }
+#if defined(GHASH)
+ while (len >= GHASH_CHUNK) {
+ (*stream)(in, out, GHASH_CHUNK / 16, key, ctx->Yi.c);
+ ctr += GHASH_CHUNK / 16;
+ if (is_endian.little) {
+ PUTU32(ctx->Yi.c + 12, ctr);
+ } else {
+ ctx->Yi.d[3] = 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;
+ if (is_endian.little) {
+ PUTU32(ctx->Yi.c + 12, ctr);
+ } else {
+ ctx->Yi.d[3] = 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;
+ if (is_endian.little) {
+ PUTU32(ctx->Yi.c + 12, ctr);
+ } else {
+ ctx->Yi.d[3] = ctr;
+ }
+ while (len--) {
+ ctx->Xi.c[n] ^= out[n] = in[n] ^ ctx->EKi.c[n];
+ ++n;
+ }
+ }
+
+ ctx->mres = n;
+ return 1;
+}
+
+int CRYPTO_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx, const uint8_t *in,
+ uint8_t *out, size_t len,
+ ctr128_f stream) {
+ const union {
+ long one;
+ char little;
+ } is_endian = {1};
+ unsigned int n, ctr;
+ size_t i;
+ uint64_t mlen = ctx->len.u[1];
+ void *key = ctx->key;
+#ifdef GCM_FUNCREF_4BIT
+ void (*gcm_gmult_p)(uint64_t Xi[2], const u128 Htable[16]) = ctx->gmult;
+#ifdef GHASH
+ void (*gcm_ghash_p)(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp,
+ size_t len) = ctx->ghash;
+#endif
+#endif
+
+ mlen += len;
+ if (mlen > ((OPENSSL_U64(1) << 36) - 32) ||
+ (sizeof(len) == 8 && mlen < len)) {
+ return 0;
+ }
+ ctx->len.u[1] = mlen;
+
+ if (ctx->ares) {
+ /* First call to decrypt finalizes GHASH(AAD) */
+ GCM_MUL(ctx, Xi);
+ ctx->ares = 0;
+ }
+
+ if (is_endian.little) {
+ ctr = GETU32(ctx->Yi.c + 12);
+ } else {
+ ctr = ctx->Yi.d[3];
+ }
+
+ n = ctx->mres;
+ if (n) {
+ while (n && len) {
+ uint8_t 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 1;
+ }
+ }
+#if defined(GHASH)
+ while (len >= GHASH_CHUNK) {
+ GHASH(ctx, in, GHASH_CHUNK);
+ (*stream)(in, out, GHASH_CHUNK / 16, key, ctx->Yi.c);
+ ctr += GHASH_CHUNK / 16;
+ if (is_endian.little)
+ PUTU32(ctx->Yi.c + 12, ctr);
+ else
+ ctx->Yi.d[3] = 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;
+ if (is_endian.little)
+ PUTU32(ctx->Yi.c + 12, ctr);
+ else
+ ctx->Yi.d[3] = ctr;
+ out += i;
+ in += i;
+ len -= i;
+ }
+ if (len) {
+ (*ctx->block)(ctx->Yi.c, ctx->EKi.c, key);
+ ++ctr;
+ if (is_endian.little)
+ PUTU32(ctx->Yi.c + 12, ctr);
+ else
+ ctx->Yi.d[3] = ctr;
+ while (len--) {
+ uint8_t c = in[n];
+ ctx->Xi.c[n] ^= c;
+ out[n] = c ^ ctx->EKi.c[n];
+ ++n;
+ }
+ }
+
+ ctx->mres = n;
+ return 1;
+}
+
+int CRYPTO_gcm128_finish(GCM128_CONTEXT *ctx, const uint8_t *tag, size_t len) {
+ const union {
+ long one;
+ char little;
+ } is_endian = {1};
+ uint64_t alen = ctx->len.u[0] << 3;
+ uint64_t clen = ctx->len.u[1] << 3;
+#ifdef GCM_FUNCREF_4BIT
+ void (*gcm_gmult_p)(uint64_t Xi[2], const u128 Htable[16]) = ctx->gmult;
+#endif
+
+ if (ctx->mres || ctx->ares) {
+ GCM_MUL(ctx, Xi);
+ }
+
+ if (is_endian.little) {
+#ifdef BSWAP8
+ alen = BSWAP8(alen);
+ clen = BSWAP8(clen);
+#else
+ uint8_t *p = ctx->len.c;
+
+ ctx->len.u[0] = alen;
+ ctx->len.u[1] = clen;
+
+ alen = (uint64_t)GETU32(p) << 32 | GETU32(p + 4);
+ clen = (uint64_t)GETU32(p + 8) << 32 | GETU32(p + 12);
+#endif
+ }
+
+ ctx->Xi.u[0] ^= alen;
+ ctx->Xi.u[1] ^= 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 CRYPTO_memcmp(ctx->Xi.c, tag, len) == 0;
+ } else {
+ return 0;
+ }
+}
+
+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));
+}
+
+void CRYPTO_gcm128_release(GCM128_CONTEXT *ctx) {
+ if (ctx) {
+ OPENSSL_cleanse(ctx, sizeof(*ctx));
+ OPENSSL_free(ctx);
+ }
+}
+
+#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64)
+int crypto_gcm_clmul_enabled(void) {
+#ifdef GHASH_ASM
+ return OPENSSL_ia32cap_P[0] & (1 << 24) && /* check FXSR bit */
+ OPENSSL_ia32cap_P[1] & (1 << 1); /* check PCLMULQDQ bit */
+#else
+ return 0;
+#endif
+}
+#endif
diff --git a/src/crypto/modes/gcm_test.c b/src/crypto/modes/gcm_test.c
new file mode 100644
index 0000000..29f9d95
--- /dev/null
+++ b/src/crypto/modes/gcm_test.c
@@ -0,0 +1,435 @@
+/* ====================================================================
+ * 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 <stdio.h>
+#include <string.h>
+
+#include <openssl/aes.h>
+#include <openssl/crypto.h>
+#include <openssl/mem.h>
+#include <openssl/modes.h>
+
+#include "internal.h"
+
+
+struct test_case {
+ const char *key;
+ const char *plaintext;
+ const char *additional_data;
+ const char *nonce;
+ const char *ciphertext;
+ const char *tag;
+};
+
+static const struct test_case test_cases[] = {
+ {
+ "00000000000000000000000000000000",
+ NULL,
+ NULL,
+ "000000000000000000000000",
+ NULL,
+ "58e2fccefa7e3061367f1d57a4e7455a",
+ },
+ {
+ "00000000000000000000000000000000",
+ "00000000000000000000000000000000",
+ NULL,
+ "000000000000000000000000",
+ "0388dace60b6a392f328c2b971b2fe78",
+ "ab6e47d42cec13bdf53a67b21257bddf",
+ },
+ {
+ "feffe9928665731c6d6a8f9467308308",
+ "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255",
+ NULL,
+ "cafebabefacedbaddecaf888",
+ "42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091473f5985",
+ "4d5c2af327cd64a62cf35abd2ba6fab4",
+ },
+ {
+ "feffe9928665731c6d6a8f9467308308",
+ "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
+ "feedfacedeadbeeffeedfacedeadbeefabaddad2",
+ "cafebabefacedbaddecaf888",
+ "42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091",
+ "5bc94fbc3221a5db94fae95ae7121a47",
+ },
+ {
+ "feffe9928665731c6d6a8f9467308308",
+ "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
+ "feedfacedeadbeeffeedfacedeadbeefabaddad2",
+ "cafebabefacedbad",
+ "61353b4c2806934a777ff51fa22a4755699b2a714fcdc6f83766e5f97b6c742373806900e49f24b22b097544d4896b424989b5e1ebac0f07c23f4598",
+ "3612d2e79e3b0785561be14aaca2fccb",
+ },
+ {
+ "feffe9928665731c6d6a8f9467308308",
+ "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
+ "feedfacedeadbeeffeedfacedeadbeefabaddad2",
+ "9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b",
+ "8ce24998625615b603a033aca13fb894be9112a5c3a211a8ba262a3cca7e2ca701e4a9a4fba43c90ccdcb281d48c7c6fd62875d2aca417034c34aee5",
+ "619cc5aefffe0bfa462af43c1699d050",
+ },
+ {
+ "000000000000000000000000000000000000000000000000",
+ NULL,
+ NULL,
+ "000000000000000000000000",
+ NULL,
+ "cd33b28ac773f74ba00ed1f312572435",
+ },
+ {
+ "000000000000000000000000000000000000000000000000",
+ "00000000000000000000000000000000",
+ NULL,
+ "000000000000000000000000",
+ "98e7247c07f0fe411c267e4384b0f600",
+ "2ff58d80033927ab8ef4d4587514f0fb",
+ },
+ {
+ "feffe9928665731c6d6a8f9467308308feffe9928665731c",
+ "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255",
+ NULL,
+ "cafebabefacedbaddecaf888",
+ "3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710acade256",
+ "9924a7c8587336bfb118024db8674a14",
+ },
+ {
+ "feffe9928665731c6d6a8f9467308308feffe9928665731c",
+ "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
+ "feedfacedeadbeeffeedfacedeadbeefabaddad2",
+ "cafebabefacedbaddecaf888",
+ "3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710",
+ "2519498e80f1478f37ba55bd6d27618c",
+ },
+ {
+ "feffe9928665731c6d6a8f9467308308feffe9928665731c",
+ "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
+ "feedfacedeadbeeffeedfacedeadbeefabaddad2",
+ "cafebabefacedbad",
+ "0f10f599ae14a154ed24b36e25324db8c566632ef2bbb34f8347280fc4507057fddc29df9a471f75c66541d4d4dad1c9e93a19a58e8b473fa0f062f7",
+ "65dcc57fcf623a24094fcca40d3533f8",
+ },
+ {
+ "feffe9928665731c6d6a8f9467308308feffe9928665731c",
+ "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
+ "feedfacedeadbeeffeedfacedeadbeefabaddad2",
+ "cafebabefacedbad",
+ "0f10f599ae14a154ed24b36e25324db8c566632ef2bbb34f8347280fc4507057fddc29df9a471f75c66541d4d4dad1c9e93a19a58e8b473fa0f062f7",
+ "65dcc57fcf623a24094fcca40d3533f8",
+ },
+ {
+ "feffe9928665731c6d6a8f9467308308feffe9928665731c",
+ "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
+ "feedfacedeadbeeffeedfacedeadbeefabaddad2",
+ "9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b",
+ "d27e88681ce3243c4830165a8fdcf9ff1de9a1d8e6b447ef6ef7b79828666e4581e79012af34ddd9e2f037589b292db3e67c036745fa22e7e9b7373b",
+ "dcf566ff291c25bbb8568fc3d376a6d9",
+ },
+ {
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ NULL,
+ NULL,
+ "000000000000000000000000",
+ NULL,
+ "530f8afbc74536b9a963b4f1c4cb738b",
+ },
+ {
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "00000000000000000000000000000000",
+ NULL,
+ "000000000000000000000000",
+ "cea7403d4d606b6e074ec5d3baf39d18",
+ "d0d1c8a799996bf0265b98b5d48ab919",
+ },
+ {
+ "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308",
+ "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255",
+ NULL,
+ "cafebabefacedbaddecaf888",
+ "522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad",
+ "b094dac5d93471bdec1a502270e3cc6c",
+ },
+ {
+ "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308",
+ "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
+ "feedfacedeadbeeffeedfacedeadbeefabaddad2",
+ "cafebabefacedbaddecaf888",
+ "522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662",
+ "76fc6ece0f4e1768cddf8853bb2d551b",
+ },
+ {
+ "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308",
+ "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
+ "feedfacedeadbeeffeedfacedeadbeefabaddad2",
+ "cafebabefacedbad",
+ "c3762df1ca787d32ae47c13bf19844cbaf1ae14d0b976afac52ff7d79bba9de0feb582d33934a4f0954cc2363bc73f7862ac430e64abe499f47c9b1f",
+ "3a337dbf46a792c45e454913fe2ea8f2",
+ },
+ {
+ "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308",
+ "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
+ "feedfacedeadbeeffeedfacedeadbeefabaddad2",
+ "9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b",
+ "5a8def2f0c9e53f1f75d7853659e2a20eeb2b22aafde6419a058ab4f6f746bf40fc0c3b780f244452da3ebf1c5d82cdea2418997200ef82e44ae7e3f",
+ "a44a8266ee1c8eb0c8b5d4cf5ae9f19a",
+ },
+ {
+ "00000000000000000000000000000000",
+ NULL,
+ "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad",
+ "000000000000000000000000",
+ NULL,
+ "5fea793a2d6f974d37e68e0cb8ff9492",
+ },
+ {
+ "00000000000000000000000000000000",
+ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ NULL,
+ /* This nonce results in 0xfff in counter LSB. */
+ "ffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "56b3373ca9ef6e4a2b64fe1e9a17b61425f10d47a75a5fce13efc6bc784af24f4141bdd48cf7c770887afd573cca5418a9aeffcd7c5ceddfc6a78397b9a85b499da558257267caab2ad0b23ca476a53cb17fb41c4b8b475cb4f3f7165094c229c9e8c4dc0a2a5ff1903e501511221376a1cdb8364c5061a20cae74bc4acd76ceb0abc9fd3217ef9f8c90be402ddf6d8697f4f880dff15bfb7a6b28241ec8fe183c2d59e3f9dfff653c7126f0acb9e64211f42bae12af462b1070bef1ab5e3606872ca10dee15b3249b1a1b958f23134c4bccb7d03200bce420a2f8eb66dcf3644d1423c1b5699003c13ecef4bf38a3b60eedc34033bac1902783dc6d89e2e774188a439c7ebcc0672dbda4ddcfb2794613b0be41315ef778708a70ee7d75165c",
+ "8b307f6b33286d0ab026a9ed3fe1e85f",
+ },
+};
+
+static int from_hex(uint8_t *out, char in) {
+ if (in >= '0' && in <= '9') {
+ *out = in - '0';
+ return 1;
+ }
+ if (in >= 'a' && in <= 'f') {
+ *out = in - 'a' + 10;
+ return 1;
+ }
+ if (in >= 'A' && in <= 'F') {
+ *out = in - 'A' + 10;
+ return 1;
+ }
+
+ return 0;
+}
+
+static int decode_hex(uint8_t **out, size_t *out_len, const char *in,
+ unsigned test_num, const char *description) {
+ uint8_t *buf = NULL;
+ size_t i;
+
+ if (in == NULL) {
+ *out = NULL;
+ *out_len = 0;
+ return 1;
+ }
+
+ size_t len = strlen(in);
+ if (len & 1) {
+ fprintf(stderr, "%u: Odd-length %s input.\n", test_num, description);
+ goto err;
+ }
+
+ buf = OPENSSL_malloc(len / 2);
+ if (buf == NULL) {
+ fprintf(stderr, "%u: malloc failure.\n", test_num);
+ goto err;
+ }
+
+ for (i = 0; i < len; i += 2) {
+ uint8_t v, v2;
+ if (!from_hex(&v, in[i]) ||
+ !from_hex(&v2, in[i+1])) {
+ fprintf(stderr, "%u: invalid hex digit in %s around offset %u.\n",
+ test_num, description, (unsigned)i);
+ goto err;
+ }
+ buf[i/2] = (v << 4) | v2;
+ }
+
+ *out = buf;
+ *out_len = len/2;
+ return 1;
+
+err:
+ if (buf) {
+ OPENSSL_free(buf);
+ }
+ return 0;
+}
+
+void hexdump(const char *msg, const void *in, size_t len) {
+ const uint8_t *data = in;
+ size_t i;
+
+ fprintf(stderr, "%s: ", msg);
+ for (i = 0; i < len; i++) {
+ fprintf(stderr, "%02x", data[i]);
+ }
+ fprintf(stderr, "\n");
+}
+
+static int run_test_case(unsigned test_num, const struct test_case *test) {
+ size_t key_len, plaintext_len, additional_data_len, nonce_len, ciphertext_len,
+ tag_len;
+ uint8_t *key = NULL, *plaintext = NULL, *additional_data = NULL,
+ *nonce = NULL, *ciphertext = NULL, *tag = NULL, *out = NULL;
+ int ret = 0;
+ AES_KEY aes_key;
+ GCM128_CONTEXT ctx;
+
+ if (!decode_hex(&key, &key_len, test->key, test_num, "key") ||
+ !decode_hex(&plaintext, &plaintext_len, test->plaintext, test_num,
+ "plaintext") ||
+ !decode_hex(&additional_data, &additional_data_len, test->additional_data,
+ test_num, "additional_data") ||
+ !decode_hex(&nonce, &nonce_len, test->nonce, test_num, "nonce") ||
+ !decode_hex(&ciphertext, &ciphertext_len, test->ciphertext, test_num,
+ "ciphertext") ||
+ !decode_hex(&tag, &tag_len, test->tag, test_num, "tag")) {
+ goto out;
+ }
+
+ if (plaintext_len != ciphertext_len) {
+ fprintf(stderr, "%u: plaintext and ciphertext have differing lengths.\n",
+ test_num);
+ goto out;
+ }
+
+ if (key_len != 16 && key_len != 24 && key_len != 32) {
+ fprintf(stderr, "%u: bad key length.\n", test_num);
+ goto out;
+ }
+
+ if (tag_len != 16) {
+ fprintf(stderr, "%u: bad tag length.\n", test_num);
+ goto out;
+ }
+
+ out = OPENSSL_malloc(plaintext_len);
+ if (AES_set_encrypt_key(key, key_len*8, &aes_key)) {
+ fprintf(stderr, "%u: AES_set_encrypt_key failed.\n", test_num);
+ goto out;
+ }
+
+ CRYPTO_gcm128_init(&ctx, &aes_key, (block128_f) AES_encrypt);
+ CRYPTO_gcm128_setiv(&ctx, nonce, nonce_len);
+ memset(out, 0, plaintext_len);
+ if (additional_data) {
+ CRYPTO_gcm128_aad(&ctx, additional_data, additional_data_len);
+ }
+ if (plaintext) {
+ CRYPTO_gcm128_encrypt(&ctx, plaintext, out, plaintext_len);
+ }
+ if (!CRYPTO_gcm128_finish(&ctx, tag, tag_len) ||
+ (ciphertext && memcmp(out, ciphertext, plaintext_len) != 0)) {
+ fprintf(stderr, "%u: encrypt failed.\n", test_num);
+ hexdump("got ", out, plaintext_len);
+ hexdump("want", ciphertext, plaintext_len);
+ goto out;
+ }
+
+ CRYPTO_gcm128_setiv(&ctx, nonce, nonce_len);
+ memset(out, 0, plaintext_len);
+ if (additional_data) {
+ CRYPTO_gcm128_aad(&ctx, additional_data, additional_data_len);
+ }
+ if (ciphertext) {
+ CRYPTO_gcm128_decrypt(&ctx, ciphertext, out, plaintext_len);
+ }
+ if (!CRYPTO_gcm128_finish(&ctx, tag, tag_len)) {
+ fprintf(stderr, "%u: decrypt failed.\n", test_num);
+ goto out;
+ }
+ if (plaintext && memcmp(out, plaintext, plaintext_len)) {
+ fprintf(stderr, "%u: plaintext doesn't match.\n", test_num);
+ goto out;
+ }
+
+ ret = 1;
+
+out:
+ if (key) {
+ OPENSSL_free(key);
+ }
+ if (plaintext) {
+ OPENSSL_free(plaintext);
+ }
+ if (additional_data) {
+ OPENSSL_free(additional_data);
+ }
+ if (nonce) {
+ OPENSSL_free(nonce);
+ }
+ if (ciphertext) {
+ OPENSSL_free(ciphertext);
+ }
+ if (tag) {
+ OPENSSL_free(tag);
+ }
+ if (out) {
+ OPENSSL_free(out);
+ }
+ return ret;
+}
+
+int main(void) {
+ int ret = 0;
+ unsigned i;
+
+ CRYPTO_library_init();
+
+ for (i = 0; i < sizeof(test_cases) / sizeof(struct test_case); i++) {
+ if (!run_test_case(i, &test_cases[i])) {
+ ret = 1;
+ }
+ }
+
+ if (ret == 0) {
+ printf("PASS\n");
+ }
+
+ return ret;
+}
diff --git a/src/crypto/modes/internal.h b/src/crypto/modes/internal.h
new file mode 100644
index 0000000..9662e0d
--- /dev/null
+++ b/src/crypto/modes/internal.h
@@ -0,0 +1,199 @@
+/* ====================================================================
+ * 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.
+ * ==================================================================== */
+
+#ifndef OPENSSL_HEADER_MODES_INTERNAL_H
+#define OPENSSL_HEADER_MODES_INTERNAL_H
+
+#include <openssl/base.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+#define asm __asm__
+
+#define STRICT_ALIGNMENT 1
+#if defined(OPENSSL_X86_64) || defined(OPENSSL_X86) || defined(OPENSSL_AARCH64)
+#undef STRICT_ALIGNMENT
+#define STRICT_ALIGNMENT 0
+#endif
+
+#if !defined(PEDANTIC) && !defined(OPENSSL_NO_ASM)
+#if defined(__GNUC__) && __GNUC__ >= 2
+#if defined(OPENSSL_X86_64)
+#define BSWAP8(x) \
+ ({ \
+ uint64_t ret = (x); \
+ asm("bswapq %0" : "+r"(ret)); \
+ ret; \
+ })
+#define BSWAP4(x) \
+ ({ \
+ uint32_t ret = (x); \
+ asm("bswapl %0" : "+r"(ret)); \
+ ret; \
+ })
+#elif defined(OPENSSL_X86)
+#define BSWAP8(x) \
+ ({ \
+ uint32_t lo = (uint64_t)(x) >> 32, hi = (x); \
+ asm("bswapl %0; bswapl %1" : "+r"(hi), "+r"(lo)); \
+ (uint64_t) hi << 32 | lo; \
+ })
+#define BSWAP4(x) \
+ ({ \
+ uint32_t ret = (x); \
+ asm("bswapl %0" : "+r"(ret)); \
+ ret; \
+ })
+#elif defined(OPENSSL_AARCH64)
+#define BSWAP8(x) \
+ ({ \
+ uint64_t ret; \
+ asm("rev %0,%1" : "=r"(ret) : "r"(x)); \
+ ret; \
+ })
+#define BSWAP4(x) \
+ ({ \
+ uint32_t ret; \
+ asm("rev %w0,%w1" : "=r"(ret) : "r"(x)); \
+ ret; \
+ })
+#elif defined(OPENSSL_ARM) && !defined(STRICT_ALIGNMENT)
+#define BSWAP8(x) \
+ ({ \
+ uint32_t lo = (uint64_t)(x) >> 32, hi = (x); \
+ asm("rev %0,%0; rev %1,%1" : "+r"(hi), "+r"(lo)); \
+ (uint64_t) hi << 32 | lo; \
+ })
+#define BSWAP4(x) \
+ ({ \
+ uint32_t ret; \
+ asm("rev %0,%1" : "=r"(ret) : "r"((uint32_t)(x))); \
+ ret; \
+ })
+#endif
+#elif defined(_MSC_VER)
+#if _MSC_VER >= 1300
+#pragma intrinsic(_byteswap_uint64, _byteswap_ulong)
+#define BSWAP8(x) _byteswap_uint64((uint64_t)(x))
+#define BSWAP4(x) _byteswap_ulong((uint32_t)(x))
+#elif defined(OPENSSL_X86)
+__inline uint32_t _bswap4(uint32_t val) {
+ _asm mov eax, val
+ _asm bswap eax
+}
+#define BSWAP4(x) _bswap4(x)
+#endif
+#endif
+#endif
+
+#if defined(BSWAP4) && !defined(STRICT_ALIGNMENT)
+#define GETU32(p) BSWAP4(*(const uint32_t *)(p))
+#define PUTU32(p, v) *(uint32_t *)(p) = BSWAP4(v)
+#else
+#define GETU32(p) \
+ ((uint32_t)(p)[0] << 24 | (uint32_t)(p)[1] << 16 | (uint32_t)(p)[2] << 8 | (uint32_t)(p)[3])
+#define PUTU32(p, v) \
+ ((p)[0] = (uint8_t)((v) >> 24), (p)[1] = (uint8_t)((v) >> 16), \
+ (p)[2] = (uint8_t)((v) >> 8), (p)[3] = (uint8_t)(v))
+#endif
+
+
+/* GCM definitions */
+typedef struct { uint64_t hi,lo; } u128;
+
+struct gcm128_context {
+ /* Following 6 names follow names in GCM specification */
+ union {
+ uint64_t u[2];
+ uint32_t d[4];
+ uint8_t 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! */
+ u128 Htable[16];
+ void (*gmult)(uint64_t Xi[2], const u128 Htable[16]);
+ void (*ghash)(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp,
+ size_t len);
+
+ unsigned int mres, ares;
+ block128_f block;
+ void *key;
+};
+
+struct xts128_context {
+ void *key1, *key2;
+ block128_f block1, block2;
+};
+
+struct ccm128_context {
+ union {
+ uint64_t u[2];
+ uint8_t c[16];
+ } nonce, cmac;
+ uint64_t blocks;
+ block128_f block;
+ void *key;
+};
+
+#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64)
+/* crypto_gcm_clmul_enabled returns one if the CLMUL implementation of GCM is
+ * used. */
+int crypto_gcm_clmul_enabled(void);
+#endif
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_MODES_INTERNAL_H */
diff --git a/src/crypto/modes/ofb.c b/src/crypto/modes/ofb.c
new file mode 100644
index 0000000..5836a9f
--- /dev/null
+++ b/src/crypto/modes/ofb.c
@@ -0,0 +1,107 @@
+/* ====================================================================
+ * 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 <openssl/modes.h>
+
+#include <assert.h>
+
+#include "internal.h"
+
+
+void CRYPTO_ofb128_encrypt(const uint8_t *in, uint8_t *out, size_t len,
+ const void *key, uint8_t ivec[16], int *num,
+ block128_f block) {
+ unsigned int n;
+
+ assert(in && out && key && ivec && num);
+ assert((16 % sizeof(size_t)) == 0);
+
+ n = *num;
+
+ while (n && len) {
+ *(out++) = *(in++) ^ ivec[n];
+ --len;
+ n = (n + 1) % 16;
+ }
+
+#if STRICT_ALIGNMENT
+ if (((size_t)in | (size_t)out | (size_t)ivec) % sizeof(size_t) != 0) {
+ size_t l = 0;
+ while (l < len) {
+ if (n == 0) {
+ (*block)(ivec, ivec, key);
+ }
+ out[l] = in[l] ^ ivec[n];
+ ++l;
+ n = (n + 1) % 16;
+ }
+
+ *num = n;
+ return;
+ }
+#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;
+}
diff --git a/src/crypto/obj/CMakeLists.txt b/src/crypto/obj/CMakeLists.txt
new file mode 100644
index 0000000..ade603d
--- /dev/null
+++ b/src/crypto/obj/CMakeLists.txt
@@ -0,0 +1,11 @@
+include_directories(. .. ../../include)
+
+add_library(
+ obj
+
+ OBJECT
+
+ obj.c
+ obj_xref.c
+ obj_error.c
+)
diff --git a/src/crypto/obj/README b/src/crypto/obj/README
new file mode 100644
index 0000000..8826e59
--- /dev/null
+++ b/src/crypto/obj/README
@@ -0,0 +1,37 @@
+OID information is generated via a series of perl scripts. In order, the full
+list of commands to run are:
+
+ perl objects.pl objects.txt obj_mac.num ../../include/openssl/obj_mac.h
+ perl obj_dat.pl ../../include/openssl/obj_mac.h obj_dat.h
+ perl obj_xref.pl obj_mac.num obj_xref.txt > obj_xref.h
+
+objects.txt contains the list of all built-in OIDs. It is processed by
+objects.pl to output obj_mac.num and obj_mac.h. obj_mac.num is the list of NID
+values for each OID. This is an input/output parameter so NID values are stable
+across regenerations. obj_mac.h is the header which defines macros for all the
+built-in OIDs in C.
+
+obj_mac.h is read by obj_dat.pl to generate obj_dat.h. obj_dat.h contains the
+ASN1_OBJECTs corresponding to built-in OIDs themselves along with lookup tables
+for search by short name, OID, etc.
+
+obj_mac.num and obj_xref.txt are read by obj_xref.pl to generate
+obj_xref.h. obj_xref.txt links signature OIDs to corresponding public key
+algorithms and digests. obj_xref.h contains lookup tables for querying this
+information in both directions.
+
+Dependency graph:
+
+ objects.txt
+ |
+ V
+ [objects.pl] <--+
+ / \ |
+ V V |
+ obj_mac.h obj_mac.num obj_xref.txt
+ | \ /
+ V V V
+ [obj_dat.pl] [obj_xref.pl]
+ | |
+ V V
+ obj_dat.h obj_xref.h
diff --git a/src/crypto/obj/obj.c b/src/crypto/obj/obj.c
new file mode 100644
index 0000000..b04321b
--- /dev/null
+++ b/src/crypto/obj/obj.c
@@ -0,0 +1,673 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/obj.h>
+
+#include <limits.h>
+#include <string.h>
+
+#include <openssl/asn1.h>
+#include <openssl/buf.h>
+#include <openssl/bytestring.h>
+#include <openssl/err.h>
+#include <openssl/lhash.h>
+#include <openssl/mem.h>
+#include <openssl/thread.h>
+
+#include "obj_dat.h"
+
+/* These globals are protected by CRYPTO_LOCK_OBJ. */
+static LHASH_OF(ASN1_OBJECT) *global_added_by_data = NULL;
+static LHASH_OF(ASN1_OBJECT) *global_added_by_nid = NULL;
+static LHASH_OF(ASN1_OBJECT) *global_added_by_short_name = NULL;
+static LHASH_OF(ASN1_OBJECT) *global_added_by_long_name = NULL;
+
+static unsigned global_next_nid = NUM_NID;
+
+static int obj_next_nid(void) {
+ int ret;
+
+ CRYPTO_w_lock(CRYPTO_LOCK_OBJ);
+ ret = global_next_nid++;
+ CRYPTO_w_unlock(CRYPTO_LOCK_OBJ);
+
+ return ret;
+}
+
+ASN1_OBJECT *OBJ_dup(const ASN1_OBJECT *o) {
+ ASN1_OBJECT *r;
+ unsigned char *data = NULL;
+ char *sn = NULL, *ln = NULL;
+
+ if (o == NULL) {
+ return NULL;
+ }
+
+ if (!(o->flags & ASN1_OBJECT_FLAG_DYNAMIC)) {
+ /* TODO(fork): this is a little dangerous. */
+ return (ASN1_OBJECT *)o;
+ }
+
+ r = ASN1_OBJECT_new();
+ if (r == NULL) {
+ OPENSSL_PUT_ERROR(OBJ, OBJ_dup, ERR_R_ASN1_LIB);
+ return NULL;
+ }
+ r->ln = r->sn = NULL;
+
+ data = OPENSSL_malloc(o->length);
+ if (data == NULL) {
+ goto err;
+ }
+ if (o->data != NULL) {
+ memcpy(data, o->data, o->length);
+ }
+
+ /* once data is attached to an object, it remains const */
+ r->data = data;
+ r->length = o->length;
+ r->nid = o->nid;
+
+ if (o->ln != NULL) {
+ ln = OPENSSL_strdup(o->ln);
+ if (ln == NULL) {
+ goto err;
+ }
+ }
+
+ if (o->sn != NULL) {
+ sn = OPENSSL_strdup(o->sn);
+ if (sn) {
+ goto err;
+ }
+ }
+
+ r->sn = sn;
+ r->ln = ln;
+
+ r->flags =
+ o->flags | (ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS |
+ ASN1_OBJECT_FLAG_DYNAMIC_DATA);
+ return r;
+
+err:
+ OPENSSL_PUT_ERROR(OBJ, OBJ_dup, ERR_R_MALLOC_FAILURE);
+ if (ln != NULL) {
+ OPENSSL_free(ln);
+ }
+ if (sn != NULL) {
+ OPENSSL_free(sn);
+ }
+ if (data != NULL) {
+ OPENSSL_free(data);
+ }
+ OPENSSL_free(r);
+ return NULL;
+}
+
+int OBJ_cmp(const ASN1_OBJECT *a, const ASN1_OBJECT *b) {
+ int ret;
+
+ ret = a->length - b->length;
+ if (ret) {
+ return ret;
+ }
+ return memcmp(a->data, b->data, a->length);
+}
+
+/* nids_cmp is called to search the kNIDsInOIDOrder array. The |key| argument
+ * is an |ASN1_OBJECT|* that we're looking for and |element| is a pointer to an
+ * unsigned int in the array. */
+static int obj_cmp(const void *key, const void *element) {
+ int j;
+ unsigned nid = *((unsigned*) element);
+ const ASN1_OBJECT *a = key;
+ const ASN1_OBJECT *b = &kObjects[nid];
+
+ j = a->length - b->length;
+ if (j) {
+ return j;
+ }
+ return memcmp(a->data, b->data, a->length);
+}
+
+int OBJ_obj2nid(const ASN1_OBJECT *obj) {
+ const unsigned int *nid_ptr;
+
+ if (obj == NULL) {
+ return NID_undef;
+ }
+
+ if (obj->nid != 0) {
+ return obj->nid;
+ }
+
+ CRYPTO_r_lock(CRYPTO_LOCK_OBJ);
+ if (global_added_by_data != NULL) {
+ ASN1_OBJECT *match;
+
+ match = lh_ASN1_OBJECT_retrieve(global_added_by_data, obj);
+ if (match != NULL) {
+ CRYPTO_r_unlock(CRYPTO_LOCK_OBJ);
+ return match->nid;
+ }
+ }
+ CRYPTO_r_unlock(CRYPTO_LOCK_OBJ);
+
+ nid_ptr = bsearch(obj, kNIDsInOIDOrder, NUM_OBJ, sizeof(unsigned), obj_cmp);
+ if (nid_ptr == NULL) {
+ return NID_undef;
+ }
+
+ return kObjects[*nid_ptr].nid;
+}
+
+int OBJ_cbs2nid(const CBS *cbs) {
+ ASN1_OBJECT obj;
+ memset(&obj, 0, sizeof(obj));
+ obj.data = CBS_data(cbs);
+ obj.length = CBS_len(cbs);
+
+ return OBJ_obj2nid(&obj);
+}
+
+/* short_name_cmp is called to search the kNIDsInShortNameOrder array. The
+ * |key| argument is name that we're looking for and |element| is a pointer to
+ * an unsigned int in the array. */
+static int short_name_cmp(const void *key, const void *element) {
+ const char *name = (const char *) key;
+ unsigned nid = *((unsigned*) element);
+
+ return strcmp(name, kObjects[nid].sn);
+}
+
+int OBJ_sn2nid(const char *short_name) {
+ const unsigned int *nid_ptr;
+
+ CRYPTO_r_lock(CRYPTO_LOCK_OBJ);
+ if (global_added_by_short_name != NULL) {
+ ASN1_OBJECT *match, template;
+
+ template.sn = short_name;
+ match = lh_ASN1_OBJECT_retrieve(global_added_by_short_name, &template);
+ if (match != NULL) {
+ CRYPTO_r_unlock(CRYPTO_LOCK_OBJ);
+ return match->nid;
+ }
+ }
+ CRYPTO_r_unlock(CRYPTO_LOCK_OBJ);
+
+ nid_ptr = bsearch(short_name, kNIDsInShortNameOrder, NUM_SN, sizeof(unsigned), short_name_cmp);
+ if (nid_ptr == NULL) {
+ return NID_undef;
+ }
+
+ return kObjects[*nid_ptr].nid;
+}
+
+/* long_name_cmp is called to search the kNIDsInLongNameOrder array. The
+ * |key| argument is name that we're looking for and |element| is a pointer to
+ * an unsigned int in the array. */
+static int long_name_cmp(const void *key, const void *element) {
+ const char *name = (const char *) key;
+ unsigned nid = *((unsigned*) element);
+
+ return strcmp(name, kObjects[nid].ln);
+}
+
+int OBJ_ln2nid(const char *long_name) {
+ const unsigned int *nid_ptr;
+
+ CRYPTO_r_lock(CRYPTO_LOCK_OBJ);
+ if (global_added_by_long_name != NULL) {
+ ASN1_OBJECT *match, template;
+
+ template.ln = long_name;
+ match = lh_ASN1_OBJECT_retrieve(global_added_by_long_name, &template);
+ if (match != NULL) {
+ CRYPTO_r_unlock(CRYPTO_LOCK_OBJ);
+ return match->nid;
+ }
+ }
+ CRYPTO_r_unlock(CRYPTO_LOCK_OBJ);
+
+ nid_ptr = bsearch(long_name, kNIDsInLongNameOrder, NUM_LN, sizeof(unsigned), long_name_cmp);
+ if (nid_ptr == NULL) {
+ return NID_undef;
+ }
+
+ return kObjects[*nid_ptr].nid;
+}
+
+int OBJ_txt2nid(const char *s) {
+ ASN1_OBJECT *obj;
+ int nid;
+
+ obj = OBJ_txt2obj(s, 0 /* search names */);
+ nid = OBJ_obj2nid(obj);
+ ASN1_OBJECT_free(obj);
+ return nid;
+}
+
+OPENSSL_EXPORT int OBJ_nid2cbb(CBB *out, int nid) {
+ const ASN1_OBJECT *obj = OBJ_nid2obj(nid);
+ CBB oid;
+
+ if (obj == NULL ||
+ !CBB_add_asn1(out, &oid, CBS_ASN1_OBJECT) ||
+ !CBB_add_bytes(&oid, obj->data, obj->length) ||
+ !CBB_flush(out)) {
+ return 0;
+ }
+
+ return 1;
+}
+
+const ASN1_OBJECT *OBJ_nid2obj(int nid) {
+ if (nid >= 0 && nid < NUM_NID) {
+ if (nid != NID_undef && kObjects[nid].nid == NID_undef) {
+ goto err;
+ }
+ return &kObjects[nid];
+ }
+
+ CRYPTO_r_lock(CRYPTO_LOCK_OBJ);
+ if (global_added_by_nid != NULL) {
+ ASN1_OBJECT *match, template;
+
+ template.nid = nid;
+ match = lh_ASN1_OBJECT_retrieve(global_added_by_nid, &template);
+ if (match != NULL) {
+ CRYPTO_r_unlock(CRYPTO_LOCK_OBJ);
+ return match;
+ }
+ }
+ CRYPTO_r_unlock(CRYPTO_LOCK_OBJ);
+
+err:
+ OPENSSL_PUT_ERROR(OBJ, OBJ_nid2obj, OBJ_R_UNKNOWN_NID);
+ return NULL;
+}
+
+const char *OBJ_nid2sn(int nid) {
+ const ASN1_OBJECT *obj = OBJ_nid2obj(nid);
+ if (obj == NULL) {
+ return NULL;
+ }
+
+ return obj->sn;
+}
+
+const char *OBJ_nid2ln(int nid) {
+ const ASN1_OBJECT *obj = OBJ_nid2obj(nid);
+ if (obj == NULL) {
+ return NULL;
+ }
+
+ return obj->ln;
+}
+
+ASN1_OBJECT *OBJ_txt2obj(const char *s, int dont_search_names) {
+ int nid = NID_undef;
+ ASN1_OBJECT *op = NULL;
+ unsigned char *buf;
+ unsigned char *p;
+ const unsigned char *bufp;
+ int contents_len, total_len;
+
+ if (!dont_search_names) {
+ nid = OBJ_sn2nid(s);
+ if (nid == NID_undef) {
+ nid = OBJ_ln2nid(s);
+ }
+
+ if (nid != NID_undef) {
+ return (ASN1_OBJECT*) OBJ_nid2obj(nid);
+ }
+ }
+
+ /* Work out size of content octets */
+ contents_len = a2d_ASN1_OBJECT(NULL, 0, s, -1);
+ if (contents_len <= 0) {
+ return NULL;
+ }
+ /* Work out total size */
+ total_len = ASN1_object_size(0, contents_len, V_ASN1_OBJECT);
+
+ buf = OPENSSL_malloc(total_len);
+ if (buf == NULL) {
+ OPENSSL_PUT_ERROR(OBJ, OBJ_txt2obj, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ p = buf;
+ /* Write out tag+length */
+ ASN1_put_object(&p, 0, contents_len, V_ASN1_OBJECT, V_ASN1_UNIVERSAL);
+ /* Write out contents */
+ a2d_ASN1_OBJECT(p, contents_len, s, -1);
+
+ bufp = buf;
+ op = d2i_ASN1_OBJECT(NULL, &bufp, total_len);
+ OPENSSL_free(buf);
+
+ return op;
+}
+
+int OBJ_obj2txt(char *out, int out_len, const ASN1_OBJECT *obj, int dont_return_name) {
+ int i, n = 0, len, nid, first, use_bn;
+ BIGNUM *bl;
+ unsigned long l;
+ const unsigned char *p;
+ char tbuf[DECIMAL_SIZE(i) + DECIMAL_SIZE(l) + 2];
+
+ if (out && out_len > 0) {
+ out[0] = 0;
+ }
+
+ if (obj == NULL || obj->data == NULL) {
+ return 0;
+ }
+
+ if (!dont_return_name && (nid = OBJ_obj2nid(obj)) != NID_undef) {
+ const char *s;
+ s = OBJ_nid2ln(nid);
+ if (s == NULL) {
+ s = OBJ_nid2sn(nid);
+ }
+ if (s) {
+ if (out) {
+ BUF_strlcpy(out, s, out_len);
+ }
+ return strlen(s);
+ }
+ }
+
+ len = obj->length;
+ p = obj->data;
+
+ first = 1;
+ bl = NULL;
+
+ while (len > 0) {
+ l = 0;
+ use_bn = 0;
+ for (;;) {
+ unsigned char c = *p++;
+ len--;
+ if (len == 0 && (c & 0x80)) {
+ goto err;
+ }
+ if (use_bn) {
+ if (!BN_add_word(bl, c & 0x7f)) {
+ goto err;
+ }
+ } else {
+ l |= c & 0x7f;
+ }
+ if (!(c & 0x80)) {
+ break;
+ }
+ if (!use_bn && (l > (ULONG_MAX >> 7L))) {
+ if (!bl && !(bl = BN_new())) {
+ goto err;
+ }
+ if (!BN_set_word(bl, l)) {
+ goto err;
+ }
+ use_bn = 1;
+ }
+ if (use_bn) {
+ if (!BN_lshift(bl, bl, 7)) {
+ goto err;
+ }
+ } else {
+ l <<= 7L;
+ }
+ }
+
+ if (first) {
+ first = 0;
+ if (l >= 80) {
+ i = 2;
+ if (use_bn) {
+ if (!BN_sub_word(bl, 80)) {
+ goto err;
+ }
+ } else {
+ l -= 80;
+ }
+ } else {
+ i = (int)(l / 40);
+ l -= (long)(i * 40);
+ }
+ if (out && out_len > 1) {
+ *out++ = i + '0';
+ *out = '0';
+ out_len--;
+ }
+ n++;
+ }
+
+ if (use_bn) {
+ char *bndec;
+ bndec = BN_bn2dec(bl);
+ if (!bndec) {
+ goto err;
+ }
+ i = strlen(bndec);
+ if (out) {
+ if (out_len > 1) {
+ *out++ = '.';
+ *out = 0;
+ out_len--;
+ }
+ BUF_strlcpy(out, bndec, out_len);
+ if (i > out_len) {
+ out += out_len;
+ out_len = 0;
+ } else {
+ out += i;
+ out_len -= i;
+ }
+ }
+ n++;
+ n += i;
+ OPENSSL_free(bndec);
+ } else {
+ BIO_snprintf(tbuf, sizeof(tbuf), ".%lu", l);
+ i = strlen(tbuf);
+ if (out && out_len > 0) {
+ BUF_strlcpy(out, tbuf, out_len);
+ if (i > out_len) {
+ out += out_len;
+ out_len = 0;
+ } else {
+ out += i;
+ out_len -= i;
+ }
+ }
+ n += i;
+ }
+ }
+
+ if (bl) {
+ BN_free(bl);
+ }
+ return n;
+
+err:
+ if (bl) {
+ BN_free(bl);
+ }
+ return -1;
+}
+
+static uint32_t hash_nid(const ASN1_OBJECT *obj) {
+ return obj->nid;
+}
+
+static int cmp_nid(const ASN1_OBJECT *a, const ASN1_OBJECT *b) {
+ return a->nid - b->nid;
+}
+
+static uint32_t hash_data(const ASN1_OBJECT *obj) {
+ return OPENSSL_hash32(obj->data, obj->length);
+}
+
+static int cmp_data(const ASN1_OBJECT *a, const ASN1_OBJECT *b) {
+ int i = a->length - b->length;
+ if (i) {
+ return i;
+ }
+ return memcmp(a->data, b->data, a->length);
+}
+
+static uint32_t hash_short_name(const ASN1_OBJECT *obj) {
+ return lh_strhash(obj->sn);
+}
+
+static int cmp_short_name(const ASN1_OBJECT *a, const ASN1_OBJECT *b) {
+ return strcmp(a->sn, b->sn);
+}
+
+static uint32_t hash_long_name(const ASN1_OBJECT *obj) {
+ return lh_strhash(obj->ln);
+}
+
+static int cmp_long_name(const ASN1_OBJECT *a, const ASN1_OBJECT *b) {
+ return strcmp(a->ln, b->ln);
+}
+
+/* obj_add_object inserts |obj| into the various global hashes for run-time
+ * added objects. It returns one on success or zero otherwise. */
+static int obj_add_object(ASN1_OBJECT *obj) {
+ int ok;
+ ASN1_OBJECT *old_object;
+
+ obj->flags &= ~(ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS |
+ ASN1_OBJECT_FLAG_DYNAMIC_DATA);
+
+ CRYPTO_w_lock(CRYPTO_LOCK_OBJ);
+ if (global_added_by_nid == NULL) {
+ global_added_by_nid = lh_ASN1_OBJECT_new(hash_nid, cmp_nid);
+ global_added_by_data = lh_ASN1_OBJECT_new(hash_data, cmp_data);
+ global_added_by_short_name = lh_ASN1_OBJECT_new(hash_short_name, cmp_short_name);
+ global_added_by_long_name = lh_ASN1_OBJECT_new(hash_long_name, cmp_long_name);
+ }
+
+ /* We don't pay attention to |old_object| (which contains any previous object
+ * that was evicted from the hashes) because we don't have a reference count
+ * on ASN1_OBJECT values. Also, we should never have duplicates nids and so
+ * should always have objects in |global_added_by_nid|. */
+
+ ok = lh_ASN1_OBJECT_insert(global_added_by_nid, &old_object, obj);
+ if (obj->length != 0 && obj->data != NULL) {
+ ok &= lh_ASN1_OBJECT_insert(global_added_by_data, &old_object, obj);
+ }
+ if (obj->sn != NULL) {
+ ok &= lh_ASN1_OBJECT_insert(global_added_by_short_name, &old_object, obj);
+ }
+ if (obj->ln != NULL) {
+ ok &= lh_ASN1_OBJECT_insert(global_added_by_long_name, &old_object, obj);
+ }
+ CRYPTO_w_unlock(CRYPTO_LOCK_OBJ);
+
+ return ok;
+}
+
+int OBJ_create(const char *oid, const char *short_name, const char *long_name) {
+ int ret = NID_undef;
+ ASN1_OBJECT *op = NULL;
+ unsigned char *buf = NULL;
+ int len;
+
+ len = a2d_ASN1_OBJECT(NULL, 0, oid, -1);
+ if (len <= 0) {
+ goto err;
+ }
+
+ buf = OPENSSL_malloc(len);
+ if (buf == NULL) {
+ OPENSSL_PUT_ERROR(OBJ, OBJ_create, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ len = a2d_ASN1_OBJECT(buf, len, oid, -1);
+ if (len == 0) {
+ goto err;
+ }
+
+ op = (ASN1_OBJECT *)ASN1_OBJECT_create(obj_next_nid(), buf, len, short_name,
+ long_name);
+ if (op == NULL) {
+ goto err;
+ }
+
+ if (obj_add_object(op)) {
+ ret = op->nid;
+ }
+ op = NULL;
+
+err:
+ if (op != NULL) {
+ ASN1_OBJECT_free(op);
+ }
+ if (buf != NULL) {
+ OPENSSL_free(buf);
+ }
+
+ return ret;
+}
diff --git a/src/crypto/obj/obj_dat.h b/src/crypto/obj/obj_dat.h
new file mode 100644
index 0000000..2584d87
--- /dev/null
+++ b/src/crypto/obj/obj_dat.h
@@ -0,0 +1,5261 @@
+/* THIS FILE IS GENERATED FROM objects.h by obj_dat.pl via the
+ * following command:
+ * perl obj_dat.pl ../../include/openssl/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 948
+#define NUM_SN 941
+#define NUM_LN 941
+#define NUM_OBJ 883
+
+static const unsigned char lvalues[6182]={
+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 */
+0x2A,0x86,0x48,0xCE,0x3E,0x02,0x01, /* [5973] OBJ_dhpublicnumber */
+0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x01,/* [5980] OBJ_brainpoolP160r1 */
+0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x02,/* [5989] OBJ_brainpoolP160t1 */
+0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x03,/* [5998] OBJ_brainpoolP192r1 */
+0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x04,/* [6007] OBJ_brainpoolP192t1 */
+0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x05,/* [6016] OBJ_brainpoolP224r1 */
+0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x06,/* [6025] OBJ_brainpoolP224t1 */
+0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x07,/* [6034] OBJ_brainpoolP256r1 */
+0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x08,/* [6043] OBJ_brainpoolP256t1 */
+0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x09,/* [6052] OBJ_brainpoolP320r1 */
+0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x0A,/* [6061] OBJ_brainpoolP320t1 */
+0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x0B,/* [6070] OBJ_brainpoolP384r1 */
+0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x0C,/* [6079] OBJ_brainpoolP384t1 */
+0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x0D,/* [6088] OBJ_brainpoolP512r1 */
+0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x0E,/* [6097] OBJ_brainpoolP512t1 */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x09,/* [6106] OBJ_pSpecified */
+0x2B,0x81,0x05,0x10,0x86,0x48,0x3F,0x00,0x02,/* [6115] OBJ_dhSinglePass_stdDH_sha1kdf_scheme */
+0x2B,0x81,0x04,0x01,0x0B,0x00, /* [6124] OBJ_dhSinglePass_stdDH_sha224kdf_scheme */
+0x2B,0x81,0x04,0x01,0x0B,0x01, /* [6130] OBJ_dhSinglePass_stdDH_sha256kdf_scheme */
+0x2B,0x81,0x04,0x01,0x0B,0x02, /* [6136] OBJ_dhSinglePass_stdDH_sha384kdf_scheme */
+0x2B,0x81,0x04,0x01,0x0B,0x03, /* [6142] OBJ_dhSinglePass_stdDH_sha512kdf_scheme */
+0x2B,0x81,0x05,0x10,0x86,0x48,0x3F,0x00,0x03,/* [6148] OBJ_dhSinglePass_cofactorDH_sha1kdf_scheme */
+0x2B,0x81,0x04,0x01,0x0E,0x00, /* [6157] OBJ_dhSinglePass_cofactorDH_sha224kdf_scheme */
+0x2B,0x81,0x04,0x01,0x0E,0x01, /* [6163] OBJ_dhSinglePass_cofactorDH_sha256kdf_scheme */
+0x2B,0x81,0x04,0x01,0x0E,0x02, /* [6169] OBJ_dhSinglePass_cofactorDH_sha384kdf_scheme */
+0x2B,0x81,0x04,0x01,0x0E,0x03, /* [6175] OBJ_dhSinglePass_cofactorDH_sha512kdf_scheme */
+};
+
+static const ASN1_OBJECT kObjects[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 Distrubution 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},
+{"dsa_with_SHA224","dsa_with_SHA224",NID_dsa_with_SHA224,9,
+ &(lvalues[5337]),0},
+{"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},
+{"dhpublicnumber","X9.42 DH",NID_dhpublicnumber,7,&(lvalues[5973]),0},
+{"brainpoolP160r1","brainpoolP160r1",NID_brainpoolP160r1,9,
+ &(lvalues[5980]),0},
+{"brainpoolP160t1","brainpoolP160t1",NID_brainpoolP160t1,9,
+ &(lvalues[5989]),0},
+{"brainpoolP192r1","brainpoolP192r1",NID_brainpoolP192r1,9,
+ &(lvalues[5998]),0},
+{"brainpoolP192t1","brainpoolP192t1",NID_brainpoolP192t1,9,
+ &(lvalues[6007]),0},
+{"brainpoolP224r1","brainpoolP224r1",NID_brainpoolP224r1,9,
+ &(lvalues[6016]),0},
+{"brainpoolP224t1","brainpoolP224t1",NID_brainpoolP224t1,9,
+ &(lvalues[6025]),0},
+{"brainpoolP256r1","brainpoolP256r1",NID_brainpoolP256r1,9,
+ &(lvalues[6034]),0},
+{"brainpoolP256t1","brainpoolP256t1",NID_brainpoolP256t1,9,
+ &(lvalues[6043]),0},
+{"brainpoolP320r1","brainpoolP320r1",NID_brainpoolP320r1,9,
+ &(lvalues[6052]),0},
+{"brainpoolP320t1","brainpoolP320t1",NID_brainpoolP320t1,9,
+ &(lvalues[6061]),0},
+{"brainpoolP384r1","brainpoolP384r1",NID_brainpoolP384r1,9,
+ &(lvalues[6070]),0},
+{"brainpoolP384t1","brainpoolP384t1",NID_brainpoolP384t1,9,
+ &(lvalues[6079]),0},
+{"brainpoolP512r1","brainpoolP512r1",NID_brainpoolP512r1,9,
+ &(lvalues[6088]),0},
+{"brainpoolP512t1","brainpoolP512t1",NID_brainpoolP512t1,9,
+ &(lvalues[6097]),0},
+{"PSPECIFIED","pSpecified",NID_pSpecified,9,&(lvalues[6106]),0},
+{"dhSinglePass-stdDH-sha1kdf-scheme",
+ "dhSinglePass-stdDH-sha1kdf-scheme",
+ NID_dhSinglePass_stdDH_sha1kdf_scheme,9,&(lvalues[6115]),0},
+{"dhSinglePass-stdDH-sha224kdf-scheme",
+ "dhSinglePass-stdDH-sha224kdf-scheme",
+ NID_dhSinglePass_stdDH_sha224kdf_scheme,6,&(lvalues[6124]),0},
+{"dhSinglePass-stdDH-sha256kdf-scheme",
+ "dhSinglePass-stdDH-sha256kdf-scheme",
+ NID_dhSinglePass_stdDH_sha256kdf_scheme,6,&(lvalues[6130]),0},
+{"dhSinglePass-stdDH-sha384kdf-scheme",
+ "dhSinglePass-stdDH-sha384kdf-scheme",
+ NID_dhSinglePass_stdDH_sha384kdf_scheme,6,&(lvalues[6136]),0},
+{"dhSinglePass-stdDH-sha512kdf-scheme",
+ "dhSinglePass-stdDH-sha512kdf-scheme",
+ NID_dhSinglePass_stdDH_sha512kdf_scheme,6,&(lvalues[6142]),0},
+{"dhSinglePass-cofactorDH-sha1kdf-scheme",
+ "dhSinglePass-cofactorDH-sha1kdf-scheme",
+ NID_dhSinglePass_cofactorDH_sha1kdf_scheme,9,&(lvalues[6148]),0},
+{"dhSinglePass-cofactorDH-sha224kdf-scheme",
+ "dhSinglePass-cofactorDH-sha224kdf-scheme",
+ NID_dhSinglePass_cofactorDH_sha224kdf_scheme,6,&(lvalues[6157]),0},
+{"dhSinglePass-cofactorDH-sha256kdf-scheme",
+ "dhSinglePass-cofactorDH-sha256kdf-scheme",
+ NID_dhSinglePass_cofactorDH_sha256kdf_scheme,6,&(lvalues[6163]),0},
+{"dhSinglePass-cofactorDH-sha384kdf-scheme",
+ "dhSinglePass-cofactorDH-sha384kdf-scheme",
+ NID_dhSinglePass_cofactorDH_sha384kdf_scheme,6,&(lvalues[6169]),0},
+{"dhSinglePass-cofactorDH-sha512kdf-scheme",
+ "dhSinglePass-cofactorDH-sha512kdf-scheme",
+ NID_dhSinglePass_cofactorDH_sha512kdf_scheme,6,&(lvalues[6175]),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},
+};
+
+static const unsigned int kNIDsInShortNameOrder[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" */
+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" */
+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" */
+99, /* "GN" */
+855, /* "HMAC" */
+780, /* "HMAC-MD5" */
+781, /* "HMAC-SHA1" */
+381, /* "IANA" */
+34, /* "IDEA-CBC" */
+35, /* "IDEA-CFB" */
+36, /* "IDEA-ECB" */
+46, /* "IDEA-OFB" */
+181, /* "ISO" */
+183, /* "ISO-US" */
+645, /* "ITU-T" */
+646, /* "JOINT-ISO-ITU-T" */
+773, /* "KISA" */
+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" */
+935, /* "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" */
+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" */
+673, /* "SHA384" */
+674, /* "SHA512" */
+188, /* "SMIME" */
+167, /* "SMIME-CAPS" */
+100, /* "SN" */
+16, /* "ST" */
+143, /* "SXNetID" */
+458, /* "UID" */
+ 0, /* "UNDEF" */
+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, /* "brainpoolP160r1" */
+922, /* "brainpoolP160t1" */
+923, /* "brainpoolP192r1" */
+924, /* "brainpoolP192t1" */
+925, /* "brainpoolP224r1" */
+926, /* "brainpoolP224t1" */
+927, /* "brainpoolP256r1" */
+928, /* "brainpoolP256t1" */
+929, /* "brainpoolP320r1" */
+930, /* "brainpoolP320t1" */
+931, /* "brainpoolP384r1" */
+932, /* "brainpoolP384t1" */
+933, /* "brainpoolP512r1" */
+934, /* "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" */
+500, /* "dITRedirect" */
+451, /* "dNSDomain" */
+495, /* "dSAQuality" */
+434, /* "data" */
+390, /* "dcobject" */
+140, /* "deltaCRL" */
+891, /* "deltaRevocationList" */
+107, /* "description" */
+871, /* "destinationIndicator" */
+947, /* "dh-cofactor-kdf" */
+946, /* "dh-std-kdf" */
+28, /* "dhKeyAgreement" */
+941, /* "dhSinglePass-cofactorDH-sha1kdf-scheme" */
+942, /* "dhSinglePass-cofactorDH-sha224kdf-scheme" */
+943, /* "dhSinglePass-cofactorDH-sha256kdf-scheme" */
+944, /* "dhSinglePass-cofactorDH-sha384kdf-scheme" */
+945, /* "dhSinglePass-cofactorDH-sha512kdf-scheme" */
+936, /* "dhSinglePass-stdDH-sha1kdf-scheme" */
+937, /* "dhSinglePass-stdDH-sha224kdf-scheme" */
+938, /* "dhSinglePass-stdDH-sha256kdf-scheme" */
+939, /* "dhSinglePass-stdDH-sha384kdf-scheme" */
+940, /* "dhSinglePass-stdDH-sha512kdf-scheme" */
+920, /* "dhpublicnumber" */
+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" */
+802, /* "dsa_with_SHA224" */
+803, /* "dsa_with_SHA256" */
+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" */
+814, /* "gost89-cnt" */
+812, /* "gost94" */
+850, /* "gost94cc" */
+797, /* "hmacWithMD5" */
+163, /* "hmacWithSHA1" */
+798, /* "hmacWithSHA224" */
+799, /* "hmacWithSHA256" */
+800, /* "hmacWithSHA384" */
+801, /* "hmacWithSHA512" */
+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" */
+787, /* "id-ct-asciiTextWithCRLF" */
+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" */
+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" */
+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" */
+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" */
+676, /* "identified-organization" */
+461, /* "info" */
+748, /* "inhibitAnyPolicy" */
+101, /* "initials" */
+647, /* "international-organizations" */
+869, /* "internationaliSDNNumber" */
+142, /* "invalidityDate" */
+294, /* "ipsecEndSystem" */
+295, /* "ipsecTunnel" */
+296, /* "ipsecUser" */
+86, /* "issuerAltName" */
+770, /* "issuingDistributionPoint" */
+492, /* "janetMailbox" */
+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" */
+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" */
+ 6, /* "rsaEncryption" */
+644, /* "rsaOAEPEncryptionSET" */
+377, /* "rsaSignature" */
+ 1, /* "rsadsi" */
+482, /* "sOARecord" */
+155, /* "safeContentsBag" */
+291, /* "sbgp-autonomousSysNum" */
+290, /* "sbgp-ipAddrBlock" */
+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" */
+52, /* "signingTime" */
+454, /* "simpleSecurityObject" */
+496, /* "singleLevelQuality" */
+387, /* "snmpv2" */
+660, /* "street" */
+85, /* "subjectAltName" */
+769, /* "subjectDirectoryAttributes" */
+398, /* "subjectInfoAccess" */
+82, /* "subjectKeyIdentifier" */
+498, /* "subtreeMaximumQuality" */
+497, /* "subtreeMinimumQuality" */
+890, /* "supportedAlgorithms" */
+874, /* "supportedApplicationContext" */
+402, /* "targetInformation" */
+864, /* "telephoneNumber" */
+866, /* "teletexTerminalIdentifier" */
+865, /* "telexNumber" */
+459, /* "textEncodedORAddress" */
+293, /* "textNotice" */
+133, /* "timeStamping" */
+106, /* "title" */
+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 kNIDsInLongNameOrder[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" */
+365, /* "Basic OCSP Response" */
+285, /* "Biometric Info" */
+179, /* "CA Issuers" */
+785, /* "CA Repository" */
+131, /* "Code Signing" */
+783, /* "Diffie-Hellman based MAC" */
+382, /* "Directory" */
+392, /* "Domain" */
+132, /* "E-mail Protection" */
+389, /* "Enterprises" */
+384, /* "Experimental" */
+372, /* "Extended OCSP Status" */
+172, /* "Extension Request" */
+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" */
+811, /* "GOST R 34.10-2001" */
+817, /* "GOST R 34.10-2001 DH" */
+812, /* "GOST R 34.10-94" */
+818, /* "GOST R 34.10-94 DH" */
+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" */
+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" */
+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" */
+ 1, /* "RSA Data Security, Inc." */
+ 2, /* "RSA Data Security, Inc. PKCS" */
+188, /* "S/MIME" */
+167, /* "S/MIME Capabilities" */
+387, /* "SNMPv2" */
+512, /* "Secure Electronic Transactions" */
+386, /* "Security" */
+394, /* "Selected Attribute Types" */
+143, /* "Strong Extranet ID" */
+398, /* "Subject Information Access" */
+130, /* "TLS Web Client Authentication" */
+129, /* "TLS Web Server Authentication" */
+133, /* "Time Stamping" */
+375, /* "Trust Root" */
+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 Distrubution 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" */
+920, /* "X9.42 DH" */
+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" */
+882, /* "authorityRevocationList" */
+91, /* "bf-cbc" */
+93, /* "bf-cfb" */
+92, /* "bf-ecb" */
+94, /* "bf-ofb" */
+921, /* "brainpoolP160r1" */
+922, /* "brainpoolP160t1" */
+923, /* "brainpoolP192r1" */
+924, /* "brainpoolP192t1" */
+925, /* "brainpoolP224r1" */
+926, /* "brainpoolP224t1" */
+927, /* "brainpoolP256r1" */
+928, /* "brainpoolP256t1" */
+929, /* "brainpoolP320r1" */
+930, /* "brainpoolP320t1" */
+931, /* "brainpoolP384r1" */
+932, /* "brainpoolP384t1" */
+933, /* "brainpoolP512r1" */
+934, /* "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" */
+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" */
+947, /* "dh-cofactor-kdf" */
+946, /* "dh-std-kdf" */
+28, /* "dhKeyAgreement" */
+941, /* "dhSinglePass-cofactorDH-sha1kdf-scheme" */
+942, /* "dhSinglePass-cofactorDH-sha224kdf-scheme" */
+943, /* "dhSinglePass-cofactorDH-sha256kdf-scheme" */
+944, /* "dhSinglePass-cofactorDH-sha384kdf-scheme" */
+945, /* "dhSinglePass-cofactorDH-sha512kdf-scheme" */
+936, /* "dhSinglePass-stdDH-sha1kdf-scheme" */
+937, /* "dhSinglePass-stdDH-sha224kdf-scheme" */
+938, /* "dhSinglePass-stdDH-sha256kdf-scheme" */
+939, /* "dhSinglePass-stdDH-sha384kdf-scheme" */
+940, /* "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" */
+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" */
+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" */
+814, /* "gost89-cnt" */
+855, /* "hmac" */
+780, /* "hmac-md5" */
+781, /* "hmac-sha1" */
+797, /* "hmacWithMD5" */
+163, /* "hmacWithSHA1" */
+798, /* "hmacWithSHA224" */
+799, /* "hmacWithSHA256" */
+800, /* "hmacWithSHA384" */
+801, /* "hmacWithSHA512" */
+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" */
+787, /* "id-ct-asciiTextWithCRLF" */
+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" */
+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" */
+34, /* "idea-cbc" */
+35, /* "idea-cfb" */
+36, /* "idea-ecb" */
+46, /* "idea-ofb" */
+676, /* "identified-organization" */
+461, /* "info" */
+101, /* "initials" */
+869, /* "internationaliSDNNumber" */
+749, /* "ipsec3" */
+750, /* "ipsec4" */
+181, /* "iso" */
+623, /* "issuer capabilities" */
+645, /* "itu-t" */
+492, /* "janetMailbox" */
+646, /* "joint-iso-itu-t" */
+150, /* "keyBag" */
+773, /* "kisa" */
+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" */
+475, /* "otherMailbox" */
+876, /* "owner" */
+935, /* "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" */
+290, /* "sbgp-ipAddrBlock" */
+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" */
+673, /* "sha384" */
+669, /* "sha384WithRSAEncryption" */
+674, /* "sha512" */
+670, /* "sha512WithRSAEncryption" */
+42, /* "shaWithRSAEncryption" */
+52, /* "signingTime" */
+454, /* "simpleSecurityObject" */
+496, /* "singleLevelQuality" */
+16, /* "stateOrProvinceName" */
+660, /* "streetAddress" */
+498, /* "subtreeMaximumQuality" */
+497, /* "subtreeMinimumQuality" */
+890, /* "supportedAlgorithms" */
+874, /* "supportedApplicationContext" */
+100, /* "surname" */
+864, /* "telephoneNumber" */
+866, /* "teletexTerminalIdentifier" */
+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 kNIDsInOIDOrder[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 */
+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 */
+183, /* OBJ_ISO_US 1 2 840 */
+381, /* OBJ_iana 1 3 6 1 */
+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 */
+805, /* OBJ_cryptopro 1 2 643 2 2 */
+806, /* OBJ_cryptocom 1 2 643 2 9 */
+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 */
+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 */
+937, /* OBJ_dhSinglePass_stdDH_sha224kdf_scheme 1 3 132 1 11 0 */
+938, /* OBJ_dhSinglePass_stdDH_sha256kdf_scheme 1 3 132 1 11 1 */
+939, /* OBJ_dhSinglePass_stdDH_sha384kdf_scheme 1 3 132 1 11 2 */
+940, /* OBJ_dhSinglePass_stdDH_sha512kdf_scheme 1 3 132 1 11 3 */
+942, /* OBJ_dhSinglePass_cofactorDH_sha224kdf_scheme 1 3 132 1 14 0 */
+943, /* OBJ_dhSinglePass_cofactorDH_sha256kdf_scheme 1 3 132 1 14 1 */
+944, /* OBJ_dhSinglePass_cofactorDH_sha384kdf_scheme 1 3 132 1 14 2 */
+945, /* 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 */
+920, /* OBJ_dhpublicnumber 1 2 840 10046 2 1 */
+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 */
+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 */
+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 */
+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 */
+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 */
+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 */
+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 */
+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 */
+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 */
+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 */
+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 */
+935, /* 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 */
+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 */
+921, /* OBJ_brainpoolP160r1 1 3 36 3 3 2 8 1 1 1 */
+922, /* OBJ_brainpoolP160t1 1 3 36 3 3 2 8 1 1 2 */
+923, /* OBJ_brainpoolP192r1 1 3 36 3 3 2 8 1 1 3 */
+924, /* OBJ_brainpoolP192t1 1 3 36 3 3 2 8 1 1 4 */
+925, /* OBJ_brainpoolP224r1 1 3 36 3 3 2 8 1 1 5 */
+926, /* OBJ_brainpoolP224t1 1 3 36 3 3 2 8 1 1 6 */
+927, /* OBJ_brainpoolP256r1 1 3 36 3 3 2 8 1 1 7 */
+928, /* OBJ_brainpoolP256t1 1 3 36 3 3 2 8 1 1 8 */
+929, /* OBJ_brainpoolP320r1 1 3 36 3 3 2 8 1 1 9 */
+930, /* OBJ_brainpoolP320t1 1 3 36 3 3 2 8 1 1 10 */
+931, /* OBJ_brainpoolP384r1 1 3 36 3 3 2 8 1 1 11 */
+932, /* OBJ_brainpoolP384t1 1 3 36 3 3 2 8 1 1 12 */
+933, /* OBJ_brainpoolP512r1 1 3 36 3 3 2 8 1 1 13 */
+934, /* OBJ_brainpoolP512t1 1 3 36 3 3 2 8 1 1 14 */
+936, /* OBJ_dhSinglePass_stdDH_sha1kdf_scheme 1 3 133 16 840 63 0 2 */
+941, /* 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 */
+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 */
+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 */
+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 */
+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 */
+787, /* OBJ_id_ct_asciiTextWithCRLF 1 2 840 113549 1 9 16 1 27 */
+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 */
+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 */
+};
+
diff --git a/src/crypto/obj/obj_dat.pl b/src/crypto/obj/obj_dat.pl
new file mode 100644
index 0000000..201ec72
--- /dev/null
+++ b/src/crypto/obj/obj_dat.pl
@@ -0,0 +1,309 @@
+#!/usr/bin/env perl
+
+# fixes bug in floating point emulation on sparc64 when
+# this script produces off-by-one output on sparc64
+use integer;
+
+if (scalar @ARGV != 2)
+ {
+ print "Usage: perl obj_dat.pl ../../include/openssl/obj_mac.h obj_dat.h\n";
+ exit 1;
+ }
+
+sub obj_cmp
+ {
+ local(@a,@b,$_,$r);
+
+ $A=$obj_len{$obj{$nid{$a}}};
+ $B=$obj_len{$obj{$nid{$b}}};
+
+ $r=($A-$B);
+ return($r) if $r != 0;
+
+ $A=$obj_der{$obj{$nid{$a}}};
+ $B=$obj_der{$obj{$nid{$b}}};
+
+ return($A cmp $B);
+ }
+
+sub expand_obj
+ {
+ local(*v)=@_;
+ local($k,$d);
+ local($i);
+
+ do {
+ $i=0;
+ foreach $k (keys %v)
+ {
+ if (($v{$k} =~ s/(OBJ_[^,]+),/$v{$1},/))
+ { $i++; }
+ }
+ } while($i);
+ foreach $k (keys %v)
+ {
+ @a=split(/,/,$v{$k});
+ $objn{$k}=$#a+1;
+ }
+ return(%objn);
+ }
+
+open (IN,"$ARGV[0]") || die "Can't open input file $ARGV[0]";
+open (OUT,">$ARGV[1]") || die "Can't open output file $ARGV[1]";
+
+while (<IN>)
+ {
+ next unless /^\#define\s+(\S+)\s+(.*)$/;
+ $v=$1;
+ $d=$2;
+ $d =~ s/^\"//;
+ $d =~ s/\"$//;
+ if ($v =~ /^SN_(.*)$/)
+ {
+ if(defined $snames{$d})
+ {
+ print "WARNING: Duplicate short name \"$d\"\n";
+ }
+ else
+ { $snames{$d} = "X"; }
+ $sn{$1}=$d;
+ }
+ elsif ($v =~ /^LN_(.*)$/)
+ {
+ if(defined $lnames{$d})
+ {
+ print "WARNING: Duplicate long name \"$d\"\n";
+ }
+ else
+ { $lnames{$d} = "X"; }
+ $ln{$1}=$d;
+ }
+ elsif ($v =~ /^NID_(.*)$/)
+ { $nid{$d}=$1; }
+ elsif ($v =~ /^OBJ_(.*)$/)
+ {
+ $obj{$1}=$v;
+ $objd{$v}=$d;
+ }
+ }
+close IN;
+
+%ob=&expand_obj(*objd);
+
+@a=sort { $a <=> $b } keys %nid;
+$n=$a[$#a]+1;
+
+@lvalues=();
+$lvalues=0;
+
+for ($i=0; $i<$n; $i++)
+ {
+ if (!defined($nid{$i}))
+ {
+ push(@out,"{NULL,NULL,NID_undef,0,NULL,0},\n");
+ }
+ else
+ {
+ $sn=defined($sn{$nid{$i}})?"$sn{$nid{$i}}":"NULL";
+ $ln=defined($ln{$nid{$i}})?"$ln{$nid{$i}}":"NULL";
+
+ if ($sn eq "NULL") {
+ $sn=$ln;
+ $sn{$nid{$i}} = $ln;
+ }
+
+ if ($ln eq "NULL") {
+ $ln=$sn;
+ $ln{$nid{$i}} = $sn;
+ }
+
+ $out ="{";
+ $out.="\"$sn\"";
+ $out.=","."\"$ln\"";
+ $out.=",NID_$nid{$i},";
+ if (defined($obj{$nid{$i}}) && $objd{$obj{$nid{$i}}} =~ /,/)
+ {
+ $v=$objd{$obj{$nid{$i}}};
+ $v =~ s/L//g;
+ $v =~ s/,/ /g;
+ $r=&der_it($v);
+ $z="";
+ $length=0;
+ foreach (unpack("C*",$r))
+ {
+ $z.=sprintf("0x%02X,",$_);
+ $length++;
+ }
+ $obj_der{$obj{$nid{$i}}}=$z;
+ $obj_len{$obj{$nid{$i}}}=$length;
+
+ push(@lvalues,sprintf("%-45s/* [%3d] %s */\n",
+ $z,$lvalues,$obj{$nid{$i}}));
+ $out.="$length,&(lvalues[$lvalues]),0";
+ $lvalues+=$length;
+ }
+ else
+ {
+ $out.="0,NULL,0";
+ }
+ $out.="},\n";
+ push(@out,$out);
+ }
+ }
+
+@a=grep(defined($sn{$nid{$_}}),0 .. $n);
+foreach (sort { $sn{$nid{$a}} cmp $sn{$nid{$b}} } @a)
+ {
+ push(@sn,sprintf("%2d,\t/* \"$sn{$nid{$_}}\" */\n",$_));
+ }
+
+@a=grep(defined($ln{$nid{$_}}),0 .. $n);
+foreach (sort { $ln{$nid{$a}} cmp $ln{$nid{$b}} } @a)
+ {
+ push(@ln,sprintf("%2d,\t/* \"$ln{$nid{$_}}\" */\n",$_));
+ }
+
+@a=grep(defined($obj{$nid{$_}}),0 .. $n);
+foreach (sort obj_cmp @a)
+ {
+ $m=$obj{$nid{$_}};
+ $v=$objd{$m};
+ $v =~ s/L//g;
+ $v =~ s/,/ /g;
+ push(@ob,sprintf("%2d,\t/* %-32s %s */\n",$_,$m,$v));
+ }
+
+print OUT <<'EOF';
+/* THIS FILE IS GENERATED FROM objects.h by obj_dat.pl via the
+ * following command:
+ * perl obj_dat.pl ../../include/openssl/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.] */
+
+EOF
+
+printf OUT "#define NUM_NID %d\n",$n;
+printf OUT "#define NUM_SN %d\n",$#sn+1;
+printf OUT "#define NUM_LN %d\n",$#ln+1;
+printf OUT "#define NUM_OBJ %d\n\n",$#ob+1;
+
+printf OUT "static const unsigned char lvalues[%d]={\n",$lvalues+1;
+print OUT @lvalues;
+print OUT "};\n\n";
+
+printf OUT "static const ASN1_OBJECT kObjects[NUM_NID]={\n";
+foreach (@out)
+ {
+ if (length($_) > 75)
+ {
+ $out="";
+ foreach (split(/,/))
+ {
+ $t=$out.$_.",";
+ if (length($t) > 70)
+ {
+ print OUT "$out\n";
+ $t="\t$_,";
+ }
+ $out=$t;
+ }
+ chop $out;
+ print OUT "$out";
+ }
+ else
+ { print OUT $_; }
+ }
+print OUT "};\n\n";
+
+printf OUT "static const unsigned int kNIDsInShortNameOrder[NUM_SN]={\n";
+print OUT @sn;
+print OUT "};\n\n";
+
+printf OUT "static const unsigned int kNIDsInLongNameOrder[NUM_LN]={\n";
+print OUT @ln;
+print OUT "};\n\n";
+
+printf OUT "static const unsigned int kNIDsInOIDOrder[NUM_OBJ]={\n";
+print OUT @ob;
+print OUT "};\n\n";
+
+close OUT;
+
+sub der_it
+ {
+ local($v)=@_;
+ local(@a,$i,$ret,@r);
+
+ @a=split(/\s+/,$v);
+ $ret.=pack("C*",$a[0]*40+$a[1]);
+ shift @a;
+ shift @a;
+ foreach (@a)
+ {
+ @r=();
+ $t=0;
+ while ($_ >= 128)
+ {
+ $x=$_%128;
+ $_/=128;
+ push(@r,((($t++)?0x80:0)|$x));
+ }
+ push(@r,((($t++)?0x80:0)|$_));
+ $ret.=pack("C*",reverse(@r));
+ }
+ return($ret);
+ }
diff --git a/src/crypto/obj/obj_error.c b/src/crypto/obj/obj_error.c
new file mode 100644
index 0000000..1ec9771
--- /dev/null
+++ b/src/crypto/obj/obj_error.c
@@ -0,0 +1,26 @@
+/* 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 <openssl/err.h>
+
+#include <openssl/obj.h>
+
+const ERR_STRING_DATA OBJ_error_string_data[] = {
+ {ERR_PACK(ERR_LIB_OBJ, OBJ_F_OBJ_create, 0), "OBJ_create"},
+ {ERR_PACK(ERR_LIB_OBJ, OBJ_F_OBJ_dup, 0), "OBJ_dup"},
+ {ERR_PACK(ERR_LIB_OBJ, OBJ_F_OBJ_nid2obj, 0), "OBJ_nid2obj"},
+ {ERR_PACK(ERR_LIB_OBJ, OBJ_F_OBJ_txt2obj, 0), "OBJ_txt2obj"},
+ {ERR_PACK(ERR_LIB_OBJ, 0, OBJ_R_UNKNOWN_NID), "UNKNOWN_NID"},
+ {0, NULL},
+};
diff --git a/src/crypto/obj/obj_mac.num b/src/crypto/obj/obj_mac.num
new file mode 100644
index 0000000..e143ece
--- /dev/null
+++ b/src/crypto/obj/obj_mac.num
@@ -0,0 +1,947 @@
+undef 0
+rsadsi 1
+pkcs 2
+md2 3
+md5 4
+rc4 5
+rsaEncryption 6
+md2WithRSAEncryption 7
+md5WithRSAEncryption 8
+pbeWithMD2AndDES_CBC 9
+pbeWithMD5AndDES_CBC 10
+X500 11
+X509 12
+commonName 13
+countryName 14
+localityName 15
+stateOrProvinceName 16
+organizationName 17
+organizationalUnitName 18
+rsa 19
+pkcs7 20
+pkcs7_data 21
+pkcs7_signed 22
+pkcs7_enveloped 23
+pkcs7_signedAndEnveloped 24
+pkcs7_digest 25
+pkcs7_encrypted 26
+pkcs3 27
+dhKeyAgreement 28
+des_ecb 29
+des_cfb64 30
+des_cbc 31
+des_ede_ecb 32
+des_ede3_ecb 33
+idea_cbc 34
+idea_cfb64 35
+idea_ecb 36
+rc2_cbc 37
+rc2_ecb 38
+rc2_cfb64 39
+rc2_ofb64 40
+sha 41
+shaWithRSAEncryption 42
+des_ede_cbc 43
+des_ede3_cbc 44
+des_ofb64 45
+idea_ofb64 46
+pkcs9 47
+pkcs9_emailAddress 48
+pkcs9_unstructuredName 49
+pkcs9_contentType 50
+pkcs9_messageDigest 51
+pkcs9_signingTime 52
+pkcs9_countersignature 53
+pkcs9_challengePassword 54
+pkcs9_unstructuredAddress 55
+pkcs9_extCertAttributes 56
+netscape 57
+netscape_cert_extension 58
+netscape_data_type 59
+des_ede_cfb64 60
+des_ede3_cfb64 61
+des_ede_ofb64 62
+des_ede3_ofb64 63
+sha1 64
+sha1WithRSAEncryption 65
+dsaWithSHA 66
+dsa_2 67
+pbeWithSHA1AndRC2_CBC 68
+id_pbkdf2 69
+dsaWithSHA1_2 70
+netscape_cert_type 71
+netscape_base_url 72
+netscape_revocation_url 73
+netscape_ca_revocation_url 74
+netscape_renewal_url 75
+netscape_ca_policy_url 76
+netscape_ssl_server_name 77
+netscape_comment 78
+netscape_cert_sequence 79
+desx_cbc 80
+id_ce 81
+subject_key_identifier 82
+key_usage 83
+private_key_usage_period 84
+subject_alt_name 85
+issuer_alt_name 86
+basic_constraints 87
+crl_number 88
+certificate_policies 89
+authority_key_identifier 90
+bf_cbc 91
+bf_ecb 92
+bf_cfb64 93
+bf_ofb64 94
+mdc2 95
+mdc2WithRSA 96
+rc4_40 97
+rc2_40_cbc 98
+givenName 99
+surname 100
+initials 101
+uniqueIdentifier 102
+crl_distribution_points 103
+md5WithRSA 104
+serialNumber 105
+title 106
+description 107
+cast5_cbc 108
+cast5_ecb 109
+cast5_cfb64 110
+cast5_ofb64 111
+pbeWithMD5AndCast5_CBC 112
+dsaWithSHA1 113
+md5_sha1 114
+sha1WithRSA 115
+dsa 116
+ripemd160 117
+ripemd160WithRSA 119
+rc5_cbc 120
+rc5_ecb 121
+rc5_cfb64 122
+rc5_ofb64 123
+rle_compression 124
+zlib_compression 125
+ext_key_usage 126
+id_pkix 127
+id_kp 128
+server_auth 129
+client_auth 130
+code_sign 131
+email_protect 132
+time_stamp 133
+ms_code_ind 134
+ms_code_com 135
+ms_ctl_sign 136
+ms_sgc 137
+ms_efs 138
+ns_sgc 139
+delta_crl 140
+crl_reason 141
+invalidity_date 142
+sxnet 143
+pbe_WithSHA1And128BitRC4 144
+pbe_WithSHA1And40BitRC4 145
+pbe_WithSHA1And3_Key_TripleDES_CBC 146
+pbe_WithSHA1And2_Key_TripleDES_CBC 147
+pbe_WithSHA1And128BitRC2_CBC 148
+pbe_WithSHA1And40BitRC2_CBC 149
+keyBag 150
+pkcs8ShroudedKeyBag 151
+certBag 152
+crlBag 153
+secretBag 154
+safeContentsBag 155
+friendlyName 156
+localKeyID 157
+x509Certificate 158
+sdsiCertificate 159
+x509Crl 160
+pbes2 161
+pbmac1 162
+hmacWithSHA1 163
+id_qt_cps 164
+id_qt_unotice 165
+rc2_64_cbc 166
+SMIMECapabilities 167
+pbeWithMD2AndRC2_CBC 168
+pbeWithMD5AndRC2_CBC 169
+pbeWithSHA1AndDES_CBC 170
+ms_ext_req 171
+ext_req 172
+name 173
+dnQualifier 174
+id_pe 175
+id_ad 176
+info_access 177
+ad_OCSP 178
+ad_ca_issuers 179
+OCSP_sign 180
+iso 181
+member_body 182
+ISO_US 183
+X9_57 184
+X9cm 185
+pkcs1 186
+pkcs5 187
+SMIME 188
+id_smime_mod 189
+id_smime_ct 190
+id_smime_aa 191
+id_smime_alg 192
+id_smime_cd 193
+id_smime_spq 194
+id_smime_cti 195
+id_smime_mod_cms 196
+id_smime_mod_ess 197
+id_smime_mod_oid 198
+id_smime_mod_msg_v3 199
+id_smime_mod_ets_eSignature_88 200
+id_smime_mod_ets_eSignature_97 201
+id_smime_mod_ets_eSigPolicy_88 202
+id_smime_mod_ets_eSigPolicy_97 203
+id_smime_ct_receipt 204
+id_smime_ct_authData 205
+id_smime_ct_publishCert 206
+id_smime_ct_TSTInfo 207
+id_smime_ct_TDTInfo 208
+id_smime_ct_contentInfo 209
+id_smime_ct_DVCSRequestData 210
+id_smime_ct_DVCSResponseData 211
+id_smime_aa_receiptRequest 212
+id_smime_aa_securityLabel 213
+id_smime_aa_mlExpandHistory 214
+id_smime_aa_contentHint 215
+id_smime_aa_msgSigDigest 216
+id_smime_aa_encapContentType 217
+id_smime_aa_contentIdentifier 218
+id_smime_aa_macValue 219
+id_smime_aa_equivalentLabels 220
+id_smime_aa_contentReference 221
+id_smime_aa_encrypKeyPref 222
+id_smime_aa_signingCertificate 223
+id_smime_aa_smimeEncryptCerts 224
+id_smime_aa_timeStampToken 225
+id_smime_aa_ets_sigPolicyId 226
+id_smime_aa_ets_commitmentType 227
+id_smime_aa_ets_signerLocation 228
+id_smime_aa_ets_signerAttr 229
+id_smime_aa_ets_otherSigCert 230
+id_smime_aa_ets_contentTimestamp 231
+id_smime_aa_ets_CertificateRefs 232
+id_smime_aa_ets_RevocationRefs 233
+id_smime_aa_ets_certValues 234
+id_smime_aa_ets_revocationValues 235
+id_smime_aa_ets_escTimeStamp 236
+id_smime_aa_ets_certCRLTimestamp 237
+id_smime_aa_ets_archiveTimeStamp 238
+id_smime_aa_signatureType 239
+id_smime_aa_dvcs_dvc 240
+id_smime_alg_ESDHwith3DES 241
+id_smime_alg_ESDHwithRC2 242
+id_smime_alg_3DESwrap 243
+id_smime_alg_RC2wrap 244
+id_smime_alg_ESDH 245
+id_smime_alg_CMS3DESwrap 246
+id_smime_alg_CMSRC2wrap 247
+id_smime_cd_ldap 248
+id_smime_spq_ets_sqt_uri 249
+id_smime_spq_ets_sqt_unotice 250
+id_smime_cti_ets_proofOfOrigin 251
+id_smime_cti_ets_proofOfReceipt 252
+id_smime_cti_ets_proofOfDelivery 253
+id_smime_cti_ets_proofOfSender 254
+id_smime_cti_ets_proofOfApproval 255
+id_smime_cti_ets_proofOfCreation 256
+md4 257
+id_pkix_mod 258
+id_qt 259
+id_it 260
+id_pkip 261
+id_alg 262
+id_cmc 263
+id_on 264
+id_pda 265
+id_aca 266
+id_qcs 267
+id_cct 268
+id_pkix1_explicit_88 269
+id_pkix1_implicit_88 270
+id_pkix1_explicit_93 271
+id_pkix1_implicit_93 272
+id_mod_crmf 273
+id_mod_cmc 274
+id_mod_kea_profile_88 275
+id_mod_kea_profile_93 276
+id_mod_cmp 277
+id_mod_qualified_cert_88 278
+id_mod_qualified_cert_93 279
+id_mod_attribute_cert 280
+id_mod_timestamp_protocol 281
+id_mod_ocsp 282
+id_mod_dvcs 283
+id_mod_cmp2000 284
+biometricInfo 285
+qcStatements 286
+ac_auditEntity 287
+ac_targeting 288
+aaControls 289
+sbgp_ipAddrBlock 290
+sbgp_autonomousSysNum 291
+sbgp_routerIdentifier 292
+textNotice 293
+ipsecEndSystem 294
+ipsecTunnel 295
+ipsecUser 296
+dvcs 297
+id_it_caProtEncCert 298
+id_it_signKeyPairTypes 299
+id_it_encKeyPairTypes 300
+id_it_preferredSymmAlg 301
+id_it_caKeyUpdateInfo 302
+id_it_currentCRL 303
+id_it_unsupportedOIDs 304
+id_it_subscriptionRequest 305
+id_it_subscriptionResponse 306
+id_it_keyPairParamReq 307
+id_it_keyPairParamRep 308
+id_it_revPassphrase 309
+id_it_implicitConfirm 310
+id_it_confirmWaitTime 311
+id_it_origPKIMessage 312
+id_regCtrl 313
+id_regInfo 314
+id_regCtrl_regToken 315
+id_regCtrl_authenticator 316
+id_regCtrl_pkiPublicationInfo 317
+id_regCtrl_pkiArchiveOptions 318
+id_regCtrl_oldCertID 319
+id_regCtrl_protocolEncrKey 320
+id_regInfo_utf8Pairs 321
+id_regInfo_certReq 322
+id_alg_des40 323
+id_alg_noSignature 324
+id_alg_dh_sig_hmac_sha1 325
+id_alg_dh_pop 326
+id_cmc_statusInfo 327
+id_cmc_identification 328
+id_cmc_identityProof 329
+id_cmc_dataReturn 330
+id_cmc_transactionId 331
+id_cmc_senderNonce 332
+id_cmc_recipientNonce 333
+id_cmc_addExtensions 334
+id_cmc_encryptedPOP 335
+id_cmc_decryptedPOP 336
+id_cmc_lraPOPWitness 337
+id_cmc_getCert 338
+id_cmc_getCRL 339
+id_cmc_revokeRequest 340
+id_cmc_regInfo 341
+id_cmc_responseInfo 342
+id_cmc_queryPending 343
+id_cmc_popLinkRandom 344
+id_cmc_popLinkWitness 345
+id_cmc_confirmCertAcceptance 346
+id_on_personalData 347
+id_pda_dateOfBirth 348
+id_pda_placeOfBirth 349
+id_pda_pseudonym 350
+id_pda_gender 351
+id_pda_countryOfCitizenship 352
+id_pda_countryOfResidence 353
+id_aca_authenticationInfo 354
+id_aca_accessIdentity 355
+id_aca_chargingIdentity 356
+id_aca_group 357
+id_aca_role 358
+id_qcs_pkixQCSyntax_v1 359
+id_cct_crs 360
+id_cct_PKIData 361
+id_cct_PKIResponse 362
+ad_timeStamping 363
+ad_dvcs 364
+id_pkix_OCSP_basic 365
+id_pkix_OCSP_Nonce 366
+id_pkix_OCSP_CrlID 367
+id_pkix_OCSP_acceptableResponses 368
+id_pkix_OCSP_noCheck 369
+id_pkix_OCSP_archiveCutoff 370
+id_pkix_OCSP_serviceLocator 371
+id_pkix_OCSP_extendedStatus 372
+id_pkix_OCSP_valid 373
+id_pkix_OCSP_path 374
+id_pkix_OCSP_trustRoot 375
+algorithm 376
+rsaSignature 377
+X500algorithms 378
+org 379
+dod 380
+iana 381
+Directory 382
+Management 383
+Experimental 384
+Private 385
+Security 386
+SNMPv2 387
+Mail 388
+Enterprises 389
+dcObject 390
+domainComponent 391
+Domain 392
+joint_iso_ccitt 393
+selected_attribute_types 394
+clearance 395
+md4WithRSAEncryption 396
+ac_proxying 397
+sinfo_access 398
+id_aca_encAttrs 399
+role 400
+policy_constraints 401
+target_information 402
+no_rev_avail 403
+ccitt 404
+ansi_X9_62 405
+X9_62_prime_field 406
+X9_62_characteristic_two_field 407
+X9_62_id_ecPublicKey 408
+X9_62_prime192v1 409
+X9_62_prime192v2 410
+X9_62_prime192v3 411
+X9_62_prime239v1 412
+X9_62_prime239v2 413
+X9_62_prime239v3 414
+X9_62_prime256v1 415
+ecdsa_with_SHA1 416
+ms_csp_name 417
+aes_128_ecb 418
+aes_128_cbc 419
+aes_128_ofb128 420
+aes_128_cfb128 421
+aes_192_ecb 422
+aes_192_cbc 423
+aes_192_ofb128 424
+aes_192_cfb128 425
+aes_256_ecb 426
+aes_256_cbc 427
+aes_256_ofb128 428
+aes_256_cfb128 429
+hold_instruction_code 430
+hold_instruction_none 431
+hold_instruction_call_issuer 432
+hold_instruction_reject 433
+data 434
+pss 435
+ucl 436
+pilot 437
+pilotAttributeType 438
+pilotAttributeSyntax 439
+pilotObjectClass 440
+pilotGroups 441
+iA5StringSyntax 442
+caseIgnoreIA5StringSyntax 443
+pilotObject 444
+pilotPerson 445
+account 446
+document 447
+room 448
+documentSeries 449
+rFC822localPart 450
+dNSDomain 451
+domainRelatedObject 452
+friendlyCountry 453
+simpleSecurityObject 454
+pilotOrganization 455
+pilotDSA 456
+qualityLabelledData 457
+userId 458
+textEncodedORAddress 459
+rfc822Mailbox 460
+info 461
+favouriteDrink 462
+roomNumber 463
+photo 464
+userClass 465
+host 466
+manager 467
+documentIdentifier 468
+documentTitle 469
+documentVersion 470
+documentAuthor 471
+documentLocation 472
+homeTelephoneNumber 473
+secretary 474
+otherMailbox 475
+lastModifiedTime 476
+lastModifiedBy 477
+aRecord 478
+pilotAttributeType27 479
+mXRecord 480
+nSRecord 481
+sOARecord 482
+cNAMERecord 483
+associatedDomain 484
+associatedName 485
+homePostalAddress 486
+personalTitle 487
+mobileTelephoneNumber 488
+pagerTelephoneNumber 489
+friendlyCountryName 490
+organizationalStatus 491
+janetMailbox 492
+mailPreferenceOption 493
+buildingName 494
+dSAQuality 495
+singleLevelQuality 496
+subtreeMinimumQuality 497
+subtreeMaximumQuality 498
+personalSignature 499
+dITRedirect 500
+audio 501
+documentPublisher 502
+x500UniqueIdentifier 503
+mime_mhs 504
+mime_mhs_headings 505
+mime_mhs_bodies 506
+id_hex_partial_message 507
+id_hex_multipart_message 508
+generationQualifier 509
+pseudonym 510
+InternationalRA 511
+id_set 512
+set_ctype 513
+set_msgExt 514
+set_attr 515
+set_policy 516
+set_certExt 517
+set_brand 518
+setct_PANData 519
+setct_PANToken 520
+setct_PANOnly 521
+setct_OIData 522
+setct_PI 523
+setct_PIData 524
+setct_PIDataUnsigned 525
+setct_HODInput 526
+setct_AuthResBaggage 527
+setct_AuthRevReqBaggage 528
+setct_AuthRevResBaggage 529
+setct_CapTokenSeq 530
+setct_PInitResData 531
+setct_PI_TBS 532
+setct_PResData 533
+setct_AuthReqTBS 534
+setct_AuthResTBS 535
+setct_AuthResTBSX 536
+setct_AuthTokenTBS 537
+setct_CapTokenData 538
+setct_CapTokenTBS 539
+setct_AcqCardCodeMsg 540
+setct_AuthRevReqTBS 541
+setct_AuthRevResData 542
+setct_AuthRevResTBS 543
+setct_CapReqTBS 544
+setct_CapReqTBSX 545
+setct_CapResData 546
+setct_CapRevReqTBS 547
+setct_CapRevReqTBSX 548
+setct_CapRevResData 549
+setct_CredReqTBS 550
+setct_CredReqTBSX 551
+setct_CredResData 552
+setct_CredRevReqTBS 553
+setct_CredRevReqTBSX 554
+setct_CredRevResData 555
+setct_PCertReqData 556
+setct_PCertResTBS 557
+setct_BatchAdminReqData 558
+setct_BatchAdminResData 559
+setct_CardCInitResTBS 560
+setct_MeAqCInitResTBS 561
+setct_RegFormResTBS 562
+setct_CertReqData 563
+setct_CertReqTBS 564
+setct_CertResData 565
+setct_CertInqReqTBS 566
+setct_ErrorTBS 567
+setct_PIDualSignedTBE 568
+setct_PIUnsignedTBE 569
+setct_AuthReqTBE 570
+setct_AuthResTBE 571
+setct_AuthResTBEX 572
+setct_AuthTokenTBE 573
+setct_CapTokenTBE 574
+setct_CapTokenTBEX 575
+setct_AcqCardCodeMsgTBE 576
+setct_AuthRevReqTBE 577
+setct_AuthRevResTBE 578
+setct_AuthRevResTBEB 579
+setct_CapReqTBE 580
+setct_CapReqTBEX 581
+setct_CapResTBE 582
+setct_CapRevReqTBE 583
+setct_CapRevReqTBEX 584
+setct_CapRevResTBE 585
+setct_CredReqTBE 586
+setct_CredReqTBEX 587
+setct_CredResTBE 588
+setct_CredRevReqTBE 589
+setct_CredRevReqTBEX 590
+setct_CredRevResTBE 591
+setct_BatchAdminReqTBE 592
+setct_BatchAdminResTBE 593
+setct_RegFormReqTBE 594
+setct_CertReqTBE 595
+setct_CertReqTBEX 596
+setct_CertResTBE 597
+setct_CRLNotificationTBS 598
+setct_CRLNotificationResTBS 599
+setct_BCIDistributionTBS 600
+setext_genCrypt 601
+setext_miAuth 602
+setext_pinSecure 603
+setext_pinAny 604
+setext_track2 605
+setext_cv 606
+set_policy_root 607
+setCext_hashedRoot 608
+setCext_certType 609
+setCext_merchData 610
+setCext_cCertRequired 611
+setCext_tunneling 612
+setCext_setExt 613
+setCext_setQualf 614
+setCext_PGWYcapabilities 615
+setCext_TokenIdentifier 616
+setCext_Track2Data 617
+setCext_TokenType 618
+setCext_IssuerCapabilities 619
+setAttr_Cert 620
+setAttr_PGWYcap 621
+setAttr_TokenType 622
+setAttr_IssCap 623
+set_rootKeyThumb 624
+set_addPolicy 625
+setAttr_Token_EMV 626
+setAttr_Token_B0Prime 627
+setAttr_IssCap_CVM 628
+setAttr_IssCap_T2 629
+setAttr_IssCap_Sig 630
+setAttr_GenCryptgrm 631
+setAttr_T2Enc 632
+setAttr_T2cleartxt 633
+setAttr_TokICCsig 634
+setAttr_SecDevSig 635
+set_brand_IATA_ATA 636
+set_brand_Diners 637
+set_brand_AmericanExpress 638
+set_brand_JCB 639
+set_brand_Visa 640
+set_brand_MasterCard 641
+set_brand_Novus 642
+des_cdmf 643
+rsaOAEPEncryptionSET 644
+itu_t 645
+joint_iso_itu_t 646
+international_organizations 647
+ms_smartcard_login 648
+ms_upn 649
+aes_128_cfb1 650
+aes_192_cfb1 651
+aes_256_cfb1 652
+aes_128_cfb8 653
+aes_192_cfb8 654
+aes_256_cfb8 655
+des_cfb1 656
+des_cfb8 657
+des_ede3_cfb1 658
+des_ede3_cfb8 659
+streetAddress 660
+postalCode 661
+id_ppl 662
+proxyCertInfo 663
+id_ppl_anyLanguage 664
+id_ppl_inheritAll 665
+name_constraints 666
+Independent 667
+sha256WithRSAEncryption 668
+sha384WithRSAEncryption 669
+sha512WithRSAEncryption 670
+sha224WithRSAEncryption 671
+sha256 672
+sha384 673
+sha512 674
+sha224 675
+identified_organization 676
+certicom_arc 677
+wap 678
+wap_wsg 679
+X9_62_id_characteristic_two_basis 680
+X9_62_onBasis 681
+X9_62_tpBasis 682
+X9_62_ppBasis 683
+X9_62_c2pnb163v1 684
+X9_62_c2pnb163v2 685
+X9_62_c2pnb163v3 686
+X9_62_c2pnb176v1 687
+X9_62_c2tnb191v1 688
+X9_62_c2tnb191v2 689
+X9_62_c2tnb191v3 690
+X9_62_c2onb191v4 691
+X9_62_c2onb191v5 692
+X9_62_c2pnb208w1 693
+X9_62_c2tnb239v1 694
+X9_62_c2tnb239v2 695
+X9_62_c2tnb239v3 696
+X9_62_c2onb239v4 697
+X9_62_c2onb239v5 698
+X9_62_c2pnb272w1 699
+X9_62_c2pnb304w1 700
+X9_62_c2tnb359v1 701
+X9_62_c2pnb368w1 702
+X9_62_c2tnb431r1 703
+secp112r1 704
+secp112r2 705
+secp128r1 706
+secp128r2 707
+secp160k1 708
+secp160r1 709
+secp160r2 710
+secp192k1 711
+secp224k1 712
+secp224r1 713
+secp256k1 714
+secp384r1 715
+secp521r1 716
+sect113r1 717
+sect113r2 718
+sect131r1 719
+sect131r2 720
+sect163k1 721
+sect163r1 722
+sect163r2 723
+sect193r1 724
+sect193r2 725
+sect233k1 726
+sect233r1 727
+sect239k1 728
+sect283k1 729
+sect283r1 730
+sect409k1 731
+sect409r1 732
+sect571k1 733
+sect571r1 734
+wap_wsg_idm_ecid_wtls1 735
+wap_wsg_idm_ecid_wtls3 736
+wap_wsg_idm_ecid_wtls4 737
+wap_wsg_idm_ecid_wtls5 738
+wap_wsg_idm_ecid_wtls6 739
+wap_wsg_idm_ecid_wtls7 740
+wap_wsg_idm_ecid_wtls8 741
+wap_wsg_idm_ecid_wtls9 742
+wap_wsg_idm_ecid_wtls10 743
+wap_wsg_idm_ecid_wtls11 744
+wap_wsg_idm_ecid_wtls12 745
+any_policy 746
+policy_mappings 747
+inhibit_any_policy 748
+ipsec3 749
+ipsec4 750
+camellia_128_cbc 751
+camellia_192_cbc 752
+camellia_256_cbc 753
+camellia_128_ecb 754
+camellia_192_ecb 755
+camellia_256_ecb 756
+camellia_128_cfb128 757
+camellia_192_cfb128 758
+camellia_256_cfb128 759
+camellia_128_cfb1 760
+camellia_192_cfb1 761
+camellia_256_cfb1 762
+camellia_128_cfb8 763
+camellia_192_cfb8 764
+camellia_256_cfb8 765
+camellia_128_ofb128 766
+camellia_192_ofb128 767
+camellia_256_ofb128 768
+subject_directory_attributes 769
+issuing_distribution_point 770
+certificate_issuer 771
+korea 772
+kisa 773
+kftc 774
+npki_alg 775
+seed_ecb 776
+seed_cbc 777
+seed_ofb128 778
+seed_cfb128 779
+hmac_md5 780
+hmac_sha1 781
+id_PasswordBasedMAC 782
+id_DHBasedMac 783
+id_it_suppLangTags 784
+caRepository 785
+id_smime_ct_compressedData 786
+id_ct_asciiTextWithCRLF 787
+id_aes128_wrap 788
+id_aes192_wrap 789
+id_aes256_wrap 790
+ecdsa_with_Recommended 791
+ecdsa_with_Specified 792
+ecdsa_with_SHA224 793
+ecdsa_with_SHA256 794
+ecdsa_with_SHA384 795
+ecdsa_with_SHA512 796
+hmacWithMD5 797
+hmacWithSHA224 798
+hmacWithSHA256 799
+hmacWithSHA384 800
+hmacWithSHA512 801
+dsa_with_SHA224 802
+dsa_with_SHA256 803
+whirlpool 804
+cryptopro 805
+cryptocom 806
+id_GostR3411_94_with_GostR3410_2001 807
+id_GostR3411_94_with_GostR3410_94 808
+id_GostR3411_94 809
+id_HMACGostR3411_94 810
+id_GostR3410_2001 811
+id_GostR3410_94 812
+id_Gost28147_89 813
+gost89_cnt 814
+id_Gost28147_89_MAC 815
+id_GostR3411_94_prf 816
+id_GostR3410_2001DH 817
+id_GostR3410_94DH 818
+id_Gost28147_89_CryptoPro_KeyMeshing 819
+id_Gost28147_89_None_KeyMeshing 820
+id_GostR3411_94_TestParamSet 821
+id_GostR3411_94_CryptoProParamSet 822
+id_Gost28147_89_TestParamSet 823
+id_Gost28147_89_CryptoPro_A_ParamSet 824
+id_Gost28147_89_CryptoPro_B_ParamSet 825
+id_Gost28147_89_CryptoPro_C_ParamSet 826
+id_Gost28147_89_CryptoPro_D_ParamSet 827
+id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet 828
+id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet 829
+id_Gost28147_89_CryptoPro_RIC_1_ParamSet 830
+id_GostR3410_94_TestParamSet 831
+id_GostR3410_94_CryptoPro_A_ParamSet 832
+id_GostR3410_94_CryptoPro_B_ParamSet 833
+id_GostR3410_94_CryptoPro_C_ParamSet 834
+id_GostR3410_94_CryptoPro_D_ParamSet 835
+id_GostR3410_94_CryptoPro_XchA_ParamSet 836
+id_GostR3410_94_CryptoPro_XchB_ParamSet 837
+id_GostR3410_94_CryptoPro_XchC_ParamSet 838
+id_GostR3410_2001_TestParamSet 839
+id_GostR3410_2001_CryptoPro_A_ParamSet 840
+id_GostR3410_2001_CryptoPro_B_ParamSet 841
+id_GostR3410_2001_CryptoPro_C_ParamSet 842
+id_GostR3410_2001_CryptoPro_XchA_ParamSet 843
+id_GostR3410_2001_CryptoPro_XchB_ParamSet 844
+id_GostR3410_94_a 845
+id_GostR3410_94_aBis 846
+id_GostR3410_94_b 847
+id_GostR3410_94_bBis 848
+id_Gost28147_89_cc 849
+id_GostR3410_94_cc 850
+id_GostR3410_2001_cc 851
+id_GostR3411_94_with_GostR3410_94_cc 852
+id_GostR3411_94_with_GostR3410_2001_cc 853
+id_GostR3410_2001_ParamSet_cc 854
+hmac 855
+LocalKeySet 856
+freshest_crl 857
+id_on_permanentIdentifier 858
+searchGuide 859
+businessCategory 860
+postalAddress 861
+postOfficeBox 862
+physicalDeliveryOfficeName 863
+telephoneNumber 864
+telexNumber 865
+teletexTerminalIdentifier 866
+facsimileTelephoneNumber 867
+x121Address 868
+internationaliSDNNumber 869
+registeredAddress 870
+destinationIndicator 871
+preferredDeliveryMethod 872
+presentationAddress 873
+supportedApplicationContext 874
+member 875
+owner 876
+roleOccupant 877
+seeAlso 878
+userPassword 879
+userCertificate 880
+cACertificate 881
+authorityRevocationList 882
+certificateRevocationList 883
+crossCertificatePair 884
+enhancedSearchGuide 885
+protocolInformation 886
+distinguishedName 887
+uniqueMember 888
+houseIdentifier 889
+supportedAlgorithms 890
+deltaRevocationList 891
+dmdName 892
+id_alg_PWRI_KEK 893
+cmac 894
+aes_128_gcm 895
+aes_128_ccm 896
+id_aes128_wrap_pad 897
+aes_192_gcm 898
+aes_192_ccm 899
+id_aes192_wrap_pad 900
+aes_256_gcm 901
+aes_256_ccm 902
+id_aes256_wrap_pad 903
+aes_128_ctr 904
+aes_192_ctr 905
+aes_256_ctr 906
+id_camellia128_wrap 907
+id_camellia192_wrap 908
+id_camellia256_wrap 909
+anyExtendedKeyUsage 910
+mgf1 911
+rsassaPss 912
+aes_128_xts 913
+aes_256_xts 914
+rc4_hmac_md5 915
+aes_128_cbc_hmac_sha1 916
+aes_192_cbc_hmac_sha1 917
+aes_256_cbc_hmac_sha1 918
+rsaesOaep 919
+dhpublicnumber 920
+brainpoolP160r1 921
+brainpoolP160t1 922
+brainpoolP192r1 923
+brainpoolP192t1 924
+brainpoolP224r1 925
+brainpoolP224t1 926
+brainpoolP256r1 927
+brainpoolP256t1 928
+brainpoolP320r1 929
+brainpoolP320t1 930
+brainpoolP384r1 931
+brainpoolP384t1 932
+brainpoolP512r1 933
+brainpoolP512t1 934
+pSpecified 935
+dhSinglePass_stdDH_sha1kdf_scheme 936
+dhSinglePass_stdDH_sha224kdf_scheme 937
+dhSinglePass_stdDH_sha256kdf_scheme 938
+dhSinglePass_stdDH_sha384kdf_scheme 939
+dhSinglePass_stdDH_sha512kdf_scheme 940
+dhSinglePass_cofactorDH_sha1kdf_scheme 941
+dhSinglePass_cofactorDH_sha224kdf_scheme 942
+dhSinglePass_cofactorDH_sha256kdf_scheme 943
+dhSinglePass_cofactorDH_sha384kdf_scheme 944
+dhSinglePass_cofactorDH_sha512kdf_scheme 945
+dh_std_kdf 946
+dh_cofactor_kdf 947
diff --git a/src/crypto/obj/obj_xref.c b/src/crypto/obj/obj_xref.c
new file mode 100644
index 0000000..70babea
--- /dev/null
+++ b/src/crypto/obj/obj_xref.c
@@ -0,0 +1,124 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/obj.h>
+
+#include <stdlib.h>
+
+#include "obj_xref.h"
+
+
+static int nid_triple_cmp_by_sign_id(const void *in_a, const void *in_b) {
+ const nid_triple *a = in_a;
+ const nid_triple *b = in_b;
+
+ return a->sign_id - b->sign_id;
+}
+
+int OBJ_find_sigid_algs(int sign_nid, int *out_digest_nid, int *out_pkey_nid) {
+ nid_triple key;
+ const nid_triple *triple;
+
+ key.sign_id = sign_nid;
+
+ triple = bsearch(&key, sigoid_srt, sizeof(sigoid_srt) / sizeof(nid_triple),
+ sizeof(nid_triple), nid_triple_cmp_by_sign_id);
+
+ if (triple == NULL) {
+ return 0;
+ }
+ if (out_digest_nid) {
+ *out_digest_nid = triple->hash_id;
+ }
+ if (out_pkey_nid) {
+ *out_pkey_nid = triple->pkey_id;
+ }
+
+ return 1;
+}
+
+static int nid_triple_cmp_by_digest_and_hash(const void *in_a,
+ const void *in_b) {
+ const nid_triple *a = *((nid_triple**) in_a);
+ const nid_triple *b = *((nid_triple**) in_b);
+
+ int ret = a->hash_id - b->hash_id;
+ if (ret) {
+ return ret;
+ }
+ return a->pkey_id - b->pkey_id;
+}
+
+int OBJ_find_sigid_by_algs(int *out_sign_nid, int digest_nid, int pkey_nid) {
+ nid_triple key, *pkey;
+ const nid_triple **triple;
+
+ key.hash_id = digest_nid;
+ key.pkey_id = pkey_nid;
+ pkey = &key;
+
+ triple = bsearch(&pkey, sigoid_srt_xref,
+ sizeof(sigoid_srt_xref) / sizeof(nid_triple *),
+ sizeof(nid_triple *), nid_triple_cmp_by_digest_and_hash);
+
+ if (triple == NULL) {
+ return 0;
+ }
+ if (out_sign_nid) {
+ *out_sign_nid = (*triple)->sign_id;
+ }
+ return 1;
+}
diff --git a/src/crypto/obj/obj_xref.h b/src/crypto/obj/obj_xref.h
new file mode 100644
index 0000000..b2082f5
--- /dev/null
+++ b/src/crypto/obj/obj_xref.h
@@ -0,0 +1,96 @@
+/* THIS FILE IS GENERATED FROM obj_xref.txt by obj_xref.pl via the
+ * following command:
+ * perl obj_xref.pl obj_mac.num obj_xref.txt > obj_xref.h */
+
+typedef struct
+ {
+ int sign_id;
+ int hash_id;
+ int pkey_id;
+ } nid_triple;
+
+static const nid_triple sigoid_srt[] =
+ {
+ {NID_md2WithRSAEncryption, NID_md2, NID_rsaEncryption},
+ {NID_md5WithRSAEncryption, NID_md5, NID_rsaEncryption},
+ {NID_shaWithRSAEncryption, NID_sha, NID_rsaEncryption},
+ {NID_sha1WithRSAEncryption, NID_sha1, NID_rsaEncryption},
+ {NID_dsaWithSHA, NID_sha, NID_dsa},
+ {NID_dsaWithSHA1_2, NID_sha1, NID_dsa_2},
+ {NID_mdc2WithRSA, NID_mdc2, NID_rsaEncryption},
+ {NID_md5WithRSA, NID_md5, NID_rsa},
+ {NID_dsaWithSHA1, NID_sha1, NID_dsa},
+ {NID_sha1WithRSA, NID_sha1, NID_rsa},
+ {NID_ripemd160WithRSA, NID_ripemd160, NID_rsaEncryption},
+ {NID_md4WithRSAEncryption, NID_md4, NID_rsaEncryption},
+ {NID_ecdsa_with_SHA1, NID_sha1, NID_X9_62_id_ecPublicKey},
+ {NID_sha256WithRSAEncryption, NID_sha256, NID_rsaEncryption},
+ {NID_sha384WithRSAEncryption, NID_sha384, NID_rsaEncryption},
+ {NID_sha512WithRSAEncryption, NID_sha512, NID_rsaEncryption},
+ {NID_sha224WithRSAEncryption, NID_sha224, NID_rsaEncryption},
+ {NID_ecdsa_with_Recommended, NID_undef, NID_X9_62_id_ecPublicKey},
+ {NID_ecdsa_with_Specified, NID_undef, NID_X9_62_id_ecPublicKey},
+ {NID_ecdsa_with_SHA224, NID_sha224, NID_X9_62_id_ecPublicKey},
+ {NID_ecdsa_with_SHA256, NID_sha256, NID_X9_62_id_ecPublicKey},
+ {NID_ecdsa_with_SHA384, NID_sha384, NID_X9_62_id_ecPublicKey},
+ {NID_ecdsa_with_SHA512, NID_sha512, NID_X9_62_id_ecPublicKey},
+ {NID_dsa_with_SHA224, NID_sha224, NID_dsa},
+ {NID_dsa_with_SHA256, NID_sha256, NID_dsa},
+ {NID_id_GostR3411_94_with_GostR3410_2001, NID_id_GostR3411_94, NID_id_GostR3410_2001},
+ {NID_id_GostR3411_94_with_GostR3410_94, NID_id_GostR3411_94, NID_id_GostR3410_94},
+ {NID_id_GostR3411_94_with_GostR3410_94_cc, NID_id_GostR3411_94, NID_id_GostR3410_94_cc},
+ {NID_id_GostR3411_94_with_GostR3410_2001_cc, NID_id_GostR3411_94, NID_id_GostR3410_2001_cc},
+ {NID_rsassaPss, NID_undef, NID_rsaEncryption},
+ {NID_dhSinglePass_stdDH_sha1kdf_scheme, NID_sha1, NID_dh_std_kdf},
+ {NID_dhSinglePass_stdDH_sha224kdf_scheme, NID_sha224, NID_dh_std_kdf},
+ {NID_dhSinglePass_stdDH_sha256kdf_scheme, NID_sha256, NID_dh_std_kdf},
+ {NID_dhSinglePass_stdDH_sha384kdf_scheme, NID_sha384, NID_dh_std_kdf},
+ {NID_dhSinglePass_stdDH_sha512kdf_scheme, NID_sha512, NID_dh_std_kdf},
+ {NID_dhSinglePass_cofactorDH_sha1kdf_scheme, NID_sha1, NID_dh_cofactor_kdf},
+ {NID_dhSinglePass_cofactorDH_sha224kdf_scheme, NID_sha224, NID_dh_cofactor_kdf},
+ {NID_dhSinglePass_cofactorDH_sha256kdf_scheme, NID_sha256, NID_dh_cofactor_kdf},
+ {NID_dhSinglePass_cofactorDH_sha384kdf_scheme, NID_sha384, NID_dh_cofactor_kdf},
+ {NID_dhSinglePass_cofactorDH_sha512kdf_scheme, NID_sha512, NID_dh_cofactor_kdf},
+ };
+
+static const nid_triple * const sigoid_srt_xref[] =
+ {
+ &sigoid_srt[0],
+ &sigoid_srt[1],
+ &sigoid_srt[7],
+ &sigoid_srt[2],
+ &sigoid_srt[4],
+ &sigoid_srt[3],
+ &sigoid_srt[9],
+ &sigoid_srt[5],
+ &sigoid_srt[8],
+ &sigoid_srt[12],
+ &sigoid_srt[30],
+ &sigoid_srt[35],
+ &sigoid_srt[6],
+ &sigoid_srt[10],
+ &sigoid_srt[11],
+ &sigoid_srt[13],
+ &sigoid_srt[24],
+ &sigoid_srt[20],
+ &sigoid_srt[32],
+ &sigoid_srt[37],
+ &sigoid_srt[14],
+ &sigoid_srt[21],
+ &sigoid_srt[33],
+ &sigoid_srt[38],
+ &sigoid_srt[15],
+ &sigoid_srt[22],
+ &sigoid_srt[34],
+ &sigoid_srt[39],
+ &sigoid_srt[16],
+ &sigoid_srt[23],
+ &sigoid_srt[19],
+ &sigoid_srt[31],
+ &sigoid_srt[36],
+ &sigoid_srt[25],
+ &sigoid_srt[26],
+ &sigoid_srt[27],
+ &sigoid_srt[28],
+ };
+
diff --git a/src/crypto/obj/obj_xref.pl b/src/crypto/obj/obj_xref.pl
new file mode 100644
index 0000000..51dd68f
--- /dev/null
+++ b/src/crypto/obj/obj_xref.pl
@@ -0,0 +1,118 @@
+#!/usr/bin/env perl
+
+use strict;
+
+if (scalar @ARGV != 2)
+ {
+ print "Usage: perl obj_xref.pl obj_mac.num obj_xref.txt > obj_xref.h\n";
+ exit 1;
+ }
+
+my %xref_tbl;
+my %oid_tbl;
+
+my ($mac_file, $xref_file) = @ARGV;
+
+open(IN, $mac_file) || die "Can't open $mac_file";
+
+# Read in OID nid values for a lookup table.
+
+while (<IN>)
+ {
+ chomp;
+ my ($name, $num) = /^(\S+)\s+(\S+)$/;
+ $oid_tbl{$name} = $num;
+ }
+close IN;
+
+open(IN, $xref_file) || die "Can't open $xref_file";
+
+my $ln = 1;
+
+while (<IN>)
+ {
+ chomp;
+ s/#.*$//;
+ next if (/^\S*$/);
+ my ($xr, $p1, $p2) = /^(\S+)\s+(\S+)\s+(\S+)/;
+ check_oid($xr);
+ check_oid($p1);
+ check_oid($p2);
+ $xref_tbl{$xr} = [$p1, $p2, $ln];
+ }
+
+my @xrkeys = keys %xref_tbl;
+
+my @srt1 = sort { $oid_tbl{$a} <=> $oid_tbl{$b}} @xrkeys;
+
+for(my $i = 0; $i <= $#srt1; $i++)
+ {
+ $xref_tbl{$srt1[$i]}[2] = $i;
+ }
+
+my @srt2 = sort
+ {
+ my$ap1 = $oid_tbl{$xref_tbl{$a}[0]};
+ my$bp1 = $oid_tbl{$xref_tbl{$b}[0]};
+ return $ap1 - $bp1 if ($ap1 != $bp1);
+ my$ap2 = $oid_tbl{$xref_tbl{$a}[1]};
+ my$bp2 = $oid_tbl{$xref_tbl{$b}[1]};
+
+ return $ap2 - $bp2;
+ } @xrkeys;
+
+my $pname = $0;
+
+$pname =~ s|^.[^/]/||;
+
+print <<EOF;
+/* THIS FILE IS GENERATED FROM obj_xref.txt by obj_xref.pl via the
+ * following command:
+ * perl obj_xref.pl obj_mac.num obj_xref.txt > obj_xref.h */
+
+typedef struct
+ {
+ int sign_id;
+ int hash_id;
+ int pkey_id;
+ } nid_triple;
+
+static const nid_triple sigoid_srt[] =
+ {
+EOF
+
+foreach (@srt1)
+ {
+ my $xr = $_;
+ my ($p1, $p2) = @{$xref_tbl{$_}};
+ print "\t{NID_$xr, NID_$p1, NID_$p2},\n";
+ }
+
+print "\t};";
+print <<EOF;
+
+
+static const nid_triple * const sigoid_srt_xref[] =
+ {
+EOF
+
+foreach (@srt2)
+ {
+ my ($p1, $p2, $x) = @{$xref_tbl{$_}};
+ # If digest or signature algorithm is "undef" then the algorithm
+ # needs special handling and is excluded from the cross reference table.
+ next if $p1 eq "undef" || $p2 eq "undef";
+ print "\t\&sigoid_srt\[$x\],\n";
+ }
+
+print "\t};\n\n";
+
+sub check_oid
+ {
+ my ($chk) = @_;
+ if (!exists $oid_tbl{$chk})
+ {
+ die "Not Found \"$chk\"\n";
+ }
+ }
+
diff --git a/src/crypto/obj/obj_xref.txt b/src/crypto/obj/obj_xref.txt
new file mode 100644
index 0000000..19c9422
--- /dev/null
+++ b/src/crypto/obj/obj_xref.txt
@@ -0,0 +1,58 @@
+# OID cross reference table.
+# Links signatures OIDs to their corresponding public key algorithms
+# and digests.
+
+md2WithRSAEncryption md2 rsaEncryption
+md5WithRSAEncryption md5 rsaEncryption
+shaWithRSAEncryption sha rsaEncryption
+sha1WithRSAEncryption sha1 rsaEncryption
+md4WithRSAEncryption md4 rsaEncryption
+sha256WithRSAEncryption sha256 rsaEncryption
+sha384WithRSAEncryption sha384 rsaEncryption
+sha512WithRSAEncryption sha512 rsaEncryption
+sha224WithRSAEncryption sha224 rsaEncryption
+mdc2WithRSA mdc2 rsaEncryption
+ripemd160WithRSA ripemd160 rsaEncryption
+# For PSS the digest algorithm can vary and depends on the included
+# AlgorithmIdentifier. The digest "undef" indicates the public key
+# method should handle this explicitly.
+rsassaPss undef rsaEncryption
+
+# Alternative deprecated OIDs. By using the older "rsa" OID this
+# type will be recognized by not normally used.
+
+md5WithRSA md5 rsa
+sha1WithRSA sha1 rsa
+
+dsaWithSHA sha dsa
+dsaWithSHA1 sha1 dsa
+
+dsaWithSHA1_2 sha1 dsa_2
+
+ecdsa_with_SHA1 sha1 X9_62_id_ecPublicKey
+ecdsa_with_SHA224 sha224 X9_62_id_ecPublicKey
+ecdsa_with_SHA256 sha256 X9_62_id_ecPublicKey
+ecdsa_with_SHA384 sha384 X9_62_id_ecPublicKey
+ecdsa_with_SHA512 sha512 X9_62_id_ecPublicKey
+ecdsa_with_Recommended undef X9_62_id_ecPublicKey
+ecdsa_with_Specified undef X9_62_id_ecPublicKey
+
+dsa_with_SHA224 sha224 dsa
+dsa_with_SHA256 sha256 dsa
+
+id_GostR3411_94_with_GostR3410_2001 id_GostR3411_94 id_GostR3410_2001
+id_GostR3411_94_with_GostR3410_94 id_GostR3411_94 id_GostR3410_94
+id_GostR3411_94_with_GostR3410_94_cc id_GostR3411_94 id_GostR3410_94_cc
+id_GostR3411_94_with_GostR3410_2001_cc id_GostR3411_94 id_GostR3410_2001_cc
+# ECDH KDFs and their corresponding message digests and schemes
+dhSinglePass_stdDH_sha1kdf_scheme sha1 dh_std_kdf
+dhSinglePass_stdDH_sha224kdf_scheme sha224 dh_std_kdf
+dhSinglePass_stdDH_sha256kdf_scheme sha256 dh_std_kdf
+dhSinglePass_stdDH_sha384kdf_scheme sha384 dh_std_kdf
+dhSinglePass_stdDH_sha512kdf_scheme sha512 dh_std_kdf
+
+dhSinglePass_cofactorDH_sha1kdf_scheme sha1 dh_cofactor_kdf
+dhSinglePass_cofactorDH_sha224kdf_scheme sha224 dh_cofactor_kdf
+dhSinglePass_cofactorDH_sha256kdf_scheme sha256 dh_cofactor_kdf
+dhSinglePass_cofactorDH_sha384kdf_scheme sha384 dh_cofactor_kdf
+dhSinglePass_cofactorDH_sha512kdf_scheme sha512 dh_cofactor_kdf
diff --git a/src/crypto/obj/objects.pl b/src/crypto/obj/objects.pl
new file mode 100644
index 0000000..7073e85
--- /dev/null
+++ b/src/crypto/obj/objects.pl
@@ -0,0 +1,235 @@
+#!/usr/bin/env perl
+
+if (scalar @ARGV != 3)
+ {
+ print "Usage: perl objects.pl objects.txt obj_mac.num ../../include/openssl/obj_mac.h\n";
+ exit 1;
+ }
+
+open (NUMIN,"$ARGV[1]") || die "Can't open number file $ARGV[1]";
+$max_nid=0;
+$o=0;
+while(<NUMIN>)
+ {
+ chop;
+ $o++;
+ s/#.*$//;
+ next if /^\s*$/;
+ $_ = 'X'.$_;
+ ($Cname,$mynum) = split;
+ $Cname =~ s/^X//;
+ if (defined($nidn{$mynum}))
+ { die "$ARGV[1]:$o:There's already an object with NID ",$mynum," on line ",$order{$mynum},"\n"; }
+ if (defined($nid{$Cname}))
+ { die "$ARGV[1]:$o:There's already an object with name ",$Cname," on line ",$order{$nid{$Cname}},"\n"; }
+ $nid{$Cname} = $mynum;
+ $nidn{$mynum} = $Cname;
+ $order{$mynum} = $o;
+ $max_nid = $mynum if $mynum > $max_nid;
+ }
+close NUMIN;
+
+open (IN,"$ARGV[0]") || die "Can't open input file $ARGV[0]";
+$Cname="";
+$o=0;
+while (<IN>)
+ {
+ chop;
+ $o++;
+ if (/^!module\s+(.*)$/)
+ {
+ $module = $1."-";
+ $module =~ s/\./_/g;
+ $module =~ s/-/_/g;
+ }
+ if (/^!global$/)
+ { $module = ""; }
+ if (/^!Cname\s+(.*)$/)
+ { $Cname = $1; }
+ if (/^!Alias\s+(.+?)\s+(.*)$/)
+ {
+ $Cname = $module.$1;
+ $myoid = $2;
+ $myoid = &process_oid($myoid);
+ $Cname =~ s/-/_/g;
+ $ordern{$o} = $Cname;
+ $order{$Cname} = $o;
+ $obj{$Cname} = $myoid;
+ $_ = "";
+ $Cname = "";
+ }
+ s/!.*$//;
+ s/#.*$//;
+ next if /^\s*$/;
+ ($myoid,$mysn,$myln) = split ':';
+ $mysn =~ s/^\s*//;
+ $mysn =~ s/\s*$//;
+ $myln =~ s/^\s*//;
+ $myln =~ s/\s*$//;
+ $myoid =~ s/^\s*//;
+ $myoid =~ s/\s*$//;
+ if ($myoid ne "")
+ {
+ $myoid = &process_oid($myoid);
+ }
+
+ if ($Cname eq "" && !($myln =~ / /))
+ {
+ $Cname = $myln;
+ $Cname =~ s/\./_/g;
+ $Cname =~ s/-/_/g;
+ if ($Cname ne "" && defined($ln{$module.$Cname}))
+ { die "objects.txt:$o:There's already an object with long name ",$ln{$module.$Cname}," on line ",$order{$module.$Cname},"\n"; }
+ }
+ if ($Cname eq "")
+ {
+ $Cname = $mysn;
+ $Cname =~ s/-/_/g;
+ if ($Cname ne "" && defined($sn{$module.$Cname}))
+ { die "objects.txt:$o:There's already an object with short name ",$sn{$module.$Cname}," on line ",$order{$module.$Cname},"\n"; }
+ }
+ if ($Cname eq "")
+ {
+ $Cname = $myln;
+ $Cname =~ s/-/_/g;
+ $Cname =~ s/\./_/g;
+ $Cname =~ s/ /_/g;
+ if ($Cname ne "" && defined($ln{$module.$Cname}))
+ { die "objects.txt:$o:There's already an object with long name ",$ln{$module.$Cname}," on line ",$order{$module.$Cname},"\n"; }
+ }
+ $Cname =~ s/\./_/g;
+ $Cname =~ s/-/_/g;
+ $Cname = $module.$Cname;
+ $ordern{$o} = $Cname;
+ $order{$Cname} = $o;
+ $sn{$Cname} = $mysn;
+ $ln{$Cname} = $myln;
+ $obj{$Cname} = $myoid;
+ if (!defined($nid{$Cname}))
+ {
+ $max_nid++;
+ $nid{$Cname} = $max_nid;
+ $nidn{$max_nid} = $Cname;
+print STDERR "Added OID $Cname\n";
+ }
+ $Cname="";
+ }
+close IN;
+
+open (NUMOUT,">$ARGV[1]") || die "Can't open output file $ARGV[1]";
+foreach (sort { $a <=> $b } keys %nidn)
+ {
+ print NUMOUT $nidn{$_},"\t\t",$_,"\n";
+ }
+close NUMOUT;
+
+open (OUT,">$ARGV[2]") || die "Can't open output file $ARGV[2]";
+print OUT <<'EOF';
+/* THIS FILE IS GENERATED FROM objects.txt by objects.pl via the
+ * following command:
+ * perl objects.pl objects.txt obj_mac.num ../../include/openssl/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
+
+EOF
+
+foreach (sort { $a <=> $b } keys %ordern)
+ {
+ $Cname=$ordern{$_};
+ print OUT "#define SN_",$Cname,"\t\t\"",$sn{$Cname},"\"\n" if $sn{$Cname} ne "";
+ print OUT "#define LN_",$Cname,"\t\t\"",$ln{$Cname},"\"\n" if $ln{$Cname} ne "";
+ print OUT "#define NID_",$Cname,"\t\t",$nid{$Cname},"\n" if $nid{$Cname} ne "";
+ print OUT "#define OBJ_",$Cname,"\t\t",$obj{$Cname},"\n" if $obj{$Cname} ne "";
+ print OUT "\n";
+ }
+
+close OUT;
+
+sub process_oid
+ {
+ local($oid)=@_;
+ local(@a,$oid_pref);
+
+ @a = split(/\s+/,$myoid);
+ $pref_oid = "";
+ $pref_sep = "";
+ if (!($a[0] =~ /^[0-9]+$/))
+ {
+ $a[0] =~ s/-/_/g;
+ if (!defined($obj{$a[0]}))
+ { die "$ARGV[0]:$o:Undefined identifier ",$a[0],"\n"; }
+ $pref_oid = "OBJ_" . $a[0];
+ $pref_sep = ",";
+ shift @a;
+ }
+ $oids = join('L,',@a) . "L";
+ if ($oids ne "L")
+ {
+ $oids = $pref_oid . $pref_sep . $oids;
+ }
+ else
+ {
+ $oids = $pref_oid;
+ }
+ return($oids);
+ }
diff --git a/src/crypto/obj/objects.txt b/src/crypto/obj/objects.txt
new file mode 100644
index 0000000..aeffc6c
--- /dev/null
+++ b/src/crypto/obj/objects.txt
@@ -0,0 +1,1334 @@
+# CCITT was renamed to ITU-T quite some time ago
+0 : ITU-T : itu-t
+!Alias ccitt itu-t
+
+1 : ISO : iso
+
+2 : JOINT-ISO-ITU-T : joint-iso-itu-t
+!Alias joint-iso-ccitt joint-iso-itu-t
+
+iso 2 : member-body : ISO Member Body
+
+iso 3 : identified-organization
+
+# HMAC OIDs
+identified-organization 6 1 5 5 8 1 1 : HMAC-MD5 : hmac-md5
+identified-organization 6 1 5 5 8 1 2 : HMAC-SHA1 : hmac-sha1
+
+identified-organization 132 : certicom-arc
+
+joint-iso-itu-t 23 : international-organizations : International Organizations
+
+international-organizations 43 : wap
+wap 1 : wap-wsg
+
+joint-iso-itu-t 5 1 5 : selected-attribute-types : Selected Attribute Types
+
+selected-attribute-types 55 : clearance
+
+member-body 840 : ISO-US : ISO US Member Body
+ISO-US 10040 : X9-57 : X9.57
+X9-57 4 : X9cm : X9.57 CM ?
+
+!Cname dsa
+X9cm 1 : DSA : dsaEncryption
+X9cm 3 : DSA-SHA1 : dsaWithSHA1
+
+
+ISO-US 10045 : ansi-X9-62 : ANSI X9.62
+!module X9-62
+!Alias id-fieldType ansi-X9-62 1
+X9-62_id-fieldType 1 : prime-field
+X9-62_id-fieldType 2 : characteristic-two-field
+X9-62_characteristic-two-field 3 : id-characteristic-two-basis
+X9-62_id-characteristic-two-basis 1 : onBasis
+X9-62_id-characteristic-two-basis 2 : tpBasis
+X9-62_id-characteristic-two-basis 3 : ppBasis
+!Alias id-publicKeyType ansi-X9-62 2
+X9-62_id-publicKeyType 1 : id-ecPublicKey
+!Alias ellipticCurve ansi-X9-62 3
+!Alias c-TwoCurve X9-62_ellipticCurve 0
+X9-62_c-TwoCurve 1 : c2pnb163v1
+X9-62_c-TwoCurve 2 : c2pnb163v2
+X9-62_c-TwoCurve 3 : c2pnb163v3
+X9-62_c-TwoCurve 4 : c2pnb176v1
+X9-62_c-TwoCurve 5 : c2tnb191v1
+X9-62_c-TwoCurve 6 : c2tnb191v2
+X9-62_c-TwoCurve 7 : c2tnb191v3
+X9-62_c-TwoCurve 8 : c2onb191v4
+X9-62_c-TwoCurve 9 : c2onb191v5
+X9-62_c-TwoCurve 10 : c2pnb208w1
+X9-62_c-TwoCurve 11 : c2tnb239v1
+X9-62_c-TwoCurve 12 : c2tnb239v2
+X9-62_c-TwoCurve 13 : c2tnb239v3
+X9-62_c-TwoCurve 14 : c2onb239v4
+X9-62_c-TwoCurve 15 : c2onb239v5
+X9-62_c-TwoCurve 16 : c2pnb272w1
+X9-62_c-TwoCurve 17 : c2pnb304w1
+X9-62_c-TwoCurve 18 : c2tnb359v1
+X9-62_c-TwoCurve 19 : c2pnb368w1
+X9-62_c-TwoCurve 20 : c2tnb431r1
+!Alias primeCurve X9-62_ellipticCurve 1
+X9-62_primeCurve 1 : prime192v1
+X9-62_primeCurve 2 : prime192v2
+X9-62_primeCurve 3 : prime192v3
+X9-62_primeCurve 4 : prime239v1
+X9-62_primeCurve 5 : prime239v2
+X9-62_primeCurve 6 : prime239v3
+X9-62_primeCurve 7 : prime256v1
+!Alias id-ecSigType ansi-X9-62 4
+!global
+X9-62_id-ecSigType 1 : ecdsa-with-SHA1
+X9-62_id-ecSigType 2 : ecdsa-with-Recommended
+X9-62_id-ecSigType 3 : ecdsa-with-Specified
+ecdsa-with-Specified 1 : ecdsa-with-SHA224
+ecdsa-with-Specified 2 : ecdsa-with-SHA256
+ecdsa-with-Specified 3 : ecdsa-with-SHA384
+ecdsa-with-Specified 4 : ecdsa-with-SHA512
+
+# SECG curve OIDs from "SEC 2: Recommended Elliptic Curve Domain Parameters"
+# (http://www.secg.org/)
+!Alias secg_ellipticCurve certicom-arc 0
+# SECG prime curves OIDs
+secg-ellipticCurve 6 : secp112r1
+secg-ellipticCurve 7 : secp112r2
+secg-ellipticCurve 28 : secp128r1
+secg-ellipticCurve 29 : secp128r2
+secg-ellipticCurve 9 : secp160k1
+secg-ellipticCurve 8 : secp160r1
+secg-ellipticCurve 30 : secp160r2
+secg-ellipticCurve 31 : secp192k1
+# NOTE: the curve secp192r1 is the same as prime192v1 defined above
+# and is therefore omitted
+secg-ellipticCurve 32 : secp224k1
+secg-ellipticCurve 33 : secp224r1
+secg-ellipticCurve 10 : secp256k1
+# NOTE: the curve secp256r1 is the same as prime256v1 defined above
+# and is therefore omitted
+secg-ellipticCurve 34 : secp384r1
+secg-ellipticCurve 35 : secp521r1
+# SECG characteristic two curves OIDs
+secg-ellipticCurve 4 : sect113r1
+secg-ellipticCurve 5 : sect113r2
+secg-ellipticCurve 22 : sect131r1
+secg-ellipticCurve 23 : sect131r2
+secg-ellipticCurve 1 : sect163k1
+secg-ellipticCurve 2 : sect163r1
+secg-ellipticCurve 15 : sect163r2
+secg-ellipticCurve 24 : sect193r1
+secg-ellipticCurve 25 : sect193r2
+secg-ellipticCurve 26 : sect233k1
+secg-ellipticCurve 27 : sect233r1
+secg-ellipticCurve 3 : sect239k1
+secg-ellipticCurve 16 : sect283k1
+secg-ellipticCurve 17 : sect283r1
+secg-ellipticCurve 36 : sect409k1
+secg-ellipticCurve 37 : sect409r1
+secg-ellipticCurve 38 : sect571k1
+secg-ellipticCurve 39 : sect571r1
+
+# WAP/TLS curve OIDs (http://www.wapforum.org/)
+!Alias wap-wsg-idm-ecid wap-wsg 4
+wap-wsg-idm-ecid 1 : wap-wsg-idm-ecid-wtls1
+wap-wsg-idm-ecid 3 : wap-wsg-idm-ecid-wtls3
+wap-wsg-idm-ecid 4 : wap-wsg-idm-ecid-wtls4
+wap-wsg-idm-ecid 5 : wap-wsg-idm-ecid-wtls5
+wap-wsg-idm-ecid 6 : wap-wsg-idm-ecid-wtls6
+wap-wsg-idm-ecid 7 : wap-wsg-idm-ecid-wtls7
+wap-wsg-idm-ecid 8 : wap-wsg-idm-ecid-wtls8
+wap-wsg-idm-ecid 9 : wap-wsg-idm-ecid-wtls9
+wap-wsg-idm-ecid 10 : wap-wsg-idm-ecid-wtls10
+wap-wsg-idm-ecid 11 : wap-wsg-idm-ecid-wtls11
+wap-wsg-idm-ecid 12 : wap-wsg-idm-ecid-wtls12
+
+
+ISO-US 113533 7 66 10 : CAST5-CBC : cast5-cbc
+ : CAST5-ECB : cast5-ecb
+!Cname cast5-cfb64
+ : CAST5-CFB : cast5-cfb
+!Cname cast5-ofb64
+ : CAST5-OFB : cast5-ofb
+!Cname pbeWithMD5AndCast5-CBC
+ISO-US 113533 7 66 12 : : pbeWithMD5AndCast5CBC
+
+# Macs for CMP and CRMF
+ISO-US 113533 7 66 13 : id-PasswordBasedMAC : password based MAC
+ISO-US 113533 7 66 30 : id-DHBasedMac : Diffie-Hellman based MAC
+
+ISO-US 113549 : rsadsi : RSA Data Security, Inc.
+
+rsadsi 1 : pkcs : RSA Data Security, Inc. PKCS
+
+pkcs 1 : pkcs1
+pkcs1 1 : : rsaEncryption
+pkcs1 2 : RSA-MD2 : md2WithRSAEncryption
+pkcs1 3 : RSA-MD4 : md4WithRSAEncryption
+pkcs1 4 : RSA-MD5 : md5WithRSAEncryption
+pkcs1 5 : RSA-SHA1 : sha1WithRSAEncryption
+# According to PKCS #1 version 2.1
+pkcs1 7 : RSAES-OAEP : rsaesOaep
+pkcs1 8 : MGF1 : mgf1
+pkcs1 9 : PSPECIFIED : pSpecified
+pkcs1 10 : RSASSA-PSS : rsassaPss
+
+pkcs1 11 : RSA-SHA256 : sha256WithRSAEncryption
+pkcs1 12 : RSA-SHA384 : sha384WithRSAEncryption
+pkcs1 13 : RSA-SHA512 : sha512WithRSAEncryption
+pkcs1 14 : RSA-SHA224 : sha224WithRSAEncryption
+
+pkcs 3 : pkcs3
+pkcs3 1 : : dhKeyAgreement
+
+pkcs 5 : pkcs5
+pkcs5 1 : PBE-MD2-DES : pbeWithMD2AndDES-CBC
+pkcs5 3 : PBE-MD5-DES : pbeWithMD5AndDES-CBC
+pkcs5 4 : PBE-MD2-RC2-64 : pbeWithMD2AndRC2-CBC
+pkcs5 6 : PBE-MD5-RC2-64 : pbeWithMD5AndRC2-CBC
+pkcs5 10 : PBE-SHA1-DES : pbeWithSHA1AndDES-CBC
+pkcs5 11 : PBE-SHA1-RC2-64 : pbeWithSHA1AndRC2-CBC
+!Cname id_pbkdf2
+pkcs5 12 : : PBKDF2
+!Cname pbes2
+pkcs5 13 : : PBES2
+!Cname pbmac1
+pkcs5 14 : : PBMAC1
+
+pkcs 7 : pkcs7
+pkcs7 1 : : pkcs7-data
+!Cname pkcs7-signed
+pkcs7 2 : : pkcs7-signedData
+!Cname pkcs7-enveloped
+pkcs7 3 : : pkcs7-envelopedData
+!Cname pkcs7-signedAndEnveloped
+pkcs7 4 : : pkcs7-signedAndEnvelopedData
+!Cname pkcs7-digest
+pkcs7 5 : : pkcs7-digestData
+!Cname pkcs7-encrypted
+pkcs7 6 : : pkcs7-encryptedData
+
+pkcs 9 : pkcs9
+!module pkcs9
+pkcs9 1 : : emailAddress
+pkcs9 2 : : unstructuredName
+pkcs9 3 : : contentType
+pkcs9 4 : : messageDigest
+pkcs9 5 : : signingTime
+pkcs9 6 : : countersignature
+pkcs9 7 : : challengePassword
+pkcs9 8 : : unstructuredAddress
+!Cname extCertAttributes
+pkcs9 9 : : extendedCertificateAttributes
+!global
+
+!Cname ext-req
+pkcs9 14 : extReq : Extension Request
+
+!Cname SMIMECapabilities
+pkcs9 15 : SMIME-CAPS : S/MIME Capabilities
+
+# S/MIME
+!Cname SMIME
+pkcs9 16 : SMIME : S/MIME
+SMIME 0 : id-smime-mod
+SMIME 1 : id-smime-ct
+SMIME 2 : id-smime-aa
+SMIME 3 : id-smime-alg
+SMIME 4 : id-smime-cd
+SMIME 5 : id-smime-spq
+SMIME 6 : id-smime-cti
+
+# S/MIME Modules
+id-smime-mod 1 : id-smime-mod-cms
+id-smime-mod 2 : id-smime-mod-ess
+id-smime-mod 3 : id-smime-mod-oid
+id-smime-mod 4 : id-smime-mod-msg-v3
+id-smime-mod 5 : id-smime-mod-ets-eSignature-88
+id-smime-mod 6 : id-smime-mod-ets-eSignature-97
+id-smime-mod 7 : id-smime-mod-ets-eSigPolicy-88
+id-smime-mod 8 : id-smime-mod-ets-eSigPolicy-97
+
+# S/MIME Content Types
+id-smime-ct 1 : id-smime-ct-receipt
+id-smime-ct 2 : id-smime-ct-authData
+id-smime-ct 3 : id-smime-ct-publishCert
+id-smime-ct 4 : id-smime-ct-TSTInfo
+id-smime-ct 5 : id-smime-ct-TDTInfo
+id-smime-ct 6 : id-smime-ct-contentInfo
+id-smime-ct 7 : id-smime-ct-DVCSRequestData
+id-smime-ct 8 : id-smime-ct-DVCSResponseData
+id-smime-ct 9 : id-smime-ct-compressedData
+id-smime-ct 27 : id-ct-asciiTextWithCRLF
+
+# S/MIME Attributes
+id-smime-aa 1 : id-smime-aa-receiptRequest
+id-smime-aa 2 : id-smime-aa-securityLabel
+id-smime-aa 3 : id-smime-aa-mlExpandHistory
+id-smime-aa 4 : id-smime-aa-contentHint
+id-smime-aa 5 : id-smime-aa-msgSigDigest
+# obsolete
+id-smime-aa 6 : id-smime-aa-encapContentType
+id-smime-aa 7 : id-smime-aa-contentIdentifier
+# obsolete
+id-smime-aa 8 : id-smime-aa-macValue
+id-smime-aa 9 : id-smime-aa-equivalentLabels
+id-smime-aa 10 : id-smime-aa-contentReference
+id-smime-aa 11 : id-smime-aa-encrypKeyPref
+id-smime-aa 12 : id-smime-aa-signingCertificate
+id-smime-aa 13 : id-smime-aa-smimeEncryptCerts
+id-smime-aa 14 : id-smime-aa-timeStampToken
+id-smime-aa 15 : id-smime-aa-ets-sigPolicyId
+id-smime-aa 16 : id-smime-aa-ets-commitmentType
+id-smime-aa 17 : id-smime-aa-ets-signerLocation
+id-smime-aa 18 : id-smime-aa-ets-signerAttr
+id-smime-aa 19 : id-smime-aa-ets-otherSigCert
+id-smime-aa 20 : id-smime-aa-ets-contentTimestamp
+id-smime-aa 21 : id-smime-aa-ets-CertificateRefs
+id-smime-aa 22 : id-smime-aa-ets-RevocationRefs
+id-smime-aa 23 : id-smime-aa-ets-certValues
+id-smime-aa 24 : id-smime-aa-ets-revocationValues
+id-smime-aa 25 : id-smime-aa-ets-escTimeStamp
+id-smime-aa 26 : id-smime-aa-ets-certCRLTimestamp
+id-smime-aa 27 : id-smime-aa-ets-archiveTimeStamp
+id-smime-aa 28 : id-smime-aa-signatureType
+id-smime-aa 29 : id-smime-aa-dvcs-dvc
+
+# S/MIME Algorithm Identifiers
+# obsolete
+id-smime-alg 1 : id-smime-alg-ESDHwith3DES
+# obsolete
+id-smime-alg 2 : id-smime-alg-ESDHwithRC2
+# obsolete
+id-smime-alg 3 : id-smime-alg-3DESwrap
+# obsolete
+id-smime-alg 4 : id-smime-alg-RC2wrap
+id-smime-alg 5 : id-smime-alg-ESDH
+id-smime-alg 6 : id-smime-alg-CMS3DESwrap
+id-smime-alg 7 : id-smime-alg-CMSRC2wrap
+id-smime-alg 9 : id-alg-PWRI-KEK
+
+# S/MIME Certificate Distribution
+id-smime-cd 1 : id-smime-cd-ldap
+
+# S/MIME Signature Policy Qualifier
+id-smime-spq 1 : id-smime-spq-ets-sqt-uri
+id-smime-spq 2 : id-smime-spq-ets-sqt-unotice
+
+# S/MIME Commitment Type Identifier
+id-smime-cti 1 : id-smime-cti-ets-proofOfOrigin
+id-smime-cti 2 : id-smime-cti-ets-proofOfReceipt
+id-smime-cti 3 : id-smime-cti-ets-proofOfDelivery
+id-smime-cti 4 : id-smime-cti-ets-proofOfSender
+id-smime-cti 5 : id-smime-cti-ets-proofOfApproval
+id-smime-cti 6 : id-smime-cti-ets-proofOfCreation
+
+pkcs9 20 : : friendlyName
+pkcs9 21 : : localKeyID
+!Cname ms-csp-name
+1 3 6 1 4 1 311 17 1 : CSPName : Microsoft CSP Name
+1 3 6 1 4 1 311 17 2 : LocalKeySet : Microsoft Local Key set
+!Alias certTypes pkcs9 22
+certTypes 1 : : x509Certificate
+certTypes 2 : : sdsiCertificate
+!Alias crlTypes pkcs9 23
+crlTypes 1 : : x509Crl
+
+!Alias pkcs12 pkcs 12
+!Alias pkcs12-pbeids pkcs12 1
+
+!Cname pbe-WithSHA1And128BitRC4
+pkcs12-pbeids 1 : PBE-SHA1-RC4-128 : pbeWithSHA1And128BitRC4
+!Cname pbe-WithSHA1And40BitRC4
+pkcs12-pbeids 2 : PBE-SHA1-RC4-40 : pbeWithSHA1And40BitRC4
+!Cname pbe-WithSHA1And3_Key_TripleDES-CBC
+pkcs12-pbeids 3 : PBE-SHA1-3DES : pbeWithSHA1And3-KeyTripleDES-CBC
+!Cname pbe-WithSHA1And2_Key_TripleDES-CBC
+pkcs12-pbeids 4 : PBE-SHA1-2DES : pbeWithSHA1And2-KeyTripleDES-CBC
+!Cname pbe-WithSHA1And128BitRC2-CBC
+pkcs12-pbeids 5 : PBE-SHA1-RC2-128 : pbeWithSHA1And128BitRC2-CBC
+!Cname pbe-WithSHA1And40BitRC2-CBC
+pkcs12-pbeids 6 : PBE-SHA1-RC2-40 : pbeWithSHA1And40BitRC2-CBC
+
+!Alias pkcs12-Version1 pkcs12 10
+!Alias pkcs12-BagIds pkcs12-Version1 1
+pkcs12-BagIds 1 : : keyBag
+pkcs12-BagIds 2 : : pkcs8ShroudedKeyBag
+pkcs12-BagIds 3 : : certBag
+pkcs12-BagIds 4 : : crlBag
+pkcs12-BagIds 5 : : secretBag
+pkcs12-BagIds 6 : : safeContentsBag
+
+rsadsi 2 2 : MD2 : md2
+rsadsi 2 4 : MD4 : md4
+rsadsi 2 5 : MD5 : md5
+ : MD5-SHA1 : md5-sha1
+rsadsi 2 6 : : hmacWithMD5
+rsadsi 2 7 : : hmacWithSHA1
+
+# From RFC4231
+rsadsi 2 8 : : hmacWithSHA224
+rsadsi 2 9 : : hmacWithSHA256
+rsadsi 2 10 : : hmacWithSHA384
+rsadsi 2 11 : : hmacWithSHA512
+
+rsadsi 3 2 : RC2-CBC : rc2-cbc
+ : RC2-ECB : rc2-ecb
+!Cname rc2-cfb64
+ : RC2-CFB : rc2-cfb
+!Cname rc2-ofb64
+ : RC2-OFB : rc2-ofb
+ : RC2-40-CBC : rc2-40-cbc
+ : RC2-64-CBC : rc2-64-cbc
+rsadsi 3 4 : RC4 : rc4
+ : RC4-40 : rc4-40
+rsadsi 3 7 : DES-EDE3-CBC : des-ede3-cbc
+rsadsi 3 8 : RC5-CBC : rc5-cbc
+ : RC5-ECB : rc5-ecb
+!Cname rc5-cfb64
+ : RC5-CFB : rc5-cfb
+!Cname rc5-ofb64
+ : RC5-OFB : rc5-ofb
+
+!Cname ms-ext-req
+1 3 6 1 4 1 311 2 1 14 : msExtReq : Microsoft Extension Request
+!Cname ms-code-ind
+1 3 6 1 4 1 311 2 1 21 : msCodeInd : Microsoft Individual Code Signing
+!Cname ms-code-com
+1 3 6 1 4 1 311 2 1 22 : msCodeCom : Microsoft Commercial Code Signing
+!Cname ms-ctl-sign
+1 3 6 1 4 1 311 10 3 1 : msCTLSign : Microsoft Trust List Signing
+!Cname ms-sgc
+1 3 6 1 4 1 311 10 3 3 : msSGC : Microsoft Server Gated Crypto
+!Cname ms-efs
+1 3 6 1 4 1 311 10 3 4 : msEFS : Microsoft Encrypted File System
+!Cname ms-smartcard-login
+1 3 6 1 4 1 311 20 2 2 : msSmartcardLogin : Microsoft Smartcardlogin
+!Cname ms-upn
+1 3 6 1 4 1 311 20 2 3 : msUPN : Microsoft Universal Principal Name
+
+1 3 6 1 4 1 188 7 1 1 2 : IDEA-CBC : idea-cbc
+ : IDEA-ECB : idea-ecb
+!Cname idea-cfb64
+ : IDEA-CFB : idea-cfb
+!Cname idea-ofb64
+ : IDEA-OFB : idea-ofb
+
+1 3 6 1 4 1 3029 1 2 : BF-CBC : bf-cbc
+ : BF-ECB : bf-ecb
+!Cname bf-cfb64
+ : BF-CFB : bf-cfb
+!Cname bf-ofb64
+ : BF-OFB : bf-ofb
+
+!Cname id-pkix
+1 3 6 1 5 5 7 : PKIX
+
+# PKIX Arcs
+id-pkix 0 : id-pkix-mod
+id-pkix 1 : id-pe
+id-pkix 2 : id-qt
+id-pkix 3 : id-kp
+id-pkix 4 : id-it
+id-pkix 5 : id-pkip
+id-pkix 6 : id-alg
+id-pkix 7 : id-cmc
+id-pkix 8 : id-on
+id-pkix 9 : id-pda
+id-pkix 10 : id-aca
+id-pkix 11 : id-qcs
+id-pkix 12 : id-cct
+id-pkix 21 : id-ppl
+id-pkix 48 : id-ad
+
+# PKIX Modules
+id-pkix-mod 1 : id-pkix1-explicit-88
+id-pkix-mod 2 : id-pkix1-implicit-88
+id-pkix-mod 3 : id-pkix1-explicit-93
+id-pkix-mod 4 : id-pkix1-implicit-93
+id-pkix-mod 5 : id-mod-crmf
+id-pkix-mod 6 : id-mod-cmc
+id-pkix-mod 7 : id-mod-kea-profile-88
+id-pkix-mod 8 : id-mod-kea-profile-93
+id-pkix-mod 9 : id-mod-cmp
+id-pkix-mod 10 : id-mod-qualified-cert-88
+id-pkix-mod 11 : id-mod-qualified-cert-93
+id-pkix-mod 12 : id-mod-attribute-cert
+id-pkix-mod 13 : id-mod-timestamp-protocol
+id-pkix-mod 14 : id-mod-ocsp
+id-pkix-mod 15 : id-mod-dvcs
+id-pkix-mod 16 : id-mod-cmp2000
+
+# PKIX Private Extensions
+!Cname info-access
+id-pe 1 : authorityInfoAccess : Authority Information Access
+id-pe 2 : biometricInfo : Biometric Info
+id-pe 3 : qcStatements
+id-pe 4 : ac-auditEntity
+id-pe 5 : ac-targeting
+id-pe 6 : aaControls
+id-pe 7 : sbgp-ipAddrBlock
+id-pe 8 : sbgp-autonomousSysNum
+id-pe 9 : sbgp-routerIdentifier
+id-pe 10 : ac-proxying
+!Cname sinfo-access
+id-pe 11 : subjectInfoAccess : Subject Information Access
+id-pe 14 : proxyCertInfo : Proxy Certificate Information
+
+# PKIX policyQualifiers for Internet policy qualifiers
+id-qt 1 : id-qt-cps : Policy Qualifier CPS
+id-qt 2 : id-qt-unotice : Policy Qualifier User Notice
+id-qt 3 : textNotice
+
+# PKIX key purpose identifiers
+!Cname server-auth
+id-kp 1 : serverAuth : TLS Web Server Authentication
+!Cname client-auth
+id-kp 2 : clientAuth : TLS Web Client Authentication
+!Cname code-sign
+id-kp 3 : codeSigning : Code Signing
+!Cname email-protect
+id-kp 4 : emailProtection : E-mail Protection
+id-kp 5 : ipsecEndSystem : IPSec End System
+id-kp 6 : ipsecTunnel : IPSec Tunnel
+id-kp 7 : ipsecUser : IPSec User
+!Cname time-stamp
+id-kp 8 : timeStamping : Time Stamping
+# From OCSP spec RFC2560
+!Cname OCSP-sign
+id-kp 9 : OCSPSigning : OCSP Signing
+id-kp 10 : DVCS : dvcs
+
+# CMP information types
+id-it 1 : id-it-caProtEncCert
+id-it 2 : id-it-signKeyPairTypes
+id-it 3 : id-it-encKeyPairTypes
+id-it 4 : id-it-preferredSymmAlg
+id-it 5 : id-it-caKeyUpdateInfo
+id-it 6 : id-it-currentCRL
+id-it 7 : id-it-unsupportedOIDs
+# obsolete
+id-it 8 : id-it-subscriptionRequest
+# obsolete
+id-it 9 : id-it-subscriptionResponse
+id-it 10 : id-it-keyPairParamReq
+id-it 11 : id-it-keyPairParamRep
+id-it 12 : id-it-revPassphrase
+id-it 13 : id-it-implicitConfirm
+id-it 14 : id-it-confirmWaitTime
+id-it 15 : id-it-origPKIMessage
+id-it 16 : id-it-suppLangTags
+
+# CRMF registration
+id-pkip 1 : id-regCtrl
+id-pkip 2 : id-regInfo
+
+# CRMF registration controls
+id-regCtrl 1 : id-regCtrl-regToken
+id-regCtrl 2 : id-regCtrl-authenticator
+id-regCtrl 3 : id-regCtrl-pkiPublicationInfo
+id-regCtrl 4 : id-regCtrl-pkiArchiveOptions
+id-regCtrl 5 : id-regCtrl-oldCertID
+id-regCtrl 6 : id-regCtrl-protocolEncrKey
+
+# CRMF registration information
+id-regInfo 1 : id-regInfo-utf8Pairs
+id-regInfo 2 : id-regInfo-certReq
+
+# algorithms
+id-alg 1 : id-alg-des40
+id-alg 2 : id-alg-noSignature
+id-alg 3 : id-alg-dh-sig-hmac-sha1
+id-alg 4 : id-alg-dh-pop
+
+# CMC controls
+id-cmc 1 : id-cmc-statusInfo
+id-cmc 2 : id-cmc-identification
+id-cmc 3 : id-cmc-identityProof
+id-cmc 4 : id-cmc-dataReturn
+id-cmc 5 : id-cmc-transactionId
+id-cmc 6 : id-cmc-senderNonce
+id-cmc 7 : id-cmc-recipientNonce
+id-cmc 8 : id-cmc-addExtensions
+id-cmc 9 : id-cmc-encryptedPOP
+id-cmc 10 : id-cmc-decryptedPOP
+id-cmc 11 : id-cmc-lraPOPWitness
+id-cmc 15 : id-cmc-getCert
+id-cmc 16 : id-cmc-getCRL
+id-cmc 17 : id-cmc-revokeRequest
+id-cmc 18 : id-cmc-regInfo
+id-cmc 19 : id-cmc-responseInfo
+id-cmc 21 : id-cmc-queryPending
+id-cmc 22 : id-cmc-popLinkRandom
+id-cmc 23 : id-cmc-popLinkWitness
+id-cmc 24 : id-cmc-confirmCertAcceptance
+
+# other names
+id-on 1 : id-on-personalData
+id-on 3 : id-on-permanentIdentifier : Permanent Identifier
+
+# personal data attributes
+id-pda 1 : id-pda-dateOfBirth
+id-pda 2 : id-pda-placeOfBirth
+id-pda 3 : id-pda-gender
+id-pda 4 : id-pda-countryOfCitizenship
+id-pda 5 : id-pda-countryOfResidence
+
+# attribute certificate attributes
+id-aca 1 : id-aca-authenticationInfo
+id-aca 2 : id-aca-accessIdentity
+id-aca 3 : id-aca-chargingIdentity
+id-aca 4 : id-aca-group
+# attention : the following seems to be obsolete, replace by 'role'
+id-aca 5 : id-aca-role
+id-aca 6 : id-aca-encAttrs
+
+# qualified certificate statements
+id-qcs 1 : id-qcs-pkixQCSyntax-v1
+
+# CMC content types
+id-cct 1 : id-cct-crs
+id-cct 2 : id-cct-PKIData
+id-cct 3 : id-cct-PKIResponse
+
+# Predefined Proxy Certificate policy languages
+id-ppl 0 : id-ppl-anyLanguage : Any language
+id-ppl 1 : id-ppl-inheritAll : Inherit all
+id-ppl 2 : id-ppl-independent : Independent
+
+# access descriptors for authority info access extension
+!Cname ad-OCSP
+id-ad 1 : OCSP : OCSP
+!Cname ad-ca-issuers
+id-ad 2 : caIssuers : CA Issuers
+!Cname ad-timeStamping
+id-ad 3 : ad_timestamping : AD Time Stamping
+!Cname ad-dvcs
+id-ad 4 : AD_DVCS : ad dvcs
+id-ad 5 : caRepository : CA Repository
+
+
+!Alias id-pkix-OCSP ad-OCSP
+!module id-pkix-OCSP
+!Cname basic
+id-pkix-OCSP 1 : basicOCSPResponse : Basic OCSP Response
+id-pkix-OCSP 2 : Nonce : OCSP Nonce
+id-pkix-OCSP 3 : CrlID : OCSP CRL ID
+id-pkix-OCSP 4 : acceptableResponses : Acceptable OCSP Responses
+id-pkix-OCSP 5 : noCheck : OCSP No Check
+id-pkix-OCSP 6 : archiveCutoff : OCSP Archive Cutoff
+id-pkix-OCSP 7 : serviceLocator : OCSP Service Locator
+id-pkix-OCSP 8 : extendedStatus : Extended OCSP Status
+id-pkix-OCSP 9 : valid
+id-pkix-OCSP 10 : path
+id-pkix-OCSP 11 : trustRoot : Trust Root
+!global
+
+1 3 14 3 2 : algorithm : algorithm
+algorithm 3 : RSA-NP-MD5 : md5WithRSA
+algorithm 6 : DES-ECB : des-ecb
+algorithm 7 : DES-CBC : des-cbc
+!Cname des-ofb64
+algorithm 8 : DES-OFB : des-ofb
+!Cname des-cfb64
+algorithm 9 : DES-CFB : des-cfb
+algorithm 11 : rsaSignature
+!Cname dsa-2
+algorithm 12 : DSA-old : dsaEncryption-old
+algorithm 13 : DSA-SHA : dsaWithSHA
+algorithm 15 : RSA-SHA : shaWithRSAEncryption
+!Cname des-ede-ecb
+algorithm 17 : DES-EDE : des-ede
+!Cname des-ede3-ecb
+ : DES-EDE3 : des-ede3
+ : DES-EDE-CBC : des-ede-cbc
+!Cname des-ede-cfb64
+ : DES-EDE-CFB : des-ede-cfb
+!Cname des-ede3-cfb64
+ : DES-EDE3-CFB : des-ede3-cfb
+!Cname des-ede-ofb64
+ : DES-EDE-OFB : des-ede-ofb
+!Cname des-ede3-ofb64
+ : DES-EDE3-OFB : des-ede3-ofb
+ : DESX-CBC : desx-cbc
+algorithm 18 : SHA : sha
+algorithm 26 : SHA1 : sha1
+!Cname dsaWithSHA1-2
+algorithm 27 : DSA-SHA1-old : dsaWithSHA1-old
+algorithm 29 : RSA-SHA1-2 : sha1WithRSA
+
+1 3 36 3 2 1 : RIPEMD160 : ripemd160
+1 3 36 3 3 1 2 : RSA-RIPEMD160 : ripemd160WithRSA
+
+!Cname sxnet
+1 3 101 1 4 1 : SXNetID : Strong Extranet ID
+
+2 5 : X500 : directory services (X.500)
+
+X500 4 : X509
+X509 3 : CN : commonName
+X509 4 : SN : surname
+X509 5 : : serialNumber
+X509 6 : C : countryName
+X509 7 : L : localityName
+X509 8 : ST : stateOrProvinceName
+X509 9 : street : streetAddress
+X509 10 : O : organizationName
+X509 11 : OU : organizationalUnitName
+X509 12 : title : title
+X509 13 : : description
+X509 14 : : searchGuide
+X509 15 : : businessCategory
+X509 16 : : postalAddress
+X509 17 : : postalCode
+X509 18 : : postOfficeBox
+X509 19 : : physicalDeliveryOfficeName
+X509 20 : : telephoneNumber
+X509 21 : : telexNumber
+X509 22 : : teletexTerminalIdentifier
+X509 23 : : facsimileTelephoneNumber
+X509 24 : : x121Address
+X509 25 : : internationaliSDNNumber
+X509 26 : : registeredAddress
+X509 27 : : destinationIndicator
+X509 28 : : preferredDeliveryMethod
+X509 29 : : presentationAddress
+X509 30 : : supportedApplicationContext
+X509 31 : member :
+X509 32 : owner :
+X509 33 : : roleOccupant
+X509 34 : seeAlso :
+X509 35 : : userPassword
+X509 36 : : userCertificate
+X509 37 : : cACertificate
+X509 38 : : authorityRevocationList
+X509 39 : : certificateRevocationList
+X509 40 : : crossCertificatePair
+X509 41 : name : name
+X509 42 : GN : givenName
+X509 43 : initials : initials
+X509 44 : : generationQualifier
+X509 45 : : x500UniqueIdentifier
+X509 46 : dnQualifier : dnQualifier
+X509 47 : : enhancedSearchGuide
+X509 48 : : protocolInformation
+X509 49 : : distinguishedName
+X509 50 : : uniqueMember
+X509 51 : : houseIdentifier
+X509 52 : : supportedAlgorithms
+X509 53 : : deltaRevocationList
+X509 54 : dmdName :
+X509 65 : : pseudonym
+X509 72 : role : role
+
+X500 8 : X500algorithms : directory services - algorithms
+X500algorithms 1 1 : RSA : rsa
+X500algorithms 3 100 : RSA-MDC2 : mdc2WithRSA
+X500algorithms 3 101 : MDC2 : mdc2
+
+X500 29 : id-ce
+!Cname subject-directory-attributes
+id-ce 9 : subjectDirectoryAttributes : X509v3 Subject Directory Attributes
+!Cname subject-key-identifier
+id-ce 14 : subjectKeyIdentifier : X509v3 Subject Key Identifier
+!Cname key-usage
+id-ce 15 : keyUsage : X509v3 Key Usage
+!Cname private-key-usage-period
+id-ce 16 : privateKeyUsagePeriod : X509v3 Private Key Usage Period
+!Cname subject-alt-name
+id-ce 17 : subjectAltName : X509v3 Subject Alternative Name
+!Cname issuer-alt-name
+id-ce 18 : issuerAltName : X509v3 Issuer Alternative Name
+!Cname basic-constraints
+id-ce 19 : basicConstraints : X509v3 Basic Constraints
+!Cname crl-number
+id-ce 20 : crlNumber : X509v3 CRL Number
+!Cname crl-reason
+id-ce 21 : CRLReason : X509v3 CRL Reason Code
+!Cname invalidity-date
+id-ce 24 : invalidityDate : Invalidity Date
+!Cname delta-crl
+id-ce 27 : deltaCRL : X509v3 Delta CRL Indicator
+!Cname issuing-distribution-point
+id-ce 28 : issuingDistributionPoint : X509v3 Issuing Distrubution Point
+!Cname certificate-issuer
+id-ce 29 : certificateIssuer : X509v3 Certificate Issuer
+!Cname name-constraints
+id-ce 30 : nameConstraints : X509v3 Name Constraints
+!Cname crl-distribution-points
+id-ce 31 : crlDistributionPoints : X509v3 CRL Distribution Points
+!Cname certificate-policies
+id-ce 32 : certificatePolicies : X509v3 Certificate Policies
+!Cname any-policy
+certificate-policies 0 : anyPolicy : X509v3 Any Policy
+!Cname policy-mappings
+id-ce 33 : policyMappings : X509v3 Policy Mappings
+!Cname authority-key-identifier
+id-ce 35 : authorityKeyIdentifier : X509v3 Authority Key Identifier
+!Cname policy-constraints
+id-ce 36 : policyConstraints : X509v3 Policy Constraints
+!Cname ext-key-usage
+id-ce 37 : extendedKeyUsage : X509v3 Extended Key Usage
+!Cname freshest-crl
+id-ce 46 : freshestCRL : X509v3 Freshest CRL
+!Cname inhibit-any-policy
+id-ce 54 : inhibitAnyPolicy : X509v3 Inhibit Any Policy
+!Cname target-information
+id-ce 55 : targetInformation : X509v3 AC Targeting
+!Cname no-rev-avail
+id-ce 56 : noRevAvail : X509v3 No Revocation Available
+
+# From RFC5280
+ext-key-usage 0 : anyExtendedKeyUsage : Any Extended Key Usage
+
+
+!Cname netscape
+2 16 840 1 113730 : Netscape : Netscape Communications Corp.
+!Cname netscape-cert-extension
+netscape 1 : nsCertExt : Netscape Certificate Extension
+!Cname netscape-data-type
+netscape 2 : nsDataType : Netscape Data Type
+!Cname netscape-cert-type
+netscape-cert-extension 1 : nsCertType : Netscape Cert Type
+!Cname netscape-base-url
+netscape-cert-extension 2 : nsBaseUrl : Netscape Base Url
+!Cname netscape-revocation-url
+netscape-cert-extension 3 : nsRevocationUrl : Netscape Revocation Url
+!Cname netscape-ca-revocation-url
+netscape-cert-extension 4 : nsCaRevocationUrl : Netscape CA Revocation Url
+!Cname netscape-renewal-url
+netscape-cert-extension 7 : nsRenewalUrl : Netscape Renewal Url
+!Cname netscape-ca-policy-url
+netscape-cert-extension 8 : nsCaPolicyUrl : Netscape CA Policy Url
+!Cname netscape-ssl-server-name
+netscape-cert-extension 12 : nsSslServerName : Netscape SSL Server Name
+!Cname netscape-comment
+netscape-cert-extension 13 : nsComment : Netscape Comment
+!Cname netscape-cert-sequence
+netscape-data-type 5 : nsCertSequence : Netscape Certificate Sequence
+!Cname ns-sgc
+netscape 4 1 : nsSGC : Netscape Server Gated Crypto
+
+# iso(1)
+iso 3 : ORG : org
+org 6 : DOD : dod
+dod 1 : IANA : iana
+!Alias internet iana
+
+internet 1 : directory : Directory
+internet 2 : mgmt : Management
+internet 3 : experimental : Experimental
+internet 4 : private : Private
+internet 5 : security : Security
+internet 6 : snmpv2 : SNMPv2
+# Documents refer to "internet 7" as "mail". This however leads to ambiguities
+# with RFC2798, Section 9.1.3, where "mail" is defined as the short name for
+# rfc822Mailbox. The short name is therefore here left out for a reason.
+# Subclasses of "mail", e.g. "MIME MHS" don't consitute a problem, as
+# references are realized via long name "Mail" (with capital M).
+internet 7 : : Mail
+
+Private 1 : enterprises : Enterprises
+
+# RFC 2247
+Enterprises 1466 344 : dcobject : dcObject
+
+# RFC 1495
+Mail 1 : mime-mhs : MIME MHS
+mime-mhs 1 : mime-mhs-headings : mime-mhs-headings
+mime-mhs 2 : mime-mhs-bodies : mime-mhs-bodies
+mime-mhs-headings 1 : id-hex-partial-message : id-hex-partial-message
+mime-mhs-headings 2 : id-hex-multipart-message : id-hex-multipart-message
+
+# What the hell are these OIDs, really?
+!Cname rle-compression
+1 1 1 1 666 1 : RLE : run length compression
+!Cname zlib-compression
+id-smime-alg 8 : ZLIB : zlib compression
+
+# AES aka Rijndael
+
+!Alias csor 2 16 840 1 101 3
+!Alias nistAlgorithms csor 4
+!Alias aes nistAlgorithms 1
+
+aes 1 : AES-128-ECB : aes-128-ecb
+aes 2 : AES-128-CBC : aes-128-cbc
+!Cname aes-128-ofb128
+aes 3 : AES-128-OFB : aes-128-ofb
+!Cname aes-128-cfb128
+aes 4 : AES-128-CFB : aes-128-cfb
+aes 5 : id-aes128-wrap
+aes 6 : id-aes128-GCM : aes-128-gcm
+aes 7 : id-aes128-CCM : aes-128-ccm
+aes 8 : id-aes128-wrap-pad
+
+aes 21 : AES-192-ECB : aes-192-ecb
+aes 22 : AES-192-CBC : aes-192-cbc
+!Cname aes-192-ofb128
+aes 23 : AES-192-OFB : aes-192-ofb
+!Cname aes-192-cfb128
+aes 24 : AES-192-CFB : aes-192-cfb
+aes 25 : id-aes192-wrap
+aes 26 : id-aes192-GCM : aes-192-gcm
+aes 27 : id-aes192-CCM : aes-192-ccm
+aes 28 : id-aes192-wrap-pad
+
+aes 41 : AES-256-ECB : aes-256-ecb
+aes 42 : AES-256-CBC : aes-256-cbc
+!Cname aes-256-ofb128
+aes 43 : AES-256-OFB : aes-256-ofb
+!Cname aes-256-cfb128
+aes 44 : AES-256-CFB : aes-256-cfb
+aes 45 : id-aes256-wrap
+aes 46 : id-aes256-GCM : aes-256-gcm
+aes 47 : id-aes256-CCM : aes-256-ccm
+aes 48 : id-aes256-wrap-pad
+
+# There are no OIDs for these modes...
+
+ : AES-128-CFB1 : aes-128-cfb1
+ : AES-192-CFB1 : aes-192-cfb1
+ : AES-256-CFB1 : aes-256-cfb1
+ : AES-128-CFB8 : aes-128-cfb8
+ : AES-192-CFB8 : aes-192-cfb8
+ : AES-256-CFB8 : aes-256-cfb8
+ : AES-128-CTR : aes-128-ctr
+ : AES-192-CTR : aes-192-ctr
+ : AES-256-CTR : aes-256-ctr
+ : AES-128-XTS : aes-128-xts
+ : AES-256-XTS : aes-256-xts
+ : DES-CFB1 : des-cfb1
+ : DES-CFB8 : des-cfb8
+ : DES-EDE3-CFB1 : des-ede3-cfb1
+ : DES-EDE3-CFB8 : des-ede3-cfb8
+
+# OIDs for SHA224, SHA256, SHA385 and SHA512, according to x9.84.
+!Alias nist_hashalgs nistAlgorithms 2
+nist_hashalgs 1 : SHA256 : sha256
+nist_hashalgs 2 : SHA384 : sha384
+nist_hashalgs 3 : SHA512 : sha512
+nist_hashalgs 4 : SHA224 : sha224
+
+# OIDs for dsa-with-sha224 and dsa-with-sha256
+!Alias dsa_with_sha2 nistAlgorithms 3
+dsa_with_sha2 1 : dsa_with_SHA224
+dsa_with_sha2 2 : dsa_with_SHA256
+
+# Hold instruction CRL entry extension
+!Cname hold-instruction-code
+id-ce 23 : holdInstructionCode : Hold Instruction Code
+!Alias holdInstruction X9-57 2
+!Cname hold-instruction-none
+holdInstruction 1 : holdInstructionNone : Hold Instruction None
+!Cname hold-instruction-call-issuer
+holdInstruction 2 : holdInstructionCallIssuer : Hold Instruction Call Issuer
+!Cname hold-instruction-reject
+holdInstruction 3 : holdInstructionReject : Hold Instruction Reject
+
+# OID's from ITU-T. Most of this is defined in RFC 1274. A couple of
+# them are also mentioned in RFC 2247
+itu-t 9 : data
+data 2342 : pss
+pss 19200300 : ucl
+ucl 100 : pilot
+pilot 1 : : pilotAttributeType
+pilot 3 : : pilotAttributeSyntax
+pilot 4 : : pilotObjectClass
+pilot 10 : : pilotGroups
+pilotAttributeSyntax 4 : : iA5StringSyntax
+pilotAttributeSyntax 5 : : caseIgnoreIA5StringSyntax
+pilotObjectClass 3 : : pilotObject
+pilotObjectClass 4 : : pilotPerson
+pilotObjectClass 5 : account
+pilotObjectClass 6 : document
+pilotObjectClass 7 : room
+pilotObjectClass 9 : : documentSeries
+pilotObjectClass 13 : domain : Domain
+pilotObjectClass 14 : : rFC822localPart
+pilotObjectClass 15 : : dNSDomain
+pilotObjectClass 17 : : domainRelatedObject
+pilotObjectClass 18 : : friendlyCountry
+pilotObjectClass 19 : : simpleSecurityObject
+pilotObjectClass 20 : : pilotOrganization
+pilotObjectClass 21 : : pilotDSA
+pilotObjectClass 22 : : qualityLabelledData
+pilotAttributeType 1 : UID : userId
+pilotAttributeType 2 : : textEncodedORAddress
+pilotAttributeType 3 : mail : rfc822Mailbox
+pilotAttributeType 4 : info
+pilotAttributeType 5 : : favouriteDrink
+pilotAttributeType 6 : : roomNumber
+pilotAttributeType 7 : photo
+pilotAttributeType 8 : : userClass
+pilotAttributeType 9 : host
+pilotAttributeType 10 : manager
+pilotAttributeType 11 : : documentIdentifier
+pilotAttributeType 12 : : documentTitle
+pilotAttributeType 13 : : documentVersion
+pilotAttributeType 14 : : documentAuthor
+pilotAttributeType 15 : : documentLocation
+pilotAttributeType 20 : : homeTelephoneNumber
+pilotAttributeType 21 : secretary
+pilotAttributeType 22 : : otherMailbox
+pilotAttributeType 23 : : lastModifiedTime
+pilotAttributeType 24 : : lastModifiedBy
+pilotAttributeType 25 : DC : domainComponent
+pilotAttributeType 26 : : aRecord
+pilotAttributeType 27 : : pilotAttributeType27
+pilotAttributeType 28 : : mXRecord
+pilotAttributeType 29 : : nSRecord
+pilotAttributeType 30 : : sOARecord
+pilotAttributeType 31 : : cNAMERecord
+pilotAttributeType 37 : : associatedDomain
+pilotAttributeType 38 : : associatedName
+pilotAttributeType 39 : : homePostalAddress
+pilotAttributeType 40 : : personalTitle
+pilotAttributeType 41 : : mobileTelephoneNumber
+pilotAttributeType 42 : : pagerTelephoneNumber
+pilotAttributeType 43 : : friendlyCountryName
+# The following clashes with 2.5.4.45, so commented away
+#pilotAttributeType 44 : uid : uniqueIdentifier
+pilotAttributeType 45 : : organizationalStatus
+pilotAttributeType 46 : : janetMailbox
+pilotAttributeType 47 : : mailPreferenceOption
+pilotAttributeType 48 : : buildingName
+pilotAttributeType 49 : : dSAQuality
+pilotAttributeType 50 : : singleLevelQuality
+pilotAttributeType 51 : : subtreeMinimumQuality
+pilotAttributeType 52 : : subtreeMaximumQuality
+pilotAttributeType 53 : : personalSignature
+pilotAttributeType 54 : : dITRedirect
+pilotAttributeType 55 : audio
+pilotAttributeType 56 : : documentPublisher
+
+international-organizations 42 : id-set : Secure Electronic Transactions
+
+id-set 0 : set-ctype : content types
+id-set 1 : set-msgExt : message extensions
+id-set 3 : set-attr
+id-set 5 : set-policy
+id-set 7 : set-certExt : certificate extensions
+id-set 8 : set-brand
+
+set-ctype 0 : setct-PANData
+set-ctype 1 : setct-PANToken
+set-ctype 2 : setct-PANOnly
+set-ctype 3 : setct-OIData
+set-ctype 4 : setct-PI
+set-ctype 5 : setct-PIData
+set-ctype 6 : setct-PIDataUnsigned
+set-ctype 7 : setct-HODInput
+set-ctype 8 : setct-AuthResBaggage
+set-ctype 9 : setct-AuthRevReqBaggage
+set-ctype 10 : setct-AuthRevResBaggage
+set-ctype 11 : setct-CapTokenSeq
+set-ctype 12 : setct-PInitResData
+set-ctype 13 : setct-PI-TBS
+set-ctype 14 : setct-PResData
+set-ctype 16 : setct-AuthReqTBS
+set-ctype 17 : setct-AuthResTBS
+set-ctype 18 : setct-AuthResTBSX
+set-ctype 19 : setct-AuthTokenTBS
+set-ctype 20 : setct-CapTokenData
+set-ctype 21 : setct-CapTokenTBS
+set-ctype 22 : setct-AcqCardCodeMsg
+set-ctype 23 : setct-AuthRevReqTBS
+set-ctype 24 : setct-AuthRevResData
+set-ctype 25 : setct-AuthRevResTBS
+set-ctype 26 : setct-CapReqTBS
+set-ctype 27 : setct-CapReqTBSX
+set-ctype 28 : setct-CapResData
+set-ctype 29 : setct-CapRevReqTBS
+set-ctype 30 : setct-CapRevReqTBSX
+set-ctype 31 : setct-CapRevResData
+set-ctype 32 : setct-CredReqTBS
+set-ctype 33 : setct-CredReqTBSX
+set-ctype 34 : setct-CredResData
+set-ctype 35 : setct-CredRevReqTBS
+set-ctype 36 : setct-CredRevReqTBSX
+set-ctype 37 : setct-CredRevResData
+set-ctype 38 : setct-PCertReqData
+set-ctype 39 : setct-PCertResTBS
+set-ctype 40 : setct-BatchAdminReqData
+set-ctype 41 : setct-BatchAdminResData
+set-ctype 42 : setct-CardCInitResTBS
+set-ctype 43 : setct-MeAqCInitResTBS
+set-ctype 44 : setct-RegFormResTBS
+set-ctype 45 : setct-CertReqData
+set-ctype 46 : setct-CertReqTBS
+set-ctype 47 : setct-CertResData
+set-ctype 48 : setct-CertInqReqTBS
+set-ctype 49 : setct-ErrorTBS
+set-ctype 50 : setct-PIDualSignedTBE
+set-ctype 51 : setct-PIUnsignedTBE
+set-ctype 52 : setct-AuthReqTBE
+set-ctype 53 : setct-AuthResTBE
+set-ctype 54 : setct-AuthResTBEX
+set-ctype 55 : setct-AuthTokenTBE
+set-ctype 56 : setct-CapTokenTBE
+set-ctype 57 : setct-CapTokenTBEX
+set-ctype 58 : setct-AcqCardCodeMsgTBE
+set-ctype 59 : setct-AuthRevReqTBE
+set-ctype 60 : setct-AuthRevResTBE
+set-ctype 61 : setct-AuthRevResTBEB
+set-ctype 62 : setct-CapReqTBE
+set-ctype 63 : setct-CapReqTBEX
+set-ctype 64 : setct-CapResTBE
+set-ctype 65 : setct-CapRevReqTBE
+set-ctype 66 : setct-CapRevReqTBEX
+set-ctype 67 : setct-CapRevResTBE
+set-ctype 68 : setct-CredReqTBE
+set-ctype 69 : setct-CredReqTBEX
+set-ctype 70 : setct-CredResTBE
+set-ctype 71 : setct-CredRevReqTBE
+set-ctype 72 : setct-CredRevReqTBEX
+set-ctype 73 : setct-CredRevResTBE
+set-ctype 74 : setct-BatchAdminReqTBE
+set-ctype 75 : setct-BatchAdminResTBE
+set-ctype 76 : setct-RegFormReqTBE
+set-ctype 77 : setct-CertReqTBE
+set-ctype 78 : setct-CertReqTBEX
+set-ctype 79 : setct-CertResTBE
+set-ctype 80 : setct-CRLNotificationTBS
+set-ctype 81 : setct-CRLNotificationResTBS
+set-ctype 82 : setct-BCIDistributionTBS
+
+set-msgExt 1 : setext-genCrypt : generic cryptogram
+set-msgExt 3 : setext-miAuth : merchant initiated auth
+set-msgExt 4 : setext-pinSecure
+set-msgExt 5 : setext-pinAny
+set-msgExt 7 : setext-track2
+set-msgExt 8 : setext-cv : additional verification
+
+set-policy 0 : set-policy-root
+
+set-certExt 0 : setCext-hashedRoot
+set-certExt 1 : setCext-certType
+set-certExt 2 : setCext-merchData
+set-certExt 3 : setCext-cCertRequired
+set-certExt 4 : setCext-tunneling
+set-certExt 5 : setCext-setExt
+set-certExt 6 : setCext-setQualf
+set-certExt 7 : setCext-PGWYcapabilities
+set-certExt 8 : setCext-TokenIdentifier
+set-certExt 9 : setCext-Track2Data
+set-certExt 10 : setCext-TokenType
+set-certExt 11 : setCext-IssuerCapabilities
+
+set-attr 0 : setAttr-Cert
+set-attr 1 : setAttr-PGWYcap : payment gateway capabilities
+set-attr 2 : setAttr-TokenType
+set-attr 3 : setAttr-IssCap : issuer capabilities
+
+setAttr-Cert 0 : set-rootKeyThumb
+setAttr-Cert 1 : set-addPolicy
+
+setAttr-TokenType 1 : setAttr-Token-EMV
+setAttr-TokenType 2 : setAttr-Token-B0Prime
+
+setAttr-IssCap 3 : setAttr-IssCap-CVM
+setAttr-IssCap 4 : setAttr-IssCap-T2
+setAttr-IssCap 5 : setAttr-IssCap-Sig
+
+setAttr-IssCap-CVM 1 : setAttr-GenCryptgrm : generate cryptogram
+setAttr-IssCap-T2 1 : setAttr-T2Enc : encrypted track 2
+setAttr-IssCap-T2 2 : setAttr-T2cleartxt : cleartext track 2
+
+setAttr-IssCap-Sig 1 : setAttr-TokICCsig : ICC or token signature
+setAttr-IssCap-Sig 2 : setAttr-SecDevSig : secure device signature
+
+set-brand 1 : set-brand-IATA-ATA
+set-brand 30 : set-brand-Diners
+set-brand 34 : set-brand-AmericanExpress
+set-brand 35 : set-brand-JCB
+set-brand 4 : set-brand-Visa
+set-brand 5 : set-brand-MasterCard
+set-brand 6011 : set-brand-Novus
+
+rsadsi 3 10 : DES-CDMF : des-cdmf
+rsadsi 1 1 6 : rsaOAEPEncryptionSET
+
+ : Oakley-EC2N-3 : ipsec3
+ : Oakley-EC2N-4 : ipsec4
+
+iso 0 10118 3 0 55 : whirlpool
+
+# GOST OIDs
+
+member-body 643 2 2 : cryptopro
+member-body 643 2 9 : cryptocom
+
+cryptopro 3 : id-GostR3411-94-with-GostR3410-2001 : GOST R 34.11-94 with GOST R 34.10-2001
+cryptopro 4 : id-GostR3411-94-with-GostR3410-94 : GOST R 34.11-94 with GOST R 34.10-94
+!Cname id-GostR3411-94
+cryptopro 9 : md_gost94 : GOST R 34.11-94
+cryptopro 10 : id-HMACGostR3411-94 : HMAC GOST 34.11-94
+!Cname id-GostR3410-2001
+cryptopro 19 : gost2001 : GOST R 34.10-2001
+!Cname id-GostR3410-94
+cryptopro 20 : gost94 : GOST R 34.10-94
+!Cname id-Gost28147-89
+cryptopro 21 : gost89 : GOST 28147-89
+ : gost89-cnt
+!Cname id-Gost28147-89-MAC
+cryptopro 22 : gost-mac : GOST 28147-89 MAC
+!Cname id-GostR3411-94-prf
+cryptopro 23 : prf-gostr3411-94 : GOST R 34.11-94 PRF
+cryptopro 98 : id-GostR3410-2001DH : GOST R 34.10-2001 DH
+cryptopro 99 : id-GostR3410-94DH : GOST R 34.10-94 DH
+
+cryptopro 14 1 : id-Gost28147-89-CryptoPro-KeyMeshing
+cryptopro 14 0 : id-Gost28147-89-None-KeyMeshing
+
+# GOST parameter set OIDs
+
+cryptopro 30 0 : id-GostR3411-94-TestParamSet
+cryptopro 30 1 : id-GostR3411-94-CryptoProParamSet
+
+cryptopro 31 0 : id-Gost28147-89-TestParamSet
+cryptopro 31 1 : id-Gost28147-89-CryptoPro-A-ParamSet
+cryptopro 31 2 : id-Gost28147-89-CryptoPro-B-ParamSet
+cryptopro 31 3 : id-Gost28147-89-CryptoPro-C-ParamSet
+cryptopro 31 4 : id-Gost28147-89-CryptoPro-D-ParamSet
+cryptopro 31 5 : id-Gost28147-89-CryptoPro-Oscar-1-1-ParamSet
+cryptopro 31 6 : id-Gost28147-89-CryptoPro-Oscar-1-0-ParamSet
+cryptopro 31 7 : id-Gost28147-89-CryptoPro-RIC-1-ParamSet
+
+cryptopro 32 0 : id-GostR3410-94-TestParamSet
+cryptopro 32 2 : id-GostR3410-94-CryptoPro-A-ParamSet
+cryptopro 32 3 : id-GostR3410-94-CryptoPro-B-ParamSet
+cryptopro 32 4 : id-GostR3410-94-CryptoPro-C-ParamSet
+cryptopro 32 5 : id-GostR3410-94-CryptoPro-D-ParamSet
+
+cryptopro 33 1 : id-GostR3410-94-CryptoPro-XchA-ParamSet
+cryptopro 33 2 : id-GostR3410-94-CryptoPro-XchB-ParamSet
+cryptopro 33 3 : id-GostR3410-94-CryptoPro-XchC-ParamSet
+
+cryptopro 35 0 : id-GostR3410-2001-TestParamSet
+cryptopro 35 1 : id-GostR3410-2001-CryptoPro-A-ParamSet
+cryptopro 35 2 : id-GostR3410-2001-CryptoPro-B-ParamSet
+cryptopro 35 3 : id-GostR3410-2001-CryptoPro-C-ParamSet
+
+cryptopro 36 0 : id-GostR3410-2001-CryptoPro-XchA-ParamSet
+cryptopro 36 1 : id-GostR3410-2001-CryptoPro-XchB-ParamSet
+
+id-GostR3410-94 1 : id-GostR3410-94-a
+id-GostR3410-94 2 : id-GostR3410-94-aBis
+id-GostR3410-94 3 : id-GostR3410-94-b
+id-GostR3410-94 4 : id-GostR3410-94-bBis
+
+# Cryptocom LTD GOST OIDs
+
+cryptocom 1 6 1 : id-Gost28147-89-cc : GOST 28147-89 Cryptocom ParamSet
+!Cname id-GostR3410-94-cc
+cryptocom 1 5 3 : gost94cc : GOST 34.10-94 Cryptocom
+!Cname id-GostR3410-2001-cc
+cryptocom 1 5 4 : gost2001cc : GOST 34.10-2001 Cryptocom
+
+cryptocom 1 3 3 : id-GostR3411-94-with-GostR3410-94-cc : GOST R 34.11-94 with GOST R 34.10-94 Cryptocom
+cryptocom 1 3 4 : id-GostR3411-94-with-GostR3410-2001-cc : GOST R 34.11-94 with GOST R 34.10-2001 Cryptocom
+
+cryptocom 1 8 1 : id-GostR3410-2001-ParamSet-cc : GOST R 3410-2001 Parameter Set Cryptocom
+
+# Definitions for Camellia cipher - CBC MODE
+
+1 2 392 200011 61 1 1 1 2 : CAMELLIA-128-CBC : camellia-128-cbc
+1 2 392 200011 61 1 1 1 3 : CAMELLIA-192-CBC : camellia-192-cbc
+1 2 392 200011 61 1 1 1 4 : CAMELLIA-256-CBC : camellia-256-cbc
+1 2 392 200011 61 1 1 3 2 : id-camellia128-wrap
+1 2 392 200011 61 1 1 3 3 : id-camellia192-wrap
+1 2 392 200011 61 1 1 3 4 : id-camellia256-wrap
+
+# Definitions for Camellia cipher - ECB, CFB, OFB MODE
+
+!Alias ntt-ds 0 3 4401 5
+!Alias camellia ntt-ds 3 1 9
+
+camellia 1 : CAMELLIA-128-ECB : camellia-128-ecb
+!Cname camellia-128-ofb128
+camellia 3 : CAMELLIA-128-OFB : camellia-128-ofb
+!Cname camellia-128-cfb128
+camellia 4 : CAMELLIA-128-CFB : camellia-128-cfb
+
+camellia 21 : CAMELLIA-192-ECB : camellia-192-ecb
+!Cname camellia-192-ofb128
+camellia 23 : CAMELLIA-192-OFB : camellia-192-ofb
+!Cname camellia-192-cfb128
+camellia 24 : CAMELLIA-192-CFB : camellia-192-cfb
+
+camellia 41 : CAMELLIA-256-ECB : camellia-256-ecb
+!Cname camellia-256-ofb128
+camellia 43 : CAMELLIA-256-OFB : camellia-256-ofb
+!Cname camellia-256-cfb128
+camellia 44 : CAMELLIA-256-CFB : camellia-256-cfb
+
+# There are no OIDs for these modes...
+
+ : CAMELLIA-128-CFB1 : camellia-128-cfb1
+ : CAMELLIA-192-CFB1 : camellia-192-cfb1
+ : CAMELLIA-256-CFB1 : camellia-256-cfb1
+ : CAMELLIA-128-CFB8 : camellia-128-cfb8
+ : CAMELLIA-192-CFB8 : camellia-192-cfb8
+ : CAMELLIA-256-CFB8 : camellia-256-cfb8
+
+# Definitions for SEED cipher - ECB, CBC, OFB mode
+
+member-body 410 200004 : KISA : kisa
+kisa 1 3 : SEED-ECB : seed-ecb
+kisa 1 4 : SEED-CBC : seed-cbc
+!Cname seed-cfb128
+kisa 1 5 : SEED-CFB : seed-cfb
+!Cname seed-ofb128
+kisa 1 6 : SEED-OFB : seed-ofb
+
+# There is no OID that just denotes "HMAC" oddly enough...
+
+ : HMAC : hmac
+# Nor CMAC either
+ : CMAC : cmac
+
+# Synthetic composite ciphersuites
+ : RC4-HMAC-MD5 : rc4-hmac-md5
+ : AES-128-CBC-HMAC-SHA1 : aes-128-cbc-hmac-sha1
+ : AES-192-CBC-HMAC-SHA1 : aes-192-cbc-hmac-sha1
+ : AES-256-CBC-HMAC-SHA1 : aes-256-cbc-hmac-sha1
+
+ISO-US 10046 2 1 : dhpublicnumber : X9.42 DH
+
+# RFC 5639 curve OIDs (see http://www.ietf.org/rfc/rfc5639.txt)
+# versionOne OBJECT IDENTIFIER ::= {
+# iso(1) identifified-organization(3) teletrust(36) algorithm(3)
+# signature-algorithm(3) ecSign(2) ecStdCurvesAndGeneration(8)
+# ellipticCurve(1) 1 }
+1 3 36 3 3 2 8 1 1 1 : brainpoolP160r1
+1 3 36 3 3 2 8 1 1 2 : brainpoolP160t1
+1 3 36 3 3 2 8 1 1 3 : brainpoolP192r1
+1 3 36 3 3 2 8 1 1 4 : brainpoolP192t1
+1 3 36 3 3 2 8 1 1 5 : brainpoolP224r1
+1 3 36 3 3 2 8 1 1 6 : brainpoolP224t1
+1 3 36 3 3 2 8 1 1 7 : brainpoolP256r1
+1 3 36 3 3 2 8 1 1 8 : brainpoolP256t1
+1 3 36 3 3 2 8 1 1 9 : brainpoolP320r1
+1 3 36 3 3 2 8 1 1 10 : brainpoolP320t1
+1 3 36 3 3 2 8 1 1 11 : brainpoolP384r1
+1 3 36 3 3 2 8 1 1 12 : brainpoolP384t1
+1 3 36 3 3 2 8 1 1 13 : brainpoolP512r1
+1 3 36 3 3 2 8 1 1 14 : brainpoolP512t1
+
+# ECDH schemes from RFC5753
+!Alias x9-63-scheme 1 3 133 16 840 63 0
+!Alias secg-scheme certicom-arc 1
+
+x9-63-scheme 2 : dhSinglePass-stdDH-sha1kdf-scheme
+secg-scheme 11 0 : dhSinglePass-stdDH-sha224kdf-scheme
+secg-scheme 11 1 : dhSinglePass-stdDH-sha256kdf-scheme
+secg-scheme 11 2 : dhSinglePass-stdDH-sha384kdf-scheme
+secg-scheme 11 3 : dhSinglePass-stdDH-sha512kdf-scheme
+
+x9-63-scheme 3 : dhSinglePass-cofactorDH-sha1kdf-scheme
+secg-scheme 14 0 : dhSinglePass-cofactorDH-sha224kdf-scheme
+secg-scheme 14 1 : dhSinglePass-cofactorDH-sha256kdf-scheme
+secg-scheme 14 2 : dhSinglePass-cofactorDH-sha384kdf-scheme
+secg-scheme 14 3 : dhSinglePass-cofactorDH-sha512kdf-scheme
+# NIDs for use with lookup tables.
+ : dh-std-kdf
+ : dh-cofactor-kdf
diff --git a/src/crypto/pem/CMakeLists.txt b/src/crypto/pem/CMakeLists.txt
new file mode 100644
index 0000000..3275b15
--- /dev/null
+++ b/src/crypto/pem/CMakeLists.txt
@@ -0,0 +1,17 @@
+include_directories(. .. ../../include)
+
+add_library(
+ pem
+
+ OBJECT
+
+ pem_all.c
+ pem_error.c
+ pem_info.c
+ pem_lib.c
+ pem_oth.c
+ pem_pk8.c
+ pem_pkey.c
+ pem_x509.c
+ pem_xaux.c
+)
diff --git a/src/crypto/pem/pem_all.c b/src/crypto/pem/pem_all.c
new file mode 100644
index 0000000..24ecc62
--- /dev/null
+++ b/src/crypto/pem/pem_all.c
@@ -0,0 +1,281 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <stdio.h>
+
+#include <openssl/bio.h>
+#include <openssl/dh.h>
+#include <openssl/dsa.h>
+#include <openssl/evp.h>
+#include <openssl/pem.h>
+/*#include <openssl/pkcs7.h> */
+#include <openssl/rsa.h>
+#include <openssl/x509.h>
+
+
+static RSA *pkey_get_rsa(EVP_PKEY *key, RSA **rsa);
+static DSA *pkey_get_dsa(EVP_PKEY *key, DSA **dsa);
+static EC_KEY *pkey_get_eckey(EVP_PKEY *key, EC_KEY **eckey);
+
+
+IMPLEMENT_PEM_rw(X509_REQ, X509_REQ, PEM_STRING_X509_REQ, X509_REQ)
+
+IMPLEMENT_PEM_write(X509_REQ_NEW, X509_REQ, PEM_STRING_X509_REQ_OLD, X509_REQ)
+
+IMPLEMENT_PEM_rw(X509_CRL, X509_CRL, PEM_STRING_X509_CRL, X509_CRL)
+
+
+
+/* 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_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);
+}
+
+#ifndef OPENSSL_NO_FP_API
+
+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);
+}
+
+#endif
+
+IMPLEMENT_PEM_write_cb_const(RSAPrivateKey, RSA, PEM_STRING_RSA, RSAPrivateKey)
+
+IMPLEMENT_PEM_rw_const(RSAPublicKey, RSA, PEM_STRING_RSA_PUBLIC, RSAPublicKey)
+IMPLEMENT_PEM_rw(RSA_PUBKEY, RSA, PEM_STRING_PUBLIC, RSA_PUBKEY)
+
+#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_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 */
+}
+
+
+IMPLEMENT_PEM_write_cb_const(DSAPrivateKey, DSA, PEM_STRING_DSA, DSAPrivateKey)
+
+IMPLEMENT_PEM_rw(DSA_PUBKEY, DSA, PEM_STRING_PUBLIC, DSA_PUBKEY)
+
+#ifndef OPENSSL_NO_FP_API
+
+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 */
+}
+
+#endif
+
+IMPLEMENT_PEM_rw_const(DSAparams, DSA, PEM_STRING_DSAPARAMS, DSAparams)
+
+#endif
+
+
+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_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 */
+}
+
+/* TODO(fork): remove this code? */
+/* IMPLEMENT_PEM_rw_const(ECPKParameters, EC_GROUP, PEM_STRING_ECPARAMETERS, ECPKParameters) */
+
+
+
+
+IMPLEMENT_PEM_write_cb(ECPrivateKey, EC_KEY, PEM_STRING_ECPRIVATEKEY, ECPrivateKey)
+
+
+IMPLEMENT_PEM_rw(EC_PUBKEY, EC_KEY, PEM_STRING_PUBLIC, EC_PUBKEY)
+
+#ifndef OPENSSL_NO_FP_API
+
+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 */
+}
+
+#endif
+
+
+
+IMPLEMENT_PEM_write_const(DHparams, DH, PEM_STRING_DHPARAMS, DHparams)
+
+/* TODO(fork): remove this code? */
+/* IMPLEMENT_PEM_write_const(DHxparams, DH, PEM_STRING_DHXPARAMS, DHxparams) */
+
+
+IMPLEMENT_PEM_rw(PUBKEY, EVP_PKEY, PEM_STRING_PUBLIC, PUBKEY)
diff --git a/src/crypto/pem/pem_error.c b/src/crypto/pem/pem_error.c
new file mode 100644
index 0000000..2745f4c
--- /dev/null
+++ b/src/crypto/pem/pem_error.c
@@ -0,0 +1,73 @@
+/* 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 <openssl/err.h>
+
+#include <openssl/pem.h>
+
+const ERR_STRING_DATA PEM_error_string_data[] = {
+ {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_ASN1_read, 0), "PEM_ASN1_read"},
+ {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_ASN1_read_bio, 0), "PEM_ASN1_read_bio"},
+ {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_ASN1_write, 0), "PEM_ASN1_write"},
+ {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_ASN1_write_bio, 0), "PEM_ASN1_write_bio"},
+ {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_X509_INFO_read, 0), "PEM_X509_INFO_read"},
+ {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_X509_INFO_read_bio, 0), "PEM_X509_INFO_read_bio"},
+ {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_X509_INFO_write_bio, 0), "PEM_X509_INFO_write_bio"},
+ {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_do_header, 0), "PEM_do_header"},
+ {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_get_EVP_CIPHER_INFO, 0), "PEM_get_EVP_CIPHER_INFO"},
+ {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_read, 0), "PEM_read"},
+ {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_read_DHparams, 0), "PEM_read_DHparams"},
+ {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_read_PrivateKey, 0), "PEM_read_PrivateKey"},
+ {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_read_bio, 0), "PEM_read_bio"},
+ {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_read_bio_DHparams, 0), "PEM_read_bio_DHparams"},
+ {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_read_bio_Parameters, 0), "PEM_read_bio_Parameters"},
+ {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_read_bio_PrivateKey, 0), "PEM_read_bio_PrivateKey"},
+ {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_write, 0), "PEM_write"},
+ {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_write_PrivateKey, 0), "PEM_write_PrivateKey"},
+ {ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_write_bio, 0), "PEM_write_bio"},
+ {ERR_PACK(ERR_LIB_PEM, PEM_F_d2i_PKCS8PrivateKey_bio, 0), "d2i_PKCS8PrivateKey_bio"},
+ {ERR_PACK(ERR_LIB_PEM, PEM_F_d2i_PKCS8PrivateKey_fp, 0), "d2i_PKCS8PrivateKey_fp"},
+ {ERR_PACK(ERR_LIB_PEM, PEM_F_do_pk8pkey, 0), "do_pk8pkey"},
+ {ERR_PACK(ERR_LIB_PEM, PEM_F_do_pk8pkey_fp, 0), "do_pk8pkey_fp"},
+ {ERR_PACK(ERR_LIB_PEM, PEM_F_load_iv, 0), "load_iv"},
+ {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_BAD_BASE64_DECODE), "BAD_BASE64_DECODE"},
+ {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_BAD_DECRYPT), "BAD_DECRYPT"},
+ {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_BAD_END_LINE), "BAD_END_LINE"},
+ {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_BAD_IV_CHARS), "BAD_IV_CHARS"},
+ {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_BAD_MAGIC_NUMBER), "BAD_MAGIC_NUMBER"},
+ {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_BAD_PASSWORD_READ), "BAD_PASSWORD_READ"},
+ {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_BAD_VERSION_NUMBER), "BAD_VERSION_NUMBER"},
+ {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_BIO_WRITE_FAILURE), "BIO_WRITE_FAILURE"},
+ {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_CIPHER_IS_NULL), "CIPHER_IS_NULL"},
+ {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_ERROR_CONVERTING_PRIVATE_KEY), "ERROR_CONVERTING_PRIVATE_KEY"},
+ {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_EXPECTING_PRIVATE_KEY_BLOB), "EXPECTING_PRIVATE_KEY_BLOB"},
+ {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_EXPECTING_PUBLIC_KEY_BLOB), "EXPECTING_PUBLIC_KEY_BLOB"},
+ {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_INCONSISTENT_HEADER), "INCONSISTENT_HEADER"},
+ {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_KEYBLOB_HEADER_PARSE_ERROR), "KEYBLOB_HEADER_PARSE_ERROR"},
+ {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_KEYBLOB_TOO_SHORT), "KEYBLOB_TOO_SHORT"},
+ {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_NOT_DEK_INFO), "NOT_DEK_INFO"},
+ {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_NOT_ENCRYPTED), "NOT_ENCRYPTED"},
+ {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_NOT_PROC_TYPE), "NOT_PROC_TYPE"},
+ {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_NO_START_LINE), "NO_START_LINE"},
+ {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_PROBLEMS_GETTING_PASSWORD), "PROBLEMS_GETTING_PASSWORD"},
+ {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_PUBLIC_KEY_NO_RSA), "PUBLIC_KEY_NO_RSA"},
+ {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_PVK_DATA_TOO_SHORT), "PVK_DATA_TOO_SHORT"},
+ {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_PVK_TOO_SHORT), "PVK_TOO_SHORT"},
+ {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_READ_KEY), "READ_KEY"},
+ {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_SHORT_HEADER), "SHORT_HEADER"},
+ {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_UNSUPPORTED_CIPHER), "UNSUPPORTED_CIPHER"},
+ {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_UNSUPPORTED_ENCRYPTION), "UNSUPPORTED_ENCRYPTION"},
+ {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_UNSUPPORTED_KEY_COMPONENTS), "UNSUPPORTED_KEY_COMPONENTS"},
+ {0, NULL},
+};
diff --git a/src/crypto/pem/pem_info.c b/src/crypto/pem/pem_info.c
new file mode 100644
index 0000000..3f02619
--- /dev/null
+++ b/src/crypto/pem/pem_info.c
@@ -0,0 +1,404 @@
+/* crypto/pem/pem_info.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 <openssl/pem.h>
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <openssl/buf.h>
+#include <openssl/dsa.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/rsa.h>
+#include <openssl/x509.h>
+
+
+#ifndef OPENSSL_NO_FP_API
+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)
+ {
+ OPENSSL_PUT_ERROR(PEM, PEM_X509_INFO_read, 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);
+ }
+#endif
+
+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,error=0;
+ int ok=0;
+ STACK_OF(X509_INFO) *ret=NULL;
+ unsigned int i,raw,ptype;
+ d2i_of_void *d2i = 0;
+
+ if (sk == NULL)
+ {
+ if ((ret=sk_X509_INFO_new_null()) == NULL)
+ {
+ OPENSSL_PUT_ERROR(PEM, PEM_X509_INFO_read_bio, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+ else
+ ret=sk;
+
+ if ((xi=X509_INFO_new()) == NULL) goto err;
+ for (;;)
+ {
+ raw=0;
+ ptype = 0;
+ i=PEM_read_bio(bp,&name,&header,&data,&len);
+ if (i == 0)
+ {
+ error=ERR_GET_REASON(ERR_peek_last_error());
+ if (error == PEM_R_NO_START_LINE)
+ {
+ ERR_clear_error();
+ break;
+ }
+ goto err;
+ }
+start:
+ if ( (strcmp(name,PEM_STRING_X509) == 0) ||
+ (strcmp(name,PEM_STRING_X509_OLD) == 0))
+ {
+ d2i=(D2I_OF(void))d2i_X509;
+ if (xi->x509 != NULL)
+ {
+ if (!sk_X509_INFO_push(ret,xi)) goto err;
+ if ((xi=X509_INFO_new()) == NULL) goto err;
+ goto start;
+ }
+ pp=&(xi->x509);
+ }
+ else if ((strcmp(name,PEM_STRING_X509_TRUSTED) == 0))
+ {
+ d2i=(D2I_OF(void))d2i_X509_AUX;
+ if (xi->x509 != NULL)
+ {
+ if (!sk_X509_INFO_push(ret,xi)) goto err;
+ if ((xi=X509_INFO_new()) == NULL) goto err;
+ goto start;
+ }
+ pp=&(xi->x509);
+ }
+ else if (strcmp(name,PEM_STRING_X509_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;
+ goto start;
+ }
+ pp=&(xi->crl);
+ }
+ else
+ 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;
+ goto start;
+ }
+
+ xi->enc_data=NULL;
+ xi->enc_len=0;
+
+ xi->x_pkey=X509_PKEY_new();
+ ptype=EVP_PKEY_RSA;
+ pp=&xi->x_pkey->dec_pkey;
+ if ((int)strlen(header) > 10) /* assume encrypted */
+ raw=1;
+ }
+ else
+#ifndef OPENSSL_NO_DSA
+ if (strcmp(name,PEM_STRING_DSA) == 0)
+ {
+ d2i=(D2I_OF(void))d2i_DSAPrivateKey;
+ if (xi->x_pkey != NULL)
+ {
+ if (!sk_X509_INFO_push(ret,xi)) goto err;
+ if ((xi=X509_INFO_new()) == NULL) goto err;
+ goto start;
+ }
+
+ xi->enc_data=NULL;
+ xi->enc_len=0;
+
+ xi->x_pkey=X509_PKEY_new();
+ ptype = EVP_PKEY_DSA;
+ pp=&xi->x_pkey->dec_pkey;
+ if ((int)strlen(header) > 10) /* assume encrypted */
+ raw=1;
+ }
+ else
+#endif
+ if (strcmp(name,PEM_STRING_ECPRIVATEKEY) == 0)
+ {
+ d2i=(D2I_OF(void))d2i_ECPrivateKey;
+ if (xi->x_pkey != NULL)
+ {
+ if (!sk_X509_INFO_push(ret,xi)) goto err;
+ if ((xi=X509_INFO_new()) == NULL) goto err;
+ goto start;
+ }
+
+ xi->enc_data=NULL;
+ xi->enc_len=0;
+
+ xi->x_pkey=X509_PKEY_new();
+ ptype = EVP_PKEY_EC;
+ pp=&xi->x_pkey->dec_pkey;
+ if ((int)strlen(header) > 10) /* assume encrypted */
+ raw=1;
+ }
+ else
+ {
+ 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))
+ {
+ OPENSSL_PUT_ERROR(PEM, PEM_X509_INFO_read_bio, ERR_R_ASN1_LIB);
+ goto err;
+ }
+ }
+ else if (d2i(pp,&p,len) == NULL)
+ {
+ OPENSSL_PUT_ERROR(PEM, PEM_X509_INFO_read_bio, 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 */
+ }
+ if (name != NULL) OPENSSL_free(name);
+ if (header != NULL) OPENSSL_free(header);
+ if (data != NULL) OPENSSL_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 (xi != NULL) X509_INFO_free(xi);
+ if (!ok)
+ {
+ for (i=0; ((int)i)<sk_X509_INFO_num(ret); i++)
+ {
+ xi=sk_X509_INFO_value(ret,i);
+ X509_INFO_free(xi);
+ }
+ if (ret != sk) sk_X509_INFO_free(ret);
+ ret=NULL;
+ }
+
+ if (name != NULL) OPENSSL_free(name);
+ if (header != NULL) OPENSSL_free(header);
+ if (data != NULL) OPENSSL_free(data);
+ return(ret);
+ }
+
+
+/* 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;
+ unsigned iv_len = 0;
+
+ if (enc != NULL)
+ {
+ iv_len = EVP_CIPHER_iv_length(enc);
+ objstr=OBJ_nid2sn(EVP_CIPHER_nid(enc));
+ if (objstr == NULL)
+ {
+ OPENSSL_PUT_ERROR(PEM, PEM_X509_INFO_write_bio, 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)
+ {
+ OPENSSL_PUT_ERROR(PEM, PEM_X509_INFO_write_bio, 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)
+ {
+ OPENSSL_PUT_ERROR(PEM, PEM_X509_INFO_write_bio, PEM_R_UNSUPPORTED_CIPHER);
+ goto err;
+ }
+
+ /* create the right magic header stuff */
+ assert(strlen(objstr)+23+2*iv_len+13 <= sizeof buf);
+ buf[0]='\0';
+ PEM_proc_type(buf,PEM_TYPE_ENCRYPTED);
+ PEM_dek_info(buf,objstr,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 */
+ /* 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;
+ }
+ }
+
+ /* 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:
+ OPENSSL_cleanse((char *)&ctx,sizeof(ctx));
+ OPENSSL_cleanse(buf,PEM_BUFSIZE);
+ return(ret);
+ }
diff --git a/src/crypto/pem/pem_lib.c b/src/crypto/pem/pem_lib.c
new file mode 100644
index 0000000..ff72c44
--- /dev/null
+++ b/src/crypto/pem/pem_lib.c
@@ -0,0 +1,812 @@
+/* crypto/pem/pem_lib.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 <assert.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <openssl/base64.h>
+#include <openssl/buf.h>
+#include <openssl/des.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/pem.h>
+#include <openssl/rand.h>
+#include <openssl/x509.h>
+
+#include "../evp/internal.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);
+
+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";
+
+ BUF_strlcat(buf,"Proc-Type: 4,",PEM_BUFSIZE);
+ BUF_strlcat(buf,str,PEM_BUFSIZE);
+ BUF_strlcat(buf,"\n",PEM_BUFSIZE);
+ }
+
+void PEM_dek_info(char *buf, const char *type, int len, char *str)
+ {
+ static const unsigned char map[17]="0123456789ABCDEF";
+ long i;
+ int j;
+
+ BUF_strlcat(buf,"DEK-Info: ",PEM_BUFSIZE);
+ BUF_strlcat(buf,type,PEM_BUFSIZE);
+ BUF_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';
+ }
+
+#ifndef OPENSSL_NO_FP_API
+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)
+ {
+ OPENSSL_PUT_ERROR(PEM, PEM_ASN1_read, 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);
+ }
+#endif
+
+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;
+ return r;
+ }
+ }
+ return 0;
+ }
+ /* If reading DH parameters handle X9.42 DH format too */
+ if(!strcmp(nm,PEM_STRING_DHXPARAMS) &&
+ !strcmp(name,PEM_STRING_DHPARAMS)) return 1;
+
+ /* 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) &&
+ !strcmp(name, PEM_STRING_CMS)) return 1;
+ /* Allow CMS to be read from PKCS#7 headers */
+ if(!strcmp(nm, PEM_STRING_PKCS7) &&
+ !strcmp(name, PEM_STRING_CMS)) 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_add_error_data(2, "Expecting: ", name);
+ return 0;
+ }
+ if(check_pem(nm, name)) break;
+ OPENSSL_free(nm);
+ OPENSSL_free(header);
+ OPENSSL_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) OPENSSL_free(nm);
+ OPENSSL_free(header);
+ if (!ret) OPENSSL_free(data);
+ return ret;
+ }
+
+#ifndef OPENSSL_NO_FP_API
+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)
+ {
+ OPENSSL_PUT_ERROR(PEM, PEM_ASN1_write, 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);
+ }
+#endif
+
+int PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp,
+ void *x, const EVP_CIPHER *enc, unsigned char *kstr,
+ int klen, pem_password_cb *callback, void *u)
+ {
+ 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)
+ {
+ OPENSSL_PUT_ERROR(PEM, PEM_ASN1_write_bio, PEM_R_UNSUPPORTED_CIPHER);
+ goto err;
+ }
+ }
+
+ if ((dsize=i2d(x,NULL)) < 0)
+ {
+ OPENSSL_PUT_ERROR(PEM, PEM_ASN1_write_bio, ERR_R_ASN1_LIB);
+ dsize=0;
+ goto err;
+ }
+ /* dzise + 8 bytes are needed */
+ /* actually it needs the cipher block size extra... */
+ data=(unsigned char *)OPENSSL_malloc((unsigned int)dsize+20);
+ if (data == NULL)
+ {
+ OPENSSL_PUT_ERROR(PEM, PEM_ASN1_write_bio, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ p=data;
+ i=i2d(x,&p);
+
+ if (enc != NULL)
+ {
+ const unsigned iv_len = EVP_CIPHER_iv_length(enc);
+
+ if (kstr == NULL)
+ {
+ klen = 0;
+ if (callback)
+ klen=(*callback)(buf,PEM_BUFSIZE,1,u);
+ if (klen <= 0)
+ {
+ OPENSSL_PUT_ERROR(PEM, PEM_ASN1_write_bio, PEM_R_READ_KEY);
+ goto err;
+ }
+ kstr=(unsigned char *)buf;
+ }
+ assert(iv_len <= (int)sizeof(iv));
+ if (!RAND_bytes(iv, iv_len)) /* Generate a salt */
+ goto err;
+ /* 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) OPENSSL_cleanse(buf,PEM_BUFSIZE);
+
+ assert(strlen(objstr)+23+2*iv_len+13 <= sizeof buf);
+
+ buf[0]='\0';
+ PEM_proc_type(buf,PEM_TYPE_ENCRYPTED);
+ PEM_dek_info(buf,objstr,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:
+ OPENSSL_cleanse(key,sizeof(key));
+ OPENSSL_cleanse(iv,sizeof(iv));
+ OPENSSL_cleanse((char *)&ctx,sizeof(ctx));
+ OPENSSL_cleanse(buf,PEM_BUFSIZE);
+ if (data != NULL)
+ {
+ OPENSSL_cleanse(data,(unsigned int)dsize);
+ OPENSSL_free(data);
+ }
+ return(ret);
+ }
+
+int PEM_do_header(EVP_CIPHER_INFO *cipher, unsigned char *data, long *plen,
+ pem_password_cb *callback,void *u)
+ {
+ int i=0,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);
+
+ klen = 0;
+ if (callback)
+ klen=callback(buf,PEM_BUFSIZE,0,u);
+ if (klen <= 0)
+ {
+ OPENSSL_PUT_ERROR(PEM, PEM_do_header, 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);
+ OPENSSL_cleanse((char *)buf,sizeof(buf));
+ OPENSSL_cleanse((char *)key,sizeof(key));
+ if (!o)
+ {
+ OPENSSL_PUT_ERROR(PEM, PEM_do_header, PEM_R_BAD_DECRYPT);
+ return(0);
+ }
+ j+=i;
+ *plen=j;
+ return(1);
+ }
+
+static const EVP_CIPHER* cipher_by_name(const char *name) {
+ if (strcmp(name, "DES-CBC") == 0) {
+ return EVP_des_cbc();
+ } else if (strcmp(name, "AES-128-CBC") == 0) {
+ return EVP_aes_128_cbc();
+ } else if (strcmp(name, "AES-256-CBC") == 0) {
+ return EVP_aes_256_cbc();
+ } else {
+ return NULL;
+ }
+}
+
+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)
+ { OPENSSL_PUT_ERROR(PEM, PEM_get_EVP_CIPHER_INFO, 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)
+ { OPENSSL_PUT_ERROR(PEM, PEM_get_EVP_CIPHER_INFO, PEM_R_NOT_ENCRYPTED); return(0); }
+ for (; (*header != '\n') && (*header != '\0'); header++)
+ ;
+ if (*header == '\0')
+ { OPENSSL_PUT_ERROR(PEM, PEM_get_EVP_CIPHER_INFO, PEM_R_SHORT_HEADER); return(0); }
+ header++;
+ if (strncmp(header,"DEK-Info: ",10) != 0)
+ { OPENSSL_PUT_ERROR(PEM, PEM_get_EVP_CIPHER_INFO, 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=cipher_by_name(p);
+ *header=c;
+ header++;
+
+ if (enc == NULL)
+ {
+ OPENSSL_PUT_ERROR(PEM, PEM_get_EVP_CIPHER_INFO, PEM_R_UNSUPPORTED_ENCRYPTION);
+ return(0);
+ }
+ if (!load_iv(header_pp,&(cipher->iv[0]),EVP_CIPHER_iv_length(enc)))
+ return(0);
+
+ return(1);
+ }
+
+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
+ {
+ OPENSSL_PUT_ERROR(PEM, load_iv, PEM_R_BAD_IV_CHARS);
+ return(0);
+ }
+ from++;
+ to[i/2]|=v<<(long)((!(i&1))*4);
+ }
+
+ *fromp=from;
+ return(1);
+ }
+
+#ifndef OPENSSL_NO_FP_API
+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)
+ {
+ OPENSSL_PUT_ERROR(PEM, PEM_write, 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);
+ }
+#endif
+
+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;
+
+ i=strlen(header);
+ if (i > 0)
+ {
+ if ( (BIO_write(bp,header,i) != i) ||
+ (BIO_write(bp,"\n",1) != 1))
+ goto err;
+ }
+
+ buf = OPENSSL_malloc(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);
+ EVP_EncodeUpdate(&ctx,buf,&outl,&(data[j]),n);
+ 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;
+ OPENSSL_cleanse(buf, PEM_BUFSIZE*8);
+ OPENSSL_free(buf);
+ 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:
+ if (buf) {
+ OPENSSL_cleanse(buf, PEM_BUFSIZE*8);
+ OPENSSL_free(buf);
+ }
+ OPENSSL_PUT_ERROR(PEM, PEM_write_bio, reason);
+ return(0);
+ }
+
+#ifndef OPENSSL_NO_FP_API
+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)
+ {
+ OPENSSL_PUT_ERROR(PEM, PEM_read, 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);
+ }
+#endif
+
+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);
+ OPENSSL_PUT_ERROR(PEM, PEM_read_bio, ERR_R_MALLOC_FAILURE);
+ return(0);
+ }
+
+ buf[254]='\0';
+ for (;;)
+ {
+ i=BIO_gets(bp,buf,254);
+
+ if (i <= 0)
+ {
+ OPENSSL_PUT_ERROR(PEM, PEM_read_bio, 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))
+ {
+ OPENSSL_PUT_ERROR(PEM, PEM_read_bio, 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))
+ { OPENSSL_PUT_ERROR(PEM, PEM_read_bio, 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))
+ { OPENSSL_PUT_ERROR(PEM, PEM_read_bio, 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))
+ { OPENSSL_PUT_ERROR(PEM, PEM_read_bio, 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))
+ {
+ OPENSSL_PUT_ERROR(PEM, PEM_read_bio, 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))
+ {
+ OPENSSL_PUT_ERROR(PEM, PEM_read_bio, 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)
+ {
+ OPENSSL_PUT_ERROR(PEM, PEM_read_bio, PEM_R_BAD_BASE64_DECODE);
+ goto err;
+ }
+ i=EVP_DecodeFinal(&ctx,(unsigned char *)&(dataB->data[bl]),&k);
+ if (i < 0)
+ {
+ OPENSSL_PUT_ERROR(PEM, PEM_read_bio, 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;
+ OPENSSL_free(nameB);
+ OPENSSL_free(headerB);
+ OPENSSL_free(dataB);
+ return(1);
+err:
+ BUF_MEM_free(nameB);
+ BUF_MEM_free(headerB);
+ BUF_MEM_free(dataB);
+ return(0);
+ }
+
+/* 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/src/crypto/pem/pem_oth.c b/src/crypto/pem/pem_oth.c
new file mode 100644
index 0000000..20d12b6
--- /dev/null
+++ b/src/crypto/pem/pem_oth.c
@@ -0,0 +1,89 @@
+/* crypto/pem/pem_oth.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 <openssl/pem.h>
+
+#include <stdio.h>
+
+#include <openssl/buf.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/evp.h>
+#include <openssl/obj.h>
+#include <openssl/rand.h>
+#include <openssl/x509.h>
+
+
+/* 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)
+ OPENSSL_PUT_ERROR(PEM, PEM_ASN1_read_bio, ERR_R_ASN1_LIB);
+ OPENSSL_free(data);
+ return ret;
+ }
diff --git a/src/crypto/pem/pem_pk8.c b/src/crypto/pem/pem_pk8.c
new file mode 100644
index 0000000..18cfb92
--- /dev/null
+++ b/src/crypto/pem/pem_pk8.c
@@ -0,0 +1,243 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/pem.h>
+
+#include <openssl/buf.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/obj.h>
+#include <openssl/pkcs8.h>
+#include <openssl/rand.h>
+#include <openssl/x509.h>
+
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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))) {
+ OPENSSL_PUT_ERROR(PEM, do_pk8pkey, PEM_R_ERROR_CONVERTING_PRIVATE_KEY);
+ return 0;
+ }
+ if(enc || (nid != -1)) {
+ if(!kstr) {
+ klen = 0;
+ if (cb)
+ klen = cb(buf, PEM_BUFSIZE, 1, u);
+ if(klen <= 0) {
+ OPENSSL_PUT_ERROR(PEM, do_pk8pkey, 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) OPENSSL_cleanse(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;
+
+ klen = 0;
+ if (cb)
+ klen=cb(psbuf,PEM_BUFSIZE,0,u);
+ if (klen <= 0) {
+ OPENSSL_PUT_ERROR(PEM, d2i_PKCS8PrivateKey_bio, 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) {
+ if(*x) EVP_PKEY_free(*x);
+ *x = ret;
+ }
+ return ret;
+}
+
+#ifndef OPENSSL_NO_FP_API
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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))) {
+ OPENSSL_PUT_ERROR(PEM, do_pk8pkey_fp, 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))) {
+ OPENSSL_PUT_ERROR(PEM, d2i_PKCS8PrivateKey_fp, ERR_R_BUF_LIB);
+ return NULL;
+ }
+ ret = d2i_PKCS8PrivateKey_bio(bp, x, cb, u);
+ BIO_free(bp);
+ return ret;
+}
+
+#endif
+
+IMPLEMENT_PEM_rw(PKCS8, X509_SIG, PEM_STRING_PKCS8, X509_SIG)
+IMPLEMENT_PEM_rw(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO, PEM_STRING_PKCS8INF,
+ PKCS8_PRIV_KEY_INFO)
diff --git a/src/crypto/pem/pem_pkey.c b/src/crypto/pem/pem_pkey.c
new file mode 100644
index 0000000..c0aba51
--- /dev/null
+++ b/src/crypto/pem/pem_pkey.c
@@ -0,0 +1,312 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/pem.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include <openssl/buf.h>
+#include <openssl/dh.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/pkcs8.h>
+#include <openssl/rand.h>
+#include <openssl/x509.h>
+
+#include "../evp/internal.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) {
+ if(*x) EVP_PKEY_free((EVP_PKEY *)*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;
+
+ klen = 0;
+ if (cb) klen=cb(psbuf,PEM_BUFSIZE,0,u);
+ if (klen <= 0) {
+ OPENSSL_PUT_ERROR(PEM, PEM_read_bio_PrivateKey, 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) {
+ if(*x) EVP_PKEY_free((EVP_PKEY *)*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)
+ OPENSSL_PUT_ERROR(PEM, PEM_read_bio_PrivateKey, ERR_R_ASN1_LIB);
+
+err:
+ OPENSSL_free(nm);
+ OPENSSL_cleanse(data, len);
+ OPENSSL_free(data);
+ return(ret);
+ }
+
+int PEM_write_bio_PrivateKey(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc,
+ unsigned char *kstr, int klen,
+ pem_password_cb *cb, void *u)
+ {
+ char pem_str[80];
+ if (!x->ameth || x->ameth->priv_encode)
+ return PEM_write_bio_PKCS8PrivateKey(bp, x, enc,
+ (char *)kstr, klen,
+ cb, u);
+
+ BIO_snprintf(pem_str, 80, "%s PRIVATE KEY", x->ameth->pem_str);
+ return PEM_ASN1_write_bio((i2d_of_void *)i2d_PrivateKey,
+ pem_str,bp,x,enc,kstr,klen,cb,u);
+ }
+
+static int public_key_type_from_str(const char *name, size_t len) {
+ if (len == 3 && memcmp(name, "RSA", 3) == 0) {
+ return EVP_PKEY_RSA;
+ } else if (len == 2 && memcmp(name, "DH", 2) == 0) {
+ return EVP_PKEY_DH;
+ } else if (len == 2 && memcmp(name, "EC", 2) == 0) {
+ return EVP_PKEY_EC;
+ }
+ return NID_undef;
+}
+
+static int set_pkey_type_from_str(EVP_PKEY *pkey, const char *name, size_t len) {
+ int nid = public_key_type_from_str(name, len);
+ if (nid == NID_undef) {
+ return 0;
+ }
+ return EVP_PKEY_set_type(pkey, nid);
+}
+
+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 (!set_pkey_type_from_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)
+ {
+ if(*x) EVP_PKEY_free((EVP_PKEY *)*x);
+ *x = ret;
+ }
+ }
+err:
+ if (ret == NULL)
+ OPENSSL_PUT_ERROR(PEM, PEM_read_bio_Parameters, ERR_R_ASN1_LIB);
+ OPENSSL_free(nm);
+ OPENSSL_free(data);
+ return(ret);
+ }
+
+int PEM_write_bio_Parameters(BIO *bp, EVP_PKEY *x)
+ {
+ char pem_str[80];
+ if (!x->ameth || !x->ameth->param_encode)
+ return 0;
+
+ BIO_snprintf(pem_str, 80, "%s PARAMETERS", x->ameth->pem_str);
+ return PEM_ASN1_write_bio(
+ (i2d_of_void *)x->ameth->param_encode,
+ pem_str,bp,x,NULL,NULL,0,0,NULL);
+ }
+
+#ifndef OPENSSL_NO_FP_API
+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)
+ {
+ OPENSSL_PUT_ERROR(PEM, PEM_read_PrivateKey, 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);
+ }
+
+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)
+ {
+ OPENSSL_PUT_ERROR(PEM, PEM_write_PrivateKey, ERR_R_BUF_LIB);
+ return 0;
+ }
+ ret=PEM_write_bio_PrivateKey(b, x, enc, kstr, klen, cb, u);
+ BIO_free(b);
+ return ret;
+ }
+
+#endif
+
+
+/* Transparently read in PKCS#3 or X9.42 DH parameters */
+
+DH *PEM_read_bio_DHparams(BIO *bp, DH **x, pem_password_cb *cb, void *u)
+ {
+ char *nm=NULL;
+ const unsigned char *p=NULL;
+ unsigned char *data=NULL;
+ long len;
+ DH *ret=NULL;
+
+ if (!PEM_bytes_read_bio(&data, &len, &nm, PEM_STRING_DHPARAMS,
+ bp, cb, u))
+ return NULL;
+ p = data;
+
+ /* TODO(fork): remove? */
+ /*if (!strcmp(nm, PEM_STRING_DHXPARAMS))
+ ret = d2i_DHxparams(x, &p, len);
+ else */
+ ret = d2i_DHparams(x, &p, len);
+
+ if (ret == NULL)
+ OPENSSL_PUT_ERROR(PEM, PEM_read_bio_DHparams, ERR_R_ASN1_LIB);
+ OPENSSL_free(nm);
+ OPENSSL_free(data);
+ return ret;
+ }
+
+#ifndef OPENSSL_NO_FP_API
+DH *PEM_read_DHparams(FILE *fp, DH **x, pem_password_cb *cb, void *u)
+ {
+ BIO *b;
+ DH *ret;
+
+ if ((b=BIO_new(BIO_s_file())) == NULL)
+ {
+ OPENSSL_PUT_ERROR(PEM, PEM_read_DHparams, ERR_R_BUF_LIB);
+ return(0);
+ }
+ BIO_set_fp(b,fp,BIO_NOCLOSE);
+ ret=PEM_read_bio_DHparams(b,x,cb,u);
+ BIO_free(b);
+ return(ret);
+ }
+#endif
+
diff --git a/src/crypto/pem/pem_x509.c b/src/crypto/pem/pem_x509.c
new file mode 100644
index 0000000..f463047
--- /dev/null
+++ b/src/crypto/pem/pem_x509.c
@@ -0,0 +1,65 @@
+/* pem_x509.c */
+/* 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 <stdio.h>
+
+#include <openssl/bio.h>
+#include <openssl/evp.h>
+#include <openssl/pem.h>
+#include <openssl/x509.h>
+
+
+IMPLEMENT_PEM_rw(X509, X509, PEM_STRING_X509, X509)
diff --git a/src/crypto/pem/pem_xaux.c b/src/crypto/pem/pem_xaux.c
new file mode 100644
index 0000000..8dabd41
--- /dev/null
+++ b/src/crypto/pem/pem_xaux.c
@@ -0,0 +1,66 @@
+/* pem_xaux.c */
+/* 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 <stdio.h>
+
+#include <openssl/bio.h>
+#include <openssl/evp.h>
+#include <openssl/pem.h>
+#include <openssl/x509.h>
+
+
+IMPLEMENT_PEM_rw(X509_AUX, X509, PEM_STRING_X509_TRUSTED, X509_AUX)
+IMPLEMENT_PEM_rw(X509_CERT_PAIR, X509_CERT_PAIR, PEM_STRING_X509_PAIR, X509_CERT_PAIR)
diff --git a/src/crypto/perlasm/cbc.pl b/src/crypto/perlasm/cbc.pl
new file mode 100644
index 0000000..24561e7
--- /dev/null
+++ b/src/crypto/perlasm/cbc.pl
@@ -0,0 +1,349 @@
+#!/usr/local/bin/perl
+
+# void des_ncbc_encrypt(input, output, length, schedule, ivec, enc)
+# des_cblock (*input);
+# des_cblock (*output);
+# long length;
+# des_key_schedule schedule;
+# des_cblock (*ivec);
+# int enc;
+#
+# calls
+# des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT);
+#
+
+#&cbc("des_ncbc_encrypt","des_encrypt",0);
+#&cbc("BF_cbc_encrypt","BF_encrypt","BF_encrypt",
+# 1,4,5,3,5,-1);
+#&cbc("des_ncbc_encrypt","des_encrypt","des_encrypt",
+# 0,4,5,3,5,-1);
+#&cbc("des_ede3_cbc_encrypt","des_encrypt3","des_decrypt3",
+# 0,6,7,3,4,5);
+#
+# When doing a cipher that needs bigendian order,
+# for encrypt, the iv is kept in bigendian form,
+# while for decrypt, it is kept in little endian.
+sub cbc
+ {
+ local($name,$enc_func,$dec_func,$swap,$iv_off,$enc_off,$p1,$p2,$p3)=@_;
+ # name is the function name
+ # enc_func and dec_func and the functions to call for encrypt/decrypt
+ # swap is true if byte order needs to be reversed
+ # iv_off is parameter number for the iv
+ # enc_off is parameter number for the encrypt/decrypt flag
+ # p1,p2,p3 are the offsets for parameters to be passed to the
+ # underlying calls.
+
+ &function_begin_B($name,"");
+ &comment("");
+
+ $in="esi";
+ $out="edi";
+ $count="ebp";
+
+ &push("ebp");
+ &push("ebx");
+ &push("esi");
+ &push("edi");
+
+ $data_off=4;
+ $data_off+=4 if ($p1 > 0);
+ $data_off+=4 if ($p2 > 0);
+ $data_off+=4 if ($p3 > 0);
+
+ &mov($count, &wparam(2)); # length
+
+ &comment("getting iv ptr from parameter $iv_off");
+ &mov("ebx", &wparam($iv_off)); # Get iv ptr
+
+ &mov($in, &DWP(0,"ebx","",0));# iv[0]
+ &mov($out, &DWP(4,"ebx","",0));# iv[1]
+
+ &push($out);
+ &push($in);
+ &push($out); # used in decrypt for iv[1]
+ &push($in); # used in decrypt for iv[0]
+
+ &mov("ebx", "esp"); # This is the address of tin[2]
+
+ &mov($in, &wparam(0)); # in
+ &mov($out, &wparam(1)); # out
+
+ # We have loaded them all, how lets push things
+ &comment("getting encrypt flag from parameter $enc_off");
+ &mov("ecx", &wparam($enc_off)); # Get enc flag
+ if ($p3 > 0)
+ {
+ &comment("get and push parameter $p3");
+ if ($enc_off != $p3)
+ { &mov("eax", &wparam($p3)); &push("eax"); }
+ else { &push("ecx"); }
+ }
+ if ($p2 > 0)
+ {
+ &comment("get and push parameter $p2");
+ if ($enc_off != $p2)
+ { &mov("eax", &wparam($p2)); &push("eax"); }
+ else { &push("ecx"); }
+ }
+ if ($p1 > 0)
+ {
+ &comment("get and push parameter $p1");
+ if ($enc_off != $p1)
+ { &mov("eax", &wparam($p1)); &push("eax"); }
+ else { &push("ecx"); }
+ }
+ &push("ebx"); # push data/iv
+
+ &cmp("ecx",0);
+ &jz(&label("decrypt"));
+
+ &and($count,0xfffffff8);
+ &mov("eax", &DWP($data_off,"esp","",0)); # load iv[0]
+ &mov("ebx", &DWP($data_off+4,"esp","",0)); # load iv[1]
+
+ &jz(&label("encrypt_finish"));
+
+ #############################################################
+
+ &set_label("encrypt_loop");
+ # encrypt start
+ # "eax" and "ebx" hold iv (or the last cipher text)
+
+ &mov("ecx", &DWP(0,$in,"",0)); # load first 4 bytes
+ &mov("edx", &DWP(4,$in,"",0)); # second 4 bytes
+
+ &xor("eax", "ecx");
+ &xor("ebx", "edx");
+
+ &bswap("eax") if $swap;
+ &bswap("ebx") if $swap;
+
+ &mov(&DWP($data_off,"esp","",0), "eax"); # put in array for call
+ &mov(&DWP($data_off+4,"esp","",0), "ebx"); #
+
+ &call($enc_func);
+
+ &mov("eax", &DWP($data_off,"esp","",0));
+ &mov("ebx", &DWP($data_off+4,"esp","",0));
+
+ &bswap("eax") if $swap;
+ &bswap("ebx") if $swap;
+
+ &mov(&DWP(0,$out,"",0),"eax");
+ &mov(&DWP(4,$out,"",0),"ebx");
+
+ # eax and ebx are the next iv.
+
+ &add($in, 8);
+ &add($out, 8);
+
+ &sub($count, 8);
+ &jnz(&label("encrypt_loop"));
+
+###################################################################3
+ &set_label("encrypt_finish");
+ &mov($count, &wparam(2)); # length
+ &and($count, 7);
+ &jz(&label("finish"));
+ &call(&label("PIC_point"));
+&set_label("PIC_point");
+ &blindpop("edx");
+ &lea("ecx",&DWP(&label("cbc_enc_jmp_table")."-".&label("PIC_point"),"edx"));
+ &mov($count,&DWP(0,"ecx",$count,4));
+ &add($count,"edx");
+ &xor("ecx","ecx");
+ &xor("edx","edx");
+ #&mov($count,&DWP(&label("cbc_enc_jmp_table"),"",$count,4));
+ &jmp_ptr($count);
+
+&set_label("ej7");
+ &movb(&HB("edx"), &BP(6,$in,"",0));
+ &shl("edx",8);
+&set_label("ej6");
+ &movb(&HB("edx"), &BP(5,$in,"",0));
+&set_label("ej5");
+ &movb(&LB("edx"), &BP(4,$in,"",0));
+&set_label("ej4");
+ &mov("ecx", &DWP(0,$in,"",0));
+ &jmp(&label("ejend"));
+&set_label("ej3");
+ &movb(&HB("ecx"), &BP(2,$in,"",0));
+ &shl("ecx",8);
+&set_label("ej2");
+ &movb(&HB("ecx"), &BP(1,$in,"",0));
+&set_label("ej1");
+ &movb(&LB("ecx"), &BP(0,$in,"",0));
+&set_label("ejend");
+
+ &xor("eax", "ecx");
+ &xor("ebx", "edx");
+
+ &bswap("eax") if $swap;
+ &bswap("ebx") if $swap;
+
+ &mov(&DWP($data_off,"esp","",0), "eax"); # put in array for call
+ &mov(&DWP($data_off+4,"esp","",0), "ebx"); #
+
+ &call($enc_func);
+
+ &mov("eax", &DWP($data_off,"esp","",0));
+ &mov("ebx", &DWP($data_off+4,"esp","",0));
+
+ &bswap("eax") if $swap;
+ &bswap("ebx") if $swap;
+
+ &mov(&DWP(0,$out,"",0),"eax");
+ &mov(&DWP(4,$out,"",0),"ebx");
+
+ &jmp(&label("finish"));
+
+ #############################################################
+ #############################################################
+ &set_label("decrypt",1);
+ # decrypt start
+ &and($count,0xfffffff8);
+ # The next 2 instructions are only for if the jz is taken
+ &mov("eax", &DWP($data_off+8,"esp","",0)); # get iv[0]
+ &mov("ebx", &DWP($data_off+12,"esp","",0)); # get iv[1]
+ &jz(&label("decrypt_finish"));
+
+ &set_label("decrypt_loop");
+ &mov("eax", &DWP(0,$in,"",0)); # load first 4 bytes
+ &mov("ebx", &DWP(4,$in,"",0)); # second 4 bytes
+
+ &bswap("eax") if $swap;
+ &bswap("ebx") if $swap;
+
+ &mov(&DWP($data_off,"esp","",0), "eax"); # put back
+ &mov(&DWP($data_off+4,"esp","",0), "ebx"); #
+
+ &call($dec_func);
+
+ &mov("eax", &DWP($data_off,"esp","",0)); # get return
+ &mov("ebx", &DWP($data_off+4,"esp","",0)); #
+
+ &bswap("eax") if $swap;
+ &bswap("ebx") if $swap;
+
+ &mov("ecx", &DWP($data_off+8,"esp","",0)); # get iv[0]
+ &mov("edx", &DWP($data_off+12,"esp","",0)); # get iv[1]
+
+ &xor("ecx", "eax");
+ &xor("edx", "ebx");
+
+ &mov("eax", &DWP(0,$in,"",0)); # get old cipher text,
+ &mov("ebx", &DWP(4,$in,"",0)); # next iv actually
+
+ &mov(&DWP(0,$out,"",0),"ecx");
+ &mov(&DWP(4,$out,"",0),"edx");
+
+ &mov(&DWP($data_off+8,"esp","",0), "eax"); # save iv
+ &mov(&DWP($data_off+12,"esp","",0), "ebx"); #
+
+ &add($in, 8);
+ &add($out, 8);
+
+ &sub($count, 8);
+ &jnz(&label("decrypt_loop"));
+############################ ENDIT #######################3
+ &set_label("decrypt_finish");
+ &mov($count, &wparam(2)); # length
+ &and($count, 7);
+ &jz(&label("finish"));
+
+ &mov("eax", &DWP(0,$in,"",0)); # load first 4 bytes
+ &mov("ebx", &DWP(4,$in,"",0)); # second 4 bytes
+
+ &bswap("eax") if $swap;
+ &bswap("ebx") if $swap;
+
+ &mov(&DWP($data_off,"esp","",0), "eax"); # put back
+ &mov(&DWP($data_off+4,"esp","",0), "ebx"); #
+
+ &call($dec_func);
+
+ &mov("eax", &DWP($data_off,"esp","",0)); # get return
+ &mov("ebx", &DWP($data_off+4,"esp","",0)); #
+
+ &bswap("eax") if $swap;
+ &bswap("ebx") if $swap;
+
+ &mov("ecx", &DWP($data_off+8,"esp","",0)); # get iv[0]
+ &mov("edx", &DWP($data_off+12,"esp","",0)); # get iv[1]
+
+ &xor("ecx", "eax");
+ &xor("edx", "ebx");
+
+ # this is for when we exit
+ &mov("eax", &DWP(0,$in,"",0)); # get old cipher text,
+ &mov("ebx", &DWP(4,$in,"",0)); # next iv actually
+
+&set_label("dj7");
+ &rotr("edx", 16);
+ &movb(&BP(6,$out,"",0), &LB("edx"));
+ &shr("edx",16);
+&set_label("dj6");
+ &movb(&BP(5,$out,"",0), &HB("edx"));
+&set_label("dj5");
+ &movb(&BP(4,$out,"",0), &LB("edx"));
+&set_label("dj4");
+ &mov(&DWP(0,$out,"",0), "ecx");
+ &jmp(&label("djend"));
+&set_label("dj3");
+ &rotr("ecx", 16);
+ &movb(&BP(2,$out,"",0), &LB("ecx"));
+ &shl("ecx",16);
+&set_label("dj2");
+ &movb(&BP(1,$in,"",0), &HB("ecx"));
+&set_label("dj1");
+ &movb(&BP(0,$in,"",0), &LB("ecx"));
+&set_label("djend");
+
+ # final iv is still in eax:ebx
+ &jmp(&label("finish"));
+
+
+############################ FINISH #######################3
+ &set_label("finish",1);
+ &mov("ecx", &wparam($iv_off)); # Get iv ptr
+
+ #################################################
+ $total=16+4;
+ $total+=4 if ($p1 > 0);
+ $total+=4 if ($p2 > 0);
+ $total+=4 if ($p3 > 0);
+ &add("esp",$total);
+
+ &mov(&DWP(0,"ecx","",0), "eax"); # save iv
+ &mov(&DWP(4,"ecx","",0), "ebx"); # save iv
+
+ &function_end_A($name);
+
+ &align(64);
+ &set_label("cbc_enc_jmp_table");
+ &data_word("0");
+ &data_word(&label("ej1")."-".&label("PIC_point"));
+ &data_word(&label("ej2")."-".&label("PIC_point"));
+ &data_word(&label("ej3")."-".&label("PIC_point"));
+ &data_word(&label("ej4")."-".&label("PIC_point"));
+ &data_word(&label("ej5")."-".&label("PIC_point"));
+ &data_word(&label("ej6")."-".&label("PIC_point"));
+ &data_word(&label("ej7")."-".&label("PIC_point"));
+ # not used
+ #&set_label("cbc_dec_jmp_table",1);
+ #&data_word("0");
+ #&data_word(&label("dj1")."-".&label("PIC_point"));
+ #&data_word(&label("dj2")."-".&label("PIC_point"));
+ #&data_word(&label("dj3")."-".&label("PIC_point"));
+ #&data_word(&label("dj4")."-".&label("PIC_point"));
+ #&data_word(&label("dj5")."-".&label("PIC_point"));
+ #&data_word(&label("dj6")."-".&label("PIC_point"));
+ #&data_word(&label("dj7")."-".&label("PIC_point"));
+ &align(64);
+
+ &function_end_B($name);
+
+ }
+
+1;
diff --git a/src/crypto/perlasm/ppc-xlate.pl b/src/crypto/perlasm/ppc-xlate.pl
new file mode 100755
index 0000000..3c1caac
--- /dev/null
+++ b/src/crypto/perlasm/ppc-xlate.pl
@@ -0,0 +1,167 @@
+#!/usr/bin/env perl
+
+# PowerPC assembler distiller by <appro>.
+
+my $flavour = shift;
+my $output = shift;
+open STDOUT,">$output" || die "can't open $output: $!";
+
+my %GLOBALS;
+my $dotinlocallabels=($flavour=~/linux/)?1:0;
+
+################################################################
+# directives which need special treatment on different platforms
+################################################################
+my $globl = sub {
+ my $junk = shift;
+ my $name = shift;
+ my $global = \$GLOBALS{$name};
+ my $ret;
+
+ $name =~ s|^[\.\_]||;
+
+ SWITCH: for ($flavour) {
+ /aix/ && do { $name = ".$name";
+ last;
+ };
+ /osx/ && do { $name = "_$name";
+ last;
+ };
+ /linux.*(32|64le)/
+ && do { $ret .= ".globl $name\n";
+ $ret .= ".type $name,\@function";
+ last;
+ };
+ /linux.*64/ && do { $ret .= ".globl $name\n";
+ $ret .= ".type $name,\@function\n";
+ $ret .= ".section \".opd\",\"aw\"\n";
+ $ret .= ".align 3\n";
+ $ret .= "$name:\n";
+ $ret .= ".quad .$name,.TOC.\@tocbase,0\n";
+ $ret .= ".previous\n";
+
+ $name = ".$name";
+ last;
+ };
+ }
+
+ $ret = ".globl $name" if (!$ret);
+ $$global = $name;
+ $ret;
+};
+my $text = sub {
+ my $ret = ($flavour =~ /aix/) ? ".csect" : ".text";
+ $ret = ".abiversion 2\n".$ret if ($flavour =~ /linux.*64le/);
+ $ret;
+};
+my $machine = sub {
+ my $junk = shift;
+ my $arch = shift;
+ if ($flavour =~ /osx/)
+ { $arch =~ s/\"//g;
+ $arch = ($flavour=~/64/) ? "ppc970-64" : "ppc970" if ($arch eq "any");
+ }
+ ".machine $arch";
+};
+my $size = sub {
+ if ($flavour =~ /linux/)
+ { shift;
+ my $name = shift; $name =~ s|^[\.\_]||;
+ my $ret = ".size $name,.-".($flavour=~/64$/?".":"").$name;
+ $ret .= "\n.size .$name,.-.$name" if ($flavour=~/64$/);
+ $ret;
+ }
+ else
+ { ""; }
+};
+my $asciz = sub {
+ shift;
+ my $line = join(",",@_);
+ if ($line =~ /^"(.*)"$/)
+ { ".byte " . join(",",unpack("C*",$1),0) . "\n.align 2"; }
+ else
+ { ""; }
+};
+
+################################################################
+# simplified mnemonics not handled by at least one assembler
+################################################################
+my $cmplw = sub {
+ my $f = shift;
+ my $cr = 0; $cr = shift if ($#_>1);
+ # Some out-of-date 32-bit GNU assembler just can't handle cmplw...
+ ($flavour =~ /linux.*32/) ?
+ " .long ".sprintf "0x%x",31<<26|$cr<<23|$_[0]<<16|$_[1]<<11|64 :
+ " cmplw ".join(',',$cr,@_);
+};
+my $bdnz = sub {
+ my $f = shift;
+ my $bo = $f=~/[\+\-]/ ? 16+9 : 16; # optional "to be taken" hint
+ " bc $bo,0,".shift;
+} if ($flavour!~/linux/);
+my $bltlr = sub {
+ my $f = shift;
+ my $bo = $f=~/\-/ ? 12+2 : 12; # optional "not to be taken" hint
+ ($flavour =~ /linux/) ? # GNU as doesn't allow most recent hints
+ " .long ".sprintf "0x%x",19<<26|$bo<<21|16<<1 :
+ " bclr $bo,0";
+};
+my $bnelr = sub {
+ my $f = shift;
+ my $bo = $f=~/\-/ ? 4+2 : 4; # optional "not to be taken" hint
+ ($flavour =~ /linux/) ? # GNU as doesn't allow most recent hints
+ " .long ".sprintf "0x%x",19<<26|$bo<<21|2<<16|16<<1 :
+ " bclr $bo,2";
+};
+my $beqlr = sub {
+ my $f = shift;
+ my $bo = $f=~/-/ ? 12+2 : 12; # optional "not to be taken" hint
+ ($flavour =~ /linux/) ? # GNU as doesn't allow most recent hints
+ " .long ".sprintf "0x%X",19<<26|$bo<<21|2<<16|16<<1 :
+ " bclr $bo,2";
+};
+# GNU assembler can't handle extrdi rA,rS,16,48, or when sum of last two
+# arguments is 64, with "operand out of range" error.
+my $extrdi = sub {
+ my ($f,$ra,$rs,$n,$b) = @_;
+ $b = ($b+$n)&63; $n = 64-$n;
+ " rldicl $ra,$rs,$b,$n";
+};
+
+while($line=<>) {
+
+ $line =~ s|[#!;].*$||; # get rid of asm-style comments...
+ $line =~ s|/\*.*\*/||; # ... and C-style comments...
+ $line =~ s|^\s+||; # ... and skip white spaces in beginning...
+ $line =~ s|\s+$||; # ... and at the end
+
+ {
+ $line =~ s|\b\.L(\w+)|L$1|g; # common denominator for Locallabel
+ $line =~ s|\bL(\w+)|\.L$1|g if ($dotinlocallabels);
+ }
+
+ {
+ $line =~ s|(^[\.\w]+)\:\s*||;
+ my $label = $1;
+ if ($label) {
+ printf "%s:",($GLOBALS{$label} or $label);
+ printf "\n.localentry\t$GLOBALS{$label},0" if ($GLOBALS{$label} && $flavour =~ /linux.*64le/);
+ }
+ }
+
+ {
+ $line =~ s|^\s*(\.?)(\w+)([\.\+\-]?)\s*||;
+ my $c = $1; $c = "\t" if ($c eq "");
+ my $mnemonic = $2;
+ my $f = $3;
+ my $opcode = eval("\$$mnemonic");
+ $line =~ s|\bc?[rf]([0-9]+)\b|$1|g if ($c ne "." and $flavour !~ /osx/);
+ if (ref($opcode) eq 'CODE') { $line = &$opcode($f,split(',',$line)); }
+ elsif ($mnemonic) { $line = $c.$mnemonic.$f."\t".$line; }
+ }
+
+ print $line if ($line);
+ print "\n";
+}
+
+close STDOUT;
diff --git a/src/crypto/perlasm/readme b/src/crypto/perlasm/readme
new file mode 100644
index 0000000..f02bbee
--- /dev/null
+++ b/src/crypto/perlasm/readme
@@ -0,0 +1,124 @@
+The perl scripts in this directory are my 'hack' to generate
+multiple different assembler formats via the one origional script.
+
+The way to use this library is to start with adding the path to this directory
+and then include it.
+
+push(@INC,"perlasm","../../perlasm");
+require "x86asm.pl";
+
+The first thing we do is setup the file and type of assember
+
+&asm_init($ARGV[0],$0);
+
+The first argument is the 'type'. Currently
+'cpp', 'sol', 'a.out', 'elf' or 'win32'.
+Argument 2 is the file name.
+
+The reciprocal function is
+&asm_finish() which should be called at the end.
+
+There are 2 main 'packages'. x86ms.pl, which is the microsoft assembler,
+and x86unix.pl which is the unix (gas) version.
+
+Functions of interest are:
+&external_label("des_SPtrans"); declare and external variable
+&LB(reg); Low byte for a register
+&HB(reg); High byte for a register
+&BP(off,base,index,scale) Byte pointer addressing
+&DWP(off,base,index,scale) Word pointer addressing
+&stack_push(num) Basically a 'sub esp, num*4' with extra
+&stack_pop(num) inverse of stack_push
+&function_begin(name,extra) Start a function with pushing of
+ edi, esi, ebx and ebp. extra is extra win32
+ external info that may be required.
+&function_begin_B(name,extra) Same as norma function_begin but no pushing.
+&function_end(name) Call at end of function.
+&function_end_A(name) Standard pop and ret, for use inside functions
+&function_end_B(name) Call at end but with poping or 'ret'.
+&swtmp(num) Address on stack temp word.
+&wparam(num) Parameter number num, that was push
+ in C convention. This all works over pushes
+ and pops.
+&comment("hello there") Put in a comment.
+&label("loop") Refer to a label, normally a jmp target.
+&set_label("loop") Set a label at this point.
+&data_word(word) Put in a word of data.
+
+So how does this all hold together? Given
+
+int calc(int len, int *data)
+ {
+ int i,j=0;
+
+ for (i=0; i<len; i++)
+ {
+ j+=other(data[i]);
+ }
+ }
+
+So a very simple version of this function could be coded as
+
+ push(@INC,"perlasm","../../perlasm");
+ require "x86asm.pl";
+
+ &asm_init($ARGV[0],"cacl.pl");
+
+ &external_label("other");
+
+ $tmp1= "eax";
+ $j= "edi";
+ $data= "esi";
+ $i= "ebp";
+
+ &comment("a simple function");
+ &function_begin("calc");
+ &mov( $data, &wparam(1)); # data
+ &xor( $j, $j);
+ &xor( $i, $i);
+
+ &set_label("loop");
+ &cmp( $i, &wparam(0));
+ &jge( &label("end"));
+
+ &mov( $tmp1, &DWP(0,$data,$i,4));
+ &push( $tmp1);
+ &call( "other");
+ &add( $j, "eax");
+ &pop( $tmp1);
+ &inc( $i);
+ &jmp( &label("loop"));
+
+ &set_label("end");
+ &mov( "eax", $j);
+
+ &function_end("calc");
+
+ &asm_finish();
+
+The above example is very very unoptimised but gives an idea of how
+things work.
+
+There is also a cbc mode function generator in cbc.pl
+
+&cbc( $name,
+ $encrypt_function_name,
+ $decrypt_function_name,
+ $true_if_byte_swap_needed,
+ $parameter_number_for_iv,
+ $parameter_number_for_encrypt_flag,
+ $first_parameter_to_pass,
+ $second_parameter_to_pass,
+ $third_parameter_to_pass);
+
+So for example, given
+void BF_encrypt(BF_LONG *data,BF_KEY *key);
+void BF_decrypt(BF_LONG *data,BF_KEY *key);
+void BF_cbc_encrypt(unsigned char *in, unsigned char *out, long length,
+ BF_KEY *ks, unsigned char *iv, int enc);
+
+&cbc("BF_cbc_encrypt","BF_encrypt","BF_encrypt",1,4,5,3,-1,-1);
+
+&cbc("des_ncbc_encrypt","des_encrypt","des_encrypt",0,4,5,3,5,-1);
+&cbc("des_ede3_cbc_encrypt","des_encrypt3","des_decrypt3",0,6,7,3,4,5);
+
diff --git a/src/crypto/perlasm/sparcv9_modes.pl b/src/crypto/perlasm/sparcv9_modes.pl
new file mode 100644
index 0000000..6b47bb1
--- /dev/null
+++ b/src/crypto/perlasm/sparcv9_modes.pl
@@ -0,0 +1,1680 @@
+#!/usr/bin/env perl
+
+# Specific modes implementations for SPARC Architecture 2011. There
+# is T4 dependency though, an ASI value that is not specified in the
+# Architecture Manual. But as SPARC universe is rather monocultural,
+# we imply that processor capable of executing crypto instructions
+# can handle the ASI in question as well. This means that we ought to
+# keep eyes open when new processors emerge...
+#
+# As for above mentioned ASI. It's so called "block initializing
+# store" which cancels "read" in "read-update-write" on cache lines.
+# This is "cooperative" optimization, as it reduces overall pressure
+# on memory interface. Benefits can't be observed/quantified with
+# usual benchmarks, on the contrary you can notice that single-thread
+# performance for parallelizable modes is ~1.5% worse for largest
+# block sizes [though few percent better for not so long ones]. All
+# this based on suggestions from David Miller.
+
+sub asm_init { # to be called with @ARGV as argument
+ for (@_) { $::abibits=64 if (/\-m64/ || /\-xarch\=v9/); }
+ if ($::abibits==64) { $::bias=2047; $::frame=192; $::size_t_cc="%xcc"; }
+ else { $::bias=0; $::frame=112; $::size_t_cc="%icc"; }
+}
+
+# unified interface
+my ($inp,$out,$len,$key,$ivec)=map("%i$_",(0..5));
+# local variables
+my ($ileft,$iright,$ooff,$omask,$ivoff,$blk_init)=map("%l$_",(0..7));
+
+sub alg_cbc_encrypt_implement {
+my ($alg,$bits) = @_;
+
+$::code.=<<___;
+.globl ${alg}${bits}_t4_cbc_encrypt
+.align 32
+${alg}${bits}_t4_cbc_encrypt:
+ save %sp, -$::frame, %sp
+ sub $inp, $out, $blk_init ! $inp!=$out
+___
+$::code.=<<___ if (!$::evp);
+ andcc $ivec, 7, $ivoff
+ alignaddr $ivec, %g0, $ivec
+
+ ldd [$ivec + 0], %f0 ! load ivec
+ bz,pt %icc, 1f
+ ldd [$ivec + 8], %f2
+ ldd [$ivec + 16], %f4
+ faligndata %f0, %f2, %f0
+ faligndata %f2, %f4, %f2
+1:
+___
+$::code.=<<___ if ($::evp);
+ ld [$ivec + 0], %f0
+ ld [$ivec + 4], %f1
+ ld [$ivec + 8], %f2
+ ld [$ivec + 12], %f3
+___
+$::code.=<<___;
+ prefetch [$inp], 20
+ prefetch [$inp + 63], 20
+ call _${alg}${bits}_load_enckey
+ and $inp, 7, $ileft
+ andn $inp, 7, $inp
+ sll $ileft, 3, $ileft
+ mov 64, $iright
+ mov 0xff, $omask
+ sub $iright, $ileft, $iright
+ and $out, 7, $ooff
+ cmp $len, 127
+ movrnz $ooff, 0, $blk_init ! if ( $out&7 ||
+ movleu $::size_t_cc, 0, $blk_init ! $len<128 ||
+ brnz,pn $blk_init, .L${bits}cbc_enc_blk ! $inp==$out)
+ srl $omask, $ooff, $omask
+
+ alignaddrl $out, %g0, $out
+ srlx $len, 4, $len
+ prefetch [$out], 22
+
+.L${bits}_cbc_enc_loop:
+ ldx [$inp + 0], %o0
+ brz,pt $ileft, 4f
+ ldx [$inp + 8], %o1
+
+ ldx [$inp + 16], %o2
+ sllx %o0, $ileft, %o0
+ srlx %o1, $iright, %g1
+ sllx %o1, $ileft, %o1
+ or %g1, %o0, %o0
+ srlx %o2, $iright, %o2
+ or %o2, %o1, %o1
+4:
+ xor %g4, %o0, %o0 ! ^= rk[0]
+ xor %g5, %o1, %o1
+ movxtod %o0, %f12
+ movxtod %o1, %f14
+
+ fxor %f12, %f0, %f0 ! ^= ivec
+ fxor %f14, %f2, %f2
+ prefetch [$out + 63], 22
+ prefetch [$inp + 16+63], 20
+ call _${alg}${bits}_encrypt_1x
+ add $inp, 16, $inp
+
+ brnz,pn $ooff, 2f
+ sub $len, 1, $len
+
+ std %f0, [$out + 0]
+ std %f2, [$out + 8]
+ brnz,pt $len, .L${bits}_cbc_enc_loop
+ add $out, 16, $out
+___
+$::code.=<<___ if ($::evp);
+ st %f0, [$ivec + 0]
+ st %f1, [$ivec + 4]
+ st %f2, [$ivec + 8]
+ st %f3, [$ivec + 12]
+___
+$::code.=<<___ if (!$::evp);
+ brnz,pn $ivoff, 3f
+ nop
+
+ std %f0, [$ivec + 0] ! write out ivec
+ std %f2, [$ivec + 8]
+___
+$::code.=<<___;
+ ret
+ restore
+
+.align 16
+2: ldxa [$inp]0x82, %o0 ! avoid read-after-write hazard
+ ! and ~3x deterioration
+ ! in inp==out case
+ faligndata %f0, %f0, %f4 ! handle unaligned output
+ faligndata %f0, %f2, %f6
+ faligndata %f2, %f2, %f8
+
+ stda %f4, [$out + $omask]0xc0 ! partial store
+ std %f6, [$out + 8]
+ add $out, 16, $out
+ orn %g0, $omask, $omask
+ stda %f8, [$out + $omask]0xc0 ! partial store
+
+ brnz,pt $len, .L${bits}_cbc_enc_loop+4
+ orn %g0, $omask, $omask
+___
+$::code.=<<___ if ($::evp);
+ st %f0, [$ivec + 0]
+ st %f1, [$ivec + 4]
+ st %f2, [$ivec + 8]
+ st %f3, [$ivec + 12]
+___
+$::code.=<<___ if (!$::evp);
+ brnz,pn $ivoff, 3f
+ nop
+
+ std %f0, [$ivec + 0] ! write out ivec
+ std %f2, [$ivec + 8]
+ ret
+ restore
+
+.align 16
+3: alignaddrl $ivec, $ivoff, %g0 ! handle unaligned ivec
+ mov 0xff, $omask
+ srl $omask, $ivoff, $omask
+ faligndata %f0, %f0, %f4
+ faligndata %f0, %f2, %f6
+ faligndata %f2, %f2, %f8
+ stda %f4, [$ivec + $omask]0xc0
+ std %f6, [$ivec + 8]
+ add $ivec, 16, $ivec
+ orn %g0, $omask, $omask
+ stda %f8, [$ivec + $omask]0xc0
+___
+$::code.=<<___;
+ ret
+ restore
+
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+.align 32
+.L${bits}cbc_enc_blk:
+ add $out, $len, $blk_init
+ and $blk_init, 63, $blk_init ! tail
+ sub $len, $blk_init, $len
+ add $blk_init, 15, $blk_init ! round up to 16n
+ srlx $len, 4, $len
+ srl $blk_init, 4, $blk_init
+
+.L${bits}_cbc_enc_blk_loop:
+ ldx [$inp + 0], %o0
+ brz,pt $ileft, 5f
+ ldx [$inp + 8], %o1
+
+ ldx [$inp + 16], %o2
+ sllx %o0, $ileft, %o0
+ srlx %o1, $iright, %g1
+ sllx %o1, $ileft, %o1
+ or %g1, %o0, %o0
+ srlx %o2, $iright, %o2
+ or %o2, %o1, %o1
+5:
+ xor %g4, %o0, %o0 ! ^= rk[0]
+ xor %g5, %o1, %o1
+ movxtod %o0, %f12
+ movxtod %o1, %f14
+
+ fxor %f12, %f0, %f0 ! ^= ivec
+ fxor %f14, %f2, %f2
+ prefetch [$inp + 16+63], 20
+ call _${alg}${bits}_encrypt_1x
+ add $inp, 16, $inp
+ sub $len, 1, $len
+
+ stda %f0, [$out]0xe2 ! ASI_BLK_INIT, T4-specific
+ add $out, 8, $out
+ stda %f2, [$out]0xe2 ! ASI_BLK_INIT, T4-specific
+ brnz,pt $len, .L${bits}_cbc_enc_blk_loop
+ add $out, 8, $out
+
+ membar #StoreLoad|#StoreStore
+ brnz,pt $blk_init, .L${bits}_cbc_enc_loop
+ mov $blk_init, $len
+___
+$::code.=<<___ if ($::evp);
+ st %f0, [$ivec + 0]
+ st %f1, [$ivec + 4]
+ st %f2, [$ivec + 8]
+ st %f3, [$ivec + 12]
+___
+$::code.=<<___ if (!$::evp);
+ brnz,pn $ivoff, 3b
+ nop
+
+ std %f0, [$ivec + 0] ! write out ivec
+ std %f2, [$ivec + 8]
+___
+$::code.=<<___;
+ ret
+ restore
+.type ${alg}${bits}_t4_cbc_encrypt,#function
+.size ${alg}${bits}_t4_cbc_encrypt,.-${alg}${bits}_t4_cbc_encrypt
+___
+}
+
+sub alg_cbc_decrypt_implement {
+my ($alg,$bits) = @_;
+
+$::code.=<<___;
+.globl ${alg}${bits}_t4_cbc_decrypt
+.align 32
+${alg}${bits}_t4_cbc_decrypt:
+ save %sp, -$::frame, %sp
+ sub $inp, $out, $blk_init ! $inp!=$out
+___
+$::code.=<<___ if (!$::evp);
+ andcc $ivec, 7, $ivoff
+ alignaddr $ivec, %g0, $ivec
+
+ ldd [$ivec + 0], %f12 ! load ivec
+ bz,pt %icc, 1f
+ ldd [$ivec + 8], %f14
+ ldd [$ivec + 16], %f0
+ faligndata %f12, %f14, %f12
+ faligndata %f14, %f0, %f14
+1:
+___
+$::code.=<<___ if ($::evp);
+ ld [$ivec + 0], %f12 ! load ivec
+ ld [$ivec + 4], %f13
+ ld [$ivec + 8], %f14
+ ld [$ivec + 12], %f15
+___
+$::code.=<<___;
+ prefetch [$inp], 20
+ prefetch [$inp + 63], 20
+ call _${alg}${bits}_load_deckey
+ and $inp, 7, $ileft
+ andn $inp, 7, $inp
+ sll $ileft, 3, $ileft
+ mov 64, $iright
+ mov 0xff, $omask
+ sub $iright, $ileft, $iright
+ and $out, 7, $ooff
+ cmp $len, 255
+ movrnz $ooff, 0, $blk_init ! if ( $out&7 ||
+ movleu $::size_t_cc, 0, $blk_init ! $len<256 ||
+ brnz,pn $blk_init, .L${bits}cbc_dec_blk ! $inp==$out)
+ srl $omask, $ooff, $omask
+
+ andcc $len, 16, %g0 ! is number of blocks even?
+ srlx $len, 4, $len
+ alignaddrl $out, %g0, $out
+ bz %icc, .L${bits}_cbc_dec_loop2x
+ prefetch [$out], 22
+.L${bits}_cbc_dec_loop:
+ ldx [$inp + 0], %o0
+ brz,pt $ileft, 4f
+ ldx [$inp + 8], %o1
+
+ ldx [$inp + 16], %o2
+ sllx %o0, $ileft, %o0
+ srlx %o1, $iright, %g1
+ sllx %o1, $ileft, %o1
+ or %g1, %o0, %o0
+ srlx %o2, $iright, %o2
+ or %o2, %o1, %o1
+4:
+ xor %g4, %o0, %o2 ! ^= rk[0]
+ xor %g5, %o1, %o3
+ movxtod %o2, %f0
+ movxtod %o3, %f2
+
+ prefetch [$out + 63], 22
+ prefetch [$inp + 16+63], 20
+ call _${alg}${bits}_decrypt_1x
+ add $inp, 16, $inp
+
+ fxor %f12, %f0, %f0 ! ^= ivec
+ fxor %f14, %f2, %f2
+ movxtod %o0, %f12
+ movxtod %o1, %f14
+
+ brnz,pn $ooff, 2f
+ sub $len, 1, $len
+
+ std %f0, [$out + 0]
+ std %f2, [$out + 8]
+ brnz,pt $len, .L${bits}_cbc_dec_loop2x
+ add $out, 16, $out
+___
+$::code.=<<___ if ($::evp);
+ st %f12, [$ivec + 0]
+ st %f13, [$ivec + 4]
+ st %f14, [$ivec + 8]
+ st %f15, [$ivec + 12]
+___
+$::code.=<<___ if (!$::evp);
+ brnz,pn $ivoff, .L${bits}_cbc_dec_unaligned_ivec
+ nop
+
+ std %f12, [$ivec + 0] ! write out ivec
+ std %f14, [$ivec + 8]
+___
+$::code.=<<___;
+ ret
+ restore
+
+.align 16
+2: ldxa [$inp]0x82, %o0 ! avoid read-after-write hazard
+ ! and ~3x deterioration
+ ! in inp==out case
+ faligndata %f0, %f0, %f4 ! handle unaligned output
+ faligndata %f0, %f2, %f6
+ faligndata %f2, %f2, %f8
+
+ stda %f4, [$out + $omask]0xc0 ! partial store
+ std %f6, [$out + 8]
+ add $out, 16, $out
+ orn %g0, $omask, $omask
+ stda %f8, [$out + $omask]0xc0 ! partial store
+
+ brnz,pt $len, .L${bits}_cbc_dec_loop2x+4
+ orn %g0, $omask, $omask
+___
+$::code.=<<___ if ($::evp);
+ st %f12, [$ivec + 0]
+ st %f13, [$ivec + 4]
+ st %f14, [$ivec + 8]
+ st %f15, [$ivec + 12]
+___
+$::code.=<<___ if (!$::evp);
+ brnz,pn $ivoff, .L${bits}_cbc_dec_unaligned_ivec
+ nop
+
+ std %f12, [$ivec + 0] ! write out ivec
+ std %f14, [$ivec + 8]
+___
+$::code.=<<___;
+ ret
+ restore
+
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+.align 32
+.L${bits}_cbc_dec_loop2x:
+ ldx [$inp + 0], %o0
+ ldx [$inp + 8], %o1
+ ldx [$inp + 16], %o2
+ brz,pt $ileft, 4f
+ ldx [$inp + 24], %o3
+
+ ldx [$inp + 32], %o4
+ sllx %o0, $ileft, %o0
+ srlx %o1, $iright, %g1
+ or %g1, %o0, %o0
+ sllx %o1, $ileft, %o1
+ srlx %o2, $iright, %g1
+ or %g1, %o1, %o1
+ sllx %o2, $ileft, %o2
+ srlx %o3, $iright, %g1
+ or %g1, %o2, %o2
+ sllx %o3, $ileft, %o3
+ srlx %o4, $iright, %o4
+ or %o4, %o3, %o3
+4:
+ xor %g4, %o0, %o4 ! ^= rk[0]
+ xor %g5, %o1, %o5
+ movxtod %o4, %f0
+ movxtod %o5, %f2
+ xor %g4, %o2, %o4
+ xor %g5, %o3, %o5
+ movxtod %o4, %f4
+ movxtod %o5, %f6
+
+ prefetch [$out + 63], 22
+ prefetch [$inp + 32+63], 20
+ call _${alg}${bits}_decrypt_2x
+ add $inp, 32, $inp
+
+ movxtod %o0, %f8
+ movxtod %o1, %f10
+ fxor %f12, %f0, %f0 ! ^= ivec
+ fxor %f14, %f2, %f2
+ movxtod %o2, %f12
+ movxtod %o3, %f14
+ fxor %f8, %f4, %f4
+ fxor %f10, %f6, %f6
+
+ brnz,pn $ooff, 2f
+ sub $len, 2, $len
+
+ std %f0, [$out + 0]
+ std %f2, [$out + 8]
+ std %f4, [$out + 16]
+ std %f6, [$out + 24]
+ brnz,pt $len, .L${bits}_cbc_dec_loop2x
+ add $out, 32, $out
+___
+$::code.=<<___ if ($::evp);
+ st %f12, [$ivec + 0]
+ st %f13, [$ivec + 4]
+ st %f14, [$ivec + 8]
+ st %f15, [$ivec + 12]
+___
+$::code.=<<___ if (!$::evp);
+ brnz,pn $ivoff, .L${bits}_cbc_dec_unaligned_ivec
+ nop
+
+ std %f12, [$ivec + 0] ! write out ivec
+ std %f14, [$ivec + 8]
+___
+$::code.=<<___;
+ ret
+ restore
+
+.align 16
+2: ldxa [$inp]0x82, %o0 ! avoid read-after-write hazard
+ ! and ~3x deterioration
+ ! in inp==out case
+ faligndata %f0, %f0, %f8 ! handle unaligned output
+ faligndata %f0, %f2, %f0
+ faligndata %f2, %f4, %f2
+ faligndata %f4, %f6, %f4
+ faligndata %f6, %f6, %f6
+ stda %f8, [$out + $omask]0xc0 ! partial store
+ std %f0, [$out + 8]
+ std %f2, [$out + 16]
+ std %f4, [$out + 24]
+ add $out, 32, $out
+ orn %g0, $omask, $omask
+ stda %f6, [$out + $omask]0xc0 ! partial store
+
+ brnz,pt $len, .L${bits}_cbc_dec_loop2x+4
+ orn %g0, $omask, $omask
+___
+$::code.=<<___ if ($::evp);
+ st %f12, [$ivec + 0]
+ st %f13, [$ivec + 4]
+ st %f14, [$ivec + 8]
+ st %f15, [$ivec + 12]
+___
+$::code.=<<___ if (!$::evp);
+ brnz,pn $ivoff, .L${bits}_cbc_dec_unaligned_ivec
+ nop
+
+ std %f12, [$ivec + 0] ! write out ivec
+ std %f14, [$ivec + 8]
+ ret
+ restore
+
+.align 16
+.L${bits}_cbc_dec_unaligned_ivec:
+ alignaddrl $ivec, $ivoff, %g0 ! handle unaligned ivec
+ mov 0xff, $omask
+ srl $omask, $ivoff, $omask
+ faligndata %f12, %f12, %f0
+ faligndata %f12, %f14, %f2
+ faligndata %f14, %f14, %f4
+ stda %f0, [$ivec + $omask]0xc0
+ std %f2, [$ivec + 8]
+ add $ivec, 16, $ivec
+ orn %g0, $omask, $omask
+ stda %f4, [$ivec + $omask]0xc0
+___
+$::code.=<<___;
+ ret
+ restore
+
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+.align 32
+.L${bits}cbc_dec_blk:
+ add $out, $len, $blk_init
+ and $blk_init, 63, $blk_init ! tail
+ sub $len, $blk_init, $len
+ add $blk_init, 15, $blk_init ! round up to 16n
+ srlx $len, 4, $len
+ srl $blk_init, 4, $blk_init
+ sub $len, 1, $len
+ add $blk_init, 1, $blk_init
+
+.L${bits}_cbc_dec_blk_loop2x:
+ ldx [$inp + 0], %o0
+ ldx [$inp + 8], %o1
+ ldx [$inp + 16], %o2
+ brz,pt $ileft, 5f
+ ldx [$inp + 24], %o3
+
+ ldx [$inp + 32], %o4
+ sllx %o0, $ileft, %o0
+ srlx %o1, $iright, %g1
+ or %g1, %o0, %o0
+ sllx %o1, $ileft, %o1
+ srlx %o2, $iright, %g1
+ or %g1, %o1, %o1
+ sllx %o2, $ileft, %o2
+ srlx %o3, $iright, %g1
+ or %g1, %o2, %o2
+ sllx %o3, $ileft, %o3
+ srlx %o4, $iright, %o4
+ or %o4, %o3, %o3
+5:
+ xor %g4, %o0, %o4 ! ^= rk[0]
+ xor %g5, %o1, %o5
+ movxtod %o4, %f0
+ movxtod %o5, %f2
+ xor %g4, %o2, %o4
+ xor %g5, %o3, %o5
+ movxtod %o4, %f4
+ movxtod %o5, %f6
+
+ prefetch [$inp + 32+63], 20
+ call _${alg}${bits}_decrypt_2x
+ add $inp, 32, $inp
+ subcc $len, 2, $len
+
+ movxtod %o0, %f8
+ movxtod %o1, %f10
+ fxor %f12, %f0, %f0 ! ^= ivec
+ fxor %f14, %f2, %f2
+ movxtod %o2, %f12
+ movxtod %o3, %f14
+ fxor %f8, %f4, %f4
+ fxor %f10, %f6, %f6
+
+ stda %f0, [$out]0xe2 ! ASI_BLK_INIT, T4-specific
+ add $out, 8, $out
+ stda %f2, [$out]0xe2 ! ASI_BLK_INIT, T4-specific
+ add $out, 8, $out
+ stda %f4, [$out]0xe2 ! ASI_BLK_INIT, T4-specific
+ add $out, 8, $out
+ stda %f6, [$out]0xe2 ! ASI_BLK_INIT, T4-specific
+ bgu,pt $::size_t_cc, .L${bits}_cbc_dec_blk_loop2x
+ add $out, 8, $out
+
+ add $blk_init, $len, $len
+ andcc $len, 1, %g0 ! is number of blocks even?
+ membar #StoreLoad|#StoreStore
+ bnz,pt %icc, .L${bits}_cbc_dec_loop
+ srl $len, 0, $len
+ brnz,pn $len, .L${bits}_cbc_dec_loop2x
+ nop
+___
+$::code.=<<___ if ($::evp);
+ st %f12, [$ivec + 0] ! write out ivec
+ st %f13, [$ivec + 4]
+ st %f14, [$ivec + 8]
+ st %f15, [$ivec + 12]
+___
+$::code.=<<___ if (!$::evp);
+ brnz,pn $ivoff, 3b
+ nop
+
+ std %f12, [$ivec + 0] ! write out ivec
+ std %f14, [$ivec + 8]
+___
+$::code.=<<___;
+ ret
+ restore
+.type ${alg}${bits}_t4_cbc_decrypt,#function
+.size ${alg}${bits}_t4_cbc_decrypt,.-${alg}${bits}_t4_cbc_decrypt
+___
+}
+
+sub alg_ctr32_implement {
+my ($alg,$bits) = @_;
+
+$::code.=<<___;
+.globl ${alg}${bits}_t4_ctr32_encrypt
+.align 32
+${alg}${bits}_t4_ctr32_encrypt:
+ save %sp, -$::frame, %sp
+
+ prefetch [$inp], 20
+ prefetch [$inp + 63], 20
+ call _${alg}${bits}_load_enckey
+ sllx $len, 4, $len
+
+ ld [$ivec + 0], %l4 ! counter
+ ld [$ivec + 4], %l5
+ ld [$ivec + 8], %l6
+ ld [$ivec + 12], %l7
+
+ sllx %l4, 32, %o5
+ or %l5, %o5, %o5
+ sllx %l6, 32, %g1
+ xor %o5, %g4, %g4 ! ^= rk[0]
+ xor %g1, %g5, %g5
+ movxtod %g4, %f14 ! most significant 64 bits
+
+ sub $inp, $out, $blk_init ! $inp!=$out
+ and $inp, 7, $ileft
+ andn $inp, 7, $inp
+ sll $ileft, 3, $ileft
+ mov 64, $iright
+ mov 0xff, $omask
+ sub $iright, $ileft, $iright
+ and $out, 7, $ooff
+ cmp $len, 255
+ movrnz $ooff, 0, $blk_init ! if ( $out&7 ||
+ movleu $::size_t_cc, 0, $blk_init ! $len<256 ||
+ brnz,pn $blk_init, .L${bits}_ctr32_blk ! $inp==$out)
+ srl $omask, $ooff, $omask
+
+ andcc $len, 16, %g0 ! is number of blocks even?
+ alignaddrl $out, %g0, $out
+ bz %icc, .L${bits}_ctr32_loop2x
+ srlx $len, 4, $len
+.L${bits}_ctr32_loop:
+ ldx [$inp + 0], %o0
+ brz,pt $ileft, 4f
+ ldx [$inp + 8], %o1
+
+ ldx [$inp + 16], %o2
+ sllx %o0, $ileft, %o0
+ srlx %o1, $iright, %g1
+ sllx %o1, $ileft, %o1
+ or %g1, %o0, %o0
+ srlx %o2, $iright, %o2
+ or %o2, %o1, %o1
+4:
+ xor %g5, %l7, %g1 ! ^= rk[0]
+ add %l7, 1, %l7
+ movxtod %g1, %f2
+ srl %l7, 0, %l7 ! clruw
+ prefetch [$out + 63], 22
+ prefetch [$inp + 16+63], 20
+___
+$::code.=<<___ if ($alg eq "aes");
+ aes_eround01 %f16, %f14, %f2, %f4
+ aes_eround23 %f18, %f14, %f2, %f2
+___
+$::code.=<<___ if ($alg eq "cmll");
+ camellia_f %f16, %f2, %f14, %f2
+ camellia_f %f18, %f14, %f2, %f0
+___
+$::code.=<<___;
+ call _${alg}${bits}_encrypt_1x+8
+ add $inp, 16, $inp
+
+ movxtod %o0, %f10
+ movxtod %o1, %f12
+ fxor %f10, %f0, %f0 ! ^= inp
+ fxor %f12, %f2, %f2
+
+ brnz,pn $ooff, 2f
+ sub $len, 1, $len
+
+ std %f0, [$out + 0]
+ std %f2, [$out + 8]
+ brnz,pt $len, .L${bits}_ctr32_loop2x
+ add $out, 16, $out
+
+ ret
+ restore
+
+.align 16
+2: ldxa [$inp]0x82, %o0 ! avoid read-after-write hazard
+ ! and ~3x deterioration
+ ! in inp==out case
+ faligndata %f0, %f0, %f4 ! handle unaligned output
+ faligndata %f0, %f2, %f6
+ faligndata %f2, %f2, %f8
+ stda %f4, [$out + $omask]0xc0 ! partial store
+ std %f6, [$out + 8]
+ add $out, 16, $out
+ orn %g0, $omask, $omask
+ stda %f8, [$out + $omask]0xc0 ! partial store
+
+ brnz,pt $len, .L${bits}_ctr32_loop2x+4
+ orn %g0, $omask, $omask
+
+ ret
+ restore
+
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+.align 32
+.L${bits}_ctr32_loop2x:
+ ldx [$inp + 0], %o0
+ ldx [$inp + 8], %o1
+ ldx [$inp + 16], %o2
+ brz,pt $ileft, 4f
+ ldx [$inp + 24], %o3
+
+ ldx [$inp + 32], %o4
+ sllx %o0, $ileft, %o0
+ srlx %o1, $iright, %g1
+ or %g1, %o0, %o0
+ sllx %o1, $ileft, %o1
+ srlx %o2, $iright, %g1
+ or %g1, %o1, %o1
+ sllx %o2, $ileft, %o2
+ srlx %o3, $iright, %g1
+ or %g1, %o2, %o2
+ sllx %o3, $ileft, %o3
+ srlx %o4, $iright, %o4
+ or %o4, %o3, %o3
+4:
+ xor %g5, %l7, %g1 ! ^= rk[0]
+ add %l7, 1, %l7
+ movxtod %g1, %f2
+ srl %l7, 0, %l7 ! clruw
+ xor %g5, %l7, %g1
+ add %l7, 1, %l7
+ movxtod %g1, %f6
+ srl %l7, 0, %l7 ! clruw
+ prefetch [$out + 63], 22
+ prefetch [$inp + 32+63], 20
+___
+$::code.=<<___ if ($alg eq "aes");
+ aes_eround01 %f16, %f14, %f2, %f8
+ aes_eround23 %f18, %f14, %f2, %f2
+ aes_eround01 %f16, %f14, %f6, %f10
+ aes_eround23 %f18, %f14, %f6, %f6
+___
+$::code.=<<___ if ($alg eq "cmll");
+ camellia_f %f16, %f2, %f14, %f2
+ camellia_f %f16, %f6, %f14, %f6
+ camellia_f %f18, %f14, %f2, %f0
+ camellia_f %f18, %f14, %f6, %f4
+___
+$::code.=<<___;
+ call _${alg}${bits}_encrypt_2x+16
+ add $inp, 32, $inp
+
+ movxtod %o0, %f8
+ movxtod %o1, %f10
+ movxtod %o2, %f12
+ fxor %f8, %f0, %f0 ! ^= inp
+ movxtod %o3, %f8
+ fxor %f10, %f2, %f2
+ fxor %f12, %f4, %f4
+ fxor %f8, %f6, %f6
+
+ brnz,pn $ooff, 2f
+ sub $len, 2, $len
+
+ std %f0, [$out + 0]
+ std %f2, [$out + 8]
+ std %f4, [$out + 16]
+ std %f6, [$out + 24]
+ brnz,pt $len, .L${bits}_ctr32_loop2x
+ add $out, 32, $out
+
+ ret
+ restore
+
+.align 16
+2: ldxa [$inp]0x82, %o0 ! avoid read-after-write hazard
+ ! and ~3x deterioration
+ ! in inp==out case
+ faligndata %f0, %f0, %f8 ! handle unaligned output
+ faligndata %f0, %f2, %f0
+ faligndata %f2, %f4, %f2
+ faligndata %f4, %f6, %f4
+ faligndata %f6, %f6, %f6
+
+ stda %f8, [$out + $omask]0xc0 ! partial store
+ std %f0, [$out + 8]
+ std %f2, [$out + 16]
+ std %f4, [$out + 24]
+ add $out, 32, $out
+ orn %g0, $omask, $omask
+ stda %f6, [$out + $omask]0xc0 ! partial store
+
+ brnz,pt $len, .L${bits}_ctr32_loop2x+4
+ orn %g0, $omask, $omask
+
+ ret
+ restore
+
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+.align 32
+.L${bits}_ctr32_blk:
+ add $out, $len, $blk_init
+ and $blk_init, 63, $blk_init ! tail
+ sub $len, $blk_init, $len
+ add $blk_init, 15, $blk_init ! round up to 16n
+ srlx $len, 4, $len
+ srl $blk_init, 4, $blk_init
+ sub $len, 1, $len
+ add $blk_init, 1, $blk_init
+
+.L${bits}_ctr32_blk_loop2x:
+ ldx [$inp + 0], %o0
+ ldx [$inp + 8], %o1
+ ldx [$inp + 16], %o2
+ brz,pt $ileft, 5f
+ ldx [$inp + 24], %o3
+
+ ldx [$inp + 32], %o4
+ sllx %o0, $ileft, %o0
+ srlx %o1, $iright, %g1
+ or %g1, %o0, %o0
+ sllx %o1, $ileft, %o1
+ srlx %o2, $iright, %g1
+ or %g1, %o1, %o1
+ sllx %o2, $ileft, %o2
+ srlx %o3, $iright, %g1
+ or %g1, %o2, %o2
+ sllx %o3, $ileft, %o3
+ srlx %o4, $iright, %o4
+ or %o4, %o3, %o3
+5:
+ xor %g5, %l7, %g1 ! ^= rk[0]
+ add %l7, 1, %l7
+ movxtod %g1, %f2
+ srl %l7, 0, %l7 ! clruw
+ xor %g5, %l7, %g1
+ add %l7, 1, %l7
+ movxtod %g1, %f6
+ srl %l7, 0, %l7 ! clruw
+ prefetch [$inp + 32+63], 20
+___
+$::code.=<<___ if ($alg eq "aes");
+ aes_eround01 %f16, %f14, %f2, %f8
+ aes_eround23 %f18, %f14, %f2, %f2
+ aes_eround01 %f16, %f14, %f6, %f10
+ aes_eround23 %f18, %f14, %f6, %f6
+___
+$::code.=<<___ if ($alg eq "cmll");
+ camellia_f %f16, %f2, %f14, %f2
+ camellia_f %f16, %f6, %f14, %f6
+ camellia_f %f18, %f14, %f2, %f0
+ camellia_f %f18, %f14, %f6, %f4
+___
+$::code.=<<___;
+ call _${alg}${bits}_encrypt_2x+16
+ add $inp, 32, $inp
+ subcc $len, 2, $len
+
+ movxtod %o0, %f8
+ movxtod %o1, %f10
+ movxtod %o2, %f12
+ fxor %f8, %f0, %f0 ! ^= inp
+ movxtod %o3, %f8
+ fxor %f10, %f2, %f2
+ fxor %f12, %f4, %f4
+ fxor %f8, %f6, %f6
+
+ stda %f0, [$out]0xe2 ! ASI_BLK_INIT, T4-specific
+ add $out, 8, $out
+ stda %f2, [$out]0xe2 ! ASI_BLK_INIT, T4-specific
+ add $out, 8, $out
+ stda %f4, [$out]0xe2 ! ASI_BLK_INIT, T4-specific
+ add $out, 8, $out
+ stda %f6, [$out]0xe2 ! ASI_BLK_INIT, T4-specific
+ bgu,pt $::size_t_cc, .L${bits}_ctr32_blk_loop2x
+ add $out, 8, $out
+
+ add $blk_init, $len, $len
+ andcc $len, 1, %g0 ! is number of blocks even?
+ membar #StoreLoad|#StoreStore
+ bnz,pt %icc, .L${bits}_ctr32_loop
+ srl $len, 0, $len
+ brnz,pn $len, .L${bits}_ctr32_loop2x
+ nop
+
+ ret
+ restore
+.type ${alg}${bits}_t4_ctr32_encrypt,#function
+.size ${alg}${bits}_t4_ctr32_encrypt,.-${alg}${bits}_t4_ctr32_encrypt
+___
+}
+
+sub alg_xts_implement {
+my ($alg,$bits,$dir) = @_;
+my ($inp,$out,$len,$key1,$key2,$ivec)=map("%i$_",(0..5));
+my $rem=$ivec;
+
+$::code.=<<___;
+.globl ${alg}${bits}_t4_xts_${dir}crypt
+.align 32
+${alg}${bits}_t4_xts_${dir}crypt:
+ save %sp, -$::frame-16, %sp
+
+ mov $ivec, %o0
+ add %fp, $::bias-16, %o1
+ call ${alg}_t4_encrypt
+ mov $key2, %o2
+
+ add %fp, $::bias-16, %l7
+ ldxa [%l7]0x88, %g2
+ add %fp, $::bias-8, %l7
+ ldxa [%l7]0x88, %g3 ! %g3:%g2 is tweak
+
+ sethi %hi(0x76543210), %l7
+ or %l7, %lo(0x76543210), %l7
+ bmask %l7, %g0, %g0 ! byte swap mask
+
+ prefetch [$inp], 20
+ prefetch [$inp + 63], 20
+ call _${alg}${bits}_load_${dir}ckey
+ and $len, 15, $rem
+ and $len, -16, $len
+___
+$code.=<<___ if ($dir eq "de");
+ mov 0, %l7
+ movrnz $rem, 16, %l7
+ sub $len, %l7, $len
+___
+$code.=<<___;
+
+ sub $inp, $out, $blk_init ! $inp!=$out
+ and $inp, 7, $ileft
+ andn $inp, 7, $inp
+ sll $ileft, 3, $ileft
+ mov 64, $iright
+ mov 0xff, $omask
+ sub $iright, $ileft, $iright
+ and $out, 7, $ooff
+ cmp $len, 255
+ movrnz $ooff, 0, $blk_init ! if ( $out&7 ||
+ movleu $::size_t_cc, 0, $blk_init ! $len<256 ||
+ brnz,pn $blk_init, .L${bits}_xts_${dir}blk ! $inp==$out)
+ srl $omask, $ooff, $omask
+
+ andcc $len, 16, %g0 ! is number of blocks even?
+___
+$code.=<<___ if ($dir eq "de");
+ brz,pn $len, .L${bits}_xts_${dir}steal
+___
+$code.=<<___;
+ alignaddrl $out, %g0, $out
+ bz %icc, .L${bits}_xts_${dir}loop2x
+ srlx $len, 4, $len
+.L${bits}_xts_${dir}loop:
+ ldx [$inp + 0], %o0
+ brz,pt $ileft, 4f
+ ldx [$inp + 8], %o1
+
+ ldx [$inp + 16], %o2
+ sllx %o0, $ileft, %o0
+ srlx %o1, $iright, %g1
+ sllx %o1, $ileft, %o1
+ or %g1, %o0, %o0
+ srlx %o2, $iright, %o2
+ or %o2, %o1, %o1
+4:
+ movxtod %g2, %f12
+ movxtod %g3, %f14
+ bshuffle %f12, %f12, %f12
+ bshuffle %f14, %f14, %f14
+
+ xor %g4, %o0, %o0 ! ^= rk[0]
+ xor %g5, %o1, %o1
+ movxtod %o0, %f0
+ movxtod %o1, %f2
+
+ fxor %f12, %f0, %f0 ! ^= tweak[0]
+ fxor %f14, %f2, %f2
+
+ prefetch [$out + 63], 22
+ prefetch [$inp + 16+63], 20
+ call _${alg}${bits}_${dir}crypt_1x
+ add $inp, 16, $inp
+
+ fxor %f12, %f0, %f0 ! ^= tweak[0]
+ fxor %f14, %f2, %f2
+
+ srax %g3, 63, %l7 ! next tweak value
+ addcc %g2, %g2, %g2
+ and %l7, 0x87, %l7
+ addxc %g3, %g3, %g3
+ xor %l7, %g2, %g2
+
+ brnz,pn $ooff, 2f
+ sub $len, 1, $len
+
+ std %f0, [$out + 0]
+ std %f2, [$out + 8]
+ brnz,pt $len, .L${bits}_xts_${dir}loop2x
+ add $out, 16, $out
+
+ brnz,pn $rem, .L${bits}_xts_${dir}steal
+ nop
+
+ ret
+ restore
+
+.align 16
+2: ldxa [$inp]0x82, %o0 ! avoid read-after-write hazard
+ ! and ~3x deterioration
+ ! in inp==out case
+ faligndata %f0, %f0, %f4 ! handle unaligned output
+ faligndata %f0, %f2, %f6
+ faligndata %f2, %f2, %f8
+ stda %f4, [$out + $omask]0xc0 ! partial store
+ std %f6, [$out + 8]
+ add $out, 16, $out
+ orn %g0, $omask, $omask
+ stda %f8, [$out + $omask]0xc0 ! partial store
+
+ brnz,pt $len, .L${bits}_xts_${dir}loop2x+4
+ orn %g0, $omask, $omask
+
+ brnz,pn $rem, .L${bits}_xts_${dir}steal
+ nop
+
+ ret
+ restore
+
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+.align 32
+.L${bits}_xts_${dir}loop2x:
+ ldx [$inp + 0], %o0
+ ldx [$inp + 8], %o1
+ ldx [$inp + 16], %o2
+ brz,pt $ileft, 4f
+ ldx [$inp + 24], %o3
+
+ ldx [$inp + 32], %o4
+ sllx %o0, $ileft, %o0
+ srlx %o1, $iright, %g1
+ or %g1, %o0, %o0
+ sllx %o1, $ileft, %o1
+ srlx %o2, $iright, %g1
+ or %g1, %o1, %o1
+ sllx %o2, $ileft, %o2
+ srlx %o3, $iright, %g1
+ or %g1, %o2, %o2
+ sllx %o3, $ileft, %o3
+ srlx %o4, $iright, %o4
+ or %o4, %o3, %o3
+4:
+ movxtod %g2, %f12
+ movxtod %g3, %f14
+ bshuffle %f12, %f12, %f12
+ bshuffle %f14, %f14, %f14
+
+ srax %g3, 63, %l7 ! next tweak value
+ addcc %g2, %g2, %g2
+ and %l7, 0x87, %l7
+ addxc %g3, %g3, %g3
+ xor %l7, %g2, %g2
+
+ movxtod %g2, %f8
+ movxtod %g3, %f10
+ bshuffle %f8, %f8, %f8
+ bshuffle %f10, %f10, %f10
+
+ xor %g4, %o0, %o0 ! ^= rk[0]
+ xor %g5, %o1, %o1
+ xor %g4, %o2, %o2 ! ^= rk[0]
+ xor %g5, %o3, %o3
+ movxtod %o0, %f0
+ movxtod %o1, %f2
+ movxtod %o2, %f4
+ movxtod %o3, %f6
+
+ fxor %f12, %f0, %f0 ! ^= tweak[0]
+ fxor %f14, %f2, %f2
+ fxor %f8, %f4, %f4 ! ^= tweak[0]
+ fxor %f10, %f6, %f6
+
+ prefetch [$out + 63], 22
+ prefetch [$inp + 32+63], 20
+ call _${alg}${bits}_${dir}crypt_2x
+ add $inp, 32, $inp
+
+ movxtod %g2, %f8
+ movxtod %g3, %f10
+
+ srax %g3, 63, %l7 ! next tweak value
+ addcc %g2, %g2, %g2
+ and %l7, 0x87, %l7
+ addxc %g3, %g3, %g3
+ xor %l7, %g2, %g2
+
+ bshuffle %f8, %f8, %f8
+ bshuffle %f10, %f10, %f10
+
+ fxor %f12, %f0, %f0 ! ^= tweak[0]
+ fxor %f14, %f2, %f2
+ fxor %f8, %f4, %f4
+ fxor %f10, %f6, %f6
+
+ brnz,pn $ooff, 2f
+ sub $len, 2, $len
+
+ std %f0, [$out + 0]
+ std %f2, [$out + 8]
+ std %f4, [$out + 16]
+ std %f6, [$out + 24]
+ brnz,pt $len, .L${bits}_xts_${dir}loop2x
+ add $out, 32, $out
+
+ fsrc2 %f4, %f0
+ fsrc2 %f6, %f2
+ brnz,pn $rem, .L${bits}_xts_${dir}steal
+ nop
+
+ ret
+ restore
+
+.align 16
+2: ldxa [$inp]0x82, %o0 ! avoid read-after-write hazard
+ ! and ~3x deterioration
+ ! in inp==out case
+ faligndata %f0, %f0, %f8 ! handle unaligned output
+ faligndata %f0, %f2, %f10
+ faligndata %f2, %f4, %f12
+ faligndata %f4, %f6, %f14
+ faligndata %f6, %f6, %f0
+
+ stda %f8, [$out + $omask]0xc0 ! partial store
+ std %f10, [$out + 8]
+ std %f12, [$out + 16]
+ std %f14, [$out + 24]
+ add $out, 32, $out
+ orn %g0, $omask, $omask
+ stda %f0, [$out + $omask]0xc0 ! partial store
+
+ brnz,pt $len, .L${bits}_xts_${dir}loop2x+4
+ orn %g0, $omask, $omask
+
+ fsrc2 %f4, %f0
+ fsrc2 %f6, %f2
+ brnz,pn $rem, .L${bits}_xts_${dir}steal
+ nop
+
+ ret
+ restore
+
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+.align 32
+.L${bits}_xts_${dir}blk:
+ add $out, $len, $blk_init
+ and $blk_init, 63, $blk_init ! tail
+ sub $len, $blk_init, $len
+ add $blk_init, 15, $blk_init ! round up to 16n
+ srlx $len, 4, $len
+ srl $blk_init, 4, $blk_init
+ sub $len, 1, $len
+ add $blk_init, 1, $blk_init
+
+.L${bits}_xts_${dir}blk2x:
+ ldx [$inp + 0], %o0
+ ldx [$inp + 8], %o1
+ ldx [$inp + 16], %o2
+ brz,pt $ileft, 5f
+ ldx [$inp + 24], %o3
+
+ ldx [$inp + 32], %o4
+ sllx %o0, $ileft, %o0
+ srlx %o1, $iright, %g1
+ or %g1, %o0, %o0
+ sllx %o1, $ileft, %o1
+ srlx %o2, $iright, %g1
+ or %g1, %o1, %o1
+ sllx %o2, $ileft, %o2
+ srlx %o3, $iright, %g1
+ or %g1, %o2, %o2
+ sllx %o3, $ileft, %o3
+ srlx %o4, $iright, %o4
+ or %o4, %o3, %o3
+5:
+ movxtod %g2, %f12
+ movxtod %g3, %f14
+ bshuffle %f12, %f12, %f12
+ bshuffle %f14, %f14, %f14
+
+ srax %g3, 63, %l7 ! next tweak value
+ addcc %g2, %g2, %g2
+ and %l7, 0x87, %l7
+ addxc %g3, %g3, %g3
+ xor %l7, %g2, %g2
+
+ movxtod %g2, %f8
+ movxtod %g3, %f10
+ bshuffle %f8, %f8, %f8
+ bshuffle %f10, %f10, %f10
+
+ xor %g4, %o0, %o0 ! ^= rk[0]
+ xor %g5, %o1, %o1
+ xor %g4, %o2, %o2 ! ^= rk[0]
+ xor %g5, %o3, %o3
+ movxtod %o0, %f0
+ movxtod %o1, %f2
+ movxtod %o2, %f4
+ movxtod %o3, %f6
+
+ fxor %f12, %f0, %f0 ! ^= tweak[0]
+ fxor %f14, %f2, %f2
+ fxor %f8, %f4, %f4 ! ^= tweak[0]
+ fxor %f10, %f6, %f6
+
+ prefetch [$inp + 32+63], 20
+ call _${alg}${bits}_${dir}crypt_2x
+ add $inp, 32, $inp
+
+ movxtod %g2, %f8
+ movxtod %g3, %f10
+
+ srax %g3, 63, %l7 ! next tweak value
+ addcc %g2, %g2, %g2
+ and %l7, 0x87, %l7
+ addxc %g3, %g3, %g3
+ xor %l7, %g2, %g2
+
+ bshuffle %f8, %f8, %f8
+ bshuffle %f10, %f10, %f10
+
+ fxor %f12, %f0, %f0 ! ^= tweak[0]
+ fxor %f14, %f2, %f2
+ fxor %f8, %f4, %f4
+ fxor %f10, %f6, %f6
+
+ stda %f0, [$out]0xe2 ! ASI_BLK_INIT, T4-specific
+ add $out, 8, $out
+ stda %f2, [$out]0xe2 ! ASI_BLK_INIT, T4-specific
+ add $out, 8, $out
+ stda %f4, [$out]0xe2 ! ASI_BLK_INIT, T4-specific
+ add $out, 8, $out
+ stda %f6, [$out]0xe2 ! ASI_BLK_INIT, T4-specific
+ bgu,pt $::size_t_cc, .L${bits}_xts_${dir}blk2x
+ add $out, 8, $out
+
+ add $blk_init, $len, $len
+ andcc $len, 1, %g0 ! is number of blocks even?
+ membar #StoreLoad|#StoreStore
+ bnz,pt %icc, .L${bits}_xts_${dir}loop
+ srl $len, 0, $len
+ brnz,pn $len, .L${bits}_xts_${dir}loop2x
+ nop
+
+ fsrc2 %f4, %f0
+ fsrc2 %f6, %f2
+ brnz,pn $rem, .L${bits}_xts_${dir}steal
+ nop
+
+ ret
+ restore
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+___
+$code.=<<___ if ($dir eq "en");
+.align 32
+.L${bits}_xts_${dir}steal:
+ std %f0, [%fp + $::bias-16] ! copy of output
+ std %f2, [%fp + $::bias-8]
+
+ srl $ileft, 3, $ileft
+ add %fp, $::bias-16, %l7
+ add $inp, $ileft, $inp ! original $inp+$len&-15
+ add $out, $ooff, $out ! original $out+$len&-15
+ mov 0, $ileft
+ nop ! align
+
+.L${bits}_xts_${dir}stealing:
+ ldub [$inp + $ileft], %o0
+ ldub [%l7 + $ileft], %o1
+ dec $rem
+ stb %o0, [%l7 + $ileft]
+ stb %o1, [$out + $ileft]
+ brnz $rem, .L${bits}_xts_${dir}stealing
+ inc $ileft
+
+ mov %l7, $inp
+ sub $out, 16, $out
+ mov 0, $ileft
+ sub $out, $ooff, $out
+ ba .L${bits}_xts_${dir}loop ! one more time
+ mov 1, $len ! $rem is 0
+___
+$code.=<<___ if ($dir eq "de");
+.align 32
+.L${bits}_xts_${dir}steal:
+ ldx [$inp + 0], %o0
+ brz,pt $ileft, 8f
+ ldx [$inp + 8], %o1
+
+ ldx [$inp + 16], %o2
+ sllx %o0, $ileft, %o0
+ srlx %o1, $iright, %g1
+ sllx %o1, $ileft, %o1
+ or %g1, %o0, %o0
+ srlx %o2, $iright, %o2
+ or %o2, %o1, %o1
+8:
+ srax %g3, 63, %l7 ! next tweak value
+ addcc %g2, %g2, %o2
+ and %l7, 0x87, %l7
+ addxc %g3, %g3, %o3
+ xor %l7, %o2, %o2
+
+ movxtod %o2, %f12
+ movxtod %o3, %f14
+ bshuffle %f12, %f12, %f12
+ bshuffle %f14, %f14, %f14
+
+ xor %g4, %o0, %o0 ! ^= rk[0]
+ xor %g5, %o1, %o1
+ movxtod %o0, %f0
+ movxtod %o1, %f2
+
+ fxor %f12, %f0, %f0 ! ^= tweak[0]
+ fxor %f14, %f2, %f2
+
+ call _${alg}${bits}_${dir}crypt_1x
+ add $inp, 16, $inp
+
+ fxor %f12, %f0, %f0 ! ^= tweak[0]
+ fxor %f14, %f2, %f2
+
+ std %f0, [%fp + $::bias-16]
+ std %f2, [%fp + $::bias-8]
+
+ srl $ileft, 3, $ileft
+ add %fp, $::bias-16, %l7
+ add $inp, $ileft, $inp ! original $inp+$len&-15
+ add $out, $ooff, $out ! original $out+$len&-15
+ mov 0, $ileft
+ add $out, 16, $out
+ nop ! align
+
+.L${bits}_xts_${dir}stealing:
+ ldub [$inp + $ileft], %o0
+ ldub [%l7 + $ileft], %o1
+ dec $rem
+ stb %o0, [%l7 + $ileft]
+ stb %o1, [$out + $ileft]
+ brnz $rem, .L${bits}_xts_${dir}stealing
+ inc $ileft
+
+ mov %l7, $inp
+ sub $out, 16, $out
+ mov 0, $ileft
+ sub $out, $ooff, $out
+ ba .L${bits}_xts_${dir}loop ! one more time
+ mov 1, $len ! $rem is 0
+___
+$code.=<<___;
+ ret
+ restore
+.type ${alg}${bits}_t4_xts_${dir}crypt,#function
+.size ${alg}${bits}_t4_xts_${dir}crypt,.-${alg}${bits}_t4_xts_${dir}crypt
+___
+}
+
+# Purpose of these subroutines is to explicitly encode VIS instructions,
+# so that one can compile the module without having to specify VIS
+# extentions on compiler command line, e.g. -xarch=v9 vs. -xarch=v9a.
+# Idea is to reserve for option to produce "universal" binary and let
+# programmer detect if current CPU is VIS capable at run-time.
+sub unvis {
+my ($mnemonic,$rs1,$rs2,$rd)=@_;
+my ($ref,$opf);
+my %visopf = ( "faligndata" => 0x048,
+ "bshuffle" => 0x04c,
+ "fnot2" => 0x066,
+ "fxor" => 0x06c,
+ "fsrc2" => 0x078 );
+
+ $ref = "$mnemonic\t$rs1,$rs2,$rd";
+
+ if ($opf=$visopf{$mnemonic}) {
+ foreach ($rs1,$rs2,$rd) {
+ return $ref if (!/%f([0-9]{1,2})/);
+ $_=$1;
+ if ($1>=32) {
+ return $ref if ($1&1);
+ # re-encode for upper double register addressing
+ $_=($1|$1>>5)&31;
+ }
+ }
+
+ return sprintf ".word\t0x%08x !%s",
+ 0x81b00000|$rd<<25|$rs1<<14|$opf<<5|$rs2,
+ $ref;
+ } else {
+ return $ref;
+ }
+}
+
+sub unvis3 {
+my ($mnemonic,$rs1,$rs2,$rd)=@_;
+my %bias = ( "g" => 0, "o" => 8, "l" => 16, "i" => 24 );
+my ($ref,$opf);
+my %visopf = ( "addxc" => 0x011,
+ "addxccc" => 0x013,
+ "umulxhi" => 0x016,
+ "alignaddr" => 0x018,
+ "bmask" => 0x019,
+ "alignaddrl" => 0x01a );
+
+ $ref = "$mnemonic\t$rs1,$rs2,$rd";
+
+ if ($opf=$visopf{$mnemonic}) {
+ foreach ($rs1,$rs2,$rd) {
+ return $ref if (!/%([goli])([0-9])/);
+ $_=$bias{$1}+$2;
+ }
+
+ return sprintf ".word\t0x%08x !%s",
+ 0x81b00000|$rd<<25|$rs1<<14|$opf<<5|$rs2,
+ $ref;
+ } else {
+ return $ref;
+ }
+}
+
+sub unaes_round { # 4-argument instructions
+my ($mnemonic,$rs1,$rs2,$rs3,$rd)=@_;
+my ($ref,$opf);
+my %aesopf = ( "aes_eround01" => 0,
+ "aes_eround23" => 1,
+ "aes_dround01" => 2,
+ "aes_dround23" => 3,
+ "aes_eround01_l"=> 4,
+ "aes_eround23_l"=> 5,
+ "aes_dround01_l"=> 6,
+ "aes_dround23_l"=> 7,
+ "aes_kexpand1" => 8 );
+
+ $ref = "$mnemonic\t$rs1,$rs2,$rs3,$rd";
+
+ if (defined($opf=$aesopf{$mnemonic})) {
+ $rs3 = ($rs3 =~ /%f([0-6]*[02468])/) ? (($1|$1>>5)&31) : $rs3;
+ foreach ($rs1,$rs2,$rd) {
+ return $ref if (!/%f([0-9]{1,2})/);
+ $_=$1;
+ if ($1>=32) {
+ return $ref if ($1&1);
+ # re-encode for upper double register addressing
+ $_=($1|$1>>5)&31;
+ }
+ }
+
+ return sprintf ".word\t0x%08x !%s",
+ 2<<30|$rd<<25|0x19<<19|$rs1<<14|$rs3<<9|$opf<<5|$rs2,
+ $ref;
+ } else {
+ return $ref;
+ }
+}
+
+sub unaes_kexpand { # 3-argument instructions
+my ($mnemonic,$rs1,$rs2,$rd)=@_;
+my ($ref,$opf);
+my %aesopf = ( "aes_kexpand0" => 0x130,
+ "aes_kexpand2" => 0x131 );
+
+ $ref = "$mnemonic\t$rs1,$rs2,$rd";
+
+ if (defined($opf=$aesopf{$mnemonic})) {
+ foreach ($rs1,$rs2,$rd) {
+ return $ref if (!/%f([0-9]{1,2})/);
+ $_=$1;
+ if ($1>=32) {
+ return $ref if ($1&1);
+ # re-encode for upper double register addressing
+ $_=($1|$1>>5)&31;
+ }
+ }
+
+ return sprintf ".word\t0x%08x !%s",
+ 2<<30|$rd<<25|0x36<<19|$rs1<<14|$opf<<5|$rs2,
+ $ref;
+ } else {
+ return $ref;
+ }
+}
+
+sub uncamellia_f { # 4-argument instructions
+my ($mnemonic,$rs1,$rs2,$rs3,$rd)=@_;
+my ($ref,$opf);
+
+ $ref = "$mnemonic\t$rs1,$rs2,$rs3,$rd";
+
+ if (1) {
+ $rs3 = ($rs3 =~ /%f([0-6]*[02468])/) ? (($1|$1>>5)&31) : $rs3;
+ foreach ($rs1,$rs2,$rd) {
+ return $ref if (!/%f([0-9]{1,2})/);
+ $_=$1;
+ if ($1>=32) {
+ return $ref if ($1&1);
+ # re-encode for upper double register addressing
+ $_=($1|$1>>5)&31;
+ }
+ }
+
+ return sprintf ".word\t0x%08x !%s",
+ 2<<30|$rd<<25|0x19<<19|$rs1<<14|$rs3<<9|0xc<<5|$rs2,
+ $ref;
+ } else {
+ return $ref;
+ }
+}
+
+sub uncamellia3 { # 3-argument instructions
+my ($mnemonic,$rs1,$rs2,$rd)=@_;
+my ($ref,$opf);
+my %cmllopf = ( "camellia_fl" => 0x13c,
+ "camellia_fli" => 0x13d );
+
+ $ref = "$mnemonic\t$rs1,$rs2,$rd";
+
+ if (defined($opf=$cmllopf{$mnemonic})) {
+ foreach ($rs1,$rs2,$rd) {
+ return $ref if (!/%f([0-9]{1,2})/);
+ $_=$1;
+ if ($1>=32) {
+ return $ref if ($1&1);
+ # re-encode for upper double register addressing
+ $_=($1|$1>>5)&31;
+ }
+ }
+
+ return sprintf ".word\t0x%08x !%s",
+ 2<<30|$rd<<25|0x36<<19|$rs1<<14|$opf<<5|$rs2,
+ $ref;
+ } else {
+ return $ref;
+ }
+}
+
+sub unmovxtox { # 2-argument instructions
+my ($mnemonic,$rs,$rd)=@_;
+my %bias = ( "g" => 0, "o" => 8, "l" => 16, "i" => 24, "f" => 0 );
+my ($ref,$opf);
+my %movxopf = ( "movdtox" => 0x110,
+ "movstouw" => 0x111,
+ "movstosw" => 0x113,
+ "movxtod" => 0x118,
+ "movwtos" => 0x119 );
+
+ $ref = "$mnemonic\t$rs,$rd";
+
+ if (defined($opf=$movxopf{$mnemonic})) {
+ foreach ($rs,$rd) {
+ return $ref if (!/%([fgoli])([0-9]{1,2})/);
+ $_=$bias{$1}+$2;
+ if ($2>=32) {
+ return $ref if ($2&1);
+ # re-encode for upper double register addressing
+ $_=($2|$2>>5)&31;
+ }
+ }
+
+ return sprintf ".word\t0x%08x !%s",
+ 2<<30|$rd<<25|0x36<<19|$opf<<5|$rs,
+ $ref;
+ } else {
+ return $ref;
+ }
+}
+
+sub undes {
+my ($mnemonic)=shift;
+my @args=@_;
+my ($ref,$opf);
+my %desopf = ( "des_round" => 0b1001,
+ "des_ip" => 0b100110100,
+ "des_iip" => 0b100110101,
+ "des_kexpand" => 0b100110110 );
+
+ $ref = "$mnemonic\t".join(",",@_);
+
+ if (defined($opf=$desopf{$mnemonic})) { # 4-arg
+ if ($mnemonic eq "des_round") {
+ foreach (@args[0..3]) {
+ return $ref if (!/%f([0-9]{1,2})/);
+ $_=$1;
+ if ($1>=32) {
+ return $ref if ($1&1);
+ # re-encode for upper double register addressing
+ $_=($1|$1>>5)&31;
+ }
+ }
+ return sprintf ".word\t0x%08x !%s",
+ 2<<30|0b011001<<19|$opf<<5|$args[0]<<14|$args[1]|$args[2]<<9|$args[3]<<25,
+ $ref;
+ } elsif ($mnemonic eq "des_kexpand") { # 3-arg
+ foreach (@args[0..2]) {
+ return $ref if (!/(%f)?([0-9]{1,2})/);
+ $_=$2;
+ if ($2>=32) {
+ return $ref if ($2&1);
+ # re-encode for upper double register addressing
+ $_=($2|$2>>5)&31;
+ }
+ }
+ return sprintf ".word\t0x%08x !%s",
+ 2<<30|0b110110<<19|$opf<<5|$args[0]<<14|$args[1]|$args[2]<<25,
+ $ref;
+ } else { # 2-arg
+ foreach (@args[0..1]) {
+ return $ref if (!/%f([0-9]{1,2})/);
+ $_=$1;
+ if ($1>=32) {
+ return $ref if ($2&1);
+ # re-encode for upper double register addressing
+ $_=($1|$1>>5)&31;
+ }
+ }
+ return sprintf ".word\t0x%08x !%s",
+ 2<<30|0b110110<<19|$opf<<5|$args[0]<<14|$args[1]<<25,
+ $ref;
+ }
+ } else {
+ return $ref;
+ }
+}
+
+sub emit_assembler {
+ foreach (split("\n",$::code)) {
+ s/\`([^\`]*)\`/eval $1/ge;
+
+ s/\b(f[a-z]+2[sd]*)\s+(%f[0-9]{1,2}),\s*(%f[0-9]{1,2})\s*$/$1\t%f0,$2,$3/go;
+
+ s/\b(aes_[edk][^\s]*)\s+(%f[0-9]{1,2}),\s*(%f[0-9]{1,2}),\s*([%fx0-9]+),\s*(%f[0-9]{1,2})/
+ &unaes_round($1,$2,$3,$4,$5)
+ /geo or
+ s/\b(aes_kexpand[02])\s+(%f[0-9]{1,2}),\s*(%f[0-9]{1,2}),\s*(%f[0-9]{1,2})/
+ &unaes_kexpand($1,$2,$3,$4)
+ /geo or
+ s/\b(camellia_f)\s+(%f[0-9]{1,2}),\s*(%f[0-9]{1,2}),\s*([%fx0-9]+),\s*(%f[0-9]{1,2})/
+ &uncamellia_f($1,$2,$3,$4,$5)
+ /geo or
+ s/\b(camellia_[^s]+)\s+(%f[0-9]{1,2}),\s*(%f[0-9]{1,2}),\s*(%f[0-9]{1,2})/
+ &uncamellia3($1,$2,$3,$4)
+ /geo or
+ s/\b(des_\w+)\s+(%f[0-9]{1,2}),\s*([%fx0-9]+)(?:,\s*(%f[0-9]{1,2})(?:,\s*(%f[0-9]{1,2}))?)?/
+ &undes($1,$2,$3,$4,$5)
+ /geo or
+ s/\b(mov[ds]to\w+)\s+(%f[0-9]{1,2}),\s*(%[goli][0-7])/
+ &unmovxtox($1,$2,$3)
+ /geo or
+ s/\b(mov[xw]to[ds])\s+(%[goli][0-7]),\s*(%f[0-9]{1,2})/
+ &unmovxtox($1,$2,$3)
+ /geo or
+ s/\b([fb][^\s]*)\s+(%f[0-9]{1,2}),\s*(%f[0-9]{1,2}),\s*(%f[0-9]{1,2})/
+ &unvis($1,$2,$3,$4)
+ /geo or
+ s/\b(umulxhi|bmask|addxc[c]{0,2}|alignaddr[l]*)\s+(%[goli][0-7]),\s*(%[goli][0-7]),\s*(%[goli][0-7])/
+ &unvis3($1,$2,$3,$4)
+ /geo;
+
+ print $_,"\n";
+ }
+}
+
+1;
diff --git a/src/crypto/perlasm/x86_64-xlate.pl b/src/crypto/perlasm/x86_64-xlate.pl
new file mode 100755
index 0000000..ed545f2
--- /dev/null
+++ b/src/crypto/perlasm/x86_64-xlate.pl
@@ -0,0 +1,1165 @@
+#!/usr/bin/env perl
+
+# Ascetic x86_64 AT&T to MASM/NASM assembler translator by <appro>.
+#
+# Why AT&T to MASM and not vice versa? Several reasons. Because AT&T
+# format is way easier to parse. Because it's simpler to "gear" from
+# Unix ABI to Windows one [see cross-reference "card" at the end of
+# file]. Because Linux targets were available first...
+#
+# In addition the script also "distills" code suitable for GNU
+# assembler, so that it can be compiled with more rigid assemblers,
+# such as Solaris /usr/ccs/bin/as.
+#
+# This translator is not designed to convert *arbitrary* assembler
+# code from AT&T format to MASM one. It's designed to convert just
+# enough to provide for dual-ABI OpenSSL modules development...
+# There *are* limitations and you might have to modify your assembler
+# code or this script to achieve the desired result...
+#
+# Currently recognized limitations:
+#
+# - can't use multiple ops per line;
+#
+# Dual-ABI styling rules.
+#
+# 1. Adhere to Unix register and stack layout [see cross-reference
+# ABI "card" at the end for explanation].
+# 2. Forget about "red zone," stick to more traditional blended
+# stack frame allocation. If volatile storage is actually required
+# that is. If not, just leave the stack as is.
+# 3. Functions tagged with ".type name,@function" get crafted with
+# unified Win64 prologue and epilogue automatically. If you want
+# to take care of ABI differences yourself, tag functions as
+# ".type name,@abi-omnipotent" instead.
+# 4. To optimize the Win64 prologue you can specify number of input
+# arguments as ".type name,@function,N." Keep in mind that if N is
+# larger than 6, then you *have to* write "abi-omnipotent" code,
+# because >6 cases can't be addressed with unified prologue.
+# 5. Name local labels as .L*, do *not* use dynamic labels such as 1:
+# (sorry about latter).
+# 6. Don't use [or hand-code with .byte] "rep ret." "ret" mnemonic is
+# required to identify the spots, where to inject Win64 epilogue!
+# But on the pros, it's then prefixed with rep automatically:-)
+# 7. Stick to explicit ip-relative addressing. If you have to use
+# GOTPCREL addressing, stick to mov symbol@GOTPCREL(%rip),%r??.
+# Both are recognized and translated to proper Win64 addressing
+# modes. To support legacy code a synthetic directive, .picmeup,
+# is implemented. It puts address of the *next* instruction into
+# target register, e.g.:
+#
+# .picmeup %rax
+# lea .Label-.(%rax),%rax
+#
+# 8. In order to provide for structured exception handling unified
+# Win64 prologue copies %rsp value to %rax. For further details
+# see SEH paragraph at the end.
+# 9. .init segment is allowed to contain calls to functions only.
+# a. If function accepts more than 4 arguments *and* >4th argument
+# is declared as non 64-bit value, do clear its upper part.
+
+my $flavour = shift;
+my $output = shift;
+if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+
+open STDOUT,">$output" || die "can't open $output: $!"
+ if (defined($output));
+
+my $gas=1; $gas=0 if ($output =~ /\.asm$/);
+my $elf=1; $elf=0 if (!$gas);
+my $win64=0;
+my $prefix="";
+my $decor=".L";
+
+my $masmref=8 + 50727*2**-32; # 8.00.50727 shipped with VS2005
+my $masm=0;
+my $PTR=" PTR";
+
+my $nasmref=2.03;
+my $nasm=0;
+
+if ($flavour eq "mingw64") { $gas=1; $elf=0; $win64=1;
+ $prefix=`echo __USER_LABEL_PREFIX__ | $ENV{CC} -E -P -`;
+ chomp($prefix);
+ }
+elsif ($flavour eq "macosx") { $gas=1; $elf=0; $prefix="_"; $decor="L\$"; }
+elsif ($flavour eq "masm") { $gas=0; $elf=0; $masm=$masmref; $win64=1; $decor="\$L\$"; }
+elsif ($flavour eq "nasm") { $gas=0; $elf=0; $nasm=$nasmref; $win64=1; $decor="\$L\$"; $PTR=""; }
+elsif (!$gas)
+{ if ($ENV{ASM} =~ m/nasm/ && `nasm -v` =~ m/version ([0-9]+)\.([0-9]+)/i)
+ { $nasm = $1 + $2*0.01; $PTR=""; }
+ elsif (`ml64 2>&1` =~ m/Version ([0-9]+)\.([0-9]+)(\.([0-9]+))?/)
+ { $masm = $1 + $2*2**-16 + $4*2**-32; }
+ die "no assembler found on %PATH" if (!($nasm || $masm));
+ $win64=1;
+ $elf=0;
+ $decor="\$L\$";
+}
+
+my $current_segment;
+my $current_function;
+my %globals;
+
+{ package opcode; # pick up opcodes
+ sub re {
+ my $self = shift; # single instance in enough...
+ local *line = shift;
+ undef $ret;
+
+ if ($line =~ /^([a-z][a-z0-9]*)/i) {
+ $self->{op} = $1;
+ $ret = $self;
+ $line = substr($line,@+[0]); $line =~ s/^\s+//;
+
+ undef $self->{sz};
+ if ($self->{op} =~ /^(movz)x?([bw]).*/) { # movz is pain...
+ $self->{op} = $1;
+ $self->{sz} = $2;
+ } elsif ($self->{op} =~ /call|jmp/) {
+ $self->{sz} = "";
+ } elsif ($self->{op} =~ /^p/ && $' !~ /^(ush|op|insrw)/) { # SSEn
+ $self->{sz} = "";
+ } elsif ($self->{op} =~ /^v/) { # VEX
+ $self->{sz} = "";
+ } elsif ($self->{op} =~ /mov[dq]/ && $line =~ /%xmm/) {
+ $self->{sz} = "";
+ } elsif ($self->{op} =~ /([a-z]{3,})([qlwb])$/) {
+ $self->{op} = $1;
+ $self->{sz} = $2;
+ }
+ }
+ $ret;
+ }
+ sub size {
+ my $self = shift;
+ my $sz = shift;
+ $self->{sz} = $sz if (defined($sz) && !defined($self->{sz}));
+ $self->{sz};
+ }
+ sub out {
+ my $self = shift;
+ if ($gas) {
+ if ($self->{op} eq "movz") { # movz is pain...
+ sprintf "%s%s%s",$self->{op},$self->{sz},shift;
+ } elsif ($self->{op} =~ /^set/) {
+ "$self->{op}";
+ } elsif ($self->{op} eq "ret") {
+ my $epilogue = "";
+ if ($win64 && $current_function->{abi} eq "svr4") {
+ $epilogue = "movq 8(%rsp),%rdi\n\t" .
+ "movq 16(%rsp),%rsi\n\t";
+ }
+ $epilogue . ".byte 0xf3,0xc3";
+ } elsif ($self->{op} eq "call" && !$elf && $current_segment eq ".init") {
+ ".p2align\t3\n\t.quad";
+ } else {
+ "$self->{op}$self->{sz}";
+ }
+ } else {
+ $self->{op} =~ s/^movz/movzx/;
+ if ($self->{op} eq "ret") {
+ $self->{op} = "";
+ if ($win64 && $current_function->{abi} eq "svr4") {
+ $self->{op} = "mov rdi,QWORD${PTR}[8+rsp]\t;WIN64 epilogue\n\t".
+ "mov rsi,QWORD${PTR}[16+rsp]\n\t";
+ }
+ $self->{op} .= "DB\t0F3h,0C3h\t\t;repret";
+ } elsif ($self->{op} =~ /^(pop|push)f/) {
+ $self->{op} .= $self->{sz};
+ } elsif ($self->{op} eq "call" && $current_segment eq ".CRT\$XCU") {
+ $self->{op} = "\tDQ";
+ }
+ $self->{op};
+ }
+ }
+ sub mnemonic {
+ my $self=shift;
+ my $op=shift;
+ $self->{op}=$op if (defined($op));
+ $self->{op};
+ }
+}
+{ package const; # pick up constants, which start with $
+ sub re {
+ my $self = shift; # single instance in enough...
+ local *line = shift;
+ undef $ret;
+
+ if ($line =~ /^\$([^,]+)/) {
+ $self->{value} = $1;
+ $ret = $self;
+ $line = substr($line,@+[0]); $line =~ s/^\s+//;
+ }
+ $ret;
+ }
+ sub out {
+ my $self = shift;
+
+ if ($gas) {
+ # Solaris /usr/ccs/bin/as can't handle multiplications
+ # in $self->{value}
+ $self->{value} =~ s/(?<![\w\$\.])(0x?[0-9a-f]+)/oct($1)/egi;
+ $self->{value} =~ s/([0-9]+\s*[\*\/\%]\s*[0-9]+)/eval($1)/eg;
+ sprintf "\$%s",$self->{value};
+ } else {
+ $self->{value} =~ s/(0b[0-1]+)/oct($1)/eig;
+ $self->{value} =~ s/0x([0-9a-f]+)/0$1h/ig if ($masm);
+ sprintf "%s",$self->{value};
+ }
+ }
+}
+{ package ea; # pick up effective addresses: expr(%reg,%reg,scale)
+ sub re {
+ my $self = shift; # single instance in enough...
+ local *line = shift;
+ undef $ret;
+
+ # optional * ---vvv--- appears in indirect jmp/call
+ if ($line =~ /^(\*?)([^\(,]*)\(([%\w,]+)\)/) {
+ $self->{asterisk} = $1;
+ $self->{label} = $2;
+ ($self->{base},$self->{index},$self->{scale})=split(/,/,$3);
+ $self->{scale} = 1 if (!defined($self->{scale}));
+ $ret = $self;
+ $line = substr($line,@+[0]); $line =~ s/^\s+//;
+
+ if ($win64 && $self->{label} =~ s/\@GOTPCREL//) {
+ die if (opcode->mnemonic() ne "mov");
+ opcode->mnemonic("lea");
+ }
+ $self->{base} =~ s/^%//;
+ $self->{index} =~ s/^%// if (defined($self->{index}));
+ }
+ $ret;
+ }
+ sub size {}
+ sub out {
+ my $self = shift;
+ my $sz = shift;
+
+ $self->{label} =~ s/([_a-z][_a-z0-9]*)/$globals{$1} or $1/gei;
+ $self->{label} =~ s/\.L/$decor/g;
+
+ # Silently convert all EAs to 64-bit. This is required for
+ # elder GNU assembler and results in more compact code,
+ # *but* most importantly AES module depends on this feature!
+ $self->{index} =~ s/^[er](.?[0-9xpi])[d]?$/r\1/;
+ $self->{base} =~ s/^[er](.?[0-9xpi])[d]?$/r\1/;
+
+ # Solaris /usr/ccs/bin/as can't handle multiplications
+ # in $self->{label}, new gas requires sign extension...
+ use integer;
+ $self->{label} =~ s/(?<![\w\$\.])(0x?[0-9a-f]+)/oct($1)/egi;
+ $self->{label} =~ s/\b([0-9]+\s*[\*\/\%]\s*[0-9]+)\b/eval($1)/eg;
+ $self->{label} =~ s/\b([0-9]+)\b/$1<<32>>32/eg;
+
+ if (!$self->{label} && $self->{index} && $self->{scale}==1 &&
+ $self->{base} =~ /(rbp|r13)/) {
+ $self->{base} = $self->{index}; $self->{index} = $1;
+ }
+
+ if ($gas) {
+ $self->{label} =~ s/^___imp_/__imp__/ if ($flavour eq "mingw64");
+
+ if (defined($self->{index})) {
+ sprintf "%s%s(%s,%%%s,%d)",$self->{asterisk},
+ $self->{label},
+ $self->{base}?"%$self->{base}":"",
+ $self->{index},$self->{scale};
+ } else {
+ sprintf "%s%s(%%%s)", $self->{asterisk},$self->{label},$self->{base};
+ }
+ } else {
+ %szmap = ( b=>"BYTE$PTR", w=>"WORD$PTR",
+ l=>"DWORD$PTR", d=>"DWORD$PTR",
+ q=>"QWORD$PTR", o=>"OWORD$PTR",
+ x=>"XMMWORD$PTR", y=>"YMMWORD$PTR", z=>"ZMMWORD$PTR" );
+
+ $self->{label} =~ s/\./\$/g;
+ $self->{label} =~ s/(?<![\w\$\.])0x([0-9a-f]+)/0$1h/ig;
+ $self->{label} = "($self->{label})" if ($self->{label} =~ /[\*\+\-\/]/);
+
+ ($self->{asterisk}) && ($sz="q") ||
+ (opcode->mnemonic() =~ /^v?mov([qd])$/) && ($sz=$1) ||
+ (opcode->mnemonic() =~ /^v?pinsr([qdwb])$/) && ($sz=$1) ||
+ (opcode->mnemonic() =~ /^vpbroadcast([qdwb])$/) && ($sz=$1) ||
+ (opcode->mnemonic() =~ /^vinsert[fi]128$/) && ($sz="x");
+
+ if (defined($self->{index})) {
+ sprintf "%s[%s%s*%d%s]",$szmap{$sz},
+ $self->{label}?"$self->{label}+":"",
+ $self->{index},$self->{scale},
+ $self->{base}?"+$self->{base}":"";
+ } elsif ($self->{base} eq "rip") {
+ sprintf "%s[%s]",$szmap{$sz},$self->{label};
+ } else {
+ sprintf "%s[%s%s]",$szmap{$sz},
+ $self->{label}?"$self->{label}+":"",
+ $self->{base};
+ }
+ }
+ }
+}
+{ package register; # pick up registers, which start with %.
+ sub re {
+ my $class = shift; # muliple instances...
+ my $self = {};
+ local *line = shift;
+ undef $ret;
+
+ # optional * ---vvv--- appears in indirect jmp/call
+ if ($line =~ /^(\*?)%(\w+)/) {
+ bless $self,$class;
+ $self->{asterisk} = $1;
+ $self->{value} = $2;
+ $ret = $self;
+ $line = substr($line,@+[0]); $line =~ s/^\s+//;
+ }
+ $ret;
+ }
+ sub size {
+ my $self = shift;
+ undef $ret;
+
+ if ($self->{value} =~ /^r[\d]+b$/i) { $ret="b"; }
+ elsif ($self->{value} =~ /^r[\d]+w$/i) { $ret="w"; }
+ elsif ($self->{value} =~ /^r[\d]+d$/i) { $ret="l"; }
+ elsif ($self->{value} =~ /^r[\w]+$/i) { $ret="q"; }
+ elsif ($self->{value} =~ /^[a-d][hl]$/i){ $ret="b"; }
+ elsif ($self->{value} =~ /^[\w]{2}l$/i) { $ret="b"; }
+ elsif ($self->{value} =~ /^[\w]{2}$/i) { $ret="w"; }
+ elsif ($self->{value} =~ /^e[a-z]{2}$/i){ $ret="l"; }
+
+ $ret;
+ }
+ sub out {
+ my $self = shift;
+ if ($gas) { sprintf "%s%%%s",$self->{asterisk},$self->{value}; }
+ else { $self->{value}; }
+ }
+}
+{ package label; # pick up labels, which end with :
+ sub re {
+ my $self = shift; # single instance is enough...
+ local *line = shift;
+ undef $ret;
+
+ if ($line =~ /(^[\.\w]+)\:/) {
+ $self->{value} = $1;
+ $ret = $self;
+ $line = substr($line,@+[0]); $line =~ s/^\s+//;
+
+ $self->{value} =~ s/^\.L/$decor/;
+ }
+ $ret;
+ }
+ sub out {
+ my $self = shift;
+
+ if ($gas) {
+ my $func = ($globals{$self->{value}} or $self->{value}) . ":";
+ if ($win64 &&
+ $current_function->{name} eq $self->{value} &&
+ $current_function->{abi} eq "svr4") {
+ $func .= "\n";
+ $func .= " movq %rdi,8(%rsp)\n";
+ $func .= " movq %rsi,16(%rsp)\n";
+ $func .= " movq %rsp,%rax\n";
+ $func .= "${decor}SEH_begin_$current_function->{name}:\n";
+ my $narg = $current_function->{narg};
+ $narg=6 if (!defined($narg));
+ $func .= " movq %rcx,%rdi\n" if ($narg>0);
+ $func .= " movq %rdx,%rsi\n" if ($narg>1);
+ $func .= " movq %r8,%rdx\n" if ($narg>2);
+ $func .= " movq %r9,%rcx\n" if ($narg>3);
+ $func .= " movq 40(%rsp),%r8\n" if ($narg>4);
+ $func .= " movq 48(%rsp),%r9\n" if ($narg>5);
+ }
+ $func;
+ } elsif ($self->{value} ne "$current_function->{name}") {
+ $self->{value} .= ":" if ($masm && $ret!~m/^\$/);
+ $self->{value} . ":";
+ } elsif ($win64 && $current_function->{abi} eq "svr4") {
+ my $func = "$current_function->{name}" .
+ ($nasm ? ":" : "\tPROC $current_function->{scope}") .
+ "\n";
+ $func .= " mov QWORD${PTR}[8+rsp],rdi\t;WIN64 prologue\n";
+ $func .= " mov QWORD${PTR}[16+rsp],rsi\n";
+ $func .= " mov rax,rsp\n";
+ $func .= "${decor}SEH_begin_$current_function->{name}:";
+ $func .= ":" if ($masm);
+ $func .= "\n";
+ my $narg = $current_function->{narg};
+ $narg=6 if (!defined($narg));
+ $func .= " mov rdi,rcx\n" if ($narg>0);
+ $func .= " mov rsi,rdx\n" if ($narg>1);
+ $func .= " mov rdx,r8\n" if ($narg>2);
+ $func .= " mov rcx,r9\n" if ($narg>3);
+ $func .= " mov r8,QWORD${PTR}[40+rsp]\n" if ($narg>4);
+ $func .= " mov r9,QWORD${PTR}[48+rsp]\n" if ($narg>5);
+ $func .= "\n";
+ } else {
+ "$current_function->{name}".
+ ($nasm ? ":" : "\tPROC $current_function->{scope}");
+ }
+ }
+}
+{ package expr; # pick up expressioins
+ sub re {
+ my $self = shift; # single instance is enough...
+ local *line = shift;
+ undef $ret;
+
+ if ($line =~ /(^[^,]+)/) {
+ $self->{value} = $1;
+ $ret = $self;
+ $line = substr($line,@+[0]); $line =~ s/^\s+//;
+
+ $self->{value} =~ s/\@PLT// if (!$elf);
+ $self->{value} =~ s/([_a-z][_a-z0-9]*)/$globals{$1} or $1/gei;
+ $self->{value} =~ s/\.L/$decor/g;
+ }
+ $ret;
+ }
+ sub out {
+ my $self = shift;
+ if ($nasm && opcode->mnemonic()=~m/^j(?![re]cxz)/) {
+ "NEAR ".$self->{value};
+ } else {
+ $self->{value};
+ }
+ }
+}
+{ package directive; # pick up directives, which start with .
+ sub re {
+ my $self = shift; # single instance is enough...
+ local *line = shift;
+ undef $ret;
+ my $dir;
+ my %opcode = # lea 2f-1f(%rip),%dst; 1: nop; 2:
+ ( "%rax"=>0x01058d48, "%rcx"=>0x010d8d48,
+ "%rdx"=>0x01158d48, "%rbx"=>0x011d8d48,
+ "%rsp"=>0x01258d48, "%rbp"=>0x012d8d48,
+ "%rsi"=>0x01358d48, "%rdi"=>0x013d8d48,
+ "%r8" =>0x01058d4c, "%r9" =>0x010d8d4c,
+ "%r10"=>0x01158d4c, "%r11"=>0x011d8d4c,
+ "%r12"=>0x01258d4c, "%r13"=>0x012d8d4c,
+ "%r14"=>0x01358d4c, "%r15"=>0x013d8d4c );
+
+ if ($line =~ /^\s*(\.\w+)/) {
+ $dir = $1;
+ $ret = $self;
+ undef $self->{value};
+ $line = substr($line,@+[0]); $line =~ s/^\s+//;
+
+ SWITCH: for ($dir) {
+ /\.picmeup/ && do { if ($line =~ /(%r[\w]+)/i) {
+ $dir="\t.long";
+ $line=sprintf "0x%x,0x90000000",$opcode{$1};
+ }
+ last;
+ };
+ /\.global|\.globl|\.extern/
+ && do { $globals{$line} = $prefix . $line;
+ $line = $globals{$line} if ($prefix);
+ last;
+ };
+ /\.type/ && do { ($sym,$type,$narg) = split(',',$line);
+ if ($type eq "\@function") {
+ undef $current_function;
+ $current_function->{name} = $sym;
+ $current_function->{abi} = "svr4";
+ $current_function->{narg} = $narg;
+ $current_function->{scope} = defined($globals{$sym})?"PUBLIC":"PRIVATE";
+ } elsif ($type eq "\@abi-omnipotent") {
+ undef $current_function;
+ $current_function->{name} = $sym;
+ $current_function->{scope} = defined($globals{$sym})?"PUBLIC":"PRIVATE";
+ }
+ $line =~ s/\@abi\-omnipotent/\@function/;
+ $line =~ s/\@function.*/\@function/;
+ last;
+ };
+ /\.asciz/ && do { if ($line =~ /^"(.*)"$/) {
+ $dir = ".byte";
+ $line = join(",",unpack("C*",$1),0);
+ }
+ last;
+ };
+ /\.rva|\.long|\.quad/
+ && do { $line =~ s/([_a-z][_a-z0-9]*)/$globals{$1} or $1/gei;
+ $line =~ s/\.L/$decor/g;
+ last;
+ };
+ }
+
+ if ($gas) {
+ $self->{value} = $dir . "\t" . $line;
+
+ if ($dir =~ /\.extern/) {
+ $self->{value} = ""; # swallow extern
+ } elsif (!$elf && $dir =~ /\.type/) {
+ $self->{value} = "";
+ $self->{value} = ".def\t" . ($globals{$1} or $1) . ";\t" .
+ (defined($globals{$1})?".scl 2;":".scl 3;") .
+ "\t.type 32;\t.endef"
+ if ($win64 && $line =~ /([^,]+),\@function/);
+ } elsif (!$elf && $dir =~ /\.size/) {
+ $self->{value} = "";
+ if (defined($current_function)) {
+ $self->{value} .= "${decor}SEH_end_$current_function->{name}:"
+ if ($win64 && $current_function->{abi} eq "svr4");
+ undef $current_function;
+ }
+ } elsif (!$elf && $dir =~ /\.align/) {
+ $self->{value} = ".p2align\t" . (log($line)/log(2));
+ } elsif ($dir eq ".section") {
+ $current_segment=$line;
+ if (!$elf && $current_segment eq ".init") {
+ if ($flavour eq "macosx") { $self->{value} = ".mod_init_func"; }
+ elsif ($flavour eq "mingw64") { $self->{value} = ".section\t.ctors"; }
+ }
+ } elsif ($dir =~ /\.(text|data)/) {
+ $current_segment=".$1";
+ } elsif ($dir =~ /\.global|\.globl|\.extern/) {
+ if ($flavour eq "macosx") {
+ $self->{value} .= "\n.private_extern $line";
+ } else {
+ $self->{value} .= "\n.hidden $line";
+ }
+ } elsif ($dir =~ /\.hidden/) {
+ if ($flavour eq "macosx") { $self->{value} = ".private_extern\t$prefix$line"; }
+ elsif ($flavour eq "mingw64") { $self->{value} = ""; }
+ } elsif ($dir =~ /\.comm/) {
+ $self->{value} = "$dir\t$prefix$line";
+ $self->{value} =~ s|,([0-9]+),([0-9]+)$|",$1,".log($2)/log(2)|e if ($flavour eq "macosx");
+ }
+ $line = "";
+ return $self;
+ }
+
+ # non-gas case or nasm/masm
+ SWITCH: for ($dir) {
+ /\.text/ && do { my $v=undef;
+ if ($nasm) {
+ $v="section .text code align=64\n";
+ } else {
+ $v="$current_segment\tENDS\n" if ($current_segment);
+ $current_segment = ".text\$";
+ $v.="$current_segment\tSEGMENT ";
+ $v.=$masm>=$masmref ? "ALIGN(256)" : "PAGE";
+ $v.=" 'CODE'";
+ }
+ $self->{value} = $v;
+ last;
+ };
+ /\.data/ && do { my $v=undef;
+ if ($nasm) {
+ $v="section .data data align=8\n";
+ } else {
+ $v="$current_segment\tENDS\n" if ($current_segment);
+ $current_segment = "_DATA";
+ $v.="$current_segment\tSEGMENT";
+ }
+ $self->{value} = $v;
+ last;
+ };
+ /\.section/ && do { my $v=undef;
+ $line =~ s/([^,]*).*/$1/;
+ $line = ".CRT\$XCU" if ($line eq ".init");
+ if ($nasm) {
+ $v="section $line";
+ if ($line=~/\.([px])data/) {
+ $v.=" rdata align=";
+ $v.=$1 eq "p"? 4 : 8;
+ } elsif ($line=~/\.CRT\$/i) {
+ $v.=" rdata align=8";
+ }
+ } else {
+ $v="$current_segment\tENDS\n" if ($current_segment);
+ $v.="$line\tSEGMENT";
+ if ($line=~/\.([px])data/) {
+ $v.=" READONLY";
+ $v.=" ALIGN(".($1 eq "p" ? 4 : 8).")" if ($masm>=$masmref);
+ } elsif ($line=~/\.CRT\$/i) {
+ $v.=" READONLY ";
+ $v.=$masm>=$masmref ? "ALIGN(8)" : "DWORD";
+ }
+ }
+ $current_segment = $line;
+ $self->{value} = $v;
+ last;
+ };
+ /\.extern/ && do { $self->{value} = "EXTERN\t".$line;
+ $self->{value} .= ":NEAR" if ($masm);
+ last;
+ };
+ /\.globl|.global/
+ && do { $self->{value} = $masm?"PUBLIC":"global";
+ $self->{value} .= "\t".$line;
+ last;
+ };
+ /\.size/ && do { if (defined($current_function)) {
+ undef $self->{value};
+ if ($current_function->{abi} eq "svr4") {
+ $self->{value}="${decor}SEH_end_$current_function->{name}:";
+ $self->{value}.=":\n" if($masm);
+ }
+ $self->{value}.="$current_function->{name}\tENDP" if($masm && $current_function->{name});
+ undef $current_function;
+ }
+ last;
+ };
+ /\.align/ && do { $self->{value} = "ALIGN\t".$line; last; };
+ /\.(value|long|rva|quad)/
+ && do { my $sz = substr($1,0,1);
+ my @arr = split(/,\s*/,$line);
+ my $last = pop(@arr);
+ my $conv = sub { my $var=shift;
+ $var=~s/^(0b[0-1]+)/oct($1)/eig;
+ $var=~s/^0x([0-9a-f]+)/0$1h/ig if ($masm);
+ if ($sz eq "D" && ($current_segment=~/.[px]data/ || $dir eq ".rva"))
+ { $var=~s/([_a-z\$\@][_a-z0-9\$\@]*)/$nasm?"$1 wrt ..imagebase":"imagerel $1"/egi; }
+ $var;
+ };
+
+ $sz =~ tr/bvlrq/BWDDQ/;
+ $self->{value} = "\tD$sz\t";
+ for (@arr) { $self->{value} .= &$conv($_).","; }
+ $self->{value} .= &$conv($last);
+ last;
+ };
+ /\.byte/ && do { my @str=split(/,\s*/,$line);
+ map(s/(0b[0-1]+)/oct($1)/eig,@str);
+ map(s/0x([0-9a-f]+)/0$1h/ig,@str) if ($masm);
+ while ($#str>15) {
+ $self->{value}.="DB\t"
+ .join(",",@str[0..15])."\n";
+ foreach (0..15) { shift @str; }
+ }
+ $self->{value}.="DB\t"
+ .join(",",@str) if (@str);
+ last;
+ };
+ /\.comm/ && do { my @str=split(/,\s*/,$line);
+ my $v=undef;
+ if ($nasm) {
+ $v.="common $prefix@str[0] @str[1]";
+ } else {
+ $v="$current_segment\tENDS\n" if ($current_segment);
+ $current_segment = "_DATA";
+ $v.="$current_segment\tSEGMENT\n";
+ $v.="COMM @str[0]:DWORD:".@str[1]/4;
+ }
+ $self->{value} = $v;
+ last;
+ };
+ }
+ $line = "";
+ }
+
+ $ret;
+ }
+ sub out {
+ my $self = shift;
+ $self->{value};
+ }
+}
+
+sub rex {
+ local *opcode=shift;
+ my ($dst,$src,$rex)=@_;
+
+ $rex|=0x04 if($dst>=8);
+ $rex|=0x01 if($src>=8);
+ push @opcode,($rex|0x40) if ($rex);
+}
+
+# older gas and ml64 don't handle SSE>2 instructions
+my %regrm = ( "%eax"=>0, "%ecx"=>1, "%edx"=>2, "%ebx"=>3,
+ "%esp"=>4, "%ebp"=>5, "%esi"=>6, "%edi"=>7 );
+
+my $movq = sub { # elderly gas can't handle inter-register movq
+ my $arg = shift;
+ my @opcode=(0x66);
+ if ($arg =~ /%xmm([0-9]+),\s*%r(\w+)/) {
+ my ($src,$dst)=($1,$2);
+ if ($dst !~ /[0-9]+/) { $dst = $regrm{"%e$dst"}; }
+ rex(\@opcode,$src,$dst,0x8);
+ push @opcode,0x0f,0x7e;
+ push @opcode,0xc0|(($src&7)<<3)|($dst&7); # ModR/M
+ @opcode;
+ } elsif ($arg =~ /%r(\w+),\s*%xmm([0-9]+)/) {
+ my ($src,$dst)=($2,$1);
+ if ($dst !~ /[0-9]+/) { $dst = $regrm{"%e$dst"}; }
+ rex(\@opcode,$src,$dst,0x8);
+ push @opcode,0x0f,0x6e;
+ push @opcode,0xc0|(($src&7)<<3)|($dst&7); # ModR/M
+ @opcode;
+ } else {
+ ();
+ }
+};
+
+my $pextrd = sub {
+ if (shift =~ /\$([0-9]+),\s*%xmm([0-9]+),\s*(%\w+)/) {
+ my @opcode=(0x66);
+ $imm=$1;
+ $src=$2;
+ $dst=$3;
+ if ($dst =~ /%r([0-9]+)d/) { $dst = $1; }
+ elsif ($dst =~ /%e/) { $dst = $regrm{$dst}; }
+ rex(\@opcode,$src,$dst);
+ push @opcode,0x0f,0x3a,0x16;
+ push @opcode,0xc0|(($src&7)<<3)|($dst&7); # ModR/M
+ push @opcode,$imm;
+ @opcode;
+ } else {
+ ();
+ }
+};
+
+my $pinsrd = sub {
+ if (shift =~ /\$([0-9]+),\s*(%\w+),\s*%xmm([0-9]+)/) {
+ my @opcode=(0x66);
+ $imm=$1;
+ $src=$2;
+ $dst=$3;
+ if ($src =~ /%r([0-9]+)/) { $src = $1; }
+ elsif ($src =~ /%e/) { $src = $regrm{$src}; }
+ rex(\@opcode,$dst,$src);
+ push @opcode,0x0f,0x3a,0x22;
+ push @opcode,0xc0|(($dst&7)<<3)|($src&7); # ModR/M
+ push @opcode,$imm;
+ @opcode;
+ } else {
+ ();
+ }
+};
+
+my $pshufb = sub {
+ if (shift =~ /%xmm([0-9]+),\s*%xmm([0-9]+)/) {
+ my @opcode=(0x66);
+ rex(\@opcode,$2,$1);
+ push @opcode,0x0f,0x38,0x00;
+ push @opcode,0xc0|($1&7)|(($2&7)<<3); # ModR/M
+ @opcode;
+ } else {
+ ();
+ }
+};
+
+my $palignr = sub {
+ if (shift =~ /\$([0-9]+),\s*%xmm([0-9]+),\s*%xmm([0-9]+)/) {
+ my @opcode=(0x66);
+ rex(\@opcode,$3,$2);
+ push @opcode,0x0f,0x3a,0x0f;
+ push @opcode,0xc0|($2&7)|(($3&7)<<3); # ModR/M
+ push @opcode,$1;
+ @opcode;
+ } else {
+ ();
+ }
+};
+
+my $pclmulqdq = sub {
+ if (shift =~ /\$([x0-9a-f]+),\s*%xmm([0-9]+),\s*%xmm([0-9]+)/) {
+ my @opcode=(0x66);
+ rex(\@opcode,$3,$2);
+ push @opcode,0x0f,0x3a,0x44;
+ push @opcode,0xc0|($2&7)|(($3&7)<<3); # ModR/M
+ my $c=$1;
+ push @opcode,$c=~/^0/?oct($c):$c;
+ @opcode;
+ } else {
+ ();
+ }
+};
+
+my $rdrand = sub {
+ if (shift =~ /%[er](\w+)/) {
+ my @opcode=();
+ my $dst=$1;
+ if ($dst !~ /[0-9]+/) { $dst = $regrm{"%e$dst"}; }
+ rex(\@opcode,0,$1,8);
+ push @opcode,0x0f,0xc7,0xf0|($dst&7);
+ @opcode;
+ } else {
+ ();
+ }
+};
+
+my $rdseed = sub {
+ if (shift =~ /%[er](\w+)/) {
+ my @opcode=();
+ my $dst=$1;
+ if ($dst !~ /[0-9]+/) { $dst = $regrm{"%e$dst"}; }
+ rex(\@opcode,0,$1,8);
+ push @opcode,0x0f,0xc7,0xf8|($dst&7);
+ @opcode;
+ } else {
+ ();
+ }
+};
+
+sub rxb {
+ local *opcode=shift;
+ my ($dst,$src1,$src2,$rxb)=@_;
+
+ $rxb|=0x7<<5;
+ $rxb&=~(0x04<<5) if($dst>=8);
+ $rxb&=~(0x01<<5) if($src1>=8);
+ $rxb&=~(0x02<<5) if($src2>=8);
+ push @opcode,$rxb;
+}
+
+my $vprotd = sub {
+ if (shift =~ /\$([x0-9a-f]+),\s*%xmm([0-9]+),\s*%xmm([0-9]+)/) {
+ my @opcode=(0x8f);
+ rxb(\@opcode,$3,$2,-1,0x08);
+ push @opcode,0x78,0xc2;
+ push @opcode,0xc0|($2&7)|(($3&7)<<3); # ModR/M
+ my $c=$1;
+ push @opcode,$c=~/^0/?oct($c):$c;
+ @opcode;
+ } else {
+ ();
+ }
+};
+
+my $vprotq = sub {
+ if (shift =~ /\$([x0-9a-f]+),\s*%xmm([0-9]+),\s*%xmm([0-9]+)/) {
+ my @opcode=(0x8f);
+ rxb(\@opcode,$3,$2,-1,0x08);
+ push @opcode,0x78,0xc3;
+ push @opcode,0xc0|($2&7)|(($3&7)<<3); # ModR/M
+ my $c=$1;
+ push @opcode,$c=~/^0/?oct($c):$c;
+ @opcode;
+ } else {
+ ();
+ }
+};
+
+if ($nasm) {
+ print <<___;
+default rel
+%define XMMWORD
+%define YMMWORD
+%define ZMMWORD
+___
+} elsif ($masm) {
+ print <<___;
+OPTION DOTNAME
+___
+}
+
+print STDOUT "#if defined(__x86_64__)\n" if ($gas);
+
+while($line=<>) {
+
+ chomp($line);
+
+ $line =~ s|[#!].*$||; # get rid of asm-style comments...
+ $line =~ s|/\*.*\*/||; # ... and C-style comments...
+ $line =~ s|^\s+||; # ... and skip white spaces in beginning
+ $line =~ s|\s+$||; # ... and at the end
+
+ undef $label;
+ undef $opcode;
+ undef @args;
+
+ if ($label=label->re(\$line)) { print $label->out(); }
+
+ if (directive->re(\$line)) {
+ printf "%s",directive->out();
+ } elsif ($opcode=opcode->re(\$line)) {
+ my $asm = eval("\$".$opcode->mnemonic());
+ undef @bytes;
+
+ if ((ref($asm) eq 'CODE') && scalar(@bytes=&$asm($line))) {
+ print $gas?".byte\t":"DB\t",join(',',@bytes),"\n";
+ next;
+ }
+
+ ARGUMENT: while (1) {
+ my $arg;
+
+ if ($arg=register->re(\$line)) { opcode->size($arg->size()); }
+ elsif ($arg=const->re(\$line)) { }
+ elsif ($arg=ea->re(\$line)) { }
+ elsif ($arg=expr->re(\$line)) { }
+ else { last ARGUMENT; }
+
+ push @args,$arg;
+
+ last ARGUMENT if ($line !~ /^,/);
+
+ $line =~ s/^,\s*//;
+ } # ARGUMENT:
+
+ if ($#args>=0) {
+ my $insn;
+ my $sz=opcode->size();
+
+ if ($gas) {
+ $insn = $opcode->out($#args>=1?$args[$#args]->size():$sz);
+ @args = map($_->out($sz),@args);
+ printf "\t%s\t%s",$insn,join(",",@args);
+ } else {
+ $insn = $opcode->out();
+ foreach (@args) {
+ my $arg = $_->out();
+ # $insn.=$sz compensates for movq, pinsrw, ...
+ if ($arg =~ /^xmm[0-9]+$/) { $insn.=$sz; $sz="x" if(!$sz); last; }
+ if ($arg =~ /^ymm[0-9]+$/) { $insn.=$sz; $sz="y" if(!$sz); last; }
+ if ($arg =~ /^zmm[0-9]+$/) { $insn.=$sz; $sz="z" if(!$sz); last; }
+ if ($arg =~ /^mm[0-9]+$/) { $insn.=$sz; $sz="q" if(!$sz); last; }
+ }
+ @args = reverse(@args);
+ undef $sz if ($nasm && $opcode->mnemonic() eq "lea");
+
+ if ($insn eq "movq" && $#args == 1 && $args[0]->out($sz) eq "xmm0" && $args[1]->out($sz) eq "rax") {
+ # I have no clue why MASM can't parse this instruction.
+ printf "DB 66h, 48h, 0fh, 6eh, 0c0h";
+ } else {
+ printf "\t%s\t%s",$insn,join(",",map($_->out($sz),@args));
+ }
+ }
+ } else {
+ printf "\t%s",$opcode->out();
+ }
+ }
+
+ print $line,"\n";
+}
+
+print "\n$current_segment\tENDS\n" if ($current_segment && $masm);
+print "END\n" if ($masm);
+print "#endif\n" if ($gas);
+
+
+close STDOUT;
+
+ #################################################
+# Cross-reference x86_64 ABI "card"
+#
+# Unix Win64
+# %rax * *
+# %rbx - -
+# %rcx #4 #1
+# %rdx #3 #2
+# %rsi #2 -
+# %rdi #1 -
+# %rbp - -
+# %rsp - -
+# %r8 #5 #3
+# %r9 #6 #4
+# %r10 * *
+# %r11 * *
+# %r12 - -
+# %r13 - -
+# %r14 - -
+# %r15 - -
+#
+# (*) volatile register
+# (-) preserved by callee
+# (#) Nth argument, volatile
+#
+# In Unix terms top of stack is argument transfer area for arguments
+# which could not be accomodated in registers. Or in other words 7th
+# [integer] argument resides at 8(%rsp) upon function entry point.
+# 128 bytes above %rsp constitute a "red zone" which is not touched
+# by signal handlers and can be used as temporal storage without
+# allocating a frame.
+#
+# In Win64 terms N*8 bytes on top of stack is argument transfer area,
+# which belongs to/can be overwritten by callee. N is the number of
+# arguments passed to callee, *but* not less than 4! This means that
+# upon function entry point 5th argument resides at 40(%rsp), as well
+# as that 32 bytes from 8(%rsp) can always be used as temporal
+# storage [without allocating a frame]. One can actually argue that
+# one can assume a "red zone" above stack pointer under Win64 as well.
+# Point is that at apparently no occasion Windows kernel would alter
+# the area above user stack pointer in true asynchronous manner...
+#
+# All the above means that if assembler programmer adheres to Unix
+# register and stack layout, but disregards the "red zone" existense,
+# it's possible to use following prologue and epilogue to "gear" from
+# Unix to Win64 ABI in leaf functions with not more than 6 arguments.
+#
+# omnipotent_function:
+# ifdef WIN64
+# movq %rdi,8(%rsp)
+# movq %rsi,16(%rsp)
+# movq %rcx,%rdi ; if 1st argument is actually present
+# movq %rdx,%rsi ; if 2nd argument is actually ...
+# movq %r8,%rdx ; if 3rd argument is ...
+# movq %r9,%rcx ; if 4th argument ...
+# movq 40(%rsp),%r8 ; if 5th ...
+# movq 48(%rsp),%r9 ; if 6th ...
+# endif
+# ...
+# ifdef WIN64
+# movq 8(%rsp),%rdi
+# movq 16(%rsp),%rsi
+# endif
+# ret
+#
+ #################################################
+# Win64 SEH, Structured Exception Handling.
+#
+# Unlike on Unix systems(*) lack of Win64 stack unwinding information
+# has undesired side-effect at run-time: if an exception is raised in
+# assembler subroutine such as those in question (basically we're
+# referring to segmentation violations caused by malformed input
+# parameters), the application is briskly terminated without invoking
+# any exception handlers, most notably without generating memory dump
+# or any user notification whatsoever. This poses a problem. It's
+# possible to address it by registering custom language-specific
+# handler that would restore processor context to the state at
+# subroutine entry point and return "exception is not handled, keep
+# unwinding" code. Writing such handler can be a challenge... But it's
+# doable, though requires certain coding convention. Consider following
+# snippet:
+#
+# .type function,@function
+# function:
+# movq %rsp,%rax # copy rsp to volatile register
+# pushq %r15 # save non-volatile registers
+# pushq %rbx
+# pushq %rbp
+# movq %rsp,%r11
+# subq %rdi,%r11 # prepare [variable] stack frame
+# andq $-64,%r11
+# movq %rax,0(%r11) # check for exceptions
+# movq %r11,%rsp # allocate [variable] stack frame
+# movq %rax,0(%rsp) # save original rsp value
+# magic_point:
+# ...
+# movq 0(%rsp),%rcx # pull original rsp value
+# movq -24(%rcx),%rbp # restore non-volatile registers
+# movq -16(%rcx),%rbx
+# movq -8(%rcx),%r15
+# movq %rcx,%rsp # restore original rsp
+# ret
+# .size function,.-function
+#
+# The key is that up to magic_point copy of original rsp value remains
+# in chosen volatile register and no non-volatile register, except for
+# rsp, is modified. While past magic_point rsp remains constant till
+# the very end of the function. In this case custom language-specific
+# exception handler would look like this:
+#
+# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame,
+# CONTEXT *context,DISPATCHER_CONTEXT *disp)
+# { ULONG64 *rsp = (ULONG64 *)context->Rax;
+# if (context->Rip >= magic_point)
+# { rsp = ((ULONG64 **)context->Rsp)[0];
+# context->Rbp = rsp[-3];
+# context->Rbx = rsp[-2];
+# context->R15 = rsp[-1];
+# }
+# context->Rsp = (ULONG64)rsp;
+# context->Rdi = rsp[1];
+# context->Rsi = rsp[2];
+#
+# memcpy (disp->ContextRecord,context,sizeof(CONTEXT));
+# RtlVirtualUnwind(UNW_FLAG_NHANDLER,disp->ImageBase,
+# dips->ControlPc,disp->FunctionEntry,disp->ContextRecord,
+# &disp->HandlerData,&disp->EstablisherFrame,NULL);
+# return ExceptionContinueSearch;
+# }
+#
+# It's appropriate to implement this handler in assembler, directly in
+# function's module. In order to do that one has to know members'
+# offsets in CONTEXT and DISPATCHER_CONTEXT structures and some constant
+# values. Here they are:
+#
+# CONTEXT.Rax 120
+# CONTEXT.Rcx 128
+# CONTEXT.Rdx 136
+# CONTEXT.Rbx 144
+# CONTEXT.Rsp 152
+# CONTEXT.Rbp 160
+# CONTEXT.Rsi 168
+# CONTEXT.Rdi 176
+# CONTEXT.R8 184
+# CONTEXT.R9 192
+# CONTEXT.R10 200
+# CONTEXT.R11 208
+# CONTEXT.R12 216
+# CONTEXT.R13 224
+# CONTEXT.R14 232
+# CONTEXT.R15 240
+# CONTEXT.Rip 248
+# CONTEXT.Xmm6 512
+# sizeof(CONTEXT) 1232
+# DISPATCHER_CONTEXT.ControlPc 0
+# DISPATCHER_CONTEXT.ImageBase 8
+# DISPATCHER_CONTEXT.FunctionEntry 16
+# DISPATCHER_CONTEXT.EstablisherFrame 24
+# DISPATCHER_CONTEXT.TargetIp 32
+# DISPATCHER_CONTEXT.ContextRecord 40
+# DISPATCHER_CONTEXT.LanguageHandler 48
+# DISPATCHER_CONTEXT.HandlerData 56
+# UNW_FLAG_NHANDLER 0
+# ExceptionContinueSearch 1
+#
+# In order to tie the handler to the function one has to compose
+# couple of structures: one for .xdata segment and one for .pdata.
+#
+# UNWIND_INFO structure for .xdata segment would be
+#
+# function_unwind_info:
+# .byte 9,0,0,0
+# .rva handler
+#
+# This structure designates exception handler for a function with
+# zero-length prologue, no stack frame or frame register.
+#
+# To facilitate composing of .pdata structures, auto-generated "gear"
+# prologue copies rsp value to rax and denotes next instruction with
+# .LSEH_begin_{function_name} label. This essentially defines the SEH
+# styling rule mentioned in the beginning. Position of this label is
+# chosen in such manner that possible exceptions raised in the "gear"
+# prologue would be accounted to caller and unwound from latter's frame.
+# End of function is marked with respective .LSEH_end_{function_name}
+# label. To summarize, .pdata segment would contain
+#
+# .rva .LSEH_begin_function
+# .rva .LSEH_end_function
+# .rva function_unwind_info
+#
+# Reference to functon_unwind_info from .xdata segment is the anchor.
+# In case you wonder why references are 32-bit .rvas and not 64-bit
+# .quads. References put into these two segments are required to be
+# *relative* to the base address of the current binary module, a.k.a.
+# image base. No Win64 module, be it .exe or .dll, can be larger than
+# 2GB and thus such relative references can be and are accommodated in
+# 32 bits.
+#
+# Having reviewed the example function code, one can argue that "movq
+# %rsp,%rax" above is redundant. It is not! Keep in mind that on Unix
+# rax would contain an undefined value. If this "offends" you, use
+# another register and refrain from modifying rax till magic_point is
+# reached, i.e. as if it was a non-volatile register. If more registers
+# are required prior [variable] frame setup is completed, note that
+# nobody says that you can have only one "magic point." You can
+# "liberate" non-volatile registers by denoting last stack off-load
+# instruction and reflecting it in finer grade unwind logic in handler.
+# After all, isn't it why it's called *language-specific* handler...
+#
+# Attentive reader can notice that exceptions would be mishandled in
+# auto-generated "gear" epilogue. Well, exception effectively can't
+# occur there, because if memory area used by it was subject to
+# segmentation violation, then it would be raised upon call to the
+# function (and as already mentioned be accounted to caller, which is
+# not a problem). If you're still not comfortable, then define tail
+# "magic point" just prior ret instruction and have handler treat it...
+#
+# (*) Note that we're talking about run-time, not debug-time. Lack of
+# unwind information makes debugging hard on both Windows and
+# Unix. "Unlike" referes to the fact that on Unix signal handler
+# will always be invoked, core dumped and appropriate exit code
+# returned to parent (for user notification).
diff --git a/src/crypto/perlasm/x86asm.pl b/src/crypto/perlasm/x86asm.pl
new file mode 100644
index 0000000..3c7be40
--- /dev/null
+++ b/src/crypto/perlasm/x86asm.pl
@@ -0,0 +1,292 @@
+#!/usr/bin/env perl
+
+# require 'x86asm.pl';
+# &asm_init(<flavor>,"des-586.pl"[,$i386only]);
+# &function_begin("foo");
+# ...
+# &function_end("foo");
+# &asm_finish
+
+$out=();
+$i386=0;
+
+# AUTOLOAD is this context has quite unpleasant side effect, namely
+# that typos in function calls effectively go to assembler output,
+# but on the pros side we don't have to implement one subroutine per
+# each opcode...
+sub ::AUTOLOAD
+{ my $opcode = $AUTOLOAD;
+
+ die "more than 4 arguments passed to $opcode" if ($#_>3);
+
+ $opcode =~ s/.*:://;
+ if ($opcode =~ /^push/) { $stack+=4; }
+ elsif ($opcode =~ /^pop/) { $stack-=4; }
+
+ &generic($opcode,@_) or die "undefined subroutine \&$AUTOLOAD";
+}
+
+sub ::emit
+{ my $opcode=shift;
+
+ if ($#_==-1) { push(@out,"\t$opcode\n"); }
+ else { push(@out,"\t$opcode\t".join(',',@_)."\n"); }
+}
+
+sub ::LB
+{ $_[0] =~ m/^e?([a-d])x$/o or die "$_[0] does not have a 'low byte'";
+ $1."l";
+}
+sub ::HB
+{ $_[0] =~ m/^e?([a-d])x$/o or die "$_[0] does not have a 'high byte'";
+ $1."h";
+}
+sub ::stack_push{ my $num=$_[0]*4; $stack+=$num; &sub("esp",$num); }
+sub ::stack_pop { my $num=$_[0]*4; $stack-=$num; &add("esp",$num); }
+sub ::blindpop { &pop($_[0]); $stack+=4; }
+sub ::wparam { &DWP($stack+4*$_[0],"esp"); }
+sub ::swtmp { &DWP(4*$_[0],"esp"); }
+
+sub ::bswap
+{ if ($i386) # emulate bswap for i386
+ { &comment("bswap @_");
+ &xchg(&HB(@_),&LB(@_));
+ &ror (@_,16);
+ &xchg(&HB(@_),&LB(@_));
+ }
+ else
+ { &generic("bswap",@_); }
+}
+# These are made-up opcodes introduced over the years essentially
+# by ignorance, just alias them to real ones...
+sub ::movb { &mov(@_); }
+sub ::xorb { &xor(@_); }
+sub ::rotl { &rol(@_); }
+sub ::rotr { &ror(@_); }
+sub ::exch { &xchg(@_); }
+sub ::halt { &hlt; }
+sub ::movz { &movzx(@_); }
+sub ::pushf { &pushfd; }
+sub ::popf { &popfd; }
+
+# 3 argument instructions
+sub ::movq
+{ my($p1,$p2,$optimize)=@_;
+
+ if ($optimize && $p1=~/^mm[0-7]$/ && $p2=~/^mm[0-7]$/)
+ # movq between mmx registers can sink Intel CPUs
+ { &::pshufw($p1,$p2,0xe4); }
+ else
+ { &::generic("movq",@_); }
+}
+
+# SSE>2 instructions
+my %regrm = ( "eax"=>0, "ecx"=>1, "edx"=>2, "ebx"=>3,
+ "esp"=>4, "ebp"=>5, "esi"=>6, "edi"=>7 );
+sub ::pextrd
+{ my($dst,$src,$imm)=@_;
+ if ("$dst:$src" =~ /(e[a-dsd][ixp]):xmm([0-7])/)
+ { &::data_byte(0x66,0x0f,0x3a,0x16,0xc0|($2<<3)|$regrm{$1},$imm); }
+ else
+ { &::generic("pextrd",@_); }
+}
+
+sub ::pinsrd
+{ my($dst,$src,$imm)=@_;
+ if ("$dst:$src" =~ /xmm([0-7]):(e[a-dsd][ixp])/)
+ { &::data_byte(0x66,0x0f,0x3a,0x22,0xc0|($1<<3)|$regrm{$2},$imm); }
+ else
+ { &::generic("pinsrd",@_); }
+}
+
+sub ::pshufb
+{ my($dst,$src)=@_;
+ if ("$dst:$src" =~ /xmm([0-7]):xmm([0-7])/)
+ { &data_byte(0x66,0x0f,0x38,0x00,0xc0|($1<<3)|$2); }
+ else
+ { &::generic("pshufb",@_); }
+}
+
+sub ::palignr
+{ my($dst,$src,$imm)=@_;
+ if ("$dst:$src" =~ /xmm([0-7]):xmm([0-7])/)
+ { &::data_byte(0x66,0x0f,0x3a,0x0f,0xc0|($1<<3)|$2,$imm); }
+ else
+ { &::generic("palignr",@_); }
+}
+
+sub ::pclmulqdq
+{ my($dst,$src,$imm)=@_;
+ if ("$dst:$src" =~ /xmm([0-7]):xmm([0-7])/)
+ { &::data_byte(0x66,0x0f,0x3a,0x44,0xc0|($1<<3)|$2,$imm); }
+ else
+ { &::generic("pclmulqdq",@_); }
+}
+
+sub ::rdrand
+{ my ($dst)=@_;
+ if ($dst =~ /(e[a-dsd][ixp])/)
+ { &::data_byte(0x0f,0xc7,0xf0|$regrm{$dst}); }
+ else
+ { &::generic("rdrand",@_); }
+}
+
+sub rxb {
+ local *opcode=shift;
+ my ($dst,$src1,$src2,$rxb)=@_;
+
+ $rxb|=0x7<<5;
+ $rxb&=~(0x04<<5) if($dst>=8);
+ $rxb&=~(0x01<<5) if($src1>=8);
+ $rxb&=~(0x02<<5) if($src2>=8);
+ push @opcode,$rxb;
+}
+
+sub ::vprotd
+{ my $args=join(',',@_);
+ if ($args =~ /xmm([0-7]),xmm([0-7]),([x0-9a-f]+)/)
+ { my @opcode=(0x8f);
+ rxb(\@opcode,$1,$2,-1,0x08);
+ push @opcode,0x78,0xc2;
+ push @opcode,0xc0|($2&7)|(($1&7)<<3); # ModR/M
+ my $c=$3;
+ push @opcode,$c=~/^0/?oct($c):$c;
+ &::data_byte(@opcode);
+ }
+ else
+ { &::generic("vprotd",@_); }
+}
+
+# label management
+$lbdecor="L"; # local label decoration, set by package
+$label="000";
+
+sub ::islabel # see is argument is a known label
+{ my $i;
+ foreach $i (values %label) { return $i if ($i eq $_[0]); }
+ $label{$_[0]}; # can be undef
+}
+
+sub ::label # instantiate a function-scope label
+{ if (!defined($label{$_[0]}))
+ { $label{$_[0]}="${lbdecor}${label}${_[0]}"; $label++; }
+ $label{$_[0]};
+}
+
+sub ::LABEL # instantiate a file-scope label
+{ $label{$_[0]}=$_[1] if (!defined($label{$_[0]}));
+ $label{$_[0]};
+}
+
+sub ::static_label { &::LABEL($_[0],$lbdecor.$_[0]); }
+
+sub ::set_label_B { push(@out,"@_:\n"); }
+sub ::set_label
+{ my $label=&::label($_[0]);
+ &::align($_[1]) if ($_[1]>1);
+ &::set_label_B($label);
+ $label;
+}
+
+sub ::wipe_labels # wipes function-scope labels
+{ foreach $i (keys %label)
+ { delete $label{$i} if ($label{$i} =~ /^\Q${lbdecor}\E[0-9]{3}/); }
+}
+
+# subroutine management
+sub ::function_begin
+{ &function_begin_B(@_);
+ $stack=4;
+ &push("ebp");
+ &push("ebx");
+ &push("esi");
+ &push("edi");
+}
+
+sub ::function_end
+{ &pop("edi");
+ &pop("esi");
+ &pop("ebx");
+ &pop("ebp");
+ &ret();
+ &function_end_B(@_);
+ $stack=0;
+ &wipe_labels();
+}
+
+sub ::function_end_A
+{ &pop("edi");
+ &pop("esi");
+ &pop("ebx");
+ &pop("ebp");
+ &ret();
+ $stack+=16; # readjust esp as if we didn't pop anything
+}
+
+sub ::asciz
+{ my @str=unpack("C*",shift);
+ push @str,0;
+ while ($#str>15) {
+ &data_byte(@str[0..15]);
+ foreach (0..15) { shift @str; }
+ }
+ &data_byte(@str) if (@str);
+}
+
+sub ::asm_finish
+{ &file_end();
+ print "#if defined(__i386__)\n" unless $win32;
+ print @out;
+ print "#endif\n" unless $win32;
+}
+
+sub ::asm_init
+{ my ($type,$fn,$cpu)=@_;
+
+ $filename=$fn;
+ $i386=$cpu;
+
+ $elf=$cpp=$coff=$aout=$macosx=$win32=$netware=$mwerks=$android=0;
+ if (($type eq "elf"))
+ { $elf=1; require "x86gas.pl"; }
+ elsif (($type eq "elf-1"))
+ { $elf=-1; require "x86gas.pl"; }
+ elsif (($type eq "a\.out"))
+ { $aout=1; require "x86gas.pl"; }
+ elsif (($type eq "coff" or $type eq "gaswin"))
+ { $coff=1; require "x86gas.pl"; }
+ elsif (($type eq "win32n"))
+ { $win32=1; require "x86nasm.pl"; }
+ elsif (($type eq "nw-nasm"))
+ { $netware=1; require "x86nasm.pl"; }
+ #elsif (($type eq "nw-mwasm"))
+ #{ $netware=1; $mwerks=1; require "x86nasm.pl"; }
+ elsif (($type eq "win32"))
+ { $win32=1; require "x86masm.pl"; }
+ elsif (($type eq "macosx"))
+ { $aout=1; $macosx=1; require "x86gas.pl"; }
+ elsif (($type eq "android"))
+ { $elf=1; $android=1; require "x86gas.pl"; }
+ else
+ { print STDERR <<"EOF";
+Pick one target type from
+ elf - Linux, FreeBSD, Solaris x86, etc.
+ a.out - DJGPP, elder OpenBSD, etc.
+ coff - GAS/COFF such as Win32 targets
+ win32n - Windows 95/Windows NT NASM format
+ nw-nasm - NetWare NASM format
+ macosx - Mac OS X
+EOF
+ exit(1);
+ }
+
+ $pic=0;
+ for (@ARGV) { $pic=1 if (/\-[fK]PIC/i); }
+
+ $filename =~ s/\.pl$//;
+ &file($filename);
+}
+
+sub ::hidden {}
+
+1;
diff --git a/src/crypto/perlasm/x86gas.pl b/src/crypto/perlasm/x86gas.pl
new file mode 100644
index 0000000..99d7c1b
--- /dev/null
+++ b/src/crypto/perlasm/x86gas.pl
@@ -0,0 +1,263 @@
+#!/usr/bin/env perl
+
+package x86gas;
+
+*out=\@::out;
+
+$::lbdecor=$::aout?"L":".L"; # local label decoration
+$nmdecor=($::aout or $::coff)?"_":""; # external name decoration
+
+$initseg="";
+
+$align=16;
+$align=log($align)/log(2) if ($::aout);
+$com_start="#" if ($::aout or $::coff);
+
+sub opsize()
+{ my $reg=shift;
+ if ($reg =~ m/^%e/o) { "l"; }
+ elsif ($reg =~ m/^%[a-d][hl]$/o) { "b"; }
+ elsif ($reg =~ m/^%[xm]/o) { undef; }
+ else { "w"; }
+}
+
+# swap arguments;
+# expand opcode with size suffix;
+# prefix numeric constants with $;
+sub ::generic
+{ my($opcode,@arg)=@_;
+ my($suffix,$dst,$src);
+
+ @arg=reverse(@arg);
+
+ for (@arg)
+ { s/^(\*?)(e?[a-dsixphl]{2})$/$1%$2/o; # gp registers
+ s/^([xy]?mm[0-7])$/%$1/o; # xmm/mmx registers
+ s/^(\-?[0-9]+)$/\$$1/o; # constants
+ s/^(\-?0x[0-9a-f]+)$/\$$1/o; # constants
+ }
+
+ $dst = $arg[$#arg] if ($#arg>=0);
+ $src = $arg[$#arg-1] if ($#arg>=1);
+ if ($dst =~ m/^%/o) { $suffix=&opsize($dst); }
+ elsif ($src =~ m/^%/o) { $suffix=&opsize($src); }
+ else { $suffix="l"; }
+ undef $suffix if ($dst =~ m/^%[xm]/o || $src =~ m/^%[xm]/o);
+
+ if ($#_==0) { &::emit($opcode); }
+ elsif ($#_==1 && $opcode =~ m/^(call|clflush|j|loop|set)/o)
+ { &::emit($opcode,@arg); }
+ else { &::emit($opcode.$suffix,@arg);}
+
+ 1;
+}
+#
+# opcodes not covered by ::generic above, mostly inconsistent namings...
+#
+sub ::movzx { &::movzb(@_); }
+sub ::pushfd { &::pushfl; }
+sub ::popfd { &::popfl; }
+sub ::cpuid { &::emit(".byte\t0x0f,0xa2"); }
+sub ::rdtsc { &::emit(".byte\t0x0f,0x31"); }
+
+sub ::call { &::emit("call",(&::islabel($_[0]) or "$nmdecor$_[0]")); }
+sub ::call_ptr { &::generic("call","*$_[0]"); }
+sub ::jmp_ptr { &::generic("jmp","*$_[0]"); }
+
+*::bswap = sub { &::emit("bswap","%$_[0]"); } if (!$::i386);
+
+sub ::DWP
+{ my($addr,$reg1,$reg2,$idx)=@_;
+ my $ret="";
+
+ if (!defined($idx) && 1*$reg2) { $idx=$reg2; $reg2=$reg1; undef $reg1; }
+
+ $addr =~ s/^\s+//;
+ # prepend global references with optional underscore
+ $addr =~ s/^([^\+\-0-9][^\+\-]*)/&::islabel($1) or "$nmdecor$1"/ige;
+
+ $reg1 = "%$reg1" if ($reg1);
+ $reg2 = "%$reg2" if ($reg2);
+
+ $ret .= $addr if (($addr ne "") && ($addr ne 0));
+
+ if ($reg2)
+ { $idx!= 0 or $idx=1;
+ $ret .= "($reg1,$reg2,$idx)";
+ }
+ elsif ($reg1)
+ { $ret .= "($reg1)"; }
+
+ $ret;
+}
+sub ::QWP { &::DWP(@_); }
+sub ::BP { &::DWP(@_); }
+sub ::WP { &::DWP(@_); }
+sub ::BC { @_; }
+sub ::DWC { @_; }
+
+sub ::file
+{ push(@out,".file\t\"$_[0].S\"\n.text\n"); }
+
+sub ::function_begin_B
+{ my $func=shift;
+ my $global=($func !~ /^_/);
+ my $begin="${::lbdecor}_${func}_begin";
+
+ &::LABEL($func,$global?"$begin":"$nmdecor$func");
+ $func=$nmdecor.$func;
+
+ push(@out,".globl\t$func\n") if ($global);
+ if ($::macosx) {
+ push(@out,".private_extern\t$func\n");
+ } else {
+ push(@out,".hidden\t$func\n");
+ }
+ if ($::coff)
+ { push(@out,".def\t$func;\t.scl\t".(3-$global).";\t.type\t32;\t.endef\n"); }
+ elsif (($::aout and !$::pic) or $::macosx)
+ { }
+ else
+ { push(@out,".type $func,\@function\n"); }
+ push(@out,".align\t$align\n");
+ push(@out,"$func:\n");
+ push(@out,"$begin:\n") if ($global);
+ $::stack=4;
+}
+
+sub ::function_end_B
+{ my $func=shift;
+ push(@out,".size\t$nmdecor$func,.-".&::LABEL($func)."\n") if ($::elf);
+ $::stack=0;
+ &::wipe_labels();
+}
+
+sub ::comment
+ {
+ if (!defined($com_start) or $::elf)
+ { # Regarding $::elf above...
+ # GNU and SVR4 as'es use different comment delimiters,
+ push(@out,"\n"); # so we just skip ELF comments...
+ return;
+ }
+ foreach (@_)
+ {
+ if (/^\s*$/)
+ { push(@out,"\n"); }
+ else
+ { push(@out,"\t$com_start $_ $com_end\n"); }
+ }
+ }
+
+sub ::external_label
+{ foreach(@_) { &::LABEL($_,$nmdecor.$_); } }
+
+sub ::public_label
+{ push(@out,".globl\t".&::LABEL($_[0],$nmdecor.$_[0])."\n"); }
+
+sub ::file_end
+{ if ($::macosx)
+ { if (%non_lazy_ptr)
+ { push(@out,".section __IMPORT,__pointers,non_lazy_symbol_pointers\n");
+ foreach $i (keys %non_lazy_ptr)
+ { push(@out,"$non_lazy_ptr{$i}:\n.indirect_symbol\t$i\n.long\t0\n"); }
+ }
+ }
+ if (0 && grep {/\b${nmdecor}OPENSSL_ia32cap_P\b/i} @out) {
+ my $tmp=".comm\t${nmdecor}OPENSSL_ia32cap_P,16";
+ if ($::macosx) { push (@out,"$tmp,2\n"); }
+ elsif ($::elf) { push (@out,"$tmp,4\n"); }
+ else { push (@out,"$tmp\n"); }
+ }
+ push(@out,$initseg) if ($initseg);
+}
+
+sub ::data_byte { push(@out,".byte\t".join(',',@_)."\n"); }
+sub ::data_short{ push(@out,".value\t".join(',',@_)."\n"); }
+sub ::data_word { push(@out,".long\t".join(',',@_)."\n"); }
+
+sub ::align
+{ my $val=$_[0];
+ if ($::aout)
+ { $val=int(log($val)/log(2));
+ $val.=",0x90";
+ }
+ push(@out,".align\t$val\n");
+}
+
+sub ::picmeup
+{ my($dst,$sym,$base,$reflabel)=@_;
+
+ if (($::pic && ($::elf || $::aout)) || $::macosx)
+ { if (!defined($base))
+ { &::call(&::label("PIC_me_up"));
+ &::set_label("PIC_me_up");
+ &::blindpop($dst);
+ $base=$dst;
+ $reflabel=&::label("PIC_me_up");
+ }
+ if ($::macosx)
+ { my $indirect=&::static_label("$nmdecor$sym\$non_lazy_ptr");
+ &::mov($dst,&::DWP("$indirect-$reflabel",$base));
+ $non_lazy_ptr{"$nmdecor$sym"}=$indirect;
+ }
+ elsif ($sym eq "OPENSSL_ia32cap_P" && $::elf>0)
+ { &::lea($dst,&::DWP("$sym-$reflabel",$base)); }
+ else
+ { &::lea($dst,&::DWP("_GLOBAL_OFFSET_TABLE_+[.-$reflabel]",
+ $base));
+ &::mov($dst,&::DWP("$sym\@GOT",$dst));
+ }
+ }
+ else
+ { &::lea($dst,&::DWP($sym)); }
+}
+
+sub ::initseg
+{ my $f=$nmdecor.shift;
+
+ if ($::android)
+ { $initseg.=<<___;
+.section .init_array
+.align 4
+.long $f
+___
+ }
+ elsif ($::elf)
+ { $initseg.=<<___;
+.section .init
+ call $f
+___
+ }
+ elsif ($::coff)
+ { $initseg.=<<___; # applies to both Cygwin and Mingw
+.section .ctors
+.long $f
+___
+ }
+ elsif ($::macosx)
+ { $initseg.=<<___;
+.mod_init_func
+.align 2
+.long $f
+___
+ }
+ elsif ($::aout)
+ { my $ctor="${nmdecor}_GLOBAL_\$I\$$f";
+ $initseg.=".text\n";
+ $initseg.=".type $ctor,\@function\n" if ($::pic);
+ $initseg.=<<___; # OpenBSD way...
+.globl $ctor
+.align 2
+$ctor:
+ jmp $f
+___
+ }
+}
+
+sub ::dataseg
+{ push(@out,".data\n"); }
+
+*::hidden = sub { push(@out,".hidden\t$nmdecor$_[0]\n"); } if ($::elf);
+
+1;
diff --git a/src/crypto/perlasm/x86masm.pl b/src/crypto/perlasm/x86masm.pl
new file mode 100644
index 0000000..a491529
--- /dev/null
+++ b/src/crypto/perlasm/x86masm.pl
@@ -0,0 +1,203 @@
+#!/usr/bin/env perl
+
+package x86masm;
+
+*out=\@::out;
+
+$::lbdecor="\$L"; # local label decoration
+$nmdecor="_"; # external name decoration
+
+$initseg="";
+$segment="";
+
+sub ::generic
+{ my ($opcode,@arg)=@_;
+
+ # fix hexadecimal constants
+ for (@arg) { s/(?<![\w\$\.])0x([0-9a-f]+)/0$1h/oi; }
+
+ if ($opcode =~ /lea/ && @arg[1] =~ s/.*PTR\s+(\(.*\))$/OFFSET $1/) # no []
+ { $opcode="mov"; }
+ elsif ($opcode !~ /movq/)
+ { # fix xmm references
+ $arg[0] =~ s/\b[A-Z]+WORD\s+PTR/XMMWORD PTR/i if ($arg[1]=~/\bxmm[0-7]\b/i);
+ $arg[1] =~ s/\b[A-Z]+WORD\s+PTR/XMMWORD PTR/i if ($arg[0]=~/\bxmm[0-7]\b/i);
+ }
+
+ &::emit($opcode,@arg);
+ 1;
+}
+#
+# opcodes not covered by ::generic above, mostly inconsistent namings...
+#
+sub ::call { &::emit("call",(&::islabel($_[0]) or "$nmdecor$_[0]")); }
+sub ::call_ptr { &::emit("call",@_); }
+sub ::jmp_ptr { &::emit("jmp",@_); }
+sub ::lock { &::data_byte(0xf0); }
+
+sub get_mem
+{ my($size,$addr,$reg1,$reg2,$idx)=@_;
+ my($post,$ret);
+
+ if (!defined($idx) && 1*$reg2) { $idx=$reg2; $reg2=$reg1; undef $reg1; }
+
+ $ret .= "$size PTR " if ($size ne "");
+
+ $addr =~ s/^\s+//;
+ # prepend global references with optional underscore
+ $addr =~ s/^([^\+\-0-9][^\+\-]*)/&::islabel($1) or "$nmdecor$1"/ige;
+ # put address arithmetic expression in parenthesis
+ $addr="($addr)" if ($addr =~ /^.+[\-\+].+$/);
+
+ if (($addr ne "") && ($addr ne 0))
+ { if ($addr !~ /^-/) { $ret .= "$addr"; }
+ else { $post=$addr; }
+ }
+ $ret .= "[";
+
+ if ($reg2 ne "")
+ { $idx!=0 or $idx=1;
+ $ret .= "$reg2*$idx";
+ $ret .= "+$reg1" if ($reg1 ne "");
+ }
+ else
+ { $ret .= "$reg1"; }
+
+ $ret .= "$post]";
+ $ret =~ s/\+\]/]/; # in case $addr was the only argument
+ $ret =~ s/\[\s*\]//;
+
+ $ret;
+}
+sub ::BP { &get_mem("BYTE",@_); }
+sub ::WP { &get_mem("WORD",@_); }
+sub ::DWP { &get_mem("DWORD",@_); }
+sub ::QWP { &get_mem("QWORD",@_); }
+sub ::BC { "@_"; }
+sub ::DWC { "@_"; }
+
+sub ::file
+{ my $tmp=<<___;
+TITLE $_[0].asm
+IF \@Version LT 800
+ECHO MASM version 8.00 or later is strongly recommended.
+ENDIF
+.686
+.MODEL FLAT
+OPTION DOTNAME
+IF \@Version LT 800
+.text\$ SEGMENT PAGE 'CODE'
+ELSE
+.text\$ SEGMENT ALIGN(64) 'CODE'
+ENDIF
+___
+ push(@out,$tmp);
+ $segment = ".text\$";
+}
+
+sub ::function_begin_B
+{ my $func=shift;
+ my $global=($func !~ /^_/);
+ my $begin="${::lbdecor}_${func}_begin";
+
+ &::LABEL($func,$global?"$begin":"$nmdecor$func");
+ $func="ALIGN\t16\n".$nmdecor.$func."\tPROC";
+
+ if ($global) { $func.=" PUBLIC\n${begin}::\n"; }
+ else { $func.=" PRIVATE\n"; }
+ push(@out,$func);
+ $::stack=4;
+}
+sub ::function_end_B
+{ my $func=shift;
+
+ push(@out,"$nmdecor$func ENDP\n");
+ $::stack=0;
+ &::wipe_labels();
+}
+
+sub ::file_end
+{ my $xmmheader=<<___;
+.686
+.XMM
+IF \@Version LT 800
+XMMWORD STRUCT 16
+DQ 2 dup (?)
+XMMWORD ENDS
+ENDIF
+___
+ if (grep {/\b[x]?mm[0-7]\b/i} @out) {
+ grep {s/\.[3-7]86/$xmmheader/} @out;
+ }
+
+ push(@out,"$segment ENDS\n");
+
+ if (grep {/\b${nmdecor}OPENSSL_ia32cap_P\b/i} @out)
+ { my $comm=<<___;
+.bss SEGMENT 'BSS'
+COMM ${nmdecor}OPENSSL_ia32cap_P:DWORD:4
+.bss ENDS
+___
+ # comment out OPENSSL_ia32cap_P declarations
+ grep {s/(^EXTERN\s+${nmdecor}OPENSSL_ia32cap_P)/\;$1/} @out;
+ push (@out,$comm);
+ }
+ push (@out,$initseg) if ($initseg);
+ push (@out,"END\n");
+}
+
+sub ::comment { foreach (@_) { push(@out,"\t; $_\n"); } }
+
+*::set_label_B = sub
+{ my $l=shift; push(@out,$l.($l=~/^\Q${::lbdecor}\E[0-9]{3}/?":\n":"::\n")); };
+
+sub ::external_label
+{ foreach(@_)
+ { push(@out, "EXTERN\t".&::LABEL($_,$nmdecor.$_).":NEAR\n"); }
+}
+
+sub ::public_label
+{ push(@out,"PUBLIC\t".&::LABEL($_[0],$nmdecor.$_[0])."\n"); }
+
+sub ::data_byte
+{ push(@out,("DB\t").join(',',@_)."\n"); }
+
+sub ::data_short
+{ push(@out,("DW\t").join(',',@_)."\n"); }
+
+sub ::data_word
+{ # MASM can't handle long lines, so emit one word at a time.
+ foreach(@_)
+ { push(@out,"DD\t$_\n"); }
+}
+
+sub ::align
+{ push(@out,"ALIGN\t$_[0]\n"); }
+
+sub ::picmeup
+{ my($dst,$sym)=@_;
+ &::lea($dst,&::DWP($sym));
+}
+
+sub ::initseg
+{ my $f=$nmdecor.shift;
+
+ $initseg.=<<___;
+.CRT\$XCU SEGMENT DWORD PUBLIC 'DATA'
+EXTERN $f:NEAR
+DD $f
+.CRT\$XCU ENDS
+___
+}
+
+sub ::dataseg
+{ push(@out,"$segment\tENDS\n_DATA\tSEGMENT\n"); $segment="_DATA"; }
+
+sub ::safeseh
+{ my $nm=shift;
+ push(@out,"IF \@Version GE 710\n");
+ push(@out,".SAFESEH ".&::LABEL($nm,$nmdecor.$nm)."\n");
+ push(@out,"ENDIF\n");
+}
+
+1;
diff --git a/src/crypto/perlasm/x86nasm.pl b/src/crypto/perlasm/x86nasm.pl
new file mode 100644
index 0000000..f8332bb
--- /dev/null
+++ b/src/crypto/perlasm/x86nasm.pl
@@ -0,0 +1,187 @@
+#!/usr/bin/env perl
+
+package x86nasm;
+
+*out=\@::out;
+
+$::lbdecor="L\$"; # local label decoration
+$nmdecor=$::netware?"":"_"; # external name decoration
+$drdecor=$::mwerks?".":""; # directive decoration
+
+$initseg="";
+
+sub ::generic
+{ my $opcode=shift;
+ my $tmp;
+
+ if (!$::mwerks)
+ { if ($opcode =~ m/^j/o && $#_==0) # optimize jumps
+ { $_[0] = "NEAR $_[0]"; }
+ elsif ($opcode eq "lea" && $#_==1) # wipe storage qualifier from lea
+ { $_[1] =~ s/^[^\[]*\[/\[/o; }
+ elsif ($opcode eq "clflush" && $#_==0)
+ { $_[0] =~ s/^[^\[]*\[/\[/o; }
+ }
+ &::emit($opcode,@_);
+ 1;
+}
+#
+# opcodes not covered by ::generic above, mostly inconsistent namings...
+#
+sub ::call { &::emit("call",(&::islabel($_[0]) or "$nmdecor$_[0]")); }
+sub ::call_ptr { &::emit("call",@_); }
+sub ::jmp_ptr { &::emit("jmp",@_); }
+
+sub get_mem
+{ my($size,$addr,$reg1,$reg2,$idx)=@_;
+ my($post,$ret);
+
+ if (!defined($idx) && 1*$reg2) { $idx=$reg2; $reg2=$reg1; undef $reg1; }
+
+ if ($size ne "")
+ { $ret .= "$size";
+ $ret .= " PTR" if ($::mwerks);
+ $ret .= " ";
+ }
+ $ret .= "[";
+
+ $addr =~ s/^\s+//;
+ # prepend global references with optional underscore
+ $addr =~ s/^([^\+\-0-9][^\+\-]*)/::islabel($1) or "$nmdecor$1"/ige;
+ # put address arithmetic expression in parenthesis
+ $addr="($addr)" if ($addr =~ /^.+[\-\+].+$/);
+
+ if (($addr ne "") && ($addr ne 0))
+ { if ($addr !~ /^-/) { $ret .= "$addr+"; }
+ else { $post=$addr; }
+ }
+
+ if ($reg2 ne "")
+ { $idx!=0 or $idx=1;
+ $ret .= "$reg2*$idx";
+ $ret .= "+$reg1" if ($reg1 ne "");
+ }
+ else
+ { $ret .= "$reg1"; }
+
+ $ret .= "$post]";
+ $ret =~ s/\+\]/]/; # in case $addr was the only argument
+
+ $ret;
+}
+sub ::BP { &get_mem("BYTE",@_); }
+sub ::DWP { &get_mem("DWORD",@_); }
+sub ::WP { &get_mem("WORD",@_); }
+sub ::QWP { &get_mem("",@_); }
+sub ::BC { (($::mwerks)?"":"BYTE ")."@_"; }
+sub ::DWC { (($::mwerks)?"":"DWORD ")."@_"; }
+
+sub ::file
+{ if ($::mwerks) { push(@out,".section\t.text,64\n"); }
+ else
+ { my $tmp=<<___;
+%ifidn __OUTPUT_FORMAT__,obj
+section code use32 class=code align=64
+%elifidn __OUTPUT_FORMAT__,win32
+%ifdef __YASM_VERSION_ID__
+%if __YASM_VERSION_ID__ < 01010000h
+%error yasm version 1.1.0 or later needed.
+%endif
+; Yasm automatically includes @feat.00 and complains about redefining it.
+; https://www.tortall.net/projects/yasm/manual/html/objfmt-win32-safeseh.html
+%else
+\$\@feat.00 equ 1
+%endif
+section .text code align=64
+%else
+section .text code
+%endif
+___
+ push(@out,$tmp);
+ }
+}
+
+sub ::function_begin_B
+{ my $func=shift;
+ my $global=($func !~ /^_/);
+ my $begin="${::lbdecor}_${func}_begin";
+
+ $begin =~ s/^\@/./ if ($::mwerks); # the torture never stops
+
+ &::LABEL($func,$global?"$begin":"$nmdecor$func");
+ $func=$nmdecor.$func;
+
+ push(@out,"${drdecor}global $func\n") if ($global);
+ push(@out,"${drdecor}align 16\n");
+ push(@out,"$func:\n");
+ push(@out,"$begin:\n") if ($global);
+ $::stack=4;
+}
+
+sub ::function_end_B
+{ $::stack=0;
+ &::wipe_labels();
+}
+
+sub ::file_end
+{ if (grep {/\b${nmdecor}OPENSSL_ia32cap_P\b/i} @out)
+ { my $comm=<<___;
+${drdecor}segment .bss
+${drdecor}common ${nmdecor}OPENSSL_ia32cap_P 16
+___
+ # comment out OPENSSL_ia32cap_P declarations
+ grep {s/(^extern\s+${nmdecor}OPENSSL_ia32cap_P)/\;$1/} @out;
+ push (@out,$comm)
+ }
+ push (@out,$initseg) if ($initseg);
+}
+
+sub ::comment { foreach (@_) { push(@out,"\t; $_\n"); } }
+
+sub ::external_label
+{ foreach(@_)
+ { push(@out,"${drdecor}extern\t".&::LABEL($_,$nmdecor.$_)."\n"); }
+}
+
+sub ::public_label
+{ push(@out,"${drdecor}global\t".&::LABEL($_[0],$nmdecor.$_[0])."\n"); }
+
+sub ::data_byte
+{ push(@out,(($::mwerks)?".byte\t":"db\t").join(',',@_)."\n"); }
+sub ::data_short
+{ push(@out,(($::mwerks)?".word\t":"dw\t").join(',',@_)."\n"); }
+sub ::data_word
+{ push(@out,(($::mwerks)?".long\t":"dd\t").join(',',@_)."\n"); }
+
+sub ::align
+{ push(@out,"${drdecor}align\t$_[0]\n"); }
+
+sub ::picmeup
+{ my($dst,$sym)=@_;
+ &::lea($dst,&::DWP($sym));
+}
+
+sub ::initseg
+{ my $f=$nmdecor.shift;
+ if ($::win32)
+ { $initseg=<<___;
+segment .CRT\$XCU data align=4
+extern $f
+dd $f
+___
+ }
+}
+
+sub ::dataseg
+{ if ($mwerks) { push(@out,".section\t.data,4\n"); }
+ else { push(@out,"section\t.data align=4\n"); }
+}
+
+sub ::safeseh
+{ my $nm=shift;
+ push(@out,"%if __NASM_VERSION_ID__ >= 0x02030000\n");
+ push(@out,"safeseh ".&::LABEL($nm,$nmdecor.$nm)."\n");
+ push(@out,"%endif\n");
+}
+
+1;
diff --git a/src/crypto/pkcs8/CMakeLists.txt b/src/crypto/pkcs8/CMakeLists.txt
new file mode 100644
index 0000000..1886fce
--- /dev/null
+++ b/src/crypto/pkcs8/CMakeLists.txt
@@ -0,0 +1,21 @@
+include_directories(. .. ../../include)
+
+add_library(
+ pkcs8
+
+ OBJECT
+
+ pkcs8.c
+ p8_pkey.c
+ p5_pbe.c
+ p5_pbev2.c
+ pkcs8_error.c
+)
+
+add_executable(
+ pkcs12_test
+
+ pkcs12_test.c
+)
+
+target_link_libraries(pkcs12_test crypto)
diff --git a/src/crypto/pkcs8/internal.h b/src/crypto/pkcs8/internal.h
new file mode 100644
index 0000000..44ca4f7
--- /dev/null
+++ b/src/crypto/pkcs8/internal.h
@@ -0,0 +1,74 @@
+/* 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 OPENSSL_HEADER_PKCS8_INTERNAL_H
+#define OPENSSL_HEADER_PKCS8_INTERNAL_H
+
+#include <openssl/base.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+#define PKCS5_DEFAULT_ITERATIONS 2048
+#define PKCS5_SALT_LEN 8
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_PKCS8_INTERNAL_H */
diff --git a/src/crypto/pkcs8/p5_pbe.c b/src/crypto/pkcs8/p5_pbe.c
new file mode 100644
index 0000000..f30ae79
--- /dev/null
+++ b/src/crypto/pkcs8/p5_pbe.c
@@ -0,0 +1,150 @@
+/* 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 <string.h>
+
+#include <openssl/asn1t.h>
+#include <openssl/err.h>
+#include <openssl/pkcs8.h>
+#include <openssl/rand.h>
+#include <openssl/x509.h>
+
+#include "internal.h"
+
+
+/* PKCS#5 password based encryption structure */
+
+ASN1_SEQUENCE(PBEPARAM) = {
+ ASN1_SIMPLE(PBEPARAM, salt, ASN1_OCTET_STRING),
+ ASN1_SIMPLE(PBEPARAM, iter, ASN1_INTEGER)
+} ASN1_SEQUENCE_END(PBEPARAM)
+
+IMPLEMENT_ASN1_FUNCTIONS(PBEPARAM)
+
+
+/* Set an algorithm identifier for a PKCS#5 PBE algorithm */
+
+int PKCS5_pbe_set0_algor(X509_ALGOR *algor, int alg, int iter,
+ const unsigned char *salt, int saltlen)
+ {
+ PBEPARAM *pbe=NULL;
+ ASN1_STRING *pbe_str=NULL;
+ unsigned char *sstr;
+
+ pbe = PBEPARAM_new();
+ if (!pbe)
+ {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS5_pbe_set0_algor, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ if(iter <= 0)
+ iter = PKCS5_DEFAULT_ITERATIONS;
+ if (!ASN1_INTEGER_set(pbe->iter, iter))
+ {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS5_pbe_set0_algor, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ if (!saltlen)
+ saltlen = PKCS5_SALT_LEN;
+ if (!ASN1_STRING_set(pbe->salt, NULL, saltlen))
+ {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS5_pbe_set0_algor, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ sstr = ASN1_STRING_data(pbe->salt);
+ if (salt)
+ memcpy(sstr, salt, saltlen);
+ else if (!RAND_bytes(sstr, saltlen))
+ goto err;
+
+ if(!ASN1_item_pack(pbe, ASN1_ITEM_rptr(PBEPARAM), &pbe_str))
+ {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS5_pbe_set0_algor, 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);
+ if (pbe_str != NULL)
+ 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)
+ {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS5_pbe_set, 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/src/crypto/pkcs8/p5_pbev2.c b/src/crypto/pkcs8/p5_pbev2.c
new file mode 100644
index 0000000..9eb9848
--- /dev/null
+++ b/src/crypto/pkcs8/p5_pbev2.c
@@ -0,0 +1,303 @@
+/* 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 <string.h>
+
+#include <openssl/asn1t.h>
+#include <openssl/cipher.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/pkcs8.h>
+#include <openssl/rand.h>
+#include <openssl/x509.h>
+
+#include "internal.h"
+
+
+/* PKCS#5 v2.0 password based encryption structures */
+
+ASN1_SEQUENCE(PBE2PARAM) = {
+ ASN1_SIMPLE(PBE2PARAM, keyfunc, X509_ALGOR),
+ ASN1_SIMPLE(PBE2PARAM, encryption, X509_ALGOR)
+} ASN1_SEQUENCE_END(PBE2PARAM)
+
+IMPLEMENT_ASN1_FUNCTIONS(PBE2PARAM)
+
+ASN1_SEQUENCE(PBKDF2PARAM) = {
+ ASN1_SIMPLE(PBKDF2PARAM, salt, ASN1_ANY),
+ ASN1_SIMPLE(PBKDF2PARAM, iter, ASN1_INTEGER),
+ ASN1_OPT(PBKDF2PARAM, keylength, ASN1_INTEGER),
+ ASN1_OPT(PBKDF2PARAM, prf, X509_ALGOR)
+} ASN1_SEQUENCE_END(PBKDF2PARAM)
+
+IMPLEMENT_ASN1_FUNCTIONS(PBKDF2PARAM);
+
+static int ASN1_TYPE_set_octetstring(ASN1_TYPE *a, unsigned char *data, int len)
+ {
+ ASN1_STRING *os;
+
+ if ((os=M_ASN1_OCTET_STRING_new()) == NULL) return(0);
+ if (!M_ASN1_OCTET_STRING_set(os,data,len))
+ {
+ M_ASN1_OCTET_STRING_free(os);
+ return 0;
+ }
+ ASN1_TYPE_set(a,V_ASN1_OCTET_STRING,os);
+ return(1);
+ }
+
+static int param_to_asn1(EVP_CIPHER_CTX *c, ASN1_TYPE *type)
+ {
+ unsigned iv_len;
+
+ iv_len = EVP_CIPHER_CTX_iv_length(c);
+ return ASN1_TYPE_set_octetstring(type, c->oiv, iv_len);
+ }
+
+/* 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;
+ const ASN1_OBJECT *obj;
+
+ alg_nid = EVP_CIPHER_nid(cipher);
+ if(alg_nid == NID_undef) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS5_pbe2_set_iv, PKCS8_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 = (ASN1_OBJECT*) 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 if (!RAND_bytes(iv, EVP_CIPHER_iv_length(cipher)))
+ goto err;
+ }
+
+ 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(param_to_asn1(&ctx, scheme->parameter) < 0) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS5_pbe2_set_iv, PKCS8_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 = (ASN1_OBJECT*) OBJ_nid2obj(NID_pbes2);
+
+ /* Encode PBE2PARAM into parameter */
+
+ if(!ASN1_item_pack(pbe2, ASN1_ITEM_rptr(PBE2PARAM),
+ &ret->parameter->value.sequence)) goto merr;
+ ret->parameter->type = V_ASN1_SEQUENCE;
+
+ PBE2PARAM_free(pbe2);
+ pbe2 = NULL;
+
+ return ret;
+
+ merr:
+ OPENSSL_PUT_ERROR(PKCS8, PKCS5_pbe2_set_iv, 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 = M_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 = OPENSSL_malloc (saltlen)))
+ goto merr;
+
+ osalt->length = saltlen;
+
+ if (salt)
+ memcpy (osalt->data, salt, saltlen);
+ else if (!RAND_bytes(osalt->data, saltlen))
+ goto merr;
+
+ if(iter <= 0)
+ iter = PKCS5_DEFAULT_ITERATIONS;
+
+ if(!ASN1_INTEGER_set(kdf->iter, iter))
+ goto merr;
+
+ /* If have a key len set it up */
+
+ if(keylen > 0)
+ {
+ if(!(kdf->keylength = M_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 = (ASN1_OBJECT*) OBJ_nid2obj(NID_id_pbkdf2);
+
+ /* Encode PBKDF2PARAM into parameter of pbe2 */
+
+ if(!(keyfunc->parameter = ASN1_TYPE_new()))
+ goto merr;
+
+ if(!ASN1_item_pack(kdf, ASN1_ITEM_rptr(PBKDF2PARAM),
+ &keyfunc->parameter->value.sequence))
+ goto merr;
+ keyfunc->parameter->type = V_ASN1_SEQUENCE;
+
+ PBKDF2PARAM_free(kdf);
+ return keyfunc;
+
+ merr:
+ OPENSSL_PUT_ERROR(PKCS8, PKCS5_pbkdf2_set, ERR_R_MALLOC_FAILURE);
+ PBKDF2PARAM_free(kdf);
+ X509_ALGOR_free(keyfunc);
+ return NULL;
+ }
+
diff --git a/src/crypto/pkcs8/p8_pkey.c b/src/crypto/pkcs8/p8_pkey.c
new file mode 100644
index 0000000..bd9d30c
--- /dev/null
+++ b/src/crypto/pkcs8/p8_pkey.c
@@ -0,0 +1,85 @@
+/* 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 <stdio.h>
+
+#include <openssl/asn1t.h>
+#include <openssl/mem.h>
+#include <openssl/x509.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 &&
+ key->pkey->value.octet_string) {
+ OPENSSL_cleanse(key->pkey->value.octet_string->data,
+ key->pkey->value.octet_string->length);
+ }
+ }
+ return 1;
+}
+
+ASN1_SEQUENCE_cb(PKCS8_PRIV_KEY_INFO, pkey_cb) = {
+ ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, version, ASN1_INTEGER),
+ ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, pkeyalg, X509_ALGOR),
+ ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, pkey, ASN1_ANY),
+ ASN1_IMP_SET_OF_OPT(PKCS8_PRIV_KEY_INFO, attributes, X509_ATTRIBUTE, 0)
+} ASN1_SEQUENCE_END_cb(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO);
+
+IMPLEMENT_ASN1_FUNCTIONS(PKCS8_PRIV_KEY_INFO);
diff --git a/src/crypto/pkcs8/pkcs12_test.c b/src/crypto/pkcs8/pkcs12_test.c
new file mode 100644
index 0000000..2292b77
--- /dev/null
+++ b/src/crypto/pkcs8/pkcs12_test.c
@@ -0,0 +1,763 @@
+/* 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 <stdio.h>
+#include <stdlib.h>
+
+#include <openssl/bio.h>
+#include <openssl/bytestring.h>
+#include <openssl/crypto.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/pkcs8.h>
+#include <openssl/stack.h>
+#include <openssl/x509.h>
+
+
+/* kPKCS12DER contains sample PKCS#12 data generated by OpenSSL with:
+ * openssl pkcs12 -export -inkey key.pem -in cacert.pem */
+static const uint8_t kOpenSSL[] = {
+ 0x30, 0x82, 0x09, 0xa1, 0x02, 0x01, 0x03, 0x30, 0x82, 0x09, 0x67, 0x06,
+ 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82,
+ 0x09, 0x58, 0x04, 0x82, 0x09, 0x54, 0x30, 0x82, 0x09, 0x50, 0x30, 0x82,
+ 0x04, 0x07, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07,
+ 0x06, 0xa0, 0x82, 0x03, 0xf8, 0x30, 0x82, 0x03, 0xf4, 0x02, 0x01, 0x00,
+ 0x30, 0x82, 0x03, 0xed, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x07, 0x01, 0x30, 0x1c, 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x0c, 0x01, 0x06, 0x30, 0x0e, 0x04, 0x08, 0x31, 0x24, 0xca,
+ 0x7d, 0xc3, 0x25, 0x3e, 0xdc, 0x02, 0x02, 0x08, 0x00, 0x80, 0x82, 0x03,
+ 0xc0, 0x55, 0xe7, 0x7f, 0x9c, 0xd6, 0x0c, 0xd2, 0x69, 0x1d, 0x6e, 0x8b,
+ 0xb8, 0x07, 0xec, 0x4a, 0xe7, 0x06, 0x67, 0xd1, 0x24, 0x1b, 0xd5, 0x68,
+ 0x13, 0x3d, 0xd7, 0x56, 0x5e, 0x15, 0x40, 0xdb, 0xda, 0x88, 0x36, 0xc9,
+ 0x02, 0x96, 0xb5, 0xb5, 0xf7, 0x81, 0xef, 0x88, 0x1d, 0x66, 0x62, 0xa8,
+ 0x83, 0xf7, 0x91, 0xb1, 0x26, 0x1f, 0x9b, 0x25, 0x78, 0x0a, 0x04, 0xb1,
+ 0xc0, 0x93, 0x48, 0xa2, 0xf0, 0x51, 0x4f, 0x2b, 0xf8, 0x03, 0x67, 0x61,
+ 0x1b, 0xed, 0x29, 0xfe, 0x3f, 0xdd, 0x83, 0xa3, 0x93, 0x75, 0xa7, 0xd9,
+ 0x37, 0x5b, 0xa7, 0xc9, 0xf4, 0x52, 0x86, 0xd2, 0x3f, 0xca, 0x61, 0x5c,
+ 0x1e, 0xf9, 0x07, 0x7d, 0xbd, 0xda, 0x76, 0x8a, 0x03, 0x8e, 0x12, 0x4e,
+ 0x8f, 0x68, 0x6e, 0x72, 0x6e, 0xf0, 0xbe, 0x22, 0xc7, 0x9d, 0x97, 0x7c,
+ 0x45, 0xc0, 0xaa, 0x31, 0xe1, 0x55, 0x81, 0xb3, 0xec, 0x98, 0x94, 0xac,
+ 0xf7, 0x15, 0x9b, 0x42, 0x49, 0x8c, 0x2a, 0x29, 0x7a, 0x25, 0x92, 0x64,
+ 0x92, 0xbd, 0x4e, 0x5c, 0xec, 0xff, 0x61, 0xbb, 0x8e, 0x5c, 0xc8, 0xdb,
+ 0xba, 0x97, 0x30, 0xf4, 0x55, 0x9e, 0x1b, 0xfa, 0xbe, 0x2a, 0x90, 0xcf,
+ 0xe8, 0xc0, 0x9d, 0xb0, 0x0e, 0x24, 0x61, 0xe7, 0x3a, 0xb7, 0x7f, 0xda,
+ 0x63, 0xaa, 0x2a, 0x4a, 0xa6, 0x91, 0x52, 0xa6, 0x76, 0xc9, 0xbe, 0x9f,
+ 0x1b, 0x1d, 0xa4, 0x09, 0x5b, 0x0f, 0xd1, 0x64, 0x4e, 0xdf, 0x0c, 0x44,
+ 0x59, 0x3a, 0xef, 0x9a, 0xd8, 0x22, 0xa2, 0x5f, 0x80, 0xb5, 0x4f, 0xbe,
+ 0x84, 0x23, 0xe3, 0x74, 0x77, 0x3c, 0x9e, 0x27, 0x64, 0xac, 0x65, 0xf4,
+ 0xbb, 0x34, 0xb7, 0xa4, 0xfe, 0x02, 0x1a, 0x88, 0x05, 0x3b, 0x4b, 0xb8,
+ 0xd8, 0xb9, 0x26, 0x69, 0x22, 0x97, 0x3d, 0x93, 0x9b, 0xe8, 0x72, 0xaa,
+ 0x4d, 0x8f, 0x76, 0x51, 0x12, 0x59, 0x58, 0xf1, 0x1a, 0xa3, 0xdb, 0x5d,
+ 0xbc, 0xea, 0x84, 0x19, 0x55, 0x4f, 0x00, 0xfb, 0xe2, 0x57, 0x47, 0xca,
+ 0xea, 0xbe, 0x8f, 0x85, 0x8b, 0x1c, 0x27, 0x8d, 0x81, 0x70, 0x7f, 0xf1,
+ 0x56, 0x58, 0xe1, 0x26, 0x94, 0xd8, 0x2f, 0xde, 0xac, 0xc8, 0xac, 0xbf,
+ 0xc3, 0xc6, 0x67, 0xa6, 0xf4, 0x6c, 0xec, 0x20, 0x3c, 0xbc, 0x9d, 0xd9,
+ 0xd0, 0xa1, 0x4e, 0x8c, 0x11, 0x19, 0x2b, 0xb3, 0xa1, 0xdf, 0x6a, 0x8f,
+ 0xa2, 0xc3, 0xcc, 0xf6, 0xbd, 0x09, 0x7a, 0x96, 0x61, 0x20, 0xd4, 0x06,
+ 0x99, 0x4c, 0x6f, 0x23, 0x9b, 0x4c, 0xcc, 0x73, 0x8b, 0x42, 0x48, 0x99,
+ 0x45, 0x8f, 0xcb, 0xc8, 0x46, 0x1a, 0xfb, 0x51, 0x03, 0x6a, 0xf2, 0x22,
+ 0x85, 0x88, 0x9d, 0x61, 0x8b, 0x16, 0x33, 0xf4, 0xf7, 0x9b, 0xc8, 0x21,
+ 0x4f, 0xb1, 0xcd, 0x30, 0xfc, 0x29, 0x88, 0x12, 0xdc, 0xd4, 0x30, 0x4c,
+ 0xb9, 0xad, 0x34, 0xde, 0x01, 0xf8, 0xc1, 0x12, 0xa7, 0x4d, 0xc7, 0x31,
+ 0x99, 0x2b, 0x45, 0x88, 0x06, 0x34, 0x69, 0x6e, 0x6d, 0x34, 0xd8, 0xdd,
+ 0x0a, 0x3d, 0x59, 0x74, 0x36, 0x31, 0x6a, 0xed, 0x91, 0x3b, 0x5b, 0x88,
+ 0x43, 0x46, 0x3f, 0x67, 0x66, 0xe4, 0xde, 0x52, 0xb4, 0xbf, 0x7b, 0x3d,
+ 0x54, 0x79, 0xaf, 0x8d, 0xf5, 0x0a, 0x80, 0xfd, 0xeb, 0x31, 0x24, 0xbc,
+ 0x24, 0xd7, 0x21, 0x9f, 0x87, 0xab, 0xbd, 0x75, 0x2c, 0x13, 0x13, 0x96,
+ 0xab, 0x76, 0xfb, 0xb2, 0x44, 0xd0, 0xd2, 0x19, 0xf1, 0x95, 0x9a, 0x91,
+ 0xbf, 0x7a, 0x7b, 0x76, 0x95, 0x72, 0xa9, 0x16, 0xfc, 0x3e, 0xa9, 0x4e,
+ 0x01, 0x15, 0x3d, 0x43, 0x73, 0xa3, 0x8b, 0xef, 0x48, 0xad, 0x11, 0xbd,
+ 0x53, 0xd3, 0x0c, 0x15, 0x15, 0x1a, 0xb4, 0x3a, 0xe0, 0x7f, 0x9a, 0xa1,
+ 0x36, 0x47, 0x72, 0x92, 0xf0, 0xdf, 0xb0, 0xe2, 0xbc, 0x35, 0xd4, 0x32,
+ 0x6b, 0x37, 0x69, 0x4f, 0x47, 0x9a, 0xe2, 0x35, 0x8a, 0x31, 0x60, 0xed,
+ 0x80, 0x57, 0xe2, 0x9d, 0x58, 0x9c, 0x7f, 0x46, 0xd2, 0x54, 0x0e, 0x28,
+ 0x53, 0x8b, 0x1f, 0x46, 0x34, 0x22, 0xac, 0x71, 0xc7, 0xca, 0x0f, 0xb4,
+ 0xb7, 0x7a, 0xfc, 0x34, 0x57, 0xa5, 0x86, 0x8d, 0x66, 0x5c, 0xc7, 0x3a,
+ 0xdb, 0xf8, 0x79, 0x3a, 0x8a, 0xf6, 0xa2, 0x1e, 0x09, 0xc9, 0x10, 0xe9,
+ 0x93, 0x3a, 0xc5, 0xed, 0xb2, 0xca, 0xbb, 0x66, 0xf1, 0x9d, 0xc9, 0x9c,
+ 0x42, 0x75, 0x64, 0x3e, 0xe4, 0x12, 0x2b, 0x67, 0xf8, 0xbf, 0x2b, 0x98,
+ 0x5d, 0xb6, 0xa0, 0xba, 0x79, 0x98, 0xe0, 0x47, 0x5c, 0x77, 0x85, 0x4e,
+ 0x26, 0x71, 0xfe, 0xab, 0x5c, 0xa8, 0x32, 0x93, 0xec, 0xd0, 0x26, 0x90,
+ 0xe4, 0xda, 0x2f, 0x34, 0x8a, 0x50, 0xb8, 0x3b, 0x7b, 0x4c, 0x5f, 0xa9,
+ 0x3e, 0x8a, 0xa8, 0xf3, 0xc0, 0xb7, 0x50, 0x0b, 0x77, 0x4e, 0x8c, 0xa0,
+ 0xaf, 0xdb, 0x59, 0xe7, 0xac, 0xd1, 0x34, 0x4e, 0x62, 0x47, 0x2e, 0x1e,
+ 0x5e, 0xb4, 0xc9, 0x64, 0xf8, 0x0f, 0xf4, 0xf8, 0xb6, 0x9a, 0xe3, 0x7e,
+ 0xcf, 0xb7, 0xee, 0x11, 0x14, 0x52, 0x89, 0x3b, 0x27, 0x98, 0xfc, 0x95,
+ 0xa7, 0xad, 0xbf, 0x61, 0x34, 0xad, 0x1a, 0x24, 0x2a, 0x48, 0x66, 0x65,
+ 0x75, 0x9c, 0x59, 0xc0, 0x4f, 0x5f, 0x3d, 0x5a, 0x8c, 0xee, 0xd0, 0xb1,
+ 0x17, 0x6d, 0x34, 0x46, 0x37, 0xa0, 0xba, 0x71, 0xac, 0x77, 0x73, 0x29,
+ 0xa3, 0x37, 0x4f, 0x02, 0xd3, 0x7f, 0x0e, 0xe8, 0xce, 0xff, 0x80, 0x11,
+ 0x45, 0x42, 0x03, 0x5a, 0x87, 0xaa, 0xff, 0x25, 0x12, 0x1f, 0x43, 0x19,
+ 0x3e, 0xa9, 0x62, 0x96, 0x0c, 0x6f, 0x33, 0x88, 0x5c, 0xaa, 0xf9, 0xe2,
+ 0xb4, 0xb9, 0xf7, 0x55, 0xae, 0xb5, 0x76, 0x57, 0x47, 0x83, 0xe3, 0xfa,
+ 0x05, 0xda, 0x86, 0x02, 0x97, 0xb4, 0x60, 0xae, 0x59, 0xd5, 0x6c, 0xc1,
+ 0x33, 0xe1, 0x36, 0x36, 0x94, 0x79, 0x9e, 0xad, 0xa3, 0x2d, 0xbc, 0xb5,
+ 0xa2, 0xeb, 0xdd, 0xcd, 0xcb, 0x48, 0x42, 0x15, 0xb8, 0xe6, 0x0e, 0x76,
+ 0x5b, 0x57, 0x74, 0x24, 0xe6, 0x89, 0xc4, 0xe8, 0x08, 0xa9, 0xfe, 0xb3,
+ 0x23, 0xa6, 0xca, 0x72, 0xe2, 0xe4, 0xcb, 0xc1, 0x4a, 0xd1, 0x1d, 0xb9,
+ 0x5e, 0x36, 0x97, 0x19, 0x7c, 0x15, 0x48, 0xf1, 0x2d, 0xeb, 0xec, 0xad,
+ 0x52, 0x6f, 0x2f, 0xe1, 0x19, 0xcf, 0xcf, 0x98, 0x13, 0x0d, 0xcc, 0xb2,
+ 0xa6, 0x8a, 0xda, 0x93, 0x24, 0x3d, 0x5d, 0x83, 0xfe, 0x8d, 0x9e, 0x47,
+ 0xd8, 0x6e, 0x8d, 0x06, 0x52, 0x7d, 0x46, 0x84, 0x04, 0x69, 0x34, 0x61,
+ 0x04, 0x50, 0x1f, 0x86, 0x92, 0x94, 0xe9, 0x0b, 0x13, 0x5b, 0xf6, 0x16,
+ 0x81, 0xeb, 0xfa, 0xf1, 0xbb, 0x04, 0x68, 0x17, 0xca, 0x35, 0x6f, 0xba,
+ 0x4e, 0x4c, 0x33, 0xce, 0xf4, 0x26, 0xb7, 0x74, 0xab, 0xa5, 0xd0, 0xaa,
+ 0x0d, 0x85, 0x11, 0x30, 0x58, 0x62, 0xdf, 0x48, 0xc7, 0xdf, 0xc9, 0x38,
+ 0x9e, 0x6f, 0x96, 0x23, 0x2f, 0xc1, 0xd4, 0x8d, 0x65, 0x9b, 0x46, 0x5f,
+ 0x9c, 0xea, 0x26, 0x60, 0xb5, 0x95, 0x85, 0x71, 0x18, 0xc3, 0xf4, 0x54,
+ 0x61, 0xca, 0xfe, 0x55, 0x3b, 0xbe, 0x81, 0xaf, 0xd9, 0x3a, 0x27, 0xe9,
+ 0x1c, 0x30, 0x82, 0x05, 0x41, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82, 0x05, 0x32, 0x04, 0x82, 0x05, 0x2e,
+ 0x30, 0x82, 0x05, 0x2a, 0x30, 0x82, 0x05, 0x26, 0x06, 0x0b, 0x2a, 0x86,
+ 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x0a, 0x01, 0x02, 0xa0, 0x82, 0x04,
+ 0xee, 0x30, 0x82, 0x04, 0xea, 0x30, 0x1c, 0x06, 0x0a, 0x2a, 0x86, 0x48,
+ 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x01, 0x03, 0x30, 0x0e, 0x04, 0x08, 0xd9,
+ 0x68, 0xcb, 0x08, 0x16, 0xc8, 0x93, 0x57, 0x02, 0x02, 0x08, 0x00, 0x04,
+ 0x82, 0x04, 0xc8, 0x7c, 0xdb, 0xa6, 0x1e, 0x33, 0xa4, 0xc6, 0x4e, 0x13,
+ 0x22, 0x7a, 0x1f, 0xc6, 0x82, 0xab, 0x93, 0x5f, 0xf0, 0xa4, 0xe4, 0x40,
+ 0xac, 0xdf, 0x16, 0xec, 0x8d, 0x1f, 0xd9, 0xe4, 0x03, 0xd6, 0xc9, 0xc4,
+ 0x1d, 0xfd, 0xa3, 0xe3, 0xba, 0xfc, 0xcb, 0xd0, 0x47, 0x65, 0x0c, 0x6e,
+ 0x5d, 0xfc, 0xd2, 0xd4, 0x63, 0xa7, 0x93, 0xf6, 0x8a, 0x44, 0x8c, 0xfe,
+ 0x84, 0xd8, 0x0d, 0xa6, 0x16, 0x22, 0xe1, 0x65, 0x10, 0x5e, 0x18, 0x44,
+ 0x58, 0x2f, 0xc7, 0x64, 0x74, 0x5f, 0xcf, 0x73, 0x34, 0xe1, 0x4b, 0xe4,
+ 0xb3, 0x5b, 0xdb, 0x81, 0x4b, 0x1c, 0x38, 0x72, 0xa6, 0xc5, 0xeb, 0x56,
+ 0x9b, 0xc7, 0xe3, 0x3d, 0x54, 0x6e, 0x05, 0x2c, 0xd3, 0x57, 0xc9, 0x4f,
+ 0x80, 0x1e, 0xd7, 0xd8, 0x26, 0x6a, 0xcb, 0x79, 0x46, 0x70, 0xfc, 0x45,
+ 0xa7, 0x79, 0xab, 0x01, 0x03, 0xb6, 0xb1, 0x44, 0x41, 0xd9, 0x73, 0x37,
+ 0xaa, 0xd7, 0xf9, 0x44, 0x93, 0xaf, 0xbb, 0xb5, 0x77, 0xeb, 0x2b, 0x20,
+ 0x2e, 0xbd, 0xea, 0x2f, 0xde, 0xa6, 0x2f, 0xd6, 0xac, 0x74, 0xa5, 0x34,
+ 0xfb, 0xdf, 0xf7, 0x02, 0xa2, 0x20, 0x15, 0xc8, 0x61, 0x72, 0xbb, 0x7f,
+ 0x04, 0xf6, 0x0f, 0xf8, 0x7e, 0xc3, 0xe6, 0xab, 0x2a, 0xe6, 0xd8, 0xe1,
+ 0x0d, 0x5a, 0x3c, 0xc0, 0x58, 0xae, 0xf8, 0x1b, 0x15, 0x3c, 0x7b, 0x7f,
+ 0xf5, 0x9f, 0xec, 0xf7, 0x3f, 0x30, 0x4f, 0x3d, 0x6c, 0x44, 0xdd, 0x0e,
+ 0x4c, 0x2c, 0x93, 0x68, 0x43, 0x31, 0xa8, 0x97, 0x4b, 0xf6, 0x66, 0x71,
+ 0x2a, 0x52, 0x3e, 0x3a, 0xe6, 0x72, 0x8a, 0xe6, 0xe3, 0xc8, 0xff, 0x65,
+ 0x68, 0x1a, 0x46, 0x21, 0xb3, 0xf0, 0x46, 0x7c, 0x0c, 0x65, 0xd1, 0x8e,
+ 0xa4, 0x91, 0x11, 0x5c, 0x93, 0xeb, 0xeb, 0xae, 0x46, 0xf4, 0xbb, 0xf8,
+ 0xf3, 0x7e, 0x20, 0x30, 0xf8, 0xcd, 0x19, 0xcd, 0x54, 0x0a, 0x7f, 0x4f,
+ 0xe8, 0xac, 0xa9, 0xac, 0x72, 0x96, 0x80, 0x45, 0x2a, 0x4a, 0x63, 0x90,
+ 0x01, 0x19, 0xd0, 0x7e, 0x26, 0x53, 0x2d, 0xc4, 0x20, 0xa5, 0x1f, 0x89,
+ 0x67, 0x0f, 0xd9, 0x75, 0x51, 0x0a, 0xf1, 0xd4, 0xfd, 0x2e, 0xbe, 0xe6,
+ 0x94, 0x3b, 0x6c, 0x8c, 0xe3, 0x0f, 0x5f, 0xce, 0x58, 0x48, 0xde, 0x8d,
+ 0xeb, 0xd3, 0xe1, 0x0a, 0xcd, 0xdf, 0x34, 0x4d, 0xd1, 0x5b, 0xab, 0x41,
+ 0x41, 0x6b, 0xeb, 0xa1, 0x2f, 0x01, 0x4a, 0x72, 0x2e, 0xf4, 0x5e, 0x44,
+ 0x76, 0xc7, 0xe6, 0x16, 0xb9, 0xfb, 0x10, 0x37, 0x00, 0x2d, 0xc6, 0x3b,
+ 0x17, 0x72, 0x21, 0xdb, 0xac, 0x86, 0x7b, 0xf5, 0x70, 0x3f, 0x73, 0xa3,
+ 0xce, 0x0e, 0x20, 0xbb, 0x59, 0x4c, 0x23, 0xc2, 0xe8, 0x22, 0x22, 0xe0,
+ 0x02, 0x0d, 0xe4, 0xa2, 0x3f, 0x55, 0x9d, 0xc0, 0xeb, 0x9a, 0xc4, 0xf3,
+ 0xaa, 0xb8, 0xf1, 0x73, 0xec, 0x47, 0xe8, 0x2d, 0x6b, 0xa1, 0x40, 0x94,
+ 0xf6, 0x07, 0xb9, 0x6f, 0x03, 0x5a, 0x78, 0xe5, 0x59, 0x41, 0x1a, 0xc7,
+ 0xcd, 0x43, 0x10, 0x20, 0x28, 0x95, 0xe0, 0x2a, 0x6f, 0xf2, 0xf8, 0x12,
+ 0xd6, 0x13, 0x7f, 0x37, 0x3d, 0x38, 0xa7, 0x22, 0x91, 0xc6, 0xe3, 0x52,
+ 0xde, 0xd8, 0xbf, 0x78, 0x9a, 0xa4, 0xf7, 0xc0, 0x8c, 0xbf, 0x81, 0x28,
+ 0x20, 0xb8, 0x01, 0xde, 0xb5, 0x6b, 0x0a, 0x56, 0x12, 0x5c, 0x62, 0x1d,
+ 0xaf, 0xb7, 0xf2, 0x74, 0x66, 0x0a, 0x7a, 0xc4, 0x9f, 0x1e, 0xc2, 0xa8,
+ 0x4c, 0xd6, 0x76, 0x6d, 0x74, 0x35, 0x37, 0x12, 0x5c, 0x95, 0xee, 0x98,
+ 0x1d, 0xe2, 0x91, 0xde, 0x13, 0x08, 0xd0, 0x59, 0x4d, 0x62, 0x92, 0x69,
+ 0x1b, 0xf7, 0x21, 0x45, 0xaf, 0x83, 0xf8, 0x64, 0xf0, 0xfb, 0x92, 0x9d,
+ 0xa1, 0xd9, 0x61, 0x5e, 0x00, 0xc8, 0x1a, 0x6e, 0x6a, 0x2d, 0xad, 0xa8,
+ 0x1b, 0x0e, 0xaf, 0xea, 0xb2, 0xae, 0x1c, 0x89, 0xc7, 0x4d, 0x2c, 0x0f,
+ 0x4d, 0x8d, 0x78, 0x8d, 0x15, 0x9d, 0x4c, 0x90, 0x52, 0xa1, 0xa9, 0xd8,
+ 0xb2, 0x66, 0xb9, 0xb1, 0x46, 0x0a, 0x69, 0x86, 0x2b, 0x0f, 0xb2, 0x41,
+ 0xce, 0xe8, 0x8e, 0x49, 0x97, 0x08, 0x0b, 0x70, 0x97, 0xcb, 0xa4, 0x33,
+ 0x3f, 0x83, 0x6b, 0x6c, 0x17, 0xce, 0xd8, 0xd5, 0x9b, 0xd4, 0x55, 0x9b,
+ 0x99, 0xe1, 0xba, 0x61, 0x31, 0x36, 0x79, 0x31, 0x5f, 0xa1, 0x8c, 0xa9,
+ 0x77, 0x42, 0xaa, 0x8c, 0x45, 0x6e, 0xb6, 0x90, 0x08, 0xe8, 0x2e, 0xc4,
+ 0x72, 0x69, 0x42, 0xca, 0xa2, 0xd4, 0x8a, 0x2c, 0x37, 0xe1, 0xde, 0xb8,
+ 0x98, 0x36, 0xeb, 0xcc, 0x58, 0x0c, 0x24, 0xad, 0xab, 0x62, 0x44, 0x6d,
+ 0x80, 0xd5, 0xce, 0x2e, 0x4a, 0x3e, 0xa5, 0xc5, 0x34, 0xf8, 0x32, 0x26,
+ 0x2a, 0x56, 0xa4, 0xdd, 0xe9, 0x92, 0x06, 0xad, 0xe8, 0x85, 0x77, 0x6b,
+ 0xf1, 0x1b, 0xeb, 0xac, 0x77, 0x19, 0x1c, 0x6a, 0xb7, 0xef, 0x28, 0x70,
+ 0x87, 0x92, 0x33, 0xdd, 0xaa, 0x30, 0xc1, 0xa0, 0x93, 0x64, 0x18, 0xa2,
+ 0x91, 0x7f, 0xf7, 0xc4, 0xa5, 0x16, 0x93, 0xb3, 0x5b, 0xd8, 0x53, 0x28,
+ 0xc5, 0x5e, 0xb1, 0xce, 0x97, 0xbc, 0xb6, 0x65, 0xa8, 0x53, 0xcd, 0xf4,
+ 0x4d, 0x6b, 0xea, 0x6f, 0x6f, 0xa5, 0x1c, 0xf1, 0x0f, 0xcb, 0x04, 0x25,
+ 0x4a, 0xfe, 0x7d, 0xfc, 0xa3, 0xbd, 0x41, 0xd3, 0x96, 0x6a, 0x8b, 0xad,
+ 0xd4, 0xaa, 0x0a, 0x76, 0xea, 0x3b, 0xab, 0x39, 0x55, 0xa3, 0x89, 0x9f,
+ 0xf6, 0xf5, 0x9b, 0x9c, 0x83, 0xf8, 0x28, 0x50, 0xdf, 0x31, 0x74, 0x83,
+ 0xdb, 0xf1, 0x0f, 0x4c, 0x35, 0x6a, 0xe5, 0x64, 0x2e, 0xb9, 0x77, 0x3d,
+ 0xdd, 0xff, 0xa3, 0xa7, 0x90, 0x79, 0xc6, 0x5b, 0x01, 0x16, 0x38, 0xa8,
+ 0x22, 0xa3, 0x14, 0x13, 0xed, 0xd0, 0x89, 0x0d, 0x1f, 0x3a, 0x41, 0x4c,
+ 0x57, 0x79, 0xfc, 0x1d, 0xdf, 0xad, 0x1a, 0x11, 0x15, 0x31, 0x7e, 0xdb,
+ 0x99, 0x3a, 0x6c, 0xde, 0x94, 0x9a, 0x45, 0x4c, 0xfb, 0xa5, 0xa5, 0x31,
+ 0xee, 0xe3, 0x09, 0x13, 0x6d, 0xfd, 0x19, 0x37, 0x3f, 0xf6, 0xed, 0x8f,
+ 0x0c, 0xce, 0x4b, 0xd1, 0xe1, 0x3d, 0xfb, 0x85, 0x00, 0x84, 0x19, 0xeb,
+ 0xa2, 0x63, 0x1d, 0x2b, 0x2d, 0x21, 0xee, 0x08, 0x5a, 0x6d, 0xb0, 0xb1,
+ 0xd6, 0x81, 0x00, 0xb6, 0xd0, 0x09, 0x90, 0xb4, 0x84, 0x17, 0xd9, 0x2a,
+ 0x3c, 0x1d, 0x53, 0xc6, 0xc1, 0x8b, 0xda, 0xae, 0x0c, 0x0a, 0x3e, 0x1c,
+ 0x8a, 0xc4, 0xd6, 0x97, 0x5d, 0x48, 0xe7, 0x79, 0x80, 0x78, 0xaa, 0xde,
+ 0x17, 0x60, 0x5d, 0x28, 0x15, 0x3a, 0x42, 0xb7, 0x85, 0xc8, 0x60, 0x93,
+ 0x28, 0xb0, 0x4e, 0xc9, 0xf7, 0x46, 0xe7, 0xfc, 0x4e, 0x9f, 0x9f, 0x12,
+ 0xdf, 0xcb, 0x6e, 0x0c, 0xaf, 0x71, 0xda, 0xb7, 0xec, 0x3d, 0x46, 0xf3,
+ 0x35, 0x41, 0x42, 0xd8, 0x27, 0x92, 0x99, 0x1c, 0x4d, 0xc9, 0x3c, 0xe9,
+ 0x0e, 0xcb, 0x3f, 0x57, 0x65, 0x77, 0x0d, 0xdd, 0xff, 0xea, 0x70, 0x35,
+ 0xcc, 0xf5, 0x38, 0x1b, 0x57, 0xdf, 0x6d, 0xcb, 0xfd, 0x13, 0x39, 0xd6,
+ 0x04, 0xe2, 0xf1, 0xc2, 0xd9, 0xea, 0x8c, 0x9f, 0xfb, 0xb5, 0xfc, 0xe6,
+ 0xa9, 0xaa, 0x0f, 0x43, 0xc9, 0x9c, 0x91, 0xe4, 0x21, 0xaf, 0x37, 0x14,
+ 0x78, 0x46, 0xe1, 0x29, 0x41, 0x0c, 0x4e, 0xf5, 0x93, 0x1d, 0xf8, 0x33,
+ 0x47, 0x6f, 0x9d, 0x8b, 0xf3, 0x27, 0xd4, 0xbb, 0xf6, 0xae, 0xfa, 0xa5,
+ 0x8b, 0x41, 0x8f, 0xb4, 0xd7, 0x2f, 0xc1, 0x27, 0xea, 0x70, 0x55, 0x1d,
+ 0xe2, 0xd8, 0x0c, 0x4a, 0x5e, 0x7c, 0x87, 0xa4, 0x0e, 0x84, 0x07, 0xd3,
+ 0x38, 0x67, 0x2c, 0x55, 0x11, 0xfd, 0x1e, 0xda, 0x4d, 0x66, 0x01, 0x12,
+ 0x0c, 0x1b, 0x7c, 0x7c, 0x5c, 0x82, 0x21, 0x35, 0x65, 0x5c, 0x7a, 0xd2,
+ 0x66, 0xc2, 0x2b, 0x5e, 0xb8, 0xb1, 0xcb, 0xdf, 0x59, 0xc9, 0x31, 0xb7,
+ 0x17, 0x26, 0x96, 0x5e, 0x6f, 0x1c, 0x62, 0x3d, 0x8d, 0x88, 0xf1, 0xd1,
+ 0x01, 0x3e, 0xf9, 0x6f, 0xb9, 0x77, 0xdc, 0xee, 0xee, 0x78, 0x59, 0xef,
+ 0xcf, 0x3a, 0x87, 0x88, 0xa2, 0xea, 0xfd, 0x0a, 0xa9, 0xa9, 0x3e, 0x0c,
+ 0xf8, 0x7f, 0x97, 0x32, 0x17, 0xc2, 0x97, 0xcb, 0xa4, 0x9b, 0xae, 0x5d,
+ 0xe7, 0x39, 0x2b, 0x2b, 0xa8, 0xe6, 0x7b, 0x51, 0x75, 0x1f, 0x53, 0x54,
+ 0x37, 0xf4, 0x00, 0xa4, 0xb0, 0xa0, 0x93, 0xb4, 0x33, 0xe7, 0xae, 0x28,
+ 0xc0, 0x2d, 0x3a, 0xb3, 0xaa, 0xd7, 0x3c, 0x76, 0x44, 0x4b, 0xbb, 0x6a,
+ 0x67, 0x98, 0xce, 0xf8, 0x15, 0x13, 0x67, 0x79, 0x3c, 0x15, 0x09, 0xb7,
+ 0x22, 0xc0, 0xec, 0x07, 0x8a, 0xfd, 0x44, 0xcb, 0x99, 0xbd, 0xdc, 0xd5,
+ 0x53, 0x4c, 0x97, 0x1b, 0x46, 0xaf, 0xc0, 0x6c, 0x06, 0x01, 0x93, 0x8a,
+ 0x50, 0x51, 0x6a, 0xe4, 0x5c, 0x0a, 0x52, 0x81, 0x3b, 0x75, 0xed, 0xa2,
+ 0x97, 0xa6, 0x5c, 0x55, 0x63, 0xee, 0xfb, 0x33, 0x82, 0x10, 0xa8, 0x21,
+ 0x1a, 0x8d, 0xc8, 0xe1, 0x52, 0x68, 0x38, 0x88, 0x2f, 0xae, 0x2b, 0x22,
+ 0x7a, 0x9b, 0x0c, 0x19, 0x73, 0x6f, 0x91, 0xc7, 0xfa, 0x95, 0x61, 0x28,
+ 0x74, 0x73, 0x70, 0x31, 0x25, 0x30, 0x23, 0x06, 0x09, 0x2a, 0x86, 0x48,
+ 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x15, 0x31, 0x16, 0x04, 0x14, 0x14, 0x74,
+ 0x2d, 0x52, 0x8e, 0x0d, 0x0c, 0x06, 0x6c, 0x32, 0x64, 0xd3, 0x7e, 0x33,
+ 0x31, 0x68, 0x8b, 0x28, 0x1a, 0x75, 0x30, 0x31, 0x30, 0x21, 0x30, 0x09,
+ 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14, 0x22,
+ 0x8e, 0xff, 0x5a, 0x78, 0xec, 0x2c, 0x21, 0xa2, 0x48, 0xb7, 0x63, 0x88,
+ 0x10, 0x47, 0x1c, 0xc0, 0xd3, 0xec, 0x5a, 0x04, 0x08, 0xb3, 0x2e, 0x21,
+ 0xfd, 0x82, 0x14, 0xd8, 0x5c, 0x02, 0x02, 0x08, 0x00,
+};
+
+/* kNSS is the result of importing the OpenSSL example PKCS#12 into Chrome and
+ * then exporting it again. */
+static const uint8_t kNSS[] = {
+ 0x30, 0x80, 0x02, 0x01, 0x03, 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48,
+ 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x80, 0x24, 0x80, 0x04, 0x82,
+ 0x09, 0xef, 0x30, 0x80, 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x80, 0x24, 0x80, 0x04, 0x82, 0x05,
+ 0x77, 0x30, 0x82, 0x05, 0x73, 0x30, 0x82, 0x05, 0x6f, 0x06, 0x0b, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x0a, 0x01, 0x02, 0xa0, 0x82,
+ 0x04, 0xf6, 0x30, 0x82, 0x04, 0xf2, 0x30, 0x24, 0x06, 0x0a, 0x2a, 0x86,
+ 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x01, 0x03, 0x30, 0x16, 0x04, 0x10,
+ 0xac, 0x71, 0x8a, 0x7c, 0x89, 0xcf, 0xa8, 0xb0, 0xd6, 0xd1, 0x07, 0xf0,
+ 0x83, 0x4f, 0x7a, 0xd0, 0x02, 0x02, 0x07, 0xd0, 0x04, 0x82, 0x04, 0xc8,
+ 0xea, 0x51, 0x2c, 0x61, 0xaa, 0x9d, 0xf3, 0x90, 0xe1, 0x38, 0x45, 0xb0,
+ 0x5f, 0xfd, 0xe2, 0x04, 0x65, 0xe6, 0xff, 0x87, 0xb6, 0x78, 0x69, 0xb0,
+ 0xcb, 0x14, 0xe9, 0x99, 0x39, 0xe3, 0xe5, 0x70, 0x84, 0x57, 0x68, 0xf7,
+ 0x28, 0xb9, 0x75, 0xa6, 0xfb, 0x16, 0x72, 0xe1, 0x34, 0xb8, 0x3b, 0x61,
+ 0x51, 0x89, 0x18, 0x94, 0x40, 0xef, 0x73, 0xda, 0xdb, 0xd7, 0xb7, 0x44,
+ 0x73, 0x8f, 0x16, 0x84, 0xa2, 0x99, 0xa6, 0x05, 0x5e, 0x74, 0xae, 0xe2,
+ 0xcf, 0x3e, 0x99, 0xca, 0xcd, 0x76, 0x36, 0x77, 0x59, 0xec, 0x25, 0x59,
+ 0x3d, 0x4b, 0x45, 0xa5, 0x4e, 0x7b, 0x7a, 0xc9, 0x8b, 0xde, 0x4f, 0x70,
+ 0x6d, 0xb1, 0xa8, 0xf3, 0xb6, 0xb5, 0xe7, 0x67, 0x3f, 0xe9, 0x64, 0xb8,
+ 0x49, 0xf4, 0x11, 0x94, 0x9d, 0x1c, 0xb0, 0xa5, 0xfb, 0xb3, 0x61, 0xd4,
+ 0xf3, 0xa7, 0x68, 0x66, 0xd7, 0xa4, 0xf0, 0xcd, 0xc8, 0x40, 0x4f, 0x3e,
+ 0xa7, 0x26, 0x40, 0x76, 0x64, 0xa1, 0x4e, 0xf1, 0x91, 0xc2, 0xa3, 0xef,
+ 0xbc, 0xcd, 0x42, 0xe5, 0xd2, 0x6f, 0xff, 0xfe, 0x4d, 0x33, 0x01, 0xb4,
+ 0x99, 0x63, 0x1b, 0xd3, 0x01, 0x55, 0x00, 0xa6, 0x23, 0x9b, 0xa9, 0x17,
+ 0x09, 0x38, 0x32, 0x18, 0x36, 0xbc, 0x20, 0x02, 0xfe, 0x7b, 0xec, 0xd3,
+ 0x4c, 0x7d, 0xc9, 0xc9, 0xce, 0x66, 0x3b, 0x34, 0x6e, 0xea, 0xf9, 0xb1,
+ 0x1a, 0x83, 0xa3, 0x3c, 0x8d, 0xc7, 0x79, 0xc9, 0xff, 0x6b, 0x1d, 0x35,
+ 0xf6, 0x2a, 0x3d, 0x3b, 0x83, 0x16, 0x64, 0xcf, 0x9f, 0x7c, 0x31, 0x02,
+ 0xda, 0x37, 0x1a, 0x16, 0x49, 0xdc, 0xd9, 0x70, 0xae, 0x99, 0x2c, 0xc7,
+ 0x01, 0xba, 0x42, 0xab, 0xe9, 0x4d, 0xa4, 0x78, 0x2c, 0xbd, 0xa0, 0xf1,
+ 0xb7, 0xcf, 0xdd, 0xc1, 0xdb, 0x8f, 0x04, 0x87, 0x0b, 0x47, 0x4f, 0xd5,
+ 0xd5, 0xe7, 0xfc, 0x6e, 0x42, 0xd5, 0x91, 0x4d, 0x7b, 0x1b, 0x5c, 0x3c,
+ 0x02, 0x70, 0xdb, 0x05, 0x91, 0xaf, 0x35, 0x43, 0x05, 0xc2, 0x6d, 0xcf,
+ 0x59, 0x23, 0xfc, 0xc4, 0xf6, 0x67, 0xf1, 0x84, 0x61, 0x4a, 0xb6, 0x4c,
+ 0x15, 0x15, 0xa3, 0xea, 0x8f, 0x13, 0x15, 0xe3, 0xd2, 0xb5, 0x50, 0xc8,
+ 0xae, 0xc8, 0x5c, 0x03, 0xb5, 0x63, 0x93, 0xaa, 0x10, 0xd7, 0x56, 0x0d,
+ 0x6e, 0x13, 0x45, 0x8f, 0xec, 0x17, 0x5c, 0x5c, 0x73, 0x91, 0x5f, 0x6c,
+ 0xaf, 0x11, 0x13, 0x32, 0x5e, 0x14, 0xf9, 0xaf, 0xaf, 0x43, 0x04, 0x60,
+ 0x93, 0x42, 0x30, 0xa6, 0x75, 0xc0, 0x83, 0xd2, 0x4c, 0xa5, 0x0a, 0x16,
+ 0x39, 0xef, 0x3f, 0xf7, 0x9d, 0x23, 0x19, 0xb9, 0xcd, 0xd8, 0x7c, 0x6e,
+ 0xee, 0x6d, 0x2e, 0xff, 0x5a, 0xf3, 0xb9, 0xab, 0xe5, 0x64, 0xdc, 0xc2,
+ 0x67, 0x30, 0x73, 0x19, 0x2d, 0xea, 0xd2, 0x19, 0x1f, 0x1f, 0xe0, 0xd9,
+ 0xac, 0xc9, 0xdb, 0x38, 0x74, 0x5e, 0x31, 0x47, 0x2e, 0x9e, 0x2b, 0xcc,
+ 0xb9, 0xe4, 0x29, 0xf8, 0xb2, 0xbf, 0x1b, 0xbc, 0x68, 0x96, 0x79, 0xcf,
+ 0xaf, 0xf2, 0x1f, 0x57, 0x3f, 0x74, 0xc4, 0x71, 0x63, 0xb4, 0xe8, 0xbe,
+ 0x58, 0xdb, 0x28, 0x62, 0xb5, 0x79, 0x8b, 0xe4, 0xd0, 0x96, 0xd0, 0xda,
+ 0x0f, 0xd2, 0x70, 0x93, 0x2f, 0x71, 0xe0, 0x9f, 0x28, 0xb7, 0x52, 0x38,
+ 0x9c, 0xcb, 0x8b, 0x2a, 0x8e, 0xbf, 0x0e, 0x3d, 0x60, 0x05, 0x0a, 0x91,
+ 0x5b, 0xb5, 0x78, 0x10, 0x31, 0x00, 0x80, 0x31, 0x2d, 0xd7, 0xb0, 0x88,
+ 0xc7, 0xd9, 0x58, 0xc6, 0xfc, 0x3b, 0xf4, 0xee, 0xec, 0xba, 0x05, 0xae,
+ 0xae, 0xff, 0xcf, 0xd0, 0x71, 0xc6, 0xe7, 0xf3, 0x8b, 0x64, 0x50, 0x7a,
+ 0x09, 0x93, 0x0f, 0x34, 0x59, 0x2d, 0xde, 0x4b, 0x1d, 0x86, 0x49, 0xff,
+ 0x63, 0x76, 0x28, 0x6b, 0x52, 0x1b, 0x46, 0x06, 0x18, 0x90, 0x1c, 0x2d,
+ 0xc5, 0x03, 0xcc, 0x00, 0x4d, 0xb7, 0xb2, 0x12, 0xc5, 0xf9, 0xb4, 0xa4,
+ 0x6a, 0x36, 0x62, 0x46, 0x34, 0x2a, 0xf0, 0x11, 0xa3, 0xd6, 0x80, 0x21,
+ 0xbf, 0x3b, 0xfd, 0xc5, 0x25, 0xa0, 0x4d, 0xc0, 0x2e, 0xc0, 0xf1, 0x7b,
+ 0x96, 0x11, 0x64, 0x8e, 0xb9, 0xdb, 0x89, 0x4e, 0x33, 0x89, 0xf5, 0xc6,
+ 0xfc, 0x2b, 0x99, 0xf5, 0xc2, 0x04, 0x83, 0x15, 0x47, 0xa8, 0xa5, 0xc1,
+ 0x4a, 0xe4, 0x76, 0xab, 0x3e, 0xf0, 0x9b, 0xb7, 0x8d, 0x46, 0xd3, 0x52,
+ 0x9b, 0xbd, 0xfd, 0x2b, 0xba, 0x73, 0x5d, 0x23, 0x67, 0x68, 0xe1, 0x76,
+ 0x6f, 0x56, 0x2b, 0x17, 0xe4, 0x7e, 0x9a, 0xfd, 0x05, 0x48, 0x39, 0xc9,
+ 0xcf, 0xa5, 0x83, 0xf7, 0x90, 0x9c, 0xa4, 0x28, 0x57, 0x40, 0xe9, 0xd4,
+ 0x4b, 0x1a, 0x4b, 0x6f, 0x65, 0x14, 0xca, 0x43, 0xc1, 0x3f, 0x7c, 0xec,
+ 0x82, 0x47, 0x0e, 0x64, 0x8b, 0x6f, 0x8c, 0xb2, 0xf0, 0x6d, 0xeb, 0x6f,
+ 0x71, 0x8f, 0xcc, 0x2d, 0x60, 0x2b, 0xc3, 0x9f, 0x13, 0x94, 0xc7, 0x23,
+ 0x02, 0xf5, 0xe6, 0xdf, 0x2d, 0xa9, 0xdb, 0xa9, 0xf3, 0xee, 0xe9, 0x3f,
+ 0x2a, 0x69, 0x24, 0x6b, 0x78, 0xff, 0x6a, 0xd7, 0xe4, 0x69, 0x8c, 0x17,
+ 0xd5, 0xc1, 0x36, 0x1a, 0xca, 0x77, 0xb0, 0xb5, 0x6b, 0x96, 0x4a, 0xb5,
+ 0x0e, 0x4d, 0x0b, 0xd6, 0xd9, 0x78, 0xc5, 0xbf, 0xe3, 0x59, 0xfe, 0x63,
+ 0xe3, 0xd3, 0x3c, 0x9a, 0xfa, 0xd7, 0x69, 0x5b, 0xef, 0xd3, 0xa4, 0xa3,
+ 0xb9, 0x1f, 0x5c, 0x40, 0x20, 0x95, 0x38, 0x2d, 0xf5, 0x04, 0x0c, 0x2c,
+ 0x79, 0x77, 0xc1, 0xb6, 0xcc, 0x74, 0x3c, 0x66, 0xf1, 0xc6, 0x65, 0xab,
+ 0x4d, 0x68, 0x41, 0x16, 0x71, 0x51, 0xb9, 0x1b, 0xcb, 0xa7, 0x6d, 0xe0,
+ 0x70, 0xa9, 0xfa, 0x65, 0x6b, 0x7b, 0x1e, 0xc5, 0xdf, 0xe2, 0x4c, 0x96,
+ 0x44, 0x6b, 0x24, 0xa1, 0x15, 0x8e, 0xe7, 0x9b, 0x1f, 0x51, 0xef, 0xd7,
+ 0x65, 0x5f, 0xcd, 0x74, 0x7f, 0x2d, 0x5c, 0xba, 0xba, 0x20, 0x32, 0x8d,
+ 0x1c, 0xf1, 0x5a, 0xed, 0x21, 0xad, 0x78, 0x7b, 0x59, 0x58, 0xe4, 0xf6,
+ 0xa7, 0x10, 0x35, 0xca, 0x5d, 0x86, 0x1a, 0x68, 0xba, 0x1c, 0x3c, 0x1c,
+ 0x23, 0x79, 0x8b, 0x9f, 0xda, 0x5c, 0xd1, 0x5a, 0xa9, 0xc8, 0xf6, 0xc9,
+ 0xdf, 0x21, 0x5a, 0x98, 0xdc, 0xf4, 0xb9, 0x02, 0x97, 0x2c, 0x10, 0x60,
+ 0xc9, 0xb5, 0xea, 0x75, 0x0b, 0xd9, 0x8a, 0xa4, 0x86, 0x92, 0xbe, 0xf5,
+ 0xd8, 0xc7, 0x6b, 0x13, 0x8b, 0xbb, 0xca, 0x5f, 0xe4, 0x8b, 0xce, 0xb5,
+ 0x27, 0xae, 0x53, 0xed, 0xef, 0x37, 0xa6, 0x81, 0x8f, 0x70, 0x25, 0x18,
+ 0x93, 0x06, 0x8c, 0x18, 0xcd, 0x7a, 0x1a, 0x8d, 0xfc, 0xde, 0x6f, 0x30,
+ 0xdb, 0x41, 0xb6, 0x42, 0x14, 0x54, 0xf8, 0xcd, 0xc6, 0xf8, 0x0f, 0x82,
+ 0x17, 0xfa, 0x8d, 0xba, 0x80, 0x81, 0x6a, 0xf7, 0x02, 0x97, 0x00, 0x78,
+ 0xd6, 0x5b, 0xc9, 0xba, 0xd1, 0x99, 0xef, 0x8e, 0x48, 0x6c, 0x35, 0x10,
+ 0x5b, 0xf1, 0x9b, 0x93, 0x4f, 0xbd, 0x7d, 0x27, 0x9e, 0xc7, 0x86, 0xb2,
+ 0x8f, 0x6a, 0x91, 0x59, 0x2d, 0x14, 0xab, 0x1b, 0x34, 0x6e, 0xfa, 0x25,
+ 0x5e, 0x14, 0xc7, 0xef, 0x3d, 0x0f, 0x13, 0xf9, 0x45, 0x4b, 0x90, 0xbc,
+ 0xd8, 0x51, 0x42, 0x95, 0x25, 0x9b, 0x1b, 0x7c, 0xaf, 0x3b, 0x60, 0x21,
+ 0x4c, 0x5f, 0x7c, 0x63, 0x4b, 0x45, 0xa6, 0xdc, 0xfd, 0x32, 0xf3, 0x06,
+ 0x61, 0x11, 0x2d, 0x27, 0xde, 0x19, 0x38, 0x63, 0xf9, 0x70, 0xd1, 0x82,
+ 0x8e, 0xc7, 0x99, 0xe1, 0x96, 0x9b, 0x54, 0x93, 0x64, 0x5f, 0xd1, 0x62,
+ 0x9c, 0x37, 0x10, 0x1a, 0x8a, 0x82, 0x8d, 0x2a, 0x93, 0x95, 0x22, 0xc9,
+ 0x21, 0xf5, 0xce, 0x21, 0xbb, 0x7c, 0x17, 0xee, 0x20, 0xa0, 0x73, 0xaa,
+ 0x69, 0x78, 0x4e, 0x0d, 0x2c, 0x2c, 0x96, 0x23, 0xdc, 0x07, 0x16, 0xbd,
+ 0xe7, 0xd5, 0x49, 0xcc, 0x44, 0xd1, 0x9d, 0xd7, 0xa3, 0x01, 0x60, 0xa0,
+ 0xe0, 0x41, 0x63, 0x28, 0x8a, 0x43, 0xdb, 0x4f, 0x25, 0x5b, 0x27, 0x52,
+ 0x4a, 0xee, 0x42, 0x43, 0x9a, 0xef, 0x33, 0x43, 0x70, 0xda, 0x64, 0x57,
+ 0x49, 0x0c, 0x7f, 0xfd, 0xc7, 0x88, 0x26, 0x94, 0x10, 0xcc, 0x05, 0x1d,
+ 0x54, 0x95, 0xea, 0x4e, 0x65, 0x28, 0x03, 0xbc, 0xa2, 0x62, 0xd2, 0xce,
+ 0x60, 0x34, 0xf9, 0xdb, 0x26, 0xb5, 0xe6, 0x9b, 0x55, 0x2c, 0x8f, 0x30,
+ 0x3a, 0x94, 0x9a, 0x15, 0x79, 0x22, 0x75, 0x4d, 0x1b, 0x91, 0xe0, 0x5b,
+ 0xdb, 0xd1, 0x15, 0x7f, 0xcc, 0xc6, 0x88, 0xb5, 0x00, 0x3f, 0x5d, 0x84,
+ 0x2e, 0x68, 0xde, 0x6f, 0x41, 0x5b, 0x4e, 0xe7, 0xdf, 0xe6, 0x3b, 0x7e,
+ 0xf2, 0xdd, 0xfc, 0x01, 0xf2, 0x1b, 0x52, 0xba, 0xc4, 0x51, 0xae, 0x8f,
+ 0xa0, 0x55, 0x12, 0x81, 0x57, 0xe0, 0x58, 0x5e, 0xea, 0xd7, 0x85, 0xfb,
+ 0x19, 0x8b, 0xb7, 0x24, 0x29, 0x94, 0xa7, 0xfc, 0xed, 0x17, 0xaa, 0x32,
+ 0x50, 0x11, 0xb3, 0x7a, 0x43, 0x3a, 0xc0, 0x2b, 0x82, 0x9c, 0x85, 0xd9,
+ 0xd0, 0xdb, 0x21, 0x71, 0x83, 0xb4, 0x30, 0x14, 0xec, 0xfc, 0x8d, 0x32,
+ 0xd6, 0xa2, 0x36, 0x5e, 0x3b, 0xe9, 0x12, 0x0c, 0x95, 0xd6, 0x0c, 0x0c,
+ 0x31, 0x66, 0x30, 0x3f, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x09, 0x14, 0x31, 0x32, 0x1e, 0x30, 0x00, 0x49, 0x00, 0x6e, 0x00,
+ 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x6e, 0x00, 0x65, 0x00, 0x74, 0x00,
+ 0x20, 0x00, 0x57, 0x00, 0x69, 0x00, 0x64, 0x00, 0x67, 0x00, 0x69, 0x00,
+ 0x74, 0x00, 0x73, 0x00, 0x20, 0x00, 0x50, 0x00, 0x74, 0x00, 0x79, 0x00,
+ 0x20, 0x00, 0x4c, 0x00, 0x74, 0x00, 0x64, 0x30, 0x23, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x15, 0x31, 0x16, 0x04, 0x14,
+ 0x14, 0x74, 0x2d, 0x52, 0x8e, 0x0d, 0x0c, 0x06, 0x6c, 0x32, 0x64, 0xd3,
+ 0x7e, 0x33, 0x31, 0x68, 0x8b, 0x28, 0x1a, 0x75, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x07, 0x06, 0xa0, 0x80, 0x30, 0x80, 0x02, 0x01, 0x00, 0x30, 0x80,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x30,
+ 0x24, 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x01,
+ 0x06, 0x30, 0x16, 0x04, 0x10, 0x9d, 0x1b, 0x68, 0x8e, 0x11, 0xc2, 0xb2,
+ 0xd6, 0xd0, 0xe9, 0x5a, 0x9e, 0x96, 0xc1, 0x8c, 0xa6, 0x02, 0x02, 0x07,
+ 0xd0, 0xa0, 0x80, 0x04, 0x82, 0x03, 0xf8, 0x1d, 0xce, 0x13, 0x70, 0x7a,
+ 0x6b, 0x0a, 0x12, 0x2d, 0x01, 0x84, 0x63, 0x5c, 0x07, 0x82, 0x23, 0xf8,
+ 0x8a, 0x5e, 0x53, 0x8f, 0xc8, 0xb4, 0x87, 0x1a, 0xa2, 0x98, 0xdb, 0xc6,
+ 0x26, 0xca, 0xbb, 0x20, 0x24, 0xad, 0xac, 0xdf, 0xbe, 0x73, 0x6d, 0x97,
+ 0x4b, 0x6e, 0x5b, 0x45, 0xd2, 0x84, 0xd4, 0xa4, 0x82, 0xd0, 0xce, 0x40,
+ 0x13, 0x4c, 0x6d, 0x4d, 0x2e, 0xc1, 0x96, 0x95, 0x01, 0x64, 0xf3, 0xf0,
+ 0x5f, 0x06, 0x06, 0xea, 0xf7, 0x84, 0x8f, 0xb3, 0xb0, 0x6e, 0x7c, 0x9b,
+ 0x71, 0x73, 0xb9, 0xcd, 0xac, 0x72, 0xf6, 0xa0, 0x23, 0xda, 0x9b, 0x9f,
+ 0xec, 0x16, 0xef, 0x33, 0xd4, 0xd0, 0x4d, 0x20, 0xf0, 0x75, 0xa9, 0x73,
+ 0xf4, 0x31, 0xc7, 0x57, 0xb8, 0x0d, 0x9d, 0x85, 0x7c, 0xee, 0x3a, 0x24,
+ 0x7b, 0x74, 0xa0, 0x5c, 0xad, 0xde, 0x5e, 0x05, 0x1e, 0xeb, 0x02, 0x78,
+ 0x12, 0xb4, 0xb9, 0xc6, 0xe5, 0xc5, 0x99, 0xbc, 0x05, 0x62, 0x5b, 0x10,
+ 0x52, 0x08, 0x00, 0x9e, 0x73, 0xac, 0xe4, 0x1d, 0xdb, 0xb8, 0xbf, 0x48,
+ 0x03, 0x28, 0x05, 0x3c, 0x61, 0x1a, 0x8b, 0x4c, 0xd7, 0x5f, 0x8c, 0xb4,
+ 0xcd, 0x91, 0x1c, 0x0b, 0xf4, 0x55, 0xd4, 0x1c, 0x42, 0x4a, 0xd4, 0xf5,
+ 0x15, 0x38, 0xd9, 0x06, 0xfc, 0x49, 0xf6, 0xe5, 0xa7, 0x09, 0x5d, 0x01,
+ 0xbd, 0xc3, 0xd1, 0x09, 0x9f, 0x5d, 0x0c, 0x19, 0x43, 0xd0, 0xfa, 0x25,
+ 0x17, 0xad, 0x2a, 0xbf, 0x89, 0x63, 0x06, 0xa8, 0x02, 0x03, 0xe4, 0xfe,
+ 0x19, 0x08, 0x70, 0xa1, 0x74, 0x74, 0xb6, 0xb6, 0x0f, 0x19, 0x4d, 0x54,
+ 0xa5, 0xb2, 0xd7, 0x37, 0x3b, 0x17, 0xc0, 0x5d, 0xc2, 0x8a, 0xf1, 0xcc,
+ 0xed, 0xef, 0x65, 0xc8, 0xca, 0xbe, 0x02, 0xd4, 0x9b, 0x1e, 0xef, 0xc9,
+ 0xe0, 0x91, 0x82, 0xb0, 0xe0, 0x50, 0xc7, 0xa0, 0xcc, 0x01, 0x6d, 0x55,
+ 0xe5, 0x67, 0x99, 0x65, 0x13, 0xe4, 0xd2, 0x90, 0x91, 0xf3, 0x76, 0x0b,
+ 0x6a, 0x2d, 0x19, 0xaf, 0x61, 0xb3, 0x7f, 0x4c, 0x04, 0xfe, 0x68, 0xf6,
+ 0xb3, 0x56, 0xd8, 0xf3, 0x34, 0xd7, 0x04, 0x0a, 0x31, 0xc8, 0x37, 0xdf,
+ 0xac, 0xd8, 0x91, 0x80, 0x8a, 0x30, 0x12, 0x22, 0x80, 0xd7, 0x24, 0xcf,
+ 0x70, 0xaf, 0x56, 0xaf, 0x81, 0xfe, 0x63, 0xf1, 0xea, 0x57, 0x4c, 0xf2,
+ 0xdb, 0x30, 0x50, 0x92, 0xc1, 0xeb, 0x04, 0x9a, 0xdf, 0xf5, 0x74, 0x57,
+ 0x5b, 0x58, 0xc2, 0x4e, 0x6b, 0x11, 0xf3, 0xe1, 0xb3, 0x0f, 0x56, 0x35,
+ 0x04, 0xf8, 0x50, 0x1d, 0x7e, 0xe6, 0x99, 0xa2, 0x48, 0xdb, 0xea, 0x62,
+ 0x4f, 0x98, 0xc2, 0xef, 0xbf, 0x7f, 0x94, 0xc0, 0x36, 0xc0, 0xf3, 0x27,
+ 0xfe, 0xe2, 0x17, 0x1e, 0x91, 0x7d, 0x96, 0xa9, 0x2b, 0x71, 0x51, 0xc3,
+ 0x59, 0x2d, 0x11, 0x50, 0x1e, 0xcb, 0xce, 0xff, 0x04, 0x4d, 0x16, 0xf5,
+ 0xc2, 0xd4, 0x1f, 0xdd, 0x7f, 0x5a, 0xfd, 0x1d, 0xe9, 0x63, 0x52, 0x44,
+ 0x76, 0x5f, 0x91, 0xfd, 0xe8, 0xdf, 0x0a, 0x69, 0x0d, 0xd3, 0x64, 0x91,
+ 0xea, 0xdd, 0x03, 0x4f, 0x42, 0xa5, 0xe9, 0xa1, 0x70, 0x05, 0xf3, 0x22,
+ 0x8e, 0xad, 0x70, 0x1a, 0x3e, 0x94, 0x42, 0x06, 0xe7, 0x47, 0x37, 0x3d,
+ 0xf5, 0xda, 0x3e, 0x2a, 0x3a, 0xc0, 0x23, 0xd9, 0x4a, 0x26, 0x69, 0x13,
+ 0xa6, 0x93, 0x7c, 0xf2, 0xaf, 0x04, 0x5e, 0x9b, 0x88, 0xc7, 0x77, 0xd0,
+ 0x93, 0xab, 0x1b, 0xbd, 0x3d, 0x69, 0x90, 0xab, 0x41, 0xa9, 0xbc, 0x84,
+ 0x18, 0x4d, 0x29, 0x02, 0xc1, 0xf8, 0xff, 0x63, 0x18, 0x24, 0x74, 0x8f,
+ 0x7e, 0x44, 0x33, 0xaf, 0x88, 0x8b, 0x93, 0x5b, 0x9a, 0xae, 0x6b, 0x08,
+ 0xa2, 0x82, 0x5d, 0xf3, 0xbe, 0x61, 0xc3, 0xf0, 0x2d, 0x31, 0x4c, 0xb5,
+ 0xb5, 0x91, 0x0f, 0xfa, 0x81, 0x61, 0xad, 0xfc, 0xba, 0x91, 0xeb, 0x3b,
+ 0x9d, 0x22, 0x41, 0x45, 0x0e, 0x8e, 0x24, 0xc7, 0x1c, 0x81, 0x95, 0xa8,
+ 0x7b, 0x64, 0xed, 0xa5, 0xec, 0x5a, 0x68, 0x3c, 0x85, 0x8d, 0x92, 0xb7,
+ 0x24, 0x0f, 0xed, 0xf5, 0xc6, 0x31, 0x61, 0xdc, 0xef, 0xa7, 0xcb, 0x8f,
+ 0xda, 0x43, 0x05, 0x42, 0xf6, 0x9e, 0xbc, 0x1b, 0x9a, 0xa1, 0xe8, 0x1d,
+ 0x8d, 0x42, 0xdb, 0x80, 0x83, 0x55, 0x52, 0x2b, 0x95, 0x00, 0x05, 0x82,
+ 0x84, 0xc3, 0x54, 0x23, 0x8e, 0x1d, 0x00, 0xa2, 0x16, 0x3e, 0xce, 0x3d,
+ 0xcc, 0x9e, 0xb8, 0x4c, 0x59, 0xb2, 0x12, 0xa2, 0x23, 0xc1, 0x46, 0x50,
+ 0x86, 0xae, 0x75, 0x7e, 0x49, 0x38, 0x77, 0x94, 0xf0, 0x27, 0xd8, 0x17,
+ 0x38, 0x8c, 0xe0, 0x73, 0x00, 0xfb, 0xaf, 0xbf, 0xe8, 0xed, 0x85, 0x58,
+ 0x3e, 0xb4, 0x88, 0x04, 0xc8, 0x22, 0x1b, 0xb4, 0x75, 0xa2, 0xc4, 0xdd,
+ 0x06, 0xd2, 0x83, 0x42, 0x21, 0x57, 0xfc, 0xd8, 0xae, 0x9c, 0x0e, 0xd8,
+ 0x6a, 0x70, 0xd1, 0xeb, 0x44, 0x9c, 0xb7, 0x37, 0x04, 0x05, 0xf5, 0x17,
+ 0xbe, 0xf3, 0x56, 0x1b, 0x06, 0x36, 0x1c, 0x59, 0x7b, 0x65, 0x8d, 0xbb,
+ 0xbe, 0x22, 0x9a, 0x70, 0xa3, 0xe9, 0x60, 0x1a, 0xc9, 0xdd, 0x81, 0x3c,
+ 0x2d, 0x4e, 0xc0, 0x8a, 0xe5, 0x91, 0xa7, 0xc1, 0x80, 0x07, 0x47, 0x7a,
+ 0x74, 0x4f, 0x3e, 0x4a, 0xdc, 0xb2, 0xcc, 0xff, 0x37, 0x66, 0x05, 0xcb,
+ 0xd6, 0xe9, 0x90, 0xf5, 0xef, 0x2b, 0x7e, 0xa7, 0x66, 0x51, 0xcb, 0x48,
+ 0xb3, 0x8a, 0x6f, 0x06, 0xba, 0x8b, 0x3d, 0x35, 0x36, 0xdf, 0x0e, 0x40,
+ 0xe5, 0xa1, 0xe3, 0xdd, 0x89, 0xab, 0x64, 0x9c, 0x01, 0x15, 0x9e, 0x93,
+ 0xea, 0xf9, 0x4f, 0x9e, 0xf5, 0x8b, 0xf2, 0xc2, 0xbb, 0xe5, 0xc3, 0xa3,
+ 0xe3, 0x13, 0x63, 0x4f, 0x7d, 0x20, 0xe4, 0x66, 0x96, 0x84, 0x8d, 0xd4,
+ 0xca, 0x72, 0x52, 0xdc, 0xb8, 0x93, 0xd4, 0xa5, 0x3e, 0x6e, 0x42, 0x56,
+ 0x80, 0x46, 0x77, 0x86, 0x49, 0xfe, 0xf3, 0xb4, 0x5b, 0x37, 0xfc, 0xb8,
+ 0x0c, 0xd7, 0x63, 0xac, 0x3c, 0x6f, 0xf0, 0xbe, 0xbe, 0xb4, 0x13, 0xe7,
+ 0x34, 0xe5, 0x06, 0xbf, 0x17, 0x48, 0x6e, 0xc0, 0x26, 0x94, 0xdd, 0xed,
+ 0xf4, 0xda, 0x97, 0x25, 0xab, 0xd6, 0x9b, 0xc3, 0x8c, 0xeb, 0x17, 0x09,
+ 0xfc, 0x03, 0x5a, 0x2f, 0x19, 0x85, 0x50, 0xc4, 0xe6, 0x35, 0x71, 0x94,
+ 0xad, 0xc5, 0xcf, 0x08, 0xcf, 0x69, 0x3b, 0xc3, 0x31, 0xec, 0xf1, 0xfa,
+ 0x80, 0x66, 0x8f, 0x14, 0xde, 0x56, 0x21, 0x12, 0x9b, 0x0c, 0xdf, 0x92,
+ 0x48, 0x06, 0xce, 0xdb, 0xeb, 0x28, 0x54, 0x27, 0x8b, 0xa9, 0xef, 0x0c,
+ 0xf4, 0xa0, 0xcc, 0x84, 0x59, 0x60, 0xed, 0x18, 0x65, 0xca, 0x67, 0x0c,
+ 0xd1, 0x1f, 0xcf, 0x59, 0x4b, 0xce, 0x07, 0x27, 0x08, 0x6a, 0xea, 0x53,
+ 0xdc, 0x47, 0xb3, 0x4e, 0xe4, 0x0b, 0xff, 0x9a, 0x7d, 0x6b, 0x0d, 0x2f,
+ 0x2d, 0x60, 0xd7, 0x8b, 0x22, 0xf5, 0x30, 0x43, 0x09, 0xe6, 0xdf, 0x01,
+ 0x03, 0x27, 0x2d, 0xb5, 0x74, 0x52, 0x5d, 0x08, 0xc7, 0x5a, 0x44, 0x25,
+ 0x0f, 0x2c, 0x14, 0x8f, 0x48, 0xea, 0x18, 0x99, 0xd1, 0xcc, 0xc5, 0xdc,
+ 0x65, 0xa5, 0x3d, 0x25, 0x94, 0xa9, 0xc7, 0xad, 0x3e, 0xa4, 0xf6, 0xe6,
+ 0xbd, 0xa7, 0x70, 0xd4, 0xdc, 0x9b, 0x26, 0xcb, 0x31, 0x70, 0xaf, 0x3e,
+ 0xa4, 0xb6, 0x8d, 0x21, 0x31, 0x67, 0x35, 0x35, 0x86, 0x67, 0xd1, 0x02,
+ 0x6c, 0x36, 0x76, 0xc9, 0x20, 0xf6, 0x0f, 0x30, 0x41, 0x83, 0x19, 0xf5,
+ 0xe1, 0x33, 0x90, 0xbc, 0x7b, 0x8c, 0x9b, 0x8a, 0x68, 0x30, 0x9e, 0xed,
+ 0xf4, 0x88, 0xc9, 0x04, 0x08, 0x2b, 0xb0, 0x0f, 0xae, 0xc7, 0xe0, 0x6e,
+ 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x39, 0x30, 0x21, 0x30,
+ 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14,
+ 0xe0, 0xf7, 0xa1, 0x1b, 0xf6, 0x3f, 0x05, 0xad, 0x55, 0x6a, 0x20, 0x4c,
+ 0x71, 0xca, 0x62, 0x47, 0x13, 0x28, 0xd5, 0x05, 0x04, 0x10, 0x3e, 0x87,
+ 0x2d, 0x96, 0xea, 0x80, 0x4b, 0xab, 0x3a, 0xb9, 0xee, 0x09, 0x65, 0x28,
+ 0xbc, 0x8d, 0x02, 0x02, 0x07, 0xd0, 0x00, 0x00,
+};
+
+/* kWindows is a dummy key and certificate exported from the certificate
+ * manager on Windows 7. */
+static const uint8_t kWindows[] = {
+ 0x30, 0x82, 0x0a, 0x02, 0x02, 0x01, 0x03, 0x30, 0x82, 0x09, 0xbe, 0x06,
+ 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82,
+ 0x09, 0xaf, 0x04, 0x82, 0x09, 0xab, 0x30, 0x82, 0x09, 0xa7, 0x30, 0x82,
+ 0x06, 0x08, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07,
+ 0x01, 0xa0, 0x82, 0x05, 0xf9, 0x04, 0x82, 0x05, 0xf5, 0x30, 0x82, 0x05,
+ 0xf1, 0x30, 0x82, 0x05, 0xed, 0x06, 0x0b, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x0c, 0x0a, 0x01, 0x02, 0xa0, 0x82, 0x04, 0xfe, 0x30, 0x82,
+ 0x04, 0xfa, 0x30, 0x1c, 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x0c, 0x01, 0x03, 0x30, 0x0e, 0x04, 0x08, 0xb7, 0x20, 0x55, 0x5a,
+ 0x4d, 0x3f, 0x0e, 0x89, 0x02, 0x02, 0x07, 0xd0, 0x04, 0x82, 0x04, 0xd8,
+ 0x3a, 0xcc, 0xd6, 0xcb, 0x4d, 0x54, 0xc0, 0x04, 0x56, 0x10, 0xcc, 0x49,
+ 0xe4, 0xe0, 0x10, 0x73, 0xfb, 0x1a, 0xdd, 0x1d, 0x4f, 0x6e, 0x55, 0xe3,
+ 0xa4, 0xab, 0xf9, 0x26, 0xaa, 0x42, 0x54, 0xa0, 0xd1, 0xf0, 0x8d, 0xbf,
+ 0x71, 0x7d, 0x18, 0x00, 0x17, 0xb3, 0xb7, 0x63, 0x50, 0x8d, 0x2c, 0xeb,
+ 0x2f, 0xe3, 0xc3, 0xbf, 0x93, 0xc8, 0x46, 0x48, 0x99, 0x47, 0xe2, 0x3b,
+ 0x8d, 0x71, 0x01, 0x5f, 0x59, 0x5b, 0x61, 0x7e, 0x1f, 0x0c, 0x6e, 0x3e,
+ 0xc4, 0x74, 0x99, 0x98, 0x30, 0xff, 0x37, 0x7b, 0x30, 0x19, 0xb5, 0xfc,
+ 0x69, 0x94, 0x5f, 0x79, 0x69, 0x34, 0xda, 0xb5, 0x21, 0xcf, 0xfe, 0x72,
+ 0x87, 0xe8, 0x7d, 0x29, 0x7e, 0x27, 0x25, 0x90, 0x80, 0x98, 0xdd, 0x8d,
+ 0xbf, 0x42, 0xb0, 0x10, 0xd8, 0x7d, 0x6d, 0xfe, 0x6f, 0x0d, 0x61, 0x09,
+ 0xfd, 0xb2, 0x9b, 0xeb, 0xbf, 0x1c, 0xca, 0x33, 0xbc, 0x4e, 0x19, 0x52,
+ 0x55, 0x53, 0xb4, 0xa5, 0x98, 0x6c, 0xa3, 0x3b, 0xf8, 0xa4, 0x8d, 0x79,
+ 0xcf, 0x40, 0xf2, 0x89, 0x09, 0x3c, 0x38, 0xab, 0xae, 0xf4, 0x09, 0x3b,
+ 0xb6, 0xcb, 0xdd, 0xd7, 0xad, 0xe0, 0x5a, 0x71, 0x64, 0xc9, 0x0f, 0x18,
+ 0xac, 0x3c, 0x12, 0xd4, 0x22, 0x54, 0x24, 0x1a, 0xa5, 0x35, 0x78, 0x99,
+ 0x09, 0x4a, 0x18, 0x95, 0x23, 0xb9, 0xf7, 0x89, 0x3f, 0x13, 0x43, 0x1f,
+ 0x8d, 0x76, 0x6b, 0x04, 0xdb, 0x64, 0xf4, 0x8e, 0xf5, 0x50, 0xa0, 0xae,
+ 0x1c, 0x8c, 0xc8, 0xf3, 0xde, 0xf3, 0x11, 0x2d, 0xfe, 0x76, 0xf0, 0xac,
+ 0x46, 0x54, 0x23, 0x03, 0x49, 0xfa, 0x73, 0xcd, 0xe0, 0xa1, 0x6c, 0x66,
+ 0x4d, 0x1b, 0x99, 0x57, 0x3d, 0x61, 0x61, 0xeb, 0x61, 0x40, 0xc7, 0xd6,
+ 0x41, 0xbe, 0x63, 0x21, 0x1e, 0x7e, 0xb5, 0x0e, 0x94, 0x93, 0x37, 0x41,
+ 0xe8, 0x91, 0x06, 0xd7, 0xa3, 0x33, 0x78, 0x17, 0x17, 0x59, 0x78, 0x8f,
+ 0xaf, 0xed, 0xf9, 0x90, 0xfb, 0xb6, 0xc8, 0xa9, 0x0b, 0x10, 0x1a, 0xf1,
+ 0xab, 0x10, 0x11, 0xbc, 0x7f, 0xa5, 0x2d, 0x34, 0x7d, 0x7b, 0xaf, 0xc8,
+ 0xb2, 0x00, 0x6b, 0xd4, 0xbb, 0x25, 0x9b, 0xc7, 0x14, 0x8b, 0x50, 0x0a,
+ 0xd5, 0x2c, 0x1f, 0xa0, 0x5f, 0x07, 0x1d, 0x5e, 0x1a, 0xa4, 0x4b, 0x85,
+ 0xb2, 0xa6, 0xe2, 0xdd, 0xb7, 0xda, 0x11, 0x25, 0x51, 0xbf, 0x72, 0x50,
+ 0x53, 0xa1, 0x3d, 0xfa, 0x1d, 0x34, 0x75, 0xdd, 0x7a, 0xe0, 0x90, 0x56,
+ 0x14, 0xc3, 0xe8, 0x0b, 0xea, 0x32, 0x5f, 0x92, 0xfc, 0x2e, 0x4d, 0x0e,
+ 0xfe, 0xba, 0x1a, 0x00, 0x6d, 0x8f, 0x75, 0xac, 0x49, 0x4c, 0x79, 0x03,
+ 0x2e, 0xf2, 0xcc, 0x8e, 0x96, 0x27, 0x3c, 0x59, 0x28, 0x7f, 0x52, 0x8d,
+ 0xc3, 0x3b, 0x24, 0x68, 0xff, 0xbb, 0xd0, 0x4e, 0xdf, 0xc4, 0x91, 0x32,
+ 0x14, 0x5e, 0x43, 0x73, 0xd8, 0x56, 0x65, 0xe1, 0x48, 0x89, 0xe4, 0x33,
+ 0xef, 0x4b, 0x51, 0x50, 0xf2, 0x53, 0xe7, 0xae, 0x7d, 0xb6, 0x8c, 0x80,
+ 0xee, 0x8d, 0x9e, 0x24, 0x1a, 0xdd, 0x95, 0x7d, 0x22, 0x58, 0x76, 0xf8,
+ 0xbb, 0x63, 0x36, 0x17, 0xdc, 0xc6, 0x3e, 0xb8, 0xe9, 0x1f, 0xd8, 0xe0,
+ 0x06, 0x18, 0x1b, 0x3c, 0x45, 0xcb, 0xe1, 0x5a, 0x41, 0xe5, 0x32, 0xa3,
+ 0x85, 0x1b, 0xff, 0xe0, 0x5e, 0x28, 0xee, 0xe9, 0x05, 0xc7, 0xc8, 0x47,
+ 0x85, 0xe8, 0x13, 0x7f, 0x1b, 0xda, 0xd7, 0x3e, 0x8e, 0xb8, 0xa3, 0x96,
+ 0x34, 0x19, 0x3b, 0x0c, 0x88, 0x26, 0x38, 0xe7, 0x65, 0xf6, 0x03, 0x4f,
+ 0xc8, 0x37, 0x6e, 0x2f, 0x5e, 0x5d, 0xcd, 0xa3, 0x29, 0x37, 0xe8, 0x86,
+ 0x84, 0x66, 0x37, 0x84, 0xa0, 0x49, 0x4e, 0x8f, 0x3b, 0x1a, 0x42, 0x9f,
+ 0x62, 0x1f, 0x2b, 0x97, 0xc9, 0x18, 0x21, 0xd2, 0xa5, 0xcd, 0x8f, 0xa4,
+ 0x03, 0xf8, 0x82, 0x1e, 0xb8, 0x3e, 0x6b, 0x54, 0x29, 0x75, 0x5f, 0x80,
+ 0xe6, 0x8f, 0x2f, 0x65, 0xb0, 0x6b, 0xbb, 0x18, 0x6e, 0x0d, 0x32, 0x62,
+ 0x8c, 0x97, 0x48, 0xd3, 0xaa, 0xf2, 0x5e, 0xb8, 0x25, 0xbc, 0xb5, 0x22,
+ 0x4a, 0xac, 0xcf, 0xdc, 0x8b, 0x48, 0xfc, 0x95, 0xf2, 0x17, 0x21, 0x1e,
+ 0xda, 0x13, 0xd3, 0x1b, 0xe2, 0x37, 0xd5, 0xbf, 0x92, 0xe4, 0x81, 0xf5,
+ 0x98, 0x57, 0x51, 0x14, 0xda, 0x80, 0x7d, 0x4a, 0x6a, 0xce, 0x17, 0xaf,
+ 0xdb, 0xc3, 0x2e, 0x84, 0x3b, 0x1e, 0x02, 0x51, 0x4a, 0xc1, 0x25, 0x8c,
+ 0x5a, 0x20, 0x56, 0xee, 0xec, 0x59, 0xcf, 0xd7, 0x3e, 0x5f, 0x39, 0x9f,
+ 0xbf, 0x4d, 0x4e, 0x94, 0xb1, 0x1d, 0x83, 0x70, 0xc0, 0xab, 0xff, 0xfa,
+ 0x7c, 0x2e, 0x5b, 0xfb, 0x57, 0x3f, 0x60, 0xb8, 0xf3, 0x36, 0x5f, 0xbf,
+ 0x6a, 0x8c, 0x6f, 0xe0, 0x34, 0xe8, 0x75, 0x26, 0xc2, 0x1e, 0x22, 0x64,
+ 0x0e, 0x43, 0xc1, 0x93, 0xe6, 0x8a, 0x2e, 0xe9, 0xd9, 0xe0, 0x9f, 0x56,
+ 0x50, 0x8a, 0xbd, 0x68, 0xf6, 0x57, 0x63, 0x55, 0xbb, 0xe7, 0xfe, 0x22,
+ 0xca, 0xdc, 0x85, 0x38, 0x39, 0xc8, 0x66, 0x02, 0x28, 0x0f, 0xe0, 0x1c,
+ 0xd6, 0x0f, 0x5d, 0x6a, 0x0b, 0xd8, 0xe5, 0x6a, 0xeb, 0x54, 0xb2, 0xe0,
+ 0x02, 0x6f, 0xe2, 0x42, 0x89, 0x66, 0xc2, 0xd5, 0xc6, 0xe2, 0xb2, 0x04,
+ 0x6d, 0x8a, 0x2b, 0x48, 0xc2, 0x51, 0x07, 0x8e, 0xf3, 0x91, 0x0b, 0xb7,
+ 0x55, 0x6e, 0xbb, 0xbf, 0x11, 0x5a, 0xcb, 0x2c, 0xb3, 0x1e, 0x61, 0xd3,
+ 0xdb, 0x90, 0xad, 0xba, 0x10, 0x96, 0xe2, 0x16, 0xf4, 0x0c, 0x47, 0xbd,
+ 0x64, 0x66, 0x7a, 0x17, 0x63, 0xb9, 0x02, 0xcb, 0x53, 0x7a, 0x35, 0x92,
+ 0x74, 0xc3, 0x2a, 0x7d, 0xc5, 0x11, 0x18, 0x2f, 0xa3, 0x62, 0x2c, 0xc0,
+ 0x87, 0xd3, 0xd3, 0xba, 0xcb, 0xe0, 0x86, 0x9b, 0x4b, 0xc5, 0x59, 0x98,
+ 0x7e, 0x32, 0x96, 0x55, 0xc1, 0x3d, 0x5a, 0xcd, 0x90, 0x2d, 0xf8, 0xb7,
+ 0xa8, 0xba, 0xce, 0x89, 0x64, 0xa6, 0xf3, 0x1b, 0x11, 0x2e, 0x12, 0x99,
+ 0x4d, 0x34, 0x45, 0x13, 0x66, 0xb7, 0x69, 0x7b, 0xc5, 0x79, 0xf5, 0x6b,
+ 0xc2, 0x1d, 0xc8, 0x3f, 0x09, 0x18, 0x0a, 0xfc, 0xf7, 0xaf, 0x98, 0xc2,
+ 0xc7, 0xcc, 0x85, 0x29, 0xc6, 0x22, 0x7a, 0x77, 0xab, 0xb5, 0xac, 0xf7,
+ 0x9e, 0x70, 0x8e, 0x7f, 0x3c, 0xf1, 0xbd, 0xd9, 0x7a, 0x92, 0x84, 0xc5,
+ 0xb8, 0x56, 0xc3, 0xcb, 0xf7, 0x25, 0xad, 0xda, 0x0e, 0x1c, 0xe4, 0x68,
+ 0x66, 0x83, 0x91, 0x78, 0xf1, 0xe7, 0x8c, 0xaa, 0x45, 0xb6, 0x85, 0x74,
+ 0x9b, 0x08, 0xff, 0xac, 0x38, 0x55, 0xa5, 0x6a, 0xea, 0x2e, 0x75, 0x71,
+ 0xd3, 0xa2, 0xdc, 0x1c, 0xc0, 0xc7, 0x0b, 0xa9, 0xd5, 0x7e, 0xf9, 0x63,
+ 0x82, 0x87, 0xb7, 0x81, 0x01, 0xb9, 0x31, 0xdf, 0x41, 0x35, 0x0e, 0xe2,
+ 0x1f, 0x48, 0xbf, 0x60, 0xce, 0xb0, 0xb4, 0x38, 0xa5, 0xb4, 0x76, 0xa3,
+ 0x80, 0x1f, 0x93, 0x57, 0xf2, 0x05, 0x81, 0x42, 0xd1, 0xae, 0x56, 0x6d,
+ 0xc5, 0x4c, 0xab, 0xa6, 0x24, 0x2a, 0x02, 0x3b, 0xb1, 0xc4, 0x75, 0xcf,
+ 0x15, 0x90, 0xb5, 0xf2, 0xe7, 0x10, 0x69, 0xa0, 0xe3, 0xc4, 0xe6, 0x52,
+ 0x63, 0x14, 0xb4, 0x15, 0x91, 0x8e, 0xba, 0x7a, 0xad, 0x2d, 0x9b, 0x24,
+ 0x74, 0x36, 0x31, 0xca, 0xcb, 0x4b, 0x5a, 0xbf, 0xd3, 0x4e, 0xb4, 0xc1,
+ 0x48, 0x44, 0x74, 0x2f, 0x83, 0xe4, 0x39, 0x3d, 0x90, 0x2d, 0x32, 0x12,
+ 0xf7, 0xfa, 0xd3, 0xe3, 0xdb, 0x4f, 0xe6, 0xe7, 0x20, 0x2c, 0x57, 0xc0,
+ 0xf9, 0x80, 0xe1, 0xdc, 0x1c, 0xf2, 0x05, 0x54, 0x35, 0xf6, 0xbd, 0xfb,
+ 0xbd, 0xc5, 0xb2, 0x82, 0x32, 0x63, 0x32, 0xca, 0xf4, 0xf7, 0x14, 0x92,
+ 0x87, 0x8a, 0x45, 0x37, 0x56, 0x93, 0xda, 0x4f, 0x04, 0x59, 0x03, 0x24,
+ 0x93, 0x1a, 0x0b, 0x4e, 0xdb, 0x58, 0xbf, 0xda, 0x2a, 0x0e, 0x7e, 0x98,
+ 0x6c, 0x0c, 0xeb, 0x21, 0xf9, 0xbf, 0x9b, 0x1f, 0xc0, 0xef, 0xd3, 0xea,
+ 0xcb, 0x99, 0x5e, 0x14, 0x3e, 0x10, 0xfa, 0xad, 0x38, 0xf7, 0x68, 0x9f,
+ 0xa3, 0xcc, 0xdf, 0xe5, 0x31, 0x91, 0x98, 0xde, 0x74, 0x5f, 0x7b, 0xce,
+ 0xe4, 0x54, 0xd9, 0x51, 0xec, 0xf5, 0x4b, 0x17, 0x5f, 0x99, 0x4c, 0xf8,
+ 0x00, 0xe0, 0x10, 0x09, 0x07, 0x64, 0xae, 0x61, 0x3b, 0x60, 0xa3, 0x89,
+ 0x38, 0xc4, 0x80, 0xf2, 0x1e, 0x11, 0x26, 0x78, 0x72, 0x05, 0x97, 0x27,
+ 0xba, 0x83, 0x33, 0x1b, 0x14, 0x4b, 0xc0, 0xc8, 0xb0, 0xcc, 0x0a, 0x9b,
+ 0x3e, 0x4c, 0xde, 0x12, 0x07, 0x11, 0xd5, 0xf0, 0xc0, 0xdd, 0x70, 0x3d,
+ 0xd8, 0x7a, 0xf7, 0xa2, 0xf2, 0x70, 0xad, 0x54, 0xce, 0x67, 0x41, 0x12,
+ 0x29, 0x1f, 0xe1, 0x49, 0x5f, 0x4c, 0x77, 0x41, 0x7c, 0x74, 0x25, 0x9c,
+ 0x91, 0xd1, 0x0d, 0xa5, 0x9a, 0xb8, 0x56, 0x4c, 0x01, 0xc0, 0x77, 0x51,
+ 0x14, 0xc8, 0x92, 0x40, 0x9a, 0xbd, 0x7f, 0x3b, 0x9b, 0x17, 0xbb, 0x80,
+ 0x6e, 0x50, 0x64, 0x31, 0xed, 0xe2, 0x22, 0x9f, 0x96, 0x8e, 0xe2, 0x4e,
+ 0x54, 0x6e, 0x36, 0x35, 0xfc, 0xf2, 0xed, 0xfc, 0x56, 0x63, 0xdb, 0x89,
+ 0x19, 0x99, 0xf8, 0x47, 0xff, 0xce, 0x35, 0xd2, 0x86, 0x63, 0xbc, 0xe4,
+ 0x8c, 0x5d, 0x12, 0x94, 0x31, 0x81, 0xdb, 0x30, 0x13, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x15, 0x31, 0x06, 0x04, 0x04,
+ 0x01, 0x00, 0x00, 0x00, 0x30, 0x57, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x0d, 0x01, 0x09, 0x14, 0x31, 0x4a, 0x1e, 0x48, 0x00, 0x65, 0x00,
+ 0x65, 0x00, 0x36, 0x00, 0x64, 0x00, 0x38, 0x00, 0x38, 0x00, 0x30, 0x00,
+ 0x35, 0x00, 0x2d, 0x00, 0x30, 0x00, 0x36, 0x00, 0x64, 0x00, 0x39, 0x00,
+ 0x2d, 0x00, 0x34, 0x00, 0x32, 0x00, 0x65, 0x00, 0x32, 0x00, 0x2d, 0x00,
+ 0x38, 0x00, 0x62, 0x00, 0x36, 0x00, 0x38, 0x00, 0x2d, 0x00, 0x66, 0x00,
+ 0x65, 0x00, 0x61, 0x00, 0x62, 0x00, 0x35, 0x00, 0x65, 0x00, 0x66, 0x00,
+ 0x32, 0x00, 0x38, 0x00, 0x32, 0x00, 0x37, 0x00, 0x30, 0x30, 0x6b, 0x06,
+ 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x11, 0x01, 0x31, 0x5e,
+ 0x1e, 0x5c, 0x00, 0x4d, 0x00, 0x69, 0x00, 0x63, 0x00, 0x72, 0x00, 0x6f,
+ 0x00, 0x73, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x74, 0x00, 0x20, 0x00, 0x45,
+ 0x00, 0x6e, 0x00, 0x68, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x65,
+ 0x00, 0x64, 0x00, 0x20, 0x00, 0x43, 0x00, 0x72, 0x00, 0x79, 0x00, 0x70,
+ 0x00, 0x74, 0x00, 0x6f, 0x00, 0x67, 0x00, 0x72, 0x00, 0x61, 0x00, 0x70,
+ 0x00, 0x68, 0x00, 0x69, 0x00, 0x63, 0x00, 0x20, 0x00, 0x50, 0x00, 0x72,
+ 0x00, 0x6f, 0x00, 0x76, 0x00, 0x69, 0x00, 0x64, 0x00, 0x65, 0x00, 0x72,
+ 0x00, 0x20, 0x00, 0x76, 0x00, 0x31, 0x00, 0x2e, 0x00, 0x30, 0x30, 0x82,
+ 0x03, 0x97, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07,
+ 0x06, 0xa0, 0x82, 0x03, 0x88, 0x30, 0x82, 0x03, 0x84, 0x02, 0x01, 0x00,
+ 0x30, 0x82, 0x03, 0x7d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x07, 0x01, 0x30, 0x1c, 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x0c, 0x01, 0x06, 0x30, 0x0e, 0x04, 0x08, 0x92, 0x16, 0x6d,
+ 0x6d, 0x68, 0xd3, 0xb0, 0xc1, 0x02, 0x02, 0x07, 0xd0, 0x80, 0x82, 0x03,
+ 0x50, 0xee, 0x76, 0xe8, 0x60, 0xbf, 0xca, 0x3c, 0x2d, 0xe5, 0x29, 0x22,
+ 0xf6, 0x33, 0xc3, 0x50, 0x6a, 0xdb, 0xf3, 0x58, 0x3c, 0xd9, 0x7c, 0xd8,
+ 0xf9, 0x83, 0x89, 0x17, 0xa8, 0x1b, 0x6b, 0x09, 0xc1, 0x99, 0x49, 0xb0,
+ 0x43, 0x06, 0xc6, 0x42, 0x4b, 0x7c, 0x85, 0x4b, 0xe6, 0x69, 0x38, 0x91,
+ 0xce, 0x3d, 0x3c, 0x97, 0xd5, 0x14, 0x4f, 0x15, 0x5a, 0x81, 0x4d, 0x77,
+ 0x40, 0xe0, 0xe1, 0x1c, 0x69, 0x3f, 0x1d, 0x65, 0x68, 0xb3, 0x98, 0x95,
+ 0x30, 0x6c, 0xb0, 0x70, 0x93, 0x0c, 0xce, 0xec, 0xaf, 0x57, 0xc6, 0x9c,
+ 0x34, 0xb4, 0x2b, 0xaf, 0xc3, 0x5e, 0x70, 0x87, 0x17, 0xe8, 0xc9, 0x54,
+ 0x06, 0xb5, 0xb7, 0x83, 0xff, 0x46, 0x2b, 0xb6, 0x6a, 0x66, 0x2f, 0x6d,
+ 0x0f, 0x96, 0x53, 0x66, 0x65, 0xb8, 0x7b, 0x48, 0x55, 0x83, 0xd3, 0xc4,
+ 0x16, 0x93, 0xde, 0x72, 0x59, 0xf1, 0x9a, 0xab, 0xd5, 0xd5, 0xcb, 0x24,
+ 0xa6, 0x4a, 0x4e, 0x57, 0xf3, 0x6e, 0xca, 0xb1, 0xeb, 0x7d, 0xdb, 0x02,
+ 0xd2, 0x79, 0x89, 0xef, 0xa2, 0x8b, 0xee, 0x6f, 0xdc, 0x5e, 0x65, 0xa5,
+ 0x09, 0x33, 0x51, 0xb5, 0x21, 0xc8, 0xc6, 0xab, 0xed, 0xd5, 0x50, 0x93,
+ 0x39, 0x71, 0x97, 0xd3, 0x2c, 0xdd, 0xaf, 0xb1, 0xc6, 0x9b, 0x4b, 0x69,
+ 0x98, 0xae, 0xaf, 0x21, 0xa0, 0x8a, 0x90, 0x25, 0xe0, 0xf4, 0x8c, 0xf2,
+ 0xc3, 0x4f, 0x64, 0xb6, 0xc6, 0x64, 0x90, 0xff, 0x95, 0x0a, 0xcc, 0x8c,
+ 0xf4, 0x86, 0x80, 0x53, 0x8d, 0x51, 0x0b, 0xcd, 0x45, 0x4f, 0xcf, 0x7c,
+ 0xc6, 0xdf, 0x08, 0x5e, 0xa7, 0xdf, 0x4f, 0xcf, 0x84, 0xde, 0xb8, 0x4d,
+ 0x73, 0x40, 0x06, 0xbe, 0x33, 0x82, 0xe8, 0x41, 0x1b, 0x9a, 0xc3, 0x5b,
+ 0xb6, 0xf3, 0xfc, 0x32, 0x98, 0xcc, 0xcc, 0x5e, 0xd5, 0xb7, 0x86, 0x0f,
+ 0xc8, 0x59, 0x72, 0xcb, 0x9a, 0xc5, 0x3c, 0x50, 0xb8, 0x25, 0xb8, 0x87,
+ 0x3e, 0x49, 0xd4, 0x2d, 0x2f, 0x50, 0x35, 0xeb, 0xb8, 0x10, 0xa7, 0xea,
+ 0xb1, 0xe2, 0x0c, 0x6a, 0x84, 0x2c, 0xe2, 0x7a, 0x26, 0xef, 0x7e, 0x6b,
+ 0x1e, 0x47, 0x6e, 0x98, 0xc0, 0x3f, 0x92, 0x24, 0xe7, 0x88, 0xf9, 0x18,
+ 0x78, 0x37, 0x8a, 0x54, 0xa6, 0x2b, 0x5b, 0xf0, 0xc7, 0xe2, 0x98, 0xa4,
+ 0xa6, 0x2e, 0xc3, 0x6a, 0x75, 0x66, 0x51, 0xe8, 0x0d, 0x90, 0xfd, 0xa7,
+ 0xec, 0x22, 0xb3, 0x7d, 0x9d, 0x0c, 0xfe, 0x72, 0x7f, 0x98, 0xf6, 0x86,
+ 0x30, 0xd3, 0x7c, 0xee, 0xa5, 0xc5, 0x20, 0x89, 0x79, 0x04, 0x8e, 0xa8,
+ 0xb6, 0x94, 0x70, 0x4e, 0x75, 0xe5, 0xa0, 0xae, 0x8c, 0x7f, 0x72, 0x4c,
+ 0xd5, 0x9f, 0xd2, 0x56, 0x0d, 0xb2, 0x28, 0x45, 0x99, 0xf8, 0x40, 0xd4,
+ 0x3f, 0x42, 0x4a, 0x0c, 0x92, 0x23, 0xe1, 0x17, 0xaf, 0x68, 0xa6, 0x0f,
+ 0x1d, 0x32, 0x0d, 0xf8, 0x08, 0x8e, 0xdc, 0x79, 0x68, 0xf0, 0xfe, 0x0b,
+ 0xda, 0x94, 0x2d, 0xa6, 0xa7, 0x76, 0x7e, 0xd6, 0xca, 0xec, 0x7c, 0x37,
+ 0x52, 0x4f, 0x77, 0xcf, 0xa3, 0xcf, 0x8a, 0xfe, 0x89, 0xd9, 0x3e, 0xbc,
+ 0xb5, 0x06, 0xa0, 0x21, 0x91, 0x89, 0x77, 0x84, 0x85, 0x43, 0x2a, 0x65,
+ 0xec, 0x75, 0x4d, 0x0d, 0x1c, 0x79, 0x0f, 0x61, 0xca, 0x3e, 0x62, 0xbb,
+ 0x41, 0xf9, 0x4c, 0x5c, 0x3b, 0xde, 0x33, 0x8e, 0xdf, 0x51, 0x72, 0x93,
+ 0xca, 0xa6, 0xc7, 0x16, 0xe5, 0xb3, 0x22, 0xb6, 0x2e, 0xbf, 0xae, 0x1d,
+ 0x91, 0x1d, 0x49, 0x96, 0xa3, 0x25, 0xd4, 0xce, 0x6f, 0xf0, 0xfb, 0xb7,
+ 0xf5, 0x4a, 0x24, 0x03, 0x54, 0x4b, 0x7f, 0x0b, 0xb4, 0x31, 0xb4, 0x33,
+ 0xb7, 0x40, 0xf0, 0xd5, 0x4c, 0xee, 0xe3, 0x4b, 0x12, 0x8c, 0xc9, 0xa7,
+ 0x06, 0xb1, 0x02, 0x5a, 0x14, 0x6f, 0xe2, 0x3b, 0x68, 0x9b, 0x3d, 0xfc,
+ 0x83, 0x4a, 0xcc, 0xb5, 0x77, 0xe7, 0xf0, 0x1b, 0x52, 0xce, 0x60, 0x89,
+ 0xe2, 0x45, 0x76, 0xaa, 0x76, 0x70, 0xc2, 0xfd, 0x21, 0x8f, 0x1d, 0x67,
+ 0x1a, 0x4c, 0xe8, 0x81, 0x2b, 0x2e, 0xa9, 0x56, 0x0a, 0x27, 0x0f, 0x81,
+ 0xba, 0x5c, 0x4f, 0xfa, 0x6e, 0x7e, 0x33, 0x7d, 0x78, 0xed, 0xd2, 0xe3,
+ 0x24, 0xae, 0x24, 0xb2, 0x1b, 0x62, 0x71, 0x0e, 0x73, 0xfe, 0x8a, 0x3b,
+ 0x98, 0x0d, 0x82, 0x8e, 0x8d, 0x0f, 0xb3, 0xe2, 0x65, 0x87, 0xeb, 0x36,
+ 0x91, 0x4d, 0x8a, 0xfb, 0x22, 0x7a, 0x23, 0x2c, 0xe1, 0xb6, 0x94, 0xb6,
+ 0x90, 0x94, 0xcc, 0x0c, 0x7d, 0x02, 0x36, 0x56, 0xda, 0x45, 0x20, 0x90,
+ 0x48, 0xdb, 0xa4, 0xf5, 0x27, 0xac, 0x22, 0x49, 0x25, 0xaa, 0xd8, 0xa7,
+ 0x79, 0x38, 0x80, 0xc0, 0x95, 0xc7, 0xd1, 0x5c, 0x17, 0x7c, 0xa7, 0xec,
+ 0xd2, 0x63, 0xc6, 0xc6, 0x55, 0xfe, 0x78, 0x99, 0x06, 0x2c, 0x6e, 0x4f,
+ 0xfe, 0xd1, 0x5b, 0x8c, 0x2f, 0xa1, 0x42, 0x03, 0x26, 0x5a, 0x5e, 0xda,
+ 0xef, 0x43, 0xd2, 0x0e, 0xf9, 0x5f, 0xdb, 0x1d, 0x9c, 0xd1, 0xcb, 0x65,
+ 0x84, 0x26, 0xed, 0x91, 0x8f, 0x16, 0xb4, 0x1c, 0xc0, 0xb3, 0x8d, 0x79,
+ 0xae, 0x9b, 0xcb, 0x36, 0x6d, 0xcd, 0x67, 0x1f, 0x87, 0x11, 0x2a, 0x7c,
+ 0xb1, 0x8c, 0xfb, 0x06, 0xab, 0xd2, 0xd6, 0x2a, 0xe3, 0x45, 0x6c, 0xa5,
+ 0xc0, 0x19, 0x6b, 0xfc, 0xc3, 0xb7, 0x54, 0x35, 0xda, 0xdf, 0x12, 0x97,
+ 0x5c, 0xac, 0x59, 0xb4, 0x42, 0x25, 0xef, 0x04, 0xf7, 0x4c, 0xdb, 0x74,
+ 0xb9, 0x68, 0x8f, 0xee, 0x37, 0x0a, 0xc6, 0x21, 0x86, 0x0f, 0x6f, 0x8e,
+ 0xab, 0xd5, 0x7b, 0x38, 0x5e, 0x5f, 0x7d, 0xb9, 0x5a, 0xcb, 0xce, 0xa0,
+ 0x56, 0x37, 0x13, 0x71, 0x4b, 0xba, 0x43, 0x7c, 0xc0, 0xb7, 0x7f, 0x32,
+ 0xd7, 0x46, 0x27, 0x58, 0xfc, 0xdb, 0xb5, 0x64, 0x20, 0x3b, 0x20, 0x85,
+ 0x79, 0xa8, 0x9a, 0x22, 0xaf, 0x29, 0x86, 0xc5, 0x9d, 0x23, 0x96, 0x52,
+ 0xca, 0xc7, 0x9d, 0x92, 0x26, 0xe5, 0x3a, 0x60, 0xd6, 0xad, 0x8d, 0x5a,
+ 0xd9, 0x29, 0xbe, 0xd5, 0x5c, 0x3a, 0x77, 0xda, 0x34, 0xe2, 0x76, 0xcb,
+ 0x98, 0xa4, 0xf3, 0x33, 0xf1, 0x68, 0x20, 0x83, 0x95, 0x0b, 0x8d, 0x93,
+ 0x59, 0x02, 0x0c, 0x8f, 0xe4, 0xc4, 0xb0, 0xe7, 0x61, 0x0d, 0xf9, 0x80,
+ 0x20, 0x58, 0x40, 0xea, 0xb7, 0x0b, 0x1b, 0xad, 0xe3, 0x30, 0x3b, 0x30,
+ 0x1f, 0x30, 0x07, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x04, 0x14,
+ 0x2d, 0x77, 0x79, 0x79, 0x90, 0x41, 0x75, 0xf4, 0x4a, 0x7f, 0xf7, 0x15,
+ 0x94, 0x28, 0x62, 0xf7, 0x69, 0xd4, 0x44, 0x27, 0x04, 0x14, 0x2b, 0x2f,
+ 0xd9, 0x24, 0xc3, 0x8a, 0x34, 0xbb, 0x52, 0x52, 0x7b, 0xf6, 0x0e, 0x7b,
+ 0xfe, 0x3a, 0x66, 0x47, 0x40, 0x49, 0x02, 0x02, 0x07, 0xd0,
+};
+
+static int test(const char *name, const uint8_t *der, size_t der_len) {
+ CBS pkcs12;
+ EVP_PKEY *key;
+ STACK_OF(X509) *certs;
+
+ certs = sk_X509_new_null();
+
+ CBS_init(&pkcs12, der, der_len);
+ if (!PKCS12_get_key_and_certs(&key, certs, &pkcs12, "foo")) {
+ fprintf(stderr, "PKCS12 failed on %s data.\n", name);
+ BIO_print_errors_fp(stderr);
+ return 0;
+ }
+
+ if (sk_X509_num(certs) != 1 || key == NULL) {
+ fprintf(stderr, "Bad result from %s data.\n", name);
+ return 0;
+ }
+
+ sk_X509_pop_free(certs, X509_free);
+ EVP_PKEY_free(key);
+
+ return 1;
+}
+
+static int test_compat(const uint8_t *der, size_t der_len) {
+ PKCS12 *p12;
+ X509 *cert = NULL;
+ STACK_OF(X509) *ca_certs = NULL;
+ EVP_PKEY *key;
+ BIO *bio;
+
+ bio = BIO_new_mem_buf((void*) der, der_len);
+
+ p12 = d2i_PKCS12_bio(bio, NULL);
+ if (p12 == NULL) {
+ fprintf(stderr, "PKCS12_parse failed.\n");
+ BIO_print_errors_fp(stderr);
+ return 0;
+ }
+ BIO_free(bio);
+
+ if (!PKCS12_parse(p12, "foo", &key, &cert, &ca_certs)) {
+ fprintf(stderr, "PKCS12_parse failed.\n");
+ BIO_print_errors_fp(stderr);
+ return 0;
+ }
+
+ if (key == NULL || cert == NULL) {
+ fprintf(stderr, "Bad result from PKCS12_parse.\n");
+ return 0;
+ }
+
+ EVP_PKEY_free(key);
+ X509_free(cert);
+
+ if (sk_X509_num(ca_certs) != 0) {
+ fprintf(stderr, "Bad result from PKCS12_parse.\n");
+ return 0;
+ }
+ sk_X509_free(ca_certs);
+
+ PKCS12_free(p12);
+
+ return 1;
+}
+
+int main(int argc, char **argv) {
+ CRYPTO_library_init();
+ ERR_load_crypto_strings();
+
+ if (!test("OpenSSL", kOpenSSL, sizeof(kOpenSSL)) ||
+ !test("NSS", kNSS, sizeof(kNSS)) ||
+ !test("Windows", kWindows, sizeof(kWindows)) ||
+ !test_compat(kWindows, sizeof(kWindows))) {
+ return 1;
+ }
+
+ printf("PASS\n");
+ return 0;
+}
diff --git a/src/crypto/pkcs8/pkcs8.c b/src/crypto/pkcs8/pkcs8.c
new file mode 100644
index 0000000..0b1dfba
--- /dev/null
+++ b/src/crypto/pkcs8/pkcs8.c
@@ -0,0 +1,1155 @@
+/* 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 <openssl/pkcs8.h>
+
+#include <assert.h>
+#include <limits.h>
+#include <string.h>
+
+#include <openssl/asn1.h>
+#include <openssl/bn.h>
+#include <openssl/buf.h>
+#include <openssl/cipher.h>
+#include <openssl/digest.h>
+#include <openssl/err.h>
+#include <openssl/hmac.h>
+#include <openssl/mem.h>
+#include <openssl/x509.h>
+
+#include "../bytestring/internal.h"
+#include "../evp/internal.h"
+
+
+#define PKCS12_KEY_ID 1
+#define PKCS12_IV_ID 2
+#define PKCS12_MAC_ID 3
+
+static int ascii_to_ucs2(const char *ascii, size_t ascii_len,
+ uint8_t **out, size_t *out_len) {
+ uint8_t *unitmp;
+ size_t ulen, i;
+
+ ulen = ascii_len * 2 + 2;
+ if (ulen < ascii_len) {
+ return 0;
+ }
+ unitmp = OPENSSL_malloc(ulen);
+ if (unitmp == NULL) {
+ return 0;
+ }
+ for (i = 0; i < ulen - 2; i += 2) {
+ unitmp[i] = 0;
+ unitmp[i + 1] = ascii[i >> 1];
+ }
+
+ /* Make result double null terminated */
+ unitmp[ulen - 2] = 0;
+ unitmp[ulen - 1] = 0;
+ *out_len = ulen;
+ *out = unitmp;
+ return 1;
+}
+
+static int pkcs12_key_gen_raw(const uint8_t *pass_raw, size_t pass_raw_len,
+ const uint8_t *salt, size_t salt_len,
+ int id, int iterations,
+ size_t out_len, uint8_t *out,
+ const EVP_MD *md_type) {
+ uint8_t *B, *D, *I, *p, *Ai;
+ int Slen, Plen, Ilen, Ijlen;
+ int i, j, v;
+ size_t u;
+ int ret = 0;
+ BIGNUM *Ij, *Bpl1; /* These hold Ij and B + 1 */
+ EVP_MD_CTX ctx;
+
+ EVP_MD_CTX_init(&ctx);
+ v = EVP_MD_block_size(md_type);
+ u = EVP_MD_size(md_type);
+ D = OPENSSL_malloc(v);
+ Ai = OPENSSL_malloc(u);
+ B = OPENSSL_malloc(v + 1);
+ Slen = v * ((salt_len + v - 1) / v);
+ if (pass_raw_len)
+ Plen = v * ((pass_raw_len + v - 1) / v);
+ else
+ Plen = 0;
+ Ilen = Slen + Plen;
+ I = OPENSSL_malloc(Ilen);
+ Ij = BN_new();
+ Bpl1 = BN_new();
+ if (!D || !Ai || !B || !I || !Ij || !Bpl1)
+ goto err;
+ for (i = 0; i < v; i++)
+ D[i] = id;
+ p = I;
+ for (i = 0; i < Slen; i++)
+ *p++ = salt[i % salt_len];
+ for (i = 0; i < Plen; i++)
+ *p++ = pass_raw[i % pass_raw_len];
+ for (;;) {
+ if (!EVP_DigestInit_ex(&ctx, md_type, NULL) ||
+ !EVP_DigestUpdate(&ctx, D, v) ||
+ !EVP_DigestUpdate(&ctx, I, Ilen) ||
+ !EVP_DigestFinal_ex(&ctx, Ai, NULL)) {
+ goto err;
+ }
+ for (j = 1; j < iterations; j++) {
+ if (!EVP_DigestInit_ex(&ctx, md_type, NULL) ||
+ !EVP_DigestUpdate(&ctx, Ai, u) ||
+ !EVP_DigestFinal_ex(&ctx, Ai, NULL)) {
+ goto err;
+ }
+ }
+ memcpy(out, Ai, out_len < u ? out_len : u);
+ if (u >= out_len) {
+ ret = 1;
+ goto end;
+ }
+ out_len -= u;
+ out += u;
+ for (j = 0; j < v; j++)
+ B[j] = Ai[j % u];
+ /* Work out B + 1 first then can use B as tmp space */
+ if (!BN_bin2bn(B, v, Bpl1))
+ goto err;
+ if (!BN_add_word(Bpl1, 1))
+ goto err;
+ for (j = 0; j < Ilen; j += v) {
+ if (!BN_bin2bn(I + j, v, Ij))
+ goto err;
+ if (!BN_add(Ij, Ij, Bpl1))
+ goto err;
+ if (!BN_bn2bin(Ij, B))
+ goto err;
+ Ijlen = BN_num_bytes(Ij);
+ /* If more than 2^(v*8) - 1 cut off MSB */
+ if (Ijlen > v) {
+ if (!BN_bn2bin(Ij, B))
+ goto err;
+ memcpy(I + j, B + 1, v);
+ /* If less than v bytes pad with zeroes */
+ } else if (Ijlen < v) {
+ memset(I + j, 0, v - Ijlen);
+ if (!BN_bn2bin(Ij, I + j + v - Ijlen))
+ goto err;
+ } else if (!BN_bn2bin(Ij, I + j)) {
+ goto err;
+ }
+ }
+ }
+
+err:
+ OPENSSL_PUT_ERROR(PKCS8, pkcs12_key_gen_raw, ERR_R_MALLOC_FAILURE);
+
+end:
+ OPENSSL_free(Ai);
+ OPENSSL_free(B);
+ OPENSSL_free(D);
+ OPENSSL_free(I);
+ BN_free(Ij);
+ BN_free(Bpl1);
+ EVP_MD_CTX_cleanup(&ctx);
+
+ return ret;
+}
+
+static int pkcs12_pbe_keyivgen(EVP_CIPHER_CTX *ctx, const uint8_t *pass_raw,
+ size_t pass_raw_len, ASN1_TYPE *param,
+ const EVP_CIPHER *cipher, const EVP_MD *md,
+ int is_encrypt) {
+ PBEPARAM *pbe;
+ int salt_len, iterations, ret;
+ uint8_t *salt;
+ const uint8_t *pbuf;
+ uint8_t 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) {
+ OPENSSL_PUT_ERROR(PKCS8, pkcs12_pbe_keyivgen, PKCS8_R_DECODE_ERROR);
+ return 0;
+ }
+
+ pbuf = param->value.sequence->data;
+ pbe = d2i_PBEPARAM(NULL, &pbuf, param->value.sequence->length);
+ if (pbe == NULL) {
+ OPENSSL_PUT_ERROR(PKCS8, pkcs12_pbe_keyivgen, PKCS8_R_DECODE_ERROR);
+ return 0;
+ }
+
+ if (!pbe->iter) {
+ iterations = 1;
+ } else {
+ iterations = ASN1_INTEGER_get(pbe->iter);
+ }
+ salt = pbe->salt->data;
+ salt_len = pbe->salt->length;
+ if (!pkcs12_key_gen_raw(pass_raw, pass_raw_len, salt, salt_len, PKCS12_KEY_ID,
+ iterations, EVP_CIPHER_key_length(cipher), key, md)) {
+ OPENSSL_PUT_ERROR(PKCS8, pkcs12_pbe_keyivgen, PKCS8_R_KEY_GEN_ERROR);
+ PBEPARAM_free(pbe);
+ return 0;
+ }
+ if (!pkcs12_key_gen_raw(pass_raw, pass_raw_len, salt, salt_len, PKCS12_IV_ID,
+ iterations, EVP_CIPHER_iv_length(cipher), iv, md)) {
+ OPENSSL_PUT_ERROR(PKCS8, pkcs12_pbe_keyivgen, PKCS8_R_KEY_GEN_ERROR);
+ PBEPARAM_free(pbe);
+ return 0;
+ }
+ PBEPARAM_free(pbe);
+ ret = EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, is_encrypt);
+ OPENSSL_cleanse(key, EVP_MAX_KEY_LENGTH);
+ OPENSSL_cleanse(iv, EVP_MAX_IV_LENGTH);
+ return ret;
+}
+
+typedef int (*keygen_func)(EVP_CIPHER_CTX *ctx, const uint8_t *pass_raw,
+ size_t pass_raw_len, ASN1_TYPE *param,
+ const EVP_CIPHER *cipher, const EVP_MD *md,
+ int is_encrypt);
+
+struct pbe_suite {
+ int pbe_nid;
+ const EVP_CIPHER* (*cipher_func)(void);
+ const EVP_MD* (*md_func)(void);
+ keygen_func keygen;
+};
+
+static const struct pbe_suite kBuiltinPBE[] = {
+ {
+ NID_pbe_WithSHA1And40BitRC2_CBC, EVP_rc2_40_cbc, EVP_sha1, pkcs12_pbe_keyivgen,
+ },
+ {
+ NID_pbe_WithSHA1And128BitRC4, EVP_rc4, EVP_sha1, pkcs12_pbe_keyivgen,
+ },
+ {
+ NID_pbe_WithSHA1And3_Key_TripleDES_CBC, EVP_des_ede3_cbc, EVP_sha1,
+ pkcs12_pbe_keyivgen,
+ },
+};
+
+static int pbe_cipher_init(ASN1_OBJECT *pbe_obj,
+ const uint8_t *pass_raw, size_t pass_raw_len,
+ ASN1_TYPE *param,
+ EVP_CIPHER_CTX *ctx, int is_encrypt) {
+ const EVP_CIPHER *cipher;
+ const EVP_MD *md;
+ unsigned i;
+
+ const struct pbe_suite *suite = NULL;
+ const int pbe_nid = OBJ_obj2nid(pbe_obj);
+
+ for (i = 0; i < sizeof(kBuiltinPBE) / sizeof(struct pbe_suite); i++) {
+ if (kBuiltinPBE[i].pbe_nid == pbe_nid) {
+ suite = &kBuiltinPBE[i];
+ break;
+ }
+ }
+
+ if (suite == NULL) {
+ char obj_str[80];
+ OPENSSL_PUT_ERROR(PKCS8, pbe_cipher_init, PKCS8_R_UNKNOWN_ALGORITHM);
+ if (!pbe_obj) {
+ strncpy(obj_str, "NULL", sizeof(obj_str));
+ } else {
+ i2t_ASN1_OBJECT(obj_str, sizeof(obj_str), pbe_obj);
+ }
+ ERR_add_error_data(2, "TYPE=", obj_str);
+ return 0;
+ }
+
+ if (suite->cipher_func == NULL) {
+ cipher = NULL;
+ } else {
+ cipher = suite->cipher_func();
+ if (!cipher) {
+ OPENSSL_PUT_ERROR(PKCS8, pbe_cipher_init, PKCS8_R_UNKNOWN_CIPHER);
+ return 0;
+ }
+ }
+
+ if (suite->md_func == NULL) {
+ md = NULL;
+ } else {
+ md = suite->md_func();
+ if (!md) {
+ OPENSSL_PUT_ERROR(PKCS8, pbe_cipher_init, PKCS8_R_UNKNOWN_DIGEST);
+ return 0;
+ }
+ }
+
+ if (!suite->keygen(ctx, pass_raw, pass_raw_len, param, cipher, md,
+ is_encrypt)) {
+ OPENSSL_PUT_ERROR(PKCS8, pbe_cipher_init, PKCS8_R_KEYGEN_FAILURE);
+ return 0;
+ }
+
+ return 1;
+}
+
+static int pbe_crypt(const X509_ALGOR *algor,
+ const uint8_t *pass_raw, size_t pass_raw_len,
+ const uint8_t *in, size_t in_len,
+ uint8_t **out, size_t *out_len,
+ int is_encrypt) {
+ uint8_t *buf;
+ int n, ret = 0;
+ EVP_CIPHER_CTX ctx;
+ unsigned block_size;
+
+ EVP_CIPHER_CTX_init(&ctx);
+
+ if (!pbe_cipher_init(algor->algorithm, pass_raw, pass_raw_len,
+ algor->parameter, &ctx, is_encrypt)) {
+ OPENSSL_PUT_ERROR(PKCS8, pbe_crypt, PKCS8_R_UNKNOWN_CIPHER_ALGORITHM);
+ return 0;
+ }
+ block_size = EVP_CIPHER_CTX_block_size(&ctx);
+
+ if (in_len + block_size < in_len) {
+ OPENSSL_PUT_ERROR(PKCS8, pbe_crypt, PKCS8_R_TOO_LONG);
+ goto err;
+ }
+
+ buf = OPENSSL_malloc(in_len + block_size);
+ if (buf == NULL) {
+ OPENSSL_PUT_ERROR(PKCS8, pbe_crypt, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (!EVP_CipherUpdate(&ctx, buf, &n, in, in_len)) {
+ OPENSSL_free(buf);
+ OPENSSL_PUT_ERROR(PKCS8, pbe_crypt, ERR_R_EVP_LIB);
+ goto err;
+ }
+ *out_len = n;
+
+ if (!EVP_CipherFinal_ex(&ctx, buf + n, &n)) {
+ OPENSSL_free(buf);
+ OPENSSL_PUT_ERROR(PKCS8, pbe_crypt, ERR_R_EVP_LIB);
+ goto err;
+ }
+ *out_len += n;
+ *out = buf;
+ ret = 1;
+
+err:
+ EVP_CIPHER_CTX_cleanup(&ctx);
+ return ret;
+}
+
+static void *pkcs12_item_decrypt_d2i(X509_ALGOR *algor, const ASN1_ITEM *it,
+ const uint8_t *pass_raw,
+ size_t pass_raw_len,
+ ASN1_OCTET_STRING *oct) {
+ uint8_t *out;
+ const uint8_t *p;
+ void *ret;
+ size_t out_len;
+
+ if (!pbe_crypt(algor, pass_raw, pass_raw_len, oct->data, oct->length,
+ &out, &out_len, 0 /* decrypt */)) {
+ OPENSSL_PUT_ERROR(PKCS8, pkcs12_item_decrypt_d2i, PKCS8_R_CRYPT_ERROR);
+ return NULL;
+ }
+ p = out;
+ ret = ASN1_item_d2i(NULL, &p, out_len, it);
+ OPENSSL_cleanse(out, out_len);
+ if (!ret) {
+ OPENSSL_PUT_ERROR(PKCS8, pkcs12_item_decrypt_d2i, PKCS8_R_DECODE_ERROR);
+ }
+ OPENSSL_free(out);
+ return ret;
+}
+
+PKCS8_PRIV_KEY_INFO *PKCS8_decrypt(X509_SIG *pkcs8, const char *pass,
+ int pass_len) {
+ uint8_t *pass_raw = NULL;
+ size_t pass_raw_len = 0;
+ PKCS8_PRIV_KEY_INFO *ret;
+
+ if (pass) {
+ if (pass_len == -1) {
+ pass_len = strlen(pass);
+ }
+ if (!ascii_to_ucs2(pass, pass_len, &pass_raw, &pass_raw_len)) {
+ OPENSSL_PUT_ERROR(PKCS8, pkcs12_key_gen_asc, PKCS8_R_DECODE_ERROR);
+ return NULL;
+ }
+ }
+
+ ret = PKCS8_decrypt_pbe(pkcs8, pass_raw, pass_raw_len);
+
+ if (pass_raw) {
+ OPENSSL_cleanse(pass_raw, pass_raw_len);
+ OPENSSL_free(pass_raw);
+ }
+ return ret;
+}
+
+PKCS8_PRIV_KEY_INFO *PKCS8_decrypt_pbe(X509_SIG *pkcs8, const uint8_t *pass_raw,
+ size_t pass_raw_len) {
+ return pkcs12_item_decrypt_d2i(pkcs8->algor,
+ ASN1_ITEM_rptr(PKCS8_PRIV_KEY_INFO), pass_raw,
+ pass_raw_len, pkcs8->digest);
+}
+
+static ASN1_OCTET_STRING *pkcs12_item_i2d_encrypt(X509_ALGOR *algor,
+ const ASN1_ITEM *it,
+ const uint8_t *pass_raw,
+ size_t pass_raw_len, void *obj) {
+ ASN1_OCTET_STRING *oct;
+ uint8_t *in = NULL;
+ int in_len;
+ size_t crypt_len;
+
+ oct = M_ASN1_OCTET_STRING_new();
+ if (oct == NULL) {
+ OPENSSL_PUT_ERROR(PKCS8, pkcs12_item_i2d_encrypt, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ in_len = ASN1_item_i2d(obj, &in, it);
+ if (!in) {
+ OPENSSL_PUT_ERROR(PKCS8, pkcs12_item_i2d_encrypt, PKCS8_R_ENCODE_ERROR);
+ return NULL;
+ }
+ if (!pbe_crypt(algor, pass_raw, pass_raw_len, in, in_len, &oct->data, &crypt_len,
+ 1 /* encrypt */)) {
+ OPENSSL_PUT_ERROR(PKCS8, pkcs12_item_i2d_encrypt, PKCS8_R_ENCRYPT_ERROR);
+ OPENSSL_free(in);
+ return NULL;
+ }
+ oct->length = crypt_len;
+ OPENSSL_cleanse(in, in_len);
+ OPENSSL_free(in);
+ return oct;
+}
+
+X509_SIG *PKCS8_encrypt(int pbe_nid, const EVP_CIPHER *cipher, const char *pass,
+ int pass_len, uint8_t *salt, size_t salt_len,
+ int iterations, PKCS8_PRIV_KEY_INFO *p8inf) {
+ uint8_t *pass_raw = NULL;
+ size_t pass_raw_len = 0;
+ X509_SIG *ret;
+
+ if (pass) {
+ if (pass_len == -1) {
+ pass_len = strlen(pass);
+ }
+ if (!ascii_to_ucs2(pass, pass_len, &pass_raw, &pass_raw_len)) {
+ OPENSSL_PUT_ERROR(PKCS8, pkcs12_key_gen_asc, PKCS8_R_DECODE_ERROR);
+ return NULL;
+ }
+ }
+
+ ret = PKCS8_encrypt_pbe(pbe_nid, pass_raw, pass_raw_len,
+ salt, salt_len, iterations, p8inf);
+
+ if (pass_raw) {
+ OPENSSL_cleanse(pass_raw, pass_raw_len);
+ OPENSSL_free(pass_raw);
+ }
+ return ret;
+}
+
+X509_SIG *PKCS8_encrypt_pbe(int pbe_nid,
+ const uint8_t *pass_raw, size_t pass_raw_len,
+ uint8_t *salt, size_t salt_len,
+ int iterations, PKCS8_PRIV_KEY_INFO *p8inf) {
+ X509_SIG *pkcs8 = NULL;
+ X509_ALGOR *pbe;
+
+ pkcs8 = X509_SIG_new();
+ if (pkcs8 == NULL) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS8_encrypt_pbe, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ pbe = PKCS5_pbe_set(pbe_nid, iterations, salt, salt_len);
+ if (!pbe) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS8_encrypt_pbe, ERR_R_ASN1_LIB);
+ goto err;
+ }
+
+ X509_ALGOR_free(pkcs8->algor);
+ pkcs8->algor = pbe;
+ M_ASN1_OCTET_STRING_free(pkcs8->digest);
+ pkcs8->digest = pkcs12_item_i2d_encrypt(
+ pbe, ASN1_ITEM_rptr(PKCS8_PRIV_KEY_INFO), pass_raw, pass_raw_len, p8inf);
+ if (!pkcs8->digest) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS8_encrypt_pbe, PKCS8_R_ENCRYPT_ERROR);
+ goto err;
+ }
+
+ return pkcs8;
+
+err:
+ X509_SIG_free(pkcs8);
+ return NULL;
+}
+
+EVP_PKEY *EVP_PKCS82PKEY(PKCS8_PRIV_KEY_INFO *p8) {
+ EVP_PKEY *pkey = NULL;
+ ASN1_OBJECT *algoid;
+ char obj_tmp[80];
+
+ if (!PKCS8_pkey_get0(&algoid, NULL, NULL, NULL, p8))
+ return NULL;
+
+ pkey = EVP_PKEY_new();
+ if (pkey == NULL) {
+ OPENSSL_PUT_ERROR(PKCS8, EVP_PKCS82PKEY, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ if (!EVP_PKEY_set_type(pkey, OBJ_obj2nid(algoid))) {
+ OPENSSL_PUT_ERROR(PKCS8, EVP_PKCS82PKEY,
+ PKCS8_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM);
+ i2t_ASN1_OBJECT(obj_tmp, 80, algoid);
+ ERR_add_error_data(2, "TYPE=", obj_tmp);
+ goto error;
+ }
+
+ if (pkey->ameth->priv_decode) {
+ if (!pkey->ameth->priv_decode(pkey, p8)) {
+ OPENSSL_PUT_ERROR(PKCS8, EVP_PKCS82PKEY, PKCS8_R_PRIVATE_KEY_DECODE_ERROR);
+ goto error;
+ }
+ } else {
+ OPENSSL_PUT_ERROR(PKCS8, EVP_PKCS82PKEY, PKCS8_R_METHOD_NOT_SUPPORTED);
+ goto error;
+ }
+
+ return pkey;
+
+error:
+ EVP_PKEY_free(pkey);
+ return NULL;
+}
+
+PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(EVP_PKEY *pkey) {
+ PKCS8_PRIV_KEY_INFO *p8;
+
+ p8 = PKCS8_PRIV_KEY_INFO_new();
+ if (p8 == NULL) {
+ OPENSSL_PUT_ERROR(PKCS8, EVP_PKEY2PKCS8, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ p8->broken = PKCS8_OK;
+
+ if (pkey->ameth) {
+ if (pkey->ameth->priv_encode) {
+ if (!pkey->ameth->priv_encode(p8, pkey)) {
+ OPENSSL_PUT_ERROR(PKCS8, EVP_PKEY2PKCS8,
+ PKCS8_R_PRIVATE_KEY_ENCODE_ERROR);
+ goto error;
+ }
+ } else {
+ OPENSSL_PUT_ERROR(PKCS8, EVP_PKEY2PKCS8, PKCS8_R_METHOD_NOT_SUPPORTED);
+ goto error;
+ }
+ } else {
+ OPENSSL_PUT_ERROR(PKCS8, EVP_PKEY2PKCS8,
+ PKCS8_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM);
+ goto error;
+ }
+ return p8;
+
+error:
+ PKCS8_PRIV_KEY_INFO_free(p8);
+ return NULL;
+}
+
+struct pkcs12_context {
+ EVP_PKEY **out_key;
+ STACK_OF(X509) *out_certs;
+ uint8_t *password;
+ size_t password_len;
+};
+
+static int PKCS12_handle_content_info(CBS *content_info, unsigned depth,
+ struct pkcs12_context *ctx);
+
+/* PKCS12_handle_content_infos parses a series of PKCS#7 ContentInfos in a
+ * SEQUENCE. */
+static int PKCS12_handle_content_infos(CBS *content_infos,
+ unsigned depth,
+ struct pkcs12_context *ctx) {
+ uint8_t *der_bytes = NULL;
+ size_t der_len;
+ CBS in;
+ int ret = 0;
+
+ /* Generally we only expect depths 0 (the top level, with a
+ * pkcs7-encryptedData and a pkcs7-data) and depth 1 (the various PKCS#12
+ * bags). */
+ if (depth > 3) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_infos,
+ PKCS8_R_PKCS12_TOO_DEEPLY_NESTED);
+ return 0;
+ }
+
+ /* Although a BER->DER conversion is done at the beginning of |PKCS12_parse|,
+ * the ASN.1 data gets wrapped in OCTETSTRINGs and/or encrypted and the
+ * conversion cannot see through those wrappings. So each time we step
+ * through one we need to convert to DER again. */
+ if (!CBS_asn1_ber_to_der(content_infos, &der_bytes, &der_len)) {
+ return 0;
+ }
+
+ if (der_bytes != NULL) {
+ CBS_init(&in, der_bytes, der_len);
+ } else {
+ CBS_init(&in, CBS_data(content_infos), CBS_len(content_infos));
+ }
+
+ if (!CBS_get_asn1(&in, &in, CBS_ASN1_SEQUENCE)) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_infos,
+ PKCS8_R_BAD_PKCS12_DATA);
+ goto err;
+ }
+
+ while (CBS_len(&in) > 0) {
+ CBS content_info;
+ if (!CBS_get_asn1(&in, &content_info, CBS_ASN1_SEQUENCE)) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_infos,
+ PKCS8_R_BAD_PKCS12_DATA);
+ goto err;
+ }
+
+ if (!PKCS12_handle_content_info(&content_info, depth + 1, ctx)) {
+ goto err;
+ }
+ }
+
+ /* NSS includes additional data after the SEQUENCE, but it's an (unwrapped)
+ * copy of the same encrypted private key (with the same IV and
+ * ciphertext)! */
+
+ ret = 1;
+
+err:
+ if (der_bytes != NULL) {
+ OPENSSL_free(der_bytes);
+ }
+ return ret;
+}
+
+/* PKCS12_handle_content_info parses a single PKCS#7 ContentInfo element in a
+ * PKCS#12 structure. */
+static int PKCS12_handle_content_info(CBS *content_info, unsigned depth,
+ struct pkcs12_context *ctx) {
+ CBS content_type, wrapped_contents, contents, content_infos;
+ int nid, ret = 0;
+
+ if (!CBS_get_asn1(content_info, &content_type, CBS_ASN1_OBJECT) ||
+ !CBS_get_asn1(content_info, &wrapped_contents,
+ CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_BAD_PKCS12_DATA);
+ goto err;
+ }
+
+ nid = OBJ_cbs2nid(&content_type);
+ if (nid == NID_pkcs7_encrypted) {
+ /* See https://tools.ietf.org/html/rfc2315#section-13.
+ *
+ * PKCS#7 encrypted data inside a PKCS#12 structure is generally an
+ * encrypted certificate bag and it's generally encrypted with 40-bit
+ * RC2-CBC. */
+ CBS version_bytes, eci, contents_type, ai, encrypted_contents;
+ X509_ALGOR *algor = NULL;
+ const uint8_t *inp;
+ uint8_t *out;
+ size_t out_len;
+
+ if (!CBS_get_asn1(&wrapped_contents, &contents, CBS_ASN1_SEQUENCE) ||
+ !CBS_get_asn1(&contents, &version_bytes, CBS_ASN1_INTEGER) ||
+ /* EncryptedContentInfo, see
+ * https://tools.ietf.org/html/rfc2315#section-10.1 */
+ !CBS_get_asn1(&contents, &eci, CBS_ASN1_SEQUENCE) ||
+ !CBS_get_asn1(&eci, &contents_type, CBS_ASN1_OBJECT) ||
+ /* AlgorithmIdentifier, see
+ * https://tools.ietf.org/html/rfc5280#section-4.1.1.2 */
+ !CBS_get_asn1_element(&eci, &ai, CBS_ASN1_SEQUENCE) ||
+ !CBS_get_asn1(&eci, &encrypted_contents,
+ CBS_ASN1_CONTEXT_SPECIFIC | 0)) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info,
+ PKCS8_R_BAD_PKCS12_DATA);
+ goto err;
+ }
+
+ if (OBJ_cbs2nid(&contents_type) != NID_pkcs7_data) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info,
+ PKCS8_R_BAD_PKCS12_DATA);
+ goto err;
+ }
+
+ inp = CBS_data(&ai);
+ algor = d2i_X509_ALGOR(NULL, &inp, CBS_len(&ai));
+ if (algor == NULL) {
+ goto err;
+ }
+ if (inp != CBS_data(&ai) + CBS_len(&ai)) {
+ X509_ALGOR_free(algor);
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info,
+ PKCS8_R_BAD_PKCS12_DATA);
+ goto err;
+ }
+
+ if (!pbe_crypt(algor, ctx->password, ctx->password_len,
+ CBS_data(&encrypted_contents), CBS_len(&encrypted_contents),
+ &out, &out_len, 0 /* decrypt */)) {
+ X509_ALGOR_free(algor);
+ goto err;
+ }
+ X509_ALGOR_free(algor);
+
+ CBS_init(&content_infos, out, out_len);
+ ret = PKCS12_handle_content_infos(&content_infos, depth + 1, ctx);
+ OPENSSL_free(out);
+ } else if (nid == NID_pkcs7_data) {
+ CBS octet_string_contents;
+
+ if (!CBS_get_asn1(&wrapped_contents, &octet_string_contents,
+ CBS_ASN1_OCTETSTRING)) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info,
+ PKCS8_R_BAD_PKCS12_DATA);
+ goto err;
+ }
+
+ ret = PKCS12_handle_content_infos(&octet_string_contents, depth + 1, ctx);
+ } else if (nid == NID_pkcs8ShroudedKeyBag) {
+ /* See ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-12/pkcs-12v1.pdf, section
+ * 4.2.2. */
+ const uint8_t *inp = CBS_data(&wrapped_contents);
+ PKCS8_PRIV_KEY_INFO *pki = NULL;
+ X509_SIG *encrypted = NULL;
+
+ if (*ctx->out_key) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info,
+ PKCS8_R_MULTIPLE_PRIVATE_KEYS_IN_PKCS12);
+ goto err;
+ }
+
+ /* encrypted isn't actually an X.509 signature, but it has the same
+ * structure as one and so |X509_SIG| is reused to store it. */
+ encrypted = d2i_X509_SIG(NULL, &inp, CBS_len(&wrapped_contents));
+ if (encrypted == NULL) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info,
+ PKCS8_R_BAD_PKCS12_DATA);
+ goto err;
+ }
+ if (inp != CBS_data(&wrapped_contents) + CBS_len(&wrapped_contents)) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info,
+ PKCS8_R_BAD_PKCS12_DATA);
+ X509_SIG_free(encrypted);
+ goto err;
+ }
+
+ pki = PKCS8_decrypt_pbe(encrypted, ctx->password, ctx->password_len);
+ X509_SIG_free(encrypted);
+ if (pki == NULL) {
+ goto err;
+ }
+
+ *ctx->out_key = EVP_PKCS82PKEY(pki);
+ PKCS8_PRIV_KEY_INFO_free(pki);
+
+ if (ctx->out_key == NULL) {
+ goto err;
+ }
+ ret = 1;
+ } else if (nid == NID_certBag) {
+ CBS cert_bag, cert_type, wrapped_cert, cert;
+
+ if (!CBS_get_asn1(&wrapped_contents, &cert_bag, CBS_ASN1_SEQUENCE) ||
+ !CBS_get_asn1(&cert_bag, &cert_type, CBS_ASN1_OBJECT) ||
+ !CBS_get_asn1(&cert_bag, &wrapped_cert,
+ CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
+ !CBS_get_asn1(&wrapped_cert, &cert, CBS_ASN1_OCTETSTRING)) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info,
+ PKCS8_R_BAD_PKCS12_DATA);
+ goto err;
+ }
+
+ if (OBJ_cbs2nid(&cert_type) == NID_x509Certificate) {
+ const uint8_t *inp = CBS_data(&cert);
+ X509 *x509 = d2i_X509(NULL, &inp, CBS_len(&cert));
+ if (!x509) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info,
+ PKCS8_R_BAD_PKCS12_DATA);
+ goto err;
+ }
+ if (inp != CBS_data(&cert) + CBS_len(&cert)) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info,
+ PKCS8_R_BAD_PKCS12_DATA);
+ X509_free(x509);
+ goto err;
+ }
+
+ if (0 == sk_X509_push(ctx->out_certs, x509)) {
+ X509_free(x509);
+ goto err;
+ }
+ }
+ ret = 1;
+ } else {
+ /* Unknown element type - ignore it. */
+ ret = 1;
+ }
+
+err:
+ return ret;
+}
+
+int PKCS12_get_key_and_certs(EVP_PKEY **out_key, STACK_OF(X509) *out_certs,
+ CBS *ber_in, const char *password) {
+ uint8_t *der_bytes = NULL;
+ size_t der_len;
+ CBS in, pfx, mac_data, authsafe, content_type, wrapped_authsafes, authsafes;
+ uint64_t version;
+ int ret = 0;
+ struct pkcs12_context ctx;
+ const size_t original_out_certs_len = sk_X509_num(out_certs);
+
+ /* The input may be in BER format. */
+ if (!CBS_asn1_ber_to_der(ber_in, &der_bytes, &der_len)) {
+ return 0;
+ }
+ if (der_bytes != NULL) {
+ CBS_init(&in, der_bytes, der_len);
+ } else {
+ CBS_init(&in, CBS_data(ber_in), CBS_len(ber_in));
+ }
+
+ *out_key = NULL;
+ memset(&ctx, 0, sizeof(ctx));
+
+ /* See ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-12/pkcs-12v1.pdf, section
+ * four. */
+ if (!CBS_get_asn1(&in, &pfx, CBS_ASN1_SEQUENCE) ||
+ CBS_len(&in) != 0 ||
+ !CBS_get_asn1_uint64(&pfx, &version)) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_BAD_PKCS12_DATA);
+ goto err;
+ }
+
+ if (version < 3) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_BAD_PKCS12_VERSION);
+ goto err;
+ }
+
+ if (!CBS_get_asn1(&pfx, &authsafe, CBS_ASN1_SEQUENCE)) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_BAD_PKCS12_DATA);
+ goto err;
+ }
+
+ if (CBS_len(&pfx) == 0) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_MISSING_MAC);
+ goto err;
+ }
+
+ if (!CBS_get_asn1(&pfx, &mac_data, CBS_ASN1_SEQUENCE)) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_BAD_PKCS12_DATA);
+ goto err;
+ }
+
+ /* authsafe is a PKCS#7 ContentInfo. See
+ * https://tools.ietf.org/html/rfc2315#section-7. */
+ if (!CBS_get_asn1(&authsafe, &content_type, CBS_ASN1_OBJECT) ||
+ !CBS_get_asn1(&authsafe, &wrapped_authsafes,
+ CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_BAD_PKCS12_DATA);
+ goto err;
+ }
+
+ /* The content type can either be |NID_pkcs7_data| or |NID_pkcs7_signed|. The
+ * latter indicates that it's signed by a public key, which isn't
+ * supported. */
+ if (OBJ_cbs2nid(&content_type) != NID_pkcs7_data) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse,
+ PKCS8_R_PKCS12_PUBLIC_KEY_INTEGRITY_NOT_SUPPORTED);
+ goto err;
+ }
+
+ if (!CBS_get_asn1(&wrapped_authsafes, &authsafes, CBS_ASN1_OCTETSTRING)) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_BAD_PKCS12_DATA);
+ goto err;
+ }
+
+ ctx.out_key = out_key;
+ ctx.out_certs = out_certs;
+ if (!ascii_to_ucs2(password, strlen(password), &ctx.password,
+ &ctx.password_len)) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_DECODE_ERROR);
+ goto err;
+ }
+
+ /* Verify the MAC. */
+ {
+ CBS mac, hash_type_seq, hash_oid, salt, expected_mac;
+ uint64_t iterations;
+ int hash_nid;
+ const EVP_MD *md;
+ uint8_t hmac_key[EVP_MAX_MD_SIZE];
+ uint8_t hmac[EVP_MAX_MD_SIZE];
+ unsigned hmac_len;
+
+ if (!CBS_get_asn1(&mac_data, &mac, CBS_ASN1_SEQUENCE) ||
+ !CBS_get_asn1(&mac, &hash_type_seq, CBS_ASN1_SEQUENCE) ||
+ !CBS_get_asn1(&hash_type_seq, &hash_oid, CBS_ASN1_OBJECT) ||
+ !CBS_get_asn1(&mac, &expected_mac, CBS_ASN1_OCTETSTRING) ||
+ !CBS_get_asn1(&mac_data, &salt, CBS_ASN1_OCTETSTRING)) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_BAD_PKCS12_DATA);
+ goto err;
+ }
+
+ /* The iteration count is optional and the default is one. */
+ iterations = 1;
+ if (CBS_len(&mac_data) > 0) {
+ if (!CBS_get_asn1_uint64(&mac_data, &iterations) ||
+ iterations > INT_MAX) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_BAD_PKCS12_DATA);
+ goto err;
+ }
+ }
+
+ hash_nid = OBJ_cbs2nid(&hash_oid);
+ if (hash_nid == NID_undef ||
+ (md = EVP_get_digestbynid(hash_nid)) == NULL) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_UNKNOWN_HASH);
+ goto err;
+ }
+
+ if (!pkcs12_key_gen_raw(ctx.password, ctx.password_len, CBS_data(&salt),
+ CBS_len(&salt), PKCS12_MAC_ID, iterations,
+ EVP_MD_size(md), hmac_key, md)) {
+ goto err;
+ }
+
+ if (NULL == HMAC(md, hmac_key, EVP_MD_size(md), CBS_data(&authsafes),
+ CBS_len(&authsafes), hmac, &hmac_len)) {
+ goto err;
+ }
+
+ if (!CBS_mem_equal(&expected_mac, hmac, hmac_len)) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_INCORRECT_PASSWORD);
+ goto err;
+ }
+ }
+
+ /* authsafes contains a series of PKCS#7 ContentInfos. */
+ if (!PKCS12_handle_content_infos(&authsafes, 0, &ctx)) {
+ goto err;
+ }
+
+ ret = 1;
+
+err:
+ if (ctx.password) {
+ OPENSSL_free(ctx.password);
+ }
+ if (der_bytes) {
+ OPENSSL_free(der_bytes);
+ }
+ if (!ret) {
+ if (*out_key) {
+ EVP_PKEY_free(*out_key);
+ *out_key = NULL;
+ }
+ while (sk_X509_num(out_certs) > original_out_certs_len) {
+ X509 *x509 = sk_X509_pop(out_certs);
+ X509_free(x509);
+ }
+ }
+
+ return ret;
+}
+
+void PKCS12_PBE_add(void) {}
+
+struct pkcs12_st {
+ uint8_t *ber_bytes;
+ size_t ber_len;
+};
+
+PKCS12* d2i_PKCS12(PKCS12 **out_p12, const uint8_t **ber_bytes, size_t ber_len) {
+ PKCS12 *p12;
+
+ /* out_p12 must be NULL because we don't export the PKCS12 structure. */
+ assert(out_p12 == NULL);
+
+ p12 = OPENSSL_malloc(sizeof(PKCS12));
+ if (!p12) {
+ return NULL;
+ }
+
+ p12->ber_bytes = OPENSSL_malloc(ber_len);
+ if (!p12->ber_bytes) {
+ OPENSSL_free(p12);
+ return NULL;
+ }
+
+ memcpy(p12->ber_bytes, *ber_bytes, ber_len);
+ p12->ber_len = ber_len;
+ *ber_bytes += ber_len;
+
+ return p12;
+}
+
+PKCS12* d2i_PKCS12_bio(BIO *bio, PKCS12 **out_p12) {
+ size_t used = 0;
+ BUF_MEM *buf;
+ const uint8_t *dummy;
+ static const size_t kMaxSize = 256 * 1024;
+ PKCS12 *ret = NULL;
+
+ buf = BUF_MEM_new();
+ if (buf == NULL) {
+ return NULL;
+ }
+ if (BUF_MEM_grow(buf, 8192) == 0) {
+ goto out;
+ }
+
+ for (;;) {
+ int n = BIO_read(bio, &buf->data[used], buf->length - used);
+ if (n < 0) {
+ goto out;
+ }
+
+ if (n == 0) {
+ break;
+ }
+ used += n;
+
+ if (used < buf->length) {
+ continue;
+ }
+
+ if (buf->length > kMaxSize ||
+ BUF_MEM_grow(buf, buf->length * 2) == 0) {
+ goto out;
+ }
+ }
+
+ dummy = (uint8_t*) buf->data;
+ ret = d2i_PKCS12(out_p12, &dummy, used);
+
+out:
+ BUF_MEM_free(buf);
+ return ret;
+}
+
+PKCS12* d2i_PKCS12_fp(FILE *fp, PKCS12 **out_p12) {
+ BIO *bio;
+ PKCS12 *ret;
+
+ bio = BIO_new_fp(fp, 0 /* don't take ownership */);
+ if (!bio) {
+ return NULL;
+ }
+
+ ret = d2i_PKCS12_bio(bio, out_p12);
+ BIO_free(bio);
+ return ret;
+}
+
+int PKCS12_parse(const PKCS12 *p12, const char *password, EVP_PKEY **out_pkey,
+ X509 **out_cert, STACK_OF(X509) **out_ca_certs) {
+ CBS ber_bytes;
+ STACK_OF(X509) *ca_certs = NULL;
+ char ca_certs_alloced = 0;
+
+ if (out_ca_certs != NULL && *out_ca_certs != NULL) {
+ ca_certs = *out_ca_certs;
+ }
+
+ if (!ca_certs) {
+ ca_certs = sk_X509_new_null();
+ if (ca_certs == NULL) {
+ return 0;
+ }
+ ca_certs_alloced = 1;
+ }
+
+ CBS_init(&ber_bytes, p12->ber_bytes, p12->ber_len);
+ if (!PKCS12_get_key_and_certs(out_pkey, ca_certs, &ber_bytes, password)) {
+ if (ca_certs_alloced) {
+ sk_X509_free(ca_certs);
+ }
+ return 0;
+ }
+
+ *out_cert = NULL;
+ if (sk_X509_num(ca_certs) > 0) {
+ *out_cert = sk_X509_shift(ca_certs);
+ }
+
+ if (out_ca_certs) {
+ *out_ca_certs = ca_certs;
+ } else {
+ sk_X509_pop_free(ca_certs, X509_free);
+ }
+
+ return 1;
+}
+
+void PKCS12_free(PKCS12 *p12) {
+ OPENSSL_free(p12->ber_bytes);
+ OPENSSL_free(p12);
+}
diff --git a/src/crypto/pkcs8/pkcs8_error.c b/src/crypto/pkcs8/pkcs8_error.c
new file mode 100644
index 0000000..3041658
--- /dev/null
+++ b/src/crypto/pkcs8/pkcs8_error.c
@@ -0,0 +1,68 @@
+/* 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 <openssl/err.h>
+
+#include <openssl/pkcs8.h>
+
+const ERR_STRING_DATA PKCS8_error_string_data[] = {
+ {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_EVP_PKCS82PKEY, 0), "EVP_PKCS82PKEY"},
+ {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_EVP_PKEY2PKCS8, 0), "EVP_PKEY2PKCS8"},
+ {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_PKCS12_get_key_and_certs, 0), "PKCS12_get_key_and_certs"},
+ {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_PKCS12_handle_content_info, 0), "PKCS12_handle_content_info"},
+ {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_PKCS12_handle_content_infos, 0), "PKCS12_handle_content_infos"},
+ {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_PKCS12_parse, 0), "PKCS12_parse"},
+ {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_PKCS5_pbe2_set_iv, 0), "PKCS5_pbe2_set_iv"},
+ {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_PKCS5_pbe_set, 0), "PKCS5_pbe_set"},
+ {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_PKCS5_pbe_set0_algor, 0), "PKCS5_pbe_set0_algor"},
+ {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_PKCS5_pbkdf2_set, 0), "PKCS5_pbkdf2_set"},
+ {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_PKCS8_decrypt, 0), "PKCS8_decrypt"},
+ {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_PKCS8_encrypt, 0), "PKCS8_encrypt"},
+ {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_PKCS8_encrypt_pbe, 0), "PKCS8_encrypt_pbe"},
+ {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_pbe_cipher_init, 0), "pbe_cipher_init"},
+ {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_pbe_crypt, 0), "pbe_crypt"},
+ {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_pkcs12_item_decrypt_d2i, 0), "pkcs12_item_decrypt_d2i"},
+ {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_pkcs12_item_i2d_encrypt, 0), "pkcs12_item_i2d_encrypt"},
+ {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_pkcs12_key_gen_asc, 0), "pkcs12_key_gen_asc"},
+ {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_pkcs12_key_gen_raw, 0), "pkcs12_key_gen_raw"},
+ {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_pkcs12_key_gen_uni, 0), "pkcs12_key_gen_uni"},
+ {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_pkcs12_pbe_keyivgen, 0), "pkcs12_pbe_keyivgen"},
+ {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_BAD_MAC), "BAD_MAC"},
+ {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_BAD_PKCS12_DATA), "BAD_PKCS12_DATA"},
+ {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_BAD_PKCS12_VERSION), "BAD_PKCS12_VERSION"},
+ {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER), "CIPHER_HAS_NO_OBJECT_IDENTIFIER"},
+ {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_CRYPT_ERROR), "CRYPT_ERROR"},
+ {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_DECODE_ERROR), "DECODE_ERROR"},
+ {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_ENCODE_ERROR), "ENCODE_ERROR"},
+ {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_ENCRYPT_ERROR), "ENCRYPT_ERROR"},
+ {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_ERROR_SETTING_CIPHER_PARAMS), "ERROR_SETTING_CIPHER_PARAMS"},
+ {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_INCORRECT_PASSWORD), "INCORRECT_PASSWORD"},
+ {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_KEYGEN_FAILURE), "KEYGEN_FAILURE"},
+ {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_KEY_GEN_ERROR), "KEY_GEN_ERROR"},
+ {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_METHOD_NOT_SUPPORTED), "METHOD_NOT_SUPPORTED"},
+ {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_MISSING_MAC), "MISSING_MAC"},
+ {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_MULTIPLE_PRIVATE_KEYS_IN_PKCS12), "MULTIPLE_PRIVATE_KEYS_IN_PKCS12"},
+ {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_PKCS12_PUBLIC_KEY_INTEGRITY_NOT_SUPPORTED), "PKCS12_PUBLIC_KEY_INTEGRITY_NOT_SUPPORTED"},
+ {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_PKCS12_TOO_DEEPLY_NESTED), "PKCS12_TOO_DEEPLY_NESTED"},
+ {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_PRIVATE_KEY_DECODE_ERROR), "PRIVATE_KEY_DECODE_ERROR"},
+ {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_PRIVATE_KEY_ENCODE_ERROR), "PRIVATE_KEY_ENCODE_ERROR"},
+ {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_TOO_LONG), "TOO_LONG"},
+ {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_UNKNOWN_ALGORITHM), "UNKNOWN_ALGORITHM"},
+ {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_UNKNOWN_CIPHER), "UNKNOWN_CIPHER"},
+ {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_UNKNOWN_CIPHER_ALGORITHM), "UNKNOWN_CIPHER_ALGORITHM"},
+ {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_UNKNOWN_DIGEST), "UNKNOWN_DIGEST"},
+ {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_UNKNOWN_HASH), "UNKNOWN_HASH"},
+ {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM), "UNSUPPORTED_PRIVATE_KEY_ALGORITHM"},
+ {0, NULL},
+};
diff --git a/src/crypto/poly1305/CMakeLists.txt b/src/crypto/poly1305/CMakeLists.txt
new file mode 100644
index 0000000..bb0c1e4
--- /dev/null
+++ b/src/crypto/poly1305/CMakeLists.txt
@@ -0,0 +1,21 @@
+include_directories(. .. ../../include)
+
+if (${ARCH} STREQUAL "arm")
+ set(
+ POLY1305_ARCH_SOURCES
+
+ poly1305_arm_asm.S
+ )
+endif()
+
+add_library(
+ poly1305
+
+ OBJECT
+
+ poly1305.c
+ poly1305_arm.c
+ poly1305_vec.c
+
+ ${POLY1305_ARCH_SOURCES}
+)
diff --git a/src/crypto/poly1305/poly1305.c b/src/crypto/poly1305/poly1305.c
new file mode 100644
index 0000000..bf5cd5e
--- /dev/null
+++ b/src/crypto/poly1305/poly1305.c
@@ -0,0 +1,323 @@
+/* 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. */
+
+/* This implementation of poly1305 is by Andrew Moon
+ * (https://github.com/floodyberry/poly1305-donna) and released as public
+ * domain. */
+
+#include <openssl/poly1305.h>
+
+#include <string.h>
+
+#include <openssl/cpu.h>
+
+
+#if defined(OPENSSL_WINDOWS) || !defined(OPENSSL_X86_64)
+
+#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64) || defined(OPENSSL_ARM)
+/* We can assume little-endian. */
+static uint32_t U8TO32_LE(const uint8_t *m) {
+ uint32_t r;
+ memcpy(&r, m, sizeof(r));
+ return r;
+}
+
+static void U32TO8_LE(uint8_t *m, uint32_t v) { memcpy(m, &v, sizeof(v)); }
+#else
+static uint32_t U8TO32_LE(const uint8_t *m) {
+ return (uint32_t)m[0] | (uint32_t)m[1] << 8 | (uint32_t)m[2] << 16 |
+ (uint32_t)m[3] << 24;
+}
+
+static void U32TO8_LE(uint8_t *m, uint32_t v) {
+ m[0] = v;
+ m[1] = v >> 8;
+ m[2] = v >> 16;
+ m[3] = v >> 24;
+}
+#endif
+
+#if defined(OPENSSL_ARM) && !defined(OPENSSL_NO_ASM)
+void CRYPTO_poly1305_init_neon(poly1305_state *state, const uint8_t key[32]);
+
+void CRYPTO_poly1305_update_neon(poly1305_state *state, const uint8_t *in,
+ size_t in_len);
+
+void CRYPTO_poly1305_finish_neon(poly1305_state *state, uint8_t mac[16]);
+#endif
+
+static uint64_t mul32x32_64(uint32_t a, uint32_t b) { return (uint64_t)a * b; }
+
+struct poly1305_state_st {
+ uint32_t r0, r1, r2, r3, r4;
+ uint32_t s1, s2, s3, s4;
+ uint32_t h0, h1, h2, h3, h4;
+ uint8_t buf[16];
+ unsigned int buf_used;
+ uint8_t key[16];
+};
+
+/* poly1305_blocks updates |state| given some amount of input data. This
+ * function may only be called with a |len| that is not a multiple of 16 at the
+ * end of the data. Otherwise the input must be buffered into 16 byte blocks. */
+static void poly1305_update(struct poly1305_state_st *state, const uint8_t *in,
+ size_t len) {
+ uint32_t t0, t1, t2, t3;
+ uint64_t t[5];
+ uint32_t b;
+ uint64_t c;
+ size_t j;
+ uint8_t mp[16];
+
+ if (len < 16) {
+ goto poly1305_donna_atmost15bytes;
+ }
+
+poly1305_donna_16bytes:
+ t0 = U8TO32_LE(in);
+ t1 = U8TO32_LE(in + 4);
+ t2 = U8TO32_LE(in + 8);
+ t3 = U8TO32_LE(in + 12);
+
+ in += 16;
+ len -= 16;
+
+ state->h0 += t0 & 0x3ffffff;
+ state->h1 += ((((uint64_t)t1 << 32) | t0) >> 26) & 0x3ffffff;
+ state->h2 += ((((uint64_t)t2 << 32) | t1) >> 20) & 0x3ffffff;
+ state->h3 += ((((uint64_t)t3 << 32) | t2) >> 14) & 0x3ffffff;
+ state->h4 += (t3 >> 8) | (1 << 24);
+
+poly1305_donna_mul:
+ t[0] = mul32x32_64(state->h0, state->r0) + mul32x32_64(state->h1, state->s4) +
+ mul32x32_64(state->h2, state->s3) + mul32x32_64(state->h3, state->s2) +
+ mul32x32_64(state->h4, state->s1);
+ t[1] = mul32x32_64(state->h0, state->r1) + mul32x32_64(state->h1, state->r0) +
+ mul32x32_64(state->h2, state->s4) + mul32x32_64(state->h3, state->s3) +
+ mul32x32_64(state->h4, state->s2);
+ t[2] = mul32x32_64(state->h0, state->r2) + mul32x32_64(state->h1, state->r1) +
+ mul32x32_64(state->h2, state->r0) + mul32x32_64(state->h3, state->s4) +
+ mul32x32_64(state->h4, state->s3);
+ t[3] = mul32x32_64(state->h0, state->r3) + mul32x32_64(state->h1, state->r2) +
+ mul32x32_64(state->h2, state->r1) + mul32x32_64(state->h3, state->r0) +
+ mul32x32_64(state->h4, state->s4);
+ t[4] = mul32x32_64(state->h0, state->r4) + mul32x32_64(state->h1, state->r3) +
+ mul32x32_64(state->h2, state->r2) + mul32x32_64(state->h3, state->r1) +
+ mul32x32_64(state->h4, state->r0);
+
+ state->h0 = (uint32_t)t[0] & 0x3ffffff;
+ c = (t[0] >> 26);
+ t[1] += c;
+ state->h1 = (uint32_t)t[1] & 0x3ffffff;
+ b = (uint32_t)(t[1] >> 26);
+ t[2] += b;
+ state->h2 = (uint32_t)t[2] & 0x3ffffff;
+ b = (uint32_t)(t[2] >> 26);
+ t[3] += b;
+ state->h3 = (uint32_t)t[3] & 0x3ffffff;
+ b = (uint32_t)(t[3] >> 26);
+ t[4] += b;
+ state->h4 = (uint32_t)t[4] & 0x3ffffff;
+ b = (uint32_t)(t[4] >> 26);
+ state->h0 += b * 5;
+
+ if (len >= 16)
+ goto poly1305_donna_16bytes;
+
+/* final bytes */
+poly1305_donna_atmost15bytes:
+ if (!len)
+ return;
+
+ for (j = 0; j < len; j++)
+ mp[j] = in[j];
+ mp[j++] = 1;
+ for (; j < 16; j++)
+ mp[j] = 0;
+ len = 0;
+
+ t0 = U8TO32_LE(mp + 0);
+ t1 = U8TO32_LE(mp + 4);
+ t2 = U8TO32_LE(mp + 8);
+ t3 = U8TO32_LE(mp + 12);
+
+ state->h0 += t0 & 0x3ffffff;
+ state->h1 += ((((uint64_t)t1 << 32) | t0) >> 26) & 0x3ffffff;
+ state->h2 += ((((uint64_t)t2 << 32) | t1) >> 20) & 0x3ffffff;
+ state->h3 += ((((uint64_t)t3 << 32) | t2) >> 14) & 0x3ffffff;
+ state->h4 += (t3 >> 8);
+
+ goto poly1305_donna_mul;
+}
+
+void CRYPTO_poly1305_init(poly1305_state *statep, const uint8_t key[32]) {
+ struct poly1305_state_st *state = (struct poly1305_state_st *)statep;
+ uint32_t t0, t1, t2, t3;
+
+#if defined(OPENSSL_ARM) && !defined(OPENSSL_NO_ASM)
+ if (CRYPTO_is_NEON_functional()) {
+ CRYPTO_poly1305_init_neon(statep, key);
+ return;
+ }
+#endif
+
+ t0 = U8TO32_LE(key + 0);
+ t1 = U8TO32_LE(key + 4);
+ t2 = U8TO32_LE(key + 8);
+ t3 = U8TO32_LE(key + 12);
+
+ /* precompute multipliers */
+ state->r0 = t0 & 0x3ffffff;
+ t0 >>= 26;
+ t0 |= t1 << 6;
+ state->r1 = t0 & 0x3ffff03;
+ t1 >>= 20;
+ t1 |= t2 << 12;
+ state->r2 = t1 & 0x3ffc0ff;
+ t2 >>= 14;
+ t2 |= t3 << 18;
+ state->r3 = t2 & 0x3f03fff;
+ t3 >>= 8;
+ state->r4 = t3 & 0x00fffff;
+
+ state->s1 = state->r1 * 5;
+ state->s2 = state->r2 * 5;
+ state->s3 = state->r3 * 5;
+ state->s4 = state->r4 * 5;
+
+ /* init state */
+ state->h0 = 0;
+ state->h1 = 0;
+ state->h2 = 0;
+ state->h3 = 0;
+ state->h4 = 0;
+
+ state->buf_used = 0;
+ memcpy(state->key, key + 16, sizeof(state->key));
+}
+
+void CRYPTO_poly1305_update(poly1305_state *statep, const uint8_t *in,
+ size_t in_len) {
+ unsigned int i;
+ struct poly1305_state_st *state = (struct poly1305_state_st *)statep;
+
+#if defined(OPENSSL_ARM) && !defined(OPENSSL_NO_ASM)
+ if (CRYPTO_is_NEON_functional()) {
+ CRYPTO_poly1305_update_neon(statep, in, in_len);
+ return;
+ }
+#endif
+
+ if (state->buf_used) {
+ unsigned int todo = 16 - state->buf_used;
+ if (todo > in_len)
+ todo = in_len;
+ for (i = 0; i < todo; i++)
+ state->buf[state->buf_used + i] = in[i];
+ state->buf_used += todo;
+ in_len -= todo;
+ in += todo;
+
+ if (state->buf_used == 16) {
+ poly1305_update(state, state->buf, 16);
+ state->buf_used = 0;
+ }
+ }
+
+ if (in_len >= 16) {
+ size_t todo = in_len & ~0xf;
+ poly1305_update(state, in, todo);
+ in += todo;
+ in_len &= 0xf;
+ }
+
+ if (in_len) {
+ for (i = 0; i < in_len; i++)
+ state->buf[i] = in[i];
+ state->buf_used = in_len;
+ }
+}
+
+void CRYPTO_poly1305_finish(poly1305_state *statep, uint8_t mac[16]) {
+ struct poly1305_state_st *state = (struct poly1305_state_st *)statep;
+ uint64_t f0, f1, f2, f3;
+ uint32_t g0, g1, g2, g3, g4;
+ uint32_t b, nb;
+
+#if defined(OPENSSL_ARM) && !defined(OPENSSL_NO_ASM)
+ if (CRYPTO_is_NEON_functional()) {
+ CRYPTO_poly1305_finish_neon(statep, mac);
+ return;
+ }
+#endif
+
+ if (state->buf_used)
+ poly1305_update(state, state->buf, state->buf_used);
+
+ b = state->h0 >> 26;
+ state->h0 = state->h0 & 0x3ffffff;
+ state->h1 += b;
+ b = state->h1 >> 26;
+ state->h1 = state->h1 & 0x3ffffff;
+ state->h2 += b;
+ b = state->h2 >> 26;
+ state->h2 = state->h2 & 0x3ffffff;
+ state->h3 += b;
+ b = state->h3 >> 26;
+ state->h3 = state->h3 & 0x3ffffff;
+ state->h4 += b;
+ b = state->h4 >> 26;
+ state->h4 = state->h4 & 0x3ffffff;
+ state->h0 += b * 5;
+
+ g0 = state->h0 + 5;
+ b = g0 >> 26;
+ g0 &= 0x3ffffff;
+ g1 = state->h1 + b;
+ b = g1 >> 26;
+ g1 &= 0x3ffffff;
+ g2 = state->h2 + b;
+ b = g2 >> 26;
+ g2 &= 0x3ffffff;
+ g3 = state->h3 + b;
+ b = g3 >> 26;
+ g3 &= 0x3ffffff;
+ g4 = state->h4 + b - (1 << 26);
+
+ b = (g4 >> 31) - 1;
+ nb = ~b;
+ state->h0 = (state->h0 & nb) | (g0 & b);
+ state->h1 = (state->h1 & nb) | (g1 & b);
+ state->h2 = (state->h2 & nb) | (g2 & b);
+ state->h3 = (state->h3 & nb) | (g3 & b);
+ state->h4 = (state->h4 & nb) | (g4 & b);
+
+ f0 = ((state->h0) | (state->h1 << 26)) + (uint64_t)U8TO32_LE(&state->key[0]);
+ f1 = ((state->h1 >> 6) | (state->h2 << 20)) +
+ (uint64_t)U8TO32_LE(&state->key[4]);
+ f2 = ((state->h2 >> 12) | (state->h3 << 14)) +
+ (uint64_t)U8TO32_LE(&state->key[8]);
+ f3 = ((state->h3 >> 18) | (state->h4 << 8)) +
+ (uint64_t)U8TO32_LE(&state->key[12]);
+
+ U32TO8_LE(&mac[0], f0);
+ f1 += (f0 >> 32);
+ U32TO8_LE(&mac[4], f1);
+ f2 += (f1 >> 32);
+ U32TO8_LE(&mac[8], f2);
+ f3 += (f2 >> 32);
+ U32TO8_LE(&mac[12], f3);
+}
+
+#endif /* OPENSSL_WINDOWS || !OPENSSL_X86_64 */
diff --git a/src/crypto/poly1305/poly1305_arm.c b/src/crypto/poly1305/poly1305_arm.c
new file mode 100644
index 0000000..61ebec5
--- /dev/null
+++ b/src/crypto/poly1305/poly1305_arm.c
@@ -0,0 +1,290 @@
+/* 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. */
+
+/* This implementation was taken from the public domain, neon2 version in
+ * SUPERCOP by D. J. Bernstein and Peter Schwabe. */
+
+#include <openssl/poly1305.h>
+
+#if defined(OPENSSL_ARM) && !defined(OPENSSL_NO_ASM)
+
+#include <string.h>
+
+
+typedef struct {
+ uint32_t v[12]; /* for alignment; only using 10 */
+} fe1305x2;
+
+#define addmulmod openssl_poly1305_neon2_addmulmod
+#define blocks openssl_poly1305_neon2_blocks
+
+extern void addmulmod(fe1305x2 *r, const fe1305x2 *x, const fe1305x2 *y,
+ const fe1305x2 *c);
+
+extern int blocks(fe1305x2 *h, const fe1305x2 *precomp, const uint8_t *in,
+ unsigned int inlen);
+
+static void freeze(fe1305x2 *r) {
+ int i;
+
+ uint32_t x0 = r->v[0];
+ uint32_t x1 = r->v[2];
+ uint32_t x2 = r->v[4];
+ uint32_t x3 = r->v[6];
+ uint32_t x4 = r->v[8];
+ uint32_t y0;
+ uint32_t y1;
+ uint32_t y2;
+ uint32_t y3;
+ uint32_t y4;
+ uint32_t swap;
+
+ for (i = 0; i < 3; ++i) {
+ x1 += x0 >> 26;
+ x0 &= 0x3ffffff;
+ x2 += x1 >> 26;
+ x1 &= 0x3ffffff;
+ x3 += x2 >> 26;
+ x2 &= 0x3ffffff;
+ x4 += x3 >> 26;
+ x3 &= 0x3ffffff;
+ x0 += 5 * (x4 >> 26);
+ x4 &= 0x3ffffff;
+ }
+
+ y0 = x0 + 5;
+ y1 = x1 + (y0 >> 26);
+ y0 &= 0x3ffffff;
+ y2 = x2 + (y1 >> 26);
+ y1 &= 0x3ffffff;
+ y3 = x3 + (y2 >> 26);
+ y2 &= 0x3ffffff;
+ y4 = x4 + (y3 >> 26);
+ y3 &= 0x3ffffff;
+ swap = -(y4 >> 26);
+ y4 &= 0x3ffffff;
+
+ y0 ^= x0;
+ y1 ^= x1;
+ y2 ^= x2;
+ y3 ^= x3;
+ y4 ^= x4;
+
+ y0 &= swap;
+ y1 &= swap;
+ y2 &= swap;
+ y3 &= swap;
+ y4 &= swap;
+
+ y0 ^= x0;
+ y1 ^= x1;
+ y2 ^= x2;
+ y3 ^= x3;
+ y4 ^= x4;
+
+ r->v[0] = y0;
+ r->v[2] = y1;
+ r->v[4] = y2;
+ r->v[6] = y3;
+ r->v[8] = y4;
+}
+
+static void fe1305x2_tobytearray(uint8_t *r, fe1305x2 *x) {
+ uint32_t x0 = x->v[0];
+ uint32_t x1 = x->v[2];
+ uint32_t x2 = x->v[4];
+ uint32_t x3 = x->v[6];
+ uint32_t x4 = x->v[8];
+
+ x1 += x0 >> 26;
+ x0 &= 0x3ffffff;
+ x2 += x1 >> 26;
+ x1 &= 0x3ffffff;
+ x3 += x2 >> 26;
+ x2 &= 0x3ffffff;
+ x4 += x3 >> 26;
+ x3 &= 0x3ffffff;
+
+ *(uint32_t *)r = x0 + (x1 << 26);
+ *(uint32_t *)(r + 4) = (x1 >> 6) + (x2 << 20);
+ *(uint32_t *)(r + 8) = (x2 >> 12) + (x3 << 14);
+ *(uint32_t *)(r + 12) = (x3 >> 18) + (x4 << 8);
+}
+
+/* load32 exists to avoid breaking strict aliasing rules in
+ * fe1305x2_frombytearray. */
+static uint32_t load32(uint8_t *t) {
+ uint32_t tmp;
+ memcpy(&tmp, t, sizeof(tmp));
+ return tmp;
+}
+
+static void fe1305x2_frombytearray(fe1305x2 *r, const uint8_t *x,
+ unsigned long long xlen) {
+ int i;
+ uint8_t t[17];
+
+ for (i = 0; (i < 16) && (i < xlen); i++)
+ t[i] = x[i];
+ xlen -= i;
+ x += i;
+ t[i++] = 1;
+ for (; i < 17; i++)
+ t[i] = 0;
+
+ r->v[0] = 0x3ffffff & load32(t);
+ r->v[2] = 0x3ffffff & (load32(t + 3) >> 2);
+ r->v[4] = 0x3ffffff & (load32(t + 6) >> 4);
+ r->v[6] = 0x3ffffff & (load32(t + 9) >> 6);
+ r->v[8] = load32(t + 13);
+
+ if (xlen) {
+ for (i = 0; (i < 16) && (i < xlen); i++)
+ t[i] = x[i];
+ t[i++] = 1;
+ for (; i < 17; i++)
+ t[i] = 0;
+
+ r->v[1] = 0x3ffffff & load32(t);
+ r->v[3] = 0x3ffffff & (load32(t + 3) >> 2);
+ r->v[5] = 0x3ffffff & (load32(t + 6) >> 4);
+ r->v[7] = 0x3ffffff & (load32(t + 9) >> 6);
+ r->v[9] = load32(t + 13);
+ } else
+ r->v[1] = r->v[3] = r->v[5] = r->v[7] = r->v[9] = 0;
+}
+
+static const fe1305x2 zero __attribute__((aligned(16)));
+
+struct poly1305_state_st {
+ uint8_t data[sizeof(fe1305x2[5]) + 128];
+ uint8_t buf[32];
+ unsigned int buf_used;
+ uint8_t key[16];
+};
+
+void CRYPTO_poly1305_init_neon(poly1305_state *state, const uint8_t key[32]) {
+ struct poly1305_state_st *st = (struct poly1305_state_st *)(state);
+ fe1305x2 *const r = (fe1305x2 *)(st->data + (15 & (-(int)st->data)));
+ fe1305x2 *const h = r + 1;
+ fe1305x2 *const c = h + 1;
+ fe1305x2 *const precomp = c + 1;
+ unsigned int j;
+
+ r->v[1] = r->v[0] = 0x3ffffff & *(uint32_t *)key;
+ r->v[3] = r->v[2] = 0x3ffff03 & ((*(uint32_t *)(key + 3)) >> 2);
+ r->v[5] = r->v[4] = 0x3ffc0ff & ((*(uint32_t *)(key + 6)) >> 4);
+ r->v[7] = r->v[6] = 0x3f03fff & ((*(uint32_t *)(key + 9)) >> 6);
+ r->v[9] = r->v[8] = 0x00fffff & ((*(uint32_t *)(key + 12)) >> 8);
+
+ for (j = 0; j < 10; j++)
+ h->v[j] = 0; /* XXX: should fast-forward a bit */
+
+ addmulmod(precomp, r, r, &zero); /* precompute r^2 */
+ addmulmod(precomp + 1, precomp, precomp, &zero); /* precompute r^4 */
+
+ memcpy(st->key, key + 16, 16);
+ st->buf_used = 0;
+}
+
+void CRYPTO_poly1305_update_neon(poly1305_state *state, const uint8_t *in,
+ size_t in_len) {
+ struct poly1305_state_st *st = (struct poly1305_state_st *)(state);
+ fe1305x2 *const r = (fe1305x2 *)(st->data + (15 & (-(int)st->data)));
+ fe1305x2 *const h = r + 1;
+ fe1305x2 *const c = h + 1;
+ fe1305x2 *const precomp = c + 1;
+ unsigned int i;
+
+ if (st->buf_used) {
+ unsigned int todo = 32 - st->buf_used;
+ if (todo > in_len)
+ todo = in_len;
+ for (i = 0; i < todo; i++)
+ st->buf[st->buf_used + i] = in[i];
+ st->buf_used += todo;
+ in_len -= todo;
+ in += todo;
+
+ if (st->buf_used == sizeof(st->buf) && in_len) {
+ addmulmod(h, h, precomp, &zero);
+ fe1305x2_frombytearray(c, st->buf, sizeof(st->buf));
+ for (i = 0; i < 10; i++)
+ h->v[i] += c->v[i];
+ st->buf_used = 0;
+ }
+ }
+
+ while (in_len > 32) {
+ unsigned int tlen = 1048576;
+ if (in_len < tlen)
+ tlen = in_len;
+ tlen -= blocks(h, precomp, in, tlen);
+ in_len -= tlen;
+ in += tlen;
+ }
+
+ if (in_len) {
+ for (i = 0; i < in_len; i++)
+ st->buf[i] = in[i];
+ st->buf_used = in_len;
+ }
+}
+
+void CRYPTO_poly1305_finish_neon(poly1305_state *state, uint8_t mac[16]) {
+ struct poly1305_state_st *st = (struct poly1305_state_st *)(state);
+ fe1305x2 *const r = (fe1305x2 *)(st->data + (15 & (-(int)st->data)));
+ fe1305x2 *const h = r + 1;
+ fe1305x2 *const c = h + 1;
+ fe1305x2 *const precomp = c + 1;
+
+ addmulmod(h, h, precomp, &zero);
+
+ if (st->buf_used > 16) {
+ fe1305x2_frombytearray(c, st->buf, st->buf_used);
+ precomp->v[1] = r->v[1];
+ precomp->v[3] = r->v[3];
+ precomp->v[5] = r->v[5];
+ precomp->v[7] = r->v[7];
+ precomp->v[9] = r->v[9];
+ addmulmod(h, h, precomp, c);
+ } else if (st->buf_used > 0) {
+ fe1305x2_frombytearray(c, st->buf, st->buf_used);
+ r->v[1] = 1;
+ r->v[3] = 0;
+ r->v[5] = 0;
+ r->v[7] = 0;
+ r->v[9] = 0;
+ addmulmod(h, h, r, c);
+ }
+
+ h->v[0] += h->v[1];
+ h->v[2] += h->v[3];
+ h->v[4] += h->v[5];
+ h->v[6] += h->v[7];
+ h->v[8] += h->v[9];
+ freeze(h);
+
+ fe1305x2_frombytearray(c, st->key, 16);
+ c->v[8] ^= (1 << 24);
+
+ h->v[0] += c->v[0];
+ h->v[2] += c->v[2];
+ h->v[4] += c->v[4];
+ h->v[6] += c->v[6];
+ h->v[8] += c->v[8];
+ fe1305x2_tobytearray(mac, h);
+}
+
+#endif /* OPENSSL_ARM && !OPENSSL_NO_ASM */
diff --git a/src/crypto/poly1305/poly1305_arm_asm.S b/src/crypto/poly1305/poly1305_arm_asm.S
new file mode 100644
index 0000000..9d87413
--- /dev/null
+++ b/src/crypto/poly1305/poly1305_arm_asm.S
@@ -0,0 +1,2015 @@
+#if defined(__arm__) && !defined(OPENSSL_NO_ASM)
+
+# This implementation was taken from the public domain, neon2 version in
+# SUPERCOP by D. J. Bernstein and Peter Schwabe.
+
+# qhasm: int32 input_0
+
+# qhasm: int32 input_1
+
+# qhasm: int32 input_2
+
+# qhasm: int32 input_3
+
+# qhasm: stack32 input_4
+
+# qhasm: stack32 input_5
+
+# qhasm: stack32 input_6
+
+# qhasm: stack32 input_7
+
+# qhasm: int32 caller_r4
+
+# qhasm: int32 caller_r5
+
+# qhasm: int32 caller_r6
+
+# qhasm: int32 caller_r7
+
+# qhasm: int32 caller_r8
+
+# qhasm: int32 caller_r9
+
+# qhasm: int32 caller_r10
+
+# qhasm: int32 caller_r11
+
+# qhasm: int32 caller_r12
+
+# qhasm: int32 caller_r14
+
+# qhasm: reg128 caller_q4
+
+# qhasm: reg128 caller_q5
+
+# qhasm: reg128 caller_q6
+
+# qhasm: reg128 caller_q7
+
+# qhasm: startcode
+.fpu neon
+.text
+
+# qhasm: reg128 r0
+
+# qhasm: reg128 r1
+
+# qhasm: reg128 r2
+
+# qhasm: reg128 r3
+
+# qhasm: reg128 r4
+
+# qhasm: reg128 x01
+
+# qhasm: reg128 x23
+
+# qhasm: reg128 x4
+
+# qhasm: reg128 y0
+
+# qhasm: reg128 y12
+
+# qhasm: reg128 y34
+
+# qhasm: reg128 5y12
+
+# qhasm: reg128 5y34
+
+# qhasm: stack128 y0_stack
+
+# qhasm: stack128 y12_stack
+
+# qhasm: stack128 y34_stack
+
+# qhasm: stack128 5y12_stack
+
+# qhasm: stack128 5y34_stack
+
+# qhasm: reg128 z0
+
+# qhasm: reg128 z12
+
+# qhasm: reg128 z34
+
+# qhasm: reg128 5z12
+
+# qhasm: reg128 5z34
+
+# qhasm: stack128 z0_stack
+
+# qhasm: stack128 z12_stack
+
+# qhasm: stack128 z34_stack
+
+# qhasm: stack128 5z12_stack
+
+# qhasm: stack128 5z34_stack
+
+# qhasm: stack128 two24
+
+# qhasm: int32 ptr
+
+# qhasm: reg128 c01
+
+# qhasm: reg128 c23
+
+# qhasm: reg128 d01
+
+# qhasm: reg128 d23
+
+# qhasm: reg128 t0
+
+# qhasm: reg128 t1
+
+# qhasm: reg128 t2
+
+# qhasm: reg128 t3
+
+# qhasm: reg128 t4
+
+# qhasm: reg128 mask
+
+# qhasm: reg128 u0
+
+# qhasm: reg128 u1
+
+# qhasm: reg128 u2
+
+# qhasm: reg128 u3
+
+# qhasm: reg128 u4
+
+# qhasm: reg128 v01
+
+# qhasm: reg128 mid
+
+# qhasm: reg128 v23
+
+# qhasm: reg128 v4
+
+# qhasm: int32 len
+
+# qhasm: qpushenter crypto_onetimeauth_poly1305_neon2_blocks
+.align 4
+.global openssl_poly1305_neon2_blocks
+.hidden openssl_poly1305_neon2_blocks
+.type openssl_poly1305_neon2_blocks STT_FUNC
+openssl_poly1305_neon2_blocks:
+vpush {q4,q5,q6,q7}
+mov r12,sp
+sub sp,sp,#192
+and sp,sp,#0xffffffe0
+
+# qhasm: len = input_3
+# asm 1: mov >len=int32#4,<input_3=int32#4
+# asm 2: mov >len=r3,<input_3=r3
+mov r3,r3
+
+# qhasm: new y0
+
+# qhasm: y0 = mem64[input_1]y0[1]; input_1 += 8
+# asm 1: vld1.8 {<y0=reg128#1%bot},[<input_1=int32#2]!
+# asm 2: vld1.8 {<y0=d0},[<input_1=r1]!
+vld1.8 {d0},[r1]!
+
+# qhasm: y12 = mem128[input_1]; input_1 += 16
+# asm 1: vld1.8 {>y12=reg128#2%bot->y12=reg128#2%top},[<input_1=int32#2]!
+# asm 2: vld1.8 {>y12=d2->y12=d3},[<input_1=r1]!
+vld1.8 {d2-d3},[r1]!
+
+# qhasm: y34 = mem128[input_1]; input_1 += 16
+# asm 1: vld1.8 {>y34=reg128#3%bot->y34=reg128#3%top},[<input_1=int32#2]!
+# asm 2: vld1.8 {>y34=d4->y34=d5},[<input_1=r1]!
+vld1.8 {d4-d5},[r1]!
+
+# qhasm: input_1 += 8
+# asm 1: add >input_1=int32#2,<input_1=int32#2,#8
+# asm 2: add >input_1=r1,<input_1=r1,#8
+add r1,r1,#8
+
+# qhasm: new z0
+
+# qhasm: z0 = mem64[input_1]z0[1]; input_1 += 8
+# asm 1: vld1.8 {<z0=reg128#4%bot},[<input_1=int32#2]!
+# asm 2: vld1.8 {<z0=d6},[<input_1=r1]!
+vld1.8 {d6},[r1]!
+
+# qhasm: z12 = mem128[input_1]; input_1 += 16
+# asm 1: vld1.8 {>z12=reg128#5%bot->z12=reg128#5%top},[<input_1=int32#2]!
+# asm 2: vld1.8 {>z12=d8->z12=d9},[<input_1=r1]!
+vld1.8 {d8-d9},[r1]!
+
+# qhasm: z34 = mem128[input_1]; input_1 += 16
+# asm 1: vld1.8 {>z34=reg128#6%bot->z34=reg128#6%top},[<input_1=int32#2]!
+# asm 2: vld1.8 {>z34=d10->z34=d11},[<input_1=r1]!
+vld1.8 {d10-d11},[r1]!
+
+# qhasm: 2x mask = 0xffffffff
+# asm 1: vmov.i64 >mask=reg128#7,#0xffffffff
+# asm 2: vmov.i64 >mask=q6,#0xffffffff
+vmov.i64 q6,#0xffffffff
+
+# qhasm: 2x u4 = 0xff
+# asm 1: vmov.i64 >u4=reg128#8,#0xff
+# asm 2: vmov.i64 >u4=q7,#0xff
+vmov.i64 q7,#0xff
+
+# qhasm: x01 aligned= mem128[input_0];input_0+=16
+# asm 1: vld1.8 {>x01=reg128#9%bot->x01=reg128#9%top},[<input_0=int32#1,: 128]!
+# asm 2: vld1.8 {>x01=d16->x01=d17},[<input_0=r0,: 128]!
+vld1.8 {d16-d17},[r0,: 128]!
+
+# qhasm: x23 aligned= mem128[input_0];input_0+=16
+# asm 1: vld1.8 {>x23=reg128#10%bot->x23=reg128#10%top},[<input_0=int32#1,: 128]!
+# asm 2: vld1.8 {>x23=d18->x23=d19},[<input_0=r0,: 128]!
+vld1.8 {d18-d19},[r0,: 128]!
+
+# qhasm: x4 aligned= mem64[input_0]x4[1]
+# asm 1: vld1.8 {<x4=reg128#11%bot},[<input_0=int32#1,: 64]
+# asm 2: vld1.8 {<x4=d20},[<input_0=r0,: 64]
+vld1.8 {d20},[r0,: 64]
+
+# qhasm: input_0 -= 32
+# asm 1: sub >input_0=int32#1,<input_0=int32#1,#32
+# asm 2: sub >input_0=r0,<input_0=r0,#32
+sub r0,r0,#32
+
+# qhasm: 2x mask unsigned>>=6
+# asm 1: vshr.u64 >mask=reg128#7,<mask=reg128#7,#6
+# asm 2: vshr.u64 >mask=q6,<mask=q6,#6
+vshr.u64 q6,q6,#6
+
+# qhasm: 2x u4 unsigned>>= 7
+# asm 1: vshr.u64 >u4=reg128#8,<u4=reg128#8,#7
+# asm 2: vshr.u64 >u4=q7,<u4=q7,#7
+vshr.u64 q7,q7,#7
+
+# qhasm: 4x 5y12 = y12 << 2
+# asm 1: vshl.i32 >5y12=reg128#12,<y12=reg128#2,#2
+# asm 2: vshl.i32 >5y12=q11,<y12=q1,#2
+vshl.i32 q11,q1,#2
+
+# qhasm: 4x 5y34 = y34 << 2
+# asm 1: vshl.i32 >5y34=reg128#13,<y34=reg128#3,#2
+# asm 2: vshl.i32 >5y34=q12,<y34=q2,#2
+vshl.i32 q12,q2,#2
+
+# qhasm: 4x 5y12 += y12
+# asm 1: vadd.i32 >5y12=reg128#12,<5y12=reg128#12,<y12=reg128#2
+# asm 2: vadd.i32 >5y12=q11,<5y12=q11,<y12=q1
+vadd.i32 q11,q11,q1
+
+# qhasm: 4x 5y34 += y34
+# asm 1: vadd.i32 >5y34=reg128#13,<5y34=reg128#13,<y34=reg128#3
+# asm 2: vadd.i32 >5y34=q12,<5y34=q12,<y34=q2
+vadd.i32 q12,q12,q2
+
+# qhasm: 2x u4 <<= 24
+# asm 1: vshl.i64 >u4=reg128#8,<u4=reg128#8,#24
+# asm 2: vshl.i64 >u4=q7,<u4=q7,#24
+vshl.i64 q7,q7,#24
+
+# qhasm: 4x 5z12 = z12 << 2
+# asm 1: vshl.i32 >5z12=reg128#14,<z12=reg128#5,#2
+# asm 2: vshl.i32 >5z12=q13,<z12=q4,#2
+vshl.i32 q13,q4,#2
+
+# qhasm: 4x 5z34 = z34 << 2
+# asm 1: vshl.i32 >5z34=reg128#15,<z34=reg128#6,#2
+# asm 2: vshl.i32 >5z34=q14,<z34=q5,#2
+vshl.i32 q14,q5,#2
+
+# qhasm: 4x 5z12 += z12
+# asm 1: vadd.i32 >5z12=reg128#14,<5z12=reg128#14,<z12=reg128#5
+# asm 2: vadd.i32 >5z12=q13,<5z12=q13,<z12=q4
+vadd.i32 q13,q13,q4
+
+# qhasm: 4x 5z34 += z34
+# asm 1: vadd.i32 >5z34=reg128#15,<5z34=reg128#15,<z34=reg128#6
+# asm 2: vadd.i32 >5z34=q14,<5z34=q14,<z34=q5
+vadd.i32 q14,q14,q5
+
+# qhasm: new two24
+
+# qhasm: new y0_stack
+
+# qhasm: new y12_stack
+
+# qhasm: new y34_stack
+
+# qhasm: new 5y12_stack
+
+# qhasm: new 5y34_stack
+
+# qhasm: new z0_stack
+
+# qhasm: new z12_stack
+
+# qhasm: new z34_stack
+
+# qhasm: new 5z12_stack
+
+# qhasm: new 5z34_stack
+
+# qhasm: ptr = &two24
+# asm 1: lea >ptr=int32#2,<two24=stack128#1
+# asm 2: lea >ptr=r1,<two24=[sp,#0]
+add r1,sp,#0
+
+# qhasm: mem128[ptr] aligned= u4
+# asm 1: vst1.8 {<u4=reg128#8%bot-<u4=reg128#8%top},[<ptr=int32#2,: 128]
+# asm 2: vst1.8 {<u4=d14-<u4=d15},[<ptr=r1,: 128]
+vst1.8 {d14-d15},[r1,: 128]
+
+# qhasm: r4 = u4
+# asm 1: vmov >r4=reg128#16,<u4=reg128#8
+# asm 2: vmov >r4=q15,<u4=q7
+vmov q15,q7
+
+# qhasm: r0 = u4
+# asm 1: vmov >r0=reg128#8,<u4=reg128#8
+# asm 2: vmov >r0=q7,<u4=q7
+vmov q7,q7
+
+# qhasm: ptr = &y0_stack
+# asm 1: lea >ptr=int32#2,<y0_stack=stack128#2
+# asm 2: lea >ptr=r1,<y0_stack=[sp,#16]
+add r1,sp,#16
+
+# qhasm: mem128[ptr] aligned= y0
+# asm 1: vst1.8 {<y0=reg128#1%bot-<y0=reg128#1%top},[<ptr=int32#2,: 128]
+# asm 2: vst1.8 {<y0=d0-<y0=d1},[<ptr=r1,: 128]
+vst1.8 {d0-d1},[r1,: 128]
+
+# qhasm: ptr = &y12_stack
+# asm 1: lea >ptr=int32#2,<y12_stack=stack128#3
+# asm 2: lea >ptr=r1,<y12_stack=[sp,#32]
+add r1,sp,#32
+
+# qhasm: mem128[ptr] aligned= y12
+# asm 1: vst1.8 {<y12=reg128#2%bot-<y12=reg128#2%top},[<ptr=int32#2,: 128]
+# asm 2: vst1.8 {<y12=d2-<y12=d3},[<ptr=r1,: 128]
+vst1.8 {d2-d3},[r1,: 128]
+
+# qhasm: ptr = &y34_stack
+# asm 1: lea >ptr=int32#2,<y34_stack=stack128#4
+# asm 2: lea >ptr=r1,<y34_stack=[sp,#48]
+add r1,sp,#48
+
+# qhasm: mem128[ptr] aligned= y34
+# asm 1: vst1.8 {<y34=reg128#3%bot-<y34=reg128#3%top},[<ptr=int32#2,: 128]
+# asm 2: vst1.8 {<y34=d4-<y34=d5},[<ptr=r1,: 128]
+vst1.8 {d4-d5},[r1,: 128]
+
+# qhasm: ptr = &z0_stack
+# asm 1: lea >ptr=int32#2,<z0_stack=stack128#7
+# asm 2: lea >ptr=r1,<z0_stack=[sp,#96]
+add r1,sp,#96
+
+# qhasm: mem128[ptr] aligned= z0
+# asm 1: vst1.8 {<z0=reg128#4%bot-<z0=reg128#4%top},[<ptr=int32#2,: 128]
+# asm 2: vst1.8 {<z0=d6-<z0=d7},[<ptr=r1,: 128]
+vst1.8 {d6-d7},[r1,: 128]
+
+# qhasm: ptr = &z12_stack
+# asm 1: lea >ptr=int32#2,<z12_stack=stack128#8
+# asm 2: lea >ptr=r1,<z12_stack=[sp,#112]
+add r1,sp,#112
+
+# qhasm: mem128[ptr] aligned= z12
+# asm 1: vst1.8 {<z12=reg128#5%bot-<z12=reg128#5%top},[<ptr=int32#2,: 128]
+# asm 2: vst1.8 {<z12=d8-<z12=d9},[<ptr=r1,: 128]
+vst1.8 {d8-d9},[r1,: 128]
+
+# qhasm: ptr = &z34_stack
+# asm 1: lea >ptr=int32#2,<z34_stack=stack128#9
+# asm 2: lea >ptr=r1,<z34_stack=[sp,#128]
+add r1,sp,#128
+
+# qhasm: mem128[ptr] aligned= z34
+# asm 1: vst1.8 {<z34=reg128#6%bot-<z34=reg128#6%top},[<ptr=int32#2,: 128]
+# asm 2: vst1.8 {<z34=d10-<z34=d11},[<ptr=r1,: 128]
+vst1.8 {d10-d11},[r1,: 128]
+
+# qhasm: ptr = &5y12_stack
+# asm 1: lea >ptr=int32#2,<5y12_stack=stack128#5
+# asm 2: lea >ptr=r1,<5y12_stack=[sp,#64]
+add r1,sp,#64
+
+# qhasm: mem128[ptr] aligned= 5y12
+# asm 1: vst1.8 {<5y12=reg128#12%bot-<5y12=reg128#12%top},[<ptr=int32#2,: 128]
+# asm 2: vst1.8 {<5y12=d22-<5y12=d23},[<ptr=r1,: 128]
+vst1.8 {d22-d23},[r1,: 128]
+
+# qhasm: ptr = &5y34_stack
+# asm 1: lea >ptr=int32#2,<5y34_stack=stack128#6
+# asm 2: lea >ptr=r1,<5y34_stack=[sp,#80]
+add r1,sp,#80
+
+# qhasm: mem128[ptr] aligned= 5y34
+# asm 1: vst1.8 {<5y34=reg128#13%bot-<5y34=reg128#13%top},[<ptr=int32#2,: 128]
+# asm 2: vst1.8 {<5y34=d24-<5y34=d25},[<ptr=r1,: 128]
+vst1.8 {d24-d25},[r1,: 128]
+
+# qhasm: ptr = &5z12_stack
+# asm 1: lea >ptr=int32#2,<5z12_stack=stack128#10
+# asm 2: lea >ptr=r1,<5z12_stack=[sp,#144]
+add r1,sp,#144
+
+# qhasm: mem128[ptr] aligned= 5z12
+# asm 1: vst1.8 {<5z12=reg128#14%bot-<5z12=reg128#14%top},[<ptr=int32#2,: 128]
+# asm 2: vst1.8 {<5z12=d26-<5z12=d27},[<ptr=r1,: 128]
+vst1.8 {d26-d27},[r1,: 128]
+
+# qhasm: ptr = &5z34_stack
+# asm 1: lea >ptr=int32#2,<5z34_stack=stack128#11
+# asm 2: lea >ptr=r1,<5z34_stack=[sp,#160]
+add r1,sp,#160
+
+# qhasm: mem128[ptr] aligned= 5z34
+# asm 1: vst1.8 {<5z34=reg128#15%bot-<5z34=reg128#15%top},[<ptr=int32#2,: 128]
+# asm 2: vst1.8 {<5z34=d28-<5z34=d29},[<ptr=r1,: 128]
+vst1.8 {d28-d29},[r1,: 128]
+
+# qhasm: unsigned>? len - 64
+# asm 1: cmp <len=int32#4,#64
+# asm 2: cmp <len=r3,#64
+cmp r3,#64
+
+# qhasm: goto below64bytes if !unsigned>
+bls ._below64bytes
+
+# qhasm: input_2 += 32
+# asm 1: add >input_2=int32#2,<input_2=int32#3,#32
+# asm 2: add >input_2=r1,<input_2=r2,#32
+add r1,r2,#32
+
+# qhasm: mainloop2:
+._mainloop2:
+
+# qhasm: c01 = mem128[input_2];input_2+=16
+# asm 1: vld1.8 {>c01=reg128#1%bot->c01=reg128#1%top},[<input_2=int32#2]!
+# asm 2: vld1.8 {>c01=d0->c01=d1},[<input_2=r1]!
+vld1.8 {d0-d1},[r1]!
+
+# qhasm: c23 = mem128[input_2];input_2+=16
+# asm 1: vld1.8 {>c23=reg128#2%bot->c23=reg128#2%top},[<input_2=int32#2]!
+# asm 2: vld1.8 {>c23=d2->c23=d3},[<input_2=r1]!
+vld1.8 {d2-d3},[r1]!
+
+# qhasm: r4[0,1] += x01[0] unsigned* z34[2]; r4[2,3] += x01[1] unsigned* z34[3]
+# asm 1: vmlal.u32 <r4=reg128#16,<x01=reg128#9%bot,<z34=reg128#6%top
+# asm 2: vmlal.u32 <r4=q15,<x01=d16,<z34=d11
+vmlal.u32 q15,d16,d11
+
+# qhasm: ptr = &z12_stack
+# asm 1: lea >ptr=int32#3,<z12_stack=stack128#8
+# asm 2: lea >ptr=r2,<z12_stack=[sp,#112]
+add r2,sp,#112
+
+# qhasm: z12 aligned= mem128[ptr]
+# asm 1: vld1.8 {>z12=reg128#3%bot->z12=reg128#3%top},[<ptr=int32#3,: 128]
+# asm 2: vld1.8 {>z12=d4->z12=d5},[<ptr=r2,: 128]
+vld1.8 {d4-d5},[r2,: 128]
+
+# qhasm: r4[0,1] += x01[2] unsigned* z34[0]; r4[2,3] += x01[3] unsigned* z34[1]
+# asm 1: vmlal.u32 <r4=reg128#16,<x01=reg128#9%top,<z34=reg128#6%bot
+# asm 2: vmlal.u32 <r4=q15,<x01=d17,<z34=d10
+vmlal.u32 q15,d17,d10
+
+# qhasm: ptr = &z0_stack
+# asm 1: lea >ptr=int32#3,<z0_stack=stack128#7
+# asm 2: lea >ptr=r2,<z0_stack=[sp,#96]
+add r2,sp,#96
+
+# qhasm: z0 aligned= mem128[ptr]
+# asm 1: vld1.8 {>z0=reg128#4%bot->z0=reg128#4%top},[<ptr=int32#3,: 128]
+# asm 2: vld1.8 {>z0=d6->z0=d7},[<ptr=r2,: 128]
+vld1.8 {d6-d7},[r2,: 128]
+
+# qhasm: r4[0,1] += x23[0] unsigned* z12[2]; r4[2,3] += x23[1] unsigned* z12[3]
+# asm 1: vmlal.u32 <r4=reg128#16,<x23=reg128#10%bot,<z12=reg128#3%top
+# asm 2: vmlal.u32 <r4=q15,<x23=d18,<z12=d5
+vmlal.u32 q15,d18,d5
+
+# qhasm: c01 c23 = c01[0]c01[1]c01[2]c23[2]c23[0]c23[1]c01[3]c23[3]
+# asm 1: vtrn.32 <c01=reg128#1%top,<c23=reg128#2%top
+# asm 2: vtrn.32 <c01=d1,<c23=d3
+vtrn.32 d1,d3
+
+# qhasm: r4[0,1] += x23[2] unsigned* z12[0]; r4[2,3] += x23[3] unsigned* z12[1]
+# asm 1: vmlal.u32 <r4=reg128#16,<x23=reg128#10%top,<z12=reg128#3%bot
+# asm 2: vmlal.u32 <r4=q15,<x23=d19,<z12=d4
+vmlal.u32 q15,d19,d4
+
+# qhasm: r4[0,1] += x4[0] unsigned* z0[0]; r4[2,3] += x4[1] unsigned* z0[1]
+# asm 1: vmlal.u32 <r4=reg128#16,<x4=reg128#11%bot,<z0=reg128#4%bot
+# asm 2: vmlal.u32 <r4=q15,<x4=d20,<z0=d6
+vmlal.u32 q15,d20,d6
+
+# qhasm: r3[0,1] = c23[2]<<18; r3[2,3] = c23[3]<<18
+# asm 1: vshll.u32 >r3=reg128#5,<c23=reg128#2%top,#18
+# asm 2: vshll.u32 >r3=q4,<c23=d3,#18
+vshll.u32 q4,d3,#18
+
+# qhasm: c01 c23 = c01[0]c23[0]c01[2]c01[3]c01[1]c23[1]c23[2]c23[3]
+# asm 1: vtrn.32 <c01=reg128#1%bot,<c23=reg128#2%bot
+# asm 2: vtrn.32 <c01=d0,<c23=d2
+vtrn.32 d0,d2
+
+# qhasm: r3[0,1] += x01[0] unsigned* z34[0]; r3[2,3] += x01[1] unsigned* z34[1]
+# asm 1: vmlal.u32 <r3=reg128#5,<x01=reg128#9%bot,<z34=reg128#6%bot
+# asm 2: vmlal.u32 <r3=q4,<x01=d16,<z34=d10
+vmlal.u32 q4,d16,d10
+
+# qhasm: r3[0,1] += x01[2] unsigned* z12[2]; r3[2,3] += x01[3] unsigned* z12[3]
+# asm 1: vmlal.u32 <r3=reg128#5,<x01=reg128#9%top,<z12=reg128#3%top
+# asm 2: vmlal.u32 <r3=q4,<x01=d17,<z12=d5
+vmlal.u32 q4,d17,d5
+
+# qhasm: r0 = r0[1]c01[0]r0[2,3]
+# asm 1: vext.32 <r0=reg128#8%bot,<r0=reg128#8%bot,<c01=reg128#1%bot,#1
+# asm 2: vext.32 <r0=d14,<r0=d14,<c01=d0,#1
+vext.32 d14,d14,d0,#1
+
+# qhasm: r3[0,1] += x23[0] unsigned* z12[0]; r3[2,3] += x23[1] unsigned* z12[1]
+# asm 1: vmlal.u32 <r3=reg128#5,<x23=reg128#10%bot,<z12=reg128#3%bot
+# asm 2: vmlal.u32 <r3=q4,<x23=d18,<z12=d4
+vmlal.u32 q4,d18,d4
+
+# qhasm: input_2 -= 64
+# asm 1: sub >input_2=int32#2,<input_2=int32#2,#64
+# asm 2: sub >input_2=r1,<input_2=r1,#64
+sub r1,r1,#64
+
+# qhasm: r3[0,1] += x23[2] unsigned* z0[0]; r3[2,3] += x23[3] unsigned* z0[1]
+# asm 1: vmlal.u32 <r3=reg128#5,<x23=reg128#10%top,<z0=reg128#4%bot
+# asm 2: vmlal.u32 <r3=q4,<x23=d19,<z0=d6
+vmlal.u32 q4,d19,d6
+
+# qhasm: ptr = &5z34_stack
+# asm 1: lea >ptr=int32#3,<5z34_stack=stack128#11
+# asm 2: lea >ptr=r2,<5z34_stack=[sp,#160]
+add r2,sp,#160
+
+# qhasm: 5z34 aligned= mem128[ptr]
+# asm 1: vld1.8 {>5z34=reg128#6%bot->5z34=reg128#6%top},[<ptr=int32#3,: 128]
+# asm 2: vld1.8 {>5z34=d10->5z34=d11},[<ptr=r2,: 128]
+vld1.8 {d10-d11},[r2,: 128]
+
+# qhasm: r3[0,1] += x4[0] unsigned* 5z34[2]; r3[2,3] += x4[1] unsigned* 5z34[3]
+# asm 1: vmlal.u32 <r3=reg128#5,<x4=reg128#11%bot,<5z34=reg128#6%top
+# asm 2: vmlal.u32 <r3=q4,<x4=d20,<5z34=d11
+vmlal.u32 q4,d20,d11
+
+# qhasm: r0 = r0[1]r0[0]r0[3]r0[2]
+# asm 1: vrev64.i32 >r0=reg128#8,<r0=reg128#8
+# asm 2: vrev64.i32 >r0=q7,<r0=q7
+vrev64.i32 q7,q7
+
+# qhasm: r2[0,1] = c01[2]<<12; r2[2,3] = c01[3]<<12
+# asm 1: vshll.u32 >r2=reg128#14,<c01=reg128#1%top,#12
+# asm 2: vshll.u32 >r2=q13,<c01=d1,#12
+vshll.u32 q13,d1,#12
+
+# qhasm: d01 = mem128[input_2];input_2+=16
+# asm 1: vld1.8 {>d01=reg128#12%bot->d01=reg128#12%top},[<input_2=int32#2]!
+# asm 2: vld1.8 {>d01=d22->d01=d23},[<input_2=r1]!
+vld1.8 {d22-d23},[r1]!
+
+# qhasm: r2[0,1] += x01[0] unsigned* z12[2]; r2[2,3] += x01[1] unsigned* z12[3]
+# asm 1: vmlal.u32 <r2=reg128#14,<x01=reg128#9%bot,<z12=reg128#3%top
+# asm 2: vmlal.u32 <r2=q13,<x01=d16,<z12=d5
+vmlal.u32 q13,d16,d5
+
+# qhasm: r2[0,1] += x01[2] unsigned* z12[0]; r2[2,3] += x01[3] unsigned* z12[1]
+# asm 1: vmlal.u32 <r2=reg128#14,<x01=reg128#9%top,<z12=reg128#3%bot
+# asm 2: vmlal.u32 <r2=q13,<x01=d17,<z12=d4
+vmlal.u32 q13,d17,d4
+
+# qhasm: r2[0,1] += x23[0] unsigned* z0[0]; r2[2,3] += x23[1] unsigned* z0[1]
+# asm 1: vmlal.u32 <r2=reg128#14,<x23=reg128#10%bot,<z0=reg128#4%bot
+# asm 2: vmlal.u32 <r2=q13,<x23=d18,<z0=d6
+vmlal.u32 q13,d18,d6
+
+# qhasm: r2[0,1] += x23[2] unsigned* 5z34[2]; r2[2,3] += x23[3] unsigned* 5z34[3]
+# asm 1: vmlal.u32 <r2=reg128#14,<x23=reg128#10%top,<5z34=reg128#6%top
+# asm 2: vmlal.u32 <r2=q13,<x23=d19,<5z34=d11
+vmlal.u32 q13,d19,d11
+
+# qhasm: r2[0,1] += x4[0] unsigned* 5z34[0]; r2[2,3] += x4[1] unsigned* 5z34[1]
+# asm 1: vmlal.u32 <r2=reg128#14,<x4=reg128#11%bot,<5z34=reg128#6%bot
+# asm 2: vmlal.u32 <r2=q13,<x4=d20,<5z34=d10
+vmlal.u32 q13,d20,d10
+
+# qhasm: r0 = r0[0,1]c01[1]r0[2]
+# asm 1: vext.32 <r0=reg128#8%top,<c01=reg128#1%bot,<r0=reg128#8%top,#1
+# asm 2: vext.32 <r0=d15,<c01=d0,<r0=d15,#1
+vext.32 d15,d0,d15,#1
+
+# qhasm: r1[0,1] = c23[0]<<6; r1[2,3] = c23[1]<<6
+# asm 1: vshll.u32 >r1=reg128#15,<c23=reg128#2%bot,#6
+# asm 2: vshll.u32 >r1=q14,<c23=d2,#6
+vshll.u32 q14,d2,#6
+
+# qhasm: r1[0,1] += x01[0] unsigned* z12[0]; r1[2,3] += x01[1] unsigned* z12[1]
+# asm 1: vmlal.u32 <r1=reg128#15,<x01=reg128#9%bot,<z12=reg128#3%bot
+# asm 2: vmlal.u32 <r1=q14,<x01=d16,<z12=d4
+vmlal.u32 q14,d16,d4
+
+# qhasm: r1[0,1] += x01[2] unsigned* z0[0]; r1[2,3] += x01[3] unsigned* z0[1]
+# asm 1: vmlal.u32 <r1=reg128#15,<x01=reg128#9%top,<z0=reg128#4%bot
+# asm 2: vmlal.u32 <r1=q14,<x01=d17,<z0=d6
+vmlal.u32 q14,d17,d6
+
+# qhasm: r1[0,1] += x23[0] unsigned* 5z34[2]; r1[2,3] += x23[1] unsigned* 5z34[3]
+# asm 1: vmlal.u32 <r1=reg128#15,<x23=reg128#10%bot,<5z34=reg128#6%top
+# asm 2: vmlal.u32 <r1=q14,<x23=d18,<5z34=d11
+vmlal.u32 q14,d18,d11
+
+# qhasm: r1[0,1] += x23[2] unsigned* 5z34[0]; r1[2,3] += x23[3] unsigned* 5z34[1]
+# asm 1: vmlal.u32 <r1=reg128#15,<x23=reg128#10%top,<5z34=reg128#6%bot
+# asm 2: vmlal.u32 <r1=q14,<x23=d19,<5z34=d10
+vmlal.u32 q14,d19,d10
+
+# qhasm: ptr = &5z12_stack
+# asm 1: lea >ptr=int32#3,<5z12_stack=stack128#10
+# asm 2: lea >ptr=r2,<5z12_stack=[sp,#144]
+add r2,sp,#144
+
+# qhasm: 5z12 aligned= mem128[ptr]
+# asm 1: vld1.8 {>5z12=reg128#1%bot->5z12=reg128#1%top},[<ptr=int32#3,: 128]
+# asm 2: vld1.8 {>5z12=d0->5z12=d1},[<ptr=r2,: 128]
+vld1.8 {d0-d1},[r2,: 128]
+
+# qhasm: r1[0,1] += x4[0] unsigned* 5z12[2]; r1[2,3] += x4[1] unsigned* 5z12[3]
+# asm 1: vmlal.u32 <r1=reg128#15,<x4=reg128#11%bot,<5z12=reg128#1%top
+# asm 2: vmlal.u32 <r1=q14,<x4=d20,<5z12=d1
+vmlal.u32 q14,d20,d1
+
+# qhasm: d23 = mem128[input_2];input_2+=16
+# asm 1: vld1.8 {>d23=reg128#2%bot->d23=reg128#2%top},[<input_2=int32#2]!
+# asm 2: vld1.8 {>d23=d2->d23=d3},[<input_2=r1]!
+vld1.8 {d2-d3},[r1]!
+
+# qhasm: input_2 += 32
+# asm 1: add >input_2=int32#2,<input_2=int32#2,#32
+# asm 2: add >input_2=r1,<input_2=r1,#32
+add r1,r1,#32
+
+# qhasm: r0[0,1] += x4[0] unsigned* 5z12[0]; r0[2,3] += x4[1] unsigned* 5z12[1]
+# asm 1: vmlal.u32 <r0=reg128#8,<x4=reg128#11%bot,<5z12=reg128#1%bot
+# asm 2: vmlal.u32 <r0=q7,<x4=d20,<5z12=d0
+vmlal.u32 q7,d20,d0
+
+# qhasm: r0[0,1] += x23[0] unsigned* 5z34[0]; r0[2,3] += x23[1] unsigned* 5z34[1]
+# asm 1: vmlal.u32 <r0=reg128#8,<x23=reg128#10%bot,<5z34=reg128#6%bot
+# asm 2: vmlal.u32 <r0=q7,<x23=d18,<5z34=d10
+vmlal.u32 q7,d18,d10
+
+# qhasm: d01 d23 = d01[0] d23[0] d01[1] d23[1]
+# asm 1: vswp <d23=reg128#2%bot,<d01=reg128#12%top
+# asm 2: vswp <d23=d2,<d01=d23
+vswp d2,d23
+
+# qhasm: r0[0,1] += x23[2] unsigned* 5z12[2]; r0[2,3] += x23[3] unsigned* 5z12[3]
+# asm 1: vmlal.u32 <r0=reg128#8,<x23=reg128#10%top,<5z12=reg128#1%top
+# asm 2: vmlal.u32 <r0=q7,<x23=d19,<5z12=d1
+vmlal.u32 q7,d19,d1
+
+# qhasm: r0[0,1] += x01[0] unsigned* z0[0]; r0[2,3] += x01[1] unsigned* z0[1]
+# asm 1: vmlal.u32 <r0=reg128#8,<x01=reg128#9%bot,<z0=reg128#4%bot
+# asm 2: vmlal.u32 <r0=q7,<x01=d16,<z0=d6
+vmlal.u32 q7,d16,d6
+
+# qhasm: new mid
+
+# qhasm: 2x v4 = d23 unsigned>> 40
+# asm 1: vshr.u64 >v4=reg128#4,<d23=reg128#2,#40
+# asm 2: vshr.u64 >v4=q3,<d23=q1,#40
+vshr.u64 q3,q1,#40
+
+# qhasm: mid = d01[1]d23[0] mid[2,3]
+# asm 1: vext.32 <mid=reg128#1%bot,<d01=reg128#12%bot,<d23=reg128#2%bot,#1
+# asm 2: vext.32 <mid=d0,<d01=d22,<d23=d2,#1
+vext.32 d0,d22,d2,#1
+
+# qhasm: new v23
+
+# qhasm: v23[2] = d23[0,1] unsigned>> 14; v23[3] = d23[2,3] unsigned>> 14
+# asm 1: vshrn.u64 <v23=reg128#10%top,<d23=reg128#2,#14
+# asm 2: vshrn.u64 <v23=d19,<d23=q1,#14
+vshrn.u64 d19,q1,#14
+
+# qhasm: mid = mid[0,1] d01[3]d23[2]
+# asm 1: vext.32 <mid=reg128#1%top,<d01=reg128#12%top,<d23=reg128#2%top,#1
+# asm 2: vext.32 <mid=d1,<d01=d23,<d23=d3,#1
+vext.32 d1,d23,d3,#1
+
+# qhasm: new v01
+
+# qhasm: v01[2] = d01[0,1] unsigned>> 26; v01[3] = d01[2,3] unsigned>> 26
+# asm 1: vshrn.u64 <v01=reg128#11%top,<d01=reg128#12,#26
+# asm 2: vshrn.u64 <v01=d21,<d01=q11,#26
+vshrn.u64 d21,q11,#26
+
+# qhasm: v01 = d01[1]d01[0] v01[2,3]
+# asm 1: vext.32 <v01=reg128#11%bot,<d01=reg128#12%bot,<d01=reg128#12%bot,#1
+# asm 2: vext.32 <v01=d20,<d01=d22,<d01=d22,#1
+vext.32 d20,d22,d22,#1
+
+# qhasm: r0[0,1] += x01[2] unsigned* 5z34[2]; r0[2,3] += x01[3] unsigned* 5z34[3]
+# asm 1: vmlal.u32 <r0=reg128#8,<x01=reg128#9%top,<5z34=reg128#6%top
+# asm 2: vmlal.u32 <r0=q7,<x01=d17,<5z34=d11
+vmlal.u32 q7,d17,d11
+
+# qhasm: v01 = v01[1]d01[2] v01[2,3]
+# asm 1: vext.32 <v01=reg128#11%bot,<v01=reg128#11%bot,<d01=reg128#12%top,#1
+# asm 2: vext.32 <v01=d20,<v01=d20,<d01=d23,#1
+vext.32 d20,d20,d23,#1
+
+# qhasm: v23[0] = mid[0,1] unsigned>> 20; v23[1] = mid[2,3] unsigned>> 20
+# asm 1: vshrn.u64 <v23=reg128#10%bot,<mid=reg128#1,#20
+# asm 2: vshrn.u64 <v23=d18,<mid=q0,#20
+vshrn.u64 d18,q0,#20
+
+# qhasm: v4 = v4[0]v4[2]v4[1]v4[3]
+# asm 1: vtrn.32 <v4=reg128#4%bot,<v4=reg128#4%top
+# asm 2: vtrn.32 <v4=d6,<v4=d7
+vtrn.32 d6,d7
+
+# qhasm: 4x v01 &= 0x03ffffff
+# asm 1: vand.i32 <v01=reg128#11,#0x03ffffff
+# asm 2: vand.i32 <v01=q10,#0x03ffffff
+vand.i32 q10,#0x03ffffff
+
+# qhasm: ptr = &y34_stack
+# asm 1: lea >ptr=int32#3,<y34_stack=stack128#4
+# asm 2: lea >ptr=r2,<y34_stack=[sp,#48]
+add r2,sp,#48
+
+# qhasm: y34 aligned= mem128[ptr]
+# asm 1: vld1.8 {>y34=reg128#3%bot->y34=reg128#3%top},[<ptr=int32#3,: 128]
+# asm 2: vld1.8 {>y34=d4->y34=d5},[<ptr=r2,: 128]
+vld1.8 {d4-d5},[r2,: 128]
+
+# qhasm: 4x v23 &= 0x03ffffff
+# asm 1: vand.i32 <v23=reg128#10,#0x03ffffff
+# asm 2: vand.i32 <v23=q9,#0x03ffffff
+vand.i32 q9,#0x03ffffff
+
+# qhasm: ptr = &y12_stack
+# asm 1: lea >ptr=int32#3,<y12_stack=stack128#3
+# asm 2: lea >ptr=r2,<y12_stack=[sp,#32]
+add r2,sp,#32
+
+# qhasm: y12 aligned= mem128[ptr]
+# asm 1: vld1.8 {>y12=reg128#2%bot->y12=reg128#2%top},[<ptr=int32#3,: 128]
+# asm 2: vld1.8 {>y12=d2->y12=d3},[<ptr=r2,: 128]
+vld1.8 {d2-d3},[r2,: 128]
+
+# qhasm: 4x v4 |= 0x01000000
+# asm 1: vorr.i32 <v4=reg128#4,#0x01000000
+# asm 2: vorr.i32 <v4=q3,#0x01000000
+vorr.i32 q3,#0x01000000
+
+# qhasm: ptr = &y0_stack
+# asm 1: lea >ptr=int32#3,<y0_stack=stack128#2
+# asm 2: lea >ptr=r2,<y0_stack=[sp,#16]
+add r2,sp,#16
+
+# qhasm: y0 aligned= mem128[ptr]
+# asm 1: vld1.8 {>y0=reg128#1%bot->y0=reg128#1%top},[<ptr=int32#3,: 128]
+# asm 2: vld1.8 {>y0=d0->y0=d1},[<ptr=r2,: 128]
+vld1.8 {d0-d1},[r2,: 128]
+
+# qhasm: r4[0,1] += v01[0] unsigned* y34[2]; r4[2,3] += v01[1] unsigned* y34[3]
+# asm 1: vmlal.u32 <r4=reg128#16,<v01=reg128#11%bot,<y34=reg128#3%top
+# asm 2: vmlal.u32 <r4=q15,<v01=d20,<y34=d5
+vmlal.u32 q15,d20,d5
+
+# qhasm: r4[0,1] += v01[2] unsigned* y34[0]; r4[2,3] += v01[3] unsigned* y34[1]
+# asm 1: vmlal.u32 <r4=reg128#16,<v01=reg128#11%top,<y34=reg128#3%bot
+# asm 2: vmlal.u32 <r4=q15,<v01=d21,<y34=d4
+vmlal.u32 q15,d21,d4
+
+# qhasm: r4[0,1] += v23[0] unsigned* y12[2]; r4[2,3] += v23[1] unsigned* y12[3]
+# asm 1: vmlal.u32 <r4=reg128#16,<v23=reg128#10%bot,<y12=reg128#2%top
+# asm 2: vmlal.u32 <r4=q15,<v23=d18,<y12=d3
+vmlal.u32 q15,d18,d3
+
+# qhasm: r4[0,1] += v23[2] unsigned* y12[0]; r4[2,3] += v23[3] unsigned* y12[1]
+# asm 1: vmlal.u32 <r4=reg128#16,<v23=reg128#10%top,<y12=reg128#2%bot
+# asm 2: vmlal.u32 <r4=q15,<v23=d19,<y12=d2
+vmlal.u32 q15,d19,d2
+
+# qhasm: r4[0,1] += v4[0] unsigned* y0[0]; r4[2,3] += v4[1] unsigned* y0[1]
+# asm 1: vmlal.u32 <r4=reg128#16,<v4=reg128#4%bot,<y0=reg128#1%bot
+# asm 2: vmlal.u32 <r4=q15,<v4=d6,<y0=d0
+vmlal.u32 q15,d6,d0
+
+# qhasm: ptr = &5y34_stack
+# asm 1: lea >ptr=int32#3,<5y34_stack=stack128#6
+# asm 2: lea >ptr=r2,<5y34_stack=[sp,#80]
+add r2,sp,#80
+
+# qhasm: 5y34 aligned= mem128[ptr]
+# asm 1: vld1.8 {>5y34=reg128#13%bot->5y34=reg128#13%top},[<ptr=int32#3,: 128]
+# asm 2: vld1.8 {>5y34=d24->5y34=d25},[<ptr=r2,: 128]
+vld1.8 {d24-d25},[r2,: 128]
+
+# qhasm: r3[0,1] += v01[0] unsigned* y34[0]; r3[2,3] += v01[1] unsigned* y34[1]
+# asm 1: vmlal.u32 <r3=reg128#5,<v01=reg128#11%bot,<y34=reg128#3%bot
+# asm 2: vmlal.u32 <r3=q4,<v01=d20,<y34=d4
+vmlal.u32 q4,d20,d4
+
+# qhasm: r3[0,1] += v01[2] unsigned* y12[2]; r3[2,3] += v01[3] unsigned* y12[3]
+# asm 1: vmlal.u32 <r3=reg128#5,<v01=reg128#11%top,<y12=reg128#2%top
+# asm 2: vmlal.u32 <r3=q4,<v01=d21,<y12=d3
+vmlal.u32 q4,d21,d3
+
+# qhasm: r3[0,1] += v23[0] unsigned* y12[0]; r3[2,3] += v23[1] unsigned* y12[1]
+# asm 1: vmlal.u32 <r3=reg128#5,<v23=reg128#10%bot,<y12=reg128#2%bot
+# asm 2: vmlal.u32 <r3=q4,<v23=d18,<y12=d2
+vmlal.u32 q4,d18,d2
+
+# qhasm: r3[0,1] += v23[2] unsigned* y0[0]; r3[2,3] += v23[3] unsigned* y0[1]
+# asm 1: vmlal.u32 <r3=reg128#5,<v23=reg128#10%top,<y0=reg128#1%bot
+# asm 2: vmlal.u32 <r3=q4,<v23=d19,<y0=d0
+vmlal.u32 q4,d19,d0
+
+# qhasm: r3[0,1] += v4[0] unsigned* 5y34[2]; r3[2,3] += v4[1] unsigned* 5y34[3]
+# asm 1: vmlal.u32 <r3=reg128#5,<v4=reg128#4%bot,<5y34=reg128#13%top
+# asm 2: vmlal.u32 <r3=q4,<v4=d6,<5y34=d25
+vmlal.u32 q4,d6,d25
+
+# qhasm: ptr = &5y12_stack
+# asm 1: lea >ptr=int32#3,<5y12_stack=stack128#5
+# asm 2: lea >ptr=r2,<5y12_stack=[sp,#64]
+add r2,sp,#64
+
+# qhasm: 5y12 aligned= mem128[ptr]
+# asm 1: vld1.8 {>5y12=reg128#12%bot->5y12=reg128#12%top},[<ptr=int32#3,: 128]
+# asm 2: vld1.8 {>5y12=d22->5y12=d23},[<ptr=r2,: 128]
+vld1.8 {d22-d23},[r2,: 128]
+
+# qhasm: r0[0,1] += v4[0] unsigned* 5y12[0]; r0[2,3] += v4[1] unsigned* 5y12[1]
+# asm 1: vmlal.u32 <r0=reg128#8,<v4=reg128#4%bot,<5y12=reg128#12%bot
+# asm 2: vmlal.u32 <r0=q7,<v4=d6,<5y12=d22
+vmlal.u32 q7,d6,d22
+
+# qhasm: r0[0,1] += v23[0] unsigned* 5y34[0]; r0[2,3] += v23[1] unsigned* 5y34[1]
+# asm 1: vmlal.u32 <r0=reg128#8,<v23=reg128#10%bot,<5y34=reg128#13%bot
+# asm 2: vmlal.u32 <r0=q7,<v23=d18,<5y34=d24
+vmlal.u32 q7,d18,d24
+
+# qhasm: r0[0,1] += v23[2] unsigned* 5y12[2]; r0[2,3] += v23[3] unsigned* 5y12[3]
+# asm 1: vmlal.u32 <r0=reg128#8,<v23=reg128#10%top,<5y12=reg128#12%top
+# asm 2: vmlal.u32 <r0=q7,<v23=d19,<5y12=d23
+vmlal.u32 q7,d19,d23
+
+# qhasm: r0[0,1] += v01[0] unsigned* y0[0]; r0[2,3] += v01[1] unsigned* y0[1]
+# asm 1: vmlal.u32 <r0=reg128#8,<v01=reg128#11%bot,<y0=reg128#1%bot
+# asm 2: vmlal.u32 <r0=q7,<v01=d20,<y0=d0
+vmlal.u32 q7,d20,d0
+
+# qhasm: r0[0,1] += v01[2] unsigned* 5y34[2]; r0[2,3] += v01[3] unsigned* 5y34[3]
+# asm 1: vmlal.u32 <r0=reg128#8,<v01=reg128#11%top,<5y34=reg128#13%top
+# asm 2: vmlal.u32 <r0=q7,<v01=d21,<5y34=d25
+vmlal.u32 q7,d21,d25
+
+# qhasm: r1[0,1] += v01[0] unsigned* y12[0]; r1[2,3] += v01[1] unsigned* y12[1]
+# asm 1: vmlal.u32 <r1=reg128#15,<v01=reg128#11%bot,<y12=reg128#2%bot
+# asm 2: vmlal.u32 <r1=q14,<v01=d20,<y12=d2
+vmlal.u32 q14,d20,d2
+
+# qhasm: r1[0,1] += v01[2] unsigned* y0[0]; r1[2,3] += v01[3] unsigned* y0[1]
+# asm 1: vmlal.u32 <r1=reg128#15,<v01=reg128#11%top,<y0=reg128#1%bot
+# asm 2: vmlal.u32 <r1=q14,<v01=d21,<y0=d0
+vmlal.u32 q14,d21,d0
+
+# qhasm: r1[0,1] += v23[0] unsigned* 5y34[2]; r1[2,3] += v23[1] unsigned* 5y34[3]
+# asm 1: vmlal.u32 <r1=reg128#15,<v23=reg128#10%bot,<5y34=reg128#13%top
+# asm 2: vmlal.u32 <r1=q14,<v23=d18,<5y34=d25
+vmlal.u32 q14,d18,d25
+
+# qhasm: r1[0,1] += v23[2] unsigned* 5y34[0]; r1[2,3] += v23[3] unsigned* 5y34[1]
+# asm 1: vmlal.u32 <r1=reg128#15,<v23=reg128#10%top,<5y34=reg128#13%bot
+# asm 2: vmlal.u32 <r1=q14,<v23=d19,<5y34=d24
+vmlal.u32 q14,d19,d24
+
+# qhasm: r1[0,1] += v4[0] unsigned* 5y12[2]; r1[2,3] += v4[1] unsigned* 5y12[3]
+# asm 1: vmlal.u32 <r1=reg128#15,<v4=reg128#4%bot,<5y12=reg128#12%top
+# asm 2: vmlal.u32 <r1=q14,<v4=d6,<5y12=d23
+vmlal.u32 q14,d6,d23
+
+# qhasm: r2[0,1] += v01[0] unsigned* y12[2]; r2[2,3] += v01[1] unsigned* y12[3]
+# asm 1: vmlal.u32 <r2=reg128#14,<v01=reg128#11%bot,<y12=reg128#2%top
+# asm 2: vmlal.u32 <r2=q13,<v01=d20,<y12=d3
+vmlal.u32 q13,d20,d3
+
+# qhasm: r2[0,1] += v01[2] unsigned* y12[0]; r2[2,3] += v01[3] unsigned* y12[1]
+# asm 1: vmlal.u32 <r2=reg128#14,<v01=reg128#11%top,<y12=reg128#2%bot
+# asm 2: vmlal.u32 <r2=q13,<v01=d21,<y12=d2
+vmlal.u32 q13,d21,d2
+
+# qhasm: r2[0,1] += v23[0] unsigned* y0[0]; r2[2,3] += v23[1] unsigned* y0[1]
+# asm 1: vmlal.u32 <r2=reg128#14,<v23=reg128#10%bot,<y0=reg128#1%bot
+# asm 2: vmlal.u32 <r2=q13,<v23=d18,<y0=d0
+vmlal.u32 q13,d18,d0
+
+# qhasm: r2[0,1] += v23[2] unsigned* 5y34[2]; r2[2,3] += v23[3] unsigned* 5y34[3]
+# asm 1: vmlal.u32 <r2=reg128#14,<v23=reg128#10%top,<5y34=reg128#13%top
+# asm 2: vmlal.u32 <r2=q13,<v23=d19,<5y34=d25
+vmlal.u32 q13,d19,d25
+
+# qhasm: r2[0,1] += v4[0] unsigned* 5y34[0]; r2[2,3] += v4[1] unsigned* 5y34[1]
+# asm 1: vmlal.u32 <r2=reg128#14,<v4=reg128#4%bot,<5y34=reg128#13%bot
+# asm 2: vmlal.u32 <r2=q13,<v4=d6,<5y34=d24
+vmlal.u32 q13,d6,d24
+
+# qhasm: ptr = &two24
+# asm 1: lea >ptr=int32#3,<two24=stack128#1
+# asm 2: lea >ptr=r2,<two24=[sp,#0]
+add r2,sp,#0
+
+# qhasm: 2x t1 = r0 unsigned>> 26
+# asm 1: vshr.u64 >t1=reg128#4,<r0=reg128#8,#26
+# asm 2: vshr.u64 >t1=q3,<r0=q7,#26
+vshr.u64 q3,q7,#26
+
+# qhasm: len -= 64
+# asm 1: sub >len=int32#4,<len=int32#4,#64
+# asm 2: sub >len=r3,<len=r3,#64
+sub r3,r3,#64
+
+# qhasm: r0 &= mask
+# asm 1: vand >r0=reg128#6,<r0=reg128#8,<mask=reg128#7
+# asm 2: vand >r0=q5,<r0=q7,<mask=q6
+vand q5,q7,q6
+
+# qhasm: 2x r1 += t1
+# asm 1: vadd.i64 >r1=reg128#4,<r1=reg128#15,<t1=reg128#4
+# asm 2: vadd.i64 >r1=q3,<r1=q14,<t1=q3
+vadd.i64 q3,q14,q3
+
+# qhasm: 2x t4 = r3 unsigned>> 26
+# asm 1: vshr.u64 >t4=reg128#8,<r3=reg128#5,#26
+# asm 2: vshr.u64 >t4=q7,<r3=q4,#26
+vshr.u64 q7,q4,#26
+
+# qhasm: r3 &= mask
+# asm 1: vand >r3=reg128#5,<r3=reg128#5,<mask=reg128#7
+# asm 2: vand >r3=q4,<r3=q4,<mask=q6
+vand q4,q4,q6
+
+# qhasm: 2x x4 = r4 + t4
+# asm 1: vadd.i64 >x4=reg128#8,<r4=reg128#16,<t4=reg128#8
+# asm 2: vadd.i64 >x4=q7,<r4=q15,<t4=q7
+vadd.i64 q7,q15,q7
+
+# qhasm: r4 aligned= mem128[ptr]
+# asm 1: vld1.8 {>r4=reg128#16%bot->r4=reg128#16%top},[<ptr=int32#3,: 128]
+# asm 2: vld1.8 {>r4=d30->r4=d31},[<ptr=r2,: 128]
+vld1.8 {d30-d31},[r2,: 128]
+
+# qhasm: 2x t2 = r1 unsigned>> 26
+# asm 1: vshr.u64 >t2=reg128#9,<r1=reg128#4,#26
+# asm 2: vshr.u64 >t2=q8,<r1=q3,#26
+vshr.u64 q8,q3,#26
+
+# qhasm: r1 &= mask
+# asm 1: vand >r1=reg128#4,<r1=reg128#4,<mask=reg128#7
+# asm 2: vand >r1=q3,<r1=q3,<mask=q6
+vand q3,q3,q6
+
+# qhasm: 2x t0 = x4 unsigned>> 26
+# asm 1: vshr.u64 >t0=reg128#10,<x4=reg128#8,#26
+# asm 2: vshr.u64 >t0=q9,<x4=q7,#26
+vshr.u64 q9,q7,#26
+
+# qhasm: 2x r2 += t2
+# asm 1: vadd.i64 >r2=reg128#9,<r2=reg128#14,<t2=reg128#9
+# asm 2: vadd.i64 >r2=q8,<r2=q13,<t2=q8
+vadd.i64 q8,q13,q8
+
+# qhasm: x4 &= mask
+# asm 1: vand >x4=reg128#11,<x4=reg128#8,<mask=reg128#7
+# asm 2: vand >x4=q10,<x4=q7,<mask=q6
+vand q10,q7,q6
+
+# qhasm: 2x x01 = r0 + t0
+# asm 1: vadd.i64 >x01=reg128#6,<r0=reg128#6,<t0=reg128#10
+# asm 2: vadd.i64 >x01=q5,<r0=q5,<t0=q9
+vadd.i64 q5,q5,q9
+
+# qhasm: r0 aligned= mem128[ptr]
+# asm 1: vld1.8 {>r0=reg128#8%bot->r0=reg128#8%top},[<ptr=int32#3,: 128]
+# asm 2: vld1.8 {>r0=d14->r0=d15},[<ptr=r2,: 128]
+vld1.8 {d14-d15},[r2,: 128]
+
+# qhasm: ptr = &z34_stack
+# asm 1: lea >ptr=int32#3,<z34_stack=stack128#9
+# asm 2: lea >ptr=r2,<z34_stack=[sp,#128]
+add r2,sp,#128
+
+# qhasm: 2x t0 <<= 2
+# asm 1: vshl.i64 >t0=reg128#10,<t0=reg128#10,#2
+# asm 2: vshl.i64 >t0=q9,<t0=q9,#2
+vshl.i64 q9,q9,#2
+
+# qhasm: 2x t3 = r2 unsigned>> 26
+# asm 1: vshr.u64 >t3=reg128#14,<r2=reg128#9,#26
+# asm 2: vshr.u64 >t3=q13,<r2=q8,#26
+vshr.u64 q13,q8,#26
+
+# qhasm: 2x x01 += t0
+# asm 1: vadd.i64 >x01=reg128#15,<x01=reg128#6,<t0=reg128#10
+# asm 2: vadd.i64 >x01=q14,<x01=q5,<t0=q9
+vadd.i64 q14,q5,q9
+
+# qhasm: z34 aligned= mem128[ptr]
+# asm 1: vld1.8 {>z34=reg128#6%bot->z34=reg128#6%top},[<ptr=int32#3,: 128]
+# asm 2: vld1.8 {>z34=d10->z34=d11},[<ptr=r2,: 128]
+vld1.8 {d10-d11},[r2,: 128]
+
+# qhasm: x23 = r2 & mask
+# asm 1: vand >x23=reg128#10,<r2=reg128#9,<mask=reg128#7
+# asm 2: vand >x23=q9,<r2=q8,<mask=q6
+vand q9,q8,q6
+
+# qhasm: 2x r3 += t3
+# asm 1: vadd.i64 >r3=reg128#5,<r3=reg128#5,<t3=reg128#14
+# asm 2: vadd.i64 >r3=q4,<r3=q4,<t3=q13
+vadd.i64 q4,q4,q13
+
+# qhasm: input_2 += 32
+# asm 1: add >input_2=int32#2,<input_2=int32#2,#32
+# asm 2: add >input_2=r1,<input_2=r1,#32
+add r1,r1,#32
+
+# qhasm: 2x t1 = x01 unsigned>> 26
+# asm 1: vshr.u64 >t1=reg128#14,<x01=reg128#15,#26
+# asm 2: vshr.u64 >t1=q13,<x01=q14,#26
+vshr.u64 q13,q14,#26
+
+# qhasm: x23 = x23[0,2,1,3]
+# asm 1: vtrn.32 <x23=reg128#10%bot,<x23=reg128#10%top
+# asm 2: vtrn.32 <x23=d18,<x23=d19
+vtrn.32 d18,d19
+
+# qhasm: x01 = x01 & mask
+# asm 1: vand >x01=reg128#9,<x01=reg128#15,<mask=reg128#7
+# asm 2: vand >x01=q8,<x01=q14,<mask=q6
+vand q8,q14,q6
+
+# qhasm: 2x r1 += t1
+# asm 1: vadd.i64 >r1=reg128#4,<r1=reg128#4,<t1=reg128#14
+# asm 2: vadd.i64 >r1=q3,<r1=q3,<t1=q13
+vadd.i64 q3,q3,q13
+
+# qhasm: 2x t4 = r3 unsigned>> 26
+# asm 1: vshr.u64 >t4=reg128#14,<r3=reg128#5,#26
+# asm 2: vshr.u64 >t4=q13,<r3=q4,#26
+vshr.u64 q13,q4,#26
+
+# qhasm: x01 = x01[0,2,1,3]
+# asm 1: vtrn.32 <x01=reg128#9%bot,<x01=reg128#9%top
+# asm 2: vtrn.32 <x01=d16,<x01=d17
+vtrn.32 d16,d17
+
+# qhasm: r3 &= mask
+# asm 1: vand >r3=reg128#5,<r3=reg128#5,<mask=reg128#7
+# asm 2: vand >r3=q4,<r3=q4,<mask=q6
+vand q4,q4,q6
+
+# qhasm: r1 = r1[0,2,1,3]
+# asm 1: vtrn.32 <r1=reg128#4%bot,<r1=reg128#4%top
+# asm 2: vtrn.32 <r1=d6,<r1=d7
+vtrn.32 d6,d7
+
+# qhasm: 2x x4 += t4
+# asm 1: vadd.i64 >x4=reg128#11,<x4=reg128#11,<t4=reg128#14
+# asm 2: vadd.i64 >x4=q10,<x4=q10,<t4=q13
+vadd.i64 q10,q10,q13
+
+# qhasm: r3 = r3[0,2,1,3]
+# asm 1: vtrn.32 <r3=reg128#5%bot,<r3=reg128#5%top
+# asm 2: vtrn.32 <r3=d8,<r3=d9
+vtrn.32 d8,d9
+
+# qhasm: x01 = x01[0,1] r1[0,1]
+# asm 1: vext.32 <x01=reg128#9%top,<r1=reg128#4%bot,<r1=reg128#4%bot,#0
+# asm 2: vext.32 <x01=d17,<r1=d6,<r1=d6,#0
+vext.32 d17,d6,d6,#0
+
+# qhasm: x23 = x23[0,1] r3[0,1]
+# asm 1: vext.32 <x23=reg128#10%top,<r3=reg128#5%bot,<r3=reg128#5%bot,#0
+# asm 2: vext.32 <x23=d19,<r3=d8,<r3=d8,#0
+vext.32 d19,d8,d8,#0
+
+# qhasm: x4 = x4[0,2,1,3]
+# asm 1: vtrn.32 <x4=reg128#11%bot,<x4=reg128#11%top
+# asm 2: vtrn.32 <x4=d20,<x4=d21
+vtrn.32 d20,d21
+
+# qhasm: unsigned>? len - 64
+# asm 1: cmp <len=int32#4,#64
+# asm 2: cmp <len=r3,#64
+cmp r3,#64
+
+# qhasm: goto mainloop2 if unsigned>
+bhi ._mainloop2
+
+# qhasm: input_2 -= 32
+# asm 1: sub >input_2=int32#3,<input_2=int32#2,#32
+# asm 2: sub >input_2=r2,<input_2=r1,#32
+sub r2,r1,#32
+
+# qhasm: below64bytes:
+._below64bytes:
+
+# qhasm: unsigned>? len - 32
+# asm 1: cmp <len=int32#4,#32
+# asm 2: cmp <len=r3,#32
+cmp r3,#32
+
+# qhasm: goto end if !unsigned>
+bls ._end
+
+# qhasm: mainloop:
+._mainloop:
+
+# qhasm: new r0
+
+# qhasm: ptr = &two24
+# asm 1: lea >ptr=int32#2,<two24=stack128#1
+# asm 2: lea >ptr=r1,<two24=[sp,#0]
+add r1,sp,#0
+
+# qhasm: r4 aligned= mem128[ptr]
+# asm 1: vld1.8 {>r4=reg128#5%bot->r4=reg128#5%top},[<ptr=int32#2,: 128]
+# asm 2: vld1.8 {>r4=d8->r4=d9},[<ptr=r1,: 128]
+vld1.8 {d8-d9},[r1,: 128]
+
+# qhasm: u4 aligned= mem128[ptr]
+# asm 1: vld1.8 {>u4=reg128#6%bot->u4=reg128#6%top},[<ptr=int32#2,: 128]
+# asm 2: vld1.8 {>u4=d10->u4=d11},[<ptr=r1,: 128]
+vld1.8 {d10-d11},[r1,: 128]
+
+# qhasm: c01 = mem128[input_2];input_2+=16
+# asm 1: vld1.8 {>c01=reg128#8%bot->c01=reg128#8%top},[<input_2=int32#3]!
+# asm 2: vld1.8 {>c01=d14->c01=d15},[<input_2=r2]!
+vld1.8 {d14-d15},[r2]!
+
+# qhasm: r4[0,1] += x01[0] unsigned* y34[2]; r4[2,3] += x01[1] unsigned* y34[3]
+# asm 1: vmlal.u32 <r4=reg128#5,<x01=reg128#9%bot,<y34=reg128#3%top
+# asm 2: vmlal.u32 <r4=q4,<x01=d16,<y34=d5
+vmlal.u32 q4,d16,d5
+
+# qhasm: c23 = mem128[input_2];input_2+=16
+# asm 1: vld1.8 {>c23=reg128#14%bot->c23=reg128#14%top},[<input_2=int32#3]!
+# asm 2: vld1.8 {>c23=d26->c23=d27},[<input_2=r2]!
+vld1.8 {d26-d27},[r2]!
+
+# qhasm: r4[0,1] += x01[2] unsigned* y34[0]; r4[2,3] += x01[3] unsigned* y34[1]
+# asm 1: vmlal.u32 <r4=reg128#5,<x01=reg128#9%top,<y34=reg128#3%bot
+# asm 2: vmlal.u32 <r4=q4,<x01=d17,<y34=d4
+vmlal.u32 q4,d17,d4
+
+# qhasm: r0 = u4[1]c01[0]r0[2,3]
+# asm 1: vext.32 <r0=reg128#4%bot,<u4=reg128#6%bot,<c01=reg128#8%bot,#1
+# asm 2: vext.32 <r0=d6,<u4=d10,<c01=d14,#1
+vext.32 d6,d10,d14,#1
+
+# qhasm: r4[0,1] += x23[0] unsigned* y12[2]; r4[2,3] += x23[1] unsigned* y12[3]
+# asm 1: vmlal.u32 <r4=reg128#5,<x23=reg128#10%bot,<y12=reg128#2%top
+# asm 2: vmlal.u32 <r4=q4,<x23=d18,<y12=d3
+vmlal.u32 q4,d18,d3
+
+# qhasm: r0 = r0[0,1]u4[1]c23[0]
+# asm 1: vext.32 <r0=reg128#4%top,<u4=reg128#6%bot,<c23=reg128#14%bot,#1
+# asm 2: vext.32 <r0=d7,<u4=d10,<c23=d26,#1
+vext.32 d7,d10,d26,#1
+
+# qhasm: r4[0,1] += x23[2] unsigned* y12[0]; r4[2,3] += x23[3] unsigned* y12[1]
+# asm 1: vmlal.u32 <r4=reg128#5,<x23=reg128#10%top,<y12=reg128#2%bot
+# asm 2: vmlal.u32 <r4=q4,<x23=d19,<y12=d2
+vmlal.u32 q4,d19,d2
+
+# qhasm: r0 = r0[1]r0[0]r0[3]r0[2]
+# asm 1: vrev64.i32 >r0=reg128#4,<r0=reg128#4
+# asm 2: vrev64.i32 >r0=q3,<r0=q3
+vrev64.i32 q3,q3
+
+# qhasm: r4[0,1] += x4[0] unsigned* y0[0]; r4[2,3] += x4[1] unsigned* y0[1]
+# asm 1: vmlal.u32 <r4=reg128#5,<x4=reg128#11%bot,<y0=reg128#1%bot
+# asm 2: vmlal.u32 <r4=q4,<x4=d20,<y0=d0
+vmlal.u32 q4,d20,d0
+
+# qhasm: r0[0,1] += x4[0] unsigned* 5y12[0]; r0[2,3] += x4[1] unsigned* 5y12[1]
+# asm 1: vmlal.u32 <r0=reg128#4,<x4=reg128#11%bot,<5y12=reg128#12%bot
+# asm 2: vmlal.u32 <r0=q3,<x4=d20,<5y12=d22
+vmlal.u32 q3,d20,d22
+
+# qhasm: r0[0,1] += x23[0] unsigned* 5y34[0]; r0[2,3] += x23[1] unsigned* 5y34[1]
+# asm 1: vmlal.u32 <r0=reg128#4,<x23=reg128#10%bot,<5y34=reg128#13%bot
+# asm 2: vmlal.u32 <r0=q3,<x23=d18,<5y34=d24
+vmlal.u32 q3,d18,d24
+
+# qhasm: r0[0,1] += x23[2] unsigned* 5y12[2]; r0[2,3] += x23[3] unsigned* 5y12[3]
+# asm 1: vmlal.u32 <r0=reg128#4,<x23=reg128#10%top,<5y12=reg128#12%top
+# asm 2: vmlal.u32 <r0=q3,<x23=d19,<5y12=d23
+vmlal.u32 q3,d19,d23
+
+# qhasm: c01 c23 = c01[0]c23[0]c01[2]c23[2]c01[1]c23[1]c01[3]c23[3]
+# asm 1: vtrn.32 <c01=reg128#8,<c23=reg128#14
+# asm 2: vtrn.32 <c01=q7,<c23=q13
+vtrn.32 q7,q13
+
+# qhasm: r0[0,1] += x01[0] unsigned* y0[0]; r0[2,3] += x01[1] unsigned* y0[1]
+# asm 1: vmlal.u32 <r0=reg128#4,<x01=reg128#9%bot,<y0=reg128#1%bot
+# asm 2: vmlal.u32 <r0=q3,<x01=d16,<y0=d0
+vmlal.u32 q3,d16,d0
+
+# qhasm: r3[0,1] = c23[2]<<18; r3[2,3] = c23[3]<<18
+# asm 1: vshll.u32 >r3=reg128#6,<c23=reg128#14%top,#18
+# asm 2: vshll.u32 >r3=q5,<c23=d27,#18
+vshll.u32 q5,d27,#18
+
+# qhasm: r0[0,1] += x01[2] unsigned* 5y34[2]; r0[2,3] += x01[3] unsigned* 5y34[3]
+# asm 1: vmlal.u32 <r0=reg128#4,<x01=reg128#9%top,<5y34=reg128#13%top
+# asm 2: vmlal.u32 <r0=q3,<x01=d17,<5y34=d25
+vmlal.u32 q3,d17,d25
+
+# qhasm: r3[0,1] += x01[0] unsigned* y34[0]; r3[2,3] += x01[1] unsigned* y34[1]
+# asm 1: vmlal.u32 <r3=reg128#6,<x01=reg128#9%bot,<y34=reg128#3%bot
+# asm 2: vmlal.u32 <r3=q5,<x01=d16,<y34=d4
+vmlal.u32 q5,d16,d4
+
+# qhasm: r3[0,1] += x01[2] unsigned* y12[2]; r3[2,3] += x01[3] unsigned* y12[3]
+# asm 1: vmlal.u32 <r3=reg128#6,<x01=reg128#9%top,<y12=reg128#2%top
+# asm 2: vmlal.u32 <r3=q5,<x01=d17,<y12=d3
+vmlal.u32 q5,d17,d3
+
+# qhasm: r3[0,1] += x23[0] unsigned* y12[0]; r3[2,3] += x23[1] unsigned* y12[1]
+# asm 1: vmlal.u32 <r3=reg128#6,<x23=reg128#10%bot,<y12=reg128#2%bot
+# asm 2: vmlal.u32 <r3=q5,<x23=d18,<y12=d2
+vmlal.u32 q5,d18,d2
+
+# qhasm: r3[0,1] += x23[2] unsigned* y0[0]; r3[2,3] += x23[3] unsigned* y0[1]
+# asm 1: vmlal.u32 <r3=reg128#6,<x23=reg128#10%top,<y0=reg128#1%bot
+# asm 2: vmlal.u32 <r3=q5,<x23=d19,<y0=d0
+vmlal.u32 q5,d19,d0
+
+# qhasm: r1[0,1] = c23[0]<<6; r1[2,3] = c23[1]<<6
+# asm 1: vshll.u32 >r1=reg128#14,<c23=reg128#14%bot,#6
+# asm 2: vshll.u32 >r1=q13,<c23=d26,#6
+vshll.u32 q13,d26,#6
+
+# qhasm: r3[0,1] += x4[0] unsigned* 5y34[2]; r3[2,3] += x4[1] unsigned* 5y34[3]
+# asm 1: vmlal.u32 <r3=reg128#6,<x4=reg128#11%bot,<5y34=reg128#13%top
+# asm 2: vmlal.u32 <r3=q5,<x4=d20,<5y34=d25
+vmlal.u32 q5,d20,d25
+
+# qhasm: r1[0,1] += x01[0] unsigned* y12[0]; r1[2,3] += x01[1] unsigned* y12[1]
+# asm 1: vmlal.u32 <r1=reg128#14,<x01=reg128#9%bot,<y12=reg128#2%bot
+# asm 2: vmlal.u32 <r1=q13,<x01=d16,<y12=d2
+vmlal.u32 q13,d16,d2
+
+# qhasm: r1[0,1] += x01[2] unsigned* y0[0]; r1[2,3] += x01[3] unsigned* y0[1]
+# asm 1: vmlal.u32 <r1=reg128#14,<x01=reg128#9%top,<y0=reg128#1%bot
+# asm 2: vmlal.u32 <r1=q13,<x01=d17,<y0=d0
+vmlal.u32 q13,d17,d0
+
+# qhasm: r1[0,1] += x23[0] unsigned* 5y34[2]; r1[2,3] += x23[1] unsigned* 5y34[3]
+# asm 1: vmlal.u32 <r1=reg128#14,<x23=reg128#10%bot,<5y34=reg128#13%top
+# asm 2: vmlal.u32 <r1=q13,<x23=d18,<5y34=d25
+vmlal.u32 q13,d18,d25
+
+# qhasm: r1[0,1] += x23[2] unsigned* 5y34[0]; r1[2,3] += x23[3] unsigned* 5y34[1]
+# asm 1: vmlal.u32 <r1=reg128#14,<x23=reg128#10%top,<5y34=reg128#13%bot
+# asm 2: vmlal.u32 <r1=q13,<x23=d19,<5y34=d24
+vmlal.u32 q13,d19,d24
+
+# qhasm: r2[0,1] = c01[2]<<12; r2[2,3] = c01[3]<<12
+# asm 1: vshll.u32 >r2=reg128#8,<c01=reg128#8%top,#12
+# asm 2: vshll.u32 >r2=q7,<c01=d15,#12
+vshll.u32 q7,d15,#12
+
+# qhasm: r1[0,1] += x4[0] unsigned* 5y12[2]; r1[2,3] += x4[1] unsigned* 5y12[3]
+# asm 1: vmlal.u32 <r1=reg128#14,<x4=reg128#11%bot,<5y12=reg128#12%top
+# asm 2: vmlal.u32 <r1=q13,<x4=d20,<5y12=d23
+vmlal.u32 q13,d20,d23
+
+# qhasm: r2[0,1] += x01[0] unsigned* y12[2]; r2[2,3] += x01[1] unsigned* y12[3]
+# asm 1: vmlal.u32 <r2=reg128#8,<x01=reg128#9%bot,<y12=reg128#2%top
+# asm 2: vmlal.u32 <r2=q7,<x01=d16,<y12=d3
+vmlal.u32 q7,d16,d3
+
+# qhasm: r2[0,1] += x01[2] unsigned* y12[0]; r2[2,3] += x01[3] unsigned* y12[1]
+# asm 1: vmlal.u32 <r2=reg128#8,<x01=reg128#9%top,<y12=reg128#2%bot
+# asm 2: vmlal.u32 <r2=q7,<x01=d17,<y12=d2
+vmlal.u32 q7,d17,d2
+
+# qhasm: r2[0,1] += x23[0] unsigned* y0[0]; r2[2,3] += x23[1] unsigned* y0[1]
+# asm 1: vmlal.u32 <r2=reg128#8,<x23=reg128#10%bot,<y0=reg128#1%bot
+# asm 2: vmlal.u32 <r2=q7,<x23=d18,<y0=d0
+vmlal.u32 q7,d18,d0
+
+# qhasm: r2[0,1] += x23[2] unsigned* 5y34[2]; r2[2,3] += x23[3] unsigned* 5y34[3]
+# asm 1: vmlal.u32 <r2=reg128#8,<x23=reg128#10%top,<5y34=reg128#13%top
+# asm 2: vmlal.u32 <r2=q7,<x23=d19,<5y34=d25
+vmlal.u32 q7,d19,d25
+
+# qhasm: r2[0,1] += x4[0] unsigned* 5y34[0]; r2[2,3] += x4[1] unsigned* 5y34[1]
+# asm 1: vmlal.u32 <r2=reg128#8,<x4=reg128#11%bot,<5y34=reg128#13%bot
+# asm 2: vmlal.u32 <r2=q7,<x4=d20,<5y34=d24
+vmlal.u32 q7,d20,d24
+
+# qhasm: 2x t1 = r0 unsigned>> 26
+# asm 1: vshr.u64 >t1=reg128#9,<r0=reg128#4,#26
+# asm 2: vshr.u64 >t1=q8,<r0=q3,#26
+vshr.u64 q8,q3,#26
+
+# qhasm: r0 &= mask
+# asm 1: vand >r0=reg128#4,<r0=reg128#4,<mask=reg128#7
+# asm 2: vand >r0=q3,<r0=q3,<mask=q6
+vand q3,q3,q6
+
+# qhasm: 2x r1 += t1
+# asm 1: vadd.i64 >r1=reg128#9,<r1=reg128#14,<t1=reg128#9
+# asm 2: vadd.i64 >r1=q8,<r1=q13,<t1=q8
+vadd.i64 q8,q13,q8
+
+# qhasm: 2x t4 = r3 unsigned>> 26
+# asm 1: vshr.u64 >t4=reg128#10,<r3=reg128#6,#26
+# asm 2: vshr.u64 >t4=q9,<r3=q5,#26
+vshr.u64 q9,q5,#26
+
+# qhasm: r3 &= mask
+# asm 1: vand >r3=reg128#6,<r3=reg128#6,<mask=reg128#7
+# asm 2: vand >r3=q5,<r3=q5,<mask=q6
+vand q5,q5,q6
+
+# qhasm: 2x r4 += t4
+# asm 1: vadd.i64 >r4=reg128#5,<r4=reg128#5,<t4=reg128#10
+# asm 2: vadd.i64 >r4=q4,<r4=q4,<t4=q9
+vadd.i64 q4,q4,q9
+
+# qhasm: 2x t2 = r1 unsigned>> 26
+# asm 1: vshr.u64 >t2=reg128#10,<r1=reg128#9,#26
+# asm 2: vshr.u64 >t2=q9,<r1=q8,#26
+vshr.u64 q9,q8,#26
+
+# qhasm: r1 &= mask
+# asm 1: vand >r1=reg128#11,<r1=reg128#9,<mask=reg128#7
+# asm 2: vand >r1=q10,<r1=q8,<mask=q6
+vand q10,q8,q6
+
+# qhasm: 2x t0 = r4 unsigned>> 26
+# asm 1: vshr.u64 >t0=reg128#9,<r4=reg128#5,#26
+# asm 2: vshr.u64 >t0=q8,<r4=q4,#26
+vshr.u64 q8,q4,#26
+
+# qhasm: 2x r2 += t2
+# asm 1: vadd.i64 >r2=reg128#8,<r2=reg128#8,<t2=reg128#10
+# asm 2: vadd.i64 >r2=q7,<r2=q7,<t2=q9
+vadd.i64 q7,q7,q9
+
+# qhasm: r4 &= mask
+# asm 1: vand >r4=reg128#5,<r4=reg128#5,<mask=reg128#7
+# asm 2: vand >r4=q4,<r4=q4,<mask=q6
+vand q4,q4,q6
+
+# qhasm: 2x r0 += t0
+# asm 1: vadd.i64 >r0=reg128#4,<r0=reg128#4,<t0=reg128#9
+# asm 2: vadd.i64 >r0=q3,<r0=q3,<t0=q8
+vadd.i64 q3,q3,q8
+
+# qhasm: 2x t0 <<= 2
+# asm 1: vshl.i64 >t0=reg128#9,<t0=reg128#9,#2
+# asm 2: vshl.i64 >t0=q8,<t0=q8,#2
+vshl.i64 q8,q8,#2
+
+# qhasm: 2x t3 = r2 unsigned>> 26
+# asm 1: vshr.u64 >t3=reg128#14,<r2=reg128#8,#26
+# asm 2: vshr.u64 >t3=q13,<r2=q7,#26
+vshr.u64 q13,q7,#26
+
+# qhasm: 2x r0 += t0
+# asm 1: vadd.i64 >r0=reg128#4,<r0=reg128#4,<t0=reg128#9
+# asm 2: vadd.i64 >r0=q3,<r0=q3,<t0=q8
+vadd.i64 q3,q3,q8
+
+# qhasm: x23 = r2 & mask
+# asm 1: vand >x23=reg128#10,<r2=reg128#8,<mask=reg128#7
+# asm 2: vand >x23=q9,<r2=q7,<mask=q6
+vand q9,q7,q6
+
+# qhasm: 2x r3 += t3
+# asm 1: vadd.i64 >r3=reg128#6,<r3=reg128#6,<t3=reg128#14
+# asm 2: vadd.i64 >r3=q5,<r3=q5,<t3=q13
+vadd.i64 q5,q5,q13
+
+# qhasm: 2x t1 = r0 unsigned>> 26
+# asm 1: vshr.u64 >t1=reg128#8,<r0=reg128#4,#26
+# asm 2: vshr.u64 >t1=q7,<r0=q3,#26
+vshr.u64 q7,q3,#26
+
+# qhasm: x01 = r0 & mask
+# asm 1: vand >x01=reg128#9,<r0=reg128#4,<mask=reg128#7
+# asm 2: vand >x01=q8,<r0=q3,<mask=q6
+vand q8,q3,q6
+
+# qhasm: 2x r1 += t1
+# asm 1: vadd.i64 >r1=reg128#4,<r1=reg128#11,<t1=reg128#8
+# asm 2: vadd.i64 >r1=q3,<r1=q10,<t1=q7
+vadd.i64 q3,q10,q7
+
+# qhasm: 2x t4 = r3 unsigned>> 26
+# asm 1: vshr.u64 >t4=reg128#8,<r3=reg128#6,#26
+# asm 2: vshr.u64 >t4=q7,<r3=q5,#26
+vshr.u64 q7,q5,#26
+
+# qhasm: r3 &= mask
+# asm 1: vand >r3=reg128#6,<r3=reg128#6,<mask=reg128#7
+# asm 2: vand >r3=q5,<r3=q5,<mask=q6
+vand q5,q5,q6
+
+# qhasm: 2x x4 = r4 + t4
+# asm 1: vadd.i64 >x4=reg128#11,<r4=reg128#5,<t4=reg128#8
+# asm 2: vadd.i64 >x4=q10,<r4=q4,<t4=q7
+vadd.i64 q10,q4,q7
+
+# qhasm: len -= 32
+# asm 1: sub >len=int32#4,<len=int32#4,#32
+# asm 2: sub >len=r3,<len=r3,#32
+sub r3,r3,#32
+
+# qhasm: x01 = x01[0,2,1,3]
+# asm 1: vtrn.32 <x01=reg128#9%bot,<x01=reg128#9%top
+# asm 2: vtrn.32 <x01=d16,<x01=d17
+vtrn.32 d16,d17
+
+# qhasm: x23 = x23[0,2,1,3]
+# asm 1: vtrn.32 <x23=reg128#10%bot,<x23=reg128#10%top
+# asm 2: vtrn.32 <x23=d18,<x23=d19
+vtrn.32 d18,d19
+
+# qhasm: r1 = r1[0,2,1,3]
+# asm 1: vtrn.32 <r1=reg128#4%bot,<r1=reg128#4%top
+# asm 2: vtrn.32 <r1=d6,<r1=d7
+vtrn.32 d6,d7
+
+# qhasm: r3 = r3[0,2,1,3]
+# asm 1: vtrn.32 <r3=reg128#6%bot,<r3=reg128#6%top
+# asm 2: vtrn.32 <r3=d10,<r3=d11
+vtrn.32 d10,d11
+
+# qhasm: x4 = x4[0,2,1,3]
+# asm 1: vtrn.32 <x4=reg128#11%bot,<x4=reg128#11%top
+# asm 2: vtrn.32 <x4=d20,<x4=d21
+vtrn.32 d20,d21
+
+# qhasm: x01 = x01[0,1] r1[0,1]
+# asm 1: vext.32 <x01=reg128#9%top,<r1=reg128#4%bot,<r1=reg128#4%bot,#0
+# asm 2: vext.32 <x01=d17,<r1=d6,<r1=d6,#0
+vext.32 d17,d6,d6,#0
+
+# qhasm: x23 = x23[0,1] r3[0,1]
+# asm 1: vext.32 <x23=reg128#10%top,<r3=reg128#6%bot,<r3=reg128#6%bot,#0
+# asm 2: vext.32 <x23=d19,<r3=d10,<r3=d10,#0
+vext.32 d19,d10,d10,#0
+
+# qhasm: unsigned>? len - 32
+# asm 1: cmp <len=int32#4,#32
+# asm 2: cmp <len=r3,#32
+cmp r3,#32
+
+# qhasm: goto mainloop if unsigned>
+bhi ._mainloop
+
+# qhasm: end:
+._end:
+
+# qhasm: mem128[input_0] = x01;input_0+=16
+# asm 1: vst1.8 {<x01=reg128#9%bot-<x01=reg128#9%top},[<input_0=int32#1]!
+# asm 2: vst1.8 {<x01=d16-<x01=d17},[<input_0=r0]!
+vst1.8 {d16-d17},[r0]!
+
+# qhasm: mem128[input_0] = x23;input_0+=16
+# asm 1: vst1.8 {<x23=reg128#10%bot-<x23=reg128#10%top},[<input_0=int32#1]!
+# asm 2: vst1.8 {<x23=d18-<x23=d19},[<input_0=r0]!
+vst1.8 {d18-d19},[r0]!
+
+# qhasm: mem64[input_0] = x4[0]
+# asm 1: vst1.8 <x4=reg128#11%bot,[<input_0=int32#1]
+# asm 2: vst1.8 <x4=d20,[<input_0=r0]
+vst1.8 d20,[r0]
+
+# qhasm: len = len
+# asm 1: mov >len=int32#1,<len=int32#4
+# asm 2: mov >len=r0,<len=r3
+mov r0,r3
+
+# qhasm: qpopreturn len
+mov sp,r12
+vpop {q4,q5,q6,q7}
+bx lr
+
+# qhasm: int32 input_0
+
+# qhasm: int32 input_1
+
+# qhasm: int32 input_2
+
+# qhasm: int32 input_3
+
+# qhasm: stack32 input_4
+
+# qhasm: stack32 input_5
+
+# qhasm: stack32 input_6
+
+# qhasm: stack32 input_7
+
+# qhasm: int32 caller_r4
+
+# qhasm: int32 caller_r5
+
+# qhasm: int32 caller_r6
+
+# qhasm: int32 caller_r7
+
+# qhasm: int32 caller_r8
+
+# qhasm: int32 caller_r9
+
+# qhasm: int32 caller_r10
+
+# qhasm: int32 caller_r11
+
+# qhasm: int32 caller_r12
+
+# qhasm: int32 caller_r14
+
+# qhasm: reg128 caller_q4
+
+# qhasm: reg128 caller_q5
+
+# qhasm: reg128 caller_q6
+
+# qhasm: reg128 caller_q7
+
+# qhasm: reg128 r0
+
+# qhasm: reg128 r1
+
+# qhasm: reg128 r2
+
+# qhasm: reg128 r3
+
+# qhasm: reg128 r4
+
+# qhasm: reg128 x01
+
+# qhasm: reg128 x23
+
+# qhasm: reg128 x4
+
+# qhasm: reg128 y01
+
+# qhasm: reg128 y23
+
+# qhasm: reg128 y4
+
+# qhasm: reg128 _5y01
+
+# qhasm: reg128 _5y23
+
+# qhasm: reg128 _5y4
+
+# qhasm: reg128 c01
+
+# qhasm: reg128 c23
+
+# qhasm: reg128 c4
+
+# qhasm: reg128 t0
+
+# qhasm: reg128 t1
+
+# qhasm: reg128 t2
+
+# qhasm: reg128 t3
+
+# qhasm: reg128 t4
+
+# qhasm: reg128 mask
+
+# qhasm: enter crypto_onetimeauth_poly1305_neon2_addmulmod
+.align 2
+.global openssl_poly1305_neon2_addmulmod
+.hidden openssl_poly1305_neon2_addmulmod
+.type openssl_poly1305_neon2_addmulmod STT_FUNC
+openssl_poly1305_neon2_addmulmod:
+sub sp,sp,#0
+
+# qhasm: 2x mask = 0xffffffff
+# asm 1: vmov.i64 >mask=reg128#1,#0xffffffff
+# asm 2: vmov.i64 >mask=q0,#0xffffffff
+vmov.i64 q0,#0xffffffff
+
+# qhasm: y01 aligned= mem128[input_2];input_2+=16
+# asm 1: vld1.8 {>y01=reg128#2%bot->y01=reg128#2%top},[<input_2=int32#3,: 128]!
+# asm 2: vld1.8 {>y01=d2->y01=d3},[<input_2=r2,: 128]!
+vld1.8 {d2-d3},[r2,: 128]!
+
+# qhasm: 4x _5y01 = y01 << 2
+# asm 1: vshl.i32 >_5y01=reg128#3,<y01=reg128#2,#2
+# asm 2: vshl.i32 >_5y01=q2,<y01=q1,#2
+vshl.i32 q2,q1,#2
+
+# qhasm: y23 aligned= mem128[input_2];input_2+=16
+# asm 1: vld1.8 {>y23=reg128#4%bot->y23=reg128#4%top},[<input_2=int32#3,: 128]!
+# asm 2: vld1.8 {>y23=d6->y23=d7},[<input_2=r2,: 128]!
+vld1.8 {d6-d7},[r2,: 128]!
+
+# qhasm: 4x _5y23 = y23 << 2
+# asm 1: vshl.i32 >_5y23=reg128#9,<y23=reg128#4,#2
+# asm 2: vshl.i32 >_5y23=q8,<y23=q3,#2
+vshl.i32 q8,q3,#2
+
+# qhasm: y4 aligned= mem64[input_2]y4[1]
+# asm 1: vld1.8 {<y4=reg128#10%bot},[<input_2=int32#3,: 64]
+# asm 2: vld1.8 {<y4=d18},[<input_2=r2,: 64]
+vld1.8 {d18},[r2,: 64]
+
+# qhasm: 4x _5y4 = y4 << 2
+# asm 1: vshl.i32 >_5y4=reg128#11,<y4=reg128#10,#2
+# asm 2: vshl.i32 >_5y4=q10,<y4=q9,#2
+vshl.i32 q10,q9,#2
+
+# qhasm: x01 aligned= mem128[input_1];input_1+=16
+# asm 1: vld1.8 {>x01=reg128#12%bot->x01=reg128#12%top},[<input_1=int32#2,: 128]!
+# asm 2: vld1.8 {>x01=d22->x01=d23},[<input_1=r1,: 128]!
+vld1.8 {d22-d23},[r1,: 128]!
+
+# qhasm: 4x _5y01 += y01
+# asm 1: vadd.i32 >_5y01=reg128#3,<_5y01=reg128#3,<y01=reg128#2
+# asm 2: vadd.i32 >_5y01=q2,<_5y01=q2,<y01=q1
+vadd.i32 q2,q2,q1
+
+# qhasm: x23 aligned= mem128[input_1];input_1+=16
+# asm 1: vld1.8 {>x23=reg128#13%bot->x23=reg128#13%top},[<input_1=int32#2,: 128]!
+# asm 2: vld1.8 {>x23=d24->x23=d25},[<input_1=r1,: 128]!
+vld1.8 {d24-d25},[r1,: 128]!
+
+# qhasm: 4x _5y23 += y23
+# asm 1: vadd.i32 >_5y23=reg128#9,<_5y23=reg128#9,<y23=reg128#4
+# asm 2: vadd.i32 >_5y23=q8,<_5y23=q8,<y23=q3
+vadd.i32 q8,q8,q3
+
+# qhasm: 4x _5y4 += y4
+# asm 1: vadd.i32 >_5y4=reg128#11,<_5y4=reg128#11,<y4=reg128#10
+# asm 2: vadd.i32 >_5y4=q10,<_5y4=q10,<y4=q9
+vadd.i32 q10,q10,q9
+
+# qhasm: c01 aligned= mem128[input_3];input_3+=16
+# asm 1: vld1.8 {>c01=reg128#14%bot->c01=reg128#14%top},[<input_3=int32#4,: 128]!
+# asm 2: vld1.8 {>c01=d26->c01=d27},[<input_3=r3,: 128]!
+vld1.8 {d26-d27},[r3,: 128]!
+
+# qhasm: 4x x01 += c01
+# asm 1: vadd.i32 >x01=reg128#12,<x01=reg128#12,<c01=reg128#14
+# asm 2: vadd.i32 >x01=q11,<x01=q11,<c01=q13
+vadd.i32 q11,q11,q13
+
+# qhasm: c23 aligned= mem128[input_3];input_3+=16
+# asm 1: vld1.8 {>c23=reg128#14%bot->c23=reg128#14%top},[<input_3=int32#4,: 128]!
+# asm 2: vld1.8 {>c23=d26->c23=d27},[<input_3=r3,: 128]!
+vld1.8 {d26-d27},[r3,: 128]!
+
+# qhasm: 4x x23 += c23
+# asm 1: vadd.i32 >x23=reg128#13,<x23=reg128#13,<c23=reg128#14
+# asm 2: vadd.i32 >x23=q12,<x23=q12,<c23=q13
+vadd.i32 q12,q12,q13
+
+# qhasm: x4 aligned= mem64[input_1]x4[1]
+# asm 1: vld1.8 {<x4=reg128#14%bot},[<input_1=int32#2,: 64]
+# asm 2: vld1.8 {<x4=d26},[<input_1=r1,: 64]
+vld1.8 {d26},[r1,: 64]
+
+# qhasm: 2x mask unsigned>>=6
+# asm 1: vshr.u64 >mask=reg128#1,<mask=reg128#1,#6
+# asm 2: vshr.u64 >mask=q0,<mask=q0,#6
+vshr.u64 q0,q0,#6
+
+# qhasm: c4 aligned= mem64[input_3]c4[1]
+# asm 1: vld1.8 {<c4=reg128#15%bot},[<input_3=int32#4,: 64]
+# asm 2: vld1.8 {<c4=d28},[<input_3=r3,: 64]
+vld1.8 {d28},[r3,: 64]
+
+# qhasm: 4x x4 += c4
+# asm 1: vadd.i32 >x4=reg128#14,<x4=reg128#14,<c4=reg128#15
+# asm 2: vadd.i32 >x4=q13,<x4=q13,<c4=q14
+vadd.i32 q13,q13,q14
+
+# qhasm: r0[0,1] = x01[0] unsigned* y01[0]; r0[2,3] = x01[1] unsigned* y01[1]
+# asm 1: vmull.u32 >r0=reg128#15,<x01=reg128#12%bot,<y01=reg128#2%bot
+# asm 2: vmull.u32 >r0=q14,<x01=d22,<y01=d2
+vmull.u32 q14,d22,d2
+
+# qhasm: r0[0,1] += x01[2] unsigned* _5y4[0]; r0[2,3] += x01[3] unsigned* _5y4[1]
+# asm 1: vmlal.u32 <r0=reg128#15,<x01=reg128#12%top,<_5y4=reg128#11%bot
+# asm 2: vmlal.u32 <r0=q14,<x01=d23,<_5y4=d20
+vmlal.u32 q14,d23,d20
+
+# qhasm: r0[0,1] += x23[0] unsigned* _5y23[2]; r0[2,3] += x23[1] unsigned* _5y23[3]
+# asm 1: vmlal.u32 <r0=reg128#15,<x23=reg128#13%bot,<_5y23=reg128#9%top
+# asm 2: vmlal.u32 <r0=q14,<x23=d24,<_5y23=d17
+vmlal.u32 q14,d24,d17
+
+# qhasm: r0[0,1] += x23[2] unsigned* _5y23[0]; r0[2,3] += x23[3] unsigned* _5y23[1]
+# asm 1: vmlal.u32 <r0=reg128#15,<x23=reg128#13%top,<_5y23=reg128#9%bot
+# asm 2: vmlal.u32 <r0=q14,<x23=d25,<_5y23=d16
+vmlal.u32 q14,d25,d16
+
+# qhasm: r0[0,1] += x4[0] unsigned* _5y01[2]; r0[2,3] += x4[1] unsigned* _5y01[3]
+# asm 1: vmlal.u32 <r0=reg128#15,<x4=reg128#14%bot,<_5y01=reg128#3%top
+# asm 2: vmlal.u32 <r0=q14,<x4=d26,<_5y01=d5
+vmlal.u32 q14,d26,d5
+
+# qhasm: r1[0,1] = x01[0] unsigned* y01[2]; r1[2,3] = x01[1] unsigned* y01[3]
+# asm 1: vmull.u32 >r1=reg128#3,<x01=reg128#12%bot,<y01=reg128#2%top
+# asm 2: vmull.u32 >r1=q2,<x01=d22,<y01=d3
+vmull.u32 q2,d22,d3
+
+# qhasm: r1[0,1] += x01[2] unsigned* y01[0]; r1[2,3] += x01[3] unsigned* y01[1]
+# asm 1: vmlal.u32 <r1=reg128#3,<x01=reg128#12%top,<y01=reg128#2%bot
+# asm 2: vmlal.u32 <r1=q2,<x01=d23,<y01=d2
+vmlal.u32 q2,d23,d2
+
+# qhasm: r1[0,1] += x23[0] unsigned* _5y4[0]; r1[2,3] += x23[1] unsigned* _5y4[1]
+# asm 1: vmlal.u32 <r1=reg128#3,<x23=reg128#13%bot,<_5y4=reg128#11%bot
+# asm 2: vmlal.u32 <r1=q2,<x23=d24,<_5y4=d20
+vmlal.u32 q2,d24,d20
+
+# qhasm: r1[0,1] += x23[2] unsigned* _5y23[2]; r1[2,3] += x23[3] unsigned* _5y23[3]
+# asm 1: vmlal.u32 <r1=reg128#3,<x23=reg128#13%top,<_5y23=reg128#9%top
+# asm 2: vmlal.u32 <r1=q2,<x23=d25,<_5y23=d17
+vmlal.u32 q2,d25,d17
+
+# qhasm: r1[0,1] += x4[0] unsigned* _5y23[0]; r1[2,3] += x4[1] unsigned* _5y23[1]
+# asm 1: vmlal.u32 <r1=reg128#3,<x4=reg128#14%bot,<_5y23=reg128#9%bot
+# asm 2: vmlal.u32 <r1=q2,<x4=d26,<_5y23=d16
+vmlal.u32 q2,d26,d16
+
+# qhasm: r2[0,1] = x01[0] unsigned* y23[0]; r2[2,3] = x01[1] unsigned* y23[1]
+# asm 1: vmull.u32 >r2=reg128#16,<x01=reg128#12%bot,<y23=reg128#4%bot
+# asm 2: vmull.u32 >r2=q15,<x01=d22,<y23=d6
+vmull.u32 q15,d22,d6
+
+# qhasm: r2[0,1] += x01[2] unsigned* y01[2]; r2[2,3] += x01[3] unsigned* y01[3]
+# asm 1: vmlal.u32 <r2=reg128#16,<x01=reg128#12%top,<y01=reg128#2%top
+# asm 2: vmlal.u32 <r2=q15,<x01=d23,<y01=d3
+vmlal.u32 q15,d23,d3
+
+# qhasm: r2[0,1] += x23[0] unsigned* y01[0]; r2[2,3] += x23[1] unsigned* y01[1]
+# asm 1: vmlal.u32 <r2=reg128#16,<x23=reg128#13%bot,<y01=reg128#2%bot
+# asm 2: vmlal.u32 <r2=q15,<x23=d24,<y01=d2
+vmlal.u32 q15,d24,d2
+
+# qhasm: r2[0,1] += x23[2] unsigned* _5y4[0]; r2[2,3] += x23[3] unsigned* _5y4[1]
+# asm 1: vmlal.u32 <r2=reg128#16,<x23=reg128#13%top,<_5y4=reg128#11%bot
+# asm 2: vmlal.u32 <r2=q15,<x23=d25,<_5y4=d20
+vmlal.u32 q15,d25,d20
+
+# qhasm: r2[0,1] += x4[0] unsigned* _5y23[2]; r2[2,3] += x4[1] unsigned* _5y23[3]
+# asm 1: vmlal.u32 <r2=reg128#16,<x4=reg128#14%bot,<_5y23=reg128#9%top
+# asm 2: vmlal.u32 <r2=q15,<x4=d26,<_5y23=d17
+vmlal.u32 q15,d26,d17
+
+# qhasm: r3[0,1] = x01[0] unsigned* y23[2]; r3[2,3] = x01[1] unsigned* y23[3]
+# asm 1: vmull.u32 >r3=reg128#9,<x01=reg128#12%bot,<y23=reg128#4%top
+# asm 2: vmull.u32 >r3=q8,<x01=d22,<y23=d7
+vmull.u32 q8,d22,d7
+
+# qhasm: r3[0,1] += x01[2] unsigned* y23[0]; r3[2,3] += x01[3] unsigned* y23[1]
+# asm 1: vmlal.u32 <r3=reg128#9,<x01=reg128#12%top,<y23=reg128#4%bot
+# asm 2: vmlal.u32 <r3=q8,<x01=d23,<y23=d6
+vmlal.u32 q8,d23,d6
+
+# qhasm: r3[0,1] += x23[0] unsigned* y01[2]; r3[2,3] += x23[1] unsigned* y01[3]
+# asm 1: vmlal.u32 <r3=reg128#9,<x23=reg128#13%bot,<y01=reg128#2%top
+# asm 2: vmlal.u32 <r3=q8,<x23=d24,<y01=d3
+vmlal.u32 q8,d24,d3
+
+# qhasm: r3[0,1] += x23[2] unsigned* y01[0]; r3[2,3] += x23[3] unsigned* y01[1]
+# asm 1: vmlal.u32 <r3=reg128#9,<x23=reg128#13%top,<y01=reg128#2%bot
+# asm 2: vmlal.u32 <r3=q8,<x23=d25,<y01=d2
+vmlal.u32 q8,d25,d2
+
+# qhasm: r3[0,1] += x4[0] unsigned* _5y4[0]; r3[2,3] += x4[1] unsigned* _5y4[1]
+# asm 1: vmlal.u32 <r3=reg128#9,<x4=reg128#14%bot,<_5y4=reg128#11%bot
+# asm 2: vmlal.u32 <r3=q8,<x4=d26,<_5y4=d20
+vmlal.u32 q8,d26,d20
+
+# qhasm: r4[0,1] = x01[0] unsigned* y4[0]; r4[2,3] = x01[1] unsigned* y4[1]
+# asm 1: vmull.u32 >r4=reg128#10,<x01=reg128#12%bot,<y4=reg128#10%bot
+# asm 2: vmull.u32 >r4=q9,<x01=d22,<y4=d18
+vmull.u32 q9,d22,d18
+
+# qhasm: r4[0,1] += x01[2] unsigned* y23[2]; r4[2,3] += x01[3] unsigned* y23[3]
+# asm 1: vmlal.u32 <r4=reg128#10,<x01=reg128#12%top,<y23=reg128#4%top
+# asm 2: vmlal.u32 <r4=q9,<x01=d23,<y23=d7
+vmlal.u32 q9,d23,d7
+
+# qhasm: r4[0,1] += x23[0] unsigned* y23[0]; r4[2,3] += x23[1] unsigned* y23[1]
+# asm 1: vmlal.u32 <r4=reg128#10,<x23=reg128#13%bot,<y23=reg128#4%bot
+# asm 2: vmlal.u32 <r4=q9,<x23=d24,<y23=d6
+vmlal.u32 q9,d24,d6
+
+# qhasm: r4[0,1] += x23[2] unsigned* y01[2]; r4[2,3] += x23[3] unsigned* y01[3]
+# asm 1: vmlal.u32 <r4=reg128#10,<x23=reg128#13%top,<y01=reg128#2%top
+# asm 2: vmlal.u32 <r4=q9,<x23=d25,<y01=d3
+vmlal.u32 q9,d25,d3
+
+# qhasm: r4[0,1] += x4[0] unsigned* y01[0]; r4[2,3] += x4[1] unsigned* y01[1]
+# asm 1: vmlal.u32 <r4=reg128#10,<x4=reg128#14%bot,<y01=reg128#2%bot
+# asm 2: vmlal.u32 <r4=q9,<x4=d26,<y01=d2
+vmlal.u32 q9,d26,d2
+
+# qhasm: 2x t1 = r0 unsigned>> 26
+# asm 1: vshr.u64 >t1=reg128#2,<r0=reg128#15,#26
+# asm 2: vshr.u64 >t1=q1,<r0=q14,#26
+vshr.u64 q1,q14,#26
+
+# qhasm: r0 &= mask
+# asm 1: vand >r0=reg128#4,<r0=reg128#15,<mask=reg128#1
+# asm 2: vand >r0=q3,<r0=q14,<mask=q0
+vand q3,q14,q0
+
+# qhasm: 2x r1 += t1
+# asm 1: vadd.i64 >r1=reg128#2,<r1=reg128#3,<t1=reg128#2
+# asm 2: vadd.i64 >r1=q1,<r1=q2,<t1=q1
+vadd.i64 q1,q2,q1
+
+# qhasm: 2x t4 = r3 unsigned>> 26
+# asm 1: vshr.u64 >t4=reg128#3,<r3=reg128#9,#26
+# asm 2: vshr.u64 >t4=q2,<r3=q8,#26
+vshr.u64 q2,q8,#26
+
+# qhasm: r3 &= mask
+# asm 1: vand >r3=reg128#9,<r3=reg128#9,<mask=reg128#1
+# asm 2: vand >r3=q8,<r3=q8,<mask=q0
+vand q8,q8,q0
+
+# qhasm: 2x r4 += t4
+# asm 1: vadd.i64 >r4=reg128#3,<r4=reg128#10,<t4=reg128#3
+# asm 2: vadd.i64 >r4=q2,<r4=q9,<t4=q2
+vadd.i64 q2,q9,q2
+
+# qhasm: 2x t2 = r1 unsigned>> 26
+# asm 1: vshr.u64 >t2=reg128#10,<r1=reg128#2,#26
+# asm 2: vshr.u64 >t2=q9,<r1=q1,#26
+vshr.u64 q9,q1,#26
+
+# qhasm: r1 &= mask
+# asm 1: vand >r1=reg128#2,<r1=reg128#2,<mask=reg128#1
+# asm 2: vand >r1=q1,<r1=q1,<mask=q0
+vand q1,q1,q0
+
+# qhasm: 2x t0 = r4 unsigned>> 26
+# asm 1: vshr.u64 >t0=reg128#11,<r4=reg128#3,#26
+# asm 2: vshr.u64 >t0=q10,<r4=q2,#26
+vshr.u64 q10,q2,#26
+
+# qhasm: 2x r2 += t2
+# asm 1: vadd.i64 >r2=reg128#10,<r2=reg128#16,<t2=reg128#10
+# asm 2: vadd.i64 >r2=q9,<r2=q15,<t2=q9
+vadd.i64 q9,q15,q9
+
+# qhasm: r4 &= mask
+# asm 1: vand >r4=reg128#3,<r4=reg128#3,<mask=reg128#1
+# asm 2: vand >r4=q2,<r4=q2,<mask=q0
+vand q2,q2,q0
+
+# qhasm: 2x r0 += t0
+# asm 1: vadd.i64 >r0=reg128#4,<r0=reg128#4,<t0=reg128#11
+# asm 2: vadd.i64 >r0=q3,<r0=q3,<t0=q10
+vadd.i64 q3,q3,q10
+
+# qhasm: 2x t0 <<= 2
+# asm 1: vshl.i64 >t0=reg128#11,<t0=reg128#11,#2
+# asm 2: vshl.i64 >t0=q10,<t0=q10,#2
+vshl.i64 q10,q10,#2
+
+# qhasm: 2x t3 = r2 unsigned>> 26
+# asm 1: vshr.u64 >t3=reg128#12,<r2=reg128#10,#26
+# asm 2: vshr.u64 >t3=q11,<r2=q9,#26
+vshr.u64 q11,q9,#26
+
+# qhasm: 2x r0 += t0
+# asm 1: vadd.i64 >r0=reg128#4,<r0=reg128#4,<t0=reg128#11
+# asm 2: vadd.i64 >r0=q3,<r0=q3,<t0=q10
+vadd.i64 q3,q3,q10
+
+# qhasm: x23 = r2 & mask
+# asm 1: vand >x23=reg128#10,<r2=reg128#10,<mask=reg128#1
+# asm 2: vand >x23=q9,<r2=q9,<mask=q0
+vand q9,q9,q0
+
+# qhasm: 2x r3 += t3
+# asm 1: vadd.i64 >r3=reg128#9,<r3=reg128#9,<t3=reg128#12
+# asm 2: vadd.i64 >r3=q8,<r3=q8,<t3=q11
+vadd.i64 q8,q8,q11
+
+# qhasm: 2x t1 = r0 unsigned>> 26
+# asm 1: vshr.u64 >t1=reg128#11,<r0=reg128#4,#26
+# asm 2: vshr.u64 >t1=q10,<r0=q3,#26
+vshr.u64 q10,q3,#26
+
+# qhasm: x23 = x23[0,2,1,3]
+# asm 1: vtrn.32 <x23=reg128#10%bot,<x23=reg128#10%top
+# asm 2: vtrn.32 <x23=d18,<x23=d19
+vtrn.32 d18,d19
+
+# qhasm: x01 = r0 & mask
+# asm 1: vand >x01=reg128#4,<r0=reg128#4,<mask=reg128#1
+# asm 2: vand >x01=q3,<r0=q3,<mask=q0
+vand q3,q3,q0
+
+# qhasm: 2x r1 += t1
+# asm 1: vadd.i64 >r1=reg128#2,<r1=reg128#2,<t1=reg128#11
+# asm 2: vadd.i64 >r1=q1,<r1=q1,<t1=q10
+vadd.i64 q1,q1,q10
+
+# qhasm: 2x t4 = r3 unsigned>> 26
+# asm 1: vshr.u64 >t4=reg128#11,<r3=reg128#9,#26
+# asm 2: vshr.u64 >t4=q10,<r3=q8,#26
+vshr.u64 q10,q8,#26
+
+# qhasm: x01 = x01[0,2,1,3]
+# asm 1: vtrn.32 <x01=reg128#4%bot,<x01=reg128#4%top
+# asm 2: vtrn.32 <x01=d6,<x01=d7
+vtrn.32 d6,d7
+
+# qhasm: r3 &= mask
+# asm 1: vand >r3=reg128#1,<r3=reg128#9,<mask=reg128#1
+# asm 2: vand >r3=q0,<r3=q8,<mask=q0
+vand q0,q8,q0
+
+# qhasm: r1 = r1[0,2,1,3]
+# asm 1: vtrn.32 <r1=reg128#2%bot,<r1=reg128#2%top
+# asm 2: vtrn.32 <r1=d2,<r1=d3
+vtrn.32 d2,d3
+
+# qhasm: 2x x4 = r4 + t4
+# asm 1: vadd.i64 >x4=reg128#3,<r4=reg128#3,<t4=reg128#11
+# asm 2: vadd.i64 >x4=q2,<r4=q2,<t4=q10
+vadd.i64 q2,q2,q10
+
+# qhasm: r3 = r3[0,2,1,3]
+# asm 1: vtrn.32 <r3=reg128#1%bot,<r3=reg128#1%top
+# asm 2: vtrn.32 <r3=d0,<r3=d1
+vtrn.32 d0,d1
+
+# qhasm: x01 = x01[0,1] r1[0,1]
+# asm 1: vext.32 <x01=reg128#4%top,<r1=reg128#2%bot,<r1=reg128#2%bot,#0
+# asm 2: vext.32 <x01=d7,<r1=d2,<r1=d2,#0
+vext.32 d7,d2,d2,#0
+
+# qhasm: x23 = x23[0,1] r3[0,1]
+# asm 1: vext.32 <x23=reg128#10%top,<r3=reg128#1%bot,<r3=reg128#1%bot,#0
+# asm 2: vext.32 <x23=d19,<r3=d0,<r3=d0,#0
+vext.32 d19,d0,d0,#0
+
+# qhasm: x4 = x4[0,2,1,3]
+# asm 1: vtrn.32 <x4=reg128#3%bot,<x4=reg128#3%top
+# asm 2: vtrn.32 <x4=d4,<x4=d5
+vtrn.32 d4,d5
+
+# qhasm: mem128[input_0] aligned= x01;input_0+=16
+# asm 1: vst1.8 {<x01=reg128#4%bot-<x01=reg128#4%top},[<input_0=int32#1,: 128]!
+# asm 2: vst1.8 {<x01=d6-<x01=d7},[<input_0=r0,: 128]!
+vst1.8 {d6-d7},[r0,: 128]!
+
+# qhasm: mem128[input_0] aligned= x23;input_0+=16
+# asm 1: vst1.8 {<x23=reg128#10%bot-<x23=reg128#10%top},[<input_0=int32#1,: 128]!
+# asm 2: vst1.8 {<x23=d18-<x23=d19},[<input_0=r0,: 128]!
+vst1.8 {d18-d19},[r0,: 128]!
+
+# qhasm: mem64[input_0] aligned= x4[0]
+# asm 1: vst1.8 <x4=reg128#3%bot,[<input_0=int32#1,: 64]
+# asm 2: vst1.8 <x4=d4,[<input_0=r0,: 64]
+vst1.8 d4,[r0,: 64]
+
+# qhasm: return
+add sp,sp,#0
+bx lr
+
+#endif /* __arm__ && !OPENSSL_NO_ASM */
diff --git a/src/crypto/poly1305/poly1305_vec.c b/src/crypto/poly1305/poly1305_vec.c
new file mode 100644
index 0000000..89fcacb
--- /dev/null
+++ b/src/crypto/poly1305/poly1305_vec.c
@@ -0,0 +1,887 @@
+/* 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. */
+
+/* This implementation of poly1305 is by Andrew Moon
+ * (https://github.com/floodyberry/poly1305-donna) and released as public
+ * domain. It implements SIMD vectorization based on the algorithm described in
+ * http://cr.yp.to/papers.html#neoncrypto. Unrolled to 2 powers, i.e. 64 byte
+ * block size */
+
+#include <openssl/poly1305.h>
+
+
+#if !defined(OPENSSL_WINDOWS) && defined(OPENSSL_X86_64)
+
+#include <emmintrin.h>
+
+#define ALIGN(x) __attribute__((aligned(x)))
+/* inline is not a keyword in C89. */
+#define INLINE
+#define U8TO64_LE(m) (*(uint64_t *)(m))
+#define U8TO32_LE(m) (*(uint32_t *)(m))
+#define U64TO8_LE(m, v) (*(uint64_t *)(m)) = v
+
+typedef __m128i xmmi;
+typedef unsigned __int128 uint128_t;
+
+static const uint32_t ALIGN(16) poly1305_x64_sse2_message_mask[4] = {
+ (1 << 26) - 1, 0, (1 << 26) - 1, 0};
+static const uint32_t ALIGN(16) poly1305_x64_sse2_5[4] = {5, 0, 5, 0};
+static const uint32_t ALIGN(16) poly1305_x64_sse2_1shl128[4] = {(1 << 24), 0,
+ (1 << 24), 0};
+
+static uint128_t INLINE add128(uint128_t a, uint128_t b) { return a + b; }
+
+static uint128_t INLINE add128_64(uint128_t a, uint64_t b) { return a + b; }
+
+static uint128_t INLINE mul64x64_128(uint64_t a, uint64_t b) {
+ return (uint128_t)a * b;
+}
+
+static uint64_t INLINE lo128(uint128_t a) { return (uint64_t)a; }
+
+static uint64_t INLINE shr128(uint128_t v, const int shift) {
+ return (uint64_t)(v >> shift);
+}
+
+static uint64_t INLINE shr128_pair(uint64_t hi, uint64_t lo, const int shift) {
+ return (uint64_t)((((uint128_t)hi << 64) | lo) >> shift);
+}
+
+typedef struct poly1305_power_t {
+ union {
+ xmmi v;
+ uint64_t u[2];
+ uint32_t d[4];
+ } R20, R21, R22, R23, R24, S21, S22, S23, S24;
+} poly1305_power;
+
+typedef struct poly1305_state_internal_t {
+ poly1305_power P[2]; /* 288 bytes, top 32 bit halves unused = 144
+ bytes of free storage */
+ union {
+ xmmi H[5]; /* 80 bytes */
+ uint64_t HH[10];
+ };
+ /* uint64_t r0,r1,r2; [24 bytes] */
+ /* uint64_t pad0,pad1; [16 bytes] */
+ uint64_t started; /* 8 bytes */
+ uint64_t leftover; /* 8 bytes */
+ uint8_t buffer[64]; /* 64 bytes */
+} poly1305_state_internal; /* 448 bytes total + 63 bytes for
+ alignment = 511 bytes raw */
+
+static poly1305_state_internal INLINE *poly1305_aligned_state(
+ poly1305_state *state) {
+ return (poly1305_state_internal *)(((uint64_t)state + 63) & ~63);
+}
+
+/* copy 0-63 bytes */
+static void INLINE
+poly1305_block_copy(uint8_t *dst, const uint8_t *src, size_t bytes) {
+ size_t offset = src - dst;
+ if (bytes & 32) {
+ _mm_storeu_si128((xmmi *)(dst + 0),
+ _mm_loadu_si128((xmmi *)(dst + offset + 0)));
+ _mm_storeu_si128((xmmi *)(dst + 16),
+ _mm_loadu_si128((xmmi *)(dst + offset + 16)));
+ dst += 32;
+ }
+ if (bytes & 16) {
+ _mm_storeu_si128((xmmi *)dst, _mm_loadu_si128((xmmi *)(dst + offset)));
+ dst += 16;
+ }
+ if (bytes & 8) {
+ *(uint64_t *)dst = *(uint64_t *)(dst + offset);
+ dst += 8;
+ }
+ if (bytes & 4) {
+ *(uint32_t *)dst = *(uint32_t *)(dst + offset);
+ dst += 4;
+ }
+ if (bytes & 2) {
+ *(uint16_t *)dst = *(uint16_t *)(dst + offset);
+ dst += 2;
+ }
+ if (bytes & 1) {
+ *(uint8_t *)dst = *(uint8_t *)(dst + offset);
+ }
+}
+
+/* zero 0-15 bytes */
+static void INLINE poly1305_block_zero(uint8_t *dst, size_t bytes) {
+ if (bytes & 8) {
+ *(uint64_t *)dst = 0;
+ dst += 8;
+ }
+ if (bytes & 4) {
+ *(uint32_t *)dst = 0;
+ dst += 4;
+ }
+ if (bytes & 2) {
+ *(uint16_t *)dst = 0;
+ dst += 2;
+ }
+ if (bytes & 1) {
+ *(uint8_t *)dst = 0;
+ }
+}
+
+static size_t INLINE poly1305_min(size_t a, size_t b) {
+ return (a < b) ? a : b;
+}
+
+void CRYPTO_poly1305_init(poly1305_state *state, const uint8_t key[32]) {
+ poly1305_state_internal *st = poly1305_aligned_state(state);
+ poly1305_power *p;
+ uint64_t r0, r1, r2;
+ uint64_t t0, t1;
+
+ /* clamp key */
+ t0 = U8TO64_LE(key + 0);
+ t1 = U8TO64_LE(key + 8);
+ r0 = t0 & 0xffc0fffffff;
+ t0 >>= 44;
+ t0 |= t1 << 20;
+ r1 = t0 & 0xfffffc0ffff;
+ t1 >>= 24;
+ r2 = t1 & 0x00ffffffc0f;
+
+ /* store r in un-used space of st->P[1] */
+ p = &st->P[1];
+ p->R20.d[1] = (uint32_t)(r0);
+ p->R20.d[3] = (uint32_t)(r0 >> 32);
+ p->R21.d[1] = (uint32_t)(r1);
+ p->R21.d[3] = (uint32_t)(r1 >> 32);
+ p->R22.d[1] = (uint32_t)(r2);
+ p->R22.d[3] = (uint32_t)(r2 >> 32);
+
+ /* store pad */
+ p->R23.d[1] = U8TO32_LE(key + 16);
+ p->R23.d[3] = U8TO32_LE(key + 20);
+ p->R24.d[1] = U8TO32_LE(key + 24);
+ p->R24.d[3] = U8TO32_LE(key + 28);
+
+ /* H = 0 */
+ st->H[0] = _mm_setzero_si128();
+ st->H[1] = _mm_setzero_si128();
+ st->H[2] = _mm_setzero_si128();
+ st->H[3] = _mm_setzero_si128();
+ st->H[4] = _mm_setzero_si128();
+
+ st->started = 0;
+ st->leftover = 0;
+}
+
+static void poly1305_first_block(poly1305_state_internal *st,
+ const uint8_t *m) {
+ const xmmi MMASK = _mm_load_si128((xmmi *)poly1305_x64_sse2_message_mask);
+ const xmmi FIVE = _mm_load_si128((xmmi *)poly1305_x64_sse2_5);
+ const xmmi HIBIT = _mm_load_si128((xmmi *)poly1305_x64_sse2_1shl128);
+ xmmi T5, T6;
+ poly1305_power *p;
+ uint128_t d[3];
+ uint64_t r0, r1, r2;
+ uint64_t r20, r21, r22, s22;
+ uint64_t pad0, pad1;
+ uint64_t c;
+ uint64_t i;
+
+ /* pull out stored info */
+ p = &st->P[1];
+
+ r0 = ((uint64_t)p->R20.d[3] << 32) | (uint64_t)p->R20.d[1];
+ r1 = ((uint64_t)p->R21.d[3] << 32) | (uint64_t)p->R21.d[1];
+ r2 = ((uint64_t)p->R22.d[3] << 32) | (uint64_t)p->R22.d[1];
+ pad0 = ((uint64_t)p->R23.d[3] << 32) | (uint64_t)p->R23.d[1];
+ pad1 = ((uint64_t)p->R24.d[3] << 32) | (uint64_t)p->R24.d[1];
+
+ /* compute powers r^2,r^4 */
+ r20 = r0;
+ r21 = r1;
+ r22 = r2;
+ for (i = 0; i < 2; i++) {
+ s22 = r22 * (5 << 2);
+
+ d[0] = add128(mul64x64_128(r20, r20), mul64x64_128(r21 * 2, s22));
+ d[1] = add128(mul64x64_128(r22, s22), mul64x64_128(r20 * 2, r21));
+ d[2] = add128(mul64x64_128(r21, r21), mul64x64_128(r22 * 2, r20));
+
+ r20 = lo128(d[0]) & 0xfffffffffff;
+ c = shr128(d[0], 44);
+ d[1] = add128_64(d[1], c);
+ r21 = lo128(d[1]) & 0xfffffffffff;
+ c = shr128(d[1], 44);
+ d[2] = add128_64(d[2], c);
+ r22 = lo128(d[2]) & 0x3ffffffffff;
+ c = shr128(d[2], 42);
+ r20 += c * 5;
+ c = (r20 >> 44);
+ r20 = r20 & 0xfffffffffff;
+ r21 += c;
+
+ p->R20.v = _mm_shuffle_epi32(_mm_cvtsi32_si128((uint32_t)(r20)&0x3ffffff),
+ _MM_SHUFFLE(1, 0, 1, 0));
+ p->R21.v = _mm_shuffle_epi32(
+ _mm_cvtsi32_si128((uint32_t)((r20 >> 26) | (r21 << 18)) & 0x3ffffff),
+ _MM_SHUFFLE(1, 0, 1, 0));
+ p->R22.v =
+ _mm_shuffle_epi32(_mm_cvtsi32_si128((uint32_t)((r21 >> 8)) & 0x3ffffff),
+ _MM_SHUFFLE(1, 0, 1, 0));
+ p->R23.v = _mm_shuffle_epi32(
+ _mm_cvtsi32_si128((uint32_t)((r21 >> 34) | (r22 << 10)) & 0x3ffffff),
+ _MM_SHUFFLE(1, 0, 1, 0));
+ p->R24.v = _mm_shuffle_epi32(_mm_cvtsi32_si128((uint32_t)((r22 >> 16))),
+ _MM_SHUFFLE(1, 0, 1, 0));
+ p->S21.v = _mm_mul_epu32(p->R21.v, FIVE);
+ p->S22.v = _mm_mul_epu32(p->R22.v, FIVE);
+ p->S23.v = _mm_mul_epu32(p->R23.v, FIVE);
+ p->S24.v = _mm_mul_epu32(p->R24.v, FIVE);
+ p--;
+ }
+
+ /* put saved info back */
+ p = &st->P[1];
+ p->R20.d[1] = (uint32_t)(r0);
+ p->R20.d[3] = (uint32_t)(r0 >> 32);
+ p->R21.d[1] = (uint32_t)(r1);
+ p->R21.d[3] = (uint32_t)(r1 >> 32);
+ p->R22.d[1] = (uint32_t)(r2);
+ p->R22.d[3] = (uint32_t)(r2 >> 32);
+ p->R23.d[1] = (uint32_t)(pad0);
+ p->R23.d[3] = (uint32_t)(pad0 >> 32);
+ p->R24.d[1] = (uint32_t)(pad1);
+ p->R24.d[3] = (uint32_t)(pad1 >> 32);
+
+ /* H = [Mx,My] */
+ T5 = _mm_unpacklo_epi64(_mm_loadl_epi64((xmmi *)(m + 0)),
+ _mm_loadl_epi64((xmmi *)(m + 16)));
+ T6 = _mm_unpacklo_epi64(_mm_loadl_epi64((xmmi *)(m + 8)),
+ _mm_loadl_epi64((xmmi *)(m + 24)));
+ st->H[0] = _mm_and_si128(MMASK, T5);
+ st->H[1] = _mm_and_si128(MMASK, _mm_srli_epi64(T5, 26));
+ T5 = _mm_or_si128(_mm_srli_epi64(T5, 52), _mm_slli_epi64(T6, 12));
+ st->H[2] = _mm_and_si128(MMASK, T5);
+ st->H[3] = _mm_and_si128(MMASK, _mm_srli_epi64(T5, 26));
+ st->H[4] = _mm_or_si128(_mm_srli_epi64(T6, 40), HIBIT);
+}
+
+static void poly1305_blocks(poly1305_state_internal *st, const uint8_t *m,
+ size_t bytes) {
+ const xmmi MMASK = _mm_load_si128((xmmi *)poly1305_x64_sse2_message_mask);
+ const xmmi FIVE = _mm_load_si128((xmmi *)poly1305_x64_sse2_5);
+ const xmmi HIBIT = _mm_load_si128((xmmi *)poly1305_x64_sse2_1shl128);
+
+ poly1305_power *p;
+ xmmi H0, H1, H2, H3, H4;
+ xmmi T0, T1, T2, T3, T4, T5, T6;
+ xmmi M0, M1, M2, M3, M4;
+ xmmi C1, C2;
+
+ H0 = st->H[0];
+ H1 = st->H[1];
+ H2 = st->H[2];
+ H3 = st->H[3];
+ H4 = st->H[4];
+
+ while (bytes >= 64) {
+ /* H *= [r^4,r^4] */
+ p = &st->P[0];
+ T0 = _mm_mul_epu32(H0, p->R20.v);
+ T1 = _mm_mul_epu32(H0, p->R21.v);
+ T2 = _mm_mul_epu32(H0, p->R22.v);
+ T3 = _mm_mul_epu32(H0, p->R23.v);
+ T4 = _mm_mul_epu32(H0, p->R24.v);
+ T5 = _mm_mul_epu32(H1, p->S24.v);
+ T6 = _mm_mul_epu32(H1, p->R20.v);
+ T0 = _mm_add_epi64(T0, T5);
+ T1 = _mm_add_epi64(T1, T6);
+ T5 = _mm_mul_epu32(H2, p->S23.v);
+ T6 = _mm_mul_epu32(H2, p->S24.v);
+ T0 = _mm_add_epi64(T0, T5);
+ T1 = _mm_add_epi64(T1, T6);
+ T5 = _mm_mul_epu32(H3, p->S22.v);
+ T6 = _mm_mul_epu32(H3, p->S23.v);
+ T0 = _mm_add_epi64(T0, T5);
+ T1 = _mm_add_epi64(T1, T6);
+ T5 = _mm_mul_epu32(H4, p->S21.v);
+ T6 = _mm_mul_epu32(H4, p->S22.v);
+ T0 = _mm_add_epi64(T0, T5);
+ T1 = _mm_add_epi64(T1, T6);
+ T5 = _mm_mul_epu32(H1, p->R21.v);
+ T6 = _mm_mul_epu32(H1, p->R22.v);
+ T2 = _mm_add_epi64(T2, T5);
+ T3 = _mm_add_epi64(T3, T6);
+ T5 = _mm_mul_epu32(H2, p->R20.v);
+ T6 = _mm_mul_epu32(H2, p->R21.v);
+ T2 = _mm_add_epi64(T2, T5);
+ T3 = _mm_add_epi64(T3, T6);
+ T5 = _mm_mul_epu32(H3, p->S24.v);
+ T6 = _mm_mul_epu32(H3, p->R20.v);
+ T2 = _mm_add_epi64(T2, T5);
+ T3 = _mm_add_epi64(T3, T6);
+ T5 = _mm_mul_epu32(H4, p->S23.v);
+ T6 = _mm_mul_epu32(H4, p->S24.v);
+ T2 = _mm_add_epi64(T2, T5);
+ T3 = _mm_add_epi64(T3, T6);
+ T5 = _mm_mul_epu32(H1, p->R23.v);
+ T4 = _mm_add_epi64(T4, T5);
+ T5 = _mm_mul_epu32(H2, p->R22.v);
+ T4 = _mm_add_epi64(T4, T5);
+ T5 = _mm_mul_epu32(H3, p->R21.v);
+ T4 = _mm_add_epi64(T4, T5);
+ T5 = _mm_mul_epu32(H4, p->R20.v);
+ T4 = _mm_add_epi64(T4, T5);
+
+ /* H += [Mx,My]*[r^2,r^2] */
+ T5 = _mm_unpacklo_epi64(_mm_loadl_epi64((xmmi *)(m + 0)),
+ _mm_loadl_epi64((xmmi *)(m + 16)));
+ T6 = _mm_unpacklo_epi64(_mm_loadl_epi64((xmmi *)(m + 8)),
+ _mm_loadl_epi64((xmmi *)(m + 24)));
+ M0 = _mm_and_si128(MMASK, T5);
+ M1 = _mm_and_si128(MMASK, _mm_srli_epi64(T5, 26));
+ T5 = _mm_or_si128(_mm_srli_epi64(T5, 52), _mm_slli_epi64(T6, 12));
+ M2 = _mm_and_si128(MMASK, T5);
+ M3 = _mm_and_si128(MMASK, _mm_srli_epi64(T5, 26));
+ M4 = _mm_or_si128(_mm_srli_epi64(T6, 40), HIBIT);
+
+ p = &st->P[1];
+ T5 = _mm_mul_epu32(M0, p->R20.v);
+ T6 = _mm_mul_epu32(M0, p->R21.v);
+ T0 = _mm_add_epi64(T0, T5);
+ T1 = _mm_add_epi64(T1, T6);
+ T5 = _mm_mul_epu32(M1, p->S24.v);
+ T6 = _mm_mul_epu32(M1, p->R20.v);
+ T0 = _mm_add_epi64(T0, T5);
+ T1 = _mm_add_epi64(T1, T6);
+ T5 = _mm_mul_epu32(M2, p->S23.v);
+ T6 = _mm_mul_epu32(M2, p->S24.v);
+ T0 = _mm_add_epi64(T0, T5);
+ T1 = _mm_add_epi64(T1, T6);
+ T5 = _mm_mul_epu32(M3, p->S22.v);
+ T6 = _mm_mul_epu32(M3, p->S23.v);
+ T0 = _mm_add_epi64(T0, T5);
+ T1 = _mm_add_epi64(T1, T6);
+ T5 = _mm_mul_epu32(M4, p->S21.v);
+ T6 = _mm_mul_epu32(M4, p->S22.v);
+ T0 = _mm_add_epi64(T0, T5);
+ T1 = _mm_add_epi64(T1, T6);
+ T5 = _mm_mul_epu32(M0, p->R22.v);
+ T6 = _mm_mul_epu32(M0, p->R23.v);
+ T2 = _mm_add_epi64(T2, T5);
+ T3 = _mm_add_epi64(T3, T6);
+ T5 = _mm_mul_epu32(M1, p->R21.v);
+ T6 = _mm_mul_epu32(M1, p->R22.v);
+ T2 = _mm_add_epi64(T2, T5);
+ T3 = _mm_add_epi64(T3, T6);
+ T5 = _mm_mul_epu32(M2, p->R20.v);
+ T6 = _mm_mul_epu32(M2, p->R21.v);
+ T2 = _mm_add_epi64(T2, T5);
+ T3 = _mm_add_epi64(T3, T6);
+ T5 = _mm_mul_epu32(M3, p->S24.v);
+ T6 = _mm_mul_epu32(M3, p->R20.v);
+ T2 = _mm_add_epi64(T2, T5);
+ T3 = _mm_add_epi64(T3, T6);
+ T5 = _mm_mul_epu32(M4, p->S23.v);
+ T6 = _mm_mul_epu32(M4, p->S24.v);
+ T2 = _mm_add_epi64(T2, T5);
+ T3 = _mm_add_epi64(T3, T6);
+ T5 = _mm_mul_epu32(M0, p->R24.v);
+ T4 = _mm_add_epi64(T4, T5);
+ T5 = _mm_mul_epu32(M1, p->R23.v);
+ T4 = _mm_add_epi64(T4, T5);
+ T5 = _mm_mul_epu32(M2, p->R22.v);
+ T4 = _mm_add_epi64(T4, T5);
+ T5 = _mm_mul_epu32(M3, p->R21.v);
+ T4 = _mm_add_epi64(T4, T5);
+ T5 = _mm_mul_epu32(M4, p->R20.v);
+ T4 = _mm_add_epi64(T4, T5);
+
+ /* H += [Mx,My] */
+ T5 = _mm_unpacklo_epi64(_mm_loadl_epi64((xmmi *)(m + 32)),
+ _mm_loadl_epi64((xmmi *)(m + 48)));
+ T6 = _mm_unpacklo_epi64(_mm_loadl_epi64((xmmi *)(m + 40)),
+ _mm_loadl_epi64((xmmi *)(m + 56)));
+ M0 = _mm_and_si128(MMASK, T5);
+ M1 = _mm_and_si128(MMASK, _mm_srli_epi64(T5, 26));
+ T5 = _mm_or_si128(_mm_srli_epi64(T5, 52), _mm_slli_epi64(T6, 12));
+ M2 = _mm_and_si128(MMASK, T5);
+ M3 = _mm_and_si128(MMASK, _mm_srli_epi64(T5, 26));
+ M4 = _mm_or_si128(_mm_srli_epi64(T6, 40), HIBIT);
+
+ T0 = _mm_add_epi64(T0, M0);
+ T1 = _mm_add_epi64(T1, M1);
+ T2 = _mm_add_epi64(T2, M2);
+ T3 = _mm_add_epi64(T3, M3);
+ T4 = _mm_add_epi64(T4, M4);
+
+ /* reduce */
+ C1 = _mm_srli_epi64(T0, 26);
+ C2 = _mm_srli_epi64(T3, 26);
+ T0 = _mm_and_si128(T0, MMASK);
+ T3 = _mm_and_si128(T3, MMASK);
+ T1 = _mm_add_epi64(T1, C1);
+ T4 = _mm_add_epi64(T4, C2);
+ C1 = _mm_srli_epi64(T1, 26);
+ C2 = _mm_srli_epi64(T4, 26);
+ T1 = _mm_and_si128(T1, MMASK);
+ T4 = _mm_and_si128(T4, MMASK);
+ T2 = _mm_add_epi64(T2, C1);
+ T0 = _mm_add_epi64(T0, _mm_mul_epu32(C2, FIVE));
+ C1 = _mm_srli_epi64(T2, 26);
+ C2 = _mm_srli_epi64(T0, 26);
+ T2 = _mm_and_si128(T2, MMASK);
+ T0 = _mm_and_si128(T0, MMASK);
+ T3 = _mm_add_epi64(T3, C1);
+ T1 = _mm_add_epi64(T1, C2);
+ C1 = _mm_srli_epi64(T3, 26);
+ T3 = _mm_and_si128(T3, MMASK);
+ T4 = _mm_add_epi64(T4, C1);
+
+ /* H = (H*[r^4,r^4] + [Mx,My]*[r^2,r^2] + [Mx,My]) */
+ H0 = T0;
+ H1 = T1;
+ H2 = T2;
+ H3 = T3;
+ H4 = T4;
+
+ m += 64;
+ bytes -= 64;
+ }
+
+ st->H[0] = H0;
+ st->H[1] = H1;
+ st->H[2] = H2;
+ st->H[3] = H3;
+ st->H[4] = H4;
+}
+
+static size_t poly1305_combine(poly1305_state_internal *st, const uint8_t *m,
+ size_t bytes) {
+ const xmmi MMASK = _mm_load_si128((xmmi *)poly1305_x64_sse2_message_mask);
+ const xmmi HIBIT = _mm_load_si128((xmmi *)poly1305_x64_sse2_1shl128);
+ const xmmi FIVE = _mm_load_si128((xmmi *)poly1305_x64_sse2_5);
+
+ poly1305_power *p;
+ xmmi H0, H1, H2, H3, H4;
+ xmmi M0, M1, M2, M3, M4;
+ xmmi T0, T1, T2, T3, T4, T5, T6;
+ xmmi C1, C2;
+
+ uint64_t r0, r1, r2;
+ uint64_t t0, t1, t2, t3, t4;
+ uint64_t c;
+ size_t consumed = 0;
+
+ H0 = st->H[0];
+ H1 = st->H[1];
+ H2 = st->H[2];
+ H3 = st->H[3];
+ H4 = st->H[4];
+
+ /* p = [r^2,r^2] */
+ p = &st->P[1];
+
+ if (bytes >= 32) {
+ /* H *= [r^2,r^2] */
+ T0 = _mm_mul_epu32(H0, p->R20.v);
+ T1 = _mm_mul_epu32(H0, p->R21.v);
+ T2 = _mm_mul_epu32(H0, p->R22.v);
+ T3 = _mm_mul_epu32(H0, p->R23.v);
+ T4 = _mm_mul_epu32(H0, p->R24.v);
+ T5 = _mm_mul_epu32(H1, p->S24.v);
+ T6 = _mm_mul_epu32(H1, p->R20.v);
+ T0 = _mm_add_epi64(T0, T5);
+ T1 = _mm_add_epi64(T1, T6);
+ T5 = _mm_mul_epu32(H2, p->S23.v);
+ T6 = _mm_mul_epu32(H2, p->S24.v);
+ T0 = _mm_add_epi64(T0, T5);
+ T1 = _mm_add_epi64(T1, T6);
+ T5 = _mm_mul_epu32(H3, p->S22.v);
+ T6 = _mm_mul_epu32(H3, p->S23.v);
+ T0 = _mm_add_epi64(T0, T5);
+ T1 = _mm_add_epi64(T1, T6);
+ T5 = _mm_mul_epu32(H4, p->S21.v);
+ T6 = _mm_mul_epu32(H4, p->S22.v);
+ T0 = _mm_add_epi64(T0, T5);
+ T1 = _mm_add_epi64(T1, T6);
+ T5 = _mm_mul_epu32(H1, p->R21.v);
+ T6 = _mm_mul_epu32(H1, p->R22.v);
+ T2 = _mm_add_epi64(T2, T5);
+ T3 = _mm_add_epi64(T3, T6);
+ T5 = _mm_mul_epu32(H2, p->R20.v);
+ T6 = _mm_mul_epu32(H2, p->R21.v);
+ T2 = _mm_add_epi64(T2, T5);
+ T3 = _mm_add_epi64(T3, T6);
+ T5 = _mm_mul_epu32(H3, p->S24.v);
+ T6 = _mm_mul_epu32(H3, p->R20.v);
+ T2 = _mm_add_epi64(T2, T5);
+ T3 = _mm_add_epi64(T3, T6);
+ T5 = _mm_mul_epu32(H4, p->S23.v);
+ T6 = _mm_mul_epu32(H4, p->S24.v);
+ T2 = _mm_add_epi64(T2, T5);
+ T3 = _mm_add_epi64(T3, T6);
+ T5 = _mm_mul_epu32(H1, p->R23.v);
+ T4 = _mm_add_epi64(T4, T5);
+ T5 = _mm_mul_epu32(H2, p->R22.v);
+ T4 = _mm_add_epi64(T4, T5);
+ T5 = _mm_mul_epu32(H3, p->R21.v);
+ T4 = _mm_add_epi64(T4, T5);
+ T5 = _mm_mul_epu32(H4, p->R20.v);
+ T4 = _mm_add_epi64(T4, T5);
+
+ /* H += [Mx,My] */
+ T5 = _mm_unpacklo_epi64(_mm_loadl_epi64((xmmi *)(m + 0)),
+ _mm_loadl_epi64((xmmi *)(m + 16)));
+ T6 = _mm_unpacklo_epi64(_mm_loadl_epi64((xmmi *)(m + 8)),
+ _mm_loadl_epi64((xmmi *)(m + 24)));
+ M0 = _mm_and_si128(MMASK, T5);
+ M1 = _mm_and_si128(MMASK, _mm_srli_epi64(T5, 26));
+ T5 = _mm_or_si128(_mm_srli_epi64(T5, 52), _mm_slli_epi64(T6, 12));
+ M2 = _mm_and_si128(MMASK, T5);
+ M3 = _mm_and_si128(MMASK, _mm_srli_epi64(T5, 26));
+ M4 = _mm_or_si128(_mm_srli_epi64(T6, 40), HIBIT);
+
+ T0 = _mm_add_epi64(T0, M0);
+ T1 = _mm_add_epi64(T1, M1);
+ T2 = _mm_add_epi64(T2, M2);
+ T3 = _mm_add_epi64(T3, M3);
+ T4 = _mm_add_epi64(T4, M4);
+
+ /* reduce */
+ C1 = _mm_srli_epi64(T0, 26);
+ C2 = _mm_srli_epi64(T3, 26);
+ T0 = _mm_and_si128(T0, MMASK);
+ T3 = _mm_and_si128(T3, MMASK);
+ T1 = _mm_add_epi64(T1, C1);
+ T4 = _mm_add_epi64(T4, C2);
+ C1 = _mm_srli_epi64(T1, 26);
+ C2 = _mm_srli_epi64(T4, 26);
+ T1 = _mm_and_si128(T1, MMASK);
+ T4 = _mm_and_si128(T4, MMASK);
+ T2 = _mm_add_epi64(T2, C1);
+ T0 = _mm_add_epi64(T0, _mm_mul_epu32(C2, FIVE));
+ C1 = _mm_srli_epi64(T2, 26);
+ C2 = _mm_srli_epi64(T0, 26);
+ T2 = _mm_and_si128(T2, MMASK);
+ T0 = _mm_and_si128(T0, MMASK);
+ T3 = _mm_add_epi64(T3, C1);
+ T1 = _mm_add_epi64(T1, C2);
+ C1 = _mm_srli_epi64(T3, 26);
+ T3 = _mm_and_si128(T3, MMASK);
+ T4 = _mm_add_epi64(T4, C1);
+
+ /* H = (H*[r^2,r^2] + [Mx,My]) */
+ H0 = T0;
+ H1 = T1;
+ H2 = T2;
+ H3 = T3;
+ H4 = T4;
+
+ consumed = 32;
+ }
+
+ /* finalize, H *= [r^2,r] */
+ r0 = ((uint64_t)p->R20.d[3] << 32) | (uint64_t)p->R20.d[1];
+ r1 = ((uint64_t)p->R21.d[3] << 32) | (uint64_t)p->R21.d[1];
+ r2 = ((uint64_t)p->R22.d[3] << 32) | (uint64_t)p->R22.d[1];
+
+ p->R20.d[2] = (uint32_t)(r0)&0x3ffffff;
+ p->R21.d[2] = (uint32_t)((r0 >> 26) | (r1 << 18)) & 0x3ffffff;
+ p->R22.d[2] = (uint32_t)((r1 >> 8)) & 0x3ffffff;
+ p->R23.d[2] = (uint32_t)((r1 >> 34) | (r2 << 10)) & 0x3ffffff;
+ p->R24.d[2] = (uint32_t)((r2 >> 16));
+ p->S21.d[2] = p->R21.d[2] * 5;
+ p->S22.d[2] = p->R22.d[2] * 5;
+ p->S23.d[2] = p->R23.d[2] * 5;
+ p->S24.d[2] = p->R24.d[2] * 5;
+
+ /* H *= [r^2,r] */
+ T0 = _mm_mul_epu32(H0, p->R20.v);
+ T1 = _mm_mul_epu32(H0, p->R21.v);
+ T2 = _mm_mul_epu32(H0, p->R22.v);
+ T3 = _mm_mul_epu32(H0, p->R23.v);
+ T4 = _mm_mul_epu32(H0, p->R24.v);
+ T5 = _mm_mul_epu32(H1, p->S24.v);
+ T6 = _mm_mul_epu32(H1, p->R20.v);
+ T0 = _mm_add_epi64(T0, T5);
+ T1 = _mm_add_epi64(T1, T6);
+ T5 = _mm_mul_epu32(H2, p->S23.v);
+ T6 = _mm_mul_epu32(H2, p->S24.v);
+ T0 = _mm_add_epi64(T0, T5);
+ T1 = _mm_add_epi64(T1, T6);
+ T5 = _mm_mul_epu32(H3, p->S22.v);
+ T6 = _mm_mul_epu32(H3, p->S23.v);
+ T0 = _mm_add_epi64(T0, T5);
+ T1 = _mm_add_epi64(T1, T6);
+ T5 = _mm_mul_epu32(H4, p->S21.v);
+ T6 = _mm_mul_epu32(H4, p->S22.v);
+ T0 = _mm_add_epi64(T0, T5);
+ T1 = _mm_add_epi64(T1, T6);
+ T5 = _mm_mul_epu32(H1, p->R21.v);
+ T6 = _mm_mul_epu32(H1, p->R22.v);
+ T2 = _mm_add_epi64(T2, T5);
+ T3 = _mm_add_epi64(T3, T6);
+ T5 = _mm_mul_epu32(H2, p->R20.v);
+ T6 = _mm_mul_epu32(H2, p->R21.v);
+ T2 = _mm_add_epi64(T2, T5);
+ T3 = _mm_add_epi64(T3, T6);
+ T5 = _mm_mul_epu32(H3, p->S24.v);
+ T6 = _mm_mul_epu32(H3, p->R20.v);
+ T2 = _mm_add_epi64(T2, T5);
+ T3 = _mm_add_epi64(T3, T6);
+ T5 = _mm_mul_epu32(H4, p->S23.v);
+ T6 = _mm_mul_epu32(H4, p->S24.v);
+ T2 = _mm_add_epi64(T2, T5);
+ T3 = _mm_add_epi64(T3, T6);
+ T5 = _mm_mul_epu32(H1, p->R23.v);
+ T4 = _mm_add_epi64(T4, T5);
+ T5 = _mm_mul_epu32(H2, p->R22.v);
+ T4 = _mm_add_epi64(T4, T5);
+ T5 = _mm_mul_epu32(H3, p->R21.v);
+ T4 = _mm_add_epi64(T4, T5);
+ T5 = _mm_mul_epu32(H4, p->R20.v);
+ T4 = _mm_add_epi64(T4, T5);
+
+ C1 = _mm_srli_epi64(T0, 26);
+ C2 = _mm_srli_epi64(T3, 26);
+ T0 = _mm_and_si128(T0, MMASK);
+ T3 = _mm_and_si128(T3, MMASK);
+ T1 = _mm_add_epi64(T1, C1);
+ T4 = _mm_add_epi64(T4, C2);
+ C1 = _mm_srli_epi64(T1, 26);
+ C2 = _mm_srli_epi64(T4, 26);
+ T1 = _mm_and_si128(T1, MMASK);
+ T4 = _mm_and_si128(T4, MMASK);
+ T2 = _mm_add_epi64(T2, C1);
+ T0 = _mm_add_epi64(T0, _mm_mul_epu32(C2, FIVE));
+ C1 = _mm_srli_epi64(T2, 26);
+ C2 = _mm_srli_epi64(T0, 26);
+ T2 = _mm_and_si128(T2, MMASK);
+ T0 = _mm_and_si128(T0, MMASK);
+ T3 = _mm_add_epi64(T3, C1);
+ T1 = _mm_add_epi64(T1, C2);
+ C1 = _mm_srli_epi64(T3, 26);
+ T3 = _mm_and_si128(T3, MMASK);
+ T4 = _mm_add_epi64(T4, C1);
+
+ /* H = H[0]+H[1] */
+ H0 = _mm_add_epi64(T0, _mm_srli_si128(T0, 8));
+ H1 = _mm_add_epi64(T1, _mm_srli_si128(T1, 8));
+ H2 = _mm_add_epi64(T2, _mm_srli_si128(T2, 8));
+ H3 = _mm_add_epi64(T3, _mm_srli_si128(T3, 8));
+ H4 = _mm_add_epi64(T4, _mm_srli_si128(T4, 8));
+
+ t0 = _mm_cvtsi128_si32(H0);
+ c = (t0 >> 26);
+ t0 &= 0x3ffffff;
+ t1 = _mm_cvtsi128_si32(H1) + c;
+ c = (t1 >> 26);
+ t1 &= 0x3ffffff;
+ t2 = _mm_cvtsi128_si32(H2) + c;
+ c = (t2 >> 26);
+ t2 &= 0x3ffffff;
+ t3 = _mm_cvtsi128_si32(H3) + c;
+ c = (t3 >> 26);
+ t3 &= 0x3ffffff;
+ t4 = _mm_cvtsi128_si32(H4) + c;
+ c = (t4 >> 26);
+ t4 &= 0x3ffffff;
+ t0 = t0 + (c * 5);
+ c = (t0 >> 26);
+ t0 &= 0x3ffffff;
+ t1 = t1 + c;
+
+ st->HH[0] = ((t0) | (t1 << 26)) & 0xfffffffffffull;
+ st->HH[1] = ((t1 >> 18) | (t2 << 8) | (t3 << 34)) & 0xfffffffffffull;
+ st->HH[2] = ((t3 >> 10) | (t4 << 16)) & 0x3ffffffffffull;
+
+ return consumed;
+}
+
+void CRYPTO_poly1305_update(poly1305_state *state, const uint8_t *m,
+ size_t bytes) {
+ poly1305_state_internal *st = poly1305_aligned_state(state);
+ size_t want;
+
+ /* need at least 32 initial bytes to start the accelerated branch */
+ if (!st->started) {
+ if ((st->leftover == 0) && (bytes > 32)) {
+ poly1305_first_block(st, m);
+ m += 32;
+ bytes -= 32;
+ } else {
+ want = poly1305_min(32 - st->leftover, bytes);
+ poly1305_block_copy(st->buffer + st->leftover, m, want);
+ bytes -= want;
+ m += want;
+ st->leftover += want;
+ if ((st->leftover < 32) || (bytes == 0))
+ return;
+ poly1305_first_block(st, st->buffer);
+ st->leftover = 0;
+ }
+ st->started = 1;
+ }
+
+ /* handle leftover */
+ if (st->leftover) {
+ want = poly1305_min(64 - st->leftover, bytes);
+ poly1305_block_copy(st->buffer + st->leftover, m, want);
+ bytes -= want;
+ m += want;
+ st->leftover += want;
+ if (st->leftover < 64)
+ return;
+ poly1305_blocks(st, st->buffer, 64);
+ st->leftover = 0;
+ }
+
+ /* process 64 byte blocks */
+ if (bytes >= 64) {
+ want = (bytes & ~63);
+ poly1305_blocks(st, m, want);
+ m += want;
+ bytes -= want;
+ }
+
+ if (bytes) {
+ poly1305_block_copy(st->buffer + st->leftover, m, bytes);
+ st->leftover += bytes;
+ }
+}
+
+void CRYPTO_poly1305_finish(poly1305_state *state, uint8_t mac[16]) {
+ poly1305_state_internal *st = poly1305_aligned_state(state);
+ size_t leftover = st->leftover;
+ uint8_t *m = st->buffer;
+ uint128_t d[3];
+ uint64_t h0, h1, h2;
+ uint64_t t0, t1;
+ uint64_t g0, g1, g2, c, nc;
+ uint64_t r0, r1, r2, s1, s2;
+ poly1305_power *p;
+
+ if (st->started) {
+ size_t consumed = poly1305_combine(st, m, leftover);
+ leftover -= consumed;
+ m += consumed;
+ }
+
+ /* st->HH will either be 0 or have the combined result */
+ h0 = st->HH[0];
+ h1 = st->HH[1];
+ h2 = st->HH[2];
+
+ p = &st->P[1];
+ r0 = ((uint64_t)p->R20.d[3] << 32) | (uint64_t)p->R20.d[1];
+ r1 = ((uint64_t)p->R21.d[3] << 32) | (uint64_t)p->R21.d[1];
+ r2 = ((uint64_t)p->R22.d[3] << 32) | (uint64_t)p->R22.d[1];
+ s1 = r1 * (5 << 2);
+ s2 = r2 * (5 << 2);
+
+ if (leftover < 16)
+ goto poly1305_donna_atmost15bytes;
+
+poly1305_donna_atleast16bytes:
+ t0 = U8TO64_LE(m + 0);
+ t1 = U8TO64_LE(m + 8);
+ h0 += t0 & 0xfffffffffff;
+ t0 = shr128_pair(t1, t0, 44);
+ h1 += t0 & 0xfffffffffff;
+ h2 += (t1 >> 24) | ((uint64_t)1 << 40);
+
+poly1305_donna_mul:
+ d[0] = add128(add128(mul64x64_128(h0, r0), mul64x64_128(h1, s2)),
+ mul64x64_128(h2, s1));
+ d[1] = add128(add128(mul64x64_128(h0, r1), mul64x64_128(h1, r0)),
+ mul64x64_128(h2, s2));
+ d[2] = add128(add128(mul64x64_128(h0, r2), mul64x64_128(h1, r1)),
+ mul64x64_128(h2, r0));
+ h0 = lo128(d[0]) & 0xfffffffffff;
+ c = shr128(d[0], 44);
+ d[1] = add128_64(d[1], c);
+ h1 = lo128(d[1]) & 0xfffffffffff;
+ c = shr128(d[1], 44);
+ d[2] = add128_64(d[2], c);
+ h2 = lo128(d[2]) & 0x3ffffffffff;
+ c = shr128(d[2], 42);
+ h0 += c * 5;
+
+ m += 16;
+ leftover -= 16;
+ if (leftover >= 16)
+ goto poly1305_donna_atleast16bytes;
+
+/* final bytes */
+poly1305_donna_atmost15bytes:
+ if (!leftover)
+ goto poly1305_donna_finish;
+
+ m[leftover++] = 1;
+ poly1305_block_zero(m + leftover, 16 - leftover);
+ leftover = 16;
+
+ t0 = U8TO64_LE(m + 0);
+ t1 = U8TO64_LE(m + 8);
+ h0 += t0 & 0xfffffffffff;
+ t0 = shr128_pair(t1, t0, 44);
+ h1 += t0 & 0xfffffffffff;
+ h2 += (t1 >> 24);
+
+ goto poly1305_donna_mul;
+
+poly1305_donna_finish:
+ c = (h0 >> 44);
+ h0 &= 0xfffffffffff;
+ h1 += c;
+ c = (h1 >> 44);
+ h1 &= 0xfffffffffff;
+ h2 += c;
+ c = (h2 >> 42);
+ h2 &= 0x3ffffffffff;
+ h0 += c * 5;
+
+ g0 = h0 + 5;
+ c = (g0 >> 44);
+ g0 &= 0xfffffffffff;
+ g1 = h1 + c;
+ c = (g1 >> 44);
+ g1 &= 0xfffffffffff;
+ g2 = h2 + c - ((uint64_t)1 << 42);
+
+ c = (g2 >> 63) - 1;
+ nc = ~c;
+ h0 = (h0 & nc) | (g0 & c);
+ h1 = (h1 & nc) | (g1 & c);
+ h2 = (h2 & nc) | (g2 & c);
+
+ /* pad */
+ t0 = ((uint64_t)p->R23.d[3] << 32) | (uint64_t)p->R23.d[1];
+ t1 = ((uint64_t)p->R24.d[3] << 32) | (uint64_t)p->R24.d[1];
+ h0 += (t0 & 0xfffffffffff);
+ c = (h0 >> 44);
+ h0 &= 0xfffffffffff;
+ t0 = shr128_pair(t1, t0, 44);
+ h1 += (t0 & 0xfffffffffff) + c;
+ c = (h1 >> 44);
+ h1 &= 0xfffffffffff;
+ t1 = (t1 >> 24);
+ h2 += (t1)+c;
+
+ U64TO8_LE(mac + 0, ((h0) | (h1 << 44)));
+ U64TO8_LE(mac + 8, ((h1 >> 20) | (h2 << 24)));
+}
+
+#endif /* !OPENSSL_WINDOWS && OPENSSL_X86_64 */
diff --git a/src/crypto/rand/CMakeLists.txt b/src/crypto/rand/CMakeLists.txt
new file mode 100644
index 0000000..23c1b24
--- /dev/null
+++ b/src/crypto/rand/CMakeLists.txt
@@ -0,0 +1,11 @@
+include_directories(. .. ../../include)
+
+add_library(
+ rand
+
+ OBJECT
+
+ rand.c
+ urandom.c
+ windows.c
+)
diff --git a/src/crypto/rand/rand.c b/src/crypto/rand/rand.c
new file mode 100644
index 0000000..6780b6c
--- /dev/null
+++ b/src/crypto/rand/rand.c
@@ -0,0 +1,28 @@
+/* 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 <openssl/rand.h>
+
+
+int RAND_pseudo_bytes(uint8_t *buf, size_t len) {
+ return RAND_bytes(buf, len);
+}
+
+void RAND_seed(const void *buf, int num) {}
+
+void RAND_add(const void *buf, int num, double entropy) {}
+
+int RAND_poll(void) {
+ return 1;
+}
diff --git a/src/crypto/rand/urandom.c b/src/crypto/rand/urandom.c
new file mode 100644
index 0000000..2ad4af0
--- /dev/null
+++ b/src/crypto/rand/urandom.c
@@ -0,0 +1,241 @@
+/* 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 <openssl/rand.h>
+
+#if !defined(OPENSSL_WINDOWS)
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <openssl/thread.h>
+#include <openssl/mem.h>
+
+
+/* This file implements a PRNG by reading from /dev/urandom, optionally with a
+ * fork-safe buffer.
+ *
+ * If buffering is enabled then it maintains a global, linked list of buffers.
+ * Threads which need random bytes grab a buffer from the list under a lock and
+ * copy out the bytes that they need. In the rare case that the buffer is
+ * empty, it's refilled from /dev/urandom outside of the lock.
+ *
+ * Large requests are always serviced from /dev/urandom directly.
+ *
+ * Each buffer contains the PID of the process that created it and it's tested
+ * against the current PID each time. Thus processes that fork will discard all
+ * the buffers filled by the parent process. There are two problems with this:
+ *
+ * 1) glibc maintains a cache of the current PID+PPID and, if this cache isn't
+ * correctly invalidated, the getpid() will continue to believe that
+ * it's the old process. Glibc depends on the glibc wrappers for fork,
+ * vfork and clone being used in order to invalidate the getpid() cache.
+ *
+ * 2) If a process forks, dies and then its child forks, it's possible that
+ * the third process will end up with the same PID as the original process.
+ * If the second process never used any random values then this will mean
+ * that the third process has stale, cached values and won't notice.
+ */
+
+/* BUF_SIZE is intended to be a 4K allocation with malloc overhead. struct
+ * rand_buffer also fits in this space and the remainder is entropy. */
+#define BUF_SIZE (4096 - 16)
+
+/* rand_buffer contains unused, random bytes. These structures form a linked
+ * list via the |next| pointer, which is NULL in the final element. */
+struct rand_buffer {
+ size_t used; /* used contains the number of bytes of |rand| that have
+ been consumed. */
+ struct rand_buffer *next;
+ pid_t pid; /* pid contains the pid at the time that the buffer was
+ created so that data is not duplicated after a fork. */
+ pid_t ppid; /* ppid contains the parent pid in order to try and reduce
+ the possibility of duplicated PID confusing the
+ detection of a fork. */
+ uint8_t rand[];
+};
+
+/* rand_bytes_per_buf is the number of actual entropy bytes in a buffer. */
+static const size_t rand_bytes_per_buf = BUF_SIZE - sizeof(struct rand_buffer);
+
+/* list_head is the start of a global, linked-list of rand_buffer objects. It's
+ * protected by CRYPTO_LOCK_RAND. */
+static struct rand_buffer *list_head;
+
+/* urandom_fd is a file descriptor to /dev/urandom. It's protected by
+ * CRYPTO_LOCK_RAND. */
+static int urandom_fd = -2;
+
+/* urandom_buffering controls whether buffering is enabled (1) or not (0). This
+ * is protected by CRYPTO_LOCK_RAND. */
+static int urandom_buffering = 0;
+
+/* urandom_get_fd_locked returns a file descriptor to /dev/urandom. The caller
+ * of this function must hold CRYPTO_LOCK_RAND. */
+static int urandom_get_fd_locked(void) {
+ if (urandom_fd != -2)
+ return urandom_fd;
+
+ urandom_fd = open("/dev/urandom", O_RDONLY);
+ return urandom_fd;
+}
+
+/* RAND_cleanup frees all buffers, closes any cached file descriptor
+ * and resets the global state. */
+void RAND_cleanup(void) {
+ struct rand_buffer *cur;
+
+ CRYPTO_w_lock(CRYPTO_LOCK_RAND);
+ while ((cur = list_head)) {
+ list_head = cur->next;
+ OPENSSL_free(cur);
+ }
+ if (urandom_fd >= 0) {
+ close(urandom_fd);
+ }
+ urandom_fd = -2;
+ list_head = NULL;
+ CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
+}
+
+/* read_full reads exactly |len| bytes from |fd| into |out| and returns 1. In
+ * the case of an error it returns 0. */
+static char read_full(int fd, uint8_t *out, size_t len) {
+ ssize_t r;
+
+ while (len > 0) {
+ do {
+ r = read(fd, out, len);
+ } while (r == -1 && errno == EINTR);
+
+ if (r <= 0) {
+ return 0;
+ }
+ out += r;
+ len -= r;
+ }
+
+ return 1;
+}
+
+/* urandom_rand_pseudo_bytes puts |num| random bytes into |out|. It returns
+ * one on success and zero otherwise. */
+int RAND_bytes(uint8_t *out, size_t requested) {
+ int fd;
+ struct rand_buffer *buf;
+ size_t todo;
+ pid_t pid, ppid;
+
+ if (requested == 0) {
+ return 1;
+ }
+
+ CRYPTO_w_lock(CRYPTO_LOCK_RAND);
+ fd = urandom_get_fd_locked();
+
+ if (fd < 0) {
+ CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
+ abort();
+ return 0;
+ }
+
+ /* If buffering is not enabled, or if the request is large, then the
+ * result comes directly from urandom. */
+ if (!urandom_buffering || requested > BUF_SIZE / 2) {
+ CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
+ if (!read_full(fd, out, requested)) {
+ abort();
+ return 0;
+ }
+ return 1;
+ }
+
+ pid = getpid();
+ ppid = getppid();
+
+ for (;;) {
+ buf = list_head;
+ if (buf && buf->pid == pid && buf->ppid == ppid &&
+ rand_bytes_per_buf - buf->used >= requested) {
+ memcpy(out, &buf->rand[buf->used], requested);
+ buf->used += requested;
+ CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
+ return 1;
+ }
+
+ /* If we don't immediately have enough entropy with the correct
+ * PID, remove the buffer from the list in order to gain
+ * exclusive access and unlock. */
+ if (buf) {
+ list_head = buf->next;
+ }
+ CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
+
+ if (!buf) {
+ buf = (struct rand_buffer *)OPENSSL_malloc(BUF_SIZE);
+ /* The buffer doesn't contain any random bytes yet
+ * so we mark it as fully used so that it will be
+ * filled below. */
+ buf->used = rand_bytes_per_buf;
+ buf->next = NULL;
+ buf->pid = pid;
+ buf->ppid = ppid;
+ }
+
+ if (buf->pid == pid && buf->ppid == ppid) {
+ break;
+ }
+
+ /* We have forked and so cannot use these bytes as they
+ * may have been used in another process. */
+ OPENSSL_free(buf);
+ CRYPTO_w_lock(CRYPTO_LOCK_RAND);
+ }
+
+ while (requested > 0) {
+ todo = rand_bytes_per_buf - buf->used;
+ if (todo > requested) {
+ todo = requested;
+ }
+ memcpy(out, &buf->rand[buf->used], todo);
+ requested -= todo;
+ out += todo;
+ buf->used += todo;
+
+ if (buf->used < rand_bytes_per_buf) {
+ break;
+ }
+
+ if (!read_full(fd, buf->rand, rand_bytes_per_buf)) {
+ OPENSSL_free(buf);
+ abort();
+ return 0;
+ }
+
+ buf->used = 0;
+ }
+
+ CRYPTO_w_lock(CRYPTO_LOCK_RAND);
+ assert(list_head != buf);
+ buf->next = list_head;
+ list_head = buf;
+ CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
+ return 1;
+}
+
+#endif /* !OPENSSL_WINDOWS */
diff --git a/src/crypto/rand/windows.c b/src/crypto/rand/windows.c
new file mode 100644
index 0000000..6f3f3a7
--- /dev/null
+++ b/src/crypto/rand/windows.c
@@ -0,0 +1,54 @@
+/* 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 <openssl/rand.h>
+
+#if defined(OPENSSL_WINDOWS)
+
+#include <limits.h>
+#include <stdlib.h>
+
+#pragma warning(push, 3)
+
+#include <Windows.h>
+
+/* #define needed to link in RtlGenRandom(), a.k.a. SystemFunction036. See the
+ * "Community Additions" comment on MSDN here:
+ * http://msdn.microsoft.com/en-us/library/windows/desktop/aa387694.aspx */
+#define SystemFunction036 NTAPI SystemFunction036
+#include <NTSecAPI.h>
+#undef SystemFunction036
+
+#pragma warning(pop)
+
+
+void RAND_cleanup(void) {
+}
+
+int RAND_bytes(uint8_t *out, size_t requested) {
+ while (requested > 0) {
+ ULONG output_bytes_this_pass = ULONG_MAX;
+ if (requested < output_bytes_this_pass) {
+ output_bytes_this_pass = requested;
+ }
+ if (RtlGenRandom(out, output_bytes_this_pass) == FALSE) {
+ abort();
+ }
+ requested -= output_bytes_this_pass;
+ out += output_bytes_this_pass;
+ }
+ return 1;
+}
+
+#endif /* OPENSSL_WINDOWS */
diff --git a/src/crypto/rc4/CMakeLists.txt b/src/crypto/rc4/CMakeLists.txt
new file mode 100644
index 0000000..fe2d0c6
--- /dev/null
+++ b/src/crypto/rc4/CMakeLists.txt
@@ -0,0 +1,31 @@
+include_directories(. .. ../../include)
+
+if (${ARCH} STREQUAL "x86_64")
+ set(
+ RC4_ARCH_SOURCES
+
+ rc4-x86_64.${ASM_EXT}
+ rc4-md5-x86_64.${ASM_EXT}
+ )
+endif()
+
+if (${ARCH} STREQUAL "x86")
+ set(
+ RC4_ARCH_SOURCES
+
+ rc4-586.${ASM_EXT}
+ )
+endif()
+
+add_library(
+ rc4
+
+ OBJECT
+
+ rc4.c
+ ${RC4_ARCH_SOURCES}
+)
+
+perlasm(rc4-x86_64.${ASM_EXT} asm/rc4-x86_64.pl)
+perlasm(rc4-md5-x86_64.${ASM_EXT} asm/rc4-md5-x86_64.pl)
+perlasm(rc4-586.${ASM_EXT} asm/rc4-586.pl)
diff --git a/src/crypto/rc4/asm/rc4-586.pl b/src/crypto/rc4/asm/rc4-586.pl
new file mode 100644
index 0000000..fc860ae
--- /dev/null
+++ b/src/crypto/rc4/asm/rc4-586.pl
@@ -0,0 +1,414 @@
+#!/usr/bin/env perl
+
+# ====================================================================
+# [Re]written by Andy Polyakov <appro@fy.chalmers.se> for the OpenSSL
+# project. The module is, however, dual licensed under OpenSSL and
+# CRYPTOGAMS licenses depending on where you obtain it. For further
+# details see http://www.openssl.org/~appro/cryptogams/.
+# ====================================================================
+
+# At some point it became apparent that the original SSLeay RC4
+# assembler implementation performs suboptimally on latest IA-32
+# microarchitectures. After re-tuning performance has changed as
+# following:
+#
+# Pentium -10%
+# Pentium III +12%
+# AMD +50%(*)
+# P4 +250%(**)
+#
+# (*) This number is actually a trade-off:-) It's possible to
+# achieve +72%, but at the cost of -48% off PIII performance.
+# In other words code performing further 13% faster on AMD
+# would perform almost 2 times slower on Intel PIII...
+# For reference! This code delivers ~80% of rc4-amd64.pl
+# performance on the same Opteron machine.
+# (**) This number requires compressed key schedule set up by
+# RC4_set_key [see commentary below for further details].
+#
+# <appro@fy.chalmers.se>
+
+# May 2011
+#
+# Optimize for Core2 and Westmere [and incidentally Opteron]. Current
+# performance in cycles per processed byte (less is better) and
+# improvement relative to previous version of this module is:
+#
+# Pentium 10.2 # original numbers
+# Pentium III 7.8(*)
+# Intel P4 7.5
+#
+# Opteron 6.1/+20% # new MMX numbers
+# Core2 5.3/+67%(**)
+# Westmere 5.1/+94%(**)
+# Sandy Bridge 5.0/+8%
+# Atom 12.6/+6%
+#
+# (*) PIII can actually deliver 6.6 cycles per byte with MMX code,
+# but this specific code performs poorly on Core2. And vice
+# versa, below MMX/SSE code delivering 5.8/7.1 on Core2 performs
+# poorly on PIII, at 8.0/14.5:-( As PIII is not a "hot" CPU
+# [anymore], I chose to discard PIII-specific code path and opt
+# for original IALU-only code, which is why MMX/SSE code path
+# is guarded by SSE2 bit (see below), not MMX/SSE.
+# (**) Performance vs. block size on Core2 and Westmere had a maximum
+# at ... 64 bytes block size. And it was quite a maximum, 40-60%
+# in comparison to largest 8KB block size. Above improvement
+# coefficients are for the largest block size.
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+push(@INC,"${dir}","${dir}../../perlasm");
+require "x86asm.pl";
+
+&asm_init($ARGV[0],"rc4-586.pl",$x86only = $ARGV[$#ARGV] eq "386");
+
+$xx="eax";
+$yy="ebx";
+$tx="ecx";
+$ty="edx";
+$inp="esi";
+$out="ebp";
+$dat="edi";
+
+sub RC4_loop {
+ my $i=shift;
+ my $func = ($i==0)?*mov:*or;
+
+ &add (&LB($yy),&LB($tx));
+ &mov ($ty,&DWP(0,$dat,$yy,4));
+ &mov (&DWP(0,$dat,$yy,4),$tx);
+ &mov (&DWP(0,$dat,$xx,4),$ty);
+ &add ($ty,$tx);
+ &inc (&LB($xx));
+ &and ($ty,0xff);
+ &ror ($out,8) if ($i!=0);
+ if ($i<3) {
+ &mov ($tx,&DWP(0,$dat,$xx,4));
+ } else {
+ &mov ($tx,&wparam(3)); # reload [re-biased] out
+ }
+ &$func ($out,&DWP(0,$dat,$ty,4));
+}
+
+if ($alt=0) {
+ # >20% faster on Atom and Sandy Bridge[!], 8% faster on Opteron,
+ # but ~40% slower on Core2 and Westmere... Attempt to add movz
+ # brings down Opteron by 25%, Atom and Sandy Bridge by 15%, yet
+ # on Core2 with movz it's almost 20% slower than below alternative
+ # code... Yes, it's a total mess...
+ my @XX=($xx,$out);
+ $RC4_loop_mmx = sub { # SSE actually...
+ my $i=shift;
+ my $j=$i<=0?0:$i>>1;
+ my $mm=$i<=0?"mm0":"mm".($i&1);
+
+ &add (&LB($yy),&LB($tx));
+ &lea (@XX[1],&DWP(1,@XX[0]));
+ &pxor ("mm2","mm0") if ($i==0);
+ &psllq ("mm1",8) if ($i==0);
+ &and (@XX[1],0xff);
+ &pxor ("mm0","mm0") if ($i<=0);
+ &mov ($ty,&DWP(0,$dat,$yy,4));
+ &mov (&DWP(0,$dat,$yy,4),$tx);
+ &pxor ("mm1","mm2") if ($i==0);
+ &mov (&DWP(0,$dat,$XX[0],4),$ty);
+ &add (&LB($ty),&LB($tx));
+ &movd (@XX[0],"mm7") if ($i==0);
+ &mov ($tx,&DWP(0,$dat,@XX[1],4));
+ &pxor ("mm1","mm1") if ($i==1);
+ &movq ("mm2",&QWP(0,$inp)) if ($i==1);
+ &movq (&QWP(-8,(@XX[0],$inp)),"mm1") if ($i==0);
+ &pinsrw ($mm,&DWP(0,$dat,$ty,4),$j);
+
+ push (@XX,shift(@XX)) if ($i>=0);
+ }
+} else {
+ # Using pinsrw here improves performane on Intel CPUs by 2-3%, but
+ # brings down AMD by 7%...
+ $RC4_loop_mmx = sub {
+ my $i=shift;
+
+ &add (&LB($yy),&LB($tx));
+ &psllq ("mm1",8*(($i-1)&7)) if (abs($i)!=1);
+ &mov ($ty,&DWP(0,$dat,$yy,4));
+ &mov (&DWP(0,$dat,$yy,4),$tx);
+ &mov (&DWP(0,$dat,$xx,4),$ty);
+ &inc ($xx);
+ &add ($ty,$tx);
+ &movz ($xx,&LB($xx)); # (*)
+ &movz ($ty,&LB($ty)); # (*)
+ &pxor ("mm2",$i==1?"mm0":"mm1") if ($i>=0);
+ &movq ("mm0",&QWP(0,$inp)) if ($i<=0);
+ &movq (&QWP(-8,($out,$inp)),"mm2") if ($i==0);
+ &mov ($tx,&DWP(0,$dat,$xx,4));
+ &movd ($i>0?"mm1":"mm2",&DWP(0,$dat,$ty,4));
+
+ # (*) This is the key to Core2 and Westmere performance.
+ # Whithout movz out-of-order execution logic confuses
+ # itself and fails to reorder loads and stores. Problem
+ # appears to be fixed in Sandy Bridge...
+ }
+}
+
+&external_label("OPENSSL_ia32cap_P");
+
+# void asm_RC4(RC4_KEY *key,size_t len,const unsigned char *inp,unsigned char *out);
+&function_begin("asm_RC4");
+ &mov ($dat,&wparam(0)); # load key schedule pointer
+ &mov ($ty, &wparam(1)); # load len
+ &mov ($inp,&wparam(2)); # load inp
+ &mov ($out,&wparam(3)); # load out
+
+ &xor ($xx,$xx); # avoid partial register stalls
+ &xor ($yy,$yy);
+
+ &cmp ($ty,0); # safety net
+ &je (&label("abort"));
+
+ &mov (&LB($xx),&BP(0,$dat)); # load key->x
+ &mov (&LB($yy),&BP(4,$dat)); # load key->y
+ &add ($dat,8);
+
+ &lea ($tx,&DWP(0,$inp,$ty));
+ &sub ($out,$inp); # re-bias out
+ &mov (&wparam(1),$tx); # save input+len
+
+ &inc (&LB($xx));
+
+ # detect compressed key schedule...
+ &cmp (&DWP(256,$dat),-1);
+ &je (&label("RC4_CHAR"));
+
+ &mov ($tx,&DWP(0,$dat,$xx,4));
+
+ &and ($ty,-4); # how many 4-byte chunks?
+ &jz (&label("loop1"));
+
+ &mov (&wparam(3),$out); # $out as accumulator in these loops
+ if ($x86only) {
+ &jmp (&label("go4loop4"));
+ } else {
+ &test ($ty,-8);
+ &jz (&label("go4loop4"));
+
+ &picmeup($out,"OPENSSL_ia32cap_P");
+ &bt (&DWP(0,$out),26); # check SSE2 bit [could have been MMX]
+ &jnc (&label("go4loop4"));
+
+ &mov ($out,&wparam(3)) if (!$alt);
+ &movd ("mm7",&wparam(3)) if ($alt);
+ &and ($ty,-8);
+ &lea ($ty,&DWP(-8,$inp,$ty));
+ &mov (&DWP(-4,$dat),$ty); # save input+(len/8)*8-8
+
+ &$RC4_loop_mmx(-1);
+ &jmp(&label("loop_mmx_enter"));
+
+ &set_label("loop_mmx",16);
+ &$RC4_loop_mmx(0);
+ &set_label("loop_mmx_enter");
+ for ($i=1;$i<8;$i++) { &$RC4_loop_mmx($i); }
+ &mov ($ty,$yy);
+ &xor ($yy,$yy); # this is second key to Core2
+ &mov (&LB($yy),&LB($ty)); # and Westmere performance...
+ &cmp ($inp,&DWP(-4,$dat));
+ &lea ($inp,&DWP(8,$inp));
+ &jb (&label("loop_mmx"));
+
+ if ($alt) {
+ &movd ($out,"mm7");
+ &pxor ("mm2","mm0");
+ &psllq ("mm1",8);
+ &pxor ("mm1","mm2");
+ &movq (&QWP(-8,$out,$inp),"mm1");
+ } else {
+ &psllq ("mm1",56);
+ &pxor ("mm2","mm1");
+ &movq (&QWP(-8,$out,$inp),"mm2");
+ }
+ &emms ();
+
+ &cmp ($inp,&wparam(1)); # compare to input+len
+ &je (&label("done"));
+ &jmp (&label("loop1"));
+ }
+
+&set_label("go4loop4",16);
+ &lea ($ty,&DWP(-4,$inp,$ty));
+ &mov (&wparam(2),$ty); # save input+(len/4)*4-4
+
+ &set_label("loop4");
+ for ($i=0;$i<4;$i++) { RC4_loop($i); }
+ &ror ($out,8);
+ &xor ($out,&DWP(0,$inp));
+ &cmp ($inp,&wparam(2)); # compare to input+(len/4)*4-4
+ &mov (&DWP(0,$tx,$inp),$out);# $tx holds re-biased out here
+ &lea ($inp,&DWP(4,$inp));
+ &mov ($tx,&DWP(0,$dat,$xx,4));
+ &jb (&label("loop4"));
+
+ &cmp ($inp,&wparam(1)); # compare to input+len
+ &je (&label("done"));
+ &mov ($out,&wparam(3)); # restore $out
+
+ &set_label("loop1",16);
+ &add (&LB($yy),&LB($tx));
+ &mov ($ty,&DWP(0,$dat,$yy,4));
+ &mov (&DWP(0,$dat,$yy,4),$tx);
+ &mov (&DWP(0,$dat,$xx,4),$ty);
+ &add ($ty,$tx);
+ &inc (&LB($xx));
+ &and ($ty,0xff);
+ &mov ($ty,&DWP(0,$dat,$ty,4));
+ &xor (&LB($ty),&BP(0,$inp));
+ &lea ($inp,&DWP(1,$inp));
+ &mov ($tx,&DWP(0,$dat,$xx,4));
+ &cmp ($inp,&wparam(1)); # compare to input+len
+ &mov (&BP(-1,$out,$inp),&LB($ty));
+ &jb (&label("loop1"));
+
+ &jmp (&label("done"));
+
+# this is essentially Intel P4 specific codepath...
+&set_label("RC4_CHAR",16);
+ &movz ($tx,&BP(0,$dat,$xx));
+ # strangely enough unrolled loop performs over 20% slower...
+ &set_label("cloop1");
+ &add (&LB($yy),&LB($tx));
+ &movz ($ty,&BP(0,$dat,$yy));
+ &mov (&BP(0,$dat,$yy),&LB($tx));
+ &mov (&BP(0,$dat,$xx),&LB($ty));
+ &add (&LB($ty),&LB($tx));
+ &movz ($ty,&BP(0,$dat,$ty));
+ &add (&LB($xx),1);
+ &xor (&LB($ty),&BP(0,$inp));
+ &lea ($inp,&DWP(1,$inp));
+ &movz ($tx,&BP(0,$dat,$xx));
+ &cmp ($inp,&wparam(1));
+ &mov (&BP(-1,$out,$inp),&LB($ty));
+ &jb (&label("cloop1"));
+
+&set_label("done");
+ &dec (&LB($xx));
+ &mov (&DWP(-4,$dat),$yy); # save key->y
+ &mov (&BP(-8,$dat),&LB($xx)); # save key->x
+&set_label("abort");
+&function_end("asm_RC4");
+
+########################################################################
+
+$inp="esi";
+$out="edi";
+$idi="ebp";
+$ido="ecx";
+$idx="edx";
+
+# void asm_RC4_set_key(RC4_KEY *key,int len,const unsigned char *data);
+&function_begin("asm_RC4_set_key");
+ &mov ($out,&wparam(0)); # load key
+ &mov ($idi,&wparam(1)); # load len
+ &mov ($inp,&wparam(2)); # load data
+ &picmeup($idx,"OPENSSL_ia32cap_P");
+
+ &lea ($out,&DWP(2*4,$out)); # &key->data
+ &lea ($inp,&DWP(0,$inp,$idi)); # $inp to point at the end
+ &neg ($idi);
+ &xor ("eax","eax");
+ &mov (&DWP(-4,$out),$idi); # borrow key->y
+
+ &bt (&DWP(0,$idx),20); # check for bit#20
+ &jc (&label("c1stloop"));
+
+&set_label("w1stloop",16);
+ &mov (&DWP(0,$out,"eax",4),"eax"); # key->data[i]=i;
+ &add (&LB("eax"),1); # i++;
+ &jnc (&label("w1stloop"));
+
+ &xor ($ido,$ido);
+ &xor ($idx,$idx);
+
+&set_label("w2ndloop",16);
+ &mov ("eax",&DWP(0,$out,$ido,4));
+ &add (&LB($idx),&BP(0,$inp,$idi));
+ &add (&LB($idx),&LB("eax"));
+ &add ($idi,1);
+ &mov ("ebx",&DWP(0,$out,$idx,4));
+ &jnz (&label("wnowrap"));
+ &mov ($idi,&DWP(-4,$out));
+ &set_label("wnowrap");
+ &mov (&DWP(0,$out,$idx,4),"eax");
+ &mov (&DWP(0,$out,$ido,4),"ebx");
+ &add (&LB($ido),1);
+ &jnc (&label("w2ndloop"));
+&jmp (&label("exit"));
+
+# Unlike all other x86 [and x86_64] implementations, Intel P4 core
+# [including EM64T] was found to perform poorly with above "32-bit" key
+# schedule, a.k.a. RC4_INT. Performance improvement for IA-32 hand-coded
+# assembler turned out to be 3.5x if re-coded for compressed 8-bit one,
+# a.k.a. RC4_CHAR! It's however inappropriate to just switch to 8-bit
+# schedule for x86[_64], because non-P4 implementations suffer from
+# significant performance losses then, e.g. PIII exhibits >2x
+# deterioration, and so does Opteron. In order to assure optimal
+# all-round performance, we detect P4 at run-time and set up compressed
+# key schedule, which is recognized by RC4 procedure.
+
+&set_label("c1stloop",16);
+ &mov (&BP(0,$out,"eax"),&LB("eax")); # key->data[i]=i;
+ &add (&LB("eax"),1); # i++;
+ &jnc (&label("c1stloop"));
+
+ &xor ($ido,$ido);
+ &xor ($idx,$idx);
+ &xor ("ebx","ebx");
+
+&set_label("c2ndloop",16);
+ &mov (&LB("eax"),&BP(0,$out,$ido));
+ &add (&LB($idx),&BP(0,$inp,$idi));
+ &add (&LB($idx),&LB("eax"));
+ &add ($idi,1);
+ &mov (&LB("ebx"),&BP(0,$out,$idx));
+ &jnz (&label("cnowrap"));
+ &mov ($idi,&DWP(-4,$out));
+ &set_label("cnowrap");
+ &mov (&BP(0,$out,$idx),&LB("eax"));
+ &mov (&BP(0,$out,$ido),&LB("ebx"));
+ &add (&LB($ido),1);
+ &jnc (&label("c2ndloop"));
+
+ &mov (&DWP(256,$out),-1); # mark schedule as compressed
+
+&set_label("exit");
+ &xor ("eax","eax");
+ &mov (&DWP(-8,$out),"eax"); # key->x=0;
+ &mov (&DWP(-4,$out),"eax"); # key->y=0;
+&function_end("asm_RC4_set_key");
+
+# const char *RC4_options(void);
+&function_begin_B("RC4_options");
+ &call (&label("pic_point"));
+&set_label("pic_point");
+ &blindpop("eax");
+ &lea ("eax",&DWP(&label("opts")."-".&label("pic_point"),"eax"));
+ &picmeup("edx","OPENSSL_ia32cap_P");
+ &mov ("edx",&DWP(0,"edx"));
+ &bt ("edx",20);
+ &jc (&label("1xchar"));
+ &bt ("edx",26);
+ &jnc (&label("ret"));
+ &add ("eax",25);
+ &ret ();
+&set_label("1xchar");
+ &add ("eax",12);
+&set_label("ret");
+ &ret ();
+&set_label("opts",64);
+&asciz ("rc4(4x,int)");
+&asciz ("rc4(1x,char)");
+&asciz ("rc4(8x,mmx)");
+&asciz ("RC4 for x86, CRYPTOGAMS by <appro\@openssl.org>");
+&align (64);
+&function_end_B("RC4_options");
+
+&asm_finish();
+
diff --git a/src/crypto/rc4/asm/rc4-md5-x86_64.pl b/src/crypto/rc4/asm/rc4-md5-x86_64.pl
new file mode 100644
index 0000000..272fa91
--- /dev/null
+++ b/src/crypto/rc4/asm/rc4-md5-x86_64.pl
@@ -0,0 +1,632 @@
+#!/usr/bin/env perl
+#
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+# project. The module is, however, dual licensed under OpenSSL and
+# CRYPTOGAMS licenses depending on where you obtain it. For further
+# details see http://www.openssl.org/~appro/cryptogams/.
+# ====================================================================
+
+# June 2011
+#
+# This is RC4+MD5 "stitch" implementation. The idea, as spelled in
+# http://download.intel.com/design/intarch/papers/323686.pdf, is that
+# since both algorithms exhibit instruction-level parallelism, ILP,
+# below theoretical maximum, interleaving them would allow to utilize
+# processor resources better and achieve better performance. RC4
+# instruction sequence is virtually identical to rc4-x86_64.pl, which
+# is heavily based on submission by Maxim Perminov, Maxim Locktyukhin
+# and Jim Guilford of Intel. MD5 is fresh implementation aiming to
+# minimize register usage, which was used as "main thread" with RC4
+# weaved into it, one RC4 round per one MD5 round. In addition to the
+# stiched subroutine the script can generate standalone replacement
+# md5_block_asm_data_order and RC4. Below are performance numbers in
+# cycles per processed byte, less is better, for these the standalone
+# subroutines, sum of them, and stitched one:
+#
+# RC4 MD5 RC4+MD5 stitch gain
+# Opteron 6.5(*) 5.4 11.9 7.0 +70%(*)
+# Core2 6.5 5.8 12.3 7.7 +60%
+# Westmere 4.3 5.2 9.5 7.0 +36%
+# Sandy Bridge 4.2 5.5 9.7 6.8 +43%
+# Atom 9.3 6.5 15.8 11.1 +42%
+#
+# (*) rc4-x86_64.pl delivers 5.3 on Opteron, so real improvement
+# is +53%...
+
+my ($rc4,$md5)=(1,1); # what to generate?
+my $D="#" if (!$md5); # if set to "#", MD5 is stitched into RC4(),
+ # but its result is discarded. Idea here is
+ # to be able to use 'openssl speed rc4' for
+ # benchmarking the stitched subroutine...
+
+my $flavour = shift;
+my $output = shift;
+if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+
+my $win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; my $dir=$1; my $xlate;
+( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
+( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
+die "can't locate x86_64-xlate.pl";
+
+open OUT,"| \"$^X\" $xlate $flavour $output";
+*STDOUT=*OUT;
+
+my ($dat,$in0,$out,$ctx,$inp,$len, $func,$nargs);
+
+if ($rc4 && !$md5) {
+ ($dat,$len,$in0,$out) = ("%rdi","%rsi","%rdx","%rcx");
+ $func="RC4"; $nargs=4;
+} elsif ($md5 && !$rc4) {
+ ($ctx,$inp,$len) = ("%rdi","%rsi","%rdx");
+ $func="md5_block_asm_data_order"; $nargs=3;
+} else {
+ ($dat,$in0,$out,$ctx,$inp,$len) = ("%rdi","%rsi","%rdx","%rcx","%r8","%r9");
+ $func="rc4_md5_enc"; $nargs=6;
+ # void rc4_md5_enc(
+ # RC4_KEY *key, #
+ # const void *in0, # RC4 input
+ # void *out, # RC4 output
+ # MD5_CTX *ctx, #
+ # const void *inp, # MD5 input
+ # size_t len); # number of 64-byte blocks
+}
+
+my @K=( 0xd76aa478,0xe8c7b756,0x242070db,0xc1bdceee,
+ 0xf57c0faf,0x4787c62a,0xa8304613,0xfd469501,
+ 0x698098d8,0x8b44f7af,0xffff5bb1,0x895cd7be,
+ 0x6b901122,0xfd987193,0xa679438e,0x49b40821,
+
+ 0xf61e2562,0xc040b340,0x265e5a51,0xe9b6c7aa,
+ 0xd62f105d,0x02441453,0xd8a1e681,0xe7d3fbc8,
+ 0x21e1cde6,0xc33707d6,0xf4d50d87,0x455a14ed,
+ 0xa9e3e905,0xfcefa3f8,0x676f02d9,0x8d2a4c8a,
+
+ 0xfffa3942,0x8771f681,0x6d9d6122,0xfde5380c,
+ 0xa4beea44,0x4bdecfa9,0xf6bb4b60,0xbebfbc70,
+ 0x289b7ec6,0xeaa127fa,0xd4ef3085,0x04881d05,
+ 0xd9d4d039,0xe6db99e5,0x1fa27cf8,0xc4ac5665,
+
+ 0xf4292244,0x432aff97,0xab9423a7,0xfc93a039,
+ 0x655b59c3,0x8f0ccc92,0xffeff47d,0x85845dd1,
+ 0x6fa87e4f,0xfe2ce6e0,0xa3014314,0x4e0811a1,
+ 0xf7537e82,0xbd3af235,0x2ad7d2bb,0xeb86d391 );
+
+my @V=("%r8d","%r9d","%r10d","%r11d"); # MD5 registers
+my $tmp="%r12d";
+
+my @XX=("%rbp","%rsi"); # RC4 registers
+my @TX=("%rax","%rbx");
+my $YY="%rcx";
+my $TY="%rdx";
+
+my $MOD=32; # 16, 32 or 64
+
+$code.=<<___;
+.text
+.align 16
+
+.globl $func
+.type $func,\@function,$nargs
+$func:
+ cmp \$0,$len
+ je .Labort
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+ sub \$40,%rsp
+.Lbody:
+___
+if ($rc4) {
+$code.=<<___;
+$D#md5# mov $ctx,%r11 # reassign arguments
+ mov $len,%r12
+ mov $in0,%r13
+ mov $out,%r14
+$D#md5# mov $inp,%r15
+___
+ $ctx="%r11" if ($md5); # reassign arguments
+ $len="%r12";
+ $in0="%r13";
+ $out="%r14";
+ $inp="%r15" if ($md5);
+ $inp=$in0 if (!$md5);
+$code.=<<___;
+ xor $XX[0],$XX[0]
+ xor $YY,$YY
+
+ lea 8($dat),$dat
+ mov -8($dat),$XX[0]#b
+ mov -4($dat),$YY#b
+
+ inc $XX[0]#b
+ sub $in0,$out
+ movl ($dat,$XX[0],4),$TX[0]#d
+___
+$code.=<<___ if (!$md5);
+ xor $TX[1],$TX[1]
+ test \$-128,$len
+ jz .Loop1
+ sub $XX[0],$TX[1]
+ and \$`$MOD-1`,$TX[1]
+ jz .Loop${MOD}_is_hot
+ sub $TX[1],$len
+.Loop${MOD}_warmup:
+ add $TX[0]#b,$YY#b
+ movl ($dat,$YY,4),$TY#d
+ movl $TX[0]#d,($dat,$YY,4)
+ movl $TY#d,($dat,$XX[0],4)
+ add $TY#b,$TX[0]#b
+ inc $XX[0]#b
+ movl ($dat,$TX[0],4),$TY#d
+ movl ($dat,$XX[0],4),$TX[0]#d
+ xorb ($in0),$TY#b
+ movb $TY#b,($out,$in0)
+ lea 1($in0),$in0
+ dec $TX[1]
+ jnz .Loop${MOD}_warmup
+
+ mov $YY,$TX[1]
+ xor $YY,$YY
+ mov $TX[1]#b,$YY#b
+
+.Loop${MOD}_is_hot:
+ mov $len,32(%rsp) # save original $len
+ shr \$6,$len # number of 64-byte blocks
+___
+ if ($D && !$md5) { # stitch in dummy MD5
+ $md5=1;
+ $ctx="%r11";
+ $inp="%r15";
+ $code.=<<___;
+ mov %rsp,$ctx
+ mov $in0,$inp
+___
+ }
+}
+$code.=<<___;
+#rc4# add $TX[0]#b,$YY#b
+#rc4# lea ($dat,$XX[0],4),$XX[1]
+ shl \$6,$len
+ add $inp,$len # pointer to the end of input
+ mov $len,16(%rsp)
+
+#md5# mov $ctx,24(%rsp) # save pointer to MD5_CTX
+#md5# mov 0*4($ctx),$V[0] # load current hash value from MD5_CTX
+#md5# mov 1*4($ctx),$V[1]
+#md5# mov 2*4($ctx),$V[2]
+#md5# mov 3*4($ctx),$V[3]
+ jmp .Loop
+
+.align 16
+.Loop:
+#md5# mov $V[0],0*4(%rsp) # put aside current hash value
+#md5# mov $V[1],1*4(%rsp)
+#md5# mov $V[2],2*4(%rsp)
+#md5# mov $V[3],$tmp # forward reference
+#md5# mov $V[3],3*4(%rsp)
+___
+
+sub R0 {
+ my ($i,$a,$b,$c,$d)=@_;
+ my @rot0=(7,12,17,22);
+ my $j=$i%16;
+ my $k=$i%$MOD;
+ my $xmm="%xmm".($j&1);
+ $code.=" movdqu ($in0),%xmm2\n" if ($rc4 && $j==15);
+ $code.=" add \$$MOD,$XX[0]#b\n" if ($rc4 && $j==15 && $k==$MOD-1);
+ $code.=" pxor $xmm,$xmm\n" if ($rc4 && $j<=1);
+ $code.=<<___;
+#rc4# movl ($dat,$YY,4),$TY#d
+#md5# xor $c,$tmp
+#rc4# movl $TX[0]#d,($dat,$YY,4)
+#md5# and $b,$tmp
+#md5# add 4*`$j`($inp),$a
+#rc4# add $TY#b,$TX[0]#b
+#rc4# movl `4*(($k+1)%$MOD)`(`$k==$MOD-1?"$dat,$XX[0],4":"$XX[1]"`),$TX[1]#d
+#md5# add \$$K[$i],$a
+#md5# xor $d,$tmp
+#rc4# movz $TX[0]#b,$TX[0]#d
+#rc4# movl $TY#d,4*$k($XX[1])
+#md5# add $tmp,$a
+#rc4# add $TX[1]#b,$YY#b
+#md5# rol \$$rot0[$j%4],$a
+#md5# mov `$j==15?"$b":"$c"`,$tmp # forward reference
+#rc4# pinsrw \$`($j>>1)&7`,($dat,$TX[0],4),$xmm\n
+#md5# add $b,$a
+___
+ $code.=<<___ if ($rc4 && $j==15 && $k==$MOD-1);
+ mov $YY,$XX[1]
+ xor $YY,$YY # keyword to partial register
+ mov $XX[1]#b,$YY#b
+ lea ($dat,$XX[0],4),$XX[1]
+___
+ $code.=<<___ if ($rc4 && $j==15);
+ psllq \$8,%xmm1
+ pxor %xmm0,%xmm2
+ pxor %xmm1,%xmm2
+___
+}
+sub R1 {
+ my ($i,$a,$b,$c,$d)=@_;
+ my @rot1=(5,9,14,20);
+ my $j=$i%16;
+ my $k=$i%$MOD;
+ my $xmm="%xmm".($j&1);
+ $code.=" movdqu 16($in0),%xmm3\n" if ($rc4 && $j==15);
+ $code.=" add \$$MOD,$XX[0]#b\n" if ($rc4 && $j==15 && $k==$MOD-1);
+ $code.=" pxor $xmm,$xmm\n" if ($rc4 && $j<=1);
+ $code.=<<___;
+#rc4# movl ($dat,$YY,4),$TY#d
+#md5# xor $b,$tmp
+#rc4# movl $TX[0]#d,($dat,$YY,4)
+#md5# and $d,$tmp
+#md5# add 4*`((1+5*$j)%16)`($inp),$a
+#rc4# add $TY#b,$TX[0]#b
+#rc4# movl `4*(($k+1)%$MOD)`(`$k==$MOD-1?"$dat,$XX[0],4":"$XX[1]"`),$TX[1]#d
+#md5# add \$$K[$i],$a
+#md5# xor $c,$tmp
+#rc4# movz $TX[0]#b,$TX[0]#d
+#rc4# movl $TY#d,4*$k($XX[1])
+#md5# add $tmp,$a
+#rc4# add $TX[1]#b,$YY#b
+#md5# rol \$$rot1[$j%4],$a
+#md5# mov `$j==15?"$c":"$b"`,$tmp # forward reference
+#rc4# pinsrw \$`($j>>1)&7`,($dat,$TX[0],4),$xmm\n
+#md5# add $b,$a
+___
+ $code.=<<___ if ($rc4 && $j==15 && $k==$MOD-1);
+ mov $YY,$XX[1]
+ xor $YY,$YY # keyword to partial register
+ mov $XX[1]#b,$YY#b
+ lea ($dat,$XX[0],4),$XX[1]
+___
+ $code.=<<___ if ($rc4 && $j==15);
+ psllq \$8,%xmm1
+ pxor %xmm0,%xmm3
+ pxor %xmm1,%xmm3
+___
+}
+sub R2 {
+ my ($i,$a,$b,$c,$d)=@_;
+ my @rot2=(4,11,16,23);
+ my $j=$i%16;
+ my $k=$i%$MOD;
+ my $xmm="%xmm".($j&1);
+ $code.=" movdqu 32($in0),%xmm4\n" if ($rc4 && $j==15);
+ $code.=" add \$$MOD,$XX[0]#b\n" if ($rc4 && $j==15 && $k==$MOD-1);
+ $code.=" pxor $xmm,$xmm\n" if ($rc4 && $j<=1);
+ $code.=<<___;
+#rc4# movl ($dat,$YY,4),$TY#d
+#md5# xor $c,$tmp
+#rc4# movl $TX[0]#d,($dat,$YY,4)
+#md5# xor $b,$tmp
+#md5# add 4*`((5+3*$j)%16)`($inp),$a
+#rc4# add $TY#b,$TX[0]#b
+#rc4# movl `4*(($k+1)%$MOD)`(`$k==$MOD-1?"$dat,$XX[0],4":"$XX[1]"`),$TX[1]#d
+#md5# add \$$K[$i],$a
+#rc4# movz $TX[0]#b,$TX[0]#d
+#md5# add $tmp,$a
+#rc4# movl $TY#d,4*$k($XX[1])
+#rc4# add $TX[1]#b,$YY#b
+#md5# rol \$$rot2[$j%4],$a
+#md5# mov `$j==15?"\\\$-1":"$c"`,$tmp # forward reference
+#rc4# pinsrw \$`($j>>1)&7`,($dat,$TX[0],4),$xmm\n
+#md5# add $b,$a
+___
+ $code.=<<___ if ($rc4 && $j==15 && $k==$MOD-1);
+ mov $YY,$XX[1]
+ xor $YY,$YY # keyword to partial register
+ mov $XX[1]#b,$YY#b
+ lea ($dat,$XX[0],4),$XX[1]
+___
+ $code.=<<___ if ($rc4 && $j==15);
+ psllq \$8,%xmm1
+ pxor %xmm0,%xmm4
+ pxor %xmm1,%xmm4
+___
+}
+sub R3 {
+ my ($i,$a,$b,$c,$d)=@_;
+ my @rot3=(6,10,15,21);
+ my $j=$i%16;
+ my $k=$i%$MOD;
+ my $xmm="%xmm".($j&1);
+ $code.=" movdqu 48($in0),%xmm5\n" if ($rc4 && $j==15);
+ $code.=" add \$$MOD,$XX[0]#b\n" if ($rc4 && $j==15 && $k==$MOD-1);
+ $code.=" pxor $xmm,$xmm\n" if ($rc4 && $j<=1);
+ $code.=<<___;
+#rc4# movl ($dat,$YY,4),$TY#d
+#md5# xor $d,$tmp
+#rc4# movl $TX[0]#d,($dat,$YY,4)
+#md5# or $b,$tmp
+#md5# add 4*`((7*$j)%16)`($inp),$a
+#rc4# add $TY#b,$TX[0]#b
+#rc4# movl `4*(($k+1)%$MOD)`(`$k==$MOD-1?"$dat,$XX[0],4":"$XX[1]"`),$TX[1]#d
+#md5# add \$$K[$i],$a
+#rc4# movz $TX[0]#b,$TX[0]#d
+#md5# xor $c,$tmp
+#rc4# movl $TY#d,4*$k($XX[1])
+#md5# add $tmp,$a
+#rc4# add $TX[1]#b,$YY#b
+#md5# rol \$$rot3[$j%4],$a
+#md5# mov \$-1,$tmp # forward reference
+#rc4# pinsrw \$`($j>>1)&7`,($dat,$TX[0],4),$xmm\n
+#md5# add $b,$a
+___
+ $code.=<<___ if ($rc4 && $j==15);
+ mov $XX[0],$XX[1]
+ xor $XX[0],$XX[0] # keyword to partial register
+ mov $XX[1]#b,$XX[0]#b
+ mov $YY,$XX[1]
+ xor $YY,$YY # keyword to partial register
+ mov $XX[1]#b,$YY#b
+ lea ($dat,$XX[0],4),$XX[1]
+ psllq \$8,%xmm1
+ pxor %xmm0,%xmm5
+ pxor %xmm1,%xmm5
+___
+}
+
+my $i=0;
+for(;$i<16;$i++) { R0($i,@V); unshift(@V,pop(@V)); push(@TX,shift(@TX)); }
+for(;$i<32;$i++) { R1($i,@V); unshift(@V,pop(@V)); push(@TX,shift(@TX)); }
+for(;$i<48;$i++) { R2($i,@V); unshift(@V,pop(@V)); push(@TX,shift(@TX)); }
+for(;$i<64;$i++) { R3($i,@V); unshift(@V,pop(@V)); push(@TX,shift(@TX)); }
+
+$code.=<<___;
+#md5# add 0*4(%rsp),$V[0] # accumulate hash value
+#md5# add 1*4(%rsp),$V[1]
+#md5# add 2*4(%rsp),$V[2]
+#md5# add 3*4(%rsp),$V[3]
+
+#rc4# movdqu %xmm2,($out,$in0) # write RC4 output
+#rc4# movdqu %xmm3,16($out,$in0)
+#rc4# movdqu %xmm4,32($out,$in0)
+#rc4# movdqu %xmm5,48($out,$in0)
+#md5# lea 64($inp),$inp
+#rc4# lea 64($in0),$in0
+ cmp 16(%rsp),$inp # are we done?
+ jb .Loop
+
+#md5# mov 24(%rsp),$len # restore pointer to MD5_CTX
+#rc4# sub $TX[0]#b,$YY#b # correct $YY
+#md5# mov $V[0],0*4($len) # write MD5_CTX
+#md5# mov $V[1],1*4($len)
+#md5# mov $V[2],2*4($len)
+#md5# mov $V[3],3*4($len)
+___
+$code.=<<___ if ($rc4 && (!$md5 || $D));
+ mov 32(%rsp),$len # restore original $len
+ and \$63,$len # remaining bytes
+ jnz .Loop1
+ jmp .Ldone
+
+.align 16
+.Loop1:
+ add $TX[0]#b,$YY#b
+ movl ($dat,$YY,4),$TY#d
+ movl $TX[0]#d,($dat,$YY,4)
+ movl $TY#d,($dat,$XX[0],4)
+ add $TY#b,$TX[0]#b
+ inc $XX[0]#b
+ movl ($dat,$TX[0],4),$TY#d
+ movl ($dat,$XX[0],4),$TX[0]#d
+ xorb ($in0),$TY#b
+ movb $TY#b,($out,$in0)
+ lea 1($in0),$in0
+ dec $len
+ jnz .Loop1
+
+.Ldone:
+___
+$code.=<<___;
+#rc4# sub \$1,$XX[0]#b
+#rc4# movl $XX[0]#d,-8($dat)
+#rc4# movl $YY#d,-4($dat)
+
+ mov 40(%rsp),%r15
+ mov 48(%rsp),%r14
+ mov 56(%rsp),%r13
+ mov 64(%rsp),%r12
+ mov 72(%rsp),%rbp
+ mov 80(%rsp),%rbx
+ lea 88(%rsp),%rsp
+.Lepilogue:
+.Labort:
+ ret
+.size $func,.-$func
+___
+
+if ($rc4 && $D) { # sole purpose of this section is to provide
+ # option to use the generated module as drop-in
+ # replacement for rc4-x86_64.pl for debugging
+ # and testing purposes...
+my ($idx,$ido)=("%r8","%r9");
+my ($dat,$len,$inp)=("%rdi","%rsi","%rdx");
+
+$code.=<<___;
+.globl RC4_set_key
+.type RC4_set_key,\@function,3
+.align 16
+RC4_set_key:
+ lea 8($dat),$dat
+ lea ($inp,$len),$inp
+ neg $len
+ mov $len,%rcx
+ xor %eax,%eax
+ xor $ido,$ido
+ xor %r10,%r10
+ xor %r11,%r11
+ jmp .Lw1stloop
+
+.align 16
+.Lw1stloop:
+ mov %eax,($dat,%rax,4)
+ add \$1,%al
+ jnc .Lw1stloop
+
+ xor $ido,$ido
+ xor $idx,$idx
+.align 16
+.Lw2ndloop:
+ mov ($dat,$ido,4),%r10d
+ add ($inp,$len,1),$idx#b
+ add %r10b,$idx#b
+ add \$1,$len
+ mov ($dat,$idx,4),%r11d
+ cmovz %rcx,$len
+ mov %r10d,($dat,$idx,4)
+ mov %r11d,($dat,$ido,4)
+ add \$1,$ido#b
+ jnc .Lw2ndloop
+
+ xor %eax,%eax
+ mov %eax,-8($dat)
+ mov %eax,-4($dat)
+ ret
+.size RC4_set_key,.-RC4_set_key
+
+.globl RC4_options
+.type RC4_options,\@abi-omnipotent
+.align 16
+RC4_options:
+ lea .Lopts(%rip),%rax
+ ret
+.align 64
+.Lopts:
+.asciz "rc4(64x,int)"
+.align 64
+.size RC4_options,.-RC4_options
+___
+}
+# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame,
+# CONTEXT *context,DISPATCHER_CONTEXT *disp)
+if ($win64) {
+my $rec="%rcx";
+my $frame="%rdx";
+my $context="%r8";
+my $disp="%r9";
+
+$code.=<<___;
+.extern __imp_RtlVirtualUnwind
+.type se_handler,\@abi-omnipotent
+.align 16
+se_handler:
+ push %rsi
+ push %rdi
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+ pushfq
+ sub \$64,%rsp
+
+ mov 120($context),%rax # pull context->Rax
+ mov 248($context),%rbx # pull context->Rip
+
+ lea .Lbody(%rip),%r10
+ cmp %r10,%rbx # context->Rip<.Lbody
+ jb .Lin_prologue
+
+ mov 152($context),%rax # pull context->Rsp
+
+ lea .Lepilogue(%rip),%r10
+ cmp %r10,%rbx # context->Rip>=.Lepilogue
+ jae .Lin_prologue
+
+ mov 40(%rax),%r15
+ mov 48(%rax),%r14
+ mov 56(%rax),%r13
+ mov 64(%rax),%r12
+ mov 72(%rax),%rbp
+ mov 80(%rax),%rbx
+ lea 88(%rax),%rax
+
+ mov %rbx,144($context) # restore context->Rbx
+ mov %rbp,160($context) # restore context->Rbp
+ mov %r12,216($context) # restore context->R12
+ mov %r13,224($context) # restore context->R12
+ mov %r14,232($context) # restore context->R14
+ mov %r15,240($context) # restore context->R15
+
+.Lin_prologue:
+ mov 8(%rax),%rdi
+ mov 16(%rax),%rsi
+ mov %rax,152($context) # restore context->Rsp
+ mov %rsi,168($context) # restore context->Rsi
+ mov %rdi,176($context) # restore context->Rdi
+
+ mov 40($disp),%rdi # disp->ContextRecord
+ mov $context,%rsi # context
+ mov \$154,%ecx # sizeof(CONTEXT)
+ .long 0xa548f3fc # cld; rep movsq
+
+ mov $disp,%rsi
+ xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER
+ mov 8(%rsi),%rdx # arg2, disp->ImageBase
+ mov 0(%rsi),%r8 # arg3, disp->ControlPc
+ mov 16(%rsi),%r9 # arg4, disp->FunctionEntry
+ mov 40(%rsi),%r10 # disp->ContextRecord
+ lea 56(%rsi),%r11 # &disp->HandlerData
+ lea 24(%rsi),%r12 # &disp->EstablisherFrame
+ mov %r10,32(%rsp) # arg5
+ mov %r11,40(%rsp) # arg6
+ mov %r12,48(%rsp) # arg7
+ mov %rcx,56(%rsp) # arg8, (NULL)
+ call *__imp_RtlVirtualUnwind(%rip)
+
+ mov \$1,%eax # ExceptionContinueSearch
+ add \$64,%rsp
+ popfq
+ pop %r15
+ pop %r14
+ pop %r13
+ pop %r12
+ pop %rbp
+ pop %rbx
+ pop %rdi
+ pop %rsi
+ ret
+.size se_handler,.-se_handler
+
+.section .pdata
+.align 4
+ .rva .LSEH_begin_$func
+ .rva .LSEH_end_$func
+ .rva .LSEH_info_$func
+
+.section .xdata
+.align 8
+.LSEH_info_$func:
+ .byte 9,0,0,0
+ .rva se_handler
+___
+}
+
+sub reg_part {
+my ($reg,$conv)=@_;
+ if ($reg =~ /%r[0-9]+/) { $reg .= $conv; }
+ elsif ($conv eq "b") { $reg =~ s/%[er]([^x]+)x?/%$1l/; }
+ elsif ($conv eq "w") { $reg =~ s/%[er](.+)/%$1/; }
+ elsif ($conv eq "d") { $reg =~ s/%[er](.+)/%e$1/; }
+ return $reg;
+}
+
+$code =~ s/(%[a-z0-9]+)#([bwd])/reg_part($1,$2)/gem;
+$code =~ s/\`([^\`]*)\`/eval $1/gem;
+$code =~ s/pinsrw\s+\$0,/movd /gm;
+
+$code =~ s/#md5#//gm if ($md5);
+$code =~ s/#rc4#//gm if ($rc4);
+
+print $code;
+
+close STDOUT;
diff --git a/src/crypto/rc4/asm/rc4-x86_64.pl b/src/crypto/rc4/asm/rc4-x86_64.pl
new file mode 100644
index 0000000..2c52ac0
--- /dev/null
+++ b/src/crypto/rc4/asm/rc4-x86_64.pl
@@ -0,0 +1,679 @@
+#!/usr/bin/env perl
+#
+# ====================================================================
+# Written by Andy Polyakov <appro@fy.chalmers.se> for the OpenSSL
+# project. The module is, however, dual licensed under OpenSSL and
+# CRYPTOGAMS licenses depending on where you obtain it. For further
+# details see http://www.openssl.org/~appro/cryptogams/.
+# ====================================================================
+#
+# July 2004
+#
+# 2.22x RC4 tune-up:-) It should be noted though that my hand [as in
+# "hand-coded assembler"] doesn't stand for the whole improvement
+# coefficient. It turned out that eliminating RC4_CHAR from config
+# line results in ~40% improvement (yes, even for C implementation).
+# Presumably it has everything to do with AMD cache architecture and
+# RAW or whatever penalties. Once again! The module *requires* config
+# line *without* RC4_CHAR! As for coding "secret," I bet on partial
+# register arithmetics. For example instead of 'inc %r8; and $255,%r8'
+# I simply 'inc %r8b'. Even though optimization manual discourages
+# to operate on partial registers, it turned out to be the best bet.
+# At least for AMD... How IA32E would perform remains to be seen...
+
+# November 2004
+#
+# As was shown by Marc Bevand reordering of couple of load operations
+# results in even higher performance gain of 3.3x:-) At least on
+# Opteron... For reference, 1x in this case is RC4_CHAR C-code
+# compiled with gcc 3.3.2, which performs at ~54MBps per 1GHz clock.
+# Latter means that if you want to *estimate* what to expect from
+# *your* Opteron, then multiply 54 by 3.3 and clock frequency in GHz.
+
+# November 2004
+#
+# Intel P4 EM64T core was found to run the AMD64 code really slow...
+# The only way to achieve comparable performance on P4 was to keep
+# RC4_CHAR. Kind of ironic, huh? As it's apparently impossible to
+# compose blended code, which would perform even within 30% marginal
+# on either AMD and Intel platforms, I implement both cases. See
+# rc4_skey.c for further details...
+
+# April 2005
+#
+# P4 EM64T core appears to be "allergic" to 64-bit inc/dec. Replacing
+# those with add/sub results in 50% performance improvement of folded
+# loop...
+
+# May 2005
+#
+# As was shown by Zou Nanhai loop unrolling can improve Intel EM64T
+# performance by >30% [unlike P4 32-bit case that is]. But this is
+# provided that loads are reordered even more aggressively! Both code
+# pathes, AMD64 and EM64T, reorder loads in essentially same manner
+# as my IA-64 implementation. On Opteron this resulted in modest 5%
+# improvement [I had to test it], while final Intel P4 performance
+# achieves respectful 432MBps on 2.8GHz processor now. For reference.
+# If executed on Xeon, current RC4_CHAR code-path is 2.7x faster than
+# RC4_INT code-path. While if executed on Opteron, it's only 25%
+# slower than the RC4_INT one [meaning that if CPU µ-arch detection
+# is not implemented, then this final RC4_CHAR code-path should be
+# preferred, as it provides better *all-round* performance].
+
+# March 2007
+#
+# Intel Core2 was observed to perform poorly on both code paths:-( It
+# apparently suffers from some kind of partial register stall, which
+# occurs in 64-bit mode only [as virtually identical 32-bit loop was
+# observed to outperform 64-bit one by almost 50%]. Adding two movzb to
+# cloop1 boosts its performance by 80%! This loop appears to be optimal
+# fit for Core2 and therefore the code was modified to skip cloop8 on
+# this CPU.
+
+# May 2010
+#
+# Intel Westmere was observed to perform suboptimally. Adding yet
+# another movzb to cloop1 improved performance by almost 50%! Core2
+# performance is improved too, but nominally...
+
+# May 2011
+#
+# The only code path that was not modified is P4-specific one. Non-P4
+# Intel code path optimization is heavily based on submission by Maxim
+# Perminov, Maxim Locktyukhin and Jim Guilford of Intel. I've used
+# some of the ideas even in attempt to optmize the original RC4_INT
+# code path... Current performance in cycles per processed byte (less
+# is better) and improvement coefficients relative to previous
+# version of this module are:
+#
+# Opteron 5.3/+0%(*)
+# P4 6.5
+# Core2 6.2/+15%(**)
+# Westmere 4.2/+60%
+# Sandy Bridge 4.2/+120%
+# Atom 9.3/+80%
+#
+# (*) But corresponding loop has less instructions, which should have
+# positive effect on upcoming Bulldozer, which has one less ALU.
+# For reference, Intel code runs at 6.8 cpb rate on Opteron.
+# (**) Note that Core2 result is ~15% lower than corresponding result
+# for 32-bit code, meaning that it's possible to improve it,
+# but more than likely at the cost of the others (see rc4-586.pl
+# to get the idea)...
+
+$flavour = shift;
+$output = shift;
+if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+
+$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
+( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
+die "can't locate x86_64-xlate.pl";
+
+open OUT,"| \"$^X\" $xlate $flavour $output";
+*STDOUT=*OUT;
+
+$dat="%rdi"; # arg1
+$len="%rsi"; # arg2
+$inp="%rdx"; # arg3
+$out="%rcx"; # arg4
+
+{
+$code=<<___;
+.text
+.extern OPENSSL_ia32cap_P
+
+.globl asm_RC4
+.type asm_RC4,\@function,4
+.align 16
+asm_RC4:
+ or $len,$len
+ jne .Lentry
+ ret
+.Lentry:
+ push %rbx
+ push %r12
+ push %r13
+.Lprologue:
+ mov $len,%r11
+ mov $inp,%r12
+ mov $out,%r13
+___
+my $len="%r11"; # reassign input arguments
+my $inp="%r12";
+my $out="%r13";
+
+my @XX=("%r10","%rsi");
+my @TX=("%rax","%rbx");
+my $YY="%rcx";
+my $TY="%rdx";
+
+$code.=<<___;
+ xor $XX[0],$XX[0]
+ xor $YY,$YY
+
+ lea 8($dat),$dat
+ mov -8($dat),$XX[0]#b
+ mov -4($dat),$YY#b
+ cmpl \$-1,256($dat)
+ je .LRC4_CHAR
+ mov OPENSSL_ia32cap_P(%rip),%r8d
+ xor $TX[1],$TX[1]
+ inc $XX[0]#b
+ sub $XX[0],$TX[1]
+ sub $inp,$out
+ movl ($dat,$XX[0],4),$TX[0]#d
+ test \$-16,$len
+ jz .Lloop1
+ bt \$30,%r8d # Intel CPU?
+ jc .Lintel
+ and \$7,$TX[1]
+ lea 1($XX[0]),$XX[1]
+ jz .Loop8
+ sub $TX[1],$len
+.Loop8_warmup:
+ add $TX[0]#b,$YY#b
+ movl ($dat,$YY,4),$TY#d
+ movl $TX[0]#d,($dat,$YY,4)
+ movl $TY#d,($dat,$XX[0],4)
+ add $TY#b,$TX[0]#b
+ inc $XX[0]#b
+ movl ($dat,$TX[0],4),$TY#d
+ movl ($dat,$XX[0],4),$TX[0]#d
+ xorb ($inp),$TY#b
+ movb $TY#b,($out,$inp)
+ lea 1($inp),$inp
+ dec $TX[1]
+ jnz .Loop8_warmup
+
+ lea 1($XX[0]),$XX[1]
+ jmp .Loop8
+.align 16
+.Loop8:
+___
+for ($i=0;$i<8;$i++) {
+$code.=<<___ if ($i==7);
+ add \$8,$XX[1]#b
+___
+$code.=<<___;
+ add $TX[0]#b,$YY#b
+ movl ($dat,$YY,4),$TY#d
+ movl $TX[0]#d,($dat,$YY,4)
+ movl `4*($i==7?-1:$i)`($dat,$XX[1],4),$TX[1]#d
+ ror \$8,%r8 # ror is redundant when $i=0
+ movl $TY#d,4*$i($dat,$XX[0],4)
+ add $TX[0]#b,$TY#b
+ movb ($dat,$TY,4),%r8b
+___
+push(@TX,shift(@TX)); #push(@XX,shift(@XX)); # "rotate" registers
+}
+$code.=<<___;
+ add \$8,$XX[0]#b
+ ror \$8,%r8
+ sub \$8,$len
+
+ xor ($inp),%r8
+ mov %r8,($out,$inp)
+ lea 8($inp),$inp
+
+ test \$-8,$len
+ jnz .Loop8
+ cmp \$0,$len
+ jne .Lloop1
+ jmp .Lexit
+
+.align 16
+.Lintel:
+ test \$-32,$len
+ jz .Lloop1
+ and \$15,$TX[1]
+ jz .Loop16_is_hot
+ sub $TX[1],$len
+.Loop16_warmup:
+ add $TX[0]#b,$YY#b
+ movl ($dat,$YY,4),$TY#d
+ movl $TX[0]#d,($dat,$YY,4)
+ movl $TY#d,($dat,$XX[0],4)
+ add $TY#b,$TX[0]#b
+ inc $XX[0]#b
+ movl ($dat,$TX[0],4),$TY#d
+ movl ($dat,$XX[0],4),$TX[0]#d
+ xorb ($inp),$TY#b
+ movb $TY#b,($out,$inp)
+ lea 1($inp),$inp
+ dec $TX[1]
+ jnz .Loop16_warmup
+
+ mov $YY,$TX[1]
+ xor $YY,$YY
+ mov $TX[1]#b,$YY#b
+
+.Loop16_is_hot:
+ lea ($dat,$XX[0],4),$XX[1]
+___
+sub RC4_loop {
+ my $i=shift;
+ my $j=$i<0?0:$i;
+ my $xmm="%xmm".($j&1);
+
+ $code.=" add \$16,$XX[0]#b\n" if ($i==15);
+ $code.=" movdqu ($inp),%xmm2\n" if ($i==15);
+ $code.=" add $TX[0]#b,$YY#b\n" if ($i<=0);
+ $code.=" movl ($dat,$YY,4),$TY#d\n";
+ $code.=" pxor %xmm0,%xmm2\n" if ($i==0);
+ $code.=" psllq \$8,%xmm1\n" if ($i==0);
+ $code.=" pxor $xmm,$xmm\n" if ($i<=1);
+ $code.=" movl $TX[0]#d,($dat,$YY,4)\n";
+ $code.=" add $TY#b,$TX[0]#b\n";
+ $code.=" movl `4*($j+1)`($XX[1]),$TX[1]#d\n" if ($i<15);
+ $code.=" movz $TX[0]#b,$TX[0]#d\n";
+ $code.=" movl $TY#d,4*$j($XX[1])\n";
+ $code.=" pxor %xmm1,%xmm2\n" if ($i==0);
+ $code.=" lea ($dat,$XX[0],4),$XX[1]\n" if ($i==15);
+ $code.=" add $TX[1]#b,$YY#b\n" if ($i<15);
+ $code.=" pinsrw \$`($j>>1)&7`,($dat,$TX[0],4),$xmm\n";
+ $code.=" movdqu %xmm2,($out,$inp)\n" if ($i==0);
+ $code.=" lea 16($inp),$inp\n" if ($i==0);
+ $code.=" movl ($XX[1]),$TX[1]#d\n" if ($i==15);
+}
+ RC4_loop(-1);
+$code.=<<___;
+ jmp .Loop16_enter
+.align 16
+.Loop16:
+___
+
+for ($i=0;$i<16;$i++) {
+ $code.=".Loop16_enter:\n" if ($i==1);
+ RC4_loop($i);
+ push(@TX,shift(@TX)); # "rotate" registers
+}
+$code.=<<___;
+ mov $YY,$TX[1]
+ xor $YY,$YY # keyword to partial register
+ sub \$16,$len
+ mov $TX[1]#b,$YY#b
+ test \$-16,$len
+ jnz .Loop16
+
+ psllq \$8,%xmm1
+ pxor %xmm0,%xmm2
+ pxor %xmm1,%xmm2
+ movdqu %xmm2,($out,$inp)
+ lea 16($inp),$inp
+
+ cmp \$0,$len
+ jne .Lloop1
+ jmp .Lexit
+
+.align 16
+.Lloop1:
+ add $TX[0]#b,$YY#b
+ movl ($dat,$YY,4),$TY#d
+ movl $TX[0]#d,($dat,$YY,4)
+ movl $TY#d,($dat,$XX[0],4)
+ add $TY#b,$TX[0]#b
+ inc $XX[0]#b
+ movl ($dat,$TX[0],4),$TY#d
+ movl ($dat,$XX[0],4),$TX[0]#d
+ xorb ($inp),$TY#b
+ movb $TY#b,($out,$inp)
+ lea 1($inp),$inp
+ dec $len
+ jnz .Lloop1
+ jmp .Lexit
+
+.align 16
+.LRC4_CHAR:
+ add \$1,$XX[0]#b
+ movzb ($dat,$XX[0]),$TX[0]#d
+ test \$-8,$len
+ jz .Lcloop1
+ jmp .Lcloop8
+.align 16
+.Lcloop8:
+ mov ($inp),%r8d
+ mov 4($inp),%r9d
+___
+# unroll 2x4-wise, because 64-bit rotates kill Intel P4...
+for ($i=0;$i<4;$i++) {
+$code.=<<___;
+ add $TX[0]#b,$YY#b
+ lea 1($XX[0]),$XX[1]
+ movzb ($dat,$YY),$TY#d
+ movzb $XX[1]#b,$XX[1]#d
+ movzb ($dat,$XX[1]),$TX[1]#d
+ movb $TX[0]#b,($dat,$YY)
+ cmp $XX[1],$YY
+ movb $TY#b,($dat,$XX[0])
+ jne .Lcmov$i # Intel cmov is sloooow...
+ mov $TX[0],$TX[1]
+.Lcmov$i:
+ add $TX[0]#b,$TY#b
+ xor ($dat,$TY),%r8b
+ ror \$8,%r8d
+___
+push(@TX,shift(@TX)); push(@XX,shift(@XX)); # "rotate" registers
+}
+for ($i=4;$i<8;$i++) {
+$code.=<<___;
+ add $TX[0]#b,$YY#b
+ lea 1($XX[0]),$XX[1]
+ movzb ($dat,$YY),$TY#d
+ movzb $XX[1]#b,$XX[1]#d
+ movzb ($dat,$XX[1]),$TX[1]#d
+ movb $TX[0]#b,($dat,$YY)
+ cmp $XX[1],$YY
+ movb $TY#b,($dat,$XX[0])
+ jne .Lcmov$i # Intel cmov is sloooow...
+ mov $TX[0],$TX[1]
+.Lcmov$i:
+ add $TX[0]#b,$TY#b
+ xor ($dat,$TY),%r9b
+ ror \$8,%r9d
+___
+push(@TX,shift(@TX)); push(@XX,shift(@XX)); # "rotate" registers
+}
+$code.=<<___;
+ lea -8($len),$len
+ mov %r8d,($out)
+ lea 8($inp),$inp
+ mov %r9d,4($out)
+ lea 8($out),$out
+
+ test \$-8,$len
+ jnz .Lcloop8
+ cmp \$0,$len
+ jne .Lcloop1
+ jmp .Lexit
+___
+$code.=<<___;
+.align 16
+.Lcloop1:
+ add $TX[0]#b,$YY#b
+ movzb $YY#b,$YY#d
+ movzb ($dat,$YY),$TY#d
+ movb $TX[0]#b,($dat,$YY)
+ movb $TY#b,($dat,$XX[0])
+ add $TX[0]#b,$TY#b
+ add \$1,$XX[0]#b
+ movzb $TY#b,$TY#d
+ movzb $XX[0]#b,$XX[0]#d
+ movzb ($dat,$TY),$TY#d
+ movzb ($dat,$XX[0]),$TX[0]#d
+ xorb ($inp),$TY#b
+ lea 1($inp),$inp
+ movb $TY#b,($out)
+ lea 1($out),$out
+ sub \$1,$len
+ jnz .Lcloop1
+ jmp .Lexit
+
+.align 16
+.Lexit:
+ sub \$1,$XX[0]#b
+ movl $XX[0]#d,-8($dat)
+ movl $YY#d,-4($dat)
+
+ mov (%rsp),%r13
+ mov 8(%rsp),%r12
+ mov 16(%rsp),%rbx
+ add \$24,%rsp
+.Lepilogue:
+ ret
+.size asm_RC4,.-asm_RC4
+___
+}
+
+$idx="%r8";
+$ido="%r9";
+
+$code.=<<___;
+.globl asm_RC4_set_key
+.type asm_RC4_set_key,\@function,3
+.align 16
+asm_RC4_set_key:
+ lea 8($dat),$dat
+ lea ($inp,$len),$inp
+ neg $len
+ mov $len,%rcx
+ xor %eax,%eax
+ xor $ido,$ido
+ xor %r10,%r10
+ xor %r11,%r11
+
+ mov OPENSSL_ia32cap_P(%rip),$idx#d
+ bt \$20,$idx#d # RC4_CHAR?
+ jc .Lc1stloop
+ jmp .Lw1stloop
+
+.align 16
+.Lw1stloop:
+ mov %eax,($dat,%rax,4)
+ add \$1,%al
+ jnc .Lw1stloop
+
+ xor $ido,$ido
+ xor $idx,$idx
+.align 16
+.Lw2ndloop:
+ mov ($dat,$ido,4),%r10d
+ add ($inp,$len,1),$idx#b
+ add %r10b,$idx#b
+ add \$1,$len
+ mov ($dat,$idx,4),%r11d
+ cmovz %rcx,$len
+ mov %r10d,($dat,$idx,4)
+ mov %r11d,($dat,$ido,4)
+ add \$1,$ido#b
+ jnc .Lw2ndloop
+ jmp .Lexit_key
+
+.align 16
+.Lc1stloop:
+ mov %al,($dat,%rax)
+ add \$1,%al
+ jnc .Lc1stloop
+
+ xor $ido,$ido
+ xor $idx,$idx
+.align 16
+.Lc2ndloop:
+ mov ($dat,$ido),%r10b
+ add ($inp,$len),$idx#b
+ add %r10b,$idx#b
+ add \$1,$len
+ mov ($dat,$idx),%r11b
+ jnz .Lcnowrap
+ mov %rcx,$len
+.Lcnowrap:
+ mov %r10b,($dat,$idx)
+ mov %r11b,($dat,$ido)
+ add \$1,$ido#b
+ jnc .Lc2ndloop
+ movl \$-1,256($dat)
+
+.align 16
+.Lexit_key:
+ xor %eax,%eax
+ mov %eax,-8($dat)
+ mov %eax,-4($dat)
+ ret
+.size asm_RC4_set_key,.-asm_RC4_set_key
+
+.globl RC4_options
+.type RC4_options,\@abi-omnipotent
+.align 16
+RC4_options:
+ lea .Lopts(%rip),%rax
+ mov OPENSSL_ia32cap_P(%rip),%rdx
+ mov (%rdx),%edx
+ bt \$20,%edx
+ jc .L8xchar
+ bt \$30,%edx
+ jnc .Ldone
+ add \$25,%rax
+ ret
+.L8xchar:
+ add \$12,%rax
+.Ldone:
+ ret
+.align 64
+.Lopts:
+.asciz "rc4(8x,int)"
+.asciz "rc4(8x,char)"
+.asciz "rc4(16x,int)"
+.asciz "RC4 for x86_64, CRYPTOGAMS by <appro\@openssl.org>"
+.align 64
+.size RC4_options,.-RC4_options
+___
+
+# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame,
+# CONTEXT *context,DISPATCHER_CONTEXT *disp)
+if ($win64) {
+$rec="%rcx";
+$frame="%rdx";
+$context="%r8";
+$disp="%r9";
+
+$code.=<<___;
+.extern __imp_RtlVirtualUnwind
+.type stream_se_handler,\@abi-omnipotent
+.align 16
+stream_se_handler:
+ push %rsi
+ push %rdi
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+ pushfq
+ sub \$64,%rsp
+
+ mov 120($context),%rax # pull context->Rax
+ mov 248($context),%rbx # pull context->Rip
+
+ lea .Lprologue(%rip),%r10
+ cmp %r10,%rbx # context->Rip<prologue label
+ jb .Lin_prologue
+
+ mov 152($context),%rax # pull context->Rsp
+
+ lea .Lepilogue(%rip),%r10
+ cmp %r10,%rbx # context->Rip>=epilogue label
+ jae .Lin_prologue
+
+ lea 24(%rax),%rax
+
+ mov -8(%rax),%rbx
+ mov -16(%rax),%r12
+ mov -24(%rax),%r13
+ mov %rbx,144($context) # restore context->Rbx
+ mov %r12,216($context) # restore context->R12
+ mov %r13,224($context) # restore context->R13
+
+.Lin_prologue:
+ mov 8(%rax),%rdi
+ mov 16(%rax),%rsi
+ mov %rax,152($context) # restore context->Rsp
+ mov %rsi,168($context) # restore context->Rsi
+ mov %rdi,176($context) # restore context->Rdi
+
+ jmp .Lcommon_seh_exit
+.size stream_se_handler,.-stream_se_handler
+
+.type key_se_handler,\@abi-omnipotent
+.align 16
+key_se_handler:
+ push %rsi
+ push %rdi
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+ pushfq
+ sub \$64,%rsp
+
+ mov 152($context),%rax # pull context->Rsp
+ mov 8(%rax),%rdi
+ mov 16(%rax),%rsi
+ mov %rsi,168($context) # restore context->Rsi
+ mov %rdi,176($context) # restore context->Rdi
+
+.Lcommon_seh_exit:
+
+ mov 40($disp),%rdi # disp->ContextRecord
+ mov $context,%rsi # context
+ mov \$154,%ecx # sizeof(CONTEXT)
+ .long 0xa548f3fc # cld; rep movsq
+
+ mov $disp,%rsi
+ xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER
+ mov 8(%rsi),%rdx # arg2, disp->ImageBase
+ mov 0(%rsi),%r8 # arg3, disp->ControlPc
+ mov 16(%rsi),%r9 # arg4, disp->FunctionEntry
+ mov 40(%rsi),%r10 # disp->ContextRecord
+ lea 56(%rsi),%r11 # &disp->HandlerData
+ lea 24(%rsi),%r12 # &disp->EstablisherFrame
+ mov %r10,32(%rsp) # arg5
+ mov %r11,40(%rsp) # arg6
+ mov %r12,48(%rsp) # arg7
+ mov %rcx,56(%rsp) # arg8, (NULL)
+ call *__imp_RtlVirtualUnwind(%rip)
+
+ mov \$1,%eax # ExceptionContinueSearch
+ add \$64,%rsp
+ popfq
+ pop %r15
+ pop %r14
+ pop %r13
+ pop %r12
+ pop %rbp
+ pop %rbx
+ pop %rdi
+ pop %rsi
+ ret
+.size key_se_handler,.-key_se_handler
+
+.section .pdata
+.align 4
+ .rva .LSEH_begin_asm_RC4
+ .rva .LSEH_end_asm_RC4
+ .rva .LSEH_info_asm_RC4
+
+ .rva .LSEH_begin_asm_RC4_set_key
+ .rva .LSEH_end_asm_RC4_set_key
+ .rva .LSEH_info_asm_RC4_set_key
+
+.section .xdata
+.align 8
+.LSEH_info_asm_RC4:
+ .byte 9,0,0,0
+ .rva stream_se_handler
+.LSEH_info_asm_RC4_set_key:
+ .byte 9,0,0,0
+ .rva key_se_handler
+___
+}
+
+sub reg_part {
+my ($reg,$conv)=@_;
+ if ($reg =~ /%r[0-9]+/) { $reg .= $conv; }
+ elsif ($conv eq "b") { $reg =~ s/%[er]([^x]+)x?/%$1l/; }
+ elsif ($conv eq "w") { $reg =~ s/%[er](.+)/%$1/; }
+ elsif ($conv eq "d") { $reg =~ s/%[er](.+)/%e$1/; }
+ return $reg;
+}
+
+$code =~ s/(%[a-z0-9]+)#([bwd])/reg_part($1,$2)/gem;
+$code =~ s/\`([^\`]*)\`/eval $1/gem;
+
+print $code;
+
+close STDOUT;
diff --git a/src/crypto/rc4/rc4.c b/src/crypto/rc4/rc4.c
new file mode 100644
index 0000000..00b59c8
--- /dev/null
+++ b/src/crypto/rc4/rc4.c
@@ -0,0 +1,371 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/rc4.h>
+
+#if defined(OPENSSL_NO_ASM) || \
+ (!defined(OPENSSL_X86_64) && !defined(OPENSSL_X86))
+
+#if defined(OPENSSL_64_BIT)
+#define RC4_CHUNK uint64_t
+#elif defined(OPENSSL_32_BIT)
+#define RC4_CHUNK uint32_t
+#else
+#error "Unknown word size"
+#endif
+
+#define RC4_INT uint32_t
+
+
+/* RC4 as implemented from a posting from
+ * Newsgroups: sci.crypt
+ * From: sterndark@netcom.com (David Sterndark)
+ * Subject: RC4 Algorithm revealed.
+ * Message-ID: <sternCvKL4B.Hyy@netcom.com>
+ * Date: Wed, 14 Sep 1994 06:35:31 GMT */
+
+void RC4(RC4_KEY *key, size_t len, const uint8_t *in, uint8_t *out) {
+ register RC4_INT *d;
+ register 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...
+ *
+ * Cavets.
+ *
+ * - 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".
+ *
+ * <appro@fy.chalmers.se> */
+
+#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)in & (sizeof(RC4_CHUNK) - 1)) |
+ ((size_t)out & (sizeof(RC4_CHUNK) - 1))) == 0) {
+ RC4_CHUNK ichunk, otp;
+ const union {
+ long one;
+ char little;
+ } is_endian = {1};
+
+ /* 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 <terr@terralogic.net>
+ * who also stands for the is_endian union:-)
+ *
+ * Special notes.
+ *
+ * - is_endian is declared automatic as doing otherwise
+ * (declaring static) prevents gcc from eliminating
+ * the redundant code;
+ * - 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
+ *
+ * <appro@fy.chalmers.se> */
+ if (!is_endian.little) { /* BIG-ENDIAN CASE */
+#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 *)in;
+ otp = RC4_STEP << BESHFT(0);
+ otp |= RC4_STEP << BESHFT(1);
+ otp |= RC4_STEP << BESHFT(2);
+ otp |= RC4_STEP << BESHFT(3);
+#if defined(OPENSSL_64_BIT)
+ otp |= RC4_STEP << BESHFT(4);
+ otp |= RC4_STEP << BESHFT(5);
+ otp |= RC4_STEP << BESHFT(6);
+ otp |= RC4_STEP << BESHFT(7);
+#endif
+ *(RC4_CHUNK *)out = otp ^ ichunk;
+ in += sizeof(RC4_CHUNK);
+ out += sizeof(RC4_CHUNK);
+ }
+ if (len) {
+ RC4_CHUNK mask = (RC4_CHUNK) - 1, ochunk;
+
+ ichunk = *(RC4_CHUNK *)in;
+ ochunk = *(RC4_CHUNK *)out;
+ otp = 0;
+ i = BESHFT(0);
+ mask <<= (sizeof(RC4_CHUNK) - len) << 3;
+ switch (len & (sizeof(RC4_CHUNK) - 1)) {
+ case 7:
+ otp = RC4_STEP << i, i -= 8;
+ case 6:
+ otp |= RC4_STEP << i, i -= 8;
+ case 5:
+ otp |= RC4_STEP << i, i -= 8;
+ case 4:
+ otp |= RC4_STEP << i, i -= 8;
+ case 3:
+ otp |= RC4_STEP << i, i -= 8;
+ case 2:
+ otp |= RC4_STEP << i, i -= 8;
+ case 1:
+ otp |= RC4_STEP << i, i -= 8;
+ }
+ ochunk &= ~mask;
+ ochunk |= (otp ^ ichunk) & mask;
+ *(RC4_CHUNK *)out = ochunk;
+ }
+ key->x = x;
+ key->y = y;
+ return;
+ } else { /* LITTLE-ENDIAN CASE */
+#define LESHFT(c) (((c) * 8) & (sizeof(RC4_CHUNK) * 8 - 1))
+ for (; len & (0 - sizeof(RC4_CHUNK)); len -= sizeof(RC4_CHUNK)) {
+ ichunk = *(RC4_CHUNK *)in;
+ otp = RC4_STEP;
+ otp |= RC4_STEP << 8;
+ otp |= RC4_STEP << 16;
+ otp |= RC4_STEP << 24;
+#if defined(OPENSSL_64_BIT)
+ otp |= RC4_STEP << LESHFT(4);
+ otp |= RC4_STEP << LESHFT(5);
+ otp |= RC4_STEP << LESHFT(6);
+ otp |= RC4_STEP << LESHFT(7);
+#endif
+ *(RC4_CHUNK *)out = otp ^ ichunk;
+ in += sizeof(RC4_CHUNK);
+ out += sizeof(RC4_CHUNK);
+ }
+ if (len) {
+ RC4_CHUNK mask = (RC4_CHUNK) - 1, ochunk;
+
+ ichunk = *(RC4_CHUNK *)in;
+ ochunk = *(RC4_CHUNK *)out;
+ otp = 0;
+ i = 0;
+ mask >>= (sizeof(RC4_CHUNK) - len) << 3;
+ switch (len & (sizeof(RC4_CHUNK) - 1)) {
+ case 7:
+ otp = RC4_STEP, i += 8;
+ case 6:
+ otp |= RC4_STEP << i, i += 8;
+ case 5:
+ otp |= RC4_STEP << i, i += 8;
+ case 4:
+ otp |= RC4_STEP << i, i += 8;
+ case 3:
+ otp |= RC4_STEP << i, i += 8;
+ case 2:
+ otp |= RC4_STEP << i, i += 8;
+ case 1:
+ otp |= RC4_STEP << i, i += 8;
+ }
+ ochunk &= ~mask;
+ ochunk |= (otp ^ ichunk) & mask;
+ *(RC4_CHUNK *)out = ochunk;
+ }
+ key->x = x;
+ key->y = y;
+ return;
+ }
+ }
+#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(in, out, 0);
+ RC4_LOOP(in, out, 1);
+ RC4_LOOP(in, out, 2);
+ RC4_LOOP(in, out, 3);
+ RC4_LOOP(in, out, 4);
+ RC4_LOOP(in, out, 5);
+ RC4_LOOP(in, out, 6);
+ RC4_LOOP(in, out, 7);
+#ifdef RC4_INDEX
+ in += 8;
+ out += 8;
+#endif
+ if (--i == 0)
+ break;
+ }
+ }
+ i = len & 0x07;
+ if (i) {
+ for (;;) {
+ RC4_LOOP(in, out, 0);
+ if (--i == 0)
+ break;
+ RC4_LOOP(in, out, 1);
+ if (--i == 0)
+ break;
+ RC4_LOOP(in, out, 2);
+ if (--i == 0)
+ break;
+ RC4_LOOP(in, out, 3);
+ if (--i == 0)
+ break;
+ RC4_LOOP(in, out, 4);
+ if (--i == 0)
+ break;
+ RC4_LOOP(in, out, 5);
+ if (--i == 0)
+ break;
+ RC4_LOOP(in, out, 6);
+ if (--i == 0)
+ break;
+ }
+ }
+ key->x = x;
+ key->y = y;
+}
+
+void RC4_set_key(RC4_KEY *rc4key, unsigned len, const uint8_t *key) {
+ register RC4_INT tmp;
+ register int id1, id2;
+ register RC4_INT *d;
+ unsigned int i;
+
+ d = &rc4key->data[0];
+ rc4key->x = 0;
+ rc4key->y = 0;
+ id1 = id2 = 0;
+
+#define SK_LOOP(d, n) \
+ { \
+ tmp = d[(n)]; \
+ id2 = (key[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);
+ }
+}
+
+#else
+
+/* In this case several functions are provided by asm code. However, one cannot
+ * control asm symbol visibility with command line flags and such so they are
+ * always hidden and wrapped by these C functions, which can be so
+ * controlled. */
+
+void asm_RC4(RC4_KEY *key, size_t len, const uint8_t *in, uint8_t *out);
+void RC4(RC4_KEY *key, size_t len, const uint8_t *in, uint8_t *out) {
+ asm_RC4(key, len, in, out);
+}
+
+void asm_RC4_set_key(RC4_KEY *rc4key, unsigned len, const uint8_t *key);
+void RC4_set_key(RC4_KEY *rc4key, unsigned len, const uint8_t *key) {
+ asm_RC4_set_key(rc4key, len, key);
+}
+
+#endif /* OPENSSL_NO_ASM || (!OPENSSL_X86_64 && !OPENSSL_X86) */
diff --git a/src/crypto/rsa/CMakeLists.txt b/src/crypto/rsa/CMakeLists.txt
new file mode 100644
index 0000000..b3d8fa4
--- /dev/null
+++ b/src/crypto/rsa/CMakeLists.txt
@@ -0,0 +1,22 @@
+include_directories(. .. ../../include)
+
+add_library(
+ rsa
+
+ OBJECT
+
+ rsa.c
+ rsa_impl.c
+ blinding.c
+ padding.c
+ rsa_asn1.c
+ rsa_error.c
+)
+
+add_executable(
+ rsa_test
+
+ rsa_test.c
+)
+
+target_link_libraries(rsa_test crypto)
diff --git a/src/crypto/rsa/blinding.c b/src/crypto/rsa/blinding.c
new file mode 100644
index 0000000..06f87a7
--- /dev/null
+++ b/src/crypto/rsa/blinding.c
@@ -0,0 +1,471 @@
+/* ====================================================================
+ * 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 <openssl/rsa.h>
+
+#include <string.h>
+
+#include <openssl/bn.h>
+#include <openssl/mem.h>
+#include <openssl/err.h>
+
+#include "internal.h"
+
+
+#define BN_BLINDING_COUNTER 32
+
+struct bn_blinding_st {
+ BIGNUM *A;
+ BIGNUM *Ai;
+ BIGNUM *e;
+ BIGNUM *mod; /* just a reference */
+ CRYPTO_THREADID tid;
+ int counter;
+ unsigned long flags;
+ BN_MONT_CTX *m_ctx;
+ int (*bn_mod_exp)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
+};
+
+BN_BLINDING *BN_BLINDING_new(const BIGNUM *A, const BIGNUM *Ai, BIGNUM *mod) {
+ BN_BLINDING *ret = NULL;
+
+ ret = (BN_BLINDING*) OPENSSL_malloc(sizeof(BN_BLINDING));
+ if (ret == NULL) {
+ OPENSSL_PUT_ERROR(RSA, BN_BLINDING_new, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ memset(ret, 0, sizeof(BN_BLINDING));
+ if (A != NULL) {
+ ret->A = BN_dup(A);
+ if (ret->A == NULL) {
+ goto err;
+ }
+ }
+ if (Ai != NULL) {
+ ret->Ai = BN_dup(Ai);
+ if (ret->Ai == NULL) {
+ goto err;
+ }
+ }
+
+ /* save a copy of mod in the BN_BLINDING structure */
+ ret->mod = BN_dup(mod);
+ if (ret->mod == NULL) {
+ goto err;
+ }
+ if (BN_get_flags(mod, BN_FLG_CONSTTIME) != 0) {
+ BN_set_flags(ret->mod, BN_FLG_CONSTTIME);
+ }
+
+ /* Set the counter to the special value -1
+ * to indicate that this is never-used fresh blinding
+ * that does not need updating before first use. */
+ ret->counter = -1;
+ CRYPTO_THREADID_current(&ret->tid);
+ return ret;
+
+err:
+ if (ret != NULL) {
+ BN_BLINDING_free(ret);
+ }
+ return NULL;
+}
+
+void BN_BLINDING_free(BN_BLINDING *r) {
+ if (r == NULL) {
+ return;
+ }
+
+ if (r->A != NULL)
+ BN_free(r->A);
+ if (r->Ai != NULL)
+ BN_free(r->Ai);
+ if (r->e != NULL)
+ BN_free(r->e);
+ if (r->mod != NULL)
+ BN_free(r->mod);
+ OPENSSL_free(r);
+}
+
+int BN_BLINDING_update(BN_BLINDING *b, BN_CTX *ctx) {
+ int ret = 0;
+
+ if (b->A == NULL || b->Ai == NULL) {
+ OPENSSL_PUT_ERROR(RSA, BN_BLINDING_update, RSA_R_BN_NOT_INITIALIZED);
+ goto err;
+ }
+
+ if (b->counter == -1) {
+ b->counter = 0;
+ }
+
+ if (++b->counter == BN_BLINDING_COUNTER && b->e != NULL &&
+ !(b->flags & BN_BLINDING_NO_RECREATE)) {
+ /* re-create blinding parameters */
+ if (!BN_BLINDING_create_param(b, NULL, NULL, ctx, NULL, NULL)) {
+ goto err;
+ }
+ } else if (!(b->flags & BN_BLINDING_NO_UPDATE)) {
+ if (!BN_mod_mul(b->A, b->A, b->A, b->mod, ctx)) {
+ goto err;
+ }
+ if (!BN_mod_mul(b->Ai, b->Ai, b->Ai, b->mod, ctx)) {
+ goto err;
+ }
+ }
+
+ ret = 1;
+
+err:
+ if (b->counter == BN_BLINDING_COUNTER) {
+ b->counter = 0;
+ }
+ return ret;
+}
+
+int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx) {
+ return BN_BLINDING_convert_ex(n, NULL, b, ctx);
+}
+
+int BN_BLINDING_convert_ex(BIGNUM *n, BIGNUM *r, BN_BLINDING *b, BN_CTX *ctx) {
+ int ret = 1;
+
+ if (b->A == NULL || b->Ai == NULL) {
+ OPENSSL_PUT_ERROR(RSA, BN_BLINDING_convert_ex, RSA_R_BN_NOT_INITIALIZED);
+ return 0;
+ }
+
+ if (b->counter == -1) {
+ /* Fresh blinding, doesn't need updating. */
+ b->counter = 0;
+ } else if (!BN_BLINDING_update(b, ctx)) {
+ return 0;
+ }
+
+ if (r != NULL) {
+ if (!BN_copy(r, b->Ai)) {
+ ret = 0;
+ }
+ }
+
+ if (!BN_mod_mul(n, n, b->A, b->mod, ctx)) {
+ ret = 0;
+ }
+
+ return ret;
+}
+
+int BN_BLINDING_invert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx) {
+ return BN_BLINDING_invert_ex(n, NULL, b, ctx);
+}
+
+int BN_BLINDING_invert_ex(BIGNUM *n, const BIGNUM *r, BN_BLINDING *b,
+ BN_CTX *ctx) {
+ int ret;
+
+ if (r != NULL) {
+ ret = BN_mod_mul(n, n, r, b->mod, ctx);
+ } else {
+ if (b->Ai == NULL) {
+ OPENSSL_PUT_ERROR(RSA, BN_BLINDING_invert_ex, RSA_R_BN_NOT_INITIALIZED);
+ return 0;
+ }
+ ret = BN_mod_mul(n, n, b->Ai, b->mod, ctx);
+ }
+
+ return ret;
+}
+
+CRYPTO_THREADID *BN_BLINDING_thread_id(BN_BLINDING *b) { return &b->tid; }
+
+unsigned long BN_BLINDING_get_flags(const BN_BLINDING *b) { return b->flags; }
+
+void BN_BLINDING_set_flags(BN_BLINDING *b, unsigned long flags) {
+ b->flags = flags;
+}
+
+BN_BLINDING *BN_BLINDING_create_param(
+ BN_BLINDING *b, const BIGNUM *e, BIGNUM *m, 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) {
+ int retry_counter = 32;
+ BN_BLINDING *ret = NULL;
+
+ if (b == NULL) {
+ ret = BN_BLINDING_new(NULL, NULL, m);
+ } else {
+ ret = b;
+ }
+
+ if (ret == NULL) {
+ goto err;
+ }
+
+ if (ret->A == NULL && (ret->A = BN_new()) == NULL) {
+ goto err;
+ }
+ if (ret->Ai == NULL && (ret->Ai = BN_new()) == NULL) {
+ goto err;
+ }
+
+ if (e != NULL) {
+ if (ret->e != NULL) {
+ BN_free(ret->e);
+ }
+ ret->e = BN_dup(e);
+ }
+ if (ret->e == NULL) {
+ goto err;
+ }
+
+ if (bn_mod_exp != NULL) {
+ ret->bn_mod_exp = bn_mod_exp;
+ }
+ if (m_ctx != NULL) {
+ ret->m_ctx = m_ctx;
+ }
+
+ do {
+ if (!BN_rand_range(ret->A, ret->mod)) {
+ goto err;
+ }
+ if (BN_mod_inverse(ret->Ai, ret->A, ret->mod, ctx) == NULL) {
+ /* this should almost never happen for good RSA keys */
+ uint32_t error = ERR_peek_last_error();
+ if (ERR_GET_REASON(error) == BN_R_NO_INVERSE) {
+ if (retry_counter-- == 0) {
+ OPENSSL_PUT_ERROR(RSA, BN_BLINDING_create_param,
+ RSA_R_TOO_MANY_ITERATIONS);
+ goto err;
+ }
+ ERR_clear_error();
+ } else {
+ goto err;
+ }
+ } else {
+ break;
+ }
+ } while (1);
+
+ if (ret->bn_mod_exp != NULL && ret->m_ctx != NULL) {
+ if (!ret->bn_mod_exp(ret->A, ret->A, ret->e, ret->mod, ctx, ret->m_ctx)) {
+ goto err;
+ }
+ } else {
+ if (!BN_mod_exp(ret->A, ret->A, ret->e, ret->mod, ctx)) {
+ goto err;
+ }
+ }
+
+ return ret;
+
+err:
+ if (b == NULL && ret != NULL) {
+ BN_BLINDING_free(ret);
+ ret = NULL;
+ }
+
+ return ret;
+}
+
+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);
+ r0 = BN_CTX_get(ctx);
+ r1 = BN_CTX_get(ctx);
+ r2 = BN_CTX_get(ctx);
+ if (r2 == 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(NULL, d, r0, ctx);
+
+err:
+ BN_CTX_end(ctx);
+ return ret;
+}
+
+BN_BLINDING *rsa_setup_blinding(RSA *rsa, BN_CTX *in_ctx) {
+ BIGNUM local_n;
+ BIGNUM *e, *n;
+ BN_CTX *ctx;
+ BN_BLINDING *ret = NULL;
+
+ if (in_ctx == NULL) {
+ ctx = BN_CTX_new();
+ if (ctx == NULL) {
+ return 0;
+ }
+ } else {
+ ctx = in_ctx;
+ }
+
+ BN_CTX_start(ctx);
+ e = BN_CTX_get(ctx);
+ if (e == NULL) {
+ OPENSSL_PUT_ERROR(RSA, rsa_setup_blinding, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (rsa->e == NULL) {
+ e = rsa_get_public_exp(rsa->d, rsa->p, rsa->q, ctx);
+ if (e == NULL) {
+ OPENSSL_PUT_ERROR(RSA, rsa_setup_blinding, RSA_R_NO_PUBLIC_EXPONENT);
+ goto err;
+ }
+ } else {
+ e = rsa->e;
+ }
+
+ n = &local_n;
+ BN_with_flags(n, rsa->n, BN_FLG_CONSTTIME);
+
+ 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;
+ }
+ }
+
+ ret = BN_BLINDING_create_param(NULL, e, n, ctx, rsa->meth->bn_mod_exp,
+ rsa->_method_mod_n);
+ if (ret == NULL) {
+ OPENSSL_PUT_ERROR(RSA, rsa_setup_blinding, ERR_R_BN_LIB);
+ goto err;
+ }
+ CRYPTO_THREADID_current(BN_BLINDING_thread_id(ret));
+
+err:
+ BN_CTX_end(ctx);
+ if (in_ctx == NULL) {
+ BN_CTX_free(ctx);
+ }
+ if (rsa->e == NULL) {
+ BN_free(e);
+ }
+
+ return ret;
+}
diff --git a/src/crypto/rsa/internal.h b/src/crypto/rsa/internal.h
new file mode 100644
index 0000000..aa3a982
--- /dev/null
+++ b/src/crypto/rsa/internal.h
@@ -0,0 +1,150 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 OPENSSL_HEADER_RSA_INTERNAL_H
+#define OPENSSL_HEADER_RSA_INTERNAL_H
+
+#include <openssl/base.h>
+
+#include <openssl/asn1.h>
+#include <openssl/thread.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+#define RSA_PKCS1_PADDING_SIZE 11
+
+
+/* BN_BLINDING flags */
+#define BN_BLINDING_NO_UPDATE 0x00000001
+#define BN_BLINDING_NO_RECREATE 0x00000002
+
+BN_BLINDING *BN_BLINDING_new(const BIGNUM *A, const BIGNUM *Ai, BIGNUM *mod);
+void BN_BLINDING_free(BN_BLINDING *b);
+int BN_BLINDING_update(BN_BLINDING *b, BN_CTX *ctx);
+int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx);
+int BN_BLINDING_invert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx);
+int BN_BLINDING_convert_ex(BIGNUM *n, BIGNUM *r, BN_BLINDING *b, BN_CTX *);
+int BN_BLINDING_invert_ex(BIGNUM *n, const BIGNUM *r, BN_BLINDING *b, BN_CTX *);
+CRYPTO_THREADID *BN_BLINDING_thread_id(BN_BLINDING *);
+unsigned long BN_BLINDING_get_flags(const BN_BLINDING *);
+void BN_BLINDING_set_flags(BN_BLINDING *, unsigned long);
+BN_BLINDING *BN_BLINDING_create_param(
+ BN_BLINDING *b, const BIGNUM *e, BIGNUM *m, 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 *rsa_setup_blinding(RSA *rsa, BN_CTX *in_ctx);
+
+
+int RSA_padding_add_PKCS1_type_1(uint8_t *to, unsigned to_len,
+ const uint8_t *from, unsigned from_len);
+int RSA_padding_check_PKCS1_type_1(uint8_t *to, unsigned to_len,
+ const uint8_t *from, unsigned from_len);
+int RSA_padding_add_PKCS1_type_2(uint8_t *to, unsigned to_len,
+ const uint8_t *from, unsigned from_len);
+int RSA_padding_check_PKCS1_type_2(uint8_t *to, unsigned to_len,
+ const uint8_t *from, unsigned from_len);
+int RSA_padding_add_PKCS1_OAEP_mgf1(uint8_t *to, unsigned to_len,
+ const uint8_t *from, unsigned from_len,
+ const uint8_t *param, unsigned plen,
+ const EVP_MD *md, const EVP_MD *mgf1md);
+int RSA_padding_check_PKCS1_OAEP_mgf1(uint8_t *to, unsigned to_len,
+ const uint8_t *from, unsigned from_len,
+ const uint8_t *param, unsigned plen,
+ const EVP_MD *md, const EVP_MD *mgf1md);
+int RSA_padding_add_none(uint8_t *to, unsigned to_len, const uint8_t *from,
+ unsigned from_len);
+int RSA_padding_check_none(uint8_t *to, unsigned to_len, const uint8_t *from,
+ unsigned from_len);
+
+/* RSA_verify_PKCS1_PSS_mgf1 */
+int RSA_verify_PKCS1_PSS_mgf1(RSA *rsa, const uint8_t *mHash,
+ const EVP_MD *Hash, const EVP_MD *mgf1Hash,
+ const uint8_t *EM, int sLen);
+
+int RSA_padding_add_PKCS1_PSS_mgf1(RSA *rsa, uint8_t *EM, const uint8_t *mHash,
+ const EVP_MD *Hash, const EVP_MD *mgf1Hash,
+ int sLen);
+
+/* RSA_private_transform calls either the method-specific |private_transform|
+ * function (if given) or the generic one. See the comment for
+ * |private_transform| in |rsa_meth_st|. */
+int RSA_private_transform(RSA *rsa, uint8_t *out, const uint8_t *in,
+ size_t len);
+
+typedef struct rsa_pss_params_st {
+ X509_ALGOR *hashAlgorithm;
+ X509_ALGOR *maskGenAlgorithm;
+ ASN1_INTEGER *saltLength;
+ ASN1_INTEGER *trailerField;
+} RSA_PSS_PARAMS;
+
+DECLARE_ASN1_FUNCTIONS(RSA_PSS_PARAMS)
+
+typedef struct rsa_oaep_params_st {
+ X509_ALGOR *hashFunc;
+ X509_ALGOR *maskGenFunc;
+ X509_ALGOR *pSourceFunc;
+} RSA_OAEP_PARAMS;
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_RSA_INTERNAL_H */
diff --git a/src/crypto/rsa/padding.c b/src/crypto/rsa/padding.c
new file mode 100644
index 0000000..66fdf13
--- /dev/null
+++ b/src/crypto/rsa/padding.c
@@ -0,0 +1,779 @@
+/* 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 <openssl/rsa.h>
+
+#include <assert.h>
+#include <string.h>
+
+#include <openssl/digest.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/rand.h>
+#include <openssl/sha.h>
+
+#include "internal.h"
+
+/* TODO(fork): don't the check functions have to be constant time? */
+
+int RSA_padding_add_PKCS1_type_1(uint8_t *to, unsigned tlen,
+ const uint8_t *from, unsigned flen) {
+ unsigned j;
+ uint8_t *p;
+
+ if (tlen < RSA_PKCS1_PADDING_SIZE) {
+ OPENSSL_PUT_ERROR(RSA, RSA_padding_add_PKCS1_type_1,
+ RSA_R_KEY_SIZE_TOO_SMALL);
+ return 0;
+ }
+
+ if (flen > tlen - RSA_PKCS1_PADDING_SIZE) {
+ OPENSSL_PUT_ERROR(RSA, RSA_padding_add_PKCS1_type_1,
+ RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
+ return 0;
+ }
+
+ p = (uint8_t *)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, (unsigned int)flen);
+ return 1;
+}
+
+int RSA_padding_check_PKCS1_type_1(uint8_t *to, unsigned tlen,
+ const uint8_t *from, unsigned flen) {
+ unsigned i, j;
+ const uint8_t *p;
+
+ if (flen < 2) {
+ OPENSSL_PUT_ERROR(RSA, RSA_padding_check_PKCS1_type_1,
+ RSA_R_DATA_TOO_SMALL);
+ return -1;
+ }
+
+ p = from;
+ if ((*(p++) != 0) || (*(p++) != 1)) {
+ OPENSSL_PUT_ERROR(RSA, RSA_padding_check_PKCS1_type_1,
+ RSA_R_BLOCK_TYPE_IS_NOT_01);
+ return -1;
+ }
+
+ /* scan over padding data */
+ j = flen - 2; /* one for leading 00, one for type. */
+ for (i = 0; i < j; i++) {
+ /* should decrypt to 0xff */
+ if (*p != 0xff) {
+ if (*p == 0) {
+ p++;
+ break;
+ } else {
+ OPENSSL_PUT_ERROR(RSA, RSA_padding_check_PKCS1_type_1,
+ RSA_R_BAD_FIXED_HEADER_DECRYPT);
+ return -1;
+ }
+ }
+ p++;
+ }
+
+ if (i == j) {
+ OPENSSL_PUT_ERROR(RSA, RSA_padding_check_PKCS1_type_1,
+ RSA_R_NULL_BEFORE_BLOCK_MISSING);
+ return -1;
+ }
+
+ if (i < 8) {
+ OPENSSL_PUT_ERROR(RSA, RSA_padding_check_PKCS1_type_1,
+ RSA_R_BAD_PAD_BYTE_COUNT);
+ return -1;
+ }
+ i++; /* Skip over the '\0' */
+ j -= i;
+ if (j > tlen) {
+ OPENSSL_PUT_ERROR(RSA, RSA_padding_check_PKCS1_type_1,
+ RSA_R_DATA_TOO_LARGE);
+ return -1;
+ }
+ memcpy(to, p, j);
+
+ return j;
+}
+
+int RSA_padding_add_PKCS1_type_2(uint8_t *to, unsigned tlen,
+ const uint8_t *from, unsigned flen) {
+ unsigned i, j;
+ uint8_t *p;
+
+ if (tlen < RSA_PKCS1_PADDING_SIZE) {
+ OPENSSL_PUT_ERROR(RSA, RSA_padding_add_PKCS1_type_2,
+ RSA_R_KEY_SIZE_TOO_SMALL);
+ return 0;
+ }
+
+ if (flen > tlen - RSA_PKCS1_PADDING_SIZE) {
+ OPENSSL_PUT_ERROR(RSA, RSA_padding_add_PKCS1_type_2,
+ 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;
+
+ if (!RAND_bytes(p, j)) {
+ return 0;
+ }
+
+ for (i = 0; i < j; i++) {
+ while (*p == 0) {
+ if (!RAND_bytes(p, 1)) {
+ return 0;
+ }
+ }
+ p++;
+ }
+
+ *(p++) = 0;
+
+ memcpy(p, from, (unsigned int)flen);
+ return 1;
+}
+
+/* constant_time_byte_eq returns 1 if |x| == |y| and 0 otherwise. */
+static int constant_time_byte_eq(unsigned char a, unsigned char b) {
+ unsigned char z = ~(a ^ b);
+ z &= z >> 4;
+ z &= z >> 2;
+ z &= z >> 1;
+
+ return z;
+}
+
+/* constant_time_select returns |x| if |v| is 1 and |y| if |v| is 0.
+ * Its behavior is undefined if |v| takes any other value. */
+static int constant_time_select(int v, int x, int y) {
+ return ((~(v - 1)) & x) | ((v - 1) & y);
+}
+
+/* constant_time_le returns 1 if |x| <= |y| and 0 otherwise.
+ * |x| and |y| must be positive. */
+static int constant_time_le(int x, int y) {
+ return ((x - y - 1) >> (sizeof(int) * 8 - 1)) & 1;
+}
+
+int RSA_message_index_PKCS1_type_2(const uint8_t *from, size_t from_len,
+ size_t *out_index) {
+ size_t i;
+ int first_byte_is_zero, second_byte_is_two, looking_for_index;
+ int valid_index, zero_index = 0;
+
+ /* PKCS#1 v1.5 decryption. See "PKCS #1 v2.2: RSA Cryptography
+ * Standard", section 7.2.2. */
+ if (from_len < RSA_PKCS1_PADDING_SIZE) {
+ /* |from| is zero-padded to the size of the RSA modulus, a public value, so
+ * this can be rejected in non-constant time. */
+ *out_index = 0;
+ return 0;
+ }
+
+ first_byte_is_zero = constant_time_byte_eq(from[0], 0);
+ second_byte_is_two = constant_time_byte_eq(from[1], 2);
+
+ looking_for_index = 1;
+ for (i = 2; i < from_len; i++) {
+ int equals0 = constant_time_byte_eq(from[i], 0);
+ zero_index =
+ constant_time_select(looking_for_index & equals0, i, zero_index);
+ looking_for_index = constant_time_select(equals0, 0, looking_for_index);
+ }
+
+ /* The input must begin with 00 02. */
+ valid_index = first_byte_is_zero;
+ valid_index &= second_byte_is_two;
+
+ /* We must have found the end of PS. */
+ valid_index &= ~looking_for_index;
+
+ /* PS must be at least 8 bytes long, and it starts two bytes into |from|. */
+ valid_index &= constant_time_le(2 + 8, zero_index);
+
+ /* Skip the zero byte. */
+ zero_index++;
+
+ *out_index = constant_time_select(valid_index, zero_index, 0);
+ return valid_index;
+}
+
+int RSA_padding_check_PKCS1_type_2(uint8_t *to, unsigned tlen,
+ const uint8_t *from, unsigned flen) {
+ size_t msg_index, msg_len;
+
+ if (flen == 0) {
+ OPENSSL_PUT_ERROR(RSA, RSA_padding_check_PKCS1_type_2,
+ RSA_R_EMPTY_PUBLIC_KEY);
+ return -1;
+ }
+
+ /* NOTE: Although |RSA_message_index_PKCS1_type_2| itself is constant time,
+ * the API contracts of this function and |RSA_decrypt| with
+ * |RSA_PKCS1_PADDING| make it impossible to completely avoid Bleichenbacher's
+ * attack. */
+ if (!RSA_message_index_PKCS1_type_2(from, flen, &msg_index)) {
+ OPENSSL_PUT_ERROR(RSA, RSA_padding_check_PKCS1_type_2,
+ RSA_R_PKCS_DECODING_ERROR);
+ return -1;
+ }
+
+ msg_len = flen - msg_index;
+ if (msg_len > tlen) {
+ /* This shouldn't happen because this function is always called with |tlen|
+ * the key size and |flen| is bounded by the key size. */
+ OPENSSL_PUT_ERROR(RSA, RSA_padding_check_PKCS1_type_2,
+ RSA_R_PKCS_DECODING_ERROR);
+ return -1;
+ }
+ memcpy(to, &from[msg_index], msg_len);
+ return msg_len;
+}
+
+int RSA_padding_add_none(uint8_t *to, unsigned tlen, const uint8_t *from, unsigned flen) {
+ if (flen > tlen) {
+ OPENSSL_PUT_ERROR(RSA, RSA_padding_add_none,
+ RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
+ return 0;
+ }
+
+ if (flen < tlen) {
+ OPENSSL_PUT_ERROR(RSA, RSA_padding_add_none,
+ RSA_R_DATA_TOO_SMALL_FOR_KEY_SIZE);
+ return 0;
+ }
+
+ memcpy(to, from, (unsigned int)flen);
+ return 1;
+}
+
+int RSA_padding_check_none(uint8_t *to, unsigned tlen, const uint8_t *from,
+ unsigned flen) {
+ if (flen > tlen) {
+ OPENSSL_PUT_ERROR(RSA, RSA_padding_check_none, RSA_R_DATA_TOO_LARGE);
+ return -1;
+ }
+
+ memcpy(to, from, flen);
+ return flen;
+}
+
+int PKCS1_MGF1(uint8_t *mask, unsigned len, const uint8_t *seed,
+ unsigned seedlen, const EVP_MD *dgst) {
+ unsigned outlen = 0;
+ uint32_t i;
+ uint8_t cnt[4];
+ EVP_MD_CTX c;
+ uint8_t md[EVP_MAX_MD_SIZE];
+ unsigned mdlen;
+ int ret = -1;
+
+ EVP_MD_CTX_init(&c);
+ mdlen = EVP_MD_size(dgst);
+
+ for (i = 0; outlen < len; i++) {
+ cnt[0] = (uint8_t)((i >> 24) & 255);
+ cnt[1] = (uint8_t)((i >> 16) & 255);
+ cnt[2] = (uint8_t)((i >> 8)) & 255;
+ cnt[3] = (uint8_t)(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;
+ }
+ }
+ ret = 0;
+
+err:
+ EVP_MD_CTX_cleanup(&c);
+ return ret;
+}
+
+int RSA_padding_add_PKCS1_OAEP_mgf1(uint8_t *to, unsigned tlen,
+ const uint8_t *from, unsigned flen,
+ const uint8_t *param, unsigned plen,
+ const EVP_MD *md, const EVP_MD *mgf1md) {
+ unsigned i, emlen, mdlen;
+ uint8_t *db, *seed;
+ uint8_t *dbmask = NULL, seedmask[EVP_MAX_MD_SIZE];
+ int ret = 0;
+
+ if (md == NULL) {
+ md = EVP_sha1();
+ }
+ if (mgf1md == NULL) {
+ mgf1md = md;
+ }
+
+ mdlen = EVP_MD_size(md);
+
+ if (tlen < 2 * mdlen + 2) {
+ OPENSSL_PUT_ERROR(RSA, RSA_padding_add_PKCS1_OAEP_mgf1,
+ RSA_R_KEY_SIZE_TOO_SMALL);
+ return 0;
+ }
+
+ emlen = tlen - 1;
+ if (flen > emlen - 2 * mdlen - 1) {
+ OPENSSL_PUT_ERROR(RSA, RSA_padding_add_PKCS1_OAEP_mgf1,
+ RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
+ return 0;
+ }
+
+ if (emlen < 2 * mdlen + 1) {
+ OPENSSL_PUT_ERROR(RSA, RSA_padding_add_PKCS1_OAEP_mgf1,
+ RSA_R_KEY_SIZE_TOO_SMALL);
+ return 0;
+ }
+
+ to[0] = 0;
+ seed = to + 1;
+ db = to + mdlen + 1;
+
+ if (!EVP_Digest((void *)param, plen, db, NULL, md, NULL)) {
+ return 0;
+ }
+ memset(db + mdlen, 0, emlen - flen - 2 * mdlen - 1);
+ db[emlen - flen - mdlen - 1] = 0x01;
+ memcpy(db + emlen - flen - mdlen, from, flen);
+ if (!RAND_bytes(seed, mdlen)) {
+ return 0;
+ }
+
+ dbmask = OPENSSL_malloc(emlen - mdlen);
+ if (dbmask == NULL) {
+ OPENSSL_PUT_ERROR(RSA, RSA_padding_add_PKCS1_OAEP_mgf1,
+ ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ if (PKCS1_MGF1(dbmask, emlen - mdlen, seed, mdlen, mgf1md) < 0) {
+ goto out;
+ }
+ for (i = 0; i < emlen - mdlen; i++) {
+ db[i] ^= dbmask[i];
+ }
+
+ if (PKCS1_MGF1(seedmask, mdlen, db, emlen - mdlen, mgf1md) < 0) {
+ goto out;
+ }
+ for (i = 0; i < mdlen; i++) {
+ seed[i] ^= seedmask[i];
+ }
+ ret = 1;
+
+out:
+ if (dbmask != NULL) {
+ OPENSSL_free(dbmask);
+ }
+ return ret;
+}
+
+int RSA_padding_check_PKCS1_OAEP_mgf1(uint8_t *to, unsigned tlen,
+ const uint8_t *from, unsigned flen,
+ const uint8_t *param, unsigned plen,
+ const EVP_MD *md, const EVP_MD *mgf1md) {
+ unsigned i, dblen, mlen = -1, mdlen;
+ const uint8_t *maskeddb, *maskedseed;
+ uint8_t *db = NULL, seed[EVP_MAX_MD_SIZE], phash[EVP_MAX_MD_SIZE];
+ int bad, looking_for_one_byte, one_index = 0;
+
+ if (md == NULL) {
+ md = EVP_sha1();
+ }
+ if (mgf1md == NULL) {
+ mgf1md = md;
+ }
+
+ mdlen = EVP_MD_size(md);
+
+ /* The encoded message is one byte smaller than the modulus to ensure that it
+ * doesn't end up greater than the modulus. Thus there's an extra "+1" here
+ * compared to https://tools.ietf.org/html/rfc2437#section-9.1.1.2. */
+ if (flen < 1 + 2*mdlen + 1) {
+ /* 'flen' is the length of the modulus, i.e. does not depend on the
+ * particular ciphertext. */
+ goto decoding_err;
+ }
+
+ dblen = flen - mdlen - 1;
+ db = OPENSSL_malloc(dblen);
+ if (db == NULL) {
+ OPENSSL_PUT_ERROR(RSA, RSA_padding_check_PKCS1_OAEP_mgf1,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ maskedseed = from + 1;
+ maskeddb = from + 1 + mdlen;
+
+ if (PKCS1_MGF1(seed, mdlen, maskeddb, dblen, mgf1md)) {
+ goto err;
+ }
+ for (i = 0; i < mdlen; i++) {
+ seed[i] ^= maskedseed[i];
+ }
+
+ if (PKCS1_MGF1(db, dblen, seed, mdlen, mgf1md)) {
+ goto err;
+ }
+ for (i = 0; i < dblen; i++) {
+ db[i] ^= maskeddb[i];
+ }
+
+ if (!EVP_Digest((void *)param, plen, phash, NULL, md, NULL)) {
+ goto err;
+ }
+
+ bad = CRYPTO_memcmp(db, phash, mdlen);
+ bad |= from[0];
+
+ looking_for_one_byte = 1;
+ for (i = mdlen; i < dblen; i++) {
+ int equals1 = constant_time_byte_eq(db[i], 1);
+ int equals0 = constant_time_byte_eq(db[i], 0);
+ one_index =
+ constant_time_select(looking_for_one_byte & equals1, i, one_index);
+ looking_for_one_byte =
+ constant_time_select(equals1, 0, looking_for_one_byte);
+ bad |= looking_for_one_byte & ~equals0;
+ }
+
+ bad |= looking_for_one_byte;
+
+ if (bad) {
+ goto decoding_err;
+ }
+
+ one_index++;
+ mlen = dblen - one_index;
+ if (tlen < mlen) {
+ OPENSSL_PUT_ERROR(RSA, RSA_padding_check_PKCS1_OAEP_mgf1,
+ RSA_R_DATA_TOO_LARGE);
+ mlen = -1;
+ } else {
+ memcpy(to, db + one_index, mlen);
+ }
+
+ OPENSSL_free(db);
+ return mlen;
+
+decoding_err:
+ /* to avoid chosen ciphertext attacks, the error message should not reveal
+ * which kind of decoding error happened */
+ OPENSSL_PUT_ERROR(RSA, RSA_padding_check_PKCS1_OAEP_mgf1,
+ RSA_R_OAEP_DECODING_ERROR);
+ err:
+ if (db != NULL) {
+ OPENSSL_free(db);
+ }
+ return -1;
+}
+
+static const unsigned char zeroes[] = {0,0,0,0,0,0,0,0};
+
+int RSA_verify_PKCS1_PSS_mgf1(RSA *rsa, const uint8_t *mHash,
+ const EVP_MD *Hash, const EVP_MD *mgf1Hash,
+ const uint8_t *EM, int sLen) {
+ int i;
+ int ret = 0;
+ int maskedDBLen, MSBits, emLen;
+ size_t hLen;
+ const uint8_t *H;
+ uint8_t *DB = NULL;
+ EVP_MD_CTX ctx;
+ uint8_t H_[EVP_MAX_MD_SIZE];
+ EVP_MD_CTX_init(&ctx);
+
+ if (mgf1Hash == NULL) {
+ mgf1Hash = Hash;
+ }
+
+ hLen = EVP_MD_size(Hash);
+
+ /* 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) {
+ OPENSSL_PUT_ERROR(RSA, RSA_verify_PKCS1_PSS_mgf1, RSA_R_SLEN_CHECK_FAILED);
+ goto err;
+ }
+
+ MSBits = (BN_num_bits(rsa->n) - 1) & 0x7;
+ emLen = RSA_size(rsa);
+ if (EM[0] & (0xFF << MSBits)) {
+ OPENSSL_PUT_ERROR(RSA, RSA_verify_PKCS1_PSS_mgf1,
+ RSA_R_FIRST_OCTET_INVALID);
+ goto err;
+ }
+ if (MSBits == 0) {
+ EM++;
+ emLen--;
+ }
+ if (emLen < ((int)hLen + sLen + 2)) {
+ /* sLen can be small negative */
+ OPENSSL_PUT_ERROR(RSA, RSA_verify_PKCS1_PSS_mgf1, RSA_R_DATA_TOO_LARGE);
+ goto err;
+ }
+ if (EM[emLen - 1] != 0xbc) {
+ OPENSSL_PUT_ERROR(RSA, RSA_verify_PKCS1_PSS_mgf1, RSA_R_LAST_OCTET_INVALID);
+ goto err;
+ }
+ maskedDBLen = emLen - hLen - 1;
+ H = EM + maskedDBLen;
+ DB = OPENSSL_malloc(maskedDBLen);
+ if (!DB) {
+ OPENSSL_PUT_ERROR(RSA, RSA_verify_PKCS1_PSS_mgf1, 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) {
+ OPENSSL_PUT_ERROR(RSA, RSA_verify_PKCS1_PSS_mgf1,
+ RSA_R_SLEN_RECOVERY_FAILED);
+ goto err;
+ }
+ if (sLen >= 0 && (maskedDBLen - i) != sLen) {
+ OPENSSL_PUT_ERROR(RSA, RSA_verify_PKCS1_PSS_mgf1, 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 (memcmp(H_, H, hLen)) {
+ OPENSSL_PUT_ERROR(RSA, RSA_verify_PKCS1_PSS_mgf1, RSA_R_BAD_SIGNATURE);
+ ret = 0;
+ } else {
+ ret = 1;
+ }
+
+err:
+ if (DB) {
+ OPENSSL_free(DB);
+ }
+ EVP_MD_CTX_cleanup(&ctx);
+
+ return ret;
+}
+
+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;
+ size_t maskedDBLen, MSBits, emLen;
+ size_t hLen;
+ unsigned char *H, *salt = NULL, *p;
+ EVP_MD_CTX ctx;
+
+ if (mgf1Hash == NULL) {
+ mgf1Hash = Hash;
+ }
+
+ hLen = EVP_MD_size(Hash);
+
+ /* 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) {
+ OPENSSL_PUT_ERROR(RSA, RSA_padding_add_PKCS1_PSS_mgf1,
+ RSA_R_SLEN_CHECK_FAILED);
+ goto err;
+ }
+
+ if (BN_is_zero(rsa->n)) {
+ OPENSSL_PUT_ERROR(RSA, RSA_padding_add_PKCS1_PSS_mgf1,
+ RSA_R_EMPTY_PUBLIC_KEY);
+ goto err;
+ }
+
+ MSBits = (BN_num_bits(rsa->n) - 1) & 0x7;
+ emLen = RSA_size(rsa);
+ if (MSBits == 0) {
+ assert(emLen >= 1);
+ *EM++ = 0;
+ emLen--;
+ }
+ if (sLen == -2) {
+ if (emLen < hLen + 2) {
+ OPENSSL_PUT_ERROR(RSA, RSA_padding_add_PKCS1_PSS_mgf1,
+ RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
+ goto err;
+ }
+ sLen = emLen - hLen - 2;
+ } else if (emLen < hLen + sLen + 2) {
+ OPENSSL_PUT_ERROR(RSA, RSA_padding_add_PKCS1_PSS_mgf1,
+ RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
+ goto err;
+ }
+ if (sLen > 0) {
+ salt = OPENSSL_malloc(sLen);
+ if (!salt) {
+ OPENSSL_PUT_ERROR(RSA, RSA_padding_add_PKCS1_PSS_mgf1,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ if (!RAND_bytes(salt, sLen)) {
+ goto err;
+ }
+ }
+ maskedDBLen = emLen - hLen - 1;
+ H = EM + maskedDBLen;
+ EVP_MD_CTX_init(&ctx);
+ 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;
+ }
+ EVP_MD_CTX_cleanup(&ctx);
+
+ /* 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:
+ if (salt) {
+ OPENSSL_free(salt);
+ }
+
+ return ret;
+}
diff --git a/src/crypto/rsa/rsa.c b/src/crypto/rsa/rsa.c
new file mode 100644
index 0000000..cfdd7ff
--- /dev/null
+++ b/src/crypto/rsa/rsa.c
@@ -0,0 +1,761 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/rsa.h>
+
+#include <string.h>
+
+#include <openssl/bn.h>
+#include <openssl/engine.h>
+#include <openssl/err.h>
+#include <openssl/ex_data.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+
+#include "internal.h"
+
+
+extern const RSA_METHOD RSA_default_method;
+
+RSA *RSA_new(void) { return RSA_new_method(NULL); }
+
+RSA *RSA_new_method(const ENGINE *engine) {
+ RSA *rsa = (RSA *)OPENSSL_malloc(sizeof(RSA));
+ if (rsa == NULL) {
+ OPENSSL_PUT_ERROR(RSA, RSA_new_method, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ memset(rsa, 0, sizeof(RSA));
+
+ if (engine) {
+ rsa->meth = ENGINE_get_RSA_method(engine);
+ }
+
+ if (rsa->meth == NULL) {
+ rsa->meth = (RSA_METHOD*) &RSA_default_method;
+ }
+ METHOD_ref(rsa->meth);
+
+ rsa->references = 1;
+ rsa->flags = rsa->meth->flags;
+
+ if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_RSA, rsa, &rsa->ex_data)) {
+ METHOD_unref(rsa->meth);
+ OPENSSL_free(rsa);
+ return NULL;
+ }
+
+ if (rsa->meth->init && !rsa->meth->init(rsa)) {
+ CRYPTO_free_ex_data(CRYPTO_EX_INDEX_RSA, rsa, &rsa->ex_data);
+ METHOD_unref(rsa->meth);
+ OPENSSL_free(rsa);
+ return NULL;
+ }
+
+ return rsa;
+}
+
+void RSA_free(RSA *rsa) {
+ unsigned u;
+
+ if (rsa == NULL) {
+ return;
+ }
+
+ if (CRYPTO_add(&rsa->references, -1, CRYPTO_LOCK_RSA) > 0) {
+ return;
+ }
+
+ if (rsa->meth->finish) {
+ rsa->meth->finish(rsa);
+ }
+ METHOD_unref(rsa->meth);
+
+ CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DSA, rsa, &rsa->ex_data);
+
+ if (rsa->n != NULL)
+ BN_clear_free(rsa->n);
+ if (rsa->e != NULL)
+ BN_clear_free(rsa->e);
+ if (rsa->d != NULL)
+ BN_clear_free(rsa->d);
+ if (rsa->p != NULL)
+ BN_clear_free(rsa->p);
+ if (rsa->q != NULL)
+ BN_clear_free(rsa->q);
+ if (rsa->dmp1 != NULL)
+ BN_clear_free(rsa->dmp1);
+ if (rsa->dmq1 != NULL)
+ BN_clear_free(rsa->dmq1);
+ if (rsa->iqmp != NULL)
+ BN_clear_free(rsa->iqmp);
+ for (u = 0; u < rsa->num_blindings; u++) {
+ BN_BLINDING_free(rsa->blindings[u]);
+ }
+ if (rsa->blindings != NULL)
+ OPENSSL_free(rsa->blindings);
+ if (rsa->blindings_inuse != NULL)
+ OPENSSL_free(rsa->blindings_inuse);
+ OPENSSL_free(rsa);
+}
+
+int RSA_up_ref(RSA *rsa) {
+ CRYPTO_add(&rsa->references, 1, CRYPTO_LOCK_RSA);
+ return 1;
+}
+
+int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb) {
+ if (rsa->meth->keygen) {
+ return rsa->meth->keygen(rsa, bits, e_value, cb);
+ }
+
+ return RSA_default_method.keygen(rsa, bits, e_value, cb);
+}
+
+int RSA_encrypt(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
+ const uint8_t *in, size_t in_len, int padding) {
+ if (rsa->meth->encrypt) {
+ return rsa->meth->encrypt(rsa, out_len, out, max_out, in, in_len, padding);
+ }
+
+ return RSA_default_method.encrypt(rsa, out_len, out, max_out, in, in_len,
+ padding);
+}
+
+int RSA_public_encrypt(int flen, const uint8_t *from, uint8_t *to, RSA *rsa,
+ int padding) {
+ size_t out_len;
+
+ if (!RSA_encrypt(rsa, &out_len, to, RSA_size(rsa), from, flen, padding)) {
+ return -1;
+ }
+
+ return out_len;
+}
+
+int RSA_sign_raw(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
+ const uint8_t *in, size_t in_len, int padding) {
+ if (rsa->meth->sign_raw) {
+ return rsa->meth->sign_raw(rsa, out_len, out, max_out, in, in_len, padding);
+ }
+
+ return RSA_default_method.sign_raw(rsa, out_len, out, max_out, in, in_len,
+ padding);
+}
+
+int RSA_private_encrypt(int flen, const uint8_t *from, uint8_t *to, RSA *rsa,
+ int padding) {
+ size_t out_len;
+
+ if (!RSA_sign_raw(rsa, &out_len, to, RSA_size(rsa), from, flen, padding)) {
+ return -1;
+ }
+
+ return out_len;
+}
+
+int RSA_decrypt(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
+ const uint8_t *in, size_t in_len, int padding) {
+ if (rsa->meth->decrypt) {
+ return rsa->meth->decrypt(rsa, out_len, out, max_out, in, in_len, padding);
+ }
+
+ return RSA_default_method.decrypt(rsa, out_len, out, max_out, in, in_len,
+ padding);
+}
+
+int RSA_private_decrypt(int flen, const uint8_t *from, uint8_t *to, RSA *rsa,
+ int padding) {
+ size_t out_len;
+
+ if (!RSA_decrypt(rsa, &out_len, to, RSA_size(rsa), from, flen, padding)) {
+ return -1;
+ }
+
+ return out_len;
+}
+
+int RSA_verify_raw(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
+ const uint8_t *in, size_t in_len, int padding) {
+ if (rsa->meth->verify_raw) {
+ return rsa->meth->verify_raw(rsa, out_len, out, max_out, in, in_len, padding);
+ }
+
+ return RSA_default_method.verify_raw(rsa, out_len, out, max_out, in, in_len,
+ padding);
+}
+
+int RSA_public_decrypt(int flen, const uint8_t *from, uint8_t *to, RSA *rsa,
+ int padding) {
+ size_t out_len;
+
+ if (!RSA_verify_raw(rsa, &out_len, to, RSA_size(rsa), from, flen, padding)) {
+ return -1;
+ }
+
+ return out_len;
+}
+
+unsigned RSA_size(const RSA *rsa) {
+ if (rsa->meth->size) {
+ return rsa->meth->size(rsa);
+ }
+
+ return RSA_default_method.size(rsa);
+}
+
+int RSA_is_opaque(const RSA *rsa) {
+ return rsa->meth && (rsa->meth->flags & RSA_FLAG_OPAQUE);
+}
+
+int RSA_supports_digest(const RSA *rsa, const EVP_MD *md) {
+ if (rsa->meth && rsa->meth->supports_digest) {
+ return rsa->meth->supports_digest(rsa, md);
+ }
+ return 1;
+}
+
+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);
+}
+
+int RSA_set_ex_data(RSA *d, int idx, void *arg) {
+ return CRYPTO_set_ex_data(&d->ex_data, idx, arg);
+}
+
+void *RSA_get_ex_data(const RSA *d, int idx) {
+ return CRYPTO_get_ex_data(&d->ex_data, idx);
+}
+
+/* SSL_SIG_LENGTH is the size of an SSL/TLS (prior to TLS 1.2) signature: it's
+ * the length of an MD5 and SHA1 hash. */
+static const unsigned SSL_SIG_LENGTH = 36;
+
+/* pkcs1_sig_prefix contains the ASN.1, DER encoded prefix for a hash that is
+ * to be signed with PKCS#1. */
+struct pkcs1_sig_prefix {
+ /* nid identifies the hash function. */
+ int nid;
+ /* len is the number of bytes of |bytes| which are valid. */
+ uint8_t len;
+ /* bytes contains the DER bytes. */
+ uint8_t bytes[19];
+};
+
+/* kPKCS1SigPrefixes contains the ASN.1 prefixes for PKCS#1 signatures with
+ * different hash functions. */
+static const struct pkcs1_sig_prefix kPKCS1SigPrefixes[] = {
+ {
+ NID_md5,
+ 18,
+ {0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x02, 0x05, 0x05, 0x00, 0x04, 0x10},
+ },
+ {
+ NID_sha1,
+ 15,
+ {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05,
+ 0x00, 0x04, 0x14},
+ },
+ {
+ NID_sha224,
+ 19,
+ {0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
+ 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1c},
+ },
+ {
+ NID_sha256,
+ 19,
+ {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
+ 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20},
+ },
+ {
+ NID_sha384,
+ 19,
+ {0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
+ 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30},
+ },
+ {
+ NID_sha512,
+ 19,
+ {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
+ 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40},
+ },
+ {
+ NID_ripemd160,
+ 14,
+ {0x30, 0x20, 0x30, 0x08, 0x06, 0x06, 0x28, 0xcf, 0x06, 0x03, 0x00, 0x31,
+ 0x04, 0x14},
+ },
+ {
+ NID_undef, 0, {0},
+ },
+};
+
+/* TODO(fork): mostly new code, needs careful review. */
+
+/* pkcs1_prefixed_msg builds a PKCS#1, prefixed version of |msg| for the given
+ * hash function and sets |out_msg| to point to it. On successful return,
+ * |*out_msg| may be allocated memory and, if so, |*is_alloced| will be 1. */
+static int pkcs1_prefixed_msg(uint8_t **out_msg, size_t *out_msg_len,
+ int *is_alloced, int hash_nid, const uint8_t *msg,
+ size_t msg_len) {
+ unsigned i;
+ const uint8_t* prefix = NULL;
+ unsigned prefix_len;
+ uint8_t *signed_msg;
+ unsigned signed_msg_len;
+
+ if (hash_nid == NID_md5_sha1) {
+ /* Special case: SSL signature, just check the length. */
+ if (msg_len != SSL_SIG_LENGTH) {
+ OPENSSL_PUT_ERROR(RSA, RSA_sign, RSA_R_INVALID_MESSAGE_LENGTH);
+ return 0;
+ }
+
+ *out_msg = (uint8_t*) msg;
+ *out_msg_len = SSL_SIG_LENGTH;
+ *is_alloced = 0;
+ return 1;
+ }
+
+ for (i = 0; kPKCS1SigPrefixes[i].nid != NID_undef; i++) {
+ const struct pkcs1_sig_prefix *sig_prefix = &kPKCS1SigPrefixes[i];
+ if (sig_prefix->nid == hash_nid) {
+ prefix = sig_prefix->bytes;
+ prefix_len = sig_prefix->len;
+ break;
+ }
+ }
+
+ if (prefix == NULL) {
+ OPENSSL_PUT_ERROR(RSA, RSA_sign, RSA_R_UNKNOWN_ALGORITHM_TYPE);
+ return 0;
+ }
+
+ signed_msg_len = prefix_len + msg_len;
+ if (signed_msg_len < prefix_len) {
+ OPENSSL_PUT_ERROR(RSA, RSA_sign, RSA_R_TOO_LONG);
+ return 0;
+ }
+
+ signed_msg = OPENSSL_malloc(signed_msg_len);
+ if (!signed_msg) {
+ OPENSSL_PUT_ERROR(RSA, RSA_sign, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ memcpy(signed_msg, prefix, prefix_len);
+ memcpy(signed_msg + prefix_len, msg, msg_len);
+
+ *out_msg = signed_msg;
+ *out_msg_len = signed_msg_len;
+ *is_alloced = 1;
+
+ return 1;
+}
+
+int RSA_sign(int hash_nid, const uint8_t *in, unsigned in_len, uint8_t *out,
+ unsigned *out_len, RSA *rsa) {
+ const unsigned rsa_size = RSA_size(rsa);
+ int ret = 0;
+ uint8_t *signed_msg;
+ size_t signed_msg_len;
+ int signed_msg_is_alloced = 0;
+ size_t size_t_out_len;
+
+ if (rsa->meth->sign) {
+ return rsa->meth->sign(hash_nid, in, in_len, out, out_len, rsa);
+ }
+
+ if (!pkcs1_prefixed_msg(&signed_msg, &signed_msg_len, &signed_msg_is_alloced,
+ hash_nid, in, in_len)) {
+ return 0;
+ }
+
+ if (rsa_size < RSA_PKCS1_PADDING_SIZE ||
+ signed_msg_len > rsa_size - RSA_PKCS1_PADDING_SIZE) {
+ OPENSSL_PUT_ERROR(RSA, RSA_sign, RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY);
+ goto finish;
+ }
+
+ if (RSA_sign_raw(rsa, &size_t_out_len, out, rsa_size, signed_msg,
+ signed_msg_len, RSA_PKCS1_PADDING)) {
+ *out_len = size_t_out_len;
+ ret = 1;
+ }
+
+finish:
+ if (signed_msg_is_alloced) {
+ OPENSSL_free(signed_msg);
+ }
+ return ret;
+}
+
+int RSA_verify(int hash_nid, const uint8_t *msg, size_t msg_len,
+ const uint8_t *sig, size_t sig_len, RSA *rsa) {
+ const size_t rsa_size = RSA_size(rsa);
+ uint8_t *buf = NULL;
+ int ret = 0;
+ uint8_t *signed_msg = NULL;
+ size_t signed_msg_len, len;
+ int signed_msg_is_alloced = 0;
+
+ if (rsa->meth->verify) {
+ return rsa->meth->verify(hash_nid, msg, msg_len, sig, sig_len, rsa);
+ }
+
+ if (sig_len != rsa_size) {
+ OPENSSL_PUT_ERROR(RSA, RSA_verify, RSA_R_WRONG_SIGNATURE_LENGTH);
+ return 0;
+ }
+
+ if (hash_nid == NID_md5_sha1 && msg_len != SSL_SIG_LENGTH) {
+ OPENSSL_PUT_ERROR(RSA, RSA_verify, RSA_R_INVALID_MESSAGE_LENGTH);
+ return 0;
+ }
+
+ buf = OPENSSL_malloc(rsa_size);
+ if (!buf) {
+ OPENSSL_PUT_ERROR(RSA, RSA_verify, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ if (!RSA_verify_raw(rsa, &len, buf, rsa_size, sig, sig_len,
+ RSA_PKCS1_PADDING)) {
+ goto out;
+ }
+
+ if (!pkcs1_prefixed_msg(&signed_msg, &signed_msg_len, &signed_msg_is_alloced,
+ hash_nid, msg, msg_len)) {
+ goto out;
+ }
+
+ if (len != signed_msg_len || CRYPTO_memcmp(buf, signed_msg, len) != 0) {
+ OPENSSL_PUT_ERROR(RSA, RSA_verify, RSA_R_BAD_SIGNATURE);
+ goto out;
+ }
+
+ ret = 1;
+
+out:
+ if (buf != NULL) {
+ OPENSSL_free(buf);
+ }
+ if (signed_msg_is_alloced) {
+ OPENSSL_free(signed_msg);
+ }
+ return ret;
+}
+
+static void bn_free_and_null(BIGNUM **bn) {
+ if (*bn == NULL) {
+ return;
+ }
+
+ BN_free(*bn);
+ *bn = NULL;
+}
+
+int RSA_check_key(const RSA *key) {
+ BIGNUM n, pm1, qm1, lcm, gcd, de, dmp1, dmq1, iqmp;
+ BN_CTX *ctx;
+ int ok = 0, has_crt_values;
+
+ if (RSA_is_opaque(key)) {
+ /* Opaque keys can't be checked. */
+ return 1;
+ }
+
+ if ((key->p != NULL) != (key->q != NULL)) {
+ OPENSSL_PUT_ERROR(RSA, RSA_check_key, RSA_R_ONLY_ONE_OF_P_Q_GIVEN);
+ return 0;
+ }
+
+ if (!key->n || !key->e) {
+ OPENSSL_PUT_ERROR(RSA, RSA_check_key, RSA_R_VALUE_MISSING);
+ return 0;
+ }
+
+ if (!key->d || !key->p) {
+ /* For a public key, or without p and q, there's nothing that can be
+ * checked. */
+ return 1;
+ }
+
+ ctx = BN_CTX_new();
+ if (ctx == NULL) {
+ OPENSSL_PUT_ERROR(RSA, RSA_check_key, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ BN_init(&n);
+ BN_init(&pm1);
+ BN_init(&qm1);
+ BN_init(&lcm);
+ BN_init(&gcd);
+ BN_init(&de);
+ BN_init(&dmp1);
+ BN_init(&dmq1);
+ BN_init(&iqmp);
+
+ if (/* n = pq */
+ !BN_mul(&n, key->p, key->q, ctx) ||
+ /* lcm = lcm(p-1, q-1) */
+ !BN_sub(&pm1, key->p, BN_value_one()) ||
+ !BN_sub(&qm1, key->q, BN_value_one()) ||
+ !BN_mul(&lcm, &pm1, &qm1, ctx) ||
+ !BN_gcd(&gcd, &pm1, &qm1, ctx) ||
+ !BN_div(&lcm, NULL, &lcm, &gcd, ctx) ||
+ /* de = d*e mod lcm(p-1, q-1) */
+ !BN_mod_mul(&de, key->d, key->e, &lcm, ctx)) {
+ OPENSSL_PUT_ERROR(RSA, RSA_check_key, ERR_LIB_BN);
+ goto out;
+ }
+
+ if (BN_cmp(&n, key->n) != 0) {
+ OPENSSL_PUT_ERROR(RSA, RSA_check_key, RSA_R_N_NOT_EQUAL_P_Q);
+ goto out;
+ }
+
+ if (!BN_is_one(&de)) {
+ OPENSSL_PUT_ERROR(RSA, RSA_check_key, RSA_R_D_E_NOT_CONGRUENT_TO_1);
+ goto out;
+ }
+
+ has_crt_values = key->dmp1 != NULL;
+ if (has_crt_values != (key->dmq1 != NULL) ||
+ has_crt_values != (key->iqmp != NULL)) {
+ OPENSSL_PUT_ERROR(RSA, RSA_check_key, RSA_R_INCONSISTENT_SET_OF_CRT_VALUES);
+ goto out;
+ }
+
+ if (has_crt_values) {
+ if (/* dmp1 = d mod (p-1) */
+ !BN_mod(&dmp1, key->d, &pm1, ctx) ||
+ /* dmq1 = d mod (q-1) */
+ !BN_mod(&dmq1, key->d, &qm1, ctx) ||
+ /* iqmp = q^-1 mod p */
+ !BN_mod_inverse(&iqmp, key->q, key->p, ctx)) {
+ OPENSSL_PUT_ERROR(RSA, RSA_check_key, ERR_LIB_BN);
+ goto out;
+ }
+
+ if (BN_cmp(&dmp1, key->dmp1) != 0 ||
+ BN_cmp(&dmq1, key->dmq1) != 0 ||
+ BN_cmp(&iqmp, key->iqmp) != 0) {
+ OPENSSL_PUT_ERROR(RSA, RSA_check_key, RSA_R_CRT_VALUES_INCORRECT);
+ goto out;
+ }
+ }
+
+ ok = 1;
+
+out:
+ BN_free(&n);
+ BN_free(&pm1);
+ BN_free(&qm1);
+ BN_free(&lcm);
+ BN_free(&gcd);
+ BN_free(&de);
+ BN_free(&dmp1);
+ BN_free(&dmq1);
+ BN_free(&iqmp);
+ BN_CTX_free(ctx);
+
+ return ok;
+}
+
+int RSA_recover_crt_params(RSA *rsa) {
+ BN_CTX *ctx;
+ BIGNUM *totient, *rem, *multiple, *p_plus_q, *p_minus_q;
+ int ok = 0;
+
+ if (rsa->n == NULL || rsa->e == NULL || rsa->d == NULL) {
+ OPENSSL_PUT_ERROR(RSA, RSA_recover_crt_params, RSA_R_EMPTY_PUBLIC_KEY);
+ return 0;
+ }
+
+ if (rsa->p || rsa->q || rsa->dmp1 || rsa->dmq1 || rsa->iqmp) {
+ OPENSSL_PUT_ERROR(RSA, RSA_recover_crt_params,
+ RSA_R_CRT_PARAMS_ALREADY_GIVEN);
+ return 0;
+ }
+
+ /* This uses the algorithm from section 9B of the RSA paper:
+ * http://people.csail.mit.edu/rivest/Rsapaper.pdf */
+
+ ctx = BN_CTX_new();
+ if (ctx == NULL) {
+ OPENSSL_PUT_ERROR(RSA, RSA_recover_crt_params, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ BN_CTX_start(ctx);
+ totient = BN_CTX_get(ctx);
+ rem = BN_CTX_get(ctx);
+ multiple = BN_CTX_get(ctx);
+ p_plus_q = BN_CTX_get(ctx);
+ p_minus_q = BN_CTX_get(ctx);
+
+ if (totient == NULL || rem == NULL || multiple == NULL || p_plus_q == NULL ||
+ p_minus_q == NULL) {
+ OPENSSL_PUT_ERROR(RSA, RSA_recover_crt_params, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ /* ed-1 is a small multiple of φ(n). */
+ if (!BN_mul(totient, rsa->e, rsa->d, ctx) ||
+ !BN_sub_word(totient, 1) ||
+ /* φ(n) =
+ * pq - p - q + 1 =
+ * n - (p + q) + 1
+ *
+ * Thus n is a reasonable estimate for φ(n). So, (ed-1)/n will be very
+ * close. But, when we calculate the quotient, we'll be truncating it
+ * because we discard the remainder. Thus (ed-1)/multiple will be >= n,
+ * which the totient cannot be. So we add one to the estimate.
+ *
+ * Consider ed-1 as:
+ *
+ * multiple * (n - (p+q) + 1) =
+ * multiple*n - multiple*(p+q) + multiple
+ *
+ * When we divide by n, the first term becomes multiple and, since
+ * multiple and p+q is tiny compared to n, the second and third terms can
+ * be ignored. Thus I claim that subtracting one from the estimate is
+ * sufficient. */
+ !BN_div(multiple, NULL, totient, rsa->n, ctx) ||
+ !BN_add_word(multiple, 1) ||
+ !BN_div(totient, rem, totient, multiple, ctx)) {
+ OPENSSL_PUT_ERROR(RSA, RSA_recover_crt_params, ERR_R_BN_LIB);
+ goto err;
+ }
+
+ if (!BN_is_zero(rem)) {
+ OPENSSL_PUT_ERROR(RSA, RSA_recover_crt_params, RSA_R_BAD_RSA_PARAMETERS);
+ goto err;
+ }
+
+ rsa->p = BN_new();
+ rsa->q = BN_new();
+ rsa->dmp1 = BN_new();
+ rsa->dmq1 = BN_new();
+ rsa->iqmp = BN_new();
+ if (rsa->p == NULL || rsa->q == NULL || rsa->dmp1 == NULL || rsa->dmq1 ==
+ NULL || rsa->iqmp == NULL) {
+ OPENSSL_PUT_ERROR(RSA, RSA_recover_crt_params, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ /* φ(n) = n - (p + q) + 1 =>
+ * n - totient + 1 = p + q */
+ if (!BN_sub(p_plus_q, rsa->n, totient) ||
+ !BN_add_word(p_plus_q, 1) ||
+ /* p - q = sqrt((p+q)^2 - 4n) */
+ !BN_sqr(rem, p_plus_q, ctx) ||
+ !BN_lshift(multiple, rsa->n, 2) ||
+ !BN_sub(rem, rem, multiple) ||
+ !BN_sqrt(p_minus_q, rem, ctx) ||
+ /* q is 1/2 (p+q)-(p-q) */
+ !BN_sub(rsa->q, p_plus_q, p_minus_q) ||
+ !BN_rshift1(rsa->q, rsa->q) ||
+ !BN_div(rsa->p, NULL, rsa->n, rsa->q, ctx) ||
+ !BN_mul(multiple, rsa->p, rsa->q, ctx)) {
+ OPENSSL_PUT_ERROR(RSA, RSA_recover_crt_params, ERR_R_BN_LIB);
+ goto err;
+ }
+
+ if (BN_cmp(multiple, rsa->n) != 0) {
+ OPENSSL_PUT_ERROR(RSA, RSA_recover_crt_params, RSA_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ if (!BN_sub(rem, rsa->p, BN_value_one()) ||
+ !BN_mod(rsa->dmp1, rsa->d, rem, ctx) ||
+ !BN_sub(rem, rsa->q, BN_value_one()) ||
+ !BN_mod(rsa->dmq1, rsa->d, rem, ctx) ||
+ !BN_mod_inverse(rsa->iqmp, rsa->q, rsa->p, ctx)) {
+ OPENSSL_PUT_ERROR(RSA, RSA_recover_crt_params, ERR_R_BN_LIB);
+ goto err;
+ }
+
+ ok = 1;
+
+err:
+ BN_CTX_end(ctx);
+ BN_CTX_free(ctx);
+ if (!ok) {
+ bn_free_and_null(&rsa->p);
+ bn_free_and_null(&rsa->q);
+ bn_free_and_null(&rsa->dmp1);
+ bn_free_and_null(&rsa->dmq1);
+ bn_free_and_null(&rsa->iqmp);
+ }
+ return ok;
+}
+
+int RSA_private_transform(RSA *rsa, uint8_t *out, const uint8_t *in,
+ size_t len) {
+ if (rsa->meth->private_transform) {
+ return rsa->meth->private_transform(rsa, out, in, len);
+ }
+
+ return RSA_default_method.private_transform(rsa, out, in, len);
+}
diff --git a/src/crypto/rsa/rsa_asn1.c b/src/crypto/rsa/rsa_asn1.c
new file mode 100644
index 0000000..924cb8a
--- /dev/null
+++ b/src/crypto/rsa/rsa_asn1.c
@@ -0,0 +1,125 @@
+/* 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 <openssl/rsa.h>
+
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+
+#include "internal.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;
+}
+
+ASN1_SEQUENCE_cb(RSAPrivateKey, rsa_cb) = {
+ ASN1_SIMPLE(RSA, version, LONG),
+ ASN1_SIMPLE(RSA, n, BIGNUM),
+ ASN1_SIMPLE(RSA, e, BIGNUM),
+ ASN1_SIMPLE(RSA, d, BIGNUM),
+ ASN1_SIMPLE(RSA, p, BIGNUM),
+ ASN1_SIMPLE(RSA, q, BIGNUM),
+ ASN1_SIMPLE(RSA, dmp1, BIGNUM),
+ ASN1_SIMPLE(RSA, dmq1, BIGNUM),
+ ASN1_SIMPLE(RSA, iqmp, BIGNUM),
+} ASN1_SEQUENCE_END_cb(RSA, RSAPrivateKey);
+
+ASN1_SEQUENCE_cb(RSAPublicKey, rsa_cb) = {
+ ASN1_SIMPLE(RSA, n, BIGNUM),
+ ASN1_SIMPLE(RSA, e, BIGNUM),
+} ASN1_SEQUENCE_END_cb(RSA, RSAPublicKey);
+
+ASN1_SEQUENCE(RSA_PSS_PARAMS) = {
+ ASN1_EXP_OPT(RSA_PSS_PARAMS, hashAlgorithm, X509_ALGOR,0),
+ ASN1_EXP_OPT(RSA_PSS_PARAMS, maskGenAlgorithm, X509_ALGOR,1),
+ ASN1_EXP_OPT(RSA_PSS_PARAMS, saltLength, ASN1_INTEGER,2),
+ ASN1_EXP_OPT(RSA_PSS_PARAMS, trailerField, ASN1_INTEGER,3),
+} ASN1_SEQUENCE_END(RSA_PSS_PARAMS);
+
+IMPLEMENT_ASN1_FUNCTIONS(RSA_PSS_PARAMS);
+
+ASN1_SEQUENCE(RSA_OAEP_PARAMS) = {
+ ASN1_EXP_OPT(RSA_OAEP_PARAMS, hashFunc, X509_ALGOR, 0),
+ ASN1_EXP_OPT(RSA_OAEP_PARAMS, maskGenFunc, X509_ALGOR, 1),
+ ASN1_EXP_OPT(RSA_OAEP_PARAMS, pSourceFunc, X509_ALGOR, 2),
+} ASN1_SEQUENCE_END(RSA_OAEP_PARAMS);
+
+IMPLEMENT_ASN1_FUNCTIONS(RSA_OAEP_PARAMS);
+
+IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(RSA, RSAPrivateKey, RSAPrivateKey);
+
+IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(RSA, RSAPublicKey, RSAPublicKey);
+
+RSA *RSAPublicKey_dup(const RSA *rsa) {
+ return ASN1_item_dup(ASN1_ITEM_rptr(RSAPublicKey), (RSA *) rsa);
+}
+
+RSA *RSAPrivateKey_dup(const RSA *rsa) {
+ return ASN1_item_dup(ASN1_ITEM_rptr(RSAPrivateKey), (RSA *) rsa);
+}
diff --git a/src/crypto/rsa/rsa_error.c b/src/crypto/rsa/rsa_error.c
new file mode 100644
index 0000000..3c8ebe4
--- /dev/null
+++ b/src/crypto/rsa/rsa_error.c
@@ -0,0 +1,95 @@
+/* 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 <openssl/err.h>
+
+#include <openssl/rsa.h>
+
+const ERR_STRING_DATA RSA_error_string_data[] = {
+ {ERR_PACK(ERR_LIB_RSA, RSA_F_BN_BLINDING_convert_ex, 0), "BN_BLINDING_convert_ex"},
+ {ERR_PACK(ERR_LIB_RSA, RSA_F_BN_BLINDING_create_param, 0), "BN_BLINDING_create_param"},
+ {ERR_PACK(ERR_LIB_RSA, RSA_F_BN_BLINDING_invert_ex, 0), "BN_BLINDING_invert_ex"},
+ {ERR_PACK(ERR_LIB_RSA, RSA_F_BN_BLINDING_new, 0), "BN_BLINDING_new"},
+ {ERR_PACK(ERR_LIB_RSA, RSA_F_BN_BLINDING_update, 0), "BN_BLINDING_update"},
+ {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_check_key, 0), "RSA_check_key"},
+ {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_new_method, 0), "RSA_new_method"},
+ {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_padding_add_PKCS1_OAEP_mgf1, 0), "RSA_padding_add_PKCS1_OAEP_mgf1"},
+ {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_padding_add_PKCS1_PSS_mgf1, 0), "RSA_padding_add_PKCS1_PSS_mgf1"},
+ {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_padding_add_PKCS1_type_1, 0), "RSA_padding_add_PKCS1_type_1"},
+ {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_padding_add_PKCS1_type_2, 0), "RSA_padding_add_PKCS1_type_2"},
+ {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_padding_add_SSLv23, 0), "RSA_padding_add_SSLv23"},
+ {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_padding_add_none, 0), "RSA_padding_add_none"},
+ {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_padding_check_PKCS1_OAEP_mgf1, 0), "RSA_padding_check_PKCS1_OAEP_mgf1"},
+ {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_padding_check_PKCS1_type_1, 0), "RSA_padding_check_PKCS1_type_1"},
+ {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_padding_check_PKCS1_type_2, 0), "RSA_padding_check_PKCS1_type_2"},
+ {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_padding_check_SSLv23, 0), "RSA_padding_check_SSLv23"},
+ {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_padding_check_none, 0), "RSA_padding_check_none"},
+ {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_recover_crt_params, 0), "RSA_recover_crt_params"},
+ {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_sign, 0), "RSA_sign"},
+ {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_verify, 0), "RSA_verify"},
+ {ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_verify_PKCS1_PSS_mgf1, 0), "RSA_verify_PKCS1_PSS_mgf1"},
+ {ERR_PACK(ERR_LIB_RSA, RSA_F_decrypt, 0), "decrypt"},
+ {ERR_PACK(ERR_LIB_RSA, RSA_F_encrypt, 0), "encrypt"},
+ {ERR_PACK(ERR_LIB_RSA, RSA_F_keygen, 0), "keygen"},
+ {ERR_PACK(ERR_LIB_RSA, RSA_F_pkcs1_prefixed_msg, 0), "pkcs1_prefixed_msg"},
+ {ERR_PACK(ERR_LIB_RSA, RSA_F_private_transform, 0), "private_transform"},
+ {ERR_PACK(ERR_LIB_RSA, RSA_F_rsa_setup_blinding, 0), "rsa_setup_blinding"},
+ {ERR_PACK(ERR_LIB_RSA, RSA_F_sign_raw, 0), "sign_raw"},
+ {ERR_PACK(ERR_LIB_RSA, RSA_F_verify_raw, 0), "verify_raw"},
+ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_BAD_E_VALUE), "BAD_E_VALUE"},
+ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_BAD_FIXED_HEADER_DECRYPT), "BAD_FIXED_HEADER_DECRYPT"},
+ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_BAD_PAD_BYTE_COUNT), "BAD_PAD_BYTE_COUNT"},
+ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_BAD_RSA_PARAMETERS), "BAD_RSA_PARAMETERS"},
+ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_BAD_SIGNATURE), "BAD_SIGNATURE"},
+ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_BLOCK_TYPE_IS_NOT_01), "BLOCK_TYPE_IS_NOT_01"},
+ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_BLOCK_TYPE_IS_NOT_02), "BLOCK_TYPE_IS_NOT_02"},
+ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_BN_NOT_INITIALIZED), "BN_NOT_INITIALIZED"},
+ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_CRT_PARAMS_ALREADY_GIVEN), "CRT_PARAMS_ALREADY_GIVEN"},
+ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_CRT_VALUES_INCORRECT), "CRT_VALUES_INCORRECT"},
+ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_DATA_LEN_NOT_EQUAL_TO_MOD_LEN), "DATA_LEN_NOT_EQUAL_TO_MOD_LEN"},
+ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_DATA_TOO_LARGE), "DATA_TOO_LARGE"},
+ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE), "DATA_TOO_LARGE_FOR_KEY_SIZE"},
+ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_DATA_TOO_LARGE_FOR_MODULUS), "DATA_TOO_LARGE_FOR_MODULUS"},
+ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_DATA_TOO_SMALL), "DATA_TOO_SMALL"},
+ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_DATA_TOO_SMALL_FOR_KEY_SIZE), "DATA_TOO_SMALL_FOR_KEY_SIZE"},
+ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY), "DIGEST_TOO_BIG_FOR_RSA_KEY"},
+ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_D_E_NOT_CONGRUENT_TO_1), "D_E_NOT_CONGRUENT_TO_1"},
+ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_EMPTY_PUBLIC_KEY), "EMPTY_PUBLIC_KEY"},
+ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_FIRST_OCTET_INVALID), "FIRST_OCTET_INVALID"},
+ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INCONSISTENT_SET_OF_CRT_VALUES), "INCONSISTENT_SET_OF_CRT_VALUES"},
+ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INTERNAL_ERROR), "INTERNAL_ERROR"},
+ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_MESSAGE_LENGTH), "INVALID_MESSAGE_LENGTH"},
+ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_KEY_SIZE_TOO_SMALL), "KEY_SIZE_TOO_SMALL"},
+ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_LAST_OCTET_INVALID), "LAST_OCTET_INVALID"},
+ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_MODULUS_TOO_LARGE), "MODULUS_TOO_LARGE"},
+ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_NO_PUBLIC_EXPONENT), "NO_PUBLIC_EXPONENT"},
+ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_NULL_BEFORE_BLOCK_MISSING), "NULL_BEFORE_BLOCK_MISSING"},
+ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_N_NOT_EQUAL_P_Q), "N_NOT_EQUAL_P_Q"},
+ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_OAEP_DECODING_ERROR), "OAEP_DECODING_ERROR"},
+ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_ONLY_ONE_OF_P_Q_GIVEN), "ONLY_ONE_OF_P_Q_GIVEN"},
+ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_OUTPUT_BUFFER_TOO_SMALL), "OUTPUT_BUFFER_TOO_SMALL"},
+ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_PADDING_CHECK_FAILED), "PADDING_CHECK_FAILED"},
+ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_PKCS_DECODING_ERROR), "PKCS_DECODING_ERROR"},
+ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_SLEN_CHECK_FAILED), "SLEN_CHECK_FAILED"},
+ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_SLEN_RECOVERY_FAILED), "SLEN_RECOVERY_FAILED"},
+ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_SSLV3_ROLLBACK_ATTACK), "SSLV3_ROLLBACK_ATTACK"},
+ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD), "THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD"},
+ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_TOO_LONG), "TOO_LONG"},
+ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_TOO_MANY_ITERATIONS), "TOO_MANY_ITERATIONS"},
+ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_UNKNOWN_ALGORITHM_TYPE), "UNKNOWN_ALGORITHM_TYPE"},
+ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_UNKNOWN_PADDING_TYPE), "UNKNOWN_PADDING_TYPE"},
+ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_VALUE_MISSING), "VALUE_MISSING"},
+ {ERR_PACK(ERR_LIB_RSA, 0, RSA_R_WRONG_SIGNATURE_LENGTH), "WRONG_SIGNATURE_LENGTH"},
+ {0, NULL},
+};
diff --git a/src/crypto/rsa/rsa_impl.c b/src/crypto/rsa/rsa_impl.c
new file mode 100644
index 0000000..d950d50
--- /dev/null
+++ b/src/crypto/rsa/rsa_impl.c
@@ -0,0 +1,960 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/rsa.h>
+
+#include <string.h>
+
+#include <openssl/bn.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+
+#include "internal.h"
+
+
+#define OPENSSL_RSA_MAX_MODULUS_BITS 16384
+#define OPENSSL_RSA_SMALL_MODULUS_BITS 3072
+#define OPENSSL_RSA_MAX_PUBEXP_BITS \
+ 64 /* exponent limit enforced for "large" modulus only */
+
+
+static int finish(RSA *rsa) {
+ if (rsa->_method_mod_n != NULL) {
+ BN_MONT_CTX_free(rsa->_method_mod_n);
+ }
+ if (rsa->_method_mod_p != NULL) {
+ BN_MONT_CTX_free(rsa->_method_mod_p);
+ }
+ if (rsa->_method_mod_q != NULL) {
+ BN_MONT_CTX_free(rsa->_method_mod_q);
+ }
+
+ return 1;
+}
+
+static size_t size(const RSA *rsa) {
+ return BN_num_bytes(rsa->n);
+}
+
+static int encrypt(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
+ const uint8_t *in, size_t in_len, int padding) {
+ const unsigned rsa_size = RSA_size(rsa);
+ BIGNUM *f, *result;
+ uint8_t *buf = NULL;
+ BN_CTX *ctx = NULL;
+ int i, ret = 0;
+
+ if (rsa_size > OPENSSL_RSA_MAX_MODULUS_BITS) {
+ OPENSSL_PUT_ERROR(RSA, encrypt, RSA_R_MODULUS_TOO_LARGE);
+ return 0;
+ }
+
+ if (max_out < rsa_size) {
+ OPENSSL_PUT_ERROR(RSA, encrypt, RSA_R_OUTPUT_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ if (BN_ucmp(rsa->n, rsa->e) <= 0) {
+ OPENSSL_PUT_ERROR(RSA, encrypt, RSA_R_BAD_E_VALUE);
+ return 0;
+ }
+
+ /* for large moduli, enforce exponent limit */
+ if (BN_num_bits(rsa->n) > OPENSSL_RSA_SMALL_MODULUS_BITS &&
+ BN_num_bits(rsa->e) > OPENSSL_RSA_MAX_PUBEXP_BITS) {
+ OPENSSL_PUT_ERROR(RSA, encrypt, RSA_R_BAD_E_VALUE);
+ return 0;
+ }
+
+ ctx = BN_CTX_new();
+ if (ctx == NULL) {
+ goto err;
+ }
+
+ BN_CTX_start(ctx);
+ f = BN_CTX_get(ctx);
+ result = BN_CTX_get(ctx);
+ buf = OPENSSL_malloc(rsa_size);
+ if (!f || !result || !buf) {
+ OPENSSL_PUT_ERROR(RSA, encrypt, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ switch (padding) {
+ case RSA_PKCS1_PADDING:
+ i = RSA_padding_add_PKCS1_type_2(buf, rsa_size, in, in_len);
+ break;
+ case RSA_PKCS1_OAEP_PADDING:
+ /* Use the default parameters: SHA-1 for both hashes and no label. */
+ i = RSA_padding_add_PKCS1_OAEP_mgf1(buf, rsa_size, in, in_len,
+ NULL, 0, NULL, NULL);
+ break;
+ case RSA_NO_PADDING:
+ i = RSA_padding_add_none(buf, rsa_size, in, in_len);
+ break;
+ default:
+ OPENSSL_PUT_ERROR(RSA, encrypt, RSA_R_UNKNOWN_PADDING_TYPE);
+ goto err;
+ }
+
+ if (i <= 0) {
+ goto err;
+ }
+
+ if (BN_bin2bn(buf, rsa_size, f) == NULL) {
+ goto err;
+ }
+
+ if (BN_ucmp(f, rsa->n) >= 0) {
+ /* usually the padding functions would catch this */
+ OPENSSL_PUT_ERROR(RSA, encrypt, 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(result, 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 */
+ if (!BN_bn2bin_padded(out, rsa_size, result)) {
+ OPENSSL_PUT_ERROR(RSA, encrypt, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ *out_len = rsa_size;
+ ret = 1;
+
+err:
+ if (ctx != NULL) {
+ BN_CTX_end(ctx);
+ BN_CTX_free(ctx);
+ }
+ if (buf != NULL) {
+ OPENSSL_cleanse(buf, rsa_size);
+ OPENSSL_free(buf);
+ }
+
+ return ret;
+}
+
+/* MAX_BLINDINGS_PER_RSA defines the maximum number of cached BN_BLINDINGs per
+ * RSA*. Then this limit is exceeded, BN_BLINDING objects will be created and
+ * destroyed as needed. */
+#define MAX_BLINDINGS_PER_RSA 1024
+
+/* rsa_blinding_get returns a BN_BLINDING to use with |rsa|. It does this by
+ * allocating one of the cached BN_BLINDING objects in |rsa->blindings|. If
+ * none are free, the cache will be extended by a extra element and the new
+ * BN_BLINDING is returned.
+ *
+ * On success, the index of the assigned BN_BLINDING is written to
+ * |*index_used| and must be passed to |rsa_blinding_release| when finished. */
+static BN_BLINDING *rsa_blinding_get(RSA *rsa, unsigned *index_used,
+ BN_CTX *ctx) {
+ BN_BLINDING *ret = NULL;
+ BN_BLINDING **new_blindings;
+ uint8_t *new_blindings_inuse;
+ char overflow = 0;
+
+ CRYPTO_w_lock(CRYPTO_LOCK_RSA_BLINDING);
+ if (rsa->num_blindings > 0) {
+ unsigned i, starting_index;
+ CRYPTO_THREADID threadid;
+
+ /* We start searching the array at a value based on the
+ * threadid in order to try avoid bouncing the BN_BLINDING
+ * values around different threads. It's harmless if
+ * threadid.val is always set to zero. */
+ CRYPTO_THREADID_current(&threadid);
+ starting_index = threadid.val % rsa->num_blindings;
+
+ for (i = starting_index;;) {
+ if (rsa->blindings_inuse[i] == 0) {
+ rsa->blindings_inuse[i] = 1;
+ ret = rsa->blindings[i];
+ *index_used = i;
+ break;
+ }
+ i++;
+ if (i == rsa->num_blindings) {
+ i = 0;
+ }
+ if (i == starting_index) {
+ break;
+ }
+ }
+ }
+
+ if (ret != NULL) {
+ CRYPTO_w_unlock(CRYPTO_LOCK_RSA_BLINDING);
+ return ret;
+ }
+
+ overflow = rsa->num_blindings >= MAX_BLINDINGS_PER_RSA;
+
+ /* We didn't find a free BN_BLINDING to use so increase the length of
+ * the arrays by one and use the newly created element. */
+
+ CRYPTO_w_unlock(CRYPTO_LOCK_RSA_BLINDING);
+ ret = rsa_setup_blinding(rsa, ctx);
+ if (ret == NULL) {
+ return NULL;
+ }
+
+ if (overflow) {
+ /* We cannot add any more cached BN_BLINDINGs so we use |ret|
+ * and mark it for destruction in |rsa_blinding_release|. */
+ *index_used = MAX_BLINDINGS_PER_RSA;
+ return ret;
+ }
+
+ CRYPTO_w_lock(CRYPTO_LOCK_RSA_BLINDING);
+
+ new_blindings =
+ OPENSSL_malloc(sizeof(BN_BLINDING *) * (rsa->num_blindings + 1));
+ if (new_blindings == NULL) {
+ goto err1;
+ }
+ memcpy(new_blindings, rsa->blindings,
+ sizeof(BN_BLINDING *) * rsa->num_blindings);
+ new_blindings[rsa->num_blindings] = ret;
+
+ new_blindings_inuse = OPENSSL_malloc(rsa->num_blindings + 1);
+ if (new_blindings_inuse == NULL) {
+ goto err2;
+ }
+ memcpy(new_blindings_inuse, rsa->blindings_inuse, rsa->num_blindings);
+ new_blindings_inuse[rsa->num_blindings] = 1;
+ *index_used = rsa->num_blindings;
+
+ if (rsa->blindings != NULL) {
+ OPENSSL_free(rsa->blindings);
+ }
+ rsa->blindings = new_blindings;
+ if (rsa->blindings_inuse != NULL) {
+ OPENSSL_free(rsa->blindings_inuse);
+ }
+ rsa->blindings_inuse = new_blindings_inuse;
+ rsa->num_blindings++;
+
+ CRYPTO_w_unlock(CRYPTO_LOCK_RSA_BLINDING);
+ return ret;
+
+err2:
+ OPENSSL_free(new_blindings);
+
+err1:
+ CRYPTO_w_unlock(CRYPTO_LOCK_RSA_BLINDING);
+ BN_BLINDING_free(ret);
+ return NULL;
+}
+
+/* rsa_blinding_release marks the cached BN_BLINDING at the given index as free
+ * for other threads to use. */
+static void rsa_blinding_release(RSA *rsa, BN_BLINDING *blinding,
+ unsigned blinding_index) {
+ if (blinding_index == MAX_BLINDINGS_PER_RSA) {
+ /* This blinding wasn't cached. */
+ BN_BLINDING_free(blinding);
+ return;
+ }
+
+ CRYPTO_w_lock(CRYPTO_LOCK_RSA_BLINDING);
+ rsa->blindings_inuse[blinding_index] = 0;
+ CRYPTO_w_unlock(CRYPTO_LOCK_RSA_BLINDING);
+}
+
+/* signing */
+static int sign_raw(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
+ const uint8_t *in, size_t in_len, int padding) {
+ const unsigned rsa_size = RSA_size(rsa);
+ uint8_t *buf = NULL;
+ int i, ret = 0;
+
+ if (max_out < rsa_size) {
+ OPENSSL_PUT_ERROR(RSA, sign_raw, RSA_R_OUTPUT_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ buf = OPENSSL_malloc(rsa_size);
+ if (buf == NULL) {
+ OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ switch (padding) {
+ case RSA_PKCS1_PADDING:
+ i = RSA_padding_add_PKCS1_type_1(buf, rsa_size, in, in_len);
+ break;
+ case RSA_NO_PADDING:
+ i = RSA_padding_add_none(buf, rsa_size, in, in_len);
+ break;
+ default:
+ OPENSSL_PUT_ERROR(RSA, sign_raw, RSA_R_UNKNOWN_PADDING_TYPE);
+ goto err;
+ }
+
+ if (i <= 0) {
+ goto err;
+ }
+
+ if (!RSA_private_transform(rsa, out, buf, rsa_size)) {
+ OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ *out_len = rsa_size;
+ ret = 1;
+
+err:
+ if (buf != NULL) {
+ OPENSSL_cleanse(buf, rsa_size);
+ OPENSSL_free(buf);
+ }
+
+ return ret;
+}
+
+static int decrypt(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
+ const uint8_t *in, size_t in_len, int padding) {
+ const unsigned rsa_size = RSA_size(rsa);
+ int r = -1;
+ uint8_t *buf = NULL;
+ int ret = 0;
+
+ if (max_out < rsa_size) {
+ OPENSSL_PUT_ERROR(RSA, decrypt, RSA_R_OUTPUT_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ buf = OPENSSL_malloc(rsa_size);
+ if (buf == NULL) {
+ OPENSSL_PUT_ERROR(RSA, decrypt, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (in_len != rsa_size) {
+ OPENSSL_PUT_ERROR(RSA, decrypt, RSA_R_DATA_LEN_NOT_EQUAL_TO_MOD_LEN);
+ goto err;
+ }
+
+ if (!RSA_private_transform(rsa, buf, in, rsa_size)) {
+ OPENSSL_PUT_ERROR(RSA, decrypt, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ switch (padding) {
+ case RSA_PKCS1_PADDING:
+ r = RSA_padding_check_PKCS1_type_2(out, rsa_size, buf, rsa_size);
+ break;
+ case RSA_PKCS1_OAEP_PADDING:
+ /* Use the default parameters: SHA-1 for both hashes and no label. */
+ r = RSA_padding_check_PKCS1_OAEP_mgf1(out, rsa_size, buf, rsa_size,
+ NULL, 0, NULL, NULL);
+ break;
+ case RSA_NO_PADDING:
+ r = RSA_padding_check_none(out, rsa_size, buf, rsa_size);
+ break;
+ default:
+ OPENSSL_PUT_ERROR(RSA, decrypt, RSA_R_UNKNOWN_PADDING_TYPE);
+ goto err;
+ }
+
+ if (r < 0) {
+ OPENSSL_PUT_ERROR(RSA, decrypt, RSA_R_PADDING_CHECK_FAILED);
+ } else {
+ *out_len = r;
+ ret = 1;
+ }
+
+err:
+ if (buf != NULL) {
+ OPENSSL_cleanse(buf, rsa_size);
+ OPENSSL_free(buf);
+ }
+
+ return ret;
+}
+
+static int verify_raw(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
+ const uint8_t *in, size_t in_len, int padding) {
+ const unsigned rsa_size = RSA_size(rsa);
+ BIGNUM *f, *result;
+ int ret = 0;
+ int r = -1;
+ uint8_t *buf = NULL;
+ BN_CTX *ctx = NULL;
+
+ if (BN_num_bits(rsa->n) > OPENSSL_RSA_MAX_MODULUS_BITS) {
+ OPENSSL_PUT_ERROR(RSA, verify_raw, RSA_R_MODULUS_TOO_LARGE);
+ return 0;
+ }
+
+ if (BN_ucmp(rsa->n, rsa->e) <= 0) {
+ OPENSSL_PUT_ERROR(RSA, verify_raw, RSA_R_BAD_E_VALUE);
+ return 0;
+ }
+
+ if (max_out < rsa_size) {
+ OPENSSL_PUT_ERROR(RSA, verify_raw, RSA_R_OUTPUT_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ /* for large moduli, enforce exponent limit */
+ if (BN_num_bits(rsa->n) > OPENSSL_RSA_SMALL_MODULUS_BITS &&
+ BN_num_bits(rsa->e) > OPENSSL_RSA_MAX_PUBEXP_BITS) {
+ OPENSSL_PUT_ERROR(RSA, verify_raw, RSA_R_BAD_E_VALUE);
+ return 0;
+ }
+
+ ctx = BN_CTX_new();
+ if (ctx == NULL) {
+ goto err;
+ }
+
+ BN_CTX_start(ctx);
+ f = BN_CTX_get(ctx);
+ result = BN_CTX_get(ctx);
+ buf = OPENSSL_malloc(rsa_size);
+ if (!f || !result || !buf) {
+ OPENSSL_PUT_ERROR(RSA, verify_raw, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (in_len != rsa_size) {
+ OPENSSL_PUT_ERROR(RSA, verify_raw, RSA_R_DATA_LEN_NOT_EQUAL_TO_MOD_LEN);
+ goto err;
+ }
+
+ if (BN_bin2bn(in, in_len, f) == NULL) {
+ goto err;
+ }
+
+ if (BN_ucmp(f, rsa->n) >= 0) {
+ OPENSSL_PUT_ERROR(RSA, verify_raw, 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(result, f, rsa->e, rsa->n, ctx,
+ rsa->_method_mod_n)) {
+ goto err;
+ }
+
+ if (!BN_bn2bin_padded(buf, rsa_size, result)) {
+ OPENSSL_PUT_ERROR(RSA, verify_raw, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ switch (padding) {
+ case RSA_PKCS1_PADDING:
+ r = RSA_padding_check_PKCS1_type_1(out, rsa_size, buf, rsa_size);
+ break;
+ case RSA_NO_PADDING:
+ r = RSA_padding_check_none(out, rsa_size, buf, rsa_size);
+ break;
+ default:
+ OPENSSL_PUT_ERROR(RSA, verify_raw, RSA_R_UNKNOWN_PADDING_TYPE);
+ goto err;
+ }
+
+ if (r < 0) {
+ OPENSSL_PUT_ERROR(RSA, verify_raw, RSA_R_PADDING_CHECK_FAILED);
+ } else {
+ *out_len = r;
+ ret = 1;
+ }
+
+err:
+ if (ctx != NULL) {
+ BN_CTX_end(ctx);
+ BN_CTX_free(ctx);
+ }
+ if (buf != NULL) {
+ OPENSSL_cleanse(buf, rsa_size);
+ OPENSSL_free(buf);
+ }
+ return ret;
+}
+
+static int private_transform(RSA *rsa, uint8_t *out, const uint8_t *in,
+ size_t len) {
+ BIGNUM *f, *result;
+ BN_CTX *ctx = NULL;
+ unsigned blinding_index = 0;
+ BN_BLINDING *blinding = NULL;
+ int ret = 0;
+
+ ctx = BN_CTX_new();
+ if (ctx == NULL) {
+ goto err;
+ }
+ BN_CTX_start(ctx);
+ f = BN_CTX_get(ctx);
+ result = BN_CTX_get(ctx);
+
+ if (f == NULL || result == NULL) {
+ OPENSSL_PUT_ERROR(RSA, private_transform, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (BN_bin2bn(in, len, f) == NULL) {
+ goto err;
+ }
+
+ if (BN_ucmp(f, rsa->n) >= 0) {
+ /* Usually the padding functions would catch this. */
+ OPENSSL_PUT_ERROR(RSA, private_transform, RSA_R_DATA_TOO_LARGE_FOR_MODULUS);
+ goto err;
+ }
+
+ if (!(rsa->flags & RSA_FLAG_NO_BLINDING)) {
+ blinding = rsa_blinding_get(rsa, &blinding_index, ctx);
+ if (blinding == NULL) {
+ OPENSSL_PUT_ERROR(RSA, private_transform, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ if (!BN_BLINDING_convert_ex(f, NULL, blinding, 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->mod_exp(result, f, rsa, ctx)) {
+ goto err;
+ }
+ } else {
+ BIGNUM local_d;
+ BIGNUM *d = NULL;
+
+ BN_init(&local_d);
+ d = &local_d;
+ BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME);
+
+ if (rsa->flags & RSA_FLAG_CACHE_PUBLIC) {
+ if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, CRYPTO_LOCK_RSA, rsa->n,
+ ctx)) {
+ goto err;
+ }
+ }
+
+ if (!rsa->meth->bn_mod_exp(result, f, d, rsa->n, ctx, rsa->_method_mod_n)) {
+ goto err;
+ }
+ }
+
+ if (blinding) {
+ if (!BN_BLINDING_invert_ex(result, NULL, blinding, ctx)) {
+ goto err;
+ }
+ }
+
+ if (!BN_bn2bin_padded(out, len, result)) {
+ OPENSSL_PUT_ERROR(RSA, private_transform, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ ret = 1;
+
+err:
+ if (ctx != NULL) {
+ BN_CTX_end(ctx);
+ BN_CTX_free(ctx);
+ }
+ if (blinding != NULL) {
+ rsa_blinding_release(rsa, blinding, blinding_index);
+ }
+
+ return ret;
+}
+
+static int mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) {
+ BIGNUM *r1, *m1, *vrfy;
+ BIGNUM local_dmp1, local_dmq1, local_c, local_r1;
+ 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);
+
+ {
+ BIGNUM local_p, local_q;
+ BIGNUM *p = NULL, *q = NULL;
+
+ /* Make sure BN_mod_inverse in Montgomery intialization uses the
+ * BN_FLG_CONSTTIME flag (unless RSA_FLAG_NO_CONSTTIME is set) */
+ BN_init(&local_p);
+ p = &local_p;
+ BN_with_flags(p, rsa->p, BN_FLG_CONSTTIME);
+
+ BN_init(&local_q);
+ q = &local_q;
+ 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)) {
+ goto err;
+ }
+ if (!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 */
+ c = &local_c;
+ BN_with_flags(c, I, BN_FLG_CONSTTIME);
+ if (!BN_mod(r1, c, rsa->q, ctx)) {
+ goto err;
+ }
+
+ /* compute r1^dmq1 mod q */
+ dmq1 = &local_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 */
+ c = &local_c;
+ BN_with_flags(c, I, BN_FLG_CONSTTIME);
+ if (!BN_mod(r1, c, rsa->p, ctx)) {
+ goto err;
+ }
+
+ /* compute r1^dmp1 mod p */
+ dmp1 = &local_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 */
+ pr1 = &local_r1;
+ BN_with_flags(pr1, r1, BN_FLG_CONSTTIME);
+
+ if (!BN_mod(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(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 local_d;
+ BIGNUM *d = NULL;
+
+ d = &local_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 keygen(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb) {
+ BIGNUM *r0 = NULL, *r1 = NULL, *r2 = NULL, *r3 = NULL, *tmp;
+ BIGNUM local_r0, local_d, local_p;
+ 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);
+ r0 = BN_CTX_get(ctx);
+ r1 = BN_CTX_get(ctx);
+ r2 = BN_CTX_get(ctx);
+ r3 = BN_CTX_get(ctx);
+ if (r3 == 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;
+
+ BN_copy(rsa->e, e_value);
+
+ /* 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(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 */
+ OPENSSL_PUT_ERROR(RSA, keygen, RSA_R_KEY_SIZE_TOO_SMALL);
+ goto err;
+ }
+ if (!BN_sub(r2, rsa->q, BN_value_one()))
+ goto err;
+ if (!BN_gcd(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()))
+ goto err; /* p-1 */
+ if (!BN_sub(r2, rsa->q, BN_value_one()))
+ goto err; /* q-1 */
+ if (!BN_mul(r0, r1, r2, ctx))
+ goto err; /* (p-1)(q-1) */
+ pr0 = &local_r0;
+ BN_with_flags(pr0, r0, BN_FLG_CONSTTIME);
+ if (!BN_mod_inverse(rsa->d, rsa->e, pr0, ctx))
+ goto err; /* d */
+
+ /* set up d for correct BN_FLG_CONSTTIME flag */
+ d = &local_d;
+ BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME);
+
+ /* calculate d mod (p-1) */
+ if (!BN_mod(rsa->dmp1, d, r1, ctx))
+ goto err;
+
+ /* calculate d mod (q-1) */
+ if (!BN_mod(rsa->dmq1, d, r2, ctx))
+ goto err;
+
+ /* calculate inverse of q mod p */
+ p = &local_p;
+ BN_with_flags(p, rsa->p, BN_FLG_CONSTTIME);
+
+ if (!BN_mod_inverse(rsa->iqmp, rsa->q, p, ctx))
+ goto err;
+
+ ok = 1;
+
+err:
+ if (ok == -1) {
+ OPENSSL_PUT_ERROR(RSA, keygen, ERR_LIB_BN);
+ ok = 0;
+ }
+ if (ctx != NULL) {
+ BN_CTX_end(ctx);
+ BN_CTX_free(ctx);
+ }
+
+ return ok;
+}
+
+const struct rsa_meth_st RSA_default_method = {
+ {
+ 0 /* references */,
+ 1 /* is_static */,
+ },
+ NULL /* app_data */,
+
+ NULL /* init */,
+ finish,
+
+ size,
+
+ NULL /* sign */,
+ NULL /* verify */,
+
+ encrypt,
+ sign_raw,
+ decrypt,
+ verify_raw,
+
+ private_transform,
+
+ mod_exp /* mod_exp */,
+ BN_mod_exp_mont /* bn_mod_exp */,
+
+ RSA_FLAG_CACHE_PUBLIC | RSA_FLAG_CACHE_PRIVATE,
+
+ keygen,
+};
diff --git a/src/crypto/rsa/rsa_test.c b/src/crypto/rsa/rsa_test.c
new file mode 100644
index 0000000..75489e0
--- /dev/null
+++ b/src/crypto/rsa/rsa_test.c
@@ -0,0 +1,508 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/rsa.h>
+
+#include <string.h>
+
+#include <openssl/bio.h>
+#include <openssl/bn.h>
+#include <openssl/crypto.h>
+#include <openssl/err.h>
+#include <openssl/obj.h>
+
+
+#define SetKey \
+ key->n = BN_bin2bn(n, sizeof(n) - 1, key->n); \
+ key->e = BN_bin2bn(e, sizeof(e) - 1, key->e); \
+ key->d = BN_bin2bn(d, sizeof(d) - 1, key->d); \
+ key->p = BN_bin2bn(p, sizeof(p) - 1, key->p); \
+ key->q = BN_bin2bn(q, sizeof(q) - 1, key->q); \
+ key->dmp1 = BN_bin2bn(dmp1, sizeof(dmp1) - 1, key->dmp1); \
+ key->dmq1 = BN_bin2bn(dmq1, sizeof(dmq1) - 1, key->dmq1); \
+ key->iqmp = BN_bin2bn(iqmp, sizeof(iqmp) - 1, key->iqmp); \
+ memcpy(c, ctext_ex, sizeof(ctext_ex) - 1); \
+ return (sizeof(ctext_ex) - 1);
+
+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";
+
+ SetKey;
+}
+
+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";
+
+ SetKey;
+}
+
+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";
+
+ SetKey;
+}
+
+static int test_bad_key(void) {
+ RSA *key = RSA_new();
+ BIGNUM e;
+
+ BN_init(&e);
+ BN_set_word(&e, RSA_F4);
+
+ if (!RSA_generate_key_ex(key, 512, &e, NULL)) {
+ fprintf(stderr, "RSA_generate_key_ex failed.\n");
+ BIO_print_errors_fp(stderr);
+ return 0;
+ }
+
+ if (!BN_add(key->p, key->p, BN_value_one())) {
+ fprintf(stderr, "BN error.\n");
+ BIO_print_errors_fp(stderr);
+ return 0;
+ }
+
+ if (RSA_check_key(key)) {
+ fprintf(stderr, "RSA_check_key passed with invalid key!\n");
+ return 0;
+ }
+
+ ERR_clear_error();
+ BN_free(&e);
+ RSA_free(key);
+ return 1;
+}
+
+static int test_only_d_given(void) {
+ RSA *key = RSA_new();
+ uint8_t buf[64];
+ unsigned buf_len = sizeof(buf);
+ const uint8_t kDummyHash[16] = {0};
+ int ret = 0;
+
+ if (!BN_hex2bn(&key->n,
+ "00e77bbf3889d4ef36a9a25d4d69f3f632eb4362214c74517da6d6aeaa9bd"
+ "09ac42b26621cd88f3a6eb013772fc3bf9f83914b6467231c630202c35b3e"
+ "5808c659") ||
+ !BN_hex2bn(&key->e, "010001") ||
+ !BN_hex2bn(&key->d,
+ "0365db9eb6d73b53b015c40cd8db4de7dd7035c68b5ac1bf786d7a4ee2cea"
+ "316eaeca21a73ac365e58713195f2ae9849348525ca855386b6d028e437a9"
+ "495a01") ||
+ RSA_size(key) > sizeof(buf)) {
+ goto err;
+ }
+
+ if (!RSA_check_key(key)) {
+ fprintf(stderr, "RSA_check_key failed with only d given.\n");
+ BIO_print_errors_fp(stderr);
+ goto err;
+ }
+
+ if (!RSA_sign(NID_md5, kDummyHash, sizeof(kDummyHash), buf, &buf_len, key)) {
+ fprintf(stderr, "RSA_sign failed with only d given.\n");
+ BIO_print_errors_fp(stderr);
+ goto err;
+ }
+
+ if (!RSA_verify(NID_md5, kDummyHash, sizeof(kDummyHash), buf, buf_len, key)) {
+ fprintf(stderr, "RSA_verify failed with only d given.\n");
+ BIO_print_errors_fp(stderr);
+ goto err;
+ }
+
+ ret = 1;
+
+err:
+ RSA_free(key);
+ return ret;
+}
+
+static int test_recover_crt_params(void) {
+ RSA *key1, *key2;
+ BIGNUM *e = BN_new();
+ uint8_t buf[128];
+ unsigned buf_len = sizeof(buf);
+ const uint8_t kDummyHash[16] = {0};
+ unsigned i;
+
+ BN_set_word(e, RSA_F4);
+
+ ERR_clear_error();
+
+ for (i = 0; i < 1; i++) {
+ key1 = RSA_new();
+ if (!RSA_generate_key_ex(key1, 512, e, NULL)) {
+ fprintf(stderr, "RSA_generate_key_ex failed.\n");
+ BIO_print_errors_fp(stderr);
+ return 0;
+ }
+
+ if (!RSA_check_key(key1)) {
+ fprintf(stderr, "RSA_check_key failed with original key.\n");
+ BIO_print_errors_fp(stderr);
+ return 0;
+ }
+
+ key2 = RSA_new();
+ key2->n = BN_dup(key1->n);
+ key2->e = BN_dup(key1->e);
+ key2->d = BN_dup(key1->d);
+ RSA_free(key1);
+
+ if (!RSA_recover_crt_params(key2)) {
+ fprintf(stderr, "RSA_recover_crt_params failed.\n");
+ BIO_print_errors_fp(stderr);
+ return 0;
+ }
+
+ if (RSA_size(key2) > buf_len) {
+ return 0;
+ }
+
+ if (!RSA_check_key(key2)) {
+ fprintf(stderr, "RSA_check_key failed with recovered key.\n");
+ BIO_print_errors_fp(stderr);
+ return 0;
+ }
+
+ if (!RSA_sign(NID_md5, kDummyHash, sizeof(kDummyHash), buf, &buf_len,
+ key2)) {
+ fprintf(stderr, "RSA_sign failed with recovered key.\n");
+ BIO_print_errors_fp(stderr);
+ return 0;
+ }
+
+ if (!RSA_verify(NID_md5, kDummyHash, sizeof(kDummyHash), buf, buf_len,
+ key2)) {
+ fprintf(stderr, "RSA_verify failed with recovered key.\n");
+ BIO_print_errors_fp(stderr);
+ return 0;
+ }
+
+ RSA_free(key2);
+ }
+
+ BN_free(e);
+ return 1;
+}
+
+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;
+
+ CRYPTO_library_init();
+
+ 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;
+ default:
+ abort();
+ }
+
+ if (!RSA_check_key(key)) {
+ printf("%d: RSA_check_key failed\n", v);
+ err = 1;
+ goto oaep;
+ }
+
+ 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) {
+ 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) {
+ int b;
+ unsigned char saved = ctext[n];
+ for (b = 0; b < 256; ++b) {
+ if (b == saved)
+ continue;
+ ctext[n] = b;
+ num =
+ RSA_private_decrypt(num, ctext, ptext, key, RSA_PKCS1_OAEP_PADDING);
+ if (num > 0) {
+ printf("Corrupt data decrypted!\n");
+ err = 1;
+ }
+ }
+ }
+
+ next:
+ RSA_free(key);
+ }
+
+ if (err != 0 ||
+ !test_only_d_given() ||
+ !test_recover_crt_params() ||
+ !test_bad_key()) {
+ err = 1;
+ }
+
+ if (err == 0) {
+ printf("PASS\n");
+ }
+ return err;
+}
diff --git a/src/crypto/sha/CMakeLists.txt b/src/crypto/sha/CMakeLists.txt
new file mode 100644
index 0000000..5a10c85
--- /dev/null
+++ b/src/crypto/sha/CMakeLists.txt
@@ -0,0 +1,66 @@
+include_directories(. .. ../../include)
+
+if (${ARCH} STREQUAL "x86_64")
+ set(
+ SHA_ARCH_SOURCES
+
+ sha1-x86_64.${ASM_EXT}
+ sha256-x86_64.${ASM_EXT}
+ sha512-x86_64.${ASM_EXT}
+ )
+endif()
+
+if (${ARCH} STREQUAL "x86")
+ set(
+ SHA_ARCH_SOURCES
+
+ sha1-586.${ASM_EXT}
+ sha256-586.${ASM_EXT}
+ sha512-586.${ASM_EXT}
+ )
+endif()
+
+if (${ARCH} STREQUAL "arm")
+ set(
+ SHA_ARCH_SOURCES
+
+ sha1-armv4-large.${ASM_EXT}
+ sha256-armv4.${ASM_EXT}
+ sha512-armv4.${ASM_EXT}
+ )
+endif()
+
+if (${ARCH} STREQUAL "aarch64")
+ set(
+ SHA_ARCH_SOURCES
+
+ sha1-armv8.${ASM_EXT}
+ sha256-armv8.${ASM_EXT}
+ sha512-armv8.${ASM_EXT}
+ )
+endif()
+
+add_library(
+ sha
+
+ OBJECT
+
+ sha1.c
+ sha256.c
+ sha512.c
+
+ ${SHA_ARCH_SOURCES}
+)
+
+perlasm(sha1-x86_64.${ASM_EXT} asm/sha1-x86_64.pl)
+perlasm(sha256-x86_64.${ASM_EXT} asm/sha512-x86_64.pl sha256)
+perlasm(sha512-x86_64.${ASM_EXT} asm/sha512-x86_64.pl sha512)
+perlasm(sha1-586.${ASM_EXT} asm/sha1-586.pl)
+perlasm(sha256-586.${ASM_EXT} asm/sha256-586.pl)
+perlasm(sha512-586.${ASM_EXT} asm/sha512-586.pl)
+perlasm(sha1-armv4-large.${ASM_EXT} asm/sha1-armv4-large.pl)
+perlasm(sha256-armv4.${ASM_EXT} asm/sha256-armv4.pl)
+perlasm(sha512-armv4.${ASM_EXT} asm/sha512-armv4.pl)
+perlasm(sha1-armv8.${ASM_EXT} asm/sha1-armv8.pl)
+perlasm(sha256-armv8.${ASM_EXT} asm/sha512-armv8.pl sha256)
+perlasm(sha512-armv8.${ASM_EXT} asm/sha512-armv8.pl sha512)
diff --git a/src/crypto/sha/asm/sha1-586.pl b/src/crypto/sha/asm/sha1-586.pl
new file mode 100644
index 0000000..8377299
--- /dev/null
+++ b/src/crypto/sha/asm/sha1-586.pl
@@ -0,0 +1,1476 @@
+#!/usr/bin/env perl
+
+# ====================================================================
+# [Re]written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+# project. The module is, however, dual licensed under OpenSSL and
+# CRYPTOGAMS licenses depending on where you obtain it. For further
+# details see http://www.openssl.org/~appro/cryptogams/.
+# ====================================================================
+
+# "[Re]written" was achieved in two major overhauls. In 2004 BODY_*
+# functions were re-implemented to address P4 performance issue [see
+# commentary below], and in 2006 the rest was rewritten in order to
+# gain freedom to liberate licensing terms.
+
+# January, September 2004.
+#
+# It was noted that Intel IA-32 C compiler generates code which
+# performs ~30% *faster* on P4 CPU than original *hand-coded*
+# SHA1 assembler implementation. To address this problem (and
+# prove that humans are still better than machines:-), the
+# original code was overhauled, which resulted in following
+# performance changes:
+#
+# compared with original compared with Intel cc
+# assembler impl. generated code
+# Pentium -16% +48%
+# PIII/AMD +8% +16%
+# P4 +85%(!) +45%
+#
+# As you can see Pentium came out as looser:-( Yet I reckoned that
+# improvement on P4 outweights the loss and incorporate this
+# re-tuned code to 0.9.7 and later.
+# ----------------------------------------------------------------
+# <appro@fy.chalmers.se>
+
+# August 2009.
+#
+# George Spelvin has tipped that F_40_59(b,c,d) can be rewritten as
+# '(c&d) + (b&(c^d))', which allows to accumulate partial results
+# and lighten "pressure" on scratch registers. This resulted in
+# >12% performance improvement on contemporary AMD cores (with no
+# degradation on other CPUs:-). Also, the code was revised to maximize
+# "distance" between instructions producing input to 'lea' instruction
+# and the 'lea' instruction itself, which is essential for Intel Atom
+# core and resulted in ~15% improvement.
+
+# October 2010.
+#
+# Add SSSE3, Supplemental[!] SSE3, implementation. The idea behind it
+# is to offload message schedule denoted by Wt in NIST specification,
+# or Xupdate in OpenSSL source, to SIMD unit. The idea is not novel,
+# and in SSE2 context was first explored by Dean Gaudet in 2004, see
+# http://arctic.org/~dean/crypto/sha1.html. Since then several things
+# have changed that made it interesting again:
+#
+# a) XMM units became faster and wider;
+# b) instruction set became more versatile;
+# c) an important observation was made by Max Locktykhin, which made
+# it possible to reduce amount of instructions required to perform
+# the operation in question, for further details see
+# http://software.intel.com/en-us/articles/improving-the-performance-of-the-secure-hash-algorithm-1/.
+
+# April 2011.
+#
+# Add AVX code path, probably most controversial... The thing is that
+# switch to AVX alone improves performance by as little as 4% in
+# comparison to SSSE3 code path. But below result doesn't look like
+# 4% improvement... Trouble is that Sandy Bridge decodes 'ro[rl]' as
+# pair of µ-ops, and it's the additional µ-ops, two per round, that
+# make it run slower than Core2 and Westmere. But 'sh[rl]d' is decoded
+# as single µ-op by Sandy Bridge and it's replacing 'ro[rl]' with
+# equivalent 'sh[rl]d' that is responsible for the impressive 5.1
+# cycles per processed byte. But 'sh[rl]d' is not something that used
+# to be fast, nor does it appear to be fast in upcoming Bulldozer
+# [according to its optimization manual]. Which is why AVX code path
+# is guarded by *both* AVX and synthetic bit denoting Intel CPUs.
+# One can argue that it's unfair to AMD, but without 'sh[rl]d' it
+# makes no sense to keep the AVX code path. If somebody feels that
+# strongly, it's probably more appropriate to discuss possibility of
+# using vector rotate XOP on AMD...
+
+# March 2014.
+#
+# Add support for Intel SHA Extensions.
+
+######################################################################
+# Current performance is summarized in following table. Numbers are
+# CPU clock cycles spent to process single byte (less is better).
+#
+# x86 SSSE3 AVX
+# Pentium 15.7 -
+# PIII 11.5 -
+# P4 10.6 -
+# AMD K8 7.1 -
+# Core2 7.3 6.0/+22% -
+# Westmere 7.3 5.5/+33% -
+# Sandy Bridge 8.8 6.2/+40% 5.1(**)/+73%
+# Ivy Bridge 7.2 4.8/+51% 4.7(**)/+53%
+# Haswell 6.5 4.3/+51% 4.1(**)/+58%
+# Bulldozer 11.6 6.0/+92%
+# VIA Nano 10.6 7.5/+41%
+# Atom 12.5 9.3(*)/+35%
+# Silvermont 14.5 9.9(*)/+46%
+#
+# (*) Loop is 1056 instructions long and expected result is ~8.25.
+# The discrepancy is because of front-end limitations, so
+# called MS-ROM penalties, and on Silvermont even rotate's
+# limited parallelism.
+#
+# (**) As per above comment, the result is for AVX *plus* sh[rl]d.
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+push(@INC,"${dir}","${dir}../../perlasm");
+require "x86asm.pl";
+
+&asm_init($ARGV[0],"sha1-586.pl",$ARGV[$#ARGV] eq "386");
+
+$xmm=$ymm=0;
+for (@ARGV) { $xmm=1 if (/-DOPENSSL_IA32_SSE2/); }
+
+$ymm=1 if ($xmm &&
+ `$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
+ =~ /GNU assembler version ([2-9]\.[0-9]+)/ &&
+ $1>=2.19); # first version supporting AVX
+
+$ymm=1 if ($xmm && !$ymm && $ARGV[0] eq "win32n" &&
+ `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)/ &&
+ $1>=2.03); # first version supporting AVX
+
+$ymm=1 if ($xmm && !$ymm && $ARGV[0] eq "win32" &&
+ `ml 2>&1` =~ /Version ([0-9]+)\./ &&
+ $1>=10); # first version supporting AVX
+
+$ymm=1 if ($xmm && !$ymm && `$ENV{CC} -v 2>&1` =~ /(^clang version|based on LLVM) ([3-9]\.[0-9]+)/ &&
+ $2>=3.0); # first version supporting AVX
+
+$shaext=$xmm; ### set to zero if compiling for 1.0.1
+
+&external_label("OPENSSL_ia32cap_P") if ($xmm);
+
+
+$A="eax";
+$B="ebx";
+$C="ecx";
+$D="edx";
+$E="edi";
+$T="esi";
+$tmp1="ebp";
+
+@V=($A,$B,$C,$D,$E,$T);
+
+$alt=0; # 1 denotes alternative IALU implementation, which performs
+ # 8% *worse* on P4, same on Westmere and Atom, 2% better on
+ # Sandy Bridge...
+
+sub BODY_00_15
+ {
+ local($n,$a,$b,$c,$d,$e,$f)=@_;
+
+ &comment("00_15 $n");
+
+ &mov($f,$c); # f to hold F_00_19(b,c,d)
+ if ($n==0) { &mov($tmp1,$a); }
+ else { &mov($a,$tmp1); }
+ &rotl($tmp1,5); # tmp1=ROTATE(a,5)
+ &xor($f,$d);
+ &add($tmp1,$e); # tmp1+=e;
+ &mov($e,&swtmp($n%16)); # e becomes volatile and is loaded
+ # with xi, also note that e becomes
+ # f in next round...
+ &and($f,$b);
+ &rotr($b,2); # b=ROTATE(b,30)
+ &xor($f,$d); # f holds F_00_19(b,c,d)
+ &lea($tmp1,&DWP(0x5a827999,$tmp1,$e)); # tmp1+=K_00_19+xi
+
+ if ($n==15) { &mov($e,&swtmp(($n+1)%16));# pre-fetch f for next round
+ &add($f,$tmp1); } # f+=tmp1
+ else { &add($tmp1,$f); } # f becomes a in next round
+ &mov($tmp1,$a) if ($alt && $n==15);
+ }
+
+sub BODY_16_19
+ {
+ local($n,$a,$b,$c,$d,$e,$f)=@_;
+
+ &comment("16_19 $n");
+
+if ($alt) {
+ &xor($c,$d);
+ &xor($f,&swtmp(($n+2)%16)); # f to hold Xupdate(xi,xa,xb,xc,xd)
+ &and($tmp1,$c); # tmp1 to hold F_00_19(b,c,d), b&=c^d
+ &xor($f,&swtmp(($n+8)%16));
+ &xor($tmp1,$d); # tmp1=F_00_19(b,c,d)
+ &xor($f,&swtmp(($n+13)%16)); # f holds xa^xb^xc^xd
+ &rotl($f,1); # f=ROTATE(f,1)
+ &add($e,$tmp1); # e+=F_00_19(b,c,d)
+ &xor($c,$d); # restore $c
+ &mov($tmp1,$a); # b in next round
+ &rotr($b,$n==16?2:7); # b=ROTATE(b,30)
+ &mov(&swtmp($n%16),$f); # xi=f
+ &rotl($a,5); # ROTATE(a,5)
+ &lea($f,&DWP(0x5a827999,$f,$e));# f+=F_00_19(b,c,d)+e
+ &mov($e,&swtmp(($n+1)%16)); # pre-fetch f for next round
+ &add($f,$a); # f+=ROTATE(a,5)
+} else {
+ &mov($tmp1,$c); # tmp1 to hold F_00_19(b,c,d)
+ &xor($f,&swtmp(($n+2)%16)); # f to hold Xupdate(xi,xa,xb,xc,xd)
+ &xor($tmp1,$d);
+ &xor($f,&swtmp(($n+8)%16));
+ &and($tmp1,$b);
+ &xor($f,&swtmp(($n+13)%16)); # f holds xa^xb^xc^xd
+ &rotl($f,1); # f=ROTATE(f,1)
+ &xor($tmp1,$d); # tmp1=F_00_19(b,c,d)
+ &add($e,$tmp1); # e+=F_00_19(b,c,d)
+ &mov($tmp1,$a);
+ &rotr($b,2); # b=ROTATE(b,30)
+ &mov(&swtmp($n%16),$f); # xi=f
+ &rotl($tmp1,5); # ROTATE(a,5)
+ &lea($f,&DWP(0x5a827999,$f,$e));# f+=F_00_19(b,c,d)+e
+ &mov($e,&swtmp(($n+1)%16)); # pre-fetch f for next round
+ &add($f,$tmp1); # f+=ROTATE(a,5)
+}
+ }
+
+sub BODY_20_39
+ {
+ local($n,$a,$b,$c,$d,$e,$f)=@_;
+ local $K=($n<40)?0x6ed9eba1:0xca62c1d6;
+
+ &comment("20_39 $n");
+
+if ($alt) {
+ &xor($tmp1,$c); # tmp1 to hold F_20_39(b,c,d), b^=c
+ &xor($f,&swtmp(($n+2)%16)); # f to hold Xupdate(xi,xa,xb,xc,xd)
+ &xor($tmp1,$d); # tmp1 holds F_20_39(b,c,d)
+ &xor($f,&swtmp(($n+8)%16));
+ &add($e,$tmp1); # e+=F_20_39(b,c,d)
+ &xor($f,&swtmp(($n+13)%16)); # f holds xa^xb^xc^xd
+ &rotl($f,1); # f=ROTATE(f,1)
+ &mov($tmp1,$a); # b in next round
+ &rotr($b,7); # b=ROTATE(b,30)
+ &mov(&swtmp($n%16),$f) if($n<77);# xi=f
+ &rotl($a,5); # ROTATE(a,5)
+ &xor($b,$c) if($n==39);# warm up for BODY_40_59
+ &and($tmp1,$b) if($n==39);
+ &lea($f,&DWP($K,$f,$e)); # f+=e+K_XX_YY
+ &mov($e,&swtmp(($n+1)%16)) if($n<79);# pre-fetch f for next round
+ &add($f,$a); # f+=ROTATE(a,5)
+ &rotr($a,5) if ($n==79);
+} else {
+ &mov($tmp1,$b); # tmp1 to hold F_20_39(b,c,d)
+ &xor($f,&swtmp(($n+2)%16)); # f to hold Xupdate(xi,xa,xb,xc,xd)
+ &xor($tmp1,$c);
+ &xor($f,&swtmp(($n+8)%16));
+ &xor($tmp1,$d); # tmp1 holds F_20_39(b,c,d)
+ &xor($f,&swtmp(($n+13)%16)); # f holds xa^xb^xc^xd
+ &rotl($f,1); # f=ROTATE(f,1)
+ &add($e,$tmp1); # e+=F_20_39(b,c,d)
+ &rotr($b,2); # b=ROTATE(b,30)
+ &mov($tmp1,$a);
+ &rotl($tmp1,5); # ROTATE(a,5)
+ &mov(&swtmp($n%16),$f) if($n<77);# xi=f
+ &lea($f,&DWP($K,$f,$e)); # f+=e+K_XX_YY
+ &mov($e,&swtmp(($n+1)%16)) if($n<79);# pre-fetch f for next round
+ &add($f,$tmp1); # f+=ROTATE(a,5)
+}
+ }
+
+sub BODY_40_59
+ {
+ local($n,$a,$b,$c,$d,$e,$f)=@_;
+
+ &comment("40_59 $n");
+
+if ($alt) {
+ &add($e,$tmp1); # e+=b&(c^d)
+ &xor($f,&swtmp(($n+2)%16)); # f to hold Xupdate(xi,xa,xb,xc,xd)
+ &mov($tmp1,$d);
+ &xor($f,&swtmp(($n+8)%16));
+ &xor($c,$d); # restore $c
+ &xor($f,&swtmp(($n+13)%16)); # f holds xa^xb^xc^xd
+ &rotl($f,1); # f=ROTATE(f,1)
+ &and($tmp1,$c);
+ &rotr($b,7); # b=ROTATE(b,30)
+ &add($e,$tmp1); # e+=c&d
+ &mov($tmp1,$a); # b in next round
+ &mov(&swtmp($n%16),$f); # xi=f
+ &rotl($a,5); # ROTATE(a,5)
+ &xor($b,$c) if ($n<59);
+ &and($tmp1,$b) if ($n<59);# tmp1 to hold F_40_59(b,c,d)
+ &lea($f,&DWP(0x8f1bbcdc,$f,$e));# f+=K_40_59+e+(b&(c^d))
+ &mov($e,&swtmp(($n+1)%16)); # pre-fetch f for next round
+ &add($f,$a); # f+=ROTATE(a,5)
+} else {
+ &mov($tmp1,$c); # tmp1 to hold F_40_59(b,c,d)
+ &xor($f,&swtmp(($n+2)%16)); # f to hold Xupdate(xi,xa,xb,xc,xd)
+ &xor($tmp1,$d);
+ &xor($f,&swtmp(($n+8)%16));
+ &and($tmp1,$b);
+ &xor($f,&swtmp(($n+13)%16)); # f holds xa^xb^xc^xd
+ &rotl($f,1); # f=ROTATE(f,1)
+ &add($tmp1,$e); # b&(c^d)+=e
+ &rotr($b,2); # b=ROTATE(b,30)
+ &mov($e,$a); # e becomes volatile
+ &rotl($e,5); # ROTATE(a,5)
+ &mov(&swtmp($n%16),$f); # xi=f
+ &lea($f,&DWP(0x8f1bbcdc,$f,$tmp1));# f+=K_40_59+e+(b&(c^d))
+ &mov($tmp1,$c);
+ &add($f,$e); # f+=ROTATE(a,5)
+ &and($tmp1,$d);
+ &mov($e,&swtmp(($n+1)%16)); # pre-fetch f for next round
+ &add($f,$tmp1); # f+=c&d
+}
+ }
+
+&function_begin("sha1_block_data_order");
+if ($xmm) {
+ &static_label("shaext_shortcut") if ($shaext);
+ &static_label("ssse3_shortcut");
+ &static_label("avx_shortcut") if ($ymm);
+ &static_label("K_XX_XX");
+
+ &call (&label("pic_point")); # make it PIC!
+ &set_label("pic_point");
+ &blindpop($tmp1);
+ &picmeup($T,"OPENSSL_ia32cap_P",$tmp1,&label("pic_point"));
+ &lea ($tmp1,&DWP(&label("K_XX_XX")."-".&label("pic_point"),$tmp1));
+
+ &mov ($A,&DWP(0,$T));
+ &mov ($D,&DWP(4,$T));
+ &test ($D,1<<9); # check SSSE3 bit
+ &jz (&label("x86"));
+ &mov ($C,&DWP(8,$T));
+ &test ($A,1<<24); # check FXSR bit
+ &jz (&label("x86"));
+ if ($shaext) {
+ &test ($C,1<<29); # check SHA bit
+ &jnz (&label("shaext_shortcut"));
+ }
+ if ($ymm) {
+ &and ($D,1<<28); # mask AVX bit
+ &and ($A,1<<30); # mask "Intel CPU" bit
+ &or ($A,$D);
+ &cmp ($A,1<<28|1<<30);
+ &je (&label("avx_shortcut"));
+ }
+ &jmp (&label("ssse3_shortcut"));
+ &set_label("x86",16);
+}
+ &mov($tmp1,&wparam(0)); # SHA_CTX *c
+ &mov($T,&wparam(1)); # const void *input
+ &mov($A,&wparam(2)); # size_t num
+ &stack_push(16+3); # allocate X[16]
+ &shl($A,6);
+ &add($A,$T);
+ &mov(&wparam(2),$A); # pointer beyond the end of input
+ &mov($E,&DWP(16,$tmp1));# pre-load E
+ &jmp(&label("loop"));
+
+&set_label("loop",16);
+
+ # copy input chunk to X, but reversing byte order!
+ for ($i=0; $i<16; $i+=4)
+ {
+ &mov($A,&DWP(4*($i+0),$T));
+ &mov($B,&DWP(4*($i+1),$T));
+ &mov($C,&DWP(4*($i+2),$T));
+ &mov($D,&DWP(4*($i+3),$T));
+ &bswap($A);
+ &bswap($B);
+ &bswap($C);
+ &bswap($D);
+ &mov(&swtmp($i+0),$A);
+ &mov(&swtmp($i+1),$B);
+ &mov(&swtmp($i+2),$C);
+ &mov(&swtmp($i+3),$D);
+ }
+ &mov(&wparam(1),$T); # redundant in 1st spin
+
+ &mov($A,&DWP(0,$tmp1)); # load SHA_CTX
+ &mov($B,&DWP(4,$tmp1));
+ &mov($C,&DWP(8,$tmp1));
+ &mov($D,&DWP(12,$tmp1));
+ # E is pre-loaded
+
+ for($i=0;$i<16;$i++) { &BODY_00_15($i,@V); unshift(@V,pop(@V)); }
+ for(;$i<20;$i++) { &BODY_16_19($i,@V); unshift(@V,pop(@V)); }
+ for(;$i<40;$i++) { &BODY_20_39($i,@V); unshift(@V,pop(@V)); }
+ for(;$i<60;$i++) { &BODY_40_59($i,@V); unshift(@V,pop(@V)); }
+ for(;$i<80;$i++) { &BODY_20_39($i,@V); unshift(@V,pop(@V)); }
+
+ (($V[5] eq $D) and ($V[0] eq $E)) or die; # double-check
+
+ &mov($tmp1,&wparam(0)); # re-load SHA_CTX*
+ &mov($D,&wparam(1)); # D is last "T" and is discarded
+
+ &add($E,&DWP(0,$tmp1)); # E is last "A"...
+ &add($T,&DWP(4,$tmp1));
+ &add($A,&DWP(8,$tmp1));
+ &add($B,&DWP(12,$tmp1));
+ &add($C,&DWP(16,$tmp1));
+
+ &mov(&DWP(0,$tmp1),$E); # update SHA_CTX
+ &add($D,64); # advance input pointer
+ &mov(&DWP(4,$tmp1),$T);
+ &cmp($D,&wparam(2)); # have we reached the end yet?
+ &mov(&DWP(8,$tmp1),$A);
+ &mov($E,$C); # C is last "E" which needs to be "pre-loaded"
+ &mov(&DWP(12,$tmp1),$B);
+ &mov($T,$D); # input pointer
+ &mov(&DWP(16,$tmp1),$C);
+ &jb(&label("loop"));
+
+ &stack_pop(16+3);
+&function_end("sha1_block_data_order");
+
+if ($xmm) {
+if ($shaext) {
+######################################################################
+# Intel SHA Extensions implementation of SHA1 update function.
+#
+my ($ctx,$inp,$num)=("edi","esi","ecx");
+my ($ABCD,$E,$E_,$BSWAP)=map("xmm$_",(0..3));
+my @MSG=map("xmm$_",(4..7));
+
+sub sha1rnds4 {
+ my ($dst,$src,$imm)=@_;
+ if ("$dst:$src" =~ /xmm([0-7]):xmm([0-7])/)
+ { &data_byte(0x0f,0x3a,0xcc,0xc0|($1<<3)|$2,$imm); }
+}
+sub sha1op38 {
+ my ($opcodelet,$dst,$src)=@_;
+ if ("$dst:$src" =~ /xmm([0-7]):xmm([0-7])/)
+ { &data_byte(0x0f,0x38,$opcodelet,0xc0|($1<<3)|$2); }
+}
+sub sha1nexte { sha1op38(0xc8,@_); }
+sub sha1msg1 { sha1op38(0xc9,@_); }
+sub sha1msg2 { sha1op38(0xca,@_); }
+
+&function_begin("_sha1_block_data_order_shaext");
+ &call (&label("pic_point")); # make it PIC!
+ &set_label("pic_point");
+ &blindpop($tmp1);
+ &lea ($tmp1,&DWP(&label("K_XX_XX")."-".&label("pic_point"),$tmp1));
+&set_label("shaext_shortcut");
+ &mov ($ctx,&wparam(0));
+ &mov ("ebx","esp");
+ &mov ($inp,&wparam(1));
+ &mov ($num,&wparam(2));
+ &sub ("esp",32);
+
+ &movdqu ($ABCD,&QWP(0,$ctx));
+ &movd ($E,&QWP(16,$ctx));
+ &and ("esp",-32);
+ &movdqa ($BSWAP,&QWP(0x50,$tmp1)); # byte-n-word swap
+
+ &movdqu (@MSG[0],&QWP(0,$inp));
+ &pshufd ($ABCD,$ABCD,0b00011011); # flip word order
+ &movdqu (@MSG[1],&QWP(0x10,$inp));
+ &pshufd ($E,$E,0b00011011); # flip word order
+ &movdqu (@MSG[2],&QWP(0x20,$inp));
+ &pshufb (@MSG[0],$BSWAP);
+ &movdqu (@MSG[3],&QWP(0x30,$inp));
+ &pshufb (@MSG[1],$BSWAP);
+ &pshufb (@MSG[2],$BSWAP);
+ &pshufb (@MSG[3],$BSWAP);
+ &jmp (&label("loop_shaext"));
+
+&set_label("loop_shaext",16);
+ &dec ($num);
+ &lea ("eax",&DWP(0x40,$inp));
+ &movdqa (&QWP(0,"esp"),$E); # offload $E
+ &paddd ($E,@MSG[0]);
+ &cmovne ($inp,"eax");
+ &movdqa (&QWP(16,"esp"),$ABCD); # offload $ABCD
+
+for($i=0;$i<20-4;$i+=2) {
+ &sha1msg1 (@MSG[0],@MSG[1]);
+ &movdqa ($E_,$ABCD);
+ &sha1rnds4 ($ABCD,$E,int($i/5)); # 0-3...
+ &sha1nexte ($E_,@MSG[1]);
+ &pxor (@MSG[0],@MSG[2]);
+ &sha1msg1 (@MSG[1],@MSG[2]);
+ &sha1msg2 (@MSG[0],@MSG[3]);
+
+ &movdqa ($E,$ABCD);
+ &sha1rnds4 ($ABCD,$E_,int(($i+1)/5));
+ &sha1nexte ($E,@MSG[2]);
+ &pxor (@MSG[1],@MSG[3]);
+ &sha1msg2 (@MSG[1],@MSG[0]);
+
+ push(@MSG,shift(@MSG)); push(@MSG,shift(@MSG));
+}
+ &movdqu (@MSG[0],&QWP(0,$inp));
+ &movdqa ($E_,$ABCD);
+ &sha1rnds4 ($ABCD,$E,3); # 64-67
+ &sha1nexte ($E_,@MSG[1]);
+ &movdqu (@MSG[1],&QWP(0x10,$inp));
+ &pshufb (@MSG[0],$BSWAP);
+
+ &movdqa ($E,$ABCD);
+ &sha1rnds4 ($ABCD,$E_,3); # 68-71
+ &sha1nexte ($E,@MSG[2]);
+ &movdqu (@MSG[2],&QWP(0x20,$inp));
+ &pshufb (@MSG[1],$BSWAP);
+
+ &movdqa ($E_,$ABCD);
+ &sha1rnds4 ($ABCD,$E,3); # 72-75
+ &sha1nexte ($E_,@MSG[3]);
+ &movdqu (@MSG[3],&QWP(0x30,$inp));
+ &pshufb (@MSG[2],$BSWAP);
+
+ &movdqa ($E,$ABCD);
+ &sha1rnds4 ($ABCD,$E_,3); # 76-79
+ &movdqa ($E_,&QWP(0,"esp"));
+ &pshufb (@MSG[3],$BSWAP);
+ &sha1nexte ($E,$E_);
+ &paddd ($ABCD,&QWP(16,"esp"));
+
+ &jnz (&label("loop_shaext"));
+
+ &pshufd ($ABCD,$ABCD,0b00011011);
+ &pshufd ($E,$E,0b00011011);
+ &movdqu (&QWP(0,$ctx),$ABCD)
+ &movd (&DWP(16,$ctx),$E);
+ &mov ("esp","ebx");
+&function_end("_sha1_block_data_order_shaext");
+}
+######################################################################
+# The SSSE3 implementation.
+#
+# %xmm[0-7] are used as ring @X[] buffer containing quadruples of last
+# 32 elements of the message schedule or Xupdate outputs. First 4
+# quadruples are simply byte-swapped input, next 4 are calculated
+# according to method originally suggested by Dean Gaudet (modulo
+# being implemented in SSSE3). Once 8 quadruples or 32 elements are
+# collected, it switches to routine proposed by Max Locktyukhin.
+#
+# Calculations inevitably require temporary reqisters, and there are
+# no %xmm registers left to spare. For this reason part of the ring
+# buffer, X[2..4] to be specific, is offloaded to 3 quadriples ring
+# buffer on the stack. Keep in mind that X[2] is alias X[-6], X[3] -
+# X[-5], and X[4] - X[-4]...
+#
+# Another notable optimization is aggressive stack frame compression
+# aiming to minimize amount of 9-byte instructions...
+#
+# Yet another notable optimization is "jumping" $B variable. It means
+# that there is no register permanently allocated for $B value. This
+# allowed to eliminate one instruction from body_20_39...
+#
+my $Xi=4; # 4xSIMD Xupdate round, start pre-seeded
+my @X=map("xmm$_",(4..7,0..3)); # pre-seeded for $Xi=4
+my @V=($A,$B,$C,$D,$E);
+my $j=0; # hash round
+my $rx=0;
+my @T=($T,$tmp1);
+my $inp;
+
+my $_rol=sub { &rol(@_) };
+my $_ror=sub { &ror(@_) };
+
+&function_begin("_sha1_block_data_order_ssse3");
+ &call (&label("pic_point")); # make it PIC!
+ &set_label("pic_point");
+ &blindpop($tmp1);
+ &lea ($tmp1,&DWP(&label("K_XX_XX")."-".&label("pic_point"),$tmp1));
+&set_label("ssse3_shortcut");
+
+ &movdqa (@X[3],&QWP(0,$tmp1)); # K_00_19
+ &movdqa (@X[4],&QWP(16,$tmp1)); # K_20_39
+ &movdqa (@X[5],&QWP(32,$tmp1)); # K_40_59
+ &movdqa (@X[6],&QWP(48,$tmp1)); # K_60_79
+ &movdqa (@X[2],&QWP(64,$tmp1)); # pbswap mask
+
+ &mov ($E,&wparam(0)); # load argument block
+ &mov ($inp=@T[1],&wparam(1));
+ &mov ($D,&wparam(2));
+ &mov (@T[0],"esp");
+
+ # stack frame layout
+ #
+ # +0 X[0]+K X[1]+K X[2]+K X[3]+K # XMM->IALU xfer area
+ # X[4]+K X[5]+K X[6]+K X[7]+K
+ # X[8]+K X[9]+K X[10]+K X[11]+K
+ # X[12]+K X[13]+K X[14]+K X[15]+K
+ #
+ # +64 X[0] X[1] X[2] X[3] # XMM->XMM backtrace area
+ # X[4] X[5] X[6] X[7]
+ # X[8] X[9] X[10] X[11] # even borrowed for K_00_19
+ #
+ # +112 K_20_39 K_20_39 K_20_39 K_20_39 # constants
+ # K_40_59 K_40_59 K_40_59 K_40_59
+ # K_60_79 K_60_79 K_60_79 K_60_79
+ # K_00_19 K_00_19 K_00_19 K_00_19
+ # pbswap mask
+ #
+ # +192 ctx # argument block
+ # +196 inp
+ # +200 end
+ # +204 esp
+ &sub ("esp",208);
+ &and ("esp",-64);
+
+ &movdqa (&QWP(112+0,"esp"),@X[4]); # copy constants
+ &movdqa (&QWP(112+16,"esp"),@X[5]);
+ &movdqa (&QWP(112+32,"esp"),@X[6]);
+ &shl ($D,6); # len*64
+ &movdqa (&QWP(112+48,"esp"),@X[3]);
+ &add ($D,$inp); # end of input
+ &movdqa (&QWP(112+64,"esp"),@X[2]);
+ &add ($inp,64);
+ &mov (&DWP(192+0,"esp"),$E); # save argument block
+ &mov (&DWP(192+4,"esp"),$inp);
+ &mov (&DWP(192+8,"esp"),$D);
+ &mov (&DWP(192+12,"esp"),@T[0]); # save original %esp
+
+ &mov ($A,&DWP(0,$E)); # load context
+ &mov ($B,&DWP(4,$E));
+ &mov ($C,&DWP(8,$E));
+ &mov ($D,&DWP(12,$E));
+ &mov ($E,&DWP(16,$E));
+ &mov (@T[0],$B); # magic seed
+
+ &movdqu (@X[-4&7],&QWP(-64,$inp)); # load input to %xmm[0-3]
+ &movdqu (@X[-3&7],&QWP(-48,$inp));
+ &movdqu (@X[-2&7],&QWP(-32,$inp));
+ &movdqu (@X[-1&7],&QWP(-16,$inp));
+ &pshufb (@X[-4&7],@X[2]); # byte swap
+ &pshufb (@X[-3&7],@X[2]);
+ &pshufb (@X[-2&7],@X[2]);
+ &movdqa (&QWP(112-16,"esp"),@X[3]); # borrow last backtrace slot
+ &pshufb (@X[-1&7],@X[2]);
+ &paddd (@X[-4&7],@X[3]); # add K_00_19
+ &paddd (@X[-3&7],@X[3]);
+ &paddd (@X[-2&7],@X[3]);
+ &movdqa (&QWP(0,"esp"),@X[-4&7]); # X[]+K xfer to IALU
+ &psubd (@X[-4&7],@X[3]); # restore X[]
+ &movdqa (&QWP(0+16,"esp"),@X[-3&7]);
+ &psubd (@X[-3&7],@X[3]);
+ &movdqa (&QWP(0+32,"esp"),@X[-2&7]);
+ &mov (@T[1],$C);
+ &psubd (@X[-2&7],@X[3]);
+ &xor (@T[1],$D);
+ &pshufd (@X[0],@X[-4&7],0xee); # was &movdqa (@X[0],@X[-3&7]);
+ &and (@T[0],@T[1]);
+ &jmp (&label("loop"));
+
+######################################################################
+# SSE instruction sequence is first broken to groups of indepentent
+# instructions, independent in respect to their inputs and shifter
+# (not all architectures have more than one). Then IALU instructions
+# are "knitted in" between the SSE groups. Distance is maintained for
+# SSE latency of 2 in hope that it fits better upcoming AMD Bulldozer
+# [which allegedly also implements SSSE3]...
+#
+# Temporary registers usage. X[2] is volatile at the entry and at the
+# end is restored from backtrace ring buffer. X[3] is expected to
+# contain current K_XX_XX constant and is used to caclulate X[-1]+K
+# from previous round, it becomes volatile the moment the value is
+# saved to stack for transfer to IALU. X[4] becomes volatile whenever
+# X[-4] is accumulated and offloaded to backtrace ring buffer, at the
+# end it is loaded with next K_XX_XX [which becomes X[3] in next
+# round]...
+#
+sub Xupdate_ssse3_16_31() # recall that $Xi starts wtih 4
+{ use integer;
+ my $body = shift;
+ my @insns = (&$body,&$body,&$body,&$body); # 40 instructions
+ my ($a,$b,$c,$d,$e);
+
+ eval(shift(@insns)); # ror
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &punpcklqdq(@X[0],@X[-3&7]); # compose "X[-14]" in "X[0]", was &palignr(@X[0],@X[-4&7],8);
+ &movdqa (@X[2],@X[-1&7]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ &paddd (@X[3],@X[-1&7]);
+ &movdqa (&QWP(64+16*(($Xi-4)%3),"esp"),@X[-4&7]);# save X[] to backtrace buffer
+ eval(shift(@insns)); # rol
+ eval(shift(@insns));
+ &psrldq (@X[2],4); # "X[-3]", 3 dwords
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &pxor (@X[0],@X[-4&7]); # "X[0]"^="X[-16]"
+ eval(shift(@insns));
+ eval(shift(@insns)); # ror
+
+ &pxor (@X[2],@X[-2&7]); # "X[-3]"^"X[-8]"
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ &pxor (@X[0],@X[2]); # "X[0]"^="X[-3]"^"X[-8]"
+ eval(shift(@insns));
+ eval(shift(@insns)); # rol
+ &movdqa (&QWP(0+16*(($Xi-1)&3),"esp"),@X[3]); # X[]+K xfer to IALU
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ &movdqa (@X[4],@X[0]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns)); # ror
+ &movdqa (@X[2],@X[0]);
+ eval(shift(@insns));
+
+ &pslldq (@X[4],12); # "X[0]"<<96, extract one dword
+ &paddd (@X[0],@X[0]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ &psrld (@X[2],31);
+ eval(shift(@insns));
+ eval(shift(@insns)); # rol
+ &movdqa (@X[3],@X[4]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ &psrld (@X[4],30);
+ eval(shift(@insns));
+ eval(shift(@insns)); # ror
+ &por (@X[0],@X[2]); # "X[0]"<<<=1
+ eval(shift(@insns));
+ &movdqa (@X[2],&QWP(64+16*(($Xi-6)%3),"esp")) if ($Xi>5); # restore X[] from backtrace buffer
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ &pslld (@X[3],2);
+ eval(shift(@insns));
+ eval(shift(@insns)); # rol
+ &pxor (@X[0],@X[4]);
+ &movdqa (@X[4],&QWP(112-16+16*(($Xi)/5),"esp")); # K_XX_XX
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ &pxor (@X[0],@X[3]); # "X[0]"^=("X[0]"<<96)<<<2
+ &pshufd (@X[1],@X[-3&7],0xee) if ($Xi<7); # was &movdqa (@X[1],@X[-2&7])
+ &pshufd (@X[3],@X[-1&7],0xee) if ($Xi==7);
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ foreach (@insns) { eval; } # remaining instructions [if any]
+
+ $Xi++; push(@X,shift(@X)); # "rotate" X[]
+}
+
+sub Xupdate_ssse3_32_79()
+{ use integer;
+ my $body = shift;
+ my @insns = (&$body,&$body,&$body,&$body); # 32 to 44 instructions
+ my ($a,$b,$c,$d,$e);
+
+ eval(shift(@insns)); # body_20_39
+ &pxor (@X[0],@X[-4&7]); # "X[0]"="X[-32]"^"X[-16]"
+ &punpcklqdq(@X[2],@X[-1&7]); # compose "X[-6]", was &palignr(@X[2],@X[-2&7],8)
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns)); # rol
+
+ &pxor (@X[0],@X[-7&7]); # "X[0]"^="X[-28]"
+ &movdqa (&QWP(64+16*(($Xi-4)%3),"esp"),@X[-4&7]); # save X[] to backtrace buffer
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns)) if (@insns[0] =~ /_rol/);
+ if ($Xi%5) {
+ &movdqa (@X[4],@X[3]); # "perpetuate" K_XX_XX...
+ } else { # ... or load next one
+ &movdqa (@X[4],&QWP(112-16+16*($Xi/5),"esp"));
+ }
+ eval(shift(@insns)); # ror
+ &paddd (@X[3],@X[-1&7]);
+ eval(shift(@insns));
+
+ &pxor (@X[0],@X[2]); # "X[0]"^="X[-6]"
+ eval(shift(@insns)); # body_20_39
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns)); # rol
+
+ &movdqa (@X[2],@X[0]);
+ &movdqa (&QWP(0+16*(($Xi-1)&3),"esp"),@X[3]); # X[]+K xfer to IALU
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns)); # ror
+ eval(shift(@insns));
+ eval(shift(@insns)) if (@insns[0] =~ /_rol/);
+
+ &pslld (@X[0],2);
+ eval(shift(@insns)); # body_20_39
+ eval(shift(@insns));
+ &psrld (@X[2],30);
+ eval(shift(@insns));
+ eval(shift(@insns)); # rol
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns)); # ror
+ eval(shift(@insns));
+ eval(shift(@insns)) if (@insns[1] =~ /_rol/);
+ eval(shift(@insns)) if (@insns[0] =~ /_rol/);
+
+ &por (@X[0],@X[2]); # "X[0]"<<<=2
+ eval(shift(@insns)); # body_20_39
+ eval(shift(@insns));
+ &movdqa (@X[2],&QWP(64+16*(($Xi-6)%3),"esp")) if($Xi<19); # restore X[] from backtrace buffer
+ eval(shift(@insns));
+ eval(shift(@insns)); # rol
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns)); # ror
+ &pshufd (@X[3],@X[-1],0xee) if ($Xi<19); # was &movdqa (@X[3],@X[0])
+ eval(shift(@insns));
+
+ foreach (@insns) { eval; } # remaining instructions
+
+ $Xi++; push(@X,shift(@X)); # "rotate" X[]
+}
+
+sub Xuplast_ssse3_80()
+{ use integer;
+ my $body = shift;
+ my @insns = (&$body,&$body,&$body,&$body); # 32 instructions
+ my ($a,$b,$c,$d,$e);
+
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &paddd (@X[3],@X[-1&7]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ &movdqa (&QWP(0+16*(($Xi-1)&3),"esp"),@X[3]); # X[]+K xfer IALU
+
+ foreach (@insns) { eval; } # remaining instructions
+
+ &mov ($inp=@T[1],&DWP(192+4,"esp"));
+ &cmp ($inp,&DWP(192+8,"esp"));
+ &je (&label("done"));
+
+ &movdqa (@X[3],&QWP(112+48,"esp")); # K_00_19
+ &movdqa (@X[2],&QWP(112+64,"esp")); # pbswap mask
+ &movdqu (@X[-4&7],&QWP(0,$inp)); # load input
+ &movdqu (@X[-3&7],&QWP(16,$inp));
+ &movdqu (@X[-2&7],&QWP(32,$inp));
+ &movdqu (@X[-1&7],&QWP(48,$inp));
+ &add ($inp,64);
+ &pshufb (@X[-4&7],@X[2]); # byte swap
+ &mov (&DWP(192+4,"esp"),$inp);
+ &movdqa (&QWP(112-16,"esp"),@X[3]); # borrow last backtrace slot
+
+ $Xi=0;
+}
+
+sub Xloop_ssse3()
+{ use integer;
+ my $body = shift;
+ my @insns = (&$body,&$body,&$body,&$body); # 32 instructions
+ my ($a,$b,$c,$d,$e);
+
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &pshufb (@X[($Xi-3)&7],@X[2]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &paddd (@X[($Xi-4)&7],@X[3]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &movdqa (&QWP(0+16*$Xi,"esp"),@X[($Xi-4)&7]); # X[]+K xfer to IALU
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &psubd (@X[($Xi-4)&7],@X[3]);
+
+ foreach (@insns) { eval; }
+ $Xi++;
+}
+
+sub Xtail_ssse3()
+{ use integer;
+ my $body = shift;
+ my @insns = (&$body,&$body,&$body,&$body); # 32 instructions
+ my ($a,$b,$c,$d,$e);
+
+ foreach (@insns) { eval; }
+}
+
+sub body_00_19 () { # ((c^d)&b)^d
+ # on start @T[0]=(c^d)&b
+ return &body_20_39() if ($rx==19); $rx++;
+ (
+ '($a,$b,$c,$d,$e)=@V;'.
+ '&$_ror ($b,$j?7:2);', # $b>>>2
+ '&xor (@T[0],$d);',
+ '&mov (@T[1],$a);', # $b in next round
+
+ '&add ($e,&DWP(4*($j&15),"esp"));', # X[]+K xfer
+ '&xor ($b,$c);', # $c^$d for next round
+
+ '&$_rol ($a,5);',
+ '&add ($e,@T[0]);',
+ '&and (@T[1],$b);', # ($b&($c^$d)) for next round
+
+ '&xor ($b,$c);', # restore $b
+ '&add ($e,$a);' .'$j++; unshift(@V,pop(@V)); unshift(@T,pop(@T));'
+ );
+}
+
+sub body_20_39 () { # b^d^c
+ # on entry @T[0]=b^d
+ return &body_40_59() if ($rx==39); $rx++;
+ (
+ '($a,$b,$c,$d,$e)=@V;'.
+ '&add ($e,&DWP(4*($j&15),"esp"));', # X[]+K xfer
+ '&xor (@T[0],$d) if($j==19);'.
+ '&xor (@T[0],$c) if($j> 19);', # ($b^$d^$c)
+ '&mov (@T[1],$a);', # $b in next round
+
+ '&$_rol ($a,5);',
+ '&add ($e,@T[0]);',
+ '&xor (@T[1],$c) if ($j< 79);', # $b^$d for next round
+
+ '&$_ror ($b,7);', # $b>>>2
+ '&add ($e,$a);' .'$j++; unshift(@V,pop(@V)); unshift(@T,pop(@T));'
+ );
+}
+
+sub body_40_59 () { # ((b^c)&(c^d))^c
+ # on entry @T[0]=(b^c), (c^=d)
+ $rx++;
+ (
+ '($a,$b,$c,$d,$e)=@V;'.
+ '&add ($e,&DWP(4*($j&15),"esp"));', # X[]+K xfer
+ '&and (@T[0],$c) if ($j>=40);', # (b^c)&(c^d)
+ '&xor ($c,$d) if ($j>=40);', # restore $c
+
+ '&$_ror ($b,7);', # $b>>>2
+ '&mov (@T[1],$a);', # $b for next round
+ '&xor (@T[0],$c);',
+
+ '&$_rol ($a,5);',
+ '&add ($e,@T[0]);',
+ '&xor (@T[1],$c) if ($j==59);'.
+ '&xor (@T[1],$b) if ($j< 59);', # b^c for next round
+
+ '&xor ($b,$c) if ($j< 59);', # c^d for next round
+ '&add ($e,$a);' .'$j++; unshift(@V,pop(@V)); unshift(@T,pop(@T));'
+ );
+}
+######
+sub bodyx_00_19 () { # ((c^d)&b)^d
+ # on start @T[0]=(b&c)^(~b&d), $e+=X[]+K
+ return &bodyx_20_39() if ($rx==19); $rx++;
+ (
+ '($a,$b,$c,$d,$e)=@V;'.
+
+ '&rorx ($b,$b,2) if ($j==0);'. # $b>>>2
+ '&rorx ($b,@T[1],7) if ($j!=0);', # $b>>>2
+ '&lea ($e,&DWP(0,$e,@T[0]));',
+ '&rorx (@T[0],$a,5);',
+
+ '&andn (@T[1],$a,$c);',
+ '&and ($a,$b)',
+ '&add ($d,&DWP(4*(($j+1)&15),"esp"));', # X[]+K xfer
+
+ '&xor (@T[1],$a)',
+ '&add ($e,@T[0]);' .'$j++; unshift(@V,pop(@V)); unshift(@T,pop(@T));'
+ );
+}
+
+sub bodyx_20_39 () { # b^d^c
+ # on start $b=b^c^d
+ return &bodyx_40_59() if ($rx==39); $rx++;
+ (
+ '($a,$b,$c,$d,$e)=@V;'.
+
+ '&add ($e,($j==19?@T[0]:$b))',
+ '&rorx ($b,@T[1],7);', # $b>>>2
+ '&rorx (@T[0],$a,5);',
+
+ '&xor ($a,$b) if ($j<79);',
+ '&add ($d,&DWP(4*(($j+1)&15),"esp")) if ($j<79);', # X[]+K xfer
+ '&xor ($a,$c) if ($j<79);',
+ '&add ($e,@T[0]);' .'$j++; unshift(@V,pop(@V)); unshift(@T,pop(@T));'
+ );
+}
+
+sub bodyx_40_59 () { # ((b^c)&(c^d))^c
+ # on start $b=((b^c)&(c^d))^c
+ return &bodyx_20_39() if ($rx==59); $rx++;
+ (
+ '($a,$b,$c,$d,$e)=@V;'.
+
+ '&rorx (@T[0],$a,5)',
+ '&lea ($e,&DWP(0,$e,$b))',
+ '&rorx ($b,@T[1],7)', # $b>>>2
+ '&add ($d,&DWP(4*(($j+1)&15),"esp"))', # X[]+K xfer
+
+ '&mov (@T[1],$c)',
+ '&xor ($a,$b)', # b^c for next round
+ '&xor (@T[1],$b)', # c^d for next round
+
+ '&and ($a,@T[1])',
+ '&add ($e,@T[0])',
+ '&xor ($a,$b)' .'$j++; unshift(@V,pop(@V)); unshift(@T,pop(@T));'
+ );
+}
+
+&set_label("loop",16);
+ &Xupdate_ssse3_16_31(\&body_00_19);
+ &Xupdate_ssse3_16_31(\&body_00_19);
+ &Xupdate_ssse3_16_31(\&body_00_19);
+ &Xupdate_ssse3_16_31(\&body_00_19);
+ &Xupdate_ssse3_32_79(\&body_00_19);
+ &Xupdate_ssse3_32_79(\&body_20_39);
+ &Xupdate_ssse3_32_79(\&body_20_39);
+ &Xupdate_ssse3_32_79(\&body_20_39);
+ &Xupdate_ssse3_32_79(\&body_20_39);
+ &Xupdate_ssse3_32_79(\&body_20_39);
+ &Xupdate_ssse3_32_79(\&body_40_59);
+ &Xupdate_ssse3_32_79(\&body_40_59);
+ &Xupdate_ssse3_32_79(\&body_40_59);
+ &Xupdate_ssse3_32_79(\&body_40_59);
+ &Xupdate_ssse3_32_79(\&body_40_59);
+ &Xupdate_ssse3_32_79(\&body_20_39);
+ &Xuplast_ssse3_80(\&body_20_39); # can jump to "done"
+
+ $saved_j=$j; @saved_V=@V;
+
+ &Xloop_ssse3(\&body_20_39);
+ &Xloop_ssse3(\&body_20_39);
+ &Xloop_ssse3(\&body_20_39);
+
+ &mov (@T[1],&DWP(192,"esp")); # update context
+ &add ($A,&DWP(0,@T[1]));
+ &add (@T[0],&DWP(4,@T[1])); # $b
+ &add ($C,&DWP(8,@T[1]));
+ &mov (&DWP(0,@T[1]),$A);
+ &add ($D,&DWP(12,@T[1]));
+ &mov (&DWP(4,@T[1]),@T[0]);
+ &add ($E,&DWP(16,@T[1]));
+ &mov (&DWP(8,@T[1]),$C);
+ &mov ($B,$C);
+ &mov (&DWP(12,@T[1]),$D);
+ &xor ($B,$D);
+ &mov (&DWP(16,@T[1]),$E);
+ &mov (@T[1],@T[0]);
+ &pshufd (@X[0],@X[-4&7],0xee); # was &movdqa (@X[0],@X[-3&7]);
+ &and (@T[0],$B);
+ &mov ($B,$T[1]);
+
+ &jmp (&label("loop"));
+
+&set_label("done",16); $j=$saved_j; @V=@saved_V;
+
+ &Xtail_ssse3(\&body_20_39);
+ &Xtail_ssse3(\&body_20_39);
+ &Xtail_ssse3(\&body_20_39);
+
+ &mov (@T[1],&DWP(192,"esp")); # update context
+ &add ($A,&DWP(0,@T[1]));
+ &mov ("esp",&DWP(192+12,"esp")); # restore %esp
+ &add (@T[0],&DWP(4,@T[1])); # $b
+ &add ($C,&DWP(8,@T[1]));
+ &mov (&DWP(0,@T[1]),$A);
+ &add ($D,&DWP(12,@T[1]));
+ &mov (&DWP(4,@T[1]),@T[0]);
+ &add ($E,&DWP(16,@T[1]));
+ &mov (&DWP(8,@T[1]),$C);
+ &mov (&DWP(12,@T[1]),$D);
+ &mov (&DWP(16,@T[1]),$E);
+
+&function_end("_sha1_block_data_order_ssse3");
+
+$rx=0; # reset
+
+if ($ymm) {
+my $Xi=4; # 4xSIMD Xupdate round, start pre-seeded
+my @X=map("xmm$_",(4..7,0..3)); # pre-seeded for $Xi=4
+my @V=($A,$B,$C,$D,$E);
+my $j=0; # hash round
+my @T=($T,$tmp1);
+my $inp;
+
+my $_rol=sub { &shld(@_[0],@_) };
+my $_ror=sub { &shrd(@_[0],@_) };
+
+&function_begin("_sha1_block_data_order_avx");
+ &call (&label("pic_point")); # make it PIC!
+ &set_label("pic_point");
+ &blindpop($tmp1);
+ &lea ($tmp1,&DWP(&label("K_XX_XX")."-".&label("pic_point"),$tmp1));
+&set_label("avx_shortcut");
+ &vzeroall();
+
+ &vmovdqa(@X[3],&QWP(0,$tmp1)); # K_00_19
+ &vmovdqa(@X[4],&QWP(16,$tmp1)); # K_20_39
+ &vmovdqa(@X[5],&QWP(32,$tmp1)); # K_40_59
+ &vmovdqa(@X[6],&QWP(48,$tmp1)); # K_60_79
+ &vmovdqa(@X[2],&QWP(64,$tmp1)); # pbswap mask
+
+ &mov ($E,&wparam(0)); # load argument block
+ &mov ($inp=@T[1],&wparam(1));
+ &mov ($D,&wparam(2));
+ &mov (@T[0],"esp");
+
+ # stack frame layout
+ #
+ # +0 X[0]+K X[1]+K X[2]+K X[3]+K # XMM->IALU xfer area
+ # X[4]+K X[5]+K X[6]+K X[7]+K
+ # X[8]+K X[9]+K X[10]+K X[11]+K
+ # X[12]+K X[13]+K X[14]+K X[15]+K
+ #
+ # +64 X[0] X[1] X[2] X[3] # XMM->XMM backtrace area
+ # X[4] X[5] X[6] X[7]
+ # X[8] X[9] X[10] X[11] # even borrowed for K_00_19
+ #
+ # +112 K_20_39 K_20_39 K_20_39 K_20_39 # constants
+ # K_40_59 K_40_59 K_40_59 K_40_59
+ # K_60_79 K_60_79 K_60_79 K_60_79
+ # K_00_19 K_00_19 K_00_19 K_00_19
+ # pbswap mask
+ #
+ # +192 ctx # argument block
+ # +196 inp
+ # +200 end
+ # +204 esp
+ &sub ("esp",208);
+ &and ("esp",-64);
+
+ &vmovdqa(&QWP(112+0,"esp"),@X[4]); # copy constants
+ &vmovdqa(&QWP(112+16,"esp"),@X[5]);
+ &vmovdqa(&QWP(112+32,"esp"),@X[6]);
+ &shl ($D,6); # len*64
+ &vmovdqa(&QWP(112+48,"esp"),@X[3]);
+ &add ($D,$inp); # end of input
+ &vmovdqa(&QWP(112+64,"esp"),@X[2]);
+ &add ($inp,64);
+ &mov (&DWP(192+0,"esp"),$E); # save argument block
+ &mov (&DWP(192+4,"esp"),$inp);
+ &mov (&DWP(192+8,"esp"),$D);
+ &mov (&DWP(192+12,"esp"),@T[0]); # save original %esp
+
+ &mov ($A,&DWP(0,$E)); # load context
+ &mov ($B,&DWP(4,$E));
+ &mov ($C,&DWP(8,$E));
+ &mov ($D,&DWP(12,$E));
+ &mov ($E,&DWP(16,$E));
+ &mov (@T[0],$B); # magic seed
+
+ &vmovdqu(@X[-4&7],&QWP(-64,$inp)); # load input to %xmm[0-3]
+ &vmovdqu(@X[-3&7],&QWP(-48,$inp));
+ &vmovdqu(@X[-2&7],&QWP(-32,$inp));
+ &vmovdqu(@X[-1&7],&QWP(-16,$inp));
+ &vpshufb(@X[-4&7],@X[-4&7],@X[2]); # byte swap
+ &vpshufb(@X[-3&7],@X[-3&7],@X[2]);
+ &vpshufb(@X[-2&7],@X[-2&7],@X[2]);
+ &vmovdqa(&QWP(112-16,"esp"),@X[3]); # borrow last backtrace slot
+ &vpshufb(@X[-1&7],@X[-1&7],@X[2]);
+ &vpaddd (@X[0],@X[-4&7],@X[3]); # add K_00_19
+ &vpaddd (@X[1],@X[-3&7],@X[3]);
+ &vpaddd (@X[2],@X[-2&7],@X[3]);
+ &vmovdqa(&QWP(0,"esp"),@X[0]); # X[]+K xfer to IALU
+ &mov (@T[1],$C);
+ &vmovdqa(&QWP(0+16,"esp"),@X[1]);
+ &xor (@T[1],$D);
+ &vmovdqa(&QWP(0+32,"esp"),@X[2]);
+ &and (@T[0],@T[1]);
+ &jmp (&label("loop"));
+
+sub Xupdate_avx_16_31() # recall that $Xi starts wtih 4
+{ use integer;
+ my $body = shift;
+ my @insns = (&$body,&$body,&$body,&$body); # 40 instructions
+ my ($a,$b,$c,$d,$e);
+
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vpalignr(@X[0],@X[-3&7],@X[-4&7],8); # compose "X[-14]" in "X[0]"
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ &vpaddd (@X[3],@X[3],@X[-1&7]);
+ &vmovdqa (&QWP(64+16*(($Xi-4)%3),"esp"),@X[-4&7]);# save X[] to backtrace buffer
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vpsrldq(@X[2],@X[-1&7],4); # "X[-3]", 3 dwords
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vpxor (@X[0],@X[0],@X[-4&7]); # "X[0]"^="X[-16]"
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ &vpxor (@X[2],@X[2],@X[-2&7]); # "X[-3]"^"X[-8]"
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vmovdqa (&QWP(0+16*(($Xi-1)&3),"esp"),@X[3]); # X[]+K xfer to IALU
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ &vpxor (@X[0],@X[0],@X[2]); # "X[0]"^="X[-3]"^"X[-8]"
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ &vpsrld (@X[2],@X[0],31);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ &vpslldq(@X[4],@X[0],12); # "X[0]"<<96, extract one dword
+ &vpaddd (@X[0],@X[0],@X[0]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ &vpsrld (@X[3],@X[4],30);
+ &vpor (@X[0],@X[0],@X[2]); # "X[0]"<<<=1
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ &vpslld (@X[4],@X[4],2);
+ &vmovdqa (@X[2],&QWP(64+16*(($Xi-6)%3),"esp")) if ($Xi>5); # restore X[] from backtrace buffer
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vpxor (@X[0],@X[0],@X[3]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ &vpxor (@X[0],@X[0],@X[4]); # "X[0]"^=("X[0]"<<96)<<<2
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vmovdqa (@X[4],&QWP(112-16+16*(($Xi)/5),"esp")); # K_XX_XX
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ foreach (@insns) { eval; } # remaining instructions [if any]
+
+ $Xi++; push(@X,shift(@X)); # "rotate" X[]
+}
+
+sub Xupdate_avx_32_79()
+{ use integer;
+ my $body = shift;
+ my @insns = (&$body,&$body,&$body,&$body); # 32 to 44 instructions
+ my ($a,$b,$c,$d,$e);
+
+ &vpalignr(@X[2],@X[-1&7],@X[-2&7],8); # compose "X[-6]"
+ &vpxor (@X[0],@X[0],@X[-4&7]); # "X[0]"="X[-32]"^"X[-16]"
+ eval(shift(@insns)); # body_20_39
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns)); # rol
+
+ &vpxor (@X[0],@X[0],@X[-7&7]); # "X[0]"^="X[-28]"
+ &vmovdqa (&QWP(64+16*(($Xi-4)%3),"esp"),@X[-4&7]); # save X[] to backtrace buffer
+ eval(shift(@insns));
+ eval(shift(@insns));
+ if ($Xi%5) {
+ &vmovdqa (@X[4],@X[3]); # "perpetuate" K_XX_XX...
+ } else { # ... or load next one
+ &vmovdqa (@X[4],&QWP(112-16+16*($Xi/5),"esp"));
+ }
+ &vpaddd (@X[3],@X[3],@X[-1&7]);
+ eval(shift(@insns)); # ror
+ eval(shift(@insns));
+
+ &vpxor (@X[0],@X[0],@X[2]); # "X[0]"^="X[-6]"
+ eval(shift(@insns)); # body_20_39
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns)); # rol
+
+ &vpsrld (@X[2],@X[0],30);
+ &vmovdqa (&QWP(0+16*(($Xi-1)&3),"esp"),@X[3]); # X[]+K xfer to IALU
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns)); # ror
+ eval(shift(@insns));
+
+ &vpslld (@X[0],@X[0],2);
+ eval(shift(@insns)); # body_20_39
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns)); # rol
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns)); # ror
+ eval(shift(@insns));
+
+ &vpor (@X[0],@X[0],@X[2]); # "X[0]"<<<=2
+ eval(shift(@insns)); # body_20_39
+ eval(shift(@insns));
+ &vmovdqa (@X[2],&QWP(64+16*(($Xi-6)%3),"esp")) if($Xi<19); # restore X[] from backtrace buffer
+ eval(shift(@insns));
+ eval(shift(@insns)); # rol
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns)); # ror
+ eval(shift(@insns));
+
+ foreach (@insns) { eval; } # remaining instructions
+
+ $Xi++; push(@X,shift(@X)); # "rotate" X[]
+}
+
+sub Xuplast_avx_80()
+{ use integer;
+ my $body = shift;
+ my @insns = (&$body,&$body,&$body,&$body); # 32 instructions
+ my ($a,$b,$c,$d,$e);
+
+ eval(shift(@insns));
+ &vpaddd (@X[3],@X[3],@X[-1&7]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ &vmovdqa (&QWP(0+16*(($Xi-1)&3),"esp"),@X[3]); # X[]+K xfer IALU
+
+ foreach (@insns) { eval; } # remaining instructions
+
+ &mov ($inp=@T[1],&DWP(192+4,"esp"));
+ &cmp ($inp,&DWP(192+8,"esp"));
+ &je (&label("done"));
+
+ &vmovdqa(@X[3],&QWP(112+48,"esp")); # K_00_19
+ &vmovdqa(@X[2],&QWP(112+64,"esp")); # pbswap mask
+ &vmovdqu(@X[-4&7],&QWP(0,$inp)); # load input
+ &vmovdqu(@X[-3&7],&QWP(16,$inp));
+ &vmovdqu(@X[-2&7],&QWP(32,$inp));
+ &vmovdqu(@X[-1&7],&QWP(48,$inp));
+ &add ($inp,64);
+ &vpshufb(@X[-4&7],@X[-4&7],@X[2]); # byte swap
+ &mov (&DWP(192+4,"esp"),$inp);
+ &vmovdqa(&QWP(112-16,"esp"),@X[3]); # borrow last backtrace slot
+
+ $Xi=0;
+}
+
+sub Xloop_avx()
+{ use integer;
+ my $body = shift;
+ my @insns = (&$body,&$body,&$body,&$body); # 32 instructions
+ my ($a,$b,$c,$d,$e);
+
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vpshufb (@X[($Xi-3)&7],@X[($Xi-3)&7],@X[2]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vpaddd (@X[$Xi&7],@X[($Xi-4)&7],@X[3]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vmovdqa (&QWP(0+16*$Xi,"esp"),@X[$Xi&7]); # X[]+K xfer to IALU
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ foreach (@insns) { eval; }
+ $Xi++;
+}
+
+sub Xtail_avx()
+{ use integer;
+ my $body = shift;
+ my @insns = (&$body,&$body,&$body,&$body); # 32 instructions
+ my ($a,$b,$c,$d,$e);
+
+ foreach (@insns) { eval; }
+}
+
+&set_label("loop",16);
+ &Xupdate_avx_16_31(\&body_00_19);
+ &Xupdate_avx_16_31(\&body_00_19);
+ &Xupdate_avx_16_31(\&body_00_19);
+ &Xupdate_avx_16_31(\&body_00_19);
+ &Xupdate_avx_32_79(\&body_00_19);
+ &Xupdate_avx_32_79(\&body_20_39);
+ &Xupdate_avx_32_79(\&body_20_39);
+ &Xupdate_avx_32_79(\&body_20_39);
+ &Xupdate_avx_32_79(\&body_20_39);
+ &Xupdate_avx_32_79(\&body_20_39);
+ &Xupdate_avx_32_79(\&body_40_59);
+ &Xupdate_avx_32_79(\&body_40_59);
+ &Xupdate_avx_32_79(\&body_40_59);
+ &Xupdate_avx_32_79(\&body_40_59);
+ &Xupdate_avx_32_79(\&body_40_59);
+ &Xupdate_avx_32_79(\&body_20_39);
+ &Xuplast_avx_80(\&body_20_39); # can jump to "done"
+
+ $saved_j=$j; @saved_V=@V;
+
+ &Xloop_avx(\&body_20_39);
+ &Xloop_avx(\&body_20_39);
+ &Xloop_avx(\&body_20_39);
+
+ &mov (@T[1],&DWP(192,"esp")); # update context
+ &add ($A,&DWP(0,@T[1]));
+ &add (@T[0],&DWP(4,@T[1])); # $b
+ &add ($C,&DWP(8,@T[1]));
+ &mov (&DWP(0,@T[1]),$A);
+ &add ($D,&DWP(12,@T[1]));
+ &mov (&DWP(4,@T[1]),@T[0]);
+ &add ($E,&DWP(16,@T[1]));
+ &mov ($B,$C);
+ &mov (&DWP(8,@T[1]),$C);
+ &xor ($B,$D);
+ &mov (&DWP(12,@T[1]),$D);
+ &mov (&DWP(16,@T[1]),$E);
+ &mov (@T[1],@T[0]);
+ &and (@T[0],$B);
+ &mov ($B,@T[1]);
+
+ &jmp (&label("loop"));
+
+&set_label("done",16); $j=$saved_j; @V=@saved_V;
+
+ &Xtail_avx(\&body_20_39);
+ &Xtail_avx(\&body_20_39);
+ &Xtail_avx(\&body_20_39);
+
+ &vzeroall();
+
+ &mov (@T[1],&DWP(192,"esp")); # update context
+ &add ($A,&DWP(0,@T[1]));
+ &mov ("esp",&DWP(192+12,"esp")); # restore %esp
+ &add (@T[0],&DWP(4,@T[1])); # $b
+ &add ($C,&DWP(8,@T[1]));
+ &mov (&DWP(0,@T[1]),$A);
+ &add ($D,&DWP(12,@T[1]));
+ &mov (&DWP(4,@T[1]),@T[0]);
+ &add ($E,&DWP(16,@T[1]));
+ &mov (&DWP(8,@T[1]),$C);
+ &mov (&DWP(12,@T[1]),$D);
+ &mov (&DWP(16,@T[1]),$E);
+&function_end("_sha1_block_data_order_avx");
+}
+&set_label("K_XX_XX",64);
+&data_word(0x5a827999,0x5a827999,0x5a827999,0x5a827999); # K_00_19
+&data_word(0x6ed9eba1,0x6ed9eba1,0x6ed9eba1,0x6ed9eba1); # K_20_39
+&data_word(0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc); # K_40_59
+&data_word(0xca62c1d6,0xca62c1d6,0xca62c1d6,0xca62c1d6); # K_60_79
+&data_word(0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f); # pbswap mask
+&data_byte(0xf,0xe,0xd,0xc,0xb,0xa,0x9,0x8,0x7,0x6,0x5,0x4,0x3,0x2,0x1,0x0);
+}
+&asciz("SHA1 block transform for x86, CRYPTOGAMS by <appro\@openssl.org>");
+
+&asm_finish();
diff --git a/src/crypto/sha/asm/sha1-armv4-large.pl b/src/crypto/sha/asm/sha1-armv4-large.pl
new file mode 100644
index 0000000..b2c3032
--- /dev/null
+++ b/src/crypto/sha/asm/sha1-armv4-large.pl
@@ -0,0 +1,683 @@
+#!/usr/bin/env perl
+
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+# project. The module is, however, dual licensed under OpenSSL and
+# CRYPTOGAMS licenses depending on where you obtain it. For further
+# details see http://www.openssl.org/~appro/cryptogams/.
+# ====================================================================
+
+# sha1_block procedure for ARMv4.
+#
+# January 2007.
+
+# Size/performance trade-off
+# ====================================================================
+# impl size in bytes comp cycles[*] measured performance
+# ====================================================================
+# thumb 304 3212 4420
+# armv4-small 392/+29% 1958/+64% 2250/+96%
+# armv4-compact 740/+89% 1552/+26% 1840/+22%
+# armv4-large 1420/+92% 1307/+19% 1370/+34%[***]
+# full unroll ~5100/+260% ~1260/+4% ~1300/+5%
+# ====================================================================
+# thumb = same as 'small' but in Thumb instructions[**] and
+# with recurring code in two private functions;
+# small = detached Xload/update, loops are folded;
+# compact = detached Xload/update, 5x unroll;
+# large = interleaved Xload/update, 5x unroll;
+# full unroll = interleaved Xload/update, full unroll, estimated[!];
+#
+# [*] Manually counted instructions in "grand" loop body. Measured
+# performance is affected by prologue and epilogue overhead,
+# i-cache availability, branch penalties, etc.
+# [**] While each Thumb instruction is twice smaller, they are not as
+# diverse as ARM ones: e.g., there are only two arithmetic
+# instructions with 3 arguments, no [fixed] rotate, addressing
+# modes are limited. As result it takes more instructions to do
+# the same job in Thumb, therefore the code is never twice as
+# small and always slower.
+# [***] which is also ~35% better than compiler generated code. Dual-
+# issue Cortex A8 core was measured to process input block in
+# ~990 cycles.
+
+# August 2010.
+#
+# Rescheduling for dual-issue pipeline resulted in 13% improvement on
+# Cortex A8 core and in absolute terms ~870 cycles per input block
+# [or 13.6 cycles per byte].
+
+# February 2011.
+#
+# Profiler-assisted and platform-specific optimization resulted in 10%
+# improvement on Cortex A8 core and 12.2 cycles per byte.
+
+# September 2013.
+#
+# Add NEON implementation (see sha1-586.pl for background info). On
+# Cortex A8 it was measured to process one byte in 6.7 cycles or >80%
+# faster than integer-only code. Because [fully unrolled] NEON code
+# is ~2.5x larger and there are some redundant instructions executed
+# when processing last block, improvement is not as big for smallest
+# blocks, only ~30%. Snapdragon S4 is a tad faster, 6.4 cycles per
+# byte, which is also >80% faster than integer-only code.
+
+# May 2014.
+#
+# Add ARMv8 code path performing at 2.35 cpb on Apple A7.
+
+while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {}
+open STDOUT,">$output";
+
+$ctx="r0";
+$inp="r1";
+$len="r2";
+$a="r3";
+$b="r4";
+$c="r5";
+$d="r6";
+$e="r7";
+$K="r8";
+$t0="r9";
+$t1="r10";
+$t2="r11";
+$t3="r12";
+$Xi="r14";
+@V=($a,$b,$c,$d,$e);
+
+sub Xupdate {
+my ($a,$b,$c,$d,$e,$opt1,$opt2)=@_;
+$code.=<<___;
+ ldr $t0,[$Xi,#15*4]
+ ldr $t1,[$Xi,#13*4]
+ ldr $t2,[$Xi,#7*4]
+ add $e,$K,$e,ror#2 @ E+=K_xx_xx
+ ldr $t3,[$Xi,#2*4]
+ eor $t0,$t0,$t1
+ eor $t2,$t2,$t3 @ 1 cycle stall
+ eor $t1,$c,$d @ F_xx_xx
+ mov $t0,$t0,ror#31
+ add $e,$e,$a,ror#27 @ E+=ROR(A,27)
+ eor $t0,$t0,$t2,ror#31
+ str $t0,[$Xi,#-4]!
+ $opt1 @ F_xx_xx
+ $opt2 @ F_xx_xx
+ add $e,$e,$t0 @ E+=X[i]
+___
+}
+
+sub BODY_00_15 {
+my ($a,$b,$c,$d,$e)=@_;
+$code.=<<___;
+#if __ARM_ARCH__<7
+ ldrb $t1,[$inp,#2]
+ ldrb $t0,[$inp,#3]
+ ldrb $t2,[$inp,#1]
+ add $e,$K,$e,ror#2 @ E+=K_00_19
+ ldrb $t3,[$inp],#4
+ orr $t0,$t0,$t1,lsl#8
+ eor $t1,$c,$d @ F_xx_xx
+ orr $t0,$t0,$t2,lsl#16
+ add $e,$e,$a,ror#27 @ E+=ROR(A,27)
+ orr $t0,$t0,$t3,lsl#24
+#else
+ ldr $t0,[$inp],#4 @ handles unaligned
+ add $e,$K,$e,ror#2 @ E+=K_00_19
+ eor $t1,$c,$d @ F_xx_xx
+ add $e,$e,$a,ror#27 @ E+=ROR(A,27)
+#ifdef __ARMEL__
+ rev $t0,$t0 @ byte swap
+#endif
+#endif
+ and $t1,$b,$t1,ror#2
+ add $e,$e,$t0 @ E+=X[i]
+ eor $t1,$t1,$d,ror#2 @ F_00_19(B,C,D)
+ str $t0,[$Xi,#-4]!
+ add $e,$e,$t1 @ E+=F_00_19(B,C,D)
+___
+}
+
+sub BODY_16_19 {
+my ($a,$b,$c,$d,$e)=@_;
+ &Xupdate(@_,"and $t1,$b,$t1,ror#2");
+$code.=<<___;
+ eor $t1,$t1,$d,ror#2 @ F_00_19(B,C,D)
+ add $e,$e,$t1 @ E+=F_00_19(B,C,D)
+___
+}
+
+sub BODY_20_39 {
+my ($a,$b,$c,$d,$e)=@_;
+ &Xupdate(@_,"eor $t1,$b,$t1,ror#2");
+$code.=<<___;
+ add $e,$e,$t1 @ E+=F_20_39(B,C,D)
+___
+}
+
+sub BODY_40_59 {
+my ($a,$b,$c,$d,$e)=@_;
+ &Xupdate(@_,"and $t1,$b,$t1,ror#2","and $t2,$c,$d");
+$code.=<<___;
+ add $e,$e,$t1 @ E+=F_40_59(B,C,D)
+ add $e,$e,$t2,ror#2
+___
+}
+
+$code=<<___;
+#include "arm_arch.h"
+
+.text
+.code 32
+
+.global sha1_block_data_order
+.type sha1_block_data_order,%function
+
+.align 5
+sha1_block_data_order:
+#if __ARM_MAX_ARCH__>=7
+ sub r3,pc,#8 @ sha1_block_data_order
+ ldr r12,.LOPENSSL_armcap
+ ldr r12,[r3,r12] @ OPENSSL_armcap_P
+ tst r12,#ARMV8_SHA1
+ bne .LARMv8
+ tst r12,#ARMV7_NEON
+ bne .LNEON
+#endif
+ stmdb sp!,{r4-r12,lr}
+ add $len,$inp,$len,lsl#6 @ $len to point at the end of $inp
+ ldmia $ctx,{$a,$b,$c,$d,$e}
+.Lloop:
+ ldr $K,.LK_00_19
+ mov $Xi,sp
+ sub sp,sp,#15*4
+ mov $c,$c,ror#30
+ mov $d,$d,ror#30
+ mov $e,$e,ror#30 @ [6]
+.L_00_15:
+___
+for($i=0;$i<5;$i++) {
+ &BODY_00_15(@V); unshift(@V,pop(@V));
+}
+$code.=<<___;
+ teq $Xi,sp
+ bne .L_00_15 @ [((11+4)*5+2)*3]
+ sub sp,sp,#25*4
+___
+ &BODY_00_15(@V); unshift(@V,pop(@V));
+ &BODY_16_19(@V); unshift(@V,pop(@V));
+ &BODY_16_19(@V); unshift(@V,pop(@V));
+ &BODY_16_19(@V); unshift(@V,pop(@V));
+ &BODY_16_19(@V); unshift(@V,pop(@V));
+$code.=<<___;
+
+ ldr $K,.LK_20_39 @ [+15+16*4]
+ cmn sp,#0 @ [+3], clear carry to denote 20_39
+.L_20_39_or_60_79:
+___
+for($i=0;$i<5;$i++) {
+ &BODY_20_39(@V); unshift(@V,pop(@V));
+}
+$code.=<<___;
+ teq $Xi,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 $K,.LK_40_59
+ sub sp,sp,#20*4 @ [+2]
+.L_40_59:
+___
+for($i=0;$i<5;$i++) {
+ &BODY_40_59(@V); unshift(@V,pop(@V));
+}
+$code.=<<___;
+ teq $Xi,sp
+ bne .L_40_59 @ [+((12+5)*5+2)*4]
+
+ ldr $K,.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 $ctx,{$K,$t0,$t1,$t2,$t3}
+ add $a,$K,$a
+ add $b,$t0,$b
+ add $c,$t1,$c,ror#2
+ add $d,$t2,$d,ror#2
+ add $e,$t3,$e,ror#2
+ stmia $ctx,{$a,$b,$c,$d,$e}
+ teq $inp,$len
+ 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
+ bx lr @ interoperable with Thumb ISA:-)
+#endif
+.size sha1_block_data_order,.-sha1_block_data_order
+
+.align 5
+.LK_00_19: .word 0x5a827999
+.LK_20_39: .word 0x6ed9eba1
+.LK_40_59: .word 0x8f1bbcdc
+.LK_60_79: .word 0xca62c1d6
+#if __ARM_MAX_ARCH__>=7
+.LOPENSSL_armcap:
+.word OPENSSL_armcap_P-sha1_block_data_order
+#endif
+.asciz "SHA1 block transform for ARMv4/NEON/ARMv8, CRYPTOGAMS by <appro\@openssl.org>"
+.align 5
+___
+#####################################################################
+# NEON stuff
+#
+{{{
+my @V=($a,$b,$c,$d,$e);
+my ($K_XX_XX,$Ki,$t0,$t1,$Xfer,$saved_sp)=map("r$_",(8..12,14));
+my $Xi=4;
+my @X=map("q$_",(8..11,0..3));
+my @Tx=("q12","q13");
+my ($K,$zero)=("q14","q15");
+my $j=0;
+
+sub AUTOLOAD() # thunk [simplified] x86-style perlasm
+{ my $opcode = $AUTOLOAD; $opcode =~ s/.*:://; $opcode =~ s/_/\./;
+ my $arg = pop;
+ $arg = "#$arg" if ($arg*1 eq $arg);
+ $code .= "\t$opcode\t".join(',',@_,$arg)."\n";
+}
+
+sub body_00_19 () {
+ (
+ '($a,$b,$c,$d,$e)=@V;'. # '$code.="@ $j\n";'.
+ '&bic ($t0,$d,$b)',
+ '&add ($e,$e,$Ki)', # e+=X[i]+K
+ '&and ($t1,$c,$b)',
+ '&ldr ($Ki,sprintf "[sp,#%d]",4*(($j+1)&15))',
+ '&add ($e,$e,$a,"ror#27")', # e+=ROR(A,27)
+ '&eor ($t1,$t1,$t0)', # F_00_19
+ '&mov ($b,$b,"ror#2")', # b=ROR(b,2)
+ '&add ($e,$e,$t1);'. # e+=F_00_19
+ '$j++; unshift(@V,pop(@V));'
+ )
+}
+sub body_20_39 () {
+ (
+ '($a,$b,$c,$d,$e)=@V;'. # '$code.="@ $j\n";'.
+ '&eor ($t0,$b,$d)',
+ '&add ($e,$e,$Ki)', # e+=X[i]+K
+ '&ldr ($Ki,sprintf "[sp,#%d]",4*(($j+1)&15)) if ($j<79)',
+ '&eor ($t1,$t0,$c)', # F_20_39
+ '&add ($e,$e,$a,"ror#27")', # e+=ROR(A,27)
+ '&mov ($b,$b,"ror#2")', # b=ROR(b,2)
+ '&add ($e,$e,$t1);'. # e+=F_20_39
+ '$j++; unshift(@V,pop(@V));'
+ )
+}
+sub body_40_59 () {
+ (
+ '($a,$b,$c,$d,$e)=@V;'. # '$code.="@ $j\n";'.
+ '&add ($e,$e,$Ki)', # e+=X[i]+K
+ '&and ($t0,$c,$d)',
+ '&ldr ($Ki,sprintf "[sp,#%d]",4*(($j+1)&15))',
+ '&add ($e,$e,$a,"ror#27")', # e+=ROR(A,27)
+ '&eor ($t1,$c,$d)',
+ '&add ($e,$e,$t0)',
+ '&and ($t1,$t1,$b)',
+ '&mov ($b,$b,"ror#2")', # b=ROR(b,2)
+ '&add ($e,$e,$t1);'. # e+=F_40_59
+ '$j++; unshift(@V,pop(@V));'
+ )
+}
+
+sub Xupdate_16_31 ()
+{ use integer;
+ my $body = shift;
+ my @insns = (&$body,&$body,&$body,&$body);
+ my ($a,$b,$c,$d,$e);
+
+ &vext_8 (@X[0],@X[-4&7],@X[-3&7],8); # compose "X[-14]" in "X[0]"
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vadd_i32 (@Tx[1],@X[-1&7],$K);
+ eval(shift(@insns));
+ &vld1_32 ("{$K\[]}","[$K_XX_XX,:32]!") if ($Xi%5==0);
+ eval(shift(@insns));
+ &vext_8 (@Tx[0],@X[-1&7],$zero,4); # "X[-3]", 3 words
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &veor (@X[0],@X[0],@X[-4&7]); # "X[0]"^="X[-16]"
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &veor (@Tx[0],@Tx[0],@X[-2&7]); # "X[-3]"^"X[-8]"
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &veor (@Tx[0],@Tx[0],@X[0]); # "X[0]"^="X[-3]"^"X[-8]
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vst1_32 ("{@Tx[1]}","[$Xfer,:128]!"); # X[]+K xfer
+ &sub ($Xfer,$Xfer,64) if ($Xi%4==0);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vext_8 (@Tx[1],$zero,@Tx[0],4); # "X[0]"<<96, extract one dword
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vadd_i32 (@X[0],@Tx[0],@Tx[0]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vsri_32 (@X[0],@Tx[0],31); # "X[0]"<<<=1
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vshr_u32 (@Tx[0],@Tx[1],30);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vshl_u32 (@Tx[1],@Tx[1],2);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &veor (@X[0],@X[0],@Tx[0]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &veor (@X[0],@X[0],@Tx[1]); # "X[0]"^=("X[0]">>96)<<<2
+
+ foreach (@insns) { eval; } # remaining instructions [if any]
+
+ $Xi++; push(@X,shift(@X)); # "rotate" X[]
+}
+
+sub Xupdate_32_79 ()
+{ use integer;
+ my $body = shift;
+ my @insns = (&$body,&$body,&$body,&$body);
+ my ($a,$b,$c,$d,$e);
+
+ &vext_8 (@Tx[0],@X[-2&7],@X[-1&7],8); # compose "X[-6]"
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &veor (@X[0],@X[0],@X[-4&7]); # "X[0]"="X[-32]"^"X[-16]"
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &veor (@X[0],@X[0],@X[-7&7]); # "X[0]"^="X[-28]"
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vadd_i32 (@Tx[1],@X[-1&7],$K);
+ eval(shift(@insns));
+ &vld1_32 ("{$K\[]}","[$K_XX_XX,:32]!") if ($Xi%5==0);
+ eval(shift(@insns));
+ &veor (@Tx[0],@Tx[0],@X[0]); # "X[-6]"^="X[0]"
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vshr_u32 (@X[0],@Tx[0],30);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vst1_32 ("{@Tx[1]}","[$Xfer,:128]!"); # X[]+K xfer
+ &sub ($Xfer,$Xfer,64) if ($Xi%4==0);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vsli_32 (@X[0],@Tx[0],2); # "X[0]"="X[-6]"<<<2
+
+ foreach (@insns) { eval; } # remaining instructions [if any]
+
+ $Xi++; push(@X,shift(@X)); # "rotate" X[]
+}
+
+sub Xuplast_80 ()
+{ use integer;
+ my $body = shift;
+ my @insns = (&$body,&$body,&$body,&$body);
+ my ($a,$b,$c,$d,$e);
+
+ &vadd_i32 (@Tx[1],@X[-1&7],$K);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vst1_32 ("{@Tx[1]}","[$Xfer,:128]!");
+ &sub ($Xfer,$Xfer,64);
+
+ &teq ($inp,$len);
+ &sub ($K_XX_XX,$K_XX_XX,16); # rewind $K_XX_XX
+ &subeq ($inp,$inp,64); # reload last block to avoid SEGV
+ &vld1_8 ("{@X[-4&7]-@X[-3&7]}","[$inp]!");
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vld1_8 ("{@X[-2&7]-@X[-1&7]}","[$inp]!");
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vld1_32 ("{$K\[]}","[$K_XX_XX,:32]!"); # load K_00_19
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vrev32_8 (@X[-4&7],@X[-4&7]);
+
+ foreach (@insns) { eval; } # remaining instructions
+
+ $Xi=0;
+}
+
+sub Xloop()
+{ use integer;
+ my $body = shift;
+ my @insns = (&$body,&$body,&$body,&$body);
+ my ($a,$b,$c,$d,$e);
+
+ &vrev32_8 (@X[($Xi-3)&7],@X[($Xi-3)&7]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vadd_i32 (@X[$Xi&7],@X[($Xi-4)&7],$K);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vst1_32 ("{@X[$Xi&7]}","[$Xfer,:128]!");# X[]+K xfer to IALU
+
+ foreach (@insns) { eval; }
+
+ $Xi++;
+}
+
+$code.=<<___;
+#if __ARM_MAX_ARCH__>=7
+.arch armv7-a
+.fpu neon
+
+.type sha1_block_data_order_neon,%function
+.align 4
+sha1_block_data_order_neon:
+.LNEON:
+ stmdb sp!,{r4-r12,lr}
+ add $len,$inp,$len,lsl#6 @ $len to point at the end of $inp
+ @ dmb @ errata #451034 on early Cortex A8
+ @ vstmdb sp!,{d8-d15} @ ABI specification says so
+ mov $saved_sp,sp
+ sub sp,sp,#64 @ alloca
+ adr $K_XX_XX,.LK_00_19
+ bic sp,sp,#15 @ align for 128-bit stores
+
+ ldmia $ctx,{$a,$b,$c,$d,$e} @ load context
+ mov $Xfer,sp
+
+ vld1.8 {@X[-4&7]-@X[-3&7]},[$inp]! @ handles unaligned
+ veor $zero,$zero,$zero
+ vld1.8 {@X[-2&7]-@X[-1&7]},[$inp]!
+ vld1.32 {${K}\[]},[$K_XX_XX,:32]! @ load K_00_19
+ vrev32.8 @X[-4&7],@X[-4&7] @ yes, even on
+ vrev32.8 @X[-3&7],@X[-3&7] @ big-endian...
+ vrev32.8 @X[-2&7],@X[-2&7]
+ vadd.i32 @X[0],@X[-4&7],$K
+ vrev32.8 @X[-1&7],@X[-1&7]
+ vadd.i32 @X[1],@X[-3&7],$K
+ vst1.32 {@X[0]},[$Xfer,:128]!
+ vadd.i32 @X[2],@X[-2&7],$K
+ vst1.32 {@X[1]},[$Xfer,:128]!
+ vst1.32 {@X[2]},[$Xfer,:128]!
+ ldr $Ki,[sp] @ big RAW stall
+
+.Loop_neon:
+___
+ &Xupdate_16_31(\&body_00_19);
+ &Xupdate_16_31(\&body_00_19);
+ &Xupdate_16_31(\&body_00_19);
+ &Xupdate_16_31(\&body_00_19);
+ &Xupdate_32_79(\&body_00_19);
+ &Xupdate_32_79(\&body_20_39);
+ &Xupdate_32_79(\&body_20_39);
+ &Xupdate_32_79(\&body_20_39);
+ &Xupdate_32_79(\&body_20_39);
+ &Xupdate_32_79(\&body_20_39);
+ &Xupdate_32_79(\&body_40_59);
+ &Xupdate_32_79(\&body_40_59);
+ &Xupdate_32_79(\&body_40_59);
+ &Xupdate_32_79(\&body_40_59);
+ &Xupdate_32_79(\&body_40_59);
+ &Xupdate_32_79(\&body_20_39);
+ &Xuplast_80(\&body_20_39);
+ &Xloop(\&body_20_39);
+ &Xloop(\&body_20_39);
+ &Xloop(\&body_20_39);
+$code.=<<___;
+ ldmia $ctx,{$Ki,$t0,$t1,$Xfer} @ accumulate context
+ add $a,$a,$Ki
+ ldr $Ki,[$ctx,#16]
+ add $b,$b,$t0
+ add $c,$c,$t1
+ add $d,$d,$Xfer
+ moveq sp,$saved_sp
+ add $e,$e,$Ki
+ ldrne $Ki,[sp]
+ stmia $ctx,{$a,$b,$c,$d,$e}
+ addne $Xfer,sp,#3*16
+ bne .Loop_neon
+
+ @ vldmia sp!,{d8-d15}
+ ldmia sp!,{r4-r12,pc}
+.size sha1_block_data_order_neon,.-sha1_block_data_order_neon
+#endif
+___
+}}}
+#####################################################################
+# ARMv8 stuff
+#
+{{{
+my ($ABCD,$E,$E0,$E1)=map("q$_",(0..3));
+my @MSG=map("q$_",(4..7));
+my @Kxx=map("q$_",(8..11));
+my ($W0,$W1,$ABCD_SAVE)=map("q$_",(12..14));
+
+$code.=<<___;
+#if __ARM_MAX_ARCH__>=7
+.type sha1_block_data_order_armv8,%function
+.align 5
+sha1_block_data_order_armv8:
+.LARMv8:
+ vstmdb sp!,{d8-d15} @ ABI specification says so
+
+ veor $E,$E,$E
+ adr r3,.LK_00_19
+ vld1.32 {$ABCD},[$ctx]!
+ vld1.32 {$E\[0]},[$ctx]
+ sub $ctx,$ctx,#16
+ vld1.32 {@Kxx[0]\[]},[r3,:32]!
+ vld1.32 {@Kxx[1]\[]},[r3,:32]!
+ vld1.32 {@Kxx[2]\[]},[r3,:32]!
+ vld1.32 {@Kxx[3]\[]},[r3,:32]
+
+.Loop_v8:
+ vld1.8 {@MSG[0]-@MSG[1]},[$inp]!
+ vld1.8 {@MSG[2]-@MSG[3]},[$inp]!
+ vrev32.8 @MSG[0],@MSG[0]
+ vrev32.8 @MSG[1],@MSG[1]
+
+ vadd.i32 $W0,@Kxx[0],@MSG[0]
+ vrev32.8 @MSG[2],@MSG[2]
+ vmov $ABCD_SAVE,$ABCD @ offload
+ subs $len,$len,#1
+
+ vadd.i32 $W1,@Kxx[0],@MSG[1]
+ vrev32.8 @MSG[3],@MSG[3]
+ sha1h $E1,$ABCD @ 0
+ sha1c $ABCD,$E,$W0
+ vadd.i32 $W0,@Kxx[$j],@MSG[2]
+ sha1su0 @MSG[0],@MSG[1],@MSG[2]
+___
+for ($j=0,$i=1;$i<20-3;$i++) {
+my $f=("c","p","m","p")[$i/5];
+$code.=<<___;
+ sha1h $E0,$ABCD @ $i
+ sha1$f $ABCD,$E1,$W1
+ vadd.i32 $W1,@Kxx[$j],@MSG[3]
+ sha1su1 @MSG[0],@MSG[3]
+___
+$code.=<<___ if ($i<20-4);
+ sha1su0 @MSG[1],@MSG[2],@MSG[3]
+___
+ ($E0,$E1)=($E1,$E0); ($W0,$W1)=($W1,$W0);
+ push(@MSG,shift(@MSG)); $j++ if ((($i+3)%5)==0);
+}
+$code.=<<___;
+ sha1h $E0,$ABCD @ $i
+ sha1p $ABCD,$E1,$W1
+ vadd.i32 $W1,@Kxx[$j],@MSG[3]
+
+ sha1h $E1,$ABCD @ 18
+ sha1p $ABCD,$E0,$W0
+
+ sha1h $E0,$ABCD @ 19
+ sha1p $ABCD,$E1,$W1
+
+ vadd.i32 $E,$E,$E0
+ vadd.i32 $ABCD,$ABCD,$ABCD_SAVE
+ bne .Loop_v8
+
+ vst1.32 {$ABCD},[$ctx]!
+ vst1.32 {$E\[0]},[$ctx]
+
+ vldmia sp!,{d8-d15}
+ ret @ bx lr
+.size sha1_block_data_order_armv8,.-sha1_block_data_order_armv8
+#endif
+___
+}}}
+$code.=<<___;
+#if __ARM_MAX_ARCH__>=7
+.comm OPENSSL_armcap_P,4,4
+#endif
+___
+
+{ my %opcode = (
+ "sha1c" => 0xf2000c40, "sha1p" => 0xf2100c40,
+ "sha1m" => 0xf2200c40, "sha1su0" => 0xf2300c40,
+ "sha1h" => 0xf3b902c0, "sha1su1" => 0xf3ba0380 );
+
+ sub unsha1 {
+ my ($mnemonic,$arg)=@_;
+
+ if ($arg =~ m/q([0-9]+)(?:,\s*q([0-9]+))?,\s*q([0-9]+)/o) {
+ my $word = $opcode{$mnemonic}|(($1&7)<<13)|(($1&8)<<19)
+ |(($2&7)<<17)|(($2&8)<<4)
+ |(($3&7)<<1) |(($3&8)<<2);
+ # since ARMv7 instructions are always encoded little-endian.
+ # correct solution is to use .inst directive, but older
+ # assemblers don't implement it:-(
+ sprintf ".byte\t0x%02x,0x%02x,0x%02x,0x%02x\t@ %s %s",
+ $word&0xff,($word>>8)&0xff,
+ ($word>>16)&0xff,($word>>24)&0xff,
+ $mnemonic,$arg;
+ }
+ }
+}
+
+foreach (split($/,$code)) {
+ s/{q([0-9]+)\[\]}/sprintf "{d%d[],d%d[]}",2*$1,2*$1+1/eo or
+ s/{q([0-9]+)\[0\]}/sprintf "{d%d[0]}",2*$1/eo;
+
+ s/\b(sha1\w+)\s+(q.*)/unsha1($1,$2)/geo;
+
+ s/\bret\b/bx lr/o or
+ s/\bbx\s+lr\b/.word\t0xe12fff1e/o; # make it possible to compile with -march=armv4
+
+ print $_,$/;
+}
+
+close STDOUT; # enforce flush
diff --git a/src/crypto/sha/asm/sha1-armv8.pl b/src/crypto/sha/asm/sha1-armv8.pl
new file mode 100644
index 0000000..deb1238
--- /dev/null
+++ b/src/crypto/sha/asm/sha1-armv8.pl
@@ -0,0 +1,334 @@
+#!/usr/bin/env perl
+#
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+# project. The module is, however, dual licensed under OpenSSL and
+# CRYPTOGAMS licenses depending on where you obtain it. For further
+# details see http://www.openssl.org/~appro/cryptogams/.
+# ====================================================================
+#
+# SHA1 for ARMv8.
+#
+# Performance in cycles per processed byte and improvement coefficient
+# over code generated with "default" compiler:
+#
+# hardware-assisted software(*)
+# Apple A7 2.31 4.13 (+14%)
+# Cortex-A53 2.19 8.73 (+108%)
+# Cortex-A57 2.35 7.88 (+74%)
+#
+# (*) Software results are presented mostly for reference purposes.
+
+$flavour = shift;
+open STDOUT,">".shift;
+
+($ctx,$inp,$num)=("x0","x1","x2");
+@Xw=map("w$_",(3..17,19));
+@Xx=map("x$_",(3..17,19));
+@V=($A,$B,$C,$D,$E)=map("w$_",(20..24));
+($t0,$t1,$t2,$K)=map("w$_",(25..28));
+
+
+sub BODY_00_19 {
+my ($i,$a,$b,$c,$d,$e)=@_;
+my $j=($i+2)&15;
+
+$code.=<<___ if ($i<15 && !($i&1));
+ lsr @Xx[$i+1],@Xx[$i],#32
+___
+$code.=<<___ if ($i<14 && !($i&1));
+ ldr @Xx[$i+2],[$inp,#`($i+2)*4-64`]
+___
+$code.=<<___ if ($i<14 && ($i&1));
+#ifdef __ARMEB__
+ ror @Xx[$i+1],@Xx[$i+1],#32
+#else
+ rev32 @Xx[$i+1],@Xx[$i+1]
+#endif
+___
+$code.=<<___ if ($i<14);
+ bic $t0,$d,$b
+ and $t1,$c,$b
+ ror $t2,$a,#27
+ add $d,$d,$K // future e+=K
+ orr $t0,$t0,$t1
+ add $e,$e,$t2 // e+=rot(a,5)
+ ror $b,$b,#2
+ add $d,$d,@Xw[($i+1)&15] // future e+=X[i]
+ add $e,$e,$t0 // e+=F(b,c,d)
+___
+$code.=<<___ if ($i==19);
+ movz $K,#0xeba1
+ movk $K,#0x6ed9,lsl#16
+___
+$code.=<<___ if ($i>=14);
+ eor @Xw[$j],@Xw[$j],@Xw[($j+2)&15]
+ bic $t0,$d,$b
+ and $t1,$c,$b
+ ror $t2,$a,#27
+ eor @Xw[$j],@Xw[$j],@Xw[($j+8)&15]
+ add $d,$d,$K // future e+=K
+ orr $t0,$t0,$t1
+ add $e,$e,$t2 // e+=rot(a,5)
+ eor @Xw[$j],@Xw[$j],@Xw[($j+13)&15]
+ ror $b,$b,#2
+ add $d,$d,@Xw[($i+1)&15] // future e+=X[i]
+ add $e,$e,$t0 // e+=F(b,c,d)
+ ror @Xw[$j],@Xw[$j],#31
+___
+}
+
+sub BODY_40_59 {
+my ($i,$a,$b,$c,$d,$e)=@_;
+my $j=($i+2)&15;
+
+$code.=<<___ if ($i==59);
+ movz $K,#0xc1d6
+ movk $K,#0xca62,lsl#16
+___
+$code.=<<___;
+ orr $t0,$b,$c
+ and $t1,$b,$c
+ eor @Xw[$j],@Xw[$j],@Xw[($j+2)&15]
+ ror $t2,$a,#27
+ and $t0,$t0,$d
+ add $d,$d,$K // future e+=K
+ eor @Xw[$j],@Xw[$j],@Xw[($j+8)&15]
+ add $e,$e,$t2 // e+=rot(a,5)
+ orr $t0,$t0,$t1
+ ror $b,$b,#2
+ eor @Xw[$j],@Xw[$j],@Xw[($j+13)&15]
+ add $d,$d,@Xw[($i+1)&15] // future e+=X[i]
+ add $e,$e,$t0 // e+=F(b,c,d)
+ ror @Xw[$j],@Xw[$j],#31
+___
+}
+
+sub BODY_20_39 {
+my ($i,$a,$b,$c,$d,$e)=@_;
+my $j=($i+2)&15;
+
+$code.=<<___ if ($i==39);
+ movz $K,#0xbcdc
+ movk $K,#0x8f1b,lsl#16
+___
+$code.=<<___ if ($i<78);
+ eor @Xw[$j],@Xw[$j],@Xw[($j+2)&15]
+ eor $t0,$d,$b
+ ror $t2,$a,#27
+ add $d,$d,$K // future e+=K
+ eor @Xw[$j],@Xw[$j],@Xw[($j+8)&15]
+ eor $t0,$t0,$c
+ add $e,$e,$t2 // e+=rot(a,5)
+ ror $b,$b,#2
+ eor @Xw[$j],@Xw[$j],@Xw[($j+13)&15]
+ add $d,$d,@Xw[($i+1)&15] // future e+=X[i]
+ add $e,$e,$t0 // e+=F(b,c,d)
+ ror @Xw[$j],@Xw[$j],#31
+___
+$code.=<<___ if ($i==78);
+ ldp @Xw[1],@Xw[2],[$ctx]
+ eor $t0,$d,$b
+ ror $t2,$a,#27
+ add $d,$d,$K // future e+=K
+ eor $t0,$t0,$c
+ add $e,$e,$t2 // e+=rot(a,5)
+ ror $b,$b,#2
+ add $d,$d,@Xw[($i+1)&15] // future e+=X[i]
+ add $e,$e,$t0 // e+=F(b,c,d)
+___
+$code.=<<___ if ($i==79);
+ ldp @Xw[3],@Xw[4],[$ctx,#8]
+ eor $t0,$d,$b
+ ror $t2,$a,#27
+ eor $t0,$t0,$c
+ add $e,$e,$t2 // e+=rot(a,5)
+ ror $b,$b,#2
+ ldr @Xw[5],[$ctx,#16]
+ add $e,$e,$t0 // e+=F(b,c,d)
+___
+}
+
+$code.=<<___;
+#include "arm_arch.h"
+
+.text
+
+.globl sha1_block_data_order
+.type sha1_block_data_order,%function
+.align 6
+sha1_block_data_order:
+ ldr x16,.LOPENSSL_armcap_P
+ adr x17,.LOPENSSL_armcap_P
+ add x16,x16,x17
+ ldr w16,[x16]
+ tst w16,#ARMV8_SHA1
+ b.ne .Lv8_entry
+
+ stp x29,x30,[sp,#-96]!
+ add x29,sp,#0
+ stp x19,x20,[sp,#16]
+ stp x21,x22,[sp,#32]
+ stp x23,x24,[sp,#48]
+ stp x25,x26,[sp,#64]
+ stp x27,x28,[sp,#80]
+
+ ldp $A,$B,[$ctx]
+ ldp $C,$D,[$ctx,#8]
+ ldr $E,[$ctx,#16]
+
+.Loop:
+ ldr @Xx[0],[$inp],#64
+ movz $K,#0x7999
+ sub $num,$num,#1
+ movk $K,#0x5a82,lsl#16
+#ifdef __ARMEB__
+ ror $Xx[0],@Xx[0],#32
+#else
+ rev32 @Xx[0],@Xx[0]
+#endif
+ add $E,$E,$K // warm it up
+ add $E,$E,@Xw[0]
+___
+for($i=0;$i<20;$i++) { &BODY_00_19($i,@V); unshift(@V,pop(@V)); }
+for(;$i<40;$i++) { &BODY_20_39($i,@V); unshift(@V,pop(@V)); }
+for(;$i<60;$i++) { &BODY_40_59($i,@V); unshift(@V,pop(@V)); }
+for(;$i<80;$i++) { &BODY_20_39($i,@V); unshift(@V,pop(@V)); }
+$code.=<<___;
+ add $B,$B,@Xw[2]
+ add $C,$C,@Xw[3]
+ add $A,$A,@Xw[1]
+ add $D,$D,@Xw[4]
+ add $E,$E,@Xw[5]
+ stp $A,$B,[$ctx]
+ stp $C,$D,[$ctx,#8]
+ str $E,[$ctx,#16]
+ cbnz $num,.Loop
+
+ ldp x19,x20,[sp,#16]
+ ldp x21,x22,[sp,#32]
+ ldp x23,x24,[sp,#48]
+ ldp x25,x26,[sp,#64]
+ ldp x27,x28,[sp,#80]
+ ldr x29,[sp],#96
+ ret
+.size sha1_block_data_order,.-sha1_block_data_order
+___
+{{{
+my ($ABCD,$E,$E0,$E1)=map("v$_.16b",(0..3));
+my @MSG=map("v$_.16b",(4..7));
+my @Kxx=map("v$_.4s",(16..19));
+my ($W0,$W1)=("v20.4s","v21.4s");
+my $ABCD_SAVE="v22.16b";
+
+$code.=<<___;
+.type sha1_block_armv8,%function
+.align 6
+sha1_block_armv8:
+.Lv8_entry:
+ stp x29,x30,[sp,#-16]!
+ add x29,sp,#0
+
+ adr x4,.Lconst
+ eor $E,$E,$E
+ ld1.32 {$ABCD},[$ctx],#16
+ ld1.32 {$E}[0],[$ctx]
+ sub $ctx,$ctx,#16
+ ld1.32 {@Kxx[0]-@Kxx[3]},[x4]
+
+.Loop_hw:
+ ld1 {@MSG[0]-@MSG[3]},[$inp],#64
+ sub $num,$num,#1
+ rev32 @MSG[0],@MSG[0]
+ rev32 @MSG[1],@MSG[1]
+
+ add.i32 $W0,@Kxx[0],@MSG[0]
+ rev32 @MSG[2],@MSG[2]
+ orr $ABCD_SAVE,$ABCD,$ABCD // offload
+
+ add.i32 $W1,@Kxx[0],@MSG[1]
+ rev32 @MSG[3],@MSG[3]
+ sha1h $E1,$ABCD
+ sha1c $ABCD,$E,$W0 // 0
+ add.i32 $W0,@Kxx[$j],@MSG[2]
+ sha1su0 @MSG[0],@MSG[1],@MSG[2]
+___
+for ($j=0,$i=1;$i<20-3;$i++) {
+my $f=("c","p","m","p")[$i/5];
+$code.=<<___;
+ sha1h $E0,$ABCD // $i
+ sha1$f $ABCD,$E1,$W1
+ add.i32 $W1,@Kxx[$j],@MSG[3]
+ sha1su1 @MSG[0],@MSG[3]
+___
+$code.=<<___ if ($i<20-4);
+ sha1su0 @MSG[1],@MSG[2],@MSG[3]
+___
+ ($E0,$E1)=($E1,$E0); ($W0,$W1)=($W1,$W0);
+ push(@MSG,shift(@MSG)); $j++ if ((($i+3)%5)==0);
+}
+$code.=<<___;
+ sha1h $E0,$ABCD // $i
+ sha1p $ABCD,$E1,$W1
+ add.i32 $W1,@Kxx[$j],@MSG[3]
+
+ sha1h $E1,$ABCD // 18
+ sha1p $ABCD,$E0,$W0
+
+ sha1h $E0,$ABCD // 19
+ sha1p $ABCD,$E1,$W1
+
+ add.i32 $E,$E,$E0
+ add.i32 $ABCD,$ABCD,$ABCD_SAVE
+
+ cbnz $num,.Loop_hw
+
+ st1.32 {$ABCD},[$ctx],#16
+ st1.32 {$E}[0],[$ctx]
+
+ ldr x29,[sp],#16
+ ret
+.size sha1_block_armv8,.-sha1_block_armv8
+.align 6
+.Lconst:
+.long 0x5a827999,0x5a827999,0x5a827999,0x5a827999 //K_00_19
+.long 0x6ed9eba1,0x6ed9eba1,0x6ed9eba1,0x6ed9eba1 //K_20_39
+.long 0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc //K_40_59
+.long 0xca62c1d6,0xca62c1d6,0xca62c1d6,0xca62c1d6 //K_60_79
+.LOPENSSL_armcap_P:
+.quad OPENSSL_armcap_P-.
+.asciz "SHA1 block transform for ARMv8, CRYPTOGAMS by <appro\@openssl.org>"
+.align 2
+.comm OPENSSL_armcap_P,4,4
+___
+}}}
+
+{ my %opcode = (
+ "sha1c" => 0x5e000000, "sha1p" => 0x5e001000,
+ "sha1m" => 0x5e002000, "sha1su0" => 0x5e003000,
+ "sha1h" => 0x5e280800, "sha1su1" => 0x5e281800 );
+
+ sub unsha1 {
+ my ($mnemonic,$arg)=@_;
+
+ $arg =~ m/[qv]([0-9]+)[^,]*,\s*[qv]([0-9]+)[^,]*(?:,\s*[qv]([0-9]+))?/o
+ &&
+ sprintf ".inst\t0x%08x\t//%s %s",
+ $opcode{$mnemonic}|$1|($2<<5)|($3<<16),
+ $mnemonic,$arg;
+ }
+}
+
+foreach(split("\n",$code)) {
+
+ s/\`([^\`]*)\`/eval($1)/geo;
+
+ s/\b(sha1\w+)\s+([qv].*)/unsha1($1,$2)/geo;
+
+ s/\.\w?32\b//o and s/\.16b/\.4s/go;
+ m/(ld|st)1[^\[]+\[0\]/o and s/\.4s/\.s/go;
+
+ print $_,"\n";
+}
+
+close STDOUT;
diff --git a/src/crypto/sha/asm/sha1-x86_64.pl b/src/crypto/sha/asm/sha1-x86_64.pl
new file mode 100644
index 0000000..124034d
--- /dev/null
+++ b/src/crypto/sha/asm/sha1-x86_64.pl
@@ -0,0 +1,2067 @@
+#!/usr/bin/env perl
+#
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+# project. The module is, however, dual licensed under OpenSSL and
+# CRYPTOGAMS licenses depending on where you obtain it. For further
+# details see http://www.openssl.org/~appro/cryptogams/.
+# ====================================================================
+#
+# sha1_block procedure for x86_64.
+#
+# It was brought to my attention that on EM64T compiler-generated code
+# was far behind 32-bit assembler implementation. This is unlike on
+# Opteron where compiler-generated code was only 15% behind 32-bit
+# assembler, which originally made it hard to motivate the effort.
+# There was suggestion to mechanically translate 32-bit code, but I
+# dismissed it, reasoning that x86_64 offers enough register bank
+# capacity to fully utilize SHA-1 parallelism. Therefore this fresh
+# implementation:-) However! While 64-bit code does perform better
+# on Opteron, I failed to beat 32-bit assembler on EM64T core. Well,
+# x86_64 does offer larger *addressable* bank, but out-of-order core
+# reaches for even more registers through dynamic aliasing, and EM64T
+# core must have managed to run-time optimize even 32-bit code just as
+# good as 64-bit one. Performance improvement is summarized in the
+# following table:
+#
+# gcc 3.4 32-bit asm cycles/byte
+# Opteron +45% +20% 6.8
+# Xeon P4 +65% +0% 9.9
+# Core2 +60% +10% 7.0
+
+# August 2009.
+#
+# The code was revised to minimize code size and to maximize
+# "distance" between instructions producing input to 'lea'
+# instruction and the 'lea' instruction itself, which is essential
+# for Intel Atom core.
+
+# October 2010.
+#
+# Add SSSE3, Supplemental[!] SSE3, implementation. The idea behind it
+# is to offload message schedule denoted by Wt in NIST specification,
+# or Xupdate in OpenSSL source, to SIMD unit. See sha1-586.pl module
+# for background and implementation details. The only difference from
+# 32-bit code is that 64-bit code doesn't have to spill @X[] elements
+# to free temporary registers.
+
+# April 2011.
+#
+# Add AVX code path. See sha1-586.pl for further information.
+
+# May 2013.
+#
+# Add AVX2+BMI code path. Initial attempt (utilizing BMI instructions
+# and loading pair of consecutive blocks to 256-bit %ymm registers)
+# did not provide impressive performance improvement till a crucial
+# hint regarding the number of Xupdate iterations to pre-compute in
+# advance was provided by Ilya Albrekht of Intel Corp.
+
+# March 2014.
+#
+# Add support for Intel SHA Extensions.
+
+######################################################################
+# Current performance is summarized in following table. Numbers are
+# CPU clock cycles spent to process single byte (less is better).
+#
+# x86_64 SSSE3 AVX[2]
+# P4 9.05 -
+# Opteron 6.26 -
+# Core2 6.55 6.05/+8% -
+# Westmere 6.73 5.30/+27% -
+# Sandy Bridge 7.70 6.10/+26% 4.99/+54%
+# Ivy Bridge 6.06 4.67/+30% 4.60/+32%
+# Haswell 5.45 4.15/+31% 3.57/+53%
+# Bulldozer 9.11 5.95/+53%
+# VIA Nano 9.32 7.15/+30%
+# Atom 10.3 9.17/+12%
+# Silvermont 13.1(*) 9.37/+40%
+#
+# (*) obviously suboptimal result, nothing was done about it,
+# because SSSE3 code is compiled unconditionally;
+
+$flavour = shift;
+$output = shift;
+if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+
+$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
+( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
+die "can't locate x86_64-xlate.pl";
+
+if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
+ =~ /GNU assembler version ([2-9]\.[0-9]+)/) {
+ $avx = ($1>=2.19) + ($1>=2.22);
+}
+
+if (!$avx && $win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) &&
+ `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)/) {
+ $avx = ($1>=2.09) + ($1>=2.10);
+}
+
+if (!$avx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) &&
+ `ml64 2>&1` =~ /Version ([0-9]+)\./) {
+ $avx = ($1>=10) + ($1>=11);
+}
+
+if (!$avx && `$ENV{CC} -v 2>&1` =~ /(^clang version|based on LLVM) ([2-9]\.[0-9]+)/) {
+ $avx = ($2>=3.0) + ($2>3.0);
+}
+
+$shaext=0; ### set to zero if compiling for 1.0.1
+$avx=1 if (!$shaext && $avx);
+
+open OUT,"| \"$^X\" $xlate $flavour $output";
+*STDOUT=*OUT;
+
+$ctx="%rdi"; # 1st arg
+$inp="%rsi"; # 2nd arg
+$num="%rdx"; # 3rd arg
+
+# reassign arguments in order to produce more compact code
+$ctx="%r8";
+$inp="%r9";
+$num="%r10";
+
+$t0="%eax";
+$t1="%ebx";
+$t2="%ecx";
+@xi=("%edx","%ebp","%r14d");
+$A="%esi";
+$B="%edi";
+$C="%r11d";
+$D="%r12d";
+$E="%r13d";
+
+@V=($A,$B,$C,$D,$E);
+
+sub BODY_00_19 {
+my ($i,$a,$b,$c,$d,$e)=@_;
+my $j=$i+1;
+$code.=<<___ if ($i==0);
+ mov `4*$i`($inp),$xi[0]
+ bswap $xi[0]
+___
+$code.=<<___ if ($i<15);
+ mov `4*$j`($inp),$xi[1]
+ mov $d,$t0
+ mov $xi[0],`4*$i`(%rsp)
+ mov $a,$t2
+ bswap $xi[1]
+ xor $c,$t0
+ rol \$5,$t2
+ and $b,$t0
+ lea 0x5a827999($xi[0],$e),$e
+ add $t2,$e
+ xor $d,$t0
+ rol \$30,$b
+ add $t0,$e
+___
+$code.=<<___ if ($i>=15);
+ xor `4*($j%16)`(%rsp),$xi[1]
+ mov $d,$t0
+ mov $xi[0],`4*($i%16)`(%rsp)
+ mov $a,$t2
+ xor `4*(($j+2)%16)`(%rsp),$xi[1]
+ xor $c,$t0
+ rol \$5,$t2
+ xor `4*(($j+8)%16)`(%rsp),$xi[1]
+ and $b,$t0
+ lea 0x5a827999($xi[0],$e),$e
+ rol \$30,$b
+ xor $d,$t0
+ add $t2,$e
+ rol \$1,$xi[1]
+ add $t0,$e
+___
+push(@xi,shift(@xi));
+}
+
+sub BODY_20_39 {
+my ($i,$a,$b,$c,$d,$e)=@_;
+my $j=$i+1;
+my $K=($i<40)?0x6ed9eba1:0xca62c1d6;
+$code.=<<___ if ($i<79);
+ xor `4*($j%16)`(%rsp),$xi[1]
+ mov $b,$t0
+ `"mov $xi[0],".4*($i%16)."(%rsp)" if ($i<72)`
+ mov $a,$t2
+ xor `4*(($j+2)%16)`(%rsp),$xi[1]
+ xor $d,$t0
+ rol \$5,$t2
+ xor `4*(($j+8)%16)`(%rsp),$xi[1]
+ lea $K($xi[0],$e),$e
+ xor $c,$t0
+ add $t2,$e
+ rol \$30,$b
+ add $t0,$e
+ rol \$1,$xi[1]
+___
+$code.=<<___ if ($i==79);
+ mov $b,$t0
+ mov $a,$t2
+ xor $d,$t0
+ lea $K($xi[0],$e),$e
+ rol \$5,$t2
+ xor $c,$t0
+ add $t2,$e
+ rol \$30,$b
+ add $t0,$e
+___
+push(@xi,shift(@xi));
+}
+
+sub BODY_40_59 {
+my ($i,$a,$b,$c,$d,$e)=@_;
+my $j=$i+1;
+$code.=<<___;
+ xor `4*($j%16)`(%rsp),$xi[1]
+ mov $d,$t0
+ mov $xi[0],`4*($i%16)`(%rsp)
+ mov $d,$t1
+ xor `4*(($j+2)%16)`(%rsp),$xi[1]
+ and $c,$t0
+ mov $a,$t2
+ xor `4*(($j+8)%16)`(%rsp),$xi[1]
+ lea 0x8f1bbcdc($xi[0],$e),$e
+ xor $c,$t1
+ rol \$5,$t2
+ add $t0,$e
+ rol \$1,$xi[1]
+ and $b,$t1
+ add $t2,$e
+ rol \$30,$b
+ add $t1,$e
+___
+push(@xi,shift(@xi));
+}
+
+$code.=<<___;
+.text
+.extern OPENSSL_ia32cap_P
+
+.globl sha1_block_data_order
+.type sha1_block_data_order,\@function,3
+.align 16
+sha1_block_data_order:
+ mov OPENSSL_ia32cap_P+0(%rip),%r9d
+ mov OPENSSL_ia32cap_P+4(%rip),%r8d
+ mov OPENSSL_ia32cap_P+8(%rip),%r10d
+ test \$`1<<9`,%r8d # check SSSE3 bit
+ jz .Lialu
+___
+$code.=<<___ if ($shaext);
+ test \$`1<<29`,%r10d # check SHA bit
+ jnz _shaext_shortcut
+___
+$code.=<<___ if ($avx>1);
+ and \$`1<<3|1<<5|1<<8`,%r10d # check AVX2+BMI1+BMI2
+ cmp \$`1<<3|1<<5|1<<8`,%r10d
+ je _avx2_shortcut
+___
+$code.=<<___ if ($avx);
+ and \$`1<<28`,%r8d # mask AVX bit
+ and \$`1<<30`,%r9d # mask "Intel CPU" bit
+ or %r9d,%r8d
+ cmp \$`1<<28|1<<30`,%r8d
+ je _avx_shortcut
+___
+$code.=<<___;
+ jmp _ssse3_shortcut
+
+.align 16
+.Lialu:
+ mov %rsp,%rax
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ mov %rdi,$ctx # reassigned argument
+ sub \$`8+16*4`,%rsp
+ mov %rsi,$inp # reassigned argument
+ and \$-64,%rsp
+ mov %rdx,$num # reassigned argument
+ mov %rax,`16*4`(%rsp)
+.Lprologue:
+
+ mov 0($ctx),$A
+ mov 4($ctx),$B
+ mov 8($ctx),$C
+ mov 12($ctx),$D
+ mov 16($ctx),$E
+ jmp .Lloop
+
+.align 16
+.Lloop:
+___
+for($i=0;$i<20;$i++) { &BODY_00_19($i,@V); unshift(@V,pop(@V)); }
+for(;$i<40;$i++) { &BODY_20_39($i,@V); unshift(@V,pop(@V)); }
+for(;$i<60;$i++) { &BODY_40_59($i,@V); unshift(@V,pop(@V)); }
+for(;$i<80;$i++) { &BODY_20_39($i,@V); unshift(@V,pop(@V)); }
+$code.=<<___;
+ add 0($ctx),$A
+ add 4($ctx),$B
+ add 8($ctx),$C
+ add 12($ctx),$D
+ add 16($ctx),$E
+ mov $A,0($ctx)
+ mov $B,4($ctx)
+ mov $C,8($ctx)
+ mov $D,12($ctx)
+ mov $E,16($ctx)
+
+ sub \$1,$num
+ lea `16*4`($inp),$inp
+ jnz .Lloop
+
+ mov `16*4`(%rsp),%rsi
+ mov -40(%rsi),%r14
+ mov -32(%rsi),%r13
+ mov -24(%rsi),%r12
+ mov -16(%rsi),%rbp
+ mov -8(%rsi),%rbx
+ lea (%rsi),%rsp
+.Lepilogue:
+ ret
+.size sha1_block_data_order,.-sha1_block_data_order
+___
+if ($shaext) {{{
+######################################################################
+# Intel SHA Extensions implementation of SHA1 update function.
+#
+my ($ctx,$inp,$num)=("%rdi","%rsi","%rdx");
+my ($ABCD,$E,$E_,$BSWAP,$ABCD_SAVE,$E_SAVE)=map("%xmm$_",(0..3,8,9));
+my @MSG=map("%xmm$_",(4..7));
+
+$code.=<<___;
+.type sha1_block_data_order_shaext,\@function,3
+.align 32
+sha1_block_data_order_shaext:
+_shaext_shortcut:
+___
+$code.=<<___ if ($win64);
+ lea `-8-4*16`(%rsp),%rsp
+ movaps %xmm6,-8-4*16(%rax)
+ movaps %xmm7,-8-3*16(%rax)
+ movaps %xmm8,-8-2*16(%rax)
+ movaps %xmm9,-8-1*16(%rax)
+.Lprologue_shaext:
+___
+$code.=<<___;
+ movdqu ($ctx),$ABCD
+ movd 16($ctx),$E
+ movdqa K_XX_XX+0xa0(%rip),$BSWAP # byte-n-word swap
+
+ movdqu ($inp),@MSG[0]
+ pshufd \$0b00011011,$ABCD,$ABCD # flip word order
+ movdqu 0x10($inp),@MSG[1]
+ pshufd \$0b00011011,$E,$E # flip word order
+ movdqu 0x20($inp),@MSG[2]
+ pshufb $BSWAP,@MSG[0]
+ movdqu 0x30($inp),@MSG[3]
+ pshufb $BSWAP,@MSG[1]
+ pshufb $BSWAP,@MSG[2]
+ movdqa $E,$E_SAVE # offload $E
+ pshufb $BSWAP,@MSG[3]
+ jmp .Loop_shaext
+
+.align 16
+.Loop_shaext:
+ dec $num
+ lea 0x40($inp),%rax # next input block
+ paddd @MSG[0],$E
+ cmovne %rax,$inp
+ movdqa $ABCD,$ABCD_SAVE # offload $ABCD
+___
+for($i=0;$i<20-4;$i+=2) {
+$code.=<<___;
+ sha1msg1 @MSG[1],@MSG[0]
+ movdqa $ABCD,$E_
+ sha1rnds4 \$`int($i/5)`,$E,$ABCD # 0-3...
+ sha1nexte @MSG[1],$E_
+ pxor @MSG[2],@MSG[0]
+ sha1msg1 @MSG[2],@MSG[1]
+ sha1msg2 @MSG[3],@MSG[0]
+
+ movdqa $ABCD,$E
+ sha1rnds4 \$`int(($i+1)/5)`,$E_,$ABCD
+ sha1nexte @MSG[2],$E
+ pxor @MSG[3],@MSG[1]
+ sha1msg2 @MSG[0],@MSG[1]
+___
+ push(@MSG,shift(@MSG)); push(@MSG,shift(@MSG));
+}
+$code.=<<___;
+ movdqu ($inp),@MSG[0]
+ movdqa $ABCD,$E_
+ sha1rnds4 \$3,$E,$ABCD # 64-67
+ sha1nexte @MSG[1],$E_
+ movdqu 0x10($inp),@MSG[1]
+ pshufb $BSWAP,@MSG[0]
+
+ movdqa $ABCD,$E
+ sha1rnds4 \$3,$E_,$ABCD # 68-71
+ sha1nexte @MSG[2],$E
+ movdqu 0x20($inp),@MSG[2]
+ pshufb $BSWAP,@MSG[1]
+
+ movdqa $ABCD,$E_
+ sha1rnds4 \$3,$E,$ABCD # 72-75
+ sha1nexte @MSG[3],$E_
+ movdqu 0x30($inp),@MSG[3]
+ pshufb $BSWAP,@MSG[2]
+
+ movdqa $ABCD,$E
+ sha1rnds4 \$3,$E_,$ABCD # 76-79
+ sha1nexte $E_SAVE,$E
+ pshufb $BSWAP,@MSG[3]
+
+ paddd $ABCD_SAVE,$ABCD
+ movdqa $E,$E_SAVE # offload $E
+
+ jnz .Loop_shaext
+
+ pshufd \$0b00011011,$ABCD,$ABCD
+ pshufd \$0b00011011,$E,$E
+ movdqu $ABCD,($ctx)
+ movd $E,16($ctx)
+___
+$code.=<<___ if ($win64);
+ movaps -8-4*16(%rax),%xmm6
+ movaps -8-3*16(%rax),%xmm7
+ movaps -8-2*16(%rax),%xmm8
+ movaps -8-1*16(%rax),%xmm9
+ mov %rax,%rsp
+.Lepilogue_shaext:
+___
+$code.=<<___;
+ ret
+.size sha1_block_data_order_shaext,.-sha1_block_data_order_shaext
+___
+}}}
+{{{
+my $Xi=4;
+my @X=map("%xmm$_",(4..7,0..3));
+my @Tx=map("%xmm$_",(8..10));
+my $Kx="%xmm11";
+my @V=($A,$B,$C,$D,$E)=("%eax","%ebx","%ecx","%edx","%ebp"); # size optimization
+my @T=("%esi","%edi");
+my $j=0;
+my $rx=0;
+my $K_XX_XX="%r11";
+
+my $_rol=sub { &rol(@_) };
+my $_ror=sub { &ror(@_) };
+
+{ my $sn;
+sub align32() {
+ ++$sn;
+$code.=<<___;
+ jmp .Lalign32_$sn # see "Decoded ICache" in manual
+.align 32
+.Lalign32_$sn:
+___
+}
+}
+
+$code.=<<___;
+.type sha1_block_data_order_ssse3,\@function,3
+.align 16
+sha1_block_data_order_ssse3:
+_ssse3_shortcut:
+ mov %rsp,%rax
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13 # redundant, done to share Win64 SE handler
+ push %r14
+ lea `-64-($win64?6*16:0)`(%rsp),%rsp
+___
+$code.=<<___ if ($win64);
+ movaps %xmm6,-40-6*16(%rax)
+ movaps %xmm7,-40-5*16(%rax)
+ movaps %xmm8,-40-4*16(%rax)
+ movaps %xmm9,-40-3*16(%rax)
+ movaps %xmm10,-40-2*16(%rax)
+ movaps %xmm11,-40-1*16(%rax)
+.Lprologue_ssse3:
+___
+$code.=<<___;
+ mov %rax,%r14 # original %rsp
+ and \$-64,%rsp
+ mov %rdi,$ctx # reassigned argument
+ mov %rsi,$inp # reassigned argument
+ mov %rdx,$num # reassigned argument
+
+ shl \$6,$num
+ add $inp,$num
+ lea K_XX_XX+64(%rip),$K_XX_XX
+
+ mov 0($ctx),$A # load context
+ mov 4($ctx),$B
+ mov 8($ctx),$C
+ mov 12($ctx),$D
+ mov $B,@T[0] # magic seed
+ mov 16($ctx),$E
+ mov $C,@T[1]
+ xor $D,@T[1]
+ and @T[1],@T[0]
+
+ movdqa 64($K_XX_XX),@X[2] # pbswap mask
+ movdqa -64($K_XX_XX),@Tx[1] # K_00_19
+ movdqu 0($inp),@X[-4&7] # load input to %xmm[0-3]
+ movdqu 16($inp),@X[-3&7]
+ movdqu 32($inp),@X[-2&7]
+ movdqu 48($inp),@X[-1&7]
+ pshufb @X[2],@X[-4&7] # byte swap
+ pshufb @X[2],@X[-3&7]
+ pshufb @X[2],@X[-2&7]
+ add \$64,$inp
+ paddd @Tx[1],@X[-4&7] # add K_00_19
+ pshufb @X[2],@X[-1&7]
+ paddd @Tx[1],@X[-3&7]
+ paddd @Tx[1],@X[-2&7]
+ movdqa @X[-4&7],0(%rsp) # X[]+K xfer to IALU
+ psubd @Tx[1],@X[-4&7] # restore X[]
+ movdqa @X[-3&7],16(%rsp)
+ psubd @Tx[1],@X[-3&7]
+ movdqa @X[-2&7],32(%rsp)
+ psubd @Tx[1],@X[-2&7]
+ jmp .Loop_ssse3
+___
+
+sub AUTOLOAD() # thunk [simplified] 32-bit style perlasm
+{ my $opcode = $AUTOLOAD; $opcode =~ s/.*:://;
+ my $arg = pop;
+ $arg = "\$$arg" if ($arg*1 eq $arg);
+ $code .= "\t$opcode\t".join(',',$arg,reverse @_)."\n";
+}
+
+sub Xupdate_ssse3_16_31() # recall that $Xi starts wtih 4
+{ use integer;
+ my $body = shift;
+ my @insns = (&$body,&$body,&$body,&$body); # 40 instructions
+ my ($a,$b,$c,$d,$e);
+
+ eval(shift(@insns)); # ror
+ &pshufd (@X[0],@X[-4&7],0xee); # was &movdqa (@X[0],@X[-3&7]);
+ eval(shift(@insns));
+ &movdqa (@Tx[0],@X[-1&7]);
+ &paddd (@Tx[1],@X[-1&7]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ &punpcklqdq(@X[0],@X[-3&7]); # compose "X[-14]" in "X[0]", was &palignr(@X[0],@X[-4&7],8);
+ eval(shift(@insns));
+ eval(shift(@insns)); # rol
+ eval(shift(@insns));
+ &psrldq (@Tx[0],4); # "X[-3]", 3 dwords
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ &pxor (@X[0],@X[-4&7]); # "X[0]"^="X[-16]"
+ eval(shift(@insns));
+ eval(shift(@insns)); # ror
+ &pxor (@Tx[0],@X[-2&7]); # "X[-3]"^"X[-8]"
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ &pxor (@X[0],@Tx[0]); # "X[0]"^="X[-3]"^"X[-8]"
+ eval(shift(@insns));
+ eval(shift(@insns)); # rol
+ &movdqa (eval(16*(($Xi-1)&3))."(%rsp)",@Tx[1]); # X[]+K xfer to IALU
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ &movdqa (@Tx[2],@X[0]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns)); # ror
+ &movdqa (@Tx[0],@X[0]);
+ eval(shift(@insns));
+
+ &pslldq (@Tx[2],12); # "X[0]"<<96, extract one dword
+ &paddd (@X[0],@X[0]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ &psrld (@Tx[0],31);
+ eval(shift(@insns));
+ eval(shift(@insns)); # rol
+ eval(shift(@insns));
+ &movdqa (@Tx[1],@Tx[2]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ &psrld (@Tx[2],30);
+ eval(shift(@insns));
+ eval(shift(@insns)); # ror
+ &por (@X[0],@Tx[0]); # "X[0]"<<<=1
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ &pslld (@Tx[1],2);
+ &pxor (@X[0],@Tx[2]);
+ eval(shift(@insns));
+ &movdqa (@Tx[2],eval(2*16*(($Xi)/5)-64)."($K_XX_XX)"); # K_XX_XX
+ eval(shift(@insns)); # rol
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ &pxor (@X[0],@Tx[1]); # "X[0]"^=("X[0]">>96)<<<2
+ &pshufd (@Tx[1],@X[-1&7],0xee) if ($Xi==7); # was &movdqa (@Tx[0],@X[-1&7]) in Xupdate_ssse3_32_79
+
+ foreach (@insns) { eval; } # remaining instructions [if any]
+
+ $Xi++; push(@X,shift(@X)); # "rotate" X[]
+ push(@Tx,shift(@Tx));
+}
+
+sub Xupdate_ssse3_32_79()
+{ use integer;
+ my $body = shift;
+ my @insns = (&$body,&$body,&$body,&$body); # 32 to 44 instructions
+ my ($a,$b,$c,$d,$e);
+
+ eval(shift(@insns)) if ($Xi==8);
+ &pxor (@X[0],@X[-4&7]); # "X[0]"="X[-32]"^"X[-16]"
+ eval(shift(@insns)) if ($Xi==8);
+ eval(shift(@insns)); # body_20_39
+ eval(shift(@insns));
+ eval(shift(@insns)) if (@insns[1] =~ /_ror/);
+ eval(shift(@insns)) if (@insns[0] =~ /_ror/);
+ &punpcklqdq(@Tx[0],@X[-1&7]); # compose "X[-6]", was &palignr(@Tx[0],@X[-2&7],8);
+ eval(shift(@insns));
+ eval(shift(@insns)); # rol
+
+ &pxor (@X[0],@X[-7&7]); # "X[0]"^="X[-28]"
+ eval(shift(@insns));
+ eval(shift(@insns));
+ if ($Xi%5) {
+ &movdqa (@Tx[2],@Tx[1]);# "perpetuate" K_XX_XX...
+ } else { # ... or load next one
+ &movdqa (@Tx[2],eval(2*16*($Xi/5)-64)."($K_XX_XX)");
+ }
+ eval(shift(@insns)); # ror
+ &paddd (@Tx[1],@X[-1&7]);
+ eval(shift(@insns));
+
+ &pxor (@X[0],@Tx[0]); # "X[0]"^="X[-6]"
+ eval(shift(@insns)); # body_20_39
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns)); # rol
+ eval(shift(@insns)) if (@insns[0] =~ /_ror/);
+
+ &movdqa (@Tx[0],@X[0]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &movdqa (eval(16*(($Xi-1)&3))."(%rsp)",@Tx[1]); # X[]+K xfer to IALU
+ eval(shift(@insns)); # ror
+ eval(shift(@insns));
+ eval(shift(@insns)); # body_20_39
+
+ &pslld (@X[0],2);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &psrld (@Tx[0],30);
+ eval(shift(@insns)) if (@insns[0] =~ /_rol/);# rol
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns)); # ror
+
+ &por (@X[0],@Tx[0]); # "X[0]"<<<=2
+ eval(shift(@insns));
+ eval(shift(@insns)); # body_20_39
+ eval(shift(@insns)) if (@insns[1] =~ /_rol/);
+ eval(shift(@insns)) if (@insns[0] =~ /_rol/);
+ &pshufd(@Tx[1],@X[-1&7],0xee) if ($Xi<19); # was &movdqa (@Tx[1],@X[0])
+ eval(shift(@insns));
+ eval(shift(@insns)); # rol
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns)); # rol
+ eval(shift(@insns));
+
+ foreach (@insns) { eval; } # remaining instructions
+
+ $Xi++; push(@X,shift(@X)); # "rotate" X[]
+ push(@Tx,shift(@Tx));
+}
+
+sub Xuplast_ssse3_80()
+{ use integer;
+ my $body = shift;
+ my @insns = (&$body,&$body,&$body,&$body); # 32 instructions
+ my ($a,$b,$c,$d,$e);
+
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &paddd (@Tx[1],@X[-1&7]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ &movdqa (eval(16*(($Xi-1)&3))."(%rsp)",@Tx[1]); # X[]+K xfer IALU
+
+ foreach (@insns) { eval; } # remaining instructions
+
+ &cmp ($inp,$num);
+ &je (".Ldone_ssse3");
+
+ unshift(@Tx,pop(@Tx));
+
+ &movdqa (@X[2],"64($K_XX_XX)"); # pbswap mask
+ &movdqa (@Tx[1],"-64($K_XX_XX)"); # K_00_19
+ &movdqu (@X[-4&7],"0($inp)"); # load input
+ &movdqu (@X[-3&7],"16($inp)");
+ &movdqu (@X[-2&7],"32($inp)");
+ &movdqu (@X[-1&7],"48($inp)");
+ &pshufb (@X[-4&7],@X[2]); # byte swap
+ &add ($inp,64);
+
+ $Xi=0;
+}
+
+sub Xloop_ssse3()
+{ use integer;
+ my $body = shift;
+ my @insns = (&$body,&$body,&$body,&$body); # 32 instructions
+ my ($a,$b,$c,$d,$e);
+
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &pshufb (@X[($Xi-3)&7],@X[2]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &paddd (@X[($Xi-4)&7],@Tx[1]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &movdqa (eval(16*$Xi)."(%rsp)",@X[($Xi-4)&7]); # X[]+K xfer to IALU
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &psubd (@X[($Xi-4)&7],@Tx[1]);
+
+ foreach (@insns) { eval; }
+ $Xi++;
+}
+
+sub Xtail_ssse3()
+{ use integer;
+ my $body = shift;
+ my @insns = (&$body,&$body,&$body,&$body); # 32 instructions
+ my ($a,$b,$c,$d,$e);
+
+ foreach (@insns) { eval; }
+}
+
+sub body_00_19 () { # ((c^d)&b)^d
+ # on start @T[0]=(c^d)&b
+ return &body_20_39() if ($rx==19); $rx++;
+ (
+ '($a,$b,$c,$d,$e)=@V;'.
+ '&$_ror ($b,$j?7:2)', # $b>>>2
+ '&xor (@T[0],$d)',
+ '&mov (@T[1],$a)', # $b for next round
+
+ '&add ($e,eval(4*($j&15))."(%rsp)")', # X[]+K xfer
+ '&xor ($b,$c)', # $c^$d for next round
+
+ '&$_rol ($a,5)',
+ '&add ($e,@T[0])',
+ '&and (@T[1],$b)', # ($b&($c^$d)) for next round
+
+ '&xor ($b,$c)', # restore $b
+ '&add ($e,$a);' .'$j++; unshift(@V,pop(@V)); unshift(@T,pop(@T));'
+ );
+}
+
+sub body_20_39 () { # b^d^c
+ # on entry @T[0]=b^d
+ return &body_40_59() if ($rx==39); $rx++;
+ (
+ '($a,$b,$c,$d,$e)=@V;'.
+ '&add ($e,eval(4*($j&15))."(%rsp)")', # X[]+K xfer
+ '&xor (@T[0],$d) if($j==19);'.
+ '&xor (@T[0],$c) if($j> 19)', # ($b^$d^$c)
+ '&mov (@T[1],$a)', # $b for next round
+
+ '&$_rol ($a,5)',
+ '&add ($e,@T[0])',
+ '&xor (@T[1],$c) if ($j< 79)', # $b^$d for next round
+
+ '&$_ror ($b,7)', # $b>>>2
+ '&add ($e,$a);' .'$j++; unshift(@V,pop(@V)); unshift(@T,pop(@T));'
+ );
+}
+
+sub body_40_59 () { # ((b^c)&(c^d))^c
+ # on entry @T[0]=(b^c), (c^=d)
+ $rx++;
+ (
+ '($a,$b,$c,$d,$e)=@V;'.
+ '&add ($e,eval(4*($j&15))."(%rsp)")', # X[]+K xfer
+ '&and (@T[0],$c) if ($j>=40)', # (b^c)&(c^d)
+ '&xor ($c,$d) if ($j>=40)', # restore $c
+
+ '&$_ror ($b,7)', # $b>>>2
+ '&mov (@T[1],$a)', # $b for next round
+ '&xor (@T[0],$c)',
+
+ '&$_rol ($a,5)',
+ '&add ($e,@T[0])',
+ '&xor (@T[1],$c) if ($j==59);'.
+ '&xor (@T[1],$b) if ($j< 59)', # b^c for next round
+
+ '&xor ($b,$c) if ($j< 59)', # c^d for next round
+ '&add ($e,$a);' .'$j++; unshift(@V,pop(@V)); unshift(@T,pop(@T));'
+ );
+}
+$code.=<<___;
+.align 16
+.Loop_ssse3:
+___
+ &Xupdate_ssse3_16_31(\&body_00_19);
+ &Xupdate_ssse3_16_31(\&body_00_19);
+ &Xupdate_ssse3_16_31(\&body_00_19);
+ &Xupdate_ssse3_16_31(\&body_00_19);
+ &Xupdate_ssse3_32_79(\&body_00_19);
+ &Xupdate_ssse3_32_79(\&body_20_39);
+ &Xupdate_ssse3_32_79(\&body_20_39);
+ &Xupdate_ssse3_32_79(\&body_20_39);
+ &Xupdate_ssse3_32_79(\&body_20_39);
+ &Xupdate_ssse3_32_79(\&body_20_39);
+ &Xupdate_ssse3_32_79(\&body_40_59);
+ &Xupdate_ssse3_32_79(\&body_40_59);
+ &Xupdate_ssse3_32_79(\&body_40_59);
+ &Xupdate_ssse3_32_79(\&body_40_59);
+ &Xupdate_ssse3_32_79(\&body_40_59);
+ &Xupdate_ssse3_32_79(\&body_20_39);
+ &Xuplast_ssse3_80(\&body_20_39); # can jump to "done"
+
+ $saved_j=$j; @saved_V=@V;
+
+ &Xloop_ssse3(\&body_20_39);
+ &Xloop_ssse3(\&body_20_39);
+ &Xloop_ssse3(\&body_20_39);
+
+$code.=<<___;
+ add 0($ctx),$A # update context
+ add 4($ctx),@T[0]
+ add 8($ctx),$C
+ add 12($ctx),$D
+ mov $A,0($ctx)
+ add 16($ctx),$E
+ mov @T[0],4($ctx)
+ mov @T[0],$B # magic seed
+ mov $C,8($ctx)
+ mov $C,@T[1]
+ mov $D,12($ctx)
+ xor $D,@T[1]
+ mov $E,16($ctx)
+ and @T[1],@T[0]
+ jmp .Loop_ssse3
+
+.align 16
+.Ldone_ssse3:
+___
+ $j=$saved_j; @V=@saved_V;
+
+ &Xtail_ssse3(\&body_20_39);
+ &Xtail_ssse3(\&body_20_39);
+ &Xtail_ssse3(\&body_20_39);
+
+$code.=<<___;
+ add 0($ctx),$A # update context
+ add 4($ctx),@T[0]
+ add 8($ctx),$C
+ mov $A,0($ctx)
+ add 12($ctx),$D
+ mov @T[0],4($ctx)
+ add 16($ctx),$E
+ mov $C,8($ctx)
+ mov $D,12($ctx)
+ mov $E,16($ctx)
+___
+$code.=<<___ if ($win64);
+ movaps -40-6*16(%r14),%xmm6
+ movaps -40-5*16(%r14),%xmm7
+ movaps -40-4*16(%r14),%xmm8
+ movaps -40-3*16(%r14),%xmm9
+ movaps -40-2*16(%r14),%xmm10
+ movaps -40-1*16(%r14),%xmm11
+___
+$code.=<<___;
+ lea (%r14),%rsi
+ mov -40(%rsi),%r14
+ mov -32(%rsi),%r13
+ mov -24(%rsi),%r12
+ mov -16(%rsi),%rbp
+ mov -8(%rsi),%rbx
+ lea (%rsi),%rsp
+.Lepilogue_ssse3:
+ ret
+.size sha1_block_data_order_ssse3,.-sha1_block_data_order_ssse3
+___
+
+if ($avx) {
+$Xi=4; # reset variables
+@X=map("%xmm$_",(4..7,0..3));
+@Tx=map("%xmm$_",(8..10));
+$j=0;
+$rx=0;
+
+my $done_avx_label=".Ldone_avx";
+
+my $_rol=sub { &shld(@_[0],@_) };
+my $_ror=sub { &shrd(@_[0],@_) };
+
+$code.=<<___;
+.type sha1_block_data_order_avx,\@function,3
+.align 16
+sha1_block_data_order_avx:
+_avx_shortcut:
+ mov %rsp,%rax
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13 # redundant, done to share Win64 SE handler
+ push %r14
+ lea `-64-($win64?6*16:0)`(%rsp),%rsp
+ vzeroupper
+___
+$code.=<<___ if ($win64);
+ vmovaps %xmm6,-40-6*16(%rax)
+ vmovaps %xmm7,-40-5*16(%rax)
+ vmovaps %xmm8,-40-4*16(%rax)
+ vmovaps %xmm9,-40-3*16(%rax)
+ vmovaps %xmm10,-40-2*16(%rax)
+ vmovaps %xmm11,-40-1*16(%rax)
+.Lprologue_avx:
+___
+$code.=<<___;
+ mov %rax,%r14 # original %rsp
+ and \$-64,%rsp
+ mov %rdi,$ctx # reassigned argument
+ mov %rsi,$inp # reassigned argument
+ mov %rdx,$num # reassigned argument
+
+ shl \$6,$num
+ add $inp,$num
+ lea K_XX_XX+64(%rip),$K_XX_XX
+
+ mov 0($ctx),$A # load context
+ mov 4($ctx),$B
+ mov 8($ctx),$C
+ mov 12($ctx),$D
+ mov $B,@T[0] # magic seed
+ mov 16($ctx),$E
+ mov $C,@T[1]
+ xor $D,@T[1]
+ and @T[1],@T[0]
+
+ vmovdqa 64($K_XX_XX),@X[2] # pbswap mask
+ vmovdqa -64($K_XX_XX),$Kx # K_00_19
+ vmovdqu 0($inp),@X[-4&7] # load input to %xmm[0-3]
+ vmovdqu 16($inp),@X[-3&7]
+ vmovdqu 32($inp),@X[-2&7]
+ vmovdqu 48($inp),@X[-1&7]
+ vpshufb @X[2],@X[-4&7],@X[-4&7] # byte swap
+ add \$64,$inp
+ vpshufb @X[2],@X[-3&7],@X[-3&7]
+ vpshufb @X[2],@X[-2&7],@X[-2&7]
+ vpshufb @X[2],@X[-1&7],@X[-1&7]
+ vpaddd $Kx,@X[-4&7],@X[0] # add K_00_19
+ vpaddd $Kx,@X[-3&7],@X[1]
+ vpaddd $Kx,@X[-2&7],@X[2]
+ vmovdqa @X[0],0(%rsp) # X[]+K xfer to IALU
+ vmovdqa @X[1],16(%rsp)
+ vmovdqa @X[2],32(%rsp)
+ jmp .Loop_avx
+___
+
+sub Xupdate_avx_16_31() # recall that $Xi starts wtih 4
+{ use integer;
+ my $body = shift;
+ my @insns = (&$body,&$body,&$body,&$body); # 40 instructions
+ my ($a,$b,$c,$d,$e);
+
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vpalignr(@X[0],@X[-3&7],@X[-4&7],8); # compose "X[-14]" in "X[0]"
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ &vpaddd (@Tx[1],$Kx,@X[-1&7]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vpsrldq(@Tx[0],@X[-1&7],4); # "X[-3]", 3 dwords
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vpxor (@X[0],@X[0],@X[-4&7]); # "X[0]"^="X[-16]"
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ &vpxor (@Tx[0],@Tx[0],@X[-2&7]); # "X[-3]"^"X[-8]"
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ &vpxor (@X[0],@X[0],@Tx[0]); # "X[0]"^="X[-3]"^"X[-8]"
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vmovdqa (eval(16*(($Xi-1)&3))."(%rsp)",@Tx[1]); # X[]+K xfer to IALU
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ &vpsrld (@Tx[0],@X[0],31);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ &vpslldq(@Tx[2],@X[0],12); # "X[0]"<<96, extract one dword
+ &vpaddd (@X[0],@X[0],@X[0]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ &vpsrld (@Tx[1],@Tx[2],30);
+ &vpor (@X[0],@X[0],@Tx[0]); # "X[0]"<<<=1
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ &vpslld (@Tx[2],@Tx[2],2);
+ &vpxor (@X[0],@X[0],@Tx[1]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ &vpxor (@X[0],@X[0],@Tx[2]); # "X[0]"^=("X[0]">>96)<<<2
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vmovdqa ($Kx,eval(2*16*(($Xi)/5)-64)."($K_XX_XX)") if ($Xi%5==0); # K_XX_XX
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+
+ foreach (@insns) { eval; } # remaining instructions [if any]
+
+ $Xi++; push(@X,shift(@X)); # "rotate" X[]
+}
+
+sub Xupdate_avx_32_79()
+{ use integer;
+ my $body = shift;
+ my @insns = (&$body,&$body,&$body,&$body); # 32 to 44 instructions
+ my ($a,$b,$c,$d,$e);
+
+ &vpalignr(@Tx[0],@X[-1&7],@X[-2&7],8); # compose "X[-6]"
+ &vpxor (@X[0],@X[0],@X[-4&7]); # "X[0]"="X[-32]"^"X[-16]"
+ eval(shift(@insns)); # body_20_39
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns)); # rol
+
+ &vpxor (@X[0],@X[0],@X[-7&7]); # "X[0]"^="X[-28]"
+ eval(shift(@insns));
+ eval(shift(@insns)) if (@insns[0] !~ /&ro[rl]/);
+ &vpaddd (@Tx[1],$Kx,@X[-1&7]);
+ &vmovdqa ($Kx,eval(2*16*($Xi/5)-64)."($K_XX_XX)") if ($Xi%5==0);
+ eval(shift(@insns)); # ror
+ eval(shift(@insns));
+
+ &vpxor (@X[0],@X[0],@Tx[0]); # "X[0]"^="X[-6]"
+ eval(shift(@insns)); # body_20_39
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns)); # rol
+
+ &vpsrld (@Tx[0],@X[0],30);
+ &vmovdqa (eval(16*(($Xi-1)&3))."(%rsp)",@Tx[1]); # X[]+K xfer to IALU
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns)); # ror
+ eval(shift(@insns));
+
+ &vpslld (@X[0],@X[0],2);
+ eval(shift(@insns)); # body_20_39
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns)); # rol
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns)); # ror
+ eval(shift(@insns));
+
+ &vpor (@X[0],@X[0],@Tx[0]); # "X[0]"<<<=2
+ eval(shift(@insns)); # body_20_39
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns)); # rol
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns)); # rol
+ eval(shift(@insns));
+
+ foreach (@insns) { eval; } # remaining instructions
+
+ $Xi++; push(@X,shift(@X)); # "rotate" X[]
+}
+
+sub Xuplast_avx_80()
+{ use integer;
+ my $body = shift;
+ my @insns = (&$body,&$body,&$body,&$body); # 32 instructions
+ my ($a,$b,$c,$d,$e);
+
+ eval(shift(@insns));
+ &vpaddd (@Tx[1],$Kx,@X[-1&7]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ &vmovdqa (eval(16*(($Xi-1)&3))."(%rsp)",@Tx[1]); # X[]+K xfer IALU
+
+ foreach (@insns) { eval; } # remaining instructions
+
+ &cmp ($inp,$num);
+ &je ($done_avx_label);
+
+ &vmovdqa(@X[2],"64($K_XX_XX)"); # pbswap mask
+ &vmovdqa($Kx,"-64($K_XX_XX)"); # K_00_19
+ &vmovdqu(@X[-4&7],"0($inp)"); # load input
+ &vmovdqu(@X[-3&7],"16($inp)");
+ &vmovdqu(@X[-2&7],"32($inp)");
+ &vmovdqu(@X[-1&7],"48($inp)");
+ &vpshufb(@X[-4&7],@X[-4&7],@X[2]); # byte swap
+ &add ($inp,64);
+
+ $Xi=0;
+}
+
+sub Xloop_avx()
+{ use integer;
+ my $body = shift;
+ my @insns = (&$body,&$body,&$body,&$body); # 32 instructions
+ my ($a,$b,$c,$d,$e);
+
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vpshufb(@X[($Xi-3)&7],@X[($Xi-3)&7],@X[2]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vpaddd (@X[$Xi&7],@X[($Xi-4)&7],$Kx);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vmovdqa(eval(16*$Xi)."(%rsp)",@X[$Xi&7]); # X[]+K xfer to IALU
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ foreach (@insns) { eval; }
+ $Xi++;
+}
+
+sub Xtail_avx()
+{ use integer;
+ my $body = shift;
+ my @insns = (&$body,&$body,&$body,&$body); # 32 instructions
+ my ($a,$b,$c,$d,$e);
+
+ foreach (@insns) { eval; }
+}
+
+$code.=<<___;
+.align 16
+.Loop_avx:
+___
+ &Xupdate_avx_16_31(\&body_00_19);
+ &Xupdate_avx_16_31(\&body_00_19);
+ &Xupdate_avx_16_31(\&body_00_19);
+ &Xupdate_avx_16_31(\&body_00_19);
+ &Xupdate_avx_32_79(\&body_00_19);
+ &Xupdate_avx_32_79(\&body_20_39);
+ &Xupdate_avx_32_79(\&body_20_39);
+ &Xupdate_avx_32_79(\&body_20_39);
+ &Xupdate_avx_32_79(\&body_20_39);
+ &Xupdate_avx_32_79(\&body_20_39);
+ &Xupdate_avx_32_79(\&body_40_59);
+ &Xupdate_avx_32_79(\&body_40_59);
+ &Xupdate_avx_32_79(\&body_40_59);
+ &Xupdate_avx_32_79(\&body_40_59);
+ &Xupdate_avx_32_79(\&body_40_59);
+ &Xupdate_avx_32_79(\&body_20_39);
+ &Xuplast_avx_80(\&body_20_39); # can jump to "done"
+
+ $saved_j=$j; @saved_V=@V;
+
+ &Xloop_avx(\&body_20_39);
+ &Xloop_avx(\&body_20_39);
+ &Xloop_avx(\&body_20_39);
+
+$code.=<<___;
+ add 0($ctx),$A # update context
+ add 4($ctx),@T[0]
+ add 8($ctx),$C
+ add 12($ctx),$D
+ mov $A,0($ctx)
+ add 16($ctx),$E
+ mov @T[0],4($ctx)
+ mov @T[0],$B # magic seed
+ mov $C,8($ctx)
+ mov $C,@T[1]
+ mov $D,12($ctx)
+ xor $D,@T[1]
+ mov $E,16($ctx)
+ and @T[1],@T[0]
+ jmp .Loop_avx
+
+.align 16
+$done_avx_label:
+___
+ $j=$saved_j; @V=@saved_V;
+
+ &Xtail_avx(\&body_20_39);
+ &Xtail_avx(\&body_20_39);
+ &Xtail_avx(\&body_20_39);
+
+$code.=<<___;
+ vzeroupper
+
+ add 0($ctx),$A # update context
+ add 4($ctx),@T[0]
+ add 8($ctx),$C
+ mov $A,0($ctx)
+ add 12($ctx),$D
+ mov @T[0],4($ctx)
+ add 16($ctx),$E
+ mov $C,8($ctx)
+ mov $D,12($ctx)
+ mov $E,16($ctx)
+___
+$code.=<<___ if ($win64);
+ movaps -40-6*16(%r14),%xmm6
+ movaps -40-5*16(%r14),%xmm7
+ movaps -40-4*16(%r14),%xmm8
+ movaps -40-3*16(%r14),%xmm9
+ movaps -40-2*16(%r14),%xmm10
+ movaps -40-1*16(%r14),%xmm11
+___
+$code.=<<___;
+ lea (%r14),%rsi
+ mov -40(%rsi),%r14
+ mov -32(%rsi),%r13
+ mov -24(%rsi),%r12
+ mov -16(%rsi),%rbp
+ mov -8(%rsi),%rbx
+ lea (%rsi),%rsp
+.Lepilogue_avx:
+ ret
+.size sha1_block_data_order_avx,.-sha1_block_data_order_avx
+___
+
+if ($avx>1) {
+use integer;
+$Xi=4; # reset variables
+@X=map("%ymm$_",(4..7,0..3));
+@Tx=map("%ymm$_",(8..10));
+$Kx="%ymm11";
+$j=0;
+
+my @ROTX=("%eax","%ebp","%ebx","%ecx","%edx","%esi");
+my ($a5,$t0)=("%r12d","%edi");
+
+my ($A,$F,$B,$C,$D,$E)=@ROTX;
+my $rx=0;
+my $frame="%r13";
+
+$code.=<<___;
+.type sha1_block_data_order_avx2,\@function,3
+.align 16
+sha1_block_data_order_avx2:
+_avx2_shortcut:
+ mov %rsp,%rax
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ vzeroupper
+___
+$code.=<<___ if ($win64);
+ lea -6*16(%rsp),%rsp
+ vmovaps %xmm6,-40-6*16(%rax)
+ vmovaps %xmm7,-40-5*16(%rax)
+ vmovaps %xmm8,-40-4*16(%rax)
+ vmovaps %xmm9,-40-3*16(%rax)
+ vmovaps %xmm10,-40-2*16(%rax)
+ vmovaps %xmm11,-40-1*16(%rax)
+.Lprologue_avx2:
+___
+$code.=<<___;
+ mov %rax,%r14 # original %rsp
+ mov %rdi,$ctx # reassigned argument
+ mov %rsi,$inp # reassigned argument
+ mov %rdx,$num # reassigned argument
+
+ lea -640(%rsp),%rsp
+ shl \$6,$num
+ lea 64($inp),$frame
+ and \$-128,%rsp
+ add $inp,$num
+ lea K_XX_XX+64(%rip),$K_XX_XX
+
+ mov 0($ctx),$A # load context
+ cmp $num,$frame
+ cmovae $inp,$frame # next or same block
+ mov 4($ctx),$F
+ mov 8($ctx),$C
+ mov 12($ctx),$D
+ mov 16($ctx),$E
+ vmovdqu 64($K_XX_XX),@X[2] # pbswap mask
+
+ vmovdqu ($inp),%xmm0
+ vmovdqu 16($inp),%xmm1
+ vmovdqu 32($inp),%xmm2
+ vmovdqu 48($inp),%xmm3
+ lea 64($inp),$inp
+ vinserti128 \$1,($frame),@X[-4&7],@X[-4&7]
+ vinserti128 \$1,16($frame),@X[-3&7],@X[-3&7]
+ vpshufb @X[2],@X[-4&7],@X[-4&7]
+ vinserti128 \$1,32($frame),@X[-2&7],@X[-2&7]
+ vpshufb @X[2],@X[-3&7],@X[-3&7]
+ vinserti128 \$1,48($frame),@X[-1&7],@X[-1&7]
+ vpshufb @X[2],@X[-2&7],@X[-2&7]
+ vmovdqu -64($K_XX_XX),$Kx # K_00_19
+ vpshufb @X[2],@X[-1&7],@X[-1&7]
+
+ vpaddd $Kx,@X[-4&7],@X[0] # add K_00_19
+ vpaddd $Kx,@X[-3&7],@X[1]
+ vmovdqu @X[0],0(%rsp) # X[]+K xfer to IALU
+ vpaddd $Kx,@X[-2&7],@X[2]
+ vmovdqu @X[1],32(%rsp)
+ vpaddd $Kx,@X[-1&7],@X[3]
+ vmovdqu @X[2],64(%rsp)
+ vmovdqu @X[3],96(%rsp)
+___
+for (;$Xi<8;$Xi++) { # Xupdate_avx2_16_31
+ use integer;
+
+ &vpalignr(@X[0],@X[-3&7],@X[-4&7],8); # compose "X[-14]" in "X[0]"
+ &vpsrldq(@Tx[0],@X[-1&7],4); # "X[-3]", 3 dwords
+ &vpxor (@X[0],@X[0],@X[-4&7]); # "X[0]"^="X[-16]"
+ &vpxor (@Tx[0],@Tx[0],@X[-2&7]); # "X[-3]"^"X[-8]"
+ &vpxor (@X[0],@X[0],@Tx[0]); # "X[0]"^="X[-3]"^"X[-8]"
+ &vpsrld (@Tx[0],@X[0],31);
+ &vmovdqu($Kx,eval(2*16*(($Xi)/5)-64)."($K_XX_XX)") if ($Xi%5==0); # K_XX_XX
+ &vpslldq(@Tx[2],@X[0],12); # "X[0]"<<96, extract one dword
+ &vpaddd (@X[0],@X[0],@X[0]);
+ &vpsrld (@Tx[1],@Tx[2],30);
+ &vpor (@X[0],@X[0],@Tx[0]); # "X[0]"<<<=1
+ &vpslld (@Tx[2],@Tx[2],2);
+ &vpxor (@X[0],@X[0],@Tx[1]);
+ &vpxor (@X[0],@X[0],@Tx[2]); # "X[0]"^=("X[0]">>96)<<<2
+ &vpaddd (@Tx[1],@X[0],$Kx);
+ &vmovdqu("32*$Xi(%rsp)",@Tx[1]); # X[]+K xfer to IALU
+
+ push(@X,shift(@X)); # "rotate" X[]
+}
+$code.=<<___;
+ lea 128(%rsp),$frame
+ jmp .Loop_avx2
+.align 32
+.Loop_avx2:
+ rorx \$2,$F,$B
+ andn $D,$F,$t0
+ and $C,$F
+ xor $t0,$F
+___
+sub bodyx_00_19 () { # 8 instructions, 3 cycles critical path
+ # at start $f=(b&c)^(~b&d), $b>>>=2
+ return &bodyx_20_39() if ($rx==19); $rx++;
+ (
+ '($a,$f,$b,$c,$d,$e)=@ROTX;'.
+
+ '&add ($e,((32*($j/4)+4*($j%4))%256-128)."($frame)");'. # e+=X[i]+K
+ '&lea ($frame,"256($frame)") if ($j%32==31);',
+ '&andn ($t0,$a,$c)', # ~b&d for next round
+
+ '&add ($e,$f)', # e+=(b&c)^(~b&d)
+ '&rorx ($a5,$a,27)', # a<<<5
+ '&rorx ($f,$a,2)', # b>>>2 for next round
+ '&and ($a,$b)', # b&c for next round
+
+ '&add ($e,$a5)', # e+=a<<<5
+ '&xor ($a,$t0);'. # f=(b&c)^(~b&d) for next round
+
+ 'unshift(@ROTX,pop(@ROTX)); $j++;'
+ )
+}
+
+sub bodyx_20_39 () { # 7 instructions, 2 cycles critical path
+ # on entry $f=b^c^d, $b>>>=2
+ return &bodyx_40_59() if ($rx==39); $rx++;
+ (
+ '($a,$f,$b,$c,$d,$e)=@ROTX;'.
+
+ '&add ($e,((32*($j/4)+4*($j%4))%256-128)."($frame)");'. # e+=X[i]+K
+ '&lea ($frame,"256($frame)") if ($j%32==31);',
+
+ '&lea ($e,"($e,$f)")', # e+=b^c^d
+ '&rorx ($a5,$a,27)', # a<<<5
+ '&rorx ($f,$a,2) if ($j<79)', # b>>>2 in next round
+ '&xor ($a,$b) if ($j<79)', # b^c for next round
+
+ '&add ($e,$a5)', # e+=a<<<5
+ '&xor ($a,$c) if ($j<79);'. # f=b^c^d for next round
+
+ 'unshift(@ROTX,pop(@ROTX)); $j++;'
+ )
+}
+
+sub bodyx_40_59 () { # 10 instructions, 3 cycles critical path
+ # on entry $f=((b^c)&(c^d)), $b>>>=2
+ $rx++;
+ (
+ '($a,$f,$b,$c,$d,$e)=@ROTX;'.
+
+ '&add ($e,((32*($j/4)+4*($j%4))%256-128)."($frame)");'. # e+=X[i]+K
+ '&lea ($frame,"256($frame)") if ($j%32==31);',
+ '&xor ($f,$c) if ($j>39)', # (b^c)&(c^d)^c
+ '&mov ($t0,$b) if ($j<59)', # count on zero latency
+ '&xor ($t0,$c) if ($j<59)', # c^d for next round
+
+ '&lea ($e,"($e,$f)")', # e+=(b^c)&(c^d)^c
+ '&rorx ($a5,$a,27)', # a<<<5
+ '&rorx ($f,$a,2)', # b>>>2 in next round
+ '&xor ($a,$b)', # b^c for next round
+
+ '&add ($e,$a5)', # e+=a<<<5
+ '&and ($a,$t0) if ($j< 59);'. # f=(b^c)&(c^d) for next round
+ '&xor ($a,$c) if ($j==59);'. # f=b^c^d for next round
+
+ 'unshift(@ROTX,pop(@ROTX)); $j++;'
+ )
+}
+
+sub Xupdate_avx2_16_31() # recall that $Xi starts wtih 4
+{ use integer;
+ my $body = shift;
+ my @insns = (&$body,&$body,&$body,&$body,&$body); # 35 instructions
+ my ($a,$b,$c,$d,$e);
+
+ &vpalignr(@X[0],@X[-3&7],@X[-4&7],8); # compose "X[-14]" in "X[0]"
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ &vpsrldq(@Tx[0],@X[-1&7],4); # "X[-3]", 3 dwords
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ &vpxor (@X[0],@X[0],@X[-4&7]); # "X[0]"^="X[-16]"
+ &vpxor (@Tx[0],@Tx[0],@X[-2&7]); # "X[-3]"^"X[-8]"
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ &vpxor (@X[0],@X[0],@Tx[0]); # "X[0]"^="X[-3]"^"X[-8]"
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ &vpsrld (@Tx[0],@X[0],31);
+ &vmovdqu($Kx,eval(2*16*(($Xi)/5)-64)."($K_XX_XX)") if ($Xi%5==0); # K_XX_XX
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ &vpslldq(@Tx[2],@X[0],12); # "X[0]"<<96, extract one dword
+ &vpaddd (@X[0],@X[0],@X[0]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ &vpsrld (@Tx[1],@Tx[2],30);
+ &vpor (@X[0],@X[0],@Tx[0]); # "X[0]"<<<=1
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ &vpslld (@Tx[2],@Tx[2],2);
+ &vpxor (@X[0],@X[0],@Tx[1]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ &vpxor (@X[0],@X[0],@Tx[2]); # "X[0]"^=("X[0]">>96)<<<2
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ &vpaddd (@Tx[1],@X[0],$Kx);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vmovdqu(eval(32*($Xi))."(%rsp)",@Tx[1]); # X[]+K xfer to IALU
+
+ foreach (@insns) { eval; } # remaining instructions [if any]
+
+ $Xi++;
+ push(@X,shift(@X)); # "rotate" X[]
+}
+
+sub Xupdate_avx2_32_79()
+{ use integer;
+ my $body = shift;
+ my @insns = (&$body,&$body,&$body,&$body,&$body); # 35 to 50 instructions
+ my ($a,$b,$c,$d,$e);
+
+ &vpalignr(@Tx[0],@X[-1&7],@X[-2&7],8); # compose "X[-6]"
+ &vpxor (@X[0],@X[0],@X[-4&7]); # "X[0]"="X[-32]"^"X[-16]"
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ &vpxor (@X[0],@X[0],@X[-7&7]); # "X[0]"^="X[-28]"
+ &vmovdqu($Kx,eval(2*16*($Xi/5)-64)."($K_XX_XX)") if ($Xi%5==0);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ &vpxor (@X[0],@X[0],@Tx[0]); # "X[0]"^="X[-6]"
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ &vpsrld (@Tx[0],@X[0],30);
+ &vpslld (@X[0],@X[0],2);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ #&vpslld (@X[0],@X[0],2);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ &vpor (@X[0],@X[0],@Tx[0]); # "X[0]"<<<=2
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ &vpaddd (@Tx[1],@X[0],$Kx);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ &vmovdqu("32*$Xi(%rsp)",@Tx[1]); # X[]+K xfer to IALU
+
+ foreach (@insns) { eval; } # remaining instructions
+
+ $Xi++;
+ push(@X,shift(@X)); # "rotate" X[]
+}
+
+sub Xloop_avx2()
+{ use integer;
+ my $body = shift;
+ my @insns = (&$body,&$body,&$body,&$body,&$body); # 32 instructions
+ my ($a,$b,$c,$d,$e);
+
+ foreach (@insns) { eval; }
+}
+
+ &align32();
+ &Xupdate_avx2_32_79(\&bodyx_00_19);
+ &Xupdate_avx2_32_79(\&bodyx_00_19);
+ &Xupdate_avx2_32_79(\&bodyx_00_19);
+ &Xupdate_avx2_32_79(\&bodyx_00_19);
+
+ &Xupdate_avx2_32_79(\&bodyx_20_39);
+ &Xupdate_avx2_32_79(\&bodyx_20_39);
+ &Xupdate_avx2_32_79(\&bodyx_20_39);
+ &Xupdate_avx2_32_79(\&bodyx_20_39);
+
+ &align32();
+ &Xupdate_avx2_32_79(\&bodyx_40_59);
+ &Xupdate_avx2_32_79(\&bodyx_40_59);
+ &Xupdate_avx2_32_79(\&bodyx_40_59);
+ &Xupdate_avx2_32_79(\&bodyx_40_59);
+
+ &Xloop_avx2(\&bodyx_20_39);
+ &Xloop_avx2(\&bodyx_20_39);
+ &Xloop_avx2(\&bodyx_20_39);
+ &Xloop_avx2(\&bodyx_20_39);
+
+$code.=<<___;
+ lea 128($inp),$frame
+ lea 128($inp),%rdi # borrow $t0
+ cmp $num,$frame
+ cmovae $inp,$frame # next or previous block
+
+ # output is d-e-[a]-f-b-c => A=d,F=e,C=f,D=b,E=c
+ add 0($ctx),@ROTX[0] # update context
+ add 4($ctx),@ROTX[1]
+ add 8($ctx),@ROTX[3]
+ mov @ROTX[0],0($ctx)
+ add 12($ctx),@ROTX[4]
+ mov @ROTX[1],4($ctx)
+ mov @ROTX[0],$A # A=d
+ add 16($ctx),@ROTX[5]
+ mov @ROTX[3],$a5
+ mov @ROTX[3],8($ctx)
+ mov @ROTX[4],$D # D=b
+ #xchg @ROTX[5],$F # F=c, C=f
+ mov @ROTX[4],12($ctx)
+ mov @ROTX[1],$F # F=e
+ mov @ROTX[5],16($ctx)
+ #mov $F,16($ctx)
+ mov @ROTX[5],$E # E=c
+ mov $a5,$C # C=f
+ #xchg $F,$E # E=c, F=e
+
+ cmp $num,$inp
+ je .Ldone_avx2
+___
+
+$Xi=4; # reset variables
+@X=map("%ymm$_",(4..7,0..3));
+
+$code.=<<___;
+ vmovdqu 64($K_XX_XX),@X[2] # pbswap mask
+ cmp $num,%rdi # borrowed $t0
+ ja .Last_avx2
+
+ vmovdqu -64(%rdi),%xmm0 # low part of @X[-4&7]
+ vmovdqu -48(%rdi),%xmm1
+ vmovdqu -32(%rdi),%xmm2
+ vmovdqu -16(%rdi),%xmm3
+ vinserti128 \$1,0($frame),@X[-4&7],@X[-4&7]
+ vinserti128 \$1,16($frame),@X[-3&7],@X[-3&7]
+ vinserti128 \$1,32($frame),@X[-2&7],@X[-2&7]
+ vinserti128 \$1,48($frame),@X[-1&7],@X[-1&7]
+ jmp .Last_avx2
+
+.align 32
+.Last_avx2:
+ lea 128+16(%rsp),$frame
+ rorx \$2,$F,$B
+ andn $D,$F,$t0
+ and $C,$F
+ xor $t0,$F
+ sub \$-128,$inp
+___
+ $rx=$j=0; @ROTX=($A,$F,$B,$C,$D,$E);
+
+ &Xloop_avx2 (\&bodyx_00_19);
+ &Xloop_avx2 (\&bodyx_00_19);
+ &Xloop_avx2 (\&bodyx_00_19);
+ &Xloop_avx2 (\&bodyx_00_19);
+
+ &Xloop_avx2 (\&bodyx_20_39);
+ &vmovdqu ($Kx,"-64($K_XX_XX)"); # K_00_19
+ &vpshufb (@X[-4&7],@X[-4&7],@X[2]); # byte swap
+ &Xloop_avx2 (\&bodyx_20_39);
+ &vpshufb (@X[-3&7],@X[-3&7],@X[2]);
+ &vpaddd (@Tx[0],@X[-4&7],$Kx); # add K_00_19
+ &Xloop_avx2 (\&bodyx_20_39);
+ &vmovdqu ("0(%rsp)",@Tx[0]);
+ &vpshufb (@X[-2&7],@X[-2&7],@X[2]);
+ &vpaddd (@Tx[1],@X[-3&7],$Kx);
+ &Xloop_avx2 (\&bodyx_20_39);
+ &vmovdqu ("32(%rsp)",@Tx[1]);
+ &vpshufb (@X[-1&7],@X[-1&7],@X[2]);
+ &vpaddd (@X[2],@X[-2&7],$Kx);
+
+ &Xloop_avx2 (\&bodyx_40_59);
+ &align32 ();
+ &vmovdqu ("64(%rsp)",@X[2]);
+ &vpaddd (@X[3],@X[-1&7],$Kx);
+ &Xloop_avx2 (\&bodyx_40_59);
+ &vmovdqu ("96(%rsp)",@X[3]);
+ &Xloop_avx2 (\&bodyx_40_59);
+ &Xupdate_avx2_16_31(\&bodyx_40_59);
+
+ &Xupdate_avx2_16_31(\&bodyx_20_39);
+ &Xupdate_avx2_16_31(\&bodyx_20_39);
+ &Xupdate_avx2_16_31(\&bodyx_20_39);
+ &Xloop_avx2 (\&bodyx_20_39);
+
+$code.=<<___;
+ lea 128(%rsp),$frame
+
+ # output is d-e-[a]-f-b-c => A=d,F=e,C=f,D=b,E=c
+ add 0($ctx),@ROTX[0] # update context
+ add 4($ctx),@ROTX[1]
+ add 8($ctx),@ROTX[3]
+ mov @ROTX[0],0($ctx)
+ add 12($ctx),@ROTX[4]
+ mov @ROTX[1],4($ctx)
+ mov @ROTX[0],$A # A=d
+ add 16($ctx),@ROTX[5]
+ mov @ROTX[3],$a5
+ mov @ROTX[3],8($ctx)
+ mov @ROTX[4],$D # D=b
+ #xchg @ROTX[5],$F # F=c, C=f
+ mov @ROTX[4],12($ctx)
+ mov @ROTX[1],$F # F=e
+ mov @ROTX[5],16($ctx)
+ #mov $F,16($ctx)
+ mov @ROTX[5],$E # E=c
+ mov $a5,$C # C=f
+ #xchg $F,$E # E=c, F=e
+
+ cmp $num,$inp
+ jbe .Loop_avx2
+
+.Ldone_avx2:
+ vzeroupper
+___
+$code.=<<___ if ($win64);
+ movaps -40-6*16(%r14),%xmm6
+ movaps -40-5*16(%r14),%xmm7
+ movaps -40-4*16(%r14),%xmm8
+ movaps -40-3*16(%r14),%xmm9
+ movaps -40-2*16(%r14),%xmm10
+ movaps -40-1*16(%r14),%xmm11
+___
+$code.=<<___;
+ lea (%r14),%rsi
+ mov -40(%rsi),%r14
+ mov -32(%rsi),%r13
+ mov -24(%rsi),%r12
+ mov -16(%rsi),%rbp
+ mov -8(%rsi),%rbx
+ lea (%rsi),%rsp
+.Lepilogue_avx2:
+ ret
+.size sha1_block_data_order_avx2,.-sha1_block_data_order_avx2
+___
+}
+}
+$code.=<<___;
+.align 64
+K_XX_XX:
+.long 0x5a827999,0x5a827999,0x5a827999,0x5a827999 # K_00_19
+.long 0x5a827999,0x5a827999,0x5a827999,0x5a827999 # K_00_19
+.long 0x6ed9eba1,0x6ed9eba1,0x6ed9eba1,0x6ed9eba1 # K_20_39
+.long 0x6ed9eba1,0x6ed9eba1,0x6ed9eba1,0x6ed9eba1 # K_20_39
+.long 0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc # K_40_59
+.long 0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc # K_40_59
+.long 0xca62c1d6,0xca62c1d6,0xca62c1d6,0xca62c1d6 # K_60_79
+.long 0xca62c1d6,0xca62c1d6,0xca62c1d6,0xca62c1d6 # K_60_79
+.long 0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f # pbswap mask
+.long 0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f # pbswap mask
+.byte 0xf,0xe,0xd,0xc,0xb,0xa,0x9,0x8,0x7,0x6,0x5,0x4,0x3,0x2,0x1,0x0
+___
+}}}
+$code.=<<___;
+.asciz "SHA1 block transform for x86_64, CRYPTOGAMS by <appro\@openssl.org>"
+.align 64
+___
+
+# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame,
+# CONTEXT *context,DISPATCHER_CONTEXT *disp)
+if ($win64) {
+$rec="%rcx";
+$frame="%rdx";
+$context="%r8";
+$disp="%r9";
+
+$code.=<<___;
+.extern __imp_RtlVirtualUnwind
+.type se_handler,\@abi-omnipotent
+.align 16
+se_handler:
+ push %rsi
+ push %rdi
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+ pushfq
+ sub \$64,%rsp
+
+ mov 120($context),%rax # pull context->Rax
+ mov 248($context),%rbx # pull context->Rip
+
+ lea .Lprologue(%rip),%r10
+ cmp %r10,%rbx # context->Rip<.Lprologue
+ jb .Lcommon_seh_tail
+
+ mov 152($context),%rax # pull context->Rsp
+
+ lea .Lepilogue(%rip),%r10
+ cmp %r10,%rbx # context->Rip>=.Lepilogue
+ jae .Lcommon_seh_tail
+
+ mov `16*4`(%rax),%rax # pull saved stack pointer
+
+ mov -8(%rax),%rbx
+ mov -16(%rax),%rbp
+ mov -24(%rax),%r12
+ mov -32(%rax),%r13
+ mov -40(%rax),%r14
+ mov %rbx,144($context) # restore context->Rbx
+ mov %rbp,160($context) # restore context->Rbp
+ mov %r12,216($context) # restore context->R12
+ mov %r13,224($context) # restore context->R13
+ mov %r14,232($context) # restore context->R14
+
+ jmp .Lcommon_seh_tail
+.size se_handler,.-se_handler
+___
+
+$code.=<<___ if ($shaext);
+.type shaext_handler,\@abi-omnipotent
+.align 16
+shaext_handler:
+ push %rsi
+ push %rdi
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+ pushfq
+ sub \$64,%rsp
+
+ mov 120($context),%rax # pull context->Rax
+ mov 248($context),%rbx # pull context->Rip
+
+ lea .Lprologue_shaext(%rip),%r10
+ cmp %r10,%rbx # context->Rip<.Lprologue
+ jb .Lcommon_seh_tail
+
+ lea .Lepilogue_shaext(%rip),%r10
+ cmp %r10,%rbx # context->Rip>=.Lepilogue
+ jae .Lcommon_seh_tail
+
+ lea -8-4*16(%rax),%rsi
+ lea 512($context),%rdi # &context.Xmm6
+ mov \$8,%ecx
+ .long 0xa548f3fc # cld; rep movsq
+
+ jmp .Lcommon_seh_tail
+.size shaext_handler,.-shaext_handler
+___
+
+$code.=<<___;
+.type ssse3_handler,\@abi-omnipotent
+.align 16
+ssse3_handler:
+ push %rsi
+ push %rdi
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+ pushfq
+ sub \$64,%rsp
+
+ mov 120($context),%rax # pull context->Rax
+ mov 248($context),%rbx # pull context->Rip
+
+ mov 8($disp),%rsi # disp->ImageBase
+ mov 56($disp),%r11 # disp->HandlerData
+
+ mov 0(%r11),%r10d # HandlerData[0]
+ lea (%rsi,%r10),%r10 # prologue label
+ cmp %r10,%rbx # context->Rip<prologue label
+ jb .Lcommon_seh_tail
+
+ mov 152($context),%rax # pull context->Rsp
+
+ mov 4(%r11),%r10d # HandlerData[1]
+ lea (%rsi,%r10),%r10 # epilogue label
+ cmp %r10,%rbx # context->Rip>=epilogue label
+ jae .Lcommon_seh_tail
+
+ mov 232($context),%rax # pull context->R14
+
+ lea -40-6*16(%rax),%rsi
+ lea 512($context),%rdi # &context.Xmm6
+ mov \$12,%ecx
+ .long 0xa548f3fc # cld; rep movsq
+
+ mov -8(%rax),%rbx
+ mov -16(%rax),%rbp
+ mov -24(%rax),%r12
+ mov -32(%rax),%r13
+ mov -40(%rax),%r14
+ mov %rbx,144($context) # restore context->Rbx
+ mov %rbp,160($context) # restore context->Rbp
+ mov %r12,216($context) # restore cotnext->R12
+ mov %r13,224($context) # restore cotnext->R13
+ mov %r14,232($context) # restore cotnext->R14
+
+.Lcommon_seh_tail:
+ mov 8(%rax),%rdi
+ mov 16(%rax),%rsi
+ mov %rax,152($context) # restore context->Rsp
+ mov %rsi,168($context) # restore context->Rsi
+ mov %rdi,176($context) # restore context->Rdi
+
+ mov 40($disp),%rdi # disp->ContextRecord
+ mov $context,%rsi # context
+ mov \$154,%ecx # sizeof(CONTEXT)
+ .long 0xa548f3fc # cld; rep movsq
+
+ mov $disp,%rsi
+ xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER
+ mov 8(%rsi),%rdx # arg2, disp->ImageBase
+ mov 0(%rsi),%r8 # arg3, disp->ControlPc
+ mov 16(%rsi),%r9 # arg4, disp->FunctionEntry
+ mov 40(%rsi),%r10 # disp->ContextRecord
+ lea 56(%rsi),%r11 # &disp->HandlerData
+ lea 24(%rsi),%r12 # &disp->EstablisherFrame
+ mov %r10,32(%rsp) # arg5
+ mov %r11,40(%rsp) # arg6
+ mov %r12,48(%rsp) # arg7
+ mov %rcx,56(%rsp) # arg8, (NULL)
+ call *__imp_RtlVirtualUnwind(%rip)
+
+ mov \$1,%eax # ExceptionContinueSearch
+ add \$64,%rsp
+ popfq
+ pop %r15
+ pop %r14
+ pop %r13
+ pop %r12
+ pop %rbp
+ pop %rbx
+ pop %rdi
+ pop %rsi
+ ret
+.size ssse3_handler,.-ssse3_handler
+
+.section .pdata
+.align 4
+ .rva .LSEH_begin_sha1_block_data_order
+ .rva .LSEH_end_sha1_block_data_order
+ .rva .LSEH_info_sha1_block_data_order
+___
+$code.=<<___ if ($shaext);
+ .rva .LSEH_begin_sha1_block_data_order_shaext
+ .rva .LSEH_end_sha1_block_data_order_shaext
+ .rva .LSEH_info_sha1_block_data_order_shaext
+___
+$code.=<<___;
+ .rva .LSEH_begin_sha1_block_data_order_ssse3
+ .rva .LSEH_end_sha1_block_data_order_ssse3
+ .rva .LSEH_info_sha1_block_data_order_ssse3
+___
+$code.=<<___ if ($avx);
+ .rva .LSEH_begin_sha1_block_data_order_avx
+ .rva .LSEH_end_sha1_block_data_order_avx
+ .rva .LSEH_info_sha1_block_data_order_avx
+___
+$code.=<<___ if ($avx>1);
+ .rva .LSEH_begin_sha1_block_data_order_avx2
+ .rva .LSEH_end_sha1_block_data_order_avx2
+ .rva .LSEH_info_sha1_block_data_order_avx2
+___
+$code.=<<___;
+.section .xdata
+.align 8
+.LSEH_info_sha1_block_data_order:
+ .byte 9,0,0,0
+ .rva se_handler
+___
+$code.=<<___ if ($shaext);
+.LSEH_info_sha1_block_data_order_shaext:
+ .byte 9,0,0,0
+ .rva shaext_handler
+___
+$code.=<<___;
+.LSEH_info_sha1_block_data_order_ssse3:
+ .byte 9,0,0,0
+ .rva ssse3_handler
+ .rva .Lprologue_ssse3,.Lepilogue_ssse3 # HandlerData[]
+___
+$code.=<<___ if ($avx);
+.LSEH_info_sha1_block_data_order_avx:
+ .byte 9,0,0,0
+ .rva ssse3_handler
+ .rva .Lprologue_avx,.Lepilogue_avx # HandlerData[]
+___
+$code.=<<___ if ($avx>1);
+.LSEH_info_sha1_block_data_order_avx2:
+ .byte 9,0,0,0
+ .rva ssse3_handler
+ .rva .Lprologue_avx2,.Lepilogue_avx2 # HandlerData[]
+___
+}
+
+####################################################################
+
+sub sha1rnds4 {
+ if (@_[0] =~ /\$([x0-9a-f]+),\s*%xmm([0-7]),\s*%xmm([0-7])/) {
+ my @opcode=(0x0f,0x3a,0xcc);
+ push @opcode,0xc0|($2&7)|(($3&7)<<3); # ModR/M
+ my $c=$1;
+ push @opcode,$c=~/^0/?oct($c):$c;
+ return ".byte\t".join(',',@opcode);
+ } else {
+ return "sha1rnds4\t".@_[0];
+ }
+}
+
+sub sha1op38 {
+ my $instr = shift;
+ my %opcodelet = (
+ "sha1nexte" => 0xc8,
+ "sha1msg1" => 0xc9,
+ "sha1msg2" => 0xca );
+
+ if (defined($opcodelet{$instr}) && @_[0] =~ /%xmm([0-9]+),\s*%xmm([0-9]+)/) {
+ my @opcode=(0x0f,0x38);
+ my $rex=0;
+ $rex|=0x04 if ($2>=8);
+ $rex|=0x01 if ($1>=8);
+ unshift @opcode,0x40|$rex if ($rex);
+ push @opcode,$opcodelet{$instr};
+ push @opcode,0xc0|($1&7)|(($2&7)<<3); # ModR/M
+ return ".byte\t".join(',',@opcode);
+ } else {
+ return $instr."\t".@_[0];
+ }
+}
+
+foreach (split("\n",$code)) {
+ s/\`([^\`]*)\`/eval $1/geo;
+
+ s/\b(sha1rnds4)\s+(.*)/sha1rnds4($2)/geo or
+ s/\b(sha1[^\s]*)\s+(.*)/sha1op38($1,$2)/geo;
+
+ print $_,"\n";
+}
+close STDOUT;
diff --git a/src/crypto/sha/asm/sha256-586.pl b/src/crypto/sha/asm/sha256-586.pl
new file mode 100644
index 0000000..6462e45
--- /dev/null
+++ b/src/crypto/sha/asm/sha256-586.pl
@@ -0,0 +1,1281 @@
+#!/usr/bin/env perl
+#
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+# project. The module is, however, dual licensed under OpenSSL and
+# CRYPTOGAMS licenses depending on where you obtain it. For further
+# details see http://www.openssl.org/~appro/cryptogams/.
+# ====================================================================
+#
+# SHA256 block transform for x86. September 2007.
+#
+# Performance improvement over compiler generated code varies from
+# 10% to 40% [see below]. Not very impressive on some µ-archs, but
+# it's 5 times smaller and optimizies amount of writes.
+#
+# May 2012.
+#
+# Optimization including two of Pavel Semjanov's ideas, alternative
+# Maj and full unroll, resulted in ~20-25% improvement on most CPUs,
+# ~7% on Pentium, ~40% on Atom. As fully unrolled loop body is almost
+# 15x larger, 8KB vs. 560B, it's fired only for longer inputs. But not
+# on P4, where it kills performance, nor Sandy Bridge, where folded
+# loop is approximately as fast...
+#
+# June 2012.
+#
+# Add AMD XOP-specific code path, >30% improvement on Bulldozer over
+# May version, >60% over original. Add AVX+shrd code path, >25%
+# improvement on Sandy Bridge over May version, 60% over original.
+#
+# May 2013.
+#
+# Replace AMD XOP code path with SSSE3 to cover more processors.
+# (Biggest improvement coefficient is on upcoming Atom Silvermont,
+# not shown.) Add AVX+BMI code path.
+#
+# March 2014.
+#
+# Add support for Intel SHA Extensions.
+#
+# Performance in clock cycles per processed byte (less is better):
+#
+# gcc icc x86 asm(*) SIMD x86_64 asm(**)
+# Pentium 46 57 40/38 - -
+# PIII 36 33 27/24 - -
+# P4 41 38 28 - 17.3
+# AMD K8 27 25 19/15.5 - 14.9
+# Core2 26 23 18/15.6 14.3 13.8
+# Westmere 27 - 19/15.7 13.4 12.3
+# Sandy Bridge 25 - 15.9 12.4 11.6
+# Ivy Bridge 24 - 15.0 11.4 10.3
+# Haswell 22 - 13.9 9.46 7.80
+# Bulldozer 36 - 27/22 17.0 13.6
+# VIA Nano 36 - 25/22 16.8 16.5
+# Atom 50 - 30/25 21.9 18.9
+# Silvermont 40 - 34/31 22.9 20.6
+#
+# (*) numbers after slash are for unrolled loop, where applicable;
+# (**) x86_64 assembly performance is presented for reference
+# purposes, results are best-available;
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+push(@INC,"${dir}","${dir}../../perlasm");
+require "x86asm.pl";
+
+&asm_init($ARGV[0],"sha512-586.pl",$ARGV[$#ARGV] eq "386");
+
+$xmm=$avx=0;
+for (@ARGV) { $xmm=1 if (/-DOPENSSL_IA32_SSE2/); }
+
+if ($xmm && `$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
+ =~ /GNU assembler version ([2-9]\.[0-9]+)/) {
+ $avx = ($1>=2.19) + ($1>=2.22);
+}
+
+if ($xmm && !$avx && $ARGV[0] eq "win32n" &&
+ `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)/) {
+ $avx = ($1>=2.03) + ($1>=2.10);
+}
+
+if ($xmm && !$avx && $ARGV[0] eq "win32" &&
+ `ml 2>&1` =~ /Version ([0-9]+)\./) {
+ $avx = ($1>=10) + ($1>=11);
+}
+
+if ($xmm && !$avx && `$ENV{CC} -v 2>&1` =~ /(^clang version|based on LLVM) ([3-9]\.[0-9]+)/) {
+ $avx = ($2>=3.0) + ($2>3.0);
+}
+
+$shaext=$xmm; ### set to zero if compiling for 1.0.1
+
+$unroll_after = 64*4; # If pre-evicted from L1P cache first spin of
+ # fully unrolled loop was measured to run about
+ # 3-4x slower. If slowdown coefficient is N and
+ # unrolled loop is m times faster, then you break
+ # even at (N-1)/(m-1) blocks. Then it needs to be
+ # adjusted for probability of code being evicted,
+ # code size/cache size=1/4. Typical m is 1.15...
+
+$A="eax";
+$E="edx";
+$T="ebx";
+$Aoff=&DWP(4,"esp");
+$Boff=&DWP(8,"esp");
+$Coff=&DWP(12,"esp");
+$Doff=&DWP(16,"esp");
+$Eoff=&DWP(20,"esp");
+$Foff=&DWP(24,"esp");
+$Goff=&DWP(28,"esp");
+$Hoff=&DWP(32,"esp");
+$Xoff=&DWP(36,"esp");
+$K256="ebp";
+
+sub BODY_16_63() {
+ &mov ($T,"ecx"); # "ecx" is preloaded
+ &mov ("esi",&DWP(4*(9+15+16-14),"esp"));
+ &ror ("ecx",18-7);
+ &mov ("edi","esi");
+ &ror ("esi",19-17);
+ &xor ("ecx",$T);
+ &shr ($T,3);
+ &ror ("ecx",7);
+ &xor ("esi","edi");
+ &xor ($T,"ecx"); # T = sigma0(X[-15])
+ &ror ("esi",17);
+ &add ($T,&DWP(4*(9+15+16),"esp")); # T += X[-16]
+ &shr ("edi",10);
+ &add ($T,&DWP(4*(9+15+16-9),"esp")); # T += X[-7]
+ #&xor ("edi","esi") # sigma1(X[-2])
+ # &add ($T,"edi"); # T += sigma1(X[-2])
+ # &mov (&DWP(4*(9+15),"esp"),$T); # save X[0]
+
+ &BODY_00_15(1);
+}
+sub BODY_00_15() {
+ my $in_16_63=shift;
+
+ &mov ("ecx",$E);
+ &xor ("edi","esi") if ($in_16_63); # sigma1(X[-2])
+ &mov ("esi",$Foff);
+ &ror ("ecx",25-11);
+ &add ($T,"edi") if ($in_16_63); # T += sigma1(X[-2])
+ &mov ("edi",$Goff);
+ &xor ("ecx",$E);
+ &xor ("esi","edi");
+ &mov ($T,&DWP(4*(9+15),"esp")) if (!$in_16_63);
+ &mov (&DWP(4*(9+15),"esp"),$T) if ($in_16_63); # save X[0]
+ &ror ("ecx",11-6);
+ &and ("esi",$E);
+ &mov ($Eoff,$E); # modulo-scheduled
+ &xor ($E,"ecx");
+ &add ($T,$Hoff); # T += h
+ &xor ("esi","edi"); # Ch(e,f,g)
+ &ror ($E,6); # Sigma1(e)
+ &mov ("ecx",$A);
+ &add ($T,"esi"); # T += Ch(e,f,g)
+
+ &ror ("ecx",22-13);
+ &add ($T,$E); # T += Sigma1(e)
+ &mov ("edi",$Boff);
+ &xor ("ecx",$A);
+ &mov ($Aoff,$A); # modulo-scheduled
+ &lea ("esp",&DWP(-4,"esp"));
+ &ror ("ecx",13-2);
+ &mov ("esi",&DWP(0,$K256));
+ &xor ("ecx",$A);
+ &mov ($E,$Eoff); # e in next iteration, d in this one
+ &xor ($A,"edi"); # a ^= b
+ &ror ("ecx",2); # Sigma0(a)
+
+ &add ($T,"esi"); # T+= K[i]
+ &mov (&DWP(0,"esp"),$A); # (b^c) in next round
+ &add ($E,$T); # d += T
+ &and ($A,&DWP(4,"esp")); # a &= (b^c)
+ &add ($T,"ecx"); # T += Sigma0(a)
+ &xor ($A,"edi"); # h = Maj(a,b,c) = Ch(a^b,c,b)
+ &mov ("ecx",&DWP(4*(9+15+16-1),"esp")) if ($in_16_63); # preload T
+ &add ($K256,4);
+ &add ($A,$T); # h += T
+}
+
+&external_label("OPENSSL_ia32cap_P") if (!$i386);
+
+&function_begin("sha256_block_data_order");
+ &mov ("esi",wparam(0)); # ctx
+ &mov ("edi",wparam(1)); # inp
+ &mov ("eax",wparam(2)); # num
+ &mov ("ebx","esp"); # saved sp
+
+ &call (&label("pic_point")); # make it PIC!
+&set_label("pic_point");
+ &blindpop($K256);
+ &lea ($K256,&DWP(&label("K256")."-".&label("pic_point"),$K256));
+
+ &sub ("esp",16);
+ &and ("esp",-64);
+
+ &shl ("eax",6);
+ &add ("eax","edi");
+ &mov (&DWP(0,"esp"),"esi"); # ctx
+ &mov (&DWP(4,"esp"),"edi"); # inp
+ &mov (&DWP(8,"esp"),"eax"); # inp+num*128
+ &mov (&DWP(12,"esp"),"ebx"); # saved sp
+ if (!$i386 && $xmm) {
+ &picmeup("edx","OPENSSL_ia32cap_P",$K256,&label("K256"));
+ &mov ("ecx",&DWP(0,"edx"));
+ &mov ("ebx",&DWP(4,"edx"));
+ &test ("ecx",1<<20); # check for P4
+ &jnz (&label("loop"));
+ &mov ("edx",&DWP(8,"edx")) if ($xmm);
+ &test ("ecx",1<<24); # check for FXSR
+ &jz ($unroll_after?&label("no_xmm"):&label("loop"));
+ &and ("ecx",1<<30); # mask "Intel CPU" bit
+ &and ("ebx",1<<28|1<<9); # mask AVX and SSSE3 bits
+ &test ("edx",1<<29) if ($shaext); # check for SHA
+ &jnz (&label("shaext")) if ($shaext);
+ &or ("ecx","ebx");
+ &and ("ecx",1<<28|1<<30);
+ &cmp ("ecx",1<<28|1<<30);
+ if ($xmm) {
+ &je (&label("AVX")) if ($avx);
+ &test ("ebx",1<<9); # check for SSSE3
+ &jnz (&label("SSSE3"));
+ } else {
+ &je (&label("loop_shrd"));
+ }
+ if ($unroll_after) {
+&set_label("no_xmm");
+ &sub ("eax","edi");
+ &cmp ("eax",$unroll_after);
+ &jae (&label("unrolled"));
+ } }
+ &jmp (&label("loop"));
+
+sub COMPACT_LOOP() {
+my $suffix=shift;
+
+&set_label("loop$suffix",$suffix?32:16);
+ # copy input block to stack reversing byte and dword order
+ for($i=0;$i<4;$i++) {
+ &mov ("eax",&DWP($i*16+0,"edi"));
+ &mov ("ebx",&DWP($i*16+4,"edi"));
+ &mov ("ecx",&DWP($i*16+8,"edi"));
+ &bswap ("eax");
+ &mov ("edx",&DWP($i*16+12,"edi"));
+ &bswap ("ebx");
+ &push ("eax");
+ &bswap ("ecx");
+ &push ("ebx");
+ &bswap ("edx");
+ &push ("ecx");
+ &push ("edx");
+ }
+ &add ("edi",64);
+ &lea ("esp",&DWP(-4*9,"esp"));# place for A,B,C,D,E,F,G,H
+ &mov (&DWP(4*(9+16)+4,"esp"),"edi");
+
+ # copy ctx->h[0-7] to A,B,C,D,E,F,G,H on stack
+ &mov ($A,&DWP(0,"esi"));
+ &mov ("ebx",&DWP(4,"esi"));
+ &mov ("ecx",&DWP(8,"esi"));
+ &mov ("edi",&DWP(12,"esi"));
+ # &mov ($Aoff,$A);
+ &mov ($Boff,"ebx");
+ &xor ("ebx","ecx");
+ &mov ($Coff,"ecx");
+ &mov ($Doff,"edi");
+ &mov (&DWP(0,"esp"),"ebx"); # magic
+ &mov ($E,&DWP(16,"esi"));
+ &mov ("ebx",&DWP(20,"esi"));
+ &mov ("ecx",&DWP(24,"esi"));
+ &mov ("edi",&DWP(28,"esi"));
+ # &mov ($Eoff,$E);
+ &mov ($Foff,"ebx");
+ &mov ($Goff,"ecx");
+ &mov ($Hoff,"edi");
+
+&set_label("00_15$suffix",16);
+
+ &BODY_00_15();
+
+ &cmp ("esi",0xc19bf174);
+ &jne (&label("00_15$suffix"));
+
+ &mov ("ecx",&DWP(4*(9+15+16-1),"esp")); # preloaded in BODY_00_15(1)
+ &jmp (&label("16_63$suffix"));
+
+&set_label("16_63$suffix",16);
+
+ &BODY_16_63();
+
+ &cmp ("esi",0xc67178f2);
+ &jne (&label("16_63$suffix"));
+
+ &mov ("esi",&DWP(4*(9+16+64)+0,"esp"));#ctx
+ # &mov ($A,$Aoff);
+ &mov ("ebx",$Boff);
+ # &mov ("edi",$Coff);
+ &mov ("ecx",$Doff);
+ &add ($A,&DWP(0,"esi"));
+ &add ("ebx",&DWP(4,"esi"));
+ &add ("edi",&DWP(8,"esi"));
+ &add ("ecx",&DWP(12,"esi"));
+ &mov (&DWP(0,"esi"),$A);
+ &mov (&DWP(4,"esi"),"ebx");
+ &mov (&DWP(8,"esi"),"edi");
+ &mov (&DWP(12,"esi"),"ecx");
+ # &mov ($E,$Eoff);
+ &mov ("eax",$Foff);
+ &mov ("ebx",$Goff);
+ &mov ("ecx",$Hoff);
+ &mov ("edi",&DWP(4*(9+16+64)+4,"esp"));#inp
+ &add ($E,&DWP(16,"esi"));
+ &add ("eax",&DWP(20,"esi"));
+ &add ("ebx",&DWP(24,"esi"));
+ &add ("ecx",&DWP(28,"esi"));
+ &mov (&DWP(16,"esi"),$E);
+ &mov (&DWP(20,"esi"),"eax");
+ &mov (&DWP(24,"esi"),"ebx");
+ &mov (&DWP(28,"esi"),"ecx");
+
+ &lea ("esp",&DWP(4*(9+16+64),"esp"));# destroy frame
+ &sub ($K256,4*64); # rewind K
+
+ &cmp ("edi",&DWP(8,"esp")); # are we done yet?
+ &jb (&label("loop$suffix"));
+}
+ &COMPACT_LOOP();
+ &mov ("esp",&DWP(12,"esp")); # restore sp
+&function_end_A();
+ if (!$i386 && !$xmm) {
+ # ~20% improvement on Sandy Bridge
+ local *ror = sub { &shrd(@_[0],@_) };
+ &COMPACT_LOOP("_shrd");
+ &mov ("esp",&DWP(12,"esp")); # restore sp
+&function_end_A();
+ }
+
+&set_label("K256",64); # Yes! I keep it in the code segment!
+@K256=( 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,
+ 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5,
+ 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,
+ 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174,
+ 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,
+ 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da,
+ 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,
+ 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967,
+ 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,
+ 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85,
+ 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,
+ 0xd192e819,0xd6990624,0xf40e3585,0x106aa070,
+ 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,
+ 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3,
+ 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,
+ 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 );
+&data_word(@K256);
+&data_word(0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f); # byte swap mask
+&asciz("SHA256 block transform for x86, CRYPTOGAMS by <appro\@openssl.org>");
+
+($a,$b,$c,$d,$e,$f,$g,$h)=(0..7); # offsets
+sub off { &DWP(4*(((shift)-$i)&7),"esp"); }
+
+if (!$i386 && $unroll_after) {
+my @AH=($A,$K256);
+
+&set_label("unrolled",16);
+ &lea ("esp",&DWP(-96,"esp"));
+ # copy ctx->h[0-7] to A,B,C,D,E,F,G,H on stack
+ &mov ($AH[0],&DWP(0,"esi"));
+ &mov ($AH[1],&DWP(4,"esi"));
+ &mov ("ecx",&DWP(8,"esi"));
+ &mov ("ebx",&DWP(12,"esi"));
+ #&mov (&DWP(0,"esp"),$AH[0]);
+ &mov (&DWP(4,"esp"),$AH[1]);
+ &xor ($AH[1],"ecx"); # magic
+ &mov (&DWP(8,"esp"),"ecx");
+ &mov (&DWP(12,"esp"),"ebx");
+ &mov ($E,&DWP(16,"esi"));
+ &mov ("ebx",&DWP(20,"esi"));
+ &mov ("ecx",&DWP(24,"esi"));
+ &mov ("esi",&DWP(28,"esi"));
+ #&mov (&DWP(16,"esp"),$E);
+ &mov (&DWP(20,"esp"),"ebx");
+ &mov (&DWP(24,"esp"),"ecx");
+ &mov (&DWP(28,"esp"),"esi");
+ &jmp (&label("grand_loop"));
+
+&set_label("grand_loop",16);
+ # copy input block to stack reversing byte order
+ for($i=0;$i<5;$i++) {
+ &mov ("ebx",&DWP(12*$i+0,"edi"));
+ &mov ("ecx",&DWP(12*$i+4,"edi"));
+ &bswap ("ebx");
+ &mov ("esi",&DWP(12*$i+8,"edi"));
+ &bswap ("ecx");
+ &mov (&DWP(32+12*$i+0,"esp"),"ebx");
+ &bswap ("esi");
+ &mov (&DWP(32+12*$i+4,"esp"),"ecx");
+ &mov (&DWP(32+12*$i+8,"esp"),"esi");
+ }
+ &mov ("ebx",&DWP($i*12,"edi"));
+ &add ("edi",64);
+ &bswap ("ebx");
+ &mov (&DWP(96+4,"esp"),"edi");
+ &mov (&DWP(32+12*$i,"esp"),"ebx");
+
+ my ($t1,$t2) = ("ecx","esi");
+
+ for ($i=0;$i<64;$i++) {
+
+ if ($i>=16) {
+ &mov ($T,$t1); # $t1 is preloaded
+ # &mov ($t2,&DWP(32+4*(($i+14)&15),"esp"));
+ &ror ($t1,18-7);
+ &mov ("edi",$t2);
+ &ror ($t2,19-17);
+ &xor ($t1,$T);
+ &shr ($T,3);
+ &ror ($t1,7);
+ &xor ($t2,"edi");
+ &xor ($T,$t1); # T = sigma0(X[-15])
+ &ror ($t2,17);
+ &add ($T,&DWP(32+4*($i&15),"esp")); # T += X[-16]
+ &shr ("edi",10);
+ &add ($T,&DWP(32+4*(($i+9)&15),"esp")); # T += X[-7]
+ #&xor ("edi",$t2) # sigma1(X[-2])
+ # &add ($T,"edi"); # T += sigma1(X[-2])
+ # &mov (&DWP(4*(9+15),"esp"),$T); # save X[0]
+ }
+ &mov ($t1,$E);
+ &xor ("edi",$t2) if ($i>=16); # sigma1(X[-2])
+ &mov ($t2,&off($f));
+ &ror ($E,25-11);
+ &add ($T,"edi") if ($i>=16); # T += sigma1(X[-2])
+ &mov ("edi",&off($g));
+ &xor ($E,$t1);
+ &mov ($T,&DWP(32+4*($i&15),"esp")) if ($i<16); # X[i]
+ &mov (&DWP(32+4*($i&15),"esp"),$T) if ($i>=16 && $i<62); # save X[0]
+ &xor ($t2,"edi");
+ &ror ($E,11-6);
+ &and ($t2,$t1);
+ &mov (&off($e),$t1); # save $E, modulo-scheduled
+ &xor ($E,$t1);
+ &add ($T,&off($h)); # T += h
+ &xor ("edi",$t2); # Ch(e,f,g)
+ &ror ($E,6); # Sigma1(e)
+ &mov ($t1,$AH[0]);
+ &add ($T,"edi"); # T += Ch(e,f,g)
+
+ &ror ($t1,22-13);
+ &mov ($t2,$AH[0]);
+ &mov ("edi",&off($b));
+ &xor ($t1,$AH[0]);
+ &mov (&off($a),$AH[0]); # save $A, modulo-scheduled
+ &xor ($AH[0],"edi"); # a ^= b, (b^c) in next round
+ &ror ($t1,13-2);
+ &and ($AH[1],$AH[0]); # (b^c) &= (a^b)
+ &lea ($E,&DWP(@K256[$i],$T,$E)); # T += Sigma1(1)+K[i]
+ &xor ($t1,$t2);
+ &xor ($AH[1],"edi"); # h = Maj(a,b,c) = Ch(a^b,c,b)
+ &mov ($t2,&DWP(32+4*(($i+2)&15),"esp")) if ($i>=15 && $i<63);
+ &ror ($t1,2); # Sigma0(a)
+
+ &add ($AH[1],$E); # h += T
+ &add ($E,&off($d)); # d += T
+ &add ($AH[1],$t1); # h += Sigma0(a)
+ &mov ($t1,&DWP(32+4*(($i+15)&15),"esp")) if ($i>=15 && $i<63);
+
+ @AH = reverse(@AH); # rotate(a,h)
+ ($t1,$t2) = ($t2,$t1); # rotate(t1,t2)
+ }
+ &mov ("esi",&DWP(96,"esp")); #ctx
+ #&mov ($AH[0],&DWP(0,"esp"));
+ &xor ($AH[1],"edi"); #&mov ($AH[1],&DWP(4,"esp"));
+ #&mov ("edi", &DWP(8,"esp"));
+ &mov ("ecx",&DWP(12,"esp"));
+ &add ($AH[0],&DWP(0,"esi"));
+ &add ($AH[1],&DWP(4,"esi"));
+ &add ("edi",&DWP(8,"esi"));
+ &add ("ecx",&DWP(12,"esi"));
+ &mov (&DWP(0,"esi"),$AH[0]);
+ &mov (&DWP(4,"esi"),$AH[1]);
+ &mov (&DWP(8,"esi"),"edi");
+ &mov (&DWP(12,"esi"),"ecx");
+ #&mov (&DWP(0,"esp"),$AH[0]);
+ &mov (&DWP(4,"esp"),$AH[1]);
+ &xor ($AH[1],"edi"); # magic
+ &mov (&DWP(8,"esp"),"edi");
+ &mov (&DWP(12,"esp"),"ecx");
+ #&mov ($E,&DWP(16,"esp"));
+ &mov ("edi",&DWP(20,"esp"));
+ &mov ("ebx",&DWP(24,"esp"));
+ &mov ("ecx",&DWP(28,"esp"));
+ &add ($E,&DWP(16,"esi"));
+ &add ("edi",&DWP(20,"esi"));
+ &add ("ebx",&DWP(24,"esi"));
+ &add ("ecx",&DWP(28,"esi"));
+ &mov (&DWP(16,"esi"),$E);
+ &mov (&DWP(20,"esi"),"edi");
+ &mov (&DWP(24,"esi"),"ebx");
+ &mov (&DWP(28,"esi"),"ecx");
+ #&mov (&DWP(16,"esp"),$E);
+ &mov (&DWP(20,"esp"),"edi");
+ &mov ("edi",&DWP(96+4,"esp")); # inp
+ &mov (&DWP(24,"esp"),"ebx");
+ &mov (&DWP(28,"esp"),"ecx");
+
+ &cmp ("edi",&DWP(96+8,"esp")); # are we done yet?
+ &jb (&label("grand_loop"));
+
+ &mov ("esp",&DWP(96+12,"esp")); # restore sp
+&function_end_A();
+}
+ if (!$i386 && $xmm) {{{
+if ($shaext) {
+######################################################################
+# Intel SHA Extensions implementation of SHA256 update function.
+#
+my ($ctx,$inp,$end)=("esi","edi","eax");
+my ($Wi,$ABEF,$CDGH,$TMP)=map("xmm$_",(0..2,7));
+my @MSG=map("xmm$_",(3..6));
+
+sub sha256op38 {
+ my ($opcodelet,$dst,$src)=@_;
+ if ("$dst:$src" =~ /xmm([0-7]):xmm([0-7])/)
+ { &data_byte(0x0f,0x38,$opcodelet,0xc0|($1<<3)|$2); }
+}
+sub sha256rnds2 { sha256op38(0xcb,@_); }
+sub sha256msg1 { sha256op38(0xcc,@_); }
+sub sha256msg2 { sha256op38(0xcd,@_); }
+
+&set_label("shaext",32);
+ &sub ("esp",32);
+
+ &movdqu ($ABEF,&QWP(0,$ctx)); # DCBA
+ &lea ($K256,&DWP(0x80,$K256));
+ &movdqu ($CDGH,&QWP(16,$ctx)); # HGFE
+ &movdqa ($TMP,&QWP(0x100-0x80,$K256)); # byte swap mask
+
+ &pshufd ($Wi,$ABEF,0x1b); # ABCD
+ &pshufd ($ABEF,$ABEF,0xb1); # CDAB
+ &pshufd ($CDGH,$CDGH,0x1b); # EFGH
+ &palignr ($ABEF,$CDGH,8); # ABEF
+ &punpcklqdq ($CDGH,$Wi); # CDGH
+ &jmp (&label("loop_shaext"));
+
+&set_label("loop_shaext",16);
+ &movdqu (@MSG[0],&QWP(0,$inp));
+ &movdqu (@MSG[1],&QWP(0x10,$inp));
+ &movdqu (@MSG[2],&QWP(0x20,$inp));
+ &pshufb (@MSG[0],$TMP);
+ &movdqu (@MSG[3],&QWP(0x30,$inp));
+ &movdqa (&QWP(16,"esp"),$CDGH); # offload
+
+ &movdqa ($Wi,&QWP(0*16-0x80,$K256));
+ &paddd ($Wi,@MSG[0]);
+ &pshufb (@MSG[1],$TMP);
+ &sha256rnds2 ($CDGH,$ABEF); # 0-3
+ &pshufd ($Wi,$Wi,0x0e);
+ &nop ();
+ &movdqa (&QWP(0,"esp"),$ABEF); # offload
+ &sha256rnds2 ($ABEF,$CDGH);
+
+ &movdqa ($Wi,&QWP(1*16-0x80,$K256));
+ &paddd ($Wi,@MSG[1]);
+ &pshufb (@MSG[2],$TMP);
+ &sha256rnds2 ($CDGH,$ABEF); # 4-7
+ &pshufd ($Wi,$Wi,0x0e);
+ &lea ($inp,&DWP(0x40,$inp));
+ &sha256msg1 (@MSG[0],@MSG[1]);
+ &sha256rnds2 ($ABEF,$CDGH);
+
+ &movdqa ($Wi,&QWP(2*16-0x80,$K256));
+ &paddd ($Wi,@MSG[2]);
+ &pshufb (@MSG[3],$TMP);
+ &sha256rnds2 ($CDGH,$ABEF); # 8-11
+ &pshufd ($Wi,$Wi,0x0e);
+ &movdqa ($TMP,@MSG[3]);
+ &palignr ($TMP,@MSG[2],4);
+ &nop ();
+ &paddd (@MSG[0],$TMP);
+ &sha256msg1 (@MSG[1],@MSG[2]);
+ &sha256rnds2 ($ABEF,$CDGH);
+
+ &movdqa ($Wi,&QWP(3*16-0x80,$K256));
+ &paddd ($Wi,@MSG[3]);
+ &sha256msg2 (@MSG[0],@MSG[3]);
+ &sha256rnds2 ($CDGH,$ABEF); # 12-15
+ &pshufd ($Wi,$Wi,0x0e);
+ &movdqa ($TMP,@MSG[0]);
+ &palignr ($TMP,@MSG[3],4);
+ &nop ();
+ &paddd (@MSG[1],$TMP);
+ &sha256msg1 (@MSG[2],@MSG[3]);
+ &sha256rnds2 ($ABEF,$CDGH);
+
+for($i=4;$i<16-3;$i++) {
+ &movdqa ($Wi,&QWP($i*16-0x80,$K256));
+ &paddd ($Wi,@MSG[0]);
+ &sha256msg2 (@MSG[1],@MSG[0]);
+ &sha256rnds2 ($CDGH,$ABEF); # 16-19...
+ &pshufd ($Wi,$Wi,0x0e);
+ &movdqa ($TMP,@MSG[1]);
+ &palignr ($TMP,@MSG[0],4);
+ &nop ();
+ &paddd (@MSG[2],$TMP);
+ &sha256msg1 (@MSG[3],@MSG[0]);
+ &sha256rnds2 ($ABEF,$CDGH);
+
+ push(@MSG,shift(@MSG));
+}
+ &movdqa ($Wi,&QWP(13*16-0x80,$K256));
+ &paddd ($Wi,@MSG[0]);
+ &sha256msg2 (@MSG[1],@MSG[0]);
+ &sha256rnds2 ($CDGH,$ABEF); # 52-55
+ &pshufd ($Wi,$Wi,0x0e);
+ &movdqa ($TMP,@MSG[1])
+ &palignr ($TMP,@MSG[0],4);
+ &sha256rnds2 ($ABEF,$CDGH);
+ &paddd (@MSG[2],$TMP);
+
+ &movdqa ($Wi,&QWP(14*16-0x80,$K256));
+ &paddd ($Wi,@MSG[1]);
+ &sha256rnds2 ($CDGH,$ABEF); # 56-59
+ &pshufd ($Wi,$Wi,0x0e);
+ &sha256msg2 (@MSG[2],@MSG[1]);
+ &movdqa ($TMP,&QWP(0x100-0x80,$K256)); # byte swap mask
+ &sha256rnds2 ($ABEF,$CDGH);
+
+ &movdqa ($Wi,&QWP(15*16-0x80,$K256));
+ &paddd ($Wi,@MSG[2]);
+ &nop ();
+ &sha256rnds2 ($CDGH,$ABEF); # 60-63
+ &pshufd ($Wi,$Wi,0x0e);
+ &cmp ($end,$inp);
+ &nop ();
+ &sha256rnds2 ($ABEF,$CDGH);
+
+ &paddd ($CDGH,&QWP(16,"esp"));
+ &paddd ($ABEF,&QWP(0,"esp"));
+ &jnz (&label("loop_shaext"));
+
+ &pshufd ($CDGH,$CDGH,0xb1); # DCHG
+ &pshufd ($TMP,$ABEF,0x1b); # FEBA
+ &pshufd ($ABEF,$ABEF,0xb1); # BAFE
+ &punpckhqdq ($ABEF,$CDGH); # DCBA
+ &palignr ($CDGH,$TMP,8); # HGFE
+
+ &mov ("esp",&DWP(32+12,"esp"));
+ &movdqu (&QWP(0,$ctx),$ABEF);
+ &movdqu (&QWP(16,$ctx),$CDGH);
+&function_end_A();
+}
+
+my @X = map("xmm$_",(0..3));
+my ($t0,$t1,$t2,$t3) = map("xmm$_",(4..7));
+my @AH = ($A,$T);
+
+&set_label("SSSE3",32);
+ &lea ("esp",&DWP(-96,"esp"));
+ # copy ctx->h[0-7] to A,B,C,D,E,F,G,H on stack
+ &mov ($AH[0],&DWP(0,"esi"));
+ &mov ($AH[1],&DWP(4,"esi"));
+ &mov ("ecx",&DWP(8,"esi"));
+ &mov ("edi",&DWP(12,"esi"));
+ #&mov (&DWP(0,"esp"),$AH[0]);
+ &mov (&DWP(4,"esp"),$AH[1]);
+ &xor ($AH[1],"ecx"); # magic
+ &mov (&DWP(8,"esp"),"ecx");
+ &mov (&DWP(12,"esp"),"edi");
+ &mov ($E,&DWP(16,"esi"));
+ &mov ("edi",&DWP(20,"esi"));
+ &mov ("ecx",&DWP(24,"esi"));
+ &mov ("esi",&DWP(28,"esi"));
+ #&mov (&DWP(16,"esp"),$E);
+ &mov (&DWP(20,"esp"),"edi");
+ &mov ("edi",&DWP(96+4,"esp")); # inp
+ &mov (&DWP(24,"esp"),"ecx");
+ &mov (&DWP(28,"esp"),"esi");
+ &movdqa ($t3,&QWP(256,$K256));
+ &jmp (&label("grand_ssse3"));
+
+&set_label("grand_ssse3",16);
+ # load input, reverse byte order, add K256[0..15], save to stack
+ &movdqu (@X[0],&QWP(0,"edi"));
+ &movdqu (@X[1],&QWP(16,"edi"));
+ &movdqu (@X[2],&QWP(32,"edi"));
+ &movdqu (@X[3],&QWP(48,"edi"));
+ &add ("edi",64);
+ &pshufb (@X[0],$t3);
+ &mov (&DWP(96+4,"esp"),"edi");
+ &pshufb (@X[1],$t3);
+ &movdqa ($t0,&QWP(0,$K256));
+ &pshufb (@X[2],$t3);
+ &movdqa ($t1,&QWP(16,$K256));
+ &paddd ($t0,@X[0]);
+ &pshufb (@X[3],$t3);
+ &movdqa ($t2,&QWP(32,$K256));
+ &paddd ($t1,@X[1]);
+ &movdqa ($t3,&QWP(48,$K256));
+ &movdqa (&QWP(32+0,"esp"),$t0);
+ &paddd ($t2,@X[2]);
+ &movdqa (&QWP(32+16,"esp"),$t1);
+ &paddd ($t3,@X[3]);
+ &movdqa (&QWP(32+32,"esp"),$t2);
+ &movdqa (&QWP(32+48,"esp"),$t3);
+ &jmp (&label("ssse3_00_47"));
+
+&set_label("ssse3_00_47",16);
+ &add ($K256,64);
+
+sub SSSE3_00_47 () {
+my $j = shift;
+my $body = shift;
+my @X = @_;
+my @insns = (&$body,&$body,&$body,&$body); # 120 instructions
+
+ eval(shift(@insns));
+ &movdqa ($t0,@X[1]);
+ eval(shift(@insns)); # @
+ eval(shift(@insns));
+ &movdqa ($t3,@X[3]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &palignr ($t0,@X[0],4); # X[1..4]
+ eval(shift(@insns));
+ eval(shift(@insns)); # @
+ eval(shift(@insns));
+ &palignr ($t3,@X[2],4); # X[9..12]
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &movdqa ($t1,$t0);
+ eval(shift(@insns)); # @
+ eval(shift(@insns));
+ &movdqa ($t2,$t0);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &psrld ($t0,3);
+ eval(shift(@insns));
+ eval(shift(@insns)); # @
+ &paddd (@X[0],$t3); # X[0..3] += X[9..12]
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &psrld ($t2,7);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns)); # @
+ eval(shift(@insns));
+ &pshufd ($t3,@X[3],0b11111010); # X[14..15]
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &pslld ($t1,32-18);
+ eval(shift(@insns));
+ eval(shift(@insns)); # @
+ &pxor ($t0,$t2);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &psrld ($t2,18-7);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns)); # @
+ &pxor ($t0,$t1);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &pslld ($t1,18-7);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns)); # @
+ &pxor ($t0,$t2);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &movdqa ($t2,$t3);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns)); # @
+ &pxor ($t0,$t1); # sigma0(X[1..4])
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &psrld ($t3,10);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns)); # @
+ &paddd (@X[0],$t0); # X[0..3] += sigma0(X[1..4])
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &psrlq ($t2,17);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns)); # @
+ &pxor ($t3,$t2);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &psrlq ($t2,19-17);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns)); # @
+ &pxor ($t3,$t2);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &pshufd ($t3,$t3,0b10000000);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns)); # @
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns)); # @
+ eval(shift(@insns));
+ &psrldq ($t3,8);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &paddd (@X[0],$t3); # X[0..1] += sigma1(X[14..15])
+ eval(shift(@insns)); # @
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns)); # @
+ eval(shift(@insns));
+ &pshufd ($t3,@X[0],0b01010000); # X[16..17]
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &movdqa ($t2,$t3);
+ eval(shift(@insns)); # @
+ &psrld ($t3,10);
+ eval(shift(@insns));
+ &psrlq ($t2,17);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns)); # @
+ &pxor ($t3,$t2);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &psrlq ($t2,19-17);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns)); # @
+ &pxor ($t3,$t2);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &pshufd ($t3,$t3,0b00001000);
+ eval(shift(@insns));
+ eval(shift(@insns)); # @
+ &movdqa ($t2,&QWP(16*$j,$K256));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &pslldq ($t3,8);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns)); # @
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns)); # @
+ &paddd (@X[0],$t3); # X[2..3] += sigma1(X[16..17])
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &paddd ($t2,@X[0]);
+ eval(shift(@insns)); # @
+
+ foreach (@insns) { eval; } # remaining instructions
+
+ &movdqa (&QWP(32+16*$j,"esp"),$t2);
+}
+
+sub body_00_15 () {
+ (
+ '&mov ("ecx",$E);',
+ '&ror ($E,25-11);',
+ '&mov ("esi",&off($f));',
+ '&xor ($E,"ecx");',
+ '&mov ("edi",&off($g));',
+ '&xor ("esi","edi");',
+ '&ror ($E,11-6);',
+ '&and ("esi","ecx");',
+ '&mov (&off($e),"ecx");', # save $E, modulo-scheduled
+ '&xor ($E,"ecx");',
+ '&xor ("edi","esi");', # Ch(e,f,g)
+ '&ror ($E,6);', # T = Sigma1(e)
+ '&mov ("ecx",$AH[0]);',
+ '&add ($E,"edi");', # T += Ch(e,f,g)
+ '&mov ("edi",&off($b));',
+ '&mov ("esi",$AH[0]);',
+
+ '&ror ("ecx",22-13);',
+ '&mov (&off($a),$AH[0]);', # save $A, modulo-scheduled
+ '&xor ("ecx",$AH[0]);',
+ '&xor ($AH[0],"edi");', # a ^= b, (b^c) in next round
+ '&add ($E,&off($h));', # T += h
+ '&ror ("ecx",13-2);',
+ '&and ($AH[1],$AH[0]);', # (b^c) &= (a^b)
+ '&xor ("ecx","esi");',
+ '&add ($E,&DWP(32+4*($i&15),"esp"));', # T += K[i]+X[i]
+ '&xor ($AH[1],"edi");', # h = Maj(a,b,c) = Ch(a^b,c,b)
+ '&ror ("ecx",2);', # Sigma0(a)
+
+ '&add ($AH[1],$E);', # h += T
+ '&add ($E,&off($d));', # d += T
+ '&add ($AH[1],"ecx");'. # h += Sigma0(a)
+
+ '@AH = reverse(@AH); $i++;' # rotate(a,h)
+ );
+}
+
+ for ($i=0,$j=0; $j<4; $j++) {
+ &SSSE3_00_47($j,\&body_00_15,@X);
+ push(@X,shift(@X)); # rotate(@X)
+ }
+ &cmp (&DWP(16*$j,$K256),0x00010203);
+ &jne (&label("ssse3_00_47"));
+
+ for ($i=0; $i<16; ) {
+ foreach(body_00_15()) { eval; }
+ }
+
+ &mov ("esi",&DWP(96,"esp")); #ctx
+ #&mov ($AH[0],&DWP(0,"esp"));
+ &xor ($AH[1],"edi"); #&mov ($AH[1],&DWP(4,"esp"));
+ #&mov ("edi", &DWP(8,"esp"));
+ &mov ("ecx",&DWP(12,"esp"));
+ &add ($AH[0],&DWP(0,"esi"));
+ &add ($AH[1],&DWP(4,"esi"));
+ &add ("edi",&DWP(8,"esi"));
+ &add ("ecx",&DWP(12,"esi"));
+ &mov (&DWP(0,"esi"),$AH[0]);
+ &mov (&DWP(4,"esi"),$AH[1]);
+ &mov (&DWP(8,"esi"),"edi");
+ &mov (&DWP(12,"esi"),"ecx");
+ #&mov (&DWP(0,"esp"),$AH[0]);
+ &mov (&DWP(4,"esp"),$AH[1]);
+ &xor ($AH[1],"edi"); # magic
+ &mov (&DWP(8,"esp"),"edi");
+ &mov (&DWP(12,"esp"),"ecx");
+ #&mov ($E,&DWP(16,"esp"));
+ &mov ("edi",&DWP(20,"esp"));
+ &mov ("ecx",&DWP(24,"esp"));
+ &add ($E,&DWP(16,"esi"));
+ &add ("edi",&DWP(20,"esi"));
+ &add ("ecx",&DWP(24,"esi"));
+ &mov (&DWP(16,"esi"),$E);
+ &mov (&DWP(20,"esi"),"edi");
+ &mov (&DWP(20,"esp"),"edi");
+ &mov ("edi",&DWP(28,"esp"));
+ &mov (&DWP(24,"esi"),"ecx");
+ #&mov (&DWP(16,"esp"),$E);
+ &add ("edi",&DWP(28,"esi"));
+ &mov (&DWP(24,"esp"),"ecx");
+ &mov (&DWP(28,"esi"),"edi");
+ &mov (&DWP(28,"esp"),"edi");
+ &mov ("edi",&DWP(96+4,"esp")); # inp
+
+ &movdqa ($t3,&QWP(64,$K256));
+ &sub ($K256,3*64); # rewind K
+ &cmp ("edi",&DWP(96+8,"esp")); # are we done yet?
+ &jb (&label("grand_ssse3"));
+
+ &mov ("esp",&DWP(96+12,"esp")); # restore sp
+&function_end_A();
+ if ($avx) {
+&set_label("AVX",32);
+ if ($avx>1) {
+ &and ("edx",1<<8|1<<3); # check for BMI2+BMI1
+ &cmp ("edx",1<<8|1<<3);
+ &je (&label("AVX_BMI"));
+ }
+ &lea ("esp",&DWP(-96,"esp"));
+ &vzeroall ();
+ # copy ctx->h[0-7] to A,B,C,D,E,F,G,H on stack
+ &mov ($AH[0],&DWP(0,"esi"));
+ &mov ($AH[1],&DWP(4,"esi"));
+ &mov ("ecx",&DWP(8,"esi"));
+ &mov ("edi",&DWP(12,"esi"));
+ #&mov (&DWP(0,"esp"),$AH[0]);
+ &mov (&DWP(4,"esp"),$AH[1]);
+ &xor ($AH[1],"ecx"); # magic
+ &mov (&DWP(8,"esp"),"ecx");
+ &mov (&DWP(12,"esp"),"edi");
+ &mov ($E,&DWP(16,"esi"));
+ &mov ("edi",&DWP(20,"esi"));
+ &mov ("ecx",&DWP(24,"esi"));
+ &mov ("esi",&DWP(28,"esi"));
+ #&mov (&DWP(16,"esp"),$E);
+ &mov (&DWP(20,"esp"),"edi");
+ &mov ("edi",&DWP(96+4,"esp")); # inp
+ &mov (&DWP(24,"esp"),"ecx");
+ &mov (&DWP(28,"esp"),"esi");
+ &vmovdqa ($t3,&QWP(256,$K256));
+ &jmp (&label("grand_avx"));
+
+&set_label("grand_avx",32);
+ # load input, reverse byte order, add K256[0..15], save to stack
+ &vmovdqu (@X[0],&QWP(0,"edi"));
+ &vmovdqu (@X[1],&QWP(16,"edi"));
+ &vmovdqu (@X[2],&QWP(32,"edi"));
+ &vmovdqu (@X[3],&QWP(48,"edi"));
+ &add ("edi",64);
+ &vpshufb (@X[0],@X[0],$t3);
+ &mov (&DWP(96+4,"esp"),"edi");
+ &vpshufb (@X[1],@X[1],$t3);
+ &vpshufb (@X[2],@X[2],$t3);
+ &vpaddd ($t0,@X[0],&QWP(0,$K256));
+ &vpshufb (@X[3],@X[3],$t3);
+ &vpaddd ($t1,@X[1],&QWP(16,$K256));
+ &vpaddd ($t2,@X[2],&QWP(32,$K256));
+ &vpaddd ($t3,@X[3],&QWP(48,$K256));
+ &vmovdqa (&QWP(32+0,"esp"),$t0);
+ &vmovdqa (&QWP(32+16,"esp"),$t1);
+ &vmovdqa (&QWP(32+32,"esp"),$t2);
+ &vmovdqa (&QWP(32+48,"esp"),$t3);
+ &jmp (&label("avx_00_47"));
+
+&set_label("avx_00_47",16);
+ &add ($K256,64);
+
+sub Xupdate_AVX () {
+ (
+ '&vpalignr ($t0,@X[1],@X[0],4);', # X[1..4]
+ '&vpalignr ($t3,@X[3],@X[2],4);', # X[9..12]
+ '&vpsrld ($t2,$t0,7);',
+ '&vpaddd (@X[0],@X[0],$t3);', # X[0..3] += X[9..16]
+ '&vpsrld ($t3,$t0,3);',
+ '&vpslld ($t1,$t0,14);',
+ '&vpxor ($t0,$t3,$t2);',
+ '&vpshufd ($t3,@X[3],0b11111010)',# X[14..15]
+ '&vpsrld ($t2,$t2,18-7);',
+ '&vpxor ($t0,$t0,$t1);',
+ '&vpslld ($t1,$t1,25-14);',
+ '&vpxor ($t0,$t0,$t2);',
+ '&vpsrld ($t2,$t3,10);',
+ '&vpxor ($t0,$t0,$t1);', # sigma0(X[1..4])
+ '&vpsrlq ($t1,$t3,17);',
+ '&vpaddd (@X[0],@X[0],$t0);', # X[0..3] += sigma0(X[1..4])
+ '&vpxor ($t2,$t2,$t1);',
+ '&vpsrlq ($t3,$t3,19);',
+ '&vpxor ($t2,$t2,$t3);', # sigma1(X[14..15]
+ '&vpshufd ($t3,$t2,0b10000100);',
+ '&vpsrldq ($t3,$t3,8);',
+ '&vpaddd (@X[0],@X[0],$t3);', # X[0..1] += sigma1(X[14..15])
+ '&vpshufd ($t3,@X[0],0b01010000)',# X[16..17]
+ '&vpsrld ($t2,$t3,10);',
+ '&vpsrlq ($t1,$t3,17);',
+ '&vpxor ($t2,$t2,$t1);',
+ '&vpsrlq ($t3,$t3,19);',
+ '&vpxor ($t2,$t2,$t3);', # sigma1(X[16..17]
+ '&vpshufd ($t3,$t2,0b11101000);',
+ '&vpslldq ($t3,$t3,8);',
+ '&vpaddd (@X[0],@X[0],$t3);' # X[2..3] += sigma1(X[16..17])
+ );
+}
+
+local *ror = sub { &shrd(@_[0],@_) };
+sub AVX_00_47 () {
+my $j = shift;
+my $body = shift;
+my @X = @_;
+my @insns = (&$body,&$body,&$body,&$body); # 120 instructions
+my $insn;
+
+ foreach (Xupdate_AVX()) { # 31 instructions
+ eval;
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval($insn = shift(@insns));
+ eval(shift(@insns)) if ($insn =~ /rorx/ && @insns[0] =~ /rorx/);
+ }
+ &vpaddd ($t2,@X[0],&QWP(16*$j,$K256));
+ foreach (@insns) { eval; } # remaining instructions
+ &vmovdqa (&QWP(32+16*$j,"esp"),$t2);
+}
+
+ for ($i=0,$j=0; $j<4; $j++) {
+ &AVX_00_47($j,\&body_00_15,@X);
+ push(@X,shift(@X)); # rotate(@X)
+ }
+ &cmp (&DWP(16*$j,$K256),0x00010203);
+ &jne (&label("avx_00_47"));
+
+ for ($i=0; $i<16; ) {
+ foreach(body_00_15()) { eval; }
+ }
+
+ &mov ("esi",&DWP(96,"esp")); #ctx
+ #&mov ($AH[0],&DWP(0,"esp"));
+ &xor ($AH[1],"edi"); #&mov ($AH[1],&DWP(4,"esp"));
+ #&mov ("edi", &DWP(8,"esp"));
+ &mov ("ecx",&DWP(12,"esp"));
+ &add ($AH[0],&DWP(0,"esi"));
+ &add ($AH[1],&DWP(4,"esi"));
+ &add ("edi",&DWP(8,"esi"));
+ &add ("ecx",&DWP(12,"esi"));
+ &mov (&DWP(0,"esi"),$AH[0]);
+ &mov (&DWP(4,"esi"),$AH[1]);
+ &mov (&DWP(8,"esi"),"edi");
+ &mov (&DWP(12,"esi"),"ecx");
+ #&mov (&DWP(0,"esp"),$AH[0]);
+ &mov (&DWP(4,"esp"),$AH[1]);
+ &xor ($AH[1],"edi"); # magic
+ &mov (&DWP(8,"esp"),"edi");
+ &mov (&DWP(12,"esp"),"ecx");
+ #&mov ($E,&DWP(16,"esp"));
+ &mov ("edi",&DWP(20,"esp"));
+ &mov ("ecx",&DWP(24,"esp"));
+ &add ($E,&DWP(16,"esi"));
+ &add ("edi",&DWP(20,"esi"));
+ &add ("ecx",&DWP(24,"esi"));
+ &mov (&DWP(16,"esi"),$E);
+ &mov (&DWP(20,"esi"),"edi");
+ &mov (&DWP(20,"esp"),"edi");
+ &mov ("edi",&DWP(28,"esp"));
+ &mov (&DWP(24,"esi"),"ecx");
+ #&mov (&DWP(16,"esp"),$E);
+ &add ("edi",&DWP(28,"esi"));
+ &mov (&DWP(24,"esp"),"ecx");
+ &mov (&DWP(28,"esi"),"edi");
+ &mov (&DWP(28,"esp"),"edi");
+ &mov ("edi",&DWP(96+4,"esp")); # inp
+
+ &vmovdqa ($t3,&QWP(64,$K256));
+ &sub ($K256,3*64); # rewind K
+ &cmp ("edi",&DWP(96+8,"esp")); # are we done yet?
+ &jb (&label("grand_avx"));
+
+ &mov ("esp",&DWP(96+12,"esp")); # restore sp
+ &vzeroall ();
+&function_end_A();
+ if ($avx>1) {
+sub bodyx_00_15 () { # +10%
+ (
+ '&rorx ("ecx",$E,6)',
+ '&rorx ("esi",$E,11)',
+ '&mov (&off($e),$E)', # save $E, modulo-scheduled
+ '&rorx ("edi",$E,25)',
+ '&xor ("ecx","esi")',
+ '&andn ("esi",$E,&off($g))',
+ '&xor ("ecx","edi")', # Sigma1(e)
+ '&and ($E,&off($f))',
+ '&mov (&off($a),$AH[0]);', # save $A, modulo-scheduled
+ '&or ($E,"esi")', # T = Ch(e,f,g)
+
+ '&rorx ("edi",$AH[0],2)',
+ '&rorx ("esi",$AH[0],13)',
+ '&lea ($E,&DWP(0,$E,"ecx"))', # T += Sigma1(e)
+ '&rorx ("ecx",$AH[0],22)',
+ '&xor ("esi","edi")',
+ '&mov ("edi",&off($b))',
+ '&xor ("ecx","esi")', # Sigma0(a)
+
+ '&xor ($AH[0],"edi")', # a ^= b, (b^c) in next round
+ '&add ($E,&off($h))', # T += h
+ '&and ($AH[1],$AH[0])', # (b^c) &= (a^b)
+ '&add ($E,&DWP(32+4*($i&15),"esp"))', # T += K[i]+X[i]
+ '&xor ($AH[1],"edi")', # h = Maj(a,b,c) = Ch(a^b,c,b)
+
+ '&add ("ecx",$E)', # h += T
+ '&add ($E,&off($d))', # d += T
+ '&lea ($AH[1],&DWP(0,$AH[1],"ecx"));'. # h += Sigma0(a)
+
+ '@AH = reverse(@AH); $i++;' # rotate(a,h)
+ );
+}
+
+&set_label("AVX_BMI",32);
+ &lea ("esp",&DWP(-96,"esp"));
+ &vzeroall ();
+ # copy ctx->h[0-7] to A,B,C,D,E,F,G,H on stack
+ &mov ($AH[0],&DWP(0,"esi"));
+ &mov ($AH[1],&DWP(4,"esi"));
+ &mov ("ecx",&DWP(8,"esi"));
+ &mov ("edi",&DWP(12,"esi"));
+ #&mov (&DWP(0,"esp"),$AH[0]);
+ &mov (&DWP(4,"esp"),$AH[1]);
+ &xor ($AH[1],"ecx"); # magic
+ &mov (&DWP(8,"esp"),"ecx");
+ &mov (&DWP(12,"esp"),"edi");
+ &mov ($E,&DWP(16,"esi"));
+ &mov ("edi",&DWP(20,"esi"));
+ &mov ("ecx",&DWP(24,"esi"));
+ &mov ("esi",&DWP(28,"esi"));
+ #&mov (&DWP(16,"esp"),$E);
+ &mov (&DWP(20,"esp"),"edi");
+ &mov ("edi",&DWP(96+4,"esp")); # inp
+ &mov (&DWP(24,"esp"),"ecx");
+ &mov (&DWP(28,"esp"),"esi");
+ &vmovdqa ($t3,&QWP(256,$K256));
+ &jmp (&label("grand_avx_bmi"));
+
+&set_label("grand_avx_bmi",32);
+ # load input, reverse byte order, add K256[0..15], save to stack
+ &vmovdqu (@X[0],&QWP(0,"edi"));
+ &vmovdqu (@X[1],&QWP(16,"edi"));
+ &vmovdqu (@X[2],&QWP(32,"edi"));
+ &vmovdqu (@X[3],&QWP(48,"edi"));
+ &add ("edi",64);
+ &vpshufb (@X[0],@X[0],$t3);
+ &mov (&DWP(96+4,"esp"),"edi");
+ &vpshufb (@X[1],@X[1],$t3);
+ &vpshufb (@X[2],@X[2],$t3);
+ &vpaddd ($t0,@X[0],&QWP(0,$K256));
+ &vpshufb (@X[3],@X[3],$t3);
+ &vpaddd ($t1,@X[1],&QWP(16,$K256));
+ &vpaddd ($t2,@X[2],&QWP(32,$K256));
+ &vpaddd ($t3,@X[3],&QWP(48,$K256));
+ &vmovdqa (&QWP(32+0,"esp"),$t0);
+ &vmovdqa (&QWP(32+16,"esp"),$t1);
+ &vmovdqa (&QWP(32+32,"esp"),$t2);
+ &vmovdqa (&QWP(32+48,"esp"),$t3);
+ &jmp (&label("avx_bmi_00_47"));
+
+&set_label("avx_bmi_00_47",16);
+ &add ($K256,64);
+
+ for ($i=0,$j=0; $j<4; $j++) {
+ &AVX_00_47($j,\&bodyx_00_15,@X);
+ push(@X,shift(@X)); # rotate(@X)
+ }
+ &cmp (&DWP(16*$j,$K256),0x00010203);
+ &jne (&label("avx_bmi_00_47"));
+
+ for ($i=0; $i<16; ) {
+ foreach(bodyx_00_15()) { eval; }
+ }
+
+ &mov ("esi",&DWP(96,"esp")); #ctx
+ #&mov ($AH[0],&DWP(0,"esp"));
+ &xor ($AH[1],"edi"); #&mov ($AH[1],&DWP(4,"esp"));
+ #&mov ("edi", &DWP(8,"esp"));
+ &mov ("ecx",&DWP(12,"esp"));
+ &add ($AH[0],&DWP(0,"esi"));
+ &add ($AH[1],&DWP(4,"esi"));
+ &add ("edi",&DWP(8,"esi"));
+ &add ("ecx",&DWP(12,"esi"));
+ &mov (&DWP(0,"esi"),$AH[0]);
+ &mov (&DWP(4,"esi"),$AH[1]);
+ &mov (&DWP(8,"esi"),"edi");
+ &mov (&DWP(12,"esi"),"ecx");
+ #&mov (&DWP(0,"esp"),$AH[0]);
+ &mov (&DWP(4,"esp"),$AH[1]);
+ &xor ($AH[1],"edi"); # magic
+ &mov (&DWP(8,"esp"),"edi");
+ &mov (&DWP(12,"esp"),"ecx");
+ #&mov ($E,&DWP(16,"esp"));
+ &mov ("edi",&DWP(20,"esp"));
+ &mov ("ecx",&DWP(24,"esp"));
+ &add ($E,&DWP(16,"esi"));
+ &add ("edi",&DWP(20,"esi"));
+ &add ("ecx",&DWP(24,"esi"));
+ &mov (&DWP(16,"esi"),$E);
+ &mov (&DWP(20,"esi"),"edi");
+ &mov (&DWP(20,"esp"),"edi");
+ &mov ("edi",&DWP(28,"esp"));
+ &mov (&DWP(24,"esi"),"ecx");
+ #&mov (&DWP(16,"esp"),$E);
+ &add ("edi",&DWP(28,"esi"));
+ &mov (&DWP(24,"esp"),"ecx");
+ &mov (&DWP(28,"esi"),"edi");
+ &mov (&DWP(28,"esp"),"edi");
+ &mov ("edi",&DWP(96+4,"esp")); # inp
+
+ &vmovdqa ($t3,&QWP(64,$K256));
+ &sub ($K256,3*64); # rewind K
+ &cmp ("edi",&DWP(96+8,"esp")); # are we done yet?
+ &jb (&label("grand_avx_bmi"));
+
+ &mov ("esp",&DWP(96+12,"esp")); # restore sp
+ &vzeroall ();
+&function_end_A();
+ }
+ }
+ }}}
+&function_end_B("sha256_block_data_order");
+
+&asm_finish();
diff --git a/src/crypto/sha/asm/sha256-armv4.pl b/src/crypto/sha/asm/sha256-armv4.pl
new file mode 100644
index 0000000..f14c9c3
--- /dev/null
+++ b/src/crypto/sha/asm/sha256-armv4.pl
@@ -0,0 +1,661 @@
+#!/usr/bin/env perl
+
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+# project. The module is, however, dual licensed under OpenSSL and
+# CRYPTOGAMS licenses depending on where you obtain it. For further
+# details see http://www.openssl.org/~appro/cryptogams/.
+# ====================================================================
+
+# SHA256 block procedure for ARMv4. May 2007.
+
+# Performance is ~2x better than gcc 3.4 generated code and in "abso-
+# lute" terms is ~2250 cycles per 64-byte block or ~35 cycles per
+# byte [on single-issue Xscale PXA250 core].
+
+# July 2010.
+#
+# Rescheduling for dual-issue pipeline resulted in 22% improvement on
+# Cortex A8 core and ~20 cycles per processed byte.
+
+# February 2011.
+#
+# Profiler-assisted and platform-specific optimization resulted in 16%
+# improvement on Cortex A8 core and ~15.4 cycles per processed byte.
+
+# September 2013.
+#
+# Add NEON implementation. On Cortex A8 it was measured to process one
+# byte in 12.5 cycles or 23% faster than integer-only code. Snapdragon
+# S4 does it in 12.5 cycles too, but it's 50% faster than integer-only
+# code (meaning that latter performs sub-optimally, nothing was done
+# about it).
+
+# May 2014.
+#
+# Add ARMv8 code path performing at 2.0 cpb on Apple A7.
+
+while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {}
+open STDOUT,">$output";
+
+$ctx="r0"; $t0="r0";
+$inp="r1"; $t4="r1";
+$len="r2"; $t1="r2";
+$T1="r3"; $t3="r3";
+$A="r4";
+$B="r5";
+$C="r6";
+$D="r7";
+$E="r8";
+$F="r9";
+$G="r10";
+$H="r11";
+@V=($A,$B,$C,$D,$E,$F,$G,$H);
+$t2="r12";
+$Ktbl="r14";
+
+@Sigma0=( 2,13,22);
+@Sigma1=( 6,11,25);
+@sigma0=( 7,18, 3);
+@sigma1=(17,19,10);
+
+sub BODY_00_15 {
+my ($i,$a,$b,$c,$d,$e,$f,$g,$h) = @_;
+
+$code.=<<___ if ($i<16);
+#if __ARM_ARCH__>=7
+ @ ldr $t1,[$inp],#4 @ $i
+# if $i==15
+ str $inp,[sp,#17*4] @ make room for $t4
+# endif
+ eor $t0,$e,$e,ror#`$Sigma1[1]-$Sigma1[0]`
+ add $a,$a,$t2 @ h+=Maj(a,b,c) from the past
+ eor $t0,$t0,$e,ror#`$Sigma1[2]-$Sigma1[0]` @ Sigma1(e)
+ rev $t1,$t1
+#else
+ @ ldrb $t1,[$inp,#3] @ $i
+ add $a,$a,$t2 @ h+=Maj(a,b,c) from the past
+ ldrb $t2,[$inp,#2]
+ ldrb $t0,[$inp,#1]
+ orr $t1,$t1,$t2,lsl#8
+ ldrb $t2,[$inp],#4
+ orr $t1,$t1,$t0,lsl#16
+# if $i==15
+ str $inp,[sp,#17*4] @ make room for $t4
+# endif
+ eor $t0,$e,$e,ror#`$Sigma1[1]-$Sigma1[0]`
+ orr $t1,$t1,$t2,lsl#24
+ eor $t0,$t0,$e,ror#`$Sigma1[2]-$Sigma1[0]` @ Sigma1(e)
+#endif
+___
+$code.=<<___;
+ ldr $t2,[$Ktbl],#4 @ *K256++
+ add $h,$h,$t1 @ h+=X[i]
+ str $t1,[sp,#`$i%16`*4]
+ eor $t1,$f,$g
+ add $h,$h,$t0,ror#$Sigma1[0] @ h+=Sigma1(e)
+ and $t1,$t1,$e
+ add $h,$h,$t2 @ h+=K256[i]
+ eor $t1,$t1,$g @ Ch(e,f,g)
+ eor $t0,$a,$a,ror#`$Sigma0[1]-$Sigma0[0]`
+ add $h,$h,$t1 @ h+=Ch(e,f,g)
+#if $i==31
+ and $t2,$t2,#0xff
+ cmp $t2,#0xf2 @ done?
+#endif
+#if $i<15
+# if __ARM_ARCH__>=7
+ ldr $t1,[$inp],#4 @ prefetch
+# else
+ ldrb $t1,[$inp,#3]
+# endif
+ eor $t2,$a,$b @ a^b, b^c in next round
+#else
+ ldr $t1,[sp,#`($i+2)%16`*4] @ from future BODY_16_xx
+ eor $t2,$a,$b @ a^b, b^c in next round
+ ldr $t4,[sp,#`($i+15)%16`*4] @ from future BODY_16_xx
+#endif
+ eor $t0,$t0,$a,ror#`$Sigma0[2]-$Sigma0[0]` @ Sigma0(a)
+ and $t3,$t3,$t2 @ (b^c)&=(a^b)
+ add $d,$d,$h @ d+=h
+ eor $t3,$t3,$b @ Maj(a,b,c)
+ add $h,$h,$t0,ror#$Sigma0[0] @ h+=Sigma0(a)
+ @ add $h,$h,$t3 @ h+=Maj(a,b,c)
+___
+ ($t2,$t3)=($t3,$t2);
+}
+
+sub BODY_16_XX {
+my ($i,$a,$b,$c,$d,$e,$f,$g,$h) = @_;
+
+$code.=<<___;
+ @ ldr $t1,[sp,#`($i+1)%16`*4] @ $i
+ @ ldr $t4,[sp,#`($i+14)%16`*4]
+ mov $t0,$t1,ror#$sigma0[0]
+ add $a,$a,$t2 @ h+=Maj(a,b,c) from the past
+ mov $t2,$t4,ror#$sigma1[0]
+ eor $t0,$t0,$t1,ror#$sigma0[1]
+ eor $t2,$t2,$t4,ror#$sigma1[1]
+ eor $t0,$t0,$t1,lsr#$sigma0[2] @ sigma0(X[i+1])
+ ldr $t1,[sp,#`($i+0)%16`*4]
+ eor $t2,$t2,$t4,lsr#$sigma1[2] @ sigma1(X[i+14])
+ ldr $t4,[sp,#`($i+9)%16`*4]
+
+ add $t2,$t2,$t0
+ eor $t0,$e,$e,ror#`$Sigma1[1]-$Sigma1[0]` @ from BODY_00_15
+ add $t1,$t1,$t2
+ eor $t0,$t0,$e,ror#`$Sigma1[2]-$Sigma1[0]` @ Sigma1(e)
+ add $t1,$t1,$t4 @ X[i]
+___
+ &BODY_00_15(@_);
+}
+
+$code=<<___;
+#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
+.word 0 @ terminator
+#if __ARM_MAX_ARCH__>=7
+.LOPENSSL_armcap:
+.word OPENSSL_armcap_P-sha256_block_data_order
+#endif
+.align 5
+
+.global sha256_block_data_order
+.type sha256_block_data_order,%function
+sha256_block_data_order:
+ sub r3,pc,#8 @ sha256_block_data_order
+ add $len,$inp,$len,lsl#6 @ len to point at the end of inp
+#if __ARM_MAX_ARCH__>=7
+ ldr r12,.LOPENSSL_armcap
+ ldr r12,[r3,r12] @ OPENSSL_armcap_P
+ tst r12,#ARMV8_SHA256
+ bne .LARMv8
+ tst r12,#ARMV7_NEON
+ bne .LNEON
+#endif
+ stmdb sp!,{$ctx,$inp,$len,r4-r11,lr}
+ ldmia $ctx,{$A,$B,$C,$D,$E,$F,$G,$H}
+ sub $Ktbl,r3,#256+32 @ K256
+ sub sp,sp,#16*4 @ alloca(X[16])
+.Loop:
+# if __ARM_ARCH__>=7
+ ldr $t1,[$inp],#4
+# else
+ ldrb $t1,[$inp,#3]
+# endif
+ eor $t3,$B,$C @ magic
+ eor $t2,$t2,$t2
+___
+for($i=0;$i<16;$i++) { &BODY_00_15($i,@V); unshift(@V,pop(@V)); }
+$code.=".Lrounds_16_xx:\n";
+for (;$i<32;$i++) { &BODY_16_XX($i,@V); unshift(@V,pop(@V)); }
+$code.=<<___;
+ ldreq $t3,[sp,#16*4] @ pull ctx
+ bne .Lrounds_16_xx
+
+ add $A,$A,$t2 @ h+=Maj(a,b,c) from the past
+ ldr $t0,[$t3,#0]
+ ldr $t1,[$t3,#4]
+ ldr $t2,[$t3,#8]
+ add $A,$A,$t0
+ ldr $t0,[$t3,#12]
+ add $B,$B,$t1
+ ldr $t1,[$t3,#16]
+ add $C,$C,$t2
+ ldr $t2,[$t3,#20]
+ add $D,$D,$t0
+ ldr $t0,[$t3,#24]
+ add $E,$E,$t1
+ ldr $t1,[$t3,#28]
+ add $F,$F,$t2
+ ldr $inp,[sp,#17*4] @ pull inp
+ ldr $t2,[sp,#18*4] @ pull inp+len
+ add $G,$G,$t0
+ add $H,$H,$t1
+ stmia $t3,{$A,$B,$C,$D,$E,$F,$G,$H}
+ cmp $inp,$t2
+ sub $Ktbl,$Ktbl,#256 @ rewind Ktbl
+ bne .Loop
+
+ add sp,sp,#`16+3`*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
+ bx lr @ interoperable with Thumb ISA:-)
+#endif
+.size sha256_block_data_order,.-sha256_block_data_order
+___
+######################################################################
+# NEON stuff
+#
+{{{
+my @X=map("q$_",(0..3));
+my ($T0,$T1,$T2,$T3,$T4,$T5)=("q8","q9","q10","q11","d24","d25");
+my $Xfer=$t4;
+my $j=0;
+
+sub Dlo() { shift=~m|q([1]?[0-9])|?"d".($1*2):""; }
+sub Dhi() { shift=~m|q([1]?[0-9])|?"d".($1*2+1):""; }
+
+sub AUTOLOAD() # thunk [simplified] x86-style perlasm
+{ my $opcode = $AUTOLOAD; $opcode =~ s/.*:://; $opcode =~ s/_/\./;
+ my $arg = pop;
+ $arg = "#$arg" if ($arg*1 eq $arg);
+ $code .= "\t$opcode\t".join(',',@_,$arg)."\n";
+}
+
+sub Xupdate()
+{ use integer;
+ my $body = shift;
+ my @insns = (&$body,&$body,&$body,&$body);
+ my ($a,$b,$c,$d,$e,$f,$g,$h);
+
+ &vext_8 ($T0,@X[0],@X[1],4); # X[1..4]
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vext_8 ($T1,@X[2],@X[3],4); # X[9..12]
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vshr_u32 ($T2,$T0,$sigma0[0]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vadd_i32 (@X[0],@X[0],$T1); # X[0..3] += X[9..12]
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vshr_u32 ($T1,$T0,$sigma0[2]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vsli_32 ($T2,$T0,32-$sigma0[0]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vshr_u32 ($T3,$T0,$sigma0[1]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &veor ($T1,$T1,$T2);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vsli_32 ($T3,$T0,32-$sigma0[1]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vshr_u32 ($T4,&Dhi(@X[3]),$sigma1[0]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &veor ($T1,$T1,$T3); # sigma0(X[1..4])
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vsli_32 ($T4,&Dhi(@X[3]),32-$sigma1[0]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vshr_u32 ($T5,&Dhi(@X[3]),$sigma1[2]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vadd_i32 (@X[0],@X[0],$T1); # X[0..3] += sigma0(X[1..4])
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &veor ($T5,$T5,$T4);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vshr_u32 ($T4,&Dhi(@X[3]),$sigma1[1]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vsli_32 ($T4,&Dhi(@X[3]),32-$sigma1[1]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &veor ($T5,$T5,$T4); # sigma1(X[14..15])
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vadd_i32 (&Dlo(@X[0]),&Dlo(@X[0]),$T5);# X[0..1] += sigma1(X[14..15])
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vshr_u32 ($T4,&Dlo(@X[0]),$sigma1[0]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vsli_32 ($T4,&Dlo(@X[0]),32-$sigma1[0]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vshr_u32 ($T5,&Dlo(@X[0]),$sigma1[2]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &veor ($T5,$T5,$T4);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vshr_u32 ($T4,&Dlo(@X[0]),$sigma1[1]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vld1_32 ("{$T0}","[$Ktbl,:128]!");
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vsli_32 ($T4,&Dlo(@X[0]),32-$sigma1[1]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &veor ($T5,$T5,$T4); # sigma1(X[16..17])
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vadd_i32 (&Dhi(@X[0]),&Dhi(@X[0]),$T5);# X[2..3] += sigma1(X[16..17])
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vadd_i32 ($T0,$T0,@X[0]);
+ while($#insns>=2) { eval(shift(@insns)); }
+ &vst1_32 ("{$T0}","[$Xfer,:128]!");
+ eval(shift(@insns));
+ eval(shift(@insns));
+
+ push(@X,shift(@X)); # "rotate" X[]
+}
+
+sub Xpreload()
+{ use integer;
+ my $body = shift;
+ my @insns = (&$body,&$body,&$body,&$body);
+ my ($a,$b,$c,$d,$e,$f,$g,$h);
+
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vld1_32 ("{$T0}","[$Ktbl,:128]!");
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vrev32_8 (@X[0],@X[0]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vadd_i32 ($T0,$T0,@X[0]);
+ foreach (@insns) { eval; } # remaining instructions
+ &vst1_32 ("{$T0}","[$Xfer,:128]!");
+
+ push(@X,shift(@X)); # "rotate" X[]
+}
+
+sub body_00_15 () {
+ (
+ '($a,$b,$c,$d,$e,$f,$g,$h)=@V;'.
+ '&add ($h,$h,$t1)', # h+=X[i]+K[i]
+ '&eor ($t1,$f,$g)',
+ '&eor ($t0,$e,$e,"ror#".($Sigma1[1]-$Sigma1[0]))',
+ '&add ($a,$a,$t2)', # h+=Maj(a,b,c) from the past
+ '&and ($t1,$t1,$e)',
+ '&eor ($t2,$t0,$e,"ror#".($Sigma1[2]-$Sigma1[0]))', # Sigma1(e)
+ '&eor ($t0,$a,$a,"ror#".($Sigma0[1]-$Sigma0[0]))',
+ '&eor ($t1,$t1,$g)', # Ch(e,f,g)
+ '&add ($h,$h,$t2,"ror#$Sigma1[0]")', # h+=Sigma1(e)
+ '&eor ($t2,$a,$b)', # a^b, b^c in next round
+ '&eor ($t0,$t0,$a,"ror#".($Sigma0[2]-$Sigma0[0]))', # Sigma0(a)
+ '&add ($h,$h,$t1)', # h+=Ch(e,f,g)
+ '&ldr ($t1,sprintf "[sp,#%d]",4*(($j+1)&15)) if (($j&15)!=15);'.
+ '&ldr ($t1,"[$Ktbl]") if ($j==15);'.
+ '&ldr ($t1,"[sp,#64]") if ($j==31)',
+ '&and ($t3,$t3,$t2)', # (b^c)&=(a^b)
+ '&add ($d,$d,$h)', # d+=h
+ '&add ($h,$h,$t0,"ror#$Sigma0[0]");'. # h+=Sigma0(a)
+ '&eor ($t3,$t3,$b)', # Maj(a,b,c)
+ '$j++; unshift(@V,pop(@V)); ($t2,$t3)=($t3,$t2);'
+ )
+}
+
+$code.=<<___;
+#if __ARM_MAX_ARCH__>=7
+.arch armv7-a
+.fpu neon
+
+.type sha256_block_data_order_neon,%function
+.align 4
+sha256_block_data_order_neon:
+.LNEON:
+ stmdb sp!,{r4-r12,lr}
+
+ mov $t2,sp
+ sub sp,sp,#16*4+16 @ alloca
+ sub $Ktbl,r3,#256+32 @ K256
+ bic sp,sp,#15 @ align for 128-bit stores
+
+ vld1.8 {@X[0]},[$inp]!
+ vld1.8 {@X[1]},[$inp]!
+ vld1.8 {@X[2]},[$inp]!
+ vld1.8 {@X[3]},[$inp]!
+ vld1.32 {$T0},[$Ktbl,:128]!
+ vld1.32 {$T1},[$Ktbl,:128]!
+ vld1.32 {$T2},[$Ktbl,:128]!
+ vld1.32 {$T3},[$Ktbl,:128]!
+ vrev32.8 @X[0],@X[0] @ yes, even on
+ str $ctx,[sp,#64]
+ vrev32.8 @X[1],@X[1] @ big-endian
+ str $inp,[sp,#68]
+ mov $Xfer,sp
+ vrev32.8 @X[2],@X[2]
+ str $len,[sp,#72]
+ vrev32.8 @X[3],@X[3]
+ str $t2,[sp,#76] @ save original sp
+ vadd.i32 $T0,$T0,@X[0]
+ vadd.i32 $T1,$T1,@X[1]
+ vst1.32 {$T0},[$Xfer,:128]!
+ vadd.i32 $T2,$T2,@X[2]
+ vst1.32 {$T1},[$Xfer,:128]!
+ vadd.i32 $T3,$T3,@X[3]
+ vst1.32 {$T2},[$Xfer,:128]!
+ vst1.32 {$T3},[$Xfer,:128]!
+
+ ldmia $ctx,{$A-$H}
+ sub $Xfer,$Xfer,#64
+ ldr $t1,[sp,#0]
+ eor $t2,$t2,$t2
+ eor $t3,$B,$C
+ b .L_00_48
+
+.align 4
+.L_00_48:
+___
+ &Xupdate(\&body_00_15);
+ &Xupdate(\&body_00_15);
+ &Xupdate(\&body_00_15);
+ &Xupdate(\&body_00_15);
+$code.=<<___;
+ teq $t1,#0 @ check for K256 terminator
+ ldr $t1,[sp,#0]
+ sub $Xfer,$Xfer,#64
+ bne .L_00_48
+
+ ldr $inp,[sp,#68]
+ ldr $t0,[sp,#72]
+ sub $Ktbl,$Ktbl,#256 @ rewind $Ktbl
+ teq $inp,$t0
+ subeq $inp,$inp,#64 @ avoid SEGV
+ vld1.8 {@X[0]},[$inp]! @ load next input block
+ vld1.8 {@X[1]},[$inp]!
+ vld1.8 {@X[2]},[$inp]!
+ vld1.8 {@X[3]},[$inp]!
+ strne $inp,[sp,#68]
+ mov $Xfer,sp
+___
+ &Xpreload(\&body_00_15);
+ &Xpreload(\&body_00_15);
+ &Xpreload(\&body_00_15);
+ &Xpreload(\&body_00_15);
+$code.=<<___;
+ ldr $t0,[$t1,#0]
+ add $A,$A,$t2 @ h+=Maj(a,b,c) from the past
+ ldr $t2,[$t1,#4]
+ ldr $t3,[$t1,#8]
+ ldr $t4,[$t1,#12]
+ add $A,$A,$t0 @ accumulate
+ ldr $t0,[$t1,#16]
+ add $B,$B,$t2
+ ldr $t2,[$t1,#20]
+ add $C,$C,$t3
+ ldr $t3,[$t1,#24]
+ add $D,$D,$t4
+ ldr $t4,[$t1,#28]
+ add $E,$E,$t0
+ str $A,[$t1],#4
+ add $F,$F,$t2
+ str $B,[$t1],#4
+ add $G,$G,$t3
+ str $C,[$t1],#4
+ add $H,$H,$t4
+ str $D,[$t1],#4
+ stmia $t1,{$E-$H}
+
+ movne $Xfer,sp
+ ldrne $t1,[sp,#0]
+ eorne $t2,$t2,$t2
+ ldreq sp,[sp,#76] @ restore original sp
+ eorne $t3,$B,$C
+ bne .L_00_48
+
+ ldmia sp!,{r4-r12,pc}
+.size sha256_block_data_order_neon,.-sha256_block_data_order_neon
+#endif
+___
+}}}
+######################################################################
+# ARMv8 stuff
+#
+{{{
+my ($ABCD,$EFGH,$abcd)=map("q$_",(0..2));
+my @MSG=map("q$_",(8..11));
+my ($W0,$W1,$ABCD_SAVE,$EFGH_SAVE)=map("q$_",(12..15));
+my $Ktbl="r3";
+
+$code.=<<___;
+#if __ARM_MAX_ARCH__>=7
+.type sha256_block_data_order_armv8,%function
+.align 5
+sha256_block_data_order_armv8:
+.LARMv8:
+ vld1.32 {$ABCD,$EFGH},[$ctx]
+ sub $Ktbl,r3,#sha256_block_data_order-K256
+
+.Loop_v8:
+ vld1.8 {@MSG[0]-@MSG[1]},[$inp]!
+ vld1.8 {@MSG[2]-@MSG[3]},[$inp]!
+ vld1.32 {$W0},[$Ktbl]!
+ vrev32.8 @MSG[0],@MSG[0]
+ vrev32.8 @MSG[1],@MSG[1]
+ vrev32.8 @MSG[2],@MSG[2]
+ vrev32.8 @MSG[3],@MSG[3]
+ vmov $ABCD_SAVE,$ABCD @ offload
+ vmov $EFGH_SAVE,$EFGH
+ teq $inp,$len
+___
+for($i=0;$i<12;$i++) {
+$code.=<<___;
+ vld1.32 {$W1},[$Ktbl]!
+ vadd.i32 $W0,$W0,@MSG[0]
+ sha256su0 @MSG[0],@MSG[1]
+ vmov $abcd,$ABCD
+ sha256h $ABCD,$EFGH,$W0
+ sha256h2 $EFGH,$abcd,$W0
+ sha256su1 @MSG[0],@MSG[2],@MSG[3]
+___
+ ($W0,$W1)=($W1,$W0); push(@MSG,shift(@MSG));
+}
+$code.=<<___;
+ vld1.32 {$W1},[$Ktbl]!
+ vadd.i32 $W0,$W0,@MSG[0]
+ vmov $abcd,$ABCD
+ sha256h $ABCD,$EFGH,$W0
+ sha256h2 $EFGH,$abcd,$W0
+
+ vld1.32 {$W0},[$Ktbl]!
+ vadd.i32 $W1,$W1,@MSG[1]
+ vmov $abcd,$ABCD
+ sha256h $ABCD,$EFGH,$W1
+ sha256h2 $EFGH,$abcd,$W1
+
+ vld1.32 {$W1},[$Ktbl]
+ vadd.i32 $W0,$W0,@MSG[2]
+ sub $Ktbl,$Ktbl,#256-16 @ rewind
+ vmov $abcd,$ABCD
+ sha256h $ABCD,$EFGH,$W0
+ sha256h2 $EFGH,$abcd,$W0
+
+ vadd.i32 $W1,$W1,@MSG[3]
+ vmov $abcd,$ABCD
+ sha256h $ABCD,$EFGH,$W1
+ sha256h2 $EFGH,$abcd,$W1
+
+ vadd.i32 $ABCD,$ABCD,$ABCD_SAVE
+ vadd.i32 $EFGH,$EFGH,$EFGH_SAVE
+ bne .Loop_v8
+
+ vst1.32 {$ABCD,$EFGH},[$ctx]
+
+ ret @ bx lr
+.size sha256_block_data_order_armv8,.-sha256_block_data_order_armv8
+#endif
+___
+}}}
+$code.=<<___;
+.asciz "SHA256 block transform for ARMv4/NEON/ARMv8, CRYPTOGAMS by <appro\@openssl.org>"
+.align 2
+#if __ARM_MAX_ARCH__>=7
+.comm OPENSSL_armcap_P,4,4
+#endif
+___
+
+{ my %opcode = (
+ "sha256h" => 0xf3000c40, "sha256h2" => 0xf3100c40,
+ "sha256su0" => 0xf3ba03c0, "sha256su1" => 0xf3200c40 );
+
+ sub unsha256 {
+ my ($mnemonic,$arg)=@_;
+
+ if ($arg =~ m/q([0-9]+)(?:,\s*q([0-9]+))?,\s*q([0-9]+)/o) {
+ my $word = $opcode{$mnemonic}|(($1&7)<<13)|(($1&8)<<19)
+ |(($2&7)<<17)|(($2&8)<<4)
+ |(($3&7)<<1) |(($3&8)<<2);
+ # since ARMv7 instructions are always encoded little-endian.
+ # correct solution is to use .inst directive, but older
+ # assemblers don't implement it:-(
+ sprintf ".byte\t0x%02x,0x%02x,0x%02x,0x%02x\t@ %s %s",
+ $word&0xff,($word>>8)&0xff,
+ ($word>>16)&0xff,($word>>24)&0xff,
+ $mnemonic,$arg;
+ }
+ }
+}
+
+foreach (split($/,$code)) {
+
+ s/\`([^\`]*)\`/eval $1/geo;
+
+ s/\b(sha256\w+)\s+(q.*)/unsha256($1,$2)/geo;
+
+ s/\bret\b/bx lr/go or
+ s/\bbx\s+lr\b/.word\t0xe12fff1e/go; # make it possible to compile with -march=armv4
+
+ print $_,"\n";
+}
+
+close STDOUT; # enforce flush
diff --git a/src/crypto/sha/asm/sha512-586.pl b/src/crypto/sha/asm/sha512-586.pl
new file mode 100644
index 0000000..e96ec00
--- /dev/null
+++ b/src/crypto/sha/asm/sha512-586.pl
@@ -0,0 +1,911 @@
+#!/usr/bin/env perl
+#
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+# project. The module is, however, dual licensed under OpenSSL and
+# CRYPTOGAMS licenses depending on where you obtain it. For further
+# details see http://www.openssl.org/~appro/cryptogams/.
+# ====================================================================
+#
+# SHA512 block transform for x86. September 2007.
+#
+# May 2013.
+#
+# Add SSSE3 code path, 20-25% improvement [over original SSE2 code].
+#
+# Performance in clock cycles per processed byte (less is better):
+#
+# gcc icc x86 asm SIMD(*) x86_64(**)
+# Pentium 100 97 61 - -
+# PIII 75 77 56 - -
+# P4 116 95 82 34.6 30.8
+# AMD K8 54 55 36 20.7 9.57
+# Core2 66 57 40 15.9 9.97
+# Westmere 70 - 38 12.2 9.58
+# Sandy Bridge 58 - 35 11.9 11.2
+# Ivy Bridge 50 - 33 11.5 8.17
+# Haswell 46 - 29 11.3 7.66
+# Bulldozer 121 - 50 14.0 13.5
+# VIA Nano 91 - 52 33 14.7
+# Atom 126 - 68 48(***) 14.7
+# Silvermont 97 - 58 42(***) 17.5
+#
+# (*) whichever best applicable.
+# (**) x86_64 assembler performance is presented for reference
+# purposes, the results are for integer-only code.
+# (***) paddq is increadibly slow on Atom.
+#
+# IALU code-path is optimized for elder Pentiums. On vanilla Pentium
+# performance improvement over compiler generated code reaches ~60%,
+# while on PIII - ~35%. On newer µ-archs improvement varies from 15%
+# to 50%, but it's less important as they are expected to execute SSE2
+# code-path, which is commonly ~2-3x faster [than compiler generated
+# code]. SSE2 code-path is as fast as original sha512-sse2.pl, even
+# though it does not use 128-bit operations. The latter means that
+# SSE2-aware kernel is no longer required to execute the code. Another
+# difference is that new code optimizes amount of writes, but at the
+# cost of increased data cache "footprint" by 1/2KB.
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+push(@INC,"${dir}","${dir}../../perlasm");
+require "x86asm.pl";
+
+&asm_init($ARGV[0],"sha512-586.pl",$ARGV[$#ARGV] eq "386");
+
+$sse2=0;
+for (@ARGV) { $sse2=1 if (/-DOPENSSL_IA32_SSE2/); }
+
+&external_label("OPENSSL_ia32cap_P") if ($sse2);
+
+$Tlo=&DWP(0,"esp"); $Thi=&DWP(4,"esp");
+$Alo=&DWP(8,"esp"); $Ahi=&DWP(8+4,"esp");
+$Blo=&DWP(16,"esp"); $Bhi=&DWP(16+4,"esp");
+$Clo=&DWP(24,"esp"); $Chi=&DWP(24+4,"esp");
+$Dlo=&DWP(32,"esp"); $Dhi=&DWP(32+4,"esp");
+$Elo=&DWP(40,"esp"); $Ehi=&DWP(40+4,"esp");
+$Flo=&DWP(48,"esp"); $Fhi=&DWP(48+4,"esp");
+$Glo=&DWP(56,"esp"); $Ghi=&DWP(56+4,"esp");
+$Hlo=&DWP(64,"esp"); $Hhi=&DWP(64+4,"esp");
+$K512="ebp";
+
+$Asse2=&QWP(0,"esp");
+$Bsse2=&QWP(8,"esp");
+$Csse2=&QWP(16,"esp");
+$Dsse2=&QWP(24,"esp");
+$Esse2=&QWP(32,"esp");
+$Fsse2=&QWP(40,"esp");
+$Gsse2=&QWP(48,"esp");
+$Hsse2=&QWP(56,"esp");
+
+$A="mm0"; # B-D and
+$E="mm4"; # F-H are commonly loaded to respectively mm1-mm3 and
+ # mm5-mm7, but it's done on on-demand basis...
+$BxC="mm2"; # ... except for B^C
+
+sub BODY_00_15_sse2 {
+ my $phase=shift;
+
+ #&movq ("mm5",$Fsse2); # load f
+ #&movq ("mm6",$Gsse2); # load g
+
+ &movq ("mm1",$E); # %mm1 is sliding right
+ &pxor ("mm5","mm6"); # f^=g
+ &psrlq ("mm1",14);
+ &movq ($Esse2,$E); # modulo-scheduled save e
+ &pand ("mm5",$E); # f&=e
+ &psllq ($E,23); # $E is sliding left
+ &movq ($A,"mm3") if ($phase<2);
+ &movq (&QWP(8*9,"esp"),"mm7") # save X[i]
+ &movq ("mm3","mm1"); # %mm3 is T1
+ &psrlq ("mm1",4);
+ &pxor ("mm5","mm6"); # Ch(e,f,g)
+ &pxor ("mm3",$E);
+ &psllq ($E,23);
+ &pxor ("mm3","mm1");
+ &movq ($Asse2,$A); # modulo-scheduled save a
+ &paddq ("mm7","mm5"); # X[i]+=Ch(e,f,g)
+ &pxor ("mm3",$E);
+ &psrlq ("mm1",23);
+ &paddq ("mm7",$Hsse2); # X[i]+=h
+ &pxor ("mm3","mm1");
+ &psllq ($E,4);
+ &paddq ("mm7",QWP(0,$K512)); # X[i]+=K512[i]
+ &pxor ("mm3",$E); # T1=Sigma1_512(e)
+
+ &movq ($E,$Dsse2); # e = load d, e in next round
+ &paddq ("mm3","mm7"); # T1+=X[i]
+ &movq ("mm5",$A); # %mm5 is sliding right
+ &psrlq ("mm5",28);
+ &paddq ($E,"mm3"); # d += T1
+ &movq ("mm6",$A); # %mm6 is sliding left
+ &movq ("mm7","mm5");
+ &psllq ("mm6",25);
+ &movq ("mm1",$Bsse2); # load b
+ &psrlq ("mm5",6);
+ &pxor ("mm7","mm6");
+ &sub ("esp",8);
+ &psllq ("mm6",5);
+ &pxor ("mm7","mm5");
+ &pxor ($A,"mm1"); # a^b, b^c in next round
+ &psrlq ("mm5",5);
+ &pxor ("mm7","mm6");
+ &pand ($BxC,$A); # (b^c)&(a^b)
+ &psllq ("mm6",6);
+ &pxor ("mm7","mm5");
+ &pxor ($BxC,"mm1"); # [h=]Maj(a,b,c)
+ &pxor ("mm6","mm7"); # Sigma0_512(a)
+ &movq ("mm7",&QWP(8*(9+16-1),"esp")) if ($phase!=0); # pre-fetch
+ &movq ("mm5",$Fsse2) if ($phase==0); # load f
+
+ if ($phase>1) {
+ &paddq ($BxC,"mm6"); # h+=Sigma0(a)
+ &add ($K512,8);
+ #&paddq ($BxC,"mm3"); # h+=T1
+
+ ($A,$BxC) = ($BxC,$A); # rotate registers
+ } else {
+ &paddq ("mm3",$BxC); # T1+=Maj(a,b,c)
+ &movq ($BxC,$A);
+ &add ($K512,8);
+ &paddq ("mm3","mm6"); # T1+=Sigma0(a)
+ &movq ("mm6",$Gsse2) if ($phase==0); # load g
+ #&movq ($A,"mm3"); # h=T1
+ }
+}
+
+sub BODY_00_15_x86 {
+ #define 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 ("ecx",$Elo);
+ &mov ("edx",$Ehi);
+ &mov ("esi","ecx");
+
+ &shr ("ecx",9); # lo>>9
+ &mov ("edi","edx");
+ &shr ("edx",9); # hi>>9
+ &mov ("ebx","ecx");
+ &shl ("esi",14); # lo<<14
+ &mov ("eax","edx");
+ &shl ("edi",14); # hi<<14
+ &xor ("ebx","esi");
+
+ &shr ("ecx",14-9); # lo>>14
+ &xor ("eax","edi");
+ &shr ("edx",14-9); # hi>>14
+ &xor ("eax","ecx");
+ &shl ("esi",18-14); # lo<<18
+ &xor ("ebx","edx");
+ &shl ("edi",18-14); # hi<<18
+ &xor ("ebx","esi");
+
+ &shr ("ecx",18-14); # lo>>18
+ &xor ("eax","edi");
+ &shr ("edx",18-14); # hi>>18
+ &xor ("eax","ecx");
+ &shl ("esi",23-18); # lo<<23
+ &xor ("ebx","edx");
+ &shl ("edi",23-18); # hi<<23
+ &xor ("eax","esi");
+ &xor ("ebx","edi"); # T1 = Sigma1(e)
+
+ &mov ("ecx",$Flo);
+ &mov ("edx",$Fhi);
+ &mov ("esi",$Glo);
+ &mov ("edi",$Ghi);
+ &add ("eax",$Hlo);
+ &adc ("ebx",$Hhi); # T1 += h
+ &xor ("ecx","esi");
+ &xor ("edx","edi");
+ &and ("ecx",$Elo);
+ &and ("edx",$Ehi);
+ &add ("eax",&DWP(8*(9+15)+0,"esp"));
+ &adc ("ebx",&DWP(8*(9+15)+4,"esp")); # T1 += X[0]
+ &xor ("ecx","esi");
+ &xor ("edx","edi"); # Ch(e,f,g) = (f^g)&e)^g
+
+ &mov ("esi",&DWP(0,$K512));
+ &mov ("edi",&DWP(4,$K512)); # K[i]
+ &add ("eax","ecx");
+ &adc ("ebx","edx"); # T1 += Ch(e,f,g)
+ &mov ("ecx",$Dlo);
+ &mov ("edx",$Dhi);
+ &add ("eax","esi");
+ &adc ("ebx","edi"); # T1 += K[i]
+ &mov ($Tlo,"eax");
+ &mov ($Thi,"ebx"); # put T1 away
+ &add ("eax","ecx");
+ &adc ("ebx","edx"); # d += T1
+
+ #define 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 ("ecx",$Alo);
+ &mov ("edx",$Ahi);
+ &mov ($Dlo,"eax");
+ &mov ($Dhi,"ebx");
+ &mov ("esi","ecx");
+
+ &shr ("ecx",2); # lo>>2
+ &mov ("edi","edx");
+ &shr ("edx",2); # hi>>2
+ &mov ("ebx","ecx");
+ &shl ("esi",4); # lo<<4
+ &mov ("eax","edx");
+ &shl ("edi",4); # hi<<4
+ &xor ("ebx","esi");
+
+ &shr ("ecx",7-2); # lo>>7
+ &xor ("eax","edi");
+ &shr ("edx",7-2); # hi>>7
+ &xor ("ebx","ecx");
+ &shl ("esi",25-4); # lo<<25
+ &xor ("eax","edx");
+ &shl ("edi",25-4); # hi<<25
+ &xor ("eax","esi");
+
+ &shr ("ecx",28-7); # lo>>28
+ &xor ("ebx","edi");
+ &shr ("edx",28-7); # hi>>28
+ &xor ("eax","ecx");
+ &shl ("esi",30-25); # lo<<30
+ &xor ("ebx","edx");
+ &shl ("edi",30-25); # hi<<30
+ &xor ("eax","esi");
+ &xor ("ebx","edi"); # Sigma0(a)
+
+ &mov ("ecx",$Alo);
+ &mov ("edx",$Ahi);
+ &mov ("esi",$Blo);
+ &mov ("edi",$Bhi);
+ &add ("eax",$Tlo);
+ &adc ("ebx",$Thi); # T1 = Sigma0(a)+T1
+ &or ("ecx","esi");
+ &or ("edx","edi");
+ &and ("ecx",$Clo);
+ &and ("edx",$Chi);
+ &and ("esi",$Alo);
+ &and ("edi",$Ahi);
+ &or ("ecx","esi");
+ &or ("edx","edi"); # Maj(a,b,c) = ((a|b)&c)|(a&b)
+
+ &add ("eax","ecx");
+ &adc ("ebx","edx"); # T1 += Maj(a,b,c)
+ &mov ($Tlo,"eax");
+ &mov ($Thi,"ebx");
+
+ &mov (&LB("edx"),&BP(0,$K512)); # pre-fetch LSB of *K
+ &sub ("esp",8);
+ &lea ($K512,&DWP(8,$K512)); # K++
+}
+
+
+&function_begin("sha512_block_data_order");
+ &mov ("esi",wparam(0)); # ctx
+ &mov ("edi",wparam(1)); # inp
+ &mov ("eax",wparam(2)); # num
+ &mov ("ebx","esp"); # saved sp
+
+ &call (&label("pic_point")); # make it PIC!
+&set_label("pic_point");
+ &blindpop($K512);
+ &lea ($K512,&DWP(&label("K512")."-".&label("pic_point"),$K512));
+
+ &sub ("esp",16);
+ &and ("esp",-64);
+
+ &shl ("eax",7);
+ &add ("eax","edi");
+ &mov (&DWP(0,"esp"),"esi"); # ctx
+ &mov (&DWP(4,"esp"),"edi"); # inp
+ &mov (&DWP(8,"esp"),"eax"); # inp+num*128
+ &mov (&DWP(12,"esp"),"ebx"); # saved sp
+
+if ($sse2) {
+ &picmeup("edx","OPENSSL_ia32cap_P",$K512,&label("K512"));
+ &mov ("ecx",&DWP(0,"edx"));
+ &test ("ecx",1<<26);
+ &jz (&label("loop_x86"));
+
+ &mov ("edx",&DWP(4,"edx"));
+
+ # load ctx->h[0-7]
+ &movq ($A,&QWP(0,"esi"));
+ &and ("ecx",1<<24); # XMM registers availability
+ &movq ("mm1",&QWP(8,"esi"));
+ &and ("edx",1<<9); # SSSE3 bit
+ &movq ($BxC,&QWP(16,"esi"));
+ &or ("ecx","edx");
+ &movq ("mm3",&QWP(24,"esi"));
+ &movq ($E,&QWP(32,"esi"));
+ &movq ("mm5",&QWP(40,"esi"));
+ &movq ("mm6",&QWP(48,"esi"));
+ &movq ("mm7",&QWP(56,"esi"));
+ &cmp ("ecx",1<<24|1<<9);
+ &je (&label("SSSE3"));
+ &sub ("esp",8*10);
+ &jmp (&label("loop_sse2"));
+
+&set_label("loop_sse2",16);
+ #&movq ($Asse2,$A);
+ &movq ($Bsse2,"mm1");
+ &movq ($Csse2,$BxC);
+ &movq ($Dsse2,"mm3");
+ #&movq ($Esse2,$E);
+ &movq ($Fsse2,"mm5");
+ &movq ($Gsse2,"mm6");
+ &pxor ($BxC,"mm1"); # magic
+ &movq ($Hsse2,"mm7");
+ &movq ("mm3",$A); # magic
+
+ &mov ("eax",&DWP(0,"edi"));
+ &mov ("ebx",&DWP(4,"edi"));
+ &add ("edi",8);
+ &mov ("edx",15); # counter
+ &bswap ("eax");
+ &bswap ("ebx");
+ &jmp (&label("00_14_sse2"));
+
+&set_label("00_14_sse2",16);
+ &movd ("mm1","eax");
+ &mov ("eax",&DWP(0,"edi"));
+ &movd ("mm7","ebx");
+ &mov ("ebx",&DWP(4,"edi"));
+ &add ("edi",8);
+ &bswap ("eax");
+ &bswap ("ebx");
+ &punpckldq("mm7","mm1");
+
+ &BODY_00_15_sse2();
+
+ &dec ("edx");
+ &jnz (&label("00_14_sse2"));
+
+ &movd ("mm1","eax");
+ &movd ("mm7","ebx");
+ &punpckldq("mm7","mm1");
+
+ &BODY_00_15_sse2(1);
+
+ &pxor ($A,$A); # A is in %mm3
+ &mov ("edx",32); # counter
+ &jmp (&label("16_79_sse2"));
+
+&set_label("16_79_sse2",16);
+ for ($j=0;$j<2;$j++) { # 2x unroll
+ #&movq ("mm7",&QWP(8*(9+16-1),"esp")); # prefetched in BODY_00_15
+ &movq ("mm5",&QWP(8*(9+16-14),"esp"));
+ &movq ("mm1","mm7");
+ &psrlq ("mm7",1);
+ &movq ("mm6","mm5");
+ &psrlq ("mm5",6);
+ &psllq ("mm1",56);
+ &paddq ($A,"mm3"); # from BODY_00_15
+ &movq ("mm3","mm7");
+ &psrlq ("mm7",7-1);
+ &pxor ("mm3","mm1");
+ &psllq ("mm1",63-56);
+ &pxor ("mm3","mm7");
+ &psrlq ("mm7",8-7);
+ &pxor ("mm3","mm1");
+ &movq ("mm1","mm5");
+ &psrlq ("mm5",19-6);
+ &pxor ("mm7","mm3"); # sigma0
+
+ &psllq ("mm6",3);
+ &pxor ("mm1","mm5");
+ &paddq ("mm7",&QWP(8*(9+16),"esp"));
+ &pxor ("mm1","mm6");
+ &psrlq ("mm5",61-19);
+ &paddq ("mm7",&QWP(8*(9+16-9),"esp"));
+ &pxor ("mm1","mm5");
+ &psllq ("mm6",45-3);
+ &movq ("mm5",$Fsse2); # load f
+ &pxor ("mm1","mm6"); # sigma1
+ &movq ("mm6",$Gsse2); # load g
+
+ &paddq ("mm7","mm1"); # X[i]
+ #&movq (&QWP(8*9,"esp"),"mm7"); # moved to BODY_00_15
+
+ &BODY_00_15_sse2(2);
+ }
+ &dec ("edx");
+ &jnz (&label("16_79_sse2"));
+
+ #&movq ($A,$Asse2);
+ &paddq ($A,"mm3"); # from BODY_00_15
+ &movq ("mm1",$Bsse2);
+ #&movq ($BxC,$Csse2);
+ &movq ("mm3",$Dsse2);
+ #&movq ($E,$Esse2);
+ &movq ("mm5",$Fsse2);
+ &movq ("mm6",$Gsse2);
+ &movq ("mm7",$Hsse2);
+
+ &pxor ($BxC,"mm1"); # de-magic
+ &paddq ($A,&QWP(0,"esi"));
+ &paddq ("mm1",&QWP(8,"esi"));
+ &paddq ($BxC,&QWP(16,"esi"));
+ &paddq ("mm3",&QWP(24,"esi"));
+ &paddq ($E,&QWP(32,"esi"));
+ &paddq ("mm5",&QWP(40,"esi"));
+ &paddq ("mm6",&QWP(48,"esi"));
+ &paddq ("mm7",&QWP(56,"esi"));
+
+ &mov ("eax",8*80);
+ &movq (&QWP(0,"esi"),$A);
+ &movq (&QWP(8,"esi"),"mm1");
+ &movq (&QWP(16,"esi"),$BxC);
+ &movq (&QWP(24,"esi"),"mm3");
+ &movq (&QWP(32,"esi"),$E);
+ &movq (&QWP(40,"esi"),"mm5");
+ &movq (&QWP(48,"esi"),"mm6");
+ &movq (&QWP(56,"esi"),"mm7");
+
+ &lea ("esp",&DWP(0,"esp","eax")); # destroy frame
+ &sub ($K512,"eax"); # rewind K
+
+ &cmp ("edi",&DWP(8*10+8,"esp")); # are we done yet?
+ &jb (&label("loop_sse2"));
+
+ &mov ("esp",&DWP(8*10+12,"esp")); # restore sp
+ &emms ();
+&function_end_A();
+
+&set_label("SSSE3",32);
+{ my ($cnt,$frame)=("ecx","edx");
+ my @X=map("xmm$_",(0..7));
+ my $j;
+ my $i=0;
+
+ &lea ($frame,&DWP(-64,"esp"));
+ &sub ("esp",256);
+
+ # fixed stack frame layout
+ #
+ # +0 A B C D E F G H # backing store
+ # +64 X[0]+K[i] .. X[15]+K[i] # XMM->MM xfer area
+ # +192 # XMM off-load ring buffer
+ # +256 # saved parameters
+
+ &movdqa (@X[1],&QWP(80*8,$K512)); # byte swap mask
+ &movdqu (@X[0],&QWP(0,"edi"));
+ &pshufb (@X[0],@X[1]);
+ for ($j=0;$j<8;$j++) {
+ &movdqa (&QWP(16*(($j-1)%4),$frame),@X[3]) if ($j>4); # off-load
+ &movdqa (@X[3],&QWP(16*($j%8),$K512));
+ &movdqa (@X[2],@X[1]) if ($j<7); # perpetuate byte swap mask
+ &movdqu (@X[1],&QWP(16*($j+1),"edi")) if ($j<7); # next input
+ &movdqa (@X[1],&QWP(16*(($j+1)%4),$frame)) if ($j==7);# restore @X[0]
+ &paddq (@X[3],@X[0]);
+ &pshufb (@X[1],@X[2]) if ($j<7);
+ &movdqa (&QWP(16*($j%8)-128,$frame),@X[3]); # xfer X[i]+K[i]
+
+ push(@X,shift(@X)); # rotate(@X)
+ }
+ #&jmp (&label("loop_ssse3"));
+ &nop ();
+
+&set_label("loop_ssse3",32);
+ &movdqa (@X[2],&QWP(16*(($j+1)%4),$frame)); # pre-restore @X[1]
+ &movdqa (&QWP(16*(($j-1)%4),$frame),@X[3]); # off-load @X[3]
+ &lea ($K512,&DWP(16*8,$K512));
+
+ #&movq ($Asse2,$A); # off-load A-H
+ &movq ($Bsse2,"mm1");
+ &mov ("ebx","edi");
+ &movq ($Csse2,$BxC);
+ &lea ("edi",&DWP(128,"edi")); # advance input
+ &movq ($Dsse2,"mm3");
+ &cmp ("edi","eax");
+ #&movq ($Esse2,$E);
+ &movq ($Fsse2,"mm5");
+ &cmovb ("ebx","edi");
+ &movq ($Gsse2,"mm6");
+ &mov ("ecx",4); # loop counter
+ &pxor ($BxC,"mm1"); # magic
+ &movq ($Hsse2,"mm7");
+ &pxor ("mm3","mm3"); # magic
+
+ &jmp (&label("00_47_ssse3"));
+
+sub BODY_00_15_ssse3 { # "phase-less" copy of BODY_00_15_sse2
+ (
+ '&movq ("mm1",$E)', # %mm1 is sliding right
+ '&movq ("mm7",&QWP(((-8*$i)%128)-128,$frame))',# X[i]+K[i]
+ '&pxor ("mm5","mm6")', # f^=g
+ '&psrlq ("mm1",14)',
+ '&movq (&QWP(8*($i+4)%64,"esp"),$E)', # modulo-scheduled save e
+ '&pand ("mm5",$E)', # f&=e
+ '&psllq ($E,23)', # $E is sliding left
+ '&paddq ($A,"mm3")', # [h+=Maj(a,b,c)]
+ '&movq ("mm3","mm1")', # %mm3 is T1
+ '&psrlq("mm1",4)',
+ '&pxor ("mm5","mm6")', # Ch(e,f,g)
+ '&pxor ("mm3",$E)',
+ '&psllq($E,23)',
+ '&pxor ("mm3","mm1")',
+ '&movq (&QWP(8*$i%64,"esp"),$A)', # modulo-scheduled save a
+ '&paddq("mm7","mm5")', # X[i]+=Ch(e,f,g)
+ '&pxor ("mm3",$E)',
+ '&psrlq("mm1",23)',
+ '&paddq("mm7",&QWP(8*($i+7)%64,"esp"))', # X[i]+=h
+ '&pxor ("mm3","mm1")',
+ '&psllq($E,4)',
+ '&pxor ("mm3",$E)', # T1=Sigma1_512(e)
+
+ '&movq ($E,&QWP(8*($i+3)%64,"esp"))', # e = load d, e in next round
+ '&paddq ("mm3","mm7")', # T1+=X[i]
+ '&movq ("mm5",$A)', # %mm5 is sliding right
+ '&psrlq("mm5",28)',
+ '&paddq ($E,"mm3")', # d += T1
+ '&movq ("mm6",$A)', # %mm6 is sliding left
+ '&movq ("mm7","mm5")',
+ '&psllq("mm6",25)',
+ '&movq ("mm1",&QWP(8*($i+1)%64,"esp"))', # load b
+ '&psrlq("mm5",6)',
+ '&pxor ("mm7","mm6")',
+ '&psllq("mm6",5)',
+ '&pxor ("mm7","mm5")',
+ '&pxor ($A,"mm1")', # a^b, b^c in next round
+ '&psrlq("mm5",5)',
+ '&pxor ("mm7","mm6")',
+ '&pand ($BxC,$A)', # (b^c)&(a^b)
+ '&psllq("mm6",6)',
+ '&pxor ("mm7","mm5")',
+ '&pxor ($BxC,"mm1")', # [h=]Maj(a,b,c)
+ '&pxor ("mm6","mm7")', # Sigma0_512(a)
+ '&movq ("mm5",&QWP(8*($i+5-1)%64,"esp"))', # pre-load f
+ '&paddq ($BxC,"mm6")', # h+=Sigma0(a)
+ '&movq ("mm6",&QWP(8*($i+6-1)%64,"esp"))', # pre-load g
+
+ '($A,$BxC) = ($BxC,$A); $i--;'
+ );
+}
+
+&set_label("00_47_ssse3",32);
+
+ for(;$j<16;$j++) {
+ my ($t0,$t2,$t1)=@X[2..4];
+ my @insns = (&BODY_00_15_ssse3(),&BODY_00_15_ssse3());
+
+ &movdqa ($t2,@X[5]);
+ &movdqa (@X[1],$t0); # restore @X[1]
+ &palignr ($t0,@X[0],8); # X[1..2]
+ &movdqa (&QWP(16*($j%4),$frame),@X[4]); # off-load @X[4]
+ &palignr ($t2,@X[4],8); # X[9..10]
+
+ &movdqa ($t1,$t0);
+ &psrlq ($t0,7);
+ &paddq (@X[0],$t2); # X[0..1] += X[9..10]
+ &movdqa ($t2,$t1);
+ &psrlq ($t1,1);
+ &psllq ($t2,64-8);
+ &pxor ($t0,$t1);
+ &psrlq ($t1,8-1);
+ &pxor ($t0,$t2);
+ &psllq ($t2,8-1);
+ &pxor ($t0,$t1);
+ &movdqa ($t1,@X[7]);
+ &pxor ($t0,$t2); # sigma0(X[1..2])
+ &movdqa ($t2,@X[7]);
+ &psrlq ($t1,6);
+ &paddq (@X[0],$t0); # X[0..1] += sigma0(X[1..2])
+
+ &movdqa ($t0,@X[7]);
+ &psrlq ($t2,19);
+ &psllq ($t0,64-61);
+ &pxor ($t1,$t2);
+ &psrlq ($t2,61-19);
+ &pxor ($t1,$t0);
+ &psllq ($t0,61-19);
+ &pxor ($t1,$t2);
+ &movdqa ($t2,&QWP(16*(($j+2)%4),$frame));# pre-restore @X[1]
+ &pxor ($t1,$t0); # sigma0(X[1..2])
+ &movdqa ($t0,&QWP(16*($j%8),$K512));
+ eval(shift(@insns));
+ &paddq (@X[0],$t1); # X[0..1] += sigma0(X[14..15])
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &paddq ($t0,@X[0]);
+ foreach(@insns) { eval; }
+ &movdqa (&QWP(16*($j%8)-128,$frame),$t0);# xfer X[i]+K[i]
+
+ push(@X,shift(@X)); # rotate(@X)
+ }
+ &lea ($K512,&DWP(16*8,$K512));
+ &dec ("ecx");
+ &jnz (&label("00_47_ssse3"));
+
+ &movdqa (@X[1],&QWP(0,$K512)); # byte swap mask
+ &lea ($K512,&DWP(-80*8,$K512)); # rewind
+ &movdqu (@X[0],&QWP(0,"ebx"));
+ &pshufb (@X[0],@X[1]);
+
+ for ($j=0;$j<8;$j++) { # load next or same block
+ my @insns = (&BODY_00_15_ssse3(),&BODY_00_15_ssse3());
+
+ &movdqa (&QWP(16*(($j-1)%4),$frame),@X[3]) if ($j>4); # off-load
+ &movdqa (@X[3],&QWP(16*($j%8),$K512));
+ &movdqa (@X[2],@X[1]) if ($j<7); # perpetuate byte swap mask
+ &movdqu (@X[1],&QWP(16*($j+1),"ebx")) if ($j<7); # next input
+ &movdqa (@X[1],&QWP(16*(($j+1)%4),$frame)) if ($j==7);# restore @X[0]
+ &paddq (@X[3],@X[0]);
+ &pshufb (@X[1],@X[2]) if ($j<7);
+ foreach(@insns) { eval; }
+ &movdqa (&QWP(16*($j%8)-128,$frame),@X[3]);# xfer X[i]+K[i]
+
+ push(@X,shift(@X)); # rotate(@X)
+ }
+
+ #&movq ($A,$Asse2); # load A-H
+ &movq ("mm1",$Bsse2);
+ &paddq ($A,"mm3"); # from BODY_00_15
+ #&movq ($BxC,$Csse2);
+ &movq ("mm3",$Dsse2);
+ #&movq ($E,$Esse2);
+ #&movq ("mm5",$Fsse2);
+ #&movq ("mm6",$Gsse2);
+ &movq ("mm7",$Hsse2);
+
+ &pxor ($BxC,"mm1"); # de-magic
+ &paddq ($A,&QWP(0,"esi"));
+ &paddq ("mm1",&QWP(8,"esi"));
+ &paddq ($BxC,&QWP(16,"esi"));
+ &paddq ("mm3",&QWP(24,"esi"));
+ &paddq ($E,&QWP(32,"esi"));
+ &paddq ("mm5",&QWP(40,"esi"));
+ &paddq ("mm6",&QWP(48,"esi"));
+ &paddq ("mm7",&QWP(56,"esi"));
+
+ &movq (&QWP(0,"esi"),$A);
+ &movq (&QWP(8,"esi"),"mm1");
+ &movq (&QWP(16,"esi"),$BxC);
+ &movq (&QWP(24,"esi"),"mm3");
+ &movq (&QWP(32,"esi"),$E);
+ &movq (&QWP(40,"esi"),"mm5");
+ &movq (&QWP(48,"esi"),"mm6");
+ &movq (&QWP(56,"esi"),"mm7");
+
+ &cmp ("edi","eax") # are we done yet?
+ &jb (&label("loop_ssse3"));
+
+ &mov ("esp",&DWP(64+12,$frame)); # restore sp
+ &emms ();
+}
+&function_end_A();
+}
+&set_label("loop_x86",16);
+ # copy input block to stack reversing byte and qword order
+ for ($i=0;$i<8;$i++) {
+ &mov ("eax",&DWP($i*16+0,"edi"));
+ &mov ("ebx",&DWP($i*16+4,"edi"));
+ &mov ("ecx",&DWP($i*16+8,"edi"));
+ &mov ("edx",&DWP($i*16+12,"edi"));
+ &bswap ("eax");
+ &bswap ("ebx");
+ &bswap ("ecx");
+ &bswap ("edx");
+ &push ("eax");
+ &push ("ebx");
+ &push ("ecx");
+ &push ("edx");
+ }
+ &add ("edi",128);
+ &sub ("esp",9*8); # place for T,A,B,C,D,E,F,G,H
+ &mov (&DWP(8*(9+16)+4,"esp"),"edi");
+
+ # copy ctx->h[0-7] to A,B,C,D,E,F,G,H on stack
+ &lea ("edi",&DWP(8,"esp"));
+ &mov ("ecx",16);
+ &data_word(0xA5F3F689); # rep movsd
+
+&set_label("00_15_x86",16);
+ &BODY_00_15_x86();
+
+ &cmp (&LB("edx"),0x94);
+ &jne (&label("00_15_x86"));
+
+&set_label("16_79_x86",16);
+ #define 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 ("ecx",&DWP(8*(9+15+16-1)+0,"esp"));
+ &mov ("edx",&DWP(8*(9+15+16-1)+4,"esp"));
+ &mov ("esi","ecx");
+
+ &shr ("ecx",1); # lo>>1
+ &mov ("edi","edx");
+ &shr ("edx",1); # hi>>1
+ &mov ("eax","ecx");
+ &shl ("esi",24); # lo<<24
+ &mov ("ebx","edx");
+ &shl ("edi",24); # hi<<24
+ &xor ("ebx","esi");
+
+ &shr ("ecx",7-1); # lo>>7
+ &xor ("eax","edi");
+ &shr ("edx",7-1); # hi>>7
+ &xor ("eax","ecx");
+ &shl ("esi",31-24); # lo<<31
+ &xor ("ebx","edx");
+ &shl ("edi",25-24); # hi<<25
+ &xor ("ebx","esi");
+
+ &shr ("ecx",8-7); # lo>>8
+ &xor ("eax","edi");
+ &shr ("edx",8-7); # hi>>8
+ &xor ("eax","ecx");
+ &shl ("edi",31-25); # hi<<31
+ &xor ("ebx","edx");
+ &xor ("eax","edi"); # T1 = sigma0(X[-15])
+
+ &mov (&DWP(0,"esp"),"eax");
+ &mov (&DWP(4,"esp"),"ebx"); # put T1 away
+
+ #define 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 ("ecx",&DWP(8*(9+15+16-14)+0,"esp"));
+ &mov ("edx",&DWP(8*(9+15+16-14)+4,"esp"));
+ &mov ("esi","ecx");
+
+ &shr ("ecx",6); # lo>>6
+ &mov ("edi","edx");
+ &shr ("edx",6); # hi>>6
+ &mov ("eax","ecx");
+ &shl ("esi",3); # lo<<3
+ &mov ("ebx","edx");
+ &shl ("edi",3); # hi<<3
+ &xor ("eax","esi");
+
+ &shr ("ecx",19-6); # lo>>19
+ &xor ("ebx","edi");
+ &shr ("edx",19-6); # hi>>19
+ &xor ("eax","ecx");
+ &shl ("esi",13-3); # lo<<13
+ &xor ("ebx","edx");
+ &shl ("edi",13-3); # hi<<13
+ &xor ("ebx","esi");
+
+ &shr ("ecx",29-19); # lo>>29
+ &xor ("eax","edi");
+ &shr ("edx",29-19); # hi>>29
+ &xor ("ebx","ecx");
+ &shl ("edi",26-13); # hi<<26
+ &xor ("eax","edx");
+ &xor ("eax","edi"); # sigma1(X[-2])
+
+ &mov ("ecx",&DWP(8*(9+15+16)+0,"esp"));
+ &mov ("edx",&DWP(8*(9+15+16)+4,"esp"));
+ &add ("eax",&DWP(0,"esp"));
+ &adc ("ebx",&DWP(4,"esp")); # T1 = sigma1(X[-2])+T1
+ &mov ("esi",&DWP(8*(9+15+16-9)+0,"esp"));
+ &mov ("edi",&DWP(8*(9+15+16-9)+4,"esp"));
+ &add ("eax","ecx");
+ &adc ("ebx","edx"); # T1 += X[-16]
+ &add ("eax","esi");
+ &adc ("ebx","edi"); # T1 += X[-7]
+ &mov (&DWP(8*(9+15)+0,"esp"),"eax");
+ &mov (&DWP(8*(9+15)+4,"esp"),"ebx"); # save X[0]
+
+ &BODY_00_15_x86();
+
+ &cmp (&LB("edx"),0x17);
+ &jne (&label("16_79_x86"));
+
+ &mov ("esi",&DWP(8*(9+16+80)+0,"esp"));# ctx
+ &mov ("edi",&DWP(8*(9+16+80)+4,"esp"));# inp
+ for($i=0;$i<4;$i++) {
+ &mov ("eax",&DWP($i*16+0,"esi"));
+ &mov ("ebx",&DWP($i*16+4,"esi"));
+ &mov ("ecx",&DWP($i*16+8,"esi"));
+ &mov ("edx",&DWP($i*16+12,"esi"));
+ &add ("eax",&DWP(8+($i*16)+0,"esp"));
+ &adc ("ebx",&DWP(8+($i*16)+4,"esp"));
+ &mov (&DWP($i*16+0,"esi"),"eax");
+ &mov (&DWP($i*16+4,"esi"),"ebx");
+ &add ("ecx",&DWP(8+($i*16)+8,"esp"));
+ &adc ("edx",&DWP(8+($i*16)+12,"esp"));
+ &mov (&DWP($i*16+8,"esi"),"ecx");
+ &mov (&DWP($i*16+12,"esi"),"edx");
+ }
+ &add ("esp",8*(9+16+80)); # destroy frame
+ &sub ($K512,8*80); # rewind K
+
+ &cmp ("edi",&DWP(8,"esp")); # are we done yet?
+ &jb (&label("loop_x86"));
+
+ &mov ("esp",&DWP(12,"esp")); # restore sp
+&function_end_A();
+
+&set_label("K512",64); # Yes! I keep it in the code segment!
+ &data_word(0xd728ae22,0x428a2f98); # u64
+ &data_word(0x23ef65cd,0x71374491); # u64
+ &data_word(0xec4d3b2f,0xb5c0fbcf); # u64
+ &data_word(0x8189dbbc,0xe9b5dba5); # u64
+ &data_word(0xf348b538,0x3956c25b); # u64
+ &data_word(0xb605d019,0x59f111f1); # u64
+ &data_word(0xaf194f9b,0x923f82a4); # u64
+ &data_word(0xda6d8118,0xab1c5ed5); # u64
+ &data_word(0xa3030242,0xd807aa98); # u64
+ &data_word(0x45706fbe,0x12835b01); # u64
+ &data_word(0x4ee4b28c,0x243185be); # u64
+ &data_word(0xd5ffb4e2,0x550c7dc3); # u64
+ &data_word(0xf27b896f,0x72be5d74); # u64
+ &data_word(0x3b1696b1,0x80deb1fe); # u64
+ &data_word(0x25c71235,0x9bdc06a7); # u64
+ &data_word(0xcf692694,0xc19bf174); # u64
+ &data_word(0x9ef14ad2,0xe49b69c1); # u64
+ &data_word(0x384f25e3,0xefbe4786); # u64
+ &data_word(0x8b8cd5b5,0x0fc19dc6); # u64
+ &data_word(0x77ac9c65,0x240ca1cc); # u64
+ &data_word(0x592b0275,0x2de92c6f); # u64
+ &data_word(0x6ea6e483,0x4a7484aa); # u64
+ &data_word(0xbd41fbd4,0x5cb0a9dc); # u64
+ &data_word(0x831153b5,0x76f988da); # u64
+ &data_word(0xee66dfab,0x983e5152); # u64
+ &data_word(0x2db43210,0xa831c66d); # u64
+ &data_word(0x98fb213f,0xb00327c8); # u64
+ &data_word(0xbeef0ee4,0xbf597fc7); # u64
+ &data_word(0x3da88fc2,0xc6e00bf3); # u64
+ &data_word(0x930aa725,0xd5a79147); # u64
+ &data_word(0xe003826f,0x06ca6351); # u64
+ &data_word(0x0a0e6e70,0x14292967); # u64
+ &data_word(0x46d22ffc,0x27b70a85); # u64
+ &data_word(0x5c26c926,0x2e1b2138); # u64
+ &data_word(0x5ac42aed,0x4d2c6dfc); # u64
+ &data_word(0x9d95b3df,0x53380d13); # u64
+ &data_word(0x8baf63de,0x650a7354); # u64
+ &data_word(0x3c77b2a8,0x766a0abb); # u64
+ &data_word(0x47edaee6,0x81c2c92e); # u64
+ &data_word(0x1482353b,0x92722c85); # u64
+ &data_word(0x4cf10364,0xa2bfe8a1); # u64
+ &data_word(0xbc423001,0xa81a664b); # u64
+ &data_word(0xd0f89791,0xc24b8b70); # u64
+ &data_word(0x0654be30,0xc76c51a3); # u64
+ &data_word(0xd6ef5218,0xd192e819); # u64
+ &data_word(0x5565a910,0xd6990624); # u64
+ &data_word(0x5771202a,0xf40e3585); # u64
+ &data_word(0x32bbd1b8,0x106aa070); # u64
+ &data_word(0xb8d2d0c8,0x19a4c116); # u64
+ &data_word(0x5141ab53,0x1e376c08); # u64
+ &data_word(0xdf8eeb99,0x2748774c); # u64
+ &data_word(0xe19b48a8,0x34b0bcb5); # u64
+ &data_word(0xc5c95a63,0x391c0cb3); # u64
+ &data_word(0xe3418acb,0x4ed8aa4a); # u64
+ &data_word(0x7763e373,0x5b9cca4f); # u64
+ &data_word(0xd6b2b8a3,0x682e6ff3); # u64
+ &data_word(0x5defb2fc,0x748f82ee); # u64
+ &data_word(0x43172f60,0x78a5636f); # u64
+ &data_word(0xa1f0ab72,0x84c87814); # u64
+ &data_word(0x1a6439ec,0x8cc70208); # u64
+ &data_word(0x23631e28,0x90befffa); # u64
+ &data_word(0xde82bde9,0xa4506ceb); # u64
+ &data_word(0xb2c67915,0xbef9a3f7); # u64
+ &data_word(0xe372532b,0xc67178f2); # u64
+ &data_word(0xea26619c,0xca273ece); # u64
+ &data_word(0x21c0c207,0xd186b8c7); # u64
+ &data_word(0xcde0eb1e,0xeada7dd6); # u64
+ &data_word(0xee6ed178,0xf57d4f7f); # u64
+ &data_word(0x72176fba,0x06f067aa); # u64
+ &data_word(0xa2c898a6,0x0a637dc5); # u64
+ &data_word(0xbef90dae,0x113f9804); # u64
+ &data_word(0x131c471b,0x1b710b35); # u64
+ &data_word(0x23047d84,0x28db77f5); # u64
+ &data_word(0x40c72493,0x32caab7b); # u64
+ &data_word(0x15c9bebc,0x3c9ebe0a); # u64
+ &data_word(0x9c100d4c,0x431d67c4); # u64
+ &data_word(0xcb3e42b6,0x4cc5d4be); # u64
+ &data_word(0xfc657e2a,0x597f299c); # u64
+ &data_word(0x3ad6faec,0x5fcb6fab); # u64
+ &data_word(0x4a475817,0x6c44198c); # u64
+
+ &data_word(0x04050607,0x00010203); # byte swap
+ &data_word(0x0c0d0e0f,0x08090a0b); # mask
+&function_end_B("sha512_block_data_order");
+&asciz("SHA512 block transform for x86, CRYPTOGAMS by <appro\@openssl.org>");
+
+&asm_finish();
diff --git a/src/crypto/sha/asm/sha512-armv4.pl b/src/crypto/sha/asm/sha512-armv4.pl
new file mode 100644
index 0000000..fb7dc50
--- /dev/null
+++ b/src/crypto/sha/asm/sha512-armv4.pl
@@ -0,0 +1,609 @@
+#!/usr/bin/env perl
+
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+# project. The module is, however, dual licensed under OpenSSL and
+# CRYPTOGAMS licenses depending on where you obtain it. For further
+# details see http://www.openssl.org/~appro/cryptogams/.
+# ====================================================================
+
+# SHA512 block procedure for ARMv4. September 2007.
+
+# This code is ~4.5 (four and a half) times faster than code generated
+# by gcc 3.4 and it spends ~72 clock cycles per byte [on single-issue
+# Xscale PXA250 core].
+#
+# July 2010.
+#
+# Rescheduling for dual-issue pipeline resulted in 6% improvement on
+# Cortex A8 core and ~40 cycles per processed byte.
+
+# February 2011.
+#
+# Profiler-assisted and platform-specific optimization resulted in 7%
+# improvement on Coxtex A8 core and ~38 cycles per byte.
+
+# March 2011.
+#
+# Add NEON implementation. On Cortex A8 it was measured to process
+# one byte in 23.3 cycles or ~60% faster than integer-only code.
+
+# August 2012.
+#
+# Improve NEON performance by 12% on Snapdragon S4. In absolute
+# terms it's 22.6 cycles per byte, which is disappointing result.
+# Technical writers asserted that 3-way S4 pipeline can sustain
+# multiple NEON instructions per cycle, but dual NEON issue could
+# not be observed, and for NEON-only sequences IPC(*) was found to
+# be limited by 1:-( 0.33 and 0.66 were measured for sequences with
+# ILPs(*) of 1 and 2 respectively. This in turn means that you can
+# even find yourself striving, as I did here, for achieving IPC
+# adequate to one delivered by Cortex A8 [for reference, it's
+# 0.5 for ILP of 1, and 1 for higher ILPs].
+#
+# (*) ILP, instruction-level parallelism, how many instructions
+# *can* execute at the same time. IPC, instructions per cycle,
+# indicates how many instructions actually execute.
+
+# Byte order [in]dependence. =========================================
+#
+# Originally caller was expected to maintain specific *dword* order in
+# h[0-7], namely with most significant dword at *lower* address, which
+# was reflected in below two parameters as 0 and 4. Now caller is
+# expected to maintain native byte order for whole 64-bit values.
+$hi="HI";
+$lo="LO";
+# ====================================================================
+
+while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {}
+open STDOUT,">$output";
+
+$ctx="r0"; # parameter block
+$inp="r1";
+$len="r2";
+
+$Tlo="r3";
+$Thi="r4";
+$Alo="r5";
+$Ahi="r6";
+$Elo="r7";
+$Ehi="r8";
+$t0="r9";
+$t1="r10";
+$t2="r11";
+$t3="r12";
+############ r13 is stack pointer
+$Ktbl="r14";
+############ r15 is program counter
+
+$Aoff=8*0;
+$Boff=8*1;
+$Coff=8*2;
+$Doff=8*3;
+$Eoff=8*4;
+$Foff=8*5;
+$Goff=8*6;
+$Hoff=8*7;
+$Xoff=8*8;
+
+sub BODY_00_15() {
+my $magic = shift;
+$code.=<<___;
+ @ 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 $t0,$Elo,lsr#14
+ str $Tlo,[sp,#$Xoff+0]
+ mov $t1,$Ehi,lsr#14
+ str $Thi,[sp,#$Xoff+4]
+ eor $t0,$t0,$Ehi,lsl#18
+ ldr $t2,[sp,#$Hoff+0] @ h.lo
+ eor $t1,$t1,$Elo,lsl#18
+ ldr $t3,[sp,#$Hoff+4] @ h.hi
+ eor $t0,$t0,$Elo,lsr#18
+ eor $t1,$t1,$Ehi,lsr#18
+ eor $t0,$t0,$Ehi,lsl#14
+ eor $t1,$t1,$Elo,lsl#14
+ eor $t0,$t0,$Ehi,lsr#9
+ eor $t1,$t1,$Elo,lsr#9
+ eor $t0,$t0,$Elo,lsl#23
+ eor $t1,$t1,$Ehi,lsl#23 @ Sigma1(e)
+ adds $Tlo,$Tlo,$t0
+ ldr $t0,[sp,#$Foff+0] @ f.lo
+ adc $Thi,$Thi,$t1 @ T += Sigma1(e)
+ ldr $t1,[sp,#$Foff+4] @ f.hi
+ adds $Tlo,$Tlo,$t2
+ ldr $t2,[sp,#$Goff+0] @ g.lo
+ adc $Thi,$Thi,$t3 @ T += h
+ ldr $t3,[sp,#$Goff+4] @ g.hi
+
+ eor $t0,$t0,$t2
+ str $Elo,[sp,#$Eoff+0]
+ eor $t1,$t1,$t3
+ str $Ehi,[sp,#$Eoff+4]
+ and $t0,$t0,$Elo
+ str $Alo,[sp,#$Aoff+0]
+ and $t1,$t1,$Ehi
+ str $Ahi,[sp,#$Aoff+4]
+ eor $t0,$t0,$t2
+ ldr $t2,[$Ktbl,#$lo] @ K[i].lo
+ eor $t1,$t1,$t3 @ Ch(e,f,g)
+ ldr $t3,[$Ktbl,#$hi] @ K[i].hi
+
+ adds $Tlo,$Tlo,$t0
+ ldr $Elo,[sp,#$Doff+0] @ d.lo
+ adc $Thi,$Thi,$t1 @ T += Ch(e,f,g)
+ ldr $Ehi,[sp,#$Doff+4] @ d.hi
+ adds $Tlo,$Tlo,$t2
+ and $t0,$t2,#0xff
+ adc $Thi,$Thi,$t3 @ T += K[i]
+ adds $Elo,$Elo,$Tlo
+ ldr $t2,[sp,#$Boff+0] @ b.lo
+ adc $Ehi,$Ehi,$Thi @ d += T
+ teq $t0,#$magic
+
+ ldr $t3,[sp,#$Coff+0] @ c.lo
+ orreq $Ktbl,$Ktbl,#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 $t0,$Alo,lsr#28
+ mov $t1,$Ahi,lsr#28
+ eor $t0,$t0,$Ahi,lsl#4
+ eor $t1,$t1,$Alo,lsl#4
+ eor $t0,$t0,$Ahi,lsr#2
+ eor $t1,$t1,$Alo,lsr#2
+ eor $t0,$t0,$Alo,lsl#30
+ eor $t1,$t1,$Ahi,lsl#30
+ eor $t0,$t0,$Ahi,lsr#7
+ eor $t1,$t1,$Alo,lsr#7
+ eor $t0,$t0,$Alo,lsl#25
+ eor $t1,$t1,$Ahi,lsl#25 @ Sigma0(a)
+ adds $Tlo,$Tlo,$t0
+ and $t0,$Alo,$t2
+ adc $Thi,$Thi,$t1 @ T += Sigma0(a)
+
+ ldr $t1,[sp,#$Boff+4] @ b.hi
+ orr $Alo,$Alo,$t2
+ ldr $t2,[sp,#$Coff+4] @ c.hi
+ and $Alo,$Alo,$t3
+ and $t3,$Ahi,$t1
+ orr $Ahi,$Ahi,$t1
+ orr $Alo,$Alo,$t0 @ Maj(a,b,c).lo
+ and $Ahi,$Ahi,$t2
+ adds $Alo,$Alo,$Tlo
+ orr $Ahi,$Ahi,$t3 @ Maj(a,b,c).hi
+ sub sp,sp,#8
+ adc $Ahi,$Ahi,$Thi @ h += T
+ tst $Ktbl,#1
+ add $Ktbl,$Ktbl,#8
+___
+}
+$code=<<___;
+#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
+#if __ARM_MAX_ARCH__>=7
+.LOPENSSL_armcap:
+.word OPENSSL_armcap_P-sha512_block_data_order
+.skip 32-4
+#else
+.skip 32
+#endif
+
+.global sha512_block_data_order
+.type sha512_block_data_order,%function
+sha512_block_data_order:
+ sub r3,pc,#8 @ sha512_block_data_order
+ add $len,$inp,$len,lsl#7 @ len to point at the end of inp
+#if __ARM_MAX_ARCH__>=7
+ ldr r12,.LOPENSSL_armcap
+ ldr r12,[r3,r12] @ OPENSSL_armcap_P
+ tst r12,#1
+ bne .LNEON
+#endif
+ stmdb sp!,{r4-r12,lr}
+ sub $Ktbl,r3,#672 @ K512
+ sub sp,sp,#9*8
+
+ ldr $Elo,[$ctx,#$Eoff+$lo]
+ ldr $Ehi,[$ctx,#$Eoff+$hi]
+ ldr $t0, [$ctx,#$Goff+$lo]
+ ldr $t1, [$ctx,#$Goff+$hi]
+ ldr $t2, [$ctx,#$Hoff+$lo]
+ ldr $t3, [$ctx,#$Hoff+$hi]
+.Loop:
+ str $t0, [sp,#$Goff+0]
+ str $t1, [sp,#$Goff+4]
+ str $t2, [sp,#$Hoff+0]
+ str $t3, [sp,#$Hoff+4]
+ ldr $Alo,[$ctx,#$Aoff+$lo]
+ ldr $Ahi,[$ctx,#$Aoff+$hi]
+ ldr $Tlo,[$ctx,#$Boff+$lo]
+ ldr $Thi,[$ctx,#$Boff+$hi]
+ ldr $t0, [$ctx,#$Coff+$lo]
+ ldr $t1, [$ctx,#$Coff+$hi]
+ ldr $t2, [$ctx,#$Doff+$lo]
+ ldr $t3, [$ctx,#$Doff+$hi]
+ str $Tlo,[sp,#$Boff+0]
+ str $Thi,[sp,#$Boff+4]
+ str $t0, [sp,#$Coff+0]
+ str $t1, [sp,#$Coff+4]
+ str $t2, [sp,#$Doff+0]
+ str $t3, [sp,#$Doff+4]
+ ldr $Tlo,[$ctx,#$Foff+$lo]
+ ldr $Thi,[$ctx,#$Foff+$hi]
+ str $Tlo,[sp,#$Foff+0]
+ str $Thi,[sp,#$Foff+4]
+
+.L00_15:
+#if __ARM_ARCH__<7
+ ldrb $Tlo,[$inp,#7]
+ ldrb $t0, [$inp,#6]
+ ldrb $t1, [$inp,#5]
+ ldrb $t2, [$inp,#4]
+ ldrb $Thi,[$inp,#3]
+ ldrb $t3, [$inp,#2]
+ orr $Tlo,$Tlo,$t0,lsl#8
+ ldrb $t0, [$inp,#1]
+ orr $Tlo,$Tlo,$t1,lsl#16
+ ldrb $t1, [$inp],#8
+ orr $Tlo,$Tlo,$t2,lsl#24
+ orr $Thi,$Thi,$t3,lsl#8
+ orr $Thi,$Thi,$t0,lsl#16
+ orr $Thi,$Thi,$t1,lsl#24
+#else
+ ldr $Tlo,[$inp,#4]
+ ldr $Thi,[$inp],#8
+#ifdef __ARMEL__
+ rev $Tlo,$Tlo
+ rev $Thi,$Thi
+#endif
+#endif
+___
+ &BODY_00_15(0x94);
+$code.=<<___;
+ tst $Ktbl,#1
+ beq .L00_15
+ ldr $t0,[sp,#`$Xoff+8*(16-1)`+0]
+ ldr $t1,[sp,#`$Xoff+8*(16-1)`+4]
+ bic $Ktbl,$Ktbl,#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 $Tlo,$t0,lsr#1
+ ldr $t2,[sp,#`$Xoff+8*(16-14)`+0]
+ mov $Thi,$t1,lsr#1
+ ldr $t3,[sp,#`$Xoff+8*(16-14)`+4]
+ eor $Tlo,$Tlo,$t1,lsl#31
+ eor $Thi,$Thi,$t0,lsl#31
+ eor $Tlo,$Tlo,$t0,lsr#8
+ eor $Thi,$Thi,$t1,lsr#8
+ eor $Tlo,$Tlo,$t1,lsl#24
+ eor $Thi,$Thi,$t0,lsl#24
+ eor $Tlo,$Tlo,$t0,lsr#7
+ eor $Thi,$Thi,$t1,lsr#7
+ eor $Tlo,$Tlo,$t1,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 $t0,$t2,lsr#19
+ mov $t1,$t3,lsr#19
+ eor $t0,$t0,$t3,lsl#13
+ eor $t1,$t1,$t2,lsl#13
+ eor $t0,$t0,$t3,lsr#29
+ eor $t1,$t1,$t2,lsr#29
+ eor $t0,$t0,$t2,lsl#3
+ eor $t1,$t1,$t3,lsl#3
+ eor $t0,$t0,$t2,lsr#6
+ eor $t1,$t1,$t3,lsr#6
+ ldr $t2,[sp,#`$Xoff+8*(16-9)`+0]
+ eor $t0,$t0,$t3,lsl#26
+
+ ldr $t3,[sp,#`$Xoff+8*(16-9)`+4]
+ adds $Tlo,$Tlo,$t0
+ ldr $t0,[sp,#`$Xoff+8*16`+0]
+ adc $Thi,$Thi,$t1
+
+ ldr $t1,[sp,#`$Xoff+8*16`+4]
+ adds $Tlo,$Tlo,$t2
+ adc $Thi,$Thi,$t3
+ adds $Tlo,$Tlo,$t0
+ adc $Thi,$Thi,$t1
+___
+ &BODY_00_15(0x17);
+$code.=<<___;
+ ldreq $t0,[sp,#`$Xoff+8*(16-1)`+0]
+ ldreq $t1,[sp,#`$Xoff+8*(16-1)`+4]
+ beq .L16_79
+ bic $Ktbl,$Ktbl,#1
+
+ ldr $Tlo,[sp,#$Boff+0]
+ ldr $Thi,[sp,#$Boff+4]
+ ldr $t0, [$ctx,#$Aoff+$lo]
+ ldr $t1, [$ctx,#$Aoff+$hi]
+ ldr $t2, [$ctx,#$Boff+$lo]
+ ldr $t3, [$ctx,#$Boff+$hi]
+ adds $t0,$Alo,$t0
+ str $t0, [$ctx,#$Aoff+$lo]
+ adc $t1,$Ahi,$t1
+ str $t1, [$ctx,#$Aoff+$hi]
+ adds $t2,$Tlo,$t2
+ str $t2, [$ctx,#$Boff+$lo]
+ adc $t3,$Thi,$t3
+ str $t3, [$ctx,#$Boff+$hi]
+
+ ldr $Alo,[sp,#$Coff+0]
+ ldr $Ahi,[sp,#$Coff+4]
+ ldr $Tlo,[sp,#$Doff+0]
+ ldr $Thi,[sp,#$Doff+4]
+ ldr $t0, [$ctx,#$Coff+$lo]
+ ldr $t1, [$ctx,#$Coff+$hi]
+ ldr $t2, [$ctx,#$Doff+$lo]
+ ldr $t3, [$ctx,#$Doff+$hi]
+ adds $t0,$Alo,$t0
+ str $t0, [$ctx,#$Coff+$lo]
+ adc $t1,$Ahi,$t1
+ str $t1, [$ctx,#$Coff+$hi]
+ adds $t2,$Tlo,$t2
+ str $t2, [$ctx,#$Doff+$lo]
+ adc $t3,$Thi,$t3
+ str $t3, [$ctx,#$Doff+$hi]
+
+ ldr $Tlo,[sp,#$Foff+0]
+ ldr $Thi,[sp,#$Foff+4]
+ ldr $t0, [$ctx,#$Eoff+$lo]
+ ldr $t1, [$ctx,#$Eoff+$hi]
+ ldr $t2, [$ctx,#$Foff+$lo]
+ ldr $t3, [$ctx,#$Foff+$hi]
+ adds $Elo,$Elo,$t0
+ str $Elo,[$ctx,#$Eoff+$lo]
+ adc $Ehi,$Ehi,$t1
+ str $Ehi,[$ctx,#$Eoff+$hi]
+ adds $t2,$Tlo,$t2
+ str $t2, [$ctx,#$Foff+$lo]
+ adc $t3,$Thi,$t3
+ str $t3, [$ctx,#$Foff+$hi]
+
+ ldr $Alo,[sp,#$Goff+0]
+ ldr $Ahi,[sp,#$Goff+4]
+ ldr $Tlo,[sp,#$Hoff+0]
+ ldr $Thi,[sp,#$Hoff+4]
+ ldr $t0, [$ctx,#$Goff+$lo]
+ ldr $t1, [$ctx,#$Goff+$hi]
+ ldr $t2, [$ctx,#$Hoff+$lo]
+ ldr $t3, [$ctx,#$Hoff+$hi]
+ adds $t0,$Alo,$t0
+ str $t0, [$ctx,#$Goff+$lo]
+ adc $t1,$Ahi,$t1
+ str $t1, [$ctx,#$Goff+$hi]
+ adds $t2,$Tlo,$t2
+ str $t2, [$ctx,#$Hoff+$lo]
+ adc $t3,$Thi,$t3
+ str $t3, [$ctx,#$Hoff+$hi]
+
+ add sp,sp,#640
+ sub $Ktbl,$Ktbl,#640
+
+ teq $inp,$len
+ 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
+ bx lr @ interoperable with Thumb ISA:-)
+#endif
+___
+
+{
+my @Sigma0=(28,34,39);
+my @Sigma1=(14,18,41);
+my @sigma0=(1, 8, 7);
+my @sigma1=(19,61,6);
+
+my $Ktbl="r3";
+my $cnt="r12"; # volatile register known as ip, intra-procedure-call scratch
+
+my @X=map("d$_",(0..15));
+my @V=($A,$B,$C,$D,$E,$F,$G,$H)=map("d$_",(16..23));
+
+sub NEON_00_15() {
+my $i=shift;
+my ($a,$b,$c,$d,$e,$f,$g,$h)=@_;
+my ($t0,$t1,$t2,$T1,$K,$Ch,$Maj)=map("d$_",(24..31)); # temps
+
+$code.=<<___ if ($i<16 || $i&1);
+ vshr.u64 $t0,$e,#@Sigma1[0] @ $i
+#if $i<16
+ vld1.64 {@X[$i%16]},[$inp]! @ handles unaligned
+#endif
+ vshr.u64 $t1,$e,#@Sigma1[1]
+#if $i>0
+ vadd.i64 $a,$Maj @ h+=Maj from the past
+#endif
+ vshr.u64 $t2,$e,#@Sigma1[2]
+___
+$code.=<<___;
+ vld1.64 {$K},[$Ktbl,:64]! @ K[i++]
+ vsli.64 $t0,$e,#`64-@Sigma1[0]`
+ vsli.64 $t1,$e,#`64-@Sigma1[1]`
+ vmov $Ch,$e
+ vsli.64 $t2,$e,#`64-@Sigma1[2]`
+#if $i<16 && defined(__ARMEL__)
+ vrev64.8 @X[$i],@X[$i]
+#endif
+ veor $t1,$t0
+ vbsl $Ch,$f,$g @ Ch(e,f,g)
+ vshr.u64 $t0,$a,#@Sigma0[0]
+ veor $t2,$t1 @ Sigma1(e)
+ vadd.i64 $T1,$Ch,$h
+ vshr.u64 $t1,$a,#@Sigma0[1]
+ vsli.64 $t0,$a,#`64-@Sigma0[0]`
+ vadd.i64 $T1,$t2
+ vshr.u64 $t2,$a,#@Sigma0[2]
+ vadd.i64 $K,@X[$i%16]
+ vsli.64 $t1,$a,#`64-@Sigma0[1]`
+ veor $Maj,$a,$b
+ vsli.64 $t2,$a,#`64-@Sigma0[2]`
+ veor $h,$t0,$t1
+ vadd.i64 $T1,$K
+ vbsl $Maj,$c,$b @ Maj(a,b,c)
+ veor $h,$t2 @ Sigma0(a)
+ vadd.i64 $d,$T1
+ vadd.i64 $Maj,$T1
+ @ vadd.i64 $h,$Maj
+___
+}
+
+sub NEON_16_79() {
+my $i=shift;
+
+if ($i&1) { &NEON_00_15($i,@_); return; }
+
+# 2x-vectorized, therefore runs every 2nd round
+my @X=map("q$_",(0..7)); # view @X as 128-bit vector
+my ($t0,$t1,$s0,$s1) = map("q$_",(12..15)); # temps
+my ($d0,$d1,$d2) = map("d$_",(24..26)); # temps from NEON_00_15
+my $e=@_[4]; # $e from NEON_00_15
+$i /= 2;
+$code.=<<___;
+ vshr.u64 $t0,@X[($i+7)%8],#@sigma1[0]
+ vshr.u64 $t1,@X[($i+7)%8],#@sigma1[1]
+ vadd.i64 @_[0],d30 @ h+=Maj from the past
+ vshr.u64 $s1,@X[($i+7)%8],#@sigma1[2]
+ vsli.64 $t0,@X[($i+7)%8],#`64-@sigma1[0]`
+ vext.8 $s0,@X[$i%8],@X[($i+1)%8],#8 @ X[i+1]
+ vsli.64 $t1,@X[($i+7)%8],#`64-@sigma1[1]`
+ veor $s1,$t0
+ vshr.u64 $t0,$s0,#@sigma0[0]
+ veor $s1,$t1 @ sigma1(X[i+14])
+ vshr.u64 $t1,$s0,#@sigma0[1]
+ vadd.i64 @X[$i%8],$s1
+ vshr.u64 $s1,$s0,#@sigma0[2]
+ vsli.64 $t0,$s0,#`64-@sigma0[0]`
+ vsli.64 $t1,$s0,#`64-@sigma0[1]`
+ vext.8 $s0,@X[($i+4)%8],@X[($i+5)%8],#8 @ X[i+9]
+ veor $s1,$t0
+ vshr.u64 $d0,$e,#@Sigma1[0] @ from NEON_00_15
+ vadd.i64 @X[$i%8],$s0
+ vshr.u64 $d1,$e,#@Sigma1[1] @ from NEON_00_15
+ veor $s1,$t1 @ sigma0(X[i+1])
+ vshr.u64 $d2,$e,#@Sigma1[2] @ from NEON_00_15
+ vadd.i64 @X[$i%8],$s1
+___
+ &NEON_00_15(2*$i,@_);
+}
+
+$code.=<<___;
+#if __ARM_MAX_ARCH__>=7
+.arch armv7-a
+.fpu neon
+
+.align 4
+.LNEON:
+ dmb @ errata #451034 on early Cortex A8
+ vstmdb sp!,{d8-d15} @ ABI specification says so
+ sub $Ktbl,r3,#672 @ K512
+ vldmia $ctx,{$A-$H} @ load context
+.Loop_neon:
+___
+for($i=0;$i<16;$i++) { &NEON_00_15($i,@V); unshift(@V,pop(@V)); }
+$code.=<<___;
+ mov $cnt,#4
+.L16_79_neon:
+ subs $cnt,#1
+___
+for(;$i<32;$i++) { &NEON_16_79($i,@V); unshift(@V,pop(@V)); }
+$code.=<<___;
+ bne .L16_79_neon
+
+ vadd.i64 $A,d30 @ h+=Maj from the past
+ vldmia $ctx,{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 $ctx,{$A-$H} @ save context
+ teq $inp,$len
+ sub $Ktbl,#640 @ rewind K512
+ bne .Loop_neon
+
+ vldmia sp!,{d8-d15} @ epilogue
+ ret @ bx lr
+#endif
+___
+}
+$code.=<<___;
+.size sha512_block_data_order,.-sha512_block_data_order
+.asciz "SHA512 block transform for ARMv4/NEON, CRYPTOGAMS by <appro\@openssl.org>"
+.align 2
+#if __ARM_MAX_ARCH__>=7
+.comm OPENSSL_armcap_P,4,4
+#endif
+___
+
+$code =~ s/\`([^\`]*)\`/eval $1/gem;
+$code =~ s/\bbx\s+lr\b/.word\t0xe12fff1e/gm; # make it possible to compile with -march=armv4
+$code =~ s/\bret\b/bx lr/gm;
+print $code;
+close STDOUT; # enforce flush
diff --git a/src/crypto/sha/asm/sha512-armv8.pl b/src/crypto/sha/asm/sha512-armv8.pl
new file mode 100644
index 0000000..5a9c812
--- /dev/null
+++ b/src/crypto/sha/asm/sha512-armv8.pl
@@ -0,0 +1,419 @@
+#!/usr/bin/env perl
+#
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+# project. The module is, however, dual licensed under OpenSSL and
+# CRYPTOGAMS licenses depending on where you obtain it. For further
+# details see http://www.openssl.org/~appro/cryptogams/.
+# ====================================================================
+#
+# SHA256/512 for ARMv8.
+#
+# Performance in cycles per processed byte and improvement coefficient
+# over code generated with "default" compiler:
+#
+# SHA256-hw SHA256(*) SHA512
+# Apple A7 1.97 10.5 (+33%) 6.73 (-1%(**))
+# Cortex-A53 2.38 15.6 (+110%) 10.1 (+190%(***))
+# Cortex-A57 2.31 11.6 (+86%) 7.51 (+260%(***))
+#
+# (*) Software SHA256 results are of lesser relevance, presented
+# mostly for informational purposes.
+# (**) The result is a trade-off: it's possible to improve it by
+# 10% (or by 1 cycle per round), but at the cost of 20% loss
+# on Cortex-A53 (or by 4 cycles per round).
+# (***) Super-impressive coefficients over gcc-generated code are
+# indication of some compiler "pathology", most notably code
+# generated with -mgeneral-regs-only is significanty faster
+# and lags behind assembly only by 50-90%.
+
+$flavour=shift;
+$output=shift;
+
+if ($output =~ /512/) {
+ $BITS=512;
+ $SZ=8;
+ @Sigma0=(28,34,39);
+ @Sigma1=(14,18,41);
+ @sigma0=(1, 8, 7);
+ @sigma1=(19,61, 6);
+ $rounds=80;
+ $reg_t="x";
+} else {
+ $BITS=256;
+ $SZ=4;
+ @Sigma0=( 2,13,22);
+ @Sigma1=( 6,11,25);
+ @sigma0=( 7,18, 3);
+ @sigma1=(17,19,10);
+ $rounds=64;
+ $reg_t="w";
+}
+
+$func="sha${BITS}_block_data_order";
+
+($ctx,$inp,$num,$Ktbl)=map("x$_",(0..2,30));
+
+@X=map("$reg_t$_",(3..15,0..2));
+@V=($A,$B,$C,$D,$E,$F,$G,$H)=map("$reg_t$_",(20..27));
+($t0,$t1,$t2,$t3)=map("$reg_t$_",(16,17,19,28));
+
+sub BODY_00_xx {
+my ($i,$a,$b,$c,$d,$e,$f,$g,$h)=@_;
+my $j=($i+1)&15;
+my ($T0,$T1,$T2)=(@X[($i-8)&15],@X[($i-9)&15],@X[($i-10)&15]);
+ $T0=@X[$i+3] if ($i<11);
+
+$code.=<<___ if ($i<16);
+#ifndef __ARMEB__
+ rev @X[$i],@X[$i] // $i
+#endif
+___
+$code.=<<___ if ($i<13 && ($i&1));
+ ldp @X[$i+1],@X[$i+2],[$inp],#2*$SZ
+___
+$code.=<<___ if ($i==13);
+ ldp @X[14],@X[15],[$inp]
+___
+$code.=<<___ if ($i>=14);
+ ldr @X[($i-11)&15],[sp,#`$SZ*(($i-11)%4)`]
+___
+$code.=<<___ if ($i>0 && $i<16);
+ add $a,$a,$t1 // h+=Sigma0(a)
+___
+$code.=<<___ if ($i>=11);
+ str @X[($i-8)&15],[sp,#`$SZ*(($i-8)%4)`]
+___
+# While ARMv8 specifies merged rotate-n-logical operation such as
+# 'eor x,y,z,ror#n', it was found to negatively affect performance
+# on Apple A7. The reason seems to be that it requires even 'y' to
+# be available earlier. This means that such merged instruction is
+# not necessarily best choice on critical path... On the other hand
+# Cortex-A5x handles merged instructions much better than disjoint
+# rotate and logical... See (**) footnote above.
+$code.=<<___ if ($i<15);
+ ror $t0,$e,#$Sigma1[0]
+ add $h,$h,$t2 // h+=K[i]
+ eor $T0,$e,$e,ror#`$Sigma1[2]-$Sigma1[1]`
+ and $t1,$f,$e
+ bic $t2,$g,$e
+ add $h,$h,@X[$i&15] // h+=X[i]
+ orr $t1,$t1,$t2 // Ch(e,f,g)
+ eor $t2,$a,$b // a^b, b^c in next round
+ eor $t0,$t0,$T0,ror#$Sigma1[1] // Sigma1(e)
+ ror $T0,$a,#$Sigma0[0]
+ add $h,$h,$t1 // h+=Ch(e,f,g)
+ eor $t1,$a,$a,ror#`$Sigma0[2]-$Sigma0[1]`
+ add $h,$h,$t0 // h+=Sigma1(e)
+ and $t3,$t3,$t2 // (b^c)&=(a^b)
+ add $d,$d,$h // d+=h
+ eor $t3,$t3,$b // Maj(a,b,c)
+ eor $t1,$T0,$t1,ror#$Sigma0[1] // Sigma0(a)
+ add $h,$h,$t3 // h+=Maj(a,b,c)
+ ldr $t3,[$Ktbl],#$SZ // *K++, $t2 in next round
+ //add $h,$h,$t1 // h+=Sigma0(a)
+___
+$code.=<<___ if ($i>=15);
+ ror $t0,$e,#$Sigma1[0]
+ add $h,$h,$t2 // h+=K[i]
+ ror $T1,@X[($j+1)&15],#$sigma0[0]
+ and $t1,$f,$e
+ ror $T2,@X[($j+14)&15],#$sigma1[0]
+ bic $t2,$g,$e
+ ror $T0,$a,#$Sigma0[0]
+ add $h,$h,@X[$i&15] // h+=X[i]
+ eor $t0,$t0,$e,ror#$Sigma1[1]
+ eor $T1,$T1,@X[($j+1)&15],ror#$sigma0[1]
+ orr $t1,$t1,$t2 // Ch(e,f,g)
+ eor $t2,$a,$b // a^b, b^c in next round
+ eor $t0,$t0,$e,ror#$Sigma1[2] // Sigma1(e)
+ eor $T0,$T0,$a,ror#$Sigma0[1]
+ add $h,$h,$t1 // h+=Ch(e,f,g)
+ and $t3,$t3,$t2 // (b^c)&=(a^b)
+ eor $T2,$T2,@X[($j+14)&15],ror#$sigma1[1]
+ eor $T1,$T1,@X[($j+1)&15],lsr#$sigma0[2] // sigma0(X[i+1])
+ add $h,$h,$t0 // h+=Sigma1(e)
+ eor $t3,$t3,$b // Maj(a,b,c)
+ eor $t1,$T0,$a,ror#$Sigma0[2] // Sigma0(a)
+ eor $T2,$T2,@X[($j+14)&15],lsr#$sigma1[2] // sigma1(X[i+14])
+ add @X[$j],@X[$j],@X[($j+9)&15]
+ add $d,$d,$h // d+=h
+ add $h,$h,$t3 // h+=Maj(a,b,c)
+ ldr $t3,[$Ktbl],#$SZ // *K++, $t2 in next round
+ add @X[$j],@X[$j],$T1
+ add $h,$h,$t1 // h+=Sigma0(a)
+ add @X[$j],@X[$j],$T2
+___
+ ($t2,$t3)=($t3,$t2);
+}
+
+$code.=<<___;
+#include "arm_arch.h"
+
+.text
+
+.globl $func
+.type $func,%function
+.align 6
+$func:
+___
+$code.=<<___ if ($SZ==4);
+ ldr x16,.LOPENSSL_armcap_P
+ adr x17,.LOPENSSL_armcap_P
+ add x16,x16,x17
+ ldr w16,[x16]
+ tst w16,#ARMV8_SHA256
+ b.ne .Lv8_entry
+___
+$code.=<<___;
+ stp x29,x30,[sp,#-128]!
+ add x29,sp,#0
+
+ stp x19,x20,[sp,#16]
+ stp x21,x22,[sp,#32]
+ stp x23,x24,[sp,#48]
+ stp x25,x26,[sp,#64]
+ stp x27,x28,[sp,#80]
+ sub sp,sp,#4*$SZ
+
+ ldp $A,$B,[$ctx] // load context
+ ldp $C,$D,[$ctx,#2*$SZ]
+ ldp $E,$F,[$ctx,#4*$SZ]
+ add $num,$inp,$num,lsl#`log(16*$SZ)/log(2)` // end of input
+ ldp $G,$H,[$ctx,#6*$SZ]
+ adr $Ktbl,K$BITS
+ stp $ctx,$num,[x29,#96]
+
+.Loop:
+ ldp @X[0],@X[1],[$inp],#2*$SZ
+ ldr $t2,[$Ktbl],#$SZ // *K++
+ eor $t3,$B,$C // magic seed
+ str $inp,[x29,#112]
+___
+for ($i=0;$i<16;$i++) { &BODY_00_xx($i,@V); unshift(@V,pop(@V)); }
+$code.=".Loop_16_xx:\n";
+for (;$i<32;$i++) { &BODY_00_xx($i,@V); unshift(@V,pop(@V)); }
+$code.=<<___;
+ cbnz $t2,.Loop_16_xx
+
+ ldp $ctx,$num,[x29,#96]
+ ldr $inp,[x29,#112]
+ sub $Ktbl,$Ktbl,#`$SZ*($rounds+1)` // rewind
+
+ ldp @X[0],@X[1],[$ctx]
+ ldp @X[2],@X[3],[$ctx,#2*$SZ]
+ add $inp,$inp,#14*$SZ // advance input pointer
+ ldp @X[4],@X[5],[$ctx,#4*$SZ]
+ add $A,$A,@X[0]
+ ldp @X[6],@X[7],[$ctx,#6*$SZ]
+ add $B,$B,@X[1]
+ add $C,$C,@X[2]
+ add $D,$D,@X[3]
+ stp $A,$B,[$ctx]
+ add $E,$E,@X[4]
+ add $F,$F,@X[5]
+ stp $C,$D,[$ctx,#2*$SZ]
+ add $G,$G,@X[6]
+ add $H,$H,@X[7]
+ cmp $inp,$num
+ stp $E,$F,[$ctx,#4*$SZ]
+ stp $G,$H,[$ctx,#6*$SZ]
+ b.ne .Loop
+
+ ldp x19,x20,[x29,#16]
+ add sp,sp,#4*$SZ
+ ldp x21,x22,[x29,#32]
+ ldp x23,x24,[x29,#48]
+ ldp x25,x26,[x29,#64]
+ ldp x27,x28,[x29,#80]
+ ldp x29,x30,[sp],#128
+ ret
+.size $func,.-$func
+
+.align 6
+.type K$BITS,%object
+K$BITS:
+___
+$code.=<<___ if ($SZ==8);
+ .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
+ .quad 0 // terminator
+___
+$code.=<<___ if ($SZ==4);
+ .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
+ .long 0 //terminator
+___
+$code.=<<___;
+.size K$BITS,.-K$BITS
+.align 3
+.LOPENSSL_armcap_P:
+ .quad OPENSSL_armcap_P-.
+.asciz "SHA$BITS block transform for ARMv8, CRYPTOGAMS by <appro\@openssl.org>"
+.align 2
+___
+
+if ($SZ==4) {
+my $Ktbl="x3";
+
+my ($ABCD,$EFGH,$abcd)=map("v$_.16b",(0..2));
+my @MSG=map("v$_.16b",(4..7));
+my ($W0,$W1)=("v16.4s","v17.4s");
+my ($ABCD_SAVE,$EFGH_SAVE)=("v18.16b","v19.16b");
+
+$code.=<<___;
+.type sha256_block_armv8,%function
+.align 6
+sha256_block_armv8:
+.Lv8_entry:
+ stp x29,x30,[sp,#-16]!
+ add x29,sp,#0
+
+ ld1.32 {$ABCD,$EFGH},[$ctx]
+ adr $Ktbl,K256
+
+.Loop_hw:
+ ld1 {@MSG[0]-@MSG[3]},[$inp],#64
+ sub $num,$num,#1
+ ld1.32 {$W0},[$Ktbl],#16
+ rev32 @MSG[0],@MSG[0]
+ rev32 @MSG[1],@MSG[1]
+ rev32 @MSG[2],@MSG[2]
+ rev32 @MSG[3],@MSG[3]
+ orr $ABCD_SAVE,$ABCD,$ABCD // offload
+ orr $EFGH_SAVE,$EFGH,$EFGH
+___
+for($i=0;$i<12;$i++) {
+$code.=<<___;
+ ld1.32 {$W1},[$Ktbl],#16
+ add.i32 $W0,$W0,@MSG[0]
+ sha256su0 @MSG[0],@MSG[1]
+ orr $abcd,$ABCD,$ABCD
+ sha256h $ABCD,$EFGH,$W0
+ sha256h2 $EFGH,$abcd,$W0
+ sha256su1 @MSG[0],@MSG[2],@MSG[3]
+___
+ ($W0,$W1)=($W1,$W0); push(@MSG,shift(@MSG));
+}
+$code.=<<___;
+ ld1.32 {$W1},[$Ktbl],#16
+ add.i32 $W0,$W0,@MSG[0]
+ orr $abcd,$ABCD,$ABCD
+ sha256h $ABCD,$EFGH,$W0
+ sha256h2 $EFGH,$abcd,$W0
+
+ ld1.32 {$W0},[$Ktbl],#16
+ add.i32 $W1,$W1,@MSG[1]
+ orr $abcd,$ABCD,$ABCD
+ sha256h $ABCD,$EFGH,$W1
+ sha256h2 $EFGH,$abcd,$W1
+
+ ld1.32 {$W1},[$Ktbl]
+ add.i32 $W0,$W0,@MSG[2]
+ sub $Ktbl,$Ktbl,#$rounds*$SZ-16 // rewind
+ orr $abcd,$ABCD,$ABCD
+ sha256h $ABCD,$EFGH,$W0
+ sha256h2 $EFGH,$abcd,$W0
+
+ add.i32 $W1,$W1,@MSG[3]
+ orr $abcd,$ABCD,$ABCD
+ sha256h $ABCD,$EFGH,$W1
+ sha256h2 $EFGH,$abcd,$W1
+
+ add.i32 $ABCD,$ABCD,$ABCD_SAVE
+ add.i32 $EFGH,$EFGH,$EFGH_SAVE
+
+ cbnz $num,.Loop_hw
+
+ st1.32 {$ABCD,$EFGH},[$ctx]
+
+ ldr x29,[sp],#16
+ ret
+.size sha256_block_armv8,.-sha256_block_armv8
+___
+}
+
+$code.=<<___;
+.comm OPENSSL_armcap_P,4,4
+___
+
+{ my %opcode = (
+ "sha256h" => 0x5e004000, "sha256h2" => 0x5e005000,
+ "sha256su0" => 0x5e282800, "sha256su1" => 0x5e006000 );
+
+ sub unsha256 {
+ my ($mnemonic,$arg)=@_;
+
+ $arg =~ m/[qv]([0-9]+)[^,]*,\s*[qv]([0-9]+)[^,]*(?:,\s*[qv]([0-9]+))?/o
+ &&
+ sprintf ".inst\t0x%08x\t//%s %s",
+ $opcode{$mnemonic}|$1|($2<<5)|($3<<16),
+ $mnemonic,$arg;
+ }
+}
+
+foreach(split("\n",$code)) {
+
+ s/\`([^\`]*)\`/eval($1)/geo;
+
+ s/\b(sha256\w+)\s+([qv].*)/unsha256($1,$2)/geo;
+
+ s/\.\w?32\b//o and s/\.16b/\.4s/go;
+ m/(ld|st)1[^\[]+\[0\]/o and s/\.4s/\.s/go;
+
+ print $_,"\n";
+}
+
+close STDOUT;
diff --git a/src/crypto/sha/asm/sha512-x86_64.pl b/src/crypto/sha/asm/sha512-x86_64.pl
new file mode 100644
index 0000000..6660a88
--- /dev/null
+++ b/src/crypto/sha/asm/sha512-x86_64.pl
@@ -0,0 +1,2396 @@
+#!/usr/bin/env perl
+#
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+# project. Rights for redistribution and usage in source and binary
+# forms are granted according to the OpenSSL license.
+# ====================================================================
+#
+# sha256/512_block procedure for x86_64.
+#
+# 40% improvement over compiler-generated code on Opteron. On EM64T
+# sha256 was observed to run >80% faster and sha512 - >40%. No magical
+# tricks, just straight implementation... I really wonder why gcc
+# [being armed with inline assembler] fails to generate as fast code.
+# The only thing which is cool about this module is that it's very
+# same instruction sequence used for both SHA-256 and SHA-512. In
+# former case the instructions operate on 32-bit operands, while in
+# latter - on 64-bit ones. All I had to do is to get one flavor right,
+# the other one passed the test right away:-)
+#
+# sha256_block runs in ~1005 cycles on Opteron, which gives you
+# asymptotic performance of 64*1000/1005=63.7MBps times CPU clock
+# frequency in GHz. sha512_block runs in ~1275 cycles, which results
+# in 128*1000/1275=100MBps per GHz. Is there room for improvement?
+# Well, if you compare it to IA-64 implementation, which maintains
+# X[16] in register bank[!], tends to 4 instructions per CPU clock
+# cycle and runs in 1003 cycles, 1275 is very good result for 3-way
+# issue Opteron pipeline and X[16] maintained in memory. So that *if*
+# there is a way to improve it, *then* the only way would be to try to
+# offload X[16] updates to SSE unit, but that would require "deeper"
+# loop unroll, which in turn would naturally cause size blow-up, not
+# to mention increased complexity! And once again, only *if* it's
+# actually possible to noticeably improve overall ILP, instruction
+# level parallelism, on a given CPU implementation in this case.
+#
+# Special note on Intel EM64T. While Opteron CPU exhibits perfect
+# perfromance ratio of 1.5 between 64- and 32-bit flavors [see above],
+# [currently available] EM64T CPUs apparently are far from it. On the
+# contrary, 64-bit version, sha512_block, is ~30% *slower* than 32-bit
+# sha256_block:-( This is presumably because 64-bit shifts/rotates
+# apparently are not atomic instructions, but implemented in microcode.
+#
+# May 2012.
+#
+# Optimization including one of Pavel Semjanov's ideas, alternative
+# Maj, resulted in >=5% improvement on most CPUs, +20% SHA256 and
+# unfortunately -2% SHA512 on P4 [which nobody should care about
+# that much].
+#
+# June 2012.
+#
+# Add SIMD code paths, see below for improvement coefficients. SSSE3
+# code path was not attempted for SHA512, because improvement is not
+# estimated to be high enough, noticeably less than 9%, to justify
+# the effort, not on pre-AVX processors. [Obviously with exclusion
+# for VIA Nano, but it has SHA512 instruction that is faster and
+# should be used instead.] For reference, corresponding estimated
+# upper limit for improvement for SSSE3 SHA256 is 28%. The fact that
+# higher coefficients are observed on VIA Nano and Bulldozer has more
+# to do with specifics of their architecture [which is topic for
+# separate discussion].
+#
+# November 2012.
+#
+# Add AVX2 code path. Two consecutive input blocks are loaded to
+# 256-bit %ymm registers, with data from first block to least
+# significant 128-bit halves and data from second to most significant.
+# The data is then processed with same SIMD instruction sequence as
+# for AVX, but with %ymm as operands. Side effect is increased stack
+# frame, 448 additional bytes in SHA256 and 1152 in SHA512, and 1.2KB
+# code size increase.
+#
+# March 2014.
+#
+# Add support for Intel SHA Extensions.
+
+######################################################################
+# Current performance in cycles per processed byte (less is better):
+#
+# SHA256 SSSE3 AVX/XOP(*) SHA512 AVX/XOP(*)
+#
+# AMD K8 14.9 - - 9.57 -
+# P4 17.3 - - 30.8 -
+# Core 2 15.6 13.8(+13%) - 9.97 -
+# Westmere 14.8 12.3(+19%) - 9.58 -
+# Sandy Bridge 17.4 14.2(+23%) 11.6(+50%(**)) 11.2 8.10(+38%(**))
+# Ivy Bridge 12.6 10.5(+20%) 10.3(+22%) 8.17 7.22(+13%)
+# Haswell 12.2 9.28(+31%) 7.80(+56%) 7.66 5.40(+42%)
+# Bulldozer 21.1 13.6(+54%) 13.6(+54%(***)) 13.5 8.58(+57%)
+# VIA Nano 23.0 16.5(+39%) - 14.7 -
+# Atom 23.0 18.9(+22%) - 14.7 -
+# Silvermont 27.4 20.6(+33%) - 17.5 -
+#
+# (*) whichever best applicable;
+# (**) switch from ror to shrd stands for fair share of improvement;
+# (***) execution time is fully determined by remaining integer-only
+# part, body_00_15; reducing the amount of SIMD instructions
+# below certain limit makes no difference/sense; to conserve
+# space SHA256 XOP code path is therefore omitted;
+
+$flavour = shift;
+$output = shift;
+if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+
+$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
+( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
+die "can't locate x86_64-xlate.pl";
+
+if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
+ =~ /GNU assembler version ([2-9]\.[0-9]+)/) {
+ $avx = ($1>=2.19) + ($1>=2.22);
+}
+
+if (!$avx && $win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) &&
+ `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)/) {
+ $avx = ($1>=2.09) + ($1>=2.10);
+}
+
+if (!$avx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) &&
+ `ml64 2>&1` =~ /Version ([0-9]+)\./) {
+ $avx = ($1>=10) + ($1>=11);
+}
+
+if (!$avx && `$ENV{CC} -v 2>&1` =~ /(^clang version|based on LLVM) ([3-9]\.[0-9]+)/) {
+ $avx = ($2>=3.0) + ($2>3.0);
+}
+
+$shaext=0; ### set to zero if compiling for 1.0.1
+$avx=1 if (!$shaext && $avx);
+
+open OUT,"| \"$^X\" $xlate $flavour";
+*STDOUT=*OUT;
+
+if ($output =~ /512/) {
+ $func="sha512_block_data_order";
+ $TABLE="K512";
+ $SZ=8;
+ @ROT=($A,$B,$C,$D,$E,$F,$G,$H)=("%rax","%rbx","%rcx","%rdx",
+ "%r8", "%r9", "%r10","%r11");
+ ($T1,$a0,$a1,$a2,$a3)=("%r12","%r13","%r14","%r15","%rdi");
+ @Sigma0=(28,34,39);
+ @Sigma1=(14,18,41);
+ @sigma0=(1, 8, 7);
+ @sigma1=(19,61, 6);
+ $rounds=80;
+} else {
+ $func="sha256_block_data_order";
+ $TABLE="K256";
+ $SZ=4;
+ @ROT=($A,$B,$C,$D,$E,$F,$G,$H)=("%eax","%ebx","%ecx","%edx",
+ "%r8d","%r9d","%r10d","%r11d");
+ ($T1,$a0,$a1,$a2,$a3)=("%r12d","%r13d","%r14d","%r15d","%edi");
+ @Sigma0=( 2,13,22);
+ @Sigma1=( 6,11,25);
+ @sigma0=( 7,18, 3);
+ @sigma1=(17,19,10);
+ $rounds=64;
+}
+
+$ctx="%rdi"; # 1st arg, zapped by $a3
+$inp="%rsi"; # 2nd arg
+$Tbl="%rbp";
+
+$_ctx="16*$SZ+0*8(%rsp)";
+$_inp="16*$SZ+1*8(%rsp)";
+$_end="16*$SZ+2*8(%rsp)";
+$_rsp="16*$SZ+3*8(%rsp)";
+$framesz="16*$SZ+4*8";
+
+
+sub ROUND_00_15()
+{ my ($i,$a,$b,$c,$d,$e,$f,$g,$h) = @_;
+ my $STRIDE=$SZ;
+ $STRIDE += 16 if ($i%(16/$SZ)==(16/$SZ-1));
+
+$code.=<<___;
+ ror \$`$Sigma1[2]-$Sigma1[1]`,$a0
+ mov $f,$a2
+
+ xor $e,$a0
+ ror \$`$Sigma0[2]-$Sigma0[1]`,$a1
+ xor $g,$a2 # f^g
+
+ mov $T1,`$SZ*($i&0xf)`(%rsp)
+ xor $a,$a1
+ and $e,$a2 # (f^g)&e
+
+ ror \$`$Sigma1[1]-$Sigma1[0]`,$a0
+ add $h,$T1 # T1+=h
+ xor $g,$a2 # Ch(e,f,g)=((f^g)&e)^g
+
+ ror \$`$Sigma0[1]-$Sigma0[0]`,$a1
+ xor $e,$a0
+ add $a2,$T1 # T1+=Ch(e,f,g)
+
+ mov $a,$a2
+ add ($Tbl),$T1 # T1+=K[round]
+ xor $a,$a1
+
+ xor $b,$a2 # a^b, b^c in next round
+ ror \$$Sigma1[0],$a0 # Sigma1(e)
+ mov $b,$h
+
+ and $a2,$a3
+ ror \$$Sigma0[0],$a1 # Sigma0(a)
+ add $a0,$T1 # T1+=Sigma1(e)
+
+ xor $a3,$h # h=Maj(a,b,c)=Ch(a^b,c,b)
+ add $T1,$d # d+=T1
+ add $T1,$h # h+=T1
+
+ lea $STRIDE($Tbl),$Tbl # round++
+___
+$code.=<<___ if ($i<15);
+ add $a1,$h # h+=Sigma0(a)
+___
+ ($a2,$a3) = ($a3,$a2);
+}
+
+sub ROUND_16_XX()
+{ my ($i,$a,$b,$c,$d,$e,$f,$g,$h) = @_;
+
+$code.=<<___;
+ mov `$SZ*(($i+1)&0xf)`(%rsp),$a0
+ mov `$SZ*(($i+14)&0xf)`(%rsp),$a2
+
+ mov $a0,$T1
+ ror \$`$sigma0[1]-$sigma0[0]`,$a0
+ add $a1,$a # modulo-scheduled h+=Sigma0(a)
+ mov $a2,$a1
+ ror \$`$sigma1[1]-$sigma1[0]`,$a2
+
+ xor $T1,$a0
+ shr \$$sigma0[2],$T1
+ ror \$$sigma0[0],$a0
+ xor $a1,$a2
+ shr \$$sigma1[2],$a1
+
+ ror \$$sigma1[0],$a2
+ xor $a0,$T1 # sigma0(X[(i+1)&0xf])
+ xor $a1,$a2 # sigma1(X[(i+14)&0xf])
+ add `$SZ*(($i+9)&0xf)`(%rsp),$T1
+
+ add `$SZ*($i&0xf)`(%rsp),$T1
+ mov $e,$a0
+ add $a2,$T1
+ mov $a,$a1
+___
+ &ROUND_00_15(@_);
+}
+
+$code=<<___;
+.text
+
+.extern OPENSSL_ia32cap_P
+.globl $func
+.type $func,\@function,3
+.align 16
+$func:
+___
+$code.=<<___ if ($SZ==4 || $avx);
+ lea OPENSSL_ia32cap_P(%rip),%r11
+ mov 0(%r11),%r9d
+ mov 4(%r11),%r10d
+ mov 8(%r11),%r11d
+___
+$code.=<<___ if ($SZ==4 && $shaext);
+ test \$`1<<29`,%r11d # check for SHA
+ jnz _shaext_shortcut
+___
+$code.=<<___ if ($avx && $SZ==8);
+ test \$`1<<11`,%r10d # check for XOP
+ jnz .Lxop_shortcut
+___
+$code.=<<___ if ($avx>1);
+ and \$`1<<8|1<<5|1<<3`,%r11d # check for BMI2+AVX2+BMI1
+ cmp \$`1<<8|1<<5|1<<3`,%r11d
+ je .Lavx2_shortcut
+___
+$code.=<<___ if ($avx);
+ and \$`1<<30`,%r9d # mask "Intel CPU" bit
+ and \$`1<<28|1<<9`,%r10d # mask AVX and SSSE3 bits
+ or %r9d,%r10d
+ cmp \$`1<<28|1<<9|1<<30`,%r10d
+ je .Lavx_shortcut
+___
+$code.=<<___ if ($SZ==4);
+ test \$`1<<9`,%r10d
+ jnz .Lssse3_shortcut
+___
+$code.=<<___;
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+ mov %rsp,%r11 # copy %rsp
+ shl \$4,%rdx # num*16
+ sub \$$framesz,%rsp
+ lea ($inp,%rdx,$SZ),%rdx # inp+num*16*$SZ
+ and \$-64,%rsp # align stack frame
+ mov $ctx,$_ctx # save ctx, 1st arg
+ mov $inp,$_inp # save inp, 2nd arh
+ mov %rdx,$_end # save end pointer, "3rd" arg
+ mov %r11,$_rsp # save copy of %rsp
+.Lprologue:
+
+ mov $SZ*0($ctx),$A
+ mov $SZ*1($ctx),$B
+ mov $SZ*2($ctx),$C
+ mov $SZ*3($ctx),$D
+ mov $SZ*4($ctx),$E
+ mov $SZ*5($ctx),$F
+ mov $SZ*6($ctx),$G
+ mov $SZ*7($ctx),$H
+ jmp .Lloop
+
+.align 16
+.Lloop:
+ mov $B,$a3
+ lea $TABLE(%rip),$Tbl
+ xor $C,$a3 # magic
+___
+ for($i=0;$i<16;$i++) {
+ $code.=" mov $SZ*$i($inp),$T1\n";
+ $code.=" mov @ROT[4],$a0\n";
+ $code.=" mov @ROT[0],$a1\n";
+ $code.=" bswap $T1\n";
+ &ROUND_00_15($i,@ROT);
+ unshift(@ROT,pop(@ROT));
+ }
+$code.=<<___;
+ jmp .Lrounds_16_xx
+.align 16
+.Lrounds_16_xx:
+___
+ for(;$i<32;$i++) {
+ &ROUND_16_XX($i,@ROT);
+ unshift(@ROT,pop(@ROT));
+ }
+
+$code.=<<___;
+ cmpb \$0,`$SZ-1`($Tbl)
+ jnz .Lrounds_16_xx
+
+ mov $_ctx,$ctx
+ add $a1,$A # modulo-scheduled h+=Sigma0(a)
+ lea 16*$SZ($inp),$inp
+
+ add $SZ*0($ctx),$A
+ add $SZ*1($ctx),$B
+ add $SZ*2($ctx),$C
+ add $SZ*3($ctx),$D
+ add $SZ*4($ctx),$E
+ add $SZ*5($ctx),$F
+ add $SZ*6($ctx),$G
+ add $SZ*7($ctx),$H
+
+ cmp $_end,$inp
+
+ mov $A,$SZ*0($ctx)
+ mov $B,$SZ*1($ctx)
+ mov $C,$SZ*2($ctx)
+ mov $D,$SZ*3($ctx)
+ mov $E,$SZ*4($ctx)
+ mov $F,$SZ*5($ctx)
+ mov $G,$SZ*6($ctx)
+ mov $H,$SZ*7($ctx)
+ jb .Lloop
+
+ mov $_rsp,%rsi
+ mov (%rsi),%r15
+ mov 8(%rsi),%r14
+ mov 16(%rsi),%r13
+ mov 24(%rsi),%r12
+ mov 32(%rsi),%rbp
+ mov 40(%rsi),%rbx
+ lea 48(%rsi),%rsp
+.Lepilogue:
+ ret
+.size $func,.-$func
+___
+
+if ($SZ==4) {
+$code.=<<___;
+.align 64
+.type $TABLE,\@object
+$TABLE:
+ .long 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5
+ .long 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5
+ .long 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5
+ .long 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5
+ .long 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3
+ .long 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3
+ .long 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174
+ .long 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174
+ .long 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc
+ .long 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc
+ .long 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da
+ .long 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da
+ .long 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7
+ .long 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7
+ .long 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967
+ .long 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967
+ .long 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13
+ .long 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13
+ .long 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85
+ .long 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85
+ .long 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3
+ .long 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3
+ .long 0xd192e819,0xd6990624,0xf40e3585,0x106aa070
+ .long 0xd192e819,0xd6990624,0xf40e3585,0x106aa070
+ .long 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5
+ .long 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5
+ .long 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3
+ .long 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3
+ .long 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208
+ .long 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208
+ .long 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
+ .long 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
+
+ .long 0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f
+ .long 0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f
+ .long 0x03020100,0x0b0a0908,0xffffffff,0xffffffff
+ .long 0x03020100,0x0b0a0908,0xffffffff,0xffffffff
+ .long 0xffffffff,0xffffffff,0x03020100,0x0b0a0908
+ .long 0xffffffff,0xffffffff,0x03020100,0x0b0a0908
+ .asciz "SHA256 block transform for x86_64, CRYPTOGAMS by <appro\@openssl.org>"
+___
+} else {
+$code.=<<___;
+.align 64
+.type $TABLE,\@object
+$TABLE:
+ .quad 0x428a2f98d728ae22,0x7137449123ef65cd
+ .quad 0x428a2f98d728ae22,0x7137449123ef65cd
+ .quad 0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc
+ .quad 0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc
+ .quad 0x3956c25bf348b538,0x59f111f1b605d019
+ .quad 0x3956c25bf348b538,0x59f111f1b605d019
+ .quad 0x923f82a4af194f9b,0xab1c5ed5da6d8118
+ .quad 0x923f82a4af194f9b,0xab1c5ed5da6d8118
+ .quad 0xd807aa98a3030242,0x12835b0145706fbe
+ .quad 0xd807aa98a3030242,0x12835b0145706fbe
+ .quad 0x243185be4ee4b28c,0x550c7dc3d5ffb4e2
+ .quad 0x243185be4ee4b28c,0x550c7dc3d5ffb4e2
+ .quad 0x72be5d74f27b896f,0x80deb1fe3b1696b1
+ .quad 0x72be5d74f27b896f,0x80deb1fe3b1696b1
+ .quad 0x9bdc06a725c71235,0xc19bf174cf692694
+ .quad 0x9bdc06a725c71235,0xc19bf174cf692694
+ .quad 0xe49b69c19ef14ad2,0xefbe4786384f25e3
+ .quad 0xe49b69c19ef14ad2,0xefbe4786384f25e3
+ .quad 0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65
+ .quad 0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65
+ .quad 0x2de92c6f592b0275,0x4a7484aa6ea6e483
+ .quad 0x2de92c6f592b0275,0x4a7484aa6ea6e483
+ .quad 0x5cb0a9dcbd41fbd4,0x76f988da831153b5
+ .quad 0x5cb0a9dcbd41fbd4,0x76f988da831153b5
+ .quad 0x983e5152ee66dfab,0xa831c66d2db43210
+ .quad 0x983e5152ee66dfab,0xa831c66d2db43210
+ .quad 0xb00327c898fb213f,0xbf597fc7beef0ee4
+ .quad 0xb00327c898fb213f,0xbf597fc7beef0ee4
+ .quad 0xc6e00bf33da88fc2,0xd5a79147930aa725
+ .quad 0xc6e00bf33da88fc2,0xd5a79147930aa725
+ .quad 0x06ca6351e003826f,0x142929670a0e6e70
+ .quad 0x06ca6351e003826f,0x142929670a0e6e70
+ .quad 0x27b70a8546d22ffc,0x2e1b21385c26c926
+ .quad 0x27b70a8546d22ffc,0x2e1b21385c26c926
+ .quad 0x4d2c6dfc5ac42aed,0x53380d139d95b3df
+ .quad 0x4d2c6dfc5ac42aed,0x53380d139d95b3df
+ .quad 0x650a73548baf63de,0x766a0abb3c77b2a8
+ .quad 0x650a73548baf63de,0x766a0abb3c77b2a8
+ .quad 0x81c2c92e47edaee6,0x92722c851482353b
+ .quad 0x81c2c92e47edaee6,0x92722c851482353b
+ .quad 0xa2bfe8a14cf10364,0xa81a664bbc423001
+ .quad 0xa2bfe8a14cf10364,0xa81a664bbc423001
+ .quad 0xc24b8b70d0f89791,0xc76c51a30654be30
+ .quad 0xc24b8b70d0f89791,0xc76c51a30654be30
+ .quad 0xd192e819d6ef5218,0xd69906245565a910
+ .quad 0xd192e819d6ef5218,0xd69906245565a910
+ .quad 0xf40e35855771202a,0x106aa07032bbd1b8
+ .quad 0xf40e35855771202a,0x106aa07032bbd1b8
+ .quad 0x19a4c116b8d2d0c8,0x1e376c085141ab53
+ .quad 0x19a4c116b8d2d0c8,0x1e376c085141ab53
+ .quad 0x2748774cdf8eeb99,0x34b0bcb5e19b48a8
+ .quad 0x2748774cdf8eeb99,0x34b0bcb5e19b48a8
+ .quad 0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb
+ .quad 0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb
+ .quad 0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3
+ .quad 0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3
+ .quad 0x748f82ee5defb2fc,0x78a5636f43172f60
+ .quad 0x748f82ee5defb2fc,0x78a5636f43172f60
+ .quad 0x84c87814a1f0ab72,0x8cc702081a6439ec
+ .quad 0x84c87814a1f0ab72,0x8cc702081a6439ec
+ .quad 0x90befffa23631e28,0xa4506cebde82bde9
+ .quad 0x90befffa23631e28,0xa4506cebde82bde9
+ .quad 0xbef9a3f7b2c67915,0xc67178f2e372532b
+ .quad 0xbef9a3f7b2c67915,0xc67178f2e372532b
+ .quad 0xca273eceea26619c,0xd186b8c721c0c207
+ .quad 0xca273eceea26619c,0xd186b8c721c0c207
+ .quad 0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178
+ .quad 0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178
+ .quad 0x06f067aa72176fba,0x0a637dc5a2c898a6
+ .quad 0x06f067aa72176fba,0x0a637dc5a2c898a6
+ .quad 0x113f9804bef90dae,0x1b710b35131c471b
+ .quad 0x113f9804bef90dae,0x1b710b35131c471b
+ .quad 0x28db77f523047d84,0x32caab7b40c72493
+ .quad 0x28db77f523047d84,0x32caab7b40c72493
+ .quad 0x3c9ebe0a15c9bebc,0x431d67c49c100d4c
+ .quad 0x3c9ebe0a15c9bebc,0x431d67c49c100d4c
+ .quad 0x4cc5d4becb3e42b6,0x597f299cfc657e2a
+ .quad 0x4cc5d4becb3e42b6,0x597f299cfc657e2a
+ .quad 0x5fcb6fab3ad6faec,0x6c44198c4a475817
+ .quad 0x5fcb6fab3ad6faec,0x6c44198c4a475817
+
+ .quad 0x0001020304050607,0x08090a0b0c0d0e0f
+ .quad 0x0001020304050607,0x08090a0b0c0d0e0f
+ .asciz "SHA512 block transform for x86_64, CRYPTOGAMS by <appro\@openssl.org>"
+___
+}
+
+######################################################################
+# SIMD code paths
+#
+if ($SZ==4 && $shaext) {{{
+######################################################################
+# Intel SHA Extensions implementation of SHA256 update function.
+#
+my ($ctx,$inp,$num,$Tbl)=("%rdi","%rsi","%rdx","%rcx");
+
+my ($Wi,$ABEF,$CDGH,$TMP,$BSWAP,$ABEF_SAVE,$CDGH_SAVE)=map("%xmm$_",(0..2,7..10));
+my @MSG=map("%xmm$_",(3..6));
+
+$code.=<<___;
+.type sha256_block_data_order_shaext,\@function,3
+.align 64
+sha256_block_data_order_shaext:
+_shaext_shortcut:
+___
+$code.=<<___ if ($win64);
+ lea `-8-5*16`(%rsp),%rsp
+ movaps %xmm6,-8-5*16(%rax)
+ movaps %xmm7,-8-4*16(%rax)
+ movaps %xmm8,-8-3*16(%rax)
+ movaps %xmm9,-8-2*16(%rax)
+ movaps %xmm10,-8-1*16(%rax)
+.Lprologue_shaext:
+___
+$code.=<<___;
+ lea K256+0x80(%rip),$Tbl
+ movdqu ($ctx),$ABEF # DCBA
+ movdqu 16($ctx),$CDGH # HGFE
+ movdqa 0x200-0x80($Tbl),$TMP # byte swap mask
+
+ pshufd \$0x1b,$ABEF,$Wi # ABCD
+ pshufd \$0xb1,$ABEF,$ABEF # CDAB
+ pshufd \$0x1b,$CDGH,$CDGH # EFGH
+ movdqa $TMP,$BSWAP # offload
+ palignr \$8,$CDGH,$ABEF # ABEF
+ punpcklqdq $Wi,$CDGH # CDGH
+ jmp .Loop_shaext
+
+.align 16
+.Loop_shaext:
+ movdqu ($inp),@MSG[0]
+ movdqu 0x10($inp),@MSG[1]
+ movdqu 0x20($inp),@MSG[2]
+ pshufb $TMP,@MSG[0]
+ movdqu 0x30($inp),@MSG[3]
+
+ movdqa 0*32-0x80($Tbl),$Wi
+ paddd @MSG[0],$Wi
+ pshufb $TMP,@MSG[1]
+ movdqa $CDGH,$CDGH_SAVE # offload
+ sha256rnds2 $ABEF,$CDGH # 0-3
+ pshufd \$0x0e,$Wi,$Wi
+ nop
+ movdqa $ABEF,$ABEF_SAVE # offload
+ sha256rnds2 $CDGH,$ABEF
+
+ movdqa 1*32-0x80($Tbl),$Wi
+ paddd @MSG[1],$Wi
+ pshufb $TMP,@MSG[2]
+ sha256rnds2 $ABEF,$CDGH # 4-7
+ pshufd \$0x0e,$Wi,$Wi
+ lea 0x40($inp),$inp
+ sha256msg1 @MSG[1],@MSG[0]
+ sha256rnds2 $CDGH,$ABEF
+
+ movdqa 2*32-0x80($Tbl),$Wi
+ paddd @MSG[2],$Wi
+ pshufb $TMP,@MSG[3]
+ sha256rnds2 $ABEF,$CDGH # 8-11
+ pshufd \$0x0e,$Wi,$Wi
+ movdqa @MSG[3],$TMP
+ palignr \$4,@MSG[2],$TMP
+ nop
+ paddd $TMP,@MSG[0]
+ sha256msg1 @MSG[2],@MSG[1]
+ sha256rnds2 $CDGH,$ABEF
+
+ movdqa 3*32-0x80($Tbl),$Wi
+ paddd @MSG[3],$Wi
+ sha256msg2 @MSG[3],@MSG[0]
+ sha256rnds2 $ABEF,$CDGH # 12-15
+ pshufd \$0x0e,$Wi,$Wi
+ movdqa @MSG[0],$TMP
+ palignr \$4,@MSG[3],$TMP
+ nop
+ paddd $TMP,@MSG[1]
+ sha256msg1 @MSG[3],@MSG[2]
+ sha256rnds2 $CDGH,$ABEF
+___
+for($i=4;$i<16-3;$i++) {
+$code.=<<___;
+ movdqa $i*32-0x80($Tbl),$Wi
+ paddd @MSG[0],$Wi
+ sha256msg2 @MSG[0],@MSG[1]
+ sha256rnds2 $ABEF,$CDGH # 16-19...
+ pshufd \$0x0e,$Wi,$Wi
+ movdqa @MSG[1],$TMP
+ palignr \$4,@MSG[0],$TMP
+ nop
+ paddd $TMP,@MSG[2]
+ sha256msg1 @MSG[0],@MSG[3]
+ sha256rnds2 $CDGH,$ABEF
+___
+ push(@MSG,shift(@MSG));
+}
+$code.=<<___;
+ movdqa 13*32-0x80($Tbl),$Wi
+ paddd @MSG[0],$Wi
+ sha256msg2 @MSG[0],@MSG[1]
+ sha256rnds2 $ABEF,$CDGH # 52-55
+ pshufd \$0x0e,$Wi,$Wi
+ movdqa @MSG[1],$TMP
+ palignr \$4,@MSG[0],$TMP
+ sha256rnds2 $CDGH,$ABEF
+ paddd $TMP,@MSG[2]
+
+ movdqa 14*32-0x80($Tbl),$Wi
+ paddd @MSG[1],$Wi
+ sha256rnds2 $ABEF,$CDGH # 56-59
+ pshufd \$0x0e,$Wi,$Wi
+ sha256msg2 @MSG[1],@MSG[2]
+ movdqa $BSWAP,$TMP
+ sha256rnds2 $CDGH,$ABEF
+
+ movdqa 15*32-0x80($Tbl),$Wi
+ paddd @MSG[2],$Wi
+ nop
+ sha256rnds2 $ABEF,$CDGH # 60-63
+ pshufd \$0x0e,$Wi,$Wi
+ dec $num
+ nop
+ sha256rnds2 $CDGH,$ABEF
+
+ paddd $CDGH_SAVE,$CDGH
+ paddd $ABEF_SAVE,$ABEF
+ jnz .Loop_shaext
+
+ pshufd \$0xb1,$CDGH,$CDGH # DCHG
+ pshufd \$0x1b,$ABEF,$TMP # FEBA
+ pshufd \$0xb1,$ABEF,$ABEF # BAFE
+ punpckhqdq $CDGH,$ABEF # DCBA
+ palignr \$8,$TMP,$CDGH # HGFE
+
+ movdqu $ABEF,($ctx)
+ movdqu $CDGH,16($ctx)
+___
+$code.=<<___ if ($win64);
+ movaps -8-5*16(%rax),%xmm6
+ movaps -8-4*16(%rax),%xmm7
+ movaps -8-3*16(%rax),%xmm8
+ movaps -8-2*16(%rax),%xmm9
+ movaps -8-1*16(%rax),%xmm10
+ mov %rax,%rsp
+.Lepilogue_shaext:
+___
+$code.=<<___;
+ ret
+.size sha256_block_data_order_shaext,.-sha256_block_data_order_shaext
+___
+}}}
+{{{
+
+my $a4=$T1;
+my ($a,$b,$c,$d,$e,$f,$g,$h);
+
+sub AUTOLOAD() # thunk [simplified] 32-bit style perlasm
+{ my $opcode = $AUTOLOAD; $opcode =~ s/.*:://;
+ my $arg = pop;
+ $arg = "\$$arg" if ($arg*1 eq $arg);
+ $code .= "\t$opcode\t".join(',',$arg,reverse @_)."\n";
+}
+
+sub body_00_15 () {
+ (
+ '($a,$b,$c,$d,$e,$f,$g,$h)=@ROT;'.
+
+ '&ror ($a0,$Sigma1[2]-$Sigma1[1])',
+ '&mov ($a,$a1)',
+ '&mov ($a4,$f)',
+
+ '&ror ($a1,$Sigma0[2]-$Sigma0[1])',
+ '&xor ($a0,$e)',
+ '&xor ($a4,$g)', # f^g
+
+ '&ror ($a0,$Sigma1[1]-$Sigma1[0])',
+ '&xor ($a1,$a)',
+ '&and ($a4,$e)', # (f^g)&e
+
+ '&xor ($a0,$e)',
+ '&add ($h,$SZ*($i&15)."(%rsp)")', # h+=X[i]+K[i]
+ '&mov ($a2,$a)',
+
+ '&xor ($a4,$g)', # Ch(e,f,g)=((f^g)&e)^g
+ '&ror ($a1,$Sigma0[1]-$Sigma0[0])',
+ '&xor ($a2,$b)', # a^b, b^c in next round
+
+ '&add ($h,$a4)', # h+=Ch(e,f,g)
+ '&ror ($a0,$Sigma1[0])', # Sigma1(e)
+ '&and ($a3,$a2)', # (b^c)&(a^b)
+
+ '&xor ($a1,$a)',
+ '&add ($h,$a0)', # h+=Sigma1(e)
+ '&xor ($a3,$b)', # Maj(a,b,c)=Ch(a^b,c,b)
+
+ '&ror ($a1,$Sigma0[0])', # Sigma0(a)
+ '&add ($d,$h)', # d+=h
+ '&add ($h,$a3)', # h+=Maj(a,b,c)
+
+ '&mov ($a0,$d)',
+ '&add ($a1,$h);'. # h+=Sigma0(a)
+ '($a2,$a3) = ($a3,$a2); unshift(@ROT,pop(@ROT)); $i++;'
+ );
+}
+
+######################################################################
+# SSSE3 code path
+#
+if ($SZ==4) { # SHA256 only
+my @X = map("%xmm$_",(0..3));
+my ($t0,$t1,$t2,$t3, $t4,$t5) = map("%xmm$_",(4..9));
+
+$code.=<<___;
+.type ${func}_ssse3,\@function,3
+.align 64
+${func}_ssse3:
+.Lssse3_shortcut:
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+ mov %rsp,%r11 # copy %rsp
+ shl \$4,%rdx # num*16
+ sub \$`$framesz+$win64*16*4`,%rsp
+ lea ($inp,%rdx,$SZ),%rdx # inp+num*16*$SZ
+ and \$-64,%rsp # align stack frame
+ mov $ctx,$_ctx # save ctx, 1st arg
+ mov $inp,$_inp # save inp, 2nd arh
+ mov %rdx,$_end # save end pointer, "3rd" arg
+ mov %r11,$_rsp # save copy of %rsp
+___
+$code.=<<___ if ($win64);
+ movaps %xmm6,16*$SZ+32(%rsp)
+ movaps %xmm7,16*$SZ+48(%rsp)
+ movaps %xmm8,16*$SZ+64(%rsp)
+ movaps %xmm9,16*$SZ+80(%rsp)
+___
+$code.=<<___;
+.Lprologue_ssse3:
+
+ mov $SZ*0($ctx),$A
+ mov $SZ*1($ctx),$B
+ mov $SZ*2($ctx),$C
+ mov $SZ*3($ctx),$D
+ mov $SZ*4($ctx),$E
+ mov $SZ*5($ctx),$F
+ mov $SZ*6($ctx),$G
+ mov $SZ*7($ctx),$H
+___
+
+$code.=<<___;
+ #movdqa $TABLE+`$SZ*2*$rounds`+32(%rip),$t4
+ #movdqa $TABLE+`$SZ*2*$rounds`+64(%rip),$t5
+ jmp .Lloop_ssse3
+.align 16
+.Lloop_ssse3:
+ movdqa $TABLE+`$SZ*2*$rounds`(%rip),$t3
+ movdqu 0x00($inp),@X[0]
+ movdqu 0x10($inp),@X[1]
+ movdqu 0x20($inp),@X[2]
+ pshufb $t3,@X[0]
+ movdqu 0x30($inp),@X[3]
+ lea $TABLE(%rip),$Tbl
+ pshufb $t3,@X[1]
+ movdqa 0x00($Tbl),$t0
+ movdqa 0x20($Tbl),$t1
+ pshufb $t3,@X[2]
+ paddd @X[0],$t0
+ movdqa 0x40($Tbl),$t2
+ pshufb $t3,@X[3]
+ movdqa 0x60($Tbl),$t3
+ paddd @X[1],$t1
+ paddd @X[2],$t2
+ paddd @X[3],$t3
+ movdqa $t0,0x00(%rsp)
+ mov $A,$a1
+ movdqa $t1,0x10(%rsp)
+ mov $B,$a3
+ movdqa $t2,0x20(%rsp)
+ xor $C,$a3 # magic
+ movdqa $t3,0x30(%rsp)
+ mov $E,$a0
+ jmp .Lssse3_00_47
+
+.align 16
+.Lssse3_00_47:
+ sub \$`-16*2*$SZ`,$Tbl # size optimization
+___
+sub Xupdate_256_SSSE3 () {
+ (
+ '&movdqa ($t0,@X[1]);',
+ '&movdqa ($t3,@X[3])',
+ '&palignr ($t0,@X[0],$SZ)', # X[1..4]
+ '&palignr ($t3,@X[2],$SZ);', # X[9..12]
+ '&movdqa ($t1,$t0)',
+ '&movdqa ($t2,$t0);',
+ '&psrld ($t0,$sigma0[2])',
+ '&paddd (@X[0],$t3);', # X[0..3] += X[9..12]
+ '&psrld ($t2,$sigma0[0])',
+ '&pshufd ($t3,@X[3],0b11111010)',# X[14..15]
+ '&pslld ($t1,8*$SZ-$sigma0[1]);'.
+ '&pxor ($t0,$t2)',
+ '&psrld ($t2,$sigma0[1]-$sigma0[0]);'.
+ '&pxor ($t0,$t1)',
+ '&pslld ($t1,$sigma0[1]-$sigma0[0]);'.
+ '&pxor ($t0,$t2);',
+ '&movdqa ($t2,$t3)',
+ '&pxor ($t0,$t1);', # sigma0(X[1..4])
+ '&psrld ($t3,$sigma1[2])',
+ '&paddd (@X[0],$t0);', # X[0..3] += sigma0(X[1..4])
+ '&psrlq ($t2,$sigma1[0])',
+ '&pxor ($t3,$t2);',
+ '&psrlq ($t2,$sigma1[1]-$sigma1[0])',
+ '&pxor ($t3,$t2)',
+ '&pshufb ($t3,$t4)', # sigma1(X[14..15])
+ '&paddd (@X[0],$t3)', # X[0..1] += sigma1(X[14..15])
+ '&pshufd ($t3,@X[0],0b01010000)',# X[16..17]
+ '&movdqa ($t2,$t3);',
+ '&psrld ($t3,$sigma1[2])',
+ '&psrlq ($t2,$sigma1[0])',
+ '&pxor ($t3,$t2);',
+ '&psrlq ($t2,$sigma1[1]-$sigma1[0])',
+ '&pxor ($t3,$t2);',
+ '&movdqa ($t2,16*2*$j."($Tbl)")',
+ '&pshufb ($t3,$t5)',
+ '&paddd (@X[0],$t3)' # X[2..3] += sigma1(X[16..17])
+ );
+}
+
+sub SSSE3_256_00_47 () {
+my $j = shift;
+my $body = shift;
+my @X = @_;
+my @insns = (&$body,&$body,&$body,&$body); # 104 instructions
+
+ if (0) {
+ foreach (Xupdate_256_SSSE3()) { # 36 instructions
+ eval;
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ }
+ } else { # squeeze extra 4% on Westmere and 19% on Atom
+ eval(shift(@insns)); #@
+ &movdqa ($t0,@X[1]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &movdqa ($t3,@X[3]);
+ eval(shift(@insns)); #@
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns)); #@
+ eval(shift(@insns));
+ &palignr ($t0,@X[0],$SZ); # X[1..4]
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &palignr ($t3,@X[2],$SZ); # X[9..12]
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns)); #@
+ &movdqa ($t1,$t0);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &movdqa ($t2,$t0);
+ eval(shift(@insns)); #@
+ eval(shift(@insns));
+ &psrld ($t0,$sigma0[2]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &paddd (@X[0],$t3); # X[0..3] += X[9..12]
+ eval(shift(@insns)); #@
+ eval(shift(@insns));
+ &psrld ($t2,$sigma0[0]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &pshufd ($t3,@X[3],0b11111010); # X[4..15]
+ eval(shift(@insns));
+ eval(shift(@insns)); #@
+ &pslld ($t1,8*$SZ-$sigma0[1]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &pxor ($t0,$t2);
+ eval(shift(@insns)); #@
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns)); #@
+ &psrld ($t2,$sigma0[1]-$sigma0[0]);
+ eval(shift(@insns));
+ &pxor ($t0,$t1);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &pslld ($t1,$sigma0[1]-$sigma0[0]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &pxor ($t0,$t2);
+ eval(shift(@insns));
+ eval(shift(@insns)); #@
+ &movdqa ($t2,$t3);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &pxor ($t0,$t1); # sigma0(X[1..4])
+ eval(shift(@insns)); #@
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &psrld ($t3,$sigma1[2]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &paddd (@X[0],$t0); # X[0..3] += sigma0(X[1..4])
+ eval(shift(@insns)); #@
+ eval(shift(@insns));
+ &psrlq ($t2,$sigma1[0]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &pxor ($t3,$t2);
+ eval(shift(@insns)); #@
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns)); #@
+ &psrlq ($t2,$sigma1[1]-$sigma1[0]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &pxor ($t3,$t2);
+ eval(shift(@insns)); #@
+ eval(shift(@insns));
+ eval(shift(@insns));
+ #&pshufb ($t3,$t4); # sigma1(X[14..15])
+ &pshufd ($t3,$t3,0b10000000);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &psrldq ($t3,8);
+ eval(shift(@insns));
+ eval(shift(@insns)); #@
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns)); #@
+ &paddd (@X[0],$t3); # X[0..1] += sigma1(X[14..15])
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &pshufd ($t3,@X[0],0b01010000); # X[16..17]
+ eval(shift(@insns));
+ eval(shift(@insns)); #@
+ eval(shift(@insns));
+ &movdqa ($t2,$t3);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &psrld ($t3,$sigma1[2]);
+ eval(shift(@insns));
+ eval(shift(@insns)); #@
+ &psrlq ($t2,$sigma1[0]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &pxor ($t3,$t2);
+ eval(shift(@insns)); #@
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns)); #@
+ eval(shift(@insns));
+ &psrlq ($t2,$sigma1[1]-$sigma1[0]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &pxor ($t3,$t2);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns)); #@
+ #&pshufb ($t3,$t5);
+ &pshufd ($t3,$t3,0b00001000);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &movdqa ($t2,16*2*$j."($Tbl)");
+ eval(shift(@insns)); #@
+ eval(shift(@insns));
+ &pslldq ($t3,8);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &paddd (@X[0],$t3); # X[2..3] += sigma1(X[16..17])
+ eval(shift(@insns)); #@
+ eval(shift(@insns));
+ eval(shift(@insns));
+ }
+ &paddd ($t2,@X[0]);
+ foreach (@insns) { eval; } # remaining instructions
+ &movdqa (16*$j."(%rsp)",$t2);
+}
+
+ for ($i=0,$j=0; $j<4; $j++) {
+ &SSSE3_256_00_47($j,\&body_00_15,@X);
+ push(@X,shift(@X)); # rotate(@X)
+ }
+ &cmpb ($SZ-1+16*2*$SZ."($Tbl)",0);
+ &jne (".Lssse3_00_47");
+
+ for ($i=0; $i<16; ) {
+ foreach(body_00_15()) { eval; }
+ }
+$code.=<<___;
+ mov $_ctx,$ctx
+ mov $a1,$A
+
+ add $SZ*0($ctx),$A
+ lea 16*$SZ($inp),$inp
+ add $SZ*1($ctx),$B
+ add $SZ*2($ctx),$C
+ add $SZ*3($ctx),$D
+ add $SZ*4($ctx),$E
+ add $SZ*5($ctx),$F
+ add $SZ*6($ctx),$G
+ add $SZ*7($ctx),$H
+
+ cmp $_end,$inp
+
+ mov $A,$SZ*0($ctx)
+ mov $B,$SZ*1($ctx)
+ mov $C,$SZ*2($ctx)
+ mov $D,$SZ*3($ctx)
+ mov $E,$SZ*4($ctx)
+ mov $F,$SZ*5($ctx)
+ mov $G,$SZ*6($ctx)
+ mov $H,$SZ*7($ctx)
+ jb .Lloop_ssse3
+
+ mov $_rsp,%rsi
+___
+$code.=<<___ if ($win64);
+ movaps 16*$SZ+32(%rsp),%xmm6
+ movaps 16*$SZ+48(%rsp),%xmm7
+ movaps 16*$SZ+64(%rsp),%xmm8
+ movaps 16*$SZ+80(%rsp),%xmm9
+___
+$code.=<<___;
+ mov (%rsi),%r15
+ mov 8(%rsi),%r14
+ mov 16(%rsi),%r13
+ mov 24(%rsi),%r12
+ mov 32(%rsi),%rbp
+ mov 40(%rsi),%rbx
+ lea 48(%rsi),%rsp
+.Lepilogue_ssse3:
+ ret
+.size ${func}_ssse3,.-${func}_ssse3
+___
+}
+
+if ($avx) {{
+######################################################################
+# XOP code path
+#
+if ($SZ==8) { # SHA512 only
+$code.=<<___;
+.type ${func}_xop,\@function,3
+.align 64
+${func}_xop:
+.Lxop_shortcut:
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+ mov %rsp,%r11 # copy %rsp
+ shl \$4,%rdx # num*16
+ sub \$`$framesz+$win64*16*($SZ==4?4:6)`,%rsp
+ lea ($inp,%rdx,$SZ),%rdx # inp+num*16*$SZ
+ and \$-64,%rsp # align stack frame
+ mov $ctx,$_ctx # save ctx, 1st arg
+ mov $inp,$_inp # save inp, 2nd arh
+ mov %rdx,$_end # save end pointer, "3rd" arg
+ mov %r11,$_rsp # save copy of %rsp
+___
+$code.=<<___ if ($win64);
+ movaps %xmm6,16*$SZ+32(%rsp)
+ movaps %xmm7,16*$SZ+48(%rsp)
+ movaps %xmm8,16*$SZ+64(%rsp)
+ movaps %xmm9,16*$SZ+80(%rsp)
+___
+$code.=<<___ if ($win64 && $SZ>4);
+ movaps %xmm10,16*$SZ+96(%rsp)
+ movaps %xmm11,16*$SZ+112(%rsp)
+___
+$code.=<<___;
+.Lprologue_xop:
+
+ vzeroupper
+ mov $SZ*0($ctx),$A
+ mov $SZ*1($ctx),$B
+ mov $SZ*2($ctx),$C
+ mov $SZ*3($ctx),$D
+ mov $SZ*4($ctx),$E
+ mov $SZ*5($ctx),$F
+ mov $SZ*6($ctx),$G
+ mov $SZ*7($ctx),$H
+ jmp .Lloop_xop
+___
+ if ($SZ==4) { # SHA256
+ my @X = map("%xmm$_",(0..3));
+ my ($t0,$t1,$t2,$t3) = map("%xmm$_",(4..7));
+
+$code.=<<___;
+.align 16
+.Lloop_xop:
+ vmovdqa $TABLE+`$SZ*2*$rounds`(%rip),$t3
+ vmovdqu 0x00($inp),@X[0]
+ vmovdqu 0x10($inp),@X[1]
+ vmovdqu 0x20($inp),@X[2]
+ vmovdqu 0x30($inp),@X[3]
+ vpshufb $t3,@X[0],@X[0]
+ lea $TABLE(%rip),$Tbl
+ vpshufb $t3,@X[1],@X[1]
+ vpshufb $t3,@X[2],@X[2]
+ vpaddd 0x00($Tbl),@X[0],$t0
+ vpshufb $t3,@X[3],@X[3]
+ vpaddd 0x20($Tbl),@X[1],$t1
+ vpaddd 0x40($Tbl),@X[2],$t2
+ vpaddd 0x60($Tbl),@X[3],$t3
+ vmovdqa $t0,0x00(%rsp)
+ mov $A,$a1
+ vmovdqa $t1,0x10(%rsp)
+ mov $B,$a3
+ vmovdqa $t2,0x20(%rsp)
+ xor $C,$a3 # magic
+ vmovdqa $t3,0x30(%rsp)
+ mov $E,$a0
+ jmp .Lxop_00_47
+
+.align 16
+.Lxop_00_47:
+ sub \$`-16*2*$SZ`,$Tbl # size optimization
+___
+sub XOP_256_00_47 () {
+my $j = shift;
+my $body = shift;
+my @X = @_;
+my @insns = (&$body,&$body,&$body,&$body); # 104 instructions
+
+ &vpalignr ($t0,@X[1],@X[0],$SZ); # X[1..4]
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vpalignr ($t3,@X[3],@X[2],$SZ); # X[9..12]
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vprotd ($t1,$t0,8*$SZ-$sigma0[1]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vpsrld ($t0,$t0,$sigma0[2]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vpaddd (@X[0],@X[0],$t3); # X[0..3] += X[9..12]
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vprotd ($t2,$t1,$sigma0[1]-$sigma0[0]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vpxor ($t0,$t0,$t1);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vprotd ($t3,@X[3],8*$SZ-$sigma1[1]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vpxor ($t0,$t0,$t2); # sigma0(X[1..4])
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vpsrld ($t2,@X[3],$sigma1[2]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vpaddd (@X[0],@X[0],$t0); # X[0..3] += sigma0(X[1..4])
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vprotd ($t1,$t3,$sigma1[1]-$sigma1[0]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vpxor ($t3,$t3,$t2);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vpxor ($t3,$t3,$t1); # sigma1(X[14..15])
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vpsrldq ($t3,$t3,8);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vpaddd (@X[0],@X[0],$t3); # X[0..1] += sigma1(X[14..15])
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vprotd ($t3,@X[0],8*$SZ-$sigma1[1]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vpsrld ($t2,@X[0],$sigma1[2]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vprotd ($t1,$t3,$sigma1[1]-$sigma1[0]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vpxor ($t3,$t3,$t2);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vpxor ($t3,$t3,$t1); # sigma1(X[16..17])
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vpslldq ($t3,$t3,8); # 22 instructions
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vpaddd (@X[0],@X[0],$t3); # X[2..3] += sigma1(X[16..17])
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vpaddd ($t2,@X[0],16*2*$j."($Tbl)");
+ foreach (@insns) { eval; } # remaining instructions
+ &vmovdqa (16*$j."(%rsp)",$t2);
+}
+
+ for ($i=0,$j=0; $j<4; $j++) {
+ &XOP_256_00_47($j,\&body_00_15,@X);
+ push(@X,shift(@X)); # rotate(@X)
+ }
+ &cmpb ($SZ-1+16*2*$SZ."($Tbl)",0);
+ &jne (".Lxop_00_47");
+
+ for ($i=0; $i<16; ) {
+ foreach(body_00_15()) { eval; }
+ }
+
+ } else { # SHA512
+ my @X = map("%xmm$_",(0..7));
+ my ($t0,$t1,$t2,$t3) = map("%xmm$_",(8..11));
+
+$code.=<<___;
+.align 16
+.Lloop_xop:
+ vmovdqa $TABLE+`$SZ*2*$rounds`(%rip),$t3
+ vmovdqu 0x00($inp),@X[0]
+ lea $TABLE+0x80(%rip),$Tbl # size optimization
+ vmovdqu 0x10($inp),@X[1]
+ vmovdqu 0x20($inp),@X[2]
+ vpshufb $t3,@X[0],@X[0]
+ vmovdqu 0x30($inp),@X[3]
+ vpshufb $t3,@X[1],@X[1]
+ vmovdqu 0x40($inp),@X[4]
+ vpshufb $t3,@X[2],@X[2]
+ vmovdqu 0x50($inp),@X[5]
+ vpshufb $t3,@X[3],@X[3]
+ vmovdqu 0x60($inp),@X[6]
+ vpshufb $t3,@X[4],@X[4]
+ vmovdqu 0x70($inp),@X[7]
+ vpshufb $t3,@X[5],@X[5]
+ vpaddq -0x80($Tbl),@X[0],$t0
+ vpshufb $t3,@X[6],@X[6]
+ vpaddq -0x60($Tbl),@X[1],$t1
+ vpshufb $t3,@X[7],@X[7]
+ vpaddq -0x40($Tbl),@X[2],$t2
+ vpaddq -0x20($Tbl),@X[3],$t3
+ vmovdqa $t0,0x00(%rsp)
+ vpaddq 0x00($Tbl),@X[4],$t0
+ vmovdqa $t1,0x10(%rsp)
+ vpaddq 0x20($Tbl),@X[5],$t1
+ vmovdqa $t2,0x20(%rsp)
+ vpaddq 0x40($Tbl),@X[6],$t2
+ vmovdqa $t3,0x30(%rsp)
+ vpaddq 0x60($Tbl),@X[7],$t3
+ vmovdqa $t0,0x40(%rsp)
+ mov $A,$a1
+ vmovdqa $t1,0x50(%rsp)
+ mov $B,$a3
+ vmovdqa $t2,0x60(%rsp)
+ xor $C,$a3 # magic
+ vmovdqa $t3,0x70(%rsp)
+ mov $E,$a0
+ jmp .Lxop_00_47
+
+.align 16
+.Lxop_00_47:
+ add \$`16*2*$SZ`,$Tbl
+___
+sub XOP_512_00_47 () {
+my $j = shift;
+my $body = shift;
+my @X = @_;
+my @insns = (&$body,&$body); # 52 instructions
+
+ &vpalignr ($t0,@X[1],@X[0],$SZ); # X[1..2]
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vpalignr ($t3,@X[5],@X[4],$SZ); # X[9..10]
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vprotq ($t1,$t0,8*$SZ-$sigma0[1]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vpsrlq ($t0,$t0,$sigma0[2]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vpaddq (@X[0],@X[0],$t3); # X[0..1] += X[9..10]
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vprotq ($t2,$t1,$sigma0[1]-$sigma0[0]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vpxor ($t0,$t0,$t1);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vprotq ($t3,@X[7],8*$SZ-$sigma1[1]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vpxor ($t0,$t0,$t2); # sigma0(X[1..2])
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vpsrlq ($t2,@X[7],$sigma1[2]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vpaddq (@X[0],@X[0],$t0); # X[0..1] += sigma0(X[1..2])
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vprotq ($t1,$t3,$sigma1[1]-$sigma1[0]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vpxor ($t3,$t3,$t2);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vpxor ($t3,$t3,$t1); # sigma1(X[14..15])
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vpaddq (@X[0],@X[0],$t3); # X[0..1] += sigma1(X[14..15])
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &vpaddq ($t2,@X[0],16*2*$j-0x80."($Tbl)");
+ foreach (@insns) { eval; } # remaining instructions
+ &vmovdqa (16*$j."(%rsp)",$t2);
+}
+
+ for ($i=0,$j=0; $j<8; $j++) {
+ &XOP_512_00_47($j,\&body_00_15,@X);
+ push(@X,shift(@X)); # rotate(@X)
+ }
+ &cmpb ($SZ-1+16*2*$SZ-0x80."($Tbl)",0);
+ &jne (".Lxop_00_47");
+
+ for ($i=0; $i<16; ) {
+ foreach(body_00_15()) { eval; }
+ }
+}
+$code.=<<___;
+ mov $_ctx,$ctx
+ mov $a1,$A
+
+ add $SZ*0($ctx),$A
+ lea 16*$SZ($inp),$inp
+ add $SZ*1($ctx),$B
+ add $SZ*2($ctx),$C
+ add $SZ*3($ctx),$D
+ add $SZ*4($ctx),$E
+ add $SZ*5($ctx),$F
+ add $SZ*6($ctx),$G
+ add $SZ*7($ctx),$H
+
+ cmp $_end,$inp
+
+ mov $A,$SZ*0($ctx)
+ mov $B,$SZ*1($ctx)
+ mov $C,$SZ*2($ctx)
+ mov $D,$SZ*3($ctx)
+ mov $E,$SZ*4($ctx)
+ mov $F,$SZ*5($ctx)
+ mov $G,$SZ*6($ctx)
+ mov $H,$SZ*7($ctx)
+ jb .Lloop_xop
+
+ mov $_rsp,%rsi
+ vzeroupper
+___
+$code.=<<___ if ($win64);
+ movaps 16*$SZ+32(%rsp),%xmm6
+ movaps 16*$SZ+48(%rsp),%xmm7
+ movaps 16*$SZ+64(%rsp),%xmm8
+ movaps 16*$SZ+80(%rsp),%xmm9
+___
+$code.=<<___ if ($win64 && $SZ>4);
+ movaps 16*$SZ+96(%rsp),%xmm10
+ movaps 16*$SZ+112(%rsp),%xmm11
+___
+$code.=<<___;
+ mov (%rsi),%r15
+ mov 8(%rsi),%r14
+ mov 16(%rsi),%r13
+ mov 24(%rsi),%r12
+ mov 32(%rsi),%rbp
+ mov 40(%rsi),%rbx
+ lea 48(%rsi),%rsp
+.Lepilogue_xop:
+ ret
+.size ${func}_xop,.-${func}_xop
+___
+}
+######################################################################
+# AVX+shrd code path
+#
+local *ror = sub { &shrd(@_[0],@_) };
+
+$code.=<<___;
+.type ${func}_avx,\@function,3
+.align 64
+${func}_avx:
+.Lavx_shortcut:
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+ mov %rsp,%r11 # copy %rsp
+ shl \$4,%rdx # num*16
+ sub \$`$framesz+$win64*16*($SZ==4?4:6)`,%rsp
+ lea ($inp,%rdx,$SZ),%rdx # inp+num*16*$SZ
+ and \$-64,%rsp # align stack frame
+ mov $ctx,$_ctx # save ctx, 1st arg
+ mov $inp,$_inp # save inp, 2nd arh
+ mov %rdx,$_end # save end pointer, "3rd" arg
+ mov %r11,$_rsp # save copy of %rsp
+___
+$code.=<<___ if ($win64);
+ movaps %xmm6,16*$SZ+32(%rsp)
+ movaps %xmm7,16*$SZ+48(%rsp)
+ movaps %xmm8,16*$SZ+64(%rsp)
+ movaps %xmm9,16*$SZ+80(%rsp)
+___
+$code.=<<___ if ($win64 && $SZ>4);
+ movaps %xmm10,16*$SZ+96(%rsp)
+ movaps %xmm11,16*$SZ+112(%rsp)
+___
+$code.=<<___;
+.Lprologue_avx:
+
+ vzeroupper
+ mov $SZ*0($ctx),$A
+ mov $SZ*1($ctx),$B
+ mov $SZ*2($ctx),$C
+ mov $SZ*3($ctx),$D
+ mov $SZ*4($ctx),$E
+ mov $SZ*5($ctx),$F
+ mov $SZ*6($ctx),$G
+ mov $SZ*7($ctx),$H
+___
+ if ($SZ==4) { # SHA256
+ my @X = map("%xmm$_",(0..3));
+ my ($t0,$t1,$t2,$t3, $t4,$t5) = map("%xmm$_",(4..9));
+
+$code.=<<___;
+ vmovdqa $TABLE+`$SZ*2*$rounds`+32(%rip),$t4
+ vmovdqa $TABLE+`$SZ*2*$rounds`+64(%rip),$t5
+ jmp .Lloop_avx
+.align 16
+.Lloop_avx:
+ vmovdqa $TABLE+`$SZ*2*$rounds`(%rip),$t3
+ vmovdqu 0x00($inp),@X[0]
+ vmovdqu 0x10($inp),@X[1]
+ vmovdqu 0x20($inp),@X[2]
+ vmovdqu 0x30($inp),@X[3]
+ vpshufb $t3,@X[0],@X[0]
+ lea $TABLE(%rip),$Tbl
+ vpshufb $t3,@X[1],@X[1]
+ vpshufb $t3,@X[2],@X[2]
+ vpaddd 0x00($Tbl),@X[0],$t0
+ vpshufb $t3,@X[3],@X[3]
+ vpaddd 0x20($Tbl),@X[1],$t1
+ vpaddd 0x40($Tbl),@X[2],$t2
+ vpaddd 0x60($Tbl),@X[3],$t3
+ vmovdqa $t0,0x00(%rsp)
+ mov $A,$a1
+ vmovdqa $t1,0x10(%rsp)
+ mov $B,$a3
+ vmovdqa $t2,0x20(%rsp)
+ xor $C,$a3 # magic
+ vmovdqa $t3,0x30(%rsp)
+ mov $E,$a0
+ jmp .Lavx_00_47
+
+.align 16
+.Lavx_00_47:
+ sub \$`-16*2*$SZ`,$Tbl # size optimization
+___
+sub Xupdate_256_AVX () {
+ (
+ '&vpalignr ($t0,@X[1],@X[0],$SZ)', # X[1..4]
+ '&vpalignr ($t3,@X[3],@X[2],$SZ)', # X[9..12]
+ '&vpsrld ($t2,$t0,$sigma0[0]);',
+ '&vpaddd (@X[0],@X[0],$t3)', # X[0..3] += X[9..12]
+ '&vpsrld ($t3,$t0,$sigma0[2])',
+ '&vpslld ($t1,$t0,8*$SZ-$sigma0[1]);',
+ '&vpxor ($t0,$t3,$t2)',
+ '&vpshufd ($t3,@X[3],0b11111010)',# X[14..15]
+ '&vpsrld ($t2,$t2,$sigma0[1]-$sigma0[0]);',
+ '&vpxor ($t0,$t0,$t1)',
+ '&vpslld ($t1,$t1,$sigma0[1]-$sigma0[0]);',
+ '&vpxor ($t0,$t0,$t2)',
+ '&vpsrld ($t2,$t3,$sigma1[2]);',
+ '&vpxor ($t0,$t0,$t1)', # sigma0(X[1..4])
+ '&vpsrlq ($t3,$t3,$sigma1[0]);',
+ '&vpaddd (@X[0],@X[0],$t0)', # X[0..3] += sigma0(X[1..4])
+ '&vpxor ($t2,$t2,$t3);',
+ '&vpsrlq ($t3,$t3,$sigma1[1]-$sigma1[0])',
+ '&vpxor ($t2,$t2,$t3)',
+ '&vpshufb ($t2,$t2,$t4)', # sigma1(X[14..15])
+ '&vpaddd (@X[0],@X[0],$t2)', # X[0..1] += sigma1(X[14..15])
+ '&vpshufd ($t3,@X[0],0b01010000)',# X[16..17]
+ '&vpsrld ($t2,$t3,$sigma1[2])',
+ '&vpsrlq ($t3,$t3,$sigma1[0])',
+ '&vpxor ($t2,$t2,$t3);',
+ '&vpsrlq ($t3,$t3,$sigma1[1]-$sigma1[0])',
+ '&vpxor ($t2,$t2,$t3)',
+ '&vpshufb ($t2,$t2,$t5)',
+ '&vpaddd (@X[0],@X[0],$t2)' # X[2..3] += sigma1(X[16..17])
+ );
+}
+
+sub AVX_256_00_47 () {
+my $j = shift;
+my $body = shift;
+my @X = @_;
+my @insns = (&$body,&$body,&$body,&$body); # 104 instructions
+
+ foreach (Xupdate_256_AVX()) { # 29 instructions
+ eval;
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ }
+ &vpaddd ($t2,@X[0],16*2*$j."($Tbl)");
+ foreach (@insns) { eval; } # remaining instructions
+ &vmovdqa (16*$j."(%rsp)",$t2);
+}
+
+ for ($i=0,$j=0; $j<4; $j++) {
+ &AVX_256_00_47($j,\&body_00_15,@X);
+ push(@X,shift(@X)); # rotate(@X)
+ }
+ &cmpb ($SZ-1+16*2*$SZ."($Tbl)",0);
+ &jne (".Lavx_00_47");
+
+ for ($i=0; $i<16; ) {
+ foreach(body_00_15()) { eval; }
+ }
+
+ } else { # SHA512
+ my @X = map("%xmm$_",(0..7));
+ my ($t0,$t1,$t2,$t3) = map("%xmm$_",(8..11));
+
+$code.=<<___;
+ jmp .Lloop_avx
+.align 16
+.Lloop_avx:
+ vmovdqa $TABLE+`$SZ*2*$rounds`(%rip),$t3
+ vmovdqu 0x00($inp),@X[0]
+ lea $TABLE+0x80(%rip),$Tbl # size optimization
+ vmovdqu 0x10($inp),@X[1]
+ vmovdqu 0x20($inp),@X[2]
+ vpshufb $t3,@X[0],@X[0]
+ vmovdqu 0x30($inp),@X[3]
+ vpshufb $t3,@X[1],@X[1]
+ vmovdqu 0x40($inp),@X[4]
+ vpshufb $t3,@X[2],@X[2]
+ vmovdqu 0x50($inp),@X[5]
+ vpshufb $t3,@X[3],@X[3]
+ vmovdqu 0x60($inp),@X[6]
+ vpshufb $t3,@X[4],@X[4]
+ vmovdqu 0x70($inp),@X[7]
+ vpshufb $t3,@X[5],@X[5]
+ vpaddq -0x80($Tbl),@X[0],$t0
+ vpshufb $t3,@X[6],@X[6]
+ vpaddq -0x60($Tbl),@X[1],$t1
+ vpshufb $t3,@X[7],@X[7]
+ vpaddq -0x40($Tbl),@X[2],$t2
+ vpaddq -0x20($Tbl),@X[3],$t3
+ vmovdqa $t0,0x00(%rsp)
+ vpaddq 0x00($Tbl),@X[4],$t0
+ vmovdqa $t1,0x10(%rsp)
+ vpaddq 0x20($Tbl),@X[5],$t1
+ vmovdqa $t2,0x20(%rsp)
+ vpaddq 0x40($Tbl),@X[6],$t2
+ vmovdqa $t3,0x30(%rsp)
+ vpaddq 0x60($Tbl),@X[7],$t3
+ vmovdqa $t0,0x40(%rsp)
+ mov $A,$a1
+ vmovdqa $t1,0x50(%rsp)
+ mov $B,$a3
+ vmovdqa $t2,0x60(%rsp)
+ xor $C,$a3 # magic
+ vmovdqa $t3,0x70(%rsp)
+ mov $E,$a0
+ jmp .Lavx_00_47
+
+.align 16
+.Lavx_00_47:
+ add \$`16*2*$SZ`,$Tbl
+___
+sub Xupdate_512_AVX () {
+ (
+ '&vpalignr ($t0,@X[1],@X[0],$SZ)', # X[1..2]
+ '&vpalignr ($t3,@X[5],@X[4],$SZ)', # X[9..10]
+ '&vpsrlq ($t2,$t0,$sigma0[0])',
+ '&vpaddq (@X[0],@X[0],$t3);', # X[0..1] += X[9..10]
+ '&vpsrlq ($t3,$t0,$sigma0[2])',
+ '&vpsllq ($t1,$t0,8*$SZ-$sigma0[1]);',
+ '&vpxor ($t0,$t3,$t2)',
+ '&vpsrlq ($t2,$t2,$sigma0[1]-$sigma0[0]);',
+ '&vpxor ($t0,$t0,$t1)',
+ '&vpsllq ($t1,$t1,$sigma0[1]-$sigma0[0]);',
+ '&vpxor ($t0,$t0,$t2)',
+ '&vpsrlq ($t3,@X[7],$sigma1[2]);',
+ '&vpxor ($t0,$t0,$t1)', # sigma0(X[1..2])
+ '&vpsllq ($t2,@X[7],8*$SZ-$sigma1[1]);',
+ '&vpaddq (@X[0],@X[0],$t0)', # X[0..1] += sigma0(X[1..2])
+ '&vpsrlq ($t1,@X[7],$sigma1[0]);',
+ '&vpxor ($t3,$t3,$t2)',
+ '&vpsllq ($t2,$t2,$sigma1[1]-$sigma1[0]);',
+ '&vpxor ($t3,$t3,$t1)',
+ '&vpsrlq ($t1,$t1,$sigma1[1]-$sigma1[0]);',
+ '&vpxor ($t3,$t3,$t2)',
+ '&vpxor ($t3,$t3,$t1)', # sigma1(X[14..15])
+ '&vpaddq (@X[0],@X[0],$t3)', # X[0..1] += sigma1(X[14..15])
+ );
+}
+
+sub AVX_512_00_47 () {
+my $j = shift;
+my $body = shift;
+my @X = @_;
+my @insns = (&$body,&$body); # 52 instructions
+
+ foreach (Xupdate_512_AVX()) { # 23 instructions
+ eval;
+ eval(shift(@insns));
+ eval(shift(@insns));
+ }
+ &vpaddq ($t2,@X[0],16*2*$j-0x80."($Tbl)");
+ foreach (@insns) { eval; } # remaining instructions
+ &vmovdqa (16*$j."(%rsp)",$t2);
+}
+
+ for ($i=0,$j=0; $j<8; $j++) {
+ &AVX_512_00_47($j,\&body_00_15,@X);
+ push(@X,shift(@X)); # rotate(@X)
+ }
+ &cmpb ($SZ-1+16*2*$SZ-0x80."($Tbl)",0);
+ &jne (".Lavx_00_47");
+
+ for ($i=0; $i<16; ) {
+ foreach(body_00_15()) { eval; }
+ }
+}
+$code.=<<___;
+ mov $_ctx,$ctx
+ mov $a1,$A
+
+ add $SZ*0($ctx),$A
+ lea 16*$SZ($inp),$inp
+ add $SZ*1($ctx),$B
+ add $SZ*2($ctx),$C
+ add $SZ*3($ctx),$D
+ add $SZ*4($ctx),$E
+ add $SZ*5($ctx),$F
+ add $SZ*6($ctx),$G
+ add $SZ*7($ctx),$H
+
+ cmp $_end,$inp
+
+ mov $A,$SZ*0($ctx)
+ mov $B,$SZ*1($ctx)
+ mov $C,$SZ*2($ctx)
+ mov $D,$SZ*3($ctx)
+ mov $E,$SZ*4($ctx)
+ mov $F,$SZ*5($ctx)
+ mov $G,$SZ*6($ctx)
+ mov $H,$SZ*7($ctx)
+ jb .Lloop_avx
+
+ mov $_rsp,%rsi
+ vzeroupper
+___
+$code.=<<___ if ($win64);
+ movaps 16*$SZ+32(%rsp),%xmm6
+ movaps 16*$SZ+48(%rsp),%xmm7
+ movaps 16*$SZ+64(%rsp),%xmm8
+ movaps 16*$SZ+80(%rsp),%xmm9
+___
+$code.=<<___ if ($win64 && $SZ>4);
+ movaps 16*$SZ+96(%rsp),%xmm10
+ movaps 16*$SZ+112(%rsp),%xmm11
+___
+$code.=<<___;
+ mov (%rsi),%r15
+ mov 8(%rsi),%r14
+ mov 16(%rsi),%r13
+ mov 24(%rsi),%r12
+ mov 32(%rsi),%rbp
+ mov 40(%rsi),%rbx
+ lea 48(%rsi),%rsp
+.Lepilogue_avx:
+ ret
+.size ${func}_avx,.-${func}_avx
+___
+
+if ($avx>1) {{
+######################################################################
+# AVX2+BMI code path
+#
+my $a5=$SZ==4?"%esi":"%rsi"; # zap $inp
+my $PUSH8=8*2*$SZ;
+use integer;
+
+sub bodyx_00_15 () {
+ # at start $a1 should be zero, $a3 - $b^$c and $a4 copy of $f
+ (
+ '($a,$b,$c,$d,$e,$f,$g,$h)=@ROT;'.
+
+ '&add ($h,(32*($i/(16/$SZ))+$SZ*($i%(16/$SZ)))%$PUSH8.$base)', # h+=X[i]+K[i]
+ '&and ($a4,$e)', # f&e
+ '&rorx ($a0,$e,$Sigma1[2])',
+ '&rorx ($a2,$e,$Sigma1[1])',
+
+ '&lea ($a,"($a,$a1)")', # h+=Sigma0(a) from the past
+ '&lea ($h,"($h,$a4)")',
+ '&andn ($a4,$e,$g)', # ~e&g
+ '&xor ($a0,$a2)',
+
+ '&rorx ($a1,$e,$Sigma1[0])',
+ '&lea ($h,"($h,$a4)")', # h+=Ch(e,f,g)=(e&f)+(~e&g)
+ '&xor ($a0,$a1)', # Sigma1(e)
+ '&mov ($a2,$a)',
+
+ '&rorx ($a4,$a,$Sigma0[2])',
+ '&lea ($h,"($h,$a0)")', # h+=Sigma1(e)
+ '&xor ($a2,$b)', # a^b, b^c in next round
+ '&rorx ($a1,$a,$Sigma0[1])',
+
+ '&rorx ($a0,$a,$Sigma0[0])',
+ '&lea ($d,"($d,$h)")', # d+=h
+ '&and ($a3,$a2)', # (b^c)&(a^b)
+ '&xor ($a1,$a4)',
+
+ '&xor ($a3,$b)', # Maj(a,b,c)=Ch(a^b,c,b)
+ '&xor ($a1,$a0)', # Sigma0(a)
+ '&lea ($h,"($h,$a3)");'. # h+=Maj(a,b,c)
+ '&mov ($a4,$e)', # copy of f in future
+
+ '($a2,$a3) = ($a3,$a2); unshift(@ROT,pop(@ROT)); $i++;'
+ );
+ # and at the finish one has to $a+=$a1
+}
+
+$code.=<<___;
+.type ${func}_avx2,\@function,3
+.align 64
+${func}_avx2:
+.Lavx2_shortcut:
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+ mov %rsp,%r11 # copy %rsp
+ sub \$`2*$SZ*$rounds+4*8+$win64*16*($SZ==4?4:6)`,%rsp
+ shl \$4,%rdx # num*16
+ and \$-256*$SZ,%rsp # align stack frame
+ lea ($inp,%rdx,$SZ),%rdx # inp+num*16*$SZ
+ add \$`2*$SZ*($rounds-8)`,%rsp
+ mov $ctx,$_ctx # save ctx, 1st arg
+ mov $inp,$_inp # save inp, 2nd arh
+ mov %rdx,$_end # save end pointer, "3rd" arg
+ mov %r11,$_rsp # save copy of %rsp
+___
+$code.=<<___ if ($win64);
+ movaps %xmm6,16*$SZ+32(%rsp)
+ movaps %xmm7,16*$SZ+48(%rsp)
+ movaps %xmm8,16*$SZ+64(%rsp)
+ movaps %xmm9,16*$SZ+80(%rsp)
+___
+$code.=<<___ if ($win64 && $SZ>4);
+ movaps %xmm10,16*$SZ+96(%rsp)
+ movaps %xmm11,16*$SZ+112(%rsp)
+___
+$code.=<<___;
+.Lprologue_avx2:
+
+ vzeroupper
+ sub \$-16*$SZ,$inp # inp++, size optimization
+ mov $SZ*0($ctx),$A
+ mov $inp,%r12 # borrow $T1
+ mov $SZ*1($ctx),$B
+ cmp %rdx,$inp # $_end
+ mov $SZ*2($ctx),$C
+ cmove %rsp,%r12 # next block or random data
+ mov $SZ*3($ctx),$D
+ mov $SZ*4($ctx),$E
+ mov $SZ*5($ctx),$F
+ mov $SZ*6($ctx),$G
+ mov $SZ*7($ctx),$H
+___
+ if ($SZ==4) { # SHA256
+ my @X = map("%ymm$_",(0..3));
+ my ($t0,$t1,$t2,$t3, $t4,$t5) = map("%ymm$_",(4..9));
+
+$code.=<<___;
+ vmovdqa $TABLE+`$SZ*2*$rounds`+32(%rip),$t4
+ vmovdqa $TABLE+`$SZ*2*$rounds`+64(%rip),$t5
+ jmp .Loop_avx2
+.align 16
+.Loop_avx2:
+ vmovdqa $TABLE+`$SZ*2*$rounds`(%rip),$t3
+ vmovdqu -16*$SZ+0($inp),%xmm0
+ vmovdqu -16*$SZ+16($inp),%xmm1
+ vmovdqu -16*$SZ+32($inp),%xmm2
+ vmovdqu -16*$SZ+48($inp),%xmm3
+ #mov $inp,$_inp # offload $inp
+ vinserti128 \$1,(%r12),@X[0],@X[0]
+ vinserti128 \$1,16(%r12),@X[1],@X[1]
+ vpshufb $t3,@X[0],@X[0]
+ vinserti128 \$1,32(%r12),@X[2],@X[2]
+ vpshufb $t3,@X[1],@X[1]
+ vinserti128 \$1,48(%r12),@X[3],@X[3]
+
+ lea $TABLE(%rip),$Tbl
+ vpshufb $t3,@X[2],@X[2]
+ vpaddd 0x00($Tbl),@X[0],$t0
+ vpshufb $t3,@X[3],@X[3]
+ vpaddd 0x20($Tbl),@X[1],$t1
+ vpaddd 0x40($Tbl),@X[2],$t2
+ vpaddd 0x60($Tbl),@X[3],$t3
+ vmovdqa $t0,0x00(%rsp)
+ xor $a1,$a1
+ vmovdqa $t1,0x20(%rsp)
+ lea -$PUSH8(%rsp),%rsp
+ mov $B,$a3
+ vmovdqa $t2,0x00(%rsp)
+ xor $C,$a3 # magic
+ vmovdqa $t3,0x20(%rsp)
+ mov $F,$a4
+ sub \$-16*2*$SZ,$Tbl # size optimization
+ jmp .Lavx2_00_47
+
+.align 16
+.Lavx2_00_47:
+___
+
+sub AVX2_256_00_47 () {
+my $j = shift;
+my $body = shift;
+my @X = @_;
+my @insns = (&$body,&$body,&$body,&$body); # 96 instructions
+my $base = "+2*$PUSH8(%rsp)";
+
+ &lea ("%rsp","-$PUSH8(%rsp)") if (($j%2)==0);
+ foreach (Xupdate_256_AVX()) { # 29 instructions
+ eval;
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ }
+ &vpaddd ($t2,@X[0],16*2*$j."($Tbl)");
+ foreach (@insns) { eval; } # remaining instructions
+ &vmovdqa ((32*$j)%$PUSH8."(%rsp)",$t2);
+}
+
+ for ($i=0,$j=0; $j<4; $j++) {
+ &AVX2_256_00_47($j,\&bodyx_00_15,@X);
+ push(@X,shift(@X)); # rotate(@X)
+ }
+ &lea ($Tbl,16*2*$SZ."($Tbl)");
+ &cmpb (($SZ-1)."($Tbl)",0);
+ &jne (".Lavx2_00_47");
+
+ for ($i=0; $i<16; ) {
+ my $base=$i<8?"+$PUSH8(%rsp)":"(%rsp)";
+ foreach(bodyx_00_15()) { eval; }
+ }
+ } else { # SHA512
+ my @X = map("%ymm$_",(0..7));
+ my ($t0,$t1,$t2,$t3) = map("%ymm$_",(8..11));
+
+$code.=<<___;
+ jmp .Loop_avx2
+.align 16
+.Loop_avx2:
+ vmovdqu -16*$SZ($inp),%xmm0
+ vmovdqu -16*$SZ+16($inp),%xmm1
+ vmovdqu -16*$SZ+32($inp),%xmm2
+ lea $TABLE+0x80(%rip),$Tbl # size optimization
+ vmovdqu -16*$SZ+48($inp),%xmm3
+ vmovdqu -16*$SZ+64($inp),%xmm4
+ vmovdqu -16*$SZ+80($inp),%xmm5
+ vmovdqu -16*$SZ+96($inp),%xmm6
+ vmovdqu -16*$SZ+112($inp),%xmm7
+ #mov $inp,$_inp # offload $inp
+ vmovdqa `$SZ*2*$rounds-0x80`($Tbl),$t2
+ vinserti128 \$1,(%r12),@X[0],@X[0]
+ vinserti128 \$1,16(%r12),@X[1],@X[1]
+ vpshufb $t2,@X[0],@X[0]
+ vinserti128 \$1,32(%r12),@X[2],@X[2]
+ vpshufb $t2,@X[1],@X[1]
+ vinserti128 \$1,48(%r12),@X[3],@X[3]
+ vpshufb $t2,@X[2],@X[2]
+ vinserti128 \$1,64(%r12),@X[4],@X[4]
+ vpshufb $t2,@X[3],@X[3]
+ vinserti128 \$1,80(%r12),@X[5],@X[5]
+ vpshufb $t2,@X[4],@X[4]
+ vinserti128 \$1,96(%r12),@X[6],@X[6]
+ vpshufb $t2,@X[5],@X[5]
+ vinserti128 \$1,112(%r12),@X[7],@X[7]
+
+ vpaddq -0x80($Tbl),@X[0],$t0
+ vpshufb $t2,@X[6],@X[6]
+ vpaddq -0x60($Tbl),@X[1],$t1
+ vpshufb $t2,@X[7],@X[7]
+ vpaddq -0x40($Tbl),@X[2],$t2
+ vpaddq -0x20($Tbl),@X[3],$t3
+ vmovdqa $t0,0x00(%rsp)
+ vpaddq 0x00($Tbl),@X[4],$t0
+ vmovdqa $t1,0x20(%rsp)
+ vpaddq 0x20($Tbl),@X[5],$t1
+ vmovdqa $t2,0x40(%rsp)
+ vpaddq 0x40($Tbl),@X[6],$t2
+ vmovdqa $t3,0x60(%rsp)
+ lea -$PUSH8(%rsp),%rsp
+ vpaddq 0x60($Tbl),@X[7],$t3
+ vmovdqa $t0,0x00(%rsp)
+ xor $a1,$a1
+ vmovdqa $t1,0x20(%rsp)
+ mov $B,$a3
+ vmovdqa $t2,0x40(%rsp)
+ xor $C,$a3 # magic
+ vmovdqa $t3,0x60(%rsp)
+ mov $F,$a4
+ add \$16*2*$SZ,$Tbl
+ jmp .Lavx2_00_47
+
+.align 16
+.Lavx2_00_47:
+___
+
+sub AVX2_512_00_47 () {
+my $j = shift;
+my $body = shift;
+my @X = @_;
+my @insns = (&$body,&$body); # 48 instructions
+my $base = "+2*$PUSH8(%rsp)";
+
+ &lea ("%rsp","-$PUSH8(%rsp)") if (($j%4)==0);
+ foreach (Xupdate_512_AVX()) { # 23 instructions
+ eval;
+ if ($_ !~ /\;$/) {
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ }
+ }
+ &vpaddq ($t2,@X[0],16*2*$j-0x80."($Tbl)");
+ foreach (@insns) { eval; } # remaining instructions
+ &vmovdqa ((32*$j)%$PUSH8."(%rsp)",$t2);
+}
+
+ for ($i=0,$j=0; $j<8; $j++) {
+ &AVX2_512_00_47($j,\&bodyx_00_15,@X);
+ push(@X,shift(@X)); # rotate(@X)
+ }
+ &lea ($Tbl,16*2*$SZ."($Tbl)");
+ &cmpb (($SZ-1-0x80)."($Tbl)",0);
+ &jne (".Lavx2_00_47");
+
+ for ($i=0; $i<16; ) {
+ my $base=$i<8?"+$PUSH8(%rsp)":"(%rsp)";
+ foreach(bodyx_00_15()) { eval; }
+ }
+}
+$code.=<<___;
+ mov `2*$SZ*$rounds`(%rsp),$ctx # $_ctx
+ add $a1,$A
+ #mov `2*$SZ*$rounds+8`(%rsp),$inp # $_inp
+ lea `2*$SZ*($rounds-8)`(%rsp),$Tbl
+
+ add $SZ*0($ctx),$A
+ add $SZ*1($ctx),$B
+ add $SZ*2($ctx),$C
+ add $SZ*3($ctx),$D
+ add $SZ*4($ctx),$E
+ add $SZ*5($ctx),$F
+ add $SZ*6($ctx),$G
+ add $SZ*7($ctx),$H
+
+ mov $A,$SZ*0($ctx)
+ mov $B,$SZ*1($ctx)
+ mov $C,$SZ*2($ctx)
+ mov $D,$SZ*3($ctx)
+ mov $E,$SZ*4($ctx)
+ mov $F,$SZ*5($ctx)
+ mov $G,$SZ*6($ctx)
+ mov $H,$SZ*7($ctx)
+
+ cmp `$PUSH8+2*8`($Tbl),$inp # $_end
+ je .Ldone_avx2
+
+ xor $a1,$a1
+ mov $B,$a3
+ xor $C,$a3 # magic
+ mov $F,$a4
+ jmp .Lower_avx2
+.align 16
+.Lower_avx2:
+___
+ for ($i=0; $i<8; ) {
+ my $base="+16($Tbl)";
+ foreach(bodyx_00_15()) { eval; }
+ }
+$code.=<<___;
+ lea -$PUSH8($Tbl),$Tbl
+ cmp %rsp,$Tbl
+ jae .Lower_avx2
+
+ mov `2*$SZ*$rounds`(%rsp),$ctx # $_ctx
+ add $a1,$A
+ #mov `2*$SZ*$rounds+8`(%rsp),$inp # $_inp
+ lea `2*$SZ*($rounds-8)`(%rsp),%rsp
+
+ add $SZ*0($ctx),$A
+ add $SZ*1($ctx),$B
+ add $SZ*2($ctx),$C
+ add $SZ*3($ctx),$D
+ add $SZ*4($ctx),$E
+ add $SZ*5($ctx),$F
+ lea `2*16*$SZ`($inp),$inp # inp+=2
+ add $SZ*6($ctx),$G
+ mov $inp,%r12
+ add $SZ*7($ctx),$H
+ cmp $_end,$inp
+
+ mov $A,$SZ*0($ctx)
+ cmove %rsp,%r12 # next block or stale data
+ mov $B,$SZ*1($ctx)
+ mov $C,$SZ*2($ctx)
+ mov $D,$SZ*3($ctx)
+ mov $E,$SZ*4($ctx)
+ mov $F,$SZ*5($ctx)
+ mov $G,$SZ*6($ctx)
+ mov $H,$SZ*7($ctx)
+
+ jbe .Loop_avx2
+ lea (%rsp),$Tbl
+
+.Ldone_avx2:
+ lea ($Tbl),%rsp
+ mov $_rsp,%rsi
+ vzeroupper
+___
+$code.=<<___ if ($win64);
+ movaps 16*$SZ+32(%rsp),%xmm6
+ movaps 16*$SZ+48(%rsp),%xmm7
+ movaps 16*$SZ+64(%rsp),%xmm8
+ movaps 16*$SZ+80(%rsp),%xmm9
+___
+$code.=<<___ if ($win64 && $SZ>4);
+ movaps 16*$SZ+96(%rsp),%xmm10
+ movaps 16*$SZ+112(%rsp),%xmm11
+___
+$code.=<<___;
+ mov (%rsi),%r15
+ mov 8(%rsi),%r14
+ mov 16(%rsi),%r13
+ mov 24(%rsi),%r12
+ mov 32(%rsi),%rbp
+ mov 40(%rsi),%rbx
+ lea 48(%rsi),%rsp
+.Lepilogue_avx2:
+ ret
+.size ${func}_avx2,.-${func}_avx2
+___
+}}
+}}}}}
+
+# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame,
+# CONTEXT *context,DISPATCHER_CONTEXT *disp)
+if ($win64) {
+$rec="%rcx";
+$frame="%rdx";
+$context="%r8";
+$disp="%r9";
+
+$code.=<<___;
+.extern __imp_RtlVirtualUnwind
+.type se_handler,\@abi-omnipotent
+.align 16
+se_handler:
+ push %rsi
+ push %rdi
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+ pushfq
+ sub \$64,%rsp
+
+ mov 120($context),%rax # pull context->Rax
+ mov 248($context),%rbx # pull context->Rip
+
+ mov 8($disp),%rsi # disp->ImageBase
+ mov 56($disp),%r11 # disp->HanderlData
+
+ mov 0(%r11),%r10d # HandlerData[0]
+ lea (%rsi,%r10),%r10 # prologue label
+ cmp %r10,%rbx # context->Rip<prologue label
+ jb .Lin_prologue
+
+ mov 152($context),%rax # pull context->Rsp
+
+ mov 4(%r11),%r10d # HandlerData[1]
+ lea (%rsi,%r10),%r10 # epilogue label
+ cmp %r10,%rbx # context->Rip>=epilogue label
+ jae .Lin_prologue
+___
+$code.=<<___ if ($avx>1);
+ lea .Lavx2_shortcut(%rip),%r10
+ cmp %r10,%rbx # context->Rip<avx2_shortcut
+ jb .Lnot_in_avx2
+
+ and \$-256*$SZ,%rax
+ add \$`2*$SZ*($rounds-8)`,%rax
+.Lnot_in_avx2:
+___
+$code.=<<___;
+ mov %rax,%rsi # put aside Rsp
+ mov 16*$SZ+3*8(%rax),%rax # pull $_rsp
+ lea 48(%rax),%rax
+
+ mov -8(%rax),%rbx
+ mov -16(%rax),%rbp
+ mov -24(%rax),%r12
+ mov -32(%rax),%r13
+ mov -40(%rax),%r14
+ mov -48(%rax),%r15
+ mov %rbx,144($context) # restore context->Rbx
+ mov %rbp,160($context) # restore context->Rbp
+ mov %r12,216($context) # restore context->R12
+ mov %r13,224($context) # restore context->R13
+ mov %r14,232($context) # restore context->R14
+ mov %r15,240($context) # restore context->R15
+
+ lea .Lepilogue(%rip),%r10
+ cmp %r10,%rbx
+ jb .Lin_prologue # non-AVX code
+
+ lea 16*$SZ+4*8(%rsi),%rsi # Xmm6- save area
+ lea 512($context),%rdi # &context.Xmm6
+ mov \$`$SZ==4?8:12`,%ecx
+ .long 0xa548f3fc # cld; rep movsq
+
+.Lin_prologue:
+ mov 8(%rax),%rdi
+ mov 16(%rax),%rsi
+ mov %rax,152($context) # restore context->Rsp
+ mov %rsi,168($context) # restore context->Rsi
+ mov %rdi,176($context) # restore context->Rdi
+
+ mov 40($disp),%rdi # disp->ContextRecord
+ mov $context,%rsi # context
+ mov \$154,%ecx # sizeof(CONTEXT)
+ .long 0xa548f3fc # cld; rep movsq
+
+ mov $disp,%rsi
+ xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER
+ mov 8(%rsi),%rdx # arg2, disp->ImageBase
+ mov 0(%rsi),%r8 # arg3, disp->ControlPc
+ mov 16(%rsi),%r9 # arg4, disp->FunctionEntry
+ mov 40(%rsi),%r10 # disp->ContextRecord
+ lea 56(%rsi),%r11 # &disp->HandlerData
+ lea 24(%rsi),%r12 # &disp->EstablisherFrame
+ mov %r10,32(%rsp) # arg5
+ mov %r11,40(%rsp) # arg6
+ mov %r12,48(%rsp) # arg7
+ mov %rcx,56(%rsp) # arg8, (NULL)
+ call *__imp_RtlVirtualUnwind(%rip)
+
+ mov \$1,%eax # ExceptionContinueSearch
+ add \$64,%rsp
+ popfq
+ pop %r15
+ pop %r14
+ pop %r13
+ pop %r12
+ pop %rbp
+ pop %rbx
+ pop %rdi
+ pop %rsi
+ ret
+.size se_handler,.-se_handler
+___
+$code.=<<___ if ($SZ == 4 && $shaext);
+.type shaext_handler,\@abi-omnipotent
+.align 16
+shaext_handler:
+ push %rsi
+ push %rdi
+ push %rbx
+ push %rbp
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+ pushfq
+ sub \$64,%rsp
+
+ mov 120($context),%rax # pull context->Rax
+ mov 248($context),%rbx # pull context->Rip
+
+ lea .Lprologue_shaext(%rip),%r10
+ cmp %r10,%rbx # context->Rip<.Lprologue
+ jb .Lin_prologue
+
+ lea .Lepilogue_shaext(%rip),%r10
+ cmp %r10,%rbx # context->Rip>=.Lepilogue
+ jae .Lin_prologue
+
+ lea -8-5*16(%rax),%rsi
+ lea 512($context),%rdi # &context.Xmm6
+ mov \$10,%ecx
+ .long 0xa548f3fc # cld; rep movsq
+
+ jmp .Lin_prologue
+.size shaext_handler,.-shaext_handler
+___
+$code.=<<___;
+.section .pdata
+.align 4
+ .rva .LSEH_begin_$func
+ .rva .LSEH_end_$func
+ .rva .LSEH_info_$func
+___
+$code.=<<___ if ($SZ==4 && $shext);
+ .rva .LSEH_begin_${func}_shaext
+ .rva .LSEH_end_${func}_shaext
+ .rva .LSEH_info_${func}_shaext
+___
+$code.=<<___ if ($SZ==4);
+ .rva .LSEH_begin_${func}_ssse3
+ .rva .LSEH_end_${func}_ssse3
+ .rva .LSEH_info_${func}_ssse3
+___
+$code.=<<___ if ($avx && $SZ==8);
+ .rva .LSEH_begin_${func}_xop
+ .rva .LSEH_end_${func}_xop
+ .rva .LSEH_info_${func}_xop
+___
+$code.=<<___ if ($avx);
+ .rva .LSEH_begin_${func}_avx
+ .rva .LSEH_end_${func}_avx
+ .rva .LSEH_info_${func}_avx
+___
+$code.=<<___ if ($avx>1);
+ .rva .LSEH_begin_${func}_avx2
+ .rva .LSEH_end_${func}_avx2
+ .rva .LSEH_info_${func}_avx2
+___
+$code.=<<___;
+.section .xdata
+.align 8
+.LSEH_info_$func:
+ .byte 9,0,0,0
+ .rva se_handler
+ .rva .Lprologue,.Lepilogue # HandlerData[]
+___
+$code.=<<___ if ($SZ==4 && $shaext);
+.LSEH_info_${func}_shaext:
+ .byte 9,0,0,0
+ .rva shaext_handler
+___
+$code.=<<___ if ($SZ==4);
+.LSEH_info_${func}_ssse3:
+ .byte 9,0,0,0
+ .rva se_handler
+ .rva .Lprologue_ssse3,.Lepilogue_ssse3 # HandlerData[]
+___
+$code.=<<___ if ($avx && $SZ==8);
+.LSEH_info_${func}_xop:
+ .byte 9,0,0,0
+ .rva se_handler
+ .rva .Lprologue_xop,.Lepilogue_xop # HandlerData[]
+___
+$code.=<<___ if ($avx);
+.LSEH_info_${func}_avx:
+ .byte 9,0,0,0
+ .rva se_handler
+ .rva .Lprologue_avx,.Lepilogue_avx # HandlerData[]
+___
+$code.=<<___ if ($avx>1);
+.LSEH_info_${func}_avx2:
+ .byte 9,0,0,0
+ .rva se_handler
+ .rva .Lprologue_avx2,.Lepilogue_avx2 # HandlerData[]
+___
+}
+
+sub sha256op38 {
+ my $instr = shift;
+ my %opcodelet = (
+ "sha256rnds2" => 0xcb,
+ "sha256msg1" => 0xcc,
+ "sha256msg2" => 0xcd );
+
+ if (defined($opcodelet{$instr}) && @_[0] =~ /%xmm([0-7]),\s*%xmm([0-7])/) {
+ my @opcode=(0x0f,0x38);
+ push @opcode,$opcodelet{$instr};
+ push @opcode,0xc0|($1&7)|(($2&7)<<3); # ModR/M
+ return ".byte\t".join(',',@opcode);
+ } else {
+ return $instr."\t".@_[0];
+ }
+}
+
+foreach (split("\n",$code)) {
+ s/\`([^\`]*)\`/eval $1/geo;
+
+ s/\b(sha256[^\s]*)\s+(.*)/sha256op38($1,$2)/geo;
+
+ print $_,"\n";
+}
+close STDOUT;
diff --git a/src/crypto/sha/sha1.c b/src/crypto/sha/sha1.c
new file mode 100644
index 0000000..7595bc8
--- /dev/null
+++ b/src/crypto/sha/sha1.c
@@ -0,0 +1,380 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/sha.h>
+
+#include <string.h>
+
+#include <openssl/mem.h>
+
+
+#if !defined(OPENSSL_NO_ASM) && \
+ (defined(OPENSSL_X86) || defined(OPENSSL_X86_64) || \
+ defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64))
+#define SHA1_ASM
+#endif
+
+int SHA1_Init(SHA_CTX *sha) {
+ memset(sha, 0, sizeof(SHA_CTX));
+ sha->h0 = 0x67452301UL;
+ sha->h1 = 0xefcdab89UL;
+ sha->h2 = 0x98badcfeUL;
+ sha->h3 = 0x10325476UL;
+ sha->h4 = 0xc3d2e1f0UL;
+ return 1;
+}
+
+uint8_t *SHA1(const uint8_t *data, size_t len, uint8_t *out) {
+ SHA_CTX ctx;
+ static uint8_t buf[SHA_DIGEST_LENGTH];
+
+ /* TODO(fork): remove this static buffer. */
+ if (out == NULL) {
+ out = buf;
+ }
+ if (!SHA1_Init(&ctx)) {
+ return NULL;
+ }
+ SHA1_Update(&ctx, data, len);
+ SHA1_Final(out, &ctx);
+ OPENSSL_cleanse(&ctx, sizeof(ctx));
+ return out;
+}
+
+#define DATA_ORDER_IS_BIG_ENDIAN
+
+#define HASH_LONG uint32_t
+#define HASH_CTX SHA_CTX
+#define HASH_CBLOCK 64
+#define HASH_MAKE_STRING(c, s) \
+ do { \
+ unsigned long ll; \
+ ll = (c)->h0; \
+ (void) HOST_l2c(ll, (s)); \
+ ll = (c)->h1; \
+ (void) HOST_l2c(ll, (s)); \
+ ll = (c)->h2; \
+ (void) HOST_l2c(ll, (s)); \
+ ll = (c)->h3; \
+ (void) HOST_l2c(ll, (s)); \
+ ll = (c)->h4; \
+ (void) HOST_l2c(ll, (s)); \
+ } while (0)
+
+#define HASH_UPDATE SHA1_Update
+#define HASH_TRANSFORM SHA1_Transform
+#define HASH_FINAL SHA1_Final
+#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);
+
+#include "../digest/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 <weidai@eskimo.com>, 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);
+
+#ifdef X
+#undef X
+#endif
+
+/* Originally X was an array. As it's automatic it's natural
+* to expect RISC compiler to accomodate at least part of it in
+* the register bank, isn't it? Unfortunately not all compilers
+* "find" this expectation reasonable:-( On order to make such
+* compilers generate better code I replace X[] with a bunch of
+* X0, X1, etc. See the function body below...
+* <appro@fy.chalmers.se> */
+#define X(i) XX##i
+
+#if !defined(SHA1_ASM)
+static void HASH_BLOCK_DATA_ORDER(SHA_CTX *c, const void *p, size_t num) {
+ const uint8_t *data = p;
+ register unsigned MD32_REG_T A, B, C, D, E, T, l;
+ unsigned MD32_REG_T XX0, XX1, XX2, XX3, XX4, XX5, XX6, XX7, XX8, XX9, XX10,
+ XX11, XX12, XX13, XX14, XX15;
+
+ A = c->h0;
+ B = c->h1;
+ C = c->h2;
+ D = c->h3;
+ E = c->h4;
+
+ for (;;) {
+ const union {
+ long one;
+ char little;
+ } is_endian = {1};
+
+ if (!is_endian.little && ((size_t)p % 4) == 0) {
+ const uint32_t *W = (const uint32_t *)data;
+
+ X(0) = W[0];
+ X(1) = W[1];
+ BODY_00_15(0, A, B, C, D, E, T, X(0));
+ X(2) = W[2];
+ BODY_00_15(1, T, A, B, C, D, E, X(1));
+ X(3) = W[3];
+ BODY_00_15(2, E, T, A, B, C, D, X(2));
+ X(4) = W[4];
+ BODY_00_15(3, D, E, T, A, B, C, X(3));
+ X(5) = W[5];
+ BODY_00_15(4, C, D, E, T, A, B, X(4));
+ X(6) = W[6];
+ BODY_00_15(5, B, C, D, E, T, A, X(5));
+ X(7) = W[7];
+ BODY_00_15(6, A, B, C, D, E, T, X(6));
+ X(8) = W[8];
+ BODY_00_15(7, T, A, B, C, D, E, X(7));
+ X(9) = W[9];
+ BODY_00_15(8, E, T, A, B, C, D, X(8));
+ X(10) = W[10];
+ BODY_00_15(9, D, E, T, A, B, C, X(9));
+ X(11) = W[11];
+ BODY_00_15(10, C, D, E, T, A, B, X(10));
+ X(12) = W[12];
+ BODY_00_15(11, B, C, D, E, T, A, X(11));
+ X(13) = W[13];
+ BODY_00_15(12, A, B, C, D, E, T, X(12));
+ X(14) = W[14];
+ BODY_00_15(13, T, A, B, C, D, E, X(13));
+ X(15) = W[15];
+ BODY_00_15(14, E, T, A, B, C, D, X(14));
+ BODY_00_15(15, D, E, T, A, B, C, X(15));
+
+ data += HASH_CBLOCK;
+ } else {
+ (void)HOST_c2l(data, l);
+ X(0) = l;
+ (void)HOST_c2l(data, l);
+ X(1) = l;
+ BODY_00_15(0, A, B, C, D, E, T, X(0));
+ (void)HOST_c2l(data, l);
+ X(2) = l;
+ BODY_00_15(1, T, A, B, C, D, E, X(1));
+ (void)HOST_c2l(data, l);
+ X(3) = l;
+ BODY_00_15(2, E, T, A, B, C, D, X(2));
+ (void)HOST_c2l(data, l);
+ X(4) = l;
+ BODY_00_15(3, D, E, T, A, B, C, X(3));
+ (void)HOST_c2l(data, l);
+ X(5) = l;
+ BODY_00_15(4, C, D, E, T, A, B, X(4));
+ (void)HOST_c2l(data, l);
+ X(6) = l;
+ BODY_00_15(5, B, C, D, E, T, A, X(5));
+ (void)HOST_c2l(data, l);
+ X(7) = l;
+ BODY_00_15(6, A, B, C, D, E, T, X(6));
+ (void)HOST_c2l(data, l);
+ X(8) = l;
+ BODY_00_15(7, T, A, B, C, D, E, X(7));
+ (void)HOST_c2l(data, l);
+ X(9) = l;
+ BODY_00_15(8, E, T, A, B, C, D, X(8));
+ (void)HOST_c2l(data, l);
+ X(10) = l;
+ BODY_00_15(9, D, E, T, A, B, C, X(9));
+ (void)HOST_c2l(data, l);
+ X(11) = l;
+ BODY_00_15(10, C, D, E, T, A, B, X(10));
+ (void)HOST_c2l(data, l);
+ X(12) = l;
+ BODY_00_15(11, B, C, D, E, T, A, X(11));
+ (void)HOST_c2l(data, l);
+ X(13) = l;
+ BODY_00_15(12, A, B, C, D, E, T, X(12));
+ (void)HOST_c2l(data, l);
+ X(14) = l;
+ BODY_00_15(13, T, A, B, C, D, E, X(13));
+ (void)HOST_c2l(data, l);
+ X(15) = l;
+ BODY_00_15(14, E, T, A, B, C, D, X(14));
+ BODY_00_15(15, D, E, T, A, B, C, X(15));
+ }
+
+ BODY_16_19(16, C, D, E, T, A, B, X(0), X(0), X(2), X(8), X(13));
+ BODY_16_19(17, B, C, D, E, T, A, X(1), X(1), X(3), X(9), X(14));
+ BODY_16_19(18, A, B, C, D, E, T, X(2), X(2), X(4), X(10), X(15));
+ BODY_16_19(19, T, A, B, C, D, E, X(3), X(3), X(5), X(11), X(0));
+
+ BODY_20_31(20, E, T, A, B, C, D, X(4), X(4), X(6), X(12), X(1));
+ BODY_20_31(21, D, E, T, A, B, C, X(5), X(5), X(7), X(13), X(2));
+ BODY_20_31(22, C, D, E, T, A, B, X(6), X(6), X(8), X(14), X(3));
+ BODY_20_31(23, B, C, D, E, T, A, X(7), X(7), X(9), X(15), X(4));
+ BODY_20_31(24, A, B, C, D, E, T, X(8), X(8), X(10), X(0), X(5));
+ BODY_20_31(25, T, A, B, C, D, E, X(9), X(9), X(11), X(1), X(6));
+ BODY_20_31(26, E, T, A, B, C, D, X(10), X(10), X(12), X(2), X(7));
+ BODY_20_31(27, D, E, T, A, B, C, X(11), X(11), X(13), X(3), X(8));
+ BODY_20_31(28, C, D, E, T, A, B, X(12), X(12), X(14), X(4), X(9));
+ BODY_20_31(29, B, C, D, E, T, A, X(13), X(13), X(15), X(5), X(10));
+ BODY_20_31(30, A, B, C, D, E, T, X(14), X(14), X(0), X(6), X(11));
+ BODY_20_31(31, T, A, B, C, D, E, X(15), X(15), X(1), X(7), X(12));
+
+ BODY_32_39(32, E, T, A, B, C, D, X(0), X(2), X(8), X(13));
+ BODY_32_39(33, D, E, T, A, B, C, X(1), X(3), X(9), X(14));
+ BODY_32_39(34, C, D, E, T, A, B, X(2), X(4), X(10), X(15));
+ BODY_32_39(35, B, C, D, E, T, A, X(3), X(5), X(11), X(0));
+ BODY_32_39(36, A, B, C, D, E, T, X(4), X(6), X(12), X(1));
+ BODY_32_39(37, T, A, B, C, D, E, X(5), X(7), X(13), X(2));
+ BODY_32_39(38, E, T, A, B, C, D, X(6), X(8), X(14), X(3));
+ BODY_32_39(39, D, E, T, A, B, C, X(7), X(9), X(15), X(4));
+
+ BODY_40_59(40, C, D, E, T, A, B, X(8), X(10), X(0), X(5));
+ BODY_40_59(41, B, C, D, E, T, A, X(9), X(11), X(1), X(6));
+ BODY_40_59(42, A, B, C, D, E, T, X(10), X(12), X(2), X(7));
+ BODY_40_59(43, T, A, B, C, D, E, X(11), X(13), X(3), X(8));
+ BODY_40_59(44, E, T, A, B, C, D, X(12), X(14), X(4), X(9));
+ BODY_40_59(45, D, E, T, A, B, C, X(13), X(15), X(5), X(10));
+ BODY_40_59(46, C, D, E, T, A, B, X(14), X(0), X(6), X(11));
+ BODY_40_59(47, B, C, D, E, T, A, X(15), X(1), X(7), X(12));
+ BODY_40_59(48, A, B, C, D, E, T, X(0), X(2), X(8), X(13));
+ BODY_40_59(49, T, A, B, C, D, E, X(1), X(3), X(9), X(14));
+ BODY_40_59(50, E, T, A, B, C, D, X(2), X(4), X(10), X(15));
+ BODY_40_59(51, D, E, T, A, B, C, X(3), X(5), X(11), X(0));
+ BODY_40_59(52, C, D, E, T, A, B, X(4), X(6), X(12), X(1));
+ BODY_40_59(53, B, C, D, E, T, A, X(5), X(7), X(13), X(2));
+ BODY_40_59(54, A, B, C, D, E, T, X(6), X(8), X(14), X(3));
+ BODY_40_59(55, T, A, B, C, D, E, X(7), X(9), X(15), X(4));
+ BODY_40_59(56, E, T, A, B, C, D, X(8), X(10), X(0), X(5));
+ BODY_40_59(57, D, E, T, A, B, C, X(9), X(11), X(1), X(6));
+ BODY_40_59(58, C, D, E, T, A, B, X(10), X(12), X(2), X(7));
+ BODY_40_59(59, B, C, D, E, T, A, X(11), X(13), X(3), X(8));
+
+ BODY_60_79(60, A, B, C, D, E, T, X(12), X(14), X(4), X(9));
+ BODY_60_79(61, T, A, B, C, D, E, X(13), X(15), X(5), X(10));
+ BODY_60_79(62, E, T, A, B, C, D, X(14), X(0), X(6), X(11));
+ BODY_60_79(63, D, E, T, A, B, C, X(15), X(1), X(7), X(12));
+ BODY_60_79(64, C, D, E, T, A, B, X(0), X(2), X(8), X(13));
+ BODY_60_79(65, B, C, D, E, T, A, X(1), X(3), X(9), X(14));
+ BODY_60_79(66, A, B, C, D, E, T, X(2), X(4), X(10), X(15));
+ BODY_60_79(67, T, A, B, C, D, E, X(3), X(5), X(11), X(0));
+ BODY_60_79(68, E, T, A, B, C, D, X(4), X(6), X(12), X(1));
+ BODY_60_79(69, D, E, T, A, B, C, X(5), X(7), X(13), X(2));
+ BODY_60_79(70, C, D, E, T, A, B, X(6), X(8), X(14), X(3));
+ BODY_60_79(71, B, C, D, E, T, A, X(7), X(9), X(15), X(4));
+ BODY_60_79(72, A, B, C, D, E, T, X(8), X(10), X(0), X(5));
+ BODY_60_79(73, T, A, B, C, D, E, X(9), X(11), X(1), X(6));
+ BODY_60_79(74, E, T, A, B, C, D, X(10), X(12), X(2), X(7));
+ BODY_60_79(75, D, E, T, A, B, C, X(11), X(13), X(3), X(8));
+ BODY_60_79(76, C, D, E, T, A, B, X(12), X(14), X(4), X(9));
+ BODY_60_79(77, B, C, D, E, T, A, X(13), X(15), X(5), X(10));
+ BODY_60_79(78, A, B, C, D, E, T, X(14), X(0), X(6), X(11));
+ BODY_60_79(79, T, A, B, C, D, E, X(15), X(1), X(7), X(12));
+
+ 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
diff --git a/src/crypto/sha/sha256.c b/src/crypto/sha/sha256.c
new file mode 100644
index 0000000..8d4106e
--- /dev/null
+++ b/src/crypto/sha/sha256.c
@@ -0,0 +1,366 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/sha.h>
+
+#include <string.h>
+
+#include <openssl/mem.h>
+
+
+#if !defined(OPENSSL_NO_ASM) && \
+ (defined(OPENSSL_X86) || defined(OPENSSL_X86_64) || \
+ defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64))
+#define SHA256_ASM
+#endif
+
+int SHA224_Init(SHA256_CTX *sha) {
+ memset(sha, 0, sizeof(SHA256_CTX));
+ sha->h[0] = 0xc1059ed8UL;
+ sha->h[1] = 0x367cd507UL;
+ sha->h[2] = 0x3070dd17UL;
+ sha->h[3] = 0xf70e5939UL;
+ sha->h[4] = 0xffc00b31UL;
+ sha->h[5] = 0x68581511UL;
+ sha->h[6] = 0x64f98fa7UL;
+ sha->h[7] = 0xbefa4fa4UL;
+ sha->md_len = SHA224_DIGEST_LENGTH;
+ return 1;
+}
+
+int SHA256_Init(SHA256_CTX *sha) {
+ memset(sha, 0, sizeof(SHA256_CTX));
+ sha->h[0] = 0x6a09e667UL;
+ sha->h[1] = 0xbb67ae85UL;
+ sha->h[2] = 0x3c6ef372UL;
+ sha->h[3] = 0xa54ff53aUL;
+ sha->h[4] = 0x510e527fUL;
+ sha->h[5] = 0x9b05688cUL;
+ sha->h[6] = 0x1f83d9abUL;
+ sha->h[7] = 0x5be0cd19UL;
+ sha->md_len = SHA256_DIGEST_LENGTH;
+ return 1;
+}
+
+uint8_t *SHA224(const uint8_t *data, size_t len, uint8_t *out) {
+ SHA256_CTX ctx;
+ static uint8_t buf[SHA224_DIGEST_LENGTH];
+
+ /* TODO(fork): remove this static buffer. */
+ if (out == NULL) {
+ out = buf;
+ }
+ SHA224_Init(&ctx);
+ SHA256_Update(&ctx, data, len);
+ SHA256_Final(out, &ctx);
+ OPENSSL_cleanse(&ctx, sizeof(ctx));
+ return out;
+}
+
+uint8_t *SHA256(const uint8_t *data, size_t len, uint8_t *out) {
+ SHA256_CTX ctx;
+ static uint8_t buf[SHA256_DIGEST_LENGTH];
+
+ /* TODO(fork): remove this static buffer. */
+ if (out == NULL) {
+ out = buf;
+ }
+ SHA256_Init(&ctx);
+ SHA256_Update(&ctx, data, len);
+ SHA256_Final(out, &ctx);
+ OPENSSL_cleanse(&ctx, sizeof(ctx));
+ return out;
+}
+
+int SHA224_Update(SHA256_CTX *ctx, const void *data, size_t len) {
+ return SHA256_Update(ctx, data, len);
+}
+
+int SHA224_Final(uint8_t *md, SHA256_CTX *ctx) {
+ return SHA256_Final(md, ctx);
+}
+
+#define DATA_ORDER_IS_BIG_ENDIAN
+
+#define HASH_LONG uint32_t
+#define HASH_CTX SHA256_CTX
+#define HASH_CBLOCK 64
+
+/* 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 lenghts is to let the compiler decide if it's
+ * appropriate to unroll small loops. */
+#define HASH_MAKE_STRING(c, s) \
+ do { \
+ unsigned long ll; \
+ unsigned int nn; \
+ switch ((c)->md_len) { \
+ case SHA224_DIGEST_LENGTH: \
+ for (nn = 0; nn < SHA224_DIGEST_LENGTH / 4; nn++) { \
+ ll = (c)->h[nn]; \
+ (void) HOST_l2c(ll, (s)); \
+ } \
+ break; \
+ case SHA256_DIGEST_LENGTH: \
+ for (nn = 0; nn < SHA256_DIGEST_LENGTH / 4; nn++) { \
+ ll = (c)->h[nn]; \
+ (void) HOST_l2c(ll, (s)); \
+ } \
+ break; \
+ default: \
+ if ((c)->md_len > SHA256_DIGEST_LENGTH) \
+ return 0; \
+ for (nn = 0; nn < (c)->md_len / 4; nn++) { \
+ ll = (c)->h[nn]; \
+ (void) HOST_l2c(ll, (s)); \
+ } \
+ break; \
+ } \
+ } while (0)
+
+
+#define HASH_UPDATE SHA256_Update
+#define HASH_TRANSFORM SHA256_Transform
+#define HASH_FINAL SHA256_Final
+#define HASH_BLOCK_DATA_ORDER sha256_block_data_order
+#ifndef SHA256_ASM
+static
+#endif
+void sha256_block_data_order(SHA256_CTX *ctx, const void *in, size_t num);
+
+#include "../digest/md32_common.h"
+
+#ifndef SHA256_ASM
+static const HASH_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};
+
+/* FIPS specification refers to right rotations, while our ROTATE macro
+ * is left one. This is why you might notice that rotation coefficients
+ * differ from those observed in FIPS document by 32-N... */
+#define Sigma0(x) (ROTATE((x), 30) ^ ROTATE((x), 19) ^ ROTATE((x), 10))
+#define Sigma1(x) (ROTATE((x), 26) ^ ROTATE((x), 21) ^ ROTATE((x), 7))
+#define sigma0(x) (ROTATE((x), 25) ^ ROTATE((x), 14) ^ ((x) >> 3))
+#define sigma1(x) (ROTATE((x), 15) ^ ROTATE((x), 13) ^ ((x) >> 10))
+
+#define Ch(x, y, z) (((x) & (y)) ^ ((~(x)) & (z)))
+#define Maj(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
+
+#define ROUND_00_15(i, a, b, c, d, e, f, g, h) \
+ do { \
+ T1 += h + Sigma1(e) + Ch(e, f, g) + K256[i]; \
+ h = Sigma0(a) + Maj(a, b, c); \
+ d += T1; \
+ h += T1; \
+ } while (0)
+
+#define ROUND_16_63(i, a, b, c, d, e, f, g, h, X) \
+ do { \
+ s0 = X[(i + 1) & 0x0f]; \
+ s0 = sigma0(s0); \
+ s1 = X[(i + 14) & 0x0f]; \
+ s1 = sigma1(s1); \
+ T1 = X[(i) & 0x0f] += s0 + s1 + X[(i + 9) & 0x0f]; \
+ ROUND_00_15(i, a, b, c, d, e, f, g, h); \
+ } while (0)
+
+static void sha256_block_data_order(SHA256_CTX *ctx, const void *in,
+ size_t num) {
+ unsigned MD32_REG_T a, b, c, d, e, f, g, h, s0, s1, T1;
+ HASH_LONG X[16];
+ int i;
+ const uint8_t *data = in;
+ const union {
+ long one;
+ char little;
+ } is_endian = {1};
+
+ 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 (!is_endian.little && sizeof(HASH_LONG) == 4 && ((size_t)in % 4) == 0) {
+ const HASH_LONG *W = (const HASH_LONG *)data;
+
+ T1 = X[0] = W[0];
+ ROUND_00_15(0, a, b, c, d, e, f, g, h);
+ T1 = X[1] = W[1];
+ ROUND_00_15(1, h, a, b, c, d, e, f, g);
+ T1 = X[2] = W[2];
+ ROUND_00_15(2, g, h, a, b, c, d, e, f);
+ T1 = X[3] = W[3];
+ ROUND_00_15(3, f, g, h, a, b, c, d, e);
+ T1 = X[4] = W[4];
+ ROUND_00_15(4, e, f, g, h, a, b, c, d);
+ T1 = X[5] = W[5];
+ ROUND_00_15(5, d, e, f, g, h, a, b, c);
+ T1 = X[6] = W[6];
+ ROUND_00_15(6, c, d, e, f, g, h, a, b);
+ T1 = X[7] = W[7];
+ ROUND_00_15(7, b, c, d, e, f, g, h, a);
+ T1 = X[8] = W[8];
+ ROUND_00_15(8, a, b, c, d, e, f, g, h);
+ T1 = X[9] = W[9];
+ ROUND_00_15(9, h, a, b, c, d, e, f, g);
+ T1 = X[10] = W[10];
+ ROUND_00_15(10, g, h, a, b, c, d, e, f);
+ T1 = X[11] = W[11];
+ ROUND_00_15(11, f, g, h, a, b, c, d, e);
+ T1 = X[12] = W[12];
+ ROUND_00_15(12, e, f, g, h, a, b, c, d);
+ T1 = X[13] = W[13];
+ ROUND_00_15(13, d, e, f, g, h, a, b, c);
+ T1 = X[14] = W[14];
+ ROUND_00_15(14, c, d, e, f, g, h, a, b);
+ T1 = X[15] = W[15];
+ ROUND_00_15(15, b, c, d, e, f, g, h, a);
+
+ data += HASH_CBLOCK;
+ } else {
+ HASH_LONG l;
+
+ HOST_c2l(data, l);
+ T1 = X[0] = l;
+ ROUND_00_15(0, a, b, c, d, e, f, g, h);
+ HOST_c2l(data, l);
+ T1 = X[1] = l;
+ ROUND_00_15(1, h, a, b, c, d, e, f, g);
+ HOST_c2l(data, l);
+ T1 = X[2] = l;
+ ROUND_00_15(2, g, h, a, b, c, d, e, f);
+ HOST_c2l(data, l);
+ T1 = X[3] = l;
+ ROUND_00_15(3, f, g, h, a, b, c, d, e);
+ HOST_c2l(data, l);
+ T1 = X[4] = l;
+ ROUND_00_15(4, e, f, g, h, a, b, c, d);
+ HOST_c2l(data, l);
+ T1 = X[5] = l;
+ ROUND_00_15(5, d, e, f, g, h, a, b, c);
+ HOST_c2l(data, l);
+ T1 = X[6] = l;
+ ROUND_00_15(6, c, d, e, f, g, h, a, b);
+ HOST_c2l(data, l);
+ T1 = X[7] = l;
+ ROUND_00_15(7, b, c, d, e, f, g, h, a);
+ HOST_c2l(data, l);
+ T1 = X[8] = l;
+ ROUND_00_15(8, a, b, c, d, e, f, g, h);
+ HOST_c2l(data, l);
+ T1 = X[9] = l;
+ ROUND_00_15(9, h, a, b, c, d, e, f, g);
+ HOST_c2l(data, l);
+ T1 = X[10] = l;
+ ROUND_00_15(10, g, h, a, b, c, d, e, f);
+ HOST_c2l(data, l);
+ T1 = X[11] = l;
+ ROUND_00_15(11, f, g, h, a, b, c, d, e);
+ HOST_c2l(data, l);
+ T1 = X[12] = l;
+ ROUND_00_15(12, e, f, g, h, a, b, c, d);
+ HOST_c2l(data, l);
+ T1 = X[13] = l;
+ ROUND_00_15(13, d, e, f, g, h, a, b, c);
+ HOST_c2l(data, l);
+ T1 = X[14] = l;
+ ROUND_00_15(14, c, d, e, f, g, h, a, b);
+ HOST_c2l(data, l);
+ T1 = X[15] = l;
+ ROUND_00_15(15, b, c, d, e, f, g, h, a);
+ }
+
+ for (i = 16; i < 64; i += 8) {
+ ROUND_16_63(i + 0, a, b, c, d, e, f, g, h, X);
+ ROUND_16_63(i + 1, h, a, b, c, d, e, f, g, X);
+ ROUND_16_63(i + 2, g, h, a, b, c, d, e, f, X);
+ ROUND_16_63(i + 3, f, g, h, a, b, c, d, e, X);
+ ROUND_16_63(i + 4, e, f, g, h, a, b, c, d, X);
+ ROUND_16_63(i + 5, d, e, f, g, h, a, b, c, X);
+ ROUND_16_63(i + 6, c, d, e, f, g, h, a, b, X);
+ ROUND_16_63(i + 7, b, c, d, e, f, g, h, a, X);
+ }
+
+ 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 */
diff --git a/src/crypto/sha/sha512.c b/src/crypto/sha/sha512.c
new file mode 100644
index 0000000..59be8c1
--- /dev/null
+++ b/src/crypto/sha/sha512.c
@@ -0,0 +1,593 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/sha.h>
+
+#include <string.h>
+
+#include <openssl/mem.h>
+
+#include "../internal.h"
+
+
+/* IMPLEMENTATION NOTES.
+ *
+ * As you might have noticed 32-bit hash algorithms:
+ *
+ * - permit SHA_LONG to be wider than 32-bit (case on CRAY);
+ * - optimized versions implement two transform functions: one operating
+ * on [aligned] data in host byte order and one - on data in input
+ * stream byte order;
+ * - share common byte-order neutral collector and padding function
+ * implementations, ../md32_common.h;
+ *
+ * Neither of the above applies to this SHA-512 implementations. Reasons
+ * [in reverse order] are:
+ *
+ * - it's the only 64-bit hash algorithm for the moment of this writing,
+ * there is no need for common collector/padding implementation [yet];
+ * - by supporting only one transform function [which operates on
+ * *aligned* data in input stream byte order, big-endian in this case]
+ * we minimize burden of maintenance in two ways: a) collector/padding
+ * function is simpler; b) only one transform function to stare at;
+ * - SHA_LONG64 is required to be exactly 64-bit in order to be able to
+ * apply a number of optimizations to mitigate potential performance
+ * penalties caused by previous design decision; */
+
+#if !defined(OPENSSL_NO_ASM) && \
+ (defined(OPENSSL_X86) || defined(OPENSSL_X86_64) || \
+ defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64))
+#define SHA512_BLOCK_CAN_MANAGE_UNALIGNED_DATA
+#define SHA512_ASM
+#endif
+
+int SHA384_Init(SHA512_CTX *sha) {
+ sha->h[0] = OPENSSL_U64(0xcbbb9d5dc1059ed8);
+ sha->h[1] = OPENSSL_U64(0x629a292a367cd507);
+ sha->h[2] = OPENSSL_U64(0x9159015a3070dd17);
+ sha->h[3] = OPENSSL_U64(0x152fecd8f70e5939);
+ sha->h[4] = OPENSSL_U64(0x67332667ffc00b31);
+ sha->h[5] = OPENSSL_U64(0x8eb44a8768581511);
+ sha->h[6] = OPENSSL_U64(0xdb0c2e0d64f98fa7);
+ sha->h[7] = OPENSSL_U64(0x47b5481dbefa4fa4);
+
+ sha->Nl = 0;
+ sha->Nh = 0;
+ sha->num = 0;
+ sha->md_len = SHA384_DIGEST_LENGTH;
+ return 1;
+}
+
+
+int SHA512_Init(SHA512_CTX *sha) {
+ sha->h[0] = OPENSSL_U64(0x6a09e667f3bcc908);
+ sha->h[1] = OPENSSL_U64(0xbb67ae8584caa73b);
+ sha->h[2] = OPENSSL_U64(0x3c6ef372fe94f82b);
+ sha->h[3] = OPENSSL_U64(0xa54ff53a5f1d36f1);
+ sha->h[4] = OPENSSL_U64(0x510e527fade682d1);
+ sha->h[5] = OPENSSL_U64(0x9b05688c2b3e6c1f);
+ sha->h[6] = OPENSSL_U64(0x1f83d9abfb41bd6b);
+ sha->h[7] = OPENSSL_U64(0x5be0cd19137e2179);
+
+ sha->Nl = 0;
+ sha->Nh = 0;
+ sha->num = 0;
+ sha->md_len = SHA512_DIGEST_LENGTH;
+ return 1;
+}
+
+uint8_t *SHA384(const uint8_t *data, size_t len, uint8_t *out) {
+ SHA512_CTX ctx;
+ static uint8_t buf[SHA384_DIGEST_LENGTH];
+
+ /* TODO(fork): remove this static buffer. */
+ if (out == NULL) {
+ out = buf;
+ }
+
+ SHA384_Init(&ctx);
+ SHA512_Update(&ctx, data, len);
+ SHA512_Final(out, &ctx);
+ OPENSSL_cleanse(&ctx, sizeof(ctx));
+ return out;
+}
+
+uint8_t *SHA512(const uint8_t *data, size_t len, uint8_t *out) {
+ SHA512_CTX ctx;
+ static uint8_t buf[SHA512_DIGEST_LENGTH];
+
+ /* TODO(fork): remove this static buffer. */
+ if (out == NULL) {
+ out = buf;
+ }
+ SHA512_Init(&ctx);
+ SHA512_Update(&ctx, data, len);
+ SHA512_Final(out, &ctx);
+ OPENSSL_cleanse(&ctx, sizeof(ctx));
+ return out;
+}
+
+#if !defined(SHA512_ASM)
+static
+#endif
+void sha512_block_data_order(SHA512_CTX *ctx, const void *in, size_t num);
+
+
+int SHA384_Final(unsigned char *md, SHA512_CTX *sha) {
+ return SHA512_Final(md, sha);
+}
+
+int SHA384_Update(SHA512_CTX *sha, const void *data, size_t len) {
+ return SHA512_Update(sha, data, len);
+}
+
+void SHA512_Transform(SHA512_CTX *c, const unsigned char *data) {
+#ifndef SHA512_BLOCK_CAN_MANAGE_UNALIGNED_DATA
+ if ((size_t)data % sizeof(c->u.d[0]) != 0) {
+ memcpy(c->u.p, data, sizeof(c->u.p));
+ data = c->u.p;
+ }
+#endif
+ sha512_block_data_order(c, data, 1);
+}
+
+int SHA512_Update(SHA512_CTX *c, const void *in_data, size_t len) {
+ uint64_t l;
+ uint8_t *p = c->u.p;
+ const uint8_t *data = (const uint8_t *)in_data;
+
+ if (len == 0)
+ return 1;
+
+ l = (c->Nl + (((uint64_t)len) << 3)) & OPENSSL_U64(0xffffffffffffffff);
+ if (l < c->Nl) {
+ c->Nh++;
+ }
+ if (sizeof(len) >= 8) {
+ c->Nh += (((uint64_t)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)) {
+#ifndef SHA512_BLOCK_CAN_MANAGE_UNALIGNED_DATA
+ if ((size_t)data % sizeof(c->u.d[0]) != 0)
+ while (len >= sizeof(c->u))
+ memcpy(p, data, sizeof(c->u)), sha512_block_data_order(c, p, 1),
+ len -= sizeof(c->u), data += sizeof(c->u);
+ else
+#endif
+ 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;
+}
+
+int SHA512_Final(unsigned char *md, SHA512_CTX *sha) {
+ uint8_t *p = (uint8_t *)sha->u.p;
+ size_t n = sha->num;
+
+ p[n] = 0x80; /* There always is a room for one */
+ n++;
+ if (n > (sizeof(sha->u) - 16)) {
+ memset(p + n, 0, sizeof(sha->u) - n);
+ n = 0;
+ sha512_block_data_order(sha, p, 1);
+ }
+
+ memset(p + n, 0, sizeof(sha->u) - 16 - n);
+ p[sizeof(sha->u) - 1] = (uint8_t)(sha->Nl);
+ p[sizeof(sha->u) - 2] = (uint8_t)(sha->Nl >> 8);
+ p[sizeof(sha->u) - 3] = (uint8_t)(sha->Nl >> 16);
+ p[sizeof(sha->u) - 4] = (uint8_t)(sha->Nl >> 24);
+ p[sizeof(sha->u) - 5] = (uint8_t)(sha->Nl >> 32);
+ p[sizeof(sha->u) - 6] = (uint8_t)(sha->Nl >> 40);
+ p[sizeof(sha->u) - 7] = (uint8_t)(sha->Nl >> 48);
+ p[sizeof(sha->u) - 8] = (uint8_t)(sha->Nl >> 56);
+ p[sizeof(sha->u) - 9] = (uint8_t)(sha->Nh);
+ p[sizeof(sha->u) - 10] = (uint8_t)(sha->Nh >> 8);
+ p[sizeof(sha->u) - 11] = (uint8_t)(sha->Nh >> 16);
+ p[sizeof(sha->u) - 12] = (uint8_t)(sha->Nh >> 24);
+ p[sizeof(sha->u) - 13] = (uint8_t)(sha->Nh >> 32);
+ p[sizeof(sha->u) - 14] = (uint8_t)(sha->Nh >> 40);
+ p[sizeof(sha->u) - 15] = (uint8_t)(sha->Nh >> 48);
+ p[sizeof(sha->u) - 16] = (uint8_t)(sha->Nh >> 56);
+
+ sha512_block_data_order(sha, p, 1);
+
+ if (md == 0) {
+ return 0;
+ }
+
+ switch (sha->md_len) {
+ /* Let compiler decide if it's appropriate to unroll... */
+ case SHA384_DIGEST_LENGTH:
+ for (n = 0; n < SHA384_DIGEST_LENGTH / 8; n++) {
+ uint64_t t = sha->h[n];
+
+ *(md++) = (uint8_t)(t >> 56);
+ *(md++) = (uint8_t)(t >> 48);
+ *(md++) = (uint8_t)(t >> 40);
+ *(md++) = (uint8_t)(t >> 32);
+ *(md++) = (uint8_t)(t >> 24);
+ *(md++) = (uint8_t)(t >> 16);
+ *(md++) = (uint8_t)(t >> 8);
+ *(md++) = (uint8_t)(t);
+ }
+ break;
+ case SHA512_DIGEST_LENGTH:
+ for (n = 0; n < SHA512_DIGEST_LENGTH / 8; n++) {
+ uint64_t t = sha->h[n];
+
+ *(md++) = (uint8_t)(t >> 56);
+ *(md++) = (uint8_t)(t >> 48);
+ *(md++) = (uint8_t)(t >> 40);
+ *(md++) = (uint8_t)(t >> 32);
+ *(md++) = (uint8_t)(t >> 24);
+ *(md++) = (uint8_t)(t >> 16);
+ *(md++) = (uint8_t)(t >> 8);
+ *(md++) = (uint8_t)(t);
+ }
+ break;
+ /* ... as well as make sure md_len is not abused. */
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+#ifndef SHA512_ASM
+static const uint64_t K512[80] = {
+ 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f,
+ 0xe9b5dba58189dbbc, 0x3956c25bf348b538, 0x59f111f1b605d019,
+ 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, 0xd807aa98a3030242,
+ 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2,
+ 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235,
+ 0xc19bf174cf692694, 0xe49b69c19ef14ad2, 0xefbe4786384f25e3,
+ 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65, 0x2de92c6f592b0275,
+ 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5,
+ 0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f,
+ 0xbf597fc7beef0ee4, 0xc6e00bf33da88fc2, 0xd5a79147930aa725,
+ 0x06ca6351e003826f, 0x142929670a0e6e70, 0x27b70a8546d22ffc,
+ 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df,
+ 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6,
+ 0x92722c851482353b, 0xa2bfe8a14cf10364, 0xa81a664bbc423001,
+ 0xc24b8b70d0f89791, 0xc76c51a30654be30, 0xd192e819d6ef5218,
+ 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8,
+ 0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99,
+ 0x34b0bcb5e19b48a8, 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb,
+ 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3, 0x748f82ee5defb2fc,
+ 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec,
+ 0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915,
+ 0xc67178f2e372532b, 0xca273eceea26619c, 0xd186b8c721c0c207,
+ 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, 0x06f067aa72176fba,
+ 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b,
+ 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc,
+ 0x431d67c49c100d4c, 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a,
+ 0x5fcb6fab3ad6faec, 0x6c44198c4a475817};
+
+#if defined(__GNUC__) && __GNUC__ >= 2 && !defined(OPENSSL_NO_ASM)
+#if defined(__x86_64) || defined(__x86_64__)
+#define ROTR(a, n) \
+ ({ \
+ uint64_t ret; \
+ asm("rorq %1,%0" : "=r"(ret) : "J"(n), "0"(a) : "cc"); \
+ ret; \
+ })
+#define PULL64(x) \
+ ({ \
+ uint64_t ret = *((const uint64_t *)(&(x))); \
+ asm("bswapq %0" : "=r"(ret) : "0"(ret)); \
+ ret; \
+ })
+#elif(defined(__i386) || defined(__i386__))
+#define PULL64(x) \
+ ({ \
+ const unsigned int *p = (const unsigned int *)(&(x)); \
+ unsigned int hi = p[0], lo = p[1]; \
+ asm("bswapl %0; bswapl %1;" : "=r"(lo), "=r"(hi) : "0"(lo), "1"(hi)); \
+ ((uint64_t)hi) << 32 | lo; \
+ })
+#elif(defined(_ARCH_PPC) && defined(__64BIT__)) || defined(_ARCH_PPC64)
+#define ROTR(a, n) \
+ ({ \
+ uint64_t ret; \
+ asm("rotrdi %0,%1,%2" : "=r"(ret) : "r"(a), "K"(n)); \
+ ret; \
+ })
+#elif defined(__aarch64__)
+#define ROTR(a, n) \
+ ({ \
+ uint64_t ret; \
+ asm("ror %0,%1,%2" : "=r"(ret) : "r"(a), "I"(n)); \
+ ret; \
+ })
+#if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \
+ __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+#define PULL64(x) \
+ ({ \
+ uint64_t ret; \
+ asm("rev %0,%1" : "=r"(ret) : "r"(*((const uint64_t *)(&(x))))); \
+ ret; \
+ })
+#endif
+#endif
+#elif defined(_MSC_VER)
+#if defined(_WIN64) /* applies to both IA-64 and AMD64 */
+#pragma intrinsic(_rotr64)
+#define ROTR(a, n) _rotr64((a), n)
+#endif
+#if defined(_M_IX86) && !defined(OPENSSL_NO_ASM)
+static uint64_t __fastcall __pull64be(const void *x) {
+ _asm mov edx, [ecx + 0]
+ _asm mov eax, [ecx + 4]
+ _asm bswap edx
+ _asm bswap eax
+}
+#define PULL64(x) __pull64be(&(x))
+#if _MSC_VER <= 1200
+#pragma inline_depth(0)
+#endif
+#endif
+#endif
+
+#ifndef PULL64
+#define B(x, j) \
+ (((uint64_t)(*(((const unsigned char *)(&x)) + j))) << ((7 - j) * 8))
+#define PULL64(x) \
+ (B(x, 0) | B(x, 1) | B(x, 2) | B(x, 3) | B(x, 4) | B(x, 5) | B(x, 6) | \
+ B(x, 7))
+#endif
+
+#ifndef ROTR
+#define ROTR(x, s) (((x) >> s) | (x) << (64 - s))
+#endif
+
+#define Sigma0(x) (ROTR((x), 28) ^ ROTR((x), 34) ^ ROTR((x), 39))
+#define Sigma1(x) (ROTR((x), 14) ^ ROTR((x), 18) ^ ROTR((x), 41))
+#define sigma0(x) (ROTR((x), 1) ^ ROTR((x), 8) ^ ((x) >> 7))
+#define sigma1(x) (ROTR((x), 19) ^ ROTR((x), 61) ^ ((x) >> 6))
+
+#define Ch(x, y, z) (((x) & (y)) ^ ((~(x)) & (z)))
+#define Maj(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
+
+
+#if defined(__i386) || defined(__i386__) || defined(_M_IX86)
+/*
+ * This code should give better results on 32-bit CPU with less than
+ * ~24 registers, both size and performance wise...
+ */
+static void sha512_block_data_order(SHA512_CTX *ctx, const void *in,
+ size_t num) {
+ const uint64_t *W = in;
+ uint64_t A, E, T;
+ uint64_t X[9 + 80], *F;
+ int i;
+
+ while (num--) {
+ F = X + 80;
+ A = ctx->h[0];
+ F[1] = ctx->h[1];
+ F[2] = ctx->h[2];
+ F[3] = ctx->h[3];
+ E = ctx->h[4];
+ F[5] = ctx->h[5];
+ F[6] = ctx->h[6];
+ F[7] = ctx->h[7];
+
+ for (i = 0; i < 16; i++, F--) {
+ T = PULL64(W[i]);
+ F[0] = A;
+ F[4] = E;
+ F[8] = T;
+ T += F[7] + Sigma1(E) + Ch(E, F[5], F[6]) + K512[i];
+ E = F[3] + T;
+ A = T + Sigma0(A) + Maj(A, F[1], F[2]);
+ }
+
+ for (; i < 80; i++, F--) {
+ T = sigma0(F[8 + 16 - 1]);
+ T += sigma1(F[8 + 16 - 14]);
+ T += F[8 + 16] + F[8 + 16 - 9];
+
+ F[0] = A;
+ F[4] = E;
+ F[8] = T;
+ T += F[7] + Sigma1(E) + Ch(E, F[5], F[6]) + K512[i];
+ E = F[3] + T;
+ A = T + Sigma0(A) + Maj(A, F[1], F[2]);
+ }
+
+ ctx->h[0] += A;
+ ctx->h[1] += F[1];
+ ctx->h[2] += F[2];
+ ctx->h[3] += F[3];
+ ctx->h[4] += E;
+ ctx->h[5] += F[5];
+ ctx->h[6] += F[6];
+ ctx->h[7] += F[7];
+
+ W += 16;
+ }
+}
+
+#else
+
+#define ROUND_00_15(i, a, b, c, d, e, f, g, h) \
+ do { \
+ T1 += h + Sigma1(e) + Ch(e, f, g) + K512[i]; \
+ h = Sigma0(a) + Maj(a, b, c); \
+ d += T1; \
+ h += T1; \
+ } while (0)
+
+#define ROUND_16_80(i, j, a, b, c, d, e, f, g, h, X) \
+ do { \
+ s0 = X[(j + 1) & 0x0f]; \
+ s0 = sigma0(s0); \
+ s1 = X[(j + 14) & 0x0f]; \
+ s1 = sigma1(s1); \
+ T1 = X[(j) & 0x0f] += s0 + s1 + X[(j + 9) & 0x0f]; \
+ ROUND_00_15(i + j, a, b, c, d, e, f, g, h); \
+ } while (0)
+
+static void sha512_block_data_order(SHA512_CTX *ctx, const void *in,
+ size_t num) {
+ const uint64_t *W = in;
+ uint64_t a, b, c, d, e, f, g, h, s0, s1, T1;
+ uint64_t 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];
+
+ T1 = X[0] = PULL64(W[0]);
+ ROUND_00_15(0, a, b, c, d, e, f, g, h);
+ T1 = X[1] = PULL64(W[1]);
+ ROUND_00_15(1, h, a, b, c, d, e, f, g);
+ T1 = X[2] = PULL64(W[2]);
+ ROUND_00_15(2, g, h, a, b, c, d, e, f);
+ T1 = X[3] = PULL64(W[3]);
+ ROUND_00_15(3, f, g, h, a, b, c, d, e);
+ T1 = X[4] = PULL64(W[4]);
+ ROUND_00_15(4, e, f, g, h, a, b, c, d);
+ T1 = X[5] = PULL64(W[5]);
+ ROUND_00_15(5, d, e, f, g, h, a, b, c);
+ T1 = X[6] = PULL64(W[6]);
+ ROUND_00_15(6, c, d, e, f, g, h, a, b);
+ T1 = X[7] = PULL64(W[7]);
+ ROUND_00_15(7, b, c, d, e, f, g, h, a);
+ T1 = X[8] = PULL64(W[8]);
+ ROUND_00_15(8, a, b, c, d, e, f, g, h);
+ T1 = X[9] = PULL64(W[9]);
+ ROUND_00_15(9, h, a, b, c, d, e, f, g);
+ T1 = X[10] = PULL64(W[10]);
+ ROUND_00_15(10, g, h, a, b, c, d, e, f);
+ T1 = X[11] = PULL64(W[11]);
+ ROUND_00_15(11, f, g, h, a, b, c, d, e);
+ T1 = X[12] = PULL64(W[12]);
+ ROUND_00_15(12, e, f, g, h, a, b, c, d);
+ T1 = X[13] = PULL64(W[13]);
+ ROUND_00_15(13, d, e, f, g, h, a, b, c);
+ T1 = X[14] = PULL64(W[14]);
+ ROUND_00_15(14, c, d, e, f, g, h, a, b);
+ T1 = X[15] = PULL64(W[15]);
+ ROUND_00_15(15, b, c, d, e, f, g, h, a);
+
+ for (i = 16; i < 80; i += 16) {
+ ROUND_16_80(i, 0, a, b, c, d, e, f, g, h, X);
+ ROUND_16_80(i, 1, h, a, b, c, d, e, f, g, X);
+ ROUND_16_80(i, 2, g, h, a, b, c, d, e, f, X);
+ ROUND_16_80(i, 3, f, g, h, a, b, c, d, e, X);
+ ROUND_16_80(i, 4, e, f, g, h, a, b, c, d, X);
+ ROUND_16_80(i, 5, d, e, f, g, h, a, b, c, X);
+ ROUND_16_80(i, 6, c, d, e, f, g, h, a, b, X);
+ ROUND_16_80(i, 7, b, c, d, e, f, g, h, a, X);
+ ROUND_16_80(i, 8, a, b, c, d, e, f, g, h, X);
+ ROUND_16_80(i, 9, h, a, b, c, d, e, f, g, X);
+ ROUND_16_80(i, 10, g, h, a, b, c, d, e, f, X);
+ ROUND_16_80(i, 11, f, g, h, a, b, c, d, e, X);
+ ROUND_16_80(i, 12, e, f, g, h, a, b, c, d, X);
+ ROUND_16_80(i, 13, d, e, f, g, h, a, b, c, X);
+ ROUND_16_80(i, 14, c, d, e, f, g, h, a, b, X);
+ ROUND_16_80(i, 15, b, c, d, e, f, g, h, a, X);
+ }
+
+ 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;
+
+ W += 16;
+ }
+}
+
+#endif
+
+#endif /* SHA512_ASM */
diff --git a/src/crypto/stack/CMakeLists.txt b/src/crypto/stack/CMakeLists.txt
new file mode 100644
index 0000000..bdb0599
--- /dev/null
+++ b/src/crypto/stack/CMakeLists.txt
@@ -0,0 +1,9 @@
+include_directories(. .. ../../include)
+
+add_library(
+ stack
+
+ OBJECT
+
+ stack.c
+)
diff --git a/src/crypto/stack/make_macros.sh b/src/crypto/stack/make_macros.sh
new file mode 100644
index 0000000..f72aa33
--- /dev/null
+++ b/src/crypto/stack/make_macros.sh
@@ -0,0 +1,112 @@
+#!/bin/sh
+
+include_dir=../../include/openssl
+
+cat > "${include_dir}/stack_macros.h" << EOF
+/* 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. */
+
+#if !defined(IN_STACK_H)
+#error "Don't include this file directly. Include stack.h."
+#endif
+
+EOF
+
+output_stack () {
+ type=$1
+ ptrtype=$2
+
+ cat >> "${include_dir}/stack_macros.h" << EOF
+/* ${type} */
+#define sk_${type}_new(comp)\\
+ ((STACK_OF(${type})*) sk_new(CHECKED_CAST(stack_cmp_func, int (*) (const ${ptrtype} *a, const ${ptrtype} *b), comp)))
+
+#define sk_${type}_new_null()\\
+ ((STACK_OF(${type})*) sk_new_null())
+
+#define sk_${type}_num(sk)\\
+ sk_num(CHECKED_CAST(_STACK*, STACK_OF(${type})*, sk))
+
+#define sk_${type}_zero(sk)\\
+ sk_zero(CHECKED_CAST(_STACK*, STACK_OF(${type})*, sk));
+
+#define sk_${type}_value(sk, i)\\
+ ((${ptrtype}) sk_value(CHECKED_CAST(_STACK*, const STACK_OF(${type})*, sk), (i)))
+
+#define sk_${type}_set(sk, i, p)\\
+ ((${ptrtype}) sk_set(CHECKED_CAST(_STACK*, STACK_OF(${type})*, sk), (i), CHECKED_CAST(void*, ${ptrtype}, p)))
+
+#define sk_${type}_free(sk)\\
+ sk_free(CHECKED_CAST(_STACK*, STACK_OF(${type})*, sk))
+
+#define sk_${type}_pop_free(sk, free_func)\\
+ sk_pop_free(CHECKED_CAST(_STACK*, STACK_OF(${type})*, sk), CHECKED_CAST(void (*) (void*), void (*) (${ptrtype}), free_func))
+
+#define sk_${type}_insert(sk, p, where)\\
+ sk_insert(CHECKED_CAST(_STACK*, STACK_OF(${type})*, sk), CHECKED_CAST(void*, ${ptrtype}, p), (where))
+
+#define sk_${type}_delete(sk, where)\\
+ ((${ptrtype}) sk_delete(CHECKED_CAST(_STACK*, STACK_OF(${type})*, sk), (where)))
+
+#define sk_${type}_delete_ptr(sk, p)\\
+ ((${ptrtype}) sk_delete_ptr(CHECKED_CAST(_STACK*, STACK_OF(${type})*, sk), CHECKED_CAST(void*, ${ptrtype}, p)))
+
+#define sk_${type}_find(sk, out_index, p)\\
+ sk_find(CHECKED_CAST(_STACK*, STACK_OF(${type})*, sk), (out_index), CHECKED_CAST(void*, ${ptrtype}, p))
+
+#define sk_${type}_shift(sk)\\
+ ((${ptrtype}) sk_shift(CHECKED_CAST(_STACK*, STACK_OF(${type})*, sk)))
+
+#define sk_${type}_push(sk, p)\\
+ sk_push(CHECKED_CAST(_STACK*, STACK_OF(${type})*, sk), CHECKED_CAST(void*, ${ptrtype}, p))
+
+#define sk_${type}_pop(sk)\\
+ ((${ptrtype}) sk_pop(CHECKED_CAST(_STACK*, STACK_OF(${type})*, sk)))
+
+#define sk_${type}_dup(sk)\\
+ ((STACK_OF(${type})*) sk_dup(CHECKED_CAST(_STACK*, const STACK_OF(${type})*, sk)))
+
+#define sk_${type}_sort(sk)\\
+ sk_sort(CHECKED_CAST(_STACK*, STACK_OF(${type})*, sk))
+
+#define sk_${type}_is_sorted(sk)\\
+ sk_is_sorted(CHECKED_CAST(_STACK*, const STACK_OF(${type})*, sk))
+
+#define sk_${type}_set_cmp_func(sk, comp)\\
+ ((int (*) (const ${type} **a, const ${type} **b)) sk_set_cmp_func(CHECKED_CAST(_STACK*, STACK_OF(${type})*, sk), CHECKED_CAST(stack_cmp_func, int (*) (const ${type} **a, const ${type} **b), comp)))
+
+
+EOF
+}
+
+stack_types=$(cat "${include_dir}/stack.h" | grep '^ \* STACK_OF:' | sed -e 's/.*STACK_OF://' -e 's/ .*//')
+const_stack_types=$(cat "${include_dir}/stack.h" | grep '^ \* CONST_STACK_OF:' | sed -e 's/.*CONST_STACK_OF://' -e 's/ .*//')
+special_stack_types=$(cat "${include_dir}/stack.h" | grep '^ \* SPECIAL_STACK_OF:' | sed -e 's/.*SPECIAL_STACK_OF://' -e 's/ .*//')
+
+for type in $stack_types; do
+ echo Stack of ${type}
+ output_stack "${type}" "${type} *"
+done
+
+for type in $const_stack_types; do
+ echo Stack of ${type}
+ output_stack "${type}" "const ${type} *"
+done
+
+for type in $special_stack_types; do
+ echo Stack of ${type}
+ output_stack "${type}" "${type}"
+done
+
+clang-format -i "${include_dir}/stack_macros.h"
diff --git a/src/crypto/stack/stack.c b/src/crypto/stack/stack.c
new file mode 100644
index 0000000..0b336ba
--- /dev/null
+++ b/src/crypto/stack/stack.c
@@ -0,0 +1,362 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/stack.h>
+
+#include <string.h>
+
+#include <openssl/mem.h>
+
+/* kMinSize is the number of pointers that will be initially allocated in a new
+ * stack. */
+static const size_t kMinSize = 4;
+
+_STACK *sk_new(stack_cmp_func comp) {
+ _STACK *ret;
+
+ ret = OPENSSL_malloc(sizeof(_STACK));
+ if (ret == NULL) {
+ goto err;
+ }
+ memset(ret, 0, sizeof(_STACK));
+
+ ret->data = OPENSSL_malloc(sizeof(void *) * kMinSize);
+ if (ret->data == NULL) {
+ goto err;
+ }
+
+ memset(ret->data, 0, sizeof(void *) * kMinSize);
+
+ ret->comp = comp;
+ ret->num_alloc = kMinSize;
+
+ return ret;
+
+err:
+ if (ret) {
+ OPENSSL_free(ret);
+ }
+ return NULL;
+}
+
+_STACK *sk_new_null(void) { return sk_new(NULL); }
+
+size_t sk_num(const _STACK *sk) {
+ if (sk == NULL) {
+ return 0;
+ }
+ return sk->num;
+}
+
+void sk_zero(_STACK *sk) {
+ if (sk == NULL || sk->num == 0) {
+ return;
+ }
+ memset(sk->data, 0, sizeof(void*) * sk->num);
+ sk->num = 0;
+ sk->sorted = 0;
+}
+
+void *sk_value(const _STACK *sk, size_t i) {
+ if (!sk || i >= sk->num) {
+ return NULL;
+ }
+ return sk->data[i];
+}
+
+void *sk_set(_STACK *sk, size_t i, void *value) {
+ if (!sk || i >= sk->num) {
+ return NULL;
+ }
+ return sk->data[i] = value;
+}
+
+void sk_free(_STACK *sk) {
+ if (sk == NULL) {
+ return;
+ }
+ OPENSSL_free(sk->data);
+ OPENSSL_free(sk);
+}
+
+void sk_pop_free(_STACK *sk, void (*func)(void *)) {
+ size_t i;
+
+ if (sk == NULL) {
+ return;
+ }
+
+ for (i = 0; i < sk->num; i++) {
+ if (sk->data[i] != NULL) {
+ func(sk->data[i]);
+ }
+ }
+ sk_free(sk);
+}
+
+size_t sk_insert(_STACK *sk, void *p, size_t where) {
+ if (sk == NULL) {
+ return 0;
+ }
+
+ if (sk->num_alloc <= sk->num + 1) {
+ /* Attempt to double the size of the array. */
+ size_t new_alloc = sk->num_alloc << 1;
+ size_t alloc_size = new_alloc * sizeof(void *);
+ void **data;
+
+ /* If the doubling overflowed, try to increment. */
+ if (new_alloc < sk->num_alloc || alloc_size / sizeof(void *) != new_alloc) {
+ new_alloc = sk->num_alloc + 1;
+ alloc_size = new_alloc * sizeof(void *);
+ }
+
+ /* If the increment also overflowed, fail. */
+ if (new_alloc < sk->num_alloc || alloc_size / sizeof(void *) != new_alloc) {
+ return 0;
+ }
+
+ data = OPENSSL_realloc(sk->data, alloc_size);
+ if (data == NULL) {
+ return 0;
+ }
+
+ sk->data = data;
+ sk->num_alloc = new_alloc;
+ }
+
+ if (where >= sk->num) {
+ sk->data[sk->num] = p;
+ } else {
+ memmove(&sk->data[where + 1], &sk->data[where],
+ sizeof(void *) * (sk->num - where));
+ sk->data[where] = p;
+ }
+
+ sk->num++;
+ sk->sorted = 0;
+
+ return sk->num;
+}
+
+void *sk_delete(_STACK *sk, size_t where) {
+ void *ret;
+
+ if (!sk || where >= sk->num) {
+ return NULL;
+ }
+
+ ret = sk->data[where];
+
+ if (where != sk->num - 1) {
+ memmove(&sk->data[where], &sk->data[where + 1],
+ sizeof(void *) * (sk->num - where - 1));
+ }
+
+ sk->num--;
+ return ret;
+}
+
+void *sk_delete_ptr(_STACK *sk, void *p) {
+ size_t i;
+
+ if (sk == NULL) {
+ return NULL;
+ }
+
+ for (i = 0; i < sk->num; i++) {
+ if (sk->data[i] == p) {
+ return sk_delete(sk, i);
+ }
+ }
+
+ return NULL;
+}
+
+int sk_find(_STACK *sk, size_t *out_index, void *p) {
+ const void *const *r;
+ size_t i;
+ int (*comp_func)(const void *,const void *);
+
+ if (sk == NULL) {
+ return -1;
+ }
+
+ if (sk->comp == NULL) {
+ /* Use pointer equality when no comparison function has been set. */
+ for (i = 0; i < sk->num; i++) {
+ if (sk->data[i] == p) {
+ if (out_index) {
+ *out_index = i;
+ }
+ return 1;
+ }
+ }
+ return 0;
+ }
+
+ if (p == NULL) {
+ return 0;
+ }
+
+ sk_sort(sk);
+
+ /* sk->comp is a function that takes pointers to pointers to elements, but
+ * qsort and bsearch take a comparison function that just takes pointers to
+ * elements. However, since we're passing an array of pointers to
+ * qsort/bsearch, we can just cast the comparison function and everything
+ * works. */
+ comp_func=(int (*)(const void *,const void *))(sk->comp);
+ r = bsearch(&p, sk->data, sk->num, sizeof(void *), comp_func);
+ if (r == NULL) {
+ return 0;
+ }
+ i = ((void **)r) - sk->data;
+ /* This function always returns the first result. */
+ while (i > 0 && sk->comp((const void**) &p, (const void**) &sk->data[i-1]) == 0) {
+ i--;
+ }
+ if (out_index) {
+ *out_index = i;
+ }
+ return 1;
+}
+
+void *sk_shift(_STACK *sk) {
+ if (sk == NULL) {
+ return NULL;
+ }
+ if (sk->num == 0) {
+ return NULL;
+ }
+ return sk_delete(sk, 0);
+}
+
+size_t sk_push(_STACK *sk, void *p) { return (sk_insert(sk, p, sk->num)); }
+
+void *sk_pop(_STACK *sk) {
+ if (sk == NULL) {
+ return NULL;
+ }
+ if (sk->num == 0) {
+ return NULL;
+ }
+ return sk_delete(sk, sk->num - 1);
+}
+
+_STACK *sk_dup(const _STACK *sk) {
+ _STACK *ret;
+ void **s;
+
+ if (sk == NULL) {
+ return NULL;
+ }
+
+ ret = sk_new(sk->comp);
+ if (ret == NULL) {
+ goto err;
+ }
+
+ s = (void **)OPENSSL_realloc(ret->data, sizeof(void *) * sk->num_alloc);
+ if (s == NULL) {
+ goto err;
+ }
+ ret->data = s;
+
+ ret->num = sk->num;
+ memcpy(ret->data, sk->data, sizeof(void *) * 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;
+}
+
+void sk_sort(_STACK *sk) {
+ int (*comp_func)(const void *,const void *);
+
+ if (sk == NULL || sk->sorted) {
+ return;
+ }
+
+ /* See the comment in sk_find about this cast. */
+ comp_func = (int (*)(const void *, const void *))(sk->comp);
+ qsort(sk->data, sk->num, sizeof(void *), comp_func);
+ sk->sorted = 1;
+}
+
+int sk_is_sorted(const _STACK *sk) {
+ if (!sk) {
+ return 1;
+ }
+ return sk->sorted;
+}
+
+stack_cmp_func sk_set_cmp_func(_STACK *sk, stack_cmp_func comp) {
+ stack_cmp_func old = sk->comp;
+
+ if (sk->comp != comp) {
+ sk->sorted = 0;
+ }
+ sk->comp = comp;
+
+ return old;
+}
diff --git a/src/crypto/thread.c b/src/crypto/thread.c
new file mode 100644
index 0000000..f18bc13
--- /dev/null
+++ b/src/crypto/thread.c
@@ -0,0 +1,203 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/thread.h>
+
+#include <errno.h>
+#include <string.h>
+
+#if defined(OPENSSL_WINDOWS)
+#pragma warning(push, 3)
+#include <Windows.h>
+#pragma warning(pop)
+#endif
+
+#include <openssl/mem.h>
+#include <openssl/type_check.h>
+
+
+/* lock_names contains the names of all the locks defined in thread.h. */
+static const char *const lock_names[] = {
+ "<<ERROR>>", "err", "ex_data", "x509",
+ "x509_info", "x509_pkey", "x509_crl", "x509_req",
+ "dsa", "rsa", "evp_pkey", "x509_store",
+ "ssl_ctx", "ssl_cert", "ssl_session", "ssl_sess_cert",
+ "ssl", "ssl_method", "rand", "rand2",
+ "debug_malloc", "BIO", "gethostbyname", "getservbyname",
+ "readdir", "RSA_blinding", "dh", "debug_malloc2",
+ "dso", "dynlock", "engine", "ui",
+ "ecdsa", "ec", "ecdh", "bn",
+ "ec_pre_comp", "store", "comp", "fips",
+ "fips2", "obj",
+};
+
+OPENSSL_COMPILE_ASSERT(CRYPTO_NUM_LOCKS ==
+ sizeof(lock_names) / sizeof(lock_names[0]),
+ CRYPTO_NUM_LOCKS_inconsistent);
+
+static void (*locking_callback)(int mode, int lock_num, const char *file,
+ int line) = 0;
+static int (*add_lock_callback)(int *pointer, int amount, int lock_num,
+ const char *file, int line) = 0;
+static void (*threadid_callback)(CRYPTO_THREADID *) = 0;
+
+
+int CRYPTO_num_locks(void) { return CRYPTO_NUM_LOCKS; }
+
+void CRYPTO_set_locking_callback(void (*func)(int mode, int lock_num,
+ const char *file, int line)) {
+ locking_callback = func;
+}
+
+void CRYPTO_set_add_lock_callback(int (*func)(int *num, int mount, int lock_num,
+ const char *file, int line)) {
+ add_lock_callback = func;
+}
+
+const char *CRYPTO_get_lock_name(int lock_num) {
+ if (lock_num >= 0 && lock_num < CRYPTO_NUM_LOCKS) {
+ return lock_names[lock_num];
+ } else {
+ return "ERROR";
+ }
+}
+
+int CRYPTO_THREADID_set_callback(void (*func)(CRYPTO_THREADID *)) {
+ if (threadid_callback) {
+ return 0;
+ }
+ threadid_callback = func;
+ return 1;
+}
+
+void CRYPTO_THREADID_set_numeric(CRYPTO_THREADID *id, unsigned long val) {
+ memset(id, 0, sizeof(*id));
+ id->val = val;
+}
+
+void CRYPTO_THREADID_set_pointer(CRYPTO_THREADID *id, void *ptr) {
+ memset(id, 0, sizeof(*id));
+ id->ptr = ptr;
+}
+
+void (*CRYPTO_get_locking_callback(void))(int mode, int lock_num,
+ const char *file, int line) {
+ return locking_callback;
+}
+
+int (*CRYPTO_get_add_lock_callback(void))(int *num, int mount, int lock_num,
+ const char *file, int line) {
+ return add_lock_callback;
+}
+
+void CRYPTO_lock(int mode, int lock_num, const char *file, int line) {
+ if (locking_callback != NULL) {
+ locking_callback(mode, lock_num, file, line);
+ }
+}
+
+int CRYPTO_add_lock(int *pointer, int amount, int lock_num, const char *file,
+ int line) {
+ int ret = 0;
+
+ if (add_lock_callback != NULL) {
+ ret = add_lock_callback(pointer, amount, lock_num, file, line);
+ } else {
+ CRYPTO_lock(CRYPTO_LOCK | CRYPTO_WRITE, lock_num, file, line);
+ ret = *pointer + amount;
+ *pointer = ret;
+ CRYPTO_lock(CRYPTO_UNLOCK | CRYPTO_WRITE, lock_num, file, line);
+ }
+
+ return ret;
+}
+
+void CRYPTO_THREADID_current(CRYPTO_THREADID *id) {
+ if (threadid_callback) {
+ threadid_callback(id);
+ return;
+ }
+
+#if defined(OPENSSL_WINDOWS)
+ CRYPTO_THREADID_set_numeric(id, (unsigned long)GetCurrentThreadId());
+#else
+ /* For everything else, default to using the address of 'errno' */
+ CRYPTO_THREADID_set_pointer(id, (void *)&errno);
+#endif
+}
+
+int CRYPTO_THREADID_cmp(const CRYPTO_THREADID *a, const CRYPTO_THREADID *b) {
+ return memcmp(a, b, sizeof(*a));
+}
+
+void CRYPTO_THREADID_cpy(CRYPTO_THREADID *dest, const CRYPTO_THREADID *src) {
+ memcpy(dest, src, sizeof(*src));
+}
+
+uint32_t CRYPTO_THREADID_hash(const CRYPTO_THREADID *id) {
+ return OPENSSL_hash32(id, sizeof(CRYPTO_THREADID));
+}
+
+void CRYPTO_set_id_callback(unsigned long (*func)(void)) {}
+
+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)) {}
diff --git a/src/crypto/time_support.c b/src/crypto/time_support.c
new file mode 100644
index 0000000..bbfe303
--- /dev/null
+++ b/src/crypto/time_support.c
@@ -0,0 +1,200 @@
+/* Written by Richard Levitte (richard@levitte.org) for the OpenSSL
+ * project 2001.
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2008.
+ */
+/* ====================================================================
+ * 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). */
+
+#if !defined(_POSIX_C_SOURCE)
+#define _POSIX_C_SOURCE 201410L /* for gmtime_r */
+#endif
+
+#include <openssl/time_support.h>
+
+#define SECS_PER_DAY (24 * 60 * 60)
+
+struct tm *OPENSSL_gmtime(const time_t *time, struct tm *result) {
+#if defined(OPENSSL_WINDOWS)
+ if (gmtime_s(result, time)) {
+ return NULL;
+ }
+ return result;
+#else
+ return gmtime_r(time, result);
+#endif
+}
+
+/* Convert date to and from julian day Uses Fliegel & Van Flandern algorithm */
+static long date_to_julian(int y, int m, int d) {
+ return (1461 * (y + 4800 + (m - 14) / 12)) / 4 +
+ (367 * (m - 2 - 12 * ((m - 14) / 12))) / 12 -
+ (3 * ((y + 4900 + (m - 14) / 12) / 100)) / 4 + d - 32075;
+}
+
+static void julian_to_date(long jd, int *y, int *m, int *d) {
+ long L = jd + 68569;
+ long n = (4 * L) / 146097;
+ long i, j;
+
+ L = L - (146097 * n + 3) / 4;
+ i = (4000 * (L + 1)) / 1461001;
+ L = L - (1461 * i) / 4 + 31;
+ j = (80 * L) / 2447;
+ *d = L - (2447 * j) / 80;
+ L = j / 11;
+ *m = j + 2 - (12 * L);
+ *y = 100 * (n - 49) + i + L;
+}
+
+/* Convert tm structure and offset into julian day and seconds */
+static int julian_adj(const struct tm *tm, int off_day, long offset_sec,
+ long *pday, int *psec) {
+ int offset_hms, offset_day;
+ long time_jd;
+ int time_year, time_month, time_day;
+ /* split offset into days and day seconds */
+ offset_day = offset_sec / SECS_PER_DAY;
+ /* Avoid sign issues with % operator */
+ offset_hms = offset_sec - (offset_day * SECS_PER_DAY);
+ offset_day += off_day;
+ /* Add current time seconds to offset */
+ offset_hms += tm->tm_hour * 3600 + tm->tm_min * 60 + tm->tm_sec;
+ /* Adjust day seconds if overflow */
+ if (offset_hms >= SECS_PER_DAY) {
+ offset_day++;
+ offset_hms -= SECS_PER_DAY;
+ } else if (offset_hms < 0) {
+ offset_day--;
+ offset_hms += SECS_PER_DAY;
+ }
+
+ /* Convert date of time structure into a Julian day number. */
+
+ time_year = tm->tm_year + 1900;
+ time_month = tm->tm_mon + 1;
+ time_day = tm->tm_mday;
+
+ time_jd = date_to_julian(time_year, time_month, time_day);
+
+ /* Work out Julian day of new date */
+ time_jd += offset_day;
+
+ if (time_jd < 0)
+ return 0;
+
+ *pday = time_jd;
+ *psec = offset_hms;
+ return 1;
+}
+
+int OPENSSL_gmtime_adj(struct tm *tm, int off_day, long offset_sec) {
+ int time_sec, time_year, time_month, time_day;
+ long time_jd;
+
+ /* Convert time and offset into julian day and seconds */
+ if (!julian_adj(tm, off_day, offset_sec, &time_jd, &time_sec))
+ return 0;
+
+ /* Convert Julian day back to date */
+
+ julian_to_date(time_jd, &time_year, &time_month, &time_day);
+
+ if (time_year < 1900 || time_year > 9999)
+ return 0;
+
+ /* Update tm structure */
+
+ tm->tm_year = time_year - 1900;
+ tm->tm_mon = time_month - 1;
+ tm->tm_mday = time_day;
+
+ tm->tm_hour = time_sec / 3600;
+ tm->tm_min = (time_sec / 60) % 60;
+ tm->tm_sec = time_sec % 60;
+
+ return 1;
+}
+
+int OPENSSL_gmtime_diff(int *pday, int *psec, const struct tm *from,
+ const struct tm *to) {
+ int from_sec, to_sec, diff_sec;
+ long from_jd, to_jd, diff_day;
+
+ if (!julian_adj(from, 0, 0, &from_jd, &from_sec)) {
+ return 0;
+ }
+ if (!julian_adj(to, 0, 0, &to_jd, &to_sec)) {
+ return 0;
+ }
+
+ diff_day = to_jd - from_jd;
+ diff_sec = to_sec - from_sec;
+ /* Adjust differences so both positive or both negative */
+ if (diff_day > 0 && diff_sec < 0) {
+ diff_day--;
+ diff_sec += SECS_PER_DAY;
+ }
+ if (diff_day < 0 && diff_sec > 0) {
+ diff_day++;
+ diff_sec -= SECS_PER_DAY;
+ }
+
+ if (pday) {
+ *pday = (int)diff_day;
+ }
+ if (psec) {
+ *psec = diff_sec;
+ }
+
+ return 1;
+}
diff --git a/src/crypto/x509/CMakeLists.txt b/src/crypto/x509/CMakeLists.txt
new file mode 100644
index 0000000..f00e28a
--- /dev/null
+++ b/src/crypto/x509/CMakeLists.txt
@@ -0,0 +1,65 @@
+include_directories(. .. ../../include)
+
+add_library(
+ x509
+
+ OBJECT
+
+ a_digest.c
+ a_sign.c
+ a_strex.c
+ a_verify.c
+ asn1_gen.c
+ by_dir.c
+ by_file.c
+ i2d_pr.c
+ pkcs7.c
+ t_crl.c
+ t_x509.c
+ t_x509a.c
+ x509.c
+ x509_att.c
+ x509_cmp.c
+ x509_d2.c
+ x509_def.c
+ x509_error.c
+ x509_ext.c
+ x509_lu.c
+ x509_obj.c
+ x509_r2x.c
+ x509_req.c
+ x509_set.c
+ x509_trs.c
+ x509_txt.c
+ x509_v3.c
+ x509_vfy.c
+ x509_vpm.c
+ x509cset.c
+ x509name.c
+ x509rset.c
+ x509spki.c
+ x509type.c
+ x_algor.c
+ x_all.c
+ x_attrib.c
+ x_crl.c
+ x_exten.c
+ x_info.c
+ x_name.c
+ x_pkey.c
+ x_pubkey.c
+ x_req.c
+ x_sig.c
+ x_spki.c
+ x_val.c
+ x_x509.c
+ x_x509a.c
+)
+
+add_executable(
+ pkcs7_test
+
+ pkcs7_test.c
+)
+
+target_link_libraries(pkcs7_test crypto)
diff --git a/src/crypto/x509/a_digest.c b/src/crypto/x509/a_digest.c
new file mode 100644
index 0000000..6060bbd
--- /dev/null
+++ b/src/crypto/x509/a_digest.c
@@ -0,0 +1,97 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/x509.h>
+
+#include <openssl/asn1.h>
+#include <openssl/digest.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+
+
+int ASN1_digest(i2d_of_void *i2d, const EVP_MD *type, char *data,
+ unsigned char *md, unsigned int *len)
+ {
+ int i, ret;
+ unsigned char *str,*p;
+
+ i=i2d(data,NULL);
+ if ((str=(unsigned char *)OPENSSL_malloc(i)) == NULL)
+ {
+ OPENSSL_PUT_ERROR(X509, ASN1_digest, ERR_R_MALLOC_FAILURE);
+ return(0);
+ }
+ p=str;
+ i2d(data,&p);
+
+ ret = EVP_Digest(str, i, md, len, type, NULL);
+ OPENSSL_free(str);
+ return ret;
+ }
+
+int ASN1_item_digest(const ASN1_ITEM *it, const EVP_MD *type, void *asn,
+ unsigned char *md, unsigned int *len)
+ {
+ int i, ret;
+ unsigned char *str = NULL;
+
+ i=ASN1_item_i2d(asn,&str, it);
+ if (!str) return(0);
+
+ ret = EVP_Digest(str, i, md, len, type, NULL);
+ OPENSSL_free(str);
+ return ret;
+ }
diff --git a/src/crypto/x509/a_sign.c b/src/crypto/x509/a_sign.c
new file mode 100644
index 0000000..f219c23
--- /dev/null
+++ b/src/crypto/x509/a_sign.c
@@ -0,0 +1,136 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/asn1.h>
+#include <openssl/digest.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/x509.h>
+
+#include "../evp/internal.h"
+
+
+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);
+ }
+
+
+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;
+ unsigned char *buf_in=NULL,*buf_out=NULL;
+ size_t inl=0,outl=0,outll=0;
+
+ pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx);
+
+ /* Write out the requested copies of the AlgorithmIdentifier. */
+ if (algor1 && !EVP_DigestSignAlgorithm(ctx, algor1))
+ {
+ goto err;
+ }
+ if (algor2 && !EVP_DigestSignAlgorithm(ctx, algor2))
+ {
+ goto err;
+ }
+
+ inl=ASN1_item_i2d(asn,&buf_in, it);
+ outll=outl=EVP_PKEY_size(pkey);
+ buf_out=OPENSSL_malloc((unsigned int)outl);
+ if ((buf_in == NULL) || (buf_out == NULL))
+ {
+ outl=0;
+ OPENSSL_PUT_ERROR(X509, ASN1_item_sign_ctx, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (!EVP_DigestSignUpdate(ctx, buf_in, inl)
+ || !EVP_DigestSignFinal(ctx, buf_out, &outl))
+ {
+ outl=0;
+ OPENSSL_PUT_ERROR(X509, ASN1_item_sign_ctx, ERR_R_EVP_LIB);
+ goto err;
+ }
+ if (signature->data != NULL) OPENSSL_free(signature->data);
+ signature->data=buf_out;
+ buf_out=NULL;
+ signature->length=outl;
+ /* In the interests of compatibility, I'll make sure that
+ * the bit string has a 'not-used bits' value of 0
+ */
+ signature->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07);
+ signature->flags|=ASN1_STRING_FLAG_BITS_LEFT;
+err:
+ EVP_MD_CTX_cleanup(ctx);
+ if (buf_in != NULL)
+ { OPENSSL_cleanse((char *)buf_in,(unsigned int)inl); OPENSSL_free(buf_in); }
+ if (buf_out != NULL)
+ { OPENSSL_cleanse((char *)buf_out,outll); OPENSSL_free(buf_out); }
+ return(outl);
+ }
diff --git a/src/crypto/x509/a_strex.c b/src/crypto/x509/a_strex.c
new file mode 100644
index 0000000..b194d18
--- /dev/null
+++ b/src/crypto/x509/a_strex.c
@@ -0,0 +1,564 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/x509.h>
+
+#include <string.h>
+
+#include <openssl/asn1.h>
+#include <openssl/mem.h>
+#include <openssl/obj.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)
+
+
+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, len, arg) != (unsigned int)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.
+ */
+
+#define HEX_SIZE(type) (sizeof(type)*2)
+
+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[HEX_SIZE(long)+3];
+
+ if(c > 0xffffffffL)
+ return -1;
+ if(c > 0xffff) {
+ BIO_snprintf(tmphex, sizeof tmphex, "\\W%08lX", c);
+ if(!io_ch(arg, tmphex, 10)) return -1;
+ return 10;
+ }
+ if(c > 0xff) {
+ BIO_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)) {
+ BIO_snprintf(tmphex, 11, "\\%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++;
+ break;
+
+ case 2:
+ c = ((unsigned long)*p++) << 8;
+ c |= *p++;
+ break;
+
+ case 1:
+ c = *p++;
+ break;
+
+ case 0:
+ i = UTF8_getc(p, buflen, &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);
+ 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, 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 = OPENSSL_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);
+ OPENSSL_free(der_buf);
+ if(outlen < 0) return -1;
+ return outlen + 1;
+}
+
+/* Lookup table to convert tags to character widths,
+ * 0 = UTF8 encoded, -1 is used for non string types
+ * otherwise it is the number of bytes per character
+ */
+
+static const signed char tag2nbyte[] = {
+ -1, -1, -1, -1, -1, /* 0-4 */
+ -1, -1, -1, -1, -1, /* 5-9 */
+ -1, -1, 0, -1, /* 10-13 */
+ -1, -1, -1, -1, /* 15-17 */
+ -1, 1, 1, /* 18-20 */
+ -1, 1, 1, 1, /* 21-24 */
+ -1, 1, -1, /* 25-27 */
+ 4, -1, 2 /* 28-30 */
+};
+
+/* 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, 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 */
+
+ /* Dump everything */
+ if(lflags & ASN1_STRFLGS_DUMP_ALL) type = -1;
+ /* Ignore the string type */
+ else if(lflags & ASN1_STRFLGS_IGNORE_TYPE) type = 1;
+ else {
+ /* Else determine width based on type */
+ if((type > 0) && (type < 31)) type = tag2nbyte[type];
+ else type = -1;
+ 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, &quotes, 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, 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;
+ const 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 == ent->set) {
+ 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 = ent->set;
+ 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, 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);
+}
+
+#ifndef OPENSSL_NO_FP_API
+int X509_NAME_print_ex_fp(FILE *fp, 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);
+}
+#endif
+
+int ASN1_STRING_print_ex(BIO *out, ASN1_STRING *str, unsigned long flags)
+{
+ return do_print_ex(send_bio_chars, out, flags, str);
+}
+
+#ifndef OPENSSL_NO_FP_API
+int ASN1_STRING_print_ex_fp(FILE *fp, ASN1_STRING *str, unsigned long flags)
+{
+ return do_print_ex(send_fp_chars, fp, flags, str);
+}
+#endif
+
+/* 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, ASN1_STRING *in)
+{
+ ASN1_STRING stmp, *str = &stmp;
+ int mbflag, type, ret;
+ if(!in) return -1;
+ type = in->type;
+ if((type < 0) || (type > 30)) return -1;
+ mbflag = tag2nbyte[type];
+ if(mbflag == -1) return -1;
+ mbflag |= MBSTRING_FLAG;
+ stmp.data = NULL;
+ stmp.length = 0;
+ stmp.flags = 0;
+ ret = ASN1_mbstring_copy(&str, in->data, in->length, mbflag, B_ASN1_UTF8STRING);
+ if(ret < 0) return ret;
+ *out = stmp.data;
+ return stmp.length;
+}
diff --git a/src/crypto/x509/a_verify.c b/src/crypto/x509/a_verify.c
new file mode 100644
index 0000000..72e0a62
--- /dev/null
+++ b/src/crypto/x509/a_verify.c
@@ -0,0 +1,133 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/x509.h>
+
+#include <stdio.h>
+#include <time.h>
+#include <sys/types.h>
+
+#include <openssl/bn.h>
+#include <openssl/buf.h>
+#include <openssl/digest.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+
+#include "../evp/internal.h"
+
+
+int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a,
+ ASN1_BIT_STRING *signature, void *asn, EVP_PKEY *pkey)
+ {
+ EVP_MD_CTX ctx;
+ uint8_t *buf_in = NULL;
+ int ret = 0, inl;
+
+ if (!pkey)
+ {
+ OPENSSL_PUT_ERROR(X509, ASN1_item_verify, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ if (signature->type == V_ASN1_BIT_STRING && signature->flags & 0x7)
+ {
+ OPENSSL_PUT_ERROR(X509, ASN1_item_verify, X509_R_INVALID_BIT_STRING_BITS_LEFT);
+ return 0;
+ }
+
+ EVP_MD_CTX_init(&ctx);
+
+ if (!EVP_DigestVerifyInitFromAlgorithm(&ctx, a, pkey))
+ {
+ goto err;
+ }
+
+ inl = ASN1_item_i2d(asn, &buf_in, it);
+
+ if (buf_in == NULL)
+ {
+ OPENSSL_PUT_ERROR(X509, ASN1_item_verify, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (!EVP_DigestVerifyUpdate(&ctx,buf_in,inl))
+ {
+ OPENSSL_cleanse(buf_in,(unsigned int)inl);
+ OPENSSL_free(buf_in);
+ OPENSSL_PUT_ERROR(X509, ASN1_item_verify, ERR_R_EVP_LIB);
+ goto err;
+ }
+
+ OPENSSL_cleanse(buf_in,(unsigned int)inl);
+ OPENSSL_free(buf_in);
+
+ if (EVP_DigestVerifyFinal(&ctx,signature->data,
+ (size_t)signature->length) <= 0)
+ {
+ OPENSSL_PUT_ERROR(X509, ASN1_item_verify, ERR_R_EVP_LIB);
+ goto err;
+ }
+ /* we don't need to zero the 'ctx' because we just checked
+ * public information */
+ /* memset(&ctx,0,sizeof(ctx)); */
+ ret = 1;
+err:
+ EVP_MD_CTX_cleanup(&ctx);
+ return ret;
+ }
+
diff --git a/src/crypto/x509/asn1_gen.c b/src/crypto/x509/asn1_gen.c
new file mode 100644
index 0000000..750701e
--- /dev/null
+++ b/src/crypto/x509/asn1_gen.c
@@ -0,0 +1,862 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/x509.h>
+
+#include <string.h>
+
+#include <openssl/asn1.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/x509v3.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(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);
+ }
+
+ASN1_TYPE *ASN1_generate_v3(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;
+ 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)
+ {
+ OPENSSL_PUT_ERROR(X509, ASN1_generate_v3, 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 = OPENSSL_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:
+ if (orig_der)
+ OPENSSL_free(orig_der);
+ if (new_der)
+ OPENSSL_free(new_der);
+
+ return ret;
+
+ }
+
+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;
+
+ if (elem == NULL)
+ return 0;
+
+ 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)
+ {
+ OPENSSL_PUT_ERROR(X509, asn1_cb, ASN1_R_UNKNOWN_TAG);
+ ERR_add_error_data(2, "tag=", 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])
+ {
+ OPENSSL_PUT_ERROR(X509, asn1_cb, 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)
+ {
+ OPENSSL_PUT_ERROR(X509, asn1_cb, 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 (!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", 3))
+ arg->format = ASN1_GEN_FORMAT_BITLIST;
+ else
+ {
+ OPENSSL_PUT_ERROR(X509, asn1_cb, ASN1_R_UNKNOWN_FORMAT);
+ return -1;
+ }
+ break;
+
+ }
+
+ return 1;
+
+ }
+
+static int parse_tagging(const char *vstart, int vlen, int *ptag, int *pclass)
+ {
+ char erch[2];
+ 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)
+ {
+ OPENSSL_PUT_ERROR(X509, parse_tagging, 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:
+ erch[0] = *eptr;
+ erch[1] = 0;
+ OPENSSL_PUT_ERROR(X509, parse_tagging, ASN1_R_INVALID_MODIFIER);
+ ERR_add_error_data(2, "Char=", erch);
+ 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;
+ size_t 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:
+
+ if (der)
+ OPENSSL_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)
+ {
+ OPENSSL_PUT_ERROR(X509, append_exp, ASN1_R_ILLEGAL_IMPLICIT_TAG);
+ return 0;
+ }
+
+ if (arg->exp_count == ASN1_FLAG_EXP_MAX)
+ {
+ OPENSSL_PUT_ERROR(X509, append_exp, 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()))
+ {
+ OPENSSL_PUT_ERROR(X509, asn1_str2type, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ if (!str)
+ str = "";
+
+ switch(utype)
+ {
+
+ case V_ASN1_NULL:
+ if (str && *str)
+ {
+ OPENSSL_PUT_ERROR(X509, asn1_str2type, ASN1_R_ILLEGAL_NULL_VALUE);
+ goto bad_form;
+ }
+ break;
+
+ case V_ASN1_BOOLEAN:
+ if (format != ASN1_GEN_FORMAT_ASCII)
+ {
+ OPENSSL_PUT_ERROR(X509, asn1_str2type, 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))
+ {
+ OPENSSL_PUT_ERROR(X509, asn1_str2type, ASN1_R_ILLEGAL_BOOLEAN);
+ goto bad_str;
+ }
+ break;
+
+ case V_ASN1_INTEGER:
+ case V_ASN1_ENUMERATED:
+ if (format != ASN1_GEN_FORMAT_ASCII)
+ {
+ OPENSSL_PUT_ERROR(X509, asn1_str2type, ASN1_R_INTEGER_NOT_ASCII_FORMAT);
+ goto bad_form;
+ }
+ if (!(atmp->value.integer = s2i_ASN1_INTEGER(NULL, (char *)str)))
+ {
+ OPENSSL_PUT_ERROR(X509, asn1_str2type, ASN1_R_ILLEGAL_INTEGER);
+ goto bad_str;
+ }
+ break;
+
+ case V_ASN1_OBJECT:
+ if (format != ASN1_GEN_FORMAT_ASCII)
+ {
+ OPENSSL_PUT_ERROR(X509, asn1_str2type, ASN1_R_OBJECT_NOT_ASCII_FORMAT);
+ goto bad_form;
+ }
+ if (!(atmp->value.object = OBJ_txt2obj(str, 0)))
+ {
+ OPENSSL_PUT_ERROR(X509, asn1_str2type, ASN1_R_ILLEGAL_OBJECT);
+ goto bad_str;
+ }
+ break;
+
+ case V_ASN1_UTCTIME:
+ case V_ASN1_GENERALIZEDTIME:
+ if (format != ASN1_GEN_FORMAT_ASCII)
+ {
+ OPENSSL_PUT_ERROR(X509, asn1_str2type, ASN1_R_TIME_NOT_ASCII_FORMAT);
+ goto bad_form;
+ }
+ if (!(atmp->value.asn1_string = ASN1_STRING_new()))
+ {
+ OPENSSL_PUT_ERROR(X509, asn1_str2type, ERR_R_MALLOC_FAILURE);
+ goto bad_str;
+ }
+ if (!ASN1_STRING_set(atmp->value.asn1_string, str, -1))
+ {
+ OPENSSL_PUT_ERROR(X509, asn1_str2type, ERR_R_MALLOC_FAILURE);
+ goto bad_str;
+ }
+ atmp->value.asn1_string->type = utype;
+ if (!ASN1_TIME_check(atmp->value.asn1_string))
+ {
+ OPENSSL_PUT_ERROR(X509, asn1_str2type, 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
+ {
+ OPENSSL_PUT_ERROR(X509, asn1_str2type, ASN1_R_ILLEGAL_FORMAT);
+ goto bad_form;
+ }
+
+
+ if (ASN1_mbstring_copy(&atmp->value.asn1_string, (unsigned char *)str,
+ -1, format, ASN1_tag2bit(utype)) <= 0)
+ {
+ OPENSSL_PUT_ERROR(X509, asn1_str2type, 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()))
+ {
+ OPENSSL_PUT_ERROR(X509, asn1_str2type, ERR_R_MALLOC_FAILURE);
+ goto bad_form;
+ }
+
+ if (format == ASN1_GEN_FORMAT_HEX)
+ {
+
+ if (!(rdata = string_to_hex((char *)str, &rdlen)))
+ {
+ OPENSSL_PUT_ERROR(X509, asn1_str2type, ASN1_R_ILLEGAL_HEX);
+ goto bad_str;
+ }
+
+ atmp->value.asn1_string->data = rdata;
+ atmp->value.asn1_string->length = rdlen;
+ atmp->value.asn1_string->type = utype;
+
+ }
+ else if (format == ASN1_GEN_FORMAT_ASCII)
+ ASN1_STRING_set(atmp->value.asn1_string, str, -1);
+ else if ((format == ASN1_GEN_FORMAT_BITLIST) && (utype == V_ASN1_BIT_STRING))
+ {
+ if (!CONF_parse_list(str, ',', 1, bitstr_cb, atmp->value.bit_string))
+ {
+ OPENSSL_PUT_ERROR(X509, asn1_str2type, ASN1_R_LIST_ERROR);
+ goto bad_str;
+ }
+ no_unused = 0;
+
+ }
+ else
+ {
+ OPENSSL_PUT_ERROR(X509, asn1_str2type, ASN1_R_ILLEGAL_BITSTRING_FORMAT);
+ goto bad_form;
+ }
+
+ if ((utype == V_ASN1_BIT_STRING) && no_unused)
+ {
+ atmp->value.asn1_string->flags
+ &= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07);
+ atmp->value.asn1_string->flags
+ |= ASN1_STRING_FLAG_BITS_LEFT;
+ }
+
+
+ break;
+
+ default:
+ OPENSSL_PUT_ERROR(X509, asn1_str2type, ASN1_R_UNSUPPORTED_TYPE);
+ goto bad_str;
+ break;
+ }
+
+
+ atmp->type = utype;
+ return atmp;
+
+
+ bad_str:
+ ERR_add_error_data(2, "string=", 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)
+ {
+ OPENSSL_PUT_ERROR(X509, bitstr_cb, ASN1_R_INVALID_NUMBER);
+ return 0;
+ }
+ if (!ASN1_BIT_STRING_set_bit(bitstr, bitnum, 1))
+ {
+ OPENSSL_PUT_ERROR(X509, bitstr_cb, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ return 1;
+ }
+
diff --git a/src/crypto/x509/by_dir.c b/src/crypto/x509/by_dir.c
new file mode 100644
index 0000000..5a77b81
--- /dev/null
+++ b/src/crypto/x509/by_dir.c
@@ -0,0 +1,479 @@
+/* crypto/x509/by_dir.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 <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <openssl/buf.h>
+#include <openssl/err.h>
+#include <openssl/lhash.h>
+#include <openssl/mem.h>
+#include <openssl/x509.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);
+X509_LOOKUP_METHOD x509_dir_lookup=
+ {
+ "Load certs from files in a directory",
+ new_dir, /* new */
+ free_dir, /* free */
+ NULL, /* init */
+ NULL, /* shutdown */
+ dir_ctrl, /* ctrl */
+ get_cert_by_subject, /* get_by_subject */
+ NULL, /* get_by_issuer_serial */
+ NULL, /* get_by_fingerprint */
+ NULL, /* get_by_alias */
+ };
+
+X509_LOOKUP_METHOD *X509_LOOKUP_hash_dir(void)
+ {
+ return(&x509_dir_lookup);
+ }
+
+static int dir_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl,
+ char **retp)
+ {
+ int ret=0;
+ BY_DIR *ld;
+ char *dir = NULL;
+
+ ld=(BY_DIR *)ctx->method_data;
+
+ switch (cmd)
+ {
+ case X509_L_ADD_DIR:
+ if (argl == X509_FILETYPE_DEFAULT)
+ {
+ dir=(char *)getenv(X509_get_default_cert_dir_env());
+ if (dir)
+ ret=add_cert_dir(ld,dir,X509_FILETYPE_PEM);
+ else
+ ret=add_cert_dir(ld,X509_get_default_cert_dir(),
+ X509_FILETYPE_PEM);
+ if (!ret)
+ {
+ OPENSSL_PUT_ERROR(X509, dir_ctrl, 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=(BY_DIR *)OPENSSL_malloc(sizeof(BY_DIR))) == NULL)
+ return(0);
+ if ((a->buffer=BUF_MEM_new()) == NULL)
+ {
+ OPENSSL_free(a);
+ return(0);
+ }
+ a->dirs=NULL;
+ lu->method_data=(char *)a;
+ return(1);
+ }
+
+static void by_dir_hash_free(BY_DIR_HASH *hash)
+ {
+ OPENSSL_free(hash);
+ }
+
+static int by_dir_hash_cmp(const BY_DIR_HASH **a,
+ const BY_DIR_HASH **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)
+ {
+ if (ent->dir)
+ OPENSSL_free(ent->dir);
+ if (ent->hashes)
+ sk_BY_DIR_HASH_pop_free(ent->hashes, by_dir_hash_free);
+ OPENSSL_free(ent);
+ }
+
+static void free_dir(X509_LOOKUP *lu)
+ {
+ BY_DIR *a;
+
+ a=(BY_DIR *)lu->method_data;
+ if (a->dirs != NULL)
+ sk_BY_DIR_ENTRY_pop_free(a->dirs, by_dir_entry_free);
+ if (a->buffer != NULL)
+ BUF_MEM_free(a->buffer);
+ OPENSSL_free(a);
+ }
+
+static int add_cert_dir(BY_DIR *ctx, const char *dir, int type)
+ {
+ size_t j,len;
+ const char *s,*ss,*p;
+
+ if (dir == NULL || !*dir)
+ {
+ OPENSSL_PUT_ERROR(X509, add_cert_dir, 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) == len &&
+ strncmp(ent->dir,ss,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)
+ {
+ OPENSSL_PUT_ERROR(X509, add_cert_dir, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ }
+ ent = OPENSSL_malloc(sizeof(BY_DIR_ENTRY));
+ if (!ent)
+ return 0;
+ ent->dir_type = type;
+ ent->hashes = sk_BY_DIR_HASH_new(by_dir_hash_cmp);
+ ent->dir = OPENSSL_malloc(len+1);
+ if (!ent->dir || !ent->hashes)
+ {
+ by_dir_entry_free(ent);
+ return 0;
+ }
+ strncpy(ent->dir,ss,len);
+ ent->dir[len] = '\0';
+ if (!sk_BY_DIR_ENTRY_push(ctx->dirs, ent))
+ {
+ 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;
+ size_t i;
+ int j,k;
+ unsigned long h;
+ unsigned long hash_array[2];
+ int hash_index;
+ 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
+ {
+ OPENSSL_PUT_ERROR(X509, get_cert_by_subject, X509_R_WRONG_LOOKUP_TYPE);
+ goto finish;
+ }
+
+ if ((b=BUF_MEM_new()) == NULL)
+ {
+ OPENSSL_PUT_ERROR(X509, get_cert_by_subject, ERR_R_BUF_LIB);
+ goto finish;
+ }
+
+ ctx=(BY_DIR *)xl->method_data;
+
+ hash_array[0]=X509_NAME_hash(name);
+ hash_array[1]=X509_NAME_hash_old(name);
+ for (hash_index=0; hash_index < 2; ++hash_index)
+ {
+ h=hash_array[hash_index];
+ for (i=0; i < sk_BY_DIR_ENTRY_num(ctx->dirs); i++)
+ {
+ BY_DIR_ENTRY *ent;
+ size_t 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))
+ {
+ OPENSSL_PUT_ERROR(X509, get_cert_by_subject, ERR_R_MALLOC_FAILURE);
+ goto finish;
+ }
+ if (type == X509_LU_CRL && ent->hashes)
+ {
+ htmp.hash = h;
+ CRYPTO_r_lock(CRYPTO_LOCK_X509_STORE);
+ if (sk_BY_DIR_HASH_find(ent->hashes, &idx, &htmp))
+ {
+ 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 (;;)
+ {
+ char c = '/';
+#ifdef OPENSSL_SYS_VMS
+ c = ent->dir[strlen(ent->dir)-1];
+ if (c != ':' && c != '>' && c != ']')
+ {
+ /* If no separator is present, we assume the
+ directory specifier is a logical name, and
+ add a colon. We really should use better
+ VMS routines for merging things like this,
+ but this will do for now...
+ -- Richard Levitte */
+ c = ':';
+ }
+ else
+ {
+ c = '\0';
+ }
+#endif
+ if (c == '\0')
+ {
+ /* This is special. When c == '\0', no
+ directory separator should be added. */
+ BIO_snprintf(b->data,b->max,
+ "%s%08lx.%s%d",ent->dir,h,
+ postfix,k);
+ }
+ else
+ {
+ BIO_snprintf(b->data,b->max,
+ "%s%c%08lx.%s%d",ent->dir,c,h,
+ postfix,k);
+ }
+#ifndef OPENSSL_NO_POSIX_IO
+#ifdef _WIN32
+#define stat _stat
+#endif
+ {
+ struct stat st;
+ if (stat(b->data,&st) < 0)
+ break;
+ }
+#endif
+ /* 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);
+ tmp = NULL;
+ if (sk_X509_OBJECT_find(xl->store_ctx->objs, &idx, &stmp)) {
+ tmp=sk_X509_OBJECT_value(xl->store_ctx->objs,idx);
+ }
+ 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)
+ {
+ htmp.hash = h;
+ if (sk_BY_DIR_HASH_find(ent->hashes, &idx, &htmp))
+ hent = sk_BY_DIR_HASH_value(ent->hashes, idx);
+ }
+ if (!hent)
+ {
+ hent = OPENSSL_malloc(sizeof(BY_DIR_HASH));
+ hent->hash = h;
+ hent->suffix = k;
+ if (!sk_BY_DIR_HASH_push(ent->hashes, hent))
+ {
+ CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
+ OPENSSL_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));
+ /* If we were going to up the reference count,
+ * we would need to do it on a perl 'type'
+ * basis */
+ /* CRYPTO_add(&tmp->data.x509->references,1,
+ CRYPTO_LOCK_X509);*/
+ goto finish;
+ }
+ }
+ }
+finish:
+ if (b != NULL) BUF_MEM_free(b);
+ return(ok);
+ }
diff --git a/src/crypto/x509/by_file.c b/src/crypto/x509/by_file.c
new file mode 100644
index 0000000..2649631
--- /dev/null
+++ b/src/crypto/x509/by_file.c
@@ -0,0 +1,292 @@
+/* crypto/x509/by_file.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 <openssl/buf.h>
+#include <openssl/err.h>
+#include <openssl/lhash.h>
+#include <openssl/pem.h>
+#include <openssl/x509.h>
+
+#ifndef OPENSSL_NO_STDIO
+
+static int by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc,
+ long argl, char **ret);
+X509_LOOKUP_METHOD x509_file_lookup=
+ {
+ "Load file into cache",
+ NULL, /* new */
+ NULL, /* free */
+ NULL, /* init */
+ NULL, /* shutdown */
+ by_file_ctrl, /* ctrl */
+ NULL, /* get_by_subject */
+ NULL, /* get_by_issuer_serial */
+ NULL, /* get_by_fingerprint */
+ NULL, /* get_by_alias */
+ };
+
+X509_LOOKUP_METHOD *X509_LOOKUP_file(void)
+ {
+ return(&x509_file_lookup);
+ }
+
+static int by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl,
+ char **ret)
+ {
+ int ok=0;
+ char *file;
+
+ switch (cmd)
+ {
+ case X509_L_FILE_LOAD:
+ if (argl == X509_FILETYPE_DEFAULT)
+ {
+ file = (char *)getenv(X509_get_default_cert_file_env());
+ if (file)
+ ok = (X509_load_cert_crl_file(ctx,file,
+ X509_FILETYPE_PEM) != 0);
+
+ else
+ ok = (X509_load_cert_crl_file(ctx,X509_get_default_cert_file(),
+ X509_FILETYPE_PEM) != 0);
+
+ if (!ok)
+ {
+ OPENSSL_PUT_ERROR(X509, by_file_ctrl, 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;
+
+ if (file == NULL) return(1);
+ in=BIO_new(BIO_s_file());
+
+ if ((in == NULL) || (BIO_read_filename(in,file) <= 0))
+ {
+ OPENSSL_PUT_ERROR(X509, X509_load_cert_file, ERR_R_SYS_LIB);
+ goto err;
+ }
+
+ if (type == X509_FILETYPE_PEM)
+ {
+ for (;;)
+ {
+ x=PEM_read_bio_X509_AUX(in,NULL,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
+ {
+ OPENSSL_PUT_ERROR(X509, X509_load_cert_file, 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)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_load_cert_file, ERR_R_ASN1_LIB);
+ goto err;
+ }
+ i=X509_STORE_add_cert(ctx->store_ctx,x);
+ if (!i) goto err;
+ ret=i;
+ }
+ else
+ {
+ OPENSSL_PUT_ERROR(X509, X509_load_cert_file, X509_R_BAD_X509_FILETYPE);
+ goto err;
+ }
+err:
+ if (x != NULL) X509_free(x);
+ if (in != NULL) BIO_free(in);
+ return(ret);
+ }
+
+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;
+
+ if (file == NULL) return(1);
+ in=BIO_new(BIO_s_file());
+
+ if ((in == NULL) || (BIO_read_filename(in,file) <= 0))
+ {
+ OPENSSL_PUT_ERROR(X509, X509_load_crl_file, ERR_R_SYS_LIB);
+ goto err;
+ }
+
+ if (type == X509_FILETYPE_PEM)
+ {
+ for (;;)
+ {
+ x=PEM_read_bio_X509_CRL(in,NULL,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
+ {
+ OPENSSL_PUT_ERROR(X509, X509_load_crl_file, 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)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_load_crl_file, ERR_R_ASN1_LIB);
+ goto err;
+ }
+ i=X509_STORE_add_crl(ctx->store_ctx,x);
+ if (!i) goto err;
+ ret=i;
+ }
+ else
+ {
+ OPENSSL_PUT_ERROR(X509, X509_load_crl_file, X509_R_BAD_X509_FILETYPE);
+ goto err;
+ }
+err:
+ if (x != NULL) X509_CRL_free(x);
+ if (in != NULL) BIO_free(in);
+ return(ret);
+ }
+
+int X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type)
+{
+ STACK_OF(X509_INFO) *inf;
+ X509_INFO *itmp;
+ BIO *in;
+ size_t i;
+ int count = 0;
+ if(type != X509_FILETYPE_PEM)
+ return X509_load_cert_file(ctx, file, type);
+ in = BIO_new_file(file, "r");
+ if(!in) {
+ OPENSSL_PUT_ERROR(X509, X509_load_cert_crl_file, ERR_R_SYS_LIB);
+ return 0;
+ }
+ inf = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL);
+ BIO_free(in);
+ if(!inf) {
+ OPENSSL_PUT_ERROR(X509, X509_load_cert_crl_file, 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++;
+ }
+ }
+ sk_X509_INFO_pop_free(inf, X509_INFO_free);
+ return count;
+}
+
+#endif /* OPENSSL_NO_STDIO */
diff --git a/src/crypto/x509/charmap.h b/src/crypto/x509/charmap.h
new file mode 100644
index 0000000..b55e638
--- /dev/null
+++ b/src/crypto/x509/charmap.h
@@ -0,0 +1,15 @@
+/* Auto generated with chartype.pl script.
+ * Mask of various character properties
+ */
+
+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
+};
+
diff --git a/src/crypto/x509/i2d_pr.c b/src/crypto/x509/i2d_pr.c
new file mode 100644
index 0000000..8896565
--- /dev/null
+++ b/src/crypto/x509/i2d_pr.c
@@ -0,0 +1,83 @@
+/* crypto/asn1/i2d_pr.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 <openssl/x509.h>
+
+#include <stdio.h>
+
+#include <openssl/err.h>
+#include <openssl/evp.h>
+
+#include "../evp/internal.h"
+
+
+int i2d_PrivateKey(const 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((EVP_PKEY*)a);
+ int ret = i2d_PKCS8_PRIV_KEY_INFO(p8,pp);
+ PKCS8_PRIV_KEY_INFO_free(p8);
+ return ret;
+ }
+ OPENSSL_PUT_ERROR(X509, i2d_PrivateKey, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
+ return -1;
+ }
+
diff --git a/src/crypto/x509/pkcs7.c b/src/crypto/x509/pkcs7.c
new file mode 100644
index 0000000..75c101b
--- /dev/null
+++ b/src/crypto/x509/pkcs7.c
@@ -0,0 +1,154 @@
+/* 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 <openssl/x509.h>
+
+#include <openssl/bytestring.h>
+#include <openssl/err.h>
+#include <openssl/obj.h>
+#include <openssl/stack.h>
+
+#include "../bytestring/internal.h"
+
+
+int PKCS7_get_certificates(STACK_OF(X509) *out_certs, CBS *cbs) {
+ uint8_t *der_bytes = NULL;
+ size_t der_len;
+ CBS in, content_info, content_type, wrapped_signed_data, signed_data,
+ certificates;
+ const size_t initial_certs_len = sk_X509_num(out_certs);
+ uint64_t version;
+ int ret = 0;
+
+ /* The input may be in BER format. */
+ if (!CBS_asn1_ber_to_der(cbs, &der_bytes, &der_len)) {
+ return 0;
+ }
+ if (der_bytes != NULL) {
+ CBS_init(&in, der_bytes, der_len);
+ } else {
+ CBS_init(&in, CBS_data(cbs), CBS_len(cbs));
+ }
+
+ /* See https://tools.ietf.org/html/rfc2315#section-7 */
+ if (!CBS_get_asn1(&in, &content_info, CBS_ASN1_SEQUENCE) ||
+ !CBS_get_asn1(&content_info, &content_type, CBS_ASN1_OBJECT)) {
+ goto err;
+ }
+
+ if (OBJ_cbs2nid(&content_type) != NID_pkcs7_signed) {
+ OPENSSL_PUT_ERROR(X509, PKCS7_get_certificates,
+ X509_R_NOT_PKCS7_SIGNED_DATA);
+ goto err;
+ }
+
+ /* See https://tools.ietf.org/html/rfc2315#section-9.1 */
+ if (!CBS_get_asn1(&content_info, &wrapped_signed_data,
+ CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
+ !CBS_get_asn1(&wrapped_signed_data, &signed_data, CBS_ASN1_SEQUENCE) ||
+ !CBS_get_asn1_uint64(&signed_data, &version) ||
+ !CBS_get_asn1(&signed_data, NULL /* digests */, CBS_ASN1_SET) ||
+ !CBS_get_asn1(&signed_data, NULL /* content */, CBS_ASN1_SEQUENCE)) {
+ goto err;
+ }
+
+ if (version < 1) {
+ OPENSSL_PUT_ERROR(X509, PKCS7_get_certificates,
+ X509_R_BAD_PKCS7_VERSION);
+ goto err;
+ }
+
+ if (!CBS_get_asn1(&signed_data, &certificates,
+ CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) {
+ OPENSSL_PUT_ERROR(X509, PKCS7_get_certificates,
+ X509_R_NO_CERTIFICATES_INCLUDED);
+ goto err;
+ }
+
+ while (CBS_len(&certificates) > 0) {
+ CBS cert;
+ X509 *x509;
+ const uint8_t *inp;
+
+ if (!CBS_get_asn1_element(&certificates, &cert, CBS_ASN1_SEQUENCE)) {
+ goto err;
+ }
+
+ inp = CBS_data(&cert);
+ x509 = d2i_X509(NULL, &inp, CBS_len(&cert));
+ if (!x509) {
+ goto err;
+ }
+
+ if (inp != CBS_data(&cert) + CBS_len(&cert)) {
+ /* This suggests a disconnect between the two ASN.1 parsers. */
+ goto err;
+ }
+
+ sk_X509_push(out_certs, x509);
+ }
+
+ ret = 1;
+
+err:
+ if (der_bytes) {
+ OPENSSL_free(der_bytes);
+ }
+
+ if (!ret) {
+ while (sk_X509_num(out_certs) != initial_certs_len) {
+ X509 *x509 = sk_X509_pop(out_certs);
+ X509_free(x509);
+ }
+ }
+
+ return ret;
+}
+
+int PKCS7_bundle_certificates(CBB *out, const STACK_OF(X509) *certs) {
+ CBB outer_seq, wrapped_seq, seq, version_bytes, digest_algos_set,
+ content_info, certificates;
+ size_t i;
+
+ /* See https://tools.ietf.org/html/rfc2315#section-7 */
+ if (!CBB_add_asn1(out, &outer_seq, CBS_ASN1_SEQUENCE) ||
+ !OBJ_nid2cbb(&outer_seq, NID_pkcs7_signed) ||
+ !CBB_add_asn1(&outer_seq, &wrapped_seq,
+ CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
+ /* See https://tools.ietf.org/html/rfc2315#section-9.1 */
+ !CBB_add_asn1(&wrapped_seq, &seq, CBS_ASN1_SEQUENCE) ||
+ !CBB_add_asn1(&seq, &version_bytes, CBS_ASN1_INTEGER) ||
+ !CBB_add_u8(&version_bytes, 1) ||
+ !CBB_add_asn1(&seq, &digest_algos_set, CBS_ASN1_SET) ||
+ !CBB_add_asn1(&seq, &content_info, CBS_ASN1_SEQUENCE) ||
+ !OBJ_nid2cbb(&content_info, NID_pkcs7_data) ||
+ !CBB_add_asn1(&seq, &certificates,
+ CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) {
+ return 0;
+ }
+
+ for (i = 0; i < sk_X509_num(certs); i++) {
+ X509 *x509 = sk_X509_value(certs, i);
+ uint8_t *buf;
+ int len = i2d_X509(x509, NULL);
+
+ if (len < 0 ||
+ !CBB_add_space(&certificates, &buf, len) ||
+ i2d_X509(x509, &buf) < 0) {
+ return 0;
+ }
+ }
+
+ return CBB_flush(out);
+}
diff --git a/src/crypto/x509/pkcs7_test.c b/src/crypto/x509/pkcs7_test.c
new file mode 100644
index 0000000..4283022
--- /dev/null
+++ b/src/crypto/x509/pkcs7_test.c
@@ -0,0 +1,409 @@
+/* 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <openssl/bytestring.h>
+#include <openssl/crypto.h>
+#include <openssl/stack.h>
+#include <openssl/x509.h>
+
+
+/* kPKCS7NSS contains the certificate chain of mail.google.com, as saved by NSS
+ * using the Chrome UI. */
+static const uint8_t kPKCS7NSS[] = {
+ 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07,
+ 0x02, 0xa0, 0x80, 0x30, 0x80, 0x02, 0x01, 0x01, 0x31, 0x00, 0x30, 0x80,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x00,
+ 0x00, 0xa0, 0x82, 0x0b, 0x1e, 0x30, 0x82, 0x03, 0x54, 0x30, 0x82, 0x02,
+ 0x3c, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x02, 0x34, 0x56, 0x30,
+ 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05,
+ 0x05, 0x00, 0x30, 0x42, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
+ 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55,
+ 0x04, 0x0a, 0x13, 0x0d, 0x47, 0x65, 0x6f, 0x54, 0x72, 0x75, 0x73, 0x74,
+ 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55,
+ 0x04, 0x03, 0x13, 0x12, 0x47, 0x65, 0x6f, 0x54, 0x72, 0x75, 0x73, 0x74,
+ 0x20, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x43, 0x41, 0x30, 0x1e,
+ 0x17, 0x0d, 0x30, 0x32, 0x30, 0x35, 0x32, 0x31, 0x30, 0x34, 0x30, 0x30,
+ 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x32, 0x32, 0x30, 0x35, 0x32, 0x31, 0x30,
+ 0x34, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x42, 0x31, 0x0b, 0x30, 0x09,
+ 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30,
+ 0x14, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0d, 0x47, 0x65, 0x6f, 0x54,
+ 0x72, 0x75, 0x73, 0x74, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x1b, 0x30,
+ 0x19, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x12, 0x47, 0x65, 0x6f, 0x54,
+ 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20,
+ 0x43, 0x41, 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, 0xda,
+ 0xcc, 0x18, 0x63, 0x30, 0xfd, 0xf4, 0x17, 0x23, 0x1a, 0x56, 0x7e, 0x5b,
+ 0xdf, 0x3c, 0x6c, 0x38, 0xe4, 0x71, 0xb7, 0x78, 0x91, 0xd4, 0xbc, 0xa1,
+ 0xd8, 0x4c, 0xf8, 0xa8, 0x43, 0xb6, 0x03, 0xe9, 0x4d, 0x21, 0x07, 0x08,
+ 0x88, 0xda, 0x58, 0x2f, 0x66, 0x39, 0x29, 0xbd, 0x05, 0x78, 0x8b, 0x9d,
+ 0x38, 0xe8, 0x05, 0xb7, 0x6a, 0x7e, 0x71, 0xa4, 0xe6, 0xc4, 0x60, 0xa6,
+ 0xb0, 0xef, 0x80, 0xe4, 0x89, 0x28, 0x0f, 0x9e, 0x25, 0xd6, 0xed, 0x83,
+ 0xf3, 0xad, 0xa6, 0x91, 0xc7, 0x98, 0xc9, 0x42, 0x18, 0x35, 0x14, 0x9d,
+ 0xad, 0x98, 0x46, 0x92, 0x2e, 0x4f, 0xca, 0xf1, 0x87, 0x43, 0xc1, 0x16,
+ 0x95, 0x57, 0x2d, 0x50, 0xef, 0x89, 0x2d, 0x80, 0x7a, 0x57, 0xad, 0xf2,
+ 0xee, 0x5f, 0x6b, 0xd2, 0x00, 0x8d, 0xb9, 0x14, 0xf8, 0x14, 0x15, 0x35,
+ 0xd9, 0xc0, 0x46, 0xa3, 0x7b, 0x72, 0xc8, 0x91, 0xbf, 0xc9, 0x55, 0x2b,
+ 0xcd, 0xd0, 0x97, 0x3e, 0x9c, 0x26, 0x64, 0xcc, 0xdf, 0xce, 0x83, 0x19,
+ 0x71, 0xca, 0x4e, 0xe6, 0xd4, 0xd5, 0x7b, 0xa9, 0x19, 0xcd, 0x55, 0xde,
+ 0xc8, 0xec, 0xd2, 0x5e, 0x38, 0x53, 0xe5, 0x5c, 0x4f, 0x8c, 0x2d, 0xfe,
+ 0x50, 0x23, 0x36, 0xfc, 0x66, 0xe6, 0xcb, 0x8e, 0xa4, 0x39, 0x19, 0x00,
+ 0xb7, 0x95, 0x02, 0x39, 0x91, 0x0b, 0x0e, 0xfe, 0x38, 0x2e, 0xd1, 0x1d,
+ 0x05, 0x9a, 0xf6, 0x4d, 0x3e, 0x6f, 0x0f, 0x07, 0x1d, 0xaf, 0x2c, 0x1e,
+ 0x8f, 0x60, 0x39, 0xe2, 0xfa, 0x36, 0x53, 0x13, 0x39, 0xd4, 0x5e, 0x26,
+ 0x2b, 0xdb, 0x3d, 0xa8, 0x14, 0xbd, 0x32, 0xeb, 0x18, 0x03, 0x28, 0x52,
+ 0x04, 0x71, 0xe5, 0xab, 0x33, 0x3d, 0xe1, 0x38, 0xbb, 0x07, 0x36, 0x84,
+ 0x62, 0x9c, 0x79, 0xea, 0x16, 0x30, 0xf4, 0x5f, 0xc0, 0x2b, 0xe8, 0x71,
+ 0x6b, 0xe4, 0xf9, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x53, 0x30, 0x51,
+ 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05,
+ 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e,
+ 0x04, 0x16, 0x04, 0x14, 0xc0, 0x7a, 0x98, 0x68, 0x8d, 0x89, 0xfb, 0xab,
+ 0x05, 0x64, 0x0c, 0x11, 0x7d, 0xaa, 0x7d, 0x65, 0xb8, 0xca, 0xcc, 0x4e,
+ 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80,
+ 0x14, 0xc0, 0x7a, 0x98, 0x68, 0x8d, 0x89, 0xfb, 0xab, 0x05, 0x64, 0x0c,
+ 0x11, 0x7d, 0xaa, 0x7d, 0x65, 0xb8, 0xca, 0xcc, 0x4e, 0x30, 0x0d, 0x06,
+ 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00,
+ 0x03, 0x82, 0x01, 0x01, 0x00, 0x35, 0xe3, 0x29, 0x6a, 0xe5, 0x2f, 0x5d,
+ 0x54, 0x8e, 0x29, 0x50, 0x94, 0x9f, 0x99, 0x1a, 0x14, 0xe4, 0x8f, 0x78,
+ 0x2a, 0x62, 0x94, 0xa2, 0x27, 0x67, 0x9e, 0xd0, 0xcf, 0x1a, 0x5e, 0x47,
+ 0xe9, 0xc1, 0xb2, 0xa4, 0xcf, 0xdd, 0x41, 0x1a, 0x05, 0x4e, 0x9b, 0x4b,
+ 0xee, 0x4a, 0x6f, 0x55, 0x52, 0xb3, 0x24, 0xa1, 0x37, 0x0a, 0xeb, 0x64,
+ 0x76, 0x2a, 0x2e, 0x2c, 0xf3, 0xfd, 0x3b, 0x75, 0x90, 0xbf, 0xfa, 0x71,
+ 0xd8, 0xc7, 0x3d, 0x37, 0xd2, 0xb5, 0x05, 0x95, 0x62, 0xb9, 0xa6, 0xde,
+ 0x89, 0x3d, 0x36, 0x7b, 0x38, 0x77, 0x48, 0x97, 0xac, 0xa6, 0x20, 0x8f,
+ 0x2e, 0xa6, 0xc9, 0x0c, 0xc2, 0xb2, 0x99, 0x45, 0x00, 0xc7, 0xce, 0x11,
+ 0x51, 0x22, 0x22, 0xe0, 0xa5, 0xea, 0xb6, 0x15, 0x48, 0x09, 0x64, 0xea,
+ 0x5e, 0x4f, 0x74, 0xf7, 0x05, 0x3e, 0xc7, 0x8a, 0x52, 0x0c, 0xdb, 0x15,
+ 0xb4, 0xbd, 0x6d, 0x9b, 0xe5, 0xc6, 0xb1, 0x54, 0x68, 0xa9, 0xe3, 0x69,
+ 0x90, 0xb6, 0x9a, 0xa5, 0x0f, 0xb8, 0xb9, 0x3f, 0x20, 0x7d, 0xae, 0x4a,
+ 0xb5, 0xb8, 0x9c, 0xe4, 0x1d, 0xb6, 0xab, 0xe6, 0x94, 0xa5, 0xc1, 0xc7,
+ 0x83, 0xad, 0xdb, 0xf5, 0x27, 0x87, 0x0e, 0x04, 0x6c, 0xd5, 0xff, 0xdd,
+ 0xa0, 0x5d, 0xed, 0x87, 0x52, 0xb7, 0x2b, 0x15, 0x02, 0xae, 0x39, 0xa6,
+ 0x6a, 0x74, 0xe9, 0xda, 0xc4, 0xe7, 0xbc, 0x4d, 0x34, 0x1e, 0xa9, 0x5c,
+ 0x4d, 0x33, 0x5f, 0x92, 0x09, 0x2f, 0x88, 0x66, 0x5d, 0x77, 0x97, 0xc7,
+ 0x1d, 0x76, 0x13, 0xa9, 0xd5, 0xe5, 0xf1, 0x16, 0x09, 0x11, 0x35, 0xd5,
+ 0xac, 0xdb, 0x24, 0x71, 0x70, 0x2c, 0x98, 0x56, 0x0b, 0xd9, 0x17, 0xb4,
+ 0xd1, 0xe3, 0x51, 0x2b, 0x5e, 0x75, 0xe8, 0xd5, 0xd0, 0xdc, 0x4f, 0x34,
+ 0xed, 0xc2, 0x05, 0x66, 0x80, 0xa1, 0xcb, 0xe6, 0x33, 0x30, 0x82, 0x03,
+ 0xba, 0x30, 0x82, 0x02, 0xa2, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08,
+ 0x3e, 0xa3, 0xe4, 0x78, 0x99, 0x38, 0x13, 0x9d, 0x30, 0x0d, 0x06, 0x09,
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30,
+ 0x49, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+ 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13,
+ 0x0a, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x31,
+ 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1c, 0x47, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
+ 0x74, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20,
+ 0x47, 0x32, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x37, 0x31, 0x36,
+ 0x31, 0x32, 0x32, 0x31, 0x34, 0x30, 0x5a, 0x17, 0x0d, 0x31, 0x34, 0x31,
+ 0x30, 0x31, 0x34, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x69,
+ 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55,
+ 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a,
+ 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x16,
+ 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x0d, 0x4d, 0x6f, 0x75,
+ 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x56, 0x69, 0x65, 0x77, 0x31, 0x13,
+ 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x47, 0x6f, 0x6f,
+ 0x67, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x31, 0x18, 0x30, 0x16, 0x06,
+ 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0f, 0x6d, 0x61, 0x69, 0x6c, 0x2e, 0x67,
+ 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 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,
+ 0xb2, 0x68, 0x6e, 0x3f, 0x03, 0x9e, 0x43, 0x85, 0x16, 0xb7, 0x89, 0x0b,
+ 0x16, 0x2a, 0xbe, 0x26, 0x36, 0xdd, 0x68, 0x0a, 0x53, 0x4e, 0x20, 0x40,
+ 0xf8, 0xd1, 0xdd, 0x63, 0xcb, 0x46, 0x73, 0x09, 0x96, 0x36, 0xde, 0x2c,
+ 0x45, 0x71, 0x2e, 0x8a, 0x79, 0xeb, 0x40, 0x2f, 0x65, 0x83, 0x81, 0xdb,
+ 0x37, 0x03, 0x84, 0xa1, 0x9a, 0xd0, 0x22, 0x3b, 0x73, 0x38, 0x45, 0xd3,
+ 0xd5, 0x91, 0xb2, 0x52, 0xa3, 0x82, 0x01, 0x4f, 0x30, 0x82, 0x01, 0x4b,
+ 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, 0x1a, 0x06, 0x03, 0x55,
+ 0x1d, 0x11, 0x04, 0x13, 0x30, 0x11, 0x82, 0x0f, 0x6d, 0x61, 0x69, 0x6c,
+ 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30,
+ 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x07, 0x80,
+ 0x30, 0x68, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01,
+ 0x04, 0x5c, 0x30, 0x5a, 0x30, 0x2b, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05,
+ 0x05, 0x07, 0x30, 0x02, 0x86, 0x1f, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
+ 0x2f, 0x70, 0x6b, 0x69, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
+ 0x63, 0x6f, 0x6d, 0x2f, 0x47, 0x49, 0x41, 0x47, 0x32, 0x2e, 0x63, 0x72,
+ 0x74, 0x30, 0x2b, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30,
+ 0x01, 0x86, 0x1f, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x6c,
+ 0x69, 0x65, 0x6e, 0x74, 0x73, 0x31, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
+ 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x30, 0x1d,
+ 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x75, 0xc6, 0xb0,
+ 0x4a, 0x46, 0x61, 0x83, 0xff, 0x91, 0x46, 0x45, 0x35, 0xa7, 0x0f, 0xd0,
+ 0x5b, 0xe9, 0xdd, 0x94, 0x1b, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13,
+ 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1f, 0x06, 0x03, 0x55,
+ 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x4a, 0xdd, 0x06, 0x16,
+ 0x1b, 0xbc, 0xf6, 0x68, 0xb5, 0x76, 0xf5, 0x81, 0xb6, 0xbb, 0x62, 0x1a,
+ 0xba, 0x5a, 0x81, 0x2f, 0x30, 0x17, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04,
+ 0x10, 0x30, 0x0e, 0x30, 0x0c, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01,
+ 0xd6, 0x79, 0x02, 0x05, 0x01, 0x30, 0x30, 0x06, 0x03, 0x55, 0x1d, 0x1f,
+ 0x04, 0x29, 0x30, 0x27, 0x30, 0x25, 0xa0, 0x23, 0xa0, 0x21, 0x86, 0x1f,
+ 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x70, 0x6b, 0x69, 0x2e, 0x67,
+ 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x47, 0x49,
+ 0x41, 0x47, 0x32, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82,
+ 0x01, 0x01, 0x00, 0x7f, 0x41, 0xf5, 0x57, 0x18, 0x3c, 0x75, 0xf5, 0x23,
+ 0x66, 0xc3, 0xf0, 0xf2, 0x3e, 0x70, 0x34, 0x56, 0xca, 0x78, 0xec, 0xc7,
+ 0x81, 0x58, 0x0d, 0xdf, 0xf0, 0xfd, 0x86, 0xe6, 0xe6, 0x50, 0x3d, 0xf6,
+ 0x09, 0x9a, 0x4d, 0xca, 0x60, 0x37, 0x9a, 0xd4, 0xca, 0x51, 0x7c, 0xf0,
+ 0x66, 0x23, 0xea, 0x5e, 0x6a, 0x6f, 0x7b, 0xa6, 0x7a, 0x38, 0x97, 0x42,
+ 0x58, 0x1a, 0x1b, 0x42, 0xae, 0x28, 0xde, 0x18, 0x7f, 0xcc, 0x76, 0x18,
+ 0x58, 0x05, 0xbf, 0xea, 0xef, 0x14, 0xad, 0x34, 0xe5, 0x5f, 0x25, 0xab,
+ 0xa1, 0x5f, 0x78, 0x5b, 0x6f, 0xe6, 0x69, 0xd8, 0x74, 0x8c, 0x19, 0x59,
+ 0xb0, 0x1a, 0xfb, 0x8e, 0xdf, 0x61, 0xac, 0xeb, 0x2b, 0x0a, 0x1c, 0xab,
+ 0x30, 0x0d, 0x64, 0x25, 0x78, 0xdf, 0x81, 0x71, 0xe3, 0xbd, 0xde, 0x9c,
+ 0x3f, 0xdd, 0xe9, 0xf8, 0xb6, 0x98, 0x2d, 0x13, 0xa3, 0x7b, 0x14, 0x6f,
+ 0xe3, 0x8b, 0xfc, 0x4e, 0x31, 0x26, 0xba, 0x10, 0xb4, 0x12, 0xe9, 0xc9,
+ 0x49, 0x60, 0xf0, 0xaa, 0x1f, 0x44, 0x68, 0x19, 0xd2, 0xb3, 0xc8, 0x46,
+ 0x22, 0x6b, 0xe1, 0x21, 0x77, 0xfd, 0x72, 0x33, 0x13, 0x21, 0x27, 0x81,
+ 0xe4, 0x7a, 0xc9, 0xe4, 0x1c, 0x05, 0x04, 0x73, 0x13, 0xda, 0x47, 0xfe,
+ 0x59, 0x41, 0x9c, 0x11, 0xc5, 0xf6, 0xb5, 0xd0, 0x01, 0xcb, 0x40, 0x19,
+ 0xf5, 0xfe, 0xb3, 0x3c, 0x1f, 0x61, 0x8f, 0x4d, 0xdb, 0x81, 0x2a, 0x8a,
+ 0xed, 0xb8, 0x53, 0xc7, 0x19, 0x6b, 0xfa, 0x8b, 0xfc, 0xe3, 0x2e, 0x12,
+ 0x4e, 0xbd, 0xc5, 0x44, 0x9d, 0x1c, 0x7f, 0x3b, 0x09, 0x51, 0xd7, 0x0a,
+ 0x0f, 0x22, 0x0a, 0xfd, 0x8c, 0x90, 0x14, 0xed, 0x10, 0xcb, 0x50, 0xcf,
+ 0xa5, 0x45, 0xce, 0xb0, 0x21, 0x28, 0xcb, 0xd6, 0xf5, 0x6e, 0xb2, 0x3e,
+ 0xfa, 0x35, 0x0c, 0x3d, 0x09, 0x0d, 0x81, 0x30, 0x82, 0x04, 0x04, 0x30,
+ 0x82, 0x02, 0xec, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x02, 0x3a,
+ 0x69, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
+ 0x01, 0x05, 0x05, 0x00, 0x30, 0x42, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
+ 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06,
+ 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0d, 0x47, 0x65, 0x6f, 0x54, 0x72, 0x75,
+ 0x73, 0x74, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x1b, 0x30, 0x19, 0x06,
+ 0x03, 0x55, 0x04, 0x03, 0x13, 0x12, 0x47, 0x65, 0x6f, 0x54, 0x72, 0x75,
+ 0x73, 0x74, 0x20, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x43, 0x41,
+ 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x33, 0x30, 0x34, 0x30, 0x35, 0x31, 0x35,
+ 0x31, 0x35, 0x35, 0x35, 0x5a, 0x17, 0x0d, 0x31, 0x35, 0x30, 0x34, 0x30,
+ 0x34, 0x31, 0x35, 0x31, 0x35, 0x35, 0x35, 0x5a, 0x30, 0x49, 0x31, 0x0b,
+ 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31,
+ 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x47, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x31, 0x25, 0x30, 0x23,
+ 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1c, 0x47, 0x6f, 0x6f, 0x67, 0x6c,
+ 0x65, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x41,
+ 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x47, 0x32, 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, 0x9c, 0x2a, 0x04, 0x77,
+ 0x5c, 0xd8, 0x50, 0x91, 0x3a, 0x06, 0xa3, 0x82, 0xe0, 0xd8, 0x50, 0x48,
+ 0xbc, 0x89, 0x3f, 0xf1, 0x19, 0x70, 0x1a, 0x88, 0x46, 0x7e, 0xe0, 0x8f,
+ 0xc5, 0xf1, 0x89, 0xce, 0x21, 0xee, 0x5a, 0xfe, 0x61, 0x0d, 0xb7, 0x32,
+ 0x44, 0x89, 0xa0, 0x74, 0x0b, 0x53, 0x4f, 0x55, 0xa4, 0xce, 0x82, 0x62,
+ 0x95, 0xee, 0xeb, 0x59, 0x5f, 0xc6, 0xe1, 0x05, 0x80, 0x12, 0xc4, 0x5e,
+ 0x94, 0x3f, 0xbc, 0x5b, 0x48, 0x38, 0xf4, 0x53, 0xf7, 0x24, 0xe6, 0xfb,
+ 0x91, 0xe9, 0x15, 0xc4, 0xcf, 0xf4, 0x53, 0x0d, 0xf4, 0x4a, 0xfc, 0x9f,
+ 0x54, 0xde, 0x7d, 0xbe, 0xa0, 0x6b, 0x6f, 0x87, 0xc0, 0xd0, 0x50, 0x1f,
+ 0x28, 0x30, 0x03, 0x40, 0xda, 0x08, 0x73, 0x51, 0x6c, 0x7f, 0xff, 0x3a,
+ 0x3c, 0xa7, 0x37, 0x06, 0x8e, 0xbd, 0x4b, 0x11, 0x04, 0xeb, 0x7d, 0x24,
+ 0xde, 0xe6, 0xf9, 0xfc, 0x31, 0x71, 0xfb, 0x94, 0xd5, 0x60, 0xf3, 0x2e,
+ 0x4a, 0xaf, 0x42, 0xd2, 0xcb, 0xea, 0xc4, 0x6a, 0x1a, 0xb2, 0xcc, 0x53,
+ 0xdd, 0x15, 0x4b, 0x8b, 0x1f, 0xc8, 0x19, 0x61, 0x1f, 0xcd, 0x9d, 0xa8,
+ 0x3e, 0x63, 0x2b, 0x84, 0x35, 0x69, 0x65, 0x84, 0xc8, 0x19, 0xc5, 0x46,
+ 0x22, 0xf8, 0x53, 0x95, 0xbe, 0xe3, 0x80, 0x4a, 0x10, 0xc6, 0x2a, 0xec,
+ 0xba, 0x97, 0x20, 0x11, 0xc7, 0x39, 0x99, 0x10, 0x04, 0xa0, 0xf0, 0x61,
+ 0x7a, 0x95, 0x25, 0x8c, 0x4e, 0x52, 0x75, 0xe2, 0xb6, 0xed, 0x08, 0xca,
+ 0x14, 0xfc, 0xce, 0x22, 0x6a, 0xb3, 0x4e, 0xcf, 0x46, 0x03, 0x97, 0x97,
+ 0x03, 0x7e, 0xc0, 0xb1, 0xde, 0x7b, 0xaf, 0x45, 0x33, 0xcf, 0xba, 0x3e,
+ 0x71, 0xb7, 0xde, 0xf4, 0x25, 0x25, 0xc2, 0x0d, 0x35, 0x89, 0x9d, 0x9d,
+ 0xfb, 0x0e, 0x11, 0x79, 0x89, 0x1e, 0x37, 0xc5, 0xaf, 0x8e, 0x72, 0x69,
+ 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xfb, 0x30, 0x81, 0xf8, 0x30,
+ 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14,
+ 0xc0, 0x7a, 0x98, 0x68, 0x8d, 0x89, 0xfb, 0xab, 0x05, 0x64, 0x0c, 0x11,
+ 0x7d, 0xaa, 0x7d, 0x65, 0xb8, 0xca, 0xcc, 0x4e, 0x30, 0x1d, 0x06, 0x03,
+ 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x4a, 0xdd, 0x06, 0x16, 0x1b,
+ 0xbc, 0xf6, 0x68, 0xb5, 0x76, 0xf5, 0x81, 0xb6, 0xbb, 0x62, 0x1a, 0xba,
+ 0x5a, 0x81, 0x2f, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01,
+ 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x00, 0x30,
+ 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03,
+ 0x02, 0x01, 0x06, 0x30, 0x3a, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x33,
+ 0x30, 0x31, 0x30, 0x2f, 0xa0, 0x2d, 0xa0, 0x2b, 0x86, 0x29, 0x68, 0x74,
+ 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e, 0x67, 0x65, 0x6f,
+ 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x72,
+ 0x6c, 0x73, 0x2f, 0x67, 0x74, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x2e,
+ 0x63, 0x72, 0x6c, 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, 0x67, 0x74, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c,
+ 0x2d, 0x6f, 0x63, 0x73, 0x70, 0x2e, 0x67, 0x65, 0x6f, 0x74, 0x72, 0x75,
+ 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x17, 0x06, 0x03, 0x55, 0x1d,
+ 0x20, 0x04, 0x10, 0x30, 0x0e, 0x30, 0x0c, 0x06, 0x0a, 0x2b, 0x06, 0x01,
+ 0x04, 0x01, 0xd6, 0x79, 0x02, 0x05, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82,
+ 0x01, 0x01, 0x00, 0x36, 0xd7, 0x06, 0x80, 0x11, 0x27, 0xad, 0x2a, 0x14,
+ 0x9b, 0x38, 0x77, 0xb3, 0x23, 0xa0, 0x75, 0x58, 0xbb, 0xb1, 0x7e, 0x83,
+ 0x42, 0xba, 0x72, 0xda, 0x1e, 0xd8, 0x8e, 0x36, 0x06, 0x97, 0xe0, 0xf0,
+ 0x95, 0x3b, 0x37, 0xfd, 0x1b, 0x42, 0x58, 0xfe, 0x22, 0xc8, 0x6b, 0xbd,
+ 0x38, 0x5e, 0xd1, 0x3b, 0x25, 0x6e, 0x12, 0xeb, 0x5e, 0x67, 0x76, 0x46,
+ 0x40, 0x90, 0xda, 0x14, 0xc8, 0x78, 0x0d, 0xed, 0x95, 0x66, 0xda, 0x8e,
+ 0x86, 0x6f, 0x80, 0xa1, 0xba, 0x56, 0x32, 0x95, 0x86, 0xdc, 0xdc, 0x6a,
+ 0xca, 0x04, 0x8c, 0x5b, 0x7f, 0xf6, 0xbf, 0xcc, 0x6f, 0x85, 0x03, 0x58,
+ 0xc3, 0x68, 0x51, 0x13, 0xcd, 0xfd, 0xc8, 0xf7, 0x79, 0x3d, 0x99, 0x35,
+ 0xf0, 0x56, 0xa3, 0xbd, 0xe0, 0x59, 0xed, 0x4f, 0x44, 0x09, 0xa3, 0x9e,
+ 0x38, 0x7a, 0xf6, 0x46, 0xd1, 0x1d, 0x12, 0x9d, 0x4f, 0xbe, 0xd0, 0x40,
+ 0xfc, 0x55, 0xfe, 0x06, 0x5e, 0x3c, 0xda, 0x1c, 0x56, 0xbd, 0x96, 0x51,
+ 0x7b, 0x6f, 0x57, 0x2a, 0xdb, 0xa2, 0xaa, 0x96, 0xdc, 0x8c, 0x74, 0xc2,
+ 0x95, 0xbe, 0xf0, 0x6e, 0x95, 0x13, 0xff, 0x17, 0xf0, 0x3c, 0xac, 0xb2,
+ 0x10, 0x8d, 0xcc, 0x73, 0xfb, 0xe8, 0x8f, 0x02, 0xc6, 0xf0, 0xfb, 0x33,
+ 0xb3, 0x95, 0x3b, 0xe3, 0xc2, 0xcb, 0x68, 0x58, 0x73, 0xdb, 0xa8, 0x24,
+ 0x62, 0x3b, 0x06, 0x35, 0x9d, 0x0d, 0xa9, 0x33, 0xbd, 0x78, 0x03, 0x90,
+ 0x2e, 0x4c, 0x78, 0x5d, 0x50, 0x3a, 0x81, 0xd4, 0xee, 0xa0, 0xc8, 0x70,
+ 0x38, 0xdc, 0xb2, 0xf9, 0x67, 0xfa, 0x87, 0x40, 0x5d, 0x61, 0xc0, 0x51,
+ 0x8f, 0x6b, 0x83, 0x6b, 0xcd, 0x05, 0x3a, 0xca, 0xe1, 0xa7, 0x05, 0x78,
+ 0xfc, 0xca, 0xda, 0x94, 0xd0, 0x2c, 0x08, 0x3d, 0x7e, 0x16, 0x79, 0xc8,
+ 0xa0, 0x50, 0x20, 0x24, 0x54, 0x33, 0x71, 0x31, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00,
+};
+
+/* kPKCS7Windows is the Equifax root certificate, as exported by Windows 7. */
+static const uint8_t kPKCS7Windows[] = {
+ 0x30, 0x82, 0x02, 0xb1, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x07, 0x02, 0xa0, 0x82, 0x02, 0xa2, 0x30, 0x82, 0x02, 0x9e, 0x02,
+ 0x01, 0x01, 0x31, 0x00, 0x30, 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82, 0x02, 0x86, 0x30, 0x82, 0x02,
+ 0x82, 0x30, 0x82, 0x01, 0xeb, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01,
+ 0x04, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
+ 0x01, 0x04, 0x05, 0x00, 0x30, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
+ 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x1c, 0x30, 0x1a, 0x06,
+ 0x03, 0x55, 0x04, 0x0a, 0x13, 0x13, 0x45, 0x71, 0x75, 0x69, 0x66, 0x61,
+ 0x78, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x49, 0x6e, 0x63,
+ 0x2e, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1d,
+ 0x45, 0x71, 0x75, 0x69, 0x66, 0x61, 0x78, 0x20, 0x53, 0x65, 0x63, 0x75,
+ 0x72, 0x65, 0x20, 0x65, 0x42, 0x75, 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73,
+ 0x20, 0x43, 0x41, 0x2d, 0x31, 0x30, 0x1e, 0x17, 0x0d, 0x39, 0x39, 0x30,
+ 0x36, 0x32, 0x31, 0x30, 0x34, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d,
+ 0x32, 0x30, 0x30, 0x36, 0x32, 0x31, 0x30, 0x34, 0x30, 0x30, 0x30, 0x30,
+ 0x5a, 0x30, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+ 0x13, 0x02, 0x55, 0x53, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04,
+ 0x0a, 0x13, 0x13, 0x45, 0x71, 0x75, 0x69, 0x66, 0x61, 0x78, 0x20, 0x53,
+ 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x26,
+ 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1d, 0x45, 0x71, 0x75,
+ 0x69, 0x66, 0x61, 0x78, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20,
+ 0x65, 0x42, 0x75, 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x20, 0x43, 0x41,
+ 0x2d, 0x31, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48,
+ 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00,
+ 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xce, 0x2f, 0x19, 0xbc, 0x17,
+ 0xb7, 0x77, 0xde, 0x93, 0xa9, 0x5f, 0x5a, 0x0d, 0x17, 0x4f, 0x34, 0x1a,
+ 0x0c, 0x98, 0xf4, 0x22, 0xd9, 0x59, 0xd4, 0xc4, 0x68, 0x46, 0xf0, 0xb4,
+ 0x35, 0xc5, 0x85, 0x03, 0x20, 0xc6, 0xaf, 0x45, 0xa5, 0x21, 0x51, 0x45,
+ 0x41, 0xeb, 0x16, 0x58, 0x36, 0x32, 0x6f, 0xe2, 0x50, 0x62, 0x64, 0xf9,
+ 0xfd, 0x51, 0x9c, 0xaa, 0x24, 0xd9, 0xf4, 0x9d, 0x83, 0x2a, 0x87, 0x0a,
+ 0x21, 0xd3, 0x12, 0x38, 0x34, 0x6c, 0x8d, 0x00, 0x6e, 0x5a, 0xa0, 0xd9,
+ 0x42, 0xee, 0x1a, 0x21, 0x95, 0xf9, 0x52, 0x4c, 0x55, 0x5a, 0xc5, 0x0f,
+ 0x38, 0x4f, 0x46, 0xfa, 0x6d, 0xf8, 0x2e, 0x35, 0xd6, 0x1d, 0x7c, 0xeb,
+ 0xe2, 0xf0, 0xb0, 0x75, 0x80, 0xc8, 0xa9, 0x13, 0xac, 0xbe, 0x88, 0xef,
+ 0x3a, 0x6e, 0xab, 0x5f, 0x2a, 0x38, 0x62, 0x02, 0xb0, 0x12, 0x7b, 0xfe,
+ 0x8f, 0xa6, 0x03, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x66, 0x30, 0x64,
+ 0x30, 0x11, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01,
+ 0x01, 0x04, 0x04, 0x03, 0x02, 0x00, 0x07, 0x30, 0x0f, 0x06, 0x03, 0x55,
+ 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff,
+ 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80,
+ 0x14, 0x4a, 0x78, 0x32, 0x52, 0x11, 0xdb, 0x59, 0x16, 0x36, 0x5e, 0xdf,
+ 0xc1, 0x14, 0x36, 0x40, 0x6a, 0x47, 0x7c, 0x4c, 0xa1, 0x30, 0x1d, 0x06,
+ 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x4a, 0x78, 0x32, 0x52,
+ 0x11, 0xdb, 0x59, 0x16, 0x36, 0x5e, 0xdf, 0xc1, 0x14, 0x36, 0x40, 0x6a,
+ 0x47, 0x7c, 0x4c, 0xa1, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x0d, 0x01, 0x01, 0x04, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x75,
+ 0x5b, 0xa8, 0x9b, 0x03, 0x11, 0xe6, 0xe9, 0x56, 0x4c, 0xcd, 0xf9, 0xa9,
+ 0x4c, 0xc0, 0x0d, 0x9a, 0xf3, 0xcc, 0x65, 0x69, 0xe6, 0x25, 0x76, 0xcc,
+ 0x59, 0xb7, 0xd6, 0x54, 0xc3, 0x1d, 0xcd, 0x99, 0xac, 0x19, 0xdd, 0xb4,
+ 0x85, 0xd5, 0xe0, 0x3d, 0xfc, 0x62, 0x20, 0xa7, 0x84, 0x4b, 0x58, 0x65,
+ 0xf1, 0xe2, 0xf9, 0x95, 0x21, 0x3f, 0xf5, 0xd4, 0x7e, 0x58, 0x1e, 0x47,
+ 0x87, 0x54, 0x3e, 0x58, 0xa1, 0xb5, 0xb5, 0xf8, 0x2a, 0xef, 0x71, 0xe7,
+ 0xbc, 0xc3, 0xf6, 0xb1, 0x49, 0x46, 0xe2, 0xd7, 0xa0, 0x6b, 0xe5, 0x56,
+ 0x7a, 0x9a, 0x27, 0x98, 0x7c, 0x46, 0x62, 0x14, 0xe7, 0xc9, 0xfc, 0x6e,
+ 0x03, 0x12, 0x79, 0x80, 0x38, 0x1d, 0x48, 0x82, 0x8d, 0xfc, 0x17, 0xfe,
+ 0x2a, 0x96, 0x2b, 0xb5, 0x62, 0xa6, 0xa6, 0x3d, 0xbd, 0x7f, 0x92, 0x59,
+ 0xcd, 0x5a, 0x2a, 0x82, 0xb2, 0x37, 0x79, 0x31, 0x00,
+};
+
+static int test_reparse(const uint8_t *der_bytes, size_t der_len) {
+ CBS pkcs7;
+ CBB cbb;
+ STACK_OF(X509) *certs = sk_X509_new_null();
+ STACK_OF(X509) *certs2 = sk_X509_new_null();
+ uint8_t *result_data, *result2_data;
+ size_t result_len, result2_len, i;
+
+ CBS_init(&pkcs7, der_bytes, der_len);
+ if (!PKCS7_get_certificates(certs, &pkcs7)) {
+ fprintf(stderr, "PKCS7_get_certificates failed.\n");
+ return 0;
+ }
+
+ CBB_init(&cbb, der_len);
+ if (!PKCS7_bundle_certificates(&cbb, certs) ||
+ !CBB_finish(&cbb, &result_data, &result_len)) {
+ fprintf(stderr, "PKCS7_bundle_certificates failed.\n");
+ return 0;
+ }
+
+ CBS_init(&pkcs7, result_data, result_len);
+ if (!PKCS7_get_certificates(certs2, &pkcs7)) {
+ fprintf(stderr, "PKCS7_get_certificates reparse failed.\n");
+ return 0;
+ }
+
+ if (sk_X509_num(certs) != sk_X509_num(certs2)) {
+ fprintf(stderr, "Number of certs in results differ.\n");
+ return 0;
+ }
+
+ for (i = 0; i < sk_X509_num(certs); i++) {
+ X509 *a = sk_X509_value(certs, i);
+ X509 *b = sk_X509_value(certs2, i);
+
+ if (X509_cmp(a, b) != 0) {
+ fprintf(stderr, "Certificate %u differs.\n", (unsigned) i);
+ return 0;
+ }
+ }
+
+ CBB_init(&cbb, der_len);
+ if (!PKCS7_bundle_certificates(&cbb, certs2) ||
+ !CBB_finish(&cbb, &result2_data, &result2_len)) {
+ fprintf(stderr,
+ "PKCS7_bundle_certificates failed the second time.\n");
+ return 0;
+ }
+
+ if (result_len != result2_len ||
+ memcmp(result_data, result2_data, result_len) != 0) {
+ fprintf(stderr, "Serialisation is not stable.\n");
+ return 0;
+ }
+
+ OPENSSL_free(result_data);
+ OPENSSL_free(result2_data);
+ sk_X509_pop_free(certs, X509_free);
+ sk_X509_pop_free(certs2, X509_free);
+
+ return 1;
+}
+
+int main(void) {
+ CRYPTO_library_init();
+
+ if (!test_reparse(kPKCS7NSS, sizeof(kPKCS7NSS)) ||
+ !test_reparse(kPKCS7Windows, sizeof(kPKCS7Windows))) {
+ return 1;
+ }
+
+ printf("PASS\n");
+ return 0;
+}
+
diff --git a/src/crypto/x509/t_crl.c b/src/crypto/x509/t_crl.c
new file mode 100644
index 0000000..93a7afb
--- /dev/null
+++ b/src/crypto/x509/t_crl.c
@@ -0,0 +1,129 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/asn1.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+
+
+#ifndef OPENSSL_NO_FP_API
+int X509_CRL_print_fp(FILE *fp, X509_CRL *x)
+ {
+ BIO *b;
+ int ret;
+
+ if ((b=BIO_new(BIO_s_file())) == NULL)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_CRL_print_fp, ERR_R_BUF_LIB);
+ return(0);
+ }
+ BIO_set_fp(b,fp,BIO_NOCLOSE);
+ ret=X509_CRL_print(b, x);
+ BIO_free(b);
+ return(ret);
+ }
+#endif
+
+int X509_CRL_print(BIO *out, X509_CRL *x)
+{
+ STACK_OF(X509_REVOKED) *rev;
+ X509_REVOKED *r;
+ long l;
+ size_t i;
+ char *p;
+
+ BIO_printf(out, "Certificate Revocation List (CRL):\n");
+ l = X509_CRL_get_version(x);
+ BIO_printf(out, "%8sVersion %lu (0x%lx)\n", "", l+1, l);
+ X509_signature_print(out, x->sig_alg, NULL);
+ p=X509_NAME_oneline(X509_CRL_get_issuer(x),NULL,0);
+ BIO_printf(out,"%8sIssuer: %s\n","",p);
+ OPENSSL_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);
+ }
+ X509_signature_print(out, x->sig_alg, x->signature);
+
+ return 1;
+
+}
diff --git a/src/crypto/x509/t_x509.c b/src/crypto/x509/t_x509.c
new file mode 100644
index 0000000..2b9a421
--- /dev/null
+++ b/src/crypto/x509/t_x509.c
@@ -0,0 +1,500 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/asn1.h>
+#include <openssl/bio.h>
+#include <openssl/digest.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+
+#include "../evp/internal.h"
+
+#ifndef OPENSSL_NO_FP_API
+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)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_print_ex_fp, 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_fp(FILE *fp, X509 *x)
+ {
+ return X509_print_ex_fp(fp, x, XN_FLAG_COMPAT, X509_FLAG_COMPAT);
+ }
+#endif
+
+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;
+ const char *neg;
+
+ 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 (BIO_printf(bp,"%8sVersion: %lu (0x%lx)\n","",l+1,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);
+ if (bs->length <= (int)sizeof(long))
+ {
+ l=ASN1_INTEGER_get(bs);
+ if (bs->type == V_ASN1_NEG_INTEGER)
+ {
+ l= -l;
+ neg="-";
+ }
+ else
+ neg="";
+ if (BIO_printf(bp," %s%lu (%s0x%lx)\n",neg,l,neg,l) <= 0)
+ goto err;
+ }
+ else
+ {
+ neg=(bs->type == V_ASN1_NEG_INTEGER)?" (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, ci->signature, 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) < 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) < 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","");
+ BIO_print_errors(bp);
+ }
+ else
+ {
+ EVP_PKEY_print_public(bp, pkey, 16, NULL);
+ EVP_PKEY_free(pkey);
+ }
+ }
+
+ if(!(cflag & X509_FLAG_NO_IDS))
+ {
+ if (ci->issuerUID)
+ {
+ if (BIO_printf(bp,"%8sIssuer Unique ID: ","") <= 0)
+ goto err;
+ if (!X509_signature_dump(bp, ci->issuerUID, 12))
+ goto err;
+ }
+ if (ci->subjectUID)
+ {
+ if (BIO_printf(bp,"%8sSubject Unique ID: ","") <= 0)
+ goto err;
+ if (!X509_signature_dump(bp, ci->subjectUID, 12))
+ goto err;
+ }
+ }
+
+ 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:
+ if (m != NULL) OPENSSL_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;
+ derlen = i2d_X509_NAME(x->cert_info->subject, NULL);
+ if ((der = dertmp = (unsigned char *)OPENSSL_malloc (derlen)) == NULL)
+ goto err;
+ i2d_X509_NAME(x->cert_info->subject, &dertmp);
+
+ 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;
+ }
+ OPENSSL_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:
+ if (der != NULL) OPENSSL_free(der);
+ return(0);
+ }
+
+int X509_signature_print(BIO *bp, X509_ALGOR *sigalg, 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_STRING_print(BIO *bp, const ASN1_STRING *v)
+ {
+ int i,n;
+ char buf[80];
+ const char *p;
+
+ if (v == NULL) return(0);
+ n=0;
+ p=(const char *)v->data;
+ for (i=0; i<v->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);
+ }
+
+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);
+}
+
+static const char *const 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 = NULL;
+ 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);
+ }
+
+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);
+ }
+
+int X509_NAME_print(BIO *bp, X509_NAME *name, int obase)
+ {
+ char *s,*c,*b;
+ int ret=0,l,i;
+
+ l=80-2-obase;
+
+ b=X509_NAME_oneline(name,NULL,0);
+ if (!b)
+ return 0;
+ if (!*b)
+ {
+ OPENSSL_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;
+ }
+ l--;
+ }
+ if (*s == '\0') break;
+ s++;
+ l--;
+ }
+
+ ret=1;
+ if (0)
+ {
+err:
+ OPENSSL_PUT_ERROR(X509, X509_NAME_print, ERR_R_BUF_LIB);
+ }
+ OPENSSL_free(b);
+ return(ret);
+ }
diff --git a/src/crypto/x509/t_x509a.c b/src/crypto/x509/t_x509a.c
new file mode 100644
index 0000000..7667268
--- /dev/null
+++ b/src/crypto/x509/t_x509a.c
@@ -0,0 +1,109 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/asn1.h>
+#include <openssl/bio.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/x509.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;
+ size_t i;
+ int j;
+ 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->data);
+ if(aux->keyid) {
+ BIO_printf(out, "%*sKey Id: ", indent, "");
+ for(j = 0; j < aux->keyid->length; j++)
+ BIO_printf(out, "%s%02X",
+ j ? ":" : "",
+ aux->keyid->data[j]);
+ BIO_write(out,"\n",1);
+ }
+ return 1;
+}
diff --git a/src/crypto/x509/vpm_int.h b/src/crypto/x509/vpm_int.h
new file mode 100644
index 0000000..d18a4d4
--- /dev/null
+++ b/src/crypto/x509/vpm_int.h
@@ -0,0 +1,70 @@
+/* vpm_int.h */
+/* 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).
+ *
+ */
+
+/* internal only structure to hold additional X509_VERIFY_PARAM data */
+
+struct X509_VERIFY_PARAM_ID_st
+ {
+ unsigned char *host; /* If not NULL hostname to match */
+ size_t hostlen;
+ unsigned int hostflags; /* Flags to control matching features */
+ unsigned 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 */
+ };
diff --git a/src/crypto/x509/x509.c b/src/crypto/x509/x509.c
new file mode 100644
index 0000000..31f9e1e
--- /dev/null
+++ b/src/crypto/x509/x509.c
@@ -0,0 +1,152 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/x509.h>
+
+#include <openssl/bio.h>
+#include <openssl/mem.h>
+
+
+int PKCS8_pkey_set0(PKCS8_PRIV_KEY_INFO *priv, ASN1_OBJECT *aobj, int version,
+ int ptype, void *pval, uint8_t *penc, int penclen) {
+ uint8_t **ppenc = NULL;
+ if (version >= 0) {
+ if (!ASN1_INTEGER_set(priv->version, version)) {
+ return 0;
+ }
+ }
+
+ if (penc) {
+ int pmtype;
+ ASN1_OCTET_STRING *oct;
+
+ oct = ASN1_OCTET_STRING_new();
+ if (!oct) {
+ return 0;
+ }
+ oct->data = penc;
+ ppenc = &oct->data;
+ oct->length = penclen;
+ if (priv->broken == PKCS8_NO_OCTET) {
+ pmtype = V_ASN1_SEQUENCE;
+ } else {
+ pmtype = V_ASN1_OCTET_STRING;
+ }
+ ASN1_TYPE_set(priv->pkey, pmtype, oct);
+ }
+
+ if (!X509_ALGOR_set0(priv->pkeyalg, aobj, ptype, pval)) {
+ /* If call fails do not swallow 'enc' */
+ if (ppenc) {
+ *ppenc = NULL;
+ }
+ return 0;
+ }
+
+ return 1;
+}
+
+int PKCS8_pkey_get0(ASN1_OBJECT **ppkalg, const uint8_t **pk, int *ppklen,
+ X509_ALGOR **pa, PKCS8_PRIV_KEY_INFO *p8) {
+ if (ppkalg) {
+ *ppkalg = p8->pkeyalg->algorithm;
+ }
+
+ if (p8->pkey->type == V_ASN1_OCTET_STRING) {
+ p8->broken = PKCS8_OK;
+ if (pk) {
+ *pk = p8->pkey->value.octet_string->data;
+ *ppklen = p8->pkey->value.octet_string->length;
+ }
+ } else if (p8->pkey->type == V_ASN1_SEQUENCE) {
+ p8->broken = PKCS8_NO_OCTET;
+ if (pk) {
+ *pk = p8->pkey->value.sequence->data;
+ *ppklen = p8->pkey->value.sequence->length;
+ }
+ } else {
+ return 0;
+ }
+
+ if (pa) {
+ *pa = p8->pkeyalg;
+ }
+ return 1;
+}
+
+int X509_signature_dump(BIO *bp, const ASN1_STRING *sig, int indent) {
+ const uint8_t *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 ||
+ 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;
+}
diff --git a/src/crypto/x509/x509_att.c b/src/crypto/x509/x509_att.c
new file mode 100644
index 0000000..3613c35
--- /dev/null
+++ b/src/crypto/x509/x509_att.c
@@ -0,0 +1,353 @@
+/* crypto/x509/x509_att.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 <openssl/asn1.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/obj.h>
+#include <openssl/stack.h>
+#include <openssl/x509.h>
+
+
+int X509at_get_attr_count(const STACK_OF(X509_ATTRIBUTE) *x)
+{
+ return sk_X509_ATTRIBUTE_num(x);
+}
+
+int X509at_get_attr_by_NID(const STACK_OF(X509_ATTRIBUTE) *x, int nid,
+ int lastpos)
+{
+ const ASN1_OBJECT *obj;
+
+ obj=OBJ_nid2obj(nid);
+ if (obj == NULL) return(-2);
+ return(X509at_get_attr_by_OBJ(x,obj,lastpos));
+}
+
+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);
+}
+
+X509_ATTRIBUTE *X509at_get_attr(const STACK_OF(X509_ATTRIBUTE) *x, int loc)
+{
+ if (x == NULL || loc < 0 || sk_X509_ATTRIBUTE_num(x) <= (size_t) loc)
+ return NULL;
+ else
+ return sk_X509_ATTRIBUTE_value(x,loc);
+}
+
+X509_ATTRIBUTE *X509at_delete_attr(STACK_OF(X509_ATTRIBUTE) *x, int loc)
+{
+ X509_ATTRIBUTE *ret;
+
+ if (x == NULL || loc < 0 || sk_X509_ATTRIBUTE_num(x) <= (size_t) loc)
+ return(NULL);
+ ret=sk_X509_ATTRIBUTE_delete(x,loc);
+ return(ret);
+}
+
+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)
+ {
+ OPENSSL_PUT_ERROR(X509, X509at_add1_attr, ERR_R_PASSED_NULL_PARAMETER);
+ goto err2;
+ }
+
+ 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:
+ OPENSSL_PUT_ERROR(X509, X509at_add1_attr, ERR_R_MALLOC_FAILURE);
+err2:
+ if (new_attr != NULL) X509_ATTRIBUTE_free(new_attr);
+ if (sk != NULL) sk_X509_ATTRIBUTE_free(sk);
+ return(NULL);
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+void *X509at_get0_data_by_OBJ(STACK_OF(X509_ATTRIBUTE) *x,
+ 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);
+}
+
+X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_NID(X509_ATTRIBUTE **attr, int nid,
+ int atrtype, const void *data, int len)
+{
+ const ASN1_OBJECT *obj;
+
+ obj=OBJ_nid2obj(nid);
+ if (obj == NULL)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_ATTRIBUTE_create_by_NID, X509_R_UNKNOWN_NID);
+ return(NULL);
+ }
+ return X509_ATTRIBUTE_create_by_OBJ(attr,obj,atrtype,data,len);
+}
+
+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)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_ATTRIBUTE_create_by_OBJ, 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);
+}
+
+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)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_ATTRIBUTE_create_by_txt, X509_R_INVALID_FIELD_NAME);
+ ERR_add_error_data(2, "name=", atrname);
+ return(NULL);
+ }
+ nattr = X509_ATTRIBUTE_create_by_OBJ(attr,obj,type,bytes,len);
+ ASN1_OBJECT_free(obj);
+ return nattr;
+ }
+
+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(1);
+}
+
+int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype, const void *data, int len)
+{
+ ASN1_TYPE *ttmp;
+ 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) {
+ OPENSSL_PUT_ERROR(X509, X509_ATTRIBUTE_set1_data, 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;
+ }
+ if(!(attr->value.set = sk_ASN1_TYPE_new_null())) goto err;
+ attr->single = 0;
+ /* 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)
+ 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->value.set, ttmp)) goto err;
+ return 1;
+ err:
+ OPENSSL_PUT_ERROR(X509, X509_ATTRIBUTE_set1_data, ERR_R_MALLOC_FAILURE);
+ return 0;
+}
+
+int X509_ATTRIBUTE_count(X509_ATTRIBUTE *attr)
+{
+ if(!attr->single) return sk_ASN1_TYPE_num(attr->value.set);
+ if(attr->value.single) return 1;
+ return 0;
+}
+
+ASN1_OBJECT *X509_ATTRIBUTE_get0_object(X509_ATTRIBUTE *attr)
+{
+ if (attr == NULL) return(NULL);
+ return(attr->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)){
+ OPENSSL_PUT_ERROR(X509, X509_ATTRIBUTE_get0_data, X509_R_WRONG_TYPE);
+ return NULL;
+ }
+ return ttmp->value.ptr;
+}
+
+ASN1_TYPE *X509_ATTRIBUTE_get0_type(X509_ATTRIBUTE *attr, int idx)
+{
+ if (attr == NULL) return(NULL);
+ if(idx >= X509_ATTRIBUTE_count(attr)) return NULL;
+ if(!attr->single) return sk_ASN1_TYPE_value(attr->value.set, idx);
+ else return attr->value.single;
+}
diff --git a/src/crypto/x509/x509_cmp.c b/src/crypto/x509/x509_cmp.c
new file mode 100644
index 0000000..712e36b
--- /dev/null
+++ b/src/crypto/x509/x509_cmp.c
@@ -0,0 +1,490 @@
+/* crypto/x509/x509_cmp.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 <string.h>
+
+#include <openssl/asn1.h>
+#include <openssl/buf.h>
+#include <openssl/digest.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/stack.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.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=M_ASN1_INTEGER_cmp(ai->serialNumber,bi->serialNumber);
+ if (i) return(i);
+ return(X509_NAME_cmp(ai->issuer,bi->issuer));
+ }
+
+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 (!EVP_DigestInit_ex(&ctx, EVP_md5(), NULL))
+ goto err;
+ if (!EVP_DigestUpdate(&ctx,(unsigned char *)f,strlen(f)))
+ goto err;
+ OPENSSL_free(f);
+ 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);
+ return(ret);
+ }
+
+int X509_issuer_name_cmp(const X509 *a, const X509 *b)
+ {
+ return(X509_NAME_cmp(a->cert_info->issuer,b->cert_info->issuer));
+ }
+
+int X509_subject_name_cmp(const X509 *a, const X509 *b)
+ {
+ return(X509_NAME_cmp(a->cert_info->subject,b->cert_info->subject));
+ }
+
+int X509_CRL_cmp(const X509_CRL *a, const X509_CRL *b)
+ {
+ return(X509_NAME_cmp(a->crl->issuer,b->crl->issuer));
+ }
+
+int X509_CRL_match(const X509_CRL *a, const X509_CRL *b)
+ {
+ return memcmp(a->sha1_hash, b->sha1_hash, 20);
+ }
+
+X509_NAME *X509_get_issuer_name(X509 *a)
+ {
+ return(a->cert_info->issuer);
+ }
+
+unsigned long X509_issuer_name_hash(X509 *x)
+ {
+ return(X509_NAME_hash(x->cert_info->issuer));
+ }
+
+unsigned long X509_issuer_name_hash_old(X509 *x)
+ {
+ return(X509_NAME_hash_old(x->cert_info->issuer));
+ }
+
+X509_NAME *X509_get_subject_name(X509 *a)
+ {
+ return(a->cert_info->subject);
+ }
+
+ASN1_INTEGER *X509_get_serialNumber(X509 *a)
+ {
+ return(a->cert_info->serialNumber);
+ }
+
+unsigned long X509_subject_name_hash(X509 *x)
+ {
+ return(X509_NAME_hash(x->cert_info->subject));
+ }
+
+unsigned long X509_subject_name_hash_old(X509 *x)
+ {
+ return(X509_NAME_hash_old(x->cert_info->subject));
+ }
+
+/* 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)
+{
+ int rv;
+ /* ensure hash is valid */
+ X509_check_purpose((X509 *)a, -1, 0);
+ X509_check_purpose((X509 *)b, -1, 0);
+
+ rv = memcmp(a->sha1_hash, b->sha1_hash, SHA_DIGEST_LENGTH);
+ if (rv)
+ return rv;
+ /* Check for match against stored encoding too */
+ if (!a->cert_info->enc.modified && !b->cert_info->enc.modified)
+ {
+ rv = (int)(a->cert_info->enc.len - b->cert_info->enc.len);
+ if (rv)
+ return rv;
+ return memcmp(a->cert_info->enc.enc, b->cert_info->enc.enc,
+ a->cert_info->enc.len);
+ }
+ return rv;
+}
+
+
+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);
+
+ }
+
+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);
+ }
+
+
+/* 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);
+ /* EVP_MD_CTX_set_flags(&md_ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); */
+ 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);
+ }
+
+/* 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)
+ {
+ size_t 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);
+ }
+
+X509 *X509_find_by_subject(STACK_OF(X509) *sk, X509_NAME *name)
+ {
+ X509 *x509;
+ size_t 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);
+ }
+
+EVP_PKEY *X509_get_pubkey(X509 *x)
+ {
+ if ((x == NULL) || (x->cert_info == NULL))
+ return(NULL);
+ return(X509_PUBKEY_get(x->cert_info->key));
+ }
+
+ASN1_BIT_STRING *X509_get0_pubkey_bitstr(const X509 *x)
+ {
+ if(!x) return NULL;
+ return x->cert_info->key->public_key;
+ }
+
+
+int X509_check_private_key(X509 *x, EVP_PKEY *k)
+ {
+ EVP_PKEY *xk;
+ int ret;
+
+ xk=X509_get_pubkey(x);
+
+ if (xk)
+ ret = EVP_PKEY_cmp(xk, k);
+ else
+ ret = -2;
+
+ switch (ret)
+ {
+ case 1:
+ break;
+ case 0:
+ OPENSSL_PUT_ERROR(X509, X509_check_private_key, X509_R_KEY_VALUES_MISMATCH);
+ break;
+ case -1:
+ OPENSSL_PUT_ERROR(X509, X509_check_private_key, X509_R_KEY_TYPE_MISMATCH);
+ break;
+ case -2:
+ OPENSSL_PUT_ERROR(X509, X509_check_private_key, X509_R_UNKNOWN_KEY_TYPE);
+ }
+ if (xk)
+ EVP_PKEY_free(xk);
+ if (ret > 0)
+ return 1;
+ return 0;
+ }
+
+/* Check a suite B algorithm is permitted: pass in a public key and
+ * the NID of its signature (or 0 if no signature). The pflags is
+ * a pointer to a flags field which must contain the suite B verification
+ * flags.
+ */
+
+
+static int check_suite_b(EVP_PKEY *pkey, int sign_nid, unsigned long *pflags)
+ {
+ const EC_GROUP *grp = NULL;
+ int curve_nid;
+ if (pkey && pkey->type == EVP_PKEY_EC)
+ grp = EC_KEY_get0_group(pkey->pkey.ec);
+ if (!grp)
+ return X509_V_ERR_SUITE_B_INVALID_ALGORITHM;
+ curve_nid = EC_GROUP_get_curve_name(grp);
+ /* Check curve is consistent with LOS */
+ if (curve_nid == NID_secp384r1) /* P-384 */
+ {
+ /* Check signature algorithm is consistent with
+ * curve.
+ */
+ if (sign_nid != -1 && sign_nid != NID_ecdsa_with_SHA384)
+ return X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM;
+ if (!(*pflags & X509_V_FLAG_SUITEB_192_LOS))
+ return X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED;
+ /* If we encounter P-384 we cannot use P-256 later */
+ *pflags &= ~X509_V_FLAG_SUITEB_128_LOS_ONLY;
+ }
+ else if (curve_nid == NID_X9_62_prime256v1) /* P-256 */
+ {
+ if (sign_nid != -1 && sign_nid != NID_ecdsa_with_SHA256)
+ return X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM;
+ if (!(*pflags & X509_V_FLAG_SUITEB_128_LOS_ONLY))
+ return X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED;
+ }
+ else
+ return X509_V_ERR_SUITE_B_INVALID_CURVE;
+
+ return X509_V_OK;
+ }
+
+int X509_chain_check_suiteb(int *perror_depth, X509 *x, STACK_OF(X509) *chain,
+ unsigned long flags)
+ {
+ int rv, sign_nid;
+ size_t i;
+ EVP_PKEY *pk = NULL;
+ unsigned long tflags;
+ if (!(flags & X509_V_FLAG_SUITEB_128_LOS))
+ return X509_V_OK;
+ tflags = flags;
+ /* If no EE certificate passed in must be first in chain */
+ if (x == NULL)
+ {
+ x = sk_X509_value(chain, 0);
+ i = 1;
+ }
+ else
+ i = 0;
+
+ if (X509_get_version(x) != 2)
+ {
+ rv = X509_V_ERR_SUITE_B_INVALID_VERSION;
+ /* Correct error depth */
+ i = 0;
+ goto end;
+ }
+
+ pk = X509_get_pubkey(x);
+ /* Check EE key only */
+ rv = check_suite_b(pk, -1, &tflags);
+ if (rv != X509_V_OK)
+ {
+ /* Correct error depth */
+ i = 0;
+ goto end;
+ }
+ for(; i < sk_X509_num(chain); i++)
+ {
+ sign_nid = X509_get_signature_nid(x);
+ x = sk_X509_value(chain, i);
+ if (X509_get_version(x) != 2)
+ {
+ rv = X509_V_ERR_SUITE_B_INVALID_VERSION;
+ goto end;
+ }
+ EVP_PKEY_free(pk);
+ pk = X509_get_pubkey(x);
+ rv = check_suite_b(pk, sign_nid, &tflags);
+ if (rv != X509_V_OK)
+ goto end;
+ }
+
+ /* Final check: root CA signature */
+ rv = check_suite_b(pk, X509_get_signature_nid(x), &tflags);
+ end:
+ if (pk)
+ EVP_PKEY_free(pk);
+ if (rv != X509_V_OK)
+ {
+ /* Invalid signature or LOS errors are for previous cert */
+ if ((rv == X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM
+ || rv == X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED) && i)
+ i--;
+ /* If we have LOS error and flags changed then we are signing
+ * P-384 with P-256. Use more meaninggul error.
+ */
+ if (rv == X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED && flags != tflags)
+ rv = X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256;
+ if (perror_depth)
+ *perror_depth = i;
+ }
+ return rv;
+ }
+
+int X509_CRL_check_suiteb(X509_CRL *crl, EVP_PKEY *pk, unsigned long flags)
+ {
+ int sign_nid;
+ if (!(flags & X509_V_FLAG_SUITEB_128_LOS))
+ return X509_V_OK;
+ sign_nid = OBJ_obj2nid(crl->crl->sig_alg->algorithm);
+ return check_suite_b(pk, sign_nid, &flags);
+ }
+
+/* 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;
+ }
diff --git a/src/crypto/x509/x509_d2.c b/src/crypto/x509/x509_d2.c
new file mode 100644
index 0000000..2161d85
--- /dev/null
+++ b/src/crypto/x509/x509_d2.c
@@ -0,0 +1,105 @@
+/* crypto/x509/x509_d2.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 <openssl/err.h>
+#include <openssl/x509.h>
+
+
+#ifndef OPENSSL_NO_STDIO
+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);
+ }
+
+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);
+ }
+
+#endif
diff --git a/src/crypto/x509/x509_def.c b/src/crypto/x509/x509_def.c
new file mode 100644
index 0000000..dbae289
--- /dev/null
+++ b/src/crypto/x509/x509_def.c
@@ -0,0 +1,88 @@
+/* crypto/x509/x509_def.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 <openssl/x509.h>
+
+
+/* TODO(fork): cleanup */
+
+#define OPENSSLDIR "/etc/ssl"
+#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"
+
+const char *X509_get_default_private_dir(void)
+ { return(X509_PRIVATE_DIR); }
+
+const char *X509_get_default_cert_area(void)
+ { return(X509_CERT_AREA); }
+
+const char *X509_get_default_cert_dir(void)
+ { return(X509_CERT_DIR); }
+
+const char *X509_get_default_cert_file(void)
+ { return(X509_CERT_FILE); }
+
+const char *X509_get_default_cert_dir_env(void)
+ { return(X509_CERT_DIR_EVP); }
+
+const char *X509_get_default_cert_file_env(void)
+ { return(X509_CERT_FILE_EVP); }
+
diff --git a/src/crypto/x509/x509_error.c b/src/crypto/x509/x509_error.c
new file mode 100644
index 0000000..222a40a
--- /dev/null
+++ b/src/crypto/x509/x509_error.c
@@ -0,0 +1,125 @@
+/* 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 <openssl/err.h>
+
+#include <openssl/x509.h>
+
+const ERR_STRING_DATA X509_error_string_data[] = {
+ {ERR_PACK(ERR_LIB_X509, X509_F_ASN1_digest, 0), "ASN1_digest"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_ASN1_generate_v3, 0), "ASN1_generate_v3"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_ASN1_item_sign_ctx, 0), "ASN1_item_sign_ctx"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_ASN1_item_verify, 0), "ASN1_item_verify"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_ASN1_sign, 0), "ASN1_sign"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_NETSCAPE_SPKI_b64_decode, 0), "NETSCAPE_SPKI_b64_decode"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_NETSCAPE_SPKI_b64_encode, 0), "NETSCAPE_SPKI_b64_encode"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_PKCS7_get_certificates, 0), "PKCS7_get_certificates"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_ATTRIBUTE_create_by_NID, 0), "X509_ATTRIBUTE_create_by_NID"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_ATTRIBUTE_create_by_OBJ, 0), "X509_ATTRIBUTE_create_by_OBJ"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_ATTRIBUTE_create_by_txt, 0), "X509_ATTRIBUTE_create_by_txt"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_ATTRIBUTE_get0_data, 0), "X509_ATTRIBUTE_get0_data"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_ATTRIBUTE_set1_data, 0), "X509_ATTRIBUTE_set1_data"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_CRL_add0_revoked, 0), "X509_CRL_add0_revoked"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_CRL_diff, 0), "X509_CRL_diff"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_CRL_print_fp, 0), "X509_CRL_print_fp"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_EXTENSION_create_by_NID, 0), "X509_EXTENSION_create_by_NID"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_EXTENSION_create_by_OBJ, 0), "X509_EXTENSION_create_by_OBJ"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_INFO_new, 0), "X509_INFO_new"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_NAME_ENTRY_create_by_NID, 0), "X509_NAME_ENTRY_create_by_NID"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_NAME_ENTRY_create_by_txt, 0), "X509_NAME_ENTRY_create_by_txt"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_NAME_ENTRY_set_object, 0), "X509_NAME_ENTRY_set_object"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_NAME_add_entry, 0), "X509_NAME_add_entry"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_NAME_oneline, 0), "X509_NAME_oneline"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_NAME_print, 0), "X509_NAME_print"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_PKEY_new, 0), "X509_PKEY_new"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_PUBKEY_get, 0), "X509_PUBKEY_get"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_PUBKEY_set, 0), "X509_PUBKEY_set"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_REQ_check_private_key, 0), "X509_REQ_check_private_key"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_REQ_to_X509, 0), "X509_REQ_to_X509"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_CTX_get1_issuer, 0), "X509_STORE_CTX_get1_issuer"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_CTX_init, 0), "X509_STORE_CTX_init"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_CTX_new, 0), "X509_STORE_CTX_new"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_CTX_purpose_inherit, 0), "X509_STORE_CTX_purpose_inherit"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_add_cert, 0), "X509_STORE_add_cert"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_add_crl, 0), "X509_STORE_add_crl"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_TRUST_add, 0), "X509_TRUST_add"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_TRUST_set, 0), "X509_TRUST_set"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_check_private_key, 0), "X509_check_private_key"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_get_pubkey_parameters, 0), "X509_get_pubkey_parameters"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_load_cert_crl_file, 0), "X509_load_cert_crl_file"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_load_cert_file, 0), "X509_load_cert_file"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_load_crl_file, 0), "X509_load_crl_file"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_print_ex_fp, 0), "X509_print_ex_fp"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_to_X509_REQ, 0), "X509_to_X509_REQ"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_verify_cert, 0), "X509_verify_cert"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509at_add1_attr, 0), "X509at_add1_attr"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509v3_add_ext, 0), "X509v3_add_ext"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_add_cert_dir, 0), "add_cert_dir"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_append_exp, 0), "append_exp"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_asn1_cb, 0), "asn1_cb"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_asn1_str2type, 0), "asn1_str2type"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_bitstr_cb, 0), "bitstr_cb"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_by_file_ctrl, 0), "by_file_ctrl"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_check_policy, 0), "check_policy"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_d2i_X509_PKEY, 0), "d2i_X509_PKEY"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_dir_ctrl, 0), "dir_ctrl"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_get_cert_by_subject, 0), "get_cert_by_subject"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_i2d_DSA_PUBKEY, 0), "i2d_DSA_PUBKEY"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_i2d_EC_PUBKEY, 0), "i2d_EC_PUBKEY"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_i2d_PrivateKey, 0), "i2d_PrivateKey"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_i2d_RSA_PUBKEY, 0), "i2d_RSA_PUBKEY"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_parse_tagging, 0), "parse_tagging"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_x509_name_encode, 0), "x509_name_encode"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_x509_name_ex_d2i, 0), "x509_name_ex_d2i"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_x509_name_ex_new, 0), "x509_name_ex_new"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_AKID_MISMATCH), "AKID_MISMATCH"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_BAD_PKCS7_VERSION), "BAD_PKCS7_VERSION"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_BAD_X509_FILETYPE), "BAD_X509_FILETYPE"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_BASE64_DECODE_ERROR), "BASE64_DECODE_ERROR"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_CANT_CHECK_DH_KEY), "CANT_CHECK_DH_KEY"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_CERT_ALREADY_IN_HASH_TABLE), "CERT_ALREADY_IN_HASH_TABLE"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_CONTEXT_NOT_INITIALISED), "CONTEXT_NOT_INITIALISED"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_CRL_ALREADY_DELTA), "CRL_ALREADY_DELTA"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_CRL_VERIFY_FAILURE), "CRL_VERIFY_FAILURE"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_ERR_ASN1_LIB), "ERR_ASN1_LIB"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_IDP_MISMATCH), "IDP_MISMATCH"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_INVALID_BIT_STRING_BITS_LEFT), "INVALID_BIT_STRING_BITS_LEFT"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_INVALID_DIRECTORY), "INVALID_DIRECTORY"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_INVALID_FIELD_NAME), "INVALID_FIELD_NAME"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_INVALID_TRUST), "INVALID_TRUST"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_ISSUER_MISMATCH), "ISSUER_MISMATCH"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_KEY_TYPE_MISMATCH), "KEY_TYPE_MISMATCH"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_KEY_VALUES_MISMATCH), "KEY_VALUES_MISMATCH"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_LOADING_CERT_DIR), "LOADING_CERT_DIR"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_LOADING_DEFAULTS), "LOADING_DEFAULTS"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_METHOD_NOT_SUPPORTED), "METHOD_NOT_SUPPORTED"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_NEWER_CRL_NOT_NEWER), "NEWER_CRL_NOT_NEWER"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_NOT_PKCS7_SIGNED_DATA), "NOT_PKCS7_SIGNED_DATA"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_NO_CERTIFICATES_INCLUDED), "NO_CERTIFICATES_INCLUDED"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_NO_CERT_SET_FOR_US_TO_VERIFY), "NO_CERT_SET_FOR_US_TO_VERIFY"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_NO_CRL_NUMBER), "NO_CRL_NUMBER"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_PUBLIC_KEY_DECODE_ERROR), "PUBLIC_KEY_DECODE_ERROR"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_PUBLIC_KEY_ENCODE_ERROR), "PUBLIC_KEY_ENCODE_ERROR"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_SHOULD_RETRY), "SHOULD_RETRY"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_UNABLE_TO_FIND_PARAMETERS_IN_CHAIN), "UNABLE_TO_FIND_PARAMETERS_IN_CHAIN"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY), "UNABLE_TO_GET_CERTS_PUBLIC_KEY"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_UNKNOWN_KEY_TYPE), "UNKNOWN_KEY_TYPE"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_UNKNOWN_NID), "UNKNOWN_NID"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_UNKNOWN_PURPOSE_ID), "UNKNOWN_PURPOSE_ID"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_UNKNOWN_TRUST_ID), "UNKNOWN_TRUST_ID"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_UNSUPPORTED_ALGORITHM), "UNSUPPORTED_ALGORITHM"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_WRONG_LOOKUP_TYPE), "WRONG_LOOKUP_TYPE"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_WRONG_TYPE), "WRONG_TYPE"},
+ {0, NULL},
+};
diff --git a/src/crypto/x509/x509_ext.c b/src/crypto/x509/x509_ext.c
new file mode 100644
index 0000000..2f1e0c5
--- /dev/null
+++ b/src/crypto/x509/x509_ext.c
@@ -0,0 +1,206 @@
+/* crypto/x509/x509_ext.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 <openssl/asn1.h>
+#include <openssl/evp.h>
+#include <openssl/obj.h>
+#include <openssl/stack.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+
+
+int X509_CRL_get_ext_count(X509_CRL *x)
+ {
+ return(X509v3_get_ext_count(x->crl->extensions));
+ }
+
+int X509_CRL_get_ext_by_NID(X509_CRL *x, int nid, int lastpos)
+ {
+ return(X509v3_get_ext_by_NID(x->crl->extensions,nid,lastpos));
+ }
+
+int X509_CRL_get_ext_by_OBJ(X509_CRL *x, ASN1_OBJECT *obj, int lastpos)
+ {
+ return(X509v3_get_ext_by_OBJ(x->crl->extensions,obj,lastpos));
+ }
+
+int X509_CRL_get_ext_by_critical(X509_CRL *x, int crit, int lastpos)
+ {
+ return(X509v3_get_ext_by_critical(x->crl->extensions,crit,lastpos));
+ }
+
+X509_EXTENSION *X509_CRL_get_ext(X509_CRL *x, int loc)
+ {
+ return(X509v3_get_ext(x->crl->extensions,loc));
+ }
+
+X509_EXTENSION *X509_CRL_delete_ext(X509_CRL *x, int loc)
+ {
+ return(X509v3_delete_ext(x->crl->extensions,loc));
+ }
+
+void *X509_CRL_get_ext_d2i(X509_CRL *x, int nid, int *crit, int *idx)
+{
+ return X509V3_get_d2i(x->crl->extensions, nid, crit, idx);
+}
+
+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);
+}
+
+int X509_CRL_add_ext(X509_CRL *x, X509_EXTENSION *ex, int loc)
+ {
+ return(X509v3_add_ext(&(x->crl->extensions),ex,loc) != NULL);
+ }
+
+int X509_get_ext_count(X509 *x)
+ {
+ return(X509v3_get_ext_count(x->cert_info->extensions));
+ }
+
+int X509_get_ext_by_NID(X509 *x, int nid, int lastpos)
+ {
+ return(X509v3_get_ext_by_NID(x->cert_info->extensions,nid,lastpos));
+ }
+
+int X509_get_ext_by_OBJ(X509 *x, ASN1_OBJECT *obj, int lastpos)
+ {
+ return(X509v3_get_ext_by_OBJ(x->cert_info->extensions,obj,lastpos));
+ }
+
+int X509_get_ext_by_critical(X509 *x, int crit, int lastpos)
+ {
+ return(X509v3_get_ext_by_critical(x->cert_info->extensions,crit,lastpos));
+ }
+
+X509_EXTENSION *X509_get_ext(X509 *x, int loc)
+ {
+ return(X509v3_get_ext(x->cert_info->extensions,loc));
+ }
+
+X509_EXTENSION *X509_delete_ext(X509 *x, int loc)
+ {
+ return(X509v3_delete_ext(x->cert_info->extensions,loc));
+ }
+
+int X509_add_ext(X509 *x, X509_EXTENSION *ex, int loc)
+ {
+ return(X509v3_add_ext(&(x->cert_info->extensions),ex,loc) != NULL);
+ }
+
+void *X509_get_ext_d2i(X509 *x, int nid, int *crit, int *idx)
+{
+ return X509V3_get_d2i(x->cert_info->extensions, nid, crit, idx);
+}
+
+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);
+}
+
+int X509_REVOKED_get_ext_count(X509_REVOKED *x)
+ {
+ return(X509v3_get_ext_count(x->extensions));
+ }
+
+int X509_REVOKED_get_ext_by_NID(X509_REVOKED *x, int nid, int lastpos)
+ {
+ return(X509v3_get_ext_by_NID(x->extensions,nid,lastpos));
+ }
+
+int X509_REVOKED_get_ext_by_OBJ(X509_REVOKED *x, ASN1_OBJECT *obj,
+ int lastpos)
+ {
+ return(X509v3_get_ext_by_OBJ(x->extensions,obj,lastpos));
+ }
+
+int X509_REVOKED_get_ext_by_critical(X509_REVOKED *x, int crit, int lastpos)
+ {
+ return(X509v3_get_ext_by_critical(x->extensions,crit,lastpos));
+ }
+
+X509_EXTENSION *X509_REVOKED_get_ext(X509_REVOKED *x, int loc)
+ {
+ return(X509v3_get_ext(x->extensions,loc));
+ }
+
+X509_EXTENSION *X509_REVOKED_delete_ext(X509_REVOKED *x, int loc)
+ {
+ return(X509v3_delete_ext(x->extensions,loc));
+ }
+
+int X509_REVOKED_add_ext(X509_REVOKED *x, X509_EXTENSION *ex, int loc)
+ {
+ return(X509v3_add_ext(&(x->extensions),ex,loc) != NULL);
+ }
+
+void *X509_REVOKED_get_ext_d2i(X509_REVOKED *x, int nid, int *crit, int *idx)
+{
+ return X509V3_get_d2i(x->extensions, nid, crit, idx);
+}
+
+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);
+}
+
+IMPLEMENT_ASN1_SET_OF(X509_EXTENSION)
diff --git a/src/crypto/x509/x509_lu.c b/src/crypto/x509/x509_lu.c
new file mode 100644
index 0000000..090d341
--- /dev/null
+++ b/src/crypto/x509/x509_lu.c
@@ -0,0 +1,740 @@
+/* crypto/x509/x509_lu.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 <string.h>
+
+#include <openssl/err.h>
+#include <openssl/lhash.h>
+#include <openssl/mem.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+
+
+X509_LOOKUP *X509_LOOKUP_new(X509_LOOKUP_METHOD *method)
+ {
+ X509_LOOKUP *ret;
+
+ ret=(X509_LOOKUP *)OPENSSL_malloc(sizeof(X509_LOOKUP));
+ if (ret == NULL) return NULL;
+
+ ret->init=0;
+ ret->skip=0;
+ ret->method=method;
+ ret->method_data=NULL;
+ ret->store_ctx=NULL;
+ if ((method->new_item != NULL) && !method->new_item(ret))
+ {
+ OPENSSL_free(ret);
+ return NULL;
+ }
+ return ret;
+ }
+
+void X509_LOOKUP_free(X509_LOOKUP *ctx)
+ {
+ if (ctx == NULL) return;
+ if ( (ctx->method != NULL) &&
+ (ctx->method->free != NULL))
+ (*ctx->method->free)(ctx);
+ OPENSSL_free(ctx);
+ }
+
+int X509_LOOKUP_init(X509_LOOKUP *ctx)
+ {
+ if (ctx->method == NULL) return 0;
+ if (ctx->method->init != NULL)
+ return ctx->method->init(ctx);
+ else
+ return 1;
+ }
+
+int X509_LOOKUP_shutdown(X509_LOOKUP *ctx)
+ {
+ if (ctx->method == NULL) return 0;
+ if (ctx->method->shutdown != NULL)
+ return ctx->method->shutdown(ctx);
+ else
+ return 1;
+ }
+
+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 ctx->method->ctrl(ctx,cmd,argc,argl,ret);
+ else
+ return 1;
+ }
+
+int X509_LOOKUP_by_subject(X509_LOOKUP *ctx, int type, X509_NAME *name,
+ X509_OBJECT *ret)
+ {
+ if ((ctx->method == NULL) || (ctx->method->get_by_subject == NULL))
+ return X509_LU_FAIL;
+ if (ctx->skip) return 0;
+ return ctx->method->get_by_subject(ctx,type,name,ret);
+ }
+
+int X509_LOOKUP_by_issuer_serial(X509_LOOKUP *ctx, int type, X509_NAME *name,
+ ASN1_INTEGER *serial, X509_OBJECT *ret)
+ {
+ if ((ctx->method == NULL) ||
+ (ctx->method->get_by_issuer_serial == NULL))
+ return X509_LU_FAIL;
+ return ctx->method->get_by_issuer_serial(ctx,type,name,serial,ret);
+ }
+
+int X509_LOOKUP_by_fingerprint(X509_LOOKUP *ctx, int type,
+ unsigned char *bytes, int len, X509_OBJECT *ret)
+ {
+ if ((ctx->method == NULL) || (ctx->method->get_by_fingerprint == NULL))
+ return X509_LU_FAIL;
+ return ctx->method->get_by_fingerprint(ctx,type,bytes,len,ret);
+ }
+
+int X509_LOOKUP_by_alias(X509_LOOKUP *ctx, int type, char *str, int len,
+ X509_OBJECT *ret)
+ {
+ if ((ctx->method == NULL) || (ctx->method->get_by_alias == NULL))
+ return X509_LU_FAIL;
+ return ctx->method->get_by_alias(ctx,type,str,len,ret);
+ }
+
+
+static int x509_object_cmp(const X509_OBJECT **a, const X509_OBJECT **b)
+ {
+ int ret;
+
+ ret=((*a)->type - (*b)->type);
+ if (ret) return ret;
+ switch ((*a)->type)
+ {
+ case X509_LU_X509:
+ ret=X509_subject_name_cmp((*a)->data.x509,(*b)->data.x509);
+ break;
+ case X509_LU_CRL:
+ ret=X509_CRL_cmp((*a)->data.crl,(*b)->data.crl);
+ break;
+ default:
+ /* abort(); */
+ return 0;
+ }
+ return ret;
+ }
+
+X509_STORE *X509_STORE_new(void)
+ {
+ X509_STORE *ret;
+
+ if ((ret=(X509_STORE *)OPENSSL_malloc(sizeof(X509_STORE))) == NULL)
+ return NULL;
+ memset(ret, 0, sizeof(*ret));
+ ret->objs = sk_X509_OBJECT_new(x509_object_cmp);
+ ret->cache = 1;
+ ret->get_cert_methods = sk_X509_LOOKUP_new_null();
+
+ if ((ret->param = X509_VERIFY_PARAM_new()) == NULL)
+ goto err;
+
+ if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE, ret, &ret->ex_data))
+ goto err;
+
+ ret->references = 1;
+ return ret;
+err:
+ if (ret)
+ {
+ if (ret->param)
+ X509_VERIFY_PARAM_free(ret->param);
+ if (ret->get_cert_methods)
+ sk_X509_LOOKUP_free(ret->get_cert_methods);
+ if (ret->objs)
+ sk_X509_OBJECT_free(ret->objs);
+ OPENSSL_free(ret);
+ }
+ return NULL;
+ }
+
+static void cleanup(X509_OBJECT *a)
+ {
+ if (a->type == X509_LU_X509)
+ {
+ X509_free(a->data.x509);
+ }
+ else if (a->type == X509_LU_CRL)
+ {
+ X509_CRL_free(a->data.crl);
+ }
+ else
+ {
+ /* abort(); */
+ }
+
+ OPENSSL_free(a);
+ }
+
+void X509_STORE_free(X509_STORE *vfy)
+ {
+ int i;
+ size_t j;
+ STACK_OF(X509_LOOKUP) *sk;
+ X509_LOOKUP *lu;
+
+ if (vfy == NULL)
+ return;
+
+ i=CRYPTO_add(&vfy->references,-1,CRYPTO_LOCK_X509_STORE);
+#ifdef REF_PRINT
+ REF_PRINT("X509_STORE",vfy);
+#endif
+ if (i > 0) return;
+#ifdef REF_CHECK
+ if (i < 0)
+ {
+ fprintf(stderr,"X509_STORE_free, bad reference count\n");
+ abort(); /* ok */
+ }
+#endif
+
+ sk=vfy->get_cert_methods;
+ for (j=0; j<sk_X509_LOOKUP_num(sk); j++)
+ {
+ lu=sk_X509_LOOKUP_value(sk,j);
+ X509_LOOKUP_shutdown(lu);
+ X509_LOOKUP_free(lu);
+ }
+ sk_X509_LOOKUP_free(sk);
+ sk_X509_OBJECT_pop_free(vfy->objs, cleanup);
+
+ CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509_STORE, vfy, &vfy->ex_data);
+ if (vfy->param)
+ X509_VERIFY_PARAM_free(vfy->param);
+ OPENSSL_free(vfy);
+ }
+
+X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m)
+ {
+ size_t i;
+ STACK_OF(X509_LOOKUP) *sk;
+ X509_LOOKUP *lu;
+
+ sk=v->get_cert_methods;
+ for (i=0; i<sk_X509_LOOKUP_num(sk); i++)
+ {
+ lu=sk_X509_LOOKUP_value(sk,i);
+ if (m == lu->method)
+ {
+ return lu;
+ }
+ }
+ /* a new one */
+ lu=X509_LOOKUP_new(m);
+ if (lu == NULL)
+ return NULL;
+ else
+ {
+ lu->store_ctx=v;
+ if (sk_X509_LOOKUP_push(v->get_cert_methods,lu))
+ return lu;
+ else
+ {
+ X509_LOOKUP_free(lu);
+ return NULL;
+ }
+ }
+ }
+
+int X509_STORE_get_by_subject(X509_STORE_CTX *vs, int type, X509_NAME *name,
+ X509_OBJECT *ret)
+ {
+ X509_STORE *ctx=vs->ctx;
+ X509_LOOKUP *lu;
+ X509_OBJECT stmp,*tmp;
+ int i,j;
+
+ 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=vs->current_method; i<(int)sk_X509_LOOKUP_num(ctx->get_cert_methods); i++)
+ {
+ lu=sk_X509_LOOKUP_value(ctx->get_cert_methods,i);
+ j=X509_LOOKUP_by_subject(lu,type,name,&stmp);
+ if (j < 0)
+ {
+ vs->current_method=j;
+ return j;
+ }
+ else if (j)
+ {
+ tmp= &stmp;
+ break;
+ }
+ }
+ vs->current_method=0;
+ if (tmp == NULL)
+ return 0;
+ }
+
+/* if (ret->data.ptr != NULL)
+ X509_OBJECT_free_contents(ret); */
+
+ ret->type=tmp->type;
+ ret->data.ptr=tmp->data.ptr;
+
+ X509_OBJECT_up_ref_count(ret);
+
+ return 1;
+ }
+
+int X509_STORE_add_cert(X509_STORE *ctx, X509 *x)
+ {
+ X509_OBJECT *obj;
+ int ret=1;
+
+ if (x == NULL) return 0;
+ obj=(X509_OBJECT *)OPENSSL_malloc(sizeof(X509_OBJECT));
+ if (obj == NULL)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_STORE_add_cert, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ obj->type=X509_LU_X509;
+ obj->data.x509=x;
+
+ CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
+
+ X509_OBJECT_up_ref_count(obj);
+
+ if (X509_OBJECT_retrieve_match(ctx->objs, obj))
+ {
+ X509_OBJECT_free_contents(obj);
+ OPENSSL_free(obj);
+ OPENSSL_PUT_ERROR(X509, X509_STORE_add_cert, X509_R_CERT_ALREADY_IN_HASH_TABLE);
+ ret=0;
+ }
+ else sk_X509_OBJECT_push(ctx->objs, obj);
+
+ CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
+
+ return ret;
+ }
+
+int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x)
+ {
+ X509_OBJECT *obj;
+ int ret=1;
+
+ if (x == NULL) return 0;
+ obj=(X509_OBJECT *)OPENSSL_malloc(sizeof(X509_OBJECT));
+ if (obj == NULL)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_STORE_add_crl, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ obj->type=X509_LU_CRL;
+ obj->data.crl=x;
+
+ CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
+
+ X509_OBJECT_up_ref_count(obj);
+
+ if (X509_OBJECT_retrieve_match(ctx->objs, obj))
+ {
+ X509_OBJECT_free_contents(obj);
+ OPENSSL_free(obj);
+ OPENSSL_PUT_ERROR(X509, X509_STORE_add_crl, X509_R_CERT_ALREADY_IN_HASH_TABLE);
+ ret=0;
+ }
+ else sk_X509_OBJECT_push(ctx->objs, obj);
+
+ CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
+
+ return ret;
+ }
+
+void X509_OBJECT_up_ref_count(X509_OBJECT *a)
+ {
+ switch (a->type)
+ {
+ case X509_LU_X509:
+ X509_up_ref(a->data.x509);
+ break;
+ case X509_LU_CRL:
+ CRYPTO_add(&a->data.crl->references,1,CRYPTO_LOCK_X509_CRL);
+ break;
+ }
+ }
+
+void X509_OBJECT_free_contents(X509_OBJECT *a)
+ {
+ switch (a->type)
+ {
+ case X509_LU_X509:
+ X509_free(a->data.x509);
+ break;
+ case X509_LU_CRL:
+ X509_CRL_free(a->data.crl);
+ break;
+ }
+ }
+
+static int x509_object_idx_cnt(STACK_OF(X509_OBJECT) *h, int 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;
+ size_t 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:
+ /* abort(); */
+ return -1;
+ }
+
+ idx = -1;
+ if (sk_X509_OBJECT_find(h, &idx, &stmp) && pnmatch)
+ {
+ int tidx;
+ const X509_OBJECT *tobj, *pstmp;
+ *pnmatch = 1;
+ pstmp = &stmp;
+ for (tidx = idx + 1; tidx < (int)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, int type,
+ X509_NAME *name)
+ {
+ return x509_object_idx_cnt(h, type, name, NULL);
+ }
+
+X509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h, int 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);
+ }
+
+STACK_OF(X509)* X509_STORE_get1_certs(X509_STORE_CTX *ctx, X509_NAME *nm)
+ {
+ int i, idx, cnt;
+ STACK_OF(X509) *sk;
+ X509 *x;
+ X509_OBJECT *obj;
+ sk = sk_X509_new_null();
+ CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
+ idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_X509, nm, &cnt);
+ if (idx < 0)
+ {
+ /* Nothing found in cache: do lookup to possibly add new
+ * objects to cache
+ */
+ X509_OBJECT xobj;
+ CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
+ if (!X509_STORE_get_by_subject(ctx, X509_LU_X509, nm, &xobj))
+ {
+ sk_X509_free(sk);
+ return NULL;
+ }
+ X509_OBJECT_free_contents(&xobj);
+ CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
+ idx = x509_object_idx_cnt(ctx->ctx->objs,X509_LU_X509,nm, &cnt);
+ if (idx < 0)
+ {
+ CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
+ sk_X509_free(sk);
+ return NULL;
+ }
+ }
+ for (i = 0; i < cnt; i++, idx++)
+ {
+ obj = sk_X509_OBJECT_value(ctx->ctx->objs, idx);
+ x = obj->data.x509;
+ if (!sk_X509_push(sk, X509_up_ref(x)))
+ {
+ CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
+ X509_free(x);
+ sk_X509_pop_free(sk, X509_free);
+ return NULL;
+ }
+ }
+ CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
+ return sk;
+
+ }
+
+STACK_OF(X509_CRL)* X509_STORE_get1_crls(X509_STORE_CTX *ctx, X509_NAME *nm)
+ {
+ int i, idx, cnt;
+ STACK_OF(X509_CRL) *sk;
+ X509_CRL *x;
+ X509_OBJECT *obj, xobj;
+ sk = sk_X509_CRL_new_null();
+ CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
+ /* Check cache first */
+ idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_CRL, nm, &cnt);
+
+ /* Always do lookup to possibly add new CRLs to cache
+ */
+ CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
+ if (!X509_STORE_get_by_subject(ctx, X509_LU_CRL, nm, &xobj))
+ {
+ sk_X509_CRL_free(sk);
+ return NULL;
+ }
+ X509_OBJECT_free_contents(&xobj);
+ CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
+ idx = x509_object_idx_cnt(ctx->ctx->objs,X509_LU_CRL, nm, &cnt);
+ if (idx < 0)
+ {
+ CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
+ sk_X509_CRL_free(sk);
+ return NULL;
+ }
+
+ for (i = 0; i < cnt; i++, idx++)
+ {
+ obj = sk_X509_OBJECT_value(ctx->ctx->objs, idx);
+ x = obj->data.crl;
+ CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509_CRL);
+ if (!sk_X509_CRL_push(sk, x))
+ {
+ CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
+ X509_CRL_free(x);
+ sk_X509_CRL_pop_free(sk, X509_CRL_free);
+ return NULL;
+ }
+ }
+ CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
+ return sk;
+ }
+
+X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h, X509_OBJECT *x)
+ {
+ size_t idx, i;
+ X509_OBJECT *obj;
+
+ if (!sk_X509_OBJECT_find(h, &idx, x)) {
+ 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;
+ }
+
+
+/* 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 **issuer, X509_STORE_CTX *ctx, X509 *x)
+ {
+ X509_NAME *xn;
+ X509_OBJECT obj, *pobj;
+ int ok, idx, ret;
+ size_t i;
+ xn=X509_get_issuer_name(x);
+ ok=X509_STORE_get_by_subject(ctx,X509_LU_X509,xn,&obj);
+ if (ok != X509_LU_X509)
+ {
+ if (ok == X509_LU_RETRY)
+ {
+ X509_OBJECT_free_contents(&obj);
+ OPENSSL_PUT_ERROR(X509, X509_STORE_CTX_get1_issuer, X509_R_SHOULD_RETRY);
+ return -1;
+ }
+ else if (ok != X509_LU_FAIL)
+ {
+ X509_OBJECT_free_contents(&obj);
+ /* not good :-(, break anyway */
+ return -1;
+ }
+ return 0;
+ }
+ /* If certificate matches all OK */
+ if (ctx->check_issued(ctx, x, obj.data.x509))
+ {
+ *issuer = obj.data.x509;
+ return 1;
+ }
+ X509_OBJECT_free_contents(&obj);
+
+ /* Else find index of first cert accepted by 'check_issued' */
+ ret = 0;
+ CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
+ idx = X509_OBJECT_idx_by_subject(ctx->ctx->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->ctx->objs); i++)
+ {
+ pobj = sk_X509_OBJECT_value(ctx->ctx->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;
+ X509_OBJECT_up_ref_count(pobj);
+ ret = 1;
+ break;
+ }
+ }
+ }
+ CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
+ return ret;
+ }
+
+int X509_STORE_set_flags(X509_STORE *ctx, unsigned long flags)
+ {
+ return X509_VERIFY_PARAM_set_flags(ctx->param, flags);
+ }
+
+int X509_STORE_set_depth(X509_STORE *ctx, int depth)
+ {
+ X509_VERIFY_PARAM_set_depth(ctx->param, depth);
+ return 1;
+ }
+
+int X509_STORE_set_purpose(X509_STORE *ctx, int purpose)
+ {
+ return X509_VERIFY_PARAM_set_purpose(ctx->param, purpose);
+ }
+
+int X509_STORE_set_trust(X509_STORE *ctx, int trust)
+ {
+ return X509_VERIFY_PARAM_set_trust(ctx->param, trust);
+ }
+
+int X509_STORE_set1_param(X509_STORE *ctx, X509_VERIFY_PARAM *param)
+ {
+ return X509_VERIFY_PARAM_set1(ctx->param, param);
+ }
+
+void X509_STORE_set_verify_cb(X509_STORE *ctx,
+ int (*verify_cb)(int, X509_STORE_CTX *))
+ {
+ ctx->verify_cb = verify_cb;
+ }
+
+void X509_STORE_set_lookup_crls_cb(X509_STORE *ctx,
+ STACK_OF(X509_CRL)* (*cb)(X509_STORE_CTX *ctx, X509_NAME *nm))
+ {
+ ctx->lookup_crls = cb;
+ }
+
+X509_STORE *X509_STORE_CTX_get0_store(X509_STORE_CTX *ctx)
+ {
+ return ctx->ctx;
+ }
diff --git a/src/crypto/x509/x509_obj.c b/src/crypto/x509/x509_obj.c
new file mode 100644
index 0000000..914e0de
--- /dev/null
+++ b/src/crypto/x509/x509_obj.c
@@ -0,0 +1,191 @@
+/* crypto/x509/x509_obj.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 <string.h>
+
+#include <openssl/buf.h>
+#include <openssl/err.h>
+#include <openssl/lhash.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/x509.h>
+
+
+char *X509_NAME_oneline(X509_NAME *a, char *buf, int len)
+ {
+ X509_NAME_ENTRY *ne;
+ size_t 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;
+ OPENSSL_free(b);
+ }
+ strncpy(buf,"NO X509_NAME",len);
+ buf[len-1]='\0';
+ 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,(unsigned int)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;
+ OPENSSL_free(b);
+ }
+ else
+ p=buf;
+ if (i == 0)
+ *p = '\0';
+ return(p);
+err:
+ OPENSSL_PUT_ERROR(X509, X509_NAME_oneline, ERR_R_MALLOC_FAILURE);
+ if (b != NULL) BUF_MEM_free(b);
+ return(NULL);
+ }
+
diff --git a/src/crypto/x509/x509_r2x.c b/src/crypto/x509/x509_r2x.c
new file mode 100644
index 0000000..3c8e9c0
--- /dev/null
+++ b/src/crypto/x509/x509_r2x.c
@@ -0,0 +1,113 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/asn1.h>
+#include <openssl/bn.h>
+#include <openssl/buf.h>
+#include <openssl/digest.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/obj.h>
+#include <openssl/x509.h>
+
+
+X509 *X509_REQ_to_X509(X509_REQ *r, int days, EVP_PKEY *pkey)
+ {
+ X509 *ret=NULL;
+ X509_CINF *xi=NULL;
+ X509_NAME *xn;
+
+ if ((ret=X509_new()) == NULL)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_REQ_to_X509, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ /* duplicate the request */
+ xi=ret->cert_info;
+
+ if (sk_X509_ATTRIBUTE_num(r->req_info->attributes) != 0)
+ {
+ if ((xi->version=M_ASN1_INTEGER_new()) == NULL) goto err;
+ if (!ASN1_INTEGER_set(xi->version,2)) goto err;
+/* xi->extensions=ri->attributes; <- bad, should not ever be done
+ ri->attributes=NULL; */
+ }
+
+ xn=X509_REQ_get_subject_name(r);
+ if (X509_set_subject_name(ret,X509_NAME_dup(xn)) == 0)
+ goto err;
+ if (X509_set_issuer_name(ret,X509_NAME_dup(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;
+
+ X509_set_pubkey(ret,X509_REQ_get_pubkey(r));
+
+ if (!X509_sign(ret,pkey,EVP_md5()))
+ goto err;
+ if (0)
+ {
+err:
+ X509_free(ret);
+ ret=NULL;
+ }
+ return(ret);
+ }
+
diff --git a/src/crypto/x509/x509_req.c b/src/crypto/x509/x509_req.c
new file mode 100644
index 0000000..daaedb6
--- /dev/null
+++ b/src/crypto/x509/x509_req.c
@@ -0,0 +1,313 @@
+/* crypto/x509/x509_req.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 <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/bn.h>
+#include <openssl/buf.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/pem.h>
+#include <openssl/x509.h>
+
+
+X509_REQ *X509_to_X509_REQ(X509 *x, EVP_PKEY *pkey, const EVP_MD *md)
+ {
+ X509_REQ *ret;
+ X509_REQ_INFO *ri;
+ int i;
+ EVP_PKEY *pktmp;
+
+ ret=X509_REQ_new();
+ if (ret == NULL)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_to_X509_REQ, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ ri=ret->req_info;
+
+ ri->version->length=1;
+ ri->version->data=(unsigned char *)OPENSSL_malloc(1);
+ if (ri->version->data == NULL) goto err;
+ ri->version->data[0]=0; /* version == 0 */
+
+ if (!X509_REQ_set_subject_name(ret,X509_get_subject_name(x)))
+ goto err;
+
+ pktmp = X509_get_pubkey(x);
+ 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);
+ }
+
+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));
+ }
+
+int X509_REQ_check_private_key(X509_REQ *x, EVP_PKEY *k)
+ {
+ EVP_PKEY *xk=NULL;
+ int ok=0;
+
+ xk=X509_REQ_get_pubkey(x);
+ switch (EVP_PKEY_cmp(xk, k))
+ {
+ case 1:
+ ok=1;
+ break;
+ case 0:
+ OPENSSL_PUT_ERROR(X509, X509_REQ_check_private_key, X509_R_KEY_VALUES_MISMATCH);
+ break;
+ case -1:
+ OPENSSL_PUT_ERROR(X509, X509_REQ_check_private_key, X509_R_KEY_TYPE_MISMATCH);
+ break;
+ case -2:
+ if (k->type == EVP_PKEY_EC)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_REQ_check_private_key, ERR_R_EC_LIB);
+ break;
+ }
+ if (k->type == EVP_PKEY_DH)
+ {
+ /* No idea */
+ OPENSSL_PUT_ERROR(X509, X509_REQ_check_private_key, X509_R_CANT_CHECK_DH_KEY);
+ break;
+ }
+ OPENSSL_PUT_ERROR(X509, X509_REQ_check_private_key, X509_R_UNKNOWN_KEY_TYPE);
+ }
+
+ EVP_PKEY_free(xk);
+ return(ok);
+ }
+
+/* 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 const int ext_nid_list[] = { NID_ext_req, NID_ms_ext_req, NID_undef};
+
+static const 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;
+ }
+}
+
+const int *X509_REQ_get_extension_nids(void)
+{
+ return ext_nids;
+}
+
+void X509_REQ_set_extension_nids(const int *nids)
+{
+ ext_nids = nids;
+}
+
+STACK_OF(X509_EXTENSION) *X509_REQ_get_extensions(X509_REQ *req)
+ {
+ X509_ATTRIBUTE *attr;
+ ASN1_TYPE *ext = NULL;
+ int idx;
+ const int *pnid;
+ const unsigned char *p;
+
+ if ((req == NULL) || (req->req_info == NULL) || !ext_nids)
+ 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);
+ if(attr->single) ext = attr->value.single;
+ else if(sk_ASN1_TYPE_num(attr->value.set))
+ ext = sk_ASN1_TYPE_value(attr->value.set, 0);
+ break;
+ }
+ if(!ext || (ext->type != V_ASN1_SEQUENCE))
+ return NULL;
+ p = ext->value.sequence->data;
+ return (STACK_OF(X509_EXTENSION) *)
+ ASN1_item_d2i(NULL, &p, ext->value.sequence->length,
+ ASN1_ITEM_rptr(X509_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)
+{
+ ASN1_TYPE *at = NULL;
+ X509_ATTRIBUTE *attr = NULL;
+ if(!(at = ASN1_TYPE_new()) ||
+ !(at->value.sequence = ASN1_STRING_new())) goto err;
+
+ at->type = V_ASN1_SEQUENCE;
+ /* Generate encoding of extensions */
+ at->value.sequence->length =
+ ASN1_item_i2d((ASN1_VALUE *)exts,
+ &at->value.sequence->data,
+ ASN1_ITEM_rptr(X509_EXTENSIONS));
+ if(!(attr = X509_ATTRIBUTE_new())) goto err;
+ if(!(attr->value.set = sk_ASN1_TYPE_new_null())) goto err;
+ if(!sk_ASN1_TYPE_push(attr->value.set, at)) goto err;
+ at = NULL;
+ attr->single = 0;
+ attr->object = (ASN1_OBJECT*) OBJ_nid2obj(nid);
+ if (!req->req_info->attributes)
+ {
+ if (!(req->req_info->attributes = sk_X509_ATTRIBUTE_new_null()))
+ goto err;
+ }
+ if(!sk_X509_ATTRIBUTE_push(req->req_info->attributes, attr)) goto err;
+ return 1;
+ err:
+ X509_ATTRIBUTE_free(attr);
+ ASN1_TYPE_free(at);
+ return 0;
+}
+/* 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);
+}
+
+/* Request attribute functions */
+
+int X509_REQ_get_attr_count(const X509_REQ *req)
+{
+ return X509at_get_attr_count(req->req_info->attributes);
+}
+
+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);
+}
+
+int X509_REQ_get_attr_by_OBJ(const X509_REQ *req, ASN1_OBJECT *obj,
+ int lastpos)
+{
+ return X509at_get_attr_by_OBJ(req->req_info->attributes, obj, lastpos);
+}
+
+X509_ATTRIBUTE *X509_REQ_get_attr(const X509_REQ *req, int loc)
+{
+ return X509at_get_attr(req->req_info->attributes, loc);
+}
+
+X509_ATTRIBUTE *X509_REQ_delete_attr(X509_REQ *req, int loc)
+{
+ return X509at_delete_attr(req->req_info->attributes, loc);
+}
+
+int X509_REQ_add1_attr(X509_REQ *req, X509_ATTRIBUTE *attr)
+{
+ if(X509at_add1_attr(&req->req_info->attributes, attr)) return 1;
+ return 0;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
diff --git a/src/crypto/x509/x509_set.c b/src/crypto/x509/x509_set.c
new file mode 100644
index 0000000..06658b0
--- /dev/null
+++ b/src/crypto/x509/x509_set.c
@@ -0,0 +1,154 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/asn1.h>
+#include <openssl/cipher.h>
+#include <openssl/evp.h>
+#include <openssl/obj.h>
+#include <openssl/x509.h>
+
+
+int X509_set_version(X509 *x, long version)
+ {
+ if (x == NULL) return(0);
+ if (version == 0)
+ {
+ M_ASN1_INTEGER_free(x->cert_info->version);
+ x->cert_info->version = NULL;
+ return(1);
+ }
+ if (x->cert_info->version == NULL)
+ {
+ if ((x->cert_info->version=M_ASN1_INTEGER_new()) == NULL)
+ return(0);
+ }
+ return(ASN1_INTEGER_set(x->cert_info->version,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=M_ASN1_INTEGER_dup(serial);
+ if (in != NULL)
+ {
+ M_ASN1_INTEGER_free(x->cert_info->serialNumber);
+ x->cert_info->serialNumber=in;
+ }
+ }
+ return(in != NULL);
+ }
+
+int X509_set_issuer_name(X509 *x, X509_NAME *name)
+ {
+ if ((x == NULL) || (x->cert_info == NULL)) return(0);
+ return(X509_NAME_set(&x->cert_info->issuer,name));
+ }
+
+int X509_set_subject_name(X509 *x, X509_NAME *name)
+ {
+ if ((x == NULL) || (x->cert_info == NULL)) return(0);
+ return(X509_NAME_set(&x->cert_info->subject,name));
+ }
+
+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=M_ASN1_TIME_dup(tm);
+ if (in != NULL)
+ {
+ M_ASN1_TIME_free(x->cert_info->validity->notBefore);
+ x->cert_info->validity->notBefore=in;
+ }
+ }
+ return(in != NULL);
+ }
+
+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=M_ASN1_TIME_dup(tm);
+ if (in != NULL)
+ {
+ M_ASN1_TIME_free(x->cert_info->validity->notAfter);
+ x->cert_info->validity->notAfter=in;
+ }
+ }
+ return(in != NULL);
+ }
+
+int X509_set_pubkey(X509 *x, EVP_PKEY *pkey)
+ {
+ if ((x == NULL) || (x->cert_info == NULL)) return(0);
+ return(X509_PUBKEY_set(&(x->cert_info->key),pkey));
+ }
+
+
+
diff --git a/src/crypto/x509/x509_trs.c b/src/crypto/x509/x509_trs.c
new file mode 100644
index 0000000..9b7cc9c
--- /dev/null
+++ b/src/crypto/x509/x509_trs.c
@@ -0,0 +1,304 @@
+/* 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 <openssl/buf.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/x509v3.h>
+
+
+static int tr_cmp(const X509_TRUST **a,
+ const X509_TRUST **b);
+static void trtable_free(X509_TRUST *p);
+
+static int trust_1oidany(X509_TRUST *trust, X509 *x, int flags);
+static int trust_1oid(X509_TRUST *trust, X509 *x, int flags);
+static int trust_compat(X509_TRUST *trust, X509 *x, int flags);
+
+static int obj_trust(int id, X509 *x, int flags);
+static int (*default_trust)(int id, X509 *x, int flags) = obj_trust;
+
+/* WARNING: the following table should be kept in order of trust
+ * and without any gaps so we can just subtract the minimum trust
+ * value to get an index into the table
+ */
+
+static X509_TRUST trstandard[] = {
+{X509_TRUST_COMPAT, 0, trust_compat, (char *) "compatible", 0, NULL},
+{X509_TRUST_SSL_CLIENT, 0, trust_1oidany, (char *) "SSL Client", NID_client_auth, NULL},
+{X509_TRUST_SSL_SERVER, 0, trust_1oidany, (char *) "SSL Server", NID_server_auth, NULL},
+{X509_TRUST_EMAIL, 0, trust_1oidany, (char *) "S/MIME email", NID_email_protect, NULL},
+{X509_TRUST_OBJECT_SIGN, 0, trust_1oidany, (char *) "Object Signer", NID_code_sign, NULL},
+{X509_TRUST_OCSP_SIGN, 0, trust_1oid, (char *) "OCSP responder", NID_OCSP_sign, NULL},
+{X509_TRUST_OCSP_REQUEST, 0, trust_1oid, (char *) "OCSP request", NID_ad_OCSP, NULL},
+{X509_TRUST_TSA, 0, trust_1oidany, (char *) "TSA server", NID_time_stamp, NULL}
+};
+
+#define X509_TRUST_COUNT (sizeof(trstandard)/sizeof(X509_TRUST))
+
+static STACK_OF(X509_TRUST) *trtable = NULL;
+
+static int tr_cmp(const X509_TRUST **a,
+ const X509_TRUST **b)
+{
+ return (*a)->trust - (*b)->trust;
+}
+
+int (*X509_TRUST_set_default(int (*trust)(int , X509 *, int)))(int, X509 *, int)
+{
+ int (*oldtrust)(int , X509 *, int);
+ oldtrust = default_trust;
+ default_trust = trust;
+ return oldtrust;
+}
+
+
+int X509_check_trust(X509 *x, int id, int flags)
+{
+ X509_TRUST *pt;
+ int idx;
+ if(id == -1) return 1;
+ /* We get this as a default value */
+ 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);
+}
+
+int X509_TRUST_get_count(void)
+{
+ if(!trtable) return X509_TRUST_COUNT;
+ return sk_X509_TRUST_num(trtable) + X509_TRUST_COUNT;
+}
+
+X509_TRUST * X509_TRUST_get0(int idx)
+{
+ if(idx < 0) return NULL;
+ if(idx < (int)X509_TRUST_COUNT) return trstandard + idx;
+ return sk_X509_TRUST_value(trtable, idx - X509_TRUST_COUNT);
+}
+
+int X509_TRUST_get_by_id(int id)
+{
+ X509_TRUST tmp;
+ size_t idx;
+
+ if((id >= X509_TRUST_MIN) && (id <= X509_TRUST_MAX))
+ return id - X509_TRUST_MIN;
+ tmp.trust = id;
+ if(!trtable) return -1;
+ if (!sk_X509_TRUST_find(trtable, &idx, &tmp)) {
+ return -1;
+ }
+ return idx + X509_TRUST_COUNT;
+}
+
+int X509_TRUST_set(int *t, int trust)
+{
+ if(X509_TRUST_get_by_id(trust) == -1) {
+ OPENSSL_PUT_ERROR(X509, X509_TRUST_set, X509_R_INVALID_TRUST);
+ return 0;
+ }
+ *t = trust;
+ return 1;
+}
+
+int X509_TRUST_add(int id, int flags, int (*ck)(X509_TRUST *, X509 *, int),
+ 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 = OPENSSL_malloc(sizeof(X509_TRUST)))) {
+ OPENSSL_PUT_ERROR(X509, X509_TRUST_add, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ trtmp->flags = X509_TRUST_DYNAMIC;
+ } else trtmp = X509_TRUST_get0(idx);
+
+ /* Duplicate the supplied name. */
+ name_dup = BUF_strdup(name);
+ if (name_dup == NULL) {
+ OPENSSL_PUT_ERROR(X509, X509_TRUST_add, ERR_R_MALLOC_FAILURE);
+ if (idx == -1)
+ OPENSSL_free(trtmp);
+ return 0;
+ }
+
+ /* OPENSSL_free existing name if dynamic */
+ if (trtmp->flags & X509_TRUST_DYNAMIC_NAME) OPENSSL_free(trtmp->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 its a new entry manage the dynamic table */
+ if(idx == -1) {
+ if(!trtable && !(trtable = sk_X509_TRUST_new(tr_cmp))) {
+ OPENSSL_PUT_ERROR(X509, X509_TRUST_add, ERR_R_MALLOC_FAILURE);
+ trtable_free(trtmp);
+ return 0;
+ }
+ if (!sk_X509_TRUST_push(trtable, trtmp)) {
+ OPENSSL_PUT_ERROR(X509, X509_TRUST_add, ERR_R_MALLOC_FAILURE);
+ trtable_free(trtmp);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static void trtable_free(X509_TRUST *p)
+ {
+ if(!p) return;
+ if (p->flags & X509_TRUST_DYNAMIC)
+ {
+ if (p->flags & X509_TRUST_DYNAMIC_NAME)
+ OPENSSL_free(p->name);
+ OPENSSL_free(p);
+ }
+ }
+
+void X509_TRUST_cleanup(void)
+{
+ unsigned int i;
+ for(i = 0; i < X509_TRUST_COUNT; i++) trtable_free(trstandard + i);
+ sk_X509_TRUST_pop_free(trtable, trtable_free);
+ trtable = NULL;
+}
+
+int X509_TRUST_get_flags(X509_TRUST *xp)
+{
+ return xp->flags;
+}
+
+char *X509_TRUST_get0_name(X509_TRUST *xp)
+{
+ return xp->name;
+}
+
+int X509_TRUST_get_trust(X509_TRUST *xp)
+{
+ return xp->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;
+ size_t i;
+ 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);
+ if(OBJ_obj2nid(obj) == id) 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);
+ if(OBJ_obj2nid(obj) == id) return X509_TRUST_TRUSTED;
+ }
+ }
+ return X509_TRUST_UNTRUSTED;
+}
+
diff --git a/src/crypto/x509/x509_txt.c b/src/crypto/x509/x509_txt.c
new file mode 100644
index 0000000..c286710
--- /dev/null
+++ b/src/crypto/x509/x509_txt.c
@@ -0,0 +1,209 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/asn1.h>
+#include <openssl/buf.h>
+#include <openssl/cipher.h>
+#include <openssl/evp.h>
+#include <openssl/lhash.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/x509.h>
+
+
+const char *X509_verify_cert_error_string(long n)
+ {
+ static char buf[100];
+
+ switch ((int)n)
+ {
+ case X509_V_OK:
+ return("ok");
+ 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_CRL_NOT_YET_VALID:
+ return("CRL is not yet valid");
+ case X509_V_ERR_CERT_HAS_EXPIRED:
+ return("certificate has expired");
+ 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_INVALID_NON_CA:
+ return ("invalid non-CA certificate (has CA markings)");
+ case X509_V_ERR_PATH_LENGTH_EXCEEDED:
+ return ("path length constraint exceeded");
+ case X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED:
+ return("proxy path length constraint exceeded");
+ case X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED:
+ return("proxy certificates not allowed, please set the appropriate flag");
+ 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_APPLICATION_VERIFICATION:
+ return("application verification failure");
+ 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_KEYUSAGE_NO_DIGITAL_SIGNATURE:
+ return("key usage does not include digital signature");
+ case X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION:
+ return("unhandled critical CRL extension");
+ 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_SUITE_B_INVALID_VERSION:
+ return("Suite B: certificate version invalid");
+ case X509_V_ERR_SUITE_B_INVALID_ALGORITHM:
+ return("Suite B: invalid public key algorithm");
+ case X509_V_ERR_SUITE_B_INVALID_CURVE:
+ return("Suite B: invalid ECC curve");
+ case X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM:
+ return("Suite B: invalid signature algorithm");
+ case X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED:
+ return("Suite B: curve not allowed for this LOS");
+ case X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256:
+ return("Suite B: cannot sign P-384 with P-256");
+
+ case X509_V_ERR_HOSTNAME_MISMATCH:
+ return("Hostname mismatch");
+ case X509_V_ERR_EMAIL_MISMATCH:
+ return("Email address mismatch");
+ case X509_V_ERR_IP_ADDRESS_MISMATCH:
+ return("IP address mismatch");
+
+ default:
+ BIO_snprintf(buf,sizeof buf,"error number %ld",n);
+ return(buf);
+ }
+ }
+
+
diff --git a/src/crypto/x509/x509_v3.c b/src/crypto/x509/x509_v3.c
new file mode 100644
index 0000000..95fe729
--- /dev/null
+++ b/src/crypto/x509/x509_v3.c
@@ -0,0 +1,271 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/asn1.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/obj.h>
+#include <openssl/stack.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+
+
+int X509v3_get_ext_count(const STACK_OF(X509_EXTENSION) *x)
+ {
+ if (x == NULL) return(0);
+ return(sk_X509_EXTENSION_num(x));
+ }
+
+int X509v3_get_ext_by_NID(const STACK_OF(X509_EXTENSION) *x, int nid,
+ int lastpos)
+ {
+ const ASN1_OBJECT *obj;
+
+ obj=OBJ_nid2obj(nid);
+ if (obj == NULL) return(-2);
+ return(X509v3_get_ext_by_OBJ(x,obj,lastpos));
+ }
+
+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);
+ }
+
+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);
+ }
+
+X509_EXTENSION *X509v3_get_ext(const STACK_OF(X509_EXTENSION) *x, int loc)
+ {
+ if (x == NULL || loc < 0 || sk_X509_EXTENSION_num(x) <= (size_t) loc)
+ return NULL;
+ else
+ return sk_X509_EXTENSION_value(x,loc);
+ }
+
+X509_EXTENSION *X509v3_delete_ext(STACK_OF(X509_EXTENSION) *x, int loc)
+ {
+ X509_EXTENSION *ret;
+
+ if (x == NULL || loc < 0 || sk_X509_EXTENSION_num(x) <= (size_t) loc)
+ return(NULL);
+ ret=sk_X509_EXTENSION_delete(x,loc);
+ return(ret);
+ }
+
+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)
+ {
+ OPENSSL_PUT_ERROR(X509, X509v3_add_ext, 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:
+ OPENSSL_PUT_ERROR(X509, X509v3_add_ext, ERR_R_MALLOC_FAILURE);
+err2:
+ if (new_ex != NULL) X509_EXTENSION_free(new_ex);
+ if (sk != NULL) sk_X509_EXTENSION_free(sk);
+ return(NULL);
+ }
+
+X509_EXTENSION *X509_EXTENSION_create_by_NID(X509_EXTENSION **ex, int nid,
+ int crit, ASN1_OCTET_STRING *data)
+ {
+ const ASN1_OBJECT *obj;
+ X509_EXTENSION *ret;
+
+ obj=OBJ_nid2obj(nid);
+ if (obj == NULL)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_EXTENSION_create_by_NID, X509_R_UNKNOWN_NID);
+ return(NULL);
+ }
+ ret=X509_EXTENSION_create_by_OBJ(ex,obj,crit,data);
+ return(ret);
+ }
+
+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)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_EXTENSION_create_by_OBJ, 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);
+ }
+
+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(1);
+ }
+
+int X509_EXTENSION_set_critical(X509_EXTENSION *ex, int crit)
+ {
+ if (ex == NULL) return(0);
+ ex->critical=(crit)?0xFF:-1;
+ return(1);
+ }
+
+int X509_EXTENSION_set_data(X509_EXTENSION *ex, ASN1_OCTET_STRING *data)
+ {
+ int i;
+
+ if (ex == NULL) return(0);
+ i=M_ASN1_OCTET_STRING_set(ex->value,data->data,data->length);
+ if (!i) return(0);
+ return(1);
+ }
+
+ASN1_OBJECT *X509_EXTENSION_get_object(X509_EXTENSION *ex)
+ {
+ if (ex == NULL) return(NULL);
+ return(ex->object);
+ }
+
+ASN1_OCTET_STRING *X509_EXTENSION_get_data(X509_EXTENSION *ex)
+ {
+ if (ex == NULL) return(NULL);
+ return(ex->value);
+ }
+
+int X509_EXTENSION_get_critical(X509_EXTENSION *ex)
+ {
+ if (ex == NULL) return(0);
+ if(ex->critical > 0) return 1;
+ return 0;
+ }
diff --git a/src/crypto/x509/x509_vfy.c b/src/crypto/x509/x509_vfy.c
new file mode 100644
index 0000000..285bcaf
--- /dev/null
+++ b/src/crypto/x509/x509_vfy.c
@@ -0,0 +1,2447 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <string.h>
+#include <time.h>
+
+#include <openssl/asn1.h>
+#include <openssl/buf.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/lhash.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+
+#include "vpm_int.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 *x, X509 *issuer);
+static X509 *find_issuer(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *x);
+static int check_chain_extensions(X509_STORE_CTX *ctx);
+static int check_name_constraints(X509_STORE_CTX *ctx);
+static int check_id(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);
+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 internal_verify(X509_STORE_CTX *ctx);
+const char X509_version[]="X.509";
+
+
+static int null_callback(int ok, X509_STORE_CTX *e)
+ {
+ return ok;
+ }
+
+#if 0
+static int x509_subject_cmp(X509 **a, X509 **b)
+ {
+ return X509_subject_name_cmp(*a,*b);
+ }
+#endif
+/* Return 1 is 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;
+ }
+
+/* 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;
+ }
+
+int X509_verify_cert(X509_STORE_CTX *ctx)
+ {
+ X509 *x,*xtmp,*chain_ss=NULL;
+ int bad_chain = 0;
+ X509_VERIFY_PARAM *param = ctx->param;
+ int depth,i,ok=0;
+ int num;
+ int (*cb)(int xok,X509_STORE_CTX *xctx);
+ STACK_OF(X509) *sktmp=NULL;
+ if (ctx->cert == NULL)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_verify_cert, X509_R_NO_CERT_SET_FOR_US_TO_VERIFY);
+ return -1;
+ }
+
+ 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 */
+ if (ctx->chain == NULL)
+ {
+ if ( ((ctx->chain=sk_X509_new_null()) == NULL) ||
+ (!sk_X509_push(ctx->chain,ctx->cert)))
+ {
+ OPENSSL_PUT_ERROR(X509, X509_verify_cert, ERR_R_MALLOC_FAILURE);
+ goto end;
+ }
+ X509_up_ref(ctx->cert);
+ ctx->last_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)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_verify_cert, ERR_R_MALLOC_FAILURE);
+ 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 */
+ if (depth < num) 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 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)
+ return ok;
+ /* 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)
+ {
+ xtmp=find_issuer(ctx, sktmp,x);
+ if (xtmp != NULL)
+ {
+ if (!sk_X509_push(ctx->chain,xtmp))
+ {
+ OPENSSL_PUT_ERROR(X509, X509_verify_cert, ERR_R_MALLOC_FAILURE);
+ goto end;
+ }
+ CRYPTO_add(&xtmp->references,1,CRYPTO_LOCK_X509);
+ (void)sk_X509_delete_ptr(sktmp,xtmp);
+ ctx->last_untrusted++;
+ x=xtmp;
+ num++;
+ /* reparse the full chain for
+ * the next one */
+ continue;
+ }
+ }
+ break;
+ }
+
+ /* 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. */
+
+ /* 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 (sk_X509_num(ctx->chain) == 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->last_untrusted=0;
+ }
+ }
+ else
+ {
+ /* extract and save self signed certificate for later use */
+ chain_ss=sk_X509_pop(ctx->chain);
+ ctx->last_untrusted--;
+ num--;
+ 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) return ok;
+ if (ok == 0) break;
+
+ x = xtmp;
+ if (!sk_X509_push(ctx->chain,x))
+ {
+ X509_free(xtmp);
+ OPENSSL_PUT_ERROR(X509, X509_verify_cert, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ num++;
+ }
+
+ /* we now have our chain, lets check it... */
+
+ i = check_trust(ctx);
+
+ /* If explicitly rejected error */
+ if (i == X509_TRUST_REJECTED)
+ goto end;
+ /* 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 (i != X509_TRUST_TRUSTED && !bad_chain)
+ {
+ if ((chain_ss == NULL) || !ctx->check_issued(ctx, x, chain_ss))
+ {
+ if (ctx->last_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
+ {
+
+ sk_X509_push(ctx->chain,chain_ss);
+ num++;
+ ctx->last_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;
+ }
+
+ /* We have the chain complete: now we need to check its purpose */
+ ok = check_chain_extensions(ctx);
+
+ if (!ok) goto end;
+
+ /* Check name constraints */
+
+ ok = check_name_constraints(ctx);
+
+ if (!ok) goto end;
+
+ ok = check_id(ctx);
+
+ if (!ok) goto end;
+
+ /* We may as well copy down any DSA parameters that are required */
+ X509_get_pubkey_parameters(NULL,ctx->chain);
+
+ /* 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;
+
+ i = X509_chain_check_suiteb(&ctx->error_depth, NULL, ctx->chain,
+ ctx->param->flags);
+ if (i != X509_V_OK)
+ {
+ ctx->error = i;
+ ctx->current_cert = sk_X509_value(ctx->chain, ctx->error_depth);
+ ok = cb(0, 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 && (ctx->param->flags & X509_V_FLAG_POLICY_CHECK))
+ ok = ctx->check_policy(ctx);
+ if(!ok) goto end;
+ if (0)
+ {
+end:
+ X509_get_pubkey_parameters(NULL,ctx->chain);
+ }
+ if (sktmp != NULL) sk_X509_free(sktmp);
+ if (chain_ss != NULL) X509_free(chain_ss);
+ return ok;
+ }
+
+
+/* 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)
+{
+ size_t i;
+ X509 *issuer;
+ for (i = 0; i < sk_X509_num(sk); i++)
+ {
+ issuer = sk_X509_value(sk, i);
+ if (ctx->check_issued(ctx, x, issuer))
+ return issuer;
+ }
+ return NULL;
+}
+
+/* Given a possible certificate and issuer check them */
+
+static int check_issued(X509_STORE_CTX *ctx, X509 *x, X509 *issuer)
+{
+ int ret;
+ ret = X509_check_issued(issuer, x);
+ if (ret == X509_V_OK)
+ return 1;
+ /* If we haven't asked for issuer errors don't set ctx */
+ if (!(ctx->param->flags & X509_V_FLAG_CB_ISSUER_CHECK))
+ return 0;
+
+ ctx->error = ret;
+ ctx->current_cert = x;
+ ctx->current_issuer = issuer;
+ return ctx->verify_cb(0, ctx);
+}
+
+/* Alternative lookup method: look from a STACK stored in other_ctx */
+
+static int get_issuer_sk(X509 **issuer, X509_STORE_CTX *ctx, X509 *x)
+{
+ *issuer = find_issuer(ctx, ctx->other_ctx, x);
+ if (*issuer)
+ {
+ X509_up_ref(*issuer);
+ return 1;
+ }
+ else
+ return 0;
+}
+
+
+/* Check a certificate chains extensions for consistency
+ * with the supplied purpose
+ */
+
+static int check_chain_extensions(X509_STORE_CTX *ctx)
+{
+ 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;
+ int allow_proxy_certs;
+ 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)
+ {
+ allow_proxy_certs = 0;
+ purpose = X509_PURPOSE_CRL_SIGN;
+ }
+ else
+ {
+ allow_proxy_certs =
+ !!(ctx->param->flags & X509_V_FLAG_ALLOW_PROXY_CERTS);
+ /* A hack to keep people who don't want to modify their
+ software happy */
+ if (getenv("OPENSSL_ALLOW_PROXY_CERTS"))
+ allow_proxy_certs = 1;
+ purpose = ctx->param->purpose;
+ }
+
+ /* Check all untrusted certificates */
+ for (i = 0; i < ctx->last_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;
+ }
+ if (!allow_proxy_certs && (x->ex_flags & EXFLAG_PROXY))
+ {
+ ctx->error = X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED;
+ ctx->error_depth = i;
+ ctx->current_cert = x;
+ ok=cb(0,ctx);
+ if (!ok) goto end;
+ }
+ ret = X509_check_ca(x);
+ switch(must_be_ca)
+ {
+ case -1:
+ if ((ctx->param->flags & X509_V_FLAG_X509_STRICT)
+ && (ret != 1) && (ret != 0))
+ {
+ ret = 0;
+ ctx->error = X509_V_ERR_INVALID_CA;
+ }
+ else
+ ret = 1;
+ break;
+ case 0:
+ if (ret != 0)
+ {
+ ret = 0;
+ ctx->error = X509_V_ERR_INVALID_NON_CA;
+ }
+ else
+ ret = 1;
+ break;
+ default:
+ 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;
+ break;
+ }
+ 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++;
+ /* If this certificate is a proxy certificate, the next
+ certificate must be another proxy certificate or a EE
+ certificate. If not, the next certificate must be a
+ CA certificate. */
+ if (x->ex_flags & EXFLAG_PROXY)
+ {
+ if (x->ex_pcpathlen != -1 && i > x->ex_pcpathlen)
+ {
+ ctx->error =
+ X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED;
+ ctx->error_depth = i;
+ ctx->current_cert = x;
+ ok=cb(0,ctx);
+ if (!ok) goto end;
+ }
+ proxy_path_length++;
+ must_be_ca = 0;
+ }
+ else
+ must_be_ca = 1;
+ }
+ ok = 1;
+ end:
+ return ok;
+}
+
+static int check_name_constraints(X509_STORE_CTX *ctx)
+ {
+ X509 *x;
+ int i, j, rv;
+ /* Check name constraints for all certificates */
+ for (i = sk_X509_num(ctx->chain) - 1; i >= 0; i--)
+ {
+ x = sk_X509_value(ctx->chain, i);
+ /* Ignore self issued certs unless last in chain */
+ if (i && (x->ex_flags & EXFLAG_SI))
+ continue;
+ /* Check against constraints for all certificates higher in
+ * chain including trust anchor. Trust anchor not strictly
+ * speaking needed but if it includes constraints it is to be
+ * assumed it expects them to be obeyed.
+ */
+ for (j = sk_X509_num(ctx->chain) - 1; j > i; j--)
+ {
+ NAME_CONSTRAINTS *nc = sk_X509_value(ctx->chain, j)->nc;
+ if (nc)
+ {
+ rv = NAME_CONSTRAINTS_check(x, nc);
+ if (rv != X509_V_OK)
+ {
+ ctx->error = rv;
+ ctx->error_depth = i;
+ ctx->current_cert = x;
+ if (!ctx->verify_cb(0,ctx))
+ return 0;
+ }
+ }
+ }
+ }
+ return 1;
+ }
+
+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_id(X509_STORE_CTX *ctx)
+ {
+ X509_VERIFY_PARAM *vpm = ctx->param;
+ X509_VERIFY_PARAM_ID *id = vpm->id;
+ X509 *x = ctx->cert;
+ if (id->host && !X509_check_host(x, id->host, id->hostlen,
+ id->hostflags))
+ {
+ if (!check_id_error(ctx, X509_V_ERR_HOSTNAME_MISMATCH))
+ return 0;
+ }
+ if (id->email && !X509_check_email(x, id->email, id->emaillen, 0))
+ {
+ if (!check_id_error(ctx, X509_V_ERR_EMAIL_MISMATCH))
+ return 0;
+ }
+ if (id->ip && !X509_check_ip(x, id->ip, id->iplen, 0))
+ {
+ if (!check_id_error(ctx, X509_V_ERR_IP_ADDRESS_MISMATCH))
+ return 0;
+ }
+ return 1;
+ }
+
+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->last_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->last_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->last_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;
+}
+
+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++)
+ {
+ ctx->error_depth = i;
+ ok = check_cert(ctx);
+ if (!ok) return ok;
+ }
+ return 1;
+ }
+
+static int check_cert(X509_STORE_CTX *ctx)
+ {
+ X509_CRL *crl = NULL, *dcrl = NULL;
+ X509 *x;
+ int ok, cnum;
+ unsigned int last_reasons;
+ cnum = ctx->error_depth;
+ x = sk_X509_value(ctx->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;
+ }
+
+ 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:
+ X509_CRL_free(crl);
+ X509_CRL_free(dcrl);
+
+ ctx->current_crl = NULL;
+ 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
+ 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 crl_score, best_score = *pscore;
+ size_t i;
+ 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;
+ size_t 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;
+ size_t 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 < (int) 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->ctx, x, ctx->untrusted))
+ return -1;
+
+ 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;
+ size_t 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)
+ {
+ size_t 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)
+ {
+ size_t 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 find CRL issuer: if not last certificate then issuer
+ * is next certificate in chain.
+ */
+ else if (cnum < chnum)
+ 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
+ {
+ int rv;
+ rv = X509_CRL_check_suiteb(crl, ikey, ctx->param->flags);
+ if (rv != X509_V_OK)
+ {
+ ctx->error=rv;
+ ok = ctx->verify_cb(0, ctx);
+ if (!ok)
+ goto err;
+ }
+ /* 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;
+ }
+
+static int check_policy(X509_STORE_CTX *ctx)
+ {
+ int ret;
+ if (ctx->parent)
+ return 1;
+ ret = X509_policy_check(&ctx->tree, &ctx->explicit_policy, ctx->chain,
+ ctx->param->policies, ctx->param->flags);
+ if (ret == 0)
+ {
+ OPENSSL_PUT_ERROR(X509, check_policy, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ /* Invalid or inconsistent extensions */
+ if (ret == -1)
+ {
+ /* Locate certificates with bad extensions and notify
+ * callback.
+ */
+ X509 *x;
+ size_t i;
+ for (i = 1; i < sk_X509_num(ctx->chain); i++)
+ {
+ x = sk_X509_value(ctx->chain, i);
+ if (!(x->ex_flags & EXFLAG_INVALID_POLICY))
+ continue;
+ ctx->current_cert = x;
+ ctx->error = X509_V_ERR_INVALID_POLICY_EXTENSION;
+ if(!ctx->verify_cb(0, ctx))
+ return 0;
+ }
+ return 1;
+ }
+ if (ret == -2)
+ {
+ ctx->current_cert = NULL;
+ ctx->error = X509_V_ERR_NO_EXPLICIT_POLICY;
+ return ctx->verify_cb(0, ctx);
+ }
+
+ if (ctx->param->flags & X509_V_FLAG_NOTIFY_POLICY)
+ {
+ ctx->current_cert = NULL;
+ ctx->error = X509_V_OK;
+ if (!ctx->verify_cb(2, ctx))
+ return 0;
+ }
+
+ return 1;
+ }
+
+static int check_cert_time(X509_STORE_CTX *ctx, X509 *x)
+ {
+ time_t *ptime;
+ int i;
+
+ if (ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME)
+ ptime = &ctx->param->check_time;
+ else
+ ptime = NULL;
+
+ i=X509_cmp_time(X509_get_notBefore(x), ptime);
+ if (i == 0)
+ {
+ ctx->error=X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD;
+ ctx->current_cert=x;
+ if (!ctx->verify_cb(0, ctx))
+ return 0;
+ }
+
+ if (i > 0)
+ {
+ ctx->error=X509_V_ERR_CERT_NOT_YET_VALID;
+ ctx->current_cert=x;
+ if (!ctx->verify_cb(0, ctx))
+ return 0;
+ }
+
+ i=X509_cmp_time(X509_get_notAfter(x), ptime);
+ if (i == 0)
+ {
+ ctx->error=X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD;
+ ctx->current_cert=x;
+ if (!ctx->verify_cb(0, ctx))
+ return 0;
+ }
+
+ if (i < 0)
+ {
+ ctx->error=X509_V_ERR_CERT_HAS_EXPIRED;
+ ctx->current_cert=x;
+ if (!ctx->verify_cb(0, ctx))
+ return 0;
+ }
+
+ return 1;
+ }
+
+static int internal_verify(X509_STORE_CTX *ctx)
+ {
+ int ok=0,n;
+ X509 *xs,*xi;
+ EVP_PKEY *pkey=NULL;
+ int (*cb)(int xok,X509_STORE_CTX *xctx);
+
+ cb=ctx->verify_cb;
+
+ n=sk_X509_num(ctx->chain);
+ ctx->error_depth=n-1;
+ n--;
+ xi=sk_X509_value(ctx->chain,n);
+
+ 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)
+ {
+ ctx->error=X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE;
+ ctx->current_cert=xi;
+ ok=cb(0,ctx);
+ goto end;
+ }
+ else
+ {
+ n--;
+ ctx->error_depth=n;
+ xs=sk_X509_value(ctx->chain,n);
+ }
+ }
+
+/* ctx->error=0; not needed */
+ while (n >= 0)
+ {
+ ctx->error_depth=n;
+
+ /* Skip signature check for self signed certificates unless
+ * explicitly asked for. It doesn't add any security and
+ * just wastes time.
+ */
+ if (!xs->valid && (xs != xi || (ctx->param->flags & X509_V_FLAG_CHECK_SS_SIGNATURE)))
+ {
+ if ((pkey=X509_get_pubkey(xi)) == NULL)
+ {
+ ctx->error=X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY;
+ ctx->current_cert=xi;
+ ok=(*cb)(0,ctx);
+ if (!ok) goto end;
+ }
+ else if (X509_verify(xs,pkey) <= 0)
+ {
+ ctx->error=X509_V_ERR_CERT_SIGNATURE_FAILURE;
+ ctx->current_cert=xs;
+ ok=(*cb)(0,ctx);
+ if (!ok)
+ {
+ EVP_PKEY_free(pkey);
+ goto end;
+ }
+ }
+ EVP_PKEY_free(pkey);
+ pkey=NULL;
+ }
+
+ xs->valid = 1;
+
+ check_cert:
+ ok = check_cert_time(ctx, xs);
+ if (!ok)
+ goto end;
+
+ /* The last error (if any) is still in the error value */
+ ctx->current_issuer=xi;
+ ctx->current_cert=xs;
+ ok=(*cb)(1,ctx);
+ if (!ok) goto end;
+
+ n--;
+ if (n >= 0)
+ {
+ xi=xs;
+ xs=sk_X509_value(ctx->chain,n);
+ }
+ }
+ ok=1;
+end:
+ return ok;
+ }
+
+int X509_cmp_current_time(const ASN1_TIME *ctm)
+{
+ return X509_cmp_time(ctm, NULL);
+}
+
+int X509_cmp_time(const ASN1_TIME *ctm, time_t *cmp_time)
+ {
+ char *str;
+ ASN1_TIME atm;
+ long offset;
+ char buff1[24],buff2[24],*p;
+ int i,j;
+
+ p=buff1;
+ i=ctm->length;
+ str=(char *)ctm->data;
+ if (ctm->type == V_ASN1_UTCTIME)
+ {
+ if ((i < 11) || (i > 17)) return 0;
+ memcpy(p,str,10);
+ p+=10;
+ str+=10;
+ }
+ else
+ {
+ if (i < 13) return 0;
+ memcpy(p,str,12);
+ p+=12;
+ str+=12;
+ }
+
+ if ((*str == 'Z') || (*str == '-') || (*str == '+'))
+ { *(p++)='0'; *(p++)='0'; }
+ else
+ {
+ *(p++)= *(str++);
+ *(p++)= *(str++);
+ /* Skip any fractional seconds... */
+ if (*str == '.')
+ {
+ str++;
+ while ((*str >= '0') && (*str <= '9')) str++;
+ }
+
+ }
+ *(p++)='Z';
+ *(p++)='\0';
+
+ if (*str == 'Z')
+ offset=0;
+ else
+ {
+ if ((*str != '+') && (*str != '-'))
+ return 0;
+ offset=((str[1]-'0')*10+(str[2]-'0'))*60;
+ offset+=(str[3]-'0')*10+(str[4]-'0');
+ if (*str == '-')
+ offset= -offset;
+ }
+ atm.type=ctm->type;
+ atm.flags = 0;
+ atm.length=sizeof(buff2);
+ atm.data=(unsigned char *)buff2;
+
+ if (X509_time_adj(&atm, offset*60, cmp_time) == NULL)
+ return 0;
+
+ if (ctm->type == V_ASN1_UTCTIME)
+ {
+ i=(buff1[0]-'0')*10+(buff1[1]-'0');
+ if (i < 50) i+=100; /* cf. RFC 2459 */
+ j=(buff2[0]-'0')*10+(buff2[1]-'0');
+ if (j < 50) j+=100;
+
+ if (i < j) return -1;
+ if (i > j) return 1;
+ }
+ i=strcmp(buff1,buff2);
+ if (i == 0) /* wait a second then return younger :-) */
+ return -1;
+ else
+ return i;
+ }
+
+ASN1_TIME *X509_gmtime_adj(ASN1_TIME *s, long adj)
+{
+ return X509_time_adj(s, adj, NULL);
+}
+
+ASN1_TIME *X509_time_adj(ASN1_TIME *s, long offset_sec, time_t *in_tm)
+ {
+ return X509_time_adj_ex(s, 0, offset_sec, in_tm);
+ }
+
+ASN1_TIME *X509_time_adj_ex(ASN1_TIME *s,
+ int offset_day, long offset_sec, time_t *in_tm)
+ {
+ time_t t = 0;
+
+ if (in_tm) t = *in_tm;
+ else time(&t);
+
+ if (s && !(s->flags & ASN1_STRING_FLAG_MSTRING))
+ {
+ if (s->type == V_ASN1_UTCTIME)
+ return ASN1_UTCTIME_adj(s,t, offset_day, offset_sec);
+ if (s->type == V_ASN1_GENERALIZEDTIME)
+ return ASN1_GENERALIZEDTIME_adj(s, t, offset_day,
+ offset_sec);
+ }
+ return ASN1_TIME_adj(s, t, offset_day, offset_sec);
+ }
+
+int X509_get_pubkey_parameters(EVP_PKEY *pkey, STACK_OF(X509) *chain)
+ {
+ EVP_PKEY *ktmp=NULL,*ktmp2;
+ size_t i,j;
+
+ if ((pkey != NULL) && !EVP_PKEY_missing_parameters(pkey)) return 1;
+
+ for (i=0; i<sk_X509_num(chain); i++)
+ {
+ ktmp=X509_get_pubkey(sk_X509_value(chain,i));
+ if (ktmp == NULL)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_get_pubkey_parameters, X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY);
+ return 0;
+ }
+ if (!EVP_PKEY_missing_parameters(ktmp))
+ break;
+ else
+ {
+ EVP_PKEY_free(ktmp);
+ ktmp=NULL;
+ }
+ }
+ if (ktmp == NULL)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_get_pubkey_parameters, X509_R_UNABLE_TO_FIND_PARAMETERS_IN_CHAIN);
+ return 0;
+ }
+
+ /* first, populate the other certs */
+ for (j=i-1; j < i; j--)
+ {
+ ktmp2=X509_get_pubkey(sk_X509_value(chain,j));
+ EVP_PKEY_copy_parameters(ktmp2,ktmp);
+ EVP_PKEY_free(ktmp2);
+ }
+
+ if (pkey != NULL) EVP_PKEY_copy_parameters(pkey,ktmp);
+ EVP_PKEY_free(ktmp);
+ return 1;
+ }
+
+/* Make a delta CRL as the diff between two full CRLs */
+
+X509_CRL *X509_CRL_diff(X509_CRL *base, X509_CRL *newer,
+ EVP_PKEY *skey, const EVP_MD *md, unsigned int flags)
+ {
+ X509_CRL *crl = NULL;
+ int i;
+ size_t j;
+ STACK_OF(X509_REVOKED) *revs = NULL;
+ /* CRLs can't be delta already */
+ if (base->base_crl_number || newer->base_crl_number)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_CRL_diff, X509_R_CRL_ALREADY_DELTA);
+ return NULL;
+ }
+ /* Base and new CRL must have a CRL number */
+ if (!base->crl_number || !newer->crl_number)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_CRL_diff, X509_R_NO_CRL_NUMBER);
+ return NULL;
+ }
+ /* Issuer names must match */
+ if (X509_NAME_cmp(X509_CRL_get_issuer(base),
+ X509_CRL_get_issuer(newer)))
+ {
+ OPENSSL_PUT_ERROR(X509, X509_CRL_diff, X509_R_ISSUER_MISMATCH);
+ return NULL;
+ }
+ /* AKID and IDP must match */
+ if (!crl_extension_match(base, newer, NID_authority_key_identifier))
+ {
+ OPENSSL_PUT_ERROR(X509, X509_CRL_diff, X509_R_AKID_MISMATCH);
+ return NULL;
+ }
+ if (!crl_extension_match(base, newer, NID_issuing_distribution_point))
+ {
+ OPENSSL_PUT_ERROR(X509, X509_CRL_diff, X509_R_IDP_MISMATCH);
+ return NULL;
+ }
+ /* Newer CRL number must exceed full CRL number */
+ if (ASN1_INTEGER_cmp(newer->crl_number, base->crl_number) <= 0)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_CRL_diff, X509_R_NEWER_CRL_NOT_NEWER);
+ return NULL;
+ }
+ /* CRLs must verify */
+ if (skey && (X509_CRL_verify(base, skey) <= 0 ||
+ X509_CRL_verify(newer, skey) <= 0))
+ {
+ OPENSSL_PUT_ERROR(X509, X509_CRL_diff, X509_R_CRL_VERIFY_FAILURE);
+ return NULL;
+ }
+ /* Create new CRL */
+ crl = X509_CRL_new();
+ if (!crl || !X509_CRL_set_version(crl, 1))
+ goto memerr;
+ /* Set issuer name */
+ if (!X509_CRL_set_issuer_name(crl, X509_CRL_get_issuer(newer)))
+ goto memerr;
+
+ if (!X509_CRL_set_lastUpdate(crl, X509_CRL_get_lastUpdate(newer)))
+ goto memerr;
+ if (!X509_CRL_set_nextUpdate(crl, X509_CRL_get_nextUpdate(newer)))
+ goto memerr;
+
+ /* Set base CRL number: must be critical */
+
+ if (!X509_CRL_add1_ext_i2d(crl, NID_delta_crl, base->crl_number, 1, 0))
+ goto memerr;
+
+ /* Copy extensions across from newest CRL to delta: this will set
+ * CRL number to correct value too.
+ */
+
+ for (i = 0; i < X509_CRL_get_ext_count(newer); i++)
+ {
+ X509_EXTENSION *ext;
+ ext = X509_CRL_get_ext(newer, i);
+ if (!X509_CRL_add_ext(crl, ext, -1))
+ goto memerr;
+ }
+
+ /* Go through revoked entries, copying as needed */
+
+ revs = X509_CRL_get_REVOKED(newer);
+
+ for (j = 0; j < sk_X509_REVOKED_num(revs); j++)
+ {
+ X509_REVOKED *rvn, *rvtmp;
+ rvn = sk_X509_REVOKED_value(revs, j);
+ /* Add only if not also in base.
+ * TODO: need something cleverer here for some more complex
+ * CRLs covering multiple CAs.
+ */
+ if (!X509_CRL_get0_by_serial(base, &rvtmp, rvn->serialNumber))
+ {
+ rvtmp = X509_REVOKED_dup(rvn);
+ if (!rvtmp)
+ goto memerr;
+ if (!X509_CRL_add0_revoked(crl, rvtmp))
+ {
+ X509_REVOKED_free(rvtmp);
+ goto memerr;
+ }
+ }
+ }
+ /* TODO: optionally prune deleted entries */
+
+ if (skey && md && !X509_CRL_sign(crl, skey, md))
+ goto memerr;
+
+ return crl;
+
+ memerr:
+ OPENSSL_PUT_ERROR(X509, X509_CRL_diff, ERR_R_MALLOC_FAILURE);
+ if (crl)
+ X509_CRL_free(crl);
+ return NULL;
+ }
+
+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);
+ }
+
+int X509_STORE_CTX_set_ex_data(X509_STORE_CTX *ctx, int idx, void *data)
+ {
+ return CRYPTO_set_ex_data(&ctx->ex_data,idx,data);
+ }
+
+void *X509_STORE_CTX_get_ex_data(X509_STORE_CTX *ctx, int idx)
+ {
+ return CRYPTO_get_ex_data(&ctx->ex_data,idx);
+ }
+
+int X509_STORE_CTX_get_error(X509_STORE_CTX *ctx)
+ {
+ return ctx->error;
+ }
+
+void X509_STORE_CTX_set_error(X509_STORE_CTX *ctx, int err)
+ {
+ ctx->error=err;
+ }
+
+int X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx)
+ {
+ return ctx->error_depth;
+ }
+
+X509 *X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx)
+ {
+ return ctx->current_cert;
+ }
+
+STACK_OF(X509) *X509_STORE_CTX_get_chain(X509_STORE_CTX *ctx)
+ {
+ return ctx->chain;
+ }
+
+STACK_OF(X509) *X509_STORE_CTX_get1_chain(X509_STORE_CTX *ctx)
+ {
+ if (!ctx->chain)
+ return NULL;
+ return X509_chain_up_ref(ctx->chain);
+ }
+
+X509 *X509_STORE_CTX_get0_current_issuer(X509_STORE_CTX *ctx)
+ {
+ return ctx->current_issuer;
+ }
+
+X509_CRL *X509_STORE_CTX_get0_current_crl(X509_STORE_CTX *ctx)
+ {
+ return ctx->current_crl;
+ }
+
+X509_STORE_CTX *X509_STORE_CTX_get0_parent_ctx(X509_STORE_CTX *ctx)
+ {
+ return ctx->parent;
+ }
+
+void X509_STORE_CTX_set_cert(X509_STORE_CTX *ctx, X509 *x)
+ {
+ ctx->cert=x;
+ }
+
+void X509_STORE_CTX_set_chain(X509_STORE_CTX *ctx, STACK_OF(X509) *sk)
+ {
+ ctx->untrusted=sk;
+ }
+
+void X509_STORE_CTX_set0_crls(X509_STORE_CTX *ctx, STACK_OF(X509_CRL) *sk)
+ {
+ ctx->crls=sk;
+ }
+
+int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose)
+ {
+ return X509_STORE_CTX_purpose_inherit(ctx, 0, purpose, 0);
+ }
+
+int X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust)
+ {
+ return X509_STORE_CTX_purpose_inherit(ctx, 0, 0, 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)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_STORE_CTX_purpose_inherit, 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)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_STORE_CTX_purpose_inherit, 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)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_STORE_CTX_purpose_inherit, 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;
+}
+
+X509_STORE_CTX *X509_STORE_CTX_new(void)
+{
+ X509_STORE_CTX *ctx;
+ ctx = (X509_STORE_CTX *)OPENSSL_malloc(sizeof(X509_STORE_CTX));
+ if (!ctx)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_STORE_CTX_new, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ memset(ctx, 0, sizeof(X509_STORE_CTX));
+ return ctx;
+}
+
+void X509_STORE_CTX_free(X509_STORE_CTX *ctx)
+{
+ X509_STORE_CTX_cleanup(ctx);
+ OPENSSL_free(ctx);
+}
+
+int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509,
+ STACK_OF(X509) *chain)
+ {
+ int ret = 1;
+ int ex_data_allocated = 0;
+
+ memset(ctx, 0, sizeof(X509_STORE_CTX));
+ ctx->ctx=store;
+ ctx->cert=x509;
+ ctx->untrusted=chain;
+
+ if(!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx,
+ &ctx->ex_data))
+ {
+ goto err;
+ }
+ ex_data_allocated = 1;
+
+ ctx->param = X509_VERIFY_PARAM_new();
+ if (!ctx->param)
+ goto err;
+
+ /* Inherit callbacks and flags from X509_STORE if not set
+ * use defaults. */
+
+ if (store)
+ ret = X509_VERIFY_PARAM_inherit(ctx->param, store->param);
+ else
+ ctx->param->inh_flags |= X509_VP_FLAG_DEFAULT|X509_VP_FLAG_ONCE;
+
+ if (store)
+ {
+ ctx->verify_cb = store->verify_cb;
+ ctx->cleanup = store->cleanup;
+ }
+ else
+ ctx->cleanup = 0;
+
+ if (ret)
+ ret = X509_VERIFY_PARAM_inherit(ctx->param,
+ X509_VERIFY_PARAM_lookup("default"));
+
+ if (ret == 0)
+ goto err;
+
+ if (store && store->check_issued)
+ ctx->check_issued = store->check_issued;
+ else
+ ctx->check_issued = check_issued;
+
+ if (store && store->get_issuer)
+ ctx->get_issuer = store->get_issuer;
+ else
+ ctx->get_issuer = X509_STORE_CTX_get1_issuer;
+
+ if (store && store->verify_cb)
+ ctx->verify_cb = store->verify_cb;
+ else
+ ctx->verify_cb = null_callback;
+
+ if (store && store->verify)
+ ctx->verify = store->verify;
+ else
+ ctx->verify = internal_verify;
+
+ 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;
+
+ if (store && store->lookup_certs)
+ ctx->lookup_certs = store->lookup_certs;
+ else
+ ctx->lookup_certs = X509_STORE_get1_certs;
+
+ if (store && store->lookup_crls)
+ ctx->lookup_crls = store->lookup_crls;
+ else
+ ctx->lookup_crls = X509_STORE_get1_crls;
+
+ ctx->check_policy = check_policy;
+
+ return 1;
+
+err:
+ if (ex_data_allocated)
+ {
+ CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx, &ctx->ex_data);
+ }
+ if (ctx->param != NULL)
+ {
+ X509_VERIFY_PARAM_free(ctx->param);
+ }
+
+ memset(ctx, 0, sizeof(X509_STORE_CTX));
+ OPENSSL_PUT_ERROR(X509, X509_STORE_CTX_init, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+/* 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) *sk)
+{
+ ctx->other_ctx = sk;
+ ctx->get_issuer = get_issuer_sk;
+}
+
+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->tree != NULL)
+ {
+ X509_policy_tree_free(ctx->tree);
+ ctx->tree=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));
+ }
+
+void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth)
+ {
+ X509_VERIFY_PARAM_set_depth(ctx->param, depth);
+ }
+
+void X509_STORE_CTX_set_flags(X509_STORE_CTX *ctx, unsigned long flags)
+ {
+ X509_VERIFY_PARAM_set_flags(ctx->param, 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);
+ }
+
+void X509_STORE_CTX_set_verify_cb(X509_STORE_CTX *ctx,
+ int (*verify_cb)(int, X509_STORE_CTX *))
+ {
+ ctx->verify_cb=verify_cb;
+ }
+
+X509_POLICY_TREE *X509_STORE_CTX_get0_policy_tree(X509_STORE_CTX *ctx)
+ {
+ return ctx->tree;
+ }
+
+int X509_STORE_CTX_get_explicit_policy(X509_STORE_CTX *ctx)
+ {
+ return ctx->explicit_policy;
+ }
+
+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);
+ }
+
+X509_VERIFY_PARAM *X509_STORE_CTX_get0_param(X509_STORE_CTX *ctx)
+ {
+ return ctx->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;
+ }
+
+IMPLEMENT_ASN1_SET_OF(X509)
+IMPLEMENT_ASN1_SET_OF(X509_ATTRIBUTE)
diff --git a/src/crypto/x509/x509_vpm.c b/src/crypto/x509/x509_vpm.c
new file mode 100644
index 0000000..3daaf61
--- /dev/null
+++ b/src/crypto/x509/x509_vpm.c
@@ -0,0 +1,588 @@
+/* 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 <string.h>
+
+#include <openssl/buf.h>
+#include <openssl/lhash.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+
+#include "vpm_int.h"
+
+
+/* X509_VERIFY_PARAM functions */
+
+static void x509_verify_param_zero(X509_VERIFY_PARAM *param)
+ {
+ X509_VERIFY_PARAM_ID *paramid;
+ if (!param)
+ return;
+ 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;
+ if (param->policies)
+ {
+ sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free);
+ param->policies = NULL;
+ }
+ paramid = param->id;
+ if (paramid->host)
+ {
+ OPENSSL_free(paramid->host);
+ paramid->host = NULL;
+ paramid->hostlen = 0;
+ }
+ if (paramid->email)
+ {
+ OPENSSL_free(paramid->email);
+ paramid->email = NULL;
+ paramid->emaillen = 0;
+ }
+ if (paramid->ip)
+ {
+ OPENSSL_free(paramid->ip);
+ paramid->ip = NULL;
+ paramid->iplen = 0;
+ }
+
+ }
+
+X509_VERIFY_PARAM *X509_VERIFY_PARAM_new(void)
+ {
+ X509_VERIFY_PARAM *param;
+ X509_VERIFY_PARAM_ID *paramid;
+ param = OPENSSL_malloc(sizeof(X509_VERIFY_PARAM));
+ if (!param)
+ return NULL;
+ paramid = OPENSSL_malloc(sizeof(X509_VERIFY_PARAM_ID));
+ if (!paramid)
+ {
+ OPENSSL_free(param);
+ return NULL;
+ }
+ memset(param, 0, sizeof(X509_VERIFY_PARAM));
+ memset(paramid, 0, sizeof(X509_VERIFY_PARAM_ID));
+ param->id = paramid;
+ x509_verify_param_zero(param);
+ return param;
+ }
+
+void X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *param)
+ {
+ x509_verify_param_zero(param);
+ OPENSSL_free(param->id);
+ OPENSSL_free(param);
+ }
+
+/* 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))))
+
+/* As above but for ID fields */
+
+#define test_x509_verify_param_copy_id(idf, def) \
+ test_x509_verify_param_copy(id->idf, 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;
+ X509_VERIFY_PARAM_ID *id;
+ if (!src)
+ return 1;
+ id = src->id;
+ 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;
+ }
+
+ if (test_x509_verify_param_copy_id(host, NULL))
+ {
+ if (!X509_VERIFY_PARAM_set1_host(dest, id->host, id->hostlen))
+ return 0;
+ dest->id->hostflags = id->hostflags;
+ }
+
+ if (test_x509_verify_param_copy_id(email, NULL))
+ {
+ if (!X509_VERIFY_PARAM_set1_email(dest, id->email, id->emaillen))
+ return 0;
+ }
+
+ if (test_x509_verify_param_copy_id(ip, NULL))
+ {
+ if (!X509_VERIFY_PARAM_set1_ip(dest, id->ip, id->iplen))
+ return 0;
+ }
+
+ return 1;
+ }
+
+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;
+ }
+
+static int int_x509_param_set1(unsigned char **pdest, size_t *pdestlen,
+ const unsigned char *src, size_t srclen)
+ {
+ void *tmp;
+ if (src)
+ {
+ if (srclen == 0)
+ {
+ tmp = BUF_strdup((char *)src);
+ srclen = strlen((char *)src);
+ }
+ else
+ tmp = BUF_memdup(src, srclen);
+ if (!tmp)
+ return 0;
+ }
+ else
+ {
+ tmp = NULL;
+ srclen = 0;
+ }
+ if (*pdest)
+ OPENSSL_free(*pdest);
+ *pdest = tmp;
+ if (pdestlen)
+ *pdestlen = srclen;
+ return 1;
+ }
+
+int X509_VERIFY_PARAM_set1_name(X509_VERIFY_PARAM *param, const char *name)
+ {
+ if (param->name)
+ OPENSSL_free(param->name);
+ param->name = BUF_strdup(name);
+ if (param->name)
+ return 1;
+ return 0;
+ }
+
+int X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM *param, unsigned long flags)
+ {
+ param->flags |= flags;
+ if (flags & X509_V_FLAG_POLICY_MASK)
+ param->flags |= X509_V_FLAG_POLICY_CHECK;
+ return 1;
+ }
+
+int X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM *param, unsigned long flags)
+ {
+ param->flags &= ~flags;
+ return 1;
+ }
+
+unsigned long X509_VERIFY_PARAM_get_flags(X509_VERIFY_PARAM *param)
+ {
+ return param->flags;
+ }
+
+int X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM *param, int purpose)
+ {
+ return X509_PURPOSE_set(&param->purpose, purpose);
+ }
+
+int X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM *param, int trust)
+ {
+ return X509_TRUST_set(&param->trust, trust);
+ }
+
+void X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM *param, int depth)
+ {
+ param->depth = depth;
+ }
+
+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;
+ }
+
+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;
+ }
+
+int X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param,
+ STACK_OF(ASN1_OBJECT) *policies)
+ {
+ size_t 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;
+ }
+ }
+ param->flags |= X509_V_FLAG_POLICY_CHECK;
+ return 1;
+ }
+
+int X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param,
+ const unsigned char *name, size_t namelen)
+ {
+ return int_x509_param_set1(&param->id->host, &param->id->hostlen,
+ name, namelen);
+ }
+
+void X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param,
+ unsigned int flags)
+ {
+ param->id->hostflags = flags;
+ }
+
+int X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param,
+ const unsigned char *email, size_t emaillen)
+ {
+ return int_x509_param_set1(&param->id->email, &param->id->emaillen,
+ email, emaillen);
+ }
+
+int X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param,
+ const unsigned char *ip, size_t iplen)
+ {
+ if (iplen != 0 && iplen != 4 && iplen != 16)
+ return 0;
+ return int_x509_param_set1(&param->id->ip, &param->id->iplen, ip, iplen);
+ }
+
+int X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM *param, const char *ipasc)
+ {
+ unsigned char ipout[16];
+ int iplen;
+ iplen = a2i_ipadd(ipout, ipasc);
+ if (iplen == 0)
+ return 0;
+ return X509_VERIFY_PARAM_set1_ip(param, ipout, (size_t)iplen);
+ }
+
+int X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM *param)
+ {
+ return param->depth;
+ }
+
+const char *X509_VERIFY_PARAM_get0_name(const X509_VERIFY_PARAM *param)
+ {
+ return param->name;
+ }
+
+static const X509_VERIFY_PARAM_ID _empty_id = {NULL, 0, 0U, NULL, 0, NULL, 0};
+
+#define vpm_empty_id (X509_VERIFY_PARAM_ID *)&_empty_id
+
+/* Default verify parameters: these are used for various
+ * applications and can be overridden by the user specified table.
+ * NB: the 'name' field *must* be in alphabetical order because it
+ * will be searched using OBJ_search.
+ */
+
+static const X509_VERIFY_PARAM default_table[] = {
+ {
+ (char *) "default", /* X509 default parameters */
+ 0, /* Check time */
+ 0, /* internal flags */
+ 0, /* flags */
+ 0, /* purpose */
+ 0, /* trust */
+ 100, /* depth */
+ NULL, /* policies */
+ vpm_empty_id
+ },
+ {
+ (char *) "pkcs7", /* S/MIME sign parameters */
+ 0, /* Check time */
+ 0, /* internal flags */
+ 0, /* flags */
+ X509_PURPOSE_SMIME_SIGN, /* purpose */
+ X509_TRUST_EMAIL, /* trust */
+ -1, /* depth */
+ NULL, /* policies */
+ vpm_empty_id
+ },
+ {
+ (char *) "smime_sign", /* S/MIME sign parameters */
+ 0, /* Check time */
+ 0, /* internal flags */
+ 0, /* flags */
+ X509_PURPOSE_SMIME_SIGN, /* purpose */
+ X509_TRUST_EMAIL, /* trust */
+ -1, /* depth */
+ NULL, /* policies */
+ vpm_empty_id
+ },
+ {
+ (char *) "ssl_client", /* SSL/TLS client parameters */
+ 0, /* Check time */
+ 0, /* internal flags */
+ 0, /* flags */
+ X509_PURPOSE_SSL_CLIENT, /* purpose */
+ X509_TRUST_SSL_CLIENT, /* trust */
+ -1, /* depth */
+ NULL, /* policies */
+ vpm_empty_id
+ },
+ {
+ (char *) "ssl_server", /* SSL/TLS server parameters */
+ 0, /* Check time */
+ 0, /* internal flags */
+ 0, /* flags */
+ X509_PURPOSE_SSL_SERVER, /* purpose */
+ X509_TRUST_SSL_SERVER, /* trust */
+ -1, /* depth */
+ NULL, /* policies */
+ vpm_empty_id
+ }};
+
+static STACK_OF(X509_VERIFY_PARAM) *param_table = NULL;
+
+static int param_cmp(const X509_VERIFY_PARAM **a,
+ const X509_VERIFY_PARAM **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 (sk_X509_VERIFY_PARAM_find(param_table, &idx, param))
+ {
+ 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;
+ }
+
+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;
+ }
+
+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);
+ }
+
+const X509_VERIFY_PARAM *X509_VERIFY_PARAM_lookup(const char *name)
+ {
+ X509_VERIFY_PARAM pm;
+ unsigned i, limit;
+
+ pm.name = (char *)name;
+ if (param_table)
+ {
+ size_t idx;
+ if (sk_X509_VERIFY_PARAM_find(param_table, &idx, &pm))
+ 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;
+ }
+
+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;
+ }
diff --git a/src/crypto/x509/x509cset.c b/src/crypto/x509/x509cset.c
new file mode 100644
index 0000000..b526c69
--- /dev/null
+++ b/src/crypto/x509/x509cset.c
@@ -0,0 +1,165 @@
+/* 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 <openssl/asn1.h>
+#include <openssl/evp.h>
+#include <openssl/obj.h>
+#include <openssl/x509.h>
+
+
+int X509_CRL_set_version(X509_CRL *x, long version)
+ {
+ if (x == NULL) return(0);
+ if (x->crl->version == NULL)
+ {
+ if ((x->crl->version=M_ASN1_INTEGER_new()) == NULL)
+ return(0);
+ }
+ return(ASN1_INTEGER_set(x->crl->version,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));
+ }
+
+
+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=M_ASN1_TIME_dup(tm);
+ if (in != NULL)
+ {
+ M_ASN1_TIME_free(x->crl->lastUpdate);
+ x->crl->lastUpdate=in;
+ }
+ }
+ return(in != NULL);
+ }
+
+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=M_ASN1_TIME_dup(tm);
+ if (in != NULL)
+ {
+ M_ASN1_TIME_free(x->crl->nextUpdate);
+ x->crl->nextUpdate=in;
+ }
+ }
+ return(in != NULL);
+ }
+
+int X509_CRL_sort(X509_CRL *c)
+ {
+ size_t 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;
+ }
+
+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=M_ASN1_TIME_dup(tm);
+ if (in != NULL)
+ {
+ M_ASN1_TIME_free(x->revocationDate);
+ x->revocationDate=in;
+ }
+ }
+ return(in != NULL);
+ }
+
+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=M_ASN1_INTEGER_dup(serial);
+ if (in != NULL)
+ {
+ M_ASN1_INTEGER_free(x->serialNumber);
+ x->serialNumber=in;
+ }
+ }
+ return(in != NULL);
+ }
diff --git a/src/crypto/x509/x509name.c b/src/crypto/x509/x509name.c
new file mode 100644
index 0000000..042d18b
--- /dev/null
+++ b/src/crypto/x509/x509name.c
@@ -0,0 +1,381 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <string.h>
+
+#include <openssl/asn1.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/obj.h>
+#include <openssl/stack.h>
+#include <openssl/x509.h>
+
+
+int X509_NAME_get_text_by_NID(X509_NAME *name, int nid, char *buf, int len)
+ {
+ const ASN1_OBJECT *obj;
+
+ obj=OBJ_nid2obj(nid);
+ if (obj == NULL) return(-1);
+ return(X509_NAME_get_text_by_OBJ(name,obj,buf,len));
+ }
+
+int X509_NAME_get_text_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj, char *buf,
+ int len)
+ {
+ int i;
+ ASN1_STRING *data;
+
+ i=X509_NAME_get_index_by_OBJ(name,obj,-1);
+ if (i < 0) return(-1);
+ data=X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name,i));
+ i=(data->length > (len-1))?(len-1):data->length;
+ if (buf == NULL) return(data->length);
+ memcpy(buf,data->data,i);
+ buf[i]='\0';
+ return(i);
+ }
+
+int X509_NAME_entry_count(X509_NAME *name)
+ {
+ if (name == NULL) return(0);
+ return(sk_X509_NAME_ENTRY_num(name->entries));
+ }
+
+int X509_NAME_get_index_by_NID(X509_NAME *name, int nid, int lastpos)
+ {
+ const ASN1_OBJECT *obj;
+
+ obj=OBJ_nid2obj(nid);
+ if (obj == NULL) return(-2);
+ return(X509_NAME_get_index_by_OBJ(name,obj,lastpos));
+ }
+
+/* NOTE: you should be passsing -1, not 0 as lastpos */
+int X509_NAME_get_index_by_OBJ(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);
+ }
+
+X509_NAME_ENTRY *X509_NAME_get_entry(X509_NAME *name, int loc)
+ {
+ if(name == NULL || loc < 0 || sk_X509_NAME_ENTRY_num(name->entries) <= (size_t) loc)
+ return(NULL);
+ else
+ return(sk_X509_NAME_ENTRY_value(name->entries,loc));
+ }
+
+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 || loc < 0 || sk_X509_NAME_ENTRY_num(name->entries) <= (size_t) loc)
+ 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);
+ }
+
+int X509_NAME_add_entry_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, int type,
+ 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;
+}
+
+int X509_NAME_add_entry_by_NID(X509_NAME *name, int nid, int type,
+ 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;
+}
+
+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;
+}
+
+/* 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, 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;
+
+ name->modified=1;
+
+ if (set == -1)
+ {
+ if (loc == 0)
+ {
+ set=0;
+ inc=1;
+ }
+ else
+ {
+ set=sk_X509_NAME_ENTRY_value(sk,loc-1)->set;
+ inc=0;
+ }
+ }
+ 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;
+ inc=(set == 0)?1:0;
+ }
+
+ if ((new_name=X509_NAME_ENTRY_dup(ne)) == NULL)
+ goto err;
+ new_name->set=set;
+ if (!sk_X509_NAME_ENTRY_insert(sk,new_name,loc))
+ {
+ OPENSSL_PUT_ERROR(X509, X509_NAME_add_entry, 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-1)->set+=1;
+ }
+ return(1);
+err:
+ if (new_name != NULL)
+ X509_NAME_ENTRY_free(new_name);
+ return(0);
+ }
+
+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)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_NAME_ENTRY_create_by_txt, X509_R_INVALID_FIELD_NAME);
+ ERR_add_error_data(2, "name=", field);
+ return(NULL);
+ }
+ nentry = X509_NAME_ENTRY_create_by_OBJ(ne,obj,type,bytes,len);
+ ASN1_OBJECT_free(obj);
+ return nentry;
+ }
+
+X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_NID(X509_NAME_ENTRY **ne, int nid,
+ int type, unsigned char *bytes, int len)
+ {
+ const ASN1_OBJECT *obj;
+ X509_NAME_ENTRY *nentry;
+
+ obj=OBJ_nid2obj(nid);
+ if (obj == NULL)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_NAME_ENTRY_create_by_NID, X509_R_UNKNOWN_NID);
+ return(NULL);
+ }
+ nentry = X509_NAME_ENTRY_create_by_OBJ(ne,obj,type,bytes,len);
+ /* TODO(fork): remove this? */
+ /* ASN1_OBJECT_free(obj); */
+ return nentry;
+ }
+
+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);
+ }
+
+int X509_NAME_ENTRY_set_object(X509_NAME_ENTRY *ne, const ASN1_OBJECT *obj)
+ {
+ if ((ne == NULL) || (obj == NULL))
+ {
+ OPENSSL_PUT_ERROR(X509, X509_NAME_ENTRY_set_object, ERR_R_PASSED_NULL_PARAMETER);
+ return(0);
+ }
+ ASN1_OBJECT_free(ne->object);
+ ne->object=OBJ_dup(obj);
+ return((ne->object == NULL)?0:1);
+ }
+
+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);
+ }
+
+ASN1_OBJECT *X509_NAME_ENTRY_get_object(X509_NAME_ENTRY *ne)
+ {
+ if (ne == NULL) return(NULL);
+ return(ne->object);
+ }
+
+ASN1_STRING *X509_NAME_ENTRY_get_data(X509_NAME_ENTRY *ne)
+ {
+ if (ne == NULL) return(NULL);
+ return(ne->value);
+ }
+
diff --git a/src/crypto/x509/x509rset.c b/src/crypto/x509/x509rset.c
new file mode 100644
index 0000000..dbab555
--- /dev/null
+++ b/src/crypto/x509/x509rset.c
@@ -0,0 +1,80 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/asn1.h>
+#include <openssl/evp.h>
+#include <openssl/obj.h>
+#include <openssl/x509.h>
+
+
+int X509_REQ_set_version(X509_REQ *x, long version)
+ {
+ if (x == NULL) return(0);
+ return(ASN1_INTEGER_set(x->req_info->version,version));
+ }
+
+int X509_REQ_set_subject_name(X509_REQ *x, X509_NAME *name)
+ {
+ if ((x == NULL) || (x->req_info == NULL)) return(0);
+ return(X509_NAME_set(&x->req_info->subject,name));
+ }
+
+int X509_REQ_set_pubkey(X509_REQ *x, EVP_PKEY *pkey)
+ {
+ if ((x == NULL) || (x->req_info == NULL)) return(0);
+ return(X509_PUBKEY_set(&x->req_info->pubkey,pkey));
+ }
+
diff --git a/src/crypto/x509/x509spki.c b/src/crypto/x509/x509spki.c
new file mode 100644
index 0000000..9bab957
--- /dev/null
+++ b/src/crypto/x509/x509spki.c
@@ -0,0 +1,135 @@
+/* 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 <string.h>
+
+#include <openssl/base64.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/x509.h>
+
+
+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));
+}
+
+EVP_PKEY *NETSCAPE_SPKI_get_pubkey(NETSCAPE_SPKI *x)
+{
+ if ((x == NULL) || (x->spkac == NULL))
+ return(NULL);
+ return(X509_PUBKEY_get(x->spkac->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;
+ size_t spki_len;
+ NETSCAPE_SPKI *spki;
+ if (len <= 0)
+ len = strlen(str);
+ if (!EVP_DecodedLength(&spki_len, len)) {
+ OPENSSL_PUT_ERROR(X509, NETSCAPE_SPKI_b64_decode, X509_R_BASE64_DECODE_ERROR);
+ return NULL;
+ }
+ if (!(spki_der = OPENSSL_malloc(spki_len))) {
+ OPENSSL_PUT_ERROR(X509, NETSCAPE_SPKI_b64_decode, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ if (!EVP_DecodeBase64(spki_der, &spki_len, spki_len, (const uint8_t *)str, len)) {
+ OPENSSL_PUT_ERROR(X509, NETSCAPE_SPKI_b64_decode, X509_R_BASE64_DECODE_ERROR);
+ OPENSSL_free(spki_der);
+ return NULL;
+ }
+ p = spki_der;
+ spki = d2i_NETSCAPE_SPKI(NULL, &p, spki_len);
+ OPENSSL_free(spki_der);
+ return spki;
+}
+
+/* Generate a base64 encoded string from an SPKI */
+
+char * NETSCAPE_SPKI_b64_encode(NETSCAPE_SPKI *spki)
+{
+ unsigned char *der_spki, *p;
+ char *b64_str;
+ size_t b64_len;
+ int der_len;
+ der_len = i2d_NETSCAPE_SPKI(spki, NULL);
+ if (!EVP_EncodedLength(&b64_len, der_len))
+ {
+ OPENSSL_PUT_ERROR(X509, NETSCAPE_SPKI_b64_encode, ERR_R_OVERFLOW);
+ return NULL;
+ }
+ der_spki = OPENSSL_malloc(der_len);
+ if (der_spki == NULL) {
+ OPENSSL_PUT_ERROR(X509, NETSCAPE_SPKI_b64_encode, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ b64_str = OPENSSL_malloc(b64_len);
+ if (b64_str == NULL) {
+ OPENSSL_free(der_spki);
+ OPENSSL_PUT_ERROR(X509, NETSCAPE_SPKI_b64_encode, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ p = der_spki;
+ i2d_NETSCAPE_SPKI(spki, &p);
+ EVP_EncodeBlock((unsigned char *)b64_str, der_spki, der_len);
+ OPENSSL_free(der_spki);
+ return b64_str;
+}
diff --git a/src/crypto/x509/x509type.c b/src/crypto/x509/x509type.c
new file mode 100644
index 0000000..e7c7935
--- /dev/null
+++ b/src/crypto/x509/x509type.c
@@ -0,0 +1,128 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/evp.h>
+#include <openssl/obj.h>
+#include <openssl/x509.h>
+
+
+int X509_certificate_type(X509 *x, EVP_PKEY *pkey)
+ {
+ EVP_PKEY *pk;
+ int ret=0,i;
+
+ if (x == NULL) return(0);
+
+ if (pkey == NULL)
+ pk=X509_get_pubkey(x);
+ else
+ pk=pkey;
+
+ if (pk == NULL) return(0);
+
+ switch (pk->type)
+ {
+ case EVP_PKEY_RSA:
+ ret=EVP_PK_RSA|EVP_PKT_SIGN;
+/* if (!sign only extension) */
+ ret|=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_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;
+ }
+ }
+
+ if (EVP_PKEY_size(pk) <= 1024/8)/* /8 because it's 1024 bits we look
+ for, not bytes */
+ ret|=EVP_PKT_EXP;
+ if(pkey==NULL) EVP_PKEY_free(pk);
+ return(ret);
+ }
+
diff --git a/src/crypto/x509/x_algor.c b/src/crypto/x509/x_algor.c
new file mode 100644
index 0000000..ae694e3
--- /dev/null
+++ b/src/crypto/x509/x_algor.c
@@ -0,0 +1,154 @@
+/* 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 <openssl/x509.h>
+
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/digest.h>
+#include <openssl/obj.h>
+
+
+ASN1_SEQUENCE(X509_ALGOR) = {
+ ASN1_SIMPLE(X509_ALGOR, algorithm, ASN1_OBJECT),
+ ASN1_OPT(X509_ALGOR, parameter, ASN1_ANY)
+} ASN1_SEQUENCE_END(X509_ALGOR)
+
+ASN1_ITEM_TEMPLATE(X509_ALGORS) =
+ ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, algorithms, X509_ALGOR)
+ASN1_ITEM_TEMPLATE_END(X509_ALGORS)
+
+IMPLEMENT_ASN1_FUNCTIONS(X509_ALGOR)
+IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(X509_ALGORS, X509_ALGORS, X509_ALGORS)
+IMPLEMENT_ASN1_DUP_FUNCTION(X509_ALGOR)
+
+IMPLEMENT_ASN1_SET_OF(X509_ALGOR)
+
+int X509_ALGOR_set0(X509_ALGOR *alg, const 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 = (ASN1_OBJECT*) 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(ASN1_OBJECT **paobj, int *pptype, void **ppval,
+ 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;
+
+ if (EVP_MD_flags(md) & EVP_MD_FLAG_DIGALGID_ABSENT)
+ param_type = V_ASN1_UNDEF;
+ else
+ param_type = V_ASN1_NULL;
+
+ X509_ALGOR_set0(alg, OBJ_nid2obj(EVP_MD_type(md)), param_type, NULL);
+
+ }
+
+/* X509_ALGOR_cmp returns 0 if |a| and |b| are equal and non-zero otherwise. */
+int X509_ALGOR_cmp(const X509_ALGOR *a, const X509_ALGOR *b)
+ {
+ int rv;
+ rv = OBJ_cmp(a->algorithm, b->algorithm);
+ if (rv)
+ return rv;
+ if (!a->parameter && !b->parameter)
+ return 0;
+ return ASN1_TYPE_cmp(a->parameter, b->parameter);
+ }
diff --git a/src/crypto/x509/x_all.c b/src/crypto/x509/x_all.c
new file mode 100644
index 0000000..785fd1e
--- /dev/null
+++ b/src/crypto/x509/x_all.c
@@ -0,0 +1,544 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/asn1.h>
+#include <openssl/buf.h>
+#include <openssl/digest.h>
+#include <openssl/dsa.h>
+#include <openssl/evp.h>
+#include <openssl/rsa.h>
+#include <openssl/stack.h>
+#include <openssl/x509.h>
+
+
+extern const ASN1_ITEM RSAPrivateKey_it;
+extern const ASN1_ITEM RSAPublicKey_it;
+
+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(ASN1_ITEM_rptr(X509_CINF),a->sig_alg,
+ a->signature,a->cert_info,r));
+ }
+
+int X509_REQ_verify(X509_REQ *a, EVP_PKEY *r)
+ {
+ return( ASN1_item_verify(ASN1_ITEM_rptr(X509_REQ_INFO),
+ a->sig_alg,a->signature,a->req_info,r));
+ }
+
+int X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md)
+ {
+ x->cert_info->enc.modified = 1;
+ return(ASN1_item_sign(ASN1_ITEM_rptr(X509_CINF), x->cert_info->signature,
+ x->sig_alg, x->signature, x->cert_info,pkey,md));
+ }
+
+int X509_sign_ctx(X509 *x, EVP_MD_CTX *ctx)
+ {
+ x->cert_info->enc.modified = 1;
+ return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_CINF),
+ x->cert_info->signature,
+ x->sig_alg, x->signature, x->cert_info, ctx);
+ }
+
+/* TODO(fork)
+int X509_http_nbio(OCSP_REQ_CTX *rctx, X509 **pcert)
+ {
+ return OCSP_REQ_CTX_nbio_d2i(rctx,
+ (ASN1_VALUE **)pcert, ASN1_ITEM_rptr(X509));
+ }
+*/
+
+int X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md)
+ {
+ return(ASN1_item_sign(ASN1_ITEM_rptr(X509_REQ_INFO),x->sig_alg, NULL,
+ x->signature, x->req_info,pkey,md));
+ }
+
+int X509_REQ_sign_ctx(X509_REQ *x, EVP_MD_CTX *ctx)
+ {
+ return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_REQ_INFO),
+ x->sig_alg, NULL, x->signature, x->req_info, ctx);
+ }
+
+int X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md)
+ {
+ x->crl->enc.modified = 1;
+ return(ASN1_item_sign(ASN1_ITEM_rptr(X509_CRL_INFO),x->crl->sig_alg,
+ x->sig_alg, x->signature, x->crl,pkey,md));
+ }
+
+int X509_CRL_sign_ctx(X509_CRL *x, EVP_MD_CTX *ctx)
+ {
+ x->crl->enc.modified = 1;
+ return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_CRL_INFO),
+ x->crl->sig_alg, x->sig_alg, x->signature, x->crl, ctx);
+ }
+
+/* TODO(fork)
+int X509_CRL_http_nbio(OCSP_REQ_CTX *rctx, X509_CRL **pcrl)
+ {
+ return OCSP_REQ_CTX_nbio_d2i(rctx,
+ (ASN1_VALUE **)pcrl, ASN1_ITEM_rptr(X509_CRL));
+ }
+*/
+
+int NETSCAPE_SPKI_sign(NETSCAPE_SPKI *x, EVP_PKEY *pkey, const EVP_MD *md)
+ {
+ return(ASN1_item_sign(ASN1_ITEM_rptr(NETSCAPE_SPKAC), x->sig_algor,NULL,
+ x->signature, x->spkac,pkey,md));
+ }
+
+#ifndef OPENSSL_NO_FP_API
+X509 *d2i_X509_fp(FILE *fp, X509 **x509)
+ {
+ return ASN1_item_d2i_fp(ASN1_ITEM_rptr(X509), fp, x509);
+ }
+
+int i2d_X509_fp(FILE *fp, X509 *x509)
+ {
+ return ASN1_item_i2d_fp(ASN1_ITEM_rptr(X509), fp, x509);
+ }
+#endif
+
+X509 *d2i_X509_bio(BIO *bp, X509 **x509)
+ {
+ return ASN1_item_d2i_bio(ASN1_ITEM_rptr(X509), bp, x509);
+ }
+
+int i2d_X509_bio(BIO *bp, X509 *x509)
+ {
+ return ASN1_item_i2d_bio(ASN1_ITEM_rptr(X509), bp, x509);
+ }
+
+#ifndef OPENSSL_NO_FP_API
+X509_CRL *d2i_X509_CRL_fp(FILE *fp, X509_CRL **crl)
+ {
+ return ASN1_item_d2i_fp(ASN1_ITEM_rptr(X509_CRL), fp, crl);
+ }
+
+int i2d_X509_CRL_fp(FILE *fp, X509_CRL *crl)
+ {
+ return ASN1_item_i2d_fp(ASN1_ITEM_rptr(X509_CRL), fp, crl);
+ }
+#endif
+
+X509_CRL *d2i_X509_CRL_bio(BIO *bp, X509_CRL **crl)
+ {
+ return ASN1_item_d2i_bio(ASN1_ITEM_rptr(X509_CRL), bp, crl);
+ }
+
+int i2d_X509_CRL_bio(BIO *bp, X509_CRL *crl)
+ {
+ return ASN1_item_i2d_bio(ASN1_ITEM_rptr(X509_CRL), bp, crl);
+ }
+
+/* TODO(fork) */
+#if 0
+#ifndef OPENSSL_NO_FP_API
+PKCS7 *d2i_PKCS7_fp(FILE *fp, PKCS7 **p7)
+ {
+ return ASN1_item_d2i_fp(ASN1_ITEM_rptr(PKCS7), fp, p7);
+ }
+
+int i2d_PKCS7_fp(FILE *fp, PKCS7 *p7)
+ {
+ return ASN1_item_i2d_fp(ASN1_ITEM_rptr(PKCS7), fp, p7);
+ }
+#endif
+
+PKCS7 *d2i_PKCS7_bio(BIO *bp, PKCS7 **p7)
+ {
+ return ASN1_item_d2i_bio(ASN1_ITEM_rptr(PKCS7), bp, p7);
+ }
+
+int i2d_PKCS7_bio(BIO *bp, PKCS7 *p7)
+ {
+ return ASN1_item_i2d_bio(ASN1_ITEM_rptr(PKCS7), bp, p7);
+ }
+#endif
+
+#ifndef OPENSSL_NO_FP_API
+X509_REQ *d2i_X509_REQ_fp(FILE *fp, X509_REQ **req)
+ {
+ return ASN1_item_d2i_fp(ASN1_ITEM_rptr(X509_REQ), fp, req);
+ }
+
+int i2d_X509_REQ_fp(FILE *fp, X509_REQ *req)
+ {
+ return ASN1_item_i2d_fp(ASN1_ITEM_rptr(X509_REQ), fp, req);
+ }
+#endif
+
+X509_REQ *d2i_X509_REQ_bio(BIO *bp, X509_REQ **req)
+ {
+ return ASN1_item_d2i_bio(ASN1_ITEM_rptr(X509_REQ), bp, req);
+ }
+
+int i2d_X509_REQ_bio(BIO *bp, X509_REQ *req)
+ {
+ return ASN1_item_i2d_bio(ASN1_ITEM_rptr(X509_REQ), bp, req);
+ }
+
+
+#ifndef OPENSSL_NO_FP_API
+RSA *d2i_RSAPrivateKey_fp(FILE *fp, RSA **rsa)
+ {
+ return ASN1_item_d2i_fp(ASN1_ITEM_rptr(RSAPrivateKey), fp, rsa);
+ }
+
+int i2d_RSAPrivateKey_fp(FILE *fp, RSA *rsa)
+ {
+ return ASN1_item_i2d_fp(ASN1_ITEM_rptr(RSAPrivateKey), fp, rsa);
+ }
+
+RSA *d2i_RSAPublicKey_fp(FILE *fp, RSA **rsa)
+ {
+ return ASN1_item_d2i_fp(ASN1_ITEM_rptr(RSAPublicKey), fp, rsa);
+ }
+
+RSA *d2i_RSA_PUBKEY_fp(FILE *fp, RSA **rsa)
+ {
+ return ASN1_d2i_fp((void *(*)(void))
+ RSA_new,(D2I_OF(void))d2i_RSA_PUBKEY, fp,
+ (void **)rsa);
+ }
+
+int i2d_RSAPublicKey_fp(FILE *fp, RSA *rsa)
+ {
+ return ASN1_item_i2d_fp(ASN1_ITEM_rptr(RSAPublicKey), fp, rsa);
+ }
+
+int i2d_RSA_PUBKEY_fp(FILE *fp, RSA *rsa)
+ {
+ return ASN1_i2d_fp((I2D_OF_const(void))i2d_RSA_PUBKEY,fp,rsa);
+ }
+#endif
+
+RSA *d2i_RSAPrivateKey_bio(BIO *bp, RSA **rsa)
+ {
+ return ASN1_item_d2i_bio(ASN1_ITEM_rptr(RSAPrivateKey), bp, rsa);
+ }
+
+int i2d_RSAPrivateKey_bio(BIO *bp, RSA *rsa)
+ {
+ return ASN1_item_i2d_bio(ASN1_ITEM_rptr(RSAPrivateKey), bp, rsa);
+ }
+
+RSA *d2i_RSAPublicKey_bio(BIO *bp, RSA **rsa)
+ {
+ return ASN1_item_d2i_bio(ASN1_ITEM_rptr(RSAPublicKey), bp, rsa);
+ }
+
+
+RSA *d2i_RSA_PUBKEY_bio(BIO *bp, RSA **rsa)
+ {
+ return ASN1_d2i_bio_of(RSA,RSA_new,d2i_RSA_PUBKEY,bp,rsa);
+ }
+
+int i2d_RSAPublicKey_bio(BIO *bp, RSA *rsa)
+ {
+ return ASN1_item_i2d_bio(ASN1_ITEM_rptr(RSAPublicKey), bp, rsa);
+ }
+
+int i2d_RSA_PUBKEY_bio(BIO *bp, RSA *rsa)
+ {
+ return ASN1_i2d_bio_of_const(RSA,i2d_RSA_PUBKEY,bp,rsa);
+ }
+
+#ifndef OPENSSL_NO_DSA
+#ifndef OPENSSL_NO_FP_API
+DSA *d2i_DSAPrivateKey_fp(FILE *fp, DSA **dsa)
+ {
+ return ASN1_d2i_fp_of(DSA,DSA_new,d2i_DSAPrivateKey,fp,dsa);
+ }
+
+int i2d_DSAPrivateKey_fp(FILE *fp, DSA *dsa)
+ {
+ return ASN1_i2d_fp_of_const(DSA,i2d_DSAPrivateKey,fp,dsa);
+ }
+
+DSA *d2i_DSA_PUBKEY_fp(FILE *fp, DSA **dsa)
+ {
+ return ASN1_d2i_fp_of(DSA,DSA_new,d2i_DSA_PUBKEY,fp,dsa);
+ }
+
+int i2d_DSA_PUBKEY_fp(FILE *fp, DSA *dsa)
+ {
+ return ASN1_i2d_fp_of_const(DSA,i2d_DSA_PUBKEY,fp,dsa);
+ }
+#endif
+
+DSA *d2i_DSAPrivateKey_bio(BIO *bp, DSA **dsa)
+ {
+ return ASN1_d2i_bio_of(DSA,DSA_new,d2i_DSAPrivateKey,bp,dsa
+);
+ }
+
+int i2d_DSAPrivateKey_bio(BIO *bp, DSA *dsa)
+ {
+ return ASN1_i2d_bio_of_const(DSA,i2d_DSAPrivateKey,bp,dsa);
+ }
+
+DSA *d2i_DSA_PUBKEY_bio(BIO *bp, DSA **dsa)
+ {
+ return ASN1_d2i_bio_of(DSA,DSA_new,d2i_DSA_PUBKEY,bp,dsa);
+ }
+
+int i2d_DSA_PUBKEY_bio(BIO *bp, DSA *dsa)
+ {
+ return ASN1_i2d_bio_of_const(DSA,i2d_DSA_PUBKEY,bp,dsa);
+ }
+
+#endif
+
+#ifndef OPENSSL_NO_FP_API
+EC_KEY *d2i_EC_PUBKEY_fp(FILE *fp, EC_KEY **eckey)
+ {
+ return ASN1_d2i_fp_of(EC_KEY,EC_KEY_new,d2i_EC_PUBKEY,fp,eckey);
+ }
+
+int i2d_EC_PUBKEY_fp(FILE *fp, EC_KEY *eckey)
+ {
+ return ASN1_i2d_fp_of_const(EC_KEY,i2d_EC_PUBKEY,fp,eckey);
+ }
+
+EC_KEY *d2i_ECPrivateKey_fp(FILE *fp, EC_KEY **eckey)
+ {
+ return ASN1_d2i_fp_of(EC_KEY,EC_KEY_new,d2i_ECPrivateKey,fp,eckey);
+ }
+
+int i2d_ECPrivateKey_fp(FILE *fp, EC_KEY *eckey)
+ {
+ return ASN1_i2d_fp_of_const(EC_KEY,i2d_ECPrivateKey,fp,eckey);
+ }
+#endif
+EC_KEY *d2i_EC_PUBKEY_bio(BIO *bp, EC_KEY **eckey)
+ {
+ return ASN1_d2i_bio_of(EC_KEY,EC_KEY_new,d2i_EC_PUBKEY,bp,eckey);
+ }
+
+int i2d_EC_PUBKEY_bio(BIO *bp, EC_KEY *ecdsa)
+ {
+ return ASN1_i2d_bio_of_const(EC_KEY,i2d_EC_PUBKEY,bp,ecdsa);
+ }
+
+EC_KEY *d2i_ECPrivateKey_bio(BIO *bp, EC_KEY **eckey)
+ {
+ return ASN1_d2i_bio_of(EC_KEY,EC_KEY_new,d2i_ECPrivateKey,bp,eckey);
+ }
+
+int i2d_ECPrivateKey_bio(BIO *bp, EC_KEY *eckey)
+ {
+ return ASN1_i2d_bio_of_const(EC_KEY,i2d_ECPrivateKey,bp,eckey);
+ }
+
+
+int X509_pubkey_digest(const X509 *data, const EVP_MD *type, unsigned char *md,
+ unsigned int *len)
+ {
+ ASN1_BIT_STRING *key;
+ key = X509_get0_pubkey_bitstr(data);
+ if(!key) return 0;
+ return EVP_Digest(key->data, key->length, md, len, type, NULL);
+ }
+
+int X509_digest(const X509 *data, const EVP_MD *type, unsigned char *md,
+ unsigned int *len)
+ {
+ return(ASN1_item_digest(ASN1_ITEM_rptr(X509),type,(char *)data,md,len));
+ }
+
+int X509_CRL_digest(const X509_CRL *data, const EVP_MD *type, unsigned char *md,
+ unsigned int *len)
+ {
+ return(ASN1_item_digest(ASN1_ITEM_rptr(X509_CRL),type,(char *)data,md,len));
+ }
+
+int X509_REQ_digest(const X509_REQ *data, const EVP_MD *type, unsigned char *md,
+ unsigned int *len)
+ {
+ return(ASN1_item_digest(ASN1_ITEM_rptr(X509_REQ),type,(char *)data,md,len));
+ }
+
+int X509_NAME_digest(const X509_NAME *data, const EVP_MD *type, unsigned char *md,
+ unsigned int *len)
+ {
+ return(ASN1_item_digest(ASN1_ITEM_rptr(X509_NAME),type,(char *)data,md,len));
+ }
+
+#if 0 /* TODO(fork): remove */
+int PKCS7_ISSUER_AND_SERIAL_digest(PKCS7_ISSUER_AND_SERIAL *data, const EVP_MD *type,
+ unsigned char *md, unsigned int *len)
+ {
+ return(ASN1_item_digest(ASN1_ITEM_rptr(PKCS7_ISSUER_AND_SERIAL),type,
+ (char *)data,md,len));
+ }
+#endif
+
+#ifndef OPENSSL_NO_FP_API
+X509_SIG *d2i_PKCS8_fp(FILE *fp, X509_SIG **p8)
+ {
+ return ASN1_d2i_fp_of(X509_SIG,X509_SIG_new,d2i_X509_SIG,fp,p8);
+ }
+
+int i2d_PKCS8_fp(FILE *fp, X509_SIG *p8)
+ {
+ return ASN1_i2d_fp_of(X509_SIG,i2d_X509_SIG,fp,p8);
+ }
+#endif
+
+X509_SIG *d2i_PKCS8_bio(BIO *bp, X509_SIG **p8)
+ {
+ return ASN1_d2i_bio_of(X509_SIG,X509_SIG_new,d2i_X509_SIG,bp,p8);
+ }
+
+int i2d_PKCS8_bio(BIO *bp, X509_SIG *p8)
+ {
+ return ASN1_i2d_bio_of(X509_SIG,i2d_X509_SIG,bp,p8);
+ }
+
+#ifndef OPENSSL_NO_FP_API
+PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_fp(FILE *fp,
+ PKCS8_PRIV_KEY_INFO **p8inf)
+ {
+ return ASN1_d2i_fp_of(PKCS8_PRIV_KEY_INFO,PKCS8_PRIV_KEY_INFO_new,
+ d2i_PKCS8_PRIV_KEY_INFO,fp,p8inf);
+ }
+
+int i2d_PKCS8_PRIV_KEY_INFO_fp(FILE *fp, PKCS8_PRIV_KEY_INFO *p8inf)
+ {
+ return ASN1_i2d_fp_of(PKCS8_PRIV_KEY_INFO,i2d_PKCS8_PRIV_KEY_INFO,fp,
+ p8inf);
+ }
+
+int i2d_PKCS8PrivateKeyInfo_fp(FILE *fp, EVP_PKEY *key)
+ {
+ 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;
+ }
+
+int i2d_PrivateKey_fp(FILE *fp, EVP_PKEY *pkey)
+ {
+ return ASN1_i2d_fp_of_const(EVP_PKEY,i2d_PrivateKey,fp,pkey);
+ }
+
+EVP_PKEY *d2i_PrivateKey_fp(FILE *fp, EVP_PKEY **a)
+{
+ return ASN1_d2i_fp_of(EVP_PKEY,EVP_PKEY_new,d2i_AutoPrivateKey,fp,a);
+}
+
+int i2d_PUBKEY_fp(FILE *fp, EVP_PKEY *pkey)
+ {
+ return ASN1_i2d_fp_of_const(EVP_PKEY,i2d_PUBKEY,fp,pkey);
+ }
+
+EVP_PKEY *d2i_PUBKEY_fp(FILE *fp, EVP_PKEY **a)
+{
+ return ASN1_d2i_fp_of(EVP_PKEY,EVP_PKEY_new,d2i_PUBKEY,fp,a);
+}
+
+PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_bio(BIO *bp,
+ PKCS8_PRIV_KEY_INFO **p8inf)
+ {
+ return ASN1_d2i_bio_of(PKCS8_PRIV_KEY_INFO,PKCS8_PRIV_KEY_INFO_new,
+ d2i_PKCS8_PRIV_KEY_INFO,bp,p8inf);
+ }
+
+int i2d_PKCS8_PRIV_KEY_INFO_bio(BIO *bp, PKCS8_PRIV_KEY_INFO *p8inf)
+ {
+ return ASN1_i2d_bio_of(PKCS8_PRIV_KEY_INFO,i2d_PKCS8_PRIV_KEY_INFO,bp,
+ p8inf);
+ }
+
+int i2d_PKCS8PrivateKeyInfo_bio(BIO *bp, EVP_PKEY *key)
+ {
+ 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;
+ }
+#endif
+
+int i2d_PrivateKey_bio(BIO *bp, EVP_PKEY *pkey)
+ {
+ return ASN1_i2d_bio_of_const(EVP_PKEY,i2d_PrivateKey,bp,pkey);
+ }
+
+EVP_PKEY *d2i_PrivateKey_bio(BIO *bp, EVP_PKEY **a)
+ {
+ return ASN1_d2i_bio_of(EVP_PKEY,EVP_PKEY_new,d2i_AutoPrivateKey,bp,a);
+ }
+
+int i2d_PUBKEY_bio(BIO *bp, EVP_PKEY *pkey)
+ {
+ return ASN1_i2d_bio_of_const(EVP_PKEY,i2d_PUBKEY,bp,pkey);
+ }
+
+EVP_PKEY *d2i_PUBKEY_bio(BIO *bp, EVP_PKEY **a)
+ {
+ return ASN1_d2i_bio_of(EVP_PKEY,EVP_PKEY_new,d2i_PUBKEY,bp,a);
+ }
diff --git a/src/crypto/x509/x_attrib.c b/src/crypto/x509/x_attrib.c
new file mode 100644
index 0000000..c460a70
--- /dev/null
+++ b/src/crypto/x509/x_attrib.c
@@ -0,0 +1,117 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/x509.h>
+#include <openssl/obj.h>
+
+
+/* X509_ATTRIBUTE: this has the following form:
+ *
+ * typedef struct x509_attributes_st
+ * {
+ * ASN1_OBJECT *object;
+ * int single;
+ * union {
+ * char *ptr;
+ * STACK_OF(ASN1_TYPE) *set;
+ * ASN1_TYPE *single;
+ * } value;
+ * } X509_ATTRIBUTE;
+ *
+ * this needs some extra thought because the CHOICE type is
+ * merged with the main structure and because the value can
+ * be anything at all we *must* try the SET OF first because
+ * the ASN1_ANY type will swallow anything including the whole
+ * SET OF structure.
+ */
+
+ASN1_CHOICE(X509_ATTRIBUTE_SET) = {
+ ASN1_SET_OF(X509_ATTRIBUTE, value.set, ASN1_ANY),
+ ASN1_SIMPLE(X509_ATTRIBUTE, value.single, ASN1_ANY)
+} ASN1_CHOICE_END_selector(X509_ATTRIBUTE, X509_ATTRIBUTE_SET, single)
+
+ASN1_SEQUENCE(X509_ATTRIBUTE) = {
+ ASN1_SIMPLE(X509_ATTRIBUTE, object, ASN1_OBJECT),
+ /* CHOICE type merged with parent */
+ ASN1_EX_COMBINE(0, 0, X509_ATTRIBUTE_SET)
+} ASN1_SEQUENCE_END(X509_ATTRIBUTE)
+
+IMPLEMENT_ASN1_FUNCTIONS(X509_ATTRIBUTE)
+IMPLEMENT_ASN1_DUP_FUNCTION(X509_ATTRIBUTE)
+
+X509_ATTRIBUTE *X509_ATTRIBUTE_create(int nid, int atrtype, void *value)
+ {
+ X509_ATTRIBUTE *ret=NULL;
+ ASN1_TYPE *val=NULL;
+
+ if ((ret=X509_ATTRIBUTE_new()) == NULL)
+ return(NULL);
+ /* TODO(fork): const correctness. */
+ ret->object=(ASN1_OBJECT*) OBJ_nid2obj(nid);
+ ret->single=0;
+ if ((ret->value.set=sk_ASN1_TYPE_new_null()) == NULL) goto err;
+ if ((val=ASN1_TYPE_new()) == NULL) goto err;
+ if (!sk_ASN1_TYPE_push(ret->value.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/src/crypto/x509/x_crl.c b/src/crypto/x509/x_crl.c
new file mode 100644
index 0000000..bb23b57
--- /dev/null
+++ b/src/crypto/x509/x_crl.c
@@ -0,0 +1,545 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/digest.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/stack.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+
+/* 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);
+ };
+
+static int X509_REVOKED_cmp(const X509_REVOKED **a,
+ const X509_REVOKED **b);
+static void setup_idp(X509_CRL *crl, ISSUING_DIST_POINT *idp);
+
+ASN1_SEQUENCE(X509_REVOKED) = {
+ ASN1_SIMPLE(X509_REVOKED,serialNumber, ASN1_INTEGER),
+ ASN1_SIMPLE(X509_REVOKED,revocationDate, ASN1_TIME),
+ ASN1_SEQUENCE_OF_OPT(X509_REVOKED,extensions, X509_EXTENSION)
+} ASN1_SEQUENCE_END(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 const X509_CRL_METHOD int_crl_meth =
+ {
+ 0,
+ 0,0,
+ def_crl_lookup,
+ 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;
+}
+
+
+ASN1_SEQUENCE_enc(X509_CRL_INFO, enc, crl_inf_cb) = {
+ ASN1_OPT(X509_CRL_INFO, version, ASN1_INTEGER),
+ ASN1_SIMPLE(X509_CRL_INFO, sig_alg, X509_ALGOR),
+ ASN1_SIMPLE(X509_CRL_INFO, issuer, X509_NAME),
+ ASN1_SIMPLE(X509_CRL_INFO, lastUpdate, ASN1_TIME),
+ ASN1_OPT(X509_CRL_INFO, nextUpdate, ASN1_TIME),
+ ASN1_SEQUENCE_OF_OPT(X509_CRL_INFO, revoked, X509_REVOKED),
+ ASN1_EXP_SEQUENCE_OF_OPT(X509_CRL_INFO, extensions, X509_EXTENSION, 0)
+} ASN1_SEQUENCE_END_enc(X509_CRL_INFO, 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)
+ {
+
+ size_t i, k;
+ int 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 (k = 0; k < sk_X509_EXTENSION_num(exts); k++)
+ {
+ ext = sk_X509_EXTENSION_value(exts, k);
+ 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;
+ size_t idx;
+
+ 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, EVP_sha1(), crl->sha1_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 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 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))
+ return 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 1;
+ }
+
+/* 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));
+ }
+
+ASN1_SEQUENCE_ref(X509_CRL, crl_cb, CRYPTO_LOCK_X509_CRL) = {
+ ASN1_SIMPLE(X509_CRL, crl, X509_CRL_INFO),
+ ASN1_SIMPLE(X509_CRL, sig_alg, X509_ALGOR),
+ ASN1_SIMPLE(X509_CRL, signature, ASN1_BIT_STRING)
+} ASN1_SEQUENCE_END_ref(X509_CRL, X509_CRL)
+
+IMPLEMENT_ASN1_FUNCTIONS(X509_REVOKED)
+IMPLEMENT_ASN1_DUP_FUNCTION(X509_REVOKED)
+IMPLEMENT_ASN1_FUNCTIONS(X509_CRL_INFO)
+IMPLEMENT_ASN1_FUNCTIONS(X509_CRL)
+IMPLEMENT_ASN1_DUP_FUNCTION(X509_CRL)
+
+static int X509_REVOKED_cmp(const X509_REVOKED **a,
+ const X509_REVOKED **b)
+ {
+ return(ASN1_STRING_cmp(
+ (ASN1_STRING *)(*a)->serialNumber,
+ (ASN1_STRING *)(*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)) {
+ OPENSSL_PUT_ERROR(X509, X509_CRL_add0_revoked, 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(ASN1_ITEM_rptr(X509_CRL_INFO),
+ crl->sig_alg, crl->signature,crl->crl,r));
+ }
+
+static int crl_revoked_issuer_match(X509_CRL *crl, X509_NAME *nm,
+ X509_REVOKED *rev)
+ {
+ size_t 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;
+ size_t 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);
+ }
+ if (!sk_X509_REVOKED_find(crl->crl->revoked, &idx, &rtmp))
+ 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;
+ m = OPENSSL_malloc(sizeof(X509_CRL_METHOD));
+ if (!m)
+ 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->flags & X509_CRL_METHOD_DYNAMIC))
+ return;
+ OPENSSL_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;
+ }
+
+IMPLEMENT_ASN1_SET_OF(X509_REVOKED)
+IMPLEMENT_ASN1_SET_OF(X509_CRL)
diff --git a/src/crypto/x509/x_exten.c b/src/crypto/x509/x_exten.c
new file mode 100644
index 0000000..cf64c84
--- /dev/null
+++ b/src/crypto/x509/x_exten.c
@@ -0,0 +1,75 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/cipher.h>
+#include <openssl/x509.h>
+
+
+ASN1_SEQUENCE(X509_EXTENSION) = {
+ ASN1_SIMPLE(X509_EXTENSION, object, ASN1_OBJECT),
+ ASN1_OPT(X509_EXTENSION, critical, ASN1_BOOLEAN),
+ ASN1_SIMPLE(X509_EXTENSION, value, ASN1_OCTET_STRING)
+} ASN1_SEQUENCE_END(X509_EXTENSION)
+
+ASN1_ITEM_TEMPLATE(X509_EXTENSIONS) =
+ ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, Extension, X509_EXTENSION)
+ASN1_ITEM_TEMPLATE_END(X509_EXTENSIONS)
+
+IMPLEMENT_ASN1_FUNCTIONS(X509_EXTENSION)
+IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(X509_EXTENSIONS, X509_EXTENSIONS, X509_EXTENSIONS)
+IMPLEMENT_ASN1_DUP_FUNCTION(X509_EXTENSION)
diff --git a/src/crypto/x509/x_info.c b/src/crypto/x509/x_info.c
new file mode 100644
index 0000000..8047c71
--- /dev/null
+++ b/src/crypto/x509/x_info.c
@@ -0,0 +1,110 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/x509.h>
+
+#include <openssl/asn1.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+
+
+X509_INFO *X509_INFO_new(void)
+ {
+ X509_INFO *ret=NULL;
+
+ ret=(X509_INFO *)OPENSSL_malloc(sizeof(X509_INFO));
+ if (ret == NULL)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_INFO_new, ERR_R_MALLOC_FAILURE);
+ return(NULL);
+ }
+
+ ret->enc_cipher.cipher=NULL;
+ ret->enc_len=0;
+ ret->enc_data=NULL;
+
+ ret->references=1;
+ ret->x509=NULL;
+ ret->crl=NULL;
+ ret->x_pkey=NULL;
+ return(ret);
+ }
+
+void X509_INFO_free(X509_INFO *x)
+ {
+ int i;
+
+ if (x == NULL) return;
+
+ i=CRYPTO_add(&x->references,-1,CRYPTO_LOCK_X509_INFO);
+#ifdef REF_PRINT
+ REF_PRINT("X509_INFO",x);
+#endif
+ if (i > 0) return;
+#ifdef REF_CHECK
+ if (i < 0)
+ {
+ fprintf(stderr,"X509_INFO_free, bad reference count\n");
+ abort();
+ }
+#endif
+
+ if (x->x509 != NULL) X509_free(x->x509);
+ if (x->crl != NULL) X509_CRL_free(x->crl);
+ if (x->x_pkey != NULL) X509_PKEY_free(x->x_pkey);
+ if (x->enc_data != NULL) OPENSSL_free(x->enc_data);
+ OPENSSL_free(x);
+ }
diff --git a/src/crypto/x509/x_name.c b/src/crypto/x509/x_name.c
new file mode 100644
index 0000000..211f68f
--- /dev/null
+++ b/src/crypto/x509/x_name.c
@@ -0,0 +1,533 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <ctype.h>
+#include <string.h>
+
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/buf.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/stack.h>
+#include <openssl/x509.h>
+
+#include "../asn1/asn1_locl.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);
+
+ASN1_SEQUENCE(X509_NAME_ENTRY) = {
+ ASN1_SIMPLE(X509_NAME_ENTRY, object, ASN1_OBJECT),
+ ASN1_SIMPLE(X509_NAME_ENTRY, value, ASN1_PRINTABLE)
+} ASN1_SEQUENCE_END(X509_NAME_ENTRY)
+
+IMPLEMENT_ASN1_FUNCTIONS(X509_NAME_ENTRY)
+IMPLEMENT_ASN1_DUP_FUNCTION(X509_NAME_ENTRY)
+
+/* For the "Name" type we need a SEQUENCE OF { SET OF X509_NAME_ENTRY }
+ * so declare two template wrappers for this
+ */
+
+ASN1_ITEM_TEMPLATE(X509_NAME_ENTRIES) =
+ ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SET_OF, 0, RDNS, X509_NAME_ENTRY)
+ASN1_ITEM_TEMPLATE_END(X509_NAME_ENTRIES)
+
+ASN1_ITEM_TEMPLATE(X509_NAME_INTERNAL) =
+ ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, Name, X509_NAME_ENTRIES)
+ASN1_ITEM_TEMPLATE_END(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 = {
+ NULL,
+ x509_name_ex_new,
+ x509_name_ex_free,
+ 0, /* Default clear behaviour is OK */
+ x509_name_ex_d2i,
+ x509_name_ex_i2d,
+ x509_name_ex_print
+};
+
+IMPLEMENT_EXTERN_ASN1(X509_NAME, V_ASN1_SEQUENCE, x509_name_ff)
+
+IMPLEMENT_ASN1_FUNCTIONS(X509_NAME)
+IMPLEMENT_ASN1_DUP_FUNCTION(X509_NAME)
+
+static int x509_name_ex_new(ASN1_VALUE **val, const ASN1_ITEM *it)
+{
+ X509_NAME *ret = NULL;
+ ret = OPENSSL_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:
+ OPENSSL_PUT_ERROR(X509, x509_name_ex_new, ERR_R_MALLOC_FAILURE);
+ if (ret)
+ {
+ if (ret->entries)
+ sk_X509_NAME_ENTRY_free(ret->entries);
+ OPENSSL_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);
+ if (a->canon_enc)
+ OPENSSL_free(a->canon_enc);
+ OPENSSL_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};
+ size_t i, j;
+ int 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, ASN1_ITEM_rptr(X509_NAME_INTERNAL),
+ 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);
+ OPENSSL_PUT_ERROR(X509, x509_name_ex_d2i, ERR_R_ASN1_LIB);
+ 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 set = -1;
+ size_t i;
+ 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(!sk_X509_NAME_ENTRY_push(entries, entry)) goto memerr;
+ }
+ len = ASN1_item_ex_i2d(&intname.a, NULL,
+ ASN1_ITEM_rptr(X509_NAME_INTERNAL), -1, -1);
+ if (!BUF_MEM_grow(a->bytes,len)) goto memerr;
+ p=(unsigned char *)a->bytes->data;
+ ASN1_item_ex_i2d(&intname.a,
+ &p, ASN1_ITEM_rptr(X509_NAME_INTERNAL), -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);
+ OPENSSL_PUT_ERROR(X509, x509_name_encode, 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
+ * perfomed 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 set = -1, ret = 0;
+ size_t i;
+
+ if (a->canon_enc)
+ {
+ OPENSSL_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))
+ {
+ 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 (!asn1_string_canon(tmpentry->value, entry->value))
+ goto err;
+ if(!sk_X509_NAME_ENTRY_push(entries, tmpentry))
+ goto err;
+ tmpentry = NULL;
+ }
+
+ /* Finally generate encoding */
+
+ a->canon_enclen = i2d_name_canon(intname, NULL);
+
+ p = OPENSSL_malloc(a->canon_enclen);
+
+ if (!p)
+ goto err;
+
+ a->canon_enc = p;
+
+ 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 len, ltmp;
+ size_t i;
+ 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,
+ ASN1_ITEM_rptr(X509_NAME_ENTRIES), -1, -1);
+ if (ltmp < 0)
+ return ltmp;
+ len += ltmp;
+ }
+ return len;
+ }
+
+int X509_NAME_set(X509_NAME **xn, X509_NAME *name)
+ {
+ X509_NAME *in;
+
+ if (!xn || !name) return(0);
+
+ if (*xn != name)
+ {
+ in=X509_NAME_dup(name);
+ if (in != NULL)
+ {
+ X509_NAME_free(*xn);
+ *xn=in;
+ }
+ }
+ return(*xn != NULL);
+ }
+
+IMPLEMENT_ASN1_SET_OF(X509_NAME_ENTRY)
diff --git a/src/crypto/x509/x_pkey.c b/src/crypto/x509/x_pkey.c
new file mode 100644
index 0000000..550078b
--- /dev/null
+++ b/src/crypto/x509/x_pkey.c
@@ -0,0 +1,105 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/x509.h>
+
+#include <string.h>
+
+#include <openssl/asn1.h>
+#include <openssl/mem.h>
+#include <openssl/err.h>
+
+
+X509_PKEY *X509_PKEY_new(void)
+ {
+ X509_PKEY *ret = OPENSSL_malloc(sizeof(X509_PKEY));
+ if (ret == NULL)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_PKEY_new, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ memset(ret, 0, sizeof(X509_PKEY));
+ ret->references=1;
+
+ ret->enc_algor = X509_ALGOR_new();
+ if (ret->enc_algor == NULL)
+ goto err;
+ ret->enc_pkey = M_ASN1_OCTET_STRING_new();
+ if (ret->enc_pkey == NULL)
+ goto err;
+ return ret;
+
+err:
+ if (ret != NULL)
+ X509_PKEY_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);
+ if (x->enc_pkey != NULL) M_ASN1_OCTET_STRING_free(x->enc_pkey);
+ if (x->dec_pkey != NULL)EVP_PKEY_free(x->dec_pkey);
+ if ((x->key_data != NULL) && (x->key_free)) OPENSSL_free(x->key_data);
+ OPENSSL_free(x);
+ }
diff --git a/src/crypto/x509/x_pubkey.c b/src/crypto/x509/x_pubkey.c
new file mode 100644
index 0000000..c285aa6
--- /dev/null
+++ b/src/crypto/x509/x_pubkey.c
@@ -0,0 +1,373 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/x509.h>
+
+#include "../evp/internal.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;
+ }
+
+ASN1_SEQUENCE_cb(X509_PUBKEY, pubkey_cb) = {
+ ASN1_SIMPLE(X509_PUBKEY, algor, X509_ALGOR),
+ ASN1_SIMPLE(X509_PUBKEY, public_key, ASN1_BIT_STRING)
+} ASN1_SEQUENCE_END_cb(X509_PUBKEY, X509_PUBKEY)
+
+IMPLEMENT_ASN1_FUNCTIONS(X509_PUBKEY)
+
+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))
+ {
+ OPENSSL_PUT_ERROR(X509, X509_PUBKEY_set, X509_R_PUBLIC_KEY_ENCODE_ERROR);
+ goto error;
+ }
+ }
+ else
+ {
+ OPENSSL_PUT_ERROR(X509, X509_PUBKEY_set, X509_R_METHOD_NOT_SUPPORTED);
+ goto error;
+ }
+ }
+ else
+ {
+ OPENSSL_PUT_ERROR(X509, X509_PUBKEY_set, 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_get(X509_PUBKEY *key)
+ {
+ EVP_PKEY *ret=NULL;
+
+ if (key == NULL) goto error;
+
+ if (key->pkey != NULL)
+ {
+ return EVP_PKEY_dup(key->pkey);
+ }
+
+ if (key->public_key == NULL) goto error;
+
+ if ((ret = EVP_PKEY_new()) == NULL)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_PUBKEY_get, ERR_R_MALLOC_FAILURE);
+ goto error;
+ }
+
+ if (!EVP_PKEY_set_type(ret, OBJ_obj2nid(key->algor->algorithm)))
+ {
+ OPENSSL_PUT_ERROR(X509, X509_PUBKEY_get, X509_R_UNSUPPORTED_ALGORITHM);
+ goto error;
+ }
+
+ if (ret->ameth->pub_decode)
+ {
+ if (!ret->ameth->pub_decode(ret, key))
+ {
+ OPENSSL_PUT_ERROR(X509, X509_PUBKEY_get, X509_R_PUBLIC_KEY_DECODE_ERROR);
+ goto error;
+ }
+ }
+ else
+ {
+ OPENSSL_PUT_ERROR(X509, X509_PUBKEY_get, 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 EVP_PKEY_dup(ret);
+
+ error:
+ if (ret != NULL)
+ EVP_PKEY_free(ret);
+ return(NULL);
+ }
+
+/* Now two pseudo ASN1 routines that take an EVP_PKEY structure
+ * and encode or decode as X509_PUBKEY
+ */
+
+EVP_PKEY *d2i_PUBKEY(EVP_PKEY **a, const unsigned char **pp,
+ long length)
+ {
+ X509_PUBKEY *xpk;
+ EVP_PKEY *pktmp;
+ xpk = d2i_X509_PUBKEY(NULL, pp, length);
+ if(!xpk) return NULL;
+ pktmp = X509_PUBKEY_get(xpk);
+ X509_PUBKEY_free(xpk);
+ if(!pktmp) return NULL;
+ if(a)
+ {
+ EVP_PKEY_free(*a);
+ *a = pktmp;
+ }
+ return pktmp;
+ }
+
+int i2d_PUBKEY(const EVP_PKEY *a, unsigned char **pp)
+ {
+ X509_PUBKEY *xpk=NULL;
+ int ret;
+ if(!a) return 0;
+ if(!X509_PUBKEY_set(&xpk, (EVP_PKEY*) a)) return 0;
+ ret = i2d_X509_PUBKEY(xpk, pp);
+ X509_PUBKEY_free(xpk);
+ return ret;
+ }
+
+/* The following are equivalents but which return RSA and DSA
+ * keys
+ */
+RSA *d2i_RSA_PUBKEY(RSA **a, const unsigned char **pp,
+ long length)
+ {
+ EVP_PKEY *pkey;
+ RSA *key;
+ const unsigned char *q;
+ q = *pp;
+ pkey = d2i_PUBKEY(NULL, &q, length);
+ if (!pkey) return NULL;
+ key = EVP_PKEY_get1_RSA(pkey);
+ EVP_PKEY_free(pkey);
+ if (!key) return NULL;
+ *pp = q;
+ if (a)
+ {
+ RSA_free(*a);
+ *a = key;
+ }
+ return key;
+ }
+
+int i2d_RSA_PUBKEY(const RSA *a, unsigned char **pp)
+ {
+ EVP_PKEY *pktmp;
+ int ret;
+ if (!a) return 0;
+ pktmp = EVP_PKEY_new();
+ if (!pktmp)
+ {
+ OPENSSL_PUT_ERROR(X509, i2d_RSA_PUBKEY, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ EVP_PKEY_set1_RSA(pktmp, (RSA*) a);
+ ret = i2d_PUBKEY(pktmp, pp);
+ EVP_PKEY_free(pktmp);
+ return ret;
+ }
+
+#ifndef OPENSSL_NO_DSA
+DSA *d2i_DSA_PUBKEY(DSA **a, const unsigned char **pp,
+ long length)
+ {
+ EVP_PKEY *pkey;
+ DSA *key;
+ const unsigned char *q;
+ q = *pp;
+ pkey = d2i_PUBKEY(NULL, &q, length);
+ if (!pkey) return NULL;
+ key = EVP_PKEY_get1_DSA(pkey);
+ EVP_PKEY_free(pkey);
+ if (!key) return NULL;
+ *pp = q;
+ if (a)
+ {
+ DSA_free(*a);
+ *a = key;
+ }
+ return key;
+ }
+
+int i2d_DSA_PUBKEY(const DSA *a, unsigned char **pp)
+ {
+ EVP_PKEY *pktmp;
+ int ret;
+ if(!a) return 0;
+ pktmp = EVP_PKEY_new();
+ if(!pktmp)
+ {
+ OPENSSL_PUT_ERROR(X509, i2d_DSA_PUBKEY, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ EVP_PKEY_set1_DSA(pktmp, (DSA*) a);
+ ret = i2d_PUBKEY(pktmp, pp);
+ EVP_PKEY_free(pktmp);
+ return ret;
+ }
+#endif
+
+EC_KEY *d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp, long length)
+ {
+ EVP_PKEY *pkey;
+ EC_KEY *key;
+ const unsigned char *q;
+ q = *pp;
+ pkey = d2i_PUBKEY(NULL, &q, length);
+ if (!pkey) return(NULL);
+ key = EVP_PKEY_get1_EC_KEY(pkey);
+ EVP_PKEY_free(pkey);
+ if (!key) return(NULL);
+ *pp = q;
+ if (a)
+ {
+ EC_KEY_free(*a);
+ *a = key;
+ }
+ return(key);
+ }
+
+int i2d_EC_PUBKEY(const EC_KEY *a, unsigned char **pp)
+ {
+ EVP_PKEY *pktmp;
+ int ret;
+ if (!a) return(0);
+ if ((pktmp = EVP_PKEY_new()) == NULL)
+ {
+ OPENSSL_PUT_ERROR(X509, i2d_EC_PUBKEY, ERR_R_MALLOC_FAILURE);
+ return(0);
+ }
+ EVP_PKEY_set1_EC_KEY(pktmp, (EC_KEY*) a);
+ ret = i2d_PUBKEY(pktmp, pp);
+ EVP_PKEY_free(pktmp);
+ return(ret);
+ }
+
+int X509_PUBKEY_set0_param(X509_PUBKEY *pub, const 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)
+ {
+ if (pub->public_key->data)
+ OPENSSL_free(pub->public_key->data);
+ pub->public_key->data = penc;
+ pub->public_key->length = penclen;
+ /* Set number of unused bits to zero */
+ pub->public_key->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07);
+ pub->public_key->flags|=ASN1_STRING_FLAG_BITS_LEFT;
+ }
+ return 1;
+ }
+
+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/src/crypto/x509/x_req.c b/src/crypto/x509/x_req.c
new file mode 100644
index 0000000..8bf4613
--- /dev/null
+++ b/src/crypto/x509/x_req.c
@@ -0,0 +1,112 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <stdio.h>
+
+#include <openssl/asn1t.h>
+#include <openssl/thread.h>
+#include <openssl/x509.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;
+}
+
+ASN1_SEQUENCE_enc(X509_REQ_INFO, enc, rinf_cb) = {
+ ASN1_SIMPLE(X509_REQ_INFO, version, ASN1_INTEGER),
+ ASN1_SIMPLE(X509_REQ_INFO, subject, X509_NAME),
+ ASN1_SIMPLE(X509_REQ_INFO, pubkey, X509_PUBKEY),
+ /* This isn't really OPTIONAL but it gets round invalid
+ * encodings
+ */
+ ASN1_IMP_SET_OF_OPT(X509_REQ_INFO, attributes, X509_ATTRIBUTE, 0)
+} ASN1_SEQUENCE_END_enc(X509_REQ_INFO, X509_REQ_INFO)
+
+IMPLEMENT_ASN1_FUNCTIONS(X509_REQ_INFO)
+
+ASN1_SEQUENCE_ref(X509_REQ, 0, CRYPTO_LOCK_X509_REQ) = {
+ ASN1_SIMPLE(X509_REQ, req_info, X509_REQ_INFO),
+ ASN1_SIMPLE(X509_REQ, sig_alg, X509_ALGOR),
+ ASN1_SIMPLE(X509_REQ, signature, ASN1_BIT_STRING)
+} ASN1_SEQUENCE_END_ref(X509_REQ, X509_REQ)
+
+IMPLEMENT_ASN1_FUNCTIONS(X509_REQ)
+IMPLEMENT_ASN1_DUP_FUNCTION(X509_REQ)
diff --git a/src/crypto/x509/x_sig.c b/src/crypto/x509/x_sig.c
new file mode 100644
index 0000000..fabdb67
--- /dev/null
+++ b/src/crypto/x509/x_sig.c
@@ -0,0 +1,69 @@
+/* crypto/asn1/x_sig.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 <stdio.h>
+
+#include <openssl/asn1t.h>
+#include <openssl/x509.h>
+
+
+ASN1_SEQUENCE(X509_SIG) = {
+ ASN1_SIMPLE(X509_SIG, algor, X509_ALGOR),
+ ASN1_SIMPLE(X509_SIG, digest, ASN1_OCTET_STRING)
+} ASN1_SEQUENCE_END(X509_SIG)
+
+IMPLEMENT_ASN1_FUNCTIONS(X509_SIG)
diff --git a/src/crypto/x509/x_spki.c b/src/crypto/x509/x_spki.c
new file mode 100644
index 0000000..35bf246
--- /dev/null
+++ b/src/crypto/x509/x_spki.c
@@ -0,0 +1,78 @@
+/* crypto/asn1/x_spki.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.] */
+
+ /* This module was send to me my Pat Richards <patr@x509.com> who
+ * wrote it. It is under my Copyright with his permission. */
+
+#include <openssl/x509.h>
+#include <openssl/asn1t.h>
+
+
+ASN1_SEQUENCE(NETSCAPE_SPKAC) = {
+ ASN1_SIMPLE(NETSCAPE_SPKAC, pubkey, X509_PUBKEY),
+ ASN1_SIMPLE(NETSCAPE_SPKAC, challenge, ASN1_IA5STRING)
+} ASN1_SEQUENCE_END(NETSCAPE_SPKAC)
+
+IMPLEMENT_ASN1_FUNCTIONS(NETSCAPE_SPKAC)
+
+ASN1_SEQUENCE(NETSCAPE_SPKI) = {
+ ASN1_SIMPLE(NETSCAPE_SPKI, spkac, NETSCAPE_SPKAC),
+ ASN1_SIMPLE(NETSCAPE_SPKI, sig_algor, X509_ALGOR),
+ ASN1_SIMPLE(NETSCAPE_SPKI, signature, ASN1_BIT_STRING)
+} ASN1_SEQUENCE_END(NETSCAPE_SPKI)
+
+IMPLEMENT_ASN1_FUNCTIONS(NETSCAPE_SPKI)
diff --git a/src/crypto/x509/x_val.c b/src/crypto/x509/x_val.c
new file mode 100644
index 0000000..26200ee
--- /dev/null
+++ b/src/crypto/x509/x_val.c
@@ -0,0 +1,69 @@
+/* crypto/asn1/x_val.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 <stdio.h>
+
+#include <openssl/asn1t.h>
+#include <openssl/x509.h>
+
+
+ASN1_SEQUENCE(X509_VAL) = {
+ ASN1_SIMPLE(X509_VAL, notBefore, ASN1_TIME),
+ ASN1_SIMPLE(X509_VAL, notAfter, ASN1_TIME)
+} ASN1_SEQUENCE_END(X509_VAL)
+
+IMPLEMENT_ASN1_FUNCTIONS(X509_VAL)
diff --git a/src/crypto/x509/x_x509.c b/src/crypto/x509/x_x509.c
new file mode 100644
index 0000000..5cda3c7
--- /dev/null
+++ b/src/crypto/x509/x_x509.c
@@ -0,0 +1,209 @@
+/* crypto/asn1/x_x509.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 <stdio.h>
+
+#include <openssl/asn1t.h>
+#include <openssl/evp.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/thread.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+
+
+ASN1_SEQUENCE_enc(X509_CINF, enc, 0) = {
+ ASN1_EXP_OPT(X509_CINF, version, ASN1_INTEGER, 0),
+ ASN1_SIMPLE(X509_CINF, serialNumber, ASN1_INTEGER),
+ ASN1_SIMPLE(X509_CINF, signature, X509_ALGOR),
+ ASN1_SIMPLE(X509_CINF, issuer, X509_NAME),
+ ASN1_SIMPLE(X509_CINF, validity, X509_VAL),
+ ASN1_SIMPLE(X509_CINF, subject, X509_NAME),
+ ASN1_SIMPLE(X509_CINF, key, X509_PUBKEY),
+ ASN1_IMP_OPT(X509_CINF, issuerUID, ASN1_BIT_STRING, 1),
+ ASN1_IMP_OPT(X509_CINF, subjectUID, ASN1_BIT_STRING, 2),
+ ASN1_EXP_SEQUENCE_OF_OPT(X509_CINF, extensions, X509_EXTENSION, 3)
+} ASN1_SEQUENCE_END_enc(X509_CINF, X509_CINF)
+
+IMPLEMENT_ASN1_FUNCTIONS(X509_CINF)
+/* X509 top level structure needs a bit of customisation */
+
+extern void policy_cache_free(X509_POLICY_CACHE *cache);
+
+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;
+ CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509, ret, &ret->ex_data);
+ break;
+
+ case ASN1_OP_D2I_POST:
+ if (ret->name != NULL) OPENSSL_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);
+ policy_cache_free(ret->policy_cache);
+ GENERAL_NAMES_free(ret->altname);
+ NAME_CONSTRAINTS_free(ret->nc);
+
+ if (ret->name != NULL) OPENSSL_free(ret->name);
+ break;
+
+ }
+
+ return 1;
+
+}
+
+ASN1_SEQUENCE_ref(X509, x509_cb, CRYPTO_LOCK_X509) = {
+ ASN1_SIMPLE(X509, cert_info, X509_CINF),
+ ASN1_SIMPLE(X509, sig_alg, X509_ALGOR),
+ ASN1_SIMPLE(X509, signature, ASN1_BIT_STRING)
+} ASN1_SEQUENCE_END_ref(X509, X509)
+
+IMPLEMENT_ASN1_FUNCTIONS(X509)
+IMPLEMENT_ASN1_DUP_FUNCTION(X509)
+
+X509 *X509_up_ref(X509 *x)
+ {
+ CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509);
+ return 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(a, pp, length);
+ /* If certificate unreadable then forget it */
+ if(!ret) return NULL;
+ /* update length */
+ length -= *pp - q;
+ if(!length) return ret;
+ if(!d2i_X509_CERT_AUX(&ret->aux, pp, length)) goto err;
+ 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;
+}
+
+void X509_get0_signature(ASN1_BIT_STRING **psig, X509_ALGOR **palg,
+ const X509 *x)
+ {
+ if (psig)
+ *psig = x->signature;
+ if (palg)
+ *palg = x->sig_alg;
+ }
+
+int X509_get_signature_nid(const X509 *x)
+ {
+ return OBJ_obj2nid(x->sig_alg->algorithm);
+ }
diff --git a/src/crypto/x509/x_x509a.c b/src/crypto/x509/x_x509a.c
new file mode 100644
index 0000000..e13204b
--- /dev/null
+++ b/src/crypto/x509/x_x509a.c
@@ -0,0 +1,177 @@
+/* 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 <stdio.h>
+
+#include <openssl/asn1t.h>
+#include <openssl/evp.h>
+#include <openssl/obj.h>
+#include <openssl/x509.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);
+
+ASN1_SEQUENCE(X509_CERT_AUX) = {
+ ASN1_SEQUENCE_OF_OPT(X509_CERT_AUX, trust, ASN1_OBJECT),
+ ASN1_IMP_SEQUENCE_OF_OPT(X509_CERT_AUX, reject, ASN1_OBJECT, 0),
+ ASN1_OPT(X509_CERT_AUX, alias, ASN1_UTF8STRING),
+ ASN1_OPT(X509_CERT_AUX, keyid, ASN1_OCTET_STRING),
+ ASN1_IMP_SEQUENCE_OF_OPT(X509_CERT_AUX, other, X509_ALGOR, 1)
+} ASN1_SEQUENCE_END(X509_CERT_AUX)
+
+IMPLEMENT_ASN1_FUNCTIONS(X509_CERT_AUX)
+
+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, 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, 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, ASN1_OBJECT *obj)
+{
+ X509_CERT_AUX *aux;
+ ASN1_OBJECT *objtmp;
+ if(!(objtmp = OBJ_dup(obj))) return 0;
+ if(!(aux = aux_get(x))) return 0;
+ if(!aux->trust
+ && !(aux->trust = sk_ASN1_OBJECT_new_null())) return 0;
+ return sk_ASN1_OBJECT_push(aux->trust, objtmp);
+}
+
+int X509_add1_reject_object(X509 *x, ASN1_OBJECT *obj)
+{
+ X509_CERT_AUX *aux;
+ ASN1_OBJECT *objtmp;
+ if(!(objtmp = OBJ_dup(obj))) return 0;
+ if(!(aux = aux_get(x))) return 0;
+ if(!aux->reject
+ && !(aux->reject = sk_ASN1_OBJECT_new_null())) return 0;
+ return sk_ASN1_OBJECT_push(aux->reject, objtmp);
+}
+
+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;
+ }
+}
+
+ASN1_SEQUENCE(X509_CERT_PAIR) = {
+ ASN1_EXP_OPT(X509_CERT_PAIR, forward, X509, 0),
+ ASN1_EXP_OPT(X509_CERT_PAIR, reverse, X509, 1)
+} ASN1_SEQUENCE_END(X509_CERT_PAIR)
+
+IMPLEMENT_ASN1_FUNCTIONS(X509_CERT_PAIR)
diff --git a/src/crypto/x509v3/CMakeLists.txt b/src/crypto/x509v3/CMakeLists.txt
new file mode 100644
index 0000000..26de0ed
--- /dev/null
+++ b/src/crypto/x509v3/CMakeLists.txt
@@ -0,0 +1,60 @@
+include_directories(. .. ../../include)
+
+add_library(
+ x509v3
+
+ OBJECT
+
+ # v3_addr.c - disabled by upstream by default.
+ # v3_asid.c - disabled by upstream by default.
+ # v3_ocsp.c - missing OCSP for now.
+
+ pcy_cache.c
+ pcy_data.c
+ pcy_lib.c
+ pcy_map.c
+ pcy_node.c
+ pcy_tree.c
+ v3_akey.c
+ v3_akeya.c
+ v3_alt.c
+ v3_bcons.c
+ v3_bitst.c
+ v3_conf.c
+ v3_cpols.c
+ v3_crld.c
+ v3_enum.c
+ v3_extku.c
+ v3_genn.c
+ v3_ia5.c
+ v3_info.c
+ v3_int.c
+ v3_lib.c
+ v3_ncons.c
+ v3_pci.c
+ v3_pcia.c
+ v3_pcons.c
+ v3_pku.c
+ v3_pmaps.c
+ v3_prn.c
+ v3_purp.c
+ v3_skey.c
+ v3_sxnet.c
+ v3_utl.c
+ x509v3_error.c
+)
+
+add_executable(
+ v3name_test
+
+ v3nametest.c
+)
+
+add_executable(
+ tab_test
+
+ tabtest.c
+)
+
+target_link_libraries(v3name_test crypto)
+target_link_libraries(tab_test crypto)
diff --git a/src/crypto/x509v3/ext_dat.h b/src/crypto/x509v3/ext_dat.h
new file mode 100644
index 0000000..8b2c123
--- /dev/null
+++ b/src/crypto/x509v3/ext_dat.h
@@ -0,0 +1,129 @@
+/* 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). */
+
+/* This file contains a table of "standard" extensions */
+
+extern X509V3_EXT_METHOD v3_bcons, v3_nscert, v3_key_usage, v3_ext_ku;
+extern X509V3_EXT_METHOD v3_pkey_usage_period, v3_sxnet, v3_info, v3_sinfo;
+extern X509V3_EXT_METHOD v3_ns_ia5_list[], v3_alt[], v3_skey_id, v3_akey_id;
+extern X509V3_EXT_METHOD v3_crl_num, v3_crl_reason, v3_crl_invdate;
+extern X509V3_EXT_METHOD v3_delta_crl, v3_cpols, v3_crld, v3_freshest_crl;
+extern X509V3_EXT_METHOD v3_ocsp_nonce, v3_ocsp_accresp, v3_ocsp_acutoff;
+extern X509V3_EXT_METHOD v3_ocsp_crlid, v3_ocsp_nocheck, v3_ocsp_serviceloc;
+extern X509V3_EXT_METHOD v3_crl_hold, v3_pci;
+extern X509V3_EXT_METHOD v3_policy_mappings, v3_policy_constraints;
+extern X509V3_EXT_METHOD v3_name_constraints, v3_inhibit_anyp, v3_idp;
+extern X509V3_EXT_METHOD v3_addr, v3_asid;
+
+/* This table will be searched using OBJ_bsearch so it *must* kept in
+ * order of the ext_nid values.
+ */
+
+/* TODO(fork): OCSP support */
+#define OPENSSL_NO_OCSP
+
+static const X509V3_EXT_METHOD *const standard_exts[] = {
+&v3_nscert,
+&v3_ns_ia5_list[0],
+&v3_ns_ia5_list[1],
+&v3_ns_ia5_list[2],
+&v3_ns_ia5_list[3],
+&v3_ns_ia5_list[4],
+&v3_ns_ia5_list[5],
+&v3_ns_ia5_list[6],
+&v3_skey_id,
+&v3_key_usage,
+&v3_pkey_usage_period,
+&v3_alt[0],
+&v3_alt[1],
+&v3_bcons,
+&v3_crl_num,
+&v3_cpols,
+&v3_akey_id,
+&v3_crld,
+&v3_ext_ku,
+&v3_delta_crl,
+&v3_crl_reason,
+#ifndef OPENSSL_NO_OCSP
+&v3_crl_invdate,
+#endif
+&v3_sxnet,
+&v3_info,
+#ifndef OPENSSL_NO_OCSP
+&v3_ocsp_nonce,
+&v3_ocsp_crlid,
+&v3_ocsp_accresp,
+&v3_ocsp_nocheck,
+&v3_ocsp_acutoff,
+&v3_ocsp_serviceloc,
+#endif
+&v3_sinfo,
+&v3_policy_constraints,
+#ifndef OPENSSL_NO_OCSP
+&v3_crl_hold,
+#endif
+&v3_pci,
+&v3_name_constraints,
+&v3_policy_mappings,
+&v3_inhibit_anyp,
+&v3_idp,
+&v3_alt[2],
+&v3_freshest_crl,
+};
+
+/* Number of standard extensions */
+
+#define STANDARD_EXTENSION_COUNT (sizeof(standard_exts)/sizeof(X509V3_EXT_METHOD *))
+
diff --git a/src/crypto/x509v3/pcy_cache.c b/src/crypto/x509v3/pcy_cache.c
new file mode 100644
index 0000000..5d59c00
--- /dev/null
+++ b/src/crypto/x509v3/pcy_cache.c
@@ -0,0 +1,286 @@
+/* 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 <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/thread.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+
+#include "pcy_int.h"
+
+
+static int policy_data_cmp(const X509_POLICY_DATA **a,
+ const X509_POLICY_DATA **b);
+static int policy_cache_set_int(long *out, ASN1_INTEGER *value);
+
+/* Set cache entry according to CertificatePolicies extension.
+ * Note: this destroys the passed CERTIFICATEPOLICIES structure.
+ */
+
+static int policy_cache_create(X509 *x,
+ CERTIFICATEPOLICIES *policies, int crit)
+ {
+ size_t i;
+ int ret = 0;
+ X509_POLICY_CACHE *cache = x->policy_cache;
+ X509_POLICY_DATA *data = NULL;
+ POLICYINFO *policy;
+ if (sk_POLICYINFO_num(policies) == 0)
+ goto bad_policy;
+ cache->data = sk_X509_POLICY_DATA_new(policy_data_cmp);
+ if (!cache->data)
+ goto bad_policy;
+ for (i = 0; i < sk_POLICYINFO_num(policies); i++)
+ {
+ policy = sk_POLICYINFO_value(policies, i);
+ data = policy_data_new(policy, NULL, crit);
+ if (!data)
+ goto bad_policy;
+ /* Duplicate policy OIDs are illegal: reject if matches
+ * found.
+ */
+ if (OBJ_obj2nid(data->valid_policy) == NID_any_policy)
+ {
+ if (cache->anyPolicy)
+ {
+ ret = -1;
+ goto bad_policy;
+ }
+ cache->anyPolicy = data;
+ }
+ else if (sk_X509_POLICY_DATA_find(cache->data, NULL, data))
+ {
+ ret = -1;
+ goto bad_policy;
+ }
+ else if (!sk_X509_POLICY_DATA_push(cache->data, data))
+ goto bad_policy;
+ data = NULL;
+ }
+ ret = 1;
+ bad_policy:
+ if (ret == -1)
+ x->ex_flags |= EXFLAG_INVALID_POLICY;
+ if (data)
+ policy_data_free(data);
+ sk_POLICYINFO_pop_free(policies, POLICYINFO_free);
+ if (ret <= 0)
+ {
+ sk_X509_POLICY_DATA_pop_free(cache->data, policy_data_free);
+ cache->data = NULL;
+ }
+ return ret;
+ }
+
+
+static int policy_cache_new(X509 *x)
+ {
+ X509_POLICY_CACHE *cache;
+ ASN1_INTEGER *ext_any = NULL;
+ POLICY_CONSTRAINTS *ext_pcons = NULL;
+ CERTIFICATEPOLICIES *ext_cpols = NULL;
+ POLICY_MAPPINGS *ext_pmaps = NULL;
+ int i;
+ cache = OPENSSL_malloc(sizeof(X509_POLICY_CACHE));
+ if (!cache)
+ return 0;
+ cache->anyPolicy = NULL;
+ cache->data = NULL;
+ cache->any_skip = -1;
+ cache->explicit_skip = -1;
+ cache->map_skip = -1;
+
+ x->policy_cache = cache;
+
+ /* Handle requireExplicitPolicy *first*. Need to process this
+ * even if we don't have any policies.
+ */
+ ext_pcons = X509_get_ext_d2i(x, NID_policy_constraints, &i, NULL);
+
+ if (!ext_pcons)
+ {
+ if (i != -1)
+ goto bad_cache;
+ }
+ else
+ {
+ if (!ext_pcons->requireExplicitPolicy
+ && !ext_pcons->inhibitPolicyMapping)
+ goto bad_cache;
+ if (!policy_cache_set_int(&cache->explicit_skip,
+ ext_pcons->requireExplicitPolicy))
+ goto bad_cache;
+ if (!policy_cache_set_int(&cache->map_skip,
+ ext_pcons->inhibitPolicyMapping))
+ goto bad_cache;
+ }
+
+ /* Process CertificatePolicies */
+
+ ext_cpols = X509_get_ext_d2i(x, NID_certificate_policies, &i, NULL);
+ /* If no CertificatePolicies extension or problem decoding then
+ * there is no point continuing because the valid policies will be
+ * NULL.
+ */
+ if (!ext_cpols)
+ {
+ /* If not absent some problem with extension */
+ if (i != -1)
+ goto bad_cache;
+ return 1;
+ }
+
+ i = policy_cache_create(x, ext_cpols, i);
+
+ /* NB: ext_cpols freed by policy_cache_set_policies */
+
+ if (i <= 0)
+ return i;
+
+ ext_pmaps = X509_get_ext_d2i(x, NID_policy_mappings, &i, NULL);
+
+ if (!ext_pmaps)
+ {
+ /* If not absent some problem with extension */
+ if (i != -1)
+ goto bad_cache;
+ }
+ else
+ {
+ i = policy_cache_set_mapping(x, ext_pmaps);
+ if (i <= 0)
+ goto bad_cache;
+ }
+
+ ext_any = X509_get_ext_d2i(x, NID_inhibit_any_policy, &i, NULL);
+
+ if (!ext_any)
+ {
+ if (i != -1)
+ goto bad_cache;
+ }
+ else if (!policy_cache_set_int(&cache->any_skip, ext_any))
+ goto bad_cache;
+
+ if (0)
+ {
+ bad_cache:
+ x->ex_flags |= EXFLAG_INVALID_POLICY;
+ }
+
+ if(ext_pcons)
+ POLICY_CONSTRAINTS_free(ext_pcons);
+
+ if (ext_any)
+ ASN1_INTEGER_free(ext_any);
+
+ return 1;
+
+
+}
+
+void policy_cache_free(X509_POLICY_CACHE *cache)
+ {
+ if (!cache)
+ return;
+ if (cache->anyPolicy)
+ policy_data_free(cache->anyPolicy);
+ if (cache->data)
+ sk_X509_POLICY_DATA_pop_free(cache->data, policy_data_free);
+ OPENSSL_free(cache);
+ }
+
+const X509_POLICY_CACHE *policy_cache_set(X509 *x)
+ {
+
+ if (x->policy_cache == NULL)
+ {
+ CRYPTO_w_lock(CRYPTO_LOCK_X509);
+ policy_cache_new(x);
+ CRYPTO_w_unlock(CRYPTO_LOCK_X509);
+ }
+
+ return x->policy_cache;
+
+ }
+
+X509_POLICY_DATA *policy_cache_find_data(const X509_POLICY_CACHE *cache,
+ const ASN1_OBJECT *id)
+ {
+ size_t idx;
+ X509_POLICY_DATA tmp;
+
+ tmp.valid_policy = (ASN1_OBJECT *)id;
+ if (!sk_X509_POLICY_DATA_find(cache->data, &idx, &tmp))
+ return NULL;
+ return sk_X509_POLICY_DATA_value(cache->data, idx);
+ }
+
+static int policy_data_cmp(const X509_POLICY_DATA **a,
+ const X509_POLICY_DATA **b)
+ {
+ return OBJ_cmp((*a)->valid_policy, (*b)->valid_policy);
+ }
+
+static int policy_cache_set_int(long *out, ASN1_INTEGER *value)
+ {
+ if (value == NULL)
+ return 1;
+ if (value->type == V_ASN1_NEG_INTEGER)
+ return 0;
+ *out = ASN1_INTEGER_get(value);
+ return 1;
+ }
diff --git a/src/crypto/x509v3/pcy_data.c b/src/crypto/x509v3/pcy_data.c
new file mode 100644
index 0000000..cd45dca
--- /dev/null
+++ b/src/crypto/x509v3/pcy_data.c
@@ -0,0 +1,137 @@
+/* pcy_data.c */
+/* 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 <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+
+#include "pcy_int.h"
+
+
+/* Policy Node routines */
+
+void policy_data_free(X509_POLICY_DATA *data)
+ {
+ ASN1_OBJECT_free(data->valid_policy);
+ /* Don't free qualifiers if shared */
+ if (!(data->flags & POLICY_DATA_FLAG_SHARED_QUALIFIERS))
+ sk_POLICYQUALINFO_pop_free(data->qualifier_set,
+ POLICYQUALINFO_free);
+ sk_ASN1_OBJECT_pop_free(data->expected_policy_set, ASN1_OBJECT_free);
+ OPENSSL_free(data);
+ }
+
+/* Create a data based on an existing policy. If 'id' is NULL use the
+ * oid in the policy, otherwise use 'id'. This behaviour covers the two
+ * types of data in RFC3280: data with from a CertificatePolcies extension
+ * and additional data with just the qualifiers of anyPolicy and ID from
+ * another source.
+ */
+
+X509_POLICY_DATA *policy_data_new(POLICYINFO *policy,
+ const ASN1_OBJECT *cid, int crit)
+ {
+ X509_POLICY_DATA *ret;
+ ASN1_OBJECT *id;
+ if (!policy && !cid)
+ return NULL;
+ if (cid)
+ {
+ id = OBJ_dup(cid);
+ if (!id)
+ return NULL;
+ }
+ else
+ id = NULL;
+ ret = OPENSSL_malloc(sizeof(X509_POLICY_DATA));
+ if (!ret)
+ return NULL;
+ ret->expected_policy_set = sk_ASN1_OBJECT_new_null();
+ if (!ret->expected_policy_set)
+ {
+ OPENSSL_free(ret);
+ if (id)
+ ASN1_OBJECT_free(id);
+ return NULL;
+ }
+
+ if (crit)
+ ret->flags = POLICY_DATA_FLAG_CRITICAL;
+ else
+ ret->flags = 0;
+
+ if (id)
+ ret->valid_policy = id;
+ else
+ {
+ ret->valid_policy = policy->policyid;
+ policy->policyid = NULL;
+ }
+
+ if (policy)
+ {
+ ret->qualifier_set = policy->qualifiers;
+ policy->qualifiers = NULL;
+ }
+ else
+ ret->qualifier_set = NULL;
+
+ return ret;
+ }
+
diff --git a/src/crypto/x509v3/pcy_int.h b/src/crypto/x509v3/pcy_int.h
new file mode 100644
index 0000000..ccff928
--- /dev/null
+++ b/src/crypto/x509v3/pcy_int.h
@@ -0,0 +1,212 @@
+/* pcy_int.h */
+/* 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).
+ *
+ */
+
+
+typedef struct X509_POLICY_DATA_st X509_POLICY_DATA;
+
+DECLARE_STACK_OF(X509_POLICY_DATA)
+
+/* Internal structures */
+
+/* This structure and the field names correspond to the Policy 'node' of
+ * RFC3280. NB this structure contains no pointers to parent or child
+ * data: X509_POLICY_NODE contains that. This means that the main policy data
+ * can be kept static and cached with the certificate.
+ */
+
+struct X509_POLICY_DATA_st
+ {
+ unsigned int flags;
+ /* Policy OID and qualifiers for this data */
+ ASN1_OBJECT *valid_policy;
+ STACK_OF(POLICYQUALINFO) *qualifier_set;
+ STACK_OF(ASN1_OBJECT) *expected_policy_set;
+ };
+
+/* X509_POLICY_DATA flags values */
+
+/* This flag indicates the structure has been mapped using a policy mapping
+ * extension. If policy mapping is not active its references get deleted.
+ */
+
+#define POLICY_DATA_FLAG_MAPPED 0x1
+
+/* This flag indicates the data doesn't correspond to a policy in Certificate
+ * Policies: it has been mapped to any policy.
+ */
+
+#define POLICY_DATA_FLAG_MAPPED_ANY 0x2
+
+/* AND with flags to see if any mapping has occurred */
+
+#define POLICY_DATA_FLAG_MAP_MASK 0x3
+
+/* qualifiers are shared and shouldn't be freed */
+
+#define POLICY_DATA_FLAG_SHARED_QUALIFIERS 0x4
+
+/* Parent node is an extra node and should be freed */
+
+#define POLICY_DATA_FLAG_EXTRA_NODE 0x8
+
+/* Corresponding CertificatePolicies is critical */
+
+#define POLICY_DATA_FLAG_CRITICAL 0x10
+
+/* This structure is cached with a certificate */
+
+struct X509_POLICY_CACHE_st {
+ /* anyPolicy data or NULL if no anyPolicy */
+ X509_POLICY_DATA *anyPolicy;
+ /* other policy data */
+ STACK_OF(X509_POLICY_DATA) *data;
+ /* If InhibitAnyPolicy present this is its value or -1 if absent. */
+ long any_skip;
+ /* If policyConstraints and requireExplicitPolicy present this is its
+ * value or -1 if absent.
+ */
+ long explicit_skip;
+ /* If policyConstraints and policyMapping present this is its
+ * value or -1 if absent.
+ */
+ long map_skip;
+ };
+
+/*#define POLICY_CACHE_FLAG_CRITICAL POLICY_DATA_FLAG_CRITICAL*/
+
+/* This structure represents the relationship between nodes */
+
+struct X509_POLICY_NODE_st
+ {
+ /* node data this refers to */
+ const X509_POLICY_DATA *data;
+ /* Parent node */
+ X509_POLICY_NODE *parent;
+ /* Number of child nodes */
+ int nchild;
+ };
+
+struct X509_POLICY_LEVEL_st
+ {
+ /* Cert for this level */
+ X509 *cert;
+ /* nodes at this level */
+ STACK_OF(X509_POLICY_NODE) *nodes;
+ /* anyPolicy node */
+ X509_POLICY_NODE *anyPolicy;
+ /* Extra data */
+ /*STACK_OF(X509_POLICY_DATA) *extra_data;*/
+ unsigned int flags;
+ };
+
+struct X509_POLICY_TREE_st
+ {
+ /* This is the tree 'level' data */
+ X509_POLICY_LEVEL *levels;
+ int nlevel;
+ /* Extra policy data when additional nodes (not from the certificate)
+ * are required.
+ */
+ STACK_OF(X509_POLICY_DATA) *extra_data;
+ /* This is the authority constained policy set */
+ STACK_OF(X509_POLICY_NODE) *auth_policies;
+ STACK_OF(X509_POLICY_NODE) *user_policies;
+ unsigned int flags;
+ };
+
+/* Set if anyPolicy present in user policies */
+#define POLICY_FLAG_ANY_POLICY 0x2
+
+/* Useful macros */
+
+#define node_data_critical(data) (data->flags & POLICY_DATA_FLAG_CRITICAL)
+#define node_critical(node) node_data_critical(node->data)
+
+/* Internal functions */
+
+X509_POLICY_DATA *policy_data_new(POLICYINFO *policy, const ASN1_OBJECT *id,
+ int crit);
+void policy_data_free(X509_POLICY_DATA *data);
+
+X509_POLICY_DATA *policy_cache_find_data(const X509_POLICY_CACHE *cache,
+ const ASN1_OBJECT *id);
+int policy_cache_set_mapping(X509 *x, POLICY_MAPPINGS *maps);
+
+
+STACK_OF(X509_POLICY_NODE) *policy_node_cmp_new(void);
+
+void policy_cache_init(void);
+
+void policy_cache_free(X509_POLICY_CACHE *cache);
+
+X509_POLICY_NODE *level_find_node(const X509_POLICY_LEVEL *level,
+ const X509_POLICY_NODE *parent,
+ const ASN1_OBJECT *id);
+
+X509_POLICY_NODE *tree_find_sk(STACK_OF(X509_POLICY_NODE) *sk,
+ const ASN1_OBJECT *id);
+
+X509_POLICY_NODE *level_add_node(X509_POLICY_LEVEL *level,
+ const X509_POLICY_DATA *data,
+ X509_POLICY_NODE *parent,
+ X509_POLICY_TREE *tree);
+void policy_node_free(X509_POLICY_NODE *node);
+int policy_node_match(const X509_POLICY_LEVEL *lvl,
+ const X509_POLICY_NODE *node, const ASN1_OBJECT *oid);
+
+const X509_POLICY_CACHE *policy_cache_set(X509 *x);
diff --git a/src/crypto/x509v3/pcy_lib.c b/src/crypto/x509v3/pcy_lib.c
new file mode 100644
index 0000000..16be2f0
--- /dev/null
+++ b/src/crypto/x509v3/pcy_lib.c
@@ -0,0 +1,165 @@
+/* pcy_lib.c */
+/* 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 <openssl/x509.h>
+#include <openssl/x509v3.h>
+
+#include "pcy_int.h"
+
+
+/* accessor functions */
+
+/* X509_POLICY_TREE stuff */
+
+int X509_policy_tree_level_count(const X509_POLICY_TREE *tree)
+ {
+ if (!tree)
+ return 0;
+ return tree->nlevel;
+ }
+
+X509_POLICY_LEVEL *
+ X509_policy_tree_get0_level(const X509_POLICY_TREE *tree, int i)
+ {
+ if (!tree || (i < 0) || (i >= tree->nlevel))
+ return NULL;
+ return tree->levels + i;
+ }
+
+STACK_OF(X509_POLICY_NODE) *
+ X509_policy_tree_get0_policies(const X509_POLICY_TREE *tree)
+ {
+ if (!tree)
+ return NULL;
+ return tree->auth_policies;
+ }
+
+STACK_OF(X509_POLICY_NODE) *
+ X509_policy_tree_get0_user_policies(const X509_POLICY_TREE *tree)
+ {
+ if (!tree)
+ return NULL;
+ if (tree->flags & POLICY_FLAG_ANY_POLICY)
+ return tree->auth_policies;
+ else
+ return tree->user_policies;
+ }
+
+/* X509_POLICY_LEVEL stuff */
+
+int X509_policy_level_node_count(X509_POLICY_LEVEL *level)
+ {
+ int n;
+ if (!level)
+ return 0;
+ if (level->anyPolicy)
+ n = 1;
+ else
+ n = 0;
+ if (level->nodes)
+ n += sk_X509_POLICY_NODE_num(level->nodes);
+ return n;
+ }
+
+X509_POLICY_NODE *X509_policy_level_get0_node(X509_POLICY_LEVEL *level, int i)
+ {
+ if (!level)
+ return NULL;
+ if (level->anyPolicy)
+ {
+ if (i == 0)
+ return level->anyPolicy;
+ i--;
+ }
+ return sk_X509_POLICY_NODE_value(level->nodes, i);
+ }
+
+/* X509_POLICY_NODE stuff */
+
+const ASN1_OBJECT *X509_policy_node_get0_policy(const X509_POLICY_NODE *node)
+ {
+ if (!node)
+ return NULL;
+ return node->data->valid_policy;
+ }
+
+#if 0
+int X509_policy_node_get_critical(const X509_POLICY_NODE *node)
+ {
+ if (node_critical(node))
+ return 1;
+ return 0;
+ }
+#endif
+
+STACK_OF(POLICYQUALINFO) *
+ X509_policy_node_get0_qualifiers(const X509_POLICY_NODE *node)
+ {
+ if (!node)
+ return NULL;
+ return node->data->qualifier_set;
+ }
+
+const X509_POLICY_NODE *
+ X509_policy_node_get0_parent(const X509_POLICY_NODE *node)
+ {
+ if (!node)
+ return NULL;
+ return node->parent;
+ }
+
+
diff --git a/src/crypto/x509v3/pcy_map.c b/src/crypto/x509v3/pcy_map.c
new file mode 100644
index 0000000..2b8307b
--- /dev/null
+++ b/src/crypto/x509v3/pcy_map.c
@@ -0,0 +1,133 @@
+/* pcy_map.c */
+/* 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 <openssl/obj.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+
+#include "pcy_int.h"
+
+
+/* Set policy mapping entries in cache.
+ * Note: this modifies the passed POLICY_MAPPINGS structure
+ */
+
+int policy_cache_set_mapping(X509 *x, POLICY_MAPPINGS *maps)
+ {
+ POLICY_MAPPING *map;
+ X509_POLICY_DATA *data;
+ X509_POLICY_CACHE *cache = x->policy_cache;
+ size_t i;
+ int ret = 0;
+ if (sk_POLICY_MAPPING_num(maps) == 0)
+ {
+ ret = -1;
+ goto bad_mapping;
+ }
+ for (i = 0; i < sk_POLICY_MAPPING_num(maps); i++)
+ {
+ map = sk_POLICY_MAPPING_value(maps, i);
+ /* Reject if map to or from anyPolicy */
+ if ((OBJ_obj2nid(map->subjectDomainPolicy) == NID_any_policy)
+ || (OBJ_obj2nid(map->issuerDomainPolicy) == NID_any_policy))
+ {
+ ret = -1;
+ goto bad_mapping;
+ }
+
+ /* Attempt to find matching policy data */
+ data = policy_cache_find_data(cache, map->issuerDomainPolicy);
+ /* If we don't have anyPolicy can't map */
+ if (!data && !cache->anyPolicy)
+ continue;
+
+ /* Create a NODE from anyPolicy */
+ if (!data)
+ {
+ data = policy_data_new(NULL, map->issuerDomainPolicy,
+ cache->anyPolicy->flags
+ & POLICY_DATA_FLAG_CRITICAL);
+ if (!data)
+ goto bad_mapping;
+ data->qualifier_set = cache->anyPolicy->qualifier_set;
+ /*map->issuerDomainPolicy = NULL;*/
+ data->flags |= POLICY_DATA_FLAG_MAPPED_ANY;
+ data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS;
+ if (!sk_X509_POLICY_DATA_push(cache->data, data))
+ {
+ policy_data_free(data);
+ goto bad_mapping;
+ }
+ }
+ else
+ data->flags |= POLICY_DATA_FLAG_MAPPED;
+ if (!sk_ASN1_OBJECT_push(data->expected_policy_set,
+ map->subjectDomainPolicy))
+ goto bad_mapping;
+ map->subjectDomainPolicy = NULL;
+
+ }
+
+ ret = 1;
+ bad_mapping:
+ if (ret == -1)
+ x->ex_flags |= EXFLAG_INVALID_POLICY;
+ sk_POLICY_MAPPING_pop_free(maps, POLICY_MAPPING_free);
+ return ret;
+
+ }
diff --git a/src/crypto/x509v3/pcy_node.c b/src/crypto/x509v3/pcy_node.c
new file mode 100644
index 0000000..55cc203
--- /dev/null
+++ b/src/crypto/x509v3/pcy_node.c
@@ -0,0 +1,197 @@
+/* pcy_node.c */
+/* 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 <openssl/asn1.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+
+#include "pcy_int.h"
+
+
+static int node_cmp(const X509_POLICY_NODE **a,
+ const X509_POLICY_NODE **b)
+ {
+ return OBJ_cmp((*a)->data->valid_policy, (*b)->data->valid_policy);
+ }
+
+STACK_OF(X509_POLICY_NODE) *policy_node_cmp_new(void)
+ {
+ return sk_X509_POLICY_NODE_new(node_cmp);
+ }
+
+X509_POLICY_NODE *tree_find_sk(STACK_OF(X509_POLICY_NODE) *nodes,
+ const ASN1_OBJECT *id)
+ {
+ X509_POLICY_DATA n;
+ X509_POLICY_NODE l;
+ size_t idx;
+
+ n.valid_policy = (ASN1_OBJECT *)id;
+ l.data = &n;
+
+ if (!sk_X509_POLICY_NODE_find(nodes, &idx, &l))
+ return NULL;
+
+ return sk_X509_POLICY_NODE_value(nodes, idx);
+
+ }
+
+X509_POLICY_NODE *level_find_node(const X509_POLICY_LEVEL *level,
+ const X509_POLICY_NODE *parent,
+ const ASN1_OBJECT *id)
+ {
+ X509_POLICY_NODE *node;
+ size_t i;
+ for (i = 0; i < sk_X509_POLICY_NODE_num(level->nodes); i++)
+ {
+ node = sk_X509_POLICY_NODE_value(level->nodes, i);
+ if (node->parent == parent)
+ {
+ if (!OBJ_cmp(node->data->valid_policy, id))
+ return node;
+ }
+ }
+ return NULL;
+ }
+
+X509_POLICY_NODE *level_add_node(X509_POLICY_LEVEL *level,
+ const X509_POLICY_DATA *data,
+ X509_POLICY_NODE *parent,
+ X509_POLICY_TREE *tree)
+ {
+ X509_POLICY_NODE *node;
+ node = OPENSSL_malloc(sizeof(X509_POLICY_NODE));
+ if (!node)
+ return NULL;
+ node->data = data;
+ node->parent = parent;
+ node->nchild = 0;
+ if (level)
+ {
+ if (OBJ_obj2nid(data->valid_policy) == NID_any_policy)
+ {
+ if (level->anyPolicy)
+ goto node_error;
+ level->anyPolicy = node;
+ }
+ else
+ {
+
+ if (!level->nodes)
+ level->nodes = policy_node_cmp_new();
+ if (!level->nodes)
+ goto node_error;
+ if (!sk_X509_POLICY_NODE_push(level->nodes, node))
+ goto node_error;
+ }
+ }
+
+ if (tree)
+ {
+ if (!tree->extra_data)
+ tree->extra_data = sk_X509_POLICY_DATA_new_null();
+ if (!tree->extra_data)
+ goto node_error;
+ if (!sk_X509_POLICY_DATA_push(tree->extra_data, data))
+ goto node_error;
+ }
+
+ if (parent)
+ parent->nchild++;
+
+ return node;
+
+ node_error:
+ policy_node_free(node);
+ return 0;
+
+ }
+
+void policy_node_free(X509_POLICY_NODE *node)
+ {
+ OPENSSL_free(node);
+ }
+
+/* See if a policy node matches a policy OID. If mapping enabled look through
+ * expected policy set otherwise just valid policy.
+ */
+
+int policy_node_match(const X509_POLICY_LEVEL *lvl,
+ const X509_POLICY_NODE *node, const ASN1_OBJECT *oid)
+ {
+ size_t i;
+ ASN1_OBJECT *policy_oid;
+ const X509_POLICY_DATA *x = node->data;
+
+ if ( (lvl->flags & X509_V_FLAG_INHIBIT_MAP)
+ || !(x->flags & POLICY_DATA_FLAG_MAP_MASK))
+ {
+ if (!OBJ_cmp(x->valid_policy, oid))
+ return 1;
+ return 0;
+ }
+
+ for (i = 0; i < sk_ASN1_OBJECT_num(x->expected_policy_set); i++)
+ {
+ policy_oid = sk_ASN1_OBJECT_value(x->expected_policy_set, i);
+ if (!OBJ_cmp(policy_oid, oid))
+ return 1;
+ }
+ return 0;
+
+ }
diff --git a/src/crypto/x509v3/pcy_tree.c b/src/crypto/x509v3/pcy_tree.c
new file mode 100644
index 0000000..682474d
--- /dev/null
+++ b/src/crypto/x509v3/pcy_tree.c
@@ -0,0 +1,876 @@
+/* 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 <string.h>
+
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/stack.h>
+#include <openssl/thread.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+
+#include "pcy_int.h"
+
+
+/* Enable this to print out the complete policy tree at various point during
+ * evaluation.
+ */
+
+/*#define OPENSSL_POLICY_DEBUG*/
+
+#ifdef OPENSSL_POLICY_DEBUG
+
+static void expected_print(BIO *err, X509_POLICY_LEVEL *lev,
+ X509_POLICY_NODE *node, int indent)
+ {
+ if ( (lev->flags & X509_V_FLAG_INHIBIT_MAP)
+ || !(node->data->flags & POLICY_DATA_FLAG_MAP_MASK))
+ BIO_puts(err, " Not Mapped\n");
+ else
+ {
+ int i;
+ STACK_OF(ASN1_OBJECT) *pset = node->data->expected_policy_set;
+ ASN1_OBJECT *oid;
+ BIO_puts(err, " Expected: ");
+ for (i = 0; i < sk_ASN1_OBJECT_num(pset); i++)
+ {
+ oid = sk_ASN1_OBJECT_value(pset, i);
+ if (i)
+ BIO_puts(err, ", ");
+ i2a_ASN1_OBJECT(err, oid);
+ }
+ BIO_puts(err, "\n");
+ }
+ }
+
+static void tree_print(char *str, X509_POLICY_TREE *tree,
+ X509_POLICY_LEVEL *curr)
+ {
+ X509_POLICY_LEVEL *plev;
+ X509_POLICY_NODE *node;
+ int i;
+ BIO *err;
+ err = BIO_new_fp(stderr, BIO_NOCLOSE);
+ if (!curr)
+ curr = tree->levels + tree->nlevel;
+ else
+ curr++;
+ BIO_printf(err, "Level print after %s\n", str);
+ BIO_printf(err, "Printing Up to Level %ld\n", curr - tree->levels);
+ for (plev = tree->levels; plev != curr; plev++)
+ {
+ BIO_printf(err, "Level %ld, flags = %x\n",
+ plev - tree->levels, plev->flags);
+ for (i = 0; i < sk_X509_POLICY_NODE_num(plev->nodes); i++)
+ {
+ node = sk_X509_POLICY_NODE_value(plev->nodes, i);
+ X509_POLICY_NODE_print(err, node, 2);
+ expected_print(err, plev, node, 2);
+ BIO_printf(err, " Flags: %x\n", node->data->flags);
+ }
+ if (plev->anyPolicy)
+ X509_POLICY_NODE_print(err, plev->anyPolicy, 2);
+ }
+
+ BIO_free(err);
+
+ }
+#else
+
+#define tree_print(a,b,c) /* */
+
+#endif
+
+/* Initialize policy tree. Return values:
+ * 0 Some internal error occured.
+ * -1 Inconsistent or invalid extensions in certificates.
+ * 1 Tree initialized OK.
+ * 2 Policy tree is empty.
+ * 5 Tree OK and requireExplicitPolicy true.
+ * 6 Tree empty and requireExplicitPolicy true.
+ */
+
+static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs,
+ unsigned int flags)
+ {
+ X509_POLICY_TREE *tree;
+ X509_POLICY_LEVEL *level;
+ const X509_POLICY_CACHE *cache;
+ X509_POLICY_DATA *data = NULL;
+ X509 *x;
+ int ret = 1;
+ int i, n;
+ int explicit_policy;
+ int any_skip;
+ int map_skip;
+ *ptree = NULL;
+ n = sk_X509_num(certs);
+
+#if 0
+ /* Disable policy mapping for now... */
+ flags |= X509_V_FLAG_INHIBIT_MAP;
+#endif
+
+ if (flags & X509_V_FLAG_EXPLICIT_POLICY)
+ explicit_policy = 0;
+ else
+ explicit_policy = n + 1;
+
+ if (flags & X509_V_FLAG_INHIBIT_ANY)
+ any_skip = 0;
+ else
+ any_skip = n + 1;
+
+ if (flags & X509_V_FLAG_INHIBIT_MAP)
+ map_skip = 0;
+ else
+ map_skip = n + 1;
+
+ /* Can't do anything with just a trust anchor */
+ if (n == 1)
+ return 1;
+ /* First setup policy cache in all certificates apart from the
+ * trust anchor. Note any bad cache results on the way. Also can
+ * calculate explicit_policy value at this point.
+ */
+ for (i = n - 2; i >= 0; i--)
+ {
+ x = sk_X509_value(certs, i);
+ X509_check_purpose(x, -1, -1);
+ cache = policy_cache_set(x);
+ /* If cache NULL something bad happened: return immediately */
+ if (cache == NULL)
+ return 0;
+ /* If inconsistent extensions keep a note of it but continue */
+ if (x->ex_flags & EXFLAG_INVALID_POLICY)
+ ret = -1;
+ /* Otherwise if we have no data (hence no CertificatePolicies)
+ * and haven't already set an inconsistent code note it.
+ */
+ else if ((ret == 1) && !cache->data)
+ ret = 2;
+ if (explicit_policy > 0)
+ {
+ if (!(x->ex_flags & EXFLAG_SI))
+ explicit_policy--;
+ if ((cache->explicit_skip != -1)
+ && (cache->explicit_skip < explicit_policy))
+ explicit_policy = cache->explicit_skip;
+ }
+ }
+
+ if (ret != 1)
+ {
+ if (ret == 2 && !explicit_policy)
+ return 6;
+ return ret;
+ }
+
+
+ /* If we get this far initialize the tree */
+
+ tree = OPENSSL_malloc(sizeof(X509_POLICY_TREE));
+
+ if (!tree)
+ return 0;
+
+ tree->flags = 0;
+ tree->levels = OPENSSL_malloc(sizeof(X509_POLICY_LEVEL) * n);
+ tree->nlevel = 0;
+ tree->extra_data = NULL;
+ tree->auth_policies = NULL;
+ tree->user_policies = NULL;
+
+ if (!tree->levels)
+ {
+ OPENSSL_free(tree);
+ return 0;
+ }
+
+ memset(tree->levels, 0, n * sizeof(X509_POLICY_LEVEL));
+
+ tree->nlevel = n;
+
+ level = tree->levels;
+
+ /* Root data: initialize to anyPolicy */
+
+ data = policy_data_new(NULL, OBJ_nid2obj(NID_any_policy), 0);
+
+ if (!data || !level_add_node(level, data, NULL, tree))
+ goto bad_tree;
+
+ for (i = n - 2; i >= 0; i--)
+ {
+ level++;
+ x = sk_X509_value(certs, i);
+ cache = policy_cache_set(x);
+ level->cert = X509_up_ref(x);
+
+ if (!cache->anyPolicy)
+ level->flags |= X509_V_FLAG_INHIBIT_ANY;
+
+ /* Determine inhibit any and inhibit map flags */
+ if (any_skip == 0)
+ {
+ /* Any matching allowed if certificate is self
+ * issued and not the last in the chain.
+ */
+ if (!(x->ex_flags & EXFLAG_SI) || (i == 0))
+ level->flags |= X509_V_FLAG_INHIBIT_ANY;
+ }
+ else
+ {
+ if (!(x->ex_flags & EXFLAG_SI))
+ any_skip--;
+ if ((cache->any_skip >= 0)
+ && (cache->any_skip < any_skip))
+ any_skip = cache->any_skip;
+ }
+
+ if (map_skip == 0)
+ level->flags |= X509_V_FLAG_INHIBIT_MAP;
+ else
+ {
+ if (!(x->ex_flags & EXFLAG_SI))
+ map_skip--;
+ if ((cache->map_skip >= 0)
+ && (cache->map_skip < map_skip))
+ map_skip = cache->map_skip;
+ }
+
+ }
+
+ *ptree = tree;
+
+ if (explicit_policy)
+ return 1;
+ else
+ return 5;
+
+ bad_tree:
+
+ X509_policy_tree_free(tree);
+
+ return 0;
+
+ }
+
+static int tree_link_matching_nodes(X509_POLICY_LEVEL *curr,
+ const X509_POLICY_DATA *data)
+ {
+ X509_POLICY_LEVEL *last = curr - 1;
+ X509_POLICY_NODE *node;
+ int matched = 0;
+ size_t i;
+ /* Iterate through all in nodes linking matches */
+ for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++)
+ {
+ node = sk_X509_POLICY_NODE_value(last->nodes, i);
+ if (policy_node_match(last, node, data->valid_policy))
+ {
+ if (!level_add_node(curr, data, node, NULL))
+ return 0;
+ matched = 1;
+ }
+ }
+ if (!matched && last->anyPolicy)
+ {
+ if (!level_add_node(curr, data, last->anyPolicy, NULL))
+ return 0;
+ }
+ return 1;
+ }
+
+/* This corresponds to RFC3280 6.1.3(d)(1):
+ * link any data from CertificatePolicies onto matching parent
+ * or anyPolicy if no match.
+ */
+
+static int tree_link_nodes(X509_POLICY_LEVEL *curr,
+ const X509_POLICY_CACHE *cache)
+ {
+ size_t i;
+ X509_POLICY_DATA *data;
+
+ for (i = 0; i < sk_X509_POLICY_DATA_num(cache->data); i++)
+ {
+ data = sk_X509_POLICY_DATA_value(cache->data, i);
+ /* If a node is mapped any it doesn't have a corresponding
+ * CertificatePolicies entry.
+ * However such an identical node would be created
+ * if anyPolicy matching is enabled because there would be
+ * no match with the parent valid_policy_set. So we create
+ * link because then it will have the mapping flags
+ * right and we can prune it later.
+ */
+#if 0
+ if ((data->flags & POLICY_DATA_FLAG_MAPPED_ANY)
+ && !(curr->flags & X509_V_FLAG_INHIBIT_ANY))
+ continue;
+#endif
+ /* Look for matching nodes in previous level */
+ if (!tree_link_matching_nodes(curr, data))
+ return 0;
+ }
+ return 1;
+ }
+
+/* This corresponds to RFC3280 6.1.3(d)(2):
+ * Create new data for any unmatched policies in the parent and link
+ * to anyPolicy.
+ */
+
+static int tree_add_unmatched(X509_POLICY_LEVEL *curr,
+ const X509_POLICY_CACHE *cache,
+ const ASN1_OBJECT *id,
+ X509_POLICY_NODE *node,
+ X509_POLICY_TREE *tree)
+ {
+ X509_POLICY_DATA *data;
+ if (id == NULL)
+ id = node->data->valid_policy;
+ /* Create a new node with qualifiers from anyPolicy and
+ * id from unmatched node.
+ */
+ data = policy_data_new(NULL, id, node_critical(node));
+
+ if (data == NULL)
+ return 0;
+ /* Curr may not have anyPolicy */
+ data->qualifier_set = cache->anyPolicy->qualifier_set;
+ data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS;
+ if (!level_add_node(curr, data, node, tree))
+ {
+ policy_data_free(data);
+ return 0;
+ }
+
+ return 1;
+ }
+
+static int tree_link_unmatched(X509_POLICY_LEVEL *curr,
+ const X509_POLICY_CACHE *cache,
+ X509_POLICY_NODE *node,
+ X509_POLICY_TREE *tree)
+ {
+ const X509_POLICY_LEVEL *last = curr - 1;
+ size_t i;
+
+ if ( (last->flags & X509_V_FLAG_INHIBIT_MAP)
+ || !(node->data->flags & POLICY_DATA_FLAG_MAPPED))
+ {
+ /* If no policy mapping: matched if one child present */
+ if (node->nchild)
+ return 1;
+ if (!tree_add_unmatched(curr, cache, NULL, node, tree))
+ return 0;
+ /* Add it */
+ }
+ else
+ {
+ /* If mapping: matched if one child per expected policy set */
+ STACK_OF(ASN1_OBJECT) *expset = node->data->expected_policy_set;
+ if (node->nchild == sk_ASN1_OBJECT_num(expset))
+ return 1;
+ /* Locate unmatched nodes */
+ for (i = 0; i < sk_ASN1_OBJECT_num(expset); i++)
+ {
+ ASN1_OBJECT *oid = sk_ASN1_OBJECT_value(expset, i);
+ if (level_find_node(curr, node, oid))
+ continue;
+ if (!tree_add_unmatched(curr, cache, oid, node, tree))
+ return 0;
+ }
+
+ }
+
+ return 1;
+
+ }
+
+static int tree_link_any(X509_POLICY_LEVEL *curr,
+ const X509_POLICY_CACHE *cache,
+ X509_POLICY_TREE *tree)
+ {
+ size_t i;
+ /*X509_POLICY_DATA *data;*/
+ X509_POLICY_NODE *node;
+ X509_POLICY_LEVEL *last = curr - 1;
+
+ for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++)
+ {
+ node = sk_X509_POLICY_NODE_value(last->nodes, i);
+
+ if (!tree_link_unmatched(curr, cache, node, tree))
+ return 0;
+
+#if 0
+
+ /* Skip any node with any children: we only want unmathced
+ * nodes.
+ *
+ * Note: need something better for policy mapping
+ * because each node may have multiple children
+ */
+ if (node->nchild)
+ continue;
+
+ /* Create a new node with qualifiers from anyPolicy and
+ * id from unmatched node.
+ */
+ data = policy_data_new(NULL, node->data->valid_policy,
+ node_critical(node));
+
+ if (data == NULL)
+ return 0;
+ /* Curr may not have anyPolicy */
+ data->qualifier_set = cache->anyPolicy->qualifier_set;
+ data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS;
+ if (!level_add_node(curr, data, node, tree))
+ {
+ policy_data_free(data);
+ return 0;
+ }
+
+#endif
+
+ }
+ /* Finally add link to anyPolicy */
+ if (last->anyPolicy)
+ {
+ if (!level_add_node(curr, cache->anyPolicy,
+ last->anyPolicy, NULL))
+ return 0;
+ }
+ return 1;
+ }
+
+/* Prune the tree: delete any child mapped child data on the current level
+ * then proceed up the tree deleting any data with no children. If we ever
+ * have no data on a level we can halt because the tree will be empty.
+ */
+
+static int tree_prune(X509_POLICY_TREE *tree, X509_POLICY_LEVEL *curr)
+ {
+ STACK_OF(X509_POLICY_NODE) *nodes;
+ X509_POLICY_NODE *node;
+ int i;
+ nodes = curr->nodes;
+ if (curr->flags & X509_V_FLAG_INHIBIT_MAP)
+ {
+ for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--)
+ {
+ node = sk_X509_POLICY_NODE_value(nodes, i);
+ /* Delete any mapped data: see RFC3280 XXXX */
+ if (node->data->flags & POLICY_DATA_FLAG_MAP_MASK)
+ {
+ node->parent->nchild--;
+ OPENSSL_free(node);
+ (void)sk_X509_POLICY_NODE_delete(nodes,i);
+ }
+ }
+ }
+
+ for(;;) {
+ --curr;
+ nodes = curr->nodes;
+ for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--)
+ {
+ node = sk_X509_POLICY_NODE_value(nodes, i);
+ if (node->nchild == 0)
+ {
+ node->parent->nchild--;
+ OPENSSL_free(node);
+ (void)sk_X509_POLICY_NODE_delete(nodes, i);
+ }
+ }
+ if (curr->anyPolicy && !curr->anyPolicy->nchild)
+ {
+ if (curr->anyPolicy->parent)
+ curr->anyPolicy->parent->nchild--;
+ OPENSSL_free(curr->anyPolicy);
+ curr->anyPolicy = NULL;
+ }
+ if (curr == tree->levels)
+ {
+ /* If we zapped anyPolicy at top then tree is empty */
+ if (!curr->anyPolicy)
+ return 2;
+ return 1;
+ }
+ }
+
+ }
+
+static int tree_add_auth_node(STACK_OF(X509_POLICY_NODE) **pnodes,
+ X509_POLICY_NODE *pcy)
+ {
+ if (!*pnodes)
+ {
+ *pnodes = policy_node_cmp_new();
+ if (!*pnodes)
+ return 0;
+ }
+ else if (sk_X509_POLICY_NODE_find(*pnodes, NULL, pcy))
+ return 1;
+
+ if (!sk_X509_POLICY_NODE_push(*pnodes, pcy))
+ return 0;
+
+ return 1;
+
+ }
+
+/* Calculate the authority set based on policy tree.
+ * The 'pnodes' parameter is used as a store for the set of policy nodes
+ * used to calculate the user set. If the authority set is not anyPolicy
+ * then pnodes will just point to the authority set. If however the authority
+ * set is anyPolicy then the set of valid policies (other than anyPolicy)
+ * is store in pnodes. The return value of '2' is used in this case to indicate
+ * that pnodes should be freed.
+ */
+
+static int tree_calculate_authority_set(X509_POLICY_TREE *tree,
+ STACK_OF(X509_POLICY_NODE) **pnodes)
+ {
+ X509_POLICY_LEVEL *curr;
+ X509_POLICY_NODE *node, *anyptr;
+ STACK_OF(X509_POLICY_NODE) **addnodes;
+ int i;
+ size_t j;
+ curr = tree->levels + tree->nlevel - 1;
+
+ /* If last level contains anyPolicy set is anyPolicy */
+ if (curr->anyPolicy)
+ {
+ if (!tree_add_auth_node(&tree->auth_policies, curr->anyPolicy))
+ return 0;
+ addnodes = pnodes;
+ }
+ else
+ /* Add policies to authority set */
+ addnodes = &tree->auth_policies;
+
+ curr = tree->levels;
+ for (i = 1; i < tree->nlevel; i++)
+ {
+ /* If no anyPolicy node on this this level it can't
+ * appear on lower levels so end search.
+ */
+ if (!(anyptr = curr->anyPolicy))
+ break;
+ curr++;
+ for (j = 0; j < sk_X509_POLICY_NODE_num(curr->nodes); j++)
+ {
+ node = sk_X509_POLICY_NODE_value(curr->nodes, j);
+ if ((node->parent == anyptr)
+ && !tree_add_auth_node(addnodes, node))
+ return 0;
+ }
+ }
+
+ if (addnodes == pnodes)
+ return 2;
+
+ *pnodes = tree->auth_policies;
+
+ return 1;
+ }
+
+static int tree_calculate_user_set(X509_POLICY_TREE *tree,
+ STACK_OF(ASN1_OBJECT) *policy_oids,
+ STACK_OF(X509_POLICY_NODE) *auth_nodes)
+ {
+ size_t i;
+ X509_POLICY_NODE *node;
+ ASN1_OBJECT *oid;
+
+ X509_POLICY_NODE *anyPolicy;
+ X509_POLICY_DATA *extra;
+
+ /* Check if anyPolicy present in authority constrained policy set:
+ * this will happen if it is a leaf node.
+ */
+
+ if (sk_ASN1_OBJECT_num(policy_oids) <= 0)
+ return 1;
+
+ anyPolicy = tree->levels[tree->nlevel - 1].anyPolicy;
+
+ for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++)
+ {
+ oid = sk_ASN1_OBJECT_value(policy_oids, i);
+ if (OBJ_obj2nid(oid) == NID_any_policy)
+ {
+ tree->flags |= POLICY_FLAG_ANY_POLICY;
+ return 1;
+ }
+ }
+
+ for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++)
+ {
+ oid = sk_ASN1_OBJECT_value(policy_oids, i);
+ node = tree_find_sk(auth_nodes, oid);
+ if (!node)
+ {
+ if (!anyPolicy)
+ continue;
+ /* Create a new node with policy ID from user set
+ * and qualifiers from anyPolicy.
+ */
+ extra = policy_data_new(NULL, oid,
+ node_critical(anyPolicy));
+ if (!extra)
+ return 0;
+ extra->qualifier_set = anyPolicy->data->qualifier_set;
+ extra->flags = POLICY_DATA_FLAG_SHARED_QUALIFIERS
+ | POLICY_DATA_FLAG_EXTRA_NODE;
+ node = level_add_node(NULL, extra, anyPolicy->parent,
+ tree);
+ }
+ if (!tree->user_policies)
+ {
+ tree->user_policies = sk_X509_POLICY_NODE_new_null();
+ if (!tree->user_policies)
+ return 1;
+ }
+ if (!sk_X509_POLICY_NODE_push(tree->user_policies, node))
+ return 0;
+ }
+ return 1;
+
+ }
+
+static int tree_evaluate(X509_POLICY_TREE *tree)
+ {
+ int ret, i;
+ X509_POLICY_LEVEL *curr = tree->levels + 1;
+ const X509_POLICY_CACHE *cache;
+
+ for(i = 1; i < tree->nlevel; i++, curr++)
+ {
+ cache = policy_cache_set(curr->cert);
+ if (!tree_link_nodes(curr, cache))
+ return 0;
+
+ if (!(curr->flags & X509_V_FLAG_INHIBIT_ANY)
+ && !tree_link_any(curr, cache, tree))
+ return 0;
+ tree_print("before tree_prune()", tree, curr);
+ ret = tree_prune(tree, curr);
+ if (ret != 1)
+ return ret;
+ }
+
+ return 1;
+
+ }
+
+static void exnode_free(X509_POLICY_NODE *node)
+ {
+ if (node->data && (node->data->flags & POLICY_DATA_FLAG_EXTRA_NODE))
+ OPENSSL_free(node);
+ }
+
+
+void X509_policy_tree_free(X509_POLICY_TREE *tree)
+ {
+ X509_POLICY_LEVEL *curr;
+ int i;
+
+ if (!tree)
+ return;
+
+ sk_X509_POLICY_NODE_free(tree->auth_policies);
+ sk_X509_POLICY_NODE_pop_free(tree->user_policies, exnode_free);
+
+ for(i = 0, curr = tree->levels; i < tree->nlevel; i++, curr++)
+ {
+ if (curr->cert)
+ X509_free(curr->cert);
+ if (curr->nodes)
+ sk_X509_POLICY_NODE_pop_free(curr->nodes,
+ policy_node_free);
+ if (curr->anyPolicy)
+ policy_node_free(curr->anyPolicy);
+ }
+
+ if (tree->extra_data)
+ sk_X509_POLICY_DATA_pop_free(tree->extra_data,
+ policy_data_free);
+
+ OPENSSL_free(tree->levels);
+ OPENSSL_free(tree);
+
+ }
+
+/* Application policy checking function.
+ * Return codes:
+ * 0 Internal Error.
+ * 1 Successful.
+ * -1 One or more certificates contain invalid or inconsistent extensions
+ * -2 User constrained policy set empty and requireExplicit true.
+ */
+
+int X509_policy_check(X509_POLICY_TREE **ptree, int *pexplicit_policy,
+ STACK_OF(X509) *certs,
+ STACK_OF(ASN1_OBJECT) *policy_oids,
+ unsigned int flags)
+ {
+ int ret;
+ X509_POLICY_TREE *tree = NULL;
+ STACK_OF(X509_POLICY_NODE) *nodes, *auth_nodes = NULL;
+ *ptree = NULL;
+
+ *pexplicit_policy = 0;
+ ret = tree_init(&tree, certs, flags);
+
+ switch (ret)
+ {
+
+ /* Tree empty requireExplicit False: OK */
+ case 2:
+ return 1;
+
+ /* Some internal error */
+ case -1:
+ return -1;
+
+ /* Some internal error */
+ case 0:
+ return 0;
+
+ /* Tree empty requireExplicit True: Error */
+
+ case 6:
+ *pexplicit_policy = 1;
+ return -2;
+
+ /* Tree OK requireExplicit True: OK and continue */
+ case 5:
+ *pexplicit_policy = 1;
+ break;
+
+ /* Tree OK: continue */
+
+ case 1:
+ if (!tree)
+ /*
+ * tree_init() returns success and a null tree
+ * if it's just looking at a trust anchor.
+ * I'm not sure that returning success here is
+ * correct, but I'm sure that reporting this
+ * as an internal error which our caller
+ * interprets as a malloc failure is wrong.
+ */
+ return 1;
+ break;
+ }
+
+ if (!tree) goto error;
+ ret = tree_evaluate(tree);
+
+ tree_print("tree_evaluate()", tree, NULL);
+
+ if (ret <= 0)
+ goto error;
+
+ /* Return value 2 means tree empty */
+ if (ret == 2)
+ {
+ X509_policy_tree_free(tree);
+ if (*pexplicit_policy)
+ return -2;
+ else
+ return 1;
+ }
+
+ /* Tree is not empty: continue */
+
+ ret = tree_calculate_authority_set(tree, &auth_nodes);
+
+ if (!ret)
+ goto error;
+
+ if (!tree_calculate_user_set(tree, policy_oids, auth_nodes))
+ goto error;
+
+ if (ret == 2)
+ sk_X509_POLICY_NODE_free(auth_nodes);
+
+ if (tree)
+ *ptree = tree;
+
+ if (*pexplicit_policy)
+ {
+ nodes = X509_policy_tree_get0_user_policies(tree);
+ if (sk_X509_POLICY_NODE_num(nodes) <= 0)
+ return -2;
+ }
+
+ return 1;
+
+ error:
+
+ X509_policy_tree_free(tree);
+
+ return 0;
+
+ }
+
diff --git a/src/crypto/x509v3/tabtest.c b/src/crypto/x509v3/tabtest.c
new file mode 100644
index 0000000..26ecc6c
--- /dev/null
+++ b/src/crypto/x509v3/tabtest.c
@@ -0,0 +1,94 @@
+/* tabtest.c */
+/* 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).
+ *
+ */
+
+/* Simple program to check the ext_dat.h is correct and print out
+ * problems if it is not.
+ */
+
+#include <stdio.h>
+
+#include <openssl/crypto.h>
+#include <openssl/x509v3.h>
+
+#include "ext_dat.h"
+
+int main(void)
+{
+ int i, prev = -1, bad = 0;
+ const X509V3_EXT_METHOD *const *tmp;
+ CRYPTO_library_init();
+ i = sizeof(standard_exts) / sizeof(X509V3_EXT_METHOD *);
+ if(i != STANDARD_EXTENSION_COUNT)
+ fprintf(stderr, "Extension number invalid expecting %d\n", i);
+ tmp = standard_exts;
+ for(i = 0; i < STANDARD_EXTENSION_COUNT; i++, tmp++) {
+ if((*tmp)->ext_nid < prev) bad = 1;
+ prev = (*tmp)->ext_nid;
+
+ }
+ if(bad) {
+ tmp = standard_exts;
+ fprintf(stderr, "Extensions out of order!\n");
+ for(i = 0; i < STANDARD_EXTENSION_COUNT; i++, tmp++)
+ printf("%d : %s\n", (*tmp)->ext_nid, OBJ_nid2sn((*tmp)->ext_nid));
+ return 1;
+ } else {
+ printf("PASS\n");
+ return 0;
+ }
+}
diff --git a/src/crypto/x509v3/v3_akey.c b/src/crypto/x509v3/v3_akey.c
new file mode 100644
index 0000000..f6e6b69
--- /dev/null
+++ b/src/crypto/x509v3/v3_akey.c
@@ -0,0 +1,212 @@
+/* v3_akey.c */
+/* 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 <stdio.h>
+#include <string.h>
+
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/conf.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/x509v3.h>
+
+
+static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_KEYID(X509V3_EXT_METHOD *method,
+ AUTHORITY_KEYID *akeyid, STACK_OF(CONF_VALUE) *extlist);
+static AUTHORITY_KEYID *v2i_AUTHORITY_KEYID(X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *values);
+
+const X509V3_EXT_METHOD v3_akey_id =
+ {
+ NID_authority_key_identifier,
+ X509V3_EXT_MULTILINE, ASN1_ITEM_ref(AUTHORITY_KEYID),
+ 0,0,0,0,
+ 0,0,
+ (X509V3_EXT_I2V)i2v_AUTHORITY_KEYID,
+ (X509V3_EXT_V2I)v2i_AUTHORITY_KEYID,
+ 0,0,
+ NULL
+ };
+
+static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_KEYID(X509V3_EXT_METHOD *method,
+ AUTHORITY_KEYID *akeyid, STACK_OF(CONF_VALUE) *extlist)
+{
+ char *tmp;
+ if(akeyid->keyid) {
+ tmp = hex_to_string(akeyid->keyid->data, akeyid->keyid->length);
+ X509V3_add_value("keyid", tmp, &extlist);
+ OPENSSL_free(tmp);
+ }
+ if(akeyid->issuer)
+ extlist = i2v_GENERAL_NAMES(NULL, akeyid->issuer, extlist);
+ if(akeyid->serial) {
+ tmp = hex_to_string(akeyid->serial->data,
+ akeyid->serial->length);
+ X509V3_add_value("serial", tmp, &extlist);
+ OPENSSL_free(tmp);
+ }
+ return extlist;
+}
+
+/* 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;
+ size_t i;
+ int j;
+ CONF_VALUE *cnf;
+ ASN1_OCTET_STRING *ikeyid = NULL;
+ X509_NAME *isname = NULL;
+ GENERAL_NAMES * gens = NULL;
+ GENERAL_NAME *gen = NULL;
+ ASN1_INTEGER *serial = NULL;
+ X509_EXTENSION *ext;
+ X509 *cert;
+ AUTHORITY_KEYID *akeyid;
+
+ for(i = 0; i < sk_CONF_VALUE_num(values); i++)
+ {
+ cnf = sk_CONF_VALUE_value(values, i);
+ if(!strcmp(cnf->name, "keyid"))
+ {
+ 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
+ {
+ OPENSSL_PUT_ERROR(X509V3, v2i_AUTHORITY_KEYID, X509V3_R_UNKNOWN_OPTION);
+ ERR_add_error_data(2, "name=", cnf->name);
+ return NULL;
+ }
+ }
+
+ if(!ctx || !ctx->issuer_cert)
+ {
+ if(ctx && (ctx->flags==CTX_TEST))
+ return AUTHORITY_KEYID_new();
+ OPENSSL_PUT_ERROR(X509V3, v2i_AUTHORITY_KEYID, X509V3_R_NO_ISSUER_CERTIFICATE);
+ return NULL;
+ }
+
+ cert = ctx->issuer_cert;
+
+ if(keyid)
+ {
+ j = X509_get_ext_by_NID(cert, NID_subject_key_identifier, -1);
+ if((j >= 0) && (ext = X509_get_ext(cert, j)))
+ ikeyid = X509V3_EXT_d2i(ext);
+ if(keyid==2 && !ikeyid)
+ {
+ OPENSSL_PUT_ERROR(X509V3, v2i_AUTHORITY_KEYID, X509V3_R_UNABLE_TO_GET_ISSUER_KEYID);
+ return NULL;
+ }
+ }
+
+ if((issuer && !ikeyid) || (issuer == 2))
+ {
+ isname = X509_NAME_dup(X509_get_issuer_name(cert));
+ serial = M_ASN1_INTEGER_dup(X509_get_serialNumber(cert));
+ if(!isname || !serial)
+ {
+ OPENSSL_PUT_ERROR(X509V3, v2i_AUTHORITY_KEYID, 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))
+ {
+ OPENSSL_PUT_ERROR(X509V3, v2i_AUTHORITY_KEYID, 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:
+ X509_NAME_free(isname);
+ M_ASN1_INTEGER_free(serial);
+ M_ASN1_OCTET_STRING_free(ikeyid);
+ return NULL;
+ }
diff --git a/src/crypto/x509v3/v3_akeya.c b/src/crypto/x509v3/v3_akeya.c
new file mode 100644
index 0000000..8b72cca
--- /dev/null
+++ b/src/crypto/x509v3/v3_akeya.c
@@ -0,0 +1,71 @@
+/* v3_akey_asn1.c */
+/* 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 <stdio.h>
+
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/conf.h>
+#include <openssl/x509v3.h>
+
+
+ASN1_SEQUENCE(AUTHORITY_KEYID) = {
+ ASN1_IMP_OPT(AUTHORITY_KEYID, keyid, ASN1_OCTET_STRING, 0),
+ ASN1_IMP_SEQUENCE_OF_OPT(AUTHORITY_KEYID, issuer, GENERAL_NAME, 1),
+ ASN1_IMP_OPT(AUTHORITY_KEYID, serial, ASN1_INTEGER, 2)
+} ASN1_SEQUENCE_END(AUTHORITY_KEYID)
+
+IMPLEMENT_ASN1_FUNCTIONS(AUTHORITY_KEYID)
diff --git a/src/crypto/x509v3/v3_alt.c b/src/crypto/x509v3/v3_alt.c
new file mode 100644
index 0000000..113cf45
--- /dev/null
+++ b/src/crypto/x509v3/v3_alt.c
@@ -0,0 +1,618 @@
+/* v3_alt.c */
+/* 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 <stdio.h>
+#include <string.h>
+
+#include <openssl/conf.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/x509v3.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, char *value, X509V3_CTX *ctx);
+static int do_dirname(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx);
+
+const X509V3_EXT_METHOD v3_alt[] = {
+{ NID_subject_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES),
+0,0,0,0,
+0,0,
+(X509V3_EXT_I2V)i2v_GENERAL_NAMES,
+(X509V3_EXT_V2I)v2i_subject_alt,
+NULL, NULL, NULL},
+
+{ NID_issuer_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES),
+0,0,0,0,
+0,0,
+(X509V3_EXT_I2V)i2v_GENERAL_NAMES,
+(X509V3_EXT_V2I)v2i_issuer_alt,
+NULL, NULL, NULL},
+
+{ NID_certificate_issuer, 0, ASN1_ITEM_ref(GENERAL_NAMES),
+0,0,0,0,
+0,0,
+(X509V3_EXT_I2V)i2v_GENERAL_NAMES,
+NULL, NULL, NULL, NULL},
+};
+
+STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES(X509V3_EXT_METHOD *method,
+ GENERAL_NAMES *gens, STACK_OF(CONF_VALUE) *ret)
+{
+ size_t i;
+ GENERAL_NAME *gen;
+ for(i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
+ gen = sk_GENERAL_NAME_value(gens, i);
+ ret = i2v_GENERAL_NAME(method, gen, ret);
+ }
+ if(!ret) return sk_CONF_VALUE_new_null();
+ return ret;
+}
+
+STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method,
+ GENERAL_NAME *gen, STACK_OF(CONF_VALUE) *ret)
+{
+ unsigned char *p;
+ char oline[256], htmp[5];
+ int i;
+ switch (gen->type)
+ {
+ case GEN_OTHERNAME:
+ X509V3_add_value("othername","<unsupported>", &ret);
+ break;
+
+ case GEN_X400:
+ X509V3_add_value("X400Name","<unsupported>", &ret);
+ break;
+
+ case GEN_EDIPARTY:
+ X509V3_add_value("EdiPartyName","<unsupported>", &ret);
+ break;
+
+ case GEN_EMAIL:
+ X509V3_add_value_uchar("email",gen->d.ia5->data, &ret);
+ break;
+
+ case GEN_DNS:
+ X509V3_add_value_uchar("DNS",gen->d.ia5->data, &ret);
+ break;
+
+ case GEN_URI:
+ X509V3_add_value_uchar("URI",gen->d.ia5->data, &ret);
+ break;
+
+ case GEN_DIRNAME:
+ X509_NAME_oneline(gen->d.dirn, oline, 256);
+ X509V3_add_value("DirName",oline, &ret);
+ break;
+
+ case GEN_IPADD:
+ p = gen->d.ip->data;
+ if(gen->d.ip->length == 4)
+ BIO_snprintf(oline, sizeof oline,
+ "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
+ else if(gen->d.ip->length == 16)
+ {
+ oline[0] = 0;
+ for (i = 0; i < 8; i++)
+ {
+ BIO_snprintf(htmp, sizeof htmp,
+ "%X", p[0] << 8 | p[1]);
+ p += 2;
+ strcat(oline, htmp);
+ if (i != 7)
+ strcat(oline, ":");
+ }
+ }
+ else
+ {
+ X509V3_add_value("IP Address","<invalid>", &ret);
+ break;
+ }
+ X509V3_add_value("IP Address",oline, &ret);
+ break;
+
+ case GEN_RID:
+ i2t_ASN1_OBJECT(oline, 256, gen->d.rid);
+ X509V3_add_value("Registered ID",oline, &ret);
+ break;
+ }
+ return ret;
+}
+
+int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen)
+{
+ unsigned char *p;
+ int i;
+ switch (gen->type)
+ {
+ case GEN_OTHERNAME:
+ BIO_printf(out, "othername:<unsupported>");
+ break;
+
+ case GEN_X400:
+ BIO_printf(out, "X400Name:<unsupported>");
+ break;
+
+ case GEN_EDIPARTY:
+ /* Maybe fix this: it is supported now */
+ BIO_printf(out, "EdiPartyName:<unsupported>");
+ break;
+
+ case GEN_EMAIL:
+ BIO_printf(out, "email:%s",gen->d.ia5->data);
+ break;
+
+ case GEN_DNS:
+ BIO_printf(out, "DNS:%s",gen->d.ia5->data);
+ break;
+
+ case GEN_URI:
+ BIO_printf(out, "URI:%s",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:<invalid>");
+ break;
+ }
+ break;
+
+ case GEN_RID:
+ BIO_printf(out, "Registered ID");
+ i2a_ASN1_OBJECT(out, gen->d.rid);
+ break;
+ }
+ return 1;
+}
+
+static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
+{
+ GENERAL_NAMES *gens = NULL;
+ CONF_VALUE *cnf;
+ size_t i;
+ if(!(gens = sk_GENERAL_NAME_new_null())) {
+ OPENSSL_PUT_ERROR(X509V3, v2i_issuer_alt, 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") && cnf->value &&
+ !strcmp(cnf->value, "copy")) {
+ if(!copy_issuer(ctx, gens)) goto err;
+ } else {
+ GENERAL_NAME *gen;
+ if(!(gen = v2i_GENERAL_NAME(method, ctx, cnf)))
+ goto err;
+ sk_GENERAL_NAME_push(gens, gen);
+ }
+ }
+ return gens;
+ err:
+ sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
+ return NULL;
+}
+
+/* Append subject altname of issuer to issuer alt name of subject */
+
+static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens)
+{
+ GENERAL_NAMES *ialt;
+ GENERAL_NAME *gen;
+ X509_EXTENSION *ext;
+ int i;
+ size_t j;
+ if(ctx && (ctx->flags == CTX_TEST)) return 1;
+ if(!ctx || !ctx->issuer_cert) {
+ OPENSSL_PUT_ERROR(X509V3, copy_issuer, X509V3_R_NO_ISSUER_DETAILS);
+ goto err;
+ }
+ i = X509_get_ext_by_NID(ctx->issuer_cert, NID_subject_alt_name, -1);
+ if(i < 0) return 1;
+ if(!(ext = X509_get_ext(ctx->issuer_cert, i)) ||
+ !(ialt = X509V3_EXT_d2i(ext)) ) {
+ OPENSSL_PUT_ERROR(X509V3, copy_issuer, X509V3_R_ISSUER_DECODE_ERROR);
+ goto err;
+ }
+
+ for(j = 0; j < sk_GENERAL_NAME_num(ialt); j++) {
+ gen = sk_GENERAL_NAME_value(ialt, j);
+ if(!sk_GENERAL_NAME_push(gens, gen)) {
+ OPENSSL_PUT_ERROR(X509V3, copy_issuer, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+ sk_GENERAL_NAME_free(ialt);
+
+ return 1;
+
+ err:
+ return 0;
+
+}
+
+static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
+{
+ GENERAL_NAMES *gens = NULL;
+ CONF_VALUE *cnf;
+ size_t i;
+ if(!(gens = sk_GENERAL_NAME_new_null())) {
+ OPENSSL_PUT_ERROR(X509V3, v2i_subject_alt, 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;
+ sk_GENERAL_NAME_push(gens, gen);
+ }
+ }
+ 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)) {
+ OPENSSL_PUT_ERROR(X509V3, copy_email, X509V3_R_NO_SUBJECT_DETAILS);
+ goto err;
+ }
+ /* Find the subject name */
+ if(ctx->subject_cert) nm = X509_get_subject_name(ctx->subject_cert);
+ else nm = X509_REQ_get_subject_name(ctx->subject_req);
+
+ /* Now add any email address(es) to STACK */
+ i = -1;
+ while((i = X509_NAME_get_index_by_NID(nm,
+ NID_pkcs9_emailAddress, i)) >= 0) {
+ ne = X509_NAME_get_entry(nm, i);
+ email = M_ASN1_IA5STRING_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())) {
+ OPENSSL_PUT_ERROR(X509V3, copy_email, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ gen->d.ia5 = email;
+ email = NULL;
+ gen->type = GEN_EMAIL;
+ if(!sk_GENERAL_NAME_push(gens, gen)) {
+ OPENSSL_PUT_ERROR(X509V3, copy_email, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ gen = NULL;
+ }
+
+
+ return 1;
+
+ err:
+ GENERAL_NAME_free(gen);
+ M_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;
+ size_t i;
+ if(!(gens = sk_GENERAL_NAME_new_null())) {
+ OPENSSL_PUT_ERROR(X509V3, v2i_GENERAL_NAMES, 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;
+ sk_GENERAL_NAME_push(gens, gen);
+ }
+ return gens;
+ err:
+ sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
+ return NULL;
+}
+
+GENERAL_NAME *v2i_GENERAL_NAME(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
+ CONF_VALUE *cnf)
+ {
+ return v2i_GENERAL_NAME_ex(NULL, method, ctx, cnf, 0);
+ }
+
+GENERAL_NAME *a2i_GENERAL_NAME(GENERAL_NAME *out,
+ const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
+ int gen_type, char *value, int is_nc)
+ {
+ char is_string = 0;
+ GENERAL_NAME *gen = NULL;
+
+ if(!value)
+ {
+ OPENSSL_PUT_ERROR(X509V3, a2i_GENERAL_NAME, X509V3_R_MISSING_VALUE);
+ return NULL;
+ }
+
+ if (out)
+ gen = out;
+ else
+ {
+ gen = GENERAL_NAME_new();
+ if(gen == NULL)
+ {
+ OPENSSL_PUT_ERROR(X509V3, a2i_GENERAL_NAME, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ }
+
+ switch (gen_type)
+ {
+ case GEN_URI:
+ case GEN_EMAIL:
+ case GEN_DNS:
+ is_string = 1;
+ break;
+
+ case GEN_RID:
+ {
+ ASN1_OBJECT *obj;
+ if(!(obj = OBJ_txt2obj(value,0)))
+ {
+ OPENSSL_PUT_ERROR(X509V3, a2i_GENERAL_NAME, X509V3_R_BAD_OBJECT);
+ ERR_add_error_data(2, "value=", value);
+ goto err;
+ }
+ gen->d.rid = obj;
+ }
+ break;
+
+ case GEN_IPADD:
+ if (is_nc)
+ gen->d.ip = a2i_IPADDRESS_NC(value);
+ else
+ gen->d.ip = a2i_IPADDRESS(value);
+ if(gen->d.ip == NULL)
+ {
+ OPENSSL_PUT_ERROR(X509V3, a2i_GENERAL_NAME, X509V3_R_BAD_IP_ADDRESS);
+ ERR_add_error_data(2, "value=", value);
+ goto err;
+ }
+ break;
+
+ case GEN_DIRNAME:
+ if (!do_dirname(gen, value, ctx))
+ {
+ OPENSSL_PUT_ERROR(X509V3, a2i_GENERAL_NAME, X509V3_R_DIRNAME_ERROR);
+ goto err;
+ }
+ break;
+
+ case GEN_OTHERNAME:
+ if (!do_othername(gen, value, ctx))
+ {
+ OPENSSL_PUT_ERROR(X509V3, a2i_GENERAL_NAME, X509V3_R_OTHERNAME_ERROR);
+ goto err;
+ }
+ break;
+ default:
+ OPENSSL_PUT_ERROR(X509V3, a2i_GENERAL_NAME, X509V3_R_UNSUPPORTED_TYPE);
+ goto err;
+ }
+
+ if(is_string)
+ {
+ if(!(gen->d.ia5 = M_ASN1_IA5STRING_new()) ||
+ !ASN1_STRING_set(gen->d.ia5, (unsigned char*)value,
+ strlen(value)))
+ {
+ OPENSSL_PUT_ERROR(X509V3, a2i_GENERAL_NAME, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+
+ gen->type = gen_type;
+
+ return gen;
+
+ err:
+ if (!out)
+ GENERAL_NAME_free(gen);
+ return NULL;
+ }
+
+GENERAL_NAME *v2i_GENERAL_NAME_ex(GENERAL_NAME *out,
+ const X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, CONF_VALUE *cnf, int is_nc)
+ {
+ int type;
+
+ char *name, *value;
+
+ name = cnf->name;
+ value = cnf->value;
+
+ if(!value)
+ {
+ OPENSSL_PUT_ERROR(X509V3, v2i_GENERAL_NAME_ex, X509V3_R_MISSING_VALUE);
+ return NULL;
+ }
+
+ if(!name_cmp(name, "email"))
+ type = GEN_EMAIL;
+ else if(!name_cmp(name, "URI"))
+ type = GEN_URI;
+ else if(!name_cmp(name, "DNS"))
+ type = GEN_DNS;
+ else if(!name_cmp(name, "RID"))
+ type = GEN_RID;
+ else if(!name_cmp(name, "IP"))
+ type = GEN_IPADD;
+ else if(!name_cmp(name, "dirName"))
+ type = GEN_DIRNAME;
+ else if(!name_cmp(name, "otherName"))
+ type = GEN_OTHERNAME;
+ else
+ {
+ OPENSSL_PUT_ERROR(X509V3, v2i_GENERAL_NAME_ex, X509V3_R_UNSUPPORTED_OPTION);
+ ERR_add_error_data(2, "name=", name);
+ return NULL;
+ }
+
+ return a2i_GENERAL_NAME(out, method, ctx, type, value, is_nc);
+
+ }
+
+static int do_othername(GENERAL_NAME *gen, 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 = OPENSSL_malloc(objlen + 1);
+ strncpy(objtmp, value, objlen);
+ objtmp[objlen] = 0;
+ gen->d.otherName->type_id = OBJ_txt2obj(objtmp, 0);
+ OPENSSL_free(objtmp);
+ if (!gen->d.otherName->type_id)
+ return 0;
+ return 1;
+ }
+
+static int do_dirname(GENERAL_NAME *gen, 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)
+ {
+ OPENSSL_PUT_ERROR(X509V3, do_dirname, X509V3_R_SECTION_NOT_FOUND);
+ ERR_add_error_data(2, "section=", 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/src/crypto/x509v3/v3_bcons.c b/src/crypto/x509v3/v3_bcons.c
new file mode 100644
index 0000000..a1381b4
--- /dev/null
+++ b/src/crypto/x509v3/v3_bcons.c
@@ -0,0 +1,126 @@
+/* v3_bcons.c */
+/* 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 <stdio.h>
+#include <string.h>
+
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/conf.h>
+#include <openssl/err.h>
+#include <openssl/obj.h>
+#include <openssl/x509v3.h>
+
+
+static STACK_OF(CONF_VALUE) *i2v_BASIC_CONSTRAINTS(X509V3_EXT_METHOD *method, BASIC_CONSTRAINTS *bcons, STACK_OF(CONF_VALUE) *extlist);
+static BASIC_CONSTRAINTS *v2i_BASIC_CONSTRAINTS(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *values);
+
+const X509V3_EXT_METHOD v3_bcons = {
+NID_basic_constraints, 0,
+ASN1_ITEM_ref(BASIC_CONSTRAINTS),
+0,0,0,0,
+0,0,
+(X509V3_EXT_I2V)i2v_BASIC_CONSTRAINTS,
+(X509V3_EXT_V2I)v2i_BASIC_CONSTRAINTS,
+NULL,NULL,
+NULL
+};
+
+ASN1_SEQUENCE(BASIC_CONSTRAINTS) = {
+ ASN1_OPT(BASIC_CONSTRAINTS, ca, ASN1_FBOOLEAN),
+ ASN1_OPT(BASIC_CONSTRAINTS, pathlen, ASN1_INTEGER)
+} ASN1_SEQUENCE_END(BASIC_CONSTRAINTS)
+
+IMPLEMENT_ASN1_FUNCTIONS(BASIC_CONSTRAINTS)
+
+
+static STACK_OF(CONF_VALUE) *i2v_BASIC_CONSTRAINTS(X509V3_EXT_METHOD *method,
+ BASIC_CONSTRAINTS *bcons, STACK_OF(CONF_VALUE) *extlist)
+{
+ X509V3_add_value_bool("CA", bcons->ca, &extlist);
+ X509V3_add_value_int("pathlen", bcons->pathlen, &extlist);
+ return extlist;
+}
+
+static BASIC_CONSTRAINTS *v2i_BASIC_CONSTRAINTS(X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *values)
+{
+ BASIC_CONSTRAINTS *bcons=NULL;
+ CONF_VALUE *val;
+ size_t i;
+ if(!(bcons = BASIC_CONSTRAINTS_new())) {
+ OPENSSL_PUT_ERROR(X509V3, v2i_BASIC_CONSTRAINTS, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ for(i = 0; i < sk_CONF_VALUE_num(values); i++) {
+ val = sk_CONF_VALUE_value(values, i);
+ if(!strcmp(val->name, "CA")) {
+ 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 {
+ OPENSSL_PUT_ERROR(X509V3, v2i_BASIC_CONSTRAINTS, X509V3_R_INVALID_NAME);
+ X509V3_conf_err(val);
+ goto err;
+ }
+ }
+ return bcons;
+ err:
+ BASIC_CONSTRAINTS_free(bcons);
+ return NULL;
+}
+
diff --git a/src/crypto/x509v3/v3_bitst.c b/src/crypto/x509v3/v3_bitst.c
new file mode 100644
index 0000000..15e9859
--- /dev/null
+++ b/src/crypto/x509v3/v3_bitst.c
@@ -0,0 +1,141 @@
+/* v3_bitst.c */
+/* 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 <stdio.h>
+#include <string.h>
+
+#include <openssl/conf.h>
+#include <openssl/err.h>
+#include <openssl/obj.h>
+#include <openssl/x509v3.h>
+
+
+static const 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 const BIT_STRING_BITNAME key_usage_type_table[] = {
+{0, "Digital Signature", "digitalSignature"},
+{1, "Non Repudiation", "nonRepudiation"},
+{2, "Key Encipherment", "keyEncipherment"},
+{3, "Data Encipherment", "dataEncipherment"},
+{4, "Key Agreement", "keyAgreement"},
+{5, "Certificate Sign", "keyCertSign"},
+{6, "CRL Sign", "cRLSign"},
+{7, "Encipher Only", "encipherOnly"},
+{8, "Decipher Only", "decipherOnly"},
+{-1, NULL, NULL}
+};
+
+
+
+const X509V3_EXT_METHOD v3_nscert = EXT_BITSTRING(NID_netscape_cert_type, ns_cert_type_table);
+const X509V3_EXT_METHOD v3_key_usage = EXT_BITSTRING(NID_key_usage, key_usage_type_table);
+
+STACK_OF(CONF_VALUE) *i2v_ASN1_BIT_STRING(X509V3_EXT_METHOD *method,
+ ASN1_BIT_STRING *bits, STACK_OF(CONF_VALUE) *ret)
+{
+ const BIT_STRING_BITNAME *bnam;
+ for(bnam =method->usr_data; bnam->lname; bnam++) {
+ if(ASN1_BIT_STRING_get_bit(bits, bnam->bitnum))
+ X509V3_add_value(bnam->lname, NULL, &ret);
+ }
+ return ret;
+}
+
+ASN1_BIT_STRING *v2i_ASN1_BIT_STRING(X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
+{
+ CONF_VALUE *val;
+ ASN1_BIT_STRING *bs;
+ size_t i;
+ const BIT_STRING_BITNAME *bnam;
+ if(!(bs = M_ASN1_BIT_STRING_new())) {
+ OPENSSL_PUT_ERROR(X509V3, v2i_ASN1_BIT_STRING, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ for(i = 0; i < sk_CONF_VALUE_num(nval); i++) {
+ val = sk_CONF_VALUE_value(nval, i);
+ for(bnam = method->usr_data; bnam->lname; bnam++) {
+ if(!strcmp(bnam->sname, val->name) ||
+ !strcmp(bnam->lname, val->name) ) {
+ if(!ASN1_BIT_STRING_set_bit(bs, bnam->bitnum, 1)) {
+ OPENSSL_PUT_ERROR(X509V3, v2i_ASN1_BIT_STRING, ERR_R_MALLOC_FAILURE);
+ M_ASN1_BIT_STRING_free(bs);
+ return NULL;
+ }
+ break;
+ }
+ }
+ if(!bnam->lname) {
+ OPENSSL_PUT_ERROR(X509V3, v2i_ASN1_BIT_STRING, X509V3_R_UNKNOWN_BIT_STRING_ARGUMENT);
+ X509V3_conf_err(val);
+ M_ASN1_BIT_STRING_free(bs);
+ return NULL;
+ }
+ }
+ return bs;
+}
+
+
diff --git a/src/crypto/x509v3/v3_conf.c b/src/crypto/x509v3/v3_conf.c
new file mode 100644
index 0000000..7606ac1
--- /dev/null
+++ b/src/crypto/x509v3/v3_conf.c
@@ -0,0 +1,529 @@
+/* v3_conf.c */
+/* 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 <ctype.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <openssl/conf.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+
+
+static int v3_check_critical(char **value);
+static int v3_check_generic(char **value);
+static X509_EXTENSION *do_ext_nconf(CONF *conf, X509V3_CTX *ctx, int ext_nid, int crit, char *value);
+static X509_EXTENSION *v3_generic_extension(const char *ext, char *value, int crit, int type, X509V3_CTX *ctx);
+static X509_EXTENSION *do_ext_i2d(const X509V3_EXT_METHOD *method, int ext_nid,
+ int crit, void *ext_struc);
+static unsigned char *generic_asn1(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, char *name,
+ 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)
+ {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_EXT_nconf, X509V3_R_ERROR_IN_EXTENSION);
+ ERR_add_error_data(4,"name=", name, ", value=", value);
+ }
+ return ret;
+ }
+
+/* CONF *conf: Config file */
+/* char *value: Value */
+X509_EXTENSION *X509V3_EXT_nconf_nid(CONF *conf, X509V3_CTX *ctx, int ext_nid,
+ char *value)
+ {
+ int crit;
+ int ext_type;
+ crit = v3_check_critical(&value);
+ if ((ext_type = v3_check_generic(&value)))
+ return v3_generic_extension(OBJ_nid2sn(ext_nid),
+ value, crit, ext_type, ctx);
+ return do_ext_nconf(conf, ctx, ext_nid, crit, value);
+ }
+
+/* CONF *conf: Config file */
+/* char *value: Value */
+static X509_EXTENSION *do_ext_nconf(CONF *conf, X509V3_CTX *ctx, int ext_nid,
+ int crit, char *value)
+ {
+ const X509V3_EXT_METHOD *method;
+ X509_EXTENSION *ext;
+ STACK_OF(CONF_VALUE) *nval;
+ void *ext_struc;
+ if (ext_nid == NID_undef)
+ {
+ OPENSSL_PUT_ERROR(X509V3, do_ext_nconf, X509V3_R_UNKNOWN_EXTENSION_NAME);
+ return NULL;
+ }
+ if (!(method = X509V3_EXT_get_nid(ext_nid)))
+ {
+ OPENSSL_PUT_ERROR(X509V3, do_ext_nconf, X509V3_R_UNKNOWN_EXTENSION);
+ return NULL;
+ }
+ /* Now get internal extension representation based on type */
+ if (method->v2i)
+ {
+ if(*value == '@') nval = NCONF_get_section(conf, value + 1);
+ else nval = X509V3_parse_list(value);
+ if(sk_CONF_VALUE_num(nval) <= 0)
+ {
+ OPENSSL_PUT_ERROR(X509V3, do_ext_nconf, X509V3_R_INVALID_EXTENSION_STRING);
+ ERR_add_error_data(4, "name=", OBJ_nid2sn(ext_nid), ",section=", value);
+ return NULL;
+ }
+ ext_struc = method->v2i(method, ctx, nval);
+ if(*value != '@') sk_CONF_VALUE_pop_free(nval,
+ X509V3_conf_free);
+ if(!ext_struc) return NULL;
+ }
+ else if(method->s2i)
+ {
+ if(!(ext_struc = method->s2i(method, ctx, value))) return NULL;
+ }
+ else if(method->r2i)
+ {
+ if(!ctx->db || !ctx->db_meth)
+ {
+ OPENSSL_PUT_ERROR(X509V3, do_ext_nconf, X509V3_R_NO_CONFIG_DATABASE);
+ return NULL;
+ }
+ if(!(ext_struc = method->r2i(method, ctx, value))) return NULL;
+ }
+ else
+ {
+ OPENSSL_PUT_ERROR(X509V3, do_ext_nconf, X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED);
+ ERR_add_error_data(2, "name=", OBJ_nid2sn(ext_nid));
+ return NULL;
+ }
+
+ ext = do_ext_i2d(method, ext_nid, crit, ext_struc);
+ if(method->it) ASN1_item_free(ext_struc, ASN1_ITEM_ptr(method->it));
+ else method->ext_free(ext_struc);
+ return ext;
+
+ }
+
+static X509_EXTENSION *do_ext_i2d(const X509V3_EXT_METHOD *method, int ext_nid,
+ int crit, void *ext_struc)
+ {
+ unsigned char *ext_der;
+ int ext_len;
+ ASN1_OCTET_STRING *ext_oct;
+ X509_EXTENSION *ext;
+ /* Convert internal representation to DER */
+ if (method->it)
+ {
+ ext_der = NULL;
+ ext_len = ASN1_item_i2d(ext_struc, &ext_der, ASN1_ITEM_ptr(method->it));
+ if (ext_len < 0) goto merr;
+ }
+ else
+ {
+ unsigned char *p;
+ ext_len = method->i2d(ext_struc, NULL);
+ if(!(ext_der = OPENSSL_malloc(ext_len))) goto merr;
+ p = ext_der;
+ method->i2d(ext_struc, &p);
+ }
+ if (!(ext_oct = M_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;
+ M_ASN1_OCTET_STRING_free(ext_oct);
+
+ return ext;
+
+ merr:
+ OPENSSL_PUT_ERROR(X509V3, do_ext_i2d, 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))) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_EXT_i2d, X509V3_R_UNKNOWN_EXTENSION);
+ return NULL;
+ }
+ return do_ext_i2d(method, ext_nid, crit, ext_struc);
+}
+
+/* Check the extension string for critical flag */
+static int v3_check_critical(char **value)
+{
+ 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(char **value)
+{
+ int gen_type = 0;
+ 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, char *value,
+ int crit, int gen_type,
+ X509V3_CTX *ctx)
+ {
+ unsigned char *ext_der=NULL;
+ long ext_len;
+ ASN1_OBJECT *obj=NULL;
+ ASN1_OCTET_STRING *oct=NULL;
+ X509_EXTENSION *extension=NULL;
+ if (!(obj = OBJ_txt2obj(ext, 0)))
+ {
+ OPENSSL_PUT_ERROR(X509V3, v3_generic_extension, X509V3_R_EXTENSION_NAME_ERROR);
+ ERR_add_error_data(2, "name=", 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);
+
+ if (ext_der == NULL)
+ {
+ OPENSSL_PUT_ERROR(X509V3, v3_generic_extension, X509V3_R_EXTENSION_VALUE_ERROR);
+ ERR_add_error_data(2, "value=", value);
+ goto err;
+ }
+
+ if (!(oct = M_ASN1_OCTET_STRING_new()))
+ {
+ OPENSSL_PUT_ERROR(X509V3, v3_generic_extension, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ oct->data = ext_der;
+ oct->length = ext_len;
+ ext_der = NULL;
+
+ extension = X509_EXTENSION_create_by_OBJ(NULL, obj, crit, oct);
+
+ err:
+ ASN1_OBJECT_free(obj);
+ M_ASN1_OCTET_STRING_free(oct);
+ if(ext_der) OPENSSL_free(ext_der);
+ return extension;
+
+ }
+
+static unsigned char *generic_asn1(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, char *section,
+ STACK_OF(X509_EXTENSION) **sk)
+ {
+ X509_EXTENSION *ext;
+ STACK_OF(CONF_VALUE) *nval;
+ CONF_VALUE *val;
+ size_t 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;
+ }
+
+/* Convenience functions to add extensions to a certificate, CRL and request */
+
+int X509V3_EXT_add_nconf(CONF *conf, X509V3_CTX *ctx, char *section,
+ X509 *cert)
+ {
+ STACK_OF(X509_EXTENSION) **sk = NULL;
+ if (cert)
+ sk = &cert->cert_info->extensions;
+ return X509V3_EXT_add_nconf_sk(conf, ctx, section, sk);
+ }
+
+/* Same as above but for a CRL */
+
+int X509V3_EXT_CRL_add_nconf(CONF *conf, X509V3_CTX *ctx, char *section,
+ X509_CRL *crl)
+ {
+ STACK_OF(X509_EXTENSION) **sk = NULL;
+ if (crl)
+ sk = &crl->crl->extensions;
+ return X509V3_EXT_add_nconf_sk(conf, ctx, section, sk);
+ }
+
+/* Add extensions to certificate request */
+
+int X509V3_EXT_REQ_add_nconf(CONF *conf, X509V3_CTX *ctx, char *section,
+ X509_REQ *req)
+ {
+ STACK_OF(X509_EXTENSION) *extlist = NULL, **sk = NULL;
+ int i;
+ if (req)
+ sk = &extlist;
+ i = X509V3_EXT_add_nconf_sk(conf, ctx, section, sk);
+ if (!i || !sk)
+ return i;
+ i = X509_REQ_add_extensions(req, extlist);
+ sk_X509_EXTENSION_pop_free(extlist, X509_EXTENSION_free);
+ return i;
+ }
+
+/* Config database functions */
+
+char * X509V3_get_string(X509V3_CTX *ctx, char *name, char *section)
+ {
+ if(!ctx->db || !ctx->db_meth || !ctx->db_meth->get_string)
+ {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_get_string, X509V3_R_OPERATION_NOT_DEFINED);
+ return NULL;
+ }
+ if (ctx->db_meth->get_string)
+ return ctx->db_meth->get_string(ctx->db, name, section);
+ return NULL;
+ }
+
+STACK_OF(CONF_VALUE) * X509V3_get_section(X509V3_CTX *ctx, char *section)
+ {
+ if(!ctx->db || !ctx->db_meth || !ctx->db_meth->get_section)
+ {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_get_section, X509V3_R_OPERATION_NOT_DEFINED);
+ return NULL;
+ }
+ if (ctx->db_meth->get_section)
+ return ctx->db_meth->get_section(ctx->db, section);
+ return NULL;
+ }
+
+void X509V3_string_free(X509V3_CTX *ctx, char *str)
+ {
+ if (!str) return;
+ if (ctx->db_meth->free_string)
+ ctx->db_meth->free_string(ctx->db, str);
+ }
+
+void X509V3_section_free(X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *section)
+ {
+ if (!section) return;
+ if (ctx->db_meth->free_section)
+ ctx->db_meth->free_section(ctx->db, section);
+ }
+
+static char *nconf_get_string(void *db, char *section, char *value)
+ {
+ /* TODO(fork): this should return a const value. */
+ return (char *) NCONF_get_string(db, section, value);
+ }
+
+static STACK_OF(CONF_VALUE) *nconf_get_section(void *db, char *section)
+ {
+ return NCONF_get_section(db, section);
+ }
+
+static const X509V3_CONF_METHOD nconf_method = {
+nconf_get_string,
+nconf_get_section,
+NULL,
+NULL
+};
+
+void X509V3_set_nconf(X509V3_CTX *ctx, CONF *conf)
+ {
+ ctx->db_meth = &nconf_method;
+ ctx->db = conf;
+ }
+
+void X509V3_set_ctx(X509V3_CTX *ctx, X509 *issuer, X509 *subj, X509_REQ *req,
+ X509_CRL *crl, int flags)
+ {
+ ctx->issuer_cert = issuer;
+ ctx->subject_cert = subj;
+ ctx->crl = crl;
+ ctx->subject_req = req;
+ ctx->flags = flags;
+ }
+
+/* TODO(fork): remove */
+#if 0
+/* Old conf compatibility functions */
+
+X509_EXTENSION *X509V3_EXT_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx,
+ char *name, char *value)
+ {
+ CONF ctmp;
+ CONF_set_nconf(&ctmp, conf);
+ return X509V3_EXT_nconf(&ctmp, ctx, name, value);
+ }
+
+/* LHASH *conf: Config file */
+/* char *value: Value */
+X509_EXTENSION *X509V3_EXT_conf_nid(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx,
+ int ext_nid, char *value)
+ {
+ CONF ctmp;
+ CONF_set_nconf(&ctmp, conf);
+ return X509V3_EXT_nconf_nid(&ctmp, ctx, ext_nid, value);
+ }
+
+static char *conf_lhash_get_string(void *db, char *section, char *value)
+ {
+ return CONF_get_string(db, section, value);
+ }
+
+static STACK_OF(CONF_VALUE) *conf_lhash_get_section(void *db, char *section)
+ {
+ return CONF_get_section(db, section);
+ }
+
+static const X509V3_CONF_METHOD conf_lhash_method = {
+conf_lhash_get_string,
+conf_lhash_get_section,
+NULL,
+NULL
+};
+
+void X509V3_set_conf_lhash(X509V3_CTX *ctx, LHASH_OF(CONF_VALUE) *lhash)
+ {
+ ctx->db_meth = &conf_lhash_method;
+ ctx->db = lhash;
+ }
+
+int X509V3_EXT_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx,
+ char *section, X509 *cert)
+ {
+ CONF ctmp;
+ CONF_set_nconf(&ctmp, conf);
+ return X509V3_EXT_add_nconf(&ctmp, ctx, section, cert);
+ }
+
+/* Same as above but for a CRL */
+
+int X509V3_EXT_CRL_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx,
+ char *section, X509_CRL *crl)
+ {
+ CONF ctmp;
+ CONF_set_nconf(&ctmp, conf);
+ return X509V3_EXT_CRL_add_nconf(&ctmp, ctx, section, crl);
+ }
+
+/* Add extensions to certificate request */
+
+int X509V3_EXT_REQ_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx,
+ char *section, X509_REQ *req)
+ {
+ CONF ctmp;
+ CONF_set_nconf(&ctmp, conf);
+ return X509V3_EXT_REQ_add_nconf(&ctmp, ctx, section, req);
+ }
+#endif
diff --git a/src/crypto/x509v3/v3_cpols.c b/src/crypto/x509v3/v3_cpols.c
new file mode 100644
index 0000000..d5a8c3c
--- /dev/null
+++ b/src/crypto/x509v3/v3_cpols.c
@@ -0,0 +1,461 @@
+/* v3_cpols.c */
+/* 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 <stdio.h>
+#include <string.h>
+
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/conf.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/stack.h>
+#include <openssl/x509v3.h>
+
+#include "pcy_int.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 = {
+NID_certificate_policies, 0,ASN1_ITEM_ref(CERTIFICATEPOLICIES),
+0,0,0,0,
+0,0,
+0,0,
+(X509V3_EXT_I2R)i2r_certpol,
+(X509V3_EXT_R2I)r2i_certpol,
+NULL
+};
+
+ASN1_ITEM_TEMPLATE(CERTIFICATEPOLICIES) =
+ ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, CERTIFICATEPOLICIES, POLICYINFO)
+ASN1_ITEM_TEMPLATE_END(CERTIFICATEPOLICIES)
+
+IMPLEMENT_ASN1_FUNCTIONS(CERTIFICATEPOLICIES)
+
+ASN1_SEQUENCE(POLICYINFO) = {
+ ASN1_SIMPLE(POLICYINFO, policyid, ASN1_OBJECT),
+ ASN1_SEQUENCE_OF_OPT(POLICYINFO, qualifiers, POLICYQUALINFO)
+} ASN1_SEQUENCE_END(POLICYINFO)
+
+IMPLEMENT_ASN1_FUNCTIONS(POLICYINFO)
+
+ASN1_ADB_TEMPLATE(policydefault) = ASN1_SIMPLE(POLICYQUALINFO, d.other, ASN1_ANY);
+
+ASN1_ADB(POLICYQUALINFO) = {
+ ADB_ENTRY(NID_id_qt_cps, ASN1_SIMPLE(POLICYQUALINFO, d.cpsuri, ASN1_IA5STRING)),
+ ADB_ENTRY(NID_id_qt_unotice, ASN1_SIMPLE(POLICYQUALINFO, d.usernotice, USERNOTICE))
+} ASN1_ADB_END(POLICYQUALINFO, 0, pqualid, 0, &policydefault_tt, NULL);
+
+ASN1_SEQUENCE(POLICYQUALINFO) = {
+ ASN1_SIMPLE(POLICYQUALINFO, pqualid, ASN1_OBJECT),
+ ASN1_ADB_OBJECT(POLICYQUALINFO)
+} ASN1_SEQUENCE_END(POLICYQUALINFO)
+
+IMPLEMENT_ASN1_FUNCTIONS(POLICYQUALINFO)
+
+ASN1_SEQUENCE(USERNOTICE) = {
+ ASN1_OPT(USERNOTICE, noticeref, NOTICEREF),
+ ASN1_OPT(USERNOTICE, exptext, DISPLAYTEXT)
+} ASN1_SEQUENCE_END(USERNOTICE)
+
+IMPLEMENT_ASN1_FUNCTIONS(USERNOTICE)
+
+ASN1_SEQUENCE(NOTICEREF) = {
+ ASN1_SIMPLE(NOTICEREF, organization, DISPLAYTEXT),
+ ASN1_SEQUENCE_OF(NOTICEREF, noticenos, ASN1_INTEGER)
+} ASN1_SEQUENCE_END(NOTICEREF)
+
+IMPLEMENT_ASN1_FUNCTIONS(NOTICEREF)
+
+static STACK_OF(POLICYINFO) *r2i_certpol(X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, char *value)
+{
+ STACK_OF(POLICYINFO) *pols = NULL;
+ char *pstr;
+ POLICYINFO *pol;
+ ASN1_OBJECT *pobj;
+ STACK_OF(CONF_VALUE) *vals;
+ CONF_VALUE *cnf;
+ size_t i;
+ int ia5org;
+ pols = sk_POLICYINFO_new_null();
+ if (pols == NULL) {
+ OPENSSL_PUT_ERROR(X509V3, r2i_certpol, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ vals = X509V3_parse_list(value);
+ if (vals == NULL) {
+ OPENSSL_PUT_ERROR(X509V3, r2i_certpol, 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 ) {
+ OPENSSL_PUT_ERROR(X509V3, r2i_certpol, 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) {
+ OPENSSL_PUT_ERROR(X509V3, r2i_certpol, X509V3_R_INVALID_SECTION);
+
+ X509V3_conf_err(cnf);
+ goto err;
+ }
+ pol = policy_section(ctx, polsect, ia5org);
+ X509V3_section_free(ctx, polsect);
+ if(!pol) goto err;
+ } else {
+ if(!(pobj = OBJ_txt2obj(cnf->name, 0))) {
+ OPENSSL_PUT_ERROR(X509V3, r2i_certpol, 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);
+ OPENSSL_PUT_ERROR(X509V3, r2i_certpol, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+ sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
+ return pols;
+ err:
+ sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
+ sk_POLICYINFO_pop_free(pols, POLICYINFO_free);
+ return NULL;
+}
+
+static POLICYINFO *policy_section(X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE) *polstrs, int ia5org)
+{
+ size_t i;
+ CONF_VALUE *cnf;
+ POLICYINFO *pol;
+ POLICYQUALINFO *qual;
+ if(!(pol = POLICYINFO_new())) goto merr;
+ for(i = 0; i < sk_CONF_VALUE_num(polstrs); i++) {
+ cnf = sk_CONF_VALUE_value(polstrs, i);
+ if(!strcmp(cnf->name, "policyIdentifier")) {
+ ASN1_OBJECT *pobj;
+ if(!(pobj = OBJ_txt2obj(cnf->value, 0))) {
+ OPENSSL_PUT_ERROR(X509V3, policy_section, X509V3_R_INVALID_OBJECT_IDENTIFIER);
+ X509V3_conf_err(cnf);
+ goto err;
+ }
+ pol->policyid = pobj;
+
+ } else if(!name_cmp(cnf->name, "CPS")) {
+ if(!pol->qualifiers) pol->qualifiers =
+ sk_POLICYQUALINFO_new_null();
+ if(!(qual = POLICYQUALINFO_new())) goto merr;
+ if(!sk_POLICYQUALINFO_push(pol->qualifiers, qual))
+ goto merr;
+ /* TODO(fork): const correctness */
+ qual->pqualid = (ASN1_OBJECT*) OBJ_nid2obj(NID_id_qt_cps);
+ qual->d.cpsuri = M_ASN1_IA5STRING_new();
+ if(!ASN1_STRING_set(qual->d.cpsuri, cnf->value,
+ strlen(cnf->value))) goto merr;
+ } else if(!name_cmp(cnf->name, "userNotice")) {
+ STACK_OF(CONF_VALUE) *unot;
+ if(*cnf->value != '@') {
+ OPENSSL_PUT_ERROR(X509V3, policy_section, X509V3_R_EXPECTED_A_SECTION_NAME);
+ X509V3_conf_err(cnf);
+ goto err;
+ }
+ unot = X509V3_get_section(ctx, cnf->value + 1);
+ if(!unot) {
+ OPENSSL_PUT_ERROR(X509V3, policy_section, X509V3_R_INVALID_SECTION);
+
+ X509V3_conf_err(cnf);
+ goto err;
+ }
+ qual = notice_section(ctx, unot, ia5org);
+ X509V3_section_free(ctx, unot);
+ if(!qual) goto err;
+ if(!pol->qualifiers) pol->qualifiers =
+ sk_POLICYQUALINFO_new_null();
+ if(!sk_POLICYQUALINFO_push(pol->qualifiers, qual))
+ goto merr;
+ } else {
+ OPENSSL_PUT_ERROR(X509V3, policy_section, X509V3_R_INVALID_OPTION);
+
+ X509V3_conf_err(cnf);
+ goto err;
+ }
+ }
+ if(!pol->policyid) {
+ OPENSSL_PUT_ERROR(X509V3, policy_section, X509V3_R_NO_POLICY_IDENTIFIER);
+ goto err;
+ }
+
+ return pol;
+
+ merr:
+ OPENSSL_PUT_ERROR(X509V3, policy_section, ERR_R_MALLOC_FAILURE);
+
+ err:
+ POLICYINFO_free(pol);
+ return NULL;
+
+
+}
+
+static POLICYQUALINFO *notice_section(X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE) *unot, int ia5org)
+{
+ size_t i;
+ int ret;
+ CONF_VALUE *cnf;
+ USERNOTICE *not;
+ POLICYQUALINFO *qual;
+ if(!(qual = POLICYQUALINFO_new())) goto merr;
+ /* TODO(fork): const correctness */
+ qual->pqualid = (ASN1_OBJECT *) 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")) {
+ not->exptext = M_ASN1_VISIBLESTRING_new();
+ 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)) {
+ OPENSSL_PUT_ERROR(X509V3, notice_section, X509V3_R_INVALID_NUMBERS);
+ X509V3_conf_err(cnf);
+ goto err;
+ }
+ ret = nref_nos(nref->noticenos, nos);
+ sk_CONF_VALUE_pop_free(nos, X509V3_conf_free);
+ if (!ret)
+ goto err;
+ } else {
+ OPENSSL_PUT_ERROR(X509V3, notice_section, X509V3_R_INVALID_OPTION);
+ X509V3_conf_err(cnf);
+ goto err;
+ }
+ }
+
+ if(not->noticeref &&
+ (!not->noticeref->noticenos || !not->noticeref->organization)) {
+ OPENSSL_PUT_ERROR(X509V3, notice_section, X509V3_R_NEED_ORGANIZATION_AND_NUMBERS);
+ goto err;
+ }
+
+ return qual;
+
+ merr:
+ OPENSSL_PUT_ERROR(X509V3, notice_section, ERR_R_MALLOC_FAILURE);
+
+ err:
+ POLICYQUALINFO_free(qual);
+ return NULL;
+}
+
+static int nref_nos(STACK_OF(ASN1_INTEGER) *nnums, STACK_OF(CONF_VALUE) *nos)
+{
+ CONF_VALUE *cnf;
+ ASN1_INTEGER *aint;
+
+ size_t 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))) {
+ OPENSSL_PUT_ERROR(X509V3, nref_nos, X509V3_R_INVALID_NUMBER);
+ goto err;
+ }
+ if(!sk_ASN1_INTEGER_push(nnums, aint)) goto merr;
+ }
+ return 1;
+
+ merr:
+ OPENSSL_PUT_ERROR(X509V3, nref_nos, 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)
+{
+ size_t 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;
+ size_t 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->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)
+{
+ size_t i;
+ if(notice->noticeref) {
+ NOTICEREF *ref;
+ ref = notice->noticeref;
+ BIO_printf(out, "%*sOrganization: %s\n", indent, "",
+ 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);
+ OPENSSL_free(tmp);
+ }
+ BIO_puts(out, "\n");
+ }
+ if(notice->exptext)
+ BIO_printf(out, "%*sExplicit Text: %s\n", indent, "",
+ notice->exptext->data);
+}
+
+void X509_POLICY_NODE_print(BIO *out, X509_POLICY_NODE *node, int indent)
+ {
+ const X509_POLICY_DATA *dat = node->data;
+
+ BIO_printf(out, "%*sPolicy: ", indent, "");
+
+ i2a_ASN1_OBJECT(out, dat->valid_policy);
+ BIO_puts(out, "\n");
+ BIO_printf(out, "%*s%s\n", indent + 2, "",
+ node_data_critical(dat) ? "Critical" : "Non Critical");
+ if (dat->qualifier_set)
+ print_qualifiers(out, dat->qualifier_set, indent + 2);
+ else
+ BIO_printf(out, "%*sNo Qualifiers\n", indent + 2, "");
+ }
diff --git a/src/crypto/x509v3/v3_crld.c b/src/crypto/x509v3/v3_crld.c
new file mode 100644
index 0000000..e41dd65
--- /dev/null
+++ b/src/crypto/x509v3/v3_crld.c
@@ -0,0 +1,616 @@
+/* v3_crld.c */
+/* 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 <stdio.h>
+#include <string.h>
+
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/conf.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/x509v3.h>
+
+
+static void *v2i_crld(const X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
+static int i2r_crldp(const X509V3_EXT_METHOD *method, void *pcrldp, BIO *out,
+ int indent);
+
+const X509V3_EXT_METHOD v3_crld =
+ {
+ NID_crl_distribution_points, 0, ASN1_ITEM_ref(CRL_DIST_POINTS),
+ 0,0,0,0,
+ 0,0,
+ 0,
+ v2i_crld,
+ i2r_crldp,0,
+ NULL
+ };
+
+const X509V3_EXT_METHOD v3_freshest_crl =
+ {
+ NID_freshest_crl, 0, ASN1_ITEM_ref(CRL_DIST_POINTS),
+ 0,0,0,0,
+ 0,0,
+ 0,
+ v2i_crld,
+ i2r_crldp,0,
+ NULL
+ };
+
+static STACK_OF(GENERAL_NAME) *gnames_from_sectname(X509V3_CTX *ctx, char *sect)
+ {
+ STACK_OF(CONF_VALUE) *gnsect;
+ STACK_OF(GENERAL_NAME) *gens;
+ if (*sect == '@')
+ gnsect = X509V3_get_section(ctx, sect + 1);
+ else
+ gnsect = X509V3_parse_list(sect);
+ if (!gnsect)
+ {
+ OPENSSL_PUT_ERROR(X509V3, gnames_from_sectname, X509V3_R_SECTION_NOT_FOUND);
+ return NULL;
+ }
+ gens = v2i_GENERAL_NAMES(NULL, ctx, gnsect);
+ if (*sect == '@')
+ X509V3_section_free(ctx, gnsect);
+ else
+ sk_CONF_VALUE_pop_free(gnsect, X509V3_conf_free);
+ return gens;
+ }
+
+static int set_dist_point_name(DIST_POINT_NAME **pdp, X509V3_CTX *ctx,
+ CONF_VALUE *cnf)
+ {
+ STACK_OF(GENERAL_NAME) *fnm = NULL;
+ STACK_OF(X509_NAME_ENTRY) *rnm = NULL;
+ if (!strncmp(cnf->name, "fullname", 9))
+ {
+ 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)
+ {
+ OPENSSL_PUT_ERROR(X509V3, set_dist_point_name, X509V3_R_SECTION_NOT_FOUND);
+ return -1;
+ }
+ ret = X509V3_NAME_from_section(nm, dnsect, MBSTRING_ASC);
+ X509V3_section_free(ctx, dnsect);
+ rnm = nm->entries;
+ nm->entries = NULL;
+ X509_NAME_free(nm);
+ if (!ret || sk_X509_NAME_ENTRY_num(rnm) <= 0)
+ goto err;
+ /* Since its a name fragment can't have more than one
+ * RDNSequence
+ */
+ if (sk_X509_NAME_ENTRY_value(rnm,
+ sk_X509_NAME_ENTRY_num(rnm) - 1)->set)
+ {
+ OPENSSL_PUT_ERROR(X509V3, set_dist_point_name, X509V3_R_INVALID_MULTIPLE_RDNS);
+ goto err;
+ }
+ }
+ else
+ return 0;
+
+ if (*pdp)
+ {
+ OPENSSL_PUT_ERROR(X509V3, set_dist_point_name, 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:
+ if (fnm)
+ sk_GENERAL_NAME_pop_free(fnm, GENERAL_NAME_free);
+ if (rnm)
+ 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;
+ size_t i;
+ int ret = 0;
+ rsk = X509V3_parse_list(value);
+ if (!rsk)
+ return 0;
+ if (*preas)
+ 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, "<EMPTY>\n");
+ else
+ BIO_puts(out, "\n");
+ return 1;
+ }
+
+static DIST_POINT *crldp_from_section(X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE) *nval)
+ {
+ size_t 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:
+ if (point)
+ 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;
+ size_t 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:
+ OPENSSL_PUT_ERROR(X509V3, v2i_crld, ERR_R_MALLOC_FAILURE);
+ err:
+ GENERAL_NAME_free(gen);
+ GENERAL_NAMES_free(gens);
+ sk_DIST_POINT_pop_free(crld, DIST_POINT_free);
+ return NULL;
+}
+
+IMPLEMENT_ASN1_SET_OF(DIST_POINT)
+
+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;
+ }
+
+
+ASN1_CHOICE_cb(DIST_POINT_NAME, dpn_cb) = {
+ ASN1_IMP_SEQUENCE_OF(DIST_POINT_NAME, name.fullname, GENERAL_NAME, 0),
+ ASN1_IMP_SET_OF(DIST_POINT_NAME, name.relativename, X509_NAME_ENTRY, 1)
+} ASN1_CHOICE_END_cb(DIST_POINT_NAME, DIST_POINT_NAME, type)
+
+
+IMPLEMENT_ASN1_FUNCTIONS(DIST_POINT_NAME)
+
+ASN1_SEQUENCE(DIST_POINT) = {
+ ASN1_EXP_OPT(DIST_POINT, distpoint, DIST_POINT_NAME, 0),
+ ASN1_IMP_OPT(DIST_POINT, reasons, ASN1_BIT_STRING, 1),
+ ASN1_IMP_SEQUENCE_OF_OPT(DIST_POINT, CRLissuer, GENERAL_NAME, 2)
+} ASN1_SEQUENCE_END(DIST_POINT)
+
+IMPLEMENT_ASN1_FUNCTIONS(DIST_POINT)
+
+ASN1_ITEM_TEMPLATE(CRL_DIST_POINTS) =
+ ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, CRLDistributionPoints, DIST_POINT)
+ASN1_ITEM_TEMPLATE_END(CRL_DIST_POINTS)
+
+IMPLEMENT_ASN1_FUNCTIONS(CRL_DIST_POINTS)
+
+ASN1_SEQUENCE(ISSUING_DIST_POINT) = {
+ ASN1_EXP_OPT(ISSUING_DIST_POINT, distpoint, DIST_POINT_NAME, 0),
+ ASN1_IMP_OPT(ISSUING_DIST_POINT, onlyuser, ASN1_FBOOLEAN, 1),
+ ASN1_IMP_OPT(ISSUING_DIST_POINT, onlyCA, ASN1_FBOOLEAN, 2),
+ ASN1_IMP_OPT(ISSUING_DIST_POINT, onlysomereasons, ASN1_BIT_STRING, 3),
+ ASN1_IMP_OPT(ISSUING_DIST_POINT, indirectCRL, ASN1_FBOOLEAN, 4),
+ ASN1_IMP_OPT(ISSUING_DIST_POINT, onlyattr, ASN1_FBOOLEAN, 5)
+} ASN1_SEQUENCE_END(ISSUING_DIST_POINT)
+
+IMPLEMENT_ASN1_FUNCTIONS(ISSUING_DIST_POINT)
+
+static int i2r_idp(const X509V3_EXT_METHOD *method, void *pidp, BIO *out,
+ int indent);
+static void *v2i_idp(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE) *nval);
+
+const X509V3_EXT_METHOD v3_idp =
+ {
+ NID_issuing_distribution_point, X509V3_EXT_MULTILINE,
+ ASN1_ITEM_ref(ISSUING_DIST_POINT),
+ 0,0,0,0,
+ 0,0,
+ 0,
+ v2i_idp,
+ i2r_idp,0,
+ NULL
+ };
+
+static void *v2i_idp(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE) *nval)
+ {
+ ISSUING_DIST_POINT *idp = NULL;
+ CONF_VALUE *cnf;
+ char *name, *val;
+ size_t i;
+ int 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
+ {
+ OPENSSL_PUT_ERROR(X509V3, v2i_idp, X509V3_R_INVALID_NAME);
+ X509V3_conf_err(cnf);
+ goto err;
+ }
+ }
+ return idp;
+
+ merr:
+ OPENSSL_PUT_ERROR(X509V3, v2i_idp, ERR_R_MALLOC_FAILURE);
+ err:
+ ISSUING_DIST_POINT_free(idp);
+ return NULL;
+ }
+
+static int print_gens(BIO *out, STACK_OF(GENERAL_NAME) *gens, int indent)
+ {
+ size_t i;
+ for (i = 0; i < sk_GENERAL_NAME_num(gens); i++)
+ {
+ BIO_printf(out, "%*s", indent + 2, "");
+ GENERAL_NAME_print(out, sk_GENERAL_NAME_value(gens, i));
+ BIO_puts(out, "\n");
+ }
+ return 1;
+ }
+
+static int print_distpoint(BIO *out, DIST_POINT_NAME *dpn, int indent)
+ {
+ if (dpn->type == 0)
+ {
+ BIO_printf(out, "%*sFull Name:\n", indent, "");
+ print_gens(out, dpn->name.fullname, indent);
+ }
+ else
+ {
+ X509_NAME ntmp;
+ ntmp.entries = dpn->name.relativename;
+ BIO_printf(out, "%*sRelative Name:\n%*s",
+ indent, "", indent + 2, "");
+ X509_NAME_print_ex(out, &ntmp, 0, XN_FLAG_ONELINE);
+ BIO_puts(out, "\n");
+ }
+ return 1;
+ }
+
+static int i2r_idp(const X509V3_EXT_METHOD *method, void *pidp, BIO *out,
+ int indent)
+ {
+ ISSUING_DIST_POINT *idp = pidp;
+ if (idp->distpoint)
+ print_distpoint(out, idp->distpoint, indent);
+ if (idp->onlyuser > 0)
+ BIO_printf(out, "%*sOnly User Certificates\n", indent, "");
+ if (idp->onlyCA > 0)
+ BIO_printf(out, "%*sOnly CA Certificates\n", indent, "");
+ if (idp->indirectCRL > 0)
+ BIO_printf(out, "%*sIndirect CRL\n", indent, "");
+ if (idp->onlysomereasons)
+ print_reasons(out, "Only Some Reasons",
+ idp->onlysomereasons, indent);
+ if (idp->onlyattr > 0)
+ BIO_printf(out, "%*sOnly Attribute Certificates\n", indent, "");
+ if (!idp->distpoint && (idp->onlyuser <= 0) && (idp->onlyCA <= 0)
+ && (idp->indirectCRL <= 0) && !idp->onlysomereasons
+ && (idp->onlyattr <= 0))
+ BIO_printf(out, "%*s<EMPTY>\n", indent, "");
+
+ return 1;
+ }
+
+static int i2r_crldp(const X509V3_EXT_METHOD *method, void *pcrldp, BIO *out,
+ int indent)
+ {
+ STACK_OF(DIST_POINT) *crld = pcrldp;
+ DIST_POINT *point;
+ size_t 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)
+ {
+ size_t i;
+ STACK_OF(X509_NAME_ENTRY) *frag;
+ X509_NAME_ENTRY *ne;
+ if (!dpn || (dpn->type != 1))
+ return 1;
+ frag = dpn->name.relativename;
+ dpn->dpname = X509_NAME_dup(iname);
+ if (!dpn->dpname)
+ return 0;
+ for (i = 0; i < sk_X509_NAME_ENTRY_num(frag); i++)
+ {
+ ne = sk_X509_NAME_ENTRY_value(frag, i);
+ if (!X509_NAME_add_entry(dpn->dpname, ne, -1, i ? 0 : 1))
+ {
+ X509_NAME_free(dpn->dpname);
+ dpn->dpname = NULL;
+ return 0;
+ }
+ }
+ /* generate cached encoding of name */
+ if (i2d_X509_NAME(dpn->dpname, NULL) < 0)
+ {
+ X509_NAME_free(dpn->dpname);
+ dpn->dpname = NULL;
+ return 0;
+ }
+ return 1;
+ }
diff --git a/src/crypto/x509v3/v3_enum.c b/src/crypto/x509v3/v3_enum.c
new file mode 100644
index 0000000..0fe6bb6
--- /dev/null
+++ b/src/crypto/x509v3/v3_enum.c
@@ -0,0 +1,98 @@
+/* v3_enum.c */
+/* 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 <stdio.h>
+
+#include <openssl/buf.h>
+#include <openssl/obj.h>
+#include <openssl/x509v3.h>
+
+
+static const ENUMERATED_NAMES crl_reasons[] = {
+{CRL_REASON_UNSPECIFIED, "Unspecified", "unspecified"},
+{CRL_REASON_KEY_COMPROMISE, "Key Compromise", "keyCompromise"},
+{CRL_REASON_CA_COMPROMISE, "CA Compromise", "CACompromise"},
+{CRL_REASON_AFFILIATION_CHANGED, "Affiliation Changed", "affiliationChanged"},
+{CRL_REASON_SUPERSEDED, "Superseded", "superseded"},
+{CRL_REASON_CESSATION_OF_OPERATION,
+ "Cessation Of Operation", "cessationOfOperation"},
+{CRL_REASON_CERTIFICATE_HOLD, "Certificate Hold", "certificateHold"},
+{CRL_REASON_REMOVE_FROM_CRL, "Remove From CRL", "removeFromCRL"},
+{CRL_REASON_PRIVILEGE_WITHDRAWN, "Privilege Withdrawn", "privilegeWithdrawn"},
+{CRL_REASON_AA_COMPROMISE, "AA Compromise", "AACompromise"},
+{-1, NULL, NULL}
+};
+
+const X509V3_EXT_METHOD v3_crl_reason = {
+NID_crl_reason, 0, ASN1_ITEM_ref(ASN1_ENUMERATED),
+0,0,0,0,
+(X509V3_EXT_I2S)i2s_ASN1_ENUMERATED_TABLE,
+0,
+0,0,0,0,
+(void *)crl_reasons};
+
+
+char *i2s_ASN1_ENUMERATED_TABLE(X509V3_EXT_METHOD *method,
+ ASN1_ENUMERATED *e)
+{
+ const ENUMERATED_NAMES *enam;
+ long strval;
+ strval = ASN1_ENUMERATED_get(e);
+ for(enam = method->usr_data; enam->lname; enam++) {
+ if(strval == enam->bitnum) return BUF_strdup(enam->lname);
+ }
+ return i2s_ASN1_ENUMERATED(method, e);
+}
diff --git a/src/crypto/x509v3/v3_extku.c b/src/crypto/x509v3/v3_extku.c
new file mode 100644
index 0000000..f4b8af8
--- /dev/null
+++ b/src/crypto/x509v3/v3_extku.c
@@ -0,0 +1,145 @@
+/* v3_extku.c */
+/* 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 <stdio.h>
+
+#include <openssl/asn1t.h>
+#include <openssl/conf.h>
+#include <openssl/err.h>
+#include <openssl/obj.h>
+#include <openssl/x509v3.h>
+
+
+static void *v2i_EXTENDED_KEY_USAGE(const X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE) *nval);
+static STACK_OF(CONF_VALUE) *i2v_EXTENDED_KEY_USAGE(const X509V3_EXT_METHOD *method,
+ void *eku, STACK_OF(CONF_VALUE) *extlist);
+
+const X509V3_EXT_METHOD v3_ext_ku = {
+ NID_ext_key_usage, 0,
+ ASN1_ITEM_ref(EXTENDED_KEY_USAGE),
+ 0,0,0,0,
+ 0,0,
+ i2v_EXTENDED_KEY_USAGE,
+ v2i_EXTENDED_KEY_USAGE,
+ 0,0,
+ NULL
+};
+
+/* NB OCSP acceptable responses also is a SEQUENCE OF OBJECT */
+const X509V3_EXT_METHOD v3_ocsp_accresp = {
+ NID_id_pkix_OCSP_acceptableResponses, 0,
+ ASN1_ITEM_ref(EXTENDED_KEY_USAGE),
+ 0,0,0,0,
+ 0,0,
+ i2v_EXTENDED_KEY_USAGE,
+ v2i_EXTENDED_KEY_USAGE,
+ 0,0,
+ NULL
+};
+
+ASN1_ITEM_TEMPLATE(EXTENDED_KEY_USAGE) =
+ ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, EXTENDED_KEY_USAGE, ASN1_OBJECT)
+ASN1_ITEM_TEMPLATE_END(EXTENDED_KEY_USAGE)
+
+IMPLEMENT_ASN1_FUNCTIONS(EXTENDED_KEY_USAGE)
+
+static STACK_OF(CONF_VALUE) *
+ i2v_EXTENDED_KEY_USAGE(const X509V3_EXT_METHOD *method, void *a,
+ STACK_OF(CONF_VALUE) *ext_list)
+{
+ EXTENDED_KEY_USAGE *eku = a;
+ size_t i;
+ ASN1_OBJECT *obj;
+ char obj_tmp[80];
+ for(i = 0; i < sk_ASN1_OBJECT_num(eku); i++) {
+ obj = sk_ASN1_OBJECT_value(eku, i);
+ i2t_ASN1_OBJECT(obj_tmp, 80, obj);
+ X509V3_add_value(NULL, obj_tmp, &ext_list);
+ }
+ return ext_list;
+}
+
+static void *v2i_EXTENDED_KEY_USAGE(const X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
+{
+ EXTENDED_KEY_USAGE *extku;
+ char *extval;
+ ASN1_OBJECT *objtmp;
+ CONF_VALUE *val;
+ size_t i;
+
+ if(!(extku = sk_ASN1_OBJECT_new_null())) {
+ OPENSSL_PUT_ERROR(X509V3, v2i_EXTENDED_KEY_USAGE, 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);
+ OPENSSL_PUT_ERROR(X509V3, v2i_EXTENDED_KEY_USAGE, X509V3_R_INVALID_OBJECT_IDENTIFIER);
+ X509V3_conf_err(val);
+ return NULL;
+ }
+ sk_ASN1_OBJECT_push(extku, objtmp);
+ }
+ return extku;
+}
diff --git a/src/crypto/x509v3/v3_genn.c b/src/crypto/x509v3/v3_genn.c
new file mode 100644
index 0000000..8b0a68d
--- /dev/null
+++ b/src/crypto/x509v3/v3_genn.c
@@ -0,0 +1,252 @@
+/* v3_genn.c */
+/* 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 <stdio.h>
+
+#include <openssl/asn1t.h>
+#include <openssl/conf.h>
+#include <openssl/obj.h>
+#include <openssl/x509v3.h>
+
+
+ASN1_SEQUENCE(OTHERNAME) = {
+ ASN1_SIMPLE(OTHERNAME, type_id, ASN1_OBJECT),
+ /* Maybe have a true ANY DEFINED BY later */
+ ASN1_EXP(OTHERNAME, value, ASN1_ANY, 0)
+} ASN1_SEQUENCE_END(OTHERNAME)
+
+IMPLEMENT_ASN1_FUNCTIONS(OTHERNAME)
+
+ASN1_SEQUENCE(EDIPARTYNAME) = {
+ ASN1_IMP_OPT(EDIPARTYNAME, nameAssigner, DIRECTORYSTRING, 0),
+ ASN1_IMP_OPT(EDIPARTYNAME, partyName, DIRECTORYSTRING, 1)
+} ASN1_SEQUENCE_END(EDIPARTYNAME)
+
+IMPLEMENT_ASN1_FUNCTIONS(EDIPARTYNAME)
+
+ASN1_CHOICE(GENERAL_NAME) = {
+ ASN1_IMP(GENERAL_NAME, d.otherName, OTHERNAME, GEN_OTHERNAME),
+ ASN1_IMP(GENERAL_NAME, d.rfc822Name, ASN1_IA5STRING, GEN_EMAIL),
+ ASN1_IMP(GENERAL_NAME, d.dNSName, ASN1_IA5STRING, GEN_DNS),
+ /* Don't decode this */
+ ASN1_IMP(GENERAL_NAME, d.x400Address, ASN1_SEQUENCE, GEN_X400),
+ /* X509_NAME is a CHOICE type so use EXPLICIT */
+ ASN1_EXP(GENERAL_NAME, d.directoryName, X509_NAME, GEN_DIRNAME),
+ ASN1_IMP(GENERAL_NAME, d.ediPartyName, EDIPARTYNAME, GEN_EDIPARTY),
+ ASN1_IMP(GENERAL_NAME, d.uniformResourceIdentifier, ASN1_IA5STRING, GEN_URI),
+ ASN1_IMP(GENERAL_NAME, d.iPAddress, ASN1_OCTET_STRING, GEN_IPADD),
+ ASN1_IMP(GENERAL_NAME, d.registeredID, ASN1_OBJECT, GEN_RID)
+} ASN1_CHOICE_END(GENERAL_NAME)
+
+IMPLEMENT_ASN1_FUNCTIONS(GENERAL_NAME)
+
+ASN1_ITEM_TEMPLATE(GENERAL_NAMES) =
+ ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, GeneralNames, GENERAL_NAME)
+ASN1_ITEM_TEMPLATE_END(GENERAL_NAMES)
+
+IMPLEMENT_ASN1_FUNCTIONS(GENERAL_NAMES)
+
+GENERAL_NAME *GENERAL_NAME_dup(GENERAL_NAME *a)
+ {
+ return (GENERAL_NAME *) ASN1_dup((i2d_of_void *) i2d_GENERAL_NAME,
+ (d2i_of_void *) d2i_GENERAL_NAME,
+ (char *) a);
+ }
+
+/* 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:
+ case GEN_EDIPARTY:
+ result = ASN1_TYPE_cmp(a->d.other, b->d.other);
+ break;
+
+ case GEN_OTHERNAME:
+ result = OTHERNAME_cmp(a->d.otherName, b->d.otherName);
+ break;
+
+ case GEN_EMAIL:
+ case GEN_DNS:
+ case GEN_URI:
+ result = ASN1_STRING_cmp(a->d.ia5, b->d.ia5);
+ break;
+
+ case GEN_DIRNAME:
+ result = X509_NAME_cmp(a->d.dirn, b->d.dirn);
+ break;
+
+ case GEN_IPADD:
+ result = ASN1_OCTET_STRING_cmp(a->d.ip, b->d.ip);
+ break;
+
+ case GEN_RID:
+ result = OBJ_cmp(a->d.rid, b->d.rid);
+ break;
+ }
+ return result;
+ }
+
+/* Returns 0 if they are equal, != 0 otherwise. */
+int OTHERNAME_cmp(OTHERNAME *a, OTHERNAME *b)
+ {
+ int result = -1;
+
+ if (!a || !b) return -1;
+ /* Check their type first. */
+ if ((result = OBJ_cmp(a->type_id, b->type_id)) != 0)
+ return result;
+ /* Check the value. */
+ result = ASN1_TYPE_cmp(a->value, b->value);
+ return result;
+ }
+
+void GENERAL_NAME_set0_value(GENERAL_NAME *a, int type, void *value)
+ {
+ switch(type)
+ {
+ case GEN_X400:
+ case GEN_EDIPARTY:
+ a->d.other = value;
+ break;
+
+ case GEN_OTHERNAME:
+ a->d.otherName = value;
+ break;
+
+ case GEN_EMAIL:
+ case GEN_DNS:
+ case GEN_URI:
+ a->d.ia5 = value;
+ break;
+
+ case GEN_DIRNAME:
+ a->d.dirn = value;
+ break;
+
+ case GEN_IPADD:
+ a->d.ip = value;
+ break;
+
+ case GEN_RID:
+ a->d.rid = value;
+ break;
+ }
+ a->type = type;
+ }
+
+void *GENERAL_NAME_get0_value(GENERAL_NAME *a, int *ptype)
+ {
+ if (ptype)
+ *ptype = a->type;
+ switch(a->type)
+ {
+ case GEN_X400:
+ case GEN_EDIPARTY:
+ return a->d.other;
+
+ case GEN_OTHERNAME:
+ return a->d.otherName;
+
+ case GEN_EMAIL:
+ case GEN_DNS:
+ case GEN_URI:
+ return a->d.ia5;
+
+ case GEN_DIRNAME:
+ return a->d.dirn;
+
+ case GEN_IPADD:
+ return a->d.ip;
+
+ case GEN_RID:
+ return a->d.rid;
+
+ default:
+ return NULL;
+ }
+ }
+
+int GENERAL_NAME_set0_othername(GENERAL_NAME *gen,
+ ASN1_OBJECT *oid, ASN1_TYPE *value)
+ {
+ OTHERNAME *oth;
+ oth = OTHERNAME_new();
+ if (!oth)
+ return 0;
+ oth->type_id = oid;
+ oth->value = value;
+ GENERAL_NAME_set0_value(gen, GEN_OTHERNAME, oth);
+ return 1;
+ }
+
+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;
+ }
+
diff --git a/src/crypto/x509v3/v3_ia5.c b/src/crypto/x509v3/v3_ia5.c
new file mode 100644
index 0000000..ec57e9b
--- /dev/null
+++ b/src/crypto/x509v3/v3_ia5.c
@@ -0,0 +1,117 @@
+/* v3_ia5.c */
+/* 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 <stdio.h>
+#include <string.h>
+
+#include <openssl/asn1.h>
+#include <openssl/conf.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/x509v3.h>
+
+
+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_IA5STRING(NID_netscape_base_url),
+EXT_IA5STRING(NID_netscape_revocation_url),
+EXT_IA5STRING(NID_netscape_ca_revocation_url),
+EXT_IA5STRING(NID_netscape_renewal_url),
+EXT_IA5STRING(NID_netscape_ca_policy_url),
+EXT_IA5STRING(NID_netscape_ssl_server_name),
+EXT_IA5STRING(NID_netscape_comment),
+EXT_END
+};
+
+
+static char *i2s_ASN1_IA5STRING(X509V3_EXT_METHOD *method,
+ ASN1_IA5STRING *ia5)
+{
+ char *tmp;
+ if(!ia5 || !ia5->length) return NULL;
+ if(!(tmp = OPENSSL_malloc(ia5->length + 1))) {
+ OPENSSL_PUT_ERROR(X509V3, i2s_ASN1_IA5STRING, 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) {
+ OPENSSL_PUT_ERROR(X509V3, s2i_ASN1_IA5STRING, X509V3_R_INVALID_NULL_ARGUMENT);
+ return NULL;
+ }
+ if(!(ia5 = M_ASN1_IA5STRING_new())) goto err;
+ if(!ASN1_STRING_set((ASN1_STRING *)ia5, (unsigned char*)str,
+ strlen(str))) {
+ M_ASN1_IA5STRING_free(ia5);
+ goto err;
+ }
+ return ia5;
+ err:
+ OPENSSL_PUT_ERROR(X509V3, s2i_ASN1_IA5STRING, ERR_R_MALLOC_FAILURE);
+ return NULL;
+}
+
diff --git a/src/crypto/x509v3/v3_info.c b/src/crypto/x509v3/v3_info.c
new file mode 100644
index 0000000..7558b2d
--- /dev/null
+++ b/src/crypto/x509v3/v3_info.c
@@ -0,0 +1,200 @@
+/* v3_info.c */
+/* 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 <stdio.h>
+#include <string.h>
+
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/buf.h>
+#include <openssl/conf.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/x509v3.h>
+
+
+static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD *method,
+ AUTHORITY_INFO_ACCESS *ainfo,
+ STACK_OF(CONF_VALUE) *ret);
+static AUTHORITY_INFO_ACCESS *v2i_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
+
+const X509V3_EXT_METHOD v3_info =
+{ NID_info_access, X509V3_EXT_MULTILINE, ASN1_ITEM_ref(AUTHORITY_INFO_ACCESS),
+0,0,0,0,
+0,0,
+(X509V3_EXT_I2V)i2v_AUTHORITY_INFO_ACCESS,
+(X509V3_EXT_V2I)v2i_AUTHORITY_INFO_ACCESS,
+0,0,
+NULL};
+
+const X509V3_EXT_METHOD v3_sinfo =
+{ NID_sinfo_access, X509V3_EXT_MULTILINE, ASN1_ITEM_ref(AUTHORITY_INFO_ACCESS),
+0,0,0,0,
+0,0,
+(X509V3_EXT_I2V)i2v_AUTHORITY_INFO_ACCESS,
+(X509V3_EXT_V2I)v2i_AUTHORITY_INFO_ACCESS,
+0,0,
+NULL};
+
+ASN1_SEQUENCE(ACCESS_DESCRIPTION) = {
+ ASN1_SIMPLE(ACCESS_DESCRIPTION, method, ASN1_OBJECT),
+ ASN1_SIMPLE(ACCESS_DESCRIPTION, location, GENERAL_NAME)
+} ASN1_SEQUENCE_END(ACCESS_DESCRIPTION)
+
+IMPLEMENT_ASN1_FUNCTIONS(ACCESS_DESCRIPTION)
+
+ASN1_ITEM_TEMPLATE(AUTHORITY_INFO_ACCESS) =
+ ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, GeneralNames, ACCESS_DESCRIPTION)
+ASN1_ITEM_TEMPLATE_END(AUTHORITY_INFO_ACCESS)
+
+IMPLEMENT_ASN1_FUNCTIONS(AUTHORITY_INFO_ACCESS)
+
+static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD *method,
+ AUTHORITY_INFO_ACCESS *ainfo,
+ STACK_OF(CONF_VALUE) *ret)
+{
+ ACCESS_DESCRIPTION *desc;
+ size_t i;
+ int nlen;
+ char objtmp[80], *ntmp;
+ CONF_VALUE *vtmp;
+ for(i = 0; i < sk_ACCESS_DESCRIPTION_num(ainfo); i++) {
+ desc = sk_ACCESS_DESCRIPTION_value(ainfo, i);
+ ret = i2v_GENERAL_NAME(method, desc->location, ret);
+ if(!ret) break;
+ vtmp = sk_CONF_VALUE_value(ret, i);
+ i2t_ASN1_OBJECT(objtmp, sizeof objtmp, desc->method);
+ nlen = strlen(objtmp) + strlen(vtmp->name) + 5;
+ ntmp = OPENSSL_malloc(nlen);
+ if(!ntmp) {
+ OPENSSL_PUT_ERROR(X509V3, i2v_AUTHORITY_INFO_ACCESS, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ BUF_strlcpy(ntmp, objtmp, nlen);
+ BUF_strlcat(ntmp, " - ", nlen);
+ BUF_strlcat(ntmp, vtmp->name, nlen);
+ OPENSSL_free(vtmp->name);
+ vtmp->name = ntmp;
+
+ }
+ if(!ret) return sk_CONF_VALUE_new_null();
+ return ret;
+}
+
+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;
+ size_t i;
+ int objlen;
+ char *objtmp, *ptmp;
+ if(!(ainfo = sk_ACCESS_DESCRIPTION_new_null())) {
+ OPENSSL_PUT_ERROR(X509V3, v2i_AUTHORITY_INFO_ACCESS, 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())
+ || !sk_ACCESS_DESCRIPTION_push(ainfo, acc)) {
+ OPENSSL_PUT_ERROR(X509V3, v2i_AUTHORITY_INFO_ACCESS, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ ptmp = strchr(cnf->name, ';');
+ if(!ptmp) {
+ OPENSSL_PUT_ERROR(X509V3, v2i_AUTHORITY_INFO_ACCESS, X509V3_R_INVALID_SYNTAX);
+ goto err;
+ }
+ objlen = ptmp - cnf->name;
+ ctmp.name = ptmp + 1;
+ ctmp.value = cnf->value;
+ if(!v2i_GENERAL_NAME_ex(acc->location, method, ctx, &ctmp, 0))
+ goto err;
+ if(!(objtmp = OPENSSL_malloc(objlen + 1))) {
+ OPENSSL_PUT_ERROR(X509V3, v2i_AUTHORITY_INFO_ACCESS, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ strncpy(objtmp, cnf->name, objlen);
+ objtmp[objlen] = 0;
+ acc->method = OBJ_txt2obj(objtmp, 0);
+ if(!acc->method) {
+ OPENSSL_PUT_ERROR(X509V3, v2i_AUTHORITY_INFO_ACCESS, X509V3_R_BAD_OBJECT);
+ ERR_add_error_data(2, "value=", objtmp);
+ OPENSSL_free(objtmp);
+ goto err;
+ }
+ OPENSSL_free(objtmp);
+
+ }
+ return ainfo;
+ err:
+ sk_ACCESS_DESCRIPTION_pop_free(ainfo, ACCESS_DESCRIPTION_free);
+ return NULL;
+}
+
+int i2a_ACCESS_DESCRIPTION(BIO *bp, ACCESS_DESCRIPTION* a)
+ {
+ i2a_ASN1_OBJECT(bp, a->method);
+#ifdef UNDEF
+ i2a_GENERAL_NAME(bp, a->location);
+#endif
+ return 2;
+ }
diff --git a/src/crypto/x509v3/v3_int.c b/src/crypto/x509v3/v3_int.c
new file mode 100644
index 0000000..8ca23bd
--- /dev/null
+++ b/src/crypto/x509v3/v3_int.c
@@ -0,0 +1,87 @@
+/* v3_int.c */
+/* 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 <stdio.h>
+
+#include <openssl/obj.h>
+#include <openssl/x509v3.h>
+
+
+const X509V3_EXT_METHOD v3_crl_num = {
+ NID_crl_number, 0, ASN1_ITEM_ref(ASN1_INTEGER),
+ 0,0,0,0,
+ (X509V3_EXT_I2S)i2s_ASN1_INTEGER,
+ 0,
+ 0,0,0,0, NULL};
+
+const X509V3_EXT_METHOD v3_delta_crl = {
+ NID_delta_crl, 0, ASN1_ITEM_ref(ASN1_INTEGER),
+ 0,0,0,0,
+ (X509V3_EXT_I2S)i2s_ASN1_INTEGER,
+ 0,
+ 0,0,0,0, NULL};
+
+static void * s2i_asn1_int(X509V3_EXT_METHOD *meth, X509V3_CTX *ctx, char *value)
+ {
+ return s2i_ASN1_INTEGER(meth, value);
+ }
+
+const X509V3_EXT_METHOD v3_inhibit_anyp = {
+ NID_inhibit_any_policy, 0, ASN1_ITEM_ref(ASN1_INTEGER),
+ 0,0,0,0,
+ (X509V3_EXT_I2S)i2s_ASN1_INTEGER,
+ (X509V3_EXT_S2I)s2i_asn1_int,
+ 0,0,0,0, NULL};
diff --git a/src/crypto/x509v3/v3_lib.c b/src/crypto/x509v3/v3_lib.c
new file mode 100644
index 0000000..d4e4e78
--- /dev/null
+++ b/src/crypto/x509v3/v3_lib.c
@@ -0,0 +1,335 @@
+/* v3_lib.c */
+/* 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 <stdio.h>
+
+#include <openssl/conf.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/x509v3.h>
+
+#include "ext_dat.h"
+static STACK_OF(X509V3_EXT_METHOD) *ext_list = NULL;
+
+static void ext_list_free(X509V3_EXT_METHOD *ext);
+
+static int ext_stack_cmp(const X509V3_EXT_METHOD **a, const X509V3_EXT_METHOD **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_stack_cmp))) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_EXT_add, ERR_R_MALLOC_FAILURE);
+ ext_list_free(ext);
+ return 0;
+ }
+ if(!sk_X509V3_EXT_METHOD_push(ext_list, ext)) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_EXT_add, ERR_R_MALLOC_FAILURE);
+ ext_list_free(ext);
+ return 0;
+ }
+ return 1;
+}
+
+static int ext_cmp(const void *void_a,
+ const void *void_b)
+{
+ const X509V3_EXT_METHOD **a = (const X509V3_EXT_METHOD**) void_a;
+ const X509V3_EXT_METHOD **b = (const X509V3_EXT_METHOD**) void_b;
+ return ext_stack_cmp(a, b);
+}
+
+const X509V3_EXT_METHOD *X509V3_EXT_get_nid(int nid)
+{
+ X509V3_EXT_METHOD tmp;
+ const X509V3_EXT_METHOD *t = &tmp, * const *ret;
+ size_t idx;
+
+ if(nid < 0) return NULL;
+ tmp.ext_nid = nid;
+ ret = bsearch(&t, standard_exts, STANDARD_EXTENSION_COUNT, sizeof(X509V3_EXT_METHOD*), ext_cmp);
+ if(ret) return *ret;
+ if(!ext_list) return NULL;
+
+ if (!sk_X509V3_EXT_METHOD_find(ext_list, &idx, &tmp))
+ return NULL;
+ return sk_X509V3_EXT_METHOD_value(ext_list, idx);
+}
+
+const X509V3_EXT_METHOD *X509V3_EXT_get(X509_EXTENSION *ext)
+{
+ int nid;
+ if((nid = OBJ_obj2nid(ext->object)) == NID_undef) return NULL;
+ return X509V3_EXT_get_nid(nid);
+}
+
+int X509V3_EXT_free(int nid, void *ext_data)
+{
+ const X509V3_EXT_METHOD *ext_method = X509V3_EXT_get_nid(nid);
+ if (ext_method == NULL)
+ {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_EXT_free, X509V3_R_CANNOT_FIND_FREE_FUNCTION);
+ return 0;
+ }
+
+ if (ext_method->it != NULL)
+ ASN1_item_free(ext_data, ASN1_ITEM_ptr(ext_method->it));
+ else if (ext_method->ext_free != NULL)
+ ext_method->ext_free(ext_data);
+ else
+ {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_EXT_free, X509V3_R_CANNOT_FIND_FREE_FUNCTION);
+ return 0;
+ }
+
+ return 1;
+}
+
+int X509V3_EXT_add_list(X509V3_EXT_METHOD *extlist)
+{
+ for(;extlist->ext_nid!=-1;extlist++)
+ if(!X509V3_EXT_add(extlist)) return 0;
+ return 1;
+}
+
+int X509V3_EXT_add_alias(int nid_to, int nid_from)
+{
+ const X509V3_EXT_METHOD *ext;
+ X509V3_EXT_METHOD *tmpext;
+
+ if(!(ext = X509V3_EXT_get_nid(nid_from))) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_EXT_add_alias, X509V3_R_EXTENSION_NOT_FOUND);
+ return 0;
+ }
+ if(!(tmpext = (X509V3_EXT_METHOD *)OPENSSL_malloc(sizeof(X509V3_EXT_METHOD)))) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_EXT_add_alias, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ *tmpext = *ext;
+ tmpext->ext_nid = nid_to;
+ tmpext->ext_flags |= X509V3_EXT_DYNAMIC;
+ return X509V3_EXT_add(tmpext);
+}
+
+void X509V3_EXT_cleanup(void)
+{
+ sk_X509V3_EXT_METHOD_pop_free(ext_list, ext_list_free);
+ ext_list = NULL;
+}
+
+static void ext_list_free(X509V3_EXT_METHOD *ext)
+{
+ if(ext->ext_flags & X509V3_EXT_DYNAMIC) OPENSSL_free(ext);
+}
+
+/* Legacy function: we don't need to add standard extensions
+ * any more because they are now kept in ext_dat.h.
+ */
+
+int X509V3_add_standard_extensions(void)
+{
+ return 1;
+}
+
+/* Return an extension internal structure */
+
+void *X509V3_EXT_d2i(X509_EXTENSION *ext)
+{
+ const X509V3_EXT_METHOD *method;
+ const unsigned char *p;
+
+ if(!(method = X509V3_EXT_get(ext))) return NULL;
+ p = ext->value->data;
+ if(method->it) return ASN1_item_d2i(NULL, &p, ext->value->length, ASN1_ITEM_ptr(method->it));
+ return method->d2i(NULL, &p, ext->value->length);
+}
+
+/* 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(STACK_OF(X509_EXTENSION) *x, int nid, int *crit, int *idx)
+{
+ int lastpos;
+ size_t 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;
+}
+
+/* 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(!sk_X509_EXTENSION_delete(*x, extidx)) return -1;
+ 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) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_add1_i2d, X509V3_R_ERROR_CREATING_EXTENSION);
+ return 0;
+ }
+
+ /* If extension exists replace it.. */
+ if(extidx >= 0) {
+ extmp = sk_X509_EXTENSION_value(*x, extidx);
+ X509_EXTENSION_free(extmp);
+ if(!sk_X509_EXTENSION_set(*x, extidx, ext)) return -1;
+ return 1;
+ }
+
+ 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))
+ OPENSSL_PUT_ERROR(X509V3, X509V3_add1_i2d, errcode);
+ return 0;
+}
diff --git a/src/crypto/x509v3/v3_ncons.c b/src/crypto/x509v3/v3_ncons.c
new file mode 100644
index 0000000..c42a665
--- /dev/null
+++ b/src/crypto/x509v3/v3_ncons.c
@@ -0,0 +1,510 @@
+/* v3_ncons.c */
+/* 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 <stdio.h>
+#include <string.h>
+
+#include <openssl/asn1t.h>
+#include <openssl/conf.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/x509v3.h>
+
+
+static void *v2i_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
+static int i2r_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method,
+ void *a, BIO *bp, int ind);
+static int do_i2r_name_constraints(const X509V3_EXT_METHOD *method,
+ STACK_OF(GENERAL_SUBTREE) *trees,
+ BIO *bp, int ind, const char *name);
+static int print_nc_ipadd(BIO *bp, ASN1_OCTET_STRING *ip);
+
+static int nc_match(GENERAL_NAME *gen, NAME_CONSTRAINTS *nc);
+static int nc_match_single(GENERAL_NAME *sub, GENERAL_NAME *gen);
+static int nc_dn(X509_NAME *sub, X509_NAME *nm);
+static int nc_dns(ASN1_IA5STRING *sub, ASN1_IA5STRING *dns);
+static int nc_email(ASN1_IA5STRING *sub, ASN1_IA5STRING *eml);
+static int nc_uri(ASN1_IA5STRING *uri, ASN1_IA5STRING *base);
+
+const X509V3_EXT_METHOD v3_name_constraints = {
+ NID_name_constraints, 0,
+ ASN1_ITEM_ref(NAME_CONSTRAINTS),
+ 0,0,0,0,
+ 0,0,
+ 0, v2i_NAME_CONSTRAINTS,
+ i2r_NAME_CONSTRAINTS,0,
+ NULL
+};
+
+ASN1_SEQUENCE(GENERAL_SUBTREE) = {
+ ASN1_SIMPLE(GENERAL_SUBTREE, base, GENERAL_NAME),
+ ASN1_IMP_OPT(GENERAL_SUBTREE, minimum, ASN1_INTEGER, 0),
+ ASN1_IMP_OPT(GENERAL_SUBTREE, maximum, ASN1_INTEGER, 1)
+} ASN1_SEQUENCE_END(GENERAL_SUBTREE)
+
+ASN1_SEQUENCE(NAME_CONSTRAINTS) = {
+ ASN1_IMP_SEQUENCE_OF_OPT(NAME_CONSTRAINTS, permittedSubtrees,
+ GENERAL_SUBTREE, 0),
+ ASN1_IMP_SEQUENCE_OF_OPT(NAME_CONSTRAINTS, excludedSubtrees,
+ GENERAL_SUBTREE, 1),
+} ASN1_SEQUENCE_END(NAME_CONSTRAINTS)
+
+
+IMPLEMENT_ASN1_ALLOC_FUNCTIONS(GENERAL_SUBTREE)
+IMPLEMENT_ASN1_ALLOC_FUNCTIONS(NAME_CONSTRAINTS)
+
+static void *v2i_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
+ {
+ size_t 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
+ {
+ OPENSSL_PUT_ERROR(X509V3, v2i_NAME_CONSTRAINTS, 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:
+ OPENSSL_PUT_ERROR(X509V3, v2i_NAME_CONSTRAINTS, ERR_R_MALLOC_FAILURE);
+ err:
+ if (ncons)
+ NAME_CONSTRAINTS_free(ncons);
+ if (sub)
+ GENERAL_SUBTREE_free(sub);
+
+ return NULL;
+ }
+
+
+
+
+static int i2r_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method, void *a,
+ BIO *bp, int ind)
+ {
+ NAME_CONSTRAINTS *ncons = a;
+ do_i2r_name_constraints(method, ncons->permittedSubtrees,
+ bp, ind, "Permitted");
+ do_i2r_name_constraints(method, ncons->excludedSubtrees,
+ bp, ind, "Excluded");
+ return 1;
+ }
+
+static int do_i2r_name_constraints(const X509V3_EXT_METHOD *method,
+ STACK_OF(GENERAL_SUBTREE) *trees,
+ BIO *bp, int ind, const char *name)
+ {
+ GENERAL_SUBTREE *tree;
+ size_t i;
+ if (sk_GENERAL_SUBTREE_num(trees) > 0)
+ BIO_printf(bp, "%*s%s:\n", ind, "", name);
+ for(i = 0; i < sk_GENERAL_SUBTREE_num(trees); i++)
+ {
+ tree = sk_GENERAL_SUBTREE_value(trees, i);
+ BIO_printf(bp, "%*s", ind + 2, "");
+ if (tree->base->type == GEN_IPADD)
+ print_nc_ipadd(bp, tree->base->d.ip);
+ else
+ GENERAL_NAME_print(bp, tree->base);
+ BIO_puts(bp, "\n");
+ }
+ return 1;
+ }
+
+static int print_nc_ipadd(BIO *bp, ASN1_OCTET_STRING *ip)
+ {
+ int i, len;
+ unsigned char *p;
+ p = ip->data;
+ len = ip->length;
+ BIO_puts(bp, "IP:");
+ if(len == 8)
+ {
+ BIO_printf(bp, "%d.%d.%d.%d/%d.%d.%d.%d",
+ p[0], p[1], p[2], p[3],
+ p[4], p[5], p[6], p[7]);
+ }
+ else if(len == 32)
+ {
+ for (i = 0; i < 16; i++)
+ {
+ BIO_printf(bp, "%X", p[0] << 8 | p[1]);
+ p += 2;
+ if (i == 7)
+ BIO_puts(bp, "/");
+ else if (i != 15)
+ BIO_puts(bp, ":");
+ }
+ }
+ else
+ BIO_printf(bp, "IP Address:<invalid>");
+ return 1;
+ }
+
+/* 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;
+ size_t j;
+ 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 (j = 0; j < sk_GENERAL_NAME_num(x->altname); j++)
+ {
+ GENERAL_NAME *gen = sk_GENERAL_NAME_value(x->altname, j);
+ r = nc_match(gen, nc);
+ if (r != X509_V_OK)
+ return r;
+ }
+
+ return X509_V_OK;
+
+ }
+
+static int nc_match(GENERAL_NAME *gen, NAME_CONSTRAINTS *nc)
+ {
+ GENERAL_SUBTREE *sub;
+ int r, match = 0;
+ size_t i;
+
+ /* 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 != '.' && dnsptr[-1] != '.')
+ return X509_V_ERR_PERMITTED_VIOLATION;
+ }
+
+ if (OPENSSL_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: inital '.' is RHS match */
+ if (!baseat && (*baseptr == '.'))
+ {
+ if (eml->length > base->length)
+ {
+ emlptr += eml->length - base->length;
+ if (!OPENSSL_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 (OPENSSL_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: inital '.' is RHS match */
+ if (*baseptr == '.')
+ {
+ if (hostlen > base->length)
+ {
+ p = hostptr + hostlen - base->length;
+ if (!OPENSSL_strncasecmp(p, baseptr, base->length))
+ return X509_V_OK;
+ }
+ return X509_V_ERR_PERMITTED_VIOLATION;
+ }
+
+ if ((base->length != (int)hostlen) || OPENSSL_strncasecmp(hostptr, baseptr, hostlen))
+ return X509_V_ERR_PERMITTED_VIOLATION;
+
+ return X509_V_OK;
+
+ }
diff --git a/src/crypto/x509v3/v3_pci.c b/src/crypto/x509v3/v3_pci.c
new file mode 100644
index 0000000..aa93891
--- /dev/null
+++ b/src/crypto/x509v3/v3_pci.c
@@ -0,0 +1,334 @@
+/* v3_pci.c -*- mode:C; c-file-style: "eay" -*- */
+/* Contributed to the OpenSSL Project 2004
+ * by Richard Levitte (richard@levitte.org)
+ */
+/* Copyright (c) 2004 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <openssl/conf.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/x509v3.h>
+
+
+static int i2r_pci(X509V3_EXT_METHOD *method, PROXY_CERT_INFO_EXTENSION *ext,
+ BIO *out, int indent);
+static PROXY_CERT_INFO_EXTENSION *r2i_pci(X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, char *str);
+
+const X509V3_EXT_METHOD v3_pci =
+ { NID_proxyCertInfo, 0, ASN1_ITEM_ref(PROXY_CERT_INFO_EXTENSION),
+ 0,0,0,0,
+ 0,0,
+ NULL, NULL,
+ (X509V3_EXT_I2R)i2r_pci,
+ (X509V3_EXT_R2I)r2i_pci,
+ NULL,
+ };
+
+static int i2r_pci(X509V3_EXT_METHOD *method, PROXY_CERT_INFO_EXTENSION *pci,
+ BIO *out, int indent)
+ {
+ BIO_printf(out, "%*sPath Length Constraint: ", indent, "");
+ if (pci->pcPathLengthConstraint)
+ i2a_ASN1_INTEGER(out, pci->pcPathLengthConstraint);
+ else
+ BIO_printf(out, "infinite");
+ BIO_puts(out, "\n");
+ BIO_printf(out, "%*sPolicy Language: ", indent, "");
+ i2a_ASN1_OBJECT(out, pci->proxyPolicy->policyLanguage);
+ BIO_puts(out, "\n");
+ if (pci->proxyPolicy->policy && pci->proxyPolicy->policy->data)
+ BIO_printf(out, "%*sPolicy Text: %s\n", indent, "",
+ pci->proxyPolicy->policy->data);
+ return 1;
+ }
+
+static int process_pci_value(CONF_VALUE *val,
+ ASN1_OBJECT **language, ASN1_INTEGER **pathlen,
+ ASN1_OCTET_STRING **policy)
+ {
+ int free_policy = 0;
+
+ if (strcmp(val->name, "language") == 0)
+ {
+ if (*language)
+ {
+ OPENSSL_PUT_ERROR(X509V3, process_pci_value, X509V3_R_POLICY_LANGUAGE_ALREADY_DEFINED);
+ X509V3_conf_err(val);
+ return 0;
+ }
+ if (!(*language = OBJ_txt2obj(val->value, 0)))
+ {
+ OPENSSL_PUT_ERROR(X509V3, process_pci_value, X509V3_R_INVALID_OBJECT_IDENTIFIER);
+ X509V3_conf_err(val);
+ return 0;
+ }
+ }
+ else if (strcmp(val->name, "pathlen") == 0)
+ {
+ if (*pathlen)
+ {
+ OPENSSL_PUT_ERROR(X509V3, process_pci_value, X509V3_R_POLICY_PATH_LENGTH_ALREADY_DEFINED);
+ X509V3_conf_err(val);
+ return 0;
+ }
+ if (!X509V3_get_value_int(val, pathlen))
+ {
+ OPENSSL_PUT_ERROR(X509V3, process_pci_value, X509V3_R_POLICY_PATH_LENGTH);
+ X509V3_conf_err(val);
+ return 0;
+ }
+ }
+ else if (strcmp(val->name, "policy") == 0)
+ {
+ unsigned char *tmp_data = NULL;
+ long val_len;
+ if (!*policy)
+ {
+ *policy = ASN1_OCTET_STRING_new();
+ if (!*policy)
+ {
+ OPENSSL_PUT_ERROR(X509V3, process_pci_value, ERR_R_MALLOC_FAILURE);
+ X509V3_conf_err(val);
+ return 0;
+ }
+ free_policy = 1;
+ }
+ if (strncmp(val->value, "hex:", 4) == 0)
+ {
+ unsigned char *tmp_data2 =
+ string_to_hex(val->value + 4, &val_len);
+
+ if (!tmp_data2)
+ {
+ OPENSSL_PUT_ERROR(X509V3, process_pci_value, X509V3_R_ILLEGAL_HEX_DIGIT);
+ X509V3_conf_err(val);
+ goto err;
+ }
+
+ tmp_data = OPENSSL_realloc((*policy)->data,
+ (*policy)->length + val_len + 1);
+ if (tmp_data)
+ {
+ (*policy)->data = tmp_data;
+ memcpy(&(*policy)->data[(*policy)->length],
+ tmp_data2, val_len);
+ (*policy)->length += val_len;
+ (*policy)->data[(*policy)->length] = '\0';
+ }
+ else
+ {
+ OPENSSL_free(tmp_data2);
+ /* realloc failure implies the original data space is b0rked too! */
+ (*policy)->data = NULL;
+ (*policy)->length = 0;
+ OPENSSL_PUT_ERROR(X509V3, process_pci_value, ERR_R_MALLOC_FAILURE);
+ X509V3_conf_err(val);
+ goto err;
+ }
+ OPENSSL_free(tmp_data2);
+ }
+ else if (strncmp(val->value, "file:", 5) == 0)
+ {
+ unsigned char buf[2048];
+ int n;
+ BIO *b = BIO_new_file(val->value + 5, "r");
+ if (!b)
+ {
+ OPENSSL_PUT_ERROR(X509V3, process_pci_value, ERR_R_BIO_LIB);
+ X509V3_conf_err(val);
+ goto err;
+ }
+ while((n = BIO_read(b, buf, sizeof(buf))) > 0
+ || (n == 0 && BIO_should_retry(b)))
+ {
+ if (!n) continue;
+
+ tmp_data = OPENSSL_realloc((*policy)->data,
+ (*policy)->length + n + 1);
+
+ if (!tmp_data)
+ break;
+
+ (*policy)->data = tmp_data;
+ memcpy(&(*policy)->data[(*policy)->length],
+ buf, n);
+ (*policy)->length += n;
+ (*policy)->data[(*policy)->length] = '\0';
+ }
+ BIO_free_all(b);
+
+ if (n < 0)
+ {
+ OPENSSL_PUT_ERROR(X509V3, process_pci_value, ERR_R_BIO_LIB);
+ X509V3_conf_err(val);
+ goto err;
+ }
+ }
+ else if (strncmp(val->value, "text:", 5) == 0)
+ {
+ val_len = strlen(val->value + 5);
+ tmp_data = OPENSSL_realloc((*policy)->data,
+ (*policy)->length + val_len + 1);
+ if (tmp_data)
+ {
+ (*policy)->data = tmp_data;
+ memcpy(&(*policy)->data[(*policy)->length],
+ val->value + 5, val_len);
+ (*policy)->length += val_len;
+ (*policy)->data[(*policy)->length] = '\0';
+ }
+ else
+ {
+ /* realloc failure implies the original data space is b0rked too! */
+ (*policy)->data = NULL;
+ (*policy)->length = 0;
+ OPENSSL_PUT_ERROR(X509V3, process_pci_value, ERR_R_MALLOC_FAILURE);
+ X509V3_conf_err(val);
+ goto err;
+ }
+ }
+ else
+ {
+ OPENSSL_PUT_ERROR(X509V3, process_pci_value, X509V3_R_INCORRECT_POLICY_SYNTAX_TAG);
+ X509V3_conf_err(val);
+ goto err;
+ }
+ if (!tmp_data)
+ {
+ OPENSSL_PUT_ERROR(X509V3, process_pci_value, ERR_R_MALLOC_FAILURE);
+ X509V3_conf_err(val);
+ goto err;
+ }
+ }
+ return 1;
+err:
+ if (free_policy)
+ {
+ ASN1_OCTET_STRING_free(*policy);
+ *policy = NULL;
+ }
+ return 0;
+ }
+
+static PROXY_CERT_INFO_EXTENSION *r2i_pci(X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, char *value)
+ {
+ PROXY_CERT_INFO_EXTENSION *pci = NULL;
+ STACK_OF(CONF_VALUE) *vals;
+ ASN1_OBJECT *language = NULL;
+ ASN1_INTEGER *pathlen = NULL;
+ ASN1_OCTET_STRING *policy = NULL;
+ size_t i, j;
+ int nid;
+
+ vals = X509V3_parse_list(value);
+ for (i = 0; i < sk_CONF_VALUE_num(vals); i++)
+ {
+ CONF_VALUE *cnf = sk_CONF_VALUE_value(vals, i);
+ if (!cnf->name || (*cnf->name != '@' && !cnf->value))
+ {
+ OPENSSL_PUT_ERROR(X509V3, r2i_pci, X509V3_R_INVALID_PROXY_POLICY_SETTING);
+ X509V3_conf_err(cnf);
+ goto err;
+ }
+ if (*cnf->name == '@')
+ {
+ STACK_OF(CONF_VALUE) *sect;
+ int success_p = 1;
+
+ sect = X509V3_get_section(ctx, cnf->name + 1);
+ if (!sect)
+ {
+ OPENSSL_PUT_ERROR(X509V3, r2i_pci, X509V3_R_INVALID_SECTION);
+ X509V3_conf_err(cnf);
+ goto err;
+ }
+ for (j = 0; success_p && j < sk_CONF_VALUE_num(sect); j++)
+ {
+ success_p =
+ process_pci_value(sk_CONF_VALUE_value(sect, j),
+ &language, &pathlen, &policy);
+ }
+ X509V3_section_free(ctx, sect);
+ if (!success_p)
+ goto err;
+ }
+ else
+ {
+ if (!process_pci_value(cnf,
+ &language, &pathlen, &policy))
+ {
+ X509V3_conf_err(cnf);
+ goto err;
+ }
+ }
+ }
+
+ /* Language is mandatory */
+ if (!language)
+ {
+ OPENSSL_PUT_ERROR(X509V3, r2i_pci, X509V3_R_NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED);
+ goto err;
+ }
+ nid = OBJ_obj2nid(language);
+ if ((nid == NID_Independent || nid == NID_id_ppl_inheritAll) && policy)
+ {
+ OPENSSL_PUT_ERROR(X509V3, r2i_pci, X509V3_R_POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY);
+ goto err;
+ }
+
+ pci = PROXY_CERT_INFO_EXTENSION_new();
+ if (!pci)
+ {
+ OPENSSL_PUT_ERROR(X509V3, r2i_pci, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ pci->proxyPolicy->policyLanguage = language; language = NULL;
+ pci->proxyPolicy->policy = policy; policy = NULL;
+ pci->pcPathLengthConstraint = pathlen; pathlen = NULL;
+ goto end;
+err:
+ if (language) { ASN1_OBJECT_free(language); language = NULL; }
+ if (pathlen) { ASN1_INTEGER_free(pathlen); pathlen = NULL; }
+ if (policy) { ASN1_OCTET_STRING_free(policy); policy = NULL; }
+ if (pci) { PROXY_CERT_INFO_EXTENSION_free(pci); pci = NULL; }
+end:
+ sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
+ return pci;
+ }
diff --git a/src/crypto/x509v3/v3_pcia.c b/src/crypto/x509v3/v3_pcia.c
new file mode 100644
index 0000000..e3e3192
--- /dev/null
+++ b/src/crypto/x509v3/v3_pcia.c
@@ -0,0 +1,56 @@
+/* v3_pcia.c -*- mode:C; c-file-style: "eay" -*- */
+/* Contributed to the OpenSSL Project 2004
+ * by Richard Levitte (richard@levitte.org)
+ */
+/* Copyright (c) 2004 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/x509v3.h>
+
+
+ASN1_SEQUENCE(PROXY_POLICY) =
+ {
+ ASN1_SIMPLE(PROXY_POLICY,policyLanguage,ASN1_OBJECT),
+ ASN1_OPT(PROXY_POLICY,policy,ASN1_OCTET_STRING)
+} ASN1_SEQUENCE_END(PROXY_POLICY)
+
+IMPLEMENT_ASN1_FUNCTIONS(PROXY_POLICY)
+
+ASN1_SEQUENCE(PROXY_CERT_INFO_EXTENSION) =
+ {
+ ASN1_OPT(PROXY_CERT_INFO_EXTENSION,pcPathLengthConstraint,ASN1_INTEGER),
+ ASN1_SIMPLE(PROXY_CERT_INFO_EXTENSION,proxyPolicy,PROXY_POLICY)
+} ASN1_SEQUENCE_END(PROXY_CERT_INFO_EXTENSION)
+
+IMPLEMENT_ASN1_FUNCTIONS(PROXY_CERT_INFO_EXTENSION)
diff --git a/src/crypto/x509v3/v3_pcons.c b/src/crypto/x509v3/v3_pcons.c
new file mode 100644
index 0000000..f87c6a0
--- /dev/null
+++ b/src/crypto/x509v3/v3_pcons.c
@@ -0,0 +1,142 @@
+/* v3_pcons.c */
+/* 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 <stdio.h>
+#include <string.h>
+
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/conf.h>
+#include <openssl/err.h>
+#include <openssl/obj.h>
+#include <openssl/x509v3.h>
+
+
+static STACK_OF(CONF_VALUE) *
+i2v_POLICY_CONSTRAINTS(const X509V3_EXT_METHOD *method, void *bcons,
+ STACK_OF(CONF_VALUE) *extlist);
+static void *v2i_POLICY_CONSTRAINTS(const X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE) *values);
+
+const X509V3_EXT_METHOD v3_policy_constraints = {
+NID_policy_constraints, 0,
+ASN1_ITEM_ref(POLICY_CONSTRAINTS),
+0,0,0,0,
+0,0,
+i2v_POLICY_CONSTRAINTS,
+v2i_POLICY_CONSTRAINTS,
+NULL,NULL,
+NULL
+};
+
+ASN1_SEQUENCE(POLICY_CONSTRAINTS) = {
+ ASN1_IMP_OPT(POLICY_CONSTRAINTS, requireExplicitPolicy, ASN1_INTEGER,0),
+ ASN1_IMP_OPT(POLICY_CONSTRAINTS, inhibitPolicyMapping, ASN1_INTEGER,1)
+} ASN1_SEQUENCE_END(POLICY_CONSTRAINTS)
+
+IMPLEMENT_ASN1_ALLOC_FUNCTIONS(POLICY_CONSTRAINTS)
+
+
+static STACK_OF(CONF_VALUE) *
+i2v_POLICY_CONSTRAINTS(const X509V3_EXT_METHOD *method, void *a,
+ STACK_OF(CONF_VALUE) *extlist)
+{
+ POLICY_CONSTRAINTS *pcons = a;
+ X509V3_add_value_int("Require Explicit Policy",
+ pcons->requireExplicitPolicy, &extlist);
+ X509V3_add_value_int("Inhibit Policy Mapping",
+ pcons->inhibitPolicyMapping, &extlist);
+ return extlist;
+}
+
+static void *v2i_POLICY_CONSTRAINTS(const X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE) *values)
+{
+ POLICY_CONSTRAINTS *pcons=NULL;
+ CONF_VALUE *val;
+ size_t i;
+ if(!(pcons = POLICY_CONSTRAINTS_new())) {
+ OPENSSL_PUT_ERROR(X509V3, v2i_POLICY_CONSTRAINTS, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ for(i = 0; i < sk_CONF_VALUE_num(values); i++) {
+ val = sk_CONF_VALUE_value(values, i);
+ if(!strcmp(val->name, "requireExplicitPolicy")) {
+ 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 {
+ OPENSSL_PUT_ERROR(X509V3, v2i_POLICY_CONSTRAINTS, X509V3_R_INVALID_NAME);
+ X509V3_conf_err(val);
+ goto err;
+ }
+ }
+ if (!pcons->inhibitPolicyMapping && !pcons->requireExplicitPolicy) {
+ OPENSSL_PUT_ERROR(X509V3, v2i_POLICY_CONSTRAINTS, X509V3_R_ILLEGAL_EMPTY_EXTENSION);
+ goto err;
+ }
+
+ return pcons;
+ err:
+ POLICY_CONSTRAINTS_free(pcons);
+ return NULL;
+}
+
diff --git a/src/crypto/x509v3/v3_pku.c b/src/crypto/x509v3/v3_pku.c
new file mode 100644
index 0000000..445eda6
--- /dev/null
+++ b/src/crypto/x509v3/v3_pku.c
@@ -0,0 +1,109 @@
+/* v3_pku.c */
+/* 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 <stdio.h>
+
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/x509v3.h>
+
+
+static int i2r_PKEY_USAGE_PERIOD(X509V3_EXT_METHOD *method, PKEY_USAGE_PERIOD *usage, BIO *out, int indent);
+/*
+static PKEY_USAGE_PERIOD *v2i_PKEY_USAGE_PERIOD(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *values);
+*/
+const X509V3_EXT_METHOD v3_pkey_usage_period = {
+NID_private_key_usage_period, 0, ASN1_ITEM_ref(PKEY_USAGE_PERIOD),
+0,0,0,0,
+0,0,0,0,
+(X509V3_EXT_I2R)i2r_PKEY_USAGE_PERIOD, NULL,
+NULL
+};
+
+ASN1_SEQUENCE(PKEY_USAGE_PERIOD) = {
+ ASN1_IMP_OPT(PKEY_USAGE_PERIOD, notBefore, ASN1_GENERALIZEDTIME, 0),
+ ASN1_IMP_OPT(PKEY_USAGE_PERIOD, notAfter, ASN1_GENERALIZEDTIME, 1)
+} ASN1_SEQUENCE_END(PKEY_USAGE_PERIOD)
+
+IMPLEMENT_ASN1_FUNCTIONS(PKEY_USAGE_PERIOD)
+
+static int i2r_PKEY_USAGE_PERIOD(X509V3_EXT_METHOD *method,
+ PKEY_USAGE_PERIOD *usage, BIO *out, int indent)
+{
+ BIO_printf(out, "%*s", indent, "");
+ if(usage->notBefore) {
+ BIO_write(out, "Not Before: ", 12);
+ ASN1_GENERALIZEDTIME_print(out, usage->notBefore);
+ if(usage->notAfter) BIO_write(out, ", ", 2);
+ }
+ if(usage->notAfter) {
+ BIO_write(out, "Not After: ", 11);
+ ASN1_GENERALIZEDTIME_print(out, usage->notAfter);
+ }
+ return 1;
+}
+
+/*
+static PKEY_USAGE_PERIOD *v2i_PKEY_USAGE_PERIOD(method, ctx, values)
+X509V3_EXT_METHOD *method;
+X509V3_CTX *ctx;
+STACK_OF(CONF_VALUE) *values;
+{
+return NULL;
+}
+*/
diff --git a/src/crypto/x509v3/v3_pmaps.c b/src/crypto/x509v3/v3_pmaps.c
new file mode 100644
index 0000000..fbc169d
--- /dev/null
+++ b/src/crypto/x509v3/v3_pmaps.c
@@ -0,0 +1,156 @@
+/* v3_pmaps.c */
+/* 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 <stdio.h>
+
+#include <openssl/asn1t.h>
+#include <openssl/conf.h>
+#include <openssl/err.h>
+#include <openssl/obj.h>
+#include <openssl/x509v3.h>
+
+
+static void *v2i_POLICY_MAPPINGS(const X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
+static STACK_OF(CONF_VALUE) *
+i2v_POLICY_MAPPINGS(const X509V3_EXT_METHOD *method, void *pmps,
+ STACK_OF(CONF_VALUE) *extlist);
+
+const X509V3_EXT_METHOD v3_policy_mappings = {
+ NID_policy_mappings, 0,
+ ASN1_ITEM_ref(POLICY_MAPPINGS),
+ 0,0,0,0,
+ 0,0,
+ i2v_POLICY_MAPPINGS,
+ v2i_POLICY_MAPPINGS,
+ 0,0,
+ NULL
+};
+
+ASN1_SEQUENCE(POLICY_MAPPING) = {
+ ASN1_SIMPLE(POLICY_MAPPING, issuerDomainPolicy, ASN1_OBJECT),
+ ASN1_SIMPLE(POLICY_MAPPING, subjectDomainPolicy, ASN1_OBJECT)
+} ASN1_SEQUENCE_END(POLICY_MAPPING)
+
+ASN1_ITEM_TEMPLATE(POLICY_MAPPINGS) =
+ ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, POLICY_MAPPINGS,
+ POLICY_MAPPING)
+ASN1_ITEM_TEMPLATE_END(POLICY_MAPPINGS)
+
+IMPLEMENT_ASN1_ALLOC_FUNCTIONS(POLICY_MAPPING)
+
+
+static STACK_OF(CONF_VALUE) *
+i2v_POLICY_MAPPINGS(const X509V3_EXT_METHOD *method, void *a,
+ STACK_OF(CONF_VALUE) *ext_list)
+{
+ POLICY_MAPPINGS *pmaps = a;
+ POLICY_MAPPING *pmap;
+ size_t i;
+ char obj_tmp1[80];
+ char obj_tmp2[80];
+ for(i = 0; i < sk_POLICY_MAPPING_num(pmaps); i++) {
+ pmap = sk_POLICY_MAPPING_value(pmaps, i);
+ i2t_ASN1_OBJECT(obj_tmp1, 80, pmap->issuerDomainPolicy);
+ i2t_ASN1_OBJECT(obj_tmp2, 80, pmap->subjectDomainPolicy);
+ X509V3_add_value(obj_tmp1, obj_tmp2, &ext_list);
+ }
+ return ext_list;
+}
+
+static void *v2i_POLICY_MAPPINGS(const X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
+{
+ POLICY_MAPPINGS *pmaps;
+ POLICY_MAPPING *pmap;
+ ASN1_OBJECT *obj1, *obj2;
+ CONF_VALUE *val;
+ size_t i;
+
+ if(!(pmaps = sk_POLICY_MAPPING_new_null())) {
+ OPENSSL_PUT_ERROR(X509V3, v2i_POLICY_MAPPINGS, 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) {
+ sk_POLICY_MAPPING_pop_free(pmaps, POLICY_MAPPING_free);
+ OPENSSL_PUT_ERROR(X509V3, v2i_POLICY_MAPPINGS, X509V3_R_INVALID_OBJECT_IDENTIFIER);
+ X509V3_conf_err(val);
+ return NULL;
+ }
+ obj1 = OBJ_txt2obj(val->name, 0);
+ obj2 = OBJ_txt2obj(val->value, 0);
+ if(!obj1 || !obj2) {
+ sk_POLICY_MAPPING_pop_free(pmaps, POLICY_MAPPING_free);
+ OPENSSL_PUT_ERROR(X509V3, v2i_POLICY_MAPPINGS, X509V3_R_INVALID_OBJECT_IDENTIFIER);
+ X509V3_conf_err(val);
+ return NULL;
+ }
+ pmap = POLICY_MAPPING_new();
+ if (!pmap) {
+ sk_POLICY_MAPPING_pop_free(pmaps, POLICY_MAPPING_free);
+ OPENSSL_PUT_ERROR(X509V3, v2i_POLICY_MAPPINGS, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ pmap->issuerDomainPolicy = obj1;
+ pmap->subjectDomainPolicy = obj2;
+ sk_POLICY_MAPPING_push(pmaps, pmap);
+ }
+ return pmaps;
+}
diff --git a/src/crypto/x509v3/v3_prn.c b/src/crypto/x509v3/v3_prn.c
new file mode 100644
index 0000000..87aef4d
--- /dev/null
+++ b/src/crypto/x509v3/v3_prn.c
@@ -0,0 +1,207 @@
+/* v3_prn.c */
+/* 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 <stdio.h>
+
+#include <openssl/bio.h>
+#include <openssl/conf.h>
+#include <openssl/mem.h>
+#include <openssl/x509v3.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)
+{
+ size_t i;
+ CONF_VALUE *nval;
+ if(!val) return;
+ if(!ml || !sk_CONF_VALUE_num(val)) {
+ BIO_printf(out, "%*s", indent, "");
+ if(!sk_CONF_VALUE_num(val)) BIO_puts(out, "<EMPTY>\n");
+ }
+ for(i = 0; i < sk_CONF_VALUE_num(val); i++) {
+ if(ml) BIO_printf(out, "%*s", indent, "");
+ else if(i > 0) BIO_printf(out, ", ");
+ nval = sk_CONF_VALUE_value(val, i);
+ if(!nval->name) BIO_puts(out, nval->value);
+ else if(!nval->value) BIO_puts(out, nval->name);
+ else BIO_printf(out, "%s:%s", nval->name, nval->value);
+ if(ml) BIO_puts(out, "\n");
+ }
+}
+
+/* Main routine: print out a general extension */
+
+int X509V3_EXT_print(BIO *out, X509_EXTENSION *ext, unsigned long flag, int indent)
+{
+ void *ext_str = NULL;
+ char *value = NULL;
+ 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, ASN1_ITEM_ptr(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);
+ if(value) OPENSSL_free(value);
+ if(method->it) ASN1_item_free(ext_str, ASN1_ITEM_ptr(method->it));
+ else method->ext_free(ext_str);
+ return ok;
+}
+
+int X509V3_extensions_print(BIO *bp, const char *title, STACK_OF(X509_EXTENSION) *exts, unsigned long flag, int indent)
+{
+ size_t i;
+ int 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, "");
+ M_ASN1_OCTET_STRING_print(bp,ex->value);
+ }
+ if (BIO_write(bp,"\n",1) <= 0) return 0;
+ }
+ return 1;
+}
+
+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<Parse Error>", indent, "");
+ else
+ BIO_printf(out, "%*s<Not Supported>", 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_hexdump(out, ext->value->data, ext->value->length, indent);
+
+ default:
+ return 1;
+ }
+}
+
+
+#ifndef OPENSSL_NO_FP_API
+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;
+}
+#endif
diff --git a/src/crypto/x509v3/v3_purp.c b/src/crypto/x509v3/v3_purp.c
new file mode 100644
index 0000000..6daf632
--- /dev/null
+++ b/src/crypto/x509v3/v3_purp.c
@@ -0,0 +1,786 @@
+/* v3_purp.c */
+/* 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 <stdio.h>
+
+#include <string.h>
+
+#include <openssl/buf.h>
+#include <openssl/err.h>
+#include <openssl/digest.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/x509_vfy.h>
+#include <openssl/x509v3.h>
+
+
+static void x509v3_cache_extensions(X509 *x);
+
+static int check_ssl_ca(const X509 *x);
+static int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x, int ca);
+static int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x, int ca);
+static int check_purpose_ns_ssl_server(const X509_PURPOSE *xp, const X509 *x, int ca);
+static int purpose_smime(const X509 *x, int ca);
+static int check_purpose_smime_sign(const X509_PURPOSE *xp, const X509 *x, int ca);
+static int check_purpose_smime_encrypt(const X509_PURPOSE *xp, const X509 *x, int ca);
+static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x, int ca);
+static int check_purpose_timestamp_sign(const X509_PURPOSE *xp, const X509 *x, int ca);
+static int no_check(const X509_PURPOSE *xp, const X509 *x, int ca);
+static int ocsp_helper(const X509_PURPOSE *xp, const X509 *x, int ca);
+
+static int xp_cmp(const X509_PURPOSE **a, const X509_PURPOSE **b);
+static void xptable_free(X509_PURPOSE *p);
+
+static X509_PURPOSE xstandard[] = {
+ {X509_PURPOSE_SSL_CLIENT, X509_TRUST_SSL_CLIENT, 0, check_purpose_ssl_client, (char *) "SSL client", (char *) "sslclient", NULL},
+ {X509_PURPOSE_SSL_SERVER, X509_TRUST_SSL_SERVER, 0, check_purpose_ssl_server, (char *) "SSL server", (char *) "sslserver", NULL},
+ {X509_PURPOSE_NS_SSL_SERVER, X509_TRUST_SSL_SERVER, 0, check_purpose_ns_ssl_server, (char *) "Netscape SSL server", (char *) "nssslserver", NULL},
+ {X509_PURPOSE_SMIME_SIGN, X509_TRUST_EMAIL, 0, check_purpose_smime_sign, (char *) "S/MIME signing", (char *) "smimesign", NULL},
+ {X509_PURPOSE_SMIME_ENCRYPT, X509_TRUST_EMAIL, 0, check_purpose_smime_encrypt, (char *) "S/MIME encryption", (char *) "smimeencrypt", NULL},
+ {X509_PURPOSE_CRL_SIGN, X509_TRUST_COMPAT, 0, check_purpose_crl_sign, (char *) "CRL signing", (char *) "crlsign", NULL},
+ {X509_PURPOSE_ANY, X509_TRUST_DEFAULT, 0, no_check, (char *) "Any Purpose", (char *) "any", NULL},
+ {X509_PURPOSE_OCSP_HELPER, X509_TRUST_COMPAT, 0, ocsp_helper, (char *) "OCSP helper", (char *) "ocsphelper", NULL},
+ {X509_PURPOSE_TIMESTAMP_SIGN, X509_TRUST_TSA, 0, check_purpose_timestamp_sign, (char *) "Time Stamp signing", (char *) "timestampsign", NULL},
+};
+
+#define X509_PURPOSE_COUNT (sizeof(xstandard)/sizeof(X509_PURPOSE))
+
+static STACK_OF(X509_PURPOSE) *xptable = NULL;
+
+static int xp_cmp(const X509_PURPOSE **a, const X509_PURPOSE **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(!(x->ex_flags & EXFLAG_SET)) {
+ CRYPTO_w_lock(CRYPTO_LOCK_X509);
+ x509v3_cache_extensions(x);
+ CRYPTO_w_unlock(CRYPTO_LOCK_X509);
+ }
+ if(id == -1) return 1;
+ idx = X509_PURPOSE_get_by_id(id);
+ if(idx == -1) return -1;
+ pt = X509_PURPOSE_get0(idx);
+ return pt->check_purpose(pt, x, ca);
+}
+
+int X509_PURPOSE_set(int *p, int purpose)
+{
+ if(X509_PURPOSE_get_by_id(purpose) == -1) {
+ OPENSSL_PUT_ERROR(X509V3, X509_PURPOSE_set, X509V3_R_INVALID_PURPOSE);
+ return 0;
+ }
+ *p = purpose;
+ return 1;
+}
+
+int X509_PURPOSE_get_count(void)
+{
+ if(!xptable) return X509_PURPOSE_COUNT;
+ return sk_X509_PURPOSE_num(xptable) + X509_PURPOSE_COUNT;
+}
+
+X509_PURPOSE * X509_PURPOSE_get0(int idx)
+{
+ if(idx < 0) return NULL;
+ if(idx < (int)X509_PURPOSE_COUNT) return xstandard + idx;
+ return sk_X509_PURPOSE_value(xptable, idx - X509_PURPOSE_COUNT);
+}
+
+int X509_PURPOSE_get_by_sname(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;
+}
+
+int X509_PURPOSE_get_by_id(int purpose)
+{
+ X509_PURPOSE tmp;
+ size_t idx;
+
+ if((purpose >= X509_PURPOSE_MIN) && (purpose <= X509_PURPOSE_MAX))
+ return purpose - X509_PURPOSE_MIN;
+ tmp.purpose = purpose;
+ if(!xptable) return -1;
+
+ if (!sk_X509_PURPOSE_find(xptable, &idx, &tmp))
+ return -1;
+ return idx + X509_PURPOSE_COUNT;
+}
+
+int X509_PURPOSE_add(int id, int trust, int flags,
+ int (*ck)(const X509_PURPOSE *, const X509 *, int),
+ char *name, char *sname, void *arg)
+{
+ int idx;
+ X509_PURPOSE *ptmp;
+ char *name_dup, *sname_dup;
+
+ /* This is set according to what we change: application can't set it */
+ flags &= ~X509_PURPOSE_DYNAMIC;
+ /* This will always be set for application modified trust entries */
+ flags |= X509_PURPOSE_DYNAMIC_NAME;
+ /* Get existing entry if any */
+ idx = X509_PURPOSE_get_by_id(id);
+ /* Need a new entry */
+ if(idx == -1) {
+ if(!(ptmp = OPENSSL_malloc(sizeof(X509_PURPOSE)))) {
+ OPENSSL_PUT_ERROR(X509V3, X509_PURPOSE_add, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ ptmp->flags = X509_PURPOSE_DYNAMIC;
+ } else ptmp = X509_PURPOSE_get0(idx);
+
+ /* Duplicate the supplied names. */
+ name_dup = BUF_strdup(name);
+ sname_dup = BUF_strdup(sname);
+ if (name_dup == NULL || sname_dup == NULL) {
+ OPENSSL_PUT_ERROR(X509, X509_TRUST_add, ERR_R_MALLOC_FAILURE);
+ if (name_dup != NULL)
+ OPENSSL_free(name_dup);
+ if (sname_dup != NULL)
+ OPENSSL_free(sname_dup);
+ if (idx == -1)
+ OPENSSL_free(ptmp);
+ return 0;
+ }
+
+ /* OPENSSL_free existing name if dynamic */
+ if(ptmp->flags & X509_PURPOSE_DYNAMIC_NAME) {
+ OPENSSL_free(ptmp->name);
+ OPENSSL_free(ptmp->sname);
+ }
+ /* dup supplied name */
+ ptmp->name = 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 && !(xptable = sk_X509_PURPOSE_new(xp_cmp))) {
+ OPENSSL_PUT_ERROR(X509V3, X509_PURPOSE_add, ERR_R_MALLOC_FAILURE);
+ xptable_free(ptmp);
+ return 0;
+ }
+ if (!sk_X509_PURPOSE_push(xptable, ptmp)) {
+ OPENSSL_PUT_ERROR(X509V3, X509_PURPOSE_add, ERR_R_MALLOC_FAILURE);
+ xptable_free(ptmp);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static void xptable_free(X509_PURPOSE *p)
+ {
+ if(!p) return;
+ if (p->flags & X509_PURPOSE_DYNAMIC)
+ {
+ if (p->flags & X509_PURPOSE_DYNAMIC_NAME) {
+ OPENSSL_free(p->name);
+ OPENSSL_free(p->sname);
+ }
+ OPENSSL_free(p);
+ }
+ }
+
+void X509_PURPOSE_cleanup(void)
+{
+ unsigned int i;
+ sk_X509_PURPOSE_pop_free(xptable, xptable_free);
+ for(i = 0; i < X509_PURPOSE_COUNT; i++) xptable_free(xstandard + i);
+ xptable = NULL;
+}
+
+int X509_PURPOSE_get_id(X509_PURPOSE *xp)
+{
+ return xp->purpose;
+}
+
+char *X509_PURPOSE_get0_name(X509_PURPOSE *xp)
+{
+ return xp->name;
+}
+
+char *X509_PURPOSE_get0_sname(X509_PURPOSE *xp)
+{
+ return xp->sname;
+}
+
+int X509_PURPOSE_get_trust(X509_PURPOSE *xp)
+{
+ return xp->trust;
+}
+
+static int nid_cmp(const void *void_a, const void *void_b)
+ {
+ const int *a = void_a, *b = void_b;
+
+ return *a - *b;
+ }
+
+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 */
+ NID_policy_constraints, /* 401 */
+ NID_proxyCertInfo, /* 663 */
+ NID_name_constraints, /* 666 */
+ NID_policy_mappings, /* 747 */
+ NID_inhibit_any_policy /* 748 */
+ };
+
+ int ex_nid = OBJ_obj2nid(X509_EXTENSION_get_object(ex));
+
+ if (ex_nid == NID_undef)
+ return 0;
+
+ if (bsearch(&ex_nid, supported_nids, sizeof(supported_nids)/sizeof(int), sizeof(int), nid_cmp) != NULL)
+ return 1;
+ return 0;
+ }
+
+static void setup_dp(X509 *x, DIST_POINT *dp)
+ {
+ X509_NAME *iname = NULL;
+ size_t 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)
+ {
+ size_t i;
+ x->crldp = X509_get_ext_d2i(x, NID_crl_distribution_points, NULL, NULL);
+ for (i = 0; i < sk_DIST_POINT_num(x->crldp); i++)
+ setup_dp(x, sk_DIST_POINT_value(x->crldp, i));
+ }
+
+static void x509v3_cache_extensions(X509 *x)
+{
+ BASIC_CONSTRAINTS *bs;
+ PROXY_CERT_INFO_EXTENSION *pci;
+ ASN1_BIT_STRING *usage;
+ ASN1_BIT_STRING *ns;
+ EXTENDED_KEY_USAGE *extusage;
+ X509_EXTENSION *ex;
+ size_t i;
+ int j;
+ if(x->ex_flags & EXFLAG_SET) return;
+ X509_digest(x, EVP_sha1(), x->sha1_hash, NULL);
+ /* V1 should mean no extensions ... */
+ if(!X509_get_version(x)) x->ex_flags |= EXFLAG_V1;
+ /* Handle basic constraints */
+ if((bs=X509_get_ext_d2i(x, NID_basic_constraints, NULL, 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;
+ }
+ /* Handle proxy certificates */
+ if((pci=X509_get_ext_d2i(x, NID_proxyCertInfo, NULL, NULL))) {
+ if (x->ex_flags & EXFLAG_CA
+ || X509_get_ext_by_NID(x, NID_subject_alt_name, -1) >= 0
+ || X509_get_ext_by_NID(x, NID_issuer_alt_name, -1) >= 0) {
+ x->ex_flags |= EXFLAG_INVALID;
+ }
+ if (pci->pcPathLengthConstraint) {
+ x->ex_pcpathlen =
+ ASN1_INTEGER_get(pci->pcPathLengthConstraint);
+ } else x->ex_pcpathlen = -1;
+ PROXY_CERT_INFO_EXTENSION_free(pci);
+ x->ex_flags |= EXFLAG_PROXY;
+ }
+ /* Handle key usage */
+ if((usage=X509_get_ext_d2i(x, NID_key_usage, NULL, 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);
+ }
+ x->ex_xkusage = 0;
+ if((extusage=X509_get_ext_d2i(x, NID_ext_key_usage, NULL, NULL))) {
+ x->ex_flags |= EXFLAG_XKUSAGE;
+ for(i = 0; i < sk_ASN1_OBJECT_num(extusage); i++) {
+ switch(OBJ_obj2nid(sk_ASN1_OBJECT_value(extusage,i))) {
+ case NID_server_auth:
+ x->ex_xkusage |= XKU_SSL_SERVER;
+ break;
+
+ case NID_client_auth:
+ x->ex_xkusage |= XKU_SSL_CLIENT;
+ break;
+
+ case NID_email_protect:
+ x->ex_xkusage |= XKU_SMIME;
+ break;
+
+ case NID_code_sign:
+ x->ex_xkusage |= XKU_CODE_SIGN;
+ break;
+
+ case NID_ms_sgc:
+ case NID_ns_sgc:
+ x->ex_xkusage |= XKU_SGC;
+ break;
+
+ case NID_OCSP_sign:
+ x->ex_xkusage |= XKU_OCSP_SIGN;
+ break;
+
+ case NID_time_stamp:
+ x->ex_xkusage |= XKU_TIMESTAMP;
+ break;
+
+ case NID_dvcs:
+ x->ex_xkusage |= XKU_DVCS;
+ break;
+
+ case NID_anyExtendedKeyUsage:
+ x->ex_xkusage |= XKU_ANYEKU;
+ break;
+ }
+ }
+ sk_ASN1_OBJECT_pop_free(extusage, ASN1_OBJECT_free);
+ }
+
+ if((ns=X509_get_ext_d2i(x, NID_netscape_cert_type, NULL, NULL))) {
+ if(ns->length > 0) x->ex_nscert = ns->data[0];
+ else x->ex_nscert = 0;
+ x->ex_flags |= EXFLAG_NSCERT;
+ ASN1_BIT_STRING_free(ns);
+ }
+ x->skid =X509_get_ext_d2i(x, NID_subject_key_identifier, NULL, NULL);
+ x->akid =X509_get_ext_d2i(x, NID_authority_key_identifier, NULL, NULL);
+ /* 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)
+ x->ex_flags |= EXFLAG_SS;
+ }
+ x->altname = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
+ x->nc = X509_get_ext_d2i(x, NID_name_constraints, &j, NULL);
+ if (!x->nc && (j != -1))
+ x->ex_flags |= EXFLAG_INVALID;
+ setup_crldp(x);
+
+ for (j = 0; j < X509_get_ext_count(x); j++)
+ {
+ ex = X509_get_ext(x, j);
+ 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;
+ }
+ }
+ x->ex_flags |= EXFLAG_SET;
+}
+
+/* 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.
+ */
+
+#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_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)
+{
+ if(!(x->ex_flags & EXFLAG_SET)) {
+ CRYPTO_w_lock(CRYPTO_LOCK_X509);
+ x509v3_cache_extensions(x);
+ CRYPTO_w_unlock(CRYPTO_LOCK_X509);
+ }
+
+ return check_ca(x);
+}
+
+/* Check SSL CA: common checks for SSL client and server */
+static int check_ssl_ca(const X509 *x)
+{
+ int ca_ret;
+ ca_ret = check_ca(x);
+ if(!ca_ret) return 0;
+ /* check nsCertType if present */
+ if(ca_ret != 5 || x->ex_nscert & NS_SSL_CA) return ca_ret;
+ else return 0;
+}
+
+
+static int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x, int ca)
+{
+ if(xku_reject(x,XKU_SSL_CLIENT)) return 0;
+ if(ca) return check_ssl_ca(x);
+ /* We need to do digital signatures or key agreement */
+ if(ku_reject(x,KU_DIGITAL_SIGNATURE|KU_KEY_AGREEMENT)) return 0;
+ /* nsCertType if present should allow SSL client use */
+ if(ns_reject(x, NS_SSL_CLIENT)) return 0;
+ return 1;
+}
+/* Key usage needed for TLS/SSL server: digital signature, encipherment or
+ * key agreement. The ssl code can check this more thoroughly for individual
+ * key types.
+ */
+#define KU_TLS \
+ KU_DIGITAL_SIGNATURE|KU_KEY_ENCIPHERMENT|KU_KEY_AGREEMENT
+
+static int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x, int ca)
+{
+ if(xku_reject(x,XKU_SSL_SERVER|XKU_SGC)) return 0;
+ if(ca) return check_ssl_ca(x);
+
+ if(ns_reject(x, NS_SSL_SERVER)) return 0;
+ if(ku_reject(x, KU_TLS)) return 0;
+
+ return 1;
+
+}
+
+static int check_purpose_ns_ssl_server(const X509_PURPOSE *xp, const X509 *x, int ca)
+{
+ int ret;
+ ret = check_purpose_ssl_server(xp, x, ca);
+ if(!ret || ca) return ret;
+ /* We need to encipher or Netscape complains */
+ if(ku_reject(x, KU_KEY_ENCIPHERMENT)) return 0;
+ return ret;
+}
+
+/* common S/MIME checks */
+static int purpose_smime(const X509 *x, int ca)
+{
+ if(xku_reject(x,XKU_SMIME)) return 0;
+ if(ca) {
+ int ca_ret;
+ ca_ret = check_ca(x);
+ if(!ca_ret) return 0;
+ /* check nsCertType if present */
+ if(ca_ret != 5 || x->ex_nscert & NS_SMIME_CA) return ca_ret;
+ else return 0;
+ }
+ if(x->ex_flags & EXFLAG_NSCERT) {
+ if(x->ex_nscert & NS_SMIME) return 1;
+ /* Workaround for some buggy certificates */
+ if(x->ex_nscert & NS_SSL_CLIENT) return 2;
+ return 0;
+ }
+ return 1;
+}
+
+static int check_purpose_smime_sign(const X509_PURPOSE *xp, const X509 *x, int ca)
+{
+ int ret;
+ ret = purpose_smime(x, ca);
+ if(!ret || ca) return ret;
+ if(ku_reject(x, KU_DIGITAL_SIGNATURE|KU_NON_REPUDIATION)) return 0;
+ return ret;
+}
+
+static int check_purpose_smime_encrypt(const X509_PURPOSE *xp, const X509 *x, int ca)
+{
+ int ret;
+ ret = purpose_smime(x, ca);
+ if(!ret || ca) return ret;
+ if(ku_reject(x, KU_KEY_ENCIPHERMENT)) return 0;
+ return ret;
+}
+
+static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x, int ca)
+{
+ if(ca) {
+ int ca_ret;
+ if((ca_ret = check_ca(x)) != 2) return ca_ret;
+ else return 0;
+ }
+ if(ku_reject(x, KU_CRL_SIGN)) return 0;
+ return 1;
+}
+
+/* OCSP helper: this is *not* a full OCSP check. It just checks that
+ * each CA is valid. Additional checks must be made on the chain.
+ */
+
+static int ocsp_helper(const X509_PURPOSE *xp, const X509 *x, int ca)
+{
+ /* Must be a valid CA. Should we really support the "I don't know"
+ value (2)? */
+ if(ca) return check_ca(x);
+ /* leaf certificate is checked in OCSP_verify() */
+ return 1;
+}
+
+static int check_purpose_timestamp_sign(const X509_PURPOSE *xp, const X509 *x,
+ int ca)
+{
+ int i_ext;
+
+ /* If ca is true we must return if this is a valid CA certificate. */
+ if (ca) return check_ca(x);
+
+ /*
+ * Check the optional key usage field:
+ * if Key Usage is present, it must be one of digitalSignature
+ * and/or nonRepudiation (other values are not consistent and shall
+ * be rejected).
+ */
+ if ((x->ex_flags & EXFLAG_KUSAGE)
+ && ((x->ex_kusage & ~(KU_NON_REPUDIATION | KU_DIGITAL_SIGNATURE)) ||
+ !(x->ex_kusage & (KU_NON_REPUDIATION | KU_DIGITAL_SIGNATURE))))
+ return 0;
+
+ /* Only time stamp key usage is permitted and it's required. */
+ if (!(x->ex_flags & EXFLAG_XKUSAGE) || x->ex_xkusage != XKU_TIMESTAMP)
+ return 0;
+
+ /* Extended Key Usage MUST be critical */
+ i_ext = X509_get_ext_by_NID((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;
+ x509v3_cache_extensions(issuer);
+ x509v3_cache_extensions(subject);
+
+ if(subject->akid)
+ {
+ int ret = X509_check_akid(issuer, subject->akid);
+ if (ret != X509_V_OK)
+ return ret;
+ }
+
+ if(subject->ex_flags & EXFLAG_PROXY)
+ {
+ if(ku_reject(issuer, KU_DIGITAL_SIGNATURE))
+ return X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE;
+ }
+ else if(ku_reject(issuer, KU_KEY_CERT_SIGN))
+ return X509_V_ERR_KEYUSAGE_NO_CERTSIGN;
+ return X509_V_OK;
+}
+
+int X509_check_akid(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;
+ size_t 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;
+ }
+
diff --git a/src/crypto/x509v3/v3_skey.c b/src/crypto/x509v3/v3_skey.c
new file mode 100644
index 0000000..471a1ab
--- /dev/null
+++ b/src/crypto/x509v3/v3_skey.c
@@ -0,0 +1,148 @@
+/* v3_skey.c */
+/* 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 <stdio.h>
+#include <string.h>
+
+#include <openssl/digest.h>
+#include <openssl/err.h>
+#include <openssl/obj.h>
+#include <openssl/x509v3.h>
+
+
+static ASN1_OCTET_STRING *s2i_skey_id(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, char *str);
+const X509V3_EXT_METHOD v3_skey_id = {
+NID_subject_key_identifier, 0, ASN1_ITEM_ref(ASN1_OCTET_STRING),
+0,0,0,0,
+(X509V3_EXT_I2S)i2s_ASN1_OCTET_STRING,
+(X509V3_EXT_S2I)s2i_skey_id,
+0,0,0,0,
+NULL};
+
+char *i2s_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method,
+ ASN1_OCTET_STRING *oct)
+{
+ return hex_to_string(oct->data, oct->length);
+}
+
+ASN1_OCTET_STRING *s2i_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, char *str)
+{
+ ASN1_OCTET_STRING *oct;
+ long length;
+
+ if(!(oct = M_ASN1_OCTET_STRING_new())) {
+ OPENSSL_PUT_ERROR(X509V3, s2i_ASN1_OCTET_STRING, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ if(!(oct->data = string_to_hex(str, &length))) {
+ M_ASN1_OCTET_STRING_free(oct);
+ return NULL;
+ }
+
+ oct->length = length;
+
+ return oct;
+
+}
+
+static ASN1_OCTET_STRING *s2i_skey_id(X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, char *str)
+{
+ ASN1_OCTET_STRING *oct;
+ 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 = M_ASN1_OCTET_STRING_new())) {
+ OPENSSL_PUT_ERROR(X509V3, s2i_skey_id, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ if(ctx && (ctx->flags == CTX_TEST)) return oct;
+
+ if(!ctx || (!ctx->subject_req && !ctx->subject_cert)) {
+ OPENSSL_PUT_ERROR(X509V3, s2i_skey_id, 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) {
+ OPENSSL_PUT_ERROR(X509V3, s2i_skey_id, X509V3_R_NO_PUBLIC_KEY);
+ goto err;
+ }
+
+ if (!EVP_Digest(pk->data, pk->length, pkey_dig, &diglen, EVP_sha1(), NULL))
+ goto err;
+
+ if(!M_ASN1_OCTET_STRING_set(oct, pkey_dig, diglen)) {
+ OPENSSL_PUT_ERROR(X509V3, s2i_skey_id, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ return oct;
+
+ err:
+ M_ASN1_OCTET_STRING_free(oct);
+ return NULL;
+}
diff --git a/src/crypto/x509v3/v3_sxnet.c b/src/crypto/x509v3/v3_sxnet.c
new file mode 100644
index 0000000..bb5e214
--- /dev/null
+++ b/src/crypto/x509v3/v3_sxnet.c
@@ -0,0 +1,266 @@
+/* v3_sxnet.c */
+/* 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 <stdio.h>
+#include <string.h>
+
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/conf.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/x509v3.h>
+
+
+/* Support for Thawte strong extranet extension */
+
+#define SXNET_TEST
+
+static int sxnet_i2r(X509V3_EXT_METHOD *method, SXNET *sx, BIO *out, int indent);
+#ifdef SXNET_TEST
+static SXNET * sxnet_v2i(X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE) *nval);
+#endif
+const X509V3_EXT_METHOD v3_sxnet = {
+NID_sxnet, X509V3_EXT_MULTILINE, ASN1_ITEM_ref(SXNET),
+0,0,0,0,
+0,0,
+0,
+#ifdef SXNET_TEST
+(X509V3_EXT_V2I)sxnet_v2i,
+#else
+0,
+#endif
+(X509V3_EXT_I2R)sxnet_i2r,
+0,
+NULL
+};
+
+ASN1_SEQUENCE(SXNETID) = {
+ ASN1_SIMPLE(SXNETID, zone, ASN1_INTEGER),
+ ASN1_SIMPLE(SXNETID, user, ASN1_OCTET_STRING)
+} ASN1_SEQUENCE_END(SXNETID)
+
+IMPLEMENT_ASN1_FUNCTIONS(SXNETID)
+
+ASN1_SEQUENCE(SXNET) = {
+ ASN1_SIMPLE(SXNET, version, ASN1_INTEGER),
+ ASN1_SEQUENCE_OF(SXNET, ids, SXNETID)
+} ASN1_SEQUENCE_END(SXNET)
+
+IMPLEMENT_ASN1_FUNCTIONS(SXNET)
+
+static int sxnet_i2r(X509V3_EXT_METHOD *method, SXNET *sx, BIO *out,
+ int indent)
+{
+ long v;
+ char *tmp;
+ SXNETID *id;
+ size_t i;
+ v = ASN1_INTEGER_get(sx->version);
+ BIO_printf(out, "%*sVersion: %ld (0x%lX)", indent, "", v + 1, v);
+ for(i = 0; i < sk_SXNETID_num(sx->ids); i++) {
+ id = sk_SXNETID_value(sx->ids, i);
+ tmp = i2s_ASN1_INTEGER(NULL, id->zone);
+ BIO_printf(out, "\n%*sZone: %s, User: ", indent, "", tmp);
+ OPENSSL_free(tmp);
+ M_ASN1_OCTET_STRING_print(out, id->user);
+ }
+ return 1;
+}
+
+#ifdef SXNET_TEST
+
+/* NBB: this is used for testing only. It should *not* be used for anything
+ * else because it will just take static IDs from the configuration file and
+ * they should really be separate values for each user.
+ */
+
+
+static SXNET * sxnet_v2i(X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
+ STACK_OF(CONF_VALUE) *nval)
+{
+ CONF_VALUE *cnf;
+ SXNET *sx = NULL;
+ size_t i;
+ for(i = 0; i < sk_CONF_VALUE_num(nval); i++) {
+ cnf = sk_CONF_VALUE_value(nval, i);
+ if(!SXNET_add_id_asc(&sx, cnf->name, cnf->value, -1))
+ return NULL;
+ }
+ return sx;
+}
+
+
+#endif
+
+/* Strong Extranet utility functions */
+
+/* Add an id given the zone as an ASCII number */
+
+int SXNET_add_id_asc(SXNET **psx, char *zone, char *user,
+ int userlen)
+{
+ ASN1_INTEGER *izone = NULL;
+ if(!(izone = s2i_ASN1_INTEGER(NULL, zone))) {
+ OPENSSL_PUT_ERROR(X509V3, SXNET_add_id_asc, X509V3_R_ERROR_CONVERTING_ZONE);
+ return 0;
+ }
+ return SXNET_add_id_INTEGER(psx, izone, user, userlen);
+}
+
+/* Add an id given the zone as an unsigned long */
+
+int SXNET_add_id_ulong(SXNET **psx, unsigned long lzone, char *user,
+ int userlen)
+{
+ ASN1_INTEGER *izone = NULL;
+ if(!(izone = M_ASN1_INTEGER_new()) || !ASN1_INTEGER_set(izone, lzone)) {
+ OPENSSL_PUT_ERROR(X509V3, SXNET_add_id_ulong, ERR_R_MALLOC_FAILURE);
+ M_ASN1_INTEGER_free(izone);
+ return 0;
+ }
+ return SXNET_add_id_INTEGER(psx, izone, user, userlen);
+
+}
+
+/* Add an id given the zone as an ASN1_INTEGER.
+ * Note this version uses the passed integer and doesn't make a copy so don't
+ * free it up afterwards.
+ */
+
+int SXNET_add_id_INTEGER(SXNET **psx, ASN1_INTEGER *zone, char *user,
+ int userlen)
+{
+ SXNET *sx = NULL;
+ SXNETID *id = NULL;
+ if(!psx || !zone || !user) {
+ OPENSSL_PUT_ERROR(X509V3, SXNET_add_id_INTEGER, X509V3_R_INVALID_NULL_ARGUMENT);
+ return 0;
+ }
+ if(userlen == -1) userlen = strlen(user);
+ if(userlen > 64) {
+ OPENSSL_PUT_ERROR(X509V3, SXNET_add_id_INTEGER, X509V3_R_USER_TOO_LONG);
+ return 0;
+ }
+ if(!*psx) {
+ if(!(sx = SXNET_new())) goto err;
+ if(!ASN1_INTEGER_set(sx->version, 0)) goto err;
+ *psx = sx;
+ } else sx = *psx;
+ if(SXNET_get_id_INTEGER(sx, zone)) {
+ OPENSSL_PUT_ERROR(X509V3, SXNET_add_id_INTEGER, X509V3_R_DUPLICATE_ZONE_ID);
+ return 0;
+ }
+
+ if(!(id = SXNETID_new())) goto err;
+ if(userlen == -1) userlen = strlen(user);
+
+ if(!M_ASN1_OCTET_STRING_set(id->user, user, userlen)) goto err;
+ if(!sk_SXNETID_push(sx->ids, id)) goto err;
+ id->zone = zone;
+ return 1;
+
+ err:
+ OPENSSL_PUT_ERROR(X509V3, SXNET_add_id_INTEGER, ERR_R_MALLOC_FAILURE);
+ SXNETID_free(id);
+ SXNET_free(sx);
+ *psx = NULL;
+ return 0;
+}
+
+ASN1_OCTET_STRING *SXNET_get_id_asc(SXNET *sx, char *zone)
+{
+ ASN1_INTEGER *izone = NULL;
+ ASN1_OCTET_STRING *oct;
+ if(!(izone = s2i_ASN1_INTEGER(NULL, zone))) {
+ OPENSSL_PUT_ERROR(X509V3, SXNET_get_id_asc, X509V3_R_ERROR_CONVERTING_ZONE);
+ return NULL;
+ }
+ oct = SXNET_get_id_INTEGER(sx, izone);
+ M_ASN1_INTEGER_free(izone);
+ return oct;
+}
+
+ASN1_OCTET_STRING *SXNET_get_id_ulong(SXNET *sx, unsigned long lzone)
+{
+ ASN1_INTEGER *izone = NULL;
+ ASN1_OCTET_STRING *oct;
+ if(!(izone = M_ASN1_INTEGER_new()) || !ASN1_INTEGER_set(izone, lzone)) {
+ OPENSSL_PUT_ERROR(X509V3, SXNET_get_id_ulong, ERR_R_MALLOC_FAILURE);
+ M_ASN1_INTEGER_free(izone);
+ return NULL;
+ }
+ oct = SXNET_get_id_INTEGER(sx, izone);
+ M_ASN1_INTEGER_free(izone);
+ return oct;
+}
+
+ASN1_OCTET_STRING *SXNET_get_id_INTEGER(SXNET *sx, ASN1_INTEGER *zone)
+{
+ SXNETID *id;
+ size_t i;
+ for(i = 0; i < sk_SXNETID_num(sx->ids); i++) {
+ id = sk_SXNETID_value(sx->ids, i);
+ if(!M_ASN1_INTEGER_cmp(id->zone, zone)) return id->user;
+ }
+ return NULL;
+}
+
+IMPLEMENT_ASN1_SET_OF(SXNETID)
diff --git a/src/crypto/x509v3/v3_utl.c b/src/crypto/x509v3/v3_utl.c
new file mode 100644
index 0000000..d081c1c
--- /dev/null
+++ b/src/crypto/x509v3/v3_utl.c
@@ -0,0 +1,1295 @@
+/* v3_utl.c */
+/* 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).
+ *
+ */
+/* X509 v3 extension utilities */
+
+
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <openssl/bn.h>
+#include <openssl/buf.h>
+#include <openssl/conf.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/x509v3.h>
+
+
+static char *strip_spaces(char *name);
+static int sk_strcmp(const OPENSSL_STRING *a, const OPENSSL_STRING *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;
+ char *tname = NULL, *tvalue = NULL;
+ if(name && !(tname = BUF_strdup(name))) goto err;
+ if(value && !(tvalue = BUF_strdup(value))) goto err;
+ if(!(vtmp = (CONF_VALUE *)OPENSSL_malloc(sizeof(CONF_VALUE)))) goto err;
+ if(!*extlist && !(*extlist = sk_CONF_VALUE_new_null())) goto err;
+ vtmp->section = NULL;
+ vtmp->name = tname;
+ vtmp->value = tvalue;
+ if(!sk_CONF_VALUE_push(*extlist, vtmp)) goto err;
+ return 1;
+ err:
+ OPENSSL_PUT_ERROR(X509V3, X509V3_add_value, ERR_R_MALLOC_FAILURE);
+ if(vtmp) OPENSSL_free(vtmp);
+ if(tname) OPENSSL_free(tname);
+ if(tvalue) OPENSSL_free(tvalue);
+ return 0;
+}
+
+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);
+ }
+
+/* Free function for STACK_OF(CONF_VALUE) */
+
+void X509V3_conf_free(CONF_VALUE *conf)
+{
+ if(!conf) return;
+ if(conf->name) OPENSSL_free(conf->name);
+ if(conf->value) OPENSSL_free(conf->value);
+ if(conf->section) OPENSSL_free(conf->section);
+ OPENSSL_free(conf);
+}
+
+int X509V3_add_value_bool(const char *name, int asn1_bool,
+ STACK_OF(CONF_VALUE) **extlist)
+{
+ if(asn1_bool) return X509V3_add_value(name, "TRUE", extlist);
+ return X509V3_add_value(name, "FALSE", extlist);
+}
+
+int X509V3_add_value_bool_nf(char *name, int asn1_bool,
+ STACK_OF(CONF_VALUE) **extlist)
+{
+ if(asn1_bool) return X509V3_add_value(name, "TRUE", extlist);
+ return 1;
+}
+
+
+char *i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *method, ASN1_ENUMERATED *a)
+{
+ BIGNUM *bntmp = NULL;
+ char *strtmp = NULL;
+ if(!a) return NULL;
+ if(!(bntmp = ASN1_ENUMERATED_to_BN(a, NULL)) ||
+ !(strtmp = BN_bn2dec(bntmp)) )
+ OPENSSL_PUT_ERROR(X509V3, i2s_ASN1_ENUMERATED, ERR_R_MALLOC_FAILURE);
+ BN_free(bntmp);
+ return strtmp;
+}
+
+char *i2s_ASN1_INTEGER(X509V3_EXT_METHOD *method, ASN1_INTEGER *a)
+{
+ BIGNUM *bntmp = NULL;
+ char *strtmp = NULL;
+ if(!a) return NULL;
+ if(!(bntmp = ASN1_INTEGER_to_BN(a, NULL)) ||
+ !(strtmp = BN_bn2dec(bntmp)) )
+ OPENSSL_PUT_ERROR(X509V3, i2s_ASN1_INTEGER, ERR_R_MALLOC_FAILURE);
+ BN_free(bntmp);
+ return strtmp;
+}
+
+ASN1_INTEGER *s2i_ASN1_INTEGER(X509V3_EXT_METHOD *method, char *value)
+{
+ BIGNUM *bn = NULL;
+ ASN1_INTEGER *aint;
+ int isneg, ishex;
+ int ret;
+ if (!value) {
+ OPENSSL_PUT_ERROR(X509V3, s2i_ASN1_INTEGER, X509V3_R_INVALID_NULL_VALUE);
+ return 0;
+ }
+ bn = BN_new();
+ if (value[0] == '-') {
+ value++;
+ isneg = 1;
+ } else isneg = 0;
+
+ if (value[0] == '0' && ((value[1] == 'x') || (value[1] == 'X'))) {
+ value += 2;
+ ishex = 1;
+ } else ishex = 0;
+
+ if (ishex) ret = BN_hex2bn(&bn, value);
+ else ret = BN_dec2bn(&bn, value);
+
+ if (!ret || value[ret]) {
+ BN_free(bn);
+ OPENSSL_PUT_ERROR(X509V3, s2i_ASN1_INTEGER, X509V3_R_BN_DEC2BN_ERROR);
+ return 0;
+ }
+
+ if (isneg && BN_is_zero(bn)) isneg = 0;
+
+ aint = BN_to_ASN1_INTEGER(bn, NULL);
+ BN_free(bn);
+ if (!aint) {
+ OPENSSL_PUT_ERROR(X509V3, s2i_ASN1_INTEGER, X509V3_R_BN_TO_ASN1_INTEGER_ERROR);
+ return 0;
+ }
+ if (isneg) aint->type |= V_ASN1_NEG;
+ return aint;
+}
+
+int X509V3_add_value_int(const char *name, 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);
+ OPENSSL_free(strtmp);
+ return ret;
+}
+
+int X509V3_get_value_bool(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:
+ OPENSSL_PUT_ERROR(X509V3, X509V3_get_value_bool, X509V3_R_INVALID_BOOLEAN_STRING);
+ X509V3_conf_err(value);
+ return 0;
+}
+
+int X509V3_get_value_int(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;
+}
+
+#define HDR_NAME 1
+#define HDR_VALUE 2
+
+/*#define DEBUG*/
+
+STACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line)
+{
+ char *p, *q, c;
+ char *ntmp, *vtmp;
+ STACK_OF(CONF_VALUE) *values = NULL;
+ char *linebuf;
+ int state;
+ /* We are going to modify the line so copy it first */
+ linebuf = BUF_strdup(line);
+ 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) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_parse_list, X509V3_R_INVALID_NULL_NAME);
+ goto err;
+ }
+ q = p + 1;
+ } else if(c == ',') {
+ *p = 0;
+ ntmp = strip_spaces(q);
+ q = p + 1;
+#if 0
+ printf("%s\n", ntmp);
+#endif
+ if(!ntmp) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_parse_list, X509V3_R_INVALID_NULL_NAME);
+ goto err;
+ }
+ X509V3_add_value(ntmp, NULL, &values);
+ }
+ break ;
+
+ case HDR_VALUE:
+ if(c == ',') {
+ state = HDR_NAME;
+ *p = 0;
+ vtmp = strip_spaces(q);
+#if 0
+ printf("%s\n", ntmp);
+#endif
+ if(!vtmp) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_parse_list, X509V3_R_INVALID_NULL_VALUE);
+ goto err;
+ }
+ X509V3_add_value(ntmp, vtmp, &values);
+ ntmp = NULL;
+ q = p + 1;
+ }
+
+ }
+ }
+
+ if(state == HDR_VALUE) {
+ vtmp = strip_spaces(q);
+#if 0
+ printf("%s=%s\n", ntmp, vtmp);
+#endif
+ if(!vtmp) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_parse_list, X509V3_R_INVALID_NULL_VALUE);
+ goto err;
+ }
+ X509V3_add_value(ntmp, vtmp, &values);
+ } else {
+ ntmp = strip_spaces(q);
+#if 0
+ printf("%s\n", ntmp);
+#endif
+ if(!ntmp) {
+ OPENSSL_PUT_ERROR(X509V3, X509V3_parse_list, X509V3_R_INVALID_NULL_NAME);
+ goto err;
+ }
+ X509V3_add_value(ntmp, NULL, &values);
+ }
+OPENSSL_free(linebuf);
+return values;
+
+err:
+OPENSSL_free(linebuf);
+sk_CONF_VALUE_pop_free(values, X509V3_conf_free);
+return NULL;
+
+}
+
+/* Delete leading and trailing spaces from a string */
+static char *strip_spaces(char *name)
+{
+ char *p, *q;
+ /* Skip over leading spaces */
+ p = name;
+ while(*p && 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;
+}
+
+/* hex string utilities */
+
+/* Given a buffer of length 'len' return a OPENSSL_malloc'ed string with its
+ * hex representation
+ * @@@ (Contents of buffer are always kept in ASCII, also on EBCDIC machines)
+ */
+
+char *hex_to_string(const unsigned char *buffer, long len)
+{
+ char *tmp, *q;
+ const unsigned char *p;
+ int i;
+ static const char hexdig[] = "0123456789ABCDEF";
+ if(!buffer || !len) return NULL;
+ if(!(tmp = OPENSSL_malloc(len * 3 + 1))) {
+ OPENSSL_PUT_ERROR(X509V3, hex_to_string, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ q = tmp;
+ for(i = 0, p = buffer; i < len; i++,p++) {
+ *q++ = hexdig[(*p >> 4) & 0xf];
+ *q++ = hexdig[*p & 0xf];
+ *q++ = ':';
+ }
+ q[-1] = 0;
+
+ return tmp;
+}
+
+/* Give a string of hex digits convert to
+ * a buffer
+ */
+
+unsigned char *string_to_hex(const char *str, long *len)
+{
+ unsigned char *hexbuf, *q;
+ unsigned char ch, cl, *p;
+ if(!str) {
+ OPENSSL_PUT_ERROR(X509V3, string_to_hex, X509V3_R_INVALID_NULL_ARGUMENT);
+ return NULL;
+ }
+ if(!(hexbuf = OPENSSL_malloc(strlen(str) >> 1))) goto err;
+ for(p = (unsigned char *)str, q = hexbuf; *p;) {
+ ch = *p++;
+ if(ch == ':') continue;
+ cl = *p++;
+ if(!cl) {
+ OPENSSL_PUT_ERROR(X509V3, string_to_hex, X509V3_R_ODD_NUMBER_OF_DIGITS);
+ OPENSSL_free(hexbuf);
+ return NULL;
+ }
+ if(isupper(ch)) ch = tolower(ch);
+ if(isupper(cl)) cl = tolower(cl);
+
+ if((ch >= '0') && (ch <= '9')) ch -= '0';
+ else if ((ch >= 'a') && (ch <= 'f')) ch -= 'a' - 10;
+ else goto badhex;
+
+ if((cl >= '0') && (cl <= '9')) cl -= '0';
+ else if ((cl >= 'a') && (cl <= 'f')) cl -= 'a' - 10;
+ else goto badhex;
+
+ *q++ = (ch << 4) | cl;
+ }
+
+ if(len) *len = q - hexbuf;
+
+ return hexbuf;
+
+ err:
+ if(hexbuf) OPENSSL_free(hexbuf);
+ OPENSSL_PUT_ERROR(X509V3, string_to_hex, ERR_R_MALLOC_FAILURE);
+ return NULL;
+
+ badhex:
+ OPENSSL_free(hexbuf);
+ OPENSSL_PUT_ERROR(X509V3, string_to_hex, X509V3_R_ILLEGAL_HEX_DIGIT);
+ return NULL;
+
+}
+
+/* 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 OPENSSL_STRING *a, const OPENSSL_STRING *b)
+{
+ return strcmp(*a, *b);
+}
+
+STACK_OF(OPENSSL_STRING) *X509_get1_email(X509 *x)
+{
+ GENERAL_NAMES *gens;
+ STACK_OF(OPENSSL_STRING) *ret;
+
+ gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
+ ret = get_email(X509_get_subject_name(x), gens);
+ sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
+ return ret;
+}
+
+STACK_OF(OPENSSL_STRING) *X509_get1_ocsp(X509 *x)
+{
+ AUTHORITY_INFO_ACCESS *info;
+ STACK_OF(OPENSSL_STRING) *ret = NULL;
+ size_t i;
+
+ info = X509_get_ext_d2i(x, NID_info_access, NULL, NULL);
+ if (!info)
+ return NULL;
+ for (i = 0; i < sk_ACCESS_DESCRIPTION_num(info); i++)
+ {
+ ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(info, i);
+ if (OBJ_obj2nid(ad->method) == NID_ad_OCSP)
+ {
+ if (ad->location->type == GEN_URI)
+ {
+ if (!append_ia5(&ret, ad->location->d.uniformResourceIdentifier))
+ break;
+ }
+ }
+ }
+ AUTHORITY_INFO_ACCESS_free(info);
+ return ret;
+}
+
+STACK_OF(OPENSSL_STRING) *X509_REQ_get1_email(X509_REQ *x)
+{
+ GENERAL_NAMES *gens;
+ STACK_OF(X509_EXTENSION) *exts;
+ STACK_OF(OPENSSL_STRING) *ret;
+
+ exts = X509_REQ_get_extensions(x);
+ gens = X509V3_get_d2i(exts, NID_subject_alt_name, NULL, NULL);
+ ret = get_email(X509_REQ_get_subject_name(x), gens);
+ sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
+ sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
+ return ret;
+}
+
+
+static STACK_OF(OPENSSL_STRING) *get_email(X509_NAME *name, GENERAL_NAMES *gens)
+{
+ STACK_OF(OPENSSL_STRING) *ret = NULL;
+ X509_NAME_ENTRY *ne;
+ ASN1_IA5STRING *email;
+ GENERAL_NAME *gen;
+ int i;
+ size_t j;
+ /* 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(j = 0; j < sk_GENERAL_NAME_num(gens); j++)
+ {
+ gen = sk_GENERAL_NAME_value(gens, j);
+ if(gen->type != GEN_EMAIL) continue;
+ if(!append_ia5(&ret, gen->d.ia5)) return NULL;
+ }
+ return ret;
+}
+
+static void str_free(OPENSSL_STRING str)
+{
+ OPENSSL_free(str);
+}
+
+static int append_ia5(STACK_OF(OPENSSL_STRING) **sk, 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, NULL, (char *)email->data)) return 1;
+ emtmp = BUF_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);
+}
+
+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;
+ }
+ }
+
+/* Compare while ASCII ignoring case. */
+static int equal_nocase(const unsigned char *pattern, size_t pattern_len,
+ const unsigned char *subject, size_t subject_len,
+ unsigned int flags)
+ {
+ skip_prefix(&pattern, &pattern_len, subject, subject_len, flags);
+ if (pattern_len != subject_len)
+ return 0;
+ while (pattern_len)
+ {
+ unsigned char l = *pattern;
+ unsigned char r = *subject;
+ /* The pattern must not contain NUL characters. */
+ if (l == 0)
+ return 0;
+ if (l != r)
+ {
+ if ('A' <= l && l <= 'Z')
+ l = (l - 'A') + 'a';
+ if ('A' <= r && r <= 'Z')
+ r = (r - 'A') + 'a';
+ if (l != r)
+ return 0;
+ }
+ ++pattern;
+ ++subject;
+ --pattern_len;
+ }
+ return 1;
+ }
+
+/* Compare using memcmp. */
+static int equal_case(const unsigned char *pattern, size_t pattern_len,
+ const unsigned char *subject, size_t subject_len,
+ unsigned int flags)
+{
+ skip_prefix(&pattern, &pattern_len, subject, subject_len, flags);
+ if (pattern_len != subject_len)
+ return 0;
+ return !memcmp(pattern, subject, pattern_len);
+}
+
+/* RFC 5280, section 7.5, requires that only the domain is compared in
+ a case-insensitive manner. */
+static int equal_email(const unsigned char *a, size_t a_len,
+ const unsigned char *b, size_t b_len,
+ unsigned int unused_flags)
+ {
+ size_t i = a_len;
+ if (a_len != b_len)
+ return 0;
+ /* We search backwards for the '@' character, so that we do
+ not have to deal with quoted local-parts. The domain part
+ is compared in a case-insensitive manner. */
+ while (i > 0)
+ {
+ --i;
+ if (a[i] == '@' || b[i] == '@')
+ {
+ if (!equal_nocase(a + i, a_len - i,
+ b + i, a_len - i, 0))
+ return 0;
+ break;
+ }
+ }
+ if (i == 0)
+ i = a_len;
+ return equal_case(a, i, b, i, 0);
+ }
+
+/* Compare the prefix and suffix with the subject, and check that the
+ characters in-between are valid. */
+static int wildcard_match(const unsigned char *prefix, size_t prefix_len,
+ const unsigned char *suffix, size_t suffix_len,
+ const unsigned char *subject, size_t subject_len,
+ unsigned int flags)
+ {
+ const unsigned char *wildcard_start;
+ const unsigned char *wildcard_end;
+ const unsigned char *p;
+ int allow_multi = 0;
+ int allow_idna = 0;
+
+ if (subject_len < prefix_len + suffix_len)
+ return 0;
+ if (!equal_nocase(prefix, prefix_len, subject, prefix_len, flags))
+ return 0;
+ wildcard_start = subject + prefix_len;
+ wildcard_end = subject + (subject_len - suffix_len);
+ if (!equal_nocase(wildcard_end, suffix_len, suffix, suffix_len, flags))
+ return 0;
+ /*
+ * If the wildcard makes up the entire first label, it must match at
+ * least one character.
+ */
+ if (prefix_len == 0 && *suffix == '.')
+ {
+ if (wildcard_start == wildcard_end)
+ return 0;
+ allow_idna = 1;
+ if (flags & X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS)
+ allow_multi = 1;
+ }
+ /* IDNA labels cannot match partial wildcards */
+ if (!allow_idna &&
+ subject_len >= 4 && OPENSSL_strncasecmp((char *)subject, "xn--", 4) == 0)
+ return 0;
+ /* The wildcard may match a literal '*' */
+ if (wildcard_end == wildcard_start + 1 && *wildcard_start == '*')
+ return 1;
+ /*
+ * Check that the part matched by the wildcard contains only
+ * permitted characters and only matches a single label unless
+ * allow_multi is set.
+ */
+ for (p = wildcard_start; p != wildcard_end; ++p)
+ if (!(('0' <= *p && *p <= '9') ||
+ ('A' <= *p && *p <= 'Z') ||
+ ('a' <= *p && *p <= 'z') ||
+ *p == '-' || (allow_multi && *p == '.')))
+ return 0;
+ return 1;
+ }
+
+#define LABEL_START (1 << 0)
+#define LABEL_END (1 << 1)
+#define LABEL_HYPHEN (1 << 2)
+#define LABEL_IDNA (1 << 3)
+
+static const unsigned char *valid_star(const unsigned char *p, size_t len,
+ unsigned int flags)
+ {
+ const unsigned char *star = 0;
+ size_t i;
+ int state = LABEL_START;
+ int dots = 0;
+ for (i = 0; i < len; ++i)
+ {
+ /*
+ * Locate first and only legal wildcard, either at the start
+ * or end of a non-IDNA first and not final label.
+ */
+ if (p[i] == '*')
+ {
+ int atstart = (state & LABEL_START);
+ int atend = (i == len - 1 || p[i+i] == '.');
+ /*
+ * 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
+ && OPENSSL_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] == '-')
+ {
+ if (state & LABEL_HYPHEN)
+ 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 unsigned char *b, size_t blen)
+ {
+ if (!a->data || !a->length)
+ return 0;
+ if (cmp_type > 0)
+ {
+ if (cmp_type != a->type)
+ return 0;
+ if (cmp_type == V_ASN1_IA5STRING)
+ return equal(a->data, a->length, b, blen, flags);
+ if (a->length == (int)blen && !memcmp(a->data, b, blen))
+ return 1;
+ else
+ return 0;
+ }
+ else
+ {
+ int astrlen, rv;
+ unsigned char *astr;
+ astrlen = ASN1_STRING_to_UTF8(&astr, a);
+ if (astrlen < 0)
+ return -1;
+ rv = equal(astr, astrlen, b, blen, flags);
+ OPENSSL_free(astr);
+ return rv;
+ }
+ }
+
+static int do_x509_check(X509 *x, const unsigned char *chk, size_t chklen,
+ unsigned int flags, int check_type)
+ {
+ GENERAL_NAMES *gens = NULL;
+ X509_NAME *name = NULL;
+ size_t i;
+ int j;
+ int cnid;
+ int alt_type;
+ int san_present = 0;
+ equal_fn equal;
+
+ /* See below, this flag is internal-only */
+ flags &= ~_X509_CHECK_FLAG_DOT_SUBDOMAINS;
+ if (check_type == GEN_EMAIL)
+ {
+ cnid = NID_pkcs9_emailAddress;
+ alt_type = V_ASN1_IA5STRING;
+ equal = equal_email;
+ }
+ else if (check_type == GEN_DNS)
+ {
+ cnid = NID_commonName;
+ /* Implicit client-side DNS sub-domain pattern */
+ if (chklen > 1 && chk[0] == '.')
+ flags |= _X509_CHECK_FLAG_DOT_SUBDOMAINS;
+ alt_type = V_ASN1_IA5STRING;
+ if (flags & X509_CHECK_FLAG_NO_WILDCARDS)
+ equal = equal_nocase;
+ else
+ equal = equal_wildcard;
+ }
+ else
+ {
+ cnid = 0;
+ alt_type = V_ASN1_OCTET_STRING;
+ equal = equal_case;
+ }
+
+ if (chklen == 0)
+ chklen = strlen((const char *)chk);
+
+ gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
+ if (gens)
+ {
+ int rv = 0;
+ 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;
+ if (do_check_string(cstr, alt_type, equal, flags,
+ chk, chklen))
+ {
+ rv = 1;
+ break;
+ }
+ }
+ GENERAL_NAMES_free(gens);
+ if (rv)
+ return 1;
+ if (!cnid
+ || (san_present
+ && !(flags & X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT)))
+ 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;
+ ne = X509_NAME_get_entry(name, j);
+ str = X509_NAME_ENTRY_get_data(ne);
+ if (do_check_string(str, -1, equal, flags, chk, chklen))
+ return 1;
+ }
+ return 0;
+ }
+
+int X509_check_host(X509 *x, const unsigned char *chk, size_t chklen,
+ unsigned int flags)
+ {
+ return do_x509_check(x, chk, chklen, flags, GEN_DNS);
+ }
+
+int X509_check_email(X509 *x, const unsigned char *chk, size_t chklen,
+ unsigned int flags)
+ {
+ return do_x509_check(x, chk, chklen, flags, GEN_EMAIL);
+ }
+
+int X509_check_ip(X509 *x, const unsigned char *chk, size_t chklen,
+ unsigned int flags)
+ {
+ return do_x509_check(x, chk, chklen, flags, GEN_IPADD);
+ }
+
+int X509_check_ip_asc(X509 *x, const char *ipasc, unsigned int flags)
+ {
+ unsigned char ipout[16];
+ int iplen;
+ iplen = a2i_ipadd(ipout, ipasc);
+ if (iplen == 0)
+ return -2;
+ return do_x509_check(x, ipout, (size_t)iplen, flags, GEN_IPADD);
+ }
+
+/* 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;
+ }
+
+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 = BUF_strdup(ipasc);
+ if (!iptmp)
+ return NULL;
+ p = iptmp + (p - ipasc);
+ *p++ = 0;
+
+ iplen1 = a2i_ipadd(ipout, iptmp);
+
+ if (!iplen1)
+ goto err;
+
+ iplen2 = a2i_ipadd(ipout + iplen1, p);
+
+ OPENSSL_free(iptmp);
+ iptmp = NULL;
+
+ if (!iplen2 || (iplen1 != iplen2))
+ goto err;
+
+ ret = ASN1_OCTET_STRING_new();
+ if (!ret)
+ goto err;
+ if (!ASN1_OCTET_STRING_set(ret, ipout, iplen1 + iplen2))
+ goto err;
+
+ return ret;
+
+ err:
+ if (iptmp)
+ OPENSSL_free(iptmp);
+ if (ret)
+ ASN1_OCTET_STRING_free(ret);
+ return NULL;
+ }
+
+
+int a2i_ipadd(unsigned char *ipout, const char *ipasc)
+ {
+ /* If string contains a ':' assume IPv6 */
+
+ if (strchr(ipasc, ':'))
+ {
+ if (!ipv6_from_asc(ipout, ipasc))
+ return 0;
+ return 16;
+ }
+ else
+ {
+ if (!ipv4_from_asc(ipout, ipasc))
+ return 0;
+ return 4;
+ }
+ }
+
+static int ipv4_from_asc(unsigned char *v4, const char *in)
+ {
+ 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 mval;
+ size_t i;
+ 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;
+ }
diff --git a/src/crypto/x509v3/v3nametest.c b/src/crypto/x509v3/v3nametest.c
new file mode 100644
index 0000000..b2e9c09
--- /dev/null
+++ b/src/crypto/x509v3/v3nametest.c
@@ -0,0 +1,423 @@
+/* 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 <string.h>
+
+#include <openssl/crypto.h>
+#include <openssl/mem.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+
+
+static const char *const names[] =
+ {
+ "a", "b", ".", "*", "@",
+ ".a", "a.", ".b", "b.", ".*", "*.", "*@", "@*", "a@", "@a", "b@", "..",
+ "@@", "**", "*.com", "*com", "*.*.com", "*com", "com*", "*example.com",
+ "*@example.com", "test@*.example.com", "example.com", "www.example.com",
+ "test.www.example.com", "*.example.com", "*.www.example.com",
+ "test.*.example.com", "www.*.com",
+ ".www.example.com", "*www.example.com",
+ "example.net", "xn--rger-koa.example.com",
+ "a.example.com", "b.example.com",
+ "postmaster@example.com", "Postmaster@example.com",
+ "postmaster@EXAMPLE.COM",
+ NULL
+ };
+
+static const char *const exceptions[] =
+ {
+ "set CN: host: [*.example.com] matches [a.example.com]",
+ "set CN: host: [*.example.com] matches [b.example.com]",
+ "set CN: host: [*.example.com] matches [www.example.com]",
+ "set CN: host: [*.example.com] matches [xn--rger-koa.example.com]",
+ "set CN: host: [*.www.example.com] matches [test.www.example.com]",
+ "set CN: host: [*.www.example.com] matches [.www.example.com]",
+ "set CN: host: [*www.example.com] matches [www.example.com]",
+ "set CN: host: [test.www.example.com] matches [.www.example.com]",
+ "set CN: host-no-wildcards: [*.www.example.com] matches [.www.example.com]",
+ "set CN: host-no-wildcards: [test.www.example.com] matches [.www.example.com]",
+ "set emailAddress: email: [postmaster@example.com] does not match [Postmaster@example.com]",
+ "set emailAddress: email: [postmaster@EXAMPLE.COM] does not match [Postmaster@example.com]",
+ "set emailAddress: email: [Postmaster@example.com] does not match [postmaster@example.com]",
+ "set emailAddress: email: [Postmaster@example.com] does not match [postmaster@EXAMPLE.COM]",
+ "set dnsName: host: [*.example.com] matches [www.example.com]",
+ "set dnsName: host: [*.example.com] matches [a.example.com]",
+ "set dnsName: host: [*.example.com] matches [b.example.com]",
+ "set dnsName: host: [*.example.com] matches [xn--rger-koa.example.com]",
+ "set dnsName: host: [*.www.example.com] matches [test.www.example.com]",
+ "set dnsName: host-no-wildcards: [*.www.example.com] matches [.www.example.com]",
+ "set dnsName: host-no-wildcards: [test.www.example.com] matches [.www.example.com]",
+ "set dnsName: host: [*.www.example.com] matches [.www.example.com]",
+ "set dnsName: host: [*www.example.com] matches [www.example.com]",
+ "set dnsName: host: [test.www.example.com] matches [.www.example.com]",
+ "set rfc822Name: email: [postmaster@example.com] does not match [Postmaster@example.com]",
+ "set rfc822Name: email: [Postmaster@example.com] does not match [postmaster@example.com]",
+ "set rfc822Name: email: [Postmaster@example.com] does not match [postmaster@EXAMPLE.COM]",
+ "set rfc822Name: email: [postmaster@EXAMPLE.COM] does not match [Postmaster@example.com]",
+ NULL
+ };
+
+static int is_exception(const char *msg)
+ {
+ const char *const *p;
+ for (p = exceptions; *p; ++p)
+ if (strcmp(msg, *p) == 0)
+ return 1;
+ return 0;
+ }
+
+static int set_cn(X509 *crt, ...)
+ {
+ int ret = 0;
+ X509_NAME *n = NULL;
+ va_list ap;
+ va_start(ap, crt);
+ n = X509_NAME_new();
+ if (n == NULL)
+ goto out;
+ while (1) {
+ int nid;
+ const char *name;
+ nid = va_arg(ap, int);
+ if (nid == 0)
+ break;
+ name = va_arg(ap, const char *);
+ if (!X509_NAME_add_entry_by_NID(n, nid, MBSTRING_ASC,
+ (unsigned char *)name,
+ -1, -1, 1))
+ goto out;
+ }
+ if (!X509_set_subject_name(crt, n))
+ goto out;
+ ret = 1;
+ out:
+ X509_NAME_free(n);
+ va_end(ap);
+ return ret;
+ }
+
+/*
+int X509_add_ext(X509 *x, X509_EXTENSION *ex, int loc);
+X509_EXTENSION *X509_EXTENSION_create_by_NID(X509_EXTENSION **ex,
+ int nid, int crit, ASN1_OCTET_STRING *data);
+int X509_add_ext(X509 *x, X509_EXTENSION *ex, int loc);
+*/
+
+static int set_altname(X509 *crt, ...)
+ {
+ int ret = 0;
+ GENERAL_NAMES *gens = NULL;
+ GENERAL_NAME *gen = NULL;
+ ASN1_IA5STRING *ia5 = NULL;
+ va_list ap;
+ va_start(ap, crt);
+ gens = sk_GENERAL_NAME_new_null();
+ if (gens == NULL)
+ goto out;
+ while (1) {
+ int type;
+ const char *name;
+ type = va_arg(ap, int);
+ if (type == 0)
+ break;
+ name = va_arg(ap, const char *);
+
+ gen = GENERAL_NAME_new();
+ if (gen == NULL)
+ goto out;
+ ia5 = ASN1_IA5STRING_new();
+ if (ia5 == NULL)
+ goto out;
+ if (!ASN1_STRING_set(ia5, name, -1))
+ goto out;
+ switch (type)
+ {
+ case GEN_EMAIL:
+ case GEN_DNS:
+ GENERAL_NAME_set0_value(gen, type, ia5);
+ ia5 = NULL;
+ break;
+ default:
+ abort();
+ }
+ sk_GENERAL_NAME_push(gens, gen);
+ gen = NULL;
+ }
+ if (!X509_add1_ext_i2d(crt, NID_subject_alt_name, gens, 0, 0))
+ goto out;
+ ret = 1;
+ out:
+ ASN1_IA5STRING_free(ia5);
+ GENERAL_NAME_free(gen);
+ GENERAL_NAMES_free(gens);
+ va_end(ap);
+ return ret;
+ }
+
+static int set_cn1(X509 *crt, const char *name)
+ {
+ return set_cn(crt, NID_commonName, name, 0);
+ }
+
+
+static int set_cn_and_email(X509 *crt, const char *name)
+ {
+ return set_cn(crt, NID_commonName, name,
+ NID_pkcs9_emailAddress, "dummy@example.com", 0);
+ }
+
+static int set_cn2(X509 *crt, const char *name)
+ {
+ return set_cn(crt, NID_commonName, "dummy value",
+ NID_commonName, name, 0);
+ }
+
+static int set_cn3(X509 *crt, const char *name)
+ {
+ return set_cn(crt, NID_commonName, name,
+ NID_commonName, "dummy value", 0);
+ }
+
+static int set_email1(X509 *crt, const char *name)
+ {
+ return set_cn(crt, NID_pkcs9_emailAddress, name, 0);
+ }
+
+static int set_email2(X509 *crt, const char *name)
+ {
+ return set_cn(crt, NID_pkcs9_emailAddress, "dummy@example.com",
+ NID_pkcs9_emailAddress, name, 0);
+ }
+
+static int set_email3(X509 *crt, const char *name)
+ {
+ return set_cn(crt, NID_pkcs9_emailAddress, name,
+ NID_pkcs9_emailAddress, "dummy@example.com", 0);
+ }
+
+static int set_email_and_cn(X509 *crt, const char *name)
+ {
+ return set_cn(crt, NID_pkcs9_emailAddress, name,
+ NID_commonName, "www.example.org", 0);
+ }
+
+static int set_altname_dns(X509 *crt, const char *name)
+ {
+ return set_altname(crt, GEN_DNS, name, 0);
+ }
+
+static int set_altname_email(X509 *crt, const char *name)
+ {
+ return set_altname(crt, GEN_EMAIL, name, 0);
+ }
+
+struct set_name_fn
+ {
+ int (*fn)(X509 *, const char *);
+ const char *name;
+ int host;
+ int email;
+ };
+
+static const struct set_name_fn name_fns[] =
+ {
+ {set_cn1, "set CN", 1, 0},
+ {set_cn2, "set CN", 1, 0},
+ {set_cn3, "set CN", 1, 0},
+ {set_cn_and_email, "set CN", 1, 0},
+ {set_email1, "set emailAddress", 0, 1},
+ {set_email2, "set emailAddress", 0, 1},
+ {set_email3, "set emailAddress", 0, 1},
+ {set_email_and_cn, "set emailAddress", 0, 1},
+ {set_altname_dns, "set dnsName", 1, 0},
+ {set_altname_email, "set rfc822Name", 0, 1},
+ {NULL, NULL, 0}
+ };
+
+static X509 *make_cert(void)
+ {
+ X509 *ret = NULL;
+ X509 *crt = NULL;
+ X509_NAME *issuer = NULL;
+ crt = X509_new();
+ if (crt == NULL)
+ goto out;
+ if (!X509_set_version(crt, 3))
+ goto out;
+ ret = crt;
+ crt = NULL;
+ out:
+ X509_NAME_free(issuer);
+ return ret;
+ }
+
+static int errors;
+
+static void check_message(const struct set_name_fn *fn, const char *op,
+ const char *nameincert, int match, const char *name)
+ {
+ char msg[1024];
+ if (match < 0)
+ return;
+ BIO_snprintf(msg, sizeof(msg), "%s: %s: [%s] %s [%s]",
+ fn->name, op, nameincert,
+ match ? "matches" : "does not match", name);
+ if (is_exception(msg))
+ return;
+ puts(msg);
+ ++errors;
+ }
+
+static void run_cert(X509 *crt, const char *nameincert,
+ const struct set_name_fn *fn)
+ {
+ const char *const *pname = names;
+ while (*pname)
+ {
+ int samename = OPENSSL_strcasecmp(nameincert, *pname) == 0;
+ size_t namelen = strlen(*pname);
+ char *name = malloc(namelen);
+ int match, ret;
+ memcpy(name, *pname, namelen);
+
+ ret = X509_check_host(crt, (const unsigned char *)name,
+ namelen, 0);
+ match = -1;
+ if (ret < 0)
+ {
+ fprintf(stderr, "internal error in X509_check_host");
+ ++errors;
+ }
+ else if (fn->host)
+ {
+ if (ret == 1 && !samename)
+ match = 1;
+ if (ret == 0 && samename)
+ match = 0;
+ }
+ else if (ret == 1)
+ match = 1;
+ check_message(fn, "host", nameincert, match, *pname);
+
+ ret = X509_check_host(crt, (const unsigned char *)name,
+ namelen, X509_CHECK_FLAG_NO_WILDCARDS);
+ match = -1;
+ if (ret < 0)
+ {
+ fprintf(stderr, "internal error in X509_check_host");
+ ++errors;
+ }
+ else if (fn->host)
+ {
+ if (ret == 1 && !samename)
+ match = 1;
+ if (ret == 0 && samename)
+ match = 0;
+ }
+ else if (ret == 1)
+ match = 1;
+ check_message(fn, "host-no-wildcards",
+ nameincert, match, *pname);
+
+ ret = X509_check_email(crt, (const unsigned char *)name,
+ namelen, 0);
+ match = -1;
+ if (fn->email)
+ {
+ if (ret && !samename)
+ match = 1;
+ if (!ret && samename && strchr(nameincert, '@') != NULL)
+ match = 0;
+ }
+ else if (ret)
+ match = 1;
+ check_message(fn, "email", nameincert, match, *pname);
+ ++pname;
+ free(name);
+ }
+ }
+
+int
+main(void)
+ {
+ CRYPTO_library_init();
+
+ const struct set_name_fn *pfn = name_fns;
+ while (pfn->name) {
+ const char *const *pname = names;
+ while (*pname)
+ {
+ X509 *crt = make_cert();
+ if (crt == NULL)
+ {
+ fprintf(stderr, "make_cert failed\n");
+ return 1;
+ }
+ if (!pfn->fn(crt, *pname))
+ {
+ fprintf(stderr, "X509 name setting failed\n");
+ return 1;
+ }
+ run_cert(crt, *pname, pfn);
+ X509_free(crt);
+ ++pname;
+ }
+ ++pfn;
+ }
+ if (errors == 0) {
+ printf("PASS\n");
+ }
+ return errors > 0 ? 1 : 0;
+ }
diff --git a/src/crypto/x509v3/x509v3_error.c b/src/crypto/x509v3/x509v3_error.c
new file mode 100644
index 0000000..9fbca5f
--- /dev/null
+++ b/src/crypto/x509v3/x509v3_error.c
@@ -0,0 +1,147 @@
+/* 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 <openssl/err.h>
+
+#include <openssl/x509v3.h>
+
+const ERR_STRING_DATA X509V3_error_string_data[] = {
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_SXNET_add_id_INTEGER, 0), "SXNET_add_id_INTEGER"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_SXNET_add_id_asc, 0), "SXNET_add_id_asc"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_SXNET_add_id_ulong, 0), "SXNET_add_id_ulong"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_SXNET_get_id_asc, 0), "SXNET_get_id_asc"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_SXNET_get_id_ulong, 0), "SXNET_get_id_ulong"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_X509V3_EXT_add, 0), "X509V3_EXT_add"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_X509V3_EXT_add_alias, 0), "X509V3_EXT_add_alias"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_X509V3_EXT_free, 0), "X509V3_EXT_free"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_X509V3_EXT_i2d, 0), "X509V3_EXT_i2d"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_X509V3_EXT_nconf, 0), "X509V3_EXT_nconf"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_X509V3_add1_i2d, 0), "X509V3_add1_i2d"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_X509V3_add_value, 0), "X509V3_add_value"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_X509V3_get_section, 0), "X509V3_get_section"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_X509V3_get_string, 0), "X509V3_get_string"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_X509V3_get_value_bool, 0), "X509V3_get_value_bool"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_X509V3_parse_list, 0), "X509V3_parse_list"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_X509_PURPOSE_add, 0), "X509_PURPOSE_add"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_X509_PURPOSE_set, 0), "X509_PURPOSE_set"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_a2i_GENERAL_NAME, 0), "a2i_GENERAL_NAME"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_copy_email, 0), "copy_email"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_copy_issuer, 0), "copy_issuer"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_do_dirname, 0), "do_dirname"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_do_ext_i2d, 0), "do_ext_i2d"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_do_ext_nconf, 0), "do_ext_nconf"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_gnames_from_sectname, 0), "gnames_from_sectname"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_hex_to_string, 0), "hex_to_string"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_i2s_ASN1_ENUMERATED, 0), "i2s_ASN1_ENUMERATED"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_i2s_ASN1_IA5STRING, 0), "i2s_ASN1_IA5STRING"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_i2s_ASN1_INTEGER, 0), "i2s_ASN1_INTEGER"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_i2v_AUTHORITY_INFO_ACCESS, 0), "i2v_AUTHORITY_INFO_ACCESS"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_notice_section, 0), "notice_section"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_nref_nos, 0), "nref_nos"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_policy_section, 0), "policy_section"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_process_pci_value, 0), "process_pci_value"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_r2i_certpol, 0), "r2i_certpol"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_r2i_pci, 0), "r2i_pci"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_s2i_ASN1_IA5STRING, 0), "s2i_ASN1_IA5STRING"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_s2i_ASN1_INTEGER, 0), "s2i_ASN1_INTEGER"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_s2i_ASN1_OCTET_STRING, 0), "s2i_ASN1_OCTET_STRING"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_s2i_skey_id, 0), "s2i_skey_id"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_set_dist_point_name, 0), "set_dist_point_name"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_string_to_hex, 0), "string_to_hex"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_v2i_ASN1_BIT_STRING, 0), "v2i_ASN1_BIT_STRING"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_v2i_AUTHORITY_INFO_ACCESS, 0), "v2i_AUTHORITY_INFO_ACCESS"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_v2i_AUTHORITY_KEYID, 0), "v2i_AUTHORITY_KEYID"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_v2i_BASIC_CONSTRAINTS, 0), "v2i_BASIC_CONSTRAINTS"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_v2i_EXTENDED_KEY_USAGE, 0), "v2i_EXTENDED_KEY_USAGE"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_v2i_GENERAL_NAMES, 0), "v2i_GENERAL_NAMES"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_v2i_GENERAL_NAME_ex, 0), "v2i_GENERAL_NAME_ex"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_v2i_NAME_CONSTRAINTS, 0), "v2i_NAME_CONSTRAINTS"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_v2i_POLICY_CONSTRAINTS, 0), "v2i_POLICY_CONSTRAINTS"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_v2i_POLICY_MAPPINGS, 0), "v2i_POLICY_MAPPINGS"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_v2i_crld, 0), "v2i_crld"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_v2i_idp, 0), "v2i_idp"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_v2i_issuer_alt, 0), "v2i_issuer_alt"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_v2i_subject_alt, 0), "v2i_subject_alt"},
+ {ERR_PACK(ERR_LIB_X509V3, X509V3_F_v3_generic_extension, 0), "v3_generic_extension"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_BAD_IP_ADDRESS), "BAD_IP_ADDRESS"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_BAD_OBJECT), "BAD_OBJECT"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_BN_DEC2BN_ERROR), "BN_DEC2BN_ERROR"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_BN_TO_ASN1_INTEGER_ERROR), "BN_TO_ASN1_INTEGER_ERROR"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_CANNOT_FIND_FREE_FUNCTION), "CANNOT_FIND_FREE_FUNCTION"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_DIRNAME_ERROR), "DIRNAME_ERROR"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_DISTPOINT_ALREADY_SET), "DISTPOINT_ALREADY_SET"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_DUPLICATE_ZONE_ID), "DUPLICATE_ZONE_ID"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_ERROR_CONVERTING_ZONE), "ERROR_CONVERTING_ZONE"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_ERROR_CREATING_EXTENSION), "ERROR_CREATING_EXTENSION"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_ERROR_IN_EXTENSION), "ERROR_IN_EXTENSION"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_EXPECTED_A_SECTION_NAME), "EXPECTED_A_SECTION_NAME"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_EXTENSION_EXISTS), "EXTENSION_EXISTS"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_EXTENSION_NAME_ERROR), "EXTENSION_NAME_ERROR"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_EXTENSION_NOT_FOUND), "EXTENSION_NOT_FOUND"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED), "EXTENSION_SETTING_NOT_SUPPORTED"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_EXTENSION_VALUE_ERROR), "EXTENSION_VALUE_ERROR"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_ILLEGAL_EMPTY_EXTENSION), "ILLEGAL_EMPTY_EXTENSION"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_ILLEGAL_HEX_DIGIT), "ILLEGAL_HEX_DIGIT"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INCORRECT_POLICY_SYNTAX_TAG), "INCORRECT_POLICY_SYNTAX_TAG"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_ASNUMBER), "INVALID_ASNUMBER"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_ASRANGE), "INVALID_ASRANGE"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_BOOLEAN_STRING), "INVALID_BOOLEAN_STRING"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_EXTENSION_STRING), "INVALID_EXTENSION_STRING"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_INHERITANCE), "INVALID_INHERITANCE"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_IPADDRESS), "INVALID_IPADDRESS"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_MULTIPLE_RDNS), "INVALID_MULTIPLE_RDNS"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_NAME), "INVALID_NAME"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_NULL_ARGUMENT), "INVALID_NULL_ARGUMENT"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_NULL_NAME), "INVALID_NULL_NAME"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_NULL_VALUE), "INVALID_NULL_VALUE"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_NUMBER), "INVALID_NUMBER"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_NUMBERS), "INVALID_NUMBERS"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_OBJECT_IDENTIFIER), "INVALID_OBJECT_IDENTIFIER"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_OPTION), "INVALID_OPTION"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_POLICY_IDENTIFIER), "INVALID_POLICY_IDENTIFIER"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_PROXY_POLICY_SETTING), "INVALID_PROXY_POLICY_SETTING"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_PURPOSE), "INVALID_PURPOSE"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_SAFI), "INVALID_SAFI"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_SECTION), "INVALID_SECTION"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_SYNTAX), "INVALID_SYNTAX"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_ISSUER_DECODE_ERROR), "ISSUER_DECODE_ERROR"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_MISSING_VALUE), "MISSING_VALUE"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NEED_ORGANIZATION_AND_NUMBERS), "NEED_ORGANIZATION_AND_NUMBERS"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NO_CONFIG_DATABASE), "NO_CONFIG_DATABASE"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NO_ISSUER_CERTIFICATE), "NO_ISSUER_CERTIFICATE"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NO_ISSUER_DETAILS), "NO_ISSUER_DETAILS"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NO_POLICY_IDENTIFIER), "NO_POLICY_IDENTIFIER"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED), "NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NO_PUBLIC_KEY), "NO_PUBLIC_KEY"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NO_SUBJECT_DETAILS), "NO_SUBJECT_DETAILS"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_ODD_NUMBER_OF_DIGITS), "ODD_NUMBER_OF_DIGITS"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_OPERATION_NOT_DEFINED), "OPERATION_NOT_DEFINED"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_OTHERNAME_ERROR), "OTHERNAME_ERROR"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_POLICY_LANGUAGE_ALREADY_DEFINED), "POLICY_LANGUAGE_ALREADY_DEFINED"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_POLICY_PATH_LENGTH), "POLICY_PATH_LENGTH"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_POLICY_PATH_LENGTH_ALREADY_DEFINED), "POLICY_PATH_LENGTH_ALREADY_DEFINED"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_POLICY_SYNTAX_NOT_CURRENTLY_SUPPORTED), "POLICY_SYNTAX_NOT_CURRENTLY_SUPPORTED"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY), "POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_SECTION_NOT_FOUND), "SECTION_NOT_FOUND"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNABLE_TO_GET_ISSUER_DETAILS), "UNABLE_TO_GET_ISSUER_DETAILS"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNABLE_TO_GET_ISSUER_KEYID), "UNABLE_TO_GET_ISSUER_KEYID"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNKNOWN_BIT_STRING_ARGUMENT), "UNKNOWN_BIT_STRING_ARGUMENT"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNKNOWN_EXTENSION), "UNKNOWN_EXTENSION"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNKNOWN_EXTENSION_NAME), "UNKNOWN_EXTENSION_NAME"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNKNOWN_OPTION), "UNKNOWN_OPTION"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNSUPPORTED_OPTION), "UNSUPPORTED_OPTION"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNSUPPORTED_TYPE), "UNSUPPORTED_TYPE"},
+ {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_USER_TOO_LONG), "USER_TOO_LONG"},
+ {0, NULL},
+};
diff --git a/src/doc/doc.css b/src/doc/doc.css
new file mode 120000
index 0000000..d7c5102
--- /dev/null
+++ b/src/doc/doc.css
@@ -0,0 +1 @@
+../util/doc.css \ No newline at end of file
diff --git a/src/include/openssl/aead.h b/src/include/openssl/aead.h
new file mode 100644
index 0000000..6fd8116
--- /dev/null
+++ b/src/include/openssl/aead.h
@@ -0,0 +1,277 @@
+/* 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_AEAD_H
+#define OPENSSL_HEADER_AEAD_H
+
+#include <openssl/base.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* 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 ciphertext.
+ *
+ * The |EVP_AEAD_CTX_init| function initialises an |EVP_AEAD_CTX| structure and
+ * performs any precomputation needed to use |aead| with |key|. The length of
+ * the key, |key_len|, is given in bytes.
+ *
+ * The |tag_len| argument contains the length of the tags, in bytes, and allows
+ * for the processing of truncated authenticators. A zero value indicates that
+ * the default tag length should be used and this is defined as
+ * |EVP_AEAD_DEFAULT_TAG_LENGTH| in order to make the code clear. Using
+ * truncated tags increases an attacker's chance of creating a valid forgery.
+ * Be aware that the attacker's chance may increase more than exponentially as
+ * would naively be expected.
+ *
+ * When no longer needed, the initialised |EVP_AEAD_CTX| structure must be
+ * passed to |EVP_AEAD_CTX_cleanup|, which will deallocate any memory used.
+ *
+ * With an |EVP_AEAD_CTX| in hand, one can seal and open messages. These
+ * operations are intended to meet the standard notions of privacy and
+ * authenticity for authenticated encryption. For formal definitions see
+ * Bellare and Namprempre, "Authenticated encryption: relations among notions
+ * and analysis of the generic composition paradigm," Lecture Notes in Computer
+ * Science B<1976> (2000), 531–545,
+ * http://www-cse.ucsd.edu/~mihir/papers/oem.html.
+ *
+ * When sealing messages, a nonce must be given. The length of the nonce is
+ * fixed by the AEAD in use and is returned by |EVP_AEAD_nonce_length|. *The
+ * nonce must be unique for all messages with the same key*. This is critically
+ * important - nonce reuse may completely undermine the security of the AEAD.
+ * Nonces may be predictable and public, so long as they are unique. Uniqueness
+ * may be achieved with a simple counter or, if large enough, may be generated
+ * randomly. The nonce must be passed into the "open" operation by the receiver
+ * so must either be implicit (e.g. a counter), or must be transmitted along
+ * with the sealed message.
+ *
+ * The "seal" and "open" operations are atomic - an entire message must be
+ * encrypted or decrypted in a single call. Large messages may have to be split
+ * up in order to accomodate this. When doing so, be mindful of the need not to
+ * repeat nonces and the possibility that an attacker could duplicate, reorder
+ * or drop message chunks. For example, using a single key for a given (large)
+ * message and sealing chunks with nonces counting from zero would be secure as
+ * long as the number of chunks was securely transmitted. (Otherwise an
+ * attacker could truncate the message by dropping chunks from the end.)
+ *
+ * The number of chunks could be transmitted by prefixing it to the plaintext,
+ * for example. This also assumes that no other message would ever use the same
+ * key otherwise the rule that nonces must be unique for a given key would be
+ * violated.
+ *
+ * The "seal" and "open" operations also permit additional data to be
+ * authenticated via the |ad| parameter. This data is not included in the
+ * ciphertext and must be identical for both the "seal" and "open" call. This
+ * permits implicit context to be authenticated but may be empty if not needed.
+ *
+ * The "seal" and "open" operations may work in-place if the |out| and |in|
+ * arguments are equal. They may also be used to shift the data left inside the
+ * same buffer if |out| is less than |in|. However, |out| may not point inside
+ * the input data otherwise the input may be overwritten before it has been
+ * read. This situation will cause an error.
+ *
+ * The "seal" and "open" operations return one on success and zero on error. */
+
+
+/* AEAD algorithms. */
+
+/* EVP_aead_aes_128_gcm is AES-128 in Galois Counter Mode. */
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_gcm(void);
+
+/* EVP_aead_aes_256_gcm is AES-256 in Galois Counter Mode. */
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_gcm(void);
+
+/* EVP_aead_chacha20_poly1305 is an AEAD built from ChaCha20 and Poly1305. */
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_chacha20_poly1305(void);
+
+/* EVP_aead_aes_128_key_wrap is AES-128 Key Wrap mode. This should never be
+ * used except to interoperate with existing systems that use this mode.
+ *
+ * If the nonce is empty then the default nonce will be used, otherwise it must
+ * be eight bytes long. The input must be a multiple of eight bytes long. No
+ * additional data can be given to this mode. */
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_key_wrap(void);
+
+/* EVP_aead_aes_256_key_wrap is AES-256 in Key Wrap mode. This should never be
+ * used except to interoperate with existing systems that use this mode.
+ *
+ * See |EVP_aead_aes_128_key_wrap| for details. */
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_key_wrap(void);
+
+/* EVP_has_aes_hardware returns one if we enable hardware support for fast and
+ * constant-time AES-GCM. */
+OPENSSL_EXPORT int EVP_has_aes_hardware(void);
+
+
+/* TLS specific AEAD algorithms.
+ *
+ * These AEAD primitives do not meet the definition of generic AEADs. They are
+ * all specific to TLS in some fashion and should not be used outside of that
+ * context. They require an additional data of length 11 (the standard TLS one
+ * with the length omitted). They are also stateful, so a given |EVP_AEAD_CTX|
+ * may only be used for one of seal or open, but not both. */
+
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_rc4_md5_tls(void);
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_rc4_sha1_tls(void);
+
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_cbc_sha1_tls(void);
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_cbc_sha1_tls_implicit_iv(void);
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_cbc_sha256_tls(void);
+
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_cbc_sha1_tls(void);
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_cbc_sha1_tls_implicit_iv(void);
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_cbc_sha256_tls(void);
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_cbc_sha384_tls(void);
+
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_des_ede3_cbc_sha1_tls(void);
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv(void);
+
+
+/* SSLv3 specific AEAD algorithms.
+ *
+ * These AEAD primitives do not meet the definition of generic AEADs. They are
+ * all specific to SSLv3 in some fashion and should not be used outside of that
+ * context. */
+
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_rc4_md5_ssl3(void);
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_rc4_sha1_ssl3(void);
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_cbc_sha1_ssl3(void);
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_cbc_sha1_ssl3(void);
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_des_ede3_cbc_sha1_ssl3(void);
+
+
+/* Utility functions. */
+
+/* EVP_AEAD_key_length returns the length, in bytes, of the keys used by
+ * |aead|. */
+OPENSSL_EXPORT size_t EVP_AEAD_key_length(const EVP_AEAD *aead);
+
+/* EVP_AEAD_nonce_length returns the length, in bytes, of the per-message nonce
+ * for |aead|. */
+OPENSSL_EXPORT 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 |aead|. */
+OPENSSL_EXPORT size_t EVP_AEAD_max_overhead(const EVP_AEAD *aead);
+
+/* EVP_AEAD_max_tag_len returns the maximum tag length when using |aead|. This
+ * is the largest value that can be passed as |tag_len| to
+ * |EVP_AEAD_CTX_init|. */
+OPENSSL_EXPORT size_t EVP_AEAD_max_tag_len(const EVP_AEAD *aead);
+
+
+/* AEAD operations. */
+
+/* An EVP_AEAD_CTX represents an AEAD algorithm configured with a specific key
+ * and message-independent IV. */
+typedef struct evp_aead_ctx_st {
+ const EVP_AEAD *aead;
+ /* aead_state is an opaque pointer to whatever state the AEAD needs to
+ * maintain. */
+ void *aead_state;
+} EVP_AEAD_CTX;
+
+/* EVP_AEAD_MAX_KEY_LENGTH contains the maximum key length used by
+ * any AEAD defined in this header. */
+#define EVP_AEAD_MAX_KEY_LENGTH 80
+
+/* EVP_AEAD_MAX_NONCE_LENGTH contains the maximum nonce length used by
+ * any AEAD defined in this header. */
+#define EVP_AEAD_MAX_NONCE_LENGTH 16
+
+/* EVP_AEAD_MAX_OVERHEAD contains the maximum overhead used by any AEAD
+ * defined in this header. */
+#define EVP_AEAD_MAX_OVERHEAD 64
+
+/* 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_init initializes |ctx| for the given AEAD algorithm from |impl|.
+ * The |impl| argument may be NULL to choose the default implementation.
+ * Authentication tags may be truncated by passing a size as |tag_len|. A
+ * |tag_len| of zero indicates the default tag length and this is defined as
+ * EVP_AEAD_DEFAULT_TAG_LENGTH for readability.
+ * Returns 1 on success. Otherwise returns 0 and pushes to the error stack. */
+OPENSSL_EXPORT int EVP_AEAD_CTX_init(EVP_AEAD_CTX *ctx, const EVP_AEAD *aead,
+ const uint8_t *key, size_t key_len,
+ size_t tag_len, ENGINE *impl);
+
+/* EVP_AEAD_CTX_cleanup frees any data allocated by |ctx|. */
+OPENSSL_EXPORT void EVP_AEAD_CTX_cleanup(EVP_AEAD_CTX *ctx);
+
+/* EVP_AEAD_CTX_seal encrypts and authenticates |in_len| bytes from |in| and
+ * authenticates |ad_len| bytes from |ad| and writes the result to |out|. It
+ * returns one on success and zero otherwise.
+ *
+ * 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 to |out| and, in order to ensure
+ * success, |max_out_len| should be |in_len| plus the result of
+ * |EVP_AEAD_overhead|. On successful return, |*out_len| is set to the actual
+ * number of bytes written.
+ *
+ * The length of |nonce|, |nonce_len|, 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. (In this case, |*out_len| is set to
+ * zero.)
+ *
+ * If |in| and |out| alias then |out| must be <= |in|. */
+OPENSSL_EXPORT int EVP_AEAD_CTX_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
+ size_t *out_len, size_t max_out_len,
+ const uint8_t *nonce, size_t nonce_len,
+ const uint8_t *in, size_t in_len,
+ const uint8_t *ad, size_t ad_len);
+
+/* EVP_AEAD_CTX_open authenticates |in_len| bytes from |in| and |ad_len| bytes
+ * from |ad| and decrypts at most |in_len| bytes into |out|. It returns one on
+ * success and zero otherwise.
+ *
+ * This function may be called (with the same |EVP_AEAD_CTX|) concurrently with
+ * itself or |EVP_AEAD_CTX_seal|.
+ *
+ * At most |in_len| bytes are written to |out|. In order to ensure success,
+ * |max_out_len| should be at least |in_len|. On successful return, |*out_len|
+ * is set to the the actual number of bytes written.
+ *
+ * The length of |nonce|, |nonce_len|, 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. (In this case, |*out_len| is set to
+ * zero.)
+ *
+ * If |in| and |out| alias then |out| must be <= |in|. */
+OPENSSL_EXPORT int EVP_AEAD_CTX_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
+ size_t *out_len, size_t max_out_len,
+ const uint8_t *nonce, size_t nonce_len,
+ const uint8_t *in, size_t in_len,
+ const uint8_t *ad, size_t ad_len);
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_AEAD_H */
diff --git a/src/include/openssl/aes.h b/src/include/openssl/aes.h
new file mode 100644
index 0000000..11d83bb
--- /dev/null
+++ b/src/include/openssl/aes.h
@@ -0,0 +1,146 @@
+/* ====================================================================
+ * 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.
+ * ==================================================================== */
+
+#ifndef OPENSSL_HEADER_AES_H
+#define OPENSSL_HEADER_AES_H
+
+#include <openssl/base.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* Raw AES functions. */
+
+
+#define AES_ENCRYPT 1
+#define AES_DECRYPT 0
+
+/* AES_MAXNR is the maximum number of AES rounds. */
+#define AES_MAXNR 14
+
+#define AES_BLOCK_SIZE 16
+
+/* aes_key_st should be an opaque type, but EVP requires that the size be
+ * known. */
+struct aes_key_st {
+ uint32_t rd_key[4 * (AES_MAXNR + 1)];
+ unsigned rounds;
+};
+typedef struct aes_key_st AES_KEY;
+
+/* AES_set_encrypt_key configures |aeskey| to encrypt with the |bits|-bit key,
+ * |key|.
+ *
+ * WARNING: unlike other OpenSSL functions, this returns zero on success and a
+ * negative number on error. */
+OPENSSL_EXPORT int AES_set_encrypt_key(const uint8_t *key, unsigned bits,
+ AES_KEY *aeskey);
+
+/* AES_set_decrypt_key configures |aeskey| to decrypt with the |bits|-bit key,
+ * |key|.
+ *
+ * WARNING: unlike other OpenSSL functions, this returns zero on success and a
+ * negative number on error. */
+OPENSSL_EXPORT int AES_set_decrypt_key(const uint8_t *key, unsigned bits,
+ AES_KEY *aeskey);
+
+/* AES_encrypt encrypts a single block from |in| to |out| with |key|. The |in|
+ * and |out| pointers may overlap. */
+OPENSSL_EXPORT void AES_encrypt(const uint8_t *in, uint8_t *out,
+ const AES_KEY *key);
+
+/* AES_decrypt decrypts a single block from |in| to |out| with |key|. The |in|
+ * and |out| pointers may overlap. */
+OPENSSL_EXPORT void AES_decrypt(const uint8_t *in, uint8_t *out,
+ const AES_KEY *key);
+
+
+/* Block cipher modes. */
+
+/* AES_ctr128_encrypt encrypts (or decrypts, it's the same in CTR mode) |len|
+ * bytes from |in| to |out|. The |num| parameter must be set to zero on the
+ * first call and |ivec| will be incremented. */
+OPENSSL_EXPORT void AES_ctr128_encrypt(const uint8_t *in, uint8_t *out,
+ size_t len, const AES_KEY *key,
+ uint8_t ivec[AES_BLOCK_SIZE],
+ uint8_t ecount_buf[AES_BLOCK_SIZE],
+ unsigned int *num);
+
+/* AES_ecb_encrypt encrypts (or decrypts, if |enc| == |AES_DECRYPT|) a single,
+ * 16 byte block from |in| to |out|. */
+OPENSSL_EXPORT void AES_ecb_encrypt(const uint8_t *in, uint8_t *out,
+ const AES_KEY *key, const int enc);
+
+/* AES_cbc_encrypt encrypts (or decrypts, if |enc| == |AES_DECRYPT|) |len|
+ * bytes from |in| to |out|. The length must be a multiple of the block size. */
+OPENSSL_EXPORT void AES_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t len,
+ const AES_KEY *key, uint8_t *ivec,
+ const int enc);
+
+/* AES_ofb128_encrypt encrypts (or decrypts, it's the same in CTR mode) |len|
+ * bytes from |in| to |out|. The |num| parameter must be set to zero on the
+ * first call. */
+OPENSSL_EXPORT void AES_ofb128_encrypt(const uint8_t *in, uint8_t *out,
+ size_t len, const AES_KEY *key,
+ uint8_t *ivec, int *num);
+
+/* AES_cfb128_encrypt encrypts (or decrypts, if |enc| == |AES_DECRYPT|) |len|
+ * bytes from |in| to |out|. The |num| parameter must be set to zero on the
+ * first call. */
+OPENSSL_EXPORT void AES_cfb128_encrypt(const uint8_t *in, uint8_t *out,
+ size_t len, const AES_KEY *key,
+ uint8_t *ivec, int *num, int enc);
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_AES_H */
diff --git a/src/include/openssl/asn1.h b/src/include/openssl/asn1.h
new file mode 100644
index 0000000..941b156
--- /dev/null
+++ b/src/include/openssl/asn1.h
@@ -0,0 +1,1264 @@
+/* crypto/asn1/asn1.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/base.h>
+
+#include <time.h>
+
+#include <openssl/bio.h>
+#include <openssl/stack.h>
+
+#include <openssl/bn.h>
+
+#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
+
+/* For use with d2i_ASN1_type_bytes() */
+#define B_ASN1_NUMERICSTRING 0x0001
+#define B_ASN1_PRINTABLESTRING 0x0002
+#define B_ASN1_T61STRING 0x0004
+#define B_ASN1_TELETEXSTRING 0x0004
+#define B_ASN1_VIDEOTEXSTRING 0x0008
+#define B_ASN1_IA5STRING 0x0010
+#define B_ASN1_GRAPHICSTRING 0x0020
+#define B_ASN1_ISO64STRING 0x0040
+#define B_ASN1_VISIBLESTRING 0x0040
+#define B_ASN1_GENERALSTRING 0x0080
+#define B_ASN1_UNIVERSALSTRING 0x0100
+#define B_ASN1_OCTET_STRING 0x0200
+#define B_ASN1_BIT_STRING 0x0400
+#define B_ASN1_BMPSTRING 0x0800
+#define B_ASN1_UNKNOWN 0x1000
+#define B_ASN1_UTF8STRING 0x2000
+#define B_ASN1_UTCTIME 0x4000
+#define B_ASN1_GENERALIZEDTIME 0x8000
+#define B_ASN1_SEQUENCE 0x10000
+
+/* For use with ASN1_mbstring_copy() */
+#define MBSTRING_FLAG 0x1000
+#define MBSTRING_UTF8 (MBSTRING_FLAG)
+#define MBSTRING_ASC (MBSTRING_FLAG|1)
+#define MBSTRING_BMP (MBSTRING_FLAG|2)
+#define MBSTRING_UNIV (MBSTRING_FLAG|4)
+
+#define SMIME_OLDMIME 0x400
+#define SMIME_CRLFEOL 0x800
+#define SMIME_STREAM 0x1000
+
+#define DECLARE_ASN1_SET_OF(type) /* filled in by mkstack.pl */
+#define IMPLEMENT_ASN1_SET_OF(type) /* nothing, no longer needed */
+
+/* We MUST make sure that, except for constness, asn1_ctx_st and
+ asn1_const_ctx are exactly the same. Fortunately, as soon as
+ the old ASN1 parsing macros are gone, we can throw this away
+ as well... */
+typedef struct asn1_ctx_st
+ {
+ unsigned char *p;/* work char pointer */
+ int eos; /* end of sequence read for indefinite encoding */
+ int error; /* error code to use when returning an error */
+ int inf; /* constructed if 0x20, indefinite is 0x21 */
+ int tag; /* tag from last 'get object' */
+ int xclass; /* class from last 'get object' */
+ long slen; /* length of last 'get object' */
+ unsigned char *max; /* largest value of p allowed */
+ unsigned char *q;/* temporary variable */
+ unsigned char **pp;/* variable */
+ int line; /* used in error processing */
+ } ASN1_CTX;
+
+typedef struct asn1_const_ctx_st
+ {
+ const unsigned char *p;/* work char pointer */
+ int eos; /* end of sequence read for indefinite encoding */
+ int error; /* error code to use when returning an error */
+ int inf; /* constructed if 0x20, indefinite is 0x21 */
+ int tag; /* tag from last 'get object' */
+ int xclass; /* class from last 'get object' */
+ long slen; /* length of last 'get object' */
+ const unsigned char *max; /* largest value of p allowed */
+ const unsigned char *q;/* temporary variable */
+ const unsigned char **pp;/* variable */
+ int line; /* used in error processing */
+ } ASN1_const_CTX;
+
+/* 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 */
+ };
+
+#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;
+
+/* size limits: this stuff is taken straight from RFC2459 */
+
+#define ub_name 32768
+#define ub_common_name 64
+#define ub_locality_name 128
+#define ub_state_name 128
+#define ub_organization_name 64
+#define ub_organization_unit_name 64
+#define ub_title 64
+#define ub_email_address 128
+
+/* Declarations for template structures: for full definitions
+ * see asn1t.h
+ */
+typedef struct ASN1_TEMPLATE_st ASN1_TEMPLATE;
+typedef struct ASN1_TLC_st ASN1_TLC;
+/* This is just an opaque pointer */
+typedef struct ASN1_VALUE_st ASN1_VALUE;
+
+/* Declare ASN1 functions: the implement macro in in asn1t.h */
+
+#define DECLARE_ASN1_FUNCTIONS(type) DECLARE_ASN1_FUNCTIONS_name(type, type)
+
+#define DECLARE_ASN1_ALLOC_FUNCTIONS(type) \
+ DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, type)
+
+#define DECLARE_ASN1_FUNCTIONS_name(type, name) \
+ DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, name) \
+ DECLARE_ASN1_ENCODE_FUNCTIONS(type, name, name)
+
+#define DECLARE_ASN1_FUNCTIONS_fname(type, itname, name) \
+ DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, name) \
+ DECLARE_ASN1_ENCODE_FUNCTIONS(type, itname, name)
+
+#define DECLARE_ASN1_ENCODE_FUNCTIONS(type, itname, name) \
+ OPENSSL_EXPORT type *d2i_##name(type **a, const unsigned char **in, long len); \
+ OPENSSL_EXPORT int i2d_##name(type *a, unsigned char **out); \
+ DECLARE_ASN1_ITEM(itname)
+
+#define DECLARE_ASN1_ENCODE_FUNCTIONS_const(type, name) \
+ OPENSSL_EXPORT type *d2i_##name(type **a, const unsigned char **in, long len); \
+ OPENSSL_EXPORT int i2d_##name(const type *a, unsigned char **out); \
+ DECLARE_ASN1_ITEM(name)
+
+#define DECLARE_ASN1_NDEF_FUNCTION(name) \
+ OPENSSL_EXPORT 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) \
+ OPENSSL_EXPORT type *name##_new(void); \
+ OPENSSL_EXPORT 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) \
+ OPENSSL_EXPORT int fname##_print_ctx(BIO *out, stname *x, int indent, \
+ const ASN1_PCTX *pctx);
+
+#define D2I_OF(type) type *(*)(type **,const unsigned char **,long)
+#define I2D_OF(type) int (*)(type *,unsigned char **)
+#define I2D_OF_const(type) int (*)(const type *,unsigned char **)
+
+#define CHECKED_D2I_OF(type, d2i) \
+ ((d2i_of_void*) (1 ? d2i : ((D2I_OF(type))0)))
+#define CHECKED_I2D_OF(type, i2d) \
+ ((i2d_of_void*) (1 ? i2d : ((I2D_OF(type))0)))
+#define CHECKED_NEW_OF(type, xnew) \
+ ((void *(*)(void)) (1 ? xnew : ((type *(*)(void))0)))
+#define CHECKED_PPTR_OF(type, p) \
+ ((void**) (1 ? p : (type**)0))
+
+#define TYPEDEF_D2I_OF(type) typedef type *d2i_of_##type(type **,const unsigned char **,long)
+#define TYPEDEF_I2D_OF(type) typedef int i2d_of_##type(const type *,unsigned char **)
+#define TYPEDEF_D2I2D_OF(type) TYPEDEF_D2I_OF(type); TYPEDEF_I2D_OF(type)
+
+TYPEDEF_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;
+
+/* 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 OPENSSL_EXPORT const ASN1_ITEM name##_it;
+
+/* Parameters used by ASN1_STRING_print_ex() */
+
+/* These determine which characters to escape:
+ * RFC2253 special characters, control characters and
+ * MSB set characters
+ */
+
+#define ASN1_STRFLGS_ESC_2253 1
+#define ASN1_STRFLGS_ESC_CTRL 2
+#define ASN1_STRFLGS_ESC_MSB 4
+
+
+/* This flag determines how we do escaping: normally
+ * RC2253 backslash only, set this to use backslash and
+ * quote.
+ */
+
+#define ASN1_STRFLGS_ESC_QUOTE 8
+
+
+/* These three flags are internal use only. */
+
+/* Character is a valid PrintableString character */
+#define CHARTYPE_PRINTABLESTRING 0x10
+/* Character needs escaping if it is the first character */
+#define CHARTYPE_FIRST_ESC_2253 0x20
+/* Character needs escaping if it is the last character */
+#define CHARTYPE_LAST_ESC_2253 0x40
+
+/* NB the internal flags are safely reused below by flags
+ * handled at the top level.
+ */
+
+/* If this is set we convert all character strings
+ * to UTF8 first
+ */
+
+#define ASN1_STRFLGS_UTF8_CONVERT 0x10
+
+/* If this is set we don't attempt to interpret content:
+ * just assume all strings are 1 byte per character. This
+ * will produce some pretty odd looking output!
+ */
+
+#define ASN1_STRFLGS_IGNORE_TYPE 0x20
+
+/* If this is set we include the string type in the output */
+#define ASN1_STRFLGS_SHOW_TYPE 0x40
+
+/* This determines which strings to display and which to
+ * 'dump' (hex dump of content octets or DER encoding). We can
+ * only dump non character strings or everything. If we
+ * don't dump 'unknown' they are interpreted as character
+ * strings with 1 octet per character and are subject to
+ * the usual escaping options.
+ */
+
+#define ASN1_STRFLGS_DUMP_ALL 0x80
+#define ASN1_STRFLGS_DUMP_UNKNOWN 0x100
+
+/* These determine what 'dumping' does, we can dump the
+ * content octets or the DER encoding: both use the
+ * RFC2253 #XXXXX notation.
+ */
+
+#define ASN1_STRFLGS_DUMP_DER 0x200
+
+/* 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_ASN1_SET_OF(ASN1_INTEGER)
+
+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_ASN1_SET_OF(ASN1_TYPE)
+
+typedef STACK_OF(ASN1_TYPE) ASN1_SEQUENCE_ANY;
+
+DECLARE_ASN1_ENCODE_FUNCTIONS_const(ASN1_SEQUENCE_ANY, ASN1_SEQUENCE_ANY)
+DECLARE_ASN1_ENCODE_FUNCTIONS_const(ASN1_SEQUENCE_ANY, ASN1_SET_ANY)
+
+struct X509_algor_st
+ {
+ ASN1_OBJECT *algorithm;
+ ASN1_TYPE *parameter;
+ } /* X509_ALGOR */;
+DEFINE_STACK_OF(X509_ALGOR);
+
+DECLARE_ASN1_FUNCTIONS(X509_ALGOR);
+
+typedef struct NETSCAPE_X509_st
+ {
+ ASN1_OCTET_STRING *header;
+ X509 *cert;
+ } NETSCAPE_X509;
+
+/* 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 M_ASN1_STRING_length(x) ((x)->length)
+#define M_ASN1_STRING_length_set(x, n) ((x)->length = (n))
+#define M_ASN1_STRING_type(x) ((x)->type)
+#define M_ASN1_STRING_data(x) ((x)->data)
+
+/* Macros for string operations */
+#define M_ASN1_BIT_STRING_new() (ASN1_BIT_STRING *)\
+ ASN1_STRING_type_new(V_ASN1_BIT_STRING)
+#define M_ASN1_BIT_STRING_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_ASN1_BIT_STRING_dup(a) (ASN1_BIT_STRING *)\
+ ASN1_STRING_dup((const ASN1_STRING *)a)
+#define M_ASN1_BIT_STRING_cmp(a,b) ASN1_STRING_cmp(\
+ (const ASN1_STRING *)a,(const ASN1_STRING *)b)
+#define M_ASN1_BIT_STRING_set(a,b,c) ASN1_STRING_set((ASN1_STRING *)a,b,c)
+
+#define M_ASN1_INTEGER_new() (ASN1_INTEGER *)\
+ ASN1_STRING_type_new(V_ASN1_INTEGER)
+#define M_ASN1_INTEGER_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_ASN1_INTEGER_dup(a) (ASN1_INTEGER *)\
+ ASN1_STRING_dup((const ASN1_STRING *)a)
+#define M_ASN1_INTEGER_cmp(a,b) ASN1_STRING_cmp(\
+ (const ASN1_STRING *)a,(const ASN1_STRING *)b)
+
+#define M_ASN1_ENUMERATED_new() (ASN1_ENUMERATED *)\
+ ASN1_STRING_type_new(V_ASN1_ENUMERATED)
+#define M_ASN1_ENUMERATED_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_ASN1_ENUMERATED_dup(a) (ASN1_ENUMERATED *)\
+ ASN1_STRING_dup((const ASN1_STRING *)a)
+#define M_ASN1_ENUMERATED_cmp(a,b) ASN1_STRING_cmp(\
+ (const ASN1_STRING *)a,(const ASN1_STRING *)b)
+
+#define M_ASN1_OCTET_STRING_new() (ASN1_OCTET_STRING *)\
+ ASN1_STRING_type_new(V_ASN1_OCTET_STRING)
+#define M_ASN1_OCTET_STRING_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_ASN1_OCTET_STRING_dup(a) (ASN1_OCTET_STRING *)\
+ ASN1_STRING_dup((const ASN1_STRING *)a)
+#define M_ASN1_OCTET_STRING_cmp(a,b) ASN1_STRING_cmp(\
+ (const ASN1_STRING *)a,(const ASN1_STRING *)b)
+#define M_ASN1_OCTET_STRING_set(a,b,c) ASN1_STRING_set((ASN1_STRING *)a,b,c)
+#define M_ASN1_OCTET_STRING_print(a,b) ASN1_STRING_print(a,(ASN1_STRING *)b)
+#define M_i2d_ASN1_OCTET_STRING(a,pp) \
+ i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_OCTET_STRING,\
+ V_ASN1_UNIVERSAL)
+
+#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
+
+#define M_ASN1_PRINTABLE_new() ASN1_STRING_type_new(V_ASN1_T61STRING)
+#define M_ASN1_PRINTABLE_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_i2d_ASN1_PRINTABLE(a,pp) i2d_ASN1_bytes((ASN1_STRING *)a,\
+ pp,a->type,V_ASN1_UNIVERSAL)
+#define M_d2i_ASN1_PRINTABLE(a,pp,l) \
+ d2i_ASN1_type_bytes((ASN1_STRING **)a,pp,l, \
+ B_ASN1_PRINTABLE)
+
+#define M_DIRECTORYSTRING_new() ASN1_STRING_type_new(V_ASN1_PRINTABLESTRING)
+#define M_DIRECTORYSTRING_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_i2d_DIRECTORYSTRING(a,pp) i2d_ASN1_bytes((ASN1_STRING *)a,\
+ pp,a->type,V_ASN1_UNIVERSAL)
+#define M_d2i_DIRECTORYSTRING(a,pp,l) \
+ d2i_ASN1_type_bytes((ASN1_STRING **)a,pp,l, \
+ B_ASN1_DIRECTORYSTRING)
+
+#define M_DISPLAYTEXT_new() ASN1_STRING_type_new(V_ASN1_VISIBLESTRING)
+#define M_DISPLAYTEXT_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_i2d_DISPLAYTEXT(a,pp) i2d_ASN1_bytes((ASN1_STRING *)a,\
+ pp,a->type,V_ASN1_UNIVERSAL)
+#define M_d2i_DISPLAYTEXT(a,pp,l) \
+ d2i_ASN1_type_bytes((ASN1_STRING **)a,pp,l, \
+ B_ASN1_DISPLAYTEXT)
+
+#define M_ASN1_PRINTABLESTRING_new() (ASN1_PRINTABLESTRING *)\
+ ASN1_STRING_type_new(V_ASN1_PRINTABLESTRING)
+#define M_ASN1_PRINTABLESTRING_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_i2d_ASN1_PRINTABLESTRING(a,pp) \
+ i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_PRINTABLESTRING,\
+ V_ASN1_UNIVERSAL)
+#define M_d2i_ASN1_PRINTABLESTRING(a,pp,l) \
+ (ASN1_PRINTABLESTRING *)d2i_ASN1_type_bytes\
+ ((ASN1_STRING **)a,pp,l,B_ASN1_PRINTABLESTRING)
+
+#define M_ASN1_T61STRING_new() (ASN1_T61STRING *)\
+ ASN1_STRING_type_new(V_ASN1_T61STRING)
+#define M_ASN1_T61STRING_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_i2d_ASN1_T61STRING(a,pp) \
+ i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_T61STRING,\
+ V_ASN1_UNIVERSAL)
+#define M_d2i_ASN1_T61STRING(a,pp,l) \
+ (ASN1_T61STRING *)d2i_ASN1_type_bytes\
+ ((ASN1_STRING **)a,pp,l,B_ASN1_T61STRING)
+
+#define M_ASN1_IA5STRING_new() (ASN1_IA5STRING *)\
+ ASN1_STRING_type_new(V_ASN1_IA5STRING)
+#define M_ASN1_IA5STRING_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_ASN1_IA5STRING_dup(a) \
+ (ASN1_IA5STRING *)ASN1_STRING_dup((const ASN1_STRING *)a)
+#define M_i2d_ASN1_IA5STRING(a,pp) \
+ i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_IA5STRING,\
+ V_ASN1_UNIVERSAL)
+#define M_d2i_ASN1_IA5STRING(a,pp,l) \
+ (ASN1_IA5STRING *)d2i_ASN1_type_bytes((ASN1_STRING **)a,pp,l,\
+ B_ASN1_IA5STRING)
+
+#define M_ASN1_UTCTIME_new() (ASN1_UTCTIME *)\
+ ASN1_STRING_type_new(V_ASN1_UTCTIME)
+#define M_ASN1_UTCTIME_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_ASN1_UTCTIME_dup(a) (ASN1_UTCTIME *)\
+ ASN1_STRING_dup((const ASN1_STRING *)a)
+
+#define M_ASN1_GENERALIZEDTIME_new() (ASN1_GENERALIZEDTIME *)\
+ ASN1_STRING_type_new(V_ASN1_GENERALIZEDTIME)
+#define M_ASN1_GENERALIZEDTIME_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_ASN1_GENERALIZEDTIME_dup(a) (ASN1_GENERALIZEDTIME *)ASN1_STRING_dup(\
+ (const ASN1_STRING *)a)
+
+#define M_ASN1_TIME_new() (ASN1_TIME *)\
+ ASN1_STRING_type_new(V_ASN1_UTCTIME)
+#define M_ASN1_TIME_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_ASN1_TIME_dup(a) (ASN1_TIME *)\
+ ASN1_STRING_dup((const ASN1_STRING *)a)
+
+#define M_ASN1_GENERALSTRING_new() (ASN1_GENERALSTRING *)\
+ ASN1_STRING_type_new(V_ASN1_GENERALSTRING)
+#define M_ASN1_GENERALSTRING_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_i2d_ASN1_GENERALSTRING(a,pp) \
+ i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_GENERALSTRING,\
+ V_ASN1_UNIVERSAL)
+#define M_d2i_ASN1_GENERALSTRING(a,pp,l) \
+ (ASN1_GENERALSTRING *)d2i_ASN1_type_bytes\
+ ((ASN1_STRING **)a,pp,l,B_ASN1_GENERALSTRING)
+
+#define M_ASN1_UNIVERSALSTRING_new() (ASN1_UNIVERSALSTRING *)\
+ ASN1_STRING_type_new(V_ASN1_UNIVERSALSTRING)
+#define M_ASN1_UNIVERSALSTRING_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_i2d_ASN1_UNIVERSALSTRING(a,pp) \
+ i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_UNIVERSALSTRING,\
+ V_ASN1_UNIVERSAL)
+#define M_d2i_ASN1_UNIVERSALSTRING(a,pp,l) \
+ (ASN1_UNIVERSALSTRING *)d2i_ASN1_type_bytes\
+ ((ASN1_STRING **)a,pp,l,B_ASN1_UNIVERSALSTRING)
+
+#define M_ASN1_BMPSTRING_new() (ASN1_BMPSTRING *)\
+ ASN1_STRING_type_new(V_ASN1_BMPSTRING)
+#define M_ASN1_BMPSTRING_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_i2d_ASN1_BMPSTRING(a,pp) \
+ i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_BMPSTRING,\
+ V_ASN1_UNIVERSAL)
+#define M_d2i_ASN1_BMPSTRING(a,pp,l) \
+ (ASN1_BMPSTRING *)d2i_ASN1_type_bytes\
+ ((ASN1_STRING **)a,pp,l,B_ASN1_BMPSTRING)
+
+#define M_ASN1_VISIBLESTRING_new() (ASN1_VISIBLESTRING *)\
+ ASN1_STRING_type_new(V_ASN1_VISIBLESTRING)
+#define M_ASN1_VISIBLESTRING_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_i2d_ASN1_VISIBLESTRING(a,pp) \
+ i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_VISIBLESTRING,\
+ V_ASN1_UNIVERSAL)
+#define M_d2i_ASN1_VISIBLESTRING(a,pp,l) \
+ (ASN1_VISIBLESTRING *)d2i_ASN1_type_bytes\
+ ((ASN1_STRING **)a,pp,l,B_ASN1_VISIBLESTRING)
+
+#define M_ASN1_UTF8STRING_new() (ASN1_UTF8STRING *)\
+ ASN1_STRING_type_new(V_ASN1_UTF8STRING)
+#define M_ASN1_UTF8STRING_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_i2d_ASN1_UTF8STRING(a,pp) \
+ i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_UTF8STRING,\
+ V_ASN1_UNIVERSAL)
+#define M_d2i_ASN1_UTF8STRING(a,pp,l) \
+ (ASN1_UTF8STRING *)d2i_ASN1_type_bytes\
+ ((ASN1_STRING **)a,pp,l,B_ASN1_UTF8STRING)
+
+ /* for the is_set parameter to i2d_ASN1_SET */
+#define IS_SEQUENCE 0
+#define IS_SET 1
+
+DECLARE_ASN1_FUNCTIONS_fname(ASN1_TYPE, ASN1_ANY, ASN1_TYPE)
+
+OPENSSL_EXPORT int ASN1_TYPE_get(ASN1_TYPE *a);
+OPENSSL_EXPORT void ASN1_TYPE_set(ASN1_TYPE *a, int type, void *value);
+OPENSSL_EXPORT int ASN1_TYPE_set1(ASN1_TYPE *a, int type, const void *value);
+OPENSSL_EXPORT int ASN1_TYPE_cmp(const ASN1_TYPE *a, const ASN1_TYPE *b);
+
+OPENSSL_EXPORT ASN1_OBJECT * ASN1_OBJECT_new(void );
+OPENSSL_EXPORT void ASN1_OBJECT_free(ASN1_OBJECT *a);
+OPENSSL_EXPORT int i2d_ASN1_OBJECT(ASN1_OBJECT *a,unsigned char **pp);
+OPENSSL_EXPORT ASN1_OBJECT * c2i_ASN1_OBJECT(ASN1_OBJECT **a,const unsigned char **pp,
+ long length);
+OPENSSL_EXPORT ASN1_OBJECT * d2i_ASN1_OBJECT(ASN1_OBJECT **a,const unsigned char **pp,
+ long length);
+
+DECLARE_ASN1_ITEM(ASN1_OBJECT)
+
+DECLARE_ASN1_SET_OF(ASN1_OBJECT)
+
+OPENSSL_EXPORT ASN1_STRING * ASN1_STRING_new(void);
+OPENSSL_EXPORT void ASN1_STRING_free(ASN1_STRING *a);
+OPENSSL_EXPORT int ASN1_STRING_copy(ASN1_STRING *dst, const ASN1_STRING *str);
+OPENSSL_EXPORT ASN1_STRING * ASN1_STRING_dup(const ASN1_STRING *a);
+OPENSSL_EXPORT ASN1_STRING * ASN1_STRING_type_new(int type );
+OPENSSL_EXPORT 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 * */
+OPENSSL_EXPORT int ASN1_STRING_set(ASN1_STRING *str, const void *data, int len);
+OPENSSL_EXPORT void ASN1_STRING_set0(ASN1_STRING *str, void *data, int len);
+OPENSSL_EXPORT int ASN1_STRING_length(const ASN1_STRING *x);
+OPENSSL_EXPORT void ASN1_STRING_length_set(ASN1_STRING *x, int n);
+OPENSSL_EXPORT int ASN1_STRING_type(ASN1_STRING *x);
+OPENSSL_EXPORT unsigned char * ASN1_STRING_data(ASN1_STRING *x);
+
+DECLARE_ASN1_FUNCTIONS(ASN1_BIT_STRING)
+OPENSSL_EXPORT int i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a,unsigned char **pp);
+OPENSSL_EXPORT ASN1_BIT_STRING *c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a,const unsigned char **pp, long length);
+OPENSSL_EXPORT int ASN1_BIT_STRING_set(ASN1_BIT_STRING *a, unsigned char *d, int length );
+OPENSSL_EXPORT int ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value);
+OPENSSL_EXPORT int ASN1_BIT_STRING_get_bit(ASN1_BIT_STRING *a, int n);
+OPENSSL_EXPORT int ASN1_BIT_STRING_check(ASN1_BIT_STRING *a, unsigned char *flags, int flags_len);
+
+OPENSSL_EXPORT int ASN1_BIT_STRING_name_print(BIO *out, ASN1_BIT_STRING *bs, BIT_STRING_BITNAME *tbl, int indent);
+OPENSSL_EXPORT int ASN1_BIT_STRING_num_asc(char *name, BIT_STRING_BITNAME *tbl);
+OPENSSL_EXPORT int ASN1_BIT_STRING_set_asc(ASN1_BIT_STRING *bs, char *name, int value, BIT_STRING_BITNAME *tbl);
+
+OPENSSL_EXPORT int i2d_ASN1_BOOLEAN(int a,unsigned char **pp);
+OPENSSL_EXPORT int d2i_ASN1_BOOLEAN(int *a,const unsigned char **pp,long length);
+
+DECLARE_ASN1_FUNCTIONS(ASN1_INTEGER)
+OPENSSL_EXPORT int i2c_ASN1_INTEGER(ASN1_INTEGER *a,unsigned char **pp);
+OPENSSL_EXPORT ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **a,const unsigned char **pp, long length);
+OPENSSL_EXPORT ASN1_INTEGER *d2i_ASN1_UINTEGER(ASN1_INTEGER **a,const unsigned char **pp, long length);
+OPENSSL_EXPORT ASN1_INTEGER * ASN1_INTEGER_dup(const ASN1_INTEGER *x);
+OPENSSL_EXPORT int ASN1_INTEGER_cmp(const ASN1_INTEGER *x, const ASN1_INTEGER *y);
+
+DECLARE_ASN1_FUNCTIONS(ASN1_ENUMERATED)
+
+OPENSSL_EXPORT int ASN1_UTCTIME_check(const ASN1_UTCTIME *a);
+OPENSSL_EXPORT ASN1_UTCTIME *ASN1_UTCTIME_set(ASN1_UTCTIME *s,time_t t);
+OPENSSL_EXPORT ASN1_UTCTIME *ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t, int offset_day, long offset_sec);
+OPENSSL_EXPORT int ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str);
+OPENSSL_EXPORT int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t);
+#if 0
+time_t ASN1_UTCTIME_get(const ASN1_UTCTIME *s);
+#endif
+
+OPENSSL_EXPORT int ASN1_GENERALIZEDTIME_check(const ASN1_GENERALIZEDTIME *a);
+OPENSSL_EXPORT ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_set(ASN1_GENERALIZEDTIME *s,time_t t);
+OPENSSL_EXPORT ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME *s, time_t t, int offset_day, long offset_sec);
+OPENSSL_EXPORT int ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *s, const char *str);
+OPENSSL_EXPORT int ASN1_TIME_diff(int *pday, int *psec, const ASN1_TIME *from, const ASN1_TIME *to);
+
+DECLARE_ASN1_FUNCTIONS(ASN1_OCTET_STRING)
+OPENSSL_EXPORT ASN1_OCTET_STRING * ASN1_OCTET_STRING_dup(const ASN1_OCTET_STRING *a);
+OPENSSL_EXPORT int ASN1_OCTET_STRING_cmp(const ASN1_OCTET_STRING *a, const ASN1_OCTET_STRING *b);
+OPENSSL_EXPORT int ASN1_OCTET_STRING_set(ASN1_OCTET_STRING *str, const unsigned char *data, int len);
+
+DECLARE_ASN1_FUNCTIONS(ASN1_VISIBLESTRING)
+DECLARE_ASN1_FUNCTIONS(ASN1_UNIVERSALSTRING)
+DECLARE_ASN1_FUNCTIONS(ASN1_UTF8STRING)
+DECLARE_ASN1_FUNCTIONS(ASN1_NULL)
+DECLARE_ASN1_FUNCTIONS(ASN1_BMPSTRING)
+
+OPENSSL_EXPORT int UTF8_getc(const unsigned char *str, int len, unsigned long *val);
+OPENSSL_EXPORT int UTF8_putc(unsigned char *str, int len, unsigned long value);
+
+DECLARE_ASN1_FUNCTIONS_name(ASN1_STRING, ASN1_PRINTABLE)
+
+DECLARE_ASN1_FUNCTIONS_name(ASN1_STRING, DIRECTORYSTRING)
+DECLARE_ASN1_FUNCTIONS_name(ASN1_STRING, DISPLAYTEXT)
+DECLARE_ASN1_FUNCTIONS(ASN1_PRINTABLESTRING)
+DECLARE_ASN1_FUNCTIONS(ASN1_T61STRING)
+DECLARE_ASN1_FUNCTIONS(ASN1_IA5STRING)
+DECLARE_ASN1_FUNCTIONS(ASN1_GENERALSTRING)
+DECLARE_ASN1_FUNCTIONS(ASN1_UTCTIME)
+DECLARE_ASN1_FUNCTIONS(ASN1_GENERALIZEDTIME)
+DECLARE_ASN1_FUNCTIONS(ASN1_TIME)
+
+DECLARE_ASN1_ITEM(ASN1_OCTET_STRING_NDEF)
+
+OPENSSL_EXPORT ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s,time_t t);
+OPENSSL_EXPORT ASN1_TIME *ASN1_TIME_adj(ASN1_TIME *s,time_t t, int offset_day, long offset_sec);
+OPENSSL_EXPORT int ASN1_TIME_check(ASN1_TIME *t);
+OPENSSL_EXPORT ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *t, ASN1_GENERALIZEDTIME **out);
+OPENSSL_EXPORT int ASN1_TIME_set_string(ASN1_TIME *s, const char *str);
+
+OPENSSL_EXPORT int i2d_ASN1_SET(STACK_OF(OPENSSL_BLOCK) *a, unsigned char **pp, i2d_of_void *i2d, int ex_tag, int ex_class, int is_set);
+OPENSSL_EXPORT STACK_OF(OPENSSL_BLOCK) *d2i_ASN1_SET(STACK_OF(OPENSSL_BLOCK) **a,
+ const unsigned char **pp,
+ long length, d2i_of_void *d2i,
+ void (*free_func)(OPENSSL_BLOCK), int ex_tag,
+ int ex_class);
+
+OPENSSL_EXPORT int i2a_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *a);
+OPENSSL_EXPORT int a2i_ASN1_INTEGER(BIO *bp,ASN1_INTEGER *bs,char *buf,int size);
+OPENSSL_EXPORT int i2a_ASN1_ENUMERATED(BIO *bp, ASN1_ENUMERATED *a);
+OPENSSL_EXPORT int a2i_ASN1_ENUMERATED(BIO *bp,ASN1_ENUMERATED *bs,char *buf,int size);
+OPENSSL_EXPORT int i2a_ASN1_OBJECT(BIO *bp,ASN1_OBJECT *a);
+OPENSSL_EXPORT int a2i_ASN1_STRING(BIO *bp,ASN1_STRING *bs,char *buf,int size);
+OPENSSL_EXPORT int i2a_ASN1_STRING(BIO *bp, ASN1_STRING *a, int type);
+OPENSSL_EXPORT int i2t_ASN1_OBJECT(char *buf,int buf_len,ASN1_OBJECT *a);
+
+OPENSSL_EXPORT int a2d_ASN1_OBJECT(unsigned char *out,int olen, const char *buf, int num);
+OPENSSL_EXPORT ASN1_OBJECT *ASN1_OBJECT_create(int nid, unsigned char *data,int len, const char *sn, const char *ln);
+
+OPENSSL_EXPORT int ASN1_INTEGER_set(ASN1_INTEGER *a, long v);
+OPENSSL_EXPORT long ASN1_INTEGER_get(const ASN1_INTEGER *a);
+OPENSSL_EXPORT ASN1_INTEGER *BN_to_ASN1_INTEGER(const BIGNUM *bn, ASN1_INTEGER *ai);
+OPENSSL_EXPORT BIGNUM *ASN1_INTEGER_to_BN(const ASN1_INTEGER *ai,BIGNUM *bn);
+
+OPENSSL_EXPORT int ASN1_ENUMERATED_set(ASN1_ENUMERATED *a, long v);
+OPENSSL_EXPORT long ASN1_ENUMERATED_get(ASN1_ENUMERATED *a);
+OPENSSL_EXPORT ASN1_ENUMERATED *BN_to_ASN1_ENUMERATED(BIGNUM *bn, ASN1_ENUMERATED *ai);
+OPENSSL_EXPORT BIGNUM *ASN1_ENUMERATED_to_BN(ASN1_ENUMERATED *ai,BIGNUM *bn);
+
+/* General */
+/* given a string, return the correct type, max is the maximum length */
+OPENSSL_EXPORT int ASN1_PRINTABLE_type(const unsigned char *s, int max);
+
+OPENSSL_EXPORT int i2d_ASN1_bytes(ASN1_STRING *a, unsigned char **pp, int tag, int xclass);
+OPENSSL_EXPORT ASN1_STRING *d2i_ASN1_bytes(ASN1_STRING **a, const unsigned char **pp, long length, int Ptag, int Pclass);
+OPENSSL_EXPORT unsigned long ASN1_tag2bit(int tag);
+/* type is one or more of the B_ASN1_ values. */
+OPENSSL_EXPORT ASN1_STRING *d2i_ASN1_type_bytes(ASN1_STRING **a,const unsigned char **pp, long length,int type);
+
+/* PARSING */
+OPENSSL_EXPORT int asn1_Finish(ASN1_CTX *c);
+OPENSSL_EXPORT int asn1_const_Finish(ASN1_const_CTX *c);
+
+/* SPECIALS */
+OPENSSL_EXPORT int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag, int *pclass, long omax);
+OPENSSL_EXPORT int ASN1_check_infinite_end(unsigned char **p,long len);
+OPENSSL_EXPORT int ASN1_const_check_infinite_end(const unsigned char **p,long len);
+OPENSSL_EXPORT void ASN1_put_object(unsigned char **pp, int constructed, int length, int tag, int xclass);
+OPENSSL_EXPORT int ASN1_put_eoc(unsigned char **pp);
+OPENSSL_EXPORT int ASN1_object_size(int constructed, int length, int tag);
+
+/* Used to implement other functions */
+OPENSSL_EXPORT void *ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, void *x);
+
+#define ASN1_dup_of(type,i2d,d2i,x) \
+ ((type*)ASN1_dup(CHECKED_I2D_OF(type, i2d), \
+ CHECKED_D2I_OF(type, d2i), \
+ CHECKED_PTR_OF(type, x)))
+
+#define ASN1_dup_of_const(type,i2d,d2i,x) \
+ ((type*)ASN1_dup(CHECKED_I2D_OF(const type, i2d), \
+ CHECKED_D2I_OF(type, d2i), \
+ CHECKED_PTR_OF(const type, x)))
+
+OPENSSL_EXPORT void *ASN1_item_dup(const ASN1_ITEM *it, void *x);
+
+/* ASN1 alloc/free macros for when a type is only used internally */
+
+#define M_ASN1_new_of(type) (type *)ASN1_item_new(ASN1_ITEM_rptr(type))
+#define M_ASN1_free_of(x, type) \
+ ASN1_item_free(CHECKED_PTR_OF(type, x), ASN1_ITEM_rptr(type))
+
+#ifndef OPENSSL_NO_FP_API
+OPENSSL_EXPORT 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)))
+
+OPENSSL_EXPORT void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x);
+OPENSSL_EXPORT 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)))
+
+OPENSSL_EXPORT int ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, void *x);
+OPENSSL_EXPORT int ASN1_STRING_print_ex_fp(FILE *fp, ASN1_STRING *str, unsigned long flags);
+#endif
+
+OPENSSL_EXPORT int ASN1_STRING_to_UTF8(unsigned char **out, ASN1_STRING *in);
+
+OPENSSL_EXPORT 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)))
+
+OPENSSL_EXPORT void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x);
+OPENSSL_EXPORT 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)))
+
+OPENSSL_EXPORT int ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, void *x);
+OPENSSL_EXPORT int ASN1_UTCTIME_print(BIO *fp, const ASN1_UTCTIME *a);
+OPENSSL_EXPORT int ASN1_GENERALIZEDTIME_print(BIO *fp, const ASN1_GENERALIZEDTIME *a);
+OPENSSL_EXPORT int ASN1_TIME_print(BIO *fp, const ASN1_TIME *a);
+OPENSSL_EXPORT int ASN1_STRING_print(BIO *bp, const ASN1_STRING *v);
+OPENSSL_EXPORT int ASN1_STRING_print_ex(BIO *out, ASN1_STRING *str, unsigned long flags);
+OPENSSL_EXPORT int ASN1_bn_print(BIO *bp, const char *number, const BIGNUM *num, unsigned char *buf, int off);
+OPENSSL_EXPORT int ASN1_parse(BIO *bp,const unsigned char *pp,long len,int indent);
+OPENSSL_EXPORT int ASN1_parse_dump(BIO *bp,const unsigned char *pp,long len,int indent,int dump);
+OPENSSL_EXPORT const char *ASN1_tag2str(int tag);
+
+/* Used to load and write netscape format cert */
+
+DECLARE_ASN1_FUNCTIONS(NETSCAPE_X509)
+
+int ASN1_UNIVERSALSTRING_to_string(ASN1_UNIVERSALSTRING *s);
+
+OPENSSL_EXPORT STACK_OF(OPENSSL_BLOCK) *ASN1_seq_unpack(const unsigned char *buf, int len, d2i_of_void *d2i, void (*free_func)(OPENSSL_BLOCK));
+OPENSSL_EXPORT unsigned char *ASN1_seq_pack(STACK_OF(OPENSSL_BLOCK) *safes, i2d_of_void *i2d, unsigned char **buf, int *len );
+OPENSSL_EXPORT void *ASN1_unpack_string(ASN1_STRING *oct, d2i_of_void *d2i);
+OPENSSL_EXPORT void *ASN1_item_unpack(ASN1_STRING *oct, const ASN1_ITEM *it);
+OPENSSL_EXPORT ASN1_STRING *ASN1_pack_string(void *obj, i2d_of_void *i2d, ASN1_OCTET_STRING **oct);
+
+#define ASN1_pack_string_of(type,obj,i2d,oct) \
+ (ASN1_pack_string(CHECKED_PTR_OF(type, obj), \
+ CHECKED_I2D_OF(type, i2d), \
+ oct))
+
+OPENSSL_EXPORT ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it, ASN1_OCTET_STRING **oct);
+
+OPENSSL_EXPORT void ASN1_STRING_set_default_mask(unsigned long mask);
+OPENSSL_EXPORT int ASN1_STRING_set_default_mask_asc(const char *p);
+OPENSSL_EXPORT unsigned long ASN1_STRING_get_default_mask(void);
+OPENSSL_EXPORT int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len, int inform, unsigned long mask);
+OPENSSL_EXPORT int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len, int inform, unsigned long mask, long minsize, long maxsize);
+
+OPENSSL_EXPORT ASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out, const unsigned char *in, int inlen, int inform, int nid);
+OPENSSL_EXPORT ASN1_STRING_TABLE *ASN1_STRING_TABLE_get(int nid);
+OPENSSL_EXPORT int ASN1_STRING_TABLE_add(int, long, long, unsigned long, unsigned long);
+OPENSSL_EXPORT void ASN1_STRING_TABLE_cleanup(void);
+
+/* ASN1 template functions */
+
+/* Old API compatible functions */
+OPENSSL_EXPORT ASN1_VALUE *ASN1_item_new(const ASN1_ITEM *it);
+OPENSSL_EXPORT void ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it);
+OPENSSL_EXPORT ASN1_VALUE * ASN1_item_d2i(ASN1_VALUE **val, const unsigned char **in, long len, const ASN1_ITEM *it);
+OPENSSL_EXPORT int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it);
+OPENSSL_EXPORT int ASN1_item_ndef_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it);
+
+OPENSSL_EXPORT void ASN1_add_oid_module(void);
+
+OPENSSL_EXPORT ASN1_TYPE *ASN1_generate_nconf(char *str, CONF *nconf);
+OPENSSL_EXPORT ASN1_TYPE *ASN1_generate_v3(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
+
+OPENSSL_EXPORT int ASN1_item_print(BIO *out, ASN1_VALUE *ifld, int indent, const ASN1_ITEM *it, const ASN1_PCTX *pctx);
+OPENSSL_EXPORT ASN1_PCTX *ASN1_PCTX_new(void);
+OPENSSL_EXPORT void ASN1_PCTX_free(ASN1_PCTX *p);
+OPENSSL_EXPORT unsigned long ASN1_PCTX_get_flags(ASN1_PCTX *p);
+OPENSSL_EXPORT void ASN1_PCTX_set_flags(ASN1_PCTX *p, unsigned long flags);
+OPENSSL_EXPORT unsigned long ASN1_PCTX_get_nm_flags(ASN1_PCTX *p);
+OPENSSL_EXPORT void ASN1_PCTX_set_nm_flags(ASN1_PCTX *p, unsigned long flags);
+OPENSSL_EXPORT unsigned long ASN1_PCTX_get_cert_flags(ASN1_PCTX *p);
+OPENSSL_EXPORT void ASN1_PCTX_set_cert_flags(ASN1_PCTX *p, unsigned long flags);
+OPENSSL_EXPORT unsigned long ASN1_PCTX_get_oid_flags(ASN1_PCTX *p);
+OPENSSL_EXPORT void ASN1_PCTX_set_oid_flags(ASN1_PCTX *p, unsigned long flags);
+OPENSSL_EXPORT unsigned long ASN1_PCTX_get_str_flags(ASN1_PCTX *p);
+OPENSSL_EXPORT void ASN1_PCTX_set_str_flags(ASN1_PCTX *p, unsigned long flags);
+
+OPENSSL_EXPORT const BIO_METHOD *BIO_f_asn1(void);
+
+OPENSSL_EXPORT BIO *BIO_new_NDEF(BIO *out, ASN1_VALUE *val, const ASN1_ITEM *it);
+
+OPENSSL_EXPORT int i2d_ASN1_bio_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags, const ASN1_ITEM *it);
+OPENSSL_EXPORT int PEM_write_bio_ASN1_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags, const char *hdr, const ASN1_ITEM *it);
+OPENSSL_EXPORT ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it);
+OPENSSL_EXPORT int SMIME_crlf_copy(BIO *in, BIO *out, int flags);
+OPENSSL_EXPORT int SMIME_text(BIO *in, BIO *out);
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_ASN1_strings(void);
+
+typedef int asn1_ps_func(BIO *b, unsigned char **pbuf, int *plen, void *parg);
+OPENSSL_EXPORT int BIO_asn1_set_prefix(BIO *b, asn1_ps_func *prefix, asn1_ps_func *prefix_free);
+OPENSSL_EXPORT int BIO_asn1_get_prefix(BIO *b, asn1_ps_func **pprefix, asn1_ps_func **pprefix_free);
+OPENSSL_EXPORT int BIO_asn1_set_suffix(BIO *b, asn1_ps_func *suffix, asn1_ps_func *suffix_free);
+OPENSSL_EXPORT int BIO_asn1_get_suffix(BIO *b, asn1_ps_func **psuffix, asn1_ps_func **psuffix_free);
+
+#ifdef __cplusplus
+}
+#endif
+
+#define ASN1_F_asn1_template_ex_d2i 100
+#define ASN1_F_ASN1_dup 101
+#define ASN1_F_a2i_ASN1_STRING 102
+#define ASN1_F_ASN1_d2i_fp 103
+#define ASN1_F_d2i_ASN1_OBJECT 104
+#define ASN1_F_asn1_item_ex_combine_new 105
+#define ASN1_F_ASN1_template_new 106
+#define ASN1_F_asn1_do_adb 107
+#define ASN1_F_asn1_d2i_read_bio 108
+#define ASN1_F_asn1_ex_c2i 109
+#define ASN1_F_c2i_ASN1_INTEGER 110
+#define ASN1_F_ASN1_PCTX_new 111
+#define ASN1_F_ASN1_item_unpack 112
+#define ASN1_F_d2i_ASN1_type_bytes 113
+#define ASN1_F_a2i_ASN1_INTEGER 114
+#define ASN1_F_asn1_collect 115
+#define ASN1_F_ASN1_item_dup 116
+#define ASN1_F_ASN1_ENUMERATED_set 117
+#define ASN1_F_c2i_ASN1_OBJECT 118
+#define ASN1_F_ASN1_unpack_string 119
+#define ASN1_F_d2i_ASN1_UINTEGER 120
+#define ASN1_F_long_c2i 121
+#define ASN1_F_ASN1_seq_pack 122
+#define ASN1_F_a2d_ASN1_OBJECT 123
+#define ASN1_F_ASN1_STRING_type_new 124
+#define ASN1_F_ASN1_INTEGER_set 125
+#define ASN1_F_BN_to_ASN1_INTEGER 126
+#define ASN1_F_BIO_new_NDEF 127
+#define ASN1_F_ASN1_ENUMERATED_to_BN 128
+#define ASN1_F_ASN1_item_ex_d2i 129
+#define ASN1_F_ASN1_INTEGER_to_BN 130
+#define ASN1_F_i2d_ASN1_TIME 131
+#define ASN1_F_ASN1_TIME_adj 132
+#define ASN1_F_ASN1_BIT_STRING_set_bit 133
+#define ASN1_F_ASN1_seq_unpack 134
+#define ASN1_F_ASN1_item_pack 135
+#define ASN1_F_ASN1_STRING_set 136
+#define ASN1_F_ASN1_UTCTIME_adj 137
+#define ASN1_F_ASN1_mbstring_ncopy 138
+#define ASN1_F_d2i_ASN1_BOOLEAN 139
+#define ASN1_F_ASN1_OBJECT_new 140
+#define ASN1_F_asn1_template_noexp_d2i 141
+#define ASN1_F_c2i_ASN1_BIT_STRING 142
+#define ASN1_F_BN_to_ASN1_ENUMERATED 143
+#define ASN1_F_asn1_d2i_ex_primitive 144
+#define ASN1_F_ASN1_i2d_bio 145
+#define ASN1_F_ASN1_item_i2d_bio 146
+#define ASN1_F_d2i_ASN1_UTCTIME 147
+#define ASN1_F_ASN1_STRING_TABLE_add 148
+#define ASN1_F_asn1_find_end 149
+#define ASN1_F_ASN1_item_d2i_fp 150
+#define ASN1_F_collect_data 151
+#define ASN1_F_asn1_check_tlen 152
+#define ASN1_F_ASN1_i2d_fp 153
+#define ASN1_F_ASN1_item_i2d_fp 154
+#define ASN1_F_ASN1_GENERALIZEDTIME_adj 155
+#define ASN1_F_asn1_collate_primitive 156
+#define ASN1_F_ASN1_pack_string 157
+#define ASN1_F_ASN1_get_object 158
+#define ASN1_F_d2i_ASN1_bytes 159
+#define ASN1_F_a2i_ASN1_ENUMERATED 160
+#define ASN1_R_ASN1_SIG_PARSE_ERROR 100
+#define ASN1_R_ADDING_OBJECT 101
+#define ASN1_R_MIME_NO_CONTENT_TYPE 102
+#define ASN1_R_UNKNOWN_OBJECT_TYPE 103
+#define ASN1_R_ILLEGAL_FORMAT 104
+#define ASN1_R_HEADER_TOO_LONG 105
+#define ASN1_R_INVALID_UTF8STRING 106
+#define ASN1_R_EXPLICIT_LENGTH_MISMATCH 107
+#define ASN1_R_ILLEGAL_TAGGED_ANY 108
+#define ASN1_R_DATA_IS_WRONG 109
+#define ASN1_R_NOT_ASCII_FORMAT 110
+#define ASN1_R_NOT_ENOUGH_DATA 111
+#define ASN1_R_MSTRING_NOT_UNIVERSAL 112
+#define ASN1_R_UNKNOWN_FORMAT 113
+#define ASN1_R_BAD_PASSWORD_READ 115
+#define ASN1_R_BAD_OBJECT_HEADER 116
+#define ASN1_R_ILLEGAL_CHARACTERS 117
+#define ASN1_R_CONTEXT_NOT_INITIALISED 118
+#define ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG 119
+#define ASN1_R_BN_LIB 120
+#define ASN1_R_NO_MATCHING_CHOICE_TYPE 121
+#define ASN1_R_SEQUENCE_NOT_CONSTRUCTED 122
+#define ASN1_R_ASN1_PARSE_ERROR 123
+#define ASN1_R_NO_MULTIPART_BOUNDARY 124
+#define ASN1_R_INVALID_SEPARATOR 125
+#define ASN1_R_MALLOC_FAILURE 126
+#define ASN1_R_ILLEGAL_NULL 127
+#define ASN1_R_INVALID_MIME_TYPE 128
+#define ASN1_R_INVALID_NUMBER 129
+#define ASN1_R_STRING_TOO_LONG 130
+#define ASN1_R_BAD_GET_ASN1_OBJECT_CALL 131
+#define ASN1_R_UNABLE_TO_DECODE_RSA_KEY 132
+#define ASN1_R_EXPECTING_A_TIME 133
+#define ASN1_R_TAG_VALUE_TOO_HIGH 134
+#define ASN1_R_NESTED_ASN1_STRING 135
+#define ASN1_R_ILLEGAL_BITSTRING_FORMAT 136
+#define ASN1_R_MISSING_SECOND_NUMBER 137
+#define ASN1_R_TIME_NOT_ASCII_FORMAT 138
+#define ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD 139
+#define ASN1_R_WRONG_TYPE 140
+#define ASN1_R_EXPECTING_AN_INTEGER 141
+#define ASN1_R_DEPTH_EXCEEDED 142
+#define ASN1_R_ILLEGAL_OBJECT 143
+#define ASN1_R_UNKNOWN_TAG 144
+#define ASN1_R_ILLEGAL_IMPLICIT_TAG 145
+#define ASN1_R_AUX_ERROR 146
+#define ASN1_R_SEQUENCE_LENGTH_MISMATCH 147
+#define ASN1_R_FIELD_MISSING 148
+#define ASN1_R_TYPE_NOT_CONSTRUCTED 149
+#define ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH 150
+#define ASN1_R_FIRST_NUM_TOO_LARGE 151
+#define ASN1_R_INVALID_DIGIT 152
+#define ASN1_R_MSTRING_WRONG_TAG 153
+#define ASN1_R_OBJECT_NOT_ASCII_FORMAT 154
+#define ASN1_R_UNSUPPORTED_TYPE 155
+#define ASN1_R_ERROR_LOADING_SECTION 156
+#define ASN1_R_ODD_NUMBER_OF_CHARS 157
+#define ASN1_R_ASN1_LENGTH_MISMATCH 158
+#define ASN1_R_MISSING_EOC 159
+#define ASN1_R_ILLEGAL_INTEGER 160
+#define ASN1_R_ILLEGAL_HEX 161
+#define ASN1_R_NESTED_ASN1_ERROR 162
+#define ASN1_R_TOO_LONG 163
+#define ASN1_R_LENGTH_ERROR 164
+#define ASN1_R_DECODING_ERROR 165
+#define ASN1_R_MIME_SIG_PARSE_ERROR 166
+#define ASN1_R_ILLEGAL_NULL_VALUE 167
+#define ASN1_R_EXPECTING_A_BOOLEAN 168
+#define ASN1_R_STREAMING_NOT_SUPPORTED 169
+#define ASN1_R_INVALID_BMPSTRING_LENGTH 170
+#define ASN1_R_INTEGER_NOT_ASCII_FORMAT 171
+#define ASN1_R_INVALID_MODIFIER 172
+#define ASN1_R_UNEXPECTED_EOC 173
+#define ASN1_R_ILLEGAL_NESTED_TAGGING 174
+#define ASN1_R_IV_TOO_LARGE 175
+#define ASN1_R_INTEGER_TOO_LARGE_FOR_LONG 176
+#define ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE 177
+#define ASN1_R_BUFFER_TOO_SMALL 178
+#define ASN1_R_INVALID_UNIVERSALSTRING_LENGTH 179
+#define ASN1_R_UNSUPPORTED_ENCRYPTION_ALGORITHM 181
+#define ASN1_R_MIME_PARSE_ERROR 182
+#define ASN1_R_INVALID_OBJECT_ENCODING 183
+#define ASN1_R_PRIVATE_KEY_HEADER_MISSING 184
+#define ASN1_R_UNSUPPORTED_CIPHER 185
+#define ASN1_R_NO_MULTIPART_BODY_FAILURE 186
+#define ASN1_R_NO_CONTENT_TYPE 187
+#define ASN1_R_SECOND_NUMBER_TOO_LARGE 188
+#define ASN1_R_INVALID_TIME_FORMAT 189
+#define ASN1_R_NO_DEFAULT_DIGEST 190
+#define ASN1_R_ERROR_SETTING_CIPHER_PARAMS 191
+#define ASN1_R_EXPECTING_AN_OBJECT 192
+#define ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE 193
+#define ASN1_R_ERROR_GETTING_TIME 194
+#define ASN1_R_MISSING_VALUE 195
+#define ASN1_R_LIST_ERROR 196
+#define ASN1_R_DECODE_ERROR 197
+#define ASN1_R_NON_HEX_CHARACTERS 198
+#define ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE 199
+#define ASN1_R_EXPECTING_AN_ASN1_SEQUENCE 201
+#define ASN1_R_STRING_TOO_SHORT 203
+#define ASN1_R_ILLEGAL_OPTIONAL_ANY 204
+#define ASN1_R_BMPSTRING_IS_WRONG_LENGTH 205
+#define ASN1_R_NO_SIG_CONTENT_TYPE 206
+#define ASN1_R_ENCODE_ERROR 207
+#define ASN1_R_SHORT_LINE 208
+#define ASN1_R_ILLEGAL_TIME_VALUE 209
+#define ASN1_R_UNABLE_TO_DECODE_RSA_PRIVATE_KEY 210
+#define ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER 211
+#define ASN1_R_BAD_CLASS 212
+#define ASN1_R_BAD_TAG 213
+#define ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE 214
+#define ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED 215
+#define ASN1_R_ILLEGAL_BOOLEAN 216
+#define ASN1_R_SIG_INVALID_MIME_TYPE 217
+#define ASN1_R_NULL_IS_WRONG_LENGTH 218
+#define ASN1_R_MISSING_ASN1_EOS 219
+#define ASN1_R_ERROR_PARSING_SET_ELEMENT 220
+#define ASN1_R_WRONG_TAG 221
+#define ASN1_R_BOOLEAN_IS_WRONG_LENGTH 222
+#define ASN1_R_TYPE_NOT_PRIMITIVE 223
+#define ASN1_R_INVALID_BIT_STRING_BITS_LEFT 224
+
+#endif
diff --git a/src/include/openssl/asn1_mac.h b/src/include/openssl/asn1_mac.h
new file mode 100644
index 0000000..3e8eebb
--- /dev/null
+++ b/src/include/openssl/asn1_mac.h
@@ -0,0 +1,578 @@
+/* crypto/asn1/asn1_mac.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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_MAC_H
+#define HEADER_ASN1_MAC_H
+
+#include <openssl/asn1.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef ASN1_MAC_ERR_LIB
+#define ASN1_MAC_ERR_LIB ERR_LIB_ASN1
+#endif
+
+#define ASN1_MAC_H_err(f,r,line) \
+ ERR_put_error(ASN1_MAC_ERR_LIB,(f),(r),__FILE__,(line))
+
+#define M_ASN1_D2I_vars(a,type,func) \
+ ASN1_const_CTX c; \
+ type ret=NULL; \
+ \
+ c.pp=(const unsigned char **)pp; \
+ c.q= *(const unsigned char **)pp; \
+ c.error=ASN1_R_NESTED_ASN1_ERROR; \
+ if ((a == NULL) || ((*a) == NULL)) \
+ { if ((ret=(type)func()) == NULL) \
+ { c.line=__LINE__; goto err; } } \
+ else ret=(*a);
+
+#define M_ASN1_D2I_Init() \
+ c.p= *(const unsigned char **)pp; \
+ c.max=(length == 0)?0:(c.p+length);
+
+#define M_ASN1_D2I_Finish_2(a) \
+ if (!asn1_const_Finish(&c)) \
+ { c.line=__LINE__; goto err; } \
+ *(const unsigned char **)pp=c.p; \
+ if (a != NULL) (*a)=ret; \
+ return(ret);
+
+#define M_ASN1_D2I_Finish(a,func,e) \
+ M_ASN1_D2I_Finish_2(a); \
+err:\
+ ASN1_MAC_H_err((e),c.error,c.line); \
+ asn1_add_error(*(const unsigned char **)pp,(int)(c.q- *pp)); \
+ if ((ret != NULL) && ((a == NULL) || (*a != ret))) func(ret); \
+ return(NULL)
+
+#define M_ASN1_D2I_start_sequence() \
+ if (!asn1_GetSequence(&c,&length)) \
+ { c.line=__LINE__; goto err; }
+/* Begin reading ASN1 without a surrounding sequence */
+#define M_ASN1_D2I_begin() \
+ c.slen = length;
+
+/* End reading ASN1 with no check on length */
+#define M_ASN1_D2I_Finish_nolen(a, func, e) \
+ *pp=c.p; \
+ if (a != NULL) (*a)=ret; \
+ return(ret); \
+err:\
+ ASN1_MAC_H_err((e),c.error,c.line); \
+ asn1_add_error(*pp,(int)(c.q- *pp)); \
+ if ((ret != NULL) && ((a == NULL) || (*a != ret))) func(ret); \
+ return(NULL)
+
+#define M_ASN1_D2I_end_sequence() \
+ (((c.inf&1) == 0)?(c.slen <= 0): \
+ (c.eos=ASN1_const_check_infinite_end(&c.p,c.slen)))
+
+/* Don't use this with d2i_ASN1_BOOLEAN() */
+#define M_ASN1_D2I_get(b, func) \
+ c.q=c.p; \
+ if (func(&(b),&c.p,c.slen) == NULL) \
+ {c.line=__LINE__; goto err; } \
+ c.slen-=(c.p-c.q);
+
+/* Don't use this with d2i_ASN1_BOOLEAN() */
+#define M_ASN1_D2I_get_x(type,b,func) \
+ c.q=c.p; \
+ if (((D2I_OF(type))func)(&(b),&c.p,c.slen) == NULL) \
+ {c.line=__LINE__; goto err; } \
+ c.slen-=(c.p-c.q);
+
+/* use this instead () */
+#define M_ASN1_D2I_get_int(b,func) \
+ c.q=c.p; \
+ if (func(&(b),&c.p,c.slen) < 0) \
+ {c.line=__LINE__; goto err; } \
+ c.slen-=(c.p-c.q);
+
+#define M_ASN1_D2I_get_opt(b,func,type) \
+ if ((c.slen != 0) && ((M_ASN1_next & (~V_ASN1_CONSTRUCTED)) \
+ == (V_ASN1_UNIVERSAL|(type)))) \
+ { \
+ M_ASN1_D2I_get(b,func); \
+ }
+
+#define M_ASN1_D2I_get_int_opt(b,func,type) \
+ if ((c.slen != 0) && ((M_ASN1_next & (~V_ASN1_CONSTRUCTED)) \
+ == (V_ASN1_UNIVERSAL|(type)))) \
+ { \
+ M_ASN1_D2I_get_int(b,func); \
+ }
+
+#define M_ASN1_D2I_get_imp(b,func, type) \
+ M_ASN1_next=(_tmp& V_ASN1_CONSTRUCTED)|type; \
+ c.q=c.p; \
+ if (func(&(b),&c.p,c.slen) == NULL) \
+ {c.line=__LINE__; M_ASN1_next_prev = _tmp; goto err; } \
+ c.slen-=(c.p-c.q);\
+ M_ASN1_next_prev=_tmp;
+
+#define M_ASN1_D2I_get_IMP_opt(b,func,tag,type) \
+ if ((c.slen != 0) && ((M_ASN1_next & (~V_ASN1_CONSTRUCTED)) == \
+ (V_ASN1_CONTEXT_SPECIFIC|(tag)))) \
+ { \
+ unsigned char _tmp = M_ASN1_next; \
+ M_ASN1_D2I_get_imp(b,func, type);\
+ }
+
+#define M_ASN1_D2I_get_set(r,func,free_func) \
+ M_ASN1_D2I_get_imp_set(r,func,free_func, \
+ V_ASN1_SET,V_ASN1_UNIVERSAL);
+
+#define M_ASN1_D2I_get_set_type(type,r,func,free_func) \
+ M_ASN1_D2I_get_imp_set_type(type,r,func,free_func, \
+ V_ASN1_SET,V_ASN1_UNIVERSAL);
+
+#define M_ASN1_D2I_get_set_opt(r,func,free_func) \
+ if ((c.slen != 0) && (M_ASN1_next == (V_ASN1_UNIVERSAL| \
+ V_ASN1_CONSTRUCTED|V_ASN1_SET)))\
+ { M_ASN1_D2I_get_set(r,func,free_func); }
+
+#define M_ASN1_D2I_get_set_opt_type(type,r,func,free_func) \
+ if ((c.slen != 0) && (M_ASN1_next == (V_ASN1_UNIVERSAL| \
+ V_ASN1_CONSTRUCTED|V_ASN1_SET)))\
+ { M_ASN1_D2I_get_set_type(type,r,func,free_func); }
+
+#define M_ASN1_I2D_len_SET_opt(a,f) \
+ if ((a != NULL) && (sk_num(a) != 0)) \
+ M_ASN1_I2D_len_SET(a,f);
+
+#define M_ASN1_I2D_put_SET_opt(a,f) \
+ if ((a != NULL) && (sk_num(a) != 0)) \
+ M_ASN1_I2D_put_SET(a,f);
+
+#define M_ASN1_I2D_put_SEQUENCE_opt(a,f) \
+ if ((a != NULL) && (sk_num(a) != 0)) \
+ M_ASN1_I2D_put_SEQUENCE(a,f);
+
+#define M_ASN1_I2D_put_SEQUENCE_opt_type(type,a,f) \
+ if ((a != NULL) && (sk_##type##_num(a) != 0)) \
+ M_ASN1_I2D_put_SEQUENCE_type(type,a,f);
+
+#define M_ASN1_D2I_get_IMP_set_opt(b,func,free_func,tag) \
+ if ((c.slen != 0) && \
+ (M_ASN1_next == \
+ (V_ASN1_CONTEXT_SPECIFIC|V_ASN1_CONSTRUCTED|(tag))))\
+ { \
+ M_ASN1_D2I_get_imp_set(b,func,free_func,\
+ tag,V_ASN1_CONTEXT_SPECIFIC); \
+ }
+
+#define M_ASN1_D2I_get_IMP_set_opt_type(type,b,func,free_func,tag) \
+ if ((c.slen != 0) && \
+ (M_ASN1_next == \
+ (V_ASN1_CONTEXT_SPECIFIC|V_ASN1_CONSTRUCTED|(tag))))\
+ { \
+ M_ASN1_D2I_get_imp_set_type(type,b,func,free_func,\
+ tag,V_ASN1_CONTEXT_SPECIFIC); \
+ }
+
+#define M_ASN1_D2I_get_seq(r,func,free_func) \
+ M_ASN1_D2I_get_imp_set(r,func,free_func,\
+ V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL);
+
+#define M_ASN1_D2I_get_seq_type(type,r,func,free_func) \
+ M_ASN1_D2I_get_imp_set_type(type,r,func,free_func,\
+ V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL)
+
+#define M_ASN1_D2I_get_seq_opt(r,func,free_func) \
+ if ((c.slen != 0) && (M_ASN1_next == (V_ASN1_UNIVERSAL| \
+ V_ASN1_CONSTRUCTED|V_ASN1_SEQUENCE)))\
+ { M_ASN1_D2I_get_seq(r,func,free_func); }
+
+#define M_ASN1_D2I_get_seq_opt_type(type,r,func,free_func) \
+ if ((c.slen != 0) && (M_ASN1_next == (V_ASN1_UNIVERSAL| \
+ V_ASN1_CONSTRUCTED|V_ASN1_SEQUENCE)))\
+ { M_ASN1_D2I_get_seq_type(type,r,func,free_func); }
+
+#define M_ASN1_D2I_get_IMP_set(r,func,free_func,x) \
+ M_ASN1_D2I_get_imp_set(r,func,free_func,\
+ x,V_ASN1_CONTEXT_SPECIFIC);
+
+#define M_ASN1_D2I_get_IMP_set_type(type,r,func,free_func,x) \
+ M_ASN1_D2I_get_imp_set_type(type,r,func,free_func,\
+ x,V_ASN1_CONTEXT_SPECIFIC);
+
+#define M_ASN1_D2I_get_imp_set(r,func,free_func,a,b) \
+ c.q=c.p; \
+ if (d2i_ASN1_SET(&(r),&c.p,c.slen,(char *(*)())func,\
+ (void (*)())free_func,a,b) == NULL) \
+ { c.line=__LINE__; goto err; } \
+ c.slen-=(c.p-c.q);
+
+#define M_ASN1_D2I_get_imp_set_type(type,r,func,free_func,a,b) \
+ c.q=c.p; \
+ if (d2i_ASN1_SET_OF_##type(&(r),&c.p,c.slen,func,\
+ free_func,a,b) == NULL) \
+ { c.line=__LINE__; goto err; } \
+ c.slen-=(c.p-c.q);
+
+#define M_ASN1_D2I_get_set_strings(r,func,a,b) \
+ c.q=c.p; \
+ if (d2i_ASN1_STRING_SET(&(r),&c.p,c.slen,a,b) == NULL) \
+ { c.line=__LINE__; goto err; } \
+ c.slen-=(c.p-c.q);
+
+#define M_ASN1_D2I_get_EXP_opt(r,func,tag) \
+ if ((c.slen != 0L) && (M_ASN1_next == \
+ (V_ASN1_CONSTRUCTED|V_ASN1_CONTEXT_SPECIFIC|tag))) \
+ { \
+ int Tinf,Ttag,Tclass; \
+ long Tlen; \
+ \
+ c.q=c.p; \
+ Tinf=ASN1_get_object(&c.p,&Tlen,&Ttag,&Tclass,c.slen); \
+ if (Tinf & 0x80) \
+ { c.error=ASN1_R_BAD_OBJECT_HEADER; \
+ c.line=__LINE__; goto err; } \
+ if (Tinf == (V_ASN1_CONSTRUCTED+1)) \
+ Tlen = c.slen - (c.p - c.q) - 2; \
+ if (func(&(r),&c.p,Tlen) == NULL) \
+ { c.line=__LINE__; goto err; } \
+ if (Tinf == (V_ASN1_CONSTRUCTED+1)) { \
+ Tlen = c.slen - (c.p - c.q); \
+ if(!ASN1_const_check_infinite_end(&c.p, Tlen)) \
+ { c.error=ASN1_R_MISSING_ASN1_EOS; \
+ c.line=__LINE__; goto err; } \
+ }\
+ c.slen-=(c.p-c.q); \
+ }
+
+#define M_ASN1_D2I_get_EXP_set_opt(r,func,free_func,tag,b) \
+ if ((c.slen != 0) && (M_ASN1_next == \
+ (V_ASN1_CONSTRUCTED|V_ASN1_CONTEXT_SPECIFIC|tag))) \
+ { \
+ int Tinf,Ttag,Tclass; \
+ long Tlen; \
+ \
+ c.q=c.p; \
+ Tinf=ASN1_get_object(&c.p,&Tlen,&Ttag,&Tclass,c.slen); \
+ if (Tinf & 0x80) \
+ { c.error=ASN1_R_BAD_OBJECT_HEADER; \
+ c.line=__LINE__; goto err; } \
+ if (Tinf == (V_ASN1_CONSTRUCTED+1)) \
+ Tlen = c.slen - (c.p - c.q) - 2; \
+ if (d2i_ASN1_SET(&(r),&c.p,Tlen,(char *(*)())func, \
+ (void (*)())free_func, \
+ b,V_ASN1_UNIVERSAL) == NULL) \
+ { c.line=__LINE__; goto err; } \
+ if (Tinf == (V_ASN1_CONSTRUCTED+1)) { \
+ Tlen = c.slen - (c.p - c.q); \
+ if(!ASN1_check_infinite_end(&c.p, Tlen)) \
+ { c.error=ASN1_R_MISSING_ASN1_EOS; \
+ c.line=__LINE__; goto err; } \
+ }\
+ c.slen-=(c.p-c.q); \
+ }
+
+#define M_ASN1_D2I_get_EXP_set_opt_type(type,r,func,free_func,tag,b) \
+ if ((c.slen != 0) && (M_ASN1_next == \
+ (V_ASN1_CONSTRUCTED|V_ASN1_CONTEXT_SPECIFIC|tag))) \
+ { \
+ int Tinf,Ttag,Tclass; \
+ long Tlen; \
+ \
+ c.q=c.p; \
+ Tinf=ASN1_get_object(&c.p,&Tlen,&Ttag,&Tclass,c.slen); \
+ if (Tinf & 0x80) \
+ { c.error=ASN1_R_BAD_OBJECT_HEADER; \
+ c.line=__LINE__; goto err; } \
+ if (Tinf == (V_ASN1_CONSTRUCTED+1)) \
+ Tlen = c.slen - (c.p - c.q) - 2; \
+ if (d2i_ASN1_SET_OF_##type(&(r),&c.p,Tlen,func, \
+ free_func,b,V_ASN1_UNIVERSAL) == NULL) \
+ { c.line=__LINE__; goto err; } \
+ if (Tinf == (V_ASN1_CONSTRUCTED+1)) { \
+ Tlen = c.slen - (c.p - c.q); \
+ if(!ASN1_check_infinite_end(&c.p, Tlen)) \
+ { c.error=ASN1_R_MISSING_ASN1_EOS; \
+ c.line=__LINE__; goto err; } \
+ }\
+ c.slen-=(c.p-c.q); \
+ }
+
+/* New macros */
+#define M_ASN1_New_Malloc(ret,type) \
+ if ((ret=(type *)OPENSSL_malloc(sizeof(type))) == NULL) \
+ { c.line=__LINE__; goto err2; }
+
+#define M_ASN1_New(arg,func) \
+ if (((arg)=func()) == NULL) return(NULL)
+
+#define M_ASN1_New_Error(a) \
+/* err: ASN1_MAC_H_err((a),ASN1_R_NESTED_ASN1_ERROR,c.line); \
+ return(NULL);*/ \
+ err2: ASN1_MAC_H_err((a),ASN1_R_MALLOC_FAILURE,c.line); \
+ return(NULL)
+
+
+/* BIG UGLY WARNING! This is so damn ugly I wanna puke. Unfortunately,
+ some macros that use ASN1_const_CTX still insist on writing in the input
+ stream. ARGH! ARGH! ARGH! Let's get rid of this macro package.
+ Please? -- Richard Levitte */
+#define M_ASN1_next (*((unsigned char *)(c.p)))
+#define M_ASN1_next_prev (*((unsigned char *)(c.q)))
+
+/*************************************************/
+
+#define M_ASN1_I2D_vars(a) int r=0,ret=0; \
+ unsigned char *p; \
+ if (a == NULL) return(0)
+
+/* Length Macros */
+#define M_ASN1_I2D_len(a,f) ret+=f(a,NULL)
+#define M_ASN1_I2D_len_IMP_opt(a,f) if (a != NULL) M_ASN1_I2D_len(a,f)
+
+#define M_ASN1_I2D_len_SET(a,f) \
+ ret+=i2d_ASN1_SET(a,NULL,f,V_ASN1_SET,V_ASN1_UNIVERSAL,IS_SET);
+
+#define M_ASN1_I2D_len_SET_type(type,a,f) \
+ ret+=i2d_ASN1_SET_OF_##type(a,NULL,f,V_ASN1_SET, \
+ V_ASN1_UNIVERSAL,IS_SET);
+
+#define M_ASN1_I2D_len_SEQUENCE(a,f) \
+ ret+=i2d_ASN1_SET(a,NULL,f,V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL, \
+ IS_SEQUENCE);
+
+#define M_ASN1_I2D_len_SEQUENCE_type(type,a,f) \
+ ret+=i2d_ASN1_SET_OF_##type(a,NULL,f,V_ASN1_SEQUENCE, \
+ V_ASN1_UNIVERSAL,IS_SEQUENCE)
+
+#define M_ASN1_I2D_len_SEQUENCE_opt(a,f) \
+ if ((a != NULL) && (sk_num(a) != 0)) \
+ M_ASN1_I2D_len_SEQUENCE(a,f);
+
+#define M_ASN1_I2D_len_SEQUENCE_opt_type(type,a,f) \
+ if ((a != NULL) && (sk_##type##_num(a) != 0)) \
+ M_ASN1_I2D_len_SEQUENCE_type(type,a,f);
+
+#define M_ASN1_I2D_len_IMP_SET(a,f,x) \
+ ret+=i2d_ASN1_SET(a,NULL,f,x,V_ASN1_CONTEXT_SPECIFIC,IS_SET);
+
+#define M_ASN1_I2D_len_IMP_SET_type(type,a,f,x) \
+ ret+=i2d_ASN1_SET_OF_##type(a,NULL,f,x, \
+ V_ASN1_CONTEXT_SPECIFIC,IS_SET);
+
+#define M_ASN1_I2D_len_IMP_SET_opt(a,f,x) \
+ if ((a != NULL) && (sk_num(a) != 0)) \
+ ret+=i2d_ASN1_SET(a,NULL,f,x,V_ASN1_CONTEXT_SPECIFIC, \
+ IS_SET);
+
+#define M_ASN1_I2D_len_IMP_SET_opt_type(type,a,f,x) \
+ if ((a != NULL) && (sk_##type##_num(a) != 0)) \
+ ret+=i2d_ASN1_SET_OF_##type(a,NULL,f,x, \
+ V_ASN1_CONTEXT_SPECIFIC,IS_SET);
+
+#define M_ASN1_I2D_len_IMP_SEQUENCE(a,f,x) \
+ ret+=i2d_ASN1_SET(a,NULL,f,x,V_ASN1_CONTEXT_SPECIFIC, \
+ IS_SEQUENCE);
+
+#define M_ASN1_I2D_len_IMP_SEQUENCE_opt(a,f,x) \
+ if ((a != NULL) && (sk_num(a) != 0)) \
+ ret+=i2d_ASN1_SET(a,NULL,f,x,V_ASN1_CONTEXT_SPECIFIC, \
+ IS_SEQUENCE);
+
+#define M_ASN1_I2D_len_IMP_SEQUENCE_opt_type(type,a,f,x) \
+ if ((a != NULL) && (sk_##type##_num(a) != 0)) \
+ ret+=i2d_ASN1_SET_OF_##type(a,NULL,f,x, \
+ V_ASN1_CONTEXT_SPECIFIC, \
+ IS_SEQUENCE);
+
+#define M_ASN1_I2D_len_EXP_opt(a,f,mtag,v) \
+ if (a != NULL)\
+ { \
+ v=f(a,NULL); \
+ ret+=ASN1_object_size(1,v,mtag); \
+ }
+
+#define M_ASN1_I2D_len_EXP_SET_opt(a,f,mtag,tag,v) \
+ if ((a != NULL) && (sk_num(a) != 0))\
+ { \
+ v=i2d_ASN1_SET(a,NULL,f,tag,V_ASN1_UNIVERSAL,IS_SET); \
+ ret+=ASN1_object_size(1,v,mtag); \
+ }
+
+#define M_ASN1_I2D_len_EXP_SEQUENCE_opt(a,f,mtag,tag,v) \
+ if ((a != NULL) && (sk_num(a) != 0))\
+ { \
+ v=i2d_ASN1_SET(a,NULL,f,tag,V_ASN1_UNIVERSAL, \
+ IS_SEQUENCE); \
+ ret+=ASN1_object_size(1,v,mtag); \
+ }
+
+#define M_ASN1_I2D_len_EXP_SEQUENCE_opt_type(type,a,f,mtag,tag,v) \
+ if ((a != NULL) && (sk_##type##_num(a) != 0))\
+ { \
+ v=i2d_ASN1_SET_OF_##type(a,NULL,f,tag, \
+ V_ASN1_UNIVERSAL, \
+ IS_SEQUENCE); \
+ ret+=ASN1_object_size(1,v,mtag); \
+ }
+
+/* Put Macros */
+#define M_ASN1_I2D_put(a,f) f(a,&p)
+
+#define M_ASN1_I2D_put_IMP_opt(a,f,t) \
+ if (a != NULL) \
+ { \
+ unsigned char *q=p; \
+ f(a,&p); \
+ *q=(V_ASN1_CONTEXT_SPECIFIC|t|(*q&V_ASN1_CONSTRUCTED));\
+ }
+
+#define M_ASN1_I2D_put_SET(a,f) i2d_ASN1_SET(a,&p,f,V_ASN1_SET,\
+ V_ASN1_UNIVERSAL,IS_SET)
+#define M_ASN1_I2D_put_SET_type(type,a,f) \
+ i2d_ASN1_SET_OF_##type(a,&p,f,V_ASN1_SET,V_ASN1_UNIVERSAL,IS_SET)
+#define M_ASN1_I2D_put_IMP_SET(a,f,x) i2d_ASN1_SET(a,&p,f,x,\
+ V_ASN1_CONTEXT_SPECIFIC,IS_SET)
+#define M_ASN1_I2D_put_IMP_SET_type(type,a,f,x) \
+ i2d_ASN1_SET_OF_##type(a,&p,f,x,V_ASN1_CONTEXT_SPECIFIC,IS_SET)
+#define M_ASN1_I2D_put_IMP_SEQUENCE(a,f,x) i2d_ASN1_SET(a,&p,f,x,\
+ V_ASN1_CONTEXT_SPECIFIC,IS_SEQUENCE)
+
+#define M_ASN1_I2D_put_SEQUENCE(a,f) i2d_ASN1_SET(a,&p,f,V_ASN1_SEQUENCE,\
+ V_ASN1_UNIVERSAL,IS_SEQUENCE)
+
+#define M_ASN1_I2D_put_SEQUENCE_type(type,a,f) \
+ i2d_ASN1_SET_OF_##type(a,&p,f,V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL, \
+ IS_SEQUENCE)
+
+#define M_ASN1_I2D_put_SEQUENCE_opt(a,f) \
+ if ((a != NULL) && (sk_num(a) != 0)) \
+ M_ASN1_I2D_put_SEQUENCE(a,f);
+
+#define M_ASN1_I2D_put_IMP_SET_opt(a,f,x) \
+ if ((a != NULL) && (sk_num(a) != 0)) \
+ { i2d_ASN1_SET(a,&p,f,x,V_ASN1_CONTEXT_SPECIFIC, \
+ IS_SET); }
+
+#define M_ASN1_I2D_put_IMP_SET_opt_type(type,a,f,x) \
+ if ((a != NULL) && (sk_##type##_num(a) != 0)) \
+ { i2d_ASN1_SET_OF_##type(a,&p,f,x, \
+ V_ASN1_CONTEXT_SPECIFIC, \
+ IS_SET); }
+
+#define M_ASN1_I2D_put_IMP_SEQUENCE_opt(a,f,x) \
+ if ((a != NULL) && (sk_num(a) != 0)) \
+ { i2d_ASN1_SET(a,&p,f,x,V_ASN1_CONTEXT_SPECIFIC, \
+ IS_SEQUENCE); }
+
+#define M_ASN1_I2D_put_IMP_SEQUENCE_opt_type(type,a,f,x) \
+ if ((a != NULL) && (sk_##type##_num(a) != 0)) \
+ { i2d_ASN1_SET_OF_##type(a,&p,f,x, \
+ V_ASN1_CONTEXT_SPECIFIC, \
+ IS_SEQUENCE); }
+
+#define M_ASN1_I2D_put_EXP_opt(a,f,tag,v) \
+ if (a != NULL) \
+ { \
+ ASN1_put_object(&p,1,v,tag,V_ASN1_CONTEXT_SPECIFIC); \
+ f(a,&p); \
+ }
+
+#define M_ASN1_I2D_put_EXP_SET_opt(a,f,mtag,tag,v) \
+ if ((a != NULL) && (sk_num(a) != 0)) \
+ { \
+ ASN1_put_object(&p,1,v,mtag,V_ASN1_CONTEXT_SPECIFIC); \
+ i2d_ASN1_SET(a,&p,f,tag,V_ASN1_UNIVERSAL,IS_SET); \
+ }
+
+#define M_ASN1_I2D_put_EXP_SEQUENCE_opt(a,f,mtag,tag,v) \
+ if ((a != NULL) && (sk_num(a) != 0)) \
+ { \
+ ASN1_put_object(&p,1,v,mtag,V_ASN1_CONTEXT_SPECIFIC); \
+ i2d_ASN1_SET(a,&p,f,tag,V_ASN1_UNIVERSAL,IS_SEQUENCE); \
+ }
+
+#define M_ASN1_I2D_put_EXP_SEQUENCE_opt_type(type,a,f,mtag,tag,v) \
+ if ((a != NULL) && (sk_##type##_num(a) != 0)) \
+ { \
+ ASN1_put_object(&p,1,v,mtag,V_ASN1_CONTEXT_SPECIFIC); \
+ i2d_ASN1_SET_OF_##type(a,&p,f,tag,V_ASN1_UNIVERSAL, \
+ IS_SEQUENCE); \
+ }
+
+#define M_ASN1_I2D_seq_total() \
+ r=ASN1_object_size(1,ret,V_ASN1_SEQUENCE); \
+ if (pp == NULL) return(r); \
+ p= *pp; \
+ ASN1_put_object(&p,1,ret,V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL)
+
+#define M_ASN1_I2D_INF_seq_start(tag,ctx) \
+ *(p++)=(V_ASN1_CONSTRUCTED|(tag)|(ctx)); \
+ *(p++)=0x80
+
+#define M_ASN1_I2D_INF_seq_end() *(p++)=0x00; *(p++)=0x00
+
+#define M_ASN1_I2D_finish() *pp=p; \
+ return(r);
+
+OPENSSL_EXPORT int asn1_GetSequence(ASN1_const_CTX *c, long *length);
+OPENSSL_EXPORT void asn1_add_error(const unsigned char *address, int offset);
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/include/openssl/asn1t.h b/src/include/openssl/asn1t.h
new file mode 100644
index 0000000..72eb2cb
--- /dev/null
+++ b/src/include/openssl/asn1t.h
@@ -0,0 +1,907 @@
+/* asn1t.h */
+/* 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 <stddef.h>
+#include <openssl/asn1.h>
+
+#ifdef OPENSSL_BUILD_SHLIBCRYPTO
+# undef OPENSSL_EXTERN
+# define OPENSSL_EXTERN OPENSSL_EXPORT
+#endif
+
+/* ASN1 template defines, structures and functions */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* 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 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)
+
+
+/* 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 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 ASN1_NDEF_SEQUENCE(tname) \
+ ASN1_SEQUENCE(tname)
+
+#define ASN1_NDEF_SEQUENCE_cb(tname, cb) \
+ ASN1_SEQUENCE_cb(tname, cb)
+
+#define ASN1_SEQUENCE_cb(tname, cb) \
+ static const ASN1_AUX tname##_aux = {NULL, 0, 0, 0, cb, 0}; \
+ ASN1_SEQUENCE(tname)
+
+#define ASN1_BROKEN_SEQUENCE(tname) \
+ static const ASN1_AUX tname##_aux = {NULL, ASN1_AFLG_BROKEN, 0, 0, 0, 0}; \
+ ASN1_SEQUENCE(tname)
+
+#define ASN1_SEQUENCE_ref(tname, cb, 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 ASN1_BROKEN_SEQUENCE_END(stname) ASN1_SEQUENCE_END_ref(stname, stname)
+
+#define ASN1_SEQUENCE_END_enc(stname, tname) ASN1_SEQUENCE_END_ref(stname, tname)
+
+#define ASN1_SEQUENCE_END_cb(stname, tname) ASN1_SEQUENCE_END_ref(stname, tname)
+
+#define 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 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 ASN1_CHOICE_END_name(stname, tname) 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 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) }
+
+/* used when the structure is combined with the parent */
+
+#define ASN1_EX_COMBINE(flags, tag, type) { \
+ (flags)|ASN1_TFLG_COMBINE, (tag), 0, NULL, 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
+
+/* 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 */
+#ifndef NO_ASN1_FIELD_NAMES
+const char *field_name; /* Field name */
+#endif
+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 */
+ STACK_OF(ASN1_ADB_TABLE) **app_items; /* Application defined items */
+ const ASN1_ADB_TABLE *tbl; /* Table of possible types */
+ long tblcount; /* Number of entries in tbl */
+ const ASN1_TEMPLATE *default_tt; /* Type to use if no match */
+ const ASN1_TEMPLATE *null_tt; /* Type to use if selector is NULL */
+};
+
+struct ASN1_ADB_TABLE_st {
+ long value; /* NID for an object or value for an int */
+ const ASN1_TEMPLATE tt; /* item for this value */
+};
+
+/* template flags */
+
+/* Field is optional */
+#define ASN1_TFLG_OPTIONAL (0x1)
+
+/* Field is a SET OF */
+#define ASN1_TFLG_SET_OF (0x1 << 1)
+
+/* Field is a SEQUENCE OF */
+#define ASN1_TFLG_SEQUENCE_OF (0x2 << 1)
+
+/* Special case: this refers to a SET OF that
+ * will be sorted into DER order when encoded *and*
+ * the corresponding STACK will be modified to match
+ * the new order.
+ */
+#define ASN1_TFLG_SET_ORDER (0x3 << 1)
+
+/* Mask for SET OF or SEQUENCE OF */
+#define ASN1_TFLG_SK_MASK (0x3 << 1)
+
+/* These flags mean the tag should be taken from the
+ * tag field. If EXPLICIT then the underlying type
+ * is used for the inner tag.
+ */
+
+/* IMPLICIT tagging */
+#define ASN1_TFLG_IMPTAG (0x1 << 3)
+
+
+/* EXPLICIT tagging, inner tag from underlying type */
+#define ASN1_TFLG_EXPTAG (0x2 << 3)
+
+#define ASN1_TFLG_TAG_MASK (0x3 << 3)
+
+/* context specific IMPLICIT */
+#define ASN1_TFLG_IMPLICIT ASN1_TFLG_IMPTAG|ASN1_TFLG_CONTEXT
+
+/* context specific EXPLICIT */
+#define ASN1_TFLG_EXPLICIT ASN1_TFLG_EXPTAG|ASN1_TFLG_CONTEXT
+
+/* If tagging is in force these determine the
+ * type of tag to use. Otherwise the tag is
+ * determined by the underlying type. These
+ * values reflect the actual octet format.
+ */
+
+/* Universal tag */
+#define ASN1_TFLG_UNIVERSAL (0x0<<6)
+/* Application tag */
+#define ASN1_TFLG_APPLICATION (0x1<<6)
+/* Context specific tag */
+#define ASN1_TFLG_CONTEXT (0x2<<6)
+/* Private tag */
+#define ASN1_TFLG_PRIVATE (0x3<<6)
+
+#define ASN1_TFLG_TAG_CLASS (0x3<<6)
+
+/* These are for ANY DEFINED BY type. In this case
+ * the 'item' field points to an ASN1_ADB structure
+ * which contains a table of values to decode the
+ * relevant type
+ */
+
+#define ASN1_TFLG_ADB_MASK (0x3<<8)
+
+#define ASN1_TFLG_ADB_OID (0x1<<8)
+
+#define ASN1_TFLG_ADB_INT (0x1<<9)
+
+/* This flag means a parent structure is passed
+ * instead of the field: this is useful is a
+ * SEQUENCE is being combined with a CHOICE for
+ * example. Since this means the structure and
+ * item name will differ we need to use the
+ * ASN1_CHOICE_END_name() macro for example.
+ */
+
+#define ASN1_TFLG_COMBINE (0x1<<10)
+
+/* 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)*/
+#ifndef NO_ASN1_FIELD_NAMES
+const char *sname; /* Structure name */
+#endif
+};
+
+/* 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.
+ *
+ * For COMPAT types the funcs field gives a
+ * set of functions that handle this type, this
+ * supports the old d2i, i2d convention.
+ *
+ * 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_COMPAT 0x3
+
+#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_COMPAT_FUNCS_st {
+ ASN1_new_func *asn1_new;
+ ASN1_free_func *asn1_free;
+ ASN1_d2i_func *asn1_d2i;
+ ASN1_i2d_func *asn1_i2d;
+} ASN1_COMPAT_FUNCS;
+
+typedef struct ASN1_EXTERN_FUNCS_st {
+ void *app_data;
+ ASN1_ex_new_func *asn1_ex_new;
+ ASN1_ex_free_func *asn1_ex_free;
+ ASN1_ex_free_func *asn1_ex_clear;
+ ASN1_ex_d2i *asn1_ex_d2i;
+ ASN1_ex_i2d *asn1_ex_i2d;
+ ASN1_ex_print_func *asn1_ex_print;
+} ASN1_EXTERN_FUNCS;
+
+typedef struct ASN1_PRIMITIVE_FUNCS_st {
+ void *app_data;
+ unsigned long flags;
+ ASN1_ex_new_func *prim_new;
+ ASN1_ex_free_func *prim_free;
+ ASN1_ex_free_func *prim_clear;
+ ASN1_primitive_c2i *prim_c2i;
+ ASN1_primitive_i2c *prim_i2c;
+ ASN1_primitive_print *prim_print;
+} ASN1_PRIMITIVE_FUNCS;
+
+/* This is the ASN1_AUX structure: it handles various
+ * miscellaneous requirements. For example the use of
+ * reference counts and an informational callback.
+ *
+ * The "informational callback" is called at various
+ * points during the ASN1 encoding and decoding. It can
+ * be used to provide minor customisation of the structures
+ * used. This is most useful where the supplied routines
+ * *almost* do the right thing but need some extra help
+ * at a few points. If the callback returns zero then
+ * it is assumed a fatal error has occurred and the
+ * main operation should be abandoned.
+ *
+ * If major changes in the default behaviour are required
+ * then an external type is more appropriate.
+ */
+
+typedef int ASN1_aux_cb(int operation, ASN1_VALUE **in, const ASN1_ITEM *it,
+ void *exarg);
+
+typedef struct ASN1_AUX_st {
+ void *app_data;
+ int flags;
+ int ref_offset; /* Offset of reference value */
+ int ref_lock; /* Lock type to use */
+ ASN1_aux_cb *asn1_cb;
+ int enc_offset; /* Offset of ASN1_ENCODING structure */
+} ASN1_AUX;
+
+/* For print related callbacks exarg points to this structure */
+typedef struct ASN1_PRINT_ARG_st {
+ BIO *out;
+ int indent;
+ const ASN1_PCTX *pctx;
+} ASN1_PRINT_ARG;
+
+/* For streaming related callbacks exarg points to this structure */
+typedef struct ASN1_STREAM_ARG_st {
+ /* BIO to stream through */
+ BIO *out;
+ /* BIO with filters appended */
+ BIO *ndef_bio;
+ /* Streaming I/O boundary */
+ unsigned char **boundary;
+} ASN1_STREAM_ARG;
+
+/* Flags in ASN1_AUX */
+
+/* Use a reference count */
+#define ASN1_AFLG_REFCOUNT 1
+/* Save the encoding of structure (useful for signatures) */
+#define ASN1_AFLG_ENCODING 2
+/* The Sequence length is invalid */
+#define ASN1_AFLG_BROKEN 4
+
+/* operation values for asn1_cb */
+
+#define ASN1_OP_NEW_PRE 0
+#define ASN1_OP_NEW_POST 1
+#define ASN1_OP_FREE_PRE 2
+#define ASN1_OP_FREE_POST 3
+#define ASN1_OP_D2I_PRE 4
+#define ASN1_OP_D2I_POST 5
+#define ASN1_OP_I2D_PRE 6
+#define ASN1_OP_I2D_POST 7
+#define ASN1_OP_PRINT_PRE 8
+#define ASN1_OP_PRINT_POST 9
+#define ASN1_OP_STREAM_PRE 10
+#define ASN1_OP_STREAM_POST 11
+#define ASN1_OP_DETACHED_PRE 12
+#define ASN1_OP_DETACHED_POST 13
+
+/* Macro to implement a primitive type */
+#define IMPLEMENT_ASN1_TYPE(stname) IMPLEMENT_ASN1_TYPE_ex(stname, stname, 0)
+#define IMPLEMENT_ASN1_TYPE_ex(itname, vname, ex) \
+ ASN1_ITEM_start(itname) \
+ ASN1_ITYPE_PRIMITIVE, V_##vname, NULL, 0, NULL, ex, #itname \
+ ASN1_ITEM_end(itname)
+
+/* Macro to implement a multi string type */
+#define IMPLEMENT_ASN1_MSTRING(itname, mask) \
+ ASN1_ITEM_start(itname) \
+ ASN1_ITYPE_MSTRING, mask, NULL, 0, NULL, sizeof(ASN1_STRING), #itname \
+ ASN1_ITEM_end(itname)
+
+/* Macro to implement an ASN1_ITEM in terms of old style funcs */
+
+#define IMPLEMENT_COMPAT_ASN1(sname) IMPLEMENT_COMPAT_ASN1_type(sname, V_ASN1_SEQUENCE)
+
+#define IMPLEMENT_COMPAT_ASN1_type(sname, tag) \
+ static const ASN1_COMPAT_FUNCS sname##_ff = { \
+ (ASN1_new_func *)sname##_new, \
+ (ASN1_free_func *)sname##_free, \
+ (ASN1_d2i_func *)d2i_##sname, \
+ (ASN1_i2d_func *)i2d_##sname, \
+ }; \
+ ASN1_ITEM_start(sname) \
+ ASN1_ITYPE_COMPAT, \
+ tag, \
+ NULL, \
+ 0, \
+ &sname##_ff, \
+ 0, \
+ #sname \
+ ASN1_ITEM_end(sname)
+
+#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)
+
+/* external definitions for primitive types */
+
+DECLARE_ASN1_ITEM(ASN1_BOOLEAN)
+DECLARE_ASN1_ITEM(ASN1_TBOOLEAN)
+DECLARE_ASN1_ITEM(ASN1_FBOOLEAN)
+DECLARE_ASN1_ITEM(ASN1_SEQUENCE)
+DECLARE_ASN1_ITEM(CBIGNUM)
+DECLARE_ASN1_ITEM(BIGNUM)
+DECLARE_ASN1_ITEM(LONG)
+DECLARE_ASN1_ITEM(ZLONG)
+
+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_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
+int ASN1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
+
+void ASN1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
+int ASN1_template_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, const ASN1_TEMPLATE *tt);
+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);
+int ASN1_template_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_TEMPLATE *tt);
+void ASN1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
+
+int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, const ASN1_ITEM *it);
+int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, int utype, char *free_cont, const ASN1_ITEM *it);
+
+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_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
+int asn1_enc_restore(int *len, unsigned char **out, ASN1_VALUE **pval, const ASN1_ITEM *it);
+int asn1_enc_save(ASN1_VALUE **pval, const unsigned char *in, int inlen, const ASN1_ITEM *it);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/include/openssl/base.h b/src/include/openssl/base.h
new file mode 100644
index 0000000..71223a0
--- /dev/null
+++ b/src/include/openssl/base.h
@@ -0,0 +1,219 @@
+/* ====================================================================
+ * 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 OPENSSL_HEADER_BASE_H
+#define OPENSSL_HEADER_BASE_H
+
+
+/* This file should be the first included by all BoringSSL headers. */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+#include <openssl/opensslfeatures.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+#if defined(__x86_64) || defined(_M_AMD64) || defined(_M_X64)
+#define OPENSSL_64_BIT
+#define OPENSSL_X86_64
+#elif defined(__x86) || defined(__i386) || defined(__i386__) || defined(_M_IX86)
+#define OPENSSL_32_BIT
+#define OPENSSL_X86
+#elif defined(__aarch64__)
+#define OPENSSL_64_BIT
+#define OPENSSL_AARCH64
+#elif defined(__arm) || defined(__arm__) || defined(_M_ARM)
+#define OPENSSL_32_BIT
+#define OPENSSL_ARM
+#elif defined(__aarch64__)
+#define OPENSSL_64_BIT
+#define OPENSSL_AARCH64
+#elif defined(__mips__)
+#define OPENSSL_32_BIT
+#define OPENSSL_MIPS
+#elif defined(__pnacl__)
+#define OPENSSL_32_BIT
+#define OPENSSL_PNACL
+#else
+#error "Unknown target CPU"
+#endif
+
+#if defined(__APPLE__)
+#define OPENSSL_APPLE
+#endif
+
+#if defined(WIN32) || defined(_WIN32)
+#define OPENSSL_WINDOWS
+#endif
+
+#define OPENSSL_IS_BORINGSSL
+#define OPENSSL_VERSION_NUMBER 0x10002000
+
+#if defined(BORINGSSL_SHARED_LIBRARY)
+
+#if defined(OPENSSL_WINDOWS)
+
+#if defined(BORINGSSL_IMPLEMENTATION)
+#define OPENSSL_EXPORT __declspec(dllexport)
+#else
+#define OPENSSL_EXPORT __declspec(dllimport)
+#endif
+
+#else /* defined(OPENSSL_WINDOWS) */
+
+#if defined(BORINGSSL_IMPLEMENTATION)
+#define OPENSSL_EXPORT __attribute__((visibility("default")))
+#else
+#define OPENSSL_EXPORT
+#endif
+
+#endif /* defined(OPENSSL_WINDOWS) */
+
+#else /* defined(BORINGSSL_SHARED_LIBRARY) */
+
+#define OPENSSL_EXPORT
+
+#endif /* defined(BORINGSSL_SHARED_LIBRARY) */
+
+typedef int ASN1_BOOLEAN;
+typedef int ASN1_NULL;
+typedef struct ASN1_ITEM_st ASN1_ITEM;
+typedef struct asn1_object_st ASN1_OBJECT;
+typedef struct asn1_pctx_st ASN1_PCTX;
+typedef struct asn1_string_st ASN1_BIT_STRING;
+typedef struct asn1_string_st ASN1_BMPSTRING;
+typedef struct asn1_string_st ASN1_ENUMERATED;
+typedef struct asn1_string_st ASN1_GENERALIZEDTIME;
+typedef struct asn1_string_st ASN1_GENERALSTRING;
+typedef struct asn1_string_st ASN1_IA5STRING;
+typedef struct asn1_string_st ASN1_INTEGER;
+typedef struct asn1_string_st ASN1_OCTET_STRING;
+typedef struct asn1_string_st ASN1_PRINTABLESTRING;
+typedef struct asn1_string_st ASN1_STRING;
+typedef struct asn1_string_st ASN1_T61STRING;
+typedef struct asn1_string_st ASN1_TIME;
+typedef struct asn1_string_st ASN1_UNIVERSALSTRING;
+typedef struct asn1_string_st ASN1_UTCTIME;
+typedef struct asn1_string_st ASN1_UTF8STRING;
+typedef struct asn1_string_st ASN1_VISIBLESTRING;
+
+typedef struct AUTHORITY_KEYID_st AUTHORITY_KEYID;
+typedef struct DIST_POINT_st DIST_POINT;
+typedef struct ISSUING_DIST_POINT_st ISSUING_DIST_POINT;
+typedef struct NAME_CONSTRAINTS_st NAME_CONSTRAINTS;
+typedef struct X509_POLICY_CACHE_st X509_POLICY_CACHE;
+typedef struct X509_POLICY_LEVEL_st X509_POLICY_LEVEL;
+typedef struct X509_POLICY_NODE_st X509_POLICY_NODE;
+typedef struct X509_POLICY_TREE_st X509_POLICY_TREE;
+typedef struct X509_algor_st X509_ALGOR;
+typedef struct X509_crl_st X509_CRL;
+typedef struct X509_pubkey_st X509_PUBKEY;
+typedef struct bignum_ctx BN_CTX;
+typedef struct bignum_st BIGNUM;
+typedef struct bio_method_st BIO_METHOD;
+typedef struct bio_st BIO;
+typedef struct bn_gencb_st BN_GENCB;
+typedef struct bn_mont_ctx_st BN_MONT_CTX;
+typedef struct buf_mem_st BUF_MEM;
+typedef struct cbb_st CBB;
+typedef struct cbs_st CBS;
+typedef struct conf_st CONF;
+typedef struct dh_method DH_METHOD;
+typedef struct dh_st DH;
+typedef struct dsa_method DSA_METHOD;
+typedef struct dsa_st DSA;
+typedef struct ec_key_st EC_KEY;
+typedef struct ecdsa_method_st ECDSA_METHOD;
+typedef struct ecdsa_sig_st ECDSA_SIG;
+typedef struct engine_st ENGINE;
+typedef struct env_md_ctx_st EVP_MD_CTX;
+typedef struct env_md_st EVP_MD;
+typedef struct evp_aead_st EVP_AEAD;
+typedef struct evp_cipher_ctx_st EVP_CIPHER_CTX;
+typedef struct evp_cipher_st EVP_CIPHER;
+typedef struct evp_pkey_asn1_method_st EVP_PKEY_ASN1_METHOD;
+typedef struct evp_pkey_ctx_st EVP_PKEY_CTX;
+typedef struct evp_pkey_method_st EVP_PKEY_METHOD;
+typedef struct evp_pkey_st EVP_PKEY;
+typedef struct hmac_ctx_st HMAC_CTX;
+typedef struct md4_state_st MD4_CTX;
+typedef struct md5_state_st MD5_CTX;
+typedef struct pkcs8_priv_key_info_st PKCS8_PRIV_KEY_INFO;
+typedef struct pkcs12_st PKCS12;
+typedef struct rand_meth_st RAND_METHOD;
+typedef struct rsa_meth_st RSA_METHOD;
+typedef struct rsa_st RSA;
+typedef struct sha256_state_st SHA256_CTX;
+typedef struct sha512_state_st SHA512_CTX;
+typedef struct sha_state_st SHA_CTX;
+typedef struct ssl_ctx_st SSL_CTX;
+typedef struct ssl_st SSL;
+typedef struct st_ERR_FNS ERR_FNS;
+typedef struct v3_ext_ctx X509V3_CTX;
+typedef struct x509_crl_method_st X509_CRL_METHOD;
+typedef struct x509_revoked_st X509_REVOKED;
+typedef struct x509_st X509;
+typedef struct x509_store_ctx_st X509_STORE_CTX;
+typedef struct x509_store_st X509_STORE;
+typedef void *OPENSSL_BLOCK;
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_BASE_H */
diff --git a/src/include/openssl/base64.h b/src/include/openssl/base64.h
new file mode 100644
index 0000000..7aee990
--- /dev/null
+++ b/src/include/openssl/base64.h
@@ -0,0 +1,179 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 OPENSSL_HEADER_BASE64_H
+#define OPENSSL_HEADER_BASE64_H
+
+#include <openssl/base.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* base64 functions.
+ *
+ * For historical reasons, these functions have the EVP_ prefix but just do
+ * base64 encoding and decoding. */
+
+
+typedef struct evp_encode_ctx_st EVP_ENCODE_CTX;
+
+
+/* Encoding */
+
+/* EVP_EncodeInit initialises |*ctx|, which is typically stack
+ * allocated, for an encoding operation.
+ *
+ * NOTE: The encoding operation breaks its output with newlines every
+ * 64 characters of output (48 characters of input). Use
+ * EVP_EncodeBlock to encode raw base64. */
+OPENSSL_EXPORT void EVP_EncodeInit(EVP_ENCODE_CTX *ctx);
+
+/* EVP_EncodeUpdate encodes |in_len| bytes from |in| and writes an encoded
+ * version of them to |out| and sets |*out_len| to the number of bytes written.
+ * Some state may be contained in |ctx| so |EVP_EncodeFinal| must be used to
+ * flush it before using the encoded data. */
+OPENSSL_EXPORT void EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, uint8_t *out,
+ int *out_len, const uint8_t *in,
+ size_t in_len);
+
+/* EVP_EncodeFinal flushes any remaining output bytes from |ctx| to |out| and
+ * sets |*out_len| to the number of bytes written. */
+OPENSSL_EXPORT void EVP_EncodeFinal(EVP_ENCODE_CTX *ctx, uint8_t *out,
+ int *out_len);
+
+/* EVP_EncodeBlock encodes |src_len| bytes from |src| and writes the
+ * result to |dst| with a trailing NUL. It returns the number of bytes
+ * written, not including this trailing NUL. */
+OPENSSL_EXPORT size_t EVP_EncodeBlock(uint8_t *dst, const uint8_t *src,
+ size_t src_len);
+
+/* EVP_EncodedLength sets |*out_len| to the number of bytes that will be needed
+ * to call |EVP_EncodeBlock| on an input of length |len|. This includes the
+ * final NUL that |EVP_EncodeBlock| writes. It returns one on success or zero
+ * on error. */
+OPENSSL_EXPORT int EVP_EncodedLength(size_t *out_len, size_t len);
+
+
+/* Decoding */
+
+/* EVP_DecodedLength sets |*out_len| to the maximum number of bytes
+ * that will be needed to call |EVP_DecodeBase64| on an input of
+ * length |len|. */
+OPENSSL_EXPORT int EVP_DecodedLength(size_t *out_len, size_t len);
+
+/* EVP_DecodeBase64 decodes |in_len| bytes from base64 and writes
+ * |*out_len| bytes to |out|. |max_out| is the size of the output
+ * buffer. If it is not enough for the maximum output size, the
+ * operation fails. */
+OPENSSL_EXPORT int EVP_DecodeBase64(uint8_t *out, size_t *out_len,
+ size_t max_out, const uint8_t *in,
+ size_t in_len);
+
+/* EVP_DecodeInit initialises |*ctx|, which is typically stack allocated, for
+ * a decoding operation.
+ *
+ * TODO(davidben): This isn't a straight-up base64 decode either. Document
+ * and/or fix exactly what's going on here; maximum line length and such. */
+OPENSSL_EXPORT void EVP_DecodeInit(EVP_ENCODE_CTX *ctx);
+
+/* EVP_DecodeUpdate decodes |in_len| bytes from |in| and writes the decoded
+ * data to |out| and sets |*out_len| to the number of bytes written. Some state
+ * may be contained in |ctx| so |EVP_DecodeFinal| must be used to flush it
+ * before using the encoded data.
+ *
+ * It returns -1 on error, one if a full line of input was processed and zero
+ * if the line was short (i.e. it was the last line). */
+OPENSSL_EXPORT int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, uint8_t *out,
+ int *out_len, const uint8_t *in,
+ size_t in_len);
+
+/* EVP_DecodeFinal flushes any remaining output bytes from |ctx| to |out| and
+ * sets |*out_len| to the number of bytes written. It returns one on success
+ * and minus one on error. */
+OPENSSL_EXPORT int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, uint8_t *out,
+ int *out_len);
+
+/* Deprecated: EVP_DecodeBlock encodes |src_len| bytes from |src| and
+ * writes the result to |dst|. It returns the number of bytes written
+ * or -1 on error.
+ *
+ * WARNING: EVP_DecodeBlock's return value does not take padding into
+ * account. It also strips leading whitespace and trailing
+ * whitespace. */
+OPENSSL_EXPORT int EVP_DecodeBlock(uint8_t *dst, const uint8_t *src,
+ size_t src_len);
+
+
+struct evp_encode_ctx_st {
+ unsigned num; /* number saved in a partial encode/decode */
+ unsigned 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 */
+ uint8_t enc_data[80]; /* data to encode */
+ unsigned line_num; /* number read on current line */
+ int expect_nl;
+};
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_BASE64_H */
diff --git a/src/include/openssl/bio.h b/src/include/openssl/bio.h
new file mode 100644
index 0000000..4d89d11
--- /dev/null
+++ b/src/include/openssl/bio.h
@@ -0,0 +1,896 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 OPENSSL_HEADER_BIO_H
+#define OPENSSL_HEADER_BIO_H
+
+#include <openssl/base.h>
+
+#include <stdarg.h>
+#include <stdio.h> /* For FILE */
+
+#include <openssl/ex_data.h>
+#include <openssl/stack.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* BIO abstracts over a file-descriptor like interface. */
+
+
+/* Allocation and freeing. */
+
+DEFINE_STACK_OF(BIO);
+
+/* BIO_new creates a new BIO with the given type and a reference count of one.
+ * It returns the fresh |BIO|, or NULL on error. */
+OPENSSL_EXPORT BIO *BIO_new(const BIO_METHOD *type);
+
+/* BIO_free decrements the reference count of |bio|. If the reference count
+ * drops to zero, it (optionally) calls the BIO's callback with |BIO_CB_FREE|,
+ * frees the ex_data and then, if the BIO has a destroy callback for the
+ * method, calls it. Finally it frees |bio| itself. It then repeats that for
+ * the next BIO in the chain, if any.
+ *
+ * It returns one on success or zero otherwise. */
+OPENSSL_EXPORT int BIO_free(BIO *bio);
+
+/* BIO_vfree performs the same actions as |BIO_free|, but has a void return
+ * value. This is provided for API-compat.
+ *
+ * TODO(fork): remove. */
+OPENSSL_EXPORT void BIO_vfree(BIO *bio);
+
+
+/* Basic I/O. */
+
+/* BIO_read attempts to read |len| bytes into |data|. It returns the number of
+ * bytes read, zero on EOF, or a negative number on error. */
+OPENSSL_EXPORT int BIO_read(BIO *bio, void *data, int len);
+
+/* BIO_gets "reads a line" from |bio| and puts at most |size| bytes into |buf|.
+ * It returns the number of bytes read or a negative number on error. The
+ * phrase "reads a line" is in quotes in the previous sentence because the
+ * exact operation depends on the BIO's method. For example, a digest BIO will
+ * return the digest in response to a |BIO_gets| call.
+ *
+ * TODO(fork): audit the set of BIOs that we end up needing. If all actually
+ * return a line for this call, remove the warning above. */
+OPENSSL_EXPORT int BIO_gets(BIO *bio, char *buf, int size);
+
+/* BIO_write writes |len| bytes from |data| to BIO. It returns the number of
+ * bytes written or a negative number on error. */
+OPENSSL_EXPORT int BIO_write(BIO *bio, const void *data, int len);
+
+/* BIO_puts writes a NUL terminated string from |buf| to |bio|. It returns the
+ * number of bytes written or a negative number on error. */
+OPENSSL_EXPORT int BIO_puts(BIO *bio, const char *buf);
+
+/* BIO_flush flushes any buffered output. It returns one on success and zero
+ * otherwise. */
+OPENSSL_EXPORT int BIO_flush(BIO *bio);
+
+
+/* Low-level control functions.
+ *
+ * These are generic functions for sending control requests to a BIO. In
+ * general one should use the wrapper functions like |BIO_get_close|. */
+
+/* BIO_ctrl sends the control request |cmd| to |bio|. The |cmd| argument should
+ * be one of the |BIO_C_*| values. */
+OPENSSL_EXPORT long BIO_ctrl(BIO *bio, int cmd, long larg, void *parg);
+
+/* BIO_ptr_ctrl acts like |BIO_ctrl| but passes the address of a |void*|
+ * pointer as |parg| and returns the value that is written to it, or NULL if
+ * the control request returns <= 0. */
+OPENSSL_EXPORT char *BIO_ptr_ctrl(BIO *bp, int cmd, long larg);
+
+/* BIO_int_ctrl acts like |BIO_ctrl| but passes the address of a copy of |iarg|
+ * as |parg|. */
+OPENSSL_EXPORT long BIO_int_ctrl(BIO *bp, int cmd, long larg, int iarg);
+
+/* BIO_reset resets |bio| to its initial state, the precise meaning of which
+ * depends on the concrete type of |bio|. It returns one on success and zero
+ * otherwise. */
+OPENSSL_EXPORT int BIO_reset(BIO *bio);
+
+/* BIO_set_flags ORs |flags| with |bio->flags|. */
+OPENSSL_EXPORT void BIO_set_flags(BIO *bio, int flags);
+
+/* BIO_test_flags returns |bio->flags| AND |flags|. */
+OPENSSL_EXPORT int BIO_test_flags(const BIO *bio, int flags);
+
+/* BIO_should_read returns non-zero if |bio| encountered a temporary error
+ * while reading (i.e. EAGAIN), indicating that the caller should retry the
+ * read. */
+OPENSSL_EXPORT int BIO_should_read(const BIO *bio);
+
+/* BIO_should_write returns non-zero if |bio| encountered a temporary error
+ * while writing (i.e. EAGAIN), indicating that the caller should retry the
+ * write. */
+OPENSSL_EXPORT int BIO_should_write(const BIO *bio);
+
+/* BIO_should_retry returns non-zero if the reason that caused a failed I/O
+ * operation is temporary and thus the operation should be retried. Otherwise,
+ * it was a permanent error and it returns zero. */
+OPENSSL_EXPORT int BIO_should_retry(const BIO *bio);
+
+/* BIO_should_io_special returns non-zero if |bio| encountered a temporary
+ * error while performing a special I/O operation, indicating that the caller
+ * should retry. The operation that caused the error is returned by
+ * |BIO_get_retry_reason|. */
+OPENSSL_EXPORT int BIO_should_io_special(const BIO *bio);
+
+/* BIO_RR_SSL_X509_LOOKUP indicates that an SSL BIO blocked because the SSL
+ * library returned with SSL_ERROR_WANT_X509_LOOKUP.
+ *
+ * TODO(fork): remove. */
+#define BIO_RR_SSL_X509_LOOKUP 0x01
+
+/* BIO_RR_CONNECT indicates that a connect would have blocked */
+#define BIO_RR_CONNECT 0x02
+
+/* BIO_RR_ACCEPT indicates that an accept would have blocked */
+#define BIO_RR_ACCEPT 0x03
+
+/* BIO_RR_SSL_CHANNEL_ID_LOOKUP indicates that the ChannelID code cannot find
+ * a private key for a TLS connection. */
+#define BIO_RR_SSL_CHANNEL_ID_LOOKUP 0x04
+
+/* BIO_get_retry_reason returns the special I/O operation that needs to be
+ * retried. The return value is one of the |BIO_RR_*| values. */
+OPENSSL_EXPORT int BIO_get_retry_reason(const BIO *bio);
+
+/* BIO_clear_flags ANDs |bio->flags| with the bitwise-complement of |flags|. */
+OPENSSL_EXPORT void BIO_clear_flags(BIO *bio, int flags);
+
+/* BIO_set_retry_read sets the |BIO_FLAGS_READ| and |BIO_FLAGS_SHOULD_RETRY|
+ * flags on |bio|. */
+OPENSSL_EXPORT void BIO_set_retry_read(BIO *bio);
+
+/* BIO_set_retry_read sets the |BIO_FLAGS_WRITE| and |BIO_FLAGS_SHOULD_RETRY|
+ * flags on |bio|. */
+OPENSSL_EXPORT void BIO_set_retry_write(BIO *bio);
+
+/* BIO_get_retry_flags gets the |BIO_FLAGS_READ|, |BIO_FLAGS_WRITE|,
+ * |BIO_FLAGS_IO_SPECIAL| and |BIO_FLAGS_SHOULD_RETRY| flags from |bio|. */
+OPENSSL_EXPORT int BIO_get_retry_flags(BIO *bio);
+
+/* BIO_clear_retry_flags clears the |BIO_FLAGS_READ|, |BIO_FLAGS_WRITE|,
+ * |BIO_FLAGS_IO_SPECIAL| and |BIO_FLAGS_SHOULD_RETRY| flags from |bio|. */
+OPENSSL_EXPORT void BIO_clear_retry_flags(BIO *bio);
+
+/* BIO_method_type returns the type of |bio|, which is one of the |BIO_TYPE_*|
+ * values. */
+OPENSSL_EXPORT int BIO_method_type(const BIO *bio);
+
+/* bio_info_cb is the type of a callback function that can be called for most
+ * BIO operations. The |event| argument is one of |BIO_CB_*| and can be ORed
+ * with |BIO_CB_RETURN| if the callback is being made after the operation in
+ * question. In that case, |return_value| will contain the return value from
+ * the operation. */
+typedef long (*bio_info_cb)(BIO *bio, int event, const char *parg, int cmd,
+ long larg, long return_value);
+
+/* BIO_callback_ctrl allows the callback function to be manipulated. The |cmd|
+ * arg will generally be |BIO_CTRL_SET_CALLBACK| but arbitary command values
+ * can be interpreted by the |BIO|. */
+OPENSSL_EXPORT long BIO_callback_ctrl(BIO *bio, int cmd, bio_info_cb fp);
+
+/* BIO_pending returns the number of bytes pending to be read. */
+OPENSSL_EXPORT size_t BIO_pending(const BIO *bio);
+
+/* BIO_ctrl_pending calls |BIO_pending| and exists only for compatibility with
+ * OpenSSL. */
+OPENSSL_EXPORT size_t BIO_ctrl_pending(const BIO *bio);
+
+/* BIO_wpending returns the number of bytes pending to be written. */
+OPENSSL_EXPORT size_t BIO_wpending(const BIO *bio);
+
+/* BIO_set_close sets the close flag for |bio|. The meaning of which depends on
+ * the type of |bio| but, for example, a memory BIO interprets the close flag
+ * as meaning that it owns its buffer. It returns one on success and zero
+ * otherwise. */
+OPENSSL_EXPORT int BIO_set_close(BIO *bio, int close_flag);
+
+/* BIO_set_callback sets a callback function that will be called before and
+ * after most operations. See the comment above |bio_info_cb|. */
+OPENSSL_EXPORT void BIO_set_callback(BIO *bio, bio_info_cb callback_func);
+
+/* BIO_set_callback_arg sets the opaque pointer value that can be read within a
+ * callback with |BIO_get_callback_arg|. */
+OPENSSL_EXPORT void BIO_set_callback_arg(BIO *bio, char *arg);
+
+/* BIO_get_callback_arg returns the last value of the opaque callback pointer
+ * set by |BIO_set_callback_arg|. */
+OPENSSL_EXPORT char *BIO_get_callback_arg(const BIO *bio);
+
+/* BIO_number_read returns the number of bytes that have been read from
+ * |bio|. */
+OPENSSL_EXPORT size_t BIO_number_read(const BIO *bio);
+
+/* BIO_number_written returns the number of bytes that have been written to
+ * |bio|. */
+OPENSSL_EXPORT size_t BIO_number_written(const BIO *bio);
+
+
+/* Managing chains of BIOs.
+ *
+ * BIOs can be put into chains where the output of one is used as the input of
+ * the next etc. The most common case is a buffering BIO, which accepts and
+ * buffers writes until flushed into the next BIO in the chain. */
+
+/* BIO_push adds |appended_bio| to the end of the chain with |bio| at the head.
+ * It returns |bio|. Note that |appended_bio| may be the head of a chain itself
+ * and thus this function can be used to join two chains.
+ *
+ * BIO_push takes ownership of the caller's reference to |appended_bio|. */
+OPENSSL_EXPORT BIO *BIO_push(BIO *bio, BIO *appended_bio);
+
+/* BIO_pop removes |bio| from the head of a chain and returns the next BIO in
+ * the chain, or NULL if there is no next BIO.
+ *
+ * The caller takes ownership of the chain's reference to |bio|. */
+OPENSSL_EXPORT BIO *BIO_pop(BIO *bio);
+
+/* BIO_next returns the next BIO in the chain after |bio|, or NULL if there is
+ * no such BIO. */
+OPENSSL_EXPORT BIO *BIO_next(BIO *bio);
+
+/* BIO_free_all calls |BIO_free|.
+ *
+ * TODO(fork): update callers and remove. */
+OPENSSL_EXPORT void BIO_free_all(BIO *bio);
+
+/* BIO_find_type walks a chain of BIOs and returns the first that matches
+ * |type|, which is one of the |BIO_TYPE_*| values. */
+OPENSSL_EXPORT BIO *BIO_find_type(BIO *bio, int type);
+
+/* BIO_copy_next_retry sets the retry flags and |retry_reason| of |bio| from
+ * the next BIO in the chain. */
+OPENSSL_EXPORT void BIO_copy_next_retry(BIO *bio);
+
+
+/* Printf functions.
+ *
+ * These functions are versions of printf functions that output to a BIO rather
+ * than a FILE. */
+#ifdef __GNUC__
+#define __bio_h__attr__ __attribute__
+#else
+#define __bio_h__attr__(x)
+#endif
+OPENSSL_EXPORT int BIO_printf(BIO *bio, const char *format, ...)
+ __bio_h__attr__((__format__(__printf__, 2, 3)));
+#undef __bio_h__attr__
+
+
+/* Utility functions. */
+
+/* BIO_indent prints min(|indent|, |max_indent|) spaces. It returns one on
+ * success and zero otherwise. */
+OPENSSL_EXPORT int BIO_indent(BIO *bio, unsigned indent, unsigned max_indent);
+
+/* BIO_hexdump writes a hex dump of |data| to |bio|. Each line will be indented
+ * by |indent| spaces. */
+OPENSSL_EXPORT int BIO_hexdump(BIO *bio, const uint8_t *data, size_t len,
+ unsigned indent);
+
+/* BIO_print_errors_fp prints the current contents of the error stack to |out|
+ * using human readable strings where possible. */
+OPENSSL_EXPORT void BIO_print_errors_fp(FILE *out);
+
+/* BIO_print_errors prints the current contents of the error stack to |bio|
+ * using human readable strings where possible. */
+OPENSSL_EXPORT void BIO_print_errors(BIO *bio);
+
+
+/* Memory BIOs.
+ *
+ * Memory BIOs can be used as a read-only source (with |BIO_new_mem_buf|) or a
+ * writable sink (with |BIO_new|, |BIO_s_mem| and |BIO_get_mem_buf|). Data
+ * written to a writable, memory BIO can be recalled by reading from it.
+ *
+ * Calling |BIO_reset| on a read-only BIO resets it to the original contents.
+ * On a writable BIO, it clears any data.
+ *
+ * If the close flag is set to |BIO_NOCLOSE| (not the default) then the
+ * underlying |BUF_MEM| will not be freed when the |BIO| is freed.
+ *
+ * Memory BIOs support |BIO_gets| and |BIO_puts|.
+ *
+ * |BIO_eof| is true if no data is in the BIO.
+ *
+ * |BIO_ctrl_pending| returns the number of bytes currently stored. */
+
+/* BIO_s_mem returns a |BIO_METHOD| that uses a in-memory buffer. */
+OPENSSL_EXPORT const BIO_METHOD *BIO_s_mem(void);
+
+/* BIO_new_mem_buf creates BIO that reads and writes from |len| bytes at |buf|.
+ * It does not take ownership of |buf|. It returns the BIO or NULL on error.
+ *
+ * If |len| is negative, then |buf| is treated as a NUL-terminated string, but
+ * don't depend on this in new code. */
+OPENSSL_EXPORT BIO *BIO_new_mem_buf(void *buf, int len);
+
+/* BIO_mem_contents sets |*out_contents| to point to the current contents of
+ * |bio| and |*out_len| to contain the length of that data. It returns one on
+ * success and zero otherwise. */
+OPENSSL_EXPORT int BIO_mem_contents(const BIO *bio,
+ const uint8_t **out_contents,
+ size_t *out_len);
+
+/* BIO_get_mem_data sets |*contents| to point to the current contents of |bio|
+ * and returns the length of the data.
+ *
+ * WARNING: don't use this, use |BIO_mem_contents|. A return value of zero from
+ * this function can mean either that it failed or that the memory buffer is
+ * empty. */
+OPENSSL_EXPORT long BIO_get_mem_data(BIO *bio, char **contents);
+
+/* BIO_get_mem_ptr sets |*out| to a BUF_MEM containing the current contents of
+ * |bio|. It returns one on success or zero on error. */
+OPENSSL_EXPORT int BIO_get_mem_ptr(BIO *bio, BUF_MEM **out);
+
+/* BIO_set_mem_buf sets |b| as the contents of |bio|. If |take_ownership| is
+ * non-zero, then |b| will be freed when |bio| is closed. Returns one on
+ * success or zero otherwise. */
+OPENSSL_EXPORT int BIO_set_mem_buf(BIO *bio, BUF_MEM *b, int take_ownership);
+
+/* BIO_set_mem_eof_return sets the value that will be returned from reading
+ * |bio| when empty. If |eof_value| is zero then an empty memory BIO will
+ * return EOF (that is it will return zero and |BIO_should_retry| will be
+ * false). If |eof_value| is non zero then it will return |eof_value| when it
+ * is empty and it will set the read retry flag (that is |BIO_read_retry| is
+ * true). To avoid ambiguity with a normal positive return value, |eof_value|
+ * should be set to a negative value, typically -1.
+ *
+ * For a read-only BIO, the default is zero (EOF). For a writable BIO, the
+ * default is -1 so that additional data can be written once exhausted. */
+OPENSSL_EXPORT int BIO_set_mem_eof_return(BIO *bio, int eof_value);
+
+
+/* File descriptor BIOs.
+ *
+ * File descriptor BIOs are wrappers around the system's |read| and |write|
+ * functions. If the close flag is set then then |close| is called on the
+ * underlying file descriptor when the BIO is freed.
+ *
+ * |BIO_reset| attempts to seek the file pointer to the start of file using
+ * |lseek|.
+ *
+ * |BIO_seek| sets the file pointer to position |off| from start of file using
+ * |lseek|.
+ *
+ * |BIO_tell| returns the current file position. */
+
+/* BIO_s_fd returns a |BIO_METHOD| for file descriptor fds. */
+OPENSSL_EXPORT const BIO_METHOD *BIO_s_fd(void);
+
+/* BIO_new_fd creates a new file descriptor BIO wrapping |fd|. If |close_flag|
+ * is non-zero, then |fd| will be closed when the BIO is. */
+OPENSSL_EXPORT BIO *BIO_new_fd(int fd, int close_flag);
+
+/* BIO_set_fd sets the file descriptor of |bio| to |fd|. If |close_flag| is
+ * non-zero then |fd| will be closed when |bio| is. It returns one on success
+ * or zero on error. */
+OPENSSL_EXPORT int BIO_set_fd(BIO *bio, int fd, int close_flag);
+
+/* BIO_get_fd sets |*out_fd| to the file descriptor currently in use by |bio|.
+ * It returns one on success and zero on error. */
+OPENSSL_EXPORT int BIO_get_fd(BIO *bio, int *out_fd);
+
+
+/* File BIOs.
+ *
+ * File BIOs are wrappers around a C |FILE| object.
+ *
+ * |BIO_flush| on a file BIO calls |fflush| on the wrapped stream.
+ *
+ * |BIO_reset| attempts to seek the file pointer to the start of file using
+ * |fseek|.
+ *
+ * |BIO_seek| sets the file pointer to the given position from the start of
+ * file using |fseek|.
+ *
+ * |BIO_eof| calls |feof|.
+ *
+ * Setting the close flag causes |fclose| to be called on the stream when the
+ * BIO is freed. */
+
+/* BIO_s_file returns a BIO_METHOD that wraps a |FILE|. */
+OPENSSL_EXPORT const BIO_METHOD *BIO_s_file(void);
+
+/* BIO_new_file creates a file BIO by opening |filename| with the given mode.
+ * See the |fopen| manual page for details of the mode argument. */
+OPENSSL_EXPORT BIO *BIO_new_file(const char *filename, const char *mode);
+
+/* BIO_new_fp creates a new file BIO that wraps the given |FILE|. If
+ * |close_flag| is |BIO_CLOSE|, then |fclose| will be called on |stream| when
+ * the BIO is closed. */
+OPENSSL_EXPORT BIO *BIO_new_fp(FILE *stream, int close_flag);
+
+/* BIO_get_fp sets |*out_file| to the current |FILE| for |bio|. It returns one
+ * on success and zero otherwise. */
+OPENSSL_EXPORT int BIO_get_fp(BIO *bio, FILE **out_file);
+
+/* BIO_set_fp sets the |FILE| for |bio|. If |close_flag| is |BIO_CLOSE| then
+ * |fclose| will be called on |file| when |bio| is closed. It returns one on
+ * sucess and zero otherwise. */
+OPENSSL_EXPORT int BIO_set_fp(BIO *bio, FILE *file, int close_flag);
+
+/* BIO_read_filename opens |filename| for reading and sets the result as the
+ * |FILE| for |bio|. It returns one on success and zero otherwise. The |FILE|
+ * will be closed when |bio| is freed. */
+OPENSSL_EXPORT int BIO_read_filename(BIO *bio, const char *filename);
+
+/* BIO_write_filename opens |filename| for writing and sets the result as the
+ * |FILE| for |bio|. It returns one on success and zero otherwise. The |FILE|
+ * will be closed when |bio| is freed. */
+OPENSSL_EXPORT int BIO_write_filename(BIO *bio, const char *filename);
+
+/* BIO_append_filename opens |filename| for appending and sets the result as
+ * the |FILE| for |bio|. It returns one on success and zero otherwise. The
+ * |FILE| will be closed when |bio| is freed. */
+OPENSSL_EXPORT int BIO_append_filename(BIO *bio, const char *filename);
+
+/* BIO_rw_filename opens |filename| for reading and writing and sets the result
+ * as the |FILE| for |bio|. It returns one on success and zero otherwise. The
+ * |FILE| will be closed when |bio| is freed. */
+OPENSSL_EXPORT int BIO_rw_filename(BIO *bio, const char *filename);
+
+
+/* Buffer BIOs.
+ *
+ * Buffer BIOs are a filter-type BIO, i.e. they are designed to be used in a
+ * chain of BIOs. They provide buffering to reduce the number of operations on
+ * the underlying BIOs. */
+
+OPENSSL_EXPORT const BIO_METHOD *BIO_f_buffer(void);
+
+/* BIO_set_read_buffer_size sets the size, in bytes, of the read buffer and
+ * clears it. It returns one on success and zero on failure. */
+OPENSSL_EXPORT int BIO_set_read_buffer_size(BIO *bio, int buffer_size);
+
+/* BIO_set_write_buffer_size sets the size, in bytes, of the write buffer and
+ * clears it. It returns one on success and zero on failure. */
+OPENSSL_EXPORT int BIO_set_write_buffer_size(BIO *bio, int buffer_size);
+
+
+/* Socket BIOs. */
+
+OPENSSL_EXPORT const BIO_METHOD *BIO_s_socket(void);
+
+/* BIO_new_socket allocates and initialises a fresh BIO which will read and
+ * write to the socket |fd|. If |close_flag| is |BIO_CLOSE| then closing the
+ * BIO will close |fd|. It returns the fresh |BIO| or NULL on error. */
+OPENSSL_EXPORT BIO *BIO_new_socket(int fd, int close_flag);
+
+
+/* Connect BIOs.
+ *
+ * A connection BIO creates a network connection and transfers data over the
+ * resulting socket. */
+
+OPENSSL_EXPORT const BIO_METHOD *BIO_s_connect(void);
+
+/* BIO_new_connect returns a BIO that connects to the given hostname and port.
+ * The |host_and_optional_port| argument should be of the form
+ * "www.example.com" or "www.example.com:443". If the port is omitted, it must
+ * be provided with |BIO_set_conn_port|.
+ *
+ * It returns the new BIO on success, or NULL on error. */
+OPENSSL_EXPORT BIO *BIO_new_connect(const char *host_and_optional_port);
+
+/* BIO_set_conn_hostname sets |host_and_optional_port| as the hostname and
+ * optional port that |bio| will connect to. If the port is omitted, it must be
+ * provided with |BIO_set_conn_port|.
+ *
+ * It returns one on success and zero otherwise. */
+OPENSSL_EXPORT int BIO_set_conn_hostname(BIO *bio,
+ const char *host_and_optional_port);
+
+/* BIO_set_conn_port sets |port_str| as the port or service name that |bio|
+ * will connect to. It returns one on success and zero otherwise. */
+OPENSSL_EXPORT int BIO_set_conn_port(BIO *bio, const char *port_str);
+
+/* BIO_set_nbio sets whether |bio| will use non-blocking I/O operations. It
+ * returns one on success and zero otherwise. */
+OPENSSL_EXPORT int BIO_set_nbio(BIO *bio, int on);
+
+
+/* Datagram BIOs.
+ *
+ * TODO(fork): not implemented. */
+
+#define BIO_CTRL_DGRAM_QUERY_MTU 40 /* as kernel for current 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_SET_NEXT_TIMEOUT \
+ 45 /* Next DTLS handshake timeout to adjust socket timeouts */
+
+#define BIO_CTRL_DGRAM_GET_PEER 46
+
+#define BIO_CTRL_DGRAM_GET_FALLBACK_MTU 47
+
+
+/* BIO Pairs.
+ *
+ * BIO pairs provide a "loopback" like system: a pair of BIOs where data
+ * written to one can be read from the other and vice versa. */
+
+/* BIO_new_bio_pair sets |*out1| and |*out2| to two freshly created BIOs where
+ * data written to one can be read from the other and vice versa. The
+ * |writebuf1| argument gives the size of the buffer used in |*out1| and
+ * |writebuf2| for |*out2|. It returns one on success and zero on error. */
+OPENSSL_EXPORT int BIO_new_bio_pair(BIO **out1, size_t writebuf1, BIO **out2,
+ size_t writebuf2);
+
+/* BIO_new_bio_pair_external_buf is the same as |BIO_new_bio_pair| with the
+ * difference that the caller keeps ownership of the write buffers
+ * |ext_writebuf1_len| and |ext_writebuf2_len|. This is useful when using zero
+ * copy API for read and write operations, in cases where the buffers need to
+ * outlive the BIO pairs. It returns one on success and zero on error. */
+OPENSSL_EXPORT int BIO_new_bio_pair_external_buf(BIO** bio1_p,
+ size_t writebuf1_len,
+ uint8_t* ext_writebuf1,
+ BIO** bio2_p,
+ size_t writebuf2_len,
+ uint8_t* ext_writebuf2);
+
+/* BIO_ctrl_get_read_request returns the number of bytes that the other side of
+ * |bio| tried (unsuccessfully) to read. */
+OPENSSL_EXPORT size_t BIO_ctrl_get_read_request(BIO *bio);
+
+/* BIO_ctrl_get_write_guarantee returns the number of bytes that |bio| (which
+ * must have been returned by |BIO_new_bio_pair|) will accept on the next
+ * |BIO_write| call. */
+OPENSSL_EXPORT size_t BIO_ctrl_get_write_guarantee(BIO *bio);
+
+/* BIO_shutdown_wr marks |bio| as closed, from the point of view of the other
+ * side of the pair. Future |BIO_write| calls on |bio| will fail. It returns
+ * one on success and zero otherwise. */
+OPENSSL_EXPORT int BIO_shutdown_wr(BIO *bio);
+
+
+/* Zero copy versions of BIO_read and BIO_write for BIO pairs. */
+
+/* BIO_zero_copy_get_read_buf initiates a zero copy read operation.
+ * |out_read_buf| is set to the internal read buffer, and |out_buf_offset| is
+ * set to the current read position of |out_read_buf|. The number of bytes
+ * available for read from |out_read_buf| + |out_buf_offset| is returned in
+ * |out_available_bytes|. Note that this function might report fewer bytes
+ * available than |BIO_pending|, if the internal ring buffer is wrapped. It
+ * returns one on success. In case of error it returns zero and pushes to the
+ * error stack.
+ *
+ * The zero copy read operation is completed by calling
+ * |BIO_zero_copy_get_read_buf_done|. Neither |BIO_zero_copy_get_read_buf| nor
+ * any other I/O read operation may be called while a zero copy read operation
+ * is active. */
+OPENSSL_EXPORT int BIO_zero_copy_get_read_buf(BIO* bio,
+ uint8_t** out_read_buf,
+ size_t* out_buf_offset,
+ size_t* out_available_bytes);
+
+/* BIO_zero_copy_get_read_buf_done must be called after reading from a BIO using
+ * |BIO_zero_copy_get_read_buf| to finish the read operation. The |bytes_read|
+ * argument is the number of bytes read.
+ *
+ * It returns one on success. In case of error it returns zero and pushes to the
+ * error stack. */
+OPENSSL_EXPORT int BIO_zero_copy_get_read_buf_done(BIO* bio, size_t bytes_read);
+
+/* BIO_zero_copy_get_write_buf_done initiates a zero copy write operation.
+ * |out_write_buf| is set to to the internal write buffer, and |out_buf_offset|
+ * is set to the current write position of |out_write_buf|.
+ * The number of bytes available for write from |out_write_buf| +
+ * |out_buf_offset| is returned in |out_available_bytes|. Note that this
+ * function might report fewer bytes available than
+ * |BIO_ctrl_get_write_guarantee|, if the internal buffer is wrapped. It returns
+ * one on success. In case of error it returns zero and pushes to the error
+ * stack.
+ *
+ * The zero copy write operation is completed by calling
+ * |BIO_zero_copy_write_buf_don|e. Neither |BIO_zero_copy_get_write_buf_done|
+ * nor any other I/O write operation may be called while a zero copy write
+ * operation is active. */
+OPENSSL_EXPORT int BIO_zero_copy_get_write_buf(BIO* bio,
+ uint8_t** out_write_buf,
+ size_t* out_buf_offset,
+ size_t* out_available_bytes);
+
+/* BIO_zero_copy_write_buf_done must be called after writing to a BIO using
+ * |BIO_zero_copy_get_write_buf_done| to finish the write operation. The
+ * |bytes_written| argument gives the number of bytes written.
+ *
+ * It returns one on success. In case of error it returns zero and pushes to the
+ * error stack. */
+OPENSSL_EXPORT int BIO_zero_copy_get_write_buf_done(BIO* bio,
+ size_t bytes_written);
+
+
+/* BIO_NOCLOSE and |BIO_CLOSE| can be used as symbolic arguments when a "close
+ * flag" is passed to a BIO function. */
+#define BIO_NOCLOSE 0
+#define BIO_CLOSE 1
+
+/* These are passed to 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
+
+/* These are values of the |cmd| argument 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_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 */
+
+
+/* Private functions */
+
+#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
+#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
+
+/* 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
+
+struct bio_method_st {
+ int type;
+ const char *name;
+ int (*bwrite)(BIO *, const char *, int);
+ int (*bread)(BIO *, char *, int);
+ /* TODO(fork): remove bputs. */
+ 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);
+};
+
+struct bio_st {
+ const BIO_METHOD *method;
+ /* bio, mode, argp, argi, argl, ret */
+ long (*callback)(struct bio_st *, int, const char *, int, long, long);
+ char *cb_arg; /* first argument for the callback */
+
+ /* init is non-zero if this |BIO| has been initialised. */
+ int init;
+ /* shutdown is often used by specific |BIO_METHOD|s to determine whether
+ * they own some underlying resource. This flag can often by controlled by
+ * |BIO_set_close|. For example, whether an fd BIO closes the underlying fd
+ * when it, itself, is closed. */
+ int shutdown;
+ int flags;
+ int retry_reason;
+ /* num is a BIO-specific value. For example, in fd BIOs it's used to store a
+ * file descriptor. */
+ int num;
+ /* TODO(fork): reference counting is only used by the SSL BIO code. If we can
+ * dump that then we can remove this. We could also drop
+ * BIO_CTRL_PUSH/BIO_CTRL_POP. */
+ int references;
+ void *ptr;
+ /* next_bio points to the next |BIO| in a chain. This |BIO| owns a reference
+ * to |next_bio|. */
+ struct bio_st *next_bio; /* used by filter BIOs */
+ size_t num_read, num_write;
+
+ CRYPTO_EX_DATA ex_data;
+};
+
+#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_GET_WRITE_GUARANTEE 140
+#define BIO_C_GET_READ_REQUEST 141
+#define BIO_C_SHUTDOWN_WR 142
+#define BIO_C_NREAD0 143
+#define BIO_C_NREAD 144
+#define BIO_C_NWRITE0 145
+#define BIO_C_NWRITE 146
+#define BIO_C_RESET_READ_REQUEST 147
+#define BIO_C_SET_MD_CTX 148
+
+#define BIO_C_SET_PREFIX 149
+#define BIO_C_GET_PREFIX 150
+#define BIO_C_SET_SUFFIX 151
+#define BIO_C_GET_SUFFIX 152
+
+#define BIO_C_SET_EX_ARG 153
+#define BIO_C_GET_EX_ARG 154
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#define BIO_F_bio_make_pair 100
+#define BIO_F_bio_ctrl 101
+#define BIO_F_buffer_ctrl 102
+#define BIO_F_BIO_new_file 103
+#define BIO_F_file_read 104
+#define BIO_F_BIO_new 105
+#define BIO_F_bio_io 106
+#define BIO_F_BIO_new_mem_buf 107
+#define BIO_F_mem_write 108
+#define BIO_F_conn_state 109
+#define BIO_F_conn_ctrl 110
+#define BIO_F_file_ctrl 111
+#define BIO_F_BIO_callback_ctrl 112
+#define BIO_F_bio_ip_and_port_to_socket_and_addr 113
+#define BIO_F_bio_write 114
+#define BIO_F_BIO_ctrl 115
+#define BIO_F_BIO_zero_copy_get_write_buf 116
+#define BIO_F_BIO_zero_copy_get_write_buf_done 117
+#define BIO_F_BIO_zero_copy_get_read_buf 118
+#define BIO_F_BIO_zero_copy_get_read_buf_done 119
+#define BIO_R_UNSUPPORTED_METHOD 100
+#define BIO_R_NO_PORT_SPECIFIED 101
+#define BIO_R_NO_HOSTNAME_SPECIFIED 102
+#define BIO_R_IN_USE 103
+#define BIO_R_UNINITIALIZED 104
+#define BIO_R_CONNECT_ERROR 105
+#define BIO_R_KEEPALIVE 106
+#define BIO_R_BROKEN_PIPE 107
+#define BIO_R_NBIO_CONNECT_ERROR 108
+#define BIO_R_BAD_FOPEN_MODE 109
+#define BIO_R_ASN1_OBJECT_TOO_LONG 110
+#define BIO_R_INVALID_ARGUMENT 111
+#define BIO_R_WRITE_TO_READ_ONLY_BIO 112
+#define BIO_R_ERROR_SETTING_NBIO 113
+#define BIO_R_SYS_LIB 114
+#define BIO_R_NO_SUCH_FILE 115
+#define BIO_R_NULL_PARAMETER 116
+#define BIO_R_UNABLE_TO_CREATE_SOCKET 117
+
+#endif /* OPENSSL_HEADER_BIO_H */
diff --git a/src/include/openssl/bn.h b/src/include/openssl/bn.h
new file mode 100644
index 0000000..0631b8c
--- /dev/null
+++ b/src/include/openssl/bn.h
@@ -0,0 +1,861 @@
+/* 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 OPENSSL_HEADER_BN_H
+#define OPENSSL_HEADER_BN_H
+
+#include <openssl/base.h>
+
+#include <stdio.h> /* for FILE* */
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* BN provides support for working with arbitary sized integers. For example,
+ * although the largest integer supported by the compiler might be 64 bits, BN
+ * will allow you to work with numbers until you run out of memory. */
+
+
+/* BN_ULONG is the native word size when working with big integers. */
+#if defined(OPENSSL_64_BIT)
+#define BN_ULONG uint64_t
+#define BN_BITS2 64
+#elif defined(OPENSSL_32_BIT)
+#define BN_ULONG uint32_t
+#define BN_BITS2 32
+#else
+#error "Must define either OPENSSL_32_BIT or OPENSSL_64_BIT"
+#endif
+
+
+/* Allocation and freeing. */
+
+/* BN_new creates a new, allocated BIGNUM and initialises it. */
+OPENSSL_EXPORT BIGNUM *BN_new(void);
+
+/* BN_init initialises a stack allocated |BIGNUM|. */
+OPENSSL_EXPORT void BN_init(BIGNUM *bn);
+
+/* BN_free frees the data referenced by |bn| and, if |bn| was originally
+ * allocated on the heap, frees |bn| also. */
+OPENSSL_EXPORT void BN_free(BIGNUM *bn);
+
+/* BN_clear_free erases and frees the data referenced by |bn| and, if |bn| was
+ * originally allocated on the heap, frees |bn| also. */
+OPENSSL_EXPORT void BN_clear_free(BIGNUM *bn);
+
+/* BN_dup allocates a new BIGNUM and sets it equal to |src|. It returns the
+ * allocated BIGNUM on success or NULL otherwise. */
+OPENSSL_EXPORT BIGNUM *BN_dup(const BIGNUM *src);
+
+/* BN_copy sets |dest| equal to |src| and returns |dest|. */
+OPENSSL_EXPORT BIGNUM *BN_copy(BIGNUM *dest, const BIGNUM *src);
+
+/* BN_clear sets |bn| to zero and erases the old data. */
+OPENSSL_EXPORT void BN_clear(BIGNUM *bn);
+
+/* BN_value_one returns a static BIGNUM with value 1. */
+OPENSSL_EXPORT const BIGNUM *BN_value_one(void);
+
+/* BN_with_flags initialises a stack allocated |BIGNUM| with pointers to the
+ * contents of |in| but with |flags| ORed into the flags field.
+ *
+ * Note: the two BIGNUMs share state and so |out| should /not/ be passed to
+ * |BN_free|. */
+OPENSSL_EXPORT void BN_with_flags(BIGNUM *out, const BIGNUM *in, int flags);
+
+
+/* Basic functions. */
+
+/* BN_num_bits returns the minimum number of bits needed to represent the
+ * absolute value of |bn|. */
+OPENSSL_EXPORT unsigned BN_num_bits(const BIGNUM *bn);
+
+/* BN_num_bytes returns the minimum number of bytes needed to represent the
+ * absolute value of |bn|. */
+OPENSSL_EXPORT unsigned BN_num_bytes(const BIGNUM *bn);
+
+/* BN_zero sets |bn| to zero. */
+OPENSSL_EXPORT void BN_zero(BIGNUM *bn);
+
+/* BN_one sets |bn| to one. It returns one on success or zero on allocation
+ * failure. */
+OPENSSL_EXPORT int BN_one(BIGNUM *bn);
+
+/* BN_set_word sets |bn| to |value|. It returns one on success or zero on
+ * allocation failure. */
+OPENSSL_EXPORT int BN_set_word(BIGNUM *bn, BN_ULONG value);
+
+/* BN_set_negative sets the sign of |bn|. */
+OPENSSL_EXPORT void BN_set_negative(BIGNUM *bn, int sign);
+
+/* BN_is_negative returns one if |bn| is negative and zero otherwise. */
+OPENSSL_EXPORT int BN_is_negative(const BIGNUM *bn);
+
+/* BN_get_flags returns |bn->flags| & |flags|. */
+OPENSSL_EXPORT int BN_get_flags(const BIGNUM *bn, int flags);
+
+/* BN_set_flags sets |flags| on |bn|. */
+OPENSSL_EXPORT void BN_set_flags(BIGNUM *bn, int flags);
+
+
+/* Conversion functions. */
+
+/* BN_bin2bn sets |*ret| to the value of |len| bytes from |in|, interpreted as
+ * a big-endian number, and returns |ret|. If |ret| is NULL then a fresh
+ * |BIGNUM| is allocated and returned. It returns NULL on allocation
+ * failure. */
+OPENSSL_EXPORT BIGNUM *BN_bin2bn(const uint8_t *in, size_t len, BIGNUM *ret);
+
+/* BN_bn2bin serialises the absolute value of |in| to |out| as a big-endian
+ * integer, which must have |BN_num_bytes| of space available. It returns the
+ * number of bytes written. */
+OPENSSL_EXPORT size_t BN_bn2bin(const BIGNUM *in, uint8_t *out);
+
+/* BN_bn2bin_padded serialises the absolute value of |in| to |out| as a
+ * big-endian integer. The integer is padded with leading zeros up to size
+ * |len|. If |len| is smaller than |BN_num_bytes|, the function fails and
+ * returns 0. Otherwise, it returns 1. */
+OPENSSL_EXPORT int BN_bn2bin_padded(uint8_t *out, size_t len, const BIGNUM *in);
+
+/* BN_bn2hex returns an allocated string that contains a NUL-terminated, hex
+ * representation of |bn|. If |bn| is negative, the first char in the resulting
+ * string will be '-'. Returns NULL on allocation failure. */
+OPENSSL_EXPORT char *BN_bn2hex(const BIGNUM *bn);
+
+/* BN_hex2bn parses the leading hex number from |in|, which may be proceeded by
+ * a '-' to indicate a negative number and may contain trailing, non-hex data.
+ * If |outp| is not NULL, it constructs a BIGNUM equal to the hex number and
+ * stores it in |*outp|. If |*outp| is NULL then it allocates a new BIGNUM and
+ * updates |*outp|. It returns the number of bytes of |in| processed or zero on
+ * error. */
+OPENSSL_EXPORT int BN_hex2bn(BIGNUM **outp, const char *in);
+
+/* BN_bn2dec returns an allocated string that contains a NUL-terminated,
+ * decimal representation of |bn|. If |bn| is negative, the first char in the
+ * resulting string will be '-'. Returns NULL on allocation failure. */
+OPENSSL_EXPORT char *BN_bn2dec(const BIGNUM *a);
+
+/* BN_dec2bn parses the leading decimal number from |in|, which may be
+ * proceeded by a '-' to indicate a negative number and may contain trailing,
+ * non-decimal data. If |outp| is not NULL, it constructs a BIGNUM equal to the
+ * decimal number and stores it in |*outp|. If |*outp| is NULL then it
+ * allocates a new BIGNUM and updates |*outp|. It returns the number of bytes
+ * of |in| processed or zero on error. */
+OPENSSL_EXPORT int BN_dec2bn(BIGNUM **outp, const char *in);
+
+/* BN_asc2bn acts like |BN_dec2bn| or |BN_hex2bn| depending on whether |in|
+ * begins with "0X" or "0x" (indicating hex) or not (indicating decimal). A
+ * leading '-' is still permitted and comes before the optional 0X/0x. It
+ * returns one on success or zero on error. */
+OPENSSL_EXPORT int BN_asc2bn(BIGNUM **outp, const char *in);
+
+/* BN_print writes a hex encoding of |a| to |bio|. It returns one on success
+ * and zero on error. */
+OPENSSL_EXPORT int BN_print(BIO *bio, const BIGNUM *a);
+
+/* BN_print_fp acts like |BIO_print|, but wraps |fp| in a |BIO| first. */
+OPENSSL_EXPORT int BN_print_fp(FILE *fp, const BIGNUM *a);
+
+/* BN_get_word returns the absolute value of |bn| as a single word. If |bn| is
+ * too large to be represented as a single word, the maximum possible value
+ * will be returned. */
+OPENSSL_EXPORT BN_ULONG BN_get_word(const BIGNUM *bn);
+
+
+/* Internal functions.
+ *
+ * These functions are useful for code that is doing low-level manipulations of
+ * BIGNUM values. However, be sure that no other function in this file does
+ * what you want before turning to these. */
+
+/* bn_correct_top decrements |bn->top| until |bn->d[top-1]| is non-zero or
+ * until |top| is zero. */
+OPENSSL_EXPORT void bn_correct_top(BIGNUM *bn);
+
+/* bn_wexpand ensures that |bn| has at least |words| works of space without
+ * altering its value. It returns one on success or zero on allocation
+ * failure. */
+OPENSSL_EXPORT BIGNUM *bn_wexpand(BIGNUM *bn, unsigned words);
+
+
+/* BIGNUM pools.
+ *
+ * Certain BIGNUM operations need to use many temporary variables and
+ * allocating and freeing them can be quite slow. Thus such opertions typically
+ * take a |BN_CTX| parameter, which contains a pool of |BIGNUMs|. The |ctx|
+ * argument to a public function may be NULL, in which case a local |BN_CTX|
+ * will be created just for the lifetime of that call.
+ *
+ * A function must call |BN_CTX_start| first. Then, |BN_CTX_get| may be called
+ * repeatedly to obtain temporary |BIGNUM|s. All |BN_CTX_get| calls must be made
+ * before calling any other functions that use the |ctx| as an argument.
+ *
+ * Finally, |BN_CTX_end| must be called before returning from the function.
+ * When |BN_CTX_end| is called, the |BIGNUM| pointers obtained from
+ * |BN_CTX_get| become invalid. */
+
+/* BN_CTX_new returns a new, empty BN_CTX or NULL on allocation failure. */
+OPENSSL_EXPORT BN_CTX *BN_CTX_new(void);
+
+/* BN_CTX_free frees all BIGNUMs contained in |ctx| and then frees |ctx|
+ * itself. */
+OPENSSL_EXPORT void BN_CTX_free(BN_CTX *ctx);
+
+/* BN_CTX_start "pushes" a new entry onto the |ctx| stack and allows future
+ * calls to |BN_CTX_get|. */
+OPENSSL_EXPORT void BN_CTX_start(BN_CTX *ctx);
+
+/* BN_CTX_get returns a new |BIGNUM|, or NULL on allocation failure. Once
+ * |BN_CTX_get| has returned NULL, all future calls will also return NULL until
+ * |BN_CTX_end| is called. */
+OPENSSL_EXPORT BIGNUM *BN_CTX_get(BN_CTX *ctx);
+
+/* BN_CTX_end invalidates all |BIGNUM|s returned from |BN_CTX_get| since the
+ * matching |BN_CTX_start| call. */
+OPENSSL_EXPORT void BN_CTX_end(BN_CTX *ctx);
+
+
+/* Simple arithmetic */
+
+/* BN_add sets |r| = |a| + |b|, where |r| may be the same pointer as either |a|
+ * or |b|. It returns one on success and zero on allocation failure. */
+OPENSSL_EXPORT int BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);
+
+/* BN_uadd sets |r| = |a| + |b|, where |a| and |b| are non-negative and |r| may
+ * be the same pointer as either |a| or |b|. It returns one on success and zero
+ * on allocation failure. */
+OPENSSL_EXPORT int BN_uadd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);
+
+/* BN_add_word adds |w| to |a|. It returns one on success and zero otherwise. */
+OPENSSL_EXPORT int BN_add_word(BIGNUM *a, BN_ULONG w);
+
+/* BN_sub sets |r| = |a| - |b|, where |r| must be a distinct pointer from |a|
+ * and |b|. It returns one on success and zero on allocation failure. */
+OPENSSL_EXPORT int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);
+
+/* BN_usub sets |r| = |a| - |b|, where |a| and |b| are non-negative integers,
+ * |b| < |a| and |r| must be a distinct pointer from |a| and |b|. It returns
+ * one on success and zero on allocation failure. */
+OPENSSL_EXPORT int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);
+
+/* BN_sub_word subtracts |w| from |a|. It returns one on success and zero on
+ * allocation failure. */
+OPENSSL_EXPORT int BN_sub_word(BIGNUM *a, BN_ULONG w);
+
+/* BN_mul sets |r| = |a| * |b|, where |r| may be the same pointer as |a| or
+ * |b|. Returns one on success and zero otherwise. */
+OPENSSL_EXPORT int BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+ BN_CTX *ctx);
+
+/* BN_mul_word sets |bn| = |bn| * |w|. It returns one on success or zero on
+ * allocation failure. */
+OPENSSL_EXPORT int BN_mul_word(BIGNUM *bn, BN_ULONG w);
+
+/* BN_sqr sets |r| = |a|^2 (i.e. squares), where |r| may be the same pointer as
+ * |a|. Returns one on success and zero otherwise. This is more efficient than
+ * BN_mul(r, a, a, ctx). */
+OPENSSL_EXPORT int BN_sqr(BIGNUM *r, const BIGNUM *a, BN_CTX *ctx);
+
+/* BN_div divides |numerator| by |divisor| and places the result in |quotient|
+ * and the remainder in |rem|. Either of |quotient| or |rem| may be NULL, in
+ * which case the respective value is not returned. The result is rounded
+ * towards zero; thus if |numerator| is negative, the remainder will be zero or
+ * negative. It returns one on success or zero on error. */
+OPENSSL_EXPORT int BN_div(BIGNUM *quotient, BIGNUM *rem,
+ const BIGNUM *numerator, const BIGNUM *divisor,
+ BN_CTX *ctx);
+
+/* BN_div_word sets |numerator| = |numerator|/|divisor| and returns the
+ * remainder or (BN_ULONG)-1 on error. */
+OPENSSL_EXPORT BN_ULONG BN_div_word(BIGNUM *numerator, BN_ULONG divisor);
+
+/* BN_sqrt sets |*out_sqrt| (which may be the same |BIGNUM| as |in|) to the
+ * square root of |in|, using |ctx|. It returns one on success or zero on
+ * error. Negative numbers and non-square numbers will result in an error with
+ * appropriate errors on the error queue. */
+OPENSSL_EXPORT int BN_sqrt(BIGNUM *out_sqrt, const BIGNUM *in, BN_CTX *ctx);
+
+
+/* Comparison functions */
+
+/* BN_cmp returns a value less than, equal to or greater than zero if |a| is
+ * less than, equal to or greater than |b|, respectively. */
+OPENSSL_EXPORT int BN_cmp(const BIGNUM *a, const BIGNUM *b);
+
+/* BN_ucmp returns a value less than, equal to or greater than zero if the
+ * absolute value of |a| is less than, equal to or greater than the absolute
+ * value of |b|, respectively. */
+OPENSSL_EXPORT int BN_ucmp(const BIGNUM *a, const BIGNUM *b);
+
+/* BN_abs_is_word returns one if the absolute value of |bn| equals |w| and zero
+ * otherwise. */
+OPENSSL_EXPORT int BN_abs_is_word(const BIGNUM *bn, BN_ULONG w);
+
+/* BN_is_zero returns one if |bn| is zero and zero otherwise. */
+OPENSSL_EXPORT int BN_is_zero(const BIGNUM *bn);
+
+/* BN_is_one returns one if |bn| equals one and zero otherwise. */
+OPENSSL_EXPORT int BN_is_one(const BIGNUM *bn);
+
+/* BN_is_word returns one if |bn| is exactly |w| and zero otherwise. */
+OPENSSL_EXPORT int BN_is_word(const BIGNUM *bn, BN_ULONG w);
+
+/* BN_is_odd returns one if |bn| is odd and zero otherwise. */
+OPENSSL_EXPORT int BN_is_odd(const BIGNUM *bn);
+
+
+/* Bitwise operations. */
+
+/* BN_lshift sets |r| equal to |a| << n. The |a| and |r| arguments may be the
+ * same |BIGNUM|. It returns one on success and zero on allocation failure. */
+OPENSSL_EXPORT int BN_lshift(BIGNUM *r, const BIGNUM *a, int n);
+
+/* BN_lshift1 sets |r| equal to |a| << 1, where |r| and |a| may be the same
+ * pointer. It returns one on success and zero on allocation failure. */
+OPENSSL_EXPORT int BN_lshift1(BIGNUM *r, const BIGNUM *a);
+
+/* BN_rshift sets |r| equal to |a| >> n, where |r| and |a| may be the same
+ * pointer. It returns one on success and zero on allocation failure. */
+OPENSSL_EXPORT int BN_rshift(BIGNUM *r, const BIGNUM *a, int n);
+
+/* BN_rshift1 sets |r| equal to |a| >> 1, where |r| and |a| may be the same
+ * pointer. It returns one on success and zero on allocation failure. */
+OPENSSL_EXPORT int BN_rshift1(BIGNUM *r, const BIGNUM *a);
+
+/* BN_set_bit sets the |n|th, least-significant bit in |a|. For example, if |a|
+ * is 2 then setting bit zero will make it 3. It returns one on success or zero
+ * on allocation failure. */
+OPENSSL_EXPORT int BN_set_bit(BIGNUM *a, int n);
+
+/* BN_clear_bit clears the |n|th, least-significant bit in |a|. For example, if
+ * |a| is 3, clearing bit zero will make it two. It returns one on success or
+ * zero on allocation failure. */
+OPENSSL_EXPORT int BN_clear_bit(BIGNUM *a, int n);
+
+/* BN_is_bit_set returns the value of the |n|th, least-significant bit in |a|,
+ * or zero if the bit doesn't exist. */
+OPENSSL_EXPORT int BN_is_bit_set(const BIGNUM *a, int n);
+
+/* BN_mask_bits truncates |a| so that it is only |n| bits long. It returns one
+ * on success or zero if |n| is greater than the length of |a| already. */
+OPENSSL_EXPORT int BN_mask_bits(BIGNUM *a, int n);
+
+
+/* Modulo arithmetic. */
+
+/* BN_mod_word returns |a| mod |w|. */
+OPENSSL_EXPORT BN_ULONG BN_mod_word(const BIGNUM *a, BN_ULONG w);
+
+/* BN_mod is a helper macro that calls |BN_div| and discards the quotient. */
+#define BN_mod(rem, numerator, divisor, ctx) \
+ BN_div(NULL, (rem), (numerator), (divisor), (ctx))
+
+/* BN_nnmod is a non-negative modulo function. It acts like |BN_mod|, but 0 <=
+ * |rem| < |divisor| is always true. */
+OPENSSL_EXPORT int BN_nnmod(BIGNUM *rem, const BIGNUM *numerator,
+ const BIGNUM *divisor, BN_CTX *ctx);
+
+/* BN_mod_add sets |r| = |a| + |b| mod |m|. It returns one on success and zero
+ * on error. */
+OPENSSL_EXPORT int BN_mod_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+ const BIGNUM *m, BN_CTX *ctx);
+
+/* BN_mod_add_quick acts like |BN_mod_add| but requires that |a| and |b| be
+ * non-negative and less than |m|. */
+OPENSSL_EXPORT int BN_mod_add_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+ const BIGNUM *m);
+
+/* BN_mod_sub sets |r| = |a| - |b| mod |m|. It returns one on success and zero
+ * on error. */
+OPENSSL_EXPORT int BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+ const BIGNUM *m, BN_CTX *ctx);
+
+/* BN_mod_sub_quick acts like |BN_mod_sub| but requires that |a| and |b| be
+ * non-negative and less than |m|. */
+OPENSSL_EXPORT int BN_mod_sub_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+ const BIGNUM *m);
+
+/* BN_mod_mul sets |r| = |a|*|b| mod |m|. It returns one on success and zero
+ * on error. */
+OPENSSL_EXPORT int BN_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+ const BIGNUM *m, BN_CTX *ctx);
+
+/* BN_mod_mul sets |r| = |a|^2 mod |m|. It returns one on success and zero
+ * on error. */
+OPENSSL_EXPORT int BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m,
+ BN_CTX *ctx);
+
+/* BN_mod_lshift sets |r| = (|a| << n) mod |m|, where |r| and |a| may be the
+ * same pointer. It returns one on success and zero on error. */
+OPENSSL_EXPORT int BN_mod_lshift(BIGNUM *r, const BIGNUM *a, int n,
+ const BIGNUM *m, BN_CTX *ctx);
+
+/* BN_mod_lshift_quick acts like |BN_mod_lshift| but requires that |a| be
+ * non-negative and less than |m|. */
+OPENSSL_EXPORT int BN_mod_lshift_quick(BIGNUM *r, const BIGNUM *a, int n,
+ const BIGNUM *m);
+
+/* BN_mod_lshift1 sets |r| = (|a| << 1) mod |m|, where |r| and |a| may be the
+ * same pointer. It returns one on success and zero on error. */
+OPENSSL_EXPORT int BN_mod_lshift1(BIGNUM *r, const BIGNUM *a, const BIGNUM *m,
+ BN_CTX *ctx);
+
+/* BN_mod_lshift1_quick acts like |BN_mod_lshift1| but requires that |a| be
+ * non-negative and less than |m|. */
+OPENSSL_EXPORT int BN_mod_lshift1_quick(BIGNUM *r, const BIGNUM *a,
+ const BIGNUM *m);
+
+/* BN_mod_sqrt returns a |BIGNUM|, r, such that r^2 == a (mod p). */
+OPENSSL_EXPORT BIGNUM *BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p,
+ BN_CTX *ctx);
+
+
+/* Random and prime number generation. */
+
+/* BN_rand sets |rnd| to a random number of length |bits|. If |top| is zero,
+ * the most-significant bit will be set. If |top| is one, the two most
+ * significant bits will be set.
+ *
+ * If |top| is -1 then no extra action will be taken and |BN_num_bits(rnd)| may
+ * not equal |bits| if the most significant bits randomly ended up as zeros.
+ *
+ * If |bottom| is non-zero, the least-significant bit will be set. The function
+ * returns one on success or zero otherwise. */
+OPENSSL_EXPORT int BN_rand(BIGNUM *rnd, int bits, int top, int bottom);
+
+/* BN_pseudo_rand is an alias for |BN_rand|. */
+OPENSSL_EXPORT int BN_pseudo_rand(BIGNUM *rnd, int bits, int top, int bottom);
+
+/* BN_rand_range sets |rnd| to a random value [0..range). It returns one on
+ * success and zero otherwise. */
+OPENSSL_EXPORT int BN_rand_range(BIGNUM *rnd, const BIGNUM *range);
+
+/* BN_pseudo_rand_range is an alias for BN_rand_range. */
+OPENSSL_EXPORT int BN_pseudo_rand_range(BIGNUM *rnd, const BIGNUM *range);
+
+/* BN_generate_dsa_nonce generates a random number 0 <= out < range. Unlike
+ * BN_rand_range, it also includes the contents of |priv| and |message| in the
+ * generation so that an RNG failure isn't fatal as long as |priv| remains
+ * secret. This is intended for use in DSA and ECDSA where an RNG weakness
+ * leads directly to private key exposure unless this function is used.
+ * It returns one on success and zero on error. */
+OPENSSL_EXPORT int BN_generate_dsa_nonce(BIGNUM *out, const BIGNUM *range,
+ const BIGNUM *priv,
+ const uint8_t *message,
+ size_t message_len, BN_CTX *ctx);
+
+/* BN_GENCB holds a callback function that is used by generation functions that
+ * can take a very long time to complete. Use |BN_GENCB_set| to initialise a
+ * |BN_GENCB| structure.
+ *
+ * The callback receives the address of that |BN_GENCB| structure as its last
+ * argument and the user is free to put an arbitary pointer in |arg|. The other
+ * arguments are set as follows:
+ * event=BN_GENCB_GENERATED, n=i: after generating the i'th possible prime
+ * number.
+ * event=BN_GENCB_PRIME_TEST, n=-1: when finished trial division primality
+ * checks.
+ * event=BN_GENCB_PRIME_TEST, n=i: when the i'th primality test has finished.
+ *
+ * The callback can return zero to abort the generation progress or one to
+ * allow it to continue.
+ *
+ * When other code needs to call a BN generation function it will often take a
+ * BN_GENCB argument and may call the function with other argument values. */
+#define BN_GENCB_GENERATED 0
+#define BN_GENCB_PRIME_TEST 1
+
+struct bn_gencb_st {
+ void *arg; /* callback-specific data */
+ int (*callback)(int event, int n, struct bn_gencb_st *);
+};
+
+/* BN_GENCB_set configures |callback| to call |f| and sets |callout->arg| to
+ * |arg|. */
+OPENSSL_EXPORT void BN_GENCB_set(BN_GENCB *callback,
+ int (*f)(int event, int n,
+ struct bn_gencb_st *),
+ void *arg);
+
+/* BN_GENCB_call calls |callback|, if not NULL, and returns the return value of
+ * the callback, or 1 if |callback| is NULL. */
+OPENSSL_EXPORT int BN_GENCB_call(BN_GENCB *callback, int event, int n);
+
+/* BN_generate_prime_ex sets |ret| to a prime number of |bits| length. If safe
+ * is non-zero then the prime will be such that (ret-1)/2 is also a prime.
+ * (This is needed for Diffie-Hellman groups to ensure that the only subgroups
+ * are of size 2 and (p-1)/2.).
+ *
+ * If |add| is not NULL, the prime will fulfill the condition |ret| % |add| ==
+ * |rem| in order to suit a given generator. (If |rem| is NULL then |ret| %
+ * |add| == 1.)
+ *
+ * If |cb| is not NULL, it will be called during processing to give an
+ * indication of progress. See the comments for |BN_GENCB|. It returns one on
+ * success and zero otherwise. */
+OPENSSL_EXPORT int BN_generate_prime_ex(BIGNUM *ret, int bits, int safe,
+ const BIGNUM *add, const BIGNUM *rem,
+ BN_GENCB *cb);
+
+/* BN_prime_checks is magic value that can be used as the |checks| argument to
+ * the primality testing functions in order to automatically select a number of
+ * Miller-Rabin checks that gives a false positive rate of ~2^{-80}. */
+#define BN_prime_checks 0
+
+/* BN_primality_test sets |*is_probably_prime| to one if |candidate| is
+ * probably a prime number by the Miller-Rabin test or zero if it's certainly
+ * not.
+ *
+ * If |do_trial_division| is non-zero then |candidate| will be tested against a
+ * list of small primes before Miller-Rabin tests. The probability of this
+ * function returning a false positive is 2^{2*checks}. If |checks| is
+ * |BN_prime_checks| then a value that results in approximately 2^{-80} false
+ * positive probability is used. If |cb| is not NULL then it is called during
+ * the checking process. See the comment above |BN_GENCB|.
+ *
+ * The function returns one on success and zero on error.
+ *
+ * (If you are unsure whether you want |do_trial_division|, don't set it.) */
+OPENSSL_EXPORT int BN_primality_test(int *is_probably_prime,
+ const BIGNUM *candidate, int checks,
+ BN_CTX *ctx, int do_trial_division,
+ BN_GENCB *cb);
+
+/* BN_is_prime_fasttest_ex returns one if |candidate| is probably a prime
+ * number by the Miller-Rabin test, zero if it's certainly not and -1 on error.
+ *
+ * If |do_trial_division| is non-zero then |candidate| will be tested against a
+ * list of small primes before Miller-Rabin tests. The probability of this
+ * function returning one when |candidate| is composite is 2^{2*checks}. If
+ * |checks| is |BN_prime_checks| then a value that results in approximately
+ * 2^{-80} false positive probability is used. If |cb| is not NULL then it is
+ * called during the checking process. See the comment above |BN_GENCB|.
+ *
+ * WARNING: deprecated. Use |BN_primality_test|. */
+OPENSSL_EXPORT int BN_is_prime_fasttest_ex(const BIGNUM *candidate, int checks,
+ BN_CTX *ctx, int do_trial_division,
+ BN_GENCB *cb);
+
+/* BN_is_prime_ex acts the same as |BN_is_prime_fasttest_ex| with
+ * |do_trial_division| set to zero.
+ *
+ * WARNING: deprecated: Use |BN_primality_test|. */
+OPENSSL_EXPORT int BN_is_prime_ex(const BIGNUM *candidate, int checks,
+ BN_CTX *ctx, BN_GENCB *cb);
+
+
+/* Number theory functions */
+
+/* BN_gcd sets |r| = gcd(|a|, |b|). It returns one on success and zero
+ * otherwise. */
+OPENSSL_EXPORT int BN_gcd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+ BN_CTX *ctx);
+
+/* BN_mod_inverse sets |out| equal to |a|^-1, mod |n|. If either of |a| or |n|
+ * have |BN_FLG_CONSTTIME| set then the operation is performed in constant
+ * time. If |out| is NULL, a fresh BIGNUM is allocated. It returns the result
+ * or NULL on error. */
+OPENSSL_EXPORT BIGNUM *BN_mod_inverse(BIGNUM *out, const BIGNUM *a,
+ const BIGNUM *n, BN_CTX *ctx);
+
+/* BN_kronecker returns the Kronecker symbol of |a| and |b| (which is -1, 0 or
+ * 1), or -2 on error. */
+OPENSSL_EXPORT int BN_kronecker(const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);
+
+
+/* Montgomery arithmetic. */
+
+/* BN_MONT_CTX contains the precomputed values needed to work in a specific
+ * Montgomery domain. */
+
+/* BN_MONT_CTX_new returns a fresh BN_MONT_CTX or NULL on allocation failure. */
+OPENSSL_EXPORT BN_MONT_CTX *BN_MONT_CTX_new(void);
+
+/* BN_MONT_CTX_init initialises a stack allocated |BN_MONT_CTX|. */
+OPENSSL_EXPORT void BN_MONT_CTX_init(BN_MONT_CTX *mont);
+
+/* BN_MONT_CTX_free frees the contexts of |mont| and, if it was originally
+ * allocated with |BN_MONT_CTX_new|, |mont| itself. */
+OPENSSL_EXPORT void BN_MONT_CTX_free(BN_MONT_CTX *mont);
+
+/* BN_MONT_CTX_copy sets |to| equal to |from|. It returns |to| on success or
+ * NULL on error. */
+OPENSSL_EXPORT BN_MONT_CTX *BN_MONT_CTX_copy(BN_MONT_CTX *to,
+ BN_MONT_CTX *from);
+
+/* BN_MONT_CTX_set sets up a Montgomery context given the modulus, |mod|. It
+ * returns one on success and zero on error. */
+OPENSSL_EXPORT int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod,
+ BN_CTX *ctx);
+
+/* BN_MONT_CTX_set_locked takes the lock indicated by |lock| and checks whether
+ * |*pmont| is NULL. If so, it creates a new |BN_MONT_CTX| and sets the modulus
+ * for it to |mod|. It then stores it as |*pmont| and returns it, or NULL on
+ * error.
+ *
+ * If |*pmont| is already non-NULL then the existing value is returned. */
+OPENSSL_EXPORT BN_MONT_CTX *BN_MONT_CTX_set_locked(BN_MONT_CTX **pmont,
+ int lock, const BIGNUM *mod,
+ BN_CTX *ctx);
+
+/* BN_to_montgomery sets |ret| equal to |a| in the Montgomery domain. It
+ * returns one on success and zero on error. */
+OPENSSL_EXPORT int BN_to_montgomery(BIGNUM *ret, const BIGNUM *a,
+ const BN_MONT_CTX *mont, BN_CTX *ctx);
+
+/* BN_from_montgomery sets |ret| equal to |a| * R^-1, i.e. translates values
+ * out of the Montgomery domain. It returns one on success or zero on error. */
+OPENSSL_EXPORT int BN_from_montgomery(BIGNUM *ret, const BIGNUM *a,
+ const BN_MONT_CTX *mont, BN_CTX *ctx);
+
+/* BN_mod_mul_montgomery set |r| equal to |a| * |b|, in the Montgomery domain.
+ * Both |a| and |b| must already be in the Montgomery domain (by
+ * |BN_to_montgomery|). It returns one on success or zero on error. */
+OPENSSL_EXPORT int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a,
+ const BIGNUM *b,
+ const BN_MONT_CTX *mont, BN_CTX *ctx);
+
+
+/* Exponentiation. */
+
+/* BN_exp sets |r| equal to |a|^{|p|}. It does so with a square-and-multiply
+ * algorithm that leaks side-channel information. It returns one on success or
+ * zero otherwise. */
+OPENSSL_EXPORT int BN_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+ BN_CTX *ctx);
+
+/* BN_mod_exp sets |r| equal to |a|^{|p|} mod |m|. It does so with the best
+ * algorithm for the values provided and can run in constant time if
+ * |BN_FLG_CONSTTIME| is set for |p|. It returns one on success or zero
+ * otherwise. */
+OPENSSL_EXPORT int BN_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx);
+
+OPENSSL_EXPORT int BN_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx,
+ BN_MONT_CTX *m_ctx);
+
+OPENSSL_EXPORT 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);
+
+OPENSSL_EXPORT 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);
+OPENSSL_EXPORT 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);
+
+
+/* Private functions */
+
+struct bignum_st {
+ BN_ULONG *d; /* Pointer to an array of 'BN_BITS2' bit chunks in little-endian
+ order. */
+ int top; /* Index of last used element in |d|, plus one. */
+ int dmax; /* Size of |d|, in words. */
+ int neg; /* one if the number is negative */
+ int flags; /* bitmask of BN_FLG_* values */
+};
+
+struct bn_mont_ctx_st {
+ BIGNUM RR; /* used to convert to montgomery form */
+ BIGNUM N; /* The modulus */
+ BIGNUM Ni; /* R*(1/R mod N) - N*Ni = 1
+ * (Ni is only stored for bignum algorithm) */
+ BN_ULONG n0[2]; /* least significant word(s) of Ni;
+ (type changed with 0.9.9, was "BN_ULONG n0;" before) */
+ int flags;
+ int ri; /* number of bits in R */
+};
+
+OPENSSL_EXPORT unsigned BN_num_bits_word(BN_ULONG l);
+
+#define BN_FLG_MALLOCED 0x01
+#define BN_FLG_STATIC_DATA 0x02
+/* 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. */
+#define BN_FLG_CONSTTIME 0x04
+
+
+/* Android compatibility section.
+ *
+ * These functions are declared, temporarily, for Android because
+ * wpa_supplicant will take a little time to sync with upstream. Outside of
+ * Android they'll have no definition. */
+
+OPENSSL_EXPORT BIGNUM *get_rfc3526_prime_1536(BIGNUM *bn);
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#define BN_F_BN_bn2hex 100
+#define BN_F_BN_new 101
+#define BN_F_BN_exp 102
+#define BN_F_mod_exp_recp 103
+#define BN_F_BN_mod_sqrt 104
+#define BN_F_BN_rand 105
+#define BN_F_BN_rand_range 106
+#define BN_F_bn_wexpand 107
+#define BN_F_BN_mod_exp_mont 108
+#define BN_F_BN_mod_exp2_mont 109
+#define BN_F_BN_CTX_get 110
+#define BN_F_BN_mod_inverse 111
+#define BN_F_BN_bn2dec 112
+#define BN_F_BN_div 113
+#define BN_F_BN_div_recp 114
+#define BN_F_BN_mod_exp_mont_consttime 115
+#define BN_F_BN_mod_exp_mont_word 116
+#define BN_F_BN_CTX_start 117
+#define BN_F_BN_usub 118
+#define BN_F_BN_mod_lshift_quick 119
+#define BN_F_BN_CTX_new 120
+#define BN_F_BN_mod_inverse_no_branch 121
+#define BN_F_BN_generate_dsa_nonce 122
+#define BN_F_BN_generate_prime_ex 123
+#define BN_F_BN_sqrt 124
+#define BN_R_NOT_A_SQUARE 100
+#define BN_R_TOO_MANY_ITERATIONS 101
+#define BN_R_INPUT_NOT_REDUCED 102
+#define BN_R_TOO_MANY_TEMPORARY_VARIABLES 103
+#define BN_R_NO_INVERSE 104
+#define BN_R_NOT_INITIALIZED 105
+#define BN_R_DIV_BY_ZERO 106
+#define BN_R_CALLED_WITH_EVEN_MODULUS 107
+#define BN_R_EXPAND_ON_STATIC_BIGNUM_DATA 108
+#define BN_R_BAD_RECIPROCAL 109
+#define BN_R_P_IS_NOT_PRIME 110
+#define BN_R_INVALID_RANGE 111
+#define BN_R_ARG2_LT_ARG3 112
+#define BN_R_BIGNUM_TOO_LONG 113
+#define BN_R_PRIVATE_KEY_TOO_LARGE 114
+#define BN_R_BITS_TOO_SMALL 115
+#define BN_R_NEGATIVE_NUMBER 116
+
+#endif /* OPENSSL_HEADER_BN_H */
diff --git a/src/include/openssl/buf.h b/src/include/openssl/buf.h
new file mode 100644
index 0000000..0a0a9b8
--- /dev/null
+++ b/src/include/openssl/buf.h
@@ -0,0 +1,123 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 OPENSSL_HEADER_BUFFER_H
+#define OPENSSL_HEADER_BUFFER_H
+
+#include <openssl/base.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* Memory and string functions, see also mem.h. */
+
+
+/* BUF_MEM is a generic buffer object used by OpenSSL. */
+struct buf_mem_st {
+ size_t length; /* current number of bytes */
+ char *data;
+ size_t max; /* size of buffer */
+};
+
+/* BUF_MEM_new creates a new BUF_MEM which has no allocated data buffer. */
+OPENSSL_EXPORT BUF_MEM *BUF_MEM_new(void);
+
+/* BUF_MEM_free frees |buf->data| if needed and then frees |buf| itself. */
+OPENSSL_EXPORT void BUF_MEM_free(BUF_MEM *buf);
+
+/* BUF_MEM_grow ensures that |buf| has length |len| and allocates memory if
+ * needed. If the length of |buf| increased, the new bytes are filled with
+ * zeros. It returns the length of |buf|, or zero if there's an error. */
+OPENSSL_EXPORT size_t BUF_MEM_grow(BUF_MEM *buf, size_t len);
+
+/* BUF_MEM_grow_clean acts the same as |BUF_MEM_grow|, but clears the previous
+ * contents of memory if reallocing. */
+OPENSSL_EXPORT size_t BUF_MEM_grow_clean(BUF_MEM *str, size_t len);
+
+/* BUF_strdup returns an allocated, duplicate of |str|. */
+OPENSSL_EXPORT char *BUF_strdup(const char *str);
+
+/* BUF_strnlen returns the number of characters in |str|, excluding the NUL
+ * byte, but at most |max_len|. This function never reads more than |max_len|
+ * bytes from |str|. */
+OPENSSL_EXPORT size_t BUF_strnlen(const char *str, size_t max_len);
+
+/* BUF_strndup returns an allocated, duplicate of |str|, which is, at most,
+ * |size| bytes. The result is always NUL terminated. */
+OPENSSL_EXPORT char *BUF_strndup(const char *str, size_t size);
+
+/* BUF_memdup returns an allocated, duplicate of |size| bytes from |data|. */
+OPENSSL_EXPORT void *BUF_memdup(const void *data, size_t size);
+
+/* BUF_strlcpy acts like strlcpy(3). */
+OPENSSL_EXPORT size_t BUF_strlcpy(char *dst, const char *src, size_t dst_size);
+
+/* BUF_strlcat acts like strlcat(3). */
+OPENSSL_EXPORT size_t BUF_strlcat(char *dst, const char *src, size_t size);
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#define BUF_F_BUF_MEM_new 100
+#define BUF_F_buf_mem_grow 101
+#define BUF_F_BUF_strndup 102
+#define BUF_F_BUF_memdup 103
+
+#endif /* OPENSSL_HEADER_BUFFER_H */
diff --git a/src/include/openssl/bytestring.h b/src/include/openssl/bytestring.h
new file mode 100644
index 0000000..2bff3f5
--- /dev/null
+++ b/src/include/openssl/bytestring.h
@@ -0,0 +1,325 @@
+/* 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 <openssl/base.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* 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 */
+
+struct cbs_st {
+ const uint8_t *data;
+ size_t len;
+};
+
+/* CBS_init sets |cbs| to point to |data|. It does not take ownership of
+ * |data|. */
+OPENSSL_EXPORT 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. */
+OPENSSL_EXPORT int CBS_skip(CBS *cbs, size_t len);
+
+/* CBS_data returns a pointer to the contains of |cbs|. */
+OPENSSL_EXPORT const uint8_t *CBS_data(const CBS *cbs);
+
+/* CBS_len returns the number of bytes remaining in |cbs|. */
+OPENSSL_EXPORT size_t CBS_len(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
+ * OPENSSL_free. It returns one on success and zero on allocation failure. On
+ * success, |*out_ptr| should be freed with OPENSSL_free. If |cbs| is empty,
+ * |*out_ptr| will be NULL. */
+OPENSSL_EXPORT 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 OPENSSL_free. It returns one on success and zero on allocation
+ * failure. On success, |*out_ptr| should be freed with OPENSSL_free.
+ *
+ * NOTE: If |cbs| contains NUL bytes, the string will be truncated. Call
+ * |CBS_contains_zero_byte(cbs)| to check for NUL bytes. */
+OPENSSL_EXPORT int CBS_strdup(const CBS *cbs, char **out_ptr);
+
+/* CBS_contains_zero_byte returns one if the current contents of |cbs| contains
+ * a NUL byte and zero otherwise. */
+OPENSSL_EXPORT 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. */
+OPENSSL_EXPORT 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. */
+OPENSSL_EXPORT 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. */
+OPENSSL_EXPORT 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. */
+OPENSSL_EXPORT 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. */
+OPENSSL_EXPORT int CBS_get_u32(CBS *cbs, uint32_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. */
+OPENSSL_EXPORT 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. */
+OPENSSL_EXPORT 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. */
+OPENSSL_EXPORT 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. */
+OPENSSL_EXPORT int CBS_get_u24_length_prefixed(CBS *cbs, CBS *out);
+
+
+/* Parsing ASN.1 */
+
+#define CBS_ASN1_BOOLEAN 0x1
+#define CBS_ASN1_INTEGER 0x2
+#define CBS_ASN1_BITSTRING 0x3
+#define CBS_ASN1_OCTETSTRING 0x4
+#define CBS_ASN1_OBJECT 0x6
+#define CBS_ASN1_ENUMERATED 0xa
+#define CBS_ASN1_SEQUENCE (0x10 | CBS_ASN1_CONSTRUCTED)
+#define CBS_ASN1_SET (0x11 | CBS_ASN1_CONSTRUCTED)
+
+#define CBS_ASN1_CONSTRUCTED 0x20
+#define CBS_ASN1_CONTEXT_SPECIFIC 0x80
+
+/* 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 31 are not supported. */
+OPENSSL_EXPORT int CBS_get_asn1(CBS *cbs, CBS *out, unsigned tag_value);
+
+/* CBS_get_asn1_element acts like |CBS_get_asn1| but |out| will include the
+ * ASN.1 header bytes too. */
+OPENSSL_EXPORT int CBS_get_asn1_element(CBS *cbs, CBS *out, unsigned 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. */
+OPENSSL_EXPORT int CBS_peek_asn1_tag(const CBS *cbs, unsigned 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. If
+ * 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 31 are not supported. */
+OPENSSL_EXPORT int CBS_get_any_asn1_element(CBS *cbs, CBS *out,
+ unsigned *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. */
+OPENSSL_EXPORT 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. */
+OPENSSL_EXPORT int CBS_get_optional_asn1(CBS *cbs, CBS *out, int *out_present,
+ unsigned 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. */
+OPENSSL_EXPORT int CBS_get_optional_asn1_octet_string(CBS *cbs, CBS *out,
+ int *out_present,
+ unsigned 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. */
+OPENSSL_EXPORT int CBS_get_optional_asn1_uint64(CBS *cbs, uint64_t *out,
+ unsigned 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. */
+OPENSSL_EXPORT int CBS_get_optional_asn1_bool(CBS *cbs, int *out, unsigned 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;
+ size_t len; /* The number of valid bytes. */
+ size_t cap; /* The size of buf. */
+ char can_resize; /* One iff |buf| is owned by this object. If not then |buf|
+ cannot be resized. */
+};
+
+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_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. */
+OPENSSL_EXPORT 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. */
+OPENSSL_EXPORT 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. */
+OPENSSL_EXPORT 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 |OPENSSL_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. */
+OPENSSL_EXPORT 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. */
+OPENSSL_EXPORT int CBB_flush(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. */
+OPENSSL_EXPORT 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. */
+OPENSSL_EXPORT 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. */
+OPENSSL_EXPORT 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. It returns one on success or zero on error. */
+OPENSSL_EXPORT int CBB_add_asn1(CBB *cbb, CBB *out_contents, uint8_t tag);
+
+/* CBB_add_bytes appends |len| bytes from |data| to |cbb|. It returns one on
+ * success and zero otherwise. */
+OPENSSL_EXPORT 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. */
+OPENSSL_EXPORT 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. */
+OPENSSL_EXPORT int CBB_add_u8(CBB *cbb, uint8_t value);
+
+/* CBB_add_u8 appends a 16-bit, big-endian number from |value| to |cbb|. It
+ * returns one on success and zero otherwise. */
+OPENSSL_EXPORT int CBB_add_u16(CBB *cbb, uint16_t value);
+
+/* CBB_add_u24 appends a 24-bit, big-endian number from |value| to |cbb|. It
+ * returns one on success and zero otherwise. */
+OPENSSL_EXPORT int CBB_add_u24(CBB *cbb, uint32_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. */
+OPENSSL_EXPORT int CBB_add_asn1_uint64(CBB *cbb, uint64_t value);
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_BYTESTRING_H */
diff --git a/src/include/openssl/chacha.h b/src/include/openssl/chacha.h
new file mode 100644
index 0000000..ce53d49
--- /dev/null
+++ b/src/include/openssl/chacha.h
@@ -0,0 +1,37 @@
+/* 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_CHACHA_H
+#define OPENSSL_HEADER_CHACHA_H
+
+#include <openssl/base.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* CRYPTO_chacha_20 encrypts |in_len| bytes from |in| with the given key and
+ * nonce and writes the result to |out|, which may be equal to |in|. The
+ * initial block counter is specified by |counter|. */
+void CRYPTO_chacha_20(uint8_t *out, const uint8_t *in,
+ size_t in_len, const uint8_t key[32],
+ const uint8_t nonce[8], size_t counter);
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_CHACHA_H */
diff --git a/src/include/openssl/cipher.h b/src/include/openssl/cipher.h
new file mode 100644
index 0000000..0dfd97b
--- /dev/null
+++ b/src/include/openssl/cipher.h
@@ -0,0 +1,560 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 OPENSSL_HEADER_CIPHER_H
+#define OPENSSL_HEADER_CIPHER_H
+
+#include <openssl/base.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* Ciphers. */
+
+
+/* Cipher primitives.
+ *
+ * The following functions return |EVP_CIPHER| objects that implement the named
+ * cipher algorithm. */
+
+OPENSSL_EXPORT const EVP_CIPHER *EVP_rc4(void);
+
+OPENSSL_EXPORT const EVP_CIPHER *EVP_des_cbc(void);
+OPENSSL_EXPORT const EVP_CIPHER *EVP_des_ede3_cbc(void);
+
+OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_128_ecb(void);
+OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_128_cbc(void);
+OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_128_ctr(void);
+
+OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_256_ecb(void);
+OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_256_cbc(void);
+OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_256_ctr(void);
+
+/* Deprecated AES-GCM implementations that set |EVP_CIPH_FLAG_CUSTOM_CIPHER|.
+ * Use |EVP_aead_aes_128_gcm| and |EVP_aead_aes_256_gcm| instead. */
+OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_128_gcm(void);
+OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_256_gcm(void);
+
+/* EVP_enc_null returns a 'cipher' that passes plaintext through as
+ * ciphertext. */
+OPENSSL_EXPORT const EVP_CIPHER *EVP_enc_null(void);
+
+/* EVP_rc2_40_cbc returns a cipher that implements 40-bit RC2 in CBC mode. This
+ * is obviously very, very weak and is included only in order to read PKCS#12
+ * files, which often encrypt the certificate chain using this cipher. It is
+ * deliberately not exported. */
+const EVP_CIPHER *EVP_rc2_40_cbc(void);
+
+/* EVP_get_cipherbynid returns the cipher corresponding to the given NID, or
+ * NULL if no such cipher is known. */
+OPENSSL_EXPORT const EVP_CIPHER *EVP_get_cipherbynid(int nid);
+
+
+/* Cipher context allocation.
+ *
+ * An |EVP_CIPHER_CTX| represents the state of an encryption or decryption in
+ * progress. */
+
+/* EVP_CIPHER_CTX_init initialises an, already allocated, |EVP_CIPHER_CTX|. */
+OPENSSL_EXPORT void EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *ctx);
+
+/* EVP_CIPHER_CTX_new allocates a fresh |EVP_CIPHER_CTX|, calls
+ * |EVP_CIPHER_CTX_init| and returns it, or NULL on allocation failure. */
+OPENSSL_EXPORT EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void);
+
+/* EVP_CIPHER_CTX_cleanup frees any memory referenced by |ctx|. It returns one
+ * on success and zero otherwise. */
+OPENSSL_EXPORT int EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *ctx);
+
+/* EVP_CIPHER_CTX_free calls |EVP_CIPHER_CTX_cleanup| on |ctx| and then frees
+ * |ctx| itself. */
+OPENSSL_EXPORT void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx);
+
+/* EVP_CIPHER_CTX_copy sets |out| to be a duplicate of the current state of
+ * |in|. The |out| argument must have been previously initialised. */
+OPENSSL_EXPORT int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out,
+ const EVP_CIPHER_CTX *in);
+
+
+/* Cipher context configuration. */
+
+/* EVP_CipherInit_ex configures |ctx| for a fresh encryption (or decryption, if
+ * |enc| is zero) operation using |cipher|. If |ctx| has been previously
+ * configured with a cipher then |cipher|, |key| and |iv| may be |NULL| and
+ * |enc| may be -1 to reuse the previous values. The operation will use |key|
+ * as the key and |iv| as the IV (if any). These should have the correct
+ * lengths given by |EVP_CIPHER_key_length| and |EVP_CIPHER_iv_length|. It
+ * returns one on success and zero on error. */
+OPENSSL_EXPORT int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx,
+ const EVP_CIPHER *cipher, ENGINE *engine,
+ const uint8_t *key, const uint8_t *iv,
+ int enc);
+
+/* EVP_EncryptInit_ex calls |EVP_CipherInit_ex| with |enc| equal to one. */
+OPENSSL_EXPORT int EVP_EncryptInit_ex(EVP_CIPHER_CTX *ctx,
+ const EVP_CIPHER *cipher, ENGINE *impl,
+ const uint8_t *key, const uint8_t *iv);
+
+/* EVP_DecryptInit_ex calls |EVP_CipherInit_ex| with |enc| equal to zero. */
+OPENSSL_EXPORT int EVP_DecryptInit_ex(EVP_CIPHER_CTX *ctx,
+ const EVP_CIPHER *cipher, ENGINE *impl,
+ const uint8_t *key, const uint8_t *iv);
+
+
+/* Cipher operations. */
+
+/* EVP_EncryptUpdate encrypts |in_len| bytes from |in| to |out|. The number
+ * of output bytes may be up to |in_len| plus the block length minus one and
+ * |out| must have sufficient space. The number of bytes actually output is
+ * written to |*out_len|. It returns one on success and zero otherwise. */
+OPENSSL_EXPORT int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, uint8_t *out,
+ int *out_len, const uint8_t *in,
+ int in_len);
+
+/* EVP_EncryptFinal_ex writes at most a block of ciphertext to |out| and sets
+ * |*out_len| to the number of bytes written. If padding is enabled (the
+ * default) then standard padding is applied to create the final block. If
+ * padding is disabled (with |EVP_CIPHER_CTX_set_padding|) then any partial
+ * block remaining will cause an error. The function returns one on success and
+ * zero otherwise. */
+OPENSSL_EXPORT int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, uint8_t *out,
+ int *out_len);
+
+/* EVP_DecryptUpdate decrypts |in_len| bytes from |in| to |out|. The number of
+ * output bytes may be up to |in_len| plus the block length minus one and |out|
+ * must have sufficient space. The number of bytes actually output is written
+ * to |*out_len|. It returns one on success and zero otherwise. */
+OPENSSL_EXPORT int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, uint8_t *out,
+ int *out_len, const uint8_t *in,
+ int in_len);
+
+/* EVP_DecryptFinal_ex writes at most a block of ciphertext to |out| and sets
+ * |*out_len| to the number of bytes written. If padding is enabled (the
+ * default) then padding is removed from the final block.
+ *
+ * WARNING: it is unsafe to call this function with unauthenticted
+ * ciphertext if padding is enabled. */
+OPENSSL_EXPORT int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ int *out_len);
+
+/* EVP_Cipher performs a one-shot encryption/decryption operation. No partial
+ * blocks are maintained between calls. However, any internal cipher state is
+ * still updated. For CBC-mode ciphers, the IV is updated to the final
+ * ciphertext block. For stream ciphers, the stream is advanced past the bytes
+ * used. It returns one on success and zero otherwise, unless |EVP_CIPHER_flags|
+ * has |EVP_CIPH_FLAG_CUSTOM_CIPHER| set. Then it returns the number of bytes
+ * written or -1 on error.
+ *
+ * WARNING: this differs from the usual return value convention when using
+ * |EVP_CIPH_FLAG_CUSTOM_CIPHER|.
+ *
+ * TODO(davidben): The normal ciphers currently never fail, even if, e.g.,
+ * |in_len| is not a multiple of the block size for CBC-mode decryption. The
+ * input just gets rounded up while the output gets truncated. This should
+ * either be officially documented or fail. */
+OPENSSL_EXPORT int EVP_Cipher(EVP_CIPHER_CTX *ctx, uint8_t *out,
+ const uint8_t *in, size_t in_len);
+
+/* EVP_CipherUpdate calls either |EVP_EncryptUpdate| or |EVP_DecryptUpdate|
+ * depending on how |ctx| has been setup. */
+OPENSSL_EXPORT int EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, uint8_t *out,
+ int *out_len, const uint8_t *in,
+ int in_len);
+
+/* EVP_CipherFinal_ex calls either |EVP_EncryptFinal_ex| or
+ * |EVP_DecryptFinal_ex| depending on how |ctx| has been setup. */
+OPENSSL_EXPORT int EVP_CipherFinal_ex(EVP_CIPHER_CTX *ctx, uint8_t *out,
+ int *out_len);
+
+
+/* Cipher context accessors. */
+
+/* EVP_CIPHER_CTX_cipher returns the |EVP_CIPHER| underlying |ctx|, or NULL if
+ * none has been set. */
+OPENSSL_EXPORT const EVP_CIPHER *EVP_CIPHER_CTX_cipher(
+ const EVP_CIPHER_CTX *ctx);
+
+/* EVP_CIPHER_CTX_nid returns a NID identifying the |EVP_CIPHER| underlying
+ * |ctx| (e.g. |NID_rc4|). It will crash if no cipher has been configured. */
+OPENSSL_EXPORT int EVP_CIPHER_CTX_nid(const EVP_CIPHER_CTX *ctx);
+
+/* EVP_CIPHER_CTX_block_size returns the block size, in bytes, of the cipher
+ * underlying |ctx|, or one if the cipher is a stream cipher. It will crash if
+ * no cipher has been configured. */
+OPENSSL_EXPORT unsigned EVP_CIPHER_CTX_block_size(const EVP_CIPHER_CTX *ctx);
+
+/* EVP_CIPHER_CTX_key_length returns the key size, in bytes, of the cipher
+ * underlying |ctx| or zero if no cipher has been configured. */
+OPENSSL_EXPORT unsigned EVP_CIPHER_CTX_key_length(const EVP_CIPHER_CTX *ctx);
+
+/* EVP_CIPHER_CTX_iv_length returns the IV size, in bytes, of the cipher
+ * underlying |ctx|. It will crash if no cipher has been configured. */
+OPENSSL_EXPORT unsigned EVP_CIPHER_CTX_iv_length(const EVP_CIPHER_CTX *ctx);
+
+/* EVP_CIPHER_CTX_get_app_data returns the opaque, application data pointer for
+ * |ctx|, or NULL if none has been set. */
+OPENSSL_EXPORT void *EVP_CIPHER_CTX_get_app_data(const EVP_CIPHER_CTX *ctx);
+
+/* EVP_CIPHER_CTX_set_app_data sets the opaque, application data pointer for
+ * |ctx| to |data|. */
+OPENSSL_EXPORT void EVP_CIPHER_CTX_set_app_data(EVP_CIPHER_CTX *ctx,
+ void *data);
+
+/* EVP_CIPHER_CTX_flags returns a value which is the OR of zero or more
+ * |EVP_CIPH_*| flags. It will crash if no cipher has been configured. */
+OPENSSL_EXPORT uint32_t EVP_CIPHER_CTX_flags(const EVP_CIPHER_CTX *ctx);
+
+/* EVP_CIPHER_CTX_mode returns one of the |EVP_CIPH_*| cipher mode values
+ * enumerated below. It will crash if no cipher has been configured. */
+OPENSSL_EXPORT uint32_t EVP_CIPHER_CTX_mode(const EVP_CIPHER_CTX *ctx);
+
+/* EVP_CIPHER_CTX_ctrl is an |ioctl| like function. The |command| argument
+ * should be one of the |EVP_CTRL_*| values. The |arg| and |ptr| arguments are
+ * specific to the command in question. */
+OPENSSL_EXPORT int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int command,
+ int arg, void *ptr);
+
+/* EVP_CIPHER_CTX_set_padding sets whether padding is enabled for |ctx| and
+ * returns one. Pass a non-zero |pad| to enable padding (the default) or zero
+ * to disable. */
+OPENSSL_EXPORT int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *ctx, int pad);
+
+/* EVP_CIPHER_CTX_set_key_length sets the key length for |ctx|. This is only
+ * valid for ciphers that can take a variable length key. It returns one on
+ * success and zero on error. */
+OPENSSL_EXPORT int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *ctx, unsigned key_len);
+
+
+/* Cipher accessors. */
+
+/* EVP_CIPHER_nid returns a NID identifing |cipher|. (For example,
+ * |NID_rc4|.) */
+OPENSSL_EXPORT int EVP_CIPHER_nid(const EVP_CIPHER *cipher);
+
+/* EVP_CIPHER_name returns the short name for |cipher| or NULL if no name is
+ * known. */
+OPENSSL_EXPORT const char *EVP_CIPHER_name(const EVP_CIPHER *cipher);
+
+/* EVP_CIPHER_block_size returns the block size, in bytes, for |cipher|, or one
+ * if |cipher| is a stream cipher. */
+OPENSSL_EXPORT unsigned EVP_CIPHER_block_size(const EVP_CIPHER *cipher);
+
+/* EVP_CIPHER_key_length returns the key size, in bytes, for |cipher|. If
+ * |cipher| can take a variable key length then this function returns the
+ * default key length and |EVP_CIPHER_flags| will return a value with
+ * |EVP_CIPH_VARIABLE_LENGTH| set. */
+OPENSSL_EXPORT unsigned EVP_CIPHER_key_length(const EVP_CIPHER *cipher);
+
+/* EVP_CIPHER_iv_length returns the IV size, in bytes, of |cipher|, or zero if
+ * |cipher| doesn't take an IV. */
+OPENSSL_EXPORT unsigned EVP_CIPHER_iv_length(const EVP_CIPHER *cipher);
+
+/* EVP_CIPHER_flags returns a value which is the OR of zero or more
+ * |EVP_CIPH_*| flags. */
+OPENSSL_EXPORT uint32_t EVP_CIPHER_flags(const EVP_CIPHER *cipher);
+
+/* EVP_CIPHER_mode returns one of the cipher mode values enumerated below. */
+OPENSSL_EXPORT uint32_t EVP_CIPHER_mode(const EVP_CIPHER *cipher);
+
+
+/* Key derivation. */
+
+/* EVP_BytesToKey generates a key and IV for the cipher |type| by iterating
+ * |md| |count| times using |data| and |salt|. On entry, the |key| and |iv|
+ * buffers must have enough space to hold a key and IV for |type|. It returns
+ * the length of the key on success or zero on error. */
+OPENSSL_EXPORT int EVP_BytesToKey(const EVP_CIPHER *type, const EVP_MD *md,
+ const uint8_t *salt, const uint8_t *data,
+ size_t data_len, unsigned count, uint8_t *key,
+ uint8_t *iv);
+
+
+/* Cipher modes (for |EVP_CIPHER_mode|). */
+
+#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
+
+
+/* Cipher flags (for |EVP_CIPHER_flags|). */
+
+/* EVP_CIPH_VARIABLE_LENGTH indicates that the cipher takes a variable length
+ * key. */
+#define EVP_CIPH_VARIABLE_LENGTH 0x40
+
+/* EVP_CIPH_ALWAYS_CALL_INIT indicates that the |init| function for the cipher
+ * should always be called when initialising a new operation, even if the key
+ * is NULL to indicate that the same key is being used. */
+#define EVP_CIPH_ALWAYS_CALL_INIT 0x80
+
+/* EVP_CIPH_CUSTOM_IV indicates that the cipher manages the IV itself rather
+ * than keeping it in the |iv| member of |EVP_CIPHER_CTX|. */
+#define EVP_CIPH_CUSTOM_IV 0x100
+
+/* EVP_CIPH_CTRL_INIT indicates that EVP_CTRL_INIT should be used when
+ * initialising an |EVP_CIPHER_CTX|. */
+#define EVP_CIPH_CTRL_INIT 0x200
+
+/* EVP_CIPH_FLAG_CUSTOM_CIPHER indicates that the cipher manages blocking
+ * itself. This causes EVP_(En|De)crypt_ex to be simple wrapper functions. */
+#define EVP_CIPH_FLAG_CUSTOM_CIPHER 0x400
+
+/* EVP_CIPH_FLAG_AEAD_CIPHER specifies that the cipher is an AEAD. This is an
+ * older version of the proper AEAD interface. See aead.h for the current
+ * one. */
+#define EVP_CIPH_FLAG_AEAD_CIPHER 0x800
+
+/* EVP_CIPH_CUSTOM_COPY indicates that the |ctrl| callback should be called
+ * with |EVP_CTRL_COPY| at the end of normal |EVP_CIPHER_CTX_copy|
+ * processing. */
+#define EVP_CIPH_CUSTOM_COPY 0x1000
+
+
+/* Deprecated functions */
+
+/* EVP_CipherInit acts like EVP_CipherInit_ex except that |EVP_CIPHER_CTX_init|
+ * is called on |cipher| first, if |cipher| is not NULL. */
+OPENSSL_EXPORT int EVP_CipherInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
+ const uint8_t *key, const uint8_t *iv,
+ int enc);
+
+/* EVP_EncryptInit calls |EVP_CipherInit| with |enc| equal to one. */
+OPENSSL_EXPORT int EVP_EncryptInit(EVP_CIPHER_CTX *ctx,
+ const EVP_CIPHER *cipher, const uint8_t *key,
+ const uint8_t *iv);
+
+/* EVP_DecryptInit calls |EVP_CipherInit| with |enc| equal to zero. */
+OPENSSL_EXPORT int EVP_DecryptInit(EVP_CIPHER_CTX *ctx,
+ const EVP_CIPHER *cipher, const uint8_t *key,
+ const uint8_t *iv);
+
+/* EVP_add_cipher_alias does nothing and returns one. */
+OPENSSL_EXPORT int EVP_add_cipher_alias(const char *a, const char *b);
+
+/* EVP_get_cipherbyname returns an |EVP_CIPHER| given a human readable name in
+ * |name|, or NULL if the name is unknown. */
+OPENSSL_EXPORT const EVP_CIPHER *EVP_get_cipherbyname(const char *name);
+
+
+/* Private functions. */
+
+/* EVP_CIPH_NO_PADDING disables padding in block ciphers. */
+#define EVP_CIPH_NO_PADDING 0x800
+
+/* EVP_CIPHER_CTX_ctrl commands. */
+#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_GCM_SET_IVLEN 0x9
+#define EVP_CTRL_GCM_GET_TAG 0x10
+#define EVP_CTRL_GCM_SET_TAG 0x11
+#define EVP_CTRL_GCM_SET_IV_FIXED 0x12
+#define EVP_CTRL_GCM_IV_GEN 0x13
+#define EVP_CTRL_AEAD_SET_MAC_KEY 0x17
+/* Set the GCM invocation field, decrypt only */
+#define EVP_CTRL_GCM_SET_IV_INV 0x18
+
+/* 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
+
+#define EVP_MAX_KEY_LENGTH 64
+#define EVP_MAX_IV_LENGTH 16
+#define EVP_MAX_BLOCK_LENGTH 32
+
+struct evp_cipher_ctx_st {
+ /* cipher contains the underlying cipher for this context. */
+ const EVP_CIPHER *cipher;
+
+ /* app_data is a pointer to opaque, user data. */
+ void *app_data; /* application stuff */
+
+ /* cipher_data points to the |cipher| specific state. */
+ void *cipher_data;
+
+ /* key_len contains the length of the key, which may differ from
+ * |cipher->key_len| if the cipher can take a variable key length. */
+ unsigned key_len;
+
+ /* encrypt is one if encrypting and zero if decrypting. */
+ int encrypt;
+
+ /* flags contains the OR of zero or more |EVP_CIPH_*| flags, above. */
+ uint32_t flags;
+
+ /* oiv contains the original IV value. */
+ uint8_t oiv[EVP_MAX_IV_LENGTH];
+
+ /* iv contains the current IV value, which may have been updated. */
+ uint8_t iv[EVP_MAX_IV_LENGTH];
+
+ /* buf contains a partial block which is used by, for example, CTR mode to
+ * store unused keystream bytes. */
+ uint8_t buf[EVP_MAX_BLOCK_LENGTH];
+
+ /* buf_len contains the number of bytes of a partial block contained in
+ * |buf|. */
+ int buf_len;
+
+ /* num contains the number of bytes of |iv| which are valid for modes that
+ * manage partial blocks themselves. */
+ int num;
+
+ /* final_used is non-zero if the |final| buffer contains plaintext. */
+ int final_used;
+
+ /* block_mask contains |cipher->block_size| minus one. (The block size
+ * assumed to be a power of two.) */
+ int block_mask;
+
+ uint8_t final[EVP_MAX_BLOCK_LENGTH]; /* possible final block */
+} /* EVP_CIPHER_CTX */;
+
+typedef struct evp_cipher_info_st {
+ const EVP_CIPHER *cipher;
+ unsigned char iv[EVP_MAX_IV_LENGTH];
+} EVP_CIPHER_INFO;
+
+
+/* Android compatibility section.
+ *
+ * These functions are declared, temporarily, for Android because
+ * wpa_supplicant will take a little time to sync with upstream. Outside of
+ * Android they'll have no definition. */
+
+OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_192_ecb(void);
+OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_192_cbc(void);
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#define CIPHER_F_EVP_CipherInit_ex 100
+#define CIPHER_F_EVP_EncryptFinal_ex 101
+#define CIPHER_F_EVP_DecryptFinal_ex 102
+#define CIPHER_F_EVP_CIPHER_CTX_ctrl 103
+#define CIPHER_F_aes_init_key 104
+#define CIPHER_F_aesni_init_key 105
+#define CIPHER_F_EVP_CIPHER_CTX_copy 106
+#define CIPHER_F_EVP_AEAD_CTX_open 107
+#define CIPHER_F_EVP_AEAD_CTX_init 108
+#define CIPHER_F_EVP_AEAD_CTX_seal 109
+#define CIPHER_F_aead_aes_gcm_seal 110
+#define CIPHER_F_aead_aes_gcm_open 111
+#define CIPHER_F_aead_aes_gcm_init 112
+#define CIPHER_F_aead_chacha20_poly1305_init 113
+#define CIPHER_F_aead_chacha20_poly1305_open 114
+#define CIPHER_F_aead_chacha20_poly1305_seal 115
+#define CIPHER_F_aead_rc4_md5_tls_init 116
+#define CIPHER_F_aead_rc4_md5_tls_seal 117
+#define CIPHER_F_aead_rc4_md5_tls_open 118
+#define CIPHER_F_aead_aes_key_wrap_seal 119
+#define CIPHER_F_aead_aes_key_wrap_init 120
+#define CIPHER_F_aead_aes_key_wrap_open 121
+#define CIPHER_F_EVP_CIPHER_CTX_set_key_length 122
+#define CIPHER_F_aead_tls_init 123
+#define CIPHER_F_aead_tls_open 124
+#define CIPHER_F_aead_tls_seal 125
+#define CIPHER_F_aead_tls_ensure_cipher_init 126
+#define CIPHER_F_aead_ssl3_open 127
+#define CIPHER_F_aead_ssl3_seal 128
+#define CIPHER_F_aead_ssl3_init 129
+#define CIPHER_F_aead_ssl3_ensure_cipher_init 130
+#define CIPHER_R_WRAP_MODE_NOT_ALLOWED 100
+#define CIPHER_R_AES_KEY_SETUP_FAILED 101
+#define CIPHER_R_INPUT_NOT_INITIALIZED 102
+#define CIPHER_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH 103
+#define CIPHER_R_INITIALIZATION_ERROR 104
+#define CIPHER_R_CTRL_NOT_IMPLEMENTED 105
+#define CIPHER_R_NO_CIPHER_SET 106
+#define CIPHER_R_BAD_DECRYPT 107
+#define CIPHER_R_WRONG_FINAL_BLOCK_LENGTH 108
+#define CIPHER_R_CTRL_OPERATION_NOT_IMPLEMENTED 109
+#define CIPHER_R_TAG_TOO_LARGE 110
+#define CIPHER_R_BAD_KEY_LENGTH 111
+#define CIPHER_R_BUFFER_TOO_SMALL 112
+#define CIPHER_R_OUTPUT_ALIASES_INPUT 113
+#define CIPHER_R_UNSUPPORTED_KEY_SIZE 114
+#define CIPHER_R_TOO_LARGE 115
+#define CIPHER_R_IV_TOO_LARGE 116
+#define CIPHER_R_INVALID_AD_SIZE 117
+#define CIPHER_R_INVALID_AD 118
+#define CIPHER_R_UNSUPPORTED_TAG_SIZE 119
+#define CIPHER_R_UNSUPPORTED_INPUT_SIZE 120
+#define CIPHER_R_UNSUPPORTED_AD_SIZE 121
+#define CIPHER_R_UNSUPPORTED_NONCE_SIZE 122
+#define CIPHER_R_INVALID_KEY_LENGTH 123
+#define CIPHER_R_INVALID_OPERATION 124
+#define CIPHER_R_INVALID_NONCE_SIZE 125
+
+#endif /* OPENSSL_HEADER_CIPHER_H */
diff --git a/src/include/openssl/conf.h b/src/include/openssl/conf.h
new file mode 100644
index 0000000..0918c0c
--- /dev/null
+++ b/src/include/openssl/conf.h
@@ -0,0 +1,144 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 OPENSSL_HEADER_CONF_H
+#define OPENSSL_HEADER_CONF_H
+
+#include <openssl/base.h>
+
+#include <openssl/stack.h>
+#include <openssl/lhash.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* Config files look like:
+ *
+ * # Comment
+ *
+ * # This key is in the default section.
+ * key=value
+ *
+ * [section_name]
+ * key2=value2
+ *
+ * Config files are representated by a |CONF|. */
+
+typedef struct {
+ char *section;
+ char *name;
+ char *value;
+} CONF_VALUE;
+
+struct conf_st {
+ LHASH_OF(CONF_VALUE) *data;
+};
+
+
+/* NCONF_new returns a fresh, empty |CONF|, or NULL on error. */
+CONF *NCONF_new(void);
+
+/* NCONF_free frees all the data owned by |conf| and then |conf| itself. */
+void NCONF_free(CONF *conf);
+
+/* NCONF_load parses the file named |filename| and adds the values found to
+ * |conf|. It returns one on success and zero on error. In the event of an
+ * error, if |out_error_line| is not NULL, |*out_error_line| is set to the
+ * number of the line that contained the error. */
+int NCONF_load(CONF *conf, const char *filename, long *out_error_line);
+
+/* NCONF_get_section returns a stack of values for a given section in |conf|.
+ * If |section| is NULL, the default section is returned. It returns NULL on
+ * error. */
+STACK_OF(CONF_VALUE) *NCONF_get_section(const CONF *conf, const char *section);
+
+/* NCONF_get_string returns the value of the key |name|, in section |section|.
+ * The |section| argument may be NULL to indicate the default section. It
+ * returns the value or NULL on error. */
+const char *NCONF_get_string(const CONF *conf, const char *section,
+ const char *name);
+
+
+/* Utility functions */
+
+/* CONF_parse_list takes a list separated by 'sep' and calls |list_cb| 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. If |list_cb| returns <= 0, then the iteration is halted and that
+ * value is returned immediately. Otherwise it returns one. Note that |list_cb|
+ * may be called on an empty member. */
+int CONF_parse_list(const char *list, char sep, int remove_whitespace,
+ int (*list_cb)(const char *elem, int len, void *usr),
+ void *arg);
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#define CONF_F_CONF_parse_list 100
+#define CONF_F_str_copy 101
+#define CONF_F_def_load_bio 102
+#define CONF_F_NCONF_load 103
+#define CONF_R_MISSING_EQUAL_SIGN 100
+#define CONF_R_LIST_CANNOT_BE_NULL 101
+#define CONF_R_NO_CLOSE_BRACE 102
+#define CONF_R_VARIABLE_HAS_NO_VALUE 103
+#define CONF_R_UNABLE_TO_CREATE_NEW_SECTION 104
+#define CONF_R_MISSING_CLOSE_SQUARE_BRACKET 105
+
+#endif /* OPENSSL_HEADER_THREAD_H */
diff --git a/src/include/openssl/cpu.h b/src/include/openssl/cpu.h
new file mode 100644
index 0000000..79441ae
--- /dev/null
+++ b/src/include/openssl/cpu.h
@@ -0,0 +1,122 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com). */
+
+#ifndef OPENSSL_HEADER_CPU_H
+#define OPENSSL_HEADER_CPU_H
+
+#include <openssl/base.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* Runtime CPU feature support */
+
+
+#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64)
+/* OPENSSL_ia32cap_P contains the Intel CPUID bits when running on an x86 or
+ * x86-64 system.
+ *
+ * Index 0:
+ * EDX for CPUID where EAX = 1
+ * Bit 30 is used to indicate an Intel CPU
+ * Bit 20 is used to indicate RC4_CHAR
+ * Index 1:
+ * ECX for CPUID where EAX = 1
+ * Index 2:
+ * EBX for CPUID where EAX = 7
+ *
+ * Note: the CPUID bits are pre-adjusted for the OSXSAVE bit and the YMM and XMM
+ * bits in XCR0, so it is not necessary to check those. */
+extern uint32_t OPENSSL_ia32cap_P[4];
+#endif
+
+#if defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)
+/* CRYPTO_is_NEON_capable returns true if the current CPU has a NEON unit. Note
+ * that |OPENSSL_armcap_P| also exists and contains the same information in a
+ * form that's easier for assembly to use. */
+OPENSSL_EXPORT char CRYPTO_is_NEON_capable(void);
+
+/* CRYPTO_set_NEON_capable sets the return value of |CRYPTO_is_NEON_capable|.
+ * By default, unless the code was compiled with |-mfpu=neon|, NEON is assumed
+ * not to be present. It is not autodetected. Calling this with a zero
+ * argument also causes |CRYPTO_is_NEON_functional| to return false. */
+OPENSSL_EXPORT void CRYPTO_set_NEON_capable(char neon_capable);
+
+/* CRYPTO_is_NEON_functional returns true if the current CPU has a /working/
+ * NEON unit. Some phones have a NEON unit, but the Poly1305 NEON code causes
+ * it to fail. See https://code.google.com/p/chromium/issues/detail?id=341598 */
+OPENSSL_EXPORT char CRYPTO_is_NEON_functional(void);
+
+/* CRYPTO_set_NEON_functional sets the "NEON functional" flag. For
+ * |CRYPTO_is_NEON_functional| to return true, both this flag and the NEON flag
+ * must be true. By default NEON is assumed to be functional if the code was
+ * compiled with |-mfpu=neon| or if |CRYPTO_set_NEON_capable| has been called
+ * with a non-zero argument. */
+OPENSSL_EXPORT void CRYPTO_set_NEON_functional(char neon_functional);
+#endif /* OPENSSL_ARM */
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_CPU_H */
diff --git a/src/include/openssl/crypto.h b/src/include/openssl/crypto.h
new file mode 100644
index 0000000..112431e
--- /dev/null
+++ b/src/include/openssl/crypto.h
@@ -0,0 +1,45 @@
+/* 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_CRYPTO_H
+#define OPENSSL_HEADER_CRYPTO_H
+
+#include <openssl/base.h>
+
+#include <openssl/mem.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* crypto.h contains functions for initializing the crypto library. */
+
+
+/* CRYPTO_library_init initializes the crypto library. It must be called if the
+ * library is built with BORINGSSL_NO_STATIC_INITIALIZER. Otherwise, it does
+ * nothing and a static initializer is used instead. */
+OPENSSL_EXPORT void CRYPTO_library_init(void);
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#define CRYPTO_F_CRYPTO_set_ex_data 100
+#define CRYPTO_F_get_class 101
+#define CRYPTO_F_get_new_index 102
+#define CRYPTO_F_get_func_pointers 103
+
+#endif /* OPENSSL_HEADER_CRYPTO_H */
diff --git a/src/include/openssl/des.h b/src/include/openssl/des.h
new file mode 100644
index 0000000..1f0dbad
--- /dev/null
+++ b/src/include/openssl/des.h
@@ -0,0 +1,126 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 OPENSSL_HEADER_DES_H
+#define OPENSSL_HEADER_DES_H
+
+#include <openssl/base.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* DES. */
+
+
+typedef struct DES_cblock_st {
+ uint8_t bytes[8];
+} DES_cblock;
+
+typedef struct DES_ks {
+ union {
+ DES_cblock cblock;
+ /* make sure things are correct size on machines with
+ * 8 byte longs */
+ uint32_t 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
+
+/* DES_set_key performs a key schedule and initialises |schedule| with |key|. */
+OPENSSL_EXPORT void DES_set_key(const DES_cblock *key,
+ DES_key_schedule *schedule);
+
+/* DES_ecb_encrypt encrypts (or decrypts, if |is_encrypt| is |DES_DECRYPT|) a
+ * single DES block (8 bytes) from in to out, using the key configured in
+ * |schedule|. */
+OPENSSL_EXPORT void DES_ecb_encrypt(const DES_cblock *in, DES_cblock *out,
+ const DES_key_schedule *schedule,
+ int is_encrypt);
+
+/* DES_ncbc_encrypt encrypts (or decrypts, if |enc| is |DES_DECRYPT|) |len|
+ * bytes from |in| to |out| with DES in CBC mode. */
+OPENSSL_EXPORT void DES_ncbc_encrypt(const uint8_t *in, uint8_t *out,
+ size_t len,
+ const DES_key_schedule *schedule,
+ DES_cblock *ivec, int enc);
+
+/* DES_ede3_cbc_encrypt encrypts (or decrypts, if |enc| is |DES_DECRYPT|) |len|
+ * bytes from |in| to |out| with 3DES in CBC mode. 3DES uses three keys, thus
+ * the function takes three different |DES_key_schedule|s. */
+OPENSSL_EXPORT void DES_ede3_cbc_encrypt(const uint8_t *in, uint8_t *out,
+ size_t len,
+ const DES_key_schedule *ks1,
+ const DES_key_schedule *ks2,
+ const DES_key_schedule *ks3,
+ DES_cblock *ivec, int enc);
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_DES_H */
diff --git a/src/include/openssl/dh.h b/src/include/openssl/dh.h
new file mode 100644
index 0000000..9d8bda2
--- /dev/null
+++ b/src/include/openssl/dh.h
@@ -0,0 +1,263 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 OPENSSL_HEADER_DH_H
+#define OPENSSL_HEADER_DH_H
+
+#include <openssl/base.h>
+
+#include <openssl/engine.h>
+#include <openssl/ex_data.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* DH contains functions for performing Diffie-Hellman key agreement in
+ * multiplicative groups. */
+
+
+/* Allocation and destruction. */
+
+/* DH_new returns a new, empty DH object or NULL on error. */
+OPENSSL_EXPORT DH *DH_new(void);
+
+/* DH_new_method acts the same as |DH_new| but takes an explicit |ENGINE|. */
+OPENSSL_EXPORT DH *DH_new_method(const ENGINE *engine);
+
+/* DH_free decrements the reference count of |dh| and frees it if the reference
+ * count drops to zero. */
+OPENSSL_EXPORT void DH_free(DH *dh);
+
+/* DH_up_ref increments the reference count of |dh|. */
+OPENSSL_EXPORT int DH_up_ref(DH *dh);
+
+
+/* Standard parameters.
+ *
+ * These functions return new DH objects with standard parameters configured
+ * that use the given ENGINE, which may be NULL. They return NULL on allocation
+ * failure. */
+
+/* These parameters are taken from RFC 5114. */
+
+OPENSSL_EXPORT DH *DH_get_1024_160(const ENGINE *engine);
+OPENSSL_EXPORT DH *DH_get_2048_224(const ENGINE *engine);
+OPENSSL_EXPORT DH *DH_get_2048_256(const ENGINE *engine);
+
+
+/* Parameter generation. */
+
+#define DH_GENERATOR_2 2
+#define DH_GENERATOR_5 5
+
+/* DH_generate_parameters_ex generates a suitable Diffie-Hellman group with a
+ * prime that is |prime_bits| long and stores it in |dh|. The generator of the
+ * group will be |generator|, which should be |DH_GENERATOR_2| unless there's a
+ * good reason to use a different value. The |cb| argument contains a callback
+ * function that will be called during the generation. See the documentation in
+ * |bn.h| about this. In addition to the callback invocations from |BN|, |cb|
+ * will also be called with |event| equal to three when the generation is
+ * complete. */
+OPENSSL_EXPORT int DH_generate_parameters_ex(DH *dh, int prime_bits,
+ int generator, BN_GENCB *cb);
+
+
+/* Diffie-Hellman operations. */
+
+/* DH_generate_key generates a new, random, private key and stores it in
+ * |dh|. It returns one on success and zero on error. */
+OPENSSL_EXPORT int DH_generate_key(DH *dh);
+
+/* DH_compute_key calculates the shared key between |dh| and |peers_key| and
+ * writes it as a big-endian integer into |out|, which must have |DH_size|
+ * bytes of space. It returns the number of bytes written, or a negative number
+ * on error. */
+OPENSSL_EXPORT int DH_compute_key(uint8_t *out, const BIGNUM *peers_key,
+ DH *dh);
+
+
+/* Utility functions. */
+
+/* DH_size returns the number of bytes in the DH group's prime. */
+OPENSSL_EXPORT int DH_size(const DH *dh);
+
+#define DH_CHECK_P_NOT_PRIME 0x01
+#define DH_CHECK_P_NOT_SAFE_PRIME 0x02
+#define DH_CHECK_UNABLE_TO_CHECK_GENERATOR 0x04
+#define DH_CHECK_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 checks the suitability of |dh| as a Diffie-Hellman group. and sets
+ * |DH_CHECK_*| flags in |*out_flags| if it finds any errors. It returns one if
+ * |*out_flags| was successfully set and zero on error.
+ *
+ * Note: these checks may be quite computationally expensive. */
+OPENSSL_EXPORT int DH_check(const DH *dh, int *out_flags);
+
+#define DH_CHECK_PUBKEY_TOO_SMALL 1
+#define DH_CHECK_PUBKEY_TOO_LARGE 2
+
+/* DH_check_pub_key checks the suitability of |pub_key| as a public key for the
+ * DH group in |dh| and sets |DH_CHECK_PUBKEY_*| flags in |*out_flags| if it
+ * finds any errors. It returns one if |*out_flags| was successfully set and
+ * zero on error. */
+OPENSSL_EXPORT int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key,
+ int *out_flags);
+
+/* DHparams_dup allocates a fresh |DH| and copies the parameters from |dh| into
+ * it. It returns the new |DH| or NULL on error. */
+OPENSSL_EXPORT DH *DHparams_dup(const DH *dh);
+
+
+/* ASN.1 functions. */
+
+/* d2i_DHparams parses an ASN.1, DER encoded Diffie-Hellman parameters
+ * structure from |len| bytes at |*inp|. If |ret| is not NULL then, on exit, a
+ * pointer to the result is in |*ret|. If |*ret| is already non-NULL on entry
+ * then the result is written directly into |*ret|, otherwise a fresh |DH| is
+ * allocated. On successful exit, |*inp| is advanced past the DER structure. It
+ * returns the result or NULL on error. */
+OPENSSL_EXPORT DH *d2i_DHparams(DH **ret, const unsigned char **inp, long len);
+
+/* i2d_DHparams marshals |in| to an ASN.1, DER structure. If |outp| is not NULL
+ * then the result is written to |*outp| and |*outp| is advanced just past the
+ * output. It returns the number of bytes in the result, whether written or
+ * not, or a negative value on error. */
+OPENSSL_EXPORT int i2d_DHparams(const DH *in, unsigned char **outp);
+
+
+/* ex_data functions.
+ *
+ * These functions are wrappers. See |ex_data.h| for details. */
+
+OPENSSL_EXPORT 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);
+OPENSSL_EXPORT int DH_set_ex_data(DH *d, int idx, void *arg);
+OPENSSL_EXPORT void *DH_get_ex_data(DH *d, int idx);
+
+
+/* dh_method contains function pointers to override the implementation of DH.
+ * See |engine.h| for details. */
+struct dh_method {
+ struct openssl_method_common_st common;
+
+ /* app_data is an opaque pointer for the method to use. */
+ void *app_data;
+
+ /* init is called just before the return of |DH_new_method|. It returns one
+ * on success or zero on error. */
+ int (*init)(DH *dh);
+
+ /* finish is called before |dh| is destructed. */
+ void (*finish)(DH *dh);
+
+ /* generate_parameters is called by |DH_generate_parameters_ex|. */
+ int (*generate_parameters)(DH *dh, int prime_bits, int generator,
+ BN_GENCB *cb);
+
+ /* generate_parameters is called by |DH_generate_key|. */
+ int (*generate_key)(DH *dh);
+
+ /* compute_key is called by |DH_compute_key|. */
+ int (*compute_key)(DH *dh, uint8_t *out, const BIGNUM *pub_key);
+};
+
+struct dh_st {
+ DH_METHOD *meth;
+
+ BIGNUM *p;
+ BIGNUM *g;
+ BIGNUM *pub_key; /* g^x */
+ BIGNUM *priv_key; /* x */
+
+ /* priv_length contains the length, in bits, of the private value. If zero,
+ * the private value will be the same length as |p|. */
+ unsigned priv_length;
+ 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 flags;
+ int references;
+ CRYPTO_EX_DATA ex_data;
+};
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#define DH_F_generate_parameters 100
+#define DH_F_generate_key 101
+#define DH_F_compute_key 102
+#define DH_F_DH_new_method 103
+#define DH_R_INVALID_PUBKEY 100
+#define DH_R_BAD_GENERATOR 101
+#define DH_R_MODULUS_TOO_LARGE 102
+#define DH_R_NO_PRIVATE_VALUE 103
+
+#endif /* OPENSSL_HEADER_DH_H */
diff --git a/src/include/openssl/digest.h b/src/include/openssl/digest.h
new file mode 100644
index 0000000..95a35e7
--- /dev/null
+++ b/src/include/openssl/digest.h
@@ -0,0 +1,282 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 OPENSSL_HEADER_DIGEST_H
+#define OPENSSL_HEADER_DIGEST_H
+
+#include <openssl/base.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* Digest functions.
+ *
+ * An EVP_MD abstracts the details of a specific hash function allowing code to
+ * deal with the concept of a "hash function" without needing to know exactly
+ * which hash function it is. */
+
+
+/* Hash algorithms.
+ *
+ * The following functions return |EVP_MD| objects that implement the named hash
+ * function. */
+
+OPENSSL_EXPORT const EVP_MD *EVP_md4(void);
+OPENSSL_EXPORT const EVP_MD *EVP_md5(void);
+OPENSSL_EXPORT const EVP_MD *EVP_sha1(void);
+OPENSSL_EXPORT const EVP_MD *EVP_sha224(void);
+OPENSSL_EXPORT const EVP_MD *EVP_sha256(void);
+OPENSSL_EXPORT const EVP_MD *EVP_sha384(void);
+OPENSSL_EXPORT const EVP_MD *EVP_sha512(void);
+
+/* EVP_md5_sha1 is a TLS-specific |EVP_MD| which computes the concatenation of
+ * MD5 and SHA-1, as used in TLS 1.1 and below. */
+OPENSSL_EXPORT const EVP_MD *EVP_md5_sha1(void);
+
+/* EVP_get_digestbynid returns an |EVP_MD| for the given NID, or NULL if no
+ * such digest is known. */
+OPENSSL_EXPORT const EVP_MD *EVP_get_digestbynid(int nid);
+
+/* EVP_get_digestbyobj returns an |EVP_MD| for the given |ASN1_OBJECT|, or NULL
+ * if no such digest is known. */
+OPENSSL_EXPORT const EVP_MD *EVP_get_digestbyobj(const ASN1_OBJECT *obj);
+
+
+/* Digest contexts.
+ *
+ * An EVP_MD_CTX represents the state of a specific digest operation in
+ * progress. */
+
+/* EVP_MD_CTX_init initialises an, already allocated, |EVP_MD_CTX|. */
+OPENSSL_EXPORT void EVP_MD_CTX_init(EVP_MD_CTX *ctx);
+
+/* EVP_MD_CTX_create allocates and initialises a fresh |EVP_MD_CTX| and returns
+ * it, or NULL on allocation failure. */
+OPENSSL_EXPORT EVP_MD_CTX *EVP_MD_CTX_create(void);
+
+/* EVP_MD_CTX_cleanup frees any resources owned by |ctx| and resets it to a
+ * freshly initialised state. It does not free |ctx| itself. It returns one. */
+OPENSSL_EXPORT int EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx);
+
+/* EVP_MD_CTX_destroy calls |EVP_MD_CTX_cleanup| and then frees |ctx| itself. */
+OPENSSL_EXPORT void EVP_MD_CTX_destroy(EVP_MD_CTX *ctx);
+
+/* EVP_MD_CTX_copy_ex sets |out|, which must already be initialised, to be a
+ * copy of |in|. It returns one on success and zero on error. */
+OPENSSL_EXPORT int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in);
+
+
+/* Digest operations. */
+
+/* EVP_DigestInit_ex configures |ctx|, which must already have been
+ * initialised, for a fresh hashing operation using |type|. It returns one on
+ * success and zero otherwise. */
+OPENSSL_EXPORT int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type,
+ ENGINE *engine);
+
+/* EVP_DigestInit acts like |EVP_DigestInit_ex| except that |ctx| is
+ * initialised before use. */
+OPENSSL_EXPORT int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type);
+
+/* EVP_DigestUpdate hashes |len| bytes from |data| into the hashing operation
+ * in |ctx|. It returns one on success and zero otherwise. */
+OPENSSL_EXPORT int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *data,
+ size_t len);
+
+/* EVP_MAX_MD_SIZE is the largest digest size supported. Functions that output
+ * a digest generally require the buffer have at least this much space. */
+#define EVP_MAX_MD_SIZE 64 /* SHA-512 is the longest so far. */
+
+/* EVP_DigestFinal_ex finishes the digest in |ctx| and writes the output to
+ * |md_out|. At most |EVP_MAX_MD_SIZE| bytes are written. If |out_size| is not
+ * NULL then |*out_size| is set to the number of bytes written. It returns one
+ * on success and zero otherwise. After this call, the hash cannot be updated
+ * or finished again until |EVP_DigestInit_ex| is called to start another
+ * hashing operation. */
+OPENSSL_EXPORT int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, uint8_t *md_out,
+ unsigned int *out_size);
+
+/* EVP_DigestFinal acts like |EVP_DigestFinal_ex| except that
+ * |EVP_MD_CTX_cleanup| is called on |ctx| before returning. */
+OPENSSL_EXPORT int EVP_DigestFinal(EVP_MD_CTX *ctx, uint8_t *md_out,
+ unsigned int *out_size);
+
+/* EVP_Digest performs a complete hashing operation in one call. It hashes
+ * |len| bytes from |data| and writes the digest to |md_out|. At most
+ * |EVP_MAX_MD_SIZE| bytes are written. If |out_size| is not NULL then
+ * |*out_size| is set to the number of bytes written. It returns one on success
+ * and zero otherwise. */
+OPENSSL_EXPORT int EVP_Digest(const void *data, size_t len, uint8_t *md_out,
+ unsigned int *md_out_size, const EVP_MD *type,
+ ENGINE *impl);
+
+
+/* Digest function accessors.
+ *
+ * These functions allow code to learn details about an abstract hash
+ * function. */
+
+/* EVP_MD_type returns a NID identifing |md|. (For example, |NID_md5|.) */
+OPENSSL_EXPORT int EVP_MD_type(const EVP_MD *md);
+
+/* EVP_MD_name returns the short name for |md| or NULL if no name is known. */
+OPENSSL_EXPORT const char *EVP_MD_name(const EVP_MD *md);
+
+/* EVP_MD_flags returns the flags for |md|, which is a set of |EVP_MD_FLAG_*|
+ * values, ORed together. */
+OPENSSL_EXPORT uint32_t EVP_MD_flags(const EVP_MD *md);
+
+/* EVP_MD_size returns the digest size of |md|, in bytes. */
+OPENSSL_EXPORT size_t EVP_MD_size(const EVP_MD *md);
+
+/* EVP_MD_block_size returns the native block-size of |md|. */
+OPENSSL_EXPORT size_t EVP_MD_block_size(const EVP_MD *md);
+
+/* EVP_MD_FLAG_PKEY_DIGEST indicates the the digest function is used with a
+ * specific public key in order to verify signatures. (For example,
+ * EVP_dss1.) */
+#define EVP_MD_FLAG_PKEY_DIGEST 1
+
+/* EVP_MD_FLAG_DIGALGID_ABSENT indicates that the parameter type in an X.509
+ * DigestAlgorithmIdentifier representing this digest function should be
+ * undefined rather than NULL. */
+#define EVP_MD_FLAG_DIGALGID_ABSENT 2
+
+
+/* Deprecated functions. */
+
+/* EVP_MD_CTX_copy sets |out|, which must /not/ be initialised, to be a copy of
+ * |in|. It returns one on success and zero on error. */
+OPENSSL_EXPORT int EVP_MD_CTX_copy(EVP_MD_CTX *out, const EVP_MD_CTX *in);
+
+/* EVP_add_digest does nothing and returns one. It exists only for
+ * compatibility with OpenSSL. */
+OPENSSL_EXPORT int EVP_add_digest(const EVP_MD *digest);
+
+
+/* Digest operation accessors. */
+
+/* EVP_MD_CTX_md returns the underlying digest function, or NULL if one has not
+ * been set. */
+OPENSSL_EXPORT const EVP_MD *EVP_MD_CTX_md(const EVP_MD_CTX *ctx);
+
+/* EVP_MD_CTX_size returns the digest size of |ctx|. It will crash if a digest
+ * hasn't been set on |ctx|. */
+OPENSSL_EXPORT unsigned EVP_MD_CTX_size(const EVP_MD_CTX *ctx);
+
+/* EVP_MD_CTX_block_size returns the block size of the digest function used by
+ * |ctx|. It will crash if a digest hasn't been set on |ctx|. */
+OPENSSL_EXPORT unsigned EVP_MD_CTX_block_size(const EVP_MD_CTX *ctx);
+
+/* EVP_MD_CTX_type returns a NID describing the digest function used by |ctx|.
+ * (For example, |NID_md5|.) It will crash if a digest hasn't been set on
+ * |ctx|. */
+OPENSSL_EXPORT int EVP_MD_CTX_type(const EVP_MD_CTX *ctx);
+
+/* EVP_MD_CTX_set_flags ORs |flags| into the flags member of |ctx|. */
+OPENSSL_EXPORT void EVP_MD_CTX_set_flags(EVP_MD_CTX *ctx, uint32_t flags);
+
+/* EVP_MD_CTX_clear_flags clears any bits from the flags member of |ctx| that
+ * are set in |flags|. */
+OPENSSL_EXPORT void EVP_MD_CTX_clear_flags(EVP_MD_CTX *ctx, uint32_t flags);
+
+/* EVP_MD_CTX_test_flags returns the AND of |flags| and the flags member of
+ * |ctx|. */
+OPENSSL_EXPORT uint32_t EVP_MD_CTX_test_flags(const EVP_MD_CTX *ctx,
+ uint32_t flags);
+
+
+struct evp_md_pctx_ops;
+
+struct env_md_ctx_st {
+ /* digest is the underlying digest function, or NULL if not set. */
+ const EVP_MD *digest;
+ /* flags is the OR of a number of |EVP_MD_CTX_FLAG_*| values. */
+ uint32_t flags;
+ /* md_data points to a block of memory that contains the hash-specific
+ * context. */
+ void *md_data;
+ /* update is usually copied from |digest->update| but can differ in some
+ * cases, i.e. HMAC.
+ * TODO(davidben): Remove this hook once |EVP_PKEY_HMAC| is gone. */
+ int (*update)(EVP_MD_CTX *ctx, const void *data, size_t count);
+
+ /* pctx is an opaque (at this layer) pointer to additional context that
+ * EVP_PKEY functions may store in this object. */
+ EVP_PKEY_CTX *pctx;
+
+ /* pctx_ops, if not NULL, points to a vtable that contains functions to
+ * manipulate |pctx|. */
+ const struct evp_md_pctx_ops *pctx_ops;
+} /* EVP_MD_CTX */;
+
+/* EVP_MD_CTX_FLAG_NO_INIT causes the |EVP_MD|'s |init| function not to be
+ * called, the |update| member not to be copied from the |EVP_MD| in
+ * |EVP_DigestInit_ex| and for |md_data| not to be initialised. */
+#define EVP_MD_CTX_FLAG_NO_INIT 1
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#define DIGEST_F_EVP_DigestInit_ex 100
+#define DIGEST_F_EVP_MD_CTX_copy_ex 101
+#define DIGEST_R_INPUT_NOT_INITIALIZED 100
+
+#endif /* OPENSSL_HEADER_DIGEST_H */
diff --git a/src/include/openssl/dsa.h b/src/include/openssl/dsa.h
new file mode 100644
index 0000000..8a182c2
--- /dev/null
+++ b/src/include/openssl/dsa.h
@@ -0,0 +1,377 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <schoch@sheba.arc.nasa.gov>. */
+
+#ifndef OPENSSL_HEADER_DSA_H
+#define OPENSSL_HEADER_DSA_H
+
+#include <openssl/base.h>
+
+#include <openssl/engine.h>
+#include <openssl/ex_data.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* DSA contains functions for signing and verifing with the Digital Signature
+ * Algorithm. */
+
+
+/* Allocation and destruction. */
+
+/* DSA_new returns a new, empty DSA object or NULL on error. */
+OPENSSL_EXPORT DSA *DSA_new(void);
+
+/* DSA_new_method acts the same as |DH_new| but takes an explicit |ENGINE|. */
+OPENSSL_EXPORT DSA *DSA_new_method(const ENGINE *engine);
+
+/* DSA_free decrements the reference count of |dsa| and frees it if the
+ * reference count drops to zero. */
+OPENSSL_EXPORT void DSA_free(DSA *dsa);
+
+/* DSA_up_ref increments the reference count of |dsa|. */
+OPENSSL_EXPORT int DSA_up_ref(DSA *dsa);
+
+
+/* Parameter generation. */
+
+/* DSA_generate_parameters_ex generates a set of DSA parameters by following
+ * the procedure given in FIPS 186-4, appendix A.
+ * (http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf)
+ *
+ * The larger prime will have a length of |bits| (e.g. 2048). The |seed| value
+ * allows others to generate and verify the same parameters and should be
+ * random input which is kept for reference. If |out_counter| or |out_h| are
+ * not NULL then the counter and h value used in the generation are written to
+ * them.
+ *
+ * The |cb| argument is passed to |BN_generate_prime_ex| and is thus called
+ * during the generation process in order to indicate progress. See the
+ * comments for that function for details. In addition to the calls made by
+ * |BN_generate_prime_ex|, |DSA_generate_parameters_ex| will call it with
+ * |event| equal to 2 and 3 at different stages of the process.
+ *
+ * It returns one on success and zero otherwise. */
+OPENSSL_EXPORT int DSA_generate_parameters_ex(DSA *dsa, unsigned bits,
+ const uint8_t *seed,
+ size_t seed_len, int *out_counter,
+ unsigned long *out_h,
+ BN_GENCB *cb);
+
+/* DSAparams_dup returns a freshly allocated |DSA| that contains a copy of the
+ * parameters from |dsa|. It returns NULL on error. */
+OPENSSL_EXPORT DSA *DSAparams_dup(const DSA *dsa);
+
+
+/* Key generation. */
+
+/* DSA_generate_key generates a public/private key pair in |dsa|, which must
+ * already have parameters setup. It returns one on success and zero on
+ * error. */
+OPENSSL_EXPORT int DSA_generate_key(DSA *dsa);
+
+
+/* Signatures. */
+
+/* DSA_SIG contains a DSA signature as a pair of integers. */
+typedef struct DSA_SIG_st {
+ BIGNUM *r, *s;
+} DSA_SIG;
+
+/* DSA_SIG_new returns a freshly allocated, DIG_SIG structure or NULL on error.
+ * Both |r| and |s| in the signature will be NULL. */
+OPENSSL_EXPORT DSA_SIG *DSA_SIG_new(void);
+
+/* DSA_SIG_free frees the contents of |sig| and then frees |sig| itself. */
+OPENSSL_EXPORT void DSA_SIG_free(DSA_SIG *sig);
+
+/* DSA_do_sign returns a signature of the hash in |digest| by the key in |dsa|
+ * and returns an allocated, DSA_SIG structure, or NULL on error. */
+OPENSSL_EXPORT DSA_SIG *DSA_do_sign(const uint8_t *digest, size_t digest_len,
+ DSA *dsa);
+
+/* DSA_do_verify verifies that |sig| is a valid signature, by the public key in
+ * |dsa|, of the hash in |digest|. It returns one if so, zero if invalid and -1
+ * on error.
+ *
+ * WARNING: do not use. This function returns -1 for error, 0 for invalid and 1
+ * for valid. However, this is dangerously different to the usual OpenSSL
+ * convention and could be a disaster if a user did |if (DSA_do_verify(...))|.
+ * Because of this, |DSA_check_signature| is a safer version of this.
+ *
+ * TODO(fork): deprecate. */
+OPENSSL_EXPORT int DSA_do_verify(const uint8_t *digest, size_t digest_len,
+ DSA_SIG *sig, const DSA *dsa);
+
+/* DSA_do_check_signature sets |*out_valid| to zero. Then it verifies that |sig|
+ * is a valid signature, by the public key in |dsa| of the hash in |digest|
+ * and, if so, it sets |*out_valid| to one.
+ *
+ * It returns one if it was able to verify the signature as valid or invalid,
+ * and zero on error. */
+OPENSSL_EXPORT int DSA_do_check_signature(int *out_valid, const uint8_t *digest,
+ size_t digest_len, DSA_SIG *sig,
+ const DSA *dsa);
+
+
+/* ASN.1 signatures.
+ *
+ * These functions also perform DSA signature operations, but deal with ASN.1
+ * encoded signatures as opposed to raw |BIGNUM|s. If you don't know what
+ * encoding a DSA signature is in, it's probably ASN.1. */
+
+/* DSA_sign signs |digest| with the key in |dsa| and writes the resulting
+ * signature, in ASN.1 form, to |out_sig| and the length of the signature to
+ * |*out_siglen|. There must be, at least, |DSA_size(dsa)| bytes of space in
+ * |out_sig|. It returns one on success and zero otherwise.
+ *
+ * (The |type| argument is ignored.) */
+OPENSSL_EXPORT int DSA_sign(int type, const uint8_t *digest, size_t digest_len,
+ uint8_t *out_sig, unsigned int *out_siglen,
+ DSA *dsa);
+
+/* DSA_verify verifies that |sig| is a valid, ASN.1 signature, by the public
+ * key in |dsa|, of the hash in |digest|. It returns one if so, zero if invalid
+ * and -1 on error.
+ *
+ * (The |type| argument is ignored.)
+ *
+ * WARNING: do not use. This function returns -1 for error, 0 for invalid and 1
+ * for valid. However, this is dangerously different to the usual OpenSSL
+ * convention and could be a disaster if a user did |if (DSA_do_verify(...))|.
+ * Because of this, |DSA_check_signature| is a safer version of this.
+ *
+ * TODO(fork): deprecate. */
+OPENSSL_EXPORT int DSA_verify(int type, const uint8_t *digest,
+ size_t digest_len, const uint8_t *sig,
+ size_t sig_len, const DSA *dsa);
+
+/* DSA_check_signature sets |*out_valid| to zero. Then it verifies that |sig|
+ * is a valid, ASN.1 signature, by the public key in |dsa|, of the hash in
+ * |digest|. If so, it sets |*out_valid| to one.
+ *
+ * It returns one if it was able to verify the signature as valid or invalid,
+ * and zero on error. */
+OPENSSL_EXPORT int DSA_check_signature(int *out_valid, const uint8_t *digest,
+ size_t digest_len, const uint8_t *sig,
+ size_t sig_len, const DSA *dsa);
+
+/* DSA_size returns the size, in bytes, of an ASN.1 encoded, DSA signature
+ * generated by |dsa|. Parameters must already have been setup in |dsa|. */
+OPENSSL_EXPORT int DSA_size(const DSA *dsa);
+
+
+/* ASN.1 encoding. */
+
+/* d2i_DSA_SIG parses an ASN.1, DER-encoded, DSA signature from |len| bytes at
+ * |*inp|. If |out_sig| is not NULL then, on exit, a pointer to the result is
+ * in |*out_sig|. If |*out_sig| is already non-NULL on entry then the result is
+ * written directly into |*out_sig|, otherwise a fresh |DSA_SIG| is allocated.
+ * On successful exit, |*inp| is advanced past the DER structure. It returns
+ * the result or NULL on error. */
+OPENSSL_EXPORT DSA_SIG *d2i_DSA_SIG(DSA_SIG **out_sig, const uint8_t **inp,
+ long len);
+
+/* i2d_DSA_SIG marshals |in| to an ASN.1, DER structure. If |outp| is not NULL
+ * then the result is written to |*outp| and |*outp| is advanced just past the
+ * output. It returns the number of bytes in the result, whether written or not,
+ * or a negative value on error. */
+OPENSSL_EXPORT int i2d_DSA_SIG(const DSA_SIG *in, uint8_t **outp);
+
+/* d2i_DSAPublicKey parses an ASN.1, DER-encoded, DSA public key from |len|
+ * bytes at |*inp|. If |out| is not NULL then, on exit, a pointer to the result
+ * is in |*out|. If |*out| is already non-NULL on entry then the result is
+ * written directly into |*out|, otherwise a fresh |DSA| is allocated. On
+ * successful exit, |*inp| is advanced past the DER structure. It returns the
+ * result or NULL on error. */
+OPENSSL_EXPORT DSA *d2i_DSAPublicKey(DSA **out, const uint8_t **inp, long len);
+
+/* i2d_DSAPublicKey marshals a public key from |in| to an ASN.1, DER structure.
+ * If |outp| is not NULL then the result is written to |*outp| and |*outp| is
+ * advanced just past the output. It returns the number of bytes in the result,
+ * whether written or not, or a negative value on error. */
+OPENSSL_EXPORT int i2d_DSAPublicKey(const DSA *in, unsigned char **outp);
+
+/* d2i_DSAPrivateKey parses an ASN.1, DER-encoded, DSA private key from |len|
+ * bytes at |*inp|. If |out| is not NULL then, on exit, a pointer to the result
+ * is in |*out|. If |*out| is already non-NULL on entry then the result is
+ * written directly into |*out|, otherwise a fresh |DSA| is allocated. On
+ * successful exit, |*inp| is advanced past the DER structure. It returns the
+ * result or NULL on error. */
+OPENSSL_EXPORT DSA *d2i_DSAPrivateKey(DSA **out, const uint8_t **inp, long len);
+
+/* i2d_DSAPrivateKey marshals a private key from |in| to an ASN.1, DER structure.
+ * If |outp| is not NULL then the result is written to |*outp| and |*outp| is
+ * advanced just past the output. It returns the number of bytes in the result,
+ * whether written or not, or a negative value on error. */
+OPENSSL_EXPORT int i2d_DSAPrivateKey(const DSA *in, unsigned char **outp);
+
+/* d2i_DSAparams parses ASN.1, DER-encoded, DSA parameters from |len| bytes at
+ * |*inp|. If |out| is not NULL then, on exit, a pointer to the result is in
+ * |*out|. If |*out| is already non-NULL on entry then the result is written
+ * directly into |*out|, otherwise a fresh |DSA| is allocated. On successful
+ * exit, |*inp| is advanced past the DER structure. It returns the result or
+ * NULL on error. */
+OPENSSL_EXPORT DSA *d2i_DSAparams(DSA **out, const uint8_t **inp, long len);
+
+/* i2d_DSAparams marshals DSA parameters from |in| to an ASN.1, DER structure.
+ * If |outp| is not NULL then the result is written to |*outp| and |*outp| is
+ * advanced just past the output. It returns the number of bytes in the result,
+ * whether written or not, or a negative value on error. */
+OPENSSL_EXPORT int i2d_DSAparams(const DSA *in, unsigned char **outp);
+
+
+/* Precomputation. */
+
+/* DSA_sign_setup precomputes the message independent part of the DSA signature
+ * and writes them to |*out_kinv| and |*out_r|. Returns one on success, zero on
+ * error.
+ *
+ * TODO(fork): decide what to do with this. Since making DSA* opaque there's no
+ * way for the user to install them. Also, it forces the DSA* not to be const
+ * when passing to the signing function. */
+OPENSSL_EXPORT int DSA_sign_setup(const DSA *dsa, BN_CTX *ctx,
+ BIGNUM **out_kinv, BIGNUM **out_r);
+
+
+/* Conversion. */
+
+/* DSA_dup_DH returns a |DH| constructed from the parameters of |dsa|. This is
+ * sometimes needed when Diffie-Hellman parameters are stored in the form of
+ * DSA parameters. It returns an allocated |DH| on success or NULL on error. */
+OPENSSL_EXPORT DH *DSA_dup_DH(const DSA *dsa);
+
+
+/* ex_data functions.
+ *
+ * These functions are wrappers. See |ex_data.h| for details. */
+
+OPENSSL_EXPORT 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);
+OPENSSL_EXPORT int DSA_set_ex_data(DSA *d, int idx, void *arg);
+OPENSSL_EXPORT void *DSA_get_ex_data(const DSA *d, int idx);
+
+
+struct dsa_method {
+ struct openssl_method_common_st common;
+
+ void *app_data;
+
+ int (*init)(DSA *dsa);
+ int (*finish)(DSA *dsa);
+
+ DSA_SIG *(*sign)(const uint8_t *digest, size_t digest_len, DSA *dsa);
+
+ int (*sign_setup)(const DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp,
+ const uint8_t *digest, size_t digest_len);
+
+ int (*verify)(int *out_valid, const uint8_t *digest, size_t digest_len,
+ DSA_SIG *sig, const DSA *dsa);
+
+ /* generate_parameters, if non-NULL, is used to generate DSA parameters. */
+ int (*generate_parameters)(DSA *dsa, unsigned bits, const uint8_t *seed,
+ size_t seed_len, int *counter_ret,
+ unsigned long *h_ret, BN_GENCB *cb);
+
+ /* keygen, if non-NULL, is used to generate DSA keys. */
+ int (*keygen)(DSA *dsa);
+};
+
+struct dsa_st {
+ long version;
+ int write_params;
+ 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;
+ DSA_METHOD *meth;
+ /* functional reference if 'meth' is ENGINE-provided */
+ ENGINE *engine;
+};
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#define DSA_F_sign 100
+#define DSA_F_verify 101
+#define DSA_F_dsa_sig_cb 102
+#define DSA_F_DSA_new_method 103
+#define DSA_F_sign_setup 104
+#define DSA_R_NEED_NEW_SETUP_VALUES 100
+#define DSA_R_BAD_Q_VALUE 101
+#define DSA_R_MODULUS_TOO_LARGE 102
+#define DSA_R_MISSING_PARAMETERS 103
+
+#endif /* OPENSSL_HEADER_DSA_H */
diff --git a/src/include/openssl/dtls1.h b/src/include/openssl/dtls1.h
new file mode 100644
index 0000000..0fc3ae6
--- /dev/null
+++ b/src/include/openssl/dtls1.h
@@ -0,0 +1,255 @@
+/* ssl/dtls1.h */
+/*
+ * 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
+
+#include <openssl/base.h>
+#include <openssl/buf.h>
+#include <openssl/pqueue.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define DTLS1_VERSION 0xFEFF
+#define DTLS1_2_VERSION 0xFEFD
+
+/* 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
+
+#ifndef OPENSSL_NO_SSL_INTERN
+
+
+#if defined(OPENSSL_WINDOWS)
+/* Because of Windows header issues, we can't get the normal declaration of
+ * timeval. */
+typedef struct OPENSSL_timeval_st {
+ long tv_sec;
+ long tv_usec;
+} OPENSSL_timeval;
+#else
+#include <sys/time.h>
+typedef struct timeval OPENSSL_timeval;
+#endif
+
+typedef struct dtls1_bitmap_st
+ {
+ /* map is a bit mask of the last 64 sequence numbers. Bit
+ * |1<<i| corresponds to |max_seq_num - i|. */
+ uint64_t map;
+ /* max_seq_num is the largest sequence number seen so far. It
+ * is a 64-bit value in big-endian encoding. */
+ uint8_t max_seq_num[8];
+ } DTLS1_BITMAP;
+
+struct dtls1_retransmit_state
+ {
+ SSL_AEAD_CTX *aead_write_ctx;
+ 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 ccs_header_st
+ {
+ unsigned char type;
+ unsigned short seq;
+ };
+
+struct dtls1_timeout_st
+ {
+ /* Number of read timeouts so far */
+ unsigned int read_timeouts;
+
+ /* Number of write timeouts so far */
+ unsigned int write_timeouts;
+
+ /* Number of alerts received so far */
+ unsigned int num_alerts;
+ };
+
+typedef struct record_pqueue_st
+ {
+ unsigned short epoch;
+ pqueue q;
+ } record_pqueue;
+
+typedef struct hm_fragment_st
+ {
+ struct hm_header_st msg_header;
+ unsigned char *fragment;
+ unsigned char *reassembly;
+ } hm_fragment;
+
+typedef struct dtls1_state_st
+ {
+ /* send_cookie is true if we are resending the ClientHello
+ * with a cookie from a HelloVerifyRequest. */
+ unsigned int send_cookie;
+
+ uint8_t cookie[DTLS1_COOKIE_LENGTH];
+ size_t cookie_len;
+
+ /*
+ * The current data and handshake epoch. This is initially
+ * undefined, and starts at zero once the initial handshake is
+ * completed
+ */
+ unsigned short r_epoch;
+ unsigned short w_epoch;
+
+ /* 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;
+
+ /* save last sequence number for retransmissions */
+ unsigned char last_write_sequence[8];
+
+ /* Received handshake records (processed and unprocessed) */
+ record_pqueue unprocessed_rcds;
+ record_pqueue processed_rcds;
+
+ /* Buffered handshake messages */
+ pqueue buffered_messages;
+
+ /* Buffered (sent) handshake records */
+ pqueue sent_messages;
+
+ /* Buffered application records.
+ * Only for records between CCS and Finished
+ * to prevent either protocol violation or
+ * unnecessary message loss.
+ */
+ record_pqueue buffered_app_data;
+
+ 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;
+
+ /* Indicates when the last handshake msg or heartbeat sent will
+ * timeout. Because of header issues on Windows, this cannot actually
+ * be a struct timeval. */
+ OPENSSL_timeval next_timeout;
+
+ /* Timeout duration */
+ unsigned short timeout_duration;
+
+ /* storage for Alert/Handshake protocol data received but not
+ * yet processed by ssl3_read_bytes: */
+ unsigned char alert_fragment[DTLS1_AL_HEADER_LENGTH];
+ unsigned int alert_fragment_len;
+ unsigned char handshake_fragment[DTLS1_HM_HEADER_LENGTH];
+ unsigned int handshake_fragment_len;
+
+ unsigned int change_cipher_spec_ok;
+ } DTLS1_STATE;
+
+typedef struct dtls1_record_data_st
+ {
+ unsigned char *packet;
+ unsigned int packet_length;
+ SSL3_BUFFER rbuf;
+ SSL3_RECORD rrec;
+ } DTLS1_RECORD_DATA;
+
+#endif
+
+/* 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/src/include/openssl/ec.h b/src/include/openssl/ec.h
new file mode 100644
index 0000000..86d7de7
--- /dev/null
+++ b/src/include/openssl/ec.h
@@ -0,0 +1,387 @@
+/* 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 OPENSSL_HEADER_EC_H
+#define OPENSSL_HEADER_EC_H
+
+#include <openssl/base.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* Low-level operations on elliptic curves. */
+
+
+typedef struct ec_group_st EC_GROUP;
+typedef struct ec_point_st EC_POINT;
+
+/** Enum for the point conversion form as defined in X9.62 (ECDSA)
+ * for the encoding of a elliptic curve point (x,y) */
+typedef enum {
+ /** the point is encoded as z||x, where the octet z specifies
+ * which solution of the quadratic equation y is */
+ POINT_CONVERSION_COMPRESSED = 2,
+ /** the point is encoded as z||x||y, where z is the octet 0x02 */
+ POINT_CONVERSION_UNCOMPRESSED = 4
+} point_conversion_form_t;
+
+
+/* Elliptic curve groups. */
+
+/* EC_GROUP_new_by_curve_name returns a fresh EC_GROUP object for the elliptic
+ * curve specified by |nid|, or NULL on error.
+ *
+ * The supported NIDs are:
+ * NID_secp224r1,
+ * NID_X9_62_prime256v1,
+ * NID_secp384r1,
+ * NID_secp521r1 */
+OPENSSL_EXPORT EC_GROUP *EC_GROUP_new_by_curve_name(int nid);
+
+/* EC_GROUP_free frees |group| and the data that it points to. */
+OPENSSL_EXPORT void EC_GROUP_free(EC_GROUP *group);
+
+/* EC_GROUP_copy sets |*dest| equal to |*src|. It returns one on success and
+ * zero otherwise. */
+OPENSSL_EXPORT int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src);
+
+/* EC_GROUP_dup returns a fresh |EC_GROUP| which is equal to |a| or NULL on
+ * error. */
+OPENSSL_EXPORT EC_GROUP *EC_GROUP_dup(const EC_GROUP *a);
+
+/* EC_GROUP_cmp returns one if |a| and |b| are the same group and zero
+ * otherwise. */
+OPENSSL_EXPORT int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b);
+
+/* EC_GROUP_get0_generator returns a pointer to the internal |EC_POINT| object
+ * in |group| that specifies the generator for the group. */
+OPENSSL_EXPORT const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group);
+
+/* EC_GROUP_get_order sets |*order| to the order of |group|, if it's not
+ * NULL. It returns one on success and zero otherwise. |ctx| is ignored. */
+OPENSSL_EXPORT int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order,
+ BN_CTX *ctx);
+
+/* EC_GROUP_get_cofactor sets |*cofactor| to the cofactor of |group| using
+ * |ctx|, if it's not NULL. It returns one on success and zero otherwise. */
+OPENSSL_EXPORT int EC_GROUP_get_cofactor(const EC_GROUP *group,
+ BIGNUM *cofactor, BN_CTX *ctx);
+
+/* EC_GROUP_get_curve_GFp gets various parameters about a group. It sets
+ * |*out_p| to the order of the coordinate field and |*out_a| and |*out_b| to
+ * the parameters of the curve when expressed as y² = x³ + ax + b. Any of the
+ * output parameters can be NULL. It returns one on success and zero on
+ * error. */
+OPENSSL_EXPORT int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *out_p,
+ BIGNUM *out_a, BIGNUM *out_b,
+ BN_CTX *ctx);
+
+/* EC_GROUP_get_curve_name returns a NID that identifies |group|. */
+OPENSSL_EXPORT int EC_GROUP_get_curve_name(const EC_GROUP *group);
+
+/* EC_GROUP_get_degree returns the number of bits needed to represent an
+ * element of the field underlying |group|. */
+OPENSSL_EXPORT int EC_GROUP_get_degree(const EC_GROUP *group);
+
+/* EC_GROUP_precompute_mult precomputes multiplies of the generator in order to
+ * speed up operations that involve calculating generator multiples. It returns
+ * one on sucess and zero otherwise. If |ctx| is not NULL, it may be used. */
+OPENSSL_EXPORT int EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx);
+
+/* EC_GROUP_have_precompute_mult returns one if |group| contains precomputed
+ * generator multiples. */
+OPENSSL_EXPORT int EC_GROUP_have_precompute_mult(const EC_GROUP *group);
+
+
+/* Points on elliptic curves. */
+
+/* EC_POINT_new returns a fresh |EC_POINT| object in the given group, or NULL
+ * on error. */
+OPENSSL_EXPORT EC_POINT *EC_POINT_new(const EC_GROUP *group);
+
+/* EC_POINT_free frees |point| and the data that it points to. */
+OPENSSL_EXPORT void EC_POINT_free(EC_POINT *point);
+
+/* EC_POINT_clear_free clears the data that |point| points to, frees it and
+ * then frees |point| itself. */
+OPENSSL_EXPORT void EC_POINT_clear_free(EC_POINT *point);
+
+/* EC_POINT_copy sets |*dest| equal to |*src|. It returns one on success and
+ * zero otherwise. */
+OPENSSL_EXPORT int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src);
+
+/* EC_POINT_dup returns a fresh |EC_POINT| that contains the same values as
+ * |src|, or NULL on error. */
+OPENSSL_EXPORT EC_POINT *EC_POINT_dup(const EC_POINT *src,
+ const EC_GROUP *group);
+
+/* EC_POINT_set_to_infinity sets |point| to be the "point at infinity" for the
+ * given group. */
+OPENSSL_EXPORT int EC_POINT_set_to_infinity(const EC_GROUP *group,
+ EC_POINT *point);
+
+/* EC_POINT_is_at_infinity returns one iff |point| is the point at infinity and
+ * zero otherwise. */
+OPENSSL_EXPORT int EC_POINT_is_at_infinity(const EC_GROUP *group,
+ const EC_POINT *point);
+
+/* EC_POINT_is_on_curve returns one if |point| is an element of |group| and
+ * zero otheriwse. If |ctx| is non-NULL, it may be used. */
+OPENSSL_EXPORT int EC_POINT_is_on_curve(const EC_GROUP *group,
+ const EC_POINT *point, BN_CTX *ctx);
+
+/* EC_POINT_cmp returns zero if |a| is equal to |b|, greater than zero is
+ * non-equal and -1 on error. If |ctx| is not NULL, it may be used. */
+OPENSSL_EXPORT int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a,
+ const EC_POINT *b, BN_CTX *ctx);
+
+/* EC_POINT_make_affine converts |point| to affine form, internally. It returns
+ * one on success and zero otherwise. If |ctx| is not NULL, it may be used. */
+OPENSSL_EXPORT int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point,
+ BN_CTX *ctx);
+
+/* EC_POINTs_make_affine converts |num| points from |points| to affine form,
+ * internally. It returns one on success and zero otherwise. If |ctx| is not
+ * NULL, it may be used. */
+OPENSSL_EXPORT int EC_POINTs_make_affine(const EC_GROUP *group, size_t num,
+ EC_POINT *points[], BN_CTX *ctx);
+
+
+/* Point conversion. */
+
+/* EC_POINT_get_affine_coordinates_GFp sets |x| and |y| to the affine value of
+ * |point| using |ctx|, if it's not NULL. It returns one on success and zero
+ * otherwise. */
+OPENSSL_EXPORT int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group,
+ const EC_POINT *point,
+ BIGNUM *x, BIGNUM *y,
+ BN_CTX *ctx);
+
+/* EC_POINT_set_affine_coordinates sets the value of |p| to be (|x|, |y|). The
+ * |ctx| argument may be used if not NULL. */
+OPENSSL_EXPORT int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group,
+ EC_POINT *point,
+ const BIGNUM *x,
+ const BIGNUM *y,
+ BN_CTX *ctx);
+
+/* EC_POINT_point2oct serialises |point| into the X9.62 form given by |form|
+ * into, at most, |len| bytes at |buf|. It returns the number of bytes written
+ * or zero on error if |buf| is non-NULL, else the number of bytes needed. The
+ * |ctx| argument may be used if not NULL. */
+OPENSSL_EXPORT size_t EC_POINT_point2oct(const EC_GROUP *group,
+ const EC_POINT *point,
+ point_conversion_form_t form,
+ uint8_t *buf, size_t len, BN_CTX *ctx);
+
+/* EC_POINT_oct2point sets |point| from |len| bytes of X9.62 format
+ * serialisation in |buf|. It returns one on success and zero otherwise. The
+ * |ctx| argument may be used if not NULL. */
+OPENSSL_EXPORT int EC_POINT_oct2point(const EC_GROUP *group, EC_POINT *point,
+ const uint8_t *buf, size_t len,
+ BN_CTX *ctx);
+
+/* EC_POINT_set_compressed_coordinates_GFp sets |point| to equal the point with
+ * the given |x| coordinate and the y coordinate specified by |y_bit| (see
+ * X9.62). It returns one on success and zero otherwise. */
+OPENSSL_EXPORT int EC_POINT_set_compressed_coordinates_GFp(
+ const EC_GROUP *group, EC_POINT *point, const BIGNUM *x, int y_bit,
+ BN_CTX *ctx);
+
+
+/* Group operations. */
+
+/* EC_POINT_add sets |r| equal to |a| plus |b|. It returns one on success and
+ * zero otherwise. If |ctx| is not NULL, it may be used. */
+OPENSSL_EXPORT int EC_POINT_add(const EC_GROUP *group, EC_POINT *r,
+ const EC_POINT *a, const EC_POINT *b,
+ BN_CTX *ctx);
+
+/* EC_POINT_dbl sets |r| equal to |a| plus |a|. It returns one on success and
+ * zero otherwise. If |ctx| is not NULL, it may be used. */
+OPENSSL_EXPORT int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r,
+ const EC_POINT *a, BN_CTX *ctx);
+
+/* EC_POINT_dbl sets |a| equal to minus |a|. It returns one on success and zero
+ * otherwise. If |ctx| is not NULL, it may be used. */
+OPENSSL_EXPORT int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a,
+ BN_CTX *ctx);
+
+/* EC_POINT_mul sets r = generator*n + q*m. It returns one on success and zero
+ * otherwise. If |ctx| is not NULL, it may be used. */
+OPENSSL_EXPORT int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r,
+ const BIGNUM *n, const EC_POINT *q,
+ const BIGNUM *m, BN_CTX *ctx);
+
+/* EC_POINTs_mul sets r = generator*n + sum(p[i]*m[i]). It returns one on
+ * success and zero otherwise. If |ctx| is not NULL, it may be used. */
+OPENSSL_EXPORT 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);
+
+
+/* Old code expects to get EC_KEY from ec.h. */
+#if !defined(OPENSSL_HEADER_EC_KEY_H)
+#include <openssl/ec_key.h>
+#endif
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#define EC_F_ec_pre_comp_new 100
+#define EC_F_ec_GFp_mont_field_decode 101
+#define EC_F_ec_group_new_from_data 102
+#define EC_F_ec_GFp_simple_point_get_affine_coordinates 103
+#define EC_F_ec_GFp_simple_make_affine 104
+#define EC_F_EC_KEY_new_method 105
+#define EC_F_ec_GFp_mont_field_encode 106
+#define EC_F_EC_GROUP_new_by_curve_name 107
+#define EC_F_ec_group_new 108
+#define EC_F_ec_asn1_group2pkparameters 109
+#define EC_F_EC_POINT_set_compressed_coordinates_GFp 110
+#define EC_F_ec_GFp_mont_field_sqr 111
+#define EC_F_EC_POINT_make_affine 112
+#define EC_F_i2d_ECParameters 113
+#define EC_F_ec_wNAF_mul 114
+#define EC_F_EC_GROUP_copy 115
+#define EC_F_EC_POINT_cmp 116
+#define EC_F_ec_GFp_mont_field_mul 117
+#define EC_F_EC_POINT_dup 118
+#define EC_F_EC_POINT_invert 119
+#define EC_F_ec_GFp_simple_point_set_affine_coordinates 120
+#define EC_F_ec_GFp_simple_points_make_affine 121
+#define EC_F_i2o_ECPublicKey 122
+#define EC_F_EC_KEY_check_key 123
+#define EC_F_ec_wNAF_precompute_mult 124
+#define EC_F_EC_POINT_oct2point 125
+#define EC_F_EC_POINT_is_at_infinity 126
+#define EC_F_EC_POINT_get_affine_coordinates_GFp 127
+#define EC_F_ec_point_set_Jprojective_coordinates_GFp 128
+#define EC_F_o2i_ECPublicKey 129
+#define EC_F_ec_GFp_mont_field_set_to_one 130
+#define EC_F_ec_group_new_curve_GFp 131
+#define EC_F_EC_POINT_dbl 132
+#define EC_F_ec_asn1_pkparameters2group 133
+#define EC_F_i2d_ECPKParameters 134
+#define EC_F_EC_KEY_copy 135
+#define EC_F_EC_POINT_new 136
+#define EC_F_EC_POINT_point2oct 137
+#define EC_F_EC_POINT_copy 138
+#define EC_F_EC_POINT_is_on_curve 139
+#define EC_F_ec_GFp_simple_group_set_curve 140
+#define EC_F_i2d_ECPrivateKey 141
+#define EC_F_d2i_ECParameters 142
+#define EC_F_ec_GFp_mont_group_set_curve 143
+#define EC_F_EC_POINT_set_to_infinity 144
+#define EC_F_EC_POINTs_make_affine 145
+#define EC_F_compute_wNAF 146
+#define EC_F_ec_GFp_simple_point2oct 147
+#define EC_F_EC_GROUP_get_degree 148
+#define EC_F_ec_GFp_simple_group_check_discriminant 149
+#define EC_F_d2i_ECPKParameters 150
+#define EC_F_d2i_ECPrivateKey 151
+#define EC_F_ec_GFp_simple_oct2point 152
+#define EC_F_EC_POINT_set_affine_coordinates_GFp 153
+#define EC_F_EC_KEY_set_public_key_affine_coordinates 154
+#define EC_F_EC_KEY_generate_key 155
+#define EC_F_ec_GFp_simple_set_compressed_coordinates 156
+#define EC_F_EC_POINT_add 157
+#define EC_F_EC_GROUP_get_curve_GFp 158
+#define EC_R_PKPARAMETERS2GROUP_FAILURE 100
+#define EC_R_NON_NAMED_CURVE 101
+#define EC_R_COORDINATES_OUT_OF_RANGE 102
+#define EC_R_POINT_AT_INFINITY 103
+#define EC_R_NOT_INITIALIZED 104
+#define EC_R_MISSING_PRIVATE_KEY 105
+#define EC_R_GROUP2PKPARAMETERS_FAILURE 106
+#define EC_R_INVALID_ENCODING 107
+#define EC_R_BUFFER_TOO_SMALL 108
+#define EC_R_D2I_ECPKPARAMETERS_FAILURE 109
+#define EC_R_INVALID_FORM 110
+#define EC_R_INVALID_PRIVATE_KEY 111
+#define EC_R_INVALID_COMPRESSED_POINT 112
+#define EC_R_MISSING_PARAMETERS 113
+#define EC_R_INVALID_FIELD 114
+#define EC_R_INVALID_COMPRESSION_BIT 115
+#define EC_R_GF2M_NOT_SUPPORTED 116
+#define EC_R_POINT_IS_NOT_ON_CURVE 117
+#define EC_R_UNKNOWN_ORDER 118
+#define EC_R_UNKNOWN_GROUP 119
+#define EC_R_WRONG_ORDER 120
+#define EC_R_UNDEFINED_GENERATOR 121
+#define EC_R_INCOMPATIBLE_OBJECTS 122
+#define EC_R_I2D_ECPKPARAMETERS_FAILURE 123
+#define EC_R_EC_GROUP_NEW_BY_NAME_FAILURE 124
+#define EC_R_INVALID_GROUP_ORDER 125
+#define EC_R_SLOT_FULL 126
+
+#endif /* OPENSSL_HEADER_EC_H */
diff --git a/src/include/openssl/ec_key.h b/src/include/openssl/ec_key.h
new file mode 100644
index 0000000..d659216
--- /dev/null
+++ b/src/include/openssl/ec_key.h
@@ -0,0 +1,280 @@
+/* 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 OPENSSL_HEADER_EC_KEY_H
+#define OPENSSL_HEADER_EC_KEY_H
+
+#include <openssl/base.h>
+
+#include <openssl/ec.h>
+#include <openssl/engine.h>
+#include <openssl/ex_data.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* ec_key.h conatins functions that handle elliptic-curve points that are
+ * public/private keys. */
+
+
+/* EC key objects. */
+
+/* EC_KEY_new returns a fresh |EC_KEY| object or NULL on error. */
+OPENSSL_EXPORT EC_KEY *EC_KEY_new(void);
+
+/* EC_KEY_new_method acts the same as |EC_KEY_new|, but takes an explicit
+ * |ENGINE|. */
+OPENSSL_EXPORT EC_KEY *EC_KEY_new_method(const ENGINE *engine);
+
+/* EC_KEY_new_by_curve_name returns a fresh EC_KEY for group specified by |nid|
+ * or NULL on error. */
+OPENSSL_EXPORT EC_KEY *EC_KEY_new_by_curve_name(int nid);
+
+/* EC_KEY_free frees all the data owned by |key| and |key| itself. */
+OPENSSL_EXPORT void EC_KEY_free(EC_KEY *key);
+
+/* EC_KEY_copy sets |dst| equal to |src| and returns |dst| or NULL on error. */
+OPENSSL_EXPORT EC_KEY *EC_KEY_copy(EC_KEY *dst, const EC_KEY *src);
+
+/* EC_KEY_dup returns a fresh copy of |src| or NULL on error. */
+OPENSSL_EXPORT EC_KEY *EC_KEY_dup(const EC_KEY *src);
+
+/* EC_KEY_up_ref increases the reference count of |key|. It returns one on
+ * success and zero otherwise. */
+OPENSSL_EXPORT int EC_KEY_up_ref(EC_KEY *key);
+
+/* EC_KEY_is_opaque returns one if |key| is opaque and doesn't expose its key
+ * material. Otherwise it return zero. */
+OPENSSL_EXPORT int EC_KEY_is_opaque(const EC_KEY *key);
+
+/* EC_KEY_get0_group returns a pointer to the |EC_GROUP| object inside |key|. */
+OPENSSL_EXPORT const EC_GROUP *EC_KEY_get0_group(const EC_KEY *key);
+
+/* EC_KEY_set_group sets the |EC_GROUP| object that |key| will use to |group|.
+ * It returns one on success and zero otherwise. */
+OPENSSL_EXPORT int EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group);
+
+/* EC_KEY_get0_private_key returns a pointer to the private key inside |key|. */
+OPENSSL_EXPORT const BIGNUM *EC_KEY_get0_private_key(const EC_KEY *key);
+
+/* EC_KEY_set_private_key sets the private key of |key| to |priv|. It returns
+ * one on success and zero otherwise. */
+OPENSSL_EXPORT int EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *prv);
+
+/* EC_KEY_get0_public_key returns a pointer to the public key point inside
+ * |key|. */
+OPENSSL_EXPORT const EC_POINT *EC_KEY_get0_public_key(const EC_KEY *key);
+
+/* EC_KEY_set_public_key sets the public key of |key| to |pub|, by copying it.
+ * It returns one on success and zero otherwise. */
+OPENSSL_EXPORT int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub);
+
+#define EC_PKEY_NO_PARAMETERS 0x001
+#define EC_PKEY_NO_PUBKEY 0x002
+
+/* EC_KEY_get_enc_flags returns the encoding flags for |key|, which is a
+ * bitwise-OR of |EC_PKEY_*| values. */
+OPENSSL_EXPORT unsigned EC_KEY_get_enc_flags(const EC_KEY *key);
+
+/* EC_KEY_set_enc_flags sets the encoding flags for |key|, which is a
+ * bitwise-OR of |EC_PKEY_*| values. */
+OPENSSL_EXPORT void EC_KEY_set_enc_flags(EC_KEY *key, unsigned flags);
+
+/* EC_KEY_get_conv_form returns the conversation form that will be used by
+ * |key|. */
+OPENSSL_EXPORT point_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *key);
+
+/* EC_KEY_set_conv_form sets the conversion form to be used by |key|. */
+OPENSSL_EXPORT void EC_KEY_set_conv_form(EC_KEY *key,
+ point_conversion_form_t cform);
+
+/* EC_KEY_precompute_mult precomputes multiplies of the generator of the
+ * underlying group in order to speed up operations that calculate generator
+ * multiples. If |ctx| is not NULL, it may be used. It returns one on success
+ * and zero otherwise. */
+OPENSSL_EXPORT int EC_KEY_precompute_mult(EC_KEY *key, BN_CTX *ctx);
+
+/* EC_KEY_check_key performs several checks on |key| (possibly including an
+ * expensive check that the public key is in the primary subgroup). It returns
+ * one if all checks pass and zero otherwise. If it returns zero then detail
+ * about the problem can be found on the error stack. */
+OPENSSL_EXPORT int EC_KEY_check_key(const EC_KEY *key);
+
+/* EC_KEY_set_public_key_affine_coordinates sets the public key in |key| to
+ * (|x|, |y|). It returns one on success and zero otherwise. */
+OPENSSL_EXPORT int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key,
+ BIGNUM *x,
+ BIGNUM *y);
+
+
+/* Key generation. */
+
+/* EC_KEY_generate_key generates a random, private key, calculates the
+ * corresponding public key and stores both in |key|. It returns one on success
+ * or zero otherwise. */
+OPENSSL_EXPORT int EC_KEY_generate_key(EC_KEY *key);
+
+
+/* Serialisation. */
+
+/* d2i_ECPrivateKey parses an ASN.1, DER-encoded, private key from |len| bytes
+ * at |*inp|. If |out_key| is not NULL then, on exit, a pointer to the result
+ * is in |*out_key|. If |*out_key| is already non-NULL on entry then the result
+ * is written directly into |*out_key|, otherwise a fresh |EC_KEY| is
+ * allocated. On successful exit, |*inp| is advanced past the DER structure. It
+ * returns the result or NULL on error. */
+OPENSSL_EXPORT EC_KEY *d2i_ECPrivateKey(EC_KEY **out_key, const uint8_t **inp,
+ long len);
+
+/* i2d_ECParameters marshals an EC private key from |key| to an ASN.1, DER
+ * structure. If |outp| is not NULL then the result is written to |*outp| and
+ * |*outp| is advanced just past the output. It returns the number of bytes in
+ * the result, whether written or not, or a negative value on error. */
+OPENSSL_EXPORT int i2d_ECPrivateKey(const EC_KEY *key, uint8_t **outp);
+
+/* d2i_ECParameters parses an ASN.1, DER-encoded, set of EC parameters from
+ * |len| bytes at |*inp|. If |out_key| is not NULL then, on exit, a pointer to
+ * the result is in |*out_key|. If |*out_key| is already non-NULL on entry then
+ * the result is written directly into |*out_key|, otherwise a fresh |EC_KEY|
+ * is allocated. On successful exit, |*inp| is advanced past the DER structure.
+ * It returns the result or NULL on error. */
+OPENSSL_EXPORT EC_KEY *d2i_ECParameters(EC_KEY **out_key, const uint8_t **inp,
+ long len);
+
+/* i2d_ECParameters marshals EC parameters from |key| to an ASN.1, DER
+ * structure. If |outp| is not NULL then the result is written to |*outp| and
+ * |*outp| is advanced just past the output. It returns the number of bytes in
+ * the result, whether written or not, or a negative value on error. */
+OPENSSL_EXPORT int i2d_ECParameters(const EC_KEY *key, uint8_t **outp);
+
+/* o2i_ECPublicKey parses an EC point from |len| bytes at |*inp| into
+ * |*out_key|. Note that this differs from the d2i format in that |*out_key|
+ * must be non-NULL. On successful exit, |*inp| is advanced past the DER
+ * structure. It returns |*out_key| or NULL on error. */
+OPENSSL_EXPORT EC_KEY *o2i_ECPublicKey(EC_KEY **out_key, const uint8_t **inp,
+ long len);
+
+/* i2o_ECPublicKey marshals an EC point from |key|. If |outp| is not NULL then
+ * the result is written to |*outp| and |*outp| is advanced just past the
+ * output. It returns the number of bytes in the result, whether written or
+ * not, or a negative value on error. */
+OPENSSL_EXPORT int i2o_ECPublicKey(const EC_KEY *key, unsigned char **outp);
+
+
+/* ex_data functions.
+ *
+ * These functions are wrappers. See |ex_data.h| for details. */
+
+OPENSSL_EXPORT int EC_KEY_get_ex_new_index(long argl, void *argp,
+ CRYPTO_EX_new *new_func,
+ CRYPTO_EX_dup *dup_func,
+ CRYPTO_EX_free *free_func);
+OPENSSL_EXPORT int EC_KEY_set_ex_data(EC_KEY *r, int idx, void *arg);
+OPENSSL_EXPORT void *EC_KEY_get_ex_data(const EC_KEY *r, int idx);
+
+
+/* ECDSA method. */
+
+/* ECDSA_FLAG_OPAQUE specifies that this ECDSA_METHOD does not expose its key
+ * material. This may be set if, for instance, it is wrapping some other crypto
+ * API, like a platform key store. */
+#define ECDSA_FLAG_OPAQUE 1
+
+/* ecdsa_method_st is a structure of function pointers for implementing ECDSA.
+ * See engine.h. */
+struct ecdsa_method_st {
+ struct openssl_method_common_st common;
+
+ void *app_data;
+
+ int (*init)(EC_KEY *key);
+ int (*finish)(EC_KEY *key);
+
+ /* group_order_size returns the number of bytes needed to represent the order
+ * of the group. This is used to calculate the maximum size of an ECDSA
+ * signature in |ECDSA_size|. */
+ size_t (*group_order_size)(const EC_KEY *key);
+
+ /* sign matches the arguments and behaviour of |ECDSA_sign|. */
+ int (*sign)(const uint8_t *digest, size_t digest_len, uint8_t *sig,
+ unsigned int *sig_len, EC_KEY *eckey);
+
+ /* verify matches the arguments and behaviour of |ECDSA_verify|. */
+ int (*verify)(const uint8_t *digest, size_t digest_len, const uint8_t *sig,
+ size_t sig_len, EC_KEY *eckey);
+
+ int flags;
+};
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_EC_KEY_H */
diff --git a/src/include/openssl/ecdh.h b/src/include/openssl/ecdh.h
new file mode 100644
index 0000000..46cf839
--- /dev/null
+++ b/src/include/openssl/ecdh.h
@@ -0,0 +1,103 @@
+/* ====================================================================
+ * 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) 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). */
+
+#ifndef OPENSSL_HEADER_ECDH_H
+#define OPENSSL_HEADER_ECDH_H
+
+#include <openssl/base.h>
+
+#include <openssl/ec_key.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* Elliptic curve Diffie-Hellman. */
+
+
+/* ECDH_compute_key calculates the shared key between |pub_key| and |priv_key|.
+ * If |KDF| is not NULL, then it is called with the bytes of the shared key and
+ * the parameter |out|. When |KDF| returns, the value of |*outlen| becomes the
+ * return value. Otherwise, as many bytes of the shared key as will fit are
+ * copied directly to, at most, |outlen| bytes at |out|. It returns the number
+ * of bytes written to |out|, or -1 on error. */
+OPENSSL_EXPORT int ECDH_compute_key(void *out, size_t outlen,
+ const EC_POINT *pub_key, EC_KEY *priv_key,
+ void *(*KDF)(const void *in, size_t inlen,
+ void *out, size_t *outlen));
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#define ECDH_F_ECDH_compute_key 100
+#define ECDH_R_POINT_ARITHMETIC_FAILURE 100
+#define ECDH_R_KDF_FAILED 101
+#define ECDH_R_NO_PRIVATE_VALUE 102
+
+#endif /* OPENSSL_HEADER_ECDH_H */
diff --git a/src/include/openssl/ecdsa.h b/src/include/openssl/ecdsa.h
new file mode 100644
index 0000000..f3ff49f
--- /dev/null
+++ b/src/include/openssl/ecdsa.h
@@ -0,0 +1,187 @@
+/* ====================================================================
+ * 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). */
+
+#ifndef OPENSSL_HEADER_ECDSA_H
+#define OPENSSL_HEADER_ECDSA_H
+
+#include <openssl/base.h>
+
+#include <openssl/ec_key.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* ECDSA contains functions for signing and verifying with the Digital Signature
+ * Algorithm over elliptic curves. */
+
+
+/* Signing and verifing. */
+
+/* ECDSA_sign signs |digest_len| bytes from |digest| with |key| and writes the
+ * resulting signature to |sig|, which must have |ECDSA_size(key)| bytes of
+ * space. On successful exit, |*sig_len| is set to the actual number of bytes
+ * written. The |type| argument should be zero. It returns one on success and
+ * zero otherwise. */
+OPENSSL_EXPORT int ECDSA_sign(int type, const uint8_t *digest,
+ size_t digest_len, uint8_t *sig,
+ unsigned int *sig_len, EC_KEY *key);
+
+/* ECDSA_verify verifies that |sig_len| bytes from |sig| constitute a valid
+ * signature by |key| of |digest|. (The |type| argument should be zero.) It
+ * returns one on success or zero if the signature is invalid or an error
+ * occured. */
+OPENSSL_EXPORT int ECDSA_verify(int type, const uint8_t *digest,
+ size_t digest_len, const uint8_t *sig,
+ size_t sig_len, EC_KEY *key);
+
+/* ECDSA_size returns the maximum size of an ECDSA signature using |key|. It
+ * returns zero on error. */
+OPENSSL_EXPORT size_t ECDSA_size(const EC_KEY *key);
+
+
+/* Low-level signing and verification.
+ *
+ * Low-level functions handle signatures as |ECDSA_SIG| structures which allow
+ * the two values in an ECDSA signature to be handled separately. */
+
+struct ecdsa_sig_st {
+ BIGNUM *r;
+ BIGNUM *s;
+};
+
+/* ECDSA_SIG_new returns a fresh |ECDSA_SIG| structure or NULL on error. */
+OPENSSL_EXPORT ECDSA_SIG *ECDSA_SIG_new(void);
+
+/* ECDSA_SIG_free frees |sig| its member |BIGNUM|s. */
+OPENSSL_EXPORT void ECDSA_SIG_free(ECDSA_SIG *sig);
+
+/* ECDSA_sign signs |digest_len| bytes from |digest| with |key| and returns the
+ * resulting signature structure, or NULL on error.
+ *
+ * TODO(fork): remove this function. */
+OPENSSL_EXPORT ECDSA_SIG *ECDSA_do_sign(const uint8_t *digest,
+ size_t digest_len, EC_KEY *key);
+
+/* ECDSA_verify verifies that |sig| constitutes a valid signature by |key| of
+ * |digest|. It returns one on success or zero if the signature is invalid or
+ * on error.
+ *
+ * TODO(fork): remove this function. */
+OPENSSL_EXPORT int ECDSA_do_verify(const uint8_t *digest, size_t digest_len,
+ const ECDSA_SIG *sig, EC_KEY *key);
+
+
+/* Signing with precomputation.
+ *
+ * Parts of the ECDSA signature can be independent of the message to be signed
+ * thus it's possible to precompute them and reduce the signing latency.
+ *
+ * TODO(fork): remove support for this as it cannot support safe-randomness. */
+
+/* ECDSA_sign_setup precomputes parts of an ECDSA signing operation. It sets
+ * |*kinv| and |*rp| to the precomputed values and uses the |ctx| argument, if
+ * not NULL. It returns one on success and zero otherwise. */
+OPENSSL_EXPORT int ECDSA_sign_setup(EC_KEY *eckey, BN_CTX *ctx, BIGNUM **kinv,
+ BIGNUM **rp);
+
+/* ECDSA_do_sign_ex is the same as |ECDSA_do_sign| but takes precomputed values
+ * as generated by |ECDSA_sign_setup|. */
+OPENSSL_EXPORT ECDSA_SIG *ECDSA_do_sign_ex(const uint8_t *digest,
+ size_t digest_len,
+ const BIGNUM *kinv, const BIGNUM *rp,
+ EC_KEY *eckey);
+
+/* ECDSA_sign_ex is the same as |ECDSA_sign| but takes precomputed values as
+ * generated by |ECDSA_sign_setup|. */
+OPENSSL_EXPORT int ECDSA_sign_ex(int type, const uint8_t *digest,
+ size_t digest_len, uint8_t *sig,
+ unsigned int *sig_len, const BIGNUM *kinv,
+ const BIGNUM *rp, EC_KEY *eckey);
+
+
+/* ASN.1 functions. */
+
+/* d2i_ECDSA_SIG parses an ASN.1, DER-encoded, signature from |len| bytes at
+ * |*inp|. If |out| is not NULL then, on exit, a pointer to the result is in
+ * |*out|. If |*out| is already non-NULL on entry then the result is written
+ * directly into |*out|, otherwise a fresh |ECDSA_SIG| is allocated. On
+ * successful exit, |*inp| is advanced past the DER structure. It returns the
+ * result or NULL on error. */
+OPENSSL_EXPORT ECDSA_SIG *d2i_ECDSA_SIG(ECDSA_SIG **out, const uint8_t **inp,
+ long len);
+
+/* i2d_ECDSA_SIG marshals a signature from |sig| to an ASN.1, DER
+ * structure. If |outp| is not NULL then the result is written to |*outp| and
+ * |*outp| is advanced just past the output. It returns the number of bytes in
+ * the result, whether written or not, or a negative value on error. */
+OPENSSL_EXPORT int i2d_ECDSA_SIG(const ECDSA_SIG *sig, uint8_t **outp);
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#define ECDSA_F_digest_to_bn 100
+#define ECDSA_F_ECDSA_do_verify 101
+#define ECDSA_F_ECDSA_sign_setup 102
+#define ECDSA_F_ECDSA_do_sign_ex 103
+#define ECDSA_F_ECDSA_sign_ex 104
+#define ECDSA_F_ecdsa_sign_setup 105
+#define ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED 100
+#define ECDSA_R_NEED_NEW_SETUP_VALUES 101
+#define ECDSA_R_MISSING_PARAMETERS 102
+#define ECDSA_R_BAD_SIGNATURE 103
+#define ECDSA_R_NOT_IMPLEMENTED 104
+
+#endif /* OPENSSL_HEADER_ECDSA_H */
diff --git a/src/include/openssl/engine.h b/src/include/openssl/engine.h
new file mode 100644
index 0000000..4a4f37d
--- /dev/null
+++ b/src/include/openssl/engine.h
@@ -0,0 +1,105 @@
+/* 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_ENGINE_H
+#define OPENSSL_HEADER_ENGINE_H
+
+#include <openssl/base.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* Engines are collections of methods. Methods are tables of function pointers,
+ * defined for certain algorithms, that allow operations on those algorithms to
+ * be overridden via a callback. This can be used, for example, to implement an
+ * RSA* that forwards operations to a hardware module.
+ *
+ * Methods are reference counted but |ENGINE|s are not. When creating a method,
+ * you should zero the whole structure and fill in the function pointers that
+ * you wish before setting it on an |ENGINE|. Any functions pointers that
+ * are NULL indicate that the default behaviour should be used. */
+
+
+/* Allocation and destruction. */
+
+/* ENGINE_new returns an empty ENGINE that uses the default method for all
+ * algorithms. */
+OPENSSL_EXPORT ENGINE *ENGINE_new(void);
+
+/* ENGINE_free decrements the reference counts for all methods linked from
+ * |engine| and frees |engine| itself. */
+OPENSSL_EXPORT void ENGINE_free(ENGINE *engine);
+
+
+/* Method accessors.
+ *
+ * Method accessors take a method pointer and the size of the structure. The
+ * size allows for ABI compatibility in the case that the method structure is
+ * extended with extra elements at the end. Methods are always copied by the
+ * set functions.
+ *
+ * Set functions return one on success and zero on allocation failure. */
+
+OPENSSL_EXPORT int ENGINE_set_DH_method(ENGINE *engine, const DH_METHOD *method,
+ size_t method_size);
+OPENSSL_EXPORT DH_METHOD *ENGINE_get_DH_method(const ENGINE *engine);
+
+OPENSSL_EXPORT int ENGINE_set_DSA_method(ENGINE *engine,
+ const DSA_METHOD *method,
+ size_t method_size);
+OPENSSL_EXPORT DSA_METHOD *ENGINE_get_DSA_method(const ENGINE *engine);
+
+OPENSSL_EXPORT int ENGINE_set_RSA_method(ENGINE *engine,
+ const RSA_METHOD *method,
+ size_t method_size);
+OPENSSL_EXPORT RSA_METHOD *ENGINE_get_RSA_method(const ENGINE *engine);
+
+OPENSSL_EXPORT int ENGINE_set_ECDSA_method(ENGINE *engine,
+ const ECDSA_METHOD *method,
+ size_t method_size);
+OPENSSL_EXPORT ECDSA_METHOD *ENGINE_get_ECDSA_method(const ENGINE *engine);
+
+
+/* Generic method functions.
+ *
+ * These functions take a void* type but actually operate on all method
+ * structures. */
+
+/* METHOD_ref increments the reference count of |method|. */
+OPENSSL_EXPORT void METHOD_ref(void *method);
+
+/* METHOD_unref decrements the reference count of |method| and frees it if the
+ * reference count drops to zero. */
+OPENSSL_EXPORT void METHOD_unref(void *method);
+
+
+/* Private functions. */
+
+/* openssl_method_common_st contains the common part of all method structures.
+ * This must be the first member of all method structures. */
+struct openssl_method_common_st {
+ int references;
+ char is_static;
+};
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#define ENGINE_R_OPERATION_NOT_SUPPORTED 100
+
+#endif /* OPENSSL_HEADER_ENGINE_H */
diff --git a/src/include/openssl/err.h b/src/include/openssl/err.h
new file mode 100644
index 0000000..c749659
--- /dev/null
+++ b/src/include/openssl/err.h
@@ -0,0 +1,544 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 OPENSSL_HEADER_ERR_H
+#define OPENSSL_HEADER_ERR_H
+
+#include <openssl/base.h>
+#include <openssl/thread.h>
+#include <openssl/lhash.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* Error queue handling functions.
+ *
+ * Errors in OpenSSL are generally signalled by the return value of a function.
+ * When a function fails it may add an entry to a per-thread error queue,
+ * which is managed by the functions in this header.
+ *
+ * Each error contains:
+ * 1) The library (i.e. ec, pem, rsa) which created it.
+ * 2) A function identifier and reason code.
+ * 3) The file and line number of the call that added the error.
+ * 4) A pointer to some error specific data, which may be NULL.
+ *
+ * The library identifier, function identifier and reason code are packed in a
+ * uint32_t and there exist various functions for unpacking it.
+ *
+ * The typical behaviour is that an error will occur deep in a call queue and
+ * that code will push an error onto the error queue. As the error queue
+ * unwinds, other functions will push their own errors. Thus, the "least
+ * recent" error is the most specific and the other errors will provide a
+ * backtrace of sorts. */
+
+
+/* Startup and shutdown. */
+
+/* ERR_load_crypto_strings initialises the error string hash with builtin
+ * values. If this is not called then the string forms of errors produced by
+ * the functions below will contain numeric identifiers rather than
+ * human-readable strings. */
+OPENSSL_EXPORT void ERR_load_crypto_strings(void);
+
+/* ERR_free_strings frees any memory retained by the error system, expect for
+ * per-thread structures which are assumed to have already been freed with
+ * |ERR_remove_thread_state|. This should only be called at process
+ * shutdown. */
+OPENSSL_EXPORT void ERR_free_strings(void);
+
+
+/* Reading and formatting errors. */
+
+/* ERR_get_error gets the packed error code for the least recent error and
+ * removes that error from the queue. If there are no errors in the queue then
+ * it returns zero. */
+OPENSSL_EXPORT uint32_t ERR_get_error(void);
+
+/* ERR_get_error_line acts like |ERR_get_error|, except that the file and line
+ * number of the call that added the error are also returned. */
+OPENSSL_EXPORT uint32_t ERR_get_error_line(const char **file, int *line);
+
+/* ERR_get_error_line_data acts like |ERR_get_error_line|, but also returns the
+ * error-specific data pointer and flags. The flags are a bitwise-OR of
+ * |ERR_FLAG_*| values. The error-specific data is owned by the error queue
+ * and the pointer becomes invalid after the next call that affects the same
+ * thread's error queue. If |*flags| contains |ERR_FLAG_STRING| then |*data| is
+ * human-readable. */
+OPENSSL_EXPORT uint32_t ERR_get_error_line_data(const char **file, int *line,
+ const char **data, int *flags);
+
+/* The "peek" functions act like the |ERR_get_error| functions, above, but they
+ * do not remove the error from the queue. */
+OPENSSL_EXPORT uint32_t ERR_peek_error(void);
+OPENSSL_EXPORT uint32_t ERR_peek_error_line(const char **file, int *line);
+OPENSSL_EXPORT uint32_t ERR_peek_error_line_data(const char **file, int *line,
+ const char **data, int *flags);
+
+/* The "peek last" functions act like the "peek" functions, above, except that
+ * they return the most recent error. */
+OPENSSL_EXPORT uint32_t ERR_peek_last_error(void);
+OPENSSL_EXPORT uint32_t ERR_peek_last_error_line(const char **file, int *line);
+OPENSSL_EXPORT uint32_t ERR_peek_last_error_line_data(const char **file,
+ int *line,
+ const char **data,
+ int *flags);
+
+/* ERR_error_string generates a human-readable string representing
+ * |packed_error|, places it at |buf| (which must be at least
+ * ERR_ERROR_STRING_BUF_LEN bytes long) and returns |buf|. If |buf| is NULL,
+ * the error string is placed in a static buffer which is returned. (The static
+ * buffer may be overridden by concurrent calls in other threads so this form
+ * is deprecated.)
+ *
+ * The string will have the following format:
+ *
+ * error:[error code]:[library name]:[function name]:[reason string]
+ *
+ * error code is an 8 digit hexadecimal number; library name, function name
+ * and reason string are ASCII text.
+ *
+ * TODO(fork): remove in favour of |ERR_error_string_n|. */
+OPENSSL_EXPORT char *ERR_error_string(uint32_t packed_error, char *buf);
+#define ERR_ERROR_STRING_BUF_LEN 256
+
+/* ERR_error_string_n is a variant of |ERR_error_string| that writes at most
+ * len characters (including the terminating NUL) and truncates the string if
+ * necessary. If |len| is greater than zero then |buf| is always NUL
+ * terminated. */
+OPENSSL_EXPORT void ERR_error_string_n(uint32_t packed_error, char *buf,
+ size_t len);
+
+/* ERR_lib_error_string returns a string representation of the library that
+ * generated |packed_error|. */
+OPENSSL_EXPORT const char *ERR_lib_error_string(uint32_t packed_error);
+
+/* ERR_func_error_string returns a string representation of the function that
+ * generated |packed_error|. */
+OPENSSL_EXPORT const char *ERR_func_error_string(uint32_t packed_error);
+
+/* ERR_reason_error_string returns a string representation of the reason for
+ * |packed_error|. */
+OPENSSL_EXPORT const char *ERR_reason_error_string(uint32_t packed_error);
+
+/* ERR_print_errors_callback_t is the type of a function used by
+ * |ERR_print_errors_cb|. It takes a pointer to a human readable string (and
+ * its length) that describes an entry in the error queue. The |ctx| argument
+ * is an opaque pointer given to |ERR_print_errors_cb|.
+ *
+ * It should return one on success or zero on error, which will stop the
+ * iteration over the error queue. */
+typedef int (*ERR_print_errors_callback_t)(const char *str, size_t len,
+ void *ctx);
+
+/* ERR_print_errors_cb calls |callback| with a string representation of each
+ * error in the current thread's error queue, from the least recent to the most
+ * recent error.
+ *
+ * The string will have the following format (which differs from
+ * |ERR_error_string|):
+ *
+ * [thread id]:error:[error code]:[library name]:[function name]:
+ * [reason string]:[file]:[line number]:[optional string data]
+ *
+ * (All in one line.)
+ *
+ * The callback can return one to continue the iteration or zero to stop it.
+ * The |ctx| argument is an opaque value that is passed through to the
+ * callback. */
+OPENSSL_EXPORT void ERR_print_errors_cb(ERR_print_errors_callback_t callback,
+ void *ctx);
+
+
+/* Clearing errors. */
+
+/* ERR_clear_error clears the error queue for the current thread. */
+OPENSSL_EXPORT void ERR_clear_error(void);
+
+/* ERR_remove_thread_state deletes the error queue for the given thread. If
+ * |tid| is NULL then the error queue for the current thread is deleted. */
+OPENSSL_EXPORT void ERR_remove_thread_state(const CRYPTO_THREADID *tid);
+
+
+/* Custom errors. */
+
+/* ERR_get_next_error_library returns a value suitable for passing as the
+ * |library| argument to |ERR_put_error|. This is intended for code that wishes
+ * to push its own, non-standard errors to the error queue. */
+OPENSSL_EXPORT int ERR_get_next_error_library(void);
+
+
+/* Private functions. */
+
+/* ERR_clear_system_error clears the system's error value (i.e. errno). */
+OPENSSL_EXPORT void ERR_clear_system_error(void);
+
+/* OPENSSL_PUT_ERROR is used by OpenSSL code to add an error to the error
+ * queue. */
+#define OPENSSL_PUT_ERROR(library, func, reason) \
+ ERR_put_error(ERR_LIB_##library, library##_F_##func, reason, __FILE__, \
+ __LINE__)
+
+/* OPENSSL_PUT_SYSTEM_ERROR is used by OpenSSL code to add an error from the
+ * operating system to the error queue. */
+/* TODO(fork): include errno. */
+#define OPENSSL_PUT_SYSTEM_ERROR(func) \
+ ERR_put_error(ERR_LIB_SYS, SYS_F_##func, 0, __FILE__, __LINE__);
+
+/* ERR_put_error adds an error to the error queue, dropping the least recent
+ * error if neccessary for space reasons. */
+OPENSSL_EXPORT void ERR_put_error(int library, int func, int reason,
+ const char *file, unsigned line);
+
+/* ERR_add_error_data takes a variable number (|count|) of const char*
+ * pointers, concatenates them and sets the result as the data on the most
+ * recent error. */
+OPENSSL_EXPORT void ERR_add_error_data(unsigned count, ...);
+
+/* ERR_add_error_dataf takes a printf-style format and arguments, and sets the
+ * result as the data on the most recent error. */
+OPENSSL_EXPORT void ERR_add_error_dataf(const char *format, ...);
+
+/* ERR_set_mark "marks" the most recent error for use with |ERR_pop_to_mark|.
+ * It returns one if an error was marked and zero if there are no errors. */
+OPENSSL_EXPORT int ERR_set_mark(void);
+
+/* ERR_pop_to_mark removes errors from the most recent to the least recent
+ * until (and not including) a "marked" error. It returns zero if no marked
+ * error was found (and thus all errors were removed) and one otherwise. Errors
+ * are marked using |ERR_set_mark|. */
+OPENSSL_EXPORT int ERR_pop_to_mark(void);
+
+struct err_error_st {
+ /* file contains the filename where the error occured. */
+ const char *file;
+ /* data contains optional data. It must be freed with |OPENSSL_free| if
+ * |flags&ERR_FLAG_MALLOCED|. */
+ char *data;
+ /* packed contains the error library, function and reason, as packed by
+ * ERR_PACK. */
+ uint32_t packed;
+ /* line contains the line number where the error occured. */
+ uint16_t line;
+ /* flags contains a bitwise-OR of ERR_FLAG_* values. */
+ uint8_t flags;
+};
+
+/* ERR_FLAG_STRING means that the |data| member is a NUL-terminated string that
+ * can be printed. */
+#define ERR_FLAG_STRING 1
+/* ERR_TXT_STRING is provided for compatibility with code that assumes that
+ * it's using OpenSSL. */
+#define ERR_TXT_STRING ERR_FLAG_STRING
+
+/* ERR_FLAG_PUBLIC_MASK is applied to the flags field before it is returned
+ * from functions like |ERR_get_error_line_data|. */
+#define ERR_FLAG_PUBLIC_MASK 0xf
+
+/* The following flag values are internal and are masked when flags are
+ * returned from functions like |ERR_get_error_line_data|. */
+
+/* ERR_FLAG_MALLOCED means the the |data| member must be freed when no longer
+ * needed. */
+#define ERR_FLAG_MALLOCED 16
+/* ERR_FLAG_MARK is used to indicate a reversion point in the queue. See
+ * |ERR_pop_to_mark|. */
+#define ERR_FLAG_MARK 32
+
+/* ERR_NUM_ERRORS is the limit of the number of errors in the queue. */
+#define ERR_NUM_ERRORS 16
+
+/* ERR_STATE contains the per-thread, error queue. */
+typedef struct err_state_st {
+ /* tid is the identifier of the thread that owns this queue. */
+ CRYPTO_THREADID tid;
+
+ /* errors contains the ERR_NUM_ERRORS most recent errors, organised as a ring
+ * buffer. */
+ struct err_error_st errors[ERR_NUM_ERRORS];
+ /* top contains the index one past the most recent error. If |top| equals
+ * |bottom| then the queue is empty. */
+ unsigned top;
+ /* bottom contains the index of the last error in the queue. */
+ unsigned bottom;
+
+ /* to_free, if not NULL, contains a pointer owned by this structure that was
+ * previously a |data| pointer of one of the elements of |errors|. */
+ void *to_free;
+} ERR_STATE;
+
+enum {
+ ERR_LIB_NONE = 1,
+ ERR_LIB_SYS,
+ ERR_LIB_BN,
+ ERR_LIB_RSA,
+ ERR_LIB_DH,
+ ERR_LIB_EVP,
+ ERR_LIB_BUF,
+ ERR_LIB_OBJ,
+ ERR_LIB_PEM,
+ ERR_LIB_DSA,
+ ERR_LIB_X509,
+ ERR_LIB_ASN1,
+ ERR_LIB_CONF,
+ ERR_LIB_CRYPTO,
+ ERR_LIB_EC,
+ ERR_LIB_SSL,
+ ERR_LIB_BIO,
+ ERR_LIB_PKCS7,
+ ERR_LIB_PKCS8,
+ ERR_LIB_X509V3,
+ ERR_LIB_RAND,
+ ERR_LIB_ENGINE,
+ ERR_LIB_OCSP,
+ ERR_LIB_UI,
+ ERR_LIB_COMP,
+ ERR_LIB_ECDSA,
+ ERR_LIB_ECDH,
+ ERR_LIB_HMAC,
+ ERR_LIB_DIGEST,
+ ERR_LIB_CIPHER,
+ ERR_LIB_USER,
+ ERR_LIB_HKDF,
+ ERR_NUM_LIBS
+};
+
+#define ERR_R_SYS_LIB ERR_LIB_SYS
+#define ERR_R_BN_LIB ERR_LIB_BN
+#define ERR_R_RSA_LIB ERR_LIB_RSA
+#define ERR_R_DH_LIB ERR_LIB_DH
+#define ERR_R_EVP_LIB ERR_LIB_EVP
+#define ERR_R_BUF_LIB ERR_LIB_BUF
+#define ERR_R_OBJ_LIB ERR_LIB_OBJ
+#define ERR_R_PEM_LIB ERR_LIB_PEM
+#define ERR_R_DSA_LIB ERR_LIB_DSA
+#define ERR_R_X509_LIB ERR_LIB_X509
+#define ERR_R_ASN1_LIB ERR_LIB_ASN1
+#define ERR_R_CONF_LIB ERR_LIB_CONF
+#define ERR_R_CRYPTO_LIB ERR_LIB_CRYPTO
+#define ERR_R_EC_LIB ERR_LIB_EC
+#define ERR_R_SSL_LIB ERR_LIB_SSL
+#define ERR_R_BIO_LIB ERR_LIB_BIO
+#define ERR_R_PKCS7_LIB ERR_LIB_PKCS7
+#define ERR_R_PKCS8_LIB ERR_LIB_PKCS8
+#define ERR_R_X509V3_LIB ERR_LIB_X509V3
+#define ERR_R_RAND_LIB ERR_LIB_RAND
+#define ERR_R_DSO_LIB ERR_LIB_DSO
+#define ERR_R_ENGINE_LIB ERR_LIB_ENGINE
+#define ERR_R_OCSP_LIB ERR_LIB_OCSP
+#define ERR_R_UI_LIB ERR_LIB_UI
+#define ERR_R_COMP_LIB ERR_LIB_COMP
+#define ERR_R_ECDSA_LIB ERR_LIB_ECDSA
+#define ERR_R_ECDH_LIB ERR_LIB_ECDH
+#define ERR_R_STORE_LIB ERR_LIB_STORE
+#define ERR_R_FIPS_LIB ERR_LIB_FIPS
+#define ERR_R_CMS_LIB ERR_LIB_CMS
+#define ERR_R_TS_LIB ERR_LIB_TS
+#define ERR_R_HMAC_LIB ERR_LIB_HMAC
+#define ERR_R_JPAKE_LIB ERR_LIB_JPAKE
+#define ERR_R_USER_LIB ERR_LIB_USER
+#define ERR_R_DIGEST_LIB ERR_LIB_DIGEST
+#define ERR_R_CIPHER_LIB ERR_LIB_CIPHER
+#define ERR_R_HKDF_LIB ERR_LIB_HKDF
+
+/* Global reasons. */
+#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_OVERFLOW (5 | ERR_R_FATAL)
+
+/* System error functions */
+#define SYS_F_fopen 100
+#define SYS_F_fclose 101
+#define SYS_F_fread 102
+#define SYS_F_fwrite 103
+#define SYS_F_socket 104
+#define SYS_F_setsockopt 105
+#define SYS_F_connect 106
+#define SYS_F_getaddrinfo 107
+
+#define ERR_PACK(lib, func, reason) \
+ (((((uint32_t)lib) & 0xff) << 24) | ((((uint32_t)func) & 0xfff) << 12) | \
+ ((((uint32_t)reason) & 0xfff)))
+
+#define ERR_GET_LIB(packed_error) ((int)(((packed_error) >> 24) & 0xff))
+#define ERR_GET_FUNC(packed_error) ((int)(((packed_error) >> 12) & 0xfff))
+#define ERR_GET_REASON(packed_error) ((int)((packed_error) & 0xfff))
+
+/* ERR_STRING_DATA is the type of an lhash node that contains a mapping from a
+ * library, function or reason code to a string representation of it. */
+typedef struct err_string_data_st {
+ uint32_t error;
+ const char *string;
+} ERR_STRING_DATA;
+
+/* ERR_load_strings loads an array of ERR_STRING_DATA into the hash table. The
+ * array must be terminated by an entry with a NULL string. */
+OPENSSL_EXPORT void ERR_load_strings(const ERR_STRING_DATA *str);
+
+/* ERR_FNS_st is a structure of function pointers that contains the actual
+ * implementation of the error queue handling functions. */
+struct ERR_FNS_st {
+ void (*shutdown)(void (*err_state_free_cb)(ERR_STATE*));
+ ERR_STRING_DATA *(*get_item)(uint32_t packed_error);
+ ERR_STRING_DATA *(*set_item)(const ERR_STRING_DATA *);
+ ERR_STRING_DATA *(*del_item)(uint32_t packed_error);
+
+ /* get_state returns the ERR_STATE for the current thread. This function
+ * never returns NULL. */
+ ERR_STATE *(*get_state)(void);
+
+ /* release_state returns the |ERR_STATE| for the given thread, or NULL if
+ * none exists. It the return value is not NULL, it also returns ownership of
+ * the |ERR_STATE| and deletes it from its data structures. */
+ ERR_STATE *(*release_state)(const CRYPTO_THREADID *tid);
+
+ /* get_next_library returns a unique value suitable for passing as the
+ * |library| to error calls. It will be distinct from all built-in library
+ * values. */
+ int (*get_next_library)(void);
+};
+
+/* OPENSSL_DECLARE_ERROR_REASON is used by util/make_errors.h (which generates
+ * the error defines) to recognise that an additional reason value is needed.
+ * This is needed when the reason value is used outside of an
+ * |OPENSSL_PUT_ERROR| macro. The resulting define will be
+ * ${lib}_R_${reason}. */
+#define OPENSSL_DECLARE_ERROR_REASON(lib, reason)
+
+/* OPENSSL_DECLARE_ERROR_FUNCTION is used by util/make_errors.h (which
+ * generates the error * defines to recognise that an additional function value
+ * is needed. This is * needed when the function value is used outside of an
+ * |OPENSSL_PUT_ERROR| * macro. The resulting define will be
+ * ${lib}_F_${reason}. */
+#define OPENSSL_DECLARE_ERROR_FUNCTION(lib, function_name)
+
+/* ERR_load_BIO_strings does nothing.
+ *
+ * TODO(fork): remove. libjingle calls this. */
+OPENSSL_EXPORT void ERR_load_BIO_strings(void);
+
+
+/* Android compatibility section.
+ *
+ * These functions are declared, temporarily, for Android because
+ * wpa_supplicant will take a little time to sync with upstream. Outside of
+ * Android they'll have no definition. */
+
+OPENSSL_EXPORT void ERR_remove_state(unsigned long pid);
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_ERR_H */
diff --git a/src/include/openssl/evp.h b/src/include/openssl/evp.h
new file mode 100644
index 0000000..39da689
--- /dev/null
+++ b/src/include/openssl/evp.h
@@ -0,0 +1,876 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 OPENSSL_HEADER_EVP_H
+#define OPENSSL_HEADER_EVP_H
+
+#include <openssl/base.h>
+#include <openssl/stack.h>
+
+/* OpenSSL included digest and cipher functions in this header so we include
+ * them for users that still expect that.
+ *
+ * TODO(fork): clean up callers so that they include what they use. */
+#include <openssl/aead.h>
+#include <openssl/cipher.h>
+#include <openssl/digest.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/thread.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* EVP abstracts over public/private key algorithms. */
+
+
+/* Public key objects. */
+
+/* EVP_PKEY_new creates a new, empty public-key object and returns it or NULL
+ * on allocation failure. */
+OPENSSL_EXPORT EVP_PKEY *EVP_PKEY_new(void);
+
+/* EVP_PKEY_free frees all data referenced by |pkey| and then frees |pkey|
+ * itself. */
+OPENSSL_EXPORT void EVP_PKEY_free(EVP_PKEY *pkey);
+
+/* EVP_PKEY_is_opaque returns one if |pkey| is opaque. Opaque keys are backed by
+ * custom implementations which do not expose key material and parameters. It is
+ * an error to attempt to duplicate, export, or compare an opaque key. */
+OPENSSL_EXPORT int EVP_PKEY_is_opaque(const EVP_PKEY *pkey);
+
+/* EVP_PKEY_supports_digest returns one if |pkey| supports digests of
+ * type |md|. This is intended for use with EVP_PKEYs backing custom
+ * implementations which can't sign all digests. */
+OPENSSL_EXPORT int EVP_PKEY_supports_digest(const EVP_PKEY *pkey,
+ const EVP_MD *md);
+
+/* EVP_PKEY_cmp compares |a| and |b| and returns one if they are equal, zero if
+ * not and a negative number on error.
+ *
+ * WARNING: this differs from the traditional return value of a "cmp"
+ * function. */
+OPENSSL_EXPORT int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b);
+
+/* EVP_PKEY_dup adds one to the reference count of |pkey| and returns
+ * |pkey|. */
+OPENSSL_EXPORT EVP_PKEY *EVP_PKEY_dup(EVP_PKEY *pkey);
+
+/* EVP_PKEY_copy_parameters sets the parameters of |to| to equal the parameters
+ * of |from|. It returns one on success and zero on error. */
+OPENSSL_EXPORT int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from);
+
+/* EVP_PKEY_missing_parameters returns one if |pkey| is missing needed
+ * parameters or zero if not, or if the algorithm doesn't take parameters. */
+OPENSSL_EXPORT int EVP_PKEY_missing_parameters(const EVP_PKEY *pkey);
+
+/* EVP_PKEY_size returns the "size", in bytes, of |pkey|. For example, for an
+ * RSA key this returns the number of bytes needed to represent the modulus. */
+OPENSSL_EXPORT int EVP_PKEY_size(const EVP_PKEY *pkey);
+
+/* EVP_PKEY_bits returns the "size", in bits, of |pkey|. For example, for an
+ * RSA key, this returns the bit length of the modulus. */
+OPENSSL_EXPORT int EVP_PKEY_bits(EVP_PKEY *pkey);
+
+/* EVP_PKEY_id returns the type of |pkey|, which is one of the |EVP_PKEY_*|
+ * values. */
+OPENSSL_EXPORT int EVP_PKEY_id(const EVP_PKEY *pkey);
+
+/* EVP_PKEY_type returns a canonicalised form of |NID|. For example,
+ * |EVP_PKEY_RSA2| will be turned into |EVP_PKEY_RSA|. */
+OPENSSL_EXPORT int EVP_PKEY_type(int nid);
+
+/* Deprecated: EVP_PKEY_new_mac_key allocates a fresh |EVP_PKEY| of the given
+ * type (e.g. |EVP_PKEY_HMAC|), sets |mac_key| as the MAC key and "generates" a
+ * new key, suitable for signing. It returns the fresh |EVP_PKEY|, or NULL on
+ * error. Use |HMAC_CTX| directly instead. */
+OPENSSL_EXPORT EVP_PKEY *EVP_PKEY_new_mac_key(int type, ENGINE *engine,
+ const uint8_t *mac_key,
+ size_t mac_key_len);
+
+
+/* Getting and setting concrete public key types.
+ *
+ * The following functions get and set the underlying public key in an
+ * |EVP_PKEY| object. The |set1| functions take an additional reference to the
+ * underlying key and return one on success or zero on error. The |assign|
+ * functions adopt the caller's reference. The getters return a fresh reference
+ * to the underlying object. */
+
+OPENSSL_EXPORT int EVP_PKEY_set1_RSA(EVP_PKEY *pkey, RSA *key);
+OPENSSL_EXPORT int EVP_PKEY_assign_RSA(EVP_PKEY *pkey, RSA *key);
+OPENSSL_EXPORT RSA *EVP_PKEY_get1_RSA(EVP_PKEY *pkey);
+
+OPENSSL_EXPORT int EVP_PKEY_set1_DSA(EVP_PKEY *pkey, struct dsa_st *key);
+OPENSSL_EXPORT int EVP_PKEY_assign_DSA(EVP_PKEY *pkey, DSA *key);
+OPENSSL_EXPORT struct dsa_st *EVP_PKEY_get1_DSA(EVP_PKEY *pkey);
+
+OPENSSL_EXPORT int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, struct ec_key_st *key);
+OPENSSL_EXPORT int EVP_PKEY_assign_EC_KEY(EVP_PKEY *pkey, EC_KEY *key);
+OPENSSL_EXPORT struct ec_key_st *EVP_PKEY_get1_EC_KEY(EVP_PKEY *pkey);
+
+OPENSSL_EXPORT int EVP_PKEY_set1_DH(EVP_PKEY *pkey, struct dh_st *key);
+OPENSSL_EXPORT int EVP_PKEY_assign_DH(EVP_PKEY *pkey, DH *key);
+OPENSSL_EXPORT struct dh_st *EVP_PKEY_get1_DH(EVP_PKEY *pkey);
+
+#define EVP_PKEY_NONE NID_undef
+#define EVP_PKEY_RSA NID_rsaEncryption
+#define EVP_PKEY_RSA2 NID_rsa
+#define EVP_PKEY_DSA NID_dsa
+#define EVP_PKEY_DH NID_dhKeyAgreement
+#define EVP_PKEY_DHX NID_dhpublicnumber
+#define EVP_PKEY_EC NID_X9_62_id_ecPublicKey
+
+/* Deprecated: Use |HMAC_CTX| directly instead. */
+#define EVP_PKEY_HMAC NID_hmac
+
+/* EVP_PKEY_assign sets the underlying key of |pkey| to |key|, which must be of
+ * the given type. The |type| argument should be one of the |EVP_PKEY_*|
+ * values. */
+OPENSSL_EXPORT int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key);
+
+/* EVP_PKEY_set_type sets the type of |pkey| to |type|, which should be one of
+ * the |EVP_PKEY_*| values. It returns one if sucessful or zero otherwise. If
+ * |pkey| is NULL, it simply reports whether the type is known. */
+OPENSSL_EXPORT int EVP_PKEY_set_type(EVP_PKEY *pkey, int type);
+
+/* EVP_PKEY_cmp_parameters compares the parameters of |a| and |b|. It returns
+ * one if they match, zero if not, or a negative number of on error.
+ *
+ * WARNING: the return value differs from the usual return value convention. */
+OPENSSL_EXPORT int EVP_PKEY_cmp_parameters(const EVP_PKEY *a,
+ const EVP_PKEY *b);
+
+
+/* ASN.1 functions */
+
+/* d2i_PrivateKey parses an ASN.1, DER-encoded, private key from |len| bytes at
+ * |*inp|. If |out| is not NULL then, on exit, a pointer to the result is in
+ * |*out|. If |*out| is already non-NULL on entry then the result is written
+ * directly into |*out|, otherwise a fresh |EVP_PKEY| is allocated. On
+ * successful exit, |*inp| is advanced past the DER structure. It returns the
+ * result or NULL on error. */
+OPENSSL_EXPORT EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **out,
+ const uint8_t **inp, long len);
+
+/* d2i_AutoPrivateKey acts the same as |d2i_PrivateKey|, but detects the type
+ * of the private key. */
+OPENSSL_EXPORT EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **out, const uint8_t **inp,
+ long len);
+
+/* i2d_PrivateKey marshals a private key from |key| to an ASN.1, DER
+ * structure. If |outp| is not NULL then the result is written to |*outp| and
+ * |*outp| is advanced just past the output. It returns the number of bytes in
+ * the result, whether written or not, or a negative value on error. */
+OPENSSL_EXPORT int i2d_PrivateKey(const EVP_PKEY *key, uint8_t **outp);
+
+/* i2d_PublicKey marshals a public key from |key| to an ASN.1, DER
+ * structure. If |outp| is not NULL then the result is written to |*outp| and
+ * |*outp| is advanced just past the output. It returns the number of bytes in
+ * the result, whether written or not, or a negative value on error. */
+OPENSSL_EXPORT int i2d_PublicKey(EVP_PKEY *key, uint8_t **outp);
+
+
+/* Signing */
+
+/* EVP_DigestSignInit sets up |ctx| for a signing operation with |type| and
+ * |pkey|. The |ctx| argument must have been initialised with
+ * |EVP_MD_CTX_init|. If |pctx| is not NULL, the |EVP_PKEY_CTX| of the signing
+ * operation will be written to |*pctx|; this can be used to set alternative
+ * signing options.
+ *
+ * It returns one on success, or zero on error. */
+OPENSSL_EXPORT int EVP_DigestSignInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
+ const EVP_MD *type, ENGINE *e,
+ EVP_PKEY *pkey);
+
+/* EVP_DigestSignUpdate appends |len| bytes from |data| to the data which will
+ * be signed in |EVP_DigestSignFinal|. It returns one on success and zero
+ * otherwise. */
+OPENSSL_EXPORT int EVP_DigestSignUpdate(EVP_MD_CTX *ctx, const void *data,
+ size_t len);
+
+/* EVP_DigestSignFinal signs the data that has been included by one or more
+ * calls to |EVP_DigestSignUpdate|. If |out_sig| is NULL then |*out_sig_len| is
+ * set to the maximum number of output bytes. Otherwise, on entry,
+ * |*out_sig_len| must contain the length of the |out_sig| buffer. If the call
+ * is successful, the signature is written to |out_sig| and |*out_sig_len| is
+ * set to its length.
+ *
+ * It returns one on success, or zero on error. */
+OPENSSL_EXPORT int EVP_DigestSignFinal(EVP_MD_CTX *ctx, uint8_t *out_sig,
+ size_t *out_sig_len);
+
+/* EVP_DigestSignAlgorithm encodes the signing parameters of |ctx| as an
+ * AlgorithmIdentifer and saves the result in |algor|.
+ *
+ * It returns one on success, or zero on error.
+ *
+ * TODO(davidben): This API should eventually lose the dependency on
+ * crypto/asn1/. */
+OPENSSL_EXPORT int EVP_DigestSignAlgorithm(EVP_MD_CTX *ctx, X509_ALGOR *algor);
+
+
+/* Verifying */
+
+/* EVP_DigestVerifyInit sets up |ctx| for a signature verification operation
+ * with |type| and |pkey|. The |ctx| argument must have been initialised with
+ * |EVP_MD_CTX_init|. If |pctx| is not NULL, the |EVP_PKEY_CTX| of the signing
+ * operation will be written to |*pctx|; this can be used to set alternative
+ * signing options.
+ *
+ * It returns one on success, or zero on error. */
+OPENSSL_EXPORT int EVP_DigestVerifyInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
+ const EVP_MD *type, ENGINE *e,
+ EVP_PKEY *pkey);
+
+/* EVP_DigestVerifyInitFromAlgorithm sets up |ctx| for a signature verification
+ * operation with public key |pkey| and parameters from |algor|. The |ctx|
+ * argument must have been initialised with |EVP_MD_CTX_init|.
+ *
+ * It returns one on success, or zero on error.
+ *
+ * TODO(davidben): This API should eventually lose the dependency on
+ * crypto/asn1/. */
+OPENSSL_EXPORT int EVP_DigestVerifyInitFromAlgorithm(EVP_MD_CTX *ctx,
+ X509_ALGOR *algor,
+ EVP_PKEY *pkey);
+
+/* EVP_DigestVerifyUpdate appends |len| bytes from |data| to the data which
+ * will be verified by |EVP_DigestVerifyFinal|. It returns one on success and
+ * zero otherwise. */
+OPENSSL_EXPORT int EVP_DigestVerifyUpdate(EVP_MD_CTX *ctx, const void *data,
+ size_t len);
+
+/* EVP_DigestVerifyFinal verifies that |sig_len| bytes of |sig| are a valid
+ * signature for the data that has been included by one or more calls to
+ * |EVP_DigestVerifyUpdate|. It returns one on success and zero otherwise. */
+OPENSSL_EXPORT int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const uint8_t *sig,
+ size_t sig_len);
+
+
+/* Signing (old functions) */
+
+/* EVP_SignInit_ex configures |ctx|, which must already have been initialised,
+ * for a fresh signing operation using the hash function |type|. It returns one
+ * on success and zero otherwise.
+ *
+ * (In order to initialise |ctx|, either obtain it initialised with
+ * |EVP_MD_CTX_create|, or use |EVP_MD_CTX_init|.) */
+OPENSSL_EXPORT int EVP_SignInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type,
+ ENGINE *impl);
+
+/* EVP_SignInit is a deprecated version of |EVP_SignInit_ex|.
+ *
+ * TODO(fork): remove. */
+OPENSSL_EXPORT int EVP_SignInit(EVP_MD_CTX *ctx, const EVP_MD *type);
+
+/* EVP_SignUpdate appends |len| bytes from |data| to the data which will be
+ * signed in |EVP_SignFinal|. */
+OPENSSL_EXPORT int EVP_SignUpdate(EVP_MD_CTX *ctx, const void *data,
+ size_t len);
+
+/* EVP_SignFinal signs the data that has been included by one or more calls to
+ * |EVP_SignUpdate|, using the key |pkey|, and writes it to |sig|. On entry,
+ * |sig| must point to at least |EVP_PKEY_size(pkey)| bytes of space. The
+ * actual size of the signature is written to |*out_sig_len|.
+ *
+ * It returns one on success and zero otherwise.
+ *
+ * It does not modify |ctx|, thus it's possible to continue to use |ctx| in
+ * order to sign a longer message. */
+OPENSSL_EXPORT int EVP_SignFinal(const EVP_MD_CTX *ctx, uint8_t *sig,
+ unsigned int *out_sig_len, EVP_PKEY *pkey);
+
+
+/* Verifying (old functions) */
+
+/* EVP_VerifyInit_ex configures |ctx|, which must already have been
+ * initialised, for a fresh signature verification operation using the hash
+ * function |type|. It returns one on success and zero otherwise.
+ *
+ * (In order to initialise |ctx|, either obtain it initialised with
+ * |EVP_MD_CTX_create|, or use |EVP_MD_CTX_init|.) */
+OPENSSL_EXPORT int EVP_VerifyInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type,
+ ENGINE *impl);
+
+/* EVP_VerifyInit is a deprecated version of |EVP_VerifyInit_ex|.
+ *
+ * TODO(fork): remove. */
+OPENSSL_EXPORT int EVP_VerifyInit(EVP_MD_CTX *ctx, const EVP_MD *type);
+
+/* EVP_VerifyUpdate appends |len| bytes from |data| to the data which will be
+ * signed in |EVP_VerifyFinal|. */
+OPENSSL_EXPORT int EVP_VerifyUpdate(EVP_MD_CTX *ctx, const void *data,
+ size_t len);
+
+/* EVP_VerifyFinal verifies that |sig_len| bytes of |sig| are a valid
+ * signature, by |pkey|, for the data that has been included by one or more
+ * calls to |EVP_VerifyUpdate|.
+ *
+ * It returns one on success and zero otherwise.
+ *
+ * It does not modify |ctx|, thus it's possible to continue to use |ctx| in
+ * order to sign a longer message. */
+OPENSSL_EXPORT int EVP_VerifyFinal(EVP_MD_CTX *ctx, const uint8_t *sig,
+ size_t sig_len, EVP_PKEY *pkey);
+
+
+/* Printing */
+
+/* EVP_PKEY_print_public prints a textual representation of the public key in
+ * |pkey| to |out|. Returns one on success or zero otherwise. */
+OPENSSL_EXPORT int EVP_PKEY_print_public(BIO *out, const EVP_PKEY *pkey,
+ int indent, ASN1_PCTX *pctx);
+
+/* EVP_PKEY_print_public prints a textual representation of the private key in
+ * |pkey| to |out|. Returns one on success or zero otherwise. */
+OPENSSL_EXPORT int EVP_PKEY_print_private(BIO *out, const EVP_PKEY *pkey,
+ int indent, ASN1_PCTX *pctx);
+
+/* EVP_PKEY_print_public prints a textual representation of the parameters in
+ * |pkey| to |out|. Returns one on success or zero otherwise. */
+OPENSSL_EXPORT int EVP_PKEY_print_params(BIO *out, const EVP_PKEY *pkey,
+ int indent, ASN1_PCTX *pctx);
+
+
+/* Password stretching.
+ *
+ * Password stretching functions take a low-entropy password and apply a slow
+ * function that results in a key suitable for use in symmetric
+ * cryptography. */
+
+/* PKCS5_PBKDF2_HMAC computes |iterations| iterations of PBKDF2 of |password|
+ * and |salt|, using |digest|, and outputs |key_len| bytes to |out_key|. It
+ * returns one on success and zero on error. */
+OPENSSL_EXPORT int PKCS5_PBKDF2_HMAC(const char *password, size_t password_len,
+ const uint8_t *salt, size_t salt_len,
+ unsigned iterations, const EVP_MD *digest,
+ size_t key_len, uint8_t *out_key);
+
+/* PKCS5_PBKDF2_HMAC_SHA1 is the same as PKCS5_PBKDF2_HMAC, but with |digest|
+ * fixed to |EVP_sha1|. */
+OPENSSL_EXPORT int PKCS5_PBKDF2_HMAC_SHA1(const char *password,
+ size_t password_len, const uint8_t *salt,
+ size_t salt_len, unsigned iterations,
+ size_t key_len, uint8_t *out_key);
+
+
+/* Public key contexts.
+ *
+ * |EVP_PKEY_CTX| objects hold the context of an operation (e.g. signing or
+ * encrypting) that uses a public key. */
+
+/* EVP_PKEY_CTX_new allocates a fresh |EVP_PKEY_CTX| for use with |pkey|. It
+ * returns the context or NULL on error. */
+OPENSSL_EXPORT EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e);
+
+/* EVP_PKEY_CTX_new allocates a fresh |EVP_PKEY_CTX| for a key of type |id|
+ * (e.g. |EVP_PKEY_HMAC|). This can be used for key generation where
+ * |EVP_PKEY_CTX_new| can't be used because there isn't an |EVP_PKEY| to pass
+ * it. It returns the context or NULL on error. */
+OPENSSL_EXPORT EVP_PKEY_CTX *EVP_PKEY_CTX_new_id(int id, ENGINE *e);
+
+/* EVP_KEY_CTX_free frees |ctx| and the data it owns. */
+OPENSSL_EXPORT void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx);
+
+/* EVP_PKEY_CTX_dup allocates a fresh |EVP_PKEY_CTX| and sets it equal to the
+ * state of |ctx|. It returns the fresh |EVP_PKEY_CTX| or NULL on error. */
+OPENSSL_EXPORT EVP_PKEY_CTX *EVP_PKEY_CTX_dup(EVP_PKEY_CTX *ctx);
+
+/* EVP_PKEY_CTX_get0_pkey returns the |EVP_PKEY| associated with |ctx|. */
+OPENSSL_EXPORT EVP_PKEY *EVP_PKEY_CTX_get0_pkey(EVP_PKEY_CTX *ctx);
+
+/* EVP_PKEY_CTX_set_app_data sets an opaque pointer on |ctx|. */
+OPENSSL_EXPORT void EVP_PKEY_CTX_set_app_data(EVP_PKEY_CTX *ctx, void *data);
+
+/* EVP_PKEY_CTX_get_app_data returns the opaque pointer from |ctx| that was
+ * previously set with |EVP_PKEY_CTX_set_app_data|, or NULL if none has been
+ * set. */
+OPENSSL_EXPORT void *EVP_PKEY_CTX_get_app_data(EVP_PKEY_CTX *ctx);
+
+/* EVP_PKEY_CTX_ctrl performs |cmd| on |ctx|. The |keytype| and |optype|
+ * arguments can be -1 to specify that any type and operation are acceptable,
+ * otherwise |keytype| must match the type of |ctx| and the bits of |optype|
+ * must intersect the operation flags set on |ctx|.
+ *
+ * The |p1| and |p2| arguments depend on the value of |cmd|.
+ *
+ * It returns -2 if |cmd| is not recognised, -1 on error or a |cmd| specific
+ * value otherwise. */
+OPENSSL_EXPORT int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype,
+ int cmd, int p1, void *p2);
+
+/* EVP_PKEY_sign_init initialises an |EVP_PKEY_CTX| for a signing operation. It
+ * should be called before |EVP_PKEY_sign|.
+ *
+ * It returns one on success or zero on error. */
+OPENSSL_EXPORT int EVP_PKEY_sign_init(EVP_PKEY_CTX *ctx);
+
+/* EVP_PKEY_sign signs |data_len| bytes from |data| using |ctx|. If |sig| is
+ * NULL, the maximum size of the signature is written to
+ * |out_sig_len|. Otherwise, |*sig_len| must contain the number of bytes of
+ * space available at |sig|. If sufficient, the signature will be written to
+ * |sig| and |*sig_len| updated with the true length.
+ *
+ * WARNING: Setting |sig| to NULL only gives the maximum size of the
+ * signature. The actual signature may be smaller.
+ *
+ * It returns one on success or zero on error. (Note: this differs from
+ * OpenSSL, which can also return negative values to indicate an error. ) */
+OPENSSL_EXPORT int EVP_PKEY_sign(EVP_PKEY_CTX *ctx, uint8_t *sig,
+ size_t *sig_len, const uint8_t *data,
+ size_t data_len);
+
+/* EVP_PKEY_verify_init initialises an |EVP_PKEY_CTX| for a signature
+ * verification operation. It should be called before |EVP_PKEY_verify|.
+ *
+ * It returns one on success or zero on error. */
+OPENSSL_EXPORT int EVP_PKEY_verify_init(EVP_PKEY_CTX *ctx);
+
+/* EVP_PKEY_verify verifies that |sig_len| bytes from |sig| are a valid signature
+ * for |data|.
+ *
+ * It returns one on success or zero on error. */
+OPENSSL_EXPORT int EVP_PKEY_verify(EVP_PKEY_CTX *ctx, const uint8_t *sig,
+ size_t sig_len, const uint8_t *data,
+ size_t data_len);
+
+/* EVP_PKEY_encrypt_init initialises an |EVP_PKEY_CTX| for an encryption
+ * operation. It should be called before |EVP_PKEY_encrypt|.
+ *
+ * It returns one on success or zero on error. */
+OPENSSL_EXPORT int EVP_PKEY_encrypt_init(EVP_PKEY_CTX *ctx);
+
+/* EVP_PKEY_encrypt encrypts |in_len| bytes from |in|. If |out| is NULL, the
+ * maximum size of the ciphertext is written to |out_len|. Otherwise, |*out_len|
+ * must contain the number of bytes of space available at |out|. If sufficient,
+ * the ciphertext will be written to |out| and |*out_len| updated with the true
+ * length.
+ *
+ * WARNING: Setting |out| to NULL only gives the maximum size of the
+ * ciphertext. The actual ciphertext may be smaller.
+ *
+ * It returns one on success or zero on error. */
+OPENSSL_EXPORT int EVP_PKEY_encrypt(EVP_PKEY_CTX *ctx, uint8_t *out,
+ size_t *out_len, const uint8_t *in,
+ size_t in_len);
+
+/* EVP_PKEY_decrypt_init initialises an |EVP_PKEY_CTX| for a decryption
+ * operation. It should be called before |EVP_PKEY_decrypt|.
+ *
+ * It returns one on success or zero on error. */
+OPENSSL_EXPORT int EVP_PKEY_decrypt_init(EVP_PKEY_CTX *ctx);
+
+/* EVP_PKEY_decrypt decrypts |in_len| bytes from |in|. If |out| is NULL, the
+ * maximum size of the plaintext is written to |out_len|. Otherwise, |*out_len|
+ * must contain the number of bytes of space available at |out|. If sufficient,
+ * the ciphertext will be written to |out| and |*out_len| updated with the true
+ * length.
+ *
+ * WARNING: Setting |out| to NULL only gives the maximum size of the
+ * plaintext. The actual plaintext may be smaller.
+ *
+ * It returns one on success or zero on error. */
+OPENSSL_EXPORT int EVP_PKEY_decrypt(EVP_PKEY_CTX *ctx, uint8_t *out,
+ size_t *out_len, const uint8_t *in,
+ size_t in_len);
+
+/* EVP_PKEY_derive_init initialises an |EVP_PKEY_CTX| for a key derivation
+ * operation. It should be called before |EVP_PKEY_derive_set_peer| and
+ * |EVP_PKEY_derive|.
+ *
+ * It returns one on success or zero on error. */
+OPENSSL_EXPORT int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx);
+
+/* EVP_PKEY_derive_set_peer sets the peer's key to be used for key derivation
+ * by |ctx| to |peer|. It should be called after |EVP_PKEY_derive_init|. (For
+ * example, this is used to set the peer's key in (EC)DH.) It returns one on
+ * success and zero on error. */
+OPENSSL_EXPORT int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer);
+
+/* EVP_PKEY_derive derives a shared key between the two keys configured in
+ * |ctx|. If |key| is non-NULL then, on entry, |out_key_len| must contain the
+ * amount of space at |key|. If sufficient then the shared key will be written
+ * to |key| and |*out_key_len| will be set to the length. If |key| is NULL then
+ * |out_key_len| will be set to the maximum length.
+ *
+ * WARNING: Setting |out| to NULL only gives the maximum size of the key. The
+ * actual key may be smaller.
+ *
+ * It returns one on success and zero on error. */
+OPENSSL_EXPORT int EVP_PKEY_derive(EVP_PKEY_CTX *ctx, uint8_t *key,
+ size_t *out_key_len);
+
+/* EVP_PKEY_keygen_init initialises an |EVP_PKEY_CTX| for a key generation
+ * operation. It should be called before |EVP_PKEY_keygen|.
+ *
+ * It returns one on success or zero on error. */
+OPENSSL_EXPORT int EVP_PKEY_keygen_init(EVP_PKEY_CTX *ctx);
+
+/* EVP_PKEY_keygen performs a key generation operation using the values from
+ * |ctx| and sets |*ppkey| to a fresh |EVP_PKEY| containing the resulting key.
+ * It returns one on success or zero on error. */
+OPENSSL_EXPORT int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey);
+
+
+/* EVP_PKEY_CTX_ctrl operations.
+ *
+ * These values are passed as the |cmd| argument to
+ * EVP_PKEY_CTX_ctrl */
+
+/* Generic. */
+
+/* EVP_PKEY_CTX_set_signature_md sets |md| as the digest to be used in a
+ * signature operation. It returns one on success or otherwise on error. See
+ * the return values of |EVP_PKEY_CTX_ctrl| for details. */
+OPENSSL_EXPORT int EVP_PKEY_CTX_set_signature_md(EVP_PKEY_CTX *ctx,
+ const EVP_MD *md);
+
+/* EVP_PKEY_CTX_get_signature_md sets |*out_md| to the digest to be used in a
+ * signature operation. It returns one on success or otherwise on error. See
+ * the return values of |EVP_PKEY_CTX_ctrl| for details. */
+OPENSSL_EXPORT int EVP_PKEY_CTX_get_signature_md(EVP_PKEY_CTX *ctx,
+ const EVP_MD **out_md);
+
+/* EVP_PKEY_CTRL_DIGESTINIT is an internal value. It's called by
+ * EVP_DigestInit_ex to signal the |EVP_PKEY| that a digest operation is
+ * starting. */
+#define EVP_PKEY_CTRL_DIGESTINIT 3
+
+/* EVP_PKEY_CTRL_PEER_KEY is called with different values of |p1|:
+ * 0: Is called from |EVP_PKEY_derive_set_peer| and |p2| contains a peer key.
+ * If the return value is <= 0, the key is rejected.
+ * 1: Is called at the end of |EVP_PKEY_derive_set_peer| and |p2| contains a
+ * peer key. If the return value is <= 0, the key is rejected.
+ * 2: Is called with |p2| == NULL to test whether the peer's key was used.
+ * (EC)DH always return one in this case.
+ * 3: Is called with |p2| == NULL to set whether the peer's key was used.
+ * (EC)DH always return one in this case. This was only used for GOST. */
+#define EVP_PKEY_CTRL_PEER_KEY 4
+
+/* EVP_PKEY_CTRL_SET_MAC_KEY sets a MAC key. For example, this can be done an
+ * |EVP_PKEY_CTX| prior to calling |EVP_PKEY_keygen| in order to generate an
+ * HMAC |EVP_PKEY| with the given key. It returns one on success and zero on
+ * error. */
+#define EVP_PKEY_CTRL_SET_MAC_KEY 5
+
+/* EVP_PKEY_ALG_CTRL is the base value from which key-type specific ctrl
+ * commands are numbered. */
+#define EVP_PKEY_ALG_CTRL 0x1000
+
+
+/* RSA specific control functions. */
+
+/* EVP_PKEY_CTX_set_rsa_padding sets the padding type to use. It should be one
+ * of the |RSA_*_PADDING| values. Returns one on success or another value on
+ * error. See |EVP_PKEY_CTX_ctrl| for the other return values, which are
+ * non-standard. */
+OPENSSL_EXPORT int EVP_PKEY_CTX_set_rsa_padding(EVP_PKEY_CTX *ctx, int padding);
+
+/* EVP_PKEY_CTX_get_rsa_padding sets |*out_padding| to the current padding
+ * value, which is one of the |RSA_*_PADDING| values. Returns one on success or
+ * another value on error. See |EVP_PKEY_CTX_ctrl| for the other return values,
+ * which are non-standard. */
+OPENSSL_EXPORT int EVP_PKEY_CTX_get_rsa_padding(EVP_PKEY_CTX *ctx,
+ int *out_padding);
+
+/* EVP_PKEY_CTX_set_rsa_pss_saltlen sets the length of the salt in a PSS-padded
+ * signature. A value of -1 cause the salt to be the same length as the digest
+ * in the signature. A value of -2 causes the salt to be the maximum length
+ * that will fit. Otherwise the value gives the size of the salt in bytes.
+ *
+ * Returns one on success or another value on error. See |EVP_PKEY_CTX_ctrl|
+ * for the other return values, which are non-standard. */
+OPENSSL_EXPORT int EVP_PKEY_CTX_set_rsa_pss_saltlen(EVP_PKEY_CTX *ctx,
+ int salt_len);
+
+/* EVP_PKEY_CTX_get_rsa_pss_saltlen sets |*out_salt_len| to the salt length of
+ * a PSS-padded signature. See the documentation for
+ * |EVP_PKEY_CTX_set_rsa_pss_saltlen| for details of the special values that it
+ * can take.
+ *
+ * Returns one on success or another value on error. See |EVP_PKEY_CTX_ctrl|
+ * for the other return values, which are non-standard. */
+OPENSSL_EXPORT int EVP_PKEY_CTX_get_rsa_pss_saltlen(EVP_PKEY_CTX *ctx,
+ int *out_salt_len);
+
+/* EVP_PKEY_CTX_set_rsa_keygen_bits sets the size of the desired RSA modulus,
+ * in bits, for key generation. Returns one on success or another value on
+ * error. See |EVP_PKEY_CTX_ctrl| for the other return values, which are
+ * non-standard. */
+OPENSSL_EXPORT int EVP_PKEY_CTX_set_rsa_keygen_bits(EVP_PKEY_CTX *ctx,
+ int bits);
+
+/* EVP_PKEY_CTX_set_rsa_keygen_pubexp sets |e| as the public exponent for key
+ * generation. Returns one on success or another value on error. See
+ * |EVP_PKEY_CTX_ctrl| for the other return values, which are non-standard. */
+OPENSSL_EXPORT int EVP_PKEY_CTX_set_rsa_keygen_pubexp(EVP_PKEY_CTX *ctx,
+ BIGNUM *e);
+
+/* EVP_PKEY_CTX_set_rsa_oaep_md sets |md| as the digest used in OAEP padding.
+ * Returns one on success or another value on error. See |EVP_PKEY_CTX_ctrl|
+ * for the other return values, which are non-standard. */
+OPENSSL_EXPORT int EVP_PKEY_CTX_set_rsa_oaep_md(EVP_PKEY_CTX *ctx,
+ const EVP_MD *md);
+
+/* EVP_PKEY_CTX_get_rsa_oaep_md sets |*out_md| to the digest function used in
+ * OAEP padding. Returns one on success or another value on error. See
+ * |EVP_PKEY_CTX_ctrl| for the other return values, which are non-standard. */
+OPENSSL_EXPORT int EVP_PKEY_CTX_get_rsa_oaep_md(EVP_PKEY_CTX *ctx,
+ const EVP_MD **out_md);
+
+/* EVP_PKEY_CTX_set_rsa_mgf1_md sets |md| as the digest used in MGF1. Returns
+ * one on success or another value on error. See |EVP_PKEY_CTX_ctrl| for the
+ * other return values, which are non-standard. */
+OPENSSL_EXPORT int EVP_PKEY_CTX_set_rsa_mgf1_md(EVP_PKEY_CTX *ctx,
+ const EVP_MD *md);
+
+/* EVP_PKEY_CTX_get_rsa_mgf1_md sets |*out_md| to the digest function used in
+ * MGF1. Returns one on success or another value on error. See
+ * |EVP_PKEY_CTX_ctrl| for the other return values, which are non-standard. */
+OPENSSL_EXPORT int EVP_PKEY_CTX_get_rsa_mgf1_md(EVP_PKEY_CTX *ctx,
+ const EVP_MD **out_md);
+
+/* EVP_PKEY_CTX_set0_rsa_oaep_label sets |label_len| bytes from |label| as the
+ * label used in OAEP. DANGER: this call takes ownership of |label| and will
+ * call |free| on it when |ctx| is destroyed.
+ *
+ * Returns one on success or another value on error. See |EVP_PKEY_CTX_ctrl|
+ * for the other return values, which are non-standard. */
+OPENSSL_EXPORT int EVP_PKEY_CTX_set0_rsa_oaep_label(EVP_PKEY_CTX *ctx,
+ const uint8_t *label,
+ size_t label_len);
+
+/* EVP_PKEY_CTX_get0_rsa_oaep_label sets |*out_label| to point to the internal
+ * buffer containing the OAEP label (which may be NULL) and returns the length
+ * of the label or a negative value on error. */
+OPENSSL_EXPORT int EVP_PKEY_CTX_get0_rsa_oaep_label(EVP_PKEY_CTX *ctx,
+ const uint8_t **out_label);
+
+
+/* EC specific */
+
+#define EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID (EVP_PKEY_ALG_CTRL + 1)
+
+
+/* Private functions */
+
+/* OpenSSL_add_all_algorithms does nothing. */
+OPENSSL_EXPORT void OpenSSL_add_all_algorithms(void);
+
+/* EVP_cleanup does nothing. */
+OPENSSL_EXPORT void EVP_cleanup(void);
+
+/* EVP_PKEY_asn1_find returns the ASN.1 method table for the given |nid|, which
+ * should be one of the |EVP_PKEY_*| values. It returns NULL if |nid| is
+ * unknown. */
+OPENSSL_EXPORT const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find(ENGINE **pengine,
+ int nid);
+
+/* TODO(fork): move to PEM? */
+OPENSSL_EXPORT const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find_str(
+ ENGINE **pengine, const char *name, size_t len);
+
+struct evp_pkey_st {
+ int references;
+
+ /* type contains one of the EVP_PKEY_* values or NID_undef and determines
+ * which element (if any) of the |pkey| union is valid. */
+ int type;
+
+ /* TODO(fork): document */
+ int save_type;
+
+ union {
+ char *ptr;
+ struct rsa_st *rsa; /* RSA */
+ struct dsa_st *dsa; /* DSA */
+ struct dh_st *dh; /* DH */
+ struct ec_key_st *ec; /* ECC */
+ } pkey;
+
+ ENGINE *engine;
+
+ /* TODO(fork): document */
+ int save_parameters;
+ /* ameth contains a pointer to a method table that contains many ASN.1
+ * methods for the key type. */
+ const EVP_PKEY_ASN1_METHOD *ameth;
+
+ /* TODO(fork): document; */
+ STACK_OF(X509_ATTRIBUTE) * attributes; /* [ 0 ] */
+} /* EVP_PKEY */;
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#define EVP_F_rsa_item_verify 100
+#define EVP_F_do_sigver_init 101
+#define EVP_F_eckey_priv_decode 102
+#define EVP_F_pkey_ec_sign 103
+#define EVP_F_EVP_PKEY_sign_init 104
+#define EVP_F_d2i_PrivateKey 105
+#define EVP_F_rsa_priv_encode 106
+#define EVP_F_rsa_mgf1_to_md 107
+#define EVP_F_EVP_PKEY_get1_DH 108
+#define EVP_F_EVP_PKEY_sign 109
+#define EVP_F_old_ec_priv_decode 110
+#define EVP_F_EVP_PKEY_get1_RSA 111
+#define EVP_F_pkey_ec_ctrl 112
+#define EVP_F_evp_pkey_ctx_new 113
+#define EVP_F_EVP_PKEY_verify 114
+#define EVP_F_EVP_PKEY_encrypt 115
+#define EVP_F_EVP_PKEY_keygen 116
+#define EVP_F_eckey_type2param 117
+#define EVP_F_eckey_priv_encode 118
+#define EVP_F_do_EC_KEY_print 119
+#define EVP_F_pkey_ec_keygen 120
+#define EVP_F_EVP_PKEY_encrypt_init 121
+#define EVP_F_pkey_rsa_ctrl 122
+#define EVP_F_rsa_priv_decode 123
+#define EVP_F_rsa_pss_to_ctx 124
+#define EVP_F_EVP_PKEY_get1_EC_KEY 125
+#define EVP_F_EVP_PKEY_verify_init 126
+#define EVP_F_EVP_PKEY_derive_init 127
+#define EVP_F_eckey_param2type 128
+#define EVP_F_eckey_pub_decode 129
+#define EVP_F_d2i_AutoPrivateKey 130
+#define EVP_F_eckey_param_decode 131
+#define EVP_F_EVP_PKEY_new 132
+#define EVP_F_pkey_ec_derive 133
+#define EVP_F_pkey_ec_paramgen 134
+#define EVP_F_EVP_PKEY_CTX_ctrl 135
+#define EVP_F_EVP_PKEY_decrypt_init 136
+#define EVP_F_EVP_PKEY_decrypt 137
+#define EVP_F_EVP_PKEY_copy_parameters 138
+#define EVP_F_EVP_PKEY_set_type 139
+#define EVP_F_EVP_PKEY_derive 140
+#define EVP_F_EVP_PKEY_keygen_init 141
+#define EVP_F_do_rsa_print 142
+#define EVP_F_old_rsa_priv_decode 143
+#define EVP_F_rsa_algor_to_md 144
+#define EVP_F_eckey_pub_encode 145
+#define EVP_F_EVP_PKEY_derive_set_peer 146
+#define EVP_F_pkey_rsa_sign 147
+#define EVP_F_check_padding_md 148
+#define EVP_F_i2d_PublicKey 149
+#define EVP_F_rsa_pub_decode 150
+#define EVP_F_EVP_PKEY_get1_DSA 151
+#define EVP_F_pkey_rsa_encrypt 152
+#define EVP_F_pkey_rsa_decrypt 153
+#define EVP_F_hmac_signctx 154
+#define EVP_F_EVP_DigestVerifyInitFromAlgorithm 155
+#define EVP_F_EVP_DigestSignAlgorithm 156
+#define EVP_F_rsa_digest_verify_init_from_algorithm 157
+#define EVP_F_EVP_PKEY_CTX_dup 158
+#define EVP_R_UNSUPPORTED_PUBLIC_KEY_TYPE 100
+#define EVP_R_UNSUPPORTED_SIGNATURE_TYPE 101
+#define EVP_R_INVALID_DIGEST_TYPE 102
+#define EVP_R_EXPECTING_A_DH_KEY 103
+#define EVP_R_OPERATON_NOT_INITIALIZED 104
+#define EVP_R_MISSING_PARAMETERS 105
+#define EVP_R_NO_DEFAULT_DIGEST 106
+#define EVP_R_UNKNOWN_DIGEST 107
+#define EVP_R_KEYS_NOT_SET 108
+#define EVP_R_X931_UNSUPPORTED 109
+#define EVP_R_DIGEST_DOES_NOT_MATCH 110
+#define EVP_R_DIFFERENT_PARAMETERS 111
+#define EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE 112
+#define EVP_R_DIFFERENT_KEY_TYPES 113
+#define EVP_R_NO_PARAMETERS_SET 114
+#define EVP_R_NO_NID_FOR_CURVE 115
+#define EVP_R_NO_OPERATION_SET 116
+#define EVP_R_UNSUPPORTED_ALGORITHM 117
+#define EVP_R_EXPECTING_AN_DSA_KEY 118
+#define EVP_R_UNKNOWN_MASK_DIGEST 119
+#define EVP_R_INVALID_SALT_LENGTH 120
+#define EVP_R_BUFFER_TOO_SMALL 121
+#define EVP_R_INVALID_PADDING_MODE 122
+#define EVP_R_INVALID_MGF1_MD 123
+#define EVP_R_SHARED_INFO_ERROR 124
+#define EVP_R_INVALID_KEYBITS 125
+#define EVP_R_PEER_KEY_ERROR 126
+#define EVP_R_EXPECTING_A_DSA_KEY 127
+#define EVP_R_UNSUPPORTED_MASK_ALGORITHM 128
+#define EVP_R_EXPECTING_AN_EC_KEY_KEY 129
+#define EVP_R_INVALID_TRAILER 130
+#define EVP_R_INVALID_DIGEST_LENGTH 131
+#define EVP_R_COMMAND_NOT_SUPPORTED 132
+#define EVP_R_EXPLICIT_EC_PARAMETERS_NOT_SUPPORTED 133
+#define EVP_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE 134
+#define EVP_R_NO_MDC2_SUPPORT 135
+#define EVP_R_INVALID_CURVE 136
+#define EVP_R_NO_KEY_SET 137
+#define EVP_R_INVALID_PSS_PARAMETERS 138
+#define EVP_R_KDF_PARAMETER_ERROR 139
+#define EVP_R_UNSUPPORTED_MASK_PARAMETER 140
+#define EVP_R_EXPECTING_AN_RSA_KEY 141
+#define EVP_R_INVALID_OPERATION 142
+#define EVP_R_DECODE_ERROR 143
+#define EVP_R_INVALID_PSS_SALTLEN 144
+#define EVP_R_UNKNOWN_PUBLIC_KEY_TYPE 145
+#define EVP_R_CONTEXT_NOT_INITIALISED 146
+#define EVP_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED 147
+#define EVP_R_WRONG_PUBLIC_KEY_TYPE 148
+#define EVP_R_UNKNOWN_SIGNATURE_ALGORITHM 149
+#define EVP_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM 150
+
+#endif /* OPENSSL_HEADER_EVP_H */
diff --git a/src/include/openssl/ex_data.h b/src/include/openssl/ex_data.h
new file mode 100644
index 0000000..f61501a
--- /dev/null
+++ b/src/include/openssl/ex_data.h
@@ -0,0 +1,300 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 OPENSSL_HEADER_EX_DATA_H
+#define OPENSSL_HEADER_EX_DATA_H
+
+#include <openssl/base.h>
+
+#include <openssl/stack.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* ex_data is a mechanism for associating arbitrary extra data with objects.
+ * The different types of objects which can have data associated with them are
+ * called "classes" and there are predefined classes for all the OpenSSL
+ * objects that support ex_data.
+ *
+ * Within a given class, different users can be assigned indexes in which to
+ * store their data. Each index has callback functions that are called when a
+ * new object of that type is created, freed and duplicated. */
+
+
+typedef struct crypto_ex_data_st CRYPTO_EX_DATA;
+
+/* CRYPTO_EX_new is the type of a callback function that is called whenever a
+ * new object of a given class is created. For example, if this callback has
+ * been passed to |CRYPTO_get_ex_new_index| with a |class| of
+ * |CRYPTO_EX_INDEX_SSL| then it'll be called each time an SSL* is created.
+ *
+ * The callback is passed the new object (i.e. the SSL*) in |parent|. The
+ * arguments |argl| and |argp| contain opaque values that were given to
+ * |CRYPTO_get_ex_new_index|. The callback should return one on success, but
+ * the value is ignored.
+ *
+ * TODO(fork): the |ptr| argument is always NULL, no? */
+typedef int CRYPTO_EX_new(void *parent, void *ptr, CRYPTO_EX_DATA *ad,
+ int index, long argl, void *argp);
+
+/* CRYPTO_EX_free is a callback function that is called when an object of the
+ * class is being destroyed. See |CRYPTO_EX_new| for a discussion of the
+ * arguments.
+ *
+ * If |CRYPTO_get_ex_new_index| was called after the creation of objects of the
+ * class that this applies to then, when those those objects are destroyed,
+ * this callback will be called with a NULL value for |ptr|. */
+typedef void CRYPTO_EX_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad,
+ int index, long argl, void *argp);
+
+/* CRYPTO_EX_dup is a callback function that is called when an object of the
+ * class is being copied and thus the ex_data linked to it also needs to be
+ * copied. On entry, |*from_d| points to the data for this index from the
+ * original object. When the callback returns, |*from_d| will be set as the
+ * data for this index in |to|.
+ *
+ * If |CRYPTO_get_ex_new_index| was called after the creation of objects of the
+ * class that this applies to then, when those those objects are copies, this
+ * callback will be called with a NULL value for |*from_d|. */
+typedef int CRYPTO_EX_dup(CRYPTO_EX_DATA *to, const CRYPTO_EX_DATA *from,
+ void **from_d, int index, long argl, void *argp);
+
+/* CRYPTO_get_ex_new_index allocates a new index for ex_data linked with
+ * objects of the given |class|. This should not be called directly, rather
+ * each class of object should provide a wrapper function that sets
+ * |class_value| correctly.
+ *
+ * The |class_value| argument should be one of |CRYPTO_EX_INDEX_*| or a
+ * user-defined class value returned from |CRYPTO_ex_data_new_class|.
+ *
+ * See the descriptions of the callback typedefs for details of when they are
+ * called. Any of the callback arguments may be NULL. The |argl| and |argp|
+ * arguments are opaque values that are passed to the callbacks.
+ *
+ * It returns the new index, or a negative number on error.
+ *
+ * TODO(fork): this should follow the standard calling convention.
+ *
+ * TODO(fork): replace the class_value with a pointer to EX_CLASS_ITEM. Saves
+ * having that hash table and some of the lock-bouncing. Maybe have every
+ * module have a private global EX_CLASS_ITEM somewhere and any direct callers
+ * of CRYPTO_{get,set}_ex_data{,_index} would have to always call the
+ * wrappers. */
+OPENSSL_EXPORT int CRYPTO_get_ex_new_index(int class_value, long argl,
+ void *argp, CRYPTO_EX_new *new_func,
+ CRYPTO_EX_dup *dup_func,
+ CRYPTO_EX_free *free_func);
+
+/* CRYPTO_set_ex_data sets an extra data pointer on a given object. This should
+ * not be called directly, rather each class of object should provide a wrapper
+ * function.
+ *
+ * The |index| argument should have been returned from a previous call to
+ * |CRYPTO_get_ex_new_index|. */
+OPENSSL_EXPORT int CRYPTO_set_ex_data(CRYPTO_EX_DATA *ad, int index, void *val);
+
+/* CRYPTO_set_ex_data return an extra data pointer for a given object, or NULL
+ * if no such index exists. This should not be called directly, rather each
+ * class of object should provide a wrapper function.
+ *
+ * The |index| argument should have been returned from a previous call to
+ * |CRYPTO_get_ex_new_index|. */
+OPENSSL_EXPORT void *CRYPTO_get_ex_data(const CRYPTO_EX_DATA *ad, int index);
+
+/* CRYPTO_EX_INDEX_* are the built-in classes of objects.
+ *
+ * User defined classes start at 100.
+ *
+ * TODO(fork): WARNING: these are called "INDEX", but they aren't! */
+#define CRYPTO_EX_INDEX_BIO 0
+#define CRYPTO_EX_INDEX_SSL 1
+#define CRYPTO_EX_INDEX_SSL_CTX 2
+#define CRYPTO_EX_INDEX_SSL_SESSION 3
+#define CRYPTO_EX_INDEX_X509_STORE 4
+#define CRYPTO_EX_INDEX_X509_STORE_CTX 5
+#define CRYPTO_EX_INDEX_RSA 6
+#define CRYPTO_EX_INDEX_DSA 7
+#define CRYPTO_EX_INDEX_DH 8
+#define CRYPTO_EX_INDEX_ENGINE 9
+#define CRYPTO_EX_INDEX_X509 10
+#define CRYPTO_EX_INDEX_UI 11
+#define CRYPTO_EX_INDEX_EC_KEY 12
+#define CRYPTO_EX_INDEX_EC_GROUP 13
+#define CRYPTO_EX_INDEX_COMP 14
+#define CRYPTO_EX_INDEX_STORE 15
+
+
+/* User-defined classes of objects.
+ *
+ * Core OpenSSL code has predefined class values given above (the
+ * |CRYPTO_EX_INDEX_*| values). It's possible to get dynamic class values
+ * assigned for user-defined objects. */
+
+/* CRYPTO_ex_data_new_class returns a fresh class value for a user-defined type
+ * that wishes to use ex_data.
+ *
+ * TODO(fork): hopefully remove this. */
+OPENSSL_EXPORT int CRYPTO_ex_data_new_class(void);
+
+
+/* Embedding, allocating and freeing |CRYPTO_EX_DATA| structures for objects
+ * that embed them. */
+
+/* CRYPTO_new_ex_data initialises a newly allocated |CRYPTO_EX_DATA| which is
+ * embedded inside of |obj| which is of class |class_value|. Returns one on
+ * success and zero otherwise. */
+OPENSSL_EXPORT int CRYPTO_new_ex_data(int class_value, void *obj,
+ CRYPTO_EX_DATA *ad);
+
+/* CRYPTO_dup_ex_data duplicates |from| into a freshly allocated
+ * |CRYPTO_EX_DATA|, |to|. Both of which are inside objects of the given
+ * class. It returns one on success and zero otherwise. */
+OPENSSL_EXPORT int CRYPTO_dup_ex_data(int class_value, CRYPTO_EX_DATA *to,
+ const CRYPTO_EX_DATA *from);
+
+/* CRYPTO_free_ex_data frees |ad|, which is embedded inside |obj|, which is an
+ * object of the given class. */
+OPENSSL_EXPORT void CRYPTO_free_ex_data(int class_value, void *obj,
+ CRYPTO_EX_DATA *ad);
+
+
+/* Handling different ex_data implementations. */
+
+/* CRYPTO_EX_DATA_IMPL is the opaque type of an implementation of ex_data. */
+typedef struct st_CRYPTO_EX_DATA_IMPL CRYPTO_EX_DATA_IMPL;
+
+/* CRYPTO_get_ex_data_implementation returns the current implementation of
+ * ex_data. */
+OPENSSL_EXPORT const CRYPTO_EX_DATA_IMPL *CRYPTO_get_ex_data_implementation(
+ void);
+
+/* CRYPTO_set_ex_data_implementation sets the implementation of ex_data to use,
+ * unless ex_data has already been used and the default implementation
+ * installed. It returns one on success and zero otherwise. */
+OPENSSL_EXPORT int CRYPTO_set_ex_data_implementation(
+ const CRYPTO_EX_DATA_IMPL *impl);
+
+
+/* Private functions. */
+
+/* CRYPTO_cleanup_all_ex_data cleans up all ex_data state. It assumes that no
+ * other threads are executing code that might call ex_data functions. */
+OPENSSL_EXPORT void CRYPTO_cleanup_all_ex_data(void);
+
+struct crypto_ex_data_st {
+ STACK_OF(void) *sk;
+};
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_EX_DATA_H */
diff --git a/src/include/openssl/hkdf.h b/src/include/openssl/hkdf.h
new file mode 100644
index 0000000..4091b84
--- /dev/null
+++ b/src/include/openssl/hkdf.h
@@ -0,0 +1,45 @@
+/* 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 <openssl/base.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* 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. */
+OPENSSL_EXPORT 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);
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#define HKDF_F_HKDF 100
+#define HKDF_R_OUTPUT_TOO_LARGE 100
+
+#endif /* OPENSSL_HEADER_HKDF_H */
diff --git a/src/include/openssl/hmac.h b/src/include/openssl/hmac.h
new file mode 100644
index 0000000..6c34cdc
--- /dev/null
+++ b/src/include/openssl/hmac.h
@@ -0,0 +1,164 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 OPENSSL_HEADER_HMAC_H
+#define OPENSSL_HEADER_HMAC_H
+
+#include <openssl/base.h>
+
+#include <openssl/digest.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* HMAC contains functions for constructing PRFs from Merkle–Damgård hash
+ * functions using HMAC. */
+
+
+/* One-shot operation. */
+
+/* HMAC calculates the HMAC of |data_len| bytes of |data|, using the given key
+ * and hash function, and writes the result to |out|. On entry, |out| must
+ * contain |EVP_MAX_MD_SIZE| bytes of space. The actual length of the result is
+ * written to |*out_len|. It returns |out| or NULL on error. */
+OPENSSL_EXPORT uint8_t *HMAC(const EVP_MD *evp_md, const void *key,
+ size_t key_len, const uint8_t *data,
+ size_t data_len, uint8_t *out,
+ unsigned int *out_len);
+
+
+/* Incremental operation. */
+
+/* HMAC_CTX_init initialises |ctx| for use in an HMAC operation. It's assumed
+ * that HMAC_CTX objects will be allocated on the stack thus no allocation
+ * function is provided. If needed, allocate |sizeof(HMAC_CTX)| and call
+ * |HMAC_CTX_init| on it. */
+OPENSSL_EXPORT void HMAC_CTX_init(HMAC_CTX *ctx);
+
+/* HMAC_CTX_cleanup frees data owned by |ctx|. */
+OPENSSL_EXPORT void HMAC_CTX_cleanup(HMAC_CTX *ctx);
+
+/* HMAC_Init_ex sets up an initialised |HMAC_CTX| to use |md| as the hash
+ * function and |key| as the key. Any of |md| or |key| can be NULL, in which
+ * case the previous value will be used. It returns one on success or zero
+ * otherwise. */
+OPENSSL_EXPORT int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, size_t key_len,
+ const EVP_MD *md, ENGINE *impl);
+
+/* HMAC_Update hashes |data_len| bytes from |data| into the current HMAC
+ * operation in |ctx|. It returns one on success and zero on error. */
+OPENSSL_EXPORT int HMAC_Update(HMAC_CTX *ctx, const uint8_t *data,
+ size_t data_len);
+
+/* HMAC_Final completes the HMAC operation in |ctx| and writes the result to
+ * |out| and the sets |*out_len| to the length of the result. On entry, |out|
+ * must contain at least |EVP_MAX_MD_SIZE| bytes of space. It returns one on
+ * success or zero on error. */
+OPENSSL_EXPORT int HMAC_Final(HMAC_CTX *ctx, uint8_t *out,
+ unsigned int *out_len);
+
+
+/* Utility functions. */
+
+/* HMAC_size returns the size, in bytes, of the HMAC that will be produced by
+ * |ctx|. On entry, |ctx| must have been setup with |HMAC_Init_ex|. */
+OPENSSL_EXPORT size_t HMAC_size(const HMAC_CTX *ctx);
+
+/* HMAC_CTX_copy_ex sets |dest| equal to |src|. On entry, |dest| must have been
+ * initialised by calling |HMAC_CTX_init|. It returns one on success and zero
+ * on error. */
+OPENSSL_EXPORT int HMAC_CTX_copy_ex(HMAC_CTX *dest, const HMAC_CTX *src);
+
+/* HMAC_CTX_set_flags ORs |flags| into the flags of the underlying digests of
+ * |ctx|, which must have been setup by a call to |HMAC_Init_ex|. See
+ * |EVP_MD_CTX_set_flags|.
+ *
+ * TODO(fork): remove? */
+OPENSSL_EXPORT void HMAC_CTX_set_flags(HMAC_CTX *ctx, unsigned long flags);
+
+
+/* Deprecated functions. */
+
+OPENSSL_EXPORT int HMAC_Init(HMAC_CTX *ctx, const void *key, int key_len,
+ const EVP_MD *md);
+
+/* HMAC_CTX_copy calls |HMAC_CTX_init| on |dest| and then sets it equal to
+ * |src|. On entry, |dest| must /not/ be initialised for an operation with
+ * |HMAC_Init_ex|. It returns one on success and zero on error. */
+OPENSSL_EXPORT int HMAC_CTX_copy(HMAC_CTX *dest, const HMAC_CTX *src);
+
+
+/* Private functions */
+
+#define HMAC_MAX_MD_CBLOCK 128 /* largest known is SHA512 */
+
+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 */;
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_HMAC_H */
diff --git a/src/include/openssl/lhash.h b/src/include/openssl/lhash.h
new file mode 100644
index 0000000..c8628d1
--- /dev/null
+++ b/src/include/openssl/lhash.h
@@ -0,0 +1,194 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 OPENSSL_HEADER_LHASH_H
+#define OPENSSL_HEADER_LHASH_H
+
+#include <openssl/base.h>
+#include <openssl/type_check.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* lhash is a traditional, chaining hash table that automatically expands and
+ * contracts as needed. One should not use the lh_* functions directly, rather
+ * use the type-safe macro wrappers:
+ *
+ * A hash table of a specific type of object has type |LHASH_OF(type)|. This
+ * can be defined (once) with |DEFINE_LHASH_OF(type)| and declared where needed
+ * with |DECLARE_LHASH_OF(type)|. For example:
+ *
+ * struct foo {
+ * int bar;
+ * };
+ *
+ * DEFINE_LHASH_OF(struct foo);
+ *
+ * Although note that the hash table will contain /pointers/ to |foo|.
+ *
+ * A macro will be defined for each of the lh_* functions below. For
+ * LHASH_OF(foo), the macros would be lh_foo_new, lh_foo_num_items etc. */
+
+
+#define LHASH_OF(type) struct lhash_st_##type
+
+#define DEFINE_LHASH_OF(type) LHASH_OF(type) { int dummy; }
+
+#define DECLARE_LHASH_OF(type) LHASH_OF(type);
+
+/* The make_macros.sh script in this directory parses the following lines and
+ * generates the lhash_macros.h file that contains macros for the following
+ * types of stacks:
+ *
+ * LHASH_OF:ASN1_OBJECT
+ * LHASH_OF:CONF_VALUE
+ * LHASH_OF:ERR_STATE
+ * LHASH_OF:ERR_STRING_DATA
+ * LHASH_OF:EX_CLASS_ITEM
+ * LHASH_OF:SSL_SESSION */
+
+#define IN_LHASH_H
+#include <openssl/lhash_macros.h>
+#undef IN_LHASH_H
+
+
+/* lhash_item_st is an element of a hash chain. It points to the opaque data
+ * for this element and to the next item in the chain. The linked-list is NULL
+ * terminated. */
+typedef struct lhash_item_st {
+ void *data;
+ struct lhash_item_st *next;
+ /* hash contains the cached, hash value of |data|. */
+ uint32_t hash;
+} LHASH_ITEM;
+
+/* lhash_cmp_func is a comparison function that returns a value equal, or not
+ * equal, to zero depending on whether |*a| is equal, or not equal to |*b|,
+ * respectively. Note the difference between this and |stack_cmp_func| in that
+ * this takes pointers to the objects directly. */
+typedef int (*lhash_cmp_func)(const void *a, const void *b);
+
+/* lhash_hash_func is a function that maps an object to a uniformly distributed
+ * uint32_t. */
+typedef uint32_t (*lhash_hash_func)(const void *a);
+
+typedef struct lhash_st {
+ /* num_items contains the total number of items in the hash table. */
+ size_t num_items;
+ /* buckets is an array of |num_buckets| pointers. Each points to the head of
+ * a chain of LHASH_ITEM objects that have the same hash value, mod
+ * |num_buckets|. */
+ LHASH_ITEM **buckets;
+ /* num_buckets contains the length of |buckets|. This value is always >=
+ * kMinNumBuckets. */
+ size_t num_buckets;
+ /* callback_depth contains the current depth of |lh_doall| or |lh_doall_arg|
+ * calls. If non-zero then this suppresses resizing of the |buckets| array,
+ * which would otherwise disrupt the iteration. */
+ unsigned callback_depth;
+
+ lhash_cmp_func comp;
+ lhash_hash_func hash;
+} _LHASH;
+
+/* lh_new returns a new, empty hash table or NULL on error. If |comp| is NULL,
+ * |strcmp| will be used. If |hash| is NULL, a generic hash function will be
+ * used. */
+OPENSSL_EXPORT _LHASH *lh_new(lhash_hash_func hash, lhash_cmp_func comp);
+
+/* lh_free frees the hash table itself but none of the elements. See
+ * |lh_doall|. */
+OPENSSL_EXPORT void lh_free(_LHASH *lh);
+
+/* lh_num_items returns the number of items in |lh|. */
+OPENSSL_EXPORT size_t lh_num_items(const _LHASH *lh);
+
+/* lh_retrieve finds an element equal to |data| in the hash table and returns
+ * it. If no such element exists, it returns NULL. */
+OPENSSL_EXPORT void *lh_retrieve(const _LHASH *lh, const void *data);
+
+/* lh_insert inserts |data| into the hash table. If an existing element is
+ * equal to |data| (with respect to the comparison function) then |*old_data|
+ * will be set to that value and it will be replaced. Otherwise, or in the
+ * event of an error, |*old_data| will be set to NULL. It returns one on
+ * success or zero in the case of an allocation error. */
+OPENSSL_EXPORT int lh_insert(_LHASH *lh, void **old_data, void *data);
+
+/* lh_delete removes an element equal to |data| from the hash table and returns
+ * it. If no such element is found, it returns NULL. */
+OPENSSL_EXPORT void *lh_delete(_LHASH *lh, const void *data);
+
+/* lh_doall calls |func| on each element of the hash table.
+ * TODO(fork): rename this */
+OPENSSL_EXPORT void lh_doall(_LHASH *lh, void (*func)(void *));
+
+/* lh_doall_arg calls |func| on each element of the hash table and also passes
+ * |arg| as the second argument.
+ * TODO(fork): rename this */
+OPENSSL_EXPORT void lh_doall_arg(_LHASH *lh, void (*func)(void *, void *),
+ void *arg);
+
+/* lh_strhash is the default hash function which processes NUL-terminated
+ * strings. */
+OPENSSL_EXPORT uint32_t lh_strhash(const char *c);
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_STACK_H */
diff --git a/src/include/openssl/lhash_macros.h b/src/include/openssl/lhash_macros.h
new file mode 100644
index 0000000..f84b5ed
--- /dev/null
+++ b/src/include/openssl/lhash_macros.h
@@ -0,0 +1,248 @@
+/* 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. */
+
+#if !defined(IN_LHASH_H)
+#error "Don't include this file directly. Include lhash.h"
+#endif
+
+/* ASN1_OBJECT */
+#define lh_ASN1_OBJECT_new(hash, comp) \
+ ((LHASH_OF(ASN1_OBJECT) *)lh_new( \
+ CHECKED_CAST(lhash_hash_func, uint32_t (*)(const ASN1_OBJECT *), hash), \
+ CHECKED_CAST(lhash_cmp_func, \
+ int (*)(const ASN1_OBJECT *a, const ASN1_OBJECT *b), \
+ comp)))
+
+#define lh_ASN1_OBJECT_free(lh) \
+ lh_free(CHECKED_CAST(_LHASH *, LHASH_OF(ASN1_OBJECT) *, lh));
+
+#define lh_ASN1_OBJECT_num_items(lh) \
+ lh_num_items(CHECKED_CAST(_LHASH *, LHASH_OF(ASN1_OBJECT) *, lh))
+
+#define lh_ASN1_OBJECT_retrieve(lh, data) \
+ ((ASN1_OBJECT *)lh_retrieve( \
+ CHECKED_CAST(_LHASH *, LHASH_OF(ASN1_OBJECT) *, lh), \
+ CHECKED_CAST(void *, ASN1_OBJECT *, data)))
+
+#define lh_ASN1_OBJECT_insert(lh, old_data, data) \
+ lh_insert(CHECKED_CAST(_LHASH *, LHASH_OF(ASN1_OBJECT) *, lh), \
+ CHECKED_CAST(void **, ASN1_OBJECT **, old_data), \
+ CHECKED_CAST(void *, ASN1_OBJECT *, data))
+
+#define lh_ASN1_OBJECT_delete(lh, data) \
+ ((ASN1_OBJECT *)lh_delete( \
+ CHECKED_CAST(_LHASH *, LHASH_OF(ASN1_OBJECT) *, lh), \
+ CHECKED_CAST(void *, ASN1_OBJECT *, data)))
+
+#define lh_ASN1_OBJECT_doall(lh, func) \
+ lh_doall(CHECKED_CAST(_LHASH *, LHASH_OF(ASN1_OBJECT) *, lh), \
+ CHECKED_CAST(void (*)(void *), void (*)(ASN1_OBJECT *), func));
+
+#define lh_ASN1_OBJECT_doall_arg(lh, func, arg) \
+ lh_doall_arg(CHECKED_CAST(_LHASH *, LHASH_OF(ASN1_OBJECT) *, lh), \
+ CHECKED_CAST(void (*)(void *, void *), \
+ void (*)(ASN1_OBJECT *, void *), func), \
+ arg);
+
+/* CONF_VALUE */
+#define lh_CONF_VALUE_new(hash, comp) \
+ ((LHASH_OF(CONF_VALUE) *)lh_new( \
+ CHECKED_CAST(lhash_hash_func, uint32_t (*)(const CONF_VALUE *), hash), \
+ CHECKED_CAST(lhash_cmp_func, \
+ int (*)(const CONF_VALUE *a, const CONF_VALUE *b), comp)))
+
+#define lh_CONF_VALUE_free(lh) \
+ lh_free(CHECKED_CAST(_LHASH *, LHASH_OF(CONF_VALUE) *, lh));
+
+#define lh_CONF_VALUE_num_items(lh) \
+ lh_num_items(CHECKED_CAST(_LHASH *, LHASH_OF(CONF_VALUE) *, lh))
+
+#define lh_CONF_VALUE_retrieve(lh, data) \
+ ((CONF_VALUE *)lh_retrieve( \
+ CHECKED_CAST(_LHASH *, LHASH_OF(CONF_VALUE) *, lh), \
+ CHECKED_CAST(void *, CONF_VALUE *, data)))
+
+#define lh_CONF_VALUE_insert(lh, old_data, data) \
+ lh_insert(CHECKED_CAST(_LHASH *, LHASH_OF(CONF_VALUE) *, lh), \
+ CHECKED_CAST(void **, CONF_VALUE **, old_data), \
+ CHECKED_CAST(void *, CONF_VALUE *, data))
+
+#define lh_CONF_VALUE_delete(lh, data) \
+ ((CONF_VALUE *)lh_delete(CHECKED_CAST(_LHASH *, LHASH_OF(CONF_VALUE) *, lh), \
+ CHECKED_CAST(void *, CONF_VALUE *, data)))
+
+#define lh_CONF_VALUE_doall(lh, func) \
+ lh_doall(CHECKED_CAST(_LHASH *, LHASH_OF(CONF_VALUE) *, lh), \
+ CHECKED_CAST(void (*)(void *), void (*)(CONF_VALUE *), func));
+
+#define lh_CONF_VALUE_doall_arg(lh, func, arg) \
+ lh_doall_arg(CHECKED_CAST(_LHASH *, LHASH_OF(CONF_VALUE) *, lh), \
+ CHECKED_CAST(void (*)(void *, void *), \
+ void (*)(CONF_VALUE *, void *), func), \
+ arg);
+
+/* ERR_STATE */
+#define lh_ERR_STATE_new(hash, comp) \
+ ((LHASH_OF(ERR_STATE) *)lh_new( \
+ CHECKED_CAST(lhash_hash_func, uint32_t (*)(const ERR_STATE *), hash), \
+ CHECKED_CAST(lhash_cmp_func, \
+ int (*)(const ERR_STATE *a, const ERR_STATE *b), comp)))
+
+#define lh_ERR_STATE_free(lh) \
+ lh_free(CHECKED_CAST(_LHASH *, LHASH_OF(ERR_STATE) *, lh));
+
+#define lh_ERR_STATE_num_items(lh) \
+ lh_num_items(CHECKED_CAST(_LHASH *, LHASH_OF(ERR_STATE) *, lh))
+
+#define lh_ERR_STATE_retrieve(lh, data) \
+ ((ERR_STATE *)lh_retrieve(CHECKED_CAST(_LHASH *, LHASH_OF(ERR_STATE) *, lh), \
+ CHECKED_CAST(void *, ERR_STATE *, data)))
+
+#define lh_ERR_STATE_insert(lh, old_data, data) \
+ lh_insert(CHECKED_CAST(_LHASH *, LHASH_OF(ERR_STATE) *, lh), \
+ CHECKED_CAST(void **, ERR_STATE **, old_data), \
+ CHECKED_CAST(void *, ERR_STATE *, data))
+
+#define lh_ERR_STATE_delete(lh, data) \
+ ((ERR_STATE *)lh_delete(CHECKED_CAST(_LHASH *, LHASH_OF(ERR_STATE) *, lh), \
+ CHECKED_CAST(void *, ERR_STATE *, data)))
+
+#define lh_ERR_STATE_doall(lh, func) \
+ lh_doall(CHECKED_CAST(_LHASH *, LHASH_OF(ERR_STATE) *, lh), \
+ CHECKED_CAST(void (*)(void *), void (*)(ERR_STATE *), func));
+
+#define lh_ERR_STATE_doall_arg(lh, func, arg) \
+ lh_doall_arg(CHECKED_CAST(_LHASH *, LHASH_OF(ERR_STATE) *, lh), \
+ CHECKED_CAST(void (*)(void *, void *), \
+ void (*)(ERR_STATE *, void *), func), \
+ arg);
+
+/* ERR_STRING_DATA */
+#define lh_ERR_STRING_DATA_new(hash, comp) \
+ ((LHASH_OF(ERR_STRING_DATA) *)lh_new( \
+ CHECKED_CAST(lhash_hash_func, uint32_t (*)(const ERR_STRING_DATA *), \
+ hash), \
+ CHECKED_CAST( \
+ lhash_cmp_func, \
+ int (*)(const ERR_STRING_DATA *a, const ERR_STRING_DATA *b), comp)))
+
+#define lh_ERR_STRING_DATA_free(lh) \
+ lh_free(CHECKED_CAST(_LHASH *, LHASH_OF(ERR_STRING_DATA) *, lh));
+
+#define lh_ERR_STRING_DATA_num_items(lh) \
+ lh_num_items(CHECKED_CAST(_LHASH *, LHASH_OF(ERR_STRING_DATA) *, lh))
+
+#define lh_ERR_STRING_DATA_retrieve(lh, data) \
+ ((ERR_STRING_DATA *)lh_retrieve( \
+ CHECKED_CAST(_LHASH *, LHASH_OF(ERR_STRING_DATA) *, lh), \
+ CHECKED_CAST(void *, ERR_STRING_DATA *, data)))
+
+#define lh_ERR_STRING_DATA_insert(lh, old_data, data) \
+ lh_insert(CHECKED_CAST(_LHASH *, LHASH_OF(ERR_STRING_DATA) *, lh), \
+ CHECKED_CAST(void **, ERR_STRING_DATA **, old_data), \
+ CHECKED_CAST(void *, ERR_STRING_DATA *, data))
+
+#define lh_ERR_STRING_DATA_delete(lh, data) \
+ ((ERR_STRING_DATA *)lh_delete( \
+ CHECKED_CAST(_LHASH *, LHASH_OF(ERR_STRING_DATA) *, lh), \
+ CHECKED_CAST(void *, ERR_STRING_DATA *, data)))
+
+#define lh_ERR_STRING_DATA_doall(lh, func) \
+ lh_doall(CHECKED_CAST(_LHASH *, LHASH_OF(ERR_STRING_DATA) *, lh), \
+ CHECKED_CAST(void (*)(void *), void (*)(ERR_STRING_DATA *), func));
+
+#define lh_ERR_STRING_DATA_doall_arg(lh, func, arg) \
+ lh_doall_arg(CHECKED_CAST(_LHASH *, LHASH_OF(ERR_STRING_DATA) *, lh), \
+ CHECKED_CAST(void (*)(void *, void *), \
+ void (*)(ERR_STRING_DATA *, void *), func), \
+ arg);
+
+/* EX_CLASS_ITEM */
+#define lh_EX_CLASS_ITEM_new(hash, comp) \
+ ((LHASH_OF(EX_CLASS_ITEM) *)lh_new( \
+ CHECKED_CAST(lhash_hash_func, uint32_t (*)(const EX_CLASS_ITEM *), \
+ hash), \
+ CHECKED_CAST(lhash_cmp_func, \
+ int (*)(const EX_CLASS_ITEM *a, const EX_CLASS_ITEM *b), \
+ comp)))
+
+#define lh_EX_CLASS_ITEM_free(lh) \
+ lh_free(CHECKED_CAST(_LHASH *, LHASH_OF(EX_CLASS_ITEM) *, lh));
+
+#define lh_EX_CLASS_ITEM_num_items(lh) \
+ lh_num_items(CHECKED_CAST(_LHASH *, LHASH_OF(EX_CLASS_ITEM) *, lh))
+
+#define lh_EX_CLASS_ITEM_retrieve(lh, data) \
+ ((EX_CLASS_ITEM *)lh_retrieve( \
+ CHECKED_CAST(_LHASH *, LHASH_OF(EX_CLASS_ITEM) *, lh), \
+ CHECKED_CAST(void *, EX_CLASS_ITEM *, data)))
+
+#define lh_EX_CLASS_ITEM_insert(lh, old_data, data) \
+ lh_insert(CHECKED_CAST(_LHASH *, LHASH_OF(EX_CLASS_ITEM) *, lh), \
+ CHECKED_CAST(void **, EX_CLASS_ITEM **, old_data), \
+ CHECKED_CAST(void *, EX_CLASS_ITEM *, data))
+
+#define lh_EX_CLASS_ITEM_delete(lh, data) \
+ ((EX_CLASS_ITEM *)lh_delete( \
+ CHECKED_CAST(_LHASH *, LHASH_OF(EX_CLASS_ITEM) *, lh), \
+ CHECKED_CAST(void *, EX_CLASS_ITEM *, data)))
+
+#define lh_EX_CLASS_ITEM_doall(lh, func) \
+ lh_doall(CHECKED_CAST(_LHASH *, LHASH_OF(EX_CLASS_ITEM) *, lh), \
+ CHECKED_CAST(void (*)(void *), void (*)(EX_CLASS_ITEM *), func));
+
+#define lh_EX_CLASS_ITEM_doall_arg(lh, func, arg) \
+ lh_doall_arg(CHECKED_CAST(_LHASH *, LHASH_OF(EX_CLASS_ITEM) *, lh), \
+ CHECKED_CAST(void (*)(void *, void *), \
+ void (*)(EX_CLASS_ITEM *, void *), func), \
+ arg);
+
+/* SSL_SESSION */
+#define lh_SSL_SESSION_new(hash, comp) \
+ ((LHASH_OF(SSL_SESSION) *)lh_new( \
+ CHECKED_CAST(lhash_hash_func, uint32_t (*)(const SSL_SESSION *), hash), \
+ CHECKED_CAST(lhash_cmp_func, \
+ int (*)(const SSL_SESSION *a, const SSL_SESSION *b), \
+ comp)))
+
+#define lh_SSL_SESSION_free(lh) \
+ lh_free(CHECKED_CAST(_LHASH *, LHASH_OF(SSL_SESSION) *, lh));
+
+#define lh_SSL_SESSION_num_items(lh) \
+ lh_num_items(CHECKED_CAST(_LHASH *, LHASH_OF(SSL_SESSION) *, lh))
+
+#define lh_SSL_SESSION_retrieve(lh, data) \
+ ((SSL_SESSION *)lh_retrieve( \
+ CHECKED_CAST(_LHASH *, LHASH_OF(SSL_SESSION) *, lh), \
+ CHECKED_CAST(void *, SSL_SESSION *, data)))
+
+#define lh_SSL_SESSION_insert(lh, old_data, data) \
+ lh_insert(CHECKED_CAST(_LHASH *, LHASH_OF(SSL_SESSION) *, lh), \
+ CHECKED_CAST(void **, SSL_SESSION **, old_data), \
+ CHECKED_CAST(void *, SSL_SESSION *, data))
+
+#define lh_SSL_SESSION_delete(lh, data) \
+ ((SSL_SESSION *)lh_delete( \
+ CHECKED_CAST(_LHASH *, LHASH_OF(SSL_SESSION) *, lh), \
+ CHECKED_CAST(void *, SSL_SESSION *, data)))
+
+#define lh_SSL_SESSION_doall(lh, func) \
+ lh_doall(CHECKED_CAST(_LHASH *, LHASH_OF(SSL_SESSION) *, lh), \
+ CHECKED_CAST(void (*)(void *), void (*)(SSL_SESSION *), func));
+
+#define lh_SSL_SESSION_doall_arg(lh, func, arg) \
+ lh_doall_arg(CHECKED_CAST(_LHASH *, LHASH_OF(SSL_SESSION) *, lh), \
+ CHECKED_CAST(void (*)(void *, void *), \
+ void (*)(SSL_SESSION *, void *), func), \
+ arg);
diff --git a/src/include/openssl/md4.h b/src/include/openssl/md4.h
new file mode 100644
index 0000000..ce4fa99
--- /dev/null
+++ b/src/include/openssl/md4.h
@@ -0,0 +1,101 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 OPENSSL_HEADER_MD4_H
+#define OPENSSL_HEADER_MD4_H
+
+#include <openssl/base.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* MD4. */
+
+/* MD4_CBLOCK is the block size of MD4. */
+#define MD4_CBLOCK 64
+
+/* MD4_DIGEST_LENGTH is the length of an MD4 digest. */
+#define MD4_DIGEST_LENGTH 16
+
+/* MD41_Init initialises |md4| and returns one. */
+OPENSSL_EXPORT int MD4_Init(MD4_CTX *md4);
+
+/* MD4_Update adds |len| bytes from |data| to |md4| and returns one. */
+OPENSSL_EXPORT int MD4_Update(MD4_CTX *md4, const void *data, size_t len);
+
+/* MD4_Final adds the final padding to |md4| and writes the resulting digest to
+ * |md|, which must have at least |MD4_DIGEST_LENGTH| bytes of space. It
+ * returns one. */
+OPENSSL_EXPORT int MD4_Final(uint8_t *md, MD4_CTX *md4);
+
+/* MD4_Transform is a low-level function that performs a single, MD4 block
+ * transformation using the state from |md4| and 64 bytes from |block|. */
+OPENSSL_EXPORT void MD4_Transform(MD4_CTX *md4, const uint8_t *block);
+
+struct md4_state_st {
+ uint32_t A, B, C, D;
+ uint32_t Nl, Nh;
+ uint32_t data[16];
+ unsigned int num;
+};
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_MD4_H */
diff --git a/src/include/openssl/md5.h b/src/include/openssl/md5.h
new file mode 100644
index 0000000..efedc98
--- /dev/null
+++ b/src/include/openssl/md5.h
@@ -0,0 +1,106 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 OPENSSL_HEADER_MD5_H
+#define OPENSSL_HEADER_MD5_H
+
+#include <openssl/base.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* MD5. */
+
+
+/* MD5_CBLOCK is the block size of MD5. */
+#define MD5_CBLOCK 64
+
+/* MD5_DIGEST_LENGTH is the length of an MD5 digest. */
+#define MD5_DIGEST_LENGTH 16
+
+/* MD51_Init initialises |md5| and returns one. */
+OPENSSL_EXPORT int MD5_Init(MD5_CTX *md5);
+
+/* MD5_Update adds |len| bytes from |data| to |md5| and returns one. */
+OPENSSL_EXPORT int MD5_Update(MD5_CTX *md5, const void *data, size_t len);
+
+/* MD5_Final adds the final padding to |md5| and writes the resulting digest to
+ * |md|, which must have at least |MD5_DIGEST_LENGTH| bytes of space. It
+ * returns one. */
+OPENSSL_EXPORT int MD5_Final(uint8_t *md, MD5_CTX *md5);
+
+/* MD5 writes the digest of |len| bytes from |data| to |out| and returns |out|.
+ * There must be at least |MD5_DIGEST_LENGTH| bytes of space in |out|. */
+OPENSSL_EXPORT uint8_t *MD5(const uint8_t *data, size_t len, uint8_t *out);
+
+/* MD5_Transform is a low-level function that performs a single, MD5 block
+ * transformation using the state from |md5| and 64 bytes from |block|. */
+OPENSSL_EXPORT void MD5_Transform(MD5_CTX *md5, const uint8_t *block);
+
+struct md5_state_st {
+ uint32_t A, B, C, D;
+ uint32_t Nl, Nh;
+ uint32_t data[16];
+ unsigned int num;
+};
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_MD5_H */
diff --git a/src/include/openssl/mem.h b/src/include/openssl/mem.h
new file mode 100644
index 0000000..3bd01c0
--- /dev/null
+++ b/src/include/openssl/mem.h
@@ -0,0 +1,138 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 OPENSSL_HEADER_MEM_H
+#define OPENSSL_HEADER_MEM_H
+
+#include <openssl/base.h>
+
+#include <stdarg.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* Memory and string functions, see also buf.h.
+ *
+ * OpenSSL has, historically, had a complex set of malloc debugging options.
+ * However, that was written in a time before Valgrind and ASAN. Since we now
+ * have those tools, the OpenSSL allocation functions are simply macros around
+ * the standard memory functions. */
+
+
+#define OPENSSL_malloc malloc
+#define OPENSSL_realloc realloc
+#define OPENSSL_free free
+
+/* OPENSSL_realloc_clean acts like |realloc|, but clears the previous memory
+ * buffer. Because this is implemented as a wrapper around |malloc|, it needs
+ * to be given the size of the buffer pointed to by |ptr|. */
+void *OPENSSL_realloc_clean(void *ptr, size_t old_size, size_t new_size);
+
+/* OPENSSL_cleanse zeros out |len| bytes of memory at |ptr|. This is similar to
+ * |memset_s| from C11. */
+OPENSSL_EXPORT void OPENSSL_cleanse(void *ptr, size_t len);
+
+/* 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. */
+OPENSSL_EXPORT int CRYPTO_memcmp(const void *a, const void *b, size_t len);
+
+/* OPENSSL_hash32 implements the 32 bit, FNV-1a hash. */
+OPENSSL_EXPORT uint32_t OPENSSL_hash32(const void *ptr, size_t len);
+
+/* OPENSSL_strdup has the same behaviour as strdup(3). */
+OPENSSL_EXPORT char *OPENSSL_strdup(const char *s);
+
+/* OPENSSL_strnlen has the same behaviour as strnlen(3). */
+OPENSSL_EXPORT size_t OPENSSL_strnlen(const char *s, size_t len);
+
+/* OPENSSL_strcasecmp has the same behaviour as strcasecmp(3). */
+OPENSSL_EXPORT int OPENSSL_strcasecmp(const char *a, const char *b);
+
+/* OPENSSL_strncasecmp has the same behaviour as strncasecmp(3). */
+OPENSSL_EXPORT int OPENSSL_strncasecmp(const char *a, const char *b, size_t n);
+
+/* DECIMAL_SIZE returns an upper bound for the length of the decimal
+ * representation of the given type. */
+#define DECIMAL_SIZE(type) ((sizeof(type)*8+2)/3+1)
+
+/* Printf functions.
+ *
+ * These functions are either OpenSSL wrappers for standard functions (i.e.
+ * |BIO_snprintf| and |BIO_vsnprintf|) which don't exist in C89, or are
+ * versions of printf functions that output to a BIO rather than a FILE. */
+#ifdef __GNUC__
+#define __bio_h__attr__ __attribute__
+#else
+#define __bio_h__attr__(x)
+#endif
+OPENSSL_EXPORT int BIO_snprintf(char *buf, size_t n, const char *format, ...)
+ __bio_h__attr__((__format__(__printf__, 3, 4)));
+
+OPENSSL_EXPORT int BIO_vsnprintf(char *buf, size_t n, const char *format,
+ va_list args)
+ __bio_h__attr__((__format__(__printf__, 3, 0)));
+#undef __bio_h__attr__
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_MEM_H */
diff --git a/src/include/openssl/modes.h b/src/include/openssl/modes.h
new file mode 100644
index 0000000..220adec
--- /dev/null
+++ b/src/include/openssl/modes.h
@@ -0,0 +1,223 @@
+/* ====================================================================
+ * 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.
+ * ==================================================================== */
+
+#ifndef OPENSSL_HEADER_MODES_H
+#define OPENSSL_HEADER_MODES_H
+
+#include <openssl/base.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* modes.h contains functions that implement various block-cipher modes. */
+
+
+/* block128_f is the type of a 128-bit, block cipher. */
+typedef void (*block128_f)(const uint8_t in[16], uint8_t out[16],
+ const void *key);
+
+
+/* CTR. */
+
+/* ctr128_f is the type of a function that performs CTR-mode encryption. */
+typedef void (*ctr128_f)(const uint8_t *in, uint8_t *out, size_t blocks,
+ const void *key, const uint8_t ivec[16]);
+
+/* CRYPTO_ctr128_encrypt encrypts (or decrypts, it's the same in CTR mode)
+ * |len| bytes from |in| to |out| using |block| in counter mode. There's no
+ * requirement that |len| be a multiple of any value and any partial blocks are
+ * stored in |ecount_buf| and |*num|, which must be zeroed before the initial
+ * call. The counter is a 128-bit, big-endian value in |ivec| and is
+ * incremented by this function. */
+OPENSSL_EXPORT void CRYPTO_ctr128_encrypt(const uint8_t *in, uint8_t *out,
+ size_t len, const void *key,
+ uint8_t ivec[16],
+ uint8_t ecount_buf[16],
+ unsigned int *num, block128_f block);
+
+/* CRYPTO_ctr128_encrypt_ctr32 acts like |CRYPTO_ctr128_encrypt| but takes
+ * |ctr|, a function that performs CTR mode but only deals with the lower 32
+ * bits of the counter. This is useful when |ctr| can be an optimised
+ * function. */
+OPENSSL_EXPORT void CRYPTO_ctr128_encrypt_ctr32(
+ const uint8_t *in, uint8_t *out, size_t len, const void *key,
+ uint8_t ivec[16], uint8_t ecount_buf[16], unsigned int *num, ctr128_f ctr);
+
+
+/* GCM. */
+
+typedef struct gcm128_context GCM128_CONTEXT;
+
+/* CRYPTO_gcm128_new allocates a fresh |GCM128_CONTEXT| and calls
+ * |CRYPTO_gcm128_init|. It returns the new context, or NULL on error. */
+OPENSSL_EXPORT GCM128_CONTEXT *CRYPTO_gcm128_new(void *key, block128_f block);
+
+/* CRYPTO_gcm128_init initialises |ctx| to use |block| (typically AES) with the
+ * given key. */
+OPENSSL_EXPORT void CRYPTO_gcm128_init(GCM128_CONTEXT *ctx, void *key,
+ block128_f block);
+
+/* CRYPTO_gcm128_setiv sets the IV (nonce) for |ctx|. */
+OPENSSL_EXPORT void CRYPTO_gcm128_setiv(GCM128_CONTEXT *ctx, const uint8_t *iv,
+ size_t len);
+
+/* CRYPTO_gcm128_aad sets the authenticated data for an instance of GCM. This
+ * must be called before and data is encrypted. It returns one on success and
+ * zero otherwise. */
+OPENSSL_EXPORT int CRYPTO_gcm128_aad(GCM128_CONTEXT *ctx, const uint8_t *aad,
+ size_t len);
+
+/* CRYPTO_gcm128_encrypt encrypts |len| bytes from |in| to |out|. It returns
+ * one on success and zero otherwise. */
+OPENSSL_EXPORT int CRYPTO_gcm128_encrypt(GCM128_CONTEXT *ctx, const uint8_t *in,
+ uint8_t *out, size_t len);
+
+/* CRYPTO_gcm128_decrypt decrypts |len| bytes from |in| to |out|. It returns
+ * one on success and zero otherwise. */
+OPENSSL_EXPORT int CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx, const uint8_t *in,
+ uint8_t *out, size_t len);
+
+/* CRYPTO_gcm128_encrypt_ctr32 encrypts |len| bytes from |in| to |out| using a
+ * CTR function that only handles the bottom 32 bits of the nonce, like
+ * |CRYPTO_ctr128_encrypt_ctr32|. It returns one on success and zero
+ * otherwise. */
+OPENSSL_EXPORT int CRYPTO_gcm128_encrypt_ctr32(GCM128_CONTEXT *ctx,
+ const uint8_t *in, uint8_t *out,
+ size_t len, ctr128_f stream);
+
+/* CRYPTO_gcm128_decrypt_ctr32 decrypts |len| bytes from |in| to |out| using a
+ * CTR function that only handles the bottom 32 bits of the nonce, like
+ * |CRYPTO_ctr128_encrypt_ctr32|. It returns one on success and zero
+ * otherwise. */
+OPENSSL_EXPORT int CRYPTO_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx,
+ const uint8_t *in, uint8_t *out,
+ size_t len, ctr128_f stream);
+
+/* CRYPTO_gcm128_finish calculates the authenticator and compares it against
+ * |len| bytes of |tag|. It returns one on success and zero otherwise. */
+OPENSSL_EXPORT int CRYPTO_gcm128_finish(GCM128_CONTEXT *ctx, const uint8_t *tag,
+ size_t len);
+
+/* CRYPTO_gcm128_tag calculates the authenticator and copies it into |tag|. The
+ * minimum of |len| and 16 bytes are copied into |tag|. */
+OPENSSL_EXPORT void CRYPTO_gcm128_tag(GCM128_CONTEXT *ctx, uint8_t *tag,
+ size_t len);
+
+/* CRYPTO_gcm128_release clears and frees |ctx|. */
+OPENSSL_EXPORT void CRYPTO_gcm128_release(GCM128_CONTEXT *ctx);
+
+
+/* CBC. */
+
+/* cbc128_f is the type of a function that performs CBC-mode encryption. */
+typedef void (*cbc128_f)(const uint8_t *in, uint8_t *out, size_t len,
+ const void *key, uint8_t ivec[16], int enc);
+
+/* CRYPTO_cbc128_encrypt encrypts |len| bytes from |in| to |out| using the
+ * given IV and block cipher in CBC mode. The input need not be a multiple of
+ * 128 bits long, but the output will round up to the nearest 128 bit multiple,
+ * zero padding the input if needed. The IV will be updated on return. */
+void CRYPTO_cbc128_encrypt(const uint8_t *in, uint8_t *out, size_t len,
+ const void *key, uint8_t ivec[16], block128_f block);
+
+/* CRYPTO_cbc128_decrypt decrypts |len| bytes from |in| to |out| using the
+ * given IV and block cipher in CBC mode. If |len| is not a multiple of 128
+ * bits then only that many bytes will be written, but a multiple of 128 bits
+ * is always read from |in|. The IV will be updated on return. */
+void CRYPTO_cbc128_decrypt(const uint8_t *in, uint8_t *out, size_t len,
+ const void *key, uint8_t ivec[16], block128_f block);
+
+
+/* OFB. */
+
+/* CRYPTO_ofb128_encrypt encrypts (or decrypts, it's the same with OFB mode)
+ * |len| bytes from |in| to |out| using |block| in OFB mode. There's no
+ * requirement that |len| be a multiple of any value and any partial blocks are
+ * stored in |ivec| and |*num|, the latter must be zero before the initial
+ * call. */
+void CRYPTO_ofb128_encrypt(const uint8_t *in, uint8_t *out,
+ size_t len, const void *key, uint8_t ivec[16],
+ int *num, block128_f block);
+
+
+/* CFB. */
+
+/* CRYPTO_cfb128_encrypt encrypts (or decrypts, if |enc| is zero) |len| bytes
+ * from |in| to |out| using |block| in CFB mode. There's no requirement that
+ * |len| be a multiple of any value and any partial blocks are stored in |ivec|
+ * and |*num|, the latter must be zero before the initial call. */
+void CRYPTO_cfb128_encrypt(const uint8_t *in, uint8_t *out, size_t len,
+ const void *key, uint8_t ivec[16], int *num, int enc,
+ block128_f block);
+
+/* CRYPTO_cfb128_8_encrypt encrypts (or decrypts, if |enc| is zero) |len| bytes
+ * from |in| to |out| using |block| in CFB-8 mode. Prior to the first call
+ * |num| should be set to zero. */
+void CRYPTO_cfb128_8_encrypt(const uint8_t *in, uint8_t *out, size_t len,
+ const void *key, uint8_t ivec[16], int *num,
+ int enc, block128_f block);
+
+/* CRYPTO_cfb128_1_encrypt encrypts (or decrypts, if |enc| is zero) |len| bytes
+ * from |in| to |out| using |block| in CFB-1 mode. Prior to the first call
+ * |num| should be set to zero. */
+void CRYPTO_cfb128_1_encrypt(const uint8_t *in, uint8_t *out, size_t bits,
+ const void *key, uint8_t ivec[16], int *num,
+ int enc, block128_f block);
+
+size_t CRYPTO_cts128_encrypt_block(const uint8_t *in, uint8_t *out, size_t len,
+ const void *key, uint8_t ivec[16],
+ block128_f block);
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_MODES_H */
diff --git a/src/include/openssl/obj.h b/src/include/openssl/obj.h
new file mode 100644
index 0000000..5dd8886
--- /dev/null
+++ b/src/include/openssl/obj.h
@@ -0,0 +1,202 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 OPENSSL_HEADER_OBJECTS_H
+#define OPENSSL_HEADER_OBJECTS_H
+
+#include <openssl/base.h>
+
+#include <openssl/bytestring.h>
+#include <openssl/obj_mac.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* The objects library deals with the registration and indexing of ASN.1 object
+ * identifiers. These values are often written as a dotted sequence of numbers,
+ * e.g. 1.2.840.113549.1.9.16.3.9.
+ *
+ * Internally, OpenSSL likes to deal with these values by numbering them with
+ * numbers called "nids". OpenSSL has a large, built-in database of common
+ * object identifiers and also has both short and long names for them.
+ *
+ * This library provides functions for translating between object identifiers,
+ * nids, short names and long names.
+ *
+ * The nid values should not be used outside of a single process: they are not
+ * stable identifiers. */
+
+
+/* Basic operations. */
+
+/* OBJ_dup returns a duplicate copy of |obj| or NULL on allocation failure. */
+OPENSSL_EXPORT ASN1_OBJECT *OBJ_dup(const ASN1_OBJECT *obj);
+
+/* OBJ_cmp returns a value less than, equal to or greater than zero if |a| is
+ * less than, equal to or greater than |b|, respectively. */
+OPENSSL_EXPORT int OBJ_cmp(const ASN1_OBJECT *a, const ASN1_OBJECT *b);
+
+
+/* Looking up nids. */
+
+/* OBJ_obj2nid returns the nid corresponding to |obj|, or |NID_undef| if no
+ * such object is known. */
+OPENSSL_EXPORT int OBJ_obj2nid(const ASN1_OBJECT *obj);
+
+/* OBJ_cbs2nid returns the nid corresponding to the DER data in |cbs|, or
+ * |NID_undef| if no such object is known. */
+OPENSSL_EXPORT int OBJ_cbs2nid(const CBS *cbs);
+
+/* OBJ_sn2nid returns the nid corresponding to |short_name|, or |NID_undef| if
+ * no such short name is known. */
+OPENSSL_EXPORT int OBJ_sn2nid(const char *short_name);
+
+/* OBJ_ln2nid returns the nid corresponding to |long_name|, or |NID_undef| if
+ * no such long name is known. */
+OPENSSL_EXPORT int OBJ_ln2nid(const char *long_name);
+
+/* OBJ_txt2nid returns the nid corresponding to |s|, which may be a short name,
+ * long name, or an ASCII string containing a dotted sequence of numbers. It
+ * returns the nid or NID_undef if unknown. */
+OPENSSL_EXPORT int OBJ_txt2nid(const char *s);
+
+
+/* Getting information about nids. */
+
+/* OBJ_nid2obj returns the ASN1_OBJECT corresponding to |nid|, or NULL if |nid|
+ * is unknown. */
+OPENSSL_EXPORT const ASN1_OBJECT *OBJ_nid2obj(int nid);
+
+/* OBJ_nid2sn returns the short name for |nid|, or NULL if |nid| is unknown. */
+OPENSSL_EXPORT const char *OBJ_nid2sn(int nid);
+
+/* OBJ_nid2sn returns the long name for |nid|, or NULL if |nid| is unknown. */
+OPENSSL_EXPORT const char *OBJ_nid2ln(int nid);
+
+/* OBJ_nid2cbs writes |nid| as an ASN.1 OBJECT IDENTIFIER to |out|. It returns
+ * one on success or zero otherwise. */
+OPENSSL_EXPORT int OBJ_nid2cbb(CBB *out, int nid);
+
+
+/* Dealing with textual representations of object identifiers. */
+
+/* OBJ_txt2obj returns an ASN1_OBJECT for the textual respresentation in |s|.
+ * If |dont_search_names| is zero, then |s| will be matched against the long
+ * and short names of a known objects to find a match. Otherwise |s| must
+ * contain an ASCII string with a dotted sequence of numbers. The resulting
+ * object need not be previously known. It returns a freshly allocated
+ * |ASN1_OBJECT| or NULL on error. */
+OPENSSL_EXPORT ASN1_OBJECT *OBJ_txt2obj(const char *s, int dont_search_names);
+
+/* OBJ_obj2txt converts |obj| to a textual representation. If
+ * |dont_return_name| is zero then |obj| will be matched against known objects
+ * and the long (preferably) or short name will be used if found. Otherwise
+ * |obj| will be converted into a dotted sequence of integers. If |out| is not
+ * NULL, then at most |out_len| bytes of the textual form will be written
+ * there. If |out_len| is at least one, then string written to |out| will
+ * always be NUL terminated. It returns the number of characters that could
+ * have been written, not including the final NUL, or -1 on error. */
+OPENSSL_EXPORT int OBJ_obj2txt(char *out, int out_len, const ASN1_OBJECT *obj,
+ int dont_return_name);
+
+
+/* Adding objects at runtime. */
+
+/* OBJ_create adds a known object and returns the nid of the new object, or
+ * NID_undef on error. */
+OPENSSL_EXPORT int OBJ_create(const char *oid, const char *short_name,
+ const char *long_name);
+
+
+/* Handling signature algorithm identifiers.
+ *
+ * Some NIDs (e.g. sha256WithRSAEncryption) specify both a digest algorithm and
+ * a public key algorithm. The following functions map between pairs of digest
+ * and public-key algorithms and the NIDs that specify their combination.
+ *
+ * Sometimes the combination NID leaves the digest unspecified (e.g.
+ * rsassaPss). In these cases, the digest NID is |NID_undef|. */
+
+/* OBJ_find_sigid_algs finds the digest and public-key NIDs that correspond to
+ * the signing algorithm |sign_nid|. If successful, it sets |*out_digest_nid|
+ * and |*out_pkey_nid| and returns one. Otherwise it returns zero. Any of
+ * |out_digest_nid| or |out_pkey_nid| can be NULL if the caller doesn't need
+ * that output value. */
+OPENSSL_EXPORT int OBJ_find_sigid_algs(int sign_nid, int *out_digest_nid,
+ int *out_pkey_nid);
+
+/* OBJ_find_sigid_by_algs finds the signature NID that corresponds to the
+ * combination of |digest_nid| and |pkey_nid|. If success, it sets
+ * |*out_sign_nid| and returns one. Otherwise it returns zero. The
+ * |out_sign_nid| argument can be NULL if the caller only wishes to learn
+ * whether the combination is valid. */
+OPENSSL_EXPORT int OBJ_find_sigid_by_algs(int *out_sign_nid, int digest_nid,
+ int pkey_nid);
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#define OBJ_F_OBJ_txt2obj 100
+#define OBJ_F_OBJ_create 101
+#define OBJ_F_OBJ_dup 102
+#define OBJ_F_OBJ_nid2obj 103
+#define OBJ_R_UNKNOWN_NID 100
+
+#endif /* OPENSSL_HEADER_OBJECTS_H */
diff --git a/src/include/openssl/obj_mac.h b/src/include/openssl/obj_mac.h
new file mode 100644
index 0000000..b028c00
--- /dev/null
+++ b/src/include/openssl/obj_mac.h
@@ -0,0 +1,4145 @@
+/* THIS FILE IS GENERATED FROM objects.txt by objects.pl via the
+ * following command:
+ * perl objects.pl objects.txt obj_mac.num ../../include/openssl/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 935
+#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_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_asciiTextWithCRLF "id-ct-asciiTextWithCRLF"
+#define NID_id_ct_asciiTextWithCRLF 787
+#define OBJ_id_ct_asciiTextWithCRLF OBJ_id_smime_ct,27L
+
+#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_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 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_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_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_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_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 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 Distrubution 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 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 OBJ_dsa_with_sha2 OBJ_nistAlgorithms,3L
+
+#define SN_dsa_with_SHA224 "dsa_with_SHA224"
+#define NID_dsa_with_SHA224 802
+#define OBJ_dsa_with_SHA224 OBJ_dsa_with_sha2,1L
+
+#define SN_dsa_with_SHA256 "dsa_with_SHA256"
+#define NID_dsa_with_SHA256 803
+#define OBJ_dsa_with_SHA256 OBJ_dsa_with_sha2,2L
+
+#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_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_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 SN_dhpublicnumber "dhpublicnumber"
+#define LN_dhpublicnumber "X9.42 DH"
+#define NID_dhpublicnumber 920
+#define OBJ_dhpublicnumber OBJ_ISO_US,10046L,2L,1L
+
+#define SN_brainpoolP160r1 "brainpoolP160r1"
+#define NID_brainpoolP160r1 921
+#define OBJ_brainpoolP160r1 1L,3L,36L,3L,3L,2L,8L,1L,1L,1L
+
+#define SN_brainpoolP160t1 "brainpoolP160t1"
+#define NID_brainpoolP160t1 922
+#define OBJ_brainpoolP160t1 1L,3L,36L,3L,3L,2L,8L,1L,1L,2L
+
+#define SN_brainpoolP192r1 "brainpoolP192r1"
+#define NID_brainpoolP192r1 923
+#define OBJ_brainpoolP192r1 1L,3L,36L,3L,3L,2L,8L,1L,1L,3L
+
+#define SN_brainpoolP192t1 "brainpoolP192t1"
+#define NID_brainpoolP192t1 924
+#define OBJ_brainpoolP192t1 1L,3L,36L,3L,3L,2L,8L,1L,1L,4L
+
+#define SN_brainpoolP224r1 "brainpoolP224r1"
+#define NID_brainpoolP224r1 925
+#define OBJ_brainpoolP224r1 1L,3L,36L,3L,3L,2L,8L,1L,1L,5L
+
+#define SN_brainpoolP224t1 "brainpoolP224t1"
+#define NID_brainpoolP224t1 926
+#define OBJ_brainpoolP224t1 1L,3L,36L,3L,3L,2L,8L,1L,1L,6L
+
+#define SN_brainpoolP256r1 "brainpoolP256r1"
+#define NID_brainpoolP256r1 927
+#define OBJ_brainpoolP256r1 1L,3L,36L,3L,3L,2L,8L,1L,1L,7L
+
+#define SN_brainpoolP256t1 "brainpoolP256t1"
+#define NID_brainpoolP256t1 928
+#define OBJ_brainpoolP256t1 1L,3L,36L,3L,3L,2L,8L,1L,1L,8L
+
+#define SN_brainpoolP320r1 "brainpoolP320r1"
+#define NID_brainpoolP320r1 929
+#define OBJ_brainpoolP320r1 1L,3L,36L,3L,3L,2L,8L,1L,1L,9L
+
+#define SN_brainpoolP320t1 "brainpoolP320t1"
+#define NID_brainpoolP320t1 930
+#define OBJ_brainpoolP320t1 1L,3L,36L,3L,3L,2L,8L,1L,1L,10L
+
+#define SN_brainpoolP384r1 "brainpoolP384r1"
+#define NID_brainpoolP384r1 931
+#define OBJ_brainpoolP384r1 1L,3L,36L,3L,3L,2L,8L,1L,1L,11L
+
+#define SN_brainpoolP384t1 "brainpoolP384t1"
+#define NID_brainpoolP384t1 932
+#define OBJ_brainpoolP384t1 1L,3L,36L,3L,3L,2L,8L,1L,1L,12L
+
+#define SN_brainpoolP512r1 "brainpoolP512r1"
+#define NID_brainpoolP512r1 933
+#define OBJ_brainpoolP512r1 1L,3L,36L,3L,3L,2L,8L,1L,1L,13L
+
+#define SN_brainpoolP512t1 "brainpoolP512t1"
+#define NID_brainpoolP512t1 934
+#define OBJ_brainpoolP512t1 1L,3L,36L,3L,3L,2L,8L,1L,1L,14L
+
+#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 936
+#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 937
+#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 938
+#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 939
+#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 940
+#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 941
+#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 942
+#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 943
+#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 944
+#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 945
+#define OBJ_dhSinglePass_cofactorDH_sha512kdf_scheme OBJ_secg_scheme,14L,3L
+
+#define SN_dh_std_kdf "dh-std-kdf"
+#define NID_dh_std_kdf 946
+
+#define SN_dh_cofactor_kdf "dh-cofactor-kdf"
+#define NID_dh_cofactor_kdf 947
+
diff --git a/src/include/openssl/objects.h b/src/include/openssl/objects.h
new file mode 100644
index 0000000..dd6556f
--- /dev/null
+++ b/src/include/openssl/objects.h
@@ -0,0 +1,18 @@
+/* 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. */
+
+/* This header is provided in order to make compiling against code that expects
+ OpenSSL easier. */
+
+#include "obj.h"
diff --git a/src/include/openssl/opensslfeatures.h b/src/include/openssl/opensslfeatures.h
new file mode 100644
index 0000000..4f5cb31
--- /dev/null
+++ b/src/include/openssl/opensslfeatures.h
@@ -0,0 +1,55 @@
+/* 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. */
+
+/* This header is provided in order to make compiling against code that expects
+ OpenSSL easier. */
+
+#ifndef OPENSSL_HEADER_OPENSSLFEATURES_H
+#define OPENSSL_HEADER_OPENSSLFEATURES_H
+
+
+#define OPENSSL_NO_BF
+#define OPENSSL_NO_BUF_FREELISTS
+#define OPENSSL_NO_CAMELLIA
+#define OPENSSL_NO_CAST
+#define OPENSSL_NO_CMS
+#define OPENSSL_NO_COMP
+#define OPENSSL_NO_DANE
+#define OPENSSL_NO_DEPRECATED
+#define OPENSSL_NO_DYNAMIC_ENGINE
+#define OPENSSL_NO_ENGINE
+#define OPENSSL_NO_GMP
+#define OPENSSL_NO_GOST
+#define OPENSSL_NO_HEARTBEATS
+#define OPENSSL_NO_HW
+#define OPENSSL_NO_IDEA
+#define OPENSSL_NO_JPAKE
+#define OPENSSL_NO_KRB5
+#define OPENSSL_NO_MD2
+#define OPENSSL_NO_MDC2
+#define OPENSSL_NO_OCSP
+#define OPENSSL_NO_RC2
+#define OPENSSL_NO_RC5
+#define OPENSSL_NO_RFC3779
+#define OPENSSL_NO_RIPEMD
+#define OPENSSL_NO_SCTP
+#define OPENSSL_NO_SEED
+#define OPENSSL_NO_SRP
+#define OPENSSL_NO_SSL2
+#define OPENSSL_NO_STATIC_ENGINE
+#define OPENSSL_NO_STORE
+#define OPENSSL_NO_WHIRLPOOL
+
+
+#endif /* OPENSSL_HEADER_OPENSSLFEATURES_H */
diff --git a/src/include/openssl/opensslv.h b/src/include/openssl/opensslv.h
new file mode 100644
index 0000000..c2b3fe7
--- /dev/null
+++ b/src/include/openssl/opensslv.h
@@ -0,0 +1,18 @@
+/* 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. */
+
+/* This header is provided in order to make compiling against code that expects
+ OpenSSL easier. */
+
+#include "base.h"
diff --git a/src/include/openssl/ossl_typ.h b/src/include/openssl/ossl_typ.h
new file mode 100644
index 0000000..c2b3fe7
--- /dev/null
+++ b/src/include/openssl/ossl_typ.h
@@ -0,0 +1,18 @@
+/* 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. */
+
+/* This header is provided in order to make compiling against code that expects
+ OpenSSL easier. */
+
+#include "base.h"
diff --git a/src/include/openssl/pem.h b/src/include/openssl/pem.h
new file mode 100644
index 0000000..5f61cab
--- /dev/null
+++ b/src/include/openssl/pem.h
@@ -0,0 +1,558 @@
+/* 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 OPENSSL_HEADER_PEM_H
+#define OPENSSL_HEADER_PEM_H
+
+#include <openssl/base64.h>
+#include <openssl/bio.h>
+#include <openssl/cipher.h>
+#include <openssl/digest.h>
+#include <openssl/evp.h>
+#include <openssl/stack.h>
+#include <openssl/x509.h>
+
+#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_PAIR "CERTIFICATE PAIR"
+#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_DHXPARAMS "X9.42 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"
+
+ /* Note that this structure is initialised by PEM_SealInit and cleaned up
+ by PEM_SealFinal (at least for now) */
+typedef struct PEM_Encode_Seal_st
+ {
+ EVP_ENCODE_CTX encode;
+ EVP_MD_CTX md;
+ EVP_CIPHER_CTX cipher;
+ } PEM_ENCODE_SEAL_CTX;
+
+/* 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;
+
+ 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;
+
+/* 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(...)
+ */
+
+#ifdef OPENSSL_NO_FP_API
+
+#define IMPLEMENT_PEM_read_fp(name, type, str, asn1) /**/
+#define IMPLEMENT_PEM_write_fp(name, type, str, asn1) /**/
+#define IMPLEMENT_PEM_write_fp_const(name, type, str, asn1) /**/
+#define IMPLEMENT_PEM_write_cb_fp(name, type, str, asn1) /**/
+#define IMPLEMENT_PEM_write_cb_fp_const(name, type, str, asn1) /**/
+
+#else
+
+#define IMPLEMENT_PEM_read_fp(name, type, str, asn1) \
+OPENSSL_EXPORT 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) \
+OPENSSL_EXPORT 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) \
+OPENSSL_EXPORT 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) \
+OPENSSL_EXPORT 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) \
+OPENSSL_EXPORT 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); \
+ }
+
+#endif
+
+#define IMPLEMENT_PEM_read_bio(name, type, str, asn1) \
+OPENSSL_EXPORT 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) \
+OPENSSL_EXPORT 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) \
+OPENSSL_EXPORT 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) \
+OPENSSL_EXPORT 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) \
+OPENSSL_EXPORT 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)
+
+/* These are the same except they are for the declarations */
+
+#if defined(OPENSSL_NO_FP_API)
+
+#define DECLARE_PEM_read_fp(name, type) /**/
+#define DECLARE_PEM_write_fp(name, type) /**/
+#define DECLARE_PEM_write_cb_fp(name, type) /**/
+
+#else
+
+#define DECLARE_PEM_read_fp(name, type) \
+ OPENSSL_EXPORT type *PEM_read_##name(FILE *fp, type **x, pem_password_cb *cb, void *u);
+
+#define DECLARE_PEM_write_fp(name, type) \
+ OPENSSL_EXPORT int PEM_write_##name(FILE *fp, type *x);
+
+#define DECLARE_PEM_write_fp_const(name, type) \
+ OPENSSL_EXPORT int PEM_write_##name(FILE *fp, const type *x);
+
+#define DECLARE_PEM_write_cb_fp(name, type) \
+ OPENSSL_EXPORT int PEM_write_##name(FILE *fp, type *x, const EVP_CIPHER *enc, \
+ unsigned char *kstr, int klen, pem_password_cb *cb, void *u);
+
+#endif
+
+#define DECLARE_PEM_read_bio(name, type) \
+ OPENSSL_EXPORT type *PEM_read_bio_##name(BIO *bp, type **x, pem_password_cb *cb, void *u);
+
+#define DECLARE_PEM_write_bio(name, type) \
+ OPENSSL_EXPORT int PEM_write_bio_##name(BIO *bp, type *x);
+
+#define DECLARE_PEM_write_bio_const(name, type) \
+ OPENSSL_EXPORT int PEM_write_bio_##name(BIO *bp, const type *x);
+
+#define DECLARE_PEM_write_cb_bio(name, type) \
+ OPENSSL_EXPORT int PEM_write_bio_##name(BIO *bp, type *x, const EVP_CIPHER *enc, \
+ unsigned char *kstr, int klen, pem_password_cb *cb, void *u);
+
+
+#define DECLARE_PEM_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)
+
+#if 1
+/* "userdata": new with OpenSSL 0.9.4 */
+typedef int pem_password_cb(char *buf, int size, int rwflag, void *userdata);
+#else
+/* OpenSSL 0.9.3, 0.9.3a */
+typedef int pem_password_cb(char *buf, int size, int rwflag);
+#endif
+
+OPENSSL_EXPORT int PEM_get_EVP_CIPHER_INFO(char *header, EVP_CIPHER_INFO *cipher);
+OPENSSL_EXPORT int PEM_do_header (EVP_CIPHER_INFO *cipher, unsigned char *data,long *len, pem_password_cb *callback,void *u);
+
+OPENSSL_EXPORT int PEM_read_bio(BIO *bp, char **name, char **header, unsigned char **data,long *len);
+OPENSSL_EXPORT int PEM_write_bio(BIO *bp,const char *name, const char *hdr, const unsigned char *data, long len);
+OPENSSL_EXPORT int PEM_bytes_read_bio(unsigned char **pdata, long *plen, char **pnm, const char *name, BIO *bp, pem_password_cb *cb, void *u);
+OPENSSL_EXPORT void * PEM_ASN1_read_bio(d2i_of_void *d2i, const char *name, BIO *bp, void **x, pem_password_cb *cb, void *u);
+OPENSSL_EXPORT 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);
+
+OPENSSL_EXPORT STACK_OF(X509_INFO) * PEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk, pem_password_cb *cb, void *u);
+OPENSSL_EXPORT 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);
+
+OPENSSL_EXPORT int PEM_read(FILE *fp, char **name, char **header, unsigned char **data,long *len);
+OPENSSL_EXPORT int PEM_write(FILE *fp, const char *name, const char *hdr, const unsigned char *data, long len);
+OPENSSL_EXPORT void * PEM_ASN1_read(d2i_of_void *d2i, const char *name, FILE *fp, void **x, pem_password_cb *cb, void *u);
+OPENSSL_EXPORT 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);
+OPENSSL_EXPORT STACK_OF(X509_INFO) * PEM_X509_INFO_read(FILE *fp, STACK_OF(X509_INFO) *sk, pem_password_cb *cb, void *u);
+
+OPENSSL_EXPORT int PEM_SealInit(PEM_ENCODE_SEAL_CTX *ctx, EVP_CIPHER *type, EVP_MD *md_type, unsigned char **ek, int *ekl, unsigned char *iv, EVP_PKEY **pubk, int npubk);
+OPENSSL_EXPORT void PEM_SealUpdate(PEM_ENCODE_SEAL_CTX *ctx, unsigned char *out, int *outl, unsigned char *in, int inl);
+OPENSSL_EXPORT int PEM_SealFinal(PEM_ENCODE_SEAL_CTX *ctx, unsigned char *sig,int *sigl, unsigned char *out, int *outl, EVP_PKEY *priv);
+
+OPENSSL_EXPORT void PEM_SignInit(EVP_MD_CTX *ctx, EVP_MD *type);
+OPENSSL_EXPORT void PEM_SignUpdate(EVP_MD_CTX *ctx,unsigned char *d,unsigned int cnt);
+OPENSSL_EXPORT int PEM_SignFinal(EVP_MD_CTX *ctx, unsigned char *sigret, unsigned int *siglen, EVP_PKEY *pkey);
+
+OPENSSL_EXPORT int PEM_def_callback(char *buf, int num, int w, void *key);
+OPENSSL_EXPORT void PEM_proc_type(char *buf, int type);
+OPENSSL_EXPORT 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_CERT_PAIR, X509_CERT_PAIR)
+
+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(NETSCAPE_CERT_SEQUENCE, NETSCAPE_CERT_SEQUENCE)
+
+DECLARE_PEM_rw(PKCS8, X509_SIG)
+
+DECLARE_PEM_rw(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO)
+
+DECLARE_PEM_rw_cb(RSAPrivateKey, RSA)
+
+DECLARE_PEM_rw_const(RSAPublicKey, RSA)
+DECLARE_PEM_rw(RSA_PUBKEY, RSA)
+
+#ifndef OPENSSL_NO_DSA
+
+DECLARE_PEM_rw_cb(DSAPrivateKey, DSA)
+
+DECLARE_PEM_rw(DSA_PUBKEY, DSA)
+
+DECLARE_PEM_rw_const(DSAparams, DSA)
+
+#endif
+
+DECLARE_PEM_rw_const(ECPKParameters, EC_GROUP)
+DECLARE_PEM_rw_cb(ECPrivateKey, EC_KEY)
+DECLARE_PEM_rw(EC_PUBKEY, EC_KEY)
+
+
+DECLARE_PEM_rw_const(DHparams, DH)
+DECLARE_PEM_write_const(DHxparams, DH)
+
+
+DECLARE_PEM_rw_cb(PrivateKey, EVP_PKEY)
+
+DECLARE_PEM_rw(PUBKEY, EVP_PKEY)
+
+OPENSSL_EXPORT int PEM_write_bio_PKCS8PrivateKey_nid(BIO *bp, EVP_PKEY *x, int nid, char *kstr, int klen, pem_password_cb *cb, void *u);
+OPENSSL_EXPORT int PEM_write_bio_PKCS8PrivateKey(BIO *, EVP_PKEY *, const EVP_CIPHER *, char *, int, pem_password_cb *, void *);
+OPENSSL_EXPORT int i2d_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc, char *kstr, int klen, pem_password_cb *cb, void *u);
+OPENSSL_EXPORT int i2d_PKCS8PrivateKey_nid_bio(BIO *bp, EVP_PKEY *x, int nid, char *kstr, int klen, pem_password_cb *cb, void *u);
+OPENSSL_EXPORT EVP_PKEY *d2i_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY **x, pem_password_cb *cb, void *u);
+
+OPENSSL_EXPORT int i2d_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc, char *kstr, int klen, pem_password_cb *cb, void *u);
+OPENSSL_EXPORT int i2d_PKCS8PrivateKey_nid_fp(FILE *fp, EVP_PKEY *x, int nid, char *kstr, int klen, pem_password_cb *cb, void *u);
+OPENSSL_EXPORT int PEM_write_PKCS8PrivateKey_nid(FILE *fp, EVP_PKEY *x, int nid, char *kstr, int klen, pem_password_cb *cb, void *u);
+
+OPENSSL_EXPORT EVP_PKEY *d2i_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY **x, pem_password_cb *cb, void *u);
+
+OPENSSL_EXPORT int PEM_write_PKCS8PrivateKey(FILE *fp,EVP_PKEY *x,const EVP_CIPHER *enc, char *kstr,int klen, pem_password_cb *cd, void *u);
+
+OPENSSL_EXPORT EVP_PKEY *PEM_read_bio_Parameters(BIO *bp, EVP_PKEY **x);
+OPENSSL_EXPORT int PEM_write_bio_Parameters(BIO *bp, EVP_PKEY *x);
+
+
+OPENSSL_EXPORT EVP_PKEY *b2i_PrivateKey(const unsigned char **in, long length);
+OPENSSL_EXPORT EVP_PKEY *b2i_PublicKey(const unsigned char **in, long length);
+OPENSSL_EXPORT EVP_PKEY *b2i_PrivateKey_bio(BIO *in);
+OPENSSL_EXPORT EVP_PKEY *b2i_PublicKey_bio(BIO *in);
+OPENSSL_EXPORT int i2b_PrivateKey_bio(BIO *out, EVP_PKEY *pk);
+OPENSSL_EXPORT int i2b_PublicKey_bio(BIO *out, EVP_PKEY *pk);
+OPENSSL_EXPORT EVP_PKEY *b2i_PVK_bio(BIO *in, pem_password_cb *cb, void *u);
+OPENSSL_EXPORT int i2b_PVK_bio(BIO *out, EVP_PKEY *pk, int enclevel, pem_password_cb *cb, void *u);
+
+
+void ERR_load_PEM_strings(void);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#define PEM_F_PEM_read_bio_DHparams 100
+#define PEM_F_load_iv 101
+#define PEM_F_PEM_write 102
+#define PEM_F_do_pk8pkey_fp 103
+#define PEM_F_PEM_read_PrivateKey 104
+#define PEM_F_PEM_read_DHparams 105
+#define PEM_F_PEM_ASN1_read_bio 106
+#define PEM_F_PEM_ASN1_read 107
+#define PEM_F_PEM_get_EVP_CIPHER_INFO 108
+#define PEM_F_PEM_X509_INFO_read 109
+#define PEM_F_PEM_read_bio_Parameters 110
+#define PEM_F_PEM_read 111
+#define PEM_F_PEM_X509_INFO_read_bio 112
+#define PEM_F_PEM_X509_INFO_write_bio 113
+#define PEM_F_PEM_ASN1_write 114
+#define PEM_F_d2i_PKCS8PrivateKey_bio 115
+#define PEM_F_d2i_PKCS8PrivateKey_fp 116
+#define PEM_F_PEM_read_bio_PrivateKey 117
+#define PEM_F_PEM_write_PrivateKey 118
+#define PEM_F_PEM_ASN1_write_bio 119
+#define PEM_F_PEM_do_header 120
+#define PEM_F_PEM_write_bio 121
+#define PEM_F_do_pk8pkey 122
+#define PEM_F_PEM_read_bio 123
+#define PEM_R_NO_START_LINE 100
+#define PEM_R_NOT_PROC_TYPE 101
+#define PEM_R_SHORT_HEADER 102
+#define PEM_R_BAD_IV_CHARS 103
+#define PEM_R_ERROR_CONVERTING_PRIVATE_KEY 104
+#define PEM_R_BAD_END_LINE 105
+#define PEM_R_CIPHER_IS_NULL 106
+#define PEM_R_BAD_MAGIC_NUMBER 107
+#define PEM_R_BAD_DECRYPT 108
+#define PEM_R_UNSUPPORTED_ENCRYPTION 109
+#define PEM_R_PVK_DATA_TOO_SHORT 110
+#define PEM_R_PROBLEMS_GETTING_PASSWORD 111
+#define PEM_R_KEYBLOB_HEADER_PARSE_ERROR 112
+#define PEM_R_BIO_WRITE_FAILURE 113
+#define PEM_R_INCONSISTENT_HEADER 114
+#define PEM_R_PUBLIC_KEY_NO_RSA 115
+#define PEM_R_EXPECTING_PUBLIC_KEY_BLOB 116
+#define PEM_R_KEYBLOB_TOO_SHORT 117
+#define PEM_R_BAD_BASE64_DECODE 118
+#define PEM_R_READ_KEY 119
+#define PEM_R_BAD_PASSWORD_READ 120
+#define PEM_R_UNSUPPORTED_KEY_COMPONENTS 121
+#define PEM_R_UNSUPPORTED_CIPHER 122
+#define PEM_R_NOT_ENCRYPTED 123
+#define PEM_R_NOT_DEK_INFO 124
+#define PEM_R_BAD_VERSION_NUMBER 125
+#define PEM_R_EXPECTING_PRIVATE_KEY_BLOB 126
+#define PEM_R_PVK_TOO_SHORT 127
+
+#endif /* OPENSSL_HEADER_PEM_H */
diff --git a/src/include/openssl/pkcs12.h b/src/include/openssl/pkcs12.h
new file mode 100644
index 0000000..b5e9516
--- /dev/null
+++ b/src/include/openssl/pkcs12.h
@@ -0,0 +1,18 @@
+/* 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. */
+
+/* This header is provided in order to make compiling against code that expects
+ OpenSSL easier. */
+
+#include "pkcs8.h"
diff --git a/src/include/openssl/pkcs7.h b/src/include/openssl/pkcs7.h
new file mode 100644
index 0000000..6e5e433
--- /dev/null
+++ b/src/include/openssl/pkcs7.h
@@ -0,0 +1,16 @@
+/* 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. */
+
+/* This header is provided in order to make compiling against code that expects
+ OpenSSL easier. */
diff --git a/src/include/openssl/pkcs8.h b/src/include/openssl/pkcs8.h
new file mode 100644
index 0000000..826ac7f
--- /dev/null
+++ b/src/include/openssl/pkcs8.h
@@ -0,0 +1,223 @@
+/* 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 OPENSSL_HEADER_PKCS8_H
+#define OPENSSL_HEADER_PKCS8_H
+
+#include <openssl/base.h>
+
+#include <stdio.h>
+
+#include <openssl/x509.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* PKCS8_encrypt_pbe serializes and encrypts a PKCS8_PRIV_KEY_INFO with PBES1 as
+ * defined in PKCS #5. Only pbeWithSHAAnd128BitRC4,
+ * pbeWithSHAAnd3-KeyTripleDES-CBC and pbeWithSHA1And40BitRC2, defined in PKCS
+ * #12, are supported. The |pass_raw_len| bytes pointed to by |pass_raw| are
+ * used as the password. Note that any conversions from the password as
+ * supplied in a text string (such as those specified in B.1 of PKCS #12) must
+ * be performed by the caller.
+ *
+ * If |salt| is NULL, a random salt of |salt_len| bytes is generated. If
+ * |salt_len| is zero, a default salt length is used instead.
+ *
+ * The resulting structure is stored in an X509_SIG which must be freed by the
+ * caller.
+ *
+ * TODO(davidben): Really? An X509_SIG? OpenSSL probably did that because it has
+ * the same structure as EncryptedPrivateKeyInfo. */
+OPENSSL_EXPORT X509_SIG *PKCS8_encrypt_pbe(int pbe_nid,
+ const uint8_t *pass_raw,
+ size_t pass_raw_len,
+ uint8_t *salt, size_t salt_len,
+ int iterations,
+ PKCS8_PRIV_KEY_INFO *p8inf);
+
+/* PKCS8_decrypt_pbe decrypts and decodes a PKCS8_PRIV_KEY_INFO with PBES1 as
+ * defined in PKCS #5. Only pbeWithSHAAnd128BitRC4,
+ * pbeWithSHAAnd3-KeyTripleDES-CBC and pbeWithSHA1And40BitRC2, defined in PKCS
+ * #12, are supported. The |pass_raw_len| bytes pointed to by |pass_raw| are
+ * used as the password. Note that any conversions from the password as
+ * supplied in a text string (such as those specified in B.1 of PKCS #12) must
+ * be performed by the caller.
+ *
+ * The resulting structure must be freed by the caller. */
+OPENSSL_EXPORT PKCS8_PRIV_KEY_INFO *PKCS8_decrypt_pbe(X509_SIG *pkcs8,
+ const uint8_t *pass_raw,
+ size_t pass_raw_len);
+
+
+/* Deprecated functions. */
+
+/* PKCS8_encrypt calls PKCS8_encrypt_pbe after treating |pass| as an ASCII
+ * string, appending U+0000, and converting to UCS-2. (So the empty password
+ * encodes as two NUL bytes.) The |cipher| argument is ignored. */
+OPENSSL_EXPORT X509_SIG *PKCS8_encrypt(int pbe_nid, const EVP_CIPHER *cipher,
+ const char *pass, int pass_len,
+ uint8_t *salt, size_t salt_len,
+ int iterations,
+ PKCS8_PRIV_KEY_INFO *p8inf);
+
+/* PKCS8_decrypt calls PKCS8_decrypt_pbe after treating |pass| as an ASCII
+ * string, appending U+0000, and converting to UCS-2. (So the empty password
+ * encodes as two NUL bytes.) */
+OPENSSL_EXPORT PKCS8_PRIV_KEY_INFO *PKCS8_decrypt(X509_SIG *pkcs8,
+ const char *pass,
+ int pass_len);
+
+/* PKCS12_get_key_and_certs parses a PKCS#12 structure from |in|, authenticates
+ * and decrypts it using |password|, sets |*out_key| to the included private
+ * key and appends the included certificates to |out_certs|. It returns one on
+ * success and zero on error. The caller takes ownership of the outputs. */
+OPENSSL_EXPORT int PKCS12_get_key_and_certs(EVP_PKEY **out_key,
+ STACK_OF(X509) *out_certs,
+ CBS *in, const char *password);
+
+
+/* Deprecated functions. */
+
+/* PKCS12_PBE_add does nothing. It exists for compatibility with OpenSSL. */
+OPENSSL_EXPORT void PKCS12_PBE_add(void);
+
+/* d2i_PKCS12 is a dummy function that copies |*ber_bytes| into a
+ * |PKCS12| structure. The |out_p12| argument must be NULL. On exit,
+ * |*ber_bytes| will be advanced by |ber_len|. It returns a fresh |PKCS12|
+ * structure or NULL on error.
+ *
+ * Note: unlike other d2i functions, |d2i_PKCS12| will always consume |ber_len|
+ * bytes.*/
+OPENSSL_EXPORT PKCS12 *d2i_PKCS12(PKCS12 **out_p12, const uint8_t **ber_bytes,
+ size_t ber_len);
+
+/* d2i_PKCS12_bio acts like |d2i_PKCS12| but reads from a |BIO|. */
+OPENSSL_EXPORT PKCS12* d2i_PKCS12_bio(BIO *bio, PKCS12 **out_p12);
+
+/* d2i_PKCS12_fp acts like |d2i_PKCS12| but reads from a |FILE|. */
+OPENSSL_EXPORT PKCS12* d2i_PKCS12_fp(FILE *fp, PKCS12 **out_p12);
+
+/* PKCS12_parse calls |PKCS12_get_key_and_certs| on the ASN.1 data stored in
+ * |p12|. The |out_pkey| and |out_cert| arguments must not be NULL and, on
+ * successful exit, the private key and first certificate will be stored in
+ * them. The |out_ca_certs| argument may be NULL but, if not, then any extra
+ * certificates will be appended to |*out_ca_certs|. If |*out_ca_certs| is NULL
+ * then it will be set to a freshly allocated stack containing the extra certs.
+ *
+ * It returns one on success and zero on error. */
+OPENSSL_EXPORT int PKCS12_parse(const PKCS12 *p12, const char *password,
+ EVP_PKEY **out_pkey, X509 **out_cert,
+ STACK_OF(X509) **out_ca_certs);
+
+/* PKCS12_free frees |p12| and its contents. */
+OPENSSL_EXPORT void PKCS12_free(PKCS12 *p12);
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#define PKCS8_F_PKCS8_encrypt 100
+#define PKCS8_F_EVP_PKEY2PKCS8 101
+#define PKCS8_F_EVP_PKCS82PKEY 102
+#define PKCS8_F_PKCS5_pbe_set0_algor 103
+#define PKCS8_F_pbe_crypt 104
+#define PKCS8_F_pkcs12_item_decrypt_d2i 105
+#define PKCS8_F_PKCS5_pbe_set 106
+#define PKCS8_F_pkcs12_key_gen_uni 107
+#define PKCS8_F_pkcs12_key_gen_asc 108
+#define PKCS8_F_pkcs12_pbe_keyivgen 109
+#define PKCS8_F_pbe_cipher_init 110
+#define PKCS8_F_pkcs12_item_i2d_encrypt 111
+#define PKCS8_F_PKCS5_pbe2_set_iv 112
+#define PKCS8_F_PKCS5_pbkdf2_set 113
+#define PKCS8_F_pkcs12_key_gen_raw 114
+#define PKCS8_F_PKCS8_decrypt 115
+#define PKCS8_F_PKCS8_encrypt_pbe 116
+#define PKCS8_F_PKCS12_parse 117
+#define PKCS8_F_PKCS12_handle_content_info 118
+#define PKCS8_F_PKCS12_handle_content_infos 119
+#define PKCS8_F_PKCS12_get_key_and_certs 120
+#define PKCS8_R_ERROR_SETTING_CIPHER_PARAMS 100
+#define PKCS8_R_PRIVATE_KEY_ENCODE_ERROR 101
+#define PKCS8_R_UNKNOWN_ALGORITHM 102
+#define PKCS8_R_UNKNOWN_CIPHER 103
+#define PKCS8_R_UNKNOWN_DIGEST 104
+#define PKCS8_R_ENCODE_ERROR 105
+#define PKCS8_R_DECODE_ERROR 106
+#define PKCS8_R_ENCRYPT_ERROR 107
+#define PKCS8_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM 108
+#define PKCS8_R_PRIVATE_KEY_DECODE_ERROR 109
+#define PKCS8_R_UNKNOWN_CIPHER_ALGORITHM 110
+#define PKCS8_R_KEYGEN_FAILURE 111
+#define PKCS8_R_TOO_LONG 112
+#define PKCS8_R_CRYPT_ERROR 113
+#define PKCS8_R_METHOD_NOT_SUPPORTED 114
+#define PKCS8_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER 115
+#define PKCS8_R_KEY_GEN_ERROR 116
+#define PKCS8_R_BAD_PKCS12_DATA 117
+#define PKCS8_R_PKCS12_PUBLIC_KEY_INTEGRITY_NOT_SUPPORTED 118
+#define PKCS8_R_BAD_PKCS12_VERSION 119
+#define PKCS8_R_PKCS12_TOO_DEEPLY_NESTED 120
+#define PKCS8_R_MULTIPLE_PRIVATE_KEYS_IN_PKCS12 121
+#define PKCS8_R_UNKNOWN_HASH 122
+#define PKCS8_R_BAD_MAC 123
+#define PKCS8_R_MISSING_MAC 124
+#define PKCS8_R_INCORRECT_PASSWORD 125
+
+#endif /* OPENSSL_HEADER_PKCS8_H */
diff --git a/src/include/openssl/poly1305.h b/src/include/openssl/poly1305.h
new file mode 100644
index 0000000..aa90486
--- /dev/null
+++ b/src/include/openssl/poly1305.h
@@ -0,0 +1,47 @@
+/* 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_POLY1305_H
+#define OPENSSL_HEADER_POLY1305_H
+
+#include <openssl/base.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef unsigned char poly1305_state[512];
+
+/* poly1305_init sets up |state| so that it can be used to calculate an
+ * authentication tag with the one-time key |key|. Note that |key| is a
+ * one-time key and therefore there is no `reset' method because that would
+ * enable several messages to be authenticated with the same key. */
+extern void CRYPTO_poly1305_init(poly1305_state* state, const uint8_t key[32]);
+
+/* poly1305_update processes |in_len| bytes from |in|. It can be called zero or
+ * more times after poly1305_init. */
+extern void CRYPTO_poly1305_update(poly1305_state* state, const uint8_t* in,
+ size_t in_len);
+
+/* poly1305_finish completes the poly1305 calculation and writes a 16 byte
+ * authentication tag to |mac|. The |mac| address must be 16-byte aligned. */
+extern void CRYPTO_poly1305_finish(poly1305_state* state, uint8_t mac[16]);
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_POLY1305_H */
diff --git a/src/include/openssl/pqueue.h b/src/include/openssl/pqueue.h
new file mode 100644
index 0000000..ceb1fa2
--- /dev/null
+++ b/src/include/openssl/pqueue.h
@@ -0,0 +1,146 @@
+/*
+ * 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 OPENSSL_HEADER_PQUEUE_H
+#define OPENSSL_HEADER_PQUEUE_H
+
+#include <openssl/base.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* Priority queue.
+ *
+ * The priority queue maintains a linked-list of nodes, each with a unique,
+ * 64-bit priority, in ascending priority order. */
+
+typedef struct _pqueue *pqueue;
+
+typedef struct _pitem {
+ uint8_t priority[8]; /* 64-bit value in big-endian encoding */
+ void *data;
+ struct _pitem *next;
+} pitem;
+
+typedef struct _pitem *piterator;
+
+
+/* Creating and freeing queues. */
+
+/* pqueue_new allocates a fresh, empty priority queue object and returns it, or
+ * NULL on error. */
+OPENSSL_EXPORT pqueue pqueue_new(void);
+
+/* pqueue_free frees |pq| but not any of the items it points to. Thus |pq| must
+ * be empty or a memory leak will occur. */
+OPENSSL_EXPORT void pqueue_free(pqueue pq);
+
+
+/* Creating and freeing items. */
+
+/* pitem_new allocates a fresh priority queue item that points at |data| and
+ * has a priority given by |prio64be|, which is a 64-bit, unsigned number
+ * expressed in big-endian form. It returns the fresh item, or NULL on
+ * error. */
+OPENSSL_EXPORT pitem *pitem_new(uint8_t prio64be[8], void *data);
+
+/* pitem_free frees |item|, but not any data that it points to. */
+OPENSSL_EXPORT void pitem_free(pitem *item);
+
+
+/* Queue accessor functions */
+
+/* pqueue_peek returns the item with the smallest priority from |pq|, or NULL
+ * if empty. */
+OPENSSL_EXPORT pitem *pqueue_peek(pqueue pq);
+
+/* pqueue_find returns the item whose priority matches |prio64be| or NULL if no
+ * such item exists. */
+OPENSSL_EXPORT pitem *pqueue_find(pqueue pq, uint8_t *prio64be);
+
+
+/* Queue mutation functions */
+
+/* pqueue_insert inserts |item| into |pq| and returns item. */
+OPENSSL_EXPORT pitem *pqueue_insert(pqueue pq, pitem *item);
+
+/* pqueue_pop takes the item with the least priority from |pq| and returns it,
+ * or NULL if |pq| is empty. */
+OPENSSL_EXPORT pitem *pqueue_pop(pqueue pq);
+
+/* pqueue_size returns the number of items in |pq|. */
+OPENSSL_EXPORT size_t pqueue_size(pqueue pq);
+
+
+/* Iterating */
+
+/* pqueue_iterator returns an iterator that can be used to iterate over the
+ * contents of the queue. */
+OPENSSL_EXPORT piterator pqueue_iterator(pqueue pq);
+
+/* pqueue_next returns the current value of |iter| and advances it to the next
+ * position. If the iterator has advanced over all the elements, it returns
+ * NULL. */
+OPENSSL_EXPORT pitem *pqueue_next(piterator *iter);
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_PQUEUE_H */
diff --git a/src/include/openssl/rand.h b/src/include/openssl/rand.h
new file mode 100644
index 0000000..5a84a89
--- /dev/null
+++ b/src/include/openssl/rand.h
@@ -0,0 +1,53 @@
+/* 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_RAND_H
+#define OPENSSL_HEADER_RAND_H
+
+#include <openssl/base.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* RAND_bytes writes |len| bytes of random data to |buf|. It returns one on
+ * success and zero on otherwise. */
+OPENSSL_EXPORT int RAND_bytes(uint8_t *buf, size_t len);
+
+/* RAND_cleanup frees any resources used by the RNG. This is not safe if other
+ * threads might still be calling |RAND_bytes|. */
+OPENSSL_EXPORT void RAND_cleanup(void);
+
+
+/* Deprecated functions */
+
+/* RAND_pseudo_bytes is a wrapper around |RAND_bytes|. */
+OPENSSL_EXPORT int RAND_pseudo_bytes(uint8_t *buf, size_t len);
+
+/* RAND_seed does nothing. */
+OPENSSL_EXPORT void RAND_seed(const void *buf, int num);
+
+/* RAND_add does nothing. */
+OPENSSL_EXPORT void RAND_add(const void *buf, int num, double entropy);
+
+/* RAND_poll returns one. */
+OPENSSL_EXPORT int RAND_poll(void);
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_RAND_H */
diff --git a/src/include/openssl/rc4.h b/src/include/openssl/rc4.h
new file mode 100644
index 0000000..727b474
--- /dev/null
+++ b/src/include/openssl/rc4.h
@@ -0,0 +1,93 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 OPENSSL_HEADER_RC4_H
+#define OPENSSL_HEADER_RC4_H
+
+#include <openssl/base.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* RC4. */
+
+
+typedef struct rc4_key_st {
+ uint32_t x, y;
+ /* data is sometimes used as an array of 32-bit values and sometimes as 8-bit
+ * values, depending on the platform. */
+ uint32_t data[256];
+} RC4_KEY;
+
+
+/* RC4_set_key performs an RC4 key schedule and initialises |rc4key| with |len|
+ * bytes of key material from |key|. */
+OPENSSL_EXPORT void RC4_set_key(RC4_KEY *rc4key, unsigned len,
+ const uint8_t *key);
+
+/* RC4 encrypts (or decrypts, it's the same with RC4) |len| bytes from |in| to
+ * |out|. */
+OPENSSL_EXPORT void RC4(RC4_KEY *key, size_t len, const uint8_t *in,
+ uint8_t *out);
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_RC4_H */
diff --git a/src/include/openssl/rsa.h b/src/include/openssl/rsa.h
new file mode 100644
index 0000000..ff2bd8b
--- /dev/null
+++ b/src/include/openssl/rsa.h
@@ -0,0 +1,541 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 OPENSSL_HEADER_RSA_H
+#define OPENSSL_HEADER_RSA_H
+
+#include <openssl/base.h>
+
+#include <openssl/engine.h>
+#include <openssl/ex_data.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* rsa.h contains functions for handling encryption and signature using RSA. */
+
+
+/* Allocation and destruction. */
+
+/* RSA_new returns a new, empty RSA object or NULL on error. */
+OPENSSL_EXPORT RSA *RSA_new(void);
+
+/* RSA_new_method acts the same as |RSA_new| but takes an explicit |ENGINE|. */
+OPENSSL_EXPORT RSA *RSA_new_method(const ENGINE *engine);
+
+/* RSA_free decrements the reference count of |rsa| and frees it if the
+ * reference count drops to zero. */
+OPENSSL_EXPORT void RSA_free(RSA *rsa);
+
+/* RSA_up_ref increments the reference count of |rsa|. */
+OPENSSL_EXPORT int RSA_up_ref(RSA *rsa);
+
+
+/* Key generation. */
+
+/* RSA_generate_key_ex generates a new RSA key where the modulus has size
+ * |bits| and the public exponent is |e|. If unsure, |RSA_F4| is a good value
+ * for |e|. If |cb| is not NULL then it is called during the key generation
+ * process. In addition to the calls documented for |BN_generate_prime_ex|, it
+ * is called with event=2 when the n'th prime is rejected as unsuitable and
+ * with event=3 when a suitable value for |p| is found.
+ *
+ * It returns one on success or zero on error. */
+OPENSSL_EXPORT int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e,
+ BN_GENCB *cb);
+
+
+/* Encryption / Decryption */
+
+/* Padding types for encryption. */
+#define RSA_PKCS1_PADDING 1
+#define RSA_NO_PADDING 3
+#define RSA_PKCS1_OAEP_PADDING 4
+/* RSA_PKCS1_PSS_PADDING can only be used via the EVP interface. */
+#define RSA_PKCS1_PSS_PADDING 6
+
+/* RSA_encrypt encrypts |in_len| bytes from |in| to the public key from |rsa|
+ * and writes, at most, |max_out| bytes of encrypted data to |out|. The
+ * |max_out| argument must be, at least, |RSA_size| in order to ensure success.
+ *
+ * It returns 1 on success or zero on error.
+ *
+ * The |padding| argument must be one of the |RSA_*_PADDING| values. If in
+ * doubt, |RSA_PKCS1_PADDING| is the most common but |RSA_PKCS1_OAEP_PADDING|
+ * is the most secure. */
+OPENSSL_EXPORT int RSA_encrypt(RSA *rsa, size_t *out_len, uint8_t *out,
+ size_t max_out, const uint8_t *in, size_t in_len,
+ int padding);
+
+/* RSA_decrypt decrypts |in_len| bytes from |in| with the private key from
+ * |rsa| and writes, at most, |max_out| bytes of plaintext to |out|. The
+ * |max_out| argument must be, at least, |RSA_size| in order to ensure success.
+ *
+ * It returns 1 on success or zero on error.
+ *
+ * The |padding| argument must be one of the |RSA_*_PADDING| values. If in
+ * doubt, |RSA_PKCS1_PADDING| is the most common but |RSA_PKCS1_OAEP_PADDING|
+ * is the most secure. */
+OPENSSL_EXPORT int RSA_decrypt(RSA *rsa, size_t *out_len, uint8_t *out,
+ size_t max_out, const uint8_t *in, size_t in_len,
+ int padding);
+
+/* RSA_public_encrypt encrypts |flen| bytes from |from| to the public key in
+ * |rsa| and writes the encrypted data to |to|. The |to| buffer must have at
+ * least |RSA_size| bytes of space. It returns the number of bytes written, or
+ * -1 on error. The |padding| argument must be one of the |RSA_*_PADDING|
+ * values. If in doubt, |RSA_PKCS1_PADDING| is the most common but
+ * |RSA_PKCS1_OAEP_PADDING| is the most secure.
+ *
+ * WARNING: this function is dangerous because it breaks the usual return value
+ * convention. Use |RSA_encrypt| instead. */
+OPENSSL_EXPORT int RSA_public_encrypt(int flen, const uint8_t *from,
+ uint8_t *to, RSA *rsa, int padding);
+
+/* RSA_private_decrypt decrypts |flen| bytes from |from| with the public key in
+ * |rsa| and writes the plaintext to |to|. The |to| buffer must have at
+ * least |RSA_size| bytes of space. It returns the number of bytes written, or
+ * -1 on error. The |padding| argument must be one of the |RSA_*_PADDING|
+ * values. If in doubt, |RSA_PKCS1_PADDING| is the most common but
+ * |RSA_PKCS1_OAEP_PADDING| is the most secure.
+ *
+ * WARNING: this function is dangerous because it breaks the usual return value
+ * convention. Use |RSA_decrypt| instead. */
+OPENSSL_EXPORT int RSA_private_decrypt(int flen, const uint8_t *from,
+ uint8_t *to, RSA *rsa, int padding);
+
+/* RSA_message_index_PKCS1_type_2 performs the first step of a PKCS #1 padding
+ * check for decryption. If the |from_len| bytes pointed to at |from| are a
+ * valid PKCS #1 message, it returns one and sets |*out_index| to the start of
+ * the unpadded message. The unpadded message is a suffix of the input and has
+ * length |from_len - *out_index|. Otherwise, it returns zero and sets
+ * |*out_index| to zero. This function runs in time independent of the input
+ * data and is intended to be used directly to avoid Bleichenbacher's attack.
+ *
+ * WARNING: This function behaves differently from the usual OpenSSL convention
+ * in that it does NOT put an error on the queue in the error case. */
+OPENSSL_EXPORT int RSA_message_index_PKCS1_type_2(const uint8_t *from,
+ size_t from_len,
+ size_t *out_index);
+
+
+/* Signing / Verification */
+
+/* RSA_sign signs |in_len| bytes of digest from |in| with |rsa| and writes, at
+ * most, |RSA_size(rsa)| bytes to |out|. On successful return, the actual
+ * number of bytes written is written to |*out_len|.
+ *
+ * The |hash_nid| argument identifies the hash function used to calculate |in|
+ * and is embedded in the resulting signature. For example, it might be
+ * |NID_sha256|.
+ *
+ * It returns 1 on success and zero on error. */
+OPENSSL_EXPORT int RSA_sign(int hash_nid, const uint8_t *in,
+ unsigned int in_len, uint8_t *out,
+ unsigned int *out_len, RSA *rsa);
+
+/* RSA_sign_raw signs |in_len| bytes from |in| with the public key from |rsa|
+ * and writes, at most, |max_out| bytes of encrypted data to |out|. The
+ * |max_out| argument must be, at least, |RSA_size| in order to ensure success.
+ *
+ * It returns 1 on success or zero on error.
+ *
+ * The |padding| argument must be one of the |RSA_*_PADDING| values. If in
+ * doubt, |RSA_PKCS1_PADDING| is the most common. */
+OPENSSL_EXPORT int RSA_sign_raw(RSA *rsa, size_t *out_len, uint8_t *out,
+ size_t max_out, const uint8_t *in,
+ size_t in_len, int padding);
+
+/* RSA_verify verifies that |sig_len| bytes from |sig| are a valid, PKCS#1
+ * signature of |msg_len| bytes at |msg| by |rsa|.
+ *
+ * The |hash_nid| argument identifies the hash function used to calculate |in|
+ * and is embedded in the resulting signature in order to prevent hash
+ * confusion attacks. For example, it might be |NID_sha256|.
+ *
+ * It returns one if the signature is valid and zero otherwise.
+ *
+ * WARNING: this differs from the original, OpenSSL function which additionally
+ * returned -1 on error. */
+OPENSSL_EXPORT int RSA_verify(int hash_nid, const uint8_t *msg, size_t msg_len,
+ const uint8_t *sig, size_t sig_len, RSA *rsa);
+
+/* RSA_verify_raw verifies |in_len| bytes of signature from |in| using the
+ * public key from |rsa| and writes, at most, |max_out| bytes of plaintext to
+ * |out|. The |max_out| argument must be, at least, |RSA_size| in order to
+ * ensure success.
+ *
+ * It returns 1 on success or zero on error.
+ *
+ * The |padding| argument must be one of the |RSA_*_PADDING| values. If in
+ * doubt, |RSA_PKCS1_PADDING| is the most common. */
+OPENSSL_EXPORT int RSA_verify_raw(RSA *rsa, size_t *out_len, uint8_t *out,
+ size_t max_out, const uint8_t *in,
+ size_t in_len, int padding);
+
+/* RSA_private_encrypt encrypts |flen| bytes from |from| with the private key in
+ * |rsa| and writes the encrypted data to |to|. The |to| buffer must have at
+ * least |RSA_size| bytes of space. It returns the number of bytes written, or
+ * -1 on error. The |padding| argument must be one of the |RSA_*_PADDING|
+ * values. If in doubt, |RSA_PKCS1_PADDING| is the most common.
+ *
+ * WARNING: this function is dangerous because it breaks the usual return value
+ * convention. Use |RSA_sign_raw| instead. */
+OPENSSL_EXPORT int RSA_private_encrypt(int flen, const uint8_t *from,
+ uint8_t *to, RSA *rsa, int padding);
+
+/* RSA_private_encrypt verifies |flen| bytes of signature from |from| using the
+ * public key in |rsa| and writes the plaintext to |to|. The |to| buffer must
+ * have at least |RSA_size| bytes of space. It returns the number of bytes
+ * written, or -1 on error. The |padding| argument must be one of the
+ * |RSA_*_PADDING| values. If in doubt, |RSA_PKCS1_PADDING| is the most common.
+ *
+ * WARNING: this function is dangerous because it breaks the usual return value
+ * convention. Use |RSA_verify_raw| instead. */
+OPENSSL_EXPORT int RSA_public_decrypt(int flen, const uint8_t *from,
+ uint8_t *to, RSA *rsa, int padding);
+
+
+/* Utility functions. */
+
+/* RSA_size returns the number of bytes in the modulus, which is also the size
+ * of a signature of encrypted value using |rsa|. */
+OPENSSL_EXPORT unsigned RSA_size(const RSA *rsa);
+
+/* RSA_is_opaque returns one if |rsa| is opaque and doesn't expose its key
+ * material. Otherwise it returns zero. */
+OPENSSL_EXPORT int RSA_is_opaque(const RSA *rsa);
+
+/* RSA_supports_digest returns one if |rsa| supports signing digests
+ * of type |md|. Otherwise it returns zero. */
+OPENSSL_EXPORT int RSA_supports_digest(const RSA *rsa, const EVP_MD *md);
+
+/* RSAPublicKey_dup allocates a fresh |RSA| and copies the private key from
+ * |rsa| into it. It returns the fresh |RSA| object, or NULL on error. */
+OPENSSL_EXPORT RSA *RSAPublicKey_dup(const RSA *rsa);
+
+/* RSAPrivateKey_dup allocates a fresh |RSA| and copies the private key from
+ * |rsa| into it. It returns the fresh |RSA| object, or NULL on error. */
+OPENSSL_EXPORT RSA *RSAPrivateKey_dup(const RSA *rsa);
+
+/* RSA_check_key performs basic validatity tests on |rsa|. It returns one if
+ * they pass and zero otherwise. Opaque keys and public keys always pass. If it
+ * returns zero then a more detailed error is available on the error queue. */
+OPENSSL_EXPORT int RSA_check_key(const RSA *rsa);
+
+/* RSA_recover_crt_params uses |rsa->n|, |rsa->d| and |rsa->e| in order to
+ * calculate the two primes used and thus the precomputed, CRT values. These
+ * values are set in the |p|, |q|, |dmp1|, |dmq1| and |iqmp| members of |rsa|,
+ * which must be |NULL| on entry. It returns one on success and zero
+ * otherwise. */
+OPENSSL_EXPORT int RSA_recover_crt_params(RSA *rsa);
+
+
+/* ASN.1 functions. */
+
+/* d2i_RSAPublicKey parses an ASN.1, DER-encoded, RSA public key from |len|
+ * bytes at |*inp|. If |out| is not NULL then, on exit, a pointer to the result
+ * is in |*out|. If |*out| is already non-NULL on entry then the result is
+ * written directly into |*out|, otherwise a fresh |RSA| is allocated. On
+ * successful exit, |*inp| is advanced past the DER structure. It returns the
+ * result or NULL on error. */
+OPENSSL_EXPORT RSA *d2i_RSAPublicKey(RSA **out, const uint8_t **inp, long len);
+
+/* i2d_RSAPublicKey marshals |in| to an ASN.1, DER structure. If |outp| is not
+ * NULL then the result is written to |*outp| and |*outp| is advanced just past
+ * the output. It returns the number of bytes in the result, whether written or
+ * not, or a negative value on error. */
+OPENSSL_EXPORT int i2d_RSAPublicKey(const RSA *in, uint8_t **outp);
+
+/* d2i_RSAPrivateKey parses an ASN.1, DER-encoded, RSA private key from |len|
+ * bytes at |*inp|. If |out| is not NULL then, on exit, a pointer to the result
+ * is in |*out|. If |*out| is already non-NULL on entry then the result is
+ * written directly into |*out|, otherwise a fresh |RSA| is allocated. On
+ * successful exit, |*inp| is advanced past the DER structure. It returns the
+ * result or NULL on error. */
+OPENSSL_EXPORT RSA *d2i_RSAPrivateKey(RSA **out, const uint8_t **inp, long len);
+
+/* i2d_RSAPrivateKey marshals |in| to an ASN.1, DER structure. If |outp| is not
+ * NULL then the result is written to |*outp| and |*outp| is advanced just past
+ * the output. It returns the number of bytes in the result, whether written or
+ * not, or a negative value on error. */
+OPENSSL_EXPORT int i2d_RSAPrivateKey(const RSA *in, uint8_t **outp);
+
+
+/* ex_data functions.
+ *
+ * These functions are wrappers. See |ex_data.h| for details. */
+
+OPENSSL_EXPORT 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);
+OPENSSL_EXPORT int RSA_set_ex_data(RSA *r, int idx, void *arg);
+OPENSSL_EXPORT void *RSA_get_ex_data(const RSA *r, int idx);
+
+/* RSA_FLAG_OPAQUE specifies that this RSA_METHOD does not expose its key
+ * material. This may be set if, for instance, it is wrapping some other crypto
+ * API, like a platform key store. */
+#define RSA_FLAG_OPAQUE 1
+
+/* RSA_FLAG_CACHE_PUBLIC causes a precomputed Montgomery context to be created,
+ * on demand, for the public key operations. */
+#define RSA_FLAG_CACHE_PUBLIC 2
+
+/* RSA_FLAG_CACHE_PRIVATE causes a precomputed Montgomery context to be
+ * created, on demand, for the private key operations. */
+#define RSA_FLAG_CACHE_PRIVATE 4
+
+/* RSA_FLAG_NO_BLINDING disables blinding of private operations. */
+#define RSA_FLAG_NO_BLINDING 8
+
+/* RSA_FLAG_EXT_PKEY means that private key operations will be handled by
+ * |mod_exp| and that they do not depend on the private key components being
+ * present: for example a key stored in external hardware. */
+#define RSA_FLAG_EXT_PKEY 0x20
+
+/* RSA_FLAG_SIGN_VER causes the |sign| and |verify| functions of |rsa_meth_st|
+ * to be called when set. */
+#define RSA_FLAG_SIGN_VER 0x40
+
+
+/* RSA public exponent values. */
+
+#define RSA_3 0x3
+#define RSA_F4 0x10001
+
+
+struct rsa_meth_st {
+ struct openssl_method_common_st common;
+
+ void *app_data;
+
+ int (*init)(RSA *rsa);
+ int (*finish)(RSA *rsa);
+
+ /* size returns the size of the RSA modulus in bytes. */
+ size_t (*size)(const RSA *rsa);
+
+ int (*sign)(int type, const uint8_t *m, unsigned int m_length,
+ uint8_t *sigret, unsigned int *siglen, const RSA *rsa);
+
+ int (*verify)(int dtype, const uint8_t *m, unsigned int m_length,
+ const uint8_t *sigbuf, unsigned int siglen, const RSA *rsa);
+
+
+ /* These functions mirror the |RSA_*| functions of the same name. */
+ int (*encrypt)(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
+ const uint8_t *in, size_t in_len, int padding);
+ int (*sign_raw)(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
+ const uint8_t *in, size_t in_len, int padding);
+
+ int (*decrypt)(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
+ const uint8_t *in, size_t in_len, int padding);
+ int (*verify_raw)(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
+ const uint8_t *in, size_t in_len, int padding);
+
+ /* private_transform takes a big-endian integer from |in|, calculates the
+ * d'th power of it, modulo the RSA modulus and writes the result as a
+ * big-endian integer to |out|. Both |in| and |out| are |len| bytes long and
+ * |len| is always equal to |RSA_size(rsa)|. If the result of the transform
+ * can be represented in fewer than |len| bytes, then |out| must be zero
+ * padded on the left.
+ *
+ * It returns one on success and zero otherwise.
+ *
+ * RSA decrypt and sign operations will call this, thus an ENGINE might wish
+ * to override it in order to avoid having to implement the padding
+ * functionality demanded by those, higher level, operations. */
+ int (*private_transform)(RSA *rsa, uint8_t *out, const uint8_t *in,
+ size_t len);
+
+ int (*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);
+
+ int flags;
+
+ int (*keygen)(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb);
+
+ /* supports_digest returns one if |rsa| supports digests of type
+ * |md|. If null, it is assumed that all digests are supported. */
+ int (*supports_digest)(const RSA *rsa, const EVP_MD *md);
+};
+
+
+/* Private functions. */
+
+typedef struct bn_blinding_st BN_BLINDING;
+
+struct rsa_st {
+ /* version is only used during ASN.1 (de)serialisation. */
+ long version;
+ RSA_METHOD *meth;
+
+ BIGNUM *n;
+ BIGNUM *e;
+ BIGNUM *d;
+ BIGNUM *p;
+ BIGNUM *q;
+ BIGNUM *dmp1;
+ BIGNUM *dmq1;
+ BIGNUM *iqmp;
+ /* 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;
+
+ /* num_blindings contains the size of the |blindings| and |blindings_inuse|
+ * arrays. This member and the |blindings_inuse| array are protected by
+ * CRYPTO_LOCK_RSA_BLINDING. */
+ unsigned num_blindings;
+ /* blindings is an array of BN_BLINDING structures that can be reserved by a
+ * thread by locking CRYPTO_LOCK_RSA_BLINDING and changing the corresponding
+ * element in |blindings_inuse| from 0 to 1. */
+ BN_BLINDING **blindings;
+ unsigned char *blindings_inuse;
+};
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#define RSA_F_RSA_padding_check_none 100
+#define RSA_F_RSA_padding_add_none 101
+#define RSA_F_RSA_padding_check_PKCS1_OAEP_mgf1 102
+#define RSA_F_RSA_verify_PKCS1_PSS_mgf1 103
+#define RSA_F_RSA_padding_add_PKCS1_PSS_mgf1 104
+#define RSA_F_RSA_verify 105
+#define RSA_F_rsa_setup_blinding 106
+#define RSA_F_verify_raw 107
+#define RSA_F_RSA_padding_add_PKCS1_type_1 108
+#define RSA_F_keygen 109
+#define RSA_F_RSA_padding_add_PKCS1_OAEP_mgf1 110
+#define RSA_F_pkcs1_prefixed_msg 111
+#define RSA_F_BN_BLINDING_update 112
+#define RSA_F_RSA_padding_check_SSLv23 113
+#define RSA_F_RSA_padding_add_SSLv23 114
+#define RSA_F_BN_BLINDING_new 115
+#define RSA_F_RSA_padding_add_PKCS1_type_2 116
+#define RSA_F_BN_BLINDING_convert_ex 117
+#define RSA_F_BN_BLINDING_invert_ex 118
+#define RSA_F_encrypt 119
+#define RSA_F_sign_raw 120
+#define RSA_F_RSA_new_method 121
+#define RSA_F_RSA_padding_check_PKCS1_type_1 122
+#define RSA_F_RSA_sign 123
+#define RSA_F_BN_BLINDING_create_param 124
+#define RSA_F_decrypt 125
+#define RSA_F_RSA_padding_check_PKCS1_type_2 126
+#define RSA_F_RSA_recover_crt_params 127
+#define RSA_F_RSA_check_key 128
+#define RSA_F_private_transform 129
+#define RSA_R_INVALID_MESSAGE_LENGTH 100
+#define RSA_R_NO_PUBLIC_EXPONENT 102
+#define RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE 103
+#define RSA_R_BLOCK_TYPE_IS_NOT_01 104
+#define RSA_R_DATA_TOO_SMALL_FOR_KEY_SIZE 105
+#define RSA_R_UNKNOWN_PADDING_TYPE 106
+#define RSA_R_TOO_MANY_ITERATIONS 107
+#define RSA_R_SLEN_RECOVERY_FAILED 108
+#define RSA_R_WRONG_SIGNATURE_LENGTH 109
+#define RSA_R_MODULUS_TOO_LARGE 110
+#define RSA_R_NULL_BEFORE_BLOCK_MISSING 111
+#define RSA_R_DATA_TOO_LARGE 112
+#define RSA_R_OUTPUT_BUFFER_TOO_SMALL 113
+#define RSA_R_SLEN_CHECK_FAILED 114
+#define RSA_R_FIRST_OCTET_INVALID 115
+#define RSA_R_BAD_E_VALUE 116
+#define RSA_R_DATA_TOO_LARGE_FOR_MODULUS 117
+#define RSA_R_EMPTY_PUBLIC_KEY 118
+#define RSA_R_BAD_PAD_BYTE_COUNT 119
+#define RSA_R_OAEP_DECODING_ERROR 120
+#define RSA_R_TOO_LONG 121
+#define RSA_R_BAD_FIXED_HEADER_DECRYPT 122
+#define RSA_R_DATA_TOO_SMALL 123
+#define RSA_R_UNKNOWN_ALGORITHM_TYPE 124
+#define RSA_R_PADDING_CHECK_FAILED 125
+#define RSA_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD 126
+#define RSA_R_BLOCK_TYPE_IS_NOT_02 127
+#define RSA_R_LAST_OCTET_INVALID 128
+#define RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY 129
+#define RSA_R_SSLV3_ROLLBACK_ATTACK 130
+#define RSA_R_KEY_SIZE_TOO_SMALL 131
+#define RSA_R_BAD_SIGNATURE 132
+#define RSA_R_BN_NOT_INITIALIZED 133
+#define RSA_R_PKCS_DECODING_ERROR 134
+#define RSA_R_BAD_RSA_PARAMETERS 135
+#define RSA_R_INTERNAL_ERROR 136
+#define RSA_R_CRT_PARAMS_ALREADY_GIVEN 137
+#define RSA_R_D_E_NOT_CONGRUENT_TO_1 138
+#define RSA_R_VALUE_MISSING 139
+#define RSA_R_N_NOT_EQUAL_P_Q 140
+#define RSA_R_CRT_VALUES_INCORRECT 141
+#define RSA_R_INCONSISTENT_SET_OF_CRT_VALUES 142
+#define RSA_R_ONLY_ONE_OF_P_Q_GIVEN 143
+#define RSA_R_DATA_LEN_NOT_EQUAL_TO_MOD_LEN 144
+
+#endif /* OPENSSL_HEADER_RSA_H */
diff --git a/src/include/openssl/safe_stack.h b/src/include/openssl/safe_stack.h
new file mode 100644
index 0000000..6e5e433
--- /dev/null
+++ b/src/include/openssl/safe_stack.h
@@ -0,0 +1,16 @@
+/* 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. */
+
+/* This header is provided in order to make compiling against code that expects
+ OpenSSL easier. */
diff --git a/src/include/openssl/sha.h b/src/include/openssl/sha.h
new file mode 100644
index 0000000..5b363ee
--- /dev/null
+++ b/src/include/openssl/sha.h
@@ -0,0 +1,237 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 OPENSSL_HEADER_SHA_H
+#define OPENSSL_HEADER_SHA_H
+
+#include <openssl/base.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* The SHA family of hash functions (SHA-1 and SHA-2). */
+
+
+/* SHA_CBLOCK is the block size of SHA-1. */
+#define SHA_CBLOCK 64
+
+/* SHA_DIGEST_LENGTH is the length of a SHA-1 digest. */
+#define SHA_DIGEST_LENGTH 20
+
+/* TODO(fork): remove */
+#define SHA_LBLOCK 16
+#define SHA_LONG uint32_t
+
+/* SHA1_Init initialises |sha| and returns one. */
+OPENSSL_EXPORT int SHA1_Init(SHA_CTX *sha);
+
+/* SHA1_Update adds |len| bytes from |data| to |sha| and returns one. */
+OPENSSL_EXPORT int SHA1_Update(SHA_CTX *sha, const void *data, size_t len);
+
+/* SHA1_Final adds the final padding to |sha| and writes the resulting digest
+ * to |md|, which must have at least |SHA_DIGEST_LENGTH| bytes of space. It
+ * returns one. */
+OPENSSL_EXPORT int SHA1_Final(uint8_t *md, SHA_CTX *sha);
+
+/* SHA1 writes the digest of |len| bytes from |data| to |out| and returns
+ * |out|. There must be at least |SHA_DIGEST_LENGTH| bytes of space in
+ * |out|. */
+OPENSSL_EXPORT uint8_t *SHA1(const uint8_t *data, size_t len, uint8_t *out);
+
+/* SHA1_Transform is a low-level function that performs a single, SHA-1 block
+ * transformation using the state from |sha| and 64 bytes from |block|. */
+OPENSSL_EXPORT void SHA1_Transform(SHA_CTX *sha, const uint8_t *block);
+
+struct sha_state_st {
+ uint32_t h0, h1, h2, h3, h4;
+ uint32_t Nl, Nh;
+ uint32_t data[16];
+ unsigned int num;
+};
+
+
+/* SHA-224. */
+
+/* SHA224_CBLOCK is the block size of SHA-224. */
+#define SHA224_CBLOCK 64
+
+/* SHA224_DIGEST_LENGTH is the length of a SHA-224 digest. */
+#define SHA224_DIGEST_LENGTH 28
+
+/* SHA224_Init initialises |sha| and returns 1. */
+OPENSSL_EXPORT int SHA224_Init(SHA256_CTX *sha);
+
+/* SHA224_Update adds |len| bytes from |data| to |sha| and returns 1. */
+OPENSSL_EXPORT int SHA224_Update(SHA256_CTX *sha, const void *data, size_t len);
+
+/* SHA224_Final adds the final padding to |sha| and writes the resulting digest
+ * to |md|, which must have at least |SHA224_DIGEST_LENGTH| bytes of space. */
+OPENSSL_EXPORT int SHA224_Final(uint8_t *md, SHA256_CTX *sha);
+
+/* SHA224 writes the digest of |len| bytes from |data| to |out| and returns
+ * |out|. There must be at least |SHA224_DIGEST_LENGTH| bytes of space in
+ * |out|. */
+OPENSSL_EXPORT uint8_t *SHA224(const uint8_t *data, size_t len, uint8_t *out);
+
+
+/* SHA-256. */
+
+/* SHA256_CBLOCK is the block size of SHA-256. */
+#define SHA256_CBLOCK 64
+
+/* SHA256_DIGEST_LENGTH is the length of a SHA-256 digest. */
+#define SHA256_DIGEST_LENGTH 32
+
+/* SHA256_Init initialises |sha| and returns 1. */
+OPENSSL_EXPORT int SHA256_Init(SHA256_CTX *sha);
+
+/* SHA256_Update adds |len| bytes from |data| to |sha| and returns 1. */
+OPENSSL_EXPORT int SHA256_Update(SHA256_CTX *sha, const void *data, size_t len);
+
+/* SHA256_Final adds the final padding to |sha| and writes the resulting digest
+ * to |md|, which must have at least |SHA256_DIGEST_LENGTH| bytes of space. */
+OPENSSL_EXPORT int SHA256_Final(uint8_t *md, SHA256_CTX *sha);
+
+/* SHA256 writes the digest of |len| bytes from |data| to |out| and returns
+ * |out|. There must be at least |SHA256_DIGEST_LENGTH| bytes of space in
+ * |out|. */
+OPENSSL_EXPORT uint8_t *SHA256(const uint8_t *data, size_t len, uint8_t *out);
+
+/* SHA256_Transform is a low-level function that performs a single, SHA-1 block
+ * transformation using the state from |sha| and 64 bytes from |block|. */
+OPENSSL_EXPORT void SHA256_Transform(SHA256_CTX *sha, const uint8_t *data);
+
+struct sha256_state_st {
+ uint32_t h[8];
+ uint32_t Nl, Nh;
+ uint32_t data[16];
+ unsigned int num, md_len;
+};
+
+
+/* SHA-384. */
+
+/* SHA384_CBLOCK is the block size of SHA-384. */
+#define SHA384_CBLOCK 128
+
+/* SHA384_DIGEST_LENGTH is the length of a SHA-384 digest. */
+#define SHA384_DIGEST_LENGTH 48
+
+/* SHA384_Init initialises |sha| and returns 1. */
+OPENSSL_EXPORT int SHA384_Init(SHA512_CTX *sha);
+
+/* SHA384_Update adds |len| bytes from |data| to |sha| and returns 1. */
+OPENSSL_EXPORT int SHA384_Update(SHA512_CTX *sha, const void *data, size_t len);
+
+/* SHA384_Final adds the final padding to |sha| and writes the resulting digest
+ * to |md|, which must have at least |SHA384_DIGEST_LENGTH| bytes of space. */
+OPENSSL_EXPORT int SHA384_Final(uint8_t *md, SHA512_CTX *sha);
+
+/* SHA384 writes the digest of |len| bytes from |data| to |out| and returns
+ * |out|. There must be at least |SHA384_DIGEST_LENGTH| bytes of space in
+ * |out|. */
+OPENSSL_EXPORT uint8_t *SHA384(const uint8_t *data, size_t len, uint8_t *out);
+
+/* SHA384_Transform is a low-level function that performs a single, SHA-1 block
+ * transformation using the state from |sha| and 64 bytes from |block|. */
+OPENSSL_EXPORT void SHA384_Transform(SHA512_CTX *sha, const uint8_t *data);
+
+
+/* SHA-512. */
+
+/* SHA512_CBLOCK is the block size of SHA-512. */
+#define SHA512_CBLOCK 128
+
+/* SHA512_DIGEST_LENGTH is the length of a SHA-512 digest. */
+#define SHA512_DIGEST_LENGTH 64
+
+/* SHA512_Init initialises |sha| and returns 1. */
+OPENSSL_EXPORT int SHA512_Init(SHA512_CTX *sha);
+
+/* SHA512_Update adds |len| bytes from |data| to |sha| and returns 1. */
+OPENSSL_EXPORT int SHA512_Update(SHA512_CTX *sha, const void *data, size_t len);
+
+/* SHA512_Final adds the final padding to |sha| and writes the resulting digest
+ * to |md|, which must have at least |SHA512_DIGEST_LENGTH| bytes of space. */
+OPENSSL_EXPORT int SHA512_Final(uint8_t *md, SHA512_CTX *sha);
+
+/* SHA512 writes the digest of |len| bytes from |data| to |out| and returns
+ * |out|. There must be at least |SHA512_DIGEST_LENGTH| bytes of space in
+ * |out|. */
+OPENSSL_EXPORT uint8_t *SHA512(const uint8_t *data, size_t len, uint8_t *out);
+
+/* SHA512_Transform is a low-level function that performs a single, SHA-1 block
+ * transformation using the state from |sha| and 64 bytes from |block|. */
+OPENSSL_EXPORT void SHA512_Transform(SHA512_CTX *sha, const uint8_t *data);
+
+struct sha512_state_st {
+ uint64_t h[8];
+ uint64_t Nl, Nh;
+ union {
+ uint64_t d[16];
+ uint8_t p[64];
+ } u;
+ unsigned int num, md_len;
+};
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_SHA_H */
diff --git a/src/include/openssl/srtp.h b/src/include/openssl/srtp.h
new file mode 100644
index 0000000..3f5a53e
--- /dev/null
+++ b/src/include/openssl/srtp.h
@@ -0,0 +1,178 @@
+/* ssl/tls1.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <ekr@rtfm.com>
+
+ Copyright (C) 2006, Network Resonance, Inc.
+ Copyright (C) 2011, RTFM, Inc.
+*/
+
+#ifndef OPENSSL_HEADER_SRTP_H
+#define OPENSSL_HEADER_SRTP_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Constants for SRTP profiles */
+#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
+
+/* SSL_CTX_set_srtp_profiles enables SRTP for all SSL objects created from
+ * |ctx|. |profile| contains a colon-separated list of profile names. It returns
+ * one on success and zero on failure. */
+OPENSSL_EXPORT int SSL_CTX_set_srtp_profiles(SSL_CTX *ctx,
+ const char *profiles);
+
+/* SSL_set_srtp_profiles enables SRTP for |ssl|. |profile| contains a
+ * colon-separated list of profile names. It returns one on success and zero on
+ * failure. */
+OPENSSL_EXPORT int SSL_set_srtp_profiles(SSL *ctx, const char *profiles);
+
+/* SSL_get_srtp_profiles returns the SRTP profiles supported by |ssl|. */
+OPENSSL_EXPORT STACK_OF(SRTP_PROTECTION_PROFILE) *SSL_get_srtp_profiles(
+ SSL *ssl);
+
+/* SSL_get_selected_srtp_profile returns the selected SRTP profile, or NULL if
+ * SRTP was not negotiated. */
+OPENSSL_EXPORT const SRTP_PROTECTION_PROFILE *SSL_get_selected_srtp_profile(
+ SSL *s);
+
+
+/* Deprecated functions */
+
+/* SSL_CTX_set_tlsext_use_srtp calls SSL_CTX_set_srtp_profiles. It returns zero
+ * on success and one on failure.
+ *
+ * WARNING: this function is dangerous because it breaks the usual return value
+ * convention. Use SSL_CTX_set_srtp_profiles instead. */
+OPENSSL_EXPORT int SSL_CTX_set_tlsext_use_srtp(SSL_CTX *ctx,
+ const char *profiles);
+
+/* SSL_set_tlsext_use_srtp calls SSL_set_srtp_profiles. It returns zero on
+ * success and one on failure.
+ *
+ * WARNING: this function is dangerous because it breaks the usual return value
+ * convention. Use SSL_set_srtp_profiles instead. */
+OPENSSL_EXPORT int SSL_set_tlsext_use_srtp(SSL *ctx, const char *profiles);
+
+
+#ifdef __cplusplus
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_SRTP_H */
+
diff --git a/src/include/openssl/ssl.h b/src/include/openssl/ssl.h
new file mode 100644
index 0000000..649e38f
--- /dev/null
+++ b/src/include/openssl/ssl.h
@@ -0,0 +1,2751 @@
+/* ssl/ssl.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/base.h>
+
+#include <openssl/bio.h>
+#include <openssl/buf.h>
+#include <openssl/hmac.h>
+#include <openssl/lhash.h>
+#include <openssl/pem.h>
+#include <openssl/x509.h>
+
+/* Some code expected to get the threading functions by including ssl.h. */
+#include <openssl/thread.h>
+
+#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
+
+#define SSL_MAX_SSL_SESSION_ID_LENGTH 32
+#define SSL_MAX_SID_CTX_LENGTH 32
+#define SSL_MAX_MASTER_KEY_LENGTH 48
+
+/* These are used to specify which ciphers to use and not to use */
+
+#define SSL_TXT_MEDIUM "MEDIUM"
+#define SSL_TXT_HIGH "HIGH"
+#define SSL_TXT_FIPS "FIPS"
+
+#define SSL_TXT_aNULL "aNULL"
+
+#define SSL_TXT_kRSA "kRSA"
+#define SSL_TXT_kEDH "kEDH"
+#define SSL_TXT_kEECDH "kEECDH"
+#define SSL_TXT_kPSK "kPSK"
+
+#define SSL_TXT_aRSA "aRSA"
+#define SSL_TXT_aECDSA "aECDSA"
+#define SSL_TXT_aPSK "aPSK"
+
+#define SSL_TXT_DH "DH"
+#define SSL_TXT_EDH "EDH" /* same as "kEDH:-ADH" */
+#define SSL_TXT_ADH "ADH"
+#define SSL_TXT_RSA "RSA"
+#define SSL_TXT_ECDH "ECDH"
+#define SSL_TXT_EECDH "EECDH" /* same as "kEECDH:-AECDH" */
+#define SSL_TXT_AECDH "AECDH"
+#define SSL_TXT_ECDSA "ECDSA"
+#define SSL_TXT_PSK "PSK"
+
+#define SSL_TXT_3DES "3DES"
+#define SSL_TXT_RC4 "RC4"
+#define SSL_TXT_AES128 "AES128"
+#define SSL_TXT_AES256 "AES256"
+#define SSL_TXT_AES "AES"
+#define SSL_TXT_AES_GCM "AESGCM"
+#define SSL_TXT_CHACHA20 "CHACHA20"
+
+#define SSL_TXT_MD5 "MD5"
+#define SSL_TXT_SHA1 "SHA1"
+#define SSL_TXT_SHA "SHA" /* same as "SHA1" */
+#define SSL_TXT_SHA256 "SHA256"
+#define SSL_TXT_SHA384 "SHA384"
+
+#define SSL_TXT_SSLV3 "SSLv3"
+#define SSL_TXT_TLSV1 "TLSv1"
+#define SSL_TXT_TLSV1_1 "TLSv1.1"
+#define SSL_TXT_TLSV1_2 "TLSv1.2"
+
+#define SSL_TXT_ALL "ALL"
+
+/* COMPLEMENTOF* definitions. These identifiers are used to (de-select) ciphers
+ * normally not being used.
+ *
+ * Example: "RC4" will activate all ciphers using RC4 including ciphers without
+ * authentication, which would normally disabled by DEFAULT (due the "!ADH"
+ * being part of default). Therefore "RC4:!COMPLEMENTOFDEFAULT" will make sure
+ * that it is also disabled in the specific selection. COMPLEMENTOF*
+ * identifiers are portable between version, as adjustments to the default
+ * cipher setup will also be included here.
+ *
+ * COMPLEMENTOFDEFAULT does not experience the same special treatment that
+ * DEFAULT gets, as only selection is being done and no sorting as needed for
+ * DEFAULT. */
+#define SSL_TXT_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
+
+typedef struct ssl_method_st SSL_METHOD;
+typedef struct ssl_protocol_method_st SSL_PROTOCOL_METHOD;
+typedef struct ssl_cipher_st SSL_CIPHER;
+typedef struct ssl_session_st SSL_SESSION;
+typedef struct tls_sigalgs_st TLS_SIGALGS;
+typedef struct ssl_conf_ctx_st SSL_CONF_CTX;
+typedef struct ssl3_enc_method SSL3_ENC_METHOD;
+
+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)
+
+/* used to hold info on the particular ciphers used */
+struct ssl_cipher_st {
+ int valid;
+ const char *name; /* text name */
+ unsigned long id; /* id, 4 bytes, first is version */
+
+ /* changed in 0.9.9: these four used to be portions of a single value
+ * 'algorithms' */
+ 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. See SSL2_CF_* in ssl2.h
+ and algorithm2 section in
+ ssl_locl.h */
+ int strength_bits; /* Number of bits really used */
+ int alg_bits; /* Number of bits for algorithm */
+};
+
+/* An SSL_SESSION represents an SSL session that may be resumed in an
+ * abbreviated handshake. */
+struct ssl_session_st {
+ int ssl_version; /* what ssl version session info is being kept in here? */
+
+ int master_key_length;
+ uint8_t master_key[SSL_MAX_MASTER_KEY_LENGTH];
+ /* session_id - valid? */
+ unsigned int session_id_length;
+ uint8_t 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 */
+ unsigned int sid_ctx_length;
+ uint8_t sid_ctx[SSL_MAX_SID_CTX_LENGTH];
+
+ char *psk_identity;
+ /* 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;
+
+ /* The cert is the certificate used to establish this connection */
+ struct sess_cert_st /* SESS_CERT */ *sess_cert;
+
+ /* This is the cert for the other end. On clients, it will be the same as
+ * sess_cert->peer_key->x509 (the latter is not enough as sess_cert is not
+ * retained in the external representation of sessions, see ssl_asn1.c). */
+ X509 *peer;
+ /* 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 */
+
+ int references;
+ long timeout;
+ long time;
+
+ const SSL_CIPHER *cipher;
+
+ 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;
+ char *tlsext_hostname;
+ /* RFC4507 info */
+ uint8_t *tlsext_tick; /* Session ticket */
+ size_t tlsext_ticklen; /* Session ticket length */
+ uint32_t tlsext_tick_lifetime_hint; /* Session lifetime hint in seconds */
+
+ size_t tlsext_signed_cert_timestamp_list_length;
+ uint8_t *tlsext_signed_cert_timestamp_list; /* Server's list. */
+
+ /* The OCSP response that came with the session. */
+ size_t ocsp_response_length;
+ uint8_t *ocsp_response;
+
+ char peer_sha256_valid; /* Non-zero if peer_sha256 is valid */
+ uint8_t
+ peer_sha256[SHA256_DIGEST_LENGTH]; /* SHA256 of peer certificate */
+
+ /* original_handshake_hash contains the handshake hash (either SHA-1+MD5 or
+ * SHA-2, depending on TLS version) for the original, full handshake that
+ * created a session. This is used by Channel IDs during resumption. */
+ uint8_t original_handshake_hash[EVP_MAX_MD_SIZE];
+ unsigned int original_handshake_hash_len;
+
+ /* extended_master_secret is true if the master secret in this session was
+ * generated using EMS and thus isn't vulnerable to the Triple Handshake
+ * attack. */
+ char extended_master_secret;
+};
+
+/* SSL_OP_LEGACY_SERVER_CONNECT allows initial connection to servers that don't
+ * support RI */
+#define SSL_OP_LEGACY_SERVER_CONNECT 0x00000004L
+
+/* SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER allows for record sizes SSL3_RT_MAX_EXTRA
+ * bytes above the maximum record size. */
+#define SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER 0x00000020L
+
+/* SSL_OP_TLS_D5_BUG accepts an RSAClientKeyExchange in TLS encoded as SSL3,
+ * without a length prefix. */
+#define SSL_OP_TLS_D5_BUG 0x00000100L
+
+/* SSL_OP_ALL enables the above bug workarounds that should be rather harmless.
+ * */
+#define SSL_OP_ALL 0x00000BFFL
+
+/* 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
+/* Don't use compression even if supported */
+#define SSL_OP_NO_COMPRESSION 0x00020000L
+/* Permit unsafe legacy renegotiation */
+#define SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION 0x00040000L
+/* If set, always create a new key when using tmp_ecdh parameters */
+#define SSL_OP_SINGLE_ECDH_USE 0x00080000L
+/* 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
+/* SSL_OP_TLS_ROLLBACK_BUG does nothing. */
+#define SSL_OP_TLS_ROLLBACK_BUG 0x00800000L
+
+/* Deprecated: Use SSL_CTX_set_min_version and SSL_CTX_set_max_version
+ * instead. */
+#define SSL_OP_NO_SSLv2 0x01000000L
+#define SSL_OP_NO_SSLv3 0x02000000L
+#define SSL_OP_NO_TLSv1 0x04000000L
+#define SSL_OP_NO_TLSv1_2 0x08000000L
+#define SSL_OP_NO_TLSv1_1 0x10000000L
+
+#define SSL_OP_NO_DTLSv1 SSL_OP_NO_TLSv1
+#define SSL_OP_NO_DTLSv1_2 SSL_OP_NO_TLSv1_2
+
+#define SSL_OP_NO_SSL_MASK \
+ (SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | \
+ SSL_OP_NO_TLSv1_2)
+
+/* The following flags do nothing and are included only to make it easier to
+ * compile code with BoringSSL. */
+#define SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS 0
+#define SSL_OP_MICROSOFT_SESS_ID_BUG 0
+#define SSL_OP_NETSCAPE_CHALLENGE_BUG 0
+#define SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG 0
+#define SSL_OP_TLS_BLOCK_PADDING_BUG 0
+
+/* 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
+/* 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
+
+/* The following flags do nothing and are included only to make it easier to
+ * compile code with BoringSSL. */
+#define SSL_MODE_AUTO_RETRY 0
+
+/* Send the current time in the Random fields of the ClientHello and
+ * ServerHello records for compatibility with hypothetical implementations that
+ * require it. */
+#define SSL_MODE_SEND_CLIENTHELLO_TIME 0x00000020L
+#define SSL_MODE_SEND_SERVERHELLO_TIME 0x00000040L
+
+/* Cert related flags */
+/* Many implementations ignore some aspects of the TLS standards such as
+ * enforcing certifcate chain algorithms. When this is set we enforce them. */
+#define SSL_CERT_FLAG_TLS_STRICT 0x00000001L
+
+/* Flags for building certificate chains */
+/* Treat any existing certificates as untrusted CAs */
+#define SSL_BUILD_CHAIN_FLAG_UNTRUSTED 0x1
+/* Don't include root CA in chain */
+#define SSL_BUILD_CHAIN_FLAG_NO_ROOT 0x2
+/* Just check certificates already there */
+#define SSL_BUILD_CHAIN_FLAG_CHECK 0x4
+/* Ignore verification errors */
+#define SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR 0x8
+/* Clear verification errors from queue */
+#define SSL_BUILD_CHAIN_FLAG_CLEAR_ERROR 0x10
+
+/* When set, clients may send application data before receipt of CCS and
+ * Finished. This mode enables full-handshakes to 'complete' in one RTT. */
+#define SSL_MODE_HANDSHAKE_CUTTHROUGH 0x00000080L
+
+/* When set, TLS 1.0 and SSLv3, multi-byte, CBC records will be split in two:
+ * the first record will contain a single byte and the second will contain the
+ * rest of the bytes. This effectively randomises the IV and prevents BEAST
+ * attacks. */
+#define SSL_MODE_CBC_RECORD_SPLITTING 0x00000100L
+
+/* SSL_MODE_NO_SESSION_CREATION will cause any attempts to create a session to
+ * fail with SSL_R_SESSION_MAY_NOT_BE_CREATED. This can be used to enforce that
+ * session resumption is used for a given SSL*. */
+#define SSL_MODE_NO_SESSION_CREATION 0x00000200L
+
+/* 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), SSL_CTRL_GET_RI_SUPPORT, 0, NULL)
+
+#define SSL_CTX_set_cert_flags(ctx, op) \
+ SSL_CTX_ctrl((ctx), SSL_CTRL_CERT_FLAGS, (op), NULL)
+#define SSL_set_cert_flags(s, op) SSL_ctrl((s), SSL_CTRL_CERT_FLAGS, (op), NULL)
+#define SSL_CTX_clear_cert_flags(ctx, op) \
+ SSL_CTX_ctrl((ctx), SSL_CTRL_CLEAR_CERT_FLAGS, (op), NULL)
+#define SSL_clear_cert_flags(s, op) \
+ SSL_ctrl((s), SSL_CTRL_CLEAR_CERT_FLAGS, (op), NULL)
+
+/* SSL_CTX_set_min_version sets the minimum protocol version for |ctx| to
+ * |version|. */
+OPENSSL_EXPORT void SSL_CTX_set_min_version(SSL_CTX *ctx, uint16_t version);
+
+/* SSL_CTX_set_max_version sets the maximum protocol version for |ctx| to
+ * |version|. */
+OPENSSL_EXPORT void SSL_CTX_set_max_version(SSL_CTX *ctx, uint16_t version);
+
+/* SSL_set_min_version sets the minimum protocol version for |ssl| to
+ * |version|. */
+OPENSSL_EXPORT void SSL_set_min_version(SSL *ssl, uint16_t version);
+
+/* SSL_set_max_version sets the maximum protocol version for |ssl| to
+ * |version|. */
+OPENSSL_EXPORT void SSL_set_max_version(SSL *ssl, uint16_t version);
+
+OPENSSL_EXPORT 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));
+OPENSSL_EXPORT 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))
+
+/* SSL_CTX_set_keylog_bio sets configures all SSL objects attached to |ctx| to
+ * log session material to |keylog_bio|. This is intended for debugging use
+ * with tools like Wireshark. |ctx| takes ownership of |keylog_bio|.
+ *
+ * The format is described in
+ * https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format. */
+OPENSSL_EXPORT void SSL_CTX_set_keylog_bio(SSL_CTX *ctx, BIO *keylog_bio);
+
+
+struct ssl_aead_ctx_st;
+typedef struct ssl_aead_ctx_st SSL_AEAD_CTX;
+
+#define SSL_MAX_CERT_LIST_DEFAULT 1024 * 100 /* 100k max cert list */
+
+#define SSL_SESSION_CACHE_MAX_SIZE_DEFAULT (1024 * 20)
+
+#define SSL_DEFAULT_SESSION_TIMEOUT (2 * 60 * 60)
+
+/* 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, uint8_t *id,
+ unsigned int *id_len);
+
+/* ssl_early_callback_ctx is passed to certain callbacks that are called very
+ * early on during the server handshake. At this point, much of the SSL* hasn't
+ * been filled out and only the ClientHello can be depended on. */
+struct ssl_early_callback_ctx {
+ SSL *ssl;
+ const uint8_t *client_hello;
+ size_t client_hello_len;
+ const uint8_t *session_id;
+ size_t session_id_len;
+ const uint8_t *cipher_suites;
+ size_t cipher_suites_len;
+ const uint8_t *compression_methods;
+ size_t compression_methods_len;
+ const uint8_t *extensions;
+ size_t extensions_len;
+};
+
+/* SSL_early_callback_ctx_extension_get searches the extensions in |ctx| for an
+ * extension of the given type. If not found, it returns zero. Otherwise it
+ * sets |out_data| to point to the extension contents (not including the type
+ * and length bytes), sets |out_len| to the length of the extension contents
+ * and returns one. */
+OPENSSL_EXPORT char SSL_early_callback_ctx_extension_get(
+ const struct ssl_early_callback_ctx *ctx, uint16_t extension_type,
+ const uint8_t **out_data, size_t *out_len);
+
+typedef struct ssl_comp_st SSL_COMP;
+
+struct ssl_comp_st {
+ int id;
+ const char *name;
+ char *method;
+};
+
+DECLARE_STACK_OF(SSL_COMP)
+DECLARE_LHASH_OF(SSL_SESSION);
+
+/* ssl_cipher_preference_list_st contains a list of SSL_CIPHERs with
+ * equal-preference groups. For TLS clients, the groups are moot because the
+ * server picks the cipher and groups cannot be expressed on the wire. However,
+ * for servers, the equal-preference groups allow the client's preferences to
+ * be partially respected. (This only has an effect with
+ * SSL_OP_CIPHER_SERVER_PREFERENCE).
+ *
+ * The equal-preference groups are expressed by grouping SSL_CIPHERs together.
+ * All elements of a group have the same priority: no ordering is expressed
+ * within a group.
+ *
+ * The values in |ciphers| are in one-to-one correspondence with
+ * |in_group_flags|. (That is, sk_SSL_CIPHER_num(ciphers) is the number of
+ * bytes in |in_group_flags|.) The bytes in |in_group_flags| are either 1, to
+ * indicate that the corresponding SSL_CIPHER is not the last element of a
+ * group, or 0 to indicate that it is.
+ *
+ * For example, if |in_group_flags| contains all zeros then that indicates a
+ * traditional, fully-ordered preference. Every SSL_CIPHER is the last element
+ * of the group (i.e. they are all in a one-element group).
+ *
+ * For a more complex example, consider:
+ * ciphers: A B C D E F
+ * in_group_flags: 1 1 0 0 1 0
+ *
+ * That would express the following, order:
+ *
+ * A E
+ * B -> D -> F
+ * C
+ */
+struct ssl_cipher_preference_list_st {
+ STACK_OF(SSL_CIPHER) *ciphers;
+ uint8_t *in_group_flags;
+};
+
+struct ssl_ctx_st {
+ const SSL_PROTOCOL_METHOD *method;
+
+ /* max_version is the maximum acceptable protocol version. If zero, the
+ * maximum supported version, currently (D)TLS 1.2, is used. */
+ uint16_t max_version;
+
+ /* min_version is the minimum acceptable protocl version. If zero, the
+ * minimum supported version, currently SSL 3.0 and DTLS 1.0, is used */
+ uint16_t min_version;
+
+ struct ssl_cipher_preference_list_st *cipher_list;
+ /* same as above but sorted for lookup */
+ STACK_OF(SSL_CIPHER) *cipher_list_by_id;
+ /* cipher_list_tls11 is the list of ciphers when TLS 1.1 or greater is in
+ * use. This only applies to server connections as, for clients, the version
+ * number is known at connect time and so the cipher list can be set then. */
+ struct ssl_cipher_preference_list_st *cipher_list_tls11;
+
+ struct x509_store_st /* X509_STORE */ *cert_store;
+ LHASH_OF(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;
+
+ /* 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;
+
+ /* 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, uint8_t *data, int len,
+ int *copy);
+
+ /* TODO(agl): remove the stats stuff. */
+ 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;
+
+ int references;
+
+ /* if defined, these override the X509_verify_cert() calls */
+ int (*app_verify_callback)(X509_STORE_CTX *, void *);
+ void *app_verify_arg;
+ /* before OpenSSL 0.9.7, 'app_verify_arg' was ignored ('app_verify_callback'
+ * was called with just one argument) */
+
+ /* Default password callback. */
+ pem_password_cb *default_passwd_callback;
+
+ /* Default password callback user data. */
+ void *default_passwd_callback_userdata;
+
+ /* get client cert callback */
+ int (*client_cert_cb)(SSL *ssl, X509 **x509, EVP_PKEY **pkey);
+
+ /* get channel id callback */
+ void (*channel_id_cb)(SSL *ssl, EVP_PKEY **pkey);
+
+ /* cookie generate callback */
+ int (*app_gen_cookie_cb)(SSL *ssl, uint8_t *cookie, size_t *cookie_len);
+
+ /* verify cookie callback */
+ int (*app_verify_cookie_cb)(SSL *ssl, const uint8_t *cookie,
+ size_t cookie_len);
+
+ CRYPTO_EX_DATA ex_data;
+
+ STACK_OF(X509) *extra_certs;
+
+
+ /* Default values used when no per-SSL value is defined follow */
+
+ void (*info_callback)(const SSL *ssl, int type,
+ int val); /* used if SSL's info_callback is NULL */
+
+ /* what we put in client cert requests */
+ STACK_OF(X509_NAME) *client_CA;
+
+
+ /* Default values to use in SSL structures follow (these are copied by
+ * SSL_new) */
+
+ unsigned long options;
+ unsigned long mode;
+ long max_cert_list;
+
+ struct cert_st /* CERT */ *cert;
+ int read_ahead;
+
+ /* callback that allows applications to peek at protocol messages */
+ void (*msg_callback)(int write_p, int version, int content_type,
+ const void *buf, size_t len, SSL *ssl, void *arg);
+ void *msg_callback_arg;
+
+ int verify_mode;
+ unsigned int sid_ctx_length;
+ uint8_t sid_ctx[SSL_MAX_SID_CTX_LENGTH];
+ 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;
+
+ X509_VERIFY_PARAM *param;
+
+ /* select_certificate_cb is called before most ClientHello processing and
+ * before the decision whether to resume a session is made. It may return one
+ * to continue the handshake or zero to cause the handshake loop to return
+ * with an error and cause SSL_get_error to return
+ * SSL_ERROR_PENDING_CERTIFICATE. */
+ int (*select_certificate_cb)(const struct ssl_early_callback_ctx *);
+
+ /* quiet_shutdown is true if the connection should not send a close_notify on
+ * shutdown. */
+ 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;
+
+ /* TLS extensions servername callback */
+ int (*tlsext_servername_callback)(SSL *, int *, void *);
+ void *tlsext_servername_arg;
+ /* RFC 4507 session ticket keys */
+ uint8_t tlsext_tick_key_name[16];
+ uint8_t tlsext_tick_hmac_key[16];
+ uint8_t tlsext_tick_aes_key[16];
+ /* Callback to support customisation of ticket key setting */
+ int (*tlsext_ticket_key_cb)(SSL *ssl, uint8_t *name, uint8_t *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;
+
+ /* Server-only: psk_identity_hint is the default identity hint to send in
+ * PSK-based key exchanges. */
+ char *psk_identity_hint;
+
+ unsigned int (*psk_client_callback)(SSL *ssl, const char *hint,
+ char *identity,
+ unsigned int max_identity_len,
+ uint8_t *psk, unsigned int max_psk_len);
+ unsigned int (*psk_server_callback)(SSL *ssl, const char *identity,
+ uint8_t *psk, unsigned int max_psk_len);
+
+
+ /* retain_only_sha256_of_client_certs is true if we should compute the SHA256
+ * hash of the peer's certifiate and then discard it to save memory and
+ * session space. Only effective on the server side. */
+ char retain_only_sha256_of_client_certs;
+
+ /* Next protocol negotiation information */
+ /* (for experimental NPN extension). */
+
+ /* For a server, this contains a callback function by which the set of
+ * advertised protocols can be provided. */
+ int (*next_protos_advertised_cb)(SSL *s, const uint8_t **buf,
+ unsigned int *len, void *arg);
+ void *next_protos_advertised_cb_arg;
+ /* For a client, this contains a callback function that selects the
+ * next protocol from the list provided by the server. */
+ int (*next_proto_select_cb)(SSL *s, uint8_t **out, uint8_t *outlen,
+ const uint8_t *in, unsigned int inlen, void *arg);
+ void *next_proto_select_cb_arg;
+
+ /* ALPN information
+ * (we are in the process of transitioning from NPN to ALPN.) */
+
+ /* For a server, this contains a 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 uint8_t **out, uint8_t *outlen,
+ const uint8_t *in, unsigned int inlen, void *arg);
+ void *alpn_select_cb_arg;
+
+ /* For a client, this contains the list of supported protocols in wire
+ * format. */
+ uint8_t *alpn_client_proto_list;
+ unsigned alpn_client_proto_list_len;
+
+ /* SRTP profiles we are willing to do from RFC 5764 */
+ STACK_OF(SRTP_PROTECTION_PROFILE) *srtp_profiles;
+
+ /* EC extension values inherited by SSL structure */
+ size_t tlsext_ecpointformatlist_length;
+ uint8_t *tlsext_ecpointformatlist;
+ size_t tlsext_ellipticcurvelist_length;
+ uint16_t *tlsext_ellipticcurvelist;
+
+ /* If true, a client will advertise the Channel ID extension and a server
+ * will echo it. */
+ char tlsext_channel_id_enabled;
+ /* tlsext_channel_id_enabled_new is a hack to support both old and new
+ * ChannelID signatures. It indicates that a client should advertise the new
+ * ChannelID extension number. */
+ char tlsext_channel_id_enabled_new;
+ /* The client's Channel ID private key. */
+ EVP_PKEY *tlsext_channel_id_private;
+
+ /* If true, a client will request certificate timestamps. */
+ char signed_cert_timestamps_enabled;
+
+ /* If true, a client will request a stapled OCSP response. */
+ char ocsp_stapling_enabled;
+
+ /* If not NULL, session key material will be logged to this BIO for debugging
+ * purposes. The format matches NSS's and is readable by Wireshark. */
+ BIO *keylog_bio;
+};
+
+#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
+/* 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)
+
+OPENSSL_EXPORT LHASH_OF(SSL_SESSION) *SSL_CTX_sessions(SSL_CTX *ctx);
+#define SSL_CTX_sess_number(ctx) \
+ SSL_CTX_ctrl(ctx, SSL_CTRL_SESS_NUMBER, 0, NULL)
+#define SSL_CTX_sess_connect(ctx) \
+ SSL_CTX_ctrl(ctx, SSL_CTRL_SESS_CONNECT, 0, NULL)
+#define SSL_CTX_sess_connect_good(ctx) \
+ SSL_CTX_ctrl(ctx, SSL_CTRL_SESS_CONNECT_GOOD, 0, NULL)
+#define SSL_CTX_sess_connect_renegotiate(ctx) \
+ SSL_CTX_ctrl(ctx, SSL_CTRL_SESS_CONNECT_RENEGOTIATE, 0, NULL)
+#define SSL_CTX_sess_accept(ctx) \
+ SSL_CTX_ctrl(ctx, SSL_CTRL_SESS_ACCEPT, 0, NULL)
+#define SSL_CTX_sess_accept_renegotiate(ctx) \
+ SSL_CTX_ctrl(ctx, SSL_CTRL_SESS_ACCEPT_RENEGOTIATE, 0, NULL)
+#define SSL_CTX_sess_accept_good(ctx) \
+ SSL_CTX_ctrl(ctx, SSL_CTRL_SESS_ACCEPT_GOOD, 0, NULL)
+#define SSL_CTX_sess_hits(ctx) SSL_CTX_ctrl(ctx, SSL_CTRL_SESS_HIT, 0, NULL)
+#define SSL_CTX_sess_cb_hits(ctx) \
+ SSL_CTX_ctrl(ctx, SSL_CTRL_SESS_CB_HIT, 0, NULL)
+#define SSL_CTX_sess_misses(ctx) \
+ SSL_CTX_ctrl(ctx, SSL_CTRL_SESS_MISSES, 0, NULL)
+#define SSL_CTX_sess_timeouts(ctx) \
+ SSL_CTX_ctrl(ctx, SSL_CTRL_SESS_TIMEOUTS, 0, NULL)
+#define SSL_CTX_sess_cache_full(ctx) \
+ SSL_CTX_ctrl(ctx, SSL_CTRL_SESS_CACHE_FULL, 0, NULL)
+/* SSL_CTX_enable_tls_channel_id configures a TLS server to accept TLS client
+ * IDs from clients. Returns 1 on success. */
+#define SSL_CTX_enable_tls_channel_id(ctx) \
+ SSL_CTX_ctrl(ctx, SSL_CTRL_CHANNEL_ID, 0, NULL)
+
+OPENSSL_EXPORT void SSL_CTX_sess_set_new_cb(
+ SSL_CTX *ctx, int (*new_session_cb)(struct ssl_st *ssl, SSL_SESSION *sess));
+OPENSSL_EXPORT int (*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx))(struct ssl_st *ssl,
+ SSL_SESSION *sess);
+OPENSSL_EXPORT void SSL_CTX_sess_set_remove_cb(
+ SSL_CTX *ctx,
+ void (*remove_session_cb)(struct ssl_ctx_st *ctx, SSL_SESSION *sess));
+OPENSSL_EXPORT void (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx))(
+ struct ssl_ctx_st *ctx, SSL_SESSION *sess);
+OPENSSL_EXPORT void SSL_CTX_sess_set_get_cb(
+ SSL_CTX *ctx,
+ SSL_SESSION *(*get_session_cb)(struct ssl_st *ssl, uint8_t *data, int len,
+ int *copy));
+OPENSSL_EXPORT SSL_SESSION *(*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx))(
+ struct ssl_st *ssl, uint8_t *Data, int len, int *copy);
+/* SSL_magic_pending_session_ptr returns a magic SSL_SESSION* which indicates
+ * that the session isn't currently unavailable. SSL_get_error will then return
+ * SSL_ERROR_PENDING_SESSION and the handshake can be retried later when the
+ * lookup has completed. */
+OPENSSL_EXPORT SSL_SESSION *SSL_magic_pending_session_ptr(void);
+OPENSSL_EXPORT void SSL_CTX_set_info_callback(SSL_CTX *ctx,
+ void (*cb)(const SSL *ssl,
+ int type, int val));
+OPENSSL_EXPORT void (*SSL_CTX_get_info_callback(SSL_CTX *ctx))(const SSL *ssl,
+ int type,
+ int val);
+OPENSSL_EXPORT void SSL_CTX_set_client_cert_cb(
+ SSL_CTX *ctx,
+ int (*client_cert_cb)(SSL *ssl, X509 **x509, EVP_PKEY **pkey));
+OPENSSL_EXPORT int (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx))(SSL *ssl,
+ X509 **x509,
+ EVP_PKEY **pkey);
+OPENSSL_EXPORT void SSL_CTX_set_channel_id_cb(
+ SSL_CTX *ctx, void (*channel_id_cb)(SSL *ssl, EVP_PKEY **pkey));
+OPENSSL_EXPORT void (*SSL_CTX_get_channel_id_cb(SSL_CTX *ctx))(SSL *ssl,
+ EVP_PKEY **pkey);
+OPENSSL_EXPORT void SSL_CTX_set_cookie_generate_cb(
+ SSL_CTX *ctx,
+ int (*app_gen_cookie_cb)(SSL *ssl, uint8_t *cookie, size_t *cookie_len));
+OPENSSL_EXPORT void SSL_CTX_set_cookie_verify_cb(
+ SSL_CTX *ctx, int (*app_verify_cookie_cb)(SSL *ssl, const uint8_t *cookie,
+ size_t cookie_len));
+
+
+/* SSL_enable_signed_cert_timestamps causes |ssl| (which must be the client end
+ * of a connection) to request SCTs from the server. See
+ * https://tools.ietf.org/html/rfc6962. Returns 1 on success. */
+OPENSSL_EXPORT int SSL_enable_signed_cert_timestamps(SSL *ssl);
+
+/* SSL_CTX_enable_signed_cert_timestamps enables SCT requests on all client SSL
+ * objects created from |ctx|. */
+OPENSSL_EXPORT void SSL_CTX_enable_signed_cert_timestamps(SSL_CTX *ctx);
+
+/* SSL_enable_signed_cert_timestamps causes |ssl| (which must be the client end
+ * of a connection) to request a stapled OCSP response from the server. Returns
+ * 1 on success. */
+OPENSSL_EXPORT int SSL_enable_ocsp_stapling(SSL *ssl);
+
+/* SSL_CTX_enable_ocsp_stapling enables OCSP stapling on all client SSL objects
+ * created from |ctx|. */
+OPENSSL_EXPORT void SSL_CTX_enable_ocsp_stapling(SSL_CTX *ctx);
+
+/* SSL_get0_signed_cert_timestamp_list sets |*out| and |*out_len| to point to
+ * |*out_len| bytes of SCT information from the server. This is only valid if
+ * |ssl| is a client. The SCT information is a SignedCertificateTimestampList
+ * (including the two leading length bytes).
+ * See https://tools.ietf.org/html/rfc6962#section-3.3
+ * If no SCT was received then |*out_len| will be zero on return.
+ *
+ * WARNING: the returned data is not guaranteed to be well formed. */
+OPENSSL_EXPORT void SSL_get0_signed_cert_timestamp_list(const SSL *ssl,
+ const uint8_t **out,
+ size_t *out_len);
+
+/* SSL_get0_ocsp_response sets |*out| and |*out_len| to point to |*out_len|
+ * bytes of an OCSP response from the server. This is the DER encoding of an
+ * OCSPResponse type as defined in RFC 2560.
+ *
+ * WARNING: the returned data is not guaranteed to be well formed. */
+OPENSSL_EXPORT void SSL_get0_ocsp_response(const SSL *ssl, const uint8_t **out,
+ size_t *out_len);
+
+OPENSSL_EXPORT void SSL_CTX_set_next_protos_advertised_cb(
+ SSL_CTX *s,
+ int (*cb)(SSL *ssl, const uint8_t **out, unsigned int *outlen, void *arg),
+ void *arg);
+OPENSSL_EXPORT void SSL_CTX_set_next_proto_select_cb(
+ SSL_CTX *s, int (*cb)(SSL *ssl, uint8_t **out, uint8_t *outlen,
+ const uint8_t *in, unsigned int inlen, void *arg),
+ void *arg);
+OPENSSL_EXPORT void SSL_get0_next_proto_negotiated(const SSL *s,
+ const uint8_t **data,
+ unsigned *len);
+
+OPENSSL_EXPORT int SSL_select_next_proto(uint8_t **out, uint8_t *outlen,
+ const uint8_t *in, unsigned int inlen,
+ const uint8_t *client,
+ unsigned int client_len);
+
+#define OPENSSL_NPN_UNSUPPORTED 0
+#define OPENSSL_NPN_NEGOTIATED 1
+#define OPENSSL_NPN_NO_OVERLAP 2
+
+OPENSSL_EXPORT int SSL_CTX_set_alpn_protos(SSL_CTX *ctx, const uint8_t *protos,
+ unsigned protos_len);
+OPENSSL_EXPORT int SSL_set_alpn_protos(SSL *ssl, const uint8_t *protos,
+ unsigned protos_len);
+OPENSSL_EXPORT void SSL_CTX_set_alpn_select_cb(
+ SSL_CTX *ctx, int (*cb)(SSL *ssl, const uint8_t **out, uint8_t *outlen,
+ const uint8_t *in, unsigned int inlen, void *arg),
+ void *arg);
+OPENSSL_EXPORT void SSL_get0_alpn_selected(const SSL *ssl, const uint8_t **data,
+ unsigned *len);
+
+/* SSL_enable_fastradio_padding controls whether fastradio padding is enabled
+ * on |ssl|. If it is, ClientHello messages are padded to 1024 bytes. This
+ * causes 3G radios to switch to DCH mode (high data rate). */
+OPENSSL_EXPORT void SSL_enable_fastradio_padding(SSL *ssl, char on_off);
+
+/* the maximum length of the buffer given to callbacks containing the resulting
+ * identity/psk */
+#define PSK_MAX_IDENTITY_LEN 128
+#define PSK_MAX_PSK_LEN 256
+OPENSSL_EXPORT void SSL_CTX_set_psk_client_callback(
+ SSL_CTX *ctx,
+ unsigned int (*psk_client_callback)(
+ SSL *ssl, const char *hint, char *identity,
+ unsigned int max_identity_len, uint8_t *psk, unsigned int max_psk_len));
+OPENSSL_EXPORT void SSL_set_psk_client_callback(
+ SSL *ssl, unsigned int (*psk_client_callback)(SSL *ssl, const char *hint,
+ char *identity,
+ unsigned int max_identity_len,
+ uint8_t *psk,
+ unsigned int max_psk_len));
+OPENSSL_EXPORT void SSL_CTX_set_psk_server_callback(
+ SSL_CTX *ctx,
+ unsigned int (*psk_server_callback)(SSL *ssl, const char *identity,
+ uint8_t *psk,
+ unsigned int max_psk_len));
+OPENSSL_EXPORT void SSL_set_psk_server_callback(
+ SSL *ssl,
+ unsigned int (*psk_server_callback)(SSL *ssl, const char *identity,
+ uint8_t *psk,
+ unsigned int max_psk_len));
+OPENSSL_EXPORT int SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx,
+ const char *identity_hint);
+OPENSSL_EXPORT int SSL_use_psk_identity_hint(SSL *s, const char *identity_hint);
+OPENSSL_EXPORT const char *SSL_get_psk_identity_hint(const SSL *s);
+OPENSSL_EXPORT const char *SSL_get_psk_identity(const SSL *s);
+OPENSSL_EXPORT void ssl_update_cache(SSL *s, int mode);
+OPENSSL_EXPORT int ssl_get_new_session(SSL *s, int session);
+
+#define SSL_NOTHING 1
+#define SSL_WRITING 2
+#define SSL_READING 3
+#define SSL_X509_LOOKUP 4
+#define SSL_CHANNEL_ID_LOOKUP 5
+#define SSL_PENDING_SESSION 7
+#define SSL_CERTIFICATE_SELECTION_PENDING 8
+
+/* These will only be used when doing non-blocking IO */
+#define SSL_want_nothing(s) (SSL_want(s) == SSL_NOTHING)
+#define SSL_want_read(s) (SSL_want(s) == SSL_READING)
+#define SSL_want_write(s) (SSL_want(s) == SSL_WRITING)
+#define SSL_want_x509_lookup(s) (SSL_want(s) == SSL_X509_LOOKUP)
+#define SSL_want_channel_id_lookup(s) (SSL_want(s) == SSL_CHANNEL_ID_LOOKUP)
+#define SSL_want_session(s) (SSL_want(s) == SSL_PENDING_SESSION)
+#define SSL_want_certificate(s) \
+ (SSL_want(s) == SSL_CERTIFICATE_SELECTION_PENDING)
+
+struct ssl_st {
+ /* version is the protocol version. */
+ int version;
+
+ /* method is the method table corresponding to the current protocol (DTLS or
+ * TLS). */
+ const SSL_PROTOCOL_METHOD *method;
+
+ /* enc_method is the method table corresponding to the current protocol
+ * version. */
+ const SSL3_ENC_METHOD *enc_method;
+
+ /* max_version is the maximum acceptable protocol version. If zero, the
+ * maximum supported version, currently (D)TLS 1.2, is used. */
+ uint16_t max_version;
+
+ /* min_version is the minimum acceptable protocl version. If zero, the
+ * minimum supported version, currently SSL 3.0 and DTLS 1.0, is used */
+ uint16_t min_version;
+
+ /* 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 */
+
+ /* 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;
+
+ /* true when we are actually in SSL_accept() or SSL_connect() */
+ int in_handshake;
+ int (*handshake_func)(SSL *);
+
+ /* 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. */
+
+ /* server is true iff the this SSL* is the server half. Note: before the SSL*
+ * is initialized by either SSL_set_accept_state or SSL_set_connect_state,
+ * the side is not determined. In this state, server is always false. */
+ int server;
+
+
+ /* 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 new_session;
+
+ /* quiet_shutdown is true if the connection should not send a close_notify on
+ * shutdown. */
+ int quiet_shutdown;
+
+ int shutdown; /* we have shut things down, 0x01 sent, 0x02
+ * for received */
+ int state; /* where we are */
+ int rstate; /* where we are when reading */
+
+ BUF_MEM *init_buf; /* buffer used during init */
+ uint8_t *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 */
+ uint8_t *packet;
+ unsigned int packet_length;
+
+ struct ssl3_state_st *s3; /* SSLv3 variables */
+ struct dtls1_state_st *d1; /* DTLSv1 variables */
+
+ int read_ahead; /* Read as many input bytes as possible
+ * (for non-blocking reads) */
+
+ /* callback that allows applications to peek at protocol messages */
+ void (*msg_callback)(int write_p, int version, int content_type,
+ const void *buf, size_t len, SSL *ssl, void *arg);
+ void *msg_callback_arg;
+
+ int hit; /* reusing a previous session */
+
+ X509_VERIFY_PARAM *param;
+
+ /* crypto */
+ struct ssl_cipher_preference_list_st *cipher_list;
+ STACK_OF(SSL_CIPHER) *cipher_list_by_id;
+
+ SSL_AEAD_CTX *aead_read_ctx;
+ SSL_AEAD_CTX *aead_write_ctx;
+
+ /* session info */
+
+ /* client cert? */
+ /* This is used to hold the server certificate used */
+ struct cert_st /* CERT */ *cert;
+
+ /* the session_id_context is used to ensure sessions are only reused
+ * in the appropriate context */
+ unsigned int sid_ctx_length;
+ uint8_t sid_ctx[SSL_MAX_SID_CTX_LENGTH];
+
+ /* This can also be in the session once a session is established */
+ SSL_SESSION *session;
+
+ /* Default generate session ID callback. */
+ GEN_SESSION_CB generate_session_id;
+
+ /* Used in SSL2 and SSL3 */
+ int verify_mode; /* 0 don't care about verify failure.
+ * 1 fail if verify fails */
+ int (*verify_callback)(int ok,
+ X509_STORE_CTX *ctx); /* fail if callback returns 0 */
+
+ void (*info_callback)(const SSL *ssl, int type,
+ int val); /* optional informational callback */
+
+ /* Server-only: psk_identity_hint is the identity hint to send in
+ * PSK-based key exchanges. */
+ char *psk_identity_hint;
+
+ unsigned int (*psk_client_callback)(SSL *ssl, const char *hint,
+ char *identity,
+ unsigned int max_identity_len,
+ uint8_t *psk, unsigned int max_psk_len);
+ unsigned int (*psk_server_callback)(SSL *ssl, const char *identity,
+ uint8_t *psk, unsigned int max_psk_len);
+
+ SSL_CTX *ctx;
+
+ /* extra application data */
+ long verify_result;
+ CRYPTO_EX_DATA ex_data;
+
+ /* for server side, keep the list of CA_dn we can use */
+ STACK_OF(X509_NAME) *client_CA;
+
+ int references;
+ unsigned long options; /* protocol behaviour */
+ unsigned long mode; /* API behaviour */
+ long max_cert_list;
+ int client_version; /* what was passed, used for
+ * SSLv3/TLS rollback check */
+ unsigned int max_send_fragment;
+ /* TLS extension debug callback */
+ void (*tlsext_debug_cb)(SSL *s, int client_server, int type, uint8_t *data,
+ int len, void *arg);
+ void *tlsext_debug_arg;
+ char *tlsext_hostname;
+ /* should_ack_sni is true if the SNI extension should be acked. This is
+ * only used by a server. */
+ char should_ack_sni;
+ /* 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_ellipticcurvelist_length;
+ uint16_t *tlsext_ellipticcurvelist; /* our list */
+
+ SSL_CTX *initial_ctx; /* initial ctx, used to store sessions */
+
+ /* Next protocol negotiation. For the client, this is the protocol that we
+ * sent in NextProtocol and is set when handling ServerHello extensions.
+ *
+ * For a server, this is the client's selected_protocol from NextProtocol and
+ * is set when handling the NextProtocol message, before the Finished
+ * message. */
+ uint8_t *next_proto_negotiated;
+ size_t next_proto_negotiated_len;
+
+ /* srtp_profiles is the list of configured SRTP protection profiles for
+ * DTLS-SRTP. */
+ STACK_OF(SRTP_PROTECTION_PROFILE) *srtp_profiles;
+
+ /* srtp_profile is the selected SRTP protection profile for
+ * DTLS-SRTP. */
+ const SRTP_PROTECTION_PROFILE *srtp_profile;
+
+ /* Copied from the SSL_CTX. For a server, means that we'll accept Channel IDs
+ * from clients. For a client, means that we'll advertise support. */
+ char tlsext_channel_id_enabled;
+ /* The client's Channel ID private key. */
+ EVP_PKEY *tlsext_channel_id_private;
+
+ /* Enable signed certificate time stamps. Currently client only. */
+ char signed_cert_timestamps_enabled;
+
+ /* Enable OCSP stapling. Currently client only.
+ * TODO(davidben): Add a server-side implementation when it becomes
+ * necesary. */
+ char ocsp_stapling_enabled;
+
+ /* For a client, this contains the list of supported protocols in wire
+ * format. */
+ uint8_t *alpn_client_proto_list;
+ unsigned alpn_client_proto_list_len;
+
+ 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) */
+
+ /* fallback_scsv is non-zero iff we are sending the TLS_FALLBACK_SCSV cipher
+ * suite value. Only applies to a client. */
+ char fallback_scsv;
+
+ /* fastradio_padding, if true, causes ClientHellos to be padded to 1024
+ * bytes. This ensures that the cellular radio is fast forwarded to DCH (high
+ * data rate) state in 3G networks. */
+ char fastradio_padding;
+
+ /* These fields are always NULL and exist only to keep wpa_supplicant happy
+ * about the change to EVP_AEAD. They are only needed for EAP-FAST, which we
+ * don't support. */
+ EVP_CIPHER_CTX *enc_read_ctx;
+ EVP_MD_CTX *read_hash;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#include <openssl/ssl2.h>
+#include <openssl/ssl3.h>
+#include <openssl/tls1.h> /* This is mostly sslv3 with a few tweaks */
+#include <openssl/dtls1.h> /* Datagram TLS */
+#include <openssl/ssl23.h>
+#include <openssl/srtp.h> /* 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) && !SSL_cutthrough_complete(a))
+#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)
+OPENSSL_EXPORT int SSL_cutthrough_complete(const SSL *s);
+
+/* 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. */
+OPENSSL_EXPORT size_t SSL_get_finished(const SSL *s, void *buf, size_t count);
+OPENSSL_EXPORT size_t SSL_get_peer_finished(const SSL *s, void *buf, size_t count);
+
+/* use either SSL_VERIFY_NONE or SSL_VERIFY_PEER, the last 3 options
+ * are 'ored' with SSL_VERIFY_PEER if they are desired */
+#define SSL_VERIFY_NONE 0x00
+#define SSL_VERIFY_PEER 0x01
+#define SSL_VERIFY_FAIL_IF_NO_PEER_CERT 0x02
+#define SSL_VERIFY_CLIENT_ONCE 0x04
+#define SSL_VERIFY_PEER_IF_NO_OBC 0x08
+
+#define OpenSSL_add_ssl_algorithms() SSL_library_init()
+#define SSLeay_add_ssl_algorithms() SSL_library_init()
+
+/* For backward compatibility */
+#define SSL_get_cipher(s) SSL_CIPHER_get_name(SSL_get_current_cipher(s))
+#define SSL_get_cipher_bits(s, np) \
+ SSL_CIPHER_get_bits(SSL_get_current_cipher(s), np)
+#define SSL_get_cipher_version(s) \
+ SSL_CIPHER_get_version(SSL_get_current_cipher(s))
+#define SSL_get_cipher_name(s) SSL_CIPHER_get_name(SSL_get_current_cipher(s))
+#define SSL_get_time(a) SSL_SESSION_get_time(a)
+#define SSL_set_time(a, b) SSL_SESSION_set_time((a), (b))
+#define SSL_get_timeout(a) SSL_SESSION_get_timeout(a)
+#define SSL_set_timeout(a, b) SSL_SESSION_set_timeout((a), (b))
+
+#define d2i_SSL_SESSION_bio(bp, s_id) \
+ ASN1_d2i_bio_of(SSL_SESSION, SSL_SESSION_new, d2i_SSL_SESSION, bp, s_id)
+#define i2d_SSL_SESSION_bio(bp, s_id) \
+ ASN1_i2d_bio_of(SSL_SESSION, i2d_SSL_SESSION, bp, s_id)
+
+DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
+
+/* make_errors.go reserves error codes above 1000 for manually-assigned errors.
+ * This value must be kept in sync with reservedReasonCode in make_errors.h */
+#define SSL_AD_REASON_OFFSET \
+ 1000 /* offset to get SSL_R_... value from SSL_AD_... */
+
+/* These alert types are for SSLv3 and TLSv1 */
+#define SSL_AD_CLOSE_NOTIFY SSL3_AD_CLOSE_NOTIFY
+#define SSL_AD_UNEXPECTED_MESSAGE SSL3_AD_UNEXPECTED_MESSAGE /* fatal */
+#define SSL_AD_BAD_RECORD_MAC SSL3_AD_BAD_RECORD_MAC /* fatal */
+#define SSL_AD_DECRYPTION_FAILED TLS1_AD_DECRYPTION_FAILED
+#define SSL_AD_RECORD_OVERFLOW TLS1_AD_RECORD_OVERFLOW
+#define SSL_AD_DECOMPRESSION_FAILURE SSL3_AD_DECOMPRESSION_FAILURE /* fatal */
+#define SSL_AD_HANDSHAKE_FAILURE SSL3_AD_HANDSHAKE_FAILURE /* fatal */
+#define SSL_AD_NO_CERTIFICATE SSL3_AD_NO_CERTIFICATE /* Not for TLS */
+#define SSL_AD_BAD_CERTIFICATE SSL3_AD_BAD_CERTIFICATE
+#define SSL_AD_UNSUPPORTED_CERTIFICATE SSL3_AD_UNSUPPORTED_CERTIFICATE
+#define SSL_AD_CERTIFICATE_REVOKED SSL3_AD_CERTIFICATE_REVOKED
+#define SSL_AD_CERTIFICATE_EXPIRED SSL3_AD_CERTIFICATE_EXPIRED
+#define SSL_AD_CERTIFICATE_UNKNOWN SSL3_AD_CERTIFICATE_UNKNOWN
+#define SSL_AD_ILLEGAL_PARAMETER SSL3_AD_ILLEGAL_PARAMETER /* fatal */
+#define SSL_AD_UNKNOWN_CA TLS1_AD_UNKNOWN_CA /* fatal */
+#define SSL_AD_ACCESS_DENIED TLS1_AD_ACCESS_DENIED /* fatal */
+#define SSL_AD_DECODE_ERROR TLS1_AD_DECODE_ERROR /* fatal */
+#define SSL_AD_DECRYPT_ERROR TLS1_AD_DECRYPT_ERROR
+#define SSL_AD_EXPORT_RESTRICTION TLS1_AD_EXPORT_RESTRICTION /* fatal */
+#define SSL_AD_PROTOCOL_VERSION TLS1_AD_PROTOCOL_VERSION /* fatal */
+#define SSL_AD_INSUFFICIENT_SECURITY TLS1_AD_INSUFFICIENT_SECURITY /* fatal */
+#define SSL_AD_INTERNAL_ERROR TLS1_AD_INTERNAL_ERROR /* fatal */
+#define SSL_AD_USER_CANCELLED TLS1_AD_USER_CANCELLED
+#define SSL_AD_NO_RENEGOTIATION TLS1_AD_NO_RENEGOTIATION
+#define SSL_AD_UNSUPPORTED_EXTENSION TLS1_AD_UNSUPPORTED_EXTENSION
+#define SSL_AD_CERTIFICATE_UNOBTAINABLE TLS1_AD_CERTIFICATE_UNOBTAINABLE
+#define SSL_AD_UNRECOGNIZED_NAME TLS1_AD_UNRECOGNIZED_NAME
+#define SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE \
+ TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE
+#define SSL_AD_BAD_CERTIFICATE_HASH_VALUE TLS1_AD_BAD_CERTIFICATE_HASH_VALUE
+#define SSL_AD_UNKNOWN_PSK_IDENTITY TLS1_AD_UNKNOWN_PSK_IDENTITY /* fatal */
+#define SSL_AD_INAPPROPRIATE_FALLBACK SSL3_AD_INAPPROPRIATE_FALLBACK /* fatal */
+
+#define SSL_ERROR_NONE 0
+#define SSL_ERROR_SSL 1
+#define SSL_ERROR_WANT_READ 2
+#define SSL_ERROR_WANT_WRITE 3
+#define SSL_ERROR_WANT_X509_LOOKUP 4
+#define SSL_ERROR_SYSCALL 5 /* look at error stack/return value/errno */
+#define SSL_ERROR_ZERO_RETURN 6
+#define SSL_ERROR_WANT_CONNECT 7
+#define SSL_ERROR_WANT_ACCEPT 8
+#define SSL_ERROR_WANT_CHANNEL_ID_LOOKUP 9
+#define SSL_ERROR_PENDING_SESSION 11
+#define SSL_ERROR_PENDING_CERTIFICATE 12
+
+#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_SET_TLSEXT_STATUS_REQ_CB 63
+#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB_ARG 64
+
+#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 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_GET_CURVES 90
+#define SSL_CTRL_SET_CURVES 91
+#define SSL_CTRL_SET_CURVES_LIST 92
+#define SSL_CTRL_SET_ECDH_AUTO 94
+#define SSL_CTRL_SET_SIGALGS 97
+#define SSL_CTRL_SET_SIGALGS_LIST 98
+#define SSL_CTRL_CERT_FLAGS 99
+#define SSL_CTRL_CLEAR_CERT_FLAGS 100
+#define SSL_CTRL_SET_CLIENT_SIGALGS 101
+#define SSL_CTRL_SET_CLIENT_SIGALGS_LIST 102
+#define SSL_CTRL_GET_CLIENT_CERT_TYPES 103
+#define SSL_CTRL_SET_CLIENT_CERT_TYPES 104
+#define SSL_CTRL_BUILD_CERT_CHAIN 105
+#define SSL_CTRL_SET_VERIFY_CERT_STORE 106
+#define SSL_CTRL_SET_CHAIN_CERT_STORE 107
+#define SSL_CTRL_GET_SERVER_TMP_KEY 109
+#define SSL_CTRL_GET_RAW_CIPHERLIST 110
+#define SSL_CTRL_GET_EC_POINT_FORMATS 111
+
+#define SSL_CTRL_GET_CHAIN_CERTS 115
+#define SSL_CTRL_SELECT_CURRENT_CERT 116
+
+#define SSL_CTRL_CHANNEL_ID 117
+#define SSL_CTRL_GET_CHANNEL_ID 118
+#define SSL_CTRL_SET_CHANNEL_ID 119
+
+#define SSL_CTRL_FALLBACK_SCSV 120
+
+#define DTLSv1_get_timeout(ssl, arg) \
+ SSL_ctrl(ssl, DTLS_CTRL_GET_TIMEOUT, 0, (void *)arg)
+#define DTLSv1_handle_timeout(ssl) \
+ SSL_ctrl(ssl, DTLS_CTRL_HANDLE_TIMEOUT, 0, NULL)
+
+#define SSL_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_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)
+
+/* SSL_enable_tls_channel_id either configures a TLS server to accept TLS
+ * client IDs from clients, or configure a client to send TLS client IDs to
+ * server. Returns 1 on success. */
+#define SSL_enable_tls_channel_id(s) SSL_ctrl(s, SSL_CTRL_CHANNEL_ID, 0, NULL)
+
+/* SSL_set1_tls_channel_id configures a TLS client to send a TLS Channel ID to
+ * compatible servers. private_key must be a P-256 EVP_PKEY*. Returns 1 on
+ * success. */
+#define SSL_set1_tls_channel_id(s, private_key) \
+ SSL_ctrl(s, SSL_CTRL_SET_CHANNEL_ID, 0, (void *)private_key)
+#define SSL_CTX_set1_tls_channel_id(ctx, private_key) \
+ SSL_CTX_ctrl(ctx, SSL_CTRL_SET_CHANNEL_ID, 0, (void *)private_key)
+
+/* SSL_get_tls_channel_id gets the client's TLS Channel ID from a server SSL*
+ * and copies up to the first |channel_id_len| bytes into |channel_id|. The
+ * Channel ID consists of the client's P-256 public key as an (x,y) pair where
+ * each is a 32-byte, big-endian field element. Returns 0 if the client didn't
+ * offer a Channel ID and the length of the complete Channel ID otherwise. */
+#define SSL_get_tls_channel_id(ctx, channel_id, channel_id_len) \
+ SSL_ctrl(ctx, SSL_CTRL_GET_CHANNEL_ID, channel_id_len, (void *)channel_id)
+
+#define SSL_CTX_add_extra_chain_cert(ctx, x509) \
+ SSL_CTX_ctrl(ctx, SSL_CTRL_EXTRA_CHAIN_CERT, 0, (char *)x509)
+#define SSL_CTX_get_extra_chain_certs(ctx, px509) \
+ SSL_CTX_ctrl(ctx, SSL_CTRL_GET_EXTRA_CHAIN_CERTS, 0, px509)
+#define SSL_CTX_get_extra_chain_certs_only(ctx, px509) \
+ SSL_CTX_ctrl(ctx, SSL_CTRL_GET_EXTRA_CHAIN_CERTS, 1, px509)
+#define SSL_CTX_clear_extra_chain_certs(ctx) \
+ SSL_CTX_ctrl(ctx, SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS, 0, NULL)
+
+#define SSL_CTX_set0_chain(ctx, sk) \
+ SSL_CTX_ctrl(ctx, SSL_CTRL_CHAIN, 0, (char *)sk)
+#define SSL_CTX_set1_chain(ctx, sk) \
+ SSL_CTX_ctrl(ctx, SSL_CTRL_CHAIN, 1, (char *)sk)
+#define SSL_CTX_add0_chain_cert(ctx, x509) \
+ SSL_CTX_ctrl(ctx, SSL_CTRL_CHAIN_CERT, 0, (char *)x509)
+#define SSL_CTX_add1_chain_cert(ctx, x509) \
+ SSL_CTX_ctrl(ctx, SSL_CTRL_CHAIN_CERT, 1, (char *)x509)
+#define SSL_CTX_get0_chain_certs(ctx, px509) \
+ SSL_CTX_ctrl(ctx, SSL_CTRL_GET_CHAIN_CERTS, 0, px509)
+#define SSL_CTX_clear_chain_certs(ctx) SSL_CTX_set0_chain(ctx, NULL)
+#define SSL_CTX_build_cert_chain(ctx, flags) \
+ SSL_CTX_ctrl(ctx, SSL_CTRL_BUILD_CERT_CHAIN, flags, NULL)
+#define SSL_CTX_select_current_cert(ctx, x509) \
+ SSL_CTX_ctrl(ctx, SSL_CTRL_SELECT_CURRENT_CERT, 0, (char *)x509)
+
+#define SSL_CTX_set0_verify_cert_store(ctx, st) \
+ SSL_CTX_ctrl(ctx, SSL_CTRL_SET_VERIFY_CERT_STORE, 0, (char *)st)
+#define SSL_CTX_set1_verify_cert_store(ctx, st) \
+ SSL_CTX_ctrl(ctx, SSL_CTRL_SET_VERIFY_CERT_STORE, 1, (char *)st)
+#define SSL_CTX_set0_chain_cert_store(ctx, st) \
+ SSL_CTX_ctrl(ctx, SSL_CTRL_SET_CHAIN_CERT_STORE, 0, (char *)st)
+#define SSL_CTX_set1_chain_cert_store(ctx, st) \
+ SSL_CTX_ctrl(ctx, SSL_CTRL_SET_CHAIN_CERT_STORE, 1, (char *)st)
+
+#define SSL_set0_chain(ctx, sk) SSL_ctrl(ctx, SSL_CTRL_CHAIN, 0, (char *)sk)
+#define SSL_set1_chain(ctx, sk) SSL_ctrl(ctx, SSL_CTRL_CHAIN, 1, (char *)sk)
+#define SSL_add0_chain_cert(ctx, x509) \
+ SSL_ctrl(ctx, SSL_CTRL_CHAIN_CERT, 0, (char *)x509)
+#define SSL_add1_chain_cert(ctx, x509) \
+ SSL_ctrl(ctx, SSL_CTRL_CHAIN_CERT, 1, (char *)x509)
+#define SSL_get0_chain_certs(ctx, px509) \
+ SSL_ctrl(ctx, SSL_CTRL_GET_CHAIN_CERTS, 0, px509)
+#define SSL_clear_chain_certs(ctx) SSL_set0_chain(ctx, NULL)
+#define SSL_build_cert_chain(s, flags) \
+ SSL_ctrl(s, SSL_CTRL_BUILD_CERT_CHAIN, flags, NULL)
+#define SSL_select_current_cert(ctx, x509) \
+ SSL_ctrl(ctx, SSL_CTRL_SELECT_CURRENT_CERT, 0, (char *)x509)
+
+#define SSL_set0_verify_cert_store(s, st) \
+ SSL_ctrl(s, SSL_CTRL_SET_VERIFY_CERT_STORE, 0, (char *)st)
+#define SSL_set1_verify_cert_store(s, st) \
+ SSL_ctrl(s, SSL_CTRL_SET_VERIFY_CERT_STORE, 1, (char *)st)
+#define SSL_set0_chain_cert_store(s, st) \
+ SSL_ctrl(s, SSL_CTRL_SET_CHAIN_CERT_STORE, 0, (char *)st)
+#define SSL_set1_chain_cert_store(s, st) \
+ SSL_ctrl(s, SSL_CTRL_SET_CHAIN_CERT_STORE, 1, (char *)st)
+
+#define SSL_get1_curves(ctx, s) SSL_ctrl(ctx, SSL_CTRL_GET_CURVES, 0, (char *)s)
+#define SSL_CTX_set1_curves(ctx, clist, clistlen) \
+ SSL_CTX_ctrl(ctx, SSL_CTRL_SET_CURVES, clistlen, (char *)clist)
+#define SSL_CTX_set1_curves_list(ctx, s) \
+ SSL_CTX_ctrl(ctx, SSL_CTRL_SET_CURVES_LIST, 0, (char *)s)
+#define SSL_set1_curves(ctx, clist, clistlen) \
+ SSL_ctrl(ctx, SSL_CTRL_SET_CURVES, clistlen, (char *)clist)
+#define SSL_set1_curves_list(ctx, s) \
+ SSL_ctrl(ctx, SSL_CTRL_SET_CURVES_LIST, 0, (char *)s)
+#define SSL_CTX_set_ecdh_auto(ctx, onoff) \
+ SSL_CTX_ctrl(ctx, SSL_CTRL_SET_ECDH_AUTO, onoff, NULL)
+#define SSL_set_ecdh_auto(s, onoff) \
+ SSL_ctrl(s, SSL_CTRL_SET_ECDH_AUTO, onoff, NULL)
+
+#define SSL_CTX_set1_sigalgs(ctx, slist, slistlen) \
+ SSL_CTX_ctrl(ctx, SSL_CTRL_SET_SIGALGS, slistlen, (int *)slist)
+#define SSL_CTX_set1_sigalgs_list(ctx, s) \
+ SSL_CTX_ctrl(ctx, SSL_CTRL_SET_SIGALGS_LIST, 0, (char *)s)
+#define SSL_set1_sigalgs(ctx, slist, slistlen) \
+ SSL_ctrl(ctx, SSL_CTRL_SET_SIGALGS, clistlen, (int *)slist)
+#define SSL_set1_sigalgs_list(ctx, s) \
+ SSL_ctrl(ctx, SSL_CTRL_SET_SIGALGS_LIST, 0, (char *)s)
+
+#define SSL_CTX_set1_client_sigalgs(ctx, slist, slistlen) \
+ SSL_CTX_ctrl(ctx, SSL_CTRL_SET_CLIENT_SIGALGS, slistlen, (int *)slist)
+#define SSL_CTX_set1_client_sigalgs_list(ctx, s) \
+ SSL_CTX_ctrl(ctx, SSL_CTRL_SET_CLIENT_SIGALGS_LIST, 0, (char *)s)
+#define SSL_set1_client_sigalgs(ctx, slist, slistlen) \
+ SSL_ctrl(ctx, SSL_CTRL_SET_CLIENT_SIGALGS, clistlen, (int *)slist)
+#define SSL_set1_client_sigalgs_list(ctx, s) \
+ SSL_ctrl(ctx, SSL_CTRL_SET_CLIENT_SIGALGS_LIST, 0, (char *)s)
+
+#define SSL_get0_certificate_types(s, clist) \
+ SSL_ctrl(s, SSL_CTRL_GET_CLIENT_CERT_TYPES, 0, (char *)clist)
+
+#define SSL_CTX_set1_client_certificate_types(ctx, clist, clistlen) \
+ SSL_CTX_ctrl(ctx, SSL_CTRL_SET_CLIENT_CERT_TYPES, clistlen, (char *)clist)
+#define SSL_set1_client_certificate_types(s, clist, clistlen) \
+ SSL_ctrl(s, SSL_CTRL_SET_CLIENT_CERT_TYPES, clistlen, (char *)clist)
+
+#define SSL_get_server_tmp_key(s, pk) \
+ SSL_ctrl(s, SSL_CTRL_GET_SERVER_TMP_KEY, 0, pk)
+
+#define SSL_get0_raw_cipherlist(s, plst) \
+ SSL_ctrl(s, SSL_CTRL_GET_RAW_CIPHERLIST, 0, (char *)plst)
+
+#define SSL_get0_ec_point_formats(s, plst) \
+ SSL_ctrl(s, SSL_CTRL_GET_EC_POINT_FORMATS, 0, (char *)plst)
+
+#define SSL_enable_fallback_scsv(s) \
+ SSL_ctrl(s, SSL_CTRL_FALLBACK_SCSV, 0, NULL)
+
+OPENSSL_EXPORT int SSL_CTX_set_cipher_list(SSL_CTX *, const char *str);
+OPENSSL_EXPORT int SSL_CTX_set_cipher_list_tls11(SSL_CTX *, const char *str);
+OPENSSL_EXPORT SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth);
+OPENSSL_EXPORT void SSL_CTX_free(SSL_CTX *);
+OPENSSL_EXPORT long SSL_CTX_set_timeout(SSL_CTX *ctx, long t);
+OPENSSL_EXPORT long SSL_CTX_get_timeout(const SSL_CTX *ctx);
+OPENSSL_EXPORT X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *);
+OPENSSL_EXPORT void SSL_CTX_set_cert_store(SSL_CTX *, X509_STORE *);
+OPENSSL_EXPORT int SSL_want(const SSL *s);
+OPENSSL_EXPORT int SSL_clear(SSL *s);
+
+OPENSSL_EXPORT void SSL_CTX_flush_sessions(SSL_CTX *ctx, long tm);
+
+OPENSSL_EXPORT const SSL_CIPHER *SSL_get_current_cipher(const SSL *s);
+OPENSSL_EXPORT int SSL_CIPHER_get_bits(const SSL_CIPHER *c, int *alg_bits);
+OPENSSL_EXPORT const char *SSL_CIPHER_get_version(const SSL_CIPHER *c);
+OPENSSL_EXPORT const char *SSL_CIPHER_get_name(const SSL_CIPHER *c);
+/* SSL_CIPHER_get_kx_name returns a string that describes the key-exchange
+ * method used by |c|. For example, "ECDHE-ECDSA". */
+OPENSSL_EXPORT const char *SSL_CIPHER_get_kx_name(const SSL_CIPHER *cipher);
+OPENSSL_EXPORT unsigned long SSL_CIPHER_get_id(const SSL_CIPHER *c);
+
+OPENSSL_EXPORT int SSL_get_fd(const SSL *s);
+OPENSSL_EXPORT int SSL_get_rfd(const SSL *s);
+OPENSSL_EXPORT int SSL_get_wfd(const SSL *s);
+OPENSSL_EXPORT const char *SSL_get_cipher_list(const SSL *s, int n);
+OPENSSL_EXPORT int SSL_get_read_ahead(const SSL *s);
+OPENSSL_EXPORT int SSL_pending(const SSL *s);
+OPENSSL_EXPORT int SSL_set_fd(SSL *s, int fd);
+OPENSSL_EXPORT int SSL_set_rfd(SSL *s, int fd);
+OPENSSL_EXPORT int SSL_set_wfd(SSL *s, int fd);
+OPENSSL_EXPORT void SSL_set_bio(SSL *s, BIO *rbio, BIO *wbio);
+OPENSSL_EXPORT BIO *SSL_get_rbio(const SSL *s);
+OPENSSL_EXPORT BIO *SSL_get_wbio(const SSL *s);
+OPENSSL_EXPORT int SSL_set_cipher_list(SSL *s, const char *str);
+OPENSSL_EXPORT void SSL_set_read_ahead(SSL *s, int yes);
+OPENSSL_EXPORT int SSL_get_verify_mode(const SSL *s);
+OPENSSL_EXPORT int SSL_get_verify_depth(const SSL *s);
+OPENSSL_EXPORT int (*SSL_get_verify_callback(const SSL *s))(int,
+ X509_STORE_CTX *);
+OPENSSL_EXPORT void SSL_set_verify(SSL *s, int mode,
+ int (*callback)(int ok,
+ X509_STORE_CTX *ctx));
+OPENSSL_EXPORT void SSL_set_verify_depth(SSL *s, int depth);
+OPENSSL_EXPORT void SSL_set_cert_cb(SSL *s, int (*cb)(SSL *ssl, void *arg),
+ void *arg);
+OPENSSL_EXPORT int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa);
+OPENSSL_EXPORT int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, uint8_t *d, long len);
+OPENSSL_EXPORT int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey);
+OPENSSL_EXPORT int SSL_use_PrivateKey_ASN1(int pk, SSL *ssl, const uint8_t *d,
+ long len);
+OPENSSL_EXPORT int SSL_use_certificate(SSL *ssl, X509 *x);
+OPENSSL_EXPORT int SSL_use_certificate_ASN1(SSL *ssl, const uint8_t *d,
+ int len);
+
+OPENSSL_EXPORT int SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file,
+ int type);
+OPENSSL_EXPORT int SSL_use_PrivateKey_file(SSL *ssl, const char *file,
+ int type);
+OPENSSL_EXPORT int SSL_use_certificate_file(SSL *ssl, const char *file,
+ int type);
+OPENSSL_EXPORT int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx,
+ const char *file, int type);
+OPENSSL_EXPORT int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file,
+ int type);
+OPENSSL_EXPORT int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file,
+ int type);
+OPENSSL_EXPORT int SSL_CTX_use_certificate_chain_file(
+ SSL_CTX *ctx, const char *file); /* PEM type */
+OPENSSL_EXPORT STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file);
+OPENSSL_EXPORT int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *
+ stackCAs,
+ const char *file);
+OPENSSL_EXPORT int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *
+ stackCAs,
+ const char *dir);
+
+/* SSL_load_error_strings does nothing. */
+OPENSSL_EXPORT void SSL_load_error_strings(void);
+
+OPENSSL_EXPORT const char *SSL_state_string(const SSL *s);
+OPENSSL_EXPORT const char *SSL_rstate_string(const SSL *s);
+OPENSSL_EXPORT const char *SSL_state_string_long(const SSL *s);
+OPENSSL_EXPORT const char *SSL_rstate_string_long(const SSL *s);
+OPENSSL_EXPORT long SSL_SESSION_get_time(const SSL_SESSION *s);
+OPENSSL_EXPORT long SSL_SESSION_set_time(SSL_SESSION *s, long t);
+OPENSSL_EXPORT long SSL_SESSION_get_timeout(const SSL_SESSION *s);
+OPENSSL_EXPORT long SSL_SESSION_set_timeout(SSL_SESSION *s, long t);
+OPENSSL_EXPORT X509 *SSL_SESSION_get0_peer(SSL_SESSION *s);
+OPENSSL_EXPORT int SSL_SESSION_set1_id_context(SSL_SESSION *s,
+ const uint8_t *sid_ctx,
+ unsigned int sid_ctx_len);
+
+OPENSSL_EXPORT SSL_SESSION *SSL_SESSION_new(void);
+OPENSSL_EXPORT const uint8_t *SSL_SESSION_get_id(const SSL_SESSION *s,
+ unsigned int *len);
+OPENSSL_EXPORT int SSL_SESSION_print_fp(FILE *fp, const SSL_SESSION *ses);
+OPENSSL_EXPORT int SSL_SESSION_print(BIO *fp, const SSL_SESSION *ses);
+OPENSSL_EXPORT void SSL_SESSION_free(SSL_SESSION *ses);
+OPENSSL_EXPORT int SSL_set_session(SSL *to, SSL_SESSION *session);
+OPENSSL_EXPORT int SSL_CTX_add_session(SSL_CTX *s, SSL_SESSION *c);
+OPENSSL_EXPORT int SSL_CTX_remove_session(SSL_CTX *, SSL_SESSION *c);
+OPENSSL_EXPORT int SSL_CTX_set_generate_session_id(SSL_CTX *, GEN_SESSION_CB);
+OPENSSL_EXPORT int SSL_set_generate_session_id(SSL *, GEN_SESSION_CB);
+OPENSSL_EXPORT int SSL_has_matching_session_id(const SSL *ssl,
+ const uint8_t *id,
+ unsigned int id_len);
+
+/* SSL_SESSION_to_bytes serializes |in| into a newly allocated buffer and sets
+ * |*out_data| to that buffer and |*out_len| to its length. The caller takes
+ * ownership of the buffer and must call |OPENSSL_free| when done. It returns
+ * one on success and zero on error. */
+OPENSSL_EXPORT int SSL_SESSION_to_bytes(SSL_SESSION *in, uint8_t **out_data,
+ size_t *out_len);
+
+/* SSL_SESSION_to_bytes_for_ticket serializes |in|, but excludes the session ID
+ * which is not necessary in a session ticket. */
+OPENSSL_EXPORT int SSL_SESSION_to_bytes_for_ticket(SSL_SESSION *in,
+ uint8_t **out_data,
+ size_t *out_len);
+
+/* Deprecated: i2d_SSL_SESSION serializes |in| to the bytes pointed to by
+ * |*pp|. On success, it returns the number of bytes written and advances |*pp|
+ * by that many bytes. On failure, it returns -1. If |pp| is NULL, no bytes are
+ * written and only the length is returned.
+ *
+ * Use SSL_SESSION_to_bytes instead. */
+OPENSSL_EXPORT int i2d_SSL_SESSION(SSL_SESSION *in, uint8_t **pp);
+
+/* d2i_SSL_SESSION deserializes a serialized buffer contained in the |length|
+ * bytes pointed to by |*pp|. It returns the new SSL_SESSION and advances |*pp|
+ * by the number of bytes consumed on success and NULL on failure. If |a| is
+ * NULL, the caller takes ownership of the new session and must call
+ * |SSL_SESSION_free| when done.
+ *
+ * If |a| and |*a| are not NULL, the SSL_SESSION at |*a| is overridden with the
+ * deserialized session rather than allocating a new one. In addition, |a| is
+ * not NULL, but |*a| is, |*a| is set to the new SSL_SESSION.
+ *
+ * Passing a value other than NULL to |a| is deprecated. */
+OPENSSL_EXPORT SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const uint8_t **pp,
+ long length);
+
+OPENSSL_EXPORT X509 *SSL_get_peer_certificate(const SSL *s);
+
+OPENSSL_EXPORT STACK_OF(X509) *SSL_get_peer_cert_chain(const SSL *s);
+
+OPENSSL_EXPORT int SSL_CTX_get_verify_mode(const SSL_CTX *ctx);
+OPENSSL_EXPORT int SSL_CTX_get_verify_depth(const SSL_CTX *ctx);
+OPENSSL_EXPORT int (*SSL_CTX_get_verify_callback(const SSL_CTX *ctx))(
+ int, X509_STORE_CTX *);
+OPENSSL_EXPORT void SSL_CTX_set_verify(SSL_CTX *ctx, int mode,
+ int (*callback)(int, X509_STORE_CTX *));
+OPENSSL_EXPORT void SSL_CTX_set_verify_depth(SSL_CTX *ctx, int depth);
+OPENSSL_EXPORT void SSL_CTX_set_cert_verify_callback(
+ SSL_CTX *ctx, int (*cb)(X509_STORE_CTX *, void *), void *arg);
+OPENSSL_EXPORT void SSL_CTX_set_cert_cb(SSL_CTX *c,
+ int (*cb)(SSL *ssl, void *arg),
+ void *arg);
+OPENSSL_EXPORT int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa);
+OPENSSL_EXPORT int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx,
+ const uint8_t *d, long len);
+OPENSSL_EXPORT int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey);
+OPENSSL_EXPORT int SSL_CTX_use_PrivateKey_ASN1(int pk, SSL_CTX *ctx,
+ const uint8_t *d, long len);
+OPENSSL_EXPORT int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x);
+OPENSSL_EXPORT int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len,
+ const uint8_t *d);
+
+OPENSSL_EXPORT void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx,
+ pem_password_cb *cb);
+OPENSSL_EXPORT void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx,
+ void *u);
+
+OPENSSL_EXPORT int SSL_CTX_check_private_key(const SSL_CTX *ctx);
+OPENSSL_EXPORT int SSL_check_private_key(const SSL *ctx);
+
+OPENSSL_EXPORT int SSL_CTX_set_session_id_context(SSL_CTX *ctx,
+ const uint8_t *sid_ctx,
+ unsigned int sid_ctx_len);
+
+OPENSSL_EXPORT SSL *SSL_new(SSL_CTX *ctx);
+OPENSSL_EXPORT int SSL_set_session_id_context(SSL *ssl, const uint8_t *sid_ctx,
+ unsigned int sid_ctx_len);
+
+OPENSSL_EXPORT int SSL_CTX_set_purpose(SSL_CTX *s, int purpose);
+OPENSSL_EXPORT int SSL_set_purpose(SSL *s, int purpose);
+OPENSSL_EXPORT int SSL_CTX_set_trust(SSL_CTX *s, int trust);
+OPENSSL_EXPORT int SSL_set_trust(SSL *s, int trust);
+
+OPENSSL_EXPORT int SSL_CTX_set1_param(SSL_CTX *ctx, X509_VERIFY_PARAM *vpm);
+OPENSSL_EXPORT int SSL_set1_param(SSL *ssl, X509_VERIFY_PARAM *vpm);
+
+OPENSSL_EXPORT X509_VERIFY_PARAM *SSL_CTX_get0_param(SSL_CTX *ctx);
+OPENSSL_EXPORT X509_VERIFY_PARAM *SSL_get0_param(SSL *ssl);
+
+OPENSSL_EXPORT void SSL_certs_clear(SSL *s);
+OPENSSL_EXPORT void SSL_free(SSL *ssl);
+OPENSSL_EXPORT int SSL_accept(SSL *ssl);
+OPENSSL_EXPORT int SSL_connect(SSL *ssl);
+OPENSSL_EXPORT int SSL_read(SSL *ssl, void *buf, int num);
+OPENSSL_EXPORT int SSL_peek(SSL *ssl, void *buf, int num);
+OPENSSL_EXPORT int SSL_write(SSL *ssl, const void *buf, int num);
+OPENSSL_EXPORT long SSL_ctrl(SSL *ssl, int cmd, long larg, void *parg);
+OPENSSL_EXPORT long SSL_callback_ctrl(SSL *, int, void (*)(void));
+OPENSSL_EXPORT long SSL_CTX_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg);
+OPENSSL_EXPORT long SSL_CTX_callback_ctrl(SSL_CTX *, int, void (*)(void));
+
+OPENSSL_EXPORT int SSL_get_error(const SSL *s, int ret_code);
+/* SSL_get_version returns a string describing the TLS version used by |s|. For
+ * example, "TLSv1.2" or "SSLv3". */
+OPENSSL_EXPORT const char *SSL_get_version(const SSL *s);
+/* SSL_SESSION_get_version returns a string describing the TLS version used by
+ * |sess|. For example, "TLSv1.2" or "SSLv3". */
+OPENSSL_EXPORT const char *SSL_SESSION_get_version(const SSL_SESSION *sess);
+
+OPENSSL_EXPORT int SSL_CIPHER_is_AES(const SSL_CIPHER *c);
+OPENSSL_EXPORT int SSL_CIPHER_has_MD5_HMAC(const SSL_CIPHER *c);
+OPENSSL_EXPORT int SSL_CIPHER_is_AESGCM(const SSL_CIPHER *c);
+OPENSSL_EXPORT int SSL_CIPHER_is_CHACHA20POLY1305(const SSL_CIPHER *c);
+
+/* TLS_method is the SSL_METHOD used for TLS (and SSLv3) connections. */
+OPENSSL_EXPORT const SSL_METHOD *TLS_method(void);
+
+/* DTLS_method is the SSL_METHOD used for DTLS connections. */
+OPENSSL_EXPORT const SSL_METHOD *DTLS_method(void);
+
+
+/* Deprecated methods. */
+
+/* SSLv23_method calls TLS_method. */
+OPENSSL_EXPORT const SSL_METHOD *SSLv23_method(void);
+
+/* Version-specific methods behave exactly like TLS_method and DTLS_method
+ * except they also call SSL_CTX_set_min_version and SSL_CTX_set_max_version to
+ * lock connections to that protocol version. */
+OPENSSL_EXPORT const SSL_METHOD *SSLv3_method(void);
+OPENSSL_EXPORT const SSL_METHOD *TLSv1_method(void);
+OPENSSL_EXPORT const SSL_METHOD *TLSv1_1_method(void);
+OPENSSL_EXPORT const SSL_METHOD *TLSv1_2_method(void);
+OPENSSL_EXPORT const SSL_METHOD *DTLSv1_method(void);
+OPENSSL_EXPORT const SSL_METHOD *DTLSv1_2_method(void);
+
+/* Client- and server-specific methods call their corresponding generic
+ * methods. */
+OPENSSL_EXPORT const SSL_METHOD *SSLv23_server_method(void);
+OPENSSL_EXPORT const SSL_METHOD *SSLv23_client_method(void);
+OPENSSL_EXPORT const SSL_METHOD *SSLv3_server_method(void);
+OPENSSL_EXPORT const SSL_METHOD *SSLv3_client_method(void);
+OPENSSL_EXPORT const SSL_METHOD *TLSv1_server_method(void);
+OPENSSL_EXPORT const SSL_METHOD *TLSv1_client_method(void);
+OPENSSL_EXPORT const SSL_METHOD *TLSv1_1_server_method(void);
+OPENSSL_EXPORT const SSL_METHOD *TLSv1_1_client_method(void);
+OPENSSL_EXPORT const SSL_METHOD *TLSv1_2_server_method(void);
+OPENSSL_EXPORT const SSL_METHOD *TLSv1_2_client_method(void);
+OPENSSL_EXPORT const SSL_METHOD *DTLS_server_method(void);
+OPENSSL_EXPORT const SSL_METHOD *DTLS_client_method(void);
+OPENSSL_EXPORT const SSL_METHOD *DTLSv1_server_method(void);
+OPENSSL_EXPORT const SSL_METHOD *DTLSv1_client_method(void);
+OPENSSL_EXPORT const SSL_METHOD *DTLSv1_2_server_method(void);
+OPENSSL_EXPORT const SSL_METHOD *DTLSv1_2_client_method(void);
+
+
+OPENSSL_EXPORT STACK_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL *s);
+
+OPENSSL_EXPORT int SSL_do_handshake(SSL *s);
+OPENSSL_EXPORT int SSL_renegotiate(SSL *s);
+OPENSSL_EXPORT int SSL_renegotiate_abbreviated(SSL *s);
+OPENSSL_EXPORT int SSL_renegotiate_pending(SSL *s);
+OPENSSL_EXPORT int SSL_shutdown(SSL *s);
+
+OPENSSL_EXPORT const char *SSL_alert_type_string_long(int value);
+OPENSSL_EXPORT const char *SSL_alert_type_string(int value);
+OPENSSL_EXPORT const char *SSL_alert_desc_string_long(int value);
+OPENSSL_EXPORT const char *SSL_alert_desc_string(int value);
+
+OPENSSL_EXPORT void SSL_set_client_CA_list(SSL *s,
+ STACK_OF(X509_NAME) *name_list);
+OPENSSL_EXPORT void SSL_CTX_set_client_CA_list(SSL_CTX *ctx,
+ STACK_OF(X509_NAME) *name_list);
+OPENSSL_EXPORT STACK_OF(X509_NAME) *SSL_get_client_CA_list(const SSL *s);
+OPENSSL_EXPORT STACK_OF(X509_NAME) *
+ SSL_CTX_get_client_CA_list(const SSL_CTX *s);
+OPENSSL_EXPORT int SSL_add_client_CA(SSL *ssl, X509 *x);
+OPENSSL_EXPORT int SSL_CTX_add_client_CA(SSL_CTX *ctx, X509 *x);
+
+OPENSSL_EXPORT void SSL_set_connect_state(SSL *s);
+OPENSSL_EXPORT void SSL_set_accept_state(SSL *s);
+
+OPENSSL_EXPORT long SSL_get_default_timeout(const SSL *s);
+
+/* SSL_library_init initializes the crypto and SSL libraries, loads their error
+ * strings, and returns one. */
+OPENSSL_EXPORT int SSL_library_init(void);
+
+OPENSSL_EXPORT const char *SSL_CIPHER_description(const SSL_CIPHER *, char *buf,
+ int size);
+OPENSSL_EXPORT STACK_OF(X509_NAME) *SSL_dup_CA_list(STACK_OF(X509_NAME) *sk);
+
+OPENSSL_EXPORT X509 *SSL_get_certificate(const SSL *ssl);
+OPENSSL_EXPORT /* EVP_PKEY */ struct evp_pkey_st *SSL_get_privatekey(
+ const SSL *ssl);
+
+OPENSSL_EXPORT X509 *SSL_CTX_get0_certificate(const SSL_CTX *ctx);
+OPENSSL_EXPORT EVP_PKEY *SSL_CTX_get0_privatekey(const SSL_CTX *ctx);
+
+OPENSSL_EXPORT void SSL_CTX_set_quiet_shutdown(SSL_CTX *ctx, int mode);
+OPENSSL_EXPORT int SSL_CTX_get_quiet_shutdown(const SSL_CTX *ctx);
+OPENSSL_EXPORT void SSL_set_quiet_shutdown(SSL *ssl, int mode);
+OPENSSL_EXPORT int SSL_get_quiet_shutdown(const SSL *ssl);
+OPENSSL_EXPORT void SSL_set_shutdown(SSL *ssl, int mode);
+OPENSSL_EXPORT int SSL_get_shutdown(const SSL *ssl);
+OPENSSL_EXPORT int SSL_version(const SSL *ssl);
+OPENSSL_EXPORT int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx);
+OPENSSL_EXPORT int SSL_CTX_load_verify_locations(SSL_CTX *ctx,
+ const char *CAfile,
+ const char *CApath);
+#define SSL_get0_session SSL_get_session /* just peek at pointer */
+OPENSSL_EXPORT SSL_SESSION *SSL_get_session(const SSL *ssl);
+OPENSSL_EXPORT SSL_SESSION *SSL_get1_session(
+ SSL *ssl); /* obtain a reference count */
+OPENSSL_EXPORT SSL_CTX *SSL_get_SSL_CTX(const SSL *ssl);
+OPENSSL_EXPORT SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX *ctx);
+OPENSSL_EXPORT void SSL_set_info_callback(SSL *ssl,
+ void (*cb)(const SSL *ssl, int type,
+ int val));
+OPENSSL_EXPORT void (*SSL_get_info_callback(const SSL *ssl))(const SSL *ssl,
+ int type, int val);
+OPENSSL_EXPORT int SSL_state(const SSL *ssl);
+OPENSSL_EXPORT void SSL_set_state(SSL *ssl, int state);
+
+OPENSSL_EXPORT void SSL_set_verify_result(SSL *ssl, long v);
+OPENSSL_EXPORT long SSL_get_verify_result(const SSL *ssl);
+
+OPENSSL_EXPORT int SSL_set_ex_data(SSL *ssl, int idx, void *data);
+OPENSSL_EXPORT void *SSL_get_ex_data(const SSL *ssl, int idx);
+OPENSSL_EXPORT 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);
+
+OPENSSL_EXPORT int SSL_SESSION_set_ex_data(SSL_SESSION *ss, int idx,
+ void *data);
+OPENSSL_EXPORT void *SSL_SESSION_get_ex_data(const SSL_SESSION *ss, int idx);
+OPENSSL_EXPORT 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);
+
+OPENSSL_EXPORT int SSL_CTX_set_ex_data(SSL_CTX *ssl, int idx, void *data);
+OPENSSL_EXPORT void *SSL_CTX_get_ex_data(const SSL_CTX *ssl, int idx);
+OPENSSL_EXPORT 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);
+
+OPENSSL_EXPORT 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 */
+OPENSSL_EXPORT void SSL_CTX_set_tmp_rsa_callback(
+ SSL_CTX *ctx, RSA *(*cb)(SSL *ssl, int is_export, int keylength));
+
+OPENSSL_EXPORT void SSL_set_tmp_rsa_callback(SSL *ssl,
+ RSA *(*cb)(SSL *ssl, int is_export,
+ int keylength));
+OPENSSL_EXPORT void SSL_CTX_set_tmp_dh_callback(
+ SSL_CTX *ctx, DH *(*dh)(SSL *ssl, int is_export, int keylength));
+OPENSSL_EXPORT void SSL_set_tmp_dh_callback(SSL *ssl,
+ DH *(*dh)(SSL *ssl, int is_export,
+ int keylength));
+OPENSSL_EXPORT void SSL_CTX_set_tmp_ecdh_callback(
+ SSL_CTX *ctx, EC_KEY *(*ecdh)(SSL *ssl, int is_export, int keylength));
+OPENSSL_EXPORT void SSL_set_tmp_ecdh_callback(
+ SSL *ssl, EC_KEY *(*ecdh)(SSL *ssl, int is_export, int keylength));
+
+OPENSSL_EXPORT const void *SSL_get_current_compression(SSL *s);
+OPENSSL_EXPORT const void *SSL_get_current_expansion(SSL *s);
+OPENSSL_EXPORT const char *SSL_COMP_get_name(const void *comp);
+OPENSSL_EXPORT void *SSL_COMP_get_compression_methods(void);
+OPENSSL_EXPORT int SSL_COMP_add_compression_method(int id, void *cm);
+
+OPENSSL_EXPORT int SSL_cache_hit(SSL *s);
+OPENSSL_EXPORT int SSL_is_server(SSL *s);
+
+/* SSL_get_structure_sizes returns the sizes of the SSL, SSL_CTX and
+ * SSL_SESSION structures so that a test can ensure that outside code agrees on
+ * these values. */
+OPENSSL_EXPORT void SSL_get_structure_sizes(size_t *ssl_size,
+ size_t *ssl_ctx_size,
+ size_t *ssl_session_size);
+
+OPENSSL_EXPORT void ERR_load_SSL_strings(void);
+
+
+/* Android compatibility section.
+ *
+ * These functions are declared, temporarily, for Android because
+ * wpa_supplicant will take a little time to sync with upstream. Outside of
+ * Android they'll have no definition. */
+
+#define SSL_F_SSL_SET_SESSION_TICKET_EXT doesnt_exist
+
+OPENSSL_EXPORT int SSL_set_session_ticket_ext(SSL *s, void *ext_data,
+ int ext_len);
+OPENSSL_EXPORT int SSL_set_session_secret_cb(SSL *s, void *cb, void *arg);
+OPENSSL_EXPORT int SSL_set_session_ticket_ext_cb(SSL *s, void *cb, void *arg);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script make_errors.go. Any
+ * changes made after this point may be overwritten when the script is next run.
+ */
+#define SSL_F_SSL_use_PrivateKey_file 100
+#define SSL_F_dtls1_write_app_data_bytes 101
+#define SSL_F_ssl_cipher_process_rulestr 102
+#define SSL_F_SSL_set_session_id_context 103
+#define SSL_F_SSL_read 104
+#define SSL_F_ssl_cert_new 105
+#define SSL_F_dtls1_heartbeat 106
+#define SSL_F_ssl3_digest_cached_records 107
+#define SSL_F_SSL_set_wfd 108
+#define SSL_F_ssl_set_pkey 110
+#define SSL_F_SSL_CTX_use_certificate 111
+#define SSL_F_dtls1_read_bytes 112
+#define SSL_F_ssl23_write 113
+#define SSL_F_ssl3_check_client_hello 114
+#define SSL_F_SSL_use_certificate_ASN1 115
+#define SSL_F_ssl_verify_cert_chain 116
+#define SSL_F_ssl_parse_serverhello_renegotiate_ext 117
+#define SSL_F_ssl_undefined_const_function 118
+#define SSL_F_ssl3_get_server_certificate 119
+#define SSL_F_tls1_get_server_supplemental_data 120
+#define SSL_F_dtls1_buffer_record 121
+#define SSL_F_ssl_prepare_clienthello_tlsext 122
+#define SSL_F_ssl3_get_server_hello 123
+#define SSL_F_ssl3_send_client_key_exchange 124
+#define SSL_F_ssl3_write_bytes 125
+#define SSL_F_SSL_use_RSAPrivateKey_file 126
+#define SSL_F_ssl_bad_method 127
+#define SSL_F_ssl3_connect 128
+#define SSL_F_dtls1_connect 129
+#define SSL_F_SSL_use_RSAPrivateKey 130
+#define SSL_F_tls1_prf 131
+#define SSL_F_ssl_bytes_to_cipher_list 132
+#define SSL_F_ssl3_do_change_cipher_spec 133
+#define SSL_F_SSL_SESSION_set1_id_context 134
+#define SSL_F_ssl_add_serverhello_tlsext 135
+#define SSL_F_read_authz 136
+#define SSL_F_ssl3_get_client_hello 137
+#define SSL_F_ssl3_get_certificate_request 138
+#define SSL_F_authz_find_data 139
+#define SSL_F_ssl_add_cert_to_buf 140
+#define SSL_F_ssl_add_serverhello_renegotiate_ext 141
+#define SSL_F_ssl3_get_message 142
+#define SSL_F_ssl_check_srvr_ecc_cert_and_alg 143
+#define SSL_F_ssl_parse_clienthello_tlsext 144
+#define SSL_F_SSL_add_file_cert_subjects_to_stack 145
+#define SSL_F_ssl3_ctx_ctrl 146
+#define SSL_F_ssl3_get_record 147
+#define SSL_F_SSL_CTX_use_RSAPrivateKey 148
+#define SSL_F_SSL_use_certificate_file 149
+#define SSL_F_SSL_load_client_CA_file 151
+#define SSL_F_dtls1_preprocess_fragment 152
+#define SSL_F_SSL_CTX_check_private_key 153
+#define SSL_F_ssl3_get_cert_status 154
+#define SSL_F_printf 155
+#define SSL_F_SSL_CTX_new 156
+#define SSL_F_ssl23_accept 157
+#define SSL_F_SSL_use_authz 158
+#define SSL_F_ssl_undefined_function 159
+#define SSL_F_dtls1_send_hello_verify_request 160
+#define SSL_F_ssl_build_cert_chain 161
+#define SSL_F_SSL_SESSION_print_fp 162
+#define SSL_F_tls1_change_cipher_state 163
+#define SSL_F_tls12_check_peer_sigalg 164
+#define SSL_F_ssl_sess_cert_new 165
+#define SSL_F_ssl3_read_bytes 166
+#define SSL_F_dtls1_get_hello_verify 167
+#define SSL_F_tls1_cert_verify_mac 168
+#define SSL_F_ssl23_client_hello 169
+#define SSL_F_SSL_shutdown 170
+#define SSL_F_ssl_init_wbio_buffer 171
+#define SSL_F_SSL_use_certificate 172
+#define SSL_F_SSL_CTX_use_RSAPrivateKey_ASN1 173
+#define SSL_F_ssl_set_authz 174
+#define SSL_F_ssl23_peek 175
+#define SSL_F_SSL_use_psk_identity_hint 176
+#define SSL_F_ssl3_get_cert_verify 177
+#define SSL_F_ssl_ctx_make_profiles 178
+#define SSL_F_ssl_add_clienthello_use_srtp_ext 179
+#define SSL_F_ssl3_get_client_key_exchange 180
+#define SSL_F_do_ssl3_write 181
+#define SSL_F_ssl3_handshake_mac 182
+#define SSL_F_tls1_setup_key_block 183
+#define SSL_F_SSL_set_fd 184
+#define SSL_F_SSL_check_private_key 185
+#define SSL_F_ssl3_send_cert_verify 186
+#define SSL_F_ssl3_write_pending 187
+#define SSL_F_ssl_cert_inst 188
+#define SSL_F_ssl3_change_cipher_state 189
+#define SSL_F_ssl23_get_server_hello 190
+#define SSL_F_SSL_write 191
+#define SSL_F_ssl_get_sign_pkey 192
+#define SSL_F_ssl_set_cert 193
+#define SSL_F_SSL_CTX_use_RSAPrivateKey_file 194
+#define SSL_F_SSL_CTX_use_authz 195
+#define SSL_F_ssl_get_new_session 196
+#define SSL_F_SSL_set_session_ticket_ext 197
+#define SSL_F_ssl_add_clienthello_renegotiate_ext 198
+#define SSL_F_ssl3_send_server_key_exchange 199
+#define SSL_F_fprintf 200
+#define SSL_F_ssl3_get_new_session_ticket 201
+#define SSL_F_SSL_CTX_use_certificate_ASN1 202
+#define SSL_F_ssl_add_cert_chain 203
+#define SSL_F_ssl_create_cipher_list 204
+#define SSL_F_ssl3_callback_ctrl 205
+#define SSL_F_SSL_CTX_set_cipher_list 206
+#define SSL_F_ssl3_send_certificate_request 207
+#define SSL_F_SSL_use_PrivateKey_ASN1 208
+#define SSL_F_SSL_CTX_use_certificate_chain_file 209
+#define SSL_F_SSL_SESSION_new 210
+#define SSL_F_check_suiteb_cipher_list 211
+#define SSL_F_ssl_scan_clienthello_tlsext 212
+#define SSL_F_ssl3_send_client_hello 213
+#define SSL_F_SSL_use_RSAPrivateKey_ASN1 214
+#define SSL_F_ssl3_ctrl 215
+#define SSL_F_ssl3_setup_write_buffer 216
+#define SSL_F_ssl_parse_serverhello_use_srtp_ext 217
+#define SSL_F_ssl3_get_server_key_exchange 218
+#define SSL_F_ssl3_send_server_hello 219
+#define SSL_F_SSL_add_dir_cert_subjects_to_stack 220
+#define SSL_F_ssl_check_serverhello_tlsext 221
+#define SSL_F_ssl3_get_server_done 222
+#define SSL_F_ssl3_check_cert_and_algorithm 223
+#define SSL_F_do_dtls1_write 224
+#define SSL_F_dtls1_check_timeout_num 225
+#define SSL_F_tls1_export_keying_material 226
+#define SSL_F_SSL_CTX_set_session_id_context 227
+#define SSL_F_SSL_set_rfd 228
+#define SSL_F_ssl3_send_client_certificate 229
+#define SSL_F_ssl_cert_dup 230
+#define SSL_F_dtls1_process_record 231
+#define SSL_F_ssl_new 232
+#define SSL_F_ssl_get_server_cert_index 233
+#define SSL_F_tls1_send_server_supplemental_data 234
+#define SSL_F_D2I_SSL_SESSION 235
+#define SSL_F_ssl_cipher_strength_sort 236
+#define SSL_F_dtls1_get_message 237
+#define SSL_F_ssl23_connect 238
+#define SSL_F_tls1_heartbeat 239
+#define SSL_F_ssl3_read_n 240
+#define SSL_F_ssl_get_prev_session 241
+#define SSL_F_ssl_parse_clienthello_renegotiate_ext 242
+#define SSL_F_ssl3_setup_read_buffer 243
+#define SSL_F_SSL_CTX_set_ssl_version 244
+#define SSL_F_SSL_peek 245
+#define SSL_F_ssl3_send_server_certificate 246
+#define SSL_F_SSL_do_handshake 247
+#define SSL_F_ssl_undefined_void_function 248
+#define SSL_F_ssl_add_serverhello_use_srtp_ext 249
+#define SSL_F_fclose 250
+#define SSL_F_SSL_use_PrivateKey 251
+#define SSL_F_SSL_CTX_use_certificate_file 252
+#define SSL_F_SSL_CTX_use_PrivateKey 253
+#define SSL_F_SSL_set_session 254
+#define SSL_F_SSL_CTX_use_psk_identity_hint 255
+#define SSL_F_ssl_scan_serverhello_tlsext 256
+#define SSL_F_ssl23_read 257
+#define SSL_F_ssl_parse_clienthello_use_srtp_ext 258
+#define SSL_F_ssl3_accept 259
+#define SSL_F_ssl3_get_client_certificate 260
+#define SSL_F_SSL_CTX_use_PrivateKey_ASN1 261
+#define SSL_F_dtls1_get_message_fragment 262
+#define SSL_F_SSL_clear 263
+#define SSL_F_dtls1_accept 264
+#define SSL_F_ssl3_get_next_proto 265
+#define SSL_F_SSL_set_cipher_list 266
+#define SSL_F_ssl_add_clienthello_tlsext 267
+#define SSL_F_ssl23_get_client_hello 268
+#define SSL_F_SSL_CTX_use_PrivateKey_file 269
+#define SSL_F_ssl3_get_finished 270
+#define SSL_F_ssl3_generate_key_block 271
+#define SSL_F_ssl3_setup_key_block 272
+#define SSL_F_SSL_new 273
+#define SSL_F_ssl_parse_serverhello_tlsext 274
+#define SSL_F_ssl3_get_channel_id 275
+#define SSL_F_ssl3_send_channel_id 276
+#define SSL_F_SSL_CTX_set_cipher_list_tls11 277
+#define SSL_F_tls1_change_cipher_state_cipher 278
+#define SSL_F_tls1_change_cipher_state_aead 279
+#define SSL_F_tls1_aead_ctx_init 280
+#define SSL_F_tls1_check_duplicate_extensions 281
+#define SSL_F_ssl3_expect_change_cipher_spec 282
+#define SSL_F_ssl23_get_v2_client_hello 283
+#define SSL_F_ssl3_cert_verify_hash 284
+#define SSL_F_ssl_ctx_log_rsa_client_key_exchange 285
+#define SSL_F_ssl_ctx_log_master_secret 286
+#define SSL_F_d2i_SSL_SESSION 287
+#define SSL_F_i2d_SSL_SESSION 288
+#define SSL_F_d2i_SSL_SESSION_get_octet_string 289
+#define SSL_F_d2i_SSL_SESSION_get_string 290
+#define SSL_F_ssl3_send_new_session_ticket 291
+#define SSL_F_SSL_SESSION_to_bytes_full 292
+#define SSL_F_SSL_accept 293
+#define SSL_F_SSL_connect 294
+#define SSL_F_ssl3_get_v2_client_hello 295
+#define SSL_F_ssl3_get_initial_bytes 296
+#define SSL_F_tls1_enc 297
+#define SSL_F_ssl3_prf 298
+#define SSL_F_dtls1_do_write 299
+#define SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS 100
+#define SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC 101
+#define SSL_R_INVALID_NULL_CMD_NAME 102
+#define SSL_R_BAD_RSA_DECRYPT 103
+#define SSL_R_NO_SHARED_CIPHER 104
+#define SSL_R_BAD_PSK_IDENTITY_HINT_LENGTH 105
+#define SSL_R_SSL_HANDSHAKE_FAILURE 106
+#define SSL_R_INVALID_TICKET_KEYS_LENGTH 107
+#define SSL_R_PEER_ERROR 108
+#define SSL_R_ECC_CERT_NOT_FOR_SIGNING 109
+#define SSL_R_INCONSISTENT_COMPRESSION 110
+#define SSL_R_BAD_HELLO_REQUEST 111
+#define SSL_R_NULL_SSL_METHOD_PASSED 112
+#define SSL_R_X509_VERIFICATION_SETUP_PROBLEMS 113
+#define SSL_R_BAD_ECDSA_SIGNATURE 114
+#define SSL_R_GOT_NEXT_PROTO_WITHOUT_EXTENSION 115
+#define SSL_R_BAD_DH_PUB_KEY_LENGTH 116
+#define SSL_R_COMPRESSED_LENGTH_TOO_LONG 117
+#define SSL_R_APP_DATA_IN_HANDSHAKE 118
+#define SSL_R_NO_PEM_EXTENSIONS 119
+#define SSL_R_BAD_SRP_B_LENGTH 120
+#define SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG 121
+#define SSL_R_UNABLE_TO_DECODE_DH_CERTS 122
+#define SSL_R_MISSING_SRP_PARAM 123
+#define SSL_R_MISSING_RSA_SIGNING_CERT 124
+#define SSL_R_MISSING_DSA_SIGNING_CERT 125
+#define SSL_R_ONLY_TLS_1_2_ALLOWED_IN_SUITEB_MODE 126
+#define SSL_R_UNEXPECTED_RECORD 127
+#define SSL_R_BAD_DIGEST_LENGTH 128
+#define SSL_R_READ_TIMEOUT_EXPIRED 129
+#define SSL_R_KRB5_C_GET_CRED 130
+#define SSL_R_NULL_SSL_CTX 131
+#define SSL_R_ERROR_GENERATING_TMP_RSA_KEY 134
+#define SSL_R_SSL3_SESSION_ID_TOO_LONG 135
+#define SSL_R_BAD_DATA_RETURNED_BY_CALLBACK 136
+#define SSL_R_REUSE_CERT_LENGTH_NOT_ZERO 137
+#define SSL_R_COOKIE_MISMATCH 139
+#define SSL_R_UNINITIALIZED 140
+#define SSL_R_BAD_CHANGE_CIPHER_SPEC 141
+#define SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES 142
+#define SSL_R_BAD_SRP_G_LENGTH 143
+#define SSL_R_NO_CERTIFICATE_ASSIGNED 144
+#define SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS 145
+#define SSL_R_PEM_NAME_TOO_SHORT 146
+#define SSL_R_PROTOCOL_IS_SHUTDOWN 148
+#define SSL_R_UNABLE_TO_FIND_SSL_METHOD 149
+#define SSL_R_WRONG_MESSAGE_TYPE 150
+#define SSL_R_BAD_RSA_MODULUS_LENGTH 151
+#define SSL_R_PUBLIC_KEY_IS_NOT_RSA 152
+#define SSL_R_COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE 153
+#define SSL_R_NO_CLIENT_CERT_RECEIVED 154
+#define SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST 155
+#define SSL_R_CERT_LENGTH_MISMATCH 156
+#define SSL_R_MISSING_EXPORT_TMP_DH_KEY 157
+#define SSL_R_DUPLICATE_COMPRESSION_ID 158
+#define SSL_R_SSL3_EXT_INVALID_ECPOINTFORMAT 159
+#define SSL_R_REUSE_CIPHER_LIST_NOT_ZERO 160
+#define SSL_R_DATA_LENGTH_TOO_LONG 161
+#define SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER 162
+#define SSL_R_WRONG_SIGNATURE_LENGTH 163
+#define SSL_R_SSL2_CONNECTION_ID_TOO_LONG 164
+#define SSL_R_WRONG_VERSION_NUMBER 165
+#define SSL_R_RECORD_TOO_LARGE 166
+#define SSL_R_BIO_NOT_SET 167
+#define SSL_R_SRTP_COULD_NOT_ALLOCATE_PROFILES 168
+#define SSL_R_UNKNOWN_PKEY_TYPE 170
+#define SSL_R_CIPHER_CODE_WRONG_LENGTH 171
+#define SSL_R_SSL_SESSION_ID_CONFLICT 172
+#define SSL_R_INVALID_COMMAND 173
+#define SSL_R_NO_PROTOCOLS_AVAILABLE 174
+#define SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST 175
+#define SSL_R_LIBRARY_BUG 176
+#define SSL_R_UNSUPPORTED_CIPHER 177
+#define SSL_R_REUSE_CERT_TYPE_NOT_ZERO 178
+#define SSL_R_WRONG_SIGNATURE_TYPE 179
+#define SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST 180
+#define SSL_R_PSK_NO_SERVER_CB 181
+#define SSL_R_BLOCK_CIPHER_PAD_IS_WRONG 182
+#define SSL_R_INVALID_TRUST 183
+#define SSL_R_PARSE_TLSEXT 184
+#define SSL_R_NO_SRTP_PROFILES 185
+#define SSL_R_UNSUPPORTED_ELLIPTIC_CURVE 186
+#define SSL_R_UNKNOWN_STATE 187
+#define SSL_R_UNKNOWN_CERTIFICATE_TYPE 188
+#define SSL_R_WRONG_CIPHER_RETURNED 189
+#define SSL_R_BAD_DH_G_LENGTH 190
+#define SSL_R_BAD_ALERT_RECORD 191
+#define SSL_R_CIPHER_TABLE_SRC_ERROR 192
+#define SSL_R_UNKNOWN_REMOTE_ERROR_TYPE 194
+#define SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE 195
+#define SSL_R_MESSAGE_TOO_LONG 196
+#define SSL_R_BAD_RSA_SIGNATURE 197
+#define SSL_R_X509_LIB 198
+#define SSL_R_BAD_SRP_N_LENGTH 199
+#define SSL_R_BAD_SSL_SESSION_ID_LENGTH 200
+#define SSL_R_UNKNOWN_CIPHER_TYPE 201
+#define SSL_R_BAD_DH_P_LENGTH 202
+#define SSL_R_MISSING_DH_RSA_CERT 203
+#define SSL_R_NO_METHOD_SPECIFIED 204
+#define SSL_R_EMPTY_SRTP_PROTECTION_PROFILE_LIST 205
+#define SSL_R_MULTIPLE_SGC_RESTARTS 206
+#define SSL_R_UNABLE_TO_DECODE_ECDH_CERTS 207
+#define SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT 208
+#define SSL_R_SSL3_EXT_INVALID_SERVERNAME 209
+#define SSL_R_BAD_SRP_S_LENGTH 210
+#define SSL_R_MISSING_TMP_RSA_KEY 211
+#define SSL_R_PSK_NO_CLIENT_CB 212
+#define SSL_R_PEM_NAME_BAD_PREFIX 213
+#define SSL_R_BAD_CHECKSUM 214
+#define SSL_R_NO_CIPHER_MATCH 216
+#define SSL_R_MISSING_TMP_DH_KEY 217
+#define SSL_R_UNSUPPORTED_STATUS_TYPE 218
+#define SSL_R_UNKNOWN_AUTHZ_DATA_TYPE 219
+#define SSL_R_CONNECTION_TYPE_NOT_SET 220
+#define SSL_R_MISSING_DH_KEY 221
+#define SSL_R_CHANNEL_ID_NOT_P256 222
+#define SSL_R_UNKNOWN_SUPPLEMENTAL_DATA_TYPE 223
+#define SSL_R_UNKNOWN_PROTOCOL 224
+#define SSL_R_DATA_BETWEEN_CCS_AND_FINISHED 225
+#define SSL_R_KRB5_S_TKT_SKEW 226
+#define SSL_R_PUBLIC_KEY_NOT_RSA 227
+#define SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING 228
+#define SSL_R_GOST_NOT_SUPPORTED 229
+#define SSL_R_KRB5_C_CC_PRINC 230
+#define SSL_R_INVALID_PURPOSE 234
+#define SSL_R_KRB5_C_MK_REQ 235
+#define SSL_R_BAD_SRTP_MKI_VALUE 237
+#define SSL_R_EVP_DIGESTSIGNINIT_FAILED 238
+#define SSL_R_DIGEST_CHECK_FAILED 239
+#define SSL_R_BAD_SRP_A_LENGTH 240
+#define SSL_R_SERVERHELLO_TLSEXT 241
+#define SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG 242
+#define SSL_R_NO_CIPHERS_AVAILABLE 243
+#define SSL_R_COMPRESSION_FAILURE 244
+#define SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION 245
+#define SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED 246
+#define SSL_R_BAD_RSA_ENCRYPT 247
+#define SSL_R_EXCESSIVE_MESSAGE_SIZE 248
+#define SSL_R_INVALID_COMPRESSION_ALGORITHM 249
+#define SSL_R_SHORT_READ 250
+#define SSL_R_CA_DN_LENGTH_MISMATCH 252
+#define SSL_R_BAD_ECC_CERT 253
+#define SSL_R_NON_SSLV2_INITIAL_PACKET 254
+#define SSL_R_SSL_SESSION_ID_IS_DIFFERENT 255
+#define SSL_R_MISSING_TMP_RSA_PKEY 256
+#define SSL_R_BN_LIB 257
+#define SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE 258
+#define SSL_R_MISSING_RSA_ENCRYPTING_CERT 259
+#define SSL_R_NO_RENEGOTIATION 260
+#define SSL_R_NO_COMPRESSION_SPECIFIED 261
+#define SSL_R_WRONG_CERTIFICATE_TYPE 262
+#define SSL_R_CHANNEL_ID_SIGNATURE_INVALID 264
+#define SSL_R_READ_BIO_NOT_SET 265
+#define SSL_R_SSL23_DOING_SESSION_ID_REUSE 266
+#define SSL_R_RENEGOTIATE_EXT_TOO_LONG 267
+#define SSL_R_INVALID_CHALLENGE_LENGTH 268
+#define SSL_R_LIBRARY_HAS_NO_CIPHERS 270
+#define SSL_R_WRONG_CURVE 271
+#define SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED 272
+#define SSL_R_ECC_CERT_NOT_FOR_KEY_AGREEMENT 275
+#define SSL_R_MISSING_RSA_CERTIFICATE 276
+#define SSL_R_NO_P256_SUPPORT 277
+#define SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM 278
+#define SSL_R_INVALID_SERVERINFO_DATA 279
+#define SSL_R_GOT_CHANNEL_ID_BEFORE_A_CCS 280
+#define SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG 281
+#define SSL_R_KRB5_S_BAD_TICKET 282
+#define SSL_R_EVP_DIGESTSIGNFINAL_FAILED 283
+#define SSL_R_PACKET_LENGTH_TOO_LONG 284
+#define SSL_R_BAD_STATE 285
+#define SSL_R_USE_SRTP_NOT_NEGOTIATED 286
+#define SSL_R_BAD_RSA_E_LENGTH 287
+#define SSL_R_ILLEGAL_PADDING 288
+#define SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE 289
+#define SSL_R_BAD_VALUE 290
+#define SSL_R_ECC_CERT_SHOULD_HAVE_RSA_SIGNATURE 291
+#define SSL_R_COMPRESSION_DISABLED 292
+#define SSL_R_BAD_DECOMPRESSION 293
+#define SSL_R_CHALLENGE_IS_DIFFERENT 294
+#define SSL_R_NO_CLIENT_CERT_METHOD 295
+#define SSL_R_SRTP_PROTECTION_PROFILE_LIST_TOO_LONG 296
+#define SSL_R_INVALID_MESSAGE 297
+#define SSL_R_HTTPS_PROXY_REQUEST 298
+#define SSL_R_AUTHZ_DATA_TOO_LARGE 299
+#define SSL_R_KRB5_S_TKT_EXPIRED 300
+#define SSL_R_NO_CERTIFICATE_SPECIFIED 301
+#define SSL_R_ECC_CERT_SHOULD_HAVE_SHA1_SIGNATURE 302
+#define SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST 303
+#define SSL_R_INVALID_STATUS_RESPONSE 304
+#define SSL_R_TLS_ILLEGAL_EXPORTER_LABEL 305
+#define SSL_R_ONLY_DTLS_1_2_ALLOWED_IN_SUITEB_MODE 306
+#define SSL_R_MISSING_TMP_ECDH_KEY 307
+#define SSL_R_CERTIFICATE_VERIFY_FAILED 308
+#define SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER 309
+#define SSL_R_RENEGOTIATION_ENCODING_ERR 310
+#define SSL_R_NO_PRIVATEKEY 311
+#define SSL_R_READ_WRONG_PACKET_TYPE 313
+#define SSL_R_SSL3_SESSION_ID_TOO_SHORT 314
+#define SSL_R_UNABLE_TO_LOAD_SSL2_MD5_ROUTINES 315
+#define SSL_R_GOT_NEXT_PROTO_BEFORE_A_CCS 316
+#define SSL_R_HTTP_REQUEST 317
+#define SSL_R_KRB5_S_INIT 318
+#define SSL_R_RECORD_LENGTH_MISMATCH 320
+#define SSL_R_BAD_LENGTH 321
+#define SSL_R_NO_REQUIRED_DIGEST 322
+#define SSL_R_KRB5 323
+#define SSL_R_CCS_RECEIVED_EARLY 325
+#define SSL_R_MISSING_ECDSA_SIGNING_CERT 326
+#define SSL_R_D2I_ECDSA_SIG 327
+#define SSL_R_PATH_TOO_LONG 328
+#define SSL_R_CIPHER_OR_HASH_UNAVAILABLE 329
+#define SSL_R_UNSUPPORTED_DIGEST_TYPE 330
+#define SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED 331
+#define SSL_R_PEER_ERROR_CERTIFICATE 332
+#define SSL_R_UNABLE_TO_FIND_DH_PARAMETERS 333
+#define SSL_R_NO_CERTIFICATE_SET 334
+#define SSL_R_SSL_SESSION_ID_CALLBACK_FAILED 335
+#define SSL_R_NO_CERTIFICATES_RETURNED 337
+#define SSL_R_BAD_WRITE_RETRY 338
+#define SSL_R_BAD_SSL_FILETYPE 339
+#define SSL_R_SRTP_UNKNOWN_PROTECTION_PROFILE 340
+#define SSL_R_NO_CIPHERS_SPECIFIED 341
+#define SSL_R_LENGTH_MISMATCH 342
+#define SSL_R_NO_CIPHERS_PASSED 343
+#define SSL_R_NO_VERIFY_CALLBACK 344
+#define SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE 345
+#define SSL_R_WRONG_NUMBER_OF_KEY_BITS 347
+#define SSL_R_UNEXPECTED_MESSAGE 348
+#define SSL_R_MISSING_DH_DSA_CERT 349
+#define SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH 350
+#define SSL_R_OPAQUE_PRF_INPUT_TOO_LONG 351
+#define SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES 352
+#define SSL_R_ILLEGAL_SUITEB_DIGEST 353
+#define SSL_R_NO_SHARED_SIGATURE_ALGORITHMS 354
+#define SSL_R_CLIENTHELLO_TLSEXT 355
+#define SSL_R_INVALID_AUTHZ_DATA 356
+#define SSL_R_BAD_RESPONSE_ARGUMENT 357
+#define SSL_R_PUBLIC_KEY_ENCRYPT_ERROR 358
+#define SSL_R_REQUIRED_CIPHER_MISSING 359
+#define SSL_R_INVALID_AUDIT_PROOF 360
+#define SSL_R_PSK_IDENTITY_NOT_FOUND 361
+#define SSL_R_UNKNOWN_ALERT_TYPE 362
+#define SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER 363
+#define SSL_R_BAD_AUTHENTICATION_TYPE 365
+#define SSL_R_DECRYPTION_FAILED 366
+#define SSL_R_WRONG_SSL_VERSION 367
+#define SSL_R_NO_CERTIFICATE_RETURNED 368
+#define SSL_R_CA_DN_TOO_LONG 370
+#define SSL_R_GOT_A_FIN_BEFORE_A_CCS 371
+#define SSL_R_COMPRESSION_LIBRARY_ERROR 372
+#define SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS 374
+#define SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED 375
+#define SSL_R_BAD_ECPOINT 376
+#define SSL_R_BAD_HANDSHAKE_LENGTH 377
+#define SSL_R_KRB5_S_RD_REQ 380
+#define SSL_R_PEER_ERROR_NO_CERTIFICATE 381
+#define SSL_R_PRE_MAC_LENGTH_TOO_LONG 382
+#define SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS 383
+#define SSL_R_UNKNOWN_DIGEST 384
+#define SSL_R_WRONG_SIGNATURE_SIZE 385
+#define SSL_R_SIGNATURE_ALGORITHMS_ERROR 386
+#define SSL_R_REQUIRED_COMPRESSSION_ALGORITHM_MISSING 387
+#define SSL_R_BAD_SIGNATURE 388
+#define SSL_R_BAD_PACKET_LENGTH 389
+#define SSL_R_CANNOT_SERIALIZE_PUBLIC_KEY 390
+#define SSL_R_RENEGOTIATION_MISMATCH 391
+#define SSL_R_BAD_MAC_LENGTH 392
+#define SSL_R_NO_PUBLICKEY 393
+#define SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE 394
+#define SSL_R_BAD_MAC_DECODE 395
+#define SSL_R_NO_PRIVATE_KEY_ASSIGNED 396
+#define SSL_R_EXTRA_DATA_IN_MESSAGE 397
+#define SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER 398
+#define SSL_R_CONNECTION_ID_IS_DIFFERENT 399
+#define SSL_R_MISSING_VERIFY_MESSAGE 402
+#define SSL_R_BAD_DSA_SIGNATURE 403
+#define SSL_R_UNKNOWN_SSL_VERSION 404
+#define SSL_R_KEY_ARG_TOO_LONG 405
+#define SSL_R_KRB5_C_INIT 406
+#define SSL_R_NO_CIPHER_LIST 407
+#define SSL_R_PEER_ERROR_NO_CIPHER 408
+#define SSL_R_UNKNOWN_CMD_NAME 409
+#define SSL_R_UNKNOWN_CIPHER_RETURNED 410
+#define SSL_R_RECORD_TOO_SMALL 411
+#define SSL_R_ENCRYPTED_LENGTH_TOO_LONG 412
+#define SSL_R_UNSUPPORTED_SSL_VERSION 413
+#define SSL_R_UNABLE_TO_EXTRACT_PUBLIC_KEY 415
+#define SSL_R_MISSING_EXPORT_TMP_RSA_KEY 416
+#define SSL_R_BAD_DATA 417
+#define SSL_R_KRB5_S_TKT_NYV 418
+#define SSL_R_BAD_PROTOCOL_VERSION_NUMBER 420
+#define SSL_R_BAD_MESSAGE_TYPE 421
+#define SSL_R_MISSING_ECDH_CERT 422
+#define SSL_R_UNSUPPORTED_PROTOCOL 423
+#define SSL_R_SRP_A_CALC 424
+#define SSL_R_WRITE_BIO_NOT_SET 425
+#define SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE 426
+#define SSL_R_LENGTH_TOO_SHORT 427
+#define SSL_R_CERT_CB_ERROR 428
+#define SSL_R_DTLS_MESSAGE_TOO_BIG 429
+#define SSL_R_INVALID_SRP_USERNAME 430
+#define SSL_R_TOO_MANY_EMPTY_FRAGMENTS 431
+#define SSL_R_NESTED_GROUP 432
+#define SSL_R_UNEXPECTED_GROUP_CLOSE 433
+#define SSL_R_UNEXPECTED_OPERATOR_IN_GROUP 434
+#define SSL_R_MIXED_SPECIAL_OPERATOR_WITH_GROUPS 435
+#define SSL_R_INAPPROPRIATE_FALLBACK 436
+#define SSL_R_CLIENTHELLO_PARSE_FAILED 437
+#define SSL_R_CONNECTION_REJECTED 438
+#define SSL_R_DECODE_ERROR 439
+#define SSL_R_UNPROCESSED_HANDSHAKE_DATA 440
+#define SSL_R_HANDSHAKE_RECORD_BEFORE_CCS 441
+#define SSL_R_SESSION_MAY_NOT_BE_CREATED 442
+#define SSL_R_INVALID_SSL_SESSION 443
+#define SSL_R_BAD_ALERT 444
+#define SSL_R_HANDSHAKE_FAILURE_ON_CLIENT_HELLO 445
+#define SSL_R_MTU_TOO_SMALL 446
+#define SSL_R_SSLV3_ALERT_CLOSE_NOTIFY 1000
+#define SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE 1010
+#define SSL_R_SSLV3_ALERT_BAD_RECORD_MAC 1020
+#define SSL_R_TLSV1_ALERT_DECRYPTION_FAILED 1021
+#define SSL_R_TLSV1_ALERT_RECORD_OVERFLOW 1022
+#define SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE 1030
+#define SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE 1040
+#define SSL_R_SSLV3_ALERT_NO_CERTIFICATE 1041
+#define SSL_R_SSLV3_ALERT_BAD_CERTIFICATE 1042
+#define SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE 1043
+#define SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED 1044
+#define SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED 1045
+#define SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN 1046
+#define SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER 1047
+#define SSL_R_TLSV1_ALERT_UNKNOWN_CA 1048
+#define SSL_R_TLSV1_ALERT_ACCESS_DENIED 1049
+#define SSL_R_TLSV1_ALERT_DECODE_ERROR 1050
+#define SSL_R_TLSV1_ALERT_DECRYPT_ERROR 1051
+#define SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION 1060
+#define SSL_R_TLSV1_ALERT_PROTOCOL_VERSION 1070
+#define SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY 1071
+#define SSL_R_TLSV1_ALERT_INTERNAL_ERROR 1080
+#define SSL_R_TLSV1_ALERT_INAPPROPRIATE_FALLBACK 1086
+#define SSL_R_TLSV1_ALERT_USER_CANCELLED 1090
+#define SSL_R_TLSV1_ALERT_NO_RENEGOTIATION 1100
+#define SSL_R_TLSV1_UNSUPPORTED_EXTENSION 1110
+#define SSL_R_TLSV1_CERTIFICATE_UNOBTAINABLE 1111
+#define SSL_R_TLSV1_UNRECOGNIZED_NAME 1112
+#define SSL_R_TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE 1113
+#define SSL_R_TLSV1_BAD_CERTIFICATE_HASH_VALUE 1114
+
+#endif
diff --git a/src/include/openssl/ssl2.h b/src/include/openssl/ssl2.h
new file mode 100644
index 0000000..eb25dcb
--- /dev/null
+++ b/src/include/openssl/ssl2.h
@@ -0,0 +1,272 @@
+/* ssl/ssl2.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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
+#ifdef OPENSSL_SYS_MPE
+#define SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER 29998u
+#else
+#define SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER 32767u /* 2^15-1 */
+#endif
+#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
+
+#ifndef HEADER_SSL_LOCL_H
+#define CERT char
+#endif
+
+#ifndef OPENSSL_NO_SSL_INTERN
+
+typedef struct ssl2_state_st
+ {
+ int three_byte_header;
+ int clear_text; /* clear text */
+ int escape; /* not used in SSLv2 */
+ int ssl2_rollback; /* used if SSLv23 rolled back to SSLv2 */
+
+ /* non-blocking io info, used to make sure the same
+ * args were passwd */
+ unsigned int wnum; /* number of bytes sent so far */
+ int wpend_tot;
+ const unsigned char *wpend_buf;
+
+ int wpend_off; /* offset to data to write */
+ int wpend_len; /* number of bytes passwd to write */
+ int wpend_ret; /* number of bytes to return to caller */
+
+ /* buffer raw data */
+ int rbuf_left;
+ int rbuf_offs;
+ unsigned char *rbuf;
+ unsigned char *wbuf;
+
+ unsigned char *write_ptr;/* used to point to the start due to
+ * 2/3 byte header. */
+
+ unsigned int padding;
+ unsigned int rlength; /* passed to ssl2_enc */
+ int ract_data_length; /* Set when things are encrypted. */
+ unsigned int wlength; /* passed to ssl2_enc */
+ int wact_data_length; /* Set when things are decrypted. */
+ unsigned char *ract_data;
+ unsigned char *wact_data;
+ unsigned char *mac_data;
+
+ unsigned char *read_key;
+ unsigned char *write_key;
+
+ /* Stuff specifically to do with this SSL session */
+ unsigned int challenge_length;
+ unsigned char challenge[SSL2_MAX_CHALLENGE_LENGTH];
+ unsigned int conn_id_length;
+ unsigned char conn_id[SSL2_MAX_CONNECTION_ID_LENGTH];
+ unsigned int key_material_length;
+ unsigned char key_material[SSL2_MAX_KEY_MATERIAL_LENGTH*2];
+
+ unsigned long read_sequence;
+ unsigned long write_sequence;
+
+ struct {
+ unsigned int conn_id_length;
+ unsigned int cert_type;
+ unsigned int cert_length;
+ unsigned int csl;
+ unsigned int clear;
+ unsigned int enc;
+ unsigned char ccl[SSL2_MAX_CERT_CHALLENGE_LENGTH];
+ unsigned int cipher_spec_length;
+ unsigned int session_id_length;
+ unsigned int clen;
+ unsigned int rlen;
+ } tmp;
+ } SSL2_STATE;
+
+#endif
+
+/* SSLv2 */
+/* client */
+#define SSL2_ST_SEND_CLIENT_HELLO_A (0x10|SSL_ST_CONNECT)
+#define SSL2_ST_SEND_CLIENT_HELLO_B (0x11|SSL_ST_CONNECT)
+#define SSL2_ST_GET_SERVER_HELLO_A (0x20|SSL_ST_CONNECT)
+#define SSL2_ST_GET_SERVER_HELLO_B (0x21|SSL_ST_CONNECT)
+#define SSL2_ST_SEND_CLIENT_MASTER_KEY_A (0x30|SSL_ST_CONNECT)
+#define SSL2_ST_SEND_CLIENT_MASTER_KEY_B (0x31|SSL_ST_CONNECT)
+#define SSL2_ST_SEND_CLIENT_FINISHED_A (0x40|SSL_ST_CONNECT)
+#define SSL2_ST_SEND_CLIENT_FINISHED_B (0x41|SSL_ST_CONNECT)
+#define SSL2_ST_SEND_CLIENT_CERTIFICATE_A (0x50|SSL_ST_CONNECT)
+#define SSL2_ST_SEND_CLIENT_CERTIFICATE_B (0x51|SSL_ST_CONNECT)
+#define SSL2_ST_SEND_CLIENT_CERTIFICATE_C (0x52|SSL_ST_CONNECT)
+#define SSL2_ST_SEND_CLIENT_CERTIFICATE_D (0x53|SSL_ST_CONNECT)
+#define SSL2_ST_GET_SERVER_VERIFY_A (0x60|SSL_ST_CONNECT)
+#define SSL2_ST_GET_SERVER_VERIFY_B (0x61|SSL_ST_CONNECT)
+#define SSL2_ST_GET_SERVER_FINISHED_A (0x70|SSL_ST_CONNECT)
+#define SSL2_ST_GET_SERVER_FINISHED_B (0x71|SSL_ST_CONNECT)
+#define SSL2_ST_CLIENT_START_ENCRYPTION (0x80|SSL_ST_CONNECT)
+#define SSL2_ST_X509_GET_CLIENT_CERTIFICATE (0x90|SSL_ST_CONNECT)
+/* server */
+#define SSL2_ST_GET_CLIENT_HELLO_A (0x10|SSL_ST_ACCEPT)
+#define SSL2_ST_GET_CLIENT_HELLO_B (0x11|SSL_ST_ACCEPT)
+#define SSL2_ST_GET_CLIENT_HELLO_C (0x12|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_SERVER_HELLO_A (0x20|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_SERVER_HELLO_B (0x21|SSL_ST_ACCEPT)
+#define SSL2_ST_GET_CLIENT_MASTER_KEY_A (0x30|SSL_ST_ACCEPT)
+#define SSL2_ST_GET_CLIENT_MASTER_KEY_B (0x31|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_SERVER_VERIFY_A (0x40|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_SERVER_VERIFY_B (0x41|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_SERVER_VERIFY_C (0x42|SSL_ST_ACCEPT)
+#define SSL2_ST_GET_CLIENT_FINISHED_A (0x50|SSL_ST_ACCEPT)
+#define SSL2_ST_GET_CLIENT_FINISHED_B (0x51|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_SERVER_FINISHED_A (0x60|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_SERVER_FINISHED_B (0x61|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_REQUEST_CERTIFICATE_A (0x70|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_REQUEST_CERTIFICATE_B (0x71|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_REQUEST_CERTIFICATE_C (0x72|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_REQUEST_CERTIFICATE_D (0x73|SSL_ST_ACCEPT)
+#define SSL2_ST_SERVER_START_ENCRYPTION (0x80|SSL_ST_ACCEPT)
+#define SSL2_ST_X509_GET_SERVER_CERTIFICATE (0x90|SSL_ST_ACCEPT)
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff --git a/src/include/openssl/ssl23.h b/src/include/openssl/ssl23.h
new file mode 100644
index 0000000..df395a8
--- /dev/null
+++ b/src/include/openssl/ssl23.h
@@ -0,0 +1,85 @@
+/* ssl/ssl23.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 (0x210 | SSL_ST_ACCEPT)
+#define SSL23_ST_SR_V2_CLNT_HELLO (0x220 | SSL_ST_ACCEPT)
+#define SSL23_ST_SR_SWITCH_VERSION (0x230 | SSL_ST_ACCEPT)
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/include/openssl/ssl3.h b/src/include/openssl/ssl3.h
new file mode 100644
index 0000000..8745281
--- /dev/null
+++ b/src/include/openssl/ssl3.h
@@ -0,0 +1,662 @@
+/* ssl/ssl3.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/buf.h>
+#include <openssl/evp.h>
+#include <openssl/ssl.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Signalling cipher suite value: from RFC5746 */
+#define SSL3_CK_SCSV 0x030000FF
+/* Fallback signalling cipher suite value: not IANA assigned.
+ * See https://tools.ietf.org/html/draft-bmoeller-tls-downgrade-scsv-01 */
+#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
+
+#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_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_SESSION_ID_SIZE 32
+#define SSL3_RT_HEADER_LENGTH 5
+
+#define SSL3_HM_HEADER_LENGTH 4
+
+#ifndef SSL3_ALIGN_PAYLOAD
+/* Some will argue that this increases memory footprint, but it's not actually
+ * true. Point is that malloc has to return at least 64-bit aligned pointers,
+ * meaning that allocating 5 bytes wastes 3 bytes in either case. Suggested
+ * pre-gaping simply moves these wasted bytes from the end of allocated region
+ * to its front, but makes data payload aligned, which improves performance. */
+#define SSL3_ALIGN_PAYLOAD 8
+#else
+#if (SSL3_ALIGN_PAYLOAD & (SSL3_ALIGN_PAYLOAD - 1)) != 0
+#error "insane SSL3_ALIGN_PAYLOAD"
+#undef SSL3_ALIGN_PAYLOAD
+#endif
+#endif
+
+/* 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 + SSL3_RT_MAX_COMPRESSED_OVERHEAD)
+#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
+
+/* Pseudo content types to indicate additional parameters */
+#define TLS1_RT_CRYPTO 0x1000
+#define TLS1_RT_CRYPTO_PREMASTER (TLS1_RT_CRYPTO | 0x1)
+#define TLS1_RT_CRYPTO_CLIENT_RANDOM (TLS1_RT_CRYPTO | 0x2)
+#define TLS1_RT_CRYPTO_SERVER_RANDOM (TLS1_RT_CRYPTO | 0x3)
+#define TLS1_RT_CRYPTO_MASTER (TLS1_RT_CRYPTO | 0x4)
+
+#define TLS1_RT_CRYPTO_READ 0x0000
+#define TLS1_RT_CRYPTO_WRITE 0x0100
+#define TLS1_RT_CRYPTO_MAC (TLS1_RT_CRYPTO | 0x5)
+#define TLS1_RT_CRYPTO_KEY (TLS1_RT_CRYPTO | 0x6)
+#define TLS1_RT_CRYPTO_IV (TLS1_RT_CRYPTO | 0x7)
+#define TLS1_RT_CRYPTO_FIXED_IV (TLS1_RT_CRYPTO | 0x8)
+
+/* Pseudo content type for SSL/TLS header info */
+#define SSL3_RT_HEADER 0x100
+
+#define SSL3_AL_WARNING 1
+#define SSL3_AL_FATAL 2
+
+#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 */
+#define SSL3_AD_INAPPROPRIATE_FALLBACK 86 /* fatal */
+
+typedef struct ssl3_record_st {
+ /*r */ int type; /* type of record */
+ /*rw*/ unsigned int length; /* How many bytes available */
+ /*r */ unsigned int off; /* read/write offset into 'buf' */
+ /*rw*/ uint8_t *data; /* pointer to the record data */
+ /*rw*/ uint8_t *input; /* where the decode bytes are */
+ /*r */ unsigned long epoch; /* epoch number, needed by DTLS1 */
+ /*r */ uint8_t seq_num[8]; /* sequence number, needed by DTLS1 */
+} SSL3_RECORD;
+
+typedef struct ssl3_buffer_st {
+ uint8_t *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;
+
+#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
+
+
+/* TODO(davidben): This flag can probably be merged into s3->change_cipher_spec
+ * to something tri-state. (Normal / Expect CCS / Between CCS and Finished). */
+#define SSL3_FLAGS_EXPECT_CCS 0x0080
+
+typedef struct ssl3_state_st {
+ long flags;
+
+ uint8_t read_sequence[8];
+ int read_mac_secret_size;
+ uint8_t read_mac_secret[EVP_MAX_MD_SIZE];
+ uint8_t write_sequence[8];
+ int write_mac_secret_size;
+ uint8_t write_mac_secret[EVP_MAX_MD_SIZE];
+
+ uint8_t server_random[SSL3_RANDOM_SIZE];
+ uint8_t client_random[SSL3_RANDOM_SIZE];
+
+ /* flags for countermeasure against known-IV weakness */
+ int need_record_splitting;
+ int record_split_done;
+
+ /* The value of 'extra' when the buffers were initialized */
+ int init_extra;
+
+ /* have_version is true if the connection's final version is known. Otherwise
+ * the version has not been negotiated yet. */
+ char have_version;
+
+ /* sniff_buffer is used by the server in the initial handshake to read a
+ * V2ClientHello before the record layer is initialized. */
+ BUF_MEM *sniff_buffer;
+ size_t sniff_buffer_len;
+
+ SSL3_BUFFER rbuf; /* read IO goes into here */
+ SSL3_BUFFER wbuf; /* write IO goes into here */
+
+ SSL3_RECORD rrec; /* each decoded record goes in here */
+ SSL3_RECORD wrec; /* goes out from here */
+
+ /* storage for Handshake protocol data received but not yet processed by
+ * ssl3_read_bytes: */
+ uint8_t handshake_fragment[4];
+ unsigned int handshake_fragment_len;
+
+ /* 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 uint8_t *wpend_buf;
+
+ /* used during startup, digest all incoming/outgoing packets */
+ BIO *handshake_buffer;
+ /* When set of handshake digests is determined, buffer is hashed and freed
+ * and MD_CTX-es for all required digests are stored in this array */
+ EVP_MD_CTX **handshake_dgst;
+ /* 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;
+ /* we allow one fatal and one warning alert to be outstanding, send close
+ * alert via the warning alert */
+ int alert_dispatch;
+ uint8_t send_alert[2];
+
+ /* This flag is set when we should renegotiate ASAP, basically when there is
+ * no more data in the read or write buffers */
+ int renegotiate;
+ int total_renegotiations;
+ int num_renegotiations;
+
+ int in_read_app_data;
+
+ /* State pertaining to the pending handshake.
+ *
+ * TODO(davidben): State is current spread all over the place. Move
+ * pending handshake state here so it can be managed separately from
+ * established connection state in case of renegotiations. */
+ struct {
+ /* actually only need to be 16+20 for SSLv3 and 12 for TLS */
+ uint8_t finish_md[EVP_MAX_MD_SIZE * 2];
+ int finish_md_len;
+ uint8_t peer_finish_md[EVP_MAX_MD_SIZE * 2];
+ int peer_finish_md_len;
+
+ unsigned long message_size;
+ int message_type;
+
+ /* used to hold the new cipher we are going to use */
+ const SSL_CIPHER *new_cipher;
+ DH *dh;
+
+ EC_KEY *ecdh; /* holds short lived ECDH key */
+
+ /* used when SSL_ST_FLUSH_DATA is entered */
+ int next_state;
+
+ int reuse_message;
+
+ /* Client-only: cert_req determines if a client certificate is to be sent.
+ * This is 0 if no client Certificate message is to be sent, 1 if there is
+ * a client certificate, and 2 to send an empty client Certificate
+ * message. */
+ int cert_req;
+
+ /* Client-only: ca_names contains the list of CAs received in a
+ * CertificateRequest message. */
+ STACK_OF(X509_NAME) *ca_names;
+
+ /* Client-only: certificate_types contains the set of certificate types
+ * received in a CertificateRequest message. */
+ uint8_t *certificate_types;
+ size_t num_certificate_types;
+
+ int key_block_length;
+ uint8_t *key_block;
+
+ const EVP_AEAD *new_aead;
+ uint8_t new_mac_secret_len;
+ uint8_t new_fixed_iv_len;
+ uint8_t new_variable_iv_len;
+
+ /* Server-only: cert_request is true if a client certificate was
+ * requested. */
+ int cert_request;
+
+ /* certificate_status_expected is true if OCSP stapling was negotiated and
+ * the server is expected to send a CertificateStatus message. */
+ char certificate_status_expected;
+
+ /* peer_ecpointformatlist contains the EC point formats advertised by the
+ * peer. */
+ uint8_t *peer_ecpointformatlist;
+ size_t peer_ecpointformatlist_length;
+
+ /* Server-only: peer_ellipticcurvelist contains the EC curve IDs advertised
+ * by the peer. This is only set on the server's end. The server does not
+ * advertise this extension to the client. */
+ uint16_t *peer_ellipticcurvelist;
+ size_t peer_ellipticcurvelist_length;
+
+ /* extended_master_secret indicates whether the extended master secret
+ * computation is used in this handshake. Note that this is different from
+ * whether it was used for the current session. If this is a resumption
+ * handshake then EMS might be negotiated in the client and server hello
+ * messages, but it doesn't matter if the session that's being resumed
+ * didn't use it to create the master secret initially. */
+ char extended_master_secret;
+
+ /* Client-only: peer_psk_identity_hint is the psk_identity_hint sent by the
+ * server when using a PSK key exchange. */
+ char *peer_psk_identity_hint;
+
+ /* new_mac_secret_size is unused and exists only until wpa_supplicant can
+ * be updated. It is only needed for EAP-FAST, which we don't support. */
+ uint8_t new_mac_secret_size;
+ } tmp;
+
+ /* Connection binding to prevent renegotiation attacks */
+ uint8_t previous_client_finished[EVP_MAX_MD_SIZE];
+ uint8_t previous_client_finished_len;
+ uint8_t previous_server_finished[EVP_MAX_MD_SIZE];
+ uint8_t previous_server_finished_len;
+ int send_connection_binding; /* TODOEKR */
+
+ /* Set if we saw the Next Protocol Negotiation extension from our peer. */
+ int next_proto_neg_seen;
+
+ /* ALPN information
+ * (we are in the process of transitioning from NPN to ALPN.) */
+
+ /* In a server these point to the selected ALPN protocol after the
+ * ClientHello has been processed. In a client these contain the protocol
+ * that the server selected once the ServerHello has been processed. */
+ uint8_t *alpn_selected;
+ size_t alpn_selected_len;
+
+ /* In a client, this means that the server supported Channel ID and that a
+ * Channel ID was sent. In a server it means that we echoed support for
+ * Channel IDs and that tlsext_channel_id will be valid after the
+ * handshake. */
+ char tlsext_channel_id_valid;
+ /* tlsext_channel_id_new means that the updated Channel ID extension was
+ * negotiated. This is a temporary hack in the code to support both forms of
+ * Channel ID extension while we transition to the new format, which fixed a
+ * security issue. */
+ char tlsext_channel_id_new;
+ /* For a server:
+ * If |tlsext_channel_id_valid| is true, then this contains the
+ * verified Channel ID from the client: a P256 point, (x,y), where
+ * each are big-endian values. */
+ uint8_t tlsext_channel_id[64];
+} SSL3_STATE;
+
+/* SSLv3 */
+/* client */
+/* extra state */
+#define SSL3_ST_CW_FLUSH (0x100 | SSL_ST_CONNECT)
+#define SSL3_ST_CUTTHROUGH_COMPLETE (0x101 | 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_NEXT_PROTO_A (0x200 | SSL_ST_CONNECT)
+#define SSL3_ST_CW_NEXT_PROTO_B (0x201 | SSL_ST_CONNECT)
+#define SSL3_ST_CW_CHANNEL_ID_A (0x220 | SSL_ST_CONNECT)
+#define SSL3_ST_CW_CHANNEL_ID_B (0x221 | 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 (0x1C0 | 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 */
+#define SSL3_ST_SR_INITIAL_BYTES (0x240 | SSL_ST_ACCEPT)
+#define SSL3_ST_SR_V2_CLIENT_HELLO (0x241 | SSL_ST_ACCEPT)
+/* 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)
+#define SSL3_ST_SR_CLNT_HELLO_D (0x115 | 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 (0x1B0 | SSL_ST_ACCEPT)
+#define SSL3_ST_SR_NEXT_PROTO_A (0x210 | SSL_ST_ACCEPT)
+#define SSL3_ST_SR_NEXT_PROTO_B (0x211 | SSL_ST_ACCEPT)
+#define SSL3_ST_SR_CHANNEL_ID_A (0x230 | SSL_ST_ACCEPT)
+#define SSL3_ST_SR_CHANNEL_ID_B (0x231 | 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_ST_SW_SUPPLEMENTAL_DATA_A (0x220 | SSL_ST_ACCEPT)
+#define SSL3_ST_SW_SUPPLEMENTAL_DATA_B (0x221 | 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 SSL3_MT_SUPPLEMENTAL_DATA 23
+#define SSL3_MT_NEXT_PROTO 67
+#define SSL3_MT_ENCRYPTED_EXTENSIONS 203
+#define DTLS1_MT_HELLO_VERIFY_REQUEST 3
+
+
+#define SSL3_MT_CCS 1
+
+/* 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)
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/include/openssl/stack.h b/src/include/openssl/stack.h
new file mode 100644
index 0000000..0eeda7f
--- /dev/null
+++ b/src/include/openssl/stack.h
@@ -0,0 +1,294 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 OPENSSL_HEADER_STACK_H
+#define OPENSSL_HEADER_STACK_H
+
+#include <openssl/base.h>
+
+#include <openssl/type_check.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* A stack, in OpenSSL, is an array of pointers. They are the most commonly
+ * used collection object.
+ *
+ * This file defines macros for type safe use of the stack functions. A stack
+ * of a specific type of object has type |STACK_OF(type)|. This can be defined
+ * (once) with |DEFINE_STACK_OF(type)| and declared where needed with
+ * |DECLARE_STACK_OF(type)|. For example:
+ *
+ * struct foo {
+ * int bar;
+ * };
+ *
+ * DEFINE_STACK_OF(struct foo);
+ *
+ * Although note that the stack will contain /pointers/ to |foo|.
+ *
+ * A macro will be defined for each of the sk_* functions below. For
+ * STACK_OF(foo), the macros would be sk_foo_new, sk_foo_pop etc. */
+
+
+/* stack_cmp_func is a comparison function that returns a value < 0, 0 or > 0
+ * if |*a| is less than, equal to or greater than |*b|, respectively. Note the
+ * extra indirection - the function is given a pointer to a pointer to the
+ * element. This differs from the usual qsort/bsearch comparison function. */
+typedef int (*stack_cmp_func)(const void **a, const void **b);
+
+/* stack_st contains an array of pointers. It is not designed to be used
+ * directly, rather the wrapper macros should be used. */
+typedef struct stack_st {
+ /* num contains the number of valid pointers in |data|. */
+ size_t num;
+ void **data;
+ /* sorted is non-zero if the values pointed to by |data| are in ascending
+ * order, based on |comp|. */
+ size_t sorted;
+ /* num_alloc contains the number of pointers allocated in the buffer pointed
+ * to by |data|, which may be larger than |num|. */
+ size_t num_alloc;
+ /* comp is an optional comparison function. */
+ stack_cmp_func comp;
+} _STACK;
+
+
+#define STACK_OF(type) struct stack_st_##type
+
+#define DEFINE_STACK_OF(type) \
+STACK_OF(type) {\
+ _STACK stack; \
+};
+
+#define DECLARE_STACK_OF(type) STACK_OF(type);
+
+/* The make_macros.sh script in this directory parses the following lines and
+ * generates the stack_macros.h file that contains macros for the following
+ * types of stacks:
+ *
+ * STACK_OF:ACCESS_DESCRIPTION
+ * STACK_OF:ASN1_ADB_TABLE
+ * STACK_OF:ASN1_GENERALSTRING
+ * STACK_OF:ASN1_INTEGER
+ * STACK_OF:ASN1_OBJECT
+ * STACK_OF:ASN1_STRING_TABLE
+ * STACK_OF:ASN1_TYPE
+ * STACK_OF:ASN1_VALUE
+ * STACK_OF:BIO
+ * STACK_OF:BY_DIR_ENTRY
+ * STACK_OF:BY_DIR_HASH
+ * STACK_OF:CONF_VALUE
+ * STACK_OF:CRYPTO_EX_DATA_FUNCS
+ * STACK_OF:DIST_POINT
+ * STACK_OF:GENERAL_NAME
+ * STACK_OF:GENERAL_NAMES
+ * STACK_OF:GENERAL_SUBTREE
+ * STACK_OF:MIME_HEADER
+ * STACK_OF:PKCS7_SIGNER_INFO
+ * STACK_OF:PKCS7_RECIP_INFO
+ * STACK_OF:POLICYINFO
+ * STACK_OF:POLICYQUALINFO
+ * STACK_OF:POLICY_MAPPING
+ * STACK_OF:SSL_COMP
+ * STACK_OF:STACK_OF_X509_NAME_ENTRY
+ * STACK_OF:SXNETID
+ * STACK_OF:X509
+ * STACK_OF:X509V3_EXT_METHOD
+ * STACK_OF:X509_ALGOR
+ * STACK_OF:X509_ATTRIBUTE
+ * STACK_OF:X509_CRL
+ * STACK_OF:X509_EXTENSION
+ * STACK_OF:X509_INFO
+ * STACK_OF:X509_LOOKUP
+ * STACK_OF:X509_NAME
+ * STACK_OF:X509_NAME_ENTRY
+ * STACK_OF:X509_OBJECT
+ * STACK_OF:X509_POLICY_DATA
+ * STACK_OF:X509_POLICY_NODE
+ * STACK_OF:X509_PURPOSE
+ * STACK_OF:X509_REVOKED
+ * STACK_OF:X509_TRUST
+ * STACK_OF:X509_VERIFY_PARAM
+ * STACK_OF:void
+ *
+ * Some stacks contain only const structures, so the stack should return const
+ * pointers to retain type-checking.
+ *
+ * CONST_STACK_OF:SRTP_PROTECTION_PROFILE
+ * CONST_STACK_OF:SSL_CIPHER */
+
+
+/* Some stacks are special because, although we would like STACK_OF(char *),
+ * that would actually be a stack of pointers to char*, but we just want to
+ * point to the string directly. In this case we call them "special" and use
+ * |DEFINE_SPECIAL_STACK_OF(type)| */
+#define DEFINE_SPECIAL_STACK_OF(type, inner) \
+ STACK_OF(type) { _STACK special_stack; }; \
+ OPENSSL_COMPILE_ASSERT(sizeof(type) == sizeof(void *), \
+ special_stack_of_non_pointer_##type);
+
+typedef char *OPENSSL_STRING;
+
+DEFINE_SPECIAL_STACK_OF(OPENSSL_STRING, char)
+DEFINE_SPECIAL_STACK_OF(OPENSSL_BLOCK, uint8_t)
+
+/* The make_macros.sh script in this directory parses the following lines and
+ * generates the stack_macros.h file that contains macros for the following
+ * types of stacks:
+ *
+ * SPECIAL_STACK_OF:OPENSSL_STRING
+ * SPECIAL_STACK_OF:OPENSSL_BLOCK */
+
+#define IN_STACK_H
+#include <openssl/stack_macros.h>
+#undef IN_STACK_H
+
+
+/* These are the raw stack functions, you shouldn't be using them. Rather you
+ * should be using the type stack macros implemented above. */
+
+/* sk_new creates a new, empty stack with the given comparison function, which
+ * may be zero. It returns the new stack or NULL on allocation failure. */
+OPENSSL_EXPORT _STACK *sk_new(stack_cmp_func comp);
+
+/* sk_new_null creates a new, empty stack. It returns the new stack or NULL on
+ * allocation failure. */
+OPENSSL_EXPORT _STACK *sk_new_null(void);
+
+/* sk_num returns the number of elements in |s|. */
+OPENSSL_EXPORT size_t sk_num(const _STACK *sk);
+
+/* sk_zero resets |sk| to the empty state but does nothing to free the
+ * individual elements themselves. */
+OPENSSL_EXPORT void sk_zero(_STACK *sk);
+
+/* sk_value returns the |i|th pointer in |sk|, or NULL if |i| is out of
+ * range. */
+OPENSSL_EXPORT void *sk_value(const _STACK *sk, size_t i);
+
+/* sk_set sets the |i|th pointer in |sk| to |p| and returns |p|. If |i| is out
+ * of range, it returns NULL. */
+OPENSSL_EXPORT void *sk_set(_STACK *sk, size_t i, void *p);
+
+/* sk_free frees the given stack and array of pointers, but does nothing to
+ * free the individual elements. Also see |sk_pop_free|. */
+OPENSSL_EXPORT void sk_free(_STACK *sk);
+
+/* sk_pop_free calls |free_func| on each element in the stack and then frees
+ * the stack itself. */
+OPENSSL_EXPORT void sk_pop_free(_STACK *sk, void (*free_func)(void *));
+
+/* sk_insert inserts |p| into the stack at index |where|, moving existing
+ * elements if needed. It returns the length of the new stack, or zero on
+ * error. */
+OPENSSL_EXPORT size_t sk_insert(_STACK *sk, void *p, size_t where);
+
+/* sk_delete removes the pointer at index |where|, moving other elements down
+ * if needed. It returns the removed pointer, or NULL if |where| is out of
+ * range. */
+OPENSSL_EXPORT void *sk_delete(_STACK *sk, size_t where);
+
+/* sk_delete_ptr removes, at most, one instance of |p| from the stack based on
+ * pointer equality. If an instance of |p| is found then |p| is returned,
+ * otherwise it returns NULL. */
+OPENSSL_EXPORT void *sk_delete_ptr(_STACK *sk, void *p);
+
+/* sk_find returns the first value in the stack equal to |p|. If a comparison
+ * function has been set on the stack, then equality is defined by it and the
+ * stack will be sorted if need be so that a binary search can be used.
+ * Otherwise pointer equality is used. If a matching element is found, its
+ * index is written to |*out_index| (if |out_index| is not NULL) and one is
+ * returned. Otherwise zero is returned. */
+OPENSSL_EXPORT int sk_find(_STACK *sk, size_t *out_index, void *p);
+
+/* sk_shift removes and returns the first element in the stack, or returns NULL
+ * if the stack is empty. */
+OPENSSL_EXPORT void *sk_shift(_STACK *sk);
+
+/* sk_push appends |p| to the stack and returns the length of the new stack, or
+ * 0 on allocation failure. */
+OPENSSL_EXPORT size_t sk_push(_STACK *sk, void *p);
+
+/* sk_pop returns and removes the last element on the stack, or NULL if the
+ * stack is empty. */
+OPENSSL_EXPORT void *sk_pop(_STACK *sk);
+
+/* sk_dup performs a shallow copy of a stack and returns the new stack, or NULL
+ * on error. */
+OPENSSL_EXPORT _STACK *sk_dup(const _STACK *sk);
+
+/* sk_sort sorts the elements of |sk| into ascending order based on the
+ * comparison function. The stack maintains a |sorted| flag and sorting an
+ * already sorted stack is a no-op. */
+OPENSSL_EXPORT void sk_sort(_STACK *sk);
+
+/* sk_is_sorted returns one if |sk| is known to be sorted and zero
+ * otherwise. */
+OPENSSL_EXPORT int sk_is_sorted(const _STACK *sk);
+
+/* sk_set_cmp_func sets the comparison function to be used by |sk| and returns
+ * the previous one. */
+OPENSSL_EXPORT stack_cmp_func sk_set_cmp_func(_STACK *sk, stack_cmp_func comp);
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_STACK_H */
diff --git a/src/include/openssl/stack_macros.h b/src/include/openssl/stack_macros.h
new file mode 100644
index 0000000..a62fce3
--- /dev/null
+++ b/src/include/openssl/stack_macros.h
@@ -0,0 +1,3704 @@
+/* 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. */
+
+#if !defined(IN_STACK_H)
+#error "Don't include this file directly. Include stack.h."
+#endif
+
+/* ACCESS_DESCRIPTION */
+#define sk_ACCESS_DESCRIPTION_new(comp) \
+ ((STACK_OF(ACCESS_DESCRIPTION) *)sk_new(CHECKED_CAST( \
+ stack_cmp_func, \
+ int (*)(const ACCESS_DESCRIPTION **a, const ACCESS_DESCRIPTION **b), \
+ comp)))
+
+#define sk_ACCESS_DESCRIPTION_new_null() \
+ ((STACK_OF(ACCESS_DESCRIPTION) *)sk_new_null())
+
+#define sk_ACCESS_DESCRIPTION_num(sk) \
+ sk_num(CHECKED_CAST(_STACK *, STACK_OF(ACCESS_DESCRIPTION) *, sk))
+
+#define sk_ACCESS_DESCRIPTION_zero(sk) \
+ sk_zero(CHECKED_CAST(_STACK *, STACK_OF(ACCESS_DESCRIPTION) *, sk));
+
+#define sk_ACCESS_DESCRIPTION_value(sk, i) \
+ ((ACCESS_DESCRIPTION *)sk_value( \
+ CHECKED_CAST(_STACK *, const STACK_OF(ACCESS_DESCRIPTION) *, sk), (i)))
+
+#define sk_ACCESS_DESCRIPTION_set(sk, i, p) \
+ ((ACCESS_DESCRIPTION *)sk_set( \
+ CHECKED_CAST(_STACK *, STACK_OF(ACCESS_DESCRIPTION) *, sk), (i), \
+ CHECKED_CAST(void *, ACCESS_DESCRIPTION *, p)))
+
+#define sk_ACCESS_DESCRIPTION_free(sk) \
+ sk_free(CHECKED_CAST(_STACK *, STACK_OF(ACCESS_DESCRIPTION) *, sk))
+
+#define sk_ACCESS_DESCRIPTION_pop_free(sk, free_func) \
+ sk_pop_free(CHECKED_CAST(_STACK *, STACK_OF(ACCESS_DESCRIPTION) *, sk), \
+ CHECKED_CAST(void (*)(void *), void (*)(ACCESS_DESCRIPTION *), \
+ free_func))
+
+#define sk_ACCESS_DESCRIPTION_insert(sk, p, where) \
+ sk_insert(CHECKED_CAST(_STACK *, STACK_OF(ACCESS_DESCRIPTION) *, sk), \
+ CHECKED_CAST(void *, ACCESS_DESCRIPTION *, p), (where))
+
+#define sk_ACCESS_DESCRIPTION_delete(sk, where) \
+ ((ACCESS_DESCRIPTION *)sk_delete( \
+ CHECKED_CAST(_STACK *, STACK_OF(ACCESS_DESCRIPTION) *, sk), (where)))
+
+#define sk_ACCESS_DESCRIPTION_delete_ptr(sk, p) \
+ ((ACCESS_DESCRIPTION *)sk_delete_ptr( \
+ CHECKED_CAST(_STACK *, STACK_OF(ACCESS_DESCRIPTION) *, sk), \
+ CHECKED_CAST(void *, ACCESS_DESCRIPTION *, p)))
+
+#define sk_ACCESS_DESCRIPTION_find(sk, out_index, p) \
+ sk_find(CHECKED_CAST(_STACK *, STACK_OF(ACCESS_DESCRIPTION) *, sk), \
+ (out_index), CHECKED_CAST(void *, ACCESS_DESCRIPTION *, p))
+
+#define sk_ACCESS_DESCRIPTION_shift(sk) \
+ ((ACCESS_DESCRIPTION *)sk_shift( \
+ CHECKED_CAST(_STACK *, STACK_OF(ACCESS_DESCRIPTION) *, sk)))
+
+#define sk_ACCESS_DESCRIPTION_push(sk, p) \
+ sk_push(CHECKED_CAST(_STACK *, STACK_OF(ACCESS_DESCRIPTION) *, sk), \
+ CHECKED_CAST(void *, ACCESS_DESCRIPTION *, p))
+
+#define sk_ACCESS_DESCRIPTION_pop(sk) \
+ ((ACCESS_DESCRIPTION *)sk_pop( \
+ CHECKED_CAST(_STACK *, STACK_OF(ACCESS_DESCRIPTION) *, sk)))
+
+#define sk_ACCESS_DESCRIPTION_dup(sk) \
+ ((STACK_OF(ACCESS_DESCRIPTION) *)sk_dup( \
+ CHECKED_CAST(_STACK *, const STACK_OF(ACCESS_DESCRIPTION) *, sk)))
+
+#define sk_ACCESS_DESCRIPTION_sort(sk) \
+ sk_sort(CHECKED_CAST(_STACK *, STACK_OF(ACCESS_DESCRIPTION) *, sk))
+
+#define sk_ACCESS_DESCRIPTION_is_sorted(sk) \
+ sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(ACCESS_DESCRIPTION) *, sk))
+
+#define sk_ACCESS_DESCRIPTION_set_cmp_func(sk, comp) \
+ ((int (*)(const ACCESS_DESCRIPTION **a, const ACCESS_DESCRIPTION **b)) \
+ sk_set_cmp_func( \
+ CHECKED_CAST(_STACK *, STACK_OF(ACCESS_DESCRIPTION) *, sk), \
+ CHECKED_CAST(stack_cmp_func, int (*)(const ACCESS_DESCRIPTION **a, \
+ const ACCESS_DESCRIPTION **b), \
+ comp)))
+
+
+/* ASN1_ADB_TABLE */
+#define sk_ASN1_ADB_TABLE_new(comp) \
+ ((STACK_OF(ASN1_ADB_TABLE) *)sk_new(CHECKED_CAST( \
+ stack_cmp_func, \
+ int (*)(const ASN1_ADB_TABLE **a, const ASN1_ADB_TABLE **b), comp)))
+
+#define sk_ASN1_ADB_TABLE_new_null() ((STACK_OF(ASN1_ADB_TABLE) *)sk_new_null())
+
+#define sk_ASN1_ADB_TABLE_num(sk) \
+ sk_num(CHECKED_CAST(_STACK *, STACK_OF(ASN1_ADB_TABLE) *, sk))
+
+#define sk_ASN1_ADB_TABLE_zero(sk) \
+ sk_zero(CHECKED_CAST(_STACK *, STACK_OF(ASN1_ADB_TABLE) *, sk));
+
+#define sk_ASN1_ADB_TABLE_value(sk, i) \
+ ((ASN1_ADB_TABLE *)sk_value( \
+ CHECKED_CAST(_STACK *, const STACK_OF(ASN1_ADB_TABLE) *, sk), (i)))
+
+#define sk_ASN1_ADB_TABLE_set(sk, i, p) \
+ ((ASN1_ADB_TABLE *)sk_set( \
+ CHECKED_CAST(_STACK *, STACK_OF(ASN1_ADB_TABLE) *, sk), (i), \
+ CHECKED_CAST(void *, ASN1_ADB_TABLE *, p)))
+
+#define sk_ASN1_ADB_TABLE_free(sk) \
+ sk_free(CHECKED_CAST(_STACK *, STACK_OF(ASN1_ADB_TABLE) *, sk))
+
+#define sk_ASN1_ADB_TABLE_pop_free(sk, free_func) \
+ sk_pop_free( \
+ CHECKED_CAST(_STACK *, STACK_OF(ASN1_ADB_TABLE) *, sk), \
+ CHECKED_CAST(void (*)(void *), void (*)(ASN1_ADB_TABLE *), free_func))
+
+#define sk_ASN1_ADB_TABLE_insert(sk, p, where) \
+ sk_insert(CHECKED_CAST(_STACK *, STACK_OF(ASN1_ADB_TABLE) *, sk), \
+ CHECKED_CAST(void *, ASN1_ADB_TABLE *, p), (where))
+
+#define sk_ASN1_ADB_TABLE_delete(sk, where) \
+ ((ASN1_ADB_TABLE *)sk_delete( \
+ CHECKED_CAST(_STACK *, STACK_OF(ASN1_ADB_TABLE) *, sk), (where)))
+
+#define sk_ASN1_ADB_TABLE_delete_ptr(sk, p) \
+ ((ASN1_ADB_TABLE *)sk_delete_ptr( \
+ CHECKED_CAST(_STACK *, STACK_OF(ASN1_ADB_TABLE) *, sk), \
+ CHECKED_CAST(void *, ASN1_ADB_TABLE *, p)))
+
+#define sk_ASN1_ADB_TABLE_find(sk, out_index, p) \
+ sk_find(CHECKED_CAST(_STACK *, STACK_OF(ASN1_ADB_TABLE) *, sk), (out_index), \
+ CHECKED_CAST(void *, ASN1_ADB_TABLE *, p))
+
+#define sk_ASN1_ADB_TABLE_shift(sk) \
+ ((ASN1_ADB_TABLE *)sk_shift( \
+ CHECKED_CAST(_STACK *, STACK_OF(ASN1_ADB_TABLE) *, sk)))
+
+#define sk_ASN1_ADB_TABLE_push(sk, p) \
+ sk_push(CHECKED_CAST(_STACK *, STACK_OF(ASN1_ADB_TABLE) *, sk), \
+ CHECKED_CAST(void *, ASN1_ADB_TABLE *, p))
+
+#define sk_ASN1_ADB_TABLE_pop(sk) \
+ ((ASN1_ADB_TABLE *)sk_pop( \
+ CHECKED_CAST(_STACK *, STACK_OF(ASN1_ADB_TABLE) *, sk)))
+
+#define sk_ASN1_ADB_TABLE_dup(sk) \
+ ((STACK_OF(ASN1_ADB_TABLE) *)sk_dup( \
+ CHECKED_CAST(_STACK *, const STACK_OF(ASN1_ADB_TABLE) *, sk)))
+
+#define sk_ASN1_ADB_TABLE_sort(sk) \
+ sk_sort(CHECKED_CAST(_STACK *, STACK_OF(ASN1_ADB_TABLE) *, sk))
+
+#define sk_ASN1_ADB_TABLE_is_sorted(sk) \
+ sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(ASN1_ADB_TABLE) *, sk))
+
+#define sk_ASN1_ADB_TABLE_set_cmp_func(sk, comp) \
+ ((int (*)(const ASN1_ADB_TABLE **a, const ASN1_ADB_TABLE **b)) \
+ sk_set_cmp_func( \
+ CHECKED_CAST(_STACK *, STACK_OF(ASN1_ADB_TABLE) *, sk), \
+ CHECKED_CAST(stack_cmp_func, int (*)(const ASN1_ADB_TABLE **a, \
+ const ASN1_ADB_TABLE **b), \
+ comp)))
+
+
+/* ASN1_GENERALSTRING */
+#define sk_ASN1_GENERALSTRING_new(comp) \
+ ((STACK_OF(ASN1_GENERALSTRING) *)sk_new(CHECKED_CAST( \
+ stack_cmp_func, \
+ int (*)(const ASN1_GENERALSTRING **a, const ASN1_GENERALSTRING **b), \
+ comp)))
+
+#define sk_ASN1_GENERALSTRING_new_null() \
+ ((STACK_OF(ASN1_GENERALSTRING) *)sk_new_null())
+
+#define sk_ASN1_GENERALSTRING_num(sk) \
+ sk_num(CHECKED_CAST(_STACK *, STACK_OF(ASN1_GENERALSTRING) *, sk))
+
+#define sk_ASN1_GENERALSTRING_zero(sk) \
+ sk_zero(CHECKED_CAST(_STACK *, STACK_OF(ASN1_GENERALSTRING) *, sk));
+
+#define sk_ASN1_GENERALSTRING_value(sk, i) \
+ ((ASN1_GENERALSTRING *)sk_value( \
+ CHECKED_CAST(_STACK *, const STACK_OF(ASN1_GENERALSTRING) *, sk), (i)))
+
+#define sk_ASN1_GENERALSTRING_set(sk, i, p) \
+ ((ASN1_GENERALSTRING *)sk_set( \
+ CHECKED_CAST(_STACK *, STACK_OF(ASN1_GENERALSTRING) *, sk), (i), \
+ CHECKED_CAST(void *, ASN1_GENERALSTRING *, p)))
+
+#define sk_ASN1_GENERALSTRING_free(sk) \
+ sk_free(CHECKED_CAST(_STACK *, STACK_OF(ASN1_GENERALSTRING) *, sk))
+
+#define sk_ASN1_GENERALSTRING_pop_free(sk, free_func) \
+ sk_pop_free(CHECKED_CAST(_STACK *, STACK_OF(ASN1_GENERALSTRING) *, sk), \
+ CHECKED_CAST(void (*)(void *), void (*)(ASN1_GENERALSTRING *), \
+ free_func))
+
+#define sk_ASN1_GENERALSTRING_insert(sk, p, where) \
+ sk_insert(CHECKED_CAST(_STACK *, STACK_OF(ASN1_GENERALSTRING) *, sk), \
+ CHECKED_CAST(void *, ASN1_GENERALSTRING *, p), (where))
+
+#define sk_ASN1_GENERALSTRING_delete(sk, where) \
+ ((ASN1_GENERALSTRING *)sk_delete( \
+ CHECKED_CAST(_STACK *, STACK_OF(ASN1_GENERALSTRING) *, sk), (where)))
+
+#define sk_ASN1_GENERALSTRING_delete_ptr(sk, p) \
+ ((ASN1_GENERALSTRING *)sk_delete_ptr( \
+ CHECKED_CAST(_STACK *, STACK_OF(ASN1_GENERALSTRING) *, sk), \
+ CHECKED_CAST(void *, ASN1_GENERALSTRING *, p)))
+
+#define sk_ASN1_GENERALSTRING_find(sk, out_index, p) \
+ sk_find(CHECKED_CAST(_STACK *, STACK_OF(ASN1_GENERALSTRING) *, sk), \
+ (out_index), CHECKED_CAST(void *, ASN1_GENERALSTRING *, p))
+
+#define sk_ASN1_GENERALSTRING_shift(sk) \
+ ((ASN1_GENERALSTRING *)sk_shift( \
+ CHECKED_CAST(_STACK *, STACK_OF(ASN1_GENERALSTRING) *, sk)))
+
+#define sk_ASN1_GENERALSTRING_push(sk, p) \
+ sk_push(CHECKED_CAST(_STACK *, STACK_OF(ASN1_GENERALSTRING) *, sk), \
+ CHECKED_CAST(void *, ASN1_GENERALSTRING *, p))
+
+#define sk_ASN1_GENERALSTRING_pop(sk) \
+ ((ASN1_GENERALSTRING *)sk_pop( \
+ CHECKED_CAST(_STACK *, STACK_OF(ASN1_GENERALSTRING) *, sk)))
+
+#define sk_ASN1_GENERALSTRING_dup(sk) \
+ ((STACK_OF(ASN1_GENERALSTRING) *)sk_dup( \
+ CHECKED_CAST(_STACK *, const STACK_OF(ASN1_GENERALSTRING) *, sk)))
+
+#define sk_ASN1_GENERALSTRING_sort(sk) \
+ sk_sort(CHECKED_CAST(_STACK *, STACK_OF(ASN1_GENERALSTRING) *, sk))
+
+#define sk_ASN1_GENERALSTRING_is_sorted(sk) \
+ sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(ASN1_GENERALSTRING) *, sk))
+
+#define sk_ASN1_GENERALSTRING_set_cmp_func(sk, comp) \
+ ((int (*)(const ASN1_GENERALSTRING **a, const ASN1_GENERALSTRING **b)) \
+ sk_set_cmp_func( \
+ CHECKED_CAST(_STACK *, STACK_OF(ASN1_GENERALSTRING) *, sk), \
+ CHECKED_CAST(stack_cmp_func, int (*)(const ASN1_GENERALSTRING **a, \
+ const ASN1_GENERALSTRING **b), \
+ comp)))
+
+
+/* ASN1_INTEGER */
+#define sk_ASN1_INTEGER_new(comp) \
+ ((STACK_OF(ASN1_INTEGER) *)sk_new(CHECKED_CAST( \
+ stack_cmp_func, int (*)(const ASN1_INTEGER **a, const ASN1_INTEGER **b), \
+ comp)))
+
+#define sk_ASN1_INTEGER_new_null() ((STACK_OF(ASN1_INTEGER) *)sk_new_null())
+
+#define sk_ASN1_INTEGER_num(sk) \
+ sk_num(CHECKED_CAST(_STACK *, STACK_OF(ASN1_INTEGER) *, sk))
+
+#define sk_ASN1_INTEGER_zero(sk) \
+ sk_zero(CHECKED_CAST(_STACK *, STACK_OF(ASN1_INTEGER) *, sk));
+
+#define sk_ASN1_INTEGER_value(sk, i) \
+ ((ASN1_INTEGER *)sk_value( \
+ CHECKED_CAST(_STACK *, const STACK_OF(ASN1_INTEGER) *, sk), (i)))
+
+#define sk_ASN1_INTEGER_set(sk, i, p) \
+ ((ASN1_INTEGER *)sk_set( \
+ CHECKED_CAST(_STACK *, STACK_OF(ASN1_INTEGER) *, sk), (i), \
+ CHECKED_CAST(void *, ASN1_INTEGER *, p)))
+
+#define sk_ASN1_INTEGER_free(sk) \
+ sk_free(CHECKED_CAST(_STACK *, STACK_OF(ASN1_INTEGER) *, sk))
+
+#define sk_ASN1_INTEGER_pop_free(sk, free_func) \
+ sk_pop_free( \
+ CHECKED_CAST(_STACK *, STACK_OF(ASN1_INTEGER) *, sk), \
+ CHECKED_CAST(void (*)(void *), void (*)(ASN1_INTEGER *), free_func))
+
+#define sk_ASN1_INTEGER_insert(sk, p, where) \
+ sk_insert(CHECKED_CAST(_STACK *, STACK_OF(ASN1_INTEGER) *, sk), \
+ CHECKED_CAST(void *, ASN1_INTEGER *, p), (where))
+
+#define sk_ASN1_INTEGER_delete(sk, where) \
+ ((ASN1_INTEGER *)sk_delete( \
+ CHECKED_CAST(_STACK *, STACK_OF(ASN1_INTEGER) *, sk), (where)))
+
+#define sk_ASN1_INTEGER_delete_ptr(sk, p) \
+ ((ASN1_INTEGER *)sk_delete_ptr( \
+ CHECKED_CAST(_STACK *, STACK_OF(ASN1_INTEGER) *, sk), \
+ CHECKED_CAST(void *, ASN1_INTEGER *, p)))
+
+#define sk_ASN1_INTEGER_find(sk, out_index, p) \
+ sk_find(CHECKED_CAST(_STACK *, STACK_OF(ASN1_INTEGER) *, sk), (out_index), \
+ CHECKED_CAST(void *, ASN1_INTEGER *, p))
+
+#define sk_ASN1_INTEGER_shift(sk) \
+ ((ASN1_INTEGER *)sk_shift( \
+ CHECKED_CAST(_STACK *, STACK_OF(ASN1_INTEGER) *, sk)))
+
+#define sk_ASN1_INTEGER_push(sk, p) \
+ sk_push(CHECKED_CAST(_STACK *, STACK_OF(ASN1_INTEGER) *, sk), \
+ CHECKED_CAST(void *, ASN1_INTEGER *, p))
+
+#define sk_ASN1_INTEGER_pop(sk) \
+ ((ASN1_INTEGER *)sk_pop(CHECKED_CAST(_STACK *, STACK_OF(ASN1_INTEGER) *, sk)))
+
+#define sk_ASN1_INTEGER_dup(sk) \
+ ((STACK_OF(ASN1_INTEGER) *)sk_dup( \
+ CHECKED_CAST(_STACK *, const STACK_OF(ASN1_INTEGER) *, sk)))
+
+#define sk_ASN1_INTEGER_sort(sk) \
+ sk_sort(CHECKED_CAST(_STACK *, STACK_OF(ASN1_INTEGER) *, sk))
+
+#define sk_ASN1_INTEGER_is_sorted(sk) \
+ sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(ASN1_INTEGER) *, sk))
+
+#define sk_ASN1_INTEGER_set_cmp_func(sk, comp) \
+ ((int (*)(const ASN1_INTEGER **a, const ASN1_INTEGER **b))sk_set_cmp_func( \
+ CHECKED_CAST(_STACK *, STACK_OF(ASN1_INTEGER) *, sk), \
+ CHECKED_CAST(stack_cmp_func, \
+ int (*)(const ASN1_INTEGER **a, const ASN1_INTEGER **b), \
+ comp)))
+
+
+/* ASN1_OBJECT */
+#define sk_ASN1_OBJECT_new(comp) \
+ ((STACK_OF(ASN1_OBJECT) *)sk_new(CHECKED_CAST( \
+ stack_cmp_func, int (*)(const ASN1_OBJECT **a, const ASN1_OBJECT **b), \
+ comp)))
+
+#define sk_ASN1_OBJECT_new_null() ((STACK_OF(ASN1_OBJECT) *)sk_new_null())
+
+#define sk_ASN1_OBJECT_num(sk) \
+ sk_num(CHECKED_CAST(_STACK *, STACK_OF(ASN1_OBJECT) *, sk))
+
+#define sk_ASN1_OBJECT_zero(sk) \
+ sk_zero(CHECKED_CAST(_STACK *, STACK_OF(ASN1_OBJECT) *, sk));
+
+#define sk_ASN1_OBJECT_value(sk, i) \
+ ((ASN1_OBJECT *)sk_value( \
+ CHECKED_CAST(_STACK *, const STACK_OF(ASN1_OBJECT) *, sk), (i)))
+
+#define sk_ASN1_OBJECT_set(sk, i, p) \
+ ((ASN1_OBJECT *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(ASN1_OBJECT) *, sk), \
+ (i), CHECKED_CAST(void *, ASN1_OBJECT *, p)))
+
+#define sk_ASN1_OBJECT_free(sk) \
+ sk_free(CHECKED_CAST(_STACK *, STACK_OF(ASN1_OBJECT) *, sk))
+
+#define sk_ASN1_OBJECT_pop_free(sk, free_func) \
+ sk_pop_free( \
+ CHECKED_CAST(_STACK *, STACK_OF(ASN1_OBJECT) *, sk), \
+ CHECKED_CAST(void (*)(void *), void (*)(ASN1_OBJECT *), free_func))
+
+#define sk_ASN1_OBJECT_insert(sk, p, where) \
+ sk_insert(CHECKED_CAST(_STACK *, STACK_OF(ASN1_OBJECT) *, sk), \
+ CHECKED_CAST(void *, ASN1_OBJECT *, p), (where))
+
+#define sk_ASN1_OBJECT_delete(sk, where) \
+ ((ASN1_OBJECT *)sk_delete( \
+ CHECKED_CAST(_STACK *, STACK_OF(ASN1_OBJECT) *, sk), (where)))
+
+#define sk_ASN1_OBJECT_delete_ptr(sk, p) \
+ ((ASN1_OBJECT *)sk_delete_ptr( \
+ CHECKED_CAST(_STACK *, STACK_OF(ASN1_OBJECT) *, sk), \
+ CHECKED_CAST(void *, ASN1_OBJECT *, p)))
+
+#define sk_ASN1_OBJECT_find(sk, out_index, p) \
+ sk_find(CHECKED_CAST(_STACK *, STACK_OF(ASN1_OBJECT) *, sk), (out_index), \
+ CHECKED_CAST(void *, ASN1_OBJECT *, p))
+
+#define sk_ASN1_OBJECT_shift(sk) \
+ ((ASN1_OBJECT *)sk_shift(CHECKED_CAST(_STACK *, STACK_OF(ASN1_OBJECT) *, sk)))
+
+#define sk_ASN1_OBJECT_push(sk, p) \
+ sk_push(CHECKED_CAST(_STACK *, STACK_OF(ASN1_OBJECT) *, sk), \
+ CHECKED_CAST(void *, ASN1_OBJECT *, p))
+
+#define sk_ASN1_OBJECT_pop(sk) \
+ ((ASN1_OBJECT *)sk_pop(CHECKED_CAST(_STACK *, STACK_OF(ASN1_OBJECT) *, sk)))
+
+#define sk_ASN1_OBJECT_dup(sk) \
+ ((STACK_OF(ASN1_OBJECT) *)sk_dup( \
+ CHECKED_CAST(_STACK *, const STACK_OF(ASN1_OBJECT) *, sk)))
+
+#define sk_ASN1_OBJECT_sort(sk) \
+ sk_sort(CHECKED_CAST(_STACK *, STACK_OF(ASN1_OBJECT) *, sk))
+
+#define sk_ASN1_OBJECT_is_sorted(sk) \
+ sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(ASN1_OBJECT) *, sk))
+
+#define sk_ASN1_OBJECT_set_cmp_func(sk, comp) \
+ ((int (*)(const ASN1_OBJECT **a, const ASN1_OBJECT **b))sk_set_cmp_func( \
+ CHECKED_CAST(_STACK *, STACK_OF(ASN1_OBJECT) *, sk), \
+ CHECKED_CAST(stack_cmp_func, \
+ int (*)(const ASN1_OBJECT **a, const ASN1_OBJECT **b), \
+ comp)))
+
+
+/* ASN1_STRING_TABLE */
+#define sk_ASN1_STRING_TABLE_new(comp) \
+ ((STACK_OF(ASN1_STRING_TABLE) *)sk_new(CHECKED_CAST( \
+ stack_cmp_func, \
+ int (*)(const ASN1_STRING_TABLE **a, const ASN1_STRING_TABLE **b), \
+ comp)))
+
+#define sk_ASN1_STRING_TABLE_new_null() \
+ ((STACK_OF(ASN1_STRING_TABLE) *)sk_new_null())
+
+#define sk_ASN1_STRING_TABLE_num(sk) \
+ sk_num(CHECKED_CAST(_STACK *, STACK_OF(ASN1_STRING_TABLE) *, sk))
+
+#define sk_ASN1_STRING_TABLE_zero(sk) \
+ sk_zero(CHECKED_CAST(_STACK *, STACK_OF(ASN1_STRING_TABLE) *, sk));
+
+#define sk_ASN1_STRING_TABLE_value(sk, i) \
+ ((ASN1_STRING_TABLE *)sk_value( \
+ CHECKED_CAST(_STACK *, const STACK_OF(ASN1_STRING_TABLE) *, sk), (i)))
+
+#define sk_ASN1_STRING_TABLE_set(sk, i, p) \
+ ((ASN1_STRING_TABLE *)sk_set( \
+ CHECKED_CAST(_STACK *, STACK_OF(ASN1_STRING_TABLE) *, sk), (i), \
+ CHECKED_CAST(void *, ASN1_STRING_TABLE *, p)))
+
+#define sk_ASN1_STRING_TABLE_free(sk) \
+ sk_free(CHECKED_CAST(_STACK *, STACK_OF(ASN1_STRING_TABLE) *, sk))
+
+#define sk_ASN1_STRING_TABLE_pop_free(sk, free_func) \
+ sk_pop_free(CHECKED_CAST(_STACK *, STACK_OF(ASN1_STRING_TABLE) *, sk), \
+ CHECKED_CAST(void (*)(void *), void (*)(ASN1_STRING_TABLE *), \
+ free_func))
+
+#define sk_ASN1_STRING_TABLE_insert(sk, p, where) \
+ sk_insert(CHECKED_CAST(_STACK *, STACK_OF(ASN1_STRING_TABLE) *, sk), \
+ CHECKED_CAST(void *, ASN1_STRING_TABLE *, p), (where))
+
+#define sk_ASN1_STRING_TABLE_delete(sk, where) \
+ ((ASN1_STRING_TABLE *)sk_delete( \
+ CHECKED_CAST(_STACK *, STACK_OF(ASN1_STRING_TABLE) *, sk), (where)))
+
+#define sk_ASN1_STRING_TABLE_delete_ptr(sk, p) \
+ ((ASN1_STRING_TABLE *)sk_delete_ptr( \
+ CHECKED_CAST(_STACK *, STACK_OF(ASN1_STRING_TABLE) *, sk), \
+ CHECKED_CAST(void *, ASN1_STRING_TABLE *, p)))
+
+#define sk_ASN1_STRING_TABLE_find(sk, out_index, p) \
+ sk_find(CHECKED_CAST(_STACK *, STACK_OF(ASN1_STRING_TABLE) *, sk), \
+ (out_index), CHECKED_CAST(void *, ASN1_STRING_TABLE *, p))
+
+#define sk_ASN1_STRING_TABLE_shift(sk) \
+ ((ASN1_STRING_TABLE *)sk_shift( \
+ CHECKED_CAST(_STACK *, STACK_OF(ASN1_STRING_TABLE) *, sk)))
+
+#define sk_ASN1_STRING_TABLE_push(sk, p) \
+ sk_push(CHECKED_CAST(_STACK *, STACK_OF(ASN1_STRING_TABLE) *, sk), \
+ CHECKED_CAST(void *, ASN1_STRING_TABLE *, p))
+
+#define sk_ASN1_STRING_TABLE_pop(sk) \
+ ((ASN1_STRING_TABLE *)sk_pop( \
+ CHECKED_CAST(_STACK *, STACK_OF(ASN1_STRING_TABLE) *, sk)))
+
+#define sk_ASN1_STRING_TABLE_dup(sk) \
+ ((STACK_OF(ASN1_STRING_TABLE) *)sk_dup( \
+ CHECKED_CAST(_STACK *, const STACK_OF(ASN1_STRING_TABLE) *, sk)))
+
+#define sk_ASN1_STRING_TABLE_sort(sk) \
+ sk_sort(CHECKED_CAST(_STACK *, STACK_OF(ASN1_STRING_TABLE) *, sk))
+
+#define sk_ASN1_STRING_TABLE_is_sorted(sk) \
+ sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(ASN1_STRING_TABLE) *, sk))
+
+#define sk_ASN1_STRING_TABLE_set_cmp_func(sk, comp) \
+ ((int (*)(const ASN1_STRING_TABLE **a, const ASN1_STRING_TABLE **b)) \
+ sk_set_cmp_func( \
+ CHECKED_CAST(_STACK *, STACK_OF(ASN1_STRING_TABLE) *, sk), \
+ CHECKED_CAST(stack_cmp_func, int (*)(const ASN1_STRING_TABLE **a, \
+ const ASN1_STRING_TABLE **b), \
+ comp)))
+
+
+/* ASN1_TYPE */
+#define sk_ASN1_TYPE_new(comp) \
+ ((STACK_OF(ASN1_TYPE) *)sk_new( \
+ CHECKED_CAST(stack_cmp_func, \
+ int (*)(const ASN1_TYPE **a, const ASN1_TYPE **b), comp)))
+
+#define sk_ASN1_TYPE_new_null() ((STACK_OF(ASN1_TYPE) *)sk_new_null())
+
+#define sk_ASN1_TYPE_num(sk) \
+ sk_num(CHECKED_CAST(_STACK *, STACK_OF(ASN1_TYPE) *, sk))
+
+#define sk_ASN1_TYPE_zero(sk) \
+ sk_zero(CHECKED_CAST(_STACK *, STACK_OF(ASN1_TYPE) *, sk));
+
+#define sk_ASN1_TYPE_value(sk, i) \
+ ((ASN1_TYPE *)sk_value( \
+ CHECKED_CAST(_STACK *, const STACK_OF(ASN1_TYPE) *, sk), (i)))
+
+#define sk_ASN1_TYPE_set(sk, i, p) \
+ ((ASN1_TYPE *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(ASN1_TYPE) *, sk), (i), \
+ CHECKED_CAST(void *, ASN1_TYPE *, p)))
+
+#define sk_ASN1_TYPE_free(sk) \
+ sk_free(CHECKED_CAST(_STACK *, STACK_OF(ASN1_TYPE) *, sk))
+
+#define sk_ASN1_TYPE_pop_free(sk, free_func) \
+ sk_pop_free( \
+ CHECKED_CAST(_STACK *, STACK_OF(ASN1_TYPE) *, sk), \
+ CHECKED_CAST(void (*)(void *), void (*)(ASN1_TYPE *), free_func))
+
+#define sk_ASN1_TYPE_insert(sk, p, where) \
+ sk_insert(CHECKED_CAST(_STACK *, STACK_OF(ASN1_TYPE) *, sk), \
+ CHECKED_CAST(void *, ASN1_TYPE *, p), (where))
+
+#define sk_ASN1_TYPE_delete(sk, where) \
+ ((ASN1_TYPE *)sk_delete(CHECKED_CAST(_STACK *, STACK_OF(ASN1_TYPE) *, sk), \
+ (where)))
+
+#define sk_ASN1_TYPE_delete_ptr(sk, p) \
+ ((ASN1_TYPE *)sk_delete_ptr( \
+ CHECKED_CAST(_STACK *, STACK_OF(ASN1_TYPE) *, sk), \
+ CHECKED_CAST(void *, ASN1_TYPE *, p)))
+
+#define sk_ASN1_TYPE_find(sk, out_index, p) \
+ sk_find(CHECKED_CAST(_STACK *, STACK_OF(ASN1_TYPE) *, sk), (out_index), \
+ CHECKED_CAST(void *, ASN1_TYPE *, p))
+
+#define sk_ASN1_TYPE_shift(sk) \
+ ((ASN1_TYPE *)sk_shift(CHECKED_CAST(_STACK *, STACK_OF(ASN1_TYPE) *, sk)))
+
+#define sk_ASN1_TYPE_push(sk, p) \
+ sk_push(CHECKED_CAST(_STACK *, STACK_OF(ASN1_TYPE) *, sk), \
+ CHECKED_CAST(void *, ASN1_TYPE *, p))
+
+#define sk_ASN1_TYPE_pop(sk) \
+ ((ASN1_TYPE *)sk_pop(CHECKED_CAST(_STACK *, STACK_OF(ASN1_TYPE) *, sk)))
+
+#define sk_ASN1_TYPE_dup(sk) \
+ ((STACK_OF(ASN1_TYPE) *)sk_dup( \
+ CHECKED_CAST(_STACK *, const STACK_OF(ASN1_TYPE) *, sk)))
+
+#define sk_ASN1_TYPE_sort(sk) \
+ sk_sort(CHECKED_CAST(_STACK *, STACK_OF(ASN1_TYPE) *, sk))
+
+#define sk_ASN1_TYPE_is_sorted(sk) \
+ sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(ASN1_TYPE) *, sk))
+
+#define sk_ASN1_TYPE_set_cmp_func(sk, comp) \
+ ((int (*)(const ASN1_TYPE **a, const ASN1_TYPE **b))sk_set_cmp_func( \
+ CHECKED_CAST(_STACK *, STACK_OF(ASN1_TYPE) *, sk), \
+ CHECKED_CAST(stack_cmp_func, \
+ int (*)(const ASN1_TYPE **a, const ASN1_TYPE **b), comp)))
+
+
+/* ASN1_VALUE */
+#define sk_ASN1_VALUE_new(comp) \
+ ((STACK_OF(ASN1_VALUE) *)sk_new(CHECKED_CAST( \
+ stack_cmp_func, int (*)(const ASN1_VALUE **a, const ASN1_VALUE **b), \
+ comp)))
+
+#define sk_ASN1_VALUE_new_null() ((STACK_OF(ASN1_VALUE) *)sk_new_null())
+
+#define sk_ASN1_VALUE_num(sk) \
+ sk_num(CHECKED_CAST(_STACK *, STACK_OF(ASN1_VALUE) *, sk))
+
+#define sk_ASN1_VALUE_zero(sk) \
+ sk_zero(CHECKED_CAST(_STACK *, STACK_OF(ASN1_VALUE) *, sk));
+
+#define sk_ASN1_VALUE_value(sk, i) \
+ ((ASN1_VALUE *)sk_value( \
+ CHECKED_CAST(_STACK *, const STACK_OF(ASN1_VALUE) *, sk), (i)))
+
+#define sk_ASN1_VALUE_set(sk, i, p) \
+ ((ASN1_VALUE *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(ASN1_VALUE) *, sk), \
+ (i), CHECKED_CAST(void *, ASN1_VALUE *, p)))
+
+#define sk_ASN1_VALUE_free(sk) \
+ sk_free(CHECKED_CAST(_STACK *, STACK_OF(ASN1_VALUE) *, sk))
+
+#define sk_ASN1_VALUE_pop_free(sk, free_func) \
+ sk_pop_free( \
+ CHECKED_CAST(_STACK *, STACK_OF(ASN1_VALUE) *, sk), \
+ CHECKED_CAST(void (*)(void *), void (*)(ASN1_VALUE *), free_func))
+
+#define sk_ASN1_VALUE_insert(sk, p, where) \
+ sk_insert(CHECKED_CAST(_STACK *, STACK_OF(ASN1_VALUE) *, sk), \
+ CHECKED_CAST(void *, ASN1_VALUE *, p), (where))
+
+#define sk_ASN1_VALUE_delete(sk, where) \
+ ((ASN1_VALUE *)sk_delete(CHECKED_CAST(_STACK *, STACK_OF(ASN1_VALUE) *, sk), \
+ (where)))
+
+#define sk_ASN1_VALUE_delete_ptr(sk, p) \
+ ((ASN1_VALUE *)sk_delete_ptr( \
+ CHECKED_CAST(_STACK *, STACK_OF(ASN1_VALUE) *, sk), \
+ CHECKED_CAST(void *, ASN1_VALUE *, p)))
+
+#define sk_ASN1_VALUE_find(sk, out_index, p) \
+ sk_find(CHECKED_CAST(_STACK *, STACK_OF(ASN1_VALUE) *, sk), (out_index), \
+ CHECKED_CAST(void *, ASN1_VALUE *, p))
+
+#define sk_ASN1_VALUE_shift(sk) \
+ ((ASN1_VALUE *)sk_shift(CHECKED_CAST(_STACK *, STACK_OF(ASN1_VALUE) *, sk)))
+
+#define sk_ASN1_VALUE_push(sk, p) \
+ sk_push(CHECKED_CAST(_STACK *, STACK_OF(ASN1_VALUE) *, sk), \
+ CHECKED_CAST(void *, ASN1_VALUE *, p))
+
+#define sk_ASN1_VALUE_pop(sk) \
+ ((ASN1_VALUE *)sk_pop(CHECKED_CAST(_STACK *, STACK_OF(ASN1_VALUE) *, sk)))
+
+#define sk_ASN1_VALUE_dup(sk) \
+ ((STACK_OF(ASN1_VALUE) *)sk_dup( \
+ CHECKED_CAST(_STACK *, const STACK_OF(ASN1_VALUE) *, sk)))
+
+#define sk_ASN1_VALUE_sort(sk) \
+ sk_sort(CHECKED_CAST(_STACK *, STACK_OF(ASN1_VALUE) *, sk))
+
+#define sk_ASN1_VALUE_is_sorted(sk) \
+ sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(ASN1_VALUE) *, sk))
+
+#define sk_ASN1_VALUE_set_cmp_func(sk, comp) \
+ ((int (*)(const ASN1_VALUE **a, const ASN1_VALUE **b))sk_set_cmp_func( \
+ CHECKED_CAST(_STACK *, STACK_OF(ASN1_VALUE) *, sk), \
+ CHECKED_CAST(stack_cmp_func, \
+ int (*)(const ASN1_VALUE **a, const ASN1_VALUE **b), \
+ comp)))
+
+
+/* BIO */
+#define sk_BIO_new(comp) \
+ ((STACK_OF(BIO) *)sk_new(CHECKED_CAST( \
+ stack_cmp_func, int (*)(const BIO **a, const BIO **b), comp)))
+
+#define sk_BIO_new_null() ((STACK_OF(BIO) *)sk_new_null())
+
+#define sk_BIO_num(sk) sk_num(CHECKED_CAST(_STACK *, STACK_OF(BIO) *, sk))
+
+#define sk_BIO_zero(sk) sk_zero(CHECKED_CAST(_STACK *, STACK_OF(BIO) *, sk));
+
+#define sk_BIO_value(sk, i) \
+ ((BIO *)sk_value(CHECKED_CAST(_STACK *, const STACK_OF(BIO) *, sk), (i)))
+
+#define sk_BIO_set(sk, i, p) \
+ ((BIO *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(BIO) *, sk), (i), \
+ CHECKED_CAST(void *, BIO *, p)))
+
+#define sk_BIO_free(sk) sk_free(CHECKED_CAST(_STACK *, STACK_OF(BIO) *, sk))
+
+#define sk_BIO_pop_free(sk, free_func) \
+ sk_pop_free(CHECKED_CAST(_STACK *, STACK_OF(BIO) *, sk), \
+ CHECKED_CAST(void (*)(void *), void (*)(BIO *), free_func))
+
+#define sk_BIO_insert(sk, p, where) \
+ sk_insert(CHECKED_CAST(_STACK *, STACK_OF(BIO) *, sk), \
+ CHECKED_CAST(void *, BIO *, p), (where))
+
+#define sk_BIO_delete(sk, where) \
+ ((BIO *)sk_delete(CHECKED_CAST(_STACK *, STACK_OF(BIO) *, sk), (where)))
+
+#define sk_BIO_delete_ptr(sk, p) \
+ ((BIO *)sk_delete_ptr(CHECKED_CAST(_STACK *, STACK_OF(BIO) *, sk), \
+ CHECKED_CAST(void *, BIO *, p)))
+
+#define sk_BIO_find(sk, out_index, p) \
+ sk_find(CHECKED_CAST(_STACK *, STACK_OF(BIO) *, sk), (out_index), \
+ CHECKED_CAST(void *, BIO *, p))
+
+#define sk_BIO_shift(sk) \
+ ((BIO *)sk_shift(CHECKED_CAST(_STACK *, STACK_OF(BIO) *, sk)))
+
+#define sk_BIO_push(sk, p) \
+ sk_push(CHECKED_CAST(_STACK *, STACK_OF(BIO) *, sk), \
+ CHECKED_CAST(void *, BIO *, p))
+
+#define sk_BIO_pop(sk) \
+ ((BIO *)sk_pop(CHECKED_CAST(_STACK *, STACK_OF(BIO) *, sk)))
+
+#define sk_BIO_dup(sk) \
+ ((STACK_OF(BIO) *)sk_dup(CHECKED_CAST(_STACK *, const STACK_OF(BIO) *, sk)))
+
+#define sk_BIO_sort(sk) sk_sort(CHECKED_CAST(_STACK *, STACK_OF(BIO) *, sk))
+
+#define sk_BIO_is_sorted(sk) \
+ sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(BIO) *, sk))
+
+#define sk_BIO_set_cmp_func(sk, comp) \
+ ((int (*)(const BIO **a, const BIO **b))sk_set_cmp_func( \
+ CHECKED_CAST(_STACK *, STACK_OF(BIO) *, sk), \
+ CHECKED_CAST(stack_cmp_func, int (*)(const BIO **a, const BIO **b), \
+ comp)))
+
+
+/* BY_DIR_ENTRY */
+#define sk_BY_DIR_ENTRY_new(comp) \
+ ((STACK_OF(BY_DIR_ENTRY) *)sk_new(CHECKED_CAST( \
+ stack_cmp_func, int (*)(const BY_DIR_ENTRY **a, const BY_DIR_ENTRY **b), \
+ comp)))
+
+#define sk_BY_DIR_ENTRY_new_null() ((STACK_OF(BY_DIR_ENTRY) *)sk_new_null())
+
+#define sk_BY_DIR_ENTRY_num(sk) \
+ sk_num(CHECKED_CAST(_STACK *, STACK_OF(BY_DIR_ENTRY) *, sk))
+
+#define sk_BY_DIR_ENTRY_zero(sk) \
+ sk_zero(CHECKED_CAST(_STACK *, STACK_OF(BY_DIR_ENTRY) *, sk));
+
+#define sk_BY_DIR_ENTRY_value(sk, i) \
+ ((BY_DIR_ENTRY *)sk_value( \
+ CHECKED_CAST(_STACK *, const STACK_OF(BY_DIR_ENTRY) *, sk), (i)))
+
+#define sk_BY_DIR_ENTRY_set(sk, i, p) \
+ ((BY_DIR_ENTRY *)sk_set( \
+ CHECKED_CAST(_STACK *, STACK_OF(BY_DIR_ENTRY) *, sk), (i), \
+ CHECKED_CAST(void *, BY_DIR_ENTRY *, p)))
+
+#define sk_BY_DIR_ENTRY_free(sk) \
+ sk_free(CHECKED_CAST(_STACK *, STACK_OF(BY_DIR_ENTRY) *, sk))
+
+#define sk_BY_DIR_ENTRY_pop_free(sk, free_func) \
+ sk_pop_free( \
+ CHECKED_CAST(_STACK *, STACK_OF(BY_DIR_ENTRY) *, sk), \
+ CHECKED_CAST(void (*)(void *), void (*)(BY_DIR_ENTRY *), free_func))
+
+#define sk_BY_DIR_ENTRY_insert(sk, p, where) \
+ sk_insert(CHECKED_CAST(_STACK *, STACK_OF(BY_DIR_ENTRY) *, sk), \
+ CHECKED_CAST(void *, BY_DIR_ENTRY *, p), (where))
+
+#define sk_BY_DIR_ENTRY_delete(sk, where) \
+ ((BY_DIR_ENTRY *)sk_delete( \
+ CHECKED_CAST(_STACK *, STACK_OF(BY_DIR_ENTRY) *, sk), (where)))
+
+#define sk_BY_DIR_ENTRY_delete_ptr(sk, p) \
+ ((BY_DIR_ENTRY *)sk_delete_ptr( \
+ CHECKED_CAST(_STACK *, STACK_OF(BY_DIR_ENTRY) *, sk), \
+ CHECKED_CAST(void *, BY_DIR_ENTRY *, p)))
+
+#define sk_BY_DIR_ENTRY_find(sk, out_index, p) \
+ sk_find(CHECKED_CAST(_STACK *, STACK_OF(BY_DIR_ENTRY) *, sk), (out_index), \
+ CHECKED_CAST(void *, BY_DIR_ENTRY *, p))
+
+#define sk_BY_DIR_ENTRY_shift(sk) \
+ ((BY_DIR_ENTRY *)sk_shift( \
+ CHECKED_CAST(_STACK *, STACK_OF(BY_DIR_ENTRY) *, sk)))
+
+#define sk_BY_DIR_ENTRY_push(sk, p) \
+ sk_push(CHECKED_CAST(_STACK *, STACK_OF(BY_DIR_ENTRY) *, sk), \
+ CHECKED_CAST(void *, BY_DIR_ENTRY *, p))
+
+#define sk_BY_DIR_ENTRY_pop(sk) \
+ ((BY_DIR_ENTRY *)sk_pop(CHECKED_CAST(_STACK *, STACK_OF(BY_DIR_ENTRY) *, sk)))
+
+#define sk_BY_DIR_ENTRY_dup(sk) \
+ ((STACK_OF(BY_DIR_ENTRY) *)sk_dup( \
+ CHECKED_CAST(_STACK *, const STACK_OF(BY_DIR_ENTRY) *, sk)))
+
+#define sk_BY_DIR_ENTRY_sort(sk) \
+ sk_sort(CHECKED_CAST(_STACK *, STACK_OF(BY_DIR_ENTRY) *, sk))
+
+#define sk_BY_DIR_ENTRY_is_sorted(sk) \
+ sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(BY_DIR_ENTRY) *, sk))
+
+#define sk_BY_DIR_ENTRY_set_cmp_func(sk, comp) \
+ ((int (*)(const BY_DIR_ENTRY **a, const BY_DIR_ENTRY **b))sk_set_cmp_func( \
+ CHECKED_CAST(_STACK *, STACK_OF(BY_DIR_ENTRY) *, sk), \
+ CHECKED_CAST(stack_cmp_func, \
+ int (*)(const BY_DIR_ENTRY **a, const BY_DIR_ENTRY **b), \
+ comp)))
+
+
+/* BY_DIR_HASH */
+#define sk_BY_DIR_HASH_new(comp) \
+ ((STACK_OF(BY_DIR_HASH) *)sk_new(CHECKED_CAST( \
+ stack_cmp_func, int (*)(const BY_DIR_HASH **a, const BY_DIR_HASH **b), \
+ comp)))
+
+#define sk_BY_DIR_HASH_new_null() ((STACK_OF(BY_DIR_HASH) *)sk_new_null())
+
+#define sk_BY_DIR_HASH_num(sk) \
+ sk_num(CHECKED_CAST(_STACK *, STACK_OF(BY_DIR_HASH) *, sk))
+
+#define sk_BY_DIR_HASH_zero(sk) \
+ sk_zero(CHECKED_CAST(_STACK *, STACK_OF(BY_DIR_HASH) *, sk));
+
+#define sk_BY_DIR_HASH_value(sk, i) \
+ ((BY_DIR_HASH *)sk_value( \
+ CHECKED_CAST(_STACK *, const STACK_OF(BY_DIR_HASH) *, sk), (i)))
+
+#define sk_BY_DIR_HASH_set(sk, i, p) \
+ ((BY_DIR_HASH *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(BY_DIR_HASH) *, sk), \
+ (i), CHECKED_CAST(void *, BY_DIR_HASH *, p)))
+
+#define sk_BY_DIR_HASH_free(sk) \
+ sk_free(CHECKED_CAST(_STACK *, STACK_OF(BY_DIR_HASH) *, sk))
+
+#define sk_BY_DIR_HASH_pop_free(sk, free_func) \
+ sk_pop_free( \
+ CHECKED_CAST(_STACK *, STACK_OF(BY_DIR_HASH) *, sk), \
+ CHECKED_CAST(void (*)(void *), void (*)(BY_DIR_HASH *), free_func))
+
+#define sk_BY_DIR_HASH_insert(sk, p, where) \
+ sk_insert(CHECKED_CAST(_STACK *, STACK_OF(BY_DIR_HASH) *, sk), \
+ CHECKED_CAST(void *, BY_DIR_HASH *, p), (where))
+
+#define sk_BY_DIR_HASH_delete(sk, where) \
+ ((BY_DIR_HASH *)sk_delete( \
+ CHECKED_CAST(_STACK *, STACK_OF(BY_DIR_HASH) *, sk), (where)))
+
+#define sk_BY_DIR_HASH_delete_ptr(sk, p) \
+ ((BY_DIR_HASH *)sk_delete_ptr( \
+ CHECKED_CAST(_STACK *, STACK_OF(BY_DIR_HASH) *, sk), \
+ CHECKED_CAST(void *, BY_DIR_HASH *, p)))
+
+#define sk_BY_DIR_HASH_find(sk, out_index, p) \
+ sk_find(CHECKED_CAST(_STACK *, STACK_OF(BY_DIR_HASH) *, sk), (out_index), \
+ CHECKED_CAST(void *, BY_DIR_HASH *, p))
+
+#define sk_BY_DIR_HASH_shift(sk) \
+ ((BY_DIR_HASH *)sk_shift(CHECKED_CAST(_STACK *, STACK_OF(BY_DIR_HASH) *, sk)))
+
+#define sk_BY_DIR_HASH_push(sk, p) \
+ sk_push(CHECKED_CAST(_STACK *, STACK_OF(BY_DIR_HASH) *, sk), \
+ CHECKED_CAST(void *, BY_DIR_HASH *, p))
+
+#define sk_BY_DIR_HASH_pop(sk) \
+ ((BY_DIR_HASH *)sk_pop(CHECKED_CAST(_STACK *, STACK_OF(BY_DIR_HASH) *, sk)))
+
+#define sk_BY_DIR_HASH_dup(sk) \
+ ((STACK_OF(BY_DIR_HASH) *)sk_dup( \
+ CHECKED_CAST(_STACK *, const STACK_OF(BY_DIR_HASH) *, sk)))
+
+#define sk_BY_DIR_HASH_sort(sk) \
+ sk_sort(CHECKED_CAST(_STACK *, STACK_OF(BY_DIR_HASH) *, sk))
+
+#define sk_BY_DIR_HASH_is_sorted(sk) \
+ sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(BY_DIR_HASH) *, sk))
+
+#define sk_BY_DIR_HASH_set_cmp_func(sk, comp) \
+ ((int (*)(const BY_DIR_HASH **a, const BY_DIR_HASH **b))sk_set_cmp_func( \
+ CHECKED_CAST(_STACK *, STACK_OF(BY_DIR_HASH) *, sk), \
+ CHECKED_CAST(stack_cmp_func, \
+ int (*)(const BY_DIR_HASH **a, const BY_DIR_HASH **b), \
+ comp)))
+
+
+/* CONF_VALUE */
+#define sk_CONF_VALUE_new(comp) \
+ ((STACK_OF(CONF_VALUE) *)sk_new(CHECKED_CAST( \
+ stack_cmp_func, int (*)(const CONF_VALUE **a, const CONF_VALUE **b), \
+ comp)))
+
+#define sk_CONF_VALUE_new_null() ((STACK_OF(CONF_VALUE) *)sk_new_null())
+
+#define sk_CONF_VALUE_num(sk) \
+ sk_num(CHECKED_CAST(_STACK *, STACK_OF(CONF_VALUE) *, sk))
+
+#define sk_CONF_VALUE_zero(sk) \
+ sk_zero(CHECKED_CAST(_STACK *, STACK_OF(CONF_VALUE) *, sk));
+
+#define sk_CONF_VALUE_value(sk, i) \
+ ((CONF_VALUE *)sk_value( \
+ CHECKED_CAST(_STACK *, const STACK_OF(CONF_VALUE) *, sk), (i)))
+
+#define sk_CONF_VALUE_set(sk, i, p) \
+ ((CONF_VALUE *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(CONF_VALUE) *, sk), \
+ (i), CHECKED_CAST(void *, CONF_VALUE *, p)))
+
+#define sk_CONF_VALUE_free(sk) \
+ sk_free(CHECKED_CAST(_STACK *, STACK_OF(CONF_VALUE) *, sk))
+
+#define sk_CONF_VALUE_pop_free(sk, free_func) \
+ sk_pop_free( \
+ CHECKED_CAST(_STACK *, STACK_OF(CONF_VALUE) *, sk), \
+ CHECKED_CAST(void (*)(void *), void (*)(CONF_VALUE *), free_func))
+
+#define sk_CONF_VALUE_insert(sk, p, where) \
+ sk_insert(CHECKED_CAST(_STACK *, STACK_OF(CONF_VALUE) *, sk), \
+ CHECKED_CAST(void *, CONF_VALUE *, p), (where))
+
+#define sk_CONF_VALUE_delete(sk, where) \
+ ((CONF_VALUE *)sk_delete(CHECKED_CAST(_STACK *, STACK_OF(CONF_VALUE) *, sk), \
+ (where)))
+
+#define sk_CONF_VALUE_delete_ptr(sk, p) \
+ ((CONF_VALUE *)sk_delete_ptr( \
+ CHECKED_CAST(_STACK *, STACK_OF(CONF_VALUE) *, sk), \
+ CHECKED_CAST(void *, CONF_VALUE *, p)))
+
+#define sk_CONF_VALUE_find(sk, out_index, p) \
+ sk_find(CHECKED_CAST(_STACK *, STACK_OF(CONF_VALUE) *, sk), (out_index), \
+ CHECKED_CAST(void *, CONF_VALUE *, p))
+
+#define sk_CONF_VALUE_shift(sk) \
+ ((CONF_VALUE *)sk_shift(CHECKED_CAST(_STACK *, STACK_OF(CONF_VALUE) *, sk)))
+
+#define sk_CONF_VALUE_push(sk, p) \
+ sk_push(CHECKED_CAST(_STACK *, STACK_OF(CONF_VALUE) *, sk), \
+ CHECKED_CAST(void *, CONF_VALUE *, p))
+
+#define sk_CONF_VALUE_pop(sk) \
+ ((CONF_VALUE *)sk_pop(CHECKED_CAST(_STACK *, STACK_OF(CONF_VALUE) *, sk)))
+
+#define sk_CONF_VALUE_dup(sk) \
+ ((STACK_OF(CONF_VALUE) *)sk_dup( \
+ CHECKED_CAST(_STACK *, const STACK_OF(CONF_VALUE) *, sk)))
+
+#define sk_CONF_VALUE_sort(sk) \
+ sk_sort(CHECKED_CAST(_STACK *, STACK_OF(CONF_VALUE) *, sk))
+
+#define sk_CONF_VALUE_is_sorted(sk) \
+ sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(CONF_VALUE) *, sk))
+
+#define sk_CONF_VALUE_set_cmp_func(sk, comp) \
+ ((int (*)(const CONF_VALUE **a, const CONF_VALUE **b))sk_set_cmp_func( \
+ CHECKED_CAST(_STACK *, STACK_OF(CONF_VALUE) *, sk), \
+ CHECKED_CAST(stack_cmp_func, \
+ int (*)(const CONF_VALUE **a, const CONF_VALUE **b), \
+ comp)))
+
+
+/* CRYPTO_EX_DATA_FUNCS */
+#define sk_CRYPTO_EX_DATA_FUNCS_new(comp) \
+ ((STACK_OF(CRYPTO_EX_DATA_FUNCS) *)sk_new(CHECKED_CAST( \
+ stack_cmp_func, \
+ int (*)(const CRYPTO_EX_DATA_FUNCS **a, const CRYPTO_EX_DATA_FUNCS **b), \
+ comp)))
+
+#define sk_CRYPTO_EX_DATA_FUNCS_new_null() \
+ ((STACK_OF(CRYPTO_EX_DATA_FUNCS) *)sk_new_null())
+
+#define sk_CRYPTO_EX_DATA_FUNCS_num(sk) \
+ sk_num(CHECKED_CAST(_STACK *, STACK_OF(CRYPTO_EX_DATA_FUNCS) *, sk))
+
+#define sk_CRYPTO_EX_DATA_FUNCS_zero(sk) \
+ sk_zero(CHECKED_CAST(_STACK *, STACK_OF(CRYPTO_EX_DATA_FUNCS) *, sk));
+
+#define sk_CRYPTO_EX_DATA_FUNCS_value(sk, i) \
+ ((CRYPTO_EX_DATA_FUNCS *)sk_value( \
+ CHECKED_CAST(_STACK *, const STACK_OF(CRYPTO_EX_DATA_FUNCS) *, sk), \
+ (i)))
+
+#define sk_CRYPTO_EX_DATA_FUNCS_set(sk, i, p) \
+ ((CRYPTO_EX_DATA_FUNCS *)sk_set( \
+ CHECKED_CAST(_STACK *, STACK_OF(CRYPTO_EX_DATA_FUNCS) *, sk), (i), \
+ CHECKED_CAST(void *, CRYPTO_EX_DATA_FUNCS *, p)))
+
+#define sk_CRYPTO_EX_DATA_FUNCS_free(sk) \
+ sk_free(CHECKED_CAST(_STACK *, STACK_OF(CRYPTO_EX_DATA_FUNCS) *, sk))
+
+#define sk_CRYPTO_EX_DATA_FUNCS_pop_free(sk, free_func) \
+ sk_pop_free(CHECKED_CAST(_STACK *, STACK_OF(CRYPTO_EX_DATA_FUNCS) *, sk), \
+ CHECKED_CAST(void (*)(void *), void (*)(CRYPTO_EX_DATA_FUNCS *), \
+ free_func))
+
+#define sk_CRYPTO_EX_DATA_FUNCS_insert(sk, p, where) \
+ sk_insert(CHECKED_CAST(_STACK *, STACK_OF(CRYPTO_EX_DATA_FUNCS) *, sk), \
+ CHECKED_CAST(void *, CRYPTO_EX_DATA_FUNCS *, p), (where))
+
+#define sk_CRYPTO_EX_DATA_FUNCS_delete(sk, where) \
+ ((CRYPTO_EX_DATA_FUNCS *)sk_delete( \
+ CHECKED_CAST(_STACK *, STACK_OF(CRYPTO_EX_DATA_FUNCS) *, sk), (where)))
+
+#define sk_CRYPTO_EX_DATA_FUNCS_delete_ptr(sk, p) \
+ ((CRYPTO_EX_DATA_FUNCS *)sk_delete_ptr( \
+ CHECKED_CAST(_STACK *, STACK_OF(CRYPTO_EX_DATA_FUNCS) *, sk), \
+ CHECKED_CAST(void *, CRYPTO_EX_DATA_FUNCS *, p)))
+
+#define sk_CRYPTO_EX_DATA_FUNCS_find(sk, out_index, p) \
+ sk_find(CHECKED_CAST(_STACK *, STACK_OF(CRYPTO_EX_DATA_FUNCS) *, sk), \
+ (out_index), CHECKED_CAST(void *, CRYPTO_EX_DATA_FUNCS *, p))
+
+#define sk_CRYPTO_EX_DATA_FUNCS_shift(sk) \
+ ((CRYPTO_EX_DATA_FUNCS *)sk_shift( \
+ CHECKED_CAST(_STACK *, STACK_OF(CRYPTO_EX_DATA_FUNCS) *, sk)))
+
+#define sk_CRYPTO_EX_DATA_FUNCS_push(sk, p) \
+ sk_push(CHECKED_CAST(_STACK *, STACK_OF(CRYPTO_EX_DATA_FUNCS) *, sk), \
+ CHECKED_CAST(void *, CRYPTO_EX_DATA_FUNCS *, p))
+
+#define sk_CRYPTO_EX_DATA_FUNCS_pop(sk) \
+ ((CRYPTO_EX_DATA_FUNCS *)sk_pop( \
+ CHECKED_CAST(_STACK *, STACK_OF(CRYPTO_EX_DATA_FUNCS) *, sk)))
+
+#define sk_CRYPTO_EX_DATA_FUNCS_dup(sk) \
+ ((STACK_OF(CRYPTO_EX_DATA_FUNCS) *)sk_dup( \
+ CHECKED_CAST(_STACK *, const STACK_OF(CRYPTO_EX_DATA_FUNCS) *, sk)))
+
+#define sk_CRYPTO_EX_DATA_FUNCS_sort(sk) \
+ sk_sort(CHECKED_CAST(_STACK *, STACK_OF(CRYPTO_EX_DATA_FUNCS) *, sk))
+
+#define sk_CRYPTO_EX_DATA_FUNCS_is_sorted(sk) \
+ sk_is_sorted( \
+ CHECKED_CAST(_STACK *, const STACK_OF(CRYPTO_EX_DATA_FUNCS) *, sk))
+
+#define sk_CRYPTO_EX_DATA_FUNCS_set_cmp_func(sk, comp) \
+ ((int (*)(const CRYPTO_EX_DATA_FUNCS **a, const CRYPTO_EX_DATA_FUNCS **b)) \
+ sk_set_cmp_func( \
+ CHECKED_CAST(_STACK *, STACK_OF(CRYPTO_EX_DATA_FUNCS) *, sk), \
+ CHECKED_CAST(stack_cmp_func, int (*)(const CRYPTO_EX_DATA_FUNCS **a, \
+ const CRYPTO_EX_DATA_FUNCS **b), \
+ comp)))
+
+
+/* DIST_POINT */
+#define sk_DIST_POINT_new(comp) \
+ ((STACK_OF(DIST_POINT) *)sk_new(CHECKED_CAST( \
+ stack_cmp_func, int (*)(const DIST_POINT **a, const DIST_POINT **b), \
+ comp)))
+
+#define sk_DIST_POINT_new_null() ((STACK_OF(DIST_POINT) *)sk_new_null())
+
+#define sk_DIST_POINT_num(sk) \
+ sk_num(CHECKED_CAST(_STACK *, STACK_OF(DIST_POINT) *, sk))
+
+#define sk_DIST_POINT_zero(sk) \
+ sk_zero(CHECKED_CAST(_STACK *, STACK_OF(DIST_POINT) *, sk));
+
+#define sk_DIST_POINT_value(sk, i) \
+ ((DIST_POINT *)sk_value( \
+ CHECKED_CAST(_STACK *, const STACK_OF(DIST_POINT) *, sk), (i)))
+
+#define sk_DIST_POINT_set(sk, i, p) \
+ ((DIST_POINT *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(DIST_POINT) *, sk), \
+ (i), CHECKED_CAST(void *, DIST_POINT *, p)))
+
+#define sk_DIST_POINT_free(sk) \
+ sk_free(CHECKED_CAST(_STACK *, STACK_OF(DIST_POINT) *, sk))
+
+#define sk_DIST_POINT_pop_free(sk, free_func) \
+ sk_pop_free( \
+ CHECKED_CAST(_STACK *, STACK_OF(DIST_POINT) *, sk), \
+ CHECKED_CAST(void (*)(void *), void (*)(DIST_POINT *), free_func))
+
+#define sk_DIST_POINT_insert(sk, p, where) \
+ sk_insert(CHECKED_CAST(_STACK *, STACK_OF(DIST_POINT) *, sk), \
+ CHECKED_CAST(void *, DIST_POINT *, p), (where))
+
+#define sk_DIST_POINT_delete(sk, where) \
+ ((DIST_POINT *)sk_delete(CHECKED_CAST(_STACK *, STACK_OF(DIST_POINT) *, sk), \
+ (where)))
+
+#define sk_DIST_POINT_delete_ptr(sk, p) \
+ ((DIST_POINT *)sk_delete_ptr( \
+ CHECKED_CAST(_STACK *, STACK_OF(DIST_POINT) *, sk), \
+ CHECKED_CAST(void *, DIST_POINT *, p)))
+
+#define sk_DIST_POINT_find(sk, out_index, p) \
+ sk_find(CHECKED_CAST(_STACK *, STACK_OF(DIST_POINT) *, sk), (out_index), \
+ CHECKED_CAST(void *, DIST_POINT *, p))
+
+#define sk_DIST_POINT_shift(sk) \
+ ((DIST_POINT *)sk_shift(CHECKED_CAST(_STACK *, STACK_OF(DIST_POINT) *, sk)))
+
+#define sk_DIST_POINT_push(sk, p) \
+ sk_push(CHECKED_CAST(_STACK *, STACK_OF(DIST_POINT) *, sk), \
+ CHECKED_CAST(void *, DIST_POINT *, p))
+
+#define sk_DIST_POINT_pop(sk) \
+ ((DIST_POINT *)sk_pop(CHECKED_CAST(_STACK *, STACK_OF(DIST_POINT) *, sk)))
+
+#define sk_DIST_POINT_dup(sk) \
+ ((STACK_OF(DIST_POINT) *)sk_dup( \
+ CHECKED_CAST(_STACK *, const STACK_OF(DIST_POINT) *, sk)))
+
+#define sk_DIST_POINT_sort(sk) \
+ sk_sort(CHECKED_CAST(_STACK *, STACK_OF(DIST_POINT) *, sk))
+
+#define sk_DIST_POINT_is_sorted(sk) \
+ sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(DIST_POINT) *, sk))
+
+#define sk_DIST_POINT_set_cmp_func(sk, comp) \
+ ((int (*)(const DIST_POINT **a, const DIST_POINT **b))sk_set_cmp_func( \
+ CHECKED_CAST(_STACK *, STACK_OF(DIST_POINT) *, sk), \
+ CHECKED_CAST(stack_cmp_func, \
+ int (*)(const DIST_POINT **a, const DIST_POINT **b), \
+ comp)))
+
+
+/* GENERAL_NAME */
+#define sk_GENERAL_NAME_new(comp) \
+ ((STACK_OF(GENERAL_NAME) *)sk_new(CHECKED_CAST( \
+ stack_cmp_func, int (*)(const GENERAL_NAME **a, const GENERAL_NAME **b), \
+ comp)))
+
+#define sk_GENERAL_NAME_new_null() ((STACK_OF(GENERAL_NAME) *)sk_new_null())
+
+#define sk_GENERAL_NAME_num(sk) \
+ sk_num(CHECKED_CAST(_STACK *, STACK_OF(GENERAL_NAME) *, sk))
+
+#define sk_GENERAL_NAME_zero(sk) \
+ sk_zero(CHECKED_CAST(_STACK *, STACK_OF(GENERAL_NAME) *, sk));
+
+#define sk_GENERAL_NAME_value(sk, i) \
+ ((GENERAL_NAME *)sk_value( \
+ CHECKED_CAST(_STACK *, const STACK_OF(GENERAL_NAME) *, sk), (i)))
+
+#define sk_GENERAL_NAME_set(sk, i, p) \
+ ((GENERAL_NAME *)sk_set( \
+ CHECKED_CAST(_STACK *, STACK_OF(GENERAL_NAME) *, sk), (i), \
+ CHECKED_CAST(void *, GENERAL_NAME *, p)))
+
+#define sk_GENERAL_NAME_free(sk) \
+ sk_free(CHECKED_CAST(_STACK *, STACK_OF(GENERAL_NAME) *, sk))
+
+#define sk_GENERAL_NAME_pop_free(sk, free_func) \
+ sk_pop_free( \
+ CHECKED_CAST(_STACK *, STACK_OF(GENERAL_NAME) *, sk), \
+ CHECKED_CAST(void (*)(void *), void (*)(GENERAL_NAME *), free_func))
+
+#define sk_GENERAL_NAME_insert(sk, p, where) \
+ sk_insert(CHECKED_CAST(_STACK *, STACK_OF(GENERAL_NAME) *, sk), \
+ CHECKED_CAST(void *, GENERAL_NAME *, p), (where))
+
+#define sk_GENERAL_NAME_delete(sk, where) \
+ ((GENERAL_NAME *)sk_delete( \
+ CHECKED_CAST(_STACK *, STACK_OF(GENERAL_NAME) *, sk), (where)))
+
+#define sk_GENERAL_NAME_delete_ptr(sk, p) \
+ ((GENERAL_NAME *)sk_delete_ptr( \
+ CHECKED_CAST(_STACK *, STACK_OF(GENERAL_NAME) *, sk), \
+ CHECKED_CAST(void *, GENERAL_NAME *, p)))
+
+#define sk_GENERAL_NAME_find(sk, out_index, p) \
+ sk_find(CHECKED_CAST(_STACK *, STACK_OF(GENERAL_NAME) *, sk), (out_index), \
+ CHECKED_CAST(void *, GENERAL_NAME *, p))
+
+#define sk_GENERAL_NAME_shift(sk) \
+ ((GENERAL_NAME *)sk_shift( \
+ CHECKED_CAST(_STACK *, STACK_OF(GENERAL_NAME) *, sk)))
+
+#define sk_GENERAL_NAME_push(sk, p) \
+ sk_push(CHECKED_CAST(_STACK *, STACK_OF(GENERAL_NAME) *, sk), \
+ CHECKED_CAST(void *, GENERAL_NAME *, p))
+
+#define sk_GENERAL_NAME_pop(sk) \
+ ((GENERAL_NAME *)sk_pop(CHECKED_CAST(_STACK *, STACK_OF(GENERAL_NAME) *, sk)))
+
+#define sk_GENERAL_NAME_dup(sk) \
+ ((STACK_OF(GENERAL_NAME) *)sk_dup( \
+ CHECKED_CAST(_STACK *, const STACK_OF(GENERAL_NAME) *, sk)))
+
+#define sk_GENERAL_NAME_sort(sk) \
+ sk_sort(CHECKED_CAST(_STACK *, STACK_OF(GENERAL_NAME) *, sk))
+
+#define sk_GENERAL_NAME_is_sorted(sk) \
+ sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(GENERAL_NAME) *, sk))
+
+#define sk_GENERAL_NAME_set_cmp_func(sk, comp) \
+ ((int (*)(const GENERAL_NAME **a, const GENERAL_NAME **b))sk_set_cmp_func( \
+ CHECKED_CAST(_STACK *, STACK_OF(GENERAL_NAME) *, sk), \
+ CHECKED_CAST(stack_cmp_func, \
+ int (*)(const GENERAL_NAME **a, const GENERAL_NAME **b), \
+ comp)))
+
+
+/* GENERAL_NAMES */
+#define sk_GENERAL_NAMES_new(comp) \
+ ((STACK_OF(GENERAL_NAMES) *)sk_new(CHECKED_CAST( \
+ stack_cmp_func, \
+ int (*)(const GENERAL_NAMES **a, const GENERAL_NAMES **b), comp)))
+
+#define sk_GENERAL_NAMES_new_null() ((STACK_OF(GENERAL_NAMES) *)sk_new_null())
+
+#define sk_GENERAL_NAMES_num(sk) \
+ sk_num(CHECKED_CAST(_STACK *, STACK_OF(GENERAL_NAMES) *, sk))
+
+#define sk_GENERAL_NAMES_zero(sk) \
+ sk_zero(CHECKED_CAST(_STACK *, STACK_OF(GENERAL_NAMES) *, sk));
+
+#define sk_GENERAL_NAMES_value(sk, i) \
+ ((GENERAL_NAMES *)sk_value( \
+ CHECKED_CAST(_STACK *, const STACK_OF(GENERAL_NAMES) *, sk), (i)))
+
+#define sk_GENERAL_NAMES_set(sk, i, p) \
+ ((GENERAL_NAMES *)sk_set( \
+ CHECKED_CAST(_STACK *, STACK_OF(GENERAL_NAMES) *, sk), (i), \
+ CHECKED_CAST(void *, GENERAL_NAMES *, p)))
+
+#define sk_GENERAL_NAMES_free(sk) \
+ sk_free(CHECKED_CAST(_STACK *, STACK_OF(GENERAL_NAMES) *, sk))
+
+#define sk_GENERAL_NAMES_pop_free(sk, free_func) \
+ sk_pop_free( \
+ CHECKED_CAST(_STACK *, STACK_OF(GENERAL_NAMES) *, sk), \
+ CHECKED_CAST(void (*)(void *), void (*)(GENERAL_NAMES *), free_func))
+
+#define sk_GENERAL_NAMES_insert(sk, p, where) \
+ sk_insert(CHECKED_CAST(_STACK *, STACK_OF(GENERAL_NAMES) *, sk), \
+ CHECKED_CAST(void *, GENERAL_NAMES *, p), (where))
+
+#define sk_GENERAL_NAMES_delete(sk, where) \
+ ((GENERAL_NAMES *)sk_delete( \
+ CHECKED_CAST(_STACK *, STACK_OF(GENERAL_NAMES) *, sk), (where)))
+
+#define sk_GENERAL_NAMES_delete_ptr(sk, p) \
+ ((GENERAL_NAMES *)sk_delete_ptr( \
+ CHECKED_CAST(_STACK *, STACK_OF(GENERAL_NAMES) *, sk), \
+ CHECKED_CAST(void *, GENERAL_NAMES *, p)))
+
+#define sk_GENERAL_NAMES_find(sk, out_index, p) \
+ sk_find(CHECKED_CAST(_STACK *, STACK_OF(GENERAL_NAMES) *, sk), (out_index), \
+ CHECKED_CAST(void *, GENERAL_NAMES *, p))
+
+#define sk_GENERAL_NAMES_shift(sk) \
+ ((GENERAL_NAMES *)sk_shift( \
+ CHECKED_CAST(_STACK *, STACK_OF(GENERAL_NAMES) *, sk)))
+
+#define sk_GENERAL_NAMES_push(sk, p) \
+ sk_push(CHECKED_CAST(_STACK *, STACK_OF(GENERAL_NAMES) *, sk), \
+ CHECKED_CAST(void *, GENERAL_NAMES *, p))
+
+#define sk_GENERAL_NAMES_pop(sk) \
+ ((GENERAL_NAMES *)sk_pop( \
+ CHECKED_CAST(_STACK *, STACK_OF(GENERAL_NAMES) *, sk)))
+
+#define sk_GENERAL_NAMES_dup(sk) \
+ ((STACK_OF(GENERAL_NAMES) *)sk_dup( \
+ CHECKED_CAST(_STACK *, const STACK_OF(GENERAL_NAMES) *, sk)))
+
+#define sk_GENERAL_NAMES_sort(sk) \
+ sk_sort(CHECKED_CAST(_STACK *, STACK_OF(GENERAL_NAMES) *, sk))
+
+#define sk_GENERAL_NAMES_is_sorted(sk) \
+ sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(GENERAL_NAMES) *, sk))
+
+#define sk_GENERAL_NAMES_set_cmp_func(sk, comp) \
+ ((int (*)(const GENERAL_NAMES **a, const GENERAL_NAMES **b))sk_set_cmp_func( \
+ CHECKED_CAST(_STACK *, STACK_OF(GENERAL_NAMES) *, sk), \
+ CHECKED_CAST(stack_cmp_func, \
+ int (*)(const GENERAL_NAMES **a, const GENERAL_NAMES **b), \
+ comp)))
+
+
+/* GENERAL_SUBTREE */
+#define sk_GENERAL_SUBTREE_new(comp) \
+ ((STACK_OF(GENERAL_SUBTREE) *)sk_new(CHECKED_CAST( \
+ stack_cmp_func, \
+ int (*)(const GENERAL_SUBTREE **a, const GENERAL_SUBTREE **b), comp)))
+
+#define sk_GENERAL_SUBTREE_new_null() \
+ ((STACK_OF(GENERAL_SUBTREE) *)sk_new_null())
+
+#define sk_GENERAL_SUBTREE_num(sk) \
+ sk_num(CHECKED_CAST(_STACK *, STACK_OF(GENERAL_SUBTREE) *, sk))
+
+#define sk_GENERAL_SUBTREE_zero(sk) \
+ sk_zero(CHECKED_CAST(_STACK *, STACK_OF(GENERAL_SUBTREE) *, sk));
+
+#define sk_GENERAL_SUBTREE_value(sk, i) \
+ ((GENERAL_SUBTREE *)sk_value( \
+ CHECKED_CAST(_STACK *, const STACK_OF(GENERAL_SUBTREE) *, sk), (i)))
+
+#define sk_GENERAL_SUBTREE_set(sk, i, p) \
+ ((GENERAL_SUBTREE *)sk_set( \
+ CHECKED_CAST(_STACK *, STACK_OF(GENERAL_SUBTREE) *, sk), (i), \
+ CHECKED_CAST(void *, GENERAL_SUBTREE *, p)))
+
+#define sk_GENERAL_SUBTREE_free(sk) \
+ sk_free(CHECKED_CAST(_STACK *, STACK_OF(GENERAL_SUBTREE) *, sk))
+
+#define sk_GENERAL_SUBTREE_pop_free(sk, free_func) \
+ sk_pop_free( \
+ CHECKED_CAST(_STACK *, STACK_OF(GENERAL_SUBTREE) *, sk), \
+ CHECKED_CAST(void (*)(void *), void (*)(GENERAL_SUBTREE *), free_func))
+
+#define sk_GENERAL_SUBTREE_insert(sk, p, where) \
+ sk_insert(CHECKED_CAST(_STACK *, STACK_OF(GENERAL_SUBTREE) *, sk), \
+ CHECKED_CAST(void *, GENERAL_SUBTREE *, p), (where))
+
+#define sk_GENERAL_SUBTREE_delete(sk, where) \
+ ((GENERAL_SUBTREE *)sk_delete( \
+ CHECKED_CAST(_STACK *, STACK_OF(GENERAL_SUBTREE) *, sk), (where)))
+
+#define sk_GENERAL_SUBTREE_delete_ptr(sk, p) \
+ ((GENERAL_SUBTREE *)sk_delete_ptr( \
+ CHECKED_CAST(_STACK *, STACK_OF(GENERAL_SUBTREE) *, sk), \
+ CHECKED_CAST(void *, GENERAL_SUBTREE *, p)))
+
+#define sk_GENERAL_SUBTREE_find(sk, out_index, p) \
+ sk_find(CHECKED_CAST(_STACK *, STACK_OF(GENERAL_SUBTREE) *, sk), \
+ (out_index), CHECKED_CAST(void *, GENERAL_SUBTREE *, p))
+
+#define sk_GENERAL_SUBTREE_shift(sk) \
+ ((GENERAL_SUBTREE *)sk_shift( \
+ CHECKED_CAST(_STACK *, STACK_OF(GENERAL_SUBTREE) *, sk)))
+
+#define sk_GENERAL_SUBTREE_push(sk, p) \
+ sk_push(CHECKED_CAST(_STACK *, STACK_OF(GENERAL_SUBTREE) *, sk), \
+ CHECKED_CAST(void *, GENERAL_SUBTREE *, p))
+
+#define sk_GENERAL_SUBTREE_pop(sk) \
+ ((GENERAL_SUBTREE *)sk_pop( \
+ CHECKED_CAST(_STACK *, STACK_OF(GENERAL_SUBTREE) *, sk)))
+
+#define sk_GENERAL_SUBTREE_dup(sk) \
+ ((STACK_OF(GENERAL_SUBTREE) *)sk_dup( \
+ CHECKED_CAST(_STACK *, const STACK_OF(GENERAL_SUBTREE) *, sk)))
+
+#define sk_GENERAL_SUBTREE_sort(sk) \
+ sk_sort(CHECKED_CAST(_STACK *, STACK_OF(GENERAL_SUBTREE) *, sk))
+
+#define sk_GENERAL_SUBTREE_is_sorted(sk) \
+ sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(GENERAL_SUBTREE) *, sk))
+
+#define sk_GENERAL_SUBTREE_set_cmp_func(sk, comp) \
+ ((int (*)(const GENERAL_SUBTREE **a, const GENERAL_SUBTREE **b)) \
+ sk_set_cmp_func( \
+ CHECKED_CAST(_STACK *, STACK_OF(GENERAL_SUBTREE) *, sk), \
+ CHECKED_CAST(stack_cmp_func, int (*)(const GENERAL_SUBTREE **a, \
+ const GENERAL_SUBTREE **b), \
+ comp)))
+
+
+/* MIME_HEADER */
+#define sk_MIME_HEADER_new(comp) \
+ ((STACK_OF(MIME_HEADER) *)sk_new(CHECKED_CAST( \
+ stack_cmp_func, int (*)(const MIME_HEADER **a, const MIME_HEADER **b), \
+ comp)))
+
+#define sk_MIME_HEADER_new_null() ((STACK_OF(MIME_HEADER) *)sk_new_null())
+
+#define sk_MIME_HEADER_num(sk) \
+ sk_num(CHECKED_CAST(_STACK *, STACK_OF(MIME_HEADER) *, sk))
+
+#define sk_MIME_HEADER_zero(sk) \
+ sk_zero(CHECKED_CAST(_STACK *, STACK_OF(MIME_HEADER) *, sk));
+
+#define sk_MIME_HEADER_value(sk, i) \
+ ((MIME_HEADER *)sk_value( \
+ CHECKED_CAST(_STACK *, const STACK_OF(MIME_HEADER) *, sk), (i)))
+
+#define sk_MIME_HEADER_set(sk, i, p) \
+ ((MIME_HEADER *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(MIME_HEADER) *, sk), \
+ (i), CHECKED_CAST(void *, MIME_HEADER *, p)))
+
+#define sk_MIME_HEADER_free(sk) \
+ sk_free(CHECKED_CAST(_STACK *, STACK_OF(MIME_HEADER) *, sk))
+
+#define sk_MIME_HEADER_pop_free(sk, free_func) \
+ sk_pop_free( \
+ CHECKED_CAST(_STACK *, STACK_OF(MIME_HEADER) *, sk), \
+ CHECKED_CAST(void (*)(void *), void (*)(MIME_HEADER *), free_func))
+
+#define sk_MIME_HEADER_insert(sk, p, where) \
+ sk_insert(CHECKED_CAST(_STACK *, STACK_OF(MIME_HEADER) *, sk), \
+ CHECKED_CAST(void *, MIME_HEADER *, p), (where))
+
+#define sk_MIME_HEADER_delete(sk, where) \
+ ((MIME_HEADER *)sk_delete( \
+ CHECKED_CAST(_STACK *, STACK_OF(MIME_HEADER) *, sk), (where)))
+
+#define sk_MIME_HEADER_delete_ptr(sk, p) \
+ ((MIME_HEADER *)sk_delete_ptr( \
+ CHECKED_CAST(_STACK *, STACK_OF(MIME_HEADER) *, sk), \
+ CHECKED_CAST(void *, MIME_HEADER *, p)))
+
+#define sk_MIME_HEADER_find(sk, out_index, p) \
+ sk_find(CHECKED_CAST(_STACK *, STACK_OF(MIME_HEADER) *, sk), (out_index), \
+ CHECKED_CAST(void *, MIME_HEADER *, p))
+
+#define sk_MIME_HEADER_shift(sk) \
+ ((MIME_HEADER *)sk_shift(CHECKED_CAST(_STACK *, STACK_OF(MIME_HEADER) *, sk)))
+
+#define sk_MIME_HEADER_push(sk, p) \
+ sk_push(CHECKED_CAST(_STACK *, STACK_OF(MIME_HEADER) *, sk), \
+ CHECKED_CAST(void *, MIME_HEADER *, p))
+
+#define sk_MIME_HEADER_pop(sk) \
+ ((MIME_HEADER *)sk_pop(CHECKED_CAST(_STACK *, STACK_OF(MIME_HEADER) *, sk)))
+
+#define sk_MIME_HEADER_dup(sk) \
+ ((STACK_OF(MIME_HEADER) *)sk_dup( \
+ CHECKED_CAST(_STACK *, const STACK_OF(MIME_HEADER) *, sk)))
+
+#define sk_MIME_HEADER_sort(sk) \
+ sk_sort(CHECKED_CAST(_STACK *, STACK_OF(MIME_HEADER) *, sk))
+
+#define sk_MIME_HEADER_is_sorted(sk) \
+ sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(MIME_HEADER) *, sk))
+
+#define sk_MIME_HEADER_set_cmp_func(sk, comp) \
+ ((int (*)(const MIME_HEADER **a, const MIME_HEADER **b))sk_set_cmp_func( \
+ CHECKED_CAST(_STACK *, STACK_OF(MIME_HEADER) *, sk), \
+ CHECKED_CAST(stack_cmp_func, \
+ int (*)(const MIME_HEADER **a, const MIME_HEADER **b), \
+ comp)))
+
+
+/* PKCS7_SIGNER_INFO */
+#define sk_PKCS7_SIGNER_INFO_new(comp) \
+ ((STACK_OF(PKCS7_SIGNER_INFO) *)sk_new(CHECKED_CAST( \
+ stack_cmp_func, \
+ int (*)(const PKCS7_SIGNER_INFO **a, const PKCS7_SIGNER_INFO **b), \
+ comp)))
+
+#define sk_PKCS7_SIGNER_INFO_new_null() \
+ ((STACK_OF(PKCS7_SIGNER_INFO) *)sk_new_null())
+
+#define sk_PKCS7_SIGNER_INFO_num(sk) \
+ sk_num(CHECKED_CAST(_STACK *, STACK_OF(PKCS7_SIGNER_INFO) *, sk))
+
+#define sk_PKCS7_SIGNER_INFO_zero(sk) \
+ sk_zero(CHECKED_CAST(_STACK *, STACK_OF(PKCS7_SIGNER_INFO) *, sk));
+
+#define sk_PKCS7_SIGNER_INFO_value(sk, i) \
+ ((PKCS7_SIGNER_INFO *)sk_value( \
+ CHECKED_CAST(_STACK *, const STACK_OF(PKCS7_SIGNER_INFO) *, sk), (i)))
+
+#define sk_PKCS7_SIGNER_INFO_set(sk, i, p) \
+ ((PKCS7_SIGNER_INFO *)sk_set( \
+ CHECKED_CAST(_STACK *, STACK_OF(PKCS7_SIGNER_INFO) *, sk), (i), \
+ CHECKED_CAST(void *, PKCS7_SIGNER_INFO *, p)))
+
+#define sk_PKCS7_SIGNER_INFO_free(sk) \
+ sk_free(CHECKED_CAST(_STACK *, STACK_OF(PKCS7_SIGNER_INFO) *, sk))
+
+#define sk_PKCS7_SIGNER_INFO_pop_free(sk, free_func) \
+ sk_pop_free(CHECKED_CAST(_STACK *, STACK_OF(PKCS7_SIGNER_INFO) *, sk), \
+ CHECKED_CAST(void (*)(void *), void (*)(PKCS7_SIGNER_INFO *), \
+ free_func))
+
+#define sk_PKCS7_SIGNER_INFO_insert(sk, p, where) \
+ sk_insert(CHECKED_CAST(_STACK *, STACK_OF(PKCS7_SIGNER_INFO) *, sk), \
+ CHECKED_CAST(void *, PKCS7_SIGNER_INFO *, p), (where))
+
+#define sk_PKCS7_SIGNER_INFO_delete(sk, where) \
+ ((PKCS7_SIGNER_INFO *)sk_delete( \
+ CHECKED_CAST(_STACK *, STACK_OF(PKCS7_SIGNER_INFO) *, sk), (where)))
+
+#define sk_PKCS7_SIGNER_INFO_delete_ptr(sk, p) \
+ ((PKCS7_SIGNER_INFO *)sk_delete_ptr( \
+ CHECKED_CAST(_STACK *, STACK_OF(PKCS7_SIGNER_INFO) *, sk), \
+ CHECKED_CAST(void *, PKCS7_SIGNER_INFO *, p)))
+
+#define sk_PKCS7_SIGNER_INFO_find(sk, out_index, p) \
+ sk_find(CHECKED_CAST(_STACK *, STACK_OF(PKCS7_SIGNER_INFO) *, sk), \
+ (out_index), CHECKED_CAST(void *, PKCS7_SIGNER_INFO *, p))
+
+#define sk_PKCS7_SIGNER_INFO_shift(sk) \
+ ((PKCS7_SIGNER_INFO *)sk_shift( \
+ CHECKED_CAST(_STACK *, STACK_OF(PKCS7_SIGNER_INFO) *, sk)))
+
+#define sk_PKCS7_SIGNER_INFO_push(sk, p) \
+ sk_push(CHECKED_CAST(_STACK *, STACK_OF(PKCS7_SIGNER_INFO) *, sk), \
+ CHECKED_CAST(void *, PKCS7_SIGNER_INFO *, p))
+
+#define sk_PKCS7_SIGNER_INFO_pop(sk) \
+ ((PKCS7_SIGNER_INFO *)sk_pop( \
+ CHECKED_CAST(_STACK *, STACK_OF(PKCS7_SIGNER_INFO) *, sk)))
+
+#define sk_PKCS7_SIGNER_INFO_dup(sk) \
+ ((STACK_OF(PKCS7_SIGNER_INFO) *)sk_dup( \
+ CHECKED_CAST(_STACK *, const STACK_OF(PKCS7_SIGNER_INFO) *, sk)))
+
+#define sk_PKCS7_SIGNER_INFO_sort(sk) \
+ sk_sort(CHECKED_CAST(_STACK *, STACK_OF(PKCS7_SIGNER_INFO) *, sk))
+
+#define sk_PKCS7_SIGNER_INFO_is_sorted(sk) \
+ sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(PKCS7_SIGNER_INFO) *, sk))
+
+#define sk_PKCS7_SIGNER_INFO_set_cmp_func(sk, comp) \
+ ((int (*)(const PKCS7_SIGNER_INFO **a, const PKCS7_SIGNER_INFO **b)) \
+ sk_set_cmp_func( \
+ CHECKED_CAST(_STACK *, STACK_OF(PKCS7_SIGNER_INFO) *, sk), \
+ CHECKED_CAST(stack_cmp_func, int (*)(const PKCS7_SIGNER_INFO **a, \
+ const PKCS7_SIGNER_INFO **b), \
+ comp)))
+
+
+/* PKCS7_RECIP_INFO */
+#define sk_PKCS7_RECIP_INFO_new(comp) \
+ ((STACK_OF(PKCS7_RECIP_INFO) *)sk_new(CHECKED_CAST( \
+ stack_cmp_func, \
+ int (*)(const PKCS7_RECIP_INFO **a, const PKCS7_RECIP_INFO **b), comp)))
+
+#define sk_PKCS7_RECIP_INFO_new_null() \
+ ((STACK_OF(PKCS7_RECIP_INFO) *)sk_new_null())
+
+#define sk_PKCS7_RECIP_INFO_num(sk) \
+ sk_num(CHECKED_CAST(_STACK *, STACK_OF(PKCS7_RECIP_INFO) *, sk))
+
+#define sk_PKCS7_RECIP_INFO_zero(sk) \
+ sk_zero(CHECKED_CAST(_STACK *, STACK_OF(PKCS7_RECIP_INFO) *, sk));
+
+#define sk_PKCS7_RECIP_INFO_value(sk, i) \
+ ((PKCS7_RECIP_INFO *)sk_value( \
+ CHECKED_CAST(_STACK *, const STACK_OF(PKCS7_RECIP_INFO) *, sk), (i)))
+
+#define sk_PKCS7_RECIP_INFO_set(sk, i, p) \
+ ((PKCS7_RECIP_INFO *)sk_set( \
+ CHECKED_CAST(_STACK *, STACK_OF(PKCS7_RECIP_INFO) *, sk), (i), \
+ CHECKED_CAST(void *, PKCS7_RECIP_INFO *, p)))
+
+#define sk_PKCS7_RECIP_INFO_free(sk) \
+ sk_free(CHECKED_CAST(_STACK *, STACK_OF(PKCS7_RECIP_INFO) *, sk))
+
+#define sk_PKCS7_RECIP_INFO_pop_free(sk, free_func) \
+ sk_pop_free( \
+ CHECKED_CAST(_STACK *, STACK_OF(PKCS7_RECIP_INFO) *, sk), \
+ CHECKED_CAST(void (*)(void *), void (*)(PKCS7_RECIP_INFO *), free_func))
+
+#define sk_PKCS7_RECIP_INFO_insert(sk, p, where) \
+ sk_insert(CHECKED_CAST(_STACK *, STACK_OF(PKCS7_RECIP_INFO) *, sk), \
+ CHECKED_CAST(void *, PKCS7_RECIP_INFO *, p), (where))
+
+#define sk_PKCS7_RECIP_INFO_delete(sk, where) \
+ ((PKCS7_RECIP_INFO *)sk_delete( \
+ CHECKED_CAST(_STACK *, STACK_OF(PKCS7_RECIP_INFO) *, sk), (where)))
+
+#define sk_PKCS7_RECIP_INFO_delete_ptr(sk, p) \
+ ((PKCS7_RECIP_INFO *)sk_delete_ptr( \
+ CHECKED_CAST(_STACK *, STACK_OF(PKCS7_RECIP_INFO) *, sk), \
+ CHECKED_CAST(void *, PKCS7_RECIP_INFO *, p)))
+
+#define sk_PKCS7_RECIP_INFO_find(sk, out_index, p) \
+ sk_find(CHECKED_CAST(_STACK *, STACK_OF(PKCS7_RECIP_INFO) *, sk), \
+ (out_index), CHECKED_CAST(void *, PKCS7_RECIP_INFO *, p))
+
+#define sk_PKCS7_RECIP_INFO_shift(sk) \
+ ((PKCS7_RECIP_INFO *)sk_shift( \
+ CHECKED_CAST(_STACK *, STACK_OF(PKCS7_RECIP_INFO) *, sk)))
+
+#define sk_PKCS7_RECIP_INFO_push(sk, p) \
+ sk_push(CHECKED_CAST(_STACK *, STACK_OF(PKCS7_RECIP_INFO) *, sk), \
+ CHECKED_CAST(void *, PKCS7_RECIP_INFO *, p))
+
+#define sk_PKCS7_RECIP_INFO_pop(sk) \
+ ((PKCS7_RECIP_INFO *)sk_pop( \
+ CHECKED_CAST(_STACK *, STACK_OF(PKCS7_RECIP_INFO) *, sk)))
+
+#define sk_PKCS7_RECIP_INFO_dup(sk) \
+ ((STACK_OF(PKCS7_RECIP_INFO) *)sk_dup( \
+ CHECKED_CAST(_STACK *, const STACK_OF(PKCS7_RECIP_INFO) *, sk)))
+
+#define sk_PKCS7_RECIP_INFO_sort(sk) \
+ sk_sort(CHECKED_CAST(_STACK *, STACK_OF(PKCS7_RECIP_INFO) *, sk))
+
+#define sk_PKCS7_RECIP_INFO_is_sorted(sk) \
+ sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(PKCS7_RECIP_INFO) *, sk))
+
+#define sk_PKCS7_RECIP_INFO_set_cmp_func(sk, comp) \
+ ((int (*)(const PKCS7_RECIP_INFO **a, const PKCS7_RECIP_INFO **b)) \
+ sk_set_cmp_func( \
+ CHECKED_CAST(_STACK *, STACK_OF(PKCS7_RECIP_INFO) *, sk), \
+ CHECKED_CAST(stack_cmp_func, int (*)(const PKCS7_RECIP_INFO **a, \
+ const PKCS7_RECIP_INFO **b), \
+ comp)))
+
+
+/* POLICYINFO */
+#define sk_POLICYINFO_new(comp) \
+ ((STACK_OF(POLICYINFO) *)sk_new(CHECKED_CAST( \
+ stack_cmp_func, int (*)(const POLICYINFO **a, const POLICYINFO **b), \
+ comp)))
+
+#define sk_POLICYINFO_new_null() ((STACK_OF(POLICYINFO) *)sk_new_null())
+
+#define sk_POLICYINFO_num(sk) \
+ sk_num(CHECKED_CAST(_STACK *, STACK_OF(POLICYINFO) *, sk))
+
+#define sk_POLICYINFO_zero(sk) \
+ sk_zero(CHECKED_CAST(_STACK *, STACK_OF(POLICYINFO) *, sk));
+
+#define sk_POLICYINFO_value(sk, i) \
+ ((POLICYINFO *)sk_value( \
+ CHECKED_CAST(_STACK *, const STACK_OF(POLICYINFO) *, sk), (i)))
+
+#define sk_POLICYINFO_set(sk, i, p) \
+ ((POLICYINFO *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(POLICYINFO) *, sk), \
+ (i), CHECKED_CAST(void *, POLICYINFO *, p)))
+
+#define sk_POLICYINFO_free(sk) \
+ sk_free(CHECKED_CAST(_STACK *, STACK_OF(POLICYINFO) *, sk))
+
+#define sk_POLICYINFO_pop_free(sk, free_func) \
+ sk_pop_free( \
+ CHECKED_CAST(_STACK *, STACK_OF(POLICYINFO) *, sk), \
+ CHECKED_CAST(void (*)(void *), void (*)(POLICYINFO *), free_func))
+
+#define sk_POLICYINFO_insert(sk, p, where) \
+ sk_insert(CHECKED_CAST(_STACK *, STACK_OF(POLICYINFO) *, sk), \
+ CHECKED_CAST(void *, POLICYINFO *, p), (where))
+
+#define sk_POLICYINFO_delete(sk, where) \
+ ((POLICYINFO *)sk_delete(CHECKED_CAST(_STACK *, STACK_OF(POLICYINFO) *, sk), \
+ (where)))
+
+#define sk_POLICYINFO_delete_ptr(sk, p) \
+ ((POLICYINFO *)sk_delete_ptr( \
+ CHECKED_CAST(_STACK *, STACK_OF(POLICYINFO) *, sk), \
+ CHECKED_CAST(void *, POLICYINFO *, p)))
+
+#define sk_POLICYINFO_find(sk, out_index, p) \
+ sk_find(CHECKED_CAST(_STACK *, STACK_OF(POLICYINFO) *, sk), (out_index), \
+ CHECKED_CAST(void *, POLICYINFO *, p))
+
+#define sk_POLICYINFO_shift(sk) \
+ ((POLICYINFO *)sk_shift(CHECKED_CAST(_STACK *, STACK_OF(POLICYINFO) *, sk)))
+
+#define sk_POLICYINFO_push(sk, p) \
+ sk_push(CHECKED_CAST(_STACK *, STACK_OF(POLICYINFO) *, sk), \
+ CHECKED_CAST(void *, POLICYINFO *, p))
+
+#define sk_POLICYINFO_pop(sk) \
+ ((POLICYINFO *)sk_pop(CHECKED_CAST(_STACK *, STACK_OF(POLICYINFO) *, sk)))
+
+#define sk_POLICYINFO_dup(sk) \
+ ((STACK_OF(POLICYINFO) *)sk_dup( \
+ CHECKED_CAST(_STACK *, const STACK_OF(POLICYINFO) *, sk)))
+
+#define sk_POLICYINFO_sort(sk) \
+ sk_sort(CHECKED_CAST(_STACK *, STACK_OF(POLICYINFO) *, sk))
+
+#define sk_POLICYINFO_is_sorted(sk) \
+ sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(POLICYINFO) *, sk))
+
+#define sk_POLICYINFO_set_cmp_func(sk, comp) \
+ ((int (*)(const POLICYINFO **a, const POLICYINFO **b))sk_set_cmp_func( \
+ CHECKED_CAST(_STACK *, STACK_OF(POLICYINFO) *, sk), \
+ CHECKED_CAST(stack_cmp_func, \
+ int (*)(const POLICYINFO **a, const POLICYINFO **b), \
+ comp)))
+
+
+/* POLICYQUALINFO */
+#define sk_POLICYQUALINFO_new(comp) \
+ ((STACK_OF(POLICYQUALINFO) *)sk_new(CHECKED_CAST( \
+ stack_cmp_func, \
+ int (*)(const POLICYQUALINFO **a, const POLICYQUALINFO **b), comp)))
+
+#define sk_POLICYQUALINFO_new_null() ((STACK_OF(POLICYQUALINFO) *)sk_new_null())
+
+#define sk_POLICYQUALINFO_num(sk) \
+ sk_num(CHECKED_CAST(_STACK *, STACK_OF(POLICYQUALINFO) *, sk))
+
+#define sk_POLICYQUALINFO_zero(sk) \
+ sk_zero(CHECKED_CAST(_STACK *, STACK_OF(POLICYQUALINFO) *, sk));
+
+#define sk_POLICYQUALINFO_value(sk, i) \
+ ((POLICYQUALINFO *)sk_value( \
+ CHECKED_CAST(_STACK *, const STACK_OF(POLICYQUALINFO) *, sk), (i)))
+
+#define sk_POLICYQUALINFO_set(sk, i, p) \
+ ((POLICYQUALINFO *)sk_set( \
+ CHECKED_CAST(_STACK *, STACK_OF(POLICYQUALINFO) *, sk), (i), \
+ CHECKED_CAST(void *, POLICYQUALINFO *, p)))
+
+#define sk_POLICYQUALINFO_free(sk) \
+ sk_free(CHECKED_CAST(_STACK *, STACK_OF(POLICYQUALINFO) *, sk))
+
+#define sk_POLICYQUALINFO_pop_free(sk, free_func) \
+ sk_pop_free( \
+ CHECKED_CAST(_STACK *, STACK_OF(POLICYQUALINFO) *, sk), \
+ CHECKED_CAST(void (*)(void *), void (*)(POLICYQUALINFO *), free_func))
+
+#define sk_POLICYQUALINFO_insert(sk, p, where) \
+ sk_insert(CHECKED_CAST(_STACK *, STACK_OF(POLICYQUALINFO) *, sk), \
+ CHECKED_CAST(void *, POLICYQUALINFO *, p), (where))
+
+#define sk_POLICYQUALINFO_delete(sk, where) \
+ ((POLICYQUALINFO *)sk_delete( \
+ CHECKED_CAST(_STACK *, STACK_OF(POLICYQUALINFO) *, sk), (where)))
+
+#define sk_POLICYQUALINFO_delete_ptr(sk, p) \
+ ((POLICYQUALINFO *)sk_delete_ptr( \
+ CHECKED_CAST(_STACK *, STACK_OF(POLICYQUALINFO) *, sk), \
+ CHECKED_CAST(void *, POLICYQUALINFO *, p)))
+
+#define sk_POLICYQUALINFO_find(sk, out_index, p) \
+ sk_find(CHECKED_CAST(_STACK *, STACK_OF(POLICYQUALINFO) *, sk), (out_index), \
+ CHECKED_CAST(void *, POLICYQUALINFO *, p))
+
+#define sk_POLICYQUALINFO_shift(sk) \
+ ((POLICYQUALINFO *)sk_shift( \
+ CHECKED_CAST(_STACK *, STACK_OF(POLICYQUALINFO) *, sk)))
+
+#define sk_POLICYQUALINFO_push(sk, p) \
+ sk_push(CHECKED_CAST(_STACK *, STACK_OF(POLICYQUALINFO) *, sk), \
+ CHECKED_CAST(void *, POLICYQUALINFO *, p))
+
+#define sk_POLICYQUALINFO_pop(sk) \
+ ((POLICYQUALINFO *)sk_pop( \
+ CHECKED_CAST(_STACK *, STACK_OF(POLICYQUALINFO) *, sk)))
+
+#define sk_POLICYQUALINFO_dup(sk) \
+ ((STACK_OF(POLICYQUALINFO) *)sk_dup( \
+ CHECKED_CAST(_STACK *, const STACK_OF(POLICYQUALINFO) *, sk)))
+
+#define sk_POLICYQUALINFO_sort(sk) \
+ sk_sort(CHECKED_CAST(_STACK *, STACK_OF(POLICYQUALINFO) *, sk))
+
+#define sk_POLICYQUALINFO_is_sorted(sk) \
+ sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(POLICYQUALINFO) *, sk))
+
+#define sk_POLICYQUALINFO_set_cmp_func(sk, comp) \
+ ((int (*)(const POLICYQUALINFO **a, const POLICYQUALINFO **b)) \
+ sk_set_cmp_func( \
+ CHECKED_CAST(_STACK *, STACK_OF(POLICYQUALINFO) *, sk), \
+ CHECKED_CAST(stack_cmp_func, int (*)(const POLICYQUALINFO **a, \
+ const POLICYQUALINFO **b), \
+ comp)))
+
+
+/* POLICY_MAPPING */
+#define sk_POLICY_MAPPING_new(comp) \
+ ((STACK_OF(POLICY_MAPPING) *)sk_new(CHECKED_CAST( \
+ stack_cmp_func, \
+ int (*)(const POLICY_MAPPING **a, const POLICY_MAPPING **b), comp)))
+
+#define sk_POLICY_MAPPING_new_null() ((STACK_OF(POLICY_MAPPING) *)sk_new_null())
+
+#define sk_POLICY_MAPPING_num(sk) \
+ sk_num(CHECKED_CAST(_STACK *, STACK_OF(POLICY_MAPPING) *, sk))
+
+#define sk_POLICY_MAPPING_zero(sk) \
+ sk_zero(CHECKED_CAST(_STACK *, STACK_OF(POLICY_MAPPING) *, sk));
+
+#define sk_POLICY_MAPPING_value(sk, i) \
+ ((POLICY_MAPPING *)sk_value( \
+ CHECKED_CAST(_STACK *, const STACK_OF(POLICY_MAPPING) *, sk), (i)))
+
+#define sk_POLICY_MAPPING_set(sk, i, p) \
+ ((POLICY_MAPPING *)sk_set( \
+ CHECKED_CAST(_STACK *, STACK_OF(POLICY_MAPPING) *, sk), (i), \
+ CHECKED_CAST(void *, POLICY_MAPPING *, p)))
+
+#define sk_POLICY_MAPPING_free(sk) \
+ sk_free(CHECKED_CAST(_STACK *, STACK_OF(POLICY_MAPPING) *, sk))
+
+#define sk_POLICY_MAPPING_pop_free(sk, free_func) \
+ sk_pop_free( \
+ CHECKED_CAST(_STACK *, STACK_OF(POLICY_MAPPING) *, sk), \
+ CHECKED_CAST(void (*)(void *), void (*)(POLICY_MAPPING *), free_func))
+
+#define sk_POLICY_MAPPING_insert(sk, p, where) \
+ sk_insert(CHECKED_CAST(_STACK *, STACK_OF(POLICY_MAPPING) *, sk), \
+ CHECKED_CAST(void *, POLICY_MAPPING *, p), (where))
+
+#define sk_POLICY_MAPPING_delete(sk, where) \
+ ((POLICY_MAPPING *)sk_delete( \
+ CHECKED_CAST(_STACK *, STACK_OF(POLICY_MAPPING) *, sk), (where)))
+
+#define sk_POLICY_MAPPING_delete_ptr(sk, p) \
+ ((POLICY_MAPPING *)sk_delete_ptr( \
+ CHECKED_CAST(_STACK *, STACK_OF(POLICY_MAPPING) *, sk), \
+ CHECKED_CAST(void *, POLICY_MAPPING *, p)))
+
+#define sk_POLICY_MAPPING_find(sk, out_index, p) \
+ sk_find(CHECKED_CAST(_STACK *, STACK_OF(POLICY_MAPPING) *, sk), (out_index), \
+ CHECKED_CAST(void *, POLICY_MAPPING *, p))
+
+#define sk_POLICY_MAPPING_shift(sk) \
+ ((POLICY_MAPPING *)sk_shift( \
+ CHECKED_CAST(_STACK *, STACK_OF(POLICY_MAPPING) *, sk)))
+
+#define sk_POLICY_MAPPING_push(sk, p) \
+ sk_push(CHECKED_CAST(_STACK *, STACK_OF(POLICY_MAPPING) *, sk), \
+ CHECKED_CAST(void *, POLICY_MAPPING *, p))
+
+#define sk_POLICY_MAPPING_pop(sk) \
+ ((POLICY_MAPPING *)sk_pop( \
+ CHECKED_CAST(_STACK *, STACK_OF(POLICY_MAPPING) *, sk)))
+
+#define sk_POLICY_MAPPING_dup(sk) \
+ ((STACK_OF(POLICY_MAPPING) *)sk_dup( \
+ CHECKED_CAST(_STACK *, const STACK_OF(POLICY_MAPPING) *, sk)))
+
+#define sk_POLICY_MAPPING_sort(sk) \
+ sk_sort(CHECKED_CAST(_STACK *, STACK_OF(POLICY_MAPPING) *, sk))
+
+#define sk_POLICY_MAPPING_is_sorted(sk) \
+ sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(POLICY_MAPPING) *, sk))
+
+#define sk_POLICY_MAPPING_set_cmp_func(sk, comp) \
+ ((int (*)(const POLICY_MAPPING **a, const POLICY_MAPPING **b)) \
+ sk_set_cmp_func( \
+ CHECKED_CAST(_STACK *, STACK_OF(POLICY_MAPPING) *, sk), \
+ CHECKED_CAST(stack_cmp_func, int (*)(const POLICY_MAPPING **a, \
+ const POLICY_MAPPING **b), \
+ comp)))
+
+
+/* SSL_COMP */
+#define sk_SSL_COMP_new(comp) \
+ ((STACK_OF(SSL_COMP) *)sk_new(CHECKED_CAST( \
+ stack_cmp_func, int (*)(const SSL_COMP **a, const SSL_COMP **b), comp)))
+
+#define sk_SSL_COMP_new_null() ((STACK_OF(SSL_COMP) *)sk_new_null())
+
+#define sk_SSL_COMP_num(sk) \
+ sk_num(CHECKED_CAST(_STACK *, STACK_OF(SSL_COMP) *, sk))
+
+#define sk_SSL_COMP_zero(sk) \
+ sk_zero(CHECKED_CAST(_STACK *, STACK_OF(SSL_COMP) *, sk));
+
+#define sk_SSL_COMP_value(sk, i) \
+ ((SSL_COMP *)sk_value( \
+ CHECKED_CAST(_STACK *, const STACK_OF(SSL_COMP) *, sk), (i)))
+
+#define sk_SSL_COMP_set(sk, i, p) \
+ ((SSL_COMP *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(SSL_COMP) *, sk), (i), \
+ CHECKED_CAST(void *, SSL_COMP *, p)))
+
+#define sk_SSL_COMP_free(sk) \
+ sk_free(CHECKED_CAST(_STACK *, STACK_OF(SSL_COMP) *, sk))
+
+#define sk_SSL_COMP_pop_free(sk, free_func) \
+ sk_pop_free(CHECKED_CAST(_STACK *, STACK_OF(SSL_COMP) *, sk), \
+ CHECKED_CAST(void (*)(void *), void (*)(SSL_COMP *), free_func))
+
+#define sk_SSL_COMP_insert(sk, p, where) \
+ sk_insert(CHECKED_CAST(_STACK *, STACK_OF(SSL_COMP) *, sk), \
+ CHECKED_CAST(void *, SSL_COMP *, p), (where))
+
+#define sk_SSL_COMP_delete(sk, where) \
+ ((SSL_COMP *)sk_delete(CHECKED_CAST(_STACK *, STACK_OF(SSL_COMP) *, sk), \
+ (where)))
+
+#define sk_SSL_COMP_delete_ptr(sk, p) \
+ ((SSL_COMP *)sk_delete_ptr(CHECKED_CAST(_STACK *, STACK_OF(SSL_COMP) *, sk), \
+ CHECKED_CAST(void *, SSL_COMP *, p)))
+
+#define sk_SSL_COMP_find(sk, out_index, p) \
+ sk_find(CHECKED_CAST(_STACK *, STACK_OF(SSL_COMP) *, sk), (out_index), \
+ CHECKED_CAST(void *, SSL_COMP *, p))
+
+#define sk_SSL_COMP_shift(sk) \
+ ((SSL_COMP *)sk_shift(CHECKED_CAST(_STACK *, STACK_OF(SSL_COMP) *, sk)))
+
+#define sk_SSL_COMP_push(sk, p) \
+ sk_push(CHECKED_CAST(_STACK *, STACK_OF(SSL_COMP) *, sk), \
+ CHECKED_CAST(void *, SSL_COMP *, p))
+
+#define sk_SSL_COMP_pop(sk) \
+ ((SSL_COMP *)sk_pop(CHECKED_CAST(_STACK *, STACK_OF(SSL_COMP) *, sk)))
+
+#define sk_SSL_COMP_dup(sk) \
+ ((STACK_OF(SSL_COMP) *)sk_dup( \
+ CHECKED_CAST(_STACK *, const STACK_OF(SSL_COMP) *, sk)))
+
+#define sk_SSL_COMP_sort(sk) \
+ sk_sort(CHECKED_CAST(_STACK *, STACK_OF(SSL_COMP) *, sk))
+
+#define sk_SSL_COMP_is_sorted(sk) \
+ sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(SSL_COMP) *, sk))
+
+#define sk_SSL_COMP_set_cmp_func(sk, comp) \
+ ((int (*)(const SSL_COMP **a, const SSL_COMP **b))sk_set_cmp_func( \
+ CHECKED_CAST(_STACK *, STACK_OF(SSL_COMP) *, sk), \
+ CHECKED_CAST(stack_cmp_func, \
+ int (*)(const SSL_COMP **a, const SSL_COMP **b), comp)))
+
+
+/* STACK_OF_X509_NAME_ENTRY */
+#define sk_STACK_OF_X509_NAME_ENTRY_new(comp) \
+ ((STACK_OF(STACK_OF_X509_NAME_ENTRY) *)sk_new(CHECKED_CAST( \
+ stack_cmp_func, int (*)(const STACK_OF_X509_NAME_ENTRY **a, \
+ const STACK_OF_X509_NAME_ENTRY **b), \
+ comp)))
+
+#define sk_STACK_OF_X509_NAME_ENTRY_new_null() \
+ ((STACK_OF(STACK_OF_X509_NAME_ENTRY) *)sk_new_null())
+
+#define sk_STACK_OF_X509_NAME_ENTRY_num(sk) \
+ sk_num(CHECKED_CAST(_STACK *, STACK_OF(STACK_OF_X509_NAME_ENTRY) *, sk))
+
+#define sk_STACK_OF_X509_NAME_ENTRY_zero(sk) \
+ sk_zero(CHECKED_CAST(_STACK *, STACK_OF(STACK_OF_X509_NAME_ENTRY) *, sk));
+
+#define sk_STACK_OF_X509_NAME_ENTRY_value(sk, i) \
+ ((STACK_OF_X509_NAME_ENTRY *)sk_value( \
+ CHECKED_CAST(_STACK *, const STACK_OF(STACK_OF_X509_NAME_ENTRY) *, sk), \
+ (i)))
+
+#define sk_STACK_OF_X509_NAME_ENTRY_set(sk, i, p) \
+ ((STACK_OF_X509_NAME_ENTRY *)sk_set( \
+ CHECKED_CAST(_STACK *, STACK_OF(STACK_OF_X509_NAME_ENTRY) *, sk), (i), \
+ CHECKED_CAST(void *, STACK_OF_X509_NAME_ENTRY *, p)))
+
+#define sk_STACK_OF_X509_NAME_ENTRY_free(sk) \
+ sk_free(CHECKED_CAST(_STACK *, STACK_OF(STACK_OF_X509_NAME_ENTRY) *, sk))
+
+#define sk_STACK_OF_X509_NAME_ENTRY_pop_free(sk, free_func) \
+ sk_pop_free( \
+ CHECKED_CAST(_STACK *, STACK_OF(STACK_OF_X509_NAME_ENTRY) *, sk), \
+ CHECKED_CAST(void (*)(void *), void (*)(STACK_OF_X509_NAME_ENTRY *), \
+ free_func))
+
+#define sk_STACK_OF_X509_NAME_ENTRY_insert(sk, p, where) \
+ sk_insert(CHECKED_CAST(_STACK *, STACK_OF(STACK_OF_X509_NAME_ENTRY) *, sk), \
+ CHECKED_CAST(void *, STACK_OF_X509_NAME_ENTRY *, p), (where))
+
+#define sk_STACK_OF_X509_NAME_ENTRY_delete(sk, where) \
+ ((STACK_OF_X509_NAME_ENTRY *)sk_delete( \
+ CHECKED_CAST(_STACK *, STACK_OF(STACK_OF_X509_NAME_ENTRY) *, sk), \
+ (where)))
+
+#define sk_STACK_OF_X509_NAME_ENTRY_delete_ptr(sk, p) \
+ ((STACK_OF_X509_NAME_ENTRY *)sk_delete_ptr( \
+ CHECKED_CAST(_STACK *, STACK_OF(STACK_OF_X509_NAME_ENTRY) *, sk), \
+ CHECKED_CAST(void *, STACK_OF_X509_NAME_ENTRY *, p)))
+
+#define sk_STACK_OF_X509_NAME_ENTRY_find(sk, out_index, p) \
+ sk_find(CHECKED_CAST(_STACK *, STACK_OF(STACK_OF_X509_NAME_ENTRY) *, sk), \
+ (out_index), CHECKED_CAST(void *, STACK_OF_X509_NAME_ENTRY *, p))
+
+#define sk_STACK_OF_X509_NAME_ENTRY_shift(sk) \
+ ((STACK_OF_X509_NAME_ENTRY *)sk_shift( \
+ CHECKED_CAST(_STACK *, STACK_OF(STACK_OF_X509_NAME_ENTRY) *, sk)))
+
+#define sk_STACK_OF_X509_NAME_ENTRY_push(sk, p) \
+ sk_push(CHECKED_CAST(_STACK *, STACK_OF(STACK_OF_X509_NAME_ENTRY) *, sk), \
+ CHECKED_CAST(void *, STACK_OF_X509_NAME_ENTRY *, p))
+
+#define sk_STACK_OF_X509_NAME_ENTRY_pop(sk) \
+ ((STACK_OF_X509_NAME_ENTRY *)sk_pop( \
+ CHECKED_CAST(_STACK *, STACK_OF(STACK_OF_X509_NAME_ENTRY) *, sk)))
+
+#define sk_STACK_OF_X509_NAME_ENTRY_dup(sk) \
+ ((STACK_OF(STACK_OF_X509_NAME_ENTRY) *)sk_dup( \
+ CHECKED_CAST(_STACK *, const STACK_OF(STACK_OF_X509_NAME_ENTRY) *, sk)))
+
+#define sk_STACK_OF_X509_NAME_ENTRY_sort(sk) \
+ sk_sort(CHECKED_CAST(_STACK *, STACK_OF(STACK_OF_X509_NAME_ENTRY) *, sk))
+
+#define sk_STACK_OF_X509_NAME_ENTRY_is_sorted(sk) \
+ sk_is_sorted( \
+ CHECKED_CAST(_STACK *, const STACK_OF(STACK_OF_X509_NAME_ENTRY) *, sk))
+
+#define sk_STACK_OF_X509_NAME_ENTRY_set_cmp_func(sk, comp) \
+ ((int (*)(const STACK_OF_X509_NAME_ENTRY **a, \
+ const STACK_OF_X509_NAME_ENTRY **b)) \
+ sk_set_cmp_func( \
+ CHECKED_CAST(_STACK *, STACK_OF(STACK_OF_X509_NAME_ENTRY) *, sk), \
+ CHECKED_CAST(stack_cmp_func, \
+ int (*)(const STACK_OF_X509_NAME_ENTRY **a, \
+ const STACK_OF_X509_NAME_ENTRY **b), \
+ comp)))
+
+
+/* SXNETID */
+#define sk_SXNETID_new(comp) \
+ ((STACK_OF(SXNETID) *)sk_new(CHECKED_CAST( \
+ stack_cmp_func, int (*)(const SXNETID **a, const SXNETID **b), comp)))
+
+#define sk_SXNETID_new_null() ((STACK_OF(SXNETID) *)sk_new_null())
+
+#define sk_SXNETID_num(sk) \
+ sk_num(CHECKED_CAST(_STACK *, STACK_OF(SXNETID) *, sk))
+
+#define sk_SXNETID_zero(sk) \
+ sk_zero(CHECKED_CAST(_STACK *, STACK_OF(SXNETID) *, sk));
+
+#define sk_SXNETID_value(sk, i) \
+ ((SXNETID *)sk_value(CHECKED_CAST(_STACK *, const STACK_OF(SXNETID) *, sk), \
+ (i)))
+
+#define sk_SXNETID_set(sk, i, p) \
+ ((SXNETID *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(SXNETID) *, sk), (i), \
+ CHECKED_CAST(void *, SXNETID *, p)))
+
+#define sk_SXNETID_free(sk) \
+ sk_free(CHECKED_CAST(_STACK *, STACK_OF(SXNETID) *, sk))
+
+#define sk_SXNETID_pop_free(sk, free_func) \
+ sk_pop_free(CHECKED_CAST(_STACK *, STACK_OF(SXNETID) *, sk), \
+ CHECKED_CAST(void (*)(void *), void (*)(SXNETID *), free_func))
+
+#define sk_SXNETID_insert(sk, p, where) \
+ sk_insert(CHECKED_CAST(_STACK *, STACK_OF(SXNETID) *, sk), \
+ CHECKED_CAST(void *, SXNETID *, p), (where))
+
+#define sk_SXNETID_delete(sk, where) \
+ ((SXNETID *)sk_delete(CHECKED_CAST(_STACK *, STACK_OF(SXNETID) *, sk), \
+ (where)))
+
+#define sk_SXNETID_delete_ptr(sk, p) \
+ ((SXNETID *)sk_delete_ptr(CHECKED_CAST(_STACK *, STACK_OF(SXNETID) *, sk), \
+ CHECKED_CAST(void *, SXNETID *, p)))
+
+#define sk_SXNETID_find(sk, out_index, p) \
+ sk_find(CHECKED_CAST(_STACK *, STACK_OF(SXNETID) *, sk), (out_index), \
+ CHECKED_CAST(void *, SXNETID *, p))
+
+#define sk_SXNETID_shift(sk) \
+ ((SXNETID *)sk_shift(CHECKED_CAST(_STACK *, STACK_OF(SXNETID) *, sk)))
+
+#define sk_SXNETID_push(sk, p) \
+ sk_push(CHECKED_CAST(_STACK *, STACK_OF(SXNETID) *, sk), \
+ CHECKED_CAST(void *, SXNETID *, p))
+
+#define sk_SXNETID_pop(sk) \
+ ((SXNETID *)sk_pop(CHECKED_CAST(_STACK *, STACK_OF(SXNETID) *, sk)))
+
+#define sk_SXNETID_dup(sk) \
+ ((STACK_OF(SXNETID) *)sk_dup( \
+ CHECKED_CAST(_STACK *, const STACK_OF(SXNETID) *, sk)))
+
+#define sk_SXNETID_sort(sk) \
+ sk_sort(CHECKED_CAST(_STACK *, STACK_OF(SXNETID) *, sk))
+
+#define sk_SXNETID_is_sorted(sk) \
+ sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(SXNETID) *, sk))
+
+#define sk_SXNETID_set_cmp_func(sk, comp) \
+ ((int (*)(const SXNETID **a, const SXNETID **b))sk_set_cmp_func( \
+ CHECKED_CAST(_STACK *, STACK_OF(SXNETID) *, sk), \
+ CHECKED_CAST(stack_cmp_func, \
+ int (*)(const SXNETID **a, const SXNETID **b), comp)))
+
+
+/* X509 */
+#define sk_X509_new(comp) \
+ ((STACK_OF(X509) *)sk_new(CHECKED_CAST( \
+ stack_cmp_func, int (*)(const X509 **a, const X509 **b), comp)))
+
+#define sk_X509_new_null() ((STACK_OF(X509) *)sk_new_null())
+
+#define sk_X509_num(sk) sk_num(CHECKED_CAST(_STACK *, STACK_OF(X509) *, sk))
+
+#define sk_X509_zero(sk) sk_zero(CHECKED_CAST(_STACK *, STACK_OF(X509) *, sk));
+
+#define sk_X509_value(sk, i) \
+ ((X509 *)sk_value(CHECKED_CAST(_STACK *, const STACK_OF(X509) *, sk), (i)))
+
+#define sk_X509_set(sk, i, p) \
+ ((X509 *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(X509) *, sk), (i), \
+ CHECKED_CAST(void *, X509 *, p)))
+
+#define sk_X509_free(sk) sk_free(CHECKED_CAST(_STACK *, STACK_OF(X509) *, sk))
+
+#define sk_X509_pop_free(sk, free_func) \
+ sk_pop_free(CHECKED_CAST(_STACK *, STACK_OF(X509) *, sk), \
+ CHECKED_CAST(void (*)(void *), void (*)(X509 *), free_func))
+
+#define sk_X509_insert(sk, p, where) \
+ sk_insert(CHECKED_CAST(_STACK *, STACK_OF(X509) *, sk), \
+ CHECKED_CAST(void *, X509 *, p), (where))
+
+#define sk_X509_delete(sk, where) \
+ ((X509 *)sk_delete(CHECKED_CAST(_STACK *, STACK_OF(X509) *, sk), (where)))
+
+#define sk_X509_delete_ptr(sk, p) \
+ ((X509 *)sk_delete_ptr(CHECKED_CAST(_STACK *, STACK_OF(X509) *, sk), \
+ CHECKED_CAST(void *, X509 *, p)))
+
+#define sk_X509_find(sk, out_index, p) \
+ sk_find(CHECKED_CAST(_STACK *, STACK_OF(X509) *, sk), (out_index), \
+ CHECKED_CAST(void *, X509 *, p))
+
+#define sk_X509_shift(sk) \
+ ((X509 *)sk_shift(CHECKED_CAST(_STACK *, STACK_OF(X509) *, sk)))
+
+#define sk_X509_push(sk, p) \
+ sk_push(CHECKED_CAST(_STACK *, STACK_OF(X509) *, sk), \
+ CHECKED_CAST(void *, X509 *, p))
+
+#define sk_X509_pop(sk) \
+ ((X509 *)sk_pop(CHECKED_CAST(_STACK *, STACK_OF(X509) *, sk)))
+
+#define sk_X509_dup(sk) \
+ ((STACK_OF(X509) *)sk_dup(CHECKED_CAST(_STACK *, const STACK_OF(X509) *, sk)))
+
+#define sk_X509_sort(sk) sk_sort(CHECKED_CAST(_STACK *, STACK_OF(X509) *, sk))
+
+#define sk_X509_is_sorted(sk) \
+ sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(X509) *, sk))
+
+#define sk_X509_set_cmp_func(sk, comp) \
+ ((int (*)(const X509 **a, const X509 **b))sk_set_cmp_func( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509) *, sk), \
+ CHECKED_CAST(stack_cmp_func, int (*)(const X509 **a, const X509 **b), \
+ comp)))
+
+
+/* X509V3_EXT_METHOD */
+#define sk_X509V3_EXT_METHOD_new(comp) \
+ ((STACK_OF(X509V3_EXT_METHOD) *)sk_new(CHECKED_CAST( \
+ stack_cmp_func, \
+ int (*)(const X509V3_EXT_METHOD **a, const X509V3_EXT_METHOD **b), \
+ comp)))
+
+#define sk_X509V3_EXT_METHOD_new_null() \
+ ((STACK_OF(X509V3_EXT_METHOD) *)sk_new_null())
+
+#define sk_X509V3_EXT_METHOD_num(sk) \
+ sk_num(CHECKED_CAST(_STACK *, STACK_OF(X509V3_EXT_METHOD) *, sk))
+
+#define sk_X509V3_EXT_METHOD_zero(sk) \
+ sk_zero(CHECKED_CAST(_STACK *, STACK_OF(X509V3_EXT_METHOD) *, sk));
+
+#define sk_X509V3_EXT_METHOD_value(sk, i) \
+ ((X509V3_EXT_METHOD *)sk_value( \
+ CHECKED_CAST(_STACK *, const STACK_OF(X509V3_EXT_METHOD) *, sk), (i)))
+
+#define sk_X509V3_EXT_METHOD_set(sk, i, p) \
+ ((X509V3_EXT_METHOD *)sk_set( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509V3_EXT_METHOD) *, sk), (i), \
+ CHECKED_CAST(void *, X509V3_EXT_METHOD *, p)))
+
+#define sk_X509V3_EXT_METHOD_free(sk) \
+ sk_free(CHECKED_CAST(_STACK *, STACK_OF(X509V3_EXT_METHOD) *, sk))
+
+#define sk_X509V3_EXT_METHOD_pop_free(sk, free_func) \
+ sk_pop_free(CHECKED_CAST(_STACK *, STACK_OF(X509V3_EXT_METHOD) *, sk), \
+ CHECKED_CAST(void (*)(void *), void (*)(X509V3_EXT_METHOD *), \
+ free_func))
+
+#define sk_X509V3_EXT_METHOD_insert(sk, p, where) \
+ sk_insert(CHECKED_CAST(_STACK *, STACK_OF(X509V3_EXT_METHOD) *, sk), \
+ CHECKED_CAST(void *, X509V3_EXT_METHOD *, p), (where))
+
+#define sk_X509V3_EXT_METHOD_delete(sk, where) \
+ ((X509V3_EXT_METHOD *)sk_delete( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509V3_EXT_METHOD) *, sk), (where)))
+
+#define sk_X509V3_EXT_METHOD_delete_ptr(sk, p) \
+ ((X509V3_EXT_METHOD *)sk_delete_ptr( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509V3_EXT_METHOD) *, sk), \
+ CHECKED_CAST(void *, X509V3_EXT_METHOD *, p)))
+
+#define sk_X509V3_EXT_METHOD_find(sk, out_index, p) \
+ sk_find(CHECKED_CAST(_STACK *, STACK_OF(X509V3_EXT_METHOD) *, sk), \
+ (out_index), CHECKED_CAST(void *, X509V3_EXT_METHOD *, p))
+
+#define sk_X509V3_EXT_METHOD_shift(sk) \
+ ((X509V3_EXT_METHOD *)sk_shift( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509V3_EXT_METHOD) *, sk)))
+
+#define sk_X509V3_EXT_METHOD_push(sk, p) \
+ sk_push(CHECKED_CAST(_STACK *, STACK_OF(X509V3_EXT_METHOD) *, sk), \
+ CHECKED_CAST(void *, X509V3_EXT_METHOD *, p))
+
+#define sk_X509V3_EXT_METHOD_pop(sk) \
+ ((X509V3_EXT_METHOD *)sk_pop( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509V3_EXT_METHOD) *, sk)))
+
+#define sk_X509V3_EXT_METHOD_dup(sk) \
+ ((STACK_OF(X509V3_EXT_METHOD) *)sk_dup( \
+ CHECKED_CAST(_STACK *, const STACK_OF(X509V3_EXT_METHOD) *, sk)))
+
+#define sk_X509V3_EXT_METHOD_sort(sk) \
+ sk_sort(CHECKED_CAST(_STACK *, STACK_OF(X509V3_EXT_METHOD) *, sk))
+
+#define sk_X509V3_EXT_METHOD_is_sorted(sk) \
+ sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(X509V3_EXT_METHOD) *, sk))
+
+#define sk_X509V3_EXT_METHOD_set_cmp_func(sk, comp) \
+ ((int (*)(const X509V3_EXT_METHOD **a, const X509V3_EXT_METHOD **b)) \
+ sk_set_cmp_func( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509V3_EXT_METHOD) *, sk), \
+ CHECKED_CAST(stack_cmp_func, int (*)(const X509V3_EXT_METHOD **a, \
+ const X509V3_EXT_METHOD **b), \
+ comp)))
+
+
+/* X509_ALGOR */
+#define sk_X509_ALGOR_new(comp) \
+ ((STACK_OF(X509_ALGOR) *)sk_new(CHECKED_CAST( \
+ stack_cmp_func, int (*)(const X509_ALGOR **a, const X509_ALGOR **b), \
+ comp)))
+
+#define sk_X509_ALGOR_new_null() ((STACK_OF(X509_ALGOR) *)sk_new_null())
+
+#define sk_X509_ALGOR_num(sk) \
+ sk_num(CHECKED_CAST(_STACK *, STACK_OF(X509_ALGOR) *, sk))
+
+#define sk_X509_ALGOR_zero(sk) \
+ sk_zero(CHECKED_CAST(_STACK *, STACK_OF(X509_ALGOR) *, sk));
+
+#define sk_X509_ALGOR_value(sk, i) \
+ ((X509_ALGOR *)sk_value( \
+ CHECKED_CAST(_STACK *, const STACK_OF(X509_ALGOR) *, sk), (i)))
+
+#define sk_X509_ALGOR_set(sk, i, p) \
+ ((X509_ALGOR *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(X509_ALGOR) *, sk), \
+ (i), CHECKED_CAST(void *, X509_ALGOR *, p)))
+
+#define sk_X509_ALGOR_free(sk) \
+ sk_free(CHECKED_CAST(_STACK *, STACK_OF(X509_ALGOR) *, sk))
+
+#define sk_X509_ALGOR_pop_free(sk, free_func) \
+ sk_pop_free( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_ALGOR) *, sk), \
+ CHECKED_CAST(void (*)(void *), void (*)(X509_ALGOR *), free_func))
+
+#define sk_X509_ALGOR_insert(sk, p, where) \
+ sk_insert(CHECKED_CAST(_STACK *, STACK_OF(X509_ALGOR) *, sk), \
+ CHECKED_CAST(void *, X509_ALGOR *, p), (where))
+
+#define sk_X509_ALGOR_delete(sk, where) \
+ ((X509_ALGOR *)sk_delete(CHECKED_CAST(_STACK *, STACK_OF(X509_ALGOR) *, sk), \
+ (where)))
+
+#define sk_X509_ALGOR_delete_ptr(sk, p) \
+ ((X509_ALGOR *)sk_delete_ptr( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_ALGOR) *, sk), \
+ CHECKED_CAST(void *, X509_ALGOR *, p)))
+
+#define sk_X509_ALGOR_find(sk, out_index, p) \
+ sk_find(CHECKED_CAST(_STACK *, STACK_OF(X509_ALGOR) *, sk), (out_index), \
+ CHECKED_CAST(void *, X509_ALGOR *, p))
+
+#define sk_X509_ALGOR_shift(sk) \
+ ((X509_ALGOR *)sk_shift(CHECKED_CAST(_STACK *, STACK_OF(X509_ALGOR) *, sk)))
+
+#define sk_X509_ALGOR_push(sk, p) \
+ sk_push(CHECKED_CAST(_STACK *, STACK_OF(X509_ALGOR) *, sk), \
+ CHECKED_CAST(void *, X509_ALGOR *, p))
+
+#define sk_X509_ALGOR_pop(sk) \
+ ((X509_ALGOR *)sk_pop(CHECKED_CAST(_STACK *, STACK_OF(X509_ALGOR) *, sk)))
+
+#define sk_X509_ALGOR_dup(sk) \
+ ((STACK_OF(X509_ALGOR) *)sk_dup( \
+ CHECKED_CAST(_STACK *, const STACK_OF(X509_ALGOR) *, sk)))
+
+#define sk_X509_ALGOR_sort(sk) \
+ sk_sort(CHECKED_CAST(_STACK *, STACK_OF(X509_ALGOR) *, sk))
+
+#define sk_X509_ALGOR_is_sorted(sk) \
+ sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(X509_ALGOR) *, sk))
+
+#define sk_X509_ALGOR_set_cmp_func(sk, comp) \
+ ((int (*)(const X509_ALGOR **a, const X509_ALGOR **b))sk_set_cmp_func( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_ALGOR) *, sk), \
+ CHECKED_CAST(stack_cmp_func, \
+ int (*)(const X509_ALGOR **a, const X509_ALGOR **b), \
+ comp)))
+
+
+/* X509_ATTRIBUTE */
+#define sk_X509_ATTRIBUTE_new(comp) \
+ ((STACK_OF(X509_ATTRIBUTE) *)sk_new(CHECKED_CAST( \
+ stack_cmp_func, \
+ int (*)(const X509_ATTRIBUTE **a, const X509_ATTRIBUTE **b), comp)))
+
+#define sk_X509_ATTRIBUTE_new_null() ((STACK_OF(X509_ATTRIBUTE) *)sk_new_null())
+
+#define sk_X509_ATTRIBUTE_num(sk) \
+ sk_num(CHECKED_CAST(_STACK *, STACK_OF(X509_ATTRIBUTE) *, sk))
+
+#define sk_X509_ATTRIBUTE_zero(sk) \
+ sk_zero(CHECKED_CAST(_STACK *, STACK_OF(X509_ATTRIBUTE) *, sk));
+
+#define sk_X509_ATTRIBUTE_value(sk, i) \
+ ((X509_ATTRIBUTE *)sk_value( \
+ CHECKED_CAST(_STACK *, const STACK_OF(X509_ATTRIBUTE) *, sk), (i)))
+
+#define sk_X509_ATTRIBUTE_set(sk, i, p) \
+ ((X509_ATTRIBUTE *)sk_set( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_ATTRIBUTE) *, sk), (i), \
+ CHECKED_CAST(void *, X509_ATTRIBUTE *, p)))
+
+#define sk_X509_ATTRIBUTE_free(sk) \
+ sk_free(CHECKED_CAST(_STACK *, STACK_OF(X509_ATTRIBUTE) *, sk))
+
+#define sk_X509_ATTRIBUTE_pop_free(sk, free_func) \
+ sk_pop_free( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_ATTRIBUTE) *, sk), \
+ CHECKED_CAST(void (*)(void *), void (*)(X509_ATTRIBUTE *), free_func))
+
+#define sk_X509_ATTRIBUTE_insert(sk, p, where) \
+ sk_insert(CHECKED_CAST(_STACK *, STACK_OF(X509_ATTRIBUTE) *, sk), \
+ CHECKED_CAST(void *, X509_ATTRIBUTE *, p), (where))
+
+#define sk_X509_ATTRIBUTE_delete(sk, where) \
+ ((X509_ATTRIBUTE *)sk_delete( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_ATTRIBUTE) *, sk), (where)))
+
+#define sk_X509_ATTRIBUTE_delete_ptr(sk, p) \
+ ((X509_ATTRIBUTE *)sk_delete_ptr( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_ATTRIBUTE) *, sk), \
+ CHECKED_CAST(void *, X509_ATTRIBUTE *, p)))
+
+#define sk_X509_ATTRIBUTE_find(sk, out_index, p) \
+ sk_find(CHECKED_CAST(_STACK *, STACK_OF(X509_ATTRIBUTE) *, sk), (out_index), \
+ CHECKED_CAST(void *, X509_ATTRIBUTE *, p))
+
+#define sk_X509_ATTRIBUTE_shift(sk) \
+ ((X509_ATTRIBUTE *)sk_shift( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_ATTRIBUTE) *, sk)))
+
+#define sk_X509_ATTRIBUTE_push(sk, p) \
+ sk_push(CHECKED_CAST(_STACK *, STACK_OF(X509_ATTRIBUTE) *, sk), \
+ CHECKED_CAST(void *, X509_ATTRIBUTE *, p))
+
+#define sk_X509_ATTRIBUTE_pop(sk) \
+ ((X509_ATTRIBUTE *)sk_pop( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_ATTRIBUTE) *, sk)))
+
+#define sk_X509_ATTRIBUTE_dup(sk) \
+ ((STACK_OF(X509_ATTRIBUTE) *)sk_dup( \
+ CHECKED_CAST(_STACK *, const STACK_OF(X509_ATTRIBUTE) *, sk)))
+
+#define sk_X509_ATTRIBUTE_sort(sk) \
+ sk_sort(CHECKED_CAST(_STACK *, STACK_OF(X509_ATTRIBUTE) *, sk))
+
+#define sk_X509_ATTRIBUTE_is_sorted(sk) \
+ sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(X509_ATTRIBUTE) *, sk))
+
+#define sk_X509_ATTRIBUTE_set_cmp_func(sk, comp) \
+ ((int (*)(const X509_ATTRIBUTE **a, const X509_ATTRIBUTE **b)) \
+ sk_set_cmp_func( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_ATTRIBUTE) *, sk), \
+ CHECKED_CAST(stack_cmp_func, int (*)(const X509_ATTRIBUTE **a, \
+ const X509_ATTRIBUTE **b), \
+ comp)))
+
+
+/* X509_CRL */
+#define sk_X509_CRL_new(comp) \
+ ((STACK_OF(X509_CRL) *)sk_new(CHECKED_CAST( \
+ stack_cmp_func, int (*)(const X509_CRL **a, const X509_CRL **b), comp)))
+
+#define sk_X509_CRL_new_null() ((STACK_OF(X509_CRL) *)sk_new_null())
+
+#define sk_X509_CRL_num(sk) \
+ sk_num(CHECKED_CAST(_STACK *, STACK_OF(X509_CRL) *, sk))
+
+#define sk_X509_CRL_zero(sk) \
+ sk_zero(CHECKED_CAST(_STACK *, STACK_OF(X509_CRL) *, sk));
+
+#define sk_X509_CRL_value(sk, i) \
+ ((X509_CRL *)sk_value( \
+ CHECKED_CAST(_STACK *, const STACK_OF(X509_CRL) *, sk), (i)))
+
+#define sk_X509_CRL_set(sk, i, p) \
+ ((X509_CRL *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(X509_CRL) *, sk), (i), \
+ CHECKED_CAST(void *, X509_CRL *, p)))
+
+#define sk_X509_CRL_free(sk) \
+ sk_free(CHECKED_CAST(_STACK *, STACK_OF(X509_CRL) *, sk))
+
+#define sk_X509_CRL_pop_free(sk, free_func) \
+ sk_pop_free(CHECKED_CAST(_STACK *, STACK_OF(X509_CRL) *, sk), \
+ CHECKED_CAST(void (*)(void *), void (*)(X509_CRL *), free_func))
+
+#define sk_X509_CRL_insert(sk, p, where) \
+ sk_insert(CHECKED_CAST(_STACK *, STACK_OF(X509_CRL) *, sk), \
+ CHECKED_CAST(void *, X509_CRL *, p), (where))
+
+#define sk_X509_CRL_delete(sk, where) \
+ ((X509_CRL *)sk_delete(CHECKED_CAST(_STACK *, STACK_OF(X509_CRL) *, sk), \
+ (where)))
+
+#define sk_X509_CRL_delete_ptr(sk, p) \
+ ((X509_CRL *)sk_delete_ptr(CHECKED_CAST(_STACK *, STACK_OF(X509_CRL) *, sk), \
+ CHECKED_CAST(void *, X509_CRL *, p)))
+
+#define sk_X509_CRL_find(sk, out_index, p) \
+ sk_find(CHECKED_CAST(_STACK *, STACK_OF(X509_CRL) *, sk), (out_index), \
+ CHECKED_CAST(void *, X509_CRL *, p))
+
+#define sk_X509_CRL_shift(sk) \
+ ((X509_CRL *)sk_shift(CHECKED_CAST(_STACK *, STACK_OF(X509_CRL) *, sk)))
+
+#define sk_X509_CRL_push(sk, p) \
+ sk_push(CHECKED_CAST(_STACK *, STACK_OF(X509_CRL) *, sk), \
+ CHECKED_CAST(void *, X509_CRL *, p))
+
+#define sk_X509_CRL_pop(sk) \
+ ((X509_CRL *)sk_pop(CHECKED_CAST(_STACK *, STACK_OF(X509_CRL) *, sk)))
+
+#define sk_X509_CRL_dup(sk) \
+ ((STACK_OF(X509_CRL) *)sk_dup( \
+ CHECKED_CAST(_STACK *, const STACK_OF(X509_CRL) *, sk)))
+
+#define sk_X509_CRL_sort(sk) \
+ sk_sort(CHECKED_CAST(_STACK *, STACK_OF(X509_CRL) *, sk))
+
+#define sk_X509_CRL_is_sorted(sk) \
+ sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(X509_CRL) *, sk))
+
+#define sk_X509_CRL_set_cmp_func(sk, comp) \
+ ((int (*)(const X509_CRL **a, const X509_CRL **b))sk_set_cmp_func( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_CRL) *, sk), \
+ CHECKED_CAST(stack_cmp_func, \
+ int (*)(const X509_CRL **a, const X509_CRL **b), comp)))
+
+
+/* X509_EXTENSION */
+#define sk_X509_EXTENSION_new(comp) \
+ ((STACK_OF(X509_EXTENSION) *)sk_new(CHECKED_CAST( \
+ stack_cmp_func, \
+ int (*)(const X509_EXTENSION **a, const X509_EXTENSION **b), comp)))
+
+#define sk_X509_EXTENSION_new_null() ((STACK_OF(X509_EXTENSION) *)sk_new_null())
+
+#define sk_X509_EXTENSION_num(sk) \
+ sk_num(CHECKED_CAST(_STACK *, STACK_OF(X509_EXTENSION) *, sk))
+
+#define sk_X509_EXTENSION_zero(sk) \
+ sk_zero(CHECKED_CAST(_STACK *, STACK_OF(X509_EXTENSION) *, sk));
+
+#define sk_X509_EXTENSION_value(sk, i) \
+ ((X509_EXTENSION *)sk_value( \
+ CHECKED_CAST(_STACK *, const STACK_OF(X509_EXTENSION) *, sk), (i)))
+
+#define sk_X509_EXTENSION_set(sk, i, p) \
+ ((X509_EXTENSION *)sk_set( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_EXTENSION) *, sk), (i), \
+ CHECKED_CAST(void *, X509_EXTENSION *, p)))
+
+#define sk_X509_EXTENSION_free(sk) \
+ sk_free(CHECKED_CAST(_STACK *, STACK_OF(X509_EXTENSION) *, sk))
+
+#define sk_X509_EXTENSION_pop_free(sk, free_func) \
+ sk_pop_free( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_EXTENSION) *, sk), \
+ CHECKED_CAST(void (*)(void *), void (*)(X509_EXTENSION *), free_func))
+
+#define sk_X509_EXTENSION_insert(sk, p, where) \
+ sk_insert(CHECKED_CAST(_STACK *, STACK_OF(X509_EXTENSION) *, sk), \
+ CHECKED_CAST(void *, X509_EXTENSION *, p), (where))
+
+#define sk_X509_EXTENSION_delete(sk, where) \
+ ((X509_EXTENSION *)sk_delete( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_EXTENSION) *, sk), (where)))
+
+#define sk_X509_EXTENSION_delete_ptr(sk, p) \
+ ((X509_EXTENSION *)sk_delete_ptr( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_EXTENSION) *, sk), \
+ CHECKED_CAST(void *, X509_EXTENSION *, p)))
+
+#define sk_X509_EXTENSION_find(sk, out_index, p) \
+ sk_find(CHECKED_CAST(_STACK *, STACK_OF(X509_EXTENSION) *, sk), (out_index), \
+ CHECKED_CAST(void *, X509_EXTENSION *, p))
+
+#define sk_X509_EXTENSION_shift(sk) \
+ ((X509_EXTENSION *)sk_shift( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_EXTENSION) *, sk)))
+
+#define sk_X509_EXTENSION_push(sk, p) \
+ sk_push(CHECKED_CAST(_STACK *, STACK_OF(X509_EXTENSION) *, sk), \
+ CHECKED_CAST(void *, X509_EXTENSION *, p))
+
+#define sk_X509_EXTENSION_pop(sk) \
+ ((X509_EXTENSION *)sk_pop( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_EXTENSION) *, sk)))
+
+#define sk_X509_EXTENSION_dup(sk) \
+ ((STACK_OF(X509_EXTENSION) *)sk_dup( \
+ CHECKED_CAST(_STACK *, const STACK_OF(X509_EXTENSION) *, sk)))
+
+#define sk_X509_EXTENSION_sort(sk) \
+ sk_sort(CHECKED_CAST(_STACK *, STACK_OF(X509_EXTENSION) *, sk))
+
+#define sk_X509_EXTENSION_is_sorted(sk) \
+ sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(X509_EXTENSION) *, sk))
+
+#define sk_X509_EXTENSION_set_cmp_func(sk, comp) \
+ ((int (*)(const X509_EXTENSION **a, const X509_EXTENSION **b)) \
+ sk_set_cmp_func( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_EXTENSION) *, sk), \
+ CHECKED_CAST(stack_cmp_func, int (*)(const X509_EXTENSION **a, \
+ const X509_EXTENSION **b), \
+ comp)))
+
+
+/* X509_INFO */
+#define sk_X509_INFO_new(comp) \
+ ((STACK_OF(X509_INFO) *)sk_new( \
+ CHECKED_CAST(stack_cmp_func, \
+ int (*)(const X509_INFO **a, const X509_INFO **b), comp)))
+
+#define sk_X509_INFO_new_null() ((STACK_OF(X509_INFO) *)sk_new_null())
+
+#define sk_X509_INFO_num(sk) \
+ sk_num(CHECKED_CAST(_STACK *, STACK_OF(X509_INFO) *, sk))
+
+#define sk_X509_INFO_zero(sk) \
+ sk_zero(CHECKED_CAST(_STACK *, STACK_OF(X509_INFO) *, sk));
+
+#define sk_X509_INFO_value(sk, i) \
+ ((X509_INFO *)sk_value( \
+ CHECKED_CAST(_STACK *, const STACK_OF(X509_INFO) *, sk), (i)))
+
+#define sk_X509_INFO_set(sk, i, p) \
+ ((X509_INFO *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(X509_INFO) *, sk), (i), \
+ CHECKED_CAST(void *, X509_INFO *, p)))
+
+#define sk_X509_INFO_free(sk) \
+ sk_free(CHECKED_CAST(_STACK *, STACK_OF(X509_INFO) *, sk))
+
+#define sk_X509_INFO_pop_free(sk, free_func) \
+ sk_pop_free( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_INFO) *, sk), \
+ CHECKED_CAST(void (*)(void *), void (*)(X509_INFO *), free_func))
+
+#define sk_X509_INFO_insert(sk, p, where) \
+ sk_insert(CHECKED_CAST(_STACK *, STACK_OF(X509_INFO) *, sk), \
+ CHECKED_CAST(void *, X509_INFO *, p), (where))
+
+#define sk_X509_INFO_delete(sk, where) \
+ ((X509_INFO *)sk_delete(CHECKED_CAST(_STACK *, STACK_OF(X509_INFO) *, sk), \
+ (where)))
+
+#define sk_X509_INFO_delete_ptr(sk, p) \
+ ((X509_INFO *)sk_delete_ptr( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_INFO) *, sk), \
+ CHECKED_CAST(void *, X509_INFO *, p)))
+
+#define sk_X509_INFO_find(sk, out_index, p) \
+ sk_find(CHECKED_CAST(_STACK *, STACK_OF(X509_INFO) *, sk), (out_index), \
+ CHECKED_CAST(void *, X509_INFO *, p))
+
+#define sk_X509_INFO_shift(sk) \
+ ((X509_INFO *)sk_shift(CHECKED_CAST(_STACK *, STACK_OF(X509_INFO) *, sk)))
+
+#define sk_X509_INFO_push(sk, p) \
+ sk_push(CHECKED_CAST(_STACK *, STACK_OF(X509_INFO) *, sk), \
+ CHECKED_CAST(void *, X509_INFO *, p))
+
+#define sk_X509_INFO_pop(sk) \
+ ((X509_INFO *)sk_pop(CHECKED_CAST(_STACK *, STACK_OF(X509_INFO) *, sk)))
+
+#define sk_X509_INFO_dup(sk) \
+ ((STACK_OF(X509_INFO) *)sk_dup( \
+ CHECKED_CAST(_STACK *, const STACK_OF(X509_INFO) *, sk)))
+
+#define sk_X509_INFO_sort(sk) \
+ sk_sort(CHECKED_CAST(_STACK *, STACK_OF(X509_INFO) *, sk))
+
+#define sk_X509_INFO_is_sorted(sk) \
+ sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(X509_INFO) *, sk))
+
+#define sk_X509_INFO_set_cmp_func(sk, comp) \
+ ((int (*)(const X509_INFO **a, const X509_INFO **b))sk_set_cmp_func( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_INFO) *, sk), \
+ CHECKED_CAST(stack_cmp_func, \
+ int (*)(const X509_INFO **a, const X509_INFO **b), comp)))
+
+
+/* X509_LOOKUP */
+#define sk_X509_LOOKUP_new(comp) \
+ ((STACK_OF(X509_LOOKUP) *)sk_new(CHECKED_CAST( \
+ stack_cmp_func, int (*)(const X509_LOOKUP **a, const X509_LOOKUP **b), \
+ comp)))
+
+#define sk_X509_LOOKUP_new_null() ((STACK_OF(X509_LOOKUP) *)sk_new_null())
+
+#define sk_X509_LOOKUP_num(sk) \
+ sk_num(CHECKED_CAST(_STACK *, STACK_OF(X509_LOOKUP) *, sk))
+
+#define sk_X509_LOOKUP_zero(sk) \
+ sk_zero(CHECKED_CAST(_STACK *, STACK_OF(X509_LOOKUP) *, sk));
+
+#define sk_X509_LOOKUP_value(sk, i) \
+ ((X509_LOOKUP *)sk_value( \
+ CHECKED_CAST(_STACK *, const STACK_OF(X509_LOOKUP) *, sk), (i)))
+
+#define sk_X509_LOOKUP_set(sk, i, p) \
+ ((X509_LOOKUP *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(X509_LOOKUP) *, sk), \
+ (i), CHECKED_CAST(void *, X509_LOOKUP *, p)))
+
+#define sk_X509_LOOKUP_free(sk) \
+ sk_free(CHECKED_CAST(_STACK *, STACK_OF(X509_LOOKUP) *, sk))
+
+#define sk_X509_LOOKUP_pop_free(sk, free_func) \
+ sk_pop_free( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_LOOKUP) *, sk), \
+ CHECKED_CAST(void (*)(void *), void (*)(X509_LOOKUP *), free_func))
+
+#define sk_X509_LOOKUP_insert(sk, p, where) \
+ sk_insert(CHECKED_CAST(_STACK *, STACK_OF(X509_LOOKUP) *, sk), \
+ CHECKED_CAST(void *, X509_LOOKUP *, p), (where))
+
+#define sk_X509_LOOKUP_delete(sk, where) \
+ ((X509_LOOKUP *)sk_delete( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_LOOKUP) *, sk), (where)))
+
+#define sk_X509_LOOKUP_delete_ptr(sk, p) \
+ ((X509_LOOKUP *)sk_delete_ptr( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_LOOKUP) *, sk), \
+ CHECKED_CAST(void *, X509_LOOKUP *, p)))
+
+#define sk_X509_LOOKUP_find(sk, out_index, p) \
+ sk_find(CHECKED_CAST(_STACK *, STACK_OF(X509_LOOKUP) *, sk), (out_index), \
+ CHECKED_CAST(void *, X509_LOOKUP *, p))
+
+#define sk_X509_LOOKUP_shift(sk) \
+ ((X509_LOOKUP *)sk_shift(CHECKED_CAST(_STACK *, STACK_OF(X509_LOOKUP) *, sk)))
+
+#define sk_X509_LOOKUP_push(sk, p) \
+ sk_push(CHECKED_CAST(_STACK *, STACK_OF(X509_LOOKUP) *, sk), \
+ CHECKED_CAST(void *, X509_LOOKUP *, p))
+
+#define sk_X509_LOOKUP_pop(sk) \
+ ((X509_LOOKUP *)sk_pop(CHECKED_CAST(_STACK *, STACK_OF(X509_LOOKUP) *, sk)))
+
+#define sk_X509_LOOKUP_dup(sk) \
+ ((STACK_OF(X509_LOOKUP) *)sk_dup( \
+ CHECKED_CAST(_STACK *, const STACK_OF(X509_LOOKUP) *, sk)))
+
+#define sk_X509_LOOKUP_sort(sk) \
+ sk_sort(CHECKED_CAST(_STACK *, STACK_OF(X509_LOOKUP) *, sk))
+
+#define sk_X509_LOOKUP_is_sorted(sk) \
+ sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(X509_LOOKUP) *, sk))
+
+#define sk_X509_LOOKUP_set_cmp_func(sk, comp) \
+ ((int (*)(const X509_LOOKUP **a, const X509_LOOKUP **b))sk_set_cmp_func( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_LOOKUP) *, sk), \
+ CHECKED_CAST(stack_cmp_func, \
+ int (*)(const X509_LOOKUP **a, const X509_LOOKUP **b), \
+ comp)))
+
+
+/* X509_NAME */
+#define sk_X509_NAME_new(comp) \
+ ((STACK_OF(X509_NAME) *)sk_new( \
+ CHECKED_CAST(stack_cmp_func, \
+ int (*)(const X509_NAME **a, const X509_NAME **b), comp)))
+
+#define sk_X509_NAME_new_null() ((STACK_OF(X509_NAME) *)sk_new_null())
+
+#define sk_X509_NAME_num(sk) \
+ sk_num(CHECKED_CAST(_STACK *, STACK_OF(X509_NAME) *, sk))
+
+#define sk_X509_NAME_zero(sk) \
+ sk_zero(CHECKED_CAST(_STACK *, STACK_OF(X509_NAME) *, sk));
+
+#define sk_X509_NAME_value(sk, i) \
+ ((X509_NAME *)sk_value( \
+ CHECKED_CAST(_STACK *, const STACK_OF(X509_NAME) *, sk), (i)))
+
+#define sk_X509_NAME_set(sk, i, p) \
+ ((X509_NAME *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(X509_NAME) *, sk), (i), \
+ CHECKED_CAST(void *, X509_NAME *, p)))
+
+#define sk_X509_NAME_free(sk) \
+ sk_free(CHECKED_CAST(_STACK *, STACK_OF(X509_NAME) *, sk))
+
+#define sk_X509_NAME_pop_free(sk, free_func) \
+ sk_pop_free( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_NAME) *, sk), \
+ CHECKED_CAST(void (*)(void *), void (*)(X509_NAME *), free_func))
+
+#define sk_X509_NAME_insert(sk, p, where) \
+ sk_insert(CHECKED_CAST(_STACK *, STACK_OF(X509_NAME) *, sk), \
+ CHECKED_CAST(void *, X509_NAME *, p), (where))
+
+#define sk_X509_NAME_delete(sk, where) \
+ ((X509_NAME *)sk_delete(CHECKED_CAST(_STACK *, STACK_OF(X509_NAME) *, sk), \
+ (where)))
+
+#define sk_X509_NAME_delete_ptr(sk, p) \
+ ((X509_NAME *)sk_delete_ptr( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_NAME) *, sk), \
+ CHECKED_CAST(void *, X509_NAME *, p)))
+
+#define sk_X509_NAME_find(sk, out_index, p) \
+ sk_find(CHECKED_CAST(_STACK *, STACK_OF(X509_NAME) *, sk), (out_index), \
+ CHECKED_CAST(void *, X509_NAME *, p))
+
+#define sk_X509_NAME_shift(sk) \
+ ((X509_NAME *)sk_shift(CHECKED_CAST(_STACK *, STACK_OF(X509_NAME) *, sk)))
+
+#define sk_X509_NAME_push(sk, p) \
+ sk_push(CHECKED_CAST(_STACK *, STACK_OF(X509_NAME) *, sk), \
+ CHECKED_CAST(void *, X509_NAME *, p))
+
+#define sk_X509_NAME_pop(sk) \
+ ((X509_NAME *)sk_pop(CHECKED_CAST(_STACK *, STACK_OF(X509_NAME) *, sk)))
+
+#define sk_X509_NAME_dup(sk) \
+ ((STACK_OF(X509_NAME) *)sk_dup( \
+ CHECKED_CAST(_STACK *, const STACK_OF(X509_NAME) *, sk)))
+
+#define sk_X509_NAME_sort(sk) \
+ sk_sort(CHECKED_CAST(_STACK *, STACK_OF(X509_NAME) *, sk))
+
+#define sk_X509_NAME_is_sorted(sk) \
+ sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(X509_NAME) *, sk))
+
+#define sk_X509_NAME_set_cmp_func(sk, comp) \
+ ((int (*)(const X509_NAME **a, const X509_NAME **b))sk_set_cmp_func( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_NAME) *, sk), \
+ CHECKED_CAST(stack_cmp_func, \
+ int (*)(const X509_NAME **a, const X509_NAME **b), comp)))
+
+
+/* X509_NAME_ENTRY */
+#define sk_X509_NAME_ENTRY_new(comp) \
+ ((STACK_OF(X509_NAME_ENTRY) *)sk_new(CHECKED_CAST( \
+ stack_cmp_func, \
+ int (*)(const X509_NAME_ENTRY **a, const X509_NAME_ENTRY **b), comp)))
+
+#define sk_X509_NAME_ENTRY_new_null() \
+ ((STACK_OF(X509_NAME_ENTRY) *)sk_new_null())
+
+#define sk_X509_NAME_ENTRY_num(sk) \
+ sk_num(CHECKED_CAST(_STACK *, STACK_OF(X509_NAME_ENTRY) *, sk))
+
+#define sk_X509_NAME_ENTRY_zero(sk) \
+ sk_zero(CHECKED_CAST(_STACK *, STACK_OF(X509_NAME_ENTRY) *, sk));
+
+#define sk_X509_NAME_ENTRY_value(sk, i) \
+ ((X509_NAME_ENTRY *)sk_value( \
+ CHECKED_CAST(_STACK *, const STACK_OF(X509_NAME_ENTRY) *, sk), (i)))
+
+#define sk_X509_NAME_ENTRY_set(sk, i, p) \
+ ((X509_NAME_ENTRY *)sk_set( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_NAME_ENTRY) *, sk), (i), \
+ CHECKED_CAST(void *, X509_NAME_ENTRY *, p)))
+
+#define sk_X509_NAME_ENTRY_free(sk) \
+ sk_free(CHECKED_CAST(_STACK *, STACK_OF(X509_NAME_ENTRY) *, sk))
+
+#define sk_X509_NAME_ENTRY_pop_free(sk, free_func) \
+ sk_pop_free( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_NAME_ENTRY) *, sk), \
+ CHECKED_CAST(void (*)(void *), void (*)(X509_NAME_ENTRY *), free_func))
+
+#define sk_X509_NAME_ENTRY_insert(sk, p, where) \
+ sk_insert(CHECKED_CAST(_STACK *, STACK_OF(X509_NAME_ENTRY) *, sk), \
+ CHECKED_CAST(void *, X509_NAME_ENTRY *, p), (where))
+
+#define sk_X509_NAME_ENTRY_delete(sk, where) \
+ ((X509_NAME_ENTRY *)sk_delete( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_NAME_ENTRY) *, sk), (where)))
+
+#define sk_X509_NAME_ENTRY_delete_ptr(sk, p) \
+ ((X509_NAME_ENTRY *)sk_delete_ptr( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_NAME_ENTRY) *, sk), \
+ CHECKED_CAST(void *, X509_NAME_ENTRY *, p)))
+
+#define sk_X509_NAME_ENTRY_find(sk, out_index, p) \
+ sk_find(CHECKED_CAST(_STACK *, STACK_OF(X509_NAME_ENTRY) *, sk), \
+ (out_index), CHECKED_CAST(void *, X509_NAME_ENTRY *, p))
+
+#define sk_X509_NAME_ENTRY_shift(sk) \
+ ((X509_NAME_ENTRY *)sk_shift( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_NAME_ENTRY) *, sk)))
+
+#define sk_X509_NAME_ENTRY_push(sk, p) \
+ sk_push(CHECKED_CAST(_STACK *, STACK_OF(X509_NAME_ENTRY) *, sk), \
+ CHECKED_CAST(void *, X509_NAME_ENTRY *, p))
+
+#define sk_X509_NAME_ENTRY_pop(sk) \
+ ((X509_NAME_ENTRY *)sk_pop( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_NAME_ENTRY) *, sk)))
+
+#define sk_X509_NAME_ENTRY_dup(sk) \
+ ((STACK_OF(X509_NAME_ENTRY) *)sk_dup( \
+ CHECKED_CAST(_STACK *, const STACK_OF(X509_NAME_ENTRY) *, sk)))
+
+#define sk_X509_NAME_ENTRY_sort(sk) \
+ sk_sort(CHECKED_CAST(_STACK *, STACK_OF(X509_NAME_ENTRY) *, sk))
+
+#define sk_X509_NAME_ENTRY_is_sorted(sk) \
+ sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(X509_NAME_ENTRY) *, sk))
+
+#define sk_X509_NAME_ENTRY_set_cmp_func(sk, comp) \
+ ((int (*)(const X509_NAME_ENTRY **a, const X509_NAME_ENTRY **b)) \
+ sk_set_cmp_func( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_NAME_ENTRY) *, sk), \
+ CHECKED_CAST(stack_cmp_func, int (*)(const X509_NAME_ENTRY **a, \
+ const X509_NAME_ENTRY **b), \
+ comp)))
+
+
+/* X509_OBJECT */
+#define sk_X509_OBJECT_new(comp) \
+ ((STACK_OF(X509_OBJECT) *)sk_new(CHECKED_CAST( \
+ stack_cmp_func, int (*)(const X509_OBJECT **a, const X509_OBJECT **b), \
+ comp)))
+
+#define sk_X509_OBJECT_new_null() ((STACK_OF(X509_OBJECT) *)sk_new_null())
+
+#define sk_X509_OBJECT_num(sk) \
+ sk_num(CHECKED_CAST(_STACK *, STACK_OF(X509_OBJECT) *, sk))
+
+#define sk_X509_OBJECT_zero(sk) \
+ sk_zero(CHECKED_CAST(_STACK *, STACK_OF(X509_OBJECT) *, sk));
+
+#define sk_X509_OBJECT_value(sk, i) \
+ ((X509_OBJECT *)sk_value( \
+ CHECKED_CAST(_STACK *, const STACK_OF(X509_OBJECT) *, sk), (i)))
+
+#define sk_X509_OBJECT_set(sk, i, p) \
+ ((X509_OBJECT *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(X509_OBJECT) *, sk), \
+ (i), CHECKED_CAST(void *, X509_OBJECT *, p)))
+
+#define sk_X509_OBJECT_free(sk) \
+ sk_free(CHECKED_CAST(_STACK *, STACK_OF(X509_OBJECT) *, sk))
+
+#define sk_X509_OBJECT_pop_free(sk, free_func) \
+ sk_pop_free( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_OBJECT) *, sk), \
+ CHECKED_CAST(void (*)(void *), void (*)(X509_OBJECT *), free_func))
+
+#define sk_X509_OBJECT_insert(sk, p, where) \
+ sk_insert(CHECKED_CAST(_STACK *, STACK_OF(X509_OBJECT) *, sk), \
+ CHECKED_CAST(void *, X509_OBJECT *, p), (where))
+
+#define sk_X509_OBJECT_delete(sk, where) \
+ ((X509_OBJECT *)sk_delete( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_OBJECT) *, sk), (where)))
+
+#define sk_X509_OBJECT_delete_ptr(sk, p) \
+ ((X509_OBJECT *)sk_delete_ptr( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_OBJECT) *, sk), \
+ CHECKED_CAST(void *, X509_OBJECT *, p)))
+
+#define sk_X509_OBJECT_find(sk, out_index, p) \
+ sk_find(CHECKED_CAST(_STACK *, STACK_OF(X509_OBJECT) *, sk), (out_index), \
+ CHECKED_CAST(void *, X509_OBJECT *, p))
+
+#define sk_X509_OBJECT_shift(sk) \
+ ((X509_OBJECT *)sk_shift(CHECKED_CAST(_STACK *, STACK_OF(X509_OBJECT) *, sk)))
+
+#define sk_X509_OBJECT_push(sk, p) \
+ sk_push(CHECKED_CAST(_STACK *, STACK_OF(X509_OBJECT) *, sk), \
+ CHECKED_CAST(void *, X509_OBJECT *, p))
+
+#define sk_X509_OBJECT_pop(sk) \
+ ((X509_OBJECT *)sk_pop(CHECKED_CAST(_STACK *, STACK_OF(X509_OBJECT) *, sk)))
+
+#define sk_X509_OBJECT_dup(sk) \
+ ((STACK_OF(X509_OBJECT) *)sk_dup( \
+ CHECKED_CAST(_STACK *, const STACK_OF(X509_OBJECT) *, sk)))
+
+#define sk_X509_OBJECT_sort(sk) \
+ sk_sort(CHECKED_CAST(_STACK *, STACK_OF(X509_OBJECT) *, sk))
+
+#define sk_X509_OBJECT_is_sorted(sk) \
+ sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(X509_OBJECT) *, sk))
+
+#define sk_X509_OBJECT_set_cmp_func(sk, comp) \
+ ((int (*)(const X509_OBJECT **a, const X509_OBJECT **b))sk_set_cmp_func( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_OBJECT) *, sk), \
+ CHECKED_CAST(stack_cmp_func, \
+ int (*)(const X509_OBJECT **a, const X509_OBJECT **b), \
+ comp)))
+
+
+/* X509_POLICY_DATA */
+#define sk_X509_POLICY_DATA_new(comp) \
+ ((STACK_OF(X509_POLICY_DATA) *)sk_new(CHECKED_CAST( \
+ stack_cmp_func, \
+ int (*)(const X509_POLICY_DATA **a, const X509_POLICY_DATA **b), comp)))
+
+#define sk_X509_POLICY_DATA_new_null() \
+ ((STACK_OF(X509_POLICY_DATA) *)sk_new_null())
+
+#define sk_X509_POLICY_DATA_num(sk) \
+ sk_num(CHECKED_CAST(_STACK *, STACK_OF(X509_POLICY_DATA) *, sk))
+
+#define sk_X509_POLICY_DATA_zero(sk) \
+ sk_zero(CHECKED_CAST(_STACK *, STACK_OF(X509_POLICY_DATA) *, sk));
+
+#define sk_X509_POLICY_DATA_value(sk, i) \
+ ((X509_POLICY_DATA *)sk_value( \
+ CHECKED_CAST(_STACK *, const STACK_OF(X509_POLICY_DATA) *, sk), (i)))
+
+#define sk_X509_POLICY_DATA_set(sk, i, p) \
+ ((X509_POLICY_DATA *)sk_set( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_POLICY_DATA) *, sk), (i), \
+ CHECKED_CAST(void *, X509_POLICY_DATA *, p)))
+
+#define sk_X509_POLICY_DATA_free(sk) \
+ sk_free(CHECKED_CAST(_STACK *, STACK_OF(X509_POLICY_DATA) *, sk))
+
+#define sk_X509_POLICY_DATA_pop_free(sk, free_func) \
+ sk_pop_free( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_POLICY_DATA) *, sk), \
+ CHECKED_CAST(void (*)(void *), void (*)(X509_POLICY_DATA *), free_func))
+
+#define sk_X509_POLICY_DATA_insert(sk, p, where) \
+ sk_insert(CHECKED_CAST(_STACK *, STACK_OF(X509_POLICY_DATA) *, sk), \
+ CHECKED_CAST(void *, X509_POLICY_DATA *, p), (where))
+
+#define sk_X509_POLICY_DATA_delete(sk, where) \
+ ((X509_POLICY_DATA *)sk_delete( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_POLICY_DATA) *, sk), (where)))
+
+#define sk_X509_POLICY_DATA_delete_ptr(sk, p) \
+ ((X509_POLICY_DATA *)sk_delete_ptr( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_POLICY_DATA) *, sk), \
+ CHECKED_CAST(void *, X509_POLICY_DATA *, p)))
+
+#define sk_X509_POLICY_DATA_find(sk, out_index, p) \
+ sk_find(CHECKED_CAST(_STACK *, STACK_OF(X509_POLICY_DATA) *, sk), \
+ (out_index), CHECKED_CAST(void *, X509_POLICY_DATA *, p))
+
+#define sk_X509_POLICY_DATA_shift(sk) \
+ ((X509_POLICY_DATA *)sk_shift( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_POLICY_DATA) *, sk)))
+
+#define sk_X509_POLICY_DATA_push(sk, p) \
+ sk_push(CHECKED_CAST(_STACK *, STACK_OF(X509_POLICY_DATA) *, sk), \
+ CHECKED_CAST(void *, X509_POLICY_DATA *, p))
+
+#define sk_X509_POLICY_DATA_pop(sk) \
+ ((X509_POLICY_DATA *)sk_pop( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_POLICY_DATA) *, sk)))
+
+#define sk_X509_POLICY_DATA_dup(sk) \
+ ((STACK_OF(X509_POLICY_DATA) *)sk_dup( \
+ CHECKED_CAST(_STACK *, const STACK_OF(X509_POLICY_DATA) *, sk)))
+
+#define sk_X509_POLICY_DATA_sort(sk) \
+ sk_sort(CHECKED_CAST(_STACK *, STACK_OF(X509_POLICY_DATA) *, sk))
+
+#define sk_X509_POLICY_DATA_is_sorted(sk) \
+ sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(X509_POLICY_DATA) *, sk))
+
+#define sk_X509_POLICY_DATA_set_cmp_func(sk, comp) \
+ ((int (*)(const X509_POLICY_DATA **a, const X509_POLICY_DATA **b)) \
+ sk_set_cmp_func( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_POLICY_DATA) *, sk), \
+ CHECKED_CAST(stack_cmp_func, int (*)(const X509_POLICY_DATA **a, \
+ const X509_POLICY_DATA **b), \
+ comp)))
+
+
+/* X509_POLICY_NODE */
+#define sk_X509_POLICY_NODE_new(comp) \
+ ((STACK_OF(X509_POLICY_NODE) *)sk_new(CHECKED_CAST( \
+ stack_cmp_func, \
+ int (*)(const X509_POLICY_NODE **a, const X509_POLICY_NODE **b), comp)))
+
+#define sk_X509_POLICY_NODE_new_null() \
+ ((STACK_OF(X509_POLICY_NODE) *)sk_new_null())
+
+#define sk_X509_POLICY_NODE_num(sk) \
+ sk_num(CHECKED_CAST(_STACK *, STACK_OF(X509_POLICY_NODE) *, sk))
+
+#define sk_X509_POLICY_NODE_zero(sk) \
+ sk_zero(CHECKED_CAST(_STACK *, STACK_OF(X509_POLICY_NODE) *, sk));
+
+#define sk_X509_POLICY_NODE_value(sk, i) \
+ ((X509_POLICY_NODE *)sk_value( \
+ CHECKED_CAST(_STACK *, const STACK_OF(X509_POLICY_NODE) *, sk), (i)))
+
+#define sk_X509_POLICY_NODE_set(sk, i, p) \
+ ((X509_POLICY_NODE *)sk_set( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_POLICY_NODE) *, sk), (i), \
+ CHECKED_CAST(void *, X509_POLICY_NODE *, p)))
+
+#define sk_X509_POLICY_NODE_free(sk) \
+ sk_free(CHECKED_CAST(_STACK *, STACK_OF(X509_POLICY_NODE) *, sk))
+
+#define sk_X509_POLICY_NODE_pop_free(sk, free_func) \
+ sk_pop_free( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_POLICY_NODE) *, sk), \
+ CHECKED_CAST(void (*)(void *), void (*)(X509_POLICY_NODE *), free_func))
+
+#define sk_X509_POLICY_NODE_insert(sk, p, where) \
+ sk_insert(CHECKED_CAST(_STACK *, STACK_OF(X509_POLICY_NODE) *, sk), \
+ CHECKED_CAST(void *, X509_POLICY_NODE *, p), (where))
+
+#define sk_X509_POLICY_NODE_delete(sk, where) \
+ ((X509_POLICY_NODE *)sk_delete( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_POLICY_NODE) *, sk), (where)))
+
+#define sk_X509_POLICY_NODE_delete_ptr(sk, p) \
+ ((X509_POLICY_NODE *)sk_delete_ptr( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_POLICY_NODE) *, sk), \
+ CHECKED_CAST(void *, X509_POLICY_NODE *, p)))
+
+#define sk_X509_POLICY_NODE_find(sk, out_index, p) \
+ sk_find(CHECKED_CAST(_STACK *, STACK_OF(X509_POLICY_NODE) *, sk), \
+ (out_index), CHECKED_CAST(void *, X509_POLICY_NODE *, p))
+
+#define sk_X509_POLICY_NODE_shift(sk) \
+ ((X509_POLICY_NODE *)sk_shift( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_POLICY_NODE) *, sk)))
+
+#define sk_X509_POLICY_NODE_push(sk, p) \
+ sk_push(CHECKED_CAST(_STACK *, STACK_OF(X509_POLICY_NODE) *, sk), \
+ CHECKED_CAST(void *, X509_POLICY_NODE *, p))
+
+#define sk_X509_POLICY_NODE_pop(sk) \
+ ((X509_POLICY_NODE *)sk_pop( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_POLICY_NODE) *, sk)))
+
+#define sk_X509_POLICY_NODE_dup(sk) \
+ ((STACK_OF(X509_POLICY_NODE) *)sk_dup( \
+ CHECKED_CAST(_STACK *, const STACK_OF(X509_POLICY_NODE) *, sk)))
+
+#define sk_X509_POLICY_NODE_sort(sk) \
+ sk_sort(CHECKED_CAST(_STACK *, STACK_OF(X509_POLICY_NODE) *, sk))
+
+#define sk_X509_POLICY_NODE_is_sorted(sk) \
+ sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(X509_POLICY_NODE) *, sk))
+
+#define sk_X509_POLICY_NODE_set_cmp_func(sk, comp) \
+ ((int (*)(const X509_POLICY_NODE **a, const X509_POLICY_NODE **b)) \
+ sk_set_cmp_func( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_POLICY_NODE) *, sk), \
+ CHECKED_CAST(stack_cmp_func, int (*)(const X509_POLICY_NODE **a, \
+ const X509_POLICY_NODE **b), \
+ comp)))
+
+
+/* X509_PURPOSE */
+#define sk_X509_PURPOSE_new(comp) \
+ ((STACK_OF(X509_PURPOSE) *)sk_new(CHECKED_CAST( \
+ stack_cmp_func, int (*)(const X509_PURPOSE **a, const X509_PURPOSE **b), \
+ comp)))
+
+#define sk_X509_PURPOSE_new_null() ((STACK_OF(X509_PURPOSE) *)sk_new_null())
+
+#define sk_X509_PURPOSE_num(sk) \
+ sk_num(CHECKED_CAST(_STACK *, STACK_OF(X509_PURPOSE) *, sk))
+
+#define sk_X509_PURPOSE_zero(sk) \
+ sk_zero(CHECKED_CAST(_STACK *, STACK_OF(X509_PURPOSE) *, sk));
+
+#define sk_X509_PURPOSE_value(sk, i) \
+ ((X509_PURPOSE *)sk_value( \
+ CHECKED_CAST(_STACK *, const STACK_OF(X509_PURPOSE) *, sk), (i)))
+
+#define sk_X509_PURPOSE_set(sk, i, p) \
+ ((X509_PURPOSE *)sk_set( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_PURPOSE) *, sk), (i), \
+ CHECKED_CAST(void *, X509_PURPOSE *, p)))
+
+#define sk_X509_PURPOSE_free(sk) \
+ sk_free(CHECKED_CAST(_STACK *, STACK_OF(X509_PURPOSE) *, sk))
+
+#define sk_X509_PURPOSE_pop_free(sk, free_func) \
+ sk_pop_free( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_PURPOSE) *, sk), \
+ CHECKED_CAST(void (*)(void *), void (*)(X509_PURPOSE *), free_func))
+
+#define sk_X509_PURPOSE_insert(sk, p, where) \
+ sk_insert(CHECKED_CAST(_STACK *, STACK_OF(X509_PURPOSE) *, sk), \
+ CHECKED_CAST(void *, X509_PURPOSE *, p), (where))
+
+#define sk_X509_PURPOSE_delete(sk, where) \
+ ((X509_PURPOSE *)sk_delete( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_PURPOSE) *, sk), (where)))
+
+#define sk_X509_PURPOSE_delete_ptr(sk, p) \
+ ((X509_PURPOSE *)sk_delete_ptr( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_PURPOSE) *, sk), \
+ CHECKED_CAST(void *, X509_PURPOSE *, p)))
+
+#define sk_X509_PURPOSE_find(sk, out_index, p) \
+ sk_find(CHECKED_CAST(_STACK *, STACK_OF(X509_PURPOSE) *, sk), (out_index), \
+ CHECKED_CAST(void *, X509_PURPOSE *, p))
+
+#define sk_X509_PURPOSE_shift(sk) \
+ ((X509_PURPOSE *)sk_shift( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_PURPOSE) *, sk)))
+
+#define sk_X509_PURPOSE_push(sk, p) \
+ sk_push(CHECKED_CAST(_STACK *, STACK_OF(X509_PURPOSE) *, sk), \
+ CHECKED_CAST(void *, X509_PURPOSE *, p))
+
+#define sk_X509_PURPOSE_pop(sk) \
+ ((X509_PURPOSE *)sk_pop(CHECKED_CAST(_STACK *, STACK_OF(X509_PURPOSE) *, sk)))
+
+#define sk_X509_PURPOSE_dup(sk) \
+ ((STACK_OF(X509_PURPOSE) *)sk_dup( \
+ CHECKED_CAST(_STACK *, const STACK_OF(X509_PURPOSE) *, sk)))
+
+#define sk_X509_PURPOSE_sort(sk) \
+ sk_sort(CHECKED_CAST(_STACK *, STACK_OF(X509_PURPOSE) *, sk))
+
+#define sk_X509_PURPOSE_is_sorted(sk) \
+ sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(X509_PURPOSE) *, sk))
+
+#define sk_X509_PURPOSE_set_cmp_func(sk, comp) \
+ ((int (*)(const X509_PURPOSE **a, const X509_PURPOSE **b))sk_set_cmp_func( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_PURPOSE) *, sk), \
+ CHECKED_CAST(stack_cmp_func, \
+ int (*)(const X509_PURPOSE **a, const X509_PURPOSE **b), \
+ comp)))
+
+
+/* X509_REVOKED */
+#define sk_X509_REVOKED_new(comp) \
+ ((STACK_OF(X509_REVOKED) *)sk_new(CHECKED_CAST( \
+ stack_cmp_func, int (*)(const X509_REVOKED **a, const X509_REVOKED **b), \
+ comp)))
+
+#define sk_X509_REVOKED_new_null() ((STACK_OF(X509_REVOKED) *)sk_new_null())
+
+#define sk_X509_REVOKED_num(sk) \
+ sk_num(CHECKED_CAST(_STACK *, STACK_OF(X509_REVOKED) *, sk))
+
+#define sk_X509_REVOKED_zero(sk) \
+ sk_zero(CHECKED_CAST(_STACK *, STACK_OF(X509_REVOKED) *, sk));
+
+#define sk_X509_REVOKED_value(sk, i) \
+ ((X509_REVOKED *)sk_value( \
+ CHECKED_CAST(_STACK *, const STACK_OF(X509_REVOKED) *, sk), (i)))
+
+#define sk_X509_REVOKED_set(sk, i, p) \
+ ((X509_REVOKED *)sk_set( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_REVOKED) *, sk), (i), \
+ CHECKED_CAST(void *, X509_REVOKED *, p)))
+
+#define sk_X509_REVOKED_free(sk) \
+ sk_free(CHECKED_CAST(_STACK *, STACK_OF(X509_REVOKED) *, sk))
+
+#define sk_X509_REVOKED_pop_free(sk, free_func) \
+ sk_pop_free( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_REVOKED) *, sk), \
+ CHECKED_CAST(void (*)(void *), void (*)(X509_REVOKED *), free_func))
+
+#define sk_X509_REVOKED_insert(sk, p, where) \
+ sk_insert(CHECKED_CAST(_STACK *, STACK_OF(X509_REVOKED) *, sk), \
+ CHECKED_CAST(void *, X509_REVOKED *, p), (where))
+
+#define sk_X509_REVOKED_delete(sk, where) \
+ ((X509_REVOKED *)sk_delete( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_REVOKED) *, sk), (where)))
+
+#define sk_X509_REVOKED_delete_ptr(sk, p) \
+ ((X509_REVOKED *)sk_delete_ptr( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_REVOKED) *, sk), \
+ CHECKED_CAST(void *, X509_REVOKED *, p)))
+
+#define sk_X509_REVOKED_find(sk, out_index, p) \
+ sk_find(CHECKED_CAST(_STACK *, STACK_OF(X509_REVOKED) *, sk), (out_index), \
+ CHECKED_CAST(void *, X509_REVOKED *, p))
+
+#define sk_X509_REVOKED_shift(sk) \
+ ((X509_REVOKED *)sk_shift( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_REVOKED) *, sk)))
+
+#define sk_X509_REVOKED_push(sk, p) \
+ sk_push(CHECKED_CAST(_STACK *, STACK_OF(X509_REVOKED) *, sk), \
+ CHECKED_CAST(void *, X509_REVOKED *, p))
+
+#define sk_X509_REVOKED_pop(sk) \
+ ((X509_REVOKED *)sk_pop(CHECKED_CAST(_STACK *, STACK_OF(X509_REVOKED) *, sk)))
+
+#define sk_X509_REVOKED_dup(sk) \
+ ((STACK_OF(X509_REVOKED) *)sk_dup( \
+ CHECKED_CAST(_STACK *, const STACK_OF(X509_REVOKED) *, sk)))
+
+#define sk_X509_REVOKED_sort(sk) \
+ sk_sort(CHECKED_CAST(_STACK *, STACK_OF(X509_REVOKED) *, sk))
+
+#define sk_X509_REVOKED_is_sorted(sk) \
+ sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(X509_REVOKED) *, sk))
+
+#define sk_X509_REVOKED_set_cmp_func(sk, comp) \
+ ((int (*)(const X509_REVOKED **a, const X509_REVOKED **b))sk_set_cmp_func( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_REVOKED) *, sk), \
+ CHECKED_CAST(stack_cmp_func, \
+ int (*)(const X509_REVOKED **a, const X509_REVOKED **b), \
+ comp)))
+
+
+/* X509_TRUST */
+#define sk_X509_TRUST_new(comp) \
+ ((STACK_OF(X509_TRUST) *)sk_new(CHECKED_CAST( \
+ stack_cmp_func, int (*)(const X509_TRUST **a, const X509_TRUST **b), \
+ comp)))
+
+#define sk_X509_TRUST_new_null() ((STACK_OF(X509_TRUST) *)sk_new_null())
+
+#define sk_X509_TRUST_num(sk) \
+ sk_num(CHECKED_CAST(_STACK *, STACK_OF(X509_TRUST) *, sk))
+
+#define sk_X509_TRUST_zero(sk) \
+ sk_zero(CHECKED_CAST(_STACK *, STACK_OF(X509_TRUST) *, sk));
+
+#define sk_X509_TRUST_value(sk, i) \
+ ((X509_TRUST *)sk_value( \
+ CHECKED_CAST(_STACK *, const STACK_OF(X509_TRUST) *, sk), (i)))
+
+#define sk_X509_TRUST_set(sk, i, p) \
+ ((X509_TRUST *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(X509_TRUST) *, sk), \
+ (i), CHECKED_CAST(void *, X509_TRUST *, p)))
+
+#define sk_X509_TRUST_free(sk) \
+ sk_free(CHECKED_CAST(_STACK *, STACK_OF(X509_TRUST) *, sk))
+
+#define sk_X509_TRUST_pop_free(sk, free_func) \
+ sk_pop_free( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_TRUST) *, sk), \
+ CHECKED_CAST(void (*)(void *), void (*)(X509_TRUST *), free_func))
+
+#define sk_X509_TRUST_insert(sk, p, where) \
+ sk_insert(CHECKED_CAST(_STACK *, STACK_OF(X509_TRUST) *, sk), \
+ CHECKED_CAST(void *, X509_TRUST *, p), (where))
+
+#define sk_X509_TRUST_delete(sk, where) \
+ ((X509_TRUST *)sk_delete(CHECKED_CAST(_STACK *, STACK_OF(X509_TRUST) *, sk), \
+ (where)))
+
+#define sk_X509_TRUST_delete_ptr(sk, p) \
+ ((X509_TRUST *)sk_delete_ptr( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_TRUST) *, sk), \
+ CHECKED_CAST(void *, X509_TRUST *, p)))
+
+#define sk_X509_TRUST_find(sk, out_index, p) \
+ sk_find(CHECKED_CAST(_STACK *, STACK_OF(X509_TRUST) *, sk), (out_index), \
+ CHECKED_CAST(void *, X509_TRUST *, p))
+
+#define sk_X509_TRUST_shift(sk) \
+ ((X509_TRUST *)sk_shift(CHECKED_CAST(_STACK *, STACK_OF(X509_TRUST) *, sk)))
+
+#define sk_X509_TRUST_push(sk, p) \
+ sk_push(CHECKED_CAST(_STACK *, STACK_OF(X509_TRUST) *, sk), \
+ CHECKED_CAST(void *, X509_TRUST *, p))
+
+#define sk_X509_TRUST_pop(sk) \
+ ((X509_TRUST *)sk_pop(CHECKED_CAST(_STACK *, STACK_OF(X509_TRUST) *, sk)))
+
+#define sk_X509_TRUST_dup(sk) \
+ ((STACK_OF(X509_TRUST) *)sk_dup( \
+ CHECKED_CAST(_STACK *, const STACK_OF(X509_TRUST) *, sk)))
+
+#define sk_X509_TRUST_sort(sk) \
+ sk_sort(CHECKED_CAST(_STACK *, STACK_OF(X509_TRUST) *, sk))
+
+#define sk_X509_TRUST_is_sorted(sk) \
+ sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(X509_TRUST) *, sk))
+
+#define sk_X509_TRUST_set_cmp_func(sk, comp) \
+ ((int (*)(const X509_TRUST **a, const X509_TRUST **b))sk_set_cmp_func( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_TRUST) *, sk), \
+ CHECKED_CAST(stack_cmp_func, \
+ int (*)(const X509_TRUST **a, const X509_TRUST **b), \
+ comp)))
+
+
+/* X509_VERIFY_PARAM */
+#define sk_X509_VERIFY_PARAM_new(comp) \
+ ((STACK_OF(X509_VERIFY_PARAM) *)sk_new(CHECKED_CAST( \
+ stack_cmp_func, \
+ int (*)(const X509_VERIFY_PARAM **a, const X509_VERIFY_PARAM **b), \
+ comp)))
+
+#define sk_X509_VERIFY_PARAM_new_null() \
+ ((STACK_OF(X509_VERIFY_PARAM) *)sk_new_null())
+
+#define sk_X509_VERIFY_PARAM_num(sk) \
+ sk_num(CHECKED_CAST(_STACK *, STACK_OF(X509_VERIFY_PARAM) *, sk))
+
+#define sk_X509_VERIFY_PARAM_zero(sk) \
+ sk_zero(CHECKED_CAST(_STACK *, STACK_OF(X509_VERIFY_PARAM) *, sk));
+
+#define sk_X509_VERIFY_PARAM_value(sk, i) \
+ ((X509_VERIFY_PARAM *)sk_value( \
+ CHECKED_CAST(_STACK *, const STACK_OF(X509_VERIFY_PARAM) *, sk), (i)))
+
+#define sk_X509_VERIFY_PARAM_set(sk, i, p) \
+ ((X509_VERIFY_PARAM *)sk_set( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_VERIFY_PARAM) *, sk), (i), \
+ CHECKED_CAST(void *, X509_VERIFY_PARAM *, p)))
+
+#define sk_X509_VERIFY_PARAM_free(sk) \
+ sk_free(CHECKED_CAST(_STACK *, STACK_OF(X509_VERIFY_PARAM) *, sk))
+
+#define sk_X509_VERIFY_PARAM_pop_free(sk, free_func) \
+ sk_pop_free(CHECKED_CAST(_STACK *, STACK_OF(X509_VERIFY_PARAM) *, sk), \
+ CHECKED_CAST(void (*)(void *), void (*)(X509_VERIFY_PARAM *), \
+ free_func))
+
+#define sk_X509_VERIFY_PARAM_insert(sk, p, where) \
+ sk_insert(CHECKED_CAST(_STACK *, STACK_OF(X509_VERIFY_PARAM) *, sk), \
+ CHECKED_CAST(void *, X509_VERIFY_PARAM *, p), (where))
+
+#define sk_X509_VERIFY_PARAM_delete(sk, where) \
+ ((X509_VERIFY_PARAM *)sk_delete( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_VERIFY_PARAM) *, sk), (where)))
+
+#define sk_X509_VERIFY_PARAM_delete_ptr(sk, p) \
+ ((X509_VERIFY_PARAM *)sk_delete_ptr( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_VERIFY_PARAM) *, sk), \
+ CHECKED_CAST(void *, X509_VERIFY_PARAM *, p)))
+
+#define sk_X509_VERIFY_PARAM_find(sk, out_index, p) \
+ sk_find(CHECKED_CAST(_STACK *, STACK_OF(X509_VERIFY_PARAM) *, sk), \
+ (out_index), CHECKED_CAST(void *, X509_VERIFY_PARAM *, p))
+
+#define sk_X509_VERIFY_PARAM_shift(sk) \
+ ((X509_VERIFY_PARAM *)sk_shift( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_VERIFY_PARAM) *, sk)))
+
+#define sk_X509_VERIFY_PARAM_push(sk, p) \
+ sk_push(CHECKED_CAST(_STACK *, STACK_OF(X509_VERIFY_PARAM) *, sk), \
+ CHECKED_CAST(void *, X509_VERIFY_PARAM *, p))
+
+#define sk_X509_VERIFY_PARAM_pop(sk) \
+ ((X509_VERIFY_PARAM *)sk_pop( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_VERIFY_PARAM) *, sk)))
+
+#define sk_X509_VERIFY_PARAM_dup(sk) \
+ ((STACK_OF(X509_VERIFY_PARAM) *)sk_dup( \
+ CHECKED_CAST(_STACK *, const STACK_OF(X509_VERIFY_PARAM) *, sk)))
+
+#define sk_X509_VERIFY_PARAM_sort(sk) \
+ sk_sort(CHECKED_CAST(_STACK *, STACK_OF(X509_VERIFY_PARAM) *, sk))
+
+#define sk_X509_VERIFY_PARAM_is_sorted(sk) \
+ sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(X509_VERIFY_PARAM) *, sk))
+
+#define sk_X509_VERIFY_PARAM_set_cmp_func(sk, comp) \
+ ((int (*)(const X509_VERIFY_PARAM **a, const X509_VERIFY_PARAM **b)) \
+ sk_set_cmp_func( \
+ CHECKED_CAST(_STACK *, STACK_OF(X509_VERIFY_PARAM) *, sk), \
+ CHECKED_CAST(stack_cmp_func, int (*)(const X509_VERIFY_PARAM **a, \
+ const X509_VERIFY_PARAM **b), \
+ comp)))
+
+
+/* void */
+#define sk_void_new(comp) \
+ ((STACK_OF(void)*)sk_new(CHECKED_CAST( \
+ stack_cmp_func, int (*)(const void **a, const void **b), comp)))
+
+#define sk_void_new_null() ((STACK_OF(void)*)sk_new_null())
+
+#define sk_void_num(sk) sk_num(CHECKED_CAST(_STACK *, STACK_OF(void)*, sk))
+
+#define sk_void_zero(sk) sk_zero(CHECKED_CAST(_STACK *, STACK_OF(void)*, sk));
+
+#define sk_void_value(sk, i) \
+ ((void *)sk_value(CHECKED_CAST(_STACK *, const STACK_OF(void)*, sk), (i)))
+
+#define sk_void_set(sk, i, p) \
+ ((void *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(void)*, sk), (i), \
+ CHECKED_CAST(void *, void *, p)))
+
+#define sk_void_free(sk) sk_free(CHECKED_CAST(_STACK *, STACK_OF(void)*, sk))
+
+#define sk_void_pop_free(sk, free_func) \
+ sk_pop_free(CHECKED_CAST(_STACK *, STACK_OF(void)*, sk), \
+ CHECKED_CAST(void (*)(void *), void (*)(void *), free_func))
+
+#define sk_void_insert(sk, p, where) \
+ sk_insert(CHECKED_CAST(_STACK *, STACK_OF(void)*, sk), \
+ CHECKED_CAST(void *, void *, p), (where))
+
+#define sk_void_delete(sk, where) \
+ ((void *)sk_delete(CHECKED_CAST(_STACK *, STACK_OF(void)*, sk), (where)))
+
+#define sk_void_delete_ptr(sk, p) \
+ ((void *)sk_delete_ptr(CHECKED_CAST(_STACK *, STACK_OF(void)*, sk), \
+ CHECKED_CAST(void *, void *, p)))
+
+#define sk_void_find(sk, out_index, p) \
+ sk_find(CHECKED_CAST(_STACK *, STACK_OF(void)*, sk), (out_index), \
+ CHECKED_CAST(void *, void *, p))
+
+#define sk_void_shift(sk) \
+ ((void *)sk_shift(CHECKED_CAST(_STACK *, STACK_OF(void)*, sk)))
+
+#define sk_void_push(sk, p) \
+ sk_push(CHECKED_CAST(_STACK *, STACK_OF(void)*, sk), \
+ CHECKED_CAST(void *, void *, p))
+
+#define sk_void_pop(sk) \
+ ((void *)sk_pop(CHECKED_CAST(_STACK *, STACK_OF(void)*, sk)))
+
+#define sk_void_dup(sk) \
+ ((STACK_OF(void)*)sk_dup(CHECKED_CAST(_STACK *, const STACK_OF(void)*, sk)))
+
+#define sk_void_sort(sk) sk_sort(CHECKED_CAST(_STACK *, STACK_OF(void)*, sk))
+
+#define sk_void_is_sorted(sk) \
+ sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(void)*, sk))
+
+#define sk_void_set_cmp_func(sk, comp) \
+ ((int (*)(const void **a, const void **b))sk_set_cmp_func( \
+ CHECKED_CAST(_STACK *, STACK_OF(void)*, sk), \
+ CHECKED_CAST(stack_cmp_func, int (*)(const void **a, const void **b), \
+ comp)))
+
+
+/* SRTP_PROTECTION_PROFILE */
+#define sk_SRTP_PROTECTION_PROFILE_new(comp) \
+ ((STACK_OF(SRTP_PROTECTION_PROFILE) *)sk_new(CHECKED_CAST( \
+ stack_cmp_func, int (*)(const const SRTP_PROTECTION_PROFILE **a, \
+ const const SRTP_PROTECTION_PROFILE **b), \
+ comp)))
+
+#define sk_SRTP_PROTECTION_PROFILE_new_null() \
+ ((STACK_OF(SRTP_PROTECTION_PROFILE) *)sk_new_null())
+
+#define sk_SRTP_PROTECTION_PROFILE_num(sk) \
+ sk_num(CHECKED_CAST(_STACK *, STACK_OF(SRTP_PROTECTION_PROFILE) *, sk))
+
+#define sk_SRTP_PROTECTION_PROFILE_zero(sk) \
+ sk_zero(CHECKED_CAST(_STACK *, STACK_OF(SRTP_PROTECTION_PROFILE) *, sk));
+
+#define sk_SRTP_PROTECTION_PROFILE_value(sk, i) \
+ ((const SRTP_PROTECTION_PROFILE *)sk_value( \
+ CHECKED_CAST(_STACK *, const STACK_OF(SRTP_PROTECTION_PROFILE) *, sk), \
+ (i)))
+
+#define sk_SRTP_PROTECTION_PROFILE_set(sk, i, p) \
+ ((const SRTP_PROTECTION_PROFILE *)sk_set( \
+ CHECKED_CAST(_STACK *, STACK_OF(SRTP_PROTECTION_PROFILE) *, sk), (i), \
+ CHECKED_CAST(void *, const SRTP_PROTECTION_PROFILE *, p)))
+
+#define sk_SRTP_PROTECTION_PROFILE_free(sk) \
+ sk_free(CHECKED_CAST(_STACK *, STACK_OF(SRTP_PROTECTION_PROFILE) *, sk))
+
+#define sk_SRTP_PROTECTION_PROFILE_pop_free(sk, free_func) \
+ sk_pop_free( \
+ CHECKED_CAST(_STACK *, STACK_OF(SRTP_PROTECTION_PROFILE) *, sk), \
+ CHECKED_CAST(void (*)(void *), \
+ void (*)(const SRTP_PROTECTION_PROFILE *), free_func))
+
+#define sk_SRTP_PROTECTION_PROFILE_insert(sk, p, where) \
+ sk_insert(CHECKED_CAST(_STACK *, STACK_OF(SRTP_PROTECTION_PROFILE) *, sk), \
+ CHECKED_CAST(void *, const SRTP_PROTECTION_PROFILE *, p), (where))
+
+#define sk_SRTP_PROTECTION_PROFILE_delete(sk, where) \
+ ((const SRTP_PROTECTION_PROFILE *)sk_delete( \
+ CHECKED_CAST(_STACK *, STACK_OF(SRTP_PROTECTION_PROFILE) *, sk), \
+ (where)))
+
+#define sk_SRTP_PROTECTION_PROFILE_delete_ptr(sk, p) \
+ ((const SRTP_PROTECTION_PROFILE *)sk_delete_ptr( \
+ CHECKED_CAST(_STACK *, STACK_OF(SRTP_PROTECTION_PROFILE) *, sk), \
+ CHECKED_CAST(void *, const SRTP_PROTECTION_PROFILE *, p)))
+
+#define sk_SRTP_PROTECTION_PROFILE_find(sk, out_index, p) \
+ sk_find(CHECKED_CAST(_STACK *, STACK_OF(SRTP_PROTECTION_PROFILE) *, sk), \
+ (out_index), \
+ CHECKED_CAST(void *, const SRTP_PROTECTION_PROFILE *, p))
+
+#define sk_SRTP_PROTECTION_PROFILE_shift(sk) \
+ ((const SRTP_PROTECTION_PROFILE *)sk_shift( \
+ CHECKED_CAST(_STACK *, STACK_OF(SRTP_PROTECTION_PROFILE) *, sk)))
+
+#define sk_SRTP_PROTECTION_PROFILE_push(sk, p) \
+ sk_push(CHECKED_CAST(_STACK *, STACK_OF(SRTP_PROTECTION_PROFILE) *, sk), \
+ CHECKED_CAST(void *, const SRTP_PROTECTION_PROFILE *, p))
+
+#define sk_SRTP_PROTECTION_PROFILE_pop(sk) \
+ ((const SRTP_PROTECTION_PROFILE *)sk_pop( \
+ CHECKED_CAST(_STACK *, STACK_OF(SRTP_PROTECTION_PROFILE) *, sk)))
+
+#define sk_SRTP_PROTECTION_PROFILE_dup(sk) \
+ ((STACK_OF(SRTP_PROTECTION_PROFILE) *)sk_dup( \
+ CHECKED_CAST(_STACK *, const STACK_OF(SRTP_PROTECTION_PROFILE) *, sk)))
+
+#define sk_SRTP_PROTECTION_PROFILE_sort(sk) \
+ sk_sort(CHECKED_CAST(_STACK *, STACK_OF(SRTP_PROTECTION_PROFILE) *, sk))
+
+#define sk_SRTP_PROTECTION_PROFILE_is_sorted(sk) \
+ sk_is_sorted( \
+ CHECKED_CAST(_STACK *, const STACK_OF(SRTP_PROTECTION_PROFILE) *, sk))
+
+#define sk_SRTP_PROTECTION_PROFILE_set_cmp_func(sk, comp) \
+ ((int (*)(const SRTP_PROTECTION_PROFILE **a, \
+ const SRTP_PROTECTION_PROFILE **b)) \
+ sk_set_cmp_func( \
+ CHECKED_CAST(_STACK *, STACK_OF(SRTP_PROTECTION_PROFILE) *, sk), \
+ CHECKED_CAST(stack_cmp_func, \
+ int (*)(const SRTP_PROTECTION_PROFILE **a, \
+ const SRTP_PROTECTION_PROFILE **b), \
+ comp)))
+
+
+/* SSL_CIPHER */
+#define sk_SSL_CIPHER_new(comp) \
+ ((STACK_OF(SSL_CIPHER) *)sk_new(CHECKED_CAST( \
+ stack_cmp_func, \
+ int (*)(const const SSL_CIPHER **a, const const SSL_CIPHER **b), comp)))
+
+#define sk_SSL_CIPHER_new_null() ((STACK_OF(SSL_CIPHER) *)sk_new_null())
+
+#define sk_SSL_CIPHER_num(sk) \
+ sk_num(CHECKED_CAST(_STACK *, STACK_OF(SSL_CIPHER) *, sk))
+
+#define sk_SSL_CIPHER_zero(sk) \
+ sk_zero(CHECKED_CAST(_STACK *, STACK_OF(SSL_CIPHER) *, sk));
+
+#define sk_SSL_CIPHER_value(sk, i) \
+ ((const SSL_CIPHER *)sk_value( \
+ CHECKED_CAST(_STACK *, const STACK_OF(SSL_CIPHER) *, sk), (i)))
+
+#define sk_SSL_CIPHER_set(sk, i, p) \
+ ((const SSL_CIPHER *)sk_set( \
+ CHECKED_CAST(_STACK *, STACK_OF(SSL_CIPHER) *, sk), (i), \
+ CHECKED_CAST(void *, const SSL_CIPHER *, p)))
+
+#define sk_SSL_CIPHER_free(sk) \
+ sk_free(CHECKED_CAST(_STACK *, STACK_OF(SSL_CIPHER) *, sk))
+
+#define sk_SSL_CIPHER_pop_free(sk, free_func) \
+ sk_pop_free( \
+ CHECKED_CAST(_STACK *, STACK_OF(SSL_CIPHER) *, sk), \
+ CHECKED_CAST(void (*)(void *), void (*)(const SSL_CIPHER *), free_func))
+
+#define sk_SSL_CIPHER_insert(sk, p, where) \
+ sk_insert(CHECKED_CAST(_STACK *, STACK_OF(SSL_CIPHER) *, sk), \
+ CHECKED_CAST(void *, const SSL_CIPHER *, p), (where))
+
+#define sk_SSL_CIPHER_delete(sk, where) \
+ ((const SSL_CIPHER *)sk_delete( \
+ CHECKED_CAST(_STACK *, STACK_OF(SSL_CIPHER) *, sk), (where)))
+
+#define sk_SSL_CIPHER_delete_ptr(sk, p) \
+ ((const SSL_CIPHER *)sk_delete_ptr( \
+ CHECKED_CAST(_STACK *, STACK_OF(SSL_CIPHER) *, sk), \
+ CHECKED_CAST(void *, const SSL_CIPHER *, p)))
+
+#define sk_SSL_CIPHER_find(sk, out_index, p) \
+ sk_find(CHECKED_CAST(_STACK *, STACK_OF(SSL_CIPHER) *, sk), (out_index), \
+ CHECKED_CAST(void *, const SSL_CIPHER *, p))
+
+#define sk_SSL_CIPHER_shift(sk) \
+ ((const SSL_CIPHER *)sk_shift( \
+ CHECKED_CAST(_STACK *, STACK_OF(SSL_CIPHER) *, sk)))
+
+#define sk_SSL_CIPHER_push(sk, p) \
+ sk_push(CHECKED_CAST(_STACK *, STACK_OF(SSL_CIPHER) *, sk), \
+ CHECKED_CAST(void *, const SSL_CIPHER *, p))
+
+#define sk_SSL_CIPHER_pop(sk) \
+ ((const SSL_CIPHER *)sk_pop( \
+ CHECKED_CAST(_STACK *, STACK_OF(SSL_CIPHER) *, sk)))
+
+#define sk_SSL_CIPHER_dup(sk) \
+ ((STACK_OF(SSL_CIPHER) *)sk_dup( \
+ CHECKED_CAST(_STACK *, const STACK_OF(SSL_CIPHER) *, sk)))
+
+#define sk_SSL_CIPHER_sort(sk) \
+ sk_sort(CHECKED_CAST(_STACK *, STACK_OF(SSL_CIPHER) *, sk))
+
+#define sk_SSL_CIPHER_is_sorted(sk) \
+ sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(SSL_CIPHER) *, sk))
+
+#define sk_SSL_CIPHER_set_cmp_func(sk, comp) \
+ ((int (*)(const SSL_CIPHER **a, const SSL_CIPHER **b))sk_set_cmp_func( \
+ CHECKED_CAST(_STACK *, STACK_OF(SSL_CIPHER) *, sk), \
+ CHECKED_CAST(stack_cmp_func, \
+ int (*)(const SSL_CIPHER **a, const SSL_CIPHER **b), \
+ comp)))
+
+
+/* OPENSSL_STRING */
+#define sk_OPENSSL_STRING_new(comp) \
+ ((STACK_OF(OPENSSL_STRING) *)sk_new(CHECKED_CAST( \
+ stack_cmp_func, \
+ int (*)(const OPENSSL_STRING *a, const OPENSSL_STRING *b), comp)))
+
+#define sk_OPENSSL_STRING_new_null() ((STACK_OF(OPENSSL_STRING) *)sk_new_null())
+
+#define sk_OPENSSL_STRING_num(sk) \
+ sk_num(CHECKED_CAST(_STACK *, STACK_OF(OPENSSL_STRING) *, sk))
+
+#define sk_OPENSSL_STRING_zero(sk) \
+ sk_zero(CHECKED_CAST(_STACK *, STACK_OF(OPENSSL_STRING) *, sk));
+
+#define sk_OPENSSL_STRING_value(sk, i) \
+ ((OPENSSL_STRING)sk_value( \
+ CHECKED_CAST(_STACK *, const STACK_OF(OPENSSL_STRING) *, sk), (i)))
+
+#define sk_OPENSSL_STRING_set(sk, i, p) \
+ ((OPENSSL_STRING)sk_set( \
+ CHECKED_CAST(_STACK *, STACK_OF(OPENSSL_STRING) *, sk), (i), \
+ CHECKED_CAST(void *, OPENSSL_STRING, p)))
+
+#define sk_OPENSSL_STRING_free(sk) \
+ sk_free(CHECKED_CAST(_STACK *, STACK_OF(OPENSSL_STRING) *, sk))
+
+#define sk_OPENSSL_STRING_pop_free(sk, free_func) \
+ sk_pop_free( \
+ CHECKED_CAST(_STACK *, STACK_OF(OPENSSL_STRING) *, sk), \
+ CHECKED_CAST(void (*)(void *), void (*)(OPENSSL_STRING), free_func))
+
+#define sk_OPENSSL_STRING_insert(sk, p, where) \
+ sk_insert(CHECKED_CAST(_STACK *, STACK_OF(OPENSSL_STRING) *, sk), \
+ CHECKED_CAST(void *, OPENSSL_STRING, p), (where))
+
+#define sk_OPENSSL_STRING_delete(sk, where) \
+ ((OPENSSL_STRING)sk_delete( \
+ CHECKED_CAST(_STACK *, STACK_OF(OPENSSL_STRING) *, sk), (where)))
+
+#define sk_OPENSSL_STRING_delete_ptr(sk, p) \
+ ((OPENSSL_STRING)sk_delete_ptr( \
+ CHECKED_CAST(_STACK *, STACK_OF(OPENSSL_STRING) *, sk), \
+ CHECKED_CAST(void *, OPENSSL_STRING, p)))
+
+#define sk_OPENSSL_STRING_find(sk, out_index, p) \
+ sk_find(CHECKED_CAST(_STACK *, STACK_OF(OPENSSL_STRING) *, sk), (out_index), \
+ CHECKED_CAST(void *, OPENSSL_STRING, p))
+
+#define sk_OPENSSL_STRING_shift(sk) \
+ ((OPENSSL_STRING)sk_shift( \
+ CHECKED_CAST(_STACK *, STACK_OF(OPENSSL_STRING) *, sk)))
+
+#define sk_OPENSSL_STRING_push(sk, p) \
+ sk_push(CHECKED_CAST(_STACK *, STACK_OF(OPENSSL_STRING) *, sk), \
+ CHECKED_CAST(void *, OPENSSL_STRING, p))
+
+#define sk_OPENSSL_STRING_pop(sk) \
+ ((OPENSSL_STRING)sk_pop( \
+ CHECKED_CAST(_STACK *, STACK_OF(OPENSSL_STRING) *, sk)))
+
+#define sk_OPENSSL_STRING_dup(sk) \
+ ((STACK_OF(OPENSSL_STRING) *)sk_dup( \
+ CHECKED_CAST(_STACK *, const STACK_OF(OPENSSL_STRING) *, sk)))
+
+#define sk_OPENSSL_STRING_sort(sk) \
+ sk_sort(CHECKED_CAST(_STACK *, STACK_OF(OPENSSL_STRING) *, sk))
+
+#define sk_OPENSSL_STRING_is_sorted(sk) \
+ sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(OPENSSL_STRING) *, sk))
+
+#define sk_OPENSSL_STRING_set_cmp_func(sk, comp) \
+ ((int (*)(const OPENSSL_STRING **a, const OPENSSL_STRING **b)) \
+ sk_set_cmp_func( \
+ CHECKED_CAST(_STACK *, STACK_OF(OPENSSL_STRING) *, sk), \
+ CHECKED_CAST(stack_cmp_func, int (*)(const OPENSSL_STRING **a, \
+ const OPENSSL_STRING **b), \
+ comp)))
+
+
+/* OPENSSL_BLOCK */
+#define sk_OPENSSL_BLOCK_new(comp) \
+ ((STACK_OF(OPENSSL_BLOCK) *)sk_new(CHECKED_CAST( \
+ stack_cmp_func, int (*)(const OPENSSL_BLOCK *a, const OPENSSL_BLOCK *b), \
+ comp)))
+
+#define sk_OPENSSL_BLOCK_new_null() ((STACK_OF(OPENSSL_BLOCK) *)sk_new_null())
+
+#define sk_OPENSSL_BLOCK_num(sk) \
+ sk_num(CHECKED_CAST(_STACK *, STACK_OF(OPENSSL_BLOCK) *, sk))
+
+#define sk_OPENSSL_BLOCK_zero(sk) \
+ sk_zero(CHECKED_CAST(_STACK *, STACK_OF(OPENSSL_BLOCK) *, sk));
+
+#define sk_OPENSSL_BLOCK_value(sk, i) \
+ ((OPENSSL_BLOCK)sk_value( \
+ CHECKED_CAST(_STACK *, const STACK_OF(OPENSSL_BLOCK) *, sk), (i)))
+
+#define sk_OPENSSL_BLOCK_set(sk, i, p) \
+ ((OPENSSL_BLOCK)sk_set( \
+ CHECKED_CAST(_STACK *, STACK_OF(OPENSSL_BLOCK) *, sk), (i), \
+ CHECKED_CAST(void *, OPENSSL_BLOCK, p)))
+
+#define sk_OPENSSL_BLOCK_free(sk) \
+ sk_free(CHECKED_CAST(_STACK *, STACK_OF(OPENSSL_BLOCK) *, sk))
+
+#define sk_OPENSSL_BLOCK_pop_free(sk, free_func) \
+ sk_pop_free( \
+ CHECKED_CAST(_STACK *, STACK_OF(OPENSSL_BLOCK) *, sk), \
+ CHECKED_CAST(void (*)(void *), void (*)(OPENSSL_BLOCK), free_func))
+
+#define sk_OPENSSL_BLOCK_insert(sk, p, where) \
+ sk_insert(CHECKED_CAST(_STACK *, STACK_OF(OPENSSL_BLOCK) *, sk), \
+ CHECKED_CAST(void *, OPENSSL_BLOCK, p), (where))
+
+#define sk_OPENSSL_BLOCK_delete(sk, where) \
+ ((OPENSSL_BLOCK)sk_delete( \
+ CHECKED_CAST(_STACK *, STACK_OF(OPENSSL_BLOCK) *, sk), (where)))
+
+#define sk_OPENSSL_BLOCK_delete_ptr(sk, p) \
+ ((OPENSSL_BLOCK)sk_delete_ptr( \
+ CHECKED_CAST(_STACK *, STACK_OF(OPENSSL_BLOCK) *, sk), \
+ CHECKED_CAST(void *, OPENSSL_BLOCK, p)))
+
+#define sk_OPENSSL_BLOCK_find(sk, out_index, p) \
+ sk_find(CHECKED_CAST(_STACK *, STACK_OF(OPENSSL_BLOCK) *, sk), (out_index), \
+ CHECKED_CAST(void *, OPENSSL_BLOCK, p))
+
+#define sk_OPENSSL_BLOCK_shift(sk) \
+ ((OPENSSL_BLOCK)sk_shift( \
+ CHECKED_CAST(_STACK *, STACK_OF(OPENSSL_BLOCK) *, sk)))
+
+#define sk_OPENSSL_BLOCK_push(sk, p) \
+ sk_push(CHECKED_CAST(_STACK *, STACK_OF(OPENSSL_BLOCK) *, sk), \
+ CHECKED_CAST(void *, OPENSSL_BLOCK, p))
+
+#define sk_OPENSSL_BLOCK_pop(sk) \
+ ((OPENSSL_BLOCK)sk_pop(CHECKED_CAST(_STACK *, STACK_OF(OPENSSL_BLOCK) *, sk)))
+
+#define sk_OPENSSL_BLOCK_dup(sk) \
+ ((STACK_OF(OPENSSL_BLOCK) *)sk_dup( \
+ CHECKED_CAST(_STACK *, const STACK_OF(OPENSSL_BLOCK) *, sk)))
+
+#define sk_OPENSSL_BLOCK_sort(sk) \
+ sk_sort(CHECKED_CAST(_STACK *, STACK_OF(OPENSSL_BLOCK) *, sk))
+
+#define sk_OPENSSL_BLOCK_is_sorted(sk) \
+ sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(OPENSSL_BLOCK) *, sk))
+
+#define sk_OPENSSL_BLOCK_set_cmp_func(sk, comp) \
+ ((int (*)(const OPENSSL_BLOCK **a, const OPENSSL_BLOCK **b))sk_set_cmp_func( \
+ CHECKED_CAST(_STACK *, STACK_OF(OPENSSL_BLOCK) *, sk), \
+ CHECKED_CAST(stack_cmp_func, \
+ int (*)(const OPENSSL_BLOCK **a, const OPENSSL_BLOCK **b), \
+ comp)))
diff --git a/src/include/openssl/thread.h b/src/include/openssl/thread.h
new file mode 100644
index 0000000..ea65405
--- /dev/null
+++ b/src/include/openssl/thread.h
@@ -0,0 +1,273 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 OPENSSL_HEADER_THREAD_H
+#define OPENSSL_HEADER_THREAD_H
+
+#include <openssl/base.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* Functions to support multithreading.
+ *
+ * OpenSSL can safely be used in multi-threaded applications provided that at
+ * least two callback functions are set with |CRYPTO_set_locking_callback| and
+ * |CRYPTO_THREADID_set_callback|.
+ *
+ * The locking callback performs mutual exclusion. Rather than using a single
+ * lock for all, shared data-structures, OpenSSL requires that the locking
+ * callback support a fixed (at run-time) number of different locks, given by
+ * |CRYPTO_num_locks|.
+ *
+ * The thread ID callback is called to record the currently executing thread's
+ * identifier in a |CRYPTO_THREADID| structure. If this callback is not
+ * provided then the address of |errno| is used as the thread identifier. This
+ * is sufficient only if the system has a thread-local |errno| value. */
+
+
+/* CRYPTO_num_locks returns the number of static locks that the callback
+ * function passed to |CRYPTO_set_locking_callback| must be able to handle. */
+OPENSSL_EXPORT int CRYPTO_num_locks(void);
+
+/* CRYPTO_set_locking_callback sets a callback function that implements locking
+ * on behalf of OpenSSL. The callback is called whenever OpenSSL needs to lock
+ * or unlock a lock, and locks are specified as a number between zero and
+ * |CRYPTO_num_locks()-1|.
+ *
+ * The mode argument to the callback is a bitwise-OR of either CRYPTO_LOCK or
+ * CRYPTO_UNLOCK, to denote the action, and CRYPTO_READ or CRYPTO_WRITE, to
+ * indicate the type of lock. The |file| and |line| arguments give the location
+ * in the OpenSSL source where the locking action originated. */
+OPENSSL_EXPORT void CRYPTO_set_locking_callback(
+ void (*func)(int mode, int lock_num, const char *file, int line));
+
+/* CRYPTO_set_add_lock_callback sets an optional callback which is used when
+ * OpenSSL needs to add a fixed amount to an integer. For example, this is used
+ * when maintaining reference counts. Normally the reference counts are
+ * maintained by performing the addition under a lock but, if this callback
+ * has been set, the application is free to implement the operation using
+ * faster methods (i.e. atomic operations).
+ *
+ * The callback is given a pointer to the integer to be altered (|num|), the
+ * amount to add to the integer (|amount|, which may be negative), the number
+ * of the lock which would have been taken to protect the operation and the
+ * position in the OpenSSL code where the operation originated. */
+OPENSSL_EXPORT void CRYPTO_set_add_lock_callback(int (*func)(
+ int *num, int amount, int lock_num, const char *file, int line));
+
+/* CRYPTO_get_lock_name returns the name of the lock given by |lock_num|. This
+ * can be used in a locking callback for debugging purposes. */
+OPENSSL_EXPORT const char *CRYPTO_get_lock_name(int lock_num);
+
+
+/* CRYPTO_THREADID identifies a thread in a multithreaded program. This
+ * structure should not be used directly. Rather applications should use
+ * |CRYPTO_THREADID_set_numeric| and |CRYPTO_THREADID_set_pointer|. */
+typedef struct crypto_threadid_st {
+ void *ptr;
+ unsigned long val;
+} CRYPTO_THREADID;
+
+/* CRYPTO_THREADID_set_callback sets a callback function that stores an
+ * identifier of the currently executing thread into |threadid|. The
+ * CRYPTO_THREADID structure should not be accessed directly. Rather one of
+ * |CRYPTO_THREADID_set_numeric| or |CRYPTO_THREADID_set_pointer| should be
+ * used depending on whether thread IDs are numbers or pointers on the host
+ * system. */
+OPENSSL_EXPORT int CRYPTO_THREADID_set_callback(
+ void (*threadid_func)(CRYPTO_THREADID *threadid));
+
+OPENSSL_EXPORT void CRYPTO_THREADID_set_numeric(CRYPTO_THREADID *id,
+ unsigned long val);
+OPENSSL_EXPORT void CRYPTO_THREADID_set_pointer(CRYPTO_THREADID *id, void *ptr);
+
+
+/* Private functions: */
+
+/* CRYPTO_get_locking_callback returns the callback, if any, that was most
+ * recently set using |CRYPTO_set_locking_callback|. */
+void (*CRYPTO_get_locking_callback(void))(int mode, int lock_num,
+ const char *file, int line);
+
+/* CRYPTO_get_add_lock_callback returns the callback, if any, that was most
+ * recently set using |CRYPTO_set_add_lock_callback|. */
+int (*CRYPTO_get_add_lock_callback(void))(int *num, int amount, int lock_num,
+ const char *file, int line);
+
+/* CRYPTO_lock locks or unlocks the lock specified by |lock_num| (one of
+ * |CRYPTO_LOCK_*|). Don't call this directly, rather use one of the
+ * CRYPTO_[rw]_(un)lock macros. */
+OPENSSL_EXPORT void CRYPTO_lock(int mode, int lock_num, const char *file,
+ int line);
+
+/* CRYPTO_add_lock adds |amount| to |*pointer|, protected by the lock specified
+ * by |lock_num|. It returns the new value of |*pointer|. Don't call this
+ * function directly, rather use the |CRYPTO_add_lock| macro.
+ *
+ * TODO(fork): rename to CRYPTO_add_locked. */
+OPENSSL_EXPORT int CRYPTO_add_lock(int *pointer, int amount, int lock_num,
+ const char *file, int line);
+
+
+/* CRYPTO_THREADID_current stores the current thread identifier in |id|. */
+OPENSSL_EXPORT void CRYPTO_THREADID_current(CRYPTO_THREADID *id);
+
+/* CRYPTO_THREADID_cmp returns < 0, 0 or > 0 if |a| is less than, equal to or
+ * greater than |b|, respectively. */
+int CRYPTO_THREADID_cmp(const CRYPTO_THREADID *a, const CRYPTO_THREADID *b);
+
+/* CRYPTO_THREADID_cpy sets |*dest| equal to |*src|. */
+void CRYPTO_THREADID_cpy(CRYPTO_THREADID *dest, const CRYPTO_THREADID *src);
+
+/* CRYPTO_THREADID_hash returns a hash of the numeric value of |id|. */
+uint32_t CRYPTO_THREADID_hash(const CRYPTO_THREADID *id);
+
+/* These are the locks used by OpenSSL. These values should match up with the
+ * table in thread.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_LOCK_OBJ 40
+#define CRYPTO_NUM_LOCKS 42
+
+#define CRYPTO_LOCK 1
+#define CRYPTO_UNLOCK 2
+#define CRYPTO_READ 4
+#define CRYPTO_WRITE 8
+
+#define CRYPTO_w_lock(lock_num) \
+ CRYPTO_lock(CRYPTO_LOCK | CRYPTO_WRITE, lock_num, __FILE__, __LINE__)
+#define CRYPTO_w_unlock(lock_num) \
+ CRYPTO_lock(CRYPTO_UNLOCK | CRYPTO_WRITE, lock_num, __FILE__, __LINE__)
+#define CRYPTO_r_lock(lock_num) \
+ CRYPTO_lock(CRYPTO_LOCK | CRYPTO_READ, lock_num, __FILE__, __LINE__)
+#define CRYPTO_r_unlock(lock_num) \
+ CRYPTO_lock(CRYPTO_UNLOCK | CRYPTO_READ, lock_num, __FILE__, __LINE__)
+#define CRYPTO_add(addr, amount, lock_num) \
+ CRYPTO_add_lock(addr, amount, lock_num, __FILE__, __LINE__)
+
+
+/* Private functions.
+ *
+ * Some old code calls these functions and so no-op implementations are
+ * provided.
+ *
+ * TODO(fork): cleanup callers and remove. */
+
+OPENSSL_EXPORT void CRYPTO_set_id_callback(unsigned long (*func)(void));
+
+typedef struct {
+ int references;
+ struct CRYPTO_dynlock_value *data;
+} CRYPTO_dynlock;
+
+OPENSSL_EXPORT void CRYPTO_set_dynlock_create_callback(
+ struct CRYPTO_dynlock_value *(*dyn_create_function)(const char *file,
+ int line));
+
+OPENSSL_EXPORT void CRYPTO_set_dynlock_lock_callback(void (*dyn_lock_function)(
+ int mode, struct CRYPTO_dynlock_value *l, const char *file, int line));
+
+OPENSSL_EXPORT void CRYPTO_set_dynlock_destroy_callback(
+ void (*dyn_destroy_function)(struct CRYPTO_dynlock_value *l,
+ const char *file, int line));
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_THREAD_H */
diff --git a/src/include/openssl/time_support.h b/src/include/openssl/time_support.h
new file mode 100644
index 0000000..d03a99d
--- /dev/null
+++ b/src/include/openssl/time_support.h
@@ -0,0 +1,91 @@
+/* Written by Richard Levitte (richard@levitte.org) for the OpenSSL
+ * project 2001.
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2008.
+ */
+/* ====================================================================
+ * 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). */
+
+#ifndef OPENSSL_HEADER_TIME_H
+#define OPENSSL_HEADER_TIME_H
+
+#include <openssl/base.h>
+
+#include <time.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* Wrapper functions for time functions. */
+
+
+/* OPENSSL_gmtime wraps |gmtime_r|. See the manual page for that function. */
+struct tm *OPENSSL_gmtime(const time_t *timer, struct tm *result);
+
+/* OPENSSL_gmtime_adj updates |tm| by adding |offset_day| days and |offset_sec|
+ * seconds. */
+int OPENSSL_gmtime_adj(struct tm *tm, int offset_day, long offset_sec);
+
+/* OPENSSL_gmtime_diff calculates the difference between |from| and |to| and
+ * outputs the difference as a number of days and seconds in |*out_days| and
+ * |*out_secs|. */
+int OPENSSL_gmtime_diff(int *out_days, int *out_secs, const struct tm *from,
+ const struct tm *to);
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_TIME_H */
diff --git a/src/include/openssl/tls1.h b/src/include/openssl/tls1.h
new file mode 100644
index 0000000..ef00b68
--- /dev/null
+++ b/src/include/openssl/tls1.h
@@ -0,0 +1,716 @@
+/* ssl/tls1.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/buf.h>
+#include <openssl/stack.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define TLS1_ALLOW_EXPERIMENTAL_CIPHERSUITES 0
+
+#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
+
+#define TLS1_get_version(s) \
+ ((s->version >> 8) == TLS1_VERSION_MAJOR ? s->version : 0)
+
+#define TLS1_get_client_version(s) \
+ ((s->client_version >> 8) == TLS1_VERSION_MAJOR ? s->client_version : 0)
+
+#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 */
+#define TLS1_AD_USER_CANCELLED 90
+#define TLS1_AD_NO_RENEGOTIATION 100
+/* codes 110-114 are from RFC3546 */
+#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
+#define TLS1_AD_UNKNOWN_PSK_IDENTITY 115 /* fatal */
+
+/* ExtensionType values from RFC3546 / RFC4366 / RFC6066 */
+#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 RFC4681 */
+#define TLSEXT_TYPE_user_mapping 6
+
+/* ExtensionType values from RFC5878 */
+#define TLSEXT_TYPE_client_authz 7
+#define TLSEXT_TYPE_server_authz 8
+
+/* ExtensionType values from RFC6091 */
+#define TLSEXT_TYPE_cert_type 9
+
+/* ExtensionType values from RFC4492 */
+#define TLSEXT_TYPE_elliptic_curves 10
+#define TLSEXT_TYPE_ec_point_formats 11
+
+/* ExtensionType value from RFC5054 */
+#define TLSEXT_TYPE_srp 12
+
+/* ExtensionType values from RFC5246 */
+#define TLSEXT_TYPE_signature_algorithms 13
+
+/* ExtensionType value from RFC5764 */
+#define TLSEXT_TYPE_use_srtp 14
+
+/* ExtensionType value from RFC5620 */
+#define TLSEXT_TYPE_heartbeat 15
+
+/* ExtensionType value from RFC7301 */
+#define TLSEXT_TYPE_application_layer_protocol_negotiation 16
+
+/* ExtensionType value for TLS padding extension.
+ * http://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml
+ * http://tools.ietf.org/html/draft-agl-tls-padding-03
+ */
+#define TLSEXT_TYPE_padding 21
+
+/* https://tools.ietf.org/html/draft-ietf-tls-session-hash-01 */
+#define TLSEXT_TYPE_extended_master_secret 23
+
+/* ExtensionType value from RFC4507 */
+#define TLSEXT_TYPE_session_ticket 35
+
+/* ExtensionType value from RFC5746 */
+#define TLSEXT_TYPE_renegotiate 0xff01
+
+/* ExtensionType value from RFC6962 */
+#define TLSEXT_TYPE_certificate_timestamp 18
+
+/* This is not an IANA defined extension number */
+#define TLSEXT_TYPE_next_proto_neg 13172
+
+/* This is not an IANA defined extension number */
+#define TLSEXT_TYPE_channel_id 30031
+#define TLSEXT_TYPE_channel_id_new 30032
+
+/* 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_uncompressed 0
+#define TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime 1
+#define TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2 2
+
+/* Signature and hash algorithms from RFC 5246 */
+
+#define TLSEXT_signature_anonymous 0
+#define TLSEXT_signature_rsa 1
+#define TLSEXT_signature_dsa 2
+#define TLSEXT_signature_ecdsa 3
+
+#define TLSEXT_hash_none 0
+#define TLSEXT_hash_md5 1
+#define TLSEXT_hash_sha1 2
+#define TLSEXT_hash_sha224 3
+#define TLSEXT_hash_sha256 4
+#define TLSEXT_hash_sha384 5
+#define TLSEXT_hash_sha512 6
+
+/* Flag set for unrecognised algorithms */
+#define TLSEXT_nid_unknown 0x1000000
+
+/* ECC curves */
+
+#define TLSEXT_curve_P_256 23
+#define TLSEXT_curve_P_384 24
+
+
+#define TLSEXT_MAXLEN_host_name 255
+
+OPENSSL_EXPORT const char *SSL_get_servername(const SSL *s, const int type);
+OPENSSL_EXPORT 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. */
+OPENSSL_EXPORT int SSL_export_keying_material(SSL *s, uint8_t *out, size_t olen,
+ const char *label, size_t llen,
+ const uint8_t *p, size_t plen,
+ int use_context);
+
+OPENSSL_EXPORT int SSL_get_sigalgs(SSL *s, int idx, int *psign, int *phash,
+ int *psignandhash, uint8_t *rsig,
+ uint8_t *rhash);
+
+OPENSSL_EXPORT int SSL_get_shared_sigalgs(SSL *s, int idx, int *psign,
+ int *phash, int *psignandhash,
+ uint8_t *rsig, uint8_t *rhash);
+
+#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_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_set_tlsext_status_cb(ssl, cb) \
+ SSL_CTX_callback_ctrl(ssl, SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB, \
+ (void (*)(void))cb)
+
+#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 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 RFC3268 */
+
+#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 RFC4132 */
+#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 RFC4132 */
+#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 RFC4162 */
+#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 RFC5288 */
+#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
+
+/* ECC ciphersuites from RFC4492 */
+#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 RFC5289 */
+
+#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 RFC5289 */
+#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
+
+#define TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305 0x0300CC13
+#define TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305 0x0300CC14
+#define TLS1_CK_DHE_RSA_CHACHA20_POLY1305 0x0300CC15
+
+/* Non-standard ECDHE PSK ciphersuites */
+#define TLS1_CK_ECDHE_PSK_WITH_AES_128_GCM_SHA256 0x0300CAFE
+
+/* XXX
+ * Inconsistency alert:
+ * The OpenSSL names of ciphers with ephemeral DH here include the string
+ * "DHE", while elsewhere it has always been "EDH".
+ * (The alias for the list of all such ciphers also is "EDH".)
+ * The specifications speak of "EDH"; maybe we should allow both forms
+ * for everything. */
+#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 RFC3268 */
+#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 RFC4492 */
+#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 RFC4132 */
+#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"
+
+/* SEED ciphersuites from RFC4162 */
+#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 RFC5288 */
+#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 RFC5289 */
+
+#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 RFC5289 */
+#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"
+
+#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"
+
+/* Non-standard ECDHE PSK ciphersuites */
+#define TLS1_TXT_ECDHE_PSK_WITH_AES_128_GCM_SHA256 \
+ "ECDHE-PSK-WITH-AES-128-GCM-SHA256"
+
+#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_ECDSA_SIGN 64
+#define TLS_CT_RSA_FIXED_ECDH 65
+#define TLS_CT_ECDSA_FIXED_ECDH 66
+
+#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_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
+#define TLS_MD_EXTENDED_MASTER_SECRET_CONST "extended master secret"
+#define TLS_MD_EXTENDED_MASTER_SECRET_CONST_SIZE 22
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/include/openssl/type_check.h b/src/include/openssl/type_check.h
new file mode 100644
index 0000000..dd59151
--- /dev/null
+++ b/src/include/openssl/type_check.h
@@ -0,0 +1,87 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 OPENSSL_HEADER_TYPE_CHECK_H
+#define OPENSSL_HEADER_TYPE_CHECK_H
+
+#include <openssl/base.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* This header file contains some common macros for enforcing type checking.
+ * Several, common OpenSSL structures (i.e. stack and lhash) operate on void
+ * pointers, but we wish to have type checking when they are used with a
+ * specific type. */
+
+/* CHECKED_CAST casts |p| from type |from| to type |to|. */
+#define CHECKED_CAST(to, from, p) ((to) (1 ? (p) : (from)0))
+
+/* CHECKED_PTR_OF casts a given pointer to void* and statically checks that it
+ * was a pointer to |type|. */
+#define CHECKED_PTR_OF(type, p) CHECKED_CAST(void*, type*, (p))
+
+#define OPENSSL_COMPILE_ASSERT(cond, msg) \
+ typedef char OPENSSL_COMPILE_ASSERT_##msg[((cond) ? 1 : -1)]
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_TYPE_CHECK_H */
diff --git a/src/include/openssl/x509.h b/src/include/openssl/x509.h
new file mode 100644
index 0000000..1ee63a1
--- /dev/null
+++ b/src/include/openssl/x509.h
@@ -0,0 +1,1309 @@
+/* crypto/x509/x509.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/base.h>
+
+#include <time.h>
+
+#include <openssl/asn1.h>
+#include <openssl/bio.h>
+#include <openssl/cipher.h>
+#include <openssl/dh.h>
+#include <openssl/dsa.h>
+#include <openssl/ec.h>
+#include <openssl/ecdh.h>
+#include <openssl/ecdsa.h>
+#include <openssl/evp.h>
+#include <openssl/rsa.h>
+#include <openssl/sha.h>
+#include <openssl/stack.h>
+
+#ifdef __cplusplus
+extern "C" {
+#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
+
+typedef struct X509_objects_st
+ {
+ int nid;
+ int (*a2i)(void);
+ int (*i2a)(void);
+ } X509_OBJECTS;
+
+DECLARE_ASN1_SET_OF(X509_ALGOR)
+
+typedef STACK_OF(X509_ALGOR) X509_ALGORS;
+
+typedef struct X509_val_st
+ {
+ ASN1_TIME *notBefore;
+ ASN1_TIME *notAfter;
+ } X509_VAL;
+
+struct X509_pubkey_st
+ {
+ X509_ALGOR *algor;
+ ASN1_BIT_STRING *public_key;
+ EVP_PKEY *pkey;
+ };
+
+typedef struct X509_sig_st
+ {
+ X509_ALGOR *algor;
+ ASN1_OCTET_STRING *digest;
+ } X509_SIG;
+
+typedef struct X509_name_entry_st
+ {
+ ASN1_OBJECT *object;
+ ASN1_STRING *value;
+ int set;
+ int size; /* temp variable */
+ } X509_NAME_ENTRY;
+
+DECLARE_STACK_OF(X509_NAME_ENTRY)
+DECLARE_ASN1_SET_OF(X509_NAME_ENTRY)
+
+/* we always keep X509_NAMEs in 2 forms. */
+typedef 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;
+
+DECLARE_STACK_OF(X509_NAME)
+
+#define X509_EX_V_NETSCAPE_HACK 0x8000
+#define X509_EX_V_INIT 0x0001
+typedef struct X509_extension_st
+ {
+ ASN1_OBJECT *object;
+ ASN1_BOOLEAN critical;
+ ASN1_OCTET_STRING *value;
+ } X509_EXTENSION;
+
+typedef STACK_OF(X509_EXTENSION) X509_EXTENSIONS;
+
+DECLARE_STACK_OF(X509_EXTENSION)
+DECLARE_ASN1_SET_OF(X509_EXTENSION)
+
+/* a sequence of these are used */
+typedef struct x509_attributes_st
+ {
+ ASN1_OBJECT *object;
+ int single; /* 0 for a set, 1 for a single item (which is wrong) */
+ union {
+ char *ptr;
+/* 0 */ STACK_OF(ASN1_TYPE) *set;
+/* 1 */ ASN1_TYPE *single;
+ } value;
+ } X509_ATTRIBUTE;
+
+DECLARE_STACK_OF(X509_ATTRIBUTE)
+DECLARE_ASN1_SET_OF(X509_ATTRIBUTE)
+
+
+typedef 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;
+
+typedef struct X509_req_st
+ {
+ X509_REQ_INFO *req_info;
+ X509_ALGOR *sig_alg;
+ ASN1_BIT_STRING *signature;
+ int references;
+ } X509_REQ;
+
+typedef 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;
+
+/* 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
+ */
+
+typedef 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_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;
+ long ex_pcpathlen;
+ unsigned long ex_flags;
+ unsigned long ex_kusage;
+ unsigned long ex_xkusage;
+ unsigned long ex_nscert;
+ ASN1_OCTET_STRING *skid;
+ AUTHORITY_KEYID *akid;
+ X509_POLICY_CACHE *policy_cache;
+ STACK_OF(DIST_POINT) *crldp;
+ STACK_OF(GENERAL_NAME) *altname;
+ NAME_CONSTRAINTS *nc;
+ unsigned char sha1_hash[SHA_DIGEST_LENGTH];
+ X509_CERT_AUX *aux;
+ } /* X509 */;
+
+DECLARE_STACK_OF(X509)
+DECLARE_ASN1_SET_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)
+
+typedef struct x509_cert_pair_st {
+ X509 *forward;
+ X509 *reverse;
+} X509_CERT_PAIR;
+
+/* standard trust ids */
+
+#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)
+#define X509_FLAG_NO_IDS (1L << 12)
+
+/* Flags specific to X509_NAME_print_ex() */
+
+/* The field separator information */
+
+#define XN_FLAG_SEP_MASK (0xf << 16)
+
+#define XN_FLAG_COMPAT 0 /* Traditional 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)
+
+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 */
+ };
+
+DECLARE_STACK_OF(X509_REVOKED)
+DECLARE_ASN1_SET_OF(X509_REVOKED)
+
+typedef 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 sha1_hash[SHA_DIGEST_LENGTH];
+ STACK_OF(GENERAL_NAMES) *issuers;
+ const X509_CRL_METHOD *meth;
+ void *meth_data;
+ } /* X509_CRL */;
+
+DECLARE_STACK_OF(X509_CRL)
+DECLARE_ASN1_SET_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 <patr@x509.com> 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;
+
+/* Netscape certificate sequence structure */
+typedef struct Netscape_certificate_sequence
+ {
+ ASN1_OBJECT *type;
+ STACK_OF(X509) *certs;
+ } NETSCAPE_CERT_SEQUENCE;
+
+/* Unused (and iv length is wrong)
+typedef struct CBCParameter_st
+ {
+ unsigned char iv[8];
+ } CBC_PARAM;
+*/
+
+/* Password based encryption structure */
+
+typedef struct PBEPARAM_st {
+ASN1_OCTET_STRING *salt;
+ASN1_INTEGER *iter;
+} PBEPARAM;
+
+/* Password based encryption V2 structures */
+
+typedef struct PBE2PARAM_st {
+X509_ALGOR *keyfunc;
+X509_ALGOR *encryption;
+} PBE2PARAM;
+
+typedef struct PBKDF2PARAM_st {
+ASN1_TYPE *salt; /* Usually OCTET STRING but could be anything */
+ASN1_INTEGER *iter;
+ASN1_INTEGER *keylength;
+X509_ALGOR *prf;
+} PBKDF2PARAM;
+
+
+/* PKCS#8 private key info structure */
+
+struct pkcs8_priv_key_info_st
+ {
+ int broken; /* Flag for various broken formats */
+#define PKCS8_OK 0
+#define PKCS8_NO_OCTET 1
+#define PKCS8_EMBEDDED_PARAM 2
+#define PKCS8_NS_DB 3
+#define PKCS8_NEG_PRIVKEY 4
+ ASN1_INTEGER *version;
+ X509_ALGOR *pkeyalg;
+ ASN1_TYPE *pkey; /* Should be OCTET STRING but some are broken */
+ STACK_OF(X509_ATTRIBUTE) *attributes;
+ };
+
+#ifdef __cplusplus
+}
+#endif
+
+#include <openssl/x509_vfy.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define X509_EXT_PACK_UNKNOWN 1
+#define X509_EXT_PACK_STRING 2
+
+#define X509_get_version(x) ASN1_INTEGER_get((x)->cert_info->version)
+/* #define X509_get_serialNumber(x) ((x)->cert_info->serialNumber) */
+#define X509_get_notBefore(x) ((x)->cert_info->validity->notBefore)
+#define X509_get_notAfter(x) ((x)->cert_info->validity->notAfter)
+#define X509_get_cert_info(x) ((x)->cert_info)
+#define X509_extract_key(x) X509_get_pubkey(x) /*****/
+#define X509_REQ_get_version(x) ASN1_INTEGER_get((x)->req_info->version)
+#define X509_REQ_get_subject_name(x) ((x)->req_info->subject)
+#define X509_REQ_extract_key(a) X509_REQ_get_pubkey(a)
+#define X509_name_cmp(a,b) X509_NAME_cmp((a),(b))
+#define X509_get_signature_type(x) EVP_PKEY_type(OBJ_obj2nid((x)->sig_alg->algorithm))
+
+#define X509_CRL_get_version(x) ASN1_INTEGER_get((x)->crl->version)
+#define X509_CRL_get_lastUpdate(x) ((x)->crl->lastUpdate)
+#define X509_CRL_get_nextUpdate(x) ((x)->crl->nextUpdate)
+#define X509_CRL_get_issuer(x) ((x)->crl->issuer)
+#define X509_CRL_get_REVOKED(x) ((x)->crl->revoked)
+
+#define X509_CINF_set_modified(c) ((c)->enc.modified = 1)
+#define X509_CINF_get_issuer(c) (&(c)->issuer)
+#define X509_CINF_get_extensions(c) ((c)->extensions)
+#define X509_CINF_get_signature(c) ((c)->signature)
+
+OPENSSL_EXPORT void X509_CRL_set_default_method(const X509_CRL_METHOD *meth);
+OPENSSL_EXPORT 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));
+OPENSSL_EXPORT void X509_CRL_METHOD_free(X509_CRL_METHOD *m);
+
+OPENSSL_EXPORT void X509_CRL_set_meth_data(X509_CRL *crl, void *dat);
+OPENSSL_EXPORT void *X509_CRL_get_meth_data(X509_CRL *crl);
+
+/* This one is only used so that a binary form can output, as in
+ * i2d_X509_NAME(X509_get_X509_PUBKEY(x),&buf) */
+#define X509_get_X509_PUBKEY(x) ((x)->cert_info->key)
+
+
+OPENSSL_EXPORT const char *X509_verify_cert_error_string(long n);
+
+#ifndef OPENSSL_NO_EVP
+OPENSSL_EXPORT int X509_verify(X509 *a, EVP_PKEY *r);
+
+OPENSSL_EXPORT int X509_REQ_verify(X509_REQ *a, EVP_PKEY *r);
+OPENSSL_EXPORT int X509_CRL_verify(X509_CRL *a, EVP_PKEY *r);
+OPENSSL_EXPORT int NETSCAPE_SPKI_verify(NETSCAPE_SPKI *a, EVP_PKEY *r);
+
+OPENSSL_EXPORT NETSCAPE_SPKI * NETSCAPE_SPKI_b64_decode(const char *str, int len);
+OPENSSL_EXPORT char * NETSCAPE_SPKI_b64_encode(NETSCAPE_SPKI *x);
+OPENSSL_EXPORT EVP_PKEY *NETSCAPE_SPKI_get_pubkey(NETSCAPE_SPKI *x);
+OPENSSL_EXPORT int NETSCAPE_SPKI_set_pubkey(NETSCAPE_SPKI *x, EVP_PKEY *pkey);
+
+OPENSSL_EXPORT int NETSCAPE_SPKI_print(BIO *out, NETSCAPE_SPKI *spki);
+
+OPENSSL_EXPORT int X509_signature_dump(BIO *bp,const ASN1_STRING *sig, int indent);
+OPENSSL_EXPORT int X509_signature_print(BIO *bp,X509_ALGOR *alg, ASN1_STRING *sig);
+
+OPENSSL_EXPORT int X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md);
+OPENSSL_EXPORT int X509_sign_ctx(X509 *x, EVP_MD_CTX *ctx);
+/* int X509_http_nbio(OCSP_REQ_CTX *rctx, X509 **pcert); */
+OPENSSL_EXPORT int X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md);
+OPENSSL_EXPORT int X509_REQ_sign_ctx(X509_REQ *x, EVP_MD_CTX *ctx);
+OPENSSL_EXPORT int X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md);
+OPENSSL_EXPORT int X509_CRL_sign_ctx(X509_CRL *x, EVP_MD_CTX *ctx);
+/* int X509_CRL_http_nbio(OCSP_REQ_CTX *rctx, X509_CRL **pcrl); */
+OPENSSL_EXPORT int NETSCAPE_SPKI_sign(NETSCAPE_SPKI *x, EVP_PKEY *pkey, const EVP_MD *md);
+
+OPENSSL_EXPORT int X509_pubkey_digest(const X509 *data,const EVP_MD *type,
+ unsigned char *md, unsigned int *len);
+OPENSSL_EXPORT int X509_digest(const X509 *data,const EVP_MD *type,
+ unsigned char *md, unsigned int *len);
+OPENSSL_EXPORT int X509_CRL_digest(const X509_CRL *data,const EVP_MD *type,
+ unsigned char *md, unsigned int *len);
+OPENSSL_EXPORT int X509_REQ_digest(const X509_REQ *data,const EVP_MD *type,
+ unsigned char *md, unsigned int *len);
+OPENSSL_EXPORT int X509_NAME_digest(const X509_NAME *data,const EVP_MD *type,
+ unsigned char *md, unsigned int *len);
+#endif
+
+#ifndef OPENSSL_NO_FP_API
+OPENSSL_EXPORT X509 *d2i_X509_fp(FILE *fp, X509 **x509);
+OPENSSL_EXPORT int i2d_X509_fp(FILE *fp,X509 *x509);
+OPENSSL_EXPORT X509_CRL *d2i_X509_CRL_fp(FILE *fp,X509_CRL **crl);
+OPENSSL_EXPORT int i2d_X509_CRL_fp(FILE *fp,X509_CRL *crl);
+OPENSSL_EXPORT X509_REQ *d2i_X509_REQ_fp(FILE *fp,X509_REQ **req);
+OPENSSL_EXPORT int i2d_X509_REQ_fp(FILE *fp,X509_REQ *req);
+OPENSSL_EXPORT RSA *d2i_RSAPrivateKey_fp(FILE *fp,RSA **rsa);
+OPENSSL_EXPORT int i2d_RSAPrivateKey_fp(FILE *fp,RSA *rsa);
+OPENSSL_EXPORT RSA *d2i_RSAPublicKey_fp(FILE *fp,RSA **rsa);
+OPENSSL_EXPORT int i2d_RSAPublicKey_fp(FILE *fp,RSA *rsa);
+OPENSSL_EXPORT RSA *d2i_RSA_PUBKEY_fp(FILE *fp,RSA **rsa);
+OPENSSL_EXPORT int i2d_RSA_PUBKEY_fp(FILE *fp,RSA *rsa);
+#ifndef OPENSSL_NO_DSA
+OPENSSL_EXPORT DSA *d2i_DSA_PUBKEY_fp(FILE *fp, DSA **dsa);
+OPENSSL_EXPORT int i2d_DSA_PUBKEY_fp(FILE *fp, DSA *dsa);
+OPENSSL_EXPORT DSA *d2i_DSAPrivateKey_fp(FILE *fp, DSA **dsa);
+OPENSSL_EXPORT int i2d_DSAPrivateKey_fp(FILE *fp, DSA *dsa);
+#endif
+OPENSSL_EXPORT EC_KEY *d2i_EC_PUBKEY_fp(FILE *fp, EC_KEY **eckey);
+OPENSSL_EXPORT int i2d_EC_PUBKEY_fp(FILE *fp, EC_KEY *eckey);
+OPENSSL_EXPORT EC_KEY *d2i_ECPrivateKey_fp(FILE *fp, EC_KEY **eckey);
+OPENSSL_EXPORT int i2d_ECPrivateKey_fp(FILE *fp, EC_KEY *eckey);
+OPENSSL_EXPORT X509_SIG *d2i_PKCS8_fp(FILE *fp,X509_SIG **p8);
+OPENSSL_EXPORT int i2d_PKCS8_fp(FILE *fp,X509_SIG *p8);
+OPENSSL_EXPORT PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_fp(FILE *fp,
+ PKCS8_PRIV_KEY_INFO **p8inf);
+OPENSSL_EXPORT int i2d_PKCS8_PRIV_KEY_INFO_fp(FILE *fp,PKCS8_PRIV_KEY_INFO *p8inf);
+OPENSSL_EXPORT int i2d_PKCS8PrivateKeyInfo_fp(FILE *fp, EVP_PKEY *key);
+OPENSSL_EXPORT int i2d_PrivateKey_fp(FILE *fp, EVP_PKEY *pkey);
+OPENSSL_EXPORT EVP_PKEY *d2i_PrivateKey_fp(FILE *fp, EVP_PKEY **a);
+OPENSSL_EXPORT int i2d_PUBKEY_fp(FILE *fp, EVP_PKEY *pkey);
+OPENSSL_EXPORT EVP_PKEY *d2i_PUBKEY_fp(FILE *fp, EVP_PKEY **a);
+#endif
+
+OPENSSL_EXPORT X509 *d2i_X509_bio(BIO *bp,X509 **x509);
+OPENSSL_EXPORT int i2d_X509_bio(BIO *bp,X509 *x509);
+OPENSSL_EXPORT X509_CRL *d2i_X509_CRL_bio(BIO *bp,X509_CRL **crl);
+OPENSSL_EXPORT int i2d_X509_CRL_bio(BIO *bp,X509_CRL *crl);
+OPENSSL_EXPORT X509_REQ *d2i_X509_REQ_bio(BIO *bp,X509_REQ **req);
+OPENSSL_EXPORT int i2d_X509_REQ_bio(BIO *bp,X509_REQ *req);
+OPENSSL_EXPORT RSA *d2i_RSAPrivateKey_bio(BIO *bp,RSA **rsa);
+OPENSSL_EXPORT int i2d_RSAPrivateKey_bio(BIO *bp,RSA *rsa);
+OPENSSL_EXPORT RSA *d2i_RSAPublicKey_bio(BIO *bp,RSA **rsa);
+OPENSSL_EXPORT int i2d_RSAPublicKey_bio(BIO *bp,RSA *rsa);
+OPENSSL_EXPORT RSA *d2i_RSA_PUBKEY_bio(BIO *bp,RSA **rsa);
+OPENSSL_EXPORT int i2d_RSA_PUBKEY_bio(BIO *bp,RSA *rsa);
+#ifndef OPENSSL_NO_DSA
+OPENSSL_EXPORT DSA *d2i_DSA_PUBKEY_bio(BIO *bp, DSA **dsa);
+OPENSSL_EXPORT int i2d_DSA_PUBKEY_bio(BIO *bp, DSA *dsa);
+OPENSSL_EXPORT DSA *d2i_DSAPrivateKey_bio(BIO *bp, DSA **dsa);
+OPENSSL_EXPORT int i2d_DSAPrivateKey_bio(BIO *bp, DSA *dsa);
+#endif
+OPENSSL_EXPORT EC_KEY *d2i_EC_PUBKEY_bio(BIO *bp, EC_KEY **eckey);
+OPENSSL_EXPORT int i2d_EC_PUBKEY_bio(BIO *bp, EC_KEY *eckey);
+OPENSSL_EXPORT EC_KEY *d2i_ECPrivateKey_bio(BIO *bp, EC_KEY **eckey);
+OPENSSL_EXPORT int i2d_ECPrivateKey_bio(BIO *bp, EC_KEY *eckey);
+OPENSSL_EXPORT X509_SIG *d2i_PKCS8_bio(BIO *bp,X509_SIG **p8);
+OPENSSL_EXPORT int i2d_PKCS8_bio(BIO *bp,X509_SIG *p8);
+OPENSSL_EXPORT PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_bio(BIO *bp,
+ PKCS8_PRIV_KEY_INFO **p8inf);
+OPENSSL_EXPORT int i2d_PKCS8_PRIV_KEY_INFO_bio(BIO *bp,PKCS8_PRIV_KEY_INFO *p8inf);
+OPENSSL_EXPORT int i2d_PKCS8PrivateKeyInfo_bio(BIO *bp, EVP_PKEY *key);
+OPENSSL_EXPORT int i2d_PrivateKey_bio(BIO *bp, EVP_PKEY *pkey);
+OPENSSL_EXPORT EVP_PKEY *d2i_PrivateKey_bio(BIO *bp, EVP_PKEY **a);
+OPENSSL_EXPORT int i2d_PUBKEY_bio(BIO *bp, EVP_PKEY *pkey);
+OPENSSL_EXPORT EVP_PKEY *d2i_PUBKEY_bio(BIO *bp, EVP_PKEY **a);
+
+OPENSSL_EXPORT X509 *X509_dup(X509 *x509);
+OPENSSL_EXPORT X509_ATTRIBUTE *X509_ATTRIBUTE_dup(X509_ATTRIBUTE *xa);
+OPENSSL_EXPORT X509_EXTENSION *X509_EXTENSION_dup(X509_EXTENSION *ex);
+OPENSSL_EXPORT X509_CRL *X509_CRL_dup(X509_CRL *crl);
+OPENSSL_EXPORT X509_REVOKED *X509_REVOKED_dup(X509_REVOKED *rev);
+OPENSSL_EXPORT X509_REQ *X509_REQ_dup(X509_REQ *req);
+OPENSSL_EXPORT X509_ALGOR *X509_ALGOR_dup(X509_ALGOR *xn);
+OPENSSL_EXPORT int X509_ALGOR_set0(X509_ALGOR *alg, const ASN1_OBJECT *aobj, int ptype, void *pval);
+OPENSSL_EXPORT void X509_ALGOR_get0(ASN1_OBJECT **paobj, int *pptype, void **ppval,
+ X509_ALGOR *algor);
+OPENSSL_EXPORT void X509_ALGOR_set_md(X509_ALGOR *alg, const EVP_MD *md);
+OPENSSL_EXPORT int X509_ALGOR_cmp(const X509_ALGOR *a, const X509_ALGOR *b);
+
+OPENSSL_EXPORT X509_NAME *X509_NAME_dup(X509_NAME *xn);
+OPENSSL_EXPORT X509_NAME_ENTRY *X509_NAME_ENTRY_dup(X509_NAME_ENTRY *ne);
+
+OPENSSL_EXPORT int X509_cmp_time(const ASN1_TIME *s, time_t *t);
+OPENSSL_EXPORT int X509_cmp_current_time(const ASN1_TIME *s);
+OPENSSL_EXPORT ASN1_TIME * X509_time_adj(ASN1_TIME *s, long adj, time_t *t);
+OPENSSL_EXPORT ASN1_TIME * X509_time_adj_ex(ASN1_TIME *s, int offset_day, long offset_sec, time_t *t);
+OPENSSL_EXPORT ASN1_TIME * X509_gmtime_adj(ASN1_TIME *s, long adj);
+
+OPENSSL_EXPORT const char * X509_get_default_cert_area(void );
+OPENSSL_EXPORT const char * X509_get_default_cert_dir(void );
+OPENSSL_EXPORT const char * X509_get_default_cert_file(void );
+OPENSSL_EXPORT const char * X509_get_default_cert_dir_env(void );
+OPENSSL_EXPORT const char * X509_get_default_cert_file_env(void );
+OPENSSL_EXPORT const char * X509_get_default_private_dir(void );
+
+OPENSSL_EXPORT X509_REQ * X509_to_X509_REQ(X509 *x, EVP_PKEY *pkey, const EVP_MD *md);
+OPENSSL_EXPORT X509 * X509_REQ_to_X509(X509_REQ *r, int days,EVP_PKEY *pkey);
+
+DECLARE_ASN1_ENCODE_FUNCTIONS(X509_ALGORS, X509_ALGORS, X509_ALGORS)
+DECLARE_ASN1_FUNCTIONS(X509_VAL)
+
+DECLARE_ASN1_FUNCTIONS(X509_PUBKEY)
+
+OPENSSL_EXPORT int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey);
+OPENSSL_EXPORT EVP_PKEY * X509_PUBKEY_get(X509_PUBKEY *key);
+OPENSSL_EXPORT int X509_get_pubkey_parameters(EVP_PKEY *pkey,
+ STACK_OF(X509) *chain);
+OPENSSL_EXPORT int i2d_PUBKEY(const EVP_PKEY *a,unsigned char **pp);
+OPENSSL_EXPORT EVP_PKEY * d2i_PUBKEY(EVP_PKEY **a,const unsigned char **pp,
+ long length);
+OPENSSL_EXPORT int i2d_RSA_PUBKEY(const RSA *a,unsigned char **pp);
+OPENSSL_EXPORT RSA * d2i_RSA_PUBKEY(RSA **a,const unsigned char **pp,
+ long length);
+#ifndef OPENSSL_NO_DSA
+OPENSSL_EXPORT int i2d_DSA_PUBKEY(const DSA *a,unsigned char **pp);
+OPENSSL_EXPORT DSA * d2i_DSA_PUBKEY(DSA **a,const unsigned char **pp,
+ long length);
+#endif
+OPENSSL_EXPORT int i2d_EC_PUBKEY(const EC_KEY *a, unsigned char **pp);
+OPENSSL_EXPORT EC_KEY *d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp,
+ long length);
+
+DECLARE_ASN1_FUNCTIONS(X509_SIG)
+DECLARE_ASN1_FUNCTIONS(X509_REQ_INFO)
+DECLARE_ASN1_FUNCTIONS(X509_REQ)
+
+DECLARE_ASN1_FUNCTIONS(X509_ATTRIBUTE)
+OPENSSL_EXPORT X509_ATTRIBUTE *X509_ATTRIBUTE_create(int nid, int atrtype, void *value);
+
+DECLARE_ASN1_FUNCTIONS(X509_EXTENSION)
+DECLARE_ASN1_ENCODE_FUNCTIONS(X509_EXTENSIONS, X509_EXTENSIONS, X509_EXTENSIONS)
+
+DECLARE_ASN1_FUNCTIONS(X509_NAME_ENTRY)
+
+DECLARE_ASN1_FUNCTIONS(X509_NAME)
+
+OPENSSL_EXPORT int X509_NAME_set(X509_NAME **xn, X509_NAME *name);
+
+DECLARE_ASN1_FUNCTIONS(X509_CINF)
+
+DECLARE_ASN1_FUNCTIONS(X509)
+DECLARE_ASN1_FUNCTIONS(X509_CERT_AUX)
+
+DECLARE_ASN1_FUNCTIONS(X509_CERT_PAIR)
+
+/* X509_up_ref adds one to the reference count of |x| and returns
+ * |x|. */
+OPENSSL_EXPORT X509 *X509_up_ref(X509 *x);
+
+OPENSSL_EXPORT 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);
+OPENSSL_EXPORT int X509_set_ex_data(X509 *r, int idx, void *arg);
+OPENSSL_EXPORT void *X509_get_ex_data(X509 *r, int idx);
+OPENSSL_EXPORT int i2d_X509_AUX(X509 *a,unsigned char **pp);
+OPENSSL_EXPORT X509 * d2i_X509_AUX(X509 **a,const unsigned char **pp,long length);
+
+OPENSSL_EXPORT void X509_get0_signature(ASN1_BIT_STRING **psig, X509_ALGOR **palg,
+ const X509 *x);
+OPENSSL_EXPORT int X509_get_signature_nid(const X509 *x);
+
+OPENSSL_EXPORT int X509_alias_set1(X509 *x, unsigned char *name, int len);
+OPENSSL_EXPORT int X509_keyid_set1(X509 *x, unsigned char *id, int len);
+OPENSSL_EXPORT unsigned char * X509_alias_get0(X509 *x, int *len);
+OPENSSL_EXPORT unsigned char * X509_keyid_get0(X509 *x, int *len);
+OPENSSL_EXPORT int (*X509_TRUST_set_default(int (*trust)(int , X509 *, int)))(int, X509 *, int);
+OPENSSL_EXPORT int X509_TRUST_set(int *t, int trust);
+OPENSSL_EXPORT int X509_add1_trust_object(X509 *x, ASN1_OBJECT *obj);
+OPENSSL_EXPORT int X509_add1_reject_object(X509 *x, ASN1_OBJECT *obj);
+OPENSSL_EXPORT void X509_trust_clear(X509 *x);
+OPENSSL_EXPORT void X509_reject_clear(X509 *x);
+
+DECLARE_ASN1_FUNCTIONS(X509_REVOKED)
+DECLARE_ASN1_FUNCTIONS(X509_CRL_INFO)
+DECLARE_ASN1_FUNCTIONS(X509_CRL)
+
+OPENSSL_EXPORT int X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev);
+OPENSSL_EXPORT int X509_CRL_get0_by_serial(X509_CRL *crl,
+ X509_REVOKED **ret, ASN1_INTEGER *serial);
+OPENSSL_EXPORT int X509_CRL_get0_by_cert(X509_CRL *crl, X509_REVOKED **ret, X509 *x);
+
+OPENSSL_EXPORT X509_PKEY * X509_PKEY_new(void );
+OPENSSL_EXPORT void X509_PKEY_free(X509_PKEY *a);
+
+DECLARE_ASN1_FUNCTIONS(NETSCAPE_SPKI)
+DECLARE_ASN1_FUNCTIONS(NETSCAPE_SPKAC)
+DECLARE_ASN1_FUNCTIONS(NETSCAPE_CERT_SEQUENCE)
+
+#ifndef OPENSSL_NO_EVP
+OPENSSL_EXPORT X509_INFO * X509_INFO_new(void);
+OPENSSL_EXPORT void X509_INFO_free(X509_INFO *a);
+OPENSSL_EXPORT char * X509_NAME_oneline(X509_NAME *a,char *buf,int size);
+
+OPENSSL_EXPORT int ASN1_digest(i2d_of_void *i2d,const EVP_MD *type,char *data,
+ unsigned char *md,unsigned int *len);
+
+OPENSSL_EXPORT int ASN1_item_digest(const ASN1_ITEM *it,const EVP_MD *type,void *data,
+ unsigned char *md,unsigned int *len);
+
+OPENSSL_EXPORT int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *algor1,
+ ASN1_BIT_STRING *signature,void *data,EVP_PKEY *pkey);
+
+OPENSSL_EXPORT 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);
+OPENSSL_EXPORT 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
+
+OPENSSL_EXPORT int X509_set_version(X509 *x,long version);
+OPENSSL_EXPORT int X509_set_serialNumber(X509 *x, ASN1_INTEGER *serial);
+OPENSSL_EXPORT ASN1_INTEGER * X509_get_serialNumber(X509 *x);
+OPENSSL_EXPORT int X509_set_issuer_name(X509 *x, X509_NAME *name);
+OPENSSL_EXPORT X509_NAME * X509_get_issuer_name(X509 *a);
+OPENSSL_EXPORT int X509_set_subject_name(X509 *x, X509_NAME *name);
+OPENSSL_EXPORT X509_NAME * X509_get_subject_name(X509 *a);
+OPENSSL_EXPORT int X509_set_notBefore(X509 *x, const ASN1_TIME *tm);
+OPENSSL_EXPORT int X509_set_notAfter(X509 *x, const ASN1_TIME *tm);
+OPENSSL_EXPORT int X509_set_pubkey(X509 *x, EVP_PKEY *pkey);
+OPENSSL_EXPORT EVP_PKEY * X509_get_pubkey(X509 *x);
+OPENSSL_EXPORT ASN1_BIT_STRING * X509_get0_pubkey_bitstr(const X509 *x);
+OPENSSL_EXPORT int X509_certificate_type(X509 *x,EVP_PKEY *pubkey /* optional */);
+
+OPENSSL_EXPORT int X509_REQ_set_version(X509_REQ *x,long version);
+OPENSSL_EXPORT int X509_REQ_set_subject_name(X509_REQ *req,X509_NAME *name);
+OPENSSL_EXPORT int X509_REQ_set_pubkey(X509_REQ *x, EVP_PKEY *pkey);
+OPENSSL_EXPORT EVP_PKEY * X509_REQ_get_pubkey(X509_REQ *req);
+OPENSSL_EXPORT int X509_REQ_extension_nid(int nid);
+OPENSSL_EXPORT const int * X509_REQ_get_extension_nids(void);
+OPENSSL_EXPORT void X509_REQ_set_extension_nids(const int *nids);
+OPENSSL_EXPORT STACK_OF(X509_EXTENSION) *X509_REQ_get_extensions(X509_REQ *req);
+OPENSSL_EXPORT int X509_REQ_add_extensions_nid(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts,
+ int nid);
+OPENSSL_EXPORT int X509_REQ_add_extensions(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts);
+OPENSSL_EXPORT int X509_REQ_get_attr_count(const X509_REQ *req);
+OPENSSL_EXPORT int X509_REQ_get_attr_by_NID(const X509_REQ *req, int nid,
+ int lastpos);
+OPENSSL_EXPORT int X509_REQ_get_attr_by_OBJ(const X509_REQ *req, ASN1_OBJECT *obj,
+ int lastpos);
+OPENSSL_EXPORT X509_ATTRIBUTE *X509_REQ_get_attr(const X509_REQ *req, int loc);
+OPENSSL_EXPORT X509_ATTRIBUTE *X509_REQ_delete_attr(X509_REQ *req, int loc);
+OPENSSL_EXPORT int X509_REQ_add1_attr(X509_REQ *req, X509_ATTRIBUTE *attr);
+OPENSSL_EXPORT int X509_REQ_add1_attr_by_OBJ(X509_REQ *req,
+ const ASN1_OBJECT *obj, int type,
+ const unsigned char *bytes, int len);
+OPENSSL_EXPORT int X509_REQ_add1_attr_by_NID(X509_REQ *req,
+ int nid, int type,
+ const unsigned char *bytes, int len);
+OPENSSL_EXPORT int X509_REQ_add1_attr_by_txt(X509_REQ *req,
+ const char *attrname, int type,
+ const unsigned char *bytes, int len);
+
+OPENSSL_EXPORT int X509_CRL_set_version(X509_CRL *x, long version);
+OPENSSL_EXPORT int X509_CRL_set_issuer_name(X509_CRL *x, X509_NAME *name);
+OPENSSL_EXPORT int X509_CRL_set_lastUpdate(X509_CRL *x, const ASN1_TIME *tm);
+OPENSSL_EXPORT int X509_CRL_set_nextUpdate(X509_CRL *x, const ASN1_TIME *tm);
+OPENSSL_EXPORT int X509_CRL_sort(X509_CRL *crl);
+
+OPENSSL_EXPORT int X509_REVOKED_set_serialNumber(X509_REVOKED *x, ASN1_INTEGER *serial);
+OPENSSL_EXPORT int X509_REVOKED_set_revocationDate(X509_REVOKED *r, ASN1_TIME *tm);
+
+OPENSSL_EXPORT X509_CRL *X509_CRL_diff(X509_CRL *base, X509_CRL *newer,
+ EVP_PKEY *skey, const EVP_MD *md, unsigned int flags);
+
+OPENSSL_EXPORT int X509_REQ_check_private_key(X509_REQ *x509,EVP_PKEY *pkey);
+
+OPENSSL_EXPORT int X509_check_private_key(X509 *x509,EVP_PKEY *pkey);
+OPENSSL_EXPORT int X509_chain_check_suiteb(int *perror_depth,
+ X509 *x, STACK_OF(X509) *chain,
+ unsigned long flags);
+OPENSSL_EXPORT int X509_CRL_check_suiteb(X509_CRL *crl, EVP_PKEY *pk,
+ unsigned long flags);
+OPENSSL_EXPORT STACK_OF(X509) *X509_chain_up_ref(STACK_OF(X509) *chain);
+
+OPENSSL_EXPORT int X509_issuer_and_serial_cmp(const X509 *a, const X509 *b);
+OPENSSL_EXPORT unsigned long X509_issuer_and_serial_hash(X509 *a);
+
+OPENSSL_EXPORT int X509_issuer_name_cmp(const X509 *a, const X509 *b);
+OPENSSL_EXPORT unsigned long X509_issuer_name_hash(X509 *a);
+
+OPENSSL_EXPORT int X509_subject_name_cmp(const X509 *a, const X509 *b);
+OPENSSL_EXPORT unsigned long X509_subject_name_hash(X509 *x);
+
+OPENSSL_EXPORT unsigned long X509_issuer_name_hash_old(X509 *a);
+OPENSSL_EXPORT unsigned long X509_subject_name_hash_old(X509 *x);
+
+OPENSSL_EXPORT int X509_cmp(const X509 *a, const X509 *b);
+OPENSSL_EXPORT int X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b);
+OPENSSL_EXPORT unsigned long X509_NAME_hash(X509_NAME *x);
+OPENSSL_EXPORT unsigned long X509_NAME_hash_old(X509_NAME *x);
+
+OPENSSL_EXPORT int X509_CRL_cmp(const X509_CRL *a, const X509_CRL *b);
+OPENSSL_EXPORT int X509_CRL_match(const X509_CRL *a, const X509_CRL *b);
+#ifndef OPENSSL_NO_FP_API
+OPENSSL_EXPORT int X509_print_ex_fp(FILE *bp,X509 *x, unsigned long nmflag, unsigned long cflag);
+OPENSSL_EXPORT int X509_print_fp(FILE *bp,X509 *x);
+OPENSSL_EXPORT int X509_CRL_print_fp(FILE *bp,X509_CRL *x);
+OPENSSL_EXPORT int X509_REQ_print_fp(FILE *bp,X509_REQ *req);
+OPENSSL_EXPORT int X509_NAME_print_ex_fp(FILE *fp, X509_NAME *nm, int indent, unsigned long flags);
+#endif
+
+OPENSSL_EXPORT int X509_NAME_print(BIO *bp, X509_NAME *name, int obase);
+OPENSSL_EXPORT int X509_NAME_print_ex(BIO *out, X509_NAME *nm, int indent, unsigned long flags);
+OPENSSL_EXPORT int X509_print_ex(BIO *bp,X509 *x, unsigned long nmflag, unsigned long cflag);
+OPENSSL_EXPORT int X509_print(BIO *bp,X509 *x);
+OPENSSL_EXPORT int X509_ocspid_print(BIO *bp,X509 *x);
+OPENSSL_EXPORT int X509_CERT_AUX_print(BIO *bp,X509_CERT_AUX *x, int indent);
+OPENSSL_EXPORT int X509_CRL_print(BIO *bp,X509_CRL *x);
+OPENSSL_EXPORT int X509_REQ_print_ex(BIO *bp, X509_REQ *x, unsigned long nmflag, unsigned long cflag);
+OPENSSL_EXPORT int X509_REQ_print(BIO *bp,X509_REQ *req);
+
+OPENSSL_EXPORT int X509_NAME_entry_count(X509_NAME *name);
+OPENSSL_EXPORT int X509_NAME_get_text_by_NID(X509_NAME *name, int nid,
+ char *buf,int len);
+OPENSSL_EXPORT int X509_NAME_get_text_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj,
+ char *buf,int len);
+
+/* NOTE: you should be passsing -1, not 0 as lastpos. The functions that use
+ * lastpos, search after that position on. */
+OPENSSL_EXPORT int X509_NAME_get_index_by_NID(X509_NAME *name,int nid,int lastpos);
+OPENSSL_EXPORT int X509_NAME_get_index_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj,
+ int lastpos);
+OPENSSL_EXPORT X509_NAME_ENTRY *X509_NAME_get_entry(X509_NAME *name, int loc);
+OPENSSL_EXPORT X509_NAME_ENTRY *X509_NAME_delete_entry(X509_NAME *name, int loc);
+OPENSSL_EXPORT int X509_NAME_add_entry(X509_NAME *name,X509_NAME_ENTRY *ne,
+ int loc, int set);
+OPENSSL_EXPORT int X509_NAME_add_entry_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, int type,
+ unsigned char *bytes, int len, int loc, int set);
+OPENSSL_EXPORT int X509_NAME_add_entry_by_NID(X509_NAME *name, int nid, int type,
+ unsigned char *bytes, int len, int loc, int set);
+OPENSSL_EXPORT X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_txt(X509_NAME_ENTRY **ne,
+ const char *field, int type, const unsigned char *bytes, int len);
+OPENSSL_EXPORT X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_NID(X509_NAME_ENTRY **ne, int nid,
+ int type,unsigned char *bytes, int len);
+OPENSSL_EXPORT 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);
+OPENSSL_EXPORT 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);
+OPENSSL_EXPORT int X509_NAME_ENTRY_set_object(X509_NAME_ENTRY *ne,
+ const ASN1_OBJECT *obj);
+OPENSSL_EXPORT int X509_NAME_ENTRY_set_data(X509_NAME_ENTRY *ne, int type,
+ const unsigned char *bytes, int len);
+OPENSSL_EXPORT ASN1_OBJECT * X509_NAME_ENTRY_get_object(X509_NAME_ENTRY *ne);
+OPENSSL_EXPORT ASN1_STRING * X509_NAME_ENTRY_get_data(X509_NAME_ENTRY *ne);
+
+OPENSSL_EXPORT int X509v3_get_ext_count(const STACK_OF(X509_EXTENSION) *x);
+OPENSSL_EXPORT int X509v3_get_ext_by_NID(const STACK_OF(X509_EXTENSION) *x,
+ int nid, int lastpos);
+OPENSSL_EXPORT int X509v3_get_ext_by_OBJ(const STACK_OF(X509_EXTENSION) *x,
+ const ASN1_OBJECT *obj,int lastpos);
+OPENSSL_EXPORT int X509v3_get_ext_by_critical(const STACK_OF(X509_EXTENSION) *x,
+ int crit, int lastpos);
+OPENSSL_EXPORT X509_EXTENSION *X509v3_get_ext(const STACK_OF(X509_EXTENSION) *x, int loc);
+OPENSSL_EXPORT X509_EXTENSION *X509v3_delete_ext(STACK_OF(X509_EXTENSION) *x, int loc);
+OPENSSL_EXPORT STACK_OF(X509_EXTENSION) *X509v3_add_ext(STACK_OF(X509_EXTENSION) **x,
+ X509_EXTENSION *ex, int loc);
+
+OPENSSL_EXPORT int X509_get_ext_count(X509 *x);
+OPENSSL_EXPORT int X509_get_ext_by_NID(X509 *x, int nid, int lastpos);
+OPENSSL_EXPORT int X509_get_ext_by_OBJ(X509 *x,ASN1_OBJECT *obj,int lastpos);
+OPENSSL_EXPORT int X509_get_ext_by_critical(X509 *x, int crit, int lastpos);
+OPENSSL_EXPORT X509_EXTENSION *X509_get_ext(X509 *x, int loc);
+OPENSSL_EXPORT X509_EXTENSION *X509_delete_ext(X509 *x, int loc);
+OPENSSL_EXPORT int X509_add_ext(X509 *x, X509_EXTENSION *ex, int loc);
+OPENSSL_EXPORT void * X509_get_ext_d2i(X509 *x, int nid, int *crit, int *idx);
+OPENSSL_EXPORT int X509_add1_ext_i2d(X509 *x, int nid, void *value, int crit,
+ unsigned long flags);
+
+OPENSSL_EXPORT int X509_CRL_get_ext_count(X509_CRL *x);
+OPENSSL_EXPORT int X509_CRL_get_ext_by_NID(X509_CRL *x, int nid, int lastpos);
+OPENSSL_EXPORT int X509_CRL_get_ext_by_OBJ(X509_CRL *x,ASN1_OBJECT *obj,int lastpos);
+OPENSSL_EXPORT int X509_CRL_get_ext_by_critical(X509_CRL *x, int crit, int lastpos);
+OPENSSL_EXPORT X509_EXTENSION *X509_CRL_get_ext(X509_CRL *x, int loc);
+OPENSSL_EXPORT X509_EXTENSION *X509_CRL_delete_ext(X509_CRL *x, int loc);
+OPENSSL_EXPORT int X509_CRL_add_ext(X509_CRL *x, X509_EXTENSION *ex, int loc);
+OPENSSL_EXPORT void * X509_CRL_get_ext_d2i(X509_CRL *x, int nid, int *crit, int *idx);
+OPENSSL_EXPORT int X509_CRL_add1_ext_i2d(X509_CRL *x, int nid, void *value, int crit,
+ unsigned long flags);
+
+OPENSSL_EXPORT int X509_REVOKED_get_ext_count(X509_REVOKED *x);
+OPENSSL_EXPORT int X509_REVOKED_get_ext_by_NID(X509_REVOKED *x, int nid, int lastpos);
+OPENSSL_EXPORT int X509_REVOKED_get_ext_by_OBJ(X509_REVOKED *x,ASN1_OBJECT *obj,int lastpos);
+OPENSSL_EXPORT int X509_REVOKED_get_ext_by_critical(X509_REVOKED *x, int crit, int lastpos);
+OPENSSL_EXPORT X509_EXTENSION *X509_REVOKED_get_ext(X509_REVOKED *x, int loc);
+OPENSSL_EXPORT X509_EXTENSION *X509_REVOKED_delete_ext(X509_REVOKED *x, int loc);
+OPENSSL_EXPORT int X509_REVOKED_add_ext(X509_REVOKED *x, X509_EXTENSION *ex, int loc);
+OPENSSL_EXPORT void * X509_REVOKED_get_ext_d2i(X509_REVOKED *x, int nid, int *crit, int *idx);
+OPENSSL_EXPORT int X509_REVOKED_add1_ext_i2d(X509_REVOKED *x, int nid, void *value, int crit,
+ unsigned long flags);
+
+OPENSSL_EXPORT X509_EXTENSION *X509_EXTENSION_create_by_NID(X509_EXTENSION **ex,
+ int nid, int crit, ASN1_OCTET_STRING *data);
+OPENSSL_EXPORT X509_EXTENSION *X509_EXTENSION_create_by_OBJ(X509_EXTENSION **ex,
+ const ASN1_OBJECT *obj,int crit,ASN1_OCTET_STRING *data);
+OPENSSL_EXPORT int X509_EXTENSION_set_object(X509_EXTENSION *ex,const ASN1_OBJECT *obj);
+OPENSSL_EXPORT int X509_EXTENSION_set_critical(X509_EXTENSION *ex, int crit);
+OPENSSL_EXPORT int X509_EXTENSION_set_data(X509_EXTENSION *ex,
+ ASN1_OCTET_STRING *data);
+OPENSSL_EXPORT ASN1_OBJECT * X509_EXTENSION_get_object(X509_EXTENSION *ex);
+OPENSSL_EXPORT ASN1_OCTET_STRING *X509_EXTENSION_get_data(X509_EXTENSION *ne);
+OPENSSL_EXPORT int X509_EXTENSION_get_critical(X509_EXTENSION *ex);
+
+OPENSSL_EXPORT int X509at_get_attr_count(const STACK_OF(X509_ATTRIBUTE) *x);
+OPENSSL_EXPORT int X509at_get_attr_by_NID(const STACK_OF(X509_ATTRIBUTE) *x, int nid,
+ int lastpos);
+OPENSSL_EXPORT int X509at_get_attr_by_OBJ(const STACK_OF(X509_ATTRIBUTE) *sk, const ASN1_OBJECT *obj,
+ int lastpos);
+OPENSSL_EXPORT X509_ATTRIBUTE *X509at_get_attr(const STACK_OF(X509_ATTRIBUTE) *x, int loc);
+OPENSSL_EXPORT X509_ATTRIBUTE *X509at_delete_attr(STACK_OF(X509_ATTRIBUTE) *x, int loc);
+OPENSSL_EXPORT STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr(STACK_OF(X509_ATTRIBUTE) **x,
+ X509_ATTRIBUTE *attr);
+OPENSSL_EXPORT 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);
+OPENSSL_EXPORT STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_NID(STACK_OF(X509_ATTRIBUTE) **x,
+ int nid, int type,
+ const unsigned char *bytes, int len);
+OPENSSL_EXPORT 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);
+OPENSSL_EXPORT void *X509at_get0_data_by_OBJ(STACK_OF(X509_ATTRIBUTE) *x,
+ ASN1_OBJECT *obj, int lastpos, int type);
+OPENSSL_EXPORT X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_NID(X509_ATTRIBUTE **attr, int nid,
+ int atrtype, const void *data, int len);
+OPENSSL_EXPORT X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_OBJ(X509_ATTRIBUTE **attr,
+ const ASN1_OBJECT *obj, int atrtype, const void *data, int len);
+OPENSSL_EXPORT X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_txt(X509_ATTRIBUTE **attr,
+ const char *atrname, int type, const unsigned char *bytes, int len);
+OPENSSL_EXPORT int X509_ATTRIBUTE_set1_object(X509_ATTRIBUTE *attr, const ASN1_OBJECT *obj);
+OPENSSL_EXPORT int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype, const void *data, int len);
+OPENSSL_EXPORT void *X509_ATTRIBUTE_get0_data(X509_ATTRIBUTE *attr, int idx,
+ int atrtype, void *data);
+OPENSSL_EXPORT int X509_ATTRIBUTE_count(X509_ATTRIBUTE *attr);
+OPENSSL_EXPORT ASN1_OBJECT *X509_ATTRIBUTE_get0_object(X509_ATTRIBUTE *attr);
+OPENSSL_EXPORT ASN1_TYPE *X509_ATTRIBUTE_get0_type(X509_ATTRIBUTE *attr, int idx);
+
+OPENSSL_EXPORT int EVP_PKEY_get_attr_count(const EVP_PKEY *key);
+OPENSSL_EXPORT int EVP_PKEY_get_attr_by_NID(const EVP_PKEY *key, int nid,
+ int lastpos);
+OPENSSL_EXPORT int EVP_PKEY_get_attr_by_OBJ(const EVP_PKEY *key, ASN1_OBJECT *obj,
+ int lastpos);
+OPENSSL_EXPORT X509_ATTRIBUTE *EVP_PKEY_get_attr(const EVP_PKEY *key, int loc);
+OPENSSL_EXPORT X509_ATTRIBUTE *EVP_PKEY_delete_attr(EVP_PKEY *key, int loc);
+OPENSSL_EXPORT int EVP_PKEY_add1_attr(EVP_PKEY *key, X509_ATTRIBUTE *attr);
+OPENSSL_EXPORT int EVP_PKEY_add1_attr_by_OBJ(EVP_PKEY *key,
+ const ASN1_OBJECT *obj, int type,
+ const unsigned char *bytes, int len);
+OPENSSL_EXPORT int EVP_PKEY_add1_attr_by_NID(EVP_PKEY *key,
+ int nid, int type,
+ const unsigned char *bytes, int len);
+OPENSSL_EXPORT int EVP_PKEY_add1_attr_by_txt(EVP_PKEY *key,
+ const char *attrname, int type,
+ const unsigned char *bytes, int len);
+
+OPENSSL_EXPORT int X509_verify_cert(X509_STORE_CTX *ctx);
+
+/* lookup a cert from a X509 STACK */
+OPENSSL_EXPORT X509 *X509_find_by_issuer_and_serial(STACK_OF(X509) *sk,X509_NAME *name,
+ ASN1_INTEGER *serial);
+OPENSSL_EXPORT X509 *X509_find_by_subject(STACK_OF(X509) *sk,X509_NAME *name);
+
+DECLARE_ASN1_FUNCTIONS(PBEPARAM)
+DECLARE_ASN1_FUNCTIONS(PBE2PARAM)
+DECLARE_ASN1_FUNCTIONS(PBKDF2PARAM)
+
+OPENSSL_EXPORT int PKCS5_pbe_set0_algor(X509_ALGOR *algor, int alg, int iter,
+ const unsigned char *salt, int saltlen);
+
+OPENSSL_EXPORT X509_ALGOR *PKCS5_pbe_set(int alg, int iter,
+ const unsigned char *salt, int saltlen);
+OPENSSL_EXPORT X509_ALGOR *PKCS5_pbe2_set(const EVP_CIPHER *cipher, int iter,
+ unsigned char *salt, int saltlen);
+OPENSSL_EXPORT X509_ALGOR *PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter,
+ unsigned char *salt, int saltlen,
+ unsigned char *aiv, int prf_nid);
+
+OPENSSL_EXPORT X509_ALGOR *PKCS5_pbkdf2_set(int iter, unsigned char *salt, int saltlen,
+ int prf_nid, int keylen);
+
+/* PKCS#8 utilities */
+
+DECLARE_ASN1_FUNCTIONS(PKCS8_PRIV_KEY_INFO)
+
+OPENSSL_EXPORT EVP_PKEY *EVP_PKCS82PKEY(PKCS8_PRIV_KEY_INFO *p8);
+OPENSSL_EXPORT PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(EVP_PKEY *pkey);
+OPENSSL_EXPORT PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8_broken(EVP_PKEY *pkey, int broken);
+OPENSSL_EXPORT PKCS8_PRIV_KEY_INFO *PKCS8_set_broken(PKCS8_PRIV_KEY_INFO *p8, int broken);
+
+OPENSSL_EXPORT int PKCS8_pkey_set0(PKCS8_PRIV_KEY_INFO *priv, ASN1_OBJECT *aobj,
+ int version, int ptype, void *pval,
+ unsigned char *penc, int penclen);
+OPENSSL_EXPORT int PKCS8_pkey_get0(ASN1_OBJECT **ppkalg,
+ const unsigned char **pk, int *ppklen,
+ X509_ALGOR **pa,
+ PKCS8_PRIV_KEY_INFO *p8);
+
+OPENSSL_EXPORT int X509_PUBKEY_set0_param(X509_PUBKEY *pub, const ASN1_OBJECT *aobj,
+ int ptype, void *pval,
+ unsigned char *penc, int penclen);
+OPENSSL_EXPORT int X509_PUBKEY_get0_param(ASN1_OBJECT **ppkalg,
+ const unsigned char **pk, int *ppklen,
+ X509_ALGOR **pa,
+ X509_PUBKEY *pub);
+
+OPENSSL_EXPORT int X509_check_trust(X509 *x, int id, int flags);
+OPENSSL_EXPORT int X509_TRUST_get_count(void);
+OPENSSL_EXPORT X509_TRUST * X509_TRUST_get0(int idx);
+OPENSSL_EXPORT int X509_TRUST_get_by_id(int id);
+OPENSSL_EXPORT int X509_TRUST_add(int id, int flags, int (*ck)(X509_TRUST *, X509 *, int),
+ char *name, int arg1, void *arg2);
+OPENSSL_EXPORT void X509_TRUST_cleanup(void);
+OPENSSL_EXPORT int X509_TRUST_get_flags(X509_TRUST *xp);
+OPENSSL_EXPORT char *X509_TRUST_get0_name(X509_TRUST *xp);
+OPENSSL_EXPORT int X509_TRUST_get_trust(X509_TRUST *xp);
+
+/* PKCS7_get_certificates parses a PKCS#7, SignedData structure from |cbs| and
+ * appends the included certificates to |out_certs|. It returns one on success
+ * and zero on error. */
+OPENSSL_EXPORT int PKCS7_get_certificates(STACK_OF(X509) *out_certs, CBS *cbs);
+
+/* PKCS7_bundle_certificates appends a PKCS#7, SignedData structure containing
+ * |certs| to |cbb|. It returns one on success and zero on error. */
+OPENSSL_EXPORT int PKCS7_bundle_certificates(
+ CBB *out, const STACK_OF(X509) *certs);
+
+
+/* EVP_PK values indicate the algorithm of the public key in a certificate. */
+
+#define EVP_PK_RSA 0x0001
+#define EVP_PK_DSA 0x0002
+#define EVP_PK_DH 0x0004
+#define EVP_PK_EC 0x0008
+
+/* EVP_PKS values indicate the algorithm used to sign a certificate. */
+
+#define EVP_PKS_RSA 0x0100
+#define EVP_PKS_DSA 0x0200
+#define EVP_PKS_EC 0x0400
+
+/* EVP_PKT values are flags that define what public-key operations can be
+ * performed with the public key from a certificate. */
+
+/* EVP_PKT_SIGN indicates that the public key can be used for signing. */
+#define EVP_PKT_SIGN 0x0010
+/* EVP_PKT_ENC indicates that a session key can be encrypted to the public
+ * key. */
+#define EVP_PKT_ENC 0x0020
+/* EVP_PKT_EXCH indicates that key-agreement can be performed. */
+#define EVP_PKT_EXCH 0x0040
+/* EVP_PKT_EXP indicates that key is weak (i.e. "export"). */
+#define EVP_PKT_EXP 0x1000
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#define X509_F_x509_name_ex_new 100
+#define X509_F_X509_EXTENSION_create_by_NID 101
+#define X509_F_X509_load_crl_file 102
+#define X509_F_X509_TRUST_set 103
+#define X509_F_X509_EXTENSION_create_by_OBJ 104
+#define X509_F_by_file_ctrl 105
+#define X509_F_X509_load_cert_crl_file 106
+#define X509_F_X509_CRL_add0_revoked 107
+#define X509_F_bitstr_cb 108
+#define X509_F_X509_STORE_CTX_new 109
+#define X509_F_X509_REQ_to_X509 110
+#define X509_F_X509v3_add_ext 111
+#define X509_F_ASN1_sign 112
+#define X509_F_asn1_str2type 113
+#define X509_F_i2d_RSA_PUBKEY 114
+#define X509_F_ASN1_item_sign_ctx 115
+#define X509_F_x509_name_encode 116
+#define X509_F_d2i_X509_PKEY 117
+#define X509_F_ASN1_generate_v3 118
+#define X509_F_dir_ctrl 119
+#define X509_F_X509_print_ex_fp 120
+#define X509_F_X509_ATTRIBUTE_get0_data 121
+#define X509_F_X509_NAME_oneline 122
+#define X509_F_X509_CRL_print_fp 123
+#define X509_F_X509_STORE_CTX_get1_issuer 124
+#define X509_F_add_cert_dir 125
+#define X509_F_PKCS7_get_certificates 126
+#define X509_F_X509_ATTRIBUTE_create_by_NID 127
+#define X509_F_X509_ATTRIBUTE_set1_data 128
+#define X509_F_X509_STORE_CTX_init 129
+#define X509_F_NETSCAPE_SPKI_b64_decode 130
+#define X509_F_X509_NAME_print 131
+#define X509_F_x509_name_ex_d2i 132
+#define X509_F_X509_PKEY_new 133
+#define X509_F_X509_STORE_add_cert 134
+#define X509_F_parse_tagging 135
+#define X509_F_check_policy 136
+#define X509_F_ASN1_digest 137
+#define X509_F_X509_load_cert_file 138
+#define X509_F_X509_ATTRIBUTE_create_by_txt 139
+#define X509_F_X509_PUBKEY_set 140
+#define X509_F_X509_PUBKEY_get 141
+#define X509_F_get_cert_by_subject 142
+#define X509_F_X509_NAME_add_entry 143
+#define X509_F_X509at_add1_attr 144
+#define X509_F_X509_check_private_key 145
+#define X509_F_append_exp 146
+#define X509_F_i2d_EC_PUBKEY 147
+#define X509_F_X509_INFO_new 148
+#define X509_F_X509_STORE_CTX_purpose_inherit 149
+#define X509_F_NETSCAPE_SPKI_b64_encode 150
+#define X509_F_X509_to_X509_REQ 151
+#define X509_F_X509_NAME_ENTRY_create_by_txt 152
+#define X509_F_X509_NAME_ENTRY_set_object 153
+#define X509_F_asn1_cb 154
+#define X509_F_X509_verify_cert 155
+#define X509_F_X509_CRL_diff 156
+#define X509_F_i2d_PrivateKey 157
+#define X509_F_X509_REQ_check_private_key 158
+#define X509_F_X509_STORE_add_crl 159
+#define X509_F_X509_get_pubkey_parameters 160
+#define X509_F_ASN1_item_verify 161
+#define X509_F_X509_ATTRIBUTE_create_by_OBJ 162
+#define X509_F_i2d_DSA_PUBKEY 163
+#define X509_F_X509_TRUST_add 164
+#define X509_F_X509_NAME_ENTRY_create_by_NID 165
+#define X509_R_NO_CERT_SET_FOR_US_TO_VERIFY 100
+#define X509_R_UNABLE_TO_FIND_PARAMETERS_IN_CHAIN 101
+#define X509_R_METHOD_NOT_SUPPORTED 102
+#define X509_R_UNSUPPORTED_ALGORITHM 103
+#define X509_R_CRL_VERIFY_FAILURE 104
+#define X509_R_BASE64_DECODE_ERROR 105
+#define X509_R_INVALID_TRUST 106
+#define X509_R_UNKNOWN_NID 107
+#define X509_R_INVALID_DIRECTORY 108
+#define X509_R_KEY_VALUES_MISMATCH 109
+#define X509_R_CERT_ALREADY_IN_HASH_TABLE 110
+#define X509_R_PUBLIC_KEY_DECODE_ERROR 111
+#define X509_R_NOT_PKCS7_SIGNED_DATA 112
+#define X509_R_PUBLIC_KEY_ENCODE_ERROR 113
+#define X509_R_LOADING_CERT_DIR 114
+#define X509_R_WRONG_TYPE 115
+#define X509_R_UNKNOWN_PURPOSE_ID 116
+#define X509_R_NEWER_CRL_NOT_NEWER 117
+#define X509_R_UNKNOWN_TRUST_ID 118
+#define X509_R_KEY_TYPE_MISMATCH 120
+#define X509_R_UNKNOWN_KEY_TYPE 121
+#define X509_R_BAD_X509_FILETYPE 122
+#define X509_R_ISSUER_MISMATCH 123
+#define X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY 124
+#define X509_R_WRONG_LOOKUP_TYPE 125
+#define X509_R_CONTEXT_NOT_INITIALISED 126
+#define X509_R_CANT_CHECK_DH_KEY 127
+#define X509_R_NO_CERTIFICATES_INCLUDED 128
+#define X509_R_INVALID_FIELD_NAME 129
+#define X509_R_SHOULD_RETRY 130
+#define X509_R_NO_CRL_NUMBER 131
+#define X509_R_IDP_MISMATCH 132
+#define X509_R_LOADING_DEFAULTS 133
+#define X509_R_BAD_PKCS7_VERSION 134
+#define X509_R_CRL_ALREADY_DELTA 135
+#define X509_R_ERR_ASN1_LIB 136
+#define X509_R_AKID_MISMATCH 137
+#define X509_R_INVALID_BIT_STRING_BITS_LEFT 138
+
+#endif
diff --git a/src/include/openssl/x509_vfy.h b/src/include/openssl/x509_vfy.h
new file mode 100644
index 0000000..c65bfde
--- /dev/null
+++ b/src/include/openssl/x509_vfy.h
@@ -0,0 +1,607 @@
+/* crypto/x509/x509_vfy.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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>
+/* 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 <openssl/bio.h>
+#include <openssl/lhash.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if 0
+/* Outer object */
+typedef struct x509_hash_dir_st
+ {
+ int num_dirs;
+ char **dirs;
+ int *dirs_type;
+ int num_dirs_alloced;
+ } X509_HASH_DIR_CTX;
+#endif
+
+typedef struct x509_file_st
+ {
+ int num_paths; /* number of paths to files or directories */
+ int num_alloced;
+ char **paths; /* the list of paths or directories */
+ int *path_type;
+ } X509_CERT_FILE_CTX;
+
+/*******************************/
+/*
+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.
+*/
+
+#define X509_LU_RETRY -1
+#define X509_LU_FAIL 0
+#define X509_LU_X509 1
+#define X509_LU_CRL 2
+#define X509_LU_PKEY 3
+
+typedef struct x509_object_st
+ {
+ /* one of the above types */
+ int type;
+ union {
+ char *ptr;
+ X509 *x509;
+ X509_CRL *crl;
+ EVP_PKEY *pkey;
+ } data;
+ } X509_OBJECT;
+
+typedef struct x509_lookup_st X509_LOOKUP;
+
+DECLARE_STACK_OF(X509_LOOKUP)
+DECLARE_STACK_OF(X509_OBJECT)
+
+/* This is a static that defines the function interface */
+typedef 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,
+ unsigned char *bytes,int len,
+ X509_OBJECT *ret);
+ int (*get_by_alias)(X509_LOOKUP *ctx,int type,char *str,int len,
+ X509_OBJECT *ret);
+ } X509_LOOKUP_METHOD;
+
+typedef struct X509_VERIFY_PARAM_ID_st X509_VERIFY_PARAM_ID;
+
+/* This structure hold all parameters associated with a verify operation
+ * by including an X509_VERIFY_PARAM structure in related structures the
+ * parameters used can be customized
+ */
+
+typedef 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 */
+ STACK_OF(ASN1_OBJECT) *policies; /* Permissible policies */
+ X509_VERIFY_PARAM_ID *id; /* opaque ID data */
+ } X509_VERIFY_PARAM;
+
+DECLARE_STACK_OF(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 */
+ int cache; /* if true, stash any hits */
+ 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 */;
+
+OPENSSL_EXPORT int X509_STORE_set_depth(X509_STORE *store, int depth);
+
+#define X509_STORE_set_verify_cb_func(ctx,func) ((ctx)->verify_cb=(func))
+#define X509_STORE_set_verify_func(ctx,func) ((ctx)->verify=(func))
+
+/* This is the functions plus an instance of the local variables. */
+struct x509_lookup_st
+ {
+ int init; /* have we been started */
+ int skip; /* don't use us. */
+ X509_LOOKUP_METHOD *method; /* the functions */
+ char *method_data; /* method data */
+
+ X509_STORE *store_ctx; /* who owns us */
+ } /* X509_LOOKUP */;
+
+/* This is a used when verifying cert chains. Since the
+ * gathering of the cert chain can take some time (and have to be
+ * 'retried', this needs to be kept and passed around. */
+struct x509_store_ctx_st /* X509_STORE_CTX */
+ {
+ X509_STORE *ctx;
+ 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_CRL) *crls; /* set of CRLs passed in */
+
+ X509_VERIFY_PARAM *param;
+ void *other_ctx; /* Other info for use with get_issuer() */
+
+ /* 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 last_untrusted; /* index of last untrusted cert */
+ STACK_OF(X509) *chain; /* chain of X509s - built up and trusted */
+ X509_POLICY_TREE *tree; /* Valid policy tree */
+
+ 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 */;
+
+OPENSSL_EXPORT void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth);
+
+#define X509_STORE_CTX_set_app_data(ctx,data) \
+ X509_STORE_CTX_set_ex_data(ctx,0,data)
+#define X509_STORE_CTX_get_app_data(ctx) \
+ X509_STORE_CTX_get_ex_data(ctx,0)
+
+#define X509_L_FILE_LOAD 1
+#define X509_L_ADD_DIR 2
+
+#define X509_LOOKUP_load_file(x,name,type) \
+ X509_LOOKUP_ctrl((x),X509_L_FILE_LOAD,(name),(long)(type),NULL)
+
+#define X509_LOOKUP_add_dir(x,name,type) \
+ X509_LOOKUP_ctrl((x),X509_L_ADD_DIR,(name),(long)(type),NULL)
+
+#define X509_V_OK 0
+/* illegal error (for uninitialized values, to avoid X509_V_OK): 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
+
+/* Suite B mode algorithm violation */
+#define X509_V_ERR_SUITE_B_INVALID_VERSION 56
+#define X509_V_ERR_SUITE_B_INVALID_ALGORITHM 57
+#define X509_V_ERR_SUITE_B_INVALID_CURVE 58
+#define X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM 59
+#define X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED 60
+#define X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256 61
+
+/* Host, email and IP check errors */
+#define X509_V_ERR_HOSTNAME_MISMATCH 62
+#define X509_V_ERR_EMAIL_MISMATCH 63
+#define X509_V_ERR_IP_ADDRESS_MISMATCH 64
+
+/* The application is not happy */
+#define X509_V_ERR_APPLICATION_VERIFICATION 50
+
+/* Certificate verify flags */
+
+/* Send issuer+subject checks to verify_cb */
+#define X509_V_FLAG_CB_ISSUER_CHECK 0x1
+/* Use check time instead of current time */
+#define X509_V_FLAG_USE_CHECK_TIME 0x2
+/* Lookup CRLs */
+#define X509_V_FLAG_CRL_CHECK 0x4
+/* Lookup CRLs for whole chain */
+#define X509_V_FLAG_CRL_CHECK_ALL 0x8
+/* Ignore unhandled critical extensions */
+#define X509_V_FLAG_IGNORE_CRITICAL 0x10
+/* Disable workarounds for broken certificates */
+#define X509_V_FLAG_X509_STRICT 0x20
+/* Enable proxy certificate validation */
+#define X509_V_FLAG_ALLOW_PROXY_CERTS 0x40
+/* Enable policy checking */
+#define X509_V_FLAG_POLICY_CHECK 0x80
+/* Policy variable require-explicit-policy */
+#define X509_V_FLAG_EXPLICIT_POLICY 0x100
+/* Policy variable inhibit-any-policy */
+#define X509_V_FLAG_INHIBIT_ANY 0x200
+/* Policy variable inhibit-policy-mapping */
+#define X509_V_FLAG_INHIBIT_MAP 0x400
+/* Notify callback that policy is OK */
+#define X509_V_FLAG_NOTIFY_POLICY 0x800
+/* Extended CRL features such as indirect CRLs, alternate CRL signing keys */
+#define X509_V_FLAG_EXTENDED_CRL_SUPPORT 0x1000
+/* Delta CRL support */
+#define X509_V_FLAG_USE_DELTAS 0x2000
+/* Check selfsigned CA signature */
+#define X509_V_FLAG_CHECK_SS_SIGNATURE 0x4000
+/* Use trusted store first */
+#define X509_V_FLAG_TRUSTED_FIRST 0x8000
+/* Suite B 128 bit only mode: not normally used */
+#define X509_V_FLAG_SUITEB_128_LOS_ONLY 0x10000
+/* Suite B 192 bit only mode */
+#define X509_V_FLAG_SUITEB_192_LOS 0x20000
+/* Suite B 128 bit mode allowing 192 bit algorithms */
+#define X509_V_FLAG_SUITEB_128_LOS 0x30000
+
+/* Allow partial chains if at least one certificate is in trusted store */
+#define X509_V_FLAG_PARTIAL_CHAIN 0x80000
+
+#define X509_VP_FLAG_DEFAULT 0x1
+#define X509_VP_FLAG_OVERWRITE 0x2
+#define X509_VP_FLAG_RESET_FLAGS 0x4
+#define X509_VP_FLAG_LOCKED 0x8
+#define X509_VP_FLAG_ONCE 0x10
+
+/* Internal use: mask of policy related options */
+#define X509_V_FLAG_POLICY_MASK (X509_V_FLAG_POLICY_CHECK \
+ | X509_V_FLAG_EXPLICIT_POLICY \
+ | X509_V_FLAG_INHIBIT_ANY \
+ | X509_V_FLAG_INHIBIT_MAP)
+
+OPENSSL_EXPORT int X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, int type,
+ X509_NAME *name);
+OPENSSL_EXPORT X509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h,int type,X509_NAME *name);
+OPENSSL_EXPORT X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h, X509_OBJECT *x);
+OPENSSL_EXPORT void X509_OBJECT_up_ref_count(X509_OBJECT *a);
+OPENSSL_EXPORT void X509_OBJECT_free_contents(X509_OBJECT *a);
+OPENSSL_EXPORT X509_STORE *X509_STORE_new(void );
+OPENSSL_EXPORT void X509_STORE_free(X509_STORE *v);
+
+OPENSSL_EXPORT STACK_OF(X509)* X509_STORE_get1_certs(X509_STORE_CTX *st, X509_NAME *nm);
+OPENSSL_EXPORT STACK_OF(X509_CRL)* X509_STORE_get1_crls(X509_STORE_CTX *st, X509_NAME *nm);
+OPENSSL_EXPORT int X509_STORE_set_flags(X509_STORE *ctx, unsigned long flags);
+OPENSSL_EXPORT int X509_STORE_set_purpose(X509_STORE *ctx, int purpose);
+OPENSSL_EXPORT int X509_STORE_set_trust(X509_STORE *ctx, int trust);
+OPENSSL_EXPORT int X509_STORE_set1_param(X509_STORE *ctx, X509_VERIFY_PARAM *pm);
+
+OPENSSL_EXPORT void X509_STORE_set_verify_cb(X509_STORE *ctx,
+ int (*verify_cb)(int, X509_STORE_CTX *));
+
+OPENSSL_EXPORT void X509_STORE_set_lookup_crls_cb(X509_STORE *ctx,
+ STACK_OF(X509_CRL)* (*cb)(X509_STORE_CTX *ctx, X509_NAME *nm));
+
+OPENSSL_EXPORT X509_STORE_CTX *X509_STORE_CTX_new(void);
+
+OPENSSL_EXPORT int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x);
+
+OPENSSL_EXPORT void X509_STORE_CTX_free(X509_STORE_CTX *ctx);
+OPENSSL_EXPORT int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store,
+ X509 *x509, STACK_OF(X509) *chain);
+OPENSSL_EXPORT void X509_STORE_CTX_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *sk);
+OPENSSL_EXPORT void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx);
+
+OPENSSL_EXPORT X509_STORE *X509_STORE_CTX_get0_store(X509_STORE_CTX *ctx);
+
+OPENSSL_EXPORT X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m);
+
+OPENSSL_EXPORT X509_LOOKUP_METHOD *X509_LOOKUP_hash_dir(void);
+OPENSSL_EXPORT X509_LOOKUP_METHOD *X509_LOOKUP_file(void);
+
+OPENSSL_EXPORT int X509_STORE_add_cert(X509_STORE *ctx, X509 *x);
+OPENSSL_EXPORT int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x);
+
+OPENSSL_EXPORT int X509_STORE_get_by_subject(X509_STORE_CTX *vs,int type,X509_NAME *name,
+ X509_OBJECT *ret);
+
+OPENSSL_EXPORT int X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc,
+ long argl, char **ret);
+
+#ifndef OPENSSL_NO_STDIO
+OPENSSL_EXPORT int X509_load_cert_file(X509_LOOKUP *ctx, const char *file, int type);
+OPENSSL_EXPORT int X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type);
+OPENSSL_EXPORT int X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type);
+#endif
+
+
+OPENSSL_EXPORT X509_LOOKUP *X509_LOOKUP_new(X509_LOOKUP_METHOD *method);
+OPENSSL_EXPORT void X509_LOOKUP_free(X509_LOOKUP *ctx);
+OPENSSL_EXPORT int X509_LOOKUP_init(X509_LOOKUP *ctx);
+OPENSSL_EXPORT int X509_LOOKUP_by_subject(X509_LOOKUP *ctx, int type, X509_NAME *name,
+ X509_OBJECT *ret);
+OPENSSL_EXPORT int X509_LOOKUP_by_issuer_serial(X509_LOOKUP *ctx, int type, X509_NAME *name,
+ ASN1_INTEGER *serial, X509_OBJECT *ret);
+OPENSSL_EXPORT int X509_LOOKUP_by_fingerprint(X509_LOOKUP *ctx, int type,
+ unsigned char *bytes, int len, X509_OBJECT *ret);
+OPENSSL_EXPORT int X509_LOOKUP_by_alias(X509_LOOKUP *ctx, int type, char *str,
+ int len, X509_OBJECT *ret);
+OPENSSL_EXPORT int X509_LOOKUP_shutdown(X509_LOOKUP *ctx);
+
+#ifndef OPENSSL_NO_STDIO
+OPENSSL_EXPORT int X509_STORE_load_locations (X509_STORE *ctx,
+ const char *file, const char *dir);
+OPENSSL_EXPORT int X509_STORE_set_default_paths(X509_STORE *ctx);
+#endif
+
+OPENSSL_EXPORT 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);
+OPENSSL_EXPORT int X509_STORE_CTX_set_ex_data(X509_STORE_CTX *ctx,int idx,void *data);
+OPENSSL_EXPORT void * X509_STORE_CTX_get_ex_data(X509_STORE_CTX *ctx,int idx);
+OPENSSL_EXPORT int X509_STORE_CTX_get_error(X509_STORE_CTX *ctx);
+OPENSSL_EXPORT void X509_STORE_CTX_set_error(X509_STORE_CTX *ctx,int s);
+OPENSSL_EXPORT int X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx);
+OPENSSL_EXPORT X509 * X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx);
+OPENSSL_EXPORT X509 *X509_STORE_CTX_get0_current_issuer(X509_STORE_CTX *ctx);
+OPENSSL_EXPORT X509_CRL *X509_STORE_CTX_get0_current_crl(X509_STORE_CTX *ctx);
+OPENSSL_EXPORT X509_STORE_CTX *X509_STORE_CTX_get0_parent_ctx(X509_STORE_CTX *ctx);
+OPENSSL_EXPORT STACK_OF(X509) *X509_STORE_CTX_get_chain(X509_STORE_CTX *ctx);
+OPENSSL_EXPORT STACK_OF(X509) *X509_STORE_CTX_get1_chain(X509_STORE_CTX *ctx);
+OPENSSL_EXPORT void X509_STORE_CTX_set_cert(X509_STORE_CTX *c,X509 *x);
+OPENSSL_EXPORT void X509_STORE_CTX_set_chain(X509_STORE_CTX *c,STACK_OF(X509) *sk);
+OPENSSL_EXPORT void X509_STORE_CTX_set0_crls(X509_STORE_CTX *c,STACK_OF(X509_CRL) *sk);
+OPENSSL_EXPORT int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose);
+OPENSSL_EXPORT int X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust);
+OPENSSL_EXPORT int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose,
+ int purpose, int trust);
+OPENSSL_EXPORT void X509_STORE_CTX_set_flags(X509_STORE_CTX *ctx, unsigned long flags);
+OPENSSL_EXPORT void X509_STORE_CTX_set_time(X509_STORE_CTX *ctx, unsigned long flags,
+ time_t t);
+OPENSSL_EXPORT void X509_STORE_CTX_set_verify_cb(X509_STORE_CTX *ctx,
+ int (*verify_cb)(int, X509_STORE_CTX *));
+
+OPENSSL_EXPORT X509_POLICY_TREE *X509_STORE_CTX_get0_policy_tree(X509_STORE_CTX *ctx);
+OPENSSL_EXPORT int X509_STORE_CTX_get_explicit_policy(X509_STORE_CTX *ctx);
+
+OPENSSL_EXPORT X509_VERIFY_PARAM *X509_STORE_CTX_get0_param(X509_STORE_CTX *ctx);
+OPENSSL_EXPORT void X509_STORE_CTX_set0_param(X509_STORE_CTX *ctx, X509_VERIFY_PARAM *param);
+OPENSSL_EXPORT int X509_STORE_CTX_set_default(X509_STORE_CTX *ctx, const char *name);
+
+/* X509_VERIFY_PARAM functions */
+
+OPENSSL_EXPORT X509_VERIFY_PARAM *X509_VERIFY_PARAM_new(void);
+OPENSSL_EXPORT void X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *param);
+OPENSSL_EXPORT int X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *to,
+ const X509_VERIFY_PARAM *from);
+OPENSSL_EXPORT int X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM *to,
+ const X509_VERIFY_PARAM *from);
+OPENSSL_EXPORT int X509_VERIFY_PARAM_set1_name(X509_VERIFY_PARAM *param, const char *name);
+OPENSSL_EXPORT int X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM *param, unsigned long flags);
+OPENSSL_EXPORT int X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM *param,
+ unsigned long flags);
+OPENSSL_EXPORT unsigned long X509_VERIFY_PARAM_get_flags(X509_VERIFY_PARAM *param);
+OPENSSL_EXPORT int X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM *param, int purpose);
+OPENSSL_EXPORT int X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM *param, int trust);
+OPENSSL_EXPORT void X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM *param, int depth);
+OPENSSL_EXPORT void X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM *param, time_t t);
+OPENSSL_EXPORT int X509_VERIFY_PARAM_add0_policy(X509_VERIFY_PARAM *param,
+ ASN1_OBJECT *policy);
+OPENSSL_EXPORT int X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param,
+ STACK_OF(ASN1_OBJECT) *policies);
+
+OPENSSL_EXPORT int X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param,
+ const unsigned char *name, size_t namelen);
+OPENSSL_EXPORT void X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param,
+ unsigned int flags);
+OPENSSL_EXPORT int X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param,
+ const unsigned char *email, size_t emaillen);
+OPENSSL_EXPORT int X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param,
+ const unsigned char *ip, size_t iplen);
+OPENSSL_EXPORT int X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM *param, const char *ipasc);
+
+OPENSSL_EXPORT int X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM *param);
+OPENSSL_EXPORT const char *X509_VERIFY_PARAM_get0_name(const X509_VERIFY_PARAM *param);
+
+OPENSSL_EXPORT int X509_VERIFY_PARAM_add0_table(X509_VERIFY_PARAM *param);
+OPENSSL_EXPORT int X509_VERIFY_PARAM_get_count(void);
+OPENSSL_EXPORT const X509_VERIFY_PARAM *X509_VERIFY_PARAM_get0(int id);
+OPENSSL_EXPORT const X509_VERIFY_PARAM *X509_VERIFY_PARAM_lookup(const char *name);
+OPENSSL_EXPORT void X509_VERIFY_PARAM_table_cleanup(void);
+
+OPENSSL_EXPORT int X509_policy_check(X509_POLICY_TREE **ptree, int *pexplicit_policy,
+ STACK_OF(X509) *certs,
+ STACK_OF(ASN1_OBJECT) *policy_oids,
+ unsigned int flags);
+
+OPENSSL_EXPORT void X509_policy_tree_free(X509_POLICY_TREE *tree);
+
+OPENSSL_EXPORT int X509_policy_tree_level_count(const X509_POLICY_TREE *tree);
+OPENSSL_EXPORT X509_POLICY_LEVEL *
+ X509_policy_tree_get0_level(const X509_POLICY_TREE *tree, int i);
+
+OPENSSL_EXPORT STACK_OF(X509_POLICY_NODE) *
+ X509_policy_tree_get0_policies(const X509_POLICY_TREE *tree);
+
+OPENSSL_EXPORT STACK_OF(X509_POLICY_NODE) *
+ X509_policy_tree_get0_user_policies(const X509_POLICY_TREE *tree);
+
+OPENSSL_EXPORT int X509_policy_level_node_count(X509_POLICY_LEVEL *level);
+
+OPENSSL_EXPORT X509_POLICY_NODE *X509_policy_level_get0_node(X509_POLICY_LEVEL *level, int i);
+
+OPENSSL_EXPORT const ASN1_OBJECT *X509_policy_node_get0_policy(const X509_POLICY_NODE *node);
+
+OPENSSL_EXPORT STACK_OF(POLICYQUALINFO) *
+ X509_policy_node_get0_qualifiers(const X509_POLICY_NODE *node);
+OPENSSL_EXPORT const X509_POLICY_NODE *
+ X509_policy_node_get0_parent(const X509_POLICY_NODE *node);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff --git a/src/include/openssl/x509v3.h b/src/include/openssl/x509v3.h
new file mode 100644
index 0000000..c891022
--- /dev/null
+++ b/src/include/openssl/x509v3.h
@@ -0,0 +1,870 @@
+/* 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 <openssl/bio.h>
+#include <openssl/conf.h>
+#include <openssl/x509.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Forward reference */
+struct v3_ext_method;
+struct v3_ext_ctx;
+
+/* Useful typedefs */
+
+typedef void * (*X509V3_EXT_NEW)(void);
+typedef void (*X509V3_EXT_FREE)(void *);
+typedef void * (*X509V3_EXT_D2I)(void *, const unsigned char ** , long);
+typedef int (*X509V3_EXT_I2D)(void *, unsigned char **);
+typedef STACK_OF(CONF_VALUE) *
+ (*X509V3_EXT_I2V)(const struct v3_ext_method *method, void *ext,
+ STACK_OF(CONF_VALUE) *extlist);
+typedef void * (*X509V3_EXT_V2I)(const struct v3_ext_method *method,
+ struct v3_ext_ctx *ctx,
+ STACK_OF(CONF_VALUE) *values);
+typedef char * (*X509V3_EXT_I2S)(const struct v3_ext_method *method, void *ext);
+typedef void * (*X509V3_EXT_S2I)(const struct v3_ext_method *method,
+ struct v3_ext_ctx *ctx, const char *str);
+typedef int (*X509V3_EXT_I2R)(const struct v3_ext_method *method, void *ext,
+ BIO *out, int indent);
+typedef void * (*X509V3_EXT_R2I)(const struct v3_ext_method *method,
+ struct v3_ext_ctx *ctx, const char *str);
+
+/* V3 extension structure */
+
+struct v3_ext_method {
+int ext_nid;
+int ext_flags;
+/* If this is set the following four fields are ignored */
+ASN1_ITEM_EXP *it;
+/* Old style ASN1 calls */
+X509V3_EXT_NEW ext_new;
+X509V3_EXT_FREE ext_free;
+X509V3_EXT_D2I d2i;
+X509V3_EXT_I2D i2d;
+
+/* The following pair is used for string extensions */
+X509V3_EXT_I2S i2s;
+X509V3_EXT_S2I s2i;
+
+/* The following pair is used for multi-valued extensions */
+X509V3_EXT_I2V i2v;
+X509V3_EXT_V2I v2i;
+
+/* The following are used for raw extensions */
+X509V3_EXT_I2R i2r;
+X509V3_EXT_R2I r2i;
+
+void *usr_data; /* Any extension specific data */
+};
+
+typedef struct X509V3_CONF_METHOD_st {
+char * (*get_string)(void *db, char *section, char *value);
+STACK_OF(CONF_VALUE) * (*get_section)(void *db, 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;
+const 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_TYPE *x400Address;
+ X509_NAME *directoryName;
+ EDIPARTYNAME *ediPartyName;
+ ASN1_IA5STRING *uniformResourceIdentifier;
+ ASN1_OCTET_STRING *iPAddress;
+ ASN1_OBJECT *registeredID;
+
+ /* Old names */
+ ASN1_OCTET_STRING *ip; /* iPAddress */
+ X509_NAME *dirn; /* dirn */
+ ASN1_IA5STRING *ia5;/* rfc822Name, dNSName, uniformResourceIdentifier */
+ ASN1_OBJECT *rid; /* registeredID */
+ ASN1_TYPE *other; /* x400Address */
+} d;
+} GENERAL_NAME;
+
+typedef STACK_OF(GENERAL_NAME) GENERAL_NAMES;
+
+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)
+DECLARE_ASN1_SET_OF(GENERAL_NAME)
+
+DECLARE_STACK_OF(ACCESS_DESCRIPTION)
+DECLARE_ASN1_SET_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)
+DECLARE_ASN1_SET_OF(DIST_POINT)
+
+struct AUTHORITY_KEYID_st {
+ASN1_OCTET_STRING *keyid;
+GENERAL_NAMES *issuer;
+ASN1_INTEGER *serial;
+};
+
+/* Strong extranet structures */
+
+typedef struct SXNET_ID_st {
+ ASN1_INTEGER *zone;
+ ASN1_OCTET_STRING *user;
+} SXNETID;
+
+DECLARE_STACK_OF(SXNETID)
+DECLARE_ASN1_SET_OF(SXNETID)
+
+typedef struct SXNET_st {
+ ASN1_INTEGER *version;
+ STACK_OF(SXNETID) *ids;
+} SXNET;
+
+typedef struct NOTICEREF_st {
+ ASN1_STRING *organization;
+ STACK_OF(ASN1_INTEGER) *noticenos;
+} NOTICEREF;
+
+typedef struct USERNOTICE_st {
+ NOTICEREF *noticeref;
+ ASN1_STRING *exptext;
+} USERNOTICE;
+
+typedef struct POLICYQUALINFO_st {
+ ASN1_OBJECT *pqualid;
+ union {
+ ASN1_IA5STRING *cpsuri;
+ USERNOTICE *usernotice;
+ ASN1_TYPE *other;
+ } d;
+} POLICYQUALINFO;
+
+DECLARE_STACK_OF(POLICYQUALINFO)
+DECLARE_ASN1_SET_OF(POLICYQUALINFO)
+
+typedef struct POLICYINFO_st {
+ ASN1_OBJECT *policyid;
+ STACK_OF(POLICYQUALINFO) *qualifiers;
+} POLICYINFO;
+
+typedef STACK_OF(POLICYINFO) CERTIFICATEPOLICIES;
+
+DECLARE_STACK_OF(POLICYINFO)
+DECLARE_ASN1_SET_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;
+
+/* Proxy certificate structures, see RFC 3820 */
+typedef struct PROXY_POLICY_st
+ {
+ ASN1_OBJECT *policyLanguage;
+ ASN1_OCTET_STRING *policy;
+ } PROXY_POLICY;
+
+typedef struct PROXY_CERT_INFO_EXTENSION_st
+ {
+ ASN1_INTEGER *pcPathLengthConstraint;
+ PROXY_POLICY *proxyPolicy;
+ } PROXY_CERT_INFO_EXTENSION;
+
+DECLARE_ASN1_FUNCTIONS(PROXY_POLICY)
+DECLARE_ASN1_FUNCTIONS(PROXY_CERT_INFO_EXTENSION)
+
+struct ISSUING_DIST_POINT_st
+ {
+ DIST_POINT_NAME *distpoint;
+ int onlyuser;
+ int onlyCA;
+ ASN1_BIT_STRING *onlysomereasons;
+ int indirectCRL;
+ int onlyattr;
+ };
+
+/* Values in idp_flags field */
+/* IDP present */
+#define IDP_PRESENT 0x1
+/* IDP values inconsistent */
+#define IDP_INVALID 0x2
+/* onlyuser true */
+#define IDP_ONLYUSER 0x4
+/* onlyCA true */
+#define IDP_ONLYCA 0x8
+/* onlyattr true */
+#define IDP_ONLYATTR 0x10
+/* indirectCRL true */
+#define IDP_INDIRECT 0x20
+/* onlysomereasons present */
+#define IDP_REASONS 0x40
+
+#define X509V3_conf_err(val) ERR_add_error_data(6, "section:", val->section, \
+",name:", val->name, ",value:", val->value);
+
+#define X509V3_set_ctx_test(ctx) \
+ X509V3_set_ctx(ctx, NULL, NULL, NULL, NULL, CTX_TEST)
+#define X509V3_set_ctx_nodb(ctx) (ctx)->db = NULL;
+
+#define EXT_BITSTRING(nid, table) { nid, 0, ASN1_ITEM_ref(ASN1_BIT_STRING), \
+ 0,0,0,0, \
+ 0,0, \
+ (X509V3_EXT_I2V)i2v_ASN1_BIT_STRING, \
+ (X509V3_EXT_V2I)v2i_ASN1_BIT_STRING, \
+ NULL, NULL, \
+ (void *)table}
+
+#define EXT_IA5STRING(nid) { nid, 0, ASN1_ITEM_ref(ASN1_IA5STRING), \
+ 0,0,0,0, \
+ (X509V3_EXT_I2S)i2s_ASN1_IA5STRING, \
+ (X509V3_EXT_S2I)s2i_ASN1_IA5STRING, \
+ 0,0,0,0, \
+ NULL}
+
+#define EXT_END { -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+
+
+/* X509_PURPOSE stuff */
+
+#define EXFLAG_BCONS 0x1
+#define EXFLAG_KUSAGE 0x2
+#define EXFLAG_XKUSAGE 0x4
+#define EXFLAG_NSCERT 0x8
+
+#define EXFLAG_CA 0x10
+/* Really self issued not necessarily self signed */
+#define EXFLAG_SI 0x20
+#define EXFLAG_V1 0x40
+#define EXFLAG_INVALID 0x80
+#define EXFLAG_SET 0x100
+#define EXFLAG_CRITICAL 0x200
+#define EXFLAG_PROXY 0x400
+
+#define EXFLAG_INVALID_POLICY 0x800
+#define EXFLAG_FRESHEST 0x1000
+/* Self signed */
+#define EXFLAG_SS 0x2000
+
+#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)
+
+DECLARE_ASN1_FUNCTIONS(BASIC_CONSTRAINTS)
+
+DECLARE_ASN1_FUNCTIONS(SXNET)
+DECLARE_ASN1_FUNCTIONS(SXNETID)
+
+int SXNET_add_id_asc(SXNET **psx, char *zone, char *user, int userlen);
+int SXNET_add_id_ulong(SXNET **psx, unsigned long lzone, char *user, int userlen);
+int SXNET_add_id_INTEGER(SXNET **psx, ASN1_INTEGER *izone, char *user, int userlen);
+
+ASN1_OCTET_STRING *SXNET_get_id_asc(SXNET *sx, char *zone);
+ASN1_OCTET_STRING *SXNET_get_id_ulong(SXNET *sx, unsigned long lzone);
+ASN1_OCTET_STRING *SXNET_get_id_INTEGER(SXNET *sx, ASN1_INTEGER *zone);
+
+DECLARE_ASN1_FUNCTIONS(AUTHORITY_KEYID)
+
+DECLARE_ASN1_FUNCTIONS(PKEY_USAGE_PERIOD)
+
+DECLARE_ASN1_FUNCTIONS(GENERAL_NAME)
+OPENSSL_EXPORT GENERAL_NAME *GENERAL_NAME_dup(GENERAL_NAME *a);
+OPENSSL_EXPORT int GENERAL_NAME_cmp(GENERAL_NAME *a, GENERAL_NAME *b);
+
+
+
+OPENSSL_EXPORT ASN1_BIT_STRING *v2i_ASN1_BIT_STRING(X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
+OPENSSL_EXPORT STACK_OF(CONF_VALUE) *i2v_ASN1_BIT_STRING(X509V3_EXT_METHOD *method,
+ ASN1_BIT_STRING *bits,
+ STACK_OF(CONF_VALUE) *extlist);
+
+OPENSSL_EXPORT STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method, GENERAL_NAME *gen, STACK_OF(CONF_VALUE) *ret);
+OPENSSL_EXPORT int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen);
+
+DECLARE_ASN1_FUNCTIONS(GENERAL_NAMES)
+
+OPENSSL_EXPORT STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES(X509V3_EXT_METHOD *method,
+ GENERAL_NAMES *gen, STACK_OF(CONF_VALUE) *extlist);
+OPENSSL_EXPORT GENERAL_NAMES *v2i_GENERAL_NAMES(const X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
+
+DECLARE_ASN1_FUNCTIONS(OTHERNAME)
+DECLARE_ASN1_FUNCTIONS(EDIPARTYNAME)
+OPENSSL_EXPORT int OTHERNAME_cmp(OTHERNAME *a, OTHERNAME *b);
+OPENSSL_EXPORT void GENERAL_NAME_set0_value(GENERAL_NAME *a, int type, void *value);
+OPENSSL_EXPORT void *GENERAL_NAME_get0_value(GENERAL_NAME *a, int *ptype);
+OPENSSL_EXPORT int GENERAL_NAME_set0_othername(GENERAL_NAME *gen,
+ ASN1_OBJECT *oid, ASN1_TYPE *value);
+OPENSSL_EXPORT int GENERAL_NAME_get0_otherName(GENERAL_NAME *gen,
+ ASN1_OBJECT **poid, ASN1_TYPE **pvalue);
+
+OPENSSL_EXPORT char *i2s_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method, ASN1_OCTET_STRING *ia5);
+OPENSSL_EXPORT ASN1_OCTET_STRING *s2i_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, char *str);
+
+DECLARE_ASN1_FUNCTIONS(EXTENDED_KEY_USAGE)
+OPENSSL_EXPORT int i2a_ACCESS_DESCRIPTION(BIO *bp, ACCESS_DESCRIPTION* a);
+
+DECLARE_ASN1_FUNCTIONS(CERTIFICATEPOLICIES)
+DECLARE_ASN1_FUNCTIONS(POLICYINFO)
+DECLARE_ASN1_FUNCTIONS(POLICYQUALINFO)
+DECLARE_ASN1_FUNCTIONS(USERNOTICE)
+DECLARE_ASN1_FUNCTIONS(NOTICEREF)
+
+DECLARE_ASN1_FUNCTIONS(CRL_DIST_POINTS)
+DECLARE_ASN1_FUNCTIONS(DIST_POINT)
+DECLARE_ASN1_FUNCTIONS(DIST_POINT_NAME)
+DECLARE_ASN1_FUNCTIONS(ISSUING_DIST_POINT)
+
+OPENSSL_EXPORT int DIST_POINT_set_dpname(DIST_POINT_NAME *dpn, X509_NAME *iname);
+
+OPENSSL_EXPORT int NAME_CONSTRAINTS_check(X509 *x, NAME_CONSTRAINTS *nc);
+
+DECLARE_ASN1_FUNCTIONS(ACCESS_DESCRIPTION)
+DECLARE_ASN1_FUNCTIONS(AUTHORITY_INFO_ACCESS)
+
+DECLARE_ASN1_ITEM(POLICY_MAPPING)
+DECLARE_ASN1_ALLOC_FUNCTIONS(POLICY_MAPPING)
+DECLARE_ASN1_ITEM(POLICY_MAPPINGS)
+
+DECLARE_ASN1_ITEM(GENERAL_SUBTREE)
+DECLARE_ASN1_ALLOC_FUNCTIONS(GENERAL_SUBTREE)
+
+DECLARE_ASN1_ITEM(NAME_CONSTRAINTS)
+DECLARE_ASN1_ALLOC_FUNCTIONS(NAME_CONSTRAINTS)
+
+DECLARE_ASN1_ALLOC_FUNCTIONS(POLICY_CONSTRAINTS)
+DECLARE_ASN1_ITEM(POLICY_CONSTRAINTS)
+
+OPENSSL_EXPORT GENERAL_NAME *a2i_GENERAL_NAME(GENERAL_NAME *out,
+ const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
+ int gen_type, char *value, int is_nc);
+
+OPENSSL_EXPORT GENERAL_NAME *v2i_GENERAL_NAME(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
+ CONF_VALUE *cnf);
+OPENSSL_EXPORT GENERAL_NAME *v2i_GENERAL_NAME_ex(GENERAL_NAME *out,
+ const X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, CONF_VALUE *cnf, int is_nc);
+OPENSSL_EXPORT void X509V3_conf_free(CONF_VALUE *val);
+
+OPENSSL_EXPORT X509_EXTENSION *X509V3_EXT_nconf_nid(CONF *conf, X509V3_CTX *ctx, int ext_nid, char *value);
+OPENSSL_EXPORT X509_EXTENSION *X509V3_EXT_nconf(CONF *conf, X509V3_CTX *ctx, char *name, char *value);
+OPENSSL_EXPORT int X509V3_EXT_add_nconf_sk(CONF *conf, X509V3_CTX *ctx, char *section, STACK_OF(X509_EXTENSION) **sk);
+OPENSSL_EXPORT int X509V3_EXT_add_nconf(CONF *conf, X509V3_CTX *ctx, char *section, X509 *cert);
+OPENSSL_EXPORT int X509V3_EXT_REQ_add_nconf(CONF *conf, X509V3_CTX *ctx, char *section, X509_REQ *req);
+OPENSSL_EXPORT int X509V3_EXT_CRL_add_nconf(CONF *conf, X509V3_CTX *ctx, char *section, X509_CRL *crl);
+
+OPENSSL_EXPORT X509_EXTENSION *X509V3_EXT_conf_nid(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx,
+ int ext_nid, char *value);
+OPENSSL_EXPORT X509_EXTENSION *X509V3_EXT_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx,
+ char *name, char *value);
+OPENSSL_EXPORT int X509V3_EXT_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx,
+ char *section, X509 *cert);
+OPENSSL_EXPORT int X509V3_EXT_REQ_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx,
+ char *section, X509_REQ *req);
+OPENSSL_EXPORT int X509V3_EXT_CRL_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx,
+ char *section, X509_CRL *crl);
+
+OPENSSL_EXPORT int X509V3_add_value_bool_nf(char *name, int asn1_bool,
+ STACK_OF(CONF_VALUE) **extlist);
+OPENSSL_EXPORT int X509V3_get_value_bool(CONF_VALUE *value, int *asn1_bool);
+OPENSSL_EXPORT int X509V3_get_value_int(CONF_VALUE *value, ASN1_INTEGER **aint);
+OPENSSL_EXPORT void X509V3_set_nconf(X509V3_CTX *ctx, CONF *conf);
+OPENSSL_EXPORT void X509V3_set_conf_lhash(X509V3_CTX *ctx, LHASH_OF(CONF_VALUE) *lhash);
+
+OPENSSL_EXPORT char * X509V3_get_string(X509V3_CTX *ctx, char *name, char *section);
+OPENSSL_EXPORT STACK_OF(CONF_VALUE) * X509V3_get_section(X509V3_CTX *ctx, char *section);
+OPENSSL_EXPORT void X509V3_string_free(X509V3_CTX *ctx, char *str);
+OPENSSL_EXPORT void X509V3_section_free( X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *section);
+OPENSSL_EXPORT void X509V3_set_ctx(X509V3_CTX *ctx, X509 *issuer, X509 *subject,
+ X509_REQ *req, X509_CRL *crl, int flags);
+
+OPENSSL_EXPORT int X509V3_add_value(const char *name, const char *value,
+ STACK_OF(CONF_VALUE) **extlist);
+OPENSSL_EXPORT int X509V3_add_value_uchar(const char *name, const unsigned char *value,
+ STACK_OF(CONF_VALUE) **extlist);
+OPENSSL_EXPORT int X509V3_add_value_bool(const char *name, int asn1_bool,
+ STACK_OF(CONF_VALUE) **extlist);
+OPENSSL_EXPORT int X509V3_add_value_int(const char *name, ASN1_INTEGER *aint,
+ STACK_OF(CONF_VALUE) **extlist);
+OPENSSL_EXPORT char * i2s_ASN1_INTEGER(X509V3_EXT_METHOD *meth, ASN1_INTEGER *aint);
+OPENSSL_EXPORT ASN1_INTEGER * s2i_ASN1_INTEGER(X509V3_EXT_METHOD *meth, char *value);
+OPENSSL_EXPORT char * i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *meth, ASN1_ENUMERATED *aint);
+OPENSSL_EXPORT char * i2s_ASN1_ENUMERATED_TABLE(X509V3_EXT_METHOD *meth, ASN1_ENUMERATED *aint);
+OPENSSL_EXPORT int X509V3_EXT_add(X509V3_EXT_METHOD *ext);
+OPENSSL_EXPORT int X509V3_EXT_add_list(X509V3_EXT_METHOD *extlist);
+OPENSSL_EXPORT int X509V3_EXT_add_alias(int nid_to, int nid_from);
+OPENSSL_EXPORT void X509V3_EXT_cleanup(void);
+
+OPENSSL_EXPORT const X509V3_EXT_METHOD *X509V3_EXT_get(X509_EXTENSION *ext);
+OPENSSL_EXPORT const X509V3_EXT_METHOD *X509V3_EXT_get_nid(int nid);
+OPENSSL_EXPORT int X509V3_add_standard_extensions(void);
+OPENSSL_EXPORT STACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line);
+OPENSSL_EXPORT void *X509V3_EXT_d2i(X509_EXTENSION *ext);
+OPENSSL_EXPORT void *X509V3_get_d2i(STACK_OF(X509_EXTENSION) *x, int nid, int *crit, int *idx);
+
+
+OPENSSL_EXPORT X509_EXTENSION *X509V3_EXT_i2d(int ext_nid, int crit, void *ext_struc);
+OPENSSL_EXPORT 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);
+int name_cmp(const char *name, const char *cmp);
+
+OPENSSL_EXPORT void X509V3_EXT_val_prn(BIO *out, STACK_OF(CONF_VALUE) *val, int indent,
+ int ml);
+OPENSSL_EXPORT int X509V3_EXT_print(BIO *out, X509_EXTENSION *ext, unsigned long flag, int indent);
+OPENSSL_EXPORT int X509V3_EXT_print_fp(FILE *out, X509_EXTENSION *ext, int flag, int indent);
+
+OPENSSL_EXPORT int X509V3_extensions_print(BIO *out, const char *title, STACK_OF(X509_EXTENSION) *exts, unsigned long flag, int indent);
+
+OPENSSL_EXPORT int X509_check_ca(X509 *x);
+OPENSSL_EXPORT int X509_check_purpose(X509 *x, int id, int ca);
+OPENSSL_EXPORT int X509_supported_extension(X509_EXTENSION *ex);
+OPENSSL_EXPORT int X509_PURPOSE_set(int *p, int purpose);
+OPENSSL_EXPORT int X509_check_issued(X509 *issuer, X509 *subject);
+OPENSSL_EXPORT int X509_check_akid(X509 *issuer, AUTHORITY_KEYID *akid);
+OPENSSL_EXPORT int X509_PURPOSE_get_count(void);
+OPENSSL_EXPORT X509_PURPOSE * X509_PURPOSE_get0(int idx);
+OPENSSL_EXPORT int X509_PURPOSE_get_by_sname(char *sname);
+OPENSSL_EXPORT int X509_PURPOSE_get_by_id(int id);
+OPENSSL_EXPORT int X509_PURPOSE_add(int id, int trust, int flags,
+ int (*ck)(const X509_PURPOSE *, const X509 *, int),
+ char *name, char *sname, void *arg);
+OPENSSL_EXPORT char *X509_PURPOSE_get0_name(X509_PURPOSE *xp);
+OPENSSL_EXPORT char *X509_PURPOSE_get0_sname(X509_PURPOSE *xp);
+OPENSSL_EXPORT int X509_PURPOSE_get_trust(X509_PURPOSE *xp);
+OPENSSL_EXPORT void X509_PURPOSE_cleanup(void);
+OPENSSL_EXPORT int X509_PURPOSE_get_id(X509_PURPOSE *);
+
+OPENSSL_EXPORT STACK_OF(OPENSSL_STRING) *X509_get1_email(X509 *x);
+OPENSSL_EXPORT STACK_OF(OPENSSL_STRING) *X509_REQ_get1_email(X509_REQ *x);
+OPENSSL_EXPORT void X509_email_free(STACK_OF(OPENSSL_STRING) *sk);
+OPENSSL_EXPORT 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
+/*
+ * 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
+
+OPENSSL_EXPORT int X509_check_host(X509 *x, const unsigned char *chk, size_t chklen,
+ unsigned int flags);
+OPENSSL_EXPORT int X509_check_email(X509 *x, const unsigned char *chk, size_t chklen,
+ unsigned int flags);
+OPENSSL_EXPORT int X509_check_ip(X509 *x, const unsigned char *chk, size_t chklen,
+ unsigned int flags);
+OPENSSL_EXPORT int X509_check_ip_asc(X509 *x, const char *ipasc, unsigned int flags);
+
+OPENSSL_EXPORT ASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc);
+OPENSSL_EXPORT ASN1_OCTET_STRING *a2i_IPADDRESS_NC(const char *ipasc);
+OPENSSL_EXPORT int a2i_ipadd(unsigned char *ipout, const char *ipasc);
+OPENSSL_EXPORT int X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE)*dn_sk,
+ unsigned long chtype);
+
+OPENSSL_EXPORT void X509_POLICY_NODE_print(BIO *out, X509_POLICY_NODE *node, int indent);
+DECLARE_STACK_OF(X509_POLICY_NODE)
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_X509V3_strings(void);
+
+
+#ifdef __cplusplus
+}
+#endif
+#define X509V3_F_do_ext_i2d 100
+#define X509V3_F_v2i_AUTHORITY_KEYID 101
+#define X509V3_F_X509V3_parse_list 102
+#define X509V3_F_SXNET_add_id_asc 103
+#define X509V3_F_SXNET_get_id_ulong 104
+#define X509V3_F_v2i_AUTHORITY_INFO_ACCESS 105
+#define X509V3_F_X509V3_EXT_add 106
+#define X509V3_F_i2s_ASN1_INTEGER 107
+#define X509V3_F_s2i_ASN1_OCTET_STRING 108
+#define X509V3_F_copy_issuer 109
+#define X509V3_F_v2i_subject_alt 110
+#define X509V3_F_copy_email 111
+#define X509V3_F_X509V3_EXT_i2d 112
+#define X509V3_F_v2i_crld 113
+#define X509V3_F_policy_section 114
+#define X509V3_F_a2i_GENERAL_NAME 115
+#define X509V3_F_hex_to_string 116
+#define X509V3_F_i2s_ASN1_IA5STRING 117
+#define X509V3_F_string_to_hex 118
+#define X509V3_F_v3_generic_extension 119
+#define X509V3_F_X509V3_get_section 120
+#define X509V3_F_s2i_skey_id 121
+#define X509V3_F_nref_nos 122
+#define X509V3_F_X509V3_get_value_bool 123
+#define X509V3_F_v2i_NAME_CONSTRAINTS 124
+#define X509V3_F_v2i_POLICY_MAPPINGS 125
+#define X509V3_F_v2i_GENERAL_NAMES 126
+#define X509V3_F_do_dirname 127
+#define X509V3_F_v2i_ASN1_BIT_STRING 128
+#define X509V3_F_SXNET_add_id_ulong 129
+#define X509V3_F_X509V3_EXT_add_alias 130
+#define X509V3_F_X509V3_add1_i2d 131
+#define X509V3_F_r2i_pci 132
+#define X509V3_F_X509V3_get_string 133
+#define X509V3_F_gnames_from_sectname 134
+#define X509V3_F_r2i_certpol 135
+#define X509V3_F_X509V3_add_value 136
+#define X509V3_F_s2i_ASN1_INTEGER 137
+#define X509V3_F_v2i_issuer_alt 138
+#define X509V3_F_v2i_GENERAL_NAME_ex 139
+#define X509V3_F_X509V3_EXT_nconf 140
+#define X509V3_F_v2i_BASIC_CONSTRAINTS 141
+#define X509V3_F_process_pci_value 142
+#define X509V3_F_notice_section 143
+#define X509V3_F_X509_PURPOSE_set 144
+#define X509V3_F_do_ext_nconf 145
+#define X509V3_F_i2s_ASN1_ENUMERATED 146
+#define X509V3_F_s2i_ASN1_IA5STRING 147
+#define X509V3_F_v2i_POLICY_CONSTRAINTS 148
+#define X509V3_F_v2i_EXTENDED_KEY_USAGE 149
+#define X509V3_F_SXNET_get_id_asc 150
+#define X509V3_F_set_dist_point_name 151
+#define X509V3_F_v2i_idp 152
+#define X509V3_F_X509_PURPOSE_add 153
+#define X509V3_F_SXNET_add_id_INTEGER 154
+#define X509V3_F_i2v_AUTHORITY_INFO_ACCESS 155
+#define X509V3_F_X509V3_EXT_free 156
+#define X509V3_R_INVALID_BOOLEAN_STRING 100
+#define X509V3_R_POLICY_SYNTAX_NOT_CURRENTLY_SUPPORTED 101
+#define X509V3_R_INVALID_NAME 102
+#define X509V3_R_OPERATION_NOT_DEFINED 103
+#define X509V3_R_POLICY_PATH_LENGTH 104
+#define X509V3_R_INVALID_PROXY_POLICY_SETTING 105
+#define X509V3_R_INVALID_ASRANGE 106
+#define X509V3_R_ERROR_CREATING_EXTENSION 107
+#define X509V3_R_ISSUER_DECODE_ERROR 108
+#define X509V3_R_OTHERNAME_ERROR 109
+#define X509V3_R_ILLEGAL_HEX_DIGIT 110
+#define X509V3_R_NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED 111
+#define X509V3_R_USER_TOO_LONG 112
+#define X509V3_R_INVALID_INHERITANCE 113
+#define X509V3_R_INVALID_SAFI 114
+#define X509V3_R_INVALID_NULL_VALUE 115
+#define X509V3_R_NO_SUBJECT_DETAILS 116
+#define X509V3_R_BAD_OBJECT 117
+#define X509V3_R_DIRNAME_ERROR 118
+#define X509V3_R_UNKNOWN_BIT_STRING_ARGUMENT 119
+#define X509V3_R_INVALID_EXTENSION_STRING 120
+#define X509V3_R_NEED_ORGANIZATION_AND_NUMBERS 121
+#define X509V3_R_BN_TO_ASN1_INTEGER_ERROR 122
+#define X509V3_R_INVALID_OPTION 123
+#define X509V3_R_UNABLE_TO_GET_ISSUER_DETAILS 124
+#define X509V3_R_INVALID_POLICY_IDENTIFIER 125
+#define X509V3_R_INVALID_PURPOSE 126
+#define X509V3_R_UNKNOWN_EXTENSION 127
+#define X509V3_R_NO_ISSUER_CERTIFICATE 128
+#define X509V3_R_BN_DEC2BN_ERROR 129
+#define X509V3_R_EXPECTED_A_SECTION_NAME 130
+#define X509V3_R_POLICY_PATH_LENGTH_ALREADY_DEFINED 131
+#define X509V3_R_MISSING_VALUE 132
+#define X509V3_R_SECTION_NOT_FOUND 133
+#define X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED 134
+#define X509V3_R_POLICY_LANGUAGE_ALREADY_DEFINED 135
+#define X509V3_R_ILLEGAL_EMPTY_EXTENSION 136
+#define X509V3_R_NO_POLICY_IDENTIFIER 137
+#define X509V3_R_NO_ISSUER_DETAILS 138
+#define X509V3_R_NO_CONFIG_DATABASE 139
+#define X509V3_R_INCORRECT_POLICY_SYNTAX_TAG 140
+#define X509V3_R_INVALID_SECTION 141
+#define X509V3_R_INVALID_IPADDRESS 142
+#define X509V3_R_EXTENSION_VALUE_ERROR 143
+#define X509V3_R_UNABLE_TO_GET_ISSUER_KEYID 144
+#define X509V3_R_INVALID_NULL_ARGUMENT 145
+#define X509V3_R_ERROR_IN_EXTENSION 146
+#define X509V3_R_INVALID_NULL_NAME 147
+#define X509V3_R_BAD_IP_ADDRESS 148
+#define X509V3_R_UNSUPPORTED_OPTION 149
+#define X509V3_R_POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY 150
+#define X509V3_R_EXTENSION_EXISTS 151
+#define X509V3_R_UNKNOWN_OPTION 152
+#define X509V3_R_ERROR_CONVERTING_ZONE 153
+#define X509V3_R_NO_PUBLIC_KEY 154
+#define X509V3_R_INVALID_MULTIPLE_RDNS 155
+#define X509V3_R_INVALID_SYNTAX 156
+#define X509V3_R_UNKNOWN_EXTENSION_NAME 157
+#define X509V3_R_ODD_NUMBER_OF_DIGITS 158
+#define X509V3_R_DISTPOINT_ALREADY_SET 159
+#define X509V3_R_UNSUPPORTED_TYPE 160
+#define X509V3_R_EXTENSION_NAME_ERROR 161
+#define X509V3_R_INVALID_NUMBERS 162
+#define X509V3_R_INVALID_NUMBER 163
+#define X509V3_R_INVALID_OBJECT_IDENTIFIER 164
+#define X509V3_R_DUPLICATE_ZONE_ID 165
+#define X509V3_R_EXTENSION_NOT_FOUND 166
+#define X509V3_R_INVALID_ASNUMBER 167
+#define X509V3_R_CANNOT_FIND_FREE_FUNCTION 168
+
+#endif
diff --git a/src/ssl/CMakeLists.txt b/src/ssl/CMakeLists.txt
new file mode 100644
index 0000000..91bd5ea
--- /dev/null
+++ b/src/ssl/CMakeLists.txt
@@ -0,0 +1,45 @@
+include_directories(. .. ../include)
+
+add_subdirectory(pqueue)
+
+add_library(
+ ssl
+
+ d1_both.c
+ d1_clnt.c
+ d1_lib.c
+ d1_meth.c
+ d1_pkt.c
+ d1_srtp.c
+ d1_srvr.c
+ s3_both.c
+ s3_clnt.c
+ s3_enc.c
+ s3_lib.c
+ s3_meth.c
+ s3_pkt.c
+ s3_srvr.c
+ ssl_algs.c
+ ssl_asn1.c
+ ssl_cert.c
+ ssl_ciph.c
+ ssl_error.c
+ ssl_lib.c
+ ssl_rsa.c
+ ssl_sess.c
+ ssl_stat.c
+ ssl_txt.c
+ t1_enc.c
+ t1_lib.c
+ t1_reneg.c
+
+ $<TARGET_OBJECTS:pqueue>
+)
+
+add_executable(
+ ssl_test
+
+ ssl_test.c
+)
+
+target_link_libraries(ssl_test ssl crypto)
diff --git a/src/ssl/d1_both.c b/src/ssl/d1_both.c
new file mode 100644
index 0000000..5edc93f
--- /dev/null
+++ b/src/ssl/d1_both.c
@@ -0,0 +1,1173 @@
+/*
+ * 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 <assert.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <openssl/buf.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/rand.h>
+#include <openssl/x509.h>
+
+#include "ssl_locl.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; \
+ 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 uint8_t bitmask_start_values[] = {0xff, 0xfe, 0xfc, 0xf8,
+ 0xf0, 0xe0, 0xc0, 0x80};
+static const uint8_t bitmask_end_values[] = {0xff, 0x01, 0x03, 0x07,
+ 0x0f, 0x1f, 0x3f, 0x7f};
+
+/* TODO(davidben): 28 comes from the size of IP + UDP header. Is this reasonable
+ * for these values? Notably, why is kMinMTU a function of the transport
+ * protocol's overhead rather than, say, what's needed to hold a minimally-sized
+ * handshake fragment plus protocol overhead. */
+
+/* kMinMTU is the minimum acceptable MTU value. */
+static const unsigned int kMinMTU = 256 - 28;
+
+/* kDefaultMTU is the default MTU value to use if neither the user nor
+ * the underlying BIO supplies one. */
+static const unsigned int kDefaultMTU = 1500 - 28;
+
+static void dtls1_fix_message_header(SSL *s, unsigned long frag_off,
+ unsigned long frag_len);
+static unsigned char *dtls1_write_message_header(SSL *s, unsigned char *p);
+static long dtls1_get_message_fragment(SSL *s, int stn, long max, int *ok);
+
+static hm_fragment *dtls1_hm_fragment_new(unsigned long frag_len,
+ int reassembly) {
+ hm_fragment *frag = NULL;
+ unsigned char *buf = NULL;
+ unsigned char *bitmask = NULL;
+
+ frag = (hm_fragment *)OPENSSL_malloc(sizeof(hm_fragment));
+ if (frag == NULL) {
+ return NULL;
+ }
+
+ if (frag_len) {
+ buf = (unsigned char *)OPENSSL_malloc(frag_len);
+ if (buf == NULL) {
+ OPENSSL_free(frag);
+ return NULL;
+ }
+ }
+
+ /* zero length fragment gets zero frag->fragment */
+ frag->fragment = buf;
+
+ /* Initialize reassembly bitmask if necessary */
+ if (reassembly) {
+ bitmask = (unsigned char *)OPENSSL_malloc(RSMBLY_BITMASK_SIZE(frag_len));
+ if (bitmask == NULL) {
+ if (buf != NULL) {
+ OPENSSL_free(buf);
+ }
+ OPENSSL_free(frag);
+ return NULL;
+ }
+ memset(bitmask, 0, RSMBLY_BITMASK_SIZE(frag_len));
+ }
+
+ frag->reassembly = bitmask;
+
+ return frag;
+}
+
+void dtls1_hm_fragment_free(hm_fragment *frag) {
+ if (frag->msg_header.is_ccs) {
+ /* TODO(davidben): Simplify aead_write_ctx ownership, probably by just
+ * forbidding DTLS renego. */
+ SSL_AEAD_CTX *aead_write_ctx =
+ frag->msg_header.saved_retransmit_state.aead_write_ctx;
+ if (aead_write_ctx) {
+ EVP_AEAD_CTX_cleanup(&aead_write_ctx->ctx);
+ OPENSSL_free(aead_write_ctx);
+ }
+ }
+ if (frag->fragment) {
+ OPENSSL_free(frag->fragment);
+ }
+ if (frag->reassembly) {
+ OPENSSL_free(frag->reassembly);
+ }
+ OPENSSL_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 max_overhead = 0;
+
+ /* 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)) {
+ long mtu = BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL);
+ if (mtu >= 0 && mtu <= (1 << 30) && (unsigned)mtu >= dtls1_min_mtu()) {
+ s->d1->mtu = (unsigned)mtu;
+ } else {
+ s->d1->mtu = kDefaultMTU;
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SET_MTU, s->d1->mtu, NULL);
+ }
+ }
+
+ /* should have something reasonable now */
+ assert(s->d1->mtu >= dtls1_min_mtu());
+
+ if (s->init_off == 0 && type == SSL3_RT_HANDSHAKE) {
+ assert(s->init_num ==
+ (int)s->d1->w_msg_hdr.msg_len + DTLS1_HM_HEADER_LENGTH);
+ }
+
+ /* Determine the maximum overhead of the current cipher. */
+ if (s->aead_write_ctx != NULL) {
+ max_overhead = EVP_AEAD_max_overhead(s->aead_write_ctx->ctx.aead);
+ if (s->aead_write_ctx->variable_nonce_included_in_record) {
+ max_overhead += s->aead_write_ctx->variable_nonce_len;
+ }
+ }
+
+ frag_off = 0;
+ while (s->init_num) {
+ /* Account for data in the buffering BIO; multiple records may be packed
+ * into a single packet during the handshake.
+ *
+ * TODO(davidben): This is buggy; if the MTU is larger than the buffer size,
+ * the large record will be split across two packets. Moreover, in that
+ * case, the |dtls1_write_bytes| call may not return synchronously. This
+ * will break on retry as the |s->init_off| and |s->init_num| adjustment
+ * will run a second time. */
+ curr_mtu = s->d1->mtu - BIO_wpending(SSL_get_wbio(s)) -
+ DTLS1_RT_HEADER_LENGTH - max_overhead;
+
+ if (curr_mtu <= DTLS1_HM_HEADER_LENGTH) {
+ /* Flush the buffer and continue with a fresh packet.
+ *
+ * TODO(davidben): If |BIO_flush| is not synchronous and requires multiple
+ * calls to |dtls1_do_write|, |frag_off| will be wrong. */
+ ret = BIO_flush(SSL_get_wbio(s));
+ if (ret <= 0) {
+ return ret;
+ }
+ assert(BIO_wpending(SSL_get_wbio(s)) == 0);
+ curr_mtu = s->d1->mtu - DTLS1_RT_HEADER_LENGTH - max_overhead;
+ }
+
+ /* XDTLS: this function is too long. split out the CCS part */
+ if (type == SSL3_RT_HANDSHAKE) {
+ /* If this isn't the first fragment, reserve space to prepend a new
+ * fragment header. This will override the body of a previous fragment. */
+ if (s->init_off != 0) {
+ assert(s->init_off > DTLS1_HM_HEADER_LENGTH);
+ s->init_off -= DTLS1_HM_HEADER_LENGTH;
+ s->init_num += DTLS1_HM_HEADER_LENGTH;
+ }
+
+ if (curr_mtu <= DTLS1_HM_HEADER_LENGTH) {
+ /* To make forward progress, the MTU must, at minimum, fit the handshake
+ * header and one byte of handshake body. */
+ OPENSSL_PUT_ERROR(SSL, dtls1_do_write, SSL_R_MTU_TOO_SMALL);
+ return -1;
+ }
+
+ if (s->init_num > curr_mtu) {
+ len = curr_mtu;
+ } else {
+ len = s->init_num;
+ }
+ assert(len >= DTLS1_HM_HEADER_LENGTH);
+
+ dtls1_fix_message_header(s, frag_off, len - DTLS1_HM_HEADER_LENGTH);
+ dtls1_write_message_header(
+ s, (uint8_t *)&s->init_buf->data[s->init_off]);
+ } else {
+ assert(type == SSL3_RT_CHANGE_CIPHER_SPEC);
+ /* ChangeCipherSpec cannot be fragmented. */
+ if (s->init_num > curr_mtu) {
+ OPENSSL_PUT_ERROR(SSL, dtls1_do_write, SSL_R_MTU_TOO_SMALL);
+ return -1;
+ }
+ len = s->init_num;
+ }
+
+ ret = dtls1_write_bytes(s, type, &s->init_buf->data[s->init_off], len);
+ if (ret < 0) {
+ return -1;
+ }
+
+ /* bad if this assert fails, only part of the handshake message got sent.
+ * But why would this happen? */
+ assert(len == (unsigned int)ret);
+
+ 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. */
+long dtls1_get_message(SSL *s, int st1, int stn, int mt, long max,
+ int hash_message, int *ok) {
+ int i, al;
+ struct hm_header_st *msg_hdr;
+ uint8_t *p;
+ unsigned long msg_len;
+
+ /* s3->tmp is used to store messages that are unexpected, caused
+ * by the absence of an optional handshake message */
+ if (s->s3->tmp.reuse_message) {
+ /* A SSL_GET_MESSAGE_DONT_HASH_MESSAGE call cannot be combined
+ * with reuse_message; the SSL_GET_MESSAGE_DONT_HASH_MESSAGE
+ * would have to have been applied to the previous call. */
+ assert(hash_message != SSL_GET_MESSAGE_DONT_HASH_MESSAGE);
+ s->s3->tmp.reuse_message = 0;
+ if (mt >= 0 && s->s3->tmp.message_type != mt) {
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ OPENSSL_PUT_ERROR(SSL, dtls1_get_message, SSL_R_UNEXPECTED_MESSAGE);
+ goto f_err;
+ }
+ *ok = 1;
+ s->init_msg = (uint8_t *)s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
+ s->init_num = (int)s->s3->tmp.message_size;
+ return s->init_num;
+ }
+
+ msg_hdr = &s->d1->r_msg_hdr;
+ memset(msg_hdr, 0x00, sizeof(struct hm_header_st));
+
+again:
+ i = dtls1_get_message_fragment(s, 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 = (uint8_t *)s->init_buf->data;
+ msg_len = msg_hdr->msg_len;
+
+ /* reconstruct message header */
+ *(p++) = msg_hdr->type;
+ l2n3(msg_len, p);
+ s2n(msg_hdr->seq, p);
+ l2n3(0, p);
+ l2n3(msg_len, p);
+ p -= DTLS1_HM_HEADER_LENGTH;
+ msg_len += DTLS1_HM_HEADER_LENGTH;
+
+ s->init_msg = (uint8_t *)s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
+
+ if (hash_message != SSL_GET_MESSAGE_DONT_HASH_MESSAGE) {
+ ssl3_hash_current_message(s);
+ }
+ if (s->msg_callback) {
+ s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, p, msg_len, s,
+ s->msg_callback_arg);
+ }
+
+ memset(msg_hdr, 0x00, sizeof(struct hm_header_st));
+
+ s->d1->handshake_read_seq++;
+
+ return s->init_num;
+
+f_err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ *ok = 0;
+ 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) {
+ OPENSSL_PUT_ERROR(SSL, dtls1_preprocess_fragment,
+ SSL_R_EXCESSIVE_MESSAGE_SIZE);
+ return SSL_AD_ILLEGAL_PARAMETER;
+ }
+
+ if ((frag_off + frag_len) > (unsigned long)max) {
+ OPENSSL_PUT_ERROR(SSL, dtls1_preprocess_fragment,
+ 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)) {
+ OPENSSL_PUT_ERROR(SSL, dtls1_preprocess_fragment, ERR_R_BUF_LIB);
+ return SSL_AD_INTERNAL_ERROR;
+ }
+
+ s->s3->tmp.message_size = msg_len;
+ s->d1->r_msg_hdr.msg_len = msg_len;
+ s->s3->tmp.message_type = msg_hdr->type;
+ s->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. */
+ OPENSSL_PUT_ERROR(SSL, dtls1_preprocess_fragment,
+ 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;
+ unsigned long frag_len;
+
+ *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) {
+ return 0;
+ }
+
+ 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 */
+ uint8_t *p = (uint8_t *)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;
+}
+
+/* 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 = 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, const struct hm_header_st *msg_hdr,
+ int *ok) {
+ hm_fragment *frag = NULL;
+ pitem *item = NULL;
+ int i = -1, is_complete;
+ uint8_t 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) {
+ return DTLS1_HM_FRAGMENT_RETRY;
+ }
+
+ /* Try to find item in queue */
+ memset(seq64be, 0, sizeof(seq64be));
+ seq64be[6] = (uint8_t)(msg_hdr->seq >> 8);
+ seq64be[7] = (uint8_t)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. In this case item != NULL and so frag
+ * does not need to be freed. */
+ if (frag->reassembly == NULL) {
+ uint8_t devnull[256];
+
+ assert(item != NULL);
+ 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;
+ }
+ return DTLS1_HM_FRAGMENT_RETRY;
+ }
+
+ /* 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 ((unsigned long)i != frag_len) {
+ i = -1;
+ }
+ if (i <= 0) {
+ 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) {
+ OPENSSL_free(frag->reassembly);
+ frag->reassembly = NULL;
+ }
+
+ if (item == NULL) {
+ item = pitem_new(seq64be, frag);
+ if (item == NULL) {
+ i = -1;
+ goto err;
+ }
+
+ item = pqueue_insert(s->d1->buffered_messages, item);
+ /* pqueue_insert fails iff a duplicate item is inserted.
+ * However, |item| cannot be a duplicate. If it were,
+ * |pqueue_find|, above, would have returned it and control
+ * would never have reached this branch. */
+ assert(item != NULL);
+ }
+
+ return DTLS1_HM_FRAGMENT_RETRY;
+
+err:
+ if (frag != NULL && item == NULL) {
+ dtls1_hm_fragment_free(frag);
+ }
+ *ok = 0;
+ return i;
+}
+
+static int dtls1_process_out_of_seq_message(SSL *s,
+ const struct hm_header_st *msg_hdr,
+ int *ok) {
+ int i = -1;
+ hm_fragment *frag = NULL;
+ pitem *item = NULL;
+ uint8_t 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] = (uint8_t)(msg_hdr->seq >> 8);
+ seq64be[7] = (uint8_t)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)) {
+ uint8_t 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 ((unsigned long)i != frag_len) {
+ i = -1;
+ }
+ if (i <= 0) {
+ goto err;
+ }
+ }
+
+ item = pitem_new(seq64be, frag);
+ if (item == NULL) {
+ goto err;
+ }
+
+ item = pqueue_insert(s->d1->buffered_messages, item);
+ /* pqueue_insert fails iff a duplicate item is inserted.
+ * However, |item| cannot be a duplicate. If it were,
+ * |pqueue_find|, above, would have returned it. Then, either
+ * |frag_len| != |msg_hdr->msg_len| in which case |item| is set
+ * to NULL and it will have been processed with
+ * |dtls1_reassemble_fragment|, above, or the record will have
+ * been discarded. */
+ assert(item != NULL);
+ }
+
+ return DTLS1_HM_FRAGMENT_RETRY;
+
+err:
+ if (frag != NULL && item == NULL) {
+ dtls1_hm_fragment_free(frag);
+ }
+ *ok = 0;
+ return i;
+}
+
+
+static long dtls1_get_message_fragment(SSL *s, int stn, long max, int *ok) {
+ uint8_t wire[DTLS1_HM_HEADER_LENGTH];
+ unsigned long len, frag_off, frag_len;
+ int i, al;
+ struct hm_header_st msg_hdr;
+
+redo:
+ /* 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;
+ }
+
+ /* Handshake fails if message header is incomplete */
+ if (i != DTLS1_HM_HEADER_LENGTH) {
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ OPENSSL_PUT_ERROR(SSL, dtls1_get_message_fragment,
+ SSL_R_UNEXPECTED_MESSAGE);
+ goto f_err;
+ }
+
+ /* parse the message fragment header */
+ dtls1_get_message_header(wire, &msg_hdr);
+
+ /* if this is a future (or stale) message it gets buffered
+ * (or dropped)--no further processing at this time. */
+ if (msg_hdr.seq != s->d1->handshake_read_seq) {
+ 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 redo;
+ } else {
+ /* Incorrectly formated Hello request */
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ OPENSSL_PUT_ERROR(SSL, dtls1_get_message_fragment,
+ SSL_R_UNEXPECTED_MESSAGE);
+ goto f_err;
+ }
+ }
+
+ if ((al = dtls1_preprocess_fragment(s, &msg_hdr, max))) {
+ goto f_err;
+ }
+
+ /* XDTLS: ressurect this when restart is in place */
+ s->state = stn;
+
+ if (frag_len > 0) {
+ uint8_t *p = (uint8_t *)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 = SSL3_AD_ILLEGAL_PARAMETER;
+ OPENSSL_PUT_ERROR(SSL, dtls1_get_message_fragment,
+ SSL3_AD_ILLEGAL_PARAMETER);
+ goto f_err;
+ }
+
+ *ok = 1;
+
+ /* 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;
+ return frag_len;
+
+f_err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ s->init_num = 0;
+
+ *ok = 0;
+ return -1;
+}
+
+/* for these 2 messages, we need to
+ * ssl->enc_read_ctx re-init
+ * ssl->s3->read_sequence zero
+ * ssl->s3->read_mac_secret re-init
+ * ssl->session->read_sym_enc assign
+ * ssl->session->read_compression assign
+ * ssl->session->read_hash assign */
+int dtls1_send_change_cipher_spec(SSL *s, int a, int b) {
+ uint8_t *p;
+
+ if (s->state == a) {
+ p = (uint8_t *)s->init_buf->data;
+ *p++ = SSL3_MT_CCS;
+ s->d1->handshake_write_seq = s->d1->next_handshake_write_seq;
+ s->init_num = DTLS1_CCS_HEADER_LENGTH;
+
+ s->init_off = 0;
+
+ dtls1_set_message_header(s, SSL3_MT_CCS, 0, s->d1->handshake_write_seq, 0,
+ 0);
+
+ /* buffer the message to handle re-xmits */
+ dtls1_buffer_message(s, 1);
+
+ s->state = b;
+ }
+
+ /* SSL3_ST_CW_CHANGE_B */
+ return dtls1_do_write(s, SSL3_RT_CHANGE_CIPHER_SPEC);
+}
+
+int dtls1_read_failed(SSL *s, int code) {
+ if (code > 0) {
+ fprintf(stderr, "invalid state reached %s:%d", __FILE__, __LINE__);
+ 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) {
+ fprintf(stderr, "dtls1_retransmit_message() failed\n");
+ return -1;
+ }
+ }
+
+ return 1;
+}
+
+int dtls1_buffer_message(SSL *s, int is_ccs) {
+ pitem *item;
+ hm_fragment *frag;
+ uint8_t seq64be[8];
+
+ /* this function is called immediately after a message has
+ * been serialized */
+ assert(s->init_off == 0);
+
+ frag = dtls1_hm_fragment_new(s->init_num, 0);
+ if (!frag) {
+ return 0;
+ }
+
+ memcpy(frag->fragment, s->init_buf->data, s->init_num);
+
+ if (is_ccs) {
+ assert(s->d1->w_msg_hdr.msg_len + DTLS1_CCS_HEADER_LENGTH ==
+ (unsigned int)s->init_num);
+ } else {
+ assert(s->d1->w_msg_hdr.msg_len + 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.aead_write_ctx = s->aead_write_ctx;
+ frag->msg_header.saved_retransmit_state.session = s->session;
+ frag->msg_header.saved_retransmit_state.epoch = s->d1->w_epoch;
+
+ memset(seq64be, 0, sizeof(seq64be));
+ seq64be[6] = (uint8_t)(
+ dtls1_get_queue_priority(frag->msg_header.seq, frag->msg_header.is_ccs) >>
+ 8);
+ seq64be[7] = (uint8_t)(
+ 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;
+ uint8_t seq64be[8];
+ struct dtls1_retransmit_state saved_state;
+ uint8_t save_write_sequence[8];
+
+ /* assert(s->init_num == 0);
+ assert(s->init_off == 0); */
+
+ /* XDTLS: the requested message ought to be found, otherwise error */
+ memset(seq64be, 0, sizeof(seq64be));
+ seq64be[6] = (uint8_t)(seq >> 8);
+ seq64be[7] = (uint8_t)seq;
+
+ item = pqueue_find(s->d1->sent_messages, seq64be);
+ if (item == NULL) {
+ fprintf(stderr, "retransmit: message %d non-existant\n", seq);
+ *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(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.aead_write_ctx = s->aead_write_ctx;
+ saved_state.session = s->session;
+ saved_state.epoch = s->d1->w_epoch;
+
+ /* restore state in which the message was originally sent */
+ s->aead_write_ctx = frag->msg_header.saved_retransmit_state.aead_write_ctx;
+ s->session = frag->msg_header.saved_retransmit_state.session;
+ s->d1->w_epoch = frag->msg_header.saved_retransmit_state.epoch;
+
+ if (frag->msg_header.saved_retransmit_state.epoch == saved_state.epoch - 1) {
+ memcpy(save_write_sequence, s->s3->write_sequence,
+ sizeof(s->s3->write_sequence));
+ memcpy(s->s3->write_sequence, s->d1->last_write_sequence,
+ sizeof(s->s3->write_sequence));
+ }
+
+ ret = dtls1_do_write(s, frag->msg_header.is_ccs ? SSL3_RT_CHANGE_CIPHER_SPEC
+ : SSL3_RT_HANDSHAKE);
+
+ /* restore current state */
+ s->aead_write_ctx = saved_state.aead_write_ctx;
+ s->session = saved_state.session;
+ s->d1->w_epoch = saved_state.epoch;
+
+ if (frag->msg_header.saved_retransmit_state.epoch == saved_state.epoch - 1) {
+ memcpy(s->d1->last_write_sequence, s->s3->write_sequence,
+ sizeof(s->s3->write_sequence));
+ memcpy(s->s3->write_sequence, save_write_sequence,
+ sizeof(s->s3->write_sequence));
+ }
+
+ (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) {
+ pitem *item;
+
+ for (item = pqueue_pop(s->d1->sent_messages); item != NULL;
+ item = pqueue_pop(s->d1->sent_messages)) {
+ dtls1_hm_fragment_free((hm_fragment *)item->data);
+ pitem_free(item);
+ }
+}
+
+/* don't actually do the writing, wait till the MTU has been retrieved */
+void dtls1_set_message_header(SSL *s, uint8_t 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 uint8_t *dtls1_write_message_header(SSL *s, uint8_t *p) {
+ struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
+
+ *p++ = msg_hdr->type;
+ l2n3(msg_hdr->msg_len, p);
+
+ s2n(msg_hdr->seq, p);
+ l2n3(msg_hdr->frag_off, p);
+ l2n3(msg_hdr->frag_len, p);
+
+ return p;
+}
+
+unsigned int dtls1_min_mtu(void) {
+ return kMinMTU;
+}
+
+void dtls1_get_message_header(uint8_t *data,
+ struct hm_header_st *msg_hdr) {
+ memset(msg_hdr, 0x00, sizeof(struct hm_header_st));
+ msg_hdr->type = *(data++);
+ n2l3(data, msg_hdr->msg_len);
+
+ n2s(data, msg_hdr->seq);
+ n2l3(data, msg_hdr->frag_off);
+ n2l3(data, msg_hdr->frag_len);
+}
+
+void dtls1_get_ccs_header(uint8_t *data, struct ccs_header_st *ccs_hdr) {
+ memset(ccs_hdr, 0x00, sizeof(struct ccs_header_st));
+
+ ccs_hdr->type = *(data++);
+}
+
+int dtls1_shutdown(SSL *s) {
+ int ret;
+ ret = ssl3_shutdown(s);
+ return ret;
+}
diff --git a/src/ssl/d1_clnt.c b/src/ssl/d1_clnt.c
new file mode 100644
index 0000000..3f9e814
--- /dev/null
+++ b/src/ssl/d1_clnt.c
@@ -0,0 +1,577 @@
+/*
+ * DTLS implementation written by Nagendra Modadugu
+ * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
+ */
+/* ====================================================================
+ * 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).
+ *
+ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <assert.h>
+#include <stdio.h>
+
+#include <openssl/bn.h>
+#include <openssl/buf.h>
+#include <openssl/dh.h>
+#include <openssl/evp.h>
+#include <openssl/md5.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/rand.h>
+
+#include "ssl_locl.h"
+
+static int dtls1_get_hello_verify(SSL *s);
+
+int dtls1_connect(SSL *s) {
+ BUF_MEM *buf = NULL;
+ void (*cb)(const SSL *ssl, int type, int val) = NULL;
+ int ret = -1;
+ int new_state, state, skip = 0;
+
+ assert(s->handshake_func == dtls1_connect);
+ assert(!s->server);
+ assert(SSL_IS_DTLS(s));
+
+ ERR_clear_error();
+ ERR_clear_system_error();
+
+ if (s->info_callback != NULL) {
+ cb = s->info_callback;
+ } else if (s->ctx->info_callback != NULL) {
+ cb = s->ctx->info_callback;
+ }
+
+ s->in_handshake++;
+
+ for (;;) {
+ state = s->state;
+
+ switch (s->state) {
+ case SSL_ST_RENEGOTIATE:
+ s->renegotiate = 1;
+ s->state = SSL_ST_CONNECT;
+ s->ctx->stats.sess_connect_renegotiate++;
+ /* break */
+ case SSL_ST_CONNECT:
+ case SSL_ST_BEFORE | SSL_ST_CONNECT:
+ if (cb != NULL) {
+ cb(s, SSL_CB_HANDSHAKE_START, 1);
+ }
+
+ if (s->init_buf == NULL) {
+ buf = BUF_MEM_new();
+ if (buf == NULL ||
+ !BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) {
+ ret = -1;
+ goto end;
+ }
+ s->init_buf = buf;
+ buf = NULL;
+ }
+
+ if (!ssl3_setup_buffers(s) ||
+ !ssl_init_wbio_buffer(s, 0)) {
+ ret = -1;
+ goto end;
+ }
+
+ /* don't push the buffering BIO quite yet */
+
+ s->state = SSL3_ST_CW_CLNT_HELLO_A;
+ s->ctx->stats.sess_connect++;
+ s->init_num = 0;
+ 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;
+
+ /* every DTLS ClientHello resets Finished MAC */
+ if (!ssl3_init_finished_mac(s)) {
+ OPENSSL_PUT_ERROR(SSL, dtls1_connect, ERR_R_INTERNAL_ERROR);
+ ret = -1;
+ goto end;
+ }
+
+ dtls1_start_timer(s);
+ ret = ssl3_send_client_hello(s);
+ if (ret <= 0) {
+ goto end;
+ }
+
+ if (s->d1->send_cookie) {
+ s->state = SSL3_ST_CW_FLUSH;
+ s->s3->tmp.next_state = SSL3_ST_CR_SRVR_HELLO_A;
+ } else {
+ s->state = DTLS1_ST_CR_HELLO_VERIFY_REQUEST_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 DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A:
+ case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B:
+ ret = dtls1_get_hello_verify(s);
+ if (ret <= 0) {
+ goto end;
+ }
+ if (s->d1->send_cookie) {
+ /* start again, with a cookie */
+ dtls1_stop_timer(s);
+ s->state = SSL3_ST_CW_CLNT_HELLO_A;
+ } else {
+ s->state = SSL3_ST_CR_SRVR_HELLO_A;
+ }
+ s->init_num = 0;
+ 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->state = SSL3_ST_CR_FINISHED_A;
+ if (s->tlsext_ticket_expected) {
+ /* receive renewed session ticket */
+ s->state = SSL3_ST_CR_SESSION_TICKET_A;
+ }
+ } else {
+ s->state = SSL3_ST_CR_CERT_A;
+ }
+ s->init_num = 0;
+ break;
+
+ case SSL3_ST_CR_CERT_A:
+ case SSL3_ST_CR_CERT_B:
+ if (ssl_cipher_has_server_public_key(s->s3->tmp.new_cipher)) {
+ ret = ssl3_get_server_certificate(s);
+ if (ret <= 0) {
+ goto end;
+ }
+ if (s->s3->tmp.certificate_status_expected) {
+ s->state = SSL3_ST_CR_CERT_STATUS_A;
+ } else {
+ s->state = SSL3_ST_CR_KEY_EXCH_A;
+ }
+ } else {
+ skip = 1;
+ s->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->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->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;
+ }
+ dtls1_stop_timer(s);
+ if (s->s3->tmp.cert_req) {
+ s->s3->tmp.next_state = SSL3_ST_CW_CERT_A;
+ } else {
+ s->s3->tmp.next_state = SSL3_ST_CW_KEY_EXCH_A;
+ }
+ s->init_num = 0;
+ s->state = s->s3->tmp.next_state;
+ 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:
+ dtls1_start_timer(s);
+ ret = ssl3_send_client_certificate(s);
+ if (ret <= 0) {
+ goto end;
+ }
+ s->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:
+ dtls1_start_timer(s);
+ ret = ssl3_send_client_key_exchange(s);
+ if (ret <= 0) {
+ goto end;
+ }
+ /* For TLS, cert_req is set to 2, so a cert chain
+ * of nothing is sent, but no verify packet is sent */
+ if (s->s3->tmp.cert_req == 1) {
+ s->state = SSL3_ST_CW_CERT_VRFY_A;
+ } else {
+ s->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:
+ dtls1_start_timer(s);
+ ret = ssl3_send_cert_verify(s);
+ if (ret <= 0) {
+ goto end;
+ }
+ s->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 (!s->hit) {
+ dtls1_start_timer(s);
+ }
+ ret = dtls1_send_change_cipher_spec(s, SSL3_ST_CW_CHANGE_A,
+ SSL3_ST_CW_CHANGE_B);
+ if (ret <= 0) {
+ goto end;
+ }
+
+ s->state = SSL3_ST_CW_FINISHED_A;
+ s->init_num = 0;
+
+ s->session->cipher = s->s3->tmp.new_cipher;
+ if (!s->enc_method->setup_key_block(s) ||
+ !s->enc_method->change_cipher_state(
+ s, SSL3_CHANGE_CIPHER_CLIENT_WRITE)) {
+ ret = -1;
+ goto end;
+ }
+
+ dtls1_reset_seq_numbers(s, SSL3_CC_WRITE);
+ break;
+
+ case SSL3_ST_CW_FINISHED_A:
+ case SSL3_ST_CW_FINISHED_B:
+ if (!s->hit) {
+ dtls1_start_timer(s);
+ }
+
+ ret =
+ ssl3_send_finished(s, SSL3_ST_CW_FINISHED_A, SSL3_ST_CW_FINISHED_B,
+ s->enc_method->client_finished_label,
+ s->enc_method->client_finished_label_len);
+ if (ret <= 0) {
+ goto end;
+ }
+ s->state = SSL3_ST_CW_FLUSH;
+
+ if (s->hit) {
+ s->s3->tmp.next_state = SSL_ST_OK;
+ } else {
+ /* Allow NewSessionTicket if ticket expected */
+ if (s->tlsext_ticket_expected) {
+ s->s3->tmp.next_state = SSL3_ST_CR_SESSION_TICKET_A;
+ } else {
+ s->s3->tmp.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->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->state = SSL3_ST_CR_KEY_EXCH_A;
+ s->init_num = 0;
+ break;
+
+ case SSL3_ST_CR_FINISHED_A:
+ case SSL3_ST_CR_FINISHED_B:
+ s->d1->change_cipher_spec_ok = 1;
+ ret =
+ ssl3_get_finished(s, SSL3_ST_CR_FINISHED_A, SSL3_ST_CR_FINISHED_B);
+ if (ret <= 0) {
+ goto end;
+ }
+ dtls1_stop_timer(s);
+
+ if (s->hit) {
+ s->state = SSL3_ST_CW_CHANGE_A;
+ } else {
+ s->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 the write error was fatal, stop trying */
+ if (!BIO_should_retry(s->wbio)) {
+ s->rwstate = SSL_NOTHING;
+ s->state = s->s3->tmp.next_state;
+ }
+
+ ret = -1;
+ goto end;
+ }
+ s->rwstate = SSL_NOTHING;
+ s->state = s->s3->tmp.next_state;
+ break;
+
+ case SSL_ST_OK:
+ /* clean a few things up */
+ ssl3_cleanup_key_block(s);
+
+ /* Remove write buffering now. */
+ 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->ctx->stats.sess_connect_good++;
+
+ if (cb != NULL)
+ cb(s, SSL_CB_HANDSHAKE_DONE, 1);
+
+ /* done with handshaking */
+ s->d1->handshake_read_seq = 0;
+ s->d1->next_handshake_write_seq = 0;
+ goto end;
+
+ default:
+ OPENSSL_PUT_ERROR(SSL, dtls1_connect, SSL_R_UNKNOWN_STATE);
+ ret = -1;
+ goto end;
+ }
+
+ /* did we do anything? */
+ if (!s->s3->tmp.reuse_message && !skip) {
+ if ((cb != NULL) && (s->state != state)) {
+ new_state = s->state;
+ s->state = state;
+ cb(s, SSL_CB_CONNECT_LOOP, 1);
+ s->state = new_state;
+ }
+ }
+ skip = 0;
+ }
+
+end:
+ s->in_handshake--;
+
+ if (buf != NULL) {
+ BUF_MEM_free(buf);
+ }
+ if (cb != NULL) {
+ cb(s, SSL_CB_CONNECT_EXIT, ret);
+ }
+ return ret;
+}
+
+static int dtls1_get_hello_verify(SSL *s) {
+ long n;
+ int al, ok = 0;
+ CBS hello_verify_request, cookie;
+ uint16_t server_version;
+
+ n = s->method->ssl_get_message(
+ s, DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A, DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B,
+ -1,
+ /* Use the same maximum size as ssl3_get_server_hello. */
+ 20000, SSL_GET_MESSAGE_HASH_MESSAGE, &ok);
+
+ if (!ok) {
+ return n;
+ }
+
+ if (s->s3->tmp.message_type != DTLS1_MT_HELLO_VERIFY_REQUEST) {
+ s->d1->send_cookie = 0;
+ s->s3->tmp.reuse_message = 1;
+ return 1;
+ }
+
+ CBS_init(&hello_verify_request, s->init_msg, n);
+
+ if (!CBS_get_u16(&hello_verify_request, &server_version) ||
+ !CBS_get_u8_length_prefixed(&hello_verify_request, &cookie) ||
+ CBS_len(&hello_verify_request) != 0) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_cert_status, SSL_R_DECODE_ERROR);
+ goto f_err;
+ }
+
+ if (CBS_len(&cookie) > sizeof(s->d1->cookie)) {
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ goto f_err;
+ }
+
+ memcpy(s->d1->cookie, CBS_data(&cookie), CBS_len(&cookie));
+ s->d1->cookie_len = CBS_len(&cookie);
+
+ s->d1->send_cookie = 1;
+ return 1;
+
+f_err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ return -1;
+}
diff --git a/src/ssl/d1_lib.c b/src/ssl/d1_lib.c
new file mode 100644
index 0000000..8244cb9
--- /dev/null
+++ b/src/ssl/d1_lib.c
@@ -0,0 +1,439 @@
+/*
+ * 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 <openssl/base.h>
+
+#include <limits.h>
+#include <stdio.h>
+
+#if defined(OPENSSL_WINDOWS)
+#include <sys/timeb.h>
+#else
+#include <sys/socket.h>
+#include <sys/time.h>
+#endif
+
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+
+#include "ssl_locl.h"
+
+static void get_current_time(OPENSSL_timeval *t);
+static OPENSSL_timeval *dtls1_get_timeout(SSL *s, OPENSSL_timeval *timeleft);
+static void dtls1_set_handshake_header(SSL *s, int type, unsigned long len);
+static int dtls1_handshake_write(SSL *s);
+
+const SSL3_ENC_METHOD DTLSv1_enc_data = {
+ tls1_enc,
+ tls1_prf,
+ tls1_setup_key_block,
+ tls1_generate_master_secret,
+ tls1_change_cipher_state,
+ tls1_final_finish_mac,
+ TLS1_FINISH_MAC_LENGTH,
+ tls1_cert_verify_mac,
+ TLS_MD_CLIENT_FINISH_CONST,TLS_MD_CLIENT_FINISH_CONST_SIZE,
+ TLS_MD_SERVER_FINISH_CONST,TLS_MD_SERVER_FINISH_CONST_SIZE,
+ tls1_alert_code,
+ tls1_export_keying_material,
+ SSL_ENC_FLAG_DTLS|SSL_ENC_FLAG_EXPLICIT_IV,
+ DTLS1_HM_HEADER_LENGTH,
+ dtls1_set_handshake_header,
+ dtls1_handshake_write,
+};
+
+const SSL3_ENC_METHOD DTLSv1_2_enc_data = {
+ tls1_enc,
+ tls1_prf,
+ tls1_setup_key_block,
+ tls1_generate_master_secret,
+ tls1_change_cipher_state,
+ tls1_final_finish_mac,
+ TLS1_FINISH_MAC_LENGTH,
+ tls1_cert_verify_mac,
+ TLS_MD_CLIENT_FINISH_CONST,TLS_MD_CLIENT_FINISH_CONST_SIZE,
+ TLS_MD_SERVER_FINISH_CONST,TLS_MD_SERVER_FINISH_CONST_SIZE,
+ tls1_alert_code,
+ tls1_export_keying_material,
+ SSL_ENC_FLAG_DTLS | SSL_ENC_FLAG_EXPLICIT_IV | SSL_ENC_FLAG_SIGALGS |
+ SSL_ENC_FLAG_SHA256_PRF | SSL_ENC_FLAG_TLS1_2_CIPHERS,
+ DTLS1_HM_HEADER_LENGTH,
+ dtls1_set_handshake_header,
+ dtls1_handshake_write,
+};
+
+int dtls1_new(SSL *s) {
+ DTLS1_STATE *d1;
+
+ if (!ssl3_new(s)) {
+ return 0;
+ }
+ d1 = OPENSSL_malloc(sizeof *d1);
+ if (d1 == NULL) {
+ ssl3_free(s);
+ return 0;
+ }
+ memset(d1, 0, sizeof *d1);
+
+ d1->unprocessed_rcds.q = pqueue_new();
+ d1->processed_rcds.q = pqueue_new();
+ d1->buffered_messages = pqueue_new();
+ d1->sent_messages = pqueue_new();
+ d1->buffered_app_data.q = pqueue_new();
+
+ if (!d1->unprocessed_rcds.q || !d1->processed_rcds.q ||
+ !d1->buffered_messages || !d1->sent_messages ||
+ !d1->buffered_app_data.q) {
+ if (d1->unprocessed_rcds.q) {
+ pqueue_free(d1->unprocessed_rcds.q);
+ }
+ if (d1->processed_rcds.q) {
+ pqueue_free(d1->processed_rcds.q);
+ }
+ if (d1->buffered_messages) {
+ pqueue_free(d1->buffered_messages);
+ }
+ if (d1->sent_messages) {
+ pqueue_free(d1->sent_messages);
+ }
+ if (d1->buffered_app_data.q) {
+ pqueue_free(d1->buffered_app_data.q);
+ }
+ OPENSSL_free(d1);
+ ssl3_free(s);
+ return 0;
+ }
+
+ s->d1 = d1;
+
+ /* Set the version to the highest version for DTLS. This controls the initial
+ * state of |s->enc_method| and what the API reports as the version prior to
+ * negotiation.
+ *
+ * TODO(davidben): This is fragile and confusing. */
+ s->version = DTLS1_2_VERSION;
+ return 1;
+}
+
+static void dtls1_clear_queues(SSL *s) {
+ pitem *item = NULL;
+ hm_fragment *frag = NULL;
+ DTLS1_RECORD_DATA *rdata;
+
+ while ((item = pqueue_pop(s->d1->unprocessed_rcds.q)) != NULL) {
+ rdata = (DTLS1_RECORD_DATA *)item->data;
+ if (rdata->rbuf.buf) {
+ OPENSSL_free(rdata->rbuf.buf);
+ }
+ OPENSSL_free(item->data);
+ pitem_free(item);
+ }
+
+ while ((item = pqueue_pop(s->d1->processed_rcds.q)) != NULL) {
+ rdata = (DTLS1_RECORD_DATA *)item->data;
+ if (rdata->rbuf.buf) {
+ OPENSSL_free(rdata->rbuf.buf);
+ }
+ OPENSSL_free(item->data);
+ pitem_free(item);
+ }
+
+ while ((item = pqueue_pop(s->d1->buffered_messages)) != NULL) {
+ frag = (hm_fragment *)item->data;
+ dtls1_hm_fragment_free(frag);
+ pitem_free(item);
+ }
+
+ while ((item = pqueue_pop(s->d1->sent_messages)) != NULL) {
+ frag = (hm_fragment *)item->data;
+ dtls1_hm_fragment_free(frag);
+ pitem_free(item);
+ }
+
+ while ((item = pqueue_pop(s->d1->buffered_app_data.q)) != NULL) {
+ rdata = (DTLS1_RECORD_DATA *)item->data;
+ if (rdata->rbuf.buf) {
+ OPENSSL_free(rdata->rbuf.buf);
+ }
+ OPENSSL_free(item->data);
+ pitem_free(item);
+ }
+}
+
+void dtls1_free(SSL *s) {
+ ssl3_free(s);
+
+ if (s == NULL || s->d1 == NULL) {
+ return;
+ }
+
+ dtls1_clear_queues(s);
+
+ pqueue_free(s->d1->unprocessed_rcds.q);
+ pqueue_free(s->d1->processed_rcds.q);
+ pqueue_free(s->d1->buffered_messages);
+ pqueue_free(s->d1->sent_messages);
+ pqueue_free(s->d1->buffered_app_data.q);
+
+ OPENSSL_free(s->d1);
+ s->d1 = NULL;
+}
+
+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, (OPENSSL_timeval *)parg) != NULL) {
+ ret = 1;
+ }
+ break;
+
+ case DTLS_CTRL_HANDLE_TIMEOUT:
+ ret = dtls1_handle_timeout(s);
+ break;
+
+ default:
+ ret = ssl3_ctrl(s, cmd, larg, parg);
+ break;
+ }
+
+ return ret;
+}
+
+const SSL_CIPHER *dtls1_get_cipher(unsigned int u) {
+ const SSL_CIPHER *ciph = ssl3_get_cipher(u);
+ /* DTLS does not support stream ciphers. */
+ if (ciph == NULL || ciph->algorithm_enc == SSL_RC4) {
+ return NULL;
+ }
+
+ return ciph;
+}
+
+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 */
+ get_current_time(&s->d1->next_timeout);
+
+ /* 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);
+}
+
+static OPENSSL_timeval *dtls1_get_timeout(SSL *s, OPENSSL_timeval *timeleft) {
+ OPENSSL_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 */
+ get_current_time(&timenow);
+
+ /* 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(OPENSSL_timeval));
+ return timeleft;
+ }
+
+ /* Calculate time left until timer expires */
+ memcpy(timeleft, &s->d1->next_timeout, sizeof(OPENSSL_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(OPENSSL_timeval));
+ }
+
+ return timeleft;
+}
+
+int dtls1_is_timer_expired(SSL *s) {
+ OPENSSL_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(OPENSSL_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 &&
+ !(SSL_get_options(s) & SSL_OP_NO_QUERY_MTU)) {
+ long mtu = BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_GET_FALLBACK_MTU, 0,
+ NULL);
+ if (mtu >= 0 && mtu <= (1 << 30) && (unsigned)mtu >= dtls1_min_mtu()) {
+ s->d1->mtu = (unsigned)mtu;
+ }
+ }
+
+ if (s->d1->timeout.num_alerts > DTLS1_TMO_ALERT_COUNT) {
+ /* fail the connection, enough alerts have been sent */
+ OPENSSL_PUT_ERROR(SSL, dtls1_check_timeout_num, 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);
+}
+
+static void get_current_time(OPENSSL_timeval *t) {
+#if defined(OPENSSL_WINDOWS)
+ struct _timeb time;
+ _ftime(&time);
+ t->tv_sec = time.time;
+ t->tv_usec = time.millitm * 1000;
+#else
+ gettimeofday(t, NULL);
+#endif
+}
+
+static void dtls1_set_handshake_header(SSL *s, int htype, unsigned long len) {
+ uint8_t *message = (uint8_t *)s->init_buf->data;
+ const struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
+ uint8_t serialised_header[DTLS1_HM_HEADER_LENGTH];
+ uint8_t *p = serialised_header;
+
+ s->d1->handshake_write_seq = s->d1->next_handshake_write_seq;
+ s->d1->next_handshake_write_seq++;
+
+ dtls1_set_message_header(s, htype, len, s->d1->handshake_write_seq, 0, len);
+ s->init_num = (int)len + DTLS1_HM_HEADER_LENGTH;
+ s->init_off = 0;
+
+ /* Buffer the message to handle re-xmits */
+ dtls1_buffer_message(s, 0);
+
+ /* Add the new message to the handshake hash. Serialize the message
+ * header as if it were a single fragment. */
+ *p++ = msg_hdr->type;
+ l2n3(msg_hdr->msg_len, p);
+ s2n(msg_hdr->seq, p);
+ l2n3(0, p);
+ l2n3(msg_hdr->msg_len, p);
+ ssl3_finish_mac(s, serialised_header, sizeof(serialised_header));
+ ssl3_finish_mac(s, message + DTLS1_HM_HEADER_LENGTH, len);
+}
+
+static int dtls1_handshake_write(SSL *s) {
+ return dtls1_do_write(s, SSL3_RT_HANDSHAKE);
+}
diff --git a/src/ssl/d1_meth.c b/src/ssl/d1_meth.c
new file mode 100644
index 0000000..a894222
--- /dev/null
+++ b/src/ssl/d1_meth.c
@@ -0,0 +1,136 @@
+/* ssl/d1_meth.h */
+/*
+ * 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 "ssl_locl.h"
+
+
+static const SSL_PROTOCOL_METHOD DTLS_protocol_method = {
+ dtls1_new,
+ dtls1_free,
+ dtls1_accept,
+ dtls1_connect,
+ ssl3_read,
+ ssl3_peek,
+ ssl3_write,
+ dtls1_shutdown,
+ ssl3_renegotiate,
+ ssl3_renegotiate_check,
+ dtls1_get_message,
+ dtls1_read_bytes,
+ dtls1_write_app_data_bytes,
+ dtls1_dispatch_alert,
+ dtls1_ctrl,
+ ssl3_ctx_ctrl,
+ ssl3_pending,
+ ssl3_num_ciphers,
+ dtls1_get_cipher,
+ ssl_undefined_void_function,
+ ssl3_callback_ctrl,
+ ssl3_ctx_callback_ctrl,
+};
+
+const SSL_METHOD *DTLS_method(void) {
+ static const SSL_METHOD method = {
+ 0,
+ &DTLS_protocol_method,
+ };
+ return &method;
+}
+
+/* Legacy version-locked methods. */
+
+const SSL_METHOD *DTLSv1_2_method(void) {
+ static const SSL_METHOD method = {
+ DTLS1_2_VERSION,
+ &DTLS_protocol_method,
+ };
+ return &method;
+}
+
+const SSL_METHOD *DTLSv1_method(void) {
+ static const SSL_METHOD method = {
+ DTLS1_VERSION,
+ &DTLS_protocol_method,
+ };
+ return &method;
+}
+
+/* Legacy side-specific methods. */
+
+const SSL_METHOD *DTLSv1_2_server_method(void) {
+ return DTLSv1_2_method();
+}
+
+const SSL_METHOD *DTLSv1_server_method(void) {
+ return DTLSv1_method();
+}
+
+const SSL_METHOD *DTLSv1_2_client_method(void) {
+ return DTLSv1_2_method();
+}
+
+const SSL_METHOD *DTLSv1_client_method(void) {
+ return DTLSv1_method();
+}
+
+const SSL_METHOD *DTLS_server_method(void) {
+ return DTLS_method();
+}
+
+const SSL_METHOD *DTLS_client_method(void) {
+ return DTLS_method();
+}
diff --git a/src/ssl/d1_pkt.c b/src/ssl/d1_pkt.c
new file mode 100644
index 0000000..a77ad4e
--- /dev/null
+++ b/src/ssl/d1_pkt.c
@@ -0,0 +1,1321 @@
+/* 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 <stdio.h>
+#include <errno.h>
+#include <assert.h>
+
+#include <openssl/buf.h>
+#include <openssl/mem.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <openssl/rand.h>
+
+#include "ssl_locl.h"
+
+
+/* mod 128 saturating subtract of two 64-bit values in big-endian order */
+static int satsub64be(const uint8_t *v1, const uint8_t *v2) {
+ int ret, sat, brw, i;
+
+ if (sizeof(long) == 8) {
+ do {
+ const union {
+ long one;
+ char little;
+ } is_endian = {1};
+ long l;
+
+ if (is_endian.little) {
+ 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 have_handshake_fragment(SSL *s, int type, uint8_t *buf, int len,
+ int peek);
+static int dtls1_record_replay_check(SSL *s, DTLS1_BITMAP *bitmap);
+static void dtls1_record_bitmap_update(SSL *s, DTLS1_BITMAP *bitmap);
+static DTLS1_BITMAP *dtls1_get_bitmap(SSL *s, SSL3_RECORD *rr,
+ unsigned int *is_next_epoch);
+static int dtls1_buffer_record(SSL *s, record_pqueue *q,
+ uint8_t *priority);
+static int dtls1_process_record(SSL *s);
+static int do_dtls1_write(SSL *s, int type, const uint8_t *buf,
+ unsigned int len);
+
+/* copy buffered record into SSL structure */
+static int dtls1_copy_record(SSL *s, pitem *item) {
+ DTLS1_RECORD_DATA *rdata;
+
+ rdata = (DTLS1_RECORD_DATA *)item->data;
+
+ if (s->s3->rbuf.buf != NULL) {
+ OPENSSL_free(s->s3->rbuf.buf);
+ }
+
+ s->packet = rdata->packet;
+ s->packet_length = rdata->packet_length;
+ memcpy(&(s->s3->rbuf), &(rdata->rbuf), sizeof(SSL3_BUFFER));
+ memcpy(&(s->s3->rrec), &(rdata->rrec), sizeof(SSL3_RECORD));
+
+ /* Set proper sequence number for mac calculation */
+ memcpy(&(s->s3->read_sequence[2]), &(rdata->packet[5]), 6);
+
+ return 1;
+}
+
+static int dtls1_buffer_record(SSL *s, record_pqueue *queue,
+ uint8_t *priority) {
+ DTLS1_RECORD_DATA *rdata;
+ pitem *item;
+
+ /* Limit the size of the queue to prevent DOS attacks */
+ if (pqueue_size(queue->q) >= 100) {
+ return 0;
+ }
+
+ rdata = OPENSSL_malloc(sizeof(DTLS1_RECORD_DATA));
+ item = pitem_new(priority, rdata);
+ if (rdata == NULL || item == NULL) {
+ if (rdata != NULL) {
+ OPENSSL_free(rdata);
+ }
+ if (item != NULL) {
+ pitem_free(item);
+ }
+
+ OPENSSL_PUT_ERROR(SSL, dtls1_buffer_record, ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
+
+ rdata->packet = s->packet;
+ rdata->packet_length = s->packet_length;
+ memcpy(&(rdata->rbuf), &(s->s3->rbuf), sizeof(SSL3_BUFFER));
+ memcpy(&(rdata->rrec), &(s->s3->rrec), sizeof(SSL3_RECORD));
+
+ item->data = rdata;
+
+ s->packet = NULL;
+ s->packet_length = 0;
+ memset(&(s->s3->rbuf), 0, sizeof(SSL3_BUFFER));
+ memset(&(s->s3->rrec), 0, sizeof(SSL3_RECORD));
+
+ if (!ssl3_setup_buffers(s)) {
+ goto internal_error;
+ }
+
+ /* insert should not fail, since duplicates are dropped */
+ if (pqueue_insert(queue->q, item) == NULL) {
+ goto internal_error;
+ }
+
+ return 1;
+
+internal_error:
+ OPENSSL_PUT_ERROR(SSL, dtls1_buffer_record, ERR_R_INTERNAL_ERROR);
+ if (rdata->rbuf.buf != NULL) {
+ OPENSSL_free(rdata->rbuf.buf);
+ }
+ OPENSSL_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);
+
+ OPENSSL_free(item->data);
+ pitem_free(item);
+
+ return 1;
+ }
+
+ return 0;
+}
+
+/* retrieve a buffered record that belongs to the new epoch, i.e., not
+ * processed yet */
+#define dtls1_get_unprocessed_record(s) \
+ dtls1_retrieve_buffered_record((s), &((s)->d1->unprocessed_rcds))
+
+/* retrieve a buffered record that belongs to the current epoch, i.e.,
+ * processed */
+#define dtls1_get_processed_record(s) \
+ dtls1_retrieve_buffered_record((s), &((s)->d1->processed_rcds))
+
+static int dtls1_process_buffered_records(SSL *s) {
+ pitem *item;
+
+ item = pqueue_peek(s->d1->unprocessed_rcds.q);
+ if (item) {
+ /* Check if epoch is current. */
+ if (s->d1->unprocessed_rcds.epoch != s->d1->r_epoch) {
+ return 1; /* Nothing to do. */
+ }
+
+ /* Process all the records. */
+ while (pqueue_peek(s->d1->unprocessed_rcds.q)) {
+ dtls1_get_unprocessed_record(s);
+ if (!dtls1_process_record(s)) {
+ return 0;
+ }
+ if (dtls1_buffer_record(s, &(s->d1->processed_rcds),
+ s->s3->rrec.seq_num) < 0) {
+ return -1;
+ }
+ }
+ }
+
+ /* sync epoch numbers once all the unprocessed records have been processed */
+ s->d1->processed_rcds.epoch = s->d1->r_epoch;
+ s->d1->unprocessed_rcds.epoch = s->d1->r_epoch + 1;
+
+ return 1;
+}
+
+static int dtls1_process_record(SSL *s) {
+ int al;
+ SSL3_RECORD *rr;
+
+ rr = &(s->s3->rrec);
+
+ /* At this point, s->packet_length == SSL3_RT_HEADER_LNGTH + rr->length, and
+ * we have that many bytes in s->packet. */
+ rr->input = &(s->packet[DTLS1_RT_HEADER_LENGTH]);
+
+ /* ok, we can now read from 's->packet' data into 'rr' rr->input points at
+ * rr->length bytes, which need to be copied into rr->data by either the
+ * decryption or by the decompression When the data is 'copied' into the
+ * rr->data buffer, rr->input will be pointed at the new buffer */
+
+ /* We now have - encrypted [ MAC [ compressed [ plain ] ] ] rr->length bytes
+ * of encrypted compressed stuff. */
+
+ /* check is not needed I believe */
+ if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH) {
+ al = SSL_AD_RECORD_OVERFLOW;
+ OPENSSL_PUT_ERROR(SSL, dtls1_process_record,
+ SSL_R_ENCRYPTED_LENGTH_TOO_LONG);
+ goto f_err;
+ }
+
+ /* decrypt in place in 'rr->input' */
+ rr->data = rr->input;
+
+ if (!s->enc_method->enc(s, 0)) {
+ /* Bad packets are silently dropped in DTLS. Clear the error queue of any
+ * errors decryption may have added. */
+ ERR_clear_error();
+ rr->length = 0;
+ s->packet_length = 0;
+ goto err;
+ }
+
+ if (rr->length > SSL3_RT_MAX_PLAIN_LENGTH) {
+ al = SSL_AD_RECORD_OVERFLOW;
+ OPENSSL_PUT_ERROR(SSL, dtls1_process_record, SSL_R_DATA_LENGTH_TOO_LONG);
+ goto f_err;
+ }
+
+ rr->off = 0;
+ /* So at this point the following is true
+ * ssl->s3->rrec.type is the type of record
+ * ssl->s3->rrec.length == number of bytes in record
+ * ssl->s3->rrec.off == offset to first valid byte
+ * ssl->s3->rrec.data == where to take bytes from, increment
+ * after use :-). */
+
+ /* we have pulled in a full packet so zero things */
+ s->packet_length = 0;
+ return 1;
+
+f_err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+
+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) {
+ int ssl_major, ssl_minor;
+ int i, n;
+ SSL3_RECORD *rr;
+ unsigned char *p = NULL;
+ unsigned short version;
+ DTLS1_BITMAP *bitmap;
+ unsigned int is_next_epoch;
+
+ rr = &(s->s3->rrec);
+
+ /* The epoch may have changed. If so, process all the pending records. This
+ * is a non-blocking operation. */
+ if (dtls1_process_buffered_records(s) < 0) {
+ return -1;
+ }
+
+ /* If we're renegotiating, then there may be buffered records. */
+ if (dtls1_get_processed_record(s)) {
+ return 1;
+ }
+
+ /* get something from the wire */
+again:
+ /* check if we have the header */
+ if ((s->rstate != SSL_ST_READ_BODY) ||
+ (s->packet_length < DTLS1_RT_HEADER_LENGTH)) {
+ n = ssl3_read_n(s, DTLS1_RT_HEADER_LENGTH, s->s3->rbuf.len, 0);
+ /* read timeout is handled by dtls1_read_bytes */
+ if (n <= 0) {
+ return n; /* error or non-blocking */
+ }
+
+ /* this packet contained a partial record, dump it */
+ if (s->packet_length != DTLS1_RT_HEADER_LENGTH) {
+ s->packet_length = 0;
+ goto again;
+ }
+
+ s->rstate = SSL_ST_READ_BODY;
+
+ p = s->packet;
+
+ if (s->msg_callback) {
+ s->msg_callback(0, 0, SSL3_RT_HEADER, p, DTLS1_RT_HEADER_LENGTH, s,
+ s->msg_callback_arg);
+ }
+
+ /* Pull apart the header into the DTLS1_RECORD */
+ rr->type = *(p++);
+ ssl_major = *(p++);
+ ssl_minor = *(p++);
+ version = (ssl_major << 8) | ssl_minor;
+
+ /* sequence number is 64 bits, with top 2 bytes = epoch */
+ n2s(p, rr->epoch);
+
+ memcpy(&(s->s3->read_sequence[2]), p, 6);
+ p += 6;
+
+ n2s(p, rr->length);
+
+ /* Lets check version */
+ if (s->s3->have_version) {
+ if (version != s->version) {
+ /* The record's version doesn't match, so silently drop it.
+ *
+ * TODO(davidben): This doesn't work. The DTLS record layer is not
+ * packet-based, so the remainder of the packet isn't dropped and we
+ * get a framing error. It's also unclear what it means to silently
+ * drop a record in a packet containing two records. */
+ rr->length = 0;
+ s->packet_length = 0;
+ goto again;
+ }
+ }
+
+ if ((version & 0xff00) != (s->version & 0xff00)) {
+ /* wrong version, silently discard record */
+ rr->length = 0;
+ s->packet_length = 0;
+ goto again;
+ }
+
+ if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH) {
+ /* record too long, silently discard it */
+ rr->length = 0;
+ s->packet_length = 0;
+ goto again;
+ }
+
+ /* now s->rstate == SSL_ST_READ_BODY */
+ }
+
+ /* s->rstate == SSL_ST_READ_BODY, get and decode the data */
+
+ if (rr->length > s->packet_length - DTLS1_RT_HEADER_LENGTH) {
+ /* now s->packet_length == DTLS1_RT_HEADER_LENGTH */
+ i = rr->length;
+ n = ssl3_read_n(s, i, i, 1);
+ if (n <= 0) {
+ return n; /* error or non-blocking io */
+ }
+
+ /* this packet contained a partial record, dump it */
+ if (n != i) {
+ rr->length = 0;
+ s->packet_length = 0;
+ goto again;
+ }
+
+ /* now n == rr->length,
+ * and s->packet_length == DTLS1_RT_HEADER_LENGTH + rr->length */
+ }
+ 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) {
+ rr->length = 0;
+ s->packet_length = 0; /* dump this record */
+ goto again; /* get another record */
+ }
+
+ /* Check whether this is a repeat, or aged record. */
+ if (!dtls1_record_replay_check(s, bitmap)) {
+ rr->length = 0;
+ s->packet_length = 0; /* dump this record */
+ goto again; /* get another record */
+ }
+
+ /* 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.
+ */
+ if (is_next_epoch) {
+ if (SSL_in_init(s) || s->in_handshake) {
+ if (dtls1_buffer_record(s, &(s->d1->unprocessed_rcds), rr->seq_num) < 0) {
+ return -1;
+ }
+ dtls1_record_bitmap_update(s, bitmap); /* Mark receipt of record. */
+ }
+ rr->length = 0;
+ s->packet_length = 0;
+ goto again;
+ }
+
+ if (!dtls1_process_record(s)) {
+ rr->length = 0;
+ s->packet_length = 0; /* dump this record */
+ goto again; /* get another record */
+ }
+ dtls1_record_bitmap_update(s, bitmap); /* Mark receipt of record. */
+
+ 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 al, i, j, ret;
+ unsigned int n;
+ SSL3_RECORD *rr;
+ void (*cb)(const SSL *ssl, int type2, int val) = NULL;
+
+ if (s->s3->rbuf.buf == NULL && !ssl3_setup_buffers(s)) {
+ return -1;
+ }
+
+ /* XXX: check what the second '&& type' is about */
+ if ((type && (type != SSL3_RT_APPLICATION_DATA) &&
+ (type != SSL3_RT_HANDSHAKE) && type) ||
+ (peek && (type != SSL3_RT_APPLICATION_DATA))) {
+ OPENSSL_PUT_ERROR(SSL, dtls1_read_bytes, ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
+
+ /* check whether there's a handshake message (client hello?) waiting */
+ ret = have_handshake_fragment(s, type, buf, len, peek);
+ if (ret) {
+ return ret;
+ }
+
+ /* Now s->d1->handshake_fragment_len == 0 if type == SSL3_RT_HANDSHAKE. */
+
+ if (!s->in_handshake && SSL_in_init(s)) {
+ /* type == SSL3_RT_APPLICATION_DATA */
+ i = s->handshake_func(s);
+ if (i < 0) {
+ return i;
+ }
+ if (i == 0) {
+ OPENSSL_PUT_ERROR(SSL, dtls1_read_bytes, SSL_R_SSL_HANDSHAKE_FAILURE);
+ return -1;
+ }
+ }
+
+start:
+ s->rwstate = SSL_NOTHING;
+
+ /* s->s3->rrec.type - is the type of record
+ * s->s3->rrec.data - data
+ * s->s3->rrec.off - offset into 'data' for next read
+ * s->s3->rrec.length - number of bytes. */
+ rr = &s->s3->rrec;
+
+ /* We are not handshaking and have no data yet,
+ * so process data buffered during the last handshake
+ * in advance, if any.
+ */
+ if (s->state == SSL_ST_OK && rr->length == 0) {
+ pitem *item;
+ item = pqueue_pop(s->d1->buffered_app_data.q);
+ if (item) {
+ dtls1_copy_record(s, item);
+
+ OPENSSL_free(item->data);
+ pitem_free(item);
+ }
+ }
+
+ /* Check for timeout */
+ if (dtls1_handle_timeout(s) > 0) {
+ goto start;
+ }
+
+ /* get new packet if necessary */
+ if (rr->length == 0 || s->rstate == SSL_ST_READ_BODY) {
+ ret = dtls1_get_record(s);
+ if (ret <= 0) {
+ ret = dtls1_read_failed(s, ret);
+ /* anything other than a timeout is an error */
+ if (ret <= 0) {
+ return ret;
+ } else {
+ goto start;
+ }
+ }
+ }
+
+ /* we now have a packet which can be read and processed */
+
+ /* |change_cipher_spec is set when we receive a ChangeCipherSpec and reset by
+ * ssl3_get_finished. */
+ if (s->s3->change_cipher_spec && rr->type != 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_record(s, &(s->d1->buffered_app_data), rr->seq_num) < 0) {
+ OPENSSL_PUT_ERROR(SSL, dtls1_read_bytes, ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
+ rr->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) {
+ rr->length = 0;
+ s->rwstate = SSL_NOTHING;
+ return 0;
+ }
+
+
+ if (type == rr->type) { /* SSL3_RT_APPLICATION_DATA or SSL3_RT_HANDSHAKE */
+ /* 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) &&
+ (s->aead_read_ctx == NULL)) {
+ /* TODO(davidben): Is this check redundant with the handshake_func
+ * check? */
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ OPENSSL_PUT_ERROR(SSL, dtls1_read_bytes, SSL_R_APP_DATA_IN_HANDSHAKE);
+ goto f_err;
+ }
+
+ if (len <= 0) {
+ return len;
+ }
+
+ if ((unsigned int)len > rr->length) {
+ n = rr->length;
+ } else {
+ n = (unsigned int)len;
+ }
+
+ memcpy(buf, &(rr->data[rr->off]), n);
+ if (!peek) {
+ rr->length -= n;
+ rr->off += n;
+ if (rr->length == 0) {
+ s->rstate = SSL_ST_READ_HEADER;
+ rr->off = 0;
+ }
+ }
+
+ return n;
+ }
+
+ /* If we get here, then type != rr->type; if we have a handshake message,
+ * then it was unexpected (Hello Request or Client Hello). */
+
+ /* In case of record types for which we have 'fragment' storage, fill that so
+ * that we can process the data at a fixed place. */
+ {
+ unsigned int k, dest_maxlen = 0;
+ uint8_t *dest = NULL;
+ unsigned int *dest_len = NULL;
+
+ if (rr->type == SSL3_RT_HANDSHAKE) {
+ dest_maxlen = sizeof s->d1->handshake_fragment;
+ dest = s->d1->handshake_fragment;
+ dest_len = &s->d1->handshake_fragment_len;
+ } else if (rr->type == SSL3_RT_ALERT) {
+ dest_maxlen = sizeof(s->d1->alert_fragment);
+ dest = s->d1->alert_fragment;
+ dest_len = &s->d1->alert_fragment_len;
+ }
+ /* else it's a CCS message, or application data or wrong */
+ else if (rr->type != SSL3_RT_CHANGE_CIPHER_SPEC) {
+ /* Application data while renegotiating is allowed. Try again reading. */
+ if (rr->type == SSL3_RT_APPLICATION_DATA) {
+ BIO *bio;
+ s->s3->in_read_app_data = 2;
+ bio = SSL_get_rbio(s);
+ s->rwstate = SSL_READING;
+ BIO_clear_retry_flags(bio);
+ BIO_set_retry_read(bio);
+ return -1;
+ }
+
+ /* Not certain if this is the right error handling */
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ OPENSSL_PUT_ERROR(SSL, dtls1_read_bytes, SSL_R_UNEXPECTED_RECORD);
+ goto f_err;
+ }
+
+ if (dest_maxlen > 0) {
+ /* XDTLS: In a pathalogical case, the Client Hello
+ * may be fragmented--don't always expect dest_maxlen bytes */
+ if (rr->length < dest_maxlen) {
+ s->rstate = SSL_ST_READ_HEADER;
+ rr->length = 0;
+ goto start;
+ }
+
+ /* now move 'n' bytes: */
+ for (k = 0; k < dest_maxlen; k++) {
+ dest[k] = rr->data[rr->off++];
+ rr->length--;
+ }
+ *dest_len = dest_maxlen;
+ }
+ }
+
+ /* s->d1->handshake_fragment_len == 12 iff rr->type == SSL3_RT_HANDSHAKE;
+ * s->d1->alert_fragment_len == 7 iff rr->type == SSL3_RT_ALERT.
+ * (Possibly rr is 'empty' now, i.e. rr->length may be 0.) */
+
+ /* If we are a client, check for an incoming 'Hello Request': */
+ if (!s->server && s->d1->handshake_fragment_len >= DTLS1_HM_HEADER_LENGTH &&
+ s->d1->handshake_fragment[0] == SSL3_MT_HELLO_REQUEST &&
+ s->session != NULL && s->session->cipher != NULL) {
+ s->d1->handshake_fragment_len = 0;
+
+ if ((s->d1->handshake_fragment[1] != 0) ||
+ (s->d1->handshake_fragment[2] != 0) ||
+ (s->d1->handshake_fragment[3] != 0)) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, dtls1_read_bytes, SSL_R_BAD_HELLO_REQUEST);
+ goto f_err;
+ }
+
+ /* no need to check sequence number on HELLO REQUEST messages */
+
+ if (s->msg_callback) {
+ s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE,
+ s->d1->handshake_fragment, 4, s, s->msg_callback_arg);
+ }
+
+ if (SSL_is_init_finished(s) && !s->s3->renegotiate) {
+ s->d1->handshake_read_seq++;
+ s->new_session = 1;
+ ssl3_renegotiate(s);
+ if (ssl3_renegotiate_check(s)) {
+ i = s->handshake_func(s);
+ if (i < 0) {
+ return i;
+ }
+ if (i == 0) {
+ OPENSSL_PUT_ERROR(SSL, dtls1_read_bytes, SSL_R_SSL_HANDSHAKE_FAILURE);
+ return -1;
+ }
+ }
+ }
+
+ /* we either finished a handshake or ignored the request, now try again to
+ * obtain the (application) data we were asked for */
+ goto start;
+ }
+
+ if (s->d1->alert_fragment_len >= DTLS1_AL_HEADER_LENGTH) {
+ int alert_level = s->d1->alert_fragment[0];
+ int alert_descr = s->d1->alert_fragment[1];
+
+ s->d1->alert_fragment_len = 0;
+
+ if (s->msg_callback) {
+ s->msg_callback(0, s->version, SSL3_RT_ALERT, s->d1->alert_fragment, 2, s,
+ s->msg_callback_arg);
+ }
+
+ if (s->info_callback != NULL) {
+ cb = s->info_callback;
+ } else if (s->ctx->info_callback != NULL) {
+ cb = s->ctx->info_callback;
+ }
+
+ if (cb != NULL) {
+ j = (alert_level << 8) | alert_descr;
+ cb(s, SSL_CB_READ_ALERT, j);
+ }
+
+ if (alert_level == 1) { /* warning */
+ s->s3->warn_alert = alert_descr;
+ if (alert_descr == SSL_AD_CLOSE_NOTIFY) {
+ s->shutdown |= SSL_RECEIVED_SHUTDOWN;
+ return 0;
+ }
+ } else if (alert_level == 2) { /* fatal */
+ char tmp[16];
+
+ s->rwstate = SSL_NOTHING;
+ s->s3->fatal_alert = alert_descr;
+ OPENSSL_PUT_ERROR(SSL, dtls1_read_bytes,
+ SSL_AD_REASON_OFFSET + alert_descr);
+ BIO_snprintf(tmp, sizeof tmp, "%d", alert_descr);
+ ERR_add_error_data(2, "SSL alert number ", tmp);
+ s->shutdown |= SSL_RECEIVED_SHUTDOWN;
+ SSL_CTX_remove_session(s->ctx, s->session);
+ return 0;
+ } else {
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ OPENSSL_PUT_ERROR(SSL, dtls1_read_bytes, SSL_R_UNKNOWN_ALERT_TYPE);
+ goto f_err;
+ }
+
+ goto start;
+ }
+
+ if (s->shutdown & SSL_SENT_SHUTDOWN) {
+ /* but we have not received a shutdown */
+ s->rwstate = SSL_NOTHING;
+ rr->length = 0;
+ return 0;
+ }
+
+ if (rr->type == SSL3_RT_CHANGE_CIPHER_SPEC) {
+ struct ccs_header_st ccs_hdr;
+ unsigned int ccs_hdr_len = DTLS1_CCS_HEADER_LENGTH;
+
+ dtls1_get_ccs_header(rr->data, &ccs_hdr);
+
+ /* 'Change Cipher Spec' is just a single byte, so we know
+ * exactly what the record payload has to look like */
+ /* XDTLS: check that epoch is consistent */
+ if ((rr->length != ccs_hdr_len) || (rr->off != 0) ||
+ (rr->data[0] != SSL3_MT_CCS)) {
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ OPENSSL_PUT_ERROR(SSL, dtls1_read_bytes, SSL_R_BAD_CHANGE_CIPHER_SPEC);
+ goto f_err;
+ }
+
+ rr->length = 0;
+
+ if (s->msg_callback) {
+ s->msg_callback(0, s->version, SSL3_RT_CHANGE_CIPHER_SPEC, rr->data, 1, s,
+ s->msg_callback_arg);
+ }
+
+ /* We can't process a CCS now, because previous handshake
+ * messages are still missing, so just drop it.
+ */
+ if (!s->d1->change_cipher_spec_ok) {
+ goto start;
+ }
+
+ s->d1->change_cipher_spec_ok = 0;
+
+ s->s3->change_cipher_spec = 1;
+ if (!ssl3_do_change_cipher_spec(s)) {
+ goto err;
+ }
+
+ /* do this whenever CCS is processed */
+ dtls1_reset_seq_numbers(s, SSL3_CC_READ);
+
+ goto start;
+ }
+
+ /* Unexpected handshake message (Client Hello, or protocol violation) */
+ if ((s->d1->handshake_fragment_len >= DTLS1_HM_HEADER_LENGTH) &&
+ !s->in_handshake) {
+ struct hm_header_st msg_hdr;
+
+ /* this may just be a stale retransmit */
+ dtls1_get_message_header(rr->data, &msg_hdr);
+ if (rr->epoch != s->d1->r_epoch) {
+ rr->length = 0;
+ goto start;
+ }
+
+ /* If we are server, we may have a repeated FINISHED of the client here,
+ * then retransmit our CCS and FINISHED. */
+ if (msg_hdr.type == SSL3_MT_FINISHED) {
+ if (dtls1_check_timeout_num(s) < 0) {
+ return -1;
+ }
+
+ dtls1_retransmit_buffered_messages(s);
+ rr->length = 0;
+ goto start;
+ }
+
+ if ((s->state & SSL_ST_MASK) == SSL_ST_OK) {
+ s->state = s->server ? SSL_ST_ACCEPT : SSL_ST_CONNECT;
+ s->renegotiate = 1;
+ s->new_session = 1;
+ }
+ i = s->handshake_func(s);
+ if (i < 0) {
+ return i;
+ }
+ if (i == 0) {
+ OPENSSL_PUT_ERROR(SSL, dtls1_read_bytes, SSL_R_SSL_HANDSHAKE_FAILURE);
+ return -1;
+ }
+
+ goto start;
+ }
+
+ switch (rr->type) {
+ default:
+ /* TLS just ignores unknown message types */
+ if (s->version == TLS1_VERSION) {
+ rr->length = 0;
+ goto start;
+ }
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ OPENSSL_PUT_ERROR(SSL, dtls1_read_bytes, SSL_R_UNEXPECTED_RECORD);
+ goto f_err;
+
+ case SSL3_RT_CHANGE_CIPHER_SPEC:
+ case SSL3_RT_ALERT:
+ case SSL3_RT_HANDSHAKE:
+ /* we already handled all of these, with the possible exception of
+ * SSL3_RT_HANDSHAKE when s->in_handshake is set, but that should not
+ * happen when type != rr->type */
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ OPENSSL_PUT_ERROR(SSL, dtls1_read_bytes, ERR_R_INTERNAL_ERROR);
+ goto f_err;
+
+ case 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 && (s->s3->total_renegotiations != 0) &&
+ (((s->state & SSL_ST_CONNECT) &&
+ (s->state >= SSL3_ST_CW_CLNT_HELLO_A) &&
+ (s->state <= SSL3_ST_CR_SRVR_HELLO_A)) ||
+ ((s->state & SSL_ST_ACCEPT) &&
+ (s->state <= SSL3_ST_SW_HELLO_REQ_A) &&
+ (s->state >= SSL3_ST_SR_CLNT_HELLO_A)))) {
+ s->s3->in_read_app_data = 2;
+ return -1;
+ } else {
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ OPENSSL_PUT_ERROR(SSL, dtls1_read_bytes, SSL_R_UNEXPECTED_RECORD);
+ goto f_err;
+ }
+ }
+
+ /* not reached */
+
+f_err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+err:
+ 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) {
+ OPENSSL_PUT_ERROR(SSL, dtls1_write_app_data_bytes,
+ SSL_R_SSL_HANDSHAKE_FAILURE);
+ return -1;
+ }
+ }
+
+ if (len > SSL3_RT_MAX_PLAIN_LENGTH) {
+ OPENSSL_PUT_ERROR(SSL, dtls1_write_app_data_bytes,
+ SSL_R_DTLS_MESSAGE_TOO_BIG);
+ return -1;
+ }
+
+ i = dtls1_write_bytes(s, type, buf_, len);
+ return i;
+}
+
+
+/* this only happens when a client hello is received and a handshake is
+ * started. */
+static int have_handshake_fragment(SSL *s, int type, uint8_t *buf,
+ int len, int peek) {
+ if (type == SSL3_RT_HANDSHAKE && s->d1->handshake_fragment_len > 0) {
+ /* (partially) satisfy request from storage */
+ uint8_t *src = s->d1->handshake_fragment;
+ uint8_t *dst = buf;
+ unsigned int k, n;
+
+ /* peek == 0 */
+ n = 0;
+ while (len > 0 && s->d1->handshake_fragment_len > 0) {
+ *dst++ = *src++;
+ len--;
+ s->d1->handshake_fragment_len--;
+ n++;
+ }
+ /* move any remaining fragment bytes: */
+ for (k = 0; k < s->d1->handshake_fragment_len; k++) {
+ s->d1->handshake_fragment[k] = *src++;
+ }
+ return n;
+ }
+
+ return 0;
+}
+
+/* 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;
+
+ assert(len <= SSL3_RT_MAX_PLAIN_LENGTH);
+ s->rwstate = SSL_NOTHING;
+ i = do_dtls1_write(s, type, buf, len);
+ return i;
+}
+
+static int do_dtls1_write(SSL *s, int type, const uint8_t *buf,
+ unsigned int len) {
+ uint8_t *p, *pseq;
+ int i;
+ int prefix_len = 0;
+ int eivlen = 0;
+ SSL3_RECORD *wr;
+ SSL3_BUFFER *wb;
+
+ /* first check if there is a SSL3_BUFFER still being written
+ * out. This will happen with non blocking IO */
+ if (s->s3->wbuf.left != 0) {
+ 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, lets send it */
+ if (s->s3->alert_dispatch) {
+ i = s->method->ssl_dispatch_alert(s);
+ if (i <= 0) {
+ return i;
+ }
+ /* if it went, fall through and send more stuff */
+ }
+
+ if (len == 0) {
+ return 0;
+ }
+
+ wr = &(s->s3->wrec);
+ wb = &(s->s3->wbuf);
+
+ p = wb->buf + prefix_len;
+
+ /* write the header */
+
+ *(p++) = type & 0xff;
+ wr->type = type;
+ /* Special case: for hello verify request, client version 1.0 and
+ * we haven't decided which version to use yet send back using
+ * version 1.0 header: otherwise some clients will ignore it.
+ */
+ if (!s->s3->have_version) {
+ *(p++) = DTLS1_VERSION >> 8;
+ *(p++) = DTLS1_VERSION & 0xff;
+ } else {
+ *(p++) = s->version >> 8;
+ *(p++) = s->version & 0xff;
+ }
+
+ /* field where we are to write out packet epoch, seq num and len */
+ pseq = p;
+ p += 10;
+
+ /* Leave room for the variable nonce for AEADs which specify it explicitly. */
+ if (s->aead_write_ctx != NULL &&
+ s->aead_write_ctx->variable_nonce_included_in_record) {
+ eivlen = s->aead_write_ctx->variable_nonce_len;
+ }
+
+ /* lets setup the record stuff. */
+ wr->data = p + eivlen; /* make room for IV in case of CBC */
+ wr->length = (int)len;
+ wr->input = (unsigned char *)buf;
+
+ /* we now 'read' from wr->input, wr->length bytes into wr->data */
+ memcpy(wr->data, wr->input, wr->length);
+ wr->input = wr->data;
+
+ /* this is true regardless of mac size */
+ wr->input = p;
+ wr->data = p;
+ wr->length += eivlen;
+
+ if (!s->enc_method->enc(s, 1)) {
+ goto err;
+ }
+
+ /* there's only one epoch between handshake and app data */
+ s2n(s->d1->w_epoch, pseq);
+
+ memcpy(pseq, &(s->s3->write_sequence[2]), 6);
+ pseq += 6;
+ s2n(wr->length, pseq);
+
+ if (s->msg_callback) {
+ s->msg_callback(1, 0, SSL3_RT_HEADER, pseq - DTLS1_RT_HEADER_LENGTH,
+ DTLS1_RT_HEADER_LENGTH, s, s->msg_callback_arg);
+ }
+
+ /* we should now have wr->data pointing to the encrypted data, which is
+ * wr->length long */
+ wr->type = type; /* not needed but helps for debugging */
+ wr->length += DTLS1_RT_HEADER_LENGTH;
+
+ ssl3_record_sequence_update(&(s->s3->write_sequence[0]));
+
+ /* now let's set up wb */
+ wb->left = prefix_len + wr->length;
+ wb->offset = 0;
+
+ /* 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:
+ return -1;
+}
+
+static int dtls1_record_replay_check(SSL *s, DTLS1_BITMAP *bitmap) {
+ int cmp;
+ unsigned int shift;
+ const uint8_t *seq = s->s3->read_sequence;
+
+ cmp = satsub64be(seq, bitmap->max_seq_num);
+ if (cmp > 0) {
+ memcpy(s->s3->rrec.seq_num, seq, 8);
+ return 1; /* this record in new */
+ }
+ shift = -cmp;
+ if (shift >= sizeof(bitmap->map) * 8) {
+ return 0; /* stale, outside the window */
+ } else if (bitmap->map & (((uint64_t)1) << shift)) {
+ return 0; /* record previously received */
+ }
+
+ memcpy(s->s3->rrec.seq_num, seq, 8);
+ return 1;
+}
+
+static void dtls1_record_bitmap_update(SSL *s, DTLS1_BITMAP *bitmap) {
+ int cmp;
+ unsigned int shift;
+ const uint8_t *seq = s->s3->read_sequence;
+
+ 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 |= ((uint64_t)1) << shift;
+ }
+ }
+}
+
+int dtls1_dispatch_alert(SSL *s) {
+ int i, j;
+ void (*cb)(const SSL *ssl, int type, int val) = NULL;
+ uint8_t buf[DTLS1_AL_HEADER_LENGTH];
+ uint8_t *ptr = &buf[0];
+
+ s->s3->alert_dispatch = 0;
+
+ memset(buf, 0x00, sizeof(buf));
+ *ptr++ = s->s3->send_alert[0];
+ *ptr++ = s->s3->send_alert[1];
+
+ i = do_dtls1_write(s, SSL3_RT_ALERT, &buf[0], sizeof(buf));
+ if (i <= 0) {
+ s->s3->alert_dispatch = 1;
+ } else {
+ if (s->s3->send_alert[0] == SSL3_AL_FATAL) {
+ (void)BIO_flush(s->wbio);
+ }
+
+ if (s->msg_callback) {
+ s->msg_callback(1, s->version, SSL3_RT_ALERT, s->s3->send_alert, 2, s,
+ s->msg_callback_arg);
+ }
+
+ if (s->info_callback != NULL) {
+ cb = s->info_callback;
+ } else if (s->ctx->info_callback != NULL) {
+ cb = s->ctx->info_callback;
+ }
+
+ if (cb != NULL) {
+ j = (s->s3->send_alert[0] << 8) | s->s3->send_alert[1];
+ cb(s, SSL_CB_WRITE_ALERT, j);
+ }
+ }
+
+ return i;
+}
+
+static DTLS1_BITMAP *dtls1_get_bitmap(SSL *s, SSL3_RECORD *rr,
+ unsigned int *is_next_epoch) {
+ *is_next_epoch = 0;
+
+ /* In current epoch, accept HM, CCS, DATA, & ALERT */
+ if (rr->epoch == s->d1->r_epoch) {
+ return &s->d1->bitmap;
+ } else if (rr->epoch == (unsigned long)(s->d1->r_epoch + 1) &&
+ (rr->type == SSL3_RT_HANDSHAKE || rr->type == SSL3_RT_ALERT)) {
+ /* Only HM and ALERT messages can be from the next epoch */
+ *is_next_epoch = 1;
+ return &s->d1->next_bitmap;
+ }
+
+ return NULL;
+}
+
+void dtls1_reset_seq_numbers(SSL *s, int rw) {
+ uint8_t *seq;
+ unsigned int seq_bytes = sizeof(s->s3->read_sequence);
+
+ if (rw & SSL3_CC_READ) {
+ seq = s->s3->read_sequence;
+ s->d1->r_epoch++;
+ memcpy(&(s->d1->bitmap), &(s->d1->next_bitmap), sizeof(DTLS1_BITMAP));
+ memset(&(s->d1->next_bitmap), 0x00, sizeof(DTLS1_BITMAP));
+ } else {
+ seq = s->s3->write_sequence;
+ memcpy(s->d1->last_write_sequence, seq, sizeof(s->s3->write_sequence));
+ s->d1->w_epoch++;
+ }
+
+ memset(seq, 0x00, seq_bytes);
+}
diff --git a/src/ssl/d1_srtp.c b/src/ssl/d1_srtp.c
new file mode 100644
index 0000000..b85ff9b
--- /dev/null
+++ b/src/ssl/d1_srtp.c
@@ -0,0 +1,431 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <ekr@rtfm.com>
+
+ Copyright (C) 2006, Network Resonance, Inc.
+ Copyright (C) 2011, RTFM, Inc.
+*/
+
+#include <stdio.h>
+
+#include <openssl/bytestring.h>
+#include <openssl/obj.h>
+#include <openssl/err.h>
+
+#include "ssl_locl.h"
+#include <openssl/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,
+ },
+ {0},
+};
+
+static int find_profile_by_name(const char *profile_name,
+ const SRTP_PROTECTION_PROFILE **pptr,
+ size_t 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 1;
+ }
+
+ p++;
+ }
+
+ return 0;
+}
+
+static int find_profile_by_num(unsigned 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 1;
+ }
+ p++;
+ }
+
+ return 0;
+}
+
+static int ssl_ctx_make_profiles(const char *profiles_string,
+ STACK_OF(SRTP_PROTECTION_PROFILE) * *out) {
+ STACK_OF(SRTP_PROTECTION_PROFILE) *profiles;
+
+ const char *col;
+ const char *ptr = profiles_string;
+
+ profiles = sk_SRTP_PROTECTION_PROFILE_new_null();
+ if (profiles == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl_ctx_make_profiles,
+ SSL_R_SRTP_COULD_NOT_ALLOCATE_PROFILES);
+ return 0;
+ }
+
+ do {
+ const SRTP_PROTECTION_PROFILE *p;
+
+ col = strchr(ptr, ':');
+ if (find_profile_by_name(ptr, &p, col ? col - ptr : strlen(ptr))) {
+ sk_SRTP_PROTECTION_PROFILE_push(profiles, p);
+ } else {
+ OPENSSL_PUT_ERROR(SSL, ssl_ctx_make_profiles,
+ SSL_R_SRTP_UNKNOWN_PROTECTION_PROFILE);
+ return 0;
+ }
+
+ if (col) {
+ ptr = col + 1;
+ }
+ } while (col);
+
+ *out = profiles;
+
+ return 1;
+}
+
+int SSL_CTX_set_srtp_profiles(SSL_CTX *ctx, const char *profiles) {
+ return ssl_ctx_make_profiles(profiles, &ctx->srtp_profiles);
+}
+
+int SSL_set_srtp_profiles(SSL *s, const char *profiles) {
+ return ssl_ctx_make_profiles(profiles, &s->srtp_profiles);
+}
+
+STACK_OF(SRTP_PROTECTION_PROFILE) *SSL_get_srtp_profiles(SSL *s) {
+ if (s == NULL) {
+ return NULL;
+ }
+
+ if (s->srtp_profiles != NULL) {
+ return s->srtp_profiles;
+ }
+
+ if (s->ctx != NULL && s->ctx->srtp_profiles != NULL) {
+ return s->ctx->srtp_profiles;
+ }
+
+ return NULL;
+}
+
+const SRTP_PROTECTION_PROFILE *SSL_get_selected_srtp_profile(SSL *s) {
+ return s->srtp_profile;
+}
+
+int SSL_CTX_set_tlsext_use_srtp(SSL_CTX *ctx, const char *profiles) {
+ /* This API inverts its return value. */
+ return !SSL_CTX_set_srtp_profiles(ctx, profiles);
+}
+
+int SSL_set_tlsext_use_srtp(SSL *s, const char *profiles) {
+ /* This API inverts its return value. */
+ return !SSL_set_srtp_profiles(s, profiles);
+}
+
+/* Note: this function returns 0 length if there are no profiles specified */
+int ssl_add_clienthello_use_srtp_ext(SSL *s, uint8_t *p, int *len, int maxlen) {
+ int ct = 0;
+ int i;
+ STACK_OF(SRTP_PROTECTION_PROFILE) *clnt = 0;
+ const SRTP_PROTECTION_PROFILE *prof;
+
+ clnt = SSL_get_srtp_profiles(s);
+ ct = sk_SRTP_PROTECTION_PROFILE_num(clnt); /* -1 if clnt == 0 */
+
+ if (p) {
+ if (ct == 0) {
+ OPENSSL_PUT_ERROR(SSL, ssl_add_clienthello_use_srtp_ext,
+ SSL_R_EMPTY_SRTP_PROTECTION_PROFILE_LIST);
+ return 0;
+ }
+
+ if (2 + ct * 2 + 1 > maxlen) {
+ OPENSSL_PUT_ERROR(SSL, ssl_add_clienthello_use_srtp_ext,
+ SSL_R_SRTP_PROTECTION_PROFILE_LIST_TOO_LONG);
+ return 0;
+ }
+
+ /* Add the length */
+ s2n(ct * 2, p);
+ for (i = 0; i < ct; i++) {
+ prof = sk_SRTP_PROTECTION_PROFILE_value(clnt, i);
+ s2n(prof->id, p);
+ }
+
+ /* Add an empty use_mki value */
+ *p++ = 0;
+ }
+
+ *len = 2 + ct * 2 + 1;
+
+ return 1;
+}
+
+int ssl_parse_clienthello_use_srtp_ext(SSL *s, CBS *cbs, int *out_alert) {
+ CBS profile_ids, srtp_mki;
+ const SRTP_PROTECTION_PROFILE *cprof, *sprof;
+ STACK_OF(SRTP_PROTECTION_PROFILE) *client_profiles = 0, *server_profiles;
+ size_t i, j;
+ int ret = 0;
+
+ if (!CBS_get_u16_length_prefixed(cbs, &profile_ids) ||
+ CBS_len(&profile_ids) < 2 ||
+ !CBS_get_u8_length_prefixed(cbs, &srtp_mki) ||
+ CBS_len(cbs) != 0) {
+ OPENSSL_PUT_ERROR(SSL, ssl_parse_clienthello_use_srtp_ext,
+ SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
+ *out_alert = SSL_AD_DECODE_ERROR;
+ goto done;
+ }
+
+ client_profiles = sk_SRTP_PROTECTION_PROFILE_new_null();
+ if (client_profiles == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl_parse_clienthello_use_srtp_ext,
+ ERR_R_MALLOC_FAILURE);
+ *out_alert = SSL_AD_INTERNAL_ERROR;
+ goto done;
+ }
+
+ while (CBS_len(&profile_ids) > 0) {
+ uint16_t profile_id;
+
+ if (!CBS_get_u16(&profile_ids, &profile_id)) {
+ *out_alert = SSL_AD_DECODE_ERROR;
+ goto done;
+ }
+
+ if (find_profile_by_num(profile_id, &cprof)) {
+ sk_SRTP_PROTECTION_PROFILE_push(client_profiles, cprof);
+ }
+ }
+
+ /* Discard the MKI value for now. */
+
+ server_profiles = SSL_get_srtp_profiles(s);
+
+ /* Pick the server's most preferred profile. */
+ for (i = 0; i < sk_SRTP_PROTECTION_PROFILE_num(server_profiles); i++) {
+ sprof = sk_SRTP_PROTECTION_PROFILE_value(server_profiles, i);
+
+ for (j = 0; j < sk_SRTP_PROTECTION_PROFILE_num(client_profiles); j++) {
+ cprof = sk_SRTP_PROTECTION_PROFILE_value(client_profiles, j);
+
+ if (cprof->id == sprof->id) {
+ s->srtp_profile = sprof;
+ ret = 1;
+ goto done;
+ }
+ }
+ }
+
+ ret = 1;
+
+done:
+ if (client_profiles) {
+ sk_SRTP_PROTECTION_PROFILE_free(client_profiles);
+ }
+
+ return ret;
+}
+
+int ssl_add_serverhello_use_srtp_ext(SSL *s, unsigned char *p, int *len,
+ int maxlen) {
+ if (p) {
+ if (maxlen < 5) {
+ OPENSSL_PUT_ERROR(SSL, ssl_add_serverhello_use_srtp_ext,
+ SSL_R_SRTP_PROTECTION_PROFILE_LIST_TOO_LONG);
+ return 0;
+ }
+
+ if (s->srtp_profile == 0) {
+ OPENSSL_PUT_ERROR(SSL, ssl_add_serverhello_use_srtp_ext,
+ SSL_R_USE_SRTP_NOT_NEGOTIATED);
+ return 0;
+ }
+
+ s2n(2, p);
+ s2n(s->srtp_profile->id, p);
+ *p++ = 0;
+ }
+
+ *len = 5;
+
+ return 1;
+}
+
+int ssl_parse_serverhello_use_srtp_ext(SSL *s, CBS *cbs, int *out_alert) {
+ CBS profile_ids, srtp_mki;
+ uint16_t profile_id;
+ size_t i;
+
+ STACK_OF(SRTP_PROTECTION_PROFILE) *client_profiles;
+ const SRTP_PROTECTION_PROFILE *prof;
+
+ /* The extension consists of a u16-prefixed profile ID list containing a
+ * single uint16_t profile ID, then followed by a u8-prefixed srtp_mki field.
+ *
+ * See https://tools.ietf.org/html/rfc5764#section-4.1.1 */
+ if (!CBS_get_u16_length_prefixed(cbs, &profile_ids) ||
+ !CBS_get_u16(&profile_ids, &profile_id) || CBS_len(&profile_ids) != 0 ||
+ !CBS_get_u8_length_prefixed(cbs, &srtp_mki) || CBS_len(cbs) != 0) {
+ OPENSSL_PUT_ERROR(SSL, ssl_parse_serverhello_use_srtp_ext,
+ SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
+ *out_alert = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ if (CBS_len(&srtp_mki) != 0) {
+ /* Must be no MKI, since we never offer one. */
+ OPENSSL_PUT_ERROR(SSL, ssl_parse_serverhello_use_srtp_ext,
+ SSL_R_BAD_SRTP_MKI_VALUE);
+ *out_alert = SSL_AD_ILLEGAL_PARAMETER;
+ return 0;
+ }
+
+ client_profiles = SSL_get_srtp_profiles(s);
+
+ /* Throw an error if the server gave us an unsolicited extension */
+ if (client_profiles == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl_parse_serverhello_use_srtp_ext,
+ SSL_R_NO_SRTP_PROFILES);
+ *out_alert = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ /* Check to see if the server gave us something we support
+ (and presumably offered). */
+ for (i = 0; i < sk_SRTP_PROTECTION_PROFILE_num(client_profiles); i++) {
+ prof = sk_SRTP_PROTECTION_PROFILE_value(client_profiles, i);
+
+ if (prof->id == profile_id) {
+ s->srtp_profile = prof;
+ *out_alert = 0;
+ return 1;
+ }
+ }
+
+ OPENSSL_PUT_ERROR(SSL, ssl_parse_serverhello_use_srtp_ext,
+ SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
+ *out_alert = SSL_AD_ILLEGAL_PARAMETER;
+ return 0;
+}
diff --git a/src/ssl/d1_srvr.c b/src/ssl/d1_srvr.c
new file mode 100644
index 0000000..5bce98e
--- /dev/null
+++ b/src/ssl/d1_srvr.c
@@ -0,0 +1,605 @@
+/*
+ * DTLS implementation written by Nagendra Modadugu
+ * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
+ */
+/* ====================================================================
+ * 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).
+ *
+ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <assert.h>
+#include <stdio.h>
+
+#include <openssl/bn.h>
+#include <openssl/buf.h>
+#include <openssl/dh.h>
+#include <openssl/evp.h>
+#include <openssl/md5.h>
+#include <openssl/obj.h>
+#include <openssl/rand.h>
+#include <openssl/x509.h>
+
+#include "ssl_locl.h"
+
+
+static int dtls1_send_hello_verify_request(SSL *s);
+
+int dtls1_accept(SSL *s) {
+ BUF_MEM *buf = NULL;
+ void (*cb)(const SSL *ssl, int type, int val) = NULL;
+ unsigned long alg_a;
+ int ret = -1;
+ int new_state, state, skip = 0;
+
+ assert(s->handshake_func == dtls1_accept);
+ assert(s->server);
+ assert(SSL_IS_DTLS(s));
+
+ ERR_clear_error();
+ ERR_clear_system_error();
+
+ if (s->info_callback != NULL) {
+ cb = s->info_callback;
+ } else if (s->ctx->info_callback != NULL) {
+ cb = s->ctx->info_callback;
+ }
+
+ s->in_handshake++;
+
+ if (s->cert == NULL) {
+ OPENSSL_PUT_ERROR(SSL, dtls1_accept, SSL_R_NO_CERTIFICATE_SET);
+ return -1;
+ }
+
+ for (;;) {
+ state = s->state;
+
+ switch (s->state) {
+ case SSL_ST_RENEGOTIATE:
+ s->renegotiate = 1;
+ /* s->state=SSL_ST_ACCEPT; */
+
+ case SSL_ST_ACCEPT:
+ case SSL_ST_BEFORE | SSL_ST_ACCEPT:
+ if (cb != NULL) {
+ cb(s, SSL_CB_HANDSHAKE_START, 1);
+ }
+
+ if (s->init_buf == NULL) {
+ buf = BUF_MEM_new();
+ if (buf == NULL || !BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) {
+ ret = -1;
+ goto end;
+ }
+ s->init_buf = buf;
+ buf = NULL;
+ }
+
+ if (!ssl3_setup_buffers(s)) {
+ ret = -1;
+ goto end;
+ }
+
+ s->init_num = 0;
+
+ if (s->state != SSL_ST_RENEGOTIATE) {
+ if (!ssl_init_wbio_buffer(s, 1)) {
+ ret = -1;
+ goto end;
+ }
+
+ if (!ssl3_init_finished_mac(s)) {
+ OPENSSL_PUT_ERROR(SSL, dtls1_accept, ERR_R_INTERNAL_ERROR);
+ ret = -1;
+ goto end;
+ }
+
+ s->state = SSL3_ST_SR_CLNT_HELLO_A;
+ s->ctx->stats.sess_accept++;
+ } else {
+ /* s->state == SSL_ST_RENEGOTIATE, * we will just send a
+ * HelloRequest */
+ s->ctx->stats.sess_accept_renegotiate++;
+ s->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;
+ dtls1_clear_record_buffer(s);
+ dtls1_start_timer(s);
+ ret = ssl3_send_hello_request(s);
+ if (ret <= 0) {
+ goto end;
+ }
+ s->s3->tmp.next_state = SSL3_ST_SR_CLNT_HELLO_A;
+ s->state = SSL3_ST_SW_FLUSH;
+ s->init_num = 0;
+
+ if (!ssl3_init_finished_mac(s)) {
+ OPENSSL_PUT_ERROR(SSL, dtls1_accept, ERR_R_INTERNAL_ERROR);
+ ret = -1;
+ goto end;
+ }
+ break;
+
+ case SSL3_ST_SW_HELLO_REQ_C:
+ s->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:
+ case SSL3_ST_SR_CLNT_HELLO_D:
+ s->shutdown = 0;
+ 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->state = DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A;
+ } else {
+ s->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 = dtls1_send_hello_verify_request(s);
+ if (ret <= 0) {
+ goto end;
+ }
+ s->state = SSL3_ST_SW_FLUSH;
+ s->s3->tmp.next_state = SSL3_ST_SR_CLNT_HELLO_A;
+
+ /* HelloVerifyRequest resets Finished MAC */
+ if (!ssl3_init_finished_mac(s)) {
+ OPENSSL_PUT_ERROR(SSL, dtls1_accept, ERR_R_INTERNAL_ERROR);
+ ret = -1;
+ goto end;
+ }
+ break;
+
+ case SSL3_ST_SW_SRVR_HELLO_A:
+ case SSL3_ST_SW_SRVR_HELLO_B:
+ 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->state = SSL3_ST_SW_SESSION_TICKET_A;
+ } else {
+ s->state = SSL3_ST_SW_CHANGE_A;
+ }
+ } else {
+ s->state = SSL3_ST_SW_CERT_A;
+ }
+ s->init_num = 0;
+ break;
+
+ case SSL3_ST_SW_CERT_A:
+ case SSL3_ST_SW_CERT_B:
+ if (ssl_cipher_has_server_public_key(s->s3->tmp.new_cipher)) {
+ dtls1_start_timer(s);
+ ret = ssl3_send_server_certificate(s);
+ if (ret <= 0) {
+ goto end;
+ }
+ if (s->s3->tmp.certificate_status_expected) {
+ s->state = SSL3_ST_SW_CERT_STATUS_A;
+ } else {
+ s->state = SSL3_ST_SW_KEY_EXCH_A;
+ }
+ } else {
+ skip = 1;
+ s->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_a = s->s3->tmp.new_cipher->algorithm_auth;
+
+ /* Send a ServerKeyExchange message if:
+ * - The key exchange is ephemeral or anonymous
+ * Diffie-Hellman.
+ * - There is a PSK identity hint.
+ *
+ * TODO(davidben): This logic is currently duplicated
+ * in s3_srvr.c. Fix this. In the meantime, keep them
+ * in sync. */
+ if (ssl_cipher_requires_server_key_exchange(s->s3->tmp.new_cipher) ||
+ ((alg_a & SSL_aPSK) && s->psk_identity_hint)) {
+ dtls1_start_timer(s);
+ ret = ssl3_send_server_key_exchange(s);
+ if (ret <= 0) {
+ goto end;
+ }
+ } else {
+ skip = 1;
+ }
+
+ s->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:
+ if (/* don't request cert unless asked for it: */
+ !(s->verify_mode & SSL_VERIFY_PEER) ||
+ /* if SSL_VERIFY_CLIENT_ONCE is set,
+ * don't request cert during re-negotiation: */
+ ((s->session->peer != NULL) &&
+ (s->verify_mode & SSL_VERIFY_CLIENT_ONCE)) ||
+ /* never request cert in anonymous ciphersuites
+ * (see section "Certificate request" in SSL 3 drafts
+ * and in RFC 2246): */
+ ((s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) &&
+ /* ... except when the application insists on verification
+ * (against the specs, but s3_clnt.c accepts this for SSL 3) */
+ !(s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) ||
+ /* With normal PSK Certificates and
+ * Certificate Requests are omitted */
+ (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) {
+ /* no cert request */
+ skip = 1;
+ s->s3->tmp.cert_request = 0;
+ s->state = SSL3_ST_SW_SRVR_DONE_A;
+ } else {
+ s->s3->tmp.cert_request = 1;
+ dtls1_start_timer(s);
+ ret = ssl3_send_certificate_request(s);
+ if (ret <= 0) {
+ goto end;
+ }
+#ifndef NETSCAPE_HANG_BUG
+ s->state = SSL3_ST_SW_SRVR_DONE_A;
+#else
+ s->state = SSL3_ST_SW_FLUSH;
+ s->s3->tmp.next_state = SSL3_ST_SR_CERT_A;
+#endif
+ s->init_num = 0;
+ }
+ break;
+
+ case SSL3_ST_SW_SRVR_DONE_A:
+ case SSL3_ST_SW_SRVR_DONE_B:
+ dtls1_start_timer(s);
+ ret = ssl3_send_server_done(s);
+ if (ret <= 0) {
+ goto end;
+ }
+ s->s3->tmp.next_state = SSL3_ST_SR_CERT_A;
+ s->state = SSL3_ST_SW_FLUSH;
+ s->init_num = 0;
+ break;
+
+ case SSL3_ST_SW_FLUSH:
+ s->rwstate = SSL_WRITING;
+ if (BIO_flush(s->wbio) <= 0) {
+ /* If the write error was fatal, stop trying */
+ if (!BIO_should_retry(s->wbio)) {
+ s->rwstate = SSL_NOTHING;
+ s->state = s->s3->tmp.next_state;
+ }
+
+ ret = -1;
+ goto end;
+ }
+ s->rwstate = SSL_NOTHING;
+ s->state = s->s3->tmp.next_state;
+ break;
+
+ case SSL3_ST_SR_CERT_A:
+ case SSL3_ST_SR_CERT_B:
+ if (s->s3->tmp.cert_request) {
+ ret = ssl3_get_client_certificate(s);
+ if (ret <= 0) {
+ goto end;
+ }
+ }
+ s->init_num = 0;
+ s->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;
+ }
+ s->state = SSL3_ST_SR_CERT_VRFY_A;
+ s->init_num = 0;
+ break;
+
+ case SSL3_ST_SR_CERT_VRFY_A:
+ case SSL3_ST_SR_CERT_VRFY_B:
+ ret = ssl3_get_cert_verify(s);
+ if (ret <= 0) {
+ goto end;
+ }
+ s->state = SSL3_ST_SR_FINISHED_A;
+ s->init_num = 0;
+ break;
+
+ case SSL3_ST_SR_FINISHED_A:
+ case SSL3_ST_SR_FINISHED_B:
+ s->d1->change_cipher_spec_ok = 1;
+ ret =
+ ssl3_get_finished(s, SSL3_ST_SR_FINISHED_A, SSL3_ST_SR_FINISHED_B);
+ if (ret <= 0) {
+ goto end;
+ }
+ dtls1_stop_timer(s);
+ if (s->hit) {
+ s->state = SSL_ST_OK;
+ } else if (s->tlsext_ticket_expected) {
+ s->state = SSL3_ST_SW_SESSION_TICKET_A;
+ } else {
+ s->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_new_session_ticket(s);
+ if (ret <= 0) {
+ goto end;
+ }
+ s->state = SSL3_ST_SW_CHANGE_A;
+ s->init_num = 0;
+ break;
+
+ case SSL3_ST_SW_CHANGE_A:
+ case SSL3_ST_SW_CHANGE_B:
+ s->session->cipher = s->s3->tmp.new_cipher;
+ if (!s->enc_method->setup_key_block(s)) {
+ ret = -1;
+ goto end;
+ }
+
+ ret = dtls1_send_change_cipher_spec(s, SSL3_ST_SW_CHANGE_A,
+ SSL3_ST_SW_CHANGE_B);
+
+ if (ret <= 0) {
+ goto end;
+ }
+
+ s->state = SSL3_ST_SW_FINISHED_A;
+ s->init_num = 0;
+
+ if (!s->enc_method->change_cipher_state(
+ s, SSL3_CHANGE_CIPHER_SERVER_WRITE)) {
+ ret = -1;
+ goto end;
+ }
+
+ dtls1_reset_seq_numbers(s, SSL3_CC_WRITE);
+ break;
+
+ case SSL3_ST_SW_FINISHED_A:
+ case SSL3_ST_SW_FINISHED_B:
+ ret =
+ ssl3_send_finished(s, SSL3_ST_SW_FINISHED_A, SSL3_ST_SW_FINISHED_B,
+ s->enc_method->server_finished_label,
+ s->enc_method->server_finished_label_len);
+ if (ret <= 0) {
+ goto end;
+ }
+ s->state = SSL3_ST_SW_FLUSH;
+ if (s->hit) {
+ s->s3->tmp.next_state = SSL3_ST_SR_FINISHED_A;
+ } else {
+ s->s3->tmp.next_state = SSL_ST_OK;
+ }
+ s->init_num = 0;
+ break;
+
+ case SSL_ST_OK:
+ ssl3_cleanup_key_block(s);
+
+ /* remove buffering on output */
+ ssl_free_wbio_buffer(s);
+
+ s->init_num = 0;
+
+ if (s->renegotiate == 2) {
+ /* skipped if we just sent a HelloRequest */
+ s->renegotiate = 0;
+ s->new_session = 0;
+
+ ssl_update_cache(s, SSL_SESS_CACHE_SERVER);
+
+ s->ctx->stats.sess_accept_good++;
+
+ if (cb != NULL) {
+ cb(s, SSL_CB_HANDSHAKE_DONE, 1);
+ }
+ }
+
+ ret = 1;
+
+ /* 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;
+
+ default:
+ OPENSSL_PUT_ERROR(SSL, dtls1_accept, SSL_R_UNKNOWN_STATE);
+ ret = -1;
+ goto end;
+ }
+
+ if (!s->s3->tmp.reuse_message && !skip) {
+ if (cb != NULL && s->state != state) {
+ new_state = s->state;
+ s->state = state;
+ cb(s, SSL_CB_ACCEPT_LOOP, 1);
+ s->state = new_state;
+ }
+ }
+ skip = 0;
+ }
+
+end:
+ s->in_handshake--;
+ if (buf != NULL) {
+ BUF_MEM_free(buf);
+ }
+ if (cb != NULL) {
+ cb(s, SSL_CB_ACCEPT_EXIT, ret);
+ }
+ return ret;
+}
+
+int dtls1_send_hello_verify_request(SSL *s) {
+ uint8_t *msg, *p;
+
+ if (s->state == DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A) {
+ msg = p = ssl_handshake_start(s);
+ /* Always use DTLS 1.0 version: see RFC 6347 */
+ *(p++) = DTLS1_VERSION >> 8;
+ *(p++) = DTLS1_VERSION & 0xFF;
+
+ /* Inform the callback how much space is in the
+ * cookie's buffer. */
+ s->d1->cookie_len = sizeof(s->d1->cookie);
+
+ if (s->ctx->app_gen_cookie_cb == NULL ||
+ s->ctx->app_gen_cookie_cb(s, s->d1->cookie, &(s->d1->cookie_len)) ==
+ 0) {
+ OPENSSL_PUT_ERROR(SSL, dtls1_send_hello_verify_request,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ *(p++) = (uint8_t)s->d1->cookie_len;
+ memcpy(p, s->d1->cookie, s->d1->cookie_len);
+ p += s->d1->cookie_len;
+
+ ssl_set_handshake_header(s, DTLS1_MT_HELLO_VERIFY_REQUEST, p - msg);
+ s->state = DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B;
+ }
+
+ /* s->state = DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B */
+ return ssl_do_write(s);
+}
diff --git a/src/ssl/pqueue/CMakeLists.txt b/src/ssl/pqueue/CMakeLists.txt
new file mode 100644
index 0000000..9f14020
--- /dev/null
+++ b/src/ssl/pqueue/CMakeLists.txt
@@ -0,0 +1,17 @@
+include_directories(../../include)
+
+add_library(
+ pqueue
+
+ OBJECT
+
+ pqueue.c
+)
+
+add_executable(
+ pqueue_test
+
+ pqueue_test.c
+)
+
+target_link_libraries(pqueue_test ssl crypto)
diff --git a/src/ssl/pqueue/pqueue.c b/src/ssl/pqueue/pqueue.c
new file mode 100644
index 0000000..ecaa139
--- /dev/null
+++ b/src/ssl/pqueue/pqueue.c
@@ -0,0 +1,194 @@
+/*
+ * 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 <openssl/pqueue.h>
+
+#include <string.h>
+
+#include <openssl/mem.h>
+
+
+typedef struct _pqueue {
+ pitem *items;
+ unsigned count;
+} pqueue_s;
+
+
+pitem *pitem_new(uint8_t prio64be[8], void *data) {
+ pitem *item = (pitem *)OPENSSL_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) {
+ if (item == NULL) {
+ return;
+ }
+
+ OPENSSL_free(item);
+}
+
+pqueue pqueue_new(void) {
+ pqueue_s *pq = (pqueue_s *)OPENSSL_malloc(sizeof(pqueue_s));
+ if (pq == NULL) {
+ return NULL;
+ }
+
+ memset(pq, 0, sizeof(pqueue_s));
+ return pq;
+}
+
+void pqueue_free(pqueue_s *pq) {
+ if (pq == NULL) {
+ return;
+ }
+
+ OPENSSL_free(pq);
+}
+
+pitem *pqueue_peek(pqueue_s *pq) { return pq->items; }
+
+pitem *pqueue_find(pqueue_s *pq, uint8_t *prio64be) {
+ pitem *curr;
+
+ for (curr = pq->items; curr; curr = curr->next) {
+ if (memcmp(curr->priority, prio64be, sizeof(curr->priority)) == 0) {
+ return curr;
+ }
+ }
+
+ return NULL;
+}
+
+size_t pqueue_size(pqueue_s *pq) {
+ pitem *item = pq->items;
+ size_t count = 0;
+
+ while (item != NULL) {
+ count++;
+ item = item->next;
+ }
+ return count;
+}
+
+piterator pqueue_iterator(pqueue_s *pq) { return pq->items; }
+
+pitem *pqueue_next(piterator *item) {
+ pitem *ret;
+
+ if (item == NULL || *item == NULL) {
+ return NULL;
+ }
+
+ ret = *item;
+ *item = (*item)->next;
+
+ return ret;
+}
+
+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_pop(pqueue_s *pq) {
+ pitem *item = pq->items;
+
+ if (pq->items != NULL) {
+ pq->items = pq->items->next;
+ }
+
+ return item;
+}
diff --git a/src/ssl/pqueue/pqueue_test.c b/src/ssl/pqueue/pqueue_test.c
new file mode 100644
index 0000000..c4b4b9d
--- /dev/null
+++ b/src/ssl/pqueue/pqueue_test.c
@@ -0,0 +1,117 @@
+/* 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 <stdio.h>
+#include <string.h>
+
+#include <openssl/pqueue.h>
+#include <openssl/ssl.h>
+
+
+static int trivial(void) {
+ pqueue q = pqueue_new();
+ if (q == NULL) {
+ return 0;
+ }
+ int32_t data = 0xdeadbeef;
+ uint8_t priority[8] = {0};
+ pitem *item = pitem_new(priority, &data);
+ if (item == NULL ||
+ pqueue_insert(q, item) != item ||
+ pqueue_size(q) != 1 ||
+ pqueue_peek(q) != item ||
+ pqueue_pop(q) != item ||
+ pqueue_size(q) != 0 ||
+ pqueue_pop(q) != NULL) {
+ return 0;
+ }
+ pitem_free(item);
+ pqueue_free(q);
+ return 1;
+}
+
+#define NUM_ITEMS 10
+
+static int fixed_random(void) {
+ /* Random order of 10 elements, chosen by
+ * random.choice(list(itertools.permutations(range(10)))) */
+ int ordering[NUM_ITEMS] = {9, 6, 3, 4, 0, 2, 7, 1, 8, 5};
+ int i;
+ pqueue q = pqueue_new();
+ uint8_t priority[8] = {0};
+ piterator iter;
+ pitem *curr, *item;
+
+ if (q == NULL) {
+ return 0;
+ }
+
+ /* Insert the elements */
+ for (i = 0; i < NUM_ITEMS; i++) {
+ priority[7] = ordering[i];
+ item = pitem_new(priority, &ordering[i]);
+ if (pqueue_insert(q, item) != item) {
+ return 0;
+ }
+ }
+
+ /* Insert the elements again. This inserts duplicates and should
+ * fail. */
+ for (i = 0; i < NUM_ITEMS; i++) {
+ priority[7] = ordering[i];
+ item = pitem_new(priority, &ordering[i]);
+ if (pqueue_insert(q, item) != NULL) {
+ return 0;
+ }
+ pitem_free(item);
+ }
+
+ if (pqueue_size(q) != NUM_ITEMS) {
+ return 0;
+ }
+
+ /* Iterate over the elements. */
+ iter = pqueue_iterator(q);
+ curr = pqueue_next(&iter);
+ if (curr == NULL) {
+ return 0;
+ }
+ while (1) {
+ pitem *next = pqueue_next(&iter);
+ int *curr_data, *next_data;
+
+ if (next == NULL) {
+ break;
+ }
+ curr_data = (int*)curr->data;
+ next_data = (int*)next->data;
+ if (*curr_data >= *next_data) {
+ return 0;
+ }
+ curr = next;
+ }
+ pqueue_free(q);
+ return 1;
+}
+
+int main(void) {
+ SSL_library_init();
+
+ if (!trivial() || !fixed_random()) {
+ return 1;
+ }
+
+ printf("PASS\n");
+ return 0;
+}
diff --git a/src/ssl/s3_both.c b/src/ssl/s3_both.c
new file mode 100644
index 0000000..a34d221
--- /dev/null
+++ b/src/ssl/s3_both.c
@@ -0,0 +1,699 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <assert.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <openssl/buf.h>
+#include <openssl/evp.h>
+#include <openssl/mem.h>
+#include <openssl/md5.h>
+#include <openssl/obj.h>
+#include <openssl/rand.h>
+#include <openssl/sha.h>
+#include <openssl/x509.h>
+
+#include "ssl_locl.h"
+
+
+/* ssl3_do_write sends |s->init_buf| in records of type 'type'
+ * (SSL3_RT_HANDSHAKE or SSL3_RT_CHANGE_CIPHER_SPEC). It returns -1 on error, 1
+ * on success or zero if the transmission is still incomplete. */
+int ssl3_do_write(SSL *s, int type) {
+ int n;
+
+ n = ssl3_write_bytes(s, type, &s->init_buf->data[s->init_off], s->init_num);
+ if (n < 0) {
+ return -1;
+ }
+
+ if (n == 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);
+ }
+ return 1;
+ }
+
+ s->init_off += n;
+ s->init_num -= n;
+ return 0;
+}
+
+int ssl3_send_finished(SSL *s, int a, int b, const char *sender, int slen) {
+ uint8_t *p;
+ int n;
+
+ if (s->state == a) {
+ p = ssl_handshake_start(s);
+
+ n = s->enc_method->final_finish_mac(s, sender, slen, s->s3->tmp.finish_md);
+ if (n == 0) {
+ return 0;
+ }
+ s->s3->tmp.finish_md_len = n;
+ memcpy(p, s->s3->tmp.finish_md, n);
+
+ /* Log the master secret, if logging is enabled. */
+ if (!ssl_ctx_log_master_secret(s->ctx, s->s3->client_random,
+ SSL3_RANDOM_SIZE, s->session->master_key,
+ s->session->master_key_length)) {
+ return 0;
+ }
+
+ /* Copy the finished so we can use it for
+ * renegotiation checks */
+ if (s->server) {
+ assert(n <= EVP_MAX_MD_SIZE);
+ memcpy(s->s3->previous_server_finished, s->s3->tmp.finish_md, n);
+ s->s3->previous_server_finished_len = n;
+ } else {
+ assert(n <= EVP_MAX_MD_SIZE);
+ memcpy(s->s3->previous_client_finished, s->s3->tmp.finish_md, n);
+ s->s3->previous_client_finished_len = n;
+ }
+
+ ssl_set_handshake_header(s, SSL3_MT_FINISHED, n);
+ s->state = b;
+ }
+
+ /* SSL3_ST_SEND_xxxxxx_HELLO_B */
+ return ssl_do_write(s);
+}
+
+/* ssl3_take_mac calculates the Finished MAC for the handshakes messages seen to
+ * far. */
+static void ssl3_take_mac(SSL *s) {
+ const char *sender;
+ int slen;
+
+ /* If no new cipher setup then return immediately: other functions will set
+ * the appropriate error. */
+ if (s->s3->tmp.new_cipher == NULL) {
+ return;
+ }
+
+ if (s->state & SSL_ST_CONNECT) {
+ sender = s->enc_method->server_finished_label;
+ slen = s->enc_method->server_finished_label_len;
+ } else {
+ sender = s->enc_method->client_finished_label;
+ slen = s->enc_method->client_finished_label_len;
+ }
+
+ s->s3->tmp.peer_finish_md_len = s->enc_method->final_finish_mac(
+ s, sender, slen, s->s3->tmp.peer_finish_md);
+}
+
+int ssl3_get_finished(SSL *s, int a, int b) {
+ int al, finished_len, ok;
+ long message_len;
+ uint8_t *p;
+
+ message_len =
+ s->method->ssl_get_message(s, a, b, SSL3_MT_FINISHED, EVP_MAX_MD_SIZE,
+ SSL_GET_MESSAGE_DONT_HASH_MESSAGE, &ok);
+
+ if (!ok) {
+ return message_len;
+ }
+
+ /* Snapshot the finished hash before incorporating the new message. */
+ ssl3_take_mac(s);
+ ssl3_hash_current_message(s);
+
+ /* If this occurs, we have missed a message.
+ * TODO(davidben): Is this check now redundant with SSL3_FLAGS_EXPECT_CCS? */
+ if (!s->s3->change_cipher_spec) {
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_finished, SSL_R_GOT_A_FIN_BEFORE_A_CCS);
+ goto f_err;
+ }
+ s->s3->change_cipher_spec = 0;
+
+ p = s->init_msg;
+ finished_len = s->s3->tmp.peer_finish_md_len;
+
+ if (finished_len != message_len) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_finished, SSL_R_BAD_DIGEST_LENGTH);
+ goto f_err;
+ }
+
+ if (CRYPTO_memcmp(p, s->s3->tmp.peer_finish_md, finished_len) != 0) {
+ al = SSL_AD_DECRYPT_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_finished, SSL_R_DIGEST_CHECK_FAILED);
+ goto f_err;
+ }
+
+ /* Copy the finished so we can use it for renegotiation checks */
+ if (s->server) {
+ assert(finished_len <= EVP_MAX_MD_SIZE);
+ memcpy(s->s3->previous_client_finished, s->s3->tmp.peer_finish_md, finished_len);
+ s->s3->previous_client_finished_len = finished_len;
+ } else {
+ assert(finished_len <= EVP_MAX_MD_SIZE);
+ memcpy(s->s3->previous_server_finished, s->s3->tmp.peer_finish_md, finished_len);
+ s->s3->previous_server_finished_len = finished_len;
+ }
+
+ return 1;
+
+f_err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ return 0;
+}
+
+/* for these 2 messages, we need to
+ * ssl->enc_read_ctx re-init
+ * ssl->s3->read_sequence zero
+ * ssl->s3->read_mac_secret re-init
+ * ssl->session->read_sym_enc assign
+ * ssl->session->read_compression assign
+ * ssl->session->read_hash assign */
+int ssl3_send_change_cipher_spec(SSL *s, int a, int b) {
+ if (s->state == a) {
+ *((uint8_t *)s->init_buf->data) = SSL3_MT_CCS;
+ s->init_num = 1;
+ s->init_off = 0;
+
+ s->state = b;
+ }
+
+ /* SSL3_ST_CW_CHANGE_B */
+ return ssl3_do_write(s, SSL3_RT_CHANGE_CIPHER_SPEC);
+}
+
+unsigned long ssl3_output_cert_chain(SSL *s, CERT_PKEY *cpk) {
+ uint8_t *p;
+ unsigned long l = 3 + SSL_HM_HEADER_LENGTH(s);
+
+ if (!ssl_add_cert_chain(s, cpk, &l)) {
+ return 0;
+ }
+
+ l -= 3 + SSL_HM_HEADER_LENGTH(s);
+ p = ssl_handshake_start(s);
+ l2n3(l, p);
+ l += 3;
+ ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE, l);
+ return l + SSL_HM_HEADER_LENGTH(s);
+}
+
+/* Obtain handshake message of message type |msg_type| (any if |msg_type| == -1),
+ * maximum acceptable body length |max|. The first four bytes (msg_type and
+ * length) are read in state |header_state|, the body is read in state |body_state|. */
+long ssl3_get_message(SSL *s, int header_state, int body_state, int msg_type,
+ long max, int hash_message, int *ok) {
+ uint8_t *p;
+ unsigned long l;
+ long n;
+ int al;
+
+ if (s->s3->tmp.reuse_message) {
+ /* A SSL_GET_MESSAGE_DONT_HASH_MESSAGE call cannot be combined with
+ * reuse_message; the SSL_GET_MESSAGE_DONT_HASH_MESSAGE would have to have
+ * been applied to the previous call. */
+ assert(hash_message != SSL_GET_MESSAGE_DONT_HASH_MESSAGE);
+ s->s3->tmp.reuse_message = 0;
+ if (msg_type >= 0 && s->s3->tmp.message_type != msg_type) {
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_message, SSL_R_UNEXPECTED_MESSAGE);
+ goto f_err;
+ }
+ *ok = 1;
+ s->state = body_state;
+ s->init_msg = (uint8_t *)s->init_buf->data + 4;
+ s->init_num = (int)s->s3->tmp.message_size;
+ return s->init_num;
+ }
+
+ p = (uint8_t *)s->init_buf->data;
+
+ if (s->state == header_state) {
+ assert(s->init_num < 4);
+
+ for (;;) {
+ while (s->init_num < 4) {
+ int bytes_read = s->method->ssl_read_bytes(
+ s, SSL3_RT_HANDSHAKE, &p[s->init_num], 4 - s->init_num, 0);
+ if (bytes_read <= 0) {
+ s->rwstate = SSL_READING;
+ *ok = 0;
+ return bytes_read;
+ }
+ s->init_num += bytes_read;
+ }
+
+ static const uint8_t kHelloRequest[4] = {SSL3_MT_HELLO_REQUEST, 0, 0, 0};
+ if (s->server || memcmp(p, kHelloRequest, sizeof(kHelloRequest)) != 0) {
+ break;
+ }
+
+ /* 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. */
+ s->init_num = 0;
+
+ if (s->msg_callback) {
+ s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, p, 4, s,
+ s->msg_callback_arg);
+ }
+ }
+
+ /* s->init_num == 4 */
+
+ if (msg_type >= 0 && *p != msg_type) {
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_message, SSL_R_UNEXPECTED_MESSAGE);
+ goto f_err;
+ }
+ s->s3->tmp.message_type = *(p++);
+
+ n2l3(p, l);
+ if (l > (unsigned long)max) {
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_message, SSL_R_EXCESSIVE_MESSAGE_SIZE);
+ goto f_err;
+ }
+
+ if (l && !BUF_MEM_grow_clean(s->init_buf, l + 4)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_message, ERR_R_BUF_LIB);
+ goto err;
+ }
+ s->s3->tmp.message_size = l;
+ s->state = body_state;
+
+ s->init_msg = (uint8_t *)s->init_buf->data + 4;
+ s->init_num = 0;
+ }
+
+ /* next state (body_state) */
+ p = s->init_msg;
+ n = s->s3->tmp.message_size - s->init_num;
+ while (n > 0) {
+ int bytes_read =
+ s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, &p[s->init_num], n, 0);
+ if (bytes_read <= 0) {
+ s->rwstate = SSL_READING;
+ *ok = 0;
+ return bytes_read;
+ }
+ s->init_num += bytes_read;
+ n -= bytes_read;
+ }
+
+ /* Feed this message into MAC computation. */
+ if (hash_message != SSL_GET_MESSAGE_DONT_HASH_MESSAGE) {
+ ssl3_hash_current_message(s);
+ }
+ if (s->msg_callback) {
+ s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, s->init_buf->data,
+ (size_t)s->init_num + 4, s, s->msg_callback_arg);
+ }
+ *ok = 1;
+ return s->init_num;
+
+f_err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+
+err:
+ *ok = 0;
+ return -1;
+}
+
+void ssl3_hash_current_message(SSL *s) {
+ /* The handshake header (different size between DTLS and TLS) is included in
+ * the hash. */
+ size_t header_len = s->init_msg - (uint8_t *)s->init_buf->data;
+ ssl3_finish_mac(s, (uint8_t *)s->init_buf->data, s->init_num + header_len);
+}
+
+/* ssl3_cert_verify_hash is documented as needing EVP_MAX_MD_SIZE because that
+ * is sufficient pre-TLS1.2 as well. */
+OPENSSL_COMPILE_ASSERT(EVP_MAX_MD_SIZE > MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH,
+ combined_tls_hash_fits_in_max);
+
+int ssl3_cert_verify_hash(SSL *s, uint8_t *out, size_t *out_len,
+ const EVP_MD **out_md, EVP_PKEY *pkey) {
+ /* For TLS v1.2 send signature algorithm and signature using
+ * agreed digest and cached handshake records. Otherwise, use
+ * SHA1 or MD5 + SHA1 depending on key type. */
+ if (SSL_USE_SIGALGS(s)) {
+ const uint8_t *hdata;
+ size_t hdatalen;
+ EVP_MD_CTX mctx;
+ unsigned len;
+
+ if (!BIO_mem_contents(s->s3->handshake_buffer, &hdata, &hdatalen)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_cert_verify_hash, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ EVP_MD_CTX_init(&mctx);
+ if (!EVP_DigestInit_ex(&mctx, *out_md, NULL) ||
+ !EVP_DigestUpdate(&mctx, hdata, hdatalen) ||
+ !EVP_DigestFinal(&mctx, out, &len)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_cert_verify_hash, ERR_R_EVP_LIB);
+ EVP_MD_CTX_cleanup(&mctx);
+ return 0;
+ }
+ *out_len = len;
+ } else if (pkey->type == EVP_PKEY_RSA) {
+ if (s->enc_method->cert_verify_mac(s, NID_md5, out) == 0 ||
+ s->enc_method->cert_verify_mac(s, NID_sha1, out + MD5_DIGEST_LENGTH) ==
+ 0) {
+ return 0;
+ }
+ *out_len = MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH;
+ *out_md = EVP_md5_sha1();
+ } else if (pkey->type == EVP_PKEY_EC) {
+ if (s->enc_method->cert_verify_mac(s, NID_sha1, out) == 0) {
+ return 0;
+ }
+ *out_len = SHA_DIGEST_LENGTH;
+ *out_md = EVP_sha1();
+ } else {
+ OPENSSL_PUT_ERROR(SSL, ssl3_cert_verify_hash, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ return 1;
+}
+
+int ssl_cert_type(EVP_PKEY *pkey) {
+ switch (pkey->type) {
+ case EVP_PKEY_RSA:
+ return SSL_PKEY_RSA_ENC;
+ case EVP_PKEY_EC:
+ return SSL_PKEY_ECC;
+ default:
+ 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_read_buffer(SSL *s) {
+ uint8_t *p;
+ size_t len, align = 0, headerlen;
+
+ if (SSL_IS_DTLS(s)) {
+ headerlen = DTLS1_RT_HEADER_LENGTH;
+ } else {
+ headerlen = SSL3_RT_HEADER_LENGTH;
+ }
+
+#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD != 0
+ align = (-SSL3_RT_HEADER_LENGTH) & (SSL3_ALIGN_PAYLOAD - 1);
+#endif
+
+ if (s->s3->rbuf.buf == NULL) {
+ len = SSL3_RT_MAX_PLAIN_LENGTH + SSL3_RT_MAX_ENCRYPTED_OVERHEAD +
+ headerlen + align;
+ if (s->options & SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER) {
+ s->s3->init_extra = 1;
+ len += SSL3_RT_MAX_EXTRA;
+ }
+ p = OPENSSL_malloc(len);
+ if (p == NULL) {
+ goto err;
+ }
+ s->s3->rbuf.buf = p;
+ s->s3->rbuf.len = len;
+ }
+
+ s->packet = &s->s3->rbuf.buf[0];
+ return 1;
+
+err:
+ OPENSSL_PUT_ERROR(SSL, ssl3_setup_read_buffer, ERR_R_MALLOC_FAILURE);
+ return 0;
+}
+
+int ssl3_setup_write_buffer(SSL *s) {
+ uint8_t *p;
+ size_t len, align = 0, headerlen;
+
+ if (SSL_IS_DTLS(s)) {
+ headerlen = DTLS1_RT_HEADER_LENGTH + 1;
+ } else {
+ headerlen = SSL3_RT_HEADER_LENGTH;
+ }
+
+#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD != 0
+ align = (-SSL3_RT_HEADER_LENGTH) & (SSL3_ALIGN_PAYLOAD - 1);
+#endif
+
+ if (s->s3->wbuf.buf == NULL) {
+ len = s->max_send_fragment + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD +
+ headerlen + align;
+ /* Account for 1/n-1 record splitting. */
+ if (s->mode & SSL_MODE_CBC_RECORD_SPLITTING) {
+ len += headerlen + align + 1 + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD;
+ }
+
+ p = OPENSSL_malloc(len);
+ if (p == NULL) {
+ goto err;
+ }
+ s->s3->wbuf.buf = p;
+ s->s3->wbuf.len = len;
+ }
+
+ return 1;
+
+err:
+ OPENSSL_PUT_ERROR(SSL, ssl3_setup_write_buffer, ERR_R_MALLOC_FAILURE);
+ return 0;
+}
+
+
+int ssl3_setup_buffers(SSL *s) {
+ if (!ssl3_setup_read_buffer(s) ||
+ !ssl3_setup_write_buffer(s)) {
+ return 0;
+ }
+ return 1;
+}
+
+int ssl3_release_write_buffer(SSL *s) {
+ if (s->s3->wbuf.buf != NULL) {
+ OPENSSL_free(s->s3->wbuf.buf);
+ s->s3->wbuf.buf = NULL;
+ }
+ return 1;
+}
+
+int ssl3_release_read_buffer(SSL *s) {
+ if (s->s3->rbuf.buf != NULL) {
+ OPENSSL_free(s->s3->rbuf.buf);
+ s->s3->rbuf.buf = NULL;
+ }
+ return 1;
+}
+
+/* ssl_fill_hello_random fills a client_random or server_random field of length
+ * |len|. Returns 0 on failure or 1 on success. */
+int ssl_fill_hello_random(SSL *s, int server, uint8_t *result, size_t len) {
+ int send_time = 0;
+
+ if (server) {
+ send_time = (s->mode & SSL_MODE_SEND_SERVERHELLO_TIME) != 0;
+ } else {
+ send_time = (s->mode & SSL_MODE_SEND_CLIENTHELLO_TIME) != 0;
+ }
+
+ if (send_time) {
+ const uint32_t current_time = time(NULL);
+ uint8_t *p = result;
+
+ if (len < 4) {
+ return 0;
+ }
+ p[0] = current_time >> 24;
+ p[1] = current_time >> 16;
+ p[2] = current_time >> 8;
+ p[3] = current_time;
+ return RAND_bytes(p + 4, len - 4);
+ } else {
+ return RAND_bytes(result, len);
+ }
+}
diff --git a/src/ssl/s3_clnt.c b/src/ssl/s3_clnt.c
new file mode 100644
index 0000000..231cc65
--- /dev/null
+++ b/src/ssl/s3_clnt.c
@@ -0,0 +1,2417 @@
+/* ssl/s3_clnt.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.]
+ */
+/* ====================================================================
+ * 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 <assert.h>
+#include <stdio.h>
+
+#include <openssl/buf.h>
+#include <openssl/bytestring.h>
+#include <openssl/rand.h>
+#include <openssl/obj.h>
+#include <openssl/evp.h>
+#include <openssl/mem.h>
+#include <openssl/md5.h>
+#include <openssl/dh.h>
+#include <openssl/bn.h>
+#include <openssl/engine.h>
+#include <openssl/x509.h>
+
+#include "ssl_locl.h"
+#include "../crypto/dh/internal.h"
+
+
+int ssl3_connect(SSL *s) {
+ BUF_MEM *buf = NULL;
+ void (*cb)(const SSL *ssl, int type, int val) = NULL;
+ int ret = -1;
+ int new_state, state, skip = 0;
+
+ assert(s->handshake_func == ssl3_connect);
+ assert(!s->server);
+ assert(!SSL_IS_DTLS(s));
+
+ ERR_clear_error();
+ ERR_clear_system_error();
+
+ if (s->info_callback != NULL) {
+ cb = s->info_callback;
+ } else if (s->ctx->info_callback != NULL) {
+ cb = s->ctx->info_callback;
+ }
+
+ s->in_handshake++;
+
+ for (;;) {
+ state = s->state;
+
+ switch (s->state) {
+ case SSL_ST_RENEGOTIATE:
+ s->renegotiate = 1;
+ s->state = SSL_ST_CONNECT;
+ s->ctx->stats.sess_connect_renegotiate++;
+ /* fallthrough */
+ case SSL_ST_CONNECT:
+ case SSL_ST_BEFORE | SSL_ST_CONNECT:
+ if (cb != NULL)
+ cb(s, SSL_CB_HANDSHAKE_START, 1);
+
+ if (s->init_buf == NULL) {
+ buf = BUF_MEM_new();
+ if (buf == NULL ||
+ !BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) {
+ ret = -1;
+ goto end;
+ }
+
+ s->init_buf = buf;
+ buf = NULL;
+ }
+
+ if (!ssl3_setup_buffers(s) ||
+ !ssl_init_wbio_buffer(s, 0)) {
+ ret = -1;
+ goto end;
+ }
+
+ /* don't push the buffering BIO quite yet */
+
+ if (!ssl3_init_finished_mac(s)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_connect, ERR_R_INTERNAL_ERROR);
+ ret = -1;
+ goto end;
+ }
+
+ s->state = SSL3_ST_CW_CLNT_HELLO_A;
+ s->ctx->stats.sess_connect++;
+ s->init_num = 0;
+ break;
+
+ case SSL3_ST_CW_CLNT_HELLO_A:
+ case SSL3_ST_CW_CLNT_HELLO_B:
+ s->shutdown = 0;
+ ret = ssl3_send_client_hello(s);
+ if (ret <= 0) {
+ goto end;
+ }
+ s->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->state = SSL3_ST_CR_CHANGE;
+ if (s->tlsext_ticket_expected) {
+ /* receive renewed session ticket */
+ s->state = SSL3_ST_CR_SESSION_TICKET_A;
+ }
+ } else {
+ s->state = SSL3_ST_CR_CERT_A;
+ }
+ s->init_num = 0;
+ break;
+
+ case SSL3_ST_CR_CERT_A:
+ case SSL3_ST_CR_CERT_B:
+ if (ssl_cipher_has_server_public_key(s->s3->tmp.new_cipher)) {
+ ret = ssl3_get_server_certificate(s);
+ if (ret <= 0) {
+ goto end;
+ }
+ if (s->s3->tmp.certificate_status_expected) {
+ s->state = SSL3_ST_CR_CERT_STATUS_A;
+ } else {
+ s->state = SSL3_ST_CR_KEY_EXCH_A;
+ }
+ } else {
+ skip = 1;
+ s->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->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->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 (s->s3->tmp.cert_req) {
+ s->state = SSL3_ST_CW_CERT_A;
+ } else {
+ s->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:
+ ret = ssl3_send_client_certificate(s);
+ if (ret <= 0) {
+ goto end;
+ }
+ s->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:
+ ret = ssl3_send_client_key_exchange(s);
+ if (ret <= 0) {
+ goto end;
+ }
+ /* For TLS, cert_req is set to 2, so a cert chain
+ * of nothing is sent, but no verify packet is sent */
+ if (s->s3->tmp.cert_req == 1) {
+ s->state = SSL3_ST_CW_CERT_VRFY_A;
+ } else {
+ s->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:
+ ret = ssl3_send_cert_verify(s);
+ if (ret <= 0) {
+ goto end;
+ }
+ s->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:
+ ret = ssl3_send_change_cipher_spec(s, SSL3_ST_CW_CHANGE_A,
+ SSL3_ST_CW_CHANGE_B);
+ if (ret <= 0) {
+ goto end;
+ }
+
+ s->state = SSL3_ST_CW_FINISHED_A;
+ if (s->s3->tlsext_channel_id_valid) {
+ s->state = SSL3_ST_CW_CHANNEL_ID_A;
+ }
+ if (s->s3->next_proto_neg_seen) {
+ s->state = SSL3_ST_CW_NEXT_PROTO_A;
+ }
+ s->init_num = 0;
+
+ s->session->cipher = s->s3->tmp.new_cipher;
+ if (!s->enc_method->setup_key_block(s)) {
+ ret = -1;
+ goto end;
+ }
+
+ if (!s->enc_method->change_cipher_state(
+ s, SSL3_CHANGE_CIPHER_CLIENT_WRITE)) {
+ ret = -1;
+ goto end;
+ }
+
+ break;
+
+ case SSL3_ST_CW_NEXT_PROTO_A:
+ case SSL3_ST_CW_NEXT_PROTO_B:
+ ret = ssl3_send_next_proto(s);
+ if (ret <= 0) {
+ goto end;
+ }
+
+ if (s->s3->tlsext_channel_id_valid) {
+ s->state = SSL3_ST_CW_CHANNEL_ID_A;
+ } else {
+ s->state = SSL3_ST_CW_FINISHED_A;
+ }
+ break;
+
+ case SSL3_ST_CW_CHANNEL_ID_A:
+ case SSL3_ST_CW_CHANNEL_ID_B:
+ ret = ssl3_send_channel_id(s);
+ if (ret <= 0) {
+ goto end;
+ }
+ s->state = SSL3_ST_CW_FINISHED_A;
+ break;
+
+ case SSL3_ST_CW_FINISHED_A:
+ case SSL3_ST_CW_FINISHED_B:
+ ret =
+ ssl3_send_finished(s, SSL3_ST_CW_FINISHED_A, SSL3_ST_CW_FINISHED_B,
+ s->enc_method->client_finished_label,
+ s->enc_method->client_finished_label_len);
+ if (ret <= 0) {
+ goto end;
+ }
+ s->state = SSL3_ST_CW_FLUSH;
+
+ if (s->hit) {
+ s->s3->tmp.next_state = SSL_ST_OK;
+ } else {
+ /* This is a non-resumption handshake. If it involves ChannelID, then
+ * record the handshake hashes at this point in the session so that
+ * any resumption of this session with ChannelID can sign those
+ * hashes. */
+ if (s->s3->tlsext_channel_id_new) {
+ ret = tls1_record_handshake_hashes_for_channel_id(s);
+ if (ret <= 0)
+ goto end;
+ }
+ if ((SSL_get_mode(s) & SSL_MODE_HANDSHAKE_CUTTHROUGH) &&
+ ssl3_can_cutthrough(s) &&
+ /* no cutthrough on renegotiation (would complicate the state
+ * machine) */
+ s->s3->previous_server_finished_len == 0) {
+ s->s3->tmp.next_state = SSL3_ST_CUTTHROUGH_COMPLETE;
+ } else {
+ /* Allow NewSessionTicket if ticket expected */
+ if (s->tlsext_ticket_expected) {
+ s->s3->tmp.next_state = SSL3_ST_CR_SESSION_TICKET_A;
+ } else {
+ s->s3->tmp.next_state = SSL3_ST_CR_CHANGE;
+ }
+ }
+ }
+ 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->state = SSL3_ST_CR_CHANGE;
+ 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->state = SSL3_ST_CR_KEY_EXCH_A;
+ s->init_num = 0;
+ break;
+
+ case SSL3_ST_CR_CHANGE:
+ /* At this point, the next message must be entirely behind a
+ * ChangeCipherSpec. */
+ if (!ssl3_expect_change_cipher_spec(s)) {
+ ret = -1;
+ goto end;
+ }
+ s->state = SSL3_ST_CR_FINISHED_A;
+ break;
+
+ case SSL3_ST_CR_FINISHED_A:
+ case SSL3_ST_CR_FINISHED_B:
+ ret =
+ ssl3_get_finished(s, SSL3_ST_CR_FINISHED_A, SSL3_ST_CR_FINISHED_B);
+ if (ret <= 0) {
+ goto end;
+ }
+
+ if (s->hit) {
+ s->state = SSL3_ST_CW_CHANGE_A;
+ } else {
+ s->state = SSL_ST_OK;
+ }
+ s->init_num = 0;
+ break;
+
+ case SSL3_ST_CW_FLUSH:
+ s->rwstate = SSL_WRITING;
+ if (BIO_flush(s->wbio) <= 0) {
+ ret = -1;
+ goto end;
+ }
+ s->rwstate = SSL_NOTHING;
+ s->state = s->s3->tmp.next_state;
+ break;
+
+ case SSL3_ST_CUTTHROUGH_COMPLETE:
+ /* Allow NewSessionTicket if ticket expected */
+ if (s->tlsext_ticket_expected) {
+ s->state = SSL3_ST_CR_SESSION_TICKET_A;
+ } else {
+ s->state = SSL3_ST_CR_CHANGE;
+ }
+
+ ssl_free_wbio_buffer(s);
+ ret = 1;
+ goto end;
+
+ case SSL_ST_OK:
+ /* clean a few things up */
+ ssl3_cleanup_key_block(s);
+
+ if (s->init_buf != NULL) {
+ BUF_MEM_free(s->init_buf);
+ s->init_buf = NULL;
+ }
+
+ /* Remove write buffering now. */
+ 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->ctx->stats.sess_connect_good++;
+
+ if (cb != NULL) {
+ cb(s, SSL_CB_HANDSHAKE_DONE, 1);
+ }
+
+ goto end;
+
+ default:
+ OPENSSL_PUT_ERROR(SSL, ssl3_connect, SSL_R_UNKNOWN_STATE);
+ ret = -1;
+ goto end;
+ }
+
+ if (!s->s3->tmp.reuse_message && !skip) {
+ if (cb != NULL && s->state != state) {
+ new_state = s->state;
+ s->state = state;
+ cb(s, SSL_CB_CONNECT_LOOP, 1);
+ s->state = new_state;
+ }
+ }
+ skip = 0;
+ }
+
+end:
+ s->in_handshake--;
+ if (buf != NULL) {
+ BUF_MEM_free(buf);
+ }
+ if (cb != NULL) {
+ cb(s, SSL_CB_CONNECT_EXIT, ret);
+ }
+ return ret;
+}
+
+int ssl3_send_client_hello(SSL *s) {
+ uint8_t *buf, *p, *d;
+ int i;
+ unsigned long l;
+
+ buf = (uint8_t *)s->init_buf->data;
+ if (s->state == SSL3_ST_CW_CLNT_HELLO_A) {
+ if (!s->s3->have_version) {
+ uint16_t max_version = ssl3_get_max_client_version(s);
+ /* Disabling all versions is silly: return an error. */
+ if (max_version == 0) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_hello, SSL_R_WRONG_SSL_VERSION);
+ goto err;
+ }
+ s->version = max_version;
+ s->client_version = max_version;
+ }
+
+ /* If the configured session was created at a version higher than our
+ * maximum version, drop it. */
+ if (s->session &&
+ (s->session->session_id_length == 0 || s->session->not_resumable ||
+ (!SSL_IS_DTLS(s) && s->session->ssl_version > s->version) ||
+ (SSL_IS_DTLS(s) && s->session->ssl_version < s->version))) {
+ SSL_set_session(s, NULL);
+ }
+
+ /* else use the pre-loaded session */
+ p = s->s3->client_random;
+
+ /* If resending the ClientHello in DTLS after a HelloVerifyRequest, don't
+ * renegerate the client_random. The random must be reused. */
+ if (!SSL_IS_DTLS(s) || !s->d1->send_cookie) {
+ ssl_fill_hello_random(s, 0, p, sizeof(s->s3->client_random));
+ }
+
+ /* Do the message type and length last. Note: the final argument to
+ * ssl_add_clienthello_tlsext below depends on the size of this prefix. */
+ d = p = ssl_handshake_start(s);
+
+ /* version indicates the negotiated version: for example from an SSLv2/v3
+ * compatible client hello). The client_version field is the maximum
+ * version we permit and it is also used in RSA encrypted premaster
+ * secrets. Some servers can choke if we initially report a higher version
+ * then renegotiate to a lower one in the premaster secret. This didn't
+ * happen with TLS 1.0 as most servers supported it but it can with TLS 1.1
+ * or later if the server only supports 1.0.
+ *
+ * Possible scenario with previous logic:
+ * 1. Client hello indicates TLS 1.2
+ * 2. Server hello says TLS 1.0
+ * 3. RSA encrypted premaster secret uses 1.2.
+ * 4. Handhaked proceeds using TLS 1.0.
+ * 5. Server sends hello request to renegotiate.
+ * 6. Client hello indicates TLS v1.0 as we now
+ * know that is maximum server supports.
+ * 7. Server chokes on RSA encrypted premaster secret
+ * containing version 1.0.
+ *
+ * For interoperability it should be OK to always use the maximum version
+ * we support in client hello and then rely on the checking of version to
+ * ensure the servers isn't being inconsistent: for example initially
+ * negotiating with TLS 1.0 and renegotiating with TLS 1.2. We do this by
+ * using client_version in client hello and not resetting it to the
+ * negotiated version. */
+ *(p++) = s->client_version >> 8;
+ *(p++) = s->client_version & 0xff;
+
+ /* Random stuff */
+ memcpy(p, s->s3->client_random, SSL3_RANDOM_SIZE);
+ p += SSL3_RANDOM_SIZE;
+
+ /* Session ID */
+ if (s->new_session || s->session == NULL) {
+ i = 0;
+ } else {
+ i = s->session->session_id_length;
+ }
+ *(p++) = i;
+ if (i != 0) {
+ if (i > (int)sizeof(s->session->session_id)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_hello, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ memcpy(p, s->session->session_id, i);
+ p += i;
+ }
+
+ /* cookie stuff for DTLS */
+ if (SSL_IS_DTLS(s)) {
+ if (s->d1->cookie_len > sizeof(s->d1->cookie)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_hello, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ *(p++) = s->d1->cookie_len;
+ memcpy(p, s->d1->cookie, s->d1->cookie_len);
+ p += s->d1->cookie_len;
+ }
+
+ /* Ciphers supported */
+ i = ssl_cipher_list_to_bytes(s, SSL_get_ciphers(s), &p[2]);
+ if (i == 0) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_hello,
+ SSL_R_NO_CIPHERS_AVAILABLE);
+ goto err;
+ }
+ s2n(i, p);
+ p += i;
+
+ /* COMPRESSION */
+ *(p++) = 1;
+ *(p++) = 0; /* Add the NULL method */
+
+ /* TLS extensions*/
+ if (ssl_prepare_clienthello_tlsext(s) <= 0) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_hello, SSL_R_CLIENTHELLO_TLSEXT);
+ goto err;
+ }
+
+ p = ssl_add_clienthello_tlsext(s, p, buf + SSL3_RT_MAX_PLAIN_LENGTH,
+ p - buf);
+ if (p == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_hello, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ l = p - d;
+ ssl_set_handshake_header(s, SSL3_MT_CLIENT_HELLO, l);
+ s->state = SSL3_ST_CW_CLNT_HELLO_B;
+ }
+
+ /* SSL3_ST_CW_CLNT_HELLO_B */
+ return ssl_do_write(s);
+
+err:
+ return -1;
+}
+
+int ssl3_get_server_hello(SSL *s) {
+ STACK_OF(SSL_CIPHER) * sk;
+ const SSL_CIPHER *c;
+ CERT *ct = s->cert;
+ int al = SSL_AD_INTERNAL_ERROR, ok;
+ long n;
+ CBS server_hello, server_random, session_id;
+ uint16_t server_version, cipher_suite;
+ uint8_t compression_method;
+ unsigned long mask_ssl;
+
+ n = s->method->ssl_get_message(s, SSL3_ST_CR_SRVR_HELLO_A,
+ SSL3_ST_CR_SRVR_HELLO_B, SSL3_MT_SERVER_HELLO,
+ 20000, /* ?? */
+ SSL_GET_MESSAGE_HASH_MESSAGE, &ok);
+
+ if (!ok) {
+ uint32_t err = ERR_peek_error();
+ if (ERR_GET_LIB(err) == ERR_LIB_SSL &&
+ ERR_GET_REASON(err) == SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE) {
+ /* Add a dedicated error code to the queue for a handshake_failure alert
+ * in response to ClientHello. This matches NSS's client behavior and
+ * gives a better error on a (probable) failure to negotiate initial
+ * parameters. Note: this error code comes after the original one.
+ *
+ * See https://crbug.com/446505. */
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello,
+ SSL_R_HANDSHAKE_FAILURE_ON_CLIENT_HELLO);
+ }
+ return n;
+ }
+
+ CBS_init(&server_hello, s->init_msg, n);
+
+ if (!CBS_get_u16(&server_hello, &server_version) ||
+ !CBS_get_bytes(&server_hello, &server_random, SSL3_RANDOM_SIZE) ||
+ !CBS_get_u8_length_prefixed(&server_hello, &session_id) ||
+ CBS_len(&session_id) > SSL3_SESSION_ID_SIZE ||
+ !CBS_get_u16(&server_hello, &cipher_suite) ||
+ !CBS_get_u8(&server_hello, &compression_method)) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, SSL_R_DECODE_ERROR);
+ goto f_err;
+ }
+
+ if (!s->s3->have_version) {
+ if (!ssl3_is_version_enabled(s, server_version)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, SSL_R_UNSUPPORTED_PROTOCOL);
+ s->version = server_version;
+ /* Mark the version as fixed so the record-layer version is not clamped
+ * to TLS 1.0. */
+ s->s3->have_version = 1;
+ al = SSL_AD_PROTOCOL_VERSION;
+ goto f_err;
+ }
+ s->version = server_version;
+ s->enc_method = ssl3_get_enc_method(server_version);
+ assert(s->enc_method != NULL);
+ /* At this point, the connection's version is known and s->version is
+ * fixed. Begin enforcing the record-layer version. */
+ s->s3->have_version = 1;
+ } else if (server_version != s->version) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, SSL_R_WRONG_SSL_VERSION);
+ al = SSL_AD_PROTOCOL_VERSION;
+ goto f_err;
+ }
+
+ /* Copy over the server random. */
+ memcpy(s->s3->server_random, CBS_data(&server_random), SSL3_RANDOM_SIZE);
+
+ assert(s->session == NULL || s->session->session_id_length > 0);
+ if (s->session != NULL && CBS_mem_equal(&session_id, s->session->session_id,
+ s->session->session_id_length)) {
+ if (s->sid_ctx_length != s->session->sid_ctx_length ||
+ memcmp(s->session->sid_ctx, s->sid_ctx, s->sid_ctx_length)) {
+ /* actually a client application bug */
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello,
+ SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT);
+ goto f_err;
+ }
+ s->hit = 1;
+ } else {
+ /* The session wasn't resumed. Create a fresh SSL_SESSION to
+ * fill out. */
+ s->hit = 0;
+ if (!ssl_get_new_session(s, 0)) {
+ goto f_err;
+ }
+ /* Note: session_id could be empty. */
+ s->session->session_id_length = CBS_len(&session_id);
+ memcpy(s->session->session_id, CBS_data(&session_id), CBS_len(&session_id));
+ }
+
+ c = ssl3_get_cipher_by_value(cipher_suite);
+ if (c == NULL) {
+ /* unknown cipher */
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello,
+ SSL_R_UNKNOWN_CIPHER_RETURNED);
+ goto f_err;
+ }
+ /* ct->mask_ssl was computed from client capabilities. Now
+ * that the final version is known, compute a new mask_ssl. */
+ if (!SSL_USE_TLS1_2_CIPHERS(s)) {
+ mask_ssl = SSL_TLSV1_2;
+ } else {
+ mask_ssl = 0;
+ }
+ /* If the cipher is disabled then we didn't sent it in the ClientHello, so if
+ * the server selected it, it's an error. */
+ if ((c->algorithm_ssl & mask_ssl) ||
+ (c->algorithm_mkey & ct->mask_k) ||
+ (c->algorithm_auth & ct->mask_a)) {
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, SSL_R_WRONG_CIPHER_RETURNED);
+ goto f_err;
+ }
+
+ sk = ssl_get_ciphers_by_id(s);
+ if (!sk_SSL_CIPHER_find(sk, NULL, c)) {
+ /* we did not say we would use this cipher */
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, SSL_R_WRONG_CIPHER_RETURNED);
+ goto f_err;
+ }
+
+ if (s->hit && s->session->cipher != c) {
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello,
+ SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED);
+ goto f_err;
+ }
+ s->s3->tmp.new_cipher = c;
+
+ /* Most clients also require that the negotiated version match the session's
+ * version if resuming. However OpenSSL has historically not had the
+ * corresponding logic on the server, so this may not be compatible,
+ * depending on other factors. (Whether the ClientHello version is clamped to
+ * the session's version and whether the session cache is keyed on IP
+ * address.)
+ *
+ * TODO(davidben): See if we can still enforce this? Perhaps for the future
+ * TLS 1.3 and forward if this is fixed upstream. */
+
+ /* Don't digest cached records if no sigalgs: we may need them for client
+ * authentication. */
+ if (!SSL_USE_SIGALGS(s) &&
+ !ssl3_digest_cached_records(s, free_handshake_buffer)) {
+ goto f_err;
+ }
+
+ /* Only the NULL compression algorithm is supported. */
+ if (compression_method != 0) {
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello,
+ SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
+ goto f_err;
+ }
+
+ /* TLS extensions */
+ if (!ssl_parse_serverhello_tlsext(s, &server_hello)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, SSL_R_PARSE_TLSEXT);
+ goto err;
+ }
+
+ /* There should be nothing left over in the record. */
+ if (CBS_len(&server_hello) != 0) {
+ /* wrong packet length */
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, SSL_R_BAD_PACKET_LENGTH);
+ goto f_err;
+ }
+
+ return 1;
+
+f_err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+err:
+ return -1;
+}
+
+int ssl3_get_server_certificate(SSL *s) {
+ int al, i, ok, ret = -1;
+ unsigned long n;
+ X509 *x = NULL;
+ STACK_OF(X509) *sk = NULL;
+ SESS_CERT *sc;
+ EVP_PKEY *pkey = NULL;
+ CBS cbs, certificate_list;
+ const uint8_t *data;
+
+ n = s->method->ssl_get_message(s, SSL3_ST_CR_CERT_A, SSL3_ST_CR_CERT_B,
+ SSL3_MT_CERTIFICATE, s->max_cert_list,
+ SSL_GET_MESSAGE_HASH_MESSAGE, &ok);
+
+ if (!ok) {
+ return n;
+ }
+
+ CBS_init(&cbs, s->init_msg, n);
+
+ sk = sk_X509_new_null();
+ if (sk == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_certificate, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (!CBS_get_u24_length_prefixed(&cbs, &certificate_list) ||
+ CBS_len(&cbs) != 0) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_certificate, SSL_R_LENGTH_MISMATCH);
+ goto f_err;
+ }
+
+ while (CBS_len(&certificate_list) > 0) {
+ CBS certificate;
+ if (!CBS_get_u24_length_prefixed(&certificate_list, &certificate)) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_certificate,
+ SSL_R_CERT_LENGTH_MISMATCH);
+ goto f_err;
+ }
+ data = CBS_data(&certificate);
+ x = d2i_X509(NULL, &data, CBS_len(&certificate));
+ if (x == NULL) {
+ al = SSL_AD_BAD_CERTIFICATE;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_certificate, ERR_R_ASN1_LIB);
+ goto f_err;
+ }
+ if (data != CBS_data(&certificate) + CBS_len(&certificate)) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_certificate,
+ SSL_R_CERT_LENGTH_MISMATCH);
+ goto f_err;
+ }
+ if (!sk_X509_push(sk, x)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_certificate, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ x = NULL;
+ }
+
+ i = ssl_verify_cert_chain(s, sk);
+ if (s->verify_mode != SSL_VERIFY_NONE && i <= 0) {
+ al = ssl_verify_alarm_type(s->verify_result);
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_certificate,
+ SSL_R_CERTIFICATE_VERIFY_FAILED);
+ goto f_err;
+ }
+ ERR_clear_error(); /* but we keep s->verify_result */
+
+ sc = ssl_sess_cert_new();
+ if (sc == NULL) {
+ goto err;
+ }
+
+ if (s->session->sess_cert) {
+ ssl_sess_cert_free(s->session->sess_cert);
+ }
+ s->session->sess_cert = sc;
+
+ sc->cert_chain = sk;
+ /* Inconsistency alert: cert_chain does include the peer's certificate, which
+ * we don't include in s3_srvr.c */
+ x = sk_X509_value(sk, 0);
+ sk = NULL;
+ /* VRS 19990621: possible memory leak; sk=null ==> !sk_pop_free() @end*/
+
+ pkey = X509_get_pubkey(x);
+
+ if (pkey == NULL || EVP_PKEY_missing_parameters(pkey)) {
+ x = NULL;
+ al = SSL3_AL_FATAL;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_certificate,
+ SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS);
+ goto f_err;
+ }
+
+ i = ssl_cert_type(pkey);
+ if (i < 0) {
+ x = NULL;
+ al = SSL3_AL_FATAL;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_certificate,
+ SSL_R_UNKNOWN_CERTIFICATE_TYPE);
+ goto f_err;
+ }
+
+ int exp_idx = ssl_cipher_get_cert_index(s->s3->tmp.new_cipher);
+ if (exp_idx >= 0 && i != exp_idx) {
+ x = NULL;
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_certificate,
+ SSL_R_WRONG_CERTIFICATE_TYPE);
+ goto f_err;
+ }
+ sc->peer_cert_type = i;
+ /* Why would the following ever happen? We just created sc a couple of lines
+ * ago. */
+ if (sc->peer_pkeys[i].x509 != NULL) {
+ X509_free(sc->peer_pkeys[i].x509);
+ }
+ sc->peer_pkeys[i].x509 = X509_up_ref(x);
+ sc->peer_key = &(sc->peer_pkeys[i]);
+
+ if (s->session->peer != NULL) {
+ X509_free(s->session->peer);
+ }
+ s->session->peer = X509_up_ref(x);
+
+ s->session->verify_result = s->verify_result;
+
+ x = NULL;
+ ret = 1;
+
+ if (0) {
+ f_err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ }
+
+err:
+ EVP_PKEY_free(pkey);
+ X509_free(x);
+ sk_X509_pop_free(sk, X509_free);
+ return ret;
+}
+
+int ssl3_get_server_key_exchange(SSL *s) {
+ EVP_MD_CTX md_ctx;
+ int al, ok;
+ long n, alg_k, alg_a;
+ EVP_PKEY *pkey = NULL;
+ const EVP_MD *md = NULL;
+ RSA *rsa = NULL;
+ DH *dh = NULL;
+ EC_KEY *ecdh = NULL;
+ BN_CTX *bn_ctx = NULL;
+ EC_POINT *srvr_ecpoint = NULL;
+ CBS server_key_exchange, server_key_exchange_orig, parameter;
+
+ /* use same message size as in ssl3_get_certificate_request() as
+ * ServerKeyExchange message may be skipped */
+ n = s->method->ssl_get_message(s, SSL3_ST_CR_KEY_EXCH_A,
+ SSL3_ST_CR_KEY_EXCH_B, -1, s->max_cert_list,
+ SSL_GET_MESSAGE_HASH_MESSAGE, &ok);
+ if (!ok) {
+ return n;
+ }
+
+ if (s->s3->tmp.message_type != SSL3_MT_SERVER_KEY_EXCHANGE) {
+ if (ssl_cipher_requires_server_key_exchange(s->s3->tmp.new_cipher)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange,
+ SSL_R_UNEXPECTED_MESSAGE);
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
+ return -1;
+ }
+
+ /* In plain PSK ciphersuite, ServerKeyExchange can be
+ omitted if no identity hint is sent. Set session->sess_cert anyway to
+ avoid problems later.*/
+ if (s->s3->tmp.new_cipher->algorithm_auth & SSL_aPSK) {
+ /* PSK ciphersuites that also send a Certificate would have already
+ * initialized |sess_cert|. */
+ if (s->session->sess_cert == NULL) {
+ s->session->sess_cert = ssl_sess_cert_new();
+ }
+
+ /* TODO(davidben): This should be reset in one place with the rest of the
+ * handshake state. */
+ if (s->s3->tmp.peer_psk_identity_hint) {
+ OPENSSL_free(s->s3->tmp.peer_psk_identity_hint);
+ s->s3->tmp.peer_psk_identity_hint = NULL;
+ }
+ }
+ s->s3->tmp.reuse_message = 1;
+ return 1;
+ }
+
+ /* Retain a copy of the original CBS to compute the signature over. */
+ CBS_init(&server_key_exchange, s->init_msg, n);
+ server_key_exchange_orig = server_key_exchange;
+
+ if (s->session->sess_cert != NULL) {
+ if (s->session->sess_cert->peer_dh_tmp) {
+ DH_free(s->session->sess_cert->peer_dh_tmp);
+ s->session->sess_cert->peer_dh_tmp = NULL;
+ }
+ if (s->session->sess_cert->peer_ecdh_tmp) {
+ EC_KEY_free(s->session->sess_cert->peer_ecdh_tmp);
+ s->session->sess_cert->peer_ecdh_tmp = NULL;
+ }
+ } else {
+ s->session->sess_cert = ssl_sess_cert_new();
+ }
+
+ alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
+ alg_a = s->s3->tmp.new_cipher->algorithm_auth;
+ EVP_MD_CTX_init(&md_ctx);
+
+ if (alg_a & SSL_aPSK) {
+ CBS psk_identity_hint;
+
+ /* Each of the PSK key exchanges begins with a psk_identity_hint. */
+ if (!CBS_get_u16_length_prefixed(&server_key_exchange,
+ &psk_identity_hint)) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, SSL_R_DECODE_ERROR);
+ goto f_err;
+ }
+
+ /* Store PSK identity hint for later use, hint is used in
+ * ssl3_send_client_key_exchange. Assume that the maximum length of a PSK
+ * identity hint can be as long as the maximum length of a PSK identity.
+ * Also do not allow NULL characters; identities are saved as C strings.
+ *
+ * TODO(davidben): Should invalid hints be ignored? It's a hint rather than
+ * a specific identity. */
+ if (CBS_len(&psk_identity_hint) > PSK_MAX_IDENTITY_LEN ||
+ CBS_contains_zero_byte(&psk_identity_hint)) {
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange,
+ SSL_R_DATA_LENGTH_TOO_LONG);
+ goto f_err;
+ }
+
+ /* Save the identity hint as a C string. */
+ if (!CBS_strdup(&psk_identity_hint, &s->s3->tmp.peer_psk_identity_hint)) {
+ al = SSL_AD_INTERNAL_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange,
+ ERR_R_MALLOC_FAILURE);
+ goto f_err;
+ }
+ }
+
+ if (alg_k & SSL_kEDH) {
+ CBS dh_p, dh_g, dh_Ys;
+
+ if (!CBS_get_u16_length_prefixed(&server_key_exchange, &dh_p) ||
+ CBS_len(&dh_p) == 0 ||
+ !CBS_get_u16_length_prefixed(&server_key_exchange, &dh_g) ||
+ CBS_len(&dh_g) == 0 ||
+ !CBS_get_u16_length_prefixed(&server_key_exchange, &dh_Ys) ||
+ CBS_len(&dh_Ys) == 0) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, SSL_R_DECODE_ERROR);
+ goto f_err;
+ }
+
+ dh = DH_new();
+ if (dh == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, ERR_R_DH_LIB);
+ goto err;
+ }
+
+ if ((dh->p = BN_bin2bn(CBS_data(&dh_p), CBS_len(&dh_p), NULL)) == NULL ||
+ (dh->g = BN_bin2bn(CBS_data(&dh_g), CBS_len(&dh_g), NULL)) == NULL ||
+ (dh->pub_key = BN_bin2bn(CBS_data(&dh_Ys), CBS_len(&dh_Ys), NULL)) ==
+ NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, ERR_R_BN_LIB);
+ goto err;
+ }
+
+ if (DH_size(dh) < 512 / 8) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange,
+ SSL_R_BAD_DH_P_LENGTH);
+ goto err;
+ }
+
+ if (alg_a & SSL_aRSA) {
+ pkey = X509_get_pubkey(
+ s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509);
+ }
+ /* else anonymous DH, so no certificate or pkey. */
+
+ s->session->sess_cert->peer_dh_tmp = dh;
+ dh = NULL;
+ } else if (alg_k & SSL_kEECDH) {
+ uint16_t curve_id;
+ int curve_nid = 0;
+ EC_GROUP *ngroup;
+ const EC_GROUP *group;
+ CBS point;
+
+ /* Extract elliptic curve parameters and the server's ephemeral ECDH public
+ * key. Check curve is one of our preferences, if not server has sent an
+ * invalid curve. */
+ if (!tls1_check_curve(s, &server_key_exchange, &curve_id)) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, SSL_R_WRONG_CURVE);
+ goto f_err;
+ }
+
+ curve_nid = tls1_ec_curve_id2nid(curve_id);
+ if (curve_nid == 0) {
+ al = SSL_AD_INTERNAL_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange,
+ SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS);
+ goto f_err;
+ }
+
+ ecdh = EC_KEY_new();
+ if (ecdh == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ ngroup = EC_GROUP_new_by_curve_name(curve_nid);
+ if (ngroup == NULL ||
+ EC_KEY_set_group(ecdh, ngroup) == 0) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, ERR_R_EC_LIB);
+ goto err;
+ }
+ EC_GROUP_free(ngroup);
+
+ group = EC_KEY_get0_group(ecdh);
+
+ /* Next, get the encoded ECPoint */
+ if (!CBS_get_u8_length_prefixed(&server_key_exchange, &point)) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, SSL_R_DECODE_ERROR);
+ goto f_err;
+ }
+
+ if (((srvr_ecpoint = EC_POINT_new(group)) == NULL) ||
+ ((bn_ctx = BN_CTX_new()) == NULL)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (!EC_POINT_oct2point(group, srvr_ecpoint, CBS_data(&point),
+ CBS_len(&point), bn_ctx)) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, SSL_R_BAD_ECPOINT);
+ goto f_err;
+ }
+
+ /* The ECC/TLS specification does not mention the use of DSA to sign
+ * ECParameters in the server key exchange message. We do support RSA and
+ * ECDSA. */
+ if (alg_a & SSL_aRSA) {
+ pkey = X509_get_pubkey(
+ s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509);
+ } else if (alg_a & SSL_aECDSA) {
+ pkey =
+ X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_ECC].x509);
+ }
+ /* else anonymous ECDH, so no certificate or pkey. */
+ EC_KEY_set_public_key(ecdh, srvr_ecpoint);
+ s->session->sess_cert->peer_ecdh_tmp = ecdh;
+ ecdh = NULL;
+ BN_CTX_free(bn_ctx);
+ bn_ctx = NULL;
+ EC_POINT_free(srvr_ecpoint);
+ srvr_ecpoint = NULL;
+ } else if (!(alg_k & SSL_kPSK)) {
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange,
+ SSL_R_UNEXPECTED_MESSAGE);
+ goto f_err;
+ }
+
+ /* At this point, |server_key_exchange| contains the signature, if any, while
+ * |server_key_exchange_orig| contains the entire message. From that, derive
+ * a CBS containing just the parameter. */
+ CBS_init(&parameter, CBS_data(&server_key_exchange_orig),
+ CBS_len(&server_key_exchange_orig) - CBS_len(&server_key_exchange));
+
+ /* if it was signed, check the signature */
+ if (pkey != NULL) {
+ CBS signature;
+
+ if (SSL_USE_SIGALGS(s)) {
+ if (!tls12_check_peer_sigalg(&md, &al, s, &server_key_exchange, pkey)) {
+ goto f_err;
+ }
+ } else if (pkey->type == EVP_PKEY_RSA) {
+ md = EVP_md5_sha1();
+ } else {
+ md = EVP_sha1();
+ }
+
+ /* The last field in |server_key_exchange| is the signature. */
+ if (!CBS_get_u16_length_prefixed(&server_key_exchange, &signature) ||
+ CBS_len(&server_key_exchange) != 0) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, SSL_R_DECODE_ERROR);
+ goto f_err;
+ }
+
+ if (!EVP_DigestVerifyInit(&md_ctx, NULL, md, NULL, pkey) ||
+ !EVP_DigestVerifyUpdate(&md_ctx, s->s3->client_random,
+ SSL3_RANDOM_SIZE) ||
+ !EVP_DigestVerifyUpdate(&md_ctx, s->s3->server_random,
+ SSL3_RANDOM_SIZE) ||
+ !EVP_DigestVerifyUpdate(&md_ctx, CBS_data(&parameter),
+ CBS_len(&parameter)) ||
+ !EVP_DigestVerifyFinal(&md_ctx, CBS_data(&signature),
+ CBS_len(&signature))) {
+ /* bad signature */
+ al = SSL_AD_DECRYPT_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, SSL_R_BAD_SIGNATURE);
+ goto f_err;
+ }
+ } else {
+ if (ssl_cipher_has_server_public_key(s->s3->tmp.new_cipher)) {
+ /* Might be wrong key type, check it */
+ if (ssl3_check_cert_and_algorithm(s)) {
+ /* Otherwise this shouldn't happen */
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange,
+ ERR_R_INTERNAL_ERROR);
+ }
+ goto err;
+ }
+ /* still data left over */
+ if (CBS_len(&server_key_exchange) > 0) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange,
+ SSL_R_EXTRA_DATA_IN_MESSAGE);
+ goto f_err;
+ }
+ }
+ EVP_PKEY_free(pkey);
+ EVP_MD_CTX_cleanup(&md_ctx);
+ return 1;
+
+f_err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+err:
+ EVP_PKEY_free(pkey);
+ if (rsa != NULL) {
+ RSA_free(rsa);
+ }
+ if (dh != NULL) {
+ DH_free(dh);
+ }
+ BN_CTX_free(bn_ctx);
+ EC_POINT_free(srvr_ecpoint);
+ if (ecdh != NULL) {
+ EC_KEY_free(ecdh);
+ }
+ EVP_MD_CTX_cleanup(&md_ctx);
+ return -1;
+}
+
+static int ca_dn_cmp(const X509_NAME **a, const X509_NAME **b) {
+ return X509_NAME_cmp(*a, *b);
+}
+
+int ssl3_get_certificate_request(SSL *s) {
+ int ok, ret = 0;
+ unsigned long n;
+ X509_NAME *xn = NULL;
+ STACK_OF(X509_NAME) *ca_sk = NULL;
+ CBS cbs;
+ CBS certificate_types;
+ CBS certificate_authorities;
+ const uint8_t *data;
+
+ n = s->method->ssl_get_message(s, SSL3_ST_CR_CERT_REQ_A,
+ SSL3_ST_CR_CERT_REQ_B, -1, s->max_cert_list,
+ SSL_GET_MESSAGE_HASH_MESSAGE, &ok);
+
+ if (!ok) {
+ return n;
+ }
+
+ s->s3->tmp.cert_req = 0;
+
+ if (s->s3->tmp.message_type == SSL3_MT_SERVER_DONE) {
+ s->s3->tmp.reuse_message = 1;
+ /* If we get here we don't need any cached handshake records as we wont be
+ * doing client auth. */
+ if (s->s3->handshake_buffer &&
+ !ssl3_digest_cached_records(s, free_handshake_buffer)) {
+ goto err;
+ }
+ return 1;
+ }
+
+ if (s->s3->tmp.message_type != SSL3_MT_CERTIFICATE_REQUEST) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request,
+ SSL_R_WRONG_MESSAGE_TYPE);
+ goto err;
+ }
+
+ /* TLS does not like anon-DH with client cert */
+ if (s->version > SSL3_VERSION &&
+ (s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL)) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request,
+ SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER);
+ goto err;
+ }
+
+ CBS_init(&cbs, s->init_msg, n);
+
+ ca_sk = sk_X509_NAME_new(ca_dn_cmp);
+ if (ca_sk == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ /* get the certificate types */
+ if (!CBS_get_u8_length_prefixed(&cbs, &certificate_types)) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request, SSL_R_DECODE_ERROR);
+ goto err;
+ }
+
+ if (!CBS_stow(&certificate_types, &s->s3->tmp.certificate_types,
+ &s->s3->tmp.num_certificate_types)) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+ goto err;
+ }
+
+ if (SSL_USE_SIGALGS(s)) {
+ CBS supported_signature_algorithms;
+ if (!CBS_get_u16_length_prefixed(&cbs, &supported_signature_algorithms)) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request, SSL_R_DECODE_ERROR);
+ goto err;
+ }
+
+ if (!tls1_process_sigalgs(s, &supported_signature_algorithms)) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request,
+ SSL_R_SIGNATURE_ALGORITHMS_ERROR);
+ goto err;
+ }
+ }
+
+ /* get the CA RDNs */
+ if (!CBS_get_u16_length_prefixed(&cbs, &certificate_authorities)) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request, SSL_R_LENGTH_MISMATCH);
+ goto err;
+ }
+
+ while (CBS_len(&certificate_authorities) > 0) {
+ CBS distinguished_name;
+ if (!CBS_get_u16_length_prefixed(&certificate_authorities,
+ &distinguished_name)) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request,
+ SSL_R_CA_DN_TOO_LONG);
+ goto err;
+ }
+
+ data = CBS_data(&distinguished_name);
+
+ xn = d2i_X509_NAME(NULL, &data, CBS_len(&distinguished_name));
+ if (xn == NULL) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request, ERR_R_ASN1_LIB);
+ goto err;
+ }
+
+ if (!CBS_skip(&distinguished_name, data - CBS_data(&distinguished_name))) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_certificate, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ if (CBS_len(&distinguished_name) != 0) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request,
+ SSL_R_CA_DN_LENGTH_MISMATCH);
+ goto err;
+ }
+
+ if (!sk_X509_NAME_push(ca_sk, xn)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+
+ /* we should setup a certificate to return.... */
+ s->s3->tmp.cert_req = 1;
+ if (s->s3->tmp.ca_names != NULL) {
+ sk_X509_NAME_pop_free(s->s3->tmp.ca_names, X509_NAME_free);
+ }
+ s->s3->tmp.ca_names = ca_sk;
+ ca_sk = NULL;
+
+ ret = 1;
+
+err:
+ if (ca_sk != NULL) {
+ sk_X509_NAME_pop_free(ca_sk, X509_NAME_free);
+ }
+ return ret;
+}
+
+int ssl3_get_new_session_ticket(SSL *s) {
+ int ok, al, ret = 0;
+ long n;
+ CBS new_session_ticket, ticket;
+
+ n = s->method->ssl_get_message(
+ s, SSL3_ST_CR_SESSION_TICKET_A, SSL3_ST_CR_SESSION_TICKET_B,
+ SSL3_MT_NEWSESSION_TICKET, 16384, SSL_GET_MESSAGE_HASH_MESSAGE, &ok);
+
+ if (!ok) {
+ return n;
+ }
+
+ CBS_init(&new_session_ticket, s->init_msg, n);
+
+ if (!CBS_get_u32(&new_session_ticket,
+ &s->session->tlsext_tick_lifetime_hint) ||
+ !CBS_get_u16_length_prefixed(&new_session_ticket, &ticket) ||
+ CBS_len(&new_session_ticket) != 0) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_new_session_ticket, SSL_R_DECODE_ERROR);
+ goto f_err;
+ }
+
+ if (!CBS_stow(&ticket, &s->session->tlsext_tick,
+ &s->session->tlsext_ticklen)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_new_session_ticket, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ /* There are two ways to detect a resumed ticket sesion. 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 (or SHA1 is
+ * SHA256 is disabled) hash of the ticket. */
+ EVP_Digest(CBS_data(&ticket), CBS_len(&ticket), s->session->session_id,
+ &s->session->session_id_length, EVP_sha256(), NULL);
+ ret = 1;
+ return ret;
+
+f_err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+err:
+ return -1;
+}
+
+int ssl3_get_cert_status(SSL *s) {
+ int ok, al;
+ long n;
+ CBS certificate_status, ocsp_response;
+ uint8_t status_type;
+
+ n = s->method->ssl_get_message(
+ s, SSL3_ST_CR_CERT_STATUS_A, SSL3_ST_CR_CERT_STATUS_B,
+ SSL3_MT_CERTIFICATE_STATUS, 16384, SSL_GET_MESSAGE_HASH_MESSAGE, &ok);
+
+ if (!ok) {
+ return n;
+ }
+
+ CBS_init(&certificate_status, s->init_msg, n);
+ if (!CBS_get_u8(&certificate_status, &status_type) ||
+ status_type != TLSEXT_STATUSTYPE_ocsp ||
+ !CBS_get_u24_length_prefixed(&certificate_status, &ocsp_response) ||
+ CBS_len(&ocsp_response) == 0 ||
+ CBS_len(&certificate_status) != 0) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_cert_status, SSL_R_DECODE_ERROR);
+ goto f_err;
+ }
+
+ if (!CBS_stow(&ocsp_response, &s->session->ocsp_response,
+ &s->session->ocsp_response_length)) {
+ al = SSL_AD_INTERNAL_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_cert_status, ERR_R_MALLOC_FAILURE);
+ goto f_err;
+ }
+ return 1;
+
+f_err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ return -1;
+}
+
+int ssl3_get_server_done(SSL *s) {
+ int ok;
+ long n;
+
+ n = s->method->ssl_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 :-) */
+ SSL_GET_MESSAGE_HASH_MESSAGE, &ok);
+
+ if (!ok) {
+ return n;
+ }
+
+ if (n > 0) {
+ /* should contain no data */
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_done, SSL_R_LENGTH_MISMATCH);
+ return -1;
+ }
+
+ return 1;
+}
+
+
+int ssl3_send_client_key_exchange(SSL *s) {
+ uint8_t *p;
+ int n = 0;
+ unsigned long alg_k;
+ unsigned long alg_a;
+ uint8_t *q;
+ EVP_PKEY *pkey = NULL;
+ EC_KEY *clnt_ecdh = NULL;
+ const EC_POINT *srvr_ecpoint = NULL;
+ EVP_PKEY *srvr_pub_pkey = NULL;
+ uint8_t *encodedPoint = NULL;
+ int encoded_pt_len = 0;
+ BN_CTX *bn_ctx = NULL;
+ unsigned int psk_len = 0;
+ uint8_t psk[PSK_MAX_PSK_LEN];
+ uint8_t *pms = NULL;
+ size_t pms_len = 0;
+
+ if (s->state == SSL3_ST_CW_KEY_EXCH_A) {
+ p = ssl_handshake_start(s);
+
+ alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
+ alg_a = s->s3->tmp.new_cipher->algorithm_auth;
+
+ /* If using a PSK key exchange, prepare the pre-shared key. */
+ if (alg_a & SSL_aPSK) {
+ char identity[PSK_MAX_IDENTITY_LEN + 1];
+ size_t identity_len;
+
+ if (s->psk_client_callback == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange,
+ SSL_R_PSK_NO_CLIENT_CB);
+ goto err;
+ }
+
+ memset(identity, 0, sizeof(identity));
+ psk_len =
+ s->psk_client_callback(s, s->s3->tmp.peer_psk_identity_hint, identity,
+ sizeof(identity), psk, sizeof(psk));
+ if (psk_len > PSK_MAX_PSK_LEN) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ } else if (psk_len == 0) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange,
+ SSL_R_PSK_IDENTITY_NOT_FOUND);
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+ goto err;
+ }
+
+ identity_len = OPENSSL_strnlen(identity, sizeof(identity));
+ if (identity_len > PSK_MAX_IDENTITY_LEN) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ if (s->session->psk_identity != NULL) {
+ OPENSSL_free(s->session->psk_identity);
+ }
+
+ s->session->psk_identity = BUF_strdup(identity);
+ if (s->session->psk_identity == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ /* Write out psk_identity. */
+ s2n(identity_len, p);
+ memcpy(p, identity, identity_len);
+ p += identity_len;
+ n = 2 + identity_len;
+ }
+
+ /* Depending on the key exchange method, compute |pms| and |pms_len|. */
+ if (alg_k & SSL_kRSA) {
+ RSA *rsa;
+ size_t enc_pms_len;
+
+ pms_len = SSL_MAX_MASTER_KEY_LENGTH;
+ pms = OPENSSL_malloc(pms_len);
+ if (pms == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (s->session->sess_cert == NULL) {
+ /* We should always have a server certificate with SSL_kRSA. */
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ pkey = X509_get_pubkey(
+ s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509);
+ if (pkey == NULL ||
+ pkey->type != EVP_PKEY_RSA ||
+ pkey->pkey.rsa == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange,
+ ERR_R_INTERNAL_ERROR);
+ if (pkey != NULL) {
+ EVP_PKEY_free(pkey);
+ }
+ goto err;
+ }
+
+ rsa = pkey->pkey.rsa;
+ EVP_PKEY_free(pkey);
+
+ pms[0] = s->client_version >> 8;
+ pms[1] = s->client_version & 0xff;
+ if (!RAND_bytes(&pms[2], SSL_MAX_MASTER_KEY_LENGTH - 2)) {
+ goto err;
+ }
+
+ s->session->master_key_length = SSL_MAX_MASTER_KEY_LENGTH;
+
+ q = p;
+ /* In TLS and beyond, reserve space for the length prefix. */
+ if (s->version > SSL3_VERSION) {
+ p += 2;
+ n += 2;
+ }
+ if (!RSA_encrypt(rsa, &enc_pms_len, p, RSA_size(rsa), pms, pms_len,
+ RSA_PKCS1_PADDING)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange,
+ SSL_R_BAD_RSA_ENCRYPT);
+ goto err;
+ }
+ n += enc_pms_len;
+
+ /* Log the premaster secret, if logging is enabled. */
+ if (!ssl_ctx_log_rsa_client_key_exchange(s->ctx, p, enc_pms_len, pms,
+ pms_len)) {
+ goto err;
+ }
+
+ /* Fill in the length prefix. */
+ if (s->version > SSL3_VERSION) {
+ s2n(enc_pms_len, q);
+ }
+ } else if (alg_k & SSL_kEDH) {
+ DH *dh_srvr, *dh_clnt;
+ SESS_CERT *scert = s->session->sess_cert;
+ int dh_len;
+ size_t pub_len;
+
+ if (scert == NULL) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange,
+ SSL_R_UNEXPECTED_MESSAGE);
+ goto err;
+ }
+
+ if (scert->peer_dh_tmp == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ dh_srvr = scert->peer_dh_tmp;
+
+ /* generate a new random key */
+ dh_clnt = DHparams_dup(dh_srvr);
+ if (dh_clnt == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_DH_LIB);
+ goto err;
+ }
+ if (!DH_generate_key(dh_clnt)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_DH_LIB);
+ DH_free(dh_clnt);
+ goto err;
+ }
+
+ pms_len = DH_size(dh_clnt);
+ pms = OPENSSL_malloc(pms_len);
+ if (pms == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange,
+ ERR_R_MALLOC_FAILURE);
+ DH_free(dh_clnt);
+ goto err;
+ }
+
+ dh_len = DH_compute_key(pms, dh_srvr->pub_key, dh_clnt);
+ if (dh_len <= 0) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_DH_LIB);
+ DH_free(dh_clnt);
+ goto err;
+ }
+ pms_len = dh_len;
+
+ /* send off the data */
+ pub_len = BN_num_bytes(dh_clnt->pub_key);
+ s2n(pub_len, p);
+ BN_bn2bin(dh_clnt->pub_key, p);
+ n += 2 + pub_len;
+
+ DH_free(dh_clnt);
+ } else if (alg_k & SSL_kEECDH) {
+ const EC_GROUP *srvr_group = NULL;
+ EC_KEY *tkey;
+ int field_size = 0, ecdh_len;
+
+ if (s->session->sess_cert == NULL) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange,
+ SSL_R_UNEXPECTED_MESSAGE);
+ goto err;
+ }
+
+ if (s->session->sess_cert->peer_ecdh_tmp == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ tkey = s->session->sess_cert->peer_ecdh_tmp;
+
+ srvr_group = EC_KEY_get0_group(tkey);
+ srvr_ecpoint = EC_KEY_get0_public_key(tkey);
+ if (srvr_group == NULL || srvr_ecpoint == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ clnt_ecdh = EC_KEY_new();
+ if (clnt_ecdh == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (!EC_KEY_set_group(clnt_ecdh, srvr_group)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_EC_LIB);
+ goto err;
+ }
+
+ /* Generate a new ECDH key pair */
+ if (!EC_KEY_generate_key(clnt_ecdh)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_ECDH_LIB);
+ goto err;
+ }
+
+ field_size = EC_GROUP_get_degree(srvr_group);
+ if (field_size <= 0) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_ECDH_LIB);
+ goto err;
+ }
+
+ pms_len = (field_size + 7) / 8;
+ pms = OPENSSL_malloc(pms_len);
+ if (pms == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ ecdh_len = ECDH_compute_key(pms, pms_len, srvr_ecpoint, clnt_ecdh, NULL);
+ if (ecdh_len <= 0) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_ECDH_LIB);
+ goto err;
+ }
+ pms_len = ecdh_len;
+
+ /* First check the size of encoding and allocate memory accordingly. */
+ encoded_pt_len =
+ EC_POINT_point2oct(srvr_group, EC_KEY_get0_public_key(clnt_ecdh),
+ POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL);
+
+ encodedPoint =
+ (uint8_t *)OPENSSL_malloc(encoded_pt_len * sizeof(uint8_t));
+ bn_ctx = BN_CTX_new();
+ if (encodedPoint == NULL || bn_ctx == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ /* Encode the public key */
+ encoded_pt_len = EC_POINT_point2oct(
+ srvr_group, EC_KEY_get0_public_key(clnt_ecdh),
+ POINT_CONVERSION_UNCOMPRESSED, encodedPoint, encoded_pt_len, bn_ctx);
+
+ *p = encoded_pt_len; /* length of encoded point */
+ /* Encoded point will be copied here */
+ p += 1;
+ n += 1;
+ /* copy the point */
+ memcpy(p, encodedPoint, encoded_pt_len);
+ /* increment n to account for length field */
+ n += encoded_pt_len;
+
+ /* Free allocated memory */
+ BN_CTX_free(bn_ctx);
+ bn_ctx = NULL;
+ OPENSSL_free(encodedPoint);
+ encodedPoint = NULL;
+ EC_KEY_free(clnt_ecdh);
+ clnt_ecdh = NULL;
+ EVP_PKEY_free(srvr_pub_pkey);
+ srvr_pub_pkey = NULL;
+ } else if (alg_k & SSL_kPSK) {
+ /* For plain PSK, other_secret is a block of 0s with the same length as
+ * the pre-shared key. */
+ pms_len = psk_len;
+ pms = OPENSSL_malloc(pms_len);
+ if (pms == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ memset(pms, 0, pms_len);
+ } else {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ /* For a PSK cipher suite, other_secret is combined with the pre-shared
+ * key. */
+ if (alg_a & SSL_aPSK) {
+ CBB cbb, child;
+ uint8_t *new_pms;
+ size_t new_pms_len;
+
+ if (!CBB_init(&cbb, 2 + psk_len + 2 + pms_len)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ if (!CBB_add_u16_length_prefixed(&cbb, &child) ||
+ !CBB_add_bytes(&child, pms, pms_len) ||
+ !CBB_add_u16_length_prefixed(&cbb, &child) ||
+ !CBB_add_bytes(&child, psk, psk_len) ||
+ !CBB_finish(&cbb, &new_pms, &new_pms_len)) {
+ CBB_cleanup(&cbb);
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ OPENSSL_cleanse(pms, pms_len);
+ OPENSSL_free(pms);
+ pms = new_pms;
+ pms_len = new_pms_len;
+ }
+
+ /* The message must be added to the finished hash before calculating the
+ * master secret. */
+ ssl_set_handshake_header(s, SSL3_MT_CLIENT_KEY_EXCHANGE, n);
+ s->state = SSL3_ST_CW_KEY_EXCH_B;
+
+ s->session->master_key_length = s->enc_method->generate_master_secret(
+ s, s->session->master_key, pms, pms_len);
+ if (s->session->master_key_length == 0) {
+ goto err;
+ }
+ s->session->extended_master_secret = s->s3->tmp.extended_master_secret;
+ OPENSSL_cleanse(pms, pms_len);
+ OPENSSL_free(pms);
+ }
+
+ /* SSL3_ST_CW_KEY_EXCH_B */
+ return s->enc_method->do_write(s);
+
+err:
+ BN_CTX_free(bn_ctx);
+ if (encodedPoint != NULL) {
+ OPENSSL_free(encodedPoint);
+ }
+ if (clnt_ecdh != NULL) {
+ EC_KEY_free(clnt_ecdh);
+ }
+ EVP_PKEY_free(srvr_pub_pkey);
+ if (pms) {
+ OPENSSL_cleanse(pms, pms_len);
+ OPENSSL_free(pms);
+ }
+ return -1;
+}
+
+int ssl3_send_cert_verify(SSL *s) {
+ uint8_t *buf, *p;
+ const EVP_MD *md = NULL;
+ uint8_t digest[EVP_MAX_MD_SIZE];
+ size_t digest_length;
+ EVP_PKEY *pkey;
+ EVP_PKEY_CTX *pctx = NULL;
+ size_t signature_length = 0;
+ unsigned long n = 0;
+
+ buf = (uint8_t *)s->init_buf->data;
+
+ if (s->state == SSL3_ST_CW_CERT_VRFY_A) {
+ p = ssl_handshake_start(s);
+ pkey = s->cert->key->privatekey;
+
+ /* Write out the digest type if needbe. */
+ if (SSL_USE_SIGALGS(s)) {
+ md = tls1_choose_signing_digest(s, pkey);
+ if (!tls12_get_sigandhash(p, pkey, md)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_cert_verify, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ p += 2;
+ n += 2;
+ }
+
+ /* Compute the digest. */
+ if (!ssl3_cert_verify_hash(s, digest, &digest_length, &md, pkey)) {
+ goto err;
+ }
+
+ /* The handshake buffer is no longer necessary. */
+ if (s->s3->handshake_buffer &&
+ !ssl3_digest_cached_records(s, free_handshake_buffer)) {
+ goto err;
+ }
+
+ /* Sign the digest. */
+ pctx = EVP_PKEY_CTX_new(pkey, NULL);
+ if (pctx == NULL) {
+ goto err;
+ }
+
+ /* Initialize the EVP_PKEY_CTX and determine the size of the signature. */
+ if (!EVP_PKEY_sign_init(pctx) || !EVP_PKEY_CTX_set_signature_md(pctx, md) ||
+ !EVP_PKEY_sign(pctx, NULL, &signature_length, digest, digest_length)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_cert_verify, ERR_R_EVP_LIB);
+ goto err;
+ }
+
+ if (p + 2 + signature_length > buf + SSL3_RT_MAX_PLAIN_LENGTH) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_cert_verify, SSL_R_DATA_LENGTH_TOO_LONG);
+ goto err;
+ }
+
+ if (!EVP_PKEY_sign(pctx, &p[2], &signature_length, digest, digest_length)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_cert_verify, ERR_R_EVP_LIB);
+ goto err;
+ }
+
+ s2n(signature_length, p);
+ n += signature_length + 2;
+
+ ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE_VERIFY, n);
+ s->state = SSL3_ST_CW_CERT_VRFY_B;
+ }
+
+ EVP_PKEY_CTX_free(pctx);
+ return ssl_do_write(s);
+
+err:
+ EVP_PKEY_CTX_free(pctx);
+ return -1;
+}
+
+/* ssl3_has_client_certificate returns true if a client certificate is
+ * configured. */
+static int ssl3_has_client_certificate(SSL *s) {
+ return s->cert && s->cert->key->x509 && s->cert->key->privatekey;
+}
+
+int ssl3_send_client_certificate(SSL *s) {
+ X509 *x509 = NULL;
+ EVP_PKEY *pkey = NULL;
+ int i;
+
+ if (s->state == SSL3_ST_CW_CERT_A) {
+ /* Let cert callback update client certificates if required */
+ if (s->cert->cert_cb) {
+ i = s->cert->cert_cb(s, s->cert->cert_cb_arg);
+ if (i < 0) {
+ s->rwstate = SSL_X509_LOOKUP;
+ return -1;
+ }
+ if (i == 0) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+ return 0;
+ }
+ s->rwstate = SSL_NOTHING;
+ }
+
+ if (ssl3_has_client_certificate(s)) {
+ s->state = SSL3_ST_CW_CERT_C;
+ } else {
+ s->state = SSL3_ST_CW_CERT_B;
+ }
+ }
+
+ /* We need to get a client cert */
+ if (s->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->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;
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_certificate,
+ SSL_R_BAD_DATA_RETURNED_BY_CALLBACK);
+ }
+
+ if (x509 != NULL) {
+ X509_free(x509);
+ }
+ if (pkey != NULL) {
+ EVP_PKEY_free(pkey);
+ }
+ if (i && !ssl3_has_client_certificate(s)) {
+ i = 0;
+ }
+ if (i == 0) {
+ if (s->version == SSL3_VERSION) {
+ s->s3->tmp.cert_req = 0;
+ ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_NO_CERTIFICATE);
+ return 1;
+ } else {
+ s->s3->tmp.cert_req = 2;
+ }
+ }
+
+ /* Ok, we have a cert */
+ s->state = SSL3_ST_CW_CERT_C;
+ }
+
+ if (s->state == SSL3_ST_CW_CERT_C) {
+ s->state = SSL3_ST_CW_CERT_D;
+ ssl3_output_cert_chain(s, (s->s3->tmp.cert_req == 2) ? NULL : s->cert->key);
+ }
+
+ /* SSL3_ST_CW_CERT_D */
+ return ssl_do_write(s);
+}
+
+#define has_bits(i, m) (((i) & (m)) == (m))
+
+int ssl3_check_cert_and_algorithm(SSL *s) {
+ int i, idx;
+ long alg_k, alg_a;
+ EVP_PKEY *pkey = NULL;
+ SESS_CERT *sc;
+ DH *dh;
+
+ /* we don't have a certificate */
+ if (!ssl_cipher_has_server_public_key(s->s3->tmp.new_cipher)) {
+ return 1;
+ }
+
+ alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
+ alg_a = s->s3->tmp.new_cipher->algorithm_auth;
+
+ sc = s->session->sess_cert;
+ if (sc == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_check_cert_and_algorithm, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ dh = s->session->sess_cert->peer_dh_tmp;
+
+ /* This is the passed certificate */
+
+ idx = sc->peer_cert_type;
+ if (idx == SSL_PKEY_ECC) {
+ if (ssl_check_srvr_ecc_cert_and_alg(sc->peer_pkeys[idx].x509, s) == 0) {
+ /* check failed */
+ OPENSSL_PUT_ERROR(SSL, ssl3_check_cert_and_algorithm, SSL_R_BAD_ECC_CERT);
+ goto f_err;
+ } else {
+ return 1;
+ }
+ } else if (alg_a & SSL_aECDSA) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_check_cert_and_algorithm,
+ SSL_R_MISSING_ECDSA_SIGNING_CERT);
+ goto f_err;
+ }
+ pkey = X509_get_pubkey(sc->peer_pkeys[idx].x509);
+ i = X509_certificate_type(sc->peer_pkeys[idx].x509, pkey);
+ EVP_PKEY_free(pkey);
+
+ /* Check that we have a certificate if we require one */
+ if ((alg_a & SSL_aRSA) && !has_bits(i, EVP_PK_RSA | EVP_PKT_SIGN)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_check_cert_and_algorithm,
+ SSL_R_MISSING_RSA_SIGNING_CERT);
+ goto f_err;
+ }
+
+ if ((alg_k & SSL_kRSA) && !has_bits(i, EVP_PK_RSA | EVP_PKT_ENC)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_check_cert_and_algorithm,
+ SSL_R_MISSING_RSA_ENCRYPTING_CERT);
+ goto f_err;
+ }
+
+ if ((alg_k & SSL_kEDH) &&
+ !(has_bits(i, EVP_PK_DH | EVP_PKT_EXCH) || dh != NULL)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_check_cert_and_algorithm, SSL_R_MISSING_DH_KEY);
+ goto f_err;
+ }
+
+ return 1;
+
+f_err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+err:
+ return 0;
+}
+
+int ssl3_send_next_proto(SSL *s) {
+ unsigned int len, padding_len;
+ uint8_t *d, *p;
+
+ if (s->state == SSL3_ST_CW_NEXT_PROTO_A) {
+ len = s->next_proto_negotiated_len;
+ padding_len = 32 - ((len + 2) % 32);
+
+ d = p = ssl_handshake_start(s);
+ *(p++) = len;
+ memcpy(p, s->next_proto_negotiated, len);
+ p += len;
+ *(p++) = padding_len;
+ memset(p, 0, padding_len);
+ p += padding_len;
+
+ ssl_set_handshake_header(s, SSL3_MT_NEXT_PROTO, p - d);
+ s->state = SSL3_ST_CW_NEXT_PROTO_B;
+ }
+
+ return ssl_do_write(s);
+}
+
+int ssl3_send_channel_id(SSL *s) {
+ uint8_t *d;
+ int ret = -1, public_key_len;
+ EVP_MD_CTX md_ctx;
+ size_t sig_len;
+ ECDSA_SIG *sig = NULL;
+ uint8_t *public_key = NULL, *derp, *der_sig = NULL;
+
+ if (s->state != SSL3_ST_CW_CHANNEL_ID_A) {
+ return ssl_do_write(s);
+ }
+
+ if (!s->tlsext_channel_id_private && s->ctx->channel_id_cb) {
+ EVP_PKEY *key = NULL;
+ s->ctx->channel_id_cb(s, &key);
+ if (key != NULL) {
+ s->tlsext_channel_id_private = key;
+ }
+ }
+
+ if (!s->tlsext_channel_id_private) {
+ s->rwstate = SSL_CHANNEL_ID_LOOKUP;
+ return -1;
+ }
+ s->rwstate = SSL_NOTHING;
+
+ d = ssl_handshake_start(s);
+ if (s->s3->tlsext_channel_id_new) {
+ s2n(TLSEXT_TYPE_channel_id_new, d);
+ } else {
+ s2n(TLSEXT_TYPE_channel_id, d);
+ }
+ s2n(TLSEXT_CHANNEL_ID_SIZE, d);
+
+ EVP_MD_CTX_init(&md_ctx);
+
+ public_key_len = i2d_PublicKey(s->tlsext_channel_id_private, NULL);
+ if (public_key_len <= 0) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_channel_id,
+ SSL_R_CANNOT_SERIALIZE_PUBLIC_KEY);
+ goto err;
+ }
+
+ /* i2d_PublicKey will produce an ANSI X9.62 public key which, for a
+ * P-256 key, is 0x04 (meaning uncompressed) followed by the x and y
+ * field elements as 32-byte, big-endian numbers. */
+ if (public_key_len != 65) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_channel_id, SSL_R_CHANNEL_ID_NOT_P256);
+ goto err;
+ }
+ public_key = OPENSSL_malloc(public_key_len);
+ if (!public_key) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_channel_id, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ derp = public_key;
+ i2d_PublicKey(s->tlsext_channel_id_private, &derp);
+
+ if (EVP_DigestSignInit(&md_ctx, NULL, EVP_sha256(), NULL,
+ s->tlsext_channel_id_private) != 1) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_channel_id,
+ SSL_R_EVP_DIGESTSIGNINIT_FAILED);
+ goto err;
+ }
+
+ if (!tls1_channel_id_hash(&md_ctx, s)) {
+ goto err;
+ }
+
+ if (!EVP_DigestSignFinal(&md_ctx, NULL, &sig_len)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_channel_id,
+ SSL_R_EVP_DIGESTSIGNFINAL_FAILED);
+ goto err;
+ }
+
+ der_sig = OPENSSL_malloc(sig_len);
+ if (!der_sig) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_channel_id, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (!EVP_DigestSignFinal(&md_ctx, der_sig, &sig_len)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_channel_id,
+ SSL_R_EVP_DIGESTSIGNFINAL_FAILED);
+ goto err;
+ }
+
+ derp = der_sig;
+ sig = d2i_ECDSA_SIG(NULL, (const uint8_t **)&derp, sig_len);
+ if (sig == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_channel_id, SSL_R_D2I_ECDSA_SIG);
+ goto err;
+ }
+
+ /* The first byte of public_key will be 0x4, denoting an uncompressed key. */
+ memcpy(d, public_key + 1, 64);
+ d += 64;
+ if (!BN_bn2bin_padded(d, 32, sig->r) ||
+ !BN_bn2bin_padded(d + 32, 32, sig->s)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_channel_id, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ ssl_set_handshake_header(s, SSL3_MT_ENCRYPTED_EXTENSIONS,
+ 2 + 2 + TLSEXT_CHANNEL_ID_SIZE);
+ s->state = SSL3_ST_CW_CHANNEL_ID_B;
+
+ ret = ssl_do_write(s);
+
+err:
+ EVP_MD_CTX_cleanup(&md_ctx);
+ if (public_key) {
+ OPENSSL_free(public_key);
+ }
+ if (der_sig) {
+ OPENSSL_free(der_sig);
+ }
+ if (sig) {
+ ECDSA_SIG_free(sig);
+ }
+
+ return ret;
+}
+
+int ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey) {
+ int i = 0;
+ if (s->ctx->client_cert_cb) {
+ i = s->ctx->client_cert_cb(s, px509, ppkey);
+ }
+ return i;
+}
diff --git a/src/ssl/s3_enc.c b/src/ssl/s3_enc.c
new file mode 100644
index 0000000..562cb84
--- /dev/null
+++ b/src/ssl/s3_enc.c
@@ -0,0 +1,527 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *g
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *g
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *g
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) fromg
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *g
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *g
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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.g
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "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 <stdio.h>
+#include <assert.h>
+
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/mem.h>
+#include <openssl/md5.h>
+#include <openssl/obj.h>
+
+#include "ssl_locl.h"
+
+
+static const uint8_t ssl3_pad_1[48] = {
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+};
+
+static const uint8_t ssl3_pad_2[48] = {
+ 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+ 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+ 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+ 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+};
+
+static int ssl3_handshake_mac(SSL *s, int md_nid, const char *sender, int len,
+ uint8_t *p);
+
+int ssl3_prf(SSL *s, uint8_t *out, size_t out_len, const uint8_t *secret,
+ size_t secret_len, const char *label, size_t label_len,
+ const uint8_t *seed1, size_t seed1_len,
+ const uint8_t *seed2, size_t seed2_len) {
+ EVP_MD_CTX md5;
+ EVP_MD_CTX sha1;
+ uint8_t buf[16], smd[SHA_DIGEST_LENGTH];
+ uint8_t c = 'A';
+ size_t i, j, k;
+
+ k = 0;
+ EVP_MD_CTX_init(&md5);
+ EVP_MD_CTX_init(&sha1);
+ for (i = 0; i < out_len; i += MD5_DIGEST_LENGTH) {
+ k++;
+ if (k > sizeof(buf)) {
+ /* bug: 'buf' is too small for this ciphersuite */
+ OPENSSL_PUT_ERROR(SSL, ssl3_prf, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ for (j = 0; j < k; j++) {
+ buf[j] = c;
+ }
+ c++;
+ if (!EVP_DigestInit_ex(&sha1, EVP_sha1(), NULL)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_prf, ERR_LIB_EVP);
+ return 0;
+ }
+ EVP_DigestUpdate(&sha1, buf, k);
+ EVP_DigestUpdate(&sha1, secret, secret_len);
+ /* |label| is ignored for SSLv3. */
+ if (seed1_len) {
+ EVP_DigestUpdate(&sha1, seed1, seed1_len);
+ }
+ if (seed2_len) {
+ EVP_DigestUpdate(&sha1, seed2, seed2_len);
+ }
+ EVP_DigestFinal_ex(&sha1, smd, NULL);
+
+ if (!EVP_DigestInit_ex(&md5, EVP_md5(), NULL)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_prf, ERR_LIB_EVP);
+ return 0;
+ }
+ EVP_DigestUpdate(&md5, secret, secret_len);
+ EVP_DigestUpdate(&md5, smd, SHA_DIGEST_LENGTH);
+ if (i + MD5_DIGEST_LENGTH > out_len) {
+ EVP_DigestFinal_ex(&md5, smd, NULL);
+ memcpy(out, smd, out_len - i);
+ } else {
+ EVP_DigestFinal_ex(&md5, out, NULL);
+ }
+
+ out += MD5_DIGEST_LENGTH;
+ }
+
+ OPENSSL_cleanse(smd, SHA_DIGEST_LENGTH);
+ EVP_MD_CTX_cleanup(&md5);
+ EVP_MD_CTX_cleanup(&sha1);
+
+ return 1;
+}
+
+void ssl3_cleanup_key_block(SSL *s) {
+ if (s->s3->tmp.key_block != NULL) {
+ OPENSSL_cleanse(s->s3->tmp.key_block, s->s3->tmp.key_block_length);
+ OPENSSL_free(s->s3->tmp.key_block);
+ s->s3->tmp.key_block = NULL;
+ }
+ s->s3->tmp.key_block_length = 0;
+}
+
+int ssl3_init_finished_mac(SSL *s) {
+ if (s->s3->handshake_buffer) {
+ BIO_free(s->s3->handshake_buffer);
+ }
+ if (s->s3->handshake_dgst) {
+ ssl3_free_digest_list(s);
+ }
+ s->s3->handshake_buffer = BIO_new(BIO_s_mem());
+ if (s->s3->handshake_buffer == NULL) {
+ return 0;
+ }
+ BIO_set_close(s->s3->handshake_buffer, BIO_CLOSE);
+
+ return 1;
+}
+
+void ssl3_free_digest_list(SSL *s) {
+ int i;
+ if (!s->s3->handshake_dgst) {
+ return;
+ }
+ for (i = 0; i < SSL_MAX_DIGEST; i++) {
+ if (s->s3->handshake_dgst[i]) {
+ EVP_MD_CTX_destroy(s->s3->handshake_dgst[i]);
+ }
+ }
+ OPENSSL_free(s->s3->handshake_dgst);
+ s->s3->handshake_dgst = NULL;
+}
+
+void ssl3_finish_mac(SSL *s, const uint8_t *buf, int len) {
+ int i;
+
+ if (s->s3->handshake_buffer) {
+ BIO_write(s->s3->handshake_buffer, (void *)buf, len);
+ return;
+ }
+
+ for (i = 0; i < SSL_MAX_DIGEST; i++) {
+ if (s->s3->handshake_dgst[i] != NULL) {
+ EVP_DigestUpdate(s->s3->handshake_dgst[i], buf, len);
+ }
+ }
+}
+
+int ssl3_digest_cached_records(
+ SSL *s, enum should_free_handshake_buffer_t should_free_handshake_buffer) {
+ int i;
+ long mask;
+ const EVP_MD *md;
+ const uint8_t *hdata;
+ size_t hdatalen;
+
+ /* Allocate handshake_dgst array */
+ ssl3_free_digest_list(s);
+ s->s3->handshake_dgst = OPENSSL_malloc(SSL_MAX_DIGEST * sizeof(EVP_MD_CTX *));
+ if (s->s3->handshake_dgst == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_digest_cached_records, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ memset(s->s3->handshake_dgst, 0, SSL_MAX_DIGEST * sizeof(EVP_MD_CTX *));
+ if (!BIO_mem_contents(s->s3->handshake_buffer, &hdata, &hdatalen)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_digest_cached_records,
+ SSL_R_BAD_HANDSHAKE_LENGTH);
+ return 0;
+ }
+
+ /* Loop through bits of algorithm2 field and create MD_CTX-es */
+ for (i = 0; ssl_get_handshake_digest(i, &mask, &md); i++) {
+ if ((mask & ssl_get_algorithm2(s)) && md) {
+ s->s3->handshake_dgst[i] = EVP_MD_CTX_create();
+ if (s->s3->handshake_dgst[i] == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_digest_cached_records, ERR_LIB_EVP);
+ return 0;
+ }
+ if (!EVP_DigestInit_ex(s->s3->handshake_dgst[i], md, NULL)) {
+ EVP_MD_CTX_destroy(s->s3->handshake_dgst[i]);
+ s->s3->handshake_dgst[i] = NULL;
+ OPENSSL_PUT_ERROR(SSL, ssl3_digest_cached_records, ERR_LIB_EVP);
+ return 0;
+ }
+ EVP_DigestUpdate(s->s3->handshake_dgst[i], hdata, hdatalen);
+ } else {
+ s->s3->handshake_dgst[i] = NULL;
+ }
+ }
+
+ if (should_free_handshake_buffer == free_handshake_buffer) {
+ /* Free handshake_buffer BIO */
+ BIO_free(s->s3->handshake_buffer);
+ s->s3->handshake_buffer = NULL;
+ }
+
+ return 1;
+}
+
+int ssl3_cert_verify_mac(SSL *s, int md_nid, uint8_t *p) {
+ return ssl3_handshake_mac(s, md_nid, NULL, 0, p);
+}
+
+int ssl3_final_finish_mac(SSL *s, const char *sender, int len, uint8_t *p) {
+ int ret, sha1len;
+ ret = ssl3_handshake_mac(s, NID_md5, sender, len, p);
+ if (ret == 0) {
+ return 0;
+ }
+
+ p += ret;
+
+ sha1len = ssl3_handshake_mac(s, NID_sha1, sender, len, p);
+ if (sha1len == 0) {
+ return 0;
+ }
+
+ ret += sha1len;
+ return ret;
+}
+
+static int ssl3_handshake_mac(SSL *s, int md_nid, const char *sender, int len,
+ uint8_t *p) {
+ unsigned int ret;
+ int npad, n;
+ unsigned int i;
+ uint8_t md_buf[EVP_MAX_MD_SIZE];
+ EVP_MD_CTX ctx, *d = NULL;
+
+ if (s->s3->handshake_buffer &&
+ !ssl3_digest_cached_records(s, free_handshake_buffer)) {
+ return 0;
+ }
+
+ /* Search for digest of specified type in the handshake_dgst array. */
+ for (i = 0; i < SSL_MAX_DIGEST; i++) {
+ if (s->s3->handshake_dgst[i] &&
+ EVP_MD_CTX_type(s->s3->handshake_dgst[i]) == md_nid) {
+ d = s->s3->handshake_dgst[i];
+ break;
+ }
+ }
+
+ if (!d) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_handshake_mac, SSL_R_NO_REQUIRED_DIGEST);
+ return 0;
+ }
+
+ EVP_MD_CTX_init(&ctx);
+ if (!EVP_MD_CTX_copy_ex(&ctx, d)) {
+ EVP_MD_CTX_cleanup(&ctx);
+ OPENSSL_PUT_ERROR(SSL, ssl3_generate_key_block, ERR_LIB_EVP);
+ return 0;
+ }
+
+ n = EVP_MD_CTX_size(&ctx);
+ if (n < 0) {
+ return 0;
+ }
+
+ npad = (48 / n) * n;
+ if (sender != NULL) {
+ EVP_DigestUpdate(&ctx, sender, len);
+ }
+ EVP_DigestUpdate(&ctx, s->session->master_key, s->session->master_key_length);
+ EVP_DigestUpdate(&ctx, ssl3_pad_1, npad);
+ EVP_DigestFinal_ex(&ctx, md_buf, &i);
+
+ if (!EVP_DigestInit_ex(&ctx, EVP_MD_CTX_md(&ctx), NULL)) {
+ EVP_MD_CTX_cleanup(&ctx);
+ OPENSSL_PUT_ERROR(SSL, ssl3_generate_key_block, ERR_LIB_EVP);
+ return 0;
+ }
+ EVP_DigestUpdate(&ctx, s->session->master_key, s->session->master_key_length);
+ EVP_DigestUpdate(&ctx, ssl3_pad_2, npad);
+ EVP_DigestUpdate(&ctx, md_buf, i);
+ EVP_DigestFinal_ex(&ctx, p, &ret);
+
+ EVP_MD_CTX_cleanup(&ctx);
+
+ return ret;
+}
+
+void ssl3_record_sequence_update(uint8_t *seq) {
+ int i;
+
+ for (i = 7; i >= 0; i--) {
+ ++seq[i];
+ if (seq[i] != 0) {
+ break;
+ }
+ }
+}
+
+int ssl3_alert_code(int code) {
+ switch (code) {
+ case SSL_AD_CLOSE_NOTIFY:
+ return SSL3_AD_CLOSE_NOTIFY;
+
+ case SSL_AD_UNEXPECTED_MESSAGE:
+ return SSL3_AD_UNEXPECTED_MESSAGE;
+
+ case SSL_AD_BAD_RECORD_MAC:
+ return SSL3_AD_BAD_RECORD_MAC;
+
+ case SSL_AD_DECRYPTION_FAILED:
+ return SSL3_AD_BAD_RECORD_MAC;
+
+ case SSL_AD_RECORD_OVERFLOW:
+ return SSL3_AD_BAD_RECORD_MAC;
+
+ case SSL_AD_DECOMPRESSION_FAILURE:
+ return SSL3_AD_DECOMPRESSION_FAILURE;
+
+ case SSL_AD_HANDSHAKE_FAILURE:
+ return SSL3_AD_HANDSHAKE_FAILURE;
+
+ case SSL_AD_NO_CERTIFICATE:
+ return SSL3_AD_NO_CERTIFICATE;
+
+ case SSL_AD_BAD_CERTIFICATE:
+ return SSL3_AD_BAD_CERTIFICATE;
+
+ case SSL_AD_UNSUPPORTED_CERTIFICATE:
+ return SSL3_AD_UNSUPPORTED_CERTIFICATE;
+
+ case SSL_AD_CERTIFICATE_REVOKED:
+ return SSL3_AD_CERTIFICATE_REVOKED;
+
+ case SSL_AD_CERTIFICATE_EXPIRED:
+ return SSL3_AD_CERTIFICATE_EXPIRED;
+
+ case SSL_AD_CERTIFICATE_UNKNOWN:
+ return SSL3_AD_CERTIFICATE_UNKNOWN;
+
+ case SSL_AD_ILLEGAL_PARAMETER:
+ return SSL3_AD_ILLEGAL_PARAMETER;
+
+ case SSL_AD_UNKNOWN_CA:
+ return SSL3_AD_BAD_CERTIFICATE;
+
+ case SSL_AD_ACCESS_DENIED:
+ return SSL3_AD_HANDSHAKE_FAILURE;
+
+ case SSL_AD_DECODE_ERROR:
+ return SSL3_AD_HANDSHAKE_FAILURE;
+
+ case SSL_AD_DECRYPT_ERROR:
+ return SSL3_AD_HANDSHAKE_FAILURE;
+
+ case SSL_AD_EXPORT_RESTRICTION:
+ return SSL3_AD_HANDSHAKE_FAILURE;
+
+ case SSL_AD_PROTOCOL_VERSION:
+ return SSL3_AD_HANDSHAKE_FAILURE;
+
+ case SSL_AD_INSUFFICIENT_SECURITY:
+ return SSL3_AD_HANDSHAKE_FAILURE;
+
+ case SSL_AD_INTERNAL_ERROR:
+ return SSL3_AD_HANDSHAKE_FAILURE;
+
+ case SSL_AD_USER_CANCELLED:
+ return SSL3_AD_HANDSHAKE_FAILURE;
+
+ case SSL_AD_NO_RENEGOTIATION:
+ return -1; /* Don't send it. */
+
+ case SSL_AD_UNSUPPORTED_EXTENSION:
+ return SSL3_AD_HANDSHAKE_FAILURE;
+
+ case SSL_AD_CERTIFICATE_UNOBTAINABLE:
+ return SSL3_AD_HANDSHAKE_FAILURE;
+
+ case SSL_AD_UNRECOGNIZED_NAME:
+ return SSL3_AD_HANDSHAKE_FAILURE;
+
+ case SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE:
+ return SSL3_AD_HANDSHAKE_FAILURE;
+
+ case SSL_AD_BAD_CERTIFICATE_HASH_VALUE:
+ return SSL3_AD_HANDSHAKE_FAILURE;
+
+ case SSL_AD_UNKNOWN_PSK_IDENTITY:
+ return TLS1_AD_UNKNOWN_PSK_IDENTITY;
+
+ case SSL_AD_INAPPROPRIATE_FALLBACK:
+ return SSL3_AD_INAPPROPRIATE_FALLBACK;
+
+ default:
+ return -1;
+ }
+}
diff --git a/src/ssl/s3_lib.c b/src/ssl/s3_lib.c
new file mode 100644
index 0000000..9782296
--- /dev/null
+++ b/src/ssl/s3_lib.c
@@ -0,0 +1,1548 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <assert.h>
+#include <stdio.h>
+
+#include <openssl/buf.h>
+#include <openssl/dh.h>
+#include <openssl/md5.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+
+#include "ssl_locl.h"
+
+
+#define SSL3_NUM_CIPHERS (sizeof(ssl3_ciphers) / sizeof(SSL_CIPHER))
+
+/* list of available SSLv3 ciphers (sorted by id) */
+const SSL_CIPHER ssl3_ciphers[] = {
+ /* The RSA ciphers */
+ /* Cipher 04 */
+ {
+ 1, SSL3_TXT_RSA_RC4_128_MD5, SSL3_CK_RSA_RC4_128_MD5, SSL_kRSA, SSL_aRSA,
+ SSL_RC4, SSL_MD5, SSL_SSLV3, SSL_MEDIUM,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, 128, 128,
+ },
+
+ /* Cipher 05 */
+ {
+ 1, SSL3_TXT_RSA_RC4_128_SHA, SSL3_CK_RSA_RC4_128_SHA, SSL_kRSA, SSL_aRSA,
+ SSL_RC4, SSL_SHA1, SSL_SSLV3, SSL_MEDIUM,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, 128, 128,
+ },
+
+ /* Cipher 0A */
+ {
+ 1, SSL3_TXT_RSA_DES_192_CBC3_SHA, SSL3_CK_RSA_DES_192_CBC3_SHA, SSL_kRSA,
+ SSL_aRSA, SSL_3DES, SSL_SHA1, SSL_SSLV3, SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, 112, 168,
+ },
+
+
+ /* The Ephemeral DH ciphers */
+
+ /* Cipher 18 */
+ {
+ 1, SSL3_TXT_ADH_RC4_128_MD5, SSL3_CK_ADH_RC4_128_MD5, SSL_kEDH, SSL_aNULL,
+ SSL_RC4, SSL_MD5, SSL_SSLV3, SSL_MEDIUM,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, 128, 128,
+ },
+
+
+ /* New AES ciphersuites */
+
+ /* Cipher 2F */
+ {
+ 1, TLS1_TXT_RSA_WITH_AES_128_SHA, TLS1_CK_RSA_WITH_AES_128_SHA, SSL_kRSA,
+ SSL_aRSA, SSL_AES128, SSL_SHA1, SSL_TLSV1, SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, 128, 128,
+ },
+
+ /* Cipher 33 */
+ {
+ 1, TLS1_TXT_DHE_RSA_WITH_AES_128_SHA, TLS1_CK_DHE_RSA_WITH_AES_128_SHA,
+ SSL_kEDH, SSL_aRSA, SSL_AES128, SSL_SHA1, SSL_TLSV1, SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, 128, 128,
+ },
+
+ /* Cipher 34 */
+ {
+ 1, TLS1_TXT_ADH_WITH_AES_128_SHA, TLS1_CK_ADH_WITH_AES_128_SHA, SSL_kEDH,
+ SSL_aNULL, SSL_AES128, SSL_SHA1, SSL_TLSV1, SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, 128, 128,
+ },
+
+ /* Cipher 35 */
+ {
+ 1, TLS1_TXT_RSA_WITH_AES_256_SHA, TLS1_CK_RSA_WITH_AES_256_SHA, SSL_kRSA,
+ SSL_aRSA, SSL_AES256, SSL_SHA1, SSL_TLSV1, SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, 256, 256,
+ },
+
+ /* Cipher 39 */
+ {
+ 1, TLS1_TXT_DHE_RSA_WITH_AES_256_SHA, TLS1_CK_DHE_RSA_WITH_AES_256_SHA,
+ SSL_kEDH, SSL_aRSA, SSL_AES256, SSL_SHA1, SSL_TLSV1, SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, 256, 256,
+ },
+
+ /* Cipher 3A */
+ {
+ 1, TLS1_TXT_ADH_WITH_AES_256_SHA, TLS1_CK_ADH_WITH_AES_256_SHA, SSL_kEDH,
+ SSL_aNULL, SSL_AES256, SSL_SHA1, SSL_TLSV1, SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, 256, 256,
+ },
+
+
+ /* TLS v1.2 ciphersuites */
+
+ /* Cipher 3C */
+ {
+ 1, TLS1_TXT_RSA_WITH_AES_128_SHA256, TLS1_CK_RSA_WITH_AES_128_SHA256,
+ SSL_kRSA, SSL_aRSA, SSL_AES128, SSL_SHA256, SSL_TLSV1_2,
+ SSL_HIGH | SSL_FIPS, SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, 128, 128,
+ },
+
+ /* Cipher 3D */
+ {
+ 1, TLS1_TXT_RSA_WITH_AES_256_SHA256, TLS1_CK_RSA_WITH_AES_256_SHA256,
+ SSL_kRSA, SSL_aRSA, SSL_AES256, SSL_SHA256, SSL_TLSV1_2,
+ SSL_HIGH | SSL_FIPS, SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, 256, 256,
+ },
+
+ /* Cipher 67 */
+ {
+ 1, TLS1_TXT_DHE_RSA_WITH_AES_128_SHA256,
+ TLS1_CK_DHE_RSA_WITH_AES_128_SHA256, SSL_kEDH, SSL_aRSA, SSL_AES128,
+ SSL_SHA256, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, 128, 128,
+ },
+
+ /* Cipher 6B */
+ {
+ 1, TLS1_TXT_DHE_RSA_WITH_AES_256_SHA256,
+ TLS1_CK_DHE_RSA_WITH_AES_256_SHA256, SSL_kEDH, SSL_aRSA, SSL_AES256,
+ SSL_SHA256, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, 256, 256,
+ },
+
+ /* Cipher 6C */
+ {
+ 1, TLS1_TXT_ADH_WITH_AES_128_SHA256, TLS1_CK_ADH_WITH_AES_128_SHA256,
+ SSL_kEDH, SSL_aNULL, SSL_AES128, SSL_SHA256, SSL_TLSV1_2,
+ SSL_HIGH | SSL_FIPS, SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, 128, 128,
+ },
+
+ /* Cipher 6D */
+ {
+ 1, TLS1_TXT_ADH_WITH_AES_256_SHA256, TLS1_CK_ADH_WITH_AES_256_SHA256,
+ SSL_kEDH, SSL_aNULL, SSL_AES256, SSL_SHA256, SSL_TLSV1_2,
+ SSL_HIGH | SSL_FIPS, SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, 256, 256,
+ },
+
+ /* Cipher 8A */
+ {
+ 1, TLS1_TXT_PSK_WITH_RC4_128_SHA, TLS1_CK_PSK_WITH_RC4_128_SHA, SSL_kPSK,
+ SSL_aPSK, SSL_RC4, SSL_SHA1, SSL_TLSV1, SSL_MEDIUM,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, 128, 128,
+ },
+
+ /* Cipher 8C */
+ {
+ 1, TLS1_TXT_PSK_WITH_AES_128_CBC_SHA, TLS1_CK_PSK_WITH_AES_128_CBC_SHA,
+ SSL_kPSK, SSL_aPSK, SSL_AES128, SSL_SHA1, SSL_TLSV1, SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, 128, 128,
+ },
+
+ /* Cipher 8D */
+ {
+ 1, TLS1_TXT_PSK_WITH_AES_256_CBC_SHA, TLS1_CK_PSK_WITH_AES_256_CBC_SHA,
+ SSL_kPSK, SSL_aPSK, SSL_AES256, SSL_SHA1, SSL_TLSV1, SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, 256, 256,
+ },
+
+
+ /* GCM ciphersuites from RFC5288 */
+
+ /* Cipher 9C */
+ {
+ 1, TLS1_TXT_RSA_WITH_AES_128_GCM_SHA256,
+ TLS1_CK_RSA_WITH_AES_128_GCM_SHA256, SSL_kRSA, SSL_aRSA, SSL_AES128GCM,
+ SSL_AEAD, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256 | SSL_CIPHER_ALGORITHM2_AEAD |
+ SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
+ 128, 128,
+ },
+
+ /* Cipher 9D */
+ {
+ 1, TLS1_TXT_RSA_WITH_AES_256_GCM_SHA384,
+ TLS1_CK_RSA_WITH_AES_256_GCM_SHA384, SSL_kRSA, SSL_aRSA, SSL_AES256GCM,
+ SSL_AEAD, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384 | SSL_CIPHER_ALGORITHM2_AEAD |
+ SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
+ 256, 256,
+ },
+
+ /* Cipher 9E */
+ {
+ 1, TLS1_TXT_DHE_RSA_WITH_AES_128_GCM_SHA256,
+ TLS1_CK_DHE_RSA_WITH_AES_128_GCM_SHA256, SSL_kEDH, SSL_aRSA, SSL_AES128GCM,
+ SSL_AEAD, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256 | SSL_CIPHER_ALGORITHM2_AEAD |
+ SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
+ 128, 128,
+ },
+
+ /* Cipher 9F */
+ {
+ 1, TLS1_TXT_DHE_RSA_WITH_AES_256_GCM_SHA384,
+ TLS1_CK_DHE_RSA_WITH_AES_256_GCM_SHA384, SSL_kEDH, SSL_aRSA, SSL_AES256GCM,
+ SSL_AEAD, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384 | SSL_CIPHER_ALGORITHM2_AEAD |
+ SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
+ 256, 256,
+ },
+
+ /* Cipher A6 */
+ {
+ 1, TLS1_TXT_ADH_WITH_AES_128_GCM_SHA256,
+ TLS1_CK_ADH_WITH_AES_128_GCM_SHA256, SSL_kEDH, SSL_aNULL, SSL_AES128GCM,
+ SSL_AEAD, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256 | SSL_CIPHER_ALGORITHM2_AEAD |
+ SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
+ 128, 128,
+ },
+
+ /* Cipher A7 */
+ {
+ 1, TLS1_TXT_ADH_WITH_AES_256_GCM_SHA384,
+ TLS1_CK_ADH_WITH_AES_256_GCM_SHA384, SSL_kEDH, SSL_aNULL, SSL_AES256GCM,
+ SSL_AEAD, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384 | SSL_CIPHER_ALGORITHM2_AEAD |
+ SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
+ 256, 256,
+ },
+
+ /* Cipher C007 */
+ {
+ 1, TLS1_TXT_ECDHE_ECDSA_WITH_RC4_128_SHA,
+ TLS1_CK_ECDHE_ECDSA_WITH_RC4_128_SHA, SSL_kEECDH, SSL_aECDSA, SSL_RC4,
+ SSL_SHA1, SSL_TLSV1, SSL_MEDIUM, SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, 128,
+ 128,
+ },
+
+ /* Cipher C009 */
+ {
+ 1, TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
+ TLS1_CK_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, SSL_kEECDH, SSL_aECDSA,
+ SSL_AES128, SSL_SHA1, SSL_TLSV1, SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, 128, 128,
+ },
+
+ /* Cipher C00A */
+ {
+ 1, TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
+ TLS1_CK_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, SSL_kEECDH, SSL_aECDSA,
+ SSL_AES256, SSL_SHA1, SSL_TLSV1, SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, 256, 256,
+ },
+
+ /* Cipher C011 */
+ {
+ 1, TLS1_TXT_ECDHE_RSA_WITH_RC4_128_SHA, TLS1_CK_ECDHE_RSA_WITH_RC4_128_SHA,
+ SSL_kEECDH, SSL_aRSA, SSL_RC4, SSL_SHA1, SSL_TLSV1, SSL_MEDIUM,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, 128, 128,
+ },
+
+ /* Cipher C013 */
+ {
+ 1, TLS1_TXT_ECDHE_RSA_WITH_AES_128_CBC_SHA,
+ TLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA, SSL_kEECDH, SSL_aRSA, SSL_AES128,
+ SSL_SHA1, SSL_TLSV1, SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, 128, 128,
+ },
+
+ /* Cipher C014 */
+ {
+ 1, TLS1_TXT_ECDHE_RSA_WITH_AES_256_CBC_SHA,
+ TLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA, SSL_kEECDH, SSL_aRSA, SSL_AES256,
+ SSL_SHA1, SSL_TLSV1, SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, 256, 256,
+ },
+
+ /* Cipher C016 */
+ {
+ 1, TLS1_TXT_ECDH_anon_WITH_RC4_128_SHA, TLS1_CK_ECDH_anon_WITH_RC4_128_SHA,
+ SSL_kEECDH, SSL_aNULL, SSL_RC4, SSL_SHA1, SSL_TLSV1, SSL_MEDIUM,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, 128, 128,
+ },
+
+ /* Cipher C018 */
+ {
+ 1, TLS1_TXT_ECDH_anon_WITH_AES_128_CBC_SHA,
+ TLS1_CK_ECDH_anon_WITH_AES_128_CBC_SHA, SSL_kEECDH, SSL_aNULL, SSL_AES128,
+ SSL_SHA1, SSL_TLSV1, SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, 128, 128,
+ },
+
+ /* Cipher C019 */
+ {
+ 1, TLS1_TXT_ECDH_anon_WITH_AES_256_CBC_SHA,
+ TLS1_CK_ECDH_anon_WITH_AES_256_CBC_SHA, SSL_kEECDH, SSL_aNULL, SSL_AES256,
+ SSL_SHA1, SSL_TLSV1, SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, 256, 256,
+ },
+
+
+ /* HMAC based TLS v1.2 ciphersuites from RFC5289 */
+
+ /* Cipher C023 */
+ {
+ 1, TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_SHA256,
+ TLS1_CK_ECDHE_ECDSA_WITH_AES_128_SHA256, SSL_kEECDH, SSL_aECDSA,
+ SSL_AES128, SSL_SHA256, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, 128, 128,
+ },
+
+ /* Cipher C024 */
+ {
+ 1, TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_SHA384,
+ TLS1_CK_ECDHE_ECDSA_WITH_AES_256_SHA384, SSL_kEECDH, SSL_aECDSA,
+ SSL_AES256, SSL_SHA384, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384, 256, 256,
+ },
+
+ /* Cipher C027 */
+ {
+ 1, TLS1_TXT_ECDHE_RSA_WITH_AES_128_SHA256,
+ TLS1_CK_ECDHE_RSA_WITH_AES_128_SHA256, SSL_kEECDH, SSL_aRSA, SSL_AES128,
+ SSL_SHA256, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, 128, 128,
+ },
+
+ /* Cipher C028 */
+ {
+ 1, TLS1_TXT_ECDHE_RSA_WITH_AES_256_SHA384,
+ TLS1_CK_ECDHE_RSA_WITH_AES_256_SHA384, SSL_kEECDH, SSL_aRSA, SSL_AES256,
+ SSL_SHA384, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384, 256, 256,
+ },
+
+
+ /* GCM based TLS v1.2 ciphersuites from RFC5289 */
+
+ /* Cipher C02B */
+ {
+ 1, TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
+ TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, SSL_kEECDH, SSL_aECDSA,
+ SSL_AES128GCM, SSL_AEAD, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256 | SSL_CIPHER_ALGORITHM2_AEAD |
+ SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
+ 128, 128,
+ },
+
+ /* Cipher C02C */
+ {
+ 1, TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
+ TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, SSL_kEECDH, SSL_aECDSA,
+ SSL_AES256GCM, SSL_AEAD, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384 | SSL_CIPHER_ALGORITHM2_AEAD |
+ SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
+ 256, 256,
+ },
+
+ /* Cipher C02F */
+ {
+ 1, TLS1_TXT_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+ TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, SSL_kEECDH, SSL_aRSA,
+ SSL_AES128GCM, SSL_AEAD, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256 | SSL_CIPHER_ALGORITHM2_AEAD |
+ SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
+ 128, 128,
+ },
+
+ /* Cipher C030 */
+ {
+ 1, TLS1_TXT_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
+ TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, SSL_kEECDH, SSL_aRSA,
+ SSL_AES256GCM, SSL_AEAD, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
+ SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384 | SSL_CIPHER_ALGORITHM2_AEAD |
+ SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
+ 256, 256,
+ },
+
+
+ /* ECDH PSK ciphersuites */
+
+ /* Cipher CAFE */
+ {
+ 1, TLS1_TXT_ECDHE_PSK_WITH_AES_128_GCM_SHA256,
+ TLS1_CK_ECDHE_PSK_WITH_AES_128_GCM_SHA256, SSL_kEECDH, SSL_aPSK,
+ SSL_AES128GCM, SSL_AEAD, SSL_TLSV1_2, SSL_HIGH,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256 | SSL_CIPHER_ALGORITHM2_AEAD |
+ SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
+ 128, 128,
+ },
+
+ {
+ 1, TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305,
+ TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305, SSL_kEECDH, SSL_aRSA,
+ SSL_CHACHA20POLY1305, SSL_AEAD, SSL_TLSV1_2, SSL_HIGH,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256 | SSL_CIPHER_ALGORITHM2_AEAD,
+ 256, 0,
+ },
+
+ {
+ 1, TLS1_TXT_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
+ TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305, SSL_kEECDH, SSL_aECDSA,
+ SSL_CHACHA20POLY1305, SSL_AEAD, SSL_TLSV1_2, SSL_HIGH,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256 | SSL_CIPHER_ALGORITHM2_AEAD,
+ 256, 0,
+ },
+
+ {
+ 1, TLS1_TXT_DHE_RSA_WITH_CHACHA20_POLY1305,
+ TLS1_CK_DHE_RSA_CHACHA20_POLY1305, SSL_kEDH, SSL_aRSA,
+ SSL_CHACHA20POLY1305, SSL_AEAD, SSL_TLSV1_2, SSL_HIGH,
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256 | SSL_CIPHER_ALGORITHM2_AEAD,
+ 256, 0,
+ },
+};
+
+const SSL3_ENC_METHOD SSLv3_enc_data = {
+ tls1_enc,
+ ssl3_prf,
+ tls1_setup_key_block,
+ tls1_generate_master_secret,
+ tls1_change_cipher_state,
+ ssl3_final_finish_mac,
+ MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH,
+ ssl3_cert_verify_mac,
+ SSL3_MD_CLIENT_FINISHED_CONST, 4,
+ SSL3_MD_SERVER_FINISHED_CONST, 4,
+ ssl3_alert_code,
+ (int (*)(SSL *, uint8_t *, size_t, const char *, size_t, const uint8_t *,
+ size_t, int use_context)) ssl_undefined_function,
+ 0,
+ SSL3_HM_HEADER_LENGTH,
+ ssl3_set_handshake_header,
+ ssl3_handshake_write,
+};
+
+int ssl3_num_ciphers(void) { return SSL3_NUM_CIPHERS; }
+
+const SSL_CIPHER *ssl3_get_cipher(unsigned int u) {
+ if (u >= SSL3_NUM_CIPHERS) {
+ return NULL;
+ }
+
+ return &ssl3_ciphers[SSL3_NUM_CIPHERS - 1 - u];
+}
+
+int ssl3_pending(const SSL *s) {
+ if (s->rstate == SSL_ST_READ_BODY) {
+ return 0;
+ }
+
+ return (s->s3->rrec.type == SSL3_RT_APPLICATION_DATA) ? s->s3->rrec.length
+ : 0;
+}
+
+void ssl3_set_handshake_header(SSL *s, int htype, unsigned long len) {
+ uint8_t *p = (uint8_t *)s->init_buf->data;
+ *(p++) = htype;
+ l2n3(len, p);
+ s->init_num = (int)len + SSL3_HM_HEADER_LENGTH;
+ s->init_off = 0;
+
+ /* Add the message to the handshake hash. */
+ ssl3_finish_mac(s, (uint8_t *)s->init_buf->data, s->init_num);
+}
+
+int ssl3_handshake_write(SSL *s) { return ssl3_do_write(s, SSL3_RT_HANDSHAKE); }
+
+int ssl3_new(SSL *s) {
+ SSL3_STATE *s3;
+
+ s3 = OPENSSL_malloc(sizeof *s3);
+ if (s3 == NULL) {
+ goto err;
+ }
+ memset(s3, 0, sizeof *s3);
+ memset(s3->rrec.seq_num, 0, sizeof(s3->rrec.seq_num));
+ memset(s3->wrec.seq_num, 0, sizeof(s3->wrec.seq_num));
+
+ s->s3 = s3;
+
+ /* Set the version to the highest supported version for TLS. This controls the
+ * initial state of |s->enc_method| and what the API reports as the version
+ * prior to negotiation.
+ *
+ * TODO(davidben): This is fragile and confusing. */
+ s->version = TLS1_2_VERSION;
+ return 1;
+err:
+ return 0;
+}
+
+void ssl3_free(SSL *s) {
+ if (s == NULL || s->s3 == NULL) {
+ return;
+ }
+
+ if (s->s3->sniff_buffer != NULL) {
+ BUF_MEM_free(s->s3->sniff_buffer);
+ }
+ ssl3_cleanup_key_block(s);
+ if (s->s3->rbuf.buf != NULL) {
+ ssl3_release_read_buffer(s);
+ }
+ if (s->s3->wbuf.buf != NULL) {
+ ssl3_release_write_buffer(s);
+ }
+ if (s->s3->tmp.dh != NULL) {
+ DH_free(s->s3->tmp.dh);
+ }
+ if (s->s3->tmp.ecdh != NULL) {
+ EC_KEY_free(s->s3->tmp.ecdh);
+ }
+
+ if (s->s3->tmp.ca_names != NULL) {
+ sk_X509_NAME_pop_free(s->s3->tmp.ca_names, X509_NAME_free);
+ }
+ if (s->s3->tmp.certificate_types != NULL) {
+ OPENSSL_free(s->s3->tmp.certificate_types);
+ }
+ if (s->s3->tmp.peer_ecpointformatlist) {
+ OPENSSL_free(s->s3->tmp.peer_ecpointformatlist);
+ }
+ if (s->s3->tmp.peer_ellipticcurvelist) {
+ OPENSSL_free(s->s3->tmp.peer_ellipticcurvelist);
+ }
+ if (s->s3->tmp.peer_psk_identity_hint) {
+ OPENSSL_free(s->s3->tmp.peer_psk_identity_hint);
+ }
+ if (s->s3->handshake_buffer) {
+ BIO_free(s->s3->handshake_buffer);
+ }
+ if (s->s3->handshake_dgst) {
+ ssl3_free_digest_list(s);
+ }
+ if (s->s3->alpn_selected) {
+ OPENSSL_free(s->s3->alpn_selected);
+ }
+
+ OPENSSL_cleanse(s->s3, sizeof *s->s3);
+ OPENSSL_free(s->s3);
+ s->s3 = NULL;
+}
+
+static int ssl3_set_req_cert_type(CERT *c, const uint8_t *p, size_t len);
+
+long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg) {
+ int ret = 0;
+
+ if (cmd == SSL_CTRL_SET_TMP_RSA || cmd == SSL_CTRL_SET_TMP_RSA_CB ||
+ cmd == SSL_CTRL_SET_TMP_DH || cmd == SSL_CTRL_SET_TMP_DH_CB) {
+ if (!ssl_cert_inst(&s->cert)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_ctrl, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ }
+
+ switch (cmd) {
+ case SSL_CTRL_GET_SESSION_REUSED:
+ ret = s->hit;
+ break;
+
+ case SSL_CTRL_GET_CLIENT_CERT_REQUEST:
+ break;
+
+ case SSL_CTRL_GET_NUM_RENEGOTIATIONS:
+ ret = s->s3->num_renegotiations;
+ break;
+
+ case SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS:
+ ret = s->s3->num_renegotiations;
+ s->s3->num_renegotiations = 0;
+ break;
+
+ case SSL_CTRL_GET_TOTAL_RENEGOTIATIONS:
+ ret = s->s3->total_renegotiations;
+ break;
+
+ case SSL_CTRL_GET_FLAGS:
+ ret = (int)(s->s3->flags);
+ break;
+
+ case SSL_CTRL_NEED_TMP_RSA:
+ /* Temporary RSA keys are never used. */
+ ret = 0;
+ break;
+
+ case SSL_CTRL_SET_TMP_RSA:
+ /* Temporary RSA keys are never used. */
+ OPENSSL_PUT_ERROR(SSL, ssl3_ctrl, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ break;
+
+ case SSL_CTRL_SET_TMP_RSA_CB:
+ OPENSSL_PUT_ERROR(SSL, ssl3_ctrl, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return ret;
+
+ case SSL_CTRL_SET_TMP_DH: {
+ DH *dh = (DH *)parg;
+ if (dh == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_ctrl, ERR_R_PASSED_NULL_PARAMETER);
+ return ret;
+ }
+ dh = DHparams_dup(dh);
+ if (dh == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_ctrl, ERR_R_DH_LIB);
+ return ret;
+ }
+ if (!(s->options & SSL_OP_SINGLE_DH_USE) && !DH_generate_key(dh)) {
+ DH_free(dh);
+ OPENSSL_PUT_ERROR(SSL, ssl3_ctrl, ERR_R_DH_LIB);
+ return ret;
+ }
+ if (s->cert->dh_tmp != NULL) {
+ DH_free(s->cert->dh_tmp);
+ }
+ s->cert->dh_tmp = dh;
+ ret = 1;
+ break;
+ }
+
+ case SSL_CTRL_SET_TMP_DH_CB:
+ OPENSSL_PUT_ERROR(SSL, ssl3_ctrl, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return ret;
+
+ case SSL_CTRL_SET_TMP_ECDH: {
+ EC_KEY *ecdh = NULL;
+
+ if (parg == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_ctrl, ERR_R_PASSED_NULL_PARAMETER);
+ return ret;
+ }
+ if (!EC_KEY_up_ref((EC_KEY *)parg)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_ctrl, ERR_R_ECDH_LIB);
+ return ret;
+ }
+ ecdh = (EC_KEY *)parg;
+ if (!(s->options & SSL_OP_SINGLE_ECDH_USE) && !EC_KEY_generate_key(ecdh)) {
+ EC_KEY_free(ecdh);
+ OPENSSL_PUT_ERROR(SSL, ssl3_ctrl, ERR_R_ECDH_LIB);
+ return ret;
+ }
+ if (s->cert->ecdh_tmp != NULL) {
+ EC_KEY_free(s->cert->ecdh_tmp);
+ }
+ s->cert->ecdh_tmp = ecdh;
+ ret = 1;
+ break;
+ }
+
+ case SSL_CTRL_SET_TMP_ECDH_CB:
+ OPENSSL_PUT_ERROR(SSL, ssl3_ctrl, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return ret;
+
+ case SSL_CTRL_SET_TLSEXT_HOSTNAME:
+ if (larg == TLSEXT_NAMETYPE_host_name) {
+ if (s->tlsext_hostname != NULL) {
+ OPENSSL_free(s->tlsext_hostname);
+ }
+ s->tlsext_hostname = NULL;
+
+ ret = 1;
+ if (parg == NULL) {
+ break;
+ }
+ if (strlen((char *)parg) > TLSEXT_MAXLEN_host_name) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_ctrl, SSL_R_SSL3_EXT_INVALID_SERVERNAME);
+ return 0;
+ }
+ s->tlsext_hostname = BUF_strdup((char *) parg);
+ if (s->tlsext_hostname == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_ctrl, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ } else {
+ OPENSSL_PUT_ERROR(SSL, ssl3_ctrl,
+ SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE);
+ return 0;
+ }
+ break;
+
+ case SSL_CTRL_SET_TLSEXT_DEBUG_ARG:
+ s->tlsext_debug_arg = parg;
+ ret = 1;
+ break;
+
+ case SSL_CTRL_CHAIN:
+ if (larg) {
+ return ssl_cert_set1_chain(s->cert, (STACK_OF(X509) *)parg);
+ } else {
+ return ssl_cert_set0_chain(s->cert, (STACK_OF(X509) *)parg);
+ }
+
+ case SSL_CTRL_CHAIN_CERT:
+ if (larg) {
+ return ssl_cert_add1_chain_cert(s->cert, (X509 *)parg);
+ } else {
+ return ssl_cert_add0_chain_cert(s->cert, (X509 *)parg);
+ }
+
+ case SSL_CTRL_GET_CHAIN_CERTS:
+ *(STACK_OF(X509) **)parg = s->cert->key->chain;
+ break;
+
+ case SSL_CTRL_SELECT_CURRENT_CERT:
+ return ssl_cert_select_current(s->cert, (X509 *)parg);
+
+ case SSL_CTRL_GET_CURVES: {
+ const uint16_t *clist = s->s3->tmp.peer_ellipticcurvelist;
+ size_t clistlen = s->s3->tmp.peer_ellipticcurvelist_length;
+ if (parg) {
+ size_t i;
+ int *cptr = parg;
+ int nid;
+ for (i = 0; i < clistlen; i++) {
+ nid = tls1_ec_curve_id2nid(clist[i]);
+ if (nid != NID_undef) {
+ cptr[i] = nid;
+ } else {
+ cptr[i] = TLSEXT_nid_unknown | clist[i];
+ }
+ }
+ }
+ return (int)clistlen;
+ }
+
+ case SSL_CTRL_SET_CURVES:
+ return tls1_set_curves(&s->tlsext_ellipticcurvelist,
+ &s->tlsext_ellipticcurvelist_length, parg, larg);
+
+ case SSL_CTRL_SET_ECDH_AUTO:
+ s->cert->ecdh_tmp_auto = larg;
+ return 1;
+
+ case SSL_CTRL_SET_SIGALGS:
+ return tls1_set_sigalgs(s->cert, parg, larg, 0);
+
+ case SSL_CTRL_SET_CLIENT_SIGALGS:
+ return tls1_set_sigalgs(s->cert, parg, larg, 1);
+
+ case SSL_CTRL_GET_CLIENT_CERT_TYPES: {
+ const uint8_t **pctype = parg;
+ if (s->server || !s->s3->tmp.cert_req) {
+ return 0;
+ }
+ if (pctype) {
+ *pctype = s->s3->tmp.certificate_types;
+ }
+ return (int)s->s3->tmp.num_certificate_types;
+ }
+
+ case SSL_CTRL_SET_CLIENT_CERT_TYPES:
+ if (!s->server) {
+ return 0;
+ }
+ return ssl3_set_req_cert_type(s->cert, parg, larg);
+
+ case SSL_CTRL_BUILD_CERT_CHAIN:
+ return ssl_build_cert_chain(s->cert, s->ctx->cert_store, larg);
+
+ case SSL_CTRL_SET_VERIFY_CERT_STORE:
+ return ssl_cert_set_cert_store(s->cert, parg, 0, larg);
+
+ case SSL_CTRL_SET_CHAIN_CERT_STORE:
+ return ssl_cert_set_cert_store(s->cert, parg, 1, larg);
+
+ case SSL_CTRL_GET_SERVER_TMP_KEY:
+ if (s->server || !s->session || !s->session->sess_cert) {
+ return 0;
+ } else {
+ SESS_CERT *sc;
+ EVP_PKEY *ptmp;
+ int rv = 0;
+ sc = s->session->sess_cert;
+ if (!sc->peer_dh_tmp && !sc->peer_ecdh_tmp) {
+ return 0;
+ }
+ ptmp = EVP_PKEY_new();
+ if (!ptmp) {
+ return 0;
+ }
+ if (sc->peer_dh_tmp) {
+ rv = EVP_PKEY_set1_DH(ptmp, sc->peer_dh_tmp);
+ } else if (sc->peer_ecdh_tmp) {
+ rv = EVP_PKEY_set1_EC_KEY(ptmp, sc->peer_ecdh_tmp);
+ }
+ if (rv) {
+ *(EVP_PKEY **)parg = ptmp;
+ return 1;
+ }
+ EVP_PKEY_free(ptmp);
+ return 0;
+ }
+
+ case SSL_CTRL_GET_EC_POINT_FORMATS: {
+ const uint8_t **pformat = parg;
+ if (!s->s3->tmp.peer_ecpointformatlist) {
+ return 0;
+ }
+ *pformat = s->s3->tmp.peer_ecpointformatlist;
+ return (int)s->s3->tmp.peer_ecpointformatlist_length;
+ }
+
+ case SSL_CTRL_CHANNEL_ID:
+ s->tlsext_channel_id_enabled = 1;
+ ret = 1;
+ break;
+
+ case SSL_CTRL_SET_CHANNEL_ID:
+ s->tlsext_channel_id_enabled = 1;
+ if (EVP_PKEY_bits(parg) != 256) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_ctrl, SSL_R_CHANNEL_ID_NOT_P256);
+ break;
+ }
+ if (s->tlsext_channel_id_private) {
+ EVP_PKEY_free(s->tlsext_channel_id_private);
+ }
+ s->tlsext_channel_id_private = EVP_PKEY_dup((EVP_PKEY *)parg);
+ ret = 1;
+ break;
+
+ case SSL_CTRL_GET_CHANNEL_ID:
+ if (!s->s3->tlsext_channel_id_valid) {
+ break;
+ }
+ memcpy(parg, s->s3->tlsext_channel_id, larg < 64 ? larg : 64);
+ return 64;
+
+ case SSL_CTRL_FALLBACK_SCSV:
+ s->fallback_scsv = 1;
+ ret = 1;
+ break;
+
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+long ssl3_callback_ctrl(SSL *s, int cmd, void (*fp)(void)) {
+ int ret = 0;
+
+ if ((cmd == SSL_CTRL_SET_TMP_RSA_CB || cmd == SSL_CTRL_SET_TMP_DH_CB) &&
+ !ssl_cert_inst(&s->cert)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_callback_ctrl, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ switch (cmd) {
+ case SSL_CTRL_SET_TMP_RSA_CB:
+ /* Ignore the callback; temporary RSA keys are never used. */
+ break;
+
+ case SSL_CTRL_SET_TMP_DH_CB:
+ s->cert->dh_tmp_cb = (DH * (*)(SSL *, int, int))fp;
+ break;
+
+ case SSL_CTRL_SET_TMP_ECDH_CB:
+ s->cert->ecdh_tmp_cb = (EC_KEY * (*)(SSL *, int, int))fp;
+ break;
+
+ case SSL_CTRL_SET_TLSEXT_DEBUG_CB:
+ s->tlsext_debug_cb =
+ (void (*)(SSL *, int, int, uint8_t *, int, void *))fp;
+ break;
+
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg) {
+ CERT *cert;
+
+ cert = ctx->cert;
+
+ switch (cmd) {
+ case SSL_CTRL_NEED_TMP_RSA:
+ /* Temporary RSA keys are never used. */
+ return 0;
+
+ case SSL_CTRL_SET_TMP_RSA:
+ OPENSSL_PUT_ERROR(SSL, ssl3_ctx_ctrl, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return 0;
+
+ case SSL_CTRL_SET_TMP_RSA_CB:
+ OPENSSL_PUT_ERROR(SSL, ssl3_ctx_ctrl, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return 0;
+
+ case SSL_CTRL_SET_TMP_DH: {
+ DH *new = NULL, *dh;
+
+ dh = (DH *)parg;
+ new = DHparams_dup(dh);
+ if (new == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_ctx_ctrl, ERR_R_DH_LIB);
+ return 0;
+ }
+ if (!(ctx->options & SSL_OP_SINGLE_DH_USE) && !DH_generate_key(new)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_ctx_ctrl, ERR_R_DH_LIB);
+ DH_free(new);
+ return 0;
+ }
+ if (cert->dh_tmp != NULL) {
+ DH_free(cert->dh_tmp);
+ }
+ cert->dh_tmp = new;
+ return 1;
+ }
+
+ case SSL_CTRL_SET_TMP_DH_CB:
+ OPENSSL_PUT_ERROR(SSL, ssl3_ctx_ctrl, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return 0;
+
+ case SSL_CTRL_SET_TMP_ECDH: {
+ EC_KEY *ecdh = NULL;
+
+ if (parg == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_ctx_ctrl, ERR_R_ECDH_LIB);
+ return 0;
+ }
+ ecdh = EC_KEY_dup((EC_KEY *)parg);
+ if (ecdh == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_ctx_ctrl, ERR_R_EC_LIB);
+ return 0;
+ }
+ if (!(ctx->options & SSL_OP_SINGLE_ECDH_USE) &&
+ !EC_KEY_generate_key(ecdh)) {
+ EC_KEY_free(ecdh);
+ OPENSSL_PUT_ERROR(SSL, ssl3_ctx_ctrl, ERR_R_ECDH_LIB);
+ return 0;
+ }
+
+ if (cert->ecdh_tmp != NULL) {
+ EC_KEY_free(cert->ecdh_tmp);
+ }
+ cert->ecdh_tmp = ecdh;
+ return 1;
+ }
+
+ case SSL_CTRL_SET_TMP_ECDH_CB:
+ OPENSSL_PUT_ERROR(SSL, ssl3_ctx_ctrl, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return 0;
+
+ case SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG:
+ ctx->tlsext_servername_arg = parg;
+ break;
+
+ case SSL_CTRL_SET_TLSEXT_TICKET_KEYS:
+ case SSL_CTRL_GET_TLSEXT_TICKET_KEYS: {
+ uint8_t *keys = parg;
+ if (!keys) {
+ return 48;
+ }
+ if (larg != 48) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_ctx_ctrl, SSL_R_INVALID_TICKET_KEYS_LENGTH);
+ return 0;
+ }
+ if (cmd == SSL_CTRL_SET_TLSEXT_TICKET_KEYS) {
+ 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);
+ } else {
+ 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;
+ }
+
+ case SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB_ARG:
+ ctx->tlsext_status_arg = parg;
+ return 1;
+ break;
+
+ case SSL_CTRL_SET_CURVES:
+ return tls1_set_curves(&ctx->tlsext_ellipticcurvelist,
+ &ctx->tlsext_ellipticcurvelist_length, parg, larg);
+
+ case SSL_CTRL_SET_ECDH_AUTO:
+ ctx->cert->ecdh_tmp_auto = larg;
+ return 1;
+
+ case SSL_CTRL_SET_SIGALGS:
+ return tls1_set_sigalgs(ctx->cert, parg, larg, 0);
+
+ case SSL_CTRL_SET_CLIENT_SIGALGS:
+ return tls1_set_sigalgs(ctx->cert, parg, larg, 1);
+
+ case SSL_CTRL_SET_CLIENT_CERT_TYPES:
+ return ssl3_set_req_cert_type(ctx->cert, parg, larg);
+
+ case SSL_CTRL_BUILD_CERT_CHAIN:
+ return ssl_build_cert_chain(ctx->cert, ctx->cert_store, larg);
+
+ case SSL_CTRL_SET_VERIFY_CERT_STORE:
+ return ssl_cert_set_cert_store(ctx->cert, parg, 0, larg);
+
+ case SSL_CTRL_SET_CHAIN_CERT_STORE:
+ return ssl_cert_set_cert_store(ctx->cert, parg, 1, larg);
+
+ case SSL_CTRL_EXTRA_CHAIN_CERT:
+ if (ctx->extra_certs == NULL) {
+ ctx->extra_certs = sk_X509_new_null();
+ if (ctx->extra_certs == NULL) {
+ return 0;
+ }
+ }
+ sk_X509_push(ctx->extra_certs, (X509 *)parg);
+ break;
+
+ case SSL_CTRL_GET_EXTRA_CHAIN_CERTS:
+ if (ctx->extra_certs == NULL && larg == 0) {
+ *(STACK_OF(X509) **)parg = ctx->cert->key->chain;
+ } else {
+ *(STACK_OF(X509) **)parg = ctx->extra_certs;
+ }
+ break;
+
+ case SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS:
+ if (ctx->extra_certs) {
+ sk_X509_pop_free(ctx->extra_certs, X509_free);
+ ctx->extra_certs = NULL;
+ }
+ break;
+
+ case SSL_CTRL_CHAIN:
+ if (larg) {
+ return ssl_cert_set1_chain(ctx->cert, (STACK_OF(X509) *)parg);
+ } else {
+ return ssl_cert_set0_chain(ctx->cert, (STACK_OF(X509) *)parg);
+ }
+
+ case SSL_CTRL_CHAIN_CERT:
+ if (larg) {
+ return ssl_cert_add1_chain_cert(ctx->cert, (X509 *)parg);
+ } else {
+ return ssl_cert_add0_chain_cert(ctx->cert, (X509 *)parg);
+ }
+
+ case SSL_CTRL_GET_CHAIN_CERTS:
+ *(STACK_OF(X509) **)parg = ctx->cert->key->chain;
+ break;
+
+ case SSL_CTRL_SELECT_CURRENT_CERT:
+ return ssl_cert_select_current(ctx->cert, (X509 *)parg);
+
+ case SSL_CTRL_CHANNEL_ID:
+ ctx->tlsext_channel_id_enabled = 1;
+ return 1;
+
+ case SSL_CTRL_SET_CHANNEL_ID:
+ ctx->tlsext_channel_id_enabled = 1;
+ if (EVP_PKEY_bits(parg) != 256) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_ctx_ctrl, SSL_R_CHANNEL_ID_NOT_P256);
+ break;
+ }
+ if (ctx->tlsext_channel_id_private) {
+ EVP_PKEY_free(ctx->tlsext_channel_id_private);
+ }
+ ctx->tlsext_channel_id_private = EVP_PKEY_dup((EVP_PKEY *)parg);
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+long ssl3_ctx_callback_ctrl(SSL_CTX *ctx, int cmd, void (*fp)(void)) {
+ CERT *cert;
+
+ cert = ctx->cert;
+
+ switch (cmd) {
+ case SSL_CTRL_SET_TMP_RSA_CB:
+ /* Ignore the callback; temporary RSA keys are never used. */
+ break;
+
+ case SSL_CTRL_SET_TMP_DH_CB:
+ cert->dh_tmp_cb = (DH * (*)(SSL *, int, int))fp;
+ break;
+
+ case SSL_CTRL_SET_TMP_ECDH_CB:
+ cert->ecdh_tmp_cb = (EC_KEY * (*)(SSL *, int, int))fp;
+ break;
+
+ case SSL_CTRL_SET_TLSEXT_SERVERNAME_CB:
+ ctx->tlsext_servername_callback = (int (*)(SSL *, int *, void *))fp;
+ break;
+
+ case SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB:
+ ctx->tlsext_status_cb = (int (*)(SSL *, void *))fp;
+ break;
+
+ case SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB:
+ ctx->tlsext_ticket_key_cb = (int (
+ *)(SSL *, uint8_t *, uint8_t *, EVP_CIPHER_CTX *, HMAC_CTX *, int))fp;
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+/* ssl3_get_cipher_by_value returns the SSL_CIPHER with value |value| or NULL
+ * if none exists.
+ *
+ * This function needs to check if the ciphers required are actually
+ * available. */
+const SSL_CIPHER *ssl3_get_cipher_by_value(uint16_t value) {
+ SSL_CIPHER c;
+
+ c.id = 0x03000000L | value;
+ return bsearch(&c, ssl3_ciphers, SSL3_NUM_CIPHERS, sizeof(SSL_CIPHER),
+ ssl_cipher_id_cmp);
+}
+
+/* ssl3_get_cipher_by_value returns the cipher value of |c|. */
+uint16_t ssl3_get_cipher_value(const SSL_CIPHER *c) {
+ unsigned long id = c->id;
+ /* All ciphers are SSLv3 now. */
+ assert((id & 0xff000000) == 0x03000000);
+ return id & 0xffff;
+}
+
+struct ssl_cipher_preference_list_st *ssl_get_cipher_preferences(SSL *s) {
+ if (s->cipher_list != NULL) {
+ return s->cipher_list;
+ }
+
+ if (s->version >= TLS1_1_VERSION && s->ctx != NULL &&
+ s->ctx->cipher_list_tls11 != NULL) {
+ return s->ctx->cipher_list_tls11;
+ }
+
+ if (s->ctx != NULL && s->ctx->cipher_list != NULL) {
+ return s->ctx->cipher_list;
+ }
+
+ return NULL;
+}
+
+const SSL_CIPHER *ssl3_choose_cipher(
+ SSL *s, STACK_OF(SSL_CIPHER) * clnt,
+ struct ssl_cipher_preference_list_st *server_pref) {
+ const SSL_CIPHER *c, *ret = NULL;
+ STACK_OF(SSL_CIPHER) *srvr = server_pref->ciphers, *prio, *allow;
+ size_t i;
+ int ok;
+ size_t cipher_index;
+ unsigned long alg_k, alg_a, mask_k, mask_a;
+ /* in_group_flags will either be NULL, or will point to an array of bytes
+ * which indicate equal-preference groups in the |prio| stack. See the
+ * comment about |in_group_flags| in the |ssl_cipher_preference_list_st|
+ * struct. */
+ const uint8_t *in_group_flags;
+ /* group_min contains the minimal index so far found in a group, or -1 if no
+ * such value exists yet. */
+ int group_min = -1;
+
+ if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE) {
+ prio = srvr;
+ in_group_flags = server_pref->in_group_flags;
+ allow = clnt;
+ } else {
+ prio = clnt;
+ in_group_flags = NULL;
+ allow = srvr;
+ }
+
+ ssl_get_compatible_server_ciphers(s, &mask_k, &mask_a);
+
+ for (i = 0; i < sk_SSL_CIPHER_num(prio); i++) {
+ c = sk_SSL_CIPHER_value(prio, i);
+
+ ok = 1;
+
+ /* Skip TLS v1.2 only ciphersuites if not supported */
+ if ((c->algorithm_ssl & SSL_TLSV1_2) && !SSL_USE_TLS1_2_CIPHERS(s)) {
+ ok = 0;
+ }
+
+ alg_k = c->algorithm_mkey;
+ alg_a = c->algorithm_auth;
+
+ ok = ok && (alg_k & mask_k) && (alg_a & mask_a);
+
+ if (ok && sk_SSL_CIPHER_find(allow, &cipher_index, c)) {
+ if (in_group_flags != NULL && in_group_flags[i] == 1) {
+ /* This element of |prio| is in a group. Update the minimum index found
+ * so far and continue looking. */
+ if (group_min == -1 || (size_t)group_min > cipher_index) {
+ group_min = cipher_index;
+ }
+ } else {
+ if (group_min != -1 && (size_t)group_min < cipher_index) {
+ cipher_index = group_min;
+ }
+ ret = sk_SSL_CIPHER_value(allow, cipher_index);
+ break;
+ }
+ }
+
+ if (in_group_flags != NULL && in_group_flags[i] == 0 && group_min != -1) {
+ /* We are about to leave a group, but we found a match in it, so that's
+ * our answer. */
+ ret = sk_SSL_CIPHER_value(allow, group_min);
+ break;
+ }
+ }
+
+ return ret;
+}
+
+int ssl3_get_req_cert_type(SSL *s, uint8_t *p) {
+ int ret = 0;
+ const uint8_t *sig;
+ size_t i, siglen;
+ int have_rsa_sign = 0;
+ int have_ecdsa_sign = 0;
+
+ /* If we have custom certificate types set, use them */
+ if (s->cert->client_certificate_types) {
+ memcpy(p, s->cert->client_certificate_types,
+ s->cert->num_client_certificate_types);
+ return s->cert->num_client_certificate_types;
+ }
+
+ /* get configured sigalgs */
+ siglen = tls12_get_psigalgs(s, &sig);
+ for (i = 0; i < siglen; i += 2, sig += 2) {
+ switch (sig[1]) {
+ case TLSEXT_signature_rsa:
+ have_rsa_sign = 1;
+ break;
+
+ case TLSEXT_signature_ecdsa:
+ have_ecdsa_sign = 1;
+ break;
+ }
+ }
+
+ if (have_rsa_sign) {
+ p[ret++] = SSL3_CT_RSA_SIGN;
+ }
+
+ /* ECDSA certs can be used with RSA cipher suites as well so we don't need to
+ * check for SSL_kECDH or SSL_kEECDH. */
+ if (s->version >= TLS1_VERSION && have_ecdsa_sign) {
+ p[ret++] = TLS_CT_ECDSA_SIGN;
+ }
+
+ return ret;
+}
+
+static int ssl3_set_req_cert_type(CERT *c, const uint8_t *p, size_t len) {
+ if (c->client_certificate_types) {
+ OPENSSL_free(c->client_certificate_types);
+ c->client_certificate_types = NULL;
+ }
+
+ c->num_client_certificate_types = 0;
+ if (!p || !len) {
+ return 1;
+ }
+
+ if (len > 0xff) {
+ return 0;
+ }
+
+ c->client_certificate_types = BUF_memdup(p, len);
+ if (!c->client_certificate_types) {
+ return 0;
+ }
+
+ c->num_client_certificate_types = len;
+ return 1;
+}
+
+int ssl3_shutdown(SSL *s) {
+ int ret;
+
+ /* Do nothing if configured not to send a close_notify. */
+ if (s->quiet_shutdown) {
+ 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 = s->method->ssl_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) {
+ ERR_clear_system_error();
+ 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;
+
+ ERR_clear_system_error();
+ 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;
+ }
+
+ s->s3->renegotiate = 1;
+ return 1;
+}
+
+int ssl3_renegotiate_check(SSL *s) {
+ if (s->s3->renegotiate && s->s3->rbuf.left == 0 && s->s3->wbuf.left == 0 &&
+ !SSL_in_init(s)) {
+ /* if we are the server, and we have sent a 'RENEGOTIATE' message, we
+ * need to go to SSL_ST_ACCEPT. */
+ s->state = SSL_ST_RENEGOTIATE;
+ s->s3->renegotiate = 0;
+ s->s3->num_renegotiations++;
+ s->s3->total_renegotiations++;
+ return 1;
+ }
+
+ return 0;
+}
+
+/* If we are using default SHA1+MD5 algorithms switch to new SHA256 PRF and
+ * handshake macs if required. */
+long ssl_get_algorithm2(SSL *s) {
+ static const unsigned long kMask = SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF;
+ long alg2 = s->s3->tmp.new_cipher->algorithm2;
+ if (s->enc_method->enc_flags & SSL_ENC_FLAG_SHA256_PRF &&
+ (alg2 & kMask) == kMask) {
+ return SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256;
+ }
+ return alg2;
+}
diff --git a/src/ssl/s3_meth.c b/src/ssl/s3_meth.c
new file mode 100644
index 0000000..5a25d7b
--- /dev/null
+++ b/src/ssl/s3_meth.c
@@ -0,0 +1,171 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 "ssl_locl.h"
+
+
+static const SSL_PROTOCOL_METHOD TLS_protocol_method = {
+ ssl3_new,
+ ssl3_free,
+ ssl3_accept,
+ ssl3_connect,
+ ssl3_read,
+ ssl3_peek,
+ ssl3_write,
+ ssl3_shutdown,
+ ssl3_renegotiate,
+ ssl3_renegotiate_check,
+ ssl3_get_message,
+ ssl3_read_bytes,
+ ssl3_write_bytes,
+ ssl3_dispatch_alert,
+ ssl3_ctrl,
+ ssl3_ctx_ctrl,
+ ssl3_pending,
+ ssl3_num_ciphers,
+ ssl3_get_cipher,
+ ssl_undefined_void_function,
+ ssl3_callback_ctrl,
+ ssl3_ctx_callback_ctrl,
+};
+
+const SSL_METHOD *TLS_method(void) {
+ static const SSL_METHOD method = {
+ 0,
+ &TLS_protocol_method,
+ };
+ return &method;
+}
+
+const SSL_METHOD *SSLv23_method(void) {
+ return TLS_method();
+}
+
+/* Legacy version-locked methods. */
+
+const SSL_METHOD *TLSv1_2_method(void) {
+ static const SSL_METHOD method = {
+ TLS1_2_VERSION,
+ &TLS_protocol_method,
+ };
+ return &method;
+}
+
+const SSL_METHOD *TLSv1_1_method(void) {
+ static const SSL_METHOD method = {
+ TLS1_1_VERSION,
+ &TLS_protocol_method,
+ };
+ return &method;
+}
+
+const SSL_METHOD *TLSv1_method(void) {
+ static const SSL_METHOD method = {
+ TLS1_VERSION,
+ &TLS_protocol_method,
+ };
+ return &method;
+}
+
+const SSL_METHOD *SSLv3_method(void) {
+ static const SSL_METHOD method = {
+ SSL3_VERSION,
+ &TLS_protocol_method,
+ };
+ return &method;
+}
+
+/* Legacy side-specific methods. */
+
+const SSL_METHOD *TLSv1_2_server_method(void) {
+ return TLSv1_2_method();
+}
+
+const SSL_METHOD *TLSv1_1_server_method(void) {
+ return TLSv1_1_method();
+}
+
+const SSL_METHOD *TLSv1_server_method(void) {
+ return TLSv1_method();
+}
+
+const SSL_METHOD *SSLv3_server_method(void) {
+ return SSLv3_method();
+}
+
+const SSL_METHOD *TLSv1_2_client_method(void) {
+ return TLSv1_2_method();
+}
+
+const SSL_METHOD *TLSv1_1_client_method(void) {
+ return TLSv1_1_method();
+}
+
+const SSL_METHOD *TLSv1_client_method(void) {
+ return TLSv1_method();
+}
+
+const SSL_METHOD *SSLv3_client_method(void) {
+ return SSLv3_method();
+}
+
+const SSL_METHOD *SSLv23_server_method(void) {
+ return SSLv23_method();
+}
+
+const SSL_METHOD *SSLv23_client_method(void) {
+ return SSLv23_method();
+}
diff --git a/src/ssl/s3_pkt.c b/src/ssl/s3_pkt.c
new file mode 100644
index 0000000..4263cb0
--- /dev/null
+++ b/src/ssl/s3_pkt.c
@@ -0,0 +1,1216 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include <openssl/buf.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/mem.h>
+#include <openssl/rand.h>
+
+#include "ssl_locl.h"
+
+
+static int do_ssl3_write(SSL *s, int type, const uint8_t *buf, unsigned int len,
+ char fragment, char is_fragment);
+static int ssl3_get_record(SSL *s);
+
+int ssl3_read_n(SSL *s, int n, int max, int extend) {
+ /* If |extend| is 0, obtain new n-byte packet;
+ * if |extend| is 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|
+ * is one.) */
+ int i, len, left;
+ long align = 0;
+ uint8_t *pkt;
+ SSL3_BUFFER *rb;
+
+ if (n <= 0) {
+ return n;
+ }
+
+ rb = &s->s3->rbuf;
+ if (rb->buf == NULL && !ssl3_setup_read_buffer(s)) {
+ return -1;
+ }
+
+ left = rb->left;
+
+ align = (long)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) && 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;
+ }
+
+ assert(n <= (int)(rb->len - rb->offset));
+
+ if (!s->read_ahead) {
+ /* ignore max parameter */
+ max = n;
+ } else {
+ if (max < n) {
+ max = n;
+ }
+ if (max > (int)(rb->len - rb->offset)) {
+ max = rb->len - rb->offset;
+ }
+ }
+
+ 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). */
+ ERR_clear_system_error();
+ if (s->rbio != NULL) {
+ s->rwstate = SSL_READING;
+ i = BIO_read(s->rbio, pkt + len + left, max - left);
+ } else {
+ OPENSSL_PUT_ERROR(SSL, ssl3_read_n, 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) &&
+ 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) && 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;
+}
+
+/* MAX_EMPTY_RECORDS defines the number of consecutive, empty records that will
+ * be processed per call to ssl3_get_record. Without this limit an attacker
+ * could send empty records at a faster rate than we can process and cause
+ * ssl3_get_record to loop forever. */
+#define MAX_EMPTY_RECORDS 32
+
+/* 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) {
+ int ssl_major, ssl_minor, al;
+ int n, i, ret = -1;
+ SSL3_RECORD *rr;
+ uint8_t *p;
+ short version;
+ size_t extra;
+ unsigned empty_record_count = 0;
+
+ rr = &s->s3->rrec;
+
+ if (s->options & SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER) {
+ extra = SSL3_RT_MAX_EXTRA;
+ } else {
+ extra = 0;
+ }
+
+ if (extra && !s->s3->init_extra) {
+ /* An application error: SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER set after
+ * ssl3_setup_buffers() was done */
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_record, ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
+
+again:
+ /* check if we have the header */
+ if (s->rstate != SSL_ST_READ_BODY ||
+ s->packet_length < SSL3_RT_HEADER_LENGTH) {
+ n = ssl3_read_n(s, SSL3_RT_HEADER_LENGTH, s->s3->rbuf.len, 0);
+ if (n <= 0) {
+ return n; /* error or non-blocking */
+ }
+ s->rstate = SSL_ST_READ_BODY;
+
+ p = s->packet;
+ if (s->msg_callback) {
+ s->msg_callback(0, 0, SSL3_RT_HEADER, p, 5, s, s->msg_callback_arg);
+ }
+
+ /* Pull apart the header into the SSL3_RECORD */
+ rr->type = *(p++);
+ ssl_major = *(p++);
+ ssl_minor = *(p++);
+ version = (ssl_major << 8) | ssl_minor;
+ n2s(p, rr->length);
+
+ if (s->s3->have_version && version != s->version) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_record, SSL_R_WRONG_VERSION_NUMBER);
+ if ((s->version & 0xFF00) == (version & 0xFF00)) {
+ /* Send back error using their minor version number. */
+ s->version = (unsigned short)version;
+ }
+ al = SSL_AD_PROTOCOL_VERSION;
+ goto f_err;
+ }
+
+ if ((version >> 8) != SSL3_VERSION_MAJOR) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_record, SSL_R_WRONG_VERSION_NUMBER);
+ goto err;
+ }
+
+ if (rr->length > s->s3->rbuf.len - SSL3_RT_HEADER_LENGTH) {
+ al = SSL_AD_RECORD_OVERFLOW;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_record, SSL_R_PACKET_LENGTH_TOO_LONG);
+ goto f_err;
+ }
+
+ /* now s->rstate == SSL_ST_READ_BODY */
+ }
+
+ /* s->rstate == SSL_ST_READ_BODY, get and decode the data */
+
+ if (rr->length > s->packet_length - SSL3_RT_HEADER_LENGTH) {
+ /* now s->packet_length == SSL3_RT_HEADER_LENGTH */
+ i = rr->length;
+ n = ssl3_read_n(s, i, i, 1);
+ if (n <= 0) {
+ /* Error or non-blocking IO. Now |n| == |rr->length|, and
+ * |s->packet_length| == |SSL3_RT_HEADER_LENGTH| + |rr->length|. */
+ return n;
+ }
+ }
+
+ s->rstate = SSL_ST_READ_HEADER; /* set state for later operations */
+
+ /* At this point, s->packet_length == SSL3_RT_HEADER_LNGTH + rr->length, and
+ * we have that many bytes in s->packet. */
+ rr->input = &s->packet[SSL3_RT_HEADER_LENGTH];
+
+ /* ok, we can now read from |s->packet| data into |rr|. |rr->input| points at
+ * |rr->length| bytes, which need to be copied into |rr->data| by decryption.
+ * When the data is 'copied' into the |rr->data| buffer, |rr->input| will be
+ * pointed at the new buffer. */
+
+ /* We now have - encrypted [ MAC [ compressed [ plain ] ] ]
+ * rr->length bytes of encrypted compressed stuff. */
+
+ /* check is not needed I believe */
+ if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH + extra) {
+ al = SSL_AD_RECORD_OVERFLOW;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_record, SSL_R_ENCRYPTED_LENGTH_TOO_LONG);
+ goto f_err;
+ }
+
+ /* decrypt in place in 'rr->input' */
+ rr->data = rr->input;
+
+ if (!s->enc_method->enc(s, 0)) {
+ al = SSL_AD_BAD_RECORD_MAC;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_record,
+ SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
+ goto f_err;
+ }
+
+ if (rr->length > SSL3_RT_MAX_PLAIN_LENGTH + extra) {
+ al = SSL_AD_RECORD_OVERFLOW;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_record, SSL_R_DATA_LENGTH_TOO_LONG);
+ goto f_err;
+ }
+
+ rr->off = 0;
+ /* So at this point the following is true:
+ * ssl->s3->rrec.type is the type of record;
+ * ssl->s3->rrec.length is the number of bytes in the record;
+ * ssl->s3->rrec.off is the offset to first valid byte;
+ * ssl->s3->rrec.data is where to take bytes from (increment after use). */
+
+ /* we have pulled in a full packet so zero things */
+ s->packet_length = 0;
+
+ /* just read a 0 length packet */
+ if (rr->length == 0) {
+ empty_record_count++;
+ if (empty_record_count > MAX_EMPTY_RECORDS) {
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_record, SSL_R_TOO_MANY_EMPTY_FRAGMENTS);
+ goto f_err;
+ }
+ goto again;
+ }
+
+ return 1;
+
+f_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 uint8_t *buf = buf_;
+ unsigned int tot, n, nw;
+ int i;
+
+ s->rwstate = SSL_NOTHING;
+ assert(s->s3->wnum <= INT_MAX);
+ 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) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_write_bytes, SSL_R_SSL_HANDSHAKE_FAILURE);
+ return -1;
+ }
+ }
+
+ /* Ensure that if we end up with a smaller value of data to write out than
+ * the the original len from a write which didn't complete for non-blocking
+ * I/O and also somehow ended up avoiding the check for this in
+ * ssl3_write_pending/SSL_R_BAD_WRITE_RETRY as it must never be possible to
+ * end up with (len-tot) as a large number that will then promptly send
+ * beyond the end of the users buffer ... so we trap and report the error in
+ * a way the user will notice. */
+ if (len < 0 || (size_t)len < tot) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_write_bytes, SSL_R_BAD_LENGTH);
+ return -1;
+ }
+
+ n = (len - tot);
+ for (;;) {
+ /* max contains the maximum number of bytes that we can put into a
+ * record. */
+ unsigned max = s->max_send_fragment;
+ /* fragment is true if do_ssl3_write should send the first byte in its own
+ * record in order to randomise a CBC IV. */
+ int fragment = 0;
+
+ if (n > 1 && s->s3->need_record_splitting &&
+ type == SSL3_RT_APPLICATION_DATA && !s->s3->record_split_done) {
+ fragment = 1;
+ /* record_split_done records that the splitting has been done in case we
+ * hit an SSL_WANT_WRITE condition. In that case, we don't need to do the
+ * split again. */
+ s->s3->record_split_done = 1;
+ }
+
+ if (n > max) {
+ nw = max;
+ } else {
+ nw = n;
+ }
+
+ i = do_ssl3_write(s, type, &(buf[tot]), nw, fragment, 0);
+ if (i <= 0) {
+ s->s3->wnum = tot;
+ s->s3->record_split_done = 0;
+ 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, one-byte fragment in
+ * ciphersuites with known-IV weakness. */
+ s->s3->record_split_done = 0;
+ return tot + i;
+ }
+
+ n -= i;
+ tot += i;
+ }
+}
+
+/* do_ssl3_write writes an SSL record of the given type. If |fragment| is 1
+ * then it splits the record into a one byte record and a record with the rest
+ * of the data in order to randomise a CBC IV. If |is_fragment| is true then
+ * this call resulted from do_ssl3_write calling itself in order to create that
+ * one byte fragment. */
+static int do_ssl3_write(SSL *s, int type, const uint8_t *buf, unsigned int len,
+ char fragment, char is_fragment) {
+ uint8_t *p, *plen;
+ int i;
+ int prefix_len = 0;
+ int eivlen = 0;
+ long align = 0;
+ SSL3_RECORD *wr;
+ SSL3_BUFFER *wb = &(s->s3->wbuf);
+
+ /* first check if there is a SSL3_BUFFER 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, lets send it */
+ if (s->s3->alert_dispatch) {
+ i = s->method->ssl_dispatch_alert(s);
+ if (i <= 0) {
+ return i;
+ }
+ /* if it went, fall through and send more stuff */
+ }
+
+ if (wb->buf == NULL && !ssl3_setup_write_buffer(s)) {
+ return -1;
+ }
+
+ if (len == 0) {
+ return 0;
+ }
+
+ wr = &s->s3->wrec;
+
+ if (fragment) {
+ /* countermeasure against known-IV weakness in CBC ciphersuites (see
+ * http://www.openssl.org/~bodo/tls-cbc.txt) */
+ prefix_len = do_ssl3_write(s, type, buf, 1 /* length */, 0 /* fragment */,
+ 1 /* is_fragment */);
+ if (prefix_len <= 0) {
+ goto err;
+ }
+
+ if (prefix_len >
+ (SSL3_RT_HEADER_LENGTH + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD)) {
+ /* insufficient space */
+ OPENSSL_PUT_ERROR(SSL, do_ssl3_write, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ }
+
+ if (is_fragment) {
+ /* The extra fragment would be couple of cipher blocks, and that will be a
+ * multiple of SSL3_ALIGN_PAYLOAD. So, if we want to align the real
+ * payload, we can just pretend that we have two headers and a byte. */
+ align = (long)wb->buf + 2 * SSL3_RT_HEADER_LENGTH + 1;
+ align = (-align) & (SSL3_ALIGN_PAYLOAD - 1);
+ p = wb->buf + align;
+ wb->offset = align;
+ } else if (prefix_len) {
+ p = wb->buf + wb->offset + prefix_len;
+ } else {
+ align = (long)wb->buf + SSL3_RT_HEADER_LENGTH;
+ align = (-align) & (SSL3_ALIGN_PAYLOAD - 1);
+ p = wb->buf + align;
+ wb->offset = align;
+ }
+
+ /* write the header */
+
+ *(p++) = type & 0xff;
+ wr->type = type;
+
+ /* Some servers hang if initial ClientHello is larger than 256 bytes and
+ * record version number > TLS 1.0. */
+ if (!s->s3->have_version && s->version > SSL3_VERSION) {
+ *(p++) = TLS1_VERSION >> 8;
+ *(p++) = TLS1_VERSION & 0xff;
+ } else {
+ *(p++) = s->version >> 8;
+ *(p++) = s->version & 0xff;
+ }
+
+ /* field where we are to write out packet length */
+ plen = p;
+ p += 2;
+
+ /* Leave room for the variable nonce for AEADs which specify it explicitly. */
+ if (s->aead_write_ctx != NULL &&
+ s->aead_write_ctx->variable_nonce_included_in_record) {
+ eivlen = s->aead_write_ctx->variable_nonce_len;
+ }
+
+ /* lets setup the record stuff. */
+ wr->data = p + eivlen;
+ wr->length = (int)(len - (fragment != 0));
+ wr->input = (uint8_t *)buf + (fragment != 0);
+
+ /* we now 'read' from wr->input, wr->length bytes into wr->data */
+
+ memcpy(wr->data, wr->input, wr->length);
+ wr->input = wr->data;
+
+ /* we should still have the output to wr->data and the input from wr->input.
+ * Length should be wr->length. wr->data still points in the wb->buf */
+
+ wr->input = p;
+ wr->data = p;
+ wr->length += eivlen;
+
+ if (!s->enc_method->enc(s, 1)) {
+ goto err;
+ }
+
+ /* record length after mac and block padding */
+ s2n(wr->length, plen);
+
+ if (s->msg_callback) {
+ s->msg_callback(1, 0, SSL3_RT_HEADER, plen - 5, 5, s, s->msg_callback_arg);
+ }
+
+ /* we should now have wr->data pointing to the encrypted data, which is
+ * wr->length long. */
+ wr->type = type; /* not needed but helps for debugging */
+ wr->length += SSL3_RT_HEADER_LENGTH;
+
+ if (is_fragment) {
+ /* we are in a recursive call; just return the length, don't write out
+ * anything. */
+ return wr->length;
+ }
+
+ /* now let's set up wb */
+ wb->left = prefix_len + wr->length;
+
+ /* 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:
+ return -1;
+}
+
+/* if s->s3->wbuf.left != 0, we need to call this */
+int ssl3_write_pending(SSL *s, int type, const uint8_t *buf, unsigned int len) {
+ int i;
+ SSL3_BUFFER *wb = &(s->s3->wbuf);
+
+ 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) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_write_pending, SSL_R_BAD_WRITE_RETRY);
+ return -1;
+ }
+
+ for (;;) {
+ ERR_clear_system_error();
+ if (s->wbio != NULL) {
+ s->rwstate = SSL_WRITING;
+ i = BIO_write(s->wbio, (char *)&(wb->buf[wb->offset]),
+ (unsigned int)wb->left);
+ } else {
+ OPENSSL_PUT_ERROR(SSL, ssl3_write_pending, 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) {
+ if (SSL_IS_DTLS(s)) {
+ /* For DTLS, just drop it. That's kind of the whole
+ point in using a datagram service */
+ wb->left = 0;
+ }
+ return i;
+ }
+ wb->offset += i;
+ wb->left -= i;
+ }
+}
+
+/* ssl3_expect_change_cipher_spec informs the record layer that a
+ * ChangeCipherSpec record is required at this point. If a Handshake record is
+ * received before ChangeCipherSpec, the connection will fail. Moreover, if
+ * there are unprocessed handshake bytes, the handshake will also fail and the
+ * function returns zero. Otherwise, the function returns one. */
+int ssl3_expect_change_cipher_spec(SSL *s) {
+ if (s->s3->handshake_fragment_len > 0 || s->s3->tmp.reuse_message) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_expect_change_cipher_spec,
+ SSL_R_UNPROCESSED_HANDSHAKE_DATA);
+ return 0;
+ }
+
+ s->s3->flags |= SSL3_FLAGS_EXPECT_CCS;
+ 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, uint8_t *buf, int len, int peek) {
+ int al, i, j, ret;
+ unsigned int n;
+ SSL3_RECORD *rr;
+ void (*cb)(const SSL *ssl, int type2, int val) = NULL;
+ uint8_t alert_buffer[2];
+
+ if (s->s3->rbuf.buf == NULL && !ssl3_setup_read_buffer(s)) {
+ return -1;
+ }
+
+ if ((type && type != SSL3_RT_APPLICATION_DATA && type != SSL3_RT_HANDSHAKE) ||
+ (peek && type != SSL3_RT_APPLICATION_DATA)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
+
+ if (type == SSL3_RT_HANDSHAKE && s->s3->handshake_fragment_len > 0) {
+ /* (partially) satisfy request from storage */
+ uint8_t *src = s->s3->handshake_fragment;
+ uint8_t *dst = buf;
+ unsigned int k;
+
+ /* peek == 0 */
+ n = 0;
+ while (len > 0 && s->s3->handshake_fragment_len > 0) {
+ *dst++ = *src++;
+ len--;
+ s->s3->handshake_fragment_len--;
+ n++;
+ }
+ /* move any remaining fragment bytes: */
+ for (k = 0; k < s->s3->handshake_fragment_len; k++) {
+ s->s3->handshake_fragment[k] = *src++;
+ }
+ return n;
+ }
+
+ /* Now s->s3->handshake_fragment_len == 0 if type == SSL3_RT_HANDSHAKE. */
+
+ if (!s->in_handshake && SSL_in_init(s)) {
+ /* type == SSL3_RT_APPLICATION_DATA */
+ i = s->handshake_func(s);
+ if (i < 0) {
+ return i;
+ }
+ if (i == 0) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, SSL_R_SSL_HANDSHAKE_FAILURE);
+ return -1;
+ }
+ }
+
+start:
+ s->rwstate = SSL_NOTHING;
+
+ /* s->s3->rrec.type - is the type of record
+ * s->s3->rrec.data - data
+ * s->s3->rrec.off - offset into 'data' for next read
+ * s->s3->rrec.length - number of bytes. */
+ rr = &s->s3->rrec;
+
+ /* get new packet if necessary */
+ if (rr->length == 0 || s->rstate == SSL_ST_READ_BODY) {
+ ret = ssl3_get_record(s);
+ if (ret <= 0) {
+ return ret;
+ }
+ }
+
+ /* we now have a packet which can be read and processed */
+
+ if (s->s3->change_cipher_spec /* set when we receive ChangeCipherSpec,
+ * reset by ssl3_get_finished */
+ && rr->type != SSL3_RT_HANDSHAKE) {
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes,
+ SSL_R_DATA_BETWEEN_CCS_AND_FINISHED);
+ goto f_err;
+ }
+
+ /* If we are expecting a ChangeCipherSpec, it is illegal to receive a
+ * Handshake record. */
+ if (rr->type == SSL3_RT_HANDSHAKE && (s->s3->flags & SSL3_FLAGS_EXPECT_CCS)) {
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, SSL_R_HANDSHAKE_RECORD_BEFORE_CCS);
+ goto f_err;
+ }
+
+ /* If the other end has shut down, throw anything we read away (even in
+ * 'peek' mode) */
+ if (s->shutdown & SSL_RECEIVED_SHUTDOWN) {
+ rr->length = 0;
+ s->rwstate = SSL_NOTHING;
+ return 0;
+ }
+
+ if (type == rr->type) {
+ /* SSL3_RT_APPLICATION_DATA or SSL3_RT_HANDSHAKE */
+ /* 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 &&
+ s->aead_read_ctx == NULL) {
+ /* TODO(davidben): Is this check redundant with the handshake_func
+ * check? */
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, SSL_R_APP_DATA_IN_HANDSHAKE);
+ goto f_err;
+ }
+
+ if (len <= 0) {
+ return len;
+ }
+
+ if ((unsigned int)len > rr->length) {
+ n = rr->length;
+ } else {
+ n = (unsigned int)len;
+ }
+
+ memcpy(buf, &(rr->data[rr->off]), n);
+ if (!peek) {
+ rr->length -= n;
+ rr->off += n;
+ if (rr->length == 0) {
+ s->rstate = SSL_ST_READ_HEADER;
+ rr->off = 0;
+ if (s->mode & SSL_MODE_RELEASE_BUFFERS && s->s3->rbuf.left == 0) {
+ ssl3_release_read_buffer(s);
+ }
+ }
+ }
+
+ return n;
+ }
+
+
+ /* If we get here, then type != rr->type; if we have a handshake message,
+ * then it was unexpected (Hello Request or Client Hello). */
+
+ /* In case of record types for which we have 'fragment' storage, fill that so
+ * that we can process the data at a fixed place. */
+
+ if (rr->type == SSL3_RT_HANDSHAKE) {
+ const size_t size = sizeof(s->s3->handshake_fragment);
+ const size_t avail = size - s->s3->handshake_fragment_len;
+ const size_t todo = (rr->length < avail) ? rr->length : avail;
+ memcpy(s->s3->handshake_fragment + s->s3->handshake_fragment_len,
+ &rr->data[rr->off], todo);
+ rr->off += todo;
+ rr->length -= todo;
+ s->s3->handshake_fragment_len += todo;
+ if (s->s3->handshake_fragment_len < size) {
+ goto start; /* fragment was too small */
+ }
+ } else if (rr->type == SSL3_RT_ALERT) {
+ /* Note that this will still allow multiple alerts to be processed in the
+ * same record */
+ if (rr->length < sizeof(alert_buffer)) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, SSL_R_BAD_ALERT);
+ goto f_err;
+ }
+ memcpy(alert_buffer, &rr->data[rr->off], sizeof(alert_buffer));
+ rr->off += sizeof(alert_buffer);
+ rr->length -= sizeof(alert_buffer);
+ }
+
+ /* s->s3->handshake_fragment_len == 4 iff rr->type == SSL3_RT_HANDSHAKE;
+ * (Possibly rr is 'empty' now, i.e. rr->length may be 0.) */
+
+ /* If we are a client, check for an incoming 'Hello Request': */
+ if (!s->server && s->s3->handshake_fragment_len >= 4 &&
+ s->s3->handshake_fragment[0] == SSL3_MT_HELLO_REQUEST &&
+ s->session != NULL && s->session->cipher != NULL) {
+ s->s3->handshake_fragment_len = 0;
+
+ if (s->s3->handshake_fragment[1] != 0 ||
+ s->s3->handshake_fragment[2] != 0 ||
+ s->s3->handshake_fragment[3] != 0) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, SSL_R_BAD_HELLO_REQUEST);
+ goto f_err;
+ }
+
+ if (s->msg_callback) {
+ s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE,
+ s->s3->handshake_fragment, 4, s, s->msg_callback_arg);
+ }
+
+ if (SSL_is_init_finished(s) && !s->s3->renegotiate) {
+ ssl3_renegotiate(s);
+ if (ssl3_renegotiate_check(s)) {
+ i = s->handshake_func(s);
+ if (i < 0) {
+ return i;
+ }
+ if (i == 0) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, SSL_R_SSL_HANDSHAKE_FAILURE);
+ return -1;
+ }
+ }
+ }
+ /* we either finished a handshake or ignored the request, now try again to
+ * obtain the (application) data we were asked for */
+ goto start;
+ }
+
+ if (rr->type == SSL3_RT_ALERT) {
+ const uint8_t alert_level = alert_buffer[0];
+ const uint8_t alert_descr = alert_buffer[1];
+
+ if (s->msg_callback) {
+ s->msg_callback(0, s->version, SSL3_RT_ALERT, alert_buffer, 2, s,
+ s->msg_callback_arg);
+ }
+
+ if (s->info_callback != NULL) {
+ cb = s->info_callback;
+ } else if (s->ctx->info_callback != NULL) {
+ cb = s->ctx->info_callback;
+ }
+
+ if (cb != NULL) {
+ j = (alert_level << 8) | alert_descr;
+ cb(s, SSL_CB_READ_ALERT, j);
+ }
+
+ if (alert_level == 1) {
+ /* warning */
+ s->s3->warn_alert = alert_descr;
+ if (alert_descr == SSL_AD_CLOSE_NOTIFY) {
+ s->shutdown |= SSL_RECEIVED_SHUTDOWN;
+ return 0;
+ }
+
+ /* This is a warning but we receive it if we requested renegotiation and
+ * the peer denied it. Terminate with a fatal alert because if
+ * application tried to renegotiatie it presumably had a good reason and
+ * expects it to succeed.
+ *
+ * In future we might have a renegotiation where we don't care if the
+ * peer refused it where we carry on. */
+ else if (alert_descr == SSL_AD_NO_RENEGOTIATION) {
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, SSL_R_NO_RENEGOTIATION);
+ goto f_err;
+ }
+ } else if (alert_level == 2) {
+ /* fatal */
+ char tmp[16];
+
+ s->rwstate = SSL_NOTHING;
+ s->s3->fatal_alert = alert_descr;
+ OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes,
+ SSL_AD_REASON_OFFSET + alert_descr);
+ BIO_snprintf(tmp, sizeof(tmp), "%d", alert_descr);
+ ERR_add_error_data(2, "SSL alert number ", tmp);
+ s->shutdown |= SSL_RECEIVED_SHUTDOWN;
+ SSL_CTX_remove_session(s->ctx, s->session);
+ return 0;
+ } else {
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, SSL_R_UNKNOWN_ALERT_TYPE);
+ goto f_err;
+ }
+
+ goto start;
+ }
+
+ if (s->shutdown & SSL_SENT_SHUTDOWN) {
+ /* but we have not received a shutdown */
+ s->rwstate = SSL_NOTHING;
+ rr->length = 0;
+ return 0;
+ }
+
+ if (rr->type == SSL3_RT_CHANGE_CIPHER_SPEC) {
+ /* 'Change Cipher Spec' is just a single byte, so we know exactly what the
+ * record payload has to look like */
+ if (rr->length != 1 || rr->off != 0 || rr->data[0] != SSL3_MT_CCS) {
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, SSL_R_BAD_CHANGE_CIPHER_SPEC);
+ goto f_err;
+ }
+
+ /* Check we have a cipher to change to */
+ if (s->s3->tmp.new_cipher == NULL) {
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, SSL_R_CCS_RECEIVED_EARLY);
+ goto f_err;
+ }
+
+ if (!(s->s3->flags & SSL3_FLAGS_EXPECT_CCS)) {
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, SSL_R_CCS_RECEIVED_EARLY);
+ goto f_err;
+ }
+
+ s->s3->flags &= ~SSL3_FLAGS_EXPECT_CCS;
+
+ rr->length = 0;
+
+ if (s->msg_callback) {
+ s->msg_callback(0, s->version, SSL3_RT_CHANGE_CIPHER_SPEC, rr->data, 1, s,
+ s->msg_callback_arg);
+ }
+
+ s->s3->change_cipher_spec = 1;
+ if (!ssl3_do_change_cipher_spec(s)) {
+ goto err;
+ } else {
+ goto start;
+ }
+ }
+
+ /* Unexpected handshake message (Client Hello, or protocol violation) */
+ if (s->s3->handshake_fragment_len >= 4 && !s->in_handshake) {
+ if ((s->state & SSL_ST_MASK) == SSL_ST_OK) {
+ s->state = s->server ? SSL_ST_ACCEPT : SSL_ST_CONNECT;
+ s->renegotiate = 1;
+ s->new_session = 1;
+ }
+ i = s->handshake_func(s);
+ if (i < 0) {
+ return i;
+ }
+ if (i == 0) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, SSL_R_SSL_HANDSHAKE_FAILURE);
+ return -1;
+ }
+
+ goto start;
+ }
+
+ switch (rr->type) {
+ default:
+ /* TLS up to v1.1 just ignores unknown message types. TLS v1.2 gives an
+ * unexpected message alert. */
+ if (s->version >= TLS1_VERSION && s->version <= TLS1_1_VERSION) {
+ rr->length = 0;
+ goto start;
+ }
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, SSL_R_UNEXPECTED_RECORD);
+ goto f_err;
+
+ case SSL3_RT_CHANGE_CIPHER_SPEC:
+ case SSL3_RT_ALERT:
+ case SSL3_RT_HANDSHAKE:
+ /* we already handled all of these, with the possible exception of
+ * SSL3_RT_HANDSHAKE when s->in_handshake is set, but that should not
+ * happen when type != rr->type */
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, ERR_R_INTERNAL_ERROR);
+ goto f_err;
+
+ case 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 && s->s3->total_renegotiations != 0 &&
+ (((s->state & SSL_ST_CONNECT) &&
+ s->state >= SSL3_ST_CW_CLNT_HELLO_A &&
+ s->state <= SSL3_ST_CR_SRVR_HELLO_A) ||
+ ((s->state & SSL_ST_ACCEPT) &&
+ s->state <= SSL3_ST_SW_HELLO_REQ_A &&
+ s->state >= SSL3_ST_SR_CLNT_HELLO_A))) {
+ s->s3->in_read_app_data = 2;
+ return -1;
+ } else {
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, SSL_R_UNEXPECTED_RECORD);
+ goto f_err;
+ }
+ }
+ /* not reached */
+
+f_err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+err:
+ return -1;
+}
+
+int ssl3_do_change_cipher_spec(SSL *s) {
+ int i;
+
+ if (s->state & SSL_ST_ACCEPT) {
+ i = SSL3_CHANGE_CIPHER_SERVER_READ;
+ } else {
+ i = SSL3_CHANGE_CIPHER_CLIENT_READ;
+ }
+
+ if (s->s3->tmp.key_block == NULL) {
+ if (s->session == NULL || s->session->master_key_length == 0) {
+ /* might happen if dtls1_read_bytes() calls this */
+ OPENSSL_PUT_ERROR(SSL, ssl3_do_change_cipher_spec,
+ SSL_R_CCS_RECEIVED_EARLY);
+ return 0;
+ }
+
+ s->session->cipher = s->s3->tmp.new_cipher;
+ if (!s->enc_method->setup_key_block(s)) {
+ return 0;
+ }
+ }
+
+ if (!s->enc_method->change_cipher_state(s, i)) {
+ return 0;
+ }
+
+ return 1;
+}
+
+int ssl3_send_alert(SSL *s, int level, int desc) {
+ /* Map tls/ssl alert value to correct one */
+ desc = s->enc_method->alert_value(desc);
+ if (s->version == SSL3_VERSION && desc == SSL_AD_PROTOCOL_VERSION) {
+ /* SSL 3.0 does not have protocol_version alerts */
+ desc = SSL_AD_HANDSHAKE_FAILURE;
+ }
+ if (desc < 0) {
+ return -1;
+ }
+
+ /* If a fatal one, remove from cache */
+ if (level == 2 && s->session != NULL) {
+ 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 (s->s3->wbuf.left == 0) {
+ /* data is still being written out. */
+ return s->method->ssl_dispatch_alert(s);
+ }
+
+ /* else data is still being written out, we will get written some time in the
+ * future */
+ return -1;
+}
+
+int ssl3_dispatch_alert(SSL *s) {
+ int i, j;
+ void (*cb)(const SSL *ssl, int type, int val) = NULL;
+
+ s->s3->alert_dispatch = 0;
+ i = do_ssl3_write(s, SSL3_RT_ALERT, &s->s3->send_alert[0], 2, 0, 0);
+ if (i <= 0) {
+ s->s3->alert_dispatch = 1;
+ } else {
+ /* 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) {
+ BIO_flush(s->wbio);
+ }
+
+ if (s->msg_callback) {
+ s->msg_callback(1, s->version, SSL3_RT_ALERT, s->s3->send_alert, 2, s,
+ s->msg_callback_arg);
+ }
+
+ if (s->info_callback != NULL) {
+ cb = s->info_callback;
+ } else if (s->ctx->info_callback != NULL) {
+ cb = s->ctx->info_callback;
+ }
+
+ if (cb != NULL) {
+ j = (s->s3->send_alert[0] << 8) | s->s3->send_alert[1];
+ cb(s, SSL_CB_WRITE_ALERT, j);
+ }
+ }
+
+ return i;
+}
diff --git a/src/ssl/s3_srvr.c b/src/ssl/s3_srvr.c
new file mode 100644
index 0000000..b346d14
--- /dev/null
+++ b/src/ssl/s3_srvr.c
@@ -0,0 +1,2807 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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. */
+
+#define NETSCAPE_HANG_BUG
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <openssl/bn.h>
+#include <openssl/buf.h>
+#include <openssl/bytestring.h>
+#include <openssl/cipher.h>
+#include <openssl/dh.h>
+#include <openssl/ec.h>
+#include <openssl/ecdsa.h>
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
+#include <openssl/md5.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/rand.h>
+#include <openssl/sha.h>
+#include <openssl/x509.h>
+
+#include "ssl_locl.h"
+#include "../crypto/internal.h"
+#include "../crypto/dh/internal.h"
+
+
+/* INITIAL_SNIFF_BUFFER_SIZE is the number of bytes read in the initial sniff
+ * buffer. */
+#define INITIAL_SNIFF_BUFFER_SIZE 8
+
+int ssl3_accept(SSL *s) {
+ BUF_MEM *buf = NULL;
+ unsigned long alg_a;
+ void (*cb)(const SSL *ssl, int type, int val) = NULL;
+ int ret = -1;
+ int new_state, state, skip = 0;
+
+ assert(s->handshake_func == ssl3_accept);
+ assert(s->server);
+ assert(!SSL_IS_DTLS(s));
+
+ ERR_clear_error();
+ ERR_clear_system_error();
+
+ if (s->info_callback != NULL) {
+ cb = s->info_callback;
+ } else if (s->ctx->info_callback != NULL) {
+ cb = s->ctx->info_callback;
+ }
+
+ s->in_handshake++;
+
+ if (s->cert == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_accept, SSL_R_NO_CERTIFICATE_SET);
+ return -1;
+ }
+
+ for (;;) {
+ state = s->state;
+
+ switch (s->state) {
+ case SSL_ST_RENEGOTIATE:
+ /* This state is the renegotiate entry point. It sends a HelloRequest
+ * and nothing else. */
+ s->renegotiate = 1;
+
+ if (cb != NULL) {
+ cb(s, SSL_CB_HANDSHAKE_START, 1);
+ }
+
+ if (s->init_buf == NULL) {
+ buf = BUF_MEM_new();
+ if (!buf || !BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) {
+ ret = -1;
+ goto end;
+ }
+ s->init_buf = buf;
+ buf = NULL;
+ }
+ s->init_num = 0;
+
+ if (!ssl3_setup_buffers(s)) {
+ ret = -1;
+ goto end;
+ }
+
+ if (!s->s3->send_connection_binding &&
+ !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)) {
+ /* Server attempting to renegotiate with client that doesn't support
+ * secure renegotiation. */
+ OPENSSL_PUT_ERROR(SSL, ssl3_accept,
+ SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+ ret = -1;
+ goto end;
+ }
+
+ s->ctx->stats.sess_accept_renegotiate++;
+ s->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;
+ ret = ssl3_send_hello_request(s);
+ if (ret <= 0) {
+ goto end;
+ }
+ s->s3->tmp.next_state = SSL3_ST_SW_HELLO_REQ_C;
+ s->state = SSL3_ST_SW_FLUSH;
+ s->init_num = 0;
+
+ if (!ssl3_init_finished_mac(s)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_accept, ERR_R_INTERNAL_ERROR);
+ ret = -1;
+ goto end;
+ }
+ break;
+
+ case SSL3_ST_SW_HELLO_REQ_C:
+ s->state = SSL_ST_OK;
+ break;
+
+ case SSL_ST_ACCEPT:
+ case SSL_ST_BEFORE | SSL_ST_ACCEPT:
+ /* This state is the entry point for the handshake itself (initial and
+ * renegotiation). */
+ if (cb != NULL) {
+ cb(s, SSL_CB_HANDSHAKE_START, 1);
+ }
+
+ if (s->init_buf == NULL) {
+ buf = BUF_MEM_new();
+ if (!buf || !BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) {
+ ret = -1;
+ goto end;
+ }
+ s->init_buf = buf;
+ buf = NULL;
+ }
+ s->init_num = 0;
+
+ if (!ssl3_init_finished_mac(s)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_accept, ERR_R_INTERNAL_ERROR);
+ ret = -1;
+ goto end;
+ }
+
+ if (!s->s3->have_version) {
+ /* This is the initial handshake. The record layer has not been
+ * initialized yet. Sniff for a V2ClientHello before reading a
+ * ClientHello normally. */
+ assert(s->s3->rbuf.buf == NULL);
+ assert(s->s3->wbuf.buf == NULL);
+ s->state = SSL3_ST_SR_INITIAL_BYTES;
+ } else {
+ /* Enable a write buffer. This groups handshake messages within a
+ * flight into a single write. */
+ if (!ssl3_setup_buffers(s) || !ssl_init_wbio_buffer(s, 1)) {
+ ret = -1;
+ goto end;
+ }
+ s->state = SSL3_ST_SR_CLNT_HELLO_A;
+ }
+ s->ctx->stats.sess_accept++;
+ break;
+
+ case SSL3_ST_SR_INITIAL_BYTES:
+ ret = ssl3_get_initial_bytes(s);
+ if (ret <= 0) {
+ goto end;
+ }
+ /* ssl3_get_initial_bytes sets s->state to one of
+ * SSL3_ST_SR_V2_CLIENT_HELLO or SSL3_ST_SR_CLNT_HELLO_A on success. */
+ break;
+
+ case SSL3_ST_SR_V2_CLIENT_HELLO:
+ ret = ssl3_get_v2_client_hello(s);
+ if (ret <= 0) {
+ goto end;
+ }
+ s->state = SSL3_ST_SR_CLNT_HELLO_A;
+ break;
+
+ case SSL3_ST_SR_CLNT_HELLO_A:
+ case SSL3_ST_SR_CLNT_HELLO_B:
+ case SSL3_ST_SR_CLNT_HELLO_C:
+ case SSL3_ST_SR_CLNT_HELLO_D:
+ s->shutdown = 0;
+ ret = ssl3_get_client_hello(s);
+ if (ret == PENDING_SESSION) {
+ s->rwstate = SSL_PENDING_SESSION;
+ goto end;
+ }
+ if (ret == CERTIFICATE_SELECTION_PENDING) {
+ s->rwstate = SSL_CERTIFICATE_SELECTION_PENDING;
+ goto end;
+ }
+ if (ret <= 0) {
+ goto end;
+ }
+ s->renegotiate = 2;
+ s->state = SSL3_ST_SW_SRVR_HELLO_A;
+ s->init_num = 0;
+ break;
+
+ case SSL3_ST_SW_SRVR_HELLO_A:
+ case SSL3_ST_SW_SRVR_HELLO_B:
+ ret = ssl3_send_server_hello(s);
+ if (ret <= 0) {
+ goto end;
+ }
+ if (s->hit) {
+ if (s->tlsext_ticket_expected) {
+ s->state = SSL3_ST_SW_SESSION_TICKET_A;
+ } else {
+ s->state = SSL3_ST_SW_CHANGE_A;
+ }
+ } else {
+ s->state = SSL3_ST_SW_CERT_A;
+ }
+ s->init_num = 0;
+ break;
+
+ case SSL3_ST_SW_CERT_A:
+ case SSL3_ST_SW_CERT_B:
+ if (ssl_cipher_has_server_public_key(s->s3->tmp.new_cipher)) {
+ ret = ssl3_send_server_certificate(s);
+ if (ret <= 0) {
+ goto end;
+ }
+ if (s->s3->tmp.certificate_status_expected) {
+ s->state = SSL3_ST_SW_CERT_STATUS_A;
+ } else {
+ s->state = SSL3_ST_SW_KEY_EXCH_A;
+ }
+ } else {
+ skip = 1;
+ s->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_a = s->s3->tmp.new_cipher->algorithm_auth;
+
+ /* Send a ServerKeyExchange message if:
+ * - The key exchange is ephemeral or anonymous
+ * Diffie-Hellman.
+ * - There is a PSK identity hint.
+ *
+ * TODO(davidben): This logic is currently duplicated in d1_srvr.c. Fix
+ * this. In the meantime, keep them in sync. */
+ if (ssl_cipher_requires_server_key_exchange(s->s3->tmp.new_cipher) ||
+ ((alg_a & SSL_aPSK) && s->psk_identity_hint)) {
+ ret = ssl3_send_server_key_exchange(s);
+ if (ret <= 0)
+ goto end;
+ } else {
+ skip = 1;
+ }
+
+ s->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:
+ if (/* don't request cert unless asked for it: */
+ !(s->verify_mode & SSL_VERIFY_PEER) ||
+ /* Don't request a certificate if an obc was presented */
+ ((s->verify_mode & SSL_VERIFY_PEER_IF_NO_OBC) &&
+ s->s3->tlsext_channel_id_valid) ||
+ /* if SSL_VERIFY_CLIENT_ONCE is set,
+ * don't request cert during re-negotiation: */
+ ((s->session->peer != NULL) &&
+ (s->verify_mode & SSL_VERIFY_CLIENT_ONCE)) ||
+ /* never request cert in anonymous ciphersuites
+ * (see section "Certificate request" in SSL 3 drafts
+ * and in RFC 2246): */
+ ((s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) &&
+ /* ... except when the application insists on verification
+ * (against the specs, but s3_clnt.c accepts this for SSL 3) */
+ !(s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) ||
+ /* With normal PSK Certificates and
+ * Certificate Requests are omitted */
+ (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) {
+ /* no cert request */
+ skip = 1;
+ s->s3->tmp.cert_request = 0;
+ s->state = SSL3_ST_SW_SRVR_DONE_A;
+ if (s->s3->handshake_buffer &&
+ !ssl3_digest_cached_records(s, free_handshake_buffer)) {
+ return -1;
+ }
+ } else {
+ s->s3->tmp.cert_request = 1;
+ ret = ssl3_send_certificate_request(s);
+ if (ret <= 0) {
+ goto end;
+ }
+#ifndef NETSCAPE_HANG_BUG
+ s->state = SSL3_ST_SW_SRVR_DONE_A;
+#else
+ /* ServerHelloDone was already sent in the
+ * previous record. */
+ s->state = SSL3_ST_SW_FLUSH;
+ s->s3->tmp.next_state = SSL3_ST_SR_CERT_A;
+#endif
+ s->init_num = 0;
+ }
+ break;
+
+ case SSL3_ST_SW_SRVR_DONE_A:
+ case SSL3_ST_SW_SRVR_DONE_B:
+ ret = ssl3_send_server_done(s);
+ if (ret <= 0) {
+ goto end;
+ }
+ s->s3->tmp.next_state = SSL3_ST_SR_CERT_A;
+ s->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) {
+ ret = -1;
+ goto end;
+ }
+ s->rwstate = SSL_NOTHING;
+
+ s->state = s->s3->tmp.next_state;
+ break;
+
+ case SSL3_ST_SR_CERT_A:
+ case SSL3_ST_SR_CERT_B:
+ if (s->s3->tmp.cert_request) {
+ ret = ssl3_get_client_certificate(s);
+ if (ret <= 0) {
+ goto end;
+ }
+ }
+ s->init_num = 0;
+ s->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;
+ }
+ s->state = SSL3_ST_SR_CERT_VRFY_A;
+ s->init_num = 0;
+ break;
+
+ case SSL3_ST_SR_CERT_VRFY_A:
+ case SSL3_ST_SR_CERT_VRFY_B:
+ ret = ssl3_get_cert_verify(s);
+ if (ret <= 0) {
+ goto end;
+ }
+
+ s->state = SSL3_ST_SR_CHANGE;
+ s->init_num = 0;
+ break;
+
+ case SSL3_ST_SR_CHANGE: {
+ char next_proto_neg = 0;
+ char channel_id = 0;
+ next_proto_neg = s->s3->next_proto_neg_seen;
+ channel_id = s->s3->tlsext_channel_id_valid;
+
+ /* At this point, the next message must be entirely behind a
+ * ChangeCipherSpec. */
+ if (!ssl3_expect_change_cipher_spec(s)) {
+ ret = -1;
+ goto end;
+ }
+ if (next_proto_neg) {
+ s->state = SSL3_ST_SR_NEXT_PROTO_A;
+ } else if (channel_id) {
+ s->state = SSL3_ST_SR_CHANNEL_ID_A;
+ } else {
+ s->state = SSL3_ST_SR_FINISHED_A;
+ }
+ break;
+ }
+
+ case SSL3_ST_SR_NEXT_PROTO_A:
+ case SSL3_ST_SR_NEXT_PROTO_B:
+ ret = ssl3_get_next_proto(s);
+ if (ret <= 0) {
+ goto end;
+ }
+ s->init_num = 0;
+ if (s->s3->tlsext_channel_id_valid) {
+ s->state = SSL3_ST_SR_CHANNEL_ID_A;
+ } else {
+ s->state = SSL3_ST_SR_FINISHED_A;
+ }
+ break;
+
+ case SSL3_ST_SR_CHANNEL_ID_A:
+ case SSL3_ST_SR_CHANNEL_ID_B:
+ ret = ssl3_get_channel_id(s);
+ if (ret <= 0) {
+ goto end;
+ }
+ s->init_num = 0;
+ s->state = SSL3_ST_SR_FINISHED_A;
+ break;
+
+ case SSL3_ST_SR_FINISHED_A:
+ case SSL3_ST_SR_FINISHED_B:
+ ret =
+ ssl3_get_finished(s, SSL3_ST_SR_FINISHED_A, SSL3_ST_SR_FINISHED_B);
+ if (ret <= 0) {
+ goto end;
+ }
+
+ if (s->hit) {
+ s->state = SSL_ST_OK;
+ } else if (s->tlsext_ticket_expected) {
+ s->state = SSL3_ST_SW_SESSION_TICKET_A;
+ } else {
+ s->state = SSL3_ST_SW_CHANGE_A;
+ }
+ /* If this is a full handshake with ChannelID then record the hashshake
+ * hashes in |s->session| in case we need them to verify a ChannelID
+ * signature on a resumption of this session in the future. */
+ if (!s->hit && s->s3->tlsext_channel_id_new) {
+ ret = tls1_record_handshake_hashes_for_channel_id(s);
+ if (ret <= 0) {
+ goto end;
+ }
+ }
+ s->init_num = 0;
+ break;
+
+ case SSL3_ST_SW_SESSION_TICKET_A:
+ case SSL3_ST_SW_SESSION_TICKET_B:
+ ret = ssl3_send_new_session_ticket(s);
+ if (ret <= 0) {
+ goto end;
+ }
+ s->state = SSL3_ST_SW_CHANGE_A;
+ s->init_num = 0;
+ break;
+
+ case SSL3_ST_SW_CHANGE_A:
+ case SSL3_ST_SW_CHANGE_B:
+ s->session->cipher = s->s3->tmp.new_cipher;
+ if (!s->enc_method->setup_key_block(s)) {
+ ret = -1;
+ goto end;
+ }
+
+ ret = ssl3_send_change_cipher_spec(s, SSL3_ST_SW_CHANGE_A,
+ SSL3_ST_SW_CHANGE_B);
+ if (ret <= 0) {
+ goto end;
+ }
+ s->state = SSL3_ST_SW_FINISHED_A;
+ s->init_num = 0;
+
+ if (!s->enc_method->change_cipher_state(
+ s, SSL3_CHANGE_CIPHER_SERVER_WRITE)) {
+ ret = -1;
+ goto end;
+ }
+ break;
+
+ case SSL3_ST_SW_FINISHED_A:
+ case SSL3_ST_SW_FINISHED_B:
+ ret =
+ ssl3_send_finished(s, SSL3_ST_SW_FINISHED_A, SSL3_ST_SW_FINISHED_B,
+ s->enc_method->server_finished_label,
+ s->enc_method->server_finished_label_len);
+ if (ret <= 0) {
+ goto end;
+ }
+ s->state = SSL3_ST_SW_FLUSH;
+ if (s->hit) {
+ s->s3->tmp.next_state = SSL3_ST_SR_CHANGE;
+ } else {
+ s->s3->tmp.next_state = SSL_ST_OK;
+ }
+ s->init_num = 0;
+ break;
+
+ case SSL_ST_OK:
+ /* clean a few things up */
+ ssl3_cleanup_key_block(s);
+
+ BUF_MEM_free(s->init_buf);
+ s->init_buf = NULL;
+
+ /* remove buffering on output */
+ ssl_free_wbio_buffer(s);
+
+ s->init_num = 0;
+
+ /* If we aren't retaining peer certificates then we can discard it
+ * now. */
+ if (s->session->peer && s->ctx->retain_only_sha256_of_client_certs) {
+ X509_free(s->session->peer);
+ s->session->peer = NULL;
+ }
+
+ if (s->renegotiate == 2) {
+ /* skipped if we just sent a HelloRequest */
+ s->renegotiate = 0;
+ s->new_session = 0;
+
+ ssl_update_cache(s, SSL_SESS_CACHE_SERVER);
+
+ s->ctx->stats.sess_accept_good++;
+
+ if (cb != NULL) {
+ cb(s, SSL_CB_HANDSHAKE_DONE, 1);
+ }
+ }
+
+ ret = 1;
+ goto end;
+
+ default:
+ OPENSSL_PUT_ERROR(SSL, ssl3_accept, SSL_R_UNKNOWN_STATE);
+ ret = -1;
+ goto end;
+ }
+
+ if (!s->s3->tmp.reuse_message && !skip && cb != NULL && s->state != state) {
+ new_state = s->state;
+ s->state = state;
+ cb(s, SSL_CB_ACCEPT_LOOP, 1);
+ s->state = new_state;
+ }
+ skip = 0;
+ }
+
+end:
+ s->in_handshake--;
+ if (buf != NULL) {
+ BUF_MEM_free(buf);
+ }
+ if (cb != NULL) {
+ cb(s, SSL_CB_ACCEPT_EXIT, ret);
+ }
+ return ret;
+}
+
+static int ssl3_read_sniff_buffer(SSL *s, size_t n) {
+ if (s->s3->sniff_buffer == NULL) {
+ s->s3->sniff_buffer = BUF_MEM_new();
+ }
+ if (s->s3->sniff_buffer == NULL || !BUF_MEM_grow(s->s3->sniff_buffer, n)) {
+ return -1;
+ }
+
+ while (s->s3->sniff_buffer_len < n) {
+ int ret;
+
+ s->rwstate = SSL_READING;
+ ret = BIO_read(s->rbio, s->s3->sniff_buffer->data + s->s3->sniff_buffer_len,
+ n - s->s3->sniff_buffer_len);
+ if (ret <= 0) {
+ return ret;
+ }
+ s->rwstate = SSL_NOTHING;
+ s->s3->sniff_buffer_len += ret;
+ }
+
+ return 1;
+}
+
+int ssl3_get_initial_bytes(SSL *s) {
+ int ret;
+ const uint8_t *p;
+
+ /* Read the first 8 bytes. To recognize a ClientHello or V2ClientHello only
+ * needs the first 6 bytes, but 8 is needed to recognize CONNECT below. */
+ ret = ssl3_read_sniff_buffer(s, INITIAL_SNIFF_BUFFER_SIZE);
+ if (ret <= 0) {
+ return ret;
+ }
+ assert(s->s3->sniff_buffer_len >= INITIAL_SNIFF_BUFFER_SIZE);
+ p = (const uint8_t *)s->s3->sniff_buffer->data;
+
+ /* Some dedicated error codes for protocol mixups should the application wish
+ * to interpret them differently. (These do not overlap with ClientHello or
+ * V2ClientHello.) */
+ if (strncmp("GET ", (const char *)p, 4) == 0 ||
+ strncmp("POST ", (const char *)p, 5) == 0 ||
+ strncmp("HEAD ", (const char *)p, 5) == 0 ||
+ strncmp("PUT ", (const char *)p, 4) == 0) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_initial_bytes, SSL_R_HTTP_REQUEST);
+ return -1;
+ }
+ if (strncmp("CONNECT ", (const char *)p, 8) == 0) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_initial_bytes, SSL_R_HTTPS_PROXY_REQUEST);
+ return -1;
+ }
+
+ /* Determine if this is a ClientHello or V2ClientHello. */
+ if ((p[0] & 0x80) && p[2] == SSL2_MT_CLIENT_HELLO &&
+ p[3] >= SSL3_VERSION_MAJOR) {
+ /* This is a V2ClientHello. */
+ s->state = SSL3_ST_SR_V2_CLIENT_HELLO;
+ return 1;
+ }
+ if (p[0] == SSL3_RT_HANDSHAKE && p[1] >= SSL3_VERSION_MAJOR &&
+ p[5] == SSL3_MT_CLIENT_HELLO) {
+ /* This is a ClientHello. Initialize the record layer with the already
+ * consumed data and continue the handshake. */
+ if (!ssl3_setup_buffers(s) || !ssl_init_wbio_buffer(s, 1)) {
+ return -1;
+ }
+ assert(s->rstate == SSL_ST_READ_HEADER);
+ memcpy(s->s3->rbuf.buf, p, s->s3->sniff_buffer_len);
+ s->s3->rbuf.offset = 0;
+ s->s3->rbuf.left = s->s3->sniff_buffer_len;
+ s->packet_length = 0;
+
+ BUF_MEM_free(s->s3->sniff_buffer);
+ s->s3->sniff_buffer = NULL;
+ s->s3->sniff_buffer_len = 0;
+
+ s->state = SSL3_ST_SR_CLNT_HELLO_A;
+ return 1;
+ }
+
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_initial_bytes, SSL_R_UNKNOWN_PROTOCOL);
+ return -1;
+}
+
+int ssl3_get_v2_client_hello(SSL *s) {
+ const uint8_t *p;
+ int ret;
+ CBS v2_client_hello, cipher_specs, session_id, challenge;
+ size_t msg_length, rand_len, len;
+ uint8_t msg_type;
+ uint16_t version, cipher_spec_length, session_id_length, challenge_length;
+ CBB client_hello, hello_body, cipher_suites;
+ uint8_t random[SSL3_RANDOM_SIZE];
+
+ /* Read the remainder of the V2ClientHello. We have previously read 8 bytes
+ * in ssl3_get_initial_bytes. */
+ assert(s->s3->sniff_buffer_len >= INITIAL_SNIFF_BUFFER_SIZE);
+ p = (const uint8_t *)s->s3->sniff_buffer->data;
+ msg_length = ((p[0] & 0x7f) << 8) | p[1];
+ if (msg_length > (1024 * 4)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_v2_client_hello, SSL_R_RECORD_TOO_LARGE);
+ return -1;
+ }
+ if (msg_length < INITIAL_SNIFF_BUFFER_SIZE - 2) {
+ /* Reject lengths that are too short early. We have already read 8 bytes,
+ * so we should not attempt to process an (invalid) V2ClientHello which
+ * would be shorter than that. */
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_v2_client_hello,
+ SSL_R_RECORD_LENGTH_MISMATCH);
+ return -1;
+ }
+
+ ret = ssl3_read_sniff_buffer(s, msg_length + 2);
+ if (ret <= 0) {
+ return ret;
+ }
+ assert(s->s3->sniff_buffer_len == msg_length + 2);
+ CBS_init(&v2_client_hello, (const uint8_t *)s->s3->sniff_buffer->data + 2,
+ msg_length);
+
+ /* The V2ClientHello without the length is incorporated into the Finished
+ * hash. */
+ ssl3_finish_mac(s, CBS_data(&v2_client_hello), CBS_len(&v2_client_hello));
+ if (s->msg_callback) {
+ s->msg_callback(0, SSL2_VERSION, 0, CBS_data(&v2_client_hello),
+ CBS_len(&v2_client_hello), s, s->msg_callback_arg);
+ }
+
+ if (!CBS_get_u8(&v2_client_hello, &msg_type) ||
+ !CBS_get_u16(&v2_client_hello, &version) ||
+ !CBS_get_u16(&v2_client_hello, &cipher_spec_length) ||
+ !CBS_get_u16(&v2_client_hello, &session_id_length) ||
+ !CBS_get_u16(&v2_client_hello, &challenge_length) ||
+ !CBS_get_bytes(&v2_client_hello, &cipher_specs, cipher_spec_length) ||
+ !CBS_get_bytes(&v2_client_hello, &session_id, session_id_length) ||
+ !CBS_get_bytes(&v2_client_hello, &challenge, challenge_length) ||
+ CBS_len(&v2_client_hello) != 0) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_v2_client_hello, SSL_R_DECODE_ERROR);
+ return -1;
+ }
+
+ /* msg_type has already been checked. */
+ assert(msg_type == SSL2_MT_CLIENT_HELLO);
+
+ /* The client_random is the V2ClientHello challenge. Truncate or
+ * left-pad with zeros as needed. */
+ memset(random, 0, SSL3_RANDOM_SIZE);
+ rand_len = CBS_len(&challenge);
+ if (rand_len > SSL3_RANDOM_SIZE) {
+ rand_len = SSL3_RANDOM_SIZE;
+ }
+ memcpy(random + (SSL3_RANDOM_SIZE - rand_len), CBS_data(&challenge),
+ rand_len);
+
+ /* Write out an equivalent SSLv3 ClientHello. */
+ if (!CBB_init_fixed(&client_hello, (uint8_t *)s->init_buf->data,
+ s->init_buf->max)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_v2_client_hello, ERR_R_MALLOC_FAILURE);
+ return -1;
+ }
+ if (!CBB_add_u8(&client_hello, SSL3_MT_CLIENT_HELLO) ||
+ !CBB_add_u24_length_prefixed(&client_hello, &hello_body) ||
+ !CBB_add_u16(&hello_body, version) ||
+ !CBB_add_bytes(&hello_body, random, SSL3_RANDOM_SIZE) ||
+ /* No session id. */
+ !CBB_add_u8(&hello_body, 0) ||
+ !CBB_add_u16_length_prefixed(&hello_body, &cipher_suites)) {
+ CBB_cleanup(&client_hello);
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_v2_client_hello, ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
+
+ /* Copy the cipher suites. */
+ while (CBS_len(&cipher_specs) > 0) {
+ uint32_t cipher_spec;
+ if (!CBS_get_u24(&cipher_specs, &cipher_spec)) {
+ CBB_cleanup(&client_hello);
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_v2_client_hello, SSL_R_DECODE_ERROR);
+ return -1;
+ }
+
+ /* Skip SSLv2 ciphers. */
+ if ((cipher_spec & 0xff0000) != 0) {
+ continue;
+ }
+ if (!CBB_add_u16(&cipher_suites, cipher_spec)) {
+ CBB_cleanup(&client_hello);
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_v2_client_hello, ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
+ }
+
+ /* Add the null compression scheme and finish. */
+ if (!CBB_add_u8(&hello_body, 1) || !CBB_add_u8(&hello_body, 0) ||
+ !CBB_finish(&client_hello, NULL, &len)) {
+ CBB_cleanup(&client_hello);
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_v2_client_hello, ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
+
+ /* Mark the message for "re"-use by the version-specific method. */
+ s->s3->tmp.reuse_message = 1;
+ s->s3->tmp.message_type = SSL3_MT_CLIENT_HELLO;
+ /* The handshake message header is 4 bytes. */
+ s->s3->tmp.message_size = len - 4;
+
+ /* Initialize the record layer. */
+ if (!ssl3_setup_buffers(s) || !ssl_init_wbio_buffer(s, 1)) {
+ return -1;
+ }
+
+ /* Drop the sniff buffer. */
+ BUF_MEM_free(s->s3->sniff_buffer);
+ s->s3->sniff_buffer = NULL;
+ s->s3->sniff_buffer_len = 0;
+
+ return 1;
+}
+
+int ssl3_send_hello_request(SSL *s) {
+ if (s->state == SSL3_ST_SW_HELLO_REQ_A) {
+ ssl_set_handshake_header(s, SSL3_MT_HELLO_REQUEST, 0);
+ s->state = SSL3_ST_SW_HELLO_REQ_B;
+ }
+
+ /* SSL3_ST_SW_HELLO_REQ_B */
+ return ssl_do_write(s);
+}
+
+int ssl3_get_client_hello(SSL *s) {
+ int i, ok, al = SSL_AD_INTERNAL_ERROR, ret = -1;
+ long n;
+ const SSL_CIPHER *c;
+ STACK_OF(SSL_CIPHER) *ciphers = NULL;
+ struct ssl_early_callback_ctx early_ctx;
+ CBS client_hello;
+ uint16_t client_version;
+ CBS client_random, session_id, cipher_suites, compression_methods;
+
+ /* 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. */
+ switch (s->state) {
+ case SSL3_ST_SR_CLNT_HELLO_A:
+ case SSL3_ST_SR_CLNT_HELLO_B:
+ n = s->method->ssl_get_message(
+ s, SSL3_ST_SR_CLNT_HELLO_A, SSL3_ST_SR_CLNT_HELLO_B,
+ SSL3_MT_CLIENT_HELLO, SSL3_RT_MAX_PLAIN_LENGTH,
+ SSL_GET_MESSAGE_HASH_MESSAGE, &ok);
+
+ if (!ok) {
+ return n;
+ }
+
+ /* If we require cookies and this ClientHello doesn't contain one, just
+ * return since we do not want to allocate any memory yet. So check
+ * cookie length... */
+ if (SSL_IS_DTLS(s) && (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE)) {
+ uint8_t cookie_length;
+
+ CBS_init(&client_hello, s->init_msg, n);
+ if (!CBS_skip(&client_hello, 2 + SSL3_RANDOM_SIZE) ||
+ !CBS_get_u8_length_prefixed(&client_hello, &session_id) ||
+ !CBS_get_u8(&client_hello, &cookie_length)) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_DECODE_ERROR);
+ goto f_err;
+ }
+
+ if (cookie_length == 0) {
+ return 1;
+ }
+ }
+ s->state = SSL3_ST_SR_CLNT_HELLO_C;
+ /* fallthrough */
+ case SSL3_ST_SR_CLNT_HELLO_C:
+ case SSL3_ST_SR_CLNT_HELLO_D:
+ /* We have previously parsed the ClientHello message, and can't call
+ * ssl_get_message again without hashing the message into the Finished
+ * digest again. */
+ n = s->init_num;
+
+ memset(&early_ctx, 0, sizeof(early_ctx));
+ early_ctx.ssl = s;
+ early_ctx.client_hello = s->init_msg;
+ early_ctx.client_hello_len = n;
+ if (!ssl_early_callback_init(&early_ctx)) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello,
+ SSL_R_CLIENTHELLO_PARSE_FAILED);
+ goto f_err;
+ }
+
+ if (s->state == SSL3_ST_SR_CLNT_HELLO_C &&
+ s->ctx->select_certificate_cb != NULL) {
+ s->state = SSL3_ST_SR_CLNT_HELLO_D;
+ switch (s->ctx->select_certificate_cb(&early_ctx)) {
+ case 0:
+ return CERTIFICATE_SELECTION_PENDING;
+
+ case -1:
+ /* Connection rejected. */
+ al = SSL_AD_ACCESS_DENIED;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello,
+ SSL_R_CONNECTION_REJECTED);
+ goto f_err;
+
+ default:
+ /* fallthrough */;
+ }
+ }
+ s->state = SSL3_ST_SR_CLNT_HELLO_D;
+ break;
+
+ default:
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_UNKNOWN_STATE);
+ return -1;
+ }
+
+ CBS_init(&client_hello, s->init_msg, n);
+ if (!CBS_get_u16(&client_hello, &client_version) ||
+ !CBS_get_bytes(&client_hello, &client_random, SSL3_RANDOM_SIZE) ||
+ !CBS_get_u8_length_prefixed(&client_hello, &session_id) ||
+ CBS_len(&session_id) > SSL_MAX_SSL_SESSION_ID_LENGTH) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_DECODE_ERROR);
+ goto f_err;
+ }
+
+ /* use version from inside client hello, not from record header (may differ:
+ * see RFC 2246, Appendix E, second paragraph) */
+ s->client_version = client_version;
+
+ /* Load the client random. */
+ memcpy(s->s3->client_random, CBS_data(&client_random), SSL3_RANDOM_SIZE);
+
+ if (SSL_IS_DTLS(s)) {
+ CBS cookie;
+
+ if (!CBS_get_u8_length_prefixed(&client_hello, &cookie) ||
+ CBS_len(&cookie) > DTLS1_COOKIE_LENGTH) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_DECODE_ERROR);
+ goto f_err;
+ }
+
+ /* Verify the cookie if appropriate option is set. */
+ if ((SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) && CBS_len(&cookie) > 0) {
+ if (s->ctx->app_verify_cookie_cb != NULL) {
+ if (s->ctx->app_verify_cookie_cb(s, CBS_data(&cookie),
+ CBS_len(&cookie)) == 0) {
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_COOKIE_MISMATCH);
+ goto f_err;
+ }
+ /* else cookie verification succeeded */
+ } else if (!CBS_mem_equal(&cookie, s->d1->cookie, s->d1->cookie_len)) {
+ /* default verification */
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_COOKIE_MISMATCH);
+ goto f_err;
+ }
+ /* Set to -2 so if successful we return 2 and don't send
+ * HelloVerifyRequest. */
+ ret = -2;
+ }
+ }
+
+ if (!s->s3->have_version) {
+ /* Select version to use */
+ uint16_t version = ssl3_get_mutual_version(s, client_version);
+ if (version == 0) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_UNSUPPORTED_PROTOCOL);
+ s->version = s->client_version;
+ al = SSL_AD_PROTOCOL_VERSION;
+ goto f_err;
+ }
+ s->version = version;
+ s->enc_method = ssl3_get_enc_method(version);
+ assert(s->enc_method != NULL);
+ /* At this point, the connection's version is known and |s->version| is
+ * fixed. Begin enforcing the record-layer version. */
+ s->s3->have_version = 1;
+ } else if (SSL_IS_DTLS(s) ? (s->client_version > s->version)
+ : (s->client_version < s->version)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_WRONG_VERSION_NUMBER);
+ al = SSL_AD_PROTOCOL_VERSION;
+ goto f_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 {
+ i = ssl_get_prev_session(s, &early_ctx);
+ if (i == PENDING_SESSION) {
+ ret = PENDING_SESSION;
+ goto err;
+ } else if (i == -1) {
+ goto err;
+ }
+
+ /* Only resume if the session's version matches the negotiated version:
+ * most clients do not accept a mismatch. */
+ if (i == 1 && s->version == s->session->ssl_version) {
+ s->hit = 1;
+ } else {
+ /* No session was found or it was unacceptable. */
+ if (!ssl_get_new_session(s, 1)) {
+ goto err;
+ }
+ }
+ }
+
+ if (!CBS_get_u16_length_prefixed(&client_hello, &cipher_suites) ||
+ !CBS_get_u8_length_prefixed(&client_hello, &compression_methods) ||
+ CBS_len(&compression_methods) == 0) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_DECODE_ERROR);
+ goto f_err;
+ }
+
+ /* TODO(davidben): Per spec, cipher_suites can never be empty (specified at
+ * the ClientHello structure level). This logic allows it to be empty if
+ * resuming a session. Can we always require non-empty? If a client sends
+ * empty cipher_suites because it's resuming a session, it could always fail
+ * to resume a session, so it's unlikely to actually work. */
+ 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;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_NO_CIPHERS_SPECIFIED);
+ goto f_err;
+ }
+
+ ciphers = ssl_bytes_to_cipher_list(s, &cipher_suites);
+ if (ciphers == NULL) {
+ goto err;
+ }
+
+ /* If it is a hit, check that the cipher is in the list. */
+ if (s->hit && CBS_len(&cipher_suites) > 0) {
+ size_t j;
+ int found_cipher = 0;
+ unsigned long id = s->session->cipher->id;
+
+ for (j = 0; j < sk_SSL_CIPHER_num(ciphers); j++) {
+ c = sk_SSL_CIPHER_value(ciphers, j);
+ if (c->id == id) {
+ found_cipher = 1;
+ break;
+ }
+ }
+
+ if (!found_cipher) {
+ /* we need to have the cipher in the cipher list if we are asked to reuse
+ * it */
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello,
+ SSL_R_REQUIRED_CIPHER_MISSING);
+ goto f_err;
+ }
+ }
+
+ /* Only null compression is supported. */
+ if (memchr(CBS_data(&compression_methods), 0,
+ CBS_len(&compression_methods)) == NULL) {
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello,
+ SSL_R_NO_COMPRESSION_SPECIFIED);
+ goto f_err;
+ }
+
+ /* TLS extensions. */
+ if (s->version >= SSL3_VERSION &&
+ !ssl_parse_clienthello_tlsext(s, &client_hello)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_PARSE_TLSEXT);
+ goto err;
+ }
+
+ /* There should be nothing left over in the record. */
+ if (CBS_len(&client_hello) != 0) {
+ /* wrong packet length */
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_BAD_PACKET_LENGTH);
+ goto f_err;
+ }
+
+ /* Given ciphers and SSL_get_ciphers, we must pick a cipher */
+ if (!s->hit) {
+ if (ciphers == NULL) {
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_NO_CIPHERS_PASSED);
+ goto f_err;
+ }
+
+ /* Let cert callback update server certificates if required */
+ if (s->cert->cert_cb) {
+ int rv = s->cert->cert_cb(s, s->cert->cert_cb_arg);
+ if (rv == 0) {
+ al = SSL_AD_INTERNAL_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_CERT_CB_ERROR);
+ goto f_err;
+ }
+ if (rv < 0) {
+ s->rwstate = SSL_X509_LOOKUP;
+ goto err;
+ }
+ s->rwstate = SSL_NOTHING;
+ }
+ c = ssl3_choose_cipher(s, ciphers, ssl_get_cipher_preferences(s));
+
+ if (c == NULL) {
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_NO_SHARED_CIPHER);
+ goto f_err;
+ }
+ s->s3->tmp.new_cipher = c;
+ } else {
+ /* Session-id reuse */
+ s->s3->tmp.new_cipher = s->session->cipher;
+ }
+
+ if ((!SSL_USE_SIGALGS(s) || !(s->verify_mode & SSL_VERIFY_PEER)) &&
+ !ssl3_digest_cached_records(s, free_handshake_buffer)) {
+ goto f_err;
+ }
+
+ /* we now have the following setup;
+ * client_random
+ * cipher_list - our prefered list of ciphers
+ * ciphers - the clients prefered 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->tmp.new_cipher - the new cipher to use. */
+
+ if (ret < 0) {
+ ret = -ret;
+ }
+
+ if (0) {
+ f_err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ }
+
+err:
+ if (ciphers != NULL) {
+ sk_SSL_CIPHER_free(ciphers);
+ }
+ return ret;
+}
+
+int ssl3_send_server_hello(SSL *s) {
+ uint8_t *buf;
+ uint8_t *p, *d;
+ int sl;
+ unsigned long l;
+
+ if (s->state == SSL3_ST_SW_SRVR_HELLO_A) {
+ /* We only accept ChannelIDs on connections with ECDHE in order to avoid a
+ * known attack while we fix ChannelID itself. */
+ if (s->s3->tlsext_channel_id_valid &&
+ (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kEECDH) == 0) {
+ s->s3->tlsext_channel_id_valid = 0;
+ }
+
+ /* If this is a resumption and the original handshake didn't support
+ * ChannelID then we didn't record the original handshake hashes in the
+ * session and so cannot resume with ChannelIDs. */
+ if (s->hit && s->s3->tlsext_channel_id_new &&
+ s->session->original_handshake_hash_len == 0) {
+ s->s3->tlsext_channel_id_valid = 0;
+ }
+
+ buf = (uint8_t *)s->init_buf->data;
+ /* Do the message type and length last */
+ d = p = ssl_handshake_start(s);
+
+ *(p++) = s->version >> 8;
+ *(p++) = s->version & 0xff;
+
+ /* Random stuff */
+ if (!ssl_fill_hello_random(s, 1, s->s3->server_random, SSL3_RANDOM_SIZE)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_server_hello, ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
+ memcpy(p, s->s3->server_random, SSL3_RANDOM_SIZE);
+ p += SSL3_RANDOM_SIZE;
+
+ /* 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 > (int)sizeof(s->session->session_id)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_server_hello, ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
+ *(p++) = sl;
+ memcpy(p, s->session->session_id, sl);
+ p += sl;
+
+ /* put the cipher */
+ s2n(ssl3_get_cipher_value(s->s3->tmp.new_cipher), p);
+
+ /* put the compression method */
+ *(p++) = 0;
+ if (ssl_prepare_serverhello_tlsext(s) <= 0) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_server_hello, SSL_R_SERVERHELLO_TLSEXT);
+ return -1;
+ }
+ p = ssl_add_serverhello_tlsext(s, p, buf + SSL3_RT_MAX_PLAIN_LENGTH);
+ if (p == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_server_hello, ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
+
+ /* do the header */
+ l = (p - d);
+ ssl_set_handshake_header(s, SSL3_MT_SERVER_HELLO, l);
+ s->state = SSL3_ST_SW_SRVR_HELLO_B;
+ }
+
+ /* SSL3_ST_SW_SRVR_HELLO_B */
+ return ssl_do_write(s);
+}
+
+int ssl3_send_server_done(SSL *s) {
+ if (s->state == SSL3_ST_SW_SRVR_DONE_A) {
+ ssl_set_handshake_header(s, SSL3_MT_SERVER_DONE, 0);
+ s->state = SSL3_ST_SW_SRVR_DONE_B;
+ }
+
+ /* SSL3_ST_SW_SRVR_DONE_B */
+ return ssl_do_write(s);
+}
+
+int ssl3_send_server_key_exchange(SSL *s) {
+ DH *dh = NULL, *dhp;
+ EC_KEY *ecdh = NULL, *ecdhp;
+ uint8_t *encodedPoint = NULL;
+ int encodedlen = 0;
+ uint16_t curve_id = 0;
+ BN_CTX *bn_ctx = NULL;
+ const char *psk_identity_hint = NULL;
+ size_t psk_identity_hint_len = 0;
+ EVP_PKEY *pkey;
+ uint8_t *p, *d;
+ int al, i;
+ unsigned long alg_k;
+ unsigned long alg_a;
+ int n;
+ CERT *cert;
+ BIGNUM *r[4];
+ int nr[4], kn;
+ BUF_MEM *buf;
+ EVP_MD_CTX md_ctx;
+
+ EVP_MD_CTX_init(&md_ctx);
+ if (s->state == SSL3_ST_SW_KEY_EXCH_A) {
+ alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
+ alg_a = s->s3->tmp.new_cipher->algorithm_auth;
+ cert = s->cert;
+
+ buf = s->init_buf;
+
+ r[0] = r[1] = r[2] = r[3] = NULL;
+ n = 0;
+ if (alg_a & SSL_aPSK) {
+ /* size for PSK identity hint */
+ psk_identity_hint = s->psk_identity_hint;
+ if (psk_identity_hint) {
+ psk_identity_hint_len = strlen(psk_identity_hint);
+ } else {
+ psk_identity_hint_len = 0;
+ }
+ n += 2 + psk_identity_hint_len;
+ }
+
+ if (alg_k & SSL_kEDH) {
+ dhp = cert->dh_tmp;
+ if (dhp == NULL && s->cert->dh_tmp_cb != NULL) {
+ dhp = s->cert->dh_tmp_cb(s, 0, 1024);
+ }
+ if (dhp == NULL) {
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange,
+ SSL_R_MISSING_TMP_DH_KEY);
+ goto f_err;
+ }
+
+ if (s->s3->tmp.dh != NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ dh = DHparams_dup(dhp);
+ if (dh == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_R_DH_LIB);
+ goto err;
+ }
+
+ s->s3->tmp.dh = dh;
+ if (dhp->pub_key == NULL || dhp->priv_key == NULL ||
+ (s->options & SSL_OP_SINGLE_DH_USE)) {
+ if (!DH_generate_key(dh)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_R_DH_LIB);
+ goto err;
+ }
+ } else {
+ dh->pub_key = BN_dup(dhp->pub_key);
+ dh->priv_key = BN_dup(dhp->priv_key);
+ if (dh->pub_key == NULL || dh->priv_key == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_R_DH_LIB);
+ goto err;
+ }
+ }
+
+ r[0] = dh->p;
+ r[1] = dh->g;
+ r[2] = dh->pub_key;
+ } else if (alg_k & SSL_kEECDH) {
+ const EC_GROUP *group;
+
+ ecdhp = cert->ecdh_tmp;
+ if (s->cert->ecdh_tmp_auto) {
+ /* Get NID of appropriate shared curve */
+ int nid = tls1_get_shared_curve(s);
+ if (nid != NID_undef) {
+ ecdhp = EC_KEY_new_by_curve_name(nid);
+ }
+ } else if (ecdhp == NULL && s->cert->ecdh_tmp_cb) {
+ ecdhp = s->cert->ecdh_tmp_cb(s, 0, 1024);
+ }
+ if (ecdhp == NULL) {
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange,
+ SSL_R_MISSING_TMP_ECDH_KEY);
+ goto f_err;
+ }
+
+ if (s->s3->tmp.ecdh != NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ /* Duplicate the ECDH structure. */
+ if (ecdhp == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_R_ECDH_LIB);
+ goto err;
+ }
+
+ if (s->cert->ecdh_tmp_auto) {
+ ecdh = ecdhp;
+ } else {
+ ecdh = EC_KEY_dup(ecdhp);
+ if (ecdh == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_R_ECDH_LIB);
+ goto err;
+ }
+ }
+
+ s->s3->tmp.ecdh = ecdh;
+ if (EC_KEY_get0_public_key(ecdh) == NULL ||
+ EC_KEY_get0_private_key(ecdh) == NULL ||
+ (s->options & SSL_OP_SINGLE_ECDH_USE)) {
+ if (!EC_KEY_generate_key(ecdh)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_R_ECDH_LIB);
+ goto err;
+ }
+ }
+
+ group = EC_KEY_get0_group(ecdh);
+ if (group == NULL ||
+ EC_KEY_get0_public_key(ecdh) == NULL ||
+ EC_KEY_get0_private_key(ecdh) == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_R_ECDH_LIB);
+ goto err;
+ }
+
+ /* We only support ephemeral ECDH keys over named (not generic) curves. */
+ if (!tls1_ec_nid2curve_id(&curve_id, EC_GROUP_get_curve_name(group))) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange,
+ SSL_R_UNSUPPORTED_ELLIPTIC_CURVE);
+ goto err;
+ }
+
+ /* Encode the public key. First check the size of encoding and allocate
+ * memory accordingly. */
+ encodedlen =
+ EC_POINT_point2oct(group, EC_KEY_get0_public_key(ecdh),
+ POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL);
+
+ encodedPoint = (uint8_t *)OPENSSL_malloc(encodedlen * sizeof(uint8_t));
+ bn_ctx = BN_CTX_new();
+ if (encodedPoint == NULL || bn_ctx == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ encodedlen = EC_POINT_point2oct(group, EC_KEY_get0_public_key(ecdh),
+ POINT_CONVERSION_UNCOMPRESSED,
+ encodedPoint, encodedlen, bn_ctx);
+
+ if (encodedlen == 0) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_R_ECDH_LIB);
+ goto err;
+ }
+
+ BN_CTX_free(bn_ctx);
+ bn_ctx = NULL;
+
+ /* We only support named (not generic) curves in ECDH ephemeral key
+ * exchanges. In this situation, we need four additional bytes to encode
+ * the entire ServerECDHParams structure. */
+ n += 4 + encodedlen;
+
+ /* We'll generate the serverKeyExchange message explicitly so we can set
+ * these to NULLs */
+ r[0] = NULL;
+ r[1] = NULL;
+ r[2] = NULL;
+ r[3] = NULL;
+ } else if (!(alg_k & SSL_kPSK)) {
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange,
+ SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE);
+ goto f_err;
+ }
+
+ for (i = 0; i < 4 && r[i] != NULL; i++) {
+ nr[i] = BN_num_bytes(r[i]);
+ n += 2 + nr[i];
+ }
+
+ if (ssl_cipher_has_server_public_key(s->s3->tmp.new_cipher)) {
+ pkey = ssl_get_sign_pkey(s, s->s3->tmp.new_cipher);
+ if (pkey == NULL) {
+ al = SSL_AD_DECODE_ERROR;
+ goto f_err;
+ }
+ kn = EVP_PKEY_size(pkey);
+ } else {
+ pkey = NULL;
+ kn = 0;
+ }
+
+ if (!BUF_MEM_grow_clean(buf, n + SSL_HM_HEADER_LENGTH(s) + kn)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_LIB_BUF);
+ goto err;
+ }
+ d = p = ssl_handshake_start(s);
+
+ for (i = 0; i < 4 && r[i] != NULL; i++) {
+ s2n(nr[i], p);
+ BN_bn2bin(r[i], p);
+ p += nr[i];
+ }
+
+ /* Note: ECDHE PSK ciphersuites use SSL_kEECDH and SSL_aPSK. When one of
+ * them is used, the server key exchange record needs to have both the
+ * psk_identity_hint and the ServerECDHParams. */
+ if (alg_a & SSL_aPSK) {
+ /* copy PSK identity hint (if provided) */
+ s2n(psk_identity_hint_len, p);
+ if (psk_identity_hint_len > 0) {
+ memcpy(p, psk_identity_hint, psk_identity_hint_len);
+ p += psk_identity_hint_len;
+ }
+ }
+
+ if (alg_k & SSL_kEECDH) {
+ /* We only support named (not generic) curves. In this situation, the
+ * serverKeyExchange message has:
+ * [1 byte CurveType], [2 byte CurveName]
+ * [1 byte length of encoded point], followed by
+ * the actual encoded point itself. */
+ *(p++) = NAMED_CURVE_TYPE;
+ *(p++) = (uint8_t)(curve_id >> 8);
+ *(p++) = (uint8_t)(curve_id & 0xff);
+ *(p++) = encodedlen;
+ memcpy(p, encodedPoint, encodedlen);
+ p += encodedlen;
+ OPENSSL_free(encodedPoint);
+ encodedPoint = NULL;
+ }
+
+ /* not anonymous */
+ if (pkey != NULL) {
+ /* n is the length of the params, they start at &(d[4]) and p points to
+ * the space at the end. */
+ const EVP_MD *md;
+ size_t sig_len = EVP_PKEY_size(pkey);
+
+ /* Determine signature algorithm. */
+ if (SSL_USE_SIGALGS(s)) {
+ md = tls1_choose_signing_digest(s, pkey);
+ if (!tls12_get_sigandhash(p, pkey, md)) {
+ /* Should never happen */
+ al = SSL_AD_INTERNAL_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange,
+ ERR_R_INTERNAL_ERROR);
+ goto f_err;
+ }
+ p += 2;
+ } else if (pkey->type == EVP_PKEY_RSA) {
+ md = EVP_md5_sha1();
+ } else {
+ md = EVP_sha1();
+ }
+
+ if (!EVP_DigestSignInit(&md_ctx, NULL, md, NULL, pkey) ||
+ !EVP_DigestSignUpdate(&md_ctx, s->s3->client_random,
+ SSL3_RANDOM_SIZE) ||
+ !EVP_DigestSignUpdate(&md_ctx, s->s3->server_random,
+ SSL3_RANDOM_SIZE) ||
+ !EVP_DigestSignUpdate(&md_ctx, d, n) ||
+ !EVP_DigestSignFinal(&md_ctx, &p[2], &sig_len)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_LIB_EVP);
+ goto err;
+ }
+
+ s2n(sig_len, p);
+ n += sig_len + 2;
+ if (SSL_USE_SIGALGS(s)) {
+ n += 2;
+ }
+ }
+
+ ssl_set_handshake_header(s, SSL3_MT_SERVER_KEY_EXCHANGE, n);
+ }
+
+ s->state = SSL3_ST_SW_KEY_EXCH_B;
+ EVP_MD_CTX_cleanup(&md_ctx);
+ return ssl_do_write(s);
+
+f_err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+err:
+ if (encodedPoint != NULL) {
+ OPENSSL_free(encodedPoint);
+ }
+ BN_CTX_free(bn_ctx);
+ EVP_MD_CTX_cleanup(&md_ctx);
+ return -1;
+}
+
+int ssl3_send_certificate_request(SSL *s) {
+ uint8_t *p, *d;
+ size_t i;
+ int j, nl, off, n;
+ STACK_OF(X509_NAME) *sk = NULL;
+ X509_NAME *name;
+ BUF_MEM *buf;
+
+ if (s->state == SSL3_ST_SW_CERT_REQ_A) {
+ buf = s->init_buf;
+
+ d = p = ssl_handshake_start(s);
+
+ /* get the list of acceptable cert types */
+ p++;
+ n = ssl3_get_req_cert_type(s, p);
+ d[0] = n;
+ p += n;
+ n++;
+
+ if (SSL_USE_SIGALGS(s)) {
+ const uint8_t *psigs;
+ nl = tls12_get_psigalgs(s, &psigs);
+ s2n(nl, p);
+ memcpy(p, psigs, nl);
+ p += nl;
+ n += nl + 2;
+ }
+
+ off = n;
+ p += 2;
+ n += 2;
+
+ sk = SSL_get_client_CA_list(s);
+ nl = 0;
+ if (sk != NULL) {
+ for (i = 0; i < sk_X509_NAME_num(sk); i++) {
+ name = sk_X509_NAME_value(sk, i);
+ j = i2d_X509_NAME(name, NULL);
+ if (!BUF_MEM_grow_clean(buf, SSL_HM_HEADER_LENGTH(s) + n + j + 2)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_certificate_request, ERR_R_BUF_LIB);
+ goto err;
+ }
+ p = ssl_handshake_start(s) + n;
+ s2n(j, p);
+ i2d_X509_NAME(name, &p);
+ n += 2 + j;
+ nl += 2 + j;
+ }
+ }
+
+ /* else no CA names */
+ p = ssl_handshake_start(s) + off;
+ s2n(nl, p);
+
+ ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE_REQUEST, n);
+
+#ifdef NETSCAPE_HANG_BUG
+ if (!SSL_IS_DTLS(s)) {
+ /* Prepare a ServerHelloDone in the same record. This is to workaround a
+ * hang in Netscape. */
+ if (!BUF_MEM_grow_clean(buf, s->init_num + 4)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_certificate_request, ERR_R_BUF_LIB);
+ goto err;
+ }
+ p = (uint8_t *)s->init_buf->data + s->init_num;
+ /* do the header */
+ *(p++) = SSL3_MT_SERVER_DONE;
+ *(p++) = 0;
+ *(p++) = 0;
+ *(p++) = 0;
+ s->init_num += 4;
+ ssl3_finish_mac(s, p - 4, 4);
+ }
+#endif
+
+ s->state = SSL3_ST_SW_CERT_REQ_B;
+ }
+
+ /* SSL3_ST_SW_CERT_REQ_B */
+ return ssl_do_write(s);
+
+err:
+ return -1;
+}
+
+int ssl3_get_client_key_exchange(SSL *s) {
+ int al, ok;
+ long n;
+ CBS client_key_exchange;
+ unsigned long alg_k;
+ unsigned long alg_a;
+ uint8_t *premaster_secret = NULL;
+ size_t premaster_secret_len = 0;
+ RSA *rsa = NULL;
+ uint8_t *decrypt_buf = NULL;
+ EVP_PKEY *pkey = NULL;
+ BIGNUM *pub = NULL;
+ DH *dh_srvr;
+
+ EC_KEY *srvr_ecdh = NULL;
+ EVP_PKEY *clnt_pub_pkey = NULL;
+ EC_POINT *clnt_ecpoint = NULL;
+ BN_CTX *bn_ctx = NULL;
+ unsigned int psk_len = 0;
+ uint8_t psk[PSK_MAX_PSK_LEN];
+
+ n = s->method->ssl_get_message(s, SSL3_ST_SR_KEY_EXCH_A,
+ SSL3_ST_SR_KEY_EXCH_B,
+ SSL3_MT_CLIENT_KEY_EXCHANGE, 2048, /* ??? */
+ SSL_GET_MESSAGE_HASH_MESSAGE, &ok);
+
+ if (!ok) {
+ return n;
+ }
+
+ CBS_init(&client_key_exchange, s->init_msg, n);
+
+ alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
+ alg_a = s->s3->tmp.new_cipher->algorithm_auth;
+
+ /* If using a PSK key exchange, prepare the pre-shared key. */
+ if (alg_a & SSL_aPSK) {
+ CBS psk_identity;
+
+ /* If using PSK, the ClientKeyExchange contains a psk_identity. If PSK,
+ * then this is the only field in the message. */
+ if (!CBS_get_u16_length_prefixed(&client_key_exchange, &psk_identity) ||
+ ((alg_k & SSL_kPSK) && CBS_len(&client_key_exchange) != 0)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, SSL_R_DECODE_ERROR);
+ al = SSL_AD_DECODE_ERROR;
+ goto f_err;
+ }
+
+ if (s->psk_server_callback == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange,
+ SSL_R_PSK_NO_SERVER_CB);
+ al = SSL_AD_INTERNAL_ERROR;
+ goto f_err;
+ }
+
+ if (CBS_len(&psk_identity) > PSK_MAX_IDENTITY_LEN ||
+ CBS_contains_zero_byte(&psk_identity)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange,
+ SSL_R_DATA_LENGTH_TOO_LONG);
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ goto f_err;
+ }
+
+ if (!CBS_strdup(&psk_identity, &s->session->psk_identity)) {
+ al = SSL_AD_INTERNAL_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange,
+ ERR_R_MALLOC_FAILURE);
+ goto f_err;
+ }
+
+ /* Look up the key for the identity. */
+ psk_len =
+ s->psk_server_callback(s, s->session->psk_identity, psk, sizeof(psk));
+ if (psk_len > PSK_MAX_PSK_LEN) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange,
+ ERR_R_INTERNAL_ERROR);
+ al = SSL_AD_INTERNAL_ERROR;
+ goto f_err;
+ } else if (psk_len == 0) {
+ /* PSK related to the given identity not found */
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange,
+ SSL_R_PSK_IDENTITY_NOT_FOUND);
+ al = SSL_AD_UNKNOWN_PSK_IDENTITY;
+ goto f_err;
+ }
+ }
+
+ /* Depending on the key exchange method, compute |premaster_secret| and
+ * |premaster_secret_len|. */
+ if (alg_k & SSL_kRSA) {
+ CBS encrypted_premaster_secret;
+ uint8_t rand_premaster_secret[SSL_MAX_MASTER_KEY_LENGTH];
+ uint8_t good;
+ size_t rsa_size, decrypt_len, premaster_index, j;
+
+ pkey = s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey;
+ if (pkey == NULL || pkey->type != EVP_PKEY_RSA || pkey->pkey.rsa == NULL) {
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange,
+ SSL_R_MISSING_RSA_CERTIFICATE);
+ goto f_err;
+ }
+ rsa = pkey->pkey.rsa;
+
+ /* TLS and [incidentally] DTLS{0xFEFF} */
+ if (s->version > SSL3_VERSION) {
+ CBS copy = client_key_exchange;
+ if (!CBS_get_u16_length_prefixed(&client_key_exchange,
+ &encrypted_premaster_secret) ||
+ CBS_len(&client_key_exchange) != 0) {
+ if (!(s->options & SSL_OP_TLS_D5_BUG)) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange,
+ SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG);
+ goto f_err;
+ } else {
+ encrypted_premaster_secret = copy;
+ }
+ }
+ } else {
+ encrypted_premaster_secret = client_key_exchange;
+ }
+
+ /* Reject overly short RSA keys because we want to be sure that the buffer
+ * size makes it safe to iterate over the entire size of a premaster secret
+ * (SSL_MAX_MASTER_KEY_LENGTH). The actual expected size is larger due to
+ * RSA padding, but the bound is sufficient to be safe. */
+ rsa_size = RSA_size(rsa);
+ if (rsa_size < SSL_MAX_MASTER_KEY_LENGTH) {
+ al = SSL_AD_DECRYPT_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange,
+ SSL_R_DECRYPTION_FAILED);
+ goto f_err;
+ }
+
+ /* We must not leak whether a decryption failure occurs because of
+ * Bleichenbacher's attack on PKCS #1 v1.5 RSA padding (see RFC 2246,
+ * section 7.4.7.1). The code follows that advice of the TLS RFC and
+ * generates a random premaster secret for the case that the decrypt fails.
+ * See https://tools.ietf.org/html/rfc5246#section-7.4.7.1 */
+ if (!RAND_bytes(rand_premaster_secret, sizeof(rand_premaster_secret))) {
+ goto err;
+ }
+
+ /* Allocate a buffer large enough for an RSA decryption. */
+ decrypt_buf = OPENSSL_malloc(rsa_size);
+ if (decrypt_buf == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ /* Decrypt with no padding. PKCS#1 padding will be removed as part of the
+ * timing-sensitive code below. */
+ if (!RSA_decrypt(rsa, &decrypt_len, decrypt_buf, rsa_size,
+ CBS_data(&encrypted_premaster_secret),
+ CBS_len(&encrypted_premaster_secret), RSA_NO_PADDING)) {
+ goto err;
+ }
+ if (decrypt_len != rsa_size) {
+ /* This should never happen, but do a check so we do not read
+ * uninitialized memory. */
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ /* Remove the PKCS#1 padding and adjust |decrypt_len| as appropriate.
+ * |good| will be 0xff if the premaster is acceptable and zero otherwise.
+ * */
+ good =
+ constant_time_eq_int_8(RSA_message_index_PKCS1_type_2(
+ decrypt_buf, decrypt_len, &premaster_index),
+ 1);
+ decrypt_len = decrypt_len - premaster_index;
+
+ /* decrypt_len should be SSL_MAX_MASTER_KEY_LENGTH. */
+ good &= constant_time_eq_8(decrypt_len, SSL_MAX_MASTER_KEY_LENGTH);
+
+ /* Copy over the unpadded premaster. Whatever the value of
+ * |decrypt_good_mask|, copy as if the premaster were the right length. It
+ * is important the memory access pattern be constant. */
+ premaster_secret =
+ BUF_memdup(decrypt_buf + (rsa_size - SSL_MAX_MASTER_KEY_LENGTH),
+ SSL_MAX_MASTER_KEY_LENGTH);
+ if (premaster_secret == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ OPENSSL_free(decrypt_buf);
+ decrypt_buf = NULL;
+
+ /* If the version in the decrypted pre-master secret is correct then
+ * version_good will be 0xff, otherwise it'll be zero. The
+ * Klima-Pokorny-Rosa extension of Bleichenbacher's attack
+ * (http://eprint.iacr.org/2003/052/) exploits the version number check as
+ * a "bad version oracle". Thus version checks are done in constant time
+ * and are treated like any other decryption error. */
+ good &= constant_time_eq_8(premaster_secret[0],
+ (unsigned)(s->client_version >> 8));
+ good &= constant_time_eq_8(premaster_secret[1],
+ (unsigned)(s->client_version & 0xff));
+
+ /* Now copy rand_premaster_secret over premaster_secret using
+ * decrypt_good_mask. */
+ for (j = 0; j < sizeof(rand_premaster_secret); j++) {
+ premaster_secret[j] = constant_time_select_8(good, premaster_secret[j],
+ rand_premaster_secret[j]);
+ }
+
+ premaster_secret_len = sizeof(rand_premaster_secret);
+ } else if (alg_k & SSL_kEDH) {
+ CBS dh_Yc;
+ int dh_len;
+
+ if (!CBS_get_u16_length_prefixed(&client_key_exchange, &dh_Yc) ||
+ CBS_len(&dh_Yc) == 0 || CBS_len(&client_key_exchange) != 0) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange,
+ SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG);
+ al = SSL_R_DECODE_ERROR;
+ goto f_err;
+ }
+
+ if (s->s3->tmp.dh == NULL) {
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange,
+ SSL_R_MISSING_TMP_DH_KEY);
+ goto f_err;
+ }
+ dh_srvr = s->s3->tmp.dh;
+
+ pub = BN_bin2bn(CBS_data(&dh_Yc), CBS_len(&dh_Yc), NULL);
+ if (pub == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, SSL_R_BN_LIB);
+ goto err;
+ }
+
+ /* Allocate a buffer for the premaster secret. */
+ premaster_secret = OPENSSL_malloc(DH_size(dh_srvr));
+ if (premaster_secret == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ dh_len = DH_compute_key(premaster_secret, pub, dh_srvr);
+ if (dh_len <= 0) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_DH_LIB);
+ BN_clear_free(pub);
+ goto err;
+ }
+
+ DH_free(s->s3->tmp.dh);
+ s->s3->tmp.dh = NULL;
+ BN_clear_free(pub);
+ pub = NULL;
+
+ premaster_secret_len = dh_len;
+ } else if (alg_k & SSL_kEECDH) {
+ int field_size = 0, ecdh_len;
+ const EC_KEY *tkey;
+ const EC_GROUP *group;
+ const BIGNUM *priv_key;
+ CBS ecdh_Yc;
+
+ /* initialize structures for server's ECDH key pair */
+ srvr_ecdh = EC_KEY_new();
+ if (srvr_ecdh == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ /* Use the ephermeral values we saved when generating the ServerKeyExchange
+ * msg. */
+ tkey = s->s3->tmp.ecdh;
+
+ group = EC_KEY_get0_group(tkey);
+ priv_key = EC_KEY_get0_private_key(tkey);
+
+ if (!EC_KEY_set_group(srvr_ecdh, group) ||
+ !EC_KEY_set_private_key(srvr_ecdh, priv_key)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_EC_LIB);
+ goto err;
+ }
+
+ /* Let's get client's public key */
+ clnt_ecpoint = EC_POINT_new(group);
+ if (clnt_ecpoint == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ /* Get client's public key from encoded point in the ClientKeyExchange
+ * message. */
+ if (!CBS_get_u8_length_prefixed(&client_key_exchange, &ecdh_Yc) ||
+ CBS_len(&client_key_exchange) != 0) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, SSL_R_DECODE_ERROR);
+ goto f_err;
+ }
+
+ bn_ctx = BN_CTX_new();
+ if (bn_ctx == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (!EC_POINT_oct2point(group, clnt_ecpoint, CBS_data(&ecdh_Yc),
+ CBS_len(&ecdh_Yc), bn_ctx)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_EC_LIB);
+ goto err;
+ }
+
+ /* Allocate a buffer for both the secret and the PSK. */
+ field_size = EC_GROUP_get_degree(group);
+ if (field_size <= 0) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_ECDH_LIB);
+ goto err;
+ }
+
+ ecdh_len = (field_size + 7) / 8;
+ premaster_secret = OPENSSL_malloc(ecdh_len);
+ if (premaster_secret == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ /* Compute the shared pre-master secret */
+ ecdh_len = ECDH_compute_key(premaster_secret, ecdh_len, clnt_ecpoint,
+ srvr_ecdh, NULL);
+ if (ecdh_len <= 0) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_ECDH_LIB);
+ goto err;
+ }
+
+ EVP_PKEY_free(clnt_pub_pkey);
+ clnt_pub_pkey = NULL;
+ EC_POINT_free(clnt_ecpoint);
+ clnt_ecpoint = NULL;
+ EC_KEY_free(srvr_ecdh);
+ srvr_ecdh = NULL;
+ BN_CTX_free(bn_ctx);
+ bn_ctx = NULL;
+ EC_KEY_free(s->s3->tmp.ecdh);
+ s->s3->tmp.ecdh = NULL;
+
+ premaster_secret_len = ecdh_len;
+ } else if (alg_k & SSL_kPSK) {
+ /* For plain PSK, other_secret is a block of 0s with the same length as the
+ * pre-shared key. */
+ premaster_secret_len = psk_len;
+ premaster_secret = OPENSSL_malloc(premaster_secret_len);
+ if (premaster_secret == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ memset(premaster_secret, 0, premaster_secret_len);
+ } else {
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange,
+ SSL_R_UNKNOWN_CIPHER_TYPE);
+ goto f_err;
+ }
+
+ /* For a PSK cipher suite, the actual pre-master secret is combined with the
+ * pre-shared key. */
+ if (alg_a & SSL_aPSK) {
+ CBB new_premaster, child;
+ uint8_t *new_data;
+ size_t new_len;
+
+ if (!CBB_init(&new_premaster, 2 + psk_len + 2 + premaster_secret_len)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ if (!CBB_add_u16_length_prefixed(&new_premaster, &child) ||
+ !CBB_add_bytes(&child, premaster_secret, premaster_secret_len) ||
+ !CBB_add_u16_length_prefixed(&new_premaster, &child) ||
+ !CBB_add_bytes(&child, psk, psk_len) ||
+ !CBB_finish(&new_premaster, &new_data, &new_len)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange,
+ ERR_R_INTERNAL_ERROR);
+ CBB_cleanup(&new_premaster);
+ goto err;
+ }
+
+ OPENSSL_cleanse(premaster_secret, premaster_secret_len);
+ OPENSSL_free(premaster_secret);
+ premaster_secret = new_data;
+ premaster_secret_len = new_len;
+ }
+
+ /* Compute the master secret */
+ s->session->master_key_length = s->enc_method->generate_master_secret(
+ s, s->session->master_key, premaster_secret, premaster_secret_len);
+ if (s->session->master_key_length == 0) {
+ goto err;
+ }
+ s->session->extended_master_secret = s->s3->tmp.extended_master_secret;
+
+ OPENSSL_cleanse(premaster_secret, premaster_secret_len);
+ OPENSSL_free(premaster_secret);
+ return 1;
+
+f_err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+err:
+ if (premaster_secret) {
+ if (premaster_secret_len) {
+ OPENSSL_cleanse(premaster_secret, premaster_secret_len);
+ }
+ OPENSSL_free(premaster_secret);
+ }
+ if (decrypt_buf) {
+ OPENSSL_free(decrypt_buf);
+ }
+ EVP_PKEY_free(clnt_pub_pkey);
+ EC_POINT_free(clnt_ecpoint);
+ if (srvr_ecdh != NULL) {
+ EC_KEY_free(srvr_ecdh);
+ }
+ BN_CTX_free(bn_ctx);
+
+ return -1;
+}
+
+int ssl3_get_cert_verify(SSL *s) {
+ int al, ok, ret = 0;
+ long n;
+ CBS certificate_verify, signature;
+ X509 *peer = s->session->peer;
+ EVP_PKEY *pkey = NULL;
+ const EVP_MD *md = NULL;
+ uint8_t digest[EVP_MAX_MD_SIZE];
+ size_t digest_length;
+ EVP_PKEY_CTX *pctx = NULL;
+
+ /* Only RSA and ECDSA client certificates are supported, so a
+ * CertificateVerify is required if and only if there's a client certificate.
+ * */
+ if (peer == NULL) {
+ if (s->s3->handshake_buffer &&
+ !ssl3_digest_cached_records(s, free_handshake_buffer)) {
+ return -1;
+ }
+ return 1;
+ }
+
+ n = s->method->ssl_get_message(
+ s, SSL3_ST_SR_CERT_VRFY_A, SSL3_ST_SR_CERT_VRFY_B,
+ SSL3_MT_CERTIFICATE_VERIFY, SSL3_RT_MAX_PLAIN_LENGTH,
+ SSL_GET_MESSAGE_DONT_HASH_MESSAGE, &ok);
+
+ if (!ok) {
+ return n;
+ }
+
+ /* Filter out unsupported certificate types. */
+ pkey = X509_get_pubkey(peer);
+ if (!(X509_certificate_type(peer, pkey) & EVP_PKT_SIGN) ||
+ (pkey->type != EVP_PKEY_RSA && pkey->type != EVP_PKEY_EC)) {
+ al = SSL_AD_UNSUPPORTED_CERTIFICATE;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_cert_verify,
+ SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE);
+ goto f_err;
+ }
+
+ CBS_init(&certificate_verify, s->init_msg, n);
+
+ /* Determine the digest type if needbe. */
+ if (SSL_USE_SIGALGS(s) &&
+ !tls12_check_peer_sigalg(&md, &al, s, &certificate_verify, pkey)) {
+ goto f_err;
+ }
+
+ /* Compute the digest. */
+ if (!ssl3_cert_verify_hash(s, digest, &digest_length, &md, pkey)) {
+ goto err;
+ }
+
+ /* The handshake buffer is no longer necessary, and we may hash the current
+ * message.*/
+ if (s->s3->handshake_buffer &&
+ !ssl3_digest_cached_records(s, free_handshake_buffer)) {
+ goto err;
+ }
+ ssl3_hash_current_message(s);
+
+ /* Parse and verify the signature. */
+ if (!CBS_get_u16_length_prefixed(&certificate_verify, &signature) ||
+ CBS_len(&certificate_verify) != 0) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_cert_verify, SSL_R_DECODE_ERROR);
+ goto f_err;
+ }
+
+ pctx = EVP_PKEY_CTX_new(pkey, NULL);
+ if (pctx == NULL) {
+ goto err;
+ }
+ if (!EVP_PKEY_verify_init(pctx) ||
+ !EVP_PKEY_CTX_set_signature_md(pctx, md) ||
+ !EVP_PKEY_verify(pctx, CBS_data(&signature), CBS_len(&signature), digest,
+ digest_length)) {
+ al = SSL_AD_DECRYPT_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_cert_verify, SSL_R_BAD_SIGNATURE);
+ goto f_err;
+ }
+
+ ret = 1;
+
+ if (0) {
+ f_err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ }
+
+err:
+ EVP_PKEY_CTX_free(pctx);
+ EVP_PKEY_free(pkey);
+
+ return ret;
+}
+
+int ssl3_get_client_certificate(SSL *s) {
+ int i, ok, al, ret = -1;
+ X509 *x = NULL;
+ unsigned long n;
+ STACK_OF(X509) *sk = NULL;
+ SHA256_CTX sha256;
+ CBS certificate_msg, certificate_list;
+ int is_first_certificate = 1;
+
+ n = s->method->ssl_get_message(s, SSL3_ST_SR_CERT_A, SSL3_ST_SR_CERT_B, -1,
+ s->max_cert_list, SSL_GET_MESSAGE_HASH_MESSAGE,
+ &ok);
+
+ if (!ok) {
+ return n;
+ }
+
+ if (s->s3->tmp.message_type == SSL3_MT_CLIENT_KEY_EXCHANGE) {
+ if ((s->verify_mode & SSL_VERIFY_PEER) &&
+ (s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate,
+ SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ goto f_err;
+ }
+
+ /* If tls asked for a client cert, the client must return a 0 list */
+ if (s->version > SSL3_VERSION && s->s3->tmp.cert_request) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate,
+ SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST);
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ goto f_err;
+ }
+ s->s3->tmp.reuse_message = 1;
+
+ return 1;
+ }
+
+ if (s->s3->tmp.message_type != SSL3_MT_CERTIFICATE) {
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate,
+ SSL_R_WRONG_MESSAGE_TYPE);
+ goto f_err;
+ }
+
+ CBS_init(&certificate_msg, s->init_msg, n);
+
+ sk = sk_X509_new_null();
+ if (sk == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (!CBS_get_u24_length_prefixed(&certificate_msg, &certificate_list) ||
+ CBS_len(&certificate_msg) != 0) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, SSL_R_DECODE_ERROR);
+ goto f_err;
+ }
+
+ while (CBS_len(&certificate_list) > 0) {
+ CBS certificate;
+ const uint8_t *data;
+
+ if (!CBS_get_u24_length_prefixed(&certificate_list, &certificate)) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, SSL_R_DECODE_ERROR);
+ goto f_err;
+ }
+
+ if (is_first_certificate && s->ctx->retain_only_sha256_of_client_certs) {
+ /* If this is the first certificate, and we don't want to keep peer
+ * certificates in memory, then we hash it right away. */
+ SHA256_Init(&sha256);
+ SHA256_Update(&sha256, CBS_data(&certificate), CBS_len(&certificate));
+ SHA256_Final(s->session->peer_sha256, &sha256);
+ s->session->peer_sha256_valid = 1;
+ }
+ is_first_certificate = 0;
+
+ data = CBS_data(&certificate);
+ x = d2i_X509(NULL, &data, CBS_len(&certificate));
+ if (x == NULL) {
+ al = SSL_AD_BAD_CERTIFICATE;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, ERR_R_ASN1_LIB);
+ goto f_err;
+ }
+ if (data != CBS_data(&certificate) + CBS_len(&certificate)) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate,
+ SSL_R_CERT_LENGTH_MISMATCH);
+ goto f_err;
+ }
+ if (!sk_X509_push(sk, x)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ x = NULL;
+ }
+
+ if (sk_X509_num(sk) <= 0) {
+ /* TLS does not mind 0 certs returned */
+ if (s->version == SSL3_VERSION) {
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate,
+ SSL_R_NO_CERTIFICATES_RETURNED);
+ goto f_err;
+ }
+ /* Fail for TLS only if we required a certificate */
+ else if ((s->verify_mode & SSL_VERIFY_PEER) &&
+ (s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate,
+ SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ goto f_err;
+ }
+ /* No client certificate so digest cached records */
+ if (s->s3->handshake_buffer &&
+ !ssl3_digest_cached_records(s, free_handshake_buffer)) {
+ al = SSL_AD_INTERNAL_ERROR;
+ goto f_err;
+ }
+ } else {
+ i = ssl_verify_cert_chain(s, sk);
+ if (i <= 0) {
+ al = ssl_verify_alarm_type(s->verify_result);
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate,
+ SSL_R_CERTIFICATE_VERIFY_FAILED);
+ goto f_err;
+ }
+ }
+
+ if (s->session->peer != NULL) {
+ /* This should not be needed */
+ X509_free(s->session->peer);
+ }
+
+ s->session->peer = sk_X509_shift(sk);
+ s->session->verify_result = s->verify_result;
+
+ /* With the current implementation, sess_cert will always be NULL when we
+ * arrive here. */
+ if (s->session->sess_cert == NULL) {
+ s->session->sess_cert = ssl_sess_cert_new();
+ if (s->session->sess_cert == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+ if (s->session->sess_cert->cert_chain != NULL) {
+ sk_X509_pop_free(s->session->sess_cert->cert_chain, X509_free);
+ }
+ s->session->sess_cert->cert_chain = sk;
+ /* Inconsistency alert: cert_chain does *not* include the peer's own
+ * certificate, while we do include it in s3_clnt.c */
+
+ sk = NULL;
+
+ ret = 1;
+
+ if (0) {
+ f_err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ }
+
+err:
+ if (x != NULL) {
+ X509_free(x);
+ }
+ if (sk != NULL) {
+ sk_X509_pop_free(sk, X509_free);
+ }
+ return ret;
+}
+
+int ssl3_send_server_certificate(SSL *s) {
+ CERT_PKEY *cpk;
+
+ if (s->state == SSL3_ST_SW_CERT_A) {
+ cpk = ssl_get_server_send_pkey(s);
+ if (cpk == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_server_certificate,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ ssl3_output_cert_chain(s, cpk);
+ s->state = SSL3_ST_SW_CERT_B;
+ }
+
+ /* SSL3_ST_SW_CERT_B */
+ return ssl_do_write(s);
+}
+
+/* send a new session ticket (not necessarily for a new session) */
+int ssl3_send_new_session_ticket(SSL *s) {
+ if (s->state == SSL3_ST_SW_SESSION_TICKET_A) {
+ uint8_t *session;
+ size_t session_len;
+ uint8_t *p, *macstart;
+ int len;
+ unsigned int hlen;
+ EVP_CIPHER_CTX ctx;
+ HMAC_CTX hctx;
+ SSL_CTX *tctx = s->initial_ctx;
+ uint8_t iv[EVP_MAX_IV_LENGTH];
+ uint8_t key_name[16];
+ /* The maximum overhead of encrypting the session is 16 (key name) + IV +
+ * one block of encryption overhead + HMAC. */
+ const size_t max_ticket_overhead =
+ 16 + EVP_MAX_IV_LENGTH + EVP_MAX_BLOCK_LENGTH + EVP_MAX_MD_SIZE;
+
+ /* Serialize the SSL_SESSION to be encoded into the ticket. */
+ if (!SSL_SESSION_to_bytes_for_ticket(s->session, &session, &session_len)) {
+ return -1;
+ }
+
+ /* If the session is too long, emit a dummy value rather than abort the
+ * connection. */
+ if (session_len > 0xFFFF - max_ticket_overhead) {
+ static const char kTicketPlaceholder[] = "TICKET TOO LARGE";
+ const size_t placeholder_len = strlen(kTicketPlaceholder);
+
+ OPENSSL_free(session);
+
+ p = ssl_handshake_start(s);
+ /* Emit ticket_lifetime_hint. */
+ l2n(0, p);
+ /* Emit ticket. */
+ s2n(placeholder_len, p);
+ memcpy(p, kTicketPlaceholder, placeholder_len);
+ p += placeholder_len;
+
+ len = p - ssl_handshake_start(s);
+ ssl_set_handshake_header(s, SSL3_MT_NEWSESSION_TICKET, len);
+ s->state = SSL3_ST_SW_SESSION_TICKET_B;
+ return ssl_do_write(s);
+ }
+
+ /* Grow buffer if need be: the length calculation is as follows:
+ * handshake_header_length + 4 (ticket lifetime hint) + 2 (ticket length) +
+ * max_ticket_overhead + * session_length */
+ if (!BUF_MEM_grow(s->init_buf, SSL_HM_HEADER_LENGTH(s) + 6 +
+ max_ticket_overhead + session_len)) {
+ OPENSSL_free(session);
+ return -1;
+ }
+ p = ssl_handshake_start(s);
+ EVP_CIPHER_CTX_init(&ctx);
+ HMAC_CTX_init(&hctx);
+ /* Initialize HMAC and cipher contexts. If callback present it does all the
+ * work otherwise use generated values from parent ctx. */
+ if (tctx->tlsext_ticket_key_cb) {
+ if (tctx->tlsext_ticket_key_cb(s, key_name, iv, &ctx, &hctx, 1) < 0) {
+ OPENSSL_free(session);
+ EVP_CIPHER_CTX_cleanup(&ctx);
+ HMAC_CTX_cleanup(&hctx);
+ return -1;
+ }
+ } else {
+ if (!RAND_bytes(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, tlsext_tick_md(),
+ NULL)) {
+ OPENSSL_free(session);
+ EVP_CIPHER_CTX_cleanup(&ctx);
+ HMAC_CTX_cleanup(&hctx);
+ return -1;
+ }
+ memcpy(key_name, tctx->tlsext_tick_key_name, 16);
+ }
+
+ /* 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. */
+ l2n(s->hit ? 0 : s->session->timeout, p);
+
+ /* Skip ticket length for now */
+ p += 2;
+ /* Output key name */
+ macstart = p;
+ memcpy(p, key_name, 16);
+ p += 16;
+ /* output IV */
+ memcpy(p, iv, EVP_CIPHER_CTX_iv_length(&ctx));
+ p += EVP_CIPHER_CTX_iv_length(&ctx);
+ /* Encrypt session data */
+ EVP_EncryptUpdate(&ctx, p, &len, session, session_len);
+ p += len;
+ EVP_EncryptFinal_ex(&ctx, p, &len);
+ p += len;
+ EVP_CIPHER_CTX_cleanup(&ctx);
+
+ HMAC_Update(&hctx, macstart, p - macstart);
+ HMAC_Final(&hctx, p, &hlen);
+ HMAC_CTX_cleanup(&hctx);
+
+ p += hlen;
+ /* Now write out lengths: p points to end of data written */
+ /* Total length */
+ len = p - ssl_handshake_start(s);
+ /* Skip ticket lifetime hint */
+ p = ssl_handshake_start(s) + 4;
+ s2n(len - 6, p);
+ ssl_set_handshake_header(s, SSL3_MT_NEWSESSION_TICKET, len);
+ s->state = SSL3_ST_SW_SESSION_TICKET_B;
+ OPENSSL_free(session);
+ }
+
+ /* SSL3_ST_SW_SESSION_TICKET_B */
+ return ssl_do_write(s);
+}
+
+/* ssl3_get_next_proto reads a Next Protocol Negotiation handshake message. It
+ * sets the next_proto member in s if found */
+int ssl3_get_next_proto(SSL *s) {
+ int ok;
+ long n;
+ CBS next_protocol, selected_protocol, padding;
+
+ /* Clients cannot send a NextProtocol message if we didn't see the extension
+ * in their ClientHello */
+ if (!s->s3->next_proto_neg_seen) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_next_proto,
+ SSL_R_GOT_NEXT_PROTO_WITHOUT_EXTENSION);
+ return -1;
+ }
+
+ n = s->method->ssl_get_message(s, SSL3_ST_SR_NEXT_PROTO_A,
+ SSL3_ST_SR_NEXT_PROTO_B, SSL3_MT_NEXT_PROTO,
+ 514, /* See the payload format below */
+ SSL_GET_MESSAGE_HASH_MESSAGE, &ok);
+
+ if (!ok) {
+ return n;
+ }
+
+ /* s->state doesn't reflect whether ChangeCipherSpec has been received in
+ * this handshake, but s->s3->change_cipher_spec does (will be reset by
+ * ssl3_get_finished).
+ *
+ * TODO(davidben): Is this check now redundant with
+ * SSL3_FLAGS_EXPECT_CCS? */
+ if (!s->s3->change_cipher_spec) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_next_proto,
+ SSL_R_GOT_NEXT_PROTO_BEFORE_A_CCS);
+ return -1;
+ }
+
+ CBS_init(&next_protocol, s->init_msg, n);
+
+ /* The payload looks like:
+ * uint8 proto_len;
+ * uint8 proto[proto_len];
+ * uint8 padding_len;
+ * uint8 padding[padding_len]; */
+ if (!CBS_get_u8_length_prefixed(&next_protocol, &selected_protocol) ||
+ !CBS_get_u8_length_prefixed(&next_protocol, &padding) ||
+ CBS_len(&next_protocol) != 0 ||
+ !CBS_stow(&selected_protocol, &s->next_proto_negotiated,
+ &s->next_proto_negotiated_len)) {
+ return 0;
+ }
+
+ return 1;
+}
+
+/* ssl3_get_channel_id reads and verifies a ClientID handshake message. */
+int ssl3_get_channel_id(SSL *s) {
+ int ret = -1, ok;
+ long n;
+ EVP_MD_CTX md_ctx;
+ uint8_t channel_id_hash[SHA256_DIGEST_LENGTH];
+ unsigned int channel_id_hash_len;
+ const uint8_t *p;
+ uint16_t extension_type, expected_extension_type;
+ EC_GROUP *p256 = NULL;
+ EC_KEY *key = NULL;
+ EC_POINT *point = NULL;
+ ECDSA_SIG sig;
+ BIGNUM x, y;
+ CBS encrypted_extensions, extension;
+
+ n = s->method->ssl_get_message(
+ s, SSL3_ST_SR_CHANNEL_ID_A, SSL3_ST_SR_CHANNEL_ID_B,
+ SSL3_MT_ENCRYPTED_EXTENSIONS, 2 + 2 + TLSEXT_CHANNEL_ID_SIZE,
+ SSL_GET_MESSAGE_DONT_HASH_MESSAGE, &ok);
+
+ if (!ok) {
+ return n;
+ }
+
+ /* Before incorporating the EncryptedExtensions message to the handshake
+ * hash, compute the hash that should have been signed. */
+ channel_id_hash_len = sizeof(channel_id_hash);
+ EVP_MD_CTX_init(&md_ctx);
+ if (!EVP_DigestInit_ex(&md_ctx, EVP_sha256(), NULL) ||
+ !tls1_channel_id_hash(&md_ctx, s) ||
+ !EVP_DigestFinal(&md_ctx, channel_id_hash, &channel_id_hash_len)) {
+ EVP_MD_CTX_cleanup(&md_ctx);
+ return -1;
+ }
+ EVP_MD_CTX_cleanup(&md_ctx);
+ assert(channel_id_hash_len == SHA256_DIGEST_LENGTH);
+
+ ssl3_hash_current_message(s);
+
+ /* s->state doesn't reflect whether ChangeCipherSpec has been received in
+ * this handshake, but s->s3->change_cipher_spec does (will be reset by
+ * ssl3_get_finished).
+ *
+ * TODO(davidben): Is this check now redundant with SSL3_FLAGS_EXPECT_CCS? */
+ if (!s->s3->change_cipher_spec) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_channel_id,
+ SSL_R_GOT_CHANNEL_ID_BEFORE_A_CCS);
+ return -1;
+ }
+
+ CBS_init(&encrypted_extensions, s->init_msg, n);
+
+ /* EncryptedExtensions could include multiple extensions, but the only
+ * extension that could be negotiated is ChannelID, so there can only be one
+ * entry.
+ *
+ * The payload looks like:
+ * uint16 extension_type
+ * uint16 extension_len;
+ * uint8 x[32];
+ * uint8 y[32];
+ * uint8 r[32];
+ * uint8 s[32]; */
+ expected_extension_type = TLSEXT_TYPE_channel_id;
+ if (s->s3->tlsext_channel_id_new) {
+ expected_extension_type = TLSEXT_TYPE_channel_id_new;
+ }
+
+ if (!CBS_get_u16(&encrypted_extensions, &extension_type) ||
+ !CBS_get_u16_length_prefixed(&encrypted_extensions, &extension) ||
+ CBS_len(&encrypted_extensions) != 0 ||
+ extension_type != expected_extension_type ||
+ CBS_len(&extension) != TLSEXT_CHANNEL_ID_SIZE) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_channel_id, SSL_R_INVALID_MESSAGE);
+ return -1;
+ }
+
+ p256 = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1);
+ if (!p256) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_channel_id, SSL_R_NO_P256_SUPPORT);
+ return -1;
+ }
+
+ BN_init(&x);
+ BN_init(&y);
+ sig.r = BN_new();
+ sig.s = BN_new();
+
+ p = CBS_data(&extension);
+ if (BN_bin2bn(p + 0, 32, &x) == NULL ||
+ BN_bin2bn(p + 32, 32, &y) == NULL ||
+ BN_bin2bn(p + 64, 32, sig.r) == NULL ||
+ BN_bin2bn(p + 96, 32, sig.s) == NULL) {
+ goto err;
+ }
+
+ point = EC_POINT_new(p256);
+ if (!point || !EC_POINT_set_affine_coordinates_GFp(p256, point, &x, &y, NULL)) {
+ goto err;
+ }
+
+ key = EC_KEY_new();
+ if (!key || !EC_KEY_set_group(key, p256) ||
+ !EC_KEY_set_public_key(key, point)) {
+ goto err;
+ }
+
+ /* We stored the handshake hash in |tlsext_channel_id| the first time that we
+ * were called. */
+ if (!ECDSA_do_verify(channel_id_hash, channel_id_hash_len, &sig, key)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_channel_id,
+ SSL_R_CHANNEL_ID_SIGNATURE_INVALID);
+ s->s3->tlsext_channel_id_valid = 0;
+ goto err;
+ }
+
+ memcpy(s->s3->tlsext_channel_id, p, 64);
+ ret = 1;
+
+err:
+ BN_free(&x);
+ BN_free(&y);
+ BN_free(sig.r);
+ BN_free(sig.s);
+ if (key) {
+ EC_KEY_free(key);
+ }
+ if (point) {
+ EC_POINT_free(point);
+ }
+ if (p256) {
+ EC_GROUP_free(p256);
+ }
+ return ret;
+}
diff --git a/src/ssl/ssl_algs.c b/src/ssl/ssl_algs.c
new file mode 100644
index 0000000..6ec88bf
--- /dev/null
+++ b/src/ssl/ssl_algs.c
@@ -0,0 +1,71 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 "ssl_locl.h"
+
+#include <openssl/crypto.h>
+
+extern const ERR_STRING_DATA SSL_error_string_data[];
+
+int SSL_library_init(void) {
+ CRYPTO_library_init();
+ ERR_load_crypto_strings();
+ ERR_load_strings(SSL_error_string_data);
+ return 1;
+}
+
+void SSL_load_error_strings(void) {
+}
diff --git a/src/ssl/ssl_asn1.c b/src/ssl/ssl_asn1.c
new file mode 100644
index 0000000..d39da87
--- /dev/null
+++ b/src/ssl/ssl_asn1.c
@@ -0,0 +1,591 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <limits.h>
+#include <string.h>
+
+#include <openssl/bytestring.h>
+#include <openssl/err.h>
+#include <openssl/x509.h>
+
+#include "ssl_locl.h"
+
+
+/* An SSL_SESSION is serialized as the following ASN.1 structure:
+ *
+ * SSLSession ::= SEQUENCE {
+ * version INTEGER (1), -- ignored
+ * sslVersion INTEGER, -- protocol version number
+ * cipher OCTET STRING, -- two bytes long
+ * sessionID OCTET STRING,
+ * masterKey OCTET STRING,
+ * time [1] INTEGER OPTIONAL, -- seconds since UNIX epoch
+ * timeout [2] INTEGER OPTIONAL, -- in seconds
+ * peer [3] Certificate OPTIONAL,
+ * sessionIDContext [4] OCTET STRING OPTIONAL,
+ * verifyResult [5] INTEGER OPTIONAL, -- one of X509_V_* codes
+ * hostName [6] OCTET STRING OPTIONAL,
+ * -- from server_name extension
+ * pskIdentity [8] OCTET STRING OPTIONAL,
+ * ticketLifetimeHint [9] INTEGER OPTIONAL, -- client-only
+ * ticket [10] OCTET STRING OPTIONAL, -- client-only
+ * peerSHA256 [13] OCTET STRING OPTIONAL,
+ * originalHandshakeHash [14] OCTET STRING OPTIONAL,
+ * signedCertTimestampList [15] OCTET STRING OPTIONAL,
+ * -- contents of SCT extension
+ * ocspResponse [16] OCTET STRING OPTIONAL,
+ * -- stapled OCSP response from the server
+ * extendedMasterSecret [17] BOOLEAN OPTIONAL,
+ * }
+ *
+ * Note: historically this serialization has included other optional
+ * fields. Their presense is currently treated as a parse error:
+ *
+ * keyArg [0] IMPLICIT OCTET STRING OPTIONAL,
+ * pskIdentityHint [7] OCTET STRING OPTIONAL,
+ * compressionMethod [11] OCTET STRING OPTIONAL,
+ * srpUsername [12] OCTET STRING OPTIONAL, */
+
+static const int kTimeTag =
+ CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 1;
+static const int kTimeoutTag =
+ CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 2;
+static const int kPeerTag =
+ CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 3;
+ static const int kSessionIDContextTag =
+ CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 4;
+static const int kVerifyResultTag =
+ CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 5;
+static const int kHostNameTag =
+ CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 6;
+static const int kPSKIdentityTag =
+ CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 8;
+static const int kTicketLifetimeHintTag =
+ CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 9;
+static const int kTicketTag =
+ CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 10;
+static const int kPeerSHA256Tag =
+ CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 13;
+static const int kOriginalHandshakeHashTag =
+ CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 14;
+static const int kSignedCertTimestampListTag =
+ CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 15;
+static const int kOCSPResponseTag =
+ CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 16;
+static const int kExtendedMasterSecretTag =
+ CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 17;
+
+static int SSL_SESSION_to_bytes_full(SSL_SESSION *in, uint8_t **out_data,
+ size_t *out_len, int for_ticket) {
+ CBB cbb, session, child, child2;
+
+ if (in == NULL || in->cipher == NULL) {
+ return 0;
+ }
+
+ if (!CBB_init(&cbb, 0)) {
+ return 0;
+ }
+
+ if (!CBB_add_asn1(&cbb, &session, CBS_ASN1_SEQUENCE) ||
+ !CBB_add_asn1_uint64(&session, SSL_SESSION_ASN1_VERSION) ||
+ !CBB_add_asn1_uint64(&session, in->ssl_version) ||
+ !CBB_add_asn1(&session, &child, CBS_ASN1_OCTETSTRING) ||
+ !CBB_add_u16(&child, (uint16_t)(in->cipher->id & 0xffff)) ||
+ !CBB_add_asn1(&session, &child, CBS_ASN1_OCTETSTRING) ||
+ /* The session ID is irrelevant for a session ticket. */
+ !CBB_add_bytes(&child, in->session_id,
+ for_ticket ? 0 : in->session_id_length) ||
+ !CBB_add_asn1(&session, &child, CBS_ASN1_OCTETSTRING) ||
+ !CBB_add_bytes(&child, in->master_key, in->master_key_length)) {
+ OPENSSL_PUT_ERROR(SSL, i2d_SSL_SESSION, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (in->time != 0) {
+ if (!CBB_add_asn1(&session, &child, kTimeTag) ||
+ !CBB_add_asn1_uint64(&child, in->time)) {
+ OPENSSL_PUT_ERROR(SSL, i2d_SSL_SESSION, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+
+ if (in->timeout != 0) {
+ if (!CBB_add_asn1(&session, &child, kTimeoutTag) ||
+ !CBB_add_asn1_uint64(&child, in->timeout)) {
+ OPENSSL_PUT_ERROR(SSL, i2d_SSL_SESSION, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+
+ /* The peer certificate is only serialized if the SHA-256 isn't
+ * serialized instead. */
+ if (in->peer && !in->peer_sha256_valid) {
+ uint8_t *buf;
+ int len = i2d_X509(in->peer, NULL);
+ if (len < 0) {
+ goto err;
+ }
+ if (!CBB_add_asn1(&session, &child, kPeerTag) ||
+ !CBB_add_space(&child, &buf, len)) {
+ OPENSSL_PUT_ERROR(SSL, i2d_SSL_SESSION, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ if (buf != NULL && i2d_X509(in->peer, &buf) < 0) {
+ goto err;
+ }
+ }
+
+ /* Although it is OPTIONAL and usually empty, OpenSSL has
+ * historically always encoded the sid_ctx. */
+ if (!CBB_add_asn1(&session, &child, kSessionIDContextTag) ||
+ !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
+ !CBB_add_bytes(&child2, in->sid_ctx, in->sid_ctx_length)) {
+ OPENSSL_PUT_ERROR(SSL, i2d_SSL_SESSION, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (in->verify_result != X509_V_OK) {
+ if (!CBB_add_asn1(&session, &child, kVerifyResultTag) ||
+ !CBB_add_asn1_uint64(&child, in->verify_result)) {
+ OPENSSL_PUT_ERROR(SSL, i2d_SSL_SESSION, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+
+ if (in->tlsext_hostname) {
+ if (!CBB_add_asn1(&session, &child, kHostNameTag) ||
+ !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
+ !CBB_add_bytes(&child2, (const uint8_t *)in->tlsext_hostname,
+ strlen(in->tlsext_hostname))) {
+ OPENSSL_PUT_ERROR(SSL, i2d_SSL_SESSION, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+
+ if (in->psk_identity) {
+ if (!CBB_add_asn1(&session, &child, kPSKIdentityTag) ||
+ !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
+ !CBB_add_bytes(&child2, (const uint8_t *)in->psk_identity,
+ strlen(in->psk_identity))) {
+ OPENSSL_PUT_ERROR(SSL, i2d_SSL_SESSION, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+
+ if (in->tlsext_tick_lifetime_hint > 0) {
+ if (!CBB_add_asn1(&session, &child, kTicketLifetimeHintTag) ||
+ !CBB_add_asn1_uint64(&child, in->tlsext_tick_lifetime_hint)) {
+ OPENSSL_PUT_ERROR(SSL, i2d_SSL_SESSION, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+
+ if (in->tlsext_tick) {
+ if (!CBB_add_asn1(&session, &child, kTicketTag) ||
+ !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
+ !CBB_add_bytes(&child2, in->tlsext_tick, in->tlsext_ticklen)) {
+ OPENSSL_PUT_ERROR(SSL, i2d_SSL_SESSION, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+
+ if (in->peer_sha256_valid) {
+ if (!CBB_add_asn1(&session, &child, kPeerSHA256Tag) ||
+ !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
+ !CBB_add_bytes(&child2, in->peer_sha256, sizeof(in->peer_sha256))) {
+ OPENSSL_PUT_ERROR(SSL, i2d_SSL_SESSION, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+
+ if (in->original_handshake_hash_len > 0) {
+ if (!CBB_add_asn1(&session, &child, kOriginalHandshakeHashTag) ||
+ !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
+ !CBB_add_bytes(&child2, in->original_handshake_hash,
+ in->original_handshake_hash_len)) {
+ OPENSSL_PUT_ERROR(SSL, i2d_SSL_SESSION, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+
+ if (in->tlsext_signed_cert_timestamp_list_length > 0) {
+ if (!CBB_add_asn1(&session, &child, kSignedCertTimestampListTag) ||
+ !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
+ !CBB_add_bytes(&child2, in->tlsext_signed_cert_timestamp_list,
+ in->tlsext_signed_cert_timestamp_list_length)) {
+ OPENSSL_PUT_ERROR(SSL, i2d_SSL_SESSION, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+
+ if (in->ocsp_response_length > 0) {
+ if (!CBB_add_asn1(&session, &child, kOCSPResponseTag) ||
+ !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
+ !CBB_add_bytes(&child2, in->ocsp_response, in->ocsp_response_length)) {
+ OPENSSL_PUT_ERROR(SSL, i2d_SSL_SESSION, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+
+ if (in->extended_master_secret) {
+ if (!CBB_add_asn1(&session, &child, kExtendedMasterSecretTag) ||
+ !CBB_add_asn1(&child, &child2, CBS_ASN1_BOOLEAN) ||
+ !CBB_add_u8(&child2, 0xff)) {
+ OPENSSL_PUT_ERROR(SSL, i2d_SSL_SESSION, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+
+ if (!CBB_finish(&cbb, out_data, out_len)) {
+ OPENSSL_PUT_ERROR(SSL, i2d_SSL_SESSION, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ return 1;
+
+ err:
+ CBB_cleanup(&cbb);
+ return 0;
+}
+
+int SSL_SESSION_to_bytes(SSL_SESSION *in, uint8_t **out_data, size_t *out_len) {
+ return SSL_SESSION_to_bytes_full(in, out_data, out_len, 0);
+}
+
+int SSL_SESSION_to_bytes_for_ticket(SSL_SESSION *in, uint8_t **out_data,
+ size_t *out_len) {
+ return SSL_SESSION_to_bytes_full(in, out_data, out_len, 1);
+}
+
+int i2d_SSL_SESSION(SSL_SESSION *in, uint8_t **pp) {
+ uint8_t *out;
+ size_t len;
+
+ if (!SSL_SESSION_to_bytes(in, &out, &len)) {
+ return -1;
+ }
+
+ if (len > INT_MAX) {
+ OPENSSL_free(out);
+ OPENSSL_PUT_ERROR(SSL, i2d_SSL_SESSION, ERR_R_OVERFLOW);
+ return -1;
+ }
+
+ if (pp) {
+ memcpy(*pp, out, len);
+ *pp += len;
+ }
+ OPENSSL_free(out);
+
+ return len;
+}
+
+/* d2i_SSL_SESSION_get_string gets an optional ASN.1 OCTET STRING
+ * explicitly tagged with |tag| from |cbs| and saves it in |*out|. On
+ * entry, if |*out| is not NULL, it frees the existing contents. If
+ * the element was not found, it sets |*out| to NULL. It returns one
+ * on success, whether or not the element was found, and zero on
+ * decode error. */
+static int d2i_SSL_SESSION_get_string(CBS *cbs, char **out, unsigned tag) {
+ CBS value;
+ int present;
+ if (!CBS_get_optional_asn1_octet_string(cbs, &value, &present, tag)) {
+ OPENSSL_PUT_ERROR(SSL, d2i_SSL_SESSION, SSL_R_INVALID_SSL_SESSION);
+ return 0;
+ }
+ if (present) {
+ if (CBS_contains_zero_byte(&value)) {
+ OPENSSL_PUT_ERROR(SSL, d2i_SSL_SESSION, SSL_R_INVALID_SSL_SESSION);
+ return 0;
+ }
+ if (!CBS_strdup(&value, out)) {
+ OPENSSL_PUT_ERROR(SSL, d2i_SSL_SESSION, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ } else if (*out) {
+ OPENSSL_free(*out);
+ *out = NULL;
+ }
+ return 1;
+}
+
+/* d2i_SSL_SESSION_get_string gets an optional ASN.1 OCTET STRING
+ * explicitly tagged with |tag| from |cbs| and stows it in |*out_ptr|
+ * and |*out_len|. If |*out_ptr| is not NULL, it frees the existing
+ * contents. On entry, if the element was not found, it sets
+ * |*out_ptr| to NULL. It returns one on success, whether or not the
+ * element was found, and zero on decode error. */
+static int d2i_SSL_SESSION_get_octet_string(CBS *cbs, uint8_t **out_ptr,
+ size_t *out_len, unsigned tag) {
+ CBS value;
+ if (!CBS_get_optional_asn1_octet_string(cbs, &value, NULL, tag)) {
+ OPENSSL_PUT_ERROR(SSL, d2i_SSL_SESSION, SSL_R_INVALID_SSL_SESSION);
+ return 0;
+ }
+ if (!CBS_stow(&value, out_ptr, out_len)) {
+ OPENSSL_PUT_ERROR(SSL, d2i_SSL_SESSION, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ return 1;
+}
+
+SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const uint8_t **pp, long length) {
+ SSL_SESSION *ret = NULL;
+ CBS cbs, session, cipher, session_id, master_key;
+ CBS peer, sid_ctx, peer_sha256, original_handshake_hash;
+ int has_peer, has_peer_sha256, extended_master_secret;
+ uint64_t version, ssl_version;
+ uint64_t session_time, timeout, verify_result, ticket_lifetime_hint;
+
+ if (a && *a) {
+ ret = *a;
+ } else {
+ ret = SSL_SESSION_new();
+ if (ret == NULL) {
+ goto err;
+ }
+ }
+
+ CBS_init(&cbs, *pp, length);
+ if (!CBS_get_asn1(&cbs, &session, CBS_ASN1_SEQUENCE) ||
+ !CBS_get_asn1_uint64(&session, &version) ||
+ !CBS_get_asn1_uint64(&session, &ssl_version) ||
+ !CBS_get_asn1(&session, &cipher, CBS_ASN1_OCTETSTRING) ||
+ !CBS_get_asn1(&session, &session_id, CBS_ASN1_OCTETSTRING) ||
+ !CBS_get_asn1(&session, &master_key, CBS_ASN1_OCTETSTRING) ||
+ !CBS_get_optional_asn1_uint64(&session, &session_time, kTimeTag,
+ time(NULL)) ||
+ !CBS_get_optional_asn1_uint64(&session, &timeout, kTimeoutTag, 3) ||
+ !CBS_get_optional_asn1(&session, &peer, &has_peer, kPeerTag) ||
+ !CBS_get_optional_asn1_octet_string(&session, &sid_ctx, NULL,
+ kSessionIDContextTag) ||
+ !CBS_get_optional_asn1_uint64(&session, &verify_result, kVerifyResultTag,
+ X509_V_OK)) {
+ OPENSSL_PUT_ERROR(SSL, d2i_SSL_SESSION, SSL_R_INVALID_SSL_SESSION);
+ goto err;
+ }
+ if (!d2i_SSL_SESSION_get_string(&session, &ret->tlsext_hostname,
+ kHostNameTag) ||
+ !d2i_SSL_SESSION_get_string(&session, &ret->psk_identity,
+ kPSKIdentityTag)) {
+ goto err;
+ }
+ if (!CBS_get_optional_asn1_uint64(&session, &ticket_lifetime_hint,
+ kTicketLifetimeHintTag, 0)) {
+ OPENSSL_PUT_ERROR(SSL, d2i_SSL_SESSION, SSL_R_INVALID_SSL_SESSION);
+ goto err;
+ }
+ if (!d2i_SSL_SESSION_get_octet_string(&session, &ret->tlsext_tick,
+ &ret->tlsext_ticklen, kTicketTag)) {
+ goto err;
+ }
+ if (!CBS_get_optional_asn1_octet_string(&session, &peer_sha256,
+ &has_peer_sha256, kPeerSHA256Tag) ||
+ !CBS_get_optional_asn1_octet_string(&session, &original_handshake_hash,
+ NULL, kOriginalHandshakeHashTag)) {
+ OPENSSL_PUT_ERROR(SSL, d2i_SSL_SESSION, SSL_R_INVALID_SSL_SESSION);
+ goto err;
+ }
+ if (!d2i_SSL_SESSION_get_octet_string(
+ &session, &ret->tlsext_signed_cert_timestamp_list,
+ &ret->tlsext_signed_cert_timestamp_list_length,
+ kSignedCertTimestampListTag) ||
+ !d2i_SSL_SESSION_get_octet_string(
+ &session, &ret->ocsp_response, &ret->ocsp_response_length,
+ kOCSPResponseTag)) {
+ goto err;
+ }
+ if (!CBS_get_optional_asn1_bool(&session, &extended_master_secret,
+ kExtendedMasterSecretTag,
+ 0 /* default to false */)) {
+ OPENSSL_PUT_ERROR(SSL, d2i_SSL_SESSION, SSL_R_INVALID_SSL_SESSION);
+ goto err;
+ }
+ ret->extended_master_secret = extended_master_secret;
+
+ /* Ignore |version|. The structure version number is ignored. */
+
+ /* Only support SSLv3/TLS and DTLS. */
+ if ((ssl_version >> 8) != SSL3_VERSION_MAJOR &&
+ (ssl_version >> 8) != (DTLS1_VERSION >> 8)) {
+ OPENSSL_PUT_ERROR(SSL, d2i_SSL_SESSION, SSL_R_UNKNOWN_SSL_VERSION);
+ goto err;
+ }
+ ret->ssl_version = ssl_version;
+
+ uint16_t cipher_value;
+ if (!CBS_get_u16(&cipher, &cipher_value) || CBS_len(&cipher) != 0) {
+ OPENSSL_PUT_ERROR(SSL, d2i_SSL_SESSION, SSL_R_CIPHER_CODE_WRONG_LENGTH);
+ goto err;
+ }
+ ret->cipher = ssl3_get_cipher_by_value(cipher_value);
+ if (ret->cipher == NULL) {
+ OPENSSL_PUT_ERROR(SSL, d2i_SSL_SESSION, SSL_R_UNSUPPORTED_CIPHER);
+ goto err;
+ }
+
+ if (CBS_len(&session_id) > SSL3_MAX_SSL_SESSION_ID_LENGTH) {
+ OPENSSL_PUT_ERROR(SSL, d2i_SSL_SESSION, SSL_R_INVALID_SSL_SESSION);
+ goto err;
+ }
+ memcpy(ret->session_id, CBS_data(&session_id), CBS_len(&session_id));
+ ret->session_id_length = CBS_len(&session_id);
+
+ if (CBS_len(&master_key) > SSL_MAX_MASTER_KEY_LENGTH) {
+ OPENSSL_PUT_ERROR(SSL, d2i_SSL_SESSION, SSL_R_INVALID_SSL_SESSION);
+ goto err;
+ }
+ memcpy(ret->master_key, CBS_data(&master_key), CBS_len(&master_key));
+ ret->master_key_length = CBS_len(&master_key);
+
+ if (session_time > LONG_MAX ||
+ timeout > LONG_MAX) {
+ OPENSSL_PUT_ERROR(SSL, d2i_SSL_SESSION, SSL_R_INVALID_SSL_SESSION);
+ goto err;
+ }
+ ret->time = session_time;
+ ret->timeout = timeout;
+
+ if (ret->peer != NULL) {
+ X509_free(ret->peer);
+ ret->peer = NULL;
+ }
+ if (has_peer) {
+ const uint8_t *ptr;
+ ptr = CBS_data(&peer);
+ ret->peer = d2i_X509(NULL, &ptr, CBS_len(&peer));
+ if (ret->peer == NULL) {
+ goto err;
+ }
+ if (ptr != CBS_data(&peer) + CBS_len(&peer)) {
+ OPENSSL_PUT_ERROR(SSL, d2i_SSL_SESSION, SSL_R_INVALID_SSL_SESSION);
+ goto err;
+ }
+ }
+
+ if (CBS_len(&sid_ctx) > sizeof(ret->sid_ctx)) {
+ OPENSSL_PUT_ERROR(SSL, d2i_SSL_SESSION, SSL_R_INVALID_SSL_SESSION);
+ goto err;
+ }
+ memcpy(ret->sid_ctx, CBS_data(&sid_ctx), CBS_len(&sid_ctx));
+ ret->sid_ctx_length = CBS_len(&sid_ctx);
+
+ if (verify_result > LONG_MAX ||
+ ticket_lifetime_hint > 0xffffffff) {
+ OPENSSL_PUT_ERROR(SSL, d2i_SSL_SESSION, SSL_R_INVALID_SSL_SESSION);
+ goto err;
+ }
+ ret->verify_result = verify_result;
+ ret->tlsext_tick_lifetime_hint = ticket_lifetime_hint;
+
+ if (has_peer_sha256) {
+ if (CBS_len(&peer_sha256) != sizeof(ret->peer_sha256)) {
+ OPENSSL_PUT_ERROR(SSL, d2i_SSL_SESSION, SSL_R_INVALID_SSL_SESSION);
+ goto err;
+ }
+ memcpy(ret->peer_sha256, CBS_data(&peer_sha256), sizeof(ret->peer_sha256));
+ ret->peer_sha256_valid = 1;
+ } else {
+ ret->peer_sha256_valid = 0;
+ }
+
+ if (CBS_len(&original_handshake_hash) >
+ sizeof(ret->original_handshake_hash)) {
+ OPENSSL_PUT_ERROR(SSL, d2i_SSL_SESSION, SSL_R_INVALID_SSL_SESSION);
+ goto err;
+ }
+ memcpy(ret->original_handshake_hash, CBS_data(&original_handshake_hash),
+ CBS_len(&original_handshake_hash));
+ ret->original_handshake_hash_len = CBS_len(&original_handshake_hash);
+
+ if (a) {
+ *a = ret;
+ }
+ *pp = CBS_data(&cbs);
+ return ret;
+
+err:
+ if (a && *a != ret) {
+ SSL_SESSION_free(ret);
+ }
+ return NULL;
+}
diff --git a/src/ssl/ssl_cert.c b/src/ssl/ssl_cert.c
new file mode 100644
index 0000000..624c41a
--- /dev/null
+++ b/src/ssl/ssl_cert.c
@@ -0,0 +1,1081 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <stdio.h>
+
+#include <openssl/bio.h>
+#include <openssl/bn.h>
+#include <openssl/buf.h>
+#include <openssl/dh.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/pem.h>
+#include <openssl/x509v3.h>
+
+#include "../crypto/dh/internal.h"
+#include "../crypto/directory.h"
+#include "ssl_locl.h"
+
+
+int SSL_get_ex_data_X509_STORE_CTX_idx(void) {
+ static 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;
+}
+
+CERT *ssl_cert_new(void) {
+ CERT *ret;
+
+ ret = (CERT *)OPENSSL_malloc(sizeof(CERT));
+ if (ret == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl_cert_new, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ memset(ret, 0, sizeof(CERT));
+
+ ret->key = &ret->pkeys[SSL_PKEY_RSA_ENC];
+ return ret;
+}
+
+CERT *ssl_cert_dup(CERT *cert) {
+ CERT *ret;
+ int i;
+
+ ret = (CERT *)OPENSSL_malloc(sizeof(CERT));
+ if (ret == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl_cert_dup, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ memset(ret, 0, sizeof(CERT));
+
+ ret->key = &ret->pkeys[cert->key - &cert->pkeys[0]];
+ /* or ret->key = ret->pkeys + (cert->key - cert->pkeys), if you find that
+ * more readable */
+
+ ret->mask_k = cert->mask_k;
+ ret->mask_a = cert->mask_a;
+
+ if (cert->dh_tmp != NULL) {
+ ret->dh_tmp = DHparams_dup(cert->dh_tmp);
+ if (ret->dh_tmp == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl_cert_dup, ERR_R_DH_LIB);
+ goto err;
+ }
+ if (cert->dh_tmp->priv_key) {
+ BIGNUM *b = BN_dup(cert->dh_tmp->priv_key);
+ if (!b) {
+ OPENSSL_PUT_ERROR(SSL, ssl_cert_dup, ERR_R_BN_LIB);
+ goto err;
+ }
+ ret->dh_tmp->priv_key = b;
+ }
+ if (cert->dh_tmp->pub_key) {
+ BIGNUM *b = BN_dup(cert->dh_tmp->pub_key);
+ if (!b) {
+ OPENSSL_PUT_ERROR(SSL, ssl_cert_dup, ERR_R_BN_LIB);
+ goto err;
+ }
+ ret->dh_tmp->pub_key = b;
+ }
+ }
+ ret->dh_tmp_cb = cert->dh_tmp_cb;
+
+ if (cert->ecdh_tmp) {
+ ret->ecdh_tmp = EC_KEY_dup(cert->ecdh_tmp);
+ if (ret->ecdh_tmp == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl_cert_dup, ERR_R_EC_LIB);
+ goto err;
+ }
+ }
+ ret->ecdh_tmp_cb = cert->ecdh_tmp_cb;
+ ret->ecdh_tmp_auto = cert->ecdh_tmp_auto;
+
+ for (i = 0; i < SSL_PKEY_NUM; i++) {
+ CERT_PKEY *cpk = cert->pkeys + i;
+ CERT_PKEY *rpk = ret->pkeys + i;
+ if (cpk->x509 != NULL) {
+ rpk->x509 = X509_up_ref(cpk->x509);
+ }
+
+ if (cpk->privatekey != NULL) {
+ rpk->privatekey = EVP_PKEY_dup(cpk->privatekey);
+ }
+
+ if (cpk->chain) {
+ rpk->chain = X509_chain_up_ref(cpk->chain);
+ if (!rpk->chain) {
+ OPENSSL_PUT_ERROR(SSL, ssl_cert_dup, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+ }
+
+ /* Peer sigalgs set to NULL as we get these from handshake too */
+ ret->peer_sigalgs = NULL;
+ ret->peer_sigalgslen = 0;
+ /* Configured sigalgs however we copy across */
+
+ if (cert->conf_sigalgs) {
+ ret->conf_sigalgs = OPENSSL_malloc(cert->conf_sigalgslen);
+ if (!ret->conf_sigalgs) {
+ goto err;
+ }
+ memcpy(ret->conf_sigalgs, cert->conf_sigalgs, cert->conf_sigalgslen);
+ ret->conf_sigalgslen = cert->conf_sigalgslen;
+ } else {
+ ret->conf_sigalgs = NULL;
+ }
+
+ if (cert->client_sigalgs) {
+ ret->client_sigalgs = OPENSSL_malloc(cert->client_sigalgslen);
+ if (!ret->client_sigalgs) {
+ goto err;
+ }
+ memcpy(ret->client_sigalgs, cert->client_sigalgs, cert->client_sigalgslen);
+ ret->client_sigalgslen = cert->client_sigalgslen;
+ } else {
+ ret->client_sigalgs = NULL;
+ }
+ /* Shared sigalgs also NULL */
+ ret->shared_sigalgs = NULL;
+ /* Copy any custom client certificate types */
+ if (cert->client_certificate_types) {
+ ret->client_certificate_types = BUF_memdup(
+ cert->client_certificate_types, cert->num_client_certificate_types);
+ if (!ret->client_certificate_types) {
+ goto err;
+ }
+ ret->num_client_certificate_types = cert->num_client_certificate_types;
+ }
+
+ ret->cert_flags = cert->cert_flags;
+
+ ret->cert_cb = cert->cert_cb;
+ ret->cert_cb_arg = cert->cert_cb_arg;
+
+ if (cert->verify_store) {
+ CRYPTO_add(&cert->verify_store->references, 1, CRYPTO_LOCK_X509_STORE);
+ ret->verify_store = cert->verify_store;
+ }
+
+ if (cert->chain_store) {
+ CRYPTO_add(&cert->chain_store->references, 1, CRYPTO_LOCK_X509_STORE);
+ ret->chain_store = cert->chain_store;
+ }
+
+ ret->ciphers_raw = NULL;
+
+ return ret;
+
+err:
+ ssl_cert_free(ret);
+ return NULL;
+}
+
+/* Free up and clear all certificates and chains */
+void ssl_cert_clear_certs(CERT *c) {
+ int i;
+ if (c == NULL) {
+ return;
+ }
+
+ for (i = 0; i < SSL_PKEY_NUM; i++) {
+ CERT_PKEY *cpk = c->pkeys + i;
+ if (cpk->x509) {
+ X509_free(cpk->x509);
+ cpk->x509 = NULL;
+ }
+ if (cpk->privatekey) {
+ EVP_PKEY_free(cpk->privatekey);
+ cpk->privatekey = NULL;
+ }
+ if (cpk->chain) {
+ sk_X509_pop_free(cpk->chain, X509_free);
+ cpk->chain = NULL;
+ }
+ }
+}
+
+void ssl_cert_free(CERT *c) {
+ if (c == NULL) {
+ return;
+ }
+
+ if (c->dh_tmp) {
+ DH_free(c->dh_tmp);
+ }
+ if (c->ecdh_tmp) {
+ EC_KEY_free(c->ecdh_tmp);
+ }
+
+ ssl_cert_clear_certs(c);
+ if (c->peer_sigalgs) {
+ OPENSSL_free(c->peer_sigalgs);
+ }
+ if (c->conf_sigalgs) {
+ OPENSSL_free(c->conf_sigalgs);
+ }
+ if (c->client_sigalgs) {
+ OPENSSL_free(c->client_sigalgs);
+ }
+ if (c->shared_sigalgs) {
+ OPENSSL_free(c->shared_sigalgs);
+ }
+ if (c->client_certificate_types) {
+ OPENSSL_free(c->client_certificate_types);
+ }
+ if (c->verify_store) {
+ X509_STORE_free(c->verify_store);
+ }
+ if (c->chain_store) {
+ X509_STORE_free(c->chain_store);
+ }
+ if (c->ciphers_raw) {
+ OPENSSL_free(c->ciphers_raw);
+ }
+
+ OPENSSL_free(c);
+}
+
+int ssl_cert_inst(CERT **o) {
+ /* Create a CERT if there isn't already one (which cannot really happen, as
+ * it is initially created in SSL_CTX_new; but the earlier code usually
+ * allows for that one being non-existant, so we follow that behaviour, as it
+ * might turn out that there actually is a reason for it -- but I'm not sure
+ * that *all* of the existing code could cope with s->cert being NULL,
+ * otherwise we could do without the initialization in SSL_CTX_new). */
+
+ if (o == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl_cert_inst, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ if (*o == NULL) {
+ *o = ssl_cert_new();
+ if (*o == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl_cert_new, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+int ssl_cert_set0_chain(CERT *c, STACK_OF(X509) * chain) {
+ CERT_PKEY *cpk = c->key;
+ if (!cpk) {
+ return 0;
+ }
+ if (cpk->chain) {
+ sk_X509_pop_free(cpk->chain, X509_free);
+ }
+ cpk->chain = chain;
+ return 1;
+}
+
+int ssl_cert_set1_chain(CERT *c, STACK_OF(X509) * chain) {
+ STACK_OF(X509) * dchain;
+ if (!chain) {
+ return ssl_cert_set0_chain(c, NULL);
+ }
+
+ dchain = X509_chain_up_ref(chain);
+ if (!dchain) {
+ return 0;
+ }
+
+ if (!ssl_cert_set0_chain(c, dchain)) {
+ sk_X509_pop_free(dchain, X509_free);
+ return 0;
+ }
+
+ return 1;
+}
+
+int ssl_cert_add0_chain_cert(CERT *c, X509 *x) {
+ CERT_PKEY *cpk = c->key;
+ if (!cpk) {
+ return 0;
+ }
+
+ if (!cpk->chain) {
+ cpk->chain = sk_X509_new_null();
+ }
+ if (!cpk->chain || !sk_X509_push(cpk->chain, x)) {
+ return 0;
+ }
+
+ return 1;
+}
+
+int ssl_cert_add1_chain_cert(CERT *c, X509 *x) {
+ if (!ssl_cert_add0_chain_cert(c, x)) {
+ return 0;
+ }
+
+ X509_up_ref(x);
+ return 1;
+}
+
+int ssl_cert_select_current(CERT *c, X509 *x) {
+ int i;
+ if (x == NULL) {
+ return 0;
+ }
+
+ for (i = 0; i < SSL_PKEY_NUM; i++) {
+ if (c->pkeys[i].x509 == x) {
+ c->key = &c->pkeys[i];
+ return 1;
+ }
+ }
+
+ for (i = 0; i < SSL_PKEY_NUM; i++) {
+ if (c->pkeys[i].x509 && !X509_cmp(c->pkeys[i].x509, x)) {
+ c->key = &c->pkeys[i];
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+void ssl_cert_set_cert_cb(CERT *c, int (*cb)(SSL *ssl, void *arg), void *arg) {
+ c->cert_cb = cb;
+ c->cert_cb_arg = arg;
+}
+
+SESS_CERT *ssl_sess_cert_new(void) {
+ SESS_CERT *ret;
+
+ ret = OPENSSL_malloc(sizeof *ret);
+ if (ret == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl_sess_cert_new, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ memset(ret, 0, sizeof *ret);
+ ret->peer_key = &(ret->peer_pkeys[SSL_PKEY_RSA_ENC]);
+
+ return ret;
+}
+
+void ssl_sess_cert_free(SESS_CERT *sc) {
+ int i;
+
+ if (sc == NULL) {
+ return;
+ }
+
+ if (sc->cert_chain != NULL) {
+ sk_X509_pop_free(sc->cert_chain, X509_free);
+ }
+
+ for (i = 0; i < SSL_PKEY_NUM; i++) {
+ if (sc->peer_pkeys[i].x509 != NULL) {
+ X509_free(sc->peer_pkeys[i].x509);
+ }
+ }
+
+ if (sc->peer_dh_tmp != NULL) {
+ DH_free(sc->peer_dh_tmp);
+ }
+ if (sc->peer_ecdh_tmp != NULL) {
+ EC_KEY_free(sc->peer_ecdh_tmp);
+ }
+
+ OPENSSL_free(sc);
+}
+
+int ssl_set_peer_cert_type(SESS_CERT *sc, int type) {
+ sc->peer_cert_type = type;
+ return 1;
+}
+
+int ssl_verify_cert_chain(SSL *s, STACK_OF(X509) * sk) {
+ X509 *x;
+ int i;
+ X509_STORE *verify_store;
+ X509_STORE_CTX ctx;
+
+ if (s->cert->verify_store) {
+ verify_store = s->cert->verify_store;
+ } else {
+ verify_store = s->ctx->cert_store;
+ }
+
+ if (sk == NULL || sk_X509_num(sk) == 0) {
+ return 0;
+ }
+
+ x = sk_X509_value(sk, 0);
+ if (!X509_STORE_CTX_init(&ctx, verify_store, x, sk)) {
+ OPENSSL_PUT_ERROR(SSL, ssl_verify_cert_chain, ERR_R_X509_LIB);
+ return 0;
+ }
+ 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");
+
+ /* Anything non-default in "param" should overwrite anything in the ctx. */
+ X509_VERIFY_PARAM_set1(X509_STORE_CTX_get0_param(&ctx), s->param);
+
+ if (s->verify_callback) {
+ X509_STORE_CTX_set_verify_cb(&ctx, s->verify_callback);
+ }
+
+ if (s->ctx->app_verify_callback != NULL) {
+ i = s->ctx->app_verify_callback(&ctx, s->ctx->app_verify_arg);
+ } else {
+ i = X509_verify_cert(&ctx);
+ }
+
+ s->verify_result = ctx.error;
+ X509_STORE_CTX_cleanup(&ctx);
+
+ return i;
+}
+
+static void set_client_CA_list(STACK_OF(X509_NAME) * *ca_list,
+ STACK_OF(X509_NAME) * name_list) {
+ if (*ca_list != NULL) {
+ sk_X509_NAME_pop_free(*ca_list, X509_NAME_free);
+ }
+
+ *ca_list = name_list;
+}
+
+STACK_OF(X509_NAME) * SSL_dup_CA_list(STACK_OF(X509_NAME) * sk) {
+ size_t i;
+ STACK_OF(X509_NAME) * ret;
+ X509_NAME *name;
+
+ ret = sk_X509_NAME_new_null();
+ for (i = 0; i < sk_X509_NAME_num(sk); i++) {
+ name = X509_NAME_dup(sk_X509_NAME_value(sk, i));
+ if (name == NULL || !sk_X509_NAME_push(ret, name)) {
+ sk_X509_NAME_pop_free(ret, X509_NAME_free);
+ return NULL;
+ }
+ }
+
+ return ret;
+}
+
+void SSL_set_client_CA_list(SSL *s, STACK_OF(X509_NAME) * name_list) {
+ set_client_CA_list(&(s->client_CA), name_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);
+}
+
+STACK_OF(X509_NAME) * SSL_CTX_get_client_CA_list(const SSL_CTX *ctx) {
+ return ctx->client_CA;
+}
+
+STACK_OF(X509_NAME) * SSL_get_client_CA_list(const SSL *s) {
+ if (s->server) {
+ if (s->client_CA != NULL) {
+ return s->client_CA;
+ } else {
+ return s->ctx->client_CA;
+ }
+ } else {
+ if ((s->version >> 8) == SSL3_VERSION_MAJOR && s->s3 != NULL) {
+ return s->s3->tmp.ca_names;
+ } else {
+ return NULL;
+ }
+ }
+}
+
+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();
+ if (*sk == NULL) {
+ return 0;
+ }
+ }
+
+ name = X509_NAME_dup(X509_get_subject_name(x));
+ if (name == 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);
+}
+
+int SSL_CTX_add_client_CA(SSL_CTX *ctx, X509 *x) {
+ return add_client_CA(&(ctx->client_CA), x);
+}
+
+static int xname_cmp(const X509_NAME **a, const X509_NAME **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) {
+ OPENSSL_PUT_ERROR(SSL, SSL_load_client_CA_file, 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) {
+ OPENSSL_PUT_ERROR(SSL, SSL_load_client_CA_file, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+ xn = X509_get_subject_name(x);
+ if (xn == NULL) {
+ goto err;
+ }
+
+ /* check for duplicates */
+ xn = X509_NAME_dup(xn);
+ if (xn == NULL) {
+ goto err;
+ }
+ if (sk_X509_NAME_find(sk, NULL, xn)) {
+ X509_NAME_free(xn);
+ } else {
+ sk_X509_NAME_push(sk, xn);
+ sk_X509_NAME_push(ret, xn);
+ }
+ }
+
+ if (0) {
+ err:
+ if (ret != NULL) {
+ sk_X509_NAME_pop_free(ret, X509_NAME_free);
+ }
+ ret = NULL;
+ }
+
+ if (sk != NULL) {
+ sk_X509_NAME_free(sk);
+ }
+ if (in != NULL) {
+ BIO_free(in);
+ }
+ if (x != NULL) {
+ X509_free(x);
+ }
+ if (ret != NULL) {
+ ERR_clear_error();
+ }
+ return ret;
+}
+
+/* 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 **a, const X509_NAME **b);
+
+ oldcmp = sk_X509_NAME_set_cmp_func(stack, xname_cmp);
+ in = BIO_new(BIO_s_file());
+
+ if (in == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_add_file_cert_subjects_to_stack,
+ 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;
+ }
+ xn = X509_get_subject_name(x);
+ if (xn == NULL) {
+ goto err;
+ }
+ xn = X509_NAME_dup(xn);
+ if (xn == NULL) {
+ goto err;
+ }
+ if (sk_X509_NAME_find(stack, NULL, xn)) {
+ X509_NAME_free(xn);
+ } else {
+ sk_X509_NAME_push(stack, xn);
+ }
+ }
+
+ ERR_clear_error();
+
+ if (0) {
+ err:
+ ret = 0;
+ }
+
+ if (in != NULL) {
+ BIO_free(in);
+ }
+ if (x != NULL) {
+ X509_free(x);
+ }
+
+ (void) sk_X509_NAME_set_cmp_func(stack, oldcmp);
+
+ return ret;
+}
+
+/* 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) {
+ OPENSSL_DIR_CTX *d = NULL;
+ const char *filename;
+ int ret = 0;
+
+ CRYPTO_w_lock(CRYPTO_LOCK_READDIR);
+
+ /* Note that a side effect is that the CAs will be sorted by name */
+ while ((filename = OPENSSL_DIR_read(&d, dir))) {
+ char buf[1024];
+ int r;
+
+ if (strlen(dir) + strlen(filename) + 2 > sizeof(buf)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_add_dir_cert_subjects_to_stack,
+ SSL_R_PATH_TOO_LONG);
+ goto err;
+ }
+
+ r = BIO_snprintf(buf, sizeof buf, "%s/%s", dir, filename);
+ if (r <= 0 || r >= (int)sizeof(buf) ||
+ !SSL_add_file_cert_subjects_to_stack(stack, buf)) {
+ goto err;
+ }
+ }
+
+ if (errno) {
+ OPENSSL_PUT_ERROR(SSL, SSL_add_file_cert_subjects_to_stack, ERR_R_SYS_LIB);
+ ERR_add_error_data(3, "OPENSSL_DIR_read(&ctx, '", dir, "')");
+ goto err;
+ }
+
+ ret = 1;
+
+err:
+ if (d) {
+ OPENSSL_DIR_end(&d);
+ }
+ CRYPTO_w_unlock(CRYPTO_LOCK_READDIR);
+ return ret;
+}
+
+/* Add a certificate to a BUF_MEM structure */
+static int ssl_add_cert_to_buf(BUF_MEM *buf, unsigned long *l, X509 *x) {
+ int n;
+ uint8_t *p;
+
+ n = i2d_X509(x, NULL);
+ if (!BUF_MEM_grow_clean(buf, (int)(n + (*l) + 3))) {
+ OPENSSL_PUT_ERROR(SSL, ssl_add_cert_to_buf, ERR_R_BUF_LIB);
+ return 0;
+ }
+ p = (uint8_t *)&(buf->data[*l]);
+ l2n3(n, p);
+ i2d_X509(x, &p);
+ *l += n + 3;
+
+ return 1;
+}
+
+/* Add certificate chain to internal SSL BUF_MEM structure. */
+int ssl_add_cert_chain(SSL *s, CERT_PKEY *cpk, unsigned long *l) {
+ BUF_MEM *buf = s->init_buf;
+ int no_chain = 0;
+ size_t i;
+
+ X509 *x = NULL;
+ STACK_OF(X509) * extra_certs;
+ X509_STORE *chain_store;
+
+ if (cpk) {
+ x = cpk->x509;
+ }
+
+ if (s->cert->chain_store) {
+ chain_store = s->cert->chain_store;
+ } else {
+ chain_store = s->ctx->cert_store;
+ }
+
+ /* If we have a certificate specific chain use it, else use parent ctx. */
+ if (cpk && cpk->chain) {
+ extra_certs = cpk->chain;
+ } else {
+ extra_certs = s->ctx->extra_certs;
+ }
+
+ if ((s->mode & SSL_MODE_NO_AUTO_CHAIN) || extra_certs) {
+ no_chain = 1;
+ }
+
+ /* TLSv1 sends a chain with nothing in it, instead of an alert. */
+ if (!BUF_MEM_grow_clean(buf, 10)) {
+ OPENSSL_PUT_ERROR(SSL, ssl_add_cert_chain, ERR_R_BUF_LIB);
+ return 0;
+ }
+
+ if (x != NULL) {
+ if (no_chain) {
+ if (!ssl_add_cert_to_buf(buf, l, x)) {
+ return 0;
+ }
+ } else {
+ X509_STORE_CTX xs_ctx;
+
+ if (!X509_STORE_CTX_init(&xs_ctx, chain_store, x, NULL)) {
+ OPENSSL_PUT_ERROR(SSL, ssl_add_cert_chain, ERR_R_X509_LIB);
+ return 0;
+ }
+ X509_verify_cert(&xs_ctx);
+ /* Don't leave errors in the queue */
+ ERR_clear_error();
+ for (i = 0; i < sk_X509_num(xs_ctx.chain); i++) {
+ x = sk_X509_value(xs_ctx.chain, i);
+
+ if (!ssl_add_cert_to_buf(buf, l, x)) {
+ X509_STORE_CTX_cleanup(&xs_ctx);
+ return 0;
+ }
+ }
+ X509_STORE_CTX_cleanup(&xs_ctx);
+ }
+ }
+
+ for (i = 0; i < sk_X509_num(extra_certs); i++) {
+ x = sk_X509_value(extra_certs, i);
+ if (!ssl_add_cert_to_buf(buf, l, x)) {
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+/* Build a certificate chain for current certificate */
+int ssl_build_cert_chain(CERT *c, X509_STORE *chain_store, int flags) {
+ CERT_PKEY *cpk = c->key;
+ X509_STORE_CTX xs_ctx;
+ STACK_OF(X509) *chain = NULL, *untrusted = NULL;
+ X509 *x;
+ int i, rv = 0;
+ unsigned long error;
+
+ if (!cpk->x509) {
+ OPENSSL_PUT_ERROR(SSL, ssl_build_cert_chain, SSL_R_NO_CERTIFICATE_SET);
+ goto err;
+ }
+
+ /* Rearranging and check the chain: add everything to a store */
+ if (flags & SSL_BUILD_CHAIN_FLAG_CHECK) {
+ size_t j;
+ chain_store = X509_STORE_new();
+ if (!chain_store) {
+ goto err;
+ }
+
+ for (j = 0; j < sk_X509_num(cpk->chain); j++) {
+ x = sk_X509_value(cpk->chain, j);
+ if (!X509_STORE_add_cert(chain_store, x)) {
+ error = ERR_peek_last_error();
+ if (ERR_GET_LIB(error) != ERR_LIB_X509 ||
+ ERR_GET_REASON(error) != X509_R_CERT_ALREADY_IN_HASH_TABLE) {
+ goto err;
+ }
+ ERR_clear_error();
+ }
+ }
+
+ /* Add EE cert too: it might be self signed */
+ if (!X509_STORE_add_cert(chain_store, cpk->x509)) {
+ error = ERR_peek_last_error();
+ if (ERR_GET_LIB(error) != ERR_LIB_X509 ||
+ ERR_GET_REASON(error) != X509_R_CERT_ALREADY_IN_HASH_TABLE) {
+ goto err;
+ }
+ ERR_clear_error();
+ }
+ } else {
+ if (c->chain_store) {
+ chain_store = c->chain_store;
+ }
+
+ if (flags & SSL_BUILD_CHAIN_FLAG_UNTRUSTED) {
+ untrusted = cpk->chain;
+ }
+ }
+
+ if (!X509_STORE_CTX_init(&xs_ctx, chain_store, cpk->x509, untrusted)) {
+ OPENSSL_PUT_ERROR(SSL, ssl_build_cert_chain, ERR_R_X509_LIB);
+ goto err;
+ }
+
+ i = X509_verify_cert(&xs_ctx);
+ if (i <= 0 && flags & SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR) {
+ if (flags & SSL_BUILD_CHAIN_FLAG_CLEAR_ERROR) {
+ ERR_clear_error();
+ }
+ i = 1;
+ rv = 2;
+ }
+
+ if (i > 0) {
+ chain = X509_STORE_CTX_get1_chain(&xs_ctx);
+ }
+ if (i <= 0) {
+ OPENSSL_PUT_ERROR(SSL, ssl_build_cert_chain,
+ SSL_R_CERTIFICATE_VERIFY_FAILED);
+ i = X509_STORE_CTX_get_error(&xs_ctx);
+ ERR_add_error_data(2, "Verify error:", X509_verify_cert_error_string(i));
+
+ X509_STORE_CTX_cleanup(&xs_ctx);
+ goto err;
+ }
+
+ X509_STORE_CTX_cleanup(&xs_ctx);
+ if (cpk->chain) {
+ sk_X509_pop_free(cpk->chain, X509_free);
+ }
+
+ /* Remove EE certificate from chain */
+ x = sk_X509_shift(chain);
+ X509_free(x);
+ if (flags & SSL_BUILD_CHAIN_FLAG_NO_ROOT) {
+ if (sk_X509_num(chain) > 0) {
+ /* See if last cert is self signed */
+ x = sk_X509_value(chain, sk_X509_num(chain) - 1);
+ X509_check_purpose(x, -1, 0);
+ if (x->ex_flags & EXFLAG_SS) {
+ x = sk_X509_pop(chain);
+ X509_free(x);
+ }
+ }
+ }
+
+ cpk->chain = chain;
+ if (rv == 0)
+ rv = 1;
+
+err:
+ if (flags & SSL_BUILD_CHAIN_FLAG_CHECK) {
+ X509_STORE_free(chain_store);
+ }
+
+ return rv;
+}
+
+int ssl_cert_set_cert_store(CERT *c, X509_STORE *store, int chain, int ref) {
+ X509_STORE **pstore;
+ if (chain) {
+ pstore = &c->chain_store;
+ } else {
+ pstore = &c->verify_store;
+ }
+
+ if (*pstore) {
+ X509_STORE_free(*pstore);
+ }
+ *pstore = store;
+
+ if (ref && store) {
+ CRYPTO_add(&store->references, 1, CRYPTO_LOCK_X509_STORE);
+ }
+ return 1;
+}
diff --git a/src/ssl/ssl_ciph.c b/src/ssl/ssl_ciph.c
new file mode 100644
index 0000000..60b9747
--- /dev/null
+++ b/src/ssl/ssl_ciph.c
@@ -0,0 +1,1421 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <stdio.h>
+#include <assert.h>
+
+#include <openssl/engine.h>
+#include <openssl/md5.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/sha.h>
+
+#include "ssl_locl.h"
+
+
+struct handshake_digest {
+ long mask;
+ const EVP_MD *(*md_func)(void);
+};
+
+static const struct handshake_digest ssl_handshake_digests[SSL_MAX_DIGEST] = {
+ {SSL_HANDSHAKE_MAC_MD5, EVP_md5},
+ {SSL_HANDSHAKE_MAC_SHA, EVP_sha1},
+ {SSL_HANDSHAKE_MAC_SHA256, EVP_sha256},
+ {SSL_HANDSHAKE_MAC_SHA384, EVP_sha384},
+};
+
+#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;
+ int in_group;
+ struct cipher_order_st *next, *prev;
+} CIPHER_ORDER;
+
+static const SSL_CIPHER cipher_aliases[] =
+ {
+ {0, SSL_TXT_ALL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+
+ /* "COMPLEMENTOFDEFAULT" (does *not* include ciphersuites not found in
+ ALL!) */
+ {0, SSL_TXT_CMPDEF, 0, SSL_kEDH | SSL_kEECDH, SSL_aNULL, 0, 0, 0, 0, 0, 0,
+ 0},
+
+ /* 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) */
+ {0, SSL_TXT_kRSA, 0, SSL_kRSA, 0, 0, 0, 0, 0, 0, 0, 0},
+
+ {0, SSL_TXT_kEDH, 0, SSL_kEDH, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, SSL_TXT_DH, 0, SSL_kEDH, 0, 0, 0, 0, 0, 0, 0, 0},
+
+ {0, SSL_TXT_kEECDH, 0, SSL_kEECDH, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, SSL_TXT_ECDH, 0, SSL_kEECDH, 0, 0, 0, 0, 0, 0, 0, 0},
+
+ {0, SSL_TXT_kPSK, 0, SSL_kPSK, 0, 0, 0, 0, 0, 0, 0, 0},
+
+ /* server authentication aliases */
+ {0, SSL_TXT_aRSA, 0, 0, SSL_aRSA, 0, 0, 0, 0, 0, 0, 0},
+ {0, SSL_TXT_aNULL, 0, 0, SSL_aNULL, 0, 0, 0, 0, 0, 0, 0},
+ {0, SSL_TXT_aECDSA, 0, 0, SSL_aECDSA, 0, 0, 0, 0, 0, 0, 0},
+ {0, SSL_TXT_ECDSA, 0, 0, SSL_aECDSA, 0, 0, 0, 0, 0, 0, 0},
+ {0, SSL_TXT_aPSK, 0, 0, SSL_aPSK, 0, 0, 0, 0, 0, 0, 0},
+
+ /* aliases combining key exchange and server authentication */
+ {0, SSL_TXT_EDH, 0, SSL_kEDH, ~SSL_aNULL, 0, 0, 0, 0, 0, 0, 0},
+ {0, SSL_TXT_EECDH, 0, SSL_kEECDH, ~SSL_aNULL, 0, 0, 0, 0, 0, 0, 0},
+ {0, SSL_TXT_RSA, 0, SSL_kRSA, SSL_aRSA, 0, 0, 0, 0, 0, 0, 0},
+ {0, SSL_TXT_ADH, 0, SSL_kEDH, SSL_aNULL, 0, 0, 0, 0, 0, 0, 0},
+ {0, SSL_TXT_AECDH, 0, SSL_kEECDH, SSL_aNULL, 0, 0, 0, 0, 0, 0, 0},
+ {0, SSL_TXT_PSK, 0, SSL_kPSK, SSL_aPSK, 0, 0, 0, 0, 0, 0, 0},
+
+ /* symmetric encryption aliases */
+ {0, SSL_TXT_3DES, 0, 0, 0, SSL_3DES, 0, 0, 0, 0, 0, 0},
+ {0, SSL_TXT_RC4, 0, 0, 0, SSL_RC4, 0, 0, 0, 0, 0, 0},
+ {0, SSL_TXT_AES128, 0, 0, 0, SSL_AES128 | SSL_AES128GCM, 0, 0, 0, 0, 0, 0},
+ {0, SSL_TXT_AES256, 0, 0, 0, SSL_AES256 | SSL_AES256GCM, 0, 0, 0, 0, 0, 0},
+ {0, SSL_TXT_AES, 0, 0, 0, SSL_AES, 0, 0, 0, 0, 0, 0},
+ {0, SSL_TXT_AES_GCM, 0, 0, 0, SSL_AES128GCM | SSL_AES256GCM, 0, 0, 0, 0, 0,
+ 0},
+ {0, SSL_TXT_CHACHA20, 0, 0, 0, SSL_CHACHA20POLY1305, 0, 0, 0, 0, 0, 0},
+
+ /* MAC aliases */
+ {0, SSL_TXT_MD5, 0, 0, 0, 0, SSL_MD5, 0, 0, 0, 0, 0},
+ {0, SSL_TXT_SHA1, 0, 0, 0, 0, SSL_SHA1, 0, 0, 0, 0, 0},
+ {0, SSL_TXT_SHA, 0, 0, 0, 0, SSL_SHA1, 0, 0, 0, 0, 0},
+ {0, SSL_TXT_SHA256, 0, 0, 0, 0, SSL_SHA256, 0, 0, 0, 0, 0},
+ {0, SSL_TXT_SHA384, 0, 0, 0, 0, SSL_SHA384, 0, 0, 0, 0, 0},
+
+ /* protocol version aliases */
+ {0, SSL_TXT_SSLV3, 0, 0, 0, 0, 0, SSL_SSLV3, 0, 0, 0, 0},
+ {0, SSL_TXT_TLSV1, 0, 0, 0, 0, 0, SSL_TLSV1, 0, 0, 0, 0},
+ {0, SSL_TXT_TLSV1_2, 0, 0, 0, 0, 0, SSL_TLSV1_2, 0, 0, 0, 0},
+
+ /* strength classes */
+ {0, SSL_TXT_MEDIUM, 0, 0, 0, 0, 0, 0, SSL_MEDIUM, 0, 0, 0},
+ {0, SSL_TXT_HIGH, 0, 0, 0, 0, 0, 0, SSL_HIGH, 0, 0, 0},
+ /* FIPS 140-2 approved ciphersuite */
+ {0, SSL_TXT_FIPS, 0, 0, 0, 0, 0, 0, SSL_FIPS, 0, 0, 0},
+};
+
+int ssl_cipher_get_evp_aead(const EVP_AEAD **out_aead,
+ size_t *out_mac_secret_len,
+ size_t *out_fixed_iv_len,
+ const SSL_CIPHER *cipher, uint16_t version) {
+ *out_aead = NULL;
+ *out_mac_secret_len = 0;
+ *out_fixed_iv_len = 0;
+
+ switch (cipher->algorithm_enc) {
+ case SSL_AES128GCM:
+ *out_aead = EVP_aead_aes_128_gcm();
+ *out_fixed_iv_len = 4;
+ return 1;
+
+ case SSL_AES256GCM:
+ *out_aead = EVP_aead_aes_256_gcm();
+ *out_fixed_iv_len = 4;
+ return 1;
+
+ case SSL_CHACHA20POLY1305:
+ *out_aead = EVP_aead_chacha20_poly1305();
+ *out_fixed_iv_len = 0;
+ return 1;
+
+ case SSL_RC4:
+ switch (cipher->algorithm_mac) {
+ case SSL_MD5:
+ if (version == SSL3_VERSION) {
+ *out_aead = EVP_aead_rc4_md5_ssl3();
+ } else {
+ *out_aead = EVP_aead_rc4_md5_tls();
+ }
+ *out_mac_secret_len = MD5_DIGEST_LENGTH;
+ return 1;
+ case SSL_SHA1:
+ if (version == SSL3_VERSION) {
+ *out_aead = EVP_aead_rc4_sha1_ssl3();
+ } else {
+ *out_aead = EVP_aead_rc4_sha1_tls();
+ }
+ *out_mac_secret_len = SHA_DIGEST_LENGTH;
+ return 1;
+ default:
+ return 0;
+ }
+
+ case SSL_AES128:
+ switch (cipher->algorithm_mac) {
+ case SSL_SHA1:
+ if (version == SSL3_VERSION) {
+ *out_aead = EVP_aead_aes_128_cbc_sha1_ssl3();
+ *out_fixed_iv_len = 16;
+ } else if (version == TLS1_VERSION) {
+ *out_aead = EVP_aead_aes_128_cbc_sha1_tls_implicit_iv();
+ *out_fixed_iv_len = 16;
+ } else {
+ *out_aead = EVP_aead_aes_128_cbc_sha1_tls();
+ }
+ *out_mac_secret_len = SHA_DIGEST_LENGTH;
+ return 1;
+ case SSL_SHA256:
+ *out_aead = EVP_aead_aes_128_cbc_sha256_tls();
+ *out_mac_secret_len = SHA256_DIGEST_LENGTH;
+ return 1;
+ default:
+ return 0;
+ }
+
+ case SSL_AES256:
+ switch (cipher->algorithm_mac) {
+ case SSL_SHA1:
+ if (version == SSL3_VERSION) {
+ *out_aead = EVP_aead_aes_256_cbc_sha1_ssl3();
+ *out_fixed_iv_len = 16;
+ } else if (version == TLS1_VERSION) {
+ *out_aead = EVP_aead_aes_256_cbc_sha1_tls_implicit_iv();
+ *out_fixed_iv_len = 16;
+ } else {
+ *out_aead = EVP_aead_aes_256_cbc_sha1_tls();
+ }
+ *out_mac_secret_len = SHA_DIGEST_LENGTH;
+ return 1;
+ case SSL_SHA256:
+ *out_aead = EVP_aead_aes_256_cbc_sha256_tls();
+ *out_mac_secret_len = SHA256_DIGEST_LENGTH;
+ return 1;
+ case SSL_SHA384:
+ *out_aead = EVP_aead_aes_256_cbc_sha384_tls();
+ *out_mac_secret_len = SHA384_DIGEST_LENGTH;
+ return 1;
+ default:
+ return 0;
+ }
+
+ case SSL_3DES:
+ switch (cipher->algorithm_mac) {
+ case SSL_SHA1:
+ if (version == SSL3_VERSION) {
+ *out_aead = EVP_aead_des_ede3_cbc_sha1_ssl3();
+ *out_fixed_iv_len = 8;
+ } else if (version == TLS1_VERSION) {
+ *out_aead = EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv();
+ *out_fixed_iv_len = 8;
+ } else {
+ *out_aead = EVP_aead_des_ede3_cbc_sha1_tls();
+ }
+ *out_mac_secret_len = SHA_DIGEST_LENGTH;
+ return 1;
+ default:
+ return 0;
+ }
+
+ default:
+ return 0;
+ }
+}
+
+int ssl_get_handshake_digest(size_t idx, long *mask, const EVP_MD **md) {
+ if (idx >= SSL_MAX_DIGEST) {
+ return 0;
+ }
+ *mask = ssl_handshake_digests[idx].mask;
+ *md = ssl_handshake_digests[idx].md_func();
+ return 1;
+}
+
+#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_collect_ciphers(const SSL_PROTOCOL_METHOD *ssl_method,
+ int num_of_ciphers,
+ 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 (SSLv2 and/or 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 those that use any of that is not available */
+ if (c != NULL && c->valid) {
+ 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[co_list_num].in_group = 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,
+ CIPHER_ORDER *head) {
+ CIPHER_ORDER *ciph_curr;
+ const SSL_CIPHER **ca_curr;
+ int i;
+
+ /* 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++) {
+ *ca_curr = 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, int in_group,
+ 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) {
+ /* needed to maintain sorting between currently deleted ciphers */
+ reverse = 1;
+ }
+
+ 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;
+ if (curr == NULL) {
+ break;
+ }
+
+ next = reverse ? curr->prev : curr->next;
+ cp = curr->cipher;
+
+ /* 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)) ||
+ (alg_auth && !(alg_auth & cp->algorithm_auth)) ||
+ (alg_enc && !(alg_enc & cp->algorithm_enc)) ||
+ (alg_mac && !(alg_mac & cp->algorithm_mac)) ||
+ (alg_ssl && !(alg_ssl & cp->algorithm_ssl)) ||
+ (algo_strength && !(algo_strength & 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;
+ curr->in_group = in_group;
+ }
+ }
+
+ /* Move the added cipher to this location */
+ else if (rule == CIPHER_ORD) {
+ /* reverse == 0 */
+ if (curr->active) {
+ ll_append_tail(&head, curr, &tail);
+ curr->in_group = 0;
+ }
+ } 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;
+ curr->in_group = 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 = OPENSSL_malloc((max_strength_bits + 1) * sizeof(int));
+ if (!number_uses) {
+ OPENSSL_PUT_ERROR(SSL, ssl_cipher_strength_sort, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ memset(number_uses, 0, (max_strength_bits + 1) * sizeof(int));
+
+ /* 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, 0, head_p,
+ tail_p);
+ }
+ }
+
+ OPENSSL_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) {
+ unsigned long alg_mkey, alg_auth, alg_enc, alg_mac, alg_ssl, algo_strength;
+ const char *l, *buf;
+ int j, multi, found, rule, retval, ok, buflen, in_group = 0, has_group = 0;
+ unsigned long cipher_id = 0;
+ char ch;
+
+ retval = 1;
+ l = rule_str;
+ for (;;) {
+ ch = *l;
+
+ if (ch == '\0') {
+ break; /* done */
+ }
+
+ if (in_group) {
+ if (ch == ']') {
+ if (!in_group) {
+ OPENSSL_PUT_ERROR(SSL, ssl_cipher_process_rulestr,
+ SSL_R_UNEXPECTED_GROUP_CLOSE);
+ retval = found = in_group = 0;
+ break;
+ }
+ if (*tail_p) {
+ (*tail_p)->in_group = 0;
+ }
+ in_group = 0;
+ l++;
+ continue;
+ }
+
+ if (ch == '|') {
+ rule = CIPHER_ADD;
+ l++;
+ continue;
+ } else if (!(ch >= 'a' && ch <= 'z') && !(ch >= 'A' && ch <= 'Z') &&
+ !(ch >= '0' && ch <= '9')) {
+ OPENSSL_PUT_ERROR(SSL, ssl_cipher_process_rulestr,
+ SSL_R_UNEXPECTED_OPERATOR_IN_GROUP);
+ retval = found = in_group = 0;
+ break;
+ } else {
+ rule = CIPHER_ADD;
+ }
+ } else 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 if (ch == '[') {
+ if (in_group) {
+ OPENSSL_PUT_ERROR(SSL, ssl_cipher_process_rulestr, SSL_R_NESTED_GROUP);
+ retval = found = in_group = 0;
+ break;
+ }
+ in_group = 1;
+ has_group = 1;
+ l++;
+ continue;
+ } else {
+ rule = CIPHER_ADD;
+ }
+
+ /* If preference groups are enabled, the only legal operator is +.
+ * Otherwise the in_group bits will get mixed up. */
+ if (has_group && rule != CIPHER_ADD) {
+ OPENSSL_PUT_ERROR(SSL, ssl_cipher_process_rulestr,
+ SSL_R_MIXED_SPECIAL_OPERATOR_WITH_GROUPS);
+ retval = found = in_group = 0;
+ break;
+ }
+
+ 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 = *(++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. */
+ OPENSSL_PUT_ERROR(SSL, ssl_cipher_process_rulestr,
+ SSL_R_INVALID_COMMAND);
+ retval = found = in_group = 0;
+ l++;
+ break;
+ }
+
+ if (rule == CIPHER_SPECIAL) {
+ found = 0; /* unused -- avoid compiler warning */
+ break; /* special treatment */
+ }
+
+ /* 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) {
+ if (algo_strength) {
+ algo_strength &= ca_list[j]->algo_strength;
+ if (!algo_strength) {
+ found = 0;
+ break;
+ }
+ } else {
+ algo_strength |= ca_list[j]->algo_strength;
+ }
+ }
+
+ 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;
+ } 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)) {
+ ok = ssl_cipher_strength_sort(head_p, tail_p);
+ } else {
+ OPENSSL_PUT_ERROR(SSL, ssl_cipher_process_rulestr,
+ SSL_R_INVALID_COMMAND);
+ }
+
+ if (ok == 0) {
+ retval = 0;
+ }
+
+ /* We do not support any "multi" options together with "@", so throw away
+ * the rest of the command, if any left, until end or ':' is found. */
+ while (*l != '\0' && !ITEM_SEP(*l)) {
+ l++;
+ }
+ } else if (found) {
+ ssl_cipher_apply_rule(cipher_id, alg_mkey, alg_auth, alg_enc, alg_mac,
+ alg_ssl, algo_strength, rule, -1, in_group, head_p,
+ tail_p);
+ } else {
+ while (*l != '\0' && !ITEM_SEP(*l)) {
+ l++;
+ }
+ }
+ }
+
+ if (in_group) {
+ OPENSSL_PUT_ERROR(SSL, ssl_cipher_process_rulestr, SSL_R_INVALID_COMMAND);
+ retval = 0;
+ }
+
+ return retval;
+}
+
+STACK_OF(SSL_CIPHER) *
+ssl_create_cipher_list(const SSL_PROTOCOL_METHOD *ssl_method,
+ struct ssl_cipher_preference_list_st **cipher_list,
+ STACK_OF(SSL_CIPHER) * *cipher_list_by_id,
+ const char *rule_str, CERT *c) {
+ int ok, num_of_ciphers, num_of_alias_max, num_of_group_aliases;
+ STACK_OF(SSL_CIPHER) *cipherstack = NULL, *tmp_cipher_list = NULL;
+ const char *rule_p;
+ CIPHER_ORDER *co_list = NULL, *head = NULL, *tail = NULL, *curr;
+ const SSL_CIPHER **ca_list = NULL;
+ uint8_t *in_group_flags = NULL;
+ unsigned int num_in_group_flags = 0;
+ struct ssl_cipher_preference_list_st *pref_list = NULL;
+
+ /* Return with error if nothing to do. */
+ if (rule_str == NULL || cipher_list == NULL) {
+ return NULL;
+ }
+
+ /* 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 = ssl_method->num_ciphers();
+ co_list =
+ (CIPHER_ORDER *)OPENSSL_malloc(sizeof(CIPHER_ORDER) * num_of_ciphers);
+ if (co_list == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl_create_cipher_list, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ ssl_cipher_collect_ciphers(ssl_method, num_of_ciphers, co_list, &head, &tail);
+
+ /* Now arrange all ciphers by preference:
+ * TODO(davidben): Compute this order once and copy it. */
+
+ /* Everything else being equal, prefer ECDHE_ECDSA then ECDHE_RSA over other
+ * key exchange mechanisms */
+ ssl_cipher_apply_rule(0, SSL_kEECDH, SSL_aECDSA, 0, 0, 0, 0, CIPHER_ADD, -1,
+ 0, &head, &tail);
+ ssl_cipher_apply_rule(0, SSL_kEECDH, 0, 0, 0, 0, 0, CIPHER_ADD, -1, 0, &head,
+ &tail);
+ ssl_cipher_apply_rule(0, SSL_kEECDH, 0, 0, 0, 0, 0, CIPHER_DEL, -1, 0, &head,
+ &tail);
+
+ /* Order the bulk ciphers. First the preferred AEAD ciphers. We prefer
+ * CHACHA20 unless there is hardware support for fast and constant-time
+ * AES_GCM. */
+ if (EVP_has_aes_hardware()) {
+ ssl_cipher_apply_rule(0, 0, 0, SSL_AES256GCM, 0, 0, 0, CIPHER_ADD, -1, 0,
+ &head, &tail);
+ ssl_cipher_apply_rule(0, 0, 0, SSL_AES128GCM, 0, 0, 0, CIPHER_ADD, -1, 0,
+ &head, &tail);
+ ssl_cipher_apply_rule(0, 0, 0, SSL_CHACHA20POLY1305, 0, 0, 0, CIPHER_ADD,
+ -1, 0, &head, &tail);
+ } else {
+ ssl_cipher_apply_rule(0, 0, 0, SSL_CHACHA20POLY1305, 0, 0, 0, CIPHER_ADD,
+ -1, 0, &head, &tail);
+ ssl_cipher_apply_rule(0, 0, 0, SSL_AES256GCM, 0, 0, 0, CIPHER_ADD, -1, 0,
+ &head, &tail);
+ ssl_cipher_apply_rule(0, 0, 0, SSL_AES128GCM, 0, 0, 0, CIPHER_ADD, -1, 0,
+ &head, &tail);
+ }
+
+ /* Then the legacy non-AEAD ciphers: AES_256_CBC, AES-128_CBC, RC4_128_SHA,
+ * RC4_128_MD5, 3DES_EDE_CBC_SHA. */
+ ssl_cipher_apply_rule(0, 0, 0, SSL_AES256, 0, 0, 0, CIPHER_ADD, -1, 0, &head,
+ &tail);
+ ssl_cipher_apply_rule(0, 0, 0, SSL_AES128, 0, 0, 0, CIPHER_ADD, -1, 0, &head,
+ &tail);
+ ssl_cipher_apply_rule(0, 0, 0, SSL_RC4, ~SSL_MD5, 0, 0, CIPHER_ADD, -1, 0,
+ &head, &tail);
+ ssl_cipher_apply_rule(0, 0, 0, SSL_RC4, SSL_MD5, 0, 0, CIPHER_ADD, -1, 0,
+ &head, &tail);
+ ssl_cipher_apply_rule(0, 0, 0, SSL_3DES, 0, 0, 0, CIPHER_ADD, -1, 0, &head,
+ &tail);
+
+ /* Temporarily enable everything else for sorting */
+ ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_ADD, -1, 0, &head, &tail);
+
+ /* Move ciphers without forward secrecy to the end. */
+ ssl_cipher_apply_rule(0, ~(SSL_kEDH | SSL_kEECDH), 0, 0, 0, 0, 0, CIPHER_ORD,
+ -1, 0, &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.)
+ * TODO(davidben): Remove them altogether? */
+ ssl_cipher_apply_rule(0, 0, SSL_aNULL, 0, 0, 0, 0, CIPHER_ORD, -1, 0, &head,
+ &tail);
+
+ /* Now disable everything (maintaining the ordering!) */
+ ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_DEL, -1, 0, &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 = OPENSSL_malloc(sizeof(SSL_CIPHER *) * num_of_alias_max);
+ if (ca_list == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl_create_cipher_list, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ ssl_cipher_collect_aliases(ca_list, num_of_group_aliases, 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);
+ 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);
+ }
+
+ OPENSSL_free((void *)ca_list); /* Not needed anymore */
+
+ if (!ok) {
+ goto err;
+ }
+
+ /* Allocate new "cipherstack" for the result, return with error
+ * if we cannot get one. */
+ cipherstack = sk_SSL_CIPHER_new_null();
+ if (cipherstack == NULL) {
+ goto err;
+ }
+
+ in_group_flags = OPENSSL_malloc(num_of_ciphers);
+ if (!in_group_flags) {
+ goto err;
+ }
+
+ /* The cipher selection for the list is done. The ciphers are added
+ * to the resulting precedence to the STACK_OF(SSL_CIPHER). */
+ for (curr = head; curr != NULL; curr = curr->next) {
+ if (curr->active) {
+ if (!sk_SSL_CIPHER_push(cipherstack, curr->cipher)) {
+ goto err;
+ }
+ in_group_flags[num_in_group_flags++] = curr->in_group;
+ }
+ }
+ OPENSSL_free(co_list); /* Not needed any longer */
+ co_list = NULL;
+
+ tmp_cipher_list = sk_SSL_CIPHER_dup(cipherstack);
+ if (tmp_cipher_list == NULL) {
+ goto err;
+ }
+ pref_list = OPENSSL_malloc(sizeof(struct ssl_cipher_preference_list_st));
+ if (!pref_list) {
+ goto err;
+ }
+ pref_list->ciphers = cipherstack;
+ pref_list->in_group_flags = OPENSSL_malloc(num_in_group_flags);
+ if (!pref_list->in_group_flags) {
+ goto err;
+ }
+ memcpy(pref_list->in_group_flags, in_group_flags, num_in_group_flags);
+ OPENSSL_free(in_group_flags);
+ in_group_flags = NULL;
+ if (*cipher_list != NULL) {
+ ssl_cipher_preference_list_free(*cipher_list);
+ }
+ *cipher_list = pref_list;
+ pref_list = NULL;
+
+ if (cipher_list_by_id != NULL) {
+ if (*cipher_list_by_id != NULL) {
+ sk_SSL_CIPHER_free(*cipher_list_by_id);
+ }
+ *cipher_list_by_id = tmp_cipher_list;
+ tmp_cipher_list = NULL;
+ (void) sk_SSL_CIPHER_set_cmp_func(*cipher_list_by_id, ssl_cipher_ptr_id_cmp);
+
+ sk_SSL_CIPHER_sort(*cipher_list_by_id);
+ } else {
+ sk_SSL_CIPHER_free(tmp_cipher_list);
+ tmp_cipher_list = NULL;
+ }
+
+ return cipherstack;
+
+err:
+ if (co_list) {
+ OPENSSL_free(co_list);
+ }
+ if (in_group_flags) {
+ OPENSSL_free(in_group_flags);
+ }
+ if (cipherstack) {
+ sk_SSL_CIPHER_free(cipherstack);
+ }
+ if (tmp_cipher_list) {
+ sk_SSL_CIPHER_free(tmp_cipher_list);
+ }
+ if (pref_list && pref_list->in_group_flags) {
+ OPENSSL_free(pref_list->in_group_flags);
+ }
+ if (pref_list) {
+ OPENSSL_free(pref_list);
+ }
+ return NULL;
+}
+
+const char *SSL_CIPHER_description(const SSL_CIPHER *cipher, char *buf,
+ int len) {
+ const char *ver;
+ const char *kx, *au, *enc, *mac;
+ unsigned long alg_mkey, alg_auth, alg_enc, alg_mac, alg_ssl;
+ static const char *format = "%-23s %s Kx=%-8s Au=%-4s Enc=%-9s Mac=%-4s\n";
+
+ 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;
+
+ if (alg_ssl & SSL_SSLV3) {
+ ver = "SSLv3";
+ } else if (alg_ssl & SSL_TLSV1_2) {
+ ver = "TLSv1.2";
+ } else {
+ ver = "unknown";
+ }
+
+ switch (alg_mkey) {
+ case SSL_kRSA:
+ kx = "RSA";
+ break;
+
+ case SSL_kEDH:
+ kx = "DH";
+ break;
+
+ case SSL_kEECDH:
+ kx = "ECDH";
+ break;
+
+ case SSL_kPSK:
+ kx = "PSK";
+ break;
+
+ default:
+ kx = "unknown";
+ }
+
+ switch (alg_auth) {
+ case SSL_aRSA:
+ au = "RSA";
+ break;
+
+ case SSL_aNULL:
+ au = "None";
+ break;
+
+ case SSL_aECDSA:
+ au = "ECDSA";
+ break;
+
+ case SSL_aPSK:
+ au = "PSK";
+ break;
+
+ default:
+ au = "unknown";
+ break;
+ }
+
+ switch (alg_enc) {
+ case SSL_3DES:
+ enc = "3DES(168)";
+ break;
+
+ case SSL_RC4:
+ enc = "RC4(128)";
+ 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_CHACHA20POLY1305:
+ enc = "ChaCha20-Poly1305";
+ 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;
+
+ default:
+ mac = "unknown";
+ break;
+ }
+
+ if (buf == NULL) {
+ len = 128;
+ buf = OPENSSL_malloc(len);
+ if (buf == NULL)
+ return "OPENSSL_malloc Error";
+ } else if (len < 128) {
+ return "Buffer too small";
+ }
+
+ BIO_snprintf(buf, len, format, cipher->name, ver, kx, au, enc, mac);
+ return buf;
+}
+
+int SSL_CIPHER_is_AES(const SSL_CIPHER *c) {
+ return (c->algorithm_enc & SSL_AES) != 0;
+}
+
+int SSL_CIPHER_has_MD5_HMAC(const SSL_CIPHER *c) {
+ return (c->algorithm_mac & SSL_MD5) != 0;
+}
+
+int SSL_CIPHER_is_AESGCM(const SSL_CIPHER *c) {
+ return (c->algorithm_mac & (SSL_AES128GCM | SSL_AES256GCM)) != 0;
+}
+
+int SSL_CIPHER_is_CHACHA20POLY1305(const SSL_CIPHER *c) {
+ return (c->algorithm_enc & SSL_CHACHA20POLY1305) != 0;
+}
+
+const char *SSL_CIPHER_get_version(const SSL_CIPHER *c) {
+ int i;
+
+ if (c == NULL) {
+ return "(NONE)";
+ }
+
+ i = (int)(c->id >> 24L);
+ if (i == 3) {
+ return "TLSv1/SSLv3";
+ } else if (i == 2) {
+ return "SSLv2";
+ } else {
+ return "unknown";
+ }
+}
+
+/* return the actual cipher being used */
+const char *SSL_CIPHER_get_name(const SSL_CIPHER *c) {
+ if (c != NULL) {
+ return c->name;
+ }
+
+ return "(NONE)";
+}
+
+const char *SSL_CIPHER_get_kx_name(const SSL_CIPHER *cipher) {
+ if (cipher == NULL) {
+ return "";
+ }
+
+ switch (cipher->algorithm_mkey) {
+ case SSL_kRSA:
+ return SSL_TXT_RSA;
+
+ case SSL_kEDH:
+ switch (cipher->algorithm_auth) {
+ case SSL_aRSA:
+ return "DHE_" SSL_TXT_RSA;
+ case SSL_aNULL:
+ return SSL_TXT_DH "_anon";
+ default:
+ return "UNKNOWN";
+ }
+
+ case SSL_kEECDH:
+ switch (cipher->algorithm_auth) {
+ case SSL_aECDSA:
+ return "ECDHE_" SSL_TXT_ECDSA;
+ case SSL_aRSA:
+ return "ECDHE_" SSL_TXT_RSA;
+ case SSL_aNULL:
+ return SSL_TXT_ECDH "_anon";
+ default:
+ return "UNKNOWN";
+ }
+
+ default:
+ return "UNKNOWN";
+ }
+}
+
+/* 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;
+}
+
+unsigned long SSL_CIPHER_get_id(const SSL_CIPHER *c) { return c->id; }
+
+void *SSL_COMP_get_compression_methods(void) { return NULL; }
+
+int SSL_COMP_add_compression_method(int id, void *cm) { return 1; }
+
+const char *SSL_COMP_get_name(const void *comp) { return NULL; }
+
+/* For a cipher return the index corresponding to the certificate type */
+int ssl_cipher_get_cert_index(const SSL_CIPHER *c) {
+ unsigned long alg_a = c->algorithm_auth;
+
+ if (alg_a & SSL_aECDSA) {
+ return SSL_PKEY_ECC;
+ } else if (alg_a & SSL_aRSA) {
+ return SSL_PKEY_RSA_ENC;
+ }
+
+ return -1;
+}
+
+/* ssl_cipher_has_server_public_key returns 1 if |cipher| involves a server
+ * public key in the key exchange, sent in a server Certificate message.
+ * Otherwise it returns 0. */
+int ssl_cipher_has_server_public_key(const SSL_CIPHER *cipher) {
+ /* Anonymous ciphers do not include a server certificate. */
+ if (cipher->algorithm_auth & SSL_aNULL) {
+ return 0;
+ }
+
+ /* Neither do PSK ciphers, except for RSA_PSK. */
+ if ((cipher->algorithm_auth & SSL_aPSK) &&
+ !(cipher->algorithm_mkey & SSL_kRSA)) {
+ return 0;
+ }
+
+ /* All other ciphers include it. */
+ return 1;
+}
+
+/* ssl_cipher_requires_server_key_exchange returns 1 if |cipher| requires a
+ * ServerKeyExchange message. Otherwise it returns 0.
+ *
+ * Unlike ssl_cipher_has_server_public_key, some ciphers take optional
+ * ServerKeyExchanges. PSK and RSA_PSK only use the ServerKeyExchange to
+ * communicate a psk_identity_hint, so it is optional. */
+int ssl_cipher_requires_server_key_exchange(const SSL_CIPHER *cipher) {
+ /* Ephemeral Diffie-Hellman key exchanges require a ServerKeyExchange. */
+ if (cipher->algorithm_mkey & SSL_kEDH || cipher->algorithm_mkey & SSL_kEECDH) {
+ return 1;
+ }
+
+ /* It is optional in all others. */
+ return 0;
+}
diff --git a/src/ssl/ssl_error.c b/src/ssl/ssl_error.c
new file mode 100644
index 0000000..2ffb9e6
--- /dev/null
+++ b/src/ssl/ssl_error.c
@@ -0,0 +1,566 @@
+/* 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 <openssl/err.h>
+
+#include <openssl/ssl.h>
+
+const ERR_STRING_DATA SSL_error_string_data[] = {
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_D2I_SSL_SESSION, 0), "D2I_SSL_SESSION"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_check_private_key, 0), "SSL_CTX_check_private_key"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_new, 0), "SSL_CTX_new"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_set_cipher_list, 0), "SSL_CTX_set_cipher_list"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_set_cipher_list_tls11, 0), "SSL_CTX_set_cipher_list_tls11"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_set_session_id_context, 0), "SSL_CTX_set_session_id_context"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_set_ssl_version, 0), "SSL_CTX_set_ssl_version"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_use_PrivateKey, 0), "SSL_CTX_use_PrivateKey"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_use_PrivateKey_ASN1, 0), "SSL_CTX_use_PrivateKey_ASN1"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_use_PrivateKey_file, 0), "SSL_CTX_use_PrivateKey_file"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_use_RSAPrivateKey, 0), "SSL_CTX_use_RSAPrivateKey"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_use_RSAPrivateKey_ASN1, 0), "SSL_CTX_use_RSAPrivateKey_ASN1"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_use_RSAPrivateKey_file, 0), "SSL_CTX_use_RSAPrivateKey_file"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_use_authz, 0), "SSL_CTX_use_authz"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_use_certificate, 0), "SSL_CTX_use_certificate"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_use_certificate_ASN1, 0), "SSL_CTX_use_certificate_ASN1"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_use_certificate_chain_file, 0), "SSL_CTX_use_certificate_chain_file"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_use_certificate_file, 0), "SSL_CTX_use_certificate_file"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_use_psk_identity_hint, 0), "SSL_CTX_use_psk_identity_hint"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SESSION_new, 0), "SSL_SESSION_new"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SESSION_print_fp, 0), "SSL_SESSION_print_fp"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SESSION_set1_id_context, 0), "SSL_SESSION_set1_id_context"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SESSION_to_bytes_full, 0), "SSL_SESSION_to_bytes_full"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_accept, 0), "SSL_accept"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_add_dir_cert_subjects_to_stack, 0), "SSL_add_dir_cert_subjects_to_stack"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_add_file_cert_subjects_to_stack, 0), "SSL_add_file_cert_subjects_to_stack"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_check_private_key, 0), "SSL_check_private_key"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_clear, 0), "SSL_clear"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_connect, 0), "SSL_connect"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_do_handshake, 0), "SSL_do_handshake"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_load_client_CA_file, 0), "SSL_load_client_CA_file"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_new, 0), "SSL_new"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_peek, 0), "SSL_peek"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_read, 0), "SSL_read"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_set_cipher_list, 0), "SSL_set_cipher_list"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_set_fd, 0), "SSL_set_fd"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_set_rfd, 0), "SSL_set_rfd"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_set_session, 0), "SSL_set_session"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_set_session_id_context, 0), "SSL_set_session_id_context"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_set_session_ticket_ext, 0), "SSL_set_session_ticket_ext"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_set_wfd, 0), "SSL_set_wfd"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_shutdown, 0), "SSL_shutdown"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_use_PrivateKey, 0), "SSL_use_PrivateKey"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_use_PrivateKey_ASN1, 0), "SSL_use_PrivateKey_ASN1"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_use_PrivateKey_file, 0), "SSL_use_PrivateKey_file"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_use_RSAPrivateKey, 0), "SSL_use_RSAPrivateKey"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_use_RSAPrivateKey_ASN1, 0), "SSL_use_RSAPrivateKey_ASN1"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_use_RSAPrivateKey_file, 0), "SSL_use_RSAPrivateKey_file"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_use_authz, 0), "SSL_use_authz"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_use_certificate, 0), "SSL_use_certificate"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_use_certificate_ASN1, 0), "SSL_use_certificate_ASN1"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_use_certificate_file, 0), "SSL_use_certificate_file"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_use_psk_identity_hint, 0), "SSL_use_psk_identity_hint"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_write, 0), "SSL_write"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_authz_find_data, 0), "authz_find_data"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_check_suiteb_cipher_list, 0), "check_suiteb_cipher_list"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_d2i_SSL_SESSION, 0), "d2i_SSL_SESSION"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_d2i_SSL_SESSION_get_octet_string, 0), "d2i_SSL_SESSION_get_octet_string"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_d2i_SSL_SESSION_get_string, 0), "d2i_SSL_SESSION_get_string"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_do_dtls1_write, 0), "do_dtls1_write"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_do_ssl3_write, 0), "do_ssl3_write"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_dtls1_accept, 0), "dtls1_accept"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_dtls1_buffer_record, 0), "dtls1_buffer_record"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_dtls1_check_timeout_num, 0), "dtls1_check_timeout_num"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_dtls1_connect, 0), "dtls1_connect"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_dtls1_do_write, 0), "dtls1_do_write"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_dtls1_get_hello_verify, 0), "dtls1_get_hello_verify"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_dtls1_get_message, 0), "dtls1_get_message"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_dtls1_get_message_fragment, 0), "dtls1_get_message_fragment"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_dtls1_heartbeat, 0), "dtls1_heartbeat"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_dtls1_preprocess_fragment, 0), "dtls1_preprocess_fragment"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_dtls1_process_record, 0), "dtls1_process_record"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_dtls1_read_bytes, 0), "dtls1_read_bytes"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_dtls1_send_hello_verify_request, 0), "dtls1_send_hello_verify_request"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_dtls1_write_app_data_bytes, 0), "dtls1_write_app_data_bytes"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_fclose, 0), "fclose"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_fprintf, 0), "fprintf"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_i2d_SSL_SESSION, 0), "i2d_SSL_SESSION"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_printf, 0), "printf"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_read_authz, 0), "read_authz"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl23_accept, 0), "ssl23_accept"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl23_client_hello, 0), "ssl23_client_hello"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl23_connect, 0), "ssl23_connect"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl23_get_client_hello, 0), "ssl23_get_client_hello"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl23_get_server_hello, 0), "ssl23_get_server_hello"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl23_get_v2_client_hello, 0), "ssl23_get_v2_client_hello"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl23_peek, 0), "ssl23_peek"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl23_read, 0), "ssl23_read"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl23_write, 0), "ssl23_write"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_accept, 0), "ssl3_accept"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_callback_ctrl, 0), "ssl3_callback_ctrl"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_cert_verify_hash, 0), "ssl3_cert_verify_hash"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_change_cipher_state, 0), "ssl3_change_cipher_state"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_check_cert_and_algorithm, 0), "ssl3_check_cert_and_algorithm"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_check_client_hello, 0), "ssl3_check_client_hello"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_connect, 0), "ssl3_connect"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_ctrl, 0), "ssl3_ctrl"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_ctx_ctrl, 0), "ssl3_ctx_ctrl"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_digest_cached_records, 0), "ssl3_digest_cached_records"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_do_change_cipher_spec, 0), "ssl3_do_change_cipher_spec"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_expect_change_cipher_spec, 0), "ssl3_expect_change_cipher_spec"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_generate_key_block, 0), "ssl3_generate_key_block"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_get_cert_status, 0), "ssl3_get_cert_status"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_get_cert_verify, 0), "ssl3_get_cert_verify"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_get_certificate_request, 0), "ssl3_get_certificate_request"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_get_channel_id, 0), "ssl3_get_channel_id"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_get_client_certificate, 0), "ssl3_get_client_certificate"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_get_client_hello, 0), "ssl3_get_client_hello"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_get_client_key_exchange, 0), "ssl3_get_client_key_exchange"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_get_finished, 0), "ssl3_get_finished"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_get_initial_bytes, 0), "ssl3_get_initial_bytes"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_get_message, 0), "ssl3_get_message"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_get_new_session_ticket, 0), "ssl3_get_new_session_ticket"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_get_next_proto, 0), "ssl3_get_next_proto"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_get_record, 0), "ssl3_get_record"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_get_server_certificate, 0), "ssl3_get_server_certificate"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_get_server_done, 0), "ssl3_get_server_done"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_get_server_hello, 0), "ssl3_get_server_hello"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_get_server_key_exchange, 0), "ssl3_get_server_key_exchange"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_get_v2_client_hello, 0), "ssl3_get_v2_client_hello"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_handshake_mac, 0), "ssl3_handshake_mac"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_prf, 0), "ssl3_prf"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_read_bytes, 0), "ssl3_read_bytes"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_read_n, 0), "ssl3_read_n"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_send_cert_verify, 0), "ssl3_send_cert_verify"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_send_certificate_request, 0), "ssl3_send_certificate_request"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_send_channel_id, 0), "ssl3_send_channel_id"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_send_client_certificate, 0), "ssl3_send_client_certificate"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_send_client_hello, 0), "ssl3_send_client_hello"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_send_client_key_exchange, 0), "ssl3_send_client_key_exchange"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_send_new_session_ticket, 0), "ssl3_send_new_session_ticket"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_send_server_certificate, 0), "ssl3_send_server_certificate"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_send_server_hello, 0), "ssl3_send_server_hello"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_send_server_key_exchange, 0), "ssl3_send_server_key_exchange"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_setup_key_block, 0), "ssl3_setup_key_block"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_setup_read_buffer, 0), "ssl3_setup_read_buffer"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_setup_write_buffer, 0), "ssl3_setup_write_buffer"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_write_bytes, 0), "ssl3_write_bytes"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_write_pending, 0), "ssl3_write_pending"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_add_cert_chain, 0), "ssl_add_cert_chain"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_add_cert_to_buf, 0), "ssl_add_cert_to_buf"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_add_clienthello_renegotiate_ext, 0), "ssl_add_clienthello_renegotiate_ext"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_add_clienthello_tlsext, 0), "ssl_add_clienthello_tlsext"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_add_clienthello_use_srtp_ext, 0), "ssl_add_clienthello_use_srtp_ext"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_add_serverhello_renegotiate_ext, 0), "ssl_add_serverhello_renegotiate_ext"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_add_serverhello_tlsext, 0), "ssl_add_serverhello_tlsext"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_add_serverhello_use_srtp_ext, 0), "ssl_add_serverhello_use_srtp_ext"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_bad_method, 0), "ssl_bad_method"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_build_cert_chain, 0), "ssl_build_cert_chain"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_bytes_to_cipher_list, 0), "ssl_bytes_to_cipher_list"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_cert_dup, 0), "ssl_cert_dup"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_cert_inst, 0), "ssl_cert_inst"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_cert_new, 0), "ssl_cert_new"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_check_serverhello_tlsext, 0), "ssl_check_serverhello_tlsext"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_check_srvr_ecc_cert_and_alg, 0), "ssl_check_srvr_ecc_cert_and_alg"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_cipher_process_rulestr, 0), "ssl_cipher_process_rulestr"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_cipher_strength_sort, 0), "ssl_cipher_strength_sort"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_create_cipher_list, 0), "ssl_create_cipher_list"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_ctx_log_master_secret, 0), "ssl_ctx_log_master_secret"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_ctx_log_rsa_client_key_exchange, 0), "ssl_ctx_log_rsa_client_key_exchange"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_ctx_make_profiles, 0), "ssl_ctx_make_profiles"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_get_new_session, 0), "ssl_get_new_session"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_get_prev_session, 0), "ssl_get_prev_session"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_get_server_cert_index, 0), "ssl_get_server_cert_index"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_get_sign_pkey, 0), "ssl_get_sign_pkey"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_init_wbio_buffer, 0), "ssl_init_wbio_buffer"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_new, 0), "ssl_new"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_parse_clienthello_renegotiate_ext, 0), "ssl_parse_clienthello_renegotiate_ext"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_parse_clienthello_tlsext, 0), "ssl_parse_clienthello_tlsext"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_parse_clienthello_use_srtp_ext, 0), "ssl_parse_clienthello_use_srtp_ext"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_parse_serverhello_renegotiate_ext, 0), "ssl_parse_serverhello_renegotiate_ext"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_parse_serverhello_tlsext, 0), "ssl_parse_serverhello_tlsext"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_parse_serverhello_use_srtp_ext, 0), "ssl_parse_serverhello_use_srtp_ext"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_prepare_clienthello_tlsext, 0), "ssl_prepare_clienthello_tlsext"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_scan_clienthello_tlsext, 0), "ssl_scan_clienthello_tlsext"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_scan_serverhello_tlsext, 0), "ssl_scan_serverhello_tlsext"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_sess_cert_new, 0), "ssl_sess_cert_new"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_set_authz, 0), "ssl_set_authz"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_set_cert, 0), "ssl_set_cert"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_set_pkey, 0), "ssl_set_pkey"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_undefined_const_function, 0), "ssl_undefined_const_function"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_undefined_function, 0), "ssl_undefined_function"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_undefined_void_function, 0), "ssl_undefined_void_function"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_verify_cert_chain, 0), "ssl_verify_cert_chain"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_tls12_check_peer_sigalg, 0), "tls12_check_peer_sigalg"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_tls1_aead_ctx_init, 0), "tls1_aead_ctx_init"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_tls1_cert_verify_mac, 0), "tls1_cert_verify_mac"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_tls1_change_cipher_state, 0), "tls1_change_cipher_state"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_tls1_change_cipher_state_aead, 0), "tls1_change_cipher_state_aead"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_tls1_change_cipher_state_cipher, 0), "tls1_change_cipher_state_cipher"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_tls1_check_duplicate_extensions, 0), "tls1_check_duplicate_extensions"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_tls1_enc, 0), "tls1_enc"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_tls1_export_keying_material, 0), "tls1_export_keying_material"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_tls1_get_server_supplemental_data, 0), "tls1_get_server_supplemental_data"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_tls1_heartbeat, 0), "tls1_heartbeat"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_tls1_prf, 0), "tls1_prf"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_tls1_send_server_supplemental_data, 0), "tls1_send_server_supplemental_data"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_tls1_setup_key_block, 0), "tls1_setup_key_block"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_APP_DATA_IN_HANDSHAKE), "APP_DATA_IN_HANDSHAKE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT), "ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_AUTHZ_DATA_TOO_LARGE), "AUTHZ_DATA_TOO_LARGE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_ALERT), "BAD_ALERT"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_ALERT_RECORD), "BAD_ALERT_RECORD"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_AUTHENTICATION_TYPE), "BAD_AUTHENTICATION_TYPE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_CHANGE_CIPHER_SPEC), "BAD_CHANGE_CIPHER_SPEC"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_CHECKSUM), "BAD_CHECKSUM"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_DATA), "BAD_DATA"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_DATA_RETURNED_BY_CALLBACK), "BAD_DATA_RETURNED_BY_CALLBACK"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_DECOMPRESSION), "BAD_DECOMPRESSION"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_DH_G_LENGTH), "BAD_DH_G_LENGTH"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_DH_PUB_KEY_LENGTH), "BAD_DH_PUB_KEY_LENGTH"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_DH_P_LENGTH), "BAD_DH_P_LENGTH"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_DIGEST_LENGTH), "BAD_DIGEST_LENGTH"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_DSA_SIGNATURE), "BAD_DSA_SIGNATURE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_ECC_CERT), "BAD_ECC_CERT"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_ECDSA_SIGNATURE), "BAD_ECDSA_SIGNATURE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_ECPOINT), "BAD_ECPOINT"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_HANDSHAKE_LENGTH), "BAD_HANDSHAKE_LENGTH"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_HELLO_REQUEST), "BAD_HELLO_REQUEST"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_LENGTH), "BAD_LENGTH"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_MAC_DECODE), "BAD_MAC_DECODE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_MAC_LENGTH), "BAD_MAC_LENGTH"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_MESSAGE_TYPE), "BAD_MESSAGE_TYPE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_PACKET_LENGTH), "BAD_PACKET_LENGTH"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_PROTOCOL_VERSION_NUMBER), "BAD_PROTOCOL_VERSION_NUMBER"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_PSK_IDENTITY_HINT_LENGTH), "BAD_PSK_IDENTITY_HINT_LENGTH"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_RESPONSE_ARGUMENT), "BAD_RESPONSE_ARGUMENT"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_RSA_DECRYPT), "BAD_RSA_DECRYPT"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_RSA_ENCRYPT), "BAD_RSA_ENCRYPT"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_RSA_E_LENGTH), "BAD_RSA_E_LENGTH"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_RSA_MODULUS_LENGTH), "BAD_RSA_MODULUS_LENGTH"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_RSA_SIGNATURE), "BAD_RSA_SIGNATURE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_SIGNATURE), "BAD_SIGNATURE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_SRP_A_LENGTH), "BAD_SRP_A_LENGTH"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_SRP_B_LENGTH), "BAD_SRP_B_LENGTH"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_SRP_G_LENGTH), "BAD_SRP_G_LENGTH"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_SRP_N_LENGTH), "BAD_SRP_N_LENGTH"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_SRP_S_LENGTH), "BAD_SRP_S_LENGTH"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_SRTP_MKI_VALUE), "BAD_SRTP_MKI_VALUE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST), "BAD_SRTP_PROTECTION_PROFILE_LIST"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_SSL_FILETYPE), "BAD_SSL_FILETYPE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_SSL_SESSION_ID_LENGTH), "BAD_SSL_SESSION_ID_LENGTH"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_STATE), "BAD_STATE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_VALUE), "BAD_VALUE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_WRITE_RETRY), "BAD_WRITE_RETRY"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BIO_NOT_SET), "BIO_NOT_SET"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BLOCK_CIPHER_PAD_IS_WRONG), "BLOCK_CIPHER_PAD_IS_WRONG"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BN_LIB), "BN_LIB"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CANNOT_SERIALIZE_PUBLIC_KEY), "CANNOT_SERIALIZE_PUBLIC_KEY"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CA_DN_LENGTH_MISMATCH), "CA_DN_LENGTH_MISMATCH"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CA_DN_TOO_LONG), "CA_DN_TOO_LONG"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CCS_RECEIVED_EARLY), "CCS_RECEIVED_EARLY"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CERTIFICATE_VERIFY_FAILED), "CERTIFICATE_VERIFY_FAILED"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CERT_CB_ERROR), "CERT_CB_ERROR"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CERT_LENGTH_MISMATCH), "CERT_LENGTH_MISMATCH"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CHALLENGE_IS_DIFFERENT), "CHALLENGE_IS_DIFFERENT"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CHANNEL_ID_NOT_P256), "CHANNEL_ID_NOT_P256"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CHANNEL_ID_SIGNATURE_INVALID), "CHANNEL_ID_SIGNATURE_INVALID"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CIPHER_CODE_WRONG_LENGTH), "CIPHER_CODE_WRONG_LENGTH"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CIPHER_OR_HASH_UNAVAILABLE), "CIPHER_OR_HASH_UNAVAILABLE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CIPHER_TABLE_SRC_ERROR), "CIPHER_TABLE_SRC_ERROR"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CLIENTHELLO_PARSE_FAILED), "CLIENTHELLO_PARSE_FAILED"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CLIENTHELLO_TLSEXT), "CLIENTHELLO_TLSEXT"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_COMPRESSED_LENGTH_TOO_LONG), "COMPRESSED_LENGTH_TOO_LONG"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_COMPRESSION_DISABLED), "COMPRESSION_DISABLED"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_COMPRESSION_FAILURE), "COMPRESSION_FAILURE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE), "COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_COMPRESSION_LIBRARY_ERROR), "COMPRESSION_LIBRARY_ERROR"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CONNECTION_ID_IS_DIFFERENT), "CONNECTION_ID_IS_DIFFERENT"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CONNECTION_REJECTED), "CONNECTION_REJECTED"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CONNECTION_TYPE_NOT_SET), "CONNECTION_TYPE_NOT_SET"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_COOKIE_MISMATCH), "COOKIE_MISMATCH"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_D2I_ECDSA_SIG), "D2I_ECDSA_SIG"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_DATA_BETWEEN_CCS_AND_FINISHED), "DATA_BETWEEN_CCS_AND_FINISHED"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_DATA_LENGTH_TOO_LONG), "DATA_LENGTH_TOO_LONG"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_DECODE_ERROR), "DECODE_ERROR"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_DECRYPTION_FAILED), "DECRYPTION_FAILED"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC), "DECRYPTION_FAILED_OR_BAD_RECORD_MAC"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG), "DH_PUBLIC_VALUE_LENGTH_IS_WRONG"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_DIGEST_CHECK_FAILED), "DIGEST_CHECK_FAILED"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_DTLS_MESSAGE_TOO_BIG), "DTLS_MESSAGE_TOO_BIG"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_DUPLICATE_COMPRESSION_ID), "DUPLICATE_COMPRESSION_ID"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_ECC_CERT_NOT_FOR_KEY_AGREEMENT), "ECC_CERT_NOT_FOR_KEY_AGREEMENT"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_ECC_CERT_NOT_FOR_SIGNING), "ECC_CERT_NOT_FOR_SIGNING"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_ECC_CERT_SHOULD_HAVE_RSA_SIGNATURE), "ECC_CERT_SHOULD_HAVE_RSA_SIGNATURE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_ECC_CERT_SHOULD_HAVE_SHA1_SIGNATURE), "ECC_CERT_SHOULD_HAVE_SHA1_SIGNATURE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER), "ECGROUP_TOO_LARGE_FOR_CIPHER"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_EMPTY_SRTP_PROTECTION_PROFILE_LIST), "EMPTY_SRTP_PROTECTION_PROFILE_LIST"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_ENCRYPTED_LENGTH_TOO_LONG), "ENCRYPTED_LENGTH_TOO_LONG"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_ERROR_GENERATING_TMP_RSA_KEY), "ERROR_GENERATING_TMP_RSA_KEY"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST), "ERROR_IN_RECEIVED_CIPHER_LIST"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_EVP_DIGESTSIGNFINAL_FAILED), "EVP_DIGESTSIGNFINAL_FAILED"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_EVP_DIGESTSIGNINIT_FAILED), "EVP_DIGESTSIGNINIT_FAILED"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_EXCESSIVE_MESSAGE_SIZE), "EXCESSIVE_MESSAGE_SIZE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_EXTRA_DATA_IN_MESSAGE), "EXTRA_DATA_IN_MESSAGE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_GOST_NOT_SUPPORTED), "GOST_NOT_SUPPORTED"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_GOT_A_FIN_BEFORE_A_CCS), "GOT_A_FIN_BEFORE_A_CCS"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_GOT_CHANNEL_ID_BEFORE_A_CCS), "GOT_CHANNEL_ID_BEFORE_A_CCS"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_GOT_NEXT_PROTO_BEFORE_A_CCS), "GOT_NEXT_PROTO_BEFORE_A_CCS"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_GOT_NEXT_PROTO_WITHOUT_EXTENSION), "GOT_NEXT_PROTO_WITHOUT_EXTENSION"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_HANDSHAKE_FAILURE_ON_CLIENT_HELLO), "HANDSHAKE_FAILURE_ON_CLIENT_HELLO"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_HANDSHAKE_RECORD_BEFORE_CCS), "HANDSHAKE_RECORD_BEFORE_CCS"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_HTTPS_PROXY_REQUEST), "HTTPS_PROXY_REQUEST"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_HTTP_REQUEST), "HTTP_REQUEST"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_ILLEGAL_PADDING), "ILLEGAL_PADDING"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_ILLEGAL_SUITEB_DIGEST), "ILLEGAL_SUITEB_DIGEST"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INAPPROPRIATE_FALLBACK), "INAPPROPRIATE_FALLBACK"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INCONSISTENT_COMPRESSION), "INCONSISTENT_COMPRESSION"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_AUDIT_PROOF), "INVALID_AUDIT_PROOF"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_AUTHZ_DATA), "INVALID_AUTHZ_DATA"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_CHALLENGE_LENGTH), "INVALID_CHALLENGE_LENGTH"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_COMMAND), "INVALID_COMMAND"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_COMPRESSION_ALGORITHM), "INVALID_COMPRESSION_ALGORITHM"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_MESSAGE), "INVALID_MESSAGE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_NULL_CMD_NAME), "INVALID_NULL_CMD_NAME"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_PURPOSE), "INVALID_PURPOSE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_SERVERINFO_DATA), "INVALID_SERVERINFO_DATA"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_SRP_USERNAME), "INVALID_SRP_USERNAME"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_SSL_SESSION), "INVALID_SSL_SESSION"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_STATUS_RESPONSE), "INVALID_STATUS_RESPONSE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_TICKET_KEYS_LENGTH), "INVALID_TICKET_KEYS_LENGTH"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_TRUST), "INVALID_TRUST"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_KEY_ARG_TOO_LONG), "KEY_ARG_TOO_LONG"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_KRB5), "KRB5"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_KRB5_C_CC_PRINC), "KRB5_C_CC_PRINC"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_KRB5_C_GET_CRED), "KRB5_C_GET_CRED"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_KRB5_C_INIT), "KRB5_C_INIT"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_KRB5_C_MK_REQ), "KRB5_C_MK_REQ"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_KRB5_S_BAD_TICKET), "KRB5_S_BAD_TICKET"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_KRB5_S_INIT), "KRB5_S_INIT"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_KRB5_S_RD_REQ), "KRB5_S_RD_REQ"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_KRB5_S_TKT_EXPIRED), "KRB5_S_TKT_EXPIRED"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_KRB5_S_TKT_NYV), "KRB5_S_TKT_NYV"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_KRB5_S_TKT_SKEW), "KRB5_S_TKT_SKEW"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_LENGTH_MISMATCH), "LENGTH_MISMATCH"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_LENGTH_TOO_SHORT), "LENGTH_TOO_SHORT"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_LIBRARY_BUG), "LIBRARY_BUG"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_LIBRARY_HAS_NO_CIPHERS), "LIBRARY_HAS_NO_CIPHERS"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MESSAGE_TOO_LONG), "MESSAGE_TOO_LONG"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MISSING_DH_DSA_CERT), "MISSING_DH_DSA_CERT"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MISSING_DH_KEY), "MISSING_DH_KEY"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MISSING_DH_RSA_CERT), "MISSING_DH_RSA_CERT"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MISSING_DSA_SIGNING_CERT), "MISSING_DSA_SIGNING_CERT"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MISSING_ECDH_CERT), "MISSING_ECDH_CERT"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MISSING_ECDSA_SIGNING_CERT), "MISSING_ECDSA_SIGNING_CERT"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MISSING_EXPORT_TMP_DH_KEY), "MISSING_EXPORT_TMP_DH_KEY"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MISSING_EXPORT_TMP_RSA_KEY), "MISSING_EXPORT_TMP_RSA_KEY"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MISSING_RSA_CERTIFICATE), "MISSING_RSA_CERTIFICATE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MISSING_RSA_ENCRYPTING_CERT), "MISSING_RSA_ENCRYPTING_CERT"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MISSING_RSA_SIGNING_CERT), "MISSING_RSA_SIGNING_CERT"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MISSING_SRP_PARAM), "MISSING_SRP_PARAM"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MISSING_TMP_DH_KEY), "MISSING_TMP_DH_KEY"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MISSING_TMP_ECDH_KEY), "MISSING_TMP_ECDH_KEY"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MISSING_TMP_RSA_KEY), "MISSING_TMP_RSA_KEY"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MISSING_TMP_RSA_PKEY), "MISSING_TMP_RSA_PKEY"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MISSING_VERIFY_MESSAGE), "MISSING_VERIFY_MESSAGE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MIXED_SPECIAL_OPERATOR_WITH_GROUPS), "MIXED_SPECIAL_OPERATOR_WITH_GROUPS"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MTU_TOO_SMALL), "MTU_TOO_SMALL"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MULTIPLE_SGC_RESTARTS), "MULTIPLE_SGC_RESTARTS"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NESTED_GROUP), "NESTED_GROUP"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NON_SSLV2_INITIAL_PACKET), "NON_SSLV2_INITIAL_PACKET"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_CERTIFICATES_RETURNED), "NO_CERTIFICATES_RETURNED"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_CERTIFICATE_ASSIGNED), "NO_CERTIFICATE_ASSIGNED"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_CERTIFICATE_RETURNED), "NO_CERTIFICATE_RETURNED"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_CERTIFICATE_SET), "NO_CERTIFICATE_SET"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_CERTIFICATE_SPECIFIED), "NO_CERTIFICATE_SPECIFIED"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_CIPHERS_AVAILABLE), "NO_CIPHERS_AVAILABLE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_CIPHERS_PASSED), "NO_CIPHERS_PASSED"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_CIPHERS_SPECIFIED), "NO_CIPHERS_SPECIFIED"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_CIPHER_LIST), "NO_CIPHER_LIST"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_CIPHER_MATCH), "NO_CIPHER_MATCH"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_CLIENT_CERT_METHOD), "NO_CLIENT_CERT_METHOD"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_CLIENT_CERT_RECEIVED), "NO_CLIENT_CERT_RECEIVED"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_COMPRESSION_SPECIFIED), "NO_COMPRESSION_SPECIFIED"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER), "NO_GOST_CERTIFICATE_SENT_BY_PEER"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_METHOD_SPECIFIED), "NO_METHOD_SPECIFIED"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_P256_SUPPORT), "NO_P256_SUPPORT"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_PEM_EXTENSIONS), "NO_PEM_EXTENSIONS"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_PRIVATEKEY), "NO_PRIVATEKEY"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_PRIVATE_KEY_ASSIGNED), "NO_PRIVATE_KEY_ASSIGNED"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_PROTOCOLS_AVAILABLE), "NO_PROTOCOLS_AVAILABLE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_PUBLICKEY), "NO_PUBLICKEY"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_RENEGOTIATION), "NO_RENEGOTIATION"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_REQUIRED_DIGEST), "NO_REQUIRED_DIGEST"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_SHARED_CIPHER), "NO_SHARED_CIPHER"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_SHARED_SIGATURE_ALGORITHMS), "NO_SHARED_SIGATURE_ALGORITHMS"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_SRTP_PROFILES), "NO_SRTP_PROFILES"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_VERIFY_CALLBACK), "NO_VERIFY_CALLBACK"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NULL_SSL_CTX), "NULL_SSL_CTX"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NULL_SSL_METHOD_PASSED), "NULL_SSL_METHOD_PASSED"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED), "OLD_SESSION_CIPHER_NOT_RETURNED"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED), "OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_ONLY_DTLS_1_2_ALLOWED_IN_SUITEB_MODE), "ONLY_DTLS_1_2_ALLOWED_IN_SUITEB_MODE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_ONLY_TLS_1_2_ALLOWED_IN_SUITEB_MODE), "ONLY_TLS_1_2_ALLOWED_IN_SUITEB_MODE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE), "ONLY_TLS_ALLOWED_IN_FIPS_MODE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_OPAQUE_PRF_INPUT_TOO_LONG), "OPAQUE_PRF_INPUT_TOO_LONG"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_PACKET_LENGTH_TOO_LONG), "PACKET_LENGTH_TOO_LONG"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_PARSE_TLSEXT), "PARSE_TLSEXT"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_PATH_TOO_LONG), "PATH_TOO_LONG"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE), "PEER_DID_NOT_RETURN_A_CERTIFICATE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_PEER_ERROR), "PEER_ERROR"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_PEER_ERROR_CERTIFICATE), "PEER_ERROR_CERTIFICATE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_PEER_ERROR_NO_CERTIFICATE), "PEER_ERROR_NO_CERTIFICATE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_PEER_ERROR_NO_CIPHER), "PEER_ERROR_NO_CIPHER"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE), "PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_PEM_NAME_BAD_PREFIX), "PEM_NAME_BAD_PREFIX"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_PEM_NAME_TOO_SHORT), "PEM_NAME_TOO_SHORT"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_PRE_MAC_LENGTH_TOO_LONG), "PRE_MAC_LENGTH_TOO_LONG"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS), "PROBLEMS_MAPPING_CIPHER_FUNCTIONS"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_PROTOCOL_IS_SHUTDOWN), "PROTOCOL_IS_SHUTDOWN"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_PSK_IDENTITY_NOT_FOUND), "PSK_IDENTITY_NOT_FOUND"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_PSK_NO_CLIENT_CB), "PSK_NO_CLIENT_CB"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_PSK_NO_SERVER_CB), "PSK_NO_SERVER_CB"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_PUBLIC_KEY_ENCRYPT_ERROR), "PUBLIC_KEY_ENCRYPT_ERROR"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_PUBLIC_KEY_IS_NOT_RSA), "PUBLIC_KEY_IS_NOT_RSA"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_PUBLIC_KEY_NOT_RSA), "PUBLIC_KEY_NOT_RSA"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_READ_BIO_NOT_SET), "READ_BIO_NOT_SET"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_READ_TIMEOUT_EXPIRED), "READ_TIMEOUT_EXPIRED"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_READ_WRONG_PACKET_TYPE), "READ_WRONG_PACKET_TYPE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_RECORD_LENGTH_MISMATCH), "RECORD_LENGTH_MISMATCH"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_RECORD_TOO_LARGE), "RECORD_TOO_LARGE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_RECORD_TOO_SMALL), "RECORD_TOO_SMALL"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_RENEGOTIATE_EXT_TOO_LONG), "RENEGOTIATE_EXT_TOO_LONG"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_RENEGOTIATION_ENCODING_ERR), "RENEGOTIATION_ENCODING_ERR"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_RENEGOTIATION_MISMATCH), "RENEGOTIATION_MISMATCH"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_REQUIRED_CIPHER_MISSING), "REQUIRED_CIPHER_MISSING"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_REQUIRED_COMPRESSSION_ALGORITHM_MISSING), "REQUIRED_COMPRESSSION_ALGORITHM_MISSING"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_REUSE_CERT_LENGTH_NOT_ZERO), "REUSE_CERT_LENGTH_NOT_ZERO"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_REUSE_CERT_TYPE_NOT_ZERO), "REUSE_CERT_TYPE_NOT_ZERO"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_REUSE_CIPHER_LIST_NOT_ZERO), "REUSE_CIPHER_LIST_NOT_ZERO"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING), "SCSV_RECEIVED_WHEN_RENEGOTIATING"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SERVERHELLO_TLSEXT), "SERVERHELLO_TLSEXT"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED), "SESSION_ID_CONTEXT_UNINITIALIZED"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SESSION_MAY_NOT_BE_CREATED), "SESSION_MAY_NOT_BE_CREATED"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SHORT_READ), "SHORT_READ"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SIGNATURE_ALGORITHMS_ERROR), "SIGNATURE_ALGORITHMS_ERROR"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE), "SIGNATURE_FOR_NON_SIGNING_CERTIFICATE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SRP_A_CALC), "SRP_A_CALC"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SRTP_COULD_NOT_ALLOCATE_PROFILES), "SRTP_COULD_NOT_ALLOCATE_PROFILES"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SRTP_PROTECTION_PROFILE_LIST_TOO_LONG), "SRTP_PROTECTION_PROFILE_LIST_TOO_LONG"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SRTP_UNKNOWN_PROTECTION_PROFILE), "SRTP_UNKNOWN_PROTECTION_PROFILE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSL23_DOING_SESSION_ID_REUSE), "SSL23_DOING_SESSION_ID_REUSE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSL2_CONNECTION_ID_TOO_LONG), "SSL2_CONNECTION_ID_TOO_LONG"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSL3_EXT_INVALID_ECPOINTFORMAT), "SSL3_EXT_INVALID_ECPOINTFORMAT"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSL3_EXT_INVALID_SERVERNAME), "SSL3_EXT_INVALID_SERVERNAME"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE), "SSL3_EXT_INVALID_SERVERNAME_TYPE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSL3_SESSION_ID_TOO_LONG), "SSL3_SESSION_ID_TOO_LONG"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSL3_SESSION_ID_TOO_SHORT), "SSL3_SESSION_ID_TOO_SHORT"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSLV3_ALERT_BAD_CERTIFICATE), "SSLV3_ALERT_BAD_CERTIFICATE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSLV3_ALERT_BAD_RECORD_MAC), "SSLV3_ALERT_BAD_RECORD_MAC"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED), "SSLV3_ALERT_CERTIFICATE_EXPIRED"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED), "SSLV3_ALERT_CERTIFICATE_REVOKED"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN), "SSLV3_ALERT_CERTIFICATE_UNKNOWN"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSLV3_ALERT_CLOSE_NOTIFY), "SSLV3_ALERT_CLOSE_NOTIFY"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE), "SSLV3_ALERT_DECOMPRESSION_FAILURE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE), "SSLV3_ALERT_HANDSHAKE_FAILURE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER), "SSLV3_ALERT_ILLEGAL_PARAMETER"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSLV3_ALERT_NO_CERTIFICATE), "SSLV3_ALERT_NO_CERTIFICATE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE), "SSLV3_ALERT_UNEXPECTED_MESSAGE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE), "SSLV3_ALERT_UNSUPPORTED_CERTIFICATE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION), "SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSL_HANDSHAKE_FAILURE), "SSL_HANDSHAKE_FAILURE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS), "SSL_LIBRARY_HAS_NO_CIPHERS"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSL_SESSION_ID_CALLBACK_FAILED), "SSL_SESSION_ID_CALLBACK_FAILED"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSL_SESSION_ID_CONFLICT), "SSL_SESSION_ID_CONFLICT"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG), "SSL_SESSION_ID_CONTEXT_TOO_LONG"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH), "SSL_SESSION_ID_HAS_BAD_LENGTH"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSL_SESSION_ID_IS_DIFFERENT), "SSL_SESSION_ID_IS_DIFFERENT"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_ALERT_ACCESS_DENIED), "TLSV1_ALERT_ACCESS_DENIED"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_ALERT_DECODE_ERROR), "TLSV1_ALERT_DECODE_ERROR"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_ALERT_DECRYPTION_FAILED), "TLSV1_ALERT_DECRYPTION_FAILED"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_ALERT_DECRYPT_ERROR), "TLSV1_ALERT_DECRYPT_ERROR"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION), "TLSV1_ALERT_EXPORT_RESTRICTION"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_ALERT_INAPPROPRIATE_FALLBACK), "TLSV1_ALERT_INAPPROPRIATE_FALLBACK"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY), "TLSV1_ALERT_INSUFFICIENT_SECURITY"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_ALERT_INTERNAL_ERROR), "TLSV1_ALERT_INTERNAL_ERROR"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_ALERT_NO_RENEGOTIATION), "TLSV1_ALERT_NO_RENEGOTIATION"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_ALERT_PROTOCOL_VERSION), "TLSV1_ALERT_PROTOCOL_VERSION"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_ALERT_RECORD_OVERFLOW), "TLSV1_ALERT_RECORD_OVERFLOW"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_ALERT_UNKNOWN_CA), "TLSV1_ALERT_UNKNOWN_CA"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_ALERT_USER_CANCELLED), "TLSV1_ALERT_USER_CANCELLED"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_BAD_CERTIFICATE_HASH_VALUE), "TLSV1_BAD_CERTIFICATE_HASH_VALUE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE), "TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_CERTIFICATE_UNOBTAINABLE), "TLSV1_CERTIFICATE_UNOBTAINABLE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_UNRECOGNIZED_NAME), "TLSV1_UNRECOGNIZED_NAME"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_UNSUPPORTED_EXTENSION), "TLSV1_UNSUPPORTED_EXTENSION"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER), "TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLS_ILLEGAL_EXPORTER_LABEL), "TLS_ILLEGAL_EXPORTER_LABEL"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST), "TLS_INVALID_ECPOINTFORMAT_LIST"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST), "TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG), "TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TOO_MANY_EMPTY_FRAGMENTS), "TOO_MANY_EMPTY_FRAGMENTS"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER), "TRIED_TO_USE_UNSUPPORTED_CIPHER"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNABLE_TO_DECODE_DH_CERTS), "UNABLE_TO_DECODE_DH_CERTS"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNABLE_TO_DECODE_ECDH_CERTS), "UNABLE_TO_DECODE_ECDH_CERTS"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNABLE_TO_EXTRACT_PUBLIC_KEY), "UNABLE_TO_EXTRACT_PUBLIC_KEY"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNABLE_TO_FIND_DH_PARAMETERS), "UNABLE_TO_FIND_DH_PARAMETERS"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS), "UNABLE_TO_FIND_ECDH_PARAMETERS"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS), "UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNABLE_TO_FIND_SSL_METHOD), "UNABLE_TO_FIND_SSL_METHOD"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNABLE_TO_LOAD_SSL2_MD5_ROUTINES), "UNABLE_TO_LOAD_SSL2_MD5_ROUTINES"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES), "UNABLE_TO_LOAD_SSL3_MD5_ROUTINES"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES), "UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNEXPECTED_GROUP_CLOSE), "UNEXPECTED_GROUP_CLOSE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNEXPECTED_MESSAGE), "UNEXPECTED_MESSAGE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNEXPECTED_OPERATOR_IN_GROUP), "UNEXPECTED_OPERATOR_IN_GROUP"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNEXPECTED_RECORD), "UNEXPECTED_RECORD"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNINITIALIZED), "UNINITIALIZED"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNKNOWN_ALERT_TYPE), "UNKNOWN_ALERT_TYPE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNKNOWN_AUTHZ_DATA_TYPE), "UNKNOWN_AUTHZ_DATA_TYPE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNKNOWN_CERTIFICATE_TYPE), "UNKNOWN_CERTIFICATE_TYPE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNKNOWN_CIPHER_RETURNED), "UNKNOWN_CIPHER_RETURNED"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNKNOWN_CIPHER_TYPE), "UNKNOWN_CIPHER_TYPE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNKNOWN_CMD_NAME), "UNKNOWN_CMD_NAME"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNKNOWN_DIGEST), "UNKNOWN_DIGEST"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE), "UNKNOWN_KEY_EXCHANGE_TYPE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNKNOWN_PKEY_TYPE), "UNKNOWN_PKEY_TYPE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNKNOWN_PROTOCOL), "UNKNOWN_PROTOCOL"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNKNOWN_REMOTE_ERROR_TYPE), "UNKNOWN_REMOTE_ERROR_TYPE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNKNOWN_SSL_VERSION), "UNKNOWN_SSL_VERSION"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNKNOWN_STATE), "UNKNOWN_STATE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNKNOWN_SUPPLEMENTAL_DATA_TYPE), "UNKNOWN_SUPPLEMENTAL_DATA_TYPE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNPROCESSED_HANDSHAKE_DATA), "UNPROCESSED_HANDSHAKE_DATA"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED), "UNSAFE_LEGACY_RENEGOTIATION_DISABLED"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNSUPPORTED_CIPHER), "UNSUPPORTED_CIPHER"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM), "UNSUPPORTED_COMPRESSION_ALGORITHM"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNSUPPORTED_DIGEST_TYPE), "UNSUPPORTED_DIGEST_TYPE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNSUPPORTED_ELLIPTIC_CURVE), "UNSUPPORTED_ELLIPTIC_CURVE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNSUPPORTED_PROTOCOL), "UNSUPPORTED_PROTOCOL"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNSUPPORTED_SSL_VERSION), "UNSUPPORTED_SSL_VERSION"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNSUPPORTED_STATUS_TYPE), "UNSUPPORTED_STATUS_TYPE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_USE_SRTP_NOT_NEGOTIATED), "USE_SRTP_NOT_NEGOTIATED"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_WRITE_BIO_NOT_SET), "WRITE_BIO_NOT_SET"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_WRONG_CERTIFICATE_TYPE), "WRONG_CERTIFICATE_TYPE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_WRONG_CIPHER_RETURNED), "WRONG_CIPHER_RETURNED"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_WRONG_CURVE), "WRONG_CURVE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_WRONG_MESSAGE_TYPE), "WRONG_MESSAGE_TYPE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_WRONG_NUMBER_OF_KEY_BITS), "WRONG_NUMBER_OF_KEY_BITS"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_WRONG_SIGNATURE_LENGTH), "WRONG_SIGNATURE_LENGTH"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_WRONG_SIGNATURE_SIZE), "WRONG_SIGNATURE_SIZE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_WRONG_SIGNATURE_TYPE), "WRONG_SIGNATURE_TYPE"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_WRONG_SSL_VERSION), "WRONG_SSL_VERSION"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_WRONG_VERSION_NUMBER), "WRONG_VERSION_NUMBER"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_X509_LIB), "X509_LIB"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_X509_VERIFICATION_SETUP_PROBLEMS), "X509_VERIFICATION_SETUP_PROBLEMS"},
+ {0, NULL},
+};
diff --git a/src/ssl/ssl_lib.c b/src/ssl/ssl_lib.c
new file mode 100644
index 0000000..c3b95d5
--- /dev/null
+++ b/src/ssl/ssl_lib.c
@@ -0,0 +1,3174 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <stdio.h>
+#include <assert.h>
+
+#include <openssl/bytestring.h>
+#include <openssl/dh.h>
+#include <openssl/engine.h>
+#include <openssl/lhash.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/rand.h>
+#include <openssl/x509v3.h>
+
+#include "ssl_locl.h"
+
+/* Some error codes are special. Ensure the make_errors.go script never
+ * regresses this. */
+OPENSSL_COMPILE_ASSERT(SSL_R_TLSV1_ALERT_NO_RENEGOTIATION ==
+ SSL_AD_NO_RENEGOTIATION + SSL_AD_REASON_OFFSET,
+ ssl_alert_reason_code_mismatch);
+
+int SSL_clear(SSL *s) {
+ if (s->method == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_clear, SSL_R_NO_METHOD_SPECIFIED);
+ return 0;
+ }
+
+ if (ssl_clear_bad_session(s)) {
+ SSL_SESSION_free(s->session);
+ s->session = NULL;
+ }
+
+ s->hit = 0;
+ s->shutdown = 0;
+
+ if (s->renegotiate) {
+ OPENSSL_PUT_ERROR(SSL, SSL_clear, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ /* SSL_clear may be called before or after the |s| is initialized in either
+ * accept or connect state. In the latter case, SSL_clear should preserve the
+ * half and reset |s->state| accordingly. */
+ if (s->handshake_func != NULL) {
+ if (s->server) {
+ SSL_set_accept_state(s);
+ } else {
+ SSL_set_connect_state(s);
+ }
+ } else {
+ assert(s->state == 0);
+ }
+
+ /* TODO(davidben): Some state on |s| is reset both in |SSL_new| and
+ * |SSL_clear| because it is per-connection state rather than configuration
+ * state. Per-connection state should be on |s->s3| and |s->d1| so it is
+ * naturally reset at the right points between |SSL_new|, |SSL_clear|, and
+ * |ssl3_new|. */
+
+ s->rwstate = SSL_NOTHING;
+ s->rstate = SSL_ST_READ_HEADER;
+
+ if (s->init_buf != NULL) {
+ BUF_MEM_free(s->init_buf);
+ s->init_buf = NULL;
+ }
+
+ s->packet = NULL;
+ s->packet_length = 0;
+
+ ssl_clear_cipher_ctx(s);
+
+ if (s->next_proto_negotiated) {
+ OPENSSL_free(s->next_proto_negotiated);
+ s->next_proto_negotiated = NULL;
+ s->next_proto_negotiated_len = 0;
+ }
+
+ /* The s->d1->mtu is simultaneously configuration (preserved across
+ * clear) and connection-specific state (gets reset).
+ *
+ * TODO(davidben): Avoid this. */
+ unsigned mtu = 0;
+ if (s->d1 != NULL) {
+ mtu = s->d1->mtu;
+ }
+
+ s->method->ssl_free(s);
+ if (!s->method->ssl_new(s)) {
+ return 0;
+ }
+ s->enc_method = ssl3_get_enc_method(s->version);
+ assert(s->enc_method != NULL);
+
+ if (SSL_IS_DTLS(s) && (SSL_get_options(s) & SSL_OP_NO_QUERY_MTU)) {
+ s->d1->mtu = mtu;
+ }
+
+ s->client_version = s->version;
+
+ return 1;
+}
+
+SSL *SSL_new(SSL_CTX *ctx) {
+ SSL *s;
+
+ if (ctx == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_new, SSL_R_NULL_SSL_CTX);
+ return NULL;
+ }
+ if (ctx->method == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_new, SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION);
+ return NULL;
+ }
+
+ s = (SSL *)OPENSSL_malloc(sizeof(SSL));
+ if (s == NULL) {
+ goto err;
+ }
+ memset(s, 0, sizeof(SSL));
+
+ s->min_version = ctx->min_version;
+ s->max_version = ctx->max_version;
+
+ s->options = ctx->options;
+ s->mode = ctx->mode;
+ s->max_cert_list = ctx->max_cert_list;
+
+ if (ctx->cert != NULL) {
+ /* Earlier library versions used to copy the pointer to the CERT, not its
+ * contents; only when setting new parameters for the per-SSL copy,
+ * ssl_cert_new would be called (and the direct reference to the
+ * per-SSL_CTX settings would be lost, but those still were indirectly
+ * accessed for various purposes, and for that reason they used to be known
+ * as s->ctx->default_cert). Now we don't look at the SSL_CTX's CERT after
+ * having duplicated it once. */
+
+ s->cert = ssl_cert_dup(ctx->cert);
+ if (s->cert == NULL) {
+ goto err;
+ }
+ } else {
+ s->cert = NULL; /* Cannot really happen (see SSL_CTX_new) */
+ }
+
+ 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;
+ 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 = 0;
+ s->tlsext_debug_arg = NULL;
+ s->tlsext_ticket_expected = 0;
+ CRYPTO_add(&ctx->references, 1, CRYPTO_LOCK_SSL_CTX);
+ s->initial_ctx = ctx;
+ if (ctx->tlsext_ecpointformatlist) {
+ s->tlsext_ecpointformatlist = BUF_memdup(
+ ctx->tlsext_ecpointformatlist, ctx->tlsext_ecpointformatlist_length);
+ if (!s->tlsext_ecpointformatlist) {
+ goto err;
+ }
+ s->tlsext_ecpointformatlist_length = ctx->tlsext_ecpointformatlist_length;
+ }
+
+ if (ctx->tlsext_ellipticcurvelist) {
+ s->tlsext_ellipticcurvelist =
+ BUF_memdup(ctx->tlsext_ellipticcurvelist,
+ ctx->tlsext_ellipticcurvelist_length * 2);
+ if (!s->tlsext_ellipticcurvelist) {
+ goto err;
+ }
+ s->tlsext_ellipticcurvelist_length = ctx->tlsext_ellipticcurvelist_length;
+ }
+ s->next_proto_negotiated = NULL;
+
+ if (s->ctx->alpn_client_proto_list) {
+ s->alpn_client_proto_list = BUF_memdup(s->ctx->alpn_client_proto_list,
+ s->ctx->alpn_client_proto_list_len);
+ if (s->alpn_client_proto_list == NULL) {
+ goto err;
+ }
+ s->alpn_client_proto_list_len = s->ctx->alpn_client_proto_list_len;
+ }
+
+ s->verify_result = X509_V_OK;
+ s->method = ctx->method;
+
+ if (!s->method->ssl_new(s)) {
+ goto err;
+ }
+ s->enc_method = ssl3_get_enc_method(s->version);
+ assert(s->enc_method != NULL);
+
+ s->references = 1;
+
+ s->rwstate = SSL_NOTHING;
+ s->rstate = SSL_ST_READ_HEADER;
+
+ CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL, s, &s->ex_data);
+
+ s->psk_identity_hint = NULL;
+ if (ctx->psk_identity_hint) {
+ s->psk_identity_hint = BUF_strdup(ctx->psk_identity_hint);
+ if (s->psk_identity_hint == NULL) {
+ goto err;
+ }
+ }
+ s->psk_client_callback = ctx->psk_client_callback;
+ s->psk_server_callback = ctx->psk_server_callback;
+
+ s->tlsext_channel_id_enabled = ctx->tlsext_channel_id_enabled;
+ if (ctx->tlsext_channel_id_private) {
+ s->tlsext_channel_id_private = EVP_PKEY_dup(ctx->tlsext_channel_id_private);
+ }
+
+ s->signed_cert_timestamps_enabled = s->ctx->signed_cert_timestamps_enabled;
+ s->ocsp_stapling_enabled = s->ctx->ocsp_stapling_enabled;
+
+ return s;
+
+err:
+ if (s != NULL) {
+ SSL_free(s);
+ }
+ OPENSSL_PUT_ERROR(SSL, SSL_new, ERR_R_MALLOC_FAILURE);
+
+ return NULL;
+}
+
+int SSL_CTX_set_session_id_context(SSL_CTX *ctx, const uint8_t *sid_ctx,
+ unsigned int sid_ctx_len) {
+ if (sid_ctx_len > sizeof ctx->sid_ctx) {
+ OPENSSL_PUT_ERROR(SSL, SSL_CTX_set_session_id_context,
+ 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;
+}
+
+int SSL_set_session_id_context(SSL *ssl, const uint8_t *sid_ctx,
+ unsigned int sid_ctx_len) {
+ if (sid_ctx_len > SSL_MAX_SID_CTX_LENGTH) {
+ OPENSSL_PUT_ERROR(SSL, SSL_set_session_id_context,
+ 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;
+}
+
+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;
+}
+
+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;
+}
+
+int SSL_has_matching_session_id(const SSL *ssl, const uint8_t *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;
+}
+
+int SSL_CTX_set_purpose(SSL_CTX *s, int purpose) {
+ return X509_VERIFY_PARAM_set_purpose(s->param, purpose);
+}
+
+int SSL_set_purpose(SSL *s, int purpose) {
+ return X509_VERIFY_PARAM_set_purpose(s->param, purpose);
+}
+
+int SSL_CTX_set_trust(SSL_CTX *s, int trust) {
+ return X509_VERIFY_PARAM_set_trust(s->param, trust);
+}
+
+int SSL_set_trust(SSL *s, int trust) {
+ return X509_VERIFY_PARAM_set_trust(s->param, trust);
+}
+
+int SSL_CTX_set1_param(SSL_CTX *ctx, X509_VERIFY_PARAM *vpm) {
+ return X509_VERIFY_PARAM_set1(ctx->param, vpm);
+}
+
+int SSL_set1_param(SSL *ssl, X509_VERIFY_PARAM *vpm) {
+ return X509_VERIFY_PARAM_set1(ssl->param, vpm);
+}
+
+void ssl_cipher_preference_list_free(
+ struct ssl_cipher_preference_list_st *cipher_list) {
+ sk_SSL_CIPHER_free(cipher_list->ciphers);
+ OPENSSL_free(cipher_list->in_group_flags);
+ OPENSSL_free(cipher_list);
+}
+
+struct ssl_cipher_preference_list_st *ssl_cipher_preference_list_dup(
+ struct ssl_cipher_preference_list_st *cipher_list) {
+ struct ssl_cipher_preference_list_st *ret = NULL;
+ size_t n = sk_SSL_CIPHER_num(cipher_list->ciphers);
+
+ ret = OPENSSL_malloc(sizeof(struct ssl_cipher_preference_list_st));
+ if (!ret) {
+ goto err;
+ }
+
+ ret->ciphers = NULL;
+ ret->in_group_flags = NULL;
+ ret->ciphers = sk_SSL_CIPHER_dup(cipher_list->ciphers);
+ if (!ret->ciphers) {
+ goto err;
+ }
+ ret->in_group_flags = BUF_memdup(cipher_list->in_group_flags, n);
+ if (!ret->in_group_flags) {
+ goto err;
+ }
+
+ return ret;
+
+err:
+ if (ret && ret->ciphers) {
+ sk_SSL_CIPHER_free(ret->ciphers);
+ }
+ if (ret) {
+ OPENSSL_free(ret);
+ }
+ return NULL;
+}
+
+struct ssl_cipher_preference_list_st *ssl_cipher_preference_list_from_ciphers(
+ STACK_OF(SSL_CIPHER) * ciphers) {
+ struct ssl_cipher_preference_list_st *ret = NULL;
+ size_t n = sk_SSL_CIPHER_num(ciphers);
+
+ ret = OPENSSL_malloc(sizeof(struct ssl_cipher_preference_list_st));
+ if (!ret) {
+ goto err;
+ }
+ ret->ciphers = NULL;
+ ret->in_group_flags = NULL;
+ ret->ciphers = sk_SSL_CIPHER_dup(ciphers);
+ if (!ret->ciphers) {
+ goto err;
+ }
+ ret->in_group_flags = OPENSSL_malloc(n);
+ if (!ret->in_group_flags) {
+ goto err;
+ }
+ memset(ret->in_group_flags, 0, n);
+ return ret;
+
+err:
+ if (ret && ret->ciphers) {
+ sk_SSL_CIPHER_free(ret->ciphers);
+ }
+ if (ret) {
+ OPENSSL_free(ret);
+ }
+ return NULL;
+}
+
+X509_VERIFY_PARAM *SSL_CTX_get0_param(SSL_CTX *ctx) { return ctx->param; }
+
+X509_VERIFY_PARAM *SSL_get0_param(SSL *ssl) { return ssl->param; }
+
+void SSL_certs_clear(SSL *s) { ssl_cert_clear_certs(s->cert); }
+
+void SSL_free(SSL *s) {
+ int i;
+
+ if (s == NULL) {
+ return;
+ }
+
+ i = CRYPTO_add(&s->references, -1, CRYPTO_LOCK_SSL);
+ if (i > 0) {
+ return;
+ }
+
+ if (s->param) {
+ 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 != NULL) {
+ BIO_free_all(s->rbio);
+ }
+
+ if (s->wbio != NULL && s->wbio != s->rbio) {
+ BIO_free_all(s->wbio);
+ }
+
+ if (s->init_buf != NULL) {
+ BUF_MEM_free(s->init_buf);
+ }
+
+ /* add extra stuff */
+ if (s->cipher_list != NULL) {
+ ssl_cipher_preference_list_free(s->cipher_list);
+ }
+ if (s->cipher_list_by_id != NULL) {
+ sk_SSL_CIPHER_free(s->cipher_list_by_id);
+ }
+
+ if (s->session != NULL) {
+ ssl_clear_bad_session(s);
+ SSL_SESSION_free(s->session);
+ }
+
+ ssl_clear_cipher_ctx(s);
+
+ if (s->cert != NULL) {
+ ssl_cert_free(s->cert);
+ }
+
+ if (s->tlsext_hostname) {
+ OPENSSL_free(s->tlsext_hostname);
+ }
+ if (s->initial_ctx) {
+ SSL_CTX_free(s->initial_ctx);
+ }
+ if (s->tlsext_ecpointformatlist) {
+ OPENSSL_free(s->tlsext_ecpointformatlist);
+ }
+ if (s->tlsext_ellipticcurvelist) {
+ OPENSSL_free(s->tlsext_ellipticcurvelist);
+ }
+ if (s->alpn_client_proto_list) {
+ OPENSSL_free(s->alpn_client_proto_list);
+ }
+ if (s->tlsext_channel_id_private) {
+ EVP_PKEY_free(s->tlsext_channel_id_private);
+ }
+ if (s->psk_identity_hint) {
+ OPENSSL_free(s->psk_identity_hint);
+ }
+ if (s->client_CA != NULL) {
+ sk_X509_NAME_pop_free(s->client_CA, X509_NAME_free);
+ }
+ if (s->next_proto_negotiated) {
+ OPENSSL_free(s->next_proto_negotiated);
+ }
+ if (s->srtp_profiles) {
+ sk_SRTP_PROTECTION_PROFILE_free(s->srtp_profiles);
+ }
+
+ if (s->method != NULL) {
+ s->method->ssl_free(s);
+ }
+ if (s->ctx) {
+ SSL_CTX_free(s->ctx);
+ }
+
+ OPENSSL_free(s);
+}
+
+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 = s->wbio->next_bio;
+ s->bbio->next_bio = NULL;
+ }
+ }
+
+ if (s->rbio != NULL && s->rbio != rbio) {
+ BIO_free_all(s->rbio);
+ }
+ if (s->wbio != NULL && s->wbio != wbio && s->rbio != s->wbio) {
+ BIO_free_all(s->wbio);
+ }
+ s->rbio = rbio;
+ s->wbio = wbio;
+}
+
+BIO *SSL_get_rbio(const SSL *s) { return s->rbio; }
+
+BIO *SSL_get_wbio(const SSL *s) { return s->wbio; }
+
+int SSL_get_fd(const SSL *s) { return SSL_get_rfd(s); }
+
+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;
+}
+
+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;
+}
+
+int SSL_set_fd(SSL *s, int fd) {
+ int ret = 0;
+ BIO *bio = NULL;
+
+ bio = BIO_new(BIO_s_fd());
+
+ if (bio == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_set_fd, ERR_R_BUF_LIB);
+ goto err;
+ }
+ BIO_set_fd(bio, fd, BIO_NOCLOSE);
+ SSL_set_bio(s, bio, bio);
+ ret = 1;
+
+err:
+ return ret;
+}
+
+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_FD ||
+ (int)BIO_get_fd(s->rbio, NULL) != fd) {
+ bio = BIO_new(BIO_s_fd());
+
+ if (bio == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_set_wfd, 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;
+}
+
+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_FD ||
+ (int)BIO_get_fd(s->wbio, NULL) != fd) {
+ bio = BIO_new(BIO_s_fd());
+
+ if (bio == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_set_rfd, 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;
+}
+
+/* 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 = 0;
+
+ if (s->s3 != NULL) {
+ ret = s->s3->tmp.finish_md_len;
+ if (count > ret) {
+ count = ret;
+ }
+ memcpy(buf, s->s3->tmp.finish_md, count);
+ }
+
+ return ret;
+}
+
+/* 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 = 0;
+
+ if (s->s3 != NULL) {
+ ret = s->s3->tmp.peer_finish_md_len;
+ if (count > ret) {
+ count = ret;
+ }
+ memcpy(buf, s->s3->tmp.peer_finish_md, count);
+ }
+
+ return ret;
+}
+
+int SSL_get_verify_mode(const SSL *s) { return s->verify_mode; }
+
+int SSL_get_verify_depth(const SSL *s) {
+ return X509_VERIFY_PARAM_get_depth(s->param);
+}
+
+int (*SSL_get_verify_callback(const SSL *s))(int, X509_STORE_CTX *) {
+ return s->verify_callback;
+}
+
+int SSL_CTX_get_verify_mode(const SSL_CTX *ctx) { return ctx->verify_mode; }
+
+int SSL_CTX_get_verify_depth(const SSL_CTX *ctx) {
+ return X509_VERIFY_PARAM_get_depth(ctx->param);
+}
+
+int (*SSL_CTX_get_verify_callback(const SSL_CTX *ctx))(int, X509_STORE_CTX *) {
+ return ctx->default_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;
+ }
+}
+
+void SSL_set_verify_depth(SSL *s, int depth) {
+ X509_VERIFY_PARAM_set_depth(s->param, depth);
+}
+
+void SSL_set_read_ahead(SSL *s, int yes) { s->read_ahead = yes; }
+
+int SSL_get_read_ahead(const SSL *s) { return s->read_ahead; }
+
+int SSL_pending(const SSL *s) {
+ /* SSL_pending cannot work properly if read-ahead is enabled
+ * (SSL_[CTX_]ctrl(..., SSL_CTRL_SET_READ_AHEAD, 1, NULL)), and it is
+ * impossible to fix since SSL_pending cannot report errors that may be
+ * observed while scanning the new data. (Note that SSL_pending() is often
+ * used as a boolean value, so we'd better not return -1.). */
+ return s->method->ssl_pending(s);
+}
+
+X509 *SSL_get_peer_certificate(const SSL *s) {
+ X509 *r;
+
+ if (s == NULL || s->session == NULL) {
+ r = NULL;
+ } else {
+ r = s->session->peer;
+ }
+
+ if (r == NULL) {
+ return NULL;
+ }
+
+ return X509_up_ref(r);
+}
+
+STACK_OF(X509) * SSL_get_peer_cert_chain(const SSL *s) {
+ STACK_OF(X509) * r;
+
+ if (s == NULL || s->session == NULL || s->session->sess_cert == NULL) {
+ r = NULL;
+ } else {
+ r = s->session->sess_cert->cert_chain;
+ }
+
+ /* If we are a client, cert_chain includes the peer's own certificate; if we
+ * are a server, it does not. */
+ return r;
+}
+
+/* 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) {
+ OPENSSL_PUT_ERROR(SSL, SSL_CTX_check_private_key,
+ SSL_R_NO_CERTIFICATE_ASSIGNED);
+ return 0;
+ }
+
+ if (ctx->cert->key->privatekey == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_CTX_check_private_key,
+ SSL_R_NO_PRIVATE_KEY_ASSIGNED);
+ return 0;
+ }
+
+ return X509_check_private_key(ctx->cert->key->x509,
+ ctx->cert->key->privatekey);
+}
+
+/* Fix this function so that it takes an optional type parameter */
+int SSL_check_private_key(const SSL *ssl) {
+ if (ssl == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_check_private_key, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ if (ssl->cert == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_check_private_key,
+ SSL_R_NO_CERTIFICATE_ASSIGNED);
+ return 0;
+ }
+
+ if (ssl->cert->key->x509 == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_check_private_key,
+ SSL_R_NO_CERTIFICATE_ASSIGNED);
+ return 0;
+ }
+
+ if (ssl->cert->key->privatekey == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_check_private_key,
+ SSL_R_NO_PRIVATE_KEY_ASSIGNED);
+ return 0;
+ }
+
+ return X509_check_private_key(ssl->cert->key->x509,
+ ssl->cert->key->privatekey);
+}
+
+int SSL_accept(SSL *s) {
+ if (s->handshake_func == 0) {
+ /* Not properly initialized yet */
+ SSL_set_accept_state(s);
+ }
+
+ if (s->handshake_func != s->method->ssl_accept) {
+ OPENSSL_PUT_ERROR(SSL, SSL_connect, ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
+
+ return s->handshake_func(s);
+}
+
+int SSL_connect(SSL *s) {
+ if (s->handshake_func == 0) {
+ /* Not properly initialized yet */
+ SSL_set_connect_state(s);
+ }
+
+ if (s->handshake_func != s->method->ssl_connect) {
+ OPENSSL_PUT_ERROR(SSL, SSL_connect, ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
+
+ return s->handshake_func(s);
+}
+
+long SSL_get_default_timeout(const SSL *s) {
+ return SSL_DEFAULT_SESSION_TIMEOUT;
+}
+
+int SSL_read(SSL *s, void *buf, int num) {
+ if (s->handshake_func == 0) {
+ OPENSSL_PUT_ERROR(SSL, SSL_read, SSL_R_UNINITIALIZED);
+ return -1;
+ }
+
+ if (s->shutdown & SSL_RECEIVED_SHUTDOWN) {
+ s->rwstate = SSL_NOTHING;
+ return 0;
+ }
+
+ return s->method->ssl_read(s, buf, num);
+}
+
+int SSL_peek(SSL *s, void *buf, int num) {
+ if (s->handshake_func == 0) {
+ OPENSSL_PUT_ERROR(SSL, SSL_peek, SSL_R_UNINITIALIZED);
+ return -1;
+ }
+
+ if (s->shutdown & SSL_RECEIVED_SHUTDOWN) {
+ return 0;
+ }
+
+ return s->method->ssl_peek(s, buf, num);
+}
+
+int SSL_write(SSL *s, const void *buf, int num) {
+ if (s->handshake_func == 0) {
+ OPENSSL_PUT_ERROR(SSL, SSL_write, SSL_R_UNINITIALIZED);
+ return -1;
+ }
+
+ if (s->shutdown & SSL_SENT_SHUTDOWN) {
+ s->rwstate = SSL_NOTHING;
+ OPENSSL_PUT_ERROR(SSL, SSL_write, SSL_R_PROTOCOL_IS_SHUTDOWN);
+ return -1;
+ }
+
+ return s->method->ssl_write(s, buf, num);
+}
+
+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 == 0) {
+ OPENSSL_PUT_ERROR(SSL, SSL_shutdown, SSL_R_UNINITIALIZED);
+ return -1;
+ }
+
+ if (!SSL_in_init(s)) {
+ return s->method->ssl_shutdown(s);
+ }
+
+ return 1;
+}
+
+int SSL_renegotiate(SSL *s) {
+ if (s->renegotiate == 0) {
+ s->renegotiate = 1;
+ }
+
+ s->new_session = 1;
+ return s->method->ssl_renegotiate(s);
+}
+
+int SSL_renegotiate_abbreviated(SSL *s) {
+ if (s->renegotiate == 0) {
+ s->renegotiate = 1;
+ }
+
+ s->new_session = 0;
+ return s->method->ssl_renegotiate(s);
+}
+
+int SSL_renegotiate_pending(SSL *s) {
+ /* becomes true when negotiation is requested; false again once a handshake
+ * has finished */
+ return s->renegotiate != 0;
+}
+
+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:
+ if (larg < (long)dtls1_min_mtu()) {
+ return 0;
+ }
+ 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;
+ }
+ return 0;
+
+ case SSL_CTRL_CERT_FLAGS:
+ return s->cert->cert_flags |= larg;
+
+ case SSL_CTRL_CLEAR_CERT_FLAGS:
+ return s->cert->cert_flags &= ~larg;
+
+ case SSL_CTRL_GET_RAW_CIPHERLIST:
+ if (parg) {
+ if (s->cert->ciphers_raw == NULL) {
+ return 0;
+ }
+ *(uint8_t **)parg = s->cert->ciphers_raw;
+ return (int)s->cert->ciphers_rawlen;
+ }
+
+ /* Passing a NULL |parg| returns the size of a single
+ * cipher suite value. */
+ return 2;
+
+ default:
+ return s->method->ssl_ctrl(s, cmd, larg, parg);
+ }
+}
+
+long SSL_callback_ctrl(SSL *s, int cmd, void (*fp)(void)) {
+ switch (cmd) {
+ case SSL_CTRL_SET_MSG_CALLBACK:
+ s->msg_callback =
+ (void (*)(int write_p, int version, int content_type, const void *buf,
+ size_t len, SSL *ssl, void *arg))(fp);
+ return 1;
+
+ default:
+ return s->method->ssl_callback_ctrl(s, cmd, fp);
+ }
+}
+
+LHASH_OF(SSL_SESSION) *SSL_CTX_sessions(SSL_CTX *ctx) { return 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;
+
+ case SSL_CTRL_CERT_FLAGS:
+ return ctx->cert->cert_flags |= larg;
+
+ case SSL_CTRL_CLEAR_CERT_FLAGS:
+ return ctx->cert->cert_flags &= ~larg;
+
+ default:
+ return ctx->method->ssl_ctx_ctrl(ctx, cmd, larg, parg);
+ }
+}
+
+long SSL_CTX_callback_ctrl(SSL_CTX *ctx, int cmd, void (*fp)(void)) {
+ switch (cmd) {
+ case SSL_CTRL_SET_MSG_CALLBACK:
+ ctx->msg_callback =
+ (void (*)(int write_p, int version, int content_type, const void *buf,
+ size_t len, SSL *ssl, void *arg))(fp);
+ return 1;
+
+ default:
+ return ctx->method->ssl_ctx_callback_ctrl(ctx, cmd, fp);
+ }
+}
+
+int ssl_cipher_id_cmp(const void *in_a, const void *in_b) {
+ long l;
+ const SSL_CIPHER *a = in_a;
+ const SSL_CIPHER *b = in_b;
+ const long a_id = a->id;
+ const long b_id = b->id;
+
+ l = a_id - b_id;
+ if (l == 0L) {
+ return 0;
+ } else {
+ return (l > 0) ? 1 : -1;
+ }
+}
+
+int ssl_cipher_ptr_id_cmp(const SSL_CIPHER **ap, const SSL_CIPHER **bp) {
+ long l;
+ const long a_id = (*ap)->id;
+ const long b_id = (*bp)->id;
+
+ l = a_id - b_id;
+ if (l == 0) {
+ return 0;
+ } else {
+ return (l > 0) ? 1 : -1;
+ }
+}
+
+/* return a STACK of the ciphers available for the SSL and in order of
+ * preference */
+STACK_OF(SSL_CIPHER) * SSL_get_ciphers(const SSL *s) {
+ if (s == NULL) {
+ return NULL;
+ }
+
+ if (s->cipher_list != NULL) {
+ return s->cipher_list->ciphers;
+ }
+
+ if (s->version >= TLS1_1_VERSION && s->ctx != NULL &&
+ s->ctx->cipher_list_tls11 != NULL) {
+ return s->ctx->cipher_list_tls11->ciphers;
+ }
+
+ if (s->ctx != NULL && s->ctx->cipher_list != NULL) {
+ return s->ctx->cipher_list->ciphers;
+ }
+
+ return NULL;
+}
+
+/* return a STACK of the ciphers available for the SSL and in order of
+ * algorithm id */
+STACK_OF(SSL_CIPHER) * ssl_get_ciphers_by_id(SSL *s) {
+ if (s == NULL) {
+ return NULL;
+ }
+
+ if (s->cipher_list_by_id != NULL) {
+ return s->cipher_list_by_id;
+ }
+
+ if (s->ctx != NULL && s->ctx->cipher_list_by_id != NULL) {
+ return s->ctx->cipher_list_by_id;
+ }
+
+ return NULL;
+}
+
+/* The old interface to get the same thing as SSL_get_ciphers() */
+const char *SSL_get_cipher_list(const SSL *s, int n) {
+ const SSL_CIPHER *c;
+ STACK_OF(SSL_CIPHER) * sk;
+
+ if (s == NULL) {
+ return NULL;
+ }
+
+ sk = SSL_get_ciphers(s);
+ if (sk == NULL || n < 0 || (size_t)n >= sk_SSL_CIPHER_num(sk)) {
+ return NULL;
+ }
+
+ c = sk_SSL_CIPHER_value(sk, n);
+ if (c == NULL) {
+ return NULL;
+ }
+
+ return c->name;
+}
+
+/* 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) *sk;
+
+ sk = ssl_create_cipher_list(ctx->method, &ctx->cipher_list,
+ &ctx->cipher_list_by_id, str, ctx->cert);
+ /* 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 and
+ * ctx->cipher_list_by_id has been updated. */
+ if (sk == NULL) {
+ return 0;
+ } else if (sk_SSL_CIPHER_num(sk) == 0) {
+ OPENSSL_PUT_ERROR(SSL, SSL_CTX_set_cipher_list, SSL_R_NO_CIPHER_MATCH);
+ return 0;
+ }
+
+ return 1;
+}
+
+int SSL_CTX_set_cipher_list_tls11(SSL_CTX *ctx, const char *str) {
+ STACK_OF(SSL_CIPHER) *sk;
+
+ sk = ssl_create_cipher_list(ctx->method, &ctx->cipher_list_tls11, NULL, str,
+ ctx->cert);
+ if (sk == NULL) {
+ return 0;
+ } else if (sk_SSL_CIPHER_num(sk) == 0) {
+ OPENSSL_PUT_ERROR(SSL, SSL_CTX_set_cipher_list_tls11,
+ SSL_R_NO_CIPHER_MATCH);
+ return 0;
+ }
+
+ return 1;
+}
+
+/* specify the ciphers to be used by the SSL */
+int SSL_set_cipher_list(SSL *s, const char *str) {
+ STACK_OF(SSL_CIPHER) *sk;
+
+ sk = ssl_create_cipher_list(s->ctx->method, &s->cipher_list,
+ &s->cipher_list_by_id, str, s->cert);
+
+ /* see comment in SSL_CTX_set_cipher_list */
+ if (sk == NULL) {
+ return 0;
+ } else if (sk_SSL_CIPHER_num(sk) == 0) {
+ OPENSSL_PUT_ERROR(SSL, SSL_set_cipher_list, SSL_R_NO_CIPHER_MATCH);
+ return 0;
+ }
+
+ return 1;
+}
+
+int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk, uint8_t *p) {
+ size_t i;
+ const SSL_CIPHER *c;
+ CERT *ct = s->cert;
+ uint8_t *q;
+ /* Set disabled masks for this session */
+ ssl_set_client_disabled(s);
+
+ if (sk == NULL) {
+ return 0;
+ }
+ q = p;
+
+ for (i = 0; i < sk_SSL_CIPHER_num(sk); i++) {
+ c = sk_SSL_CIPHER_value(sk, i);
+ /* Skip disabled ciphers */
+ if (c->algorithm_ssl & ct->mask_ssl ||
+ c->algorithm_mkey & ct->mask_k ||
+ c->algorithm_auth & ct->mask_a) {
+ continue;
+ }
+ s2n(ssl3_get_cipher_value(c), p);
+ }
+
+ /* If all ciphers were disabled, return the error to the caller. */
+ if (p == q) {
+ return 0;
+ }
+
+ /* Add SCSVs. */
+ if (!s->renegotiate) {
+ s2n(SSL3_CK_SCSV & 0xffff, p);
+ }
+
+ if (s->fallback_scsv) {
+ s2n(SSL3_CK_FALLBACK_SCSV & 0xffff, p);
+ }
+
+ return p - q;
+}
+
+STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s, const CBS *cbs) {
+ CBS cipher_suites = *cbs;
+ const SSL_CIPHER *c;
+ STACK_OF(SSL_CIPHER) * sk;
+
+ if (s->s3) {
+ s->s3->send_connection_binding = 0;
+ }
+
+ if (CBS_len(&cipher_suites) % 2 != 0) {
+ OPENSSL_PUT_ERROR(SSL, ssl_bytes_to_cipher_list,
+ SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST);
+ return NULL;
+ }
+
+ sk = sk_SSL_CIPHER_new_null();
+ if (sk == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl_bytes_to_cipher_list, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (!CBS_stow(&cipher_suites, &s->cert->ciphers_raw,
+ &s->cert->ciphers_rawlen)) {
+ OPENSSL_PUT_ERROR(SSL, ssl_bytes_to_cipher_list, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ while (CBS_len(&cipher_suites) > 0) {
+ uint16_t cipher_suite;
+
+ if (!CBS_get_u16(&cipher_suites, &cipher_suite)) {
+ OPENSSL_PUT_ERROR(SSL, ssl_bytes_to_cipher_list, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ /* Check for SCSV. */
+ if (s->s3 && cipher_suite == (SSL3_CK_SCSV & 0xffff)) {
+ /* SCSV is fatal if renegotiating. */
+ if (s->renegotiate) {
+ OPENSSL_PUT_ERROR(SSL, ssl_bytes_to_cipher_list,
+ 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;
+ }
+
+ /* Check for FALLBACK_SCSV. */
+ if (s->s3 && cipher_suite == (SSL3_CK_FALLBACK_SCSV & 0xffff)) {
+ uint16_t max_version = ssl3_get_max_server_version(s);
+ if (SSL_IS_DTLS(s) ? (uint16_t)s->version > max_version
+ : (uint16_t)s->version < max_version) {
+ OPENSSL_PUT_ERROR(SSL, ssl_bytes_to_cipher_list,
+ SSL_R_INAPPROPRIATE_FALLBACK);
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL3_AD_INAPPROPRIATE_FALLBACK);
+ goto err;
+ }
+ continue;
+ }
+
+ c = ssl3_get_cipher_by_value(cipher_suite);
+ if (c != NULL && !sk_SSL_CIPHER_push(sk, c)) {
+ OPENSSL_PUT_ERROR(SSL, ssl_bytes_to_cipher_list, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+
+ return sk;
+
+err:
+ if (sk != NULL) {
+ sk_SSL_CIPHER_free(sk);
+ }
+ return NULL;
+}
+
+
+/* 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;
+}
+
+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;
+}
+
+void SSL_CTX_enable_signed_cert_timestamps(SSL_CTX *ctx) {
+ ctx->signed_cert_timestamps_enabled = 1;
+}
+
+int SSL_enable_signed_cert_timestamps(SSL *ssl) {
+ ssl->signed_cert_timestamps_enabled = 1;
+ return 1;
+}
+
+void SSL_CTX_enable_ocsp_stapling(SSL_CTX *ctx) {
+ ctx->ocsp_stapling_enabled = 1;
+}
+
+int SSL_enable_ocsp_stapling(SSL *ssl) {
+ ssl->ocsp_stapling_enabled = 1;
+ return 1;
+}
+
+void SSL_get0_signed_cert_timestamp_list(const SSL *ssl, const uint8_t **out,
+ size_t *out_len) {
+ SSL_SESSION *session = ssl->session;
+
+ *out_len = 0;
+ *out = NULL;
+ if (ssl->server || !session || !session->tlsext_signed_cert_timestamp_list) {
+ return;
+ }
+
+ *out = session->tlsext_signed_cert_timestamp_list;
+ *out_len = session->tlsext_signed_cert_timestamp_list_length;
+}
+
+void SSL_get0_ocsp_response(const SSL *ssl, const uint8_t **out,
+ size_t *out_len) {
+ SSL_SESSION *session = ssl->session;
+
+ *out_len = 0;
+ *out = NULL;
+ if (ssl->server || !session || !session->ocsp_response) {
+ return;
+ }
+ *out = session->ocsp_response;
+ *out_len = session->ocsp_response_length;
+}
+
+/* SSL_select_next_proto implements the standard protocol selection. It is
+ * expected that this function is called from the callback set by
+ * SSL_CTX_set_next_proto_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.
+ *
+ * The current, but experimental algorithm for selecting the protocol is:
+ *
+ * 1) If the server doesn't support NPN then this is indicated to the
+ * callback. In this case, the client application has to abort the connection
+ * or have a default application level protocol.
+ *
+ * 2) If the server supports NPN, but advertises an empty list then the
+ * client selects the first protcol in its list, but indicates via the
+ * API that this fallback case was enacted.
+ *
+ * 3) Otherwise, the client finds the first protocol in the server's list
+ * that it supports and selects this protocol. This is because it's
+ * assumed that the server has better information about which protocol
+ * a client should use.
+ *
+ * 4) If the client doesn't support any of the server's advertised
+ * protocols, then this is treated the same as case 2.
+ *
+ * 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(uint8_t **out, uint8_t *outlen, const uint8_t *server,
+ unsigned int server_len, const uint8_t *client,
+ unsigned int client_len) {
+ unsigned int i, j;
+ const uint8_t *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 = (uint8_t *)result + 1;
+ *outlen = result[0];
+ return status;
+}
+
+/* SSL_get0_next_proto_negotiated sets *data and *len to point to the client's
+ * requested protocol for this connection and returns 0. If the client didn't
+ * request any protocol, then *data is set to NULL.
+ *
+ * Note that the client can request any protocol it chooses. The value returned
+ * from this function need not be a member of the list of supported protocols
+ * provided by the callback. */
+void SSL_get0_next_proto_negotiated(const SSL *s, const uint8_t **data,
+ unsigned *len) {
+ *data = s->next_proto_negotiated;
+ if (!*data) {
+ *len = 0;
+ } else {
+ *len = s->next_proto_negotiated_len;
+ }
+}
+
+/* SSL_CTX_set_next_protos_advertised_cb sets a callback that is called when a
+ * TLS server needs a list of supported protocols for Next Protocol
+ * Negotiation. The returned list must be in wire format. The list is returned
+ * by setting |out| to point to it and |outlen| to its length. This memory will
+ * not be modified, but one should assume that the SSL* keeps a reference to
+ * it.
+ *
+ * The callback should return SSL_TLSEXT_ERR_OK if it wishes to advertise.
+ * Otherwise, no such extension will be included in the ServerHello. */
+void SSL_CTX_set_next_protos_advertised_cb(
+ SSL_CTX *ctx,
+ int (*cb)(SSL *ssl, const uint8_t **out, unsigned int *outlen, void *arg),
+ void *arg) {
+ ctx->next_protos_advertised_cb = cb;
+ ctx->next_protos_advertised_cb_arg = arg;
+}
+
+/* SSL_CTX_set_next_proto_select_cb sets a callback that is called when a
+ * client needs to select a protocol from the server's provided list. |out|
+ * must be set to point to the selected protocol (which may be within |in|).
+ * The length of the protocol name must be written into |outlen|. The server's
+ * advertised protocols are provided in |in| and |inlen|. The callback can
+ * assume that |in| is syntactically valid.
+ *
+ * The client must select a protocol. It is fatal to the connection if this
+ * callback returns a value other than SSL_TLSEXT_ERR_OK.
+ */
+void SSL_CTX_set_next_proto_select_cb(
+ SSL_CTX *ctx, int (*cb)(SSL *s, uint8_t **out, uint8_t *outlen,
+ const uint8_t *in, unsigned int inlen, void *arg),
+ void *arg) {
+ ctx->next_proto_select_cb = cb;
+ ctx->next_proto_select_cb_arg = arg;
+}
+
+/* SSL_CTX_set_alpn_protos sets the ALPN protocol list on |ctx| to |protos|.
+ * |protos| 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 uint8_t *protos,
+ unsigned protos_len) {
+ if (ctx->alpn_client_proto_list) {
+ OPENSSL_free(ctx->alpn_client_proto_list);
+ }
+
+ ctx->alpn_client_proto_list = BUF_memdup(protos, protos_len);
+ if (!ctx->alpn_client_proto_list) {
+ return 1;
+ }
+ ctx->alpn_client_proto_list_len = protos_len;
+
+ return 0;
+}
+
+/* SSL_set_alpn_protos sets the ALPN protocol list on |ssl| to |protos|.
+ * |protos| 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 uint8_t *protos, unsigned protos_len) {
+ if (ssl->alpn_client_proto_list) {
+ OPENSSL_free(ssl->alpn_client_proto_list);
+ }
+
+ ssl->alpn_client_proto_list = BUF_memdup(protos, protos_len);
+ if (!ssl->alpn_client_proto_list) {
+ return 1;
+ }
+ ssl->alpn_client_proto_list_len = protos_len;
+
+ return 0;
+}
+
+/* SSL_CTX_set_alpn_select_cb sets a callback function on |ctx| 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 uint8_t **out,
+ uint8_t *outlen, const uint8_t *in,
+ unsigned int inlen, void *arg),
+ void *arg) {
+ ctx->alpn_select_cb = cb;
+ ctx->alpn_select_cb_arg = arg;
+}
+
+/* SSL_get0_alpn_selected gets the selected ALPN protocol (if any) from |ssl|.
+ * 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 uint8_t **data,
+ unsigned *len) {
+ *data = NULL;
+ if (ssl->s3) {
+ *data = ssl->s3->alpn_selected;
+ }
+ if (*data == NULL) {
+ *len = 0;
+ } else {
+ *len = ssl->s3->alpn_selected_len;
+ }
+}
+
+int SSL_export_keying_material(SSL *s, uint8_t *out, size_t olen,
+ const char *label, size_t llen, const uint8_t *p,
+ size_t plen, int use_context) {
+ if (s->version < TLS1_VERSION) {
+ return -1;
+ }
+
+ return s->enc_method->export_keying_material(s, out, olen, label, llen, p,
+ plen, use_context);
+}
+
+static uint32_t ssl_session_hash(const SSL_SESSION *a) {
+ uint32_t hash =
+ ((uint32_t)a->session_id[0]) ||
+ ((uint32_t)a->session_id[1] << 8) ||
+ ((uint32_t)a->session_id[2] << 16) ||
+ ((uint32_t)a->session_id[3] << 24);
+
+ return hash;
+}
+
+/* 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;
+ }
+
+ return memcmp(a->session_id, b->session_id, a->session_id_length);
+}
+
+SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth) {
+ SSL_CTX *ret = NULL;
+
+ if (meth == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_CTX_new, SSL_R_NULL_SSL_METHOD_PASSED);
+ return NULL;
+ }
+
+ if (SSL_get_ex_data_X509_STORE_CTX_idx() < 0) {
+ OPENSSL_PUT_ERROR(SSL, SSL_CTX_new, SSL_R_X509_VERIFICATION_SETUP_PROBLEMS);
+ goto err;
+ }
+
+ ret = (SSL_CTX *)OPENSSL_malloc(sizeof(SSL_CTX));
+ if (ret == NULL) {
+ goto err;
+ }
+
+ memset(ret, 0, sizeof(SSL_CTX));
+
+ ret->method = meth->method;
+
+ 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_DEFAULT_SESSION_TIMEOUT;
+
+ ret->new_session_cb = 0;
+ ret->remove_session_cb = 0;
+ ret->get_session_cb = 0;
+ ret->generate_session_id = 0;
+
+ memset((char *)&ret->stats, 0, sizeof(ret->stats));
+
+ ret->references = 1;
+ ret->quiet_shutdown = 0;
+
+ ret->info_callback = NULL;
+
+ ret->app_verify_callback = 0;
+ ret->app_verify_arg = NULL;
+
+ ret->max_cert_list = SSL_MAX_CERT_LIST_DEFAULT;
+ ret->read_ahead = 0;
+ ret->msg_callback = 0;
+ ret->msg_callback_arg = NULL;
+ ret->verify_mode = SSL_VERIFY_NONE;
+ ret->sid_ctx_length = 0;
+ ret->default_verify_callback = NULL;
+ ret->cert = ssl_cert_new();
+ if (ret->cert == NULL) {
+ goto err;
+ }
+
+ ret->default_passwd_callback = 0;
+ ret->default_passwd_callback_userdata = NULL;
+ ret->client_cert_cb = 0;
+ ret->app_gen_cookie_cb = 0;
+ ret->app_verify_cookie_cb = 0;
+
+ ret->sessions = lh_SSL_SESSION_new(ssl_session_hash, ssl_session_cmp);
+ 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,
+ &ret->cipher_list_by_id, SSL_DEFAULT_CIPHER_LIST,
+ ret->cert);
+ if (ret->cipher_list == NULL ||
+ sk_SSL_CIPHER_num(ret->cipher_list->ciphers) <= 0) {
+ OPENSSL_PUT_ERROR(SSL, SSL_CTX_new, SSL_R_LIBRARY_HAS_NO_CIPHERS);
+ goto err2;
+ }
+
+ ret->param = X509_VERIFY_PARAM_new();
+ if (!ret->param) {
+ goto err;
+ }
+
+ ret->client_CA = sk_X509_NAME_new_null();
+ if (ret->client_CA == 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 */
+ if (!RAND_bytes(ret->tlsext_tick_key_name, 16) ||
+ !RAND_bytes(ret->tlsext_tick_hmac_key, 16) ||
+ !RAND_bytes(ret->tlsext_tick_aes_key, 16)) {
+ ret->options |= SSL_OP_NO_TICKET;
+ }
+
+ ret->tlsext_status_cb = 0;
+ ret->tlsext_status_arg = NULL;
+
+ ret->next_protos_advertised_cb = 0;
+ ret->next_proto_select_cb = 0;
+ ret->psk_identity_hint = NULL;
+ ret->psk_client_callback = NULL;
+ ret->psk_server_callback = NULL;
+
+ /* Default is to connect to non-RI servers. When RI is more widely deployed
+ * might change this. */
+ ret->options |= SSL_OP_LEGACY_SERVER_CONNECT;
+
+ /* Lock the SSL_CTX to the specified version, for compatibility with legacy
+ * uses of SSL_METHOD. */
+ if (meth->version != 0) {
+ SSL_CTX_set_max_version(ret, meth->version);
+ SSL_CTX_set_min_version(ret, meth->version);
+ }
+
+ return ret;
+
+err:
+ OPENSSL_PUT_ERROR(SSL, SSL_CTX_new, ERR_R_MALLOC_FAILURE);
+err2:
+ if (ret != NULL) {
+ SSL_CTX_free(ret);
+ }
+ return NULL;
+}
+
+void SSL_CTX_free(SSL_CTX *a) {
+ int i;
+
+ if (a == NULL) {
+ return;
+ }
+
+ i = CRYPTO_add(&a->references, -1, CRYPTO_LOCK_SSL_CTX);
+ if (i > 0) {
+ return;
+ }
+
+ if (a->param) {
+ X509_VERIFY_PARAM_free(a->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 (a->sessions != NULL) {
+ SSL_CTX_flush_sessions(a, 0);
+ }
+
+ CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_CTX, a, &a->ex_data);
+
+ if (a->sessions != NULL) {
+ lh_SSL_SESSION_free(a->sessions);
+ }
+ if (a->cert_store != NULL) {
+ X509_STORE_free(a->cert_store);
+ }
+ if (a->cipher_list != NULL) {
+ ssl_cipher_preference_list_free(a->cipher_list);
+ }
+ if (a->cipher_list_by_id != NULL) {
+ sk_SSL_CIPHER_free(a->cipher_list_by_id);
+ }
+ if (a->cipher_list_tls11 != NULL) {
+ ssl_cipher_preference_list_free(a->cipher_list_tls11);
+ }
+ if (a->cert != NULL) {
+ ssl_cert_free(a->cert);
+ }
+ if (a->client_CA != NULL) {
+ sk_X509_NAME_pop_free(a->client_CA, X509_NAME_free);
+ }
+ if (a->extra_certs != NULL) {
+ sk_X509_pop_free(a->extra_certs, X509_free);
+ }
+ if (a->srtp_profiles) {
+ sk_SRTP_PROTECTION_PROFILE_free(a->srtp_profiles);
+ }
+ if (a->psk_identity_hint) {
+ OPENSSL_free(a->psk_identity_hint);
+ }
+ if (a->tlsext_ecpointformatlist) {
+ OPENSSL_free(a->tlsext_ecpointformatlist);
+ }
+ if (a->tlsext_ellipticcurvelist) {
+ OPENSSL_free(a->tlsext_ellipticcurvelist);
+ }
+ if (a->alpn_client_proto_list != NULL) {
+ OPENSSL_free(a->alpn_client_proto_list);
+ }
+ if (a->tlsext_channel_id_private) {
+ EVP_PKEY_free(a->tlsext_channel_id_private);
+ }
+ if (a->keylog_bio) {
+ BIO_free(a->keylog_bio);
+ }
+
+ OPENSSL_free(a);
+}
+
+void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb) {
+ ctx->default_passwd_callback = cb;
+}
+
+void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx, void *u) {
+ ctx->default_passwd_callback_userdata = u;
+}
+
+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;
+}
+
+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;
+}
+
+void SSL_CTX_set_verify_depth(SSL_CTX *ctx, int depth) {
+ X509_VERIFY_PARAM_set_depth(ctx->param, depth);
+}
+
+void SSL_CTX_set_cert_cb(SSL_CTX *c, int (*cb)(SSL *ssl, void *arg),
+ void *arg) {
+ ssl_cert_set_cert_cb(c->cert, cb, arg);
+}
+
+void SSL_set_cert_cb(SSL *s, int (*cb)(SSL *ssl, void *arg), void *arg) {
+ ssl_cert_set_cert_cb(s->cert, cb, arg);
+}
+
+static int ssl_has_key(SSL *s, size_t idx) {
+ CERT_PKEY *cpk = &s->cert->pkeys[idx];
+ return cpk->x509 && cpk->privatekey;
+}
+
+void ssl_get_compatible_server_ciphers(SSL *s, unsigned long *out_mask_k,
+ unsigned long *out_mask_a) {
+ CERT *c = s->cert;
+ int rsa_enc, rsa_sign, dh_tmp;
+ unsigned long mask_k, mask_a;
+ int have_ecc_cert, ecdsa_ok;
+ int have_ecdh_tmp;
+ X509 *x;
+
+ if (c == NULL) {
+ /* TODO(davidben): Is this codepath possible? */
+ *out_mask_k = 0;
+ *out_mask_a = 0;
+ return;
+ }
+
+ dh_tmp = (c->dh_tmp != NULL || c->dh_tmp_cb != NULL);
+
+ have_ecdh_tmp = (c->ecdh_tmp || c->ecdh_tmp_cb || c->ecdh_tmp_auto);
+ rsa_enc = ssl_has_key(s, SSL_PKEY_RSA_ENC);
+ rsa_sign = ssl_has_key(s, SSL_PKEY_RSA_SIGN);
+ have_ecc_cert = ssl_has_key(s, SSL_PKEY_ECC);
+ mask_k = 0;
+ mask_a = 0;
+
+ if (rsa_enc) {
+ mask_k |= SSL_kRSA;
+ }
+ if (dh_tmp) {
+ mask_k |= SSL_kEDH;
+ }
+ if (rsa_enc || rsa_sign) {
+ mask_a |= SSL_aRSA;
+ }
+
+ mask_a |= SSL_aNULL;
+
+ /* An ECC certificate may be usable for ECDSA cipher suites depending on the
+ * key usage extension and on the client's curve preferences. */
+ if (have_ecc_cert) {
+ x = c->pkeys[SSL_PKEY_ECC].x509;
+ /* This call populates extension flags (ex_flags). */
+ X509_check_purpose(x, -1, 0);
+ ecdsa_ok = (x->ex_flags & EXFLAG_KUSAGE)
+ ? (x->ex_kusage & X509v3_KU_DIGITAL_SIGNATURE)
+ : 1;
+ if (!tls1_check_ec_cert(s, x)) {
+ ecdsa_ok = 0;
+ }
+ if (ecdsa_ok) {
+ mask_a |= SSL_aECDSA;
+ }
+ }
+
+ /* If we are considering an ECC cipher suite that uses an ephemeral EC
+ * key, check it. */
+ if (have_ecdh_tmp && tls1_check_ec_tmp_key(s)) {
+ mask_k |= SSL_kEECDH;
+ }
+
+ /* PSK requires a server callback. */
+ if (s->psk_server_callback != NULL) {
+ mask_k |= SSL_kPSK;
+ mask_a |= SSL_aPSK;
+ }
+
+ *out_mask_k = mask_k;
+ *out_mask_a = mask_a;
+}
+
+/* This handy macro borrowed from crypto/x509v3/v3_purp.c */
+#define ku_reject(x, usage) \
+ (((x)->ex_flags & EXFLAG_KUSAGE) && !((x)->ex_kusage & (usage)))
+
+int ssl_check_srvr_ecc_cert_and_alg(X509 *x, SSL *s) {
+ unsigned long alg_a;
+ int signature_nid = 0, md_nid = 0, pk_nid = 0;
+ const SSL_CIPHER *cs = s->s3->tmp.new_cipher;
+
+ alg_a = cs->algorithm_auth;
+
+ /* This call populates the ex_flags field correctly */
+ X509_check_purpose(x, -1, 0);
+ if (x->sig_alg && x->sig_alg->algorithm) {
+ signature_nid = OBJ_obj2nid(x->sig_alg->algorithm);
+ OBJ_find_sigid_algs(signature_nid, &md_nid, &pk_nid);
+ }
+ if (alg_a & SSL_aECDSA) {
+ /* key usage, if present, must allow signing */
+ if (ku_reject(x, X509v3_KU_DIGITAL_SIGNATURE)) {
+ OPENSSL_PUT_ERROR(SSL, ssl_check_srvr_ecc_cert_and_alg,
+ SSL_R_ECC_CERT_NOT_FOR_SIGNING);
+ return 0;
+ }
+ }
+
+ return 1; /* all checks are ok */
+}
+
+static int ssl_get_server_cert_index(const SSL *s) {
+ int idx;
+ idx = ssl_cipher_get_cert_index(s->s3->tmp.new_cipher);
+ if (idx == SSL_PKEY_RSA_ENC && !s->cert->pkeys[SSL_PKEY_RSA_ENC].x509) {
+ idx = SSL_PKEY_RSA_SIGN;
+ }
+ if (idx == -1) {
+ OPENSSL_PUT_ERROR(SSL, ssl_get_server_cert_index, ERR_R_INTERNAL_ERROR);
+ }
+ return idx;
+}
+
+CERT_PKEY *ssl_get_server_send_pkey(const SSL *s) {
+ int i = ssl_get_server_cert_index(s);
+
+ /* This may or may not be an error. */
+ if (i < 0) {
+ return NULL;
+ }
+
+ /* May be NULL. */
+ return &s->cert->pkeys[i];
+}
+
+EVP_PKEY *ssl_get_sign_pkey(SSL *s, const SSL_CIPHER *cipher) {
+ unsigned long alg_a;
+ CERT *c;
+ int idx = -1;
+
+ alg_a = cipher->algorithm_auth;
+ c = s->cert;
+
+ if (alg_a & SSL_aRSA) {
+ if (c->pkeys[SSL_PKEY_RSA_SIGN].privatekey != NULL) {
+ idx = SSL_PKEY_RSA_SIGN;
+ } else if (c->pkeys[SSL_PKEY_RSA_ENC].privatekey != NULL) {
+ idx = SSL_PKEY_RSA_ENC;
+ }
+ } else if ((alg_a & SSL_aECDSA) &&
+ (c->pkeys[SSL_PKEY_ECC].privatekey != NULL)) {
+ idx = SSL_PKEY_ECC;
+ }
+
+ if (idx == -1) {
+ OPENSSL_PUT_ERROR(SSL, ssl_get_sign_pkey, ERR_R_INTERNAL_ERROR);
+ return NULL;
+ }
+
+ return c->pkeys[idx].privatekey;
+}
+
+void ssl_update_cache(SSL *s, int mode) {
+ int i;
+
+ /* If the session_id_length is 0, we are not supposed to cache it, and it
+ * would be rather hard to do anyway :-) */
+ if (s->session->session_id_length == 0) {
+ return;
+ }
+
+ i = s->initial_ctx->session_cache_mode;
+ if ((i & mode) && !s->hit &&
+ ((i & SSL_SESS_CACHE_NO_INTERNAL_STORE) ||
+ SSL_CTX_add_session(s->initial_ctx, s->session)) &&
+ s->initial_ctx->new_session_cb != NULL) {
+ CRYPTO_add(&s->session->references, 1, CRYPTO_LOCK_SSL_SESSION);
+ if (!s->initial_ctx->new_session_cb(s, s->session)) {
+ SSL_SESSION_free(s->session);
+ }
+ }
+
+ /* auto flush every 255 connections */
+ if ((!(i & SSL_SESS_CACHE_NO_AUTO_CLEAR)) && ((i & mode) == mode)) {
+ if ((((mode & SSL_SESS_CACHE_CLIENT)
+ ? s->initial_ctx->stats.sess_connect_good
+ : s->initial_ctx->stats.sess_accept_good) &
+ 0xff) == 0xff) {
+ SSL_CTX_flush_sessions(s->initial_ctx, (unsigned long)time(NULL));
+ }
+ }
+}
+
+int SSL_get_error(const SSL *s, int i) {
+ int reason;
+ unsigned long l;
+ 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 */
+ l = ERR_peek_error();
+ if (l != 0) {
+ if (ERR_GET_LIB(l) == ERR_LIB_SYS) {
+ return SSL_ERROR_SYSCALL;
+ }
+ return SSL_ERROR_SSL;
+ }
+
+ if (i == 0) {
+ if ((s->shutdown & SSL_RECEIVED_SHUTDOWN) &&
+ (s->s3->warn_alert == SSL_AD_CLOSE_NOTIFY)) {
+ /* The socket was cleanly shut down with a close_notify. */
+ return SSL_ERROR_ZERO_RETURN;
+ }
+ /* An EOF was observed which violates the protocol, and the underlying
+ * transport does not participate in the error queue. Bubble up to the
+ * caller. */
+ return SSL_ERROR_SYSCALL;
+ }
+
+ if (SSL_want_session(s)) {
+ return SSL_ERROR_PENDING_SESSION;
+ }
+
+ if (SSL_want_certificate(s)) {
+ return SSL_ERROR_PENDING_CERTIFICATE;
+ }
+
+ if (SSL_want_read(s)) {
+ bio = SSL_get_rbio(s);
+ if (BIO_should_read(bio)) {
+ return SSL_ERROR_WANT_READ;
+ }
+
+ 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;
+ }
+
+ if (BIO_should_io_special(bio)) {
+ reason = BIO_get_retry_reason(bio);
+ if (reason == BIO_RR_CONNECT) {
+ return SSL_ERROR_WANT_CONNECT;
+ }
+
+ if (reason == BIO_RR_ACCEPT) {
+ return SSL_ERROR_WANT_ACCEPT;
+ }
+
+ 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;
+ }
+
+ if (BIO_should_read(bio)) {
+ /* See above (SSL_want_read(s) with BIO_should_write(bio)) */
+ return SSL_ERROR_WANT_READ;
+ }
+
+ if (BIO_should_io_special(bio)) {
+ reason = BIO_get_retry_reason(bio);
+ if (reason == BIO_RR_CONNECT) {
+ return SSL_ERROR_WANT_CONNECT;
+ }
+
+ if (reason == BIO_RR_ACCEPT) {
+ return SSL_ERROR_WANT_ACCEPT;
+ }
+
+ return SSL_ERROR_SYSCALL;
+ }
+ }
+
+ if (SSL_want_x509_lookup(s)) {
+ return SSL_ERROR_WANT_X509_LOOKUP;
+ }
+
+ if (SSL_want_channel_id_lookup(s)) {
+ return SSL_ERROR_WANT_CHANNEL_ID_LOOKUP;
+ }
+
+ return SSL_ERROR_SYSCALL;
+}
+
+int SSL_do_handshake(SSL *s) {
+ int ret = 1;
+
+ if (s->handshake_func == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_do_handshake, SSL_R_CONNECTION_TYPE_NOT_SET);
+ return -1;
+ }
+
+ s->method->ssl_renegotiate_check(s);
+
+ if (SSL_in_init(s)) {
+ ret = s->handshake_func(s);
+ }
+ return ret;
+}
+
+void SSL_set_accept_state(SSL *s) {
+ s->server = 1;
+ s->shutdown = 0;
+ s->state = SSL_ST_ACCEPT | SSL_ST_BEFORE;
+ s->handshake_func = s->method->ssl_accept;
+ /* clear the current cipher */
+ ssl_clear_cipher_ctx(s);
+}
+
+void SSL_set_connect_state(SSL *s) {
+ s->server = 0;
+ s->shutdown = 0;
+ s->state = SSL_ST_CONNECT | SSL_ST_BEFORE;
+ s->handshake_func = s->method->ssl_connect;
+ /* clear the current cipher */
+ ssl_clear_cipher_ctx(s);
+}
+
+int ssl_undefined_function(SSL *s) {
+ OPENSSL_PUT_ERROR(SSL, ssl_undefined_function,
+ ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return 0;
+}
+
+int ssl_undefined_void_function(void) {
+ OPENSSL_PUT_ERROR(SSL, ssl_undefined_void_function,
+ ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return 0;
+}
+
+int ssl_undefined_const_function(const SSL *s) {
+ OPENSSL_PUT_ERROR(SSL, ssl_undefined_const_function,
+ ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return 0;
+}
+
+static const char *ssl_get_version(int version) {
+ switch (version) {
+ case TLS1_2_VERSION:
+ return "TLSv1.2";
+
+ case TLS1_1_VERSION:
+ return "TLSv1.1";
+
+ case TLS1_VERSION:
+ return "TLSv1";
+
+ case SSL3_VERSION:
+ return "SSLv3";
+
+ default:
+ return "unknown";
+ }
+}
+
+const char *SSL_get_version(const SSL *s) {
+ return ssl_get_version(s->version);
+}
+
+const char *SSL_SESSION_get_version(const SSL_SESSION *sess) {
+ return ssl_get_version(sess->ssl_version);
+}
+
+void ssl_clear_cipher_ctx(SSL *s) {
+ if (s->aead_read_ctx != NULL) {
+ EVP_AEAD_CTX_cleanup(&s->aead_read_ctx->ctx);
+ OPENSSL_free(s->aead_read_ctx);
+ s->aead_read_ctx = NULL;
+ }
+
+ if (s->aead_write_ctx != NULL) {
+ EVP_AEAD_CTX_cleanup(&s->aead_write_ctx->ctx);
+ OPENSSL_free(s->aead_write_ctx);
+ s->aead_write_ctx = NULL;
+ }
+}
+
+X509 *SSL_get_certificate(const SSL *s) {
+ if (s->cert != NULL) {
+ return s->cert->key->x509;
+ }
+
+ return NULL;
+}
+
+EVP_PKEY *SSL_get_privatekey(const SSL *s) {
+ if (s->cert != NULL) {
+ return s->cert->key->privatekey;
+ }
+
+ return NULL;
+}
+
+X509 *SSL_CTX_get0_certificate(const SSL_CTX *ctx) {
+ if (ctx->cert != NULL) {
+ return ctx->cert->key->x509;
+ }
+
+ return NULL;
+}
+
+EVP_PKEY *SSL_CTX_get0_privatekey(const SSL_CTX *ctx) {
+ if (ctx->cert != NULL) {
+ return ctx->cert->key->privatekey;
+ }
+
+ return NULL;
+}
+
+const SSL_CIPHER *SSL_get_current_cipher(const SSL *s) {
+ if (s->session != NULL && s->session->cipher != NULL) {
+ return s->session->cipher;
+ }
+
+ return NULL;
+}
+
+const void *SSL_get_current_compression(SSL *s) { return NULL; }
+
+const void *SSL_get_current_expansion(SSL *s) { return NULL; }
+
+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);
+ }
+ }
+
+ BIO_reset(bbio);
+ if (!BIO_set_read_buffer_size(bbio, 1)) {
+ OPENSSL_PUT_ERROR(SSL, ssl_init_wbio_buffer, 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->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;
+}
+
+int SSL_CTX_get_quiet_shutdown(const SSL_CTX *ctx) {
+ return ctx->quiet_shutdown;
+}
+
+void SSL_set_quiet_shutdown(SSL *s, int mode) { s->quiet_shutdown = mode; }
+
+int SSL_get_quiet_shutdown(const SSL *s) { return s->quiet_shutdown; }
+
+void SSL_set_shutdown(SSL *s, int mode) { s->shutdown = mode; }
+
+int SSL_get_shutdown(const SSL *s) { return s->shutdown; }
+
+int SSL_version(const SSL *s) { return s->version; }
+
+SSL_CTX *SSL_get_SSL_CTX(const SSL *ssl) { return ssl->ctx; }
+
+SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX *ctx) {
+ if (ssl->ctx == ctx) {
+ return ssl->ctx;
+ }
+
+ if (ctx == NULL) {
+ ctx = ssl->initial_ctx;
+ }
+
+ if (ssl->cert != NULL) {
+ ssl_cert_free(ssl->cert);
+ }
+
+ ssl->cert = ssl_cert_dup(ctx->cert);
+ CRYPTO_add(&ctx->references, 1, CRYPTO_LOCK_SSL_CTX);
+ if (ssl->ctx != NULL) {
+ SSL_CTX_free(ssl->ctx); /* decrement reference count */
+ }
+ ssl->ctx = ctx;
+
+ ssl->sid_ctx_length = ctx->sid_ctx_length;
+ assert(ssl->sid_ctx_length <= sizeof(ssl->sid_ctx));
+ memcpy(ssl->sid_ctx, ctx->sid_ctx, sizeof(ssl->sid_ctx));
+
+ return ssl->ctx;
+}
+
+int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx) {
+ return X509_STORE_set_default_paths(ctx->cert_store);
+}
+
+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);
+}
+
+void SSL_set_info_callback(SSL *ssl,
+ void (*cb)(const SSL *ssl, int type, int val)) {
+ ssl->info_callback = cb;
+}
+
+void (*SSL_get_info_callback(const SSL *ssl))(const SSL * /*ssl*/, int /*type*/,
+ int /*val*/) {
+ return ssl->info_callback;
+}
+
+int SSL_state(const SSL *ssl) { return ssl->state; }
+
+void SSL_set_state(SSL *ssl, int state) { ssl->state = state; }
+
+void SSL_set_verify_result(SSL *ssl, long arg) { ssl->verify_result = arg; }
+
+long SSL_get_verify_result(const SSL *ssl) { return ssl->verify_result; }
+
+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);
+}
+
+int SSL_set_ex_data(SSL *s, int idx, void *arg) {
+ return CRYPTO_set_ex_data(&s->ex_data, idx, arg);
+}
+
+void *SSL_get_ex_data(const SSL *s, int idx) {
+ return CRYPTO_get_ex_data(&s->ex_data, 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) {
+ return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_CTX, argl, argp, new_func,
+ dup_func, free_func);
+}
+
+int SSL_CTX_set_ex_data(SSL_CTX *s, int idx, void *arg) {
+ return CRYPTO_set_ex_data(&s->ex_data, idx, arg);
+}
+
+void *SSL_CTX_get_ex_data(const SSL_CTX *s, int idx) {
+ return CRYPTO_get_ex_data(&s->ex_data, idx);
+}
+
+int ssl_ok(SSL *s) { return 1; }
+
+X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *ctx) {
+ return ctx->cert_store;
+}
+
+void SSL_CTX_set_cert_store(SSL_CTX *ctx, X509_STORE *store) {
+ if (ctx->cert_store != NULL) {
+ X509_STORE_free(ctx->cert_store);
+ }
+ ctx->cert_store = store;
+}
+
+int SSL_want(const SSL *s) { return s->rwstate; }
+
+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);
+}
+
+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);
+}
+
+void SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx,
+ DH *(*dh)(SSL *ssl, int is_export,
+ int keylength)) {
+ SSL_CTX_callback_ctrl(ctx, SSL_CTRL_SET_TMP_DH_CB, (void (*)(void))dh);
+}
+
+void SSL_set_tmp_dh_callback(SSL *ssl, DH *(*dh)(SSL *ssl, int is_export,
+ int keylength)) {
+ SSL_callback_ctrl(ssl, SSL_CTRL_SET_TMP_DH_CB, (void (*)(void))dh);
+}
+
+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);
+}
+
+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);
+}
+
+int SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx, const char *identity_hint) {
+ if (identity_hint != NULL && strlen(identity_hint) > PSK_MAX_IDENTITY_LEN) {
+ OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_psk_identity_hint,
+ SSL_R_DATA_LENGTH_TOO_LONG);
+ return 0;
+ }
+
+ if (ctx->psk_identity_hint != NULL) {
+ OPENSSL_free(ctx->psk_identity_hint);
+ }
+
+ if (identity_hint != NULL) {
+ ctx->psk_identity_hint = BUF_strdup(identity_hint);
+ if (ctx->psk_identity_hint == NULL) {
+ return 0;
+ }
+ } else {
+ ctx->psk_identity_hint = NULL;
+ }
+
+ return 1;
+}
+
+int SSL_use_psk_identity_hint(SSL *s, const char *identity_hint) {
+ if (s == NULL) {
+ return 0;
+ }
+
+ if (identity_hint != NULL && strlen(identity_hint) > PSK_MAX_IDENTITY_LEN) {
+ OPENSSL_PUT_ERROR(SSL, SSL_use_psk_identity_hint,
+ SSL_R_DATA_LENGTH_TOO_LONG);
+ return 0;
+ }
+
+ /* Clear currently configured hint, if any. */
+ if (s->psk_identity_hint != NULL) {
+ OPENSSL_free(s->psk_identity_hint);
+ s->psk_identity_hint = NULL;
+ }
+
+ if (identity_hint != NULL) {
+ s->psk_identity_hint = BUF_strdup(identity_hint);
+ if (s->psk_identity_hint == NULL) {
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+const char *SSL_get_psk_identity_hint(const SSL *s) {
+ if (s == NULL) {
+ return NULL;
+ }
+ return s->psk_identity_hint;
+}
+
+const char *SSL_get_psk_identity(const SSL *s) {
+ if (s == NULL || s->session == NULL) {
+ return NULL;
+ }
+
+ return s->session->psk_identity;
+}
+
+void SSL_set_psk_client_callback(
+ SSL *s, unsigned int (*cb)(SSL *ssl, const char *hint, char *identity,
+ unsigned int max_identity_len, uint8_t *psk,
+ unsigned int max_psk_len)) {
+ s->psk_client_callback = cb;
+}
+
+void SSL_CTX_set_psk_client_callback(
+ SSL_CTX *ctx, unsigned int (*cb)(SSL *ssl, const char *hint, char *identity,
+ unsigned int max_identity_len,
+ uint8_t *psk, unsigned int max_psk_len)) {
+ ctx->psk_client_callback = cb;
+}
+
+void SSL_set_psk_server_callback(
+ SSL *s, unsigned int (*cb)(SSL *ssl, const char *identity, uint8_t *psk,
+ unsigned int max_psk_len)) {
+ s->psk_server_callback = cb;
+}
+
+void SSL_CTX_set_psk_server_callback(
+ SSL_CTX *ctx, unsigned int (*cb)(SSL *ssl, const char *identity,
+ uint8_t *psk, unsigned int max_psk_len)) {
+ ctx->psk_server_callback = cb;
+}
+
+void SSL_CTX_set_min_version(SSL_CTX *ctx, uint16_t version) {
+ ctx->min_version = version;
+}
+
+void SSL_CTX_set_max_version(SSL_CTX *ctx, uint16_t version) {
+ ctx->max_version = version;
+}
+
+void SSL_set_min_version(SSL *ssl, uint16_t version) {
+ ssl->min_version = version;
+}
+
+void SSL_set_max_version(SSL *ssl, uint16_t version) {
+ ssl->max_version = version;
+}
+
+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);
+}
+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);
+}
+
+void SSL_CTX_set_keylog_bio(SSL_CTX *ctx, BIO *keylog_bio) {
+ if (ctx->keylog_bio != NULL) {
+ BIO_free(ctx->keylog_bio);
+ }
+ ctx->keylog_bio = keylog_bio;
+}
+
+static int cbb_add_hex(CBB *cbb, const uint8_t *in, size_t in_len) {
+ static const char hextable[] = "0123456789abcdef";
+ uint8_t *out;
+ size_t i;
+
+ if (!CBB_add_space(cbb, &out, in_len * 2)) {
+ return 0;
+ }
+
+ for (i = 0; i < in_len; i++) {
+ *(out++) = (uint8_t)hextable[in[i] >> 4];
+ *(out++) = (uint8_t)hextable[in[i] & 0xf];
+ }
+
+ return 1;
+}
+
+int ssl_ctx_log_rsa_client_key_exchange(SSL_CTX *ctx,
+ const uint8_t *encrypted_premaster,
+ size_t encrypted_premaster_len,
+ const uint8_t *premaster,
+ size_t premaster_len) {
+ BIO *bio = ctx->keylog_bio;
+ CBB cbb;
+ uint8_t *out;
+ size_t out_len;
+ int ret;
+
+ if (bio == NULL) {
+ return 1;
+ }
+
+ if (encrypted_premaster_len < 8) {
+ OPENSSL_PUT_ERROR(SSL, ssl_ctx_log_rsa_client_key_exchange,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ if (!CBB_init(&cbb, 4 + 16 + 1 + premaster_len * 2 + 1)) {
+ return 0;
+ }
+
+ if (!CBB_add_bytes(&cbb, (const uint8_t *)"RSA ", 4) ||
+ /* Only the first 8 bytes of the encrypted premaster secret are
+ * logged. */
+ !cbb_add_hex(&cbb, encrypted_premaster, 8) ||
+ !CBB_add_bytes(&cbb, (const uint8_t *)" ", 1) ||
+ !cbb_add_hex(&cbb, premaster, premaster_len) ||
+ !CBB_add_bytes(&cbb, (const uint8_t *)"\n", 1) ||
+ !CBB_finish(&cbb, &out, &out_len)) {
+ CBB_cleanup(&cbb);
+ return 0;
+ }
+
+ CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
+ ret = BIO_write(bio, out, out_len) >= 0 && BIO_flush(bio);
+ CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
+
+ OPENSSL_free(out);
+ return ret;
+}
+
+int ssl_ctx_log_master_secret(SSL_CTX *ctx, const uint8_t *client_random,
+ size_t client_random_len, const uint8_t *master,
+ size_t master_len) {
+ BIO *bio = ctx->keylog_bio;
+ CBB cbb;
+ uint8_t *out;
+ size_t out_len;
+ int ret;
+
+ if (bio == NULL) {
+ return 1;
+ }
+
+ if (client_random_len != 32) {
+ OPENSSL_PUT_ERROR(SSL, ssl_ctx_log_master_secret, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ if (!CBB_init(&cbb, 14 + 64 + 1 + master_len * 2 + 1)) {
+ return 0;
+ }
+
+ if (!CBB_add_bytes(&cbb, (const uint8_t *)"CLIENT_RANDOM ", 14) ||
+ !cbb_add_hex(&cbb, client_random, 32) ||
+ !CBB_add_bytes(&cbb, (const uint8_t *)" ", 1) ||
+ !cbb_add_hex(&cbb, master, master_len) ||
+ !CBB_add_bytes(&cbb, (const uint8_t *)"\n", 1) ||
+ !CBB_finish(&cbb, &out, &out_len)) {
+ CBB_cleanup(&cbb);
+ return 0;
+ }
+
+ CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
+ ret = BIO_write(bio, out, out_len) >= 0 && BIO_flush(bio);
+ CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
+
+ OPENSSL_free(out);
+ return ret;
+}
+
+int SSL_cutthrough_complete(const SSL *s) {
+ return (
+ !s->server && /* cutthrough only applies to clients */
+ !s->hit && /* full-handshake */
+ s->version >= SSL3_VERSION &&
+ s->s3->in_read_app_data == 0 && /* cutthrough only applies to write() */
+ (SSL_get_mode((SSL *)s) &
+ SSL_MODE_HANDSHAKE_CUTTHROUGH) && /* cutthrough enabled */
+ ssl3_can_cutthrough(s) && /* cutthrough allowed */
+ s->s3->previous_server_finished_len ==
+ 0 && /* not a renegotiation handshake */
+ (s->state == SSL3_ST_CR_SESSION_TICKET_A || /* ready to write app-data*/
+ s->state == SSL3_ST_CR_CHANGE || s->state == SSL3_ST_CR_FINISHED_A));
+}
+
+void SSL_get_structure_sizes(size_t *ssl_size, size_t *ssl_ctx_size,
+ size_t *ssl_session_size) {
+ *ssl_size = sizeof(SSL);
+ *ssl_ctx_size = sizeof(SSL_CTX);
+ *ssl_session_size = sizeof(SSL_SESSION);
+}
+
+int ssl3_can_cutthrough(const SSL *s) {
+ const SSL_CIPHER *c;
+
+ /* require a strong enough cipher */
+ if (SSL_get_cipher_bits(s, NULL) < 128) {
+ return 0;
+ }
+
+ /* require ALPN or NPN extension */
+ if (!s->s3->alpn_selected && !s->s3->next_proto_neg_seen) {
+ return 0;
+ }
+
+ /* require a forward-secret cipher */
+ c = SSL_get_current_cipher(s);
+ if (!c ||
+ (c->algorithm_mkey != SSL_kEDH && c->algorithm_mkey != SSL_kEECDH)) {
+ return 0;
+ }
+
+ return 1;
+}
+
+const SSL3_ENC_METHOD *ssl3_get_enc_method(uint16_t version) {
+ switch (version) {
+ case SSL3_VERSION:
+ return &SSLv3_enc_data;
+
+ case TLS1_VERSION:
+ return &TLSv1_enc_data;
+
+ case TLS1_1_VERSION:
+ return &TLSv1_1_enc_data;
+
+ case TLS1_2_VERSION:
+ return &TLSv1_2_enc_data;
+
+ case DTLS1_VERSION:
+ return &DTLSv1_enc_data;
+
+ case DTLS1_2_VERSION:
+ return &DTLSv1_2_enc_data;
+
+ default:
+ return NULL;
+ }
+}
+
+uint16_t ssl3_get_max_server_version(const SSL *s) {
+ uint16_t max_version;
+
+ if (SSL_IS_DTLS(s)) {
+ max_version = (s->max_version != 0) ? s->max_version : DTLS1_2_VERSION;
+ if (!(s->options & SSL_OP_NO_DTLSv1_2) && DTLS1_2_VERSION >= max_version) {
+ return DTLS1_2_VERSION;
+ }
+ if (!(s->options & SSL_OP_NO_DTLSv1) && DTLS1_VERSION >= max_version) {
+ return DTLS1_VERSION;
+ }
+ return 0;
+ }
+
+ max_version = (s->max_version != 0) ? s->max_version : TLS1_2_VERSION;
+ if (!(s->options & SSL_OP_NO_TLSv1_2) && TLS1_2_VERSION <= max_version) {
+ return TLS1_2_VERSION;
+ }
+ if (!(s->options & SSL_OP_NO_TLSv1_1) && TLS1_1_VERSION <= max_version) {
+ return TLS1_1_VERSION;
+ }
+ if (!(s->options & SSL_OP_NO_TLSv1) && TLS1_VERSION <= max_version) {
+ return TLS1_VERSION;
+ }
+ if (!(s->options & SSL_OP_NO_SSLv3) && SSL3_VERSION <= max_version) {
+ return SSL3_VERSION;
+ }
+ return 0;
+}
+
+uint16_t ssl3_get_mutual_version(SSL *s, uint16_t client_version) {
+ uint16_t version = 0;
+
+ if (SSL_IS_DTLS(s)) {
+ /* Clamp client_version to max_version. */
+ if (s->max_version != 0 && client_version < s->max_version) {
+ client_version = s->max_version;
+ }
+
+ if (client_version <= DTLS1_2_VERSION && !(s->options & SSL_OP_NO_DTLSv1_2)) {
+ version = DTLS1_2_VERSION;
+ } else if (client_version <= DTLS1_VERSION &&
+ !(s->options & SSL_OP_NO_DTLSv1)) {
+ version = DTLS1_VERSION;
+ }
+
+ /* Check against min_version. */
+ if (version != 0 && s->min_version != 0 && version > s->min_version) {
+ return 0;
+ }
+ return version;
+ } else {
+ /* Clamp client_version to max_version. */
+ if (s->max_version != 0 && client_version > s->max_version) {
+ client_version = s->max_version;
+ }
+
+ if (client_version >= TLS1_2_VERSION && !(s->options & SSL_OP_NO_TLSv1_2)) {
+ version = TLS1_2_VERSION;
+ } else if (client_version >= TLS1_1_VERSION &&
+ !(s->options & SSL_OP_NO_TLSv1_1)) {
+ version = TLS1_1_VERSION;
+ } else if (client_version >= TLS1_VERSION && !(s->options & SSL_OP_NO_TLSv1)) {
+ version = TLS1_VERSION;
+ } else if (client_version >= SSL3_VERSION && !(s->options & SSL_OP_NO_SSLv3)) {
+ version = SSL3_VERSION;
+ }
+
+ /* Check against min_version. */
+ if (version != 0 && s->min_version != 0 && version < s->min_version) {
+ return 0;
+ }
+ return version;
+ }
+}
+
+uint16_t ssl3_get_max_client_version(SSL *s) {
+ unsigned long options = s->options;
+ uint16_t version = 0;
+
+ /* OpenSSL's API for controlling versions entails blacklisting individual
+ * protocols. This has two problems. First, on the client, the protocol can
+ * only express a contiguous range of versions. Second, a library consumer
+ * trying to set a maximum version cannot disable protocol versions that get
+ * added in a future version of the library.
+ *
+ * To account for both of these, OpenSSL interprets the client-side bitmask
+ * as a min/max range by picking the lowest contiguous non-empty range of
+ * enabled protocols. Note that this means it is impossible to set a maximum
+ * version of TLS 1.2 in a future-proof way.
+ *
+ * By this scheme, the maximum version is the lowest version V such that V is
+ * enabled and V+1 is disabled or unimplemented. */
+ if (SSL_IS_DTLS(s)) {
+ if (!(options & SSL_OP_NO_DTLSv1_2)) {
+ version = DTLS1_2_VERSION;
+ }
+ if (!(options & SSL_OP_NO_DTLSv1) && (options & SSL_OP_NO_DTLSv1_2)) {
+ version = DTLS1_VERSION;
+ }
+ if (s->max_version != 0 && version < s->max_version) {
+ version = s->max_version;
+ }
+ } else {
+ if (!(options & SSL_OP_NO_TLSv1_2)) {
+ version = TLS1_2_VERSION;
+ }
+ if (!(options & SSL_OP_NO_TLSv1_1) && (options & SSL_OP_NO_TLSv1_2)) {
+ version = TLS1_1_VERSION;
+ }
+ if (!(options & SSL_OP_NO_TLSv1) && (options & SSL_OP_NO_TLSv1_1)) {
+ version = TLS1_VERSION;
+ }
+ if (!(options & SSL_OP_NO_SSLv3) && (options & SSL_OP_NO_TLSv1)) {
+ version = SSL3_VERSION;
+ }
+ if (s->max_version != 0 && version > s->max_version) {
+ version = s->max_version;
+ }
+ }
+
+ return version;
+}
+
+int ssl3_is_version_enabled(SSL *s, uint16_t version) {
+ if (SSL_IS_DTLS(s)) {
+ if (s->max_version != 0 && version < s->max_version) {
+ return 0;
+ }
+ if (s->min_version != 0 && version > s->min_version) {
+ return 0;
+ }
+
+ switch (version) {
+ case DTLS1_VERSION:
+ return !(s->options & SSL_OP_NO_DTLSv1);
+
+ case DTLS1_2_VERSION:
+ return !(s->options & SSL_OP_NO_DTLSv1_2);
+
+ default:
+ return 0;
+ }
+ } else {
+ if (s->max_version != 0 && version > s->max_version) {
+ return 0;
+ }
+ if (s->min_version != 0 && version < s->min_version) {
+ return 0;
+ }
+
+ switch (version) {
+ case SSL3_VERSION:
+ return !(s->options & SSL_OP_NO_SSLv3);
+
+ case TLS1_VERSION:
+ return !(s->options & SSL_OP_NO_TLSv1);
+
+ case TLS1_1_VERSION:
+ return !(s->options & SSL_OP_NO_TLSv1_1);
+
+ case TLS1_2_VERSION:
+ return !(s->options & SSL_OP_NO_TLSv1_2);
+
+ default:
+ return 0;
+ }
+ }
+}
+
+uint16_t ssl3_version_from_wire(SSL *s, uint16_t wire_version) {
+ if (!SSL_IS_DTLS(s)) {
+ return wire_version;
+ }
+
+ uint16_t tls_version = ~wire_version;
+ uint16_t version = tls_version + 0x0201;
+ /* If either component overflowed, clamp it so comparisons still work. */
+ if ((version >> 8) < (tls_version >> 8)) {
+ version = 0xff00 | (version & 0xff);
+ }
+ if ((version & 0xff) < (tls_version & 0xff)) {
+ version = (version & 0xff00) | 0xff;
+ }
+ /* DTLS 1.0 maps to TLS 1.1, not TLS 1.0. */
+ if (version == TLS1_VERSION) {
+ version = TLS1_1_VERSION;
+ }
+ return version;
+}
+
+int SSL_cache_hit(SSL *s) { return s->hit; }
+
+int SSL_is_server(SSL *s) { return s->server; }
+
+void SSL_enable_fastradio_padding(SSL *s, char on_off) {
+ s->fastradio_padding = on_off;
+}
diff --git a/src/ssl/ssl_locl.h b/src/ssl/ssl_locl.h
new file mode 100644
index 0000000..a0c323c
--- /dev/null
+++ b/src/ssl/ssl_locl.h
@@ -0,0 +1,1035 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <openssl/base.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <openssl/aead.h>
+#include <openssl/bio.h>
+#include <openssl/buf.h>
+#include <openssl/dsa.h>
+#include <openssl/err.h>
+#include <openssl/rsa.h>
+#include <openssl/ssl.h>
+#include <openssl/stack.h>
+
+
+#define c2l(c, l) \
+ (l = ((unsigned long)(*((c)++))), l |= (((unsigned long)(*((c)++))) << 8), \
+ l |= (((unsigned long)(*((c)++))) << 16), \
+ l |= (((unsigned long)(*((c)++))) << 24))
+
+/* NOTE - c is not incremented as per c2l */
+#define c2ln(c, l1, l2, n) \
+ { \
+ c += n; \
+ l1 = l2 = 0; \
+ switch (n) { \
+ case 8: \
+ l2 = ((unsigned long)(*(--(c)))) << 24; \
+ case 7: \
+ l2 |= ((unsigned long)(*(--(c)))) << 16; \
+ case 6: \
+ l2 |= ((unsigned long)(*(--(c)))) << 8; \
+ case 5: \
+ l2 |= ((unsigned long)(*(--(c)))); \
+ case 4: \
+ l1 = ((unsigned long)(*(--(c)))) << 24; \
+ case 3: \
+ l1 |= ((unsigned long)(*(--(c)))) << 16; \
+ case 2: \
+ l1 |= ((unsigned long)(*(--(c)))) << 8; \
+ case 1: \
+ l1 |= ((unsigned long)(*(--(c)))); \
+ } \
+ }
+
+#define l2c(l, c) \
+ (*((c)++) = (uint8_t)(((l)) & 0xff), \
+ *((c)++) = (uint8_t)(((l) >> 8) & 0xff), \
+ *((c)++) = (uint8_t)(((l) >> 16) & 0xff), \
+ *((c)++) = (uint8_t)(((l) >> 24) & 0xff))
+
+#define n2l(c, l) \
+ (l = ((unsigned long)(*((c)++))) << 24, \
+ l |= ((unsigned long)(*((c)++))) << 16, \
+ l |= ((unsigned long)(*((c)++))) << 8, l |= ((unsigned long)(*((c)++))))
+
+#define l2n(l, c) \
+ (*((c)++) = (uint8_t)(((l) >> 24) & 0xff), \
+ *((c)++) = (uint8_t)(((l) >> 16) & 0xff), \
+ *((c)++) = (uint8_t)(((l) >> 8) & 0xff), \
+ *((c)++) = (uint8_t)(((l)) & 0xff))
+
+#define l2n8(l, c) \
+ (*((c)++) = (uint8_t)(((l) >> 56) & 0xff), \
+ *((c)++) = (uint8_t)(((l) >> 48) & 0xff), \
+ *((c)++) = (uint8_t)(((l) >> 40) & 0xff), \
+ *((c)++) = (uint8_t)(((l) >> 32) & 0xff), \
+ *((c)++) = (uint8_t)(((l) >> 24) & 0xff), \
+ *((c)++) = (uint8_t)(((l) >> 16) & 0xff), \
+ *((c)++) = (uint8_t)(((l) >> 8) & 0xff), \
+ *((c)++) = (uint8_t)(((l)) & 0xff))
+
+/* NOTE - c is not incremented as per l2c */
+#define l2cn(l1, l2, c, n) \
+ { \
+ c += n; \
+ switch (n) { \
+ case 8: \
+ *(--(c)) = (uint8_t)(((l2) >> 24) & 0xff); \
+ case 7: \
+ *(--(c)) = (uint8_t)(((l2) >> 16) & 0xff); \
+ case 6: \
+ *(--(c)) = (uint8_t)(((l2) >> 8) & 0xff); \
+ case 5: \
+ *(--(c)) = (uint8_t)(((l2)) & 0xff); \
+ case 4: \
+ *(--(c)) = (uint8_t)(((l1) >> 24) & 0xff); \
+ case 3: \
+ *(--(c)) = (uint8_t)(((l1) >> 16) & 0xff); \
+ case 2: \
+ *(--(c)) = (uint8_t)(((l1) >> 8) & 0xff); \
+ case 1: \
+ *(--(c)) = (uint8_t)(((l1)) & 0xff); \
+ } \
+ }
+
+#define n2s(c, s) \
+ ((s = (((unsigned int)(c[0])) << 8) | (((unsigned int)(c[1])))), c += 2)
+
+#define s2n(s, c) \
+ ((c[0] = (uint8_t)(((s) >> 8) & 0xff), \
+ c[1] = (uint8_t)(((s)) & 0xff)), \
+ c += 2)
+
+#define n2l3(c, l) \
+ ((l = (((unsigned long)(c[0])) << 16) | (((unsigned long)(c[1])) << 8) | \
+ (((unsigned long)(c[2])))), \
+ c += 3)
+
+#define l2n3(l, c) \
+ ((c[0] = (uint8_t)(((l) >> 16) & 0xff), \
+ c[1] = (uint8_t)(((l) >> 8) & 0xff), \
+ c[2] = (uint8_t)(((l)) & 0xff)), \
+ c += 3)
+
+/* LOCAL STUFF */
+
+#define SSL_DECRYPT 0
+#define SSL_ENCRYPT 1
+
+#define TWO_BYTE_BIT 0x80
+#define SEC_ESC_BIT 0x40
+#define TWO_BYTE_MASK 0x7fff
+#define THREE_BYTE_MASK 0x3fff
+
+#define INC32(a) ((a) = ((a) + 1) & 0xffffffffL)
+#define DEC32(a) ((a) = ((a)-1) & 0xffffffffL)
+#define MAX_MAC_SIZE 20 /* up from 16 for SSLv3 */
+
+/* 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_kEDH 0x00000002L /* tmp DH key no DH cert */
+#define SSL_kEECDH 0x00000004L /* ephemeral ECDH */
+#define SSL_kPSK 0x00000008L /* PSK */
+
+/* Bits for algorithm_auth (server authentication) */
+#define SSL_aRSA 0x00000001L /* RSA auth */
+#define SSL_aNULL 0x00000002L /* no auth (i.e. use ADH or AECDH) */
+#define SSL_aECDSA 0x00000004L /* ECDSA auth*/
+#define SSL_aPSK 0x00000008L /* PSK auth */
+
+/* Bits for algorithm_enc (symmetric encryption) */
+#define SSL_3DES 0x00000001L
+#define SSL_RC4 0x00000002L
+#define SSL_AES128 0x00000004L
+#define SSL_AES256 0x00000008L
+#define SSL_AES128GCM 0x00000010L
+#define SSL_AES256GCM 0x00000020L
+#define SSL_CHACHA20POLY1305 0x00000040L
+
+#define SSL_AES (SSL_AES128 | SSL_AES256 | SSL_AES128GCM | SSL_AES256GCM)
+
+/* Bits for algorithm_mac (symmetric authentication) */
+
+#define SSL_MD5 0x00000001L
+#define SSL_SHA1 0x00000002L
+#define SSL_SHA256 0x00000004L
+#define SSL_SHA384 0x00000008L
+/* Not a real MAC, just an indication it is part of cipher */
+#define SSL_AEAD 0x00000010L
+
+/* Bits for algorithm_ssl (protocol version) */
+#define SSL_SSLV3 0x00000002L
+#define SSL_TLSV1 SSL_SSLV3 /* for now */
+#define SSL_TLSV1_2 0x00000004L
+
+/* Bits for algorithm2 (handshake digests and other extra flags) */
+
+#define SSL_HANDSHAKE_MAC_MD5 0x10
+#define SSL_HANDSHAKE_MAC_SHA 0x20
+#define SSL_HANDSHAKE_MAC_SHA256 0x40
+#define SSL_HANDSHAKE_MAC_SHA384 0x80
+#define SSL_HANDSHAKE_MAC_DEFAULT \
+ (SSL_HANDSHAKE_MAC_MD5 | SSL_HANDSHAKE_MAC_SHA)
+
+/* When adding new digest in the ssl_ciph.c and increment SSM_MD_NUM_IDX
+ * make sure to update this constant too */
+#define SSL_MAX_DIGEST 4
+
+#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 (TLS1_PRF_MD5 | TLS1_PRF_SHA1)
+
+#define TLSEXT_CHANNEL_ID_SIZE 128
+
+/* SSL_CIPHER_ALGORITHM2_AEAD is a flag in SSL_CIPHER.algorithm2 which
+ * indicates that the cipher is implemented via an EVP_AEAD. */
+#define SSL_CIPHER_ALGORITHM2_AEAD (1 << 23)
+
+/* SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD is a flag in
+ * SSL_CIPHER.algorithm2 which indicates that the variable part of the nonce is
+ * included as a prefix of the record. (AES-GCM, for example, does with with an
+ * 8-byte variable nonce.) */
+#define SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD (1<<22)
+
+/* Cipher strength information. */
+#define SSL_MEDIUM 0x00000001L
+#define SSL_HIGH 0x00000002L
+#define SSL_FIPS 0x00000004L
+
+/* we have used 000001ff - 23 bits left to go */
+
+/* Check if an SSL structure is using DTLS */
+#define SSL_IS_DTLS(s) (s->enc_method->enc_flags & SSL_ENC_FLAG_DTLS)
+/* See if we need explicit IV */
+#define SSL_USE_EXPLICIT_IV(s) \
+ (s->enc_method->enc_flags & SSL_ENC_FLAG_EXPLICIT_IV)
+/* See if we use signature algorithms extension and signature algorithm before
+ * signatures. */
+#define SSL_USE_SIGALGS(s) (s->enc_method->enc_flags & SSL_ENC_FLAG_SIGALGS)
+/* Allow TLS 1.2 ciphersuites: applies to DTLS 1.2 as well as TLS 1.2: may
+ * apply to others in future. */
+#define SSL_USE_TLS1_2_CIPHERS(s) \
+ (s->enc_method->enc_flags & SSL_ENC_FLAG_TLS1_2_CIPHERS)
+/* Determine if a client can use TLS 1.2 ciphersuites: can't rely on method
+ * flags because it may not be set to correct version yet. */
+#define SSL_CLIENT_USE_TLS1_2_CIPHERS(s) \
+ ((SSL_IS_DTLS(s) && s->client_version <= DTLS1_2_VERSION) || \
+ (!SSL_IS_DTLS(s) && s->client_version >= TLS1_2_VERSION))
+
+/* Mostly for SSLv3 */
+#define SSL_PKEY_RSA_ENC 0
+#define SSL_PKEY_RSA_SIGN 1
+#define SSL_PKEY_ECC 2
+#define SSL_PKEY_NUM 3
+
+/* 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_kEDH <- RSA_ENC | RSA_SIGN | DSA_SIGN
+ * SSL_aRSA <- RSA_ENC | RSA_SIGN
+ * SSL_aDSS <- DSA_SIGN */
+
+#define PENDING_SESSION -10000
+#define CERTIFICATE_SELECTION_PENDING -10001
+
+/* From RFC4492, 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
+
+/* Values for the |hash_message| parameter of |s->method->ssl_get_message|. */
+#define SSL_GET_MESSAGE_DONT_HASH_MESSAGE 0
+#define SSL_GET_MESSAGE_HASH_MESSAGE 1
+
+typedef struct cert_pkey_st {
+ X509 *x509;
+ EVP_PKEY *privatekey;
+ /* Chain for this certificate */
+ STACK_OF(X509) * chain;
+} CERT_PKEY;
+
+typedef struct cert_st {
+ /* Current active set */
+ CERT_PKEY *key; /* ALWAYS points to an element of the pkeys array
+ * Probably it would make more sense to store
+ * an index, not a pointer. */
+
+ /* For clients the following masks are of *disabled* key and auth algorithms
+ * based on the current session.
+ *
+ * TODO(davidben): Remove these. They get checked twice: when sending the
+ * ClientHello and when processing the ServerHello. However, mask_ssl is a
+ * different value both times. mask_k and mask_a are not, but is a
+ * round-about way of checking the server's cipher was one of the advertised
+ * ones. (Currently it checks the masks and then the list of ciphers prior to
+ * applying the masks in ClientHello.) */
+ unsigned long mask_k;
+ unsigned long mask_a;
+ unsigned long mask_ssl;
+
+ DH *dh_tmp;
+ DH *(*dh_tmp_cb)(SSL *ssl, int is_export, int keysize);
+ EC_KEY *ecdh_tmp;
+ /* Callback for generating ephemeral ECDH keys */
+ EC_KEY *(*ecdh_tmp_cb)(SSL *ssl, int is_export, int keysize);
+ /* Select ECDH parameters automatically */
+ int ecdh_tmp_auto;
+ /* Flags related to certificates */
+ unsigned int cert_flags;
+ CERT_PKEY pkeys[SSL_PKEY_NUM];
+
+ /* Server-only: client_certificate_types is list of certificate types to
+ * include in the CertificateRequest message.
+ */
+ uint8_t *client_certificate_types;
+ size_t num_client_certificate_types;
+
+ /* signature algorithms peer reports: e.g. supported signature
+ * algorithms extension for server or as part of a certificate
+ * request for client. */
+ uint8_t *peer_sigalgs;
+ /* Size of above array */
+ size_t peer_sigalgslen;
+ /* suppported signature algorithms.
+ * When set on a client this is sent in the client hello as the
+ * supported signature algorithms extension. For servers
+ * it represents the signature algorithms we are willing to use. */
+ uint8_t *conf_sigalgs;
+ /* Size of above array */
+ size_t conf_sigalgslen;
+ /* Client authentication signature algorithms, if not set then
+ * uses conf_sigalgs. On servers these will be the signature
+ * algorithms sent to the client in a cerificate request for TLS 1.2.
+ * On a client this represents the signature algortithms we are
+ * willing to use for client authentication. */
+ uint8_t *client_sigalgs;
+ /* Size of above array */
+ size_t client_sigalgslen;
+ /* Signature algorithms shared by client and server: cached
+ * because these are used most often. */
+ TLS_SIGALGS *shared_sigalgs;
+ size_t shared_sigalgslen;
+
+ /* Certificate setup callback: if set is called whenever a
+ * certificate may be required (client or server). the callback
+ * can then examine any appropriate parameters and setup any
+ * certificates required. This allows advanced applications
+ * to select certificates on the fly: for example based on
+ * supported signature algorithms or curves. */
+ int (*cert_cb)(SSL *ssl, void *arg);
+ void *cert_cb_arg;
+
+ /* Optional X509_STORE for chain building or certificate validation
+ * If NULL the parent SSL_CTX store is used instead. */
+ X509_STORE *chain_store;
+ X509_STORE *verify_store;
+
+ /* Raw values of the cipher list from a client */
+ uint8_t *ciphers_raw;
+ size_t ciphers_rawlen;
+} CERT;
+
+typedef struct sess_cert_st {
+ STACK_OF(X509) * cert_chain; /* as received from peer (not for SSL2) */
+
+ /* The 'peer_...' members are used only by clients. */
+ int peer_cert_type;
+
+ CERT_PKEY *peer_key; /* points to an element of peer_pkeys (never NULL!) */
+ CERT_PKEY peer_pkeys[SSL_PKEY_NUM];
+ /* Obviously we don't have the private keys of these,
+ * so maybe we shouldn't even use the CERT_PKEY type here. */
+
+ DH *peer_dh_tmp;
+ EC_KEY *peer_ecdh_tmp;
+} SESS_CERT;
+
+/* Structure containing decoded values of signature algorithms extension */
+struct tls_sigalgs_st {
+ /* NID of hash algorithm */
+ int hash_nid;
+ /* NID of signature algorithm */
+ int sign_nid;
+ /* Combined hash and signature NID */
+ int signandhash_nid;
+ /* Raw values used in extension */
+ uint8_t rsign;
+ uint8_t rhash;
+};
+
+/* SSL_METHOD is a compatibility structure to support the legacy version-locked
+ * methods. */
+struct ssl_method_st {
+ /* version, if non-zero, is the only protocol version acceptable to an
+ * SSL_CTX initialized from this method. */
+ uint16_t version;
+ /* method is the underlying SSL_PROTOCOL_METHOD that initializes the
+ * SSL_CTX. */
+ const SSL_PROTOCOL_METHOD *method;
+};
+
+/* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */
+struct ssl_protocol_method_st {
+ int (*ssl_new)(SSL *s);
+ void (*ssl_free)(SSL *s);
+ int (*ssl_accept)(SSL *s);
+ int (*ssl_connect)(SSL *s);
+ int (*ssl_read)(SSL *s, void *buf, int len);
+ int (*ssl_peek)(SSL *s, void *buf, int len);
+ int (*ssl_write)(SSL *s, const void *buf, int len);
+ int (*ssl_shutdown)(SSL *s);
+ int (*ssl_renegotiate)(SSL *s);
+ int (*ssl_renegotiate_check)(SSL *s);
+ long (*ssl_get_message)(SSL *s, int header_state, int body_state,
+ int msg_type, long max, int hash_message, int *ok);
+ int (*ssl_read_bytes)(SSL *s, int type, uint8_t *buf, int len, int peek);
+ int (*ssl_write_bytes)(SSL *s, int type, const void *buf_, int len);
+ int (*ssl_dispatch_alert)(SSL *s);
+ long (*ssl_ctrl)(SSL *s, int cmd, long larg, void *parg);
+ long (*ssl_ctx_ctrl)(SSL_CTX *ctx, int cmd, long larg, void *parg);
+ int (*ssl_pending)(const SSL *s);
+ int (*num_ciphers)(void);
+ const SSL_CIPHER *(*get_cipher)(unsigned ncipher);
+ int (*ssl_version)(void);
+ long (*ssl_callback_ctrl)(SSL *s, int cb_id, void (*fp)(void));
+ long (*ssl_ctx_callback_ctrl)(SSL_CTX *s, int cb_id, void (*fp)(void));
+};
+
+/* This is for the SSLv3/TLSv1.0 differences in crypto/hash stuff It is a bit
+ * of a mess of functions, but hell, think of it as an opaque structure. */
+struct ssl3_enc_method {
+ int (*enc)(SSL *, int);
+ int (*prf)(SSL *, uint8_t *, size_t, const uint8_t *, size_t, const char *,
+ size_t, const uint8_t *, size_t, const uint8_t *, size_t);
+ int (*setup_key_block)(SSL *);
+ int (*generate_master_secret)(SSL *, uint8_t *, const uint8_t *, size_t);
+ int (*change_cipher_state)(SSL *, int);
+ int (*final_finish_mac)(SSL *, const char *, int, uint8_t *);
+ int finish_mac_length;
+ int (*cert_verify_mac)(SSL *, int, uint8_t *);
+ const char *client_finished_label;
+ int client_finished_label_len;
+ const char *server_finished_label;
+ int server_finished_label_len;
+ int (*alert_value)(int);
+ int (*export_keying_material)(SSL *, uint8_t *, size_t, const char *, size_t,
+ const uint8_t *, size_t, int use_context);
+ /* Various flags indicating protocol version requirements */
+ unsigned int enc_flags;
+ /* Handshake header length */
+ unsigned int hhlen;
+ /* Set the handshake header */
+ void (*set_handshake_header)(SSL *s, int type, unsigned long len);
+ /* Write out handshake message */
+ int (*do_write)(SSL *s);
+};
+
+#define SSL_HM_HEADER_LENGTH(s) s->enc_method->hhlen
+#define ssl_handshake_start(s) \
+ (((uint8_t *)s->init_buf->data) + s->enc_method->hhlen)
+#define ssl_set_handshake_header(s, htype, len) \
+ s->enc_method->set_handshake_header(s, htype, len)
+#define ssl_do_write(s) s->enc_method->do_write(s)
+
+/* Values for enc_flags */
+
+/* Uses explicit IV for CBC mode */
+#define SSL_ENC_FLAG_EXPLICIT_IV 0x1
+/* Uses signature algorithms extension */
+#define SSL_ENC_FLAG_SIGALGS 0x2
+/* Uses SHA256 default PRF */
+#define SSL_ENC_FLAG_SHA256_PRF 0x4
+/* Is DTLS */
+#define SSL_ENC_FLAG_DTLS 0x8
+/* Allow TLS 1.2 ciphersuites: applies to DTLS 1.2 as well as TLS 1.2:
+ * may apply to others in future. */
+#define SSL_ENC_FLAG_TLS1_2_CIPHERS 0x10
+
+/* ssl_aead_ctx_st contains information about an AEAD that is being used to
+ * encrypt an SSL connection. */
+struct ssl_aead_ctx_st {
+ EVP_AEAD_CTX ctx;
+ /* fixed_nonce contains any bytes of the nonce that are fixed for all
+ * records. */
+ uint8_t fixed_nonce[8];
+ uint8_t fixed_nonce_len, variable_nonce_len, tag_len;
+ /* variable_nonce_included_in_record is non-zero if the variable nonce
+ * for a record is included as a prefix before the ciphertext. */
+ char variable_nonce_included_in_record;
+ /* random_variable_nonce is non-zero if the variable nonce is
+ * randomly generated, rather than derived from the sequence
+ * number. */
+ char random_variable_nonce;
+ /* omit_length_in_ad is non-zero if the length should be omitted in the
+ * AEAD's ad parameter. */
+ char omit_length_in_ad;
+ /* omit_version_in_ad is non-zero if the version should be omitted
+ * in the AEAD's ad parameter. */
+ char omit_version_in_ad;
+};
+
+extern const SSL_CIPHER ssl3_ciphers[];
+
+extern const SSL3_ENC_METHOD TLSv1_enc_data;
+extern const SSL3_ENC_METHOD TLSv1_1_enc_data;
+extern const SSL3_ENC_METHOD TLSv1_2_enc_data;
+extern const SSL3_ENC_METHOD SSLv3_enc_data;
+extern const SSL3_ENC_METHOD DTLSv1_enc_data;
+extern const SSL3_ENC_METHOD DTLSv1_2_enc_data;
+
+void ssl_clear_cipher_ctx(SSL *s);
+int ssl_clear_bad_session(SSL *s);
+CERT *ssl_cert_new(void);
+CERT *ssl_cert_dup(CERT *cert);
+int ssl_cert_inst(CERT **o);
+void ssl_cert_clear_certs(CERT *c);
+void ssl_cert_free(CERT *c);
+SESS_CERT *ssl_sess_cert_new(void);
+void ssl_sess_cert_free(SESS_CERT *sc);
+int ssl_set_peer_cert_type(SESS_CERT *c, int type);
+int ssl_get_prev_session(SSL *s, const struct ssl_early_callback_ctx *ctx);
+int ssl_cipher_id_cmp(const void *in_a, const void *in_b);
+int ssl_cipher_ptr_id_cmp(const SSL_CIPHER **ap, const SSL_CIPHER **bp);
+STACK_OF(SSL_CIPHER) * ssl_bytes_to_cipher_list(SSL *s, const CBS *cbs);
+int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) * sk, uint8_t *p);
+STACK_OF(SSL_CIPHER) *
+ ssl_create_cipher_list(const SSL_PROTOCOL_METHOD *meth,
+ struct ssl_cipher_preference_list_st **pref,
+ STACK_OF(SSL_CIPHER) * *sorted, const char *rule_str,
+ CERT *c);
+struct ssl_cipher_preference_list_st *ssl_cipher_preference_list_dup(
+ struct ssl_cipher_preference_list_st *cipher_list);
+void ssl_cipher_preference_list_free(
+ struct ssl_cipher_preference_list_st *cipher_list);
+struct ssl_cipher_preference_list_st *ssl_cipher_preference_list_from_ciphers(
+ STACK_OF(SSL_CIPHER) * ciphers);
+struct ssl_cipher_preference_list_st *ssl_get_cipher_preferences(SSL *s);
+
+/* ssl_cipher_get_evp_aead sets |*out_aead| to point to the correct EVP_AEAD
+* object for |cipher| protocol version |version|. It sets |*out_mac_secret_len|
+* and |*out_fixed_iv_len| to the MAC key length and fixed IV length,
+* respectively. The MAC key length is zero except for legacy block and stream
+* ciphers. It returns 1 on success and 0 on error. */
+int ssl_cipher_get_evp_aead(const EVP_AEAD **out_aead,
+ size_t *out_mac_secret_len,
+ size_t *out_fixed_iv_len,
+ const SSL_CIPHER *cipher, uint16_t version);
+
+int ssl_get_handshake_digest(size_t i, long *mask, const EVP_MD **md);
+int ssl_cipher_get_cert_index(const SSL_CIPHER *c);
+int ssl_cipher_has_server_public_key(const SSL_CIPHER *cipher);
+int ssl_cipher_requires_server_key_exchange(const SSL_CIPHER *cipher);
+
+int ssl_cert_set0_chain(CERT *c, STACK_OF(X509) * chain);
+int ssl_cert_set1_chain(CERT *c, STACK_OF(X509) * chain);
+int ssl_cert_add0_chain_cert(CERT *c, X509 *x);
+int ssl_cert_add1_chain_cert(CERT *c, X509 *x);
+int ssl_cert_select_current(CERT *c, X509 *x);
+void ssl_cert_set_cert_cb(CERT *c, int (*cb)(SSL *ssl, void *arg), void *arg);
+
+int ssl_verify_cert_chain(SSL *s, STACK_OF(X509) * sk);
+int ssl_add_cert_chain(SSL *s, CERT_PKEY *cpk, unsigned long *l);
+int ssl_build_cert_chain(CERT *c, X509_STORE *chain_store, int flags);
+int ssl_cert_set_cert_store(CERT *c, X509_STORE *store, int chain, int ref);
+int ssl_undefined_function(SSL *s);
+int ssl_undefined_void_function(void);
+int ssl_undefined_const_function(const SSL *s);
+CERT_PKEY *ssl_get_server_send_pkey(const SSL *s);
+EVP_PKEY *ssl_get_sign_pkey(SSL *s, const SSL_CIPHER *c);
+int ssl_cert_type(EVP_PKEY *pkey);
+
+/* ssl_get_compatible_server_ciphers determines the key exchange and
+ * authentication cipher suite masks compatible with the server configuration
+ * and current ClientHello parameters of |s|. It sets |*out_mask_k| to the key
+ * exchange mask and |*out_mask_a| to the authentication mask. */
+void ssl_get_compatible_server_ciphers(SSL *s, unsigned long *out_mask_k,
+ unsigned long *out_mask_a);
+
+STACK_OF(SSL_CIPHER) * ssl_get_ciphers_by_id(SSL *s);
+int ssl_verify_alarm_type(long type);
+int ssl_fill_hello_random(SSL *s, int server, uint8_t *field, size_t len);
+
+const SSL_CIPHER *ssl3_get_cipher_by_value(uint16_t value);
+uint16_t ssl3_get_cipher_value(const SSL_CIPHER *c);
+int ssl3_init_finished_mac(SSL *s);
+int ssl3_send_server_certificate(SSL *s);
+int ssl3_send_new_session_ticket(SSL *s);
+int ssl3_send_cert_status(SSL *s);
+int ssl3_get_finished(SSL *s, int state_a, int state_b);
+int ssl3_send_change_cipher_spec(SSL *s, int state_a, int state_b);
+int ssl3_prf(SSL *s, uint8_t *out, size_t out_len, const uint8_t *secret,
+ size_t secret_len, const char *label, size_t label_len,
+ const uint8_t *seed1, size_t seed1_len,
+ const uint8_t *seed2, size_t seed2_len);
+void ssl3_cleanup_key_block(SSL *s);
+int ssl3_do_write(SSL *s, int type);
+int ssl3_send_alert(SSL *s, int level, int desc);
+int ssl3_get_req_cert_type(SSL *s, uint8_t *p);
+long ssl3_get_message(SSL *s, int header_state, int body_state, int msg_type,
+ long max, int hash_message, int *ok);
+
+/* ssl3_hash_current_message incorporates the current handshake message into
+ * the handshake hash. */
+void ssl3_hash_current_message(SSL *s);
+
+/* ssl3_cert_verify_hash writes the CertificateVerify hash into the bytes
+ * pointed to by |out| and writes the number of bytes to |*out_len|. |out| must
+ * have room for EVP_MAX_MD_SIZE bytes. For TLS 1.2 and up, |*out_md| is used
+ * for the hash function, otherwise the hash function depends on the type of
+ * |pkey| and is written to |*out_md|. It returns one on success and zero on
+ * failure. */
+int ssl3_cert_verify_hash(SSL *s, uint8_t *out, size_t *out_len,
+ const EVP_MD **out_md, EVP_PKEY *pkey);
+
+int ssl3_send_finished(SSL *s, int a, int b, const char *sender, int slen);
+int ssl3_num_ciphers(void);
+const SSL_CIPHER *ssl3_get_cipher(unsigned int u);
+int ssl3_renegotiate(SSL *ssl);
+int ssl3_renegotiate_check(SSL *ssl);
+int ssl3_dispatch_alert(SSL *s);
+int ssl3_expect_change_cipher_spec(SSL *s);
+int ssl3_read_bytes(SSL *s, int type, uint8_t *buf, int len, int peek);
+int ssl3_write_bytes(SSL *s, int type, const void *buf, int len);
+int ssl3_final_finish_mac(SSL *s, const char *sender, int slen, uint8_t *p);
+int ssl3_cert_verify_mac(SSL *s, int md_nid, uint8_t *p);
+void ssl3_finish_mac(SSL *s, const uint8_t *buf, int len);
+void ssl3_free_digest_list(SSL *s);
+unsigned long ssl3_output_cert_chain(SSL *s, CERT_PKEY *cpk);
+const SSL_CIPHER *ssl3_choose_cipher(
+ SSL *ssl, STACK_OF(SSL_CIPHER) * clnt,
+ struct ssl_cipher_preference_list_st *srvr);
+int ssl3_setup_buffers(SSL *s);
+int ssl3_setup_read_buffer(SSL *s);
+int ssl3_setup_write_buffer(SSL *s);
+int ssl3_release_read_buffer(SSL *s);
+int ssl3_release_write_buffer(SSL *s);
+
+enum should_free_handshake_buffer_t {
+ free_handshake_buffer,
+ dont_free_handshake_buffer,
+};
+int ssl3_digest_cached_records(SSL *s, enum should_free_handshake_buffer_t);
+
+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);
+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);
+
+void ssl3_record_sequence_update(uint8_t *seq);
+int ssl3_do_change_cipher_spec(SSL *ssl);
+
+void ssl3_set_handshake_header(SSL *s, int htype, unsigned long len);
+int ssl3_handshake_write(SSL *s);
+
+int dtls1_do_write(SSL *s, int type);
+int ssl3_read_n(SSL *s, int n, int max, int extend);
+int dtls1_read_bytes(SSL *s, int type, uint8_t *buf, int len, int peek);
+int ssl3_write_pending(SSL *s, int type, const uint8_t *buf, unsigned int len);
+void dtls1_set_message_header(SSL *s, uint8_t mt, unsigned long len,
+ unsigned short seq_num, unsigned long frag_off,
+ unsigned long frag_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_send_change_cipher_spec(SSL *s, int a, int b);
+int dtls1_send_finished(SSL *s, int a, int b, const char *sender, int slen);
+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);
+void dtls1_get_message_header(uint8_t *data, struct hm_header_st *msg_hdr);
+void dtls1_get_ccs_header(uint8_t *data, struct ccs_header_st *ccs_hdr);
+void dtls1_reset_seq_numbers(SSL *s, int rw);
+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);
+void dtls1_hm_fragment_free(hm_fragment *frag);
+
+/* some client-only functions */
+int ssl3_send_client_hello(SSL *s);
+int ssl3_get_server_hello(SSL *s);
+int ssl3_get_certificate_request(SSL *s);
+int ssl3_get_new_session_ticket(SSL *s);
+int ssl3_get_cert_status(SSL *s);
+int ssl3_get_server_done(SSL *s);
+int ssl3_send_cert_verify(SSL *s);
+int ssl3_send_client_certificate(SSL *s);
+int ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey);
+int ssl3_send_client_key_exchange(SSL *s);
+int ssl3_get_server_key_exchange(SSL *s);
+int ssl3_get_server_certificate(SSL *s);
+int ssl3_check_cert_and_algorithm(SSL *s);
+int ssl3_send_next_proto(SSL *s);
+int ssl3_send_channel_id(SSL *s);
+
+int dtls1_client_hello(SSL *s);
+
+/* some server-only functions */
+int ssl3_get_initial_bytes(SSL *s);
+int ssl3_get_v2_client_hello(SSL *s);
+int ssl3_get_client_hello(SSL *s);
+int ssl3_send_server_hello(SSL *s);
+int ssl3_send_hello_request(SSL *s);
+int ssl3_send_server_key_exchange(SSL *s);
+int ssl3_send_certificate_request(SSL *s);
+int ssl3_send_server_done(SSL *s);
+int ssl3_get_client_certificate(SSL *s);
+int ssl3_get_client_key_exchange(SSL *s);
+int ssl3_get_cert_verify(SSL *s);
+int ssl3_get_next_proto(SSL *s);
+int ssl3_get_channel_id(SSL *s);
+
+int dtls1_new(SSL *s);
+int dtls1_accept(SSL *s);
+int dtls1_connect(SSL *s);
+void dtls1_free(SSL *s);
+long dtls1_ctrl(SSL *s, int cmd, long larg, void *parg);
+int dtls1_shutdown(SSL *s);
+
+long dtls1_get_message(SSL *s, int st1, int stn, int mt, long max,
+ int hash_message, int *ok);
+int dtls1_get_record(SSL *s);
+int dtls1_dispatch_alert(SSL *s);
+
+int ssl_init_wbio_buffer(SSL *s, int push);
+void ssl_free_wbio_buffer(SSL *s);
+
+/* tls1_prf computes the TLS PRF function for |s| as described in RFC 5246,
+ * section 5 and RFC 2246 section 5. It writes |out_len| bytes to |out|, using
+ * |secret| as the secret and |label| as the label. |seed1| and |seed2| are
+ * concatenated to form the seed parameter. It returns one on success and zero
+ * on failure. */
+int tls1_prf(SSL *s, uint8_t *out, size_t out_len, const uint8_t *secret,
+ size_t secret_len, const char *label, size_t label_len,
+ const uint8_t *seed1, size_t seed1_len,
+ const uint8_t *seed2, size_t seed2_len);
+
+int tls1_change_cipher_state(SSL *s, int which);
+int tls1_setup_key_block(SSL *s);
+int tls1_enc(SSL *s, int snd);
+int tls1_handshake_digest(SSL *s, uint8_t *out, size_t out_len);
+int tls1_final_finish_mac(SSL *s, const char *str, int slen, uint8_t *p);
+int tls1_cert_verify_mac(SSL *s, int md_nid, uint8_t *p);
+int tls1_generate_master_secret(SSL *s, uint8_t *out, const uint8_t *premaster,
+ size_t premaster_len);
+int tls1_export_keying_material(SSL *s, uint8_t *out, size_t olen,
+ const char *label, size_t llen,
+ const uint8_t *p, size_t plen, int use_context);
+int tls1_alert_code(int code);
+int ssl3_alert_code(int code);
+int ssl_ok(SSL *s);
+
+int ssl_check_srvr_ecc_cert_and_alg(X509 *x, SSL *s);
+
+char ssl_early_callback_init(struct ssl_early_callback_ctx *ctx);
+int tls1_ec_curve_id2nid(uint16_t curve_id);
+int tls1_ec_nid2curve_id(uint16_t *out_curve_id, int nid);
+
+/* tls1_check_curve parses ECParameters out of |cbs|, modifying it. It
+ * checks the curve is one of our preferences and writes the
+ * NamedCurve value to |*out_curve_id|. It returns one on success and
+ * zero on error. */
+int tls1_check_curve(SSL *s, CBS *cbs, uint16_t *out_curve_id);
+
+/* tls1_get_shared_curve returns the NID of the first preferred shared curve
+ * between client and server preferences. If none can be found, it returns
+ * NID_undef. */
+int tls1_get_shared_curve(SSL *s);
+
+/* tls1_set_curves converts the array of |ncurves| NIDs pointed to by |curves|
+ * into a newly allocated array of TLS curve IDs. On success, the function
+ * returns one and writes the array to |*out_curve_ids| and its size to
+ * |*out_curve_ids_len|. Otherwise, it returns zero. */
+int tls1_set_curves(uint16_t **out_curve_ids, size_t *out_curve_ids_len,
+ const int *curves, size_t ncurves);
+
+/* tls1_check_ec_cert returns one if |x| is an ECC certificate with curve and
+ * point format compatible with the client's preferences. Otherwise it returns
+ * zero. */
+int tls1_check_ec_cert(SSL *s, X509 *x);
+
+/* tls1_check_ec_tmp_key returns one if the EC temporary key is compatible with
+ * client extensions and zero otherwise. */
+int tls1_check_ec_tmp_key(SSL *s);
+
+int tls1_shared_list(SSL *s, const uint8_t *l1, size_t l1len, const uint8_t *l2,
+ size_t l2len, int nmatch);
+uint8_t *ssl_add_clienthello_tlsext(SSL *s, uint8_t *buf, uint8_t *limit,
+ size_t header_len);
+uint8_t *ssl_add_serverhello_tlsext(SSL *s, uint8_t *buf, uint8_t *limit);
+int ssl_parse_clienthello_tlsext(SSL *s, CBS *cbs);
+int ssl_parse_serverhello_tlsext(SSL *s, CBS *cbs);
+int ssl_prepare_clienthello_tlsext(SSL *s);
+int ssl_prepare_serverhello_tlsext(SSL *s);
+
+#define tlsext_tick_md EVP_sha256
+int tls1_process_ticket(SSL *s, const struct ssl_early_callback_ctx *ctx,
+ SSL_SESSION **ret);
+
+int tls12_get_sigandhash(uint8_t *p, const EVP_PKEY *pk, const EVP_MD *md);
+int tls12_get_sigid(const EVP_PKEY *pk);
+const EVP_MD *tls12_get_hash(uint8_t hash_alg);
+
+int tls1_channel_id_hash(EVP_MD_CTX *ctx, SSL *s);
+int tls1_record_handshake_hashes_for_channel_id(SSL *s);
+
+int tls1_set_sigalgs_list(CERT *c, const char *str, int client);
+int tls1_set_sigalgs(CERT *c, const int *salg, size_t salglen, int client);
+
+/* ssl_ctx_log_rsa_client_key_exchange logs |premaster| to |ctx|, if logging is
+ * enabled. It returns one on success and zero on failure. The entry is
+ * identified by the first 8 bytes of |encrypted_premaster|. */
+int ssl_ctx_log_rsa_client_key_exchange(SSL_CTX *ctx,
+ const uint8_t *encrypted_premaster,
+ size_t encrypted_premaster_len,
+ const uint8_t *premaster,
+ size_t premaster_len);
+
+/* ssl_ctx_log_master_secret logs |master| to |ctx|, if logging is enabled. It
+ * returns one on success and zero on failure. The entry is identified by
+ * |client_random|. */
+int ssl_ctx_log_master_secret(SSL_CTX *ctx, const uint8_t *client_random,
+ size_t client_random_len, const uint8_t *master,
+ size_t master_len);
+
+int ssl3_can_cutthrough(const SSL *s);
+
+/* ssl3_get_enc_method returns the SSL3_ENC_METHOD corresponding to
+ * |version|. */
+const SSL3_ENC_METHOD *ssl3_get_enc_method(uint16_t version);
+
+/* ssl3_get_max_server_version returns the maximum SSL/TLS version number
+ * supported by |s| as a server, or zero if all versions are disabled. */
+uint16_t ssl3_get_max_server_version(const SSL *s);
+
+/* ssl3_get_mutual_version selects the protocol version on |s| for a client
+ * which advertises |client_version|. If no suitable version exists, it returns
+ * zero. */
+uint16_t ssl3_get_mutual_version(SSL *s, uint16_t client_version);
+
+/* ssl3_get_max_client_version returns the maximum protocol version configured
+ * for the client. It is guaranteed that the set of allowed versions at or below
+ * this maximum version is contiguous. If all versions are disabled, it returns
+ * zero. */
+uint16_t ssl3_get_max_client_version(SSL *s);
+
+/* ssl3_is_version_enabled returns one if |version| is an enabled protocol
+ * version for |s| and zero otherwise. */
+int ssl3_is_version_enabled(SSL *s, uint16_t version);
+
+/* ssl3_version_from_wire maps |wire_version| to a protocol version. For
+ * SSLv3/TLS, the version is returned as-is. For DTLS, the corresponding TLS
+ * version is used. Note that this mapping is not injective but preserves
+ * comparisons.
+ *
+ * TODO(davidben): To normalize some DTLS-specific code, move away from using
+ * the wire version except at API boundaries. */
+uint16_t ssl3_version_from_wire(SSL *s, uint16_t wire_version);
+
+int ssl_add_serverhello_renegotiate_ext(SSL *s, uint8_t *p, int *len,
+ int maxlen);
+int ssl_parse_serverhello_renegotiate_ext(SSL *s, CBS *cbs, int *out_alert);
+int ssl_add_clienthello_renegotiate_ext(SSL *s, uint8_t *p, int *len,
+ int maxlen);
+int ssl_parse_clienthello_renegotiate_ext(SSL *s, CBS *cbs, int *out_alert);
+long ssl_get_algorithm2(SSL *s);
+int tls1_process_sigalgs(SSL *s, const CBS *sigalgs);
+
+/* tls1_choose_signing_digest returns a digest for use with |pkey| based on the
+ * peer's preferences recorded for |s| and the digests supported by |pkey|. */
+const EVP_MD *tls1_choose_signing_digest(SSL *s, EVP_PKEY *pkey);
+
+size_t tls12_get_psigalgs(SSL *s, const uint8_t **psigs);
+int tls12_check_peer_sigalg(const EVP_MD **out_md, int *out_alert, SSL *s,
+ CBS *cbs, EVP_PKEY *pkey);
+void ssl_set_client_disabled(SSL *s);
+
+int ssl_add_clienthello_use_srtp_ext(SSL *s, uint8_t *p, int *len, int maxlen);
+int ssl_parse_clienthello_use_srtp_ext(SSL *s, CBS *cbs, int *out_alert);
+int ssl_add_serverhello_use_srtp_ext(SSL *s, uint8_t *p, int *len, int maxlen);
+int ssl_parse_serverhello_use_srtp_ext(SSL *s, CBS *cbs, int *out_alert);
+
+#endif
diff --git a/src/ssl/ssl_rsa.c b/src/ssl/ssl_rsa.c
new file mode 100644
index 0000000..3d1bc62
--- /dev/null
+++ b/src/ssl/ssl_rsa.c
@@ -0,0 +1,707 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <stdio.h>
+
+#include <openssl/bio.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/pem.h>
+#include <openssl/x509.h>
+
+#include "ssl_locl.h"
+
+static int ssl_set_cert(CERT *c, X509 *x509);
+static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey);
+
+int SSL_use_certificate(SSL *ssl, X509 *x) {
+ if (x == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_use_certificate, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ if (!ssl_cert_inst(&ssl->cert)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_use_certificate, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ return ssl_set_cert(ssl->cert, x);
+}
+
+int SSL_use_certificate_file(SSL *ssl, const char *file, int type) {
+ int reason_code;
+ BIO *in;
+ int ret = 0;
+ X509 *x = NULL;
+
+ in = BIO_new(BIO_s_file());
+ if (in == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_use_certificate_file, ERR_R_BUF_LIB);
+ goto end;
+ }
+
+ if (BIO_read_filename(in, file) <= 0) {
+ OPENSSL_PUT_ERROR(SSL, SSL_use_certificate_file, ERR_R_SYS_LIB);
+ goto end;
+ }
+
+ if (type == SSL_FILETYPE_ASN1) {
+ reason_code = ERR_R_ASN1_LIB;
+ x = d2i_X509_bio(in, NULL);
+ } else if (type == SSL_FILETYPE_PEM) {
+ reason_code = ERR_R_PEM_LIB;
+ x = PEM_read_bio_X509(in, NULL, ssl->ctx->default_passwd_callback,
+ ssl->ctx->default_passwd_callback_userdata);
+ } else {
+ OPENSSL_PUT_ERROR(SSL, SSL_use_certificate_file, SSL_R_BAD_SSL_FILETYPE);
+ goto end;
+ }
+
+ if (x == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_use_certificate_file, reason_code);
+ goto end;
+ }
+
+ ret = SSL_use_certificate(ssl, x);
+
+end:
+ if (x != NULL) {
+ X509_free(x);
+ }
+ if (in != NULL) {
+ BIO_free(in);
+ }
+
+ return ret;
+}
+
+int SSL_use_certificate_ASN1(SSL *ssl, const uint8_t *d, int len) {
+ X509 *x;
+ int ret;
+
+ x = d2i_X509(NULL, &d, (long)len);
+ if (x == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_use_certificate_ASN1, ERR_R_ASN1_LIB);
+ return 0;
+ }
+
+ ret = SSL_use_certificate(ssl, x);
+ X509_free(x);
+ return ret;
+}
+
+int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa) {
+ EVP_PKEY *pkey;
+ int ret;
+
+ if (rsa == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_use_RSAPrivateKey, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ if (!ssl_cert_inst(&ssl->cert)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_use_RSAPrivateKey, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ pkey = EVP_PKEY_new();
+ if (pkey == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_use_RSAPrivateKey, ERR_R_EVP_LIB);
+ return 0;
+ }
+
+ RSA_up_ref(rsa);
+ EVP_PKEY_assign_RSA(pkey, rsa);
+
+ ret = ssl_set_pkey(ssl->cert, pkey);
+ EVP_PKEY_free(pkey);
+
+ return ret;
+}
+
+static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey) {
+ int i;
+
+ i = ssl_cert_type(pkey);
+ if (i < 0) {
+ OPENSSL_PUT_ERROR(SSL, ssl_set_pkey, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
+ return 0;
+ }
+
+ if (c->pkeys[i].x509 != NULL) {
+ EVP_PKEY *pktmp;
+ pktmp = X509_get_pubkey(c->pkeys[i].x509);
+ EVP_PKEY_copy_parameters(pktmp, pkey);
+ EVP_PKEY_free(pktmp);
+ ERR_clear_error();
+
+ /* Sanity-check that the private key and the certificate match, unless the
+ * key is opaque (in case of, say, a smartcard). */
+ if (!EVP_PKEY_is_opaque(pkey) &&
+ !X509_check_private_key(c->pkeys[i].x509, pkey)) {
+ X509_free(c->pkeys[i].x509);
+ c->pkeys[i].x509 = NULL;
+ return 0;
+ }
+ }
+
+ if (c->pkeys[i].privatekey != NULL) {
+ EVP_PKEY_free(c->pkeys[i].privatekey);
+ }
+ c->pkeys[i].privatekey = EVP_PKEY_dup(pkey);
+ c->key = &(c->pkeys[i]);
+
+ return 1;
+}
+
+int SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type) {
+ int reason_code, ret = 0;
+ BIO *in;
+ RSA *rsa = NULL;
+
+ in = BIO_new(BIO_s_file());
+ if (in == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_use_RSAPrivateKey_file, ERR_R_BUF_LIB);
+ goto end;
+ }
+
+ if (BIO_read_filename(in, file) <= 0) {
+ OPENSSL_PUT_ERROR(SSL, SSL_use_RSAPrivateKey_file, ERR_R_SYS_LIB);
+ goto end;
+ }
+
+ if (type == SSL_FILETYPE_ASN1) {
+ reason_code = ERR_R_ASN1_LIB;
+ rsa = d2i_RSAPrivateKey_bio(in, NULL);
+ } else if (type == SSL_FILETYPE_PEM) {
+ reason_code = ERR_R_PEM_LIB;
+ rsa =
+ PEM_read_bio_RSAPrivateKey(in, NULL, ssl->ctx->default_passwd_callback,
+ ssl->ctx->default_passwd_callback_userdata);
+ } else {
+ OPENSSL_PUT_ERROR(SSL, SSL_use_RSAPrivateKey_file, SSL_R_BAD_SSL_FILETYPE);
+ goto end;
+ }
+
+ if (rsa == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_use_RSAPrivateKey_file, reason_code);
+ goto end;
+ }
+ ret = SSL_use_RSAPrivateKey(ssl, rsa);
+ RSA_free(rsa);
+
+end:
+ if (in != NULL) {
+ BIO_free(in);
+ }
+ return ret;
+}
+
+int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, uint8_t *d, long len) {
+ int ret;
+ const uint8_t *p;
+ RSA *rsa;
+
+ p = d;
+ rsa = d2i_RSAPrivateKey(NULL, &p, (long)len);
+ if (rsa == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_use_RSAPrivateKey_ASN1, ERR_R_ASN1_LIB);
+ return 0;
+ }
+
+ ret = SSL_use_RSAPrivateKey(ssl, rsa);
+ RSA_free(rsa);
+ return ret;
+}
+
+int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey) {
+ int ret;
+
+ if (pkey == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_use_PrivateKey, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ if (!ssl_cert_inst(&ssl->cert)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_use_PrivateKey, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ ret = ssl_set_pkey(ssl->cert, pkey);
+ return ret;
+}
+
+int SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type) {
+ int reason_code, ret = 0;
+ BIO *in;
+ EVP_PKEY *pkey = NULL;
+
+ in = BIO_new(BIO_s_file());
+ if (in == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_use_PrivateKey_file, ERR_R_BUF_LIB);
+ goto end;
+ }
+
+ if (BIO_read_filename(in, file) <= 0) {
+ OPENSSL_PUT_ERROR(SSL, SSL_use_PrivateKey_file, ERR_R_SYS_LIB);
+ goto end;
+ }
+
+ if (type == SSL_FILETYPE_PEM) {
+ reason_code = 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) {
+ reason_code = ERR_R_ASN1_LIB;
+ pkey = d2i_PrivateKey_bio(in, NULL);
+ } else {
+ OPENSSL_PUT_ERROR(SSL, SSL_use_PrivateKey_file, SSL_R_BAD_SSL_FILETYPE);
+ goto end;
+ }
+
+ if (pkey == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_use_PrivateKey_file, reason_code);
+ goto end;
+ }
+ ret = SSL_use_PrivateKey(ssl, pkey);
+ EVP_PKEY_free(pkey);
+
+end:
+ if (in != NULL) {
+ BIO_free(in);
+ }
+ return ret;
+}
+
+int SSL_use_PrivateKey_ASN1(int type, SSL *ssl, const uint8_t *d, long len) {
+ int ret;
+ const uint8_t *p;
+ EVP_PKEY *pkey;
+
+ p = d;
+ pkey = d2i_PrivateKey(type, NULL, &p, (long)len);
+ if (pkey == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_use_PrivateKey_ASN1, ERR_R_ASN1_LIB);
+ return 0;
+ }
+
+ ret = SSL_use_PrivateKey(ssl, pkey);
+ EVP_PKEY_free(pkey);
+ return ret;
+}
+
+int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x) {
+ if (x == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_certificate,
+ ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ if (!ssl_cert_inst(&ctx->cert)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_certificate, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ return ssl_set_cert(ctx->cert, x);
+}
+
+static int ssl_set_cert(CERT *c, X509 *x) {
+ EVP_PKEY *pkey;
+ int i;
+
+ pkey = X509_get_pubkey(x);
+ if (pkey == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl_set_cert, SSL_R_X509_LIB);
+ return 0;
+ }
+
+ i = ssl_cert_type(pkey);
+ if (i < 0) {
+ OPENSSL_PUT_ERROR(SSL, ssl_set_cert, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
+ EVP_PKEY_free(pkey);
+ return 0;
+ }
+
+ if (c->pkeys[i].privatekey != NULL) {
+ EVP_PKEY_copy_parameters(pkey, c->pkeys[i].privatekey);
+ ERR_clear_error();
+
+ /* Sanity-check that the private key and the certificate match, unless the
+ * key is opaque (in case of, say, a smartcard). */
+ if (!EVP_PKEY_is_opaque(c->pkeys[i].privatekey) &&
+ !X509_check_private_key(x, c->pkeys[i].privatekey)) {
+ /* 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;
+ /* clear error queue */
+ ERR_clear_error();
+ }
+ }
+
+ EVP_PKEY_free(pkey);
+
+ if (c->pkeys[i].x509 != NULL) {
+ X509_free(c->pkeys[i].x509);
+ }
+ c->pkeys[i].x509 = X509_up_ref(x);
+ c->key = &(c->pkeys[i]);
+
+ return 1;
+}
+
+int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type) {
+ int reason_code;
+ BIO *in;
+ int ret = 0;
+ X509 *x = NULL;
+
+ in = BIO_new(BIO_s_file());
+ if (in == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_certificate_file, ERR_R_BUF_LIB);
+ goto end;
+ }
+
+ if (BIO_read_filename(in, file) <= 0) {
+ OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_certificate_file, ERR_R_SYS_LIB);
+ goto end;
+ }
+
+ if (type == SSL_FILETYPE_ASN1) {
+ reason_code = ERR_R_ASN1_LIB;
+ x = d2i_X509_bio(in, NULL);
+ } else if (type == SSL_FILETYPE_PEM) {
+ reason_code = ERR_R_PEM_LIB;
+ x = PEM_read_bio_X509(in, NULL, ctx->default_passwd_callback,
+ ctx->default_passwd_callback_userdata);
+ } else {
+ OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_certificate_file,
+ SSL_R_BAD_SSL_FILETYPE);
+ goto end;
+ }
+
+ if (x == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_certificate_file, reason_code);
+ goto end;
+ }
+
+ ret = SSL_CTX_use_certificate(ctx, x);
+
+end:
+ if (x != NULL) {
+ X509_free(x);
+ }
+ if (in != NULL) {
+ BIO_free(in);
+ }
+ return ret;
+}
+
+int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len, const uint8_t *d) {
+ X509 *x;
+ int ret;
+
+ x = d2i_X509(NULL, &d, (long)len);
+ if (x == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_certificate_ASN1, ERR_R_ASN1_LIB);
+ return 0;
+ }
+
+ ret = SSL_CTX_use_certificate(ctx, x);
+ X509_free(x);
+ return ret;
+}
+
+int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa) {
+ int ret;
+ EVP_PKEY *pkey;
+
+ if (rsa == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_RSAPrivateKey,
+ ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ if (!ssl_cert_inst(&ctx->cert)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_RSAPrivateKey, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ pkey = EVP_PKEY_new();
+ if (pkey == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_RSAPrivateKey, ERR_R_EVP_LIB);
+ return 0;
+ }
+
+ RSA_up_ref(rsa);
+ EVP_PKEY_assign_RSA(pkey, rsa);
+
+ ret = ssl_set_pkey(ctx->cert, pkey);
+ EVP_PKEY_free(pkey);
+ return ret;
+}
+
+int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file, int type) {
+ int reason_code, ret = 0;
+ BIO *in;
+ RSA *rsa = NULL;
+
+ in = BIO_new(BIO_s_file());
+ if (in == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_RSAPrivateKey_file, ERR_R_BUF_LIB);
+ goto end;
+ }
+
+ if (BIO_read_filename(in, file) <= 0) {
+ OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_RSAPrivateKey_file, ERR_R_SYS_LIB);
+ goto end;
+ }
+
+ if (type == SSL_FILETYPE_ASN1) {
+ reason_code = ERR_R_ASN1_LIB;
+ rsa = d2i_RSAPrivateKey_bio(in, NULL);
+ } else if (type == SSL_FILETYPE_PEM) {
+ reason_code = ERR_R_PEM_LIB;
+ rsa = PEM_read_bio_RSAPrivateKey(in, NULL, ctx->default_passwd_callback,
+ ctx->default_passwd_callback_userdata);
+ } else {
+ OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_RSAPrivateKey_file,
+ SSL_R_BAD_SSL_FILETYPE);
+ goto end;
+ }
+
+ if (rsa == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_RSAPrivateKey_file, reason_code);
+ goto end;
+ }
+ ret = SSL_CTX_use_RSAPrivateKey(ctx, rsa);
+ RSA_free(rsa);
+
+end:
+ if (in != NULL) {
+ BIO_free(in);
+ }
+ return ret;
+}
+
+int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const uint8_t *d, long len) {
+ int ret;
+ const uint8_t *p;
+ RSA *rsa;
+
+ p = d;
+ rsa = d2i_RSAPrivateKey(NULL, &p, (long)len);
+ if (rsa == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_RSAPrivateKey_ASN1, ERR_R_ASN1_LIB);
+ return 0;
+ }
+
+ ret = SSL_CTX_use_RSAPrivateKey(ctx, rsa);
+ RSA_free(rsa);
+ return ret;
+}
+
+int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey) {
+ if (pkey == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_PrivateKey, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ if (!ssl_cert_inst(&ctx->cert)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_PrivateKey, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ return ssl_set_pkey(ctx->cert, pkey);
+}
+
+int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type) {
+ int reason_code, ret = 0;
+ BIO *in;
+ EVP_PKEY *pkey = NULL;
+
+ in = BIO_new(BIO_s_file());
+ if (in == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_PrivateKey_file, ERR_R_BUF_LIB);
+ goto end;
+ }
+
+ if (BIO_read_filename(in, file) <= 0) {
+ OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_PrivateKey_file, ERR_R_SYS_LIB);
+ goto end;
+ }
+
+ if (type == SSL_FILETYPE_PEM) {
+ reason_code = 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) {
+ reason_code = ERR_R_ASN1_LIB;
+ pkey = d2i_PrivateKey_bio(in, NULL);
+ } else {
+ OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_PrivateKey_file, SSL_R_BAD_SSL_FILETYPE);
+ goto end;
+ }
+
+ if (pkey == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_PrivateKey_file, reason_code);
+ goto end;
+ }
+ ret = SSL_CTX_use_PrivateKey(ctx, pkey);
+ EVP_PKEY_free(pkey);
+
+end:
+ if (in != NULL) {
+ BIO_free(in);
+ }
+ return ret;
+}
+
+int SSL_CTX_use_PrivateKey_ASN1(int type, SSL_CTX *ctx, const uint8_t *d,
+ long len) {
+ int ret;
+ const uint8_t *p;
+ EVP_PKEY *pkey;
+
+ p = d;
+ pkey = d2i_PrivateKey(type, NULL, &p, (long)len);
+ if (pkey == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_PrivateKey_ASN1, ERR_R_ASN1_LIB);
+ return 0;
+ }
+
+ ret = SSL_CTX_use_PrivateKey(ctx, pkey);
+ EVP_PKEY_free(pkey);
+ return ret;
+}
+
+
+/* Read a file 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. */
+int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file) {
+ BIO *in;
+ int ret = 0;
+ X509 *x = NULL;
+
+ ERR_clear_error(); /* clear error stack for SSL_CTX_use_certificate() */
+
+ in = BIO_new(BIO_s_file());
+ if (in == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_certificate_chain_file, ERR_R_BUF_LIB);
+ goto end;
+ }
+
+ if (BIO_read_filename(in, file) <= 0) {
+ OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_certificate_chain_file, ERR_R_SYS_LIB);
+ goto end;
+ }
+
+ x = PEM_read_bio_X509_AUX(in, NULL, ctx->default_passwd_callback,
+ ctx->default_passwd_callback_userdata);
+ if (x == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_certificate_chain_file, ERR_R_PEM_LIB);
+ goto end;
+ }
+
+ ret = SSL_CTX_use_certificate(ctx, x);
+
+ if (ERR_peek_error() != 0) {
+ ret = 0; /* Key/certificate mismatch doesn't imply ret==0 ... */
+ }
+
+ if (ret) {
+ /* If we could set up our certificate, now proceed to the CA
+ * certificates. */
+ X509 *ca;
+ int r;
+ unsigned long err;
+
+ SSL_CTX_clear_chain_certs(ctx);
+
+ while ((ca = PEM_read_bio_X509(in, NULL, ctx->default_passwd_callback,
+ ctx->default_passwd_callback_userdata)) !=
+ NULL) {
+ r = SSL_CTX_add0_chain_cert(ctx, ca);
+ if (!r) {
+ X509_free(ca);
+ ret = 0;
+ goto end;
+ }
+ /* Note that we must not free r if it was successfully added to the chain
+ * (while we must free the main certificate, since its reference count is
+ * increased by SSL_CTX_use_certificate). */
+ }
+
+ /* 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();
+ } else {
+ ret = 0; /* some real error */
+ }
+ }
+
+end:
+ if (x != NULL) {
+ X509_free(x);
+ }
+ if (in != NULL) {
+ BIO_free(in);
+ }
+ return ret;
+}
diff --git a/src/ssl/ssl_sess.c b/src/ssl/ssl_sess.c
new file mode 100644
index 0000000..c5069d8
--- /dev/null
+++ b/src/ssl/ssl_sess.c
@@ -0,0 +1,920 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <stdio.h>
+
+#include <openssl/engine.h>
+#include <openssl/err.h>
+#include <openssl/lhash.h>
+#include <openssl/mem.h>
+#include <openssl/rand.h>
+
+#include "ssl_locl.h"
+
+/* The address of this is a magic value, a pointer to which is returned by
+ * SSL_magic_pending_session_ptr(). It allows a session callback to indicate
+ * that it needs to asynchronously fetch session information. */
+static const char g_pending_session_magic = 0;
+
+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);
+
+SSL_SESSION *SSL_magic_pending_session_ptr(void) {
+ return (SSL_SESSION *)&g_pending_session_magic;
+}
+
+SSL_SESSION *SSL_get_session(const SSL *ssl)
+{
+ /* aka SSL_get0_session; gets 0 objects, just returns a copy of the pointer */
+ return ssl->session;
+}
+
+SSL_SESSION *SSL_get1_session(SSL *ssl) {
+ /* variant of SSL_get_session: caller really gets something */
+ 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;
+}
+
+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);
+}
+
+int SSL_SESSION_set_ex_data(SSL_SESSION *s, int idx, void *arg) {
+ return CRYPTO_set_ex_data(&s->ex_data, idx, arg);
+}
+
+void *SSL_SESSION_get_ex_data(const SSL_SESSION *s, int idx) {
+ return CRYPTO_get_ex_data(&s->ex_data, idx);
+}
+
+SSL_SESSION *SSL_SESSION_new(void) {
+ SSL_SESSION *ss;
+
+ ss = (SSL_SESSION *)OPENSSL_malloc(sizeof(SSL_SESSION));
+ if (ss == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_SESSION_new, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ memset(ss, 0, sizeof(SSL_SESSION));
+
+ ss->verify_result = 1; /* avoid 0 (= X509_V_OK) just in case */
+ ss->references = 1;
+ ss->timeout = SSL_DEFAULT_SESSION_TIMEOUT;
+ ss->time = (unsigned long)time(NULL);
+ CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data);
+ return ss;
+}
+
+const uint8_t *SSL_SESSION_get_id(const SSL_SESSION *s, unsigned int *len) {
+ if (len) {
+ *len = s->session_id_length;
+ }
+ return s->session_id;
+}
+
+/* Even with SSLv2, we have 16 bytes (128 bits) of session ID space.
+ * SSLv3/TLSv1 has 32 bytes (256 bits). 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 RAND 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 ... */
+static int def_generate_session_id(const SSL *ssl, uint8_t *id,
+ unsigned int *id_len) {
+ static const unsigned kMaxAttempts = 10;
+ unsigned int retry = 0;
+ do {
+ if (!RAND_bytes(id, *id_len)) {
+ return 0;
+ }
+ } while (SSL_has_matching_session_id(ssl, id, *id_len) &&
+ (++retry < kMaxAttempts));
+
+ if (retry < kMaxAttempts) {
+ 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) {
+ /* This gets used by clients and servers. */
+
+ unsigned int tmp;
+ SSL_SESSION *ss = NULL;
+ GEN_SESSION_CB cb = def_generate_session_id;
+
+ if (s->mode & SSL_MODE_NO_SESSION_CREATION) {
+ OPENSSL_PUT_ERROR(SSL, ssl_get_new_session,
+ SSL_R_SESSION_MAY_NOT_BE_CREATED);
+ return 0;
+ }
+
+ ss = SSL_SESSION_new();
+ if (ss == NULL) {
+ return 0;
+ }
+
+ /* If the context has a default timeout, use it over the default. */
+ if (s->initial_ctx->session_timeout != 0) {
+ ss->timeout = s->initial_ctx->session_timeout;
+ }
+
+ if (s->session != NULL) {
+ SSL_SESSION_free(s->session);
+ s->session = NULL;
+ }
+
+ if (session) {
+ if (s->version == SSL3_VERSION || s->version == TLS1_VERSION ||
+ s->version == TLS1_1_VERSION || s->version == TLS1_2_VERSION ||
+ s->version == DTLS1_VERSION || s->version == DTLS1_2_VERSION) {
+ ss->ssl_version = s->version;
+ ss->session_id_length = SSL3_SSL_SESSION_ID_LENGTH;
+ } else {
+ OPENSSL_PUT_ERROR(SSL, ssl_get_new_session,
+ 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->initial_ctx->generate_session_id) {
+ cb = s->initial_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 */
+ OPENSSL_PUT_ERROR(SSL, ssl_get_new_session,
+ 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 || tmp > ss->session_id_length) {
+ /* The callback set an illegal length */
+ OPENSSL_PUT_ERROR(SSL, ssl_get_new_session,
+ 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)) {
+ OPENSSL_PUT_ERROR(SSL, ssl_get_new_session,
+ SSL_R_SSL_SESSION_ID_CONFLICT);
+ SSL_SESSION_free(ss);
+ return 0;
+ }
+
+ sess_id_done:
+ if (s->tlsext_hostname) {
+ ss->tlsext_hostname = BUF_strdup(s->tlsext_hostname);
+ if (ss->tlsext_hostname == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl_get_new_session, 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)) {
+ OPENSSL_PUT_ERROR(SSL, ssl_get_new_session, 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;
+}
+
+/* ssl_get_prev attempts to find an SSL_SESSION to be used to resume this
+ * connection. It is only called by servers.
+ *
+ * ctx: contains the early callback context, which is the result of a
+ * shallow parse of the ClientHello.
+ *
+ * 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.
+ * - Both for new and resumed sessions, s->tlsext_ticket_expected is set to 1
+ * if the server should issue a new session ticket (to 0 otherwise). */
+int ssl_get_prev_session(SSL *s, const struct ssl_early_callback_ctx *ctx) {
+ /* This is used only by servers. */
+ SSL_SESSION *ret = NULL;
+ int fatal = 0;
+ int try_session_cache = 1;
+ int r;
+
+ if (ctx->session_id_len > SSL_MAX_SSL_SESSION_ID_LENGTH) {
+ goto err;
+ }
+
+ if (ctx->session_id_len == 0) {
+ try_session_cache = 0;
+ }
+
+ r = tls1_process_ticket(s, ctx, &ret); /* sets s->tlsext_ticket_expected */
+ switch (r) {
+ case -1: /* Error during processing */
+ fatal = 1;
+ goto err;
+
+ case 0: /* No ticket found */
+ case 1: /* Zero length ticket found */
+ break; /* Ok to carry on processing session id. */
+
+ case 2: /* Ticket found but not decrypted. */
+ case 3: /* Ticket decrypted, *ret has been set. */
+ try_session_cache = 0;
+ break;
+
+ default:
+ abort();
+ }
+
+ if (try_session_cache && ret == NULL &&
+ !(s->initial_ctx->session_cache_mode &
+ SSL_SESS_CACHE_NO_INTERNAL_LOOKUP)) {
+ SSL_SESSION data;
+ data.ssl_version = s->version;
+ data.session_id_length = ctx->session_id_len;
+ if (ctx->session_id_len == 0) {
+ return 0;
+ }
+ memcpy(data.session_id, ctx->session_id, ctx->session_id_len);
+ CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
+ ret = lh_SSL_SESSION_retrieve(s->initial_ctx->sessions, &data);
+ if (ret != NULL) {
+ /* don't allow other threads to steal it: */
+ CRYPTO_add(&ret->references, 1, CRYPTO_LOCK_SSL_SESSION);
+ }
+ CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
+ if (ret == NULL) {
+ s->initial_ctx->stats.sess_miss++;
+ }
+ }
+
+ if (try_session_cache && ret == NULL &&
+ s->initial_ctx->get_session_cb != NULL) {
+ int copy = 1;
+
+ ret = s->initial_ctx->get_session_cb(s, (uint8_t *)ctx->session_id,
+ ctx->session_id_len, &copy);
+ if (ret != NULL) {
+ if (ret == SSL_magic_pending_session_ptr()) {
+ /* This is a magic value which indicates that the callback needs to
+ * unwind the stack and figure out the session asynchronously. */
+ return PENDING_SESSION;
+ }
+ s->initial_ctx->stats.sess_cb_hit++;
+
+ /* Increment reference count now if the session callback asks us to do so
+ * (note that if the session structures returned by the callback are
+ * shared between threads, it must handle the reference count itself
+ * [i.e. copy == 0], or things won't be thread-safe). */
+ if (copy) {
+ CRYPTO_add(&ret->references, 1, CRYPTO_LOCK_SSL_SESSION);
+ }
+
+ /* Add the externally cached session to the internal cache as well if and
+ * only if we are supposed to. */
+ if (!(s->initial_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->initial_ctx, ret);
+ }
+ }
+ }
+
+ if (ret == NULL) {
+ goto err;
+ }
+
+ /* Now ret is non-NULL and we own one of its reference counts. */
+
+ if (ret->sid_ctx_length != s->sid_ctx_length ||
+ memcmp(ret->sid_ctx, s->sid_ctx, ret->sid_ctx_length)) {
+ /* We have the session requested by the client, but we don't want to use it
+ * in this context. */
+ goto err; /* treat like cache miss */
+ }
+
+ 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). */
+ OPENSSL_PUT_ERROR(SSL, ssl_get_prev_session,
+ SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED);
+ fatal = 1;
+ goto err;
+ }
+
+ if (ret->timeout < (long)(time(NULL) - ret->time)) {
+ /* timeout */
+ s->initial_ctx->stats.sess_timeout++;
+ if (try_session_cache) {
+ /* session was from the cache, so remove it */
+ SSL_CTX_remove_session(s->initial_ctx, ret);
+ }
+ goto err;
+ }
+
+ s->initial_ctx->stats.sess_hit++;
+
+ if (s->session != NULL) {
+ SSL_SESSION_free(s->session);
+ }
+ s->session = ret;
+ s->verify_result = s->session->verify_result;
+ return 1;
+
+err:
+ if (ret != NULL) {
+ SSL_SESSION_free(ret);
+ if (!try_session_cache) {
+ /* The session was from a ticket, so we should
+ * issue a ticket for the new session */
+ s->tlsext_ticket_expected = 1;
+ }
+ }
+ if (fatal) {
+ 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);
+ if (!lh_SSL_SESSION_insert(ctx->sessions, &s, c)) {
+ return 0;
+ }
+
+ /* 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;
+ }
+ ctx->stats.sess_cache_full++;
+ }
+ }
+ }
+
+ CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
+ return ret;
+}
+
+int SSL_CTX_remove_session(SSL_CTX *ctx, SSL_SESSION *c) {
+ return remove_session_lock(ctx, c, 1);
+}
+
+static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lock) {
+ SSL_SESSION *r;
+ int ret = 0;
+
+ if (c != NULL && c->session_id_length != 0) {
+ if (lock) {
+ CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
+ }
+ r = lh_SSL_SESSION_retrieve(ctx->sessions, c);
+ if (r == c) {
+ ret = 1;
+ r = lh_SSL_SESSION_delete(ctx->sessions, c);
+ SSL_SESSION_list_remove(ctx, c);
+ }
+
+ if (lock) {
+ 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);
+
+ OPENSSL_cleanse(ss->master_key, sizeof ss->master_key);
+ OPENSSL_cleanse(ss->session_id, sizeof ss->session_id);
+ if (ss->sess_cert != NULL) {
+ ssl_sess_cert_free(ss->sess_cert);
+ }
+ if (ss->peer != NULL) {
+ X509_free(ss->peer);
+ }
+ if (ss->tlsext_hostname != NULL) {
+ OPENSSL_free(ss->tlsext_hostname);
+ }
+ if (ss->tlsext_tick != NULL) {
+ OPENSSL_free(ss->tlsext_tick);
+ }
+ if (ss->tlsext_signed_cert_timestamp_list != NULL) {
+ OPENSSL_free(ss->tlsext_signed_cert_timestamp_list);
+ }
+ if (ss->ocsp_response != NULL) {
+ OPENSSL_free(ss->ocsp_response);
+ }
+ if (ss->psk_identity != NULL) {
+ OPENSSL_free(ss->psk_identity);
+ }
+ OPENSSL_cleanse(ss, sizeof(*ss));
+ OPENSSL_free(ss);
+}
+
+int SSL_set_session(SSL *s, SSL_SESSION *session) {
+ if (s->session == session) {
+ return 1;
+ }
+
+ if (s->session != NULL) {
+ SSL_SESSION_free(s->session);
+ }
+ s->session = session;
+ if (session != NULL) {
+ CRYPTO_add(&session->references, 1, CRYPTO_LOCK_SSL_SESSION);
+ s->verify_result = session->verify_result;
+ }
+
+ return 1;
+}
+
+long SSL_SESSION_set_timeout(SSL_SESSION *s, long t) {
+ if (s == NULL) {
+ return 0;
+ }
+
+ s->timeout = t;
+ return 1;
+}
+
+long SSL_SESSION_get_timeout(const SSL_SESSION *s) {
+ if (s == NULL) {
+ return 0;
+ }
+
+ return s->timeout;
+}
+
+long SSL_SESSION_get_time(const SSL_SESSION *s) {
+ if (s == NULL) {
+ return 0;
+ }
+
+ return s->time;
+}
+
+long SSL_SESSION_set_time(SSL_SESSION *s, long t) {
+ if (s == NULL) {
+ return 0;
+ }
+
+ s->time = t;
+ return t;
+}
+
+X509 *SSL_SESSION_get0_peer(SSL_SESSION *s) { return s->peer; }
+
+int SSL_SESSION_set1_id_context(SSL_SESSION *s, const uint8_t *sid_ctx,
+ unsigned int sid_ctx_len) {
+ if (sid_ctx_len > SSL_MAX_SID_CTX_LENGTH) {
+ OPENSSL_PUT_ERROR(SSL, SSL_SESSION_set1_id_context,
+ 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;
+}
+
+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;
+}
+
+long SSL_CTX_get_timeout(const SSL_CTX *s) {
+ if (s == NULL) {
+ return 0;
+ }
+
+ return s->session_timeout;
+}
+
+typedef struct timeout_param_st {
+ SSL_CTX *ctx;
+ long time;
+ LHASH_OF(SSL_SESSION) * cache;
+} TIMEOUT_PARAM;
+
+static void timeout_doall_arg(SSL_SESSION *sess, void *void_param) {
+ TIMEOUT_PARAM *param = void_param;
+
+ if (param->time == 0 ||
+ param->time > (sess->time + sess->timeout)) {
+ /* timeout */
+ /* The reason we don't call SSL_CTX_remove_session() is to
+ * save on locking overhead */
+ (void) lh_SSL_SESSION_delete(param->cache, sess);
+ SSL_SESSION_list_remove(param->ctx, sess);
+ sess->not_resumable = 1;
+ if (param->ctx->remove_session_cb != NULL) {
+ param->ctx->remove_session_cb(param->ctx, sess);
+ }
+ SSL_SESSION_free(sess);
+ }
+}
+
+void SSL_CTX_flush_sessions(SSL_CTX *s, long t) {
+ 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);
+ lh_SSL_SESSION_doall_arg(tp.cache, timeout_doall_arg, &tp);
+ CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
+}
+
+int ssl_clear_bad_session(SSL *s) {
+ if (s->session != NULL && !(s->shutdown & SSL_SENT_SHUTDOWN) &&
+ !SSL_in_init(s)) {
+ SSL_CTX_remove_session(s->ctx, s->session);
+ return 1;
+ }
+
+ 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;
+}
+
+int (*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx))(SSL *ssl, SSL_SESSION *sess) {
+ return ctx->new_session_cb;
+}
+
+void SSL_CTX_sess_set_remove_cb(SSL_CTX *ctx,
+ void (*cb)(SSL_CTX *ctx, SSL_SESSION *sess)) {
+ ctx->remove_session_cb = cb;
+}
+
+void (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx))(SSL_CTX *ctx,
+ SSL_SESSION *sess) {
+ return ctx->remove_session_cb;
+}
+
+void SSL_CTX_sess_set_get_cb(SSL_CTX *ctx,
+ SSL_SESSION *(*cb)(struct ssl_st *ssl,
+ uint8_t *data, int len,
+ int *copy)) {
+ ctx->get_session_cb = cb;
+}
+
+SSL_SESSION *(*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx))(SSL *ssl, uint8_t *data,
+ int len, int *copy) {
+ return ctx->get_session_cb;
+}
+
+void SSL_CTX_set_info_callback(SSL_CTX *ctx,
+ void (*cb)(const SSL *ssl, int type, int val)) {
+ ctx->info_callback = cb;
+}
+
+void (*SSL_CTX_get_info_callback(SSL_CTX *ctx))(const SSL *ssl, int type,
+ int val) {
+ return ctx->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;
+}
+
+int (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx))(SSL *ssl, X509 **x509,
+ EVP_PKEY **pkey) {
+ return ctx->client_cert_cb;
+}
+
+void SSL_CTX_set_cookie_generate_cb(SSL_CTX *ctx,
+ int (*cb)(SSL *ssl, uint8_t *cookie,
+ size_t *cookie_len)) {
+ ctx->app_gen_cookie_cb = cb;
+}
+
+void SSL_CTX_set_cookie_verify_cb(SSL_CTX *ctx,
+ int (*cb)(SSL *ssl, const uint8_t *cookie,
+ size_t cookie_len)) {
+ ctx->app_verify_cookie_cb = cb;
+}
+
+void SSL_CTX_set_channel_id_cb(SSL_CTX *ctx,
+ void (*cb)(SSL *ssl, EVP_PKEY **pkey)) {
+ ctx->channel_id_cb = cb;
+}
+
+void (*SSL_CTX_get_channel_id_cb(SSL_CTX *ctx))(SSL *ssl, EVP_PKEY **pkey) {
+ return ctx->channel_id_cb;
+}
+
+IMPLEMENT_PEM_rw(SSL_SESSION, SSL_SESSION, PEM_STRING_SSL_SESSION, SSL_SESSION)
diff --git a/src/ssl/ssl_stat.c b/src/ssl/ssl_stat.c
new file mode 100644
index 0000000..450ed7c
--- /dev/null
+++ b/src/ssl/ssl_stat.c
@@ -0,0 +1,1018 @@
+/* ssl/ssl_stat.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.]
+ */
+/* ====================================================================
+ * 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 <stdio.h>
+#include "ssl_locl.h"
+
+const char *SSL_state_string_long(const SSL *s) {
+ const char *str;
+
+ switch (s->state) {
+ 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_BEFORE | SSL_ST_ACCEPT:
+ str = "before/accept 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:
+ case SSL3_ST_SR_CHANGE:
+ str = "SSLv3 read change cipher spec";
+ 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_SR_CLNT_HELLO_D:
+ str = "SSLv3 read client hello D";
+ 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;
+
+ /* SSLv2/v3 compatibility states */
+ /* client */
+ case SSL23_ST_CW_CLNT_HELLO_A:
+ str = "SSLv2/v3 write client hello A";
+ break;
+
+ case SSL23_ST_CW_CLNT_HELLO_B:
+ str = "SSLv2/v3 write client hello B";
+ break;
+
+ case SSL23_ST_CR_SRVR_HELLO_A:
+ str = "SSLv2/v3 read server hello A";
+ break;
+
+ case SSL23_ST_CR_SRVR_HELLO_B:
+ str = "SSLv2/v3 read server hello B";
+ break;
+
+ /* server */
+ case SSL23_ST_SR_CLNT_HELLO:
+ str = "SSLv2/v3 read client hello";
+ break;
+
+ case SSL23_ST_SR_V2_CLNT_HELLO:
+ str = "SSLv2/v3 read v2 client hello";
+ break;
+
+ case SSL23_ST_SR_SWITCH_VERSION:
+ str = "SSLv2/v3 switch version";
+ 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;
+}
+
+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;
+}
+
+const char *SSL_state_string(const SSL *s) {
+ const char *str;
+
+ switch (s->state) {
+ 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_CR_CHANGE:
+ case SSL3_ST_SR_CHANGE:
+ str = "3RCCS_";
+ 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_SR_CLNT_HELLO_D:
+ str = "3RCH_D";
+ 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;
+
+ /* SSLv2/v3 compatibility states */
+ /* client */
+ case SSL23_ST_CW_CLNT_HELLO_A:
+ str = "23WCHA";
+ break;
+
+ case SSL23_ST_CW_CLNT_HELLO_B:
+ str = "23WCHB";
+ break;
+
+ case SSL23_ST_CR_SRVR_HELLO_A:
+ str = "23RSHA";
+ break;
+
+ case SSL23_ST_CR_SRVR_HELLO_B:
+ str = "23RSHA";
+ break;
+
+ /* server */
+ case SSL23_ST_SR_CLNT_HELLO:
+ str = "23RCH_";
+ break;
+
+ case SSL23_ST_SR_V2_CLNT_HELLO:
+ str = "23R2CH";
+ break;
+
+ case SSL23_ST_SR_SWITCH_VERSION:
+ str = "23RSW_";
+ 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;
+}
+
+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";
+ }
+
+ return "unknown";
+}
+
+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";
+ }
+
+ return "U";
+}
+
+const char *SSL_alert_desc_string(int value) {
+ const char *str;
+
+ switch (value & 0xff) {
+ case SSL3_AD_CLOSE_NOTIFY:
+ str = "CN";
+ break;
+
+ case SSL3_AD_UNEXPECTED_MESSAGE:
+ str = "UM";
+ break;
+
+ case SSL3_AD_BAD_RECORD_MAC:
+ str = "BM";
+ break;
+
+ case SSL3_AD_DECOMPRESSION_FAILURE:
+ str = "DF";
+ break;
+
+ case SSL3_AD_HANDSHAKE_FAILURE:
+ str = "HF";
+ break;
+
+ case SSL3_AD_NO_CERTIFICATE:
+ str = "NC";
+ break;
+
+ case SSL3_AD_BAD_CERTIFICATE:
+ str = "BC";
+ break;
+
+ case SSL3_AD_UNSUPPORTED_CERTIFICATE:
+ str = "UC";
+ break;
+
+ case SSL3_AD_CERTIFICATE_REVOKED:
+ str = "CR";
+ break;
+
+ case SSL3_AD_CERTIFICATE_EXPIRED:
+ str = "CE";
+ break;
+
+ case SSL3_AD_CERTIFICATE_UNKNOWN:
+ str = "CU";
+ break;
+
+ case SSL3_AD_ILLEGAL_PARAMETER:
+ str = "IP";
+ break;
+
+ case TLS1_AD_DECRYPTION_FAILED:
+ str = "DC";
+ break;
+
+ case TLS1_AD_RECORD_OVERFLOW:
+ str = "RO";
+ break;
+
+ case TLS1_AD_UNKNOWN_CA:
+ str = "CA";
+ break;
+
+ case TLS1_AD_ACCESS_DENIED:
+ str = "AD";
+ break;
+
+ case TLS1_AD_DECODE_ERROR:
+ str = "DE";
+ break;
+
+ case TLS1_AD_DECRYPT_ERROR:
+ str = "CY";
+ break;
+
+ case TLS1_AD_EXPORT_RESTRICTION:
+ str = "ER";
+ break;
+
+ case TLS1_AD_PROTOCOL_VERSION:
+ str = "PV";
+ break;
+
+ case TLS1_AD_INSUFFICIENT_SECURITY:
+ str = "IS";
+ break;
+
+ case TLS1_AD_INTERNAL_ERROR:
+ str = "IE";
+ break;
+
+ case TLS1_AD_USER_CANCELLED:
+ str = "US";
+ break;
+
+ case TLS1_AD_NO_RENEGOTIATION:
+ str = "NR";
+ break;
+
+ case TLS1_AD_UNSUPPORTED_EXTENSION:
+ str = "UE";
+ break;
+
+ case TLS1_AD_CERTIFICATE_UNOBTAINABLE:
+ str = "CO";
+ break;
+
+ case TLS1_AD_UNRECOGNIZED_NAME:
+ str = "UN";
+ break;
+
+ case TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE:
+ str = "BR";
+ break;
+
+ case TLS1_AD_BAD_CERTIFICATE_HASH_VALUE:
+ str = "BH";
+ break;
+
+ case TLS1_AD_UNKNOWN_PSK_IDENTITY:
+ str = "UP";
+ break;
+
+ default:
+ str = "UK";
+ break;
+ }
+
+ return str;
+}
+
+const char *SSL_alert_desc_string_long(int value) {
+ const char *str;
+
+ switch (value & 0xff) {
+ case SSL3_AD_CLOSE_NOTIFY:
+ str = "close notify";
+ break;
+
+ case SSL3_AD_UNEXPECTED_MESSAGE:
+ str = "unexpected_message";
+ break;
+
+ case SSL3_AD_BAD_RECORD_MAC:
+ str = "bad record mac";
+ break;
+
+ case SSL3_AD_DECOMPRESSION_FAILURE:
+ str = "decompression failure";
+ break;
+
+ case SSL3_AD_HANDSHAKE_FAILURE:
+ str = "handshake failure";
+ break;
+
+ case SSL3_AD_NO_CERTIFICATE:
+ str = "no certificate";
+ break;
+
+ case SSL3_AD_BAD_CERTIFICATE:
+ str = "bad certificate";
+ break;
+
+ case SSL3_AD_UNSUPPORTED_CERTIFICATE:
+ str = "unsupported certificate";
+ break;
+
+ case SSL3_AD_CERTIFICATE_REVOKED:
+ str = "certificate revoked";
+ break;
+
+ case SSL3_AD_CERTIFICATE_EXPIRED:
+ str = "certificate expired";
+ break;
+
+ case SSL3_AD_CERTIFICATE_UNKNOWN:
+ str = "certificate unknown";
+ break;
+
+ case SSL3_AD_ILLEGAL_PARAMETER:
+ str = "illegal parameter";
+ break;
+
+ case TLS1_AD_DECRYPTION_FAILED:
+ str = "decryption failed";
+ break;
+
+ case TLS1_AD_RECORD_OVERFLOW:
+ str = "record overflow";
+ break;
+
+ case TLS1_AD_UNKNOWN_CA:
+ str = "unknown CA";
+ break;
+
+ case TLS1_AD_ACCESS_DENIED:
+ str = "access denied";
+ break;
+
+ case TLS1_AD_DECODE_ERROR:
+ str = "decode error";
+ break;
+
+ case TLS1_AD_DECRYPT_ERROR:
+ str = "decrypt error";
+ break;
+
+ case TLS1_AD_EXPORT_RESTRICTION:
+ str = "export restriction";
+ break;
+
+ case TLS1_AD_PROTOCOL_VERSION:
+ str = "protocol version";
+ break;
+
+ case TLS1_AD_INSUFFICIENT_SECURITY:
+ str = "insufficient security";
+ break;
+
+ case TLS1_AD_INTERNAL_ERROR:
+ str = "internal error";
+ break;
+
+ case TLS1_AD_USER_CANCELLED:
+ str = "user canceled";
+ break;
+
+ case TLS1_AD_NO_RENEGOTIATION:
+ str = "no renegotiation";
+ break;
+
+ case TLS1_AD_UNSUPPORTED_EXTENSION:
+ str = "unsupported extension";
+ break;
+
+ case TLS1_AD_CERTIFICATE_UNOBTAINABLE:
+ str = "certificate unobtainable";
+ break;
+
+ case TLS1_AD_UNRECOGNIZED_NAME:
+ str = "unrecognized name";
+ break;
+
+ case TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE:
+ str = "bad certificate status response";
+ break;
+
+ case TLS1_AD_BAD_CERTIFICATE_HASH_VALUE:
+ str = "bad certificate hash value";
+ break;
+
+ case TLS1_AD_UNKNOWN_PSK_IDENTITY:
+ str = "unknown PSK identity";
+ break;
+
+ default:
+ str = "unknown";
+ break;
+ }
+
+ return str;
+}
+
+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;
+}
diff --git a/src/ssl/ssl_test.c b/src/ssl/ssl_test.c
new file mode 100644
index 0000000..70291a2
--- /dev/null
+++ b/src/ssl/ssl_test.c
@@ -0,0 +1,456 @@
+/* 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 <stdio.h>
+#include <string.h>
+
+#include <openssl/base64.h>
+#include <openssl/bio.h>
+#include <openssl/err.h>
+#include <openssl/ssl.h>
+
+typedef struct {
+ int id;
+ int in_group_flag;
+} EXPECTED_CIPHER;
+
+typedef struct {
+ /* The rule string to apply. */
+ const char *rule;
+ /* The list of expected ciphers, in order, terminated with -1. */
+ const EXPECTED_CIPHER *expected;
+} CIPHER_TEST;
+
+/* Selecting individual ciphers should work. */
+static const char kRule1[] =
+ "ECDHE-ECDSA-CHACHA20-POLY1305:"
+ "ECDHE-RSA-CHACHA20-POLY1305:"
+ "ECDHE-ECDSA-AES128-GCM-SHA256:"
+ "ECDHE-RSA-AES128-GCM-SHA256";
+
+static const EXPECTED_CIPHER kExpected1[] = {
+ { TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305, 0 },
+ { TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305, 0 },
+ { TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0 },
+ { TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0 },
+ { -1, -1 },
+};
+
+/* + reorders selected ciphers to the end, keeping their relative
+ * order. */
+static const char kRule2[] =
+ "ECDHE-ECDSA-CHACHA20-POLY1305:"
+ "ECDHE-RSA-CHACHA20-POLY1305:"
+ "ECDHE-ECDSA-AES128-GCM-SHA256:"
+ "ECDHE-RSA-AES128-GCM-SHA256:"
+ "+aRSA";
+
+static const EXPECTED_CIPHER kExpected2[] = {
+ { TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305, 0 },
+ { TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0 },
+ { TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305, 0 },
+ { TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0 },
+ { -1, -1 },
+};
+
+/* ! banishes ciphers from future selections. */
+static const char kRule3[] =
+ "!aRSA:"
+ "ECDHE-ECDSA-CHACHA20-POLY1305:"
+ "ECDHE-RSA-CHACHA20-POLY1305:"
+ "ECDHE-ECDSA-AES128-GCM-SHA256:"
+ "ECDHE-RSA-AES128-GCM-SHA256";
+
+static const EXPECTED_CIPHER kExpected3[] = {
+ { TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305, 0 },
+ { TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0 },
+ { -1, -1 },
+};
+
+/* Multiple masks can be ANDed in a single rule. */
+static const char kRule4[] = "kRSA+AESGCM+AES128";
+
+static const EXPECTED_CIPHER kExpected4[] = {
+ { TLS1_CK_RSA_WITH_AES_128_GCM_SHA256, 0 },
+ { -1, -1 },
+};
+
+/* - removes selected ciphers, but preserves their order for future
+ * selections. Select AES_128_GCM, but order the key exchanges RSA,
+ * DHE_RSA, ECDHE_RSA. */
+static const char kRule5[] =
+ "ALL:-kEECDH:-kEDH:-kRSA:-ALL:"
+ "AESGCM+AES128+aRSA";
+
+static const EXPECTED_CIPHER kExpected5[] = {
+ { TLS1_CK_RSA_WITH_AES_128_GCM_SHA256, 0 },
+ { TLS1_CK_DHE_RSA_WITH_AES_128_GCM_SHA256, 0 },
+ { TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0 },
+ { -1, -1 },
+};
+
+/* Unknown selectors are no-ops. */
+static const char kRule6[] =
+ "ECDHE-ECDSA-CHACHA20-POLY1305:"
+ "ECDHE-RSA-CHACHA20-POLY1305:"
+ "ECDHE-ECDSA-AES128-GCM-SHA256:"
+ "ECDHE-RSA-AES128-GCM-SHA256:"
+ "BOGUS1:-BOGUS2:+BOGUS3:!BOGUS4";
+
+static const EXPECTED_CIPHER kExpected6[] = {
+ { TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305, 0 },
+ { TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305, 0 },
+ { TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0 },
+ { TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0 },
+ { -1, -1 },
+};
+
+/* Square brackets specify equi-preference groups. */
+static const char kRule7[] =
+ "[ECDHE-ECDSA-CHACHA20-POLY1305|ECDHE-ECDSA-AES128-GCM-SHA256]:"
+ "[ECDHE-RSA-CHACHA20-POLY1305]:"
+ "ECDHE-RSA-AES128-GCM-SHA256";
+
+static const EXPECTED_CIPHER kExpected7[] = {
+ { TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305, 1 },
+ { TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0 },
+ { TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305, 0 },
+ { TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0 },
+ { -1, -1 },
+};
+
+/* @STRENGTH performs a stable strength-sort of the selected
+ * ciphers and only the selected ciphers. */
+static const char kRule8[] =
+ /* To simplify things, banish all but {ECDHE_RSA,RSA} x
+ * {CHACHA20,AES_256_CBC,AES_128_CBC,RC4} x SHA1. */
+ "!kEDH:!AESGCM:!3DES:!SHA256:!MD5:!SHA384:"
+ /* Order some ciphers backwards by strength. */
+ "ALL:-CHACHA20:-AES256:-AES128:-RC4:-ALL:"
+ /* Select ECDHE ones and sort them by strength. Ties should resolve
+ * based on the order above. */
+ "kEECDH:@STRENGTH:-ALL:"
+ /* Now bring back everything uses RSA. ECDHE_RSA should be first,
+ * sorted by strength. Then RSA, backwards by strength. */
+ "aRSA";
+
+static const EXPECTED_CIPHER kExpected8[] = {
+ { TLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA, 0 },
+ { TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305, 0 },
+ { TLS1_CK_ECDHE_RSA_WITH_RC4_128_SHA, 0 },
+ { TLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA, 0 },
+ { SSL3_CK_RSA_RC4_128_SHA, 0 },
+ { TLS1_CK_RSA_WITH_AES_128_SHA, 0 },
+ { TLS1_CK_RSA_WITH_AES_256_SHA, 0 },
+ { -1, -1 },
+};
+
+static CIPHER_TEST kCipherTests[] = {
+ { kRule1, kExpected1 },
+ { kRule2, kExpected2 },
+ { kRule3, kExpected3 },
+ { kRule4, kExpected4 },
+ { kRule5, kExpected5 },
+ { kRule6, kExpected6 },
+ { kRule7, kExpected7 },
+ { kRule8, kExpected8 },
+ { NULL, NULL },
+};
+
+static const char *kBadRules[] = {
+ /* Invalid brackets. */
+ "[ECDHE-RSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256",
+ "RSA]",
+ "[[RSA]]",
+ /* Operators inside brackets */
+ "[+RSA]",
+ /* Unknown directive. */
+ "@BOGUS",
+ /* Empty cipher lists error at SSL_CTX_set_cipher_list. */
+ "",
+ "BOGUS",
+ /* Invalid command. */
+ "?BAR",
+ /* Special operators are not allowed if groups are used. */
+ "[ECDHE-RSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256]:+FOO",
+ "[ECDHE-RSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256]:!FOO",
+ "[ECDHE-RSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256]:-FOO",
+ "[ECDHE-RSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256]:@STRENGTH",
+ NULL,
+};
+
+static void print_cipher_preference_list(
+ struct ssl_cipher_preference_list_st *list) {
+ size_t i;
+ int in_group = 0;
+ for (i = 0; i < sk_SSL_CIPHER_num(list->ciphers); i++) {
+ const SSL_CIPHER *cipher = sk_SSL_CIPHER_value(list->ciphers, i);
+ if (!in_group && list->in_group_flags[i]) {
+ fprintf(stderr, "\t[\n");
+ in_group = 1;
+ }
+ fprintf(stderr, "\t");
+ if (in_group) {
+ fprintf(stderr, " ");
+ }
+ fprintf(stderr, "%s\n", SSL_CIPHER_get_name(cipher));
+ if (in_group && !list->in_group_flags[i]) {
+ fprintf(stderr, "\t]\n");
+ in_group = 0;
+ }
+ }
+}
+
+static int test_cipher_rule(CIPHER_TEST *t) {
+ int ret = 0;
+ SSL_CTX *ctx = SSL_CTX_new(SSLv23_server_method());
+ size_t i;
+
+ if (!SSL_CTX_set_cipher_list(ctx, t->rule)) {
+ fprintf(stderr, "Error testing cipher rule '%s'\n", t->rule);
+ BIO_print_errors_fp(stderr);
+ goto done;
+ }
+
+ /* Compare the two lists. */
+ for (i = 0; i < sk_SSL_CIPHER_num(ctx->cipher_list->ciphers); i++) {
+ const SSL_CIPHER *cipher =
+ sk_SSL_CIPHER_value(ctx->cipher_list->ciphers, i);
+ if (t->expected[i].id != SSL_CIPHER_get_id(cipher) ||
+ t->expected[i].in_group_flag != ctx->cipher_list->in_group_flags[i]) {
+ fprintf(stderr, "Error: cipher rule '%s' evaluted to:\n", t->rule);
+ print_cipher_preference_list(ctx->cipher_list);
+ goto done;
+ }
+ }
+
+ if (t->expected[i].id != -1) {
+ fprintf(stderr, "Error: cipher rule '%s' evaluted to:\n", t->rule);
+ print_cipher_preference_list(ctx->cipher_list);
+ goto done;
+ }
+
+ ret = 1;
+done:
+ SSL_CTX_free(ctx);
+ return ret;
+}
+
+static int test_cipher_rules(void) {
+ size_t i;
+ for (i = 0; kCipherTests[i].rule != NULL; i++) {
+ if (!test_cipher_rule(&kCipherTests[i])) {
+ return 0;
+ }
+ }
+
+ for (i = 0; kBadRules[i] != NULL; i++) {
+ SSL_CTX *ctx = SSL_CTX_new(SSLv23_server_method());
+ if (SSL_CTX_set_cipher_list(ctx, kBadRules[i])) {
+ fprintf(stderr, "Cipher rule '%s' unexpectedly succeeded\n", kBadRules[i]);
+ return 0;
+ }
+ ERR_clear_error();
+ SSL_CTX_free(ctx);
+ }
+
+ return 1;
+}
+
+/* kOpenSSLSession is a serialized SSL_SESSION generated from openssl
+ * s_client -sess_out. */
+static const char kOpenSSLSession[] =
+ "MIIFpQIBAQICAwMEAsAvBCAG5Q1ndq4Yfmbeo1zwLkNRKmCXGdNgWvGT3cskV0yQ"
+ "kAQwJlrlzkAWBOWiLj/jJ76D7l+UXoizP2KI2C7I2FccqMmIfFmmkUy32nIJ0mZH"
+ "IWoJoQYCBFRDO46iBAICASyjggR6MIIEdjCCA16gAwIBAgIIK9dUvsPWSlUwDQYJ"
+ "KoZIhvcNAQEFBQAwSTELMAkGA1UEBhMCVVMxEzARBgNVBAoTCkdvb2dsZSBJbmMx"
+ "JTAjBgNVBAMTHEdvb2dsZSBJbnRlcm5ldCBBdXRob3JpdHkgRzIwHhcNMTQxMDA4"
+ "MTIwNzU3WhcNMTUwMTA2MDAwMDAwWjBoMQswCQYDVQQGEwJVUzETMBEGA1UECAwK"
+ "Q2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzETMBEGA1UECgwKR29v"
+ "Z2xlIEluYzEXMBUGA1UEAwwOd3d3Lmdvb2dsZS5jb20wggEiMA0GCSqGSIb3DQEB"
+ "AQUAA4IBDwAwggEKAoIBAQCcKeLrplAC+Lofy8t/wDwtB6eu72CVp0cJ4V3lknN6"
+ "huH9ct6FFk70oRIh/VBNBBz900jYy+7111Jm1b8iqOTQ9aT5C7SEhNcQFJvqzH3e"
+ "MPkb6ZSWGm1yGF7MCQTGQXF20Sk/O16FSjAynU/b3oJmOctcycWYkY0ytS/k3LBu"
+ "Id45PJaoMqjB0WypqvNeJHC3q5JjCB4RP7Nfx5jjHSrCMhw8lUMW4EaDxjaR9KDh"
+ "PLgjsk+LDIySRSRDaCQGhEOWLJZVLzLo4N6/UlctCHEllpBUSvEOyFga52qroGjg"
+ "rf3WOQ925MFwzd6AK+Ich0gDRg8sQfdLH5OuP1cfLfU1AgMBAAGjggFBMIIBPTAd"
+ "BgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwGQYDVR0RBBIwEIIOd3d3Lmdv"
+ "b2dsZS5jb20waAYIKwYBBQUHAQEEXDBaMCsGCCsGAQUFBzAChh9odHRwOi8vcGtp"
+ "Lmdvb2dsZS5jb20vR0lBRzIuY3J0MCsGCCsGAQUFBzABhh9odHRwOi8vY2xpZW50"
+ "czEuZ29vZ2xlLmNvbS9vY3NwMB0GA1UdDgQWBBQ7a+CcxsZByOpc+xpYFcIbnUMZ"
+ "hTAMBgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaAFErdBhYbvPZotXb1gba7Yhq6WoEv"
+ "MBcGA1UdIAQQMA4wDAYKKwYBBAHWeQIFATAwBgNVHR8EKTAnMCWgI6Ahhh9odHRw"
+ "Oi8vcGtpLmdvb2dsZS5jb20vR0lBRzIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCa"
+ "OXCBdoqUy5bxyq+Wrh1zsyyCFim1PH5VU2+yvDSWrgDY8ibRGJmfff3r4Lud5kal"
+ "dKs9k8YlKD3ITG7P0YT/Rk8hLgfEuLcq5cc0xqmE42xJ+Eo2uzq9rYorc5emMCxf"
+ "5L0TJOXZqHQpOEcuptZQ4OjdYMfSxk5UzueUhA3ogZKRcRkdB3WeWRp+nYRhx4St"
+ "o2rt2A0MKmY9165GHUqMK9YaaXHDXqBu7Sefr1uSoAP9gyIJKeihMivsGqJ1TD6Z"
+ "cc6LMe+dN2P8cZEQHtD1y296ul4Mivqk3jatUVL8/hCwgch9A8O4PGZq9WqBfEWm"
+ "IyHh1dPtbg1lOXdYCWtjpAIEAKUDAgEUqQUCAwGJwKqBpwSBpBwUQvoeOk0Kg36S"
+ "YTcLEkXqKwOBfF9vE4KX0NxeLwjcDTpsuh3qXEaZ992r1N38VDcyS6P7I6HBYN9B"
+ "sNHM362zZnY27GpTw+Kwd751CLoXFPoaMOe57dbBpXoro6Pd3BTbf/Tzr88K06yE"
+ "OTDKPNj3+inbMaVigtK4PLyPq+Topyzvx9USFgRvyuoxn0Hgb+R0A3j6SLRuyOdA"
+ "i4gv7Y5oliyn";
+
+/* kCustomSession is a custom serialized SSL_SESSION generated by
+ * filling in missing fields from |kOpenSSLSession|. This includes
+ * providing |peer_sha256|, so |peer| is not serialized. */
+static const char kCustomSession[] =
+ "MIIBdgIBAQICAwMEAsAvBCAG5Q1ndq4Yfmbeo1zwLkNRKmCXGdNgWvGT3cskV0yQ"
+ "kAQwJlrlzkAWBOWiLj/jJ76D7l+UXoizP2KI2C7I2FccqMmIfFmmkUy32nIJ0mZH"
+ "IWoJoQYCBFRDO46iBAICASykAwQBAqUDAgEUphAEDnd3dy5nb29nbGUuY29tqAcE"
+ "BXdvcmxkqQUCAwGJwKqBpwSBpBwUQvoeOk0Kg36SYTcLEkXqKwOBfF9vE4KX0Nxe"
+ "LwjcDTpsuh3qXEaZ992r1N38VDcyS6P7I6HBYN9BsNHM362zZnY27GpTw+Kwd751"
+ "CLoXFPoaMOe57dbBpXoro6Pd3BTbf/Tzr88K06yEOTDKPNj3+inbMaVigtK4PLyP"
+ "q+Topyzvx9USFgRvyuoxn0Hgb+R0A3j6SLRuyOdAi4gv7Y5oliynrSIEIAYGBgYG"
+ "BgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGrgMEAQevAwQBBLADBAEF";
+
+static int decode_base64(uint8_t **out, size_t *out_len, const char *in) {
+ size_t len;
+
+ if (!EVP_DecodedLength(&len, strlen(in))) {
+ fprintf(stderr, "EVP_DecodedLength failed\n");
+ return 0;
+ }
+
+ *out = OPENSSL_malloc(len);
+ if (*out == NULL) {
+ fprintf(stderr, "malloc failed\n");
+ return 0;
+ }
+
+ if (!EVP_DecodeBase64(*out, out_len, len, (const uint8_t *)in,
+ strlen(in))) {
+ fprintf(stderr, "EVP_DecodeBase64 failed\n");
+ OPENSSL_free(*out);
+ *out = NULL;
+ return 0;
+ }
+ return 1;
+}
+
+static int test_ssl_session_asn1(const char *input_b64) {
+ int ret = 0, len;
+ size_t input_len, encoded_len;
+ uint8_t *input = NULL, *encoded = NULL;
+ const uint8_t *cptr;
+ uint8_t *ptr;
+ SSL_SESSION *session = NULL;
+
+ /* Decode the input. */
+ if (!decode_base64(&input, &input_len, input_b64)) {
+ goto done;
+ }
+
+ /* Verify the SSL_SESSION decodes. */
+ cptr = input;
+ session = d2i_SSL_SESSION(NULL, &cptr, input_len);
+ if (session == NULL || cptr != input + input_len) {
+ fprintf(stderr, "d2i_SSL_SESSION failed\n");
+ goto done;
+ }
+
+ /* Verify the SSL_SESSION encoding round-trips. */
+ if (!SSL_SESSION_to_bytes(session, &encoded, &encoded_len)) {
+ fprintf(stderr, "SSL_SESSION_to_bytes failed\n");
+ goto done;
+ }
+ if (encoded_len != input_len ||
+ memcmp(input, encoded, input_len) != 0) {
+ fprintf(stderr, "SSL_SESSION_to_bytes did not round-trip\n");
+ goto done;
+ }
+ OPENSSL_free(encoded);
+ encoded = NULL;
+
+ /* Verify the SSL_SESSION encoding round-trips via the legacy API. */
+ len = i2d_SSL_SESSION(session, NULL);
+ if (len < 0 || (size_t)len != input_len) {
+ fprintf(stderr, "i2d_SSL_SESSION(NULL) returned invalid length\n");
+ goto done;
+ }
+
+ encoded = OPENSSL_malloc(input_len);
+ if (encoded == NULL) {
+ fprintf(stderr, "malloc failed\n");
+ goto done;
+ }
+ ptr = encoded;
+ len = i2d_SSL_SESSION(session, &ptr);
+ if (len < 0 || (size_t)len != input_len) {
+ fprintf(stderr, "i2d_SSL_SESSION returned invalid length\n");
+ goto done;
+ }
+ if (ptr != encoded + input_len) {
+ fprintf(stderr, "i2d_SSL_SESSION did not advance ptr correctly\n");
+ goto done;
+ }
+ if (memcmp(input, encoded, input_len) != 0) {
+ fprintf(stderr, "i2d_SSL_SESSION did not round-trip\n");
+ goto done;
+ }
+
+ ret = 1;
+
+ done:
+ if (!ret) {
+ BIO_print_errors_fp(stderr);
+ }
+
+ if (session) {
+ SSL_SESSION_free(session);
+ }
+ if (input) {
+ OPENSSL_free(input);
+ }
+ if (encoded) {
+ OPENSSL_free(encoded);
+ }
+ return ret;
+}
+
+int test_default_version(uint16_t version, const SSL_METHOD *(*method)(void)) {
+ SSL_CTX *ctx;
+ int ret;
+
+ ctx = SSL_CTX_new(method());
+ if (ctx == NULL) {
+ return 0;
+ }
+
+ ret = ctx->min_version == version && ctx->max_version == version;
+ SSL_CTX_free(ctx);
+ return ret;
+}
+
+int main(void) {
+ SSL_library_init();
+
+ if (!test_cipher_rules() ||
+ !test_ssl_session_asn1(kOpenSSLSession) ||
+ !test_ssl_session_asn1(kCustomSession) ||
+ !test_default_version(0, &TLS_method) ||
+ !test_default_version(SSL3_VERSION, &SSLv3_method) ||
+ !test_default_version(TLS1_VERSION, &TLSv1_method) ||
+ !test_default_version(TLS1_1_VERSION, &TLSv1_1_method) ||
+ !test_default_version(TLS1_2_VERSION, &TLSv1_2_method) ||
+ !test_default_version(0, &DTLS_method) ||
+ !test_default_version(DTLS1_VERSION, &DTLSv1_method) ||
+ !test_default_version(DTLS1_2_VERSION, &DTLSv1_2_method)) {
+ return 1;
+ }
+
+ printf("PASS\n");
+ return 0;
+}
diff --git a/src/ssl/ssl_txt.c b/src/ssl/ssl_txt.c
new file mode 100644
index 0000000..c950ce8
--- /dev/null
+++ b/src/ssl/ssl_txt.c
@@ -0,0 +1,211 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <inttypes.h>
+#include <stdio.h>
+
+#include <openssl/buf.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+
+#include "ssl_locl.h"
+
+
+int SSL_SESSION_print_fp(FILE *fp, const SSL_SESSION *x) {
+ BIO *b;
+ int ret;
+
+ b = BIO_new(BIO_s_file());
+ if (b == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_SESSION_print_fp, ERR_R_BUF_LIB);
+ return 0;
+ }
+
+ BIO_set_fp(b, fp, BIO_NOCLOSE);
+ ret = SSL_SESSION_print(b, x);
+ BIO_free(b);
+ return ret;
+}
+
+int SSL_SESSION_print(BIO *bp, const SSL_SESSION *x) {
+ unsigned int i;
+ const char *s;
+
+ if (x == NULL ||
+ BIO_puts(bp, "SSL-Session:\n") <= 0) {
+ goto err;
+ }
+
+ if (x->ssl_version == SSL3_VERSION) {
+ s = "SSLv3";
+ } else if (x->ssl_version == TLS1_2_VERSION) {
+ s = "TLSv1.2";
+ } else if (x->ssl_version == TLS1_1_VERSION) {
+ s = "TLSv1.1";
+ } else if (x->ssl_version == TLS1_VERSION) {
+ s = "TLSv1";
+ } else if (x->ssl_version == DTLS1_VERSION) {
+ s = "DTLSv1";
+ } else if (x->ssl_version == DTLS1_2_VERSION) {
+ s = "DTLSv1.2";
+ } else {
+ s = "unknown";
+ }
+
+ if (BIO_printf(bp, " Protocol : %s\n", s) <= 0) {
+ goto err;
+ }
+
+ if (BIO_printf(bp, " Cipher : %s\n",
+ ((x->cipher == NULL) ? "unknown" : x->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 < (unsigned int)x->master_key_length; i++) {
+ if (BIO_printf(bp, "%02X", x->master_key[i]) <= 0) {
+ goto err;
+ }
+ }
+
+ if (BIO_puts(bp, "\n PSK identity: ") <= 0 ||
+ BIO_printf(bp, "%s", x->psk_identity ? x->psk_identity : "None") <= 0) {
+ goto err;
+ }
+
+ if (x->tlsext_tick_lifetime_hint &&
+ BIO_printf(bp, "\n TLS session ticket lifetime hint: %" PRIu32
+ " (seconds)",
+ x->tlsext_tick_lifetime_hint) <= 0) {
+ goto err;
+ }
+
+ if (x->tlsext_tick) {
+ if (BIO_puts(bp, "\n TLS session ticket:\n") <= 0 ||
+ BIO_hexdump(bp, x->tlsext_tick, x->tlsext_ticklen, 4) <= 0) {
+ goto err;
+ }
+ }
+
+ if (x->time != 0L && BIO_printf(bp, "\n Start Time: %ld", x->time) <= 0) {
+ goto err;
+ }
+
+ if (x->timeout != 0L &&
+ BIO_printf(bp, "\n Timeout : %ld (sec)", x->timeout) <= 0) {
+ goto err;
+ }
+
+ if (BIO_puts(bp, "\n") <= 0 ||
+ BIO_puts(bp, " Verify return code: ") <= 0 ||
+ BIO_printf(bp, "%ld (%s)\n", x->verify_result,
+ X509_verify_cert_error_string(x->verify_result)) <= 0) {
+ goto err;
+ }
+
+ return 1;
+
+err:
+ return 0;
+}
diff --git a/src/ssl/t1_enc.c b/src/ssl/t1_enc.c
new file mode 100644
index 0000000..014bc88
--- /dev/null
+++ b/src/ssl/t1_enc.c
@@ -0,0 +1,1042 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <stdio.h>
+#include <assert.h>
+
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
+#include <openssl/md5.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/rand.h>
+
+#include "ssl_locl.h"
+
+
+/* tls1_P_hash computes the TLS P_<hash> function as described in RFC 5246,
+ * section 5. It writes |out_len| bytes to |out|, using |md| as the hash and
+ * |secret| as the secret. |seed1| through |seed3| are concatenated to form the
+ * seed parameter. It returns one on success and zero on failure. */
+static int tls1_P_hash(uint8_t *out, size_t out_len, const EVP_MD *md,
+ const uint8_t *secret, size_t secret_len,
+ const uint8_t *seed1, size_t seed1_len,
+ const uint8_t *seed2, size_t seed2_len,
+ const uint8_t *seed3, size_t seed3_len) {
+ size_t chunk;
+ HMAC_CTX ctx, ctx_tmp, ctx_init;
+ uint8_t A1[EVP_MAX_MD_SIZE];
+ unsigned A1_len;
+ int ret = 0;
+
+ chunk = EVP_MD_size(md);
+
+ HMAC_CTX_init(&ctx);
+ HMAC_CTX_init(&ctx_tmp);
+ HMAC_CTX_init(&ctx_init);
+ if (!HMAC_Init_ex(&ctx_init, secret, secret_len, md, NULL) ||
+ !HMAC_CTX_copy_ex(&ctx, &ctx_init) ||
+ (seed1_len && !HMAC_Update(&ctx, seed1, seed1_len)) ||
+ (seed2_len && !HMAC_Update(&ctx, seed2, seed2_len)) ||
+ (seed3_len && !HMAC_Update(&ctx, seed3, seed3_len)) ||
+ !HMAC_Final(&ctx, A1, &A1_len)) {
+ goto err;
+ }
+
+ for (;;) {
+ /* Reinit mac contexts. */
+ if (!HMAC_CTX_copy_ex(&ctx, &ctx_init) ||
+ !HMAC_Update(&ctx, A1, A1_len) ||
+ (out_len > chunk && !HMAC_CTX_copy_ex(&ctx_tmp, &ctx)) ||
+ (seed1_len && !HMAC_Update(&ctx, seed1, seed1_len)) ||
+ (seed2_len && !HMAC_Update(&ctx, seed2, seed2_len)) ||
+ (seed3_len && !HMAC_Update(&ctx, seed3, seed3_len))) {
+ goto err;
+ }
+
+ if (out_len > chunk) {
+ unsigned len;
+ if (!HMAC_Final(&ctx, out, &len)) {
+ goto err;
+ }
+ assert(len == chunk);
+ out += len;
+ out_len -= len;
+ /* Calculate the next A1 value. */
+ if (!HMAC_Final(&ctx_tmp, A1, &A1_len)) {
+ goto err;
+ }
+ } else {
+ /* Last chunk. */
+ if (!HMAC_Final(&ctx, A1, &A1_len)) {
+ goto err;
+ }
+ memcpy(out, A1, out_len);
+ break;
+ }
+ }
+
+ ret = 1;
+
+err:
+ HMAC_CTX_cleanup(&ctx);
+ HMAC_CTX_cleanup(&ctx_tmp);
+ HMAC_CTX_cleanup(&ctx_init);
+ OPENSSL_cleanse(A1, sizeof(A1));
+ return ret;
+}
+
+int tls1_prf(SSL *s, uint8_t *out, size_t out_len, const uint8_t *secret,
+ size_t secret_len, const char *label, size_t label_len,
+ const uint8_t *seed1, size_t seed1_len,
+ const uint8_t *seed2, size_t seed2_len) {
+ size_t idx, len, count, i;
+ const uint8_t *S1;
+ long m;
+ const EVP_MD *md;
+ int ret = 0;
+ uint8_t *tmp;
+
+ if (out_len == 0) {
+ return 1;
+ }
+
+ /* Allocate a temporary buffer. */
+ tmp = OPENSSL_malloc(out_len);
+ if (tmp == NULL) {
+ OPENSSL_PUT_ERROR(SSL, tls1_prf, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ /* Count number of digests and partition |secret| evenly. */
+ count = 0;
+ for (idx = 0; ssl_get_handshake_digest(idx, &m, &md); idx++) {
+ if ((m << TLS1_PRF_DGST_SHIFT) & ssl_get_algorithm2(s)) {
+ count++;
+ }
+ }
+ /* TODO(davidben): The only case where count isn't 1 is the old MD5/SHA-1
+ * combination. The logic around multiple handshake digests can probably be
+ * simplified. */
+ assert(count == 1 || count == 2);
+ len = secret_len / count;
+ if (count == 1) {
+ secret_len = 0;
+ }
+ S1 = secret;
+ memset(out, 0, out_len);
+ for (idx = 0; ssl_get_handshake_digest(idx, &m, &md); idx++) {
+ if ((m << TLS1_PRF_DGST_SHIFT) & ssl_get_algorithm2(s)) {
+ /* If |count| is 2 and |secret_len| is odd, |secret| is partitioned into
+ * two halves with an overlapping byte. */
+ if (!tls1_P_hash(tmp, out_len, md, S1, len + (secret_len & 1),
+ (const uint8_t *)label, label_len, seed1, seed1_len,
+ seed2, seed2_len)) {
+ goto err;
+ }
+ S1 += len;
+ for (i = 0; i < out_len; i++) {
+ out[i] ^= tmp[i];
+ }
+ }
+ }
+ ret = 1;
+
+err:
+ OPENSSL_cleanse(tmp, out_len);
+ OPENSSL_free(tmp);
+ return ret;
+}
+
+static int tls1_generate_key_block(SSL *s, uint8_t *out, size_t out_len) {
+ return s->enc_method->prf(s, out, out_len, 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);
+}
+
+/* tls1_aead_ctx_init allocates |*aead_ctx|, if needed and returns 1. It
+ * returns 0 on malloc error. */
+static int tls1_aead_ctx_init(SSL_AEAD_CTX **aead_ctx) {
+ if (*aead_ctx != NULL) {
+ EVP_AEAD_CTX_cleanup(&(*aead_ctx)->ctx);
+ } else {
+ *aead_ctx = (SSL_AEAD_CTX *)OPENSSL_malloc(sizeof(SSL_AEAD_CTX));
+ if (*aead_ctx == NULL) {
+ OPENSSL_PUT_ERROR(SSL, tls1_aead_ctx_init, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static int tls1_change_cipher_state_aead(SSL *s, char is_read,
+ const uint8_t *key, unsigned key_len,
+ const uint8_t *iv, unsigned iv_len,
+ const uint8_t *mac_secret,
+ unsigned mac_secret_len) {
+ const EVP_AEAD *aead = s->s3->tmp.new_aead;
+ SSL_AEAD_CTX *aead_ctx;
+ /* merged_key is used to merge the MAC, cipher, and IV keys for an AEAD which
+ * simulates pre-AEAD cipher suites. */
+ uint8_t merged_key[EVP_AEAD_MAX_KEY_LENGTH];
+
+ if (mac_secret_len > 0) {
+ /* This is a "stateful" AEAD (for compatibility with pre-AEAD cipher
+ * suites). */
+ if (mac_secret_len + key_len + iv_len > sizeof(merged_key)) {
+ OPENSSL_PUT_ERROR(SSL, tls1_change_cipher_state_aead,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ memcpy(merged_key, mac_secret, mac_secret_len);
+ memcpy(merged_key + mac_secret_len, key, key_len);
+ memcpy(merged_key + mac_secret_len + key_len, iv, iv_len);
+ key = merged_key;
+ key_len += mac_secret_len;
+ key_len += iv_len;
+ }
+
+ if (is_read) {
+ if (!tls1_aead_ctx_init(&s->aead_read_ctx)) {
+ return 0;
+ }
+ aead_ctx = s->aead_read_ctx;
+ } else {
+ /* When updating the cipher state for DTLS, we do not wish to overwrite the
+ * old ones because DTLS stores pointers to them in order to implement
+ * retransmission. See dtls1_hm_fragment_free.
+ *
+ * TODO(davidben): Simplify aead_write_ctx ownership, probably by just
+ * forbidding DTLS renego. */
+ if (SSL_IS_DTLS(s)) {
+ s->aead_write_ctx = NULL;
+ }
+ if (!tls1_aead_ctx_init(&s->aead_write_ctx)) {
+ return 0;
+ }
+ aead_ctx = s->aead_write_ctx;
+ }
+
+ if (!EVP_AEAD_CTX_init(&aead_ctx->ctx, aead, key, key_len,
+ EVP_AEAD_DEFAULT_TAG_LENGTH, NULL /* engine */)) {
+ OPENSSL_free(aead_ctx);
+ if (is_read) {
+ s->aead_read_ctx = NULL;
+ } else {
+ s->aead_write_ctx = NULL;
+ }
+
+ return 0;
+ }
+
+ if (mac_secret_len == 0) {
+ /* For a real AEAD, the IV is the fixed part of the nonce. */
+ if (iv_len > sizeof(aead_ctx->fixed_nonce)) {
+ OPENSSL_PUT_ERROR(SSL, tls1_change_cipher_state_aead, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ memcpy(aead_ctx->fixed_nonce, iv, iv_len);
+ aead_ctx->fixed_nonce_len = iv_len;
+ aead_ctx->variable_nonce_included_in_record =
+ (s->s3->tmp.new_cipher->algorithm2 &
+ SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD) != 0;
+ aead_ctx->random_variable_nonce = 0;
+ aead_ctx->omit_length_in_ad = 0;
+ } else {
+ aead_ctx->fixed_nonce_len = 0;
+ aead_ctx->variable_nonce_included_in_record = 1;
+ aead_ctx->random_variable_nonce = 1;
+ aead_ctx->omit_length_in_ad = 1;
+ }
+ aead_ctx->variable_nonce_len = s->s3->tmp.new_variable_iv_len;
+ aead_ctx->omit_version_in_ad = (s->version == SSL3_VERSION);
+
+ if (aead_ctx->variable_nonce_len + aead_ctx->fixed_nonce_len !=
+ EVP_AEAD_nonce_length(aead)) {
+ OPENSSL_PUT_ERROR(SSL, tls1_change_cipher_state_aead, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ aead_ctx->tag_len = EVP_AEAD_max_overhead(aead);
+
+ return 1;
+}
+
+int tls1_change_cipher_state(SSL *s, int which) {
+ /* is_read is true if we have just read a ChangeCipherSpec message - i.e. we
+ * need to update the read cipherspec. Otherwise we have just written one. */
+ const char is_read = (which & SSL3_CC_READ) != 0;
+ /* use_client_keys is true if we wish to use the keys for the "client write"
+ * direction. This is the case if we're a client sending a ChangeCipherSpec,
+ * or a server reading a client's ChangeCipherSpec. */
+ const char use_client_keys = which == SSL3_CHANGE_CIPHER_CLIENT_WRITE ||
+ which == SSL3_CHANGE_CIPHER_SERVER_READ;
+ const uint8_t *client_write_mac_secret, *server_write_mac_secret, *mac_secret;
+ const uint8_t *client_write_key, *server_write_key, *key;
+ const uint8_t *client_write_iv, *server_write_iv, *iv;
+ const EVP_AEAD *aead = s->s3->tmp.new_aead;
+ size_t key_len, iv_len, mac_secret_len;
+ const uint8_t *key_data;
+
+ /* Reset sequence number to zero. */
+ if (!SSL_IS_DTLS(s)) {
+ memset(is_read ? s->s3->read_sequence : s->s3->write_sequence, 0, 8);
+ }
+
+ mac_secret_len = s->s3->tmp.new_mac_secret_len;
+ iv_len = s->s3->tmp.new_fixed_iv_len;
+
+ if (aead == NULL) {
+ OPENSSL_PUT_ERROR(SSL, tls1_change_cipher_state, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ key_len = EVP_AEAD_key_length(aead);
+ if (mac_secret_len > 0) {
+ /* For "stateful" AEADs (i.e. compatibility with pre-AEAD cipher
+ * suites) the key length reported by |EVP_AEAD_key_length| will
+ * include the MAC and IV key bytes. */
+ if (key_len < mac_secret_len + iv_len) {
+ OPENSSL_PUT_ERROR(SSL, tls1_change_cipher_state, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ key_len -= mac_secret_len + iv_len;
+ }
+
+ key_data = s->s3->tmp.key_block;
+ client_write_mac_secret = key_data;
+ key_data += mac_secret_len;
+ server_write_mac_secret = key_data;
+ key_data += mac_secret_len;
+ client_write_key = key_data;
+ key_data += key_len;
+ server_write_key = key_data;
+ key_data += key_len;
+ client_write_iv = key_data;
+ key_data += iv_len;
+ server_write_iv = key_data;
+ key_data += iv_len;
+
+ if (use_client_keys) {
+ mac_secret = client_write_mac_secret;
+ key = client_write_key;
+ iv = client_write_iv;
+ } else {
+ mac_secret = server_write_mac_secret;
+ key = server_write_key;
+ iv = server_write_iv;
+ }
+
+ if (key_data - s->s3->tmp.key_block != s->s3->tmp.key_block_length) {
+ OPENSSL_PUT_ERROR(SSL, tls1_change_cipher_state, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ return tls1_change_cipher_state_aead(s, is_read, key, key_len, iv, iv_len,
+ mac_secret, mac_secret_len);
+}
+
+int tls1_setup_key_block(SSL *s) {
+ uint8_t *p;
+ const EVP_AEAD *aead = NULL;
+ int ret = 0;
+ size_t mac_secret_len, fixed_iv_len, variable_iv_len, key_len;
+ size_t key_block_len;
+
+ if (s->s3->tmp.key_block_length != 0) {
+ return 1;
+ }
+
+ if (s->session->cipher == NULL) {
+ goto cipher_unavailable_err;
+ }
+
+ if (!ssl_cipher_get_evp_aead(&aead, &mac_secret_len, &fixed_iv_len,
+ s->session->cipher,
+ ssl3_version_from_wire(s, s->version))) {
+ goto cipher_unavailable_err;
+ }
+ key_len = EVP_AEAD_key_length(aead);
+ variable_iv_len = EVP_AEAD_nonce_length(aead);
+ if (mac_secret_len > 0) {
+ /* For "stateful" AEADs (i.e. compatibility with pre-AEAD cipher suites) the
+ * key length reported by |EVP_AEAD_key_length| will include the MAC key
+ * bytes and initial implicit IV. */
+ if (key_len < mac_secret_len + fixed_iv_len) {
+ OPENSSL_PUT_ERROR(SSL, tls1_setup_key_block, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ key_len -= mac_secret_len + fixed_iv_len;
+ } else {
+ /* The nonce is split into a fixed portion and a variable portion. */
+ if (variable_iv_len < fixed_iv_len) {
+ OPENSSL_PUT_ERROR(SSL, tls1_setup_key_block, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ variable_iv_len -= fixed_iv_len;
+ }
+
+ assert(mac_secret_len < 256);
+ assert(fixed_iv_len < 256);
+ assert(variable_iv_len < 256);
+
+ s->s3->tmp.new_aead = aead;
+ s->s3->tmp.new_mac_secret_len = (uint8_t)mac_secret_len;
+ s->s3->tmp.new_fixed_iv_len = (uint8_t)fixed_iv_len;
+ s->s3->tmp.new_variable_iv_len = (uint8_t)variable_iv_len;
+
+ key_block_len = key_len + mac_secret_len + fixed_iv_len;
+ key_block_len *= 2;
+
+ ssl3_cleanup_key_block(s);
+
+ p = (uint8_t *)OPENSSL_malloc(key_block_len);
+ if (p == NULL) {
+ OPENSSL_PUT_ERROR(SSL, tls1_setup_key_block, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ s->s3->tmp.key_block_length = key_block_len;
+ s->s3->tmp.key_block = p;
+
+ if (!tls1_generate_key_block(s, p, key_block_len)) {
+ goto err;
+ }
+
+ if (!SSL_USE_EXPLICIT_IV(s) &&
+ (s->mode & SSL_MODE_CBC_RECORD_SPLITTING) != 0) {
+ /* enable vulnerability countermeasure for CBC ciphers with known-IV
+ * problem (http://www.openssl.org/~bodo/tls-cbc.txt). */
+ s->s3->need_record_splitting = 1;
+
+ if (s->session->cipher != NULL &&
+ s->session->cipher->algorithm_enc == SSL_RC4) {
+ s->s3->need_record_splitting = 0;
+ }
+ }
+
+ ret = 1;
+
+err:
+ return ret;
+
+cipher_unavailable_err:
+ OPENSSL_PUT_ERROR(SSL, tls1_setup_key_block,
+ SSL_R_CIPHER_OR_HASH_UNAVAILABLE);
+ return 0;
+}
+
+/* tls1_enc encrypts/decrypts the record in |s->wrec| / |s->rrec|,
+ * respectively. It returns one on success and zero on failure. */
+int tls1_enc(SSL *s, int send) {
+ SSL3_RECORD *rec;
+ const SSL_AEAD_CTX *aead;
+
+ if (send) {
+ rec = &s->s3->wrec;
+ aead = s->aead_write_ctx;
+ } else {
+ rec = &s->s3->rrec;
+ aead = s->aead_read_ctx;
+ }
+
+ if (s->session == NULL || aead == NULL) {
+ /* Handle the initial NULL cipher. */
+ memmove(rec->data, rec->input, rec->length);
+ rec->input = rec->data;
+ return 1;
+ }
+
+ uint8_t ad[13], *seq, *in, *out, nonce[EVP_AEAD_MAX_NONCE_LENGTH];
+ unsigned nonce_used;
+ size_t n, ad_len;
+
+ seq = send ? s->s3->write_sequence : s->s3->read_sequence;
+
+ if (SSL_IS_DTLS(s)) {
+ uint8_t dtlsseq[9], *p = dtlsseq;
+
+ s2n(send ? s->d1->w_epoch : s->d1->r_epoch, p);
+ memcpy(p, &seq[2], 6);
+ memcpy(ad, dtlsseq, 8);
+ } else {
+ int i;
+ memcpy(ad, seq, 8);
+ for (i = 7; i >= 0; i--) {
+ ++seq[i];
+ if (seq[i] != 0) {
+ break;
+ }
+ }
+ }
+
+ ad[8] = rec->type;
+ ad_len = 9;
+ if (!aead->omit_version_in_ad) {
+ ad[ad_len++] = (uint8_t)(s->version >> 8);
+ ad[ad_len++] = (uint8_t)(s->version);
+ }
+
+ if (aead->fixed_nonce_len + aead->variable_nonce_len > sizeof(nonce)) {
+ OPENSSL_PUT_ERROR(SSL, tls1_enc, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ memcpy(nonce, aead->fixed_nonce, aead->fixed_nonce_len);
+ nonce_used = aead->fixed_nonce_len;
+
+ if (send) {
+ size_t len = rec->length;
+ size_t eivlen = 0;
+ in = rec->input;
+ out = rec->data;
+
+ uint8_t *variable_nonce = nonce + nonce_used;
+ if (aead->random_variable_nonce) {
+ assert(aead->variable_nonce_included_in_record);
+ if (!RAND_bytes(nonce + nonce_used, aead->variable_nonce_len)) {
+ return 0;
+ }
+ } else {
+ /* When sending we use the sequence number as the variable part of the
+ * nonce. */
+ if (aead->variable_nonce_len != 8) {
+ OPENSSL_PUT_ERROR(SSL, tls1_enc, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ memcpy(nonce + nonce_used, ad, aead->variable_nonce_len);
+ }
+ nonce_used += aead->variable_nonce_len;
+
+ /* in do_ssl3_write, rec->input is moved forward by variable_nonce_len in
+ * order to leave space for the variable nonce. Thus we can copy the
+ * sequence number bytes into place without overwriting any of the
+ * plaintext. */
+ if (aead->variable_nonce_included_in_record) {
+ memcpy(out, variable_nonce, aead->variable_nonce_len);
+ len -= aead->variable_nonce_len;
+ eivlen = aead->variable_nonce_len;
+ }
+
+ if (!aead->omit_length_in_ad) {
+ ad[ad_len++] = len >> 8;
+ ad[ad_len++] = len & 0xff;
+ }
+
+ if (!EVP_AEAD_CTX_seal(&aead->ctx, out + eivlen, &n, len + aead->tag_len,
+ nonce, nonce_used, in + eivlen, len, ad, ad_len)) {
+ return 0;
+ }
+
+ if (aead->variable_nonce_included_in_record) {
+ n += aead->variable_nonce_len;
+ }
+ } else {
+ /* receive */
+ size_t len = rec->length;
+
+ if (rec->data != rec->input) {
+ OPENSSL_PUT_ERROR(SSL, tls1_enc, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ out = in = rec->input;
+
+ if (len < aead->variable_nonce_len) {
+ return 0;
+ }
+ memcpy(nonce + nonce_used,
+ aead->variable_nonce_included_in_record ? in : ad,
+ aead->variable_nonce_len);
+ nonce_used += aead->variable_nonce_len;
+
+ if (aead->variable_nonce_included_in_record) {
+ in += aead->variable_nonce_len;
+ len -= aead->variable_nonce_len;
+ out += aead->variable_nonce_len;
+ }
+
+ if (!aead->omit_length_in_ad) {
+ if (len < aead->tag_len) {
+ return 0;
+ }
+ size_t plaintext_len = len - aead->tag_len;
+
+ ad[ad_len++] = plaintext_len >> 8;
+ ad[ad_len++] = plaintext_len & 0xff;
+ }
+
+ if (!EVP_AEAD_CTX_open(&aead->ctx, out, &n, rec->length, nonce, nonce_used, in,
+ len, ad, ad_len)) {
+ return 0;
+ }
+
+ rec->data = rec->input = out;
+ }
+
+ rec->length = n;
+ return 1;
+}
+
+int tls1_cert_verify_mac(SSL *s, int md_nid, uint8_t *out) {
+ unsigned int ret;
+ EVP_MD_CTX ctx, *d = NULL;
+ int i;
+
+ if (s->s3->handshake_buffer &&
+ !ssl3_digest_cached_records(s, free_handshake_buffer)) {
+ return 0;
+ }
+
+ for (i = 0; i < SSL_MAX_DIGEST; i++) {
+ if (s->s3->handshake_dgst[i] &&
+ EVP_MD_CTX_type(s->s3->handshake_dgst[i]) == md_nid) {
+ d = s->s3->handshake_dgst[i];
+ break;
+ }
+ }
+
+ if (!d) {
+ OPENSSL_PUT_ERROR(SSL, tls1_cert_verify_mac, SSL_R_NO_REQUIRED_DIGEST);
+ return 0;
+ }
+
+ EVP_MD_CTX_init(&ctx);
+ EVP_MD_CTX_copy_ex(&ctx, d);
+ EVP_DigestFinal_ex(&ctx, out, &ret);
+ EVP_MD_CTX_cleanup(&ctx);
+
+ return ret;
+}
+
+/* tls1_handshake_digest calculates the current handshake hash and writes it to
+ * |out|, which has space for |out_len| bytes. It returns the number of bytes
+ * written or -1 in the event of an error. This function works on a copy of the
+ * underlying digests so can be called multiple times and prior to the final
+ * update etc. */
+int tls1_handshake_digest(SSL *s, uint8_t *out, size_t out_len) {
+ const EVP_MD *md;
+ EVP_MD_CTX ctx;
+ int err = 0, len = 0;
+ size_t i;
+ long mask;
+
+ EVP_MD_CTX_init(&ctx);
+
+ for (i = 0; ssl_get_handshake_digest(i, &mask, &md); i++) {
+ size_t hash_size;
+ unsigned int digest_len;
+ EVP_MD_CTX *hdgst = s->s3->handshake_dgst[i];
+
+ if ((mask & ssl_get_algorithm2(s)) == 0) {
+ continue;
+ }
+
+ hash_size = EVP_MD_size(md);
+ if (!hdgst ||
+ hash_size > out_len ||
+ !EVP_MD_CTX_copy_ex(&ctx, hdgst) ||
+ !EVP_DigestFinal_ex(&ctx, out, &digest_len) ||
+ digest_len != hash_size /* internal error */) {
+ err = 1;
+ break;
+ }
+
+ out += digest_len;
+ out_len -= digest_len;
+ len += digest_len;
+ }
+
+ EVP_MD_CTX_cleanup(&ctx);
+
+ if (err != 0) {
+ return -1;
+ }
+ return len;
+}
+
+int tls1_final_finish_mac(SSL *s, const char *str, int slen, uint8_t *out) {
+ uint8_t buf[2 * EVP_MAX_MD_SIZE];
+ int err = 0;
+ int digests_len;
+
+ if (s->s3->handshake_buffer &&
+ !ssl3_digest_cached_records(s, free_handshake_buffer)) {
+ return 0;
+ }
+
+ digests_len = tls1_handshake_digest(s, buf, sizeof(buf));
+ if (digests_len < 0) {
+ err = 1;
+ digests_len = 0;
+ }
+
+ if (!s->enc_method->prf(s, out, 12, s->session->master_key,
+ s->session->master_key_length, str, slen, buf,
+ digests_len, NULL, 0)) {
+ err = 1;
+ }
+
+ if (err) {
+ return 0;
+ } else {
+ return 12;
+ }
+}
+
+int tls1_generate_master_secret(SSL *s, uint8_t *out, const uint8_t *premaster,
+ size_t premaster_len) {
+ if (s->s3->tmp.extended_master_secret) {
+ uint8_t digests[2 * EVP_MAX_MD_SIZE];
+ int digests_len;
+
+ /* The master secret is based on the handshake hash just after sending the
+ * ClientKeyExchange. However, we might have a client certificate to send,
+ * in which case we might need different hashes for the verification and
+ * thus still need the handshake buffer around. Keeping both a handshake
+ * buffer *and* running hashes isn't yet supported so, when it comes to
+ * calculating the Finished hash, we'll have to hash the handshake buffer
+ * again. */
+ if (s->s3->handshake_buffer &&
+ !ssl3_digest_cached_records(s, dont_free_handshake_buffer)) {
+ return 0;
+ }
+
+ digests_len = tls1_handshake_digest(s, digests, sizeof(digests));
+ if (digests_len == -1) {
+ return 0;
+ }
+
+ if (!s->enc_method->prf(s, out, SSL3_MASTER_SECRET_SIZE, premaster,
+ premaster_len, TLS_MD_EXTENDED_MASTER_SECRET_CONST,
+ TLS_MD_EXTENDED_MASTER_SECRET_CONST_SIZE, digests,
+ digests_len, NULL, 0)) {
+ return 0;
+ }
+ } else {
+ if (!s->enc_method->prf(s, out, SSL3_MASTER_SECRET_SIZE, premaster,
+ premaster_len, TLS_MD_MASTER_SECRET_CONST,
+ TLS_MD_MASTER_SECRET_CONST_SIZE,
+ s->s3->client_random, SSL3_RANDOM_SIZE,
+ s->s3->server_random, SSL3_RANDOM_SIZE)) {
+ return 0;
+ }
+ }
+
+ return SSL3_MASTER_SECRET_SIZE;
+}
+
+int tls1_export_keying_material(SSL *s, uint8_t *out, size_t olen,
+ const char *label, size_t llen,
+ const uint8_t *context, size_t contextlen,
+ int use_context) {
+ uint8_t *val = NULL;
+ size_t vallen, currentvalpos;
+ int ret;
+
+ /* construct PRF arguments we construct the PRF argument ourself rather than
+ * passing separate values into the TLS PRF to ensure that the concatenation
+ * of values does not create a prohibited label. */
+ vallen = llen + SSL3_RANDOM_SIZE * 2;
+ if (use_context) {
+ vallen += 2 + contextlen;
+ }
+
+ val = OPENSSL_malloc(vallen);
+ if (val == NULL) {
+ goto err2;
+ }
+
+ currentvalpos = 0;
+ memcpy(val + currentvalpos, (uint8_t *)label, llen);
+ currentvalpos += llen;
+ memcpy(val + currentvalpos, s->s3->client_random, SSL3_RANDOM_SIZE);
+ currentvalpos += SSL3_RANDOM_SIZE;
+ memcpy(val + currentvalpos, s->s3->server_random, SSL3_RANDOM_SIZE);
+ currentvalpos += SSL3_RANDOM_SIZE;
+
+ if (use_context) {
+ val[currentvalpos] = (contextlen >> 8) & 0xff;
+ currentvalpos++;
+ val[currentvalpos] = contextlen & 0xff;
+ currentvalpos++;
+ if (contextlen > 0 || context != NULL) {
+ memcpy(val + currentvalpos, context, contextlen);
+ }
+ }
+
+ /* disallow prohibited labels note that SSL3_RANDOM_SIZE > max(prohibited
+ * label len) = 15, so size of val > max(prohibited label len) = 15 and the
+ * comparisons won't have buffer overflow. */
+ if (memcmp(val, TLS_MD_CLIENT_FINISH_CONST,
+ TLS_MD_CLIENT_FINISH_CONST_SIZE) == 0 ||
+ memcmp(val, TLS_MD_SERVER_FINISH_CONST,
+ TLS_MD_SERVER_FINISH_CONST_SIZE) == 0 ||
+ memcmp(val, TLS_MD_MASTER_SECRET_CONST,
+ TLS_MD_MASTER_SECRET_CONST_SIZE) == 0 ||
+ memcmp(val, TLS_MD_KEY_EXPANSION_CONST,
+ TLS_MD_KEY_EXPANSION_CONST_SIZE) == 0) {
+ goto err1;
+ }
+
+ /* SSL_export_keying_material is not implemented for SSLv3, so passing
+ * everything through the label parameter works. */
+ assert(s->version != SSL3_VERSION);
+ ret = s->enc_method->prf(s, out, olen, s->session->master_key,
+ s->session->master_key_length, (const char *)val,
+ vallen, NULL, 0, NULL, 0);
+ goto out;
+
+err1:
+ OPENSSL_PUT_ERROR(SSL, tls1_export_keying_material,
+ SSL_R_TLS_ILLEGAL_EXPORTER_LABEL);
+ ret = 0;
+ goto out;
+
+err2:
+ OPENSSL_PUT_ERROR(SSL, tls1_export_keying_material, ERR_R_MALLOC_FAILURE);
+ ret = 0;
+
+out:
+ if (val != NULL) {
+ OPENSSL_free(val);
+ }
+
+ return ret;
+}
+
+int tls1_alert_code(int code) {
+ switch (code) {
+ case SSL_AD_CLOSE_NOTIFY:
+ return SSL3_AD_CLOSE_NOTIFY;
+
+ case SSL_AD_UNEXPECTED_MESSAGE:
+ return SSL3_AD_UNEXPECTED_MESSAGE;
+
+ case SSL_AD_BAD_RECORD_MAC:
+ return SSL3_AD_BAD_RECORD_MAC;
+
+ case SSL_AD_DECRYPTION_FAILED:
+ return TLS1_AD_DECRYPTION_FAILED;
+
+ case SSL_AD_RECORD_OVERFLOW:
+ return TLS1_AD_RECORD_OVERFLOW;
+
+ case SSL_AD_DECOMPRESSION_FAILURE:
+ return SSL3_AD_DECOMPRESSION_FAILURE;
+
+ case SSL_AD_HANDSHAKE_FAILURE:
+ return SSL3_AD_HANDSHAKE_FAILURE;
+
+ case SSL_AD_NO_CERTIFICATE:
+ return -1;
+
+ case SSL_AD_BAD_CERTIFICATE:
+ return SSL3_AD_BAD_CERTIFICATE;
+
+ case SSL_AD_UNSUPPORTED_CERTIFICATE:
+ return SSL3_AD_UNSUPPORTED_CERTIFICATE;
+
+ case SSL_AD_CERTIFICATE_REVOKED:
+ return SSL3_AD_CERTIFICATE_REVOKED;
+
+ case SSL_AD_CERTIFICATE_EXPIRED:
+ return SSL3_AD_CERTIFICATE_EXPIRED;
+
+ case SSL_AD_CERTIFICATE_UNKNOWN:
+ return SSL3_AD_CERTIFICATE_UNKNOWN;
+
+ case SSL_AD_ILLEGAL_PARAMETER:
+ return SSL3_AD_ILLEGAL_PARAMETER;
+
+ case SSL_AD_UNKNOWN_CA:
+ return TLS1_AD_UNKNOWN_CA;
+
+ case SSL_AD_ACCESS_DENIED:
+ return TLS1_AD_ACCESS_DENIED;
+
+ case SSL_AD_DECODE_ERROR:
+ return TLS1_AD_DECODE_ERROR;
+
+ case SSL_AD_DECRYPT_ERROR:
+ return TLS1_AD_DECRYPT_ERROR;
+ case SSL_AD_EXPORT_RESTRICTION:
+ return TLS1_AD_EXPORT_RESTRICTION;
+
+ case SSL_AD_PROTOCOL_VERSION:
+ return TLS1_AD_PROTOCOL_VERSION;
+
+ case SSL_AD_INSUFFICIENT_SECURITY:
+ return TLS1_AD_INSUFFICIENT_SECURITY;
+
+ case SSL_AD_INTERNAL_ERROR:
+ return TLS1_AD_INTERNAL_ERROR;
+
+ case SSL_AD_USER_CANCELLED:
+ return TLS1_AD_USER_CANCELLED;
+
+ case SSL_AD_NO_RENEGOTIATION:
+ return TLS1_AD_NO_RENEGOTIATION;
+
+ case SSL_AD_UNSUPPORTED_EXTENSION:
+ return TLS1_AD_UNSUPPORTED_EXTENSION;
+
+ case SSL_AD_CERTIFICATE_UNOBTAINABLE:
+ return TLS1_AD_CERTIFICATE_UNOBTAINABLE;
+
+ case SSL_AD_UNRECOGNIZED_NAME:
+ return TLS1_AD_UNRECOGNIZED_NAME;
+
+ case SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE:
+ return TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE;
+
+ case SSL_AD_BAD_CERTIFICATE_HASH_VALUE:
+ return TLS1_AD_BAD_CERTIFICATE_HASH_VALUE;
+
+ case SSL_AD_UNKNOWN_PSK_IDENTITY:
+ return TLS1_AD_UNKNOWN_PSK_IDENTITY;
+
+ case SSL_AD_INAPPROPRIATE_FALLBACK:
+ return SSL3_AD_INAPPROPRIATE_FALLBACK;
+
+ default:
+ return -1;
+ }
+}
diff --git a/src/ssl/t1_lib.c b/src/ssl/t1_lib.c
new file mode 100644
index 0000000..e26351b
--- /dev/null
+++ b/src/ssl/t1_lib.c
@@ -0,0 +1,2671 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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 <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include <openssl/bytestring.h>
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/rand.h>
+
+#include "ssl_locl.h"
+
+
+static int tls_decrypt_ticket(SSL *s, const uint8_t *tick, int ticklen,
+ const uint8_t *sess_id, int sesslen,
+ SSL_SESSION **psess);
+static int ssl_check_clienthello_tlsext(SSL *s);
+static int ssl_check_serverhello_tlsext(SSL *s);
+
+const SSL3_ENC_METHOD TLSv1_enc_data = {
+ tls1_enc,
+ tls1_prf,
+ tls1_setup_key_block,
+ tls1_generate_master_secret,
+ tls1_change_cipher_state,
+ tls1_final_finish_mac,
+ TLS1_FINISH_MAC_LENGTH,
+ tls1_cert_verify_mac,
+ TLS_MD_CLIENT_FINISH_CONST,TLS_MD_CLIENT_FINISH_CONST_SIZE,
+ TLS_MD_SERVER_FINISH_CONST,TLS_MD_SERVER_FINISH_CONST_SIZE,
+ tls1_alert_code,
+ tls1_export_keying_material,
+ 0,
+ SSL3_HM_HEADER_LENGTH,
+ ssl3_set_handshake_header,
+ ssl3_handshake_write,
+};
+
+const SSL3_ENC_METHOD TLSv1_1_enc_data = {
+ tls1_enc,
+ tls1_prf,
+ tls1_setup_key_block,
+ tls1_generate_master_secret,
+ tls1_change_cipher_state,
+ tls1_final_finish_mac,
+ TLS1_FINISH_MAC_LENGTH,
+ tls1_cert_verify_mac,
+ TLS_MD_CLIENT_FINISH_CONST,TLS_MD_CLIENT_FINISH_CONST_SIZE,
+ TLS_MD_SERVER_FINISH_CONST,TLS_MD_SERVER_FINISH_CONST_SIZE,
+ tls1_alert_code,
+ tls1_export_keying_material,
+ SSL_ENC_FLAG_EXPLICIT_IV,
+ SSL3_HM_HEADER_LENGTH,
+ ssl3_set_handshake_header,
+ ssl3_handshake_write,
+};
+
+const SSL3_ENC_METHOD TLSv1_2_enc_data = {
+ tls1_enc,
+ tls1_prf,
+ tls1_setup_key_block,
+ tls1_generate_master_secret,
+ tls1_change_cipher_state,
+ tls1_final_finish_mac,
+ TLS1_FINISH_MAC_LENGTH,
+ tls1_cert_verify_mac,
+ TLS_MD_CLIENT_FINISH_CONST,TLS_MD_CLIENT_FINISH_CONST_SIZE,
+ TLS_MD_SERVER_FINISH_CONST,TLS_MD_SERVER_FINISH_CONST_SIZE,
+ tls1_alert_code,
+ tls1_export_keying_material,
+ SSL_ENC_FLAG_EXPLICIT_IV|SSL_ENC_FLAG_SIGALGS|SSL_ENC_FLAG_SHA256_PRF
+ |SSL_ENC_FLAG_TLS1_2_CIPHERS,
+ SSL3_HM_HEADER_LENGTH,
+ ssl3_set_handshake_header,
+ ssl3_handshake_write,
+};
+
+static int compare_uint16_t(const void *p1, const void *p2) {
+ uint16_t u1 = *((const uint16_t *)p1);
+ uint16_t u2 = *((const uint16_t *)p2);
+ if (u1 < u2) {
+ return -1;
+ } else if (u1 > u2) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+/* Per http://tools.ietf.org/html/rfc5246#section-7.4.1.4, there may not be
+ * more than one extension of the same type in a ClientHello or ServerHello.
+ * This function does an initial scan over the extensions block to filter those
+ * out. */
+static int tls1_check_duplicate_extensions(const CBS *cbs) {
+ CBS extensions = *cbs;
+ size_t num_extensions = 0, i = 0;
+ uint16_t *extension_types = NULL;
+ int ret = 0;
+
+ /* First pass: count the extensions. */
+ while (CBS_len(&extensions) > 0) {
+ uint16_t type;
+ CBS extension;
+
+ if (!CBS_get_u16(&extensions, &type) ||
+ !CBS_get_u16_length_prefixed(&extensions, &extension)) {
+ goto done;
+ }
+
+ num_extensions++;
+ }
+
+ if (num_extensions == 0) {
+ return 1;
+ }
+
+ extension_types =
+ (uint16_t *)OPENSSL_malloc(sizeof(uint16_t) * num_extensions);
+ if (extension_types == NULL) {
+ OPENSSL_PUT_ERROR(SSL, tls1_check_duplicate_extensions,
+ ERR_R_MALLOC_FAILURE);
+ goto done;
+ }
+
+ /* Second pass: gather the extension types. */
+ extensions = *cbs;
+ for (i = 0; i < num_extensions; i++) {
+ CBS extension;
+
+ if (!CBS_get_u16(&extensions, &extension_types[i]) ||
+ !CBS_get_u16_length_prefixed(&extensions, &extension)) {
+ /* This should not happen. */
+ goto done;
+ }
+ }
+ assert(CBS_len(&extensions) == 0);
+
+ /* Sort the extensions and make sure there are no duplicates. */
+ qsort(extension_types, num_extensions, sizeof(uint16_t), compare_uint16_t);
+ for (i = 1; i < num_extensions; i++) {
+ if (extension_types[i - 1] == extension_types[i]) {
+ goto done;
+ }
+ }
+
+ ret = 1;
+
+done:
+ if (extension_types)
+ OPENSSL_free(extension_types);
+ return ret;
+}
+
+char ssl_early_callback_init(struct ssl_early_callback_ctx *ctx) {
+ CBS client_hello, session_id, cipher_suites, compression_methods, extensions;
+
+ CBS_init(&client_hello, ctx->client_hello, ctx->client_hello_len);
+
+ if (/* Skip client version. */
+ !CBS_skip(&client_hello, 2) ||
+ /* Skip client nonce. */
+ !CBS_skip(&client_hello, 32) ||
+ /* Extract session_id. */
+ !CBS_get_u8_length_prefixed(&client_hello, &session_id)) {
+ return 0;
+ }
+
+ ctx->session_id = CBS_data(&session_id);
+ ctx->session_id_len = CBS_len(&session_id);
+
+ /* Skip past DTLS cookie */
+ if (SSL_IS_DTLS(ctx->ssl)) {
+ CBS cookie;
+
+ if (!CBS_get_u8_length_prefixed(&client_hello, &cookie)) {
+ return 0;
+ }
+ }
+
+ /* Extract cipher_suites. */
+ if (!CBS_get_u16_length_prefixed(&client_hello, &cipher_suites) ||
+ CBS_len(&cipher_suites) < 2 || (CBS_len(&cipher_suites) & 1) != 0) {
+ return 0;
+ }
+ ctx->cipher_suites = CBS_data(&cipher_suites);
+ ctx->cipher_suites_len = CBS_len(&cipher_suites);
+
+ /* Extract compression_methods. */
+ if (!CBS_get_u8_length_prefixed(&client_hello, &compression_methods) ||
+ CBS_len(&compression_methods) < 1) {
+ return 0;
+ }
+ ctx->compression_methods = CBS_data(&compression_methods);
+ ctx->compression_methods_len = CBS_len(&compression_methods);
+
+ /* If the ClientHello ends here then it's valid, but doesn't have any
+ * extensions. (E.g. SSLv3.) */
+ if (CBS_len(&client_hello) == 0) {
+ ctx->extensions = NULL;
+ ctx->extensions_len = 0;
+ return 1;
+ }
+
+ /* Extract extensions and check it is valid. */
+ if (!CBS_get_u16_length_prefixed(&client_hello, &extensions) ||
+ !tls1_check_duplicate_extensions(&extensions) ||
+ CBS_len(&client_hello) != 0) {
+ return 0;
+ }
+ ctx->extensions = CBS_data(&extensions);
+ ctx->extensions_len = CBS_len(&extensions);
+
+ return 1;
+}
+
+char SSL_early_callback_ctx_extension_get(
+ const struct ssl_early_callback_ctx *ctx, uint16_t extension_type,
+ const uint8_t **out_data, size_t *out_len) {
+ CBS extensions;
+
+ CBS_init(&extensions, ctx->extensions, ctx->extensions_len);
+
+ while (CBS_len(&extensions) != 0) {
+ uint16_t type;
+ CBS extension;
+
+ /* Decode the next extension. */
+ if (!CBS_get_u16(&extensions, &type) ||
+ !CBS_get_u16_length_prefixed(&extensions, &extension)) {
+ return 0;
+ }
+
+ if (type == extension_type) {
+ *out_data = CBS_data(&extension);
+ *out_len = CBS_len(&extension);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+struct tls_curve {
+ uint16_t curve_id;
+ int nid;
+};
+
+/* ECC curves from RFC4492. */
+static const struct tls_curve tls_curves[] = {
+ {21, NID_secp224r1},
+ {23, NID_X9_62_prime256v1},
+ {24, NID_secp384r1},
+ {25, NID_secp521r1},
+};
+
+static const uint8_t ecformats_default[] = {
+ TLSEXT_ECPOINTFORMAT_uncompressed,
+};
+
+static const uint16_t eccurves_default[] = {
+ 23, /* X9_64_prime256v1 */
+ 24, /* secp384r1 */
+};
+
+int tls1_ec_curve_id2nid(uint16_t curve_id) {
+ size_t i;
+ for (i = 0; i < sizeof(tls_curves) / sizeof(tls_curves[0]); i++) {
+ if (curve_id == tls_curves[i].curve_id) {
+ return tls_curves[i].nid;
+ }
+ }
+ return NID_undef;
+}
+
+int tls1_ec_nid2curve_id(uint16_t *out_curve_id, int nid) {
+ size_t i;
+ for (i = 0; i < sizeof(tls_curves) / sizeof(tls_curves[0]); i++) {
+ if (nid == tls_curves[i].nid) {
+ *out_curve_id = tls_curves[i].curve_id;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* tls1_get_curvelist sets |*out_curve_ids| and |*out_curve_ids_len| to the
+ * list of allowed curve IDs. If |get_peer_curves| is non-zero, return the
+ * peer's curve list. Otherwise, return the preferred list. */
+static void tls1_get_curvelist(SSL *s, int get_peer_curves,
+ const uint16_t **out_curve_ids,
+ size_t *out_curve_ids_len) {
+ if (get_peer_curves) {
+ *out_curve_ids = s->s3->tmp.peer_ellipticcurvelist;
+ *out_curve_ids_len = s->s3->tmp.peer_ellipticcurvelist_length;
+ return;
+ }
+
+ *out_curve_ids = s->tlsext_ellipticcurvelist;
+ *out_curve_ids_len = s->tlsext_ellipticcurvelist_length;
+ if (!*out_curve_ids) {
+ *out_curve_ids = eccurves_default;
+ *out_curve_ids_len = sizeof(eccurves_default) / sizeof(eccurves_default[0]);
+ }
+}
+
+int tls1_check_curve(SSL *s, CBS *cbs, uint16_t *out_curve_id) {
+ uint8_t curve_type;
+ uint16_t curve_id;
+ const uint16_t *curves;
+ size_t curves_len, i;
+
+ /* Only support named curves. */
+ if (!CBS_get_u8(cbs, &curve_type) ||
+ curve_type != NAMED_CURVE_TYPE ||
+ !CBS_get_u16(cbs, &curve_id)) {
+ return 0;
+ }
+
+ tls1_get_curvelist(s, 0, &curves, &curves_len);
+ for (i = 0; i < curves_len; i++) {
+ if (curve_id == curves[i]) {
+ *out_curve_id = curve_id;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+int tls1_get_shared_curve(SSL *s) {
+ const uint16_t *pref, *supp;
+ size_t preflen, supplen, i, j;
+
+ /* Can't do anything on client side */
+ if (s->server == 0) {
+ return NID_undef;
+ }
+
+ /* Return first preference shared curve */
+ tls1_get_curvelist(s, !!(s->options & SSL_OP_CIPHER_SERVER_PREFERENCE), &supp,
+ &supplen);
+ tls1_get_curvelist(s, !(s->options & SSL_OP_CIPHER_SERVER_PREFERENCE), &pref,
+ &preflen);
+
+ for (i = 0; i < preflen; i++) {
+ for (j = 0; j < supplen; j++) {
+ if (pref[i] == supp[j]) {
+ return tls1_ec_curve_id2nid(pref[i]);
+ }
+ }
+ }
+
+ return NID_undef;
+}
+
+int tls1_set_curves(uint16_t **out_curve_ids, size_t *out_curve_ids_len,
+ const int *curves, size_t ncurves) {
+ uint16_t *curve_ids;
+ size_t i;
+
+ curve_ids = (uint16_t *)OPENSSL_malloc(ncurves * sizeof(uint16_t));
+ if (curve_ids == NULL) {
+ return 0;
+ }
+
+ for (i = 0; i < ncurves; i++) {
+ if (!tls1_ec_nid2curve_id(&curve_ids[i], curves[i])) {
+ OPENSSL_free(curve_ids);
+ return 0;
+ }
+ }
+
+ if (*out_curve_ids) {
+ OPENSSL_free(*out_curve_ids);
+ }
+ *out_curve_ids = curve_ids;
+ *out_curve_ids_len = ncurves;
+
+ return 1;
+}
+
+/* tls1_curve_params_from_ec_key sets |*out_curve_id| and |*out_comp_id| to the
+ * TLS curve ID and point format, respectively, for |ec|. It returns one on
+ * success and zero on failure. */
+static int tls1_curve_params_from_ec_key(uint16_t *out_curve_id,
+ uint8_t *out_comp_id, EC_KEY *ec) {
+ int nid;
+ uint16_t id;
+ const EC_GROUP *grp;
+
+ if (ec == NULL) {
+ return 0;
+ }
+
+ grp = EC_KEY_get0_group(ec);
+ if (grp == NULL) {
+ return 0;
+ }
+
+ /* Determine curve ID */
+ nid = EC_GROUP_get_curve_name(grp);
+ if (!tls1_ec_nid2curve_id(&id, nid)) {
+ return 0;
+ }
+
+ /* Set the named curve ID. Arbitrary explicit curves are not supported. */
+ *out_curve_id = id;
+
+ if (out_comp_id) {
+ if (EC_KEY_get0_public_key(ec) == NULL) {
+ return 0;
+ }
+ if (EC_KEY_get_conv_form(ec) == POINT_CONVERSION_COMPRESSED) {
+ *out_comp_id = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime;
+ } else {
+ *out_comp_id = TLSEXT_ECPOINTFORMAT_uncompressed;
+ }
+ }
+
+ return 1;
+}
+
+/* tls1_check_point_format returns one if |comp_id| is consistent with the
+ * peer's point format preferences. */
+static int tls1_check_point_format(SSL *s, uint8_t comp_id) {
+ uint8_t *p = s->s3->tmp.peer_ecpointformatlist;
+ size_t plen = s->s3->tmp.peer_ecpointformatlist_length;
+ size_t i;
+
+ /* If point formats extension present check it, otherwise everything is
+ * supported (see RFC4492). */
+ if (p == NULL) {
+ return 1;
+ }
+
+ for (i = 0; i < plen; i++) {
+ if (comp_id == p[i]) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/* tls1_check_curve_id returns one if |curve_id| is consistent with both our
+ * and the peer's curve preferences. Note: if called as the client, only our
+ * preferences are checked; the peer (the server) does not send preferences. */
+static int tls1_check_curve_id(SSL *s, uint16_t curve_id) {
+ const uint16_t *curves;
+ size_t curves_len, i, j;
+
+ /* Check against our list, then the peer's list. */
+ for (j = 0; j <= 1; j++) {
+ tls1_get_curvelist(s, j, &curves, &curves_len);
+ for (i = 0; i < curves_len; i++) {
+ if (curves[i] == curve_id) {
+ break;
+ }
+ }
+
+ if (i == curves_len) {
+ return 0;
+ }
+
+ /* Servers do not present a preference list so, if we are a client, only
+ * check our list. */
+ if (!s->server) {
+ return 1;
+ }
+ }
+
+ return 1;
+}
+
+static void tls1_get_formatlist(SSL *s, const uint8_t **pformats,
+ size_t *pformatslen) {
+ /* If we have a custom point format list use it otherwise use default */
+ if (s->tlsext_ecpointformatlist) {
+ *pformats = s->tlsext_ecpointformatlist;
+ *pformatslen = s->tlsext_ecpointformatlist_length;
+ } else {
+ *pformats = ecformats_default;
+ *pformatslen = sizeof(ecformats_default);
+ }
+}
+
+int tls1_check_ec_cert(SSL *s, X509 *x) {
+ int ret = 0;
+ EVP_PKEY *pkey = X509_get_pubkey(x);
+ uint16_t curve_id;
+ uint8_t comp_id;
+
+ if (!pkey ||
+ pkey->type != EVP_PKEY_EC ||
+ !tls1_curve_params_from_ec_key(&curve_id, &comp_id, pkey->pkey.ec) ||
+ !tls1_check_curve_id(s, curve_id) ||
+ !tls1_check_point_format(s, comp_id)) {
+ goto done;
+ }
+
+ ret = 1;
+
+done:
+ if (pkey) {
+ EVP_PKEY_free(pkey);
+ }
+ return ret;
+}
+
+int tls1_check_ec_tmp_key(SSL *s) {
+ uint16_t curve_id;
+ EC_KEY *ec = s->cert->ecdh_tmp;
+
+ if (s->cert->ecdh_tmp_auto) {
+ /* Need a shared curve */
+ return tls1_get_shared_curve(s) != NID_undef;
+ }
+
+ if (!ec) {
+ if (s->cert->ecdh_tmp_cb) {
+ return 1;
+ }
+ return 0;
+ }
+
+ return tls1_curve_params_from_ec_key(&curve_id, NULL, ec) &&
+ tls1_check_curve_id(s, curve_id);
+}
+
+/* List of supported signature algorithms and hashes. Should make this
+ * customisable at some point, for now include everything we support. */
+
+#define tlsext_sigalg_rsa(md) md, TLSEXT_signature_rsa,
+
+#define tlsext_sigalg_ecdsa(md) md, TLSEXT_signature_ecdsa,
+
+#define tlsext_sigalg(md) tlsext_sigalg_rsa(md) tlsext_sigalg_ecdsa(md)
+
+static const uint8_t tls12_sigalgs[] = {
+ tlsext_sigalg(TLSEXT_hash_sha512)
+ tlsext_sigalg(TLSEXT_hash_sha384)
+ tlsext_sigalg(TLSEXT_hash_sha256)
+ tlsext_sigalg(TLSEXT_hash_sha224)
+ tlsext_sigalg(TLSEXT_hash_sha1)
+};
+
+size_t tls12_get_psigalgs(SSL *s, const uint8_t **psigs) {
+ /* If server use client authentication sigalgs if not NULL */
+ if (s->server && s->cert->client_sigalgs) {
+ *psigs = s->cert->client_sigalgs;
+ return s->cert->client_sigalgslen;
+ } else if (s->cert->conf_sigalgs) {
+ *psigs = s->cert->conf_sigalgs;
+ return s->cert->conf_sigalgslen;
+ } else {
+ *psigs = tls12_sigalgs;
+ return sizeof(tls12_sigalgs);
+ }
+}
+
+/* tls12_check_peer_sigalg parses a SignatureAndHashAlgorithm out of |cbs|. It
+ * checks it is consistent with |s|'s sent supported signature algorithms and,
+ * if so, writes the relevant digest into |*out_md| and returns 1. Otherwise it
+ * returns 0 and writes an alert into |*out_alert|. */
+int tls12_check_peer_sigalg(const EVP_MD **out_md, int *out_alert, SSL *s,
+ CBS *cbs, EVP_PKEY *pkey) {
+ const uint8_t *sent_sigs;
+ size_t sent_sigslen, i;
+ int sigalg = tls12_get_sigid(pkey);
+ uint8_t hash, signature;
+
+ /* Should never happen */
+ if (sigalg == -1) {
+ OPENSSL_PUT_ERROR(SSL, tls12_check_peer_sigalg, ERR_R_INTERNAL_ERROR);
+ *out_alert = SSL_AD_INTERNAL_ERROR;
+ return 0;
+ }
+
+ if (!CBS_get_u8(cbs, &hash) ||
+ !CBS_get_u8(cbs, &signature)) {
+ OPENSSL_PUT_ERROR(SSL, tls12_check_peer_sigalg, SSL_R_DECODE_ERROR);
+ *out_alert = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ /* Check key type is consistent with signature */
+ if (sigalg != signature) {
+ OPENSSL_PUT_ERROR(SSL, tls12_check_peer_sigalg, SSL_R_WRONG_SIGNATURE_TYPE);
+ *out_alert = SSL_AD_ILLEGAL_PARAMETER;
+ return 0;
+ }
+
+ if (pkey->type == EVP_PKEY_EC) {
+ uint16_t curve_id;
+ uint8_t comp_id;
+ /* Check compression and curve matches extensions */
+ if (!tls1_curve_params_from_ec_key(&curve_id, &comp_id, pkey->pkey.ec)) {
+ *out_alert = SSL_AD_INTERNAL_ERROR;
+ return 0;
+ }
+
+ if (s->server && (!tls1_check_curve_id(s, curve_id) ||
+ !tls1_check_point_format(s, comp_id))) {
+ OPENSSL_PUT_ERROR(SSL, tls12_check_peer_sigalg, SSL_R_WRONG_CURVE);
+ *out_alert = SSL_AD_ILLEGAL_PARAMETER;
+ return 0;
+ }
+ }
+
+ /* Check signature matches a type we sent */
+ sent_sigslen = tls12_get_psigalgs(s, &sent_sigs);
+ for (i = 0; i < sent_sigslen; i += 2, sent_sigs += 2) {
+ if (hash == sent_sigs[0] && signature == sent_sigs[1]) {
+ break;
+ }
+ }
+
+ /* Allow fallback to SHA-1. */
+ if (i == sent_sigslen && hash != TLSEXT_hash_sha1) {
+ OPENSSL_PUT_ERROR(SSL, tls12_check_peer_sigalg, SSL_R_WRONG_SIGNATURE_TYPE);
+ *out_alert = SSL_AD_ILLEGAL_PARAMETER;
+ return 0;
+ }
+
+ *out_md = tls12_get_hash(hash);
+ if (*out_md == NULL) {
+ OPENSSL_PUT_ERROR(SSL, tls12_check_peer_sigalg, SSL_R_UNKNOWN_DIGEST);
+ *out_alert = SSL_AD_ILLEGAL_PARAMETER;
+ return 0;
+ }
+
+ return 1;
+}
+
+/* Get a mask of disabled algorithms: an algorithm is disabled if it isn't
+ * supported or doesn't appear in supported signature algorithms. Unlike
+ * ssl_cipher_get_disabled this applies to a specific session and not global
+ * settings. */
+void ssl_set_client_disabled(SSL *s) {
+ CERT *c = s->cert;
+ const uint8_t *sigalgs;
+ size_t i, sigalgslen;
+ int have_rsa = 0, have_ecdsa = 0;
+ c->mask_a = 0;
+ c->mask_k = 0;
+
+ /* Don't allow TLS 1.2 only ciphers if we don't suppport them */
+ if (!SSL_CLIENT_USE_TLS1_2_CIPHERS(s)) {
+ c->mask_ssl = SSL_TLSV1_2;
+ } else {
+ c->mask_ssl = 0;
+ }
+
+ /* Now go through all signature algorithms seeing if we support any for RSA,
+ * DSA, ECDSA. Do this for all versions not just TLS 1.2. */
+ sigalgslen = tls12_get_psigalgs(s, &sigalgs);
+ for (i = 0; i < sigalgslen; i += 2, sigalgs += 2) {
+ switch (sigalgs[1]) {
+ case TLSEXT_signature_rsa:
+ have_rsa = 1;
+ break;
+
+ case TLSEXT_signature_ecdsa:
+ have_ecdsa = 1;
+ break;
+ }
+ }
+
+ /* Disable auth if we don't include any appropriate signature algorithms. */
+ if (!have_rsa) {
+ c->mask_a |= SSL_aRSA;
+ }
+ if (!have_ecdsa) {
+ c->mask_a |= SSL_aECDSA;
+ }
+
+ /* with PSK there must be client callback set */
+ if (!s->psk_client_callback) {
+ c->mask_a |= SSL_aPSK;
+ c->mask_k |= SSL_kPSK;
+ }
+}
+
+/* header_len is the length of the ClientHello header written so far, used to
+ * compute padding. It does not include the record header. Pass 0 if no padding
+ * is to be done. */
+uint8_t *ssl_add_clienthello_tlsext(SSL *s, uint8_t *buf, uint8_t *limit,
+ size_t header_len) {
+ int extdatalen = 0;
+ uint8_t *ret = buf;
+ uint8_t *orig = buf;
+ /* See if we support any ECC ciphersuites */
+ int using_ecc = 0;
+
+ if (s->version >= TLS1_VERSION || SSL_IS_DTLS(s)) {
+ size_t i;
+ unsigned long alg_k, alg_a;
+ STACK_OF(SSL_CIPHER) *cipher_stack = SSL_get_ciphers(s);
+
+ for (i = 0; i < sk_SSL_CIPHER_num(cipher_stack); i++) {
+ const SSL_CIPHER *c = sk_SSL_CIPHER_value(cipher_stack, i);
+
+ alg_k = c->algorithm_mkey;
+ alg_a = c->algorithm_auth;
+ if ((alg_k & SSL_kEECDH) || (alg_a & SSL_aECDSA)) {
+ using_ecc = 1;
+ break;
+ }
+ }
+ }
+
+ /* don't add extensions for SSLv3 unless doing secure renegotiation */
+ if (s->client_version == SSL3_VERSION && !s->s3->send_connection_binding) {
+ return orig;
+ }
+
+ ret += 2;
+
+ if (ret >= limit) {
+ return NULL; /* should never occur. */
+ }
+
+ if (s->tlsext_hostname != NULL) {
+ /* Add TLS extension servername to the Client Hello message */
+ unsigned long size_str;
+ long lenmax;
+
+ /* check for enough space.
+ 4 for the servername type and entension length
+ 2 for servernamelist length
+ 1 for the hostname type
+ 2 for hostname length
+ + hostname length */
+
+ lenmax = limit - ret - 9;
+ size_str = strlen(s->tlsext_hostname);
+ if (lenmax < 0 || size_str > (unsigned long)lenmax) {
+ return NULL;
+ }
+
+ /* extension type and length */
+ s2n(TLSEXT_TYPE_server_name, ret);
+ s2n(size_str + 5, ret);
+
+ /* length of servername list */
+ s2n(size_str + 3, ret);
+
+ /* hostname type, length and hostname */
+ *(ret++) = (uint8_t)TLSEXT_NAMETYPE_host_name;
+ s2n(size_str, ret);
+ memcpy(ret, s->tlsext_hostname, size_str);
+ ret += size_str;
+ }
+
+ /* Add RI if renegotiating */
+ if (s->renegotiate) {
+ int el;
+
+ if (!ssl_add_clienthello_renegotiate_ext(s, 0, &el, 0)) {
+ OPENSSL_PUT_ERROR(SSL, ssl_add_clienthello_tlsext, ERR_R_INTERNAL_ERROR);
+ return NULL;
+ }
+
+ if ((limit - ret - 4 - el) < 0) {
+ return NULL;
+ }
+
+ s2n(TLSEXT_TYPE_renegotiate, ret);
+ s2n(el, ret);
+
+ if (!ssl_add_clienthello_renegotiate_ext(s, ret, &el, el)) {
+ OPENSSL_PUT_ERROR(SSL, ssl_add_clienthello_tlsext, ERR_R_INTERNAL_ERROR);
+ return NULL;
+ }
+
+ ret += el;
+ }
+
+ /* Add extended master secret. */
+ if (s->version != SSL3_VERSION) {
+ if (limit - ret - 4 < 0) {
+ return NULL;
+ }
+ s2n(TLSEXT_TYPE_extended_master_secret, ret);
+ s2n(0, ret);
+ }
+
+ if (!(SSL_get_options(s) & SSL_OP_NO_TICKET)) {
+ int ticklen = 0;
+ if (!s->new_session && s->session && s->session->tlsext_tick) {
+ ticklen = s->session->tlsext_ticklen;
+ }
+
+ /* Check for enough room 2 for extension type, 2 for len rest for
+ * ticket. */
+ if ((long)(limit - ret - 4 - ticklen) < 0) {
+ return NULL;
+ }
+ s2n(TLSEXT_TYPE_session_ticket, ret);
+ s2n(ticklen, ret);
+ if (ticklen) {
+ memcpy(ret, s->session->tlsext_tick, ticklen);
+ ret += ticklen;
+ }
+ }
+
+ if (ssl3_version_from_wire(s, s->client_version) >= TLS1_2_VERSION) {
+ size_t salglen;
+ const uint8_t *salg;
+ salglen = tls12_get_psigalgs(s, &salg);
+ if ((size_t)(limit - ret) < salglen + 6) {
+ return NULL;
+ }
+ s2n(TLSEXT_TYPE_signature_algorithms, ret);
+ s2n(salglen + 2, ret);
+ s2n(salglen, ret);
+ memcpy(ret, salg, salglen);
+ ret += salglen;
+ }
+
+ if (s->ocsp_stapling_enabled) {
+ /* The status_request extension is excessively extensible at every layer.
+ * On the client, only support requesting OCSP responses with an empty
+ * responder_id_list and no extensions. */
+ if (limit - ret - 4 - 1 - 2 - 2 < 0) {
+ return NULL;
+ }
+
+ s2n(TLSEXT_TYPE_status_request, ret);
+ s2n(1 + 2 + 2, ret);
+ /* status_type */
+ *(ret++) = TLSEXT_STATUSTYPE_ocsp;
+ /* responder_id_list - empty */
+ s2n(0, ret);
+ /* request_extensions - empty */
+ s2n(0, ret);
+ }
+
+ if (s->ctx->next_proto_select_cb && !s->s3->tmp.finish_md_len &&
+ !SSL_IS_DTLS(s)) {
+ /* The client advertises an emtpy extension to indicate its support for
+ * Next Protocol Negotiation */
+ if (limit - ret - 4 < 0) {
+ return NULL;
+ }
+ s2n(TLSEXT_TYPE_next_proto_neg, ret);
+ s2n(0, ret);
+ }
+
+ if (s->signed_cert_timestamps_enabled && !s->s3->tmp.finish_md_len) {
+ /* The client advertises an empty extension to indicate its support for
+ * certificate timestamps. */
+ if (limit - ret - 4 < 0) {
+ return NULL;
+ }
+ s2n(TLSEXT_TYPE_certificate_timestamp, ret);
+ s2n(0, ret);
+ }
+
+ if (s->alpn_client_proto_list && !s->s3->tmp.finish_md_len) {
+ if ((size_t)(limit - ret) < 6 + s->alpn_client_proto_list_len) {
+ return NULL;
+ }
+ s2n(TLSEXT_TYPE_application_layer_protocol_negotiation, ret);
+ s2n(2 + s->alpn_client_proto_list_len, ret);
+ s2n(s->alpn_client_proto_list_len, ret);
+ memcpy(ret, s->alpn_client_proto_list, s->alpn_client_proto_list_len);
+ ret += s->alpn_client_proto_list_len;
+ }
+
+ if (s->tlsext_channel_id_enabled && !SSL_IS_DTLS(s)) {
+ /* The client advertises an emtpy extension to indicate its support for
+ * Channel ID. */
+ if (limit - ret - 4 < 0) {
+ return NULL;
+ }
+ if (s->ctx->tlsext_channel_id_enabled_new) {
+ s2n(TLSEXT_TYPE_channel_id_new, ret);
+ } else {
+ s2n(TLSEXT_TYPE_channel_id, ret);
+ }
+ s2n(0, ret);
+ }
+
+ if (SSL_get_srtp_profiles(s)) {
+ int el;
+
+ ssl_add_clienthello_use_srtp_ext(s, 0, &el, 0);
+
+ if ((limit - ret - 4 - el) < 0) {
+ return NULL;
+ }
+
+ s2n(TLSEXT_TYPE_use_srtp, ret);
+ s2n(el, ret);
+
+ if (!ssl_add_clienthello_use_srtp_ext(s, ret, &el, el)) {
+ OPENSSL_PUT_ERROR(SSL, ssl_add_clienthello_tlsext, ERR_R_INTERNAL_ERROR);
+ return NULL;
+ }
+ ret += el;
+ }
+
+ if (using_ecc) {
+ /* Add TLS extension ECPointFormats to the ClientHello message */
+ long lenmax;
+ const uint8_t *formats;
+ const uint16_t *curves;
+ size_t formats_len, curves_len, i;
+
+ tls1_get_formatlist(s, &formats, &formats_len);
+
+ lenmax = limit - ret - 5;
+ if (lenmax < 0) {
+ return NULL;
+ }
+ if (formats_len > (size_t)lenmax) {
+ return NULL;
+ }
+ if (formats_len > 255) {
+ OPENSSL_PUT_ERROR(SSL, ssl_add_clienthello_tlsext, ERR_R_INTERNAL_ERROR);
+ return NULL;
+ }
+
+ s2n(TLSEXT_TYPE_ec_point_formats, ret);
+ s2n(formats_len + 1, ret);
+ *(ret++) = (uint8_t)formats_len;
+ memcpy(ret, formats, formats_len);
+ ret += formats_len;
+
+ /* Add TLS extension EllipticCurves to the ClientHello message */
+ tls1_get_curvelist(s, 0, &curves, &curves_len);
+
+ lenmax = limit - ret - 6;
+ if (lenmax < 0) {
+ return NULL;
+ }
+ if (curves_len * 2 > (size_t)lenmax) {
+ return NULL;
+ }
+ if (curves_len * 2 > 65532) {
+ OPENSSL_PUT_ERROR(SSL, ssl_add_clienthello_tlsext, ERR_R_INTERNAL_ERROR);
+ return NULL;
+ }
+
+ s2n(TLSEXT_TYPE_elliptic_curves, ret);
+ s2n((curves_len * 2) + 2, ret);
+
+ s2n(curves_len * 2, ret);
+ for (i = 0; i < curves_len; i++) {
+ s2n(curves[i], ret);
+ }
+ }
+
+ if (header_len > 0) {
+ size_t clienthello_minsize = 0;
+ header_len += ret - orig;
+ if (header_len > 0xff && header_len < 0x200) {
+ /* Add padding to workaround bugs in F5 terminators. See
+ * https://tools.ietf.org/html/draft-agl-tls-padding-03
+ *
+ * NB: because this code works out the length of all existing extensions
+ * it MUST always appear last. */
+ clienthello_minsize = 0x200;
+ }
+ if (s->fastradio_padding) {
+ /* Pad the ClientHello record to 1024 bytes to fast forward the radio
+ * into DCH (high data rate) state in 3G networks. Note that when
+ * fastradio_padding is enabled, even if the header_len is less than 255
+ * bytes, the padding will be applied regardless. This is slightly
+ * different from the TLS padding extension suggested in
+ * https://tools.ietf.org/html/draft-agl-tls-padding-03 */
+ clienthello_minsize = 0x400;
+ }
+ if (header_len < clienthello_minsize) {
+ size_t padding_len = clienthello_minsize - header_len;
+ /* Extensions take at least four bytes to encode. Always include least
+ * one byte of data if including the extension. WebSphere Application
+ * Server 7.0 is intolerant to the last extension being zero-length. */
+ if (padding_len >= 4 + 1) {
+ padding_len -= 4;
+ } else {
+ padding_len = 1;
+ }
+
+ if (limit - ret - 4 - (long)padding_len < 0) {
+ return NULL;
+ }
+
+ s2n(TLSEXT_TYPE_padding, ret);
+ s2n(padding_len, ret);
+ memset(ret, 0, padding_len);
+ ret += padding_len;
+ }
+ }
+
+ extdatalen = ret - orig - 2;
+ if (extdatalen == 0) {
+ return orig;
+ }
+
+ s2n(extdatalen, orig);
+ return ret;
+}
+
+uint8_t *ssl_add_serverhello_tlsext(SSL *s, uint8_t *buf, uint8_t *limit) {
+ int extdatalen = 0;
+ uint8_t *orig = buf;
+ uint8_t *ret = buf;
+ int next_proto_neg_seen;
+ unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
+ unsigned long alg_a = s->s3->tmp.new_cipher->algorithm_auth;
+ int using_ecc = (alg_k & SSL_kEECDH) || (alg_a & SSL_aECDSA);
+ using_ecc = using_ecc && (s->s3->tmp.peer_ecpointformatlist != NULL);
+
+ /* don't add extensions for SSLv3, unless doing secure renegotiation */
+ if (s->version == SSL3_VERSION && !s->s3->send_connection_binding) {
+ return orig;
+ }
+
+ ret += 2;
+ if (ret >= limit) {
+ return NULL; /* should never happen. */
+ }
+
+ if (!s->hit && s->should_ack_sni && s->session->tlsext_hostname != NULL) {
+ if ((long)(limit - ret - 4) < 0) {
+ return NULL;
+ }
+
+ s2n(TLSEXT_TYPE_server_name, ret);
+ s2n(0, ret);
+ }
+
+ if (s->s3->send_connection_binding) {
+ int el;
+
+ if (!ssl_add_serverhello_renegotiate_ext(s, 0, &el, 0)) {
+ OPENSSL_PUT_ERROR(SSL, ssl_add_serverhello_tlsext, ERR_R_INTERNAL_ERROR);
+ return NULL;
+ }
+
+ if ((limit - ret - 4 - el) < 0) {
+ return NULL;
+ }
+
+ s2n(TLSEXT_TYPE_renegotiate, ret);
+ s2n(el, ret);
+
+ if (!ssl_add_serverhello_renegotiate_ext(s, ret, &el, el)) {
+ OPENSSL_PUT_ERROR(SSL, ssl_add_serverhello_tlsext, ERR_R_INTERNAL_ERROR);
+ return NULL;
+ }
+
+ ret += el;
+ }
+
+ if (s->s3->tmp.extended_master_secret) {
+ if ((long)(limit - ret - 4) < 0) {
+ return NULL;
+ }
+
+ s2n(TLSEXT_TYPE_extended_master_secret, ret);
+ s2n(0, ret);
+ }
+
+ if (using_ecc) {
+ const uint8_t *plist;
+ size_t plistlen;
+ /* Add TLS extension ECPointFormats to the ServerHello message */
+ long lenmax;
+
+ tls1_get_formatlist(s, &plist, &plistlen);
+
+ lenmax = limit - ret - 5;
+ if (lenmax < 0) {
+ return NULL;
+ }
+ if (plistlen > (size_t)lenmax) {
+ return NULL;
+ }
+ if (plistlen > 255) {
+ OPENSSL_PUT_ERROR(SSL, ssl_add_serverhello_tlsext, ERR_R_INTERNAL_ERROR);
+ return NULL;
+ }
+
+ s2n(TLSEXT_TYPE_ec_point_formats, ret);
+ s2n(plistlen + 1, ret);
+ *(ret++) = (uint8_t)plistlen;
+ memcpy(ret, plist, plistlen);
+ ret += plistlen;
+ }
+ /* Currently the server should not respond with a SupportedCurves extension */
+
+ if (s->tlsext_ticket_expected && !(SSL_get_options(s) & SSL_OP_NO_TICKET)) {
+ if ((long)(limit - ret - 4) < 0) {
+ return NULL;
+ }
+ s2n(TLSEXT_TYPE_session_ticket, ret);
+ s2n(0, ret);
+ }
+
+ if (s->s3->tmp.certificate_status_expected) {
+ if ((long)(limit - ret - 4) < 0) {
+ return NULL;
+ }
+ s2n(TLSEXT_TYPE_status_request, ret);
+ s2n(0, ret);
+ }
+
+ if (s->srtp_profile) {
+ int el;
+
+ ssl_add_serverhello_use_srtp_ext(s, 0, &el, 0);
+
+ if ((limit - ret - 4 - el) < 0) {
+ return NULL;
+ }
+
+ s2n(TLSEXT_TYPE_use_srtp, ret);
+ s2n(el, ret);
+
+ if (!ssl_add_serverhello_use_srtp_ext(s, ret, &el, el)) {
+ OPENSSL_PUT_ERROR(SSL, ssl_add_serverhello_tlsext, ERR_R_INTERNAL_ERROR);
+ return NULL;
+ }
+ ret += el;
+ }
+
+ next_proto_neg_seen = s->s3->next_proto_neg_seen;
+ s->s3->next_proto_neg_seen = 0;
+ if (next_proto_neg_seen && s->ctx->next_protos_advertised_cb) {
+ const uint8_t *npa;
+ unsigned int npalen;
+ int r;
+
+ r = s->ctx->next_protos_advertised_cb(
+ s, &npa, &npalen, s->ctx->next_protos_advertised_cb_arg);
+ if (r == SSL_TLSEXT_ERR_OK) {
+ if ((long)(limit - ret - 4 - npalen) < 0) {
+ return NULL;
+ }
+ s2n(TLSEXT_TYPE_next_proto_neg, ret);
+ s2n(npalen, ret);
+ memcpy(ret, npa, npalen);
+ ret += npalen;
+ s->s3->next_proto_neg_seen = 1;
+ }
+ }
+
+ if (s->s3->alpn_selected) {
+ const uint8_t *selected = s->s3->alpn_selected;
+ size_t len = s->s3->alpn_selected_len;
+
+ if ((long)(limit - ret - 4 - 2 - 1 - len) < 0) {
+ return NULL;
+ }
+ s2n(TLSEXT_TYPE_application_layer_protocol_negotiation, ret);
+ s2n(3 + len, ret);
+ s2n(1 + len, ret);
+ *ret++ = len;
+ memcpy(ret, selected, len);
+ ret += len;
+ }
+
+ /* If the client advertised support for Channel ID, and we have it
+ * enabled, then we want to echo it back. */
+ if (s->s3->tlsext_channel_id_valid) {
+ if (limit - ret - 4 < 0) {
+ return NULL;
+ }
+ if (s->s3->tlsext_channel_id_new) {
+ s2n(TLSEXT_TYPE_channel_id_new, ret);
+ } else {
+ s2n(TLSEXT_TYPE_channel_id, ret);
+ }
+ s2n(0, ret);
+ }
+
+ extdatalen = ret - orig - 2;
+ if (extdatalen == 0) {
+ return orig;
+ }
+
+ s2n(extdatalen, orig);
+ return ret;
+}
+
+/* tls1_alpn_handle_client_hello is called to process the ALPN extension in a
+ * ClientHello.
+ * cbs: the contents of the extension, not including the type and length.
+ * out_alert: a pointer to the alert value to send in the event of a zero
+ * return.
+ *
+ * returns: 1 on success. */
+static int tls1_alpn_handle_client_hello(SSL *s, CBS *cbs, int *out_alert) {
+ CBS protocol_name_list, protocol_name_list_copy;
+ const uint8_t *selected;
+ uint8_t selected_len;
+ int r;
+
+ if (s->ctx->alpn_select_cb == NULL) {
+ return 1;
+ }
+
+ if (!CBS_get_u16_length_prefixed(cbs, &protocol_name_list) ||
+ CBS_len(cbs) != 0 || CBS_len(&protocol_name_list) < 2) {
+ goto parse_error;
+ }
+
+ /* Validate the protocol list. */
+ protocol_name_list_copy = protocol_name_list;
+ while (CBS_len(&protocol_name_list_copy) > 0) {
+ CBS protocol_name;
+
+ if (!CBS_get_u8_length_prefixed(&protocol_name_list_copy, &protocol_name)) {
+ goto parse_error;
+ }
+ }
+
+ r = s->ctx->alpn_select_cb(
+ s, &selected, &selected_len, CBS_data(&protocol_name_list),
+ CBS_len(&protocol_name_list), s->ctx->alpn_select_cb_arg);
+ if (r == SSL_TLSEXT_ERR_OK) {
+ if (s->s3->alpn_selected) {
+ OPENSSL_free(s->s3->alpn_selected);
+ }
+ s->s3->alpn_selected = BUF_memdup(selected, selected_len);
+ if (!s->s3->alpn_selected) {
+ *out_alert = SSL_AD_INTERNAL_ERROR;
+ return 0;
+ }
+ s->s3->alpn_selected_len = selected_len;
+ }
+
+ return 1;
+
+parse_error:
+ *out_alert = SSL_AD_DECODE_ERROR;
+ return 0;
+}
+
+static int ssl_scan_clienthello_tlsext(SSL *s, CBS *cbs, int *out_alert) {
+ int renegotiate_seen = 0;
+ CBS extensions;
+
+ s->should_ack_sni = 0;
+ s->srtp_profile = NULL;
+ s->s3->next_proto_neg_seen = 0;
+ s->s3->tmp.certificate_status_expected = 0;
+ s->s3->tmp.extended_master_secret = 0;
+
+ if (s->s3->alpn_selected) {
+ OPENSSL_free(s->s3->alpn_selected);
+ s->s3->alpn_selected = NULL;
+ }
+
+ /* Clear any signature algorithms extension received */
+ if (s->cert->peer_sigalgs) {
+ OPENSSL_free(s->cert->peer_sigalgs);
+ s->cert->peer_sigalgs = NULL;
+ }
+
+ /* Clear any shared signature algorithms */
+ if (s->cert->shared_sigalgs) {
+ OPENSSL_free(s->cert->shared_sigalgs);
+ s->cert->shared_sigalgs = NULL;
+ }
+
+ /* Clear ECC extensions */
+ if (s->s3->tmp.peer_ecpointformatlist != 0) {
+ OPENSSL_free(s->s3->tmp.peer_ecpointformatlist);
+ s->s3->tmp.peer_ecpointformatlist = NULL;
+ s->s3->tmp.peer_ecpointformatlist_length = 0;
+ }
+
+ if (s->s3->tmp.peer_ellipticcurvelist != 0) {
+ OPENSSL_free(s->s3->tmp.peer_ellipticcurvelist);
+ s->s3->tmp.peer_ellipticcurvelist = NULL;
+ s->s3->tmp.peer_ellipticcurvelist_length = 0;
+ }
+
+ /* There may be no extensions. */
+ if (CBS_len(cbs) == 0) {
+ goto ri_check;
+ }
+
+ /* Decode the extensions block and check it is valid. */
+ if (!CBS_get_u16_length_prefixed(cbs, &extensions) ||
+ !tls1_check_duplicate_extensions(&extensions)) {
+ *out_alert = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ while (CBS_len(&extensions) != 0) {
+ uint16_t type;
+ CBS extension;
+
+ /* Decode the next extension. */
+ if (!CBS_get_u16(&extensions, &type) ||
+ !CBS_get_u16_length_prefixed(&extensions, &extension)) {
+ *out_alert = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ if (s->tlsext_debug_cb) {
+ s->tlsext_debug_cb(s, 0, type, (uint8_t *)CBS_data(&extension),
+ CBS_len(&extension), s->tlsext_debug_arg);
+ }
+
+ /* The servername extension is treated as follows:
+
+ - Only the hostname type is supported with a maximum length of 255.
+ - The servername is rejected if too long or if it contains zeros, in
+ which case an fatal alert is generated.
+ - The servername field is maintained together with the session cache.
+ - When a session is resumed, the servername call back invoked in order
+ to allow the application to position itself to the right context.
+ - The servername is acknowledged if it is new for a session or when
+ it is identical to a previously used for the same session.
+ Applications can control the behaviour. They can at any time
+ set a 'desirable' servername for a new SSL object. This can be the
+ case for example with HTTPS when a Host: header field is received and
+ a renegotiation is requested. In this case, a possible servername
+ presented in the new client hello is only acknowledged if it matches
+ the value of the Host: field.
+ - Applications must use SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
+ if they provide for changing an explicit servername context for the
+ session,
+ i.e. when the session has been established with a servername extension.
+ - On session reconnect, the servername extension may be absent. */
+
+ if (type == TLSEXT_TYPE_server_name) {
+ CBS server_name_list;
+ char have_seen_host_name = 0;
+
+ if (!CBS_get_u16_length_prefixed(&extension, &server_name_list) ||
+ CBS_len(&server_name_list) < 1 || CBS_len(&extension) != 0) {
+ *out_alert = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ /* Decode each ServerName in the extension. */
+ while (CBS_len(&server_name_list) > 0) {
+ uint8_t name_type;
+ CBS host_name;
+
+ /* Decode the NameType. */
+ if (!CBS_get_u8(&server_name_list, &name_type)) {
+ *out_alert = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ /* Only host_name is supported. */
+ if (name_type != TLSEXT_NAMETYPE_host_name) {
+ continue;
+ }
+
+ if (have_seen_host_name) {
+ /* The ServerNameList MUST NOT contain more than one name of the same
+ * name_type. */
+ *out_alert = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ have_seen_host_name = 1;
+
+ if (!CBS_get_u16_length_prefixed(&server_name_list, &host_name) ||
+ CBS_len(&host_name) < 1) {
+ *out_alert = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ if (CBS_len(&host_name) > TLSEXT_MAXLEN_host_name ||
+ CBS_contains_zero_byte(&host_name)) {
+ *out_alert = SSL_AD_UNRECOGNIZED_NAME;
+ return 0;
+ }
+
+ if (!s->hit) {
+ assert(s->session->tlsext_hostname == NULL);
+ if (s->session->tlsext_hostname) {
+ /* This should be impossible. */
+ *out_alert = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ /* Copy the hostname as a string. */
+ if (!CBS_strdup(&host_name, &s->session->tlsext_hostname)) {
+ *out_alert = SSL_AD_INTERNAL_ERROR;
+ return 0;
+ }
+
+ s->should_ack_sni = 1;
+ }
+ }
+ } else if (type == TLSEXT_TYPE_ec_point_formats) {
+ CBS ec_point_format_list;
+
+ if (!CBS_get_u8_length_prefixed(&extension, &ec_point_format_list) ||
+ CBS_len(&extension) != 0) {
+ *out_alert = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ if (!CBS_stow(&ec_point_format_list, &s->s3->tmp.peer_ecpointformatlist,
+ &s->s3->tmp.peer_ecpointformatlist_length)) {
+ *out_alert = SSL_AD_INTERNAL_ERROR;
+ return 0;
+ }
+ } else if (type == TLSEXT_TYPE_elliptic_curves) {
+ CBS elliptic_curve_list;
+ size_t i, num_curves;
+
+ if (!CBS_get_u16_length_prefixed(&extension, &elliptic_curve_list) ||
+ CBS_len(&elliptic_curve_list) == 0 ||
+ (CBS_len(&elliptic_curve_list) & 1) != 0 ||
+ CBS_len(&extension) != 0) {
+ *out_alert = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ if (s->s3->tmp.peer_ellipticcurvelist) {
+ OPENSSL_free(s->s3->tmp.peer_ellipticcurvelist);
+ s->s3->tmp.peer_ellipticcurvelist_length = 0;
+ }
+
+ s->s3->tmp.peer_ellipticcurvelist =
+ (uint16_t *)OPENSSL_malloc(CBS_len(&elliptic_curve_list));
+
+ if (s->s3->tmp.peer_ellipticcurvelist == NULL) {
+ *out_alert = SSL_AD_INTERNAL_ERROR;
+ return 0;
+ }
+
+ num_curves = CBS_len(&elliptic_curve_list) / 2;
+ for (i = 0; i < num_curves; i++) {
+ if (!CBS_get_u16(&elliptic_curve_list,
+ &s->s3->tmp.peer_ellipticcurvelist[i])) {
+ *out_alert = SSL_AD_INTERNAL_ERROR;
+ return 0;
+ }
+ }
+
+ if (CBS_len(&elliptic_curve_list) != 0) {
+ *out_alert = SSL_AD_INTERNAL_ERROR;
+ return 0;
+ }
+
+ s->s3->tmp.peer_ellipticcurvelist_length = num_curves;
+ } else if (type == TLSEXT_TYPE_renegotiate) {
+ if (!ssl_parse_clienthello_renegotiate_ext(s, &extension, out_alert)) {
+ return 0;
+ }
+ renegotiate_seen = 1;
+ } else if (type == TLSEXT_TYPE_signature_algorithms) {
+ CBS supported_signature_algorithms;
+
+ if (!CBS_get_u16_length_prefixed(&extension,
+ &supported_signature_algorithms) ||
+ CBS_len(&extension) != 0) {
+ *out_alert = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ /* Ensure the signature algorithms are non-empty. It contains a list of
+ * SignatureAndHashAlgorithms which are two bytes each. */
+ if (CBS_len(&supported_signature_algorithms) == 0 ||
+ (CBS_len(&supported_signature_algorithms) % 2) != 0) {
+ *out_alert = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ if (!tls1_process_sigalgs(s, &supported_signature_algorithms)) {
+ *out_alert = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+ /* If sigalgs received and no shared algorithms fatal error. */
+ if (s->cert->peer_sigalgs && !s->cert->shared_sigalgs) {
+ OPENSSL_PUT_ERROR(SSL, ssl_add_serverhello_tlsext,
+ SSL_R_NO_SHARED_SIGATURE_ALGORITHMS);
+ *out_alert = SSL_AD_ILLEGAL_PARAMETER;
+ return 0;
+ }
+ } else if (type == TLSEXT_TYPE_next_proto_neg &&
+ s->s3->tmp.finish_md_len == 0 && s->s3->alpn_selected == NULL &&
+ !SSL_IS_DTLS(s)) {
+ /* The extension must be empty. */
+ if (CBS_len(&extension) != 0) {
+ *out_alert = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ /* We shouldn't accept this extension on a renegotiation.
+ *
+ * s->new_session will be set on renegotiation, but we probably shouldn't
+ * rely that it couldn't be set on the initial renegotation too in
+ * certain cases (when there's some other reason to disallow resuming an
+ * earlier session -- the current code won't be doing anything like that,
+ * but this might change).
+
+ * A valid sign that there's been a previous handshake in this connection
+ * is if s->s3->tmp.finish_md_len > 0. (We are talking about a check
+ * that will happen in the Hello protocol round, well before a new
+ * Finished message could have been computed.) */
+ s->s3->next_proto_neg_seen = 1;
+ } else if (type == TLSEXT_TYPE_application_layer_protocol_negotiation &&
+ s->ctx->alpn_select_cb && s->s3->tmp.finish_md_len == 0) {
+ if (!tls1_alpn_handle_client_hello(s, &extension, out_alert)) {
+ return 0;
+ }
+ /* ALPN takes precedence over NPN. */
+ s->s3->next_proto_neg_seen = 0;
+ } else if (type == TLSEXT_TYPE_channel_id && s->tlsext_channel_id_enabled &&
+ !SSL_IS_DTLS(s)) {
+ /* The extension must be empty. */
+ if (CBS_len(&extension) != 0) {
+ *out_alert = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ s->s3->tlsext_channel_id_valid = 1;
+ } else if (type == TLSEXT_TYPE_channel_id_new &&
+ s->tlsext_channel_id_enabled && !SSL_IS_DTLS(s)) {
+ /* The extension must be empty. */
+ if (CBS_len(&extension) != 0) {
+ *out_alert = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ s->s3->tlsext_channel_id_valid = 1;
+ s->s3->tlsext_channel_id_new = 1;
+ } else if (type == TLSEXT_TYPE_use_srtp) {
+ if (!ssl_parse_clienthello_use_srtp_ext(s, &extension, out_alert)) {
+ return 0;
+ }
+ } else if (type == TLSEXT_TYPE_extended_master_secret &&
+ s->version != SSL3_VERSION) {
+ if (CBS_len(&extension) != 0) {
+ *out_alert = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ s->s3->tmp.extended_master_secret = 1;
+ }
+ }
+
+ri_check:
+ /* Need RI if renegotiating */
+
+ if (!renegotiate_seen && s->renegotiate &&
+ !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)) {
+ *out_alert = SSL_AD_HANDSHAKE_FAILURE;
+ OPENSSL_PUT_ERROR(SSL, ssl_scan_clienthello_tlsext,
+ SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
+ return 0;
+ }
+
+ return 1;
+}
+
+int ssl_parse_clienthello_tlsext(SSL *s, CBS *cbs) {
+ int alert = -1;
+ if (ssl_scan_clienthello_tlsext(s, cbs, &alert) <= 0) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, alert);
+ return 0;
+ }
+
+ if (ssl_check_clienthello_tlsext(s) <= 0) {
+ OPENSSL_PUT_ERROR(SSL, ssl_parse_clienthello_tlsext,
+ SSL_R_CLIENTHELLO_TLSEXT);
+ return 0;
+ }
+
+ return 1;
+}
+
+/* ssl_next_proto_validate validates a Next Protocol Negotiation block. No
+ * elements of zero length are allowed and the set of elements must exactly
+ * fill the length of the block. */
+static char ssl_next_proto_validate(const CBS *cbs) {
+ CBS copy = *cbs;
+
+ while (CBS_len(&copy) != 0) {
+ CBS proto;
+ if (!CBS_get_u8_length_prefixed(&copy, &proto) || CBS_len(&proto) == 0) {
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static int ssl_scan_serverhello_tlsext(SSL *s, CBS *cbs, int *out_alert) {
+ int tlsext_servername = 0;
+ int renegotiate_seen = 0;
+ CBS extensions;
+
+ /* TODO(davidben): Move all of these to some per-handshake state that gets
+ * systematically reset on a new handshake; perhaps allocate it fresh each
+ * time so it's not even kept around post-handshake. */
+ s->s3->next_proto_neg_seen = 0;
+ s->tlsext_ticket_expected = 0;
+ s->s3->tmp.certificate_status_expected = 0;
+ s->s3->tmp.extended_master_secret = 0;
+ s->srtp_profile = NULL;
+
+ if (s->s3->alpn_selected) {
+ OPENSSL_free(s->s3->alpn_selected);
+ s->s3->alpn_selected = NULL;
+ }
+
+ /* Clear ECC extensions */
+ if (s->s3->tmp.peer_ecpointformatlist != 0) {
+ OPENSSL_free(s->s3->tmp.peer_ecpointformatlist);
+ s->s3->tmp.peer_ecpointformatlist = NULL;
+ s->s3->tmp.peer_ecpointformatlist_length = 0;
+ }
+
+ /* There may be no extensions. */
+ if (CBS_len(cbs) == 0) {
+ goto ri_check;
+ }
+
+ /* Decode the extensions block and check it is valid. */
+ if (!CBS_get_u16_length_prefixed(cbs, &extensions) ||
+ !tls1_check_duplicate_extensions(&extensions)) {
+ *out_alert = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ while (CBS_len(&extensions) != 0) {
+ uint16_t type;
+ CBS extension;
+
+ /* Decode the next extension. */
+ if (!CBS_get_u16(&extensions, &type) ||
+ !CBS_get_u16_length_prefixed(&extensions, &extension)) {
+ *out_alert = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ if (s->tlsext_debug_cb) {
+ s->tlsext_debug_cb(s, 1, type, (uint8_t *)CBS_data(&extension),
+ CBS_len(&extension), s->tlsext_debug_arg);
+ }
+
+ if (type == TLSEXT_TYPE_server_name) {
+ /* The extension must be empty. */
+ if (CBS_len(&extension) != 0) {
+ *out_alert = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ /* We must have sent it in ClientHello. */
+ if (s->tlsext_hostname == NULL) {
+ *out_alert = SSL_AD_UNSUPPORTED_EXTENSION;
+ return 0;
+ }
+
+ tlsext_servername = 1;
+ } else if (type == TLSEXT_TYPE_ec_point_formats) {
+ CBS ec_point_format_list;
+
+ if (!CBS_get_u8_length_prefixed(&extension, &ec_point_format_list) ||
+ CBS_len(&extension) != 0) {
+ *out_alert = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ if (!CBS_stow(&ec_point_format_list, &s->s3->tmp.peer_ecpointformatlist,
+ &s->s3->tmp.peer_ecpointformatlist_length)) {
+ *out_alert = SSL_AD_INTERNAL_ERROR;
+ return 0;
+ }
+ } else if (type == TLSEXT_TYPE_session_ticket) {
+ if ((SSL_get_options(s) & SSL_OP_NO_TICKET) || CBS_len(&extension) > 0) {
+ *out_alert = SSL_AD_UNSUPPORTED_EXTENSION;
+ return 0;
+ }
+
+ s->tlsext_ticket_expected = 1;
+ } else if (type == TLSEXT_TYPE_status_request) {
+ /* The extension MUST be empty and may only sent if we've requested a
+ * status request message. */
+ if (CBS_len(&extension) != 0) {
+ *out_alert = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ if (!s->ocsp_stapling_enabled) {
+ *out_alert = SSL_AD_UNSUPPORTED_EXTENSION;
+ return 0;
+ }
+
+ /* Set a flag to expect a CertificateStatus message */
+ s->s3->tmp.certificate_status_expected = 1;
+ } else if (type == TLSEXT_TYPE_next_proto_neg &&
+ s->s3->tmp.finish_md_len == 0 &&
+ !SSL_IS_DTLS(s)) {
+ uint8_t *selected;
+ uint8_t selected_len;
+
+ /* We must have requested it. */
+ if (s->ctx->next_proto_select_cb == NULL) {
+ *out_alert = SSL_AD_UNSUPPORTED_EXTENSION;
+ return 0;
+ }
+
+ /* The data must be valid. */
+ if (!ssl_next_proto_validate(&extension)) {
+ *out_alert = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ if (s->ctx->next_proto_select_cb(
+ s, &selected, &selected_len, CBS_data(&extension),
+ CBS_len(&extension),
+ s->ctx->next_proto_select_cb_arg) != SSL_TLSEXT_ERR_OK) {
+ *out_alert = SSL_AD_INTERNAL_ERROR;
+ return 0;
+ }
+
+ s->next_proto_negotiated = BUF_memdup(selected, selected_len);
+ if (s->next_proto_negotiated == NULL) {
+ *out_alert = SSL_AD_INTERNAL_ERROR;
+ return 0;
+ }
+
+ s->next_proto_negotiated_len = selected_len;
+ s->s3->next_proto_neg_seen = 1;
+ } else if (type == TLSEXT_TYPE_application_layer_protocol_negotiation) {
+ CBS protocol_name_list, protocol_name;
+
+ /* We must have requested it. */
+ if (s->alpn_client_proto_list == NULL) {
+ *out_alert = SSL_AD_UNSUPPORTED_EXTENSION;
+ return 0;
+ }
+
+ /* The extension data consists of a ProtocolNameList which must have
+ * exactly one ProtocolName. Each of these is length-prefixed. */
+ if (!CBS_get_u16_length_prefixed(&extension, &protocol_name_list) ||
+ CBS_len(&extension) != 0 ||
+ !CBS_get_u8_length_prefixed(&protocol_name_list, &protocol_name) ||
+ CBS_len(&protocol_name_list) != 0) {
+ *out_alert = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ if (!CBS_stow(&protocol_name, &s->s3->alpn_selected,
+ &s->s3->alpn_selected_len)) {
+ *out_alert = SSL_AD_INTERNAL_ERROR;
+ return 0;
+ }
+ } else if (type == TLSEXT_TYPE_channel_id && !SSL_IS_DTLS(s)) {
+ if (CBS_len(&extension) != 0) {
+ *out_alert = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ s->s3->tlsext_channel_id_valid = 1;
+ } else if (type == TLSEXT_TYPE_channel_id_new && !SSL_IS_DTLS(s)) {
+ if (CBS_len(&extension) != 0) {
+ *out_alert = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ s->s3->tlsext_channel_id_valid = 1;
+ s->s3->tlsext_channel_id_new = 1;
+ } else if (type == TLSEXT_TYPE_certificate_timestamp) {
+ if (CBS_len(&extension) == 0) {
+ *out_alert = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ /* Session resumption uses the original session information. */
+ if (!s->hit &&
+ !CBS_stow(&extension, &s->session->tlsext_signed_cert_timestamp_list,
+ &s->session->tlsext_signed_cert_timestamp_list_length)) {
+ *out_alert = SSL_AD_INTERNAL_ERROR;
+ return 0;
+ }
+ } else if (type == TLSEXT_TYPE_renegotiate) {
+ if (!ssl_parse_serverhello_renegotiate_ext(s, &extension, out_alert)) {
+ return 0;
+ }
+
+ renegotiate_seen = 1;
+ } else if (type == TLSEXT_TYPE_use_srtp) {
+ if (!ssl_parse_serverhello_use_srtp_ext(s, &extension, out_alert)) {
+ return 0;
+ }
+ } else if (type == TLSEXT_TYPE_extended_master_secret) {
+ if (/* It is invalid for the server to select EMS and
+ SSLv3. */
+ s->version == SSL3_VERSION || CBS_len(&extension) != 0) {
+ *out_alert = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ s->s3->tmp.extended_master_secret = 1;
+ }
+ }
+
+ if (!s->hit && tlsext_servername == 1 && s->tlsext_hostname) {
+ if (s->session->tlsext_hostname == NULL) {
+ s->session->tlsext_hostname = BUF_strdup(s->tlsext_hostname);
+ if (!s->session->tlsext_hostname) {
+ *out_alert = SSL_AD_UNRECOGNIZED_NAME;
+ return 0;
+ }
+ } else {
+ *out_alert = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+ }
+
+ri_check:
+ /* 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 (!renegotiate_seen && !(s->options & SSL_OP_LEGACY_SERVER_CONNECT) &&
+ !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)) {
+ *out_alert = SSL_AD_HANDSHAKE_FAILURE;
+ OPENSSL_PUT_ERROR(SSL, ssl_scan_serverhello_tlsext,
+ SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
+ return 0;
+ }
+
+ return 1;
+}
+
+int ssl_prepare_clienthello_tlsext(SSL *s) { return 1; }
+
+int ssl_prepare_serverhello_tlsext(SSL *s) { return 1; }
+
+static int ssl_check_clienthello_tlsext(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. */
+
+ 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:
+ s->should_ack_sni = 0;
+ return 1;
+
+ default:
+ return 1;
+ }
+}
+
+static int ssl_check_serverhello_tlsext(SSL *s) {
+ int ret = SSL_TLSEXT_ERR_NOACK;
+ int al = SSL_AD_UNRECOGNIZED_NAME;
+
+ /* If we are client and using an elliptic curve cryptography cipher suite,
+ * then if server returns an EC point formats lists extension it must contain
+ * uncompressed. */
+ unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
+ unsigned long alg_a = s->s3->tmp.new_cipher->algorithm_auth;
+ if (((alg_k & SSL_kEECDH) || (alg_a & SSL_aECDSA)) &&
+ !tls1_check_point_format(s, TLSEXT_ECPOINTFORMAT_uncompressed)) {
+ OPENSSL_PUT_ERROR(SSL, ssl_check_serverhello_tlsext,
+ SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST);
+ return -1;
+ }
+ 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);
+ }
+
+ 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_parse_serverhello_tlsext(SSL *s, CBS *cbs) {
+ int alert = -1;
+ if (s->version < SSL3_VERSION) {
+ return 1;
+ }
+
+ if (ssl_scan_serverhello_tlsext(s, cbs, &alert) <= 0) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, alert);
+ return 0;
+ }
+
+ if (ssl_check_serverhello_tlsext(s) <= 0) {
+ OPENSSL_PUT_ERROR(SSL, ssl_parse_serverhello_tlsext,
+ SSL_R_SERVERHELLO_TLSEXT);
+ return 0;
+ }
+
+ 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.
+ *
+ * ctx: contains the early callback context, which is the result of a
+ * shallow parse of the ClientHello.
+ * ret: (output) on return, if a ticket was decrypted, then this is set to
+ * point to the resulting session.
+ *
+ * Returns:
+ * -1: fatal error, either from parsing or decrypting the ticket.
+ * 0: no ticket was found (or was ignored, based on settings).
+ * 1: a zero length extension was found, indicating that the client supports
+ * session tickets but doesn't currently have one to offer.
+ * 2: a ticket was offered but couldn't be decrypted because of a non-fatal
+ * error.
+ * 3: 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
+ * 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, const struct ssl_early_callback_ctx *ctx,
+ SSL_SESSION **ret) {
+ *ret = NULL;
+ s->tlsext_ticket_expected = 0;
+ const uint8_t *data;
+ size_t len;
+ int r;
+
+ /* If tickets disabled behave as if no ticket present to permit stateful
+ * resumption. */
+ if ((SSL_get_options(s) & SSL_OP_NO_TICKET) ||
+ (s->version <= SSL3_VERSION && !ctx->extensions) ||
+ !SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_session_ticket,
+ &data, &len)) {
+ return 0;
+ }
+
+ if (len == 0) {
+ /* The client will accept a ticket but doesn't currently have one. */
+ s->tlsext_ticket_expected = 1;
+ return 1;
+ }
+
+ r = tls_decrypt_ticket(s, data, len, ctx->session_id, ctx->session_id_len,
+ ret);
+ switch (r) {
+ case 2: /* ticket couldn't be decrypted */
+ s->tlsext_ticket_expected = 1;
+ return 2;
+
+ case 3: /* ticket was decrypted */
+ return r;
+
+ case 4: /* ticket decrypted but need to renew */
+ s->tlsext_ticket_expected = 1;
+ return 3;
+
+ default: /* fatal error */
+ return -1;
+ }
+}
+
+/* tls_decrypt_ticket attempts to decrypt a session ticket.
+ *
+ * etick: points to the body of the session ticket extension.
+ * eticklen: the length of the session tickets extenion.
+ * sess_id: points at the session ID.
+ * sesslen: the length of the session ID.
+ * psess: (output) on return, if a ticket was decrypted, then this is set to
+ * point to the resulting session.
+ *
+ * Returns:
+ * -1: fatal error, either from parsing or decrypting the ticket.
+ * 2: the ticket couldn't be decrypted.
+ * 3: a ticket was successfully decrypted and *psess was set.
+ * 4: same as 3, but the ticket needs to be renewed. */
+static int tls_decrypt_ticket(SSL *s, const uint8_t *etick, int eticklen,
+ const uint8_t *sess_id, int sesslen,
+ SSL_SESSION **psess) {
+ SSL_SESSION *sess;
+ uint8_t *sdec;
+ const uint8_t *p;
+ int slen, mlen, renew_ticket = 0;
+ uint8_t tick_hmac[EVP_MAX_MD_SIZE];
+ HMAC_CTX hctx;
+ EVP_CIPHER_CTX ctx;
+ SSL_CTX *tctx = s->initial_ctx;
+
+ /* Need at least keyname + iv + some encrypted data */
+ if (eticklen < 48) {
+ return 2;
+ }
+
+ /* Initialize session ticket encryption and HMAC contexts */
+ HMAC_CTX_init(&hctx);
+ EVP_CIPHER_CTX_init(&ctx);
+ if (tctx->tlsext_ticket_key_cb) {
+ uint8_t *nctick = (uint8_t *)etick;
+ int rv = tctx->tlsext_ticket_key_cb(s, nctick, nctick + 16, &ctx, &hctx, 0);
+ if (rv < 0) {
+ return -1;
+ }
+ if (rv == 0) {
+ return 2;
+ }
+ if (rv == 2) {
+ renew_ticket = 1;
+ }
+ } else {
+ /* Check key name matches */
+ if (memcmp(etick, tctx->tlsext_tick_key_name, 16)) {
+ return 2;
+ }
+ if (!HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16, tlsext_tick_md(),
+ NULL) ||
+ !EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL,
+ tctx->tlsext_tick_aes_key, etick + 16)) {
+ HMAC_CTX_cleanup(&hctx);
+ EVP_CIPHER_CTX_cleanup(&ctx);
+ return -1;
+ }
+ }
+
+ /* Attempt to process session ticket, first conduct sanity and integrity
+ * checks on ticket. */
+ mlen = HMAC_size(&hctx);
+ if (mlen < 0) {
+ HMAC_CTX_cleanup(&hctx);
+ EVP_CIPHER_CTX_cleanup(&ctx);
+ return -1;
+ }
+ eticklen -= mlen;
+ /* Check HMAC of encrypted ticket */
+ HMAC_Update(&hctx, etick, eticklen);
+ HMAC_Final(&hctx, tick_hmac, NULL);
+ HMAC_CTX_cleanup(&hctx);
+ if (CRYPTO_memcmp(tick_hmac, etick + eticklen, mlen)) {
+ EVP_CIPHER_CTX_cleanup(&ctx);
+ return 2;
+ }
+
+ /* Attempt to decrypt session data */
+ /* Move p after IV to start of encrypted ticket, update length */
+ p = etick + 16 + EVP_CIPHER_CTX_iv_length(&ctx);
+ eticklen -= 16 + EVP_CIPHER_CTX_iv_length(&ctx);
+ sdec = OPENSSL_malloc(eticklen);
+ if (!sdec) {
+ EVP_CIPHER_CTX_cleanup(&ctx);
+ return -1;
+ }
+ EVP_DecryptUpdate(&ctx, sdec, &slen, p, eticklen);
+ if (EVP_DecryptFinal_ex(&ctx, sdec + slen, &mlen) <= 0) {
+ EVP_CIPHER_CTX_cleanup(&ctx);
+ OPENSSL_free(sdec);
+ return 2;
+ }
+ slen += mlen;
+ EVP_CIPHER_CTX_cleanup(&ctx);
+ p = sdec;
+
+ sess = d2i_SSL_SESSION(NULL, &p, slen);
+ OPENSSL_free(sdec);
+ if (sess) {
+ /* The session ID, if non-empty, is used by some clients to detect that the
+ * ticket has been accepted. So we copy it to the session structure. If it
+ * is empty set length to zero as required by standard. */
+ if (sesslen) {
+ memcpy(sess->session_id, sess_id, sesslen);
+ }
+ sess->session_id_length = sesslen;
+ *psess = sess;
+ if (renew_ticket) {
+ return 4;
+ }
+ return 3;
+ }
+
+ ERR_clear_error();
+ /* For session parse failure, indicate that we need to send a new ticket. */
+ return 2;
+}
+
+/* Tables to translate from NIDs to TLS v1.2 ids */
+typedef struct {
+ int nid;
+ int id;
+} tls12_lookup;
+
+static const tls12_lookup tls12_md[] = {{NID_md5, TLSEXT_hash_md5},
+ {NID_sha1, TLSEXT_hash_sha1},
+ {NID_sha224, TLSEXT_hash_sha224},
+ {NID_sha256, TLSEXT_hash_sha256},
+ {NID_sha384, TLSEXT_hash_sha384},
+ {NID_sha512, TLSEXT_hash_sha512}};
+
+static const tls12_lookup tls12_sig[] = {{EVP_PKEY_RSA, TLSEXT_signature_rsa},
+ {EVP_PKEY_EC, TLSEXT_signature_ecdsa}};
+
+static int tls12_find_id(int nid, const tls12_lookup *table, size_t tlen) {
+ size_t i;
+ for (i = 0; i < tlen; i++) {
+ if (table[i].nid == nid) {
+ return table[i].id;
+ }
+ }
+
+ return -1;
+}
+
+static int tls12_find_nid(int id, const tls12_lookup *table, size_t tlen) {
+ size_t i;
+ for (i = 0; i < tlen; i++) {
+ if (table[i].id == id) {
+ return table[i].nid;
+ }
+ }
+
+ return NID_undef;
+}
+
+int tls12_get_sigandhash(uint8_t *p, const EVP_PKEY *pk, const EVP_MD *md) {
+ int sig_id, md_id;
+
+ if (!md) {
+ return 0;
+ }
+
+ md_id = tls12_find_id(EVP_MD_type(md), tls12_md,
+ sizeof(tls12_md) / sizeof(tls12_lookup));
+ if (md_id == -1) {
+ return 0;
+ }
+
+ sig_id = tls12_get_sigid(pk);
+ if (sig_id == -1) {
+ return 0;
+ }
+
+ p[0] = (uint8_t)md_id;
+ p[1] = (uint8_t)sig_id;
+ return 1;
+}
+
+int tls12_get_sigid(const EVP_PKEY *pk) {
+ return tls12_find_id(pk->type, tls12_sig,
+ sizeof(tls12_sig) / sizeof(tls12_lookup));
+}
+
+const EVP_MD *tls12_get_hash(uint8_t hash_alg) {
+ switch (hash_alg) {
+ case TLSEXT_hash_md5:
+ return EVP_md5();
+
+ case TLSEXT_hash_sha1:
+ return EVP_sha1();
+
+ case TLSEXT_hash_sha224:
+ return EVP_sha224();
+
+ case TLSEXT_hash_sha256:
+ return EVP_sha256();
+
+ case TLSEXT_hash_sha384:
+ return EVP_sha384();
+
+ case TLSEXT_hash_sha512:
+ return EVP_sha512();
+
+ default:
+ return NULL;
+ }
+}
+
+/* tls12_get_pkey_type returns the EVP_PKEY type corresponding to TLS signature
+ * algorithm |sig_alg|. It returns -1 if the type is unknown. */
+static int tls12_get_pkey_type(uint8_t sig_alg) {
+ switch (sig_alg) {
+ case TLSEXT_signature_rsa:
+ return EVP_PKEY_RSA;
+
+ case TLSEXT_signature_ecdsa:
+ return EVP_PKEY_EC;
+
+ default:
+ return -1;
+ }
+}
+
+/* Convert TLS 1.2 signature algorithm extension values into NIDs */
+static void tls1_lookup_sigalg(int *phash_nid, int *psign_nid,
+ int *psignhash_nid, const uint8_t *data) {
+ int sign_nid = 0, hash_nid = 0;
+ if (!phash_nid && !psign_nid && !psignhash_nid) {
+ return;
+ }
+
+ if (phash_nid || psignhash_nid) {
+ hash_nid = tls12_find_nid(data[0], tls12_md,
+ sizeof(tls12_md) / sizeof(tls12_lookup));
+ if (phash_nid) {
+ *phash_nid = hash_nid;
+ }
+ }
+
+ if (psign_nid || psignhash_nid) {
+ sign_nid = tls12_find_nid(data[1], tls12_sig,
+ sizeof(tls12_sig) / sizeof(tls12_lookup));
+ if (psign_nid) {
+ *psign_nid = sign_nid;
+ }
+ }
+
+ if (psignhash_nid) {
+ if (sign_nid && hash_nid) {
+ OBJ_find_sigid_by_algs(psignhash_nid, hash_nid, sign_nid);
+ } else {
+ *psignhash_nid = NID_undef;
+ }
+ }
+}
+
+/* Given preference and allowed sigalgs set shared sigalgs */
+static int tls12_do_shared_sigalgs(TLS_SIGALGS *shsig, const uint8_t *pref,
+ size_t preflen, const uint8_t *allow,
+ size_t allowlen) {
+ const uint8_t *ptmp, *atmp;
+ size_t i, j, nmatch = 0;
+
+ for (i = 0, ptmp = pref; i < preflen; i += 2, ptmp += 2) {
+ /* Skip disabled hashes or signature algorithms */
+ if (tls12_get_hash(ptmp[0]) == NULL ||
+ tls12_get_pkey_type(ptmp[1]) == -1) {
+ continue;
+ }
+
+ for (j = 0, atmp = allow; j < allowlen; j += 2, atmp += 2) {
+ if (ptmp[0] == atmp[0] && ptmp[1] == atmp[1]) {
+ nmatch++;
+ if (shsig) {
+ shsig->rhash = ptmp[0];
+ shsig->rsign = ptmp[1];
+ tls1_lookup_sigalg(&shsig->hash_nid, &shsig->sign_nid,
+ &shsig->signandhash_nid, ptmp);
+ shsig++;
+ }
+
+ break;
+ }
+ }
+ }
+
+ return nmatch;
+}
+
+/* Set shared signature algorithms for SSL structures */
+static int tls1_set_shared_sigalgs(SSL *s) {
+ const uint8_t *pref, *allow, *conf;
+ size_t preflen, allowlen, conflen;
+ size_t nmatch;
+ TLS_SIGALGS *salgs = NULL;
+ CERT *c = s->cert;
+
+ if (c->shared_sigalgs) {
+ OPENSSL_free(c->shared_sigalgs);
+ c->shared_sigalgs = NULL;
+ }
+
+ /* If client use client signature algorithms if not NULL */
+ if (!s->server && c->client_sigalgs) {
+ conf = c->client_sigalgs;
+ conflen = c->client_sigalgslen;
+ } else if (c->conf_sigalgs) {
+ conf = c->conf_sigalgs;
+ conflen = c->conf_sigalgslen;
+ } else {
+ conflen = tls12_get_psigalgs(s, &conf);
+ }
+
+ if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE) {
+ pref = conf;
+ preflen = conflen;
+ allow = c->peer_sigalgs;
+ allowlen = c->peer_sigalgslen;
+ } else {
+ allow = conf;
+ allowlen = conflen;
+ pref = c->peer_sigalgs;
+ preflen = c->peer_sigalgslen;
+ }
+
+ nmatch = tls12_do_shared_sigalgs(NULL, pref, preflen, allow, allowlen);
+ if (!nmatch) {
+ return 1;
+ }
+
+ salgs = OPENSSL_malloc(nmatch * sizeof(TLS_SIGALGS));
+ if (!salgs) {
+ return 0;
+ }
+
+ nmatch = tls12_do_shared_sigalgs(salgs, pref, preflen, allow, allowlen);
+ c->shared_sigalgs = salgs;
+ c->shared_sigalgslen = nmatch;
+ return 1;
+}
+
+/* Set preferred digest for each key type */
+int tls1_process_sigalgs(SSL *s, const CBS *sigalgs) {
+ CERT *c = s->cert;
+
+ /* Extension ignored for inappropriate versions */
+ if (!SSL_USE_SIGALGS(s)) {
+ return 1;
+ }
+
+ /* Length must be even */
+ if (CBS_len(sigalgs) % 2 != 0) {
+ return 0;
+ }
+
+ /* Should never happen */
+ if (!c) {
+ return 0;
+ }
+
+ if (!CBS_stow(sigalgs, &c->peer_sigalgs, &c->peer_sigalgslen)) {
+ return 0;
+ }
+
+ tls1_set_shared_sigalgs(s);
+ return 1;
+}
+
+const EVP_MD *tls1_choose_signing_digest(SSL *s, EVP_PKEY *pkey) {
+ CERT *c = s->cert;
+ int type = EVP_PKEY_id(pkey);
+ size_t i;
+
+ /* Select the first shared digest supported by our key. */
+ for (i = 0; i < c->shared_sigalgslen; i++) {
+ const EVP_MD *md = tls12_get_hash(c->shared_sigalgs[i].rhash);
+ if (md == NULL ||
+ tls12_get_pkey_type(c->shared_sigalgs[i].rsign) != type ||
+ !EVP_PKEY_supports_digest(pkey, md)) {
+ continue;
+ }
+ return md;
+ }
+
+ /* If no suitable digest may be found, default to SHA-1. */
+ return EVP_sha1();
+}
+
+int SSL_get_sigalgs(SSL *s, int idx, int *psign, int *phash, int *psignhash,
+ uint8_t *rsig, uint8_t *rhash) {
+ const uint8_t *psig = s->cert->peer_sigalgs;
+
+ if (psig == NULL) {
+ return 0;
+ }
+
+ if (idx >= 0) {
+ idx <<= 1;
+ if (idx >= (int)s->cert->peer_sigalgslen) {
+ return 0;
+ }
+ psig += idx;
+ if (rhash) {
+ *rhash = psig[0];
+ }
+ if (rsig) {
+ *rsig = psig[1];
+ }
+ tls1_lookup_sigalg(phash, psign, psignhash, psig);
+ }
+
+ return s->cert->peer_sigalgslen / 2;
+}
+
+int SSL_get_shared_sigalgs(SSL *s, int idx, int *psign, int *phash,
+ int *psignhash, uint8_t *rsig, uint8_t *rhash) {
+ TLS_SIGALGS *shsigalgs = s->cert->shared_sigalgs;
+
+ if (!shsigalgs || idx >= (int)s->cert->shared_sigalgslen) {
+ return 0;
+ }
+
+ shsigalgs += idx;
+ if (phash) {
+ *phash = shsigalgs->hash_nid;
+ }
+ if (psign) {
+ *psign = shsigalgs->sign_nid;
+ }
+ if (psignhash) {
+ *psignhash = shsigalgs->signandhash_nid;
+ }
+ if (rsig) {
+ *rsig = shsigalgs->rsign;
+ }
+ if (rhash) {
+ *rhash = shsigalgs->rhash;
+ }
+
+ return s->cert->shared_sigalgslen;
+}
+
+/* tls1_channel_id_hash calculates the signed data for a Channel ID on the
+ * given SSL connection and writes it to |md|. */
+int tls1_channel_id_hash(EVP_MD_CTX *md, SSL *s) {
+ EVP_MD_CTX ctx;
+ uint8_t temp_digest[EVP_MAX_MD_SIZE];
+ unsigned temp_digest_len;
+ int i;
+ static const char kClientIDMagic[] = "TLS Channel ID signature";
+
+ if (s->s3->handshake_buffer &&
+ !ssl3_digest_cached_records(s, free_handshake_buffer)) {
+ return 0;
+ }
+
+ EVP_DigestUpdate(md, kClientIDMagic, sizeof(kClientIDMagic));
+
+ if (s->hit && s->s3->tlsext_channel_id_new) {
+ static const char kResumptionMagic[] = "Resumption";
+ EVP_DigestUpdate(md, kResumptionMagic, sizeof(kResumptionMagic));
+ if (s->session->original_handshake_hash_len == 0) {
+ return 0;
+ }
+ EVP_DigestUpdate(md, s->session->original_handshake_hash,
+ s->session->original_handshake_hash_len);
+ }
+
+ EVP_MD_CTX_init(&ctx);
+ for (i = 0; i < SSL_MAX_DIGEST; i++) {
+ if (s->s3->handshake_dgst[i] == NULL) {
+ continue;
+ }
+ EVP_MD_CTX_copy_ex(&ctx, s->s3->handshake_dgst[i]);
+ EVP_DigestFinal_ex(&ctx, temp_digest, &temp_digest_len);
+ EVP_DigestUpdate(md, temp_digest, temp_digest_len);
+ }
+ EVP_MD_CTX_cleanup(&ctx);
+
+ return 1;
+}
+
+/* tls1_record_handshake_hashes_for_channel_id records the current handshake
+ * hashes in |s->session| so that Channel ID resumptions can sign that data. */
+int tls1_record_handshake_hashes_for_channel_id(SSL *s) {
+ int digest_len;
+ /* This function should never be called for a resumed session because the
+ * handshake hashes that we wish to record are for the original, full
+ * handshake. */
+ if (s->hit) {
+ return -1;
+ }
+
+ /* It only makes sense to call this function if Channel IDs have been
+ * negotiated. */
+ if (!s->s3->tlsext_channel_id_new) {
+ return -1;
+ }
+
+ digest_len =
+ tls1_handshake_digest(s, s->session->original_handshake_hash,
+ sizeof(s->session->original_handshake_hash));
+ if (digest_len < 0) {
+ return -1;
+ }
+
+ s->session->original_handshake_hash_len = digest_len;
+
+ return 1;
+}
+
+int tls1_set_sigalgs(CERT *c, const int *psig_nids, size_t salglen,
+ int client) {
+ uint8_t *sigalgs, *sptr;
+ int rhash, rsign;
+ size_t i;
+
+ if (salglen & 1) {
+ return 0;
+ }
+
+ sigalgs = OPENSSL_malloc(salglen);
+ if (sigalgs == NULL) {
+ return 0;
+ }
+
+ for (i = 0, sptr = sigalgs; i < salglen; i += 2) {
+ rhash = tls12_find_id(*psig_nids++, tls12_md,
+ sizeof(tls12_md) / sizeof(tls12_lookup));
+ rsign = tls12_find_id(*psig_nids++, tls12_sig,
+ sizeof(tls12_sig) / sizeof(tls12_lookup));
+
+ if (rhash == -1 || rsign == -1) {
+ goto err;
+ }
+ *sptr++ = rhash;
+ *sptr++ = rsign;
+ }
+
+ if (client) {
+ if (c->client_sigalgs) {
+ OPENSSL_free(c->client_sigalgs);
+ }
+ c->client_sigalgs = sigalgs;
+ c->client_sigalgslen = salglen;
+ } else {
+ if (c->conf_sigalgs) {
+ OPENSSL_free(c->conf_sigalgs);
+ }
+ c->conf_sigalgs = sigalgs;
+ c->conf_sigalgslen = salglen;
+ }
+
+ return 1;
+
+err:
+ OPENSSL_free(sigalgs);
+ return 0;
+}
diff --git a/src/ssl/t1_reneg.c b/src/ssl/t1_reneg.c
new file mode 100644
index 0000000..2d9fbc0
--- /dev/null
+++ b/src/ssl/t1_reneg.c
@@ -0,0 +1,247 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of 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-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
+ * 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 <stdio.h>
+#include <assert.h>
+
+#include <openssl/bytestring.h>
+#include <openssl/obj.h>
+#include <openssl/err.h>
+
+#include "ssl_locl.h"
+
+
+/* Add the client's renegotiation binding */
+int ssl_add_clienthello_renegotiate_ext(SSL *s, unsigned char *p, int *len,
+ int maxlen) {
+ if (p) {
+ if (s->s3->previous_client_finished_len + 1 > maxlen) {
+ OPENSSL_PUT_ERROR(SSL, ssl_add_clienthello_renegotiate_ext,
+ SSL_R_RENEGOTIATE_EXT_TOO_LONG);
+ return 0;
+ }
+
+ /* Length byte */
+ *p = s->s3->previous_client_finished_len;
+ p++;
+
+ memcpy(p, s->s3->previous_client_finished,
+ s->s3->previous_client_finished_len);
+ }
+
+ *len = s->s3->previous_client_finished_len + 1;
+
+ return 1;
+}
+
+/* Parse the client's renegotiation binding and abort if it's not right */
+int ssl_parse_clienthello_renegotiate_ext(SSL *s, CBS *cbs, int *out_alert) {
+ CBS renegotiated_connection;
+
+ if (!CBS_get_u8_length_prefixed(cbs, &renegotiated_connection) ||
+ CBS_len(cbs) != 0) {
+ OPENSSL_PUT_ERROR(SSL, ssl_parse_clienthello_renegotiate_ext,
+ SSL_R_RENEGOTIATION_ENCODING_ERR);
+ *out_alert = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ /* Check that the extension matches */
+ if (!CBS_mem_equal(&renegotiated_connection, s->s3->previous_client_finished,
+ s->s3->previous_client_finished_len)) {
+ OPENSSL_PUT_ERROR(SSL, ssl_parse_clienthello_renegotiate_ext,
+ SSL_R_RENEGOTIATION_MISMATCH);
+ *out_alert = SSL_AD_HANDSHAKE_FAILURE;
+ return 0;
+ }
+
+ s->s3->send_connection_binding = 1;
+
+ return 1;
+}
+
+/* Add the server's renegotiation binding */
+int ssl_add_serverhello_renegotiate_ext(SSL *s, unsigned char *p, int *len,
+ int maxlen) {
+ if (p) {
+ if (s->s3->previous_client_finished_len +
+ s->s3->previous_server_finished_len + 1 >
+ maxlen) {
+ OPENSSL_PUT_ERROR(SSL, ssl_add_serverhello_renegotiate_ext,
+ SSL_R_RENEGOTIATE_EXT_TOO_LONG);
+ return 0;
+ }
+
+ /* Length byte */
+ *p = s->s3->previous_client_finished_len +
+ s->s3->previous_server_finished_len;
+ p++;
+
+ memcpy(p, s->s3->previous_client_finished,
+ s->s3->previous_client_finished_len);
+ p += s->s3->previous_client_finished_len;
+
+ memcpy(p, s->s3->previous_server_finished,
+ s->s3->previous_server_finished_len);
+ }
+
+ *len = s->s3->previous_client_finished_len +
+ s->s3->previous_server_finished_len + 1;
+
+ return 1;
+}
+
+/* Parse the server's renegotiation binding and abort if it's not right */
+int ssl_parse_serverhello_renegotiate_ext(SSL *s, CBS *cbs, int *out_alert) {
+ int expected_len =
+ s->s3->previous_client_finished_len + s->s3->previous_server_finished_len;
+ CBS renegotiated_connection;
+ const uint8_t *d;
+
+ /* Check for logic errors */
+ assert(!expected_len || s->s3->previous_client_finished_len);
+ assert(!expected_len || s->s3->previous_server_finished_len);
+
+ /* Parse out the extension contents. */
+ if (!CBS_get_u8_length_prefixed(cbs, &renegotiated_connection) ||
+ CBS_len(cbs) != 0) {
+ OPENSSL_PUT_ERROR(SSL, ssl_parse_serverhello_renegotiate_ext,
+ SSL_R_RENEGOTIATION_ENCODING_ERR);
+ *out_alert = SSL_AD_ILLEGAL_PARAMETER;
+ return 0;
+ }
+
+ /* Check that the extension matches. */
+ if (CBS_len(&renegotiated_connection) != expected_len) {
+ OPENSSL_PUT_ERROR(SSL, ssl_parse_serverhello_renegotiate_ext,
+ SSL_R_RENEGOTIATION_MISMATCH);
+ *out_alert = SSL_AD_HANDSHAKE_FAILURE;
+ return 0;
+ }
+
+ d = CBS_data(&renegotiated_connection);
+ if (memcmp(d, s->s3->previous_client_finished,
+ s->s3->previous_client_finished_len)) {
+ OPENSSL_PUT_ERROR(SSL, ssl_parse_serverhello_renegotiate_ext,
+ SSL_R_RENEGOTIATION_MISMATCH);
+ *out_alert = SSL_AD_HANDSHAKE_FAILURE;
+ return 0;
+ }
+ d += s->s3->previous_client_finished_len;
+
+ if (memcmp(d, s->s3->previous_server_finished,
+ s->s3->previous_server_finished_len)) {
+ OPENSSL_PUT_ERROR(SSL, ssl_parse_serverhello_renegotiate_ext,
+ SSL_R_RENEGOTIATION_MISMATCH);
+ *out_alert = SSL_AD_ILLEGAL_PARAMETER;
+ return 0;
+ }
+ s->s3->send_connection_binding = 1;
+
+ return 1;
+}
diff --git a/src/ssl/test/CMakeLists.txt b/src/ssl/test/CMakeLists.txt
new file mode 100644
index 0000000..9992360
--- /dev/null
+++ b/src/ssl/test/CMakeLists.txt
@@ -0,0 +1,16 @@
+include_directories(../../include)
+
+add_executable(
+ bssl_shim
+
+ async_bio.cc
+ bssl_shim.cc
+ malloc.cc
+ packeted_bio.cc
+ test_config.cc
+)
+
+target_link_libraries(bssl_shim ssl crypto)
+if (NOT APPLE AND NOT WIN32)
+ target_link_libraries(bssl_shim dl)
+endif()
diff --git a/src/ssl/test/async_bio.cc b/src/ssl/test/async_bio.cc
new file mode 100644
index 0000000..c007ffa
--- /dev/null
+++ b/src/ssl/test/async_bio.cc
@@ -0,0 +1,180 @@
+/* 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 "async_bio.h"
+
+#include <errno.h>
+#include <string.h>
+
+#include <openssl/mem.h>
+
+
+namespace {
+
+extern const BIO_METHOD async_bio_method;
+
+struct async_bio {
+ bool datagram;
+ size_t read_quota;
+ size_t write_quota;
+};
+
+async_bio *get_data(BIO *bio) {
+ if (bio->method != &async_bio_method) {
+ return NULL;
+ }
+ return (async_bio *)bio->ptr;
+}
+
+static int async_write(BIO *bio, const char *in, int inl) {
+ async_bio *a = get_data(bio);
+ if (a == NULL || bio->next_bio == NULL) {
+ return 0;
+ }
+
+ if (a->datagram) {
+ // Perform writes synchronously; the DTLS implementation drops any packets
+ // that failed to send.
+ return BIO_write(bio->next_bio, in, inl);
+ }
+
+ BIO_clear_retry_flags(bio);
+
+ if (a->write_quota == 0) {
+ BIO_set_retry_write(bio);
+ errno = EAGAIN;
+ return -1;
+ }
+
+ if (!a->datagram && (size_t)inl > a->write_quota) {
+ inl = a->write_quota;
+ }
+ int ret = BIO_write(bio->next_bio, in, inl);
+ if (ret <= 0) {
+ BIO_copy_next_retry(bio);
+ } else {
+ a->write_quota -= (a->datagram ? 1 : ret);
+ }
+ return ret;
+}
+
+static int async_read(BIO *bio, char *out, int outl) {
+ async_bio *a = get_data(bio);
+ if (a == NULL || bio->next_bio == NULL) {
+ return 0;
+ }
+
+ BIO_clear_retry_flags(bio);
+
+ if (a->read_quota == 0) {
+ BIO_set_retry_read(bio);
+ errno = EAGAIN;
+ return -1;
+ }
+
+ if (!a->datagram && (size_t)outl > a->read_quota) {
+ outl = a->read_quota;
+ }
+ int ret = BIO_read(bio->next_bio, out, outl);
+ if (ret <= 0) {
+ BIO_copy_next_retry(bio);
+ } else {
+ a->read_quota -= (a->datagram ? 1 : ret);
+ }
+ return ret;
+}
+
+static long async_ctrl(BIO *bio, int cmd, long num, void *ptr) {
+ if (bio->next_bio == NULL) {
+ return 0;
+ }
+ BIO_clear_retry_flags(bio);
+ int ret = BIO_ctrl(bio->next_bio, cmd, num, ptr);
+ BIO_copy_next_retry(bio);
+ return ret;
+}
+
+static int async_new(BIO *bio) {
+ async_bio *a = (async_bio *)OPENSSL_malloc(sizeof(*a));
+ if (a == NULL) {
+ return 0;
+ }
+ memset(a, 0, sizeof(*a));
+ bio->init = 1;
+ bio->ptr = (char *)a;
+ return 1;
+}
+
+static int async_free(BIO *bio) {
+ if (bio == NULL) {
+ return 0;
+ }
+
+ OPENSSL_free(bio->ptr);
+ bio->ptr = NULL;
+ bio->init = 0;
+ bio->flags = 0;
+ return 1;
+}
+
+static long async_callback_ctrl(BIO *bio, int cmd, bio_info_cb fp) {
+ if (bio->next_bio == NULL) {
+ return 0;
+ }
+ return BIO_callback_ctrl(bio->next_bio, cmd, fp);
+}
+
+const BIO_METHOD async_bio_method = {
+ BIO_TYPE_FILTER,
+ "async bio",
+ async_write,
+ async_read,
+ NULL /* puts */,
+ NULL /* gets */,
+ async_ctrl,
+ async_new,
+ async_free,
+ async_callback_ctrl,
+};
+
+} // namespace
+
+BIO *async_bio_create() {
+ return BIO_new(&async_bio_method);
+}
+
+BIO *async_bio_create_datagram() {
+ BIO *ret = BIO_new(&async_bio_method);
+ if (!ret) {
+ return NULL;
+ }
+ get_data(ret)->datagram = true;
+ return ret;
+}
+
+void async_bio_allow_read(BIO *bio, size_t count) {
+ async_bio *a = get_data(bio);
+ if (a == NULL) {
+ return;
+ }
+ a->read_quota += count;
+}
+
+void async_bio_allow_write(BIO *bio, size_t count) {
+ async_bio *a = get_data(bio);
+ if (a == NULL) {
+ return;
+ }
+ a->write_quota += count;
+}
diff --git a/src/ssl/test/async_bio.h b/src/ssl/test/async_bio.h
new file mode 100644
index 0000000..2904036
--- /dev/null
+++ b/src/ssl/test/async_bio.h
@@ -0,0 +1,40 @@
+/* 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 HEADER_ASYNC_BIO
+#define HEADER_ASYNC_BIO
+
+#include <openssl/bio.h>
+
+
+// async_bio_create creates a filter BIO for testing asynchronous state
+// machines which consume a stream socket. Reads and writes will fail
+// and return EAGAIN unless explicitly allowed. Each async BIO has a
+// read quota and a write quota. Initially both are zero. As each is
+// incremented, bytes are allowed to flow through the BIO.
+BIO *async_bio_create();
+
+// async_bio_create_datagram creates a filter BIO for testing for
+// asynchronous state machines which consume datagram sockets. The read
+// and write quota count in packets rather than bytes.
+BIO *async_bio_create_datagram();
+
+// async_bio_allow_read increments |bio|'s read quota by |count|.
+void async_bio_allow_read(BIO *bio, size_t count);
+
+// async_bio_allow_write increments |bio|'s write quota by |count|.
+void async_bio_allow_write(BIO *bio, size_t count);
+
+
+#endif // HEADER_ASYNC_BIO
diff --git a/src/ssl/test/bssl_shim.cc b/src/ssl/test/bssl_shim.cc
new file mode 100644
index 0000000..37891b9
--- /dev/null
+++ b/src/ssl/test/bssl_shim.cc
@@ -0,0 +1,758 @@
+/* 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 <openssl/base.h>
+
+#if !defined(OPENSSL_WINDOWS)
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <signal.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#endif
+
+#include <string.h>
+#include <sys/types.h>
+
+#include <openssl/bio.h>
+#include <openssl/buf.h>
+#include <openssl/bytestring.h>
+#include <openssl/ssl.h>
+
+#include "async_bio.h"
+#include "packeted_bio.h"
+#include "test_config.h"
+
+static int usage(const char *program) {
+ fprintf(stderr, "Usage: %s [flags...]\n",
+ program);
+ return 1;
+}
+
+static int g_ex_data_index = 0;
+
+static bool SetConfigPtr(SSL *ssl, const TestConfig *config) {
+ return SSL_set_ex_data(ssl, g_ex_data_index, (void *)config) == 1;
+}
+
+static const TestConfig *GetConfigPtr(SSL *ssl) {
+ return (const TestConfig *)SSL_get_ex_data(ssl, g_ex_data_index);
+}
+
+static EVP_PKEY *LoadPrivateKey(const std::string &file) {
+ BIO *bio = BIO_new(BIO_s_file());
+ if (bio == NULL) {
+ return NULL;
+ }
+ if (!BIO_read_filename(bio, file.c_str())) {
+ BIO_free(bio);
+ return NULL;
+ }
+ EVP_PKEY *pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
+ BIO_free(bio);
+ return pkey;
+}
+
+static int early_callback_called = 0;
+
+static int select_certificate_callback(const struct ssl_early_callback_ctx *ctx) {
+ early_callback_called = 1;
+
+ const TestConfig *config = GetConfigPtr(ctx->ssl);
+
+ if (config->expected_server_name.empty()) {
+ return 1;
+ }
+
+ const uint8_t *extension_data;
+ size_t extension_len;
+ CBS extension, server_name_list, host_name;
+ uint8_t name_type;
+
+ if (!SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name,
+ &extension_data,
+ &extension_len)) {
+ fprintf(stderr, "Could not find server_name extension.\n");
+ return -1;
+ }
+
+ CBS_init(&extension, extension_data, extension_len);
+ if (!CBS_get_u16_length_prefixed(&extension, &server_name_list) ||
+ CBS_len(&extension) != 0 ||
+ !CBS_get_u8(&server_name_list, &name_type) ||
+ name_type != TLSEXT_NAMETYPE_host_name ||
+ !CBS_get_u16_length_prefixed(&server_name_list, &host_name) ||
+ CBS_len(&server_name_list) != 0) {
+ fprintf(stderr, "Could not decode server_name extension.\n");
+ return -1;
+ }
+
+ if (!CBS_mem_equal(&host_name,
+ (const uint8_t*)config->expected_server_name.data(),
+ config->expected_server_name.size())) {
+ fprintf(stderr, "Server name mismatch.\n");
+ }
+
+ return 1;
+}
+
+static int skip_verify(int preverify_ok, X509_STORE_CTX *store_ctx) {
+ return 1;
+}
+
+static int next_protos_advertised_callback(SSL *ssl,
+ const uint8_t **out,
+ unsigned int *out_len,
+ void *arg) {
+ const TestConfig *config = GetConfigPtr(ssl);
+ if (config->advertise_npn.empty())
+ return SSL_TLSEXT_ERR_NOACK;
+
+ *out = (const uint8_t*)config->advertise_npn.data();
+ *out_len = config->advertise_npn.size();
+ return SSL_TLSEXT_ERR_OK;
+}
+
+static int next_proto_select_callback(SSL* ssl,
+ uint8_t** out,
+ uint8_t* outlen,
+ const uint8_t* in,
+ unsigned inlen,
+ void* arg) {
+ const TestConfig *config = GetConfigPtr(ssl);
+ if (config->select_next_proto.empty())
+ return SSL_TLSEXT_ERR_NOACK;
+
+ *out = (uint8_t*)config->select_next_proto.data();
+ *outlen = config->select_next_proto.size();
+ return SSL_TLSEXT_ERR_OK;
+}
+
+static int alpn_select_callback(SSL* ssl,
+ const uint8_t** out,
+ uint8_t* outlen,
+ const uint8_t* in,
+ unsigned inlen,
+ void* arg) {
+ const TestConfig *config = GetConfigPtr(ssl);
+ if (config->select_alpn.empty())
+ return SSL_TLSEXT_ERR_NOACK;
+
+ if (!config->expected_advertised_alpn.empty() &&
+ (config->expected_advertised_alpn.size() != inlen ||
+ memcmp(config->expected_advertised_alpn.data(),
+ in, inlen) != 0)) {
+ fprintf(stderr, "bad ALPN select callback inputs\n");
+ exit(1);
+ }
+
+ *out = (const uint8_t*)config->select_alpn.data();
+ *outlen = config->select_alpn.size();
+ return SSL_TLSEXT_ERR_OK;
+}
+
+static int cookie_generate_callback(SSL *ssl, uint8_t *cookie, size_t *cookie_len) {
+ if (*cookie_len < 32) {
+ fprintf(stderr, "Insufficient space for cookie\n");
+ return 0;
+ }
+ *cookie_len = 32;
+ memset(cookie, 42, *cookie_len);
+ return 1;
+}
+
+static int cookie_verify_callback(SSL *ssl, const uint8_t *cookie, size_t cookie_len) {
+ if (cookie_len != 32) {
+ fprintf(stderr, "Cookie length mismatch.\n");
+ return 0;
+ }
+ for (size_t i = 0; i < cookie_len; i++) {
+ if (cookie[i] != 42) {
+ fprintf(stderr, "Cookie mismatch.\n");
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static unsigned psk_client_callback(SSL *ssl, const char *hint,
+ char *out_identity,
+ unsigned max_identity_len,
+ uint8_t *out_psk, unsigned max_psk_len) {
+ const TestConfig *config = GetConfigPtr(ssl);
+
+ if (strcmp(hint ? hint : "", config->psk_identity.c_str()) != 0) {
+ fprintf(stderr, "Server PSK hint did not match.\n");
+ return 0;
+ }
+
+ // Account for the trailing '\0' for the identity.
+ if (config->psk_identity.size() >= max_identity_len ||
+ config->psk.size() > max_psk_len) {
+ fprintf(stderr, "PSK buffers too small\n");
+ return 0;
+ }
+
+ BUF_strlcpy(out_identity, config->psk_identity.c_str(),
+ max_identity_len);
+ memcpy(out_psk, config->psk.data(), config->psk.size());
+ return config->psk.size();
+}
+
+static unsigned psk_server_callback(SSL *ssl, const char *identity,
+ uint8_t *out_psk, unsigned max_psk_len) {
+ const TestConfig *config = GetConfigPtr(ssl);
+
+ if (strcmp(identity, config->psk_identity.c_str()) != 0) {
+ fprintf(stderr, "Client PSK identity did not match.\n");
+ return 0;
+ }
+
+ if (config->psk.size() > max_psk_len) {
+ fprintf(stderr, "PSK buffers too small\n");
+ return 0;
+ }
+
+ memcpy(out_psk, config->psk.data(), config->psk.size());
+ return config->psk.size();
+}
+
+static SSL_CTX *setup_ctx(const TestConfig *config) {
+ SSL_CTX *ssl_ctx = NULL;
+ DH *dh = NULL;
+
+ ssl_ctx = SSL_CTX_new(config->is_dtls ? DTLS_method() : TLS_method());
+ if (ssl_ctx == NULL) {
+ goto err;
+ }
+
+ if (config->is_dtls) {
+ // DTLS needs read-ahead to function on a datagram BIO.
+ //
+ // TODO(davidben): this should not be necessary. DTLS code should only
+ // expect a datagram BIO.
+ SSL_CTX_set_read_ahead(ssl_ctx, 1);
+ }
+
+ if (!SSL_CTX_set_ecdh_auto(ssl_ctx, 1)) {
+ goto err;
+ }
+
+ if (!SSL_CTX_set_cipher_list(ssl_ctx, "ALL")) {
+ goto err;
+ }
+
+ dh = DH_get_2048_256(NULL);
+ if (dh == NULL ||
+ !SSL_CTX_set_tmp_dh(ssl_ctx, dh)) {
+ goto err;
+ }
+
+ SSL_CTX_set_session_cache_mode(ssl_ctx, SSL_SESS_CACHE_BOTH);
+
+ ssl_ctx->select_certificate_cb = select_certificate_callback;
+
+ SSL_CTX_set_next_protos_advertised_cb(
+ ssl_ctx, next_protos_advertised_callback, NULL);
+ if (!config->select_next_proto.empty()) {
+ SSL_CTX_set_next_proto_select_cb(ssl_ctx, next_proto_select_callback, NULL);
+ }
+
+ if (!config->select_alpn.empty()) {
+ SSL_CTX_set_alpn_select_cb(ssl_ctx, alpn_select_callback, NULL);
+ }
+
+ SSL_CTX_set_cookie_generate_cb(ssl_ctx, cookie_generate_callback);
+ SSL_CTX_set_cookie_verify_cb(ssl_ctx, cookie_verify_callback);
+
+ ssl_ctx->tlsext_channel_id_enabled_new = 1;
+
+ DH_free(dh);
+ return ssl_ctx;
+
+ err:
+ if (dh != NULL) {
+ DH_free(dh);
+ }
+ if (ssl_ctx != NULL) {
+ SSL_CTX_free(ssl_ctx);
+ }
+ return NULL;
+}
+
+static int retry_async(SSL *ssl, int ret, BIO *bio) {
+ // No error; don't retry.
+ if (ret >= 0) {
+ return 0;
+ }
+ // See if we needed to read or write more. If so, allow one byte through on
+ // the appropriate end to maximally stress the state machine.
+ int err = SSL_get_error(ssl, ret);
+ if (err == SSL_ERROR_WANT_READ) {
+ async_bio_allow_read(bio, 1);
+ return 1;
+ } else if (err == SSL_ERROR_WANT_WRITE) {
+ async_bio_allow_write(bio, 1);
+ return 1;
+ }
+ return 0;
+}
+
+static int do_exchange(SSL_SESSION **out_session,
+ SSL_CTX *ssl_ctx,
+ const TestConfig *config,
+ bool is_resume,
+ int fd,
+ SSL_SESSION *session) {
+ early_callback_called = 0;
+
+ SSL *ssl = SSL_new(ssl_ctx);
+ if (ssl == NULL) {
+ BIO_print_errors_fp(stdout);
+ return 1;
+ }
+
+ if (!SetConfigPtr(ssl, config)) {
+ BIO_print_errors_fp(stdout);
+ return 1;
+ }
+
+ if (config->fallback_scsv) {
+ if (!SSL_enable_fallback_scsv(ssl)) {
+ BIO_print_errors_fp(stdout);
+ return 1;
+ }
+ }
+ if (!config->key_file.empty()) {
+ if (!SSL_use_PrivateKey_file(ssl, config->key_file.c_str(),
+ SSL_FILETYPE_PEM)) {
+ BIO_print_errors_fp(stdout);
+ return 1;
+ }
+ }
+ if (!config->cert_file.empty()) {
+ if (!SSL_use_certificate_file(ssl, config->cert_file.c_str(),
+ SSL_FILETYPE_PEM)) {
+ BIO_print_errors_fp(stdout);
+ return 1;
+ }
+ }
+ if (config->require_any_client_certificate) {
+ SSL_set_verify(ssl, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
+ skip_verify);
+ }
+ if (config->false_start) {
+ SSL_set_mode(ssl, SSL_MODE_HANDSHAKE_CUTTHROUGH);
+ }
+ if (config->cbc_record_splitting) {
+ SSL_set_mode(ssl, SSL_MODE_CBC_RECORD_SPLITTING);
+ }
+ if (config->partial_write) {
+ SSL_set_mode(ssl, SSL_MODE_ENABLE_PARTIAL_WRITE);
+ }
+ if (config->no_tls12) {
+ SSL_set_options(ssl, SSL_OP_NO_TLSv1_2);
+ }
+ if (config->no_tls11) {
+ SSL_set_options(ssl, SSL_OP_NO_TLSv1_1);
+ }
+ if (config->no_tls1) {
+ SSL_set_options(ssl, SSL_OP_NO_TLSv1);
+ }
+ if (config->no_ssl3) {
+ SSL_set_options(ssl, SSL_OP_NO_SSLv3);
+ }
+ if (config->cookie_exchange) {
+ SSL_set_options(ssl, SSL_OP_COOKIE_EXCHANGE);
+ }
+ if (config->tls_d5_bug) {
+ SSL_set_options(ssl, SSL_OP_TLS_D5_BUG);
+ }
+ if (config->allow_unsafe_legacy_renegotiation) {
+ SSL_set_options(ssl, SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION);
+ }
+ if (!config->expected_channel_id.empty()) {
+ SSL_enable_tls_channel_id(ssl);
+ }
+ if (!config->send_channel_id.empty()) {
+ EVP_PKEY *pkey = LoadPrivateKey(config->send_channel_id);
+ if (pkey == NULL) {
+ BIO_print_errors_fp(stdout);
+ return 1;
+ }
+ SSL_enable_tls_channel_id(ssl);
+ if (!SSL_set1_tls_channel_id(ssl, pkey)) {
+ EVP_PKEY_free(pkey);
+ BIO_print_errors_fp(stdout);
+ return 1;
+ }
+ EVP_PKEY_free(pkey);
+ }
+ if (!config->host_name.empty()) {
+ SSL_set_tlsext_host_name(ssl, config->host_name.c_str());
+ }
+ if (!config->advertise_alpn.empty()) {
+ SSL_set_alpn_protos(ssl, (const uint8_t *)config->advertise_alpn.data(),
+ config->advertise_alpn.size());
+ }
+ if (!config->psk.empty()) {
+ SSL_set_psk_client_callback(ssl, psk_client_callback);
+ SSL_set_psk_server_callback(ssl, psk_server_callback);
+ }
+ if (!config->psk_identity.empty() &&
+ !SSL_use_psk_identity_hint(ssl, config->psk_identity.c_str())) {
+ BIO_print_errors_fp(stdout);
+ return 1;
+ }
+ if (!config->srtp_profiles.empty() &&
+ !SSL_set_srtp_profiles(ssl, config->srtp_profiles.c_str())) {
+ BIO_print_errors_fp(stdout);
+ return 1;
+ }
+ if (config->enable_ocsp_stapling &&
+ !SSL_enable_ocsp_stapling(ssl)) {
+ BIO_print_errors_fp(stdout);
+ return 1;
+ }
+ if (config->enable_signed_cert_timestamps &&
+ !SSL_enable_signed_cert_timestamps(ssl)) {
+ BIO_print_errors_fp(stdout);
+ return 1;
+ }
+ SSL_enable_fastradio_padding(ssl, config->fastradio_padding);
+ if (config->min_version != 0) {
+ SSL_set_min_version(ssl, (uint16_t)config->min_version);
+ }
+ if (config->max_version != 0) {
+ SSL_set_max_version(ssl, (uint16_t)config->max_version);
+ }
+ if (config->mtu != 0) {
+ SSL_set_options(ssl, SSL_OP_NO_QUERY_MTU);
+ SSL_set_mtu(ssl, config->mtu);
+ }
+
+ BIO *bio = BIO_new_fd(fd, 1 /* take ownership */);
+ if (bio == NULL) {
+ BIO_print_errors_fp(stdout);
+ return 1;
+ }
+ if (config->is_dtls) {
+ BIO *packeted = packeted_bio_create();
+ BIO_push(packeted, bio);
+ bio = packeted;
+ }
+ if (config->async) {
+ BIO *async =
+ config->is_dtls ? async_bio_create_datagram() : async_bio_create();
+ BIO_push(async, bio);
+ bio = async;
+ }
+ SSL_set_bio(ssl, bio, bio);
+
+ if (session != NULL) {
+ if (SSL_set_session(ssl, session) != 1) {
+ fprintf(stderr, "failed to set session\n");
+ return 2;
+ }
+ }
+
+ int ret;
+ do {
+ if (config->is_server) {
+ ret = SSL_accept(ssl);
+ } else {
+ ret = SSL_connect(ssl);
+ }
+ } while (config->async && retry_async(ssl, ret, bio));
+ if (ret != 1) {
+ SSL_free(ssl);
+ BIO_print_errors_fp(stdout);
+ return 2;
+ }
+
+ if (is_resume && (!!SSL_session_reused(ssl) == config->expect_session_miss)) {
+ fprintf(stderr, "session was%s reused\n",
+ SSL_session_reused(ssl) ? "" : " not");
+ return 2;
+ }
+
+ if (!config->expected_server_name.empty()) {
+ const char *server_name =
+ SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
+ if (server_name != config->expected_server_name) {
+ fprintf(stderr, "servername mismatch (got %s; want %s)\n",
+ server_name, config->expected_server_name.c_str());
+ return 2;
+ }
+
+ if (!early_callback_called) {
+ fprintf(stderr, "early callback not called\n");
+ return 2;
+ }
+ }
+
+ if (!config->expected_certificate_types.empty()) {
+ uint8_t *certificate_types;
+ int num_certificate_types =
+ SSL_get0_certificate_types(ssl, &certificate_types);
+ if (num_certificate_types !=
+ (int)config->expected_certificate_types.size() ||
+ memcmp(certificate_types,
+ config->expected_certificate_types.data(),
+ num_certificate_types) != 0) {
+ fprintf(stderr, "certificate types mismatch\n");
+ return 2;
+ }
+ }
+
+ if (!config->expected_next_proto.empty()) {
+ const uint8_t *next_proto;
+ unsigned next_proto_len;
+ SSL_get0_next_proto_negotiated(ssl, &next_proto, &next_proto_len);
+ if (next_proto_len != config->expected_next_proto.size() ||
+ memcmp(next_proto, config->expected_next_proto.data(),
+ next_proto_len) != 0) {
+ fprintf(stderr, "negotiated next proto mismatch\n");
+ return 2;
+ }
+ }
+
+ if (!config->expected_alpn.empty()) {
+ const uint8_t *alpn_proto;
+ unsigned alpn_proto_len;
+ SSL_get0_alpn_selected(ssl, &alpn_proto, &alpn_proto_len);
+ if (alpn_proto_len != config->expected_alpn.size() ||
+ memcmp(alpn_proto, config->expected_alpn.data(),
+ alpn_proto_len) != 0) {
+ fprintf(stderr, "negotiated alpn proto mismatch\n");
+ return 2;
+ }
+ }
+
+ if (!config->expected_channel_id.empty()) {
+ uint8_t channel_id[64];
+ if (!SSL_get_tls_channel_id(ssl, channel_id, sizeof(channel_id))) {
+ fprintf(stderr, "no channel id negotiated\n");
+ return 2;
+ }
+ if (config->expected_channel_id.size() != 64 ||
+ memcmp(config->expected_channel_id.data(),
+ channel_id, 64) != 0) {
+ fprintf(stderr, "channel id mismatch\n");
+ return 2;
+ }
+ }
+
+ if (config->expect_extended_master_secret) {
+ if (!ssl->session->extended_master_secret) {
+ fprintf(stderr, "No EMS for session when expected");
+ return 2;
+ }
+ }
+
+ if (!config->expected_ocsp_response.empty()) {
+ const uint8_t *data;
+ size_t len;
+ SSL_get0_ocsp_response(ssl, &data, &len);
+ if (config->expected_ocsp_response.size() != len ||
+ memcmp(config->expected_ocsp_response.data(), data, len) != 0) {
+ fprintf(stderr, "OCSP response mismatch\n");
+ return 2;
+ }
+ }
+
+ if (!config->expected_signed_cert_timestamps.empty()) {
+ const uint8_t *data;
+ size_t len;
+ SSL_get0_signed_cert_timestamp_list(ssl, &data, &len);
+ if (config->expected_signed_cert_timestamps.size() != len ||
+ memcmp(config->expected_signed_cert_timestamps.data(),
+ data, len) != 0) {
+ fprintf(stderr, "SCT list mismatch\n");
+ return 2;
+ }
+ }
+
+ if (config->renegotiate) {
+ if (config->async) {
+ fprintf(stderr, "--renegotiate is not supported with --async.\n");
+ return 2;
+ }
+
+ SSL_renegotiate(ssl);
+
+ ret = SSL_do_handshake(ssl);
+ if (ret != 1) {
+ SSL_free(ssl);
+ BIO_print_errors_fp(stdout);
+ return 2;
+ }
+
+ SSL_set_state(ssl, SSL_ST_ACCEPT);
+ ret = SSL_do_handshake(ssl);
+ if (ret != 1) {
+ SSL_free(ssl);
+ BIO_print_errors_fp(stdout);
+ return 2;
+ }
+ }
+
+ if (config->write_different_record_sizes) {
+ if (config->is_dtls) {
+ fprintf(stderr, "write_different_record_sizes not supported for DTLS\n");
+ return 6;
+ }
+ // This mode writes a number of different record sizes in an attempt to
+ // trip up the CBC record splitting code.
+ uint8_t buf[32769];
+ memset(buf, 0x42, sizeof(buf));
+ static const size_t kRecordSizes[] = {
+ 0, 1, 255, 256, 257, 16383, 16384, 16385, 32767, 32768, 32769};
+ for (size_t i = 0; i < sizeof(kRecordSizes) / sizeof(kRecordSizes[0]);
+ i++) {
+ int w;
+ const size_t len = kRecordSizes[i];
+ size_t off = 0;
+
+ if (len > sizeof(buf)) {
+ fprintf(stderr, "Bad kRecordSizes value.\n");
+ return 5;
+ }
+
+ do {
+ w = SSL_write(ssl, buf + off, len - off);
+ if (w > 0) {
+ off += (size_t) w;
+ }
+ } while ((config->async && retry_async(ssl, w, bio)) ||
+ (w > 0 && off < len));
+
+ if (w < 0 || off != len) {
+ SSL_free(ssl);
+ BIO_print_errors_fp(stdout);
+ return 4;
+ }
+ }
+ } else {
+ if (config->shim_writes_first) {
+ int w;
+ do {
+ w = SSL_write(ssl, "hello", 5);
+ } while (config->async && retry_async(ssl, w, bio));
+ }
+ for (;;) {
+ uint8_t buf[512];
+ int n;
+ do {
+ n = SSL_read(ssl, buf, sizeof(buf));
+ } while (config->async && retry_async(ssl, n, bio));
+ int err = SSL_get_error(ssl, n);
+ if (err == SSL_ERROR_ZERO_RETURN ||
+ (n == 0 && err == SSL_ERROR_SYSCALL)) {
+ if (n != 0) {
+ fprintf(stderr, "Invalid SSL_get_error output\n");
+ return 3;
+ }
+ /* Accept shutdowns with or without close_notify.
+ * TODO(davidben): Write tests which distinguish these two cases. */
+ break;
+ } else if (err != SSL_ERROR_NONE) {
+ if (n > 0) {
+ fprintf(stderr, "Invalid SSL_get_error output\n");
+ return 3;
+ }
+ SSL_free(ssl);
+ BIO_print_errors_fp(stdout);
+ return 3;
+ }
+ /* Successfully read data. */
+ if (n <= 0) {
+ fprintf(stderr, "Invalid SSL_get_error output\n");
+ return 3;
+ }
+ for (int i = 0; i < n; i++) {
+ buf[i] ^= 0xff;
+ }
+ int w;
+ do {
+ w = SSL_write(ssl, buf, n);
+ } while (config->async && retry_async(ssl, w, bio));
+ if (w != n) {
+ SSL_free(ssl);
+ BIO_print_errors_fp(stdout);
+ return 4;
+ }
+ }
+ }
+
+ if (out_session) {
+ *out_session = SSL_get1_session(ssl);
+ }
+
+ SSL_shutdown(ssl);
+ SSL_free(ssl);
+ return 0;
+}
+
+int main(int argc, char **argv) {
+#if !defined(OPENSSL_WINDOWS)
+ signal(SIGPIPE, SIG_IGN);
+#endif
+
+ if (!SSL_library_init()) {
+ return 1;
+ }
+ g_ex_data_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
+ if (g_ex_data_index < 0) {
+ return 1;
+ }
+
+ TestConfig config;
+ if (!ParseConfig(argc - 1, argv + 1, &config)) {
+ return usage(argv[0]);
+ }
+
+ SSL_CTX *ssl_ctx = setup_ctx(&config);
+ if (ssl_ctx == NULL) {
+ BIO_print_errors_fp(stdout);
+ return 1;
+ }
+
+ SSL_SESSION *session = NULL;
+ int ret = do_exchange(&session,
+ ssl_ctx, &config,
+ false /* is_resume */,
+ 3 /* fd */, NULL /* session */);
+ if (ret != 0) {
+ goto out;
+ }
+
+ if (config.resume) {
+ ret = do_exchange(NULL,
+ ssl_ctx, &config,
+ true /* is_resume */,
+ 4 /* fd */,
+ config.is_server ? NULL : session);
+ if (ret != 0) {
+ goto out;
+ }
+ }
+
+ ret = 0;
+
+out:
+ SSL_SESSION_free(session);
+ SSL_CTX_free(ssl_ctx);
+ return ret;
+}
diff --git a/src/ssl/test/malloc.cc b/src/ssl/test/malloc.cc
new file mode 100644
index 0000000..6cc0b33
--- /dev/null
+++ b/src/ssl/test/malloc.cc
@@ -0,0 +1,130 @@
+/* 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 <openssl/base.h>
+
+// This file isn't built on ARM or Aarch64 because we link statically in those
+// builds and trying to override malloc in a static link doesn't work.
+#if defined(__linux__) && !defined(OPENSSL_ARM) && !defined(OPENSSL_AARCH64)
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#include <new>
+
+
+/* This file defines overrides for the standard allocation functions that allow
+ * a given allocation to be made to fail for testing. If the program is run
+ * with MALLOC_NUMBER_TO_FAIL set to a base-10 number then that allocation will
+ * return NULL. If MALLOC_ABORT_ON_FAIL is also defined then the allocation
+ * will abort() rather than return NULL.
+ *
+ * This code is not thread safe. */
+
+static uint64_t current_malloc_count = 0;
+static uint64_t malloc_number_to_fail = 0;
+static char failure_enabled = 0, abort_on_fail = 0;
+static int in_call = 0;
+
+extern "C" {
+/* These are other names for the standard allocation functions. */
+extern void *__libc_malloc(size_t size);
+extern void *__libc_calloc(size_t num_elems, size_t size);
+extern void *__libc_realloc(void *ptr, size_t size);
+}
+
+static void exit_handler(void) {
+ if (failure_enabled && current_malloc_count > malloc_number_to_fail) {
+ _exit(88);
+ }
+}
+
+static void cpp_new_handler() {
+ // Return to try again. It won't fail a second time.
+ return;
+}
+
+/* should_fail_allocation returns true if the current allocation should fail. */
+static int should_fail_allocation() {
+ static int init = 0;
+ char should_fail;
+
+ if (in_call) {
+ return 0;
+ }
+
+ in_call = 1;
+
+ if (!init) {
+ const char *env = getenv("MALLOC_NUMBER_TO_FAIL");
+ if (env != NULL && env[0] != 0) {
+ char *endptr;
+ malloc_number_to_fail = strtoull(env, &endptr, 10);
+ if (*endptr == 0) {
+ failure_enabled = 1;
+ atexit(exit_handler);
+ std::set_new_handler(cpp_new_handler);
+ }
+ }
+ abort_on_fail = (NULL != getenv("MALLOC_ABORT_ON_FAIL"));
+ init = 1;
+ }
+
+ in_call = 0;
+
+ if (!failure_enabled) {
+ return 0;
+ }
+
+ should_fail = (current_malloc_count == malloc_number_to_fail);
+ current_malloc_count++;
+
+ if (should_fail && abort_on_fail) {
+ abort();
+ }
+ return should_fail;
+}
+
+extern "C" {
+
+void *malloc(size_t size) {
+ if (should_fail_allocation()) {
+ return NULL;
+ }
+
+ return __libc_malloc(size);
+}
+
+void *calloc(size_t num_elems, size_t size) {
+ if (should_fail_allocation()) {
+ return NULL;
+ }
+
+ return __libc_calloc(num_elems, size);
+}
+
+void *realloc(void *ptr, size_t size) {
+ if (should_fail_allocation()) {
+ return NULL;
+ }
+
+ return __libc_realloc(ptr, size);
+}
+
+} // extern "C"
+
+#endif /* defined(linux) && !ARM && !AARCH64 */
diff --git a/src/ssl/test/packeted_bio.cc b/src/ssl/test/packeted_bio.cc
new file mode 100644
index 0000000..93b2164
--- /dev/null
+++ b/src/ssl/test/packeted_bio.cc
@@ -0,0 +1,135 @@
+/* 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 "packeted_bio.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+
+#include <openssl/mem.h>
+
+
+namespace {
+
+extern const BIO_METHOD packeted_bio_method;
+
+static int packeted_write(BIO *bio, const char *in, int inl) {
+ if (bio->next_bio == NULL) {
+ return 0;
+ }
+
+ BIO_clear_retry_flags(bio);
+
+ // Write the length prefix.
+ uint8_t len_bytes[4];
+ len_bytes[0] = (inl >> 24) & 0xff;
+ len_bytes[1] = (inl >> 16) & 0xff;
+ len_bytes[2] = (inl >> 8) & 0xff;
+ len_bytes[3] = inl & 0xff;
+ int ret = BIO_write(bio->next_bio, len_bytes, sizeof(len_bytes));
+ if (ret <= 0) {
+ BIO_copy_next_retry(bio);
+ return ret;
+ }
+
+ // Write the buffer. BIOs for which this operation fails are not supported.
+ ret = BIO_write(bio->next_bio, in, inl);
+ assert(ret == inl);
+ return ret;
+}
+
+static int packeted_read(BIO *bio, char *out, int outl) {
+ if (bio->next_bio == NULL) {
+ return 0;
+ }
+
+ BIO_clear_retry_flags(bio);
+
+ // Read the length prefix.
+ uint8_t len_bytes[4];
+ int ret = BIO_read(bio->next_bio, &len_bytes, sizeof(len_bytes));
+ if (ret <= 0) {
+ BIO_copy_next_retry(bio);
+ return ret;
+ }
+ // BIOs for which a partial length comes back are not supported.
+ assert(ret == 4);
+
+ uint32_t len = (len_bytes[0] << 24) | (len_bytes[1] << 16) |
+ (len_bytes[2] << 8) | len_bytes[3];
+ char *buf = (char *)OPENSSL_malloc(len);
+ if (buf == NULL) {
+ return -1;
+ }
+ ret = BIO_read(bio->next_bio, buf, len);
+ assert(ret == (int)len);
+
+ if (outl > (int)len) {
+ outl = len;
+ }
+ memcpy(out, buf, outl);
+ OPENSSL_free(buf);
+ return outl;
+}
+
+static long packeted_ctrl(BIO *bio, int cmd, long num, void *ptr) {
+ if (bio->next_bio == NULL) {
+ return 0;
+ }
+ BIO_clear_retry_flags(bio);
+ int ret = BIO_ctrl(bio->next_bio, cmd, num, ptr);
+ BIO_copy_next_retry(bio);
+ return ret;
+}
+
+static int packeted_new(BIO *bio) {
+ bio->init = 1;
+ return 1;
+}
+
+static int packeted_free(BIO *bio) {
+ if (bio == NULL) {
+ return 0;
+ }
+
+ bio->init = 0;
+ return 1;
+}
+
+static long packeted_callback_ctrl(BIO *bio, int cmd, bio_info_cb fp) {
+ if (bio->next_bio == NULL) {
+ return 0;
+ }
+ return BIO_callback_ctrl(bio->next_bio, cmd, fp);
+}
+
+const BIO_METHOD packeted_bio_method = {
+ BIO_TYPE_FILTER,
+ "packeted bio",
+ packeted_write,
+ packeted_read,
+ NULL /* puts */,
+ NULL /* gets */,
+ packeted_ctrl,
+ packeted_new,
+ packeted_free,
+ packeted_callback_ctrl,
+};
+
+} // namespace
+
+BIO *packeted_bio_create() {
+ return BIO_new(&packeted_bio_method);
+}
diff --git a/src/ssl/test/packeted_bio.h b/src/ssl/test/packeted_bio.h
new file mode 100644
index 0000000..384bd64
--- /dev/null
+++ b/src/ssl/test/packeted_bio.h
@@ -0,0 +1,32 @@
+/* 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 HEADER_PACKETED_BIO
+#define HEADER_PACKETED_BIO
+
+#include <openssl/bio.h>
+
+
+// packeted_bio_create creates a filter BIO for testing protocols which expect
+// datagram BIOs. It implements a reliable datagram socket and reads and writes
+// packets by prefixing each packet with a big-endian 32-bit length. It must be
+// layered over a reliable blocking stream BIO.
+//
+// Note: packeted_bio_create exists because a SOCK_DGRAM socketpair on OS X is
+// does not block the caller, unlike on Linux. Writes simply fail with
+// ENOBUFS. POSIX also does not guarantee that such sockets are reliable.
+BIO *packeted_bio_create();
+
+
+#endif // HEADER_PACKETED_BIO
diff --git a/src/ssl/test/runner/alert.go b/src/ssl/test/runner/alert.go
new file mode 100644
index 0000000..b48ab2a
--- /dev/null
+++ b/src/ssl/test/runner/alert.go
@@ -0,0 +1,77 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "strconv"
+
+type alert uint8
+
+const (
+ // alert level
+ alertLevelWarning = 1
+ alertLevelError = 2
+)
+
+const (
+ alertCloseNotify alert = 0
+ alertUnexpectedMessage alert = 10
+ alertBadRecordMAC alert = 20
+ alertDecryptionFailed alert = 21
+ alertRecordOverflow alert = 22
+ alertDecompressionFailure alert = 30
+ alertHandshakeFailure alert = 40
+ alertBadCertificate alert = 42
+ alertUnsupportedCertificate alert = 43
+ alertCertificateRevoked alert = 44
+ alertCertificateExpired alert = 45
+ alertCertificateUnknown alert = 46
+ alertIllegalParameter alert = 47
+ alertUnknownCA alert = 48
+ alertAccessDenied alert = 49
+ alertDecodeError alert = 50
+ alertDecryptError alert = 51
+ alertProtocolVersion alert = 70
+ alertInsufficientSecurity alert = 71
+ alertInternalError alert = 80
+ alertUserCanceled alert = 90
+ alertNoRenegotiation alert = 100
+)
+
+var alertText = map[alert]string{
+ alertCloseNotify: "close notify",
+ alertUnexpectedMessage: "unexpected message",
+ alertBadRecordMAC: "bad record MAC",
+ alertDecryptionFailed: "decryption failed",
+ alertRecordOverflow: "record overflow",
+ alertDecompressionFailure: "decompression failure",
+ alertHandshakeFailure: "handshake failure",
+ alertBadCertificate: "bad certificate",
+ alertUnsupportedCertificate: "unsupported certificate",
+ alertCertificateRevoked: "revoked certificate",
+ alertCertificateExpired: "expired certificate",
+ alertCertificateUnknown: "unknown certificate",
+ alertIllegalParameter: "illegal parameter",
+ alertUnknownCA: "unknown certificate authority",
+ alertAccessDenied: "access denied",
+ alertDecodeError: "error decoding message",
+ alertDecryptError: "error decrypting message",
+ alertProtocolVersion: "protocol version not supported",
+ alertInsufficientSecurity: "insufficient security level",
+ alertInternalError: "internal error",
+ alertUserCanceled: "user canceled",
+ alertNoRenegotiation: "no renegotiation",
+}
+
+func (e alert) String() string {
+ s, ok := alertText[e]
+ if ok {
+ return s
+ }
+ return "alert(" + strconv.Itoa(int(e)) + ")"
+}
+
+func (e alert) Error() string {
+ return e.String()
+}
diff --git a/src/ssl/test/runner/cert.pem b/src/ssl/test/runner/cert.pem
new file mode 100644
index 0000000..4de4f49
--- /dev/null
+++ b/src/ssl/test/runner/cert.pem
@@ -0,0 +1,15 @@
+-----BEGIN CERTIFICATE-----
+MIICWDCCAcGgAwIBAgIJAPuwTC6rEJsMMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
+BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
+aWRnaXRzIFB0eSBMdGQwHhcNMTQwNDIzMjA1MDQwWhcNMTcwNDIyMjA1MDQwWjBF
+MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
+ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
+gQDYK8imMuRi/03z0K1Zi0WnvfFHvwlYeyK9Na6XJYaUoIDAtB92kWdGMdAQhLci
+HnAjkXLI6W15OoV3gA/ElRZ1xUpxTMhjP6PyY5wqT5r6y8FxbiiFKKAnHmUcrgfV
+W28tQ+0rkLGMryRtrukXOgXBv7gcrmU7G1jC2a7WqmeI8QIDAQABo1AwTjAdBgNV
+HQ4EFgQUi3XVrMsIvg4fZbf6Vr5sp3Xaha8wHwYDVR0jBBgwFoAUi3XVrMsIvg4f
+Zbf6Vr5sp3Xaha8wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQA76Hht
+ldY9avcTGSwbwoiuIqv0jTL1fHFnzy3RHMLDh+Lpvolc5DSrSJHCP5WuK0eeJXhr
+T5oQpHL9z/cCDLAKCKRa4uV0fhEdOWBqyR9p8y5jJtye72t6CuFUV5iqcpF4BH4f
+j2VNHwsSrJwkD4QUGlUtH7vwnQmyCFxZMmWAJg==
+-----END CERTIFICATE-----
diff --git a/src/ssl/test/runner/channel_id_key.pem b/src/ssl/test/runner/channel_id_key.pem
new file mode 100644
index 0000000..604752b
--- /dev/null
+++ b/src/ssl/test/runner/channel_id_key.pem
@@ -0,0 +1,5 @@
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEIPwxu50c7LEhVNRYJFRWBUnoaz7JSos96T5hBp4rjyptoAoGCCqGSM49
+AwEHoUQDQgAEzFSVTE5guxJRQ0VbZ8dicPs5e/DT7xpW7Yc9hq0VOchv7cbXuI/T
+CwadDjGWX/oaz0ftFqrVmfkwZu+C58ioWg==
+-----END EC PRIVATE KEY-----
diff --git a/src/ssl/test/runner/cipher_suites.go b/src/ssl/test/runner/cipher_suites.go
new file mode 100644
index 0000000..89e75c8
--- /dev/null
+++ b/src/ssl/test/runner/cipher_suites.go
@@ -0,0 +1,395 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "crypto/aes"
+ "crypto/cipher"
+ "crypto/des"
+ "crypto/hmac"
+ "crypto/md5"
+ "crypto/rc4"
+ "crypto/sha1"
+ "crypto/sha256"
+ "crypto/sha512"
+ "crypto/x509"
+ "hash"
+)
+
+// a keyAgreement implements the client and server side of a TLS key agreement
+// protocol by generating and processing key exchange messages.
+type keyAgreement interface {
+ // On the server side, the first two methods are called in order.
+
+ // In the case that the key agreement protocol doesn't use a
+ // ServerKeyExchange message, generateServerKeyExchange can return nil,
+ // nil.
+ generateServerKeyExchange(*Config, *Certificate, *clientHelloMsg, *serverHelloMsg) (*serverKeyExchangeMsg, error)
+ processClientKeyExchange(*Config, *Certificate, *clientKeyExchangeMsg, uint16) ([]byte, error)
+
+ // On the client side, the next two methods are called in order.
+
+ // This method may not be called if the server doesn't send a
+ // ServerKeyExchange message.
+ processServerKeyExchange(*Config, *clientHelloMsg, *serverHelloMsg, *x509.Certificate, *serverKeyExchangeMsg) error
+ generateClientKeyExchange(*Config, *clientHelloMsg, *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error)
+}
+
+const (
+ // suiteECDH indicates that the cipher suite involves elliptic curve
+ // Diffie-Hellman. This means that it should only be selected when the
+ // client indicates that it supports ECC with a curve and point format
+ // that we're happy with.
+ suiteECDHE = 1 << iota
+ // suiteECDSA indicates that the cipher suite involves an ECDSA
+ // signature and therefore may only be selected when the server's
+ // certificate is ECDSA. If this is not set then the cipher suite is
+ // RSA based.
+ suiteECDSA
+ // suiteTLS12 indicates that the cipher suite should only be advertised
+ // and accepted when using TLS 1.2.
+ suiteTLS12
+ // suiteSHA384 indicates that the cipher suite uses SHA384 as the
+ // handshake hash.
+ suiteSHA384
+ // suiteNoDTLS indicates that the cipher suite cannot be used
+ // in DTLS.
+ suiteNoDTLS
+ // suitePSK indicates that the cipher suite authenticates with
+ // a pre-shared key rather than a server private key.
+ suitePSK
+)
+
+// A cipherSuite is a specific combination of key agreement, cipher and MAC
+// function. All cipher suites currently assume RSA key agreement.
+type cipherSuite struct {
+ id uint16
+ // the lengths, in bytes, of the key material needed for each component.
+ keyLen int
+ macLen int
+ ivLen int
+ ka func(version uint16) keyAgreement
+ // flags is a bitmask of the suite* values, above.
+ flags int
+ cipher func(key, iv []byte, isRead bool) interface{}
+ mac func(version uint16, macKey []byte) macFunction
+ aead func(key, fixedNonce []byte) cipher.AEAD
+}
+
+var cipherSuites = []*cipherSuite{
+ // Ciphersuite order is chosen so that ECDHE comes before plain RSA
+ // and RC4 comes before AES (because of the Lucky13 attack).
+ {TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, ecdheRSAKA, suiteECDHE | suiteTLS12, nil, nil, aeadAESGCM},
+ {TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12, nil, nil, aeadAESGCM},
+ {TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, ecdheRSAKA, suiteECDHE | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
+ {TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
+ {TLS_ECDHE_RSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheRSAKA, suiteECDHE | suiteNoDTLS, cipherRC4, macSHA1, nil},
+ {TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteNoDTLS, cipherRC4, macSHA1, nil},
+ {TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, ecdheRSAKA, suiteECDHE | suiteTLS12, cipherAES, macSHA256, nil},
+ {TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12, cipherAES, macSHA256, nil},
+ {TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil},
+ {TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA, cipherAES, macSHA1, nil},
+ {TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, 32, 48, 16, ecdheRSAKA, suiteECDHE | suiteTLS12 | suiteSHA384, cipherAES, macSHA384, nil},
+ {TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, 32, 48, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12 | suiteSHA384, cipherAES, macSHA384, nil},
+ {TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil},
+ {TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA, cipherAES, macSHA1, nil},
+ {TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, dheRSAKA, suiteTLS12, nil, nil, aeadAESGCM},
+ {TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, dheRSAKA, suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
+ {TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, dheRSAKA, suiteTLS12, cipherAES, macSHA256, nil},
+ {TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, 32, 32, 16, dheRSAKA, suiteTLS12, cipherAES, macSHA256, nil},
+ {TLS_DHE_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, dheRSAKA, 0, cipherAES, macSHA1, nil},
+ {TLS_DHE_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, dheRSAKA, 0, cipherAES, macSHA1, nil},
+ {TLS_RSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, rsaKA, suiteTLS12, nil, nil, aeadAESGCM},
+ {TLS_RSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, rsaKA, suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
+ {TLS_RSA_WITH_RC4_128_SHA, 16, 20, 0, rsaKA, suiteNoDTLS, cipherRC4, macSHA1, nil},
+ {TLS_RSA_WITH_RC4_128_MD5, 16, 16, 0, rsaKA, suiteNoDTLS, cipherRC4, macMD5, nil},
+ {TLS_RSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, rsaKA, suiteTLS12, cipherAES, macSHA256, nil},
+ {TLS_RSA_WITH_AES_256_CBC_SHA256, 32, 32, 16, rsaKA, suiteTLS12, cipherAES, macSHA256, nil},
+ {TLS_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, rsaKA, 0, cipherAES, macSHA1, nil},
+ {TLS_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, rsaKA, 0, cipherAES, macSHA1, nil},
+ {TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, ecdheRSAKA, suiteECDHE, cipher3DES, macSHA1, nil},
+ {TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, dheRSAKA, 0, cipher3DES, macSHA1, nil},
+ {TLS_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, rsaKA, 0, cipher3DES, macSHA1, nil},
+ {TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256, 16, 0, 4, ecdhePSKKA, suiteECDHE | suiteTLS12 | suitePSK, nil, nil, aeadAESGCM},
+ {TLS_PSK_WITH_RC4_128_SHA, 16, 20, 0, pskKA, suiteNoDTLS | suitePSK, cipherRC4, macSHA1, nil},
+ {TLS_PSK_WITH_AES_128_CBC_SHA, 16, 20, 16, pskKA, suitePSK, cipherAES, macSHA1, nil},
+ {TLS_PSK_WITH_AES_256_CBC_SHA, 32, 20, 16, pskKA, suitePSK, cipherAES, macSHA1, nil},
+}
+
+func cipherRC4(key, iv []byte, isRead bool) interface{} {
+ cipher, _ := rc4.NewCipher(key)
+ return cipher
+}
+
+func cipher3DES(key, iv []byte, isRead bool) interface{} {
+ block, _ := des.NewTripleDESCipher(key)
+ if isRead {
+ return cipher.NewCBCDecrypter(block, iv)
+ }
+ return cipher.NewCBCEncrypter(block, iv)
+}
+
+func cipherAES(key, iv []byte, isRead bool) interface{} {
+ block, _ := aes.NewCipher(key)
+ if isRead {
+ return cipher.NewCBCDecrypter(block, iv)
+ }
+ return cipher.NewCBCEncrypter(block, iv)
+}
+
+// macSHA1 returns a macFunction for the given protocol version.
+func macSHA1(version uint16, key []byte) macFunction {
+ if version == VersionSSL30 {
+ mac := ssl30MAC{
+ h: sha1.New(),
+ key: make([]byte, len(key)),
+ }
+ copy(mac.key, key)
+ return mac
+ }
+ return tls10MAC{hmac.New(sha1.New, key)}
+}
+
+func macMD5(version uint16, key []byte) macFunction {
+ if version == VersionSSL30 {
+ mac := ssl30MAC{
+ h: md5.New(),
+ key: make([]byte, len(key)),
+ }
+ copy(mac.key, key)
+ return mac
+ }
+ return tls10MAC{hmac.New(md5.New, key)}
+}
+
+func macSHA256(version uint16, key []byte) macFunction {
+ if version == VersionSSL30 {
+ mac := ssl30MAC{
+ h: sha256.New(),
+ key: make([]byte, len(key)),
+ }
+ copy(mac.key, key)
+ return mac
+ }
+ return tls10MAC{hmac.New(sha256.New, key)}
+}
+
+func macSHA384(version uint16, key []byte) macFunction {
+ if version == VersionSSL30 {
+ mac := ssl30MAC{
+ h: sha512.New384(),
+ key: make([]byte, len(key)),
+ }
+ copy(mac.key, key)
+ return mac
+ }
+ return tls10MAC{hmac.New(sha512.New384, key)}
+}
+
+type macFunction interface {
+ Size() int
+ MAC(digestBuf, seq, header, length, data []byte) []byte
+}
+
+// fixedNonceAEAD wraps an AEAD and prefixes a fixed portion of the nonce to
+// each call.
+type fixedNonceAEAD struct {
+ // sealNonce and openNonce are buffers where the larger nonce will be
+ // constructed. Since a seal and open operation may be running
+ // concurrently, there is a separate buffer for each.
+ sealNonce, openNonce []byte
+ aead cipher.AEAD
+}
+
+func (f *fixedNonceAEAD) NonceSize() int { return 8 }
+func (f *fixedNonceAEAD) Overhead() int { return f.aead.Overhead() }
+
+func (f *fixedNonceAEAD) Seal(out, nonce, plaintext, additionalData []byte) []byte {
+ copy(f.sealNonce[len(f.sealNonce)-8:], nonce)
+ return f.aead.Seal(out, f.sealNonce, plaintext, additionalData)
+}
+
+func (f *fixedNonceAEAD) Open(out, nonce, plaintext, additionalData []byte) ([]byte, error) {
+ copy(f.openNonce[len(f.openNonce)-8:], nonce)
+ return f.aead.Open(out, f.openNonce, plaintext, additionalData)
+}
+
+func aeadAESGCM(key, fixedNonce []byte) cipher.AEAD {
+ aes, err := aes.NewCipher(key)
+ if err != nil {
+ panic(err)
+ }
+ aead, err := cipher.NewGCM(aes)
+ if err != nil {
+ panic(err)
+ }
+
+ nonce1, nonce2 := make([]byte, 12), make([]byte, 12)
+ copy(nonce1, fixedNonce)
+ copy(nonce2, fixedNonce)
+
+ return &fixedNonceAEAD{nonce1, nonce2, aead}
+}
+
+// ssl30MAC implements the SSLv3 MAC function, as defined in
+// www.mozilla.org/projects/security/pki/nss/ssl/draft302.txt section 5.2.3.1
+type ssl30MAC struct {
+ h hash.Hash
+ key []byte
+}
+
+func (s ssl30MAC) Size() int {
+ return s.h.Size()
+}
+
+var ssl30Pad1 = [48]byte{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36}
+
+var ssl30Pad2 = [48]byte{0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c}
+
+func (s ssl30MAC) MAC(digestBuf, seq, header, length, data []byte) []byte {
+ padLength := 48
+ if s.h.Size() == 20 {
+ padLength = 40
+ }
+
+ s.h.Reset()
+ s.h.Write(s.key)
+ s.h.Write(ssl30Pad1[:padLength])
+ s.h.Write(seq)
+ s.h.Write(header[:1])
+ s.h.Write(length)
+ s.h.Write(data)
+ digestBuf = s.h.Sum(digestBuf[:0])
+
+ s.h.Reset()
+ s.h.Write(s.key)
+ s.h.Write(ssl30Pad2[:padLength])
+ s.h.Write(digestBuf)
+ return s.h.Sum(digestBuf[:0])
+}
+
+// tls10MAC implements the TLS 1.0 MAC function. RFC 2246, section 6.2.3.
+type tls10MAC struct {
+ h hash.Hash
+}
+
+func (s tls10MAC) Size() int {
+ return s.h.Size()
+}
+
+func (s tls10MAC) MAC(digestBuf, seq, header, length, data []byte) []byte {
+ s.h.Reset()
+ s.h.Write(seq)
+ s.h.Write(header)
+ s.h.Write(length)
+ s.h.Write(data)
+ return s.h.Sum(digestBuf[:0])
+}
+
+func rsaKA(version uint16) keyAgreement {
+ return &rsaKeyAgreement{}
+}
+
+func ecdheECDSAKA(version uint16) keyAgreement {
+ return &ecdheKeyAgreement{
+ auth: &signedKeyAgreement{
+ sigType: signatureECDSA,
+ version: version,
+ },
+ }
+}
+
+func ecdheRSAKA(version uint16) keyAgreement {
+ return &ecdheKeyAgreement{
+ auth: &signedKeyAgreement{
+ sigType: signatureRSA,
+ version: version,
+ },
+ }
+}
+
+func dheRSAKA(version uint16) keyAgreement {
+ return &dheKeyAgreement{
+ auth: &signedKeyAgreement{
+ sigType: signatureRSA,
+ version: version,
+ },
+ }
+}
+
+func pskKA(version uint16) keyAgreement {
+ return &pskKeyAgreement{
+ base: &nilKeyAgreement{},
+ }
+}
+
+func ecdhePSKKA(version uint16) keyAgreement {
+ return &pskKeyAgreement{
+ base: &ecdheKeyAgreement{
+ auth: &nilKeyAgreementAuthentication{},
+ },
+ }
+}
+
+// mutualCipherSuite returns a cipherSuite given a list of supported
+// ciphersuites and the id requested by the peer.
+func mutualCipherSuite(have []uint16, want uint16) *cipherSuite {
+ for _, id := range have {
+ if id == want {
+ for _, suite := range cipherSuites {
+ if suite.id == want {
+ return suite
+ }
+ }
+ return nil
+ }
+ }
+ return nil
+}
+
+// A list of the possible cipher suite ids. Taken from
+// http://www.iana.org/assignments/tls-parameters/tls-parameters.xml
+const (
+ TLS_RSA_WITH_RC4_128_MD5 uint16 = 0x0004
+ TLS_RSA_WITH_RC4_128_SHA uint16 = 0x0005
+ TLS_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x000a
+ TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x0016
+ TLS_RSA_WITH_AES_128_CBC_SHA uint16 = 0x002f
+ TLS_DHE_RSA_WITH_AES_128_CBC_SHA uint16 = 0x0033
+ TLS_RSA_WITH_AES_256_CBC_SHA uint16 = 0x0035
+ TLS_DHE_RSA_WITH_AES_256_CBC_SHA uint16 = 0x0039
+ TLS_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0x003c
+ TLS_RSA_WITH_AES_256_CBC_SHA256 uint16 = 0x003d
+ TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0x0067
+ TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 uint16 = 0x006b
+ TLS_PSK_WITH_RC4_128_SHA uint16 = 0x008a
+ TLS_PSK_WITH_AES_128_CBC_SHA uint16 = 0x008c
+ TLS_PSK_WITH_AES_256_CBC_SHA uint16 = 0x008d
+ TLS_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0x009c
+ TLS_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0x009d
+ TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0x009e
+ TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0x009f
+ TLS_ECDHE_ECDSA_WITH_RC4_128_SHA uint16 = 0xc007
+ TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA uint16 = 0xc009
+ TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA uint16 = 0xc00a
+ TLS_ECDHE_RSA_WITH_RC4_128_SHA uint16 = 0xc011
+ TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xc012
+ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA uint16 = 0xc013
+ TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA uint16 = 0xc014
+ TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 uint16 = 0xc023
+ TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 uint16 = 0xc024
+ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0xc027
+ TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 uint16 = 0xc028
+ TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 uint16 = 0xc02b
+ TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 uint16 = 0xc02c
+ TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0xc02f
+ TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0xc030
+ fallbackSCSV uint16 = 0x5600
+)
+
+// Additional cipher suite IDs, not IANA-assigned.
+const (
+ TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256 uint16 = 0xcafe
+)
diff --git a/src/ssl/test/runner/common.go b/src/ssl/test/runner/common.go
new file mode 100644
index 0000000..7aaf9a2
--- /dev/null
+++ b/src/ssl/test/runner/common.go
@@ -0,0 +1,953 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "container/list"
+ "crypto"
+ "crypto/ecdsa"
+ "crypto/rand"
+ "crypto/x509"
+ "fmt"
+ "io"
+ "math/big"
+ "strings"
+ "sync"
+ "time"
+)
+
+const (
+ VersionSSL30 = 0x0300
+ VersionTLS10 = 0x0301
+ VersionTLS11 = 0x0302
+ VersionTLS12 = 0x0303
+)
+
+const (
+ maxPlaintext = 16384 // maximum plaintext payload length
+ maxCiphertext = 16384 + 2048 // maximum ciphertext payload length
+ tlsRecordHeaderLen = 5 // record header length
+ dtlsRecordHeaderLen = 13
+ maxHandshake = 65536 // maximum handshake we support (protocol max is 16 MB)
+
+ minVersion = VersionSSL30
+ maxVersion = VersionTLS12
+)
+
+// TLS record types.
+type recordType uint8
+
+const (
+ recordTypeChangeCipherSpec recordType = 20
+ recordTypeAlert recordType = 21
+ recordTypeHandshake recordType = 22
+ recordTypeApplicationData recordType = 23
+)
+
+// TLS handshake message types.
+const (
+ typeHelloRequest uint8 = 0
+ typeClientHello uint8 = 1
+ typeServerHello uint8 = 2
+ typeHelloVerifyRequest uint8 = 3
+ typeNewSessionTicket uint8 = 4
+ typeCertificate uint8 = 11
+ typeServerKeyExchange uint8 = 12
+ typeCertificateRequest uint8 = 13
+ typeServerHelloDone uint8 = 14
+ typeCertificateVerify uint8 = 15
+ typeClientKeyExchange uint8 = 16
+ typeFinished uint8 = 20
+ typeCertificateStatus uint8 = 22
+ typeNextProtocol uint8 = 67 // Not IANA assigned
+ typeEncryptedExtensions uint8 = 203 // Not IANA assigned
+)
+
+// TLS compression types.
+const (
+ compressionNone uint8 = 0
+)
+
+// TLS extension numbers
+const (
+ extensionServerName uint16 = 0
+ extensionStatusRequest uint16 = 5
+ extensionSupportedCurves uint16 = 10
+ extensionSupportedPoints uint16 = 11
+ extensionSignatureAlgorithms uint16 = 13
+ extensionUseSRTP uint16 = 14
+ extensionALPN uint16 = 16
+ extensionSignedCertificateTimestamp uint16 = 18
+ extensionExtendedMasterSecret uint16 = 23
+ extensionSessionTicket uint16 = 35
+ extensionNextProtoNeg uint16 = 13172 // not IANA assigned
+ extensionRenegotiationInfo uint16 = 0xff01
+ extensionChannelID uint16 = 30032 // not IANA assigned
+)
+
+// TLS signaling cipher suite values
+const (
+ scsvRenegotiation uint16 = 0x00ff
+)
+
+// CurveID is the type of a TLS identifier for an elliptic curve. See
+// http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-8
+type CurveID uint16
+
+const (
+ CurveP256 CurveID = 23
+ CurveP384 CurveID = 24
+ CurveP521 CurveID = 25
+)
+
+// TLS Elliptic Curve Point Formats
+// http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-9
+const (
+ pointFormatUncompressed uint8 = 0
+)
+
+// TLS CertificateStatusType (RFC 3546)
+const (
+ statusTypeOCSP uint8 = 1
+)
+
+// Certificate types (for certificateRequestMsg)
+const (
+ CertTypeRSASign = 1 // A certificate containing an RSA key
+ CertTypeDSSSign = 2 // A certificate containing a DSA key
+ CertTypeRSAFixedDH = 3 // A certificate containing a static DH key
+ CertTypeDSSFixedDH = 4 // A certificate containing a static DH key
+
+ // See RFC4492 sections 3 and 5.5.
+ CertTypeECDSASign = 64 // A certificate containing an ECDSA-capable public key, signed with ECDSA.
+ CertTypeRSAFixedECDH = 65 // A certificate containing an ECDH-capable public key, signed with RSA.
+ CertTypeECDSAFixedECDH = 66 // A certificate containing an ECDH-capable public key, signed with ECDSA.
+
+ // Rest of these are reserved by the TLS spec
+)
+
+// Hash functions for TLS 1.2 (See RFC 5246, section A.4.1)
+const (
+ hashMD5 uint8 = 1
+ hashSHA1 uint8 = 2
+ hashSHA224 uint8 = 3
+ hashSHA256 uint8 = 4
+ hashSHA384 uint8 = 5
+ hashSHA512 uint8 = 6
+)
+
+// Signature algorithms for TLS 1.2 (See RFC 5246, section A.4.1)
+const (
+ signatureRSA uint8 = 1
+ signatureECDSA uint8 = 3
+)
+
+// signatureAndHash mirrors the TLS 1.2, SignatureAndHashAlgorithm struct. See
+// RFC 5246, section A.4.1.
+type signatureAndHash struct {
+ signature, hash uint8
+}
+
+// supportedSKXSignatureAlgorithms contains the signature and hash algorithms
+// that the code advertises as supported in a TLS 1.2 ClientHello.
+var supportedSKXSignatureAlgorithms = []signatureAndHash{
+ {signatureRSA, hashSHA256},
+ {signatureECDSA, hashSHA256},
+ {signatureRSA, hashSHA1},
+ {signatureECDSA, hashSHA1},
+}
+
+// supportedClientCertSignatureAlgorithms contains the signature and hash
+// algorithms that the code advertises as supported in a TLS 1.2
+// CertificateRequest.
+var supportedClientCertSignatureAlgorithms = []signatureAndHash{
+ {signatureRSA, hashSHA256},
+ {signatureECDSA, hashSHA256},
+}
+
+// SRTP protection profiles (See RFC 5764, section 4.1.2)
+const (
+ SRTP_AES128_CM_HMAC_SHA1_80 uint16 = 0x0001
+ SRTP_AES128_CM_HMAC_SHA1_32 = 0x0002
+)
+
+// ConnectionState records basic TLS details about the connection.
+type ConnectionState struct {
+ Version uint16 // TLS version used by the connection (e.g. VersionTLS12)
+ HandshakeComplete bool // TLS handshake is complete
+ DidResume bool // connection resumes a previous TLS connection
+ CipherSuite uint16 // cipher suite in use (TLS_RSA_WITH_RC4_128_SHA, ...)
+ NegotiatedProtocol string // negotiated next protocol (from Config.NextProtos)
+ NegotiatedProtocolIsMutual bool // negotiated protocol was advertised by server
+ NegotiatedProtocolFromALPN bool // protocol negotiated with ALPN
+ ServerName string // server name requested by client, if any (server side only)
+ PeerCertificates []*x509.Certificate // certificate chain presented by remote peer
+ VerifiedChains [][]*x509.Certificate // verified chains built from PeerCertificates
+ ChannelID *ecdsa.PublicKey // the channel ID for this connection
+ SRTPProtectionProfile uint16 // the negotiated DTLS-SRTP protection profile
+}
+
+// ClientAuthType declares the policy the server will follow for
+// TLS Client Authentication.
+type ClientAuthType int
+
+const (
+ NoClientCert ClientAuthType = iota
+ RequestClientCert
+ RequireAnyClientCert
+ VerifyClientCertIfGiven
+ RequireAndVerifyClientCert
+)
+
+// ClientSessionState contains the state needed by clients to resume TLS
+// sessions.
+type ClientSessionState struct {
+ sessionId []uint8 // Session ID supplied by the server. nil if the session has a ticket.
+ sessionTicket []uint8 // Encrypted ticket used for session resumption with server
+ vers uint16 // SSL/TLS version negotiated for the session
+ cipherSuite uint16 // Ciphersuite negotiated for the session
+ masterSecret []byte // MasterSecret generated by client on a full handshake
+ handshakeHash []byte // Handshake hash for Channel ID purposes.
+ serverCertificates []*x509.Certificate // Certificate chain presented by the server
+ extendedMasterSecret bool // Whether an extended master secret was used to generate the session
+}
+
+// ClientSessionCache is a cache of ClientSessionState objects that can be used
+// by a client to resume a TLS session with a given server. ClientSessionCache
+// implementations should expect to be called concurrently from different
+// goroutines.
+type ClientSessionCache interface {
+ // Get searches for a ClientSessionState associated with the given key.
+ // On return, ok is true if one was found.
+ Get(sessionKey string) (session *ClientSessionState, ok bool)
+
+ // Put adds the ClientSessionState to the cache with the given key.
+ Put(sessionKey string, cs *ClientSessionState)
+}
+
+// ServerSessionCache is a cache of sessionState objects that can be used by a
+// client to resume a TLS session with a given server. ServerSessionCache
+// implementations should expect to be called concurrently from different
+// goroutines.
+type ServerSessionCache interface {
+ // Get searches for a sessionState associated with the given session
+ // ID. On return, ok is true if one was found.
+ Get(sessionId string) (session *sessionState, ok bool)
+
+ // Put adds the sessionState to the cache with the given session ID.
+ Put(sessionId string, session *sessionState)
+}
+
+// A Config structure is used to configure a TLS client or server.
+// After one has been passed to a TLS function it must not be
+// modified. A Config may be reused; the tls package will also not
+// modify it.
+type Config struct {
+ // Rand provides the source of entropy for nonces and RSA blinding.
+ // If Rand is nil, TLS uses the cryptographic random reader in package
+ // crypto/rand.
+ // The Reader must be safe for use by multiple goroutines.
+ Rand io.Reader
+
+ // Time returns the current time as the number of seconds since the epoch.
+ // If Time is nil, TLS uses time.Now.
+ Time func() time.Time
+
+ // Certificates contains one or more certificate chains
+ // to present to the other side of the connection.
+ // Server configurations must include at least one certificate.
+ Certificates []Certificate
+
+ // NameToCertificate maps from a certificate name to an element of
+ // Certificates. Note that a certificate name can be of the form
+ // '*.example.com' and so doesn't have to be a domain name as such.
+ // See Config.BuildNameToCertificate
+ // The nil value causes the first element of Certificates to be used
+ // for all connections.
+ NameToCertificate map[string]*Certificate
+
+ // RootCAs defines the set of root certificate authorities
+ // that clients use when verifying server certificates.
+ // If RootCAs is nil, TLS uses the host's root CA set.
+ RootCAs *x509.CertPool
+
+ // NextProtos is a list of supported, application level protocols.
+ NextProtos []string
+
+ // ServerName is used to verify the hostname on the returned
+ // certificates unless InsecureSkipVerify is given. It is also included
+ // in the client's handshake to support virtual hosting.
+ ServerName string
+
+ // ClientAuth determines the server's policy for
+ // TLS Client Authentication. The default is NoClientCert.
+ ClientAuth ClientAuthType
+
+ // ClientCAs defines the set of root certificate authorities
+ // that servers use if required to verify a client certificate
+ // by the policy in ClientAuth.
+ ClientCAs *x509.CertPool
+
+ // ClientCertificateTypes defines the set of allowed client certificate
+ // types. The default is CertTypeRSASign and CertTypeECDSASign.
+ ClientCertificateTypes []byte
+
+ // InsecureSkipVerify controls whether a client verifies the
+ // server's certificate chain and host name.
+ // If InsecureSkipVerify is true, TLS accepts any certificate
+ // presented by the server and any host name in that certificate.
+ // In this mode, TLS is susceptible to man-in-the-middle attacks.
+ // This should be used only for testing.
+ InsecureSkipVerify bool
+
+ // CipherSuites is a list of supported cipher suites. If CipherSuites
+ // is nil, TLS uses a list of suites supported by the implementation.
+ CipherSuites []uint16
+
+ // PreferServerCipherSuites controls whether the server selects the
+ // client's most preferred ciphersuite, or the server's most preferred
+ // ciphersuite. If true then the server's preference, as expressed in
+ // the order of elements in CipherSuites, is used.
+ PreferServerCipherSuites bool
+
+ // SessionTicketsDisabled may be set to true to disable session ticket
+ // (resumption) support.
+ SessionTicketsDisabled bool
+
+ // SessionTicketKey is used by TLS servers to provide session
+ // resumption. See RFC 5077. If zero, it will be filled with
+ // random data before the first server handshake.
+ //
+ // If multiple servers are terminating connections for the same host
+ // they should all have the same SessionTicketKey. If the
+ // SessionTicketKey leaks, previously recorded and future TLS
+ // connections using that key are compromised.
+ SessionTicketKey [32]byte
+
+ // ClientSessionCache is a cache of ClientSessionState entries
+ // for TLS session resumption.
+ ClientSessionCache ClientSessionCache
+
+ // ServerSessionCache is a cache of sessionState entries for TLS session
+ // resumption.
+ ServerSessionCache ServerSessionCache
+
+ // MinVersion contains the minimum SSL/TLS version that is acceptable.
+ // If zero, then SSLv3 is taken as the minimum.
+ MinVersion uint16
+
+ // MaxVersion contains the maximum SSL/TLS version that is acceptable.
+ // If zero, then the maximum version supported by this package is used,
+ // which is currently TLS 1.2.
+ MaxVersion uint16
+
+ // CurvePreferences contains the elliptic curves that will be used in
+ // an ECDHE handshake, in preference order. If empty, the default will
+ // be used.
+ CurvePreferences []CurveID
+
+ // ChannelID contains the ECDSA key for the client to use as
+ // its TLS Channel ID.
+ ChannelID *ecdsa.PrivateKey
+
+ // RequestChannelID controls whether the server requests a TLS
+ // Channel ID. If negotiated, the client's public key is
+ // returned in the ConnectionState.
+ RequestChannelID bool
+
+ // PreSharedKey, if not nil, is the pre-shared key to use with
+ // the PSK cipher suites.
+ PreSharedKey []byte
+
+ // PreSharedKeyIdentity, if not empty, is the identity to use
+ // with the PSK cipher suites.
+ PreSharedKeyIdentity string
+
+ // SRTPProtectionProfiles, if not nil, is the list of SRTP
+ // protection profiles to offer in DTLS-SRTP.
+ SRTPProtectionProfiles []uint16
+
+ // SignatureAndHashes, if not nil, overrides the default set of
+ // supported signature and hash algorithms to advertise in
+ // CertificateRequest.
+ SignatureAndHashes []signatureAndHash
+
+ // Bugs specifies optional misbehaviour to be used for testing other
+ // implementations.
+ Bugs ProtocolBugs
+
+ serverInitOnce sync.Once // guards calling (*Config).serverInit
+}
+
+type BadValue int
+
+const (
+ BadValueNone BadValue = iota
+ BadValueNegative
+ BadValueZero
+ BadValueLimit
+ BadValueLarge
+ NumBadValues
+)
+
+type ProtocolBugs struct {
+ // InvalidSKXSignature specifies that the signature in a
+ // ServerKeyExchange message should be invalid.
+ InvalidSKXSignature bool
+
+ // InvalidSKXCurve causes the curve ID in the ServerKeyExchange message
+ // to be wrong.
+ InvalidSKXCurve bool
+
+ // BadECDSAR controls ways in which the 'r' value of an ECDSA signature
+ // can be invalid.
+ BadECDSAR BadValue
+ BadECDSAS BadValue
+
+ // MaxPadding causes CBC records to have the maximum possible padding.
+ MaxPadding bool
+ // PaddingFirstByteBad causes the first byte of the padding to be
+ // incorrect.
+ PaddingFirstByteBad bool
+ // PaddingFirstByteBadIf255 causes the first byte of padding to be
+ // incorrect if there's a maximum amount of padding (i.e. 255 bytes).
+ PaddingFirstByteBadIf255 bool
+
+ // FailIfNotFallbackSCSV causes a server handshake to fail if the
+ // client doesn't send the fallback SCSV value.
+ FailIfNotFallbackSCSV bool
+
+ // DuplicateExtension causes an extra empty extension of bogus type to
+ // be emitted in either the ClientHello or the ServerHello.
+ DuplicateExtension bool
+
+ // UnauthenticatedECDH causes the server to pretend ECDHE_RSA
+ // and ECDHE_ECDSA cipher suites are actually ECDH_anon. No
+ // Certificate message is sent and no signature is added to
+ // ServerKeyExchange.
+ UnauthenticatedECDH bool
+
+ // SkipServerKeyExchange causes the server to skip sending
+ // ServerKeyExchange messages.
+ SkipServerKeyExchange bool
+
+ // SkipChangeCipherSpec causes the implementation to skip
+ // sending the ChangeCipherSpec message (and adjusting cipher
+ // state accordingly for the Finished message).
+ SkipChangeCipherSpec bool
+
+ // EarlyChangeCipherSpec causes the client to send an early
+ // ChangeCipherSpec message before the ClientKeyExchange. A value of
+ // zero disables this behavior. One and two configure variants for 0.9.8
+ // and 1.0.1 modes, respectively.
+ EarlyChangeCipherSpec int
+
+ // FragmentAcrossChangeCipherSpec causes the implementation to fragment
+ // the Finished (or NextProto) message around the ChangeCipherSpec
+ // messages.
+ FragmentAcrossChangeCipherSpec bool
+
+ // SkipNewSessionTicket causes the server to skip sending the
+ // NewSessionTicket message despite promising to in ServerHello.
+ SkipNewSessionTicket bool
+
+ // SendV2ClientHello causes the client to send a V2ClientHello
+ // instead of a normal ClientHello.
+ SendV2ClientHello bool
+
+ // SendFallbackSCSV causes the client to include
+ // TLS_FALLBACK_SCSV in the ClientHello.
+ SendFallbackSCSV bool
+
+ // MaxHandshakeRecordLength, if non-zero, is the maximum size of a
+ // handshake record. Handshake messages will be split into multiple
+ // records at the specified size, except that the client_version will
+ // never be fragmented.
+ MaxHandshakeRecordLength int
+
+ // FragmentClientVersion will allow MaxHandshakeRecordLength to apply to
+ // the first 6 bytes of the ClientHello.
+ FragmentClientVersion bool
+
+ // FragmentAlert will cause all alerts to be fragmented across
+ // two records.
+ FragmentAlert bool
+
+ // SendSpuriousAlert will cause an spurious, unwanted alert to be sent.
+ SendSpuriousAlert bool
+
+ // RsaClientKeyExchangeVersion, if non-zero, causes the client to send a
+ // ClientKeyExchange with the specified version rather than the
+ // client_version when performing the RSA key exchange.
+ RsaClientKeyExchangeVersion uint16
+
+ // RenewTicketOnResume causes the server to renew the session ticket and
+ // send a NewSessionTicket message during an abbreviated handshake.
+ RenewTicketOnResume bool
+
+ // SendClientVersion, if non-zero, causes the client to send a different
+ // TLS version in the ClientHello than the maximum supported version.
+ SendClientVersion uint16
+
+ // SkipHelloVerifyRequest causes a DTLS server to skip the
+ // HelloVerifyRequest message.
+ SkipHelloVerifyRequest bool
+
+ // ExpectFalseStart causes the server to, on full handshakes,
+ // expect the peer to False Start; the server Finished message
+ // isn't sent until we receive an application data record
+ // from the peer.
+ ExpectFalseStart bool
+
+ // SSL3RSAKeyExchange causes the client to always send an RSA
+ // ClientKeyExchange message without the two-byte length
+ // prefix, as if it were SSL3.
+ SSL3RSAKeyExchange bool
+
+ // SkipCipherVersionCheck causes the server to negotiate
+ // TLS 1.2 ciphers in earlier versions of TLS.
+ SkipCipherVersionCheck bool
+
+ // ExpectServerName, if not empty, is the hostname the client
+ // must specify in the server_name extension.
+ ExpectServerName string
+
+ // SwapNPNAndALPN switches the relative order between NPN and
+ // ALPN on the server. This is to test that server preference
+ // of ALPN works regardless of their relative order.
+ SwapNPNAndALPN bool
+
+ // AllowSessionVersionMismatch causes the server to resume sessions
+ // regardless of the version associated with the session.
+ AllowSessionVersionMismatch bool
+
+ // CorruptTicket causes a client to corrupt a session ticket before
+ // sending it in a resume handshake.
+ CorruptTicket bool
+
+ // OversizedSessionId causes the session id that is sent with a ticket
+ // resumption attempt to be too large (33 bytes).
+ OversizedSessionId bool
+
+ // RequireExtendedMasterSecret, if true, requires that the peer support
+ // the extended master secret option.
+ RequireExtendedMasterSecret bool
+
+ // NoExtendedMasterSecret causes the client and server to behave as if
+ // they didn't support an extended master secret.
+ NoExtendedMasterSecret bool
+
+ // EmptyRenegotiationInfo causes the renegotiation extension to be
+ // empty in a renegotiation handshake.
+ EmptyRenegotiationInfo bool
+
+ // BadRenegotiationInfo causes the renegotiation extension value in a
+ // renegotiation handshake to be incorrect.
+ BadRenegotiationInfo bool
+
+ // NoRenegotiationInfo causes the client to behave as if it
+ // didn't support the renegotiation info extension.
+ NoRenegotiationInfo bool
+
+ // SequenceNumberIncrement, if non-zero, causes outgoing sequence
+ // numbers in DTLS to increment by that value rather by 1. This is to
+ // stress the replay bitmap window by simulating extreme packet loss and
+ // retransmit at the record layer.
+ SequenceNumberIncrement uint64
+
+ // RSAServerKeyExchange, if true, causes the server to send a
+ // ServerKeyExchange message in the plain RSA key exchange.
+ RSAServerKeyExchange bool
+
+ // SRTPMasterKeyIdentifer, if not empty, is the SRTP MKI value that the
+ // client offers when negotiating SRTP. MKI support is still missing so
+ // the peer must still send none.
+ SRTPMasterKeyIdentifer string
+
+ // SendSRTPProtectionProfile, if non-zero, is the SRTP profile that the
+ // server sends in the ServerHello instead of the negotiated one.
+ SendSRTPProtectionProfile uint16
+
+ // NoSignatureAndHashes, if true, causes the client to omit the
+ // signature and hashes extension.
+ //
+ // For a server, it will cause an empty list to be sent in the
+ // CertificateRequest message. None the less, the configured set will
+ // still be enforced.
+ NoSignatureAndHashes bool
+
+ // RequireSameRenegoClientVersion, if true, causes the server
+ // to require that all ClientHellos match in offered version
+ // across a renego.
+ RequireSameRenegoClientVersion bool
+
+ // RequireFastradioPadding, if true, requires that ClientHello messages
+ // be at least 1000 bytes long.
+ RequireFastradioPadding bool
+
+ // ExpectInitialRecordVersion, if non-zero, is the expected
+ // version of the records before the version is determined.
+ ExpectInitialRecordVersion uint16
+
+ // MaxPacketLength, if non-zero, is the maximum acceptable size for a
+ // packet.
+ MaxPacketLength int
+
+ // SendCipherSuite, if non-zero, is the cipher suite value that the
+ // server will send in the ServerHello. This does not affect the cipher
+ // the server believes it has actually negotiated.
+ SendCipherSuite uint16
+
+ // AppDataAfterChangeCipherSpec, if not null, causes application data to
+ // be sent immediately after ChangeCipherSpec.
+ AppDataAfterChangeCipherSpec []byte
+}
+
+func (c *Config) serverInit() {
+ if c.SessionTicketsDisabled {
+ return
+ }
+
+ // If the key has already been set then we have nothing to do.
+ for _, b := range c.SessionTicketKey {
+ if b != 0 {
+ return
+ }
+ }
+
+ if _, err := io.ReadFull(c.rand(), c.SessionTicketKey[:]); err != nil {
+ c.SessionTicketsDisabled = true
+ }
+}
+
+func (c *Config) rand() io.Reader {
+ r := c.Rand
+ if r == nil {
+ return rand.Reader
+ }
+ return r
+}
+
+func (c *Config) time() time.Time {
+ t := c.Time
+ if t == nil {
+ t = time.Now
+ }
+ return t()
+}
+
+func (c *Config) cipherSuites() []uint16 {
+ s := c.CipherSuites
+ if s == nil {
+ s = defaultCipherSuites()
+ }
+ return s
+}
+
+func (c *Config) minVersion() uint16 {
+ if c == nil || c.MinVersion == 0 {
+ return minVersion
+ }
+ return c.MinVersion
+}
+
+func (c *Config) maxVersion() uint16 {
+ if c == nil || c.MaxVersion == 0 {
+ return maxVersion
+ }
+ return c.MaxVersion
+}
+
+var defaultCurvePreferences = []CurveID{CurveP256, CurveP384, CurveP521}
+
+func (c *Config) curvePreferences() []CurveID {
+ if c == nil || len(c.CurvePreferences) == 0 {
+ return defaultCurvePreferences
+ }
+ return c.CurvePreferences
+}
+
+// mutualVersion returns the protocol version to use given the advertised
+// version of the peer.
+func (c *Config) mutualVersion(vers uint16) (uint16, bool) {
+ minVersion := c.minVersion()
+ maxVersion := c.maxVersion()
+
+ if vers < minVersion {
+ return 0, false
+ }
+ if vers > maxVersion {
+ vers = maxVersion
+ }
+ return vers, true
+}
+
+// getCertificateForName returns the best certificate for the given name,
+// defaulting to the first element of c.Certificates if there are no good
+// options.
+func (c *Config) getCertificateForName(name string) *Certificate {
+ if len(c.Certificates) == 1 || c.NameToCertificate == nil {
+ // There's only one choice, so no point doing any work.
+ return &c.Certificates[0]
+ }
+
+ name = strings.ToLower(name)
+ for len(name) > 0 && name[len(name)-1] == '.' {
+ name = name[:len(name)-1]
+ }
+
+ if cert, ok := c.NameToCertificate[name]; ok {
+ return cert
+ }
+
+ // try replacing labels in the name with wildcards until we get a
+ // match.
+ labels := strings.Split(name, ".")
+ for i := range labels {
+ labels[i] = "*"
+ candidate := strings.Join(labels, ".")
+ if cert, ok := c.NameToCertificate[candidate]; ok {
+ return cert
+ }
+ }
+
+ // If nothing matches, return the first certificate.
+ return &c.Certificates[0]
+}
+
+func (c *Config) signatureAndHashesForServer() []signatureAndHash {
+ if c != nil && c.SignatureAndHashes != nil {
+ return c.SignatureAndHashes
+ }
+ return supportedClientCertSignatureAlgorithms
+}
+
+func (c *Config) signatureAndHashesForClient() []signatureAndHash {
+ if c != nil && c.SignatureAndHashes != nil {
+ return c.SignatureAndHashes
+ }
+ return supportedSKXSignatureAlgorithms
+}
+
+// BuildNameToCertificate parses c.Certificates and builds c.NameToCertificate
+// from the CommonName and SubjectAlternateName fields of each of the leaf
+// certificates.
+func (c *Config) BuildNameToCertificate() {
+ c.NameToCertificate = make(map[string]*Certificate)
+ for i := range c.Certificates {
+ cert := &c.Certificates[i]
+ x509Cert, err := x509.ParseCertificate(cert.Certificate[0])
+ if err != nil {
+ continue
+ }
+ if len(x509Cert.Subject.CommonName) > 0 {
+ c.NameToCertificate[x509Cert.Subject.CommonName] = cert
+ }
+ for _, san := range x509Cert.DNSNames {
+ c.NameToCertificate[san] = cert
+ }
+ }
+}
+
+// A Certificate is a chain of one or more certificates, leaf first.
+type Certificate struct {
+ Certificate [][]byte
+ PrivateKey crypto.PrivateKey // supported types: *rsa.PrivateKey, *ecdsa.PrivateKey
+ // OCSPStaple contains an optional OCSP response which will be served
+ // to clients that request it.
+ OCSPStaple []byte
+ // SignedCertificateTimestampList contains an optional encoded
+ // SignedCertificateTimestampList structure which will be
+ // served to clients that request it.
+ SignedCertificateTimestampList []byte
+ // Leaf is the parsed form of the leaf certificate, which may be
+ // initialized using x509.ParseCertificate to reduce per-handshake
+ // processing for TLS clients doing client authentication. If nil, the
+ // leaf certificate will be parsed as needed.
+ Leaf *x509.Certificate
+}
+
+// A TLS record.
+type record struct {
+ contentType recordType
+ major, minor uint8
+ payload []byte
+}
+
+type handshakeMessage interface {
+ marshal() []byte
+ unmarshal([]byte) bool
+}
+
+// lruSessionCache is a client or server session cache implementation
+// that uses an LRU caching strategy.
+type lruSessionCache struct {
+ sync.Mutex
+
+ m map[string]*list.Element
+ q *list.List
+ capacity int
+}
+
+type lruSessionCacheEntry struct {
+ sessionKey string
+ state interface{}
+}
+
+// Put adds the provided (sessionKey, cs) pair to the cache.
+func (c *lruSessionCache) Put(sessionKey string, cs interface{}) {
+ c.Lock()
+ defer c.Unlock()
+
+ if elem, ok := c.m[sessionKey]; ok {
+ entry := elem.Value.(*lruSessionCacheEntry)
+ entry.state = cs
+ c.q.MoveToFront(elem)
+ return
+ }
+
+ if c.q.Len() < c.capacity {
+ entry := &lruSessionCacheEntry{sessionKey, cs}
+ c.m[sessionKey] = c.q.PushFront(entry)
+ return
+ }
+
+ elem := c.q.Back()
+ entry := elem.Value.(*lruSessionCacheEntry)
+ delete(c.m, entry.sessionKey)
+ entry.sessionKey = sessionKey
+ entry.state = cs
+ c.q.MoveToFront(elem)
+ c.m[sessionKey] = elem
+}
+
+// Get returns the value associated with a given key. It returns (nil,
+// false) if no value is found.
+func (c *lruSessionCache) Get(sessionKey string) (interface{}, bool) {
+ c.Lock()
+ defer c.Unlock()
+
+ if elem, ok := c.m[sessionKey]; ok {
+ c.q.MoveToFront(elem)
+ return elem.Value.(*lruSessionCacheEntry).state, true
+ }
+ return nil, false
+}
+
+// lruClientSessionCache is a ClientSessionCache implementation that
+// uses an LRU caching strategy.
+type lruClientSessionCache struct {
+ lruSessionCache
+}
+
+func (c *lruClientSessionCache) Put(sessionKey string, cs *ClientSessionState) {
+ c.lruSessionCache.Put(sessionKey, cs)
+}
+
+func (c *lruClientSessionCache) Get(sessionKey string) (*ClientSessionState, bool) {
+ cs, ok := c.lruSessionCache.Get(sessionKey)
+ if !ok {
+ return nil, false
+ }
+ return cs.(*ClientSessionState), true
+}
+
+// lruServerSessionCache is a ServerSessionCache implementation that
+// uses an LRU caching strategy.
+type lruServerSessionCache struct {
+ lruSessionCache
+}
+
+func (c *lruServerSessionCache) Put(sessionId string, session *sessionState) {
+ c.lruSessionCache.Put(sessionId, session)
+}
+
+func (c *lruServerSessionCache) Get(sessionId string) (*sessionState, bool) {
+ cs, ok := c.lruSessionCache.Get(sessionId)
+ if !ok {
+ return nil, false
+ }
+ return cs.(*sessionState), true
+}
+
+// NewLRUClientSessionCache returns a ClientSessionCache with the given
+// capacity that uses an LRU strategy. If capacity is < 1, a default capacity
+// is used instead.
+func NewLRUClientSessionCache(capacity int) ClientSessionCache {
+ const defaultSessionCacheCapacity = 64
+
+ if capacity < 1 {
+ capacity = defaultSessionCacheCapacity
+ }
+ return &lruClientSessionCache{
+ lruSessionCache{
+ m: make(map[string]*list.Element),
+ q: list.New(),
+ capacity: capacity,
+ },
+ }
+}
+
+// NewLRUServerSessionCache returns a ServerSessionCache with the given
+// capacity that uses an LRU strategy. If capacity is < 1, a default capacity
+// is used instead.
+func NewLRUServerSessionCache(capacity int) ServerSessionCache {
+ const defaultSessionCacheCapacity = 64
+
+ if capacity < 1 {
+ capacity = defaultSessionCacheCapacity
+ }
+ return &lruServerSessionCache{
+ lruSessionCache{
+ m: make(map[string]*list.Element),
+ q: list.New(),
+ capacity: capacity,
+ },
+ }
+}
+
+// TODO(jsing): Make these available to both crypto/x509 and crypto/tls.
+type dsaSignature struct {
+ R, S *big.Int
+}
+
+type ecdsaSignature dsaSignature
+
+var emptyConfig Config
+
+func defaultConfig() *Config {
+ return &emptyConfig
+}
+
+var (
+ once sync.Once
+ varDefaultCipherSuites []uint16
+)
+
+func defaultCipherSuites() []uint16 {
+ once.Do(initDefaultCipherSuites)
+ return varDefaultCipherSuites
+}
+
+func initDefaultCipherSuites() {
+ for _, suite := range cipherSuites {
+ if suite.flags&suitePSK == 0 {
+ varDefaultCipherSuites = append(varDefaultCipherSuites, suite.id)
+ }
+ }
+}
+
+func unexpectedMessageError(wanted, got interface{}) error {
+ return fmt.Errorf("tls: received unexpected handshake message of type %T when waiting for %T", got, wanted)
+}
+
+func isSupportedSignatureAndHash(sigHash signatureAndHash, sigHashes []signatureAndHash) bool {
+ for _, s := range sigHashes {
+ if s == sigHash {
+ return true
+ }
+ }
+ return false
+}
diff --git a/src/ssl/test/runner/conn.go b/src/ssl/test/runner/conn.go
new file mode 100644
index 0000000..d4a6817
--- /dev/null
+++ b/src/ssl/test/runner/conn.go
@@ -0,0 +1,1229 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// TLS low level connection and record layer
+
+package main
+
+import (
+ "bytes"
+ "crypto/cipher"
+ "crypto/ecdsa"
+ "crypto/subtle"
+ "crypto/x509"
+ "errors"
+ "fmt"
+ "io"
+ "net"
+ "sync"
+ "time"
+)
+
+// A Conn represents a secured connection.
+// It implements the net.Conn interface.
+type Conn struct {
+ // constant
+ conn net.Conn
+ isDTLS bool
+ isClient bool
+
+ // constant after handshake; protected by handshakeMutex
+ handshakeMutex sync.Mutex // handshakeMutex < in.Mutex, out.Mutex, errMutex
+ handshakeErr error // error resulting from handshake
+ vers uint16 // TLS version
+ haveVers bool // version has been negotiated
+ config *Config // configuration passed to constructor
+ handshakeComplete bool
+ didResume bool // whether this connection was a session resumption
+ extendedMasterSecret bool // whether this session used an extended master secret
+ cipherSuite uint16
+ ocspResponse []byte // stapled OCSP response
+ peerCertificates []*x509.Certificate
+ // verifiedChains contains the certificate chains that we built, as
+ // opposed to the ones presented by the server.
+ verifiedChains [][]*x509.Certificate
+ // serverName contains the server name indicated by the client, if any.
+ serverName string
+
+ clientProtocol string
+ clientProtocolFallback bool
+ usedALPN bool
+
+ // verify_data values for the renegotiation extension.
+ clientVerify []byte
+ serverVerify []byte
+
+ channelID *ecdsa.PublicKey
+
+ srtpProtectionProfile uint16
+
+ clientVersion uint16
+
+ // input/output
+ in, out halfConn // in.Mutex < out.Mutex
+ rawInput *block // raw input, right off the wire
+ input *block // application record waiting to be read
+ hand bytes.Buffer // handshake record waiting to be read
+
+ // DTLS state
+ sendHandshakeSeq uint16
+ recvHandshakeSeq uint16
+ handMsg []byte // pending assembled handshake message
+ handMsgLen int // handshake message length, not including the header
+
+ tmp [16]byte
+}
+
+func (c *Conn) init() {
+ c.in.isDTLS = c.isDTLS
+ c.out.isDTLS = c.isDTLS
+ c.in.config = c.config
+ c.out.config = c.config
+}
+
+// Access to net.Conn methods.
+// Cannot just embed net.Conn because that would
+// export the struct field too.
+
+// LocalAddr returns the local network address.
+func (c *Conn) LocalAddr() net.Addr {
+ return c.conn.LocalAddr()
+}
+
+// RemoteAddr returns the remote network address.
+func (c *Conn) RemoteAddr() net.Addr {
+ return c.conn.RemoteAddr()
+}
+
+// SetDeadline sets the read and write deadlines associated with the connection.
+// A zero value for t means Read and Write will not time out.
+// After a Write has timed out, the TLS state is corrupt and all future writes will return the same error.
+func (c *Conn) SetDeadline(t time.Time) error {
+ return c.conn.SetDeadline(t)
+}
+
+// SetReadDeadline sets the read deadline on the underlying connection.
+// A zero value for t means Read will not time out.
+func (c *Conn) SetReadDeadline(t time.Time) error {
+ return c.conn.SetReadDeadline(t)
+}
+
+// SetWriteDeadline sets the write deadline on the underlying conneciton.
+// A zero value for t means Write will not time out.
+// After a Write has timed out, the TLS state is corrupt and all future writes will return the same error.
+func (c *Conn) SetWriteDeadline(t time.Time) error {
+ return c.conn.SetWriteDeadline(t)
+}
+
+// A halfConn represents one direction of the record layer
+// connection, either sending or receiving.
+type halfConn struct {
+ sync.Mutex
+
+ err error // first permanent error
+ version uint16 // protocol version
+ isDTLS bool
+ cipher interface{} // cipher algorithm
+ mac macFunction
+ seq [8]byte // 64-bit sequence number
+ bfree *block // list of free blocks
+
+ nextCipher interface{} // next encryption state
+ nextMac macFunction // next MAC algorithm
+
+ // used to save allocating a new buffer for each MAC.
+ inDigestBuf, outDigestBuf []byte
+
+ config *Config
+}
+
+func (hc *halfConn) setErrorLocked(err error) error {
+ hc.err = err
+ return err
+}
+
+func (hc *halfConn) error() error {
+ // This should be locked, but I've removed it for the renegotiation
+ // tests since we don't concurrently read and write the same tls.Conn
+ // in any case during testing.
+ err := hc.err
+ return err
+}
+
+// prepareCipherSpec sets the encryption and MAC states
+// that a subsequent changeCipherSpec will use.
+func (hc *halfConn) prepareCipherSpec(version uint16, cipher interface{}, mac macFunction) {
+ hc.version = version
+ hc.nextCipher = cipher
+ hc.nextMac = mac
+}
+
+// changeCipherSpec changes the encryption and MAC states
+// to the ones previously passed to prepareCipherSpec.
+func (hc *halfConn) changeCipherSpec(config *Config) error {
+ if hc.nextCipher == nil {
+ return alertInternalError
+ }
+ hc.cipher = hc.nextCipher
+ hc.mac = hc.nextMac
+ hc.nextCipher = nil
+ hc.nextMac = nil
+ hc.config = config
+ hc.incEpoch()
+ return nil
+}
+
+// incSeq increments the sequence number.
+func (hc *halfConn) incSeq(isOutgoing bool) {
+ limit := 0
+ increment := uint64(1)
+ if hc.isDTLS {
+ // Increment up to the epoch in DTLS.
+ limit = 2
+
+ if isOutgoing && hc.config.Bugs.SequenceNumberIncrement != 0 {
+ increment = hc.config.Bugs.SequenceNumberIncrement
+ }
+ }
+ for i := 7; i >= limit; i-- {
+ increment += uint64(hc.seq[i])
+ hc.seq[i] = byte(increment)
+ increment >>= 8
+ }
+
+ // Not allowed to let sequence number wrap.
+ // Instead, must renegotiate before it does.
+ // Not likely enough to bother.
+ if increment != 0 {
+ panic("TLS: sequence number wraparound")
+ }
+}
+
+// incEpoch resets the sequence number. In DTLS, it increments the
+// epoch half of the sequence number.
+func (hc *halfConn) incEpoch() {
+ limit := 0
+ if hc.isDTLS {
+ for i := 1; i >= 0; i-- {
+ hc.seq[i]++
+ if hc.seq[i] != 0 {
+ break
+ }
+ if i == 0 {
+ panic("TLS: epoch number wraparound")
+ }
+ }
+ limit = 2
+ }
+ seq := hc.seq[limit:]
+ for i := range seq {
+ seq[i] = 0
+ }
+}
+
+func (hc *halfConn) recordHeaderLen() int {
+ if hc.isDTLS {
+ return dtlsRecordHeaderLen
+ }
+ return tlsRecordHeaderLen
+}
+
+// removePadding returns an unpadded slice, in constant time, which is a prefix
+// of the input. It also returns a byte which is equal to 255 if the padding
+// was valid and 0 otherwise. See RFC 2246, section 6.2.3.2
+func removePadding(payload []byte) ([]byte, byte) {
+ if len(payload) < 1 {
+ return payload, 0
+ }
+
+ paddingLen := payload[len(payload)-1]
+ t := uint(len(payload)-1) - uint(paddingLen)
+ // if len(payload) >= (paddingLen - 1) then the MSB of t is zero
+ good := byte(int32(^t) >> 31)
+
+ toCheck := 255 // the maximum possible padding length
+ // The length of the padded data is public, so we can use an if here
+ if toCheck+1 > len(payload) {
+ toCheck = len(payload) - 1
+ }
+
+ for i := 0; i < toCheck; i++ {
+ t := uint(paddingLen) - uint(i)
+ // if i <= paddingLen then the MSB of t is zero
+ mask := byte(int32(^t) >> 31)
+ b := payload[len(payload)-1-i]
+ good &^= mask&paddingLen ^ mask&b
+ }
+
+ // We AND together the bits of good and replicate the result across
+ // all the bits.
+ good &= good << 4
+ good &= good << 2
+ good &= good << 1
+ good = uint8(int8(good) >> 7)
+
+ toRemove := good&paddingLen + 1
+ return payload[:len(payload)-int(toRemove)], good
+}
+
+// removePaddingSSL30 is a replacement for removePadding in the case that the
+// protocol version is SSLv3. In this version, the contents of the padding
+// are random and cannot be checked.
+func removePaddingSSL30(payload []byte) ([]byte, byte) {
+ if len(payload) < 1 {
+ return payload, 0
+ }
+
+ paddingLen := int(payload[len(payload)-1]) + 1
+ if paddingLen > len(payload) {
+ return payload, 0
+ }
+
+ return payload[:len(payload)-paddingLen], 255
+}
+
+func roundUp(a, b int) int {
+ return a + (b-a%b)%b
+}
+
+// cbcMode is an interface for block ciphers using cipher block chaining.
+type cbcMode interface {
+ cipher.BlockMode
+ SetIV([]byte)
+}
+
+// decrypt checks and strips the mac and decrypts the data in b. Returns a
+// success boolean, the number of bytes to skip from the start of the record in
+// order to get the application payload, and an optional alert value.
+func (hc *halfConn) decrypt(b *block) (ok bool, prefixLen int, alertValue alert) {
+ recordHeaderLen := hc.recordHeaderLen()
+
+ // pull out payload
+ payload := b.data[recordHeaderLen:]
+
+ macSize := 0
+ if hc.mac != nil {
+ macSize = hc.mac.Size()
+ }
+
+ paddingGood := byte(255)
+ explicitIVLen := 0
+
+ seq := hc.seq[:]
+ if hc.isDTLS {
+ // DTLS sequence numbers are explicit.
+ seq = b.data[3:11]
+ }
+
+ // decrypt
+ if hc.cipher != nil {
+ switch c := hc.cipher.(type) {
+ case cipher.Stream:
+ c.XORKeyStream(payload, payload)
+ case cipher.AEAD:
+ explicitIVLen = 8
+ if len(payload) < explicitIVLen {
+ return false, 0, alertBadRecordMAC
+ }
+ nonce := payload[:8]
+ payload = payload[8:]
+
+ var additionalData [13]byte
+ copy(additionalData[:], seq)
+ copy(additionalData[8:], b.data[:3])
+ n := len(payload) - c.Overhead()
+ additionalData[11] = byte(n >> 8)
+ additionalData[12] = byte(n)
+ var err error
+ payload, err = c.Open(payload[:0], nonce, payload, additionalData[:])
+ if err != nil {
+ return false, 0, alertBadRecordMAC
+ }
+ b.resize(recordHeaderLen + explicitIVLen + len(payload))
+ case cbcMode:
+ blockSize := c.BlockSize()
+ if hc.version >= VersionTLS11 || hc.isDTLS {
+ explicitIVLen = blockSize
+ }
+
+ if len(payload)%blockSize != 0 || len(payload) < roundUp(explicitIVLen+macSize+1, blockSize) {
+ return false, 0, alertBadRecordMAC
+ }
+
+ if explicitIVLen > 0 {
+ c.SetIV(payload[:explicitIVLen])
+ payload = payload[explicitIVLen:]
+ }
+ c.CryptBlocks(payload, payload)
+ if hc.version == VersionSSL30 {
+ payload, paddingGood = removePaddingSSL30(payload)
+ } else {
+ payload, paddingGood = removePadding(payload)
+ }
+ b.resize(recordHeaderLen + explicitIVLen + len(payload))
+
+ // note that we still have a timing side-channel in the
+ // MAC check, below. An attacker can align the record
+ // so that a correct padding will cause one less hash
+ // block to be calculated. Then they can iteratively
+ // decrypt a record by breaking each byte. See
+ // "Password Interception in a SSL/TLS Channel", Brice
+ // Canvel et al.
+ //
+ // However, our behavior matches OpenSSL, so we leak
+ // only as much as they do.
+ default:
+ panic("unknown cipher type")
+ }
+ }
+
+ // check, strip mac
+ if hc.mac != nil {
+ if len(payload) < macSize {
+ return false, 0, alertBadRecordMAC
+ }
+
+ // strip mac off payload, b.data
+ n := len(payload) - macSize
+ b.data[recordHeaderLen-2] = byte(n >> 8)
+ b.data[recordHeaderLen-1] = byte(n)
+ b.resize(recordHeaderLen + explicitIVLen + n)
+ remoteMAC := payload[n:]
+ localMAC := hc.mac.MAC(hc.inDigestBuf, seq, b.data[:3], b.data[recordHeaderLen-2:recordHeaderLen], payload[:n])
+
+ if subtle.ConstantTimeCompare(localMAC, remoteMAC) != 1 || paddingGood != 255 {
+ return false, 0, alertBadRecordMAC
+ }
+ hc.inDigestBuf = localMAC
+ }
+ hc.incSeq(false)
+
+ return true, recordHeaderLen + explicitIVLen, 0
+}
+
+// padToBlockSize calculates the needed padding block, if any, for a payload.
+// On exit, prefix aliases payload and extends to the end of the last full
+// block of payload. finalBlock is a fresh slice which contains the contents of
+// any suffix of payload as well as the needed padding to make finalBlock a
+// full block.
+func padToBlockSize(payload []byte, blockSize int, config *Config) (prefix, finalBlock []byte) {
+ overrun := len(payload) % blockSize
+ prefix = payload[:len(payload)-overrun]
+
+ paddingLen := blockSize - overrun
+ finalSize := blockSize
+ if config.Bugs.MaxPadding {
+ for paddingLen+blockSize <= 256 {
+ paddingLen += blockSize
+ }
+ finalSize = 256
+ }
+ finalBlock = make([]byte, finalSize)
+ for i := range finalBlock {
+ finalBlock[i] = byte(paddingLen - 1)
+ }
+ if config.Bugs.PaddingFirstByteBad || config.Bugs.PaddingFirstByteBadIf255 && paddingLen == 256 {
+ finalBlock[overrun] ^= 0xff
+ }
+ copy(finalBlock, payload[len(payload)-overrun:])
+ return
+}
+
+// encrypt encrypts and macs the data in b.
+func (hc *halfConn) encrypt(b *block, explicitIVLen int) (bool, alert) {
+ recordHeaderLen := hc.recordHeaderLen()
+
+ // mac
+ if hc.mac != nil {
+ mac := hc.mac.MAC(hc.outDigestBuf, hc.seq[0:], b.data[:3], b.data[recordHeaderLen-2:recordHeaderLen], b.data[recordHeaderLen+explicitIVLen:])
+
+ n := len(b.data)
+ b.resize(n + len(mac))
+ copy(b.data[n:], mac)
+ hc.outDigestBuf = mac
+ }
+
+ payload := b.data[recordHeaderLen:]
+
+ // encrypt
+ if hc.cipher != nil {
+ switch c := hc.cipher.(type) {
+ case cipher.Stream:
+ c.XORKeyStream(payload, payload)
+ case cipher.AEAD:
+ payloadLen := len(b.data) - recordHeaderLen - explicitIVLen
+ b.resize(len(b.data) + c.Overhead())
+ nonce := b.data[recordHeaderLen : recordHeaderLen+explicitIVLen]
+ payload := b.data[recordHeaderLen+explicitIVLen:]
+ payload = payload[:payloadLen]
+
+ var additionalData [13]byte
+ copy(additionalData[:], hc.seq[:])
+ copy(additionalData[8:], b.data[:3])
+ additionalData[11] = byte(payloadLen >> 8)
+ additionalData[12] = byte(payloadLen)
+
+ c.Seal(payload[:0], nonce, payload, additionalData[:])
+ case cbcMode:
+ blockSize := c.BlockSize()
+ if explicitIVLen > 0 {
+ c.SetIV(payload[:explicitIVLen])
+ payload = payload[explicitIVLen:]
+ }
+ prefix, finalBlock := padToBlockSize(payload, blockSize, hc.config)
+ b.resize(recordHeaderLen + explicitIVLen + len(prefix) + len(finalBlock))
+ c.CryptBlocks(b.data[recordHeaderLen+explicitIVLen:], prefix)
+ c.CryptBlocks(b.data[recordHeaderLen+explicitIVLen+len(prefix):], finalBlock)
+ default:
+ panic("unknown cipher type")
+ }
+ }
+
+ // update length to include MAC and any block padding needed.
+ n := len(b.data) - recordHeaderLen
+ b.data[recordHeaderLen-2] = byte(n >> 8)
+ b.data[recordHeaderLen-1] = byte(n)
+ hc.incSeq(true)
+
+ return true, 0
+}
+
+// A block is a simple data buffer.
+type block struct {
+ data []byte
+ off int // index for Read
+ link *block
+}
+
+// resize resizes block to be n bytes, growing if necessary.
+func (b *block) resize(n int) {
+ if n > cap(b.data) {
+ b.reserve(n)
+ }
+ b.data = b.data[0:n]
+}
+
+// reserve makes sure that block contains a capacity of at least n bytes.
+func (b *block) reserve(n int) {
+ if cap(b.data) >= n {
+ return
+ }
+ m := cap(b.data)
+ if m == 0 {
+ m = 1024
+ }
+ for m < n {
+ m *= 2
+ }
+ data := make([]byte, len(b.data), m)
+ copy(data, b.data)
+ b.data = data
+}
+
+// readFromUntil reads from r into b until b contains at least n bytes
+// or else returns an error.
+func (b *block) readFromUntil(r io.Reader, n int) error {
+ // quick case
+ if len(b.data) >= n {
+ return nil
+ }
+
+ // read until have enough.
+ b.reserve(n)
+ for {
+ m, err := r.Read(b.data[len(b.data):cap(b.data)])
+ b.data = b.data[0 : len(b.data)+m]
+ if len(b.data) >= n {
+ // TODO(bradfitz,agl): slightly suspicious
+ // that we're throwing away r.Read's err here.
+ break
+ }
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (b *block) Read(p []byte) (n int, err error) {
+ n = copy(p, b.data[b.off:])
+ b.off += n
+ return
+}
+
+// newBlock allocates a new block, from hc's free list if possible.
+func (hc *halfConn) newBlock() *block {
+ b := hc.bfree
+ if b == nil {
+ return new(block)
+ }
+ hc.bfree = b.link
+ b.link = nil
+ b.resize(0)
+ return b
+}
+
+// freeBlock returns a block to hc's free list.
+// The protocol is such that each side only has a block or two on
+// its free list at a time, so there's no need to worry about
+// trimming the list, etc.
+func (hc *halfConn) freeBlock(b *block) {
+ b.link = hc.bfree
+ hc.bfree = b
+}
+
+// splitBlock splits a block after the first n bytes,
+// returning a block with those n bytes and a
+// block with the remainder. the latter may be nil.
+func (hc *halfConn) splitBlock(b *block, n int) (*block, *block) {
+ if len(b.data) <= n {
+ return b, nil
+ }
+ bb := hc.newBlock()
+ bb.resize(len(b.data) - n)
+ copy(bb.data, b.data[n:])
+ b.data = b.data[0:n]
+ return b, bb
+}
+
+func (c *Conn) doReadRecord(want recordType) (recordType, *block, error) {
+ if c.isDTLS {
+ return c.dtlsDoReadRecord(want)
+ }
+
+ recordHeaderLen := tlsRecordHeaderLen
+
+ if c.rawInput == nil {
+ c.rawInput = c.in.newBlock()
+ }
+ b := c.rawInput
+
+ // Read header, payload.
+ if err := b.readFromUntil(c.conn, recordHeaderLen); err != nil {
+ // RFC suggests that EOF without an alertCloseNotify is
+ // an error, but popular web sites seem to do this,
+ // so we can't make it an error.
+ // if err == io.EOF {
+ // err = io.ErrUnexpectedEOF
+ // }
+ if e, ok := err.(net.Error); !ok || !e.Temporary() {
+ c.in.setErrorLocked(err)
+ }
+ return 0, nil, err
+ }
+ typ := recordType(b.data[0])
+
+ // No valid TLS record has a type of 0x80, however SSLv2 handshakes
+ // start with a uint16 length where the MSB is set and the first record
+ // is always < 256 bytes long. Therefore typ == 0x80 strongly suggests
+ // an SSLv2 client.
+ if want == recordTypeHandshake && typ == 0x80 {
+ c.sendAlert(alertProtocolVersion)
+ return 0, nil, c.in.setErrorLocked(errors.New("tls: unsupported SSLv2 handshake received"))
+ }
+
+ vers := uint16(b.data[1])<<8 | uint16(b.data[2])
+ n := int(b.data[3])<<8 | int(b.data[4])
+ if c.haveVers {
+ if vers != c.vers {
+ c.sendAlert(alertProtocolVersion)
+ return 0, nil, c.in.setErrorLocked(fmt.Errorf("tls: received record with version %x when expecting version %x", vers, c.vers))
+ }
+ } else {
+ if expect := c.config.Bugs.ExpectInitialRecordVersion; expect != 0 && vers != expect {
+ c.sendAlert(alertProtocolVersion)
+ return 0, nil, c.in.setErrorLocked(fmt.Errorf("tls: received record with version %x when expecting version %x", vers, expect))
+ }
+ }
+ if n > maxCiphertext {
+ c.sendAlert(alertRecordOverflow)
+ return 0, nil, c.in.setErrorLocked(fmt.Errorf("tls: oversized record received with length %d", n))
+ }
+ if !c.haveVers {
+ // First message, be extra suspicious:
+ // this might not be a TLS client.
+ // Bail out before reading a full 'body', if possible.
+ // The current max version is 3.1.
+ // If the version is >= 16.0, it's probably not real.
+ // Similarly, a clientHello message encodes in
+ // well under a kilobyte. If the length is >= 12 kB,
+ // it's probably not real.
+ if (typ != recordTypeAlert && typ != want) || vers >= 0x1000 || n >= 0x3000 {
+ c.sendAlert(alertUnexpectedMessage)
+ return 0, nil, c.in.setErrorLocked(fmt.Errorf("tls: first record does not look like a TLS handshake"))
+ }
+ }
+ if err := b.readFromUntil(c.conn, recordHeaderLen+n); err != nil {
+ if err == io.EOF {
+ err = io.ErrUnexpectedEOF
+ }
+ if e, ok := err.(net.Error); !ok || !e.Temporary() {
+ c.in.setErrorLocked(err)
+ }
+ return 0, nil, err
+ }
+
+ // Process message.
+ b, c.rawInput = c.in.splitBlock(b, recordHeaderLen+n)
+ ok, off, err := c.in.decrypt(b)
+ if !ok {
+ c.in.setErrorLocked(c.sendAlert(err))
+ }
+ b.off = off
+ return typ, b, nil
+}
+
+// readRecord reads the next TLS record from the connection
+// and updates the record layer state.
+// c.in.Mutex <= L; c.input == nil.
+func (c *Conn) readRecord(want recordType) error {
+ // Caller must be in sync with connection:
+ // handshake data if handshake not yet completed,
+ // else application data.
+ switch want {
+ default:
+ c.sendAlert(alertInternalError)
+ return c.in.setErrorLocked(errors.New("tls: unknown record type requested"))
+ case recordTypeHandshake, recordTypeChangeCipherSpec:
+ if c.handshakeComplete {
+ c.sendAlert(alertInternalError)
+ return c.in.setErrorLocked(errors.New("tls: handshake or ChangeCipherSpec requested after handshake complete"))
+ }
+ case recordTypeApplicationData:
+ if !c.handshakeComplete && !c.config.Bugs.ExpectFalseStart {
+ c.sendAlert(alertInternalError)
+ return c.in.setErrorLocked(errors.New("tls: application data record requested before handshake complete"))
+ }
+ }
+
+Again:
+ typ, b, err := c.doReadRecord(want)
+ if err != nil {
+ return err
+ }
+ data := b.data[b.off:]
+ if len(data) > maxPlaintext {
+ err := c.sendAlert(alertRecordOverflow)
+ c.in.freeBlock(b)
+ return c.in.setErrorLocked(err)
+ }
+
+ switch typ {
+ default:
+ c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage))
+
+ case recordTypeAlert:
+ if len(data) != 2 {
+ c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage))
+ break
+ }
+ if alert(data[1]) == alertCloseNotify {
+ c.in.setErrorLocked(io.EOF)
+ break
+ }
+ switch data[0] {
+ case alertLevelWarning:
+ // drop on the floor
+ c.in.freeBlock(b)
+ goto Again
+ case alertLevelError:
+ c.in.setErrorLocked(&net.OpError{Op: "remote error", Err: alert(data[1])})
+ default:
+ c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage))
+ }
+
+ case recordTypeChangeCipherSpec:
+ if typ != want || len(data) != 1 || data[0] != 1 {
+ c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage))
+ break
+ }
+ err := c.in.changeCipherSpec(c.config)
+ if err != nil {
+ c.in.setErrorLocked(c.sendAlert(err.(alert)))
+ }
+
+ case recordTypeApplicationData:
+ if typ != want {
+ c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage))
+ break
+ }
+ c.input = b
+ b = nil
+
+ case recordTypeHandshake:
+ // TODO(rsc): Should at least pick off connection close.
+ if typ != want {
+ // A client might need to process a HelloRequest from
+ // the server, thus receiving a handshake message when
+ // application data is expected is ok. Moreover, a DTLS
+ // peer who sends Finished second may retransmit the
+ // final leg. BoringSSL retrainsmits on an internal
+ // timer, so this may also occur in test code.
+ if !c.isClient && !c.isDTLS {
+ return c.in.setErrorLocked(c.sendAlert(alertNoRenegotiation))
+ }
+ }
+ c.hand.Write(data)
+ }
+
+ if b != nil {
+ c.in.freeBlock(b)
+ }
+ return c.in.err
+}
+
+// sendAlert sends a TLS alert message.
+// c.out.Mutex <= L.
+func (c *Conn) sendAlertLocked(err alert) error {
+ switch err {
+ case alertNoRenegotiation, alertCloseNotify:
+ c.tmp[0] = alertLevelWarning
+ default:
+ c.tmp[0] = alertLevelError
+ }
+ c.tmp[1] = byte(err)
+ if c.config.Bugs.FragmentAlert {
+ c.writeRecord(recordTypeAlert, c.tmp[0:1])
+ c.writeRecord(recordTypeAlert, c.tmp[1:2])
+ } else {
+ c.writeRecord(recordTypeAlert, c.tmp[0:2])
+ }
+ // closeNotify is a special case in that it isn't an error:
+ if err != alertCloseNotify {
+ return c.out.setErrorLocked(&net.OpError{Op: "local error", Err: err})
+ }
+ return nil
+}
+
+// sendAlert sends a TLS alert message.
+// L < c.out.Mutex.
+func (c *Conn) sendAlert(err alert) error {
+ c.out.Lock()
+ defer c.out.Unlock()
+ return c.sendAlertLocked(err)
+}
+
+// writeV2Record writes a record for a V2ClientHello.
+func (c *Conn) writeV2Record(data []byte) (n int, err error) {
+ record := make([]byte, 2+len(data))
+ record[0] = uint8(len(data)>>8) | 0x80
+ record[1] = uint8(len(data))
+ copy(record[2:], data)
+ return c.conn.Write(record)
+}
+
+// writeRecord writes a TLS record with the given type and payload
+// to the connection and updates the record layer state.
+// c.out.Mutex <= L.
+func (c *Conn) writeRecord(typ recordType, data []byte) (n int, err error) {
+ if c.isDTLS {
+ return c.dtlsWriteRecord(typ, data)
+ }
+
+ recordHeaderLen := tlsRecordHeaderLen
+ b := c.out.newBlock()
+ first := true
+ isClientHello := typ == recordTypeHandshake && len(data) > 0 && data[0] == typeClientHello
+ for len(data) > 0 {
+ m := len(data)
+ if m > maxPlaintext {
+ m = maxPlaintext
+ }
+ if typ == recordTypeHandshake && c.config.Bugs.MaxHandshakeRecordLength > 0 && m > c.config.Bugs.MaxHandshakeRecordLength {
+ m = c.config.Bugs.MaxHandshakeRecordLength
+ // By default, do not fragment the client_version or
+ // server_version, which are located in the first 6
+ // bytes.
+ if first && isClientHello && !c.config.Bugs.FragmentClientVersion && m < 6 {
+ m = 6
+ }
+ }
+ explicitIVLen := 0
+ explicitIVIsSeq := false
+ first = false
+
+ var cbc cbcMode
+ if c.out.version >= VersionTLS11 {
+ var ok bool
+ if cbc, ok = c.out.cipher.(cbcMode); ok {
+ explicitIVLen = cbc.BlockSize()
+ }
+ }
+ if explicitIVLen == 0 {
+ if _, ok := c.out.cipher.(cipher.AEAD); ok {
+ explicitIVLen = 8
+ // The AES-GCM construction in TLS has an
+ // explicit nonce so that the nonce can be
+ // random. However, the nonce is only 8 bytes
+ // which is too small for a secure, random
+ // nonce. Therefore we use the sequence number
+ // as the nonce.
+ explicitIVIsSeq = true
+ }
+ }
+ b.resize(recordHeaderLen + explicitIVLen + m)
+ b.data[0] = byte(typ)
+ vers := c.vers
+ if vers == 0 {
+ // Some TLS servers fail if the record version is
+ // greater than TLS 1.0 for the initial ClientHello.
+ vers = VersionTLS10
+ }
+ b.data[1] = byte(vers >> 8)
+ b.data[2] = byte(vers)
+ b.data[3] = byte(m >> 8)
+ b.data[4] = byte(m)
+ if explicitIVLen > 0 {
+ explicitIV := b.data[recordHeaderLen : recordHeaderLen+explicitIVLen]
+ if explicitIVIsSeq {
+ copy(explicitIV, c.out.seq[:])
+ } else {
+ if _, err = io.ReadFull(c.config.rand(), explicitIV); err != nil {
+ break
+ }
+ }
+ }
+ copy(b.data[recordHeaderLen+explicitIVLen:], data)
+ c.out.encrypt(b, explicitIVLen)
+ _, err = c.conn.Write(b.data)
+ if err != nil {
+ break
+ }
+ n += m
+ data = data[m:]
+ }
+ c.out.freeBlock(b)
+
+ if typ == recordTypeChangeCipherSpec {
+ err = c.out.changeCipherSpec(c.config)
+ if err != nil {
+ // Cannot call sendAlert directly,
+ // because we already hold c.out.Mutex.
+ c.tmp[0] = alertLevelError
+ c.tmp[1] = byte(err.(alert))
+ c.writeRecord(recordTypeAlert, c.tmp[0:2])
+ return n, c.out.setErrorLocked(&net.OpError{Op: "local error", Err: err})
+ }
+ }
+ return
+}
+
+func (c *Conn) doReadHandshake() ([]byte, error) {
+ if c.isDTLS {
+ return c.dtlsDoReadHandshake()
+ }
+
+ for c.hand.Len() < 4 {
+ if err := c.in.err; err != nil {
+ return nil, err
+ }
+ if err := c.readRecord(recordTypeHandshake); err != nil {
+ return nil, err
+ }
+ }
+
+ data := c.hand.Bytes()
+ n := int(data[1])<<16 | int(data[2])<<8 | int(data[3])
+ if n > maxHandshake {
+ return nil, c.in.setErrorLocked(c.sendAlert(alertInternalError))
+ }
+ for c.hand.Len() < 4+n {
+ if err := c.in.err; err != nil {
+ return nil, err
+ }
+ if err := c.readRecord(recordTypeHandshake); err != nil {
+ return nil, err
+ }
+ }
+ return c.hand.Next(4 + n), nil
+}
+
+// readHandshake reads the next handshake message from
+// the record layer.
+// c.in.Mutex < L; c.out.Mutex < L.
+func (c *Conn) readHandshake() (interface{}, error) {
+ data, err := c.doReadHandshake()
+ if err != nil {
+ return nil, err
+ }
+
+ var m handshakeMessage
+ switch data[0] {
+ case typeHelloRequest:
+ m = new(helloRequestMsg)
+ case typeClientHello:
+ m = &clientHelloMsg{
+ isDTLS: c.isDTLS,
+ }
+ case typeServerHello:
+ m = &serverHelloMsg{
+ isDTLS: c.isDTLS,
+ }
+ case typeNewSessionTicket:
+ m = new(newSessionTicketMsg)
+ case typeCertificate:
+ m = new(certificateMsg)
+ case typeCertificateRequest:
+ m = &certificateRequestMsg{
+ hasSignatureAndHash: c.vers >= VersionTLS12,
+ }
+ case typeCertificateStatus:
+ m = new(certificateStatusMsg)
+ case typeServerKeyExchange:
+ m = new(serverKeyExchangeMsg)
+ case typeServerHelloDone:
+ m = new(serverHelloDoneMsg)
+ case typeClientKeyExchange:
+ m = new(clientKeyExchangeMsg)
+ case typeCertificateVerify:
+ m = &certificateVerifyMsg{
+ hasSignatureAndHash: c.vers >= VersionTLS12,
+ }
+ case typeNextProtocol:
+ m = new(nextProtoMsg)
+ case typeFinished:
+ m = new(finishedMsg)
+ case typeHelloVerifyRequest:
+ m = new(helloVerifyRequestMsg)
+ case typeEncryptedExtensions:
+ m = new(encryptedExtensionsMsg)
+ default:
+ return nil, c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage))
+ }
+
+ // The handshake message unmarshallers
+ // expect to be able to keep references to data,
+ // so pass in a fresh copy that won't be overwritten.
+ data = append([]byte(nil), data...)
+
+ if !m.unmarshal(data) {
+ return nil, c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage))
+ }
+ return m, nil
+}
+
+// Write writes data to the connection.
+func (c *Conn) Write(b []byte) (int, error) {
+ if err := c.Handshake(); err != nil {
+ return 0, err
+ }
+
+ c.out.Lock()
+ defer c.out.Unlock()
+
+ if err := c.out.err; err != nil {
+ return 0, err
+ }
+
+ if !c.handshakeComplete {
+ return 0, alertInternalError
+ }
+
+ if c.config.Bugs.SendSpuriousAlert {
+ c.sendAlertLocked(alertRecordOverflow)
+ }
+
+ // SSL 3.0 and TLS 1.0 are susceptible to a chosen-plaintext
+ // attack when using block mode ciphers due to predictable IVs.
+ // This can be prevented by splitting each Application Data
+ // record into two records, effectively randomizing the IV.
+ //
+ // http://www.openssl.org/~bodo/tls-cbc.txt
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=665814
+ // http://www.imperialviolet.org/2012/01/15/beastfollowup.html
+
+ var m int
+ if len(b) > 1 && c.vers <= VersionTLS10 && !c.isDTLS {
+ if _, ok := c.out.cipher.(cipher.BlockMode); ok {
+ n, err := c.writeRecord(recordTypeApplicationData, b[:1])
+ if err != nil {
+ return n, c.out.setErrorLocked(err)
+ }
+ m, b = 1, b[1:]
+ }
+ }
+
+ n, err := c.writeRecord(recordTypeApplicationData, b)
+ return n + m, c.out.setErrorLocked(err)
+}
+
+func (c *Conn) handleRenegotiation() error {
+ c.handshakeComplete = false
+ if !c.isClient {
+ panic("renegotiation should only happen for a client")
+ }
+
+ msg, err := c.readHandshake()
+ if err != nil {
+ return err
+ }
+ _, ok := msg.(*helloRequestMsg)
+ if !ok {
+ c.sendAlert(alertUnexpectedMessage)
+ return alertUnexpectedMessage
+ }
+
+ return c.Handshake()
+}
+
+func (c *Conn) Renegotiate() error {
+ if !c.isClient {
+ helloReq := new(helloRequestMsg)
+ c.writeRecord(recordTypeHandshake, helloReq.marshal())
+ }
+
+ c.handshakeComplete = false
+ return c.Handshake()
+}
+
+// Read can be made to time out and return a net.Error with Timeout() == true
+// after a fixed time limit; see SetDeadline and SetReadDeadline.
+func (c *Conn) Read(b []byte) (n int, err error) {
+ if err = c.Handshake(); err != nil {
+ return
+ }
+
+ c.in.Lock()
+ defer c.in.Unlock()
+
+ // Some OpenSSL servers send empty records in order to randomize the
+ // CBC IV. So this loop ignores a limited number of empty records.
+ const maxConsecutiveEmptyRecords = 100
+ for emptyRecordCount := 0; emptyRecordCount <= maxConsecutiveEmptyRecords; emptyRecordCount++ {
+ for c.input == nil && c.in.err == nil {
+ if err := c.readRecord(recordTypeApplicationData); err != nil {
+ // Soft error, like EAGAIN
+ return 0, err
+ }
+ if c.hand.Len() > 0 && !c.isDTLS {
+ // We received handshake bytes, indicating the
+ // start of a renegotiation or a DTLS retransmit.
+ if err := c.handleRenegotiation(); err != nil {
+ return 0, err
+ }
+ continue
+ }
+ }
+ if err := c.in.err; err != nil {
+ return 0, err
+ }
+
+ n, err = c.input.Read(b)
+ if c.input.off >= len(c.input.data) || c.isDTLS {
+ c.in.freeBlock(c.input)
+ c.input = nil
+ }
+
+ // If a close-notify alert is waiting, read it so that
+ // we can return (n, EOF) instead of (n, nil), to signal
+ // to the HTTP response reading goroutine that the
+ // connection is now closed. This eliminates a race
+ // where the HTTP response reading goroutine would
+ // otherwise not observe the EOF until its next read,
+ // by which time a client goroutine might have already
+ // tried to reuse the HTTP connection for a new
+ // request.
+ // See https://codereview.appspot.com/76400046
+ // and http://golang.org/issue/3514
+ if ri := c.rawInput; ri != nil &&
+ n != 0 && err == nil &&
+ c.input == nil && len(ri.data) > 0 && recordType(ri.data[0]) == recordTypeAlert {
+ if recErr := c.readRecord(recordTypeApplicationData); recErr != nil {
+ err = recErr // will be io.EOF on closeNotify
+ }
+ }
+
+ if n != 0 || err != nil {
+ return n, err
+ }
+ }
+
+ return 0, io.ErrNoProgress
+}
+
+// Close closes the connection.
+func (c *Conn) Close() error {
+ var alertErr error
+
+ c.handshakeMutex.Lock()
+ defer c.handshakeMutex.Unlock()
+ if c.handshakeComplete {
+ alertErr = c.sendAlert(alertCloseNotify)
+ }
+
+ if err := c.conn.Close(); err != nil {
+ return err
+ }
+ return alertErr
+}
+
+// Handshake runs the client or server handshake
+// protocol if it has not yet been run.
+// Most uses of this package need not call Handshake
+// explicitly: the first Read or Write will call it automatically.
+func (c *Conn) Handshake() error {
+ c.handshakeMutex.Lock()
+ defer c.handshakeMutex.Unlock()
+ if err := c.handshakeErr; err != nil {
+ return err
+ }
+ if c.handshakeComplete {
+ return nil
+ }
+
+ if c.isClient {
+ c.handshakeErr = c.clientHandshake()
+ } else {
+ c.handshakeErr = c.serverHandshake()
+ }
+ return c.handshakeErr
+}
+
+// ConnectionState returns basic TLS details about the connection.
+func (c *Conn) ConnectionState() ConnectionState {
+ c.handshakeMutex.Lock()
+ defer c.handshakeMutex.Unlock()
+
+ var state ConnectionState
+ state.HandshakeComplete = c.handshakeComplete
+ if c.handshakeComplete {
+ state.Version = c.vers
+ state.NegotiatedProtocol = c.clientProtocol
+ state.DidResume = c.didResume
+ state.NegotiatedProtocolIsMutual = !c.clientProtocolFallback
+ state.NegotiatedProtocolFromALPN = c.usedALPN
+ state.CipherSuite = c.cipherSuite
+ state.PeerCertificates = c.peerCertificates
+ state.VerifiedChains = c.verifiedChains
+ state.ServerName = c.serverName
+ state.ChannelID = c.channelID
+ state.SRTPProtectionProfile = c.srtpProtectionProfile
+ }
+
+ return state
+}
+
+// OCSPResponse returns the stapled OCSP response from the TLS server, if
+// any. (Only valid for client connections.)
+func (c *Conn) OCSPResponse() []byte {
+ c.handshakeMutex.Lock()
+ defer c.handshakeMutex.Unlock()
+
+ return c.ocspResponse
+}
+
+// VerifyHostname checks that the peer certificate chain is valid for
+// connecting to host. If so, it returns nil; if not, it returns an error
+// describing the problem.
+func (c *Conn) VerifyHostname(host string) error {
+ c.handshakeMutex.Lock()
+ defer c.handshakeMutex.Unlock()
+ if !c.isClient {
+ return errors.New("tls: VerifyHostname called on TLS server connection")
+ }
+ if !c.handshakeComplete {
+ return errors.New("tls: handshake has not yet been performed")
+ }
+ return c.peerCertificates[0].VerifyHostname(host)
+}
diff --git a/src/ssl/test/runner/dtls.go b/src/ssl/test/runner/dtls.go
new file mode 100644
index 0000000..a395980
--- /dev/null
+++ b/src/ssl/test/runner/dtls.go
@@ -0,0 +1,342 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// DTLS implementation.
+//
+// NOTE: This is a not even a remotely production-quality DTLS
+// implementation. It is the bare minimum necessary to be able to
+// achieve coverage on BoringSSL's implementation. Of note is that
+// this implementation assumes the underlying net.PacketConn is not
+// only reliable but also ordered. BoringSSL will be expected to deal
+// with simulated loss, but there is no point in forcing the test
+// driver to.
+
+package main
+
+import (
+ "bytes"
+ "crypto/cipher"
+ "errors"
+ "fmt"
+ "io"
+ "net"
+)
+
+func versionToWire(vers uint16, isDTLS bool) uint16 {
+ if isDTLS {
+ return ^(vers - 0x0201)
+ }
+ return vers
+}
+
+func wireToVersion(vers uint16, isDTLS bool) uint16 {
+ if isDTLS {
+ return ^vers + 0x0201
+ }
+ return vers
+}
+
+func (c *Conn) dtlsDoReadRecord(want recordType) (recordType, *block, error) {
+Again:
+ recordHeaderLen := dtlsRecordHeaderLen
+
+ if c.rawInput == nil {
+ c.rawInput = c.in.newBlock()
+ }
+ b := c.rawInput
+
+ // Read a new packet only if the current one is empty.
+ if len(b.data) == 0 {
+ // Pick some absurdly large buffer size.
+ b.resize(maxCiphertext + recordHeaderLen)
+ n, err := c.conn.Read(c.rawInput.data)
+ if err != nil {
+ return 0, nil, err
+ }
+ if c.config.Bugs.MaxPacketLength != 0 && n > c.config.Bugs.MaxPacketLength {
+ return 0, nil, fmt.Errorf("dtls: exceeded maximum packet length")
+ }
+ c.rawInput.resize(n)
+ }
+
+ // Read out one record.
+ //
+ // A real DTLS implementation should be tolerant of errors,
+ // but this is test code. We should not be tolerant of our
+ // peer sending garbage.
+ if len(b.data) < recordHeaderLen {
+ return 0, nil, errors.New("dtls: failed to read record header")
+ }
+ typ := recordType(b.data[0])
+ vers := wireToVersion(uint16(b.data[1])<<8|uint16(b.data[2]), c.isDTLS)
+ if c.haveVers {
+ if vers != c.vers {
+ c.sendAlert(alertProtocolVersion)
+ return 0, nil, c.in.setErrorLocked(fmt.Errorf("dtls: received record with version %x when expecting version %x", vers, c.vers))
+ }
+ } else {
+ if expect := c.config.Bugs.ExpectInitialRecordVersion; expect != 0 && vers != expect {
+ c.sendAlert(alertProtocolVersion)
+ return 0, nil, c.in.setErrorLocked(fmt.Errorf("dtls: received record with version %x when expecting version %x", vers, expect))
+ }
+ }
+ seq := b.data[3:11]
+ if !bytes.Equal(seq[:2], c.in.seq[:2]) {
+ // If the epoch didn't match, silently drop the record.
+ // BoringSSL retransmits on an internal timer, so it may flakily
+ // revisit the previous epoch if retransmiting ChangeCipherSpec
+ // and Finished.
+ goto Again
+ }
+ // For test purposes, we assume a reliable channel. Require
+ // that the explicit sequence number matches the incrementing
+ // one we maintain. A real implementation would maintain a
+ // replay window and such.
+ if !bytes.Equal(seq, c.in.seq[:]) {
+ c.sendAlert(alertIllegalParameter)
+ return 0, nil, c.in.setErrorLocked(fmt.Errorf("dtls: bad sequence number"))
+ }
+ n := int(b.data[11])<<8 | int(b.data[12])
+ if n > maxCiphertext || len(b.data) < recordHeaderLen+n {
+ c.sendAlert(alertRecordOverflow)
+ return 0, nil, c.in.setErrorLocked(fmt.Errorf("dtls: oversized record received with length %d", n))
+ }
+
+ // Process message.
+ b, c.rawInput = c.in.splitBlock(b, recordHeaderLen+n)
+ ok, off, err := c.in.decrypt(b)
+ if !ok {
+ c.in.setErrorLocked(c.sendAlert(err))
+ }
+ b.off = off
+ return typ, b, nil
+}
+
+func (c *Conn) dtlsWriteRecord(typ recordType, data []byte) (n int, err error) {
+ recordHeaderLen := dtlsRecordHeaderLen
+ maxLen := c.config.Bugs.MaxHandshakeRecordLength
+ if maxLen <= 0 {
+ maxLen = 1024
+ }
+
+ b := c.out.newBlock()
+
+ var header []byte
+ if typ == recordTypeHandshake {
+ // Handshake messages have to be modified to include
+ // fragment offset and length and with the header
+ // replicated. Save the header here.
+ //
+ // TODO(davidben): This assumes that data contains
+ // exactly one handshake message. This is incompatible
+ // with FragmentAcrossChangeCipherSpec. (Which is
+ // unfortunate because OpenSSL's DTLS implementation
+ // will probably accept such fragmentation and could
+ // do with a fix + tests.)
+ if len(data) < 4 {
+ // This should not happen.
+ panic(data)
+ }
+ header = data[:4]
+ data = data[4:]
+ }
+
+ firstRun := true
+ for firstRun || len(data) > 0 {
+ firstRun = false
+ m := len(data)
+ var fragment []byte
+ // Handshake messages get fragmented. Other records we
+ // pass-through as is. DTLS should be a packet
+ // interface.
+ if typ == recordTypeHandshake {
+ if m > maxLen {
+ m = maxLen
+ }
+
+ // Standard handshake header.
+ fragment = make([]byte, 0, 12+m)
+ fragment = append(fragment, header...)
+ // message_seq
+ fragment = append(fragment, byte(c.sendHandshakeSeq>>8), byte(c.sendHandshakeSeq))
+ // fragment_offset
+ fragment = append(fragment, byte(n>>16), byte(n>>8), byte(n))
+ // fragment_length
+ fragment = append(fragment, byte(m>>16), byte(m>>8), byte(m))
+ fragment = append(fragment, data[:m]...)
+ } else {
+ fragment = data[:m]
+ }
+
+ // Send the fragment.
+ explicitIVLen := 0
+ explicitIVIsSeq := false
+
+ if cbc, ok := c.out.cipher.(cbcMode); ok {
+ // Block cipher modes have an explicit IV.
+ explicitIVLen = cbc.BlockSize()
+ } else if _, ok := c.out.cipher.(cipher.AEAD); ok {
+ explicitIVLen = 8
+ // The AES-GCM construction in TLS has an
+ // explicit nonce so that the nonce can be
+ // random. However, the nonce is only 8 bytes
+ // which is too small for a secure, random
+ // nonce. Therefore we use the sequence number
+ // as the nonce.
+ explicitIVIsSeq = true
+ } else if c.out.cipher != nil {
+ panic("Unknown cipher")
+ }
+ b.resize(recordHeaderLen + explicitIVLen + len(fragment))
+ b.data[0] = byte(typ)
+ vers := c.vers
+ if vers == 0 {
+ // Some TLS servers fail if the record version is
+ // greater than TLS 1.0 for the initial ClientHello.
+ vers = VersionTLS10
+ }
+ vers = versionToWire(vers, c.isDTLS)
+ b.data[1] = byte(vers >> 8)
+ b.data[2] = byte(vers)
+ // DTLS records include an explicit sequence number.
+ copy(b.data[3:11], c.out.seq[0:])
+ b.data[11] = byte(len(fragment) >> 8)
+ b.data[12] = byte(len(fragment))
+ if explicitIVLen > 0 {
+ explicitIV := b.data[recordHeaderLen : recordHeaderLen+explicitIVLen]
+ if explicitIVIsSeq {
+ copy(explicitIV, c.out.seq[:])
+ } else {
+ if _, err = io.ReadFull(c.config.rand(), explicitIV); err != nil {
+ break
+ }
+ }
+ }
+ copy(b.data[recordHeaderLen+explicitIVLen:], fragment)
+ c.out.encrypt(b, explicitIVLen)
+
+ // TODO(davidben): A real DTLS implementation needs to
+ // retransmit handshake messages. For testing
+ // purposes, we don't actually care.
+ _, err = c.conn.Write(b.data)
+ if err != nil {
+ break
+ }
+ n += m
+ data = data[m:]
+ }
+ c.out.freeBlock(b)
+
+ // Increment the handshake sequence number for the next
+ // handshake message.
+ if typ == recordTypeHandshake {
+ c.sendHandshakeSeq++
+ }
+
+ if typ == recordTypeChangeCipherSpec {
+ err = c.out.changeCipherSpec(c.config)
+ if err != nil {
+ // Cannot call sendAlert directly,
+ // because we already hold c.out.Mutex.
+ c.tmp[0] = alertLevelError
+ c.tmp[1] = byte(err.(alert))
+ c.writeRecord(recordTypeAlert, c.tmp[0:2])
+ return n, c.out.setErrorLocked(&net.OpError{Op: "local error", Err: err})
+ }
+ }
+ return
+}
+
+func (c *Conn) dtlsDoReadHandshake() ([]byte, error) {
+ // Assemble a full handshake message. For test purposes, this
+ // implementation assumes fragments arrive in order, but tolerates
+ // retransmits. It may need to be cleverer if we ever test BoringSSL's
+ // retransmit behavior.
+ for len(c.handMsg) < 4+c.handMsgLen {
+ // Get a new handshake record if the previous has been
+ // exhausted.
+ if c.hand.Len() == 0 {
+ if err := c.in.err; err != nil {
+ return nil, err
+ }
+ if err := c.readRecord(recordTypeHandshake); err != nil {
+ return nil, err
+ }
+ }
+
+ // Read the next fragment. It must fit entirely within
+ // the record.
+ if c.hand.Len() < 12 {
+ return nil, errors.New("dtls: bad handshake record")
+ }
+ header := c.hand.Next(12)
+ fragN := int(header[1])<<16 | int(header[2])<<8 | int(header[3])
+ fragSeq := uint16(header[4])<<8 | uint16(header[5])
+ fragOff := int(header[6])<<16 | int(header[7])<<8 | int(header[8])
+ fragLen := int(header[9])<<16 | int(header[10])<<8 | int(header[11])
+
+ if c.hand.Len() < fragLen {
+ return nil, errors.New("dtls: fragment length too long")
+ }
+ fragment := c.hand.Next(fragLen)
+
+ if fragSeq < c.recvHandshakeSeq {
+ // BoringSSL retransmits based on an internal timer, so
+ // it may flakily retransmit part of a handshake
+ // message. Ignore those fragments.
+ //
+ // TODO(davidben): Revise this if BoringSSL's retransmit
+ // logic is made more deterministic.
+ continue
+ } else if fragSeq > c.recvHandshakeSeq {
+ return nil, errors.New("dtls: handshake messages sent out of order")
+ }
+
+ // Check that the length is consistent.
+ if c.handMsg == nil {
+ c.handMsgLen = fragN
+ if c.handMsgLen > maxHandshake {
+ return nil, c.in.setErrorLocked(c.sendAlert(alertInternalError))
+ }
+ // Start with the TLS handshake header,
+ // without the DTLS bits.
+ c.handMsg = append([]byte{}, header[:4]...)
+ } else if fragN != c.handMsgLen {
+ return nil, errors.New("dtls: bad handshake length")
+ }
+
+ // Add the fragment to the pending message.
+ if 4+fragOff != len(c.handMsg) {
+ return nil, errors.New("dtls: bad fragment offset")
+ }
+ if fragOff+fragLen > c.handMsgLen {
+ return nil, errors.New("dtls: bad fragment length")
+ }
+ c.handMsg = append(c.handMsg, fragment...)
+ }
+ c.recvHandshakeSeq++
+ ret := c.handMsg
+ c.handMsg, c.handMsgLen = nil, 0
+ return ret, nil
+}
+
+// DTLSServer returns a new DTLS server side connection
+// using conn as the underlying transport.
+// The configuration config must be non-nil and must have
+// at least one certificate.
+func DTLSServer(conn net.Conn, config *Config) *Conn {
+ c := &Conn{config: config, isDTLS: true, conn: conn}
+ c.init()
+ return c
+}
+
+// DTLSClient returns a new DTLS client side connection
+// using conn as the underlying transport.
+// The config cannot be nil: users must set either ServerHostname or
+// InsecureSkipVerify in the config.
+func DTLSClient(conn net.Conn, config *Config) *Conn {
+ c := &Conn{config: config, isClient: true, isDTLS: true, conn: conn}
+ c.init()
+ return c
+}
diff --git a/src/ssl/test/runner/ecdsa_cert.pem b/src/ssl/test/runner/ecdsa_cert.pem
new file mode 100644
index 0000000..50bcbf5
--- /dev/null
+++ b/src/ssl/test/runner/ecdsa_cert.pem
@@ -0,0 +1,12 @@
+-----BEGIN CERTIFICATE-----
+MIIBzzCCAXagAwIBAgIJANlMBNpJfb/rMAkGByqGSM49BAEwRTELMAkGA1UEBhMC
+QVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdp
+dHMgUHR5IEx0ZDAeFw0xNDA0MjMyMzIxNTdaFw0xNDA1MjMyMzIxNTdaMEUxCzAJ
+BgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5l
+dCBXaWRnaXRzIFB0eSBMdGQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATmK2ni
+v2Wfl74vHg2UikzVl2u3qR4NRvvdqakendy6WgHn1peoChj5w8SjHlbifINI2xYa
+HPUdfvGULUvPciLBo1AwTjAdBgNVHQ4EFgQUq4TSrKuV8IJOFngHVVdf5CaNgtEw
+HwYDVR0jBBgwFoAUq4TSrKuV8IJOFngHVVdf5CaNgtEwDAYDVR0TBAUwAwEB/zAJ
+BgcqhkjOPQQBA0gAMEUCIQDyoDVeUTo2w4J5m+4nUIWOcAZ0lVfSKXQA9L4Vh13E
+BwIgfB55FGohg/B6dGh5XxSZmmi08cueFV7mHzJSYV51yRQ=
+-----END CERTIFICATE-----
diff --git a/src/ssl/test/runner/ecdsa_key.pem b/src/ssl/test/runner/ecdsa_key.pem
new file mode 100644
index 0000000..b9116f0
--- /dev/null
+++ b/src/ssl/test/runner/ecdsa_key.pem
@@ -0,0 +1,8 @@
+-----BEGIN EC PARAMETERS-----
+BggqhkjOPQMBBw==
+-----END EC PARAMETERS-----
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEIAcPCHJ61KBKnN1ZyU2JaHcItW/JXTB3DujRyc4Ki7RqoAoGCCqGSM49
+AwEHoUQDQgAE5itp4r9ln5e+Lx4NlIpM1Zdrt6keDUb73ampHp3culoB59aXqAoY
++cPEox5W4nyDSNsWGhz1HX7xlC1Lz3IiwQ==
+-----END EC PRIVATE KEY-----
diff --git a/src/ssl/test/runner/handshake_client.go b/src/ssl/test/runner/handshake_client.go
new file mode 100644
index 0000000..f297fc1
--- /dev/null
+++ b/src/ssl/test/runner/handshake_client.go
@@ -0,0 +1,910 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "bytes"
+ "crypto"
+ "crypto/ecdsa"
+ "crypto/elliptic"
+ "crypto/rsa"
+ "crypto/subtle"
+ "crypto/x509"
+ "encoding/asn1"
+ "errors"
+ "fmt"
+ "io"
+ "math/big"
+ "net"
+ "strconv"
+)
+
+type clientHandshakeState struct {
+ c *Conn
+ serverHello *serverHelloMsg
+ hello *clientHelloMsg
+ suite *cipherSuite
+ finishedHash finishedHash
+ masterSecret []byte
+ session *ClientSessionState
+}
+
+func (c *Conn) clientHandshake() error {
+ if c.config == nil {
+ c.config = defaultConfig()
+ }
+
+ if len(c.config.ServerName) == 0 && !c.config.InsecureSkipVerify {
+ return errors.New("tls: either ServerName or InsecureSkipVerify must be specified in the tls.Config")
+ }
+
+ c.sendHandshakeSeq = 0
+ c.recvHandshakeSeq = 0
+
+ nextProtosLength := 0
+ for _, proto := range c.config.NextProtos {
+ if l := len(proto); l == 0 || l > 255 {
+ return errors.New("tls: invalid NextProtos value")
+ } else {
+ nextProtosLength += 1 + l
+ }
+ }
+ if nextProtosLength > 0xffff {
+ return errors.New("tls: NextProtos values too large")
+ }
+
+ hello := &clientHelloMsg{
+ isDTLS: c.isDTLS,
+ vers: c.config.maxVersion(),
+ compressionMethods: []uint8{compressionNone},
+ random: make([]byte, 32),
+ ocspStapling: true,
+ serverName: c.config.ServerName,
+ supportedCurves: c.config.curvePreferences(),
+ supportedPoints: []uint8{pointFormatUncompressed},
+ nextProtoNeg: len(c.config.NextProtos) > 0,
+ secureRenegotiation: []byte{},
+ alpnProtocols: c.config.NextProtos,
+ duplicateExtension: c.config.Bugs.DuplicateExtension,
+ channelIDSupported: c.config.ChannelID != nil,
+ npnLast: c.config.Bugs.SwapNPNAndALPN,
+ extendedMasterSecret: c.config.maxVersion() >= VersionTLS10,
+ srtpProtectionProfiles: c.config.SRTPProtectionProfiles,
+ srtpMasterKeyIdentifier: c.config.Bugs.SRTPMasterKeyIdentifer,
+ }
+
+ if c.config.Bugs.SendClientVersion != 0 {
+ hello.vers = c.config.Bugs.SendClientVersion
+ }
+
+ if c.config.Bugs.NoExtendedMasterSecret {
+ hello.extendedMasterSecret = false
+ }
+
+ if len(c.clientVerify) > 0 && !c.config.Bugs.EmptyRenegotiationInfo {
+ if c.config.Bugs.BadRenegotiationInfo {
+ hello.secureRenegotiation = append(hello.secureRenegotiation, c.clientVerify...)
+ hello.secureRenegotiation[0] ^= 0x80
+ } else {
+ hello.secureRenegotiation = c.clientVerify
+ }
+ }
+
+ if c.config.Bugs.NoRenegotiationInfo {
+ hello.secureRenegotiation = nil
+ }
+
+ possibleCipherSuites := c.config.cipherSuites()
+ hello.cipherSuites = make([]uint16, 0, len(possibleCipherSuites))
+
+NextCipherSuite:
+ for _, suiteId := range possibleCipherSuites {
+ for _, suite := range cipherSuites {
+ if suite.id != suiteId {
+ continue
+ }
+ // Don't advertise TLS 1.2-only cipher suites unless
+ // we're attempting TLS 1.2.
+ if hello.vers < VersionTLS12 && suite.flags&suiteTLS12 != 0 {
+ continue
+ }
+ // Don't advertise non-DTLS cipher suites on DTLS.
+ if c.isDTLS && suite.flags&suiteNoDTLS != 0 {
+ continue
+ }
+ hello.cipherSuites = append(hello.cipherSuites, suiteId)
+ continue NextCipherSuite
+ }
+ }
+
+ if c.config.Bugs.SendFallbackSCSV {
+ hello.cipherSuites = append(hello.cipherSuites, fallbackSCSV)
+ }
+
+ _, err := io.ReadFull(c.config.rand(), hello.random)
+ if err != nil {
+ c.sendAlert(alertInternalError)
+ return errors.New("tls: short read from Rand: " + err.Error())
+ }
+
+ if hello.vers >= VersionTLS12 && !c.config.Bugs.NoSignatureAndHashes {
+ hello.signatureAndHashes = c.config.signatureAndHashesForClient()
+ }
+
+ var session *ClientSessionState
+ var cacheKey string
+ sessionCache := c.config.ClientSessionCache
+
+ if sessionCache != nil {
+ hello.ticketSupported = !c.config.SessionTicketsDisabled
+
+ // Try to resume a previously negotiated TLS session, if
+ // available.
+ cacheKey = clientSessionCacheKey(c.conn.RemoteAddr(), c.config)
+ candidateSession, ok := sessionCache.Get(cacheKey)
+ if ok {
+ ticketOk := !c.config.SessionTicketsDisabled || candidateSession.sessionTicket == nil
+
+ // Check that the ciphersuite/version used for the
+ // previous session are still valid.
+ cipherSuiteOk := false
+ for _, id := range hello.cipherSuites {
+ if id == candidateSession.cipherSuite {
+ cipherSuiteOk = true
+ break
+ }
+ }
+
+ versOk := candidateSession.vers >= c.config.minVersion() &&
+ candidateSession.vers <= c.config.maxVersion()
+ if ticketOk && versOk && cipherSuiteOk {
+ session = candidateSession
+ }
+ }
+ }
+
+ if session != nil {
+ if session.sessionTicket != nil {
+ hello.sessionTicket = session.sessionTicket
+ if c.config.Bugs.CorruptTicket {
+ hello.sessionTicket = make([]byte, len(session.sessionTicket))
+ copy(hello.sessionTicket, session.sessionTicket)
+ if len(hello.sessionTicket) > 0 {
+ offset := 40
+ if offset > len(hello.sessionTicket) {
+ offset = len(hello.sessionTicket) - 1
+ }
+ hello.sessionTicket[offset] ^= 0x40
+ }
+ }
+ // A random session ID is used to detect when the
+ // server accepted the ticket and is resuming a session
+ // (see RFC 5077).
+ sessionIdLen := 16
+ if c.config.Bugs.OversizedSessionId {
+ sessionIdLen = 33
+ }
+ hello.sessionId = make([]byte, sessionIdLen)
+ if _, err := io.ReadFull(c.config.rand(), hello.sessionId); err != nil {
+ c.sendAlert(alertInternalError)
+ return errors.New("tls: short read from Rand: " + err.Error())
+ }
+ } else {
+ hello.sessionId = session.sessionId
+ }
+ }
+
+ var helloBytes []byte
+ if c.config.Bugs.SendV2ClientHello {
+ // Test that the peer left-pads random.
+ hello.random[0] = 0
+ v2Hello := &v2ClientHelloMsg{
+ vers: hello.vers,
+ cipherSuites: hello.cipherSuites,
+ // No session resumption for V2ClientHello.
+ sessionId: nil,
+ challenge: hello.random[1:],
+ }
+ helloBytes = v2Hello.marshal()
+ c.writeV2Record(helloBytes)
+ } else {
+ helloBytes = hello.marshal()
+ c.writeRecord(recordTypeHandshake, helloBytes)
+ }
+
+ msg, err := c.readHandshake()
+ if err != nil {
+ return err
+ }
+
+ if c.isDTLS {
+ helloVerifyRequest, ok := msg.(*helloVerifyRequestMsg)
+ if ok {
+ if helloVerifyRequest.vers != VersionTLS10 {
+ // Per RFC 6347, the version field in
+ // HelloVerifyRequest SHOULD be always DTLS
+ // 1.0. Enforce this for testing purposes.
+ return errors.New("dtls: bad HelloVerifyRequest version")
+ }
+
+ hello.raw = nil
+ hello.cookie = helloVerifyRequest.cookie
+ helloBytes = hello.marshal()
+ c.writeRecord(recordTypeHandshake, helloBytes)
+
+ msg, err = c.readHandshake()
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ serverHello, ok := msg.(*serverHelloMsg)
+ if !ok {
+ c.sendAlert(alertUnexpectedMessage)
+ return unexpectedMessageError(serverHello, msg)
+ }
+
+ c.vers, ok = c.config.mutualVersion(serverHello.vers)
+ if !ok {
+ c.sendAlert(alertProtocolVersion)
+ return fmt.Errorf("tls: server selected unsupported protocol version %x", serverHello.vers)
+ }
+ c.haveVers = true
+
+ suite := mutualCipherSuite(c.config.cipherSuites(), serverHello.cipherSuite)
+ if suite == nil {
+ c.sendAlert(alertHandshakeFailure)
+ return fmt.Errorf("tls: server selected an unsupported cipher suite")
+ }
+
+ if len(c.clientVerify) > 0 && !c.config.Bugs.NoRenegotiationInfo {
+ var expectedRenegInfo []byte
+ expectedRenegInfo = append(expectedRenegInfo, c.clientVerify...)
+ expectedRenegInfo = append(expectedRenegInfo, c.serverVerify...)
+ if !bytes.Equal(serverHello.secureRenegotiation, expectedRenegInfo) {
+ c.sendAlert(alertHandshakeFailure)
+ return fmt.Errorf("tls: renegotiation mismatch")
+ }
+ }
+
+ hs := &clientHandshakeState{
+ c: c,
+ serverHello: serverHello,
+ hello: hello,
+ suite: suite,
+ finishedHash: newFinishedHash(c.vers, suite),
+ session: session,
+ }
+
+ hs.writeHash(helloBytes, hs.c.sendHandshakeSeq-1)
+ hs.writeServerHash(hs.serverHello.marshal())
+
+ if c.config.Bugs.EarlyChangeCipherSpec > 0 {
+ hs.establishKeys()
+ c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
+ }
+
+ isResume, err := hs.processServerHello()
+ if err != nil {
+ return err
+ }
+
+ if isResume {
+ if c.config.Bugs.EarlyChangeCipherSpec == 0 {
+ if err := hs.establishKeys(); err != nil {
+ return err
+ }
+ }
+ if err := hs.readSessionTicket(); err != nil {
+ return err
+ }
+ if err := hs.readFinished(); err != nil {
+ return err
+ }
+ if err := hs.sendFinished(isResume); err != nil {
+ return err
+ }
+ } else {
+ if err := hs.doFullHandshake(); err != nil {
+ return err
+ }
+ if err := hs.establishKeys(); err != nil {
+ return err
+ }
+ if err := hs.sendFinished(isResume); err != nil {
+ return err
+ }
+ if err := hs.readSessionTicket(); err != nil {
+ return err
+ }
+ if err := hs.readFinished(); err != nil {
+ return err
+ }
+ }
+
+ if sessionCache != nil && hs.session != nil && session != hs.session {
+ sessionCache.Put(cacheKey, hs.session)
+ }
+
+ c.didResume = isResume
+ c.handshakeComplete = true
+ c.cipherSuite = suite.id
+ return nil
+}
+
+func (hs *clientHandshakeState) doFullHandshake() error {
+ c := hs.c
+
+ var leaf *x509.Certificate
+ if hs.suite.flags&suitePSK == 0 {
+ msg, err := c.readHandshake()
+ if err != nil {
+ return err
+ }
+
+ certMsg, ok := msg.(*certificateMsg)
+ if !ok || len(certMsg.certificates) == 0 {
+ c.sendAlert(alertUnexpectedMessage)
+ return unexpectedMessageError(certMsg, msg)
+ }
+ hs.writeServerHash(certMsg.marshal())
+
+ certs := make([]*x509.Certificate, len(certMsg.certificates))
+ for i, asn1Data := range certMsg.certificates {
+ cert, err := x509.ParseCertificate(asn1Data)
+ if err != nil {
+ c.sendAlert(alertBadCertificate)
+ return errors.New("tls: failed to parse certificate from server: " + err.Error())
+ }
+ certs[i] = cert
+ }
+ leaf = certs[0]
+
+ if !c.config.InsecureSkipVerify {
+ opts := x509.VerifyOptions{
+ Roots: c.config.RootCAs,
+ CurrentTime: c.config.time(),
+ DNSName: c.config.ServerName,
+ Intermediates: x509.NewCertPool(),
+ }
+
+ for i, cert := range certs {
+ if i == 0 {
+ continue
+ }
+ opts.Intermediates.AddCert(cert)
+ }
+ c.verifiedChains, err = leaf.Verify(opts)
+ if err != nil {
+ c.sendAlert(alertBadCertificate)
+ return err
+ }
+ }
+
+ switch leaf.PublicKey.(type) {
+ case *rsa.PublicKey, *ecdsa.PublicKey:
+ break
+ default:
+ c.sendAlert(alertUnsupportedCertificate)
+ return fmt.Errorf("tls: server's certificate contains an unsupported type of public key: %T", leaf.PublicKey)
+ }
+
+ c.peerCertificates = certs
+ }
+
+ if hs.serverHello.ocspStapling {
+ msg, err := c.readHandshake()
+ if err != nil {
+ return err
+ }
+ cs, ok := msg.(*certificateStatusMsg)
+ if !ok {
+ c.sendAlert(alertUnexpectedMessage)
+ return unexpectedMessageError(cs, msg)
+ }
+ hs.writeServerHash(cs.marshal())
+
+ if cs.statusType == statusTypeOCSP {
+ c.ocspResponse = cs.response
+ }
+ }
+
+ msg, err := c.readHandshake()
+ if err != nil {
+ return err
+ }
+
+ keyAgreement := hs.suite.ka(c.vers)
+
+ skx, ok := msg.(*serverKeyExchangeMsg)
+ if ok {
+ hs.writeServerHash(skx.marshal())
+ err = keyAgreement.processServerKeyExchange(c.config, hs.hello, hs.serverHello, leaf, skx)
+ if err != nil {
+ c.sendAlert(alertUnexpectedMessage)
+ return err
+ }
+
+ msg, err = c.readHandshake()
+ if err != nil {
+ return err
+ }
+ }
+
+ var chainToSend *Certificate
+ var certRequested bool
+ certReq, ok := msg.(*certificateRequestMsg)
+ if ok {
+ certRequested = true
+
+ // RFC 4346 on the certificateAuthorities field:
+ // A list of the distinguished names of acceptable certificate
+ // authorities. These distinguished names may specify a desired
+ // distinguished name for a root CA or for a subordinate CA;
+ // thus, this message can be used to describe both known roots
+ // and a desired authorization space. If the
+ // certificate_authorities list is empty then the client MAY
+ // send any certificate of the appropriate
+ // ClientCertificateType, unless there is some external
+ // arrangement to the contrary.
+
+ hs.writeServerHash(certReq.marshal())
+
+ var rsaAvail, ecdsaAvail bool
+ for _, certType := range certReq.certificateTypes {
+ switch certType {
+ case CertTypeRSASign:
+ rsaAvail = true
+ case CertTypeECDSASign:
+ ecdsaAvail = true
+ }
+ }
+
+ // We need to search our list of client certs for one
+ // where SignatureAlgorithm is RSA and the Issuer is in
+ // certReq.certificateAuthorities
+ findCert:
+ for i, chain := range c.config.Certificates {
+ if !rsaAvail && !ecdsaAvail {
+ continue
+ }
+
+ for j, cert := range chain.Certificate {
+ x509Cert := chain.Leaf
+ // parse the certificate if this isn't the leaf
+ // node, or if chain.Leaf was nil
+ if j != 0 || x509Cert == nil {
+ if x509Cert, err = x509.ParseCertificate(cert); err != nil {
+ c.sendAlert(alertInternalError)
+ return errors.New("tls: failed to parse client certificate #" + strconv.Itoa(i) + ": " + err.Error())
+ }
+ }
+
+ switch {
+ case rsaAvail && x509Cert.PublicKeyAlgorithm == x509.RSA:
+ case ecdsaAvail && x509Cert.PublicKeyAlgorithm == x509.ECDSA:
+ default:
+ continue findCert
+ }
+
+ if len(certReq.certificateAuthorities) == 0 {
+ // they gave us an empty list, so just take the
+ // first RSA cert from c.config.Certificates
+ chainToSend = &chain
+ break findCert
+ }
+
+ for _, ca := range certReq.certificateAuthorities {
+ if bytes.Equal(x509Cert.RawIssuer, ca) {
+ chainToSend = &chain
+ break findCert
+ }
+ }
+ }
+ }
+
+ msg, err = c.readHandshake()
+ if err != nil {
+ return err
+ }
+ }
+
+ shd, ok := msg.(*serverHelloDoneMsg)
+ if !ok {
+ c.sendAlert(alertUnexpectedMessage)
+ return unexpectedMessageError(shd, msg)
+ }
+ hs.writeServerHash(shd.marshal())
+
+ // If the server requested a certificate then we have to send a
+ // Certificate message, even if it's empty because we don't have a
+ // certificate to send.
+ if certRequested {
+ certMsg := new(certificateMsg)
+ if chainToSend != nil {
+ certMsg.certificates = chainToSend.Certificate
+ }
+ hs.writeClientHash(certMsg.marshal())
+ c.writeRecord(recordTypeHandshake, certMsg.marshal())
+ }
+
+ preMasterSecret, ckx, err := keyAgreement.generateClientKeyExchange(c.config, hs.hello, leaf)
+ if err != nil {
+ c.sendAlert(alertInternalError)
+ return err
+ }
+ if ckx != nil {
+ if c.config.Bugs.EarlyChangeCipherSpec < 2 {
+ hs.writeClientHash(ckx.marshal())
+ }
+ c.writeRecord(recordTypeHandshake, ckx.marshal())
+ }
+
+ if hs.serverHello.extendedMasterSecret && c.vers >= VersionTLS10 {
+ hs.masterSecret = extendedMasterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.finishedHash)
+ c.extendedMasterSecret = true
+ } else {
+ if c.config.Bugs.RequireExtendedMasterSecret {
+ return errors.New("tls: extended master secret required but not supported by peer")
+ }
+ hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.hello.random, hs.serverHello.random)
+ }
+
+ if chainToSend != nil {
+ var signed []byte
+ certVerify := &certificateVerifyMsg{
+ hasSignatureAndHash: c.vers >= VersionTLS12,
+ }
+
+ switch key := c.config.Certificates[0].PrivateKey.(type) {
+ case *ecdsa.PrivateKey:
+ certVerify.signatureAndHash, err = hs.finishedHash.selectClientCertSignatureAlgorithm(certReq.signatureAndHashes, signatureECDSA)
+ if err != nil {
+ break
+ }
+ var digest []byte
+ digest, _, err = hs.finishedHash.hashForClientCertificate(certVerify.signatureAndHash, hs.masterSecret)
+ if err != nil {
+ break
+ }
+ var r, s *big.Int
+ r, s, err = ecdsa.Sign(c.config.rand(), key, digest)
+ if err == nil {
+ signed, err = asn1.Marshal(ecdsaSignature{r, s})
+ }
+ case *rsa.PrivateKey:
+ certVerify.signatureAndHash, err = hs.finishedHash.selectClientCertSignatureAlgorithm(certReq.signatureAndHashes, signatureRSA)
+ if err != nil {
+ break
+ }
+ var digest []byte
+ var hashFunc crypto.Hash
+ digest, hashFunc, err = hs.finishedHash.hashForClientCertificate(certVerify.signatureAndHash, hs.masterSecret)
+ if err != nil {
+ break
+ }
+ signed, err = rsa.SignPKCS1v15(c.config.rand(), key, hashFunc, digest)
+ default:
+ err = errors.New("unknown private key type")
+ }
+ if err != nil {
+ c.sendAlert(alertInternalError)
+ return errors.New("tls: failed to sign handshake with client certificate: " + err.Error())
+ }
+ certVerify.signature = signed
+
+ hs.writeClientHash(certVerify.marshal())
+ c.writeRecord(recordTypeHandshake, certVerify.marshal())
+ }
+
+ hs.finishedHash.discardHandshakeBuffer()
+
+ return nil
+}
+
+func (hs *clientHandshakeState) establishKeys() error {
+ c := hs.c
+
+ clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
+ keysFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.hello.random, hs.serverHello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen)
+ var clientCipher, serverCipher interface{}
+ var clientHash, serverHash macFunction
+ if hs.suite.cipher != nil {
+ clientCipher = hs.suite.cipher(clientKey, clientIV, false /* not for reading */)
+ clientHash = hs.suite.mac(c.vers, clientMAC)
+ serverCipher = hs.suite.cipher(serverKey, serverIV, true /* for reading */)
+ serverHash = hs.suite.mac(c.vers, serverMAC)
+ } else {
+ clientCipher = hs.suite.aead(clientKey, clientIV)
+ serverCipher = hs.suite.aead(serverKey, serverIV)
+ }
+
+ c.in.prepareCipherSpec(c.vers, serverCipher, serverHash)
+ c.out.prepareCipherSpec(c.vers, clientCipher, clientHash)
+ return nil
+}
+
+func (hs *clientHandshakeState) serverResumedSession() bool {
+ // If the server responded with the same sessionId then it means the
+ // sessionTicket is being used to resume a TLS session.
+ return hs.session != nil && hs.hello.sessionId != nil &&
+ bytes.Equal(hs.serverHello.sessionId, hs.hello.sessionId)
+}
+
+func (hs *clientHandshakeState) processServerHello() (bool, error) {
+ c := hs.c
+
+ if hs.serverHello.compressionMethod != compressionNone {
+ c.sendAlert(alertUnexpectedMessage)
+ return false, errors.New("tls: server selected unsupported compression format")
+ }
+
+ clientDidNPN := hs.hello.nextProtoNeg
+ clientDidALPN := len(hs.hello.alpnProtocols) > 0
+ serverHasNPN := hs.serverHello.nextProtoNeg
+ serverHasALPN := len(hs.serverHello.alpnProtocol) > 0
+
+ if !clientDidNPN && serverHasNPN {
+ c.sendAlert(alertHandshakeFailure)
+ return false, errors.New("server advertised unrequested NPN extension")
+ }
+
+ if !clientDidALPN && serverHasALPN {
+ c.sendAlert(alertHandshakeFailure)
+ return false, errors.New("server advertised unrequested ALPN extension")
+ }
+
+ if serverHasNPN && serverHasALPN {
+ c.sendAlert(alertHandshakeFailure)
+ return false, errors.New("server advertised both NPN and ALPN extensions")
+ }
+
+ if serverHasALPN {
+ c.clientProtocol = hs.serverHello.alpnProtocol
+ c.clientProtocolFallback = false
+ c.usedALPN = true
+ }
+
+ if !hs.hello.channelIDSupported && hs.serverHello.channelIDRequested {
+ c.sendAlert(alertHandshakeFailure)
+ return false, errors.New("server advertised unrequested Channel ID extension")
+ }
+
+ if hs.serverHello.srtpProtectionProfile != 0 {
+ if hs.serverHello.srtpMasterKeyIdentifier != "" {
+ return false, errors.New("tls: server selected SRTP MKI value")
+ }
+
+ found := false
+ for _, p := range c.config.SRTPProtectionProfiles {
+ if p == hs.serverHello.srtpProtectionProfile {
+ found = true
+ break
+ }
+ }
+ if !found {
+ return false, errors.New("tls: server advertised unsupported SRTP profile")
+ }
+
+ c.srtpProtectionProfile = hs.serverHello.srtpProtectionProfile
+ }
+
+ if hs.serverResumedSession() {
+ // Restore masterSecret and peerCerts from previous state
+ hs.masterSecret = hs.session.masterSecret
+ c.peerCertificates = hs.session.serverCertificates
+ c.extendedMasterSecret = hs.session.extendedMasterSecret
+ hs.finishedHash.discardHandshakeBuffer()
+ return true, nil
+ }
+ return false, nil
+}
+
+func (hs *clientHandshakeState) readFinished() error {
+ c := hs.c
+
+ c.readRecord(recordTypeChangeCipherSpec)
+ if err := c.in.error(); err != nil {
+ return err
+ }
+
+ msg, err := c.readHandshake()
+ if err != nil {
+ return err
+ }
+ serverFinished, ok := msg.(*finishedMsg)
+ if !ok {
+ c.sendAlert(alertUnexpectedMessage)
+ return unexpectedMessageError(serverFinished, msg)
+ }
+
+ if c.config.Bugs.EarlyChangeCipherSpec == 0 {
+ verify := hs.finishedHash.serverSum(hs.masterSecret)
+ if len(verify) != len(serverFinished.verifyData) ||
+ subtle.ConstantTimeCompare(verify, serverFinished.verifyData) != 1 {
+ c.sendAlert(alertHandshakeFailure)
+ return errors.New("tls: server's Finished message was incorrect")
+ }
+ }
+ c.serverVerify = append(c.serverVerify[:0], serverFinished.verifyData...)
+ hs.writeServerHash(serverFinished.marshal())
+ return nil
+}
+
+func (hs *clientHandshakeState) readSessionTicket() error {
+ c := hs.c
+
+ // Create a session with no server identifier. Either a
+ // session ID or session ticket will be attached.
+ session := &ClientSessionState{
+ vers: c.vers,
+ cipherSuite: hs.suite.id,
+ masterSecret: hs.masterSecret,
+ handshakeHash: hs.finishedHash.server.Sum(nil),
+ serverCertificates: c.peerCertificates,
+ }
+
+ if !hs.serverHello.ticketSupported {
+ if hs.session == nil && len(hs.serverHello.sessionId) > 0 {
+ session.sessionId = hs.serverHello.sessionId
+ hs.session = session
+ }
+ return nil
+ }
+
+ msg, err := c.readHandshake()
+ if err != nil {
+ return err
+ }
+ sessionTicketMsg, ok := msg.(*newSessionTicketMsg)
+ if !ok {
+ c.sendAlert(alertUnexpectedMessage)
+ return unexpectedMessageError(sessionTicketMsg, msg)
+ }
+
+ session.sessionTicket = sessionTicketMsg.ticket
+ hs.session = session
+
+ hs.writeServerHash(sessionTicketMsg.marshal())
+
+ return nil
+}
+
+func (hs *clientHandshakeState) sendFinished(isResume bool) error {
+ c := hs.c
+
+ var postCCSBytes []byte
+ seqno := hs.c.sendHandshakeSeq
+ if hs.serverHello.nextProtoNeg {
+ nextProto := new(nextProtoMsg)
+ proto, fallback := mutualProtocol(c.config.NextProtos, hs.serverHello.nextProtos)
+ nextProto.proto = proto
+ c.clientProtocol = proto
+ c.clientProtocolFallback = fallback
+
+ nextProtoBytes := nextProto.marshal()
+ hs.writeHash(nextProtoBytes, seqno)
+ seqno++
+ postCCSBytes = append(postCCSBytes, nextProtoBytes...)
+ }
+
+ if hs.serverHello.channelIDRequested {
+ encryptedExtensions := new(encryptedExtensionsMsg)
+ if c.config.ChannelID.Curve != elliptic.P256() {
+ return fmt.Errorf("tls: Channel ID is not on P-256.")
+ }
+ var resumeHash []byte
+ if isResume {
+ resumeHash = hs.session.handshakeHash
+ }
+ r, s, err := ecdsa.Sign(c.config.rand(), c.config.ChannelID, hs.finishedHash.hashForChannelID(resumeHash))
+ if err != nil {
+ return err
+ }
+ channelID := make([]byte, 128)
+ writeIntPadded(channelID[0:32], c.config.ChannelID.X)
+ writeIntPadded(channelID[32:64], c.config.ChannelID.Y)
+ writeIntPadded(channelID[64:96], r)
+ writeIntPadded(channelID[96:128], s)
+ encryptedExtensions.channelID = channelID
+
+ c.channelID = &c.config.ChannelID.PublicKey
+
+ encryptedExtensionsBytes := encryptedExtensions.marshal()
+ hs.writeHash(encryptedExtensionsBytes, seqno)
+ seqno++
+ postCCSBytes = append(postCCSBytes, encryptedExtensionsBytes...)
+ }
+
+ finished := new(finishedMsg)
+ if c.config.Bugs.EarlyChangeCipherSpec == 2 {
+ finished.verifyData = hs.finishedHash.clientSum(nil)
+ } else {
+ finished.verifyData = hs.finishedHash.clientSum(hs.masterSecret)
+ }
+ c.clientVerify = append(c.clientVerify[:0], finished.verifyData...)
+ finishedBytes := finished.marshal()
+ hs.writeHash(finishedBytes, seqno)
+ postCCSBytes = append(postCCSBytes, finishedBytes...)
+
+ if c.config.Bugs.FragmentAcrossChangeCipherSpec {
+ c.writeRecord(recordTypeHandshake, postCCSBytes[:5])
+ postCCSBytes = postCCSBytes[5:]
+ }
+
+ if !c.config.Bugs.SkipChangeCipherSpec &&
+ c.config.Bugs.EarlyChangeCipherSpec == 0 {
+ c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
+ }
+
+ if c.config.Bugs.AppDataAfterChangeCipherSpec != nil {
+ c.writeRecord(recordTypeApplicationData, c.config.Bugs.AppDataAfterChangeCipherSpec)
+ }
+
+ c.writeRecord(recordTypeHandshake, postCCSBytes)
+ return nil
+}
+
+func (hs *clientHandshakeState) writeClientHash(msg []byte) {
+ // writeClientHash is called before writeRecord.
+ hs.writeHash(msg, hs.c.sendHandshakeSeq)
+}
+
+func (hs *clientHandshakeState) writeServerHash(msg []byte) {
+ // writeServerHash is called after readHandshake.
+ hs.writeHash(msg, hs.c.recvHandshakeSeq-1)
+}
+
+func (hs *clientHandshakeState) writeHash(msg []byte, seqno uint16) {
+ if hs.c.isDTLS {
+ // This is somewhat hacky. DTLS hashes a slightly different format.
+ // First, the TLS header.
+ hs.finishedHash.Write(msg[:4])
+ // Then the sequence number and reassembled fragment offset (always 0).
+ hs.finishedHash.Write([]byte{byte(seqno >> 8), byte(seqno), 0, 0, 0})
+ // Then the reassembled fragment (always equal to the message length).
+ hs.finishedHash.Write(msg[1:4])
+ // And then the message body.
+ hs.finishedHash.Write(msg[4:])
+ } else {
+ hs.finishedHash.Write(msg)
+ }
+}
+
+// clientSessionCacheKey returns a key used to cache sessionTickets that could
+// be used to resume previously negotiated TLS sessions with a server.
+func clientSessionCacheKey(serverAddr net.Addr, config *Config) string {
+ if len(config.ServerName) > 0 {
+ return config.ServerName
+ }
+ return serverAddr.String()
+}
+
+// mutualProtocol finds the mutual Next Protocol Negotiation or ALPN protocol
+// given list of possible protocols and a list of the preference order. The
+// first list must not be empty. It returns the resulting protocol and flag
+// indicating if the fallback case was reached.
+func mutualProtocol(protos, preferenceProtos []string) (string, bool) {
+ for _, s := range preferenceProtos {
+ for _, c := range protos {
+ if s == c {
+ return s, false
+ }
+ }
+ }
+
+ return protos[0], true
+}
+
+// writeIntPadded writes x into b, padded up with leading zeros as
+// needed.
+func writeIntPadded(b []byte, x *big.Int) {
+ for i := range b {
+ b[i] = 0
+ }
+ xb := x.Bytes()
+ copy(b[len(b)-len(xb):], xb)
+}
diff --git a/src/ssl/test/runner/handshake_messages.go b/src/ssl/test/runner/handshake_messages.go
new file mode 100644
index 0000000..ce214fd
--- /dev/null
+++ b/src/ssl/test/runner/handshake_messages.go
@@ -0,0 +1,1875 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "bytes"
+
+type clientHelloMsg struct {
+ raw []byte
+ isDTLS bool
+ vers uint16
+ random []byte
+ sessionId []byte
+ cookie []byte
+ cipherSuites []uint16
+ compressionMethods []uint8
+ nextProtoNeg bool
+ serverName string
+ ocspStapling bool
+ supportedCurves []CurveID
+ supportedPoints []uint8
+ ticketSupported bool
+ sessionTicket []uint8
+ signatureAndHashes []signatureAndHash
+ secureRenegotiation []byte
+ alpnProtocols []string
+ duplicateExtension bool
+ channelIDSupported bool
+ npnLast bool
+ extendedMasterSecret bool
+ srtpProtectionProfiles []uint16
+ srtpMasterKeyIdentifier string
+ sctListSupported bool
+}
+
+func (m *clientHelloMsg) equal(i interface{}) bool {
+ m1, ok := i.(*clientHelloMsg)
+ if !ok {
+ return false
+ }
+
+ return bytes.Equal(m.raw, m1.raw) &&
+ m.isDTLS == m1.isDTLS &&
+ m.vers == m1.vers &&
+ bytes.Equal(m.random, m1.random) &&
+ bytes.Equal(m.sessionId, m1.sessionId) &&
+ bytes.Equal(m.cookie, m1.cookie) &&
+ eqUint16s(m.cipherSuites, m1.cipherSuites) &&
+ bytes.Equal(m.compressionMethods, m1.compressionMethods) &&
+ m.nextProtoNeg == m1.nextProtoNeg &&
+ m.serverName == m1.serverName &&
+ m.ocspStapling == m1.ocspStapling &&
+ eqCurveIDs(m.supportedCurves, m1.supportedCurves) &&
+ bytes.Equal(m.supportedPoints, m1.supportedPoints) &&
+ m.ticketSupported == m1.ticketSupported &&
+ bytes.Equal(m.sessionTicket, m1.sessionTicket) &&
+ eqSignatureAndHashes(m.signatureAndHashes, m1.signatureAndHashes) &&
+ bytes.Equal(m.secureRenegotiation, m1.secureRenegotiation) &&
+ (m.secureRenegotiation == nil) == (m1.secureRenegotiation == nil) &&
+ eqStrings(m.alpnProtocols, m1.alpnProtocols) &&
+ m.duplicateExtension == m1.duplicateExtension &&
+ m.channelIDSupported == m1.channelIDSupported &&
+ m.npnLast == m1.npnLast &&
+ m.extendedMasterSecret == m1.extendedMasterSecret &&
+ eqUint16s(m.srtpProtectionProfiles, m1.srtpProtectionProfiles) &&
+ m.srtpMasterKeyIdentifier == m1.srtpMasterKeyIdentifier &&
+ m.sctListSupported == m1.sctListSupported
+}
+
+func (m *clientHelloMsg) marshal() []byte {
+ if m.raw != nil {
+ return m.raw
+ }
+
+ length := 2 + 32 + 1 + len(m.sessionId) + 2 + len(m.cipherSuites)*2 + 1 + len(m.compressionMethods)
+ if m.isDTLS {
+ length += 1 + len(m.cookie)
+ }
+ numExtensions := 0
+ extensionsLength := 0
+ if m.nextProtoNeg {
+ numExtensions++
+ }
+ if m.ocspStapling {
+ extensionsLength += 1 + 2 + 2
+ numExtensions++
+ }
+ if len(m.serverName) > 0 {
+ extensionsLength += 5 + len(m.serverName)
+ numExtensions++
+ }
+ if len(m.supportedCurves) > 0 {
+ extensionsLength += 2 + 2*len(m.supportedCurves)
+ numExtensions++
+ }
+ if len(m.supportedPoints) > 0 {
+ extensionsLength += 1 + len(m.supportedPoints)
+ numExtensions++
+ }
+ if m.ticketSupported {
+ extensionsLength += len(m.sessionTicket)
+ numExtensions++
+ }
+ if len(m.signatureAndHashes) > 0 {
+ extensionsLength += 2 + 2*len(m.signatureAndHashes)
+ numExtensions++
+ }
+ if m.secureRenegotiation != nil {
+ extensionsLength += 1 + len(m.secureRenegotiation)
+ numExtensions++
+ }
+ if m.duplicateExtension {
+ numExtensions += 2
+ }
+ if m.channelIDSupported {
+ numExtensions++
+ }
+ if len(m.alpnProtocols) > 0 {
+ extensionsLength += 2
+ for _, s := range m.alpnProtocols {
+ if l := len(s); l == 0 || l > 255 {
+ panic("invalid ALPN protocol")
+ }
+ extensionsLength++
+ extensionsLength += len(s)
+ }
+ numExtensions++
+ }
+ if m.extendedMasterSecret {
+ numExtensions++
+ }
+ if len(m.srtpProtectionProfiles) > 0 {
+ extensionsLength += 2 + 2*len(m.srtpProtectionProfiles)
+ extensionsLength += 1 + len(m.srtpMasterKeyIdentifier)
+ numExtensions++
+ }
+ if m.sctListSupported {
+ numExtensions++
+ }
+ if numExtensions > 0 {
+ extensionsLength += 4 * numExtensions
+ length += 2 + extensionsLength
+ }
+
+ x := make([]byte, 4+length)
+ x[0] = typeClientHello
+ x[1] = uint8(length >> 16)
+ x[2] = uint8(length >> 8)
+ x[3] = uint8(length)
+ vers := versionToWire(m.vers, m.isDTLS)
+ x[4] = uint8(vers >> 8)
+ x[5] = uint8(vers)
+ copy(x[6:38], m.random)
+ x[38] = uint8(len(m.sessionId))
+ copy(x[39:39+len(m.sessionId)], m.sessionId)
+ y := x[39+len(m.sessionId):]
+ if m.isDTLS {
+ y[0] = uint8(len(m.cookie))
+ copy(y[1:], m.cookie)
+ y = y[1+len(m.cookie):]
+ }
+ y[0] = uint8(len(m.cipherSuites) >> 7)
+ y[1] = uint8(len(m.cipherSuites) << 1)
+ for i, suite := range m.cipherSuites {
+ y[2+i*2] = uint8(suite >> 8)
+ y[3+i*2] = uint8(suite)
+ }
+ z := y[2+len(m.cipherSuites)*2:]
+ z[0] = uint8(len(m.compressionMethods))
+ copy(z[1:], m.compressionMethods)
+
+ z = z[1+len(m.compressionMethods):]
+ if numExtensions > 0 {
+ z[0] = byte(extensionsLength >> 8)
+ z[1] = byte(extensionsLength)
+ z = z[2:]
+ }
+ if m.duplicateExtension {
+ // Add a duplicate bogus extension at the beginning and end.
+ z[0] = 0xff
+ z[1] = 0xff
+ z = z[4:]
+ }
+ if m.nextProtoNeg && !m.npnLast {
+ z[0] = byte(extensionNextProtoNeg >> 8)
+ z[1] = byte(extensionNextProtoNeg & 0xff)
+ // The length is always 0
+ z = z[4:]
+ }
+ if len(m.serverName) > 0 {
+ z[0] = byte(extensionServerName >> 8)
+ z[1] = byte(extensionServerName & 0xff)
+ l := len(m.serverName) + 5
+ z[2] = byte(l >> 8)
+ z[3] = byte(l)
+ z = z[4:]
+
+ // RFC 3546, section 3.1
+ //
+ // struct {
+ // NameType name_type;
+ // select (name_type) {
+ // case host_name: HostName;
+ // } name;
+ // } ServerName;
+ //
+ // enum {
+ // host_name(0), (255)
+ // } NameType;
+ //
+ // opaque HostName<1..2^16-1>;
+ //
+ // struct {
+ // ServerName server_name_list<1..2^16-1>
+ // } ServerNameList;
+
+ z[0] = byte((len(m.serverName) + 3) >> 8)
+ z[1] = byte(len(m.serverName) + 3)
+ z[3] = byte(len(m.serverName) >> 8)
+ z[4] = byte(len(m.serverName))
+ copy(z[5:], []byte(m.serverName))
+ z = z[l:]
+ }
+ if m.ocspStapling {
+ // RFC 4366, section 3.6
+ z[0] = byte(extensionStatusRequest >> 8)
+ z[1] = byte(extensionStatusRequest)
+ z[2] = 0
+ z[3] = 5
+ z[4] = 1 // OCSP type
+ // Two zero valued uint16s for the two lengths.
+ z = z[9:]
+ }
+ if len(m.supportedCurves) > 0 {
+ // http://tools.ietf.org/html/rfc4492#section-5.5.1
+ z[0] = byte(extensionSupportedCurves >> 8)
+ z[1] = byte(extensionSupportedCurves)
+ l := 2 + 2*len(m.supportedCurves)
+ z[2] = byte(l >> 8)
+ z[3] = byte(l)
+ l -= 2
+ z[4] = byte(l >> 8)
+ z[5] = byte(l)
+ z = z[6:]
+ for _, curve := range m.supportedCurves {
+ z[0] = byte(curve >> 8)
+ z[1] = byte(curve)
+ z = z[2:]
+ }
+ }
+ if len(m.supportedPoints) > 0 {
+ // http://tools.ietf.org/html/rfc4492#section-5.5.2
+ z[0] = byte(extensionSupportedPoints >> 8)
+ z[1] = byte(extensionSupportedPoints)
+ l := 1 + len(m.supportedPoints)
+ z[2] = byte(l >> 8)
+ z[3] = byte(l)
+ l--
+ z[4] = byte(l)
+ z = z[5:]
+ for _, pointFormat := range m.supportedPoints {
+ z[0] = byte(pointFormat)
+ z = z[1:]
+ }
+ }
+ if m.ticketSupported {
+ // http://tools.ietf.org/html/rfc5077#section-3.2
+ z[0] = byte(extensionSessionTicket >> 8)
+ z[1] = byte(extensionSessionTicket)
+ l := len(m.sessionTicket)
+ z[2] = byte(l >> 8)
+ z[3] = byte(l)
+ z = z[4:]
+ copy(z, m.sessionTicket)
+ z = z[len(m.sessionTicket):]
+ }
+ if len(m.signatureAndHashes) > 0 {
+ // https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
+ z[0] = byte(extensionSignatureAlgorithms >> 8)
+ z[1] = byte(extensionSignatureAlgorithms)
+ l := 2 + 2*len(m.signatureAndHashes)
+ z[2] = byte(l >> 8)
+ z[3] = byte(l)
+ z = z[4:]
+
+ l -= 2
+ z[0] = byte(l >> 8)
+ z[1] = byte(l)
+ z = z[2:]
+ for _, sigAndHash := range m.signatureAndHashes {
+ z[0] = sigAndHash.hash
+ z[1] = sigAndHash.signature
+ z = z[2:]
+ }
+ }
+ if m.secureRenegotiation != nil {
+ z[0] = byte(extensionRenegotiationInfo >> 8)
+ z[1] = byte(extensionRenegotiationInfo & 0xff)
+ z[2] = 0
+ z[3] = byte(1 + len(m.secureRenegotiation))
+ z[4] = byte(len(m.secureRenegotiation))
+ z = z[5:]
+ copy(z, m.secureRenegotiation)
+ z = z[len(m.secureRenegotiation):]
+ }
+ if len(m.alpnProtocols) > 0 {
+ z[0] = byte(extensionALPN >> 8)
+ z[1] = byte(extensionALPN & 0xff)
+ lengths := z[2:]
+ z = z[6:]
+
+ stringsLength := 0
+ for _, s := range m.alpnProtocols {
+ l := len(s)
+ z[0] = byte(l)
+ copy(z[1:], s)
+ z = z[1+l:]
+ stringsLength += 1 + l
+ }
+
+ lengths[2] = byte(stringsLength >> 8)
+ lengths[3] = byte(stringsLength)
+ stringsLength += 2
+ lengths[0] = byte(stringsLength >> 8)
+ lengths[1] = byte(stringsLength)
+ }
+ if m.channelIDSupported {
+ z[0] = byte(extensionChannelID >> 8)
+ z[1] = byte(extensionChannelID & 0xff)
+ z = z[4:]
+ }
+ if m.nextProtoNeg && m.npnLast {
+ z[0] = byte(extensionNextProtoNeg >> 8)
+ z[1] = byte(extensionNextProtoNeg & 0xff)
+ // The length is always 0
+ z = z[4:]
+ }
+ if m.duplicateExtension {
+ // Add a duplicate bogus extension at the beginning and end.
+ z[0] = 0xff
+ z[1] = 0xff
+ z = z[4:]
+ }
+ if m.extendedMasterSecret {
+ // https://tools.ietf.org/html/draft-ietf-tls-session-hash-01
+ z[0] = byte(extensionExtendedMasterSecret >> 8)
+ z[1] = byte(extensionExtendedMasterSecret & 0xff)
+ z = z[4:]
+ }
+ if len(m.srtpProtectionProfiles) > 0 {
+ z[0] = byte(extensionUseSRTP >> 8)
+ z[1] = byte(extensionUseSRTP & 0xff)
+
+ profilesLen := 2 * len(m.srtpProtectionProfiles)
+ mkiLen := len(m.srtpMasterKeyIdentifier)
+ l := 2 + profilesLen + 1 + mkiLen
+ z[2] = byte(l >> 8)
+ z[3] = byte(l & 0xff)
+
+ z[4] = byte(profilesLen >> 8)
+ z[5] = byte(profilesLen & 0xff)
+ z = z[6:]
+ for _, p := range m.srtpProtectionProfiles {
+ z[0] = byte(p >> 8)
+ z[1] = byte(p & 0xff)
+ z = z[2:]
+ }
+
+ z[0] = byte(mkiLen)
+ copy(z[1:], []byte(m.srtpMasterKeyIdentifier))
+ z = z[1+mkiLen:]
+ }
+ if m.sctListSupported {
+ z[0] = byte(extensionSignedCertificateTimestamp >> 8)
+ z[1] = byte(extensionSignedCertificateTimestamp & 0xff)
+ z = z[4:]
+ }
+
+ m.raw = x
+
+ return x
+}
+
+func (m *clientHelloMsg) unmarshal(data []byte) bool {
+ if len(data) < 42 {
+ return false
+ }
+ m.raw = data
+ m.vers = wireToVersion(uint16(data[4])<<8|uint16(data[5]), m.isDTLS)
+ m.random = data[6:38]
+ sessionIdLen := int(data[38])
+ if sessionIdLen > 32 || len(data) < 39+sessionIdLen {
+ return false
+ }
+ m.sessionId = data[39 : 39+sessionIdLen]
+ data = data[39+sessionIdLen:]
+ if m.isDTLS {
+ if len(data) < 1 {
+ return false
+ }
+ cookieLen := int(data[0])
+ if cookieLen > 32 || len(data) < 1+cookieLen {
+ return false
+ }
+ m.cookie = data[1 : 1+cookieLen]
+ data = data[1+cookieLen:]
+ }
+ if len(data) < 2 {
+ return false
+ }
+ // cipherSuiteLen is the number of bytes of cipher suite numbers. Since
+ // they are uint16s, the number must be even.
+ cipherSuiteLen := int(data[0])<<8 | int(data[1])
+ if cipherSuiteLen%2 == 1 || len(data) < 2+cipherSuiteLen {
+ return false
+ }
+ numCipherSuites := cipherSuiteLen / 2
+ m.cipherSuites = make([]uint16, numCipherSuites)
+ for i := 0; i < numCipherSuites; i++ {
+ m.cipherSuites[i] = uint16(data[2+2*i])<<8 | uint16(data[3+2*i])
+ if m.cipherSuites[i] == scsvRenegotiation {
+ m.secureRenegotiation = []byte{}
+ }
+ }
+ data = data[2+cipherSuiteLen:]
+ if len(data) < 1 {
+ return false
+ }
+ compressionMethodsLen := int(data[0])
+ if len(data) < 1+compressionMethodsLen {
+ return false
+ }
+ m.compressionMethods = data[1 : 1+compressionMethodsLen]
+
+ data = data[1+compressionMethodsLen:]
+
+ m.nextProtoNeg = false
+ m.serverName = ""
+ m.ocspStapling = false
+ m.ticketSupported = false
+ m.sessionTicket = nil
+ m.signatureAndHashes = nil
+ m.alpnProtocols = nil
+ m.extendedMasterSecret = false
+
+ if len(data) == 0 {
+ // ClientHello is optionally followed by extension data
+ return true
+ }
+ if len(data) < 2 {
+ return false
+ }
+
+ extensionsLength := int(data[0])<<8 | int(data[1])
+ data = data[2:]
+ if extensionsLength != len(data) {
+ return false
+ }
+
+ for len(data) != 0 {
+ if len(data) < 4 {
+ return false
+ }
+ extension := uint16(data[0])<<8 | uint16(data[1])
+ length := int(data[2])<<8 | int(data[3])
+ data = data[4:]
+ if len(data) < length {
+ return false
+ }
+
+ switch extension {
+ case extensionServerName:
+ if length < 2 {
+ return false
+ }
+ numNames := int(data[0])<<8 | int(data[1])
+ d := data[2:]
+ for i := 0; i < numNames; i++ {
+ if len(d) < 3 {
+ return false
+ }
+ nameType := d[0]
+ nameLen := int(d[1])<<8 | int(d[2])
+ d = d[3:]
+ if len(d) < nameLen {
+ return false
+ }
+ if nameType == 0 {
+ m.serverName = string(d[0:nameLen])
+ break
+ }
+ d = d[nameLen:]
+ }
+ case extensionNextProtoNeg:
+ if length > 0 {
+ return false
+ }
+ m.nextProtoNeg = true
+ case extensionStatusRequest:
+ m.ocspStapling = length > 0 && data[0] == statusTypeOCSP
+ case extensionSupportedCurves:
+ // http://tools.ietf.org/html/rfc4492#section-5.5.1
+ if length < 2 {
+ return false
+ }
+ l := int(data[0])<<8 | int(data[1])
+ if l%2 == 1 || length != l+2 {
+ return false
+ }
+ numCurves := l / 2
+ m.supportedCurves = make([]CurveID, numCurves)
+ d := data[2:]
+ for i := 0; i < numCurves; i++ {
+ m.supportedCurves[i] = CurveID(d[0])<<8 | CurveID(d[1])
+ d = d[2:]
+ }
+ case extensionSupportedPoints:
+ // http://tools.ietf.org/html/rfc4492#section-5.5.2
+ if length < 1 {
+ return false
+ }
+ l := int(data[0])
+ if length != l+1 {
+ return false
+ }
+ m.supportedPoints = make([]uint8, l)
+ copy(m.supportedPoints, data[1:])
+ case extensionSessionTicket:
+ // http://tools.ietf.org/html/rfc5077#section-3.2
+ m.ticketSupported = true
+ m.sessionTicket = data[:length]
+ case extensionSignatureAlgorithms:
+ // https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
+ if length < 2 || length&1 != 0 {
+ return false
+ }
+ l := int(data[0])<<8 | int(data[1])
+ if l != length-2 {
+ return false
+ }
+ n := l / 2
+ d := data[2:]
+ m.signatureAndHashes = make([]signatureAndHash, n)
+ for i := range m.signatureAndHashes {
+ m.signatureAndHashes[i].hash = d[0]
+ m.signatureAndHashes[i].signature = d[1]
+ d = d[2:]
+ }
+ case extensionRenegotiationInfo:
+ if length < 1 || length != int(data[0])+1 {
+ return false
+ }
+ m.secureRenegotiation = data[1:length]
+ case extensionALPN:
+ if length < 2 {
+ return false
+ }
+ l := int(data[0])<<8 | int(data[1])
+ if l != length-2 {
+ return false
+ }
+ d := data[2:length]
+ for len(d) != 0 {
+ stringLen := int(d[0])
+ d = d[1:]
+ if stringLen == 0 || stringLen > len(d) {
+ return false
+ }
+ m.alpnProtocols = append(m.alpnProtocols, string(d[:stringLen]))
+ d = d[stringLen:]
+ }
+ case extensionChannelID:
+ if length > 0 {
+ return false
+ }
+ m.channelIDSupported = true
+ case extensionExtendedMasterSecret:
+ if length != 0 {
+ return false
+ }
+ m.extendedMasterSecret = true
+ case extensionUseSRTP:
+ if length < 2 {
+ return false
+ }
+ l := int(data[0])<<8 | int(data[1])
+ if l > length-2 || l%2 != 0 {
+ return false
+ }
+ n := l / 2
+ m.srtpProtectionProfiles = make([]uint16, n)
+ d := data[2:length]
+ for i := 0; i < n; i++ {
+ m.srtpProtectionProfiles[i] = uint16(d[0])<<8 | uint16(d[1])
+ d = d[2:]
+ }
+ if len(d) < 1 || int(d[0]) != len(d)-1 {
+ return false
+ }
+ m.srtpMasterKeyIdentifier = string(d[1:])
+ case extensionSignedCertificateTimestamp:
+ if length != 0 {
+ return false
+ }
+ m.sctListSupported = true
+ }
+ data = data[length:]
+ }
+
+ return true
+}
+
+type serverHelloMsg struct {
+ raw []byte
+ isDTLS bool
+ vers uint16
+ random []byte
+ sessionId []byte
+ cipherSuite uint16
+ compressionMethod uint8
+ nextProtoNeg bool
+ nextProtos []string
+ ocspStapling bool
+ ticketSupported bool
+ secureRenegotiation []byte
+ alpnProtocol string
+ duplicateExtension bool
+ channelIDRequested bool
+ extendedMasterSecret bool
+ srtpProtectionProfile uint16
+ srtpMasterKeyIdentifier string
+ sctList []byte
+}
+
+func (m *serverHelloMsg) equal(i interface{}) bool {
+ m1, ok := i.(*serverHelloMsg)
+ if !ok {
+ return false
+ }
+
+ return bytes.Equal(m.raw, m1.raw) &&
+ m.isDTLS == m1.isDTLS &&
+ m.vers == m1.vers &&
+ bytes.Equal(m.random, m1.random) &&
+ bytes.Equal(m.sessionId, m1.sessionId) &&
+ m.cipherSuite == m1.cipherSuite &&
+ m.compressionMethod == m1.compressionMethod &&
+ m.nextProtoNeg == m1.nextProtoNeg &&
+ eqStrings(m.nextProtos, m1.nextProtos) &&
+ m.ocspStapling == m1.ocspStapling &&
+ m.ticketSupported == m1.ticketSupported &&
+ bytes.Equal(m.secureRenegotiation, m1.secureRenegotiation) &&
+ (m.secureRenegotiation == nil) == (m1.secureRenegotiation == nil) &&
+ m.alpnProtocol == m1.alpnProtocol &&
+ m.duplicateExtension == m1.duplicateExtension &&
+ m.channelIDRequested == m1.channelIDRequested &&
+ m.extendedMasterSecret == m1.extendedMasterSecret &&
+ m.srtpProtectionProfile == m1.srtpProtectionProfile &&
+ m.srtpMasterKeyIdentifier == m1.srtpMasterKeyIdentifier &&
+ bytes.Equal(m.sctList, m1.sctList)
+}
+
+func (m *serverHelloMsg) marshal() []byte {
+ if m.raw != nil {
+ return m.raw
+ }
+
+ length := 38 + len(m.sessionId)
+ numExtensions := 0
+ extensionsLength := 0
+
+ nextProtoLen := 0
+ if m.nextProtoNeg {
+ numExtensions++
+ for _, v := range m.nextProtos {
+ nextProtoLen += len(v)
+ }
+ nextProtoLen += len(m.nextProtos)
+ extensionsLength += nextProtoLen
+ }
+ if m.ocspStapling {
+ numExtensions++
+ }
+ if m.ticketSupported {
+ numExtensions++
+ }
+ if m.secureRenegotiation != nil {
+ extensionsLength += 1 + len(m.secureRenegotiation)
+ numExtensions++
+ }
+ if m.duplicateExtension {
+ numExtensions += 2
+ }
+ if m.channelIDRequested {
+ numExtensions++
+ }
+ if alpnLen := len(m.alpnProtocol); alpnLen > 0 {
+ if alpnLen >= 256 {
+ panic("invalid ALPN protocol")
+ }
+ extensionsLength += 2 + 1 + alpnLen
+ numExtensions++
+ }
+ if m.extendedMasterSecret {
+ numExtensions++
+ }
+ if m.srtpProtectionProfile != 0 {
+ extensionsLength += 2 + 2 + 1 + len(m.srtpMasterKeyIdentifier)
+ numExtensions++
+ }
+ if m.sctList != nil {
+ extensionsLength += len(m.sctList)
+ numExtensions++
+ }
+
+ if numExtensions > 0 {
+ extensionsLength += 4 * numExtensions
+ length += 2 + extensionsLength
+ }
+
+ x := make([]byte, 4+length)
+ x[0] = typeServerHello
+ x[1] = uint8(length >> 16)
+ x[2] = uint8(length >> 8)
+ x[3] = uint8(length)
+ vers := versionToWire(m.vers, m.isDTLS)
+ x[4] = uint8(vers >> 8)
+ x[5] = uint8(vers)
+ copy(x[6:38], m.random)
+ x[38] = uint8(len(m.sessionId))
+ copy(x[39:39+len(m.sessionId)], m.sessionId)
+ z := x[39+len(m.sessionId):]
+ z[0] = uint8(m.cipherSuite >> 8)
+ z[1] = uint8(m.cipherSuite)
+ z[2] = uint8(m.compressionMethod)
+
+ z = z[3:]
+ if numExtensions > 0 {
+ z[0] = byte(extensionsLength >> 8)
+ z[1] = byte(extensionsLength)
+ z = z[2:]
+ }
+ if m.duplicateExtension {
+ // Add a duplicate bogus extension at the beginning and end.
+ z[0] = 0xff
+ z[1] = 0xff
+ z = z[4:]
+ }
+ if m.nextProtoNeg {
+ z[0] = byte(extensionNextProtoNeg >> 8)
+ z[1] = byte(extensionNextProtoNeg & 0xff)
+ z[2] = byte(nextProtoLen >> 8)
+ z[3] = byte(nextProtoLen)
+ z = z[4:]
+
+ for _, v := range m.nextProtos {
+ l := len(v)
+ if l > 255 {
+ l = 255
+ }
+ z[0] = byte(l)
+ copy(z[1:], []byte(v[0:l]))
+ z = z[1+l:]
+ }
+ }
+ if m.ocspStapling {
+ z[0] = byte(extensionStatusRequest >> 8)
+ z[1] = byte(extensionStatusRequest)
+ z = z[4:]
+ }
+ if m.ticketSupported {
+ z[0] = byte(extensionSessionTicket >> 8)
+ z[1] = byte(extensionSessionTicket)
+ z = z[4:]
+ }
+ if m.secureRenegotiation != nil {
+ z[0] = byte(extensionRenegotiationInfo >> 8)
+ z[1] = byte(extensionRenegotiationInfo & 0xff)
+ z[2] = 0
+ z[3] = byte(1 + len(m.secureRenegotiation))
+ z[4] = byte(len(m.secureRenegotiation))
+ z = z[5:]
+ copy(z, m.secureRenegotiation)
+ z = z[len(m.secureRenegotiation):]
+ }
+ if alpnLen := len(m.alpnProtocol); alpnLen > 0 {
+ z[0] = byte(extensionALPN >> 8)
+ z[1] = byte(extensionALPN & 0xff)
+ l := 2 + 1 + alpnLen
+ z[2] = byte(l >> 8)
+ z[3] = byte(l)
+ l -= 2
+ z[4] = byte(l >> 8)
+ z[5] = byte(l)
+ l -= 1
+ z[6] = byte(l)
+ copy(z[7:], []byte(m.alpnProtocol))
+ z = z[7+alpnLen:]
+ }
+ if m.channelIDRequested {
+ z[0] = byte(extensionChannelID >> 8)
+ z[1] = byte(extensionChannelID & 0xff)
+ z = z[4:]
+ }
+ if m.duplicateExtension {
+ // Add a duplicate bogus extension at the beginning and end.
+ z[0] = 0xff
+ z[1] = 0xff
+ z = z[4:]
+ }
+ if m.extendedMasterSecret {
+ z[0] = byte(extensionExtendedMasterSecret >> 8)
+ z[1] = byte(extensionExtendedMasterSecret & 0xff)
+ z = z[4:]
+ }
+ if m.srtpProtectionProfile != 0 {
+ z[0] = byte(extensionUseSRTP >> 8)
+ z[1] = byte(extensionUseSRTP & 0xff)
+ l := 2 + 2 + 1 + len(m.srtpMasterKeyIdentifier)
+ z[2] = byte(l >> 8)
+ z[3] = byte(l & 0xff)
+ z[4] = 0
+ z[5] = 2
+ z[6] = byte(m.srtpProtectionProfile >> 8)
+ z[7] = byte(m.srtpProtectionProfile & 0xff)
+ l = len(m.srtpMasterKeyIdentifier)
+ z[8] = byte(l)
+ copy(z[9:], []byte(m.srtpMasterKeyIdentifier))
+ z = z[9+l:]
+ }
+ if m.sctList != nil {
+ z[0] = byte(extensionSignedCertificateTimestamp >> 8)
+ z[1] = byte(extensionSignedCertificateTimestamp & 0xff)
+ l := len(m.sctList)
+ z[2] = byte(l >> 8)
+ z[3] = byte(l & 0xff)
+ copy(z[4:], m.sctList)
+ z = z[4+l:]
+ }
+
+ m.raw = x
+
+ return x
+}
+
+func (m *serverHelloMsg) unmarshal(data []byte) bool {
+ if len(data) < 42 {
+ return false
+ }
+ m.raw = data
+ m.vers = wireToVersion(uint16(data[4])<<8|uint16(data[5]), m.isDTLS)
+ m.random = data[6:38]
+ sessionIdLen := int(data[38])
+ if sessionIdLen > 32 || len(data) < 39+sessionIdLen {
+ return false
+ }
+ m.sessionId = data[39 : 39+sessionIdLen]
+ data = data[39+sessionIdLen:]
+ if len(data) < 3 {
+ return false
+ }
+ m.cipherSuite = uint16(data[0])<<8 | uint16(data[1])
+ m.compressionMethod = data[2]
+ data = data[3:]
+
+ m.nextProtoNeg = false
+ m.nextProtos = nil
+ m.ocspStapling = false
+ m.ticketSupported = false
+ m.alpnProtocol = ""
+ m.extendedMasterSecret = false
+
+ if len(data) == 0 {
+ // ServerHello is optionally followed by extension data
+ return true
+ }
+ if len(data) < 2 {
+ return false
+ }
+
+ extensionsLength := int(data[0])<<8 | int(data[1])
+ data = data[2:]
+ if len(data) != extensionsLength {
+ return false
+ }
+
+ for len(data) != 0 {
+ if len(data) < 4 {
+ return false
+ }
+ extension := uint16(data[0])<<8 | uint16(data[1])
+ length := int(data[2])<<8 | int(data[3])
+ data = data[4:]
+ if len(data) < length {
+ return false
+ }
+
+ switch extension {
+ case extensionNextProtoNeg:
+ m.nextProtoNeg = true
+ d := data[:length]
+ for len(d) > 0 {
+ l := int(d[0])
+ d = d[1:]
+ if l == 0 || l > len(d) {
+ return false
+ }
+ m.nextProtos = append(m.nextProtos, string(d[:l]))
+ d = d[l:]
+ }
+ case extensionStatusRequest:
+ if length > 0 {
+ return false
+ }
+ m.ocspStapling = true
+ case extensionSessionTicket:
+ if length > 0 {
+ return false
+ }
+ m.ticketSupported = true
+ case extensionRenegotiationInfo:
+ if length < 1 || length != int(data[0])+1 {
+ return false
+ }
+ m.secureRenegotiation = data[1:length]
+ case extensionALPN:
+ d := data[:length]
+ if len(d) < 3 {
+ return false
+ }
+ l := int(d[0])<<8 | int(d[1])
+ if l != len(d)-2 {
+ return false
+ }
+ d = d[2:]
+ l = int(d[0])
+ if l != len(d)-1 {
+ return false
+ }
+ d = d[1:]
+ m.alpnProtocol = string(d)
+ case extensionChannelID:
+ if length > 0 {
+ return false
+ }
+ m.channelIDRequested = true
+ case extensionExtendedMasterSecret:
+ if length != 0 {
+ return false
+ }
+ m.extendedMasterSecret = true
+ case extensionUseSRTP:
+ if length < 2+2+1 {
+ return false
+ }
+ if data[0] != 0 || data[1] != 2 {
+ return false
+ }
+ m.srtpProtectionProfile = uint16(data[2])<<8 | uint16(data[3])
+ d := data[4:length]
+ l := int(d[0])
+ if l != len(d)-1 {
+ return false
+ }
+ m.srtpMasterKeyIdentifier = string(d[1:])
+ case extensionSignedCertificateTimestamp:
+ if length < 2 {
+ return false
+ }
+ l := int(data[0])<<8 | int(data[1])
+ if l != len(data)-2 {
+ return false
+ }
+ m.sctList = data[2:length]
+ }
+ data = data[length:]
+ }
+
+ return true
+}
+
+type certificateMsg struct {
+ raw []byte
+ certificates [][]byte
+}
+
+func (m *certificateMsg) equal(i interface{}) bool {
+ m1, ok := i.(*certificateMsg)
+ if !ok {
+ return false
+ }
+
+ return bytes.Equal(m.raw, m1.raw) &&
+ eqByteSlices(m.certificates, m1.certificates)
+}
+
+func (m *certificateMsg) marshal() (x []byte) {
+ if m.raw != nil {
+ return m.raw
+ }
+
+ var i int
+ for _, slice := range m.certificates {
+ i += len(slice)
+ }
+
+ length := 3 + 3*len(m.certificates) + i
+ x = make([]byte, 4+length)
+ x[0] = typeCertificate
+ x[1] = uint8(length >> 16)
+ x[2] = uint8(length >> 8)
+ x[3] = uint8(length)
+
+ certificateOctets := length - 3
+ x[4] = uint8(certificateOctets >> 16)
+ x[5] = uint8(certificateOctets >> 8)
+ x[6] = uint8(certificateOctets)
+
+ y := x[7:]
+ for _, slice := range m.certificates {
+ y[0] = uint8(len(slice) >> 16)
+ y[1] = uint8(len(slice) >> 8)
+ y[2] = uint8(len(slice))
+ copy(y[3:], slice)
+ y = y[3+len(slice):]
+ }
+
+ m.raw = x
+ return
+}
+
+func (m *certificateMsg) unmarshal(data []byte) bool {
+ if len(data) < 7 {
+ return false
+ }
+
+ m.raw = data
+ certsLen := uint32(data[4])<<16 | uint32(data[5])<<8 | uint32(data[6])
+ if uint32(len(data)) != certsLen+7 {
+ return false
+ }
+
+ numCerts := 0
+ d := data[7:]
+ for certsLen > 0 {
+ if len(d) < 4 {
+ return false
+ }
+ certLen := uint32(d[0])<<16 | uint32(d[1])<<8 | uint32(d[2])
+ if uint32(len(d)) < 3+certLen {
+ return false
+ }
+ d = d[3+certLen:]
+ certsLen -= 3 + certLen
+ numCerts++
+ }
+
+ m.certificates = make([][]byte, numCerts)
+ d = data[7:]
+ for i := 0; i < numCerts; i++ {
+ certLen := uint32(d[0])<<16 | uint32(d[1])<<8 | uint32(d[2])
+ m.certificates[i] = d[3 : 3+certLen]
+ d = d[3+certLen:]
+ }
+
+ return true
+}
+
+type serverKeyExchangeMsg struct {
+ raw []byte
+ key []byte
+}
+
+func (m *serverKeyExchangeMsg) equal(i interface{}) bool {
+ m1, ok := i.(*serverKeyExchangeMsg)
+ if !ok {
+ return false
+ }
+
+ return bytes.Equal(m.raw, m1.raw) &&
+ bytes.Equal(m.key, m1.key)
+}
+
+func (m *serverKeyExchangeMsg) marshal() []byte {
+ if m.raw != nil {
+ return m.raw
+ }
+ length := len(m.key)
+ x := make([]byte, length+4)
+ x[0] = typeServerKeyExchange
+ x[1] = uint8(length >> 16)
+ x[2] = uint8(length >> 8)
+ x[3] = uint8(length)
+ copy(x[4:], m.key)
+
+ m.raw = x
+ return x
+}
+
+func (m *serverKeyExchangeMsg) unmarshal(data []byte) bool {
+ m.raw = data
+ if len(data) < 4 {
+ return false
+ }
+ m.key = data[4:]
+ return true
+}
+
+type certificateStatusMsg struct {
+ raw []byte
+ statusType uint8
+ response []byte
+}
+
+func (m *certificateStatusMsg) equal(i interface{}) bool {
+ m1, ok := i.(*certificateStatusMsg)
+ if !ok {
+ return false
+ }
+
+ return bytes.Equal(m.raw, m1.raw) &&
+ m.statusType == m1.statusType &&
+ bytes.Equal(m.response, m1.response)
+}
+
+func (m *certificateStatusMsg) marshal() []byte {
+ if m.raw != nil {
+ return m.raw
+ }
+
+ var x []byte
+ if m.statusType == statusTypeOCSP {
+ x = make([]byte, 4+4+len(m.response))
+ x[0] = typeCertificateStatus
+ l := len(m.response) + 4
+ x[1] = byte(l >> 16)
+ x[2] = byte(l >> 8)
+ x[3] = byte(l)
+ x[4] = statusTypeOCSP
+
+ l -= 4
+ x[5] = byte(l >> 16)
+ x[6] = byte(l >> 8)
+ x[7] = byte(l)
+ copy(x[8:], m.response)
+ } else {
+ x = []byte{typeCertificateStatus, 0, 0, 1, m.statusType}
+ }
+
+ m.raw = x
+ return x
+}
+
+func (m *certificateStatusMsg) unmarshal(data []byte) bool {
+ m.raw = data
+ if len(data) < 5 {
+ return false
+ }
+ m.statusType = data[4]
+
+ m.response = nil
+ if m.statusType == statusTypeOCSP {
+ if len(data) < 8 {
+ return false
+ }
+ respLen := uint32(data[5])<<16 | uint32(data[6])<<8 | uint32(data[7])
+ if uint32(len(data)) != 4+4+respLen {
+ return false
+ }
+ m.response = data[8:]
+ }
+ return true
+}
+
+type serverHelloDoneMsg struct{}
+
+func (m *serverHelloDoneMsg) equal(i interface{}) bool {
+ _, ok := i.(*serverHelloDoneMsg)
+ return ok
+}
+
+func (m *serverHelloDoneMsg) marshal() []byte {
+ x := make([]byte, 4)
+ x[0] = typeServerHelloDone
+ return x
+}
+
+func (m *serverHelloDoneMsg) unmarshal(data []byte) bool {
+ return len(data) == 4
+}
+
+type clientKeyExchangeMsg struct {
+ raw []byte
+ ciphertext []byte
+}
+
+func (m *clientKeyExchangeMsg) equal(i interface{}) bool {
+ m1, ok := i.(*clientKeyExchangeMsg)
+ if !ok {
+ return false
+ }
+
+ return bytes.Equal(m.raw, m1.raw) &&
+ bytes.Equal(m.ciphertext, m1.ciphertext)
+}
+
+func (m *clientKeyExchangeMsg) marshal() []byte {
+ if m.raw != nil {
+ return m.raw
+ }
+ length := len(m.ciphertext)
+ x := make([]byte, length+4)
+ x[0] = typeClientKeyExchange
+ x[1] = uint8(length >> 16)
+ x[2] = uint8(length >> 8)
+ x[3] = uint8(length)
+ copy(x[4:], m.ciphertext)
+
+ m.raw = x
+ return x
+}
+
+func (m *clientKeyExchangeMsg) unmarshal(data []byte) bool {
+ m.raw = data
+ if len(data) < 4 {
+ return false
+ }
+ l := int(data[1])<<16 | int(data[2])<<8 | int(data[3])
+ if l != len(data)-4 {
+ return false
+ }
+ m.ciphertext = data[4:]
+ return true
+}
+
+type finishedMsg struct {
+ raw []byte
+ verifyData []byte
+}
+
+func (m *finishedMsg) equal(i interface{}) bool {
+ m1, ok := i.(*finishedMsg)
+ if !ok {
+ return false
+ }
+
+ return bytes.Equal(m.raw, m1.raw) &&
+ bytes.Equal(m.verifyData, m1.verifyData)
+}
+
+func (m *finishedMsg) marshal() (x []byte) {
+ if m.raw != nil {
+ return m.raw
+ }
+
+ x = make([]byte, 4+len(m.verifyData))
+ x[0] = typeFinished
+ x[3] = byte(len(m.verifyData))
+ copy(x[4:], m.verifyData)
+ m.raw = x
+ return
+}
+
+func (m *finishedMsg) unmarshal(data []byte) bool {
+ m.raw = data
+ if len(data) < 4 {
+ return false
+ }
+ m.verifyData = data[4:]
+ return true
+}
+
+type nextProtoMsg struct {
+ raw []byte
+ proto string
+}
+
+func (m *nextProtoMsg) equal(i interface{}) bool {
+ m1, ok := i.(*nextProtoMsg)
+ if !ok {
+ return false
+ }
+
+ return bytes.Equal(m.raw, m1.raw) &&
+ m.proto == m1.proto
+}
+
+func (m *nextProtoMsg) marshal() []byte {
+ if m.raw != nil {
+ return m.raw
+ }
+ l := len(m.proto)
+ if l > 255 {
+ l = 255
+ }
+
+ padding := 32 - (l+2)%32
+ length := l + padding + 2
+ x := make([]byte, length+4)
+ x[0] = typeNextProtocol
+ x[1] = uint8(length >> 16)
+ x[2] = uint8(length >> 8)
+ x[3] = uint8(length)
+
+ y := x[4:]
+ y[0] = byte(l)
+ copy(y[1:], []byte(m.proto[0:l]))
+ y = y[1+l:]
+ y[0] = byte(padding)
+
+ m.raw = x
+
+ return x
+}
+
+func (m *nextProtoMsg) unmarshal(data []byte) bool {
+ m.raw = data
+
+ if len(data) < 5 {
+ return false
+ }
+ data = data[4:]
+ protoLen := int(data[0])
+ data = data[1:]
+ if len(data) < protoLen {
+ return false
+ }
+ m.proto = string(data[0:protoLen])
+ data = data[protoLen:]
+
+ if len(data) < 1 {
+ return false
+ }
+ paddingLen := int(data[0])
+ data = data[1:]
+ if len(data) != paddingLen {
+ return false
+ }
+
+ return true
+}
+
+type certificateRequestMsg struct {
+ raw []byte
+ // hasSignatureAndHash indicates whether this message includes a list
+ // of signature and hash functions. This change was introduced with TLS
+ // 1.2.
+ hasSignatureAndHash bool
+
+ certificateTypes []byte
+ signatureAndHashes []signatureAndHash
+ certificateAuthorities [][]byte
+}
+
+func (m *certificateRequestMsg) equal(i interface{}) bool {
+ m1, ok := i.(*certificateRequestMsg)
+ if !ok {
+ return false
+ }
+
+ return bytes.Equal(m.raw, m1.raw) &&
+ bytes.Equal(m.certificateTypes, m1.certificateTypes) &&
+ eqByteSlices(m.certificateAuthorities, m1.certificateAuthorities) &&
+ eqSignatureAndHashes(m.signatureAndHashes, m1.signatureAndHashes)
+}
+
+func (m *certificateRequestMsg) marshal() (x []byte) {
+ if m.raw != nil {
+ return m.raw
+ }
+
+ // See http://tools.ietf.org/html/rfc4346#section-7.4.4
+ length := 1 + len(m.certificateTypes) + 2
+ casLength := 0
+ for _, ca := range m.certificateAuthorities {
+ casLength += 2 + len(ca)
+ }
+ length += casLength
+
+ if m.hasSignatureAndHash {
+ length += 2 + 2*len(m.signatureAndHashes)
+ }
+
+ x = make([]byte, 4+length)
+ x[0] = typeCertificateRequest
+ x[1] = uint8(length >> 16)
+ x[2] = uint8(length >> 8)
+ x[3] = uint8(length)
+
+ x[4] = uint8(len(m.certificateTypes))
+
+ copy(x[5:], m.certificateTypes)
+ y := x[5+len(m.certificateTypes):]
+
+ if m.hasSignatureAndHash {
+ n := len(m.signatureAndHashes) * 2
+ y[0] = uint8(n >> 8)
+ y[1] = uint8(n)
+ y = y[2:]
+ for _, sigAndHash := range m.signatureAndHashes {
+ y[0] = sigAndHash.hash
+ y[1] = sigAndHash.signature
+ y = y[2:]
+ }
+ }
+
+ y[0] = uint8(casLength >> 8)
+ y[1] = uint8(casLength)
+ y = y[2:]
+ for _, ca := range m.certificateAuthorities {
+ y[0] = uint8(len(ca) >> 8)
+ y[1] = uint8(len(ca))
+ y = y[2:]
+ copy(y, ca)
+ y = y[len(ca):]
+ }
+
+ m.raw = x
+ return
+}
+
+func (m *certificateRequestMsg) unmarshal(data []byte) bool {
+ m.raw = data
+
+ if len(data) < 5 {
+ return false
+ }
+
+ length := uint32(data[1])<<16 | uint32(data[2])<<8 | uint32(data[3])
+ if uint32(len(data))-4 != length {
+ return false
+ }
+
+ numCertTypes := int(data[4])
+ data = data[5:]
+ if numCertTypes == 0 || len(data) <= numCertTypes {
+ return false
+ }
+
+ m.certificateTypes = make([]byte, numCertTypes)
+ if copy(m.certificateTypes, data) != numCertTypes {
+ return false
+ }
+
+ data = data[numCertTypes:]
+
+ if m.hasSignatureAndHash {
+ if len(data) < 2 {
+ return false
+ }
+ sigAndHashLen := uint16(data[0])<<8 | uint16(data[1])
+ data = data[2:]
+ if sigAndHashLen&1 != 0 {
+ return false
+ }
+ if len(data) < int(sigAndHashLen) {
+ return false
+ }
+ numSigAndHash := sigAndHashLen / 2
+ m.signatureAndHashes = make([]signatureAndHash, numSigAndHash)
+ for i := range m.signatureAndHashes {
+ m.signatureAndHashes[i].hash = data[0]
+ m.signatureAndHashes[i].signature = data[1]
+ data = data[2:]
+ }
+ }
+
+ if len(data) < 2 {
+ return false
+ }
+ casLength := uint16(data[0])<<8 | uint16(data[1])
+ data = data[2:]
+ if len(data) < int(casLength) {
+ return false
+ }
+ cas := make([]byte, casLength)
+ copy(cas, data)
+ data = data[casLength:]
+
+ m.certificateAuthorities = nil
+ for len(cas) > 0 {
+ if len(cas) < 2 {
+ return false
+ }
+ caLen := uint16(cas[0])<<8 | uint16(cas[1])
+ cas = cas[2:]
+
+ if len(cas) < int(caLen) {
+ return false
+ }
+
+ m.certificateAuthorities = append(m.certificateAuthorities, cas[:caLen])
+ cas = cas[caLen:]
+ }
+ if len(data) > 0 {
+ return false
+ }
+
+ return true
+}
+
+type certificateVerifyMsg struct {
+ raw []byte
+ hasSignatureAndHash bool
+ signatureAndHash signatureAndHash
+ signature []byte
+}
+
+func (m *certificateVerifyMsg) equal(i interface{}) bool {
+ m1, ok := i.(*certificateVerifyMsg)
+ if !ok {
+ return false
+ }
+
+ return bytes.Equal(m.raw, m1.raw) &&
+ m.hasSignatureAndHash == m1.hasSignatureAndHash &&
+ m.signatureAndHash.hash == m1.signatureAndHash.hash &&
+ m.signatureAndHash.signature == m1.signatureAndHash.signature &&
+ bytes.Equal(m.signature, m1.signature)
+}
+
+func (m *certificateVerifyMsg) marshal() (x []byte) {
+ if m.raw != nil {
+ return m.raw
+ }
+
+ // See http://tools.ietf.org/html/rfc4346#section-7.4.8
+ siglength := len(m.signature)
+ length := 2 + siglength
+ if m.hasSignatureAndHash {
+ length += 2
+ }
+ x = make([]byte, 4+length)
+ x[0] = typeCertificateVerify
+ x[1] = uint8(length >> 16)
+ x[2] = uint8(length >> 8)
+ x[3] = uint8(length)
+ y := x[4:]
+ if m.hasSignatureAndHash {
+ y[0] = m.signatureAndHash.hash
+ y[1] = m.signatureAndHash.signature
+ y = y[2:]
+ }
+ y[0] = uint8(siglength >> 8)
+ y[1] = uint8(siglength)
+ copy(y[2:], m.signature)
+
+ m.raw = x
+
+ return
+}
+
+func (m *certificateVerifyMsg) unmarshal(data []byte) bool {
+ m.raw = data
+
+ if len(data) < 6 {
+ return false
+ }
+
+ length := uint32(data[1])<<16 | uint32(data[2])<<8 | uint32(data[3])
+ if uint32(len(data))-4 != length {
+ return false
+ }
+
+ data = data[4:]
+ if m.hasSignatureAndHash {
+ m.signatureAndHash.hash = data[0]
+ m.signatureAndHash.signature = data[1]
+ data = data[2:]
+ }
+
+ if len(data) < 2 {
+ return false
+ }
+ siglength := int(data[0])<<8 + int(data[1])
+ data = data[2:]
+ if len(data) != siglength {
+ return false
+ }
+
+ m.signature = data
+
+ return true
+}
+
+type newSessionTicketMsg struct {
+ raw []byte
+ ticket []byte
+}
+
+func (m *newSessionTicketMsg) equal(i interface{}) bool {
+ m1, ok := i.(*newSessionTicketMsg)
+ if !ok {
+ return false
+ }
+
+ return bytes.Equal(m.raw, m1.raw) &&
+ bytes.Equal(m.ticket, m1.ticket)
+}
+
+func (m *newSessionTicketMsg) marshal() (x []byte) {
+ if m.raw != nil {
+ return m.raw
+ }
+
+ // See http://tools.ietf.org/html/rfc5077#section-3.3
+ ticketLen := len(m.ticket)
+ length := 2 + 4 + ticketLen
+ x = make([]byte, 4+length)
+ x[0] = typeNewSessionTicket
+ x[1] = uint8(length >> 16)
+ x[2] = uint8(length >> 8)
+ x[3] = uint8(length)
+ x[8] = uint8(ticketLen >> 8)
+ x[9] = uint8(ticketLen)
+ copy(x[10:], m.ticket)
+
+ m.raw = x
+
+ return
+}
+
+func (m *newSessionTicketMsg) unmarshal(data []byte) bool {
+ m.raw = data
+
+ if len(data) < 10 {
+ return false
+ }
+
+ length := uint32(data[1])<<16 | uint32(data[2])<<8 | uint32(data[3])
+ if uint32(len(data))-4 != length {
+ return false
+ }
+
+ ticketLen := int(data[8])<<8 + int(data[9])
+ if len(data)-10 != ticketLen {
+ return false
+ }
+
+ m.ticket = data[10:]
+
+ return true
+}
+
+type v2ClientHelloMsg struct {
+ raw []byte
+ vers uint16
+ cipherSuites []uint16
+ sessionId []byte
+ challenge []byte
+}
+
+func (m *v2ClientHelloMsg) equal(i interface{}) bool {
+ m1, ok := i.(*v2ClientHelloMsg)
+ if !ok {
+ return false
+ }
+
+ return bytes.Equal(m.raw, m1.raw) &&
+ m.vers == m1.vers &&
+ eqUint16s(m.cipherSuites, m1.cipherSuites) &&
+ bytes.Equal(m.sessionId, m1.sessionId) &&
+ bytes.Equal(m.challenge, m1.challenge)
+}
+
+func (m *v2ClientHelloMsg) marshal() []byte {
+ if m.raw != nil {
+ return m.raw
+ }
+
+ length := 1 + 2 + 2 + 2 + 2 + len(m.cipherSuites)*3 + len(m.sessionId) + len(m.challenge)
+
+ x := make([]byte, length)
+ x[0] = 1
+ x[1] = uint8(m.vers >> 8)
+ x[2] = uint8(m.vers)
+ x[3] = uint8((len(m.cipherSuites) * 3) >> 8)
+ x[4] = uint8(len(m.cipherSuites) * 3)
+ x[5] = uint8(len(m.sessionId) >> 8)
+ x[6] = uint8(len(m.sessionId))
+ x[7] = uint8(len(m.challenge) >> 8)
+ x[8] = uint8(len(m.challenge))
+ y := x[9:]
+ for i, spec := range m.cipherSuites {
+ y[i*3] = 0
+ y[i*3+1] = uint8(spec >> 8)
+ y[i*3+2] = uint8(spec)
+ }
+ y = y[len(m.cipherSuites)*3:]
+ copy(y, m.sessionId)
+ y = y[len(m.sessionId):]
+ copy(y, m.challenge)
+
+ m.raw = x
+
+ return x
+}
+
+type helloVerifyRequestMsg struct {
+ raw []byte
+ vers uint16
+ cookie []byte
+}
+
+func (m *helloVerifyRequestMsg) equal(i interface{}) bool {
+ m1, ok := i.(*helloVerifyRequestMsg)
+ if !ok {
+ return false
+ }
+
+ return bytes.Equal(m.raw, m1.raw) &&
+ m.vers == m1.vers &&
+ bytes.Equal(m.cookie, m1.cookie)
+}
+
+func (m *helloVerifyRequestMsg) marshal() []byte {
+ if m.raw != nil {
+ return m.raw
+ }
+
+ length := 2 + 1 + len(m.cookie)
+
+ x := make([]byte, 4+length)
+ x[0] = typeHelloVerifyRequest
+ x[1] = uint8(length >> 16)
+ x[2] = uint8(length >> 8)
+ x[3] = uint8(length)
+ vers := versionToWire(m.vers, true)
+ x[4] = uint8(vers >> 8)
+ x[5] = uint8(vers)
+ x[6] = uint8(len(m.cookie))
+ copy(x[7:7+len(m.cookie)], m.cookie)
+
+ return x
+}
+
+func (m *helloVerifyRequestMsg) unmarshal(data []byte) bool {
+ if len(data) < 4+2+1 {
+ return false
+ }
+ m.raw = data
+ m.vers = wireToVersion(uint16(data[4])<<8|uint16(data[5]), true)
+ cookieLen := int(data[6])
+ if cookieLen > 32 || len(data) != 7+cookieLen {
+ return false
+ }
+ m.cookie = data[7 : 7+cookieLen]
+
+ return true
+}
+
+type encryptedExtensionsMsg struct {
+ raw []byte
+ channelID []byte
+}
+
+func (m *encryptedExtensionsMsg) equal(i interface{}) bool {
+ m1, ok := i.(*encryptedExtensionsMsg)
+ if !ok {
+ return false
+ }
+
+ return bytes.Equal(m.raw, m1.raw) &&
+ bytes.Equal(m.channelID, m1.channelID)
+}
+
+func (m *encryptedExtensionsMsg) marshal() []byte {
+ if m.raw != nil {
+ return m.raw
+ }
+
+ length := 2 + 2 + len(m.channelID)
+
+ x := make([]byte, 4+length)
+ x[0] = typeEncryptedExtensions
+ x[1] = uint8(length >> 16)
+ x[2] = uint8(length >> 8)
+ x[3] = uint8(length)
+ x[4] = uint8(extensionChannelID >> 8)
+ x[5] = uint8(extensionChannelID & 0xff)
+ x[6] = uint8(len(m.channelID) >> 8)
+ x[7] = uint8(len(m.channelID) & 0xff)
+ copy(x[8:], m.channelID)
+
+ return x
+}
+
+func (m *encryptedExtensionsMsg) unmarshal(data []byte) bool {
+ if len(data) != 4+2+2+128 {
+ return false
+ }
+ m.raw = data
+ if (uint16(data[4])<<8)|uint16(data[5]) != extensionChannelID {
+ return false
+ }
+ if int(data[6])<<8|int(data[7]) != 128 {
+ return false
+ }
+ m.channelID = data[4+2+2:]
+
+ return true
+}
+
+type helloRequestMsg struct {
+}
+
+func (*helloRequestMsg) marshal() []byte {
+ return []byte{typeHelloRequest, 0, 0, 0}
+}
+
+func (*helloRequestMsg) unmarshal(data []byte) bool {
+ return len(data) == 4
+}
+
+func eqUint16s(x, y []uint16) bool {
+ if len(x) != len(y) {
+ return false
+ }
+ for i, v := range x {
+ if y[i] != v {
+ return false
+ }
+ }
+ return true
+}
+
+func eqCurveIDs(x, y []CurveID) bool {
+ if len(x) != len(y) {
+ return false
+ }
+ for i, v := range x {
+ if y[i] != v {
+ return false
+ }
+ }
+ return true
+}
+
+func eqStrings(x, y []string) bool {
+ if len(x) != len(y) {
+ return false
+ }
+ for i, v := range x {
+ if y[i] != v {
+ return false
+ }
+ }
+ return true
+}
+
+func eqByteSlices(x, y [][]byte) bool {
+ if len(x) != len(y) {
+ return false
+ }
+ for i, v := range x {
+ if !bytes.Equal(v, y[i]) {
+ return false
+ }
+ }
+ return true
+}
+
+func eqSignatureAndHashes(x, y []signatureAndHash) bool {
+ if len(x) != len(y) {
+ return false
+ }
+ for i, v := range x {
+ v2 := y[i]
+ if v.hash != v2.hash || v.signature != v2.signature {
+ return false
+ }
+ }
+ return true
+}
diff --git a/src/ssl/test/runner/handshake_server.go b/src/ssl/test/runner/handshake_server.go
new file mode 100644
index 0000000..1234a57
--- /dev/null
+++ b/src/ssl/test/runner/handshake_server.go
@@ -0,0 +1,964 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "bytes"
+ "crypto"
+ "crypto/ecdsa"
+ "crypto/elliptic"
+ "crypto/rsa"
+ "crypto/subtle"
+ "crypto/x509"
+ "encoding/asn1"
+ "errors"
+ "fmt"
+ "io"
+ "math/big"
+)
+
+// serverHandshakeState contains details of a server handshake in progress.
+// It's discarded once the handshake has completed.
+type serverHandshakeState struct {
+ c *Conn
+ clientHello *clientHelloMsg
+ hello *serverHelloMsg
+ suite *cipherSuite
+ ellipticOk bool
+ ecdsaOk bool
+ sessionState *sessionState
+ finishedHash finishedHash
+ masterSecret []byte
+ certsFromClient [][]byte
+ cert *Certificate
+}
+
+// serverHandshake performs a TLS handshake as a server.
+func (c *Conn) serverHandshake() error {
+ config := c.config
+
+ // If this is the first server handshake, we generate a random key to
+ // encrypt the tickets with.
+ config.serverInitOnce.Do(config.serverInit)
+
+ c.sendHandshakeSeq = 0
+ c.recvHandshakeSeq = 0
+
+ hs := serverHandshakeState{
+ c: c,
+ }
+ isResume, err := hs.readClientHello()
+ if err != nil {
+ return err
+ }
+
+ // For an overview of TLS handshaking, see https://tools.ietf.org/html/rfc5246#section-7.3
+ if isResume {
+ // The client has included a session ticket and so we do an abbreviated handshake.
+ if err := hs.doResumeHandshake(); err != nil {
+ return err
+ }
+ if err := hs.establishKeys(); err != nil {
+ return err
+ }
+ if c.config.Bugs.RenewTicketOnResume {
+ if err := hs.sendSessionTicket(); err != nil {
+ return err
+ }
+ }
+ if err := hs.sendFinished(); err != nil {
+ return err
+ }
+ if err := hs.readFinished(isResume); err != nil {
+ return err
+ }
+ c.didResume = true
+ } else {
+ // The client didn't include a session ticket, or it wasn't
+ // valid so we do a full handshake.
+ if err := hs.doFullHandshake(); err != nil {
+ return err
+ }
+ if err := hs.establishKeys(); err != nil {
+ return err
+ }
+ if err := hs.readFinished(isResume); err != nil {
+ return err
+ }
+ if c.config.Bugs.ExpectFalseStart {
+ if err := c.readRecord(recordTypeApplicationData); err != nil {
+ return err
+ }
+ }
+ if err := hs.sendSessionTicket(); err != nil {
+ return err
+ }
+ if err := hs.sendFinished(); err != nil {
+ return err
+ }
+ }
+ c.handshakeComplete = true
+
+ return nil
+}
+
+// readClientHello reads a ClientHello message from the client and decides
+// whether we will perform session resumption.
+func (hs *serverHandshakeState) readClientHello() (isResume bool, err error) {
+ config := hs.c.config
+ c := hs.c
+
+ msg, err := c.readHandshake()
+ if err != nil {
+ return false, err
+ }
+ var ok bool
+ hs.clientHello, ok = msg.(*clientHelloMsg)
+ if !ok {
+ c.sendAlert(alertUnexpectedMessage)
+ return false, unexpectedMessageError(hs.clientHello, msg)
+ }
+ if config.Bugs.RequireFastradioPadding && len(hs.clientHello.raw) < 1000 {
+ return false, errors.New("tls: ClientHello record size should be larger than 1000 bytes when padding enabled.")
+ }
+
+ if c.isDTLS && !config.Bugs.SkipHelloVerifyRequest {
+ // Per RFC 6347, the version field in HelloVerifyRequest SHOULD
+ // be always DTLS 1.0
+ helloVerifyRequest := &helloVerifyRequestMsg{
+ vers: VersionTLS10,
+ cookie: make([]byte, 32),
+ }
+ if _, err := io.ReadFull(c.config.rand(), helloVerifyRequest.cookie); err != nil {
+ c.sendAlert(alertInternalError)
+ return false, errors.New("dtls: short read from Rand: " + err.Error())
+ }
+ c.writeRecord(recordTypeHandshake, helloVerifyRequest.marshal())
+
+ msg, err := c.readHandshake()
+ if err != nil {
+ return false, err
+ }
+ newClientHello, ok := msg.(*clientHelloMsg)
+ if !ok {
+ c.sendAlert(alertUnexpectedMessage)
+ return false, unexpectedMessageError(hs.clientHello, msg)
+ }
+ if !bytes.Equal(newClientHello.cookie, helloVerifyRequest.cookie) {
+ return false, errors.New("dtls: invalid cookie")
+ }
+
+ // Apart from the cookie, the two ClientHellos must
+ // match. Note that clientHello.equal compares the
+ // serialization, so we make a copy.
+ oldClientHelloCopy := *hs.clientHello
+ oldClientHelloCopy.raw = nil
+ oldClientHelloCopy.cookie = nil
+ newClientHelloCopy := *newClientHello
+ newClientHelloCopy.raw = nil
+ newClientHelloCopy.cookie = nil
+ if !oldClientHelloCopy.equal(&newClientHelloCopy) {
+ return false, errors.New("dtls: retransmitted ClientHello does not match")
+ }
+ hs.clientHello = newClientHello
+ }
+
+ if config.Bugs.RequireSameRenegoClientVersion && c.clientVersion != 0 {
+ if c.clientVersion != hs.clientHello.vers {
+ return false, fmt.Errorf("tls: client offered different version on renego")
+ }
+ }
+ c.clientVersion = hs.clientHello.vers
+
+ // Reject < 1.2 ClientHellos with signature_algorithms.
+ if c.clientVersion < VersionTLS12 && len(hs.clientHello.signatureAndHashes) > 0 {
+ return false, fmt.Errorf("tls: client included signature_algorithms before TLS 1.2")
+ }
+
+ c.vers, ok = config.mutualVersion(hs.clientHello.vers)
+ if !ok {
+ c.sendAlert(alertProtocolVersion)
+ return false, fmt.Errorf("tls: client offered an unsupported, maximum protocol version of %x", hs.clientHello.vers)
+ }
+ c.haveVers = true
+
+ hs.hello = new(serverHelloMsg)
+ hs.hello.isDTLS = c.isDTLS
+
+ supportedCurve := false
+ preferredCurves := config.curvePreferences()
+Curves:
+ for _, curve := range hs.clientHello.supportedCurves {
+ for _, supported := range preferredCurves {
+ if supported == curve {
+ supportedCurve = true
+ break Curves
+ }
+ }
+ }
+
+ supportedPointFormat := false
+ for _, pointFormat := range hs.clientHello.supportedPoints {
+ if pointFormat == pointFormatUncompressed {
+ supportedPointFormat = true
+ break
+ }
+ }
+ hs.ellipticOk = supportedCurve && supportedPointFormat
+
+ foundCompression := false
+ // We only support null compression, so check that the client offered it.
+ for _, compression := range hs.clientHello.compressionMethods {
+ if compression == compressionNone {
+ foundCompression = true
+ break
+ }
+ }
+
+ if !foundCompression {
+ c.sendAlert(alertHandshakeFailure)
+ return false, errors.New("tls: client does not support uncompressed connections")
+ }
+
+ hs.hello.vers = c.vers
+ hs.hello.random = make([]byte, 32)
+ _, err = io.ReadFull(config.rand(), hs.hello.random)
+ if err != nil {
+ c.sendAlert(alertInternalError)
+ return false, err
+ }
+
+ if !bytes.Equal(c.clientVerify, hs.clientHello.secureRenegotiation) {
+ c.sendAlert(alertHandshakeFailure)
+ return false, errors.New("tls: renegotiation mismatch")
+ }
+
+ if len(c.clientVerify) > 0 && !c.config.Bugs.EmptyRenegotiationInfo {
+ hs.hello.secureRenegotiation = append(hs.hello.secureRenegotiation, c.clientVerify...)
+ hs.hello.secureRenegotiation = append(hs.hello.secureRenegotiation, c.serverVerify...)
+ if c.config.Bugs.BadRenegotiationInfo {
+ hs.hello.secureRenegotiation[0] ^= 0x80
+ }
+ } else {
+ hs.hello.secureRenegotiation = hs.clientHello.secureRenegotiation
+ }
+
+ hs.hello.compressionMethod = compressionNone
+ hs.hello.duplicateExtension = c.config.Bugs.DuplicateExtension
+ if len(hs.clientHello.serverName) > 0 {
+ c.serverName = hs.clientHello.serverName
+ }
+
+ if len(hs.clientHello.alpnProtocols) > 0 {
+ if selectedProto, fallback := mutualProtocol(hs.clientHello.alpnProtocols, c.config.NextProtos); !fallback {
+ hs.hello.alpnProtocol = selectedProto
+ c.clientProtocol = selectedProto
+ c.usedALPN = true
+ }
+ } else {
+ // Although sending an empty NPN extension is reasonable, Firefox has
+ // had a bug around this. Best to send nothing at all if
+ // config.NextProtos is empty. See
+ // https://code.google.com/p/go/issues/detail?id=5445.
+ if hs.clientHello.nextProtoNeg && len(config.NextProtos) > 0 {
+ hs.hello.nextProtoNeg = true
+ hs.hello.nextProtos = config.NextProtos
+ }
+ }
+ hs.hello.extendedMasterSecret = c.vers >= VersionTLS10 && hs.clientHello.extendedMasterSecret && !c.config.Bugs.NoExtendedMasterSecret
+
+ if len(config.Certificates) == 0 {
+ c.sendAlert(alertInternalError)
+ return false, errors.New("tls: no certificates configured")
+ }
+ hs.cert = &config.Certificates[0]
+ if len(hs.clientHello.serverName) > 0 {
+ hs.cert = config.getCertificateForName(hs.clientHello.serverName)
+ }
+ if expected := c.config.Bugs.ExpectServerName; expected != "" && expected != hs.clientHello.serverName {
+ return false, errors.New("tls: unexpected server name")
+ }
+
+ if hs.clientHello.channelIDSupported && config.RequestChannelID {
+ hs.hello.channelIDRequested = true
+ }
+
+ if hs.clientHello.srtpProtectionProfiles != nil {
+ SRTPLoop:
+ for _, p1 := range c.config.SRTPProtectionProfiles {
+ for _, p2 := range hs.clientHello.srtpProtectionProfiles {
+ if p1 == p2 {
+ hs.hello.srtpProtectionProfile = p1
+ c.srtpProtectionProfile = p1
+ break SRTPLoop
+ }
+ }
+ }
+ }
+
+ if c.config.Bugs.SendSRTPProtectionProfile != 0 {
+ hs.hello.srtpProtectionProfile = c.config.Bugs.SendSRTPProtectionProfile
+ }
+
+ _, hs.ecdsaOk = hs.cert.PrivateKey.(*ecdsa.PrivateKey)
+
+ if hs.checkForResumption() {
+ return true, nil
+ }
+
+ var scsvFound bool
+
+ for _, cipherSuite := range hs.clientHello.cipherSuites {
+ if cipherSuite == fallbackSCSV {
+ scsvFound = true
+ break
+ }
+ }
+
+ if !scsvFound && config.Bugs.FailIfNotFallbackSCSV {
+ return false, errors.New("tls: no fallback SCSV found when expected")
+ } else if scsvFound && !config.Bugs.FailIfNotFallbackSCSV {
+ return false, errors.New("tls: fallback SCSV found when not expected")
+ }
+
+ var preferenceList, supportedList []uint16
+ if c.config.PreferServerCipherSuites {
+ preferenceList = c.config.cipherSuites()
+ supportedList = hs.clientHello.cipherSuites
+ } else {
+ preferenceList = hs.clientHello.cipherSuites
+ supportedList = c.config.cipherSuites()
+ }
+
+ for _, id := range preferenceList {
+ if hs.suite = c.tryCipherSuite(id, supportedList, c.vers, hs.ellipticOk, hs.ecdsaOk); hs.suite != nil {
+ break
+ }
+ }
+
+ if hs.suite == nil {
+ c.sendAlert(alertHandshakeFailure)
+ return false, errors.New("tls: no cipher suite supported by both client and server")
+ }
+
+ return false, nil
+}
+
+// checkForResumption returns true if we should perform resumption on this connection.
+func (hs *serverHandshakeState) checkForResumption() bool {
+ c := hs.c
+
+ if len(hs.clientHello.sessionTicket) > 0 {
+ if c.config.SessionTicketsDisabled {
+ return false
+ }
+
+ var ok bool
+ if hs.sessionState, ok = c.decryptTicket(hs.clientHello.sessionTicket); !ok {
+ return false
+ }
+ } else {
+ if c.config.ServerSessionCache == nil {
+ return false
+ }
+
+ var ok bool
+ sessionId := string(hs.clientHello.sessionId)
+ if hs.sessionState, ok = c.config.ServerSessionCache.Get(sessionId); !ok {
+ return false
+ }
+ }
+
+ // Never resume a session for a different SSL version.
+ if !c.config.Bugs.AllowSessionVersionMismatch && c.vers != hs.sessionState.vers {
+ return false
+ }
+
+ cipherSuiteOk := false
+ // Check that the client is still offering the ciphersuite in the session.
+ for _, id := range hs.clientHello.cipherSuites {
+ if id == hs.sessionState.cipherSuite {
+ cipherSuiteOk = true
+ break
+ }
+ }
+ if !cipherSuiteOk {
+ return false
+ }
+
+ // Check that we also support the ciphersuite from the session.
+ hs.suite = c.tryCipherSuite(hs.sessionState.cipherSuite, c.config.cipherSuites(), hs.sessionState.vers, hs.ellipticOk, hs.ecdsaOk)
+ if hs.suite == nil {
+ return false
+ }
+
+ sessionHasClientCerts := len(hs.sessionState.certificates) != 0
+ needClientCerts := c.config.ClientAuth == RequireAnyClientCert || c.config.ClientAuth == RequireAndVerifyClientCert
+ if needClientCerts && !sessionHasClientCerts {
+ return false
+ }
+ if sessionHasClientCerts && c.config.ClientAuth == NoClientCert {
+ return false
+ }
+
+ return true
+}
+
+func (hs *serverHandshakeState) doResumeHandshake() error {
+ c := hs.c
+
+ hs.hello.cipherSuite = hs.suite.id
+ // We echo the client's session ID in the ServerHello to let it know
+ // that we're doing a resumption.
+ hs.hello.sessionId = hs.clientHello.sessionId
+ hs.hello.ticketSupported = c.config.Bugs.RenewTicketOnResume
+
+ hs.finishedHash = newFinishedHash(c.vers, hs.suite)
+ hs.finishedHash.discardHandshakeBuffer()
+ hs.writeClientHash(hs.clientHello.marshal())
+ hs.writeServerHash(hs.hello.marshal())
+
+ c.writeRecord(recordTypeHandshake, hs.hello.marshal())
+
+ if len(hs.sessionState.certificates) > 0 {
+ if _, err := hs.processCertsFromClient(hs.sessionState.certificates); err != nil {
+ return err
+ }
+ }
+
+ hs.masterSecret = hs.sessionState.masterSecret
+ c.extendedMasterSecret = hs.sessionState.extendedMasterSecret
+
+ return nil
+}
+
+func (hs *serverHandshakeState) doFullHandshake() error {
+ config := hs.c.config
+ c := hs.c
+
+ isPSK := hs.suite.flags&suitePSK != 0
+ if !isPSK && hs.clientHello.ocspStapling && len(hs.cert.OCSPStaple) > 0 {
+ hs.hello.ocspStapling = true
+ }
+
+ if hs.clientHello.sctListSupported && len(hs.cert.SignedCertificateTimestampList) > 0 {
+ hs.hello.sctList = hs.cert.SignedCertificateTimestampList
+ }
+
+ hs.hello.ticketSupported = hs.clientHello.ticketSupported && !config.SessionTicketsDisabled && c.vers > VersionSSL30
+ hs.hello.cipherSuite = hs.suite.id
+ if config.Bugs.SendCipherSuite != 0 {
+ hs.hello.cipherSuite = config.Bugs.SendCipherSuite
+ }
+ c.extendedMasterSecret = hs.hello.extendedMasterSecret
+
+ // Generate a session ID if we're to save the session.
+ if !hs.hello.ticketSupported && config.ServerSessionCache != nil {
+ hs.hello.sessionId = make([]byte, 32)
+ if _, err := io.ReadFull(config.rand(), hs.hello.sessionId); err != nil {
+ c.sendAlert(alertInternalError)
+ return errors.New("tls: short read from Rand: " + err.Error())
+ }
+ }
+
+ hs.finishedHash = newFinishedHash(c.vers, hs.suite)
+ hs.writeClientHash(hs.clientHello.marshal())
+ hs.writeServerHash(hs.hello.marshal())
+
+ c.writeRecord(recordTypeHandshake, hs.hello.marshal())
+
+ if !isPSK {
+ certMsg := new(certificateMsg)
+ certMsg.certificates = hs.cert.Certificate
+ if !config.Bugs.UnauthenticatedECDH {
+ hs.writeServerHash(certMsg.marshal())
+ c.writeRecord(recordTypeHandshake, certMsg.marshal())
+ }
+ }
+
+ if hs.hello.ocspStapling {
+ certStatus := new(certificateStatusMsg)
+ certStatus.statusType = statusTypeOCSP
+ certStatus.response = hs.cert.OCSPStaple
+ hs.writeServerHash(certStatus.marshal())
+ c.writeRecord(recordTypeHandshake, certStatus.marshal())
+ }
+
+ keyAgreement := hs.suite.ka(c.vers)
+ skx, err := keyAgreement.generateServerKeyExchange(config, hs.cert, hs.clientHello, hs.hello)
+ if err != nil {
+ c.sendAlert(alertHandshakeFailure)
+ return err
+ }
+ if skx != nil && !config.Bugs.SkipServerKeyExchange {
+ hs.writeServerHash(skx.marshal())
+ c.writeRecord(recordTypeHandshake, skx.marshal())
+ }
+
+ if config.ClientAuth >= RequestClientCert {
+ // Request a client certificate
+ certReq := &certificateRequestMsg{
+ certificateTypes: config.ClientCertificateTypes,
+ }
+ if certReq.certificateTypes == nil {
+ certReq.certificateTypes = []byte{
+ byte(CertTypeRSASign),
+ byte(CertTypeECDSASign),
+ }
+ }
+ if c.vers >= VersionTLS12 {
+ certReq.hasSignatureAndHash = true
+ if !config.Bugs.NoSignatureAndHashes {
+ certReq.signatureAndHashes = config.signatureAndHashesForServer()
+ }
+ }
+
+ // An empty list of certificateAuthorities signals to
+ // the client that it may send any certificate in response
+ // to our request. When we know the CAs we trust, then
+ // we can send them down, so that the client can choose
+ // an appropriate certificate to give to us.
+ if config.ClientCAs != nil {
+ certReq.certificateAuthorities = config.ClientCAs.Subjects()
+ }
+ hs.writeServerHash(certReq.marshal())
+ c.writeRecord(recordTypeHandshake, certReq.marshal())
+ }
+
+ helloDone := new(serverHelloDoneMsg)
+ hs.writeServerHash(helloDone.marshal())
+ c.writeRecord(recordTypeHandshake, helloDone.marshal())
+
+ var pub crypto.PublicKey // public key for client auth, if any
+
+ msg, err := c.readHandshake()
+ if err != nil {
+ return err
+ }
+
+ var ok bool
+ // If we requested a client certificate, then the client must send a
+ // certificate message, even if it's empty.
+ if config.ClientAuth >= RequestClientCert {
+ var certMsg *certificateMsg
+ if certMsg, ok = msg.(*certificateMsg); !ok {
+ c.sendAlert(alertUnexpectedMessage)
+ return unexpectedMessageError(certMsg, msg)
+ }
+ hs.writeClientHash(certMsg.marshal())
+
+ if len(certMsg.certificates) == 0 {
+ // The client didn't actually send a certificate
+ switch config.ClientAuth {
+ case RequireAnyClientCert, RequireAndVerifyClientCert:
+ c.sendAlert(alertBadCertificate)
+ return errors.New("tls: client didn't provide a certificate")
+ }
+ }
+
+ pub, err = hs.processCertsFromClient(certMsg.certificates)
+ if err != nil {
+ return err
+ }
+
+ msg, err = c.readHandshake()
+ if err != nil {
+ return err
+ }
+ }
+
+ // Get client key exchange
+ ckx, ok := msg.(*clientKeyExchangeMsg)
+ if !ok {
+ c.sendAlert(alertUnexpectedMessage)
+ return unexpectedMessageError(ckx, msg)
+ }
+ hs.writeClientHash(ckx.marshal())
+
+ preMasterSecret, err := keyAgreement.processClientKeyExchange(config, hs.cert, ckx, c.vers)
+ if err != nil {
+ c.sendAlert(alertHandshakeFailure)
+ return err
+ }
+ if c.extendedMasterSecret {
+ hs.masterSecret = extendedMasterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.finishedHash)
+ } else {
+ if c.config.Bugs.RequireExtendedMasterSecret {
+ return errors.New("tls: extended master secret required but not supported by peer")
+ }
+ hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.clientHello.random, hs.hello.random)
+ }
+
+ // If we received a client cert in response to our certificate request message,
+ // the client will send us a certificateVerifyMsg immediately after the
+ // clientKeyExchangeMsg. This message is a digest of all preceding
+ // handshake-layer messages that is signed using the private key corresponding
+ // to the client's certificate. This allows us to verify that the client is in
+ // possession of the private key of the certificate.
+ if len(c.peerCertificates) > 0 {
+ msg, err = c.readHandshake()
+ if err != nil {
+ return err
+ }
+ certVerify, ok := msg.(*certificateVerifyMsg)
+ if !ok {
+ c.sendAlert(alertUnexpectedMessage)
+ return unexpectedMessageError(certVerify, msg)
+ }
+
+ // Determine the signature type.
+ var signatureAndHash signatureAndHash
+ if certVerify.hasSignatureAndHash {
+ signatureAndHash = certVerify.signatureAndHash
+ if !isSupportedSignatureAndHash(signatureAndHash, config.signatureAndHashesForServer()) {
+ return errors.New("tls: unsupported hash function for client certificate")
+ }
+ } else {
+ // Before TLS 1.2 the signature algorithm was implicit
+ // from the key type, and only one hash per signature
+ // algorithm was possible. Leave the hash as zero.
+ switch pub.(type) {
+ case *ecdsa.PublicKey:
+ signatureAndHash.signature = signatureECDSA
+ case *rsa.PublicKey:
+ signatureAndHash.signature = signatureRSA
+ }
+ }
+
+ switch key := pub.(type) {
+ case *ecdsa.PublicKey:
+ if signatureAndHash.signature != signatureECDSA {
+ err = errors.New("tls: bad signature type for client's ECDSA certificate")
+ break
+ }
+ ecdsaSig := new(ecdsaSignature)
+ if _, err = asn1.Unmarshal(certVerify.signature, ecdsaSig); err != nil {
+ break
+ }
+ if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 {
+ err = errors.New("ECDSA signature contained zero or negative values")
+ break
+ }
+ var digest []byte
+ digest, _, err = hs.finishedHash.hashForClientCertificate(signatureAndHash, hs.masterSecret)
+ if err != nil {
+ break
+ }
+ if !ecdsa.Verify(key, digest, ecdsaSig.R, ecdsaSig.S) {
+ err = errors.New("ECDSA verification failure")
+ break
+ }
+ case *rsa.PublicKey:
+ if signatureAndHash.signature != signatureRSA {
+ err = errors.New("tls: bad signature type for client's RSA certificate")
+ break
+ }
+ var digest []byte
+ var hashFunc crypto.Hash
+ digest, hashFunc, err = hs.finishedHash.hashForClientCertificate(signatureAndHash, hs.masterSecret)
+ if err != nil {
+ break
+ }
+ err = rsa.VerifyPKCS1v15(key, hashFunc, digest, certVerify.signature)
+ }
+ if err != nil {
+ c.sendAlert(alertBadCertificate)
+ return errors.New("could not validate signature of connection nonces: " + err.Error())
+ }
+
+ hs.writeClientHash(certVerify.marshal())
+ }
+
+ hs.finishedHash.discardHandshakeBuffer()
+
+ return nil
+}
+
+func (hs *serverHandshakeState) establishKeys() error {
+ c := hs.c
+
+ clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
+ keysFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.clientHello.random, hs.hello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen)
+
+ var clientCipher, serverCipher interface{}
+ var clientHash, serverHash macFunction
+
+ if hs.suite.aead == nil {
+ clientCipher = hs.suite.cipher(clientKey, clientIV, true /* for reading */)
+ clientHash = hs.suite.mac(c.vers, clientMAC)
+ serverCipher = hs.suite.cipher(serverKey, serverIV, false /* not for reading */)
+ serverHash = hs.suite.mac(c.vers, serverMAC)
+ } else {
+ clientCipher = hs.suite.aead(clientKey, clientIV)
+ serverCipher = hs.suite.aead(serverKey, serverIV)
+ }
+
+ c.in.prepareCipherSpec(c.vers, clientCipher, clientHash)
+ c.out.prepareCipherSpec(c.vers, serverCipher, serverHash)
+
+ return nil
+}
+
+func (hs *serverHandshakeState) readFinished(isResume bool) error {
+ c := hs.c
+
+ c.readRecord(recordTypeChangeCipherSpec)
+ if err := c.in.error(); err != nil {
+ return err
+ }
+
+ if hs.hello.nextProtoNeg {
+ msg, err := c.readHandshake()
+ if err != nil {
+ return err
+ }
+ nextProto, ok := msg.(*nextProtoMsg)
+ if !ok {
+ c.sendAlert(alertUnexpectedMessage)
+ return unexpectedMessageError(nextProto, msg)
+ }
+ hs.writeClientHash(nextProto.marshal())
+ c.clientProtocol = nextProto.proto
+ }
+
+ if hs.hello.channelIDRequested {
+ msg, err := c.readHandshake()
+ if err != nil {
+ return err
+ }
+ encryptedExtensions, ok := msg.(*encryptedExtensionsMsg)
+ if !ok {
+ c.sendAlert(alertUnexpectedMessage)
+ return unexpectedMessageError(encryptedExtensions, msg)
+ }
+ x := new(big.Int).SetBytes(encryptedExtensions.channelID[0:32])
+ y := new(big.Int).SetBytes(encryptedExtensions.channelID[32:64])
+ r := new(big.Int).SetBytes(encryptedExtensions.channelID[64:96])
+ s := new(big.Int).SetBytes(encryptedExtensions.channelID[96:128])
+ if !elliptic.P256().IsOnCurve(x, y) {
+ return errors.New("tls: invalid channel ID public key")
+ }
+ channelID := &ecdsa.PublicKey{elliptic.P256(), x, y}
+ var resumeHash []byte
+ if isResume {
+ resumeHash = hs.sessionState.handshakeHash
+ }
+ if !ecdsa.Verify(channelID, hs.finishedHash.hashForChannelID(resumeHash), r, s) {
+ return errors.New("tls: invalid channel ID signature")
+ }
+ c.channelID = channelID
+
+ hs.writeClientHash(encryptedExtensions.marshal())
+ }
+
+ msg, err := c.readHandshake()
+ if err != nil {
+ return err
+ }
+ clientFinished, ok := msg.(*finishedMsg)
+ if !ok {
+ c.sendAlert(alertUnexpectedMessage)
+ return unexpectedMessageError(clientFinished, msg)
+ }
+
+ verify := hs.finishedHash.clientSum(hs.masterSecret)
+ if len(verify) != len(clientFinished.verifyData) ||
+ subtle.ConstantTimeCompare(verify, clientFinished.verifyData) != 1 {
+ c.sendAlert(alertHandshakeFailure)
+ return errors.New("tls: client's Finished message is incorrect")
+ }
+ c.clientVerify = append(c.clientVerify[:0], clientFinished.verifyData...)
+
+ hs.writeClientHash(clientFinished.marshal())
+ return nil
+}
+
+func (hs *serverHandshakeState) sendSessionTicket() error {
+ c := hs.c
+ state := sessionState{
+ vers: c.vers,
+ cipherSuite: hs.suite.id,
+ masterSecret: hs.masterSecret,
+ certificates: hs.certsFromClient,
+ handshakeHash: hs.finishedHash.server.Sum(nil),
+ }
+
+ if !hs.hello.ticketSupported || hs.c.config.Bugs.SkipNewSessionTicket {
+ if c.config.ServerSessionCache != nil && len(hs.hello.sessionId) != 0 {
+ c.config.ServerSessionCache.Put(string(hs.hello.sessionId), &state)
+ }
+ return nil
+ }
+
+ m := new(newSessionTicketMsg)
+
+ var err error
+ m.ticket, err = c.encryptTicket(&state)
+ if err != nil {
+ return err
+ }
+
+ hs.writeServerHash(m.marshal())
+ c.writeRecord(recordTypeHandshake, m.marshal())
+
+ return nil
+}
+
+func (hs *serverHandshakeState) sendFinished() error {
+ c := hs.c
+
+ finished := new(finishedMsg)
+ finished.verifyData = hs.finishedHash.serverSum(hs.masterSecret)
+ c.serverVerify = append(c.serverVerify[:0], finished.verifyData...)
+ postCCSBytes := finished.marshal()
+ hs.writeServerHash(postCCSBytes)
+
+ if c.config.Bugs.FragmentAcrossChangeCipherSpec {
+ c.writeRecord(recordTypeHandshake, postCCSBytes[:5])
+ postCCSBytes = postCCSBytes[5:]
+ }
+
+ if !c.config.Bugs.SkipChangeCipherSpec {
+ c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
+ }
+
+ if c.config.Bugs.AppDataAfterChangeCipherSpec != nil {
+ c.writeRecord(recordTypeApplicationData, c.config.Bugs.AppDataAfterChangeCipherSpec)
+ }
+
+ c.writeRecord(recordTypeHandshake, postCCSBytes)
+
+ c.cipherSuite = hs.suite.id
+
+ return nil
+}
+
+// processCertsFromClient takes a chain of client certificates either from a
+// Certificates message or from a sessionState and verifies them. It returns
+// the public key of the leaf certificate.
+func (hs *serverHandshakeState) processCertsFromClient(certificates [][]byte) (crypto.PublicKey, error) {
+ c := hs.c
+
+ hs.certsFromClient = certificates
+ certs := make([]*x509.Certificate, len(certificates))
+ var err error
+ for i, asn1Data := range certificates {
+ if certs[i], err = x509.ParseCertificate(asn1Data); err != nil {
+ c.sendAlert(alertBadCertificate)
+ return nil, errors.New("tls: failed to parse client certificate: " + err.Error())
+ }
+ }
+
+ if c.config.ClientAuth >= VerifyClientCertIfGiven && len(certs) > 0 {
+ opts := x509.VerifyOptions{
+ Roots: c.config.ClientCAs,
+ CurrentTime: c.config.time(),
+ Intermediates: x509.NewCertPool(),
+ KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
+ }
+
+ for _, cert := range certs[1:] {
+ opts.Intermediates.AddCert(cert)
+ }
+
+ chains, err := certs[0].Verify(opts)
+ if err != nil {
+ c.sendAlert(alertBadCertificate)
+ return nil, errors.New("tls: failed to verify client's certificate: " + err.Error())
+ }
+
+ ok := false
+ for _, ku := range certs[0].ExtKeyUsage {
+ if ku == x509.ExtKeyUsageClientAuth {
+ ok = true
+ break
+ }
+ }
+ if !ok {
+ c.sendAlert(alertHandshakeFailure)
+ return nil, errors.New("tls: client's certificate's extended key usage doesn't permit it to be used for client authentication")
+ }
+
+ c.verifiedChains = chains
+ }
+
+ if len(certs) > 0 {
+ var pub crypto.PublicKey
+ switch key := certs[0].PublicKey.(type) {
+ case *ecdsa.PublicKey, *rsa.PublicKey:
+ pub = key
+ default:
+ c.sendAlert(alertUnsupportedCertificate)
+ return nil, fmt.Errorf("tls: client's certificate contains an unsupported public key of type %T", certs[0].PublicKey)
+ }
+ c.peerCertificates = certs
+ return pub, nil
+ }
+
+ return nil, nil
+}
+
+func (hs *serverHandshakeState) writeServerHash(msg []byte) {
+ // writeServerHash is called before writeRecord.
+ hs.writeHash(msg, hs.c.sendHandshakeSeq)
+}
+
+func (hs *serverHandshakeState) writeClientHash(msg []byte) {
+ // writeClientHash is called after readHandshake.
+ hs.writeHash(msg, hs.c.recvHandshakeSeq-1)
+}
+
+func (hs *serverHandshakeState) writeHash(msg []byte, seqno uint16) {
+ if hs.c.isDTLS {
+ // This is somewhat hacky. DTLS hashes a slightly different format.
+ // First, the TLS header.
+ hs.finishedHash.Write(msg[:4])
+ // Then the sequence number and reassembled fragment offset (always 0).
+ hs.finishedHash.Write([]byte{byte(seqno >> 8), byte(seqno), 0, 0, 0})
+ // Then the reassembled fragment (always equal to the message length).
+ hs.finishedHash.Write(msg[1:4])
+ // And then the message body.
+ hs.finishedHash.Write(msg[4:])
+ } else {
+ hs.finishedHash.Write(msg)
+ }
+}
+
+// tryCipherSuite returns a cipherSuite with the given id if that cipher suite
+// is acceptable to use.
+func (c *Conn) tryCipherSuite(id uint16, supportedCipherSuites []uint16, version uint16, ellipticOk, ecdsaOk bool) *cipherSuite {
+ for _, supported := range supportedCipherSuites {
+ if id == supported {
+ var candidate *cipherSuite
+
+ for _, s := range cipherSuites {
+ if s.id == id {
+ candidate = s
+ break
+ }
+ }
+ if candidate == nil {
+ continue
+ }
+ // Don't select a ciphersuite which we can't
+ // support for this client.
+ if (candidate.flags&suiteECDHE != 0) && !ellipticOk {
+ continue
+ }
+ if (candidate.flags&suiteECDSA != 0) != ecdsaOk {
+ continue
+ }
+ if !c.config.Bugs.SkipCipherVersionCheck && version < VersionTLS12 && candidate.flags&suiteTLS12 != 0 {
+ continue
+ }
+ if c.isDTLS && candidate.flags&suiteNoDTLS != 0 {
+ continue
+ }
+ return candidate
+ }
+ }
+
+ return nil
+}
diff --git a/src/ssl/test/runner/key.pem b/src/ssl/test/runner/key.pem
new file mode 100644
index 0000000..e9107bf
--- /dev/null
+++ b/src/ssl/test/runner/key.pem
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXgIBAAKBgQDYK8imMuRi/03z0K1Zi0WnvfFHvwlYeyK9Na6XJYaUoIDAtB92
+kWdGMdAQhLciHnAjkXLI6W15OoV3gA/ElRZ1xUpxTMhjP6PyY5wqT5r6y8FxbiiF
+KKAnHmUcrgfVW28tQ+0rkLGMryRtrukXOgXBv7gcrmU7G1jC2a7WqmeI8QIDAQAB
+AoGBAIBy09Fd4DOq/Ijp8HeKuCMKTHqTW1xGHshLQ6jwVV2vWZIn9aIgmDsvkjCe
+i6ssZvnbjVcwzSoByhjN8ZCf/i15HECWDFFh6gt0P5z0MnChwzZmvatV/FXCT0j+
+WmGNB/gkehKjGXLLcjTb6dRYVJSCZhVuOLLcbWIV10gggJQBAkEA8S8sGe4ezyyZ
+m4e9r95g6s43kPqtj5rewTsUxt+2n4eVodD+ZUlCULWVNAFLkYRTBCASlSrm9Xhj
+QpmWAHJUkQJBAOVzQdFUaewLtdOJoPCtpYoY1zd22eae8TQEmpGOR11L6kbxLQsk
+aMly/DOnOaa82tqAGTdqDEZgSNmCeKKknmECQAvpnY8GUOVAubGR6c+W90iBuQLj
+LtFp/9ihd2w/PoDwrHZaoUYVcT4VSfJQog/k7kjE4MYXYWL8eEKg3WTWQNECQQDk
+104Wi91Umd1PzF0ijd2jXOERJU1wEKe6XLkYYNHWQAe5l4J4MWj9OdxFXAxIuuR/
+tfDwbqkta4xcux67//khAkEAvvRXLHTaa6VFzTaiiO8SaFsHV3lQyXOtMrBpB5jd
+moZWgjHvB2W9Ckn7sDqsPB+U2tyX0joDdQEyuiMECDY8oQ==
+-----END RSA PRIVATE KEY-----
diff --git a/src/ssl/test/runner/key_agreement.go b/src/ssl/test/runner/key_agreement.go
new file mode 100644
index 0000000..116dfd8
--- /dev/null
+++ b/src/ssl/test/runner/key_agreement.go
@@ -0,0 +1,776 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "crypto"
+ "crypto/ecdsa"
+ "crypto/elliptic"
+ "crypto/md5"
+ "crypto/rand"
+ "crypto/rsa"
+ "crypto/sha1"
+ "crypto/x509"
+ "encoding/asn1"
+ "errors"
+ "io"
+ "math/big"
+)
+
+var errClientKeyExchange = errors.New("tls: invalid ClientKeyExchange message")
+var errServerKeyExchange = errors.New("tls: invalid ServerKeyExchange message")
+
+// rsaKeyAgreement implements the standard TLS key agreement where the client
+// encrypts the pre-master secret to the server's public key.
+type rsaKeyAgreement struct {
+ clientVersion uint16
+}
+
+func (ka *rsaKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
+ // Save the client version for comparison later.
+ ka.clientVersion = versionToWire(clientHello.vers, clientHello.isDTLS)
+
+ if config.Bugs.RSAServerKeyExchange {
+ // Send an empty ServerKeyExchange message.
+ return &serverKeyExchangeMsg{}, nil
+ }
+
+ return nil, nil
+}
+
+func (ka *rsaKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
+ preMasterSecret := make([]byte, 48)
+ _, err := io.ReadFull(config.rand(), preMasterSecret[2:])
+ if err != nil {
+ return nil, err
+ }
+
+ if len(ckx.ciphertext) < 2 {
+ return nil, errClientKeyExchange
+ }
+
+ ciphertext := ckx.ciphertext
+ if version != VersionSSL30 {
+ ciphertextLen := int(ckx.ciphertext[0])<<8 | int(ckx.ciphertext[1])
+ if ciphertextLen != len(ckx.ciphertext)-2 {
+ return nil, errClientKeyExchange
+ }
+ ciphertext = ckx.ciphertext[2:]
+ }
+
+ err = rsa.DecryptPKCS1v15SessionKey(config.rand(), cert.PrivateKey.(*rsa.PrivateKey), ciphertext, preMasterSecret)
+ if err != nil {
+ return nil, err
+ }
+ // This check should be done in constant-time, but this is a testing
+ // implementation. See the discussion at the end of section 7.4.7.1 of
+ // RFC 4346.
+ vers := uint16(preMasterSecret[0])<<8 | uint16(preMasterSecret[1])
+ if ka.clientVersion != vers {
+ return nil, errors.New("tls: invalid version in RSA premaster")
+ }
+ return preMasterSecret, nil
+}
+
+func (ka *rsaKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
+ return errors.New("tls: unexpected ServerKeyExchange")
+}
+
+func (ka *rsaKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
+ preMasterSecret := make([]byte, 48)
+ vers := clientHello.vers
+ if config.Bugs.RsaClientKeyExchangeVersion != 0 {
+ vers = config.Bugs.RsaClientKeyExchangeVersion
+ }
+ vers = versionToWire(vers, clientHello.isDTLS)
+ preMasterSecret[0] = byte(vers >> 8)
+ preMasterSecret[1] = byte(vers)
+ _, err := io.ReadFull(config.rand(), preMasterSecret[2:])
+ if err != nil {
+ return nil, nil, err
+ }
+
+ encrypted, err := rsa.EncryptPKCS1v15(config.rand(), cert.PublicKey.(*rsa.PublicKey), preMasterSecret)
+ if err != nil {
+ return nil, nil, err
+ }
+ ckx := new(clientKeyExchangeMsg)
+ if clientHello.vers != VersionSSL30 && !config.Bugs.SSL3RSAKeyExchange {
+ ckx.ciphertext = make([]byte, len(encrypted)+2)
+ ckx.ciphertext[0] = byte(len(encrypted) >> 8)
+ ckx.ciphertext[1] = byte(len(encrypted))
+ copy(ckx.ciphertext[2:], encrypted)
+ } else {
+ ckx.ciphertext = encrypted
+ }
+ return preMasterSecret, ckx, nil
+}
+
+// sha1Hash calculates a SHA1 hash over the given byte slices.
+func sha1Hash(slices [][]byte) []byte {
+ hsha1 := sha1.New()
+ for _, slice := range slices {
+ hsha1.Write(slice)
+ }
+ return hsha1.Sum(nil)
+}
+
+// md5SHA1Hash implements TLS 1.0's hybrid hash function which consists of the
+// concatenation of an MD5 and SHA1 hash.
+func md5SHA1Hash(slices [][]byte) []byte {
+ md5sha1 := make([]byte, md5.Size+sha1.Size)
+ hmd5 := md5.New()
+ for _, slice := range slices {
+ hmd5.Write(slice)
+ }
+ copy(md5sha1, hmd5.Sum(nil))
+ copy(md5sha1[md5.Size:], sha1Hash(slices))
+ return md5sha1
+}
+
+// hashForServerKeyExchange hashes the given slices and returns their digest
+// and the identifier of the hash function used. The hashFunc argument is only
+// used for >= TLS 1.2 and precisely identifies the hash function to use.
+func hashForServerKeyExchange(sigType, hashFunc uint8, version uint16, slices ...[]byte) ([]byte, crypto.Hash, error) {
+ if version >= VersionTLS12 {
+ hash, err := lookupTLSHash(hashFunc)
+ if err != nil {
+ return nil, 0, err
+ }
+ h := hash.New()
+ for _, slice := range slices {
+ h.Write(slice)
+ }
+ return h.Sum(nil), hash, nil
+ }
+ if sigType == signatureECDSA {
+ return sha1Hash(slices), crypto.SHA1, nil
+ }
+ return md5SHA1Hash(slices), crypto.MD5SHA1, nil
+}
+
+// pickTLS12HashForSignature returns a TLS 1.2 hash identifier for signing a
+// ServerKeyExchange given the signature type being used and the client's
+// advertized list of supported signature and hash combinations.
+func pickTLS12HashForSignature(sigType uint8, clientSignatureAndHashes []signatureAndHash) (uint8, error) {
+ if len(clientSignatureAndHashes) == 0 {
+ // If the client didn't specify any signature_algorithms
+ // extension then we can assume that it supports SHA1. See
+ // http://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
+ return hashSHA1, nil
+ }
+
+ for _, sigAndHash := range clientSignatureAndHashes {
+ if sigAndHash.signature != sigType {
+ continue
+ }
+ switch sigAndHash.hash {
+ case hashSHA1, hashSHA256:
+ return sigAndHash.hash, nil
+ }
+ }
+
+ return 0, errors.New("tls: client doesn't support any common hash functions")
+}
+
+func curveForCurveID(id CurveID) (elliptic.Curve, bool) {
+ switch id {
+ case CurveP256:
+ return elliptic.P256(), true
+ case CurveP384:
+ return elliptic.P384(), true
+ case CurveP521:
+ return elliptic.P521(), true
+ default:
+ return nil, false
+ }
+
+}
+
+// keyAgreementAuthentication is a helper interface that specifies how
+// to authenticate the ServerKeyExchange parameters.
+type keyAgreementAuthentication interface {
+ signParameters(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg, params []byte) (*serverKeyExchangeMsg, error)
+ verifyParameters(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, params []byte, sig []byte) error
+}
+
+// nilKeyAgreementAuthentication does not authenticate the key
+// agreement parameters.
+type nilKeyAgreementAuthentication struct{}
+
+func (ka *nilKeyAgreementAuthentication) signParameters(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg, params []byte) (*serverKeyExchangeMsg, error) {
+ skx := new(serverKeyExchangeMsg)
+ skx.key = params
+ return skx, nil
+}
+
+func (ka *nilKeyAgreementAuthentication) verifyParameters(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, params []byte, sig []byte) error {
+ return nil
+}
+
+// signedKeyAgreement signs the ServerKeyExchange parameters with the
+// server's private key.
+type signedKeyAgreement struct {
+ version uint16
+ sigType uint8
+}
+
+func (ka *signedKeyAgreement) signParameters(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg, params []byte) (*serverKeyExchangeMsg, error) {
+ var tls12HashId uint8
+ var err error
+ if ka.version >= VersionTLS12 {
+ if tls12HashId, err = pickTLS12HashForSignature(ka.sigType, clientHello.signatureAndHashes); err != nil {
+ return nil, err
+ }
+ }
+
+ digest, hashFunc, err := hashForServerKeyExchange(ka.sigType, tls12HashId, ka.version, clientHello.random, hello.random, params)
+ if err != nil {
+ return nil, err
+ }
+
+ if config.Bugs.InvalidSKXSignature {
+ digest[0] ^= 0x80
+ }
+
+ var sig []byte
+ switch ka.sigType {
+ case signatureECDSA:
+ privKey, ok := cert.PrivateKey.(*ecdsa.PrivateKey)
+ if !ok {
+ return nil, errors.New("ECDHE ECDSA requires an ECDSA server private key")
+ }
+ r, s, err := ecdsa.Sign(config.rand(), privKey, digest)
+ if err != nil {
+ return nil, errors.New("failed to sign ECDHE parameters: " + err.Error())
+ }
+ order := privKey.Curve.Params().N
+ r = maybeCorruptECDSAValue(r, config.Bugs.BadECDSAR, order)
+ s = maybeCorruptECDSAValue(s, config.Bugs.BadECDSAS, order)
+ sig, err = asn1.Marshal(ecdsaSignature{r, s})
+ case signatureRSA:
+ privKey, ok := cert.PrivateKey.(*rsa.PrivateKey)
+ if !ok {
+ return nil, errors.New("ECDHE RSA requires a RSA server private key")
+ }
+ sig, err = rsa.SignPKCS1v15(config.rand(), privKey, hashFunc, digest)
+ if err != nil {
+ return nil, errors.New("failed to sign ECDHE parameters: " + err.Error())
+ }
+ default:
+ return nil, errors.New("unknown ECDHE signature algorithm")
+ }
+
+ skx := new(serverKeyExchangeMsg)
+ if config.Bugs.UnauthenticatedECDH {
+ skx.key = params
+ } else {
+ sigAndHashLen := 0
+ if ka.version >= VersionTLS12 {
+ sigAndHashLen = 2
+ }
+ skx.key = make([]byte, len(params)+sigAndHashLen+2+len(sig))
+ copy(skx.key, params)
+ k := skx.key[len(params):]
+ if ka.version >= VersionTLS12 {
+ k[0] = tls12HashId
+ k[1] = ka.sigType
+ k = k[2:]
+ }
+ k[0] = byte(len(sig) >> 8)
+ k[1] = byte(len(sig))
+ copy(k[2:], sig)
+ }
+
+ return skx, nil
+}
+
+func (ka *signedKeyAgreement) verifyParameters(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, params []byte, sig []byte) error {
+ if len(sig) < 2 {
+ return errServerKeyExchange
+ }
+
+ var tls12HashId uint8
+ if ka.version >= VersionTLS12 {
+ // handle SignatureAndHashAlgorithm
+ var sigAndHash []uint8
+ sigAndHash, sig = sig[:2], sig[2:]
+ if sigAndHash[1] != ka.sigType {
+ return errServerKeyExchange
+ }
+ tls12HashId = sigAndHash[0]
+ if len(sig) < 2 {
+ return errServerKeyExchange
+ }
+
+ if !isSupportedSignatureAndHash(signatureAndHash{ka.sigType, tls12HashId}, config.signatureAndHashesForClient()) {
+ return errors.New("tls: unsupported hash function for ServerKeyExchange")
+ }
+ }
+ sigLen := int(sig[0])<<8 | int(sig[1])
+ if sigLen+2 != len(sig) {
+ return errServerKeyExchange
+ }
+ sig = sig[2:]
+
+ digest, hashFunc, err := hashForServerKeyExchange(ka.sigType, tls12HashId, ka.version, clientHello.random, serverHello.random, params)
+ if err != nil {
+ return err
+ }
+ switch ka.sigType {
+ case signatureECDSA:
+ pubKey, ok := cert.PublicKey.(*ecdsa.PublicKey)
+ if !ok {
+ return errors.New("ECDHE ECDSA requires a ECDSA server public key")
+ }
+ ecdsaSig := new(ecdsaSignature)
+ if _, err := asn1.Unmarshal(sig, ecdsaSig); err != nil {
+ return err
+ }
+ if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 {
+ return errors.New("ECDSA signature contained zero or negative values")
+ }
+ if !ecdsa.Verify(pubKey, digest, ecdsaSig.R, ecdsaSig.S) {
+ return errors.New("ECDSA verification failure")
+ }
+ case signatureRSA:
+ pubKey, ok := cert.PublicKey.(*rsa.PublicKey)
+ if !ok {
+ return errors.New("ECDHE RSA requires a RSA server public key")
+ }
+ if err := rsa.VerifyPKCS1v15(pubKey, hashFunc, digest, sig); err != nil {
+ return err
+ }
+ default:
+ return errors.New("unknown ECDHE signature algorithm")
+ }
+
+ return nil
+}
+
+// ecdheRSAKeyAgreement implements a TLS key agreement where the server
+// generates a ephemeral EC public/private key pair and signs it. The
+// pre-master secret is then calculated using ECDH. The signature may
+// either be ECDSA or RSA.
+type ecdheKeyAgreement struct {
+ auth keyAgreementAuthentication
+ privateKey []byte
+ curve elliptic.Curve
+ x, y *big.Int
+}
+
+func maybeCorruptECDSAValue(n *big.Int, typeOfCorruption BadValue, limit *big.Int) *big.Int {
+ switch typeOfCorruption {
+ case BadValueNone:
+ return n
+ case BadValueNegative:
+ return new(big.Int).Neg(n)
+ case BadValueZero:
+ return big.NewInt(0)
+ case BadValueLimit:
+ return limit
+ case BadValueLarge:
+ bad := new(big.Int).Set(limit)
+ return bad.Lsh(bad, 20)
+ default:
+ panic("unknown BadValue type")
+ }
+}
+
+func (ka *ecdheKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
+ var curveid CurveID
+ preferredCurves := config.curvePreferences()
+
+NextCandidate:
+ for _, candidate := range preferredCurves {
+ for _, c := range clientHello.supportedCurves {
+ if candidate == c {
+ curveid = c
+ break NextCandidate
+ }
+ }
+ }
+
+ if curveid == 0 {
+ return nil, errors.New("tls: no supported elliptic curves offered")
+ }
+
+ var ok bool
+ if ka.curve, ok = curveForCurveID(curveid); !ok {
+ return nil, errors.New("tls: preferredCurves includes unsupported curve")
+ }
+
+ var x, y *big.Int
+ var err error
+ ka.privateKey, x, y, err = elliptic.GenerateKey(ka.curve, config.rand())
+ if err != nil {
+ return nil, err
+ }
+ ecdhePublic := elliptic.Marshal(ka.curve, x, y)
+
+ // http://tools.ietf.org/html/rfc4492#section-5.4
+ serverECDHParams := make([]byte, 1+2+1+len(ecdhePublic))
+ serverECDHParams[0] = 3 // named curve
+ serverECDHParams[1] = byte(curveid >> 8)
+ serverECDHParams[2] = byte(curveid)
+ if config.Bugs.InvalidSKXCurve {
+ serverECDHParams[2] ^= 0xff
+ }
+ serverECDHParams[3] = byte(len(ecdhePublic))
+ copy(serverECDHParams[4:], ecdhePublic)
+
+ return ka.auth.signParameters(config, cert, clientHello, hello, serverECDHParams)
+}
+
+func (ka *ecdheKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
+ if len(ckx.ciphertext) == 0 || int(ckx.ciphertext[0]) != len(ckx.ciphertext)-1 {
+ return nil, errClientKeyExchange
+ }
+ x, y := elliptic.Unmarshal(ka.curve, ckx.ciphertext[1:])
+ if x == nil {
+ return nil, errClientKeyExchange
+ }
+ x, _ = ka.curve.ScalarMult(x, y, ka.privateKey)
+ preMasterSecret := make([]byte, (ka.curve.Params().BitSize+7)>>3)
+ xBytes := x.Bytes()
+ copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes)
+
+ return preMasterSecret, nil
+}
+
+func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
+ if len(skx.key) < 4 {
+ return errServerKeyExchange
+ }
+ if skx.key[0] != 3 { // named curve
+ return errors.New("tls: server selected unsupported curve")
+ }
+ curveid := CurveID(skx.key[1])<<8 | CurveID(skx.key[2])
+
+ var ok bool
+ if ka.curve, ok = curveForCurveID(curveid); !ok {
+ return errors.New("tls: server selected unsupported curve")
+ }
+
+ publicLen := int(skx.key[3])
+ if publicLen+4 > len(skx.key) {
+ return errServerKeyExchange
+ }
+ ka.x, ka.y = elliptic.Unmarshal(ka.curve, skx.key[4:4+publicLen])
+ if ka.x == nil {
+ return errServerKeyExchange
+ }
+ serverECDHParams := skx.key[:4+publicLen]
+ sig := skx.key[4+publicLen:]
+
+ return ka.auth.verifyParameters(config, clientHello, serverHello, cert, serverECDHParams, sig)
+}
+
+func (ka *ecdheKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
+ if ka.curve == nil {
+ return nil, nil, errors.New("missing ServerKeyExchange message")
+ }
+ priv, mx, my, err := elliptic.GenerateKey(ka.curve, config.rand())
+ if err != nil {
+ return nil, nil, err
+ }
+ x, _ := ka.curve.ScalarMult(ka.x, ka.y, priv)
+ preMasterSecret := make([]byte, (ka.curve.Params().BitSize+7)>>3)
+ xBytes := x.Bytes()
+ copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes)
+
+ serialized := elliptic.Marshal(ka.curve, mx, my)
+
+ ckx := new(clientKeyExchangeMsg)
+ ckx.ciphertext = make([]byte, 1+len(serialized))
+ ckx.ciphertext[0] = byte(len(serialized))
+ copy(ckx.ciphertext[1:], serialized)
+
+ return preMasterSecret, ckx, nil
+}
+
+// dheRSAKeyAgreement implements a TLS key agreement where the server generates
+// an ephemeral Diffie-Hellman public/private key pair and signs it. The
+// pre-master secret is then calculated using Diffie-Hellman.
+type dheKeyAgreement struct {
+ auth keyAgreementAuthentication
+ p, g *big.Int
+ yTheirs *big.Int
+ xOurs *big.Int
+}
+
+func (ka *dheKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
+ // 2048-bit MODP Group with 256-bit Prime Order Subgroup (RFC
+ // 5114, Section 2.3)
+ ka.p, _ = new(big.Int).SetString("87A8E61DB4B6663CFFBBD19C651959998CEEF608660DD0F25D2CEED4435E3B00E00DF8F1D61957D4FAF7DF4561B2AA3016C3D91134096FAA3BF4296D830E9A7C209E0C6497517ABD5A8A9D306BCF67ED91F9E6725B4758C022E0B1EF4275BF7B6C5BFC11D45F9088B941F54EB1E59BB8BC39A0BF12307F5C4FDB70C581B23F76B63ACAE1CAA6B7902D52526735488A0EF13C6D9A51BFA4AB3AD8347796524D8EF6A167B5A41825D967E144E5140564251CCACB83E6B486F6B3CA3F7971506026C0B857F689962856DED4010ABD0BE621C3A3960A54E710C375F26375D7014103A4B54330C198AF126116D2276E11715F693877FAD7EF09CADB094AE91E1A1597", 16)
+ ka.g, _ = new(big.Int).SetString("3FB32C9B73134D0B2E77506660EDBD484CA7B18F21EF205407F4793A1A0BA12510DBC15077BE463FFF4FED4AAC0BB555BE3A6C1B0C6B47B1BC3773BF7E8C6F62901228F8C28CBB18A55AE31341000A650196F931C77A57F2DDF463E5E9EC144B777DE62AAAB8A8628AC376D282D6ED3864E67982428EBC831D14348F6F2F9193B5045AF2767164E1DFC967C1FB3F2E55A4BD1BFFE83B9C80D052B985D182EA0ADB2A3B7313D3FE14C8484B1E052588B9B7D2BBD2DF016199ECD06E1557CD0915B3353BBB64E0EC377FD028370DF92B52C7891428CDC67EB6184B523D1DB246C32F63078490F00EF8D647D148D47954515E2327CFEF98C582664B4C0F6CC41659", 16)
+ q, _ := new(big.Int).SetString("8CF83642A709A097B447997640129DA299B1A47D1EB3750BA308B0FE64F5FBD3", 16)
+
+ var err error
+ ka.xOurs, err = rand.Int(config.rand(), q)
+ if err != nil {
+ return nil, err
+ }
+ yOurs := new(big.Int).Exp(ka.g, ka.xOurs, ka.p)
+
+ // http://tools.ietf.org/html/rfc5246#section-7.4.3
+ pBytes := ka.p.Bytes()
+ gBytes := ka.g.Bytes()
+ yBytes := yOurs.Bytes()
+ serverDHParams := make([]byte, 0, 2+len(pBytes)+2+len(gBytes)+2+len(yBytes))
+ serverDHParams = append(serverDHParams, byte(len(pBytes)>>8), byte(len(pBytes)))
+ serverDHParams = append(serverDHParams, pBytes...)
+ serverDHParams = append(serverDHParams, byte(len(gBytes)>>8), byte(len(gBytes)))
+ serverDHParams = append(serverDHParams, gBytes...)
+ serverDHParams = append(serverDHParams, byte(len(yBytes)>>8), byte(len(yBytes)))
+ serverDHParams = append(serverDHParams, yBytes...)
+
+ return ka.auth.signParameters(config, cert, clientHello, hello, serverDHParams)
+}
+
+func (ka *dheKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
+ if len(ckx.ciphertext) < 2 {
+ return nil, errClientKeyExchange
+ }
+ yLen := (int(ckx.ciphertext[0]) << 8) | int(ckx.ciphertext[1])
+ if yLen != len(ckx.ciphertext)-2 {
+ return nil, errClientKeyExchange
+ }
+ yTheirs := new(big.Int).SetBytes(ckx.ciphertext[2:])
+ if yTheirs.Sign() <= 0 || yTheirs.Cmp(ka.p) >= 0 {
+ return nil, errClientKeyExchange
+ }
+ return new(big.Int).Exp(yTheirs, ka.xOurs, ka.p).Bytes(), nil
+}
+
+func (ka *dheKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
+ // Read dh_p
+ k := skx.key
+ if len(k) < 2 {
+ return errServerKeyExchange
+ }
+ pLen := (int(k[0]) << 8) | int(k[1])
+ k = k[2:]
+ if len(k) < pLen {
+ return errServerKeyExchange
+ }
+ ka.p = new(big.Int).SetBytes(k[:pLen])
+ k = k[pLen:]
+
+ // Read dh_g
+ if len(k) < 2 {
+ return errServerKeyExchange
+ }
+ gLen := (int(k[0]) << 8) | int(k[1])
+ k = k[2:]
+ if len(k) < gLen {
+ return errServerKeyExchange
+ }
+ ka.g = new(big.Int).SetBytes(k[:gLen])
+ k = k[gLen:]
+
+ // Read dh_Ys
+ if len(k) < 2 {
+ return errServerKeyExchange
+ }
+ yLen := (int(k[0]) << 8) | int(k[1])
+ k = k[2:]
+ if len(k) < yLen {
+ return errServerKeyExchange
+ }
+ ka.yTheirs = new(big.Int).SetBytes(k[:yLen])
+ k = k[yLen:]
+ if ka.yTheirs.Sign() <= 0 || ka.yTheirs.Cmp(ka.p) >= 0 {
+ return errServerKeyExchange
+ }
+
+ sig := k
+ serverDHParams := skx.key[:len(skx.key)-len(sig)]
+
+ return ka.auth.verifyParameters(config, clientHello, serverHello, cert, serverDHParams, sig)
+}
+
+func (ka *dheKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
+ if ka.p == nil || ka.g == nil || ka.yTheirs == nil {
+ return nil, nil, errors.New("missing ServerKeyExchange message")
+ }
+
+ xOurs, err := rand.Int(config.rand(), ka.p)
+ if err != nil {
+ return nil, nil, err
+ }
+ preMasterSecret := new(big.Int).Exp(ka.yTheirs, xOurs, ka.p).Bytes()
+
+ yOurs := new(big.Int).Exp(ka.g, xOurs, ka.p)
+ yBytes := yOurs.Bytes()
+ ckx := new(clientKeyExchangeMsg)
+ ckx.ciphertext = make([]byte, 2+len(yBytes))
+ ckx.ciphertext[0] = byte(len(yBytes) >> 8)
+ ckx.ciphertext[1] = byte(len(yBytes))
+ copy(ckx.ciphertext[2:], yBytes)
+
+ return preMasterSecret, ckx, nil
+}
+
+// nilKeyAgreement is a fake key agreement used to implement the plain PSK key
+// exchange.
+type nilKeyAgreement struct{}
+
+func (ka *nilKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
+ return nil, nil
+}
+
+func (ka *nilKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
+ if len(ckx.ciphertext) != 0 {
+ return nil, errClientKeyExchange
+ }
+
+ // Although in plain PSK, otherSecret is all zeros, the base key
+ // agreement does not access to the length of the pre-shared
+ // key. pskKeyAgreement instead interprets nil to mean to use all zeros
+ // of the appropriate length.
+ return nil, nil
+}
+
+func (ka *nilKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
+ if len(skx.key) != 0 {
+ return errServerKeyExchange
+ }
+ return nil
+}
+
+func (ka *nilKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
+ // Although in plain PSK, otherSecret is all zeros, the base key
+ // agreement does not access to the length of the pre-shared
+ // key. pskKeyAgreement instead interprets nil to mean to use all zeros
+ // of the appropriate length.
+ return nil, &clientKeyExchangeMsg{}, nil
+}
+
+// makePSKPremaster formats a PSK pre-master secret based on otherSecret from
+// the base key exchange and psk.
+func makePSKPremaster(otherSecret, psk []byte) []byte {
+ out := make([]byte, 0, 2+len(otherSecret)+2+len(psk))
+ out = append(out, byte(len(otherSecret)>>8), byte(len(otherSecret)))
+ out = append(out, otherSecret...)
+ out = append(out, byte(len(psk)>>8), byte(len(psk)))
+ out = append(out, psk...)
+ return out
+}
+
+// pskKeyAgreement implements the PSK key agreement.
+type pskKeyAgreement struct {
+ base keyAgreement
+ identityHint string
+}
+
+func (ka *pskKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
+ // Assemble the identity hint.
+ bytes := make([]byte, 2+len(config.PreSharedKeyIdentity))
+ bytes[0] = byte(len(config.PreSharedKeyIdentity) >> 8)
+ bytes[1] = byte(len(config.PreSharedKeyIdentity))
+ copy(bytes[2:], []byte(config.PreSharedKeyIdentity))
+
+ // If there is one, append the base key agreement's
+ // ServerKeyExchange.
+ baseSkx, err := ka.base.generateServerKeyExchange(config, cert, clientHello, hello)
+ if err != nil {
+ return nil, err
+ }
+
+ if baseSkx != nil {
+ bytes = append(bytes, baseSkx.key...)
+ } else if config.PreSharedKeyIdentity == "" {
+ // ServerKeyExchange is optional if the identity hint is empty
+ // and there would otherwise be no ServerKeyExchange.
+ return nil, nil
+ }
+
+ skx := new(serverKeyExchangeMsg)
+ skx.key = bytes
+ return skx, nil
+}
+
+func (ka *pskKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
+ // First, process the PSK identity.
+ if len(ckx.ciphertext) < 2 {
+ return nil, errClientKeyExchange
+ }
+ identityLen := (int(ckx.ciphertext[0]) << 8) | int(ckx.ciphertext[1])
+ if 2+identityLen > len(ckx.ciphertext) {
+ return nil, errClientKeyExchange
+ }
+ identity := string(ckx.ciphertext[2 : 2+identityLen])
+
+ if identity != config.PreSharedKeyIdentity {
+ return nil, errors.New("tls: unexpected identity")
+ }
+
+ if config.PreSharedKey == nil {
+ return nil, errors.New("tls: pre-shared key not configured")
+ }
+
+ // Process the remainder of the ClientKeyExchange to compute the base
+ // pre-master secret.
+ newCkx := new(clientKeyExchangeMsg)
+ newCkx.ciphertext = ckx.ciphertext[2+identityLen:]
+ otherSecret, err := ka.base.processClientKeyExchange(config, cert, newCkx, version)
+ if err != nil {
+ return nil, err
+ }
+
+ if otherSecret == nil {
+ // Special-case for the plain PSK key exchanges.
+ otherSecret = make([]byte, len(config.PreSharedKey))
+ }
+ return makePSKPremaster(otherSecret, config.PreSharedKey), nil
+}
+
+func (ka *pskKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
+ if len(skx.key) < 2 {
+ return errServerKeyExchange
+ }
+ identityLen := (int(skx.key[0]) << 8) | int(skx.key[1])
+ if 2+identityLen > len(skx.key) {
+ return errServerKeyExchange
+ }
+ ka.identityHint = string(skx.key[2 : 2+identityLen])
+
+ // Process the remainder of the ServerKeyExchange.
+ newSkx := new(serverKeyExchangeMsg)
+ newSkx.key = skx.key[2+identityLen:]
+ return ka.base.processServerKeyExchange(config, clientHello, serverHello, cert, newSkx)
+}
+
+func (ka *pskKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
+ // The server only sends an identity hint but, for purposes of
+ // test code, the server always sends the hint and it is
+ // required to match.
+ if ka.identityHint != config.PreSharedKeyIdentity {
+ return nil, nil, errors.New("tls: unexpected identity")
+ }
+
+ // Serialize the identity.
+ bytes := make([]byte, 2+len(config.PreSharedKeyIdentity))
+ bytes[0] = byte(len(config.PreSharedKeyIdentity) >> 8)
+ bytes[1] = byte(len(config.PreSharedKeyIdentity))
+ copy(bytes[2:], []byte(config.PreSharedKeyIdentity))
+
+ // Append the base key exchange's ClientKeyExchange.
+ otherSecret, baseCkx, err := ka.base.generateClientKeyExchange(config, clientHello, cert)
+ if err != nil {
+ return nil, nil, err
+ }
+ ckx := new(clientKeyExchangeMsg)
+ ckx.ciphertext = append(bytes, baseCkx.ciphertext...)
+
+ if config.PreSharedKey == nil {
+ return nil, nil, errors.New("tls: pre-shared key not configured")
+ }
+ if otherSecret == nil {
+ otherSecret = make([]byte, len(config.PreSharedKey))
+ }
+ return makePSKPremaster(otherSecret, config.PreSharedKey), ckx, nil
+}
diff --git a/src/ssl/test/runner/packet_adapter.go b/src/ssl/test/runner/packet_adapter.go
new file mode 100644
index 0000000..671b413
--- /dev/null
+++ b/src/ssl/test/runner/packet_adapter.go
@@ -0,0 +1,101 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "encoding/binary"
+ "errors"
+ "net"
+)
+
+type packetAdaptor struct {
+ net.Conn
+}
+
+// newPacketAdaptor wraps a reliable streaming net.Conn into a
+// reliable packet-based net.Conn. Every packet is encoded with a
+// 32-bit length prefix as a framing layer.
+func newPacketAdaptor(conn net.Conn) net.Conn {
+ return &packetAdaptor{conn}
+}
+
+func (p *packetAdaptor) Read(b []byte) (int, error) {
+ var length uint32
+ if err := binary.Read(p.Conn, binary.BigEndian, &length); err != nil {
+ return 0, err
+ }
+ out := make([]byte, length)
+ n, err := p.Conn.Read(out)
+ if err != nil {
+ return 0, err
+ }
+ if n != int(length) {
+ return 0, errors.New("internal error: length mismatch!")
+ }
+ return copy(b, out), nil
+}
+
+func (p *packetAdaptor) Write(b []byte) (int, error) {
+ length := uint32(len(b))
+ if err := binary.Write(p.Conn, binary.BigEndian, length); err != nil {
+ return 0, err
+ }
+ n, err := p.Conn.Write(b)
+ if err != nil {
+ return 0, err
+ }
+ if n != len(b) {
+ return 0, errors.New("internal error: length mismatch!")
+ }
+ return len(b), nil
+}
+
+type replayAdaptor struct {
+ net.Conn
+ prevWrite []byte
+}
+
+// newReplayAdaptor wraps a packeted net.Conn. It transforms it into
+// one which, after writing a packet, always replays the previous
+// write.
+func newReplayAdaptor(conn net.Conn) net.Conn {
+ return &replayAdaptor{Conn: conn}
+}
+
+func (r *replayAdaptor) Write(b []byte) (int, error) {
+ n, err := r.Conn.Write(b)
+
+ // Replay the previous packet and save the current one to
+ // replay next.
+ if r.prevWrite != nil {
+ r.Conn.Write(r.prevWrite)
+ }
+ r.prevWrite = append(r.prevWrite[:0], b...)
+
+ return n, err
+}
+
+type damageAdaptor struct {
+ net.Conn
+ damage bool
+}
+
+// newDamageAdaptor wraps a packeted net.Conn. It transforms it into one which
+// optionally damages the final byte of every Write() call.
+func newDamageAdaptor(conn net.Conn) *damageAdaptor {
+ return &damageAdaptor{Conn: conn}
+}
+
+func (d *damageAdaptor) setDamage(damage bool) {
+ d.damage = damage
+}
+
+func (d *damageAdaptor) Write(b []byte) (int, error) {
+ if d.damage && len(b) > 0 {
+ b = append([]byte{}, b...)
+ b[len(b)-1]++
+ }
+ return d.Conn.Write(b)
+}
diff --git a/src/ssl/test/runner/prf.go b/src/ssl/test/runner/prf.go
new file mode 100644
index 0000000..75a8933
--- /dev/null
+++ b/src/ssl/test/runner/prf.go
@@ -0,0 +1,388 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "crypto"
+ "crypto/hmac"
+ "crypto/md5"
+ "crypto/sha1"
+ "crypto/sha256"
+ "crypto/sha512"
+ "errors"
+ "hash"
+)
+
+// Split a premaster secret in two as specified in RFC 4346, section 5.
+func splitPreMasterSecret(secret []byte) (s1, s2 []byte) {
+ s1 = secret[0 : (len(secret)+1)/2]
+ s2 = secret[len(secret)/2:]
+ return
+}
+
+// pHash implements the P_hash function, as defined in RFC 4346, section 5.
+func pHash(result, secret, seed []byte, hash func() hash.Hash) {
+ h := hmac.New(hash, secret)
+ h.Write(seed)
+ a := h.Sum(nil)
+
+ j := 0
+ for j < len(result) {
+ h.Reset()
+ h.Write(a)
+ h.Write(seed)
+ b := h.Sum(nil)
+ todo := len(b)
+ if j+todo > len(result) {
+ todo = len(result) - j
+ }
+ copy(result[j:j+todo], b)
+ j += todo
+
+ h.Reset()
+ h.Write(a)
+ a = h.Sum(nil)
+ }
+}
+
+// prf10 implements the TLS 1.0 pseudo-random function, as defined in RFC 2246, section 5.
+func prf10(result, secret, label, seed []byte) {
+ hashSHA1 := sha1.New
+ hashMD5 := md5.New
+
+ labelAndSeed := make([]byte, len(label)+len(seed))
+ copy(labelAndSeed, label)
+ copy(labelAndSeed[len(label):], seed)
+
+ s1, s2 := splitPreMasterSecret(secret)
+ pHash(result, s1, labelAndSeed, hashMD5)
+ result2 := make([]byte, len(result))
+ pHash(result2, s2, labelAndSeed, hashSHA1)
+
+ for i, b := range result2 {
+ result[i] ^= b
+ }
+}
+
+// prf12 implements the TLS 1.2 pseudo-random function, as defined in RFC 5246, section 5.
+func prf12(hashFunc func() hash.Hash) func(result, secret, label, seed []byte) {
+ return func(result, secret, label, seed []byte) {
+ labelAndSeed := make([]byte, len(label)+len(seed))
+ copy(labelAndSeed, label)
+ copy(labelAndSeed[len(label):], seed)
+
+ pHash(result, secret, labelAndSeed, hashFunc)
+ }
+}
+
+// prf30 implements the SSL 3.0 pseudo-random function, as defined in
+// www.mozilla.org/projects/security/pki/nss/ssl/draft302.txt section 6.
+func prf30(result, secret, label, seed []byte) {
+ hashSHA1 := sha1.New()
+ hashMD5 := md5.New()
+
+ done := 0
+ i := 0
+ // RFC5246 section 6.3 says that the largest PRF output needed is 128
+ // bytes. Since no more ciphersuites will be added to SSLv3, this will
+ // remain true. Each iteration gives us 16 bytes so 10 iterations will
+ // be sufficient.
+ var b [11]byte
+ for done < len(result) {
+ for j := 0; j <= i; j++ {
+ b[j] = 'A' + byte(i)
+ }
+
+ hashSHA1.Reset()
+ hashSHA1.Write(b[:i+1])
+ hashSHA1.Write(secret)
+ hashSHA1.Write(seed)
+ digest := hashSHA1.Sum(nil)
+
+ hashMD5.Reset()
+ hashMD5.Write(secret)
+ hashMD5.Write(digest)
+
+ done += copy(result[done:], hashMD5.Sum(nil))
+ i++
+ }
+}
+
+const (
+ tlsRandomLength = 32 // Length of a random nonce in TLS 1.1.
+ masterSecretLength = 48 // Length of a master secret in TLS 1.1.
+ finishedVerifyLength = 12 // Length of verify_data in a Finished message.
+)
+
+var masterSecretLabel = []byte("master secret")
+var extendedMasterSecretLabel = []byte("extended master secret")
+var keyExpansionLabel = []byte("key expansion")
+var clientFinishedLabel = []byte("client finished")
+var serverFinishedLabel = []byte("server finished")
+var channelIDLabel = []byte("TLS Channel ID signature\x00")
+var channelIDResumeLabel = []byte("Resumption\x00")
+
+func prfForVersion(version uint16, suite *cipherSuite) func(result, secret, label, seed []byte) {
+ switch version {
+ case VersionSSL30:
+ return prf30
+ case VersionTLS10, VersionTLS11:
+ return prf10
+ case VersionTLS12:
+ if suite.flags&suiteSHA384 != 0 {
+ return prf12(sha512.New384)
+ }
+ return prf12(sha256.New)
+ default:
+ panic("unknown version")
+ }
+}
+
+// masterFromPreMasterSecret generates the master secret from the pre-master
+// secret. See http://tools.ietf.org/html/rfc5246#section-8.1
+func masterFromPreMasterSecret(version uint16, suite *cipherSuite, preMasterSecret, clientRandom, serverRandom []byte) []byte {
+ var seed [tlsRandomLength * 2]byte
+ copy(seed[0:len(clientRandom)], clientRandom)
+ copy(seed[len(clientRandom):], serverRandom)
+ masterSecret := make([]byte, masterSecretLength)
+ prfForVersion(version, suite)(masterSecret, preMasterSecret, masterSecretLabel, seed[0:])
+ return masterSecret
+}
+
+// extendedMasterFromPreMasterSecret generates the master secret from the
+// pre-master secret when the Triple Handshake fix is in effect. See
+// https://tools.ietf.org/html/draft-ietf-tls-session-hash-01
+func extendedMasterFromPreMasterSecret(version uint16, suite *cipherSuite, preMasterSecret []byte, h finishedHash) []byte {
+ masterSecret := make([]byte, masterSecretLength)
+ prfForVersion(version, suite)(masterSecret, preMasterSecret, extendedMasterSecretLabel, h.Sum())
+ return masterSecret
+}
+
+// keysFromMasterSecret generates the connection keys from the master
+// secret, given the lengths of the MAC key, cipher key and IV, as defined in
+// RFC 2246, section 6.3.
+func keysFromMasterSecret(version uint16, suite *cipherSuite, masterSecret, clientRandom, serverRandom []byte, macLen, keyLen, ivLen int) (clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV []byte) {
+ var seed [tlsRandomLength * 2]byte
+ copy(seed[0:len(clientRandom)], serverRandom)
+ copy(seed[len(serverRandom):], clientRandom)
+
+ n := 2*macLen + 2*keyLen + 2*ivLen
+ keyMaterial := make([]byte, n)
+ prfForVersion(version, suite)(keyMaterial, masterSecret, keyExpansionLabel, seed[0:])
+ clientMAC = keyMaterial[:macLen]
+ keyMaterial = keyMaterial[macLen:]
+ serverMAC = keyMaterial[:macLen]
+ keyMaterial = keyMaterial[macLen:]
+ clientKey = keyMaterial[:keyLen]
+ keyMaterial = keyMaterial[keyLen:]
+ serverKey = keyMaterial[:keyLen]
+ keyMaterial = keyMaterial[keyLen:]
+ clientIV = keyMaterial[:ivLen]
+ keyMaterial = keyMaterial[ivLen:]
+ serverIV = keyMaterial[:ivLen]
+ return
+}
+
+// lookupTLSHash looks up the corresponding crypto.Hash for a given
+// TLS hash identifier.
+func lookupTLSHash(hash uint8) (crypto.Hash, error) {
+ switch hash {
+ case hashMD5:
+ return crypto.MD5, nil
+ case hashSHA1:
+ return crypto.SHA1, nil
+ case hashSHA224:
+ return crypto.SHA224, nil
+ case hashSHA256:
+ return crypto.SHA256, nil
+ case hashSHA384:
+ return crypto.SHA384, nil
+ case hashSHA512:
+ return crypto.SHA512, nil
+ default:
+ return 0, errors.New("tls: unsupported hash algorithm")
+ }
+}
+
+func newFinishedHash(version uint16, cipherSuite *cipherSuite) finishedHash {
+ if version >= VersionTLS12 {
+ newHash := sha256.New
+ if cipherSuite.flags&suiteSHA384 != 0 {
+ newHash = sha512.New384
+ }
+
+ return finishedHash{newHash(), newHash(), nil, nil, []byte{}, version, prf12(newHash)}
+ }
+ return finishedHash{sha1.New(), sha1.New(), md5.New(), md5.New(), []byte{}, version, prf10}
+}
+
+// A finishedHash calculates the hash of a set of handshake messages suitable
+// for including in a Finished message.
+type finishedHash struct {
+ client hash.Hash
+ server hash.Hash
+
+ // Prior to TLS 1.2, an additional MD5 hash is required.
+ clientMD5 hash.Hash
+ serverMD5 hash.Hash
+
+ // In TLS 1.2 (and SSL 3 for implementation convenience), a
+ // full buffer is required.
+ buffer []byte
+
+ version uint16
+ prf func(result, secret, label, seed []byte)
+}
+
+func (h *finishedHash) Write(msg []byte) (n int, err error) {
+ h.client.Write(msg)
+ h.server.Write(msg)
+
+ if h.version < VersionTLS12 {
+ h.clientMD5.Write(msg)
+ h.serverMD5.Write(msg)
+ }
+
+ if h.buffer != nil {
+ h.buffer = append(h.buffer, msg...)
+ }
+
+ return len(msg), nil
+}
+
+func (h finishedHash) Sum() []byte {
+ if h.version >= VersionTLS12 {
+ return h.client.Sum(nil)
+ }
+
+ out := make([]byte, 0, md5.Size+sha1.Size)
+ out = h.clientMD5.Sum(out)
+ return h.client.Sum(out)
+}
+
+// finishedSum30 calculates the contents of the verify_data member of a SSLv3
+// Finished message given the MD5 and SHA1 hashes of a set of handshake
+// messages.
+func finishedSum30(md5, sha1 hash.Hash, masterSecret []byte, magic []byte) []byte {
+ md5.Write(magic)
+ md5.Write(masterSecret)
+ md5.Write(ssl30Pad1[:])
+ md5Digest := md5.Sum(nil)
+
+ md5.Reset()
+ md5.Write(masterSecret)
+ md5.Write(ssl30Pad2[:])
+ md5.Write(md5Digest)
+ md5Digest = md5.Sum(nil)
+
+ sha1.Write(magic)
+ sha1.Write(masterSecret)
+ sha1.Write(ssl30Pad1[:40])
+ sha1Digest := sha1.Sum(nil)
+
+ sha1.Reset()
+ sha1.Write(masterSecret)
+ sha1.Write(ssl30Pad2[:40])
+ sha1.Write(sha1Digest)
+ sha1Digest = sha1.Sum(nil)
+
+ ret := make([]byte, len(md5Digest)+len(sha1Digest))
+ copy(ret, md5Digest)
+ copy(ret[len(md5Digest):], sha1Digest)
+ return ret
+}
+
+var ssl3ClientFinishedMagic = [4]byte{0x43, 0x4c, 0x4e, 0x54}
+var ssl3ServerFinishedMagic = [4]byte{0x53, 0x52, 0x56, 0x52}
+
+// clientSum returns the contents of the verify_data member of a client's
+// Finished message.
+func (h finishedHash) clientSum(masterSecret []byte) []byte {
+ if h.version == VersionSSL30 {
+ return finishedSum30(h.clientMD5, h.client, masterSecret, ssl3ClientFinishedMagic[:])
+ }
+
+ out := make([]byte, finishedVerifyLength)
+ h.prf(out, masterSecret, clientFinishedLabel, h.Sum())
+ return out
+}
+
+// serverSum returns the contents of the verify_data member of a server's
+// Finished message.
+func (h finishedHash) serverSum(masterSecret []byte) []byte {
+ if h.version == VersionSSL30 {
+ return finishedSum30(h.serverMD5, h.server, masterSecret, ssl3ServerFinishedMagic[:])
+ }
+
+ out := make([]byte, finishedVerifyLength)
+ h.prf(out, masterSecret, serverFinishedLabel, h.Sum())
+ return out
+}
+
+// selectClientCertSignatureAlgorithm returns a signatureAndHash to sign a
+// client's CertificateVerify with, or an error if none can be found.
+func (h finishedHash) selectClientCertSignatureAlgorithm(serverList []signatureAndHash, sigType uint8) (signatureAndHash, error) {
+ if h.version < VersionTLS12 {
+ // Nothing to negotiate before TLS 1.2.
+ return signatureAndHash{signature: sigType}, nil
+ }
+
+ for _, v := range serverList {
+ if v.signature == sigType && v.hash == hashSHA256 {
+ return v, nil
+ }
+ }
+ return signatureAndHash{}, errors.New("tls: no supported signature algorithm found for signing client certificate")
+}
+
+// hashForClientCertificate returns a digest, hash function, and TLS 1.2 hash
+// id suitable for signing by a TLS client certificate.
+func (h finishedHash) hashForClientCertificate(signatureAndHash signatureAndHash, masterSecret []byte) ([]byte, crypto.Hash, error) {
+ if h.version == VersionSSL30 {
+ if signatureAndHash.signature != signatureRSA {
+ return nil, 0, errors.New("tls: unsupported signature type for client certificate")
+ }
+
+ md5Hash := md5.New()
+ md5Hash.Write(h.buffer)
+ sha1Hash := sha1.New()
+ sha1Hash.Write(h.buffer)
+ return finishedSum30(md5Hash, sha1Hash, masterSecret, nil), crypto.MD5SHA1, nil
+ }
+ if h.version >= VersionTLS12 {
+ hashAlg, err := lookupTLSHash(signatureAndHash.hash)
+ if err != nil {
+ return nil, 0, err
+ }
+ hash := hashAlg.New()
+ hash.Write(h.buffer)
+ return hash.Sum(nil), hashAlg, nil
+ }
+ if signatureAndHash.signature == signatureECDSA {
+ return h.server.Sum(nil), crypto.SHA1, nil
+ }
+
+ return h.Sum(), crypto.MD5SHA1, nil
+}
+
+// hashForChannelID returns the hash to be signed for TLS Channel
+// ID. If a resumption, resumeHash has the previous handshake
+// hash. Otherwise, it is nil.
+func (h finishedHash) hashForChannelID(resumeHash []byte) []byte {
+ hash := sha256.New()
+ hash.Write(channelIDLabel)
+ if resumeHash != nil {
+ hash.Write(channelIDResumeLabel)
+ hash.Write(resumeHash)
+ }
+ hash.Write(h.server.Sum(nil))
+ return hash.Sum(nil)
+}
+
+// discardHandshakeBuffer is called when there is no more need to
+// buffer the entirety of the handshake messages.
+func (h *finishedHash) discardHandshakeBuffer() {
+ h.buffer = nil
+}
diff --git a/src/ssl/test/runner/recordingconn.go b/src/ssl/test/runner/recordingconn.go
new file mode 100644
index 0000000..a67fa48
--- /dev/null
+++ b/src/ssl/test/runner/recordingconn.go
@@ -0,0 +1,130 @@
+package main
+
+import (
+ "bufio"
+ "encoding/hex"
+ "errors"
+ "fmt"
+ "io"
+ "net"
+ "strconv"
+ "strings"
+ "sync"
+)
+
+// recordingConn is a net.Conn that records the traffic that passes through it.
+// WriteTo can be used to produce output that can be later be loaded with
+// ParseTestData.
+type recordingConn struct {
+ net.Conn
+ sync.Mutex
+ flows [][]byte
+ reading bool
+}
+
+func (r *recordingConn) Read(b []byte) (n int, err error) {
+ if n, err = r.Conn.Read(b); n == 0 {
+ return
+ }
+ b = b[:n]
+
+ r.Lock()
+ defer r.Unlock()
+
+ if l := len(r.flows); l == 0 || !r.reading {
+ buf := make([]byte, len(b))
+ copy(buf, b)
+ r.flows = append(r.flows, buf)
+ } else {
+ r.flows[l-1] = append(r.flows[l-1], b[:n]...)
+ }
+ r.reading = true
+ return
+}
+
+func (r *recordingConn) Write(b []byte) (n int, err error) {
+ if n, err = r.Conn.Write(b); n == 0 {
+ return
+ }
+ b = b[:n]
+
+ r.Lock()
+ defer r.Unlock()
+
+ if l := len(r.flows); l == 0 || r.reading {
+ buf := make([]byte, len(b))
+ copy(buf, b)
+ r.flows = append(r.flows, buf)
+ } else {
+ r.flows[l-1] = append(r.flows[l-1], b[:n]...)
+ }
+ r.reading = false
+ return
+}
+
+// WriteTo writes hex dumps to w that contains the recorded traffic.
+func (r *recordingConn) WriteTo(w io.Writer) {
+ // TLS always starts with a client to server flow.
+ clientToServer := true
+
+ for i, flow := range r.flows {
+ source, dest := "client", "server"
+ if !clientToServer {
+ source, dest = dest, source
+ }
+ fmt.Fprintf(w, ">>> Flow %d (%s to %s)\n", i+1, source, dest)
+ dumper := hex.Dumper(w)
+ dumper.Write(flow)
+ dumper.Close()
+ clientToServer = !clientToServer
+ }
+}
+
+func parseTestData(r io.Reader) (flows [][]byte, err error) {
+ var currentFlow []byte
+
+ scanner := bufio.NewScanner(r)
+ for scanner.Scan() {
+ line := scanner.Text()
+ // If the line starts with ">>> " then it marks the beginning
+ // of a new flow.
+ if strings.HasPrefix(line, ">>> ") {
+ if len(currentFlow) > 0 || len(flows) > 0 {
+ flows = append(flows, currentFlow)
+ currentFlow = nil
+ }
+ continue
+ }
+
+ // Otherwise the line is a line of hex dump that looks like:
+ // 00000170 fc f5 06 bf (...) |.....X{&?......!|
+ // (Some bytes have been omitted from the middle section.)
+
+ if i := strings.IndexByte(line, ' '); i >= 0 {
+ line = line[i:]
+ } else {
+ return nil, errors.New("invalid test data")
+ }
+
+ if i := strings.IndexByte(line, '|'); i >= 0 {
+ line = line[:i]
+ } else {
+ return nil, errors.New("invalid test data")
+ }
+
+ hexBytes := strings.Fields(line)
+ for _, hexByte := range hexBytes {
+ val, err := strconv.ParseUint(hexByte, 16, 8)
+ if err != nil {
+ return nil, errors.New("invalid hex byte in test data: " + err.Error())
+ }
+ currentFlow = append(currentFlow, byte(val))
+ }
+ }
+
+ if len(currentFlow) > 0 {
+ flows = append(flows, currentFlow)
+ }
+
+ return flows, nil
+}
diff --git a/src/ssl/test/runner/runner.go b/src/ssl/test/runner/runner.go
new file mode 100644
index 0000000..137a87c
--- /dev/null
+++ b/src/ssl/test/runner/runner.go
@@ -0,0 +1,2649 @@
+package main
+
+import (
+ "bytes"
+ "crypto/ecdsa"
+ "crypto/elliptic"
+ "crypto/x509"
+ "encoding/base64"
+ "encoding/pem"
+ "flag"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "net"
+ "os"
+ "os/exec"
+ "path"
+ "runtime"
+ "strconv"
+ "strings"
+ "sync"
+ "syscall"
+)
+
+var (
+ useValgrind = flag.Bool("valgrind", false, "If true, run code under valgrind")
+ useGDB = flag.Bool("gdb", false, "If true, run BoringSSL code under gdb")
+ flagDebug *bool = flag.Bool("debug", false, "Hexdump the contents of the connection")
+ mallocTest *int64 = flag.Int64("malloc-test", -1, "If non-negative, run each test with each malloc in turn failing from the given number onwards.")
+ mallocTestDebug *bool = flag.Bool("malloc-test-debug", false, "If true, ask bssl_shim to abort rather than fail a malloc. This can be used with a specific value for --malloc-test to identity the malloc failing that is causing problems.")
+)
+
+const (
+ rsaCertificateFile = "cert.pem"
+ ecdsaCertificateFile = "ecdsa_cert.pem"
+)
+
+const (
+ rsaKeyFile = "key.pem"
+ ecdsaKeyFile = "ecdsa_key.pem"
+ channelIDKeyFile = "channel_id_key.pem"
+)
+
+var rsaCertificate, ecdsaCertificate Certificate
+var channelIDKey *ecdsa.PrivateKey
+var channelIDBytes []byte
+
+var testOCSPResponse = []byte{1, 2, 3, 4}
+var testSCTList = []byte{5, 6, 7, 8}
+
+func initCertificates() {
+ var err error
+ rsaCertificate, err = LoadX509KeyPair(rsaCertificateFile, rsaKeyFile)
+ if err != nil {
+ panic(err)
+ }
+ rsaCertificate.OCSPStaple = testOCSPResponse
+ rsaCertificate.SignedCertificateTimestampList = testSCTList
+
+ ecdsaCertificate, err = LoadX509KeyPair(ecdsaCertificateFile, ecdsaKeyFile)
+ if err != nil {
+ panic(err)
+ }
+ ecdsaCertificate.OCSPStaple = testOCSPResponse
+ ecdsaCertificate.SignedCertificateTimestampList = testSCTList
+
+ channelIDPEMBlock, err := ioutil.ReadFile(channelIDKeyFile)
+ if err != nil {
+ panic(err)
+ }
+ channelIDDERBlock, _ := pem.Decode(channelIDPEMBlock)
+ if channelIDDERBlock.Type != "EC PRIVATE KEY" {
+ panic("bad key type")
+ }
+ channelIDKey, err = x509.ParseECPrivateKey(channelIDDERBlock.Bytes)
+ if err != nil {
+ panic(err)
+ }
+ if channelIDKey.Curve != elliptic.P256() {
+ panic("bad curve")
+ }
+
+ channelIDBytes = make([]byte, 64)
+ writeIntPadded(channelIDBytes[:32], channelIDKey.X)
+ writeIntPadded(channelIDBytes[32:], channelIDKey.Y)
+}
+
+var certificateOnce sync.Once
+
+func getRSACertificate() Certificate {
+ certificateOnce.Do(initCertificates)
+ return rsaCertificate
+}
+
+func getECDSACertificate() Certificate {
+ certificateOnce.Do(initCertificates)
+ return ecdsaCertificate
+}
+
+type testType int
+
+const (
+ clientTest testType = iota
+ serverTest
+)
+
+type protocol int
+
+const (
+ tls protocol = iota
+ dtls
+)
+
+const (
+ alpn = 1
+ npn = 2
+)
+
+type testCase struct {
+ testType testType
+ protocol protocol
+ name string
+ config Config
+ shouldFail bool
+ expectedError string
+ // expectedLocalError, if not empty, contains a substring that must be
+ // found in the local error.
+ expectedLocalError string
+ // expectedVersion, if non-zero, specifies the TLS version that must be
+ // negotiated.
+ expectedVersion uint16
+ // expectedResumeVersion, if non-zero, specifies the TLS version that
+ // must be negotiated on resumption. If zero, expectedVersion is used.
+ expectedResumeVersion uint16
+ // expectChannelID controls whether the connection should have
+ // negotiated a Channel ID with channelIDKey.
+ expectChannelID bool
+ // expectedNextProto controls whether the connection should
+ // negotiate a next protocol via NPN or ALPN.
+ expectedNextProto string
+ // expectedNextProtoType, if non-zero, is the expected next
+ // protocol negotiation mechanism.
+ expectedNextProtoType int
+ // expectedSRTPProtectionProfile is the DTLS-SRTP profile that
+ // should be negotiated. If zero, none should be negotiated.
+ expectedSRTPProtectionProfile uint16
+ // messageLen is the length, in bytes, of the test message that will be
+ // sent.
+ messageLen int
+ // certFile is the path to the certificate to use for the server.
+ certFile string
+ // keyFile is the path to the private key to use for the server.
+ keyFile string
+ // resumeSession controls whether a second connection should be tested
+ // which attempts to resume the first session.
+ resumeSession bool
+ // resumeConfig, if not nil, points to a Config to be used on
+ // resumption. Unless newSessionsOnResume is set,
+ // SessionTicketKey, ServerSessionCache, and
+ // ClientSessionCache are copied from the initial connection's
+ // config. If nil, the initial connection's config is used.
+ resumeConfig *Config
+ // newSessionsOnResume, if true, will cause resumeConfig to
+ // use a different session resumption context.
+ newSessionsOnResume bool
+ // sendPrefix sends a prefix on the socket before actually performing a
+ // handshake.
+ sendPrefix string
+ // shimWritesFirst controls whether the shim sends an initial "hello"
+ // message before doing a roundtrip with the runner.
+ shimWritesFirst bool
+ // renegotiate indicates the the connection should be renegotiated
+ // during the exchange.
+ renegotiate bool
+ // renegotiateCiphers is a list of ciphersuite ids that will be
+ // switched in just before renegotiation.
+ renegotiateCiphers []uint16
+ // replayWrites, if true, configures the underlying transport
+ // to replay every write it makes in DTLS tests.
+ replayWrites bool
+ // damageFirstWrite, if true, configures the underlying transport to
+ // damage the final byte of the first application data write.
+ damageFirstWrite bool
+ // flags, if not empty, contains a list of command-line flags that will
+ // be passed to the shim program.
+ flags []string
+}
+
+var testCases = []testCase{
+ {
+ name: "BadRSASignature",
+ config: Config{
+ CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+ Bugs: ProtocolBugs{
+ InvalidSKXSignature: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":BAD_SIGNATURE:",
+ },
+ {
+ name: "BadECDSASignature",
+ config: Config{
+ CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
+ Bugs: ProtocolBugs{
+ InvalidSKXSignature: true,
+ },
+ Certificates: []Certificate{getECDSACertificate()},
+ },
+ shouldFail: true,
+ expectedError: ":BAD_SIGNATURE:",
+ },
+ {
+ name: "BadECDSACurve",
+ config: Config{
+ CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
+ Bugs: ProtocolBugs{
+ InvalidSKXCurve: true,
+ },
+ Certificates: []Certificate{getECDSACertificate()},
+ },
+ shouldFail: true,
+ expectedError: ":WRONG_CURVE:",
+ },
+ {
+ testType: serverTest,
+ name: "BadRSAVersion",
+ config: Config{
+ CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
+ Bugs: ProtocolBugs{
+ RsaClientKeyExchangeVersion: VersionTLS11,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
+ },
+ {
+ name: "NoFallbackSCSV",
+ config: Config{
+ Bugs: ProtocolBugs{
+ FailIfNotFallbackSCSV: true,
+ },
+ },
+ shouldFail: true,
+ expectedLocalError: "no fallback SCSV found",
+ },
+ {
+ name: "SendFallbackSCSV",
+ config: Config{
+ Bugs: ProtocolBugs{
+ FailIfNotFallbackSCSV: true,
+ },
+ },
+ flags: []string{"-fallback-scsv"},
+ },
+ {
+ name: "ClientCertificateTypes",
+ config: Config{
+ ClientAuth: RequestClientCert,
+ ClientCertificateTypes: []byte{
+ CertTypeDSSSign,
+ CertTypeRSASign,
+ CertTypeECDSASign,
+ },
+ },
+ flags: []string{
+ "-expect-certificate-types",
+ base64.StdEncoding.EncodeToString([]byte{
+ CertTypeDSSSign,
+ CertTypeRSASign,
+ CertTypeECDSASign,
+ }),
+ },
+ },
+ {
+ name: "NoClientCertificate",
+ config: Config{
+ ClientAuth: RequireAnyClientCert,
+ },
+ shouldFail: true,
+ expectedLocalError: "client didn't provide a certificate",
+ },
+ {
+ name: "UnauthenticatedECDH",
+ config: Config{
+ CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+ Bugs: ProtocolBugs{
+ UnauthenticatedECDH: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":UNEXPECTED_MESSAGE:",
+ },
+ {
+ name: "SkipServerKeyExchange",
+ config: Config{
+ CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+ Bugs: ProtocolBugs{
+ SkipServerKeyExchange: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":UNEXPECTED_MESSAGE:",
+ },
+ {
+ name: "SkipChangeCipherSpec-Client",
+ config: Config{
+ Bugs: ProtocolBugs{
+ SkipChangeCipherSpec: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
+ },
+ {
+ testType: serverTest,
+ name: "SkipChangeCipherSpec-Server",
+ config: Config{
+ Bugs: ProtocolBugs{
+ SkipChangeCipherSpec: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
+ },
+ {
+ testType: serverTest,
+ name: "SkipChangeCipherSpec-Server-NPN",
+ config: Config{
+ NextProtos: []string{"bar"},
+ Bugs: ProtocolBugs{
+ SkipChangeCipherSpec: true,
+ },
+ },
+ flags: []string{
+ "-advertise-npn", "\x03foo\x03bar\x03baz",
+ },
+ shouldFail: true,
+ expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
+ },
+ {
+ name: "FragmentAcrossChangeCipherSpec-Client",
+ config: Config{
+ Bugs: ProtocolBugs{
+ FragmentAcrossChangeCipherSpec: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
+ },
+ {
+ testType: serverTest,
+ name: "FragmentAcrossChangeCipherSpec-Server",
+ config: Config{
+ Bugs: ProtocolBugs{
+ FragmentAcrossChangeCipherSpec: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
+ },
+ {
+ testType: serverTest,
+ name: "FragmentAcrossChangeCipherSpec-Server-NPN",
+ config: Config{
+ NextProtos: []string{"bar"},
+ Bugs: ProtocolBugs{
+ FragmentAcrossChangeCipherSpec: true,
+ },
+ },
+ flags: []string{
+ "-advertise-npn", "\x03foo\x03bar\x03baz",
+ },
+ shouldFail: true,
+ expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
+ },
+ {
+ testType: serverTest,
+ name: "FragmentAlert",
+ config: Config{
+ Bugs: ProtocolBugs{
+ FragmentAlert: true,
+ SendSpuriousAlert: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":BAD_ALERT:",
+ },
+ {
+ testType: serverTest,
+ name: "EarlyChangeCipherSpec-server-1",
+ config: Config{
+ Bugs: ProtocolBugs{
+ EarlyChangeCipherSpec: 1,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":CCS_RECEIVED_EARLY:",
+ },
+ {
+ testType: serverTest,
+ name: "EarlyChangeCipherSpec-server-2",
+ config: Config{
+ Bugs: ProtocolBugs{
+ EarlyChangeCipherSpec: 2,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":CCS_RECEIVED_EARLY:",
+ },
+ {
+ name: "SkipNewSessionTicket",
+ config: Config{
+ Bugs: ProtocolBugs{
+ SkipNewSessionTicket: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":CCS_RECEIVED_EARLY:",
+ },
+ {
+ testType: serverTest,
+ name: "FallbackSCSV",
+ config: Config{
+ MaxVersion: VersionTLS11,
+ Bugs: ProtocolBugs{
+ SendFallbackSCSV: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":INAPPROPRIATE_FALLBACK:",
+ },
+ {
+ testType: serverTest,
+ name: "FallbackSCSV-VersionMatch",
+ config: Config{
+ Bugs: ProtocolBugs{
+ SendFallbackSCSV: true,
+ },
+ },
+ },
+ {
+ testType: serverTest,
+ name: "FragmentedClientVersion",
+ config: Config{
+ Bugs: ProtocolBugs{
+ MaxHandshakeRecordLength: 1,
+ FragmentClientVersion: true,
+ },
+ },
+ expectedVersion: VersionTLS12,
+ },
+ {
+ testType: serverTest,
+ name: "MinorVersionTolerance",
+ config: Config{
+ Bugs: ProtocolBugs{
+ SendClientVersion: 0x03ff,
+ },
+ },
+ expectedVersion: VersionTLS12,
+ },
+ {
+ testType: serverTest,
+ name: "MajorVersionTolerance",
+ config: Config{
+ Bugs: ProtocolBugs{
+ SendClientVersion: 0x0400,
+ },
+ },
+ expectedVersion: VersionTLS12,
+ },
+ {
+ testType: serverTest,
+ name: "VersionTooLow",
+ config: Config{
+ Bugs: ProtocolBugs{
+ SendClientVersion: 0x0200,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":UNSUPPORTED_PROTOCOL:",
+ },
+ {
+ testType: serverTest,
+ name: "HttpGET",
+ sendPrefix: "GET / HTTP/1.0\n",
+ shouldFail: true,
+ expectedError: ":HTTP_REQUEST:",
+ },
+ {
+ testType: serverTest,
+ name: "HttpPOST",
+ sendPrefix: "POST / HTTP/1.0\n",
+ shouldFail: true,
+ expectedError: ":HTTP_REQUEST:",
+ },
+ {
+ testType: serverTest,
+ name: "HttpHEAD",
+ sendPrefix: "HEAD / HTTP/1.0\n",
+ shouldFail: true,
+ expectedError: ":HTTP_REQUEST:",
+ },
+ {
+ testType: serverTest,
+ name: "HttpPUT",
+ sendPrefix: "PUT / HTTP/1.0\n",
+ shouldFail: true,
+ expectedError: ":HTTP_REQUEST:",
+ },
+ {
+ testType: serverTest,
+ name: "HttpCONNECT",
+ sendPrefix: "CONNECT www.google.com:443 HTTP/1.0\n",
+ shouldFail: true,
+ expectedError: ":HTTPS_PROXY_REQUEST:",
+ },
+ {
+ testType: serverTest,
+ name: "Garbage",
+ sendPrefix: "blah",
+ shouldFail: true,
+ expectedError: ":UNKNOWN_PROTOCOL:",
+ },
+ {
+ name: "SkipCipherVersionCheck",
+ config: Config{
+ CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
+ MaxVersion: VersionTLS11,
+ Bugs: ProtocolBugs{
+ SkipCipherVersionCheck: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":WRONG_CIPHER_RETURNED:",
+ },
+ {
+ name: "RSAServerKeyExchange",
+ config: Config{
+ CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
+ Bugs: ProtocolBugs{
+ RSAServerKeyExchange: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":UNEXPECTED_MESSAGE:",
+ },
+ {
+ name: "DisableEverything",
+ flags: []string{"-no-tls12", "-no-tls11", "-no-tls1", "-no-ssl3"},
+ shouldFail: true,
+ expectedError: ":WRONG_SSL_VERSION:",
+ },
+ {
+ protocol: dtls,
+ name: "DisableEverything-DTLS",
+ flags: []string{"-no-tls12", "-no-tls1"},
+ shouldFail: true,
+ expectedError: ":WRONG_SSL_VERSION:",
+ },
+ {
+ name: "NoSharedCipher",
+ config: Config{
+ CipherSuites: []uint16{},
+ },
+ shouldFail: true,
+ expectedError: ":HANDSHAKE_FAILURE_ON_CLIENT_HELLO:",
+ },
+ {
+ protocol: dtls,
+ testType: serverTest,
+ name: "MTU",
+ config: Config{
+ Bugs: ProtocolBugs{
+ MaxPacketLength: 256,
+ },
+ },
+ flags: []string{"-mtu", "256"},
+ },
+ {
+ protocol: dtls,
+ testType: serverTest,
+ name: "MTUExceeded",
+ config: Config{
+ Bugs: ProtocolBugs{
+ MaxPacketLength: 255,
+ },
+ },
+ flags: []string{"-mtu", "256"},
+ shouldFail: true,
+ expectedLocalError: "dtls: exceeded maximum packet length",
+ },
+ {
+ name: "CertMismatchRSA",
+ config: Config{
+ CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
+ Certificates: []Certificate{getECDSACertificate()},
+ Bugs: ProtocolBugs{
+ SendCipherSuite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":WRONG_CERTIFICATE_TYPE:",
+ },
+ {
+ name: "CertMismatchECDSA",
+ config: Config{
+ CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+ Certificates: []Certificate{getRSACertificate()},
+ Bugs: ProtocolBugs{
+ SendCipherSuite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":WRONG_CERTIFICATE_TYPE:",
+ },
+ {
+ name: "TLSFatalBadPackets",
+ damageFirstWrite: true,
+ shouldFail: true,
+ expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
+ },
+ {
+ protocol: dtls,
+ name: "DTLSIgnoreBadPackets",
+ damageFirstWrite: true,
+ },
+ {
+ protocol: dtls,
+ name: "DTLSIgnoreBadPackets-Async",
+ damageFirstWrite: true,
+ flags: []string{"-async"},
+ },
+ {
+ name: "AppDataAfterChangeCipherSpec",
+ config: Config{
+ Bugs: ProtocolBugs{
+ AppDataAfterChangeCipherSpec: []byte("TEST MESSAGE"),
+ },
+ },
+ shouldFail: true,
+ expectedError: ":DATA_BETWEEN_CCS_AND_FINISHED:",
+ },
+ {
+ protocol: dtls,
+ name: "AppDataAfterChangeCipherSpec-DTLS",
+ config: Config{
+ Bugs: ProtocolBugs{
+ AppDataAfterChangeCipherSpec: []byte("TEST MESSAGE"),
+ },
+ },
+ },
+}
+
+func doExchange(test *testCase, config *Config, conn net.Conn, messageLen int, isResume bool) error {
+ var connDebug *recordingConn
+ var connDamage *damageAdaptor
+ if *flagDebug {
+ connDebug = &recordingConn{Conn: conn}
+ conn = connDebug
+ defer func() {
+ connDebug.WriteTo(os.Stdout)
+ }()
+ }
+
+ if test.protocol == dtls {
+ conn = newPacketAdaptor(conn)
+ if test.replayWrites {
+ conn = newReplayAdaptor(conn)
+ }
+ }
+
+ if test.damageFirstWrite {
+ connDamage = newDamageAdaptor(conn)
+ conn = connDamage
+ }
+
+ if test.sendPrefix != "" {
+ if _, err := conn.Write([]byte(test.sendPrefix)); err != nil {
+ return err
+ }
+ }
+
+ var tlsConn *Conn
+ if test.testType == clientTest {
+ if test.protocol == dtls {
+ tlsConn = DTLSServer(conn, config)
+ } else {
+ tlsConn = Server(conn, config)
+ }
+ } else {
+ config.InsecureSkipVerify = true
+ if test.protocol == dtls {
+ tlsConn = DTLSClient(conn, config)
+ } else {
+ tlsConn = Client(conn, config)
+ }
+ }
+
+ if err := tlsConn.Handshake(); err != nil {
+ return err
+ }
+
+ // TODO(davidben): move all per-connection expectations into a dedicated
+ // expectations struct that can be specified separately for the two
+ // legs.
+ expectedVersion := test.expectedVersion
+ if isResume && test.expectedResumeVersion != 0 {
+ expectedVersion = test.expectedResumeVersion
+ }
+ if vers := tlsConn.ConnectionState().Version; expectedVersion != 0 && vers != expectedVersion {
+ return fmt.Errorf("got version %x, expected %x", vers, expectedVersion)
+ }
+
+ if test.expectChannelID {
+ channelID := tlsConn.ConnectionState().ChannelID
+ if channelID == nil {
+ return fmt.Errorf("no channel ID negotiated")
+ }
+ if channelID.Curve != channelIDKey.Curve ||
+ channelIDKey.X.Cmp(channelIDKey.X) != 0 ||
+ channelIDKey.Y.Cmp(channelIDKey.Y) != 0 {
+ return fmt.Errorf("incorrect channel ID")
+ }
+ }
+
+ if expected := test.expectedNextProto; expected != "" {
+ if actual := tlsConn.ConnectionState().NegotiatedProtocol; actual != expected {
+ return fmt.Errorf("next proto mismatch: got %s, wanted %s", actual, expected)
+ }
+ }
+
+ if test.expectedNextProtoType != 0 {
+ if (test.expectedNextProtoType == alpn) != tlsConn.ConnectionState().NegotiatedProtocolFromALPN {
+ return fmt.Errorf("next proto type mismatch")
+ }
+ }
+
+ if p := tlsConn.ConnectionState().SRTPProtectionProfile; p != test.expectedSRTPProtectionProfile {
+ return fmt.Errorf("SRTP profile mismatch: got %d, wanted %d", p, test.expectedSRTPProtectionProfile)
+ }
+
+ if test.shimWritesFirst {
+ var buf [5]byte
+ _, err := io.ReadFull(tlsConn, buf[:])
+ if err != nil {
+ return err
+ }
+ if string(buf[:]) != "hello" {
+ return fmt.Errorf("bad initial message")
+ }
+ }
+
+ if test.renegotiate {
+ if test.renegotiateCiphers != nil {
+ config.CipherSuites = test.renegotiateCiphers
+ }
+ if err := tlsConn.Renegotiate(); err != nil {
+ return err
+ }
+ } else if test.renegotiateCiphers != nil {
+ panic("renegotiateCiphers without renegotiate")
+ }
+
+ if test.damageFirstWrite {
+ connDamage.setDamage(true)
+ tlsConn.Write([]byte("DAMAGED WRITE"))
+ connDamage.setDamage(false)
+ }
+
+ if messageLen < 0 {
+ if test.protocol == dtls {
+ return fmt.Errorf("messageLen < 0 not supported for DTLS tests")
+ }
+ // Read until EOF.
+ _, err := io.Copy(ioutil.Discard, tlsConn)
+ return err
+ }
+
+ var testMessage []byte
+ if config.Bugs.AppDataAfterChangeCipherSpec != nil {
+ // We've already sent a message. Expect the shim to echo it
+ // back.
+ testMessage = config.Bugs.AppDataAfterChangeCipherSpec
+ } else {
+ if messageLen == 0 {
+ messageLen = 32
+ }
+ testMessage = make([]byte, messageLen)
+ for i := range testMessage {
+ testMessage[i] = 0x42
+ }
+ tlsConn.Write(testMessage)
+ }
+
+ buf := make([]byte, len(testMessage))
+ if test.protocol == dtls {
+ bufTmp := make([]byte, len(buf)+1)
+ n, err := tlsConn.Read(bufTmp)
+ if err != nil {
+ return err
+ }
+ if n != len(buf) {
+ return fmt.Errorf("bad reply; length mismatch (%d vs %d)", n, len(buf))
+ }
+ copy(buf, bufTmp)
+ } else {
+ _, err := io.ReadFull(tlsConn, buf)
+ if err != nil {
+ return err
+ }
+ }
+
+ for i, v := range buf {
+ if v != testMessage[i]^0xff {
+ return fmt.Errorf("bad reply contents at byte %d", i)
+ }
+ }
+
+ return nil
+}
+
+func valgrindOf(dbAttach bool, path string, args ...string) *exec.Cmd {
+ valgrindArgs := []string{"--error-exitcode=99", "--track-origins=yes", "--leak-check=full"}
+ if dbAttach {
+ valgrindArgs = append(valgrindArgs, "--db-attach=yes", "--db-command=xterm -e gdb -nw %f %p")
+ }
+ valgrindArgs = append(valgrindArgs, path)
+ valgrindArgs = append(valgrindArgs, args...)
+
+ return exec.Command("valgrind", valgrindArgs...)
+}
+
+func gdbOf(path string, args ...string) *exec.Cmd {
+ xtermArgs := []string{"-e", "gdb", "--args"}
+ xtermArgs = append(xtermArgs, path)
+ xtermArgs = append(xtermArgs, args...)
+
+ return exec.Command("xterm", xtermArgs...)
+}
+
+func openSocketPair() (shimEnd *os.File, conn net.Conn) {
+ socks, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_STREAM, 0)
+ if err != nil {
+ panic(err)
+ }
+
+ syscall.CloseOnExec(socks[0])
+ syscall.CloseOnExec(socks[1])
+ shimEnd = os.NewFile(uintptr(socks[0]), "shim end")
+ connFile := os.NewFile(uintptr(socks[1]), "our end")
+ conn, err = net.FileConn(connFile)
+ if err != nil {
+ panic(err)
+ }
+ connFile.Close()
+ if err != nil {
+ panic(err)
+ }
+ return shimEnd, conn
+}
+
+type moreMallocsError struct{}
+
+func (moreMallocsError) Error() string {
+ return "child process did not exhaust all allocation calls"
+}
+
+var errMoreMallocs = moreMallocsError{}
+
+func runTest(test *testCase, buildDir string, mallocNumToFail int64) error {
+ if !test.shouldFail && (len(test.expectedError) > 0 || len(test.expectedLocalError) > 0) {
+ panic("Error expected without shouldFail in " + test.name)
+ }
+
+ shimEnd, conn := openSocketPair()
+ shimEndResume, connResume := openSocketPair()
+
+ shim_path := path.Join(buildDir, "ssl/test/bssl_shim")
+ var flags []string
+ if test.testType == serverTest {
+ flags = append(flags, "-server")
+
+ flags = append(flags, "-key-file")
+ if test.keyFile == "" {
+ flags = append(flags, rsaKeyFile)
+ } else {
+ flags = append(flags, test.keyFile)
+ }
+
+ flags = append(flags, "-cert-file")
+ if test.certFile == "" {
+ flags = append(flags, rsaCertificateFile)
+ } else {
+ flags = append(flags, test.certFile)
+ }
+ }
+
+ if test.protocol == dtls {
+ flags = append(flags, "-dtls")
+ }
+
+ if test.resumeSession {
+ flags = append(flags, "-resume")
+ }
+
+ if test.shimWritesFirst {
+ flags = append(flags, "-shim-writes-first")
+ }
+
+ flags = append(flags, test.flags...)
+
+ var shim *exec.Cmd
+ if *useValgrind {
+ shim = valgrindOf(false, shim_path, flags...)
+ } else if *useGDB {
+ shim = gdbOf(shim_path, flags...)
+ } else {
+ shim = exec.Command(shim_path, flags...)
+ }
+ shim.ExtraFiles = []*os.File{shimEnd, shimEndResume}
+ shim.Stdin = os.Stdin
+ var stdoutBuf, stderrBuf bytes.Buffer
+ shim.Stdout = &stdoutBuf
+ shim.Stderr = &stderrBuf
+ if mallocNumToFail >= 0 {
+ shim.Env = []string{"MALLOC_NUMBER_TO_FAIL=" + strconv.FormatInt(mallocNumToFail, 10)}
+ if *mallocTestDebug {
+ shim.Env = append(shim.Env, "MALLOC_ABORT_ON_FAIL=1")
+ }
+ shim.Env = append(shim.Env, "_MALLOC_CHECK=1")
+ }
+
+ if err := shim.Start(); err != nil {
+ panic(err)
+ }
+ shimEnd.Close()
+ shimEndResume.Close()
+
+ config := test.config
+ config.ClientSessionCache = NewLRUClientSessionCache(1)
+ config.ServerSessionCache = NewLRUServerSessionCache(1)
+ if test.testType == clientTest {
+ if len(config.Certificates) == 0 {
+ config.Certificates = []Certificate{getRSACertificate()}
+ }
+ }
+
+ err := doExchange(test, &config, conn, test.messageLen,
+ false /* not a resumption */)
+ conn.Close()
+
+ if err == nil && test.resumeSession {
+ var resumeConfig Config
+ if test.resumeConfig != nil {
+ resumeConfig = *test.resumeConfig
+ if len(resumeConfig.Certificates) == 0 {
+ resumeConfig.Certificates = []Certificate{getRSACertificate()}
+ }
+ if !test.newSessionsOnResume {
+ resumeConfig.SessionTicketKey = config.SessionTicketKey
+ resumeConfig.ClientSessionCache = config.ClientSessionCache
+ resumeConfig.ServerSessionCache = config.ServerSessionCache
+ }
+ } else {
+ resumeConfig = config
+ }
+ err = doExchange(test, &resumeConfig, connResume, test.messageLen,
+ true /* resumption */)
+ }
+ connResume.Close()
+
+ childErr := shim.Wait()
+ if exitError, ok := childErr.(*exec.ExitError); ok {
+ if exitError.Sys().(syscall.WaitStatus).ExitStatus() == 88 {
+ return errMoreMallocs
+ }
+ }
+
+ stdout := string(stdoutBuf.Bytes())
+ stderr := string(stderrBuf.Bytes())
+ failed := err != nil || childErr != nil
+ correctFailure := len(test.expectedError) == 0 || strings.Contains(stdout, test.expectedError)
+ localError := "none"
+ if err != nil {
+ localError = err.Error()
+ }
+ if len(test.expectedLocalError) != 0 {
+ correctFailure = correctFailure && strings.Contains(localError, test.expectedLocalError)
+ }
+
+ if failed != test.shouldFail || failed && !correctFailure {
+ childError := "none"
+ if childErr != nil {
+ childError = childErr.Error()
+ }
+
+ var msg string
+ switch {
+ case failed && !test.shouldFail:
+ msg = "unexpected failure"
+ case !failed && test.shouldFail:
+ msg = "unexpected success"
+ case failed && !correctFailure:
+ msg = "bad error (wanted '" + test.expectedError + "' / '" + test.expectedLocalError + "')"
+ default:
+ panic("internal error")
+ }
+
+ return fmt.Errorf("%s: local error '%s', child error '%s', stdout:\n%s\nstderr:\n%s", msg, localError, childError, string(stdoutBuf.Bytes()), stderr)
+ }
+
+ if !*useValgrind && len(stderr) > 0 {
+ println(stderr)
+ }
+
+ return nil
+}
+
+var tlsVersions = []struct {
+ name string
+ version uint16
+ flag string
+ hasDTLS bool
+}{
+ {"SSL3", VersionSSL30, "-no-ssl3", false},
+ {"TLS1", VersionTLS10, "-no-tls1", true},
+ {"TLS11", VersionTLS11, "-no-tls11", false},
+ {"TLS12", VersionTLS12, "-no-tls12", true},
+}
+
+var testCipherSuites = []struct {
+ name string
+ id uint16
+}{
+ {"3DES-SHA", TLS_RSA_WITH_3DES_EDE_CBC_SHA},
+ {"AES128-GCM", TLS_RSA_WITH_AES_128_GCM_SHA256},
+ {"AES128-SHA", TLS_RSA_WITH_AES_128_CBC_SHA},
+ {"AES128-SHA256", TLS_RSA_WITH_AES_128_CBC_SHA256},
+ {"AES256-GCM", TLS_RSA_WITH_AES_256_GCM_SHA384},
+ {"AES256-SHA", TLS_RSA_WITH_AES_256_CBC_SHA},
+ {"AES256-SHA256", TLS_RSA_WITH_AES_256_CBC_SHA256},
+ {"DHE-RSA-AES128-GCM", TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
+ {"DHE-RSA-AES128-SHA", TLS_DHE_RSA_WITH_AES_128_CBC_SHA},
+ {"DHE-RSA-AES128-SHA256", TLS_DHE_RSA_WITH_AES_128_CBC_SHA256},
+ {"DHE-RSA-AES256-GCM", TLS_DHE_RSA_WITH_AES_256_GCM_SHA384},
+ {"DHE-RSA-AES256-SHA", TLS_DHE_RSA_WITH_AES_256_CBC_SHA},
+ {"DHE-RSA-AES256-SHA256", TLS_DHE_RSA_WITH_AES_256_CBC_SHA256},
+ {"ECDHE-ECDSA-AES128-GCM", TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
+ {"ECDHE-ECDSA-AES128-SHA", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA},
+ {"ECDHE-ECDSA-AES128-SHA256", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256},
+ {"ECDHE-ECDSA-AES256-GCM", TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384},
+ {"ECDHE-ECDSA-AES256-SHA", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA},
+ {"ECDHE-ECDSA-AES256-SHA384", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384},
+ {"ECDHE-ECDSA-RC4-SHA", TLS_ECDHE_ECDSA_WITH_RC4_128_SHA},
+ {"ECDHE-PSK-WITH-AES-128-GCM-SHA256", TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256},
+ {"ECDHE-RSA-AES128-GCM", TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+ {"ECDHE-RSA-AES128-SHA", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
+ {"ECDHE-RSA-AES128-SHA256", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256},
+ {"ECDHE-RSA-AES256-GCM", TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384},
+ {"ECDHE-RSA-AES256-SHA", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA},
+ {"ECDHE-RSA-AES256-SHA384", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384},
+ {"ECDHE-RSA-RC4-SHA", TLS_ECDHE_RSA_WITH_RC4_128_SHA},
+ {"PSK-AES128-CBC-SHA", TLS_PSK_WITH_AES_128_CBC_SHA},
+ {"PSK-AES256-CBC-SHA", TLS_PSK_WITH_AES_256_CBC_SHA},
+ {"PSK-RC4-SHA", TLS_PSK_WITH_RC4_128_SHA},
+ {"RC4-MD5", TLS_RSA_WITH_RC4_128_MD5},
+ {"RC4-SHA", TLS_RSA_WITH_RC4_128_SHA},
+}
+
+func hasComponent(suiteName, component string) bool {
+ return strings.Contains("-"+suiteName+"-", "-"+component+"-")
+}
+
+func isTLS12Only(suiteName string) bool {
+ return hasComponent(suiteName, "GCM") ||
+ hasComponent(suiteName, "SHA256") ||
+ hasComponent(suiteName, "SHA384")
+}
+
+func isDTLSCipher(suiteName string) bool {
+ return !hasComponent(suiteName, "RC4")
+}
+
+func addCipherSuiteTests() {
+ for _, suite := range testCipherSuites {
+ const psk = "12345"
+ const pskIdentity = "luggage combo"
+
+ var cert Certificate
+ var certFile string
+ var keyFile string
+ if hasComponent(suite.name, "ECDSA") {
+ cert = getECDSACertificate()
+ certFile = ecdsaCertificateFile
+ keyFile = ecdsaKeyFile
+ } else {
+ cert = getRSACertificate()
+ certFile = rsaCertificateFile
+ keyFile = rsaKeyFile
+ }
+
+ var flags []string
+ if hasComponent(suite.name, "PSK") {
+ flags = append(flags,
+ "-psk", psk,
+ "-psk-identity", pskIdentity)
+ }
+
+ for _, ver := range tlsVersions {
+ if ver.version < VersionTLS12 && isTLS12Only(suite.name) {
+ continue
+ }
+
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: ver.name + "-" + suite.name + "-client",
+ config: Config{
+ MinVersion: ver.version,
+ MaxVersion: ver.version,
+ CipherSuites: []uint16{suite.id},
+ Certificates: []Certificate{cert},
+ PreSharedKey: []byte(psk),
+ PreSharedKeyIdentity: pskIdentity,
+ },
+ flags: flags,
+ resumeSession: true,
+ })
+
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: ver.name + "-" + suite.name + "-server",
+ config: Config{
+ MinVersion: ver.version,
+ MaxVersion: ver.version,
+ CipherSuites: []uint16{suite.id},
+ Certificates: []Certificate{cert},
+ PreSharedKey: []byte(psk),
+ PreSharedKeyIdentity: pskIdentity,
+ },
+ certFile: certFile,
+ keyFile: keyFile,
+ flags: flags,
+ resumeSession: true,
+ })
+
+ if ver.hasDTLS && isDTLSCipher(suite.name) {
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ protocol: dtls,
+ name: "D" + ver.name + "-" + suite.name + "-client",
+ config: Config{
+ MinVersion: ver.version,
+ MaxVersion: ver.version,
+ CipherSuites: []uint16{suite.id},
+ Certificates: []Certificate{cert},
+ PreSharedKey: []byte(psk),
+ PreSharedKeyIdentity: pskIdentity,
+ },
+ flags: flags,
+ resumeSession: true,
+ })
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ protocol: dtls,
+ name: "D" + ver.name + "-" + suite.name + "-server",
+ config: Config{
+ MinVersion: ver.version,
+ MaxVersion: ver.version,
+ CipherSuites: []uint16{suite.id},
+ Certificates: []Certificate{cert},
+ PreSharedKey: []byte(psk),
+ PreSharedKeyIdentity: pskIdentity,
+ },
+ certFile: certFile,
+ keyFile: keyFile,
+ flags: flags,
+ resumeSession: true,
+ })
+ }
+ }
+ }
+}
+
+func addBadECDSASignatureTests() {
+ for badR := BadValue(1); badR < NumBadValues; badR++ {
+ for badS := BadValue(1); badS < NumBadValues; badS++ {
+ testCases = append(testCases, testCase{
+ name: fmt.Sprintf("BadECDSA-%d-%d", badR, badS),
+ config: Config{
+ CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
+ Certificates: []Certificate{getECDSACertificate()},
+ Bugs: ProtocolBugs{
+ BadECDSAR: badR,
+ BadECDSAS: badS,
+ },
+ },
+ shouldFail: true,
+ expectedError: "SIGNATURE",
+ })
+ }
+ }
+}
+
+func addCBCPaddingTests() {
+ testCases = append(testCases, testCase{
+ name: "MaxCBCPadding",
+ config: Config{
+ CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
+ Bugs: ProtocolBugs{
+ MaxPadding: true,
+ },
+ },
+ messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size
+ })
+ testCases = append(testCases, testCase{
+ name: "BadCBCPadding",
+ config: Config{
+ CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
+ Bugs: ProtocolBugs{
+ PaddingFirstByteBad: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: "DECRYPTION_FAILED_OR_BAD_RECORD_MAC",
+ })
+ // OpenSSL previously had an issue where the first byte of padding in
+ // 255 bytes of padding wasn't checked.
+ testCases = append(testCases, testCase{
+ name: "BadCBCPadding255",
+ config: Config{
+ CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
+ Bugs: ProtocolBugs{
+ MaxPadding: true,
+ PaddingFirstByteBadIf255: true,
+ },
+ },
+ messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size
+ shouldFail: true,
+ expectedError: "DECRYPTION_FAILED_OR_BAD_RECORD_MAC",
+ })
+}
+
+func addCBCSplittingTests() {
+ testCases = append(testCases, testCase{
+ name: "CBCRecordSplitting",
+ config: Config{
+ MaxVersion: VersionTLS10,
+ MinVersion: VersionTLS10,
+ CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
+ },
+ messageLen: -1, // read until EOF
+ flags: []string{
+ "-async",
+ "-write-different-record-sizes",
+ "-cbc-record-splitting",
+ },
+ })
+ testCases = append(testCases, testCase{
+ name: "CBCRecordSplittingPartialWrite",
+ config: Config{
+ MaxVersion: VersionTLS10,
+ MinVersion: VersionTLS10,
+ CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
+ },
+ messageLen: -1, // read until EOF
+ flags: []string{
+ "-async",
+ "-write-different-record-sizes",
+ "-cbc-record-splitting",
+ "-partial-write",
+ },
+ })
+}
+
+func addClientAuthTests() {
+ // Add a dummy cert pool to stress certificate authority parsing.
+ // TODO(davidben): Add tests that those values parse out correctly.
+ certPool := x509.NewCertPool()
+ cert, err := x509.ParseCertificate(rsaCertificate.Certificate[0])
+ if err != nil {
+ panic(err)
+ }
+ certPool.AddCert(cert)
+
+ for _, ver := range tlsVersions {
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: ver.name + "-Client-ClientAuth-RSA",
+ config: Config{
+ MinVersion: ver.version,
+ MaxVersion: ver.version,
+ ClientAuth: RequireAnyClientCert,
+ ClientCAs: certPool,
+ },
+ flags: []string{
+ "-cert-file", rsaCertificateFile,
+ "-key-file", rsaKeyFile,
+ },
+ })
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: ver.name + "-Server-ClientAuth-RSA",
+ config: Config{
+ MinVersion: ver.version,
+ MaxVersion: ver.version,
+ Certificates: []Certificate{rsaCertificate},
+ },
+ flags: []string{"-require-any-client-certificate"},
+ })
+ if ver.version != VersionSSL30 {
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: ver.name + "-Server-ClientAuth-ECDSA",
+ config: Config{
+ MinVersion: ver.version,
+ MaxVersion: ver.version,
+ Certificates: []Certificate{ecdsaCertificate},
+ },
+ flags: []string{"-require-any-client-certificate"},
+ })
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: ver.name + "-Client-ClientAuth-ECDSA",
+ config: Config{
+ MinVersion: ver.version,
+ MaxVersion: ver.version,
+ ClientAuth: RequireAnyClientCert,
+ ClientCAs: certPool,
+ },
+ flags: []string{
+ "-cert-file", ecdsaCertificateFile,
+ "-key-file", ecdsaKeyFile,
+ },
+ })
+ }
+ }
+}
+
+func addExtendedMasterSecretTests() {
+ const expectEMSFlag = "-expect-extended-master-secret"
+
+ for _, with := range []bool{false, true} {
+ prefix := "No"
+ var flags []string
+ if with {
+ prefix = ""
+ flags = []string{expectEMSFlag}
+ }
+
+ for _, isClient := range []bool{false, true} {
+ suffix := "-Server"
+ testType := serverTest
+ if isClient {
+ suffix = "-Client"
+ testType = clientTest
+ }
+
+ for _, ver := range tlsVersions {
+ test := testCase{
+ testType: testType,
+ name: prefix + "ExtendedMasterSecret-" + ver.name + suffix,
+ config: Config{
+ MinVersion: ver.version,
+ MaxVersion: ver.version,
+ Bugs: ProtocolBugs{
+ NoExtendedMasterSecret: !with,
+ RequireExtendedMasterSecret: with,
+ },
+ },
+ flags: flags,
+ shouldFail: ver.version == VersionSSL30 && with,
+ }
+ if test.shouldFail {
+ test.expectedLocalError = "extended master secret required but not supported by peer"
+ }
+ testCases = append(testCases, test)
+ }
+ }
+ }
+
+ // When a session is resumed, it should still be aware that its master
+ // secret was generated via EMS and thus it's safe to use tls-unique.
+ testCases = append(testCases, testCase{
+ name: "ExtendedMasterSecret-Resume",
+ config: Config{
+ Bugs: ProtocolBugs{
+ RequireExtendedMasterSecret: true,
+ },
+ },
+ flags: []string{expectEMSFlag},
+ resumeSession: true,
+ })
+}
+
+// Adds tests that try to cover the range of the handshake state machine, under
+// various conditions. Some of these are redundant with other tests, but they
+// only cover the synchronous case.
+func addStateMachineCoverageTests(async, splitHandshake bool, protocol protocol) {
+ var suffix string
+ var flags []string
+ var maxHandshakeRecordLength int
+ if protocol == dtls {
+ suffix = "-DTLS"
+ }
+ if async {
+ suffix += "-Async"
+ flags = append(flags, "-async")
+ } else {
+ suffix += "-Sync"
+ }
+ if splitHandshake {
+ suffix += "-SplitHandshakeRecords"
+ maxHandshakeRecordLength = 1
+ }
+
+ // Basic handshake, with resumption. Client and server,
+ // session ID and session ticket.
+ testCases = append(testCases, testCase{
+ protocol: protocol,
+ name: "Basic-Client" + suffix,
+ config: Config{
+ Bugs: ProtocolBugs{
+ MaxHandshakeRecordLength: maxHandshakeRecordLength,
+ },
+ },
+ flags: flags,
+ resumeSession: true,
+ })
+ testCases = append(testCases, testCase{
+ protocol: protocol,
+ name: "Basic-Client-RenewTicket" + suffix,
+ config: Config{
+ Bugs: ProtocolBugs{
+ MaxHandshakeRecordLength: maxHandshakeRecordLength,
+ RenewTicketOnResume: true,
+ },
+ },
+ flags: flags,
+ resumeSession: true,
+ })
+ testCases = append(testCases, testCase{
+ protocol: protocol,
+ name: "Basic-Client-NoTicket" + suffix,
+ config: Config{
+ SessionTicketsDisabled: true,
+ Bugs: ProtocolBugs{
+ MaxHandshakeRecordLength: maxHandshakeRecordLength,
+ },
+ },
+ flags: flags,
+ resumeSession: true,
+ })
+ testCases = append(testCases, testCase{
+ protocol: protocol,
+ testType: serverTest,
+ name: "Basic-Server" + suffix,
+ config: Config{
+ Bugs: ProtocolBugs{
+ MaxHandshakeRecordLength: maxHandshakeRecordLength,
+ },
+ },
+ flags: flags,
+ resumeSession: true,
+ })
+ testCases = append(testCases, testCase{
+ protocol: protocol,
+ testType: serverTest,
+ name: "Basic-Server-NoTickets" + suffix,
+ config: Config{
+ SessionTicketsDisabled: true,
+ Bugs: ProtocolBugs{
+ MaxHandshakeRecordLength: maxHandshakeRecordLength,
+ },
+ },
+ flags: flags,
+ resumeSession: true,
+ })
+
+ // TLS client auth.
+ testCases = append(testCases, testCase{
+ protocol: protocol,
+ testType: clientTest,
+ name: "ClientAuth-Client" + suffix,
+ config: Config{
+ ClientAuth: RequireAnyClientCert,
+ Bugs: ProtocolBugs{
+ MaxHandshakeRecordLength: maxHandshakeRecordLength,
+ },
+ },
+ flags: append(flags,
+ "-cert-file", rsaCertificateFile,
+ "-key-file", rsaKeyFile),
+ })
+ testCases = append(testCases, testCase{
+ protocol: protocol,
+ testType: serverTest,
+ name: "ClientAuth-Server" + suffix,
+ config: Config{
+ Certificates: []Certificate{rsaCertificate},
+ },
+ flags: append(flags, "-require-any-client-certificate"),
+ })
+
+ // No session ticket support; server doesn't send NewSessionTicket.
+ testCases = append(testCases, testCase{
+ protocol: protocol,
+ name: "SessionTicketsDisabled-Client" + suffix,
+ config: Config{
+ SessionTicketsDisabled: true,
+ Bugs: ProtocolBugs{
+ MaxHandshakeRecordLength: maxHandshakeRecordLength,
+ },
+ },
+ flags: flags,
+ })
+ testCases = append(testCases, testCase{
+ protocol: protocol,
+ testType: serverTest,
+ name: "SessionTicketsDisabled-Server" + suffix,
+ config: Config{
+ SessionTicketsDisabled: true,
+ Bugs: ProtocolBugs{
+ MaxHandshakeRecordLength: maxHandshakeRecordLength,
+ },
+ },
+ flags: flags,
+ })
+
+ // Skip ServerKeyExchange in PSK key exchange if there's no
+ // identity hint.
+ testCases = append(testCases, testCase{
+ protocol: protocol,
+ name: "EmptyPSKHint-Client" + suffix,
+ config: Config{
+ CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
+ PreSharedKey: []byte("secret"),
+ Bugs: ProtocolBugs{
+ MaxHandshakeRecordLength: maxHandshakeRecordLength,
+ },
+ },
+ flags: append(flags, "-psk", "secret"),
+ })
+ testCases = append(testCases, testCase{
+ protocol: protocol,
+ testType: serverTest,
+ name: "EmptyPSKHint-Server" + suffix,
+ config: Config{
+ CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
+ PreSharedKey: []byte("secret"),
+ Bugs: ProtocolBugs{
+ MaxHandshakeRecordLength: maxHandshakeRecordLength,
+ },
+ },
+ flags: append(flags, "-psk", "secret"),
+ })
+
+ if protocol == tls {
+ // NPN on client and server; results in post-handshake message.
+ testCases = append(testCases, testCase{
+ protocol: protocol,
+ name: "NPN-Client" + suffix,
+ config: Config{
+ NextProtos: []string{"foo"},
+ Bugs: ProtocolBugs{
+ MaxHandshakeRecordLength: maxHandshakeRecordLength,
+ },
+ },
+ flags: append(flags, "-select-next-proto", "foo"),
+ expectedNextProto: "foo",
+ expectedNextProtoType: npn,
+ })
+ testCases = append(testCases, testCase{
+ protocol: protocol,
+ testType: serverTest,
+ name: "NPN-Server" + suffix,
+ config: Config{
+ NextProtos: []string{"bar"},
+ Bugs: ProtocolBugs{
+ MaxHandshakeRecordLength: maxHandshakeRecordLength,
+ },
+ },
+ flags: append(flags,
+ "-advertise-npn", "\x03foo\x03bar\x03baz",
+ "-expect-next-proto", "bar"),
+ expectedNextProto: "bar",
+ expectedNextProtoType: npn,
+ })
+
+ // Client does False Start and negotiates NPN.
+ testCases = append(testCases, testCase{
+ protocol: protocol,
+ name: "FalseStart" + suffix,
+ config: Config{
+ CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+ NextProtos: []string{"foo"},
+ Bugs: ProtocolBugs{
+ ExpectFalseStart: true,
+ MaxHandshakeRecordLength: maxHandshakeRecordLength,
+ },
+ },
+ flags: append(flags,
+ "-false-start",
+ "-select-next-proto", "foo"),
+ shimWritesFirst: true,
+ resumeSession: true,
+ })
+
+ // Client does False Start and negotiates ALPN.
+ testCases = append(testCases, testCase{
+ protocol: protocol,
+ name: "FalseStart-ALPN" + suffix,
+ config: Config{
+ CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+ NextProtos: []string{"foo"},
+ Bugs: ProtocolBugs{
+ ExpectFalseStart: true,
+ MaxHandshakeRecordLength: maxHandshakeRecordLength,
+ },
+ },
+ flags: append(flags,
+ "-false-start",
+ "-advertise-alpn", "\x03foo"),
+ shimWritesFirst: true,
+ resumeSession: true,
+ })
+
+ // False Start without session tickets.
+ testCases = append(testCases, testCase{
+ name: "FalseStart-SessionTicketsDisabled",
+ config: Config{
+ CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+ NextProtos: []string{"foo"},
+ SessionTicketsDisabled: true,
+ Bugs: ProtocolBugs{
+ ExpectFalseStart: true,
+ MaxHandshakeRecordLength: maxHandshakeRecordLength,
+ },
+ },
+ flags: append(flags,
+ "-false-start",
+ "-select-next-proto", "foo",
+ ),
+ shimWritesFirst: true,
+ })
+
+ // Server parses a V2ClientHello.
+ testCases = append(testCases, testCase{
+ protocol: protocol,
+ testType: serverTest,
+ name: "SendV2ClientHello" + suffix,
+ config: Config{
+ // Choose a cipher suite that does not involve
+ // elliptic curves, so no extensions are
+ // involved.
+ CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
+ Bugs: ProtocolBugs{
+ MaxHandshakeRecordLength: maxHandshakeRecordLength,
+ SendV2ClientHello: true,
+ },
+ },
+ flags: flags,
+ })
+
+ // Client sends a Channel ID.
+ testCases = append(testCases, testCase{
+ protocol: protocol,
+ name: "ChannelID-Client" + suffix,
+ config: Config{
+ RequestChannelID: true,
+ Bugs: ProtocolBugs{
+ MaxHandshakeRecordLength: maxHandshakeRecordLength,
+ },
+ },
+ flags: append(flags,
+ "-send-channel-id", channelIDKeyFile,
+ ),
+ resumeSession: true,
+ expectChannelID: true,
+ })
+
+ // Server accepts a Channel ID.
+ testCases = append(testCases, testCase{
+ protocol: protocol,
+ testType: serverTest,
+ name: "ChannelID-Server" + suffix,
+ config: Config{
+ ChannelID: channelIDKey,
+ Bugs: ProtocolBugs{
+ MaxHandshakeRecordLength: maxHandshakeRecordLength,
+ },
+ },
+ flags: append(flags,
+ "-expect-channel-id",
+ base64.StdEncoding.EncodeToString(channelIDBytes),
+ ),
+ resumeSession: true,
+ expectChannelID: true,
+ })
+ } else {
+ testCases = append(testCases, testCase{
+ protocol: protocol,
+ name: "SkipHelloVerifyRequest" + suffix,
+ config: Config{
+ Bugs: ProtocolBugs{
+ MaxHandshakeRecordLength: maxHandshakeRecordLength,
+ SkipHelloVerifyRequest: true,
+ },
+ },
+ flags: flags,
+ })
+
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ protocol: protocol,
+ name: "CookieExchange" + suffix,
+ config: Config{
+ Bugs: ProtocolBugs{
+ MaxHandshakeRecordLength: maxHandshakeRecordLength,
+ },
+ },
+ flags: append(flags, "-cookie-exchange"),
+ })
+ }
+}
+
+func addVersionNegotiationTests() {
+ for i, shimVers := range tlsVersions {
+ // Assemble flags to disable all newer versions on the shim.
+ var flags []string
+ for _, vers := range tlsVersions[i+1:] {
+ flags = append(flags, vers.flag)
+ }
+
+ for _, runnerVers := range tlsVersions {
+ protocols := []protocol{tls}
+ if runnerVers.hasDTLS && shimVers.hasDTLS {
+ protocols = append(protocols, dtls)
+ }
+ for _, protocol := range protocols {
+ expectedVersion := shimVers.version
+ if runnerVers.version < shimVers.version {
+ expectedVersion = runnerVers.version
+ }
+
+ suffix := shimVers.name + "-" + runnerVers.name
+ if protocol == dtls {
+ suffix += "-DTLS"
+ }
+
+ shimVersFlag := strconv.Itoa(int(versionToWire(shimVers.version, protocol == dtls)))
+
+ clientVers := shimVers.version
+ if clientVers > VersionTLS10 {
+ clientVers = VersionTLS10
+ }
+ testCases = append(testCases, testCase{
+ protocol: protocol,
+ testType: clientTest,
+ name: "VersionNegotiation-Client-" + suffix,
+ config: Config{
+ MaxVersion: runnerVers.version,
+ Bugs: ProtocolBugs{
+ ExpectInitialRecordVersion: clientVers,
+ },
+ },
+ flags: flags,
+ expectedVersion: expectedVersion,
+ })
+ testCases = append(testCases, testCase{
+ protocol: protocol,
+ testType: clientTest,
+ name: "VersionNegotiation-Client2-" + suffix,
+ config: Config{
+ MaxVersion: runnerVers.version,
+ Bugs: ProtocolBugs{
+ ExpectInitialRecordVersion: clientVers,
+ },
+ },
+ flags: []string{"-max-version", shimVersFlag},
+ expectedVersion: expectedVersion,
+ })
+
+ testCases = append(testCases, testCase{
+ protocol: protocol,
+ testType: serverTest,
+ name: "VersionNegotiation-Server-" + suffix,
+ config: Config{
+ MaxVersion: runnerVers.version,
+ Bugs: ProtocolBugs{
+ ExpectInitialRecordVersion: expectedVersion,
+ },
+ },
+ flags: flags,
+ expectedVersion: expectedVersion,
+ })
+ testCases = append(testCases, testCase{
+ protocol: protocol,
+ testType: serverTest,
+ name: "VersionNegotiation-Server2-" + suffix,
+ config: Config{
+ MaxVersion: runnerVers.version,
+ Bugs: ProtocolBugs{
+ ExpectInitialRecordVersion: expectedVersion,
+ },
+ },
+ flags: []string{"-max-version", shimVersFlag},
+ expectedVersion: expectedVersion,
+ })
+ }
+ }
+ }
+}
+
+func addMinimumVersionTests() {
+ for i, shimVers := range tlsVersions {
+ // Assemble flags to disable all older versions on the shim.
+ var flags []string
+ for _, vers := range tlsVersions[:i] {
+ flags = append(flags, vers.flag)
+ }
+
+ for _, runnerVers := range tlsVersions {
+ protocols := []protocol{tls}
+ if runnerVers.hasDTLS && shimVers.hasDTLS {
+ protocols = append(protocols, dtls)
+ }
+ for _, protocol := range protocols {
+ suffix := shimVers.name + "-" + runnerVers.name
+ if protocol == dtls {
+ suffix += "-DTLS"
+ }
+ shimVersFlag := strconv.Itoa(int(versionToWire(shimVers.version, protocol == dtls)))
+
+ var expectedVersion uint16
+ var shouldFail bool
+ var expectedError string
+ var expectedLocalError string
+ if runnerVers.version >= shimVers.version {
+ expectedVersion = runnerVers.version
+ } else {
+ shouldFail = true
+ expectedError = ":UNSUPPORTED_PROTOCOL:"
+ if runnerVers.version > VersionSSL30 {
+ expectedLocalError = "remote error: protocol version not supported"
+ } else {
+ expectedLocalError = "remote error: handshake failure"
+ }
+ }
+
+ testCases = append(testCases, testCase{
+ protocol: protocol,
+ testType: clientTest,
+ name: "MinimumVersion-Client-" + suffix,
+ config: Config{
+ MaxVersion: runnerVers.version,
+ },
+ flags: flags,
+ expectedVersion: expectedVersion,
+ shouldFail: shouldFail,
+ expectedError: expectedError,
+ expectedLocalError: expectedLocalError,
+ })
+ testCases = append(testCases, testCase{
+ protocol: protocol,
+ testType: clientTest,
+ name: "MinimumVersion-Client2-" + suffix,
+ config: Config{
+ MaxVersion: runnerVers.version,
+ },
+ flags: []string{"-min-version", shimVersFlag},
+ expectedVersion: expectedVersion,
+ shouldFail: shouldFail,
+ expectedError: expectedError,
+ expectedLocalError: expectedLocalError,
+ })
+
+ testCases = append(testCases, testCase{
+ protocol: protocol,
+ testType: serverTest,
+ name: "MinimumVersion-Server-" + suffix,
+ config: Config{
+ MaxVersion: runnerVers.version,
+ },
+ flags: flags,
+ expectedVersion: expectedVersion,
+ shouldFail: shouldFail,
+ expectedError: expectedError,
+ expectedLocalError: expectedLocalError,
+ })
+ testCases = append(testCases, testCase{
+ protocol: protocol,
+ testType: serverTest,
+ name: "MinimumVersion-Server2-" + suffix,
+ config: Config{
+ MaxVersion: runnerVers.version,
+ },
+ flags: []string{"-min-version", shimVersFlag},
+ expectedVersion: expectedVersion,
+ shouldFail: shouldFail,
+ expectedError: expectedError,
+ expectedLocalError: expectedLocalError,
+ })
+ }
+ }
+ }
+}
+
+func addD5BugTests() {
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "D5Bug-NoQuirk-Reject",
+ config: Config{
+ CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
+ Bugs: ProtocolBugs{
+ SSL3RSAKeyExchange: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG:",
+ })
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "D5Bug-Quirk-Normal",
+ config: Config{
+ CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
+ },
+ flags: []string{"-tls-d5-bug"},
+ })
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "D5Bug-Quirk-Bug",
+ config: Config{
+ CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
+ Bugs: ProtocolBugs{
+ SSL3RSAKeyExchange: true,
+ },
+ },
+ flags: []string{"-tls-d5-bug"},
+ })
+}
+
+func addExtensionTests() {
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "DuplicateExtensionClient",
+ config: Config{
+ Bugs: ProtocolBugs{
+ DuplicateExtension: true,
+ },
+ },
+ shouldFail: true,
+ expectedLocalError: "remote error: error decoding message",
+ })
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "DuplicateExtensionServer",
+ config: Config{
+ Bugs: ProtocolBugs{
+ DuplicateExtension: true,
+ },
+ },
+ shouldFail: true,
+ expectedLocalError: "remote error: error decoding message",
+ })
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "ServerNameExtensionClient",
+ config: Config{
+ Bugs: ProtocolBugs{
+ ExpectServerName: "example.com",
+ },
+ },
+ flags: []string{"-host-name", "example.com"},
+ })
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "ServerNameExtensionClient",
+ config: Config{
+ Bugs: ProtocolBugs{
+ ExpectServerName: "mismatch.com",
+ },
+ },
+ flags: []string{"-host-name", "example.com"},
+ shouldFail: true,
+ expectedLocalError: "tls: unexpected server name",
+ })
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "ServerNameExtensionClient",
+ config: Config{
+ Bugs: ProtocolBugs{
+ ExpectServerName: "missing.com",
+ },
+ },
+ shouldFail: true,
+ expectedLocalError: "tls: unexpected server name",
+ })
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "ServerNameExtensionServer",
+ config: Config{
+ ServerName: "example.com",
+ },
+ flags: []string{"-expect-server-name", "example.com"},
+ resumeSession: true,
+ })
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "ALPNClient",
+ config: Config{
+ NextProtos: []string{"foo"},
+ },
+ flags: []string{
+ "-advertise-alpn", "\x03foo\x03bar\x03baz",
+ "-expect-alpn", "foo",
+ },
+ expectedNextProto: "foo",
+ expectedNextProtoType: alpn,
+ resumeSession: true,
+ })
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "ALPNServer",
+ config: Config{
+ NextProtos: []string{"foo", "bar", "baz"},
+ },
+ flags: []string{
+ "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
+ "-select-alpn", "foo",
+ },
+ expectedNextProto: "foo",
+ expectedNextProtoType: alpn,
+ resumeSession: true,
+ })
+ // Test that the server prefers ALPN over NPN.
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "ALPNServer-Preferred",
+ config: Config{
+ NextProtos: []string{"foo", "bar", "baz"},
+ },
+ flags: []string{
+ "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
+ "-select-alpn", "foo",
+ "-advertise-npn", "\x03foo\x03bar\x03baz",
+ },
+ expectedNextProto: "foo",
+ expectedNextProtoType: alpn,
+ resumeSession: true,
+ })
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "ALPNServer-Preferred-Swapped",
+ config: Config{
+ NextProtos: []string{"foo", "bar", "baz"},
+ Bugs: ProtocolBugs{
+ SwapNPNAndALPN: true,
+ },
+ },
+ flags: []string{
+ "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
+ "-select-alpn", "foo",
+ "-advertise-npn", "\x03foo\x03bar\x03baz",
+ },
+ expectedNextProto: "foo",
+ expectedNextProtoType: alpn,
+ resumeSession: true,
+ })
+ // Resume with a corrupt ticket.
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "CorruptTicket",
+ config: Config{
+ Bugs: ProtocolBugs{
+ CorruptTicket: true,
+ },
+ },
+ resumeSession: true,
+ flags: []string{"-expect-session-miss"},
+ })
+ // Resume with an oversized session id.
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "OversizedSessionId",
+ config: Config{
+ Bugs: ProtocolBugs{
+ OversizedSessionId: true,
+ },
+ },
+ resumeSession: true,
+ shouldFail: true,
+ expectedError: ":DECODE_ERROR:",
+ })
+ // Basic DTLS-SRTP tests. Include fake profiles to ensure they
+ // are ignored.
+ testCases = append(testCases, testCase{
+ protocol: dtls,
+ name: "SRTP-Client",
+ config: Config{
+ SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
+ },
+ flags: []string{
+ "-srtp-profiles",
+ "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
+ },
+ expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
+ })
+ testCases = append(testCases, testCase{
+ protocol: dtls,
+ testType: serverTest,
+ name: "SRTP-Server",
+ config: Config{
+ SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
+ },
+ flags: []string{
+ "-srtp-profiles",
+ "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
+ },
+ expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
+ })
+ // Test that the MKI is ignored.
+ testCases = append(testCases, testCase{
+ protocol: dtls,
+ testType: serverTest,
+ name: "SRTP-Server-IgnoreMKI",
+ config: Config{
+ SRTPProtectionProfiles: []uint16{SRTP_AES128_CM_HMAC_SHA1_80},
+ Bugs: ProtocolBugs{
+ SRTPMasterKeyIdentifer: "bogus",
+ },
+ },
+ flags: []string{
+ "-srtp-profiles",
+ "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
+ },
+ expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
+ })
+ // Test that SRTP isn't negotiated on the server if there were
+ // no matching profiles.
+ testCases = append(testCases, testCase{
+ protocol: dtls,
+ testType: serverTest,
+ name: "SRTP-Server-NoMatch",
+ config: Config{
+ SRTPProtectionProfiles: []uint16{100, 101, 102},
+ },
+ flags: []string{
+ "-srtp-profiles",
+ "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
+ },
+ expectedSRTPProtectionProfile: 0,
+ })
+ // Test that the server returning an invalid SRTP profile is
+ // flagged as an error by the client.
+ testCases = append(testCases, testCase{
+ protocol: dtls,
+ name: "SRTP-Client-NoMatch",
+ config: Config{
+ Bugs: ProtocolBugs{
+ SendSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_32,
+ },
+ },
+ flags: []string{
+ "-srtp-profiles",
+ "SRTP_AES128_CM_SHA1_80",
+ },
+ shouldFail: true,
+ expectedError: ":BAD_SRTP_PROTECTION_PROFILE_LIST:",
+ })
+ // Test OCSP stapling and SCT list.
+ testCases = append(testCases, testCase{
+ name: "OCSPStapling",
+ flags: []string{
+ "-enable-ocsp-stapling",
+ "-expect-ocsp-response",
+ base64.StdEncoding.EncodeToString(testOCSPResponse),
+ },
+ })
+ testCases = append(testCases, testCase{
+ name: "SignedCertificateTimestampList",
+ flags: []string{
+ "-enable-signed-cert-timestamps",
+ "-expect-signed-cert-timestamps",
+ base64.StdEncoding.EncodeToString(testSCTList),
+ },
+ })
+}
+
+func addResumptionVersionTests() {
+ for _, sessionVers := range tlsVersions {
+ for _, resumeVers := range tlsVersions {
+ protocols := []protocol{tls}
+ if sessionVers.hasDTLS && resumeVers.hasDTLS {
+ protocols = append(protocols, dtls)
+ }
+ for _, protocol := range protocols {
+ suffix := "-" + sessionVers.name + "-" + resumeVers.name
+ if protocol == dtls {
+ suffix += "-DTLS"
+ }
+
+ testCases = append(testCases, testCase{
+ protocol: protocol,
+ name: "Resume-Client" + suffix,
+ resumeSession: true,
+ config: Config{
+ MaxVersion: sessionVers.version,
+ CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
+ Bugs: ProtocolBugs{
+ AllowSessionVersionMismatch: true,
+ },
+ },
+ expectedVersion: sessionVers.version,
+ resumeConfig: &Config{
+ MaxVersion: resumeVers.version,
+ CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
+ Bugs: ProtocolBugs{
+ AllowSessionVersionMismatch: true,
+ },
+ },
+ expectedResumeVersion: resumeVers.version,
+ })
+
+ testCases = append(testCases, testCase{
+ protocol: protocol,
+ name: "Resume-Client-NoResume" + suffix,
+ flags: []string{"-expect-session-miss"},
+ resumeSession: true,
+ config: Config{
+ MaxVersion: sessionVers.version,
+ CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
+ },
+ expectedVersion: sessionVers.version,
+ resumeConfig: &Config{
+ MaxVersion: resumeVers.version,
+ CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
+ },
+ newSessionsOnResume: true,
+ expectedResumeVersion: resumeVers.version,
+ })
+
+ var flags []string
+ if sessionVers.version != resumeVers.version {
+ flags = append(flags, "-expect-session-miss")
+ }
+ testCases = append(testCases, testCase{
+ protocol: protocol,
+ testType: serverTest,
+ name: "Resume-Server" + suffix,
+ flags: flags,
+ resumeSession: true,
+ config: Config{
+ MaxVersion: sessionVers.version,
+ CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
+ },
+ expectedVersion: sessionVers.version,
+ resumeConfig: &Config{
+ MaxVersion: resumeVers.version,
+ CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
+ },
+ expectedResumeVersion: resumeVers.version,
+ })
+ }
+ }
+ }
+}
+
+func addRenegotiationTests() {
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "Renegotiate-Server",
+ flags: []string{"-renegotiate"},
+ shimWritesFirst: true,
+ })
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "Renegotiate-Server-EmptyExt",
+ config: Config{
+ Bugs: ProtocolBugs{
+ EmptyRenegotiationInfo: true,
+ },
+ },
+ flags: []string{"-renegotiate"},
+ shimWritesFirst: true,
+ shouldFail: true,
+ expectedError: ":RENEGOTIATION_MISMATCH:",
+ })
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "Renegotiate-Server-BadExt",
+ config: Config{
+ Bugs: ProtocolBugs{
+ BadRenegotiationInfo: true,
+ },
+ },
+ flags: []string{"-renegotiate"},
+ shimWritesFirst: true,
+ shouldFail: true,
+ expectedError: ":RENEGOTIATION_MISMATCH:",
+ })
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "Renegotiate-Server-ClientInitiated",
+ renegotiate: true,
+ })
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "Renegotiate-Server-ClientInitiated-NoExt",
+ renegotiate: true,
+ config: Config{
+ Bugs: ProtocolBugs{
+ NoRenegotiationInfo: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":UNSAFE_LEGACY_RENEGOTIATION_DISABLED:",
+ })
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "Renegotiate-Server-ClientInitiated-NoExt-Allowed",
+ renegotiate: true,
+ config: Config{
+ Bugs: ProtocolBugs{
+ NoRenegotiationInfo: true,
+ },
+ },
+ flags: []string{"-allow-unsafe-legacy-renegotiation"},
+ })
+ // TODO(agl): test the renegotiation info SCSV.
+ testCases = append(testCases, testCase{
+ name: "Renegotiate-Client",
+ renegotiate: true,
+ })
+ testCases = append(testCases, testCase{
+ name: "Renegotiate-Client-EmptyExt",
+ renegotiate: true,
+ config: Config{
+ Bugs: ProtocolBugs{
+ EmptyRenegotiationInfo: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":RENEGOTIATION_MISMATCH:",
+ })
+ testCases = append(testCases, testCase{
+ name: "Renegotiate-Client-BadExt",
+ renegotiate: true,
+ config: Config{
+ Bugs: ProtocolBugs{
+ BadRenegotiationInfo: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":RENEGOTIATION_MISMATCH:",
+ })
+ testCases = append(testCases, testCase{
+ name: "Renegotiate-Client-SwitchCiphers",
+ renegotiate: true,
+ config: Config{
+ CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
+ },
+ renegotiateCiphers: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+ })
+ testCases = append(testCases, testCase{
+ name: "Renegotiate-Client-SwitchCiphers2",
+ renegotiate: true,
+ config: Config{
+ CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+ },
+ renegotiateCiphers: []uint16{TLS_RSA_WITH_RC4_128_SHA},
+ })
+ testCases = append(testCases, testCase{
+ name: "Renegotiate-SameClientVersion",
+ renegotiate: true,
+ config: Config{
+ MaxVersion: VersionTLS10,
+ Bugs: ProtocolBugs{
+ RequireSameRenegoClientVersion: true,
+ },
+ },
+ })
+}
+
+func addDTLSReplayTests() {
+ // Test that sequence number replays are detected.
+ testCases = append(testCases, testCase{
+ protocol: dtls,
+ name: "DTLS-Replay",
+ replayWrites: true,
+ })
+
+ // Test the outgoing sequence number skipping by values larger
+ // than the retransmit window.
+ testCases = append(testCases, testCase{
+ protocol: dtls,
+ name: "DTLS-Replay-LargeGaps",
+ config: Config{
+ Bugs: ProtocolBugs{
+ SequenceNumberIncrement: 127,
+ },
+ },
+ replayWrites: true,
+ })
+}
+
+func addFastRadioPaddingTests() {
+ testCases = append(testCases, testCase{
+ protocol: tls,
+ name: "FastRadio-Padding",
+ config: Config{
+ Bugs: ProtocolBugs{
+ RequireFastradioPadding: true,
+ },
+ },
+ flags: []string{"-fastradio-padding"},
+ })
+ testCases = append(testCases, testCase{
+ protocol: dtls,
+ name: "FastRadio-Padding",
+ config: Config{
+ Bugs: ProtocolBugs{
+ RequireFastradioPadding: true,
+ },
+ },
+ flags: []string{"-fastradio-padding"},
+ })
+}
+
+var testHashes = []struct {
+ name string
+ id uint8
+}{
+ {"SHA1", hashSHA1},
+ {"SHA224", hashSHA224},
+ {"SHA256", hashSHA256},
+ {"SHA384", hashSHA384},
+ {"SHA512", hashSHA512},
+}
+
+func addSigningHashTests() {
+ // Make sure each hash works. Include some fake hashes in the list and
+ // ensure they're ignored.
+ for _, hash := range testHashes {
+ testCases = append(testCases, testCase{
+ name: "SigningHash-ClientAuth-" + hash.name,
+ config: Config{
+ ClientAuth: RequireAnyClientCert,
+ SignatureAndHashes: []signatureAndHash{
+ {signatureRSA, 42},
+ {signatureRSA, hash.id},
+ {signatureRSA, 255},
+ },
+ },
+ flags: []string{
+ "-cert-file", rsaCertificateFile,
+ "-key-file", rsaKeyFile,
+ },
+ })
+
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "SigningHash-ServerKeyExchange-Sign-" + hash.name,
+ config: Config{
+ CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+ SignatureAndHashes: []signatureAndHash{
+ {signatureRSA, 42},
+ {signatureRSA, hash.id},
+ {signatureRSA, 255},
+ },
+ },
+ })
+ }
+
+ // Test that hash resolution takes the signature type into account.
+ testCases = append(testCases, testCase{
+ name: "SigningHash-ClientAuth-SignatureType",
+ config: Config{
+ ClientAuth: RequireAnyClientCert,
+ SignatureAndHashes: []signatureAndHash{
+ {signatureECDSA, hashSHA512},
+ {signatureRSA, hashSHA384},
+ {signatureECDSA, hashSHA1},
+ },
+ },
+ flags: []string{
+ "-cert-file", rsaCertificateFile,
+ "-key-file", rsaKeyFile,
+ },
+ })
+
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "SigningHash-ServerKeyExchange-SignatureType",
+ config: Config{
+ CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+ SignatureAndHashes: []signatureAndHash{
+ {signatureECDSA, hashSHA512},
+ {signatureRSA, hashSHA384},
+ {signatureECDSA, hashSHA1},
+ },
+ },
+ })
+
+ // Test that, if the list is missing, the peer falls back to SHA-1.
+ testCases = append(testCases, testCase{
+ name: "SigningHash-ClientAuth-Fallback",
+ config: Config{
+ ClientAuth: RequireAnyClientCert,
+ SignatureAndHashes: []signatureAndHash{
+ {signatureRSA, hashSHA1},
+ },
+ Bugs: ProtocolBugs{
+ NoSignatureAndHashes: true,
+ },
+ },
+ flags: []string{
+ "-cert-file", rsaCertificateFile,
+ "-key-file", rsaKeyFile,
+ },
+ })
+
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "SigningHash-ServerKeyExchange-Fallback",
+ config: Config{
+ CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+ SignatureAndHashes: []signatureAndHash{
+ {signatureRSA, hashSHA1},
+ },
+ Bugs: ProtocolBugs{
+ NoSignatureAndHashes: true,
+ },
+ },
+ })
+}
+
+func worker(statusChan chan statusMsg, c chan *testCase, buildDir string, wg *sync.WaitGroup) {
+ defer wg.Done()
+
+ for test := range c {
+ var err error
+
+ if *mallocTest < 0 {
+ statusChan <- statusMsg{test: test, started: true}
+ err = runTest(test, buildDir, -1)
+ } else {
+ for mallocNumToFail := int64(*mallocTest); ; mallocNumToFail++ {
+ statusChan <- statusMsg{test: test, started: true}
+ if err = runTest(test, buildDir, mallocNumToFail); err != errMoreMallocs {
+ if err != nil {
+ fmt.Printf("\n\nmalloc test failed at %d: %s\n", mallocNumToFail, err)
+ }
+ break
+ }
+ }
+ }
+ statusChan <- statusMsg{test: test, err: err}
+ }
+}
+
+type statusMsg struct {
+ test *testCase
+ started bool
+ err error
+}
+
+func statusPrinter(doneChan chan struct{}, statusChan chan statusMsg, total int) {
+ var started, done, failed, lineLen int
+ defer close(doneChan)
+
+ for msg := range statusChan {
+ if msg.started {
+ started++
+ } else {
+ done++
+ }
+
+ fmt.Printf("\x1b[%dD\x1b[K", lineLen)
+
+ if msg.err != nil {
+ fmt.Printf("FAILED (%s)\n%s\n", msg.test.name, msg.err)
+ failed++
+ }
+ line := fmt.Sprintf("%d/%d/%d/%d", failed, done, started, total)
+ lineLen = len(line)
+ os.Stdout.WriteString(line)
+ }
+}
+
+func main() {
+ var flagTest *string = flag.String("test", "", "The name of a test to run, or empty to run all tests")
+ var flagNumWorkers *int = flag.Int("num-workers", runtime.NumCPU(), "The number of workers to run in parallel.")
+ var flagBuildDir *string = flag.String("build-dir", "../../../build", "The build directory to run the shim from.")
+
+ flag.Parse()
+
+ addCipherSuiteTests()
+ addBadECDSASignatureTests()
+ addCBCPaddingTests()
+ addCBCSplittingTests()
+ addClientAuthTests()
+ addVersionNegotiationTests()
+ addMinimumVersionTests()
+ addD5BugTests()
+ addExtensionTests()
+ addResumptionVersionTests()
+ addExtendedMasterSecretTests()
+ addRenegotiationTests()
+ addDTLSReplayTests()
+ addSigningHashTests()
+ addFastRadioPaddingTests()
+ for _, async := range []bool{false, true} {
+ for _, splitHandshake := range []bool{false, true} {
+ for _, protocol := range []protocol{tls, dtls} {
+ addStateMachineCoverageTests(async, splitHandshake, protocol)
+ }
+ }
+ }
+
+ var wg sync.WaitGroup
+
+ numWorkers := *flagNumWorkers
+
+ statusChan := make(chan statusMsg, numWorkers)
+ testChan := make(chan *testCase, numWorkers)
+ doneChan := make(chan struct{})
+
+ go statusPrinter(doneChan, statusChan, len(testCases))
+
+ for i := 0; i < numWorkers; i++ {
+ wg.Add(1)
+ go worker(statusChan, testChan, *flagBuildDir, &wg)
+ }
+
+ for i := range testCases {
+ if len(*flagTest) == 0 || *flagTest == testCases[i].name {
+ testChan <- &testCases[i]
+ }
+ }
+
+ close(testChan)
+ wg.Wait()
+ close(statusChan)
+ <-doneChan
+
+ fmt.Printf("\n")
+}
diff --git a/src/ssl/test/runner/ticket.go b/src/ssl/test/runner/ticket.go
new file mode 100644
index 0000000..8355822
--- /dev/null
+++ b/src/ssl/test/runner/ticket.go
@@ -0,0 +1,221 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "bytes"
+ "crypto/aes"
+ "crypto/cipher"
+ "crypto/hmac"
+ "crypto/sha256"
+ "crypto/subtle"
+ "errors"
+ "io"
+)
+
+// sessionState contains the information that is serialized into a session
+// ticket in order to later resume a connection.
+type sessionState struct {
+ vers uint16
+ cipherSuite uint16
+ masterSecret []byte
+ handshakeHash []byte
+ certificates [][]byte
+ extendedMasterSecret bool
+}
+
+func (s *sessionState) equal(i interface{}) bool {
+ s1, ok := i.(*sessionState)
+ if !ok {
+ return false
+ }
+
+ if s.vers != s1.vers ||
+ s.cipherSuite != s1.cipherSuite ||
+ !bytes.Equal(s.masterSecret, s1.masterSecret) ||
+ !bytes.Equal(s.handshakeHash, s1.handshakeHash) ||
+ s.extendedMasterSecret != s1.extendedMasterSecret {
+ return false
+ }
+
+ if len(s.certificates) != len(s1.certificates) {
+ return false
+ }
+
+ for i := range s.certificates {
+ if !bytes.Equal(s.certificates[i], s1.certificates[i]) {
+ return false
+ }
+ }
+
+ return true
+}
+
+func (s *sessionState) marshal() []byte {
+ length := 2 + 2 + 2 + len(s.masterSecret) + 2 + len(s.handshakeHash) + 2
+ for _, cert := range s.certificates {
+ length += 4 + len(cert)
+ }
+ length++
+
+ ret := make([]byte, length)
+ x := ret
+ x[0] = byte(s.vers >> 8)
+ x[1] = byte(s.vers)
+ x[2] = byte(s.cipherSuite >> 8)
+ x[3] = byte(s.cipherSuite)
+ x[4] = byte(len(s.masterSecret) >> 8)
+ x[5] = byte(len(s.masterSecret))
+ x = x[6:]
+ copy(x, s.masterSecret)
+ x = x[len(s.masterSecret):]
+
+ x[0] = byte(len(s.handshakeHash) >> 8)
+ x[1] = byte(len(s.handshakeHash))
+ x = x[2:]
+ copy(x, s.handshakeHash)
+ x = x[len(s.handshakeHash):]
+
+ x[0] = byte(len(s.certificates) >> 8)
+ x[1] = byte(len(s.certificates))
+ x = x[2:]
+
+ for _, cert := range s.certificates {
+ x[0] = byte(len(cert) >> 24)
+ x[1] = byte(len(cert) >> 16)
+ x[2] = byte(len(cert) >> 8)
+ x[3] = byte(len(cert))
+ copy(x[4:], cert)
+ x = x[4+len(cert):]
+ }
+
+ if s.extendedMasterSecret {
+ x[0] = 1
+ }
+ x = x[1:]
+
+ return ret
+}
+
+func (s *sessionState) unmarshal(data []byte) bool {
+ if len(data) < 8 {
+ return false
+ }
+
+ s.vers = uint16(data[0])<<8 | uint16(data[1])
+ s.cipherSuite = uint16(data[2])<<8 | uint16(data[3])
+ masterSecretLen := int(data[4])<<8 | int(data[5])
+ data = data[6:]
+ if len(data) < masterSecretLen {
+ return false
+ }
+
+ s.masterSecret = data[:masterSecretLen]
+ data = data[masterSecretLen:]
+
+ if len(data) < 2 {
+ return false
+ }
+
+ handshakeHashLen := int(data[0])<<8 | int(data[1])
+ data = data[2:]
+ if len(data) < handshakeHashLen {
+ return false
+ }
+
+ s.handshakeHash = data[:handshakeHashLen]
+ data = data[handshakeHashLen:]
+
+ if len(data) < 2 {
+ return false
+ }
+
+ numCerts := int(data[0])<<8 | int(data[1])
+ data = data[2:]
+
+ s.certificates = make([][]byte, numCerts)
+ for i := range s.certificates {
+ if len(data) < 4 {
+ return false
+ }
+ certLen := int(data[0])<<24 | int(data[1])<<16 | int(data[2])<<8 | int(data[3])
+ data = data[4:]
+ if certLen < 0 {
+ return false
+ }
+ if len(data) < certLen {
+ return false
+ }
+ s.certificates[i] = data[:certLen]
+ data = data[certLen:]
+ }
+
+ if len(data) < 1 {
+ return false
+ }
+
+ s.extendedMasterSecret = false
+ if data[0] == 1 {
+ s.extendedMasterSecret = true
+ }
+ data = data[1:]
+
+ if len(data) > 0 {
+ return false
+ }
+
+ return true
+}
+
+func (c *Conn) encryptTicket(state *sessionState) ([]byte, error) {
+ serialized := state.marshal()
+ encrypted := make([]byte, aes.BlockSize+len(serialized)+sha256.Size)
+ iv := encrypted[:aes.BlockSize]
+ macBytes := encrypted[len(encrypted)-sha256.Size:]
+
+ if _, err := io.ReadFull(c.config.rand(), iv); err != nil {
+ return nil, err
+ }
+ block, err := aes.NewCipher(c.config.SessionTicketKey[:16])
+ if err != nil {
+ return nil, errors.New("tls: failed to create cipher while encrypting ticket: " + err.Error())
+ }
+ cipher.NewCTR(block, iv).XORKeyStream(encrypted[aes.BlockSize:], serialized)
+
+ mac := hmac.New(sha256.New, c.config.SessionTicketKey[16:32])
+ mac.Write(encrypted[:len(encrypted)-sha256.Size])
+ mac.Sum(macBytes[:0])
+
+ return encrypted, nil
+}
+
+func (c *Conn) decryptTicket(encrypted []byte) (*sessionState, bool) {
+ if len(encrypted) < aes.BlockSize+sha256.Size {
+ return nil, false
+ }
+
+ iv := encrypted[:aes.BlockSize]
+ macBytes := encrypted[len(encrypted)-sha256.Size:]
+
+ mac := hmac.New(sha256.New, c.config.SessionTicketKey[16:32])
+ mac.Write(encrypted[:len(encrypted)-sha256.Size])
+ expected := mac.Sum(nil)
+
+ if subtle.ConstantTimeCompare(macBytes, expected) != 1 {
+ return nil, false
+ }
+
+ block, err := aes.NewCipher(c.config.SessionTicketKey[:16])
+ if err != nil {
+ return nil, false
+ }
+ ciphertext := encrypted[aes.BlockSize : len(encrypted)-sha256.Size]
+ plaintext := make([]byte, len(ciphertext))
+ cipher.NewCTR(block, iv).XORKeyStream(plaintext, ciphertext)
+
+ state := new(sessionState)
+ ok := state.unmarshal(plaintext)
+ return state, ok
+}
diff --git a/src/ssl/test/runner/tls.go b/src/ssl/test/runner/tls.go
new file mode 100644
index 0000000..6b637c8
--- /dev/null
+++ b/src/ssl/test/runner/tls.go
@@ -0,0 +1,279 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package tls partially implements TLS 1.2, as specified in RFC 5246.
+package main
+
+import (
+ "crypto"
+ "crypto/ecdsa"
+ "crypto/rsa"
+ "crypto/x509"
+ "encoding/pem"
+ "errors"
+ "io/ioutil"
+ "net"
+ "strings"
+ "time"
+)
+
+// Server returns a new TLS server side connection
+// using conn as the underlying transport.
+// The configuration config must be non-nil and must have
+// at least one certificate.
+func Server(conn net.Conn, config *Config) *Conn {
+ c := &Conn{conn: conn, config: config}
+ c.init()
+ return c
+}
+
+// Client returns a new TLS client side connection
+// using conn as the underlying transport.
+// The config cannot be nil: users must set either ServerHostname or
+// InsecureSkipVerify in the config.
+func Client(conn net.Conn, config *Config) *Conn {
+ c := &Conn{conn: conn, config: config, isClient: true}
+ c.init()
+ return c
+}
+
+// A listener implements a network listener (net.Listener) for TLS connections.
+type listener struct {
+ net.Listener
+ config *Config
+}
+
+// Accept waits for and returns the next incoming TLS connection.
+// The returned connection c is a *tls.Conn.
+func (l *listener) Accept() (c net.Conn, err error) {
+ c, err = l.Listener.Accept()
+ if err != nil {
+ return
+ }
+ c = Server(c, l.config)
+ return
+}
+
+// NewListener creates a Listener which accepts connections from an inner
+// Listener and wraps each connection with Server.
+// The configuration config must be non-nil and must have
+// at least one certificate.
+func NewListener(inner net.Listener, config *Config) net.Listener {
+ l := new(listener)
+ l.Listener = inner
+ l.config = config
+ return l
+}
+
+// Listen creates a TLS listener accepting connections on the
+// given network address using net.Listen.
+// The configuration config must be non-nil and must have
+// at least one certificate.
+func Listen(network, laddr string, config *Config) (net.Listener, error) {
+ if config == nil || len(config.Certificates) == 0 {
+ return nil, errors.New("tls.Listen: no certificates in configuration")
+ }
+ l, err := net.Listen(network, laddr)
+ if err != nil {
+ return nil, err
+ }
+ return NewListener(l, config), nil
+}
+
+type timeoutError struct{}
+
+func (timeoutError) Error() string { return "tls: DialWithDialer timed out" }
+func (timeoutError) Timeout() bool { return true }
+func (timeoutError) Temporary() bool { return true }
+
+// DialWithDialer connects to the given network address using dialer.Dial and
+// then initiates a TLS handshake, returning the resulting TLS connection. Any
+// timeout or deadline given in the dialer apply to connection and TLS
+// handshake as a whole.
+//
+// DialWithDialer interprets a nil configuration as equivalent to the zero
+// configuration; see the documentation of Config for the defaults.
+func DialWithDialer(dialer *net.Dialer, network, addr string, config *Config) (*Conn, error) {
+ // We want the Timeout and Deadline values from dialer to cover the
+ // whole process: TCP connection and TLS handshake. This means that we
+ // also need to start our own timers now.
+ timeout := dialer.Timeout
+
+ if !dialer.Deadline.IsZero() {
+ deadlineTimeout := dialer.Deadline.Sub(time.Now())
+ if timeout == 0 || deadlineTimeout < timeout {
+ timeout = deadlineTimeout
+ }
+ }
+
+ var errChannel chan error
+
+ if timeout != 0 {
+ errChannel = make(chan error, 2)
+ time.AfterFunc(timeout, func() {
+ errChannel <- timeoutError{}
+ })
+ }
+
+ rawConn, err := dialer.Dial(network, addr)
+ if err != nil {
+ return nil, err
+ }
+
+ colonPos := strings.LastIndex(addr, ":")
+ if colonPos == -1 {
+ colonPos = len(addr)
+ }
+ hostname := addr[:colonPos]
+
+ if config == nil {
+ config = defaultConfig()
+ }
+ // If no ServerName is set, infer the ServerName
+ // from the hostname we're connecting to.
+ if config.ServerName == "" {
+ // Make a copy to avoid polluting argument or default.
+ c := *config
+ c.ServerName = hostname
+ config = &c
+ }
+
+ conn := Client(rawConn, config)
+
+ if timeout == 0 {
+ err = conn.Handshake()
+ } else {
+ go func() {
+ errChannel <- conn.Handshake()
+ }()
+
+ err = <-errChannel
+ }
+
+ if err != nil {
+ rawConn.Close()
+ return nil, err
+ }
+
+ return conn, nil
+}
+
+// Dial connects to the given network address using net.Dial
+// and then initiates a TLS handshake, returning the resulting
+// TLS connection.
+// Dial interprets a nil configuration as equivalent to
+// the zero configuration; see the documentation of Config
+// for the defaults.
+func Dial(network, addr string, config *Config) (*Conn, error) {
+ return DialWithDialer(new(net.Dialer), network, addr, config)
+}
+
+// LoadX509KeyPair reads and parses a public/private key pair from a pair of
+// files. The files must contain PEM encoded data.
+func LoadX509KeyPair(certFile, keyFile string) (cert Certificate, err error) {
+ certPEMBlock, err := ioutil.ReadFile(certFile)
+ if err != nil {
+ return
+ }
+ keyPEMBlock, err := ioutil.ReadFile(keyFile)
+ if err != nil {
+ return
+ }
+ return X509KeyPair(certPEMBlock, keyPEMBlock)
+}
+
+// X509KeyPair parses a public/private key pair from a pair of
+// PEM encoded data.
+func X509KeyPair(certPEMBlock, keyPEMBlock []byte) (cert Certificate, err error) {
+ var certDERBlock *pem.Block
+ for {
+ certDERBlock, certPEMBlock = pem.Decode(certPEMBlock)
+ if certDERBlock == nil {
+ break
+ }
+ if certDERBlock.Type == "CERTIFICATE" {
+ cert.Certificate = append(cert.Certificate, certDERBlock.Bytes)
+ }
+ }
+
+ if len(cert.Certificate) == 0 {
+ err = errors.New("crypto/tls: failed to parse certificate PEM data")
+ return
+ }
+
+ var keyDERBlock *pem.Block
+ for {
+ keyDERBlock, keyPEMBlock = pem.Decode(keyPEMBlock)
+ if keyDERBlock == nil {
+ err = errors.New("crypto/tls: failed to parse key PEM data")
+ return
+ }
+ if keyDERBlock.Type == "PRIVATE KEY" || strings.HasSuffix(keyDERBlock.Type, " PRIVATE KEY") {
+ break
+ }
+ }
+
+ cert.PrivateKey, err = parsePrivateKey(keyDERBlock.Bytes)
+ if err != nil {
+ return
+ }
+
+ // We don't need to parse the public key for TLS, but we so do anyway
+ // to check that it looks sane and matches the private key.
+ x509Cert, err := x509.ParseCertificate(cert.Certificate[0])
+ if err != nil {
+ return
+ }
+
+ switch pub := x509Cert.PublicKey.(type) {
+ case *rsa.PublicKey:
+ priv, ok := cert.PrivateKey.(*rsa.PrivateKey)
+ if !ok {
+ err = errors.New("crypto/tls: private key type does not match public key type")
+ return
+ }
+ if pub.N.Cmp(priv.N) != 0 {
+ err = errors.New("crypto/tls: private key does not match public key")
+ return
+ }
+ case *ecdsa.PublicKey:
+ priv, ok := cert.PrivateKey.(*ecdsa.PrivateKey)
+ if !ok {
+ err = errors.New("crypto/tls: private key type does not match public key type")
+ return
+
+ }
+ if pub.X.Cmp(priv.X) != 0 || pub.Y.Cmp(priv.Y) != 0 {
+ err = errors.New("crypto/tls: private key does not match public key")
+ return
+ }
+ default:
+ err = errors.New("crypto/tls: unknown public key algorithm")
+ return
+ }
+
+ return
+}
+
+// Attempt to parse the given private key DER block. OpenSSL 0.9.8 generates
+// PKCS#1 private keys by default, while OpenSSL 1.0.0 generates PKCS#8 keys.
+// OpenSSL ecparam generates SEC1 EC private keys for ECDSA. We try all three.
+func parsePrivateKey(der []byte) (crypto.PrivateKey, error) {
+ if key, err := x509.ParsePKCS1PrivateKey(der); err == nil {
+ return key, nil
+ }
+ if key, err := x509.ParsePKCS8PrivateKey(der); err == nil {
+ switch key := key.(type) {
+ case *rsa.PrivateKey, *ecdsa.PrivateKey:
+ return key, nil
+ default:
+ return nil, errors.New("crypto/tls: found unknown private key type in PKCS#8 wrapping")
+ }
+ }
+ if key, err := x509.ParseECPrivateKey(der); err == nil {
+ return key, nil
+ }
+
+ return nil, errors.New("crypto/tls: failed to parse private key")
+}
diff --git a/src/ssl/test/test_config.cc b/src/ssl/test/test_config.cc
new file mode 100644
index 0000000..c032d96
--- /dev/null
+++ b/src/ssl/test/test_config.cc
@@ -0,0 +1,198 @@
+/* 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 "test_config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <memory>
+
+#include <openssl/base64.h>
+
+namespace {
+
+template <typename T>
+struct Flag {
+ const char *flag;
+ T TestConfig::*member;
+};
+
+// FindField looks for the flag in |flags| that matches |flag|. If one is found,
+// it returns a pointer to the corresponding field in |config|. Otherwise, it
+// returns NULL.
+template<typename T, size_t N>
+T *FindField(TestConfig *config, const Flag<T> (&flags)[N], const char *flag) {
+ for (size_t i = 0; i < N; i++) {
+ if (strcmp(flag, flags[i].flag) == 0) {
+ return &(config->*(flags[i].member));
+ }
+ }
+ return NULL;
+}
+
+const Flag<bool> kBoolFlags[] = {
+ { "-server", &TestConfig::is_server },
+ { "-dtls", &TestConfig::is_dtls },
+ { "-resume", &TestConfig::resume },
+ { "-fallback-scsv", &TestConfig::fallback_scsv },
+ { "-require-any-client-certificate",
+ &TestConfig::require_any_client_certificate },
+ { "-false-start", &TestConfig::false_start },
+ { "-async", &TestConfig::async },
+ { "-write-different-record-sizes",
+ &TestConfig::write_different_record_sizes },
+ { "-cbc-record-splitting", &TestConfig::cbc_record_splitting },
+ { "-partial-write", &TestConfig::partial_write },
+ { "-no-tls12", &TestConfig::no_tls12 },
+ { "-no-tls11", &TestConfig::no_tls11 },
+ { "-no-tls1", &TestConfig::no_tls1 },
+ { "-no-ssl3", &TestConfig::no_ssl3 },
+ { "-cookie-exchange", &TestConfig::cookie_exchange },
+ { "-shim-writes-first", &TestConfig::shim_writes_first },
+ { "-tls-d5-bug", &TestConfig::tls_d5_bug },
+ { "-expect-session-miss", &TestConfig::expect_session_miss },
+ { "-expect-extended-master-secret",
+ &TestConfig::expect_extended_master_secret },
+ { "-renegotiate", &TestConfig::renegotiate },
+ { "-allow-unsafe-legacy-renegotiation",
+ &TestConfig::allow_unsafe_legacy_renegotiation },
+ { "-enable-ocsp-stapling", &TestConfig::enable_ocsp_stapling },
+ { "-enable-signed-cert-timestamps",
+ &TestConfig::enable_signed_cert_timestamps },
+ { "-fastradio-padding", &TestConfig::fastradio_padding },
+};
+
+const Flag<std::string> kStringFlags[] = {
+ { "-key-file", &TestConfig::key_file },
+ { "-cert-file", &TestConfig::cert_file },
+ { "-expect-server-name", &TestConfig::expected_server_name },
+ { "-advertise-npn", &TestConfig::advertise_npn },
+ { "-expect-next-proto", &TestConfig::expected_next_proto },
+ { "-select-next-proto", &TestConfig::select_next_proto },
+ { "-send-channel-id", &TestConfig::send_channel_id },
+ { "-host-name", &TestConfig::host_name },
+ { "-advertise-alpn", &TestConfig::advertise_alpn },
+ { "-expect-alpn", &TestConfig::expected_alpn },
+ { "-expect-advertised-alpn", &TestConfig::expected_advertised_alpn },
+ { "-select-alpn", &TestConfig::select_alpn },
+ { "-psk", &TestConfig::psk },
+ { "-psk-identity", &TestConfig::psk_identity },
+ { "-srtp-profiles", &TestConfig::srtp_profiles },
+};
+
+const Flag<std::string> kBase64Flags[] = {
+ { "-expect-certificate-types", &TestConfig::expected_certificate_types },
+ { "-expect-channel-id", &TestConfig::expected_channel_id },
+ { "-expect-ocsp-response", &TestConfig::expected_ocsp_response },
+ { "-expect-signed-cert-timestamps",
+ &TestConfig::expected_signed_cert_timestamps },
+};
+
+const Flag<int> kIntFlags[] = {
+ { "-min-version", &TestConfig::min_version },
+ { "-max-version", &TestConfig::max_version },
+ { "-mtu", &TestConfig::mtu },
+};
+
+} // namespace
+
+TestConfig::TestConfig()
+ : is_server(false),
+ is_dtls(false),
+ resume(false),
+ fallback_scsv(false),
+ require_any_client_certificate(false),
+ false_start(false),
+ async(false),
+ write_different_record_sizes(false),
+ cbc_record_splitting(false),
+ partial_write(false),
+ no_tls12(false),
+ no_tls11(false),
+ no_tls1(false),
+ no_ssl3(false),
+ cookie_exchange(false),
+ shim_writes_first(false),
+ tls_d5_bug(false),
+ expect_session_miss(false),
+ expect_extended_master_secret(false),
+ renegotiate(false),
+ allow_unsafe_legacy_renegotiation(false),
+ enable_ocsp_stapling(false),
+ enable_signed_cert_timestamps(false),
+ fastradio_padding(false),
+ min_version(0),
+ max_version(0),
+ mtu(0) {
+}
+
+bool ParseConfig(int argc, char **argv, TestConfig *out_config) {
+ for (int i = 0; i < argc; i++) {
+ bool *bool_field = FindField(out_config, kBoolFlags, argv[i]);
+ if (bool_field != NULL) {
+ *bool_field = true;
+ continue;
+ }
+
+ std::string *string_field = FindField(out_config, kStringFlags, argv[i]);
+ if (string_field != NULL) {
+ i++;
+ if (i >= argc) {
+ fprintf(stderr, "Missing parameter\n");
+ return false;
+ }
+ string_field->assign(argv[i]);
+ continue;
+ }
+
+ std::string *base64_field = FindField(out_config, kBase64Flags, argv[i]);
+ if (base64_field != NULL) {
+ i++;
+ if (i >= argc) {
+ fprintf(stderr, "Missing parameter\n");
+ return false;
+ }
+ size_t len;
+ if (!EVP_DecodedLength(&len, strlen(argv[i]))) {
+ fprintf(stderr, "Invalid base64: %s\n", argv[i]);
+ }
+ std::unique_ptr<uint8_t[]> decoded(new uint8_t[len]);
+ if (!EVP_DecodeBase64(decoded.get(), &len, len,
+ reinterpret_cast<const uint8_t *>(argv[i]),
+ strlen(argv[i]))) {
+ fprintf(stderr, "Invalid base64: %s\n", argv[i]);
+ }
+ base64_field->assign(reinterpret_cast<const char *>(decoded.get()), len);
+ continue;
+ }
+
+ int *int_field = FindField(out_config, kIntFlags, argv[i]);
+ if (int_field) {
+ i++;
+ if (i >= argc) {
+ fprintf(stderr, "Missing parameter\n");
+ return false;
+ }
+ *int_field = atoi(argv[i]);
+ continue;
+ }
+
+ fprintf(stderr, "Unknown argument: %s\n", argv[i]);
+ return false;
+ }
+
+ return true;
+}
diff --git a/src/ssl/test/test_config.h b/src/ssl/test/test_config.h
new file mode 100644
index 0000000..ba54227
--- /dev/null
+++ b/src/ssl/test/test_config.h
@@ -0,0 +1,75 @@
+/* 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 HEADER_TEST_CONFIG
+#define HEADER_TEST_CONFIG
+
+#include <string>
+
+
+struct TestConfig {
+ TestConfig();
+
+ bool is_server;
+ bool is_dtls;
+ bool resume;
+ bool fallback_scsv;
+ std::string key_file;
+ std::string cert_file;
+ std::string expected_server_name;
+ std::string expected_certificate_types;
+ bool require_any_client_certificate;
+ std::string advertise_npn;
+ std::string expected_next_proto;
+ bool false_start;
+ std::string select_next_proto;
+ bool async;
+ bool write_different_record_sizes;
+ bool cbc_record_splitting;
+ bool partial_write;
+ bool no_tls12;
+ bool no_tls11;
+ bool no_tls1;
+ bool no_ssl3;
+ bool cookie_exchange;
+ std::string expected_channel_id;
+ std::string send_channel_id;
+ bool shim_writes_first;
+ bool tls_d5_bug;
+ std::string host_name;
+ std::string advertise_alpn;
+ std::string expected_alpn;
+ std::string expected_advertised_alpn;
+ std::string select_alpn;
+ bool expect_session_miss;
+ bool expect_extended_master_secret;
+ std::string psk;
+ std::string psk_identity;
+ bool renegotiate;
+ bool allow_unsafe_legacy_renegotiation;
+ std::string srtp_profiles;
+ bool enable_ocsp_stapling;
+ std::string expected_ocsp_response;
+ bool enable_signed_cert_timestamps;
+ std::string expected_signed_cert_timestamps;
+ bool fastradio_padding;
+ int min_version;
+ int max_version;
+ int mtu;
+};
+
+bool ParseConfig(int argc, char **argv, TestConfig *out_config);
+
+
+#endif // HEADER_TEST_CONFIG
diff --git a/src/tool/CMakeLists.txt b/src/tool/CMakeLists.txt
new file mode 100644
index 0000000..d542f26
--- /dev/null
+++ b/src/tool/CMakeLists.txt
@@ -0,0 +1,21 @@
+include_directories(../include)
+
+add_executable(
+ bssl
+
+ args.cc
+ client.cc
+ const.cc
+ digest.cc
+ pkcs12.cc
+ server.cc
+ speed.cc
+ tool.cc
+ transport_common.cc
+)
+
+if (APPLE OR WIN32)
+ target_link_libraries(bssl ssl crypto)
+else()
+ target_link_libraries(bssl ssl crypto -lrt)
+endif()
diff --git a/src/tool/args.cc b/src/tool/args.cc
new file mode 100644
index 0000000..52856d4
--- /dev/null
+++ b/src/tool/args.cc
@@ -0,0 +1,73 @@
+/* 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 <string>
+#include <vector>
+
+#include <stdio.h>
+#include <string.h>
+
+#include "internal.h"
+
+
+bool ParseKeyValueArguments(std::map<std::string, std::string> *out_args,
+ const std::vector<std::string> &args,
+ const struct argument *templates) {
+ out_args->clear();
+
+ for (size_t i = 0; i < args.size(); i++) {
+ const std::string &arg = args[i];
+ const struct argument *templ = nullptr;
+ for (size_t j = 0; templates[j].name[0] != 0; j++) {
+ if (strcmp(arg.c_str(), templates[j].name) == 0) {
+ templ = &templates[j];
+ break;
+ }
+ }
+
+ if (templ == nullptr) {
+ fprintf(stderr, "Unknown argument: %s\n", arg.c_str());
+ return false;
+ }
+
+ if (i + 1 >= args.size()) {
+ fprintf(stderr, "Missing argument for option: %s\n", arg.c_str());
+ return false;
+ }
+
+ if (out_args->find(arg) != out_args->end()) {
+ fprintf(stderr, "Duplicate value given for: %s\n", arg.c_str());
+ return false;
+ }
+
+ (*out_args)[arg] = args[++i];
+ }
+
+ for (size_t j = 0; templates[j].name[0] != 0; j++) {
+ const struct argument *templ = &templates[j];
+ if (templ->required && out_args->find(templ->name) == out_args->end()) {
+ fprintf(stderr, "Missing value for required argument: %s\n", templ->name);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void PrintUsage(const struct argument *templates) {
+ for (size_t i = 0; templates[i].name[0] != 0; i++) {
+ const struct argument *templ = &templates[i];
+ fprintf(stderr, "%s\t%s\n", templ->name, templ->description);
+ }
+}
diff --git a/src/tool/client.cc b/src/tool/client.cc
new file mode 100644
index 0000000..59c5fe3
--- /dev/null
+++ b/src/tool/client.cc
@@ -0,0 +1,100 @@
+/* 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 <openssl/base.h>
+
+#include <string>
+#include <vector>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+#include <openssl/err.h>
+#include <openssl/ssl.h>
+
+#include "internal.h"
+#include "transport_common.h"
+
+
+static const struct argument kArguments[] = {
+ {
+ "-connect", true,
+ "The hostname and port of the server to connect to, e.g. foo.com:443",
+ },
+ {
+ "-cipher", false,
+ "An OpenSSL-style cipher suite string that configures the offered ciphers",
+ },
+ {
+ "", false, "",
+ },
+};
+
+bool Client(const std::vector<std::string> &args) {
+ if (!InitSocketLibrary()) {
+ return false;
+ }
+
+ std::map<std::string, std::string> args_map;
+
+ if (!ParseKeyValueArguments(&args_map, args, kArguments)) {
+ PrintUsage(kArguments);
+ return false;
+ }
+
+ SSL_CTX *ctx = SSL_CTX_new(SSLv23_client_method());
+
+ const char *keylog_file = getenv("SSLKEYLOGFILE");
+ if (keylog_file) {
+ BIO *keylog_bio = BIO_new_file(keylog_file, "a");
+ if (!keylog_bio) {
+ ERR_print_errors_cb(PrintErrorCallback, stderr);
+ return false;
+ }
+ SSL_CTX_set_keylog_bio(ctx, keylog_bio);
+ }
+
+ if (args_map.count("-cipher") != 0 &&
+ !SSL_CTX_set_cipher_list(ctx, args_map["-cipher"].c_str())) {
+ fprintf(stderr, "Failed setting cipher list\n");
+ return false;
+ }
+
+ int sock = -1;
+ if (!Connect(&sock, args_map["-connect"])) {
+ return false;
+ }
+
+ BIO *bio = BIO_new_socket(sock, BIO_CLOSE);
+ SSL *ssl = SSL_new(ctx);
+ SSL_set_bio(ssl, bio, bio);
+
+ int ret = SSL_connect(ssl);
+ if (ret != 1) {
+ int ssl_err = SSL_get_error(ssl, ret);
+ fprintf(stderr, "Error while connecting: %d\n", ssl_err);
+ ERR_print_errors_cb(PrintErrorCallback, stderr);
+ return false;
+ }
+
+ fprintf(stderr, "Connected.\n");
+ PrintConnectionInfo(ssl);
+
+ bool ok = TransferData(ssl, sock);
+
+ SSL_free(ssl);
+ SSL_CTX_free(ctx);
+ return ok;
+}
diff --git a/src/tool/const.cc b/src/tool/const.cc
new file mode 100644
index 0000000..219fd3c
--- /dev/null
+++ b/src/tool/const.cc
@@ -0,0 +1,326 @@
+/* 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 <stdint.h>
+#include <stdlib.h>
+
+extern "C" {
+
+uint8_t kDERRSAPrivate2048[] = {
+ 0x30, 0x82, 0x04, 0xa3, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00,
+ 0xd0, 0x02, 0xde, 0x5d, 0x19, 0x33, 0x48, 0x15, 0xc7, 0x86, 0xde, 0xa3,
+ 0xec, 0x63, 0x89, 0x14, 0x63, 0x99, 0x30, 0x1f, 0x5d, 0x25, 0xb2, 0xfa,
+ 0x27, 0x28, 0x4b, 0xb4, 0xf3, 0xba, 0xc6, 0xbc, 0x19, 0x38, 0x89, 0x56,
+ 0xf0, 0x42, 0xae, 0x9f, 0x84, 0x7b, 0x0d, 0xcf, 0xda, 0x1c, 0xd1, 0xd8,
+ 0x11, 0x26, 0x3f, 0x67, 0x76, 0x19, 0xfd, 0xfe, 0x6b, 0x12, 0xd4, 0x02,
+ 0x00, 0x42, 0x1b, 0x0f, 0xb6, 0x78, 0x5e, 0x1d, 0xb9, 0x3d, 0x32, 0x4f,
+ 0x7f, 0x41, 0xe4, 0xc9, 0x1b, 0x94, 0x40, 0x4e, 0xa2, 0x5c, 0x9c, 0x88,
+ 0x79, 0xf9, 0x9a, 0x64, 0x1b, 0x83, 0xdf, 0x1f, 0x9b, 0xb1, 0xa5, 0xe4,
+ 0xdf, 0x6d, 0x75, 0x3f, 0x98, 0xc7, 0x42, 0x53, 0xb4, 0x36, 0xba, 0x60,
+ 0xdd, 0xbd, 0x2d, 0xa9, 0x9f, 0x63, 0xd2, 0x74, 0xcc, 0xff, 0x13, 0x8a,
+ 0xa1, 0xd0, 0x91, 0x36, 0x1e, 0x22, 0x6e, 0x45, 0x46, 0xf3, 0xd1, 0xca,
+ 0xf6, 0x2c, 0x3f, 0x87, 0xf1, 0x15, 0xbf, 0xb0, 0x4d, 0xe3, 0xcc, 0xa7,
+ 0x18, 0xad, 0xa9, 0xb0, 0x5f, 0xbb, 0x2d, 0xc3, 0x06, 0x55, 0x69, 0x40,
+ 0xb9, 0x9a, 0x92, 0x14, 0x67, 0xde, 0x4c, 0x0d, 0x09, 0xab, 0x57, 0x41,
+ 0xe4, 0x30, 0xae, 0xd2, 0x22, 0x01, 0xbb, 0x36, 0xcb, 0x45, 0x0a, 0x82,
+ 0xc8, 0x56, 0x61, 0x39, 0x6a, 0x0a, 0xea, 0xab, 0x39, 0x28, 0x2c, 0x92,
+ 0x80, 0xe8, 0x00, 0xd1, 0xfa, 0xcc, 0x1d, 0xf8, 0xe5, 0xd7, 0x03, 0x34,
+ 0x04, 0x1b, 0x17, 0x35, 0xbc, 0xc6, 0xf9, 0x55, 0x0c, 0x05, 0xd8, 0xd3,
+ 0xc7, 0x4e, 0x0a, 0x92, 0xf1, 0x1d, 0x0d, 0x01, 0xf3, 0x0e, 0x3a, 0x9b,
+ 0x9b, 0x75, 0x8f, 0xe8, 0x0d, 0xbb, 0xf6, 0x81, 0x09, 0x48, 0x72, 0x05,
+ 0x9e, 0x0e, 0x48, 0x62, 0xd2, 0xba, 0x88, 0xa3, 0x18, 0xf5, 0x1b, 0xc9,
+ 0x9b, 0xff, 0x31, 0x3f, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x01,
+ 0x00, 0x76, 0xf1, 0x9c, 0xfb, 0x79, 0x64, 0x84, 0x8c, 0xc7, 0xaa, 0x4c,
+ 0x77, 0x49, 0xbd, 0xe4, 0xed, 0xbe, 0xc2, 0x22, 0xed, 0x5c, 0x53, 0x29,
+ 0x53, 0xb7, 0xbe, 0x68, 0x04, 0x11, 0xf6, 0xb4, 0x9b, 0x6c, 0x84, 0x92,
+ 0xac, 0x1e, 0xf8, 0xd2, 0x67, 0xae, 0xd6, 0xba, 0xa0, 0x27, 0x25, 0xa1,
+ 0xac, 0xbe, 0xa9, 0xb3, 0x49, 0xd3, 0x13, 0xab, 0xd4, 0xa6, 0x9f, 0x7e,
+ 0x91, 0xa2, 0x5a, 0x2a, 0xa5, 0x42, 0x7e, 0xf3, 0xba, 0x65, 0x69, 0x23,
+ 0xf2, 0xa7, 0x5f, 0x23, 0x97, 0x07, 0xe9, 0x2f, 0x18, 0x87, 0xe9, 0x13,
+ 0x2d, 0x4b, 0x2a, 0x3a, 0x69, 0x91, 0xfe, 0x47, 0x41, 0x08, 0xc3, 0x7d,
+ 0x8c, 0x31, 0x62, 0xa2, 0xcf, 0xf9, 0xe9, 0xbe, 0xf8, 0xa4, 0x2d, 0x43,
+ 0x48, 0x0e, 0xa3, 0x95, 0x8f, 0xcf, 0xef, 0xc1, 0xb1, 0x3e, 0x63, 0x81,
+ 0x66, 0x1d, 0x7f, 0x68, 0xf9, 0x9c, 0x23, 0xae, 0x0f, 0x70, 0xaf, 0xed,
+ 0xa9, 0x4e, 0x95, 0xd1, 0x39, 0x51, 0x15, 0x55, 0xfc, 0x4e, 0x9e, 0xb3,
+ 0xb0, 0xc0, 0x07, 0x1d, 0xd9, 0xd2, 0x48, 0x4c, 0x03, 0x31, 0x2d, 0x21,
+ 0xda, 0x4d, 0xed, 0x29, 0xf8, 0xbf, 0xaf, 0x1f, 0x8d, 0x6f, 0xdc, 0xae,
+ 0xf0, 0x4a, 0x01, 0xa1, 0xb8, 0x06, 0x61, 0x58, 0x18, 0xff, 0x40, 0xa1,
+ 0x1c, 0x82, 0xf8, 0x23, 0xaf, 0xce, 0x62, 0x3e, 0x2d, 0x30, 0x09, 0xff,
+ 0xba, 0xa6, 0x34, 0x7e, 0x6e, 0x9e, 0x59, 0x66, 0x6b, 0x39, 0x08, 0x1f,
+ 0x3e, 0x76, 0xbc, 0x29, 0xef, 0x10, 0x62, 0x7f, 0xf4, 0xdf, 0xe6, 0x5f,
+ 0xa4, 0x1f, 0x60, 0xfe, 0x37, 0xdb, 0xd7, 0x8f, 0xff, 0xf9, 0xf0, 0xaf,
+ 0x66, 0xa2, 0x7d, 0x36, 0x19, 0x7f, 0xe2, 0xc3, 0x84, 0x66, 0x18, 0x2b,
+ 0x18, 0x16, 0x4f, 0xb3, 0xce, 0x69, 0x6b, 0xb6, 0xd6, 0x98, 0x25, 0xcb,
+ 0x90, 0x4f, 0x60, 0x68, 0x91, 0x02, 0x81, 0x81, 0x00, 0xf6, 0xd6, 0xae,
+ 0x84, 0xc0, 0x9f, 0x2f, 0xef, 0xa6, 0x7e, 0x91, 0x7a, 0x4d, 0x1c, 0xe0,
+ 0x3e, 0x61, 0xf8, 0xcc, 0x4d, 0x0d, 0x09, 0xa3, 0xeb, 0x9a, 0xbe, 0x89,
+ 0x59, 0x50, 0xf7, 0xd6, 0x8f, 0x66, 0x67, 0x97, 0x7e, 0xb4, 0x2d, 0x73,
+ 0x08, 0xf8, 0x12, 0x22, 0x7f, 0x5c, 0x76, 0x2b, 0x06, 0x7c, 0xaa, 0x54,
+ 0x83, 0xce, 0x2d, 0xab, 0xc3, 0xb7, 0xb1, 0x74, 0x10, 0xc9, 0x67, 0xc7,
+ 0x8c, 0xd1, 0x13, 0x17, 0x1e, 0xb2, 0x4f, 0xc7, 0xda, 0xcf, 0x45, 0xc3,
+ 0x1c, 0x6d, 0x98, 0x08, 0xc9, 0xf4, 0xd4, 0x6d, 0x16, 0xb4, 0x6b, 0x02,
+ 0x24, 0x25, 0x0a, 0x2d, 0xc0, 0xa3, 0x2e, 0x4b, 0xae, 0xf7, 0x4e, 0xb5,
+ 0x68, 0xb2, 0xe7, 0x88, 0xdc, 0x2e, 0xbc, 0x91, 0x42, 0x7f, 0x36, 0xbc,
+ 0x71, 0x4e, 0xc4, 0x5f, 0xfa, 0xbe, 0x46, 0x89, 0x61, 0xe3, 0x17, 0x3b,
+ 0x51, 0x29, 0xa8, 0x2c, 0x07, 0x02, 0x81, 0x81, 0x00, 0xd7, 0xbb, 0x45,
+ 0x76, 0x81, 0x15, 0x3e, 0x1b, 0x95, 0xd8, 0x7c, 0x8c, 0x08, 0x02, 0xe1,
+ 0x04, 0xaf, 0xa1, 0x59, 0x4c, 0xc7, 0x71, 0xf1, 0xd0, 0xef, 0xa7, 0xb6,
+ 0xa0, 0x70, 0xd0, 0xf7, 0x86, 0x8d, 0x4a, 0xf6, 0x9f, 0xac, 0xf3, 0x78,
+ 0xc9, 0xb5, 0xdf, 0x86, 0x71, 0xa9, 0x69, 0x63, 0xe4, 0x8a, 0x22, 0x57,
+ 0xa2, 0xa8, 0xd5, 0xf1, 0xb0, 0xe5, 0x43, 0x20, 0xd2, 0x18, 0x89, 0x3b,
+ 0xed, 0x90, 0xf5, 0xde, 0x82, 0x90, 0x7a, 0xd4, 0x0a, 0x3d, 0x89, 0x82,
+ 0x3a, 0x5f, 0x66, 0x73, 0x0e, 0x98, 0x1c, 0x84, 0x3a, 0x5a, 0x8f, 0xa1,
+ 0xb8, 0x60, 0xaf, 0x40, 0x8b, 0x6f, 0xda, 0x85, 0xad, 0x55, 0x62, 0x04,
+ 0xe1, 0x07, 0xb8, 0x49, 0xcb, 0xd4, 0x17, 0xdc, 0xb6, 0xe3, 0x39, 0xf5,
+ 0x22, 0xa0, 0xec, 0x58, 0xbd, 0x06, 0x4a, 0x87, 0xa1, 0x90, 0x9c, 0x27,
+ 0xd7, 0xa5, 0x9d, 0xf3, 0x09, 0x02, 0x81, 0x80, 0x28, 0x4c, 0xec, 0xb9,
+ 0x67, 0xe9, 0x95, 0x9d, 0xff, 0x04, 0xf3, 0x23, 0x90, 0xab, 0x82, 0x41,
+ 0x2d, 0x25, 0xbd, 0xd5, 0x66, 0xa7, 0x88, 0x47, 0xd3, 0x40, 0x00, 0x94,
+ 0xc0, 0x8f, 0x76, 0x4c, 0x7b, 0x5f, 0xb6, 0x70, 0x4d, 0x62, 0x8e, 0x41,
+ 0x8c, 0x9f, 0x09, 0x5a, 0xd9, 0xf1, 0xc1, 0x1c, 0x92, 0x06, 0x0d, 0x3e,
+ 0x67, 0xcf, 0x35, 0x18, 0x03, 0x49, 0xc9, 0xb5, 0x63, 0xec, 0xb9, 0xbb,
+ 0xd7, 0xf6, 0xd1, 0xf3, 0x85, 0x11, 0x59, 0x83, 0xf4, 0x0b, 0x63, 0xcb,
+ 0xa4, 0x69, 0x0a, 0x26, 0x4e, 0xfe, 0xcf, 0xc0, 0xc1, 0x3c, 0x27, 0x61,
+ 0x57, 0x5a, 0xce, 0x15, 0x81, 0x8e, 0xf1, 0x74, 0x63, 0x94, 0x4a, 0x32,
+ 0x09, 0xe3, 0x9b, 0x88, 0xb7, 0x68, 0xba, 0x1e, 0xad, 0x3e, 0x76, 0x8d,
+ 0xd9, 0x5a, 0x5e, 0x81, 0x45, 0xc7, 0xa6, 0x6e, 0x80, 0xf1, 0x2e, 0x12,
+ 0x16, 0x47, 0x0a, 0xc9, 0x02, 0x81, 0x81, 0x00, 0xa0, 0xc7, 0x6e, 0x46,
+ 0x9a, 0x7f, 0x85, 0x71, 0x33, 0xa5, 0x4b, 0x75, 0x65, 0x87, 0x17, 0xc2,
+ 0xd1, 0x4e, 0x33, 0xea, 0x97, 0xfe, 0x20, 0xd5, 0xb1, 0xb6, 0xd1, 0xd2,
+ 0x13, 0x22, 0x7a, 0x47, 0xaa, 0x48, 0x03, 0x34, 0x0f, 0xc6, 0xc8, 0xef,
+ 0xb3, 0xff, 0x6a, 0x08, 0x8d, 0xd5, 0x00, 0xe0, 0xd3, 0xde, 0x32, 0x68,
+ 0x04, 0xe2, 0xa6, 0x25, 0x4b, 0x48, 0x53, 0x4e, 0xa1, 0x80, 0xad, 0xcc,
+ 0x29, 0x2c, 0x44, 0xf0, 0x13, 0xd3, 0xa6, 0xf2, 0x16, 0xd8, 0xc3, 0xd8,
+ 0xd3, 0x3e, 0xdc, 0x63, 0x35, 0x14, 0x93, 0xab, 0x95, 0xd0, 0xd4, 0x1b,
+ 0x40, 0xdb, 0x7c, 0x04, 0x2f, 0x91, 0xb1, 0xec, 0xf3, 0xe4, 0x80, 0x74,
+ 0x61, 0xb7, 0x84, 0x30, 0x47, 0xda, 0x9c, 0xe1, 0x24, 0xca, 0x0e, 0x1b,
+ 0x07, 0xc9, 0xfd, 0x7c, 0xab, 0x12, 0xa2, 0xb0, 0xd3, 0xc0, 0xbd, 0xa4,
+ 0xe7, 0x46, 0xa7, 0x59, 0x02, 0x81, 0x80, 0x30, 0x5a, 0xa3, 0x8e, 0x0f,
+ 0xeb, 0xad, 0x9f, 0xf6, 0xa4, 0x82, 0xd8, 0x78, 0x83, 0xd2, 0xe4, 0x14,
+ 0x91, 0x20, 0x6f, 0x1f, 0x2b, 0x08, 0x21, 0x92, 0x5e, 0x30, 0xfe, 0x13,
+ 0xf2, 0x02, 0xd6, 0xe8, 0x96, 0x40, 0x98, 0x85, 0xb2, 0x63, 0x2b, 0x12,
+ 0xcf, 0x37, 0x4a, 0x27, 0xb1, 0x5f, 0x6f, 0x76, 0xa0, 0x29, 0xae, 0x2f,
+ 0x63, 0x72, 0xd9, 0x39, 0xca, 0x09, 0x29, 0x47, 0x98, 0x9f, 0x85, 0xae,
+ 0xb7, 0xe3, 0x0c, 0xcd, 0xbe, 0x4e, 0x45, 0xd3, 0x69, 0x1a, 0xb7, 0x7f,
+ 0xce, 0x2d, 0xfe, 0x9b, 0xe7, 0x4c, 0x7c, 0x2c, 0x8c, 0x26, 0x92, 0xdc,
+ 0x73, 0x71, 0x5f, 0x09, 0x4b, 0x49, 0xbf, 0x86, 0x94, 0xef, 0x3f, 0xf5,
+ 0x89, 0x8f, 0x12, 0x63, 0xff, 0xf2, 0x61, 0x6a, 0x66, 0xb2, 0xcc, 0x01,
+ 0x75, 0xef, 0x54, 0xa4, 0xa7, 0x03, 0x49, 0xfd, 0x27, 0xf4, 0x85, 0x00,
+ 0x77, 0xe6, 0xd3,
+};
+
+size_t kDERRSAPrivate2048Len = sizeof(kDERRSAPrivate2048);
+
+uint8_t kDERRSAPrivate4096[] = {
+ 0x30, 0x82, 0x09, 0x28, 0x02, 0x01, 0x00, 0x02, 0x82, 0x02, 0x01, 0x00,
+ 0xc3, 0x82, 0x01, 0xda, 0x03, 0xe1, 0x0d, 0x78, 0xf4, 0x86, 0xf1, 0x28,
+ 0xf0, 0x4c, 0x34, 0xa6, 0x73, 0x0c, 0xfb, 0x22, 0xfa, 0x35, 0xc9, 0x3a,
+ 0x4c, 0xf1, 0x15, 0xfe, 0x96, 0x4a, 0x64, 0x75, 0xfe, 0x62, 0x5c, 0x77,
+ 0x76, 0x12, 0x9a, 0x68, 0x63, 0x09, 0x4d, 0x6f, 0x4a, 0xec, 0xc7, 0xac,
+ 0x17, 0x60, 0x5e, 0xfa, 0xd8, 0xe0, 0xca, 0x3d, 0xfd, 0x0b, 0x5a, 0x88,
+ 0x4c, 0xe6, 0xbd, 0x99, 0x34, 0x9e, 0x06, 0xc5, 0xf8, 0x33, 0xad, 0x5d,
+ 0x8d, 0x73, 0x5d, 0x1c, 0xc2, 0xb3, 0xcd, 0x47, 0x2f, 0x41, 0x04, 0xe8,
+ 0x71, 0x6d, 0xd9, 0x19, 0xf4, 0x56, 0xb8, 0xcf, 0x0f, 0x92, 0x13, 0xb4,
+ 0x1c, 0x6a, 0x51, 0x4e, 0xdd, 0xd0, 0xc0, 0x20, 0x3f, 0xd9, 0x32, 0x92,
+ 0xe2, 0xbd, 0x66, 0x33, 0x4b, 0x44, 0xbf, 0xd8, 0x28, 0x3d, 0x51, 0x00,
+ 0xe3, 0xf8, 0x3b, 0x6c, 0x55, 0x22, 0x71, 0xee, 0xa7, 0x3c, 0xe4, 0x36,
+ 0xa2, 0xcf, 0x41, 0xeb, 0x64, 0x79, 0xbb, 0x75, 0xe8, 0xc5, 0x29, 0xe1,
+ 0xa5, 0xd2, 0xf6, 0x84, 0x2c, 0x0e, 0x0c, 0x0f, 0xc2, 0x42, 0xfd, 0xa9,
+ 0xdb, 0x8f, 0x44, 0xa0, 0xfc, 0xf3, 0x26, 0xd8, 0x6a, 0xc2, 0x14, 0x2d,
+ 0x3c, 0x09, 0x68, 0x98, 0x67, 0x0e, 0x01, 0xd4, 0x80, 0x02, 0x5c, 0xc0,
+ 0xb9, 0xd3, 0x12, 0x2e, 0xaa, 0x3c, 0xab, 0x56, 0x8c, 0x96, 0xb3, 0x25,
+ 0xeb, 0xa7, 0x86, 0xd8, 0xbe, 0x70, 0x01, 0xe9, 0xa7, 0x7b, 0x27, 0x01,
+ 0xbe, 0x4c, 0x23, 0xf4, 0x19, 0x17, 0x6e, 0x31, 0x69, 0xab, 0x1a, 0x6a,
+ 0x1f, 0x57, 0xde, 0x9a, 0x8e, 0x1d, 0xfd, 0xd9, 0x5d, 0xce, 0xa0, 0x47,
+ 0x19, 0x8d, 0x27, 0x33, 0x77, 0xe2, 0xa4, 0x1d, 0x72, 0x72, 0xe6, 0xec,
+ 0xf3, 0xad, 0x85, 0x50, 0xc0, 0x94, 0xab, 0x78, 0x03, 0x67, 0x1e, 0x48,
+ 0x45, 0x50, 0x41, 0x7d, 0xb5, 0x62, 0x28, 0x80, 0x41, 0x89, 0xac, 0x99,
+ 0xe2, 0xd7, 0xe1, 0xc2, 0x54, 0xfc, 0xff, 0xa7, 0xc0, 0x71, 0xc6, 0xd7,
+ 0xae, 0x05, 0xf2, 0xbc, 0x2a, 0xe8, 0x43, 0x88, 0x4a, 0x0c, 0xb2, 0x61,
+ 0x2e, 0x9b, 0xac, 0x48, 0x90, 0xaa, 0x7b, 0x24, 0x9b, 0xc2, 0xc5, 0x48,
+ 0x95, 0x8d, 0x4f, 0x92, 0x6a, 0xb7, 0xcc, 0xb5, 0x9f, 0x06, 0xe4, 0x05,
+ 0xac, 0x05, 0x81, 0x66, 0xb0, 0x24, 0x04, 0x12, 0xac, 0xac, 0x9a, 0x1e,
+ 0xea, 0xce, 0x82, 0xfb, 0x27, 0x2e, 0xa1, 0x5e, 0xb8, 0x86, 0x74, 0x1a,
+ 0x3a, 0xdd, 0x8c, 0x98, 0x3c, 0x23, 0x2b, 0xea, 0x8a, 0xd0, 0x92, 0x43,
+ 0xbb, 0xec, 0xb3, 0x27, 0x52, 0x2c, 0x7f, 0x07, 0x33, 0xe5, 0x21, 0xa3,
+ 0xda, 0x4e, 0x65, 0xd2, 0x96, 0xb5, 0x88, 0xcb, 0x9f, 0x0c, 0x21, 0x41,
+ 0x80, 0x02, 0xb2, 0x9e, 0x78, 0x60, 0x40, 0x18, 0x21, 0x52, 0x4f, 0x09,
+ 0x5f, 0x75, 0x8b, 0xf3, 0x71, 0x70, 0xab, 0x94, 0x3b, 0xd1, 0xe8, 0x65,
+ 0x55, 0xf2, 0x76, 0xe3, 0x7c, 0x1d, 0x3a, 0x7c, 0x44, 0xbf, 0xb4, 0x10,
+ 0x2e, 0x16, 0x7f, 0xdc, 0xd2, 0x37, 0xf3, 0x48, 0x68, 0x80, 0xa9, 0x9d,
+ 0x56, 0xff, 0x63, 0xed, 0x29, 0x79, 0x39, 0xfa, 0x92, 0x65, 0x22, 0xee,
+ 0x5c, 0x2a, 0xa9, 0xef, 0x30, 0x82, 0x10, 0xae, 0x46, 0xe2, 0x52, 0xa5,
+ 0x2e, 0x23, 0xe6, 0x65, 0xb5, 0x54, 0xd8, 0xa1, 0xe8, 0x9c, 0xf1, 0xe3,
+ 0xf5, 0xc8, 0x4b, 0x54, 0xac, 0x02, 0x4d, 0xdf, 0x01, 0xc2, 0xc7, 0x82,
+ 0x30, 0x0d, 0x86, 0x17, 0x64, 0x99, 0x7b, 0xfa, 0x46, 0x23, 0x19, 0x6b,
+ 0x7c, 0x01, 0x61, 0x22, 0xa6, 0x28, 0x17, 0x48, 0xa4, 0x6a, 0x32, 0x00,
+ 0x16, 0x23, 0x40, 0x0b, 0x51, 0xd7, 0xc7, 0x91, 0x60, 0xd7, 0x32, 0x91,
+ 0xf5, 0xf7, 0x3c, 0x24, 0xc0, 0x9f, 0x4a, 0xf3, 0x02, 0x03, 0x01, 0x00,
+ 0x01, 0x02, 0x82, 0x02, 0x00, 0x6b, 0x3d, 0x28, 0x9e, 0xd9, 0x79, 0xdc,
+ 0xd5, 0xf7, 0xea, 0xfc, 0xe5, 0x23, 0xc9, 0xe9, 0x27, 0x53, 0xfc, 0x4e,
+ 0xd4, 0xc4, 0xc2, 0x33, 0xfa, 0x92, 0xb1, 0xbb, 0x0a, 0xc6, 0x8d, 0x4f,
+ 0xc5, 0x99, 0x1f, 0x82, 0xf0, 0xd4, 0x07, 0x28, 0x43, 0x11, 0xef, 0xcc,
+ 0x55, 0xbb, 0x97, 0x5d, 0x7e, 0xfb, 0xe3, 0x94, 0xb5, 0xab, 0xb8, 0xc1,
+ 0xb6, 0x76, 0xd2, 0x7f, 0x7a, 0x3c, 0x14, 0x64, 0xf3, 0x60, 0x75, 0x3d,
+ 0xe9, 0xe1, 0x57, 0x17, 0x45, 0x35, 0x8d, 0x8e, 0x09, 0x74, 0x93, 0x03,
+ 0x8a, 0x84, 0x54, 0xf9, 0xc8, 0x36, 0x4f, 0xb6, 0xc2, 0x11, 0xd0, 0x6f,
+ 0xd6, 0xc4, 0x07, 0xb0, 0x5f, 0x1f, 0x27, 0x02, 0x2a, 0x6c, 0x69, 0x50,
+ 0xb9, 0x5f, 0xcc, 0x57, 0x7d, 0x52, 0x79, 0xe9, 0x51, 0x41, 0x7c, 0x18,
+ 0x6f, 0x0c, 0xc3, 0x75, 0x67, 0x33, 0xa4, 0xb9, 0x93, 0x96, 0xaf, 0x2a,
+ 0x27, 0x69, 0xfc, 0x70, 0x81, 0xb7, 0x94, 0x4f, 0xe8, 0x3a, 0x58, 0xbb,
+ 0x86, 0xd5, 0x83, 0x30, 0x91, 0xe1, 0x4f, 0x72, 0x80, 0xd5, 0x59, 0x6f,
+ 0x2c, 0x45, 0xb6, 0x51, 0x45, 0x96, 0x75, 0x63, 0x83, 0x9a, 0xbc, 0x15,
+ 0x16, 0xa8, 0x98, 0x84, 0x50, 0xbb, 0x99, 0xbd, 0x91, 0xbb, 0x15, 0x67,
+ 0xd3, 0x93, 0xd3, 0xb7, 0xe4, 0xcf, 0x09, 0x03, 0xf4, 0x2c, 0xd4, 0xd2,
+ 0x76, 0xca, 0xee, 0xee, 0x9d, 0x62, 0x41, 0xa6, 0x29, 0xc5, 0x6b, 0xd2,
+ 0xe0, 0xc3, 0x49, 0x3e, 0x00, 0x2a, 0xcd, 0xc0, 0xfa, 0xe7, 0xb8, 0x7e,
+ 0x6d, 0x04, 0x35, 0x22, 0x6c, 0x0b, 0x7d, 0x3b, 0x51, 0x33, 0x9b, 0x27,
+ 0xde, 0xcf, 0x21, 0xc3, 0xb0, 0xbc, 0x47, 0x3c, 0xb5, 0x72, 0x91, 0x12,
+ 0xcc, 0x44, 0x36, 0xda, 0x8c, 0x26, 0xad, 0x8b, 0x6e, 0xdb, 0xf3, 0xb0,
+ 0x8a, 0x47, 0xf3, 0x8c, 0x1c, 0xc0, 0x48, 0x61, 0x63, 0x09, 0x48, 0x08,
+ 0x4f, 0x3b, 0xb4, 0x90, 0xf7, 0x4b, 0xd7, 0x58, 0x88, 0xfe, 0x3d, 0xe4,
+ 0x9d, 0xf2, 0xec, 0xf4, 0x6d, 0x70, 0x2c, 0x0f, 0x55, 0x61, 0xdb, 0x62,
+ 0x3d, 0x75, 0x19, 0x4b, 0x24, 0x02, 0xe3, 0xbd, 0x01, 0xd8, 0xe4, 0x05,
+ 0x85, 0xda, 0x19, 0xc5, 0x91, 0xda, 0x09, 0xf6, 0xd0, 0xff, 0x7d, 0xae,
+ 0x68, 0x86, 0x17, 0xac, 0xf7, 0xb9, 0xde, 0xe7, 0x3f, 0x1e, 0xb5, 0x7e,
+ 0xcd, 0x64, 0xf2, 0x48, 0x61, 0x86, 0x4b, 0x21, 0x5b, 0xe2, 0x3b, 0x69,
+ 0xfc, 0xeb, 0x17, 0x25, 0x97, 0x6d, 0x6f, 0xd9, 0x7e, 0xce, 0x31, 0xb7,
+ 0xad, 0x2c, 0xb0, 0x31, 0xaf, 0x89, 0x2d, 0x8d, 0x30, 0x2a, 0x45, 0x69,
+ 0x0c, 0x8e, 0x96, 0xfa, 0x00, 0xcb, 0x47, 0x32, 0x3c, 0x40, 0xe5, 0x75,
+ 0xe3, 0xa9, 0x4f, 0xd4, 0xa8, 0x33, 0x76, 0x59, 0xea, 0xbe, 0x09, 0xae,
+ 0x2c, 0x27, 0x9e, 0x1f, 0xc2, 0xdd, 0x90, 0x38, 0xe6, 0xb8, 0x49, 0x1f,
+ 0x17, 0x5a, 0x01, 0xa2, 0x73, 0xaa, 0x92, 0xb6, 0xed, 0x26, 0xd7, 0x0d,
+ 0xa0, 0x39, 0x42, 0xdb, 0xc1, 0xf6, 0xe3, 0x0b, 0x11, 0x4c, 0x3e, 0x40,
+ 0xba, 0x2a, 0x42, 0xa9, 0x5b, 0x74, 0x0a, 0xcd, 0x0c, 0xae, 0x13, 0x27,
+ 0x6b, 0x37, 0xfa, 0xdd, 0x08, 0x89, 0xb4, 0xc2, 0x11, 0xda, 0xb2, 0x8d,
+ 0x44, 0x59, 0x1f, 0x19, 0x1a, 0x7d, 0x0b, 0x70, 0x62, 0x00, 0x8a, 0x4a,
+ 0x2e, 0xda, 0x44, 0xc6, 0xc6, 0xf9, 0xe6, 0x14, 0xdc, 0xe1, 0x9e, 0xb6,
+ 0x8e, 0xcf, 0x0d, 0xa2, 0xf4, 0x64, 0x8c, 0x71, 0x4e, 0x0a, 0xf6, 0xa8,
+ 0xca, 0x2d, 0xe0, 0xd2, 0x5f, 0x78, 0xee, 0x3d, 0x77, 0x13, 0xba, 0x61,
+ 0xac, 0xe3, 0x0f, 0xb0, 0x5f, 0xd3, 0x28, 0x12, 0x5d, 0xa6, 0xe9, 0x38,
+ 0xfa, 0x6e, 0xe7, 0xdf, 0xee, 0x65, 0x98, 0x97, 0x48, 0xb7, 0xa9, 0x73,
+ 0x21, 0x02, 0x82, 0x01, 0x01, 0x00, 0xe7, 0x1b, 0x4c, 0x5c, 0xcc, 0xb7,
+ 0xae, 0x4b, 0xe8, 0x7d, 0x19, 0xc0, 0x53, 0xc7, 0x17, 0x86, 0xac, 0xef,
+ 0x79, 0x94, 0x61, 0xc3, 0x17, 0x17, 0xb6, 0x5f, 0x08, 0x7c, 0xc7, 0x96,
+ 0xf3, 0x69, 0xc4, 0x2b, 0x90, 0xae, 0x35, 0x57, 0x2c, 0x73, 0x10, 0xaa,
+ 0x59, 0x69, 0x42, 0x21, 0xa3, 0x29, 0x94, 0x35, 0x3c, 0x12, 0x9e, 0xa0,
+ 0x08, 0x28, 0xad, 0x34, 0x3d, 0x07, 0x23, 0x6d, 0xb8, 0xfa, 0x48, 0x4e,
+ 0x1a, 0x4b, 0xeb, 0x4c, 0x91, 0xf2, 0xa0, 0x83, 0x75, 0x8c, 0x82, 0x4e,
+ 0xea, 0x75, 0xfb, 0x39, 0x9e, 0x81, 0xe9, 0xac, 0x8f, 0x1f, 0x7c, 0x59,
+ 0x4f, 0x8e, 0x99, 0x81, 0x2e, 0xea, 0xb7, 0x77, 0x16, 0xf4, 0xea, 0x9e,
+ 0x4a, 0x44, 0xa0, 0x5b, 0xc6, 0x22, 0x82, 0xa3, 0x54, 0x1f, 0x9e, 0x07,
+ 0xfb, 0x8e, 0x92, 0xd0, 0x31, 0x5e, 0x68, 0x26, 0xdf, 0x18, 0xc3, 0x85,
+ 0xba, 0x43, 0xcb, 0xae, 0x3d, 0x31, 0x03, 0xc6, 0x20, 0xfd, 0x11, 0xb1,
+ 0x62, 0xdc, 0xa0, 0xb4, 0xef, 0x21, 0x8c, 0x1d, 0x95, 0xfa, 0xf1, 0x79,
+ 0xba, 0x97, 0x43, 0xf7, 0x45, 0x39, 0x05, 0x54, 0xbf, 0x49, 0xab, 0x99,
+ 0x00, 0x6a, 0x06, 0x84, 0x9c, 0xb6, 0xf0, 0xdc, 0x46, 0x8e, 0x1c, 0x66,
+ 0xec, 0x4a, 0xae, 0xc3, 0xba, 0xfb, 0x1b, 0xe7, 0xef, 0x0b, 0xb6, 0xe5,
+ 0xd7, 0xf1, 0x6c, 0x82, 0xd8, 0xdc, 0xa3, 0xc2, 0x02, 0x17, 0x53, 0xe0,
+ 0xa0, 0x84, 0x4e, 0xad, 0x4a, 0x9b, 0x07, 0x87, 0x1a, 0x59, 0x21, 0xba,
+ 0xa0, 0x9b, 0x8f, 0x27, 0xa0, 0x93, 0xf7, 0x51, 0xad, 0x62, 0xc0, 0x6f,
+ 0x00, 0x37, 0x16, 0x70, 0xa6, 0x30, 0xb7, 0xa9, 0x7b, 0x7f, 0x53, 0x9d,
+ 0x54, 0x93, 0xba, 0x1f, 0xe1, 0x35, 0x4a, 0x88, 0x45, 0x34, 0x95, 0x24,
+ 0x64, 0x9a, 0xa5, 0x61, 0x7c, 0xed, 0x83, 0x38, 0xfb, 0x45, 0x02, 0x82,
+ 0x01, 0x01, 0x00, 0xd8, 0x91, 0x15, 0x00, 0x3f, 0x7f, 0x27, 0x0a, 0x3b,
+ 0xc4, 0x67, 0x36, 0x1d, 0x13, 0xd1, 0x50, 0x39, 0x1e, 0x26, 0xad, 0x25,
+ 0x65, 0x6a, 0x1d, 0xf7, 0x5d, 0x6b, 0x4b, 0x26, 0xb0, 0x32, 0x5a, 0x30,
+ 0x78, 0xb6, 0x11, 0xab, 0x5b, 0x4b, 0x6e, 0xcd, 0xe5, 0x93, 0xb2, 0xa9,
+ 0xca, 0x4b, 0xe8, 0x61, 0x45, 0xd1, 0xf7, 0x8b, 0x11, 0x77, 0x3a, 0x59,
+ 0xd6, 0xb3, 0x2a, 0xf3, 0x8a, 0x6a, 0x2e, 0x53, 0xe8, 0x21, 0xda, 0x03,
+ 0xd5, 0x2d, 0xcc, 0xd2, 0xba, 0xec, 0x11, 0x69, 0xe3, 0xab, 0xd5, 0x9e,
+ 0xfc, 0x9c, 0xff, 0x90, 0x79, 0x05, 0x3a, 0xb0, 0x5e, 0x43, 0x05, 0xd7,
+ 0x9b, 0xec, 0xda, 0x22, 0x2c, 0xc4, 0x18, 0x28, 0x26, 0xbb, 0xdb, 0x45,
+ 0xa0, 0x7d, 0x32, 0x17, 0xc3, 0x14, 0xd8, 0x72, 0x7a, 0x59, 0x33, 0x5e,
+ 0x02, 0xb2, 0x3c, 0xd8, 0x46, 0x82, 0x5e, 0x9c, 0x06, 0x20, 0x5f, 0x63,
+ 0xd8, 0x02, 0xda, 0x59, 0x0b, 0x32, 0x89, 0xc4, 0xbd, 0x63, 0x74, 0xbb,
+ 0x76, 0x34, 0xb9, 0x18, 0x29, 0x6d, 0x79, 0xe6, 0x02, 0x57, 0xab, 0x16,
+ 0x5a, 0x59, 0xea, 0x22, 0xdc, 0x37, 0x9c, 0x19, 0x7a, 0x2a, 0x40, 0xeb,
+ 0xa7, 0x2d, 0xef, 0x3d, 0xc5, 0x29, 0x71, 0xa6, 0x4a, 0x2d, 0x62, 0xc4,
+ 0x85, 0xed, 0x65, 0x88, 0x7a, 0x83, 0x3c, 0x06, 0x9a, 0xac, 0x24, 0x50,
+ 0xed, 0x27, 0xfc, 0xff, 0x98, 0xdb, 0x8b, 0xf1, 0xf1, 0x6f, 0xa0, 0x89,
+ 0xc1, 0xfe, 0x82, 0xbb, 0xab, 0xe1, 0xc2, 0x2a, 0xea, 0xd3, 0x73, 0xbf,
+ 0xe9, 0xb3, 0x4d, 0xd7, 0xf4, 0x3b, 0x66, 0x9f, 0x3b, 0xd4, 0x9b, 0xf9,
+ 0xad, 0xa0, 0x45, 0xed, 0x58, 0x41, 0xc6, 0xf2, 0x32, 0x0c, 0xbd, 0xc6,
+ 0x4b, 0x2b, 0xfa, 0x1c, 0x57, 0x49, 0x5d, 0x82, 0x37, 0xba, 0x02, 0x8e,
+ 0x43, 0x72, 0x1f, 0xdc, 0x55, 0x74, 0xd7, 0x02, 0x82, 0x01, 0x01, 0x00,
+ 0xc0, 0xcc, 0xc3, 0x4d, 0xff, 0xf3, 0x94, 0xd2, 0xfa, 0xe7, 0xb2, 0xde,
+ 0x02, 0x86, 0x6b, 0x98, 0x0d, 0x19, 0xd3, 0xa1, 0xf8, 0x55, 0x1b, 0x24,
+ 0xcb, 0x1e, 0x49, 0x24, 0x60, 0x16, 0x0c, 0x87, 0xc6, 0x02, 0x5a, 0x37,
+ 0x1b, 0x84, 0xd8, 0x2e, 0x3e, 0x4e, 0xff, 0x3c, 0x92, 0xd1, 0x21, 0x1f,
+ 0x84, 0xe7, 0x4c, 0x70, 0x74, 0x29, 0x29, 0xe5, 0x55, 0x69, 0xe9, 0x27,
+ 0xd5, 0x64, 0xaa, 0x17, 0x12, 0xcf, 0x25, 0x9d, 0x04, 0x75, 0xe2, 0xa4,
+ 0x39, 0x48, 0xb2, 0x7e, 0x40, 0x0f, 0xba, 0x06, 0x27, 0x4a, 0x10, 0x74,
+ 0x6d, 0x0f, 0x6a, 0x6f, 0x67, 0xfb, 0xd2, 0x25, 0x32, 0xe6, 0xd4, 0xcf,
+ 0x37, 0xb3, 0x80, 0x51, 0x5e, 0x92, 0x23, 0x7f, 0x51, 0x10, 0x7f, 0x21,
+ 0x37, 0x3f, 0x2e, 0xe5, 0x19, 0x9f, 0xab, 0x3b, 0x6c, 0x3b, 0x87, 0x94,
+ 0x2c, 0xeb, 0x90, 0xdf, 0x45, 0xee, 0x80, 0x50, 0x22, 0xd1, 0xff, 0x76,
+ 0xae, 0xa1, 0x51, 0xd0, 0x0e, 0x3c, 0xa0, 0x2f, 0x53, 0x5a, 0xde, 0xcc,
+ 0x6b, 0xea, 0x1a, 0xbf, 0x39, 0x48, 0xc6, 0x63, 0x7f, 0x6e, 0x00, 0x2f,
+ 0xeb, 0xc4, 0xa1, 0xb8, 0xc2, 0x11, 0x68, 0x89, 0x0b, 0x5b, 0x02, 0xaa,
+ 0x94, 0x12, 0x10, 0x42, 0x6a, 0x6b, 0x6a, 0xe1, 0x7b, 0x1f, 0x0b, 0x14,
+ 0x86, 0x59, 0x5d, 0xd1, 0xb6, 0x09, 0xd5, 0xb7, 0x31, 0x41, 0x8f, 0xcd,
+ 0xb2, 0x48, 0x1e, 0x1a, 0x7b, 0xfd, 0x3f, 0xac, 0x61, 0x3e, 0xac, 0xa8,
+ 0xdd, 0x04, 0xd6, 0xf4, 0x58, 0xf1, 0x2b, 0x1f, 0xdb, 0xb3, 0xc1, 0x80,
+ 0xef, 0xa9, 0x12, 0x2e, 0xfa, 0x3f, 0x20, 0x3c, 0xd4, 0xd9, 0xb1, 0xab,
+ 0x9e, 0xed, 0x23, 0x7c, 0x3b, 0xb3, 0x5b, 0x65, 0xca, 0xb6, 0xe1, 0xd8,
+ 0xe5, 0x8e, 0xfd, 0xbd, 0x3a, 0x57, 0x1c, 0x1e, 0xef, 0xad, 0x7e, 0xdd,
+ 0x5e, 0xc5, 0xe0, 0xc9, 0x02, 0x82, 0x01, 0x00, 0x28, 0x3d, 0xfd, 0x5b,
+ 0x08, 0x71, 0x86, 0x3d, 0x9e, 0x91, 0x86, 0x64, 0x45, 0xce, 0xf2, 0xec,
+ 0x27, 0x50, 0xf4, 0xfa, 0xe3, 0xa2, 0x0e, 0xaf, 0xf6, 0xd1, 0x43, 0x28,
+ 0xb9, 0xcd, 0xaf, 0xed, 0x96, 0x68, 0x37, 0xdc, 0xdc, 0xac, 0xa0, 0x3d,
+ 0xbc, 0xc0, 0xd6, 0x4b, 0x32, 0xc5, 0xc6, 0x89, 0x2d, 0xda, 0x1d, 0x84,
+ 0x14, 0x31, 0x70, 0xa8, 0x45, 0x1d, 0x62, 0x39, 0xae, 0xfb, 0x9f, 0x73,
+ 0x70, 0x60, 0x08, 0x3a, 0x4c, 0xd0, 0x06, 0x2c, 0xb3, 0x53, 0xcc, 0x9e,
+ 0x07, 0xc1, 0x28, 0xa3, 0x0f, 0x61, 0xfd, 0x82, 0x77, 0xc4, 0x25, 0x36,
+ 0x9c, 0xa3, 0x47, 0x6d, 0x04, 0x7d, 0x92, 0xeb, 0x8d, 0xc2, 0x27, 0xc6,
+ 0x1d, 0x5f, 0xe5, 0x34, 0x7f, 0xa1, 0xac, 0xe1, 0xec, 0x0c, 0x72, 0x09,
+ 0x2e, 0x6c, 0x91, 0xba, 0xbb, 0xd3, 0x60, 0x6f, 0x71, 0xf8, 0xd8, 0x2c,
+ 0xe0, 0x6d, 0x3b, 0x02, 0xbe, 0xb8, 0xda, 0xfe, 0xdb, 0xe0, 0xfa, 0xc9,
+ 0x22, 0xe7, 0xd6, 0x5d, 0x50, 0xa0, 0x4c, 0x77, 0xc0, 0x87, 0xa2, 0x32,
+ 0x2e, 0x8d, 0x6c, 0xe0, 0xfb, 0xcc, 0x5a, 0x3c, 0xe9, 0xb1, 0x66, 0x1b,
+ 0xf9, 0x97, 0xfb, 0xd6, 0x08, 0x74, 0x0e, 0x53, 0x10, 0x75, 0x5c, 0x98,
+ 0x23, 0xc0, 0x50, 0xe2, 0xb3, 0x85, 0xf7, 0x71, 0x10, 0x85, 0x43, 0x71,
+ 0x9a, 0x00, 0x8f, 0xd0, 0x47, 0xc1, 0x69, 0xd6, 0xd7, 0x5f, 0xfe, 0x1b,
+ 0xe9, 0x1f, 0x66, 0x10, 0xbc, 0xc8, 0x71, 0x94, 0xb5, 0x6e, 0xe1, 0x0a,
+ 0x85, 0x93, 0x11, 0x2b, 0xc7, 0x13, 0x94, 0x1f, 0xf8, 0xeb, 0x07, 0x46,
+ 0xb0, 0x7c, 0x1b, 0xab, 0xc8, 0x1f, 0x7d, 0x52, 0xc1, 0x21, 0xcf, 0x47,
+ 0x3a, 0xa6, 0x16, 0x3c, 0x05, 0x66, 0xde, 0x8b, 0x21, 0x4d, 0x0e, 0xf2,
+ 0xf3, 0x49, 0x8b, 0xa5, 0x01, 0xee, 0x82, 0x7c, 0x6d, 0x22, 0xec, 0x0d,
+ 0x02, 0x82, 0x01, 0x00, 0x39, 0x88, 0xc7, 0x5d, 0x9c, 0x8b, 0xbc, 0xa1,
+ 0x33, 0xe4, 0x93, 0x24, 0x91, 0x3c, 0xfb, 0x35, 0xf5, 0xaf, 0x61, 0xa3,
+ 0x06, 0x0e, 0xf5, 0x28, 0x9e, 0x95, 0x21, 0xd8, 0xa3, 0xea, 0x77, 0xc0,
+ 0x70, 0x28, 0x3f, 0xff, 0x4e, 0x6b, 0x8c, 0x01, 0x83, 0x43, 0xcd, 0x71,
+ 0xb4, 0xe3, 0xcc, 0xa7, 0x1e, 0xff, 0xbe, 0xf4, 0x78, 0xdc, 0x67, 0xf5,
+ 0xe9, 0x3d, 0x6d, 0x06, 0x29, 0x53, 0xd5, 0x20, 0x99, 0x4b, 0x03, 0xab,
+ 0x41, 0x48, 0xe7, 0x13, 0x28, 0x1f, 0x0f, 0x96, 0xea, 0x44, 0x12, 0x6b,
+ 0x0d, 0x67, 0xfc, 0x3b, 0x7b, 0xbc, 0x2a, 0x2d, 0x2a, 0x8b, 0x31, 0xa5,
+ 0x81, 0xc8, 0xf4, 0x4d, 0xd2, 0x9f, 0xbf, 0x49, 0x11, 0xd6, 0x05, 0x2b,
+ 0x68, 0x8f, 0x5a, 0x40, 0x98, 0x0a, 0x3f, 0x3f, 0xd5, 0xae, 0x96, 0x46,
+ 0xae, 0xd0, 0x66, 0x80, 0xe4, 0x3c, 0x2e, 0x34, 0xde, 0x7d, 0xbc, 0x30,
+ 0x95, 0xa2, 0x6a, 0x94, 0x4e, 0xa5, 0x4c, 0x55, 0x37, 0xca, 0x0d, 0x70,
+ 0x6b, 0xae, 0xde, 0x1e, 0xa2, 0xcd, 0x6a, 0xdf, 0xda, 0xa1, 0xa1, 0xd8,
+ 0xec, 0xd3, 0x9d, 0xde, 0x07, 0xc1, 0xa0, 0xb7, 0xab, 0x52, 0xe4, 0xc8,
+ 0x3c, 0x1b, 0x55, 0xae, 0xb7, 0x84, 0x9b, 0xd6, 0x90, 0x13, 0x49, 0xed,
+ 0x65, 0x88, 0x4b, 0x3c, 0x94, 0x55, 0xc8, 0x86, 0x87, 0x5a, 0x0b, 0xa5,
+ 0x7c, 0x20, 0xec, 0xc5, 0x48, 0x9e, 0xb2, 0x6c, 0x0e, 0x0c, 0xf2, 0x4d,
+ 0xea, 0x1a, 0x44, 0x8e, 0x66, 0xaa, 0x6e, 0x6c, 0x9a, 0xea, 0x18, 0x02,
+ 0x7c, 0xaf, 0xf0, 0x5e, 0x63, 0xb7, 0xe2, 0xb1, 0x8e, 0x99, 0x99, 0x32,
+ 0xa5, 0x0f, 0x0f, 0x35, 0x88, 0x6d, 0xf6, 0xc5, 0x5c, 0x75, 0x70, 0x7f,
+ 0xab, 0x78, 0xa3, 0x15, 0x43, 0x08, 0x88, 0x58, 0x9d, 0xbb, 0x63, 0xf7,
+ 0x59, 0x8e, 0xd7, 0x45, 0x87, 0x86, 0x05, 0x9d,
+};
+
+size_t kDERRSAPrivate4096Len = sizeof(kDERRSAPrivate4096);
+
+}
diff --git a/src/tool/digest.cc b/src/tool/digest.cc
new file mode 100644
index 0000000..f95f412
--- /dev/null
+++ b/src/tool/digest.cc
@@ -0,0 +1,482 @@
+/* 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 <openssl/base.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#if !defined(OPENSSL_WINDOWS)
+#include <unistd.h>
+#if !defined(O_BINARY)
+#define O_BINARY 0
+#endif
+#else
+#define NOMINMAX
+#pragma warning(push, 3)
+#include <windows.h>
+#pragma warning(pop)
+#include <io.h>
+#define PATH_MAX MAX_PATH
+typedef int ssize_t;
+#endif
+
+#include <openssl/digest.h>
+
+
+struct close_delete {
+ void operator()(int *fd) {
+ close(*fd);
+ }
+};
+
+template<typename T, typename R, R (*func) (T*)>
+struct func_delete {
+ void operator()(T* obj) {
+ func(obj);
+ }
+};
+
+// Source is an awkward expression of a union type in C++: Stdin | File filename.
+struct Source {
+ enum Type {
+ STDIN,
+ };
+
+ Source() : is_stdin_(false) {}
+ Source(Type) : is_stdin_(true) {}
+ Source(const std::string &name) : is_stdin_(false), filename_(name) {}
+
+ bool is_stdin() const { return is_stdin_; }
+ const std::string &filename() const { return filename_; }
+
+ private:
+ bool is_stdin_;
+ std::string filename_;
+};
+
+static const char kStdinName[] = "standard input";
+
+// OpenFile opens the regular file named |filename| and sets |*out_fd| to be a
+// file descriptor to it. Returns true on sucess or prints an error to stderr
+// and returns false on error.
+static bool OpenFile(int *out_fd, const std::string &filename) {
+ *out_fd = -1;
+
+ int fd = open(filename.c_str(), O_RDONLY | O_BINARY);
+ if (fd < 0) {
+ fprintf(stderr, "Failed to open input file '%s': %s\n", filename.c_str(),
+ strerror(errno));
+ return false;
+ }
+
+#if !defined(OPENSSL_WINDOWS)
+ struct stat st;
+ if (fstat(fd, &st)) {
+ fprintf(stderr, "Failed to stat input file '%s': %s\n", filename.c_str(),
+ strerror(errno));
+ goto err;
+ }
+
+ if (!S_ISREG(st.st_mode)) {
+ fprintf(stderr, "%s: not a regular file\n", filename.c_str());
+ goto err;
+ }
+#endif
+
+ *out_fd = fd;
+ return true;
+
+#if !defined(OPENSSL_WINDOWS)
+err:
+ close(fd);
+ return false;
+#endif
+}
+
+// SumFile hashes the contents of |source| with |md| and sets |*out_hex| to the
+// hex-encoded result.
+//
+// It returns true on success or prints an error to stderr and returns false on
+// error.
+static bool SumFile(std::string *out_hex, const EVP_MD *md,
+ const Source &source) {
+ std::unique_ptr<int, close_delete> scoped_fd;
+ int fd;
+
+ if (source.is_stdin()) {
+ fd = 0;
+ } else {
+ if (!OpenFile(&fd, source.filename())) {
+ return false;
+ }
+ scoped_fd.reset(&fd);
+ }
+
+ static const size_t kBufSize = 8192;
+ std::unique_ptr<uint8_t[]> buf(new uint8_t[kBufSize]);
+
+ EVP_MD_CTX ctx;
+ EVP_MD_CTX_init(&ctx);
+ std::unique_ptr<EVP_MD_CTX, func_delete<EVP_MD_CTX, int, EVP_MD_CTX_cleanup>>
+ scoped_ctx(&ctx);
+
+ if (!EVP_DigestInit_ex(&ctx, md, NULL)) {
+ fprintf(stderr, "Failed to initialize EVP_MD_CTX.\n");
+ return false;
+ }
+
+ for (;;) {
+ ssize_t n;
+
+ do {
+ n = read(fd, buf.get(), kBufSize);
+ } while (n == -1 && errno == EINTR);
+
+ if (n == 0) {
+ break;
+ } else if (n < 0) {
+ fprintf(stderr, "Failed to read from %s: %s\n",
+ source.is_stdin() ? kStdinName : source.filename().c_str(),
+ strerror(errno));
+ return false;
+ }
+
+ if (!EVP_DigestUpdate(&ctx, buf.get(), n)) {
+ fprintf(stderr, "Failed to update hash.\n");
+ return false;
+ }
+ }
+
+ uint8_t digest[EVP_MAX_MD_SIZE];
+ unsigned digest_len;
+ if (!EVP_DigestFinal_ex(&ctx, digest, &digest_len)) {
+ fprintf(stderr, "Failed to finish hash.\n");
+ return false;
+ }
+
+ char hex_digest[EVP_MAX_MD_SIZE * 2];
+ static const char kHextable[] = "0123456789abcdef";
+ for (unsigned i = 0; i < digest_len; i++) {
+ const uint8_t b = digest[i];
+ hex_digest[i * 2] = kHextable[b >> 4];
+ hex_digest[i * 2 + 1] = kHextable[b & 0xf];
+ }
+ *out_hex = std::string(hex_digest, digest_len * 2);
+
+ return true;
+}
+
+// PrintFileSum hashes |source| with |md| and prints a line to stdout in the
+// format of the coreutils *sum utilities. It returns true on success or prints
+// an error to stderr and returns false on error.
+static bool PrintFileSum(const EVP_MD *md, const Source &source) {
+ std::string hex_digest;
+ if (!SumFile(&hex_digest, md, source)) {
+ return false;
+ }
+
+ // TODO: When given "--binary" or "-b", we should print " *" instead of " "
+ // between the digest and the filename.
+ //
+ // MSYS and Cygwin md5sum default to binary mode by default, whereas other
+ // platforms' tools default to text mode by default. We default to text mode
+ // by default and consider text mode equivalent to binary mode (i.e. we
+ // always use Unix semantics, even on Windows), which means that our default
+ // output will differ from the MSYS and Cygwin tools' default output.
+ printf("%s %s\n", hex_digest.c_str(),
+ source.is_stdin() ? "-" : source.filename().c_str());
+ return true;
+}
+
+// CheckModeArguments contains arguments for the check mode. See the
+// sha256sum(1) man page for details.
+struct CheckModeArguments {
+ bool quiet = false;
+ bool status = false;
+ bool warn = false;
+ bool strict = false;
+};
+
+// Check reads lines from |source| where each line is in the format of the
+// coreutils *sum utilities. It attempts to verify each hash by reading the
+// file named in the line.
+//
+// It returns true if all files were verified and, if |args.strict|, no input
+// lines had formatting errors. Otherwise it prints errors to stderr and
+// returns false.
+static bool Check(const CheckModeArguments &args, const EVP_MD *md,
+ const Source &source) {
+ std::unique_ptr<FILE, func_delete<FILE, int, fclose>> scoped_file;
+ FILE *file;
+
+ if (source.is_stdin()) {
+ file = stdin;
+ } else {
+ int fd;
+ if (!OpenFile(&fd, source.filename())) {
+ return false;
+ }
+
+ file = fdopen(fd, "rb");
+ if (!file) {
+ perror("fdopen");
+ close(fd);
+ return false;
+ }
+
+ scoped_file = std::unique_ptr<FILE, func_delete<FILE, int, fclose>>(file);
+ }
+
+ const size_t hex_size = EVP_MD_size(md) * 2;
+ char line[EVP_MAX_MD_SIZE * 2 + 2 /* spaces */ + PATH_MAX + 1 /* newline */ +
+ 1 /* NUL */];
+ unsigned bad_lines = 0;
+ unsigned parsed_lines = 0;
+ unsigned error_lines = 0;
+ unsigned bad_hash_lines = 0;
+ unsigned line_no = 0;
+ bool ok = true;
+ bool draining_overlong_line = false;
+
+ for (;;) {
+ line_no++;
+
+ if (fgets(line, sizeof(line), file) == nullptr) {
+ if (feof(file)) {
+ break;
+ }
+ fprintf(stderr, "Error reading from input.\n");
+ return false;
+ }
+
+ size_t len = strlen(line);
+
+ if (draining_overlong_line) {
+ if (line[len - 1] == '\n') {
+ draining_overlong_line = false;
+ }
+ continue;
+ }
+
+ const bool overlong = line[len - 1] != '\n' && !feof(file);
+
+ if (len < hex_size + 2 /* spaces */ + 1 /* filename */ ||
+ line[hex_size] != ' ' ||
+ line[hex_size + 1] != ' ' ||
+ overlong) {
+ bad_lines++;
+ if (args.warn) {
+ fprintf(stderr, "%s: %u: improperly formatted line\n",
+ source.is_stdin() ? kStdinName : source.filename().c_str(), line_no);
+ }
+ if (args.strict) {
+ ok = false;
+ }
+ if (overlong) {
+ draining_overlong_line = true;
+ }
+ continue;
+ }
+
+ if (line[len - 1] == '\n') {
+ line[len - 1] = 0;
+ len--;
+ }
+
+ parsed_lines++;
+
+ // coreutils does not attempt to restrict relative or absolute paths in the
+ // input so nor does this code.
+ std::string calculated_hex_digest;
+ const std::string target_filename(&line[hex_size + 2]);
+ Source target_source;
+ if (target_filename == "-") {
+ // coreutils reads from stdin if the filename is "-".
+ target_source = Source(Source::STDIN);
+ } else {
+ target_source = Source(target_filename);
+ }
+
+ if (!SumFile(&calculated_hex_digest, md, target_source)) {
+ error_lines++;
+ ok = false;
+ continue;
+ }
+
+ if (calculated_hex_digest != std::string(line, hex_size)) {
+ bad_hash_lines++;
+ if (!args.status) {
+ printf("%s: FAILED\n", target_filename.c_str());
+ }
+ ok = false;
+ continue;
+ }
+
+ if (!args.quiet) {
+ printf("%s: OK\n", target_filename.c_str());
+ }
+ }
+
+ if (!args.status) {
+ if (bad_lines > 0 && parsed_lines > 0) {
+ fprintf(stderr, "WARNING: %u line%s improperly formatted\n", bad_lines,
+ bad_lines == 1 ? " is" : "s are");
+ }
+ if (error_lines > 0) {
+ fprintf(stderr, "WARNING: %u computed checksum(s) did NOT match\n",
+ error_lines);
+ }
+ }
+
+ if (parsed_lines == 0) {
+ fprintf(stderr, "%s: no properly formatted checksum lines found.\n",
+ source.is_stdin() ? kStdinName : source.filename().c_str());
+ ok = false;
+ }
+
+ return ok;
+}
+
+// DigestSum acts like the coreutils *sum utilites, with the given hash
+// function.
+static bool DigestSum(const EVP_MD *md,
+ const std::vector<std::string> &args) {
+ bool check_mode = false;
+ CheckModeArguments check_args;
+ bool check_mode_args_given = false;
+ std::vector<Source> sources;
+
+ auto it = args.begin();
+ while (it != args.end()) {
+ const std::string &arg = *it;
+ if (!arg.empty() && arg[0] != '-') {
+ break;
+ }
+
+ it++;
+
+ if (arg == "--") {
+ break;
+ }
+
+ if (arg == "-") {
+ // "-" ends the argument list and indicates that stdin should be used.
+ sources.push_back(Source(Source::STDIN));
+ break;
+ }
+
+ if (arg.size() >= 2 && arg[0] == '-' && arg[1] != '-') {
+ for (size_t i = 1; i < arg.size(); i++) {
+ switch (arg[i]) {
+ case 'b':
+ case 't':
+ // Binary/text mode – irrelevent, even on Windows.
+ break;
+ case 'c':
+ check_mode = true;
+ break;
+ case 'w':
+ check_mode_args_given = true;
+ check_args.warn = true;
+ break;
+ default:
+ fprintf(stderr, "Unknown option '%c'.\n", arg[i]);
+ return false;
+ }
+ }
+ } else if (arg == "--binary" || arg == "--text") {
+ // Binary/text mode – irrelevent, even on Windows.
+ } else if (arg == "--check") {
+ check_mode = true;
+ } else if (arg == "--quiet") {
+ check_mode_args_given = true;
+ check_args.quiet = true;
+ } else if (arg == "--status") {
+ check_mode_args_given = true;
+ check_args.status = true;
+ } else if (arg == "--warn") {
+ check_mode_args_given = true;
+ check_args.warn = true;
+ } else if (arg == "--strict") {
+ check_mode_args_given = true;
+ check_args.strict = true;
+ } else {
+ fprintf(stderr, "Unknown option '%s'.\n", arg.c_str());
+ return false;
+ }
+ }
+
+ if (check_mode_args_given && !check_mode) {
+ fprintf(
+ stderr,
+ "Check mode arguments are only meaningful when verifying checksums.\n");
+ return false;
+ }
+
+ for (; it != args.end(); it++) {
+ sources.push_back(Source(*it));
+ }
+
+ if (sources.empty()) {
+ sources.push_back(Source(Source::STDIN));
+ }
+
+ bool ok = true;
+
+ if (check_mode) {
+ for (auto &source : sources) {
+ ok &= Check(check_args, md, source);
+ }
+ } else {
+ for (auto &source : sources) {
+ ok &= PrintFileSum(md, source);
+ }
+ }
+
+ return ok;
+}
+
+bool MD5Sum(const std::vector<std::string> &args) {
+ return DigestSum(EVP_md5(), args);
+}
+
+bool SHA1Sum(const std::vector<std::string> &args) {
+ return DigestSum(EVP_sha1(), args);
+}
+
+bool SHA224Sum(const std::vector<std::string> &args) {
+ return DigestSum(EVP_sha224(), args);
+}
+
+bool SHA256Sum(const std::vector<std::string> &args) {
+ return DigestSum(EVP_sha256(), args);
+}
+
+bool SHA384Sum(const std::vector<std::string> &args) {
+ return DigestSum(EVP_sha384(), args);
+}
+
+bool SHA512Sum(const std::vector<std::string> &args) {
+ return DigestSum(EVP_sha512(), args);
+}
diff --git a/src/tool/internal.h b/src/tool/internal.h
new file mode 100644
index 0000000..bc87c51
--- /dev/null
+++ b/src/tool/internal.h
@@ -0,0 +1,47 @@
+/* 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_TOOL_INTERNAL_H
+#define OPENSSL_HEADER_TOOL_INTERNAL_H
+
+#include <string>
+#include <vector>
+
+#if defined(_MSC_VER)
+#pragma warning(push)
+// MSVC issues warning C4702 for unreachable code in its xtree header when
+// compiling with -D_HAS_EXCEPTIONS=0. See
+// https://connect.microsoft.com/VisualStudio/feedback/details/809962
+#pragma warning(disable: 4702)
+#endif
+
+#include <map>
+
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif
+
+struct argument {
+ const char name[15];
+ bool required;
+ const char *description;
+};
+
+bool ParseKeyValueArguments(std::map<std::string, std::string> *out_args, const
+ std::vector<std::string> &args, const struct argument *templates);
+
+void PrintUsage(const struct argument *templates);
+
+
+#endif /* !OPENSSL_HEADER_TOOL_INTERNAL_H */
diff --git a/src/tool/pkcs12.cc b/src/tool/pkcs12.cc
new file mode 100644
index 0000000..e0133e5
--- /dev/null
+++ b/src/tool/pkcs12.cc
@@ -0,0 +1,138 @@
+/* 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 <openssl/base.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#if defined(OPENSSL_WINDOWS)
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+
+#include <openssl/bytestring.h>
+#include <openssl/pem.h>
+#include <openssl/pkcs8.h>
+#include <openssl/stack.h>
+
+#include "internal.h"
+
+
+#if defined(OPENSSL_WINDOWS)
+typedef int read_result_t;
+#else
+typedef ssize_t read_result_t;
+#endif
+
+static const struct argument kArguments[] = {
+ {
+ "-dump", false, "Dump the key and contents of the given file to stdout",
+ },
+ {
+ "", false, "",
+ },
+};
+
+bool DoPKCS12(const std::vector<std::string> &args) {
+ std::map<std::string, std::string> args_map;
+
+ if (!ParseKeyValueArguments(&args_map, args, kArguments) ||
+ args_map["-dump"].empty()) {
+ PrintUsage(kArguments);
+ return false;
+ }
+
+ int fd = open(args_map["-dump"].c_str(), O_RDONLY);
+ if (fd < 0) {
+ perror("open");
+ return false;
+ }
+
+ struct stat st;
+ if (fstat(fd, &st)) {
+ perror("fstat");
+ close(fd);
+ return false;
+ }
+ const size_t size = st.st_size;
+
+ std::unique_ptr<uint8_t[]> contents(new uint8_t[size]);
+ read_result_t n;
+ size_t off = 0;
+ do {
+ n = read(fd, &contents[off], size - off);
+ if (n >= 0) {
+ off += static_cast<size_t>(n);
+ }
+ } while ((n > 0 && off < size) || (n == -1 && errno == EINTR));
+
+ if (off != size) {
+ perror("read");
+ close(fd);
+ return false;
+ }
+
+ close(fd);
+
+ printf("Enter password: ");
+ fflush(stdout);
+
+ char password[256];
+ off = 0;
+ do {
+ n = read(0, &password[off], sizeof(password) - 1 - off);
+ if (n >= 0) {
+ off += static_cast<size_t>(n);
+ }
+ } while ((n > 0 && memchr(password, '\n', off) == NULL &&
+ off < sizeof(password) - 1) ||
+ (n == -1 && errno == EINTR));
+
+ char *newline = reinterpret_cast<char*>(memchr(password, '\n', off));
+ if (newline == NULL) {
+ return false;
+ }
+ *newline = 0;
+
+ CBS pkcs12;
+ CBS_init(&pkcs12, contents.get(), size);
+
+ EVP_PKEY *key;
+ STACK_OF(X509) *certs = sk_X509_new_null();
+
+ if (!PKCS12_get_key_and_certs(&key, certs, &pkcs12, password)) {
+ fprintf(stderr, "Failed to parse PKCS#12 data:\n");
+ BIO_print_errors_fp(stderr);
+ return false;
+ }
+
+ PEM_write_PrivateKey(stdout, key, NULL, NULL, 0, NULL, NULL);
+ EVP_PKEY_free(key);
+
+ for (size_t i = 0; i < sk_X509_num(certs); i++) {
+ PEM_write_X509(stdout, sk_X509_value(certs, i));
+ }
+ sk_X509_pop_free(certs, X509_free);
+
+ return true;
+}
diff --git a/src/tool/server.cc b/src/tool/server.cc
new file mode 100644
index 0000000..120e450
--- /dev/null
+++ b/src/tool/server.cc
@@ -0,0 +1,109 @@
+/* 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 <openssl/base.h>
+
+#include <string>
+#include <vector>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+#include <openssl/err.h>
+#include <openssl/ssl.h>
+
+#include "internal.h"
+#include "transport_common.h"
+
+
+static const struct argument kArguments[] = {
+ {
+ "-accept", true,
+ "The port of the server to bind on; eg 45102",
+ },
+ {
+ "-cipher", false,
+ "An OpenSSL-style cipher suite string that configures the offered ciphers",
+ },
+ {
+ "-key", false,
+ "Private-key file to use (default is server.pem)",
+ },
+ {
+ "", false, "",
+ },
+};
+
+bool Server(const std::vector<std::string> &args) {
+ if (!InitSocketLibrary()) {
+ return false;
+ }
+
+ std::map<std::string, std::string> args_map;
+
+ if (!ParseKeyValueArguments(&args_map, args, kArguments)) {
+ PrintUsage(kArguments);
+ return false;
+ }
+
+ SSL_CTX *ctx = SSL_CTX_new(SSLv23_server_method());
+ SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3);
+
+ // Server authentication is required.
+ std::string key_file = "server.pem";
+ if (args_map.count("-key") != 0) {
+ key_file = args_map["-key"];
+ }
+ if (SSL_CTX_use_PrivateKey_file(ctx, key_file.c_str(), SSL_FILETYPE_PEM) <= 0) {
+ fprintf(stderr, "Failed to load private key: %s\n", key_file.c_str());
+ return false;
+ }
+ if (SSL_CTX_use_certificate_chain_file(ctx, key_file.c_str()) != 1) {
+ fprintf(stderr, "Failed to load cert chain: %s\n", key_file.c_str());
+ return false;
+ }
+
+ if (args_map.count("-cipher") != 0 &&
+ !SSL_CTX_set_cipher_list(ctx, args_map["-cipher"].c_str())) {
+ fprintf(stderr, "Failed setting cipher list\n");
+ return false;
+ }
+
+ int sock = -1;
+ if (!Accept(&sock, args_map["-accept"])) {
+ return false;
+ }
+
+ BIO *bio = BIO_new_socket(sock, BIO_CLOSE);
+ SSL *ssl = SSL_new(ctx);
+ SSL_set_bio(ssl, bio, bio);
+
+ int ret = SSL_accept(ssl);
+ if (ret != 1) {
+ int ssl_err = SSL_get_error(ssl, ret);
+ fprintf(stderr, "Error while connecting: %d\n", ssl_err);
+ ERR_print_errors_cb(PrintErrorCallback, stderr);
+ return false;
+ }
+
+ fprintf(stderr, "Connected.\n");
+ PrintConnectionInfo(ssl);
+
+ bool ok = TransferData(ssl, sock);
+
+ SSL_free(ssl);
+ SSL_CTX_free(ctx);
+ return ok;
+}
diff --git a/src/tool/speed.cc b/src/tool/speed.cc
new file mode 100644
index 0000000..2df6f90
--- /dev/null
+++ b/src/tool/speed.cc
@@ -0,0 +1,329 @@
+/* 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 <string>
+#include <functional>
+#include <memory>
+#include <vector>
+
+#include <stdint.h>
+#include <string.h>
+#include <time.h>
+
+#include <openssl/aead.h>
+#include <openssl/bio.h>
+#include <openssl/digest.h>
+#include <openssl/obj.h>
+#include <openssl/rsa.h>
+
+#if defined(OPENSSL_WINDOWS)
+#pragma warning(push, 3)
+#include <Windows.h>
+#pragma warning(pop)
+#elif defined(OPENSSL_APPLE)
+#include <sys/time.h>
+#endif
+
+
+extern "C" {
+// These values are DER encoded, RSA private keys.
+extern const uint8_t kDERRSAPrivate2048[];
+extern size_t kDERRSAPrivate2048Len;
+extern const uint8_t kDERRSAPrivate4096[];
+extern size_t kDERRSAPrivate4096Len;
+}
+
+// TimeResults represents the results of benchmarking a function.
+struct TimeResults {
+ // num_calls is the number of function calls done in the time period.
+ unsigned num_calls;
+ // us is the number of microseconds that elapsed in the time period.
+ unsigned us;
+
+ void Print(const std::string &description) {
+ printf("Did %u %s operations in %uus (%.1f ops/sec)\n", num_calls,
+ description.c_str(), us,
+ (static_cast<double>(num_calls) / us) * 1000000);
+ }
+
+ void PrintWithBytes(const std::string &description, size_t bytes_per_call) {
+ printf("Did %u %s operations in %uus (%.1f ops/sec): %.1f MB/s\n",
+ num_calls, description.c_str(), us,
+ (static_cast<double>(num_calls) / us) * 1000000,
+ static_cast<double>(bytes_per_call * num_calls) / us);
+ }
+};
+
+#if defined(OPENSSL_WINDOWS)
+static uint64_t time_now() { return GetTickCount64() * 1000; }
+#elif defined(OPENSSL_APPLE)
+static uint64_t time_now() {
+ struct timeval tv;
+ uint64_t ret;
+
+ gettimeofday(&tv, NULL);
+ ret = tv.tv_sec;
+ ret *= 1000000;
+ ret += tv.tv_usec;
+ return ret;
+}
+#else
+static uint64_t time_now() {
+ struct timespec ts;
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+
+ uint64_t ret = ts.tv_sec;
+ ret *= 1000000;
+ ret += ts.tv_nsec / 1000;
+ return ret;
+}
+#endif
+
+static bool TimeFunction(TimeResults *results, std::function<bool()> func) {
+ // kTotalMS is the total amount of time that we'll aim to measure a function
+ // for.
+ static const uint64_t kTotalUS = 3000000;
+ uint64_t start = time_now(), now, delta;
+ unsigned done = 0, iterations_between_time_checks;
+
+ if (!func()) {
+ return false;
+ }
+ now = time_now();
+ delta = now - start;
+ if (delta == 0) {
+ iterations_between_time_checks = 250;
+ } else {
+ // Aim for about 100ms between time checks.
+ iterations_between_time_checks =
+ static_cast<double>(100000) / static_cast<double>(delta);
+ if (iterations_between_time_checks > 1000) {
+ iterations_between_time_checks = 1000;
+ } else if (iterations_between_time_checks < 1) {
+ iterations_between_time_checks = 1;
+ }
+ }
+
+ for (;;) {
+ for (unsigned i = 0; i < iterations_between_time_checks; i++) {
+ if (!func()) {
+ return false;
+ }
+ done++;
+ }
+
+ now = time_now();
+ if (now - start > kTotalUS) {
+ break;
+ }
+ }
+
+ results->us = now - start;
+ results->num_calls = done;
+ return true;
+}
+
+static bool SpeedRSA(const std::string& key_name, RSA *key) {
+ TimeResults results;
+
+ std::unique_ptr<uint8_t[]> sig(new uint8_t[RSA_size(key)]);
+ const uint8_t fake_sha256_hash[32] = {0};
+ unsigned sig_len;
+
+ if (!TimeFunction(&results,
+ [key, &sig, &fake_sha256_hash, &sig_len]() -> bool {
+ return RSA_sign(NID_sha256, fake_sha256_hash, sizeof(fake_sha256_hash),
+ sig.get(), &sig_len, key);
+ })) {
+ fprintf(stderr, "RSA_sign failed.\n");
+ BIO_print_errors_fp(stderr);
+ return false;
+ }
+ results.Print(key_name + " signing");
+
+ if (!TimeFunction(&results,
+ [key, &fake_sha256_hash, &sig, sig_len]() -> bool {
+ return RSA_verify(NID_sha256, fake_sha256_hash,
+ sizeof(fake_sha256_hash), sig.get(), sig_len, key);
+ })) {
+ fprintf(stderr, "RSA_verify failed.\n");
+ BIO_print_errors_fp(stderr);
+ return false;
+ }
+ results.Print(key_name + " verify");
+
+ return true;
+}
+
+template<typename T>
+struct free_functor {
+ void operator()(T* ptr) {
+ free(ptr);
+ }
+};
+
+static uint8_t *align(uint8_t *in, unsigned alignment) {
+ return reinterpret_cast<uint8_t *>(
+ (reinterpret_cast<uintptr_t>(in) + alignment) & ~(alignment - 1));
+}
+
+static bool SpeedAEADChunk(const EVP_AEAD *aead, const std::string &name,
+ size_t chunk_len, size_t ad_len) {
+ static const unsigned kAlignment = 16;
+
+ EVP_AEAD_CTX ctx;
+ const size_t key_len = EVP_AEAD_key_length(aead);
+ const size_t nonce_len = EVP_AEAD_nonce_length(aead);
+ const size_t overhead_len = EVP_AEAD_max_overhead(aead);
+
+ std::unique_ptr<uint8_t[]> key(new uint8_t[key_len]);
+ memset(key.get(), 0, key_len);
+ std::unique_ptr<uint8_t[]> nonce(new uint8_t[nonce_len]);
+ memset(nonce.get(), 0, nonce_len);
+ std::unique_ptr<uint8_t, free_functor<uint8_t>> in_storage(
+ new uint8_t[chunk_len + kAlignment]);
+ std::unique_ptr<uint8_t, free_functor<uint8_t>> out_storage(
+ new uint8_t[chunk_len + overhead_len + kAlignment]);
+ std::unique_ptr<uint8_t[]> ad(new uint8_t[ad_len]);
+ memset(ad.get(), 0, ad_len);
+
+ uint8_t *const in = align(in_storage.get(), kAlignment);
+ memset(in, 0, chunk_len);
+ uint8_t *const out = align(out_storage.get(), kAlignment);
+ memset(out, 0, chunk_len + overhead_len);
+
+ if (!EVP_AEAD_CTX_init(&ctx, aead, key.get(), key_len,
+ EVP_AEAD_DEFAULT_TAG_LENGTH, NULL)) {
+ fprintf(stderr, "Failed to create EVP_AEAD_CTX.\n");
+ BIO_print_errors_fp(stderr);
+ return false;
+ }
+
+ TimeResults results;
+ if (!TimeFunction(&results, [chunk_len, overhead_len, nonce_len, ad_len, in,
+ out, &ctx, &nonce, &ad]() -> bool {
+ size_t out_len;
+
+ return EVP_AEAD_CTX_seal(
+ &ctx, out, &out_len, chunk_len + overhead_len, nonce.get(),
+ nonce_len, in, chunk_len, ad.get(), ad_len);
+ })) {
+ fprintf(stderr, "EVP_AEAD_CTX_seal failed.\n");
+ BIO_print_errors_fp(stderr);
+ return false;
+ }
+
+ results.PrintWithBytes(name + " seal", chunk_len);
+
+ EVP_AEAD_CTX_cleanup(&ctx);
+
+ return true;
+}
+
+static bool SpeedAEAD(const EVP_AEAD *aead, const std::string &name,
+ size_t ad_len) {
+ return SpeedAEADChunk(aead, name + " (16 bytes)", 16, ad_len) &&
+ SpeedAEADChunk(aead, name + " (1350 bytes)", 1350, ad_len) &&
+ SpeedAEADChunk(aead, name + " (8192 bytes)", 8192, ad_len);
+}
+
+static bool SpeedHashChunk(const EVP_MD *md, const std::string &name,
+ size_t chunk_len) {
+ EVP_MD_CTX *ctx = EVP_MD_CTX_create();
+ uint8_t scratch[8192];
+
+ if (chunk_len > sizeof(scratch)) {
+ return false;
+ }
+
+ TimeResults results;
+ if (!TimeFunction(&results, [ctx, md, chunk_len, &scratch]() -> bool {
+ uint8_t digest[EVP_MAX_MD_SIZE];
+ unsigned int md_len;
+
+ return EVP_DigestInit_ex(ctx, md, NULL /* ENGINE */) &&
+ EVP_DigestUpdate(ctx, scratch, chunk_len) &&
+ EVP_DigestFinal_ex(ctx, digest, &md_len);
+ })) {
+ fprintf(stderr, "EVP_DigestInit_ex failed.\n");
+ BIO_print_errors_fp(stderr);
+ return false;
+ }
+
+ results.PrintWithBytes(name, chunk_len);
+
+ EVP_MD_CTX_destroy(ctx);
+
+ return true;
+}
+static bool SpeedHash(const EVP_MD *md, const std::string &name) {
+ return SpeedHashChunk(md, name + " (16 bytes)", 16) &&
+ SpeedHashChunk(md, name + " (256 bytes)", 256) &&
+ SpeedHashChunk(md, name + " (8192 bytes)", 8192);
+}
+
+bool Speed(const std::vector<std::string> &args) {
+ const uint8_t *inp;
+
+ RSA *key = NULL;
+ inp = kDERRSAPrivate2048;
+ if (NULL == d2i_RSAPrivateKey(&key, &inp, kDERRSAPrivate2048Len)) {
+ fprintf(stderr, "Failed to parse RSA key.\n");
+ BIO_print_errors_fp(stderr);
+ return false;
+ }
+
+ if (!SpeedRSA("RSA 2048", key)) {
+ return false;
+ }
+
+ RSA_free(key);
+ key = NULL;
+
+ inp = kDERRSAPrivate4096;
+ if (NULL == d2i_RSAPrivateKey(&key, &inp, kDERRSAPrivate4096Len)) {
+ fprintf(stderr, "Failed to parse 4096-bit RSA key.\n");
+ BIO_print_errors_fp(stderr);
+ return 1;
+ }
+
+ if (!SpeedRSA("RSA 4096", key)) {
+ return false;
+ }
+
+ RSA_free(key);
+
+ // kTLSADLen is the number of bytes of additional data that TLS passes to
+ // AEADs.
+ static const size_t kTLSADLen = 13;
+ // kLegacyADLen is the number of bytes that TLS passes to the "legacy" AEADs.
+ // These are AEADs that weren't originally defined as AEADs, but which we use
+ // via the AEAD interface. In order for that to work, they have some TLS
+ // knowledge in them and construct a couple of the AD bytes internally.
+ static const size_t kLegacyADLen = kTLSADLen - 2;
+
+ if (!SpeedAEAD(EVP_aead_aes_128_gcm(), "AES-128-GCM", kTLSADLen) ||
+ !SpeedAEAD(EVP_aead_aes_256_gcm(), "AES-256-GCM", kTLSADLen) ||
+ !SpeedAEAD(EVP_aead_chacha20_poly1305(), "ChaCha20-Poly1305", kTLSADLen) ||
+ !SpeedAEAD(EVP_aead_rc4_md5_tls(), "RC4-MD5", kLegacyADLen) ||
+ !SpeedAEAD(EVP_aead_aes_128_cbc_sha1_tls(), "AES-128-CBC-SHA1", kLegacyADLen) ||
+ !SpeedAEAD(EVP_aead_aes_256_cbc_sha1_tls(), "AES-256-CBC-SHA1", kLegacyADLen) ||
+ !SpeedHash(EVP_sha1(), "SHA-1") ||
+ !SpeedHash(EVP_sha256(), "SHA-256") ||
+ !SpeedHash(EVP_sha512(), "SHA-512")) {
+ return false;
+ }
+
+ return 0;
+}
diff --git a/src/tool/tool.cc b/src/tool/tool.cc
new file mode 100644
index 0000000..36e3de9
--- /dev/null
+++ b/src/tool/tool.cc
@@ -0,0 +1,132 @@
+/* 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 <string>
+#include <vector>
+
+#include <openssl/err.h>
+#include <openssl/ssl.h>
+
+#if defined(OPENSSL_WINDOWS)
+#include <fcntl.h>
+#include <io.h>
+#else
+#include <libgen.h>
+#endif
+
+
+bool Client(const std::vector<std::string> &args);
+bool Server(const std::vector<std::string> &args);
+bool MD5Sum(const std::vector<std::string> &args);
+bool SHA1Sum(const std::vector<std::string> &args);
+bool SHA224Sum(const std::vector<std::string> &args);
+bool SHA256Sum(const std::vector<std::string> &args);
+bool SHA384Sum(const std::vector<std::string> &args);
+bool SHA512Sum(const std::vector<std::string> &args);
+bool DoPKCS12(const std::vector<std::string> &args);
+bool Speed(const std::vector<std::string> &args);
+
+typedef bool (*tool_func_t)(const std::vector<std::string> &args);
+
+struct Tool {
+ char name[16];
+ tool_func_t func;
+};
+
+static const Tool kTools[] = {
+ { "speed", Speed },
+ { "pkcs12", DoPKCS12 },
+ { "client", Client },
+ { "s_client", Client },
+ { "server", Server },
+ { "s_server", Server },
+ { "md5sum", MD5Sum },
+ { "sha1sum", SHA1Sum },
+ { "sha224sum", SHA224Sum },
+ { "sha256sum", SHA256Sum },
+ { "sha384sum", SHA384Sum },
+ { "sha512sum", SHA512Sum },
+ { "", nullptr },
+};
+
+static void usage(const char *name) {
+ printf("Usage: %s [", name);
+
+ for (size_t i = 0;; i++) {
+ const Tool &tool = kTools[i];
+ if (tool.func == nullptr) {
+ break;
+ }
+ if (i > 0) {
+ printf("|");
+ }
+ printf("%s", tool.name);
+ }
+ printf("]\n");
+}
+
+tool_func_t FindTool(const std::string &name) {
+ for (size_t i = 0;; i++) {
+ const Tool &tool = kTools[i];
+ if (tool.func == nullptr || name == tool.name) {
+ return tool.func;
+ }
+ }
+}
+
+int main(int argc, char **argv) {
+#if defined(OPENSSL_WINDOWS)
+ // Read and write in binary mode. This makes bssl on Windows consistent with
+ // bssl on other platforms, and also makes it consistent with MSYS's commands
+ // like diff(1) and md5sum(1). This is especially important for the digest
+ // commands.
+ if (_setmode(_fileno(stdin), _O_BINARY) == -1) {
+ perror("_setmode(_fileno(stdin), O_BINARY)");
+ return 1;
+ }
+ if (_setmode(_fileno(stdout), _O_BINARY) == -1) {
+ perror("_setmode(_fileno(stdout), O_BINARY)");
+ return 1;
+ }
+ if (_setmode(_fileno(stderr), _O_BINARY) == -1) {
+ perror("_setmode(_fileno(stderr), O_BINARY)");
+ return 1;
+ }
+#endif
+
+ SSL_library_init();
+
+ int starting_arg = 1;
+ tool_func_t tool = nullptr;
+#if !defined(OPENSSL_WINDOWS)
+ tool = FindTool(basename(argv[0]));
+#endif
+ if (tool == nullptr) {
+ starting_arg++;
+ if (argc > 1) {
+ tool = FindTool(argv[1]);
+ }
+ }
+ if (tool == nullptr) {
+ usage(argv[0]);
+ return 1;
+ }
+
+ std::vector<std::string> args;
+ for (int i = starting_arg; i < argc; i++) {
+ args.push_back(argv[i]);
+ }
+
+ return !tool(args);
+}
diff --git a/src/tool/transport_common.cc b/src/tool/transport_common.cc
new file mode 100644
index 0000000..c05742e
--- /dev/null
+++ b/src/tool/transport_common.cc
@@ -0,0 +1,298 @@
+/* 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 <openssl/base.h>
+
+#include <string>
+#include <vector>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#if !defined(OPENSSL_WINDOWS)
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <sys/select.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#else
+#define NOMINMAX
+#include <io.h>
+#pragma warning(push, 3)
+#include <WinSock2.h>
+#include <WS2tcpip.h>
+#pragma warning(pop)
+
+typedef int ssize_t;
+#pragma comment(lib, "Ws2_32.lib")
+#endif
+
+#include <openssl/err.h>
+#include <openssl/ssl.h>
+
+#include "internal.h"
+
+
+#if !defined(OPENSSL_WINDOWS)
+static int closesocket(int sock) {
+ return close(sock);
+}
+#endif
+
+bool InitSocketLibrary() {
+#if defined(OPENSSL_WINDOWS)
+ WSADATA wsaData;
+ int err = WSAStartup(MAKEWORD(2, 2), &wsaData);
+ if (err != 0) {
+ fprintf(stderr, "WSAStartup failed with error %d\n", err);
+ return false;
+ }
+#endif
+ return true;
+}
+
+// Connect sets |*out_sock| to be a socket connected to the destination given
+// in |hostname_and_port|, which should be of the form "www.example.com:123".
+// It returns true on success and false otherwise.
+bool Connect(int *out_sock, const std::string &hostname_and_port) {
+ const size_t colon_offset = hostname_and_port.find_last_of(':');
+ std::string hostname, port;
+
+ if (colon_offset == std::string::npos) {
+ hostname = hostname_and_port;
+ port = "443";
+ } else {
+ hostname = hostname_and_port.substr(0, colon_offset);
+ port = hostname_and_port.substr(colon_offset + 1);
+ }
+
+ struct addrinfo hint, *result;
+ memset(&hint, 0, sizeof(hint));
+ hint.ai_family = AF_UNSPEC;
+ hint.ai_socktype = SOCK_STREAM;
+
+ int ret = getaddrinfo(hostname.c_str(), port.c_str(), &hint, &result);
+ if (ret != 0) {
+ fprintf(stderr, "getaddrinfo returned: %s\n", gai_strerror(ret));
+ return false;
+ }
+
+ bool ok = false;
+ char buf[256];
+
+ *out_sock =
+ socket(result->ai_family, result->ai_socktype, result->ai_protocol);
+ if (*out_sock < 0) {
+ perror("socket");
+ goto out;
+ }
+
+ switch (result->ai_family) {
+ case AF_INET: {
+ struct sockaddr_in *sin =
+ reinterpret_cast<struct sockaddr_in *>(result->ai_addr);
+ fprintf(stderr, "Connecting to %s:%d\n",
+ inet_ntop(result->ai_family, &sin->sin_addr, buf, sizeof(buf)),
+ ntohs(sin->sin_port));
+ break;
+ }
+ case AF_INET6: {
+ struct sockaddr_in6 *sin6 =
+ reinterpret_cast<struct sockaddr_in6 *>(result->ai_addr);
+ fprintf(stderr, "Connecting to [%s]:%d\n",
+ inet_ntop(result->ai_family, &sin6->sin6_addr, buf, sizeof(buf)),
+ ntohs(sin6->sin6_port));
+ break;
+ }
+ }
+
+ if (connect(*out_sock, result->ai_addr, result->ai_addrlen) != 0) {
+ perror("connect");
+ goto out;
+ }
+ ok = true;
+
+out:
+ freeaddrinfo(result);
+ return ok;
+}
+
+bool Accept(int *out_sock, const std::string &port) {
+ struct sockaddr_in addr, cli_addr;
+ socklen_t cli_addr_len = sizeof(cli_addr);
+ memset(&addr, 0, sizeof(addr));
+
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = INADDR_ANY;
+ addr.sin_port = htons(atoi(port.c_str()));
+
+ bool ok = false;
+ int server_sock = -1;
+
+ server_sock =
+ socket(addr.sin_family, SOCK_STREAM, 0);
+ if (server_sock < 0) {
+ perror("socket");
+ goto out;
+ }
+
+ if (bind(server_sock, (struct sockaddr*)&addr, sizeof(addr)) != 0) {
+ perror("connect");
+ goto out;
+ }
+ listen(server_sock, 1);
+ *out_sock = accept(server_sock, (struct sockaddr*)&cli_addr, &cli_addr_len);
+
+ ok = true;
+
+out:
+ closesocket(server_sock);
+ return ok;
+}
+
+void PrintConnectionInfo(const SSL *ssl) {
+ const SSL_CIPHER *cipher = SSL_get_current_cipher(ssl);
+
+ fprintf(stderr, " Version: %s\n", SSL_get_version(ssl));
+ fprintf(stderr, " Cipher: %s\n", SSL_CIPHER_get_name(cipher));
+ fprintf(stderr, " Secure renegotiation: %s\n",
+ SSL_get_secure_renegotiation_support(ssl) ? "yes" : "no");
+}
+
+bool SocketSetNonBlocking(int sock, bool is_non_blocking) {
+ bool ok;
+
+#if defined(OPENSSL_WINDOWS)
+ u_long arg = is_non_blocking;
+ ok = 0 == ioctlsocket(sock, FIONBIO, &arg);
+#else
+ int flags = fcntl(sock, F_GETFL, 0);
+ if (flags < 0) {
+ return false;
+ }
+ if (is_non_blocking) {
+ flags |= O_NONBLOCK;
+ } else {
+ flags &= ~O_NONBLOCK;
+ }
+ ok = 0 == fcntl(sock, F_SETFL, flags);
+#endif
+ if (!ok) {
+ fprintf(stderr, "Failed to set socket non-blocking.\n");
+ }
+ return ok;
+}
+
+// PrintErrorCallback is a callback function from OpenSSL's
+// |ERR_print_errors_cb| that writes errors to a given |FILE*|.
+int PrintErrorCallback(const char *str, size_t len, void *ctx) {
+ fwrite(str, len, 1, reinterpret_cast<FILE*>(ctx));
+ return 1;
+}
+
+bool TransferData(SSL *ssl, int sock) {
+ bool stdin_open = true;
+
+ fd_set read_fds;
+ FD_ZERO(&read_fds);
+
+ if (!SocketSetNonBlocking(sock, true)) {
+ return false;
+ }
+
+ for (;;) {
+ if (stdin_open) {
+ FD_SET(0, &read_fds);
+ }
+ FD_SET(sock, &read_fds);
+
+ int ret = select(sock + 1, &read_fds, NULL, NULL, NULL);
+ if (ret <= 0) {
+ perror("select");
+ return false;
+ }
+
+ if (FD_ISSET(0, &read_fds)) {
+ uint8_t buffer[512];
+ ssize_t n;
+
+ do {
+ n = read(0, buffer, sizeof(buffer));
+ } while (n == -1 && errno == EINTR);
+
+ if (n == 0) {
+ FD_CLR(0, &read_fds);
+ stdin_open = false;
+#if !defined(OPENSSL_WINDOWS)
+ shutdown(sock, SHUT_WR);
+#else
+ shutdown(sock, SD_SEND);
+#endif
+ continue;
+ } else if (n < 0) {
+ perror("read from stdin");
+ return false;
+ }
+
+ if (!SocketSetNonBlocking(sock, false)) {
+ return false;
+ }
+ int ssl_ret = SSL_write(ssl, buffer, n);
+ if (!SocketSetNonBlocking(sock, true)) {
+ return false;
+ }
+
+ if (ssl_ret <= 0) {
+ int ssl_err = SSL_get_error(ssl, ssl_ret);
+ fprintf(stderr, "Error while writing: %d\n", ssl_err);
+ ERR_print_errors_cb(PrintErrorCallback, stderr);
+ return false;
+ } else if (ssl_ret != n) {
+ fprintf(stderr, "Short write from SSL_write.\n");
+ return false;
+ }
+ }
+
+ if (FD_ISSET(sock, &read_fds)) {
+ uint8_t buffer[512];
+ int ssl_ret = SSL_read(ssl, buffer, sizeof(buffer));
+
+ if (ssl_ret < 0) {
+ int ssl_err = SSL_get_error(ssl, ssl_ret);
+ if (ssl_err == SSL_ERROR_WANT_READ) {
+ continue;
+ }
+ fprintf(stderr, "Error while reading: %d\n", ssl_err);
+ ERR_print_errors_cb(PrintErrorCallback, stderr);
+ return false;
+ } else if (ssl_ret == 0) {
+ return true;
+ }
+
+ ssize_t n;
+ do {
+ n = write(1, buffer, ssl_ret);
+ } while (n == -1 && errno == EINTR);
+
+ if (n != ssl_ret) {
+ fprintf(stderr, "Short write to stderr.\n");
+ return false;
+ }
+ }
+ }
+}
diff --git a/src/tool/transport_common.h b/src/tool/transport_common.h
new file mode 100644
index 0000000..b701015
--- /dev/null
+++ b/src/tool/transport_common.h
@@ -0,0 +1,43 @@
+/* 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_TOOL_TRANSPORT_COMMON_H
+#define OPENSSL_HEADER_TOOL_TRANSPORT_COMMON_H
+
+#include <openssl/ssl.h>
+#include <string.h>
+
+// InitSocketLibrary calls the Windows socket init functions, if needed.
+bool InitSocketLibrary();
+
+// Connect sets |*out_sock| to be a socket connected to the destination given
+// in |hostname_and_port|, which should be of the form "www.example.com:123".
+// It returns true on success and false otherwise.
+bool Connect(int *out_sock, const std::string &hostname_and_port);
+
+// Accept sets |*out_sock| to be a socket connected to the port given
+// in |port|, which should be of the form "123".
+// It returns true on success and false otherwise.
+bool Accept(int *out_sock, const std::string &port);
+
+void PrintConnectionInfo(const SSL *ssl);
+
+bool SocketSetNonBlocking(int sock, bool is_non_blocking);
+
+int PrintErrorCallback(const char *str, size_t len, void *ctx);
+
+bool TransferData(SSL *ssl, int sock);
+
+
+#endif /* !OPENSSL_HEADER_TOOL_TRANSPORT_COMMON_H */
diff --git a/src/util/32-bit-toolchain.cmake b/src/util/32-bit-toolchain.cmake
new file mode 100644
index 0000000..f3a10b7
--- /dev/null
+++ b/src/util/32-bit-toolchain.cmake
@@ -0,0 +1,7 @@
+set(CMAKE_SYSTEM_NAME Linux)
+set(CMAKE_SYSTEM_VERSION 1)
+set(CMAKE_SYSTEM_PROCESSOR "x86")
+
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32 -msse2" CACHE STRING "c++ flags")
+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32 -msse2" CACHE STRING "c flags")
+set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -m32 -msse2" CACHE STRING "asm flags")
diff --git a/src/util/aarch64-toolchain.cmake b/src/util/aarch64-toolchain.cmake
new file mode 100644
index 0000000..77f33ab
--- /dev/null
+++ b/src/util/aarch64-toolchain.cmake
@@ -0,0 +1,6 @@
+set(CMAKE_SYSTEM_NAME Linux)
+set(CMAKE_SYSTEM_VERSION 1)
+set(CMAKE_SYSTEM_PROCESSOR "aarch64")
+set(CMAKE_CXX_COMPILER "/opt/gcc-linaro-4.9-2014.11-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-g++")
+set(CMAKE_C_COMPILER "/opt/gcc-linaro-4.9-2014.11-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc")
+set(CMAKE_EXE_LINKER_FLAGS "-static")
diff --git a/src/util/all_tests.sh b/src/util/all_tests.sh
new file mode 100644
index 0000000..bcb5c24
--- /dev/null
+++ b/src/util/all_tests.sh
@@ -0,0 +1,85 @@
+#!/usr/bin/env bash
+
+# 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. */
+
+SRC=..
+if [ "$#" -ge 1 ]; then
+ SRC=$1
+fi
+
+TESTS="
+./crypto/base64/base64_test
+./crypto/bio/bio_test
+./crypto/bn/bn_test
+./crypto/bytestring/bytestring_test
+./crypto/cipher/aead_test aes-128-gcm $SRC/crypto/cipher/test/aes_128_gcm_tests.txt
+./crypto/cipher/aead_test aes-128-key-wrap $SRC/crypto/cipher/test/aes_128_key_wrap_tests.txt
+./crypto/cipher/aead_test aes-256-gcm $SRC/crypto/cipher/test/aes_256_gcm_tests.txt
+./crypto/cipher/aead_test aes-256-key-wrap $SRC/crypto/cipher/test/aes_256_key_wrap_tests.txt
+./crypto/cipher/aead_test chacha20-poly1305 $SRC/crypto/cipher/test/chacha20_poly1305_tests.txt
+./crypto/cipher/aead_test rc4-md5-tls $SRC/crypto/cipher/test/rc4_md5_tls_tests.txt
+./crypto/cipher/aead_test rc4-sha1-tls $SRC/crypto/cipher/test/rc4_sha1_tls_tests.txt
+./crypto/cipher/aead_test aes-128-cbc-sha1-tls $SRC/crypto/cipher/test/aes_128_cbc_sha1_tls_tests.txt
+./crypto/cipher/aead_test aes-128-cbc-sha1-tls-implicit-iv $SRC/crypto/cipher/test/aes_128_cbc_sha1_tls_implicit_iv_tests.txt
+./crypto/cipher/aead_test aes-128-cbc-sha256-tls $SRC/crypto/cipher/test/aes_128_cbc_sha256_tls_tests.txt
+./crypto/cipher/aead_test aes-256-cbc-sha1-tls $SRC/crypto/cipher/test/aes_256_cbc_sha1_tls_tests.txt
+./crypto/cipher/aead_test aes-256-cbc-sha1-tls-implicit-iv $SRC/crypto/cipher/test/aes_256_cbc_sha1_tls_implicit_iv_tests.txt
+./crypto/cipher/aead_test aes-256-cbc-sha256-tls $SRC/crypto/cipher/test/aes_256_cbc_sha256_tls_tests.txt
+./crypto/cipher/aead_test aes-256-cbc-sha384-tls $SRC/crypto/cipher/test/aes_256_cbc_sha384_tls_tests.txt
+./crypto/cipher/aead_test des-ede3-cbc-sha1-tls $SRC/crypto/cipher/test/des_ede3_cbc_sha1_tls_tests.txt
+./crypto/cipher/aead_test des-ede3-cbc-sha1-tls-implicit-iv $SRC/crypto/cipher/test/des_ede3_cbc_sha1_tls_implicit_iv_tests.txt
+./crypto/cipher/aead_test rc4-md5-ssl3 $SRC/crypto/cipher/test/rc4_md5_ssl3_tests.txt
+./crypto/cipher/aead_test rc4-sha1-ssl3 $SRC/crypto/cipher/test/rc4_sha1_ssl3_tests.txt
+./crypto/cipher/aead_test aes-128-cbc-sha1-ssl3 $SRC/crypto/cipher/test/aes_128_cbc_sha1_ssl3_tests.txt
+./crypto/cipher/aead_test aes-256-cbc-sha1-ssl3 $SRC/crypto/cipher/test/aes_256_cbc_sha1_ssl3_tests.txt
+./crypto/cipher/aead_test des-ede3-cbc-sha1-ssl3 $SRC/crypto/cipher/test/des_ede3_cbc_sha1_ssl3_tests.txt
+./crypto/cipher/cipher_test $SRC/crypto/cipher/test/cipher_test.txt
+./crypto/constant_time_test
+./crypto/dh/dh_test
+./crypto/digest/digest_test
+./crypto/dsa/dsa_test
+./crypto/ec/ec_test
+./crypto/ec/example_mul
+./crypto/ecdsa/ecdsa_test
+./crypto/err/err_test
+./crypto/evp/evp_test
+./crypto/evp/pbkdf_test
+./crypto/hkdf/hkdf_test
+./crypto/hmac/hmac_test
+./crypto/lhash/lhash_test
+./crypto/modes/gcm_test
+./crypto/pkcs8/pkcs12_test
+./crypto/rsa/rsa_test
+./crypto/x509/pkcs7_test
+./crypto/x509v3/tab_test
+./crypto/x509v3/v3name_test
+./ssl/pqueue/pqueue_test
+./ssl/ssl_test
+"
+
+IFS=$'\n'
+for bin in $TESTS; do
+ echo $bin
+ out=$(bash -c "$bin" | tail -n 1)
+ if [ $? -ne 0 ]; then
+ echo $bin failed to complete.
+ exit 1
+ fi
+
+ if [ "x$out" != "xPASS" ]; then
+ echo $bin failed to print PASS on the last line.
+ exit 1
+ fi
+done
diff --git a/src/util/arm-toolchain.cmake b/src/util/arm-toolchain.cmake
new file mode 100644
index 0000000..2dfd2bd
--- /dev/null
+++ b/src/util/arm-toolchain.cmake
@@ -0,0 +1,6 @@
+set(CMAKE_SYSTEM_NAME Linux)
+set(CMAKE_SYSTEM_VERSION 1)
+set(CMAKE_SYSTEM_PROCESSOR "arm")
+set(CMAKE_CXX_COMPILER "/opt/gcc-linaro-4.9-2014.11-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-g++")
+set(CMAKE_C_COMPILER "/opt/gcc-linaro-4.9-2014.11-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc")
+set(CMAKE_EXE_LINKER_FLAGS "-static")
diff --git a/src/util/clang-toolchain.cmake b/src/util/clang-toolchain.cmake
new file mode 100644
index 0000000..8d81379
--- /dev/null
+++ b/src/util/clang-toolchain.cmake
@@ -0,0 +1,2 @@
+set(CMAKE_CXX_COMPILER "/agl/chromium/src/third_party/llvm-build/Release+Asserts/bin/clang++")
+set(CMAKE_C_COMPILER "/agl/chromium/src/third_party/llvm-build/Release+Asserts/bin/clang")
diff --git a/src/util/doc.config b/src/util/doc.config
new file mode 100644
index 0000000..62db0f3
--- /dev/null
+++ b/src/util/doc.config
@@ -0,0 +1,49 @@
+{
+ "BaseDirectory": "..",
+ "Sections": [{
+ "Name": "Low-level infrastructure",
+ "Headers": [
+ "include/openssl/base64.h",
+ "include/openssl/bio.h",
+ "include/openssl/buf.h",
+ "include/openssl/bytestring.h",
+ "include/openssl/err.h",
+ "include/openssl/cpu.h",
+ "include/openssl/ex_data.h",
+ "include/openssl/lhash.h",
+ "include/openssl/mem.h",
+ "include/openssl/obj.h",
+ "include/openssl/stack.h",
+ "include/openssl/thread.h",
+ "include/openssl/time_support.h"
+ ]
+ },{
+ "Name": "Low-level crypto primitives",
+ "Headers": [
+ "include/openssl/aes.h",
+ "include/openssl/bn.h",
+ "include/openssl/des.h",
+ "include/openssl/dh.h",
+ "include/openssl/dsa.h",
+ "include/openssl/ec.h",
+ "include/openssl/ec_key.h",
+ "include/openssl/ecdh.h",
+ "include/openssl/ecdsa.h",
+ "include/openssl/engine.h",
+ "include/openssl/hmac.h",
+ "include/openssl/md5.h",
+ "include/openssl/modes.h",
+ "include/openssl/rc4.h",
+ "include/openssl/rsa.h",
+ "include/openssl/sha.h"
+ ]
+ },{
+ "Name": "Crypto interfaces",
+ "Headers": [
+ "include/openssl/digest.h",
+ "include/openssl/cipher.h",
+ "include/openssl/aead.h",
+ "include/openssl/evp.h"
+ ]
+ }]
+}
diff --git a/src/util/doc.css b/src/util/doc.css
new file mode 100644
index 0000000..ab653e4
--- /dev/null
+++ b/src/util/doc.css
@@ -0,0 +1,67 @@
+#main {
+ margin-left: auto;
+ margin-right: auto;
+ max-width: 55em;
+ text-align: justify;
+}
+
+h2 {
+ font-family: monospace;
+ margin-bottom: 2em;
+ background-color: #b2c9db;
+ padding: 7px;
+ border-radius: 7px;
+}
+
+ol {
+ list-style: none;
+ margin-bottom: 4em;
+}
+
+li a {
+ color: black;
+}
+
+li.header {
+ margin-top: 1em;
+ margin-bottom: 0.3em;
+ font-weight: bold;
+}
+
+div.decl p:first-child {
+ margin-top: 2.5em;
+}
+
+div.decl p:first-child .first-word {
+ font-weight: bold;
+ font-family: monospace;
+}
+
+.sectionpreamble {
+ margin-top: 5em;
+}
+
+.sectionpreamble p:first-child {
+ font-weight: bold;
+ font-size: 1.5em;
+}
+
+.section pre {
+ background-color: #b2c9db;
+ padding: 5px;
+ border-radius: 5px;
+}
+
+td {
+ padding: 2px;
+}
+
+tr:nth-child(even) {
+ background-color: #eee;
+}
+
+tr.header td {
+ font-weight: bold;
+ padding-top: 1em;
+ padding-bottom: 0.5em;
+}
diff --git a/src/util/doc.go b/src/util/doc.go
new file mode 100644
index 0000000..7c96af8
--- /dev/null
+++ b/src/util/doc.go
@@ -0,0 +1,623 @@
+// doc generates HTML files from the comments in header files.
+//
+// doc expects to be given the path to a JSON file via the --config option.
+// From that JSON (which is defined by the Config struct) it reads a list of
+// header file locations and generates HTML files for each in the current
+// directory.
+
+package main
+
+import (
+ "bufio"
+ "encoding/json"
+ "errors"
+ "flag"
+ "fmt"
+ "html/template"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "strings"
+)
+
+// Config describes the structure of the config JSON file.
+type Config struct {
+ // BaseDirectory is a path to which other paths in the file are
+ // relative.
+ BaseDirectory string
+ Sections []ConfigSection
+}
+
+type ConfigSection struct {
+ Name string
+ // Headers is a list of paths to header files.
+ Headers []string
+}
+
+// HeaderFile is the internal representation of a header file.
+type HeaderFile struct {
+ // Name is the basename of the header file (e.g. "ex_data.html").
+ Name string
+ // Preamble contains a comment for the file as a whole. Each string
+ // is a separate paragraph.
+ Preamble []string
+ Sections []HeaderSection
+}
+
+type HeaderSection struct {
+ // Preamble contains a comment for a group of functions.
+ Preamble []string
+ Decls []HeaderDecl
+ // Num is just the index of the section. It's included in order to help
+ // text/template generate anchors.
+ Num int
+ // IsPrivate is true if the section contains private functions (as
+ // indicated by its name).
+ IsPrivate bool
+}
+
+type HeaderDecl struct {
+ // Comment contains a comment for a specific function. Each string is a
+ // paragraph. Some paragraph may contain \n runes to indicate that they
+ // are preformatted.
+ Comment []string
+ // Name contains the name of the function, if it could be extracted.
+ Name string
+ // Decl contains the preformatted C declaration itself.
+ Decl string
+ // Num is an index for the declaration, but the value is unique for all
+ // declarations in a HeaderFile. It's included in order to help
+ // text/template generate anchors.
+ Num int
+}
+
+const (
+ cppGuard = "#if defined(__cplusplus)"
+ commentStart = "/* "
+ commentEnd = " */"
+)
+
+func extractComment(lines []string, lineNo int) (comment []string, rest []string, restLineNo int, err error) {
+ if len(lines) == 0 {
+ return nil, lines, lineNo, nil
+ }
+
+ restLineNo = lineNo
+ rest = lines
+
+ if !strings.HasPrefix(rest[0], commentStart) {
+ panic("extractComment called on non-comment")
+ }
+ commentParagraph := rest[0][len(commentStart):]
+ rest = rest[1:]
+ restLineNo++
+
+ for len(rest) > 0 {
+ i := strings.Index(commentParagraph, commentEnd)
+ if i >= 0 {
+ if i != len(commentParagraph)-len(commentEnd) {
+ err = fmt.Errorf("garbage after comment end on line %d", restLineNo)
+ return
+ }
+ commentParagraph = commentParagraph[:i]
+ if len(commentParagraph) > 0 {
+ comment = append(comment, commentParagraph)
+ }
+ return
+ }
+
+ line := rest[0]
+ if !strings.HasPrefix(line, " *") {
+ err = fmt.Errorf("comment doesn't start with block prefix on line %d: %s", restLineNo, line)
+ return
+ }
+ line = line[2:]
+ if strings.HasPrefix(line, " ") {
+ /* Identing the lines of a paragraph marks them as
+ * preformatted. */
+ if len(commentParagraph) > 0 {
+ commentParagraph += "\n"
+ }
+ line = line[3:]
+ }
+ if len(line) > 0 {
+ commentParagraph = commentParagraph + line
+ if len(commentParagraph) > 0 && commentParagraph[0] == ' ' {
+ commentParagraph = commentParagraph[1:]
+ }
+ } else {
+ comment = append(comment, commentParagraph)
+ commentParagraph = ""
+ }
+ rest = rest[1:]
+ restLineNo++
+ }
+
+ err = errors.New("hit EOF in comment")
+ return
+}
+
+func extractDecl(lines []string, lineNo int) (decl string, rest []string, restLineNo int, err error) {
+ if len(lines) == 0 {
+ return "", lines, lineNo, nil
+ }
+
+ rest = lines
+ restLineNo = lineNo
+
+ var stack []rune
+ for len(rest) > 0 {
+ line := rest[0]
+ for _, c := range line {
+ switch c {
+ case '(', '{', '[':
+ stack = append(stack, c)
+ case ')', '}', ']':
+ if len(stack) == 0 {
+ err = fmt.Errorf("unexpected %c on line %d", c, restLineNo)
+ return
+ }
+ var expected rune
+ switch c {
+ case ')':
+ expected = '('
+ case '}':
+ expected = '{'
+ case ']':
+ expected = '['
+ default:
+ panic("internal error")
+ }
+ if last := stack[len(stack)-1]; last != expected {
+ err = fmt.Errorf("found %c when expecting %c on line %d", c, last, restLineNo)
+ return
+ }
+ stack = stack[:len(stack)-1]
+ }
+ }
+ if len(decl) > 0 {
+ decl += "\n"
+ }
+ decl += line
+ rest = rest[1:]
+ restLineNo++
+
+ if len(stack) == 0 && (len(decl) == 0 || decl[len(decl)-1] != '\\') {
+ break
+ }
+ }
+
+ return
+}
+
+func skipPast(s, skip string) string {
+ i := strings.Index(s, skip)
+ if i > 0 {
+ return s[len(skip):]
+ }
+ return s
+}
+
+func getNameFromDecl(decl string) (string, bool) {
+ if strings.HasPrefix(decl, "struct ") {
+ return "", false
+ }
+ decl = skipPast(decl, "STACK_OF(")
+ decl = skipPast(decl, "LHASH_OF(")
+ i := strings.Index(decl, "(")
+ if i < 0 {
+ return "", false
+ }
+ j := strings.LastIndex(decl[:i], " ")
+ if j < 0 {
+ return "", false
+ }
+ for j+1 < len(decl) && decl[j+1] == '*' {
+ j++
+ }
+ return decl[j+1 : i], true
+}
+
+func (config *Config) parseHeader(path string) (*HeaderFile, error) {
+ headerPath := filepath.Join(config.BaseDirectory, path)
+
+ headerFile, err := os.Open(headerPath)
+ if err != nil {
+ return nil, err
+ }
+ defer headerFile.Close()
+
+ scanner := bufio.NewScanner(headerFile)
+ var lines, oldLines []string
+ for scanner.Scan() {
+ lines = append(lines, scanner.Text())
+ }
+ if err := scanner.Err(); err != nil {
+ return nil, err
+ }
+
+ lineNo := 0
+ found := false
+ for i, line := range lines {
+ lineNo++
+ if line == cppGuard {
+ lines = lines[i+1:]
+ lineNo++
+ found = true
+ break
+ }
+ }
+
+ if !found {
+ return nil, errors.New("no C++ guard found")
+ }
+
+ if len(lines) == 0 || lines[0] != "extern \"C\" {" {
+ return nil, errors.New("no extern \"C\" found after C++ guard")
+ }
+ lineNo += 2
+ lines = lines[2:]
+
+ header := &HeaderFile{
+ Name: filepath.Base(path),
+ }
+
+ for i, line := range lines {
+ lineNo++
+ if len(line) > 0 {
+ lines = lines[i:]
+ break
+ }
+ }
+
+ oldLines = lines
+ if len(lines) > 0 && strings.HasPrefix(lines[0], commentStart) {
+ comment, rest, restLineNo, err := extractComment(lines, lineNo)
+ if err != nil {
+ return nil, err
+ }
+
+ if len(rest) > 0 && len(rest[0]) == 0 {
+ if len(rest) < 2 || len(rest[1]) != 0 {
+ return nil, errors.New("preamble comment should be followed by two blank lines")
+ }
+ header.Preamble = comment
+ lineNo = restLineNo + 2
+ lines = rest[2:]
+ } else {
+ lines = oldLines
+ }
+ }
+
+ var sectionNumber, declNumber int
+
+ for {
+ // Start of a section.
+ if len(lines) == 0 {
+ return nil, errors.New("unexpected end of file")
+ }
+ line := lines[0]
+ if line == cppGuard {
+ break
+ }
+
+ if len(line) == 0 {
+ return nil, fmt.Errorf("blank line at start of section on line %d", lineNo)
+ }
+
+ section := HeaderSection{
+ Num: sectionNumber,
+ }
+ sectionNumber++
+
+ if strings.HasPrefix(line, commentStart) {
+ comment, rest, restLineNo, err := extractComment(lines, lineNo)
+ if err != nil {
+ return nil, err
+ }
+ if len(rest) > 0 && len(rest[0]) == 0 {
+ section.Preamble = comment
+ section.IsPrivate = len(comment) > 0 && strings.HasPrefix(comment[0], "Private functions")
+ lines = rest[1:]
+ lineNo = restLineNo + 1
+ }
+ }
+
+ for len(lines) > 0 {
+ line := lines[0]
+ if len(line) == 0 {
+ lines = lines[1:]
+ lineNo++
+ break
+ }
+ if line == cppGuard {
+ return nil, errors.New("hit ending C++ guard while in section")
+ }
+
+ var comment []string
+ var decl string
+ if strings.HasPrefix(line, commentStart) {
+ comment, lines, lineNo, err = extractComment(lines, lineNo)
+ if err != nil {
+ return nil, err
+ }
+ }
+ if len(lines) == 0 {
+ return nil, errors.New("expected decl at EOF")
+ }
+ decl, lines, lineNo, err = extractDecl(lines, lineNo)
+ if err != nil {
+ return nil, err
+ }
+ name, ok := getNameFromDecl(decl)
+ if !ok {
+ name = ""
+ }
+ if last := len(section.Decls) - 1; len(name) == 0 && len(comment) == 0 && last >= 0 {
+ section.Decls[last].Decl += "\n" + decl
+ } else {
+ section.Decls = append(section.Decls, HeaderDecl{
+ Comment: comment,
+ Name: name,
+ Decl: decl,
+ Num: declNumber,
+ })
+ declNumber++
+ }
+
+ if len(lines) > 0 && len(lines[0]) == 0 {
+ lines = lines[1:]
+ lineNo++
+ }
+ }
+
+ header.Sections = append(header.Sections, section)
+ }
+
+ return header, nil
+}
+
+func firstSentence(paragraphs []string) string {
+ if len(paragraphs) == 0 {
+ return ""
+ }
+ s := paragraphs[0]
+ i := strings.Index(s, ". ")
+ if i >= 0 {
+ return s[:i]
+ }
+ if lastIndex := len(s) - 1; s[lastIndex] == '.' {
+ return s[:lastIndex]
+ }
+ return s
+}
+
+func markupPipeWords(s string) template.HTML {
+ ret := ""
+
+ for {
+ i := strings.Index(s, "|")
+ if i == -1 {
+ ret += s
+ break
+ }
+ ret += s[:i]
+ s = s[i+1:]
+
+ i = strings.Index(s, "|")
+ j := strings.Index(s, " ")
+ if i > 0 && (j == -1 || j > i) {
+ ret += "<tt>"
+ ret += s[:i]
+ ret += "</tt>"
+ s = s[i+1:]
+ } else {
+ ret += "|"
+ }
+ }
+
+ return template.HTML(ret)
+}
+
+func markupFirstWord(s template.HTML) template.HTML {
+ start := 0
+again:
+ end := strings.Index(string(s[start:]), " ")
+ if end > 0 {
+ end += start
+ w := strings.ToLower(string(s[start:end]))
+ if w == "a" || w == "an" || w == "deprecated:" {
+ start = end + 1
+ goto again
+ }
+ return s[:start] + "<span class=\"first-word\">" + s[start:end] + "</span>" + s[end:]
+ }
+ return s
+}
+
+func newlinesToBR(html template.HTML) template.HTML {
+ s := string(html)
+ if !strings.Contains(s, "\n") {
+ return html
+ }
+ s = strings.Replace(s, "\n", "<br>", -1)
+ s = strings.Replace(s, " ", "&nbsp;", -1)
+ return template.HTML(s)
+}
+
+func generate(outPath string, config *Config) (map[string]string, error) {
+ headerTmpl := template.New("headerTmpl")
+ headerTmpl.Funcs(template.FuncMap{
+ "firstSentence": firstSentence,
+ "markupPipeWords": markupPipeWords,
+ "markupFirstWord": markupFirstWord,
+ "newlinesToBR": newlinesToBR,
+ })
+ headerTmpl, err := headerTmpl.Parse(`<!DOCTYPE html>
+<html>
+ <head>
+ <title>BoringSSL - {{.Name}}</title>
+ <meta charset="utf-8">
+ <link rel="stylesheet" type="text/css" href="doc.css">
+ </head>
+
+ <body>
+ <div id="main">
+ <h2>{{.Name}}</h2>
+
+ {{range .Preamble}}<p>{{. | html | markupPipeWords}}</p>{{end}}
+
+ <ol>
+ {{range .Sections}}
+ {{if not .IsPrivate}}
+ {{if .Preamble}}<li class="header"><a href="#section-{{.Num}}">{{.Preamble | firstSentence | html | markupPipeWords}}</a></li>{{end}}
+ {{range .Decls}}
+ {{if .Name}}<li><a href="#decl-{{.Num}}"><tt>{{.Name}}</tt></a></li>{{end}}
+ {{end}}
+ {{end}}
+ {{end}}
+ </ol>
+
+ {{range .Sections}}
+ {{if not .IsPrivate}}
+ <div class="section">
+ {{if .Preamble}}
+ <div class="sectionpreamble">
+ <a name="section-{{.Num}}">
+ {{range .Preamble}}<p>{{. | html | markupPipeWords}}</p>{{end}}
+ </a>
+ </div>
+ {{end}}
+
+ {{range .Decls}}
+ <div class="decl">
+ <a name="decl-{{.Num}}">
+ {{range .Comment}}
+ <p>{{. | html | markupPipeWords | newlinesToBR | markupFirstWord}}</p>
+ {{end}}
+ <pre>{{.Decl}}</pre>
+ </a>
+ </div>
+ {{end}}
+ </div>
+ {{end}}
+ {{end}}
+ </div>
+ </body>
+</html>`)
+ if err != nil {
+ return nil, err
+ }
+
+ headerDescriptions := make(map[string]string)
+
+ for _, section := range config.Sections {
+ for _, headerPath := range section.Headers {
+ header, err := config.parseHeader(headerPath)
+ if err != nil {
+ return nil, errors.New("while parsing " + headerPath + ": " + err.Error())
+ }
+ headerDescriptions[header.Name] = firstSentence(header.Preamble)
+ filename := filepath.Join(outPath, header.Name+".html")
+ file, err := os.OpenFile(filename, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666)
+ if err != nil {
+ panic(err)
+ }
+ defer file.Close()
+ if err := headerTmpl.Execute(file, header); err != nil {
+ return nil, err
+ }
+ }
+ }
+
+ return headerDescriptions, nil
+}
+
+func generateIndex(outPath string, config *Config, headerDescriptions map[string]string) error {
+ indexTmpl := template.New("indexTmpl")
+ indexTmpl.Funcs(template.FuncMap{
+ "baseName": filepath.Base,
+ "headerDescription": func(header string) string {
+ return headerDescriptions[header]
+ },
+ })
+ indexTmpl, err := indexTmpl.Parse(`<!DOCTYPE html5>
+
+ <head>
+ <title>BoringSSL - Headers</title>
+ <meta charset="utf-8">
+ <link rel="stylesheet" type="text/css" href="doc.css">
+ </head>
+
+ <body>
+ <div id="main">
+ <table>
+ {{range .Sections}}
+ <tr class="header"><td colspan="2">{{.Name}}</td></tr>
+ {{range .Headers}}
+ <tr><td><a href="{{. | baseName}}.html">{{. | baseName}}</a></td><td>{{. | baseName | headerDescription}}</td></tr>
+ {{end}}
+ {{end}}
+ </table>
+ </div>
+ </body>
+</html>`)
+
+ if err != nil {
+ return err
+ }
+
+ file, err := os.OpenFile(filepath.Join(outPath, "headers.html"), os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666)
+ if err != nil {
+ panic(err)
+ }
+ defer file.Close()
+
+ if err := indexTmpl.Execute(file, config); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func main() {
+ var (
+ configFlag *string = flag.String("config", "", "Location of config file")
+ outputDir *string = flag.String("out", "", "Path to the directory where the output will be written")
+ config Config
+ )
+
+ flag.Parse()
+
+ if len(*configFlag) == 0 {
+ fmt.Printf("No config file given by --config\n")
+ os.Exit(1)
+ }
+
+ if len(*outputDir) == 0 {
+ fmt.Printf("No output directory given by --out\n")
+ os.Exit(1)
+ }
+
+ configBytes, err := ioutil.ReadFile(*configFlag)
+ if err != nil {
+ fmt.Printf("Failed to open config file: %s\n", err)
+ os.Exit(1)
+ }
+
+ if err := json.Unmarshal(configBytes, &config); err != nil {
+ fmt.Printf("Failed to parse config file: %s\n", err)
+ os.Exit(1)
+ }
+
+ headerDescriptions, err := generate(*outputDir, &config)
+ if err != nil {
+ fmt.Printf("Failed to generate output: %s\n", err)
+ os.Exit(1)
+ }
+
+ if err := generateIndex(*outputDir, &config, headerDescriptions); err != nil {
+ fmt.Printf("Failed to generate index: %s\n", err)
+ os.Exit(1)
+ }
+}
diff --git a/src/util/make_errors.go b/src/util/make_errors.go
new file mode 100644
index 0000000..5fd75e2
--- /dev/null
+++ b/src/util/make_errors.go
@@ -0,0 +1,462 @@
+// 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. */
+
+package main
+
+import (
+ "bufio"
+ "errors"
+ "flag"
+ "fmt"
+ "io"
+ "os"
+ "path/filepath"
+ "sort"
+ "strconv"
+ "strings"
+ "unicode"
+)
+
+// ssl.h reserves values 1000 and above for error codes corresponding to
+// alerts. If automatically assigned reason codes exceed this value, this script
+// will error. This must be kept in sync with SSL_AD_REASON_OFFSET in ssl.h.
+const reservedReasonCode = 1000
+
+var resetFlag *bool = flag.Bool("reset", false, "If true, ignore current assignments and reassign from scratch")
+
+func makeErrors(reset bool) error {
+ dirName, err := os.Getwd()
+ if err != nil {
+ return err
+ }
+
+ lib := filepath.Base(dirName)
+ headerPath, err := findHeader(lib + ".h")
+ if err != nil {
+ return err
+ }
+ sourcePath := lib + "_error.c"
+
+ headerFile, err := os.Open(headerPath)
+ if err != nil {
+ if os.IsNotExist(err) {
+ return fmt.Errorf("No header %s. Run in the right directory or touch the file.", headerPath)
+ }
+
+ return err
+ }
+
+ prefix := strings.ToUpper(lib)
+ functions, reasons, err := parseHeader(prefix, headerFile)
+ headerFile.Close()
+
+ if reset {
+ err = nil
+ functions = make(map[string]int)
+ // Retain any reason codes above reservedReasonCode.
+ newReasons := make(map[string]int)
+ for key, value := range reasons {
+ if value >= reservedReasonCode {
+ newReasons[key] = value
+ }
+ }
+ reasons = newReasons
+ }
+
+ if err != nil {
+ return err
+ }
+
+ dir, err := os.Open(".")
+ if err != nil {
+ return err
+ }
+ defer dir.Close()
+
+ filenames, err := dir.Readdirnames(-1)
+ if err != nil {
+ return err
+ }
+
+ for _, name := range filenames {
+ if !strings.HasSuffix(name, ".c") || name == sourcePath {
+ continue
+ }
+
+ if err := addFunctionsAndReasons(functions, reasons, name, prefix); err != nil {
+ return err
+ }
+ }
+
+ assignNewValues(functions, -1)
+ assignNewValues(reasons, reservedReasonCode)
+
+ headerFile, err = os.Open(headerPath)
+ if err != nil {
+ return err
+ }
+ defer headerFile.Close()
+
+ newHeaderFile, err := os.OpenFile(headerPath+".tmp", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0666)
+ if err != nil {
+ return err
+ }
+ defer newHeaderFile.Close()
+
+ if err := writeHeaderFile(newHeaderFile, headerFile, prefix, functions, reasons); err != nil {
+ return err
+ }
+ os.Rename(headerPath+".tmp", headerPath)
+
+ sourceFile, err := os.OpenFile(sourcePath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
+ if err != nil {
+ return err
+ }
+ defer sourceFile.Close()
+
+ fmt.Fprintf(sourceFile, `/* 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 <openssl/err.h>
+
+#include <openssl/%s.h>
+
+const ERR_STRING_DATA %s_error_string_data[] = {
+`, lib, prefix)
+ outputStrings(sourceFile, lib, typeFunctions, functions)
+ outputStrings(sourceFile, lib, typeReasons, reasons)
+
+ sourceFile.WriteString(" {0, NULL},\n};\n")
+
+ return nil
+}
+
+func findHeader(basename string) (path string, err error) {
+ includeDir := filepath.Join("..", "include")
+
+ fi, err := os.Stat(includeDir)
+ if err != nil && os.IsNotExist(err) {
+ includeDir = filepath.Join("..", includeDir)
+ fi, err = os.Stat(includeDir)
+ }
+ if err != nil {
+ return "", errors.New("cannot find path to include directory")
+ }
+ if !fi.IsDir() {
+ return "", errors.New("include node is not a directory")
+ }
+ return filepath.Join(includeDir, "openssl", basename), nil
+}
+
+type assignment struct {
+ key string
+ value int
+}
+
+type assignmentsSlice []assignment
+
+func (a assignmentsSlice) Len() int {
+ return len(a)
+}
+
+func (a assignmentsSlice) Less(i, j int) bool {
+ return a[i].value < a[j].value
+}
+
+func (a assignmentsSlice) Swap(i, j int) {
+ a[i], a[j] = a[j], a[i]
+}
+
+func outputAssignments(w io.Writer, assignments map[string]int) {
+ var sorted assignmentsSlice
+
+ for key, value := range assignments {
+ sorted = append(sorted, assignment{key, value})
+ }
+
+ sort.Sort(sorted)
+
+ for _, assignment := range sorted {
+ fmt.Fprintf(w, "#define %s %d\n", assignment.key, assignment.value)
+ }
+}
+
+func parseDefineLine(line, lib string) (typ int, key string, value int, ok bool) {
+ if !strings.HasPrefix(line, "#define ") {
+ return
+ }
+
+ fields := strings.Fields(line)
+ if len(fields) != 3 {
+ return
+ }
+
+ funcPrefix := lib + "_F_"
+ reasonPrefix := lib + "_R_"
+
+ key = fields[1]
+ switch {
+ case strings.HasPrefix(key, funcPrefix):
+ typ = typeFunctions
+ case strings.HasPrefix(key, reasonPrefix):
+ typ = typeReasons
+ default:
+ return
+ }
+
+ var err error
+ if value, err = strconv.Atoi(fields[2]); err != nil {
+ return
+ }
+
+ ok = true
+ return
+}
+
+func writeHeaderFile(w io.Writer, headerFile io.Reader, lib string, functions, reasons map[string]int) error {
+ var last []byte
+ var haveLast, sawDefine bool
+ newLine := []byte("\n")
+
+ scanner := bufio.NewScanner(headerFile)
+ for scanner.Scan() {
+ line := scanner.Text()
+ _, _, _, ok := parseDefineLine(line, lib)
+ if ok {
+ sawDefine = true
+ continue
+ }
+
+ if haveLast {
+ w.Write(last)
+ w.Write(newLine)
+ }
+
+ if len(line) > 0 || !sawDefine {
+ last = []byte(line)
+ haveLast = true
+ } else {
+ haveLast = false
+ }
+ sawDefine = false
+ }
+
+ if err := scanner.Err(); err != nil {
+ return err
+ }
+
+ outputAssignments(w, functions)
+ outputAssignments(w, reasons)
+ w.Write(newLine)
+
+ if haveLast {
+ w.Write(last)
+ w.Write(newLine)
+ }
+
+ return nil
+}
+
+const (
+ typeFunctions = iota
+ typeReasons
+)
+
+func outputStrings(w io.Writer, lib string, ty int, assignments map[string]int) {
+ lib = strings.ToUpper(lib)
+ prefixLen := len(lib + "_F_")
+
+ keys := make([]string, 0, len(assignments))
+ for key := range assignments {
+ keys = append(keys, key)
+ }
+ sort.Strings(keys)
+
+ for _, key := range keys {
+ var pack string
+ if ty == typeFunctions {
+ pack = key + ", 0"
+ } else {
+ pack = "0, " + key
+ }
+
+ fmt.Fprintf(w, " {ERR_PACK(ERR_LIB_%s, %s), \"%s\"},\n", lib, pack, key[prefixLen:])
+ }
+}
+
+func assignNewValues(assignments map[string]int, reserved int) {
+ max := 99
+
+ for _, value := range assignments {
+ if reserved >= 0 && value >= reserved {
+ continue
+ }
+ if value > max {
+ max = value
+ }
+ }
+
+ max++
+
+ for key, value := range assignments {
+ if value == -1 {
+ if reserved >= 0 && max >= reserved {
+ // If this happens, try passing
+ // -reset. Otherwise bump up reservedReasonCode.
+ panic("Automatically-assigned values exceeded limit!")
+ }
+ assignments[key] = max
+ max++
+ }
+ }
+}
+
+func handleDeclareMacro(line, join, macroName string, m map[string]int) {
+ if i := strings.Index(line, macroName); i >= 0 {
+ contents := line[i+len(macroName):]
+ if i := strings.Index(contents, ")"); i >= 0 {
+ contents = contents[:i]
+ args := strings.Split(contents, ",")
+ for i := range args {
+ args[i] = strings.TrimSpace(args[i])
+ }
+ if len(args) != 2 {
+ panic("Bad macro line: " + line)
+ }
+ token := args[0] + join + args[1]
+ if _, ok := m[token]; !ok {
+ m[token] = -1
+ }
+ }
+ }
+}
+
+func addFunctionsAndReasons(functions, reasons map[string]int, filename, prefix string) error {
+ file, err := os.Open(filename)
+ if err != nil {
+ return err
+ }
+ defer file.Close()
+
+ prefix += "_"
+ reasonPrefix := prefix + "R_"
+ var currentFunction string
+
+ scanner := bufio.NewScanner(file)
+ for scanner.Scan() {
+ line := scanner.Text()
+
+ if len(line) > 0 && unicode.IsLetter(rune(line[0])) {
+ /* Function start */
+ fields := strings.Fields(line)
+ for _, field := range fields {
+ if i := strings.Index(field, "("); i != -1 {
+ f := field[:i]
+ // The return type of some functions is
+ // a macro that contains a "(".
+ if f == "STACK_OF" {
+ continue
+ }
+ currentFunction = f
+ for len(currentFunction) > 0 && currentFunction[0] == '*' {
+ currentFunction = currentFunction[1:]
+ }
+ break
+ }
+ }
+ }
+
+ if strings.Contains(line, "OPENSSL_PUT_ERROR(") {
+ functionToken := prefix + "F_" + currentFunction
+ if _, ok := functions[functionToken]; !ok {
+ functions[functionToken] = -1
+ }
+ }
+
+ handleDeclareMacro(line, "_R_", "OPENSSL_DECLARE_ERROR_REASON(", reasons)
+ handleDeclareMacro(line, "_F_", "OPENSSL_DECLARE_ERROR_FUNCTION(", functions)
+
+ for len(line) > 0 {
+ i := strings.Index(line, prefix)
+ if i == -1 {
+ break
+ }
+
+ line = line[i:]
+ end := strings.IndexFunc(line, func(r rune) bool {
+ return !(r == '_' || (r >= 'A' && r <= 'Z') || (r >= '0' && r <= '9'))
+ })
+ if end == -1 {
+ end = len(line)
+ }
+
+ var token string
+ token, line = line[:end], line[end:]
+
+ switch {
+ case strings.HasPrefix(token, reasonPrefix):
+ if _, ok := reasons[token]; !ok {
+ reasons[token] = -1
+ }
+ }
+ }
+ }
+
+ return scanner.Err()
+}
+
+func parseHeader(lib string, file io.Reader) (functions, reasons map[string]int, err error) {
+ functions = make(map[string]int)
+ reasons = make(map[string]int)
+
+ scanner := bufio.NewScanner(file)
+ for scanner.Scan() {
+ typ, key, value, ok := parseDefineLine(scanner.Text(), lib)
+ if !ok {
+ continue
+ }
+
+ switch typ {
+ case typeFunctions:
+ functions[key] = value
+ case typeReasons:
+ reasons[key] = value
+ default:
+ panic("internal error")
+ }
+ }
+
+ err = scanner.Err()
+ return
+}
+
+func main() {
+ flag.Parse()
+
+ if err := makeErrors(*resetFlag); err != nil {
+ fmt.Fprintf(os.Stderr, "%s\n", err)
+ os.Exit(1)
+ }
+}
diff --git a/ssl-sources.mk b/ssl-sources.mk
new file mode 100644
index 0000000..0d15bac
--- /dev/null
+++ b/ssl-sources.mk
@@ -0,0 +1,5 @@
+LOCAL_ADDITIONAL_DEPENDENCIES += $(LOCAL_PATH)/sources.mk
+include $(LOCAL_PATH)/sources.mk
+
+LOCAL_CFLAGS += -I$(LOCAL_PATH)/src/include -Wno-unused-parameter
+LOCAL_SRC_FILES += $(ssl_sources)
diff --git a/update_gypi_and_asm.py b/update_gypi_and_asm.py
new file mode 100644
index 0000000..6ac8383
--- /dev/null
+++ b/update_gypi_and_asm.py
@@ -0,0 +1,214 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can b
+# found in the LICENSE file.
+
+import os
+import subprocess
+import sys
+
+
+# OS_ARCH_COMBOS maps from OS and platform to the OpenSSL assembly "style" for
+# that platform and the extension used by asm files.
+OS_ARCH_COMBOS = [
+ ('linux', 'arm', 'elf', [''], 'S'),
+ ('linux', 'x86', 'elf', ['-fPIC'], 'S'),
+ ('linux', 'x86_64', 'elf', [''], 'S'),
+ ('linux', 'aarch64', 'linux64', [''], 'S'),
+ ('mac', 'x86', 'macosx', ['-fPIC'], 'S'),
+ ('mac', 'x86_64', 'macosx', [''], 'S'),
+ ('win', 'x86_64', 'masm', [''], 'asm'),
+]
+
+# NON_PERL_FILES enumerates assembly files that are not processed by the
+# perlasm system.
+NON_PERL_FILES = {
+ ('linux', 'arm'): [
+ 'src/crypto/poly1305/poly1305_arm_asm.S',
+ 'src/crypto/chacha/chacha_vec_arm.S',
+ ],
+}
+
+FILE_HEADER = """# This file is created by update_gypi_and_asm.py. Do not edit manually.
+
+"""
+
+
+def FindCMakeFiles(directory):
+ """Returns list of all CMakeLists.txt files recursively in directory."""
+ cmakefiles = []
+
+ for (path, _, filenames) in os.walk(directory):
+ for filename in filenames:
+ if filename == 'CMakeLists.txt':
+ cmakefiles.append(os.path.join(path, filename))
+
+ return cmakefiles
+
+
+def NoTests(dent, is_dir):
+ """Filter function that can be passed to FindCFiles in order to remove test
+ sources."""
+ if is_dir:
+ return dent != 'test'
+ return 'test.' not in dent and not dent.startswith('example_')
+
+
+def OnlyTests(dent, is_dir):
+ """Filter function that can be passed to FindCFiles in order to remove
+ non-test sources."""
+ if is_dir:
+ return True
+ return '_test.' in dent or dent.startswith('example_')
+
+
+def FindCFiles(directory, filter_func):
+ """Recurses through directory and returns a list of paths to all the C source
+ files that pass filter_func."""
+ cfiles = []
+
+ for (path, dirnames, filenames) in os.walk(directory):
+ for filename in filenames:
+ if (filename.endswith('.c') or filename.endswith('.cc')) and filter_func(
+ filename, False):
+ cfiles.append(os.path.join(path, filename))
+ continue
+
+ for (i, dirname) in enumerate(dirnames):
+ if not filter_func(dirname, True):
+ del dirnames[i]
+
+ return cfiles
+
+
+def ExtractPerlAsmFromCMakeFile(cmakefile):
+ """Parses the contents of the CMakeLists.txt file passed as an argument and
+ returns a list of all the perlasm() directives found in the file."""
+ perlasms = []
+ with open(cmakefile) as f:
+ for line in f:
+ line = line.strip()
+ if not line.startswith('perlasm('):
+ continue
+ if not line.endswith(')'):
+ raise ValueError('Bad perlasm line in %s' % cmakefile)
+ # Remove "perlasm(" from start and ")" from end
+ params = line[8:-1].split()
+ if len(params) < 2:
+ raise ValueError('Bad perlasm line in %s' % cmakefile)
+ perlasms.append({
+ 'extra_args': params[2:],
+ 'input': os.path.join(os.path.dirname(cmakefile), params[1]),
+ 'output': os.path.join(os.path.dirname(cmakefile), params[0]),
+ })
+
+ return perlasms
+
+
+def ReadPerlAsmOperations():
+ """Returns a list of all perlasm() directives found in CMake config files in
+ src/."""
+ perlasms = []
+ cmakefiles = FindCMakeFiles('src')
+
+ for cmakefile in cmakefiles:
+ perlasms.extend(ExtractPerlAsmFromCMakeFile(cmakefile))
+
+ return perlasms
+
+
+def PerlAsm(output_filename, input_filename, perlasm_style, extra_args):
+ """Runs the a perlasm script and puts the output into output_filename."""
+ base_dir = os.path.dirname(output_filename)
+ if not os.path.isdir(base_dir):
+ os.makedirs(base_dir)
+ output = subprocess.check_output(
+ ['perl', input_filename, perlasm_style] + extra_args)
+ with open(output_filename, 'w+') as out_file:
+ out_file.write(output)
+
+
+def ArchForAsmFilename(filename):
+ """Returns the architectures that a given asm file should be compiled for
+ based on substrings in the filename."""
+
+ if 'x86_64' in filename or 'avx2' in filename:
+ return ['x86_64']
+ elif ('x86' in filename and 'x86_64' not in filename) or '586' in filename:
+ return ['x86']
+ elif 'armx' in filename:
+ return ['arm', 'aarch64']
+ elif 'armv8' in filename:
+ return ['aarch64']
+ elif 'arm' in filename:
+ return ['arm']
+ else:
+ raise ValueError('Unknown arch for asm filename: ' + filename)
+
+
+def WriteAsmFiles(perlasms):
+ """Generates asm files from perlasm directives for each supported OS x
+ platform combination."""
+ asmfiles = {}
+
+ for osarch in OS_ARCH_COMBOS:
+ (osname, arch, perlasm_style, extra_args, asm_ext) = osarch
+ key = (osname, arch)
+ outDir = '%s-%s' % key
+
+ for perlasm in perlasms:
+ filename = os.path.basename(perlasm['input'])
+ output = perlasm['output']
+ if not output.startswith('src'):
+ raise ValueError('output missing src: %s' % output)
+ output = os.path.join(outDir, output[4:])
+ output = output.replace('${ASM_EXT}', asm_ext)
+
+ if arch in ArchForAsmFilename(filename):
+ PerlAsm(output, perlasm['input'], perlasm_style,
+ perlasm['extra_args'] + extra_args)
+ asmfiles.setdefault(key, []).append(output)
+
+ for (key, non_perl_asm_files) in NON_PERL_FILES.iteritems():
+ asmfiles.setdefault(key, []).extend(non_perl_asm_files)
+
+ return asmfiles
+
+
+def PrintVariableSection(out, name, files):
+ out.write('%s := \\\n' % name)
+ for f in sorted(files):
+ out.write(' %s\\\n' % f)
+ out.write('\n')
+
+
+def main():
+ crypto_c_files = FindCFiles(os.path.join('src', 'crypto'), NoTests)
+ ssl_c_files = FindCFiles(os.path.join('src', 'ssl'), NoTests)
+ tool_cc_files = FindCFiles(os.path.join('src', 'tool'), NoTests)
+
+ crypto_c_files.append('android_compat_hacks.c')
+
+ with open('sources.mk', 'w+') as makefile:
+ makefile.write(FILE_HEADER)
+
+ PrintVariableSection(
+ makefile, 'crypto_sources', crypto_c_files)
+
+ PrintVariableSection(
+ makefile, 'ssl_sources', ssl_c_files)
+
+ PrintVariableSection(
+ makefile, 'tool_sources', tool_cc_files)
+
+ perlasms = ReadPerlAsmOperations()
+
+ for ((osname, arch), asm_files) in sorted(
+ WriteAsmFiles(perlasms).iteritems()):
+ PrintVariableSection(makefile, '%s_%s_sources' %
+ (osname, arch), asm_files)
+
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/win-x86_64/crypto/aes/aes-x86_64.asm b/win-x86_64/crypto/aes/aes-x86_64.asm
new file mode 100644
index 0000000..96cbb4b
--- /dev/null
+++ b/win-x86_64/crypto/aes/aes-x86_64.asm
@@ -0,0 +1,2864 @@
+OPTION DOTNAME
+.text$ SEGMENT ALIGN(256) '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
+_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 r8d,dl
+ movzx esi,bh
+ movzx edi,ch
+ shr ecx,16
+ movzx ebp,dh
+ movzx r10d,BYTE PTR[r10*1+r14]
+ movzx r11d,BYTE PTR[r11*1+r14]
+ movzx r12d,BYTE PTR[r12*1+r14]
+ movzx r8d,BYTE PTR[r8*1+r14]
+
+ movzx r9d,BYTE PTR[rsi*1+r14]
+ movzx esi,ah
+ movzx r13d,BYTE PTR[rdi*1+r14]
+ movzx edi,cl
+ movzx ebp,BYTE PTR[rbp*1+r14]
+ movzx esi,BYTE PTR[rsi*1+r14]
+
+ shl r9d,8
+ shr edx,16
+ shl r13d,8
+ xor r10d,r9d
+ shr eax,16
+ movzx r9d,dl
+ shr ebx,16
+ xor r11d,r13d
+ shl ebp,8
+ movzx r13d,al
+ movzx edi,BYTE PTR[rdi*1+r14]
+ xor r12d,ebp
+
+ shl esi,8
+ movzx ebp,bl
+ shl edi,16
+ xor r8d,esi
+ movzx r9d,BYTE PTR[r9*1+r14]
+ movzx esi,dh
+ movzx r13d,BYTE PTR[r13*1+r14]
+ xor r10d,edi
+
+ shr ecx,8
+ movzx edi,ah
+ shl r9d,16
+ shr ebx,8
+ shl r13d,16
+ xor r11d,r9d
+ movzx ebp,BYTE PTR[rbp*1+r14]
+ movzx esi,BYTE PTR[rsi*1+r14]
+ movzx edi,BYTE PTR[rdi*1+r14]
+ movzx edx,BYTE PTR[rcx*1+r14]
+ movzx ecx,BYTE PTR[rbx*1+r14]
+
+ shl ebp,16
+ xor r12d,r13d
+ shl esi,24
+ xor r8d,ebp
+ shl edi,24
+ xor r10d,esi
+ shl edx,24
+ xor r11d,edi
+ shl ecx,24
+ mov eax,r10d
+ mov ebx,r11d
+ xor ecx,r12d
+ xor edx,r8d
+ cmp r15,QWORD PTR[16+rsp]
+ je $L$enc_compact_done
+ mov r10d,080808080h
+ mov r11d,080808080h
+ and r10d,eax
+ and r11d,ebx
+ mov esi,r10d
+ mov edi,r11d
+ 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 r12d,080808080h
+ rol eax,24
+ mov ebp,080808080h
+ rol ebx,24
+ and r12d,ecx
+ and ebp,edx
+ xor eax,r8d
+ xor ebx,r9d
+ mov esi,r12d
+ ror r10d,16
+ mov edi,ebp
+ ror r11d,16
+ lea r8d,DWORD PTR[rcx*1+rcx]
+ shr r12d,7
+ xor eax,r10d
+ shr ebp,7
+ xor ebx,r11d
+ ror r10d,8
+ lea r9d,DWORD PTR[rdx*1+rdx]
+ 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
+
+ ror r12d,16
+ xor ecx,r8d
+ ror ebp,16
+ xor edx,r9d
+ rol ecx,24
+ mov esi,DWORD PTR[r14]
+ rol edx,24
+ xor ecx,r8d
+ mov edi,DWORD PTR[64+r14]
+ xor edx,r9d
+ mov r8d,DWORD PTR[128+r14]
+ xor ecx,r12d
+ ror r12d,8
+ xor edx,ebp
+ ror ebp,8
+ xor ecx,r12d
+ mov r9d,DWORD PTR[192+r14]
+ 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
+_x86_64_AES_encrypt_compact ENDP
+ALIGN 16
+PUBLIC asm_AES_encrypt
+
+
+asm_AES_encrypt PROC PUBLIC
+ mov QWORD PTR[8+rsp],rdi ;WIN64 prologue
+ mov QWORD PTR[16+rsp],rsi
+ mov rax,rsp
+$L$SEH_begin_asm_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_asm_AES_encrypt::
+asm_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
+_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 r8d,dl
+ movzx esi,dh
+ movzx edi,ah
+ shr edx,16
+ movzx ebp,bh
+ movzx r10d,BYTE PTR[r10*1+r14]
+ movzx r11d,BYTE PTR[r11*1+r14]
+ movzx r12d,BYTE PTR[r12*1+r14]
+ movzx r8d,BYTE PTR[r8*1+r14]
+
+ movzx r9d,BYTE PTR[rsi*1+r14]
+ movzx esi,ch
+ movzx r13d,BYTE PTR[rdi*1+r14]
+ movzx ebp,BYTE PTR[rbp*1+r14]
+ movzx esi,BYTE PTR[rsi*1+r14]
+
+ shr ecx,16
+ shl r13d,8
+ shl r9d,8
+ movzx edi,cl
+ shr eax,16
+ xor r10d,r9d
+ shr ebx,16
+ movzx r9d,dl
+
+ shl ebp,8
+ xor r11d,r13d
+ shl esi,8
+ movzx r13d,al
+ movzx edi,BYTE PTR[rdi*1+r14]
+ xor r12d,ebp
+ movzx ebp,bl
+
+ shl edi,16
+ xor r8d,esi
+ movzx r9d,BYTE PTR[r9*1+r14]
+ movzx esi,bh
+ movzx ebp,BYTE PTR[rbp*1+r14]
+ xor r10d,edi
+ movzx r13d,BYTE PTR[r13*1+r14]
+ movzx edi,ch
+
+ shl ebp,16
+ shl r9d,16
+ shl r13d,16
+ xor r8d,ebp
+ movzx ebp,dh
+ xor r11d,r9d
+ shr eax,8
+ xor r12d,r13d
+
+ movzx esi,BYTE PTR[rsi*1+r14]
+ movzx ebx,BYTE PTR[rdi*1+r14]
+ movzx ecx,BYTE PTR[rbp*1+r14]
+ movzx edx,BYTE PTR[rax*1+r14]
+
+ mov eax,r10d
+ shl esi,24
+ shl ebx,24
+ shl ecx,24
+ xor eax,esi
+ shl edx,24
+ xor ebx,r11d
+ 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 r9,rsi
+ mov r12,rsi
+ and r9,rax
+ and r12,rcx
+ mov rbx,r9
+ mov rdx,r12
+ 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 r8,rbx
+ xor r11,rdx
+ mov r10,rsi
+ mov r13,rsi
+
+ and r10,r8
+ and r13,r11
+ mov rbx,r10
+ mov rdx,r13
+ 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 r9,rbx
+ xor r12,rdx
+ mov r10,rsi
+ mov r13,rsi
+
+ and r10,r9
+ and r13,r12
+ mov rbx,r10
+ mov rdx,r13
+ 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
+ shr rbx,32
+ xor r12,r13
+ shr rdx,32
+ xor r10,r8
+ rol eax,8
+ xor r13,r11
+ rol ecx,8
+ xor r10,r9
+ rol ebx,8
+ xor r13,r12
+
+ rol edx,8
+ xor eax,r10d
+ shr r10,32
+ xor ecx,r13d
+ shr r13,32
+ xor ebx,r10d
+ xor edx,r13d
+
+ mov r10,r8
+ rol r8d,24
+ mov r13,r11
+ rol r11d,24
+ shr r10,32
+ xor eax,r8d
+ shr r13,32
+ xor ecx,r11d
+ rol r10d,24
+ mov r8,r9
+ rol r13d,24
+ mov r11,r12
+ shr r8,32
+ xor ebx,r10d
+ shr r11,32
+ xor edx,r13d
+
+ mov rsi,QWORD PTR[r14]
+ rol r9d,16
+ mov rdi,QWORD PTR[64+r14]
+ rol r12d,16
+ mov rbp,QWORD PTR[128+r14]
+ rol r8d,16
+ mov r10,QWORD PTR[192+r14]
+ xor eax,r9d
+ rol r11d,16
+ 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
+_x86_64_AES_decrypt_compact ENDP
+ALIGN 16
+PUBLIC asm_AES_decrypt
+
+
+asm_AES_decrypt PROC PUBLIC
+ mov QWORD PTR[8+rsp],rdi ;WIN64 prologue
+ mov QWORD PTR[16+rsp],rsi
+ mov rax,rsp
+$L$SEH_begin_asm_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_asm_AES_decrypt::
+asm_AES_decrypt ENDP
+ALIGN 16
+PUBLIC asm_AES_set_encrypt_key
+
+asm_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_asm_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 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_asm_AES_set_encrypt_key::
+asm_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
+_x86_64_AES_set_encrypt_key ENDP
+ALIGN 16
+PUBLIC asm_AES_set_decrypt_key
+
+asm_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_asm_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 r9,rsi
+ mov r12,rsi
+ and r9,rax
+ and r12,rcx
+ mov rbx,r9
+ mov rdx,r12
+ 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 r8,rbx
+ xor r11,rdx
+ mov r10,rsi
+ mov r13,rsi
+
+ and r10,r8
+ and r13,r11
+ mov rbx,r10
+ mov rdx,r13
+ 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 r9,rbx
+ xor r12,rdx
+ mov r10,rsi
+ mov r13,rsi
+
+ and r10,r9
+ and r13,r12
+ mov rbx,r10
+ mov rdx,r13
+ 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
+ shr rbx,32
+ xor r12,r13
+ shr rdx,32
+ xor r10,r8
+ rol eax,8
+ xor r13,r11
+ rol ecx,8
+ xor r10,r9
+ rol ebx,8
+ xor r13,r12
+
+ rol edx,8
+ xor eax,r10d
+ shr r10,32
+ xor ecx,r13d
+ shr r13,32
+ xor ebx,r10d
+ xor edx,r13d
+
+ mov r10,r8
+ rol r8d,24
+ mov r13,r11
+ rol r11d,24
+ shr r10,32
+ xor eax,r8d
+ shr r13,32
+ xor ecx,r11d
+ rol r10d,24
+ mov r8,r9
+ rol r13d,24
+ mov r11,r12
+ shr r8,32
+ xor ebx,r10d
+ shr r11,32
+ xor edx,r13d
+
+
+ rol r9d,16
+
+ rol r12d,16
+
+ rol r8d,16
+
+ xor eax,r9d
+ rol r11d,16
+ 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_asm_AES_set_decrypt_key::
+asm_AES_set_decrypt_key ENDP
+ALIGN 16
+PUBLIC asm_AES_cbc_encrypt
+
+EXTERN OPENSSL_ia32cap_P:NEAR
+
+asm_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_asm_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_asm_AES_cbc_encrypt::
+asm_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_asm_AES_encrypt
+ DD imagerel $L$SEH_end_asm_AES_encrypt
+ DD imagerel $L$SEH_info_asm_AES_encrypt
+
+ DD imagerel $L$SEH_begin_asm_AES_decrypt
+ DD imagerel $L$SEH_end_asm_AES_decrypt
+ DD imagerel $L$SEH_info_asm_AES_decrypt
+
+ DD imagerel $L$SEH_begin_asm_AES_set_encrypt_key
+ DD imagerel $L$SEH_end_asm_AES_set_encrypt_key
+ DD imagerel $L$SEH_info_asm_AES_set_encrypt_key
+
+ DD imagerel $L$SEH_begin_asm_AES_set_decrypt_key
+ DD imagerel $L$SEH_end_asm_AES_set_decrypt_key
+ DD imagerel $L$SEH_info_asm_AES_set_decrypt_key
+
+ DD imagerel $L$SEH_begin_asm_AES_cbc_encrypt
+ DD imagerel $L$SEH_end_asm_AES_cbc_encrypt
+ DD imagerel $L$SEH_info_asm_AES_cbc_encrypt
+
+.pdata ENDS
+.xdata SEGMENT READONLY ALIGN(8)
+ALIGN 8
+$L$SEH_info_asm_AES_encrypt::
+DB 9,0,0,0
+ DD imagerel block_se_handler
+ DD imagerel $L$enc_prologue,imagerel $L$enc_epilogue
+$L$SEH_info_asm_AES_decrypt::
+DB 9,0,0,0
+ DD imagerel block_se_handler
+ DD imagerel $L$dec_prologue,imagerel $L$dec_epilogue
+$L$SEH_info_asm_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_asm_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_asm_AES_cbc_encrypt::
+DB 9,0,0,0
+ DD imagerel cbc_se_handler
+
+.xdata ENDS
+END
diff --git a/win-x86_64/crypto/aes/aesni-x86_64.asm b/win-x86_64/crypto/aes/aesni-x86_64.asm
new file mode 100644
index 0000000..53d8afc
--- /dev/null
+++ b/win-x86_64/crypto/aes/aesni-x86_64.asm
@@ -0,0 +1,3631 @@
+OPTION DOTNAME
+.text$ SEGMENT ALIGN(256) 'CODE'
+EXTERN OPENSSL_ia32cap_P:NEAR
+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::
+DB 102,15,56,220,209
+ dec eax
+ movups xmm1,XMMWORD PTR[r8]
+ lea r8,QWORD PTR[16+r8]
+ jnz $L$oop_enc1_1
+DB 102,15,56,221,209
+ 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::
+DB 102,15,56,222,209
+ dec eax
+ movups xmm1,XMMWORD PTR[r8]
+ lea r8,QWORD PTR[16+r8]
+ jnz $L$oop_dec1_2
+DB 102,15,56,223,209
+ movups XMMWORD PTR[rdx],xmm2
+ DB 0F3h,0C3h ;repret
+aesni_decrypt ENDP
+
+ALIGN 16
+_aesni_encrypt2 PROC PRIVATE
+ movups xmm0,XMMWORD PTR[rcx]
+ shl eax,4
+ movups xmm1,XMMWORD PTR[16+rcx]
+ xorps xmm2,xmm0
+ xorps xmm3,xmm0
+ movups xmm0,XMMWORD PTR[32+rcx]
+ lea rcx,QWORD PTR[32+rax*1+rcx]
+ neg rax
+ add rax,16
+
+$L$enc_loop2::
+DB 102,15,56,220,209
+DB 102,15,56,220,217
+ movups xmm1,XMMWORD PTR[rax*1+rcx]
+ add rax,32
+DB 102,15,56,220,208
+DB 102,15,56,220,216
+ movups xmm0,XMMWORD PTR[((-16))+rax*1+rcx]
+ jnz $L$enc_loop2
+
+DB 102,15,56,220,209
+DB 102,15,56,220,217
+DB 102,15,56,221,208
+DB 102,15,56,221,216
+ DB 0F3h,0C3h ;repret
+_aesni_encrypt2 ENDP
+
+ALIGN 16
+_aesni_decrypt2 PROC PRIVATE
+ movups xmm0,XMMWORD PTR[rcx]
+ shl eax,4
+ movups xmm1,XMMWORD PTR[16+rcx]
+ xorps xmm2,xmm0
+ xorps xmm3,xmm0
+ movups xmm0,XMMWORD PTR[32+rcx]
+ lea rcx,QWORD PTR[32+rax*1+rcx]
+ neg rax
+ add rax,16
+
+$L$dec_loop2::
+DB 102,15,56,222,209
+DB 102,15,56,222,217
+ movups xmm1,XMMWORD PTR[rax*1+rcx]
+ add rax,32
+DB 102,15,56,222,208
+DB 102,15,56,222,216
+ movups xmm0,XMMWORD PTR[((-16))+rax*1+rcx]
+ jnz $L$dec_loop2
+
+DB 102,15,56,222,209
+DB 102,15,56,222,217
+DB 102,15,56,223,208
+DB 102,15,56,223,216
+ DB 0F3h,0C3h ;repret
+_aesni_decrypt2 ENDP
+
+ALIGN 16
+_aesni_encrypt3 PROC PRIVATE
+ movups xmm0,XMMWORD PTR[rcx]
+ shl eax,4
+ movups xmm1,XMMWORD PTR[16+rcx]
+ xorps xmm2,xmm0
+ xorps xmm3,xmm0
+ xorps xmm4,xmm0
+ movups xmm0,XMMWORD PTR[32+rcx]
+ lea rcx,QWORD PTR[32+rax*1+rcx]
+ neg rax
+ add rax,16
+
+$L$enc_loop3::
+DB 102,15,56,220,209
+DB 102,15,56,220,217
+DB 102,15,56,220,225
+ movups xmm1,XMMWORD PTR[rax*1+rcx]
+ add rax,32
+DB 102,15,56,220,208
+DB 102,15,56,220,216
+DB 102,15,56,220,224
+ movups xmm0,XMMWORD PTR[((-16))+rax*1+rcx]
+ jnz $L$enc_loop3
+
+DB 102,15,56,220,209
+DB 102,15,56,220,217
+DB 102,15,56,220,225
+DB 102,15,56,221,208
+DB 102,15,56,221,216
+DB 102,15,56,221,224
+ DB 0F3h,0C3h ;repret
+_aesni_encrypt3 ENDP
+
+ALIGN 16
+_aesni_decrypt3 PROC PRIVATE
+ movups xmm0,XMMWORD PTR[rcx]
+ shl eax,4
+ movups xmm1,XMMWORD PTR[16+rcx]
+ xorps xmm2,xmm0
+ xorps xmm3,xmm0
+ xorps xmm4,xmm0
+ movups xmm0,XMMWORD PTR[32+rcx]
+ lea rcx,QWORD PTR[32+rax*1+rcx]
+ neg rax
+ add rax,16
+
+$L$dec_loop3::
+DB 102,15,56,222,209
+DB 102,15,56,222,217
+DB 102,15,56,222,225
+ movups xmm1,XMMWORD PTR[rax*1+rcx]
+ add rax,32
+DB 102,15,56,222,208
+DB 102,15,56,222,216
+DB 102,15,56,222,224
+ movups xmm0,XMMWORD PTR[((-16))+rax*1+rcx]
+ jnz $L$dec_loop3
+
+DB 102,15,56,222,209
+DB 102,15,56,222,217
+DB 102,15,56,222,225
+DB 102,15,56,223,208
+DB 102,15,56,223,216
+DB 102,15,56,223,224
+ DB 0F3h,0C3h ;repret
+_aesni_decrypt3 ENDP
+
+ALIGN 16
+_aesni_encrypt4 PROC PRIVATE
+ movups xmm0,XMMWORD PTR[rcx]
+ shl eax,4
+ movups xmm1,XMMWORD PTR[16+rcx]
+ xorps xmm2,xmm0
+ xorps xmm3,xmm0
+ xorps xmm4,xmm0
+ xorps xmm5,xmm0
+ movups xmm0,XMMWORD PTR[32+rcx]
+ lea rcx,QWORD PTR[32+rax*1+rcx]
+ neg rax
+DB 00fh,01fh,000h
+ add rax,16
+
+$L$enc_loop4::
+DB 102,15,56,220,209
+DB 102,15,56,220,217
+DB 102,15,56,220,225
+DB 102,15,56,220,233
+ movups xmm1,XMMWORD PTR[rax*1+rcx]
+ add rax,32
+DB 102,15,56,220,208
+DB 102,15,56,220,216
+DB 102,15,56,220,224
+DB 102,15,56,220,232
+ movups xmm0,XMMWORD PTR[((-16))+rax*1+rcx]
+ jnz $L$enc_loop4
+
+DB 102,15,56,220,209
+DB 102,15,56,220,217
+DB 102,15,56,220,225
+DB 102,15,56,220,233
+DB 102,15,56,221,208
+DB 102,15,56,221,216
+DB 102,15,56,221,224
+DB 102,15,56,221,232
+ DB 0F3h,0C3h ;repret
+_aesni_encrypt4 ENDP
+
+ALIGN 16
+_aesni_decrypt4 PROC PRIVATE
+ movups xmm0,XMMWORD PTR[rcx]
+ shl eax,4
+ movups xmm1,XMMWORD PTR[16+rcx]
+ xorps xmm2,xmm0
+ xorps xmm3,xmm0
+ xorps xmm4,xmm0
+ xorps xmm5,xmm0
+ movups xmm0,XMMWORD PTR[32+rcx]
+ lea rcx,QWORD PTR[32+rax*1+rcx]
+ neg rax
+DB 00fh,01fh,000h
+ add rax,16
+
+$L$dec_loop4::
+DB 102,15,56,222,209
+DB 102,15,56,222,217
+DB 102,15,56,222,225
+DB 102,15,56,222,233
+ movups xmm1,XMMWORD PTR[rax*1+rcx]
+ add rax,32
+DB 102,15,56,222,208
+DB 102,15,56,222,216
+DB 102,15,56,222,224
+DB 102,15,56,222,232
+ movups xmm0,XMMWORD PTR[((-16))+rax*1+rcx]
+ jnz $L$dec_loop4
+
+DB 102,15,56,222,209
+DB 102,15,56,222,217
+DB 102,15,56,222,225
+DB 102,15,56,222,233
+DB 102,15,56,223,208
+DB 102,15,56,223,216
+DB 102,15,56,223,224
+DB 102,15,56,223,232
+ DB 0F3h,0C3h ;repret
+_aesni_decrypt4 ENDP
+
+ALIGN 16
+_aesni_encrypt6 PROC PRIVATE
+ movups xmm0,XMMWORD PTR[rcx]
+ shl eax,4
+ movups xmm1,XMMWORD PTR[16+rcx]
+ xorps xmm2,xmm0
+ pxor xmm3,xmm0
+ pxor xmm4,xmm0
+DB 102,15,56,220,209
+ lea rcx,QWORD PTR[32+rax*1+rcx]
+ neg rax
+DB 102,15,56,220,217
+ pxor xmm5,xmm0
+ pxor xmm6,xmm0
+DB 102,15,56,220,225
+ pxor xmm7,xmm0
+ add rax,16
+DB 102,15,56,220,233
+DB 102,15,56,220,241
+DB 102,15,56,220,249
+ movups xmm0,XMMWORD PTR[((-16))+rax*1+rcx]
+ jmp $L$enc_loop6_enter
+ALIGN 16
+$L$enc_loop6::
+DB 102,15,56,220,209
+DB 102,15,56,220,217
+DB 102,15,56,220,225
+DB 102,15,56,220,233
+DB 102,15,56,220,241
+DB 102,15,56,220,249
+$L$enc_loop6_enter::
+ movups xmm1,XMMWORD PTR[rax*1+rcx]
+ add rax,32
+DB 102,15,56,220,208
+DB 102,15,56,220,216
+DB 102,15,56,220,224
+DB 102,15,56,220,232
+DB 102,15,56,220,240
+DB 102,15,56,220,248
+ movups xmm0,XMMWORD PTR[((-16))+rax*1+rcx]
+ jnz $L$enc_loop6
+
+DB 102,15,56,220,209
+DB 102,15,56,220,217
+DB 102,15,56,220,225
+DB 102,15,56,220,233
+DB 102,15,56,220,241
+DB 102,15,56,220,249
+DB 102,15,56,221,208
+DB 102,15,56,221,216
+DB 102,15,56,221,224
+DB 102,15,56,221,232
+DB 102,15,56,221,240
+DB 102,15,56,221,248
+ DB 0F3h,0C3h ;repret
+_aesni_encrypt6 ENDP
+
+ALIGN 16
+_aesni_decrypt6 PROC PRIVATE
+ movups xmm0,XMMWORD PTR[rcx]
+ shl eax,4
+ movups xmm1,XMMWORD PTR[16+rcx]
+ xorps xmm2,xmm0
+ pxor xmm3,xmm0
+ pxor xmm4,xmm0
+DB 102,15,56,222,209
+ lea rcx,QWORD PTR[32+rax*1+rcx]
+ neg rax
+DB 102,15,56,222,217
+ pxor xmm5,xmm0
+ pxor xmm6,xmm0
+DB 102,15,56,222,225
+ pxor xmm7,xmm0
+ add rax,16
+DB 102,15,56,222,233
+DB 102,15,56,222,241
+DB 102,15,56,222,249
+ movups xmm0,XMMWORD PTR[((-16))+rax*1+rcx]
+ jmp $L$dec_loop6_enter
+ALIGN 16
+$L$dec_loop6::
+DB 102,15,56,222,209
+DB 102,15,56,222,217
+DB 102,15,56,222,225
+DB 102,15,56,222,233
+DB 102,15,56,222,241
+DB 102,15,56,222,249
+$L$dec_loop6_enter::
+ movups xmm1,XMMWORD PTR[rax*1+rcx]
+ add rax,32
+DB 102,15,56,222,208
+DB 102,15,56,222,216
+DB 102,15,56,222,224
+DB 102,15,56,222,232
+DB 102,15,56,222,240
+DB 102,15,56,222,248
+ movups xmm0,XMMWORD PTR[((-16))+rax*1+rcx]
+ jnz $L$dec_loop6
+
+DB 102,15,56,222,209
+DB 102,15,56,222,217
+DB 102,15,56,222,225
+DB 102,15,56,222,233
+DB 102,15,56,222,241
+DB 102,15,56,222,249
+DB 102,15,56,223,208
+DB 102,15,56,223,216
+DB 102,15,56,223,224
+DB 102,15,56,223,232
+DB 102,15,56,223,240
+DB 102,15,56,223,248
+ DB 0F3h,0C3h ;repret
+_aesni_decrypt6 ENDP
+
+ALIGN 16
+_aesni_encrypt8 PROC PRIVATE
+ movups xmm0,XMMWORD PTR[rcx]
+ shl eax,4
+ movups xmm1,XMMWORD PTR[16+rcx]
+ xorps xmm2,xmm0
+ xorps xmm3,xmm0
+ pxor xmm4,xmm0
+ pxor xmm5,xmm0
+ pxor xmm6,xmm0
+ lea rcx,QWORD PTR[32+rax*1+rcx]
+ neg rax
+DB 102,15,56,220,209
+ add rax,16
+ pxor xmm7,xmm0
+DB 102,15,56,220,217
+ pxor xmm8,xmm0
+ pxor xmm9,xmm0
+DB 102,15,56,220,225
+DB 102,15,56,220,233
+DB 102,15,56,220,241
+DB 102,15,56,220,249
+DB 102,68,15,56,220,193
+DB 102,68,15,56,220,201
+ movups xmm0,XMMWORD PTR[((-16))+rax*1+rcx]
+ jmp $L$enc_loop8_enter
+ALIGN 16
+$L$enc_loop8::
+DB 102,15,56,220,209
+DB 102,15,56,220,217
+DB 102,15,56,220,225
+DB 102,15,56,220,233
+DB 102,15,56,220,241
+DB 102,15,56,220,249
+DB 102,68,15,56,220,193
+DB 102,68,15,56,220,201
+$L$enc_loop8_enter::
+ movups xmm1,XMMWORD PTR[rax*1+rcx]
+ add rax,32
+DB 102,15,56,220,208
+DB 102,15,56,220,216
+DB 102,15,56,220,224
+DB 102,15,56,220,232
+DB 102,15,56,220,240
+DB 102,15,56,220,248
+DB 102,68,15,56,220,192
+DB 102,68,15,56,220,200
+ movups xmm0,XMMWORD PTR[((-16))+rax*1+rcx]
+ jnz $L$enc_loop8
+
+DB 102,15,56,220,209
+DB 102,15,56,220,217
+DB 102,15,56,220,225
+DB 102,15,56,220,233
+DB 102,15,56,220,241
+DB 102,15,56,220,249
+DB 102,68,15,56,220,193
+DB 102,68,15,56,220,201
+DB 102,15,56,221,208
+DB 102,15,56,221,216
+DB 102,15,56,221,224
+DB 102,15,56,221,232
+DB 102,15,56,221,240
+DB 102,15,56,221,248
+DB 102,68,15,56,221,192
+DB 102,68,15,56,221,200
+ DB 0F3h,0C3h ;repret
+_aesni_encrypt8 ENDP
+
+ALIGN 16
+_aesni_decrypt8 PROC PRIVATE
+ movups xmm0,XMMWORD PTR[rcx]
+ shl eax,4
+ movups xmm1,XMMWORD PTR[16+rcx]
+ xorps xmm2,xmm0
+ xorps xmm3,xmm0
+ pxor xmm4,xmm0
+ pxor xmm5,xmm0
+ pxor xmm6,xmm0
+ lea rcx,QWORD PTR[32+rax*1+rcx]
+ neg rax
+DB 102,15,56,222,209
+ add rax,16
+ pxor xmm7,xmm0
+DB 102,15,56,222,217
+ pxor xmm8,xmm0
+ pxor xmm9,xmm0
+DB 102,15,56,222,225
+DB 102,15,56,222,233
+DB 102,15,56,222,241
+DB 102,15,56,222,249
+DB 102,68,15,56,222,193
+DB 102,68,15,56,222,201
+ movups xmm0,XMMWORD PTR[((-16))+rax*1+rcx]
+ jmp $L$dec_loop8_enter
+ALIGN 16
+$L$dec_loop8::
+DB 102,15,56,222,209
+DB 102,15,56,222,217
+DB 102,15,56,222,225
+DB 102,15,56,222,233
+DB 102,15,56,222,241
+DB 102,15,56,222,249
+DB 102,68,15,56,222,193
+DB 102,68,15,56,222,201
+$L$dec_loop8_enter::
+ movups xmm1,XMMWORD PTR[rax*1+rcx]
+ add rax,32
+DB 102,15,56,222,208
+DB 102,15,56,222,216
+DB 102,15,56,222,224
+DB 102,15,56,222,232
+DB 102,15,56,222,240
+DB 102,15,56,222,248
+DB 102,68,15,56,222,192
+DB 102,68,15,56,222,200
+ movups xmm0,XMMWORD PTR[((-16))+rax*1+rcx]
+ jnz $L$dec_loop8
+
+DB 102,15,56,222,209
+DB 102,15,56,222,217
+DB 102,15,56,222,225
+DB 102,15,56,222,233
+DB 102,15,56,222,241
+DB 102,15,56,222,249
+DB 102,68,15,56,222,193
+DB 102,68,15,56,222,201
+DB 102,15,56,223,208
+DB 102,15,56,223,216
+DB 102,15,56,223,224
+DB 102,15,56,223,232
+DB 102,15,56,223,240
+DB 102,15,56,223,248
+DB 102,68,15,56,223,192
+DB 102,68,15,56,223,200
+ 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]
+
+
+ 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$ecb_enc_body::
+ 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::
+DB 102,15,56,220,209
+ dec eax
+ movups xmm1,XMMWORD PTR[rcx]
+ lea rcx,QWORD PTR[16+rcx]
+ jnz $L$oop_enc1_3
+DB 102,15,56,221,209
+ movups XMMWORD PTR[rsi],xmm2
+ jmp $L$ecb_ret
+ALIGN 16
+$L$ecb_enc_two::
+ call _aesni_encrypt2
+ 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::
+DB 102,15,56,222,209
+ dec eax
+ movups xmm1,XMMWORD PTR[rcx]
+ lea rcx,QWORD PTR[16+rcx]
+ jnz $L$oop_dec1_4
+DB 102,15,56,223,209
+ movups XMMWORD PTR[rsi],xmm2
+ jmp $L$ecb_ret
+ALIGN 16
+$L$ecb_dec_two::
+ call _aesni_decrypt2
+ 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::
+ 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$ecb_enc_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 xmm6,XMMWORD PTR[r8]
+ movdqa xmm9,XMMWORD PTR[$L$increment64]
+ movdqa xmm7,XMMWORD PTR[$L$bswap_mask]
+
+ shl eax,4
+ mov r10d,16
+ lea r11,QWORD PTR[rcx]
+ movdqu xmm3,XMMWORD PTR[r9]
+ movdqa xmm2,xmm6
+ lea rcx,QWORD PTR[32+rax*1+rcx]
+DB 102,15,56,0,247
+ sub r10,rax
+ jmp $L$ccm64_enc_outer
+ALIGN 16
+$L$ccm64_enc_outer::
+ movups xmm0,XMMWORD PTR[r11]
+ mov rax,r10
+ movups xmm8,XMMWORD PTR[rdi]
+
+ xorps xmm2,xmm0
+ movups xmm1,XMMWORD PTR[16+r11]
+ xorps xmm0,xmm8
+ xorps xmm3,xmm0
+ movups xmm0,XMMWORD PTR[32+r11]
+
+$L$ccm64_enc2_loop::
+DB 102,15,56,220,209
+DB 102,15,56,220,217
+ movups xmm1,XMMWORD PTR[rax*1+rcx]
+ add rax,32
+DB 102,15,56,220,208
+DB 102,15,56,220,216
+ movups xmm0,XMMWORD PTR[((-16))+rax*1+rcx]
+ jnz $L$ccm64_enc2_loop
+DB 102,15,56,220,209
+DB 102,15,56,220,217
+ paddq xmm6,xmm9
+ dec rdx
+DB 102,15,56,221,208
+DB 102,15,56,221,216
+
+ lea rdi,QWORD PTR[16+rdi]
+ xorps xmm8,xmm2
+ movdqa xmm2,xmm6
+ movups XMMWORD PTR[rsi],xmm8
+DB 102,15,56,0,215
+ lea rsi,QWORD PTR[16+rsi]
+ 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 xmm6,XMMWORD PTR[r8]
+ movdqu xmm3,XMMWORD PTR[r9]
+ movdqa xmm9,XMMWORD PTR[$L$increment64]
+ movdqa xmm7,XMMWORD PTR[$L$bswap_mask]
+
+ movaps xmm2,xmm6
+ mov r10d,eax
+ mov r11,rcx
+DB 102,15,56,0,247
+ movups xmm0,XMMWORD PTR[rcx]
+ movups xmm1,XMMWORD PTR[16+rcx]
+ lea rcx,QWORD PTR[32+rcx]
+ xorps xmm2,xmm0
+$L$oop_enc1_5::
+DB 102,15,56,220,209
+ dec eax
+ movups xmm1,XMMWORD PTR[rcx]
+ lea rcx,QWORD PTR[16+rcx]
+ jnz $L$oop_enc1_5
+DB 102,15,56,221,209
+ shl r10d,4
+ mov eax,16
+ movups xmm8,XMMWORD PTR[rdi]
+ paddq xmm6,xmm9
+ lea rdi,QWORD PTR[16+rdi]
+ sub rax,r10
+ lea rcx,QWORD PTR[32+r10*1+r11]
+ mov r10,rax
+ jmp $L$ccm64_dec_outer
+ALIGN 16
+$L$ccm64_dec_outer::
+ xorps xmm8,xmm2
+ movdqa xmm2,xmm6
+ 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]
+ mov rax,r10
+ movups xmm1,XMMWORD PTR[16+r11]
+ xorps xmm8,xmm0
+ xorps xmm2,xmm0
+ xorps xmm3,xmm8
+ movups xmm0,XMMWORD PTR[32+r11]
+ jmp $L$ccm64_dec2_loop
+ALIGN 16
+$L$ccm64_dec2_loop::
+DB 102,15,56,220,209
+DB 102,15,56,220,217
+ movups xmm1,XMMWORD PTR[rax*1+rcx]
+ add rax,32
+DB 102,15,56,220,208
+DB 102,15,56,220,216
+ movups xmm0,XMMWORD PTR[((-16))+rax*1+rcx]
+ jnz $L$ccm64_dec2_loop
+ movups xmm8,XMMWORD PTR[rdi]
+ paddq xmm6,xmm9
+DB 102,15,56,220,209
+DB 102,15,56,220,217
+DB 102,15,56,221,208
+DB 102,15,56,221,216
+ lea rdi,QWORD PTR[16+rdi]
+ jmp $L$ccm64_dec_outer
+
+ALIGN 16
+$L$ccm64_dec_break::
+
+ mov eax,DWORD PTR[240+r11]
+ 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::
+DB 102,15,56,220,217
+ dec eax
+ movups xmm1,XMMWORD PTR[r11]
+ lea r11,QWORD PTR[16+r11]
+ jnz $L$oop_enc1_6
+DB 102,15,56,221,217
+ 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]
+
+
+ lea rax,QWORD PTR[rsp]
+ push rbp
+ sub rsp,288
+ and rsp,-16
+ movaps XMMWORD PTR[(-168)+rax],xmm6
+ movaps XMMWORD PTR[(-152)+rax],xmm7
+ movaps XMMWORD PTR[(-136)+rax],xmm8
+ movaps XMMWORD PTR[(-120)+rax],xmm9
+ movaps XMMWORD PTR[(-104)+rax],xmm10
+ movaps XMMWORD PTR[(-88)+rax],xmm11
+ movaps XMMWORD PTR[(-72)+rax],xmm12
+ movaps XMMWORD PTR[(-56)+rax],xmm13
+ movaps XMMWORD PTR[(-40)+rax],xmm14
+ movaps XMMWORD PTR[(-24)+rax],xmm15
+$L$ctr32_body::
+ lea rbp,QWORD PTR[((-8))+rax]
+
+ cmp rdx,1
+ je $L$ctr32_one_shortcut
+
+ movdqu xmm2,XMMWORD PTR[r8]
+ movdqu xmm0,XMMWORD PTR[rcx]
+ mov r8d,DWORD PTR[12+r8]
+ pxor xmm2,xmm0
+ mov r11d,DWORD PTR[12+rcx]
+ movdqa XMMWORD PTR[rsp],xmm2
+ bswap r8d
+ movdqa xmm3,xmm2
+ movdqa xmm4,xmm2
+ movdqa xmm5,xmm2
+ movdqa XMMWORD PTR[64+rsp],xmm2
+ movdqa XMMWORD PTR[80+rsp],xmm2
+ movdqa XMMWORD PTR[96+rsp],xmm2
+ mov r10,rdx
+ movdqa XMMWORD PTR[112+rsp],xmm2
+
+ lea rax,QWORD PTR[1+r8]
+ lea rdx,QWORD PTR[2+r8]
+ bswap eax
+ bswap edx
+ xor eax,r11d
+ xor edx,r11d
+DB 102,15,58,34,216,3
+ lea rax,QWORD PTR[3+r8]
+ movdqa XMMWORD PTR[16+rsp],xmm3
+DB 102,15,58,34,226,3
+ bswap eax
+ mov rdx,r10
+ lea r10,QWORD PTR[4+r8]
+ movdqa XMMWORD PTR[32+rsp],xmm4
+ xor eax,r11d
+ bswap r10d
+DB 102,15,58,34,232,3
+ xor r10d,r11d
+ movdqa XMMWORD PTR[48+rsp],xmm5
+ lea r9,QWORD PTR[5+r8]
+ mov DWORD PTR[((64+12))+rsp],r10d
+ bswap r9d
+ lea r10,QWORD PTR[6+r8]
+ mov eax,DWORD PTR[240+rcx]
+ xor r9d,r11d
+ bswap r10d
+ mov DWORD PTR[((80+12))+rsp],r9d
+ xor r10d,r11d
+ lea r9,QWORD PTR[7+r8]
+ mov DWORD PTR[((96+12))+rsp],r10d
+ bswap r9d
+ mov r10d,DWORD PTR[((OPENSSL_ia32cap_P+4))]
+ xor r9d,r11d
+ and r10d,71303168
+ mov DWORD PTR[((112+12))+rsp],r9d
+
+ movups xmm1,XMMWORD PTR[16+rcx]
+
+ movdqa xmm6,XMMWORD PTR[64+rsp]
+ movdqa xmm7,XMMWORD PTR[80+rsp]
+
+ cmp rdx,8
+ jb $L$ctr32_tail
+
+ sub rdx,6
+ cmp r10d,4194304
+ je $L$ctr32_6x
+
+ lea rcx,QWORD PTR[128+rcx]
+ sub rdx,2
+ jmp $L$ctr32_loop8
+
+ALIGN 16
+$L$ctr32_6x::
+ shl eax,4
+ mov r10d,48
+ bswap r11d
+ lea rcx,QWORD PTR[32+rax*1+rcx]
+ sub r10,rax
+ jmp $L$ctr32_loop6
+
+ALIGN 16
+$L$ctr32_loop6::
+ add r8d,6
+ movups xmm0,XMMWORD PTR[((-48))+r10*1+rcx]
+DB 102,15,56,220,209
+ mov eax,r8d
+ xor eax,r11d
+DB 102,15,56,220,217
+DB 00fh,038h,0f1h,044h,024h,12
+ lea eax,DWORD PTR[1+r8]
+DB 102,15,56,220,225
+ xor eax,r11d
+DB 00fh,038h,0f1h,044h,024h,28
+DB 102,15,56,220,233
+ lea eax,DWORD PTR[2+r8]
+ xor eax,r11d
+DB 102,15,56,220,241
+DB 00fh,038h,0f1h,044h,024h,44
+ lea eax,DWORD PTR[3+r8]
+DB 102,15,56,220,249
+ movups xmm1,XMMWORD PTR[((-32))+r10*1+rcx]
+ xor eax,r11d
+
+DB 102,15,56,220,208
+DB 00fh,038h,0f1h,044h,024h,60
+ lea eax,DWORD PTR[4+r8]
+DB 102,15,56,220,216
+ xor eax,r11d
+DB 00fh,038h,0f1h,044h,024h,76
+DB 102,15,56,220,224
+ lea eax,DWORD PTR[5+r8]
+ xor eax,r11d
+DB 102,15,56,220,232
+DB 00fh,038h,0f1h,044h,024h,92
+ mov rax,r10
+DB 102,15,56,220,240
+DB 102,15,56,220,248
+ movups xmm0,XMMWORD PTR[((-16))+r10*1+rcx]
+
+ call $L$enc_loop6
+
+ movdqu xmm8,XMMWORD PTR[rdi]
+ movdqu xmm9,XMMWORD PTR[16+rdi]
+ movdqu xmm10,XMMWORD PTR[32+rdi]
+ movdqu xmm11,XMMWORD PTR[48+rdi]
+ movdqu xmm12,XMMWORD PTR[64+rdi]
+ movdqu xmm13,XMMWORD PTR[80+rdi]
+ lea rdi,QWORD PTR[96+rdi]
+ movups xmm1,XMMWORD PTR[((-64))+r10*1+rcx]
+ pxor xmm8,xmm2
+ movaps xmm2,XMMWORD PTR[rsp]
+ pxor xmm9,xmm3
+ movaps xmm3,XMMWORD PTR[16+rsp]
+ pxor xmm10,xmm4
+ movaps xmm4,XMMWORD PTR[32+rsp]
+ pxor xmm11,xmm5
+ movaps xmm5,XMMWORD PTR[48+rsp]
+ pxor xmm12,xmm6
+ movaps xmm6,XMMWORD PTR[64+rsp]
+ pxor xmm13,xmm7
+ movaps xmm7,XMMWORD PTR[80+rsp]
+ movdqu XMMWORD PTR[rsi],xmm8
+ movdqu XMMWORD PTR[16+rsi],xmm9
+ movdqu XMMWORD PTR[32+rsi],xmm10
+ movdqu XMMWORD PTR[48+rsi],xmm11
+ movdqu XMMWORD PTR[64+rsi],xmm12
+ movdqu XMMWORD PTR[80+rsi],xmm13
+ lea rsi,QWORD PTR[96+rsi]
+
+ sub rdx,6
+ jnc $L$ctr32_loop6
+
+ add rdx,6
+ jz $L$ctr32_done
+
+ lea eax,DWORD PTR[((-48))+r10]
+ lea rcx,QWORD PTR[((-80))+r10*1+rcx]
+ neg eax
+ shr eax,4
+ jmp $L$ctr32_tail
+
+ALIGN 32
+$L$ctr32_loop8::
+ add r8d,8
+ movdqa xmm8,XMMWORD PTR[96+rsp]
+DB 102,15,56,220,209
+ mov r9d,r8d
+ movdqa xmm9,XMMWORD PTR[112+rsp]
+DB 102,15,56,220,217
+ bswap r9d
+ movups xmm0,XMMWORD PTR[((32-128))+rcx]
+DB 102,15,56,220,225
+ xor r9d,r11d
+ nop
+DB 102,15,56,220,233
+ mov DWORD PTR[((0+12))+rsp],r9d
+ lea r9,QWORD PTR[1+r8]
+DB 102,15,56,220,241
+DB 102,15,56,220,249
+DB 102,68,15,56,220,193
+DB 102,68,15,56,220,201
+ movups xmm1,XMMWORD PTR[((48-128))+rcx]
+ bswap r9d
+DB 102,15,56,220,208
+DB 102,15,56,220,216
+ xor r9d,r11d
+DB 066h,090h
+DB 102,15,56,220,224
+DB 102,15,56,220,232
+ mov DWORD PTR[((16+12))+rsp],r9d
+ lea r9,QWORD PTR[2+r8]
+DB 102,15,56,220,240
+DB 102,15,56,220,248
+DB 102,68,15,56,220,192
+DB 102,68,15,56,220,200
+ movups xmm0,XMMWORD PTR[((64-128))+rcx]
+ bswap r9d
+DB 102,15,56,220,209
+DB 102,15,56,220,217
+ xor r9d,r11d
+DB 066h,090h
+DB 102,15,56,220,225
+DB 102,15,56,220,233
+ mov DWORD PTR[((32+12))+rsp],r9d
+ lea r9,QWORD PTR[3+r8]
+DB 102,15,56,220,241
+DB 102,15,56,220,249
+DB 102,68,15,56,220,193
+DB 102,68,15,56,220,201
+ movups xmm1,XMMWORD PTR[((80-128))+rcx]
+ bswap r9d
+DB 102,15,56,220,208
+DB 102,15,56,220,216
+ xor r9d,r11d
+DB 066h,090h
+DB 102,15,56,220,224
+DB 102,15,56,220,232
+ mov DWORD PTR[((48+12))+rsp],r9d
+ lea r9,QWORD PTR[4+r8]
+DB 102,15,56,220,240
+DB 102,15,56,220,248
+DB 102,68,15,56,220,192
+DB 102,68,15,56,220,200
+ movups xmm0,XMMWORD PTR[((96-128))+rcx]
+ bswap r9d
+DB 102,15,56,220,209
+DB 102,15,56,220,217
+ xor r9d,r11d
+DB 066h,090h
+DB 102,15,56,220,225
+DB 102,15,56,220,233
+ mov DWORD PTR[((64+12))+rsp],r9d
+ lea r9,QWORD PTR[5+r8]
+DB 102,15,56,220,241
+DB 102,15,56,220,249
+DB 102,68,15,56,220,193
+DB 102,68,15,56,220,201
+ movups xmm1,XMMWORD PTR[((112-128))+rcx]
+ bswap r9d
+DB 102,15,56,220,208
+DB 102,15,56,220,216
+ xor r9d,r11d
+DB 066h,090h
+DB 102,15,56,220,224
+DB 102,15,56,220,232
+ mov DWORD PTR[((80+12))+rsp],r9d
+ lea r9,QWORD PTR[6+r8]
+DB 102,15,56,220,240
+DB 102,15,56,220,248
+DB 102,68,15,56,220,192
+DB 102,68,15,56,220,200
+ movups xmm0,XMMWORD PTR[((128-128))+rcx]
+ bswap r9d
+DB 102,15,56,220,209
+DB 102,15,56,220,217
+ xor r9d,r11d
+DB 066h,090h
+DB 102,15,56,220,225
+DB 102,15,56,220,233
+ mov DWORD PTR[((96+12))+rsp],r9d
+ lea r9,QWORD PTR[7+r8]
+DB 102,15,56,220,241
+DB 102,15,56,220,249
+DB 102,68,15,56,220,193
+DB 102,68,15,56,220,201
+ movups xmm1,XMMWORD PTR[((144-128))+rcx]
+ bswap r9d
+DB 102,15,56,220,208
+DB 102,15,56,220,216
+DB 102,15,56,220,224
+ xor r9d,r11d
+ movdqu xmm10,XMMWORD PTR[rdi]
+DB 102,15,56,220,232
+ mov DWORD PTR[((112+12))+rsp],r9d
+ cmp eax,11
+DB 102,15,56,220,240
+DB 102,15,56,220,248
+DB 102,68,15,56,220,192
+DB 102,68,15,56,220,200
+ movups xmm0,XMMWORD PTR[((160-128))+rcx]
+
+ jb $L$ctr32_enc_done
+
+DB 102,15,56,220,209
+DB 102,15,56,220,217
+DB 102,15,56,220,225
+DB 102,15,56,220,233
+DB 102,15,56,220,241
+DB 102,15,56,220,249
+DB 102,68,15,56,220,193
+DB 102,68,15,56,220,201
+ movups xmm1,XMMWORD PTR[((176-128))+rcx]
+
+DB 102,15,56,220,208
+DB 102,15,56,220,216
+DB 102,15,56,220,224
+DB 102,15,56,220,232
+DB 102,15,56,220,240
+DB 102,15,56,220,248
+DB 102,68,15,56,220,192
+DB 102,68,15,56,220,200
+ movups xmm0,XMMWORD PTR[((192-128))+rcx]
+ je $L$ctr32_enc_done
+
+DB 102,15,56,220,209
+DB 102,15,56,220,217
+DB 102,15,56,220,225
+DB 102,15,56,220,233
+DB 102,15,56,220,241
+DB 102,15,56,220,249
+DB 102,68,15,56,220,193
+DB 102,68,15,56,220,201
+ movups xmm1,XMMWORD PTR[((208-128))+rcx]
+
+DB 102,15,56,220,208
+DB 102,15,56,220,216
+DB 102,15,56,220,224
+DB 102,15,56,220,232
+DB 102,15,56,220,240
+DB 102,15,56,220,248
+DB 102,68,15,56,220,192
+DB 102,68,15,56,220,200
+ movups xmm0,XMMWORD PTR[((224-128))+rcx]
+ jmp $L$ctr32_enc_done
+
+ALIGN 16
+$L$ctr32_enc_done::
+ movdqu xmm11,XMMWORD PTR[16+rdi]
+ pxor xmm10,xmm0
+ movdqu xmm12,XMMWORD PTR[32+rdi]
+ pxor xmm11,xmm0
+ movdqu xmm13,XMMWORD PTR[48+rdi]
+ pxor xmm12,xmm0
+ movdqu xmm14,XMMWORD PTR[64+rdi]
+ pxor xmm13,xmm0
+ movdqu xmm15,XMMWORD PTR[80+rdi]
+ pxor xmm14,xmm0
+ pxor xmm15,xmm0
+DB 102,15,56,220,209
+DB 102,15,56,220,217
+DB 102,15,56,220,225
+DB 102,15,56,220,233
+DB 102,15,56,220,241
+DB 102,15,56,220,249
+DB 102,68,15,56,220,193
+DB 102,68,15,56,220,201
+ movdqu xmm1,XMMWORD PTR[96+rdi]
+ lea rdi,QWORD PTR[128+rdi]
+
+DB 102,65,15,56,221,210
+ pxor xmm1,xmm0
+ movdqu xmm10,XMMWORD PTR[((112-128))+rdi]
+DB 102,65,15,56,221,219
+ pxor xmm10,xmm0
+ movdqa xmm11,XMMWORD PTR[rsp]
+DB 102,65,15,56,221,228
+DB 102,65,15,56,221,237
+ movdqa xmm12,XMMWORD PTR[16+rsp]
+ movdqa xmm13,XMMWORD PTR[32+rsp]
+DB 102,65,15,56,221,246
+DB 102,65,15,56,221,255
+ movdqa xmm14,XMMWORD PTR[48+rsp]
+ movdqa xmm15,XMMWORD PTR[64+rsp]
+DB 102,68,15,56,221,193
+ movdqa xmm0,XMMWORD PTR[80+rsp]
+ movups xmm1,XMMWORD PTR[((16-128))+rcx]
+DB 102,69,15,56,221,202
+
+ movups XMMWORD PTR[rsi],xmm2
+ movdqa xmm2,xmm11
+ movups XMMWORD PTR[16+rsi],xmm3
+ movdqa xmm3,xmm12
+ movups XMMWORD PTR[32+rsi],xmm4
+ movdqa xmm4,xmm13
+ movups XMMWORD PTR[48+rsi],xmm5
+ movdqa xmm5,xmm14
+ movups XMMWORD PTR[64+rsi],xmm6
+ movdqa xmm6,xmm15
+ movups XMMWORD PTR[80+rsi],xmm7
+ movdqa xmm7,xmm0
+ movups XMMWORD PTR[96+rsi],xmm8
+ movups XMMWORD PTR[112+rsi],xmm9
+ lea rsi,QWORD PTR[128+rsi]
+
+ sub rdx,8
+ jnc $L$ctr32_loop8
+
+ add rdx,8
+ jz $L$ctr32_done
+ lea rcx,QWORD PTR[((-128))+rcx]
+
+$L$ctr32_tail::
+ lea rcx,QWORD PTR[16+rcx]
+ cmp rdx,4
+ jb $L$ctr32_loop3
+ je $L$ctr32_loop4
+
+ shl eax,4
+ movdqa xmm8,XMMWORD PTR[96+rsp]
+ pxor xmm9,xmm9
+
+ movups xmm0,XMMWORD PTR[16+rcx]
+DB 102,15,56,220,209
+DB 102,15,56,220,217
+ lea rcx,QWORD PTR[((32-16))+rax*1+rcx]
+ neg rax
+DB 102,15,56,220,225
+ add rax,16
+ movups xmm10,XMMWORD PTR[rdi]
+DB 102,15,56,220,233
+DB 102,15,56,220,241
+ movups xmm11,XMMWORD PTR[16+rdi]
+ movups xmm12,XMMWORD PTR[32+rdi]
+DB 102,15,56,220,249
+DB 102,68,15,56,220,193
+
+ call $L$enc_loop8_enter
+
+ movdqu xmm13,XMMWORD PTR[48+rdi]
+ pxor xmm2,xmm10
+ movdqu xmm10,XMMWORD PTR[64+rdi]
+ pxor xmm3,xmm11
+ movdqu XMMWORD PTR[rsi],xmm2
+ pxor xmm4,xmm12
+ movdqu XMMWORD PTR[16+rsi],xmm3
+ pxor xmm5,xmm13
+ movdqu XMMWORD PTR[32+rsi],xmm4
+ pxor xmm6,xmm10
+ movdqu XMMWORD PTR[48+rsi],xmm5
+ movdqu XMMWORD PTR[64+rsi],xmm6
+ cmp rdx,6
+ jb $L$ctr32_done
+
+ movups xmm11,XMMWORD PTR[80+rdi]
+ xorps xmm7,xmm11
+ movups XMMWORD PTR[80+rsi],xmm7
+ je $L$ctr32_done
+
+ movups xmm12,XMMWORD PTR[96+rdi]
+ xorps xmm8,xmm12
+ movups XMMWORD PTR[96+rsi],xmm8
+ jmp $L$ctr32_done
+
+ALIGN 32
+$L$ctr32_loop4::
+DB 102,15,56,220,209
+ lea rcx,QWORD PTR[16+rcx]
+ dec eax
+DB 102,15,56,220,217
+DB 102,15,56,220,225
+DB 102,15,56,220,233
+ movups xmm1,XMMWORD PTR[rcx]
+ jnz $L$ctr32_loop4
+DB 102,15,56,221,209
+DB 102,15,56,221,217
+ movups xmm10,XMMWORD PTR[rdi]
+ movups xmm11,XMMWORD PTR[16+rdi]
+DB 102,15,56,221,225
+DB 102,15,56,221,233
+ movups xmm12,XMMWORD PTR[32+rdi]
+ movups xmm13,XMMWORD PTR[48+rdi]
+
+ xorps xmm2,xmm10
+ movups XMMWORD PTR[rsi],xmm2
+ xorps xmm3,xmm11
+ movups XMMWORD PTR[16+rsi],xmm3
+ pxor xmm4,xmm12
+ movdqu XMMWORD PTR[32+rsi],xmm4
+ pxor xmm5,xmm13
+ movdqu XMMWORD PTR[48+rsi],xmm5
+ jmp $L$ctr32_done
+
+ALIGN 32
+$L$ctr32_loop3::
+DB 102,15,56,220,209
+ lea rcx,QWORD PTR[16+rcx]
+ dec eax
+DB 102,15,56,220,217
+DB 102,15,56,220,225
+ movups xmm1,XMMWORD PTR[rcx]
+ jnz $L$ctr32_loop3
+DB 102,15,56,221,209
+DB 102,15,56,221,217
+DB 102,15,56,221,225
+
+ movups xmm10,XMMWORD PTR[rdi]
+ xorps xmm2,xmm10
+ movups XMMWORD PTR[rsi],xmm2
+ cmp rdx,2
+ jb $L$ctr32_done
+
+ movups xmm11,XMMWORD PTR[16+rdi]
+ xorps xmm3,xmm11
+ movups XMMWORD PTR[16+rsi],xmm3
+ je $L$ctr32_done
+
+ movups xmm12,XMMWORD PTR[32+rdi]
+ xorps xmm4,xmm12
+ movups XMMWORD PTR[32+rsi],xmm4
+ jmp $L$ctr32_done
+
+ALIGN 16
+$L$ctr32_one_shortcut::
+ movups xmm2,XMMWORD PTR[r8]
+ movups xmm10,XMMWORD PTR[rdi]
+ mov eax,DWORD PTR[240+rcx]
+ movups xmm0,XMMWORD PTR[rcx]
+ movups xmm1,XMMWORD PTR[16+rcx]
+ lea rcx,QWORD PTR[32+rcx]
+ xorps xmm2,xmm0
+$L$oop_enc1_7::
+DB 102,15,56,220,209
+ dec eax
+ movups xmm1,XMMWORD PTR[rcx]
+ lea rcx,QWORD PTR[16+rcx]
+ jnz $L$oop_enc1_7
+DB 102,15,56,221,209
+ xorps xmm2,xmm10
+ movups XMMWORD PTR[rsi],xmm2
+ jmp $L$ctr32_done
+
+ALIGN 16
+$L$ctr32_done::
+ movaps xmm6,XMMWORD PTR[((-160))+rbp]
+ movaps xmm7,XMMWORD PTR[((-144))+rbp]
+ movaps xmm8,XMMWORD PTR[((-128))+rbp]
+ movaps xmm9,XMMWORD PTR[((-112))+rbp]
+ movaps xmm10,XMMWORD PTR[((-96))+rbp]
+ movaps xmm11,XMMWORD PTR[((-80))+rbp]
+ movaps xmm12,XMMWORD PTR[((-64))+rbp]
+ movaps xmm13,XMMWORD PTR[((-48))+rbp]
+ movaps xmm14,XMMWORD PTR[((-32))+rbp]
+ movaps xmm15,XMMWORD PTR[((-16))+rbp]
+ lea rsp,QWORD PTR[rbp]
+ pop rbp
+$L$ctr32_epilogue::
+ 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,272
+ and rsp,-16
+ movaps XMMWORD PTR[(-168)+rax],xmm6
+ movaps XMMWORD PTR[(-152)+rax],xmm7
+ movaps XMMWORD PTR[(-136)+rax],xmm8
+ movaps XMMWORD PTR[(-120)+rax],xmm9
+ movaps XMMWORD PTR[(-104)+rax],xmm10
+ movaps XMMWORD PTR[(-88)+rax],xmm11
+ movaps XMMWORD PTR[(-72)+rax],xmm12
+ movaps XMMWORD PTR[(-56)+rax],xmm13
+ movaps XMMWORD PTR[(-40)+rax],xmm14
+ movaps XMMWORD PTR[(-24)+rax],xmm15
+$L$xts_enc_body::
+ lea rbp,QWORD PTR[((-8))+rax]
+ movups xmm2,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 xmm2,xmm0
+$L$oop_enc1_8::
+DB 102,15,56,220,209
+ dec eax
+ movups xmm1,XMMWORD PTR[r8]
+ lea r8,QWORD PTR[16+r8]
+ jnz $L$oop_enc1_8
+DB 102,15,56,221,209
+ movups xmm0,XMMWORD PTR[rcx]
+ mov r11,rcx
+ mov eax,r10d
+ shl r10d,4
+ mov r9,rdx
+ and rdx,-16
+
+ movups xmm1,XMMWORD PTR[16+r10*1+rcx]
+
+ movdqa xmm8,XMMWORD PTR[$L$xts_magic]
+ movdqa xmm15,xmm2
+ pshufd xmm9,xmm2,05fh
+ pxor xmm1,xmm0
+ movdqa xmm14,xmm9
+ paddd xmm9,xmm9
+ movdqa xmm10,xmm15
+ psrad xmm14,31
+ paddq xmm15,xmm15
+ pand xmm14,xmm8
+ pxor xmm10,xmm0
+ pxor xmm15,xmm14
+ movdqa xmm14,xmm9
+ paddd xmm9,xmm9
+ movdqa xmm11,xmm15
+ psrad xmm14,31
+ paddq xmm15,xmm15
+ pand xmm14,xmm8
+ pxor xmm11,xmm0
+ pxor xmm15,xmm14
+ movdqa xmm14,xmm9
+ paddd xmm9,xmm9
+ movdqa xmm12,xmm15
+ psrad xmm14,31
+ paddq xmm15,xmm15
+ pand xmm14,xmm8
+ pxor xmm12,xmm0
+ pxor xmm15,xmm14
+ movdqa xmm14,xmm9
+ paddd xmm9,xmm9
+ movdqa xmm13,xmm15
+ psrad xmm14,31
+ paddq xmm15,xmm15
+ pand xmm14,xmm8
+ pxor xmm13,xmm0
+ pxor xmm15,xmm14
+ movdqa xmm14,xmm15
+ psrad xmm9,31
+ paddq xmm15,xmm15
+ pand xmm9,xmm8
+ pxor xmm14,xmm0
+ pxor xmm15,xmm9
+ movaps XMMWORD PTR[96+rsp],xmm1
+
+ sub rdx,16*6
+ jc $L$xts_enc_short
+
+ mov eax,16+96
+ lea rcx,QWORD PTR[32+r10*1+r11]
+ sub rax,r10
+ movups xmm1,XMMWORD PTR[16+r11]
+ mov r10,rax
+ lea r8,QWORD PTR[$L$xts_magic]
+ jmp $L$xts_enc_grandloop
+
+ALIGN 32
+$L$xts_enc_grandloop::
+ movdqu xmm2,XMMWORD PTR[rdi]
+ movdqa xmm8,xmm0
+ movdqu xmm3,XMMWORD PTR[16+rdi]
+ pxor xmm2,xmm10
+ movdqu xmm4,XMMWORD PTR[32+rdi]
+ pxor xmm3,xmm11
+DB 102,15,56,220,209
+ movdqu xmm5,XMMWORD PTR[48+rdi]
+ pxor xmm4,xmm12
+DB 102,15,56,220,217
+ movdqu xmm6,XMMWORD PTR[64+rdi]
+ pxor xmm5,xmm13
+DB 102,15,56,220,225
+ movdqu xmm7,XMMWORD PTR[80+rdi]
+ pxor xmm8,xmm15
+ movdqa xmm9,XMMWORD PTR[96+rsp]
+ pxor xmm6,xmm14
+DB 102,15,56,220,233
+ movups xmm0,XMMWORD PTR[32+r11]
+ lea rdi,QWORD PTR[96+rdi]
+ pxor xmm7,xmm8
+
+ pxor xmm10,xmm9
+DB 102,15,56,220,241
+ pxor xmm11,xmm9
+ movdqa XMMWORD PTR[rsp],xmm10
+DB 102,15,56,220,249
+ movups xmm1,XMMWORD PTR[48+r11]
+ pxor xmm12,xmm9
+
+DB 102,15,56,220,208
+ pxor xmm13,xmm9
+ movdqa XMMWORD PTR[16+rsp],xmm11
+DB 102,15,56,220,216
+ pxor xmm14,xmm9
+ movdqa XMMWORD PTR[32+rsp],xmm12
+DB 102,15,56,220,224
+DB 102,15,56,220,232
+ pxor xmm8,xmm9
+ movdqa XMMWORD PTR[64+rsp],xmm14
+DB 102,15,56,220,240
+DB 102,15,56,220,248
+ movups xmm0,XMMWORD PTR[64+r11]
+ movdqa XMMWORD PTR[80+rsp],xmm8
+ pshufd xmm9,xmm15,05fh
+ jmp $L$xts_enc_loop6
+ALIGN 32
+$L$xts_enc_loop6::
+DB 102,15,56,220,209
+DB 102,15,56,220,217
+DB 102,15,56,220,225
+DB 102,15,56,220,233
+DB 102,15,56,220,241
+DB 102,15,56,220,249
+ movups xmm1,XMMWORD PTR[((-64))+rax*1+rcx]
+ add rax,32
+
+DB 102,15,56,220,208
+DB 102,15,56,220,216
+DB 102,15,56,220,224
+DB 102,15,56,220,232
+DB 102,15,56,220,240
+DB 102,15,56,220,248
+ movups xmm0,XMMWORD PTR[((-80))+rax*1+rcx]
+ jnz $L$xts_enc_loop6
+
+ movdqa xmm8,XMMWORD PTR[r8]
+ movdqa xmm14,xmm9
+ paddd xmm9,xmm9
+DB 102,15,56,220,209
+ paddq xmm15,xmm15
+ psrad xmm14,31
+DB 102,15,56,220,217
+ pand xmm14,xmm8
+ movups xmm10,XMMWORD PTR[r11]
+DB 102,15,56,220,225
+DB 102,15,56,220,233
+DB 102,15,56,220,241
+ pxor xmm15,xmm14
+ movaps xmm11,xmm10
+DB 102,15,56,220,249
+ movups xmm1,XMMWORD PTR[((-64))+rcx]
+
+ movdqa xmm14,xmm9
+DB 102,15,56,220,208
+ paddd xmm9,xmm9
+ pxor xmm10,xmm15
+DB 102,15,56,220,216
+ psrad xmm14,31
+ paddq xmm15,xmm15
+DB 102,15,56,220,224
+DB 102,15,56,220,232
+ pand xmm14,xmm8
+ movaps xmm12,xmm11
+DB 102,15,56,220,240
+ pxor xmm15,xmm14
+ movdqa xmm14,xmm9
+DB 102,15,56,220,248
+ movups xmm0,XMMWORD PTR[((-48))+rcx]
+
+ paddd xmm9,xmm9
+DB 102,15,56,220,209
+ pxor xmm11,xmm15
+ psrad xmm14,31
+DB 102,15,56,220,217
+ paddq xmm15,xmm15
+ pand xmm14,xmm8
+DB 102,15,56,220,225
+DB 102,15,56,220,233
+ movdqa XMMWORD PTR[48+rsp],xmm13
+ pxor xmm15,xmm14
+DB 102,15,56,220,241
+ movaps xmm13,xmm12
+ movdqa xmm14,xmm9
+DB 102,15,56,220,249
+ movups xmm1,XMMWORD PTR[((-32))+rcx]
+
+ paddd xmm9,xmm9
+DB 102,15,56,220,208
+ pxor xmm12,xmm15
+ psrad xmm14,31
+DB 102,15,56,220,216
+ paddq xmm15,xmm15
+ pand xmm14,xmm8
+DB 102,15,56,220,224
+DB 102,15,56,220,232
+DB 102,15,56,220,240
+ pxor xmm15,xmm14
+ movaps xmm14,xmm13
+DB 102,15,56,220,248
+
+ movdqa xmm0,xmm9
+ paddd xmm9,xmm9
+DB 102,15,56,220,209
+ pxor xmm13,xmm15
+ psrad xmm0,31
+DB 102,15,56,220,217
+ paddq xmm15,xmm15
+ pand xmm0,xmm8
+DB 102,15,56,220,225
+DB 102,15,56,220,233
+ pxor xmm15,xmm0
+ movups xmm0,XMMWORD PTR[r11]
+DB 102,15,56,220,241
+DB 102,15,56,220,249
+ movups xmm1,XMMWORD PTR[16+r11]
+
+ pxor xmm14,xmm15
+DB 102,15,56,221,84,36,0
+ psrad xmm9,31
+ paddq xmm15,xmm15
+DB 102,15,56,221,92,36,16
+DB 102,15,56,221,100,36,32
+ pand xmm9,xmm8
+ mov rax,r10
+DB 102,15,56,221,108,36,48
+DB 102,15,56,221,116,36,64
+DB 102,15,56,221,124,36,80
+ pxor xmm15,xmm9
+
+ lea rsi,QWORD PTR[96+rsi]
+ movups XMMWORD PTR[(-96)+rsi],xmm2
+ movups XMMWORD PTR[(-80)+rsi],xmm3
+ movups XMMWORD PTR[(-64)+rsi],xmm4
+ movups XMMWORD PTR[(-48)+rsi],xmm5
+ movups XMMWORD PTR[(-32)+rsi],xmm6
+ movups XMMWORD PTR[(-16)+rsi],xmm7
+ sub rdx,16*6
+ jnc $L$xts_enc_grandloop
+
+ mov eax,16+96
+ sub eax,r10d
+ mov rcx,r11
+ shr eax,4
+
+$L$xts_enc_short::
+ mov r10d,eax
+ pxor xmm10,xmm0
+ add rdx,16*6
+ jz $L$xts_enc_done
+
+ pxor xmm11,xmm0
+ cmp rdx,020h
+ jb $L$xts_enc_one
+ pxor xmm12,xmm0
+ je $L$xts_enc_two
+
+ pxor xmm13,xmm0
+ cmp rdx,040h
+ jb $L$xts_enc_three
+ pxor xmm14,xmm0
+ je $L$xts_enc_four
+
+ movdqu xmm2,XMMWORD PTR[rdi]
+ movdqu xmm3,XMMWORD PTR[16+rdi]
+ 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::
+DB 102,15,56,220,209
+ dec eax
+ movups xmm1,XMMWORD PTR[rcx]
+ lea rcx,QWORD PTR[16+rcx]
+ jnz $L$oop_enc1_9
+DB 102,15,56,221,209
+ 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_encrypt2
+
+ 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
+
+ pxor xmm2,xmm10
+ movdqa xmm10,xmm14
+ pxor xmm3,xmm11
+ pxor xmm4,xmm12
+ movdqu XMMWORD PTR[rsi],xmm2
+ pxor xmm5,xmm13
+ movdqu XMMWORD PTR[16+rsi],xmm3
+ movdqu XMMWORD PTR[32+rsi],xmm4
+ movdqu 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::
+DB 102,15,56,220,209
+ dec eax
+ movups xmm1,XMMWORD PTR[rcx]
+ lea rcx,QWORD PTR[16+rcx]
+ jnz $L$oop_enc1_10
+DB 102,15,56,221,209
+ xorps xmm2,xmm10
+ movups XMMWORD PTR[(-16)+rsi],xmm2
+
+$L$xts_enc_ret::
+ movaps xmm6,XMMWORD PTR[((-160))+rbp]
+ movaps xmm7,XMMWORD PTR[((-144))+rbp]
+ movaps xmm8,XMMWORD PTR[((-128))+rbp]
+ movaps xmm9,XMMWORD PTR[((-112))+rbp]
+ movaps xmm10,XMMWORD PTR[((-96))+rbp]
+ movaps xmm11,XMMWORD PTR[((-80))+rbp]
+ movaps xmm12,XMMWORD PTR[((-64))+rbp]
+ movaps xmm13,XMMWORD PTR[((-48))+rbp]
+ movaps xmm14,XMMWORD PTR[((-32))+rbp]
+ movaps xmm15,XMMWORD PTR[((-16))+rbp]
+ 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,272
+ and rsp,-16
+ movaps XMMWORD PTR[(-168)+rax],xmm6
+ movaps XMMWORD PTR[(-152)+rax],xmm7
+ movaps XMMWORD PTR[(-136)+rax],xmm8
+ movaps XMMWORD PTR[(-120)+rax],xmm9
+ movaps XMMWORD PTR[(-104)+rax],xmm10
+ movaps XMMWORD PTR[(-88)+rax],xmm11
+ movaps XMMWORD PTR[(-72)+rax],xmm12
+ movaps XMMWORD PTR[(-56)+rax],xmm13
+ movaps XMMWORD PTR[(-40)+rax],xmm14
+ movaps XMMWORD PTR[(-24)+rax],xmm15
+$L$xts_dec_body::
+ lea rbp,QWORD PTR[((-8))+rax]
+ movups xmm2,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 xmm2,xmm0
+$L$oop_enc1_11::
+DB 102,15,56,220,209
+ dec eax
+ movups xmm1,XMMWORD PTR[r8]
+ lea r8,QWORD PTR[16+r8]
+ jnz $L$oop_enc1_11
+DB 102,15,56,221,209
+ xor eax,eax
+ test rdx,15
+ setnz al
+ shl rax,4
+ sub rdx,rax
+
+ movups xmm0,XMMWORD PTR[rcx]
+ mov r11,rcx
+ mov eax,r10d
+ shl r10d,4
+ mov r9,rdx
+ and rdx,-16
+
+ movups xmm1,XMMWORD PTR[16+r10*1+rcx]
+
+ movdqa xmm8,XMMWORD PTR[$L$xts_magic]
+ movdqa xmm15,xmm2
+ pshufd xmm9,xmm2,05fh
+ pxor xmm1,xmm0
+ movdqa xmm14,xmm9
+ paddd xmm9,xmm9
+ movdqa xmm10,xmm15
+ psrad xmm14,31
+ paddq xmm15,xmm15
+ pand xmm14,xmm8
+ pxor xmm10,xmm0
+ pxor xmm15,xmm14
+ movdqa xmm14,xmm9
+ paddd xmm9,xmm9
+ movdqa xmm11,xmm15
+ psrad xmm14,31
+ paddq xmm15,xmm15
+ pand xmm14,xmm8
+ pxor xmm11,xmm0
+ pxor xmm15,xmm14
+ movdqa xmm14,xmm9
+ paddd xmm9,xmm9
+ movdqa xmm12,xmm15
+ psrad xmm14,31
+ paddq xmm15,xmm15
+ pand xmm14,xmm8
+ pxor xmm12,xmm0
+ pxor xmm15,xmm14
+ movdqa xmm14,xmm9
+ paddd xmm9,xmm9
+ movdqa xmm13,xmm15
+ psrad xmm14,31
+ paddq xmm15,xmm15
+ pand xmm14,xmm8
+ pxor xmm13,xmm0
+ pxor xmm15,xmm14
+ movdqa xmm14,xmm15
+ psrad xmm9,31
+ paddq xmm15,xmm15
+ pand xmm9,xmm8
+ pxor xmm14,xmm0
+ pxor xmm15,xmm9
+ movaps XMMWORD PTR[96+rsp],xmm1
+
+ sub rdx,16*6
+ jc $L$xts_dec_short
+
+ mov eax,16+96
+ lea rcx,QWORD PTR[32+r10*1+r11]
+ sub rax,r10
+ movups xmm1,XMMWORD PTR[16+r11]
+ mov r10,rax
+ lea r8,QWORD PTR[$L$xts_magic]
+ jmp $L$xts_dec_grandloop
+
+ALIGN 32
+$L$xts_dec_grandloop::
+ movdqu xmm2,XMMWORD PTR[rdi]
+ movdqa xmm8,xmm0
+ movdqu xmm3,XMMWORD PTR[16+rdi]
+ pxor xmm2,xmm10
+ movdqu xmm4,XMMWORD PTR[32+rdi]
+ pxor xmm3,xmm11
+DB 102,15,56,222,209
+ movdqu xmm5,XMMWORD PTR[48+rdi]
+ pxor xmm4,xmm12
+DB 102,15,56,222,217
+ movdqu xmm6,XMMWORD PTR[64+rdi]
+ pxor xmm5,xmm13
+DB 102,15,56,222,225
+ movdqu xmm7,XMMWORD PTR[80+rdi]
+ pxor xmm8,xmm15
+ movdqa xmm9,XMMWORD PTR[96+rsp]
+ pxor xmm6,xmm14
+DB 102,15,56,222,233
+ movups xmm0,XMMWORD PTR[32+r11]
+ lea rdi,QWORD PTR[96+rdi]
+ pxor xmm7,xmm8
+
+ pxor xmm10,xmm9
+DB 102,15,56,222,241
+ pxor xmm11,xmm9
+ movdqa XMMWORD PTR[rsp],xmm10
+DB 102,15,56,222,249
+ movups xmm1,XMMWORD PTR[48+r11]
+ pxor xmm12,xmm9
+
+DB 102,15,56,222,208
+ pxor xmm13,xmm9
+ movdqa XMMWORD PTR[16+rsp],xmm11
+DB 102,15,56,222,216
+ pxor xmm14,xmm9
+ movdqa XMMWORD PTR[32+rsp],xmm12
+DB 102,15,56,222,224
+DB 102,15,56,222,232
+ pxor xmm8,xmm9
+ movdqa XMMWORD PTR[64+rsp],xmm14
+DB 102,15,56,222,240
+DB 102,15,56,222,248
+ movups xmm0,XMMWORD PTR[64+r11]
+ movdqa XMMWORD PTR[80+rsp],xmm8
+ pshufd xmm9,xmm15,05fh
+ jmp $L$xts_dec_loop6
+ALIGN 32
+$L$xts_dec_loop6::
+DB 102,15,56,222,209
+DB 102,15,56,222,217
+DB 102,15,56,222,225
+DB 102,15,56,222,233
+DB 102,15,56,222,241
+DB 102,15,56,222,249
+ movups xmm1,XMMWORD PTR[((-64))+rax*1+rcx]
+ add rax,32
+
+DB 102,15,56,222,208
+DB 102,15,56,222,216
+DB 102,15,56,222,224
+DB 102,15,56,222,232
+DB 102,15,56,222,240
+DB 102,15,56,222,248
+ movups xmm0,XMMWORD PTR[((-80))+rax*1+rcx]
+ jnz $L$xts_dec_loop6
+
+ movdqa xmm8,XMMWORD PTR[r8]
+ movdqa xmm14,xmm9
+ paddd xmm9,xmm9
+DB 102,15,56,222,209
+ paddq xmm15,xmm15
+ psrad xmm14,31
+DB 102,15,56,222,217
+ pand xmm14,xmm8
+ movups xmm10,XMMWORD PTR[r11]
+DB 102,15,56,222,225
+DB 102,15,56,222,233
+DB 102,15,56,222,241
+ pxor xmm15,xmm14
+ movaps xmm11,xmm10
+DB 102,15,56,222,249
+ movups xmm1,XMMWORD PTR[((-64))+rcx]
+
+ movdqa xmm14,xmm9
+DB 102,15,56,222,208
+ paddd xmm9,xmm9
+ pxor xmm10,xmm15
+DB 102,15,56,222,216
+ psrad xmm14,31
+ paddq xmm15,xmm15
+DB 102,15,56,222,224
+DB 102,15,56,222,232
+ pand xmm14,xmm8
+ movaps xmm12,xmm11
+DB 102,15,56,222,240
+ pxor xmm15,xmm14
+ movdqa xmm14,xmm9
+DB 102,15,56,222,248
+ movups xmm0,XMMWORD PTR[((-48))+rcx]
+
+ paddd xmm9,xmm9
+DB 102,15,56,222,209
+ pxor xmm11,xmm15
+ psrad xmm14,31
+DB 102,15,56,222,217
+ paddq xmm15,xmm15
+ pand xmm14,xmm8
+DB 102,15,56,222,225
+DB 102,15,56,222,233
+ movdqa XMMWORD PTR[48+rsp],xmm13
+ pxor xmm15,xmm14
+DB 102,15,56,222,241
+ movaps xmm13,xmm12
+ movdqa xmm14,xmm9
+DB 102,15,56,222,249
+ movups xmm1,XMMWORD PTR[((-32))+rcx]
+
+ paddd xmm9,xmm9
+DB 102,15,56,222,208
+ pxor xmm12,xmm15
+ psrad xmm14,31
+DB 102,15,56,222,216
+ paddq xmm15,xmm15
+ pand xmm14,xmm8
+DB 102,15,56,222,224
+DB 102,15,56,222,232
+DB 102,15,56,222,240
+ pxor xmm15,xmm14
+ movaps xmm14,xmm13
+DB 102,15,56,222,248
+
+ movdqa xmm0,xmm9
+ paddd xmm9,xmm9
+DB 102,15,56,222,209
+ pxor xmm13,xmm15
+ psrad xmm0,31
+DB 102,15,56,222,217
+ paddq xmm15,xmm15
+ pand xmm0,xmm8
+DB 102,15,56,222,225
+DB 102,15,56,222,233
+ pxor xmm15,xmm0
+ movups xmm0,XMMWORD PTR[r11]
+DB 102,15,56,222,241
+DB 102,15,56,222,249
+ movups xmm1,XMMWORD PTR[16+r11]
+
+ pxor xmm14,xmm15
+DB 102,15,56,223,84,36,0
+ psrad xmm9,31
+ paddq xmm15,xmm15
+DB 102,15,56,223,92,36,16
+DB 102,15,56,223,100,36,32
+ pand xmm9,xmm8
+ mov rax,r10
+DB 102,15,56,223,108,36,48
+DB 102,15,56,223,116,36,64
+DB 102,15,56,223,124,36,80
+ pxor xmm15,xmm9
+
+ lea rsi,QWORD PTR[96+rsi]
+ movups XMMWORD PTR[(-96)+rsi],xmm2
+ movups XMMWORD PTR[(-80)+rsi],xmm3
+ movups XMMWORD PTR[(-64)+rsi],xmm4
+ movups XMMWORD PTR[(-48)+rsi],xmm5
+ movups XMMWORD PTR[(-32)+rsi],xmm6
+ movups XMMWORD PTR[(-16)+rsi],xmm7
+ sub rdx,16*6
+ jnc $L$xts_dec_grandloop
+
+ mov eax,16+96
+ sub eax,r10d
+ mov rcx,r11
+ shr eax,4
+
+$L$xts_dec_short::
+ mov r10d,eax
+ pxor xmm10,xmm0
+ pxor xmm11,xmm0
+ add rdx,16*6
+ jz $L$xts_dec_done
+
+ pxor xmm12,xmm0
+ cmp rdx,020h
+ jb $L$xts_dec_one
+ pxor xmm13,xmm0
+ je $L$xts_dec_two
+
+ pxor xmm14,xmm0
+ cmp rdx,040h
+ jb $L$xts_dec_three
+ je $L$xts_dec_four
+
+ movdqu xmm2,XMMWORD PTR[rdi]
+ movdqu xmm3,XMMWORD PTR[16+rdi]
+ 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::
+DB 102,15,56,222,209
+ dec eax
+ movups xmm1,XMMWORD PTR[rcx]
+ lea rcx,QWORD PTR[16+rcx]
+ jnz $L$oop_dec1_12
+DB 102,15,56,223,209
+ 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_decrypt2
+
+ 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,xmm14
+ 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::
+ 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_decrypt4
+
+ pxor xmm2,xmm10
+ movdqa xmm10,xmm14
+ pxor xmm3,xmm11
+ movdqa xmm11,xmm15
+ pxor xmm4,xmm12
+ movdqu XMMWORD PTR[rsi],xmm2
+ pxor xmm5,xmm13
+ movdqu XMMWORD PTR[16+rsi],xmm3
+ movdqu XMMWORD PTR[32+rsi],xmm4
+ movdqu 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::
+DB 102,15,56,222,209
+ dec eax
+ movups xmm1,XMMWORD PTR[rcx]
+ lea rcx,QWORD PTR[16+rcx]
+ jnz $L$oop_dec1_13
+DB 102,15,56,223,209
+ 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::
+DB 102,15,56,222,209
+ dec eax
+ movups xmm1,XMMWORD PTR[rcx]
+ lea rcx,QWORD PTR[16+rcx]
+ jnz $L$oop_dec1_14
+DB 102,15,56,223,209
+ xorps xmm2,xmm10
+ movups XMMWORD PTR[rsi],xmm2
+
+$L$xts_dec_ret::
+ movaps xmm6,XMMWORD PTR[((-160))+rbp]
+ movaps xmm7,XMMWORD PTR[((-144))+rbp]
+ movaps xmm8,XMMWORD PTR[((-128))+rbp]
+ movaps xmm9,XMMWORD PTR[((-112))+rbp]
+ movaps xmm10,XMMWORD PTR[((-96))+rbp]
+ movaps xmm11,XMMWORD PTR[((-80))+rbp]
+ movaps xmm12,XMMWORD PTR[((-64))+rbp]
+ movaps xmm13,XMMWORD PTR[((-48))+rbp]
+ movaps xmm14,XMMWORD PTR[((-32))+rbp]
+ movaps xmm15,XMMWORD PTR[((-16))+rbp]
+ 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::
+DB 102,15,56,220,209
+ dec eax
+ movups xmm1,XMMWORD PTR[rcx]
+ lea rcx,QWORD PTR[16+rcx]
+ jnz $L$oop_enc1_15
+DB 102,15,56,221,209
+ 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,176
+ and rsp,-16
+ 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_decrypt_body::
+ lea rbp,QWORD PTR[((-8))+rax]
+ movups xmm10,XMMWORD PTR[r8]
+ mov eax,r10d
+ cmp rdx,050h
+ jbe $L$cbc_dec_tail
+
+ movups xmm0,XMMWORD PTR[rcx]
+ movdqu xmm2,XMMWORD PTR[rdi]
+ movdqu xmm3,XMMWORD PTR[16+rdi]
+ movdqa xmm11,xmm2
+ movdqu xmm4,XMMWORD PTR[32+rdi]
+ movdqa xmm12,xmm3
+ movdqu xmm5,XMMWORD PTR[48+rdi]
+ movdqa xmm13,xmm4
+ movdqu xmm6,XMMWORD PTR[64+rdi]
+ movdqa xmm14,xmm5
+ movdqu xmm7,XMMWORD PTR[80+rdi]
+ movdqa xmm15,xmm6
+ mov r9d,DWORD PTR[((OPENSSL_ia32cap_P+4))]
+ cmp rdx,070h
+ jbe $L$cbc_dec_six_or_seven
+
+ and r9d,71303168
+ sub rdx,050h
+ cmp r9d,4194304
+ je $L$cbc_dec_loop6_enter
+ sub rdx,020h
+ lea rcx,QWORD PTR[112+rcx]
+ jmp $L$cbc_dec_loop8_enter
+ALIGN 16
+$L$cbc_dec_loop8::
+ movups XMMWORD PTR[rsi],xmm9
+ lea rsi,QWORD PTR[16+rsi]
+$L$cbc_dec_loop8_enter::
+ movdqu xmm8,XMMWORD PTR[96+rdi]
+ pxor xmm2,xmm0
+ movdqu xmm9,XMMWORD PTR[112+rdi]
+ pxor xmm3,xmm0
+ movups xmm1,XMMWORD PTR[((16-112))+rcx]
+ pxor xmm4,xmm0
+ xor r11,r11
+ cmp rdx,070h
+ pxor xmm5,xmm0
+ pxor xmm6,xmm0
+ pxor xmm7,xmm0
+ pxor xmm8,xmm0
+
+DB 102,15,56,222,209
+ pxor xmm9,xmm0
+ movups xmm0,XMMWORD PTR[((32-112))+rcx]
+DB 102,15,56,222,217
+DB 102,15,56,222,225
+DB 102,15,56,222,233
+DB 102,15,56,222,241
+DB 102,15,56,222,249
+DB 102,68,15,56,222,193
+ setnc r11b
+ shl r11,7
+DB 102,68,15,56,222,201
+ add r11,rdi
+ movups xmm1,XMMWORD PTR[((48-112))+rcx]
+DB 102,15,56,222,208
+DB 102,15,56,222,216
+DB 102,15,56,222,224
+DB 102,15,56,222,232
+DB 102,15,56,222,240
+DB 102,15,56,222,248
+DB 102,68,15,56,222,192
+DB 102,68,15,56,222,200
+ movups xmm0,XMMWORD PTR[((64-112))+rcx]
+ nop
+DB 102,15,56,222,209
+DB 102,15,56,222,217
+DB 102,15,56,222,225
+DB 102,15,56,222,233
+DB 102,15,56,222,241
+DB 102,15,56,222,249
+DB 102,68,15,56,222,193
+DB 102,68,15,56,222,201
+ movups xmm1,XMMWORD PTR[((80-112))+rcx]
+ nop
+DB 102,15,56,222,208
+DB 102,15,56,222,216
+DB 102,15,56,222,224
+DB 102,15,56,222,232
+DB 102,15,56,222,240
+DB 102,15,56,222,248
+DB 102,68,15,56,222,192
+DB 102,68,15,56,222,200
+ movups xmm0,XMMWORD PTR[((96-112))+rcx]
+ nop
+DB 102,15,56,222,209
+DB 102,15,56,222,217
+DB 102,15,56,222,225
+DB 102,15,56,222,233
+DB 102,15,56,222,241
+DB 102,15,56,222,249
+DB 102,68,15,56,222,193
+DB 102,68,15,56,222,201
+ movups xmm1,XMMWORD PTR[((112-112))+rcx]
+ nop
+DB 102,15,56,222,208
+DB 102,15,56,222,216
+DB 102,15,56,222,224
+DB 102,15,56,222,232
+DB 102,15,56,222,240
+DB 102,15,56,222,248
+DB 102,68,15,56,222,192
+DB 102,68,15,56,222,200
+ movups xmm0,XMMWORD PTR[((128-112))+rcx]
+ nop
+DB 102,15,56,222,209
+DB 102,15,56,222,217
+DB 102,15,56,222,225
+DB 102,15,56,222,233
+DB 102,15,56,222,241
+DB 102,15,56,222,249
+DB 102,68,15,56,222,193
+DB 102,68,15,56,222,201
+ movups xmm1,XMMWORD PTR[((144-112))+rcx]
+ cmp eax,11
+DB 102,15,56,222,208
+DB 102,15,56,222,216
+DB 102,15,56,222,224
+DB 102,15,56,222,232
+DB 102,15,56,222,240
+DB 102,15,56,222,248
+DB 102,68,15,56,222,192
+DB 102,68,15,56,222,200
+ movups xmm0,XMMWORD PTR[((160-112))+rcx]
+ jb $L$cbc_dec_done
+DB 102,15,56,222,209
+DB 102,15,56,222,217
+DB 102,15,56,222,225
+DB 102,15,56,222,233
+DB 102,15,56,222,241
+DB 102,15,56,222,249
+DB 102,68,15,56,222,193
+DB 102,68,15,56,222,201
+ movups xmm1,XMMWORD PTR[((176-112))+rcx]
+ nop
+DB 102,15,56,222,208
+DB 102,15,56,222,216
+DB 102,15,56,222,224
+DB 102,15,56,222,232
+DB 102,15,56,222,240
+DB 102,15,56,222,248
+DB 102,68,15,56,222,192
+DB 102,68,15,56,222,200
+ movups xmm0,XMMWORD PTR[((192-112))+rcx]
+ je $L$cbc_dec_done
+DB 102,15,56,222,209
+DB 102,15,56,222,217
+DB 102,15,56,222,225
+DB 102,15,56,222,233
+DB 102,15,56,222,241
+DB 102,15,56,222,249
+DB 102,68,15,56,222,193
+DB 102,68,15,56,222,201
+ movups xmm1,XMMWORD PTR[((208-112))+rcx]
+ nop
+DB 102,15,56,222,208
+DB 102,15,56,222,216
+DB 102,15,56,222,224
+DB 102,15,56,222,232
+DB 102,15,56,222,240
+DB 102,15,56,222,248
+DB 102,68,15,56,222,192
+DB 102,68,15,56,222,200
+ movups xmm0,XMMWORD PTR[((224-112))+rcx]
+ jmp $L$cbc_dec_done
+ALIGN 16
+$L$cbc_dec_done::
+DB 102,15,56,222,209
+DB 102,15,56,222,217
+ pxor xmm10,xmm0
+ pxor xmm11,xmm0
+DB 102,15,56,222,225
+DB 102,15,56,222,233
+ pxor xmm12,xmm0
+ pxor xmm13,xmm0
+DB 102,15,56,222,241
+DB 102,15,56,222,249
+ pxor xmm14,xmm0
+ pxor xmm15,xmm0
+DB 102,68,15,56,222,193
+DB 102,68,15,56,222,201
+ movdqu xmm1,XMMWORD PTR[80+rdi]
+
+DB 102,65,15,56,223,210
+ movdqu xmm10,XMMWORD PTR[96+rdi]
+ pxor xmm1,xmm0
+DB 102,65,15,56,223,219
+ pxor xmm10,xmm0
+ movdqu xmm0,XMMWORD PTR[112+rdi]
+DB 102,65,15,56,223,228
+ lea rdi,QWORD PTR[128+rdi]
+ movdqu xmm11,XMMWORD PTR[r11]
+DB 102,65,15,56,223,237
+DB 102,65,15,56,223,246
+ movdqu xmm12,XMMWORD PTR[16+r11]
+ movdqu xmm13,XMMWORD PTR[32+r11]
+DB 102,65,15,56,223,255
+DB 102,68,15,56,223,193
+ movdqu xmm14,XMMWORD PTR[48+r11]
+ movdqu xmm15,XMMWORD PTR[64+r11]
+DB 102,69,15,56,223,202
+ movdqa xmm10,xmm0
+ movdqu xmm1,XMMWORD PTR[80+r11]
+ movups xmm0,XMMWORD PTR[((-112))+rcx]
+
+ movups XMMWORD PTR[rsi],xmm2
+ movdqa xmm2,xmm11
+ movups XMMWORD PTR[16+rsi],xmm3
+ movdqa xmm3,xmm12
+ movups XMMWORD PTR[32+rsi],xmm4
+ movdqa xmm4,xmm13
+ movups XMMWORD PTR[48+rsi],xmm5
+ movdqa xmm5,xmm14
+ movups XMMWORD PTR[64+rsi],xmm6
+ movdqa xmm6,xmm15
+ movups XMMWORD PTR[80+rsi],xmm7
+ movdqa xmm7,xmm1
+ movups XMMWORD PTR[96+rsi],xmm8
+ lea rsi,QWORD PTR[112+rsi]
+
+ sub rdx,080h
+ ja $L$cbc_dec_loop8
+
+ movaps xmm2,xmm9
+ lea rcx,QWORD PTR[((-112))+rcx]
+ add rdx,070h
+ jle $L$cbc_dec_tail_collected
+ movups XMMWORD PTR[rsi],xmm9
+ lea rsi,QWORD PTR[16+rsi]
+ cmp rdx,050h
+ jbe $L$cbc_dec_tail
+
+ movaps xmm2,xmm11
+$L$cbc_dec_six_or_seven::
+ cmp rdx,060h
+ ja $L$cbc_dec_seven
+
+ movaps xmm8,xmm7
+ call _aesni_decrypt6
+ pxor xmm2,xmm10
+ movaps xmm10,xmm8
+ pxor xmm3,xmm11
+ movdqu XMMWORD PTR[rsi],xmm2
+ pxor xmm4,xmm12
+ movdqu XMMWORD PTR[16+rsi],xmm3
+ pxor xmm5,xmm13
+ movdqu XMMWORD PTR[32+rsi],xmm4
+ pxor xmm6,xmm14
+ movdqu XMMWORD PTR[48+rsi],xmm5
+ pxor xmm7,xmm15
+ movdqu XMMWORD PTR[64+rsi],xmm6
+ lea rsi,QWORD PTR[80+rsi]
+ movdqa xmm2,xmm7
+ jmp $L$cbc_dec_tail_collected
+
+ALIGN 16
+$L$cbc_dec_seven::
+ movups xmm8,XMMWORD PTR[96+rdi]
+ xorps xmm9,xmm9
+ call _aesni_decrypt8
+ movups xmm9,XMMWORD PTR[80+rdi]
+ pxor xmm2,xmm10
+ movups xmm10,XMMWORD PTR[96+rdi]
+ pxor xmm3,xmm11
+ movdqu XMMWORD PTR[rsi],xmm2
+ pxor xmm4,xmm12
+ movdqu XMMWORD PTR[16+rsi],xmm3
+ pxor xmm5,xmm13
+ movdqu XMMWORD PTR[32+rsi],xmm4
+ pxor xmm6,xmm14
+ movdqu XMMWORD PTR[48+rsi],xmm5
+ pxor xmm7,xmm15
+ movdqu XMMWORD PTR[64+rsi],xmm6
+ pxor xmm8,xmm9
+ movdqu XMMWORD PTR[80+rsi],xmm7
+ lea rsi,QWORD PTR[96+rsi]
+ movdqa xmm2,xmm8
+ jmp $L$cbc_dec_tail_collected
+
+ALIGN 16
+$L$cbc_dec_loop6::
+ movups XMMWORD PTR[rsi],xmm7
+ lea rsi,QWORD PTR[16+rsi]
+ movdqu xmm2,XMMWORD PTR[rdi]
+ movdqu xmm3,XMMWORD PTR[16+rdi]
+ movdqa xmm11,xmm2
+ movdqu xmm4,XMMWORD PTR[32+rdi]
+ movdqa xmm12,xmm3
+ movdqu xmm5,XMMWORD PTR[48+rdi]
+ movdqa xmm13,xmm4
+ movdqu xmm6,XMMWORD PTR[64+rdi]
+ movdqa xmm14,xmm5
+ movdqu xmm7,XMMWORD PTR[80+rdi]
+ movdqa xmm15,xmm6
+$L$cbc_dec_loop6_enter::
+ lea rdi,QWORD PTR[96+rdi]
+ movdqa xmm8,xmm7
+
+ call _aesni_decrypt6
+
+ pxor xmm2,xmm10
+ movdqa xmm10,xmm8
+ pxor xmm3,xmm11
+ movdqu XMMWORD PTR[rsi],xmm2
+ pxor xmm4,xmm12
+ movdqu XMMWORD PTR[16+rsi],xmm3
+ pxor xmm5,xmm13
+ movdqu XMMWORD PTR[32+rsi],xmm4
+ pxor xmm6,xmm14
+ mov rcx,r11
+ movdqu XMMWORD PTR[48+rsi],xmm5
+ pxor xmm7,xmm15
+ mov eax,r10d
+ movdqu XMMWORD PTR[64+rsi],xmm6
+ lea rsi,QWORD PTR[80+rsi]
+ sub rdx,060h
+ ja $L$cbc_dec_loop6
+
+ movdqa xmm2,xmm7
+ add rdx,050h
+ jle $L$cbc_dec_tail_collected
+ movups XMMWORD PTR[rsi],xmm7
+ lea rsi,QWORD PTR[16+rsi]
+
+$L$cbc_dec_tail::
+ movups xmm2,XMMWORD PTR[rdi]
+ sub rdx,010h
+ jbe $L$cbc_dec_one
+
+ movups xmm3,XMMWORD PTR[16+rdi]
+ movaps xmm11,xmm2
+ sub rdx,010h
+ jbe $L$cbc_dec_two
+
+ movups xmm4,XMMWORD PTR[32+rdi]
+ movaps xmm12,xmm3
+ sub rdx,010h
+ jbe $L$cbc_dec_three
+
+ movups xmm5,XMMWORD PTR[48+rdi]
+ movaps xmm13,xmm4
+ sub rdx,010h
+ jbe $L$cbc_dec_four
+
+ movups xmm6,XMMWORD PTR[64+rdi]
+ movaps xmm14,xmm5
+ movaps xmm15,xmm6
+ xorps xmm7,xmm7
+ call _aesni_decrypt6
+ pxor xmm2,xmm10
+ movaps xmm10,xmm15
+ pxor xmm3,xmm11
+ movdqu XMMWORD PTR[rsi],xmm2
+ pxor xmm4,xmm12
+ movdqu XMMWORD PTR[16+rsi],xmm3
+ pxor xmm5,xmm13
+ movdqu XMMWORD PTR[32+rsi],xmm4
+ pxor xmm6,xmm14
+ movdqu XMMWORD PTR[48+rsi],xmm5
+ lea rsi,QWORD PTR[64+rsi]
+ movdqa xmm2,xmm6
+ sub rdx,010h
+ jmp $L$cbc_dec_tail_collected
+
+ALIGN 16
+$L$cbc_dec_one::
+ movaps xmm11,xmm2
+ movups xmm0,XMMWORD PTR[rcx]
+ movups xmm1,XMMWORD PTR[16+rcx]
+ lea rcx,QWORD PTR[32+rcx]
+ xorps xmm2,xmm0
+$L$oop_dec1_16::
+DB 102,15,56,222,209
+ dec eax
+ movups xmm1,XMMWORD PTR[rcx]
+ lea rcx,QWORD PTR[16+rcx]
+ jnz $L$oop_dec1_16
+DB 102,15,56,223,209
+ xorps xmm2,xmm10
+ movaps xmm10,xmm11
+ jmp $L$cbc_dec_tail_collected
+ALIGN 16
+$L$cbc_dec_two::
+ movaps xmm12,xmm3
+ call _aesni_decrypt2
+ pxor xmm2,xmm10
+ movaps xmm10,xmm12
+ pxor xmm3,xmm11
+ movdqu XMMWORD PTR[rsi],xmm2
+ movdqa xmm2,xmm3
+ lea rsi,QWORD PTR[16+rsi]
+ jmp $L$cbc_dec_tail_collected
+ALIGN 16
+$L$cbc_dec_three::
+ movaps xmm13,xmm4
+ call _aesni_decrypt3
+ pxor xmm2,xmm10
+ movaps xmm10,xmm13
+ pxor xmm3,xmm11
+ movdqu XMMWORD PTR[rsi],xmm2
+ pxor xmm4,xmm12
+ movdqu XMMWORD PTR[16+rsi],xmm3
+ movdqa xmm2,xmm4
+ lea rsi,QWORD PTR[32+rsi]
+ jmp $L$cbc_dec_tail_collected
+ALIGN 16
+$L$cbc_dec_four::
+ movaps xmm14,xmm5
+ call _aesni_decrypt4
+ pxor xmm2,xmm10
+ movaps xmm10,xmm14
+ pxor xmm3,xmm11
+ movdqu XMMWORD PTR[rsi],xmm2
+ pxor xmm4,xmm12
+ movdqu XMMWORD PTR[16+rsi],xmm3
+ pxor xmm5,xmm13
+ movdqu XMMWORD PTR[32+rsi],xmm4
+ movdqa xmm2,xmm5
+ lea rsi,QWORD PTR[48+rsi]
+ jmp $L$cbc_dec_tail_collected
+
+ALIGN 16
+$L$cbc_dec_tail_collected::
+ movups XMMWORD PTR[r8],xmm10
+ and rdx,15
+ 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]
+ 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[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
+DB 048h,083h,0ECh,008h
+ 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]
+DB 102,15,56,219,192
+DB 102,15,56,219,201
+ 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]
+DB 102,15,56,219,192
+ 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::
+DB 048h,083h,0ECh,008h
+ 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
+DB 102,15,58,223,200,1
+ call $L$key_expansion_128_cold
+DB 102,15,58,223,200,2
+ call $L$key_expansion_128
+DB 102,15,58,223,200,4
+ call $L$key_expansion_128
+DB 102,15,58,223,200,8
+ call $L$key_expansion_128
+DB 102,15,58,223,200,16
+ call $L$key_expansion_128
+DB 102,15,58,223,200,32
+ call $L$key_expansion_128
+DB 102,15,58,223,200,64
+ call $L$key_expansion_128
+DB 102,15,58,223,200,128
+ call $L$key_expansion_128
+DB 102,15,58,223,200,27
+ call $L$key_expansion_128
+DB 102,15,58,223,200,54
+ 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
+DB 102,15,58,223,202,1
+ call $L$key_expansion_192a_cold
+DB 102,15,58,223,202,2
+ call $L$key_expansion_192b
+DB 102,15,58,223,202,4
+ call $L$key_expansion_192a
+DB 102,15,58,223,202,8
+ call $L$key_expansion_192b
+DB 102,15,58,223,202,16
+ call $L$key_expansion_192a
+DB 102,15,58,223,202,32
+ call $L$key_expansion_192b
+DB 102,15,58,223,202,64
+ call $L$key_expansion_192a
+DB 102,15,58,223,202,128
+ 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
+DB 102,15,58,223,202,1
+ call $L$key_expansion_256a_cold
+DB 102,15,58,223,200,1
+ call $L$key_expansion_256b
+DB 102,15,58,223,202,2
+ call $L$key_expansion_256a
+DB 102,15,58,223,200,2
+ call $L$key_expansion_256b
+DB 102,15,58,223,202,4
+ call $L$key_expansion_256a
+DB 102,15,58,223,200,4
+ call $L$key_expansion_256b
+DB 102,15,58,223,202,8
+ call $L$key_expansion_256a
+DB 102,15,58,223,200,8
+ call $L$key_expansion_256b
+DB 102,15,58,223,202,16
+ call $L$key_expansion_256a
+DB 102,15,58,223,200,16
+ call $L$key_expansion_256b
+DB 102,15,58,223,202,32
+ call $L$key_expansion_256a
+DB 102,15,58,223,200,32
+ call $L$key_expansion_256b
+DB 102,15,58,223,202,64
+ 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
+$L$increment1::
+DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
+
+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_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
+ecb_ccm64_se_handler ENDP
+
+
+ALIGN 16
+ctr_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
+
+ mov rax,QWORD PTR[160+r8]
+ lea rsi,QWORD PTR[((-160))+rax]
+ lea rdi,QWORD PTR[512+r8]
+ mov ecx,20
+ DD 0a548f3fch
+
+ jmp $L$common_rbp_tail
+ctr_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,20
+ 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_ccm64_se_handler
+ DD imagerel $L$ecb_enc_body,imagerel $L$ecb_enc_ret
+$L$SEH_info_ccm64_enc::
+DB 9,0,0,0
+ DD imagerel ecb_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 ecb_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 ctr_xts_se_handler
+ DD imagerel $L$ctr32_body,imagerel $L$ctr32_epilogue
+$L$SEH_info_xts_enc::
+DB 9,0,0,0
+ DD imagerel ctr_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 ctr_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/win-x86_64/crypto/aes/bsaes-x86_64.asm b/win-x86_64/crypto/aes/bsaes-x86_64.asm
new file mode 100644
index 0000000..3346a7e
--- /dev/null
+++ b/win-x86_64/crypto/aes/bsaes-x86_64.asm
@@ -0,0 +1,2734 @@
+OPTION DOTNAME
+.text$ SEGMENT ALIGN(256) '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
+ pxor xmm1,xmm8
+ pxor xmm2,xmm8
+DB 102,68,15,56,0,255
+DB 102,15,56,0,199
+ pxor xmm3,xmm8
+ pxor xmm4,xmm8
+DB 102,15,56,0,207
+DB 102,15,56,0,215
+ pxor xmm5,xmm8
+ pxor xmm6,xmm8
+DB 102,15,56,0,223
+DB 102,15,56,0,231
+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]
+ pxor xmm1,XMMWORD PTR[32+rax]
+ pxor xmm2,XMMWORD PTR[48+rax]
+DB 102,68,15,56,0,255
+DB 102,15,56,0,199
+ pxor xmm3,XMMWORD PTR[64+rax]
+ pxor xmm4,XMMWORD PTR[80+rax]
+DB 102,15,56,0,207
+DB 102,15,56,0,215
+ pxor xmm5,XMMWORD PTR[96+rax]
+ pxor xmm6,XMMWORD PTR[112+rax]
+DB 102,15,56,0,223
+DB 102,15,56,0,231
+DB 102,15,56,0,239
+DB 102,15,56,0,247
+ lea rax,QWORD PTR[128+rax]
+$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
+ pxor xmm1,xmm8
+ pxor xmm2,xmm8
+DB 102,68,15,56,0,255
+DB 102,15,56,0,199
+ pxor xmm3,xmm8
+ pxor xmm4,xmm8
+DB 102,15,56,0,207
+DB 102,15,56,0,215
+ pxor xmm5,xmm8
+ pxor xmm6,xmm8
+DB 102,15,56,0,223
+DB 102,15,56,0,231
+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]
+ pxor xmm1,XMMWORD PTR[32+rax]
+ pxor xmm2,XMMWORD PTR[48+rax]
+DB 102,68,15,56,0,255
+DB 102,15,56,0,199
+ pxor xmm3,XMMWORD PTR[64+rax]
+ pxor xmm4,XMMWORD PTR[80+rax]
+DB 102,15,56,0,207
+DB 102,15,56,0,215
+ pxor xmm5,XMMWORD PTR[96+rax]
+ pxor xmm6,XMMWORD PTR[112+rax]
+DB 102,15,56,0,223
+DB 102,15,56,0,231
+DB 102,15,56,0,239
+DB 102,15,56,0,247
+ lea rax,QWORD PTR[128+rax]
+$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
+ pxor xmm1,xmm8
+ pxor xmm2,xmm8
+DB 102,68,15,56,0,255
+DB 102,15,56,0,199
+ pxor xmm3,xmm8
+ pxor xmm4,xmm8
+DB 102,15,56,0,207
+DB 102,15,56,0,215
+ pxor xmm5,xmm8
+ pxor xmm6,xmm8
+DB 102,15,56,0,223
+DB 102,15,56,0,231
+DB 102,15,56,0,239
+DB 102,15,56,0,247
+ lea r11,QWORD PTR[$L$BS0]
+ 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/win-x86_64/crypto/aes/vpaes-x86_64.asm b/win-x86_64/crypto/aes/vpaes-x86_64.asm
new file mode 100644
index 0000000..292f64d
--- /dev/null
+++ b/win-x86_64/crypto/aes/vpaes-x86_64.asm
@@ -0,0 +1,1143 @@
+OPTION DOTNAME
+.text$ SEGMENT ALIGN(256) '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
+ add r9,16
+ pxor xmm0,xmm2
+ lea r10,QWORD PTR[$L$k_mc_backward]
+ jmp $L$enc_entry
+
+ALIGN 16
+$L$enc_loop::
+
+ movdqa xmm4,xmm13
+ movdqa xmm0,xmm12
+DB 102,15,56,0,226
+DB 102,15,56,0,195
+ pxor xmm4,xmm5
+ movdqa xmm5,xmm15
+ pxor xmm0,xmm4
+ movdqa xmm1,XMMWORD PTR[((-64))+r10*1+r11]
+DB 102,15,56,0,234
+ movdqa xmm4,XMMWORD PTR[r10*1+r11]
+ movdqa xmm2,xmm14
+DB 102,15,56,0,211
+ movdqa xmm3,xmm0
+ pxor xmm2,xmm5
+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
+ sub rax,1
+ pxor xmm0,xmm3
+
+$L$enc_entry::
+
+ movdqa xmm1,xmm9
+ movdqa xmm5,xmm11
+ pandn xmm1,xmm0
+ psrld xmm1,4
+ pand xmm0,xmm9
+DB 102,15,56,0,232
+ movdqa xmm3,xmm10
+ pxor xmm0,xmm1
+DB 102,15,56,0,217
+ movdqa xmm4,xmm10
+ pxor xmm3,xmm5
+DB 102,15,56,0,224
+ movdqa xmm2,xmm10
+ pxor xmm4,xmm5
+DB 102,15,56,0,211
+ movdqa xmm3,xmm10
+ pxor xmm2,xmm0
+DB 102,15,56,0,220
+ movdqu xmm5,XMMWORD PTR[r9]
+ 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]
+ movdqa xmm1,XMMWORD PTR[((-16))+r10]
+DB 102,15,56,0,226
+DB 102,15,56,0,203
+ pxor xmm0,xmm4
+ movdqa xmm4,XMMWORD PTR[r10]
+ pxor xmm0,xmm1
+ movdqa xmm1,XMMWORD PTR[16+r10]
+
+DB 102,15,56,0,226
+DB 102,15,56,0,197
+DB 102,15,56,0,203
+ pxor xmm0,xmm4
+ movdqa xmm4,XMMWORD PTR[32+r10]
+ pxor xmm0,xmm1
+ movdqa xmm1,XMMWORD PTR[48+r10]
+
+DB 102,15,56,0,226
+DB 102,15,56,0,197
+DB 102,15,56,0,203
+ pxor xmm0,xmm4
+ movdqa xmm4,XMMWORD PTR[64+r10]
+ pxor xmm0,xmm1
+ movdqa xmm1,XMMWORD PTR[80+r10]
+
+DB 102,15,56,0,226
+DB 102,15,56,0,197
+DB 102,15,56,0,203
+ pxor xmm0,xmm4
+ add r9,16
+DB 102,15,58,15,237,12
+ pxor xmm0,xmm1
+ sub rax,1
+
+$L$dec_entry::
+
+ movdqa xmm1,xmm9
+ pandn xmm1,xmm0
+ movdqa xmm2,xmm11
+ psrld xmm1,4
+ pand xmm0,xmm9
+DB 102,15,56,0,208
+ movdqa xmm3,xmm10
+ pxor xmm0,xmm1
+DB 102,15,56,0,217
+ movdqa xmm4,xmm10
+ pxor xmm3,xmm2
+DB 102,15,56,0,224
+ pxor xmm4,xmm2
+ movdqa xmm2,xmm10
+DB 102,15,56,0,211
+ movdqa xmm3,xmm10
+ pxor xmm2,xmm0
+DB 102,15,56,0,220
+ movdqu xmm0,XMMWORD PTR[r9]
+ pxor xmm3,xmm1
+ 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 xmm1,xmm6,080h
+ pshufd xmm0,xmm7,0FEh
+ pxor xmm6,xmm1
+ pxor xmm1,xmm1
+ pxor xmm6,xmm0
+ movdqa xmm0,xmm6
+ 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/win-x86_64/crypto/bn/modexp512-x86_64.asm b/win-x86_64/crypto/bn/modexp512-x86_64.asm
new file mode 100644
index 0000000..d3e4a61
--- /dev/null
+++ b/win-x86_64/crypto/bn/modexp512-x86_64.asm
@@ -0,0 +1,1887 @@
+OPTION DOTNAME
+.text$ SEGMENT ALIGN(256) '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
+EXTERN __imp_RtlVirtualUnwind:NEAR
+
+ALIGN 16
+mod_exp_512_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$body]
+ cmp rbx,r10
+ jb $L$in_prologue
+
+ mov rax,QWORD PTR[152+r8]
+
+ lea r10,QWORD PTR[$L$epilogue]
+ cmp rbx,r10
+ jae $L$in_prologue
+
+ mov rax,QWORD PTR[rax]
+
+ mov rbx,QWORD PTR[32+rax]
+ mov rbp,QWORD PTR[40+rax]
+ mov r12,QWORD PTR[24+rax]
+ mov r13,QWORD PTR[16+rax]
+ mov r14,QWORD PTR[8+rax]
+ mov r15,QWORD PTR[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$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
+mod_exp_512_se_handler ENDP
+
+.text$ ENDS
+.pdata SEGMENT READONLY ALIGN(4)
+ALIGN 4
+ DD imagerel $L$SEH_begin_mod_exp_512
+ DD imagerel $L$SEH_end_mod_exp_512
+ DD imagerel $L$SEH_info_mod_exp_512
+
+.pdata ENDS
+.xdata SEGMENT READONLY ALIGN(8)
+ALIGN 8
+$L$SEH_info_mod_exp_512::
+DB 9,0,0,0
+ DD imagerel mod_exp_512_se_handler
+
+.xdata ENDS
+END
diff --git a/win-x86_64/crypto/bn/rsaz-avx2.asm b/win-x86_64/crypto/bn/rsaz-avx2.asm
new file mode 100644
index 0000000..f9188f5
--- /dev/null
+++ b/win-x86_64/crypto/bn/rsaz-avx2.asm
@@ -0,0 +1,29 @@
+OPTION DOTNAME
+.text$ SEGMENT ALIGN(256) 'CODE'
+
+PUBLIC rsaz_avx2_eligible
+
+rsaz_avx2_eligible PROC PUBLIC
+ xor eax,eax
+ DB 0F3h,0C3h ;repret
+rsaz_avx2_eligible ENDP
+
+PUBLIC rsaz_1024_sqr_avx2
+PUBLIC rsaz_1024_mul_avx2
+PUBLIC rsaz_1024_norm2red_avx2
+PUBLIC rsaz_1024_red2norm_avx2
+PUBLIC rsaz_1024_scatter5_avx2
+PUBLIC rsaz_1024_gather5_avx2
+
+rsaz_1024_sqr_avx2 PROC PUBLIC
+rsaz_1024_mul_avx2::
+rsaz_1024_norm2red_avx2::
+rsaz_1024_red2norm_avx2::
+rsaz_1024_scatter5_avx2::
+rsaz_1024_gather5_avx2::
+DB 00fh,00bh
+ DB 0F3h,0C3h ;repret
+rsaz_1024_sqr_avx2 ENDP
+
+.text$ ENDS
+END
diff --git a/win-x86_64/crypto/bn/rsaz-x86_64.asm b/win-x86_64/crypto/bn/rsaz-x86_64.asm
new file mode 100644
index 0000000..86e828d
--- /dev/null
+++ b/win-x86_64/crypto/bn/rsaz-x86_64.asm
@@ -0,0 +1,1326 @@
+OPTION DOTNAME
+.text$ SEGMENT ALIGN(256) 'CODE'
+
+EXTERN OPENSSL_ia32cap_P:NEAR
+
+PUBLIC rsaz_512_sqr
+
+ALIGN 32
+rsaz_512_sqr PROC PUBLIC
+ mov QWORD PTR[8+rsp],rdi ;WIN64 prologue
+ mov QWORD PTR[16+rsp],rsi
+ mov rax,rsp
+$L$SEH_begin_rsaz_512_sqr::
+ mov rdi,rcx
+ mov rsi,rdx
+ mov rdx,r8
+ mov rcx,r9
+ mov r8,QWORD PTR[40+rsp]
+
+
+ push rbx
+ push rbp
+ push r12
+ push r13
+ push r14
+ push r15
+
+ sub rsp,128+24
+$L$sqr_body::
+ mov rbp,rdx
+ mov rdx,QWORD PTR[rsi]
+ mov rax,QWORD PTR[8+rsi]
+ mov QWORD PTR[128+rsp],rcx
+ jmp $L$oop_sqr
+
+ALIGN 32
+$L$oop_sqr::
+ mov DWORD PTR[((128+8))+rsp],r8d
+
+ mov rbx,rdx
+ mul rdx
+ mov r8,rax
+ mov rax,QWORD PTR[16+rsi]
+ mov r9,rdx
+
+ mul rbx
+ add r9,rax
+ mov rax,QWORD PTR[24+rsi]
+ mov r10,rdx
+ adc r10,0
+
+ mul rbx
+ add r10,rax
+ mov rax,QWORD PTR[32+rsi]
+ mov r11,rdx
+ adc r11,0
+
+ mul rbx
+ add r11,rax
+ mov rax,QWORD PTR[40+rsi]
+ mov r12,rdx
+ adc r12,0
+
+ mul rbx
+ add r12,rax
+ mov rax,QWORD PTR[48+rsi]
+ mov r13,rdx
+ adc r13,0
+
+ mul rbx
+ add r13,rax
+ mov rax,QWORD PTR[56+rsi]
+ mov r14,rdx
+ adc r14,0
+
+ mul rbx
+ add r14,rax
+ mov rax,rbx
+ mov r15,rdx
+ adc r15,0
+
+ add r8,r8
+ mov rcx,r9
+ adc r9,r9
+
+ mul rax
+ mov QWORD PTR[rsp],rax
+ add r8,rdx
+ adc r9,0
+
+ mov QWORD PTR[8+rsp],r8
+ shr rcx,63
+
+
+ mov r8,QWORD PTR[8+rsi]
+ mov rax,QWORD PTR[16+rsi]
+ mul r8
+ add r10,rax
+ mov rax,QWORD PTR[24+rsi]
+ mov rbx,rdx
+ adc rbx,0
+
+ mul r8
+ add r11,rax
+ mov rax,QWORD PTR[32+rsi]
+ adc rdx,0
+ add r11,rbx
+ mov rbx,rdx
+ adc rbx,0
+
+ mul r8
+ add r12,rax
+ mov rax,QWORD PTR[40+rsi]
+ adc rdx,0
+ add r12,rbx
+ mov rbx,rdx
+ adc rbx,0
+
+ mul r8
+ add r13,rax
+ mov rax,QWORD PTR[48+rsi]
+ adc rdx,0
+ add r13,rbx
+ mov rbx,rdx
+ adc rbx,0
+
+ mul r8
+ add r14,rax
+ mov rax,QWORD PTR[56+rsi]
+ adc rdx,0
+ add r14,rbx
+ mov rbx,rdx
+ adc rbx,0
+
+ mul r8
+ add r15,rax
+ mov rax,r8
+ adc rdx,0
+ add r15,rbx
+ mov r8,rdx
+ mov rdx,r10
+ adc r8,0
+
+ add rdx,rdx
+ lea r10,QWORD PTR[r10*2+rcx]
+ mov rbx,r11
+ adc r11,r11
+
+ mul rax
+ add r9,rax
+ adc r10,rdx
+ adc r11,0
+
+ mov QWORD PTR[16+rsp],r9
+ mov QWORD PTR[24+rsp],r10
+ shr rbx,63
+
+
+ mov r9,QWORD PTR[16+rsi]
+ mov rax,QWORD PTR[24+rsi]
+ mul r9
+ add r12,rax
+ mov rax,QWORD PTR[32+rsi]
+ mov rcx,rdx
+ adc rcx,0
+
+ mul r9
+ add r13,rax
+ mov rax,QWORD PTR[40+rsi]
+ adc rdx,0
+ add r13,rcx
+ mov rcx,rdx
+ adc rcx,0
+
+ mul r9
+ add r14,rax
+ mov rax,QWORD PTR[48+rsi]
+ adc rdx,0
+ add r14,rcx
+ mov rcx,rdx
+ adc rcx,0
+
+ mul r9
+ mov r10,r12
+ lea r12,QWORD PTR[r12*2+rbx]
+ add r15,rax
+ mov rax,QWORD PTR[56+rsi]
+ adc rdx,0
+ add r15,rcx
+ mov rcx,rdx
+ adc rcx,0
+
+ mul r9
+ shr r10,63
+ add r8,rax
+ mov rax,r9
+ adc rdx,0
+ add r8,rcx
+ mov r9,rdx
+ adc r9,0
+
+ mov rcx,r13
+ lea r13,QWORD PTR[r13*2+r10]
+
+ mul rax
+ add r11,rax
+ adc r12,rdx
+ adc r13,0
+
+ mov QWORD PTR[32+rsp],r11
+ mov QWORD PTR[40+rsp],r12
+ shr rcx,63
+
+
+ mov r10,QWORD PTR[24+rsi]
+ mov rax,QWORD PTR[32+rsi]
+ mul r10
+ add r14,rax
+ mov rax,QWORD PTR[40+rsi]
+ mov rbx,rdx
+ adc rbx,0
+
+ mul r10
+ add r15,rax
+ mov rax,QWORD PTR[48+rsi]
+ adc rdx,0
+ add r15,rbx
+ mov rbx,rdx
+ adc rbx,0
+
+ mul r10
+ mov r12,r14
+ lea r14,QWORD PTR[r14*2+rcx]
+ add r8,rax
+ mov rax,QWORD PTR[56+rsi]
+ adc rdx,0
+ add r8,rbx
+ mov rbx,rdx
+ adc rbx,0
+
+ mul r10
+ shr r12,63
+ add r9,rax
+ mov rax,r10
+ adc rdx,0
+ add r9,rbx
+ mov r10,rdx
+ adc r10,0
+
+ mov rbx,r15
+ lea r15,QWORD PTR[r15*2+r12]
+
+ mul rax
+ add r13,rax
+ adc r14,rdx
+ adc r15,0
+
+ mov QWORD PTR[48+rsp],r13
+ mov QWORD PTR[56+rsp],r14
+ shr rbx,63
+
+
+ mov r11,QWORD PTR[32+rsi]
+ mov rax,QWORD PTR[40+rsi]
+ mul r11
+ add r8,rax
+ mov rax,QWORD PTR[48+rsi]
+ mov rcx,rdx
+ adc rcx,0
+
+ mul r11
+ add r9,rax
+ mov rax,QWORD PTR[56+rsi]
+ adc rdx,0
+ mov r12,r8
+ lea r8,QWORD PTR[r8*2+rbx]
+ add r9,rcx
+ mov rcx,rdx
+ adc rcx,0
+
+ mul r11
+ shr r12,63
+ add r10,rax
+ mov rax,r11
+ adc rdx,0
+ add r10,rcx
+ mov r11,rdx
+ adc r11,0
+
+ mov rcx,r9
+ lea r9,QWORD PTR[r9*2+r12]
+
+ mul rax
+ add r15,rax
+ adc r8,rdx
+ adc r9,0
+
+ mov QWORD PTR[64+rsp],r15
+ mov QWORD PTR[72+rsp],r8
+ shr rcx,63
+
+
+ mov r12,QWORD PTR[40+rsi]
+ mov rax,QWORD PTR[48+rsi]
+ mul r12
+ add r10,rax
+ mov rax,QWORD PTR[56+rsi]
+ mov rbx,rdx
+ adc rbx,0
+
+ mul r12
+ add r11,rax
+ mov rax,r12
+ mov r15,r10
+ lea r10,QWORD PTR[r10*2+rcx]
+ adc rdx,0
+ shr r15,63
+ add r11,rbx
+ mov r12,rdx
+ adc r12,0
+
+ mov rbx,r11
+ lea r11,QWORD PTR[r11*2+r15]
+
+ mul rax
+ add r9,rax
+ adc r10,rdx
+ adc r11,0
+
+ mov QWORD PTR[80+rsp],r9
+ mov QWORD PTR[88+rsp],r10
+
+
+ mov r13,QWORD PTR[48+rsi]
+ mov rax,QWORD PTR[56+rsi]
+ mul r13
+ add r12,rax
+ mov rax,r13
+ mov r13,rdx
+ adc r13,0
+
+ xor r14,r14
+ shl rbx,1
+ adc r12,r12
+ adc r13,r13
+ adc r14,r14
+
+ mul rax
+ add r11,rax
+ adc r12,rdx
+ adc r13,0
+
+ mov QWORD PTR[96+rsp],r11
+ mov QWORD PTR[104+rsp],r12
+
+
+ mov rax,QWORD PTR[56+rsi]
+ mul rax
+ add r13,rax
+ adc rdx,0
+
+ add r14,rdx
+
+ mov QWORD PTR[112+rsp],r13
+ mov QWORD PTR[120+rsp],r14
+
+ mov r8,QWORD PTR[rsp]
+ mov r9,QWORD PTR[8+rsp]
+ mov r10,QWORD PTR[16+rsp]
+ mov r11,QWORD PTR[24+rsp]
+ mov r12,QWORD PTR[32+rsp]
+ mov r13,QWORD PTR[40+rsp]
+ mov r14,QWORD PTR[48+rsp]
+ mov r15,QWORD PTR[56+rsp]
+
+ call __rsaz_512_reduce
+
+ add r8,QWORD PTR[64+rsp]
+ adc r9,QWORD PTR[72+rsp]
+ adc r10,QWORD PTR[80+rsp]
+ adc r11,QWORD PTR[88+rsp]
+ adc r12,QWORD PTR[96+rsp]
+ adc r13,QWORD PTR[104+rsp]
+ adc r14,QWORD PTR[112+rsp]
+ adc r15,QWORD PTR[120+rsp]
+ sbb rcx,rcx
+
+ call __rsaz_512_subtract
+
+ mov rdx,r8
+ mov rax,r9
+ mov r8d,DWORD PTR[((128+8))+rsp]
+ mov rsi,rdi
+
+ dec r8d
+ jnz $L$oop_sqr
+
+ lea rax,QWORD PTR[((128+24+48))+rsp]
+ mov r15,QWORD PTR[((-48))+rax]
+ mov r14,QWORD PTR[((-40))+rax]
+ mov r13,QWORD PTR[((-32))+rax]
+ mov r12,QWORD PTR[((-24))+rax]
+ mov rbp,QWORD PTR[((-16))+rax]
+ mov rbx,QWORD PTR[((-8))+rax]
+ lea rsp,QWORD PTR[rax]
+$L$sqr_epilogue::
+ mov rdi,QWORD PTR[8+rsp] ;WIN64 epilogue
+ mov rsi,QWORD PTR[16+rsp]
+ DB 0F3h,0C3h ;repret
+$L$SEH_end_rsaz_512_sqr::
+rsaz_512_sqr ENDP
+PUBLIC rsaz_512_mul
+
+ALIGN 32
+rsaz_512_mul PROC PUBLIC
+ mov QWORD PTR[8+rsp],rdi ;WIN64 prologue
+ mov QWORD PTR[16+rsp],rsi
+ mov rax,rsp
+$L$SEH_begin_rsaz_512_mul::
+ mov rdi,rcx
+ mov rsi,rdx
+ mov rdx,r8
+ mov rcx,r9
+ mov r8,QWORD PTR[40+rsp]
+
+
+ push rbx
+ push rbp
+ push r12
+ push r13
+ push r14
+ push r15
+
+ sub rsp,128+24
+$L$mul_body::
+DB 102,72,15,110,199
+DB 102,72,15,110,201
+ mov QWORD PTR[128+rsp],r8
+ mov rbx,QWORD PTR[rdx]
+ mov rbp,rdx
+ call __rsaz_512_mul
+
+DB 102,72,15,126,199
+DB 102,72,15,126,205
+
+ mov r8,QWORD PTR[rsp]
+ mov r9,QWORD PTR[8+rsp]
+ mov r10,QWORD PTR[16+rsp]
+ mov r11,QWORD PTR[24+rsp]
+ mov r12,QWORD PTR[32+rsp]
+ mov r13,QWORD PTR[40+rsp]
+ mov r14,QWORD PTR[48+rsp]
+ mov r15,QWORD PTR[56+rsp]
+
+ call __rsaz_512_reduce
+ add r8,QWORD PTR[64+rsp]
+ adc r9,QWORD PTR[72+rsp]
+ adc r10,QWORD PTR[80+rsp]
+ adc r11,QWORD PTR[88+rsp]
+ adc r12,QWORD PTR[96+rsp]
+ adc r13,QWORD PTR[104+rsp]
+ adc r14,QWORD PTR[112+rsp]
+ adc r15,QWORD PTR[120+rsp]
+ sbb rcx,rcx
+
+ call __rsaz_512_subtract
+
+ lea rax,QWORD PTR[((128+24+48))+rsp]
+ mov r15,QWORD PTR[((-48))+rax]
+ mov r14,QWORD PTR[((-40))+rax]
+ mov r13,QWORD PTR[((-32))+rax]
+ mov r12,QWORD PTR[((-24))+rax]
+ mov rbp,QWORD PTR[((-16))+rax]
+ mov rbx,QWORD PTR[((-8))+rax]
+ lea rsp,QWORD PTR[rax]
+$L$mul_epilogue::
+ mov rdi,QWORD PTR[8+rsp] ;WIN64 epilogue
+ mov rsi,QWORD PTR[16+rsp]
+ DB 0F3h,0C3h ;repret
+$L$SEH_end_rsaz_512_mul::
+rsaz_512_mul ENDP
+PUBLIC rsaz_512_mul_gather4
+
+ALIGN 32
+rsaz_512_mul_gather4 PROC PUBLIC
+ mov QWORD PTR[8+rsp],rdi ;WIN64 prologue
+ mov QWORD PTR[16+rsp],rsi
+ mov rax,rsp
+$L$SEH_begin_rsaz_512_mul_gather4::
+ mov rdi,rcx
+ mov rsi,rdx
+ mov rdx,r8
+ mov rcx,r9
+ mov r8,QWORD PTR[40+rsp]
+ mov r9,QWORD PTR[48+rsp]
+
+
+ push rbx
+ push rbp
+ push r12
+ push r13
+ push r14
+ push r15
+
+ mov r9d,r9d
+ sub rsp,128+24
+$L$mul_gather4_body::
+ mov eax,DWORD PTR[64+r9*4+rdx]
+DB 102,72,15,110,199
+ mov ebx,DWORD PTR[r9*4+rdx]
+DB 102,72,15,110,201
+ mov QWORD PTR[128+rsp],r8
+
+ shl rax,32
+ or rbx,rax
+ mov rax,QWORD PTR[rsi]
+ mov rcx,QWORD PTR[8+rsi]
+ lea rbp,QWORD PTR[128+r9*4+rdx]
+ mul rbx
+ mov QWORD PTR[rsp],rax
+ mov rax,rcx
+ mov r8,rdx
+
+ mul rbx
+ movd xmm4,DWORD PTR[rbp]
+ add r8,rax
+ mov rax,QWORD PTR[16+rsi]
+ mov r9,rdx
+ adc r9,0
+
+ mul rbx
+ movd xmm5,DWORD PTR[64+rbp]
+ add r9,rax
+ mov rax,QWORD PTR[24+rsi]
+ mov r10,rdx
+ adc r10,0
+
+ mul rbx
+ pslldq xmm5,4
+ add r10,rax
+ mov rax,QWORD PTR[32+rsi]
+ mov r11,rdx
+ adc r11,0
+
+ mul rbx
+ por xmm4,xmm5
+ add r11,rax
+ mov rax,QWORD PTR[40+rsi]
+ mov r12,rdx
+ adc r12,0
+
+ mul rbx
+ add r12,rax
+ mov rax,QWORD PTR[48+rsi]
+ mov r13,rdx
+ adc r13,0
+
+ mul rbx
+ lea rbp,QWORD PTR[128+rbp]
+ add r13,rax
+ mov rax,QWORD PTR[56+rsi]
+ mov r14,rdx
+ adc r14,0
+
+ mul rbx
+DB 102,72,15,126,227
+ add r14,rax
+ mov rax,QWORD PTR[rsi]
+ mov r15,rdx
+ adc r15,0
+
+ lea rdi,QWORD PTR[8+rsp]
+ mov ecx,7
+ jmp $L$oop_mul_gather
+
+ALIGN 32
+$L$oop_mul_gather::
+ mul rbx
+ add r8,rax
+ mov rax,QWORD PTR[8+rsi]
+ mov QWORD PTR[rdi],r8
+ mov r8,rdx
+ adc r8,0
+
+ mul rbx
+ movd xmm4,DWORD PTR[rbp]
+ add r9,rax
+ mov rax,QWORD PTR[16+rsi]
+ adc rdx,0
+ add r8,r9
+ mov r9,rdx
+ adc r9,0
+
+ mul rbx
+ movd xmm5,DWORD PTR[64+rbp]
+ add r10,rax
+ mov rax,QWORD PTR[24+rsi]
+ adc rdx,0
+ add r9,r10
+ mov r10,rdx
+ adc r10,0
+
+ mul rbx
+ pslldq xmm5,4
+ add r11,rax
+ mov rax,QWORD PTR[32+rsi]
+ adc rdx,0
+ add r10,r11
+ mov r11,rdx
+ adc r11,0
+
+ mul rbx
+ por xmm4,xmm5
+ add r12,rax
+ mov rax,QWORD PTR[40+rsi]
+ adc rdx,0
+ add r11,r12
+ mov r12,rdx
+ adc r12,0
+
+ mul rbx
+ add r13,rax
+ mov rax,QWORD PTR[48+rsi]
+ adc rdx,0
+ add r12,r13
+ mov r13,rdx
+ adc r13,0
+
+ mul rbx
+ add r14,rax
+ mov rax,QWORD PTR[56+rsi]
+ adc rdx,0
+ add r13,r14
+ mov r14,rdx
+ adc r14,0
+
+ mul rbx
+DB 102,72,15,126,227
+ add r15,rax
+ mov rax,QWORD PTR[rsi]
+ adc rdx,0
+ add r14,r15
+ mov r15,rdx
+ adc r15,0
+
+ lea rbp,QWORD PTR[128+rbp]
+ lea rdi,QWORD PTR[8+rdi]
+
+ dec ecx
+ jnz $L$oop_mul_gather
+
+ 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
+
+DB 102,72,15,126,199
+DB 102,72,15,126,205
+
+ mov r8,QWORD PTR[rsp]
+ mov r9,QWORD PTR[8+rsp]
+ mov r10,QWORD PTR[16+rsp]
+ mov r11,QWORD PTR[24+rsp]
+ mov r12,QWORD PTR[32+rsp]
+ mov r13,QWORD PTR[40+rsp]
+ mov r14,QWORD PTR[48+rsp]
+ mov r15,QWORD PTR[56+rsp]
+
+ call __rsaz_512_reduce
+ add r8,QWORD PTR[64+rsp]
+ adc r9,QWORD PTR[72+rsp]
+ adc r10,QWORD PTR[80+rsp]
+ adc r11,QWORD PTR[88+rsp]
+ adc r12,QWORD PTR[96+rsp]
+ adc r13,QWORD PTR[104+rsp]
+ adc r14,QWORD PTR[112+rsp]
+ adc r15,QWORD PTR[120+rsp]
+ sbb rcx,rcx
+
+ call __rsaz_512_subtract
+
+ lea rax,QWORD PTR[((128+24+48))+rsp]
+ mov r15,QWORD PTR[((-48))+rax]
+ mov r14,QWORD PTR[((-40))+rax]
+ mov r13,QWORD PTR[((-32))+rax]
+ mov r12,QWORD PTR[((-24))+rax]
+ mov rbp,QWORD PTR[((-16))+rax]
+ mov rbx,QWORD PTR[((-8))+rax]
+ lea rsp,QWORD PTR[rax]
+$L$mul_gather4_epilogue::
+ mov rdi,QWORD PTR[8+rsp] ;WIN64 epilogue
+ mov rsi,QWORD PTR[16+rsp]
+ DB 0F3h,0C3h ;repret
+$L$SEH_end_rsaz_512_mul_gather4::
+rsaz_512_mul_gather4 ENDP
+PUBLIC rsaz_512_mul_scatter4
+
+ALIGN 32
+rsaz_512_mul_scatter4 PROC PUBLIC
+ mov QWORD PTR[8+rsp],rdi ;WIN64 prologue
+ mov QWORD PTR[16+rsp],rsi
+ mov rax,rsp
+$L$SEH_begin_rsaz_512_mul_scatter4::
+ mov rdi,rcx
+ mov rsi,rdx
+ mov rdx,r8
+ mov rcx,r9
+ mov r8,QWORD PTR[40+rsp]
+ mov r9,QWORD PTR[48+rsp]
+
+
+ push rbx
+ push rbp
+ push r12
+ push r13
+ push r14
+ push r15
+
+ mov r9d,r9d
+ sub rsp,128+24
+$L$mul_scatter4_body::
+ lea r8,QWORD PTR[r9*4+r8]
+DB 102,72,15,110,199
+DB 102,72,15,110,202
+DB 102,73,15,110,208
+ mov QWORD PTR[128+rsp],rcx
+
+ mov rbp,rdi
+ mov rbx,QWORD PTR[rdi]
+ call __rsaz_512_mul
+
+DB 102,72,15,126,199
+DB 102,72,15,126,205
+
+ mov r8,QWORD PTR[rsp]
+ mov r9,QWORD PTR[8+rsp]
+ mov r10,QWORD PTR[16+rsp]
+ mov r11,QWORD PTR[24+rsp]
+ mov r12,QWORD PTR[32+rsp]
+ mov r13,QWORD PTR[40+rsp]
+ mov r14,QWORD PTR[48+rsp]
+ mov r15,QWORD PTR[56+rsp]
+
+ call __rsaz_512_reduce
+ add r8,QWORD PTR[64+rsp]
+ adc r9,QWORD PTR[72+rsp]
+ adc r10,QWORD PTR[80+rsp]
+ adc r11,QWORD PTR[88+rsp]
+ adc r12,QWORD PTR[96+rsp]
+ adc r13,QWORD PTR[104+rsp]
+ adc r14,QWORD PTR[112+rsp]
+ adc r15,QWORD PTR[120+rsp]
+DB 102,72,15,126,214
+ sbb rcx,rcx
+
+ call __rsaz_512_subtract
+
+ mov DWORD PTR[rsi],r8d
+ shr r8,32
+ mov DWORD PTR[128+rsi],r9d
+ shr r9,32
+ mov DWORD PTR[256+rsi],r10d
+ shr r10,32
+ mov DWORD PTR[384+rsi],r11d
+ shr r11,32
+ mov DWORD PTR[512+rsi],r12d
+ shr r12,32
+ mov DWORD PTR[640+rsi],r13d
+ shr r13,32
+ mov DWORD PTR[768+rsi],r14d
+ shr r14,32
+ mov DWORD PTR[896+rsi],r15d
+ shr r15,32
+ mov DWORD PTR[64+rsi],r8d
+ mov DWORD PTR[192+rsi],r9d
+ mov DWORD PTR[320+rsi],r10d
+ mov DWORD PTR[448+rsi],r11d
+ mov DWORD PTR[576+rsi],r12d
+ mov DWORD PTR[704+rsi],r13d
+ mov DWORD PTR[832+rsi],r14d
+ mov DWORD PTR[960+rsi],r15d
+
+ lea rax,QWORD PTR[((128+24+48))+rsp]
+ mov r15,QWORD PTR[((-48))+rax]
+ mov r14,QWORD PTR[((-40))+rax]
+ mov r13,QWORD PTR[((-32))+rax]
+ mov r12,QWORD PTR[((-24))+rax]
+ mov rbp,QWORD PTR[((-16))+rax]
+ mov rbx,QWORD PTR[((-8))+rax]
+ lea rsp,QWORD PTR[rax]
+$L$mul_scatter4_epilogue::
+ mov rdi,QWORD PTR[8+rsp] ;WIN64 epilogue
+ mov rsi,QWORD PTR[16+rsp]
+ DB 0F3h,0C3h ;repret
+$L$SEH_end_rsaz_512_mul_scatter4::
+rsaz_512_mul_scatter4 ENDP
+PUBLIC rsaz_512_mul_by_one
+
+ALIGN 32
+rsaz_512_mul_by_one PROC PUBLIC
+ mov QWORD PTR[8+rsp],rdi ;WIN64 prologue
+ mov QWORD PTR[16+rsp],rsi
+ mov rax,rsp
+$L$SEH_begin_rsaz_512_mul_by_one::
+ 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,128+24
+$L$mul_by_one_body::
+ mov rbp,rdx
+ mov QWORD PTR[128+rsp],rcx
+
+ mov r8,QWORD PTR[rsi]
+ pxor xmm0,xmm0
+ mov r9,QWORD PTR[8+rsi]
+ mov r10,QWORD PTR[16+rsi]
+ mov r11,QWORD PTR[24+rsi]
+ mov r12,QWORD PTR[32+rsi]
+ mov r13,QWORD PTR[40+rsi]
+ mov r14,QWORD PTR[48+rsi]
+ mov r15,QWORD PTR[56+rsi]
+
+ movdqa XMMWORD PTR[rsp],xmm0
+ movdqa XMMWORD PTR[16+rsp],xmm0
+ movdqa XMMWORD PTR[32+rsp],xmm0
+ movdqa XMMWORD PTR[48+rsp],xmm0
+ movdqa XMMWORD PTR[64+rsp],xmm0
+ movdqa XMMWORD PTR[80+rsp],xmm0
+ movdqa XMMWORD PTR[96+rsp],xmm0
+ call __rsaz_512_reduce
+ 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 rax,QWORD PTR[((128+24+48))+rsp]
+ mov r15,QWORD PTR[((-48))+rax]
+ mov r14,QWORD PTR[((-40))+rax]
+ mov r13,QWORD PTR[((-32))+rax]
+ mov r12,QWORD PTR[((-24))+rax]
+ mov rbp,QWORD PTR[((-16))+rax]
+ mov rbx,QWORD PTR[((-8))+rax]
+ lea rsp,QWORD PTR[rax]
+$L$mul_by_one_epilogue::
+ mov rdi,QWORD PTR[8+rsp] ;WIN64 epilogue
+ mov rsi,QWORD PTR[16+rsp]
+ DB 0F3h,0C3h ;repret
+$L$SEH_end_rsaz_512_mul_by_one::
+rsaz_512_mul_by_one ENDP
+
+ALIGN 32
+__rsaz_512_reduce PROC PRIVATE
+ mov rbx,r8
+ imul rbx,QWORD PTR[((128+8))+rsp]
+ mov rax,QWORD PTR[rbp]
+ mov ecx,8
+ jmp $L$reduction_loop
+
+ALIGN 32
+$L$reduction_loop::
+ mul rbx
+ mov rax,QWORD PTR[8+rbp]
+ neg r8
+ mov r8,rdx
+ adc r8,0
+
+ mul rbx
+ add r9,rax
+ mov rax,QWORD PTR[16+rbp]
+ adc rdx,0
+ add r8,r9
+ mov r9,rdx
+ adc r9,0
+
+ mul rbx
+ add r10,rax
+ mov rax,QWORD PTR[24+rbp]
+ adc rdx,0
+ add r9,r10
+ mov r10,rdx
+ adc r10,0
+
+ mul rbx
+ add r11,rax
+ mov rax,QWORD PTR[32+rbp]
+ adc rdx,0
+ add r10,r11
+ mov rsi,QWORD PTR[((128+8))+rsp]
+
+
+ adc rdx,0
+ mov r11,rdx
+
+ mul rbx
+ add r12,rax
+ mov rax,QWORD PTR[40+rbp]
+ adc rdx,0
+ imul rsi,r8
+ add r11,r12
+ mov r12,rdx
+ adc r12,0
+
+ mul rbx
+ add r13,rax
+ mov rax,QWORD PTR[48+rbp]
+ adc rdx,0
+ add r12,r13
+ mov r13,rdx
+ adc r13,0
+
+ mul rbx
+ add r14,rax
+ mov rax,QWORD PTR[56+rbp]
+ adc rdx,0
+ add r13,r14
+ mov r14,rdx
+ adc r14,0
+
+ mul rbx
+ mov rbx,rsi
+ add r15,rax
+ mov rax,QWORD PTR[rbp]
+ adc rdx,0
+ add r14,r15
+ mov r15,rdx
+ adc r15,0
+
+ dec ecx
+ jne $L$reduction_loop
+
+ DB 0F3h,0C3h ;repret
+__rsaz_512_reduce ENDP
+
+ALIGN 32
+__rsaz_512_subtract PROC PRIVATE
+ 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
+
+ mov r8,QWORD PTR[rbp]
+ mov r9,QWORD PTR[8+rbp]
+ neg r8
+ not r9
+ and r8,rcx
+ mov r10,QWORD PTR[16+rbp]
+ and r9,rcx
+ not r10
+ mov r11,QWORD PTR[24+rbp]
+ and r10,rcx
+ not r11
+ mov r12,QWORD PTR[32+rbp]
+ and r11,rcx
+ not r12
+ mov r13,QWORD PTR[40+rbp]
+ and r12,rcx
+ not r13
+ mov r14,QWORD PTR[48+rbp]
+ and r13,rcx
+ not r14
+ mov r15,QWORD PTR[56+rbp]
+ and r14,rcx
+ not r15
+ and r15,rcx
+
+ add r8,QWORD PTR[rdi]
+ adc r9,QWORD PTR[8+rdi]
+ adc r10,QWORD PTR[16+rdi]
+ adc r11,QWORD PTR[24+rdi]
+ adc r12,QWORD PTR[32+rdi]
+ adc r13,QWORD PTR[40+rdi]
+ adc r14,QWORD PTR[48+rdi]
+ adc 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
+
+ DB 0F3h,0C3h ;repret
+__rsaz_512_subtract ENDP
+
+ALIGN 32
+__rsaz_512_mul PROC PRIVATE
+ lea rdi,QWORD PTR[8+rsp]
+
+ mov rax,QWORD PTR[rsi]
+ mul rbx
+ mov QWORD PTR[rdi],rax
+ mov rax,QWORD PTR[8+rsi]
+ mov r8,rdx
+
+ mul rbx
+ add r8,rax
+ mov rax,QWORD PTR[16+rsi]
+ mov r9,rdx
+ adc r9,0
+
+ mul rbx
+ add r9,rax
+ mov rax,QWORD PTR[24+rsi]
+ mov r10,rdx
+ adc r10,0
+
+ mul rbx
+ add r10,rax
+ mov rax,QWORD PTR[32+rsi]
+ mov r11,rdx
+ adc r11,0
+
+ mul rbx
+ add r11,rax
+ mov rax,QWORD PTR[40+rsi]
+ mov r12,rdx
+ adc r12,0
+
+ mul rbx
+ add r12,rax
+ mov rax,QWORD PTR[48+rsi]
+ mov r13,rdx
+ adc r13,0
+
+ mul rbx
+ add r13,rax
+ mov rax,QWORD PTR[56+rsi]
+ mov r14,rdx
+ adc r14,0
+
+ mul rbx
+ add r14,rax
+ mov rax,QWORD PTR[rsi]
+ mov r15,rdx
+ adc r15,0
+
+ lea rbp,QWORD PTR[8+rbp]
+ lea rdi,QWORD PTR[8+rdi]
+
+ mov ecx,7
+ jmp $L$oop_mul
+
+ALIGN 32
+$L$oop_mul::
+ mov rbx,QWORD PTR[rbp]
+ mul rbx
+ add r8,rax
+ mov rax,QWORD PTR[8+rsi]
+ mov QWORD PTR[rdi],r8
+ mov r8,rdx
+ adc r8,0
+
+ mul rbx
+ add r9,rax
+ mov rax,QWORD PTR[16+rsi]
+ adc rdx,0
+ add r8,r9
+ mov r9,rdx
+ adc r9,0
+
+ mul rbx
+ add r10,rax
+ mov rax,QWORD PTR[24+rsi]
+ adc rdx,0
+ add r9,r10
+ mov r10,rdx
+ adc r10,0
+
+ mul rbx
+ add r11,rax
+ mov rax,QWORD PTR[32+rsi]
+ adc rdx,0
+ add r10,r11
+ mov r11,rdx
+ adc r11,0
+
+ mul rbx
+ add r12,rax
+ mov rax,QWORD PTR[40+rsi]
+ adc rdx,0
+ add r11,r12
+ mov r12,rdx
+ adc r12,0
+
+ mul rbx
+ add r13,rax
+ mov rax,QWORD PTR[48+rsi]
+ adc rdx,0
+ add r12,r13
+ mov r13,rdx
+ adc r13,0
+
+ mul rbx
+ add r14,rax
+ mov rax,QWORD PTR[56+rsi]
+ adc rdx,0
+ add r13,r14
+ mov r14,rdx
+ lea rbp,QWORD PTR[8+rbp]
+ adc r14,0
+
+ mul rbx
+ add r15,rax
+ mov rax,QWORD PTR[rsi]
+ adc rdx,0
+ add r14,r15
+ mov r15,rdx
+ adc r15,0
+
+ lea rdi,QWORD PTR[8+rdi]
+
+ dec ecx
+ jnz $L$oop_mul
+
+ 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
+
+ DB 0F3h,0C3h ;repret
+__rsaz_512_mul ENDP
+PUBLIC rsaz_512_scatter4
+
+ALIGN 16
+rsaz_512_scatter4 PROC PUBLIC
+ lea rcx,QWORD PTR[r8*4+rcx]
+ mov r9d,8
+ jmp $L$oop_scatter
+ALIGN 16
+$L$oop_scatter::
+ mov rax,QWORD PTR[rdx]
+ lea rdx,QWORD PTR[8+rdx]
+ mov DWORD PTR[rcx],eax
+ shr rax,32
+ mov DWORD PTR[64+rcx],eax
+ lea rcx,QWORD PTR[128+rcx]
+ dec r9d
+ jnz $L$oop_scatter
+ DB 0F3h,0C3h ;repret
+rsaz_512_scatter4 ENDP
+
+PUBLIC rsaz_512_gather4
+
+ALIGN 16
+rsaz_512_gather4 PROC PUBLIC
+ lea rdx,QWORD PTR[r8*4+rdx]
+ mov r9d,8
+ jmp $L$oop_gather
+ALIGN 16
+$L$oop_gather::
+ mov eax,DWORD PTR[rdx]
+ mov r8d,DWORD PTR[64+rdx]
+ lea rdx,QWORD PTR[128+rdx]
+ shl r8,32
+ or rax,r8
+ mov QWORD PTR[rcx],rax
+ lea rcx,QWORD PTR[8+rcx]
+ dec r9d
+ jnz $L$oop_gather
+ DB 0F3h,0C3h ;repret
+rsaz_512_gather4 ENDP
+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$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 rax,QWORD PTR[((128+24+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
+se_handler ENDP
+
+.text$ ENDS
+.pdata SEGMENT READONLY ALIGN(4)
+ALIGN 4
+ DD imagerel $L$SEH_begin_rsaz_512_sqr
+ DD imagerel $L$SEH_end_rsaz_512_sqr
+ DD imagerel $L$SEH_info_rsaz_512_sqr
+
+ DD imagerel $L$SEH_begin_rsaz_512_mul
+ DD imagerel $L$SEH_end_rsaz_512_mul
+ DD imagerel $L$SEH_info_rsaz_512_mul
+
+ DD imagerel $L$SEH_begin_rsaz_512_mul_gather4
+ DD imagerel $L$SEH_end_rsaz_512_mul_gather4
+ DD imagerel $L$SEH_info_rsaz_512_mul_gather4
+
+ DD imagerel $L$SEH_begin_rsaz_512_mul_scatter4
+ DD imagerel $L$SEH_end_rsaz_512_mul_scatter4
+ DD imagerel $L$SEH_info_rsaz_512_mul_scatter4
+
+ DD imagerel $L$SEH_begin_rsaz_512_mul_by_one
+ DD imagerel $L$SEH_end_rsaz_512_mul_by_one
+ DD imagerel $L$SEH_info_rsaz_512_mul_by_one
+
+.pdata ENDS
+.xdata SEGMENT READONLY ALIGN(8)
+ALIGN 8
+$L$SEH_info_rsaz_512_sqr::
+DB 9,0,0,0
+ DD imagerel se_handler
+ DD imagerel $L$sqr_body,imagerel $L$sqr_epilogue
+$L$SEH_info_rsaz_512_mul::
+DB 9,0,0,0
+ DD imagerel se_handler
+ DD imagerel $L$mul_body,imagerel $L$mul_epilogue
+$L$SEH_info_rsaz_512_mul_gather4::
+DB 9,0,0,0
+ DD imagerel se_handler
+ DD imagerel $L$mul_gather4_body,imagerel $L$mul_gather4_epilogue
+$L$SEH_info_rsaz_512_mul_scatter4::
+DB 9,0,0,0
+ DD imagerel se_handler
+ DD imagerel $L$mul_scatter4_body,imagerel $L$mul_scatter4_epilogue
+$L$SEH_info_rsaz_512_mul_by_one::
+DB 9,0,0,0
+ DD imagerel se_handler
+ DD imagerel $L$mul_by_one_body,imagerel $L$mul_by_one_epilogue
+
+.xdata ENDS
+END
diff --git a/win-x86_64/crypto/bn/x86_64-mont.asm b/win-x86_64/crypto/bn/x86_64-mont.asm
new file mode 100644
index 0000000..a409325
--- /dev/null
+++ b/win-x86_64/crypto/bn/x86_64-mont.asm
@@ -0,0 +1,945 @@
+OPTION DOTNAME
+.text$ SEGMENT ALIGN(256) 'CODE'
+
+EXTERN OPENSSL_ia32cap_P:NEAR
+
+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
+ test r9d,7
+ jz $L$sqr8x_enter
+ jmp $L$mul4x_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
+ jne $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
+ jne $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
+ jb $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
+ mov r15,r9
+ALIGN 16
+$L$copy::
+ mov rsi,QWORD PTR[r14*8+rsp]
+ mov rcx,QWORD PTR[r14*8+rdi]
+ xor rsi,rcx
+ and rsi,rax
+ xor rsi,rcx
+ mov QWORD PTR[r14*8+rsp],r14
+ mov QWORD PTR[r14*8+rdi],rsi
+ 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
+ jb $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
+ jb $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
+ jb $L$outer4x
+ mov rdi,QWORD PTR[16+r9*8+rsp]
+ mov rax,QWORD PTR[rsp]
+ 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
+DB 66h, 48h, 0fh, 6eh, 0c0h
+ punpcklqdq xmm0,xmm0
+ mov QWORD PTR[24+r14*8+rdi],rbp
+ xor r14,r14
+
+ mov r15,r9
+ pxor xmm5,xmm5
+ jmp $L$copy4x
+ALIGN 16
+$L$copy4x::
+ movdqu xmm2,XMMWORD PTR[r14*1+rsp]
+ movdqu xmm4,XMMWORD PTR[16+r14*1+rsp]
+ movdqu xmm1,XMMWORD PTR[r14*1+rdi]
+ movdqu xmm3,XMMWORD PTR[16+r14*1+rdi]
+ pxor xmm2,xmm1
+ pxor xmm4,xmm3
+ pand xmm2,xmm0
+ pand xmm4,xmm0
+ pxor xmm2,xmm1
+ pxor xmm4,xmm3
+ movdqu XMMWORD PTR[r14*1+rdi],xmm2
+ movdqu XMMWORD PTR[16+r14*1+rdi],xmm4
+ movdqa XMMWORD PTR[r14*1+rsp],xmm5
+ movdqa XMMWORD PTR[16+r14*1+rsp],xmm5
+
+ lea r14,QWORD PTR[32+r14]
+ dec r15
+ jnz $L$copy4x
+
+ shl r9,2
+ 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
+EXTERN bn_sqr8x_internal:NEAR
+
+
+ALIGN 32
+bn_sqr8x_mont PROC PRIVATE
+ mov QWORD PTR[8+rsp],rdi ;WIN64 prologue
+ mov QWORD PTR[16+rsp],rsi
+ mov rax,rsp
+$L$SEH_begin_bn_sqr8x_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$sqr8x_enter::
+ mov rax,rsp
+ push rbx
+ push rbp
+ push r12
+ push r13
+ push r14
+ push r15
+
+ mov r10d,r9d
+ shl r9d,3
+ shl r10,3+2
+ neg r9
+
+
+
+
+
+
+ lea r11,QWORD PTR[((-64))+r9*4+rsp]
+ mov r8,QWORD PTR[r8]
+ sub r11,rsi
+ and r11,4095
+ cmp r10,r11
+ jb $L$sqr8x_sp_alt
+ sub rsp,r11
+ lea rsp,QWORD PTR[((-64))+r9*4+rsp]
+ jmp $L$sqr8x_sp_done
+
+ALIGN 32
+$L$sqr8x_sp_alt::
+ lea r10,QWORD PTR[((4096-64))+r9*4]
+ lea rsp,QWORD PTR[((-64))+r9*4+rsp]
+ sub r11,r10
+ mov r10,0
+ cmovc r11,r10
+ sub rsp,r11
+$L$sqr8x_sp_done::
+ and rsp,-64
+ mov r10,r9
+ neg r9
+
+ lea r11,QWORD PTR[64+r9*2+rsp]
+ mov QWORD PTR[32+rsp],r8
+ mov QWORD PTR[40+rsp],rax
+$L$sqr8x_body::
+
+ mov rbp,r9
+DB 102,73,15,110,211
+ shr rbp,3+2
+ mov eax,DWORD PTR[((OPENSSL_ia32cap_P+8))]
+ jmp $L$sqr8x_copy_n
+
+ALIGN 32
+$L$sqr8x_copy_n::
+ movq xmm0,QWORD PTR[rcx]
+ movq xmm1,QWORD PTR[8+rcx]
+ movq xmm3,QWORD PTR[16+rcx]
+ movq xmm4,QWORD PTR[24+rcx]
+ lea rcx,QWORD PTR[32+rcx]
+ movdqa XMMWORD PTR[r11],xmm0
+ movdqa XMMWORD PTR[16+r11],xmm1
+ movdqa XMMWORD PTR[32+r11],xmm3
+ movdqa XMMWORD PTR[48+r11],xmm4
+ lea r11,QWORD PTR[64+r11]
+ dec rbp
+ jnz $L$sqr8x_copy_n
+
+ pxor xmm0,xmm0
+DB 102,72,15,110,207
+DB 102,73,15,110,218
+ call bn_sqr8x_internal
+
+ pxor xmm0,xmm0
+ lea rax,QWORD PTR[48+rsp]
+ lea rdx,QWORD PTR[64+r9*2+rsp]
+ shr r9,3+2
+ mov rsi,QWORD PTR[40+rsp]
+ jmp $L$sqr8x_zero
+
+ALIGN 32
+$L$sqr8x_zero::
+ movdqa XMMWORD PTR[rax],xmm0
+ movdqa XMMWORD PTR[16+rax],xmm0
+ movdqa XMMWORD PTR[32+rax],xmm0
+ movdqa XMMWORD PTR[48+rax],xmm0
+ lea rax,QWORD PTR[64+rax]
+ movdqa XMMWORD PTR[rdx],xmm0
+ movdqa XMMWORD PTR[16+rdx],xmm0
+ movdqa XMMWORD PTR[32+rdx],xmm0
+ movdqa XMMWORD PTR[48+rdx],xmm0
+ lea rdx,QWORD PTR[64+rdx]
+ dec r9
+ jnz $L$sqr8x_zero
+
+ mov rax,1
+ mov r15,QWORD PTR[((-48))+rsi]
+ mov r14,QWORD PTR[((-40))+rsi]
+ mov r13,QWORD PTR[((-32))+rsi]
+ mov r12,QWORD PTR[((-24))+rsi]
+ mov rbp,QWORD PTR[((-16))+rsi]
+ mov rbx,QWORD PTR[((-8))+rsi]
+ lea rsp,QWORD PTR[rsi]
+$L$sqr8x_epilogue::
+ mov rdi,QWORD PTR[8+rsp] ;WIN64 epilogue
+ mov rsi,QWORD PTR[16+rsp]
+ DB 0F3h,0C3h ;repret
+$L$SEH_end_bn_sqr8x_mont::
+bn_sqr8x_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
+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
+
+ 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
+
+ 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
+
+ jmp $L$common_seh_tail
+mul_handler ENDP
+
+
+ALIGN 16
+sqr_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
+
+ mov rax,QWORD PTR[40+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
+sqr_handler ENDP
+
+.text$ ENDS
+.pdata SEGMENT READONLY ALIGN(4)
+ALIGN 4
+ DD imagerel $L$SEH_begin_bn_mul_mont
+ DD imagerel $L$SEH_end_bn_mul_mont
+ DD imagerel $L$SEH_info_bn_mul_mont
+
+ DD imagerel $L$SEH_begin_bn_mul4x_mont
+ DD imagerel $L$SEH_end_bn_mul4x_mont
+ DD imagerel $L$SEH_info_bn_mul4x_mont
+
+ DD imagerel $L$SEH_begin_bn_sqr8x_mont
+ DD imagerel $L$SEH_end_bn_sqr8x_mont
+ DD imagerel $L$SEH_info_bn_sqr8x_mont
+.pdata ENDS
+.xdata SEGMENT READONLY ALIGN(8)
+ALIGN 8
+$L$SEH_info_bn_mul_mont::
+DB 9,0,0,0
+ DD imagerel mul_handler
+ DD imagerel $L$mul_body,imagerel $L$mul_epilogue
+$L$SEH_info_bn_mul4x_mont::
+DB 9,0,0,0
+ DD imagerel mul_handler
+ DD imagerel $L$mul4x_body,imagerel $L$mul4x_epilogue
+$L$SEH_info_bn_sqr8x_mont::
+DB 9,0,0,0
+ DD imagerel sqr_handler
+ DD imagerel $L$sqr8x_body,imagerel $L$sqr8x_epilogue
+
+.xdata ENDS
+END
diff --git a/win-x86_64/crypto/bn/x86_64-mont5.asm b/win-x86_64/crypto/bn/x86_64-mont5.asm
new file mode 100644
index 0000000..90c6100
--- /dev/null
+++ b/win-x86_64/crypto/bn/x86_64-mont5.asm
@@ -0,0 +1,2061 @@
+OPTION DOTNAME
+.text$ SEGMENT ALIGN(256) 'CODE'
+
+EXTERN OPENSSL_ia32cap_P:NEAR
+
+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,7
+ jnz $L$mul_enter
+ jmp $L$mul4x_enter
+
+ALIGN 16
+$L$mul_enter::
+ mov r9d,r9d
+ mov rax,rsp
+ mov r10d,DWORD PTR[56+rsp]
+ push rbx
+ push rbp
+ push r12
+ push r13
+ push r14
+ push r15
+ lea rsp,QWORD PTR[((-40))+rsp]
+ movaps XMMWORD PTR[rsp],xmm6
+ movaps XMMWORD PTR[16+rsp],xmm7
+ lea r11,QWORD PTR[2+r9]
+ neg r11
+ lea rsp,QWORD PTR[r11*8+rsp]
+ and rsp,-1024
+
+ mov QWORD PTR[8+r9*8+rsp],rax
+$L$mul_body::
+ mov r12,rdx
+ mov r11,r10
+ shr r10,3
+ and r11,7
+ not r10
+ lea rax,QWORD PTR[$L$magic_masks]
+ and r10,3
+ lea r12,QWORD PTR[96+r11*8+r12]
+ movq xmm4,QWORD PTR[r10*8+rax]
+ movq xmm5,QWORD PTR[8+r10*8+rax]
+ movq xmm6,QWORD PTR[16+r10*8+rax]
+ movq xmm7,QWORD PTR[24+r10*8+rax]
+
+ movq xmm0,QWORD PTR[(((-96)))+r12]
+ movq xmm1,QWORD PTR[((-32))+r12]
+ pand xmm0,xmm4
+ movq xmm2,QWORD PTR[32+r12]
+ pand xmm1,xmm5
+ movq xmm3,QWORD PTR[96+r12]
+ pand xmm2,xmm6
+ por xmm0,xmm1
+ pand xmm3,xmm7
+ por xmm0,xmm2
+ lea r12,QWORD PTR[256+r12]
+ por xmm0,xmm3
+
+DB 102,72,15,126,195
+
+ mov r8,QWORD PTR[r8]
+ mov rax,QWORD PTR[rsi]
+
+ xor r14,r14
+ xor r15,r15
+
+ movq xmm0,QWORD PTR[(((-96)))+r12]
+ movq xmm1,QWORD PTR[((-32))+r12]
+ pand xmm0,xmm4
+ movq xmm2,QWORD PTR[32+r12]
+ pand xmm1,xmm5
+
+ mov rbp,r8
+ mul rbx
+ mov r10,rax
+ mov rax,QWORD PTR[rcx]
+
+ movq xmm3,QWORD PTR[96+r12]
+ pand xmm2,xmm6
+ por xmm0,xmm1
+ pand xmm3,xmm7
+
+ imul rbp,r10
+ mov r11,rdx
+
+ por xmm0,xmm2
+ lea r12,QWORD PTR[256+r12]
+ por xmm0,xmm3
+
+ 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
+ jne $L$1st
+
+DB 102,72,15,126,195
+
+ 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::
+ xor r15,r15
+ mov rbp,r8
+ mov r10,QWORD PTR[rsp]
+
+ movq xmm0,QWORD PTR[(((-96)))+r12]
+ movq xmm1,QWORD PTR[((-32))+r12]
+ pand xmm0,xmm4
+ movq xmm2,QWORD PTR[32+r12]
+ pand xmm1,xmm5
+
+ mul rbx
+ add r10,rax
+ mov rax,QWORD PTR[rcx]
+ adc rdx,0
+
+ movq xmm3,QWORD PTR[96+r12]
+ pand xmm2,xmm6
+ por xmm0,xmm1
+ pand xmm3,xmm7
+
+ imul rbp,r10
+ mov r11,rdx
+
+ por xmm0,xmm2
+ lea r12,QWORD PTR[256+r12]
+ por xmm0,xmm3
+
+ 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
+ jne $L$inner
+
+DB 102,72,15,126,195
+
+ 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
+ jb $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
+ mov r15,r9
+ALIGN 16
+$L$copy::
+ mov rsi,QWORD PTR[r14*8+rsp]
+ mov rcx,QWORD PTR[r14*8+rdi]
+ xor rsi,rcx
+ and rsi,rax
+ xor rsi,rcx
+ mov QWORD PTR[r14*8+rsp],r14
+ mov QWORD PTR[r14*8+rdi],rsi
+ lea r14,QWORD PTR[1+r14]
+ sub r15,1
+ jnz $L$copy
+
+ mov rsi,QWORD PTR[8+r9*8+rsp]
+ mov rax,1
+ movaps xmm6,XMMWORD PTR[((-88))+rsi]
+ movaps xmm7,XMMWORD PTR[((-72))+rsi]
+ mov r15,QWORD PTR[((-48))+rsi]
+ mov r14,QWORD PTR[((-40))+rsi]
+ mov r13,QWORD PTR[((-32))+rsi]
+ mov r12,QWORD PTR[((-24))+rsi]
+ mov rbp,QWORD PTR[((-16))+rsi]
+ mov rbx,QWORD PTR[((-8))+rsi]
+ lea rsp,QWORD PTR[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 32
+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::
+DB 067h
+ mov rax,rsp
+ push rbx
+ push rbp
+ push r12
+ push r13
+ push r14
+ push r15
+ lea rsp,QWORD PTR[((-40))+rsp]
+ movaps XMMWORD PTR[rsp],xmm6
+ movaps XMMWORD PTR[16+rsp],xmm7
+DB 067h
+ mov r10d,r9d
+ shl r9d,3
+ shl r10d,3+2
+ neg r9
+
+
+
+
+
+
+
+
+ lea r11,QWORD PTR[((-64))+r9*2+rsp]
+ sub r11,rsi
+ and r11,4095
+ cmp r10,r11
+ jb $L$mul4xsp_alt
+ sub rsp,r11
+ lea rsp,QWORD PTR[((-64))+r9*2+rsp]
+ jmp $L$mul4xsp_done
+
+ALIGN 32
+$L$mul4xsp_alt::
+ lea r10,QWORD PTR[((4096-64))+r9*2]
+ lea rsp,QWORD PTR[((-64))+r9*2+rsp]
+ sub r11,r10
+ mov r10,0
+ cmovc r11,r10
+ sub rsp,r11
+$L$mul4xsp_done::
+ and rsp,-64
+ neg r9
+
+ mov QWORD PTR[40+rsp],rax
+$L$mul4x_body::
+
+ call mul4x_internal
+
+ mov rsi,QWORD PTR[40+rsp]
+ mov rax,1
+ movaps xmm6,XMMWORD PTR[((-88))+rsi]
+ movaps xmm7,XMMWORD PTR[((-72))+rsi]
+ mov r15,QWORD PTR[((-48))+rsi]
+ mov r14,QWORD PTR[((-40))+rsi]
+ mov r13,QWORD PTR[((-32))+rsi]
+ mov r12,QWORD PTR[((-24))+rsi]
+ mov rbp,QWORD PTR[((-16))+rsi]
+ mov rbx,QWORD PTR[((-8))+rsi]
+ lea rsp,QWORD PTR[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
+
+
+ALIGN 32
+mul4x_internal PROC PRIVATE
+ shl r9,5
+ mov r10d,DWORD PTR[56+rax]
+ lea r13,QWORD PTR[256+r9*1+rdx]
+ shr r9,5
+ mov r11,r10
+ shr r10,3
+ and r11,7
+ not r10
+ lea rax,QWORD PTR[$L$magic_masks]
+ and r10,3
+ lea r12,QWORD PTR[96+r11*8+rdx]
+ movq xmm4,QWORD PTR[r10*8+rax]
+ movq xmm5,QWORD PTR[8+r10*8+rax]
+ add r11,7
+ movq xmm6,QWORD PTR[16+r10*8+rax]
+ movq xmm7,QWORD PTR[24+r10*8+rax]
+ and r11,7
+
+ movq xmm0,QWORD PTR[(((-96)))+r12]
+ lea r14,QWORD PTR[256+r12]
+ movq xmm1,QWORD PTR[((-32))+r12]
+ pand xmm0,xmm4
+ movq xmm2,QWORD PTR[32+r12]
+ pand xmm1,xmm5
+ movq xmm3,QWORD PTR[96+r12]
+ pand xmm2,xmm6
+DB 067h
+ por xmm0,xmm1
+ movq xmm1,QWORD PTR[((-96))+r14]
+DB 067h
+ pand xmm3,xmm7
+DB 067h
+ por xmm0,xmm2
+ movq xmm2,QWORD PTR[((-32))+r14]
+DB 067h
+ pand xmm1,xmm4
+DB 067h
+ por xmm0,xmm3
+ movq xmm3,QWORD PTR[32+r14]
+
+DB 102,72,15,126,195
+ movq xmm0,QWORD PTR[96+r14]
+ mov QWORD PTR[((16+8))+rsp],r13
+ mov QWORD PTR[((56+8))+rsp],rdi
+
+ mov r8,QWORD PTR[r8]
+ mov rax,QWORD PTR[rsi]
+ lea rsi,QWORD PTR[r9*1+rsi]
+ neg r9
+
+ mov rbp,r8
+ mul rbx
+ mov r10,rax
+ mov rax,QWORD PTR[rcx]
+
+ pand xmm2,xmm5
+ pand xmm3,xmm6
+ por xmm1,xmm2
+
+ imul rbp,r10
+
+
+
+
+
+
+
+ lea r14,QWORD PTR[((64+8))+r11*8+rsp]
+ mov r11,rdx
+
+ pand xmm0,xmm7
+ por xmm1,xmm3
+ lea r12,QWORD PTR[512+r12]
+ por xmm0,xmm1
+
+ mul rbp
+ add r10,rax
+ mov rax,QWORD PTR[8+r9*1+rsi]
+ adc rdx,0
+ mov rdi,rdx
+
+ mul rbx
+ add r11,rax
+ mov rax,QWORD PTR[16+rcx]
+ adc rdx,0
+ mov r10,rdx
+
+ mul rbp
+ add rdi,rax
+ mov rax,QWORD PTR[16+r9*1+rsi]
+ adc rdx,0
+ add rdi,r11
+ lea r15,QWORD PTR[32+r9]
+ lea rcx,QWORD PTR[64+rcx]
+ adc rdx,0
+ mov QWORD PTR[r14],rdi
+ mov r13,rdx
+ jmp $L$1st4x
+
+ALIGN 32
+$L$1st4x::
+ mul rbx
+ add r10,rax
+ mov rax,QWORD PTR[((-32))+rcx]
+ lea r14,QWORD PTR[32+r14]
+ adc rdx,0
+ mov r11,rdx
+
+ mul rbp
+ add r13,rax
+ mov rax,QWORD PTR[((-8))+r15*1+rsi]
+ adc rdx,0
+ add r13,r10
+ adc rdx,0
+ mov QWORD PTR[((-24))+r14],r13
+ mov rdi,rdx
+
+ mul rbx
+ add r11,rax
+ mov rax,QWORD PTR[((-16))+rcx]
+ adc rdx,0
+ mov r10,rdx
+
+ mul rbp
+ add rdi,rax
+ mov rax,QWORD PTR[r15*1+rsi]
+ adc rdx,0
+ add rdi,r11
+ adc rdx,0
+ mov QWORD PTR[((-16))+r14],rdi
+ mov r13,rdx
+
+ mul rbx
+ add r10,rax
+ mov rax,QWORD PTR[rcx]
+ adc rdx,0
+ mov r11,rdx
+
+ mul rbp
+ add r13,rax
+ mov rax,QWORD PTR[8+r15*1+rsi]
+ adc rdx,0
+ add r13,r10
+ adc rdx,0
+ mov QWORD PTR[((-8))+r14],r13
+ mov rdi,rdx
+
+ mul rbx
+ add r11,rax
+ mov rax,QWORD PTR[16+rcx]
+ adc rdx,0
+ mov r10,rdx
+
+ mul rbp
+ add rdi,rax
+ mov rax,QWORD PTR[16+r15*1+rsi]
+ adc rdx,0
+ add rdi,r11
+ lea rcx,QWORD PTR[64+rcx]
+ adc rdx,0
+ mov QWORD PTR[r14],rdi
+ mov r13,rdx
+
+ add r15,32
+ jnz $L$1st4x
+
+ mul rbx
+ add r10,rax
+ mov rax,QWORD PTR[((-32))+rcx]
+ lea r14,QWORD PTR[32+r14]
+ adc rdx,0
+ mov r11,rdx
+
+ mul rbp
+ add r13,rax
+ mov rax,QWORD PTR[((-8))+rsi]
+ adc rdx,0
+ add r13,r10
+ adc rdx,0
+ mov QWORD PTR[((-24))+r14],r13
+ mov rdi,rdx
+
+ mul rbx
+ add r11,rax
+ mov rax,QWORD PTR[((-16))+rcx]
+ adc rdx,0
+ mov r10,rdx
+
+ mul rbp
+ add rdi,rax
+ mov rax,QWORD PTR[r9*1+rsi]
+ adc rdx,0
+ add rdi,r11
+ adc rdx,0
+ mov QWORD PTR[((-16))+r14],rdi
+ mov r13,rdx
+
+DB 102,72,15,126,195
+ lea rcx,QWORD PTR[r9*2+rcx]
+
+ xor rdi,rdi
+ add r13,r10
+ adc rdi,0
+ mov QWORD PTR[((-8))+r14],r13
+
+ jmp $L$outer4x
+
+ALIGN 32
+$L$outer4x::
+ mov r10,QWORD PTR[r9*1+r14]
+ mov rbp,r8
+ mul rbx
+ add r10,rax
+ mov rax,QWORD PTR[rcx]
+ adc rdx,0
+
+ movq xmm0,QWORD PTR[(((-96)))+r12]
+ movq xmm1,QWORD PTR[((-32))+r12]
+ pand xmm0,xmm4
+ movq xmm2,QWORD PTR[32+r12]
+ pand xmm1,xmm5
+ movq xmm3,QWORD PTR[96+r12]
+
+ imul rbp,r10
+DB 067h
+ mov r11,rdx
+ mov QWORD PTR[r14],rdi
+
+ pand xmm2,xmm6
+ por xmm0,xmm1
+ pand xmm3,xmm7
+ por xmm0,xmm2
+ lea r14,QWORD PTR[r9*1+r14]
+ lea r12,QWORD PTR[256+r12]
+ por xmm0,xmm3
+
+ mul rbp
+ add r10,rax
+ mov rax,QWORD PTR[8+r9*1+rsi]
+ adc rdx,0
+ mov rdi,rdx
+
+ mul rbx
+ add r11,rax
+ mov rax,QWORD PTR[16+rcx]
+ adc rdx,0
+ add r11,QWORD PTR[8+r14]
+ adc rdx,0
+ mov r10,rdx
+
+ mul rbp
+ add rdi,rax
+ mov rax,QWORD PTR[16+r9*1+rsi]
+ adc rdx,0
+ add rdi,r11
+ lea r15,QWORD PTR[32+r9]
+ lea rcx,QWORD PTR[64+rcx]
+ adc rdx,0
+ mov r13,rdx
+ jmp $L$inner4x
+
+ALIGN 32
+$L$inner4x::
+ mul rbx
+ add r10,rax
+ mov rax,QWORD PTR[((-32))+rcx]
+ adc rdx,0
+ add r10,QWORD PTR[16+r14]
+ lea r14,QWORD PTR[32+r14]
+ adc rdx,0
+ mov r11,rdx
+
+ mul rbp
+ add r13,rax
+ mov rax,QWORD PTR[((-8))+r15*1+rsi]
+ adc rdx,0
+ add r13,r10
+ adc rdx,0
+ mov QWORD PTR[((-32))+r14],rdi
+ mov rdi,rdx
+
+ mul rbx
+ add r11,rax
+ mov rax,QWORD PTR[((-16))+rcx]
+ adc rdx,0
+ add r11,QWORD PTR[((-8))+r14]
+ adc rdx,0
+ mov r10,rdx
+
+ mul rbp
+ add rdi,rax
+ mov rax,QWORD PTR[r15*1+rsi]
+ adc rdx,0
+ add rdi,r11
+ adc rdx,0
+ mov QWORD PTR[((-24))+r14],r13
+ mov r13,rdx
+
+ mul rbx
+ add r10,rax
+ mov rax,QWORD PTR[rcx]
+ adc rdx,0
+ add r10,QWORD PTR[r14]
+ adc rdx,0
+ mov r11,rdx
+
+ mul rbp
+ add r13,rax
+ mov rax,QWORD PTR[8+r15*1+rsi]
+ adc rdx,0
+ add r13,r10
+ adc rdx,0
+ mov QWORD PTR[((-16))+r14],rdi
+ mov rdi,rdx
+
+ mul rbx
+ add r11,rax
+ mov rax,QWORD PTR[16+rcx]
+ adc rdx,0
+ add r11,QWORD PTR[8+r14]
+ adc rdx,0
+ mov r10,rdx
+
+ mul rbp
+ add rdi,rax
+ mov rax,QWORD PTR[16+r15*1+rsi]
+ adc rdx,0
+ add rdi,r11
+ lea rcx,QWORD PTR[64+rcx]
+ adc rdx,0
+ mov QWORD PTR[((-8))+r14],r13
+ mov r13,rdx
+
+ add r15,32
+ jnz $L$inner4x
+
+ mul rbx
+ add r10,rax
+ mov rax,QWORD PTR[((-32))+rcx]
+ adc rdx,0
+ add r10,QWORD PTR[16+r14]
+ lea r14,QWORD PTR[32+r14]
+ adc rdx,0
+ mov r11,rdx
+
+ mul rbp
+ add r13,rax
+ mov rax,QWORD PTR[((-8))+rsi]
+ adc rdx,0
+ add r13,r10
+ adc rdx,0
+ mov QWORD PTR[((-32))+r14],rdi
+ mov rdi,rdx
+
+ mul rbx
+ add r11,rax
+ mov rax,rbp
+ mov rbp,QWORD PTR[((-16))+rcx]
+ adc rdx,0
+ add r11,QWORD PTR[((-8))+r14]
+ adc rdx,0
+ mov r10,rdx
+
+ mul rbp
+ add rdi,rax
+ mov rax,QWORD PTR[r9*1+rsi]
+ adc rdx,0
+ add rdi,r11
+ adc rdx,0
+ mov QWORD PTR[((-24))+r14],r13
+ mov r13,rdx
+
+DB 102,72,15,126,195
+ mov QWORD PTR[((-16))+r14],rdi
+ lea rcx,QWORD PTR[r9*2+rcx]
+
+ xor rdi,rdi
+ add r13,r10
+ adc rdi,0
+ add r13,QWORD PTR[r14]
+ adc rdi,0
+ mov QWORD PTR[((-8))+r14],r13
+
+ cmp r12,QWORD PTR[((16+8))+rsp]
+ jb $L$outer4x
+ sub rbp,r13
+ adc r15,r15
+ or rdi,r15
+ xor rdi,1
+ lea rbx,QWORD PTR[r9*1+r14]
+ lea rbp,QWORD PTR[rdi*8+rcx]
+ mov rcx,r9
+ sar rcx,3+2
+ mov rdi,QWORD PTR[((56+8))+rsp]
+ jmp $L$sqr4x_sub
+mul4x_internal ENDP
+PUBLIC bn_power5
+
+ALIGN 32
+bn_power5 PROC PUBLIC
+ mov QWORD PTR[8+rsp],rdi ;WIN64 prologue
+ mov QWORD PTR[16+rsp],rsi
+ mov rax,rsp
+$L$SEH_begin_bn_power5::
+ 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 rax,rsp
+ push rbx
+ push rbp
+ push r12
+ push r13
+ push r14
+ push r15
+ lea rsp,QWORD PTR[((-40))+rsp]
+ movaps XMMWORD PTR[rsp],xmm6
+ movaps XMMWORD PTR[16+rsp],xmm7
+ mov r10d,r9d
+ shl r9d,3
+ shl r10d,3+2
+ neg r9
+ mov r8,QWORD PTR[r8]
+
+
+
+
+
+
+
+ lea r11,QWORD PTR[((-64))+r9*2+rsp]
+ sub r11,rsi
+ and r11,4095
+ cmp r10,r11
+ jb $L$pwr_sp_alt
+ sub rsp,r11
+ lea rsp,QWORD PTR[((-64))+r9*2+rsp]
+ jmp $L$pwr_sp_done
+
+ALIGN 32
+$L$pwr_sp_alt::
+ lea r10,QWORD PTR[((4096-64))+r9*2]
+ lea rsp,QWORD PTR[((-64))+r9*2+rsp]
+ sub r11,r10
+ mov r10,0
+ cmovc r11,r10
+ sub rsp,r11
+$L$pwr_sp_done::
+ and rsp,-64
+ mov r10,r9
+ neg r9
+
+
+
+
+
+
+
+
+
+
+ mov QWORD PTR[32+rsp],r8
+ mov QWORD PTR[40+rsp],rax
+$L$power5_body::
+DB 102,72,15,110,207
+DB 102,72,15,110,209
+DB 102,73,15,110,218
+DB 102,72,15,110,226
+
+ call __bn_sqr8x_internal
+ call __bn_sqr8x_internal
+ call __bn_sqr8x_internal
+ call __bn_sqr8x_internal
+ call __bn_sqr8x_internal
+
+DB 102,72,15,126,209
+DB 102,72,15,126,226
+ mov rdi,rsi
+ mov rax,QWORD PTR[40+rsp]
+ lea r8,QWORD PTR[32+rsp]
+
+ call mul4x_internal
+
+ mov rsi,QWORD PTR[40+rsp]
+ mov rax,1
+ mov r15,QWORD PTR[((-48))+rsi]
+ mov r14,QWORD PTR[((-40))+rsi]
+ mov r13,QWORD PTR[((-32))+rsi]
+ mov r12,QWORD PTR[((-24))+rsi]
+ mov rbp,QWORD PTR[((-16))+rsi]
+ mov rbx,QWORD PTR[((-8))+rsi]
+ lea rsp,QWORD PTR[rsi]
+$L$power5_epilogue::
+ mov rdi,QWORD PTR[8+rsp] ;WIN64 epilogue
+ mov rsi,QWORD PTR[16+rsp]
+ DB 0F3h,0C3h ;repret
+$L$SEH_end_bn_power5::
+bn_power5 ENDP
+
+PUBLIC bn_sqr8x_internal
+
+
+ALIGN 32
+bn_sqr8x_internal PROC PUBLIC
+__bn_sqr8x_internal::
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 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[((48+8))+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
+
+ mul r14
+ add r11,rax
+ mov rax,rbx
+ adc rdx,0
+ mov QWORD PTR[((-16))+rbp*1+rdi],r11
+ mov r10,rdx
+
+
+ mov rbx,QWORD PTR[((-8))+rbp*1+rsi]
+ mul r15
+ mov r12,rax
+ mov rax,rbx
+ mov r13,rdx
+
+ lea rcx,QWORD PTR[rbp]
+ mul r14
+ add r10,rax
+ mov rax,rbx
+ mov r11,rdx
+ adc r11,0
+ add r10,r12
+ adc r11,0
+ mov QWORD PTR[((-8))+rcx*1+rdi],r10
+ jmp $L$sqr4x_1st
+
+ALIGN 32
+$L$sqr4x_1st::
+ mov rbx,QWORD PTR[rcx*1+rsi]
+ mul r15
+ add r13,rax
+ mov rax,rbx
+ mov r12,rdx
+ adc r12,0
+
+ mul r14
+ add r11,rax
+ mov rax,rbx
+ mov rbx,QWORD PTR[8+rcx*1+rsi]
+ mov r10,rdx
+ adc r10,0
+ add r11,r13
+ adc r10,0
+
+
+ mul r15
+ add r12,rax
+ mov rax,rbx
+ mov QWORD PTR[rcx*1+rdi],r11
+ mov r13,rdx
+ adc r13,0
+
+ mul r14
+ add r10,rax
+ mov rax,rbx
+ mov rbx,QWORD PTR[16+rcx*1+rsi]
+ mov r11,rdx
+ adc r11,0
+ add r10,r12
+ adc r11,0
+
+ mul r15
+ add r13,rax
+ mov rax,rbx
+ mov QWORD PTR[8+rcx*1+rdi],r10
+ mov r12,rdx
+ adc r12,0
+
+ mul r14
+ add r11,rax
+ mov rax,rbx
+ mov rbx,QWORD PTR[24+rcx*1+rsi]
+ mov r10,rdx
+ adc r10,0
+ add r11,r13
+ adc r10,0
+
+
+ mul r15
+ add r12,rax
+ mov rax,rbx
+ mov QWORD PTR[16+rcx*1+rdi],r11
+ mov r13,rdx
+ adc r13,0
+ lea rcx,QWORD PTR[32+rcx]
+
+ mul r14
+ add r10,rax
+ mov rax,rbx
+ mov r11,rdx
+ adc r11,0
+ add r10,r12
+ adc r11,0
+ mov QWORD PTR[((-8))+rcx*1+rdi],r10
+
+ cmp rcx,0
+ jne $L$sqr4x_1st
+
+ mul r15
+ add r13,rax
+ lea rbp,QWORD PTR[16+rbp]
+ adc rdx,0
+ add r13,r11
+ adc rdx,0
+
+ mov QWORD PTR[rdi],r13
+ mov r12,rdx
+ mov QWORD PTR[8+rdi],rdx
+ jmp $L$sqr4x_outer
+
+ALIGN 32
+$L$sqr4x_outer::
+ mov r14,QWORD PTR[((-32))+rbp*1+rsi]
+ lea rdi,QWORD PTR[((48+8))+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,QWORD PTR[((-24))+rbp*1+rdi]
+ add r10,rax
+ mov rax,rbx
+ adc rdx,0
+ mov QWORD PTR[((-24))+rbp*1+rdi],r10
+ mov r11,rdx
+
+ mul r14
+ add r11,rax
+ mov rax,rbx
+ adc rdx,0
+ add r11,QWORD PTR[((-16))+rbp*1+rdi]
+ mov r10,rdx
+ adc r10,0
+ mov QWORD PTR[((-16))+rbp*1+rdi],r11
+
+ xor r12,r12
+
+ mov rbx,QWORD PTR[((-8))+rbp*1+rsi]
+ mul r15
+ add r12,rax
+ mov rax,rbx
+ adc rdx,0
+ add r12,QWORD PTR[((-8))+rbp*1+rdi]
+ mov r13,rdx
+ adc r13,0
+
+ mul r14
+ add r10,rax
+ mov rax,rbx
+ adc rdx,0
+ add r10,r12
+ mov r11,rdx
+ adc r11,0
+ mov QWORD PTR[((-8))+rbp*1+rdi],r10
+
+ lea rcx,QWORD PTR[rbp]
+ jmp $L$sqr4x_inner
+
+ALIGN 32
+$L$sqr4x_inner::
+ mov rbx,QWORD PTR[rcx*1+rsi]
+ mul r15
+ add r13,rax
+ mov rax,rbx
+ mov r12,rdx
+ adc r12,0
+ add r13,QWORD PTR[rcx*1+rdi]
+ adc r12,0
+
+DB 067h
+ mul r14
+ add r11,rax
+ mov rax,rbx
+ mov rbx,QWORD PTR[8+rcx*1+rsi]
+ mov r10,rdx
+ adc r10,0
+ add r11,r13
+ adc r10,0
+
+ mul r15
+ add r12,rax
+ mov QWORD PTR[rcx*1+rdi],r11
+ mov rax,rbx
+ mov r13,rdx
+ adc r13,0
+ add r12,QWORD PTR[8+rcx*1+rdi]
+ lea rcx,QWORD PTR[16+rcx]
+ adc r13,0
+
+ mul r14
+ add r10,rax
+ mov rax,rbx
+ adc rdx,0
+ add r10,r12
+ mov r11,rdx
+ adc r11,0
+ mov QWORD PTR[((-8))+rcx*1+rdi],r10
+
+ cmp rcx,0
+ jne $L$sqr4x_inner
+
+DB 067h
+ mul r15
+ add r13,rax
+ adc rdx,0
+ add r13,r11
+ adc rdx,0
+
+ mov QWORD PTR[rdi],r13
+ mov r12,rdx
+ mov QWORD PTR[8+rdi],rdx
+
+ add rbp,16
+ jnz $L$sqr4x_outer
+
+
+ mov r14,QWORD PTR[((-32))+rsi]
+ lea rdi,QWORD PTR[((48+8))+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
+
+ mul r14
+ add r10,rax
+ mov rax,rbx
+ mov r11,rdx
+ adc r11,0
+
+ mul r14
+ add r11,rax
+ mov rax,rbx
+ mov QWORD PTR[((-24))+rdi],r10
+ mov r10,rdx
+ adc r10,0
+ add r11,r13
+ mov rbx,QWORD PTR[((-8))+rsi]
+ adc r10,0
+
+ mul r15
+ add r12,rax
+ mov rax,rbx
+ mov QWORD PTR[((-16))+rdi],r11
+ mov r13,rdx
+ adc r13,0
+
+ mul r14
+ add r10,rax
+ mov rax,rbx
+ mov r11,rdx
+ adc r11,0
+ add r10,r12
+ adc r11,0
+ mov QWORD PTR[((-8))+rdi],r10
+
+ mul r15
+ add r13,rax
+ mov rax,QWORD PTR[((-16))+rsi]
+ adc rdx,0
+ add r13,r11
+ adc rdx,0
+
+ mov QWORD PTR[rdi],r13
+ mov r12,rdx
+ mov QWORD PTR[8+rdi],rdx
+
+ 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[((48+8))+rsp]
+ xor r10,r10
+ mov r11,QWORD PTR[8+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+rdi]
+ mov r14,r11
+ mul rax
+ neg r15
+ mov r11,QWORD PTR[24+rdi]
+ adc r12,rax
+ mov rax,QWORD PTR[((-8))+rbp*1+rsi]
+ mov QWORD PTR[rdi],r12
+ adc r13,rdx
+
+ lea rbx,QWORD PTR[r10*2+r14]
+ mov QWORD PTR[8+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+rdi]
+ mov r14,r11
+ mul rax
+ neg r15
+ mov r11,QWORD PTR[40+rdi]
+ adc rbx,rax
+ mov rax,QWORD PTR[rbp*1+rsi]
+ mov QWORD PTR[16+rdi],rbx
+ adc r8,rdx
+ lea rbp,QWORD PTR[16+rbp]
+ mov QWORD PTR[24+rdi],r8
+ sbb r15,r15
+ lea rdi,QWORD PTR[64+rdi]
+ jmp $L$sqr4x_shift_n_add
+
+ALIGN 32
+$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))+rbp*1+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
+ mov r10,QWORD PTR[rdi]
+ mov r14,r11
+ mul rax
+ neg r15
+ mov r11,QWORD PTR[8+rdi]
+ adc rbx,rax
+ mov rax,QWORD PTR[rbp*1+rsi]
+ mov QWORD PTR[((-16))+rdi],rbx
+ adc r8,rdx
+
+ lea r12,QWORD PTR[r10*2+r14]
+ mov QWORD PTR[((-8))+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+rdi]
+ mov r14,r11
+ mul rax
+ neg r15
+ mov r11,QWORD PTR[24+rdi]
+ adc r12,rax
+ mov rax,QWORD PTR[8+rbp*1+rsi]
+ mov QWORD PTR[rdi],r12
+ adc r13,rdx
+
+ lea rbx,QWORD PTR[r10*2+r14]
+ mov QWORD PTR[8+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+rdi]
+ mov r14,r11
+ mul rax
+ neg r15
+ mov r11,QWORD PTR[40+rdi]
+ adc rbx,rax
+ mov rax,QWORD PTR[16+rbp*1+rsi]
+ mov QWORD PTR[16+rdi],rbx
+ adc r8,rdx
+ mov QWORD PTR[24+rdi],r8
+ sbb r15,r15
+ lea rdi,QWORD PTR[64+rdi]
+ add rbp,32
+ jnz $L$sqr4x_shift_n_add
+
+ lea r12,QWORD PTR[r10*2+r14]
+DB 067h
+ 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
+DB 102,72,15,126,213
+sqr8x_reduction::
+ xor rax,rax
+ lea rcx,QWORD PTR[r9*2+rbp]
+ lea rdx,QWORD PTR[((48+8))+r9*2+rsp]
+ mov QWORD PTR[((0+8))+rsp],rcx
+ lea rdi,QWORD PTR[((48+8))+r9*1+rsp]
+ mov QWORD PTR[((8+8))+rsp],rdx
+ neg r9
+ jmp $L$8x_reduction_loop
+
+ALIGN 32
+$L$8x_reduction_loop::
+ lea rdi,QWORD PTR[r9*1+rdi]
+DB 066h
+ mov rbx,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]
+ mov QWORD PTR[rdx],rax
+ lea rdi,QWORD PTR[64+rdi]
+
+DB 067h
+ mov r8,rbx
+ imul rbx,QWORD PTR[((32+8))+rsp]
+ mov rax,QWORD PTR[rbp]
+ mov ecx,8
+ jmp $L$8x_reduce
+
+ALIGN 32
+$L$8x_reduce::
+ mul rbx
+ mov rax,QWORD PTR[16+rbp]
+ neg r8
+ mov r8,rdx
+ adc r8,0
+
+ mul rbx
+ add r9,rax
+ mov rax,QWORD PTR[32+rbp]
+ adc rdx,0
+ add r8,r9
+ mov QWORD PTR[((48-8+8))+rcx*8+rsp],rbx
+ mov r9,rdx
+ adc r9,0
+
+ mul rbx
+ add r10,rax
+ mov rax,QWORD PTR[48+rbp]
+ adc rdx,0
+ add r9,r10
+ mov rsi,QWORD PTR[((32+8))+rsp]
+ mov r10,rdx
+ adc r10,0
+
+ mul rbx
+ add r11,rax
+ mov rax,QWORD PTR[64+rbp]
+ adc rdx,0
+ imul rsi,r8
+ add r10,r11
+ mov r11,rdx
+ adc r11,0
+
+ mul rbx
+ add r12,rax
+ mov rax,QWORD PTR[80+rbp]
+ adc rdx,0
+ add r11,r12
+ mov r12,rdx
+ adc r12,0
+
+ mul rbx
+ add r13,rax
+ mov rax,QWORD PTR[96+rbp]
+ adc rdx,0
+ add r12,r13
+ mov r13,rdx
+ adc r13,0
+
+ mul rbx
+ add r14,rax
+ mov rax,QWORD PTR[112+rbp]
+ adc rdx,0
+ add r13,r14
+ mov r14,rdx
+ adc r14,0
+
+ mul rbx
+ mov rbx,rsi
+ add r15,rax
+ mov rax,QWORD PTR[rbp]
+ adc rdx,0
+ add r14,r15
+ mov r15,rdx
+ adc r15,0
+
+ dec ecx
+ jnz $L$8x_reduce
+
+ lea rbp,QWORD PTR[128+rbp]
+ xor rax,rax
+ mov rdx,QWORD PTR[((8+8))+rsp]
+ cmp rbp,QWORD PTR[((0+8))+rsp]
+ jae $L$8x_no_tail
+
+DB 066h
+ add r8,QWORD PTR[rdi]
+ adc r9,QWORD PTR[8+rdi]
+ adc r10,QWORD PTR[16+rdi]
+ adc r11,QWORD PTR[24+rdi]
+ adc r12,QWORD PTR[32+rdi]
+ adc r13,QWORD PTR[40+rdi]
+ adc r14,QWORD PTR[48+rdi]
+ adc r15,QWORD PTR[56+rdi]
+ sbb rsi,rsi
+
+ mov rbx,QWORD PTR[((48+56+8))+rsp]
+ mov ecx,8
+ mov rax,QWORD PTR[rbp]
+ jmp $L$8x_tail
+
+ALIGN 32
+$L$8x_tail::
+ mul rbx
+ add r8,rax
+ mov rax,QWORD PTR[16+rbp]
+ mov QWORD PTR[rdi],r8
+ mov r8,rdx
+ adc r8,0
+
+ mul rbx
+ add r9,rax
+ mov rax,QWORD PTR[32+rbp]
+ adc rdx,0
+ add r8,r9
+ lea rdi,QWORD PTR[8+rdi]
+ mov r9,rdx
+ adc r9,0
+
+ mul rbx
+ add r10,rax
+ mov rax,QWORD PTR[48+rbp]
+ adc rdx,0
+ add r9,r10
+ mov r10,rdx
+ adc r10,0
+
+ mul rbx
+ add r11,rax
+ mov rax,QWORD PTR[64+rbp]
+ adc rdx,0
+ add r10,r11
+ mov r11,rdx
+ adc r11,0
+
+ mul rbx
+ add r12,rax
+ mov rax,QWORD PTR[80+rbp]
+ adc rdx,0
+ add r11,r12
+ mov r12,rdx
+ adc r12,0
+
+ mul rbx
+ add r13,rax
+ mov rax,QWORD PTR[96+rbp]
+ adc rdx,0
+ add r12,r13
+ mov r13,rdx
+ adc r13,0
+
+ mul rbx
+ add r14,rax
+ mov rax,QWORD PTR[112+rbp]
+ adc rdx,0
+ add r13,r14
+ mov r14,rdx
+ adc r14,0
+
+ mul rbx
+ mov rbx,QWORD PTR[((48-16+8))+rcx*8+rsp]
+ add r15,rax
+ adc rdx,0
+ add r14,r15
+ mov rax,QWORD PTR[rbp]
+ mov r15,rdx
+ adc r15,0
+
+ dec ecx
+ jnz $L$8x_tail
+
+ lea rbp,QWORD PTR[128+rbp]
+ mov rdx,QWORD PTR[((8+8))+rsp]
+ cmp rbp,QWORD PTR[((0+8))+rsp]
+ jae $L$8x_tail_done
+
+ mov rbx,QWORD PTR[((48+56+8))+rsp]
+ neg rsi
+ mov rax,QWORD PTR[rbp]
+ adc r8,QWORD PTR[rdi]
+ adc r9,QWORD PTR[8+rdi]
+ adc r10,QWORD PTR[16+rdi]
+ adc r11,QWORD PTR[24+rdi]
+ adc r12,QWORD PTR[32+rdi]
+ adc r13,QWORD PTR[40+rdi]
+ adc r14,QWORD PTR[48+rdi]
+ adc r15,QWORD PTR[56+rdi]
+ sbb rsi,rsi
+
+ mov ecx,8
+ jmp $L$8x_tail
+
+ALIGN 32
+$L$8x_tail_done::
+ add r8,QWORD PTR[rdx]
+ xor rax,rax
+
+ neg rsi
+$L$8x_no_tail::
+ adc r8,QWORD PTR[rdi]
+ adc r9,QWORD PTR[8+rdi]
+ adc r10,QWORD PTR[16+rdi]
+ adc r11,QWORD PTR[24+rdi]
+ adc r12,QWORD PTR[32+rdi]
+ adc r13,QWORD PTR[40+rdi]
+ adc r14,QWORD PTR[48+rdi]
+ adc r15,QWORD PTR[56+rdi]
+ adc rax,0
+ mov rcx,QWORD PTR[((-16))+rbp]
+ xor rsi,rsi
+
+DB 102,72,15,126,213
+
+ mov QWORD PTR[rdi],r8
+ mov QWORD PTR[8+rdi],r9
+DB 102,73,15,126,217
+ 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 rdi,QWORD PTR[64+rdi]
+
+ cmp rdi,rdx
+ jb $L$8x_reduction_loop
+
+ sub rcx,r15
+ lea rbx,QWORD PTR[r9*1+rdi]
+ adc rsi,rsi
+ mov rcx,r9
+ or rax,rsi
+DB 102,72,15,126,207
+ xor rax,1
+DB 102,72,15,126,206
+ lea rbp,QWORD PTR[rax*8+rbp]
+ sar rcx,3+2
+ jmp $L$sqr4x_sub
+
+ALIGN 32
+$L$sqr4x_sub::
+DB 066h
+ mov r12,QWORD PTR[rbx]
+ mov r13,QWORD PTR[8+rbx]
+ sbb r12,QWORD PTR[rbp]
+ mov r14,QWORD PTR[16+rbx]
+ sbb r13,QWORD PTR[16+rbp]
+ mov r15,QWORD PTR[24+rbx]
+ lea rbx,QWORD PTR[32+rbx]
+ sbb r14,QWORD PTR[32+rbp]
+ mov QWORD PTR[rdi],r12
+ sbb r15,QWORD PTR[48+rbp]
+ lea rbp,QWORD PTR[64+rbp]
+ mov QWORD PTR[8+rdi],r13
+ mov QWORD PTR[16+rdi],r14
+ mov QWORD PTR[24+rdi],r15
+ lea rdi,QWORD PTR[32+rdi]
+
+ inc rcx
+ jnz $L$sqr4x_sub
+ mov r10,r9
+ neg r9
+ DB 0F3h,0C3h ;repret
+bn_sqr8x_internal ENDP
+PUBLIC bn_from_montgomery
+
+ALIGN 32
+bn_from_montgomery PROC PUBLIC
+ test DWORD PTR[48+rsp],7
+ jz bn_from_mont8x
+ xor eax,eax
+ DB 0F3h,0C3h ;repret
+bn_from_montgomery ENDP
+
+
+ALIGN 32
+bn_from_mont8x PROC PRIVATE
+ mov QWORD PTR[8+rsp],rdi ;WIN64 prologue
+ mov QWORD PTR[16+rsp],rsi
+ mov rax,rsp
+$L$SEH_begin_bn_from_mont8x::
+ mov rdi,rcx
+ mov rsi,rdx
+ mov rdx,r8
+ mov rcx,r9
+ mov r8,QWORD PTR[40+rsp]
+ mov r9,QWORD PTR[48+rsp]
+
+
+DB 067h
+ mov rax,rsp
+ push rbx
+ push rbp
+ push r12
+ push r13
+ push r14
+ push r15
+ lea rsp,QWORD PTR[((-40))+rsp]
+ movaps XMMWORD PTR[rsp],xmm6
+ movaps XMMWORD PTR[16+rsp],xmm7
+DB 067h
+ mov r10d,r9d
+ shl r9d,3
+ shl r10d,3+2
+ neg r9
+ mov r8,QWORD PTR[r8]
+
+
+
+
+
+
+
+ lea r11,QWORD PTR[((-64))+r9*2+rsp]
+ sub r11,rsi
+ and r11,4095
+ cmp r10,r11
+ jb $L$from_sp_alt
+ sub rsp,r11
+ lea rsp,QWORD PTR[((-64))+r9*2+rsp]
+ jmp $L$from_sp_done
+
+ALIGN 32
+$L$from_sp_alt::
+ lea r10,QWORD PTR[((4096-64))+r9*2]
+ lea rsp,QWORD PTR[((-64))+r9*2+rsp]
+ sub r11,r10
+ mov r10,0
+ cmovc r11,r10
+ sub rsp,r11
+$L$from_sp_done::
+ and rsp,-64
+ mov r10,r9
+ neg r9
+
+
+
+
+
+
+
+
+
+
+ mov QWORD PTR[32+rsp],r8
+ mov QWORD PTR[40+rsp],rax
+$L$from_body::
+ mov r11,r9
+ lea rax,QWORD PTR[48+rsp]
+ pxor xmm0,xmm0
+ jmp $L$mul_by_1
+
+ALIGN 32
+$L$mul_by_1::
+ movdqu xmm1,XMMWORD PTR[rsi]
+ movdqu xmm2,XMMWORD PTR[16+rsi]
+ movdqu xmm3,XMMWORD PTR[32+rsi]
+ movdqa XMMWORD PTR[r9*1+rax],xmm0
+ movdqu xmm4,XMMWORD PTR[48+rsi]
+ movdqa XMMWORD PTR[16+r9*1+rax],xmm0
+DB 048h,08dh,0b6h,040h,000h,000h,000h
+ movdqa XMMWORD PTR[rax],xmm1
+ movdqa XMMWORD PTR[32+r9*1+rax],xmm0
+ movdqa XMMWORD PTR[16+rax],xmm2
+ movdqa XMMWORD PTR[48+r9*1+rax],xmm0
+ movdqa XMMWORD PTR[32+rax],xmm3
+ movdqa XMMWORD PTR[48+rax],xmm4
+ lea rax,QWORD PTR[64+rax]
+ sub r11,64
+ jnz $L$mul_by_1
+
+DB 102,72,15,110,207
+DB 102,72,15,110,209
+DB 067h
+ mov rbp,rcx
+DB 102,73,15,110,218
+ call sqr8x_reduction
+
+ pxor xmm0,xmm0
+ lea rax,QWORD PTR[48+rsp]
+ mov rsi,QWORD PTR[40+rsp]
+ jmp $L$from_mont_zero
+
+ALIGN 32
+$L$from_mont_zero::
+ movdqa XMMWORD PTR[rax],xmm0
+ movdqa XMMWORD PTR[16+rax],xmm0
+ movdqa XMMWORD PTR[32+rax],xmm0
+ movdqa XMMWORD PTR[48+rax],xmm0
+ lea rax,QWORD PTR[64+rax]
+ sub r9,32
+ jnz $L$from_mont_zero
+
+ mov rax,1
+ mov r15,QWORD PTR[((-48))+rsi]
+ mov r14,QWORD PTR[((-40))+rsi]
+ mov r13,QWORD PTR[((-32))+rsi]
+ mov r12,QWORD PTR[((-24))+rsi]
+ mov rbp,QWORD PTR[((-16))+rsi]
+ mov rbx,QWORD PTR[((-8))+rsi]
+ lea rsp,QWORD PTR[rsi]
+$L$from_epilogue::
+ mov rdi,QWORD PTR[8+rsp] ;WIN64 epilogue
+ mov rsi,QWORD PTR[16+rsp]
+ DB 0F3h,0C3h ;repret
+$L$SEH_end_bn_from_mont8x::
+bn_from_mont8x ENDP
+PUBLIC bn_scatter5
+
+ALIGN 16
+bn_scatter5 PROC PUBLIC
+ cmp edx,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 edx,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 048h,083h,0ech,028h
+DB 00fh,029h,034h,024h
+DB 00fh,029h,07ch,024h,010h
+ mov r11d,r9d
+ shr r9d,3
+ and r11,7
+ not r9d
+ lea rax,QWORD PTR[$L$magic_masks]
+ and r9d,3
+ lea r8,QWORD PTR[128+r11*8+r8]
+ movq xmm4,QWORD PTR[r9*8+rax]
+ movq xmm5,QWORD PTR[8+r9*8+rax]
+ movq xmm6,QWORD PTR[16+r9*8+rax]
+ movq xmm7,QWORD PTR[24+r9*8+rax]
+ jmp $L$gather
+ALIGN 16
+$L$gather::
+ movq xmm0,QWORD PTR[(((-128)))+r8]
+ movq xmm1,QWORD PTR[((-64))+r8]
+ pand xmm0,xmm4
+ movq xmm2,QWORD PTR[r8]
+ pand xmm1,xmm5
+ movq xmm3,QWORD PTR[64+r8]
+ pand xmm2,xmm6
+ por xmm0,xmm1
+ pand xmm3,xmm7
+DB 067h,067h
+ por xmm0,xmm2
+ lea r8,QWORD PTR[256+r8]
+ por xmm0,xmm3
+
+ movq QWORD PTR[rcx],xmm0
+ lea rcx,QWORD PTR[8+rcx]
+ sub edx,1
+ jnz $L$gather
+ movaps xmm6,XMMWORD PTR[rsp]
+ movaps xmm7,XMMWORD PTR[16+rsp]
+ lea rsp,QWORD PTR[40+rsp]
+ DB 0F3h,0C3h ;repret
+$L$SEH_end_bn_gather5::
+bn_gather5 ENDP
+ALIGN 64
+$L$magic_masks::
+ DD 0,0,0,0,0,0,-1,-1
+ DD 0,0,0,0,0,0,0,0
+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
+
+ 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 r10,QWORD PTR[$L$mul_epilogue]
+ cmp rbx,r10
+ jb $L$body_40
+
+ mov r10,QWORD PTR[192+r8]
+ mov rax,QWORD PTR[8+r10*8+rax]
+ jmp $L$body_proceed
+
+$L$body_40::
+ mov rax,QWORD PTR[40+rax]
+$L$body_proceed::
+
+ movaps xmm0,XMMWORD PTR[((-88))+rax]
+ movaps xmm1,XMMWORD PTR[((-72))+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
+ movups XMMWORD PTR[512+r8],xmm0
+ movups XMMWORD PTR[528+r8],xmm1
+
+$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_power5
+ DD imagerel $L$SEH_end_bn_power5
+ DD imagerel $L$SEH_info_bn_power5
+
+ DD imagerel $L$SEH_begin_bn_from_mont8x
+ DD imagerel $L$SEH_end_bn_from_mont8x
+ DD imagerel $L$SEH_info_bn_from_mont8x
+ 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_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_body,imagerel $L$mul4x_epilogue
+ALIGN 8
+$L$SEH_info_bn_power5::
+DB 9,0,0,0
+ DD imagerel mul_handler
+ DD imagerel $L$power5_body,imagerel $L$power5_epilogue
+ALIGN 8
+$L$SEH_info_bn_from_mont8x::
+DB 9,0,0,0
+ DD imagerel mul_handler
+ DD imagerel $L$from_body,imagerel $L$from_epilogue
+ALIGN 8
+$L$SEH_info_bn_gather5::
+DB 001h,00dh,005h,000h
+DB 00dh,078h,001h,000h
+DB 008h,068h,000h,000h
+DB 004h,042h,000h,000h
+ALIGN 8
+
+.xdata ENDS
+END
diff --git a/win-x86_64/crypto/cpu-x86_64-asm.asm b/win-x86_64/crypto/cpu-x86_64-asm.asm
new file mode 100644
index 0000000..dca66f5
--- /dev/null
+++ b/win-x86_64/crypto/cpu-x86_64-asm.asm
@@ -0,0 +1,158 @@
+OPTION DOTNAME
+.text$ SEGMENT ALIGN(256) 'CODE'
+
+PUBLIC OPENSSL_ia32_cpuid
+
+ALIGN 16
+OPENSSL_ia32_cpuid PROC PUBLIC
+ mov QWORD PTR[8+rsp],rdi ;WIN64 prologue
+ mov QWORD PTR[16+rsp],rsi
+ mov rax,rsp
+$L$SEH_begin_OPENSSL_ia32_cpuid::
+ mov rdi,rcx
+
+
+
+
+ mov rdi,rcx
+ mov r8,rbx
+
+ xor eax,eax
+ mov DWORD PTR[8+rdi],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,000000801h
+
+ 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
+ and edx,0efffffffh
+ 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
+
+ cmp r11d,7
+ jb $L$nocacheinfo
+
+ mov eax,7
+ xor ecx,ecx
+ cpuid
+ mov DWORD PTR[8+rdi],ebx
+
+$L$nocacheinfo::
+ mov eax,1
+ cpuid
+
+ and edx,0bfefffffh
+ cmp r9d,0
+ jne $L$notintel
+ or edx,040000000h
+ and ah,15
+ cmp ah,15
+ jne $L$notintel
+ or edx,000100000h
+$L$notintel::
+ bt edx,28
+ jnc $L$generic
+ and edx,0efffffffh
+ cmp r10d,0
+ je $L$generic
+
+ or edx,010000000h
+ shr ebx,16
+ cmp bl,1
+ ja $L$generic
+ and edx,0efffffffh
+$L$generic::
+ and r9d,000000800h
+ and ecx,0fffff7ffh
+ 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,0efffe7ffh
+ and r9d,eax
+ and DWORD PTR[8+rdi],0ffffffdfh
+$L$done::
+ mov DWORD PTR[4+rdi],r9d
+ mov DWORD PTR[rdi],r10d
+ mov rbx,r8
+ mov rdi,QWORD PTR[8+rsp] ;WIN64 epilogue
+ mov rsi,QWORD PTR[16+rsp]
+ DB 0F3h,0C3h ;repret
+$L$SEH_end_OPENSSL_ia32_cpuid::
+OPENSSL_ia32_cpuid ENDP
+
+
+.text$ ENDS
+END
diff --git a/win-x86_64/crypto/md5/md5-x86_64.asm b/win-x86_64/crypto/md5/md5-x86_64.asm
new file mode 100644
index 0000000..d2faa88
--- /dev/null
+++ b/win-x86_64/crypto/md5/md5-x86_64.asm
@@ -0,0 +1,778 @@
+OPTION DOTNAME
+.text$ SEGMENT ALIGN(256) '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
+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$in_prologue
+
+ mov rax,QWORD PTR[152+r8]
+
+ lea r10,QWORD PTR[$L$epilogue]
+ cmp rbx,r10
+ jae $L$in_prologue
+
+ lea rax,QWORD PTR[40+rax]
+
+ mov rbp,QWORD PTR[((-8))+rax]
+ mov rbx,QWORD PTR[((-16))+rax]
+ mov r12,QWORD PTR[((-24))+rax]
+ mov r14,QWORD PTR[((-32))+rax]
+ mov r15,QWORD PTR[((-40))+rax]
+ mov QWORD PTR[144+r8],rbx
+ mov QWORD PTR[160+r8],rbp
+ mov QWORD PTR[216+r8],r12
+ mov QWORD PTR[232+r8],r14
+ mov QWORD PTR[240+r8],r15
+
+$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_md5_block_asm_data_order
+ DD imagerel $L$SEH_end_md5_block_asm_data_order
+ DD imagerel $L$SEH_info_md5_block_asm_data_order
+
+.pdata ENDS
+.xdata SEGMENT READONLY ALIGN(8)
+ALIGN 8
+$L$SEH_info_md5_block_asm_data_order::
+DB 9,0,0,0
+ DD imagerel se_handler
+
+.xdata ENDS
+END
diff --git a/win-x86_64/crypto/modes/aesni-gcm-x86_64.asm b/win-x86_64/crypto/modes/aesni-gcm-x86_64.asm
new file mode 100644
index 0000000..828be8d
--- /dev/null
+++ b/win-x86_64/crypto/modes/aesni-gcm-x86_64.asm
@@ -0,0 +1,19 @@
+OPTION DOTNAME
+.text$ SEGMENT ALIGN(256) 'CODE'
+
+PUBLIC aesni_gcm_encrypt
+
+aesni_gcm_encrypt PROC PUBLIC
+ xor eax,eax
+ DB 0F3h,0C3h ;repret
+aesni_gcm_encrypt ENDP
+
+PUBLIC aesni_gcm_decrypt
+
+aesni_gcm_decrypt PROC PUBLIC
+ xor eax,eax
+ DB 0F3h,0C3h ;repret
+aesni_gcm_decrypt ENDP
+
+.text$ ENDS
+END
diff --git a/win-x86_64/crypto/modes/ghash-x86_64.asm b/win-x86_64/crypto/modes/ghash-x86_64.asm
new file mode 100644
index 0000000..9993d75
--- /dev/null
+++ b/win-x86_64/crypto/modes/ghash-x86_64.asm
@@ -0,0 +1,1510 @@
+OPTION DOTNAME
+.text$ SEGMENT ALIGN(256) 'CODE'
+EXTERN OPENSSL_ia32cap_P:NEAR
+
+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
+$L$_init_clmul::
+$L$SEH_begin_gcm_init_clmul::
+
+DB 048h,083h,0ech,018h
+DB 00fh,029h,034h,024h
+ 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
+
+
+ pshufd xmm6,xmm2,78
+ movdqa xmm0,xmm2
+ pxor xmm6,xmm2
+ movdqa xmm1,xmm0
+ pshufd xmm3,xmm0,78
+ pxor xmm3,xmm0
+DB 102,15,58,68,194,0
+DB 102,15,58,68,202,17
+DB 102,15,58,68,222,0
+ pxor xmm3,xmm0
+ pxor xmm3,xmm1
+
+ movdqa xmm4,xmm3
+ psrldq xmm3,8
+ pslldq xmm4,8
+ pxor xmm1,xmm3
+ pxor xmm0,xmm4
+
+ movdqa xmm4,xmm0
+ movdqa xmm3,xmm0
+ psllq xmm0,5
+ pxor xmm3,xmm0
+ psllq xmm0,1
+ pxor xmm0,xmm3
+ psllq xmm0,57
+ movdqa xmm3,xmm0
+ pslldq xmm0,8
+ psrldq xmm3,8
+ pxor xmm0,xmm4
+ pxor xmm1,xmm3
+
+
+ movdqa xmm4,xmm0
+ psrlq xmm0,1
+ pxor xmm1,xmm4
+ pxor xmm4,xmm0
+ psrlq xmm0,5
+ pxor xmm0,xmm4
+ psrlq xmm0,1
+ pxor xmm0,xmm1
+ pshufd xmm3,xmm2,78
+ pshufd xmm4,xmm0,78
+ pxor xmm3,xmm2
+ movdqu XMMWORD PTR[rcx],xmm2
+ pxor xmm4,xmm0
+ movdqu XMMWORD PTR[16+rcx],xmm0
+DB 102,15,58,15,227,8
+ movdqu XMMWORD PTR[32+rcx],xmm4
+ movdqa xmm1,xmm0
+ pshufd xmm3,xmm0,78
+ pxor xmm3,xmm0
+DB 102,15,58,68,194,0
+DB 102,15,58,68,202,17
+DB 102,15,58,68,222,0
+ pxor xmm3,xmm0
+ pxor xmm3,xmm1
+
+ movdqa xmm4,xmm3
+ psrldq xmm3,8
+ pslldq xmm4,8
+ pxor xmm1,xmm3
+ pxor xmm0,xmm4
+
+ movdqa xmm4,xmm0
+ movdqa xmm3,xmm0
+ psllq xmm0,5
+ pxor xmm3,xmm0
+ psllq xmm0,1
+ pxor xmm0,xmm3
+ psllq xmm0,57
+ movdqa xmm3,xmm0
+ pslldq xmm0,8
+ psrldq xmm3,8
+ pxor xmm0,xmm4
+ pxor xmm1,xmm3
+
+
+ movdqa xmm4,xmm0
+ psrlq xmm0,1
+ pxor xmm1,xmm4
+ pxor xmm4,xmm0
+ psrlq xmm0,5
+ pxor xmm0,xmm4
+ psrlq xmm0,1
+ pxor xmm0,xmm1
+ movdqa xmm5,xmm0
+ movdqa xmm1,xmm0
+ pshufd xmm3,xmm0,78
+ pxor xmm3,xmm0
+DB 102,15,58,68,194,0
+DB 102,15,58,68,202,17
+DB 102,15,58,68,222,0
+ pxor xmm3,xmm0
+ pxor xmm3,xmm1
+
+ movdqa xmm4,xmm3
+ psrldq xmm3,8
+ pslldq xmm4,8
+ pxor xmm1,xmm3
+ pxor xmm0,xmm4
+
+ movdqa xmm4,xmm0
+ movdqa xmm3,xmm0
+ psllq xmm0,5
+ pxor xmm3,xmm0
+ psllq xmm0,1
+ pxor xmm0,xmm3
+ psllq xmm0,57
+ movdqa xmm3,xmm0
+ pslldq xmm0,8
+ psrldq xmm3,8
+ pxor xmm0,xmm4
+ pxor xmm1,xmm3
+
+
+ movdqa xmm4,xmm0
+ psrlq xmm0,1
+ pxor xmm1,xmm4
+ pxor xmm4,xmm0
+ psrlq xmm0,5
+ pxor xmm0,xmm4
+ psrlq xmm0,1
+ pxor xmm0,xmm1
+ pshufd xmm3,xmm5,78
+ pshufd xmm4,xmm0,78
+ pxor xmm3,xmm5
+ movdqu XMMWORD PTR[48+rcx],xmm5
+ pxor xmm4,xmm0
+ movdqu XMMWORD PTR[64+rcx],xmm0
+DB 102,15,58,15,227,8
+ movdqu XMMWORD PTR[80+rcx],xmm4
+ movaps xmm6,XMMWORD PTR[rsp]
+ lea rsp,QWORD PTR[24+rsp]
+$L$SEH_end_gcm_init_clmul::
+ DB 0F3h,0C3h ;repret
+gcm_init_clmul ENDP
+PUBLIC gcm_gmult_clmul
+
+ALIGN 16
+gcm_gmult_clmul PROC PUBLIC
+$L$_gmult_clmul::
+ movdqu xmm0,XMMWORD PTR[rcx]
+ movdqa xmm5,XMMWORD PTR[$L$bswap_mask]
+ movdqu xmm2,XMMWORD PTR[rdx]
+ movdqu xmm4,XMMWORD PTR[32+rdx]
+DB 102,15,56,0,197
+ movdqa xmm1,xmm0
+ pshufd xmm3,xmm0,78
+ pxor xmm3,xmm0
+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 xmm4,xmm0
+ movdqa xmm3,xmm0
+ psllq xmm0,5
+ pxor xmm3,xmm0
+ psllq xmm0,1
+ pxor xmm0,xmm3
+ psllq xmm0,57
+ movdqa xmm3,xmm0
+ pslldq xmm0,8
+ psrldq xmm3,8
+ pxor xmm0,xmm4
+ pxor xmm1,xmm3
+
+
+ movdqa xmm4,xmm0
+ psrlq xmm0,1
+ pxor xmm1,xmm4
+ pxor xmm4,xmm0
+ psrlq xmm0,5
+ pxor xmm0,xmm4
+ psrlq xmm0,1
+ pxor xmm0,xmm1
+DB 102,15,56,0,197
+ movdqu XMMWORD PTR[rcx],xmm0
+ DB 0F3h,0C3h ;repret
+gcm_gmult_clmul ENDP
+PUBLIC gcm_ghash_clmul
+
+ALIGN 32
+gcm_ghash_clmul PROC PUBLIC
+$L$_ghash_clmul::
+ lea rax,QWORD PTR[((-136))+rsp]
+$L$SEH_begin_gcm_ghash_clmul::
+
+DB 048h,08dh,060h,0e0h
+DB 00fh,029h,070h,0e0h
+DB 00fh,029h,078h,0f0h
+DB 044h,00fh,029h,000h
+DB 044h,00fh,029h,048h,010h
+DB 044h,00fh,029h,050h,020h
+DB 044h,00fh,029h,058h,030h
+DB 044h,00fh,029h,060h,040h
+DB 044h,00fh,029h,068h,050h
+DB 044h,00fh,029h,070h,060h
+DB 044h,00fh,029h,078h,070h
+ movdqa xmm10,XMMWORD PTR[$L$bswap_mask]
+
+ movdqu xmm0,XMMWORD PTR[rcx]
+ movdqu xmm2,XMMWORD PTR[rdx]
+ movdqu xmm7,XMMWORD PTR[32+rdx]
+DB 102,65,15,56,0,194
+
+ sub r9,010h
+ jz $L$odd_tail
+
+ movdqu xmm6,XMMWORD PTR[16+rdx]
+ mov eax,DWORD PTR[((OPENSSL_ia32cap_P+4))]
+ cmp r9,030h
+ jb $L$skip4x
+
+ and eax,71303168
+ cmp eax,4194304
+ je $L$skip4x
+
+ sub r9,030h
+ mov rax,0A040608020C0E000h
+ movdqu xmm14,XMMWORD PTR[48+rdx]
+ movdqu xmm15,XMMWORD PTR[64+rdx]
+
+
+
+
+ movdqu xmm3,XMMWORD PTR[48+r8]
+ movdqu xmm11,XMMWORD PTR[32+r8]
+DB 102,65,15,56,0,218
+DB 102,69,15,56,0,218
+ movdqa xmm5,xmm3
+ pshufd xmm4,xmm3,78
+ pxor xmm4,xmm3
+DB 102,15,58,68,218,0
+DB 102,15,58,68,234,17
+DB 102,15,58,68,231,0
+
+ movdqa xmm13,xmm11
+ pshufd xmm12,xmm11,78
+ pxor xmm12,xmm11
+DB 102,68,15,58,68,222,0
+DB 102,68,15,58,68,238,17
+DB 102,68,15,58,68,231,16
+ xorps xmm3,xmm11
+ xorps xmm5,xmm13
+ movups xmm7,XMMWORD PTR[80+rdx]
+ xorps xmm4,xmm12
+
+ movdqu xmm11,XMMWORD PTR[16+r8]
+ movdqu xmm8,XMMWORD PTR[r8]
+DB 102,69,15,56,0,218
+DB 102,69,15,56,0,194
+ movdqa xmm13,xmm11
+ pshufd xmm12,xmm11,78
+ pxor xmm0,xmm8
+ pxor xmm12,xmm11
+DB 102,69,15,58,68,222,0
+ movdqa xmm1,xmm0
+ pshufd xmm8,xmm0,78
+ pxor xmm8,xmm0
+DB 102,69,15,58,68,238,17
+DB 102,68,15,58,68,231,0
+ xorps xmm3,xmm11
+ xorps xmm5,xmm13
+
+ lea r8,QWORD PTR[64+r8]
+ sub r9,040h
+ jc $L$tail4x
+
+ jmp $L$mod4_loop
+ALIGN 32
+$L$mod4_loop::
+DB 102,65,15,58,68,199,0
+ xorps xmm4,xmm12
+ movdqu xmm11,XMMWORD PTR[48+r8]
+DB 102,69,15,56,0,218
+DB 102,65,15,58,68,207,17
+ xorps xmm0,xmm3
+ movdqu xmm3,XMMWORD PTR[32+r8]
+ movdqa xmm13,xmm11
+DB 102,68,15,58,68,199,16
+ pshufd xmm12,xmm11,78
+ xorps xmm1,xmm5
+ pxor xmm12,xmm11
+DB 102,65,15,56,0,218
+ movups xmm7,XMMWORD PTR[32+rdx]
+ xorps xmm8,xmm4
+DB 102,68,15,58,68,218,0
+ pshufd xmm4,xmm3,78
+
+ pxor xmm8,xmm0
+ movdqa xmm5,xmm3
+ pxor xmm8,xmm1
+ pxor xmm4,xmm3
+ movdqa xmm9,xmm8
+DB 102,68,15,58,68,234,17
+ pslldq xmm8,8
+ psrldq xmm9,8
+ pxor xmm0,xmm8
+ movdqa xmm8,XMMWORD PTR[$L$7_mask]
+ pxor xmm1,xmm9
+DB 102,76,15,110,200
+
+ pand xmm8,xmm0
+DB 102,69,15,56,0,200
+ pxor xmm9,xmm0
+DB 102,68,15,58,68,231,0
+ psllq xmm9,57
+ movdqa xmm8,xmm9
+ pslldq xmm9,8
+DB 102,15,58,68,222,0
+ psrldq xmm8,8
+ pxor xmm0,xmm9
+ pxor xmm1,xmm8
+ movdqu xmm8,XMMWORD PTR[r8]
+
+ movdqa xmm9,xmm0
+ psrlq xmm0,1
+DB 102,15,58,68,238,17
+ xorps xmm3,xmm11
+ movdqu xmm11,XMMWORD PTR[16+r8]
+DB 102,69,15,56,0,218
+DB 102,15,58,68,231,16
+ xorps xmm5,xmm13
+ movups xmm7,XMMWORD PTR[80+rdx]
+DB 102,69,15,56,0,194
+ pxor xmm1,xmm9
+ pxor xmm9,xmm0
+ psrlq xmm0,5
+
+ movdqa xmm13,xmm11
+ pxor xmm4,xmm12
+ pshufd xmm12,xmm11,78
+ pxor xmm0,xmm9
+ pxor xmm1,xmm8
+ pxor xmm12,xmm11
+DB 102,69,15,58,68,222,0
+ psrlq xmm0,1
+ pxor xmm0,xmm1
+ movdqa xmm1,xmm0
+DB 102,69,15,58,68,238,17
+ xorps xmm3,xmm11
+ pshufd xmm8,xmm0,78
+ pxor xmm8,xmm0
+
+DB 102,68,15,58,68,231,0
+ xorps xmm5,xmm13
+
+ lea r8,QWORD PTR[64+r8]
+ sub r9,040h
+ jnc $L$mod4_loop
+
+$L$tail4x::
+DB 102,65,15,58,68,199,0
+DB 102,65,15,58,68,207,17
+DB 102,68,15,58,68,199,16
+ xorps xmm4,xmm12
+ xorps xmm0,xmm3
+ xorps xmm1,xmm5
+ pxor xmm1,xmm0
+ pxor xmm8,xmm4
+
+ pxor xmm8,xmm1
+ pxor xmm1,xmm0
+
+ movdqa xmm9,xmm8
+ psrldq xmm8,8
+ pslldq xmm9,8
+ pxor xmm1,xmm8
+ pxor xmm0,xmm9
+
+ movdqa xmm4,xmm0
+ movdqa xmm3,xmm0
+ psllq xmm0,5
+ pxor xmm3,xmm0
+ psllq xmm0,1
+ pxor xmm0,xmm3
+ psllq xmm0,57
+ movdqa xmm3,xmm0
+ pslldq xmm0,8
+ psrldq xmm3,8
+ pxor xmm0,xmm4
+ pxor xmm1,xmm3
+
+
+ movdqa xmm4,xmm0
+ psrlq xmm0,1
+ pxor xmm1,xmm4
+ pxor xmm4,xmm0
+ psrlq xmm0,5
+ pxor xmm0,xmm4
+ psrlq xmm0,1
+ pxor xmm0,xmm1
+ add r9,040h
+ jz $L$done
+ movdqu xmm7,XMMWORD PTR[32+rdx]
+ sub r9,010h
+ jz $L$odd_tail
+$L$skip4x::
+
+
+
+
+
+ movdqu xmm8,XMMWORD PTR[r8]
+ movdqu xmm3,XMMWORD PTR[16+r8]
+DB 102,69,15,56,0,194
+DB 102,65,15,56,0,218
+ pxor xmm0,xmm8
+
+ movdqa xmm5,xmm3
+ pshufd xmm4,xmm3,78
+ pxor xmm4,xmm3
+DB 102,15,58,68,218,0
+DB 102,15,58,68,234,17
+DB 102,15,58,68,231,0
+
+ lea r8,QWORD PTR[32+r8]
+ nop
+ sub r9,020h
+ jbe $L$even_tail
+ nop
+ jmp $L$mod_loop
+
+ALIGN 32
+$L$mod_loop::
+ movdqa xmm1,xmm0
+ movdqa xmm8,xmm4
+ pshufd xmm4,xmm0,78
+ pxor xmm4,xmm0
+
+DB 102,15,58,68,198,0
+DB 102,15,58,68,206,17
+DB 102,15,58,68,231,16
+
+ pxor xmm0,xmm3
+ pxor xmm1,xmm5
+ movdqu xmm9,XMMWORD PTR[r8]
+ pxor xmm8,xmm0
+DB 102,69,15,56,0,202
+ movdqu xmm3,XMMWORD PTR[16+r8]
+
+ pxor xmm8,xmm1
+ pxor xmm1,xmm9
+ pxor xmm4,xmm8
+DB 102,65,15,56,0,218
+ movdqa xmm8,xmm4
+ psrldq xmm8,8
+ pslldq xmm4,8
+ pxor xmm1,xmm8
+ pxor xmm0,xmm4
+
+ movdqa xmm5,xmm3
+
+ movdqa xmm9,xmm0
+ movdqa xmm8,xmm0
+ psllq xmm0,5
+ pxor xmm8,xmm0
+DB 102,15,58,68,218,0
+ psllq xmm0,1
+ pxor xmm0,xmm8
+ psllq xmm0,57
+ movdqa xmm8,xmm0
+ pslldq xmm0,8
+ psrldq xmm8,8
+ pxor xmm0,xmm9
+ pshufd xmm4,xmm5,78
+ pxor xmm1,xmm8
+ pxor xmm4,xmm5
+
+ movdqa xmm9,xmm0
+ psrlq xmm0,1
+DB 102,15,58,68,234,17
+ pxor xmm1,xmm9
+ pxor xmm9,xmm0
+ psrlq xmm0,5
+ pxor xmm0,xmm9
+ lea r8,QWORD PTR[32+r8]
+ psrlq xmm0,1
+DB 102,15,58,68,231,0
+ pxor xmm0,xmm1
+
+ sub r9,020h
+ ja $L$mod_loop
+
+$L$even_tail::
+ movdqa xmm1,xmm0
+ movdqa xmm8,xmm4
+ pshufd xmm4,xmm0,78
+ pxor xmm4,xmm0
+
+DB 102,15,58,68,198,0
+DB 102,15,58,68,206,17
+DB 102,15,58,68,231,16
+
+ pxor xmm0,xmm3
+ pxor xmm1,xmm5
+ pxor xmm8,xmm0
+ pxor xmm8,xmm1
+ pxor xmm4,xmm8
+ movdqa xmm8,xmm4
+ psrldq xmm8,8
+ pslldq xmm4,8
+ pxor xmm1,xmm8
+ pxor xmm0,xmm4
+
+ movdqa xmm4,xmm0
+ movdqa xmm3,xmm0
+ psllq xmm0,5
+ pxor xmm3,xmm0
+ psllq xmm0,1
+ pxor xmm0,xmm3
+ psllq xmm0,57
+ movdqa xmm3,xmm0
+ pslldq xmm0,8
+ psrldq xmm3,8
+ pxor xmm0,xmm4
+ pxor xmm1,xmm3
+
+
+ movdqa xmm4,xmm0
+ psrlq xmm0,1
+ pxor xmm1,xmm4
+ pxor xmm4,xmm0
+ psrlq xmm0,5
+ pxor xmm0,xmm4
+ psrlq xmm0,1
+ pxor xmm0,xmm1
+ test r9,r9
+ jnz $L$done
+
+$L$odd_tail::
+ movdqu xmm8,XMMWORD PTR[r8]
+DB 102,69,15,56,0,194
+ pxor xmm0,xmm8
+ movdqa xmm1,xmm0
+ pshufd xmm3,xmm0,78
+ pxor xmm3,xmm0
+DB 102,15,58,68,194,0
+DB 102,15,58,68,202,17
+DB 102,15,58,68,223,0
+ pxor xmm3,xmm0
+ pxor xmm3,xmm1
+
+ movdqa xmm4,xmm3
+ psrldq xmm3,8
+ pslldq xmm4,8
+ pxor xmm1,xmm3
+ pxor xmm0,xmm4
+
+ movdqa xmm4,xmm0
+ movdqa xmm3,xmm0
+ psllq xmm0,5
+ pxor xmm3,xmm0
+ psllq xmm0,1
+ pxor xmm0,xmm3
+ psllq xmm0,57
+ movdqa xmm3,xmm0
+ pslldq xmm0,8
+ psrldq xmm3,8
+ pxor xmm0,xmm4
+ pxor xmm1,xmm3
+
+
+ movdqa xmm4,xmm0
+ psrlq xmm0,1
+ pxor xmm1,xmm4
+ pxor xmm4,xmm0
+ psrlq xmm0,5
+ pxor xmm0,xmm4
+ psrlq xmm0,1
+ pxor xmm0,xmm1
+$L$done::
+DB 102,65,15,56,0,194
+ 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]
+ movaps xmm11,XMMWORD PTR[80+rsp]
+ movaps xmm12,XMMWORD PTR[96+rsp]
+ movaps xmm13,XMMWORD PTR[112+rsp]
+ movaps xmm14,XMMWORD PTR[128+rsp]
+ movaps xmm15,XMMWORD PTR[144+rsp]
+ lea rsp,QWORD PTR[168+rsp]
+$L$SEH_end_gcm_ghash_clmul::
+ DB 0F3h,0C3h ;repret
+gcm_ghash_clmul ENDP
+PUBLIC gcm_init_avx
+
+ALIGN 32
+gcm_init_avx PROC PUBLIC
+ jmp $L$_init_clmul
+gcm_init_avx ENDP
+PUBLIC gcm_gmult_avx
+
+ALIGN 32
+gcm_gmult_avx PROC PUBLIC
+ jmp $L$_gmult_clmul
+gcm_gmult_avx ENDP
+PUBLIC gcm_ghash_avx
+
+ALIGN 32
+gcm_ghash_avx PROC PUBLIC
+ jmp $L$_ghash_clmul
+gcm_ghash_avx 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
+$L$7_mask::
+ DD 7,0,7,0
+$L$7_mask_poly::
+ DD 7,0,450,0
+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_init_clmul
+ DD imagerel $L$SEH_end_gcm_init_clmul
+ DD imagerel $L$SEH_info_gcm_init_clmul
+
+ 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_init_clmul::
+DB 001h,008h,003h,000h
+DB 008h,068h,000h,000h
+DB 004h,022h,000h,000h
+$L$SEH_info_gcm_ghash_clmul::
+DB 001h,033h,016h,000h
+DB 033h,0f8h,009h,000h
+DB 02eh,0e8h,008h,000h
+DB 029h,0d8h,007h,000h
+DB 024h,0c8h,006h,000h
+DB 01fh,0b8h,005h,000h
+DB 01ah,0a8h,004h,000h
+DB 015h,098h,003h,000h
+DB 010h,088h,002h,000h
+DB 00ch,078h,001h,000h
+DB 008h,068h,000h,000h
+DB 004h,001h,015h,000h
+
+.xdata ENDS
+END
diff --git a/win-x86_64/crypto/rc4/rc4-md5-x86_64.asm b/win-x86_64/crypto/rc4/rc4-md5-x86_64.asm
new file mode 100644
index 0000000..9d823ae
--- /dev/null
+++ b/win-x86_64/crypto/rc4/rc4-md5-x86_64.asm
@@ -0,0 +1,1374 @@
+OPTION DOTNAME
+.text$ SEGMENT ALIGN(256) '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
+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$body]
+ cmp rbx,r10
+ jb $L$in_prologue
+
+ mov rax,QWORD PTR[152+r8]
+
+ lea r10,QWORD PTR[$L$epilogue]
+ cmp rbx,r10
+ jae $L$in_prologue
+
+ mov r15,QWORD PTR[40+rax]
+ mov r14,QWORD PTR[48+rax]
+ mov r13,QWORD PTR[56+rax]
+ mov r12,QWORD PTR[64+rax]
+ mov rbp,QWORD PTR[72+rax]
+ mov rbx,QWORD PTR[80+rax]
+ lea rax,QWORD PTR[88+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 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_rc4_md5_enc
+ DD imagerel $L$SEH_end_rc4_md5_enc
+ DD imagerel $L$SEH_info_rc4_md5_enc
+
+.pdata ENDS
+.xdata SEGMENT READONLY ALIGN(8)
+ALIGN 8
+$L$SEH_info_rc4_md5_enc::
+DB 9,0,0,0
+ DD imagerel se_handler
+
+.xdata ENDS
+END
diff --git a/win-x86_64/crypto/rc4/rc4-x86_64.asm b/win-x86_64/crypto/rc4/rc4-x86_64.asm
new file mode 100644
index 0000000..c183cac
--- /dev/null
+++ b/win-x86_64/crypto/rc4/rc4-x86_64.asm
@@ -0,0 +1,773 @@
+OPTION DOTNAME
+.text$ SEGMENT ALIGN(256) 'CODE'
+EXTERN OPENSSL_ia32cap_P:NEAR
+
+PUBLIC asm_RC4
+
+ALIGN 16
+asm_RC4 PROC PUBLIC
+ mov QWORD PTR[8+rsp],rdi ;WIN64 prologue
+ mov QWORD PTR[16+rsp],rsi
+ mov rax,rsp
+$L$SEH_begin_asm_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[r13*1+r12],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[r13*1+r12],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[r13*1+r12],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[r13*1+r12],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[r13*1+r12],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[r13*1+r12],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_asm_RC4::
+asm_RC4 ENDP
+PUBLIC asm_RC4_set_key
+
+ALIGN 16
+asm_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_asm_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_asm_RC4_set_key::
+asm_RC4_set_key ENDP
+
+PUBLIC RC4_options
+
+ALIGN 16
+RC4_options PROC PUBLIC
+ lea rax,QWORD PTR[$L$opts]
+ mov rdx,QWORD PTR[OPENSSL_ia32cap_P]
+ mov edx,DWORD PTR[rdx]
+ bt edx,20
+ jc $L$8xchar
+ bt edx,30
+ jnc $L$done
+ add rax,25
+ DB 0F3h,0C3h ;repret
+$L$8xchar::
+ add rax,12
+$L$done::
+ DB 0F3h,0C3h ;repret
+ALIGN 64
+$L$opts::
+DB 114,99,52,40,56,120,44,105,110,116,41,0
+DB 114,99,52,40,56,120,44,99,104,97,114,41,0
+DB 114,99,52,40,49,54,120,44,105,110,116,41,0
+DB 82,67,52,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
+RC4_options ENDP
+EXTERN __imp_RtlVirtualUnwind:NEAR
+
+ALIGN 16
+stream_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$in_prologue
+
+ mov rax,QWORD PTR[152+r8]
+
+ lea r10,QWORD PTR[$L$epilogue]
+ cmp rbx,r10
+ jae $L$in_prologue
+
+ lea rax,QWORD PTR[24+rax]
+
+ mov rbx,QWORD PTR[((-8))+rax]
+ mov r12,QWORD PTR[((-16))+rax]
+ mov r13,QWORD PTR[((-24))+rax]
+ mov QWORD PTR[144+r8],rbx
+ mov QWORD PTR[216+r8],r12
+ mov QWORD PTR[224+r8],r13
+
+$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
+
+ jmp $L$common_seh_exit
+stream_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[152+r8]
+ mov rdi,QWORD PTR[8+rax]
+ mov rsi,QWORD PTR[16+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
+key_se_handler ENDP
+
+.text$ ENDS
+.pdata SEGMENT READONLY ALIGN(4)
+ALIGN 4
+ DD imagerel $L$SEH_begin_asm_RC4
+ DD imagerel $L$SEH_end_asm_RC4
+ DD imagerel $L$SEH_info_asm_RC4
+
+ DD imagerel $L$SEH_begin_asm_RC4_set_key
+ DD imagerel $L$SEH_end_asm_RC4_set_key
+ DD imagerel $L$SEH_info_asm_RC4_set_key
+
+.pdata ENDS
+.xdata SEGMENT READONLY ALIGN(8)
+ALIGN 8
+$L$SEH_info_asm_RC4::
+DB 9,0,0,0
+ DD imagerel stream_se_handler
+$L$SEH_info_asm_RC4_set_key::
+DB 9,0,0,0
+ DD imagerel key_se_handler
+
+.xdata ENDS
+END
diff --git a/win-x86_64/crypto/sha/sha1-x86_64.asm b/win-x86_64/crypto/sha/sha1-x86_64.asm
new file mode 100644
index 0000000..ecda6dc
--- /dev/null
+++ b/win-x86_64/crypto/sha/sha1-x86_64.asm
@@ -0,0 +1,2619 @@
+OPTION DOTNAME
+.text$ SEGMENT ALIGN(256) '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))]
+ mov r10d,DWORD PTR[((OPENSSL_ia32cap_P+8))]
+ test r8d,512
+ jz $L$ialu
+ jmp _ssse3_shortcut
+
+ALIGN 16
+$L$ialu::
+ mov rax,rsp
+ push rbx
+ push rbp
+ push r12
+ push r13
+ push r14
+ mov r8,rdi
+ sub rsp,72
+ mov r9,rsi
+ and rsp,-64
+ mov r10,rdx
+ mov QWORD PTR[64+rsp],rax
+$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 ebp,DWORD PTR[4+r9]
+ mov eax,r12d
+ mov DWORD PTR[rsp],edx
+ mov ecx,esi
+ bswap ebp
+ xor eax,r11d
+ rol ecx,5
+ and eax,edi
+ lea r13d,DWORD PTR[1518500249+r13*1+rdx]
+ add r13d,ecx
+ xor eax,r12d
+ rol edi,30
+ add r13d,eax
+ mov r14d,DWORD PTR[8+r9]
+ mov eax,r11d
+ mov DWORD PTR[4+rsp],ebp
+ mov ecx,r13d
+ bswap r14d
+ xor eax,edi
+ rol ecx,5
+ and eax,esi
+ lea r12d,DWORD PTR[1518500249+r12*1+rbp]
+ add r12d,ecx
+ xor eax,r11d
+ rol esi,30
+ add r12d,eax
+ mov edx,DWORD PTR[12+r9]
+ mov eax,edi
+ mov DWORD PTR[8+rsp],r14d
+ mov ecx,r12d
+ bswap edx
+ xor eax,esi
+ rol ecx,5
+ and eax,r13d
+ lea r11d,DWORD PTR[1518500249+r11*1+r14]
+ add r11d,ecx
+ xor eax,edi
+ rol r13d,30
+ add r11d,eax
+ mov ebp,DWORD PTR[16+r9]
+ mov eax,esi
+ mov DWORD PTR[12+rsp],edx
+ mov ecx,r11d
+ bswap ebp
+ xor eax,r13d
+ rol ecx,5
+ and eax,r12d
+ lea edi,DWORD PTR[1518500249+rdi*1+rdx]
+ add edi,ecx
+ xor eax,esi
+ rol r12d,30
+ add edi,eax
+ mov r14d,DWORD PTR[20+r9]
+ mov eax,r13d
+ mov DWORD PTR[16+rsp],ebp
+ mov ecx,edi
+ bswap r14d
+ xor eax,r12d
+ rol ecx,5
+ and eax,r11d
+ lea esi,DWORD PTR[1518500249+rsi*1+rbp]
+ add esi,ecx
+ xor eax,r13d
+ rol r11d,30
+ add esi,eax
+ mov edx,DWORD PTR[24+r9]
+ mov eax,r12d
+ mov DWORD PTR[20+rsp],r14d
+ mov ecx,esi
+ bswap edx
+ xor eax,r11d
+ rol ecx,5
+ and eax,edi
+ lea r13d,DWORD PTR[1518500249+r13*1+r14]
+ add r13d,ecx
+ xor eax,r12d
+ rol edi,30
+ add r13d,eax
+ mov ebp,DWORD PTR[28+r9]
+ mov eax,r11d
+ mov DWORD PTR[24+rsp],edx
+ mov ecx,r13d
+ bswap ebp
+ xor eax,edi
+ rol ecx,5
+ and eax,esi
+ lea r12d,DWORD PTR[1518500249+r12*1+rdx]
+ add r12d,ecx
+ xor eax,r11d
+ rol esi,30
+ add r12d,eax
+ mov r14d,DWORD PTR[32+r9]
+ mov eax,edi
+ mov DWORD PTR[28+rsp],ebp
+ mov ecx,r12d
+ bswap r14d
+ xor eax,esi
+ rol ecx,5
+ and eax,r13d
+ lea r11d,DWORD PTR[1518500249+r11*1+rbp]
+ add r11d,ecx
+ xor eax,edi
+ rol r13d,30
+ add r11d,eax
+ mov edx,DWORD PTR[36+r9]
+ mov eax,esi
+ mov DWORD PTR[32+rsp],r14d
+ mov ecx,r11d
+ bswap edx
+ xor eax,r13d
+ rol ecx,5
+ and eax,r12d
+ lea edi,DWORD PTR[1518500249+rdi*1+r14]
+ add edi,ecx
+ xor eax,esi
+ rol r12d,30
+ add edi,eax
+ mov ebp,DWORD PTR[40+r9]
+ mov eax,r13d
+ mov DWORD PTR[36+rsp],edx
+ mov ecx,edi
+ bswap ebp
+ xor eax,r12d
+ rol ecx,5
+ and eax,r11d
+ lea esi,DWORD PTR[1518500249+rsi*1+rdx]
+ add esi,ecx
+ xor eax,r13d
+ rol r11d,30
+ add esi,eax
+ mov r14d,DWORD PTR[44+r9]
+ mov eax,r12d
+ mov DWORD PTR[40+rsp],ebp
+ mov ecx,esi
+ bswap r14d
+ xor eax,r11d
+ rol ecx,5
+ and eax,edi
+ lea r13d,DWORD PTR[1518500249+r13*1+rbp]
+ add r13d,ecx
+ xor eax,r12d
+ rol edi,30
+ add r13d,eax
+ mov edx,DWORD PTR[48+r9]
+ mov eax,r11d
+ mov DWORD PTR[44+rsp],r14d
+ mov ecx,r13d
+ bswap edx
+ xor eax,edi
+ rol ecx,5
+ and eax,esi
+ lea r12d,DWORD PTR[1518500249+r12*1+r14]
+ add r12d,ecx
+ xor eax,r11d
+ rol esi,30
+ add r12d,eax
+ mov ebp,DWORD PTR[52+r9]
+ mov eax,edi
+ mov DWORD PTR[48+rsp],edx
+ mov ecx,r12d
+ bswap ebp
+ xor eax,esi
+ rol ecx,5
+ and eax,r13d
+ lea r11d,DWORD PTR[1518500249+r11*1+rdx]
+ add r11d,ecx
+ xor eax,edi
+ rol r13d,30
+ add r11d,eax
+ mov r14d,DWORD PTR[56+r9]
+ mov eax,esi
+ mov DWORD PTR[52+rsp],ebp
+ mov ecx,r11d
+ bswap r14d
+ xor eax,r13d
+ rol ecx,5
+ and eax,r12d
+ lea edi,DWORD PTR[1518500249+rdi*1+rbp]
+ add edi,ecx
+ xor eax,esi
+ rol r12d,30
+ add edi,eax
+ mov edx,DWORD PTR[60+r9]
+ mov eax,r13d
+ mov DWORD PTR[56+rsp],r14d
+ mov ecx,edi
+ bswap edx
+ xor eax,r12d
+ rol ecx,5
+ and eax,r11d
+ lea esi,DWORD PTR[1518500249+rsi*1+r14]
+ add esi,ecx
+ xor eax,r13d
+ rol r11d,30
+ add esi,eax
+ xor ebp,DWORD PTR[rsp]
+ mov eax,r12d
+ mov DWORD PTR[60+rsp],edx
+ mov ecx,esi
+ xor ebp,DWORD PTR[8+rsp]
+ xor eax,r11d
+ rol ecx,5
+ xor ebp,DWORD PTR[32+rsp]
+ and eax,edi
+ lea r13d,DWORD PTR[1518500249+r13*1+rdx]
+ rol edi,30
+ xor eax,r12d
+ add r13d,ecx
+ rol ebp,1
+ add r13d,eax
+ xor r14d,DWORD PTR[4+rsp]
+ mov eax,r11d
+ mov DWORD PTR[rsp],ebp
+ mov ecx,r13d
+ xor r14d,DWORD PTR[12+rsp]
+ xor eax,edi
+ rol ecx,5
+ xor r14d,DWORD PTR[36+rsp]
+ and eax,esi
+ lea r12d,DWORD PTR[1518500249+r12*1+rbp]
+ rol esi,30
+ xor eax,r11d
+ add r12d,ecx
+ rol r14d,1
+ add r12d,eax
+ xor edx,DWORD PTR[8+rsp]
+ mov eax,edi
+ mov DWORD PTR[4+rsp],r14d
+ mov ecx,r12d
+ xor edx,DWORD PTR[16+rsp]
+ xor eax,esi
+ rol ecx,5
+ xor edx,DWORD PTR[40+rsp]
+ and eax,r13d
+ lea r11d,DWORD PTR[1518500249+r11*1+r14]
+ rol r13d,30
+ xor eax,edi
+ add r11d,ecx
+ rol edx,1
+ add r11d,eax
+ xor ebp,DWORD PTR[12+rsp]
+ mov eax,esi
+ mov DWORD PTR[8+rsp],edx
+ mov ecx,r11d
+ xor ebp,DWORD PTR[20+rsp]
+ xor eax,r13d
+ rol ecx,5
+ xor ebp,DWORD PTR[44+rsp]
+ and eax,r12d
+ lea edi,DWORD PTR[1518500249+rdi*1+rdx]
+ rol r12d,30
+ xor eax,esi
+ add edi,ecx
+ rol ebp,1
+ add edi,eax
+ xor r14d,DWORD PTR[16+rsp]
+ mov eax,r13d
+ mov DWORD PTR[12+rsp],ebp
+ mov ecx,edi
+ xor r14d,DWORD PTR[24+rsp]
+ xor eax,r12d
+ rol ecx,5
+ xor r14d,DWORD PTR[48+rsp]
+ and eax,r11d
+ lea esi,DWORD PTR[1518500249+rsi*1+rbp]
+ rol r11d,30
+ xor eax,r13d
+ add esi,ecx
+ rol r14d,1
+ add esi,eax
+ xor edx,DWORD PTR[20+rsp]
+ mov eax,edi
+ mov DWORD PTR[16+rsp],r14d
+ mov ecx,esi
+ xor edx,DWORD PTR[28+rsp]
+ xor eax,r12d
+ rol ecx,5
+ xor edx,DWORD PTR[52+rsp]
+ lea r13d,DWORD PTR[1859775393+r13*1+r14]
+ xor eax,r11d
+ add r13d,ecx
+ rol edi,30
+ add r13d,eax
+ rol edx,1
+ xor ebp,DWORD PTR[24+rsp]
+ mov eax,esi
+ mov DWORD PTR[20+rsp],edx
+ mov ecx,r13d
+ xor ebp,DWORD PTR[32+rsp]
+ xor eax,r11d
+ rol ecx,5
+ xor ebp,DWORD PTR[56+rsp]
+ lea r12d,DWORD PTR[1859775393+r12*1+rdx]
+ xor eax,edi
+ add r12d,ecx
+ rol esi,30
+ add r12d,eax
+ rol ebp,1
+ xor r14d,DWORD PTR[28+rsp]
+ mov eax,r13d
+ mov DWORD PTR[24+rsp],ebp
+ mov ecx,r12d
+ xor r14d,DWORD PTR[36+rsp]
+ xor eax,edi
+ rol ecx,5
+ xor r14d,DWORD PTR[60+rsp]
+ lea r11d,DWORD PTR[1859775393+r11*1+rbp]
+ xor eax,esi
+ add r11d,ecx
+ rol r13d,30
+ add r11d,eax
+ rol r14d,1
+ xor edx,DWORD PTR[32+rsp]
+ mov eax,r12d
+ mov DWORD PTR[28+rsp],r14d
+ mov ecx,r11d
+ xor edx,DWORD PTR[40+rsp]
+ xor eax,esi
+ rol ecx,5
+ xor edx,DWORD PTR[rsp]
+ lea edi,DWORD PTR[1859775393+rdi*1+r14]
+ xor eax,r13d
+ add edi,ecx
+ rol r12d,30
+ add edi,eax
+ rol edx,1
+ xor ebp,DWORD PTR[36+rsp]
+ mov eax,r11d
+ mov DWORD PTR[32+rsp],edx
+ mov ecx,edi
+ xor ebp,DWORD PTR[44+rsp]
+ xor eax,r13d
+ rol ecx,5
+ xor ebp,DWORD PTR[4+rsp]
+ lea esi,DWORD PTR[1859775393+rsi*1+rdx]
+ xor eax,r12d
+ add esi,ecx
+ rol r11d,30
+ add esi,eax
+ rol ebp,1
+ xor r14d,DWORD PTR[40+rsp]
+ mov eax,edi
+ mov DWORD PTR[36+rsp],ebp
+ mov ecx,esi
+ xor r14d,DWORD PTR[48+rsp]
+ xor eax,r12d
+ rol ecx,5
+ xor r14d,DWORD PTR[8+rsp]
+ lea r13d,DWORD PTR[1859775393+r13*1+rbp]
+ xor eax,r11d
+ add r13d,ecx
+ rol edi,30
+ add r13d,eax
+ rol r14d,1
+ xor edx,DWORD PTR[44+rsp]
+ mov eax,esi
+ mov DWORD PTR[40+rsp],r14d
+ mov ecx,r13d
+ xor edx,DWORD PTR[52+rsp]
+ xor eax,r11d
+ rol ecx,5
+ xor edx,DWORD PTR[12+rsp]
+ lea r12d,DWORD PTR[1859775393+r12*1+r14]
+ xor eax,edi
+ add r12d,ecx
+ rol esi,30
+ add r12d,eax
+ rol edx,1
+ xor ebp,DWORD PTR[48+rsp]
+ mov eax,r13d
+ mov DWORD PTR[44+rsp],edx
+ mov ecx,r12d
+ xor ebp,DWORD PTR[56+rsp]
+ xor eax,edi
+ rol ecx,5
+ xor ebp,DWORD PTR[16+rsp]
+ lea r11d,DWORD PTR[1859775393+r11*1+rdx]
+ xor eax,esi
+ add r11d,ecx
+ rol r13d,30
+ add r11d,eax
+ rol ebp,1
+ xor r14d,DWORD PTR[52+rsp]
+ mov eax,r12d
+ mov DWORD PTR[48+rsp],ebp
+ mov ecx,r11d
+ xor r14d,DWORD PTR[60+rsp]
+ xor eax,esi
+ rol ecx,5
+ xor r14d,DWORD PTR[20+rsp]
+ lea edi,DWORD PTR[1859775393+rdi*1+rbp]
+ xor eax,r13d
+ add edi,ecx
+ rol r12d,30
+ add edi,eax
+ rol r14d,1
+ xor edx,DWORD PTR[56+rsp]
+ mov eax,r11d
+ mov DWORD PTR[52+rsp],r14d
+ mov ecx,edi
+ xor edx,DWORD PTR[rsp]
+ xor eax,r13d
+ rol ecx,5
+ xor edx,DWORD PTR[24+rsp]
+ lea esi,DWORD PTR[1859775393+rsi*1+r14]
+ xor eax,r12d
+ add esi,ecx
+ rol r11d,30
+ add esi,eax
+ rol edx,1
+ xor ebp,DWORD PTR[60+rsp]
+ mov eax,edi
+ mov DWORD PTR[56+rsp],edx
+ mov ecx,esi
+ xor ebp,DWORD PTR[4+rsp]
+ xor eax,r12d
+ rol ecx,5
+ xor ebp,DWORD PTR[28+rsp]
+ lea r13d,DWORD PTR[1859775393+r13*1+rdx]
+ xor eax,r11d
+ add r13d,ecx
+ rol edi,30
+ add r13d,eax
+ rol ebp,1
+ xor r14d,DWORD PTR[rsp]
+ mov eax,esi
+ mov DWORD PTR[60+rsp],ebp
+ mov ecx,r13d
+ xor r14d,DWORD PTR[8+rsp]
+ xor eax,r11d
+ rol ecx,5
+ xor r14d,DWORD PTR[32+rsp]
+ lea r12d,DWORD PTR[1859775393+r12*1+rbp]
+ xor eax,edi
+ add r12d,ecx
+ rol esi,30
+ add r12d,eax
+ rol r14d,1
+ xor edx,DWORD PTR[4+rsp]
+ mov eax,r13d
+ mov DWORD PTR[rsp],r14d
+ mov ecx,r12d
+ xor edx,DWORD PTR[12+rsp]
+ xor eax,edi
+ rol ecx,5
+ xor edx,DWORD PTR[36+rsp]
+ lea r11d,DWORD PTR[1859775393+r11*1+r14]
+ xor eax,esi
+ add r11d,ecx
+ rol r13d,30
+ add r11d,eax
+ rol edx,1
+ xor ebp,DWORD PTR[8+rsp]
+ mov eax,r12d
+ mov DWORD PTR[4+rsp],edx
+ mov ecx,r11d
+ xor ebp,DWORD PTR[16+rsp]
+ xor eax,esi
+ rol ecx,5
+ xor ebp,DWORD PTR[40+rsp]
+ lea edi,DWORD PTR[1859775393+rdi*1+rdx]
+ xor eax,r13d
+ add edi,ecx
+ rol r12d,30
+ add edi,eax
+ rol ebp,1
+ xor r14d,DWORD PTR[12+rsp]
+ mov eax,r11d
+ mov DWORD PTR[8+rsp],ebp
+ mov ecx,edi
+ xor r14d,DWORD PTR[20+rsp]
+ xor eax,r13d
+ rol ecx,5
+ xor r14d,DWORD PTR[44+rsp]
+ lea esi,DWORD PTR[1859775393+rsi*1+rbp]
+ xor eax,r12d
+ add esi,ecx
+ rol r11d,30
+ add esi,eax
+ rol r14d,1
+ xor edx,DWORD PTR[16+rsp]
+ mov eax,edi
+ mov DWORD PTR[12+rsp],r14d
+ mov ecx,esi
+ xor edx,DWORD PTR[24+rsp]
+ xor eax,r12d
+ rol ecx,5
+ xor edx,DWORD PTR[48+rsp]
+ lea r13d,DWORD PTR[1859775393+r13*1+r14]
+ xor eax,r11d
+ add r13d,ecx
+ rol edi,30
+ add r13d,eax
+ rol edx,1
+ xor ebp,DWORD PTR[20+rsp]
+ mov eax,esi
+ mov DWORD PTR[16+rsp],edx
+ mov ecx,r13d
+ xor ebp,DWORD PTR[28+rsp]
+ xor eax,r11d
+ rol ecx,5
+ xor ebp,DWORD PTR[52+rsp]
+ lea r12d,DWORD PTR[1859775393+r12*1+rdx]
+ xor eax,edi
+ add r12d,ecx
+ rol esi,30
+ add r12d,eax
+ rol ebp,1
+ xor r14d,DWORD PTR[24+rsp]
+ mov eax,r13d
+ mov DWORD PTR[20+rsp],ebp
+ mov ecx,r12d
+ xor r14d,DWORD PTR[32+rsp]
+ xor eax,edi
+ rol ecx,5
+ xor r14d,DWORD PTR[56+rsp]
+ lea r11d,DWORD PTR[1859775393+r11*1+rbp]
+ xor eax,esi
+ add r11d,ecx
+ rol r13d,30
+ add r11d,eax
+ rol r14d,1
+ xor edx,DWORD PTR[28+rsp]
+ mov eax,r12d
+ mov DWORD PTR[24+rsp],r14d
+ mov ecx,r11d
+ xor edx,DWORD PTR[36+rsp]
+ xor eax,esi
+ rol ecx,5
+ xor edx,DWORD PTR[60+rsp]
+ lea edi,DWORD PTR[1859775393+rdi*1+r14]
+ xor eax,r13d
+ add edi,ecx
+ rol r12d,30
+ add edi,eax
+ rol edx,1
+ xor ebp,DWORD PTR[32+rsp]
+ mov eax,r11d
+ mov DWORD PTR[28+rsp],edx
+ mov ecx,edi
+ xor ebp,DWORD PTR[40+rsp]
+ xor eax,r13d
+ rol ecx,5
+ xor ebp,DWORD PTR[rsp]
+ lea esi,DWORD PTR[1859775393+rsi*1+rdx]
+ xor eax,r12d
+ add esi,ecx
+ rol r11d,30
+ add esi,eax
+ rol ebp,1
+ xor r14d,DWORD PTR[36+rsp]
+ mov eax,r12d
+ mov DWORD PTR[32+rsp],ebp
+ mov ebx,r12d
+ xor r14d,DWORD PTR[44+rsp]
+ and eax,r11d
+ mov ecx,esi
+ xor r14d,DWORD PTR[4+rsp]
+ lea r13d,DWORD PTR[((-1894007588))+r13*1+rbp]
+ xor ebx,r11d
+ rol ecx,5
+ add r13d,eax
+ rol r14d,1
+ and ebx,edi
+ add r13d,ecx
+ rol edi,30
+ add r13d,ebx
+ xor edx,DWORD PTR[40+rsp]
+ mov eax,r11d
+ mov DWORD PTR[36+rsp],r14d
+ mov ebx,r11d
+ xor edx,DWORD PTR[48+rsp]
+ and eax,edi
+ mov ecx,r13d
+ xor edx,DWORD PTR[8+rsp]
+ lea r12d,DWORD PTR[((-1894007588))+r12*1+r14]
+ xor ebx,edi
+ rol ecx,5
+ add r12d,eax
+ rol edx,1
+ and ebx,esi
+ add r12d,ecx
+ rol esi,30
+ add r12d,ebx
+ xor ebp,DWORD PTR[44+rsp]
+ mov eax,edi
+ mov DWORD PTR[40+rsp],edx
+ mov ebx,edi
+ xor ebp,DWORD PTR[52+rsp]
+ and eax,esi
+ mov ecx,r12d
+ xor ebp,DWORD PTR[12+rsp]
+ lea r11d,DWORD PTR[((-1894007588))+r11*1+rdx]
+ xor ebx,esi
+ rol ecx,5
+ add r11d,eax
+ rol ebp,1
+ and ebx,r13d
+ add r11d,ecx
+ rol r13d,30
+ add r11d,ebx
+ xor r14d,DWORD PTR[48+rsp]
+ mov eax,esi
+ mov DWORD PTR[44+rsp],ebp
+ mov ebx,esi
+ xor r14d,DWORD PTR[56+rsp]
+ and eax,r13d
+ mov ecx,r11d
+ xor r14d,DWORD PTR[16+rsp]
+ lea edi,DWORD PTR[((-1894007588))+rdi*1+rbp]
+ xor ebx,r13d
+ rol ecx,5
+ add edi,eax
+ rol r14d,1
+ and ebx,r12d
+ add edi,ecx
+ rol r12d,30
+ add edi,ebx
+ xor edx,DWORD PTR[52+rsp]
+ mov eax,r13d
+ mov DWORD PTR[48+rsp],r14d
+ mov ebx,r13d
+ xor edx,DWORD PTR[60+rsp]
+ and eax,r12d
+ mov ecx,edi
+ xor edx,DWORD PTR[20+rsp]
+ lea esi,DWORD PTR[((-1894007588))+rsi*1+r14]
+ xor ebx,r12d
+ rol ecx,5
+ add esi,eax
+ rol edx,1
+ and ebx,r11d
+ add esi,ecx
+ rol r11d,30
+ add esi,ebx
+ xor ebp,DWORD PTR[56+rsp]
+ mov eax,r12d
+ mov DWORD PTR[52+rsp],edx
+ mov ebx,r12d
+ xor ebp,DWORD PTR[rsp]
+ and eax,r11d
+ mov ecx,esi
+ xor ebp,DWORD PTR[24+rsp]
+ lea r13d,DWORD PTR[((-1894007588))+r13*1+rdx]
+ xor ebx,r11d
+ rol ecx,5
+ add r13d,eax
+ rol ebp,1
+ and ebx,edi
+ add r13d,ecx
+ rol edi,30
+ add r13d,ebx
+ xor r14d,DWORD PTR[60+rsp]
+ mov eax,r11d
+ mov DWORD PTR[56+rsp],ebp
+ mov ebx,r11d
+ xor r14d,DWORD PTR[4+rsp]
+ and eax,edi
+ mov ecx,r13d
+ xor r14d,DWORD PTR[28+rsp]
+ lea r12d,DWORD PTR[((-1894007588))+r12*1+rbp]
+ xor ebx,edi
+ rol ecx,5
+ add r12d,eax
+ rol r14d,1
+ and ebx,esi
+ add r12d,ecx
+ rol esi,30
+ add r12d,ebx
+ xor edx,DWORD PTR[rsp]
+ mov eax,edi
+ mov DWORD PTR[60+rsp],r14d
+ mov ebx,edi
+ xor edx,DWORD PTR[8+rsp]
+ and eax,esi
+ mov ecx,r12d
+ xor edx,DWORD PTR[32+rsp]
+ lea r11d,DWORD PTR[((-1894007588))+r11*1+r14]
+ xor ebx,esi
+ rol ecx,5
+ add r11d,eax
+ rol edx,1
+ and ebx,r13d
+ add r11d,ecx
+ rol r13d,30
+ add r11d,ebx
+ xor ebp,DWORD PTR[4+rsp]
+ mov eax,esi
+ mov DWORD PTR[rsp],edx
+ mov ebx,esi
+ xor ebp,DWORD PTR[12+rsp]
+ and eax,r13d
+ mov ecx,r11d
+ xor ebp,DWORD PTR[36+rsp]
+ lea edi,DWORD PTR[((-1894007588))+rdi*1+rdx]
+ xor ebx,r13d
+ rol ecx,5
+ add edi,eax
+ rol ebp,1
+ and ebx,r12d
+ add edi,ecx
+ rol r12d,30
+ add edi,ebx
+ xor r14d,DWORD PTR[8+rsp]
+ mov eax,r13d
+ mov DWORD PTR[4+rsp],ebp
+ mov ebx,r13d
+ xor r14d,DWORD PTR[16+rsp]
+ and eax,r12d
+ mov ecx,edi
+ xor r14d,DWORD PTR[40+rsp]
+ lea esi,DWORD PTR[((-1894007588))+rsi*1+rbp]
+ xor ebx,r12d
+ rol ecx,5
+ add esi,eax
+ rol r14d,1
+ and ebx,r11d
+ add esi,ecx
+ rol r11d,30
+ add esi,ebx
+ xor edx,DWORD PTR[12+rsp]
+ mov eax,r12d
+ mov DWORD PTR[8+rsp],r14d
+ mov ebx,r12d
+ xor edx,DWORD PTR[20+rsp]
+ and eax,r11d
+ mov ecx,esi
+ xor edx,DWORD PTR[44+rsp]
+ lea r13d,DWORD PTR[((-1894007588))+r13*1+r14]
+ xor ebx,r11d
+ rol ecx,5
+ add r13d,eax
+ rol edx,1
+ and ebx,edi
+ add r13d,ecx
+ rol edi,30
+ add r13d,ebx
+ xor ebp,DWORD PTR[16+rsp]
+ mov eax,r11d
+ mov DWORD PTR[12+rsp],edx
+ mov ebx,r11d
+ xor ebp,DWORD PTR[24+rsp]
+ and eax,edi
+ mov ecx,r13d
+ xor ebp,DWORD PTR[48+rsp]
+ lea r12d,DWORD PTR[((-1894007588))+r12*1+rdx]
+ xor ebx,edi
+ rol ecx,5
+ add r12d,eax
+ rol ebp,1
+ and ebx,esi
+ add r12d,ecx
+ rol esi,30
+ add r12d,ebx
+ xor r14d,DWORD PTR[20+rsp]
+ mov eax,edi
+ mov DWORD PTR[16+rsp],ebp
+ mov ebx,edi
+ xor r14d,DWORD PTR[28+rsp]
+ and eax,esi
+ mov ecx,r12d
+ xor r14d,DWORD PTR[52+rsp]
+ lea r11d,DWORD PTR[((-1894007588))+r11*1+rbp]
+ xor ebx,esi
+ rol ecx,5
+ add r11d,eax
+ rol r14d,1
+ and ebx,r13d
+ add r11d,ecx
+ rol r13d,30
+ add r11d,ebx
+ xor edx,DWORD PTR[24+rsp]
+ mov eax,esi
+ mov DWORD PTR[20+rsp],r14d
+ mov ebx,esi
+ xor edx,DWORD PTR[32+rsp]
+ and eax,r13d
+ mov ecx,r11d
+ xor edx,DWORD PTR[56+rsp]
+ lea edi,DWORD PTR[((-1894007588))+rdi*1+r14]
+ xor ebx,r13d
+ rol ecx,5
+ add edi,eax
+ rol edx,1
+ and ebx,r12d
+ add edi,ecx
+ rol r12d,30
+ add edi,ebx
+ xor ebp,DWORD PTR[28+rsp]
+ mov eax,r13d
+ mov DWORD PTR[24+rsp],edx
+ mov ebx,r13d
+ xor ebp,DWORD PTR[36+rsp]
+ and eax,r12d
+ mov ecx,edi
+ xor ebp,DWORD PTR[60+rsp]
+ lea esi,DWORD PTR[((-1894007588))+rsi*1+rdx]
+ xor ebx,r12d
+ rol ecx,5
+ add esi,eax
+ rol ebp,1
+ and ebx,r11d
+ add esi,ecx
+ rol r11d,30
+ add esi,ebx
+ xor r14d,DWORD PTR[32+rsp]
+ mov eax,r12d
+ mov DWORD PTR[28+rsp],ebp
+ mov ebx,r12d
+ xor r14d,DWORD PTR[40+rsp]
+ and eax,r11d
+ mov ecx,esi
+ xor r14d,DWORD PTR[rsp]
+ lea r13d,DWORD PTR[((-1894007588))+r13*1+rbp]
+ xor ebx,r11d
+ rol ecx,5
+ add r13d,eax
+ rol r14d,1
+ and ebx,edi
+ add r13d,ecx
+ rol edi,30
+ add r13d,ebx
+ xor edx,DWORD PTR[36+rsp]
+ mov eax,r11d
+ mov DWORD PTR[32+rsp],r14d
+ mov ebx,r11d
+ xor edx,DWORD PTR[44+rsp]
+ and eax,edi
+ mov ecx,r13d
+ xor edx,DWORD PTR[4+rsp]
+ lea r12d,DWORD PTR[((-1894007588))+r12*1+r14]
+ xor ebx,edi
+ rol ecx,5
+ add r12d,eax
+ rol edx,1
+ and ebx,esi
+ add r12d,ecx
+ rol esi,30
+ add r12d,ebx
+ xor ebp,DWORD PTR[40+rsp]
+ mov eax,edi
+ mov DWORD PTR[36+rsp],edx
+ mov ebx,edi
+ xor ebp,DWORD PTR[48+rsp]
+ and eax,esi
+ mov ecx,r12d
+ xor ebp,DWORD PTR[8+rsp]
+ lea r11d,DWORD PTR[((-1894007588))+r11*1+rdx]
+ xor ebx,esi
+ rol ecx,5
+ add r11d,eax
+ rol ebp,1
+ and ebx,r13d
+ add r11d,ecx
+ rol r13d,30
+ add r11d,ebx
+ xor r14d,DWORD PTR[44+rsp]
+ mov eax,esi
+ mov DWORD PTR[40+rsp],ebp
+ mov ebx,esi
+ xor r14d,DWORD PTR[52+rsp]
+ and eax,r13d
+ mov ecx,r11d
+ xor r14d,DWORD PTR[12+rsp]
+ lea edi,DWORD PTR[((-1894007588))+rdi*1+rbp]
+ xor ebx,r13d
+ rol ecx,5
+ add edi,eax
+ rol r14d,1
+ and ebx,r12d
+ add edi,ecx
+ rol r12d,30
+ add edi,ebx
+ xor edx,DWORD PTR[48+rsp]
+ mov eax,r13d
+ mov DWORD PTR[44+rsp],r14d
+ mov ebx,r13d
+ xor edx,DWORD PTR[56+rsp]
+ and eax,r12d
+ mov ecx,edi
+ xor edx,DWORD PTR[16+rsp]
+ lea esi,DWORD PTR[((-1894007588))+rsi*1+r14]
+ xor ebx,r12d
+ rol ecx,5
+ add esi,eax
+ rol edx,1
+ and ebx,r11d
+ add esi,ecx
+ rol r11d,30
+ add esi,ebx
+ xor ebp,DWORD PTR[52+rsp]
+ mov eax,edi
+ mov DWORD PTR[48+rsp],edx
+ mov ecx,esi
+ xor ebp,DWORD PTR[60+rsp]
+ xor eax,r12d
+ rol ecx,5
+ xor ebp,DWORD PTR[20+rsp]
+ lea r13d,DWORD PTR[((-899497514))+r13*1+rdx]
+ xor eax,r11d
+ add r13d,ecx
+ rol edi,30
+ add r13d,eax
+ rol ebp,1
+ xor r14d,DWORD PTR[56+rsp]
+ mov eax,esi
+ mov DWORD PTR[52+rsp],ebp
+ mov ecx,r13d
+ xor r14d,DWORD PTR[rsp]
+ xor eax,r11d
+ rol ecx,5
+ xor r14d,DWORD PTR[24+rsp]
+ lea r12d,DWORD PTR[((-899497514))+r12*1+rbp]
+ xor eax,edi
+ add r12d,ecx
+ rol esi,30
+ add r12d,eax
+ rol r14d,1
+ xor edx,DWORD PTR[60+rsp]
+ mov eax,r13d
+ mov DWORD PTR[56+rsp],r14d
+ mov ecx,r12d
+ xor edx,DWORD PTR[4+rsp]
+ xor eax,edi
+ rol ecx,5
+ xor edx,DWORD PTR[28+rsp]
+ lea r11d,DWORD PTR[((-899497514))+r11*1+r14]
+ xor eax,esi
+ add r11d,ecx
+ rol r13d,30
+ add r11d,eax
+ rol edx,1
+ xor ebp,DWORD PTR[rsp]
+ mov eax,r12d
+ mov DWORD PTR[60+rsp],edx
+ mov ecx,r11d
+ xor ebp,DWORD PTR[8+rsp]
+ xor eax,esi
+ rol ecx,5
+ xor ebp,DWORD PTR[32+rsp]
+ lea edi,DWORD PTR[((-899497514))+rdi*1+rdx]
+ xor eax,r13d
+ add edi,ecx
+ rol r12d,30
+ add edi,eax
+ rol ebp,1
+ xor r14d,DWORD PTR[4+rsp]
+ mov eax,r11d
+ mov DWORD PTR[rsp],ebp
+ mov ecx,edi
+ xor r14d,DWORD PTR[12+rsp]
+ xor eax,r13d
+ rol ecx,5
+ xor r14d,DWORD PTR[36+rsp]
+ lea esi,DWORD PTR[((-899497514))+rsi*1+rbp]
+ xor eax,r12d
+ add esi,ecx
+ rol r11d,30
+ add esi,eax
+ rol r14d,1
+ xor edx,DWORD PTR[8+rsp]
+ mov eax,edi
+ mov DWORD PTR[4+rsp],r14d
+ mov ecx,esi
+ xor edx,DWORD PTR[16+rsp]
+ xor eax,r12d
+ rol ecx,5
+ xor edx,DWORD PTR[40+rsp]
+ lea r13d,DWORD PTR[((-899497514))+r13*1+r14]
+ xor eax,r11d
+ add r13d,ecx
+ rol edi,30
+ add r13d,eax
+ rol edx,1
+ xor ebp,DWORD PTR[12+rsp]
+ mov eax,esi
+ mov DWORD PTR[8+rsp],edx
+ mov ecx,r13d
+ xor ebp,DWORD PTR[20+rsp]
+ xor eax,r11d
+ rol ecx,5
+ xor ebp,DWORD PTR[44+rsp]
+ lea r12d,DWORD PTR[((-899497514))+r12*1+rdx]
+ xor eax,edi
+ add r12d,ecx
+ rol esi,30
+ add r12d,eax
+ rol ebp,1
+ xor r14d,DWORD PTR[16+rsp]
+ mov eax,r13d
+ mov DWORD PTR[12+rsp],ebp
+ mov ecx,r12d
+ xor r14d,DWORD PTR[24+rsp]
+ xor eax,edi
+ rol ecx,5
+ xor r14d,DWORD PTR[48+rsp]
+ lea r11d,DWORD PTR[((-899497514))+r11*1+rbp]
+ xor eax,esi
+ add r11d,ecx
+ rol r13d,30
+ add r11d,eax
+ rol r14d,1
+ xor edx,DWORD PTR[20+rsp]
+ mov eax,r12d
+ mov DWORD PTR[16+rsp],r14d
+ mov ecx,r11d
+ xor edx,DWORD PTR[28+rsp]
+ xor eax,esi
+ rol ecx,5
+ xor edx,DWORD PTR[52+rsp]
+ lea edi,DWORD PTR[((-899497514))+rdi*1+r14]
+ xor eax,r13d
+ add edi,ecx
+ rol r12d,30
+ add edi,eax
+ rol edx,1
+ xor ebp,DWORD PTR[24+rsp]
+ mov eax,r11d
+ mov DWORD PTR[20+rsp],edx
+ mov ecx,edi
+ xor ebp,DWORD PTR[32+rsp]
+ xor eax,r13d
+ rol ecx,5
+ xor ebp,DWORD PTR[56+rsp]
+ lea esi,DWORD PTR[((-899497514))+rsi*1+rdx]
+ xor eax,r12d
+ add esi,ecx
+ rol r11d,30
+ add esi,eax
+ rol ebp,1
+ xor r14d,DWORD PTR[28+rsp]
+ mov eax,edi
+ mov DWORD PTR[24+rsp],ebp
+ mov ecx,esi
+ xor r14d,DWORD PTR[36+rsp]
+ xor eax,r12d
+ rol ecx,5
+ xor r14d,DWORD PTR[60+rsp]
+ lea r13d,DWORD PTR[((-899497514))+r13*1+rbp]
+ xor eax,r11d
+ add r13d,ecx
+ rol edi,30
+ add r13d,eax
+ rol r14d,1
+ xor edx,DWORD PTR[32+rsp]
+ mov eax,esi
+ mov DWORD PTR[28+rsp],r14d
+ mov ecx,r13d
+ xor edx,DWORD PTR[40+rsp]
+ xor eax,r11d
+ rol ecx,5
+ xor edx,DWORD PTR[rsp]
+ lea r12d,DWORD PTR[((-899497514))+r12*1+r14]
+ xor eax,edi
+ add r12d,ecx
+ rol esi,30
+ add r12d,eax
+ rol edx,1
+ xor ebp,DWORD PTR[36+rsp]
+ mov eax,r13d
+
+ mov ecx,r12d
+ xor ebp,DWORD PTR[44+rsp]
+ xor eax,edi
+ rol ecx,5
+ xor ebp,DWORD PTR[4+rsp]
+ lea r11d,DWORD PTR[((-899497514))+r11*1+rdx]
+ xor eax,esi
+ add r11d,ecx
+ rol r13d,30
+ add r11d,eax
+ rol ebp,1
+ xor r14d,DWORD PTR[40+rsp]
+ mov eax,r12d
+
+ mov ecx,r11d
+ xor r14d,DWORD PTR[48+rsp]
+ xor eax,esi
+ rol ecx,5
+ xor r14d,DWORD PTR[8+rsp]
+ lea edi,DWORD PTR[((-899497514))+rdi*1+rbp]
+ xor eax,r13d
+ add edi,ecx
+ rol r12d,30
+ add edi,eax
+ rol r14d,1
+ xor edx,DWORD PTR[44+rsp]
+ mov eax,r11d
+
+ mov ecx,edi
+ xor edx,DWORD PTR[52+rsp]
+ xor eax,r13d
+ rol ecx,5
+ xor edx,DWORD PTR[12+rsp]
+ lea esi,DWORD PTR[((-899497514))+rsi*1+r14]
+ xor eax,r12d
+ add esi,ecx
+ rol r11d,30
+ add esi,eax
+ rol edx,1
+ xor ebp,DWORD PTR[48+rsp]
+ mov eax,edi
+
+ mov ecx,esi
+ xor ebp,DWORD PTR[56+rsp]
+ xor eax,r12d
+ rol ecx,5
+ xor ebp,DWORD PTR[16+rsp]
+ lea r13d,DWORD PTR[((-899497514))+r13*1+rdx]
+ xor eax,r11d
+ add r13d,ecx
+ rol edi,30
+ add r13d,eax
+ rol ebp,1
+ xor r14d,DWORD PTR[52+rsp]
+ mov eax,esi
+
+ mov ecx,r13d
+ xor r14d,DWORD PTR[60+rsp]
+ xor eax,r11d
+ rol ecx,5
+ xor r14d,DWORD PTR[20+rsp]
+ lea r12d,DWORD PTR[((-899497514))+r12*1+rbp]
+ xor eax,edi
+ add r12d,ecx
+ rol esi,30
+ add r12d,eax
+ rol r14d,1
+ xor edx,DWORD PTR[56+rsp]
+ mov eax,r13d
+
+ mov ecx,r12d
+ xor edx,DWORD PTR[rsp]
+ xor eax,edi
+ rol ecx,5
+ xor edx,DWORD PTR[24+rsp]
+ lea r11d,DWORD PTR[((-899497514))+r11*1+r14]
+ xor eax,esi
+ add r11d,ecx
+ rol r13d,30
+ add r11d,eax
+ rol edx,1
+ xor ebp,DWORD PTR[60+rsp]
+ mov eax,r12d
+
+ mov ecx,r11d
+ xor ebp,DWORD PTR[4+rsp]
+ xor eax,esi
+ rol ecx,5
+ xor ebp,DWORD PTR[28+rsp]
+ lea edi,DWORD PTR[((-899497514))+rdi*1+rdx]
+ xor eax,r13d
+ add edi,ecx
+ rol r12d,30
+ add edi,eax
+ rol ebp,1
+ mov eax,r11d
+ mov ecx,edi
+ xor eax,r13d
+ lea esi,DWORD PTR[((-899497514))+rsi*1+rbp]
+ rol ecx,5
+ xor eax,r12d
+ 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 r14,QWORD PTR[((-40))+rsi]
+ mov r13,QWORD PTR[((-32))+rsi]
+ mov r12,QWORD PTR[((-24))+rsi]
+ mov rbp,QWORD PTR[((-16))+rsi]
+ mov rbx,QWORD PTR[((-8))+rsi]
+ lea rsp,QWORD PTR[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::
+ mov rax,rsp
+ push rbx
+ push rbp
+ push r12
+ push r13
+ push r14
+ lea rsp,QWORD PTR[((-160))+rsp]
+ movaps XMMWORD PTR[(-40-96)+rax],xmm6
+ movaps XMMWORD PTR[(-40-80)+rax],xmm7
+ movaps XMMWORD PTR[(-40-64)+rax],xmm8
+ movaps XMMWORD PTR[(-40-48)+rax],xmm9
+ movaps XMMWORD PTR[(-40-32)+rax],xmm10
+ movaps XMMWORD PTR[(-40-16)+rax],xmm11
+$L$prologue_ssse3::
+ mov r14,rax
+ and rsp,-64
+ mov r8,rdi
+ mov r9,rsi
+ mov r10,rdx
+
+ shl r10,6
+ add r10,r9
+ lea r11,QWORD PTR[((K_XX_XX+64))]
+
+ 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]
+ mov edi,ecx
+ xor edi,edx
+ and esi,edi
+
+ movdqa xmm6,XMMWORD PTR[64+r11]
+ movdqa xmm9,XMMWORD PTR[((-64))+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
+DB 102,15,56,0,206
+DB 102,15,56,0,214
+ add r9,64
+ paddd xmm0,xmm9
+DB 102,15,56,0,222
+ 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::
+ ror ebx,2
+ pshufd xmm4,xmm0,238
+ xor esi,edx
+ movdqa xmm8,xmm3
+ paddd xmm9,xmm3
+ mov edi,eax
+ add ebp,DWORD PTR[rsp]
+ punpcklqdq xmm4,xmm1
+ xor ebx,ecx
+ rol eax,5
+ add ebp,esi
+ psrldq xmm8,4
+ and edi,ebx
+ xor ebx,ecx
+ pxor xmm4,xmm0
+ add ebp,eax
+ ror eax,7
+ pxor xmm8,xmm2
+ xor edi,ecx
+ mov esi,ebp
+ add edx,DWORD PTR[4+rsp]
+ pxor xmm4,xmm8
+ xor eax,ebx
+ rol ebp,5
+ movdqa XMMWORD PTR[48+rsp],xmm9
+ add edx,edi
+ and esi,eax
+ movdqa xmm10,xmm4
+ xor eax,ebx
+ add edx,ebp
+ ror ebp,7
+ movdqa xmm8,xmm4
+ xor esi,ebx
+ pslldq xmm10,12
+ paddd xmm4,xmm4
+ mov edi,edx
+ add ecx,DWORD PTR[8+rsp]
+ psrld xmm8,31
+ xor ebp,eax
+ rol edx,5
+ add ecx,esi
+ movdqa xmm9,xmm10
+ and edi,ebp
+ xor ebp,eax
+ psrld xmm10,30
+ add ecx,edx
+ ror edx,7
+ por xmm4,xmm8
+ xor edi,eax
+ mov esi,ecx
+ add ebx,DWORD PTR[12+rsp]
+ pslld xmm9,2
+ pxor xmm4,xmm10
+ xor edx,ebp
+ movdqa xmm10,XMMWORD PTR[((-64))+r11]
+ rol ecx,5
+ add ebx,edi
+ and esi,edx
+ pxor xmm4,xmm9
+ xor edx,ebp
+ add ebx,ecx
+ ror ecx,7
+ pshufd xmm5,xmm1,238
+ xor esi,ebp
+ movdqa xmm9,xmm4
+ paddd xmm10,xmm4
+ mov edi,ebx
+ add eax,DWORD PTR[16+rsp]
+ punpcklqdq xmm5,xmm2
+ xor ecx,edx
+ rol ebx,5
+ add eax,esi
+ psrldq xmm9,4
+ and edi,ecx
+ xor ecx,edx
+ pxor xmm5,xmm1
+ add eax,ebx
+ ror ebx,7
+ pxor xmm9,xmm3
+ xor edi,edx
+ mov esi,eax
+ add ebp,DWORD PTR[20+rsp]
+ pxor xmm5,xmm9
+ xor ebx,ecx
+ rol eax,5
+ movdqa XMMWORD PTR[rsp],xmm10
+ add ebp,edi
+ and esi,ebx
+ movdqa xmm8,xmm5
+ xor ebx,ecx
+ add ebp,eax
+ ror eax,7
+ movdqa xmm9,xmm5
+ xor esi,ecx
+ pslldq xmm8,12
+ paddd xmm5,xmm5
+ mov edi,ebp
+ add edx,DWORD PTR[24+rsp]
+ psrld xmm9,31
+ xor eax,ebx
+ rol ebp,5
+ add edx,esi
+ movdqa xmm10,xmm8
+ and edi,eax
+ xor eax,ebx
+ psrld xmm8,30
+ add edx,ebp
+ ror ebp,7
+ por xmm5,xmm9
+ xor edi,ebx
+ mov esi,edx
+ add ecx,DWORD PTR[28+rsp]
+ pslld xmm10,2
+ pxor xmm5,xmm8
+ xor ebp,eax
+ movdqa xmm8,XMMWORD PTR[((-32))+r11]
+ rol edx,5
+ add ecx,edi
+ and esi,ebp
+ pxor xmm5,xmm10
+ xor ebp,eax
+ add ecx,edx
+ ror edx,7
+ pshufd xmm6,xmm2,238
+ xor esi,eax
+ movdqa xmm10,xmm5
+ paddd xmm8,xmm5
+ mov edi,ecx
+ add ebx,DWORD PTR[32+rsp]
+ punpcklqdq xmm6,xmm3
+ xor edx,ebp
+ rol ecx,5
+ add ebx,esi
+ psrldq xmm10,4
+ and edi,edx
+ xor edx,ebp
+ pxor xmm6,xmm2
+ add ebx,ecx
+ ror ecx,7
+ pxor xmm10,xmm4
+ xor edi,ebp
+ mov esi,ebx
+ add eax,DWORD PTR[36+rsp]
+ pxor xmm6,xmm10
+ xor ecx,edx
+ rol ebx,5
+ movdqa XMMWORD PTR[16+rsp],xmm8
+ add eax,edi
+ and esi,ecx
+ movdqa xmm9,xmm6
+ xor ecx,edx
+ add eax,ebx
+ ror ebx,7
+ movdqa xmm10,xmm6
+ xor esi,edx
+ pslldq xmm9,12
+ paddd xmm6,xmm6
+ mov edi,eax
+ add ebp,DWORD PTR[40+rsp]
+ psrld xmm10,31
+ xor ebx,ecx
+ rol eax,5
+ add ebp,esi
+ movdqa xmm8,xmm9
+ and edi,ebx
+ xor ebx,ecx
+ psrld xmm9,30
+ add ebp,eax
+ ror eax,7
+ por xmm6,xmm10
+ xor edi,ecx
+ mov esi,ebp
+ add edx,DWORD PTR[44+rsp]
+ pslld xmm8,2
+ pxor xmm6,xmm9
+ xor eax,ebx
+ movdqa xmm9,XMMWORD PTR[((-32))+r11]
+ rol ebp,5
+ add edx,edi
+ and esi,eax
+ pxor xmm6,xmm8
+ xor eax,ebx
+ add edx,ebp
+ ror ebp,7
+ pshufd xmm7,xmm3,238
+ xor esi,ebx
+ movdqa xmm8,xmm6
+ paddd xmm9,xmm6
+ mov edi,edx
+ add ecx,DWORD PTR[48+rsp]
+ punpcklqdq xmm7,xmm4
+ xor ebp,eax
+ rol edx,5
+ add ecx,esi
+ psrldq xmm8,4
+ and edi,ebp
+ xor ebp,eax
+ pxor xmm7,xmm3
+ add ecx,edx
+ ror edx,7
+ pxor xmm8,xmm5
+ xor edi,eax
+ mov esi,ecx
+ add ebx,DWORD PTR[52+rsp]
+ pxor xmm7,xmm8
+ xor edx,ebp
+ rol ecx,5
+ movdqa XMMWORD PTR[32+rsp],xmm9
+ add ebx,edi
+ and esi,edx
+ movdqa xmm10,xmm7
+ xor edx,ebp
+ add ebx,ecx
+ ror ecx,7
+ movdqa xmm8,xmm7
+ xor esi,ebp
+ pslldq xmm10,12
+ paddd xmm7,xmm7
+ mov edi,ebx
+ add eax,DWORD PTR[56+rsp]
+ psrld xmm8,31
+ xor ecx,edx
+ rol ebx,5
+ add eax,esi
+ movdqa xmm9,xmm10
+ and edi,ecx
+ xor ecx,edx
+ psrld xmm10,30
+ add eax,ebx
+ ror ebx,7
+ por xmm7,xmm8
+ xor edi,edx
+ mov esi,eax
+ add ebp,DWORD PTR[60+rsp]
+ pslld xmm9,2
+ pxor xmm7,xmm10
+ xor ebx,ecx
+ movdqa xmm10,XMMWORD PTR[((-32))+r11]
+ rol eax,5
+ add ebp,edi
+ and esi,ebx
+ pxor xmm7,xmm9
+ pshufd xmm9,xmm6,238
+ xor ebx,ecx
+ add ebp,eax
+ ror eax,7
+ pxor xmm0,xmm4
+ xor esi,ecx
+ mov edi,ebp
+ add edx,DWORD PTR[rsp]
+ punpcklqdq xmm9,xmm7
+ xor eax,ebx
+ rol ebp,5
+ pxor xmm0,xmm1
+ add edx,esi
+ and edi,eax
+ movdqa xmm8,xmm10
+ xor eax,ebx
+ paddd xmm10,xmm7
+ add edx,ebp
+ pxor xmm0,xmm9
+ ror ebp,7
+ xor edi,ebx
+ mov esi,edx
+ add ecx,DWORD PTR[4+rsp]
+ movdqa xmm9,xmm0
+ xor ebp,eax
+ rol edx,5
+ movdqa XMMWORD PTR[48+rsp],xmm10
+ add ecx,edi
+ and esi,ebp
+ xor ebp,eax
+ pslld xmm0,2
+ add ecx,edx
+ ror edx,7
+ psrld xmm9,30
+ xor esi,eax
+ mov edi,ecx
+ add ebx,DWORD PTR[8+rsp]
+ por xmm0,xmm9
+ xor edx,ebp
+ rol ecx,5
+ pshufd xmm10,xmm7,238
+ add ebx,esi
+ and edi,edx
+ xor edx,ebp
+ add ebx,ecx
+ add eax,DWORD PTR[12+rsp]
+ xor edi,ebp
+ mov esi,ebx
+ rol ebx,5
+ add eax,edi
+ xor esi,edx
+ ror ecx,7
+ add eax,ebx
+ pxor xmm1,xmm5
+ add ebp,DWORD PTR[16+rsp]
+ xor esi,ecx
+ punpcklqdq xmm10,xmm0
+ mov edi,eax
+ rol eax,5
+ pxor xmm1,xmm2
+ add ebp,esi
+ xor edi,ecx
+ movdqa xmm9,xmm8
+ ror ebx,7
+ paddd xmm8,xmm0
+ add ebp,eax
+ pxor xmm1,xmm10
+ add edx,DWORD PTR[20+rsp]
+ xor edi,ebx
+ mov esi,ebp
+ rol ebp,5
+ movdqa xmm10,xmm1
+ add edx,edi
+ xor esi,ebx
+ movdqa XMMWORD PTR[rsp],xmm8
+ ror eax,7
+ add edx,ebp
+ add ecx,DWORD PTR[24+rsp]
+ pslld xmm1,2
+ xor esi,eax
+ mov edi,edx
+ psrld xmm10,30
+ rol edx,5
+ add ecx,esi
+ xor edi,eax
+ ror ebp,7
+ por xmm1,xmm10
+ add ecx,edx
+ add ebx,DWORD PTR[28+rsp]
+ pshufd xmm8,xmm0,238
+ xor edi,ebp
+ mov esi,ecx
+ rol ecx,5
+ add ebx,edi
+ xor esi,ebp
+ ror edx,7
+ add ebx,ecx
+ pxor xmm2,xmm6
+ add eax,DWORD PTR[32+rsp]
+ xor esi,edx
+ punpcklqdq xmm8,xmm1
+ mov edi,ebx
+ rol ebx,5
+ pxor xmm2,xmm3
+ add eax,esi
+ xor edi,edx
+ movdqa xmm10,XMMWORD PTR[r11]
+ ror ecx,7
+ paddd xmm9,xmm1
+ add eax,ebx
+ pxor xmm2,xmm8
+ add ebp,DWORD PTR[36+rsp]
+ xor edi,ecx
+ mov esi,eax
+ rol eax,5
+ movdqa xmm8,xmm2
+ add ebp,edi
+ xor esi,ecx
+ movdqa XMMWORD PTR[16+rsp],xmm9
+ ror ebx,7
+ add ebp,eax
+ add edx,DWORD PTR[40+rsp]
+ pslld xmm2,2
+ xor esi,ebx
+ mov edi,ebp
+ psrld xmm8,30
+ rol ebp,5
+ add edx,esi
+ xor edi,ebx
+ ror eax,7
+ por xmm2,xmm8
+ add edx,ebp
+ add ecx,DWORD PTR[44+rsp]
+ pshufd xmm9,xmm1,238
+ xor edi,eax
+ mov esi,edx
+ rol edx,5
+ add ecx,edi
+ xor esi,eax
+ ror ebp,7
+ add ecx,edx
+ pxor xmm3,xmm7
+ add ebx,DWORD PTR[48+rsp]
+ xor esi,ebp
+ punpcklqdq xmm9,xmm2
+ mov edi,ecx
+ rol ecx,5
+ pxor xmm3,xmm4
+ add ebx,esi
+ xor edi,ebp
+ movdqa xmm8,xmm10
+ ror edx,7
+ paddd xmm10,xmm2
+ add ebx,ecx
+ pxor xmm3,xmm9
+ add eax,DWORD PTR[52+rsp]
+ xor edi,edx
+ mov esi,ebx
+ rol ebx,5
+ movdqa xmm9,xmm3
+ add eax,edi
+ xor esi,edx
+ movdqa XMMWORD PTR[32+rsp],xmm10
+ ror ecx,7
+ add eax,ebx
+ add ebp,DWORD PTR[56+rsp]
+ pslld xmm3,2
+ xor esi,ecx
+ mov edi,eax
+ psrld xmm9,30
+ rol eax,5
+ add ebp,esi
+ xor edi,ecx
+ ror ebx,7
+ por xmm3,xmm9
+ add ebp,eax
+ add edx,DWORD PTR[60+rsp]
+ pshufd xmm10,xmm2,238
+ xor edi,ebx
+ mov esi,ebp
+ rol ebp,5
+ add edx,edi
+ xor esi,ebx
+ ror eax,7
+ add edx,ebp
+ pxor xmm4,xmm0
+ add ecx,DWORD PTR[rsp]
+ xor esi,eax
+ punpcklqdq xmm10,xmm3
+ mov edi,edx
+ rol edx,5
+ pxor xmm4,xmm5
+ add ecx,esi
+ xor edi,eax
+ movdqa xmm9,xmm8
+ ror ebp,7
+ paddd xmm8,xmm3
+ add ecx,edx
+ pxor xmm4,xmm10
+ add ebx,DWORD PTR[4+rsp]
+ xor edi,ebp
+ mov esi,ecx
+ rol ecx,5
+ movdqa xmm10,xmm4
+ add ebx,edi
+ xor esi,ebp
+ movdqa XMMWORD PTR[48+rsp],xmm8
+ ror edx,7
+ add ebx,ecx
+ add eax,DWORD PTR[8+rsp]
+ pslld xmm4,2
+ xor esi,edx
+ mov edi,ebx
+ psrld xmm10,30
+ rol ebx,5
+ add eax,esi
+ xor edi,edx
+ ror ecx,7
+ por xmm4,xmm10
+ add eax,ebx
+ add ebp,DWORD PTR[12+rsp]
+ pshufd xmm8,xmm3,238
+ xor edi,ecx
+ mov esi,eax
+ rol eax,5
+ add ebp,edi
+ xor esi,ecx
+ ror ebx,7
+ add ebp,eax
+ pxor xmm5,xmm1
+ add edx,DWORD PTR[16+rsp]
+ xor esi,ebx
+ punpcklqdq xmm8,xmm4
+ mov edi,ebp
+ rol ebp,5
+ pxor xmm5,xmm6
+ add edx,esi
+ xor edi,ebx
+ movdqa xmm10,xmm9
+ ror eax,7
+ paddd xmm9,xmm4
+ add edx,ebp
+ pxor xmm5,xmm8
+ add ecx,DWORD PTR[20+rsp]
+ xor edi,eax
+ mov esi,edx
+ rol edx,5
+ movdqa xmm8,xmm5
+ add ecx,edi
+ xor esi,eax
+ movdqa XMMWORD PTR[rsp],xmm9
+ ror ebp,7
+ add ecx,edx
+ add ebx,DWORD PTR[24+rsp]
+ pslld xmm5,2
+ xor esi,ebp
+ mov edi,ecx
+ psrld xmm8,30
+ rol ecx,5
+ add ebx,esi
+ xor edi,ebp
+ ror edx,7
+ por xmm5,xmm8
+ add ebx,ecx
+ add eax,DWORD PTR[28+rsp]
+ pshufd xmm9,xmm4,238
+ ror ecx,7
+ mov esi,ebx
+ xor edi,edx
+ rol ebx,5
+ add eax,edi
+ xor esi,ecx
+ xor ecx,edx
+ add eax,ebx
+ pxor xmm6,xmm2
+ add ebp,DWORD PTR[32+rsp]
+ and esi,ecx
+ xor ecx,edx
+ ror ebx,7
+ punpcklqdq xmm9,xmm5
+ mov edi,eax
+ xor esi,ecx
+ pxor xmm6,xmm7
+ rol eax,5
+ add ebp,esi
+ movdqa xmm8,xmm10
+ xor edi,ebx
+ paddd xmm10,xmm5
+ xor ebx,ecx
+ pxor xmm6,xmm9
+ add ebp,eax
+ add edx,DWORD PTR[36+rsp]
+ and edi,ebx
+ xor ebx,ecx
+ ror eax,7
+ movdqa xmm9,xmm6
+ mov esi,ebp
+ xor edi,ebx
+ movdqa XMMWORD PTR[16+rsp],xmm10
+ rol ebp,5
+ add edx,edi
+ xor esi,eax
+ pslld xmm6,2
+ xor eax,ebx
+ add edx,ebp
+ psrld xmm9,30
+ add ecx,DWORD PTR[40+rsp]
+ and esi,eax
+ xor eax,ebx
+ por xmm6,xmm9
+ ror ebp,7
+ mov edi,edx
+ xor esi,eax
+ rol edx,5
+ pshufd xmm10,xmm5,238
+ add ecx,esi
+ xor edi,ebp
+ xor ebp,eax
+ add ecx,edx
+ add ebx,DWORD PTR[44+rsp]
+ and edi,ebp
+ xor ebp,eax
+ ror edx,7
+ mov esi,ecx
+ xor edi,ebp
+ rol ecx,5
+ add ebx,edi
+ xor esi,edx
+ xor edx,ebp
+ add ebx,ecx
+ pxor xmm7,xmm3
+ add eax,DWORD PTR[48+rsp]
+ and esi,edx
+ xor edx,ebp
+ ror ecx,7
+ punpcklqdq xmm10,xmm6
+ mov edi,ebx
+ xor esi,edx
+ pxor xmm7,xmm0
+ rol ebx,5
+ add eax,esi
+ movdqa xmm9,XMMWORD PTR[32+r11]
+ xor edi,ecx
+ paddd xmm8,xmm6
+ xor ecx,edx
+ pxor xmm7,xmm10
+ add eax,ebx
+ add ebp,DWORD PTR[52+rsp]
+ and edi,ecx
+ xor ecx,edx
+ ror ebx,7
+ movdqa xmm10,xmm7
+ mov esi,eax
+ xor edi,ecx
+ movdqa XMMWORD PTR[32+rsp],xmm8
+ rol eax,5
+ add ebp,edi
+ xor esi,ebx
+ pslld xmm7,2
+ xor ebx,ecx
+ add ebp,eax
+ psrld xmm10,30
+ add edx,DWORD PTR[56+rsp]
+ and esi,ebx
+ xor ebx,ecx
+ por xmm7,xmm10
+ ror eax,7
+ mov edi,ebp
+ xor esi,ebx
+ rol ebp,5
+ pshufd xmm8,xmm6,238
+ add edx,esi
+ xor edi,eax
+ xor eax,ebx
+ add edx,ebp
+ add ecx,DWORD PTR[60+rsp]
+ and edi,eax
+ xor eax,ebx
+ ror ebp,7
+ mov esi,edx
+ xor edi,eax
+ rol edx,5
+ add ecx,edi
+ xor esi,ebp
+ xor ebp,eax
+ add ecx,edx
+ pxor xmm0,xmm4
+ add ebx,DWORD PTR[rsp]
+ and esi,ebp
+ xor ebp,eax
+ ror edx,7
+ punpcklqdq xmm8,xmm7
+ mov edi,ecx
+ xor esi,ebp
+ pxor xmm0,xmm1
+ rol ecx,5
+ add ebx,esi
+ movdqa xmm10,xmm9
+ xor edi,edx
+ paddd xmm9,xmm7
+ xor edx,ebp
+ pxor xmm0,xmm8
+ add ebx,ecx
+ add eax,DWORD PTR[4+rsp]
+ and edi,edx
+ xor edx,ebp
+ ror ecx,7
+ movdqa xmm8,xmm0
+ mov esi,ebx
+ xor edi,edx
+ movdqa XMMWORD PTR[48+rsp],xmm9
+ rol ebx,5
+ add eax,edi
+ xor esi,ecx
+ pslld xmm0,2
+ xor ecx,edx
+ add eax,ebx
+ psrld xmm8,30
+ add ebp,DWORD PTR[8+rsp]
+ and esi,ecx
+ xor ecx,edx
+ por xmm0,xmm8
+ ror ebx,7
+ mov edi,eax
+ xor esi,ecx
+ rol eax,5
+ pshufd xmm9,xmm7,238
+ add ebp,esi
+ xor edi,ebx
+ xor ebx,ecx
+ add ebp,eax
+ add edx,DWORD PTR[12+rsp]
+ and edi,ebx
+ xor ebx,ecx
+ ror eax,7
+ mov esi,ebp
+ xor edi,ebx
+ rol ebp,5
+ add edx,edi
+ xor esi,eax
+ xor eax,ebx
+ add edx,ebp
+ pxor xmm1,xmm5
+ add ecx,DWORD PTR[16+rsp]
+ and esi,eax
+ xor eax,ebx
+ ror ebp,7
+ punpcklqdq xmm9,xmm0
+ mov edi,edx
+ xor esi,eax
+ pxor xmm1,xmm2
+ rol edx,5
+ add ecx,esi
+ movdqa xmm8,xmm10
+ xor edi,ebp
+ paddd xmm10,xmm0
+ xor ebp,eax
+ pxor xmm1,xmm9
+ add ecx,edx
+ add ebx,DWORD PTR[20+rsp]
+ and edi,ebp
+ xor ebp,eax
+ ror edx,7
+ movdqa xmm9,xmm1
+ mov esi,ecx
+ xor edi,ebp
+ movdqa XMMWORD PTR[rsp],xmm10
+ rol ecx,5
+ add ebx,edi
+ xor esi,edx
+ pslld xmm1,2
+ xor edx,ebp
+ add ebx,ecx
+ psrld xmm9,30
+ add eax,DWORD PTR[24+rsp]
+ and esi,edx
+ xor edx,ebp
+ por xmm1,xmm9
+ ror ecx,7
+ mov edi,ebx
+ xor esi,edx
+ rol ebx,5
+ pshufd xmm10,xmm0,238
+ add eax,esi
+ xor edi,ecx
+ xor ecx,edx
+ add eax,ebx
+ add ebp,DWORD PTR[28+rsp]
+ and edi,ecx
+ xor ecx,edx
+ ror ebx,7
+ mov esi,eax
+ xor edi,ecx
+ rol eax,5
+ add ebp,edi
+ xor esi,ebx
+ xor ebx,ecx
+ add ebp,eax
+ pxor xmm2,xmm6
+ add edx,DWORD PTR[32+rsp]
+ and esi,ebx
+ xor ebx,ecx
+ ror eax,7
+ punpcklqdq xmm10,xmm1
+ mov edi,ebp
+ xor esi,ebx
+ pxor xmm2,xmm3
+ rol ebp,5
+ add edx,esi
+ movdqa xmm9,xmm8
+ xor edi,eax
+ paddd xmm8,xmm1
+ xor eax,ebx
+ pxor xmm2,xmm10
+ add edx,ebp
+ add ecx,DWORD PTR[36+rsp]
+ and edi,eax
+ xor eax,ebx
+ ror ebp,7
+ movdqa xmm10,xmm2
+ mov esi,edx
+ xor edi,eax
+ movdqa XMMWORD PTR[16+rsp],xmm8
+ rol edx,5
+ add ecx,edi
+ xor esi,ebp
+ pslld xmm2,2
+ xor ebp,eax
+ add ecx,edx
+ psrld xmm10,30
+ add ebx,DWORD PTR[40+rsp]
+ and esi,ebp
+ xor ebp,eax
+ por xmm2,xmm10
+ ror edx,7
+ mov edi,ecx
+ xor esi,ebp
+ rol ecx,5
+ pshufd xmm8,xmm1,238
+ add ebx,esi
+ xor edi,edx
+ xor edx,ebp
+ add ebx,ecx
+ add eax,DWORD PTR[44+rsp]
+ and edi,edx
+ xor edx,ebp
+ ror ecx,7
+ mov esi,ebx
+ xor edi,edx
+ rol ebx,5
+ add eax,edi
+ xor esi,edx
+ add eax,ebx
+ pxor xmm3,xmm7
+ add ebp,DWORD PTR[48+rsp]
+ xor esi,ecx
+ punpcklqdq xmm8,xmm2
+ mov edi,eax
+ rol eax,5
+ pxor xmm3,xmm4
+ add ebp,esi
+ xor edi,ecx
+ movdqa xmm10,xmm9
+ ror ebx,7
+ paddd xmm9,xmm2
+ add ebp,eax
+ pxor xmm3,xmm8
+ add edx,DWORD PTR[52+rsp]
+ xor edi,ebx
+ mov esi,ebp
+ rol ebp,5
+ movdqa xmm8,xmm3
+ add edx,edi
+ xor esi,ebx
+ movdqa XMMWORD PTR[32+rsp],xmm9
+ ror eax,7
+ add edx,ebp
+ add ecx,DWORD PTR[56+rsp]
+ pslld xmm3,2
+ xor esi,eax
+ mov edi,edx
+ psrld xmm8,30
+ rol edx,5
+ add ecx,esi
+ xor edi,eax
+ ror ebp,7
+ por xmm3,xmm8
+ add ecx,edx
+ add ebx,DWORD PTR[60+rsp]
+ xor edi,ebp
+ mov esi,ecx
+ rol ecx,5
+ add ebx,edi
+ xor esi,ebp
+ ror edx,7
+ add ebx,ecx
+ add eax,DWORD PTR[rsp]
+ xor esi,edx
+ mov edi,ebx
+ rol ebx,5
+ paddd xmm10,xmm3
+ add eax,esi
+ xor edi,edx
+ movdqa XMMWORD PTR[48+rsp],xmm10
+ ror ecx,7
+ add eax,ebx
+ add ebp,DWORD PTR[4+rsp]
+ xor edi,ecx
+ mov esi,eax
+ rol eax,5
+ add ebp,edi
+ xor esi,ecx
+ ror ebx,7
+ add ebp,eax
+ add edx,DWORD PTR[8+rsp]
+ xor esi,ebx
+ mov edi,ebp
+ rol ebp,5
+ add edx,esi
+ xor edi,ebx
+ ror eax,7
+ add edx,ebp
+ add ecx,DWORD PTR[12+rsp]
+ xor edi,eax
+ mov esi,edx
+ rol edx,5
+ add ecx,edi
+ xor esi,eax
+ ror ebp,7
+ add ecx,edx
+ cmp r9,r10
+ je $L$done_ssse3
+ movdqa xmm6,XMMWORD PTR[64+r11]
+ movdqa xmm9,XMMWORD PTR[((-64))+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,ebp
+ mov edi,ecx
+DB 102,15,56,0,206
+ rol ecx,5
+ add ebx,esi
+ xor edi,ebp
+ ror edx,7
+ paddd xmm0,xmm9
+ add ebx,ecx
+ add eax,DWORD PTR[20+rsp]
+ xor edi,edx
+ mov esi,ebx
+ movdqa XMMWORD PTR[rsp],xmm0
+ rol ebx,5
+ add eax,edi
+ xor esi,edx
+ ror ecx,7
+ psubd xmm0,xmm9
+ add eax,ebx
+ add ebp,DWORD PTR[24+rsp]
+ xor esi,ecx
+ mov edi,eax
+ rol eax,5
+ add ebp,esi
+ xor edi,ecx
+ ror ebx,7
+ add ebp,eax
+ add edx,DWORD PTR[28+rsp]
+ xor edi,ebx
+ mov esi,ebp
+ rol ebp,5
+ add edx,edi
+ xor esi,ebx
+ ror eax,7
+ add edx,ebp
+ add ecx,DWORD PTR[32+rsp]
+ xor esi,eax
+ mov edi,edx
+DB 102,15,56,0,214
+ rol edx,5
+ add ecx,esi
+ xor edi,eax
+ ror ebp,7
+ paddd xmm1,xmm9
+ add ecx,edx
+ add ebx,DWORD PTR[36+rsp]
+ xor edi,ebp
+ mov esi,ecx
+ movdqa XMMWORD PTR[16+rsp],xmm1
+ rol ecx,5
+ add ebx,edi
+ xor esi,ebp
+ ror edx,7
+ psubd xmm1,xmm9
+ add ebx,ecx
+ add eax,DWORD PTR[40+rsp]
+ xor esi,edx
+ mov edi,ebx
+ rol ebx,5
+ add eax,esi
+ xor edi,edx
+ ror ecx,7
+ add eax,ebx
+ add ebp,DWORD PTR[44+rsp]
+ xor edi,ecx
+ mov esi,eax
+ rol eax,5
+ add ebp,edi
+ xor esi,ecx
+ ror ebx,7
+ add ebp,eax
+ add edx,DWORD PTR[48+rsp]
+ xor esi,ebx
+ mov edi,ebp
+DB 102,15,56,0,222
+ rol ebp,5
+ add edx,esi
+ xor edi,ebx
+ ror eax,7
+ paddd xmm2,xmm9
+ add edx,ebp
+ add ecx,DWORD PTR[52+rsp]
+ xor edi,eax
+ mov esi,edx
+ movdqa XMMWORD PTR[32+rsp],xmm2
+ rol edx,5
+ add ecx,edi
+ xor esi,eax
+ ror ebp,7
+ psubd xmm2,xmm9
+ add ecx,edx
+ add ebx,DWORD PTR[56+rsp]
+ xor esi,ebp
+ mov edi,ecx
+ rol ecx,5
+ add ebx,esi
+ xor edi,ebp
+ ror edx,7
+ add ebx,ecx
+ add eax,DWORD PTR[60+rsp]
+ xor edi,edx
+ mov esi,ebx
+ rol ebx,5
+ add eax,edi
+ ror ecx,7
+ add eax,ebx
+ 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 edi,ecx
+ mov DWORD PTR[12+r8],edx
+ xor edi,edx
+ mov DWORD PTR[16+r8],ebp
+ and esi,edi
+ jmp $L$oop_ssse3
+
+ALIGN 16
+$L$done_ssse3::
+ add ebx,DWORD PTR[16+rsp]
+ xor esi,ebp
+ mov edi,ecx
+ rol ecx,5
+ add ebx,esi
+ xor edi,ebp
+ ror edx,7
+ add ebx,ecx
+ add eax,DWORD PTR[20+rsp]
+ xor edi,edx
+ mov esi,ebx
+ rol ebx,5
+ add eax,edi
+ xor esi,edx
+ ror ecx,7
+ add eax,ebx
+ add ebp,DWORD PTR[24+rsp]
+ xor esi,ecx
+ mov edi,eax
+ rol eax,5
+ add ebp,esi
+ xor edi,ecx
+ ror ebx,7
+ add ebp,eax
+ add edx,DWORD PTR[28+rsp]
+ xor edi,ebx
+ mov esi,ebp
+ rol ebp,5
+ add edx,edi
+ xor esi,ebx
+ ror eax,7
+ add edx,ebp
+ add ecx,DWORD PTR[32+rsp]
+ xor esi,eax
+ mov edi,edx
+ rol edx,5
+ add ecx,esi
+ xor edi,eax
+ ror ebp,7
+ add ecx,edx
+ add ebx,DWORD PTR[36+rsp]
+ xor edi,ebp
+ mov esi,ecx
+ rol ecx,5
+ add ebx,edi
+ xor esi,ebp
+ ror edx,7
+ add ebx,ecx
+ add eax,DWORD PTR[40+rsp]
+ xor esi,edx
+ mov edi,ebx
+ rol ebx,5
+ add eax,esi
+ xor edi,edx
+ ror ecx,7
+ add eax,ebx
+ add ebp,DWORD PTR[44+rsp]
+ xor edi,ecx
+ mov esi,eax
+ rol eax,5
+ add ebp,edi
+ xor esi,ecx
+ ror ebx,7
+ add ebp,eax
+ add edx,DWORD PTR[48+rsp]
+ xor esi,ebx
+ mov edi,ebp
+ rol ebp,5
+ add edx,esi
+ xor edi,ebx
+ ror eax,7
+ add edx,ebp
+ add ecx,DWORD PTR[52+rsp]
+ xor edi,eax
+ mov esi,edx
+ rol edx,5
+ add ecx,edi
+ xor esi,eax
+ ror ebp,7
+ add ecx,edx
+ add ebx,DWORD PTR[56+rsp]
+ xor esi,ebp
+ mov edi,ecx
+ rol ecx,5
+ add ebx,esi
+ xor edi,ebp
+ ror edx,7
+ add ebx,ecx
+ add eax,DWORD PTR[60+rsp]
+ xor edi,edx
+ mov esi,ebx
+ rol ebx,5
+ add eax,edi
+ ror ecx,7
+ add eax,ebx
+ 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[((-40-96))+r14]
+ movaps xmm7,XMMWORD PTR[((-40-80))+r14]
+ movaps xmm8,XMMWORD PTR[((-40-64))+r14]
+ movaps xmm9,XMMWORD PTR[((-40-48))+r14]
+ movaps xmm10,XMMWORD PTR[((-40-32))+r14]
+ movaps xmm11,XMMWORD PTR[((-40-16))+r14]
+ lea rsi,QWORD PTR[r14]
+ mov r14,QWORD PTR[((-40))+rsi]
+ mov r13,QWORD PTR[((-32))+rsi]
+ mov r12,QWORD PTR[((-24))+rsi]
+ mov rbp,QWORD PTR[((-16))+rsi]
+ mov rbx,QWORD PTR[((-8))+rsi]
+ lea rsp,QWORD PTR[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 05a827999h,05a827999h,05a827999h,05a827999h
+ DD 06ed9eba1h,06ed9eba1h,06ed9eba1h,06ed9eba1h
+ DD 06ed9eba1h,06ed9eba1h,06ed9eba1h,06ed9eba1h
+ DD 08f1bbcdch,08f1bbcdch,08f1bbcdch,08f1bbcdch
+ DD 08f1bbcdch,08f1bbcdch,08f1bbcdch,08f1bbcdch
+ DD 0ca62c1d6h,0ca62c1d6h,0ca62c1d6h,0ca62c1d6h
+ DD 0ca62c1d6h,0ca62c1d6h,0ca62c1d6h,0ca62c1d6h
+ DD 000010203h,004050607h,008090a0bh,00c0d0e0fh
+ DD 000010203h,004050607h,008090a0bh,00c0d0e0fh
+DB 0fh,0eh,0dh,0ch,0bh,0ah,09h,08h,07h,06h,05h,04h,03h,02h,01h,00h
+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]
+
+ 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 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
+
+ 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
+
+ mov rax,QWORD PTR[232+r8]
+
+ lea rsi,QWORD PTR[((-40-96))+rax]
+ lea rdi,QWORD PTR[512+r8]
+ mov ecx,12
+ DD 0a548f3fch
+
+ 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 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
+
+$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/win-x86_64/crypto/sha/sha256-x86_64.asm b/win-x86_64/crypto/sha/sha256-x86_64.asm
new file mode 100644
index 0000000..41f2edd
--- /dev/null
+++ b/win-x86_64/crypto/sha/sha256-x86_64.asm
@@ -0,0 +1,2997 @@
+OPTION DOTNAME
+.text$ SEGMENT ALIGN(256) 'CODE'
+
+EXTERN OPENSSL_ia32cap_P:NEAR
+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
+
+
+ lea r11,QWORD PTR[OPENSSL_ia32cap_P]
+ mov r9d,DWORD PTR[r11]
+ mov r10d,DWORD PTR[4+r11]
+ mov r11d,DWORD PTR[8+r11]
+ test r10d,512
+ jnz $L$ssse3_shortcut
+ 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::
+
+ 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::
+ mov edi,ebx
+ lea rbp,QWORD PTR[K256]
+ xor edi,ecx
+ mov r12d,DWORD PTR[rsi]
+ mov r13d,r8d
+ mov r14d,eax
+ bswap r12d
+ ror r13d,14
+ mov r15d,r9d
+
+ xor r13d,r8d
+ ror r14d,9
+ xor r15d,r10d
+
+ mov DWORD PTR[rsp],r12d
+ xor r14d,eax
+ and r15d,r8d
+
+ ror r13d,5
+ add r12d,r11d
+ xor r15d,r10d
+
+ ror r14d,11
+ xor r13d,r8d
+ add r12d,r15d
+
+ mov r15d,eax
+ add r12d,DWORD PTR[rbp]
+ xor r14d,eax
+
+ xor r15d,ebx
+ ror r13d,6
+ mov r11d,ebx
+
+ and edi,r15d
+ ror r14d,2
+ add r12d,r13d
+
+ xor r11d,edi
+ add edx,r12d
+ add r11d,r12d
+
+ lea rbp,QWORD PTR[4+rbp]
+ add r11d,r14d
+ mov r12d,DWORD PTR[4+rsi]
+ mov r13d,edx
+ mov r14d,r11d
+ bswap r12d
+ ror r13d,14
+ mov edi,r8d
+
+ xor r13d,edx
+ ror r14d,9
+ xor edi,r9d
+
+ mov DWORD PTR[4+rsp],r12d
+ xor r14d,r11d
+ and edi,edx
+
+ ror r13d,5
+ add r12d,r10d
+ xor edi,r9d
+
+ ror r14d,11
+ xor r13d,edx
+ add r12d,edi
+
+ mov edi,r11d
+ add r12d,DWORD PTR[rbp]
+ xor r14d,r11d
+
+ xor edi,eax
+ ror r13d,6
+ mov r10d,eax
+
+ and r15d,edi
+ ror r14d,2
+ add r12d,r13d
+
+ xor r10d,r15d
+ add ecx,r12d
+ add r10d,r12d
+
+ lea rbp,QWORD PTR[4+rbp]
+ add r10d,r14d
+ mov r12d,DWORD PTR[8+rsi]
+ mov r13d,ecx
+ mov r14d,r10d
+ bswap r12d
+ ror r13d,14
+ mov r15d,edx
+
+ xor r13d,ecx
+ ror r14d,9
+ xor r15d,r8d
+
+ mov DWORD PTR[8+rsp],r12d
+ xor r14d,r10d
+ and r15d,ecx
+
+ ror r13d,5
+ add r12d,r9d
+ xor r15d,r8d
+
+ ror r14d,11
+ xor r13d,ecx
+ add r12d,r15d
+
+ mov r15d,r10d
+ add r12d,DWORD PTR[rbp]
+ xor r14d,r10d
+
+ xor r15d,r11d
+ ror r13d,6
+ mov r9d,r11d
+
+ and edi,r15d
+ ror r14d,2
+ add r12d,r13d
+
+ xor r9d,edi
+ add ebx,r12d
+ add r9d,r12d
+
+ lea rbp,QWORD PTR[4+rbp]
+ add r9d,r14d
+ mov r12d,DWORD PTR[12+rsi]
+ mov r13d,ebx
+ mov r14d,r9d
+ bswap r12d
+ ror r13d,14
+ mov edi,ecx
+
+ xor r13d,ebx
+ ror r14d,9
+ xor edi,edx
+
+ mov DWORD PTR[12+rsp],r12d
+ xor r14d,r9d
+ and edi,ebx
+
+ ror r13d,5
+ add r12d,r8d
+ xor edi,edx
+
+ ror r14d,11
+ xor r13d,ebx
+ add r12d,edi
+
+ mov edi,r9d
+ add r12d,DWORD PTR[rbp]
+ xor r14d,r9d
+
+ xor edi,r10d
+ ror r13d,6
+ mov r8d,r10d
+
+ and r15d,edi
+ ror r14d,2
+ add r12d,r13d
+
+ xor r8d,r15d
+ add eax,r12d
+ add r8d,r12d
+
+ lea rbp,QWORD PTR[20+rbp]
+ add r8d,r14d
+ mov r12d,DWORD PTR[16+rsi]
+ mov r13d,eax
+ mov r14d,r8d
+ bswap r12d
+ ror r13d,14
+ mov r15d,ebx
+
+ xor r13d,eax
+ ror r14d,9
+ xor r15d,ecx
+
+ mov DWORD PTR[16+rsp],r12d
+ xor r14d,r8d
+ and r15d,eax
+
+ ror r13d,5
+ add r12d,edx
+ xor r15d,ecx
+
+ ror r14d,11
+ xor r13d,eax
+ add r12d,r15d
+
+ mov r15d,r8d
+ add r12d,DWORD PTR[rbp]
+ xor r14d,r8d
+
+ xor r15d,r9d
+ ror r13d,6
+ mov edx,r9d
+
+ and edi,r15d
+ ror r14d,2
+ add r12d,r13d
+
+ xor edx,edi
+ add r11d,r12d
+ add edx,r12d
+
+ lea rbp,QWORD PTR[4+rbp]
+ add edx,r14d
+ mov r12d,DWORD PTR[20+rsi]
+ mov r13d,r11d
+ mov r14d,edx
+ bswap r12d
+ ror r13d,14
+ mov edi,eax
+
+ xor r13d,r11d
+ ror r14d,9
+ xor edi,ebx
+
+ mov DWORD PTR[20+rsp],r12d
+ xor r14d,edx
+ and edi,r11d
+
+ ror r13d,5
+ add r12d,ecx
+ xor edi,ebx
+
+ ror r14d,11
+ xor r13d,r11d
+ add r12d,edi
+
+ mov edi,edx
+ add r12d,DWORD PTR[rbp]
+ xor r14d,edx
+
+ xor edi,r8d
+ ror r13d,6
+ mov ecx,r8d
+
+ and r15d,edi
+ ror r14d,2
+ add r12d,r13d
+
+ xor ecx,r15d
+ add r10d,r12d
+ add ecx,r12d
+
+ lea rbp,QWORD PTR[4+rbp]
+ add ecx,r14d
+ mov r12d,DWORD PTR[24+rsi]
+ mov r13d,r10d
+ mov r14d,ecx
+ bswap r12d
+ ror r13d,14
+ mov r15d,r11d
+
+ xor r13d,r10d
+ ror r14d,9
+ xor r15d,eax
+
+ mov DWORD PTR[24+rsp],r12d
+ xor r14d,ecx
+ and r15d,r10d
+
+ ror r13d,5
+ add r12d,ebx
+ xor r15d,eax
+
+ ror r14d,11
+ xor r13d,r10d
+ add r12d,r15d
+
+ mov r15d,ecx
+ add r12d,DWORD PTR[rbp]
+ xor r14d,ecx
+
+ xor r15d,edx
+ ror r13d,6
+ mov ebx,edx
+
+ and edi,r15d
+ ror r14d,2
+ add r12d,r13d
+
+ xor ebx,edi
+ add r9d,r12d
+ add ebx,r12d
+
+ lea rbp,QWORD PTR[4+rbp]
+ add ebx,r14d
+ mov r12d,DWORD PTR[28+rsi]
+ mov r13d,r9d
+ mov r14d,ebx
+ bswap r12d
+ ror r13d,14
+ mov edi,r10d
+
+ xor r13d,r9d
+ ror r14d,9
+ xor edi,r11d
+
+ mov DWORD PTR[28+rsp],r12d
+ xor r14d,ebx
+ and edi,r9d
+
+ ror r13d,5
+ add r12d,eax
+ xor edi,r11d
+
+ ror r14d,11
+ xor r13d,r9d
+ add r12d,edi
+
+ mov edi,ebx
+ add r12d,DWORD PTR[rbp]
+ xor r14d,ebx
+
+ xor edi,ecx
+ ror r13d,6
+ mov eax,ecx
+
+ and r15d,edi
+ ror r14d,2
+ add r12d,r13d
+
+ xor eax,r15d
+ add r8d,r12d
+ add eax,r12d
+
+ lea rbp,QWORD PTR[20+rbp]
+ add eax,r14d
+ mov r12d,DWORD PTR[32+rsi]
+ mov r13d,r8d
+ mov r14d,eax
+ bswap r12d
+ ror r13d,14
+ mov r15d,r9d
+
+ xor r13d,r8d
+ ror r14d,9
+ xor r15d,r10d
+
+ mov DWORD PTR[32+rsp],r12d
+ xor r14d,eax
+ and r15d,r8d
+
+ ror r13d,5
+ add r12d,r11d
+ xor r15d,r10d
+
+ ror r14d,11
+ xor r13d,r8d
+ add r12d,r15d
+
+ mov r15d,eax
+ add r12d,DWORD PTR[rbp]
+ xor r14d,eax
+
+ xor r15d,ebx
+ ror r13d,6
+ mov r11d,ebx
+
+ and edi,r15d
+ ror r14d,2
+ add r12d,r13d
+
+ xor r11d,edi
+ add edx,r12d
+ add r11d,r12d
+
+ lea rbp,QWORD PTR[4+rbp]
+ add r11d,r14d
+ mov r12d,DWORD PTR[36+rsi]
+ mov r13d,edx
+ mov r14d,r11d
+ bswap r12d
+ ror r13d,14
+ mov edi,r8d
+
+ xor r13d,edx
+ ror r14d,9
+ xor edi,r9d
+
+ mov DWORD PTR[36+rsp],r12d
+ xor r14d,r11d
+ and edi,edx
+
+ ror r13d,5
+ add r12d,r10d
+ xor edi,r9d
+
+ ror r14d,11
+ xor r13d,edx
+ add r12d,edi
+
+ mov edi,r11d
+ add r12d,DWORD PTR[rbp]
+ xor r14d,r11d
+
+ xor edi,eax
+ ror r13d,6
+ mov r10d,eax
+
+ and r15d,edi
+ ror r14d,2
+ add r12d,r13d
+
+ xor r10d,r15d
+ add ecx,r12d
+ add r10d,r12d
+
+ lea rbp,QWORD PTR[4+rbp]
+ add r10d,r14d
+ mov r12d,DWORD PTR[40+rsi]
+ mov r13d,ecx
+ mov r14d,r10d
+ bswap r12d
+ ror r13d,14
+ mov r15d,edx
+
+ xor r13d,ecx
+ ror r14d,9
+ xor r15d,r8d
+
+ mov DWORD PTR[40+rsp],r12d
+ xor r14d,r10d
+ and r15d,ecx
+
+ ror r13d,5
+ add r12d,r9d
+ xor r15d,r8d
+
+ ror r14d,11
+ xor r13d,ecx
+ add r12d,r15d
+
+ mov r15d,r10d
+ add r12d,DWORD PTR[rbp]
+ xor r14d,r10d
+
+ xor r15d,r11d
+ ror r13d,6
+ mov r9d,r11d
+
+ and edi,r15d
+ ror r14d,2
+ add r12d,r13d
+
+ xor r9d,edi
+ add ebx,r12d
+ add r9d,r12d
+
+ lea rbp,QWORD PTR[4+rbp]
+ add r9d,r14d
+ mov r12d,DWORD PTR[44+rsi]
+ mov r13d,ebx
+ mov r14d,r9d
+ bswap r12d
+ ror r13d,14
+ mov edi,ecx
+
+ xor r13d,ebx
+ ror r14d,9
+ xor edi,edx
+
+ mov DWORD PTR[44+rsp],r12d
+ xor r14d,r9d
+ and edi,ebx
+
+ ror r13d,5
+ add r12d,r8d
+ xor edi,edx
+
+ ror r14d,11
+ xor r13d,ebx
+ add r12d,edi
+
+ mov edi,r9d
+ add r12d,DWORD PTR[rbp]
+ xor r14d,r9d
+
+ xor edi,r10d
+ ror r13d,6
+ mov r8d,r10d
+
+ and r15d,edi
+ ror r14d,2
+ add r12d,r13d
+
+ xor r8d,r15d
+ add eax,r12d
+ add r8d,r12d
+
+ lea rbp,QWORD PTR[20+rbp]
+ add r8d,r14d
+ mov r12d,DWORD PTR[48+rsi]
+ mov r13d,eax
+ mov r14d,r8d
+ bswap r12d
+ ror r13d,14
+ mov r15d,ebx
+
+ xor r13d,eax
+ ror r14d,9
+ xor r15d,ecx
+
+ mov DWORD PTR[48+rsp],r12d
+ xor r14d,r8d
+ and r15d,eax
+
+ ror r13d,5
+ add r12d,edx
+ xor r15d,ecx
+
+ ror r14d,11
+ xor r13d,eax
+ add r12d,r15d
+
+ mov r15d,r8d
+ add r12d,DWORD PTR[rbp]
+ xor r14d,r8d
+
+ xor r15d,r9d
+ ror r13d,6
+ mov edx,r9d
+
+ and edi,r15d
+ ror r14d,2
+ add r12d,r13d
+
+ xor edx,edi
+ add r11d,r12d
+ add edx,r12d
+
+ lea rbp,QWORD PTR[4+rbp]
+ add edx,r14d
+ mov r12d,DWORD PTR[52+rsi]
+ mov r13d,r11d
+ mov r14d,edx
+ bswap r12d
+ ror r13d,14
+ mov edi,eax
+
+ xor r13d,r11d
+ ror r14d,9
+ xor edi,ebx
+
+ mov DWORD PTR[52+rsp],r12d
+ xor r14d,edx
+ and edi,r11d
+
+ ror r13d,5
+ add r12d,ecx
+ xor edi,ebx
+
+ ror r14d,11
+ xor r13d,r11d
+ add r12d,edi
+
+ mov edi,edx
+ add r12d,DWORD PTR[rbp]
+ xor r14d,edx
+
+ xor edi,r8d
+ ror r13d,6
+ mov ecx,r8d
+
+ and r15d,edi
+ ror r14d,2
+ add r12d,r13d
+
+ xor ecx,r15d
+ add r10d,r12d
+ add ecx,r12d
+
+ lea rbp,QWORD PTR[4+rbp]
+ add ecx,r14d
+ mov r12d,DWORD PTR[56+rsi]
+ mov r13d,r10d
+ mov r14d,ecx
+ bswap r12d
+ ror r13d,14
+ mov r15d,r11d
+
+ xor r13d,r10d
+ ror r14d,9
+ xor r15d,eax
+
+ mov DWORD PTR[56+rsp],r12d
+ xor r14d,ecx
+ and r15d,r10d
+
+ ror r13d,5
+ add r12d,ebx
+ xor r15d,eax
+
+ ror r14d,11
+ xor r13d,r10d
+ add r12d,r15d
+
+ mov r15d,ecx
+ add r12d,DWORD PTR[rbp]
+ xor r14d,ecx
+
+ xor r15d,edx
+ ror r13d,6
+ mov ebx,edx
+
+ and edi,r15d
+ ror r14d,2
+ add r12d,r13d
+
+ xor ebx,edi
+ add r9d,r12d
+ add ebx,r12d
+
+ lea rbp,QWORD PTR[4+rbp]
+ add ebx,r14d
+ mov r12d,DWORD PTR[60+rsi]
+ mov r13d,r9d
+ mov r14d,ebx
+ bswap r12d
+ ror r13d,14
+ mov edi,r10d
+
+ xor r13d,r9d
+ ror r14d,9
+ xor edi,r11d
+
+ mov DWORD PTR[60+rsp],r12d
+ xor r14d,ebx
+ and edi,r9d
+
+ ror r13d,5
+ add r12d,eax
+ xor edi,r11d
+
+ ror r14d,11
+ xor r13d,r9d
+ add r12d,edi
+
+ mov edi,ebx
+ add r12d,DWORD PTR[rbp]
+ xor r14d,ebx
+
+ xor edi,ecx
+ ror r13d,6
+ mov eax,ecx
+
+ and r15d,edi
+ ror r14d,2
+ add r12d,r13d
+
+ xor eax,r15d
+ add r8d,r12d
+ add eax,r12d
+
+ lea rbp,QWORD PTR[20+rbp]
+ jmp $L$rounds_16_xx
+ALIGN 16
+$L$rounds_16_xx::
+ mov r13d,DWORD PTR[4+rsp]
+ mov r15d,DWORD PTR[56+rsp]
+
+ mov r12d,r13d
+ ror r13d,11
+ add eax,r14d
+ mov r14d,r15d
+ ror r15d,2
+
+ xor r13d,r12d
+ shr r12d,3
+ ror r13d,7
+ xor r15d,r14d
+ shr r14d,10
+
+ ror r15d,17
+ xor r12d,r13d
+ xor r15d,r14d
+ add r12d,DWORD PTR[36+rsp]
+
+ add r12d,DWORD PTR[rsp]
+ mov r13d,r8d
+ add r12d,r15d
+ mov r14d,eax
+ ror r13d,14
+ mov r15d,r9d
+
+ xor r13d,r8d
+ ror r14d,9
+ xor r15d,r10d
+
+ mov DWORD PTR[rsp],r12d
+ xor r14d,eax
+ and r15d,r8d
+
+ ror r13d,5
+ add r12d,r11d
+ xor r15d,r10d
+
+ ror r14d,11
+ xor r13d,r8d
+ add r12d,r15d
+
+ mov r15d,eax
+ add r12d,DWORD PTR[rbp]
+ xor r14d,eax
+
+ xor r15d,ebx
+ ror r13d,6
+ mov r11d,ebx
+
+ and edi,r15d
+ ror r14d,2
+ add r12d,r13d
+
+ xor r11d,edi
+ add edx,r12d
+ add r11d,r12d
+
+ lea rbp,QWORD PTR[4+rbp]
+ mov r13d,DWORD PTR[8+rsp]
+ mov edi,DWORD PTR[60+rsp]
+
+ mov r12d,r13d
+ ror r13d,11
+ add r11d,r14d
+ mov r14d,edi
+ ror edi,2
+
+ xor r13d,r12d
+ shr r12d,3
+ ror r13d,7
+ xor edi,r14d
+ shr r14d,10
+
+ ror edi,17
+ xor r12d,r13d
+ xor edi,r14d
+ add r12d,DWORD PTR[40+rsp]
+
+ add r12d,DWORD PTR[4+rsp]
+ mov r13d,edx
+ add r12d,edi
+ mov r14d,r11d
+ ror r13d,14
+ mov edi,r8d
+
+ xor r13d,edx
+ ror r14d,9
+ xor edi,r9d
+
+ mov DWORD PTR[4+rsp],r12d
+ xor r14d,r11d
+ and edi,edx
+
+ ror r13d,5
+ add r12d,r10d
+ xor edi,r9d
+
+ ror r14d,11
+ xor r13d,edx
+ add r12d,edi
+
+ mov edi,r11d
+ add r12d,DWORD PTR[rbp]
+ xor r14d,r11d
+
+ xor edi,eax
+ ror r13d,6
+ mov r10d,eax
+
+ and r15d,edi
+ ror r14d,2
+ add r12d,r13d
+
+ xor r10d,r15d
+ add ecx,r12d
+ add r10d,r12d
+
+ lea rbp,QWORD PTR[4+rbp]
+ mov r13d,DWORD PTR[12+rsp]
+ mov r15d,DWORD PTR[rsp]
+
+ mov r12d,r13d
+ ror r13d,11
+ add r10d,r14d
+ mov r14d,r15d
+ ror r15d,2
+
+ xor r13d,r12d
+ shr r12d,3
+ ror r13d,7
+ xor r15d,r14d
+ shr r14d,10
+
+ ror r15d,17
+ xor r12d,r13d
+ xor r15d,r14d
+ add r12d,DWORD PTR[44+rsp]
+
+ add r12d,DWORD PTR[8+rsp]
+ mov r13d,ecx
+ add r12d,r15d
+ mov r14d,r10d
+ ror r13d,14
+ mov r15d,edx
+
+ xor r13d,ecx
+ ror r14d,9
+ xor r15d,r8d
+
+ mov DWORD PTR[8+rsp],r12d
+ xor r14d,r10d
+ and r15d,ecx
+
+ ror r13d,5
+ add r12d,r9d
+ xor r15d,r8d
+
+ ror r14d,11
+ xor r13d,ecx
+ add r12d,r15d
+
+ mov r15d,r10d
+ add r12d,DWORD PTR[rbp]
+ xor r14d,r10d
+
+ xor r15d,r11d
+ ror r13d,6
+ mov r9d,r11d
+
+ and edi,r15d
+ ror r14d,2
+ add r12d,r13d
+
+ xor r9d,edi
+ add ebx,r12d
+ add r9d,r12d
+
+ lea rbp,QWORD PTR[4+rbp]
+ mov r13d,DWORD PTR[16+rsp]
+ mov edi,DWORD PTR[4+rsp]
+
+ mov r12d,r13d
+ ror r13d,11
+ add r9d,r14d
+ mov r14d,edi
+ ror edi,2
+
+ xor r13d,r12d
+ shr r12d,3
+ ror r13d,7
+ xor edi,r14d
+ shr r14d,10
+
+ ror edi,17
+ xor r12d,r13d
+ xor edi,r14d
+ add r12d,DWORD PTR[48+rsp]
+
+ add r12d,DWORD PTR[12+rsp]
+ mov r13d,ebx
+ add r12d,edi
+ mov r14d,r9d
+ ror r13d,14
+ mov edi,ecx
+
+ xor r13d,ebx
+ ror r14d,9
+ xor edi,edx
+
+ mov DWORD PTR[12+rsp],r12d
+ xor r14d,r9d
+ and edi,ebx
+
+ ror r13d,5
+ add r12d,r8d
+ xor edi,edx
+
+ ror r14d,11
+ xor r13d,ebx
+ add r12d,edi
+
+ mov edi,r9d
+ add r12d,DWORD PTR[rbp]
+ xor r14d,r9d
+
+ xor edi,r10d
+ ror r13d,6
+ mov r8d,r10d
+
+ and r15d,edi
+ ror r14d,2
+ add r12d,r13d
+
+ xor r8d,r15d
+ add eax,r12d
+ add r8d,r12d
+
+ lea rbp,QWORD PTR[20+rbp]
+ mov r13d,DWORD PTR[20+rsp]
+ mov r15d,DWORD PTR[8+rsp]
+
+ mov r12d,r13d
+ ror r13d,11
+ add r8d,r14d
+ mov r14d,r15d
+ ror r15d,2
+
+ xor r13d,r12d
+ shr r12d,3
+ ror r13d,7
+ xor r15d,r14d
+ shr r14d,10
+
+ ror r15d,17
+ xor r12d,r13d
+ xor r15d,r14d
+ add r12d,DWORD PTR[52+rsp]
+
+ add r12d,DWORD PTR[16+rsp]
+ mov r13d,eax
+ add r12d,r15d
+ mov r14d,r8d
+ ror r13d,14
+ mov r15d,ebx
+
+ xor r13d,eax
+ ror r14d,9
+ xor r15d,ecx
+
+ mov DWORD PTR[16+rsp],r12d
+ xor r14d,r8d
+ and r15d,eax
+
+ ror r13d,5
+ add r12d,edx
+ xor r15d,ecx
+
+ ror r14d,11
+ xor r13d,eax
+ add r12d,r15d
+
+ mov r15d,r8d
+ add r12d,DWORD PTR[rbp]
+ xor r14d,r8d
+
+ xor r15d,r9d
+ ror r13d,6
+ mov edx,r9d
+
+ and edi,r15d
+ ror r14d,2
+ add r12d,r13d
+
+ xor edx,edi
+ add r11d,r12d
+ add edx,r12d
+
+ lea rbp,QWORD PTR[4+rbp]
+ mov r13d,DWORD PTR[24+rsp]
+ mov edi,DWORD PTR[12+rsp]
+
+ mov r12d,r13d
+ ror r13d,11
+ add edx,r14d
+ mov r14d,edi
+ ror edi,2
+
+ xor r13d,r12d
+ shr r12d,3
+ ror r13d,7
+ xor edi,r14d
+ shr r14d,10
+
+ ror edi,17
+ xor r12d,r13d
+ xor edi,r14d
+ add r12d,DWORD PTR[56+rsp]
+
+ add r12d,DWORD PTR[20+rsp]
+ mov r13d,r11d
+ add r12d,edi
+ mov r14d,edx
+ ror r13d,14
+ mov edi,eax
+
+ xor r13d,r11d
+ ror r14d,9
+ xor edi,ebx
+
+ mov DWORD PTR[20+rsp],r12d
+ xor r14d,edx
+ and edi,r11d
+
+ ror r13d,5
+ add r12d,ecx
+ xor edi,ebx
+
+ ror r14d,11
+ xor r13d,r11d
+ add r12d,edi
+
+ mov edi,edx
+ add r12d,DWORD PTR[rbp]
+ xor r14d,edx
+
+ xor edi,r8d
+ ror r13d,6
+ mov ecx,r8d
+
+ and r15d,edi
+ ror r14d,2
+ add r12d,r13d
+
+ xor ecx,r15d
+ add r10d,r12d
+ add ecx,r12d
+
+ lea rbp,QWORD PTR[4+rbp]
+ mov r13d,DWORD PTR[28+rsp]
+ mov r15d,DWORD PTR[16+rsp]
+
+ mov r12d,r13d
+ ror r13d,11
+ add ecx,r14d
+ mov r14d,r15d
+ ror r15d,2
+
+ xor r13d,r12d
+ shr r12d,3
+ ror r13d,7
+ xor r15d,r14d
+ shr r14d,10
+
+ ror r15d,17
+ xor r12d,r13d
+ xor r15d,r14d
+ add r12d,DWORD PTR[60+rsp]
+
+ add r12d,DWORD PTR[24+rsp]
+ mov r13d,r10d
+ add r12d,r15d
+ mov r14d,ecx
+ ror r13d,14
+ mov r15d,r11d
+
+ xor r13d,r10d
+ ror r14d,9
+ xor r15d,eax
+
+ mov DWORD PTR[24+rsp],r12d
+ xor r14d,ecx
+ and r15d,r10d
+
+ ror r13d,5
+ add r12d,ebx
+ xor r15d,eax
+
+ ror r14d,11
+ xor r13d,r10d
+ add r12d,r15d
+
+ mov r15d,ecx
+ add r12d,DWORD PTR[rbp]
+ xor r14d,ecx
+
+ xor r15d,edx
+ ror r13d,6
+ mov ebx,edx
+
+ and edi,r15d
+ ror r14d,2
+ add r12d,r13d
+
+ xor ebx,edi
+ add r9d,r12d
+ add ebx,r12d
+
+ lea rbp,QWORD PTR[4+rbp]
+ mov r13d,DWORD PTR[32+rsp]
+ mov edi,DWORD PTR[20+rsp]
+
+ mov r12d,r13d
+ ror r13d,11
+ add ebx,r14d
+ mov r14d,edi
+ ror edi,2
+
+ xor r13d,r12d
+ shr r12d,3
+ ror r13d,7
+ xor edi,r14d
+ shr r14d,10
+
+ ror edi,17
+ xor r12d,r13d
+ xor edi,r14d
+ add r12d,DWORD PTR[rsp]
+
+ add r12d,DWORD PTR[28+rsp]
+ mov r13d,r9d
+ add r12d,edi
+ mov r14d,ebx
+ ror r13d,14
+ mov edi,r10d
+
+ xor r13d,r9d
+ ror r14d,9
+ xor edi,r11d
+
+ mov DWORD PTR[28+rsp],r12d
+ xor r14d,ebx
+ and edi,r9d
+
+ ror r13d,5
+ add r12d,eax
+ xor edi,r11d
+
+ ror r14d,11
+ xor r13d,r9d
+ add r12d,edi
+
+ mov edi,ebx
+ add r12d,DWORD PTR[rbp]
+ xor r14d,ebx
+
+ xor edi,ecx
+ ror r13d,6
+ mov eax,ecx
+
+ and r15d,edi
+ ror r14d,2
+ add r12d,r13d
+
+ xor eax,r15d
+ add r8d,r12d
+ add eax,r12d
+
+ lea rbp,QWORD PTR[20+rbp]
+ mov r13d,DWORD PTR[36+rsp]
+ mov r15d,DWORD PTR[24+rsp]
+
+ mov r12d,r13d
+ ror r13d,11
+ add eax,r14d
+ mov r14d,r15d
+ ror r15d,2
+
+ xor r13d,r12d
+ shr r12d,3
+ ror r13d,7
+ xor r15d,r14d
+ shr r14d,10
+
+ ror r15d,17
+ xor r12d,r13d
+ xor r15d,r14d
+ add r12d,DWORD PTR[4+rsp]
+
+ add r12d,DWORD PTR[32+rsp]
+ mov r13d,r8d
+ add r12d,r15d
+ mov r14d,eax
+ ror r13d,14
+ mov r15d,r9d
+
+ xor r13d,r8d
+ ror r14d,9
+ xor r15d,r10d
+
+ mov DWORD PTR[32+rsp],r12d
+ xor r14d,eax
+ and r15d,r8d
+
+ ror r13d,5
+ add r12d,r11d
+ xor r15d,r10d
+
+ ror r14d,11
+ xor r13d,r8d
+ add r12d,r15d
+
+ mov r15d,eax
+ add r12d,DWORD PTR[rbp]
+ xor r14d,eax
+
+ xor r15d,ebx
+ ror r13d,6
+ mov r11d,ebx
+
+ and edi,r15d
+ ror r14d,2
+ add r12d,r13d
+
+ xor r11d,edi
+ add edx,r12d
+ add r11d,r12d
+
+ lea rbp,QWORD PTR[4+rbp]
+ mov r13d,DWORD PTR[40+rsp]
+ mov edi,DWORD PTR[28+rsp]
+
+ mov r12d,r13d
+ ror r13d,11
+ add r11d,r14d
+ mov r14d,edi
+ ror edi,2
+
+ xor r13d,r12d
+ shr r12d,3
+ ror r13d,7
+ xor edi,r14d
+ shr r14d,10
+
+ ror edi,17
+ xor r12d,r13d
+ xor edi,r14d
+ add r12d,DWORD PTR[8+rsp]
+
+ add r12d,DWORD PTR[36+rsp]
+ mov r13d,edx
+ add r12d,edi
+ mov r14d,r11d
+ ror r13d,14
+ mov edi,r8d
+
+ xor r13d,edx
+ ror r14d,9
+ xor edi,r9d
+
+ mov DWORD PTR[36+rsp],r12d
+ xor r14d,r11d
+ and edi,edx
+
+ ror r13d,5
+ add r12d,r10d
+ xor edi,r9d
+
+ ror r14d,11
+ xor r13d,edx
+ add r12d,edi
+
+ mov edi,r11d
+ add r12d,DWORD PTR[rbp]
+ xor r14d,r11d
+
+ xor edi,eax
+ ror r13d,6
+ mov r10d,eax
+
+ and r15d,edi
+ ror r14d,2
+ add r12d,r13d
+
+ xor r10d,r15d
+ add ecx,r12d
+ add r10d,r12d
+
+ lea rbp,QWORD PTR[4+rbp]
+ mov r13d,DWORD PTR[44+rsp]
+ mov r15d,DWORD PTR[32+rsp]
+
+ mov r12d,r13d
+ ror r13d,11
+ add r10d,r14d
+ mov r14d,r15d
+ ror r15d,2
+
+ xor r13d,r12d
+ shr r12d,3
+ ror r13d,7
+ xor r15d,r14d
+ shr r14d,10
+
+ ror r15d,17
+ xor r12d,r13d
+ xor r15d,r14d
+ add r12d,DWORD PTR[12+rsp]
+
+ add r12d,DWORD PTR[40+rsp]
+ mov r13d,ecx
+ add r12d,r15d
+ mov r14d,r10d
+ ror r13d,14
+ mov r15d,edx
+
+ xor r13d,ecx
+ ror r14d,9
+ xor r15d,r8d
+
+ mov DWORD PTR[40+rsp],r12d
+ xor r14d,r10d
+ and r15d,ecx
+
+ ror r13d,5
+ add r12d,r9d
+ xor r15d,r8d
+
+ ror r14d,11
+ xor r13d,ecx
+ add r12d,r15d
+
+ mov r15d,r10d
+ add r12d,DWORD PTR[rbp]
+ xor r14d,r10d
+
+ xor r15d,r11d
+ ror r13d,6
+ mov r9d,r11d
+
+ and edi,r15d
+ ror r14d,2
+ add r12d,r13d
+
+ xor r9d,edi
+ add ebx,r12d
+ add r9d,r12d
+
+ lea rbp,QWORD PTR[4+rbp]
+ mov r13d,DWORD PTR[48+rsp]
+ mov edi,DWORD PTR[36+rsp]
+
+ mov r12d,r13d
+ ror r13d,11
+ add r9d,r14d
+ mov r14d,edi
+ ror edi,2
+
+ xor r13d,r12d
+ shr r12d,3
+ ror r13d,7
+ xor edi,r14d
+ shr r14d,10
+
+ ror edi,17
+ xor r12d,r13d
+ xor edi,r14d
+ add r12d,DWORD PTR[16+rsp]
+
+ add r12d,DWORD PTR[44+rsp]
+ mov r13d,ebx
+ add r12d,edi
+ mov r14d,r9d
+ ror r13d,14
+ mov edi,ecx
+
+ xor r13d,ebx
+ ror r14d,9
+ xor edi,edx
+
+ mov DWORD PTR[44+rsp],r12d
+ xor r14d,r9d
+ and edi,ebx
+
+ ror r13d,5
+ add r12d,r8d
+ xor edi,edx
+
+ ror r14d,11
+ xor r13d,ebx
+ add r12d,edi
+
+ mov edi,r9d
+ add r12d,DWORD PTR[rbp]
+ xor r14d,r9d
+
+ xor edi,r10d
+ ror r13d,6
+ mov r8d,r10d
+
+ and r15d,edi
+ ror r14d,2
+ add r12d,r13d
+
+ xor r8d,r15d
+ add eax,r12d
+ add r8d,r12d
+
+ lea rbp,QWORD PTR[20+rbp]
+ mov r13d,DWORD PTR[52+rsp]
+ mov r15d,DWORD PTR[40+rsp]
+
+ mov r12d,r13d
+ ror r13d,11
+ add r8d,r14d
+ mov r14d,r15d
+ ror r15d,2
+
+ xor r13d,r12d
+ shr r12d,3
+ ror r13d,7
+ xor r15d,r14d
+ shr r14d,10
+
+ ror r15d,17
+ xor r12d,r13d
+ xor r15d,r14d
+ add r12d,DWORD PTR[20+rsp]
+
+ add r12d,DWORD PTR[48+rsp]
+ mov r13d,eax
+ add r12d,r15d
+ mov r14d,r8d
+ ror r13d,14
+ mov r15d,ebx
+
+ xor r13d,eax
+ ror r14d,9
+ xor r15d,ecx
+
+ mov DWORD PTR[48+rsp],r12d
+ xor r14d,r8d
+ and r15d,eax
+
+ ror r13d,5
+ add r12d,edx
+ xor r15d,ecx
+
+ ror r14d,11
+ xor r13d,eax
+ add r12d,r15d
+
+ mov r15d,r8d
+ add r12d,DWORD PTR[rbp]
+ xor r14d,r8d
+
+ xor r15d,r9d
+ ror r13d,6
+ mov edx,r9d
+
+ and edi,r15d
+ ror r14d,2
+ add r12d,r13d
+
+ xor edx,edi
+ add r11d,r12d
+ add edx,r12d
+
+ lea rbp,QWORD PTR[4+rbp]
+ mov r13d,DWORD PTR[56+rsp]
+ mov edi,DWORD PTR[44+rsp]
+
+ mov r12d,r13d
+ ror r13d,11
+ add edx,r14d
+ mov r14d,edi
+ ror edi,2
+
+ xor r13d,r12d
+ shr r12d,3
+ ror r13d,7
+ xor edi,r14d
+ shr r14d,10
+
+ ror edi,17
+ xor r12d,r13d
+ xor edi,r14d
+ add r12d,DWORD PTR[24+rsp]
+
+ add r12d,DWORD PTR[52+rsp]
+ mov r13d,r11d
+ add r12d,edi
+ mov r14d,edx
+ ror r13d,14
+ mov edi,eax
+
+ xor r13d,r11d
+ ror r14d,9
+ xor edi,ebx
+
+ mov DWORD PTR[52+rsp],r12d
+ xor r14d,edx
+ and edi,r11d
+
+ ror r13d,5
+ add r12d,ecx
+ xor edi,ebx
+
+ ror r14d,11
+ xor r13d,r11d
+ add r12d,edi
+
+ mov edi,edx
+ add r12d,DWORD PTR[rbp]
+ xor r14d,edx
+
+ xor edi,r8d
+ ror r13d,6
+ mov ecx,r8d
+
+ and r15d,edi
+ ror r14d,2
+ add r12d,r13d
+
+ xor ecx,r15d
+ add r10d,r12d
+ add ecx,r12d
+
+ lea rbp,QWORD PTR[4+rbp]
+ mov r13d,DWORD PTR[60+rsp]
+ mov r15d,DWORD PTR[48+rsp]
+
+ mov r12d,r13d
+ ror r13d,11
+ add ecx,r14d
+ mov r14d,r15d
+ ror r15d,2
+
+ xor r13d,r12d
+ shr r12d,3
+ ror r13d,7
+ xor r15d,r14d
+ shr r14d,10
+
+ ror r15d,17
+ xor r12d,r13d
+ xor r15d,r14d
+ add r12d,DWORD PTR[28+rsp]
+
+ add r12d,DWORD PTR[56+rsp]
+ mov r13d,r10d
+ add r12d,r15d
+ mov r14d,ecx
+ ror r13d,14
+ mov r15d,r11d
+
+ xor r13d,r10d
+ ror r14d,9
+ xor r15d,eax
+
+ mov DWORD PTR[56+rsp],r12d
+ xor r14d,ecx
+ and r15d,r10d
+
+ ror r13d,5
+ add r12d,ebx
+ xor r15d,eax
+
+ ror r14d,11
+ xor r13d,r10d
+ add r12d,r15d
+
+ mov r15d,ecx
+ add r12d,DWORD PTR[rbp]
+ xor r14d,ecx
+
+ xor r15d,edx
+ ror r13d,6
+ mov ebx,edx
+
+ and edi,r15d
+ ror r14d,2
+ add r12d,r13d
+
+ xor ebx,edi
+ add r9d,r12d
+ add ebx,r12d
+
+ lea rbp,QWORD PTR[4+rbp]
+ mov r13d,DWORD PTR[rsp]
+ mov edi,DWORD PTR[52+rsp]
+
+ mov r12d,r13d
+ ror r13d,11
+ add ebx,r14d
+ mov r14d,edi
+ ror edi,2
+
+ xor r13d,r12d
+ shr r12d,3
+ ror r13d,7
+ xor edi,r14d
+ shr r14d,10
+
+ ror edi,17
+ xor r12d,r13d
+ xor edi,r14d
+ add r12d,DWORD PTR[32+rsp]
+
+ add r12d,DWORD PTR[60+rsp]
+ mov r13d,r9d
+ add r12d,edi
+ mov r14d,ebx
+ ror r13d,14
+ mov edi,r10d
+
+ xor r13d,r9d
+ ror r14d,9
+ xor edi,r11d
+
+ mov DWORD PTR[60+rsp],r12d
+ xor r14d,ebx
+ and edi,r9d
+
+ ror r13d,5
+ add r12d,eax
+ xor edi,r11d
+
+ ror r14d,11
+ xor r13d,r9d
+ add r12d,edi
+
+ mov edi,ebx
+ add r12d,DWORD PTR[rbp]
+ xor r14d,ebx
+
+ xor edi,ecx
+ ror r13d,6
+ mov eax,ecx
+
+ and r15d,edi
+ ror r14d,2
+ add r12d,r13d
+
+ xor eax,r15d
+ add r8d,r12d
+ add eax,r12d
+
+ lea rbp,QWORD PTR[20+rbp]
+ cmp BYTE PTR[3+rbp],0
+ jnz $L$rounds_16_xx
+
+ mov rdi,QWORD PTR[((64+0))+rsp]
+ add eax,r14d
+ 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 0428a2f98h,071374491h,0b5c0fbcfh,0e9b5dba5h
+ DD 03956c25bh,059f111f1h,0923f82a4h,0ab1c5ed5h
+ DD 03956c25bh,059f111f1h,0923f82a4h,0ab1c5ed5h
+ DD 0d807aa98h,012835b01h,0243185beh,0550c7dc3h
+ DD 0d807aa98h,012835b01h,0243185beh,0550c7dc3h
+ DD 072be5d74h,080deb1feh,09bdc06a7h,0c19bf174h
+ DD 072be5d74h,080deb1feh,09bdc06a7h,0c19bf174h
+ DD 0e49b69c1h,0efbe4786h,00fc19dc6h,0240ca1cch
+ DD 0e49b69c1h,0efbe4786h,00fc19dc6h,0240ca1cch
+ DD 02de92c6fh,04a7484aah,05cb0a9dch,076f988dah
+ DD 02de92c6fh,04a7484aah,05cb0a9dch,076f988dah
+ DD 0983e5152h,0a831c66dh,0b00327c8h,0bf597fc7h
+ DD 0983e5152h,0a831c66dh,0b00327c8h,0bf597fc7h
+ DD 0c6e00bf3h,0d5a79147h,006ca6351h,014292967h
+ DD 0c6e00bf3h,0d5a79147h,006ca6351h,014292967h
+ DD 027b70a85h,02e1b2138h,04d2c6dfch,053380d13h
+ DD 027b70a85h,02e1b2138h,04d2c6dfch,053380d13h
+ DD 0650a7354h,0766a0abbh,081c2c92eh,092722c85h
+ DD 0650a7354h,0766a0abbh,081c2c92eh,092722c85h
+ DD 0a2bfe8a1h,0a81a664bh,0c24b8b70h,0c76c51a3h
+ DD 0a2bfe8a1h,0a81a664bh,0c24b8b70h,0c76c51a3h
+ DD 0d192e819h,0d6990624h,0f40e3585h,0106aa070h
+ DD 0d192e819h,0d6990624h,0f40e3585h,0106aa070h
+ DD 019a4c116h,01e376c08h,02748774ch,034b0bcb5h
+ DD 019a4c116h,01e376c08h,02748774ch,034b0bcb5h
+ DD 0391c0cb3h,04ed8aa4ah,05b9cca4fh,0682e6ff3h
+ DD 0391c0cb3h,04ed8aa4ah,05b9cca4fh,0682e6ff3h
+ DD 0748f82eeh,078a5636fh,084c87814h,08cc70208h
+ DD 0748f82eeh,078a5636fh,084c87814h,08cc70208h
+ DD 090befffah,0a4506cebh,0bef9a3f7h,0c67178f2h
+ DD 090befffah,0a4506cebh,0bef9a3f7h,0c67178f2h
+
+ DD 000010203h,004050607h,008090a0bh,00c0d0e0fh
+ DD 000010203h,004050607h,008090a0bh,00c0d0e0fh
+ DD 003020100h,00b0a0908h,0ffffffffh,0ffffffffh
+ DD 003020100h,00b0a0908h,0ffffffffh,0ffffffffh
+ DD 0ffffffffh,0ffffffffh,003020100h,00b0a0908h
+ DD 0ffffffffh,0ffffffffh,003020100h,00b0a0908h
+DB 83,72,65,50,53,54,32,98,108,111,99,107,32,116,114,97
+DB 110,115,102,111,114,109,32,102,111,114,32,120,56,54,95,54
+DB 52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121
+DB 32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46
+DB 111,114,103,62,0
+
+ALIGN 64
+sha256_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_sha256_block_data_order_ssse3::
+ mov rdi,rcx
+ mov rsi,rdx
+ mov rdx,r8
+
+
+$L$ssse3_shortcut::
+ push rbx
+ push rbp
+ push r12
+ push r13
+ push r14
+ push r15
+ mov r11,rsp
+ shl rdx,4
+ sub rsp,160
+ 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
+ movaps XMMWORD PTR[(64+32)+rsp],xmm6
+ movaps XMMWORD PTR[(64+48)+rsp],xmm7
+ movaps XMMWORD PTR[(64+64)+rsp],xmm8
+ movaps XMMWORD PTR[(64+80)+rsp],xmm9
+$L$prologue_ssse3::
+
+ 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_ssse3
+ALIGN 16
+$L$loop_ssse3::
+ movdqa xmm7,XMMWORD PTR[((K256+512))]
+ movdqu xmm0,XMMWORD PTR[rsi]
+ movdqu xmm1,XMMWORD PTR[16+rsi]
+ movdqu xmm2,XMMWORD PTR[32+rsi]
+DB 102,15,56,0,199
+ movdqu xmm3,XMMWORD PTR[48+rsi]
+ lea rbp,QWORD PTR[K256]
+DB 102,15,56,0,207
+ movdqa xmm4,XMMWORD PTR[rbp]
+ movdqa xmm5,XMMWORD PTR[32+rbp]
+DB 102,15,56,0,215
+ paddd xmm4,xmm0
+ movdqa xmm6,XMMWORD PTR[64+rbp]
+DB 102,15,56,0,223
+ movdqa xmm7,XMMWORD PTR[96+rbp]
+ paddd xmm5,xmm1
+ paddd xmm6,xmm2
+ paddd xmm7,xmm3
+ movdqa XMMWORD PTR[rsp],xmm4
+ mov r14d,eax
+ movdqa XMMWORD PTR[16+rsp],xmm5
+ mov edi,ebx
+ movdqa XMMWORD PTR[32+rsp],xmm6
+ xor edi,ecx
+ movdqa XMMWORD PTR[48+rsp],xmm7
+ mov r13d,r8d
+ jmp $L$ssse3_00_47
+
+ALIGN 16
+$L$ssse3_00_47::
+ sub rbp,-128
+ ror r13d,14
+ movdqa xmm4,xmm1
+ mov eax,r14d
+ mov r12d,r9d
+ movdqa xmm7,xmm3
+ ror r14d,9
+ xor r13d,r8d
+ xor r12d,r10d
+ ror r13d,5
+ xor r14d,eax
+DB 102,15,58,15,224,4
+ and r12d,r8d
+ xor r13d,r8d
+DB 102,15,58,15,250,4
+ add r11d,DWORD PTR[rsp]
+ mov r15d,eax
+ xor r12d,r10d
+ ror r14d,11
+ movdqa xmm5,xmm4
+ xor r15d,ebx
+ add r11d,r12d
+ movdqa xmm6,xmm4
+ ror r13d,6
+ and edi,r15d
+ psrld xmm4,3
+ xor r14d,eax
+ add r11d,r13d
+ xor edi,ebx
+ paddd xmm0,xmm7
+ ror r14d,2
+ add edx,r11d
+ psrld xmm6,7
+ add r11d,edi
+ mov r13d,edx
+ pshufd xmm7,xmm3,250
+ add r14d,r11d
+ ror r13d,14
+ pslld xmm5,14
+ mov r11d,r14d
+ mov r12d,r8d
+ pxor xmm4,xmm6
+ ror r14d,9
+ xor r13d,edx
+ xor r12d,r9d
+ ror r13d,5
+ psrld xmm6,11
+ xor r14d,r11d
+ pxor xmm4,xmm5
+ and r12d,edx
+ xor r13d,edx
+ pslld xmm5,11
+ add r10d,DWORD PTR[4+rsp]
+ mov edi,r11d
+ pxor xmm4,xmm6
+ xor r12d,r9d
+ ror r14d,11
+ movdqa xmm6,xmm7
+ xor edi,eax
+ add r10d,r12d
+ pxor xmm4,xmm5
+ ror r13d,6
+ and r15d,edi
+ xor r14d,r11d
+ psrld xmm7,10
+ add r10d,r13d
+ xor r15d,eax
+ paddd xmm0,xmm4
+ ror r14d,2
+ add ecx,r10d
+ psrlq xmm6,17
+ add r10d,r15d
+ mov r13d,ecx
+ add r14d,r10d
+ pxor xmm7,xmm6
+ ror r13d,14
+ mov r10d,r14d
+ mov r12d,edx
+ ror r14d,9
+ psrlq xmm6,2
+ xor r13d,ecx
+ xor r12d,r8d
+ pxor xmm7,xmm6
+ ror r13d,5
+ xor r14d,r10d
+ and r12d,ecx
+ pshufd xmm7,xmm7,128
+ xor r13d,ecx
+ add r9d,DWORD PTR[8+rsp]
+ mov r15d,r10d
+ psrldq xmm7,8
+ xor r12d,r8d
+ ror r14d,11
+ xor r15d,r11d
+ add r9d,r12d
+ ror r13d,6
+ paddd xmm0,xmm7
+ and edi,r15d
+ xor r14d,r10d
+ add r9d,r13d
+ pshufd xmm7,xmm0,80
+ xor edi,r11d
+ ror r14d,2
+ add ebx,r9d
+ movdqa xmm6,xmm7
+ add r9d,edi
+ mov r13d,ebx
+ psrld xmm7,10
+ add r14d,r9d
+ ror r13d,14
+ psrlq xmm6,17
+ mov r9d,r14d
+ mov r12d,ecx
+ pxor xmm7,xmm6
+ ror r14d,9
+ xor r13d,ebx
+ xor r12d,edx
+ ror r13d,5
+ xor r14d,r9d
+ psrlq xmm6,2
+ and r12d,ebx
+ xor r13d,ebx
+ add r8d,DWORD PTR[12+rsp]
+ pxor xmm7,xmm6
+ mov edi,r9d
+ xor r12d,edx
+ ror r14d,11
+ pshufd xmm7,xmm7,8
+ xor edi,r10d
+ add r8d,r12d
+ movdqa xmm6,XMMWORD PTR[rbp]
+ ror r13d,6
+ and r15d,edi
+ pslldq xmm7,8
+ xor r14d,r9d
+ add r8d,r13d
+ xor r15d,r10d
+ paddd xmm0,xmm7
+ ror r14d,2
+ add eax,r8d
+ add r8d,r15d
+ paddd xmm6,xmm0
+ mov r13d,eax
+ add r14d,r8d
+ movdqa XMMWORD PTR[rsp],xmm6
+ ror r13d,14
+ movdqa xmm4,xmm2
+ mov r8d,r14d
+ mov r12d,ebx
+ movdqa xmm7,xmm0
+ ror r14d,9
+ xor r13d,eax
+ xor r12d,ecx
+ ror r13d,5
+ xor r14d,r8d
+DB 102,15,58,15,225,4
+ and r12d,eax
+ xor r13d,eax
+DB 102,15,58,15,251,4
+ add edx,DWORD PTR[16+rsp]
+ mov r15d,r8d
+ xor r12d,ecx
+ ror r14d,11
+ movdqa xmm5,xmm4
+ xor r15d,r9d
+ add edx,r12d
+ movdqa xmm6,xmm4
+ ror r13d,6
+ and edi,r15d
+ psrld xmm4,3
+ xor r14d,r8d
+ add edx,r13d
+ xor edi,r9d
+ paddd xmm1,xmm7
+ ror r14d,2
+ add r11d,edx
+ psrld xmm6,7
+ add edx,edi
+ mov r13d,r11d
+ pshufd xmm7,xmm0,250
+ add r14d,edx
+ ror r13d,14
+ pslld xmm5,14
+ mov edx,r14d
+ mov r12d,eax
+ pxor xmm4,xmm6
+ ror r14d,9
+ xor r13d,r11d
+ xor r12d,ebx
+ ror r13d,5
+ psrld xmm6,11
+ xor r14d,edx
+ pxor xmm4,xmm5
+ and r12d,r11d
+ xor r13d,r11d
+ pslld xmm5,11
+ add ecx,DWORD PTR[20+rsp]
+ mov edi,edx
+ pxor xmm4,xmm6
+ xor r12d,ebx
+ ror r14d,11
+ movdqa xmm6,xmm7
+ xor edi,r8d
+ add ecx,r12d
+ pxor xmm4,xmm5
+ ror r13d,6
+ and r15d,edi
+ xor r14d,edx
+ psrld xmm7,10
+ add ecx,r13d
+ xor r15d,r8d
+ paddd xmm1,xmm4
+ ror r14d,2
+ add r10d,ecx
+ psrlq xmm6,17
+ add ecx,r15d
+ mov r13d,r10d
+ add r14d,ecx
+ pxor xmm7,xmm6
+ ror r13d,14
+ mov ecx,r14d
+ mov r12d,r11d
+ ror r14d,9
+ psrlq xmm6,2
+ xor r13d,r10d
+ xor r12d,eax
+ pxor xmm7,xmm6
+ ror r13d,5
+ xor r14d,ecx
+ and r12d,r10d
+ pshufd xmm7,xmm7,128
+ xor r13d,r10d
+ add ebx,DWORD PTR[24+rsp]
+ mov r15d,ecx
+ psrldq xmm7,8
+ xor r12d,eax
+ ror r14d,11
+ xor r15d,edx
+ add ebx,r12d
+ ror r13d,6
+ paddd xmm1,xmm7
+ and edi,r15d
+ xor r14d,ecx
+ add ebx,r13d
+ pshufd xmm7,xmm1,80
+ xor edi,edx
+ ror r14d,2
+ add r9d,ebx
+ movdqa xmm6,xmm7
+ add ebx,edi
+ mov r13d,r9d
+ psrld xmm7,10
+ add r14d,ebx
+ ror r13d,14
+ psrlq xmm6,17
+ mov ebx,r14d
+ mov r12d,r10d
+ pxor xmm7,xmm6
+ ror r14d,9
+ xor r13d,r9d
+ xor r12d,r11d
+ ror r13d,5
+ xor r14d,ebx
+ psrlq xmm6,2
+ and r12d,r9d
+ xor r13d,r9d
+ add eax,DWORD PTR[28+rsp]
+ pxor xmm7,xmm6
+ mov edi,ebx
+ xor r12d,r11d
+ ror r14d,11
+ pshufd xmm7,xmm7,8
+ xor edi,ecx
+ add eax,r12d
+ movdqa xmm6,XMMWORD PTR[32+rbp]
+ ror r13d,6
+ and r15d,edi
+ pslldq xmm7,8
+ xor r14d,ebx
+ add eax,r13d
+ xor r15d,ecx
+ paddd xmm1,xmm7
+ ror r14d,2
+ add r8d,eax
+ add eax,r15d
+ paddd xmm6,xmm1
+ mov r13d,r8d
+ add r14d,eax
+ movdqa XMMWORD PTR[16+rsp],xmm6
+ ror r13d,14
+ movdqa xmm4,xmm3
+ mov eax,r14d
+ mov r12d,r9d
+ movdqa xmm7,xmm1
+ ror r14d,9
+ xor r13d,r8d
+ xor r12d,r10d
+ ror r13d,5
+ xor r14d,eax
+DB 102,15,58,15,226,4
+ and r12d,r8d
+ xor r13d,r8d
+DB 102,15,58,15,248,4
+ add r11d,DWORD PTR[32+rsp]
+ mov r15d,eax
+ xor r12d,r10d
+ ror r14d,11
+ movdqa xmm5,xmm4
+ xor r15d,ebx
+ add r11d,r12d
+ movdqa xmm6,xmm4
+ ror r13d,6
+ and edi,r15d
+ psrld xmm4,3
+ xor r14d,eax
+ add r11d,r13d
+ xor edi,ebx
+ paddd xmm2,xmm7
+ ror r14d,2
+ add edx,r11d
+ psrld xmm6,7
+ add r11d,edi
+ mov r13d,edx
+ pshufd xmm7,xmm1,250
+ add r14d,r11d
+ ror r13d,14
+ pslld xmm5,14
+ mov r11d,r14d
+ mov r12d,r8d
+ pxor xmm4,xmm6
+ ror r14d,9
+ xor r13d,edx
+ xor r12d,r9d
+ ror r13d,5
+ psrld xmm6,11
+ xor r14d,r11d
+ pxor xmm4,xmm5
+ and r12d,edx
+ xor r13d,edx
+ pslld xmm5,11
+ add r10d,DWORD PTR[36+rsp]
+ mov edi,r11d
+ pxor xmm4,xmm6
+ xor r12d,r9d
+ ror r14d,11
+ movdqa xmm6,xmm7
+ xor edi,eax
+ add r10d,r12d
+ pxor xmm4,xmm5
+ ror r13d,6
+ and r15d,edi
+ xor r14d,r11d
+ psrld xmm7,10
+ add r10d,r13d
+ xor r15d,eax
+ paddd xmm2,xmm4
+ ror r14d,2
+ add ecx,r10d
+ psrlq xmm6,17
+ add r10d,r15d
+ mov r13d,ecx
+ add r14d,r10d
+ pxor xmm7,xmm6
+ ror r13d,14
+ mov r10d,r14d
+ mov r12d,edx
+ ror r14d,9
+ psrlq xmm6,2
+ xor r13d,ecx
+ xor r12d,r8d
+ pxor xmm7,xmm6
+ ror r13d,5
+ xor r14d,r10d
+ and r12d,ecx
+ pshufd xmm7,xmm7,128
+ xor r13d,ecx
+ add r9d,DWORD PTR[40+rsp]
+ mov r15d,r10d
+ psrldq xmm7,8
+ xor r12d,r8d
+ ror r14d,11
+ xor r15d,r11d
+ add r9d,r12d
+ ror r13d,6
+ paddd xmm2,xmm7
+ and edi,r15d
+ xor r14d,r10d
+ add r9d,r13d
+ pshufd xmm7,xmm2,80
+ xor edi,r11d
+ ror r14d,2
+ add ebx,r9d
+ movdqa xmm6,xmm7
+ add r9d,edi
+ mov r13d,ebx
+ psrld xmm7,10
+ add r14d,r9d
+ ror r13d,14
+ psrlq xmm6,17
+ mov r9d,r14d
+ mov r12d,ecx
+ pxor xmm7,xmm6
+ ror r14d,9
+ xor r13d,ebx
+ xor r12d,edx
+ ror r13d,5
+ xor r14d,r9d
+ psrlq xmm6,2
+ and r12d,ebx
+ xor r13d,ebx
+ add r8d,DWORD PTR[44+rsp]
+ pxor xmm7,xmm6
+ mov edi,r9d
+ xor r12d,edx
+ ror r14d,11
+ pshufd xmm7,xmm7,8
+ xor edi,r10d
+ add r8d,r12d
+ movdqa xmm6,XMMWORD PTR[64+rbp]
+ ror r13d,6
+ and r15d,edi
+ pslldq xmm7,8
+ xor r14d,r9d
+ add r8d,r13d
+ xor r15d,r10d
+ paddd xmm2,xmm7
+ ror r14d,2
+ add eax,r8d
+ add r8d,r15d
+ paddd xmm6,xmm2
+ mov r13d,eax
+ add r14d,r8d
+ movdqa XMMWORD PTR[32+rsp],xmm6
+ ror r13d,14
+ movdqa xmm4,xmm0
+ mov r8d,r14d
+ mov r12d,ebx
+ movdqa xmm7,xmm2
+ ror r14d,9
+ xor r13d,eax
+ xor r12d,ecx
+ ror r13d,5
+ xor r14d,r8d
+DB 102,15,58,15,227,4
+ and r12d,eax
+ xor r13d,eax
+DB 102,15,58,15,249,4
+ add edx,DWORD PTR[48+rsp]
+ mov r15d,r8d
+ xor r12d,ecx
+ ror r14d,11
+ movdqa xmm5,xmm4
+ xor r15d,r9d
+ add edx,r12d
+ movdqa xmm6,xmm4
+ ror r13d,6
+ and edi,r15d
+ psrld xmm4,3
+ xor r14d,r8d
+ add edx,r13d
+ xor edi,r9d
+ paddd xmm3,xmm7
+ ror r14d,2
+ add r11d,edx
+ psrld xmm6,7
+ add edx,edi
+ mov r13d,r11d
+ pshufd xmm7,xmm2,250
+ add r14d,edx
+ ror r13d,14
+ pslld xmm5,14
+ mov edx,r14d
+ mov r12d,eax
+ pxor xmm4,xmm6
+ ror r14d,9
+ xor r13d,r11d
+ xor r12d,ebx
+ ror r13d,5
+ psrld xmm6,11
+ xor r14d,edx
+ pxor xmm4,xmm5
+ and r12d,r11d
+ xor r13d,r11d
+ pslld xmm5,11
+ add ecx,DWORD PTR[52+rsp]
+ mov edi,edx
+ pxor xmm4,xmm6
+ xor r12d,ebx
+ ror r14d,11
+ movdqa xmm6,xmm7
+ xor edi,r8d
+ add ecx,r12d
+ pxor xmm4,xmm5
+ ror r13d,6
+ and r15d,edi
+ xor r14d,edx
+ psrld xmm7,10
+ add ecx,r13d
+ xor r15d,r8d
+ paddd xmm3,xmm4
+ ror r14d,2
+ add r10d,ecx
+ psrlq xmm6,17
+ add ecx,r15d
+ mov r13d,r10d
+ add r14d,ecx
+ pxor xmm7,xmm6
+ ror r13d,14
+ mov ecx,r14d
+ mov r12d,r11d
+ ror r14d,9
+ psrlq xmm6,2
+ xor r13d,r10d
+ xor r12d,eax
+ pxor xmm7,xmm6
+ ror r13d,5
+ xor r14d,ecx
+ and r12d,r10d
+ pshufd xmm7,xmm7,128
+ xor r13d,r10d
+ add ebx,DWORD PTR[56+rsp]
+ mov r15d,ecx
+ psrldq xmm7,8
+ xor r12d,eax
+ ror r14d,11
+ xor r15d,edx
+ add ebx,r12d
+ ror r13d,6
+ paddd xmm3,xmm7
+ and edi,r15d
+ xor r14d,ecx
+ add ebx,r13d
+ pshufd xmm7,xmm3,80
+ xor edi,edx
+ ror r14d,2
+ add r9d,ebx
+ movdqa xmm6,xmm7
+ add ebx,edi
+ mov r13d,r9d
+ psrld xmm7,10
+ add r14d,ebx
+ ror r13d,14
+ psrlq xmm6,17
+ mov ebx,r14d
+ mov r12d,r10d
+ pxor xmm7,xmm6
+ ror r14d,9
+ xor r13d,r9d
+ xor r12d,r11d
+ ror r13d,5
+ xor r14d,ebx
+ psrlq xmm6,2
+ and r12d,r9d
+ xor r13d,r9d
+ add eax,DWORD PTR[60+rsp]
+ pxor xmm7,xmm6
+ mov edi,ebx
+ xor r12d,r11d
+ ror r14d,11
+ pshufd xmm7,xmm7,8
+ xor edi,ecx
+ add eax,r12d
+ movdqa xmm6,XMMWORD PTR[96+rbp]
+ ror r13d,6
+ and r15d,edi
+ pslldq xmm7,8
+ xor r14d,ebx
+ add eax,r13d
+ xor r15d,ecx
+ paddd xmm3,xmm7
+ ror r14d,2
+ add r8d,eax
+ add eax,r15d
+ paddd xmm6,xmm3
+ mov r13d,r8d
+ add r14d,eax
+ movdqa XMMWORD PTR[48+rsp],xmm6
+ cmp BYTE PTR[131+rbp],0
+ jne $L$ssse3_00_47
+ ror r13d,14
+ mov eax,r14d
+ mov r12d,r9d
+ ror r14d,9
+ xor r13d,r8d
+ xor r12d,r10d
+ ror r13d,5
+ xor r14d,eax
+ and r12d,r8d
+ xor r13d,r8d
+ add r11d,DWORD PTR[rsp]
+ mov r15d,eax
+ xor r12d,r10d
+ ror r14d,11
+ xor r15d,ebx
+ add r11d,r12d
+ ror r13d,6
+ and edi,r15d
+ xor r14d,eax
+ add r11d,r13d
+ xor edi,ebx
+ ror r14d,2
+ add edx,r11d
+ add r11d,edi
+ mov r13d,edx
+ add r14d,r11d
+ ror r13d,14
+ mov r11d,r14d
+ mov r12d,r8d
+ ror r14d,9
+ xor r13d,edx
+ xor r12d,r9d
+ ror r13d,5
+ xor r14d,r11d
+ and r12d,edx
+ xor r13d,edx
+ add r10d,DWORD PTR[4+rsp]
+ mov edi,r11d
+ xor r12d,r9d
+ ror r14d,11
+ xor edi,eax
+ add r10d,r12d
+ ror r13d,6
+ and r15d,edi
+ xor r14d,r11d
+ add r10d,r13d
+ xor r15d,eax
+ ror r14d,2
+ add ecx,r10d
+ add r10d,r15d
+ mov r13d,ecx
+ add r14d,r10d
+ ror r13d,14
+ mov r10d,r14d
+ mov r12d,edx
+ ror r14d,9
+ xor r13d,ecx
+ xor r12d,r8d
+ ror r13d,5
+ xor r14d,r10d
+ and r12d,ecx
+ xor r13d,ecx
+ add r9d,DWORD PTR[8+rsp]
+ mov r15d,r10d
+ xor r12d,r8d
+ ror r14d,11
+ xor r15d,r11d
+ add r9d,r12d
+ ror r13d,6
+ and edi,r15d
+ xor r14d,r10d
+ add r9d,r13d
+ xor edi,r11d
+ ror r14d,2
+ add ebx,r9d
+ add r9d,edi
+ mov r13d,ebx
+ add r14d,r9d
+ ror r13d,14
+ mov r9d,r14d
+ mov r12d,ecx
+ ror r14d,9
+ xor r13d,ebx
+ xor r12d,edx
+ ror r13d,5
+ xor r14d,r9d
+ and r12d,ebx
+ xor r13d,ebx
+ add r8d,DWORD PTR[12+rsp]
+ mov edi,r9d
+ xor r12d,edx
+ ror r14d,11
+ xor edi,r10d
+ add r8d,r12d
+ ror r13d,6
+ and r15d,edi
+ xor r14d,r9d
+ add r8d,r13d
+ xor r15d,r10d
+ ror r14d,2
+ add eax,r8d
+ add r8d,r15d
+ mov r13d,eax
+ add r14d,r8d
+ ror r13d,14
+ mov r8d,r14d
+ mov r12d,ebx
+ ror r14d,9
+ xor r13d,eax
+ xor r12d,ecx
+ ror r13d,5
+ xor r14d,r8d
+ and r12d,eax
+ xor r13d,eax
+ add edx,DWORD PTR[16+rsp]
+ mov r15d,r8d
+ xor r12d,ecx
+ ror r14d,11
+ xor r15d,r9d
+ add edx,r12d
+ ror r13d,6
+ and edi,r15d
+ xor r14d,r8d
+ add edx,r13d
+ xor edi,r9d
+ ror r14d,2
+ add r11d,edx
+ add edx,edi
+ mov r13d,r11d
+ add r14d,edx
+ ror r13d,14
+ mov edx,r14d
+ mov r12d,eax
+ ror r14d,9
+ xor r13d,r11d
+ xor r12d,ebx
+ ror r13d,5
+ xor r14d,edx
+ and r12d,r11d
+ xor r13d,r11d
+ add ecx,DWORD PTR[20+rsp]
+ mov edi,edx
+ xor r12d,ebx
+ ror r14d,11
+ xor edi,r8d
+ add ecx,r12d
+ ror r13d,6
+ and r15d,edi
+ xor r14d,edx
+ add ecx,r13d
+ xor r15d,r8d
+ ror r14d,2
+ add r10d,ecx
+ add ecx,r15d
+ mov r13d,r10d
+ add r14d,ecx
+ ror r13d,14
+ mov ecx,r14d
+ mov r12d,r11d
+ ror r14d,9
+ xor r13d,r10d
+ xor r12d,eax
+ ror r13d,5
+ xor r14d,ecx
+ and r12d,r10d
+ xor r13d,r10d
+ add ebx,DWORD PTR[24+rsp]
+ mov r15d,ecx
+ xor r12d,eax
+ ror r14d,11
+ xor r15d,edx
+ add ebx,r12d
+ ror r13d,6
+ and edi,r15d
+ xor r14d,ecx
+ add ebx,r13d
+ xor edi,edx
+ ror r14d,2
+ add r9d,ebx
+ add ebx,edi
+ mov r13d,r9d
+ add r14d,ebx
+ ror r13d,14
+ mov ebx,r14d
+ mov r12d,r10d
+ ror r14d,9
+ xor r13d,r9d
+ xor r12d,r11d
+ ror r13d,5
+ xor r14d,ebx
+ and r12d,r9d
+ xor r13d,r9d
+ add eax,DWORD PTR[28+rsp]
+ mov edi,ebx
+ xor r12d,r11d
+ ror r14d,11
+ xor edi,ecx
+ add eax,r12d
+ ror r13d,6
+ and r15d,edi
+ xor r14d,ebx
+ add eax,r13d
+ xor r15d,ecx
+ ror r14d,2
+ add r8d,eax
+ add eax,r15d
+ mov r13d,r8d
+ add r14d,eax
+ ror r13d,14
+ mov eax,r14d
+ mov r12d,r9d
+ ror r14d,9
+ xor r13d,r8d
+ xor r12d,r10d
+ ror r13d,5
+ xor r14d,eax
+ and r12d,r8d
+ xor r13d,r8d
+ add r11d,DWORD PTR[32+rsp]
+ mov r15d,eax
+ xor r12d,r10d
+ ror r14d,11
+ xor r15d,ebx
+ add r11d,r12d
+ ror r13d,6
+ and edi,r15d
+ xor r14d,eax
+ add r11d,r13d
+ xor edi,ebx
+ ror r14d,2
+ add edx,r11d
+ add r11d,edi
+ mov r13d,edx
+ add r14d,r11d
+ ror r13d,14
+ mov r11d,r14d
+ mov r12d,r8d
+ ror r14d,9
+ xor r13d,edx
+ xor r12d,r9d
+ ror r13d,5
+ xor r14d,r11d
+ and r12d,edx
+ xor r13d,edx
+ add r10d,DWORD PTR[36+rsp]
+ mov edi,r11d
+ xor r12d,r9d
+ ror r14d,11
+ xor edi,eax
+ add r10d,r12d
+ ror r13d,6
+ and r15d,edi
+ xor r14d,r11d
+ add r10d,r13d
+ xor r15d,eax
+ ror r14d,2
+ add ecx,r10d
+ add r10d,r15d
+ mov r13d,ecx
+ add r14d,r10d
+ ror r13d,14
+ mov r10d,r14d
+ mov r12d,edx
+ ror r14d,9
+ xor r13d,ecx
+ xor r12d,r8d
+ ror r13d,5
+ xor r14d,r10d
+ and r12d,ecx
+ xor r13d,ecx
+ add r9d,DWORD PTR[40+rsp]
+ mov r15d,r10d
+ xor r12d,r8d
+ ror r14d,11
+ xor r15d,r11d
+ add r9d,r12d
+ ror r13d,6
+ and edi,r15d
+ xor r14d,r10d
+ add r9d,r13d
+ xor edi,r11d
+ ror r14d,2
+ add ebx,r9d
+ add r9d,edi
+ mov r13d,ebx
+ add r14d,r9d
+ ror r13d,14
+ mov r9d,r14d
+ mov r12d,ecx
+ ror r14d,9
+ xor r13d,ebx
+ xor r12d,edx
+ ror r13d,5
+ xor r14d,r9d
+ and r12d,ebx
+ xor r13d,ebx
+ add r8d,DWORD PTR[44+rsp]
+ mov edi,r9d
+ xor r12d,edx
+ ror r14d,11
+ xor edi,r10d
+ add r8d,r12d
+ ror r13d,6
+ and r15d,edi
+ xor r14d,r9d
+ add r8d,r13d
+ xor r15d,r10d
+ ror r14d,2
+ add eax,r8d
+ add r8d,r15d
+ mov r13d,eax
+ add r14d,r8d
+ ror r13d,14
+ mov r8d,r14d
+ mov r12d,ebx
+ ror r14d,9
+ xor r13d,eax
+ xor r12d,ecx
+ ror r13d,5
+ xor r14d,r8d
+ and r12d,eax
+ xor r13d,eax
+ add edx,DWORD PTR[48+rsp]
+ mov r15d,r8d
+ xor r12d,ecx
+ ror r14d,11
+ xor r15d,r9d
+ add edx,r12d
+ ror r13d,6
+ and edi,r15d
+ xor r14d,r8d
+ add edx,r13d
+ xor edi,r9d
+ ror r14d,2
+ add r11d,edx
+ add edx,edi
+ mov r13d,r11d
+ add r14d,edx
+ ror r13d,14
+ mov edx,r14d
+ mov r12d,eax
+ ror r14d,9
+ xor r13d,r11d
+ xor r12d,ebx
+ ror r13d,5
+ xor r14d,edx
+ and r12d,r11d
+ xor r13d,r11d
+ add ecx,DWORD PTR[52+rsp]
+ mov edi,edx
+ xor r12d,ebx
+ ror r14d,11
+ xor edi,r8d
+ add ecx,r12d
+ ror r13d,6
+ and r15d,edi
+ xor r14d,edx
+ add ecx,r13d
+ xor r15d,r8d
+ ror r14d,2
+ add r10d,ecx
+ add ecx,r15d
+ mov r13d,r10d
+ add r14d,ecx
+ ror r13d,14
+ mov ecx,r14d
+ mov r12d,r11d
+ ror r14d,9
+ xor r13d,r10d
+ xor r12d,eax
+ ror r13d,5
+ xor r14d,ecx
+ and r12d,r10d
+ xor r13d,r10d
+ add ebx,DWORD PTR[56+rsp]
+ mov r15d,ecx
+ xor r12d,eax
+ ror r14d,11
+ xor r15d,edx
+ add ebx,r12d
+ ror r13d,6
+ and edi,r15d
+ xor r14d,ecx
+ add ebx,r13d
+ xor edi,edx
+ ror r14d,2
+ add r9d,ebx
+ add ebx,edi
+ mov r13d,r9d
+ add r14d,ebx
+ ror r13d,14
+ mov ebx,r14d
+ mov r12d,r10d
+ ror r14d,9
+ xor r13d,r9d
+ xor r12d,r11d
+ ror r13d,5
+ xor r14d,ebx
+ and r12d,r9d
+ xor r13d,r9d
+ add eax,DWORD PTR[60+rsp]
+ mov edi,ebx
+ xor r12d,r11d
+ ror r14d,11
+ xor edi,ecx
+ add eax,r12d
+ ror r13d,6
+ and r15d,edi
+ xor r14d,ebx
+ add eax,r13d
+ xor r15d,ecx
+ ror r14d,2
+ add r8d,eax
+ add eax,r15d
+ mov r13d,r8d
+ add r14d,eax
+ mov rdi,QWORD PTR[((64+0))+rsp]
+ mov eax,r14d
+
+ add eax,DWORD PTR[rdi]
+ lea rsi,QWORD PTR[64+rsi]
+ 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_ssse3
+
+ mov rsi,QWORD PTR[((64+24))+rsp]
+ movaps xmm6,XMMWORD PTR[((64+32))+rsp]
+ movaps xmm7,XMMWORD PTR[((64+48))+rsp]
+ movaps xmm8,XMMWORD PTR[((64+64))+rsp]
+ movaps xmm9,XMMWORD PTR[((64+80))+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_sha256_block_data_order_ssse3::
+sha256_block_data_order_ssse3 ENDP
+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 rsi,rax
+ mov rax,QWORD PTR[((64+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
+
+ lea r10,QWORD PTR[$L$epilogue]
+ cmp rbx,r10
+ jb $L$in_prologue
+
+ lea rsi,QWORD PTR[((64+32))+rsi]
+ lea rdi,QWORD PTR[512+r8]
+ mov ecx,8
+ DD 0a548f3fch
+
+$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_sha256_block_data_order
+ DD imagerel $L$SEH_end_sha256_block_data_order
+ DD imagerel $L$SEH_info_sha256_block_data_order
+ DD imagerel $L$SEH_begin_sha256_block_data_order_ssse3
+ DD imagerel $L$SEH_end_sha256_block_data_order_ssse3
+ DD imagerel $L$SEH_info_sha256_block_data_order_ssse3
+.pdata ENDS
+.xdata SEGMENT READONLY ALIGN(8)
+ALIGN 8
+$L$SEH_info_sha256_block_data_order::
+DB 9,0,0,0
+ DD imagerel se_handler
+ DD imagerel $L$prologue,imagerel $L$epilogue
+$L$SEH_info_sha256_block_data_order_ssse3::
+DB 9,0,0,0
+ DD imagerel se_handler
+ DD imagerel $L$prologue_ssse3,imagerel $L$epilogue_ssse3
+
+.xdata ENDS
+END
diff --git a/win-x86_64/crypto/sha/sha512-x86_64.asm b/win-x86_64/crypto/sha/sha512-x86_64.asm
new file mode 100644
index 0000000..e993c3c
--- /dev/null
+++ b/win-x86_64/crypto/sha/sha512-x86_64.asm
@@ -0,0 +1,1913 @@
+OPTION DOTNAME
+.text$ SEGMENT ALIGN(256) 'CODE'
+
+EXTERN OPENSSL_ia32cap_P:NEAR
+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
+
+
+ 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::
+
+ 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::
+ mov rdi,rbx
+ lea rbp,QWORD PTR[K512]
+ xor rdi,rcx
+ mov r12,QWORD PTR[rsi]
+ mov r13,r8
+ mov r14,rax
+ bswap r12
+ ror r13,23
+ mov r15,r9
+
+ xor r13,r8
+ ror r14,5
+ xor r15,r10
+
+ mov QWORD PTR[rsp],r12
+ xor r14,rax
+ and r15,r8
+
+ ror r13,4
+ add r12,r11
+ xor r15,r10
+
+ ror r14,6
+ xor r13,r8
+ add r12,r15
+
+ mov r15,rax
+ add r12,QWORD PTR[rbp]
+ xor r14,rax
+
+ xor r15,rbx
+ ror r13,14
+ mov r11,rbx
+
+ and rdi,r15
+ ror r14,28
+ add r12,r13
+
+ xor r11,rdi
+ add rdx,r12
+ add r11,r12
+
+ lea rbp,QWORD PTR[8+rbp]
+ add r11,r14
+ mov r12,QWORD PTR[8+rsi]
+ mov r13,rdx
+ mov r14,r11
+ bswap r12
+ ror r13,23
+ mov rdi,r8
+
+ xor r13,rdx
+ ror r14,5
+ xor rdi,r9
+
+ mov QWORD PTR[8+rsp],r12
+ xor r14,r11
+ and rdi,rdx
+
+ ror r13,4
+ add r12,r10
+ xor rdi,r9
+
+ ror r14,6
+ xor r13,rdx
+ add r12,rdi
+
+ mov rdi,r11
+ add r12,QWORD PTR[rbp]
+ xor r14,r11
+
+ xor rdi,rax
+ ror r13,14
+ mov r10,rax
+
+ and r15,rdi
+ ror r14,28
+ add r12,r13
+
+ xor r10,r15
+ add rcx,r12
+ add r10,r12
+
+ lea rbp,QWORD PTR[24+rbp]
+ add r10,r14
+ mov r12,QWORD PTR[16+rsi]
+ mov r13,rcx
+ mov r14,r10
+ bswap r12
+ ror r13,23
+ mov r15,rdx
+
+ xor r13,rcx
+ ror r14,5
+ xor r15,r8
+
+ mov QWORD PTR[16+rsp],r12
+ xor r14,r10
+ and r15,rcx
+
+ ror r13,4
+ add r12,r9
+ xor r15,r8
+
+ ror r14,6
+ xor r13,rcx
+ add r12,r15
+
+ mov r15,r10
+ add r12,QWORD PTR[rbp]
+ xor r14,r10
+
+ xor r15,r11
+ ror r13,14
+ mov r9,r11
+
+ and rdi,r15
+ ror r14,28
+ add r12,r13
+
+ xor r9,rdi
+ add rbx,r12
+ add r9,r12
+
+ lea rbp,QWORD PTR[8+rbp]
+ add r9,r14
+ mov r12,QWORD PTR[24+rsi]
+ mov r13,rbx
+ mov r14,r9
+ bswap r12
+ ror r13,23
+ mov rdi,rcx
+
+ xor r13,rbx
+ ror r14,5
+ xor rdi,rdx
+
+ mov QWORD PTR[24+rsp],r12
+ xor r14,r9
+ and rdi,rbx
+
+ ror r13,4
+ add r12,r8
+ xor rdi,rdx
+
+ ror r14,6
+ xor r13,rbx
+ add r12,rdi
+
+ mov rdi,r9
+ add r12,QWORD PTR[rbp]
+ xor r14,r9
+
+ xor rdi,r10
+ ror r13,14
+ mov r8,r10
+
+ and r15,rdi
+ ror r14,28
+ add r12,r13
+
+ xor r8,r15
+ add rax,r12
+ add r8,r12
+
+ lea rbp,QWORD PTR[24+rbp]
+ add r8,r14
+ mov r12,QWORD PTR[32+rsi]
+ mov r13,rax
+ mov r14,r8
+ bswap r12
+ ror r13,23
+ mov r15,rbx
+
+ xor r13,rax
+ ror r14,5
+ xor r15,rcx
+
+ mov QWORD PTR[32+rsp],r12
+ xor r14,r8
+ and r15,rax
+
+ ror r13,4
+ add r12,rdx
+ xor r15,rcx
+
+ ror r14,6
+ xor r13,rax
+ add r12,r15
+
+ mov r15,r8
+ add r12,QWORD PTR[rbp]
+ xor r14,r8
+
+ xor r15,r9
+ ror r13,14
+ mov rdx,r9
+
+ and rdi,r15
+ ror r14,28
+ add r12,r13
+
+ xor rdx,rdi
+ add r11,r12
+ add rdx,r12
+
+ lea rbp,QWORD PTR[8+rbp]
+ add rdx,r14
+ mov r12,QWORD PTR[40+rsi]
+ mov r13,r11
+ mov r14,rdx
+ bswap r12
+ ror r13,23
+ mov rdi,rax
+
+ xor r13,r11
+ ror r14,5
+ xor rdi,rbx
+
+ mov QWORD PTR[40+rsp],r12
+ xor r14,rdx
+ and rdi,r11
+
+ ror r13,4
+ add r12,rcx
+ xor rdi,rbx
+
+ ror r14,6
+ xor r13,r11
+ add r12,rdi
+
+ mov rdi,rdx
+ add r12,QWORD PTR[rbp]
+ xor r14,rdx
+
+ xor rdi,r8
+ ror r13,14
+ mov rcx,r8
+
+ and r15,rdi
+ ror r14,28
+ add r12,r13
+
+ xor rcx,r15
+ add r10,r12
+ add rcx,r12
+
+ lea rbp,QWORD PTR[24+rbp]
+ add rcx,r14
+ mov r12,QWORD PTR[48+rsi]
+ mov r13,r10
+ mov r14,rcx
+ bswap r12
+ ror r13,23
+ mov r15,r11
+
+ xor r13,r10
+ ror r14,5
+ xor r15,rax
+
+ mov QWORD PTR[48+rsp],r12
+ xor r14,rcx
+ and r15,r10
+
+ ror r13,4
+ add r12,rbx
+ xor r15,rax
+
+ ror r14,6
+ xor r13,r10
+ add r12,r15
+
+ mov r15,rcx
+ add r12,QWORD PTR[rbp]
+ xor r14,rcx
+
+ xor r15,rdx
+ ror r13,14
+ mov rbx,rdx
+
+ and rdi,r15
+ ror r14,28
+ add r12,r13
+
+ xor rbx,rdi
+ add r9,r12
+ add rbx,r12
+
+ lea rbp,QWORD PTR[8+rbp]
+ add rbx,r14
+ mov r12,QWORD PTR[56+rsi]
+ mov r13,r9
+ mov r14,rbx
+ bswap r12
+ ror r13,23
+ mov rdi,r10
+
+ xor r13,r9
+ ror r14,5
+ xor rdi,r11
+
+ mov QWORD PTR[56+rsp],r12
+ xor r14,rbx
+ and rdi,r9
+
+ ror r13,4
+ add r12,rax
+ xor rdi,r11
+
+ ror r14,6
+ xor r13,r9
+ add r12,rdi
+
+ mov rdi,rbx
+ add r12,QWORD PTR[rbp]
+ xor r14,rbx
+
+ xor rdi,rcx
+ ror r13,14
+ mov rax,rcx
+
+ and r15,rdi
+ ror r14,28
+ add r12,r13
+
+ xor rax,r15
+ add r8,r12
+ add rax,r12
+
+ lea rbp,QWORD PTR[24+rbp]
+ add rax,r14
+ mov r12,QWORD PTR[64+rsi]
+ mov r13,r8
+ mov r14,rax
+ bswap r12
+ ror r13,23
+ mov r15,r9
+
+ xor r13,r8
+ ror r14,5
+ xor r15,r10
+
+ mov QWORD PTR[64+rsp],r12
+ xor r14,rax
+ and r15,r8
+
+ ror r13,4
+ add r12,r11
+ xor r15,r10
+
+ ror r14,6
+ xor r13,r8
+ add r12,r15
+
+ mov r15,rax
+ add r12,QWORD PTR[rbp]
+ xor r14,rax
+
+ xor r15,rbx
+ ror r13,14
+ mov r11,rbx
+
+ and rdi,r15
+ ror r14,28
+ add r12,r13
+
+ xor r11,rdi
+ add rdx,r12
+ add r11,r12
+
+ lea rbp,QWORD PTR[8+rbp]
+ add r11,r14
+ mov r12,QWORD PTR[72+rsi]
+ mov r13,rdx
+ mov r14,r11
+ bswap r12
+ ror r13,23
+ mov rdi,r8
+
+ xor r13,rdx
+ ror r14,5
+ xor rdi,r9
+
+ mov QWORD PTR[72+rsp],r12
+ xor r14,r11
+ and rdi,rdx
+
+ ror r13,4
+ add r12,r10
+ xor rdi,r9
+
+ ror r14,6
+ xor r13,rdx
+ add r12,rdi
+
+ mov rdi,r11
+ add r12,QWORD PTR[rbp]
+ xor r14,r11
+
+ xor rdi,rax
+ ror r13,14
+ mov r10,rax
+
+ and r15,rdi
+ ror r14,28
+ add r12,r13
+
+ xor r10,r15
+ add rcx,r12
+ add r10,r12
+
+ lea rbp,QWORD PTR[24+rbp]
+ add r10,r14
+ mov r12,QWORD PTR[80+rsi]
+ mov r13,rcx
+ mov r14,r10
+ bswap r12
+ ror r13,23
+ mov r15,rdx
+
+ xor r13,rcx
+ ror r14,5
+ xor r15,r8
+
+ mov QWORD PTR[80+rsp],r12
+ xor r14,r10
+ and r15,rcx
+
+ ror r13,4
+ add r12,r9
+ xor r15,r8
+
+ ror r14,6
+ xor r13,rcx
+ add r12,r15
+
+ mov r15,r10
+ add r12,QWORD PTR[rbp]
+ xor r14,r10
+
+ xor r15,r11
+ ror r13,14
+ mov r9,r11
+
+ and rdi,r15
+ ror r14,28
+ add r12,r13
+
+ xor r9,rdi
+ add rbx,r12
+ add r9,r12
+
+ lea rbp,QWORD PTR[8+rbp]
+ add r9,r14
+ mov r12,QWORD PTR[88+rsi]
+ mov r13,rbx
+ mov r14,r9
+ bswap r12
+ ror r13,23
+ mov rdi,rcx
+
+ xor r13,rbx
+ ror r14,5
+ xor rdi,rdx
+
+ mov QWORD PTR[88+rsp],r12
+ xor r14,r9
+ and rdi,rbx
+
+ ror r13,4
+ add r12,r8
+ xor rdi,rdx
+
+ ror r14,6
+ xor r13,rbx
+ add r12,rdi
+
+ mov rdi,r9
+ add r12,QWORD PTR[rbp]
+ xor r14,r9
+
+ xor rdi,r10
+ ror r13,14
+ mov r8,r10
+
+ and r15,rdi
+ ror r14,28
+ add r12,r13
+
+ xor r8,r15
+ add rax,r12
+ add r8,r12
+
+ lea rbp,QWORD PTR[24+rbp]
+ add r8,r14
+ mov r12,QWORD PTR[96+rsi]
+ mov r13,rax
+ mov r14,r8
+ bswap r12
+ ror r13,23
+ mov r15,rbx
+
+ xor r13,rax
+ ror r14,5
+ xor r15,rcx
+
+ mov QWORD PTR[96+rsp],r12
+ xor r14,r8
+ and r15,rax
+
+ ror r13,4
+ add r12,rdx
+ xor r15,rcx
+
+ ror r14,6
+ xor r13,rax
+ add r12,r15
+
+ mov r15,r8
+ add r12,QWORD PTR[rbp]
+ xor r14,r8
+
+ xor r15,r9
+ ror r13,14
+ mov rdx,r9
+
+ and rdi,r15
+ ror r14,28
+ add r12,r13
+
+ xor rdx,rdi
+ add r11,r12
+ add rdx,r12
+
+ lea rbp,QWORD PTR[8+rbp]
+ add rdx,r14
+ mov r12,QWORD PTR[104+rsi]
+ mov r13,r11
+ mov r14,rdx
+ bswap r12
+ ror r13,23
+ mov rdi,rax
+
+ xor r13,r11
+ ror r14,5
+ xor rdi,rbx
+
+ mov QWORD PTR[104+rsp],r12
+ xor r14,rdx
+ and rdi,r11
+
+ ror r13,4
+ add r12,rcx
+ xor rdi,rbx
+
+ ror r14,6
+ xor r13,r11
+ add r12,rdi
+
+ mov rdi,rdx
+ add r12,QWORD PTR[rbp]
+ xor r14,rdx
+
+ xor rdi,r8
+ ror r13,14
+ mov rcx,r8
+
+ and r15,rdi
+ ror r14,28
+ add r12,r13
+
+ xor rcx,r15
+ add r10,r12
+ add rcx,r12
+
+ lea rbp,QWORD PTR[24+rbp]
+ add rcx,r14
+ mov r12,QWORD PTR[112+rsi]
+ mov r13,r10
+ mov r14,rcx
+ bswap r12
+ ror r13,23
+ mov r15,r11
+
+ xor r13,r10
+ ror r14,5
+ xor r15,rax
+
+ mov QWORD PTR[112+rsp],r12
+ xor r14,rcx
+ and r15,r10
+
+ ror r13,4
+ add r12,rbx
+ xor r15,rax
+
+ ror r14,6
+ xor r13,r10
+ add r12,r15
+
+ mov r15,rcx
+ add r12,QWORD PTR[rbp]
+ xor r14,rcx
+
+ xor r15,rdx
+ ror r13,14
+ mov rbx,rdx
+
+ and rdi,r15
+ ror r14,28
+ add r12,r13
+
+ xor rbx,rdi
+ add r9,r12
+ add rbx,r12
+
+ lea rbp,QWORD PTR[8+rbp]
+ add rbx,r14
+ mov r12,QWORD PTR[120+rsi]
+ mov r13,r9
+ mov r14,rbx
+ bswap r12
+ ror r13,23
+ mov rdi,r10
+
+ xor r13,r9
+ ror r14,5
+ xor rdi,r11
+
+ mov QWORD PTR[120+rsp],r12
+ xor r14,rbx
+ and rdi,r9
+
+ ror r13,4
+ add r12,rax
+ xor rdi,r11
+
+ ror r14,6
+ xor r13,r9
+ add r12,rdi
+
+ mov rdi,rbx
+ add r12,QWORD PTR[rbp]
+ xor r14,rbx
+
+ xor rdi,rcx
+ ror r13,14
+ mov rax,rcx
+
+ and r15,rdi
+ ror r14,28
+ add r12,r13
+
+ xor rax,r15
+ add r8,r12
+ add rax,r12
+
+ lea rbp,QWORD PTR[24+rbp]
+ jmp $L$rounds_16_xx
+ALIGN 16
+$L$rounds_16_xx::
+ mov r13,QWORD PTR[8+rsp]
+ mov r15,QWORD PTR[112+rsp]
+
+ mov r12,r13
+ ror r13,7
+ add rax,r14
+ mov r14,r15
+ ror r15,42
+
+ xor r13,r12
+ shr r12,7
+ ror r13,1
+ xor r15,r14
+ shr r14,6
+
+ ror r15,19
+ xor r12,r13
+ xor r15,r14
+ add r12,QWORD PTR[72+rsp]
+
+ add r12,QWORD PTR[rsp]
+ mov r13,r8
+ add r12,r15
+ mov r14,rax
+ ror r13,23
+ mov r15,r9
+
+ xor r13,r8
+ ror r14,5
+ xor r15,r10
+
+ mov QWORD PTR[rsp],r12
+ xor r14,rax
+ and r15,r8
+
+ ror r13,4
+ add r12,r11
+ xor r15,r10
+
+ ror r14,6
+ xor r13,r8
+ add r12,r15
+
+ mov r15,rax
+ add r12,QWORD PTR[rbp]
+ xor r14,rax
+
+ xor r15,rbx
+ ror r13,14
+ mov r11,rbx
+
+ and rdi,r15
+ ror r14,28
+ add r12,r13
+
+ xor r11,rdi
+ add rdx,r12
+ add r11,r12
+
+ lea rbp,QWORD PTR[8+rbp]
+ mov r13,QWORD PTR[16+rsp]
+ mov rdi,QWORD PTR[120+rsp]
+
+ mov r12,r13
+ ror r13,7
+ add r11,r14
+ mov r14,rdi
+ ror rdi,42
+
+ xor r13,r12
+ shr r12,7
+ ror r13,1
+ xor rdi,r14
+ shr r14,6
+
+ ror rdi,19
+ xor r12,r13
+ xor rdi,r14
+ add r12,QWORD PTR[80+rsp]
+
+ add r12,QWORD PTR[8+rsp]
+ mov r13,rdx
+ add r12,rdi
+ mov r14,r11
+ ror r13,23
+ mov rdi,r8
+
+ xor r13,rdx
+ ror r14,5
+ xor rdi,r9
+
+ mov QWORD PTR[8+rsp],r12
+ xor r14,r11
+ and rdi,rdx
+
+ ror r13,4
+ add r12,r10
+ xor rdi,r9
+
+ ror r14,6
+ xor r13,rdx
+ add r12,rdi
+
+ mov rdi,r11
+ add r12,QWORD PTR[rbp]
+ xor r14,r11
+
+ xor rdi,rax
+ ror r13,14
+ mov r10,rax
+
+ and r15,rdi
+ ror r14,28
+ add r12,r13
+
+ xor r10,r15
+ add rcx,r12
+ add r10,r12
+
+ lea rbp,QWORD PTR[24+rbp]
+ mov r13,QWORD PTR[24+rsp]
+ mov r15,QWORD PTR[rsp]
+
+ mov r12,r13
+ ror r13,7
+ add r10,r14
+ mov r14,r15
+ ror r15,42
+
+ xor r13,r12
+ shr r12,7
+ ror r13,1
+ xor r15,r14
+ shr r14,6
+
+ ror r15,19
+ xor r12,r13
+ xor r15,r14
+ add r12,QWORD PTR[88+rsp]
+
+ add r12,QWORD PTR[16+rsp]
+ mov r13,rcx
+ add r12,r15
+ mov r14,r10
+ ror r13,23
+ mov r15,rdx
+
+ xor r13,rcx
+ ror r14,5
+ xor r15,r8
+
+ mov QWORD PTR[16+rsp],r12
+ xor r14,r10
+ and r15,rcx
+
+ ror r13,4
+ add r12,r9
+ xor r15,r8
+
+ ror r14,6
+ xor r13,rcx
+ add r12,r15
+
+ mov r15,r10
+ add r12,QWORD PTR[rbp]
+ xor r14,r10
+
+ xor r15,r11
+ ror r13,14
+ mov r9,r11
+
+ and rdi,r15
+ ror r14,28
+ add r12,r13
+
+ xor r9,rdi
+ add rbx,r12
+ add r9,r12
+
+ lea rbp,QWORD PTR[8+rbp]
+ mov r13,QWORD PTR[32+rsp]
+ mov rdi,QWORD PTR[8+rsp]
+
+ mov r12,r13
+ ror r13,7
+ add r9,r14
+ mov r14,rdi
+ ror rdi,42
+
+ xor r13,r12
+ shr r12,7
+ ror r13,1
+ xor rdi,r14
+ shr r14,6
+
+ ror rdi,19
+ xor r12,r13
+ xor rdi,r14
+ add r12,QWORD PTR[96+rsp]
+
+ add r12,QWORD PTR[24+rsp]
+ mov r13,rbx
+ add r12,rdi
+ mov r14,r9
+ ror r13,23
+ mov rdi,rcx
+
+ xor r13,rbx
+ ror r14,5
+ xor rdi,rdx
+
+ mov QWORD PTR[24+rsp],r12
+ xor r14,r9
+ and rdi,rbx
+
+ ror r13,4
+ add r12,r8
+ xor rdi,rdx
+
+ ror r14,6
+ xor r13,rbx
+ add r12,rdi
+
+ mov rdi,r9
+ add r12,QWORD PTR[rbp]
+ xor r14,r9
+
+ xor rdi,r10
+ ror r13,14
+ mov r8,r10
+
+ and r15,rdi
+ ror r14,28
+ add r12,r13
+
+ xor r8,r15
+ add rax,r12
+ add r8,r12
+
+ lea rbp,QWORD PTR[24+rbp]
+ mov r13,QWORD PTR[40+rsp]
+ mov r15,QWORD PTR[16+rsp]
+
+ mov r12,r13
+ ror r13,7
+ add r8,r14
+ mov r14,r15
+ ror r15,42
+
+ xor r13,r12
+ shr r12,7
+ ror r13,1
+ xor r15,r14
+ shr r14,6
+
+ ror r15,19
+ xor r12,r13
+ xor r15,r14
+ add r12,QWORD PTR[104+rsp]
+
+ add r12,QWORD PTR[32+rsp]
+ mov r13,rax
+ add r12,r15
+ mov r14,r8
+ ror r13,23
+ mov r15,rbx
+
+ xor r13,rax
+ ror r14,5
+ xor r15,rcx
+
+ mov QWORD PTR[32+rsp],r12
+ xor r14,r8
+ and r15,rax
+
+ ror r13,4
+ add r12,rdx
+ xor r15,rcx
+
+ ror r14,6
+ xor r13,rax
+ add r12,r15
+
+ mov r15,r8
+ add r12,QWORD PTR[rbp]
+ xor r14,r8
+
+ xor r15,r9
+ ror r13,14
+ mov rdx,r9
+
+ and rdi,r15
+ ror r14,28
+ add r12,r13
+
+ xor rdx,rdi
+ add r11,r12
+ add rdx,r12
+
+ lea rbp,QWORD PTR[8+rbp]
+ mov r13,QWORD PTR[48+rsp]
+ mov rdi,QWORD PTR[24+rsp]
+
+ mov r12,r13
+ ror r13,7
+ add rdx,r14
+ mov r14,rdi
+ ror rdi,42
+
+ xor r13,r12
+ shr r12,7
+ ror r13,1
+ xor rdi,r14
+ shr r14,6
+
+ ror rdi,19
+ xor r12,r13
+ xor rdi,r14
+ add r12,QWORD PTR[112+rsp]
+
+ add r12,QWORD PTR[40+rsp]
+ mov r13,r11
+ add r12,rdi
+ mov r14,rdx
+ ror r13,23
+ mov rdi,rax
+
+ xor r13,r11
+ ror r14,5
+ xor rdi,rbx
+
+ mov QWORD PTR[40+rsp],r12
+ xor r14,rdx
+ and rdi,r11
+
+ ror r13,4
+ add r12,rcx
+ xor rdi,rbx
+
+ ror r14,6
+ xor r13,r11
+ add r12,rdi
+
+ mov rdi,rdx
+ add r12,QWORD PTR[rbp]
+ xor r14,rdx
+
+ xor rdi,r8
+ ror r13,14
+ mov rcx,r8
+
+ and r15,rdi
+ ror r14,28
+ add r12,r13
+
+ xor rcx,r15
+ add r10,r12
+ add rcx,r12
+
+ lea rbp,QWORD PTR[24+rbp]
+ mov r13,QWORD PTR[56+rsp]
+ mov r15,QWORD PTR[32+rsp]
+
+ mov r12,r13
+ ror r13,7
+ add rcx,r14
+ mov r14,r15
+ ror r15,42
+
+ xor r13,r12
+ shr r12,7
+ ror r13,1
+ xor r15,r14
+ shr r14,6
+
+ ror r15,19
+ xor r12,r13
+ xor r15,r14
+ add r12,QWORD PTR[120+rsp]
+
+ add r12,QWORD PTR[48+rsp]
+ mov r13,r10
+ add r12,r15
+ mov r14,rcx
+ ror r13,23
+ mov r15,r11
+
+ xor r13,r10
+ ror r14,5
+ xor r15,rax
+
+ mov QWORD PTR[48+rsp],r12
+ xor r14,rcx
+ and r15,r10
+
+ ror r13,4
+ add r12,rbx
+ xor r15,rax
+
+ ror r14,6
+ xor r13,r10
+ add r12,r15
+
+ mov r15,rcx
+ add r12,QWORD PTR[rbp]
+ xor r14,rcx
+
+ xor r15,rdx
+ ror r13,14
+ mov rbx,rdx
+
+ and rdi,r15
+ ror r14,28
+ add r12,r13
+
+ xor rbx,rdi
+ add r9,r12
+ add rbx,r12
+
+ lea rbp,QWORD PTR[8+rbp]
+ mov r13,QWORD PTR[64+rsp]
+ mov rdi,QWORD PTR[40+rsp]
+
+ mov r12,r13
+ ror r13,7
+ add rbx,r14
+ mov r14,rdi
+ ror rdi,42
+
+ xor r13,r12
+ shr r12,7
+ ror r13,1
+ xor rdi,r14
+ shr r14,6
+
+ ror rdi,19
+ xor r12,r13
+ xor rdi,r14
+ add r12,QWORD PTR[rsp]
+
+ add r12,QWORD PTR[56+rsp]
+ mov r13,r9
+ add r12,rdi
+ mov r14,rbx
+ ror r13,23
+ mov rdi,r10
+
+ xor r13,r9
+ ror r14,5
+ xor rdi,r11
+
+ mov QWORD PTR[56+rsp],r12
+ xor r14,rbx
+ and rdi,r9
+
+ ror r13,4
+ add r12,rax
+ xor rdi,r11
+
+ ror r14,6
+ xor r13,r9
+ add r12,rdi
+
+ mov rdi,rbx
+ add r12,QWORD PTR[rbp]
+ xor r14,rbx
+
+ xor rdi,rcx
+ ror r13,14
+ mov rax,rcx
+
+ and r15,rdi
+ ror r14,28
+ add r12,r13
+
+ xor rax,r15
+ add r8,r12
+ add rax,r12
+
+ lea rbp,QWORD PTR[24+rbp]
+ mov r13,QWORD PTR[72+rsp]
+ mov r15,QWORD PTR[48+rsp]
+
+ mov r12,r13
+ ror r13,7
+ add rax,r14
+ mov r14,r15
+ ror r15,42
+
+ xor r13,r12
+ shr r12,7
+ ror r13,1
+ xor r15,r14
+ shr r14,6
+
+ ror r15,19
+ xor r12,r13
+ xor r15,r14
+ add r12,QWORD PTR[8+rsp]
+
+ add r12,QWORD PTR[64+rsp]
+ mov r13,r8
+ add r12,r15
+ mov r14,rax
+ ror r13,23
+ mov r15,r9
+
+ xor r13,r8
+ ror r14,5
+ xor r15,r10
+
+ mov QWORD PTR[64+rsp],r12
+ xor r14,rax
+ and r15,r8
+
+ ror r13,4
+ add r12,r11
+ xor r15,r10
+
+ ror r14,6
+ xor r13,r8
+ add r12,r15
+
+ mov r15,rax
+ add r12,QWORD PTR[rbp]
+ xor r14,rax
+
+ xor r15,rbx
+ ror r13,14
+ mov r11,rbx
+
+ and rdi,r15
+ ror r14,28
+ add r12,r13
+
+ xor r11,rdi
+ add rdx,r12
+ add r11,r12
+
+ lea rbp,QWORD PTR[8+rbp]
+ mov r13,QWORD PTR[80+rsp]
+ mov rdi,QWORD PTR[56+rsp]
+
+ mov r12,r13
+ ror r13,7
+ add r11,r14
+ mov r14,rdi
+ ror rdi,42
+
+ xor r13,r12
+ shr r12,7
+ ror r13,1
+ xor rdi,r14
+ shr r14,6
+
+ ror rdi,19
+ xor r12,r13
+ xor rdi,r14
+ add r12,QWORD PTR[16+rsp]
+
+ add r12,QWORD PTR[72+rsp]
+ mov r13,rdx
+ add r12,rdi
+ mov r14,r11
+ ror r13,23
+ mov rdi,r8
+
+ xor r13,rdx
+ ror r14,5
+ xor rdi,r9
+
+ mov QWORD PTR[72+rsp],r12
+ xor r14,r11
+ and rdi,rdx
+
+ ror r13,4
+ add r12,r10
+ xor rdi,r9
+
+ ror r14,6
+ xor r13,rdx
+ add r12,rdi
+
+ mov rdi,r11
+ add r12,QWORD PTR[rbp]
+ xor r14,r11
+
+ xor rdi,rax
+ ror r13,14
+ mov r10,rax
+
+ and r15,rdi
+ ror r14,28
+ add r12,r13
+
+ xor r10,r15
+ add rcx,r12
+ add r10,r12
+
+ lea rbp,QWORD PTR[24+rbp]
+ mov r13,QWORD PTR[88+rsp]
+ mov r15,QWORD PTR[64+rsp]
+
+ mov r12,r13
+ ror r13,7
+ add r10,r14
+ mov r14,r15
+ ror r15,42
+
+ xor r13,r12
+ shr r12,7
+ ror r13,1
+ xor r15,r14
+ shr r14,6
+
+ ror r15,19
+ xor r12,r13
+ xor r15,r14
+ add r12,QWORD PTR[24+rsp]
+
+ add r12,QWORD PTR[80+rsp]
+ mov r13,rcx
+ add r12,r15
+ mov r14,r10
+ ror r13,23
+ mov r15,rdx
+
+ xor r13,rcx
+ ror r14,5
+ xor r15,r8
+
+ mov QWORD PTR[80+rsp],r12
+ xor r14,r10
+ and r15,rcx
+
+ ror r13,4
+ add r12,r9
+ xor r15,r8
+
+ ror r14,6
+ xor r13,rcx
+ add r12,r15
+
+ mov r15,r10
+ add r12,QWORD PTR[rbp]
+ xor r14,r10
+
+ xor r15,r11
+ ror r13,14
+ mov r9,r11
+
+ and rdi,r15
+ ror r14,28
+ add r12,r13
+
+ xor r9,rdi
+ add rbx,r12
+ add r9,r12
+
+ lea rbp,QWORD PTR[8+rbp]
+ mov r13,QWORD PTR[96+rsp]
+ mov rdi,QWORD PTR[72+rsp]
+
+ mov r12,r13
+ ror r13,7
+ add r9,r14
+ mov r14,rdi
+ ror rdi,42
+
+ xor r13,r12
+ shr r12,7
+ ror r13,1
+ xor rdi,r14
+ shr r14,6
+
+ ror rdi,19
+ xor r12,r13
+ xor rdi,r14
+ add r12,QWORD PTR[32+rsp]
+
+ add r12,QWORD PTR[88+rsp]
+ mov r13,rbx
+ add r12,rdi
+ mov r14,r9
+ ror r13,23
+ mov rdi,rcx
+
+ xor r13,rbx
+ ror r14,5
+ xor rdi,rdx
+
+ mov QWORD PTR[88+rsp],r12
+ xor r14,r9
+ and rdi,rbx
+
+ ror r13,4
+ add r12,r8
+ xor rdi,rdx
+
+ ror r14,6
+ xor r13,rbx
+ add r12,rdi
+
+ mov rdi,r9
+ add r12,QWORD PTR[rbp]
+ xor r14,r9
+
+ xor rdi,r10
+ ror r13,14
+ mov r8,r10
+
+ and r15,rdi
+ ror r14,28
+ add r12,r13
+
+ xor r8,r15
+ add rax,r12
+ add r8,r12
+
+ lea rbp,QWORD PTR[24+rbp]
+ mov r13,QWORD PTR[104+rsp]
+ mov r15,QWORD PTR[80+rsp]
+
+ mov r12,r13
+ ror r13,7
+ add r8,r14
+ mov r14,r15
+ ror r15,42
+
+ xor r13,r12
+ shr r12,7
+ ror r13,1
+ xor r15,r14
+ shr r14,6
+
+ ror r15,19
+ xor r12,r13
+ xor r15,r14
+ add r12,QWORD PTR[40+rsp]
+
+ add r12,QWORD PTR[96+rsp]
+ mov r13,rax
+ add r12,r15
+ mov r14,r8
+ ror r13,23
+ mov r15,rbx
+
+ xor r13,rax
+ ror r14,5
+ xor r15,rcx
+
+ mov QWORD PTR[96+rsp],r12
+ xor r14,r8
+ and r15,rax
+
+ ror r13,4
+ add r12,rdx
+ xor r15,rcx
+
+ ror r14,6
+ xor r13,rax
+ add r12,r15
+
+ mov r15,r8
+ add r12,QWORD PTR[rbp]
+ xor r14,r8
+
+ xor r15,r9
+ ror r13,14
+ mov rdx,r9
+
+ and rdi,r15
+ ror r14,28
+ add r12,r13
+
+ xor rdx,rdi
+ add r11,r12
+ add rdx,r12
+
+ lea rbp,QWORD PTR[8+rbp]
+ mov r13,QWORD PTR[112+rsp]
+ mov rdi,QWORD PTR[88+rsp]
+
+ mov r12,r13
+ ror r13,7
+ add rdx,r14
+ mov r14,rdi
+ ror rdi,42
+
+ xor r13,r12
+ shr r12,7
+ ror r13,1
+ xor rdi,r14
+ shr r14,6
+
+ ror rdi,19
+ xor r12,r13
+ xor rdi,r14
+ add r12,QWORD PTR[48+rsp]
+
+ add r12,QWORD PTR[104+rsp]
+ mov r13,r11
+ add r12,rdi
+ mov r14,rdx
+ ror r13,23
+ mov rdi,rax
+
+ xor r13,r11
+ ror r14,5
+ xor rdi,rbx
+
+ mov QWORD PTR[104+rsp],r12
+ xor r14,rdx
+ and rdi,r11
+
+ ror r13,4
+ add r12,rcx
+ xor rdi,rbx
+
+ ror r14,6
+ xor r13,r11
+ add r12,rdi
+
+ mov rdi,rdx
+ add r12,QWORD PTR[rbp]
+ xor r14,rdx
+
+ xor rdi,r8
+ ror r13,14
+ mov rcx,r8
+
+ and r15,rdi
+ ror r14,28
+ add r12,r13
+
+ xor rcx,r15
+ add r10,r12
+ add rcx,r12
+
+ lea rbp,QWORD PTR[24+rbp]
+ mov r13,QWORD PTR[120+rsp]
+ mov r15,QWORD PTR[96+rsp]
+
+ mov r12,r13
+ ror r13,7
+ add rcx,r14
+ mov r14,r15
+ ror r15,42
+
+ xor r13,r12
+ shr r12,7
+ ror r13,1
+ xor r15,r14
+ shr r14,6
+
+ ror r15,19
+ xor r12,r13
+ xor r15,r14
+ add r12,QWORD PTR[56+rsp]
+
+ add r12,QWORD PTR[112+rsp]
+ mov r13,r10
+ add r12,r15
+ mov r14,rcx
+ ror r13,23
+ mov r15,r11
+
+ xor r13,r10
+ ror r14,5
+ xor r15,rax
+
+ mov QWORD PTR[112+rsp],r12
+ xor r14,rcx
+ and r15,r10
+
+ ror r13,4
+ add r12,rbx
+ xor r15,rax
+
+ ror r14,6
+ xor r13,r10
+ add r12,r15
+
+ mov r15,rcx
+ add r12,QWORD PTR[rbp]
+ xor r14,rcx
+
+ xor r15,rdx
+ ror r13,14
+ mov rbx,rdx
+
+ and rdi,r15
+ ror r14,28
+ add r12,r13
+
+ xor rbx,rdi
+ add r9,r12
+ add rbx,r12
+
+ lea rbp,QWORD PTR[8+rbp]
+ mov r13,QWORD PTR[rsp]
+ mov rdi,QWORD PTR[104+rsp]
+
+ mov r12,r13
+ ror r13,7
+ add rbx,r14
+ mov r14,rdi
+ ror rdi,42
+
+ xor r13,r12
+ shr r12,7
+ ror r13,1
+ xor rdi,r14
+ shr r14,6
+
+ ror rdi,19
+ xor r12,r13
+ xor rdi,r14
+ add r12,QWORD PTR[64+rsp]
+
+ add r12,QWORD PTR[120+rsp]
+ mov r13,r9
+ add r12,rdi
+ mov r14,rbx
+ ror r13,23
+ mov rdi,r10
+
+ xor r13,r9
+ ror r14,5
+ xor rdi,r11
+
+ mov QWORD PTR[120+rsp],r12
+ xor r14,rbx
+ and rdi,r9
+
+ ror r13,4
+ add r12,rax
+ xor rdi,r11
+
+ ror r14,6
+ xor r13,r9
+ add r12,rdi
+
+ mov rdi,rbx
+ add r12,QWORD PTR[rbp]
+ xor r14,rbx
+
+ xor rdi,rcx
+ ror r13,14
+ mov rax,rcx
+
+ and r15,rdi
+ ror r14,28
+ add r12,r13
+
+ xor rax,r15
+ add r8,r12
+ add rax,r12
+
+ lea rbp,QWORD PTR[24+rbp]
+ cmp BYTE PTR[7+rbp],0
+ jnz $L$rounds_16_xx
+
+ mov rdi,QWORD PTR[((128+0))+rsp]
+ add rax,r14
+ 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 0428a2f98d728ae22h,07137449123ef65cdh
+ DQ 0b5c0fbcfec4d3b2fh,0e9b5dba58189dbbch
+ DQ 0b5c0fbcfec4d3b2fh,0e9b5dba58189dbbch
+ DQ 03956c25bf348b538h,059f111f1b605d019h
+ DQ 03956c25bf348b538h,059f111f1b605d019h
+ DQ 0923f82a4af194f9bh,0ab1c5ed5da6d8118h
+ DQ 0923f82a4af194f9bh,0ab1c5ed5da6d8118h
+ DQ 0d807aa98a3030242h,012835b0145706fbeh
+ DQ 0d807aa98a3030242h,012835b0145706fbeh
+ DQ 0243185be4ee4b28ch,0550c7dc3d5ffb4e2h
+ DQ 0243185be4ee4b28ch,0550c7dc3d5ffb4e2h
+ DQ 072be5d74f27b896fh,080deb1fe3b1696b1h
+ DQ 072be5d74f27b896fh,080deb1fe3b1696b1h
+ DQ 09bdc06a725c71235h,0c19bf174cf692694h
+ DQ 09bdc06a725c71235h,0c19bf174cf692694h
+ DQ 0e49b69c19ef14ad2h,0efbe4786384f25e3h
+ DQ 0e49b69c19ef14ad2h,0efbe4786384f25e3h
+ DQ 00fc19dc68b8cd5b5h,0240ca1cc77ac9c65h
+ DQ 00fc19dc68b8cd5b5h,0240ca1cc77ac9c65h
+ DQ 02de92c6f592b0275h,04a7484aa6ea6e483h
+ DQ 02de92c6f592b0275h,04a7484aa6ea6e483h
+ DQ 05cb0a9dcbd41fbd4h,076f988da831153b5h
+ DQ 05cb0a9dcbd41fbd4h,076f988da831153b5h
+ DQ 0983e5152ee66dfabh,0a831c66d2db43210h
+ DQ 0983e5152ee66dfabh,0a831c66d2db43210h
+ DQ 0b00327c898fb213fh,0bf597fc7beef0ee4h
+ DQ 0b00327c898fb213fh,0bf597fc7beef0ee4h
+ DQ 0c6e00bf33da88fc2h,0d5a79147930aa725h
+ DQ 0c6e00bf33da88fc2h,0d5a79147930aa725h
+ DQ 006ca6351e003826fh,0142929670a0e6e70h
+ DQ 006ca6351e003826fh,0142929670a0e6e70h
+ DQ 027b70a8546d22ffch,02e1b21385c26c926h
+ DQ 027b70a8546d22ffch,02e1b21385c26c926h
+ DQ 04d2c6dfc5ac42aedh,053380d139d95b3dfh
+ DQ 04d2c6dfc5ac42aedh,053380d139d95b3dfh
+ DQ 0650a73548baf63deh,0766a0abb3c77b2a8h
+ DQ 0650a73548baf63deh,0766a0abb3c77b2a8h
+ DQ 081c2c92e47edaee6h,092722c851482353bh
+ DQ 081c2c92e47edaee6h,092722c851482353bh
+ DQ 0a2bfe8a14cf10364h,0a81a664bbc423001h
+ DQ 0a2bfe8a14cf10364h,0a81a664bbc423001h
+ DQ 0c24b8b70d0f89791h,0c76c51a30654be30h
+ DQ 0c24b8b70d0f89791h,0c76c51a30654be30h
+ DQ 0d192e819d6ef5218h,0d69906245565a910h
+ DQ 0d192e819d6ef5218h,0d69906245565a910h
+ DQ 0f40e35855771202ah,0106aa07032bbd1b8h
+ DQ 0f40e35855771202ah,0106aa07032bbd1b8h
+ DQ 019a4c116b8d2d0c8h,01e376c085141ab53h
+ DQ 019a4c116b8d2d0c8h,01e376c085141ab53h
+ DQ 02748774cdf8eeb99h,034b0bcb5e19b48a8h
+ DQ 02748774cdf8eeb99h,034b0bcb5e19b48a8h
+ DQ 0391c0cb3c5c95a63h,04ed8aa4ae3418acbh
+ DQ 0391c0cb3c5c95a63h,04ed8aa4ae3418acbh
+ DQ 05b9cca4f7763e373h,0682e6ff3d6b2b8a3h
+ DQ 05b9cca4f7763e373h,0682e6ff3d6b2b8a3h
+ DQ 0748f82ee5defb2fch,078a5636f43172f60h
+ DQ 0748f82ee5defb2fch,078a5636f43172f60h
+ DQ 084c87814a1f0ab72h,08cc702081a6439ech
+ DQ 084c87814a1f0ab72h,08cc702081a6439ech
+ DQ 090befffa23631e28h,0a4506cebde82bde9h
+ DQ 090befffa23631e28h,0a4506cebde82bde9h
+ DQ 0bef9a3f7b2c67915h,0c67178f2e372532bh
+ DQ 0bef9a3f7b2c67915h,0c67178f2e372532bh
+ DQ 0ca273eceea26619ch,0d186b8c721c0c207h
+ DQ 0ca273eceea26619ch,0d186b8c721c0c207h
+ DQ 0eada7dd6cde0eb1eh,0f57d4f7fee6ed178h
+ DQ 0eada7dd6cde0eb1eh,0f57d4f7fee6ed178h
+ DQ 006f067aa72176fbah,00a637dc5a2c898a6h
+ DQ 006f067aa72176fbah,00a637dc5a2c898a6h
+ DQ 0113f9804bef90daeh,01b710b35131c471bh
+ DQ 0113f9804bef90daeh,01b710b35131c471bh
+ DQ 028db77f523047d84h,032caab7b40c72493h
+ DQ 028db77f523047d84h,032caab7b40c72493h
+ DQ 03c9ebe0a15c9bebch,0431d67c49c100d4ch
+ DQ 03c9ebe0a15c9bebch,0431d67c49c100d4ch
+ DQ 04cc5d4becb3e42b6h,0597f299cfc657e2ah
+ DQ 04cc5d4becb3e42b6h,0597f299cfc657e2ah
+ DQ 05fcb6fab3ad6faech,06c44198c4a475817h
+ DQ 05fcb6fab3ad6faech,06c44198c4a475817h
+
+ DQ 00001020304050607h,008090a0b0c0d0e0fh
+ DQ 00001020304050607h,008090a0b0c0d0e0fh
+DB 83,72,65,53,49,50,32,98,108,111,99,107,32,116,114,97
+DB 110,115,102,111,114,109,32,102,111,114,32,120,56,54,95,54
+DB 52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121
+DB 32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46
+DB 111,114,103,62,0
+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 rsi,rax
+ mov rax,QWORD PTR[((128+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
+
+ lea r10,QWORD PTR[$L$epilogue]
+ cmp rbx,r10
+ jb $L$in_prologue
+
+ lea rsi,QWORD PTR[((128+32))+rsi]
+ lea rdi,QWORD PTR[512+r8]
+ mov ecx,12
+ DD 0a548f3fch
+
+$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_sha512_block_data_order
+ DD imagerel $L$SEH_end_sha512_block_data_order
+ DD imagerel $L$SEH_info_sha512_block_data_order
+.pdata ENDS
+.xdata SEGMENT READONLY ALIGN(8)
+ALIGN 8
+$L$SEH_info_sha512_block_data_order::
+DB 9,0,0,0
+ DD imagerel se_handler
+ DD imagerel $L$prologue,imagerel $L$epilogue
+
+.xdata ENDS
+END